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