Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 196252
b: refs/heads/master
c: c472b43
h: refs/heads/master
v: v3
  • Loading branch information
Christoph Hellwig authored and Jan Kara committed May 21, 2010
1 parent c0e7170 commit 5c69c99
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 41 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b9b2dd36c1bc64430f8e13990ab135cbecc10076
refs/heads/master: c472b43275976512e4c1c32da5ced03f339cb380
6 changes: 3 additions & 3 deletions trunk/fs/gfs2/quota.c
Original file line number Diff line number Diff line change
Expand Up @@ -1521,8 +1521,8 @@ 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,
struct fs_disk_quota *fdq)
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;
struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);
Expand Down Expand Up @@ -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,
};

67 changes: 43 additions & 24 deletions trunk/fs/quota/dquot.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
Expand Down
36 changes: 31 additions & 5 deletions trunk/fs/quota/quota.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions trunk/fs/xfs/linux-2.6/xfs_quotaops.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
};
10 changes: 7 additions & 3 deletions trunk/fs/xfs/quota/xfs_qm_syscalls.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand All @@ -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,
Expand Down
9 changes: 9 additions & 0 deletions trunk/include/linux/dqblk_xfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,15 @@ typedef struct fs_disk_quota {
#define FS_DQ_RTBWARNS (1<<11)
#define FS_DQ_WARNS_MASK (FS_DQ_BWARNS | FS_DQ_IWARNS | FS_DQ_RTBWARNS)

/*
* Accounting values. These can only be set for filesystem with
* non-transactional quotas that require quotacheck(8) in userspace.
*/
#define FS_DQ_BCOUNT (1<<12)
#define FS_DQ_ICOUNT (1<<13)
#define FS_DQ_RTBCOUNT (1<<14)
#define FS_DQ_ACCT_MASK (FS_DQ_BCOUNT | FS_DQ_ICOUNT | FS_DQ_RTBCOUNT)

/*
* Various flags related to quotactl(2). Only relevant to XFS filesystems.
*/
Expand Down
3 changes: 1 addition & 2 deletions trunk/include/linux/quota.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,10 +338,9 @@ struct quotactl_ops {
int (*get_info)(struct super_block *, int, struct if_dqinfo *);
int (*set_info)(struct super_block *, int, struct if_dqinfo *);
int (*get_dqblk)(struct super_block *, int, qid_t, struct fs_disk_quota *);
int (*set_dqblk)(struct super_block *, int, qid_t, struct if_dqblk *);
int (*set_dqblk)(struct super_block *, int, qid_t, struct fs_disk_quota *);
int (*get_xstate)(struct super_block *, struct fs_quota_stat *);
int (*set_xstate)(struct super_block *, unsigned int, int);
int (*set_xquota)(struct super_block *, int, qid_t, struct fs_disk_quota *);
};

struct quota_format_type {
Expand Down
3 changes: 2 additions & 1 deletion trunk/include/linux/quotaops.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
int vfs_get_dqblk(struct super_block *sb, int type, qid_t id,
struct fs_disk_quota *di);
int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di);
int vfs_set_dqblk(struct super_block *sb, int type, qid_t id,
struct fs_disk_quota *di);

int dquot_transfer(struct inode *inode, struct iattr *iattr);
int vfs_dq_quota_on_remount(struct super_block *sb);
Expand Down

0 comments on commit 5c69c99

Please sign in to comment.