diff options
Diffstat (limited to 'fs/quota')
-rw-r--r-- | fs/quota/dquot.c | 63 | ||||
-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 |
4 files changed, 67 insertions, 56 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) static inline void insert_dquot_hash(struct dquot *dquot) { struct hlist_head *head; - head = dquot_hash + hashfn(dquot->dq_sb, dquot->dq_id, dquot->dq_type); + head = dquot_hash + hashfn(dquot->dq_sb, from_kqid(&init_user_ns, dquot->dq_id), dquot->dq_id.type); hlist_add_head(&dquot->dq_hash, head); } @@ -279,13 +279,13 @@ static inline void remove_dquot_hash(struct dquot *dquot) static struct dquot *find_dquot(unsigned int hashent, struct super_block *sb, unsigned int id, int type) { + struct kqid qid = make_kqid(&init_user_ns, type, id); struct hlist_node *node; struct dquot *dquot; hlist_for_each (node, dquot_hash+hashent) { dquot = hlist_entry(node, struct dquot, dq_hash); - if (dquot->dq_sb == sb && dquot->dq_id == id && - dquot->dq_type == type) + if (dquot->dq_sb == sb && qid_eq(dquot->dq_id, qid)) return dquot; } return NULL; @@ -351,7 +351,7 @@ int dquot_mark_dquot_dirty(struct dquot *dquot) spin_lock(&dq_list_lock); if (!test_and_set_bit(DQ_MOD_B, &dquot->dq_flags)) { list_add(&dquot->dq_dirty, &sb_dqopt(dquot->dq_sb)-> - info[dquot->dq_type].dqi_dirty_list); + info[dquot->dq_id.type].dqi_dirty_list); ret = 0; } spin_unlock(&dq_list_lock); @@ -410,17 +410,17 @@ int dquot_acquire(struct dquot *dquot) mutex_lock(&dquot->dq_lock); mutex_lock(&dqopt->dqio_mutex); if (!test_bit(DQ_READ_B, &dquot->dq_flags)) - ret = dqopt->ops[dquot->dq_type]->read_dqblk(dquot); + ret = dqopt->ops[dquot->dq_id.type]->read_dqblk(dquot); if (ret < 0) goto out_iolock; set_bit(DQ_READ_B, &dquot->dq_flags); /* Instantiate dquot if needed */ if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && !dquot->dq_off) { - ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot); + ret = dqopt->ops[dquot->dq_id.type]->commit_dqblk(dquot); /* Write the info if needed */ - if (info_dirty(&dqopt->info[dquot->dq_type])) { - ret2 = dqopt->ops[dquot->dq_type]->write_file_info( - dquot->dq_sb, dquot->dq_type); + if (info_dirty(&dqopt->info[dquot->dq_id.type])) { + ret2 = dqopt->ops[dquot->dq_id.type]->write_file_info( + dquot->dq_sb, dquot->dq_id.type); } if (ret < 0) goto out_iolock; @@ -455,7 +455,7 @@ int dquot_commit(struct dquot *dquot) /* Inactive dquot can be only if there was error during read/init * => we have better not writing it */ if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) - ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot); + ret = dqopt->ops[dquot->dq_id.type]->commit_dqblk(dquot); else ret = -EIO; out_sem: @@ -477,12 +477,12 @@ int dquot_release(struct dquot *dquot) if (atomic_read(&dquot->dq_count) > 1) goto out_dqlock; mutex_lock(&dqopt->dqio_mutex); - if (dqopt->ops[dquot->dq_type]->release_dqblk) { - ret = dqopt->ops[dquot->dq_type]->release_dqblk(dquot); + if (dqopt->ops[dquot->dq_id.type]->release_dqblk) { + ret = dqopt->ops[dquot->dq_id.type]->release_dqblk(dquot); /* Write the info */ - if (info_dirty(&dqopt->info[dquot->dq_type])) { - ret2 = dqopt->ops[dquot->dq_type]->write_file_info( - dquot->dq_sb, dquot->dq_type); + if (info_dirty(&dqopt->info[dquot->dq_id.type])) { + ret2 = dqopt->ops[dquot->dq_id.type]->write_file_info( + dquot->dq_sb, dquot->dq_id.type); } if (ret >= 0) ret = ret2; @@ -521,7 +521,7 @@ restart: list_for_each_entry_safe(dquot, tmp, &inuse_list, dq_inuse) { if (dquot->dq_sb != sb) continue; - if (dquot->dq_type != type) + if (dquot->dq_id.type != type) continue; /* Wait for dquot users */ if (atomic_read(&dquot->dq_count)) { @@ -741,7 +741,8 @@ void dqput(struct dquot *dquot) #ifdef CONFIG_QUOTA_DEBUG if (!atomic_read(&dquot->dq_count)) { quota_error(dquot->dq_sb, "trying to free free dquot of %s %d", - quotatypes[dquot->dq_type], dquot->dq_id); + quotatypes[dquot->dq_id.type], + from_kqid(&init_user_ns, dquot->dq_id)); BUG(); } #endif @@ -752,7 +753,7 @@ we_slept: /* We have more than one user... nothing to do */ atomic_dec(&dquot->dq_count); /* Releasing dquot during quotaoff phase? */ - if (!sb_has_quota_active(dquot->dq_sb, dquot->dq_type) && + if (!sb_has_quota_active(dquot->dq_sb, dquot->dq_id.type) && atomic_read(&dquot->dq_count) == 1) wake_up(&dquot->dq_wait_unused); spin_unlock(&dq_list_lock); @@ -815,7 +816,7 @@ static struct dquot *get_empty_dquot(struct super_block *sb, int type) INIT_LIST_HEAD(&dquot->dq_dirty); init_waitqueue_head(&dquot->dq_wait_unused); dquot->dq_sb = sb; - dquot->dq_type = type; + dquot->dq_id.type = type; atomic_set(&dquot->dq_count, 1); return dquot; @@ -859,7 +860,7 @@ we_slept: } dquot = empty; empty = NULL; - dquot->dq_id = id; + dquot->dq_id = qid; /* all dquots go on the inuse_list */ put_inuse(dquot); /* hash it first so it can be found */ @@ -1219,8 +1220,8 @@ static void prepare_warning(struct dquot_warn *warn, struct dquot *dquot, return; warn->w_type = warntype; warn->w_sb = dquot->dq_sb; - warn->w_dq_id = dquot->dq_id; - warn->w_dq_type = dquot->dq_type; + warn->w_dq_id = from_kqid(&init_user_ns, dquot->dq_id); + warn->w_dq_type = dquot->dq_id.type; } /* @@ -1245,7 +1246,7 @@ static void flush_warnings(struct dquot_warn *warn) static int ignore_hardlimit(struct dquot *dquot) { - struct mem_dqinfo *info = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_type]; + struct mem_dqinfo *info = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_id.type]; return capable(CAP_SYS_RESOURCE) && (info->dqi_format->qf_fmt_id != QFMT_VFS_OLD || @@ -1258,7 +1259,7 @@ static int check_idq(struct dquot *dquot, qsize_t inodes, { qsize_t newinodes = dquot->dq_dqb.dqb_curinodes + inodes; - if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type) || + if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_id.type) || test_bit(DQ_FAKE_B, &dquot->dq_flags)) return 0; @@ -1283,7 +1284,7 @@ static int check_idq(struct dquot *dquot, qsize_t inodes, dquot->dq_dqb.dqb_itime == 0) { prepare_warning(warn, dquot, QUOTA_NL_ISOFTWARN); dquot->dq_dqb.dqb_itime = get_seconds() + - sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_igrace; + sb_dqopt(dquot->dq_sb)->info[dquot->dq_id.type].dqi_igrace; } return 0; @@ -1296,7 +1297,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, qsize_t tspace; struct super_block *sb = dquot->dq_sb; - if (!sb_has_quota_limits_enabled(sb, dquot->dq_type) || + if (!sb_has_quota_limits_enabled(sb, dquot->dq_id.type) || test_bit(DQ_FAKE_B, &dquot->dq_flags)) return 0; @@ -1327,7 +1328,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, if (!prealloc) { prepare_warning(warn, dquot, QUOTA_NL_BSOFTWARN); dquot->dq_dqb.dqb_btime = get_seconds() + - sb_dqopt(sb)->info[dquot->dq_type].dqi_bgrace; + sb_dqopt(sb)->info[dquot->dq_id.type].dqi_bgrace; } else /* @@ -1346,7 +1347,7 @@ static int info_idq_free(struct dquot *dquot, qsize_t inodes) if (test_bit(DQ_FAKE_B, &dquot->dq_flags) || dquot->dq_dqb.dqb_curinodes <= dquot->dq_dqb.dqb_isoftlimit || - !sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type)) + !sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_id.type)) return QUOTA_NL_NOWARN; newinodes = dquot->dq_dqb.dqb_curinodes - inodes; @@ -2362,9 +2363,9 @@ static void do_get_dqblk(struct dquot *dquot, struct fs_disk_quota *di) memset(di, 0, sizeof(*di)); di->d_version = FS_DQUOT_VERSION; - di->d_flags = dquot->dq_type == USRQUOTA ? + di->d_flags = dquot->dq_id.type == USRQUOTA ? FS_USER_QUOTA : FS_GROUP_QUOTA; - di->d_id = dquot->dq_id; + di->d_id = from_kqid_munged(current_user_ns(), dquot->dq_id); spin_lock(&dq_data_lock); 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) { struct mem_dqblk *dm = &dquot->dq_dqb; int check_blim = 0, check_ilim = 0; - struct mem_dqinfo *dqi = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_type]; + struct mem_dqinfo *dqi = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_id.type]; if (di->d_fieldmask & ~VFS_FS_DQ_MASK) return -EINVAL; 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"); #define __QUOTA_QT_PARANOIA -static int get_index(struct qtree_mem_dqinfo *info, qid_t id, int depth) +static int get_index(struct qtree_mem_dqinfo *info, struct kqid qid, int depth) { unsigned int epb = info->dqi_usable_bs >> 2; + qid_t id = from_kqid(&init_user_ns, qid); depth = info->dqi_qtree_depth - depth - 1; while (depth--) @@ -244,7 +245,7 @@ static uint find_free_dqentry(struct qtree_mem_dqinfo *info, /* This is enough as the block is already zeroed and the entry * list is empty... */ info->dqi_free_entry = blk; - mark_info_dirty(dquot->dq_sb, dquot->dq_type); + mark_info_dirty(dquot->dq_sb, dquot->dq_id.type); } /* Block will be full? */ 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, */ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) { - int type = dquot->dq_type; + int type = dquot->dq_id.type; struct super_block *sb = dquot->dq_sb; ssize_t ret; char *ddquot = getdqbuf(info->dqi_entry_size); @@ -538,8 +539,9 @@ static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info, ddquot += info->dqi_entry_size; } if (i == qtree_dqstr_in_blk(info)) { - quota_error(dquot->dq_sb, "Quota for id %u referenced " - "but not present", dquot->dq_id); + quota_error(dquot->dq_sb, + "Quota for id %u referenced but not present", + from_kqid(&init_user_ns, dquot->dq_id)); ret = -EIO; goto out_buf; } else { @@ -589,7 +591,7 @@ static inline loff_t find_dqentry(struct qtree_mem_dqinfo *info, int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) { - int type = dquot->dq_type; + int type = dquot->dq_id.type; struct super_block *sb = dquot->dq_sb; loff_t offset; char *ddquot; @@ -607,8 +609,10 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) offset = find_dqentry(info, dquot); if (offset <= 0) { /* Entry not present? */ if (offset < 0) - quota_error(sb, "Can't read quota structure " - "for id %u", dquot->dq_id); + quota_error(sb,"Can't read quota structure " + "for id %u", + from_kqid(&init_user_ns, + dquot->dq_id)); dquot->dq_off = 0; set_bit(DQ_FAKE_B, &dquot->dq_flags); 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) if (ret >= 0) ret = -EIO; quota_error(sb, "Error while reading quota structure for id %u", - dquot->dq_id); + from_kqid(&init_user_ns, dquot->dq_id)); set_bit(DQ_FAKE_B, &dquot->dq_flags); memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk)); 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) static int v1_read_dqblk(struct dquot *dquot) { - int type = dquot->dq_type; + int type = dquot->dq_id.type; struct v1_disk_dqblk dqblk; if (!sb_dqopt(dquot->dq_sb)->files[type]) @@ -63,7 +63,8 @@ static int v1_read_dqblk(struct dquot *dquot) /* Set structure to 0s in case read fails/is after end of file */ memset(&dqblk, 0, sizeof(struct v1_disk_dqblk)); dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type, (char *)&dqblk, - sizeof(struct v1_disk_dqblk), v1_dqoff(dquot->dq_id)); + sizeof(struct v1_disk_dqblk), + v1_dqoff(from_kqid(&init_user_ns, dquot->dq_id))); v1_disk2mem_dqblk(&dquot->dq_dqb, &dqblk); if (dquot->dq_dqb.dqb_bhardlimit == 0 && @@ -78,12 +79,13 @@ static int v1_read_dqblk(struct dquot *dquot) static int v1_commit_dqblk(struct dquot *dquot) { - short type = dquot->dq_type; + short type = dquot->dq_id.type; ssize_t ret; struct v1_disk_dqblk dqblk; v1_mem2disk_dqblk(&dqblk, &dquot->dq_dqb); - if (dquot->dq_id == 0) { + if (((type == USRQUOTA) && uid_eq(dquot->dq_id.uid, GLOBAL_ROOT_UID)) || + ((type == GRPQUOTA) && gid_eq(dquot->dq_id.gid, GLOBAL_ROOT_GID))) { dqblk.dqb_btime = sb_dqopt(dquot->dq_sb)->info[type].dqi_bgrace; dqblk.dqb_itime = @@ -93,7 +95,7 @@ static int v1_commit_dqblk(struct dquot *dquot) if (sb_dqopt(dquot->dq_sb)->files[type]) ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type, (char *)&dqblk, sizeof(struct v1_disk_dqblk), - v1_dqoff(dquot->dq_id)); + v1_dqoff(from_kqid(&init_user_ns, dquot->dq_id))); if (ret != sizeof(struct v1_disk_dqblk)) { quota_error(dquot->dq_sb, "dquota write failed"); 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) struct v2r0_disk_dqblk *d = dp; struct mem_dqblk *m = &dquot->dq_dqb; struct qtree_mem_dqinfo *info = - sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv; + sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv; d->dqb_ihardlimit = cpu_to_le32(m->dqb_ihardlimit); d->dqb_isoftlimit = cpu_to_le32(m->dqb_isoftlimit); @@ -206,7 +206,7 @@ static void v2r0_mem2diskdqb(void *dp, struct dquot *dquot) d->dqb_bsoftlimit = cpu_to_le32(v2_stoqb(m->dqb_bsoftlimit)); d->dqb_curspace = cpu_to_le64(m->dqb_curspace); d->dqb_btime = cpu_to_le64(m->dqb_btime); - d->dqb_id = cpu_to_le32(dquot->dq_id); + d->dqb_id = cpu_to_le32(from_kqid(&init_user_ns, dquot->dq_id)); if (qtree_entry_unused(info, dp)) d->dqb_itime = cpu_to_le64(1); } @@ -215,11 +215,13 @@ static int v2r0_is_id(void *dp, struct dquot *dquot) { struct v2r0_disk_dqblk *d = dp; struct qtree_mem_dqinfo *info = - sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv; + sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv; if (qtree_entry_unused(info, dp)) return 0; - return le32_to_cpu(d->dqb_id) == dquot->dq_id; + return qid_eq(make_kqid(&init_user_ns, dquot->dq_id.type, + le32_to_cpu(d->dqb_id)), + dquot->dq_id); } static void v2r1_disk2memdqb(struct dquot *dquot, void *dp) @@ -247,7 +249,7 @@ static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot) struct v2r1_disk_dqblk *d = dp; struct mem_dqblk *m = &dquot->dq_dqb; struct qtree_mem_dqinfo *info = - sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv; + sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv; d->dqb_ihardlimit = cpu_to_le64(m->dqb_ihardlimit); d->dqb_isoftlimit = cpu_to_le64(m->dqb_isoftlimit); @@ -257,7 +259,7 @@ static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot) d->dqb_bsoftlimit = cpu_to_le64(v2_stoqb(m->dqb_bsoftlimit)); d->dqb_curspace = cpu_to_le64(m->dqb_curspace); d->dqb_btime = cpu_to_le64(m->dqb_btime); - d->dqb_id = cpu_to_le32(dquot->dq_id); + d->dqb_id = cpu_to_le32(from_kqid(&init_user_ns, dquot->dq_id)); if (qtree_entry_unused(info, dp)) d->dqb_itime = cpu_to_le64(1); } @@ -266,26 +268,28 @@ static int v2r1_is_id(void *dp, struct dquot *dquot) { struct v2r1_disk_dqblk *d = dp; struct qtree_mem_dqinfo *info = - sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv; + sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv; if (qtree_entry_unused(info, dp)) return 0; - return le32_to_cpu(d->dqb_id) == dquot->dq_id; + return qid_eq(make_kqid(&init_user_ns, dquot->dq_id.type, + le32_to_cpu(d->dqb_id)), + dquot->dq_id); } static int v2_read_dquot(struct dquot *dquot) { - return qtree_read_dquot(sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv, dquot); + return qtree_read_dquot(sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv, dquot); } static int v2_write_dquot(struct dquot *dquot) { - return qtree_write_dquot(sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv, dquot); + return qtree_write_dquot(sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv, dquot); } static int v2_release_dquot(struct dquot *dquot) { - return qtree_release_dquot(sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv, dquot); + return qtree_release_dquot(sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv, dquot); } static int v2_free_file_info(struct super_block *sb, int type) |