diff options
Diffstat (limited to 'fs/quota')
-rw-r--r-- | fs/quota/Makefile | 2 | ||||
-rw-r--r-- | fs/quota/dquot.c | 114 | ||||
-rw-r--r-- | fs/quota/kqid.c | 132 | ||||
-rw-r--r-- | fs/quota/netlink.c | 10 | ||||
-rw-r--r-- | fs/quota/quota.c | 28 | ||||
-rw-r--r-- | fs/quota/quota_tree.c | 22 | ||||
-rw-r--r-- | fs/quota/quota_v1.c | 12 | ||||
-rw-r--r-- | fs/quota/quota_v2.c | 26 |
8 files changed, 253 insertions, 93 deletions
diff --git a/fs/quota/Makefile b/fs/quota/Makefile index 5f9e9e276af0..c66c37cdaa39 100644 --- a/fs/quota/Makefile +++ b/fs/quota/Makefile | |||
@@ -2,6 +2,6 @@ obj-$(CONFIG_QUOTA) += dquot.o | |||
2 | obj-$(CONFIG_QFMT_V1) += quota_v1.o | 2 | obj-$(CONFIG_QFMT_V1) += quota_v1.o |
3 | obj-$(CONFIG_QFMT_V2) += quota_v2.o | 3 | obj-$(CONFIG_QFMT_V2) += quota_v2.o |
4 | obj-$(CONFIG_QUOTA_TREE) += quota_tree.o | 4 | obj-$(CONFIG_QUOTA_TREE) += quota_tree.o |
5 | obj-$(CONFIG_QUOTACTL) += quota.o | 5 | obj-$(CONFIG_QUOTACTL) += quota.o kqid.o |
6 | obj-$(CONFIG_QUOTACTL_COMPAT) += compat.o | 6 | obj-$(CONFIG_QUOTACTL_COMPAT) += compat.o |
7 | obj-$(CONFIG_QUOTA_NETLINK_INTERFACE) += netlink.o | 7 | obj-$(CONFIG_QUOTA_NETLINK_INTERFACE) += netlink.o |
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index c495a3055e2a..557a9c20a215 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c | |||
@@ -253,8 +253,10 @@ static qsize_t inode_get_rsv_space(struct inode *inode); | |||
253 | static void __dquot_initialize(struct inode *inode, int type); | 253 | static void __dquot_initialize(struct inode *inode, int type); |
254 | 254 | ||
255 | static inline unsigned int | 255 | static inline unsigned int |
256 | hashfn(const struct super_block *sb, unsigned int id, int type) | 256 | hashfn(const struct super_block *sb, struct kqid qid) |
257 | { | 257 | { |
258 | unsigned int id = from_kqid(&init_user_ns, qid); | ||
259 | int type = qid.type; | ||
258 | unsigned long tmp; | 260 | unsigned long tmp; |
259 | 261 | ||
260 | tmp = (((unsigned long)sb>>L1_CACHE_SHIFT) ^ id) * (MAXQUOTAS - type); | 262 | tmp = (((unsigned long)sb>>L1_CACHE_SHIFT) ^ id) * (MAXQUOTAS - type); |
@@ -267,7 +269,7 @@ hashfn(const struct super_block *sb, unsigned int id, int type) | |||
267 | static inline void insert_dquot_hash(struct dquot *dquot) | 269 | static inline void insert_dquot_hash(struct dquot *dquot) |
268 | { | 270 | { |
269 | struct hlist_head *head; | 271 | struct hlist_head *head; |
270 | head = dquot_hash + hashfn(dquot->dq_sb, dquot->dq_id, dquot->dq_type); | 272 | head = dquot_hash + hashfn(dquot->dq_sb, dquot->dq_id); |
271 | hlist_add_head(&dquot->dq_hash, head); | 273 | hlist_add_head(&dquot->dq_hash, head); |
272 | } | 274 | } |
273 | 275 | ||
@@ -277,15 +279,14 @@ static inline void remove_dquot_hash(struct dquot *dquot) | |||
277 | } | 279 | } |
278 | 280 | ||
279 | static struct dquot *find_dquot(unsigned int hashent, struct super_block *sb, | 281 | static struct dquot *find_dquot(unsigned int hashent, struct super_block *sb, |
280 | unsigned int id, int type) | 282 | struct kqid qid) |
281 | { | 283 | { |
282 | struct hlist_node *node; | 284 | struct hlist_node *node; |
283 | struct dquot *dquot; | 285 | struct dquot *dquot; |
284 | 286 | ||
285 | hlist_for_each (node, dquot_hash+hashent) { | 287 | hlist_for_each (node, dquot_hash+hashent) { |
286 | dquot = hlist_entry(node, struct dquot, dq_hash); | 288 | dquot = hlist_entry(node, struct dquot, dq_hash); |
287 | if (dquot->dq_sb == sb && dquot->dq_id == id && | 289 | if (dquot->dq_sb == sb && qid_eq(dquot->dq_id, qid)) |
288 | dquot->dq_type == type) | ||
289 | return dquot; | 290 | return dquot; |
290 | } | 291 | } |
291 | return NULL; | 292 | return NULL; |
@@ -351,7 +352,7 @@ int dquot_mark_dquot_dirty(struct dquot *dquot) | |||
351 | spin_lock(&dq_list_lock); | 352 | spin_lock(&dq_list_lock); |
352 | if (!test_and_set_bit(DQ_MOD_B, &dquot->dq_flags)) { | 353 | if (!test_and_set_bit(DQ_MOD_B, &dquot->dq_flags)) { |
353 | list_add(&dquot->dq_dirty, &sb_dqopt(dquot->dq_sb)-> | 354 | list_add(&dquot->dq_dirty, &sb_dqopt(dquot->dq_sb)-> |
354 | info[dquot->dq_type].dqi_dirty_list); | 355 | info[dquot->dq_id.type].dqi_dirty_list); |
355 | ret = 0; | 356 | ret = 0; |
356 | } | 357 | } |
357 | spin_unlock(&dq_list_lock); | 358 | spin_unlock(&dq_list_lock); |
@@ -410,17 +411,17 @@ int dquot_acquire(struct dquot *dquot) | |||
410 | mutex_lock(&dquot->dq_lock); | 411 | mutex_lock(&dquot->dq_lock); |
411 | mutex_lock(&dqopt->dqio_mutex); | 412 | mutex_lock(&dqopt->dqio_mutex); |
412 | if (!test_bit(DQ_READ_B, &dquot->dq_flags)) | 413 | if (!test_bit(DQ_READ_B, &dquot->dq_flags)) |
413 | ret = dqopt->ops[dquot->dq_type]->read_dqblk(dquot); | 414 | ret = dqopt->ops[dquot->dq_id.type]->read_dqblk(dquot); |
414 | if (ret < 0) | 415 | if (ret < 0) |
415 | goto out_iolock; | 416 | goto out_iolock; |
416 | set_bit(DQ_READ_B, &dquot->dq_flags); | 417 | set_bit(DQ_READ_B, &dquot->dq_flags); |
417 | /* Instantiate dquot if needed */ | 418 | /* Instantiate dquot if needed */ |
418 | if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && !dquot->dq_off) { | 419 | if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && !dquot->dq_off) { |
419 | ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot); | 420 | ret = dqopt->ops[dquot->dq_id.type]->commit_dqblk(dquot); |
420 | /* Write the info if needed */ | 421 | /* Write the info if needed */ |
421 | if (info_dirty(&dqopt->info[dquot->dq_type])) { | 422 | if (info_dirty(&dqopt->info[dquot->dq_id.type])) { |
422 | ret2 = dqopt->ops[dquot->dq_type]->write_file_info( | 423 | ret2 = dqopt->ops[dquot->dq_id.type]->write_file_info( |
423 | dquot->dq_sb, dquot->dq_type); | 424 | dquot->dq_sb, dquot->dq_id.type); |
424 | } | 425 | } |
425 | if (ret < 0) | 426 | if (ret < 0) |
426 | goto out_iolock; | 427 | goto out_iolock; |
@@ -455,7 +456,7 @@ int dquot_commit(struct dquot *dquot) | |||
455 | /* Inactive dquot can be only if there was error during read/init | 456 | /* Inactive dquot can be only if there was error during read/init |
456 | * => we have better not writing it */ | 457 | * => we have better not writing it */ |
457 | if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) | 458 | if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) |
458 | ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot); | 459 | ret = dqopt->ops[dquot->dq_id.type]->commit_dqblk(dquot); |
459 | else | 460 | else |
460 | ret = -EIO; | 461 | ret = -EIO; |
461 | out_sem: | 462 | out_sem: |
@@ -477,12 +478,12 @@ int dquot_release(struct dquot *dquot) | |||
477 | if (atomic_read(&dquot->dq_count) > 1) | 478 | if (atomic_read(&dquot->dq_count) > 1) |
478 | goto out_dqlock; | 479 | goto out_dqlock; |
479 | mutex_lock(&dqopt->dqio_mutex); | 480 | mutex_lock(&dqopt->dqio_mutex); |
480 | if (dqopt->ops[dquot->dq_type]->release_dqblk) { | 481 | if (dqopt->ops[dquot->dq_id.type]->release_dqblk) { |
481 | ret = dqopt->ops[dquot->dq_type]->release_dqblk(dquot); | 482 | ret = dqopt->ops[dquot->dq_id.type]->release_dqblk(dquot); |
482 | /* Write the info */ | 483 | /* Write the info */ |
483 | if (info_dirty(&dqopt->info[dquot->dq_type])) { | 484 | if (info_dirty(&dqopt->info[dquot->dq_id.type])) { |
484 | ret2 = dqopt->ops[dquot->dq_type]->write_file_info( | 485 | ret2 = dqopt->ops[dquot->dq_id.type]->write_file_info( |
485 | dquot->dq_sb, dquot->dq_type); | 486 | dquot->dq_sb, dquot->dq_id.type); |
486 | } | 487 | } |
487 | if (ret >= 0) | 488 | if (ret >= 0) |
488 | ret = ret2; | 489 | ret = ret2; |
@@ -521,7 +522,7 @@ restart: | |||
521 | list_for_each_entry_safe(dquot, tmp, &inuse_list, dq_inuse) { | 522 | list_for_each_entry_safe(dquot, tmp, &inuse_list, dq_inuse) { |
522 | if (dquot->dq_sb != sb) | 523 | if (dquot->dq_sb != sb) |
523 | continue; | 524 | continue; |
524 | if (dquot->dq_type != type) | 525 | if (dquot->dq_id.type != type) |
525 | continue; | 526 | continue; |
526 | /* Wait for dquot users */ | 527 | /* Wait for dquot users */ |
527 | if (atomic_read(&dquot->dq_count)) { | 528 | if (atomic_read(&dquot->dq_count)) { |
@@ -741,7 +742,8 @@ void dqput(struct dquot *dquot) | |||
741 | #ifdef CONFIG_QUOTA_DEBUG | 742 | #ifdef CONFIG_QUOTA_DEBUG |
742 | if (!atomic_read(&dquot->dq_count)) { | 743 | if (!atomic_read(&dquot->dq_count)) { |
743 | quota_error(dquot->dq_sb, "trying to free free dquot of %s %d", | 744 | quota_error(dquot->dq_sb, "trying to free free dquot of %s %d", |
744 | quotatypes[dquot->dq_type], dquot->dq_id); | 745 | quotatypes[dquot->dq_id.type], |
746 | from_kqid(&init_user_ns, dquot->dq_id)); | ||
745 | BUG(); | 747 | BUG(); |
746 | } | 748 | } |
747 | #endif | 749 | #endif |
@@ -752,7 +754,7 @@ we_slept: | |||
752 | /* We have more than one user... nothing to do */ | 754 | /* We have more than one user... nothing to do */ |
753 | atomic_dec(&dquot->dq_count); | 755 | atomic_dec(&dquot->dq_count); |
754 | /* Releasing dquot during quotaoff phase? */ | 756 | /* Releasing dquot during quotaoff phase? */ |
755 | if (!sb_has_quota_active(dquot->dq_sb, dquot->dq_type) && | 757 | if (!sb_has_quota_active(dquot->dq_sb, dquot->dq_id.type) && |
756 | atomic_read(&dquot->dq_count) == 1) | 758 | atomic_read(&dquot->dq_count) == 1) |
757 | wake_up(&dquot->dq_wait_unused); | 759 | wake_up(&dquot->dq_wait_unused); |
758 | spin_unlock(&dq_list_lock); | 760 | spin_unlock(&dq_list_lock); |
@@ -815,7 +817,7 @@ static struct dquot *get_empty_dquot(struct super_block *sb, int type) | |||
815 | INIT_LIST_HEAD(&dquot->dq_dirty); | 817 | INIT_LIST_HEAD(&dquot->dq_dirty); |
816 | init_waitqueue_head(&dquot->dq_wait_unused); | 818 | init_waitqueue_head(&dquot->dq_wait_unused); |
817 | dquot->dq_sb = sb; | 819 | dquot->dq_sb = sb; |
818 | dquot->dq_type = type; | 820 | dquot->dq_id = make_kqid_invalid(type); |
819 | atomic_set(&dquot->dq_count, 1); | 821 | atomic_set(&dquot->dq_count, 1); |
820 | 822 | ||
821 | return dquot; | 823 | return dquot; |
@@ -829,35 +831,35 @@ static struct dquot *get_empty_dquot(struct super_block *sb, int type) | |||
829 | * a) checking for quota flags under dq_list_lock and | 831 | * a) checking for quota flags under dq_list_lock and |
830 | * b) getting a reference to dquot before we release dq_list_lock | 832 | * b) getting a reference to dquot before we release dq_list_lock |
831 | */ | 833 | */ |
832 | struct dquot *dqget(struct super_block *sb, unsigned int id, int type) | 834 | struct dquot *dqget(struct super_block *sb, struct kqid qid) |
833 | { | 835 | { |
834 | unsigned int hashent = hashfn(sb, id, type); | 836 | unsigned int hashent = hashfn(sb, qid); |
835 | struct dquot *dquot = NULL, *empty = NULL; | 837 | struct dquot *dquot = NULL, *empty = NULL; |
836 | 838 | ||
837 | if (!sb_has_quota_active(sb, type)) | 839 | if (!sb_has_quota_active(sb, qid.type)) |
838 | return NULL; | 840 | return NULL; |
839 | we_slept: | 841 | we_slept: |
840 | spin_lock(&dq_list_lock); | 842 | spin_lock(&dq_list_lock); |
841 | spin_lock(&dq_state_lock); | 843 | spin_lock(&dq_state_lock); |
842 | if (!sb_has_quota_active(sb, type)) { | 844 | if (!sb_has_quota_active(sb, qid.type)) { |
843 | spin_unlock(&dq_state_lock); | 845 | spin_unlock(&dq_state_lock); |
844 | spin_unlock(&dq_list_lock); | 846 | spin_unlock(&dq_list_lock); |
845 | goto out; | 847 | goto out; |
846 | } | 848 | } |
847 | spin_unlock(&dq_state_lock); | 849 | spin_unlock(&dq_state_lock); |
848 | 850 | ||
849 | dquot = find_dquot(hashent, sb, id, type); | 851 | dquot = find_dquot(hashent, sb, qid); |
850 | if (!dquot) { | 852 | if (!dquot) { |
851 | if (!empty) { | 853 | if (!empty) { |
852 | spin_unlock(&dq_list_lock); | 854 | spin_unlock(&dq_list_lock); |
853 | empty = get_empty_dquot(sb, type); | 855 | empty = get_empty_dquot(sb, qid.type); |
854 | if (!empty) | 856 | if (!empty) |
855 | schedule(); /* Try to wait for a moment... */ | 857 | schedule(); /* Try to wait for a moment... */ |
856 | goto we_slept; | 858 | goto we_slept; |
857 | } | 859 | } |
858 | dquot = empty; | 860 | dquot = empty; |
859 | empty = NULL; | 861 | empty = NULL; |
860 | dquot->dq_id = id; | 862 | dquot->dq_id = qid; |
861 | /* all dquots go on the inuse_list */ | 863 | /* all dquots go on the inuse_list */ |
862 | put_inuse(dquot); | 864 | put_inuse(dquot); |
863 | /* hash it first so it can be found */ | 865 | /* hash it first so it can be found */ |
@@ -1129,8 +1131,7 @@ static void dquot_decr_space(struct dquot *dquot, qsize_t number) | |||
1129 | 1131 | ||
1130 | struct dquot_warn { | 1132 | struct dquot_warn { |
1131 | struct super_block *w_sb; | 1133 | struct super_block *w_sb; |
1132 | qid_t w_dq_id; | 1134 | struct kqid w_dq_id; |
1133 | short w_dq_type; | ||
1134 | short w_type; | 1135 | short w_type; |
1135 | }; | 1136 | }; |
1136 | 1137 | ||
@@ -1154,11 +1155,11 @@ static int need_print_warning(struct dquot_warn *warn) | |||
1154 | if (!flag_print_warnings) | 1155 | if (!flag_print_warnings) |
1155 | return 0; | 1156 | return 0; |
1156 | 1157 | ||
1157 | switch (warn->w_dq_type) { | 1158 | switch (warn->w_dq_id.type) { |
1158 | case USRQUOTA: | 1159 | case USRQUOTA: |
1159 | return current_fsuid() == warn->w_dq_id; | 1160 | return uid_eq(current_fsuid(), warn->w_dq_id.uid); |
1160 | case GRPQUOTA: | 1161 | case GRPQUOTA: |
1161 | return in_group_p(warn->w_dq_id); | 1162 | return in_group_p(warn->w_dq_id.gid); |
1162 | } | 1163 | } |
1163 | return 0; | 1164 | return 0; |
1164 | } | 1165 | } |
@@ -1184,7 +1185,7 @@ static void print_warning(struct dquot_warn *warn) | |||
1184 | tty_write_message(tty, ": warning, "); | 1185 | tty_write_message(tty, ": warning, "); |
1185 | else | 1186 | else |
1186 | tty_write_message(tty, ": write failed, "); | 1187 | tty_write_message(tty, ": write failed, "); |
1187 | tty_write_message(tty, quotatypes[warn->w_dq_type]); | 1188 | tty_write_message(tty, quotatypes[warn->w_dq_id.type]); |
1188 | switch (warntype) { | 1189 | switch (warntype) { |
1189 | case QUOTA_NL_IHARDWARN: | 1190 | case QUOTA_NL_IHARDWARN: |
1190 | msg = " file limit reached.\r\n"; | 1191 | msg = " file limit reached.\r\n"; |
@@ -1218,7 +1219,6 @@ static void prepare_warning(struct dquot_warn *warn, struct dquot *dquot, | |||
1218 | warn->w_type = warntype; | 1219 | warn->w_type = warntype; |
1219 | warn->w_sb = dquot->dq_sb; | 1220 | warn->w_sb = dquot->dq_sb; |
1220 | warn->w_dq_id = dquot->dq_id; | 1221 | warn->w_dq_id = dquot->dq_id; |
1221 | warn->w_dq_type = dquot->dq_type; | ||
1222 | } | 1222 | } |
1223 | 1223 | ||
1224 | /* | 1224 | /* |
@@ -1236,14 +1236,14 @@ static void flush_warnings(struct dquot_warn *warn) | |||
1236 | #ifdef CONFIG_PRINT_QUOTA_WARNING | 1236 | #ifdef CONFIG_PRINT_QUOTA_WARNING |
1237 | print_warning(&warn[i]); | 1237 | print_warning(&warn[i]); |
1238 | #endif | 1238 | #endif |
1239 | quota_send_warning(warn[i].w_dq_type, warn[i].w_dq_id, | 1239 | quota_send_warning(warn[i].w_dq_id, |
1240 | warn[i].w_sb->s_dev, warn[i].w_type); | 1240 | warn[i].w_sb->s_dev, warn[i].w_type); |
1241 | } | 1241 | } |
1242 | } | 1242 | } |
1243 | 1243 | ||
1244 | static int ignore_hardlimit(struct dquot *dquot) | 1244 | static int ignore_hardlimit(struct dquot *dquot) |
1245 | { | 1245 | { |
1246 | struct mem_dqinfo *info = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_type]; | 1246 | struct mem_dqinfo *info = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_id.type]; |
1247 | 1247 | ||
1248 | return capable(CAP_SYS_RESOURCE) && | 1248 | return capable(CAP_SYS_RESOURCE) && |
1249 | (info->dqi_format->qf_fmt_id != QFMT_VFS_OLD || | 1249 | (info->dqi_format->qf_fmt_id != QFMT_VFS_OLD || |
@@ -1256,7 +1256,7 @@ static int check_idq(struct dquot *dquot, qsize_t inodes, | |||
1256 | { | 1256 | { |
1257 | qsize_t newinodes = dquot->dq_dqb.dqb_curinodes + inodes; | 1257 | qsize_t newinodes = dquot->dq_dqb.dqb_curinodes + inodes; |
1258 | 1258 | ||
1259 | if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type) || | 1259 | if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_id.type) || |
1260 | test_bit(DQ_FAKE_B, &dquot->dq_flags)) | 1260 | test_bit(DQ_FAKE_B, &dquot->dq_flags)) |
1261 | return 0; | 1261 | return 0; |
1262 | 1262 | ||
@@ -1281,7 +1281,7 @@ static int check_idq(struct dquot *dquot, qsize_t inodes, | |||
1281 | dquot->dq_dqb.dqb_itime == 0) { | 1281 | dquot->dq_dqb.dqb_itime == 0) { |
1282 | prepare_warning(warn, dquot, QUOTA_NL_ISOFTWARN); | 1282 | prepare_warning(warn, dquot, QUOTA_NL_ISOFTWARN); |
1283 | dquot->dq_dqb.dqb_itime = get_seconds() + | 1283 | dquot->dq_dqb.dqb_itime = get_seconds() + |
1284 | sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_igrace; | 1284 | sb_dqopt(dquot->dq_sb)->info[dquot->dq_id.type].dqi_igrace; |
1285 | } | 1285 | } |
1286 | 1286 | ||
1287 | return 0; | 1287 | return 0; |
@@ -1294,7 +1294,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, | |||
1294 | qsize_t tspace; | 1294 | qsize_t tspace; |
1295 | struct super_block *sb = dquot->dq_sb; | 1295 | struct super_block *sb = dquot->dq_sb; |
1296 | 1296 | ||
1297 | if (!sb_has_quota_limits_enabled(sb, dquot->dq_type) || | 1297 | if (!sb_has_quota_limits_enabled(sb, dquot->dq_id.type) || |
1298 | test_bit(DQ_FAKE_B, &dquot->dq_flags)) | 1298 | test_bit(DQ_FAKE_B, &dquot->dq_flags)) |
1299 | return 0; | 1299 | return 0; |
1300 | 1300 | ||
@@ -1325,7 +1325,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, | |||
1325 | if (!prealloc) { | 1325 | if (!prealloc) { |
1326 | prepare_warning(warn, dquot, QUOTA_NL_BSOFTWARN); | 1326 | prepare_warning(warn, dquot, QUOTA_NL_BSOFTWARN); |
1327 | dquot->dq_dqb.dqb_btime = get_seconds() + | 1327 | dquot->dq_dqb.dqb_btime = get_seconds() + |
1328 | sb_dqopt(sb)->info[dquot->dq_type].dqi_bgrace; | 1328 | sb_dqopt(sb)->info[dquot->dq_id.type].dqi_bgrace; |
1329 | } | 1329 | } |
1330 | else | 1330 | else |
1331 | /* | 1331 | /* |
@@ -1344,7 +1344,7 @@ static int info_idq_free(struct dquot *dquot, qsize_t inodes) | |||
1344 | 1344 | ||
1345 | if (test_bit(DQ_FAKE_B, &dquot->dq_flags) || | 1345 | if (test_bit(DQ_FAKE_B, &dquot->dq_flags) || |
1346 | dquot->dq_dqb.dqb_curinodes <= dquot->dq_dqb.dqb_isoftlimit || | 1346 | dquot->dq_dqb.dqb_curinodes <= dquot->dq_dqb.dqb_isoftlimit || |
1347 | !sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type)) | 1347 | !sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_id.type)) |
1348 | return QUOTA_NL_NOWARN; | 1348 | return QUOTA_NL_NOWARN; |
1349 | 1349 | ||
1350 | newinodes = dquot->dq_dqb.dqb_curinodes - inodes; | 1350 | newinodes = dquot->dq_dqb.dqb_curinodes - inodes; |
@@ -1390,7 +1390,6 @@ static int dquot_active(const struct inode *inode) | |||
1390 | */ | 1390 | */ |
1391 | static void __dquot_initialize(struct inode *inode, int type) | 1391 | static void __dquot_initialize(struct inode *inode, int type) |
1392 | { | 1392 | { |
1393 | unsigned int id = 0; | ||
1394 | int cnt; | 1393 | int cnt; |
1395 | struct dquot *got[MAXQUOTAS]; | 1394 | struct dquot *got[MAXQUOTAS]; |
1396 | struct super_block *sb = inode->i_sb; | 1395 | struct super_block *sb = inode->i_sb; |
@@ -1403,18 +1402,19 @@ static void __dquot_initialize(struct inode *inode, int type) | |||
1403 | 1402 | ||
1404 | /* First get references to structures we might need. */ | 1403 | /* First get references to structures we might need. */ |
1405 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1404 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
1405 | struct kqid qid; | ||
1406 | got[cnt] = NULL; | 1406 | got[cnt] = NULL; |
1407 | if (type != -1 && cnt != type) | 1407 | if (type != -1 && cnt != type) |
1408 | continue; | 1408 | continue; |
1409 | switch (cnt) { | 1409 | switch (cnt) { |
1410 | case USRQUOTA: | 1410 | case USRQUOTA: |
1411 | id = inode->i_uid; | 1411 | qid = make_kqid_uid(inode->i_uid); |
1412 | break; | 1412 | break; |
1413 | case GRPQUOTA: | 1413 | case GRPQUOTA: |
1414 | id = inode->i_gid; | 1414 | qid = make_kqid_gid(inode->i_gid); |
1415 | break; | 1415 | break; |
1416 | } | 1416 | } |
1417 | got[cnt] = dqget(sb, id, cnt); | 1417 | got[cnt] = dqget(sb, qid); |
1418 | } | 1418 | } |
1419 | 1419 | ||
1420 | down_write(&sb_dqopt(sb)->dqptr_sem); | 1420 | down_write(&sb_dqopt(sb)->dqptr_sem); |
@@ -1897,10 +1897,10 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr) | |||
1897 | if (!dquot_active(inode)) | 1897 | if (!dquot_active(inode)) |
1898 | return 0; | 1898 | return 0; |
1899 | 1899 | ||
1900 | if (iattr->ia_valid & ATTR_UID && iattr->ia_uid != inode->i_uid) | 1900 | if (iattr->ia_valid & ATTR_UID && !uid_eq(iattr->ia_uid, inode->i_uid)) |
1901 | transfer_to[USRQUOTA] = dqget(sb, iattr->ia_uid, USRQUOTA); | 1901 | transfer_to[USRQUOTA] = dqget(sb, make_kqid_uid(iattr->ia_uid)); |
1902 | if (iattr->ia_valid & ATTR_GID && iattr->ia_gid != inode->i_gid) | 1902 | if (iattr->ia_valid & ATTR_GID && !gid_eq(iattr->ia_gid, inode->i_gid)) |
1903 | transfer_to[GRPQUOTA] = dqget(sb, iattr->ia_gid, GRPQUOTA); | 1903 | transfer_to[GRPQUOTA] = dqget(sb, make_kqid_gid(iattr->ia_gid)); |
1904 | 1904 | ||
1905 | ret = __dquot_transfer(inode, transfer_to); | 1905 | ret = __dquot_transfer(inode, transfer_to); |
1906 | dqput_all(transfer_to); | 1906 | dqput_all(transfer_to); |
@@ -2360,9 +2360,9 @@ static void do_get_dqblk(struct dquot *dquot, struct fs_disk_quota *di) | |||
2360 | 2360 | ||
2361 | memset(di, 0, sizeof(*di)); | 2361 | memset(di, 0, sizeof(*di)); |
2362 | di->d_version = FS_DQUOT_VERSION; | 2362 | di->d_version = FS_DQUOT_VERSION; |
2363 | di->d_flags = dquot->dq_type == USRQUOTA ? | 2363 | di->d_flags = dquot->dq_id.type == USRQUOTA ? |
2364 | FS_USER_QUOTA : FS_GROUP_QUOTA; | 2364 | FS_USER_QUOTA : FS_GROUP_QUOTA; |
2365 | di->d_id = dquot->dq_id; | 2365 | di->d_id = from_kqid_munged(current_user_ns(), dquot->dq_id); |
2366 | 2366 | ||
2367 | spin_lock(&dq_data_lock); | 2367 | spin_lock(&dq_data_lock); |
2368 | di->d_blk_hardlimit = stoqb(dm->dqb_bhardlimit); | 2368 | di->d_blk_hardlimit = stoqb(dm->dqb_bhardlimit); |
@@ -2376,12 +2376,12 @@ static void do_get_dqblk(struct dquot *dquot, struct fs_disk_quota *di) | |||
2376 | spin_unlock(&dq_data_lock); | 2376 | spin_unlock(&dq_data_lock); |
2377 | } | 2377 | } |
2378 | 2378 | ||
2379 | int dquot_get_dqblk(struct super_block *sb, int type, qid_t id, | 2379 | int dquot_get_dqblk(struct super_block *sb, struct kqid qid, |
2380 | struct fs_disk_quota *di) | 2380 | struct fs_disk_quota *di) |
2381 | { | 2381 | { |
2382 | struct dquot *dquot; | 2382 | struct dquot *dquot; |
2383 | 2383 | ||
2384 | dquot = dqget(sb, id, type); | 2384 | dquot = dqget(sb, qid); |
2385 | if (!dquot) | 2385 | if (!dquot) |
2386 | return -ESRCH; | 2386 | return -ESRCH; |
2387 | do_get_dqblk(dquot, di); | 2387 | do_get_dqblk(dquot, di); |
@@ -2401,7 +2401,7 @@ static int do_set_dqblk(struct dquot *dquot, struct fs_disk_quota *di) | |||
2401 | { | 2401 | { |
2402 | struct mem_dqblk *dm = &dquot->dq_dqb; | 2402 | struct mem_dqblk *dm = &dquot->dq_dqb; |
2403 | int check_blim = 0, check_ilim = 0; | 2403 | int check_blim = 0, check_ilim = 0; |
2404 | struct mem_dqinfo *dqi = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_type]; | 2404 | struct mem_dqinfo *dqi = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_id.type]; |
2405 | 2405 | ||
2406 | if (di->d_fieldmask & ~VFS_FS_DQ_MASK) | 2406 | if (di->d_fieldmask & ~VFS_FS_DQ_MASK) |
2407 | return -EINVAL; | 2407 | return -EINVAL; |
@@ -2488,13 +2488,13 @@ static int do_set_dqblk(struct dquot *dquot, struct fs_disk_quota *di) | |||
2488 | return 0; | 2488 | return 0; |
2489 | } | 2489 | } |
2490 | 2490 | ||
2491 | int dquot_set_dqblk(struct super_block *sb, int type, qid_t id, | 2491 | int dquot_set_dqblk(struct super_block *sb, struct kqid qid, |
2492 | struct fs_disk_quota *di) | 2492 | struct fs_disk_quota *di) |
2493 | { | 2493 | { |
2494 | struct dquot *dquot; | 2494 | struct dquot *dquot; |
2495 | int rc; | 2495 | int rc; |
2496 | 2496 | ||
2497 | dquot = dqget(sb, id, type); | 2497 | dquot = dqget(sb, qid); |
2498 | if (!dquot) { | 2498 | if (!dquot) { |
2499 | rc = -ESRCH; | 2499 | rc = -ESRCH; |
2500 | goto out; | 2500 | goto out; |
diff --git a/fs/quota/kqid.c b/fs/quota/kqid.c new file mode 100644 index 000000000000..2f97b0e2c501 --- /dev/null +++ b/fs/quota/kqid.c | |||
@@ -0,0 +1,132 @@ | |||
1 | #include <linux/fs.h> | ||
2 | #include <linux/quota.h> | ||
3 | #include <linux/export.h> | ||
4 | |||
5 | /** | ||
6 | * qid_eq - Test to see if to kquid values are the same | ||
7 | * @left: A qid value | ||
8 | * @right: Another quid value | ||
9 | * | ||
10 | * Return true if the two qid values are equal and false otherwise. | ||
11 | */ | ||
12 | bool qid_eq(struct kqid left, struct kqid right) | ||
13 | { | ||
14 | if (left.type != right.type) | ||
15 | return false; | ||
16 | switch(left.type) { | ||
17 | case USRQUOTA: | ||
18 | return uid_eq(left.uid, right.uid); | ||
19 | case GRPQUOTA: | ||
20 | return gid_eq(left.gid, right.gid); | ||
21 | case PRJQUOTA: | ||
22 | return projid_eq(left.projid, right.projid); | ||
23 | default: | ||
24 | BUG(); | ||
25 | } | ||
26 | } | ||
27 | EXPORT_SYMBOL(qid_eq); | ||
28 | |||
29 | /** | ||
30 | * qid_lt - Test to see if one qid value is less than another | ||
31 | * @left: The possibly lesser qid value | ||
32 | * @right: The possibly greater qid value | ||
33 | * | ||
34 | * Return true if left is less than right and false otherwise. | ||
35 | */ | ||
36 | bool qid_lt(struct kqid left, struct kqid right) | ||
37 | { | ||
38 | if (left.type < right.type) | ||
39 | return true; | ||
40 | if (left.type > right.type) | ||
41 | return false; | ||
42 | switch (left.type) { | ||
43 | case USRQUOTA: | ||
44 | return uid_lt(left.uid, right.uid); | ||
45 | case GRPQUOTA: | ||
46 | return gid_lt(left.gid, right.gid); | ||
47 | case PRJQUOTA: | ||
48 | return projid_lt(left.projid, right.projid); | ||
49 | default: | ||
50 | BUG(); | ||
51 | } | ||
52 | } | ||
53 | EXPORT_SYMBOL(qid_lt); | ||
54 | |||
55 | /** | ||
56 | * from_kqid - Create a qid from a kqid user-namespace pair. | ||
57 | * @targ: The user namespace we want a qid in. | ||
58 | * @kuid: The kernel internal quota identifier to start with. | ||
59 | * | ||
60 | * Map @kqid into the user-namespace specified by @targ and | ||
61 | * return the resulting qid. | ||
62 | * | ||
63 | * There is always a mapping into the initial user_namespace. | ||
64 | * | ||
65 | * If @kqid has no mapping in @targ (qid_t)-1 is returned. | ||
66 | */ | ||
67 | qid_t from_kqid(struct user_namespace *targ, struct kqid kqid) | ||
68 | { | ||
69 | switch (kqid.type) { | ||
70 | case USRQUOTA: | ||
71 | return from_kuid(targ, kqid.uid); | ||
72 | case GRPQUOTA: | ||
73 | return from_kgid(targ, kqid.gid); | ||
74 | case PRJQUOTA: | ||
75 | return from_kprojid(targ, kqid.projid); | ||
76 | default: | ||
77 | BUG(); | ||
78 | } | ||
79 | } | ||
80 | EXPORT_SYMBOL(from_kqid); | ||
81 | |||
82 | /** | ||
83 | * from_kqid_munged - Create a qid from a kqid user-namespace pair. | ||
84 | * @targ: The user namespace we want a qid in. | ||
85 | * @kqid: The kernel internal quota identifier to start with. | ||
86 | * | ||
87 | * Map @kqid into the user-namespace specified by @targ and | ||
88 | * return the resulting qid. | ||
89 | * | ||
90 | * There is always a mapping into the initial user_namespace. | ||
91 | * | ||
92 | * Unlike from_kqid from_kqid_munged never fails and always | ||
93 | * returns a valid projid. This makes from_kqid_munged | ||
94 | * appropriate for use in places where failing to provide | ||
95 | * a qid_t is not a good option. | ||
96 | * | ||
97 | * If @kqid has no mapping in @targ the kqid.type specific | ||
98 | * overflow identifier is returned. | ||
99 | */ | ||
100 | qid_t from_kqid_munged(struct user_namespace *targ, struct kqid kqid) | ||
101 | { | ||
102 | switch (kqid.type) { | ||
103 | case USRQUOTA: | ||
104 | return from_kuid_munged(targ, kqid.uid); | ||
105 | case GRPQUOTA: | ||
106 | return from_kgid_munged(targ, kqid.gid); | ||
107 | case PRJQUOTA: | ||
108 | return from_kprojid_munged(targ, kqid.projid); | ||
109 | default: | ||
110 | BUG(); | ||
111 | } | ||
112 | } | ||
113 | EXPORT_SYMBOL(from_kqid_munged); | ||
114 | |||
115 | /** | ||
116 | * qid_valid - Report if a valid value is stored in a kqid. | ||
117 | * @qid: The kernel internal quota identifier to test. | ||
118 | */ | ||
119 | bool qid_valid(struct kqid qid) | ||
120 | { | ||
121 | switch (qid.type) { | ||
122 | case USRQUOTA: | ||
123 | return uid_valid(qid.uid); | ||
124 | case GRPQUOTA: | ||
125 | return gid_valid(qid.gid); | ||
126 | case PRJQUOTA: | ||
127 | return projid_valid(qid.projid); | ||
128 | default: | ||
129 | BUG(); | ||
130 | } | ||
131 | } | ||
132 | EXPORT_SYMBOL(qid_valid); | ||
diff --git a/fs/quota/netlink.c b/fs/quota/netlink.c index d67908b407d9..16e8abb7709b 100644 --- a/fs/quota/netlink.c +++ b/fs/quota/netlink.c | |||
@@ -30,7 +30,7 @@ static struct genl_family quota_genl_family = { | |||
30 | * | 30 | * |
31 | */ | 31 | */ |
32 | 32 | ||
33 | void quota_send_warning(short type, unsigned int id, dev_t dev, | 33 | void quota_send_warning(struct kqid qid, dev_t dev, |
34 | const char warntype) | 34 | const char warntype) |
35 | { | 35 | { |
36 | static atomic_t seq; | 36 | static atomic_t seq; |
@@ -56,10 +56,11 @@ void quota_send_warning(short type, unsigned int id, dev_t dev, | |||
56 | "VFS: Cannot store netlink header in quota warning.\n"); | 56 | "VFS: Cannot store netlink header in quota warning.\n"); |
57 | goto err_out; | 57 | goto err_out; |
58 | } | 58 | } |
59 | ret = nla_put_u32(skb, QUOTA_NL_A_QTYPE, type); | 59 | ret = nla_put_u32(skb, QUOTA_NL_A_QTYPE, qid.type); |
60 | if (ret) | 60 | if (ret) |
61 | goto attr_err_out; | 61 | goto attr_err_out; |
62 | ret = nla_put_u64(skb, QUOTA_NL_A_EXCESS_ID, id); | 62 | ret = nla_put_u64(skb, QUOTA_NL_A_EXCESS_ID, |
63 | from_kqid_munged(&init_user_ns, qid)); | ||
63 | if (ret) | 64 | if (ret) |
64 | goto attr_err_out; | 65 | goto attr_err_out; |
65 | ret = nla_put_u32(skb, QUOTA_NL_A_WARNING, warntype); | 66 | ret = nla_put_u32(skb, QUOTA_NL_A_WARNING, warntype); |
@@ -71,7 +72,8 @@ void quota_send_warning(short type, unsigned int id, dev_t dev, | |||
71 | ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MINOR, MINOR(dev)); | 72 | ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MINOR, MINOR(dev)); |
72 | if (ret) | 73 | if (ret) |
73 | goto attr_err_out; | 74 | goto attr_err_out; |
74 | ret = nla_put_u64(skb, QUOTA_NL_A_CAUSED_ID, current_uid()); | 75 | ret = nla_put_u64(skb, QUOTA_NL_A_CAUSED_ID, |
76 | from_kuid_munged(&init_user_ns, current_uid())); | ||
75 | if (ret) | 77 | if (ret) |
76 | goto attr_err_out; | 78 | goto attr_err_out; |
77 | genlmsg_end(skb, msg_head); | 79 | genlmsg_end(skb, msg_head); |
diff --git a/fs/quota/quota.c b/fs/quota/quota.c index 6f155788cbc6..ff0135d6bc51 100644 --- a/fs/quota/quota.c +++ b/fs/quota/quota.c | |||
@@ -32,8 +32,8 @@ static int check_quotactl_permission(struct super_block *sb, int type, int cmd, | |||
32 | /* allow to query information for dquots we "own" */ | 32 | /* allow to query information for dquots we "own" */ |
33 | case Q_GETQUOTA: | 33 | case Q_GETQUOTA: |
34 | case Q_XGETQUOTA: | 34 | case Q_XGETQUOTA: |
35 | if ((type == USRQUOTA && current_euid() == id) || | 35 | if ((type == USRQUOTA && uid_eq(current_euid(), make_kuid(current_user_ns(), id))) || |
36 | (type == GRPQUOTA && in_egroup_p(id))) | 36 | (type == GRPQUOTA && in_egroup_p(make_kgid(current_user_ns(), id)))) |
37 | break; | 37 | break; |
38 | /*FALLTHROUGH*/ | 38 | /*FALLTHROUGH*/ |
39 | default: | 39 | default: |
@@ -130,13 +130,17 @@ static void copy_to_if_dqblk(struct if_dqblk *dst, struct fs_disk_quota *src) | |||
130 | static int quota_getquota(struct super_block *sb, int type, qid_t id, | 130 | static int quota_getquota(struct super_block *sb, int type, qid_t id, |
131 | void __user *addr) | 131 | void __user *addr) |
132 | { | 132 | { |
133 | struct kqid qid; | ||
133 | struct fs_disk_quota fdq; | 134 | struct fs_disk_quota fdq; |
134 | struct if_dqblk idq; | 135 | struct if_dqblk idq; |
135 | int ret; | 136 | int ret; |
136 | 137 | ||
137 | if (!sb->s_qcop->get_dqblk) | 138 | if (!sb->s_qcop->get_dqblk) |
138 | return -ENOSYS; | 139 | return -ENOSYS; |
139 | ret = sb->s_qcop->get_dqblk(sb, type, id, &fdq); | 140 | qid = make_kqid(current_user_ns(), type, id); |
141 | if (!qid_valid(qid)) | ||
142 | return -EINVAL; | ||
143 | ret = sb->s_qcop->get_dqblk(sb, qid, &fdq); | ||
140 | if (ret) | 144 | if (ret) |
141 | return ret; | 145 | return ret; |
142 | copy_to_if_dqblk(&idq, &fdq); | 146 | copy_to_if_dqblk(&idq, &fdq); |
@@ -176,13 +180,17 @@ static int quota_setquota(struct super_block *sb, int type, qid_t id, | |||
176 | { | 180 | { |
177 | struct fs_disk_quota fdq; | 181 | struct fs_disk_quota fdq; |
178 | struct if_dqblk idq; | 182 | struct if_dqblk idq; |
183 | struct kqid qid; | ||
179 | 184 | ||
180 | if (copy_from_user(&idq, addr, sizeof(idq))) | 185 | if (copy_from_user(&idq, addr, sizeof(idq))) |
181 | return -EFAULT; | 186 | return -EFAULT; |
182 | if (!sb->s_qcop->set_dqblk) | 187 | if (!sb->s_qcop->set_dqblk) |
183 | return -ENOSYS; | 188 | return -ENOSYS; |
189 | qid = make_kqid(current_user_ns(), type, id); | ||
190 | if (!qid_valid(qid)) | ||
191 | return -EINVAL; | ||
184 | copy_from_if_dqblk(&fdq, &idq); | 192 | copy_from_if_dqblk(&fdq, &idq); |
185 | return sb->s_qcop->set_dqblk(sb, type, id, &fdq); | 193 | return sb->s_qcop->set_dqblk(sb, qid, &fdq); |
186 | } | 194 | } |
187 | 195 | ||
188 | static int quota_setxstate(struct super_block *sb, int cmd, void __user *addr) | 196 | static int quota_setxstate(struct super_block *sb, int cmd, void __user *addr) |
@@ -213,23 +221,31 @@ static int quota_setxquota(struct super_block *sb, int type, qid_t id, | |||
213 | void __user *addr) | 221 | void __user *addr) |
214 | { | 222 | { |
215 | struct fs_disk_quota fdq; | 223 | struct fs_disk_quota fdq; |
224 | struct kqid qid; | ||
216 | 225 | ||
217 | if (copy_from_user(&fdq, addr, sizeof(fdq))) | 226 | if (copy_from_user(&fdq, addr, sizeof(fdq))) |
218 | return -EFAULT; | 227 | return -EFAULT; |
219 | if (!sb->s_qcop->set_dqblk) | 228 | if (!sb->s_qcop->set_dqblk) |
220 | return -ENOSYS; | 229 | return -ENOSYS; |
221 | return sb->s_qcop->set_dqblk(sb, type, id, &fdq); | 230 | qid = make_kqid(current_user_ns(), type, id); |
231 | if (!qid_valid(qid)) | ||
232 | return -EINVAL; | ||
233 | return sb->s_qcop->set_dqblk(sb, qid, &fdq); | ||
222 | } | 234 | } |
223 | 235 | ||
224 | static int quota_getxquota(struct super_block *sb, int type, qid_t id, | 236 | static int quota_getxquota(struct super_block *sb, int type, qid_t id, |
225 | void __user *addr) | 237 | void __user *addr) |
226 | { | 238 | { |
227 | struct fs_disk_quota fdq; | 239 | struct fs_disk_quota fdq; |
240 | struct kqid qid; | ||
228 | int ret; | 241 | int ret; |
229 | 242 | ||
230 | if (!sb->s_qcop->get_dqblk) | 243 | if (!sb->s_qcop->get_dqblk) |
231 | return -ENOSYS; | 244 | return -ENOSYS; |
232 | ret = sb->s_qcop->get_dqblk(sb, type, id, &fdq); | 245 | qid = make_kqid(current_user_ns(), type, id); |
246 | if (!qid_valid(qid)) | ||
247 | return -EINVAL; | ||
248 | ret = sb->s_qcop->get_dqblk(sb, qid, &fdq); | ||
233 | if (!ret && copy_to_user(addr, &fdq, sizeof(fdq))) | 249 | if (!ret && copy_to_user(addr, &fdq, sizeof(fdq))) |
234 | return -EFAULT; | 250 | return -EFAULT; |
235 | return ret; | 251 | return ret; |
diff --git a/fs/quota/quota_tree.c b/fs/quota/quota_tree.c index e41c1becf096..d65877fbe8f4 100644 --- a/fs/quota/quota_tree.c +++ b/fs/quota/quota_tree.c | |||
@@ -22,9 +22,10 @@ MODULE_LICENSE("GPL"); | |||
22 | 22 | ||
23 | #define __QUOTA_QT_PARANOIA | 23 | #define __QUOTA_QT_PARANOIA |
24 | 24 | ||
25 | static int get_index(struct qtree_mem_dqinfo *info, qid_t id, int depth) | 25 | static int get_index(struct qtree_mem_dqinfo *info, struct kqid qid, int depth) |
26 | { | 26 | { |
27 | unsigned int epb = info->dqi_usable_bs >> 2; | 27 | unsigned int epb = info->dqi_usable_bs >> 2; |
28 | qid_t id = from_kqid(&init_user_ns, qid); | ||
28 | 29 | ||
29 | depth = info->dqi_qtree_depth - depth - 1; | 30 | depth = info->dqi_qtree_depth - depth - 1; |
30 | while (depth--) | 31 | while (depth--) |
@@ -244,7 +245,7 @@ static uint find_free_dqentry(struct qtree_mem_dqinfo *info, | |||
244 | /* This is enough as the block is already zeroed and the entry | 245 | /* This is enough as the block is already zeroed and the entry |
245 | * list is empty... */ | 246 | * list is empty... */ |
246 | info->dqi_free_entry = blk; | 247 | info->dqi_free_entry = blk; |
247 | mark_info_dirty(dquot->dq_sb, dquot->dq_type); | 248 | mark_info_dirty(dquot->dq_sb, dquot->dq_id.type); |
248 | } | 249 | } |
249 | /* Block will be full? */ | 250 | /* Block will be full? */ |
250 | if (le16_to_cpu(dh->dqdh_entries) + 1 >= qtree_dqstr_in_blk(info)) { | 251 | if (le16_to_cpu(dh->dqdh_entries) + 1 >= qtree_dqstr_in_blk(info)) { |
@@ -357,7 +358,7 @@ static inline int dq_insert_tree(struct qtree_mem_dqinfo *info, | |||
357 | */ | 358 | */ |
358 | int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) | 359 | int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) |
359 | { | 360 | { |
360 | int type = dquot->dq_type; | 361 | int type = dquot->dq_id.type; |
361 | struct super_block *sb = dquot->dq_sb; | 362 | struct super_block *sb = dquot->dq_sb; |
362 | ssize_t ret; | 363 | ssize_t ret; |
363 | char *ddquot = getdqbuf(info->dqi_entry_size); | 364 | char *ddquot = getdqbuf(info->dqi_entry_size); |
@@ -538,8 +539,9 @@ static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info, | |||
538 | ddquot += info->dqi_entry_size; | 539 | ddquot += info->dqi_entry_size; |
539 | } | 540 | } |
540 | if (i == qtree_dqstr_in_blk(info)) { | 541 | if (i == qtree_dqstr_in_blk(info)) { |
541 | quota_error(dquot->dq_sb, "Quota for id %u referenced " | 542 | quota_error(dquot->dq_sb, |
542 | "but not present", dquot->dq_id); | 543 | "Quota for id %u referenced but not present", |
544 | from_kqid(&init_user_ns, dquot->dq_id)); | ||
543 | ret = -EIO; | 545 | ret = -EIO; |
544 | goto out_buf; | 546 | goto out_buf; |
545 | } else { | 547 | } else { |
@@ -589,7 +591,7 @@ static inline loff_t find_dqentry(struct qtree_mem_dqinfo *info, | |||
589 | 591 | ||
590 | int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) | 592 | int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) |
591 | { | 593 | { |
592 | int type = dquot->dq_type; | 594 | int type = dquot->dq_id.type; |
593 | struct super_block *sb = dquot->dq_sb; | 595 | struct super_block *sb = dquot->dq_sb; |
594 | loff_t offset; | 596 | loff_t offset; |
595 | char *ddquot; | 597 | char *ddquot; |
@@ -607,8 +609,10 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) | |||
607 | offset = find_dqentry(info, dquot); | 609 | offset = find_dqentry(info, dquot); |
608 | if (offset <= 0) { /* Entry not present? */ | 610 | if (offset <= 0) { /* Entry not present? */ |
609 | if (offset < 0) | 611 | if (offset < 0) |
610 | quota_error(sb, "Can't read quota structure " | 612 | quota_error(sb,"Can't read quota structure " |
611 | "for id %u", dquot->dq_id); | 613 | "for id %u", |
614 | from_kqid(&init_user_ns, | ||
615 | dquot->dq_id)); | ||
612 | dquot->dq_off = 0; | 616 | dquot->dq_off = 0; |
613 | set_bit(DQ_FAKE_B, &dquot->dq_flags); | 617 | set_bit(DQ_FAKE_B, &dquot->dq_flags); |
614 | memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk)); | 618 | memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk)); |
@@ -626,7 +630,7 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) | |||
626 | if (ret >= 0) | 630 | if (ret >= 0) |
627 | ret = -EIO; | 631 | ret = -EIO; |
628 | quota_error(sb, "Error while reading quota structure for id %u", | 632 | quota_error(sb, "Error while reading quota structure for id %u", |
629 | dquot->dq_id); | 633 | from_kqid(&init_user_ns, dquot->dq_id)); |
630 | set_bit(DQ_FAKE_B, &dquot->dq_flags); | 634 | set_bit(DQ_FAKE_B, &dquot->dq_flags); |
631 | memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk)); | 635 | memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk)); |
632 | kfree(ddquot); | 636 | kfree(ddquot); |
diff --git a/fs/quota/quota_v1.c b/fs/quota/quota_v1.c index 34b37a67bb16..469c6848b322 100644 --- a/fs/quota/quota_v1.c +++ b/fs/quota/quota_v1.c | |||
@@ -54,7 +54,7 @@ static void v1_mem2disk_dqblk(struct v1_disk_dqblk *d, struct mem_dqblk *m) | |||
54 | 54 | ||
55 | static int v1_read_dqblk(struct dquot *dquot) | 55 | static int v1_read_dqblk(struct dquot *dquot) |
56 | { | 56 | { |
57 | int type = dquot->dq_type; | 57 | int type = dquot->dq_id.type; |
58 | struct v1_disk_dqblk dqblk; | 58 | struct v1_disk_dqblk dqblk; |
59 | 59 | ||
60 | if (!sb_dqopt(dquot->dq_sb)->files[type]) | 60 | if (!sb_dqopt(dquot->dq_sb)->files[type]) |
@@ -63,7 +63,8 @@ static int v1_read_dqblk(struct dquot *dquot) | |||
63 | /* Set structure to 0s in case read fails/is after end of file */ | 63 | /* Set structure to 0s in case read fails/is after end of file */ |
64 | memset(&dqblk, 0, sizeof(struct v1_disk_dqblk)); | 64 | memset(&dqblk, 0, sizeof(struct v1_disk_dqblk)); |
65 | dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type, (char *)&dqblk, | 65 | dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type, (char *)&dqblk, |
66 | sizeof(struct v1_disk_dqblk), v1_dqoff(dquot->dq_id)); | 66 | sizeof(struct v1_disk_dqblk), |
67 | v1_dqoff(from_kqid(&init_user_ns, dquot->dq_id))); | ||
67 | 68 | ||
68 | v1_disk2mem_dqblk(&dquot->dq_dqb, &dqblk); | 69 | v1_disk2mem_dqblk(&dquot->dq_dqb, &dqblk); |
69 | if (dquot->dq_dqb.dqb_bhardlimit == 0 && | 70 | if (dquot->dq_dqb.dqb_bhardlimit == 0 && |
@@ -78,12 +79,13 @@ static int v1_read_dqblk(struct dquot *dquot) | |||
78 | 79 | ||
79 | static int v1_commit_dqblk(struct dquot *dquot) | 80 | static int v1_commit_dqblk(struct dquot *dquot) |
80 | { | 81 | { |
81 | short type = dquot->dq_type; | 82 | short type = dquot->dq_id.type; |
82 | ssize_t ret; | 83 | ssize_t ret; |
83 | struct v1_disk_dqblk dqblk; | 84 | struct v1_disk_dqblk dqblk; |
84 | 85 | ||
85 | v1_mem2disk_dqblk(&dqblk, &dquot->dq_dqb); | 86 | v1_mem2disk_dqblk(&dqblk, &dquot->dq_dqb); |
86 | if (dquot->dq_id == 0) { | 87 | if (((type == USRQUOTA) && uid_eq(dquot->dq_id.uid, GLOBAL_ROOT_UID)) || |
88 | ((type == GRPQUOTA) && gid_eq(dquot->dq_id.gid, GLOBAL_ROOT_GID))) { | ||
87 | dqblk.dqb_btime = | 89 | dqblk.dqb_btime = |
88 | sb_dqopt(dquot->dq_sb)->info[type].dqi_bgrace; | 90 | sb_dqopt(dquot->dq_sb)->info[type].dqi_bgrace; |
89 | dqblk.dqb_itime = | 91 | dqblk.dqb_itime = |
@@ -93,7 +95,7 @@ static int v1_commit_dqblk(struct dquot *dquot) | |||
93 | if (sb_dqopt(dquot->dq_sb)->files[type]) | 95 | if (sb_dqopt(dquot->dq_sb)->files[type]) |
94 | ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type, | 96 | ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type, |
95 | (char *)&dqblk, sizeof(struct v1_disk_dqblk), | 97 | (char *)&dqblk, sizeof(struct v1_disk_dqblk), |
96 | v1_dqoff(dquot->dq_id)); | 98 | v1_dqoff(from_kqid(&init_user_ns, dquot->dq_id))); |
97 | if (ret != sizeof(struct v1_disk_dqblk)) { | 99 | if (ret != sizeof(struct v1_disk_dqblk)) { |
98 | quota_error(dquot->dq_sb, "dquota write failed"); | 100 | quota_error(dquot->dq_sb, "dquota write failed"); |
99 | if (ret >= 0) | 101 | if (ret >= 0) |
diff --git a/fs/quota/quota_v2.c b/fs/quota/quota_v2.c index f1ab3604db5a..02751ec695c5 100644 --- a/fs/quota/quota_v2.c +++ b/fs/quota/quota_v2.c | |||
@@ -196,7 +196,7 @@ static void v2r0_mem2diskdqb(void *dp, struct dquot *dquot) | |||
196 | struct v2r0_disk_dqblk *d = dp; | 196 | struct v2r0_disk_dqblk *d = dp; |
197 | struct mem_dqblk *m = &dquot->dq_dqb; | 197 | struct mem_dqblk *m = &dquot->dq_dqb; |
198 | struct qtree_mem_dqinfo *info = | 198 | struct qtree_mem_dqinfo *info = |
199 | sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv; | 199 | sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv; |
200 | 200 | ||
201 | d->dqb_ihardlimit = cpu_to_le32(m->dqb_ihardlimit); | 201 | d->dqb_ihardlimit = cpu_to_le32(m->dqb_ihardlimit); |
202 | d->dqb_isoftlimit = cpu_to_le32(m->dqb_isoftlimit); | 202 | d->dqb_isoftlimit = cpu_to_le32(m->dqb_isoftlimit); |
@@ -206,7 +206,7 @@ static void v2r0_mem2diskdqb(void *dp, struct dquot *dquot) | |||
206 | d->dqb_bsoftlimit = cpu_to_le32(v2_stoqb(m->dqb_bsoftlimit)); | 206 | d->dqb_bsoftlimit = cpu_to_le32(v2_stoqb(m->dqb_bsoftlimit)); |
207 | d->dqb_curspace = cpu_to_le64(m->dqb_curspace); | 207 | d->dqb_curspace = cpu_to_le64(m->dqb_curspace); |
208 | d->dqb_btime = cpu_to_le64(m->dqb_btime); | 208 | d->dqb_btime = cpu_to_le64(m->dqb_btime); |
209 | d->dqb_id = cpu_to_le32(dquot->dq_id); | 209 | d->dqb_id = cpu_to_le32(from_kqid(&init_user_ns, dquot->dq_id)); |
210 | if (qtree_entry_unused(info, dp)) | 210 | if (qtree_entry_unused(info, dp)) |
211 | d->dqb_itime = cpu_to_le64(1); | 211 | d->dqb_itime = cpu_to_le64(1); |
212 | } | 212 | } |
@@ -215,11 +215,13 @@ static int v2r0_is_id(void *dp, struct dquot *dquot) | |||
215 | { | 215 | { |
216 | struct v2r0_disk_dqblk *d = dp; | 216 | struct v2r0_disk_dqblk *d = dp; |
217 | struct qtree_mem_dqinfo *info = | 217 | struct qtree_mem_dqinfo *info = |
218 | sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv; | 218 | sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv; |
219 | 219 | ||
220 | if (qtree_entry_unused(info, dp)) | 220 | if (qtree_entry_unused(info, dp)) |
221 | return 0; | 221 | return 0; |
222 | return le32_to_cpu(d->dqb_id) == dquot->dq_id; | 222 | return qid_eq(make_kqid(&init_user_ns, dquot->dq_id.type, |
223 | le32_to_cpu(d->dqb_id)), | ||
224 | dquot->dq_id); | ||
223 | } | 225 | } |
224 | 226 | ||
225 | static void v2r1_disk2memdqb(struct dquot *dquot, void *dp) | 227 | static void v2r1_disk2memdqb(struct dquot *dquot, void *dp) |
@@ -247,7 +249,7 @@ static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot) | |||
247 | struct v2r1_disk_dqblk *d = dp; | 249 | struct v2r1_disk_dqblk *d = dp; |
248 | struct mem_dqblk *m = &dquot->dq_dqb; | 250 | struct mem_dqblk *m = &dquot->dq_dqb; |
249 | struct qtree_mem_dqinfo *info = | 251 | struct qtree_mem_dqinfo *info = |
250 | sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv; | 252 | sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv; |
251 | 253 | ||
252 | d->dqb_ihardlimit = cpu_to_le64(m->dqb_ihardlimit); | 254 | d->dqb_ihardlimit = cpu_to_le64(m->dqb_ihardlimit); |
253 | d->dqb_isoftlimit = cpu_to_le64(m->dqb_isoftlimit); | 255 | d->dqb_isoftlimit = cpu_to_le64(m->dqb_isoftlimit); |
@@ -257,7 +259,7 @@ static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot) | |||
257 | d->dqb_bsoftlimit = cpu_to_le64(v2_stoqb(m->dqb_bsoftlimit)); | 259 | d->dqb_bsoftlimit = cpu_to_le64(v2_stoqb(m->dqb_bsoftlimit)); |
258 | d->dqb_curspace = cpu_to_le64(m->dqb_curspace); | 260 | d->dqb_curspace = cpu_to_le64(m->dqb_curspace); |
259 | d->dqb_btime = cpu_to_le64(m->dqb_btime); | 261 | d->dqb_btime = cpu_to_le64(m->dqb_btime); |
260 | d->dqb_id = cpu_to_le32(dquot->dq_id); | 262 | d->dqb_id = cpu_to_le32(from_kqid(&init_user_ns, dquot->dq_id)); |
261 | if (qtree_entry_unused(info, dp)) | 263 | if (qtree_entry_unused(info, dp)) |
262 | d->dqb_itime = cpu_to_le64(1); | 264 | d->dqb_itime = cpu_to_le64(1); |
263 | } | 265 | } |
@@ -266,26 +268,28 @@ static int v2r1_is_id(void *dp, struct dquot *dquot) | |||
266 | { | 268 | { |
267 | struct v2r1_disk_dqblk *d = dp; | 269 | struct v2r1_disk_dqblk *d = dp; |
268 | struct qtree_mem_dqinfo *info = | 270 | struct qtree_mem_dqinfo *info = |
269 | sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv; | 271 | sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv; |
270 | 272 | ||
271 | if (qtree_entry_unused(info, dp)) | 273 | if (qtree_entry_unused(info, dp)) |
272 | return 0; | 274 | return 0; |
273 | return le32_to_cpu(d->dqb_id) == dquot->dq_id; | 275 | return qid_eq(make_kqid(&init_user_ns, dquot->dq_id.type, |
276 | le32_to_cpu(d->dqb_id)), | ||
277 | dquot->dq_id); | ||
274 | } | 278 | } |
275 | 279 | ||
276 | static int v2_read_dquot(struct dquot *dquot) | 280 | static int v2_read_dquot(struct dquot *dquot) |
277 | { | 281 | { |
278 | return qtree_read_dquot(sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv, dquot); | 282 | return qtree_read_dquot(sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv, dquot); |
279 | } | 283 | } |
280 | 284 | ||
281 | static int v2_write_dquot(struct dquot *dquot) | 285 | static int v2_write_dquot(struct dquot *dquot) |
282 | { | 286 | { |
283 | return qtree_write_dquot(sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv, dquot); | 287 | return qtree_write_dquot(sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv, dquot); |
284 | } | 288 | } |
285 | 289 | ||
286 | static int v2_release_dquot(struct dquot *dquot) | 290 | static int v2_release_dquot(struct dquot *dquot) |
287 | { | 291 | { |
288 | return qtree_release_dquot(sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv, dquot); | 292 | return qtree_release_dquot(sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv, dquot); |
289 | } | 293 | } |
290 | 294 | ||
291 | static int v2_free_file_info(struct super_block *sb, int type) | 295 | static int v2_free_file_info(struct super_block *sb, int type) |