aboutsummaryrefslogtreecommitdiffstats
path: root/fs/quota/dquot.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2012-09-16 06:56:19 -0400
committerEric W. Biederman <ebiederm@xmission.com>2012-09-18 04:01:41 -0400
commit4c376dcae892e5b5daf8576c864061d076d4e4dc (patch)
treedbb4dbc9422992a00f7b478e4254b4da922f7158 /fs/quota/dquot.c
parentaca645a6a54e001e004f1f1e0eafd94f994bb1b3 (diff)
userns: Convert struct dquot dq_id to be a struct kqid
Change struct dquot dq_id to a struct kqid and remove the now unecessary dq_type. Make minimal changes to dquot, quota_tree, quota_v1, quota_v2, ext3, ext4, and ocfs2 to deal with the change in quota structures and signatures. The ocfs2 changes are larger than most because of the extensive tracing throughout the ocfs2 quota code that prints out dq_id. quota_tree.c:get_index is modified to take a struct kqid instead of a qid_t because all of it's callers pass in dquot->dq_id and it allows me to introduce only a single conversion. The rest of the changes are either just replacing dq_type with dq_id.type, adding conversions to deal with the change in type and occassionally adding qid_eq to allow quota id comparisons in a user namespace safe way. Cc: Mark Fasheh <mfasheh@suse.com> Cc: Joel Becker <jlbec@evilplan.org> Cc: Jan Kara <jack@suse.cz> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Andreas Dilger <adilger.kernel@dilger.ca> Cc: Theodore Tso <tytso@mit.edu> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Diffstat (limited to 'fs/quota/dquot.c')
-rw-r--r--fs/quota/dquot.c63
1 files changed, 32 insertions, 31 deletions
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 53e377a59b05..efaeed35476f 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -267,7 +267,7 @@ hashfn(const struct super_block *sb, unsigned int id, int type)
267static inline void insert_dquot_hash(struct dquot *dquot) 267static inline void insert_dquot_hash(struct dquot *dquot)
268{ 268{
269 struct hlist_head *head; 269 struct hlist_head *head;
270 head = dquot_hash + hashfn(dquot->dq_sb, dquot->dq_id, dquot->dq_type); 270 head = dquot_hash + hashfn(dquot->dq_sb, from_kqid(&init_user_ns, dquot->dq_id), dquot->dq_id.type);
271 hlist_add_head(&dquot->dq_hash, head); 271 hlist_add_head(&dquot->dq_hash, head);
272} 272}
273 273
@@ -279,13 +279,13 @@ static inline void remove_dquot_hash(struct dquot *dquot)
279static struct dquot *find_dquot(unsigned int hashent, struct super_block *sb, 279static struct dquot *find_dquot(unsigned int hashent, struct super_block *sb,
280 unsigned int id, int type) 280 unsigned int id, int type)
281{ 281{
282 struct kqid qid = make_kqid(&init_user_ns, type, id);
282 struct hlist_node *node; 283 struct hlist_node *node;
283 struct dquot *dquot; 284 struct dquot *dquot;
284 285
285 hlist_for_each (node, dquot_hash+hashent) { 286 hlist_for_each (node, dquot_hash+hashent) {
286 dquot = hlist_entry(node, struct dquot, dq_hash); 287 dquot = hlist_entry(node, struct dquot, dq_hash);
287 if (dquot->dq_sb == sb && dquot->dq_id == id && 288 if (dquot->dq_sb == sb && qid_eq(dquot->dq_id, qid))
288 dquot->dq_type == type)
289 return dquot; 289 return dquot;
290 } 290 }
291 return NULL; 291 return NULL;
@@ -351,7 +351,7 @@ int dquot_mark_dquot_dirty(struct dquot *dquot)
351 spin_lock(&dq_list_lock); 351 spin_lock(&dq_list_lock);
352 if (!test_and_set_bit(DQ_MOD_B, &dquot->dq_flags)) { 352 if (!test_and_set_bit(DQ_MOD_B, &dquot->dq_flags)) {
353 list_add(&dquot->dq_dirty, &sb_dqopt(dquot->dq_sb)-> 353 list_add(&dquot->dq_dirty, &sb_dqopt(dquot->dq_sb)->
354 info[dquot->dq_type].dqi_dirty_list); 354 info[dquot->dq_id.type].dqi_dirty_list);
355 ret = 0; 355 ret = 0;
356 } 356 }
357 spin_unlock(&dq_list_lock); 357 spin_unlock(&dq_list_lock);
@@ -410,17 +410,17 @@ int dquot_acquire(struct dquot *dquot)
410 mutex_lock(&dquot->dq_lock); 410 mutex_lock(&dquot->dq_lock);
411 mutex_lock(&dqopt->dqio_mutex); 411 mutex_lock(&dqopt->dqio_mutex);
412 if (!test_bit(DQ_READ_B, &dquot->dq_flags)) 412 if (!test_bit(DQ_READ_B, &dquot->dq_flags))
413 ret = dqopt->ops[dquot->dq_type]->read_dqblk(dquot); 413 ret = dqopt->ops[dquot->dq_id.type]->read_dqblk(dquot);
414 if (ret < 0) 414 if (ret < 0)
415 goto out_iolock; 415 goto out_iolock;
416 set_bit(DQ_READ_B, &dquot->dq_flags); 416 set_bit(DQ_READ_B, &dquot->dq_flags);
417 /* Instantiate dquot if needed */ 417 /* Instantiate dquot if needed */
418 if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && !dquot->dq_off) { 418 if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && !dquot->dq_off) {
419 ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot); 419 ret = dqopt->ops[dquot->dq_id.type]->commit_dqblk(dquot);
420 /* Write the info if needed */ 420 /* Write the info if needed */
421 if (info_dirty(&dqopt->info[dquot->dq_type])) { 421 if (info_dirty(&dqopt->info[dquot->dq_id.type])) {
422 ret2 = dqopt->ops[dquot->dq_type]->write_file_info( 422 ret2 = dqopt->ops[dquot->dq_id.type]->write_file_info(
423 dquot->dq_sb, dquot->dq_type); 423 dquot->dq_sb, dquot->dq_id.type);
424 } 424 }
425 if (ret < 0) 425 if (ret < 0)
426 goto out_iolock; 426 goto out_iolock;
@@ -455,7 +455,7 @@ int dquot_commit(struct dquot *dquot)
455 /* Inactive dquot can be only if there was error during read/init 455 /* Inactive dquot can be only if there was error during read/init
456 * => we have better not writing it */ 456 * => we have better not writing it */
457 if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) 457 if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags))
458 ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot); 458 ret = dqopt->ops[dquot->dq_id.type]->commit_dqblk(dquot);
459 else 459 else
460 ret = -EIO; 460 ret = -EIO;
461out_sem: 461out_sem:
@@ -477,12 +477,12 @@ int dquot_release(struct dquot *dquot)
477 if (atomic_read(&dquot->dq_count) > 1) 477 if (atomic_read(&dquot->dq_count) > 1)
478 goto out_dqlock; 478 goto out_dqlock;
479 mutex_lock(&dqopt->dqio_mutex); 479 mutex_lock(&dqopt->dqio_mutex);
480 if (dqopt->ops[dquot->dq_type]->release_dqblk) { 480 if (dqopt->ops[dquot->dq_id.type]->release_dqblk) {
481 ret = dqopt->ops[dquot->dq_type]->release_dqblk(dquot); 481 ret = dqopt->ops[dquot->dq_id.type]->release_dqblk(dquot);
482 /* Write the info */ 482 /* Write the info */
483 if (info_dirty(&dqopt->info[dquot->dq_type])) { 483 if (info_dirty(&dqopt->info[dquot->dq_id.type])) {
484 ret2 = dqopt->ops[dquot->dq_type]->write_file_info( 484 ret2 = dqopt->ops[dquot->dq_id.type]->write_file_info(
485 dquot->dq_sb, dquot->dq_type); 485 dquot->dq_sb, dquot->dq_id.type);
486 } 486 }
487 if (ret >= 0) 487 if (ret >= 0)
488 ret = ret2; 488 ret = ret2;
@@ -521,7 +521,7 @@ restart:
521 list_for_each_entry_safe(dquot, tmp, &inuse_list, dq_inuse) { 521 list_for_each_entry_safe(dquot, tmp, &inuse_list, dq_inuse) {
522 if (dquot->dq_sb != sb) 522 if (dquot->dq_sb != sb)
523 continue; 523 continue;
524 if (dquot->dq_type != type) 524 if (dquot->dq_id.type != type)
525 continue; 525 continue;
526 /* Wait for dquot users */ 526 /* Wait for dquot users */
527 if (atomic_read(&dquot->dq_count)) { 527 if (atomic_read(&dquot->dq_count)) {
@@ -741,7 +741,8 @@ void dqput(struct dquot *dquot)
741#ifdef CONFIG_QUOTA_DEBUG 741#ifdef CONFIG_QUOTA_DEBUG
742 if (!atomic_read(&dquot->dq_count)) { 742 if (!atomic_read(&dquot->dq_count)) {
743 quota_error(dquot->dq_sb, "trying to free free dquot of %s %d", 743 quota_error(dquot->dq_sb, "trying to free free dquot of %s %d",
744 quotatypes[dquot->dq_type], dquot->dq_id); 744 quotatypes[dquot->dq_id.type],
745 from_kqid(&init_user_ns, dquot->dq_id));
745 BUG(); 746 BUG();
746 } 747 }
747#endif 748#endif
@@ -752,7 +753,7 @@ we_slept:
752 /* We have more than one user... nothing to do */ 753 /* We have more than one user... nothing to do */
753 atomic_dec(&dquot->dq_count); 754 atomic_dec(&dquot->dq_count);
754 /* Releasing dquot during quotaoff phase? */ 755 /* Releasing dquot during quotaoff phase? */
755 if (!sb_has_quota_active(dquot->dq_sb, dquot->dq_type) && 756 if (!sb_has_quota_active(dquot->dq_sb, dquot->dq_id.type) &&
756 atomic_read(&dquot->dq_count) == 1) 757 atomic_read(&dquot->dq_count) == 1)
757 wake_up(&dquot->dq_wait_unused); 758 wake_up(&dquot->dq_wait_unused);
758 spin_unlock(&dq_list_lock); 759 spin_unlock(&dq_list_lock);
@@ -815,7 +816,7 @@ static struct dquot *get_empty_dquot(struct super_block *sb, int type)
815 INIT_LIST_HEAD(&dquot->dq_dirty); 816 INIT_LIST_HEAD(&dquot->dq_dirty);
816 init_waitqueue_head(&dquot->dq_wait_unused); 817 init_waitqueue_head(&dquot->dq_wait_unused);
817 dquot->dq_sb = sb; 818 dquot->dq_sb = sb;
818 dquot->dq_type = type; 819 dquot->dq_id.type = type;
819 atomic_set(&dquot->dq_count, 1); 820 atomic_set(&dquot->dq_count, 1);
820 821
821 return dquot; 822 return dquot;
@@ -859,7 +860,7 @@ we_slept:
859 } 860 }
860 dquot = empty; 861 dquot = empty;
861 empty = NULL; 862 empty = NULL;
862 dquot->dq_id = id; 863 dquot->dq_id = qid;
863 /* all dquots go on the inuse_list */ 864 /* all dquots go on the inuse_list */
864 put_inuse(dquot); 865 put_inuse(dquot);
865 /* hash it first so it can be found */ 866 /* hash it first so it can be found */
@@ -1219,8 +1220,8 @@ static void prepare_warning(struct dquot_warn *warn, struct dquot *dquot,
1219 return; 1220 return;
1220 warn->w_type = warntype; 1221 warn->w_type = warntype;
1221 warn->w_sb = dquot->dq_sb; 1222 warn->w_sb = dquot->dq_sb;
1222 warn->w_dq_id = dquot->dq_id; 1223 warn->w_dq_id = from_kqid(&init_user_ns, dquot->dq_id);
1223 warn->w_dq_type = dquot->dq_type; 1224 warn->w_dq_type = dquot->dq_id.type;
1224} 1225}
1225 1226
1226/* 1227/*
@@ -1245,7 +1246,7 @@ static void flush_warnings(struct dquot_warn *warn)
1245 1246
1246static int ignore_hardlimit(struct dquot *dquot) 1247static int ignore_hardlimit(struct dquot *dquot)
1247{ 1248{
1248 struct mem_dqinfo *info = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_type]; 1249 struct mem_dqinfo *info = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_id.type];
1249 1250
1250 return capable(CAP_SYS_RESOURCE) && 1251 return capable(CAP_SYS_RESOURCE) &&
1251 (info->dqi_format->qf_fmt_id != QFMT_VFS_OLD || 1252 (info->dqi_format->qf_fmt_id != QFMT_VFS_OLD ||
@@ -1258,7 +1259,7 @@ static int check_idq(struct dquot *dquot, qsize_t inodes,
1258{ 1259{
1259 qsize_t newinodes = dquot->dq_dqb.dqb_curinodes + inodes; 1260 qsize_t newinodes = dquot->dq_dqb.dqb_curinodes + inodes;
1260 1261
1261 if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type) || 1262 if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_id.type) ||
1262 test_bit(DQ_FAKE_B, &dquot->dq_flags)) 1263 test_bit(DQ_FAKE_B, &dquot->dq_flags))
1263 return 0; 1264 return 0;
1264 1265
@@ -1283,7 +1284,7 @@ static int check_idq(struct dquot *dquot, qsize_t inodes,
1283 dquot->dq_dqb.dqb_itime == 0) { 1284 dquot->dq_dqb.dqb_itime == 0) {
1284 prepare_warning(warn, dquot, QUOTA_NL_ISOFTWARN); 1285 prepare_warning(warn, dquot, QUOTA_NL_ISOFTWARN);
1285 dquot->dq_dqb.dqb_itime = get_seconds() + 1286 dquot->dq_dqb.dqb_itime = get_seconds() +
1286 sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_igrace; 1287 sb_dqopt(dquot->dq_sb)->info[dquot->dq_id.type].dqi_igrace;
1287 } 1288 }
1288 1289
1289 return 0; 1290 return 0;
@@ -1296,7 +1297,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc,
1296 qsize_t tspace; 1297 qsize_t tspace;
1297 struct super_block *sb = dquot->dq_sb; 1298 struct super_block *sb = dquot->dq_sb;
1298 1299
1299 if (!sb_has_quota_limits_enabled(sb, dquot->dq_type) || 1300 if (!sb_has_quota_limits_enabled(sb, dquot->dq_id.type) ||
1300 test_bit(DQ_FAKE_B, &dquot->dq_flags)) 1301 test_bit(DQ_FAKE_B, &dquot->dq_flags))
1301 return 0; 1302 return 0;
1302 1303
@@ -1327,7 +1328,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc,
1327 if (!prealloc) { 1328 if (!prealloc) {
1328 prepare_warning(warn, dquot, QUOTA_NL_BSOFTWARN); 1329 prepare_warning(warn, dquot, QUOTA_NL_BSOFTWARN);
1329 dquot->dq_dqb.dqb_btime = get_seconds() + 1330 dquot->dq_dqb.dqb_btime = get_seconds() +
1330 sb_dqopt(sb)->info[dquot->dq_type].dqi_bgrace; 1331 sb_dqopt(sb)->info[dquot->dq_id.type].dqi_bgrace;
1331 } 1332 }
1332 else 1333 else
1333 /* 1334 /*
@@ -1346,7 +1347,7 @@ static int info_idq_free(struct dquot *dquot, qsize_t inodes)
1346 1347
1347 if (test_bit(DQ_FAKE_B, &dquot->dq_flags) || 1348 if (test_bit(DQ_FAKE_B, &dquot->dq_flags) ||
1348 dquot->dq_dqb.dqb_curinodes <= dquot->dq_dqb.dqb_isoftlimit || 1349 dquot->dq_dqb.dqb_curinodes <= dquot->dq_dqb.dqb_isoftlimit ||
1349 !sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type)) 1350 !sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_id.type))
1350 return QUOTA_NL_NOWARN; 1351 return QUOTA_NL_NOWARN;
1351 1352
1352 newinodes = dquot->dq_dqb.dqb_curinodes - inodes; 1353 newinodes = dquot->dq_dqb.dqb_curinodes - inodes;
@@ -2362,9 +2363,9 @@ static void do_get_dqblk(struct dquot *dquot, struct fs_disk_quota *di)
2362 2363
2363 memset(di, 0, sizeof(*di)); 2364 memset(di, 0, sizeof(*di));
2364 di->d_version = FS_DQUOT_VERSION; 2365 di->d_version = FS_DQUOT_VERSION;
2365 di->d_flags = dquot->dq_type == USRQUOTA ? 2366 di->d_flags = dquot->dq_id.type == USRQUOTA ?
2366 FS_USER_QUOTA : FS_GROUP_QUOTA; 2367 FS_USER_QUOTA : FS_GROUP_QUOTA;
2367 di->d_id = dquot->dq_id; 2368 di->d_id = from_kqid_munged(current_user_ns(), dquot->dq_id);
2368 2369
2369 spin_lock(&dq_data_lock); 2370 spin_lock(&dq_data_lock);
2370 di->d_blk_hardlimit = stoqb(dm->dqb_bhardlimit); 2371 di->d_blk_hardlimit = stoqb(dm->dqb_bhardlimit);
@@ -2403,7 +2404,7 @@ static int do_set_dqblk(struct dquot *dquot, struct fs_disk_quota *di)
2403{ 2404{
2404 struct mem_dqblk *dm = &dquot->dq_dqb; 2405 struct mem_dqblk *dm = &dquot->dq_dqb;
2405 int check_blim = 0, check_ilim = 0; 2406 int check_blim = 0, check_ilim = 0;
2406 struct mem_dqinfo *dqi = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_type]; 2407 struct mem_dqinfo *dqi = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_id.type];
2407 2408
2408 if (di->d_fieldmask & ~VFS_FS_DQ_MASK) 2409 if (di->d_fieldmask & ~VFS_FS_DQ_MASK)
2409 return -EINVAL; 2410 return -EINVAL;