1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2008, Christoph Hellwig 4 * All Rights Reserved. 5 */ 6 #include "xfs.h" 7 #include "xfs_shared.h" 8 #include "xfs_format.h" 9 #include "xfs_log_format.h" 10 #include "xfs_trans_resv.h" 11 #include "xfs_mount.h" 12 #include "xfs_inode.h" 13 #include "xfs_quota.h" 14 #include "xfs_trans.h" 15 #include "xfs_icache.h" 16 #include "xfs_qm.h" 17 18 19 static void 20 xfs_qm_fill_state( 21 struct qc_type_state *tstate, 22 struct xfs_mount *mp, 23 struct xfs_inode *ip, 24 xfs_ino_t ino, 25 struct xfs_def_quota *defq) 26 { 27 bool tempqip = false; 28 29 tstate->ino = ino; 30 if (!ip && ino == NULLFSINO) 31 return; 32 if (!ip) { 33 if (xfs_iget(mp, NULL, ino, 0, 0, &ip)) 34 return; 35 tempqip = true; 36 } 37 tstate->flags |= QCI_SYSFILE; 38 tstate->blocks = ip->i_d.di_nblocks; 39 tstate->nextents = ip->i_df.if_nextents; 40 tstate->spc_timelimit = (u32)defq->btimelimit; 41 tstate->ino_timelimit = (u32)defq->itimelimit; 42 tstate->rt_spc_timelimit = (u32)defq->rtbtimelimit; 43 tstate->spc_warnlimit = defq->bwarnlimit; 44 tstate->ino_warnlimit = defq->iwarnlimit; 45 tstate->rt_spc_warnlimit = defq->rtbwarnlimit; 46 if (tempqip) 47 xfs_irele(ip); 48 } 49 50 /* 51 * Return quota status information, such as enforcements, quota file inode 52 * numbers etc. 53 */ 54 static int 55 xfs_fs_get_quota_state( 56 struct super_block *sb, 57 struct qc_state *state) 58 { 59 struct xfs_mount *mp = XFS_M(sb); 60 struct xfs_quotainfo *q = mp->m_quotainfo; 61 62 memset(state, 0, sizeof(*state)); 63 if (!XFS_IS_QUOTA_RUNNING(mp)) 64 return 0; 65 state->s_incoredqs = q->qi_dquots; 66 if (XFS_IS_UQUOTA_RUNNING(mp)) 67 state->s_state[USRQUOTA].flags |= QCI_ACCT_ENABLED; 68 if (XFS_IS_UQUOTA_ENFORCED(mp)) 69 state->s_state[USRQUOTA].flags |= QCI_LIMITS_ENFORCED; 70 if (XFS_IS_GQUOTA_RUNNING(mp)) 71 state->s_state[GRPQUOTA].flags |= QCI_ACCT_ENABLED; 72 if (XFS_IS_GQUOTA_ENFORCED(mp)) 73 state->s_state[GRPQUOTA].flags |= QCI_LIMITS_ENFORCED; 74 if (XFS_IS_PQUOTA_RUNNING(mp)) 75 state->s_state[PRJQUOTA].flags |= QCI_ACCT_ENABLED; 76 if (XFS_IS_PQUOTA_ENFORCED(mp)) 77 state->s_state[PRJQUOTA].flags |= QCI_LIMITS_ENFORCED; 78 79 xfs_qm_fill_state(&state->s_state[USRQUOTA], mp, q->qi_uquotaip, 80 mp->m_sb.sb_uquotino, &q->qi_usr_default); 81 xfs_qm_fill_state(&state->s_state[GRPQUOTA], mp, q->qi_gquotaip, 82 mp->m_sb.sb_gquotino, &q->qi_grp_default); 83 xfs_qm_fill_state(&state->s_state[PRJQUOTA], mp, q->qi_pquotaip, 84 mp->m_sb.sb_pquotino, &q->qi_prj_default); 85 return 0; 86 } 87 88 STATIC int 89 xfs_quota_type(int type) 90 { 91 switch (type) { 92 case USRQUOTA: 93 return XFS_DQ_USER; 94 case GRPQUOTA: 95 return XFS_DQ_GROUP; 96 default: 97 return XFS_DQ_PROJ; 98 } 99 } 100 101 #define XFS_QC_SETINFO_MASK (QC_TIMER_MASK | QC_WARNS_MASK) 102 103 /* 104 * Adjust quota timers & warnings 105 */ 106 static int 107 xfs_fs_set_info( 108 struct super_block *sb, 109 int type, 110 struct qc_info *info) 111 { 112 struct xfs_mount *mp = XFS_M(sb); 113 struct qc_dqblk newlim; 114 115 if (sb_rdonly(sb)) 116 return -EROFS; 117 if (!XFS_IS_QUOTA_RUNNING(mp)) 118 return -ENOSYS; 119 if (!XFS_IS_QUOTA_ON(mp)) 120 return -ESRCH; 121 if (info->i_fieldmask & ~XFS_QC_SETINFO_MASK) 122 return -EINVAL; 123 if ((info->i_fieldmask & XFS_QC_SETINFO_MASK) == 0) 124 return 0; 125 126 newlim.d_fieldmask = info->i_fieldmask; 127 newlim.d_spc_timer = info->i_spc_timelimit; 128 newlim.d_ino_timer = info->i_ino_timelimit; 129 newlim.d_rt_spc_timer = info->i_rt_spc_timelimit; 130 newlim.d_ino_warns = info->i_ino_warnlimit; 131 newlim.d_spc_warns = info->i_spc_warnlimit; 132 newlim.d_rt_spc_warns = info->i_rt_spc_warnlimit; 133 134 return xfs_qm_scall_setqlim(mp, 0, xfs_quota_type(type), &newlim); 135 } 136 137 static unsigned int 138 xfs_quota_flags(unsigned int uflags) 139 { 140 unsigned int flags = 0; 141 142 if (uflags & FS_QUOTA_UDQ_ACCT) 143 flags |= XFS_UQUOTA_ACCT; 144 if (uflags & FS_QUOTA_PDQ_ACCT) 145 flags |= XFS_PQUOTA_ACCT; 146 if (uflags & FS_QUOTA_GDQ_ACCT) 147 flags |= XFS_GQUOTA_ACCT; 148 if (uflags & FS_QUOTA_UDQ_ENFD) 149 flags |= XFS_UQUOTA_ENFD; 150 if (uflags & FS_QUOTA_GDQ_ENFD) 151 flags |= XFS_GQUOTA_ENFD; 152 if (uflags & FS_QUOTA_PDQ_ENFD) 153 flags |= XFS_PQUOTA_ENFD; 154 155 return flags; 156 } 157 158 STATIC int 159 xfs_quota_enable( 160 struct super_block *sb, 161 unsigned int uflags) 162 { 163 struct xfs_mount *mp = XFS_M(sb); 164 165 if (sb_rdonly(sb)) 166 return -EROFS; 167 if (!XFS_IS_QUOTA_RUNNING(mp)) 168 return -ENOSYS; 169 170 return xfs_qm_scall_quotaon(mp, xfs_quota_flags(uflags)); 171 } 172 173 STATIC int 174 xfs_quota_disable( 175 struct super_block *sb, 176 unsigned int uflags) 177 { 178 struct xfs_mount *mp = XFS_M(sb); 179 180 if (sb_rdonly(sb)) 181 return -EROFS; 182 if (!XFS_IS_QUOTA_RUNNING(mp)) 183 return -ENOSYS; 184 if (!XFS_IS_QUOTA_ON(mp)) 185 return -EINVAL; 186 187 return xfs_qm_scall_quotaoff(mp, xfs_quota_flags(uflags)); 188 } 189 190 STATIC int 191 xfs_fs_rm_xquota( 192 struct super_block *sb, 193 unsigned int uflags) 194 { 195 struct xfs_mount *mp = XFS_M(sb); 196 unsigned int flags = 0; 197 198 if (sb_rdonly(sb)) 199 return -EROFS; 200 201 if (XFS_IS_QUOTA_ON(mp)) 202 return -EINVAL; 203 204 if (uflags & ~(FS_USER_QUOTA | FS_GROUP_QUOTA | FS_PROJ_QUOTA)) 205 return -EINVAL; 206 207 if (uflags & FS_USER_QUOTA) 208 flags |= XFS_DQ_USER; 209 if (uflags & FS_GROUP_QUOTA) 210 flags |= XFS_DQ_GROUP; 211 if (uflags & FS_PROJ_QUOTA) 212 flags |= XFS_DQ_PROJ; 213 214 return xfs_qm_scall_trunc_qfiles(mp, flags); 215 } 216 217 STATIC int 218 xfs_fs_get_dqblk( 219 struct super_block *sb, 220 struct kqid qid, 221 struct qc_dqblk *qdq) 222 { 223 struct xfs_mount *mp = XFS_M(sb); 224 xfs_dqid_t id; 225 226 if (!XFS_IS_QUOTA_RUNNING(mp)) 227 return -ENOSYS; 228 if (!XFS_IS_QUOTA_ON(mp)) 229 return -ESRCH; 230 231 id = from_kqid(&init_user_ns, qid); 232 return xfs_qm_scall_getquota(mp, id, xfs_quota_type(qid.type), qdq); 233 } 234 235 /* Return quota info for active quota >= this qid */ 236 STATIC int 237 xfs_fs_get_nextdqblk( 238 struct super_block *sb, 239 struct kqid *qid, 240 struct qc_dqblk *qdq) 241 { 242 int ret; 243 struct xfs_mount *mp = XFS_M(sb); 244 xfs_dqid_t id; 245 246 if (!XFS_IS_QUOTA_RUNNING(mp)) 247 return -ENOSYS; 248 if (!XFS_IS_QUOTA_ON(mp)) 249 return -ESRCH; 250 251 id = from_kqid(&init_user_ns, *qid); 252 ret = xfs_qm_scall_getquota_next(mp, &id, xfs_quota_type(qid->type), 253 qdq); 254 if (ret) 255 return ret; 256 257 /* ID may be different, so convert back what we got */ 258 *qid = make_kqid(current_user_ns(), qid->type, id); 259 return 0; 260 } 261 262 STATIC int 263 xfs_fs_set_dqblk( 264 struct super_block *sb, 265 struct kqid qid, 266 struct qc_dqblk *qdq) 267 { 268 struct xfs_mount *mp = XFS_M(sb); 269 270 if (sb_rdonly(sb)) 271 return -EROFS; 272 if (!XFS_IS_QUOTA_RUNNING(mp)) 273 return -ENOSYS; 274 if (!XFS_IS_QUOTA_ON(mp)) 275 return -ESRCH; 276 277 return xfs_qm_scall_setqlim(mp, from_kqid(&init_user_ns, qid), 278 xfs_quota_type(qid.type), qdq); 279 } 280 281 const struct quotactl_ops xfs_quotactl_operations = { 282 .get_state = xfs_fs_get_quota_state, 283 .set_info = xfs_fs_set_info, 284 .quota_enable = xfs_quota_enable, 285 .quota_disable = xfs_quota_disable, 286 .rm_xquota = xfs_fs_rm_xquota, 287 .get_dqblk = xfs_fs_get_dqblk, 288 .get_nextdqblk = xfs_fs_get_nextdqblk, 289 .set_dqblk = xfs_fs_set_dqblk, 290 }; 291