diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2012-09-16 06:56:19 -0400 |
---|---|---|
committer | Eric W. Biederman <ebiederm@xmission.com> | 2012-09-18 04:01:41 -0400 |
commit | 4c376dcae892e5b5daf8576c864061d076d4e4dc (patch) | |
tree | dbb4dbc9422992a00f7b478e4254b4da922f7158 /fs/quota/dquot.c | |
parent | aca645a6a54e001e004f1f1e0eafd94f994bb1b3 (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.c | 63 |
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) | |||
267 | static inline void insert_dquot_hash(struct dquot *dquot) | 267 | static 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) | |||
279 | static struct dquot *find_dquot(unsigned int hashent, struct super_block *sb, | 279 | static 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; |
461 | out_sem: | 461 | out_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 | ||
1246 | static int ignore_hardlimit(struct dquot *dquot) | 1247 | static 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; |