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_nblocks; 39 tstate->nextents = ip->i_df.if_nextents; 40 tstate->spc_timelimit = (u32)defq->blk.time; 41 tstate->ino_timelimit = (u32)defq->ino.time; 42 tstate->rt_spc_timelimit = (u32)defq->rtb.time; 43 tstate->spc_warnlimit = 0; 44 tstate->ino_warnlimit = 0; 45 tstate->rt_spc_warnlimit = 0; 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_ON(mp)) 64 return 0; 65 state->s_incoredqs = q->qi_dquots; 66 if (XFS_IS_UQUOTA_ON(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_ON(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_ON(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 xfs_dqtype_t 89 xfs_quota_type(int type) 90 { 91 switch (type) { 92 case USRQUOTA: 93 return XFS_DQTYPE_USER; 94 case GRPQUOTA: 95 return XFS_DQTYPE_GROUP; 96 default: 97 return XFS_DQTYPE_PROJ; 98 } 99 } 100 101 #define XFS_QC_SETINFO_MASK (QC_TIMER_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_ON(mp)) 118 return -ENOSYS; 119 if (info->i_fieldmask & ~XFS_QC_SETINFO_MASK) 120 return -EINVAL; 121 if ((info->i_fieldmask & XFS_QC_SETINFO_MASK) == 0) 122 return 0; 123 124 newlim.d_fieldmask = info->i_fieldmask; 125 newlim.d_spc_timer = info->i_spc_timelimit; 126 newlim.d_ino_timer = info->i_ino_timelimit; 127 newlim.d_rt_spc_timer = info->i_rt_spc_timelimit; 128 newlim.d_ino_warns = info->i_ino_warnlimit; 129 newlim.d_spc_warns = info->i_spc_warnlimit; 130 newlim.d_rt_spc_warns = info->i_rt_spc_warnlimit; 131 132 return xfs_qm_scall_setqlim(mp, 0, xfs_quota_type(type), &newlim); 133 } 134 135 static unsigned int 136 xfs_quota_flags(unsigned int uflags) 137 { 138 unsigned int flags = 0; 139 140 if (uflags & FS_QUOTA_UDQ_ACCT) 141 flags |= XFS_UQUOTA_ACCT; 142 if (uflags & FS_QUOTA_PDQ_ACCT) 143 flags |= XFS_PQUOTA_ACCT; 144 if (uflags & FS_QUOTA_GDQ_ACCT) 145 flags |= XFS_GQUOTA_ACCT; 146 if (uflags & FS_QUOTA_UDQ_ENFD) 147 flags |= XFS_UQUOTA_ENFD; 148 if (uflags & FS_QUOTA_GDQ_ENFD) 149 flags |= XFS_GQUOTA_ENFD; 150 if (uflags & FS_QUOTA_PDQ_ENFD) 151 flags |= XFS_PQUOTA_ENFD; 152 153 return flags; 154 } 155 156 STATIC int 157 xfs_quota_enable( 158 struct super_block *sb, 159 unsigned int uflags) 160 { 161 struct xfs_mount *mp = XFS_M(sb); 162 163 if (sb_rdonly(sb)) 164 return -EROFS; 165 if (!XFS_IS_QUOTA_ON(mp)) 166 return -ENOSYS; 167 168 return xfs_qm_scall_quotaon(mp, xfs_quota_flags(uflags)); 169 } 170 171 STATIC int 172 xfs_quota_disable( 173 struct super_block *sb, 174 unsigned int uflags) 175 { 176 struct xfs_mount *mp = XFS_M(sb); 177 178 if (sb_rdonly(sb)) 179 return -EROFS; 180 if (!XFS_IS_QUOTA_ON(mp)) 181 return -ENOSYS; 182 183 return xfs_qm_scall_quotaoff(mp, xfs_quota_flags(uflags)); 184 } 185 186 STATIC int 187 xfs_fs_rm_xquota( 188 struct super_block *sb, 189 unsigned int uflags) 190 { 191 struct xfs_mount *mp = XFS_M(sb); 192 unsigned int flags = 0; 193 194 if (sb_rdonly(sb)) 195 return -EROFS; 196 197 if (XFS_IS_QUOTA_ON(mp)) 198 return -EINVAL; 199 200 if (uflags & ~(FS_USER_QUOTA | FS_GROUP_QUOTA | FS_PROJ_QUOTA)) 201 return -EINVAL; 202 203 if (uflags & FS_USER_QUOTA) 204 flags |= XFS_QMOPT_UQUOTA; 205 if (uflags & FS_GROUP_QUOTA) 206 flags |= XFS_QMOPT_GQUOTA; 207 if (uflags & FS_PROJ_QUOTA) 208 flags |= XFS_QMOPT_PQUOTA; 209 210 return xfs_qm_scall_trunc_qfiles(mp, flags); 211 } 212 213 STATIC int 214 xfs_fs_get_dqblk( 215 struct super_block *sb, 216 struct kqid qid, 217 struct qc_dqblk *qdq) 218 { 219 struct xfs_mount *mp = XFS_M(sb); 220 xfs_dqid_t id; 221 222 if (!XFS_IS_QUOTA_ON(mp)) 223 return -ENOSYS; 224 225 id = from_kqid(&init_user_ns, qid); 226 return xfs_qm_scall_getquota(mp, id, xfs_quota_type(qid.type), qdq); 227 } 228 229 /* Return quota info for active quota >= this qid */ 230 STATIC int 231 xfs_fs_get_nextdqblk( 232 struct super_block *sb, 233 struct kqid *qid, 234 struct qc_dqblk *qdq) 235 { 236 int ret; 237 struct xfs_mount *mp = XFS_M(sb); 238 xfs_dqid_t id; 239 240 if (!XFS_IS_QUOTA_ON(mp)) 241 return -ENOSYS; 242 243 id = from_kqid(&init_user_ns, *qid); 244 ret = xfs_qm_scall_getquota_next(mp, &id, xfs_quota_type(qid->type), 245 qdq); 246 if (ret) 247 return ret; 248 249 /* ID may be different, so convert back what we got */ 250 *qid = make_kqid(current_user_ns(), qid->type, id); 251 return 0; 252 } 253 254 STATIC int 255 xfs_fs_set_dqblk( 256 struct super_block *sb, 257 struct kqid qid, 258 struct qc_dqblk *qdq) 259 { 260 struct xfs_mount *mp = XFS_M(sb); 261 262 if (sb_rdonly(sb)) 263 return -EROFS; 264 if (!XFS_IS_QUOTA_ON(mp)) 265 return -ENOSYS; 266 267 return xfs_qm_scall_setqlim(mp, from_kqid(&init_user_ns, qid), 268 xfs_quota_type(qid.type), qdq); 269 } 270 271 const struct quotactl_ops xfs_quotactl_operations = { 272 .get_state = xfs_fs_get_quota_state, 273 .set_info = xfs_fs_set_info, 274 .quota_enable = xfs_quota_enable, 275 .quota_disable = xfs_quota_disable, 276 .rm_xquota = xfs_fs_rm_xquota, 277 .get_dqblk = xfs_fs_get_dqblk, 278 .get_nextdqblk = xfs_fs_get_nextdqblk, 279 .set_dqblk = xfs_fs_set_dqblk, 280 }; 281
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.