aboutsummaryrefslogtreecommitdiffstats
path: root/fs
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 /fs
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>
Diffstat (limited to 'fs')
-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
5 files changed, 86 insertions, 37 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,