aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2010-05-06 17:05:17 -0400
committerJan Kara <jack@suse.cz>2010-05-21 13:30:44 -0400
commitc472b43275976512e4c1c32da5ced03f339cb380 (patch)
tree9159fbfd1190456e8b3e699b856022c23f6ec10c
parentb9b2dd36c1bc64430f8e13990ab135cbecc10076 (diff)
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: Christoph Hellwig <hch@lst.de> Signed-off-by: Jan Kara <jack@suse.cz>
-rw-r--r--fs/gfs2/quota.c6
-rw-r--r--fs/quota/dquot.c67
-rw-r--r--fs/quota/quota.c36
-rw-r--r--fs/xfs/linux-2.6/xfs_quotaops.c4
-rw-r--r--fs/xfs/quota/xfs_qm_syscalls.c10
-rw-r--r--include/linux/dqblk_xfs.h9
-rw-r--r--include/linux/quota.h3
-rw-r--r--include/linux/quotaops.h3
8 files changed, 98 insertions, 40 deletions
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index dec93577a783..49667d68769e 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -1521,8 +1521,8 @@ out:
1521/* GFS2 only supports a subset of the XFS fields */ 1521/* GFS2 only supports a subset of the XFS fields */
1522#define GFS2_FIELDMASK (FS_DQ_BSOFT|FS_DQ_BHARD) 1522#define GFS2_FIELDMASK (FS_DQ_BSOFT|FS_DQ_BHARD)
1523 1523
1524static int gfs2_xquota_set(struct super_block *sb, int type, qid_t id, 1524static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id,
1525 struct fs_disk_quota *fdq) 1525 struct fs_disk_quota *fdq)
1526{ 1526{
1527 struct gfs2_sbd *sdp = sb->s_fs_info; 1527 struct gfs2_sbd *sdp = sb->s_fs_info;
1528 struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode); 1528 struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);
@@ -1630,6 +1630,6 @@ const struct quotactl_ops gfs2_quotactl_ops = {
1630 .quota_sync = gfs2_quota_sync, 1630 .quota_sync = gfs2_quota_sync,
1631 .get_xstate = gfs2_quota_get_xstate, 1631 .get_xstate = gfs2_quota_get_xstate,
1632 .get_dqblk = gfs2_get_dqblk, 1632 .get_dqblk = gfs2_get_dqblk,
1633 .set_xquota = gfs2_xquota_set, 1633 .set_dqblk = gfs2_set_dqblk,
1634}; 1634};
1635 1635
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 6aed77fc99c7..b1a5036560a9 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -2338,51 +2338,70 @@ int vfs_get_dqblk(struct super_block *sb, int type, qid_t id,
2338} 2338}
2339EXPORT_SYMBOL(vfs_get_dqblk); 2339EXPORT_SYMBOL(vfs_get_dqblk);
2340 2340
2341#define VFS_FS_DQ_MASK \
2342 (FS_DQ_BCOUNT | FS_DQ_BSOFT | FS_DQ_BHARD | \
2343 FS_DQ_ICOUNT | FS_DQ_ISOFT | FS_DQ_IHARD | \
2344 FS_DQ_BTIMER | FS_DQ_ITIMER)
2345
2341/* Generic routine for setting common part of quota structure */ 2346/* Generic routine for setting common part of quota structure */
2342static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di) 2347static int do_set_dqblk(struct dquot *dquot, struct fs_disk_quota *di)
2343{ 2348{
2344 struct mem_dqblk *dm = &dquot->dq_dqb; 2349 struct mem_dqblk *dm = &dquot->dq_dqb;
2345 int check_blim = 0, check_ilim = 0; 2350 int check_blim = 0, check_ilim = 0;
2346 struct mem_dqinfo *dqi = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_type]; 2351 struct mem_dqinfo *dqi = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_type];
2347 2352
2348 if ((di->dqb_valid & QIF_BLIMITS && 2353 if (di->d_fieldmask & ~VFS_FS_DQ_MASK)
2349 (di->dqb_bhardlimit > dqi->dqi_maxblimit || 2354 return -EINVAL;
2350 di->dqb_bsoftlimit > dqi->dqi_maxblimit)) || 2355
2351 (di->dqb_valid & QIF_ILIMITS && 2356 if (((di->d_fieldmask & FS_DQ_BSOFT) &&
2352 (di->dqb_ihardlimit > dqi->dqi_maxilimit || 2357 (di->d_blk_softlimit > dqi->dqi_maxblimit)) ||
2353 di->dqb_isoftlimit > dqi->dqi_maxilimit))) 2358 ((di->d_fieldmask & FS_DQ_BHARD) &&
2359 (di->d_blk_hardlimit > dqi->dqi_maxblimit)) ||
2360 ((di->d_fieldmask & FS_DQ_ISOFT) &&
2361 (di->d_ino_softlimit > dqi->dqi_maxilimit)) ||
2362 ((di->d_fieldmask & FS_DQ_IHARD) &&
2363 (di->d_ino_hardlimit > dqi->dqi_maxilimit)))
2354 return -ERANGE; 2364 return -ERANGE;
2355 2365
2356 spin_lock(&dq_data_lock); 2366 spin_lock(&dq_data_lock);
2357 if (di->dqb_valid & QIF_SPACE) { 2367 if (di->d_fieldmask & FS_DQ_BCOUNT) {
2358 dm->dqb_curspace = di->dqb_curspace - dm->dqb_rsvspace; 2368 dm->dqb_curspace = di->d_bcount - dm->dqb_rsvspace;
2359 check_blim = 1; 2369 check_blim = 1;
2360 set_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags); 2370 set_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags);
2361 } 2371 }
2362 if (di->dqb_valid & QIF_BLIMITS) { 2372
2363 dm->dqb_bsoftlimit = qbtos(di->dqb_bsoftlimit); 2373 if (di->d_fieldmask & FS_DQ_BSOFT)
2364 dm->dqb_bhardlimit = qbtos(di->dqb_bhardlimit); 2374 dm->dqb_bsoftlimit = qbtos(di->d_blk_softlimit);
2375 if (di->d_fieldmask & FS_DQ_BHARD)
2376 dm->dqb_bhardlimit = qbtos(di->d_blk_hardlimit);
2377 if (di->d_fieldmask & (FS_DQ_BSOFT | FS_DQ_BHARD)) {
2365 check_blim = 1; 2378 check_blim = 1;
2366 set_bit(DQ_LASTSET_B + QIF_BLIMITS_B, &dquot->dq_flags); 2379 set_bit(DQ_LASTSET_B + QIF_BLIMITS_B, &dquot->dq_flags);
2367 } 2380 }
2368 if (di->dqb_valid & QIF_INODES) { 2381
2369 dm->dqb_curinodes = di->dqb_curinodes; 2382 if (di->d_fieldmask & FS_DQ_ICOUNT) {
2383 dm->dqb_curinodes = di->d_icount;
2370 check_ilim = 1; 2384 check_ilim = 1;
2371 set_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags); 2385 set_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags);
2372 } 2386 }
2373 if (di->dqb_valid & QIF_ILIMITS) { 2387
2374 dm->dqb_isoftlimit = di->dqb_isoftlimit; 2388 if (di->d_fieldmask & FS_DQ_ISOFT)
2375 dm->dqb_ihardlimit = di->dqb_ihardlimit; 2389 dm->dqb_isoftlimit = di->d_ino_softlimit;
2390 if (di->d_fieldmask & FS_DQ_IHARD)
2391 dm->dqb_ihardlimit = di->d_ino_hardlimit;
2392 if (di->d_fieldmask & (FS_DQ_ISOFT | FS_DQ_IHARD)) {
2376 check_ilim = 1; 2393 check_ilim = 1;
2377 set_bit(DQ_LASTSET_B + QIF_ILIMITS_B, &dquot->dq_flags); 2394 set_bit(DQ_LASTSET_B + QIF_ILIMITS_B, &dquot->dq_flags);
2378 } 2395 }
2379 if (di->dqb_valid & QIF_BTIME) { 2396
2380 dm->dqb_btime = di->dqb_btime; 2397 if (di->d_fieldmask & FS_DQ_BTIMER) {
2398 dm->dqb_btime = di->d_btimer;
2381 check_blim = 1; 2399 check_blim = 1;
2382 set_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags); 2400 set_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags);
2383 } 2401 }
2384 if (di->dqb_valid & QIF_ITIME) { 2402
2385 dm->dqb_itime = di->dqb_itime; 2403 if (di->d_fieldmask & FS_DQ_ITIMER) {
2404 dm->dqb_itime = di->d_itimer;
2386 check_ilim = 1; 2405 check_ilim = 1;
2387 set_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags); 2406 set_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags);
2388 } 2407 }
@@ -2392,7 +2411,7 @@ static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
2392 dm->dqb_curspace < dm->dqb_bsoftlimit) { 2411 dm->dqb_curspace < dm->dqb_bsoftlimit) {
2393 dm->dqb_btime = 0; 2412 dm->dqb_btime = 0;
2394 clear_bit(DQ_BLKS_B, &dquot->dq_flags); 2413 clear_bit(DQ_BLKS_B, &dquot->dq_flags);
2395 } else if (!(di->dqb_valid & QIF_BTIME)) 2414 } else if (!(di->d_fieldmask & FS_DQ_BTIMER))
2396 /* Set grace only if user hasn't provided his own... */ 2415 /* Set grace only if user hasn't provided his own... */
2397 dm->dqb_btime = get_seconds() + dqi->dqi_bgrace; 2416 dm->dqb_btime = get_seconds() + dqi->dqi_bgrace;
2398 } 2417 }
@@ -2401,7 +2420,7 @@ static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
2401 dm->dqb_curinodes < dm->dqb_isoftlimit) { 2420 dm->dqb_curinodes < dm->dqb_isoftlimit) {
2402 dm->dqb_itime = 0; 2421 dm->dqb_itime = 0;
2403 clear_bit(DQ_INODES_B, &dquot->dq_flags); 2422 clear_bit(DQ_INODES_B, &dquot->dq_flags);
2404 } else if (!(di->dqb_valid & QIF_ITIME)) 2423 } else if (!(di->d_fieldmask & FS_DQ_ITIMER))
2405 /* Set grace only if user hasn't provided his own... */ 2424 /* Set grace only if user hasn't provided his own... */
2406 dm->dqb_itime = get_seconds() + dqi->dqi_igrace; 2425 dm->dqb_itime = get_seconds() + dqi->dqi_igrace;
2407 } 2426 }
@@ -2417,7 +2436,7 @@ static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
2417} 2436}
2418 2437
2419int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, 2438int vfs_set_dqblk(struct super_block *sb, int type, qid_t id,
2420 struct if_dqblk *di) 2439 struct fs_disk_quota *di)
2421{ 2440{
2422 struct dquot *dquot; 2441 struct dquot *dquot;
2423 int rc; 2442 int rc;
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index 8680e257c2bd..d6ee49dda4fd 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -167,18 +167,44 @@ static int quota_getquota(struct super_block *sb, int type, qid_t id,
167 return 0; 167 return 0;
168} 168}
169 169
170static void copy_from_if_dqblk(struct fs_disk_quota *dst, struct if_dqblk *src)
171{
172 dst->d_blk_hardlimit = src->dqb_bhardlimit;
173 dst->d_blk_softlimit = src->dqb_bsoftlimit;
174 dst->d_bcount = src->dqb_curspace;
175 dst->d_ino_hardlimit = src->dqb_ihardlimit;
176 dst->d_ino_softlimit = src->dqb_isoftlimit;
177 dst->d_icount = src->dqb_curinodes;
178 dst->d_btimer = src->dqb_btime;
179 dst->d_itimer = src->dqb_itime;
180
181 dst->d_fieldmask = 0;
182 if (src->dqb_valid & QIF_BLIMITS)
183 dst->d_fieldmask |= FS_DQ_BSOFT | FS_DQ_BHARD;
184 if (src->dqb_valid & QIF_SPACE)
185 dst->d_fieldmask |= FS_DQ_BCOUNT;
186 if (src->dqb_valid & QIF_ILIMITS)
187 dst->d_fieldmask |= FS_DQ_ISOFT | FS_DQ_IHARD;
188 if (src->dqb_valid & QIF_INODES)
189 dst->d_fieldmask |= FS_DQ_ICOUNT;
190 if (src->dqb_valid & QIF_BTIME)
191 dst->d_fieldmask |= FS_DQ_BTIMER;
192 if (src->dqb_valid & QIF_ITIME)
193 dst->d_fieldmask |= FS_DQ_ITIMER;
194}
195
170static int quota_setquota(struct super_block *sb, int type, qid_t id, 196static int quota_setquota(struct super_block *sb, int type, qid_t id,
171 void __user *addr) 197 void __user *addr)
172{ 198{
199 struct fs_disk_quota fdq;
173 struct if_dqblk idq; 200 struct if_dqblk idq;
174 201
175 if (copy_from_user(&idq, addr, sizeof(idq))) 202 if (copy_from_user(&idq, addr, sizeof(idq)))
176 return -EFAULT; 203 return -EFAULT;
177 if (!sb_has_quota_active(sb, type))
178 return -ESRCH;
179 if (!sb->s_qcop->set_dqblk) 204 if (!sb->s_qcop->set_dqblk)
180 return -ENOSYS; 205 return -ENOSYS;
181 return sb->s_qcop->set_dqblk(sb, type, id, &idq); 206 copy_from_if_dqblk(&fdq, &idq);
207 return sb->s_qcop->set_dqblk(sb, type, id, &fdq);
182} 208}
183 209
184static int quota_setxstate(struct super_block *sb, int cmd, void __user *addr) 210static 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,
212 238
213 if (copy_from_user(&fdq, addr, sizeof(fdq))) 239 if (copy_from_user(&fdq, addr, sizeof(fdq)))
214 return -EFAULT; 240 return -EFAULT;
215 if (!sb->s_qcop->set_xquota) 241 if (!sb->s_qcop->set_dqblk)
216 return -ENOSYS; 242 return -ENOSYS;
217 return sb->s_qcop->set_xquota(sb, type, id, &fdq); 243 return sb->s_qcop->set_dqblk(sb, type, id, &fdq);
218} 244}
219 245
220static int quota_getxquota(struct super_block *sb, int type, qid_t id, 246static int quota_getxquota(struct super_block *sb, int type, qid_t id,
diff --git a/fs/xfs/linux-2.6/xfs_quotaops.c b/fs/xfs/linux-2.6/xfs_quotaops.c
index 3d473f43c9a9..e31bf21fe5d3 100644
--- a/fs/xfs/linux-2.6/xfs_quotaops.c
+++ b/fs/xfs/linux-2.6/xfs_quotaops.c
@@ -114,7 +114,7 @@ xfs_fs_get_dqblk(
114} 114}
115 115
116STATIC int 116STATIC int
117xfs_fs_set_xquota( 117xfs_fs_set_dqblk(
118 struct super_block *sb, 118 struct super_block *sb,
119 int type, 119 int type,
120 qid_t id, 120 qid_t id,
@@ -136,5 +136,5 @@ const struct quotactl_ops xfs_quotactl_operations = {
136 .get_xstate = xfs_fs_get_xstate, 136 .get_xstate = xfs_fs_get_xstate,
137 .set_xstate = xfs_fs_set_xstate, 137 .set_xstate = xfs_fs_set_xstate,
138 .get_dqblk = xfs_fs_get_dqblk, 138 .get_dqblk = xfs_fs_get_dqblk,
139 .set_xquota = xfs_fs_set_xquota, 139 .set_dqblk = xfs_fs_set_dqblk,
140}; 140};
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index 26fa43140f2e..92b002f1805f 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -448,6 +448,9 @@ xfs_qm_scall_getqstat(
448 return 0; 448 return 0;
449} 449}
450 450
451#define XFS_DQ_MASK \
452 (FS_DQ_LIMIT_MASK | FS_DQ_TIMER_MASK | FS_DQ_WARNS_MASK)
453
451/* 454/*
452 * Adjust quota limits, and start/stop timers accordingly. 455 * Adjust quota limits, and start/stop timers accordingly.
453 */ 456 */
@@ -465,9 +468,10 @@ xfs_qm_scall_setqlim(
465 int error; 468 int error;
466 xfs_qcnt_t hard, soft; 469 xfs_qcnt_t hard, soft;
467 470
468 if ((newlim->d_fieldmask & 471 if (newlim->d_fieldmask & ~XFS_DQ_MASK)
469 (FS_DQ_LIMIT_MASK|FS_DQ_TIMER_MASK|FS_DQ_WARNS_MASK)) == 0) 472 return EINVAL;
470 return (0); 473 if ((newlim->d_fieldmask & XFS_DQ_MASK) == 0)
474 return 0;
471 475
472 tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SETQLIM); 476 tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SETQLIM);
473 if ((error = xfs_trans_reserve(tp, 0, sizeof(xfs_disk_dquot_t) + 128, 477 if ((error = xfs_trans_reserve(tp, 0, sizeof(xfs_disk_dquot_t) + 128,
diff --git a/include/linux/dqblk_xfs.h b/include/linux/dqblk_xfs.h
index 527504c11c5e..4389ae72024e 100644
--- a/include/linux/dqblk_xfs.h
+++ b/include/linux/dqblk_xfs.h
@@ -110,6 +110,15 @@ typedef struct fs_disk_quota {
110#define FS_DQ_WARNS_MASK (FS_DQ_BWARNS | FS_DQ_IWARNS | FS_DQ_RTBWARNS) 110#define FS_DQ_WARNS_MASK (FS_DQ_BWARNS | FS_DQ_IWARNS | FS_DQ_RTBWARNS)
111 111
112/* 112/*
113 * Accounting values. These can only be set for filesystem with
114 * non-transactional quotas that require quotacheck(8) in userspace.
115 */
116#define FS_DQ_BCOUNT (1<<12)
117#define FS_DQ_ICOUNT (1<<13)
118#define FS_DQ_RTBCOUNT (1<<14)
119#define FS_DQ_ACCT_MASK (FS_DQ_BCOUNT | FS_DQ_ICOUNT | FS_DQ_RTBCOUNT)
120
121/*
113 * Various flags related to quotactl(2). Only relevant to XFS filesystems. 122 * Various flags related to quotactl(2). Only relevant to XFS filesystems.
114 */ 123 */
115#define XFS_QUOTA_UDQ_ACCT (1<<0) /* user quota accounting */ 124#define XFS_QUOTA_UDQ_ACCT (1<<0) /* user quota accounting */
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 42364219dc9b..7126a15467f1 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -338,10 +338,9 @@ struct quotactl_ops {
338 int (*get_info)(struct super_block *, int, struct if_dqinfo *); 338 int (*get_info)(struct super_block *, int, struct if_dqinfo *);
339 int (*set_info)(struct super_block *, int, struct if_dqinfo *); 339 int (*set_info)(struct super_block *, int, struct if_dqinfo *);
340 int (*get_dqblk)(struct super_block *, int, qid_t, struct fs_disk_quota *); 340 int (*get_dqblk)(struct super_block *, int, qid_t, struct fs_disk_quota *);
341 int (*set_dqblk)(struct super_block *, int, qid_t, struct if_dqblk *); 341 int (*set_dqblk)(struct super_block *, int, qid_t, struct fs_disk_quota *);
342 int (*get_xstate)(struct super_block *, struct fs_quota_stat *); 342 int (*get_xstate)(struct super_block *, struct fs_quota_stat *);
343 int (*set_xstate)(struct super_block *, unsigned int, int); 343 int (*set_xstate)(struct super_block *, unsigned int, int);
344 int (*set_xquota)(struct super_block *, int, qid_t, struct fs_disk_quota *);
345}; 344};
346 345
347struct quota_format_type { 346struct quota_format_type {
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index d32a48631b0d..82c70c42d035 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -65,7 +65,8 @@ int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
65int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii); 65int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
66int vfs_get_dqblk(struct super_block *sb, int type, qid_t id, 66int vfs_get_dqblk(struct super_block *sb, int type, qid_t id,
67 struct fs_disk_quota *di); 67 struct fs_disk_quota *di);
68int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di); 68int vfs_set_dqblk(struct super_block *sb, int type, qid_t id,
69 struct fs_disk_quota *di);
69 70
70int dquot_transfer(struct inode *inode, struct iattr *iattr); 71int dquot_transfer(struct inode *inode, struct iattr *iattr);
71int vfs_dq_quota_on_remount(struct super_block *sb); 72int vfs_dq_quota_on_remount(struct super_block *sb);