|
@@ -517,6 +517,30 @@ static void copy_from_xfs_dqblk(struct qc_dqblk *dst, struct fs_disk_quota *src)
|
|
dst->d_fieldmask |= QC_RT_SPACE;
|
|
dst->d_fieldmask |= QC_RT_SPACE;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void copy_qcinfo_from_xfs_dqblk(struct qc_info *dst,
|
|
|
|
+ struct fs_disk_quota *src)
|
|
|
|
+{
|
|
|
|
+ memset(dst, 0, sizeof(*dst));
|
|
|
|
+ dst->i_spc_timelimit = src->d_btimer;
|
|
|
|
+ dst->i_ino_timelimit = src->d_itimer;
|
|
|
|
+ dst->i_rt_spc_timelimit = src->d_rtbtimer;
|
|
|
|
+ dst->i_ino_warnlimit = src->d_iwarns;
|
|
|
|
+ dst->i_spc_warnlimit = src->d_bwarns;
|
|
|
|
+ dst->i_rt_spc_warnlimit = src->d_rtbwarns;
|
|
|
|
+ if (src->d_fieldmask & FS_DQ_BWARNS)
|
|
|
|
+ dst->i_fieldmask |= QC_SPC_WARNS;
|
|
|
|
+ if (src->d_fieldmask & FS_DQ_IWARNS)
|
|
|
|
+ dst->i_fieldmask |= QC_INO_WARNS;
|
|
|
|
+ if (src->d_fieldmask & FS_DQ_RTBWARNS)
|
|
|
|
+ dst->i_fieldmask |= QC_RT_SPC_WARNS;
|
|
|
|
+ if (src->d_fieldmask & FS_DQ_BTIMER)
|
|
|
|
+ dst->i_fieldmask |= QC_SPC_TIMER;
|
|
|
|
+ if (src->d_fieldmask & FS_DQ_ITIMER)
|
|
|
|
+ dst->i_fieldmask |= QC_INO_TIMER;
|
|
|
|
+ if (src->d_fieldmask & FS_DQ_RTBTIMER)
|
|
|
|
+ dst->i_fieldmask |= QC_RT_SPC_TIMER;
|
|
|
|
+}
|
|
|
|
+
|
|
static int quota_setxquota(struct super_block *sb, int type, qid_t id,
|
|
static int quota_setxquota(struct super_block *sb, int type, qid_t id,
|
|
void __user *addr)
|
|
void __user *addr)
|
|
{
|
|
{
|
|
@@ -531,6 +555,21 @@ static int quota_setxquota(struct super_block *sb, int type, qid_t id,
|
|
qid = make_kqid(current_user_ns(), type, id);
|
|
qid = make_kqid(current_user_ns(), type, id);
|
|
if (!qid_valid(qid))
|
|
if (!qid_valid(qid))
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
+ /* Are we actually setting timer / warning limits for all users? */
|
|
|
|
+ if (from_kqid(&init_user_ns, qid) == 0 &&
|
|
|
|
+ fdq.d_fieldmask & (FS_DQ_WARNS_MASK | FS_DQ_TIMER_MASK)) {
|
|
|
|
+ struct qc_info qinfo;
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ if (!sb->s_qcop->set_info)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ copy_qcinfo_from_xfs_dqblk(&qinfo, &fdq);
|
|
|
|
+ ret = sb->s_qcop->set_info(sb, type, &qinfo);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+ /* These are already done */
|
|
|
|
+ fdq.d_fieldmask &= ~(FS_DQ_WARNS_MASK | FS_DQ_TIMER_MASK);
|
|
|
|
+ }
|
|
copy_from_xfs_dqblk(&qdq, &fdq);
|
|
copy_from_xfs_dqblk(&qdq, &fdq);
|
|
return sb->s_qcop->set_dqblk(sb, qid, &qdq);
|
|
return sb->s_qcop->set_dqblk(sb, qid, &qdq);
|
|
}
|
|
}
|