0001
0002
0003
0004
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
0052
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
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
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
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 };