aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 dec93577a78..49667d68769 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 6aed77fc99c..b1a5036560a 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 8680e257c2b..d6ee49dda4f 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 3d473f43c9a..e31bf21fe5d 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 26fa43140f2..92b002f1805 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 527504c11c5..4389ae72024 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 42364219dc9..7126a15467f 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 d32a48631b0..82c70c42d03 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);