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