Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2008, Christoph Hellwig
0004  * All Rights Reserved.
0005  */
0006 #include "xfs.h"
0007 #include "xfs_shared.h"
0008 #include "xfs_format.h"
0009 #include "xfs_log_format.h"
0010 #include "xfs_trans_resv.h"
0011 #include "xfs_mount.h"
0012 #include "xfs_inode.h"
0013 #include "xfs_quota.h"
0014 #include "xfs_trans.h"
0015 #include "xfs_icache.h"
0016 #include "xfs_qm.h"
0017 
0018 
0019 static void
0020 xfs_qm_fill_state(
0021     struct qc_type_state    *tstate,
0022     struct xfs_mount    *mp,
0023     struct xfs_inode    *ip,
0024     xfs_ino_t       ino,
0025     struct xfs_def_quota    *defq)
0026 {
0027     bool            tempqip = false;
0028 
0029     tstate->ino = ino;
0030     if (!ip && ino == NULLFSINO)
0031         return;
0032     if (!ip) {
0033         if (xfs_iget(mp, NULL, ino, 0, 0, &ip))
0034             return;
0035         tempqip = true;
0036     }
0037     tstate->flags |= QCI_SYSFILE;
0038     tstate->blocks = ip->i_nblocks;
0039     tstate->nextents = ip->i_df.if_nextents;
0040     tstate->spc_timelimit = (u32)defq->blk.time;
0041     tstate->ino_timelimit = (u32)defq->ino.time;
0042     tstate->rt_spc_timelimit = (u32)defq->rtb.time;
0043     tstate->spc_warnlimit = 0;
0044     tstate->ino_warnlimit = 0;
0045     tstate->rt_spc_warnlimit = 0;
0046     if (tempqip)
0047         xfs_irele(ip);
0048 }
0049 
0050 /*
0051  * Return quota status information, such as enforcements, quota file inode
0052  * numbers etc.
0053  */
0054 static int
0055 xfs_fs_get_quota_state(
0056     struct super_block  *sb,
0057     struct qc_state     *state)
0058 {
0059     struct xfs_mount *mp = XFS_M(sb);
0060     struct xfs_quotainfo *q = mp->m_quotainfo;
0061 
0062     memset(state, 0, sizeof(*state));
0063     if (!XFS_IS_QUOTA_ON(mp))
0064         return 0;
0065     state->s_incoredqs = q->qi_dquots;
0066     if (XFS_IS_UQUOTA_ON(mp))
0067         state->s_state[USRQUOTA].flags |= QCI_ACCT_ENABLED;
0068     if (XFS_IS_UQUOTA_ENFORCED(mp))
0069         state->s_state[USRQUOTA].flags |= QCI_LIMITS_ENFORCED;
0070     if (XFS_IS_GQUOTA_ON(mp))
0071         state->s_state[GRPQUOTA].flags |= QCI_ACCT_ENABLED;
0072     if (XFS_IS_GQUOTA_ENFORCED(mp))
0073         state->s_state[GRPQUOTA].flags |= QCI_LIMITS_ENFORCED;
0074     if (XFS_IS_PQUOTA_ON(mp))
0075         state->s_state[PRJQUOTA].flags |= QCI_ACCT_ENABLED;
0076     if (XFS_IS_PQUOTA_ENFORCED(mp))
0077         state->s_state[PRJQUOTA].flags |= QCI_LIMITS_ENFORCED;
0078 
0079     xfs_qm_fill_state(&state->s_state[USRQUOTA], mp, q->qi_uquotaip,
0080               mp->m_sb.sb_uquotino, &q->qi_usr_default);
0081     xfs_qm_fill_state(&state->s_state[GRPQUOTA], mp, q->qi_gquotaip,
0082               mp->m_sb.sb_gquotino, &q->qi_grp_default);
0083     xfs_qm_fill_state(&state->s_state[PRJQUOTA], mp, q->qi_pquotaip,
0084               mp->m_sb.sb_pquotino, &q->qi_prj_default);
0085     return 0;
0086 }
0087 
0088 STATIC xfs_dqtype_t
0089 xfs_quota_type(int type)
0090 {
0091     switch (type) {
0092     case USRQUOTA:
0093         return XFS_DQTYPE_USER;
0094     case GRPQUOTA:
0095         return XFS_DQTYPE_GROUP;
0096     default:
0097         return XFS_DQTYPE_PROJ;
0098     }
0099 }
0100 
0101 #define XFS_QC_SETINFO_MASK (QC_TIMER_MASK)
0102 
0103 /*
0104  * Adjust quota timers & warnings
0105  */
0106 static int
0107 xfs_fs_set_info(
0108     struct super_block  *sb,
0109     int         type,
0110     struct qc_info      *info)
0111 {
0112     struct xfs_mount    *mp = XFS_M(sb);
0113     struct qc_dqblk     newlim;
0114 
0115     if (sb_rdonly(sb))
0116         return -EROFS;
0117     if (!XFS_IS_QUOTA_ON(mp))
0118         return -ENOSYS;
0119     if (info->i_fieldmask & ~XFS_QC_SETINFO_MASK)
0120         return -EINVAL;
0121     if ((info->i_fieldmask & XFS_QC_SETINFO_MASK) == 0)
0122         return 0;
0123 
0124     newlim.d_fieldmask = info->i_fieldmask;
0125     newlim.d_spc_timer = info->i_spc_timelimit;
0126     newlim.d_ino_timer = info->i_ino_timelimit;
0127     newlim.d_rt_spc_timer = info->i_rt_spc_timelimit;
0128     newlim.d_ino_warns = info->i_ino_warnlimit;
0129     newlim.d_spc_warns = info->i_spc_warnlimit;
0130     newlim.d_rt_spc_warns = info->i_rt_spc_warnlimit;
0131 
0132     return xfs_qm_scall_setqlim(mp, 0, xfs_quota_type(type), &newlim);
0133 }
0134 
0135 static unsigned int
0136 xfs_quota_flags(unsigned int uflags)
0137 {
0138     unsigned int flags = 0;
0139 
0140     if (uflags & FS_QUOTA_UDQ_ACCT)
0141         flags |= XFS_UQUOTA_ACCT;
0142     if (uflags & FS_QUOTA_PDQ_ACCT)
0143         flags |= XFS_PQUOTA_ACCT;
0144     if (uflags & FS_QUOTA_GDQ_ACCT)
0145         flags |= XFS_GQUOTA_ACCT;
0146     if (uflags & FS_QUOTA_UDQ_ENFD)
0147         flags |= XFS_UQUOTA_ENFD;
0148     if (uflags & FS_QUOTA_GDQ_ENFD)
0149         flags |= XFS_GQUOTA_ENFD;
0150     if (uflags & FS_QUOTA_PDQ_ENFD)
0151         flags |= XFS_PQUOTA_ENFD;
0152 
0153     return flags;
0154 }
0155 
0156 STATIC int
0157 xfs_quota_enable(
0158     struct super_block  *sb,
0159     unsigned int        uflags)
0160 {
0161     struct xfs_mount    *mp = XFS_M(sb);
0162 
0163     if (sb_rdonly(sb))
0164         return -EROFS;
0165     if (!XFS_IS_QUOTA_ON(mp))
0166         return -ENOSYS;
0167 
0168     return xfs_qm_scall_quotaon(mp, xfs_quota_flags(uflags));
0169 }
0170 
0171 STATIC int
0172 xfs_quota_disable(
0173     struct super_block  *sb,
0174     unsigned int        uflags)
0175 {
0176     struct xfs_mount    *mp = XFS_M(sb);
0177 
0178     if (sb_rdonly(sb))
0179         return -EROFS;
0180     if (!XFS_IS_QUOTA_ON(mp))
0181         return -ENOSYS;
0182 
0183     return xfs_qm_scall_quotaoff(mp, xfs_quota_flags(uflags));
0184 }
0185 
0186 STATIC int
0187 xfs_fs_rm_xquota(
0188     struct super_block  *sb,
0189     unsigned int        uflags)
0190 {
0191     struct xfs_mount    *mp = XFS_M(sb);
0192     unsigned int        flags = 0;
0193 
0194     if (sb_rdonly(sb))
0195         return -EROFS;
0196 
0197     if (XFS_IS_QUOTA_ON(mp))
0198         return -EINVAL;
0199 
0200     if (uflags & ~(FS_USER_QUOTA | FS_GROUP_QUOTA | FS_PROJ_QUOTA))
0201         return -EINVAL;
0202 
0203     if (uflags & FS_USER_QUOTA)
0204         flags |= XFS_QMOPT_UQUOTA;
0205     if (uflags & FS_GROUP_QUOTA)
0206         flags |= XFS_QMOPT_GQUOTA;
0207     if (uflags & FS_PROJ_QUOTA)
0208         flags |= XFS_QMOPT_PQUOTA;
0209 
0210     return xfs_qm_scall_trunc_qfiles(mp, flags);
0211 }
0212 
0213 STATIC int
0214 xfs_fs_get_dqblk(
0215     struct super_block  *sb,
0216     struct kqid     qid,
0217     struct qc_dqblk     *qdq)
0218 {
0219     struct xfs_mount    *mp = XFS_M(sb);
0220     xfs_dqid_t      id;
0221 
0222     if (!XFS_IS_QUOTA_ON(mp))
0223         return -ENOSYS;
0224 
0225     id = from_kqid(&init_user_ns, qid);
0226     return xfs_qm_scall_getquota(mp, id, xfs_quota_type(qid.type), qdq);
0227 }
0228 
0229 /* Return quota info for active quota >= this qid */
0230 STATIC int
0231 xfs_fs_get_nextdqblk(
0232     struct super_block  *sb,
0233     struct kqid     *qid,
0234     struct qc_dqblk     *qdq)
0235 {
0236     int         ret;
0237     struct xfs_mount    *mp = XFS_M(sb);
0238     xfs_dqid_t      id;
0239 
0240     if (!XFS_IS_QUOTA_ON(mp))
0241         return -ENOSYS;
0242 
0243     id = from_kqid(&init_user_ns, *qid);
0244     ret = xfs_qm_scall_getquota_next(mp, &id, xfs_quota_type(qid->type),
0245             qdq);
0246     if (ret)
0247         return ret;
0248 
0249     /* ID may be different, so convert back what we got */
0250     *qid = make_kqid(current_user_ns(), qid->type, id);
0251     return 0;
0252 }
0253 
0254 STATIC int
0255 xfs_fs_set_dqblk(
0256     struct super_block  *sb,
0257     struct kqid     qid,
0258     struct qc_dqblk     *qdq)
0259 {
0260     struct xfs_mount    *mp = XFS_M(sb);
0261 
0262     if (sb_rdonly(sb))
0263         return -EROFS;
0264     if (!XFS_IS_QUOTA_ON(mp))
0265         return -ENOSYS;
0266 
0267     return xfs_qm_scall_setqlim(mp, from_kqid(&init_user_ns, qid),
0268                      xfs_quota_type(qid.type), qdq);
0269 }
0270 
0271 const struct quotactl_ops xfs_quotactl_operations = {
0272     .get_state      = xfs_fs_get_quota_state,
0273     .set_info       = xfs_fs_set_info,
0274     .quota_enable       = xfs_quota_enable,
0275     .quota_disable      = xfs_quota_disable,
0276     .rm_xquota      = xfs_fs_rm_xquota,
0277     .get_dqblk      = xfs_fs_get_dqblk,
0278     .get_nextdqblk      = xfs_fs_get_nextdqblk,
0279     .set_dqblk      = xfs_fs_set_dqblk,
0280 };