Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c472b432 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Jan Kara
Browse files

quota: unify ->set_dqblk



Pass the larger struct fs_disk_quota to the ->set_dqblk operation so
that the Q_SETQUOTA and Q_XSETQUOTA operations can be implemented
with a single filesystem operation and we can retire the ->set_xquota
operation.  The additional information (RT-subvolume accounting and
warn counts) are left zero for the VFS quota implementation.

Add new fieldmask values for setting the numer of blocks and inodes
values which is required for the VFS quota, but wasn't for XFS.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent b9b2dd36
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -1521,7 +1521,7 @@ static int gfs2_get_dqblk(struct super_block *sb, int type, qid_t id,
/* GFS2 only supports a subset of the XFS fields */
#define GFS2_FIELDMASK (FS_DQ_BSOFT|FS_DQ_BHARD)

static int gfs2_xquota_set(struct super_block *sb, int type, qid_t id,
static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id,
			  struct fs_disk_quota *fdq)
{
	struct gfs2_sbd *sdp = sb->s_fs_info;
@@ -1630,6 +1630,6 @@ const struct quotactl_ops gfs2_quotactl_ops = {
	.quota_sync     = gfs2_quota_sync,
	.get_xstate     = gfs2_quota_get_xstate,
	.get_dqblk	= gfs2_get_dqblk,
	.set_xquota	= gfs2_xquota_set,
	.set_dqblk	= gfs2_set_dqblk,
};
+43 −24
Original line number Diff line number Diff line
@@ -2338,51 +2338,70 @@ int vfs_get_dqblk(struct super_block *sb, int type, qid_t id,
}
EXPORT_SYMBOL(vfs_get_dqblk);

#define VFS_FS_DQ_MASK \
	(FS_DQ_BCOUNT | FS_DQ_BSOFT | FS_DQ_BHARD | \
	 FS_DQ_ICOUNT | FS_DQ_ISOFT | FS_DQ_IHARD | \
	 FS_DQ_BTIMER | FS_DQ_ITIMER)

/* Generic routine for setting common part of quota structure */
static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
static int do_set_dqblk(struct dquot *dquot, struct fs_disk_quota *di)
{
	struct mem_dqblk *dm = &dquot->dq_dqb;
	int check_blim = 0, check_ilim = 0;
	struct mem_dqinfo *dqi = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_type];

	if ((di->dqb_valid & QIF_BLIMITS &&
	     (di->dqb_bhardlimit > dqi->dqi_maxblimit ||
	      di->dqb_bsoftlimit > dqi->dqi_maxblimit)) ||
	    (di->dqb_valid & QIF_ILIMITS &&
	     (di->dqb_ihardlimit > dqi->dqi_maxilimit ||
	      di->dqb_isoftlimit > dqi->dqi_maxilimit)))
	if (di->d_fieldmask & ~VFS_FS_DQ_MASK)
		return -EINVAL;

	if (((di->d_fieldmask & FS_DQ_BSOFT) &&
	     (di->d_blk_softlimit > dqi->dqi_maxblimit)) ||
	    ((di->d_fieldmask & FS_DQ_BHARD) &&
	     (di->d_blk_hardlimit > dqi->dqi_maxblimit)) ||
	    ((di->d_fieldmask & FS_DQ_ISOFT) &&
	     (di->d_ino_softlimit > dqi->dqi_maxilimit)) ||
	    ((di->d_fieldmask & FS_DQ_IHARD) &&
	     (di->d_ino_hardlimit > dqi->dqi_maxilimit)))
		return -ERANGE;

	spin_lock(&dq_data_lock);
	if (di->dqb_valid & QIF_SPACE) {
		dm->dqb_curspace = di->dqb_curspace - dm->dqb_rsvspace;
	if (di->d_fieldmask & FS_DQ_BCOUNT) {
		dm->dqb_curspace = di->d_bcount - dm->dqb_rsvspace;
		check_blim = 1;
		set_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags);
	}
	if (di->dqb_valid & QIF_BLIMITS) {
		dm->dqb_bsoftlimit = qbtos(di->dqb_bsoftlimit);
		dm->dqb_bhardlimit = qbtos(di->dqb_bhardlimit);

	if (di->d_fieldmask & FS_DQ_BSOFT)
		dm->dqb_bsoftlimit = qbtos(di->d_blk_softlimit);
	if (di->d_fieldmask & FS_DQ_BHARD)
		dm->dqb_bhardlimit = qbtos(di->d_blk_hardlimit);
	if (di->d_fieldmask & (FS_DQ_BSOFT | FS_DQ_BHARD)) {
		check_blim = 1;
		set_bit(DQ_LASTSET_B + QIF_BLIMITS_B, &dquot->dq_flags);
	}
	if (di->dqb_valid & QIF_INODES) {
		dm->dqb_curinodes = di->dqb_curinodes;

	if (di->d_fieldmask & FS_DQ_ICOUNT) {
		dm->dqb_curinodes = di->d_icount;
		check_ilim = 1;
		set_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags);
	}
	if (di->dqb_valid & QIF_ILIMITS) {
		dm->dqb_isoftlimit = di->dqb_isoftlimit;
		dm->dqb_ihardlimit = di->dqb_ihardlimit;

	if (di->d_fieldmask & FS_DQ_ISOFT)
		dm->dqb_isoftlimit = di->d_ino_softlimit;
	if (di->d_fieldmask & FS_DQ_IHARD)
		dm->dqb_ihardlimit = di->d_ino_hardlimit;
	if (di->d_fieldmask & (FS_DQ_ISOFT | FS_DQ_IHARD)) {
		check_ilim = 1;
		set_bit(DQ_LASTSET_B + QIF_ILIMITS_B, &dquot->dq_flags);
	}
	if (di->dqb_valid & QIF_BTIME) {
		dm->dqb_btime = di->dqb_btime;

	if (di->d_fieldmask & FS_DQ_BTIMER) {
		dm->dqb_btime = di->d_btimer;
		check_blim = 1;
		set_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags);
	}
	if (di->dqb_valid & QIF_ITIME) {
		dm->dqb_itime = di->dqb_itime;

	if (di->d_fieldmask & FS_DQ_ITIMER) {
		dm->dqb_itime = di->d_itimer;
		check_ilim = 1;
		set_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags);
	}
@@ -2392,7 +2411,7 @@ static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
		    dm->dqb_curspace < dm->dqb_bsoftlimit) {
			dm->dqb_btime = 0;
			clear_bit(DQ_BLKS_B, &dquot->dq_flags);
		} else if (!(di->dqb_valid & QIF_BTIME))
		} else if (!(di->d_fieldmask & FS_DQ_BTIMER))
			/* Set grace only if user hasn't provided his own... */
			dm->dqb_btime = get_seconds() + dqi->dqi_bgrace;
	}
@@ -2401,7 +2420,7 @@ static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
		    dm->dqb_curinodes < dm->dqb_isoftlimit) {
			dm->dqb_itime = 0;
			clear_bit(DQ_INODES_B, &dquot->dq_flags);
		} else if (!(di->dqb_valid & QIF_ITIME))
		} else if (!(di->d_fieldmask & FS_DQ_ITIMER))
			/* Set grace only if user hasn't provided his own... */
			dm->dqb_itime = get_seconds() + dqi->dqi_igrace;
	}
@@ -2417,7 +2436,7 @@ static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
}

int vfs_set_dqblk(struct super_block *sb, int type, qid_t id,
		  struct if_dqblk *di)
		  struct fs_disk_quota *di)
{
	struct dquot *dquot;
	int rc;
+31 −5
Original line number Diff line number Diff line
@@ -167,18 +167,44 @@ static int quota_getquota(struct super_block *sb, int type, qid_t id,
	return 0;
}

static void copy_from_if_dqblk(struct fs_disk_quota *dst, struct if_dqblk *src)
{
	dst->d_blk_hardlimit = src->dqb_bhardlimit;
	dst->d_blk_softlimit  = src->dqb_bsoftlimit;
	dst->d_bcount = src->dqb_curspace;
	dst->d_ino_hardlimit = src->dqb_ihardlimit;
	dst->d_ino_softlimit = src->dqb_isoftlimit;
	dst->d_icount = src->dqb_curinodes;
	dst->d_btimer = src->dqb_btime;
	dst->d_itimer = src->dqb_itime;

	dst->d_fieldmask = 0;
	if (src->dqb_valid & QIF_BLIMITS)
		dst->d_fieldmask |= FS_DQ_BSOFT | FS_DQ_BHARD;
	if (src->dqb_valid & QIF_SPACE)
		dst->d_fieldmask |= FS_DQ_BCOUNT;
	if (src->dqb_valid & QIF_ILIMITS)
		dst->d_fieldmask |= FS_DQ_ISOFT | FS_DQ_IHARD;
	if (src->dqb_valid & QIF_INODES)
		dst->d_fieldmask |= FS_DQ_ICOUNT;
	if (src->dqb_valid & QIF_BTIME)
		dst->d_fieldmask |= FS_DQ_BTIMER;
	if (src->dqb_valid & QIF_ITIME)
		dst->d_fieldmask |= FS_DQ_ITIMER;
}

static int quota_setquota(struct super_block *sb, int type, qid_t id,
			  void __user *addr)
{
	struct fs_disk_quota fdq;
	struct if_dqblk idq;

	if (copy_from_user(&idq, addr, sizeof(idq)))
		return -EFAULT;
	if (!sb_has_quota_active(sb, type))
		return -ESRCH;
	if (!sb->s_qcop->set_dqblk)
		return -ENOSYS;
	return sb->s_qcop->set_dqblk(sb, type, id, &idq);
	copy_from_if_dqblk(&fdq, &idq);
	return sb->s_qcop->set_dqblk(sb, type, id, &fdq);
}

static int quota_setxstate(struct super_block *sb, int cmd, void __user *addr)
@@ -212,9 +238,9 @@ static int quota_setxquota(struct super_block *sb, int type, qid_t id,

	if (copy_from_user(&fdq, addr, sizeof(fdq)))
		return -EFAULT;
	if (!sb->s_qcop->set_xquota)
	if (!sb->s_qcop->set_dqblk)
		return -ENOSYS;
	return sb->s_qcop->set_xquota(sb, type, id, &fdq);
	return sb->s_qcop->set_dqblk(sb, type, id, &fdq);
}

static int quota_getxquota(struct super_block *sb, int type, qid_t id,
+2 −2
Original line number Diff line number Diff line
@@ -114,7 +114,7 @@ xfs_fs_get_dqblk(
}

STATIC int
xfs_fs_set_xquota(
xfs_fs_set_dqblk(
	struct super_block	*sb,
	int			type,
	qid_t			id,
@@ -136,5 +136,5 @@ const struct quotactl_ops xfs_quotactl_operations = {
	.get_xstate		= xfs_fs_get_xstate,
	.set_xstate		= xfs_fs_set_xstate,
	.get_dqblk		= xfs_fs_get_dqblk,
	.set_xquota		= xfs_fs_set_xquota,
	.set_dqblk		= xfs_fs_set_dqblk,
};
+7 −3
Original line number Diff line number Diff line
@@ -448,6 +448,9 @@ xfs_qm_scall_getqstat(
	return 0;
}

#define XFS_DQ_MASK \
	(FS_DQ_LIMIT_MASK | FS_DQ_TIMER_MASK | FS_DQ_WARNS_MASK)

/*
 * Adjust quota limits, and start/stop timers accordingly.
 */
@@ -465,9 +468,10 @@ xfs_qm_scall_setqlim(
	int			error;
	xfs_qcnt_t		hard, soft;

	if ((newlim->d_fieldmask &
	    (FS_DQ_LIMIT_MASK|FS_DQ_TIMER_MASK|FS_DQ_WARNS_MASK)) == 0)
		return (0);
	if (newlim->d_fieldmask & ~XFS_DQ_MASK)
		return EINVAL;
	if ((newlim->d_fieldmask & XFS_DQ_MASK) == 0)
		return 0;

	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SETQLIM);
	if ((error = xfs_trans_reserve(tp, 0, sizeof(xfs_disk_dquot_t) + 128,
Loading