Commit 823eded0 authored by Seth Forshee's avatar Seth Forshee

quota: Convert ids relative to s_user_ns

When dealing with mounts from user namespaces quota user ids must
be translated relative to s_user_ns, especially when they will be
stored on disk. For purposes of the in-kernel hash table using
init_user_ns is still okay and may help reduce hash collisions,
so continue using init_user_ns there.

These changes introduce the possibility that the conversion
operations in struct qtree_fmt_operations could fail if an id
cannot be legitimately converted. Change these operations to
return int rather than void, and update the callers to handle
failures.
Signed-off-by: default avatarSeth Forshee <seth.forshee@canonical.com>
parent a377566c
...@@ -66,7 +66,7 @@ ...@@ -66,7 +66,7 @@
static void qsync_work_fn(struct work_struct *work); static void qsync_work_fn(struct work_struct *work);
static void ocfs2_global_disk2memdqb(struct dquot *dquot, void *dp) static int ocfs2_global_disk2memdqb(struct dquot *dquot, void *dp)
{ {
struct ocfs2_global_disk_dqblk *d = dp; struct ocfs2_global_disk_dqblk *d = dp;
struct mem_dqblk *m = &dquot->dq_dqb; struct mem_dqblk *m = &dquot->dq_dqb;
...@@ -89,9 +89,10 @@ static void ocfs2_global_disk2memdqb(struct dquot *dquot, void *dp) ...@@ -89,9 +89,10 @@ static void ocfs2_global_disk2memdqb(struct dquot *dquot, void *dp)
if (!test_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags)) if (!test_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags))
m->dqb_itime = le64_to_cpu(d->dqb_itime); m->dqb_itime = le64_to_cpu(d->dqb_itime);
OCFS2_DQUOT(dquot)->dq_use_count = le32_to_cpu(d->dqb_use_count); OCFS2_DQUOT(dquot)->dq_use_count = le32_to_cpu(d->dqb_use_count);
return 0;
} }
static void ocfs2_global_mem2diskdqb(void *dp, struct dquot *dquot) static int ocfs2_global_mem2diskdqb(void *dp, struct dquot *dquot)
{ {
struct ocfs2_global_disk_dqblk *d = dp; struct ocfs2_global_disk_dqblk *d = dp;
struct mem_dqblk *m = &dquot->dq_dqb; struct mem_dqblk *m = &dquot->dq_dqb;
...@@ -107,6 +108,7 @@ static void ocfs2_global_mem2diskdqb(void *dp, struct dquot *dquot) ...@@ -107,6 +108,7 @@ static void ocfs2_global_mem2diskdqb(void *dp, struct dquot *dquot)
d->dqb_btime = cpu_to_le64(m->dqb_btime); d->dqb_btime = cpu_to_le64(m->dqb_btime);
d->dqb_itime = cpu_to_le64(m->dqb_itime); d->dqb_itime = cpu_to_le64(m->dqb_itime);
d->dqb_pad1 = d->dqb_pad2 = 0; d->dqb_pad1 = d->dqb_pad2 = 0;
return 0;
} }
static int ocfs2_global_is_id(void *dp, struct dquot *dquot) static int ocfs2_global_is_id(void *dp, struct dquot *dquot)
......
...@@ -741,7 +741,7 @@ void dqput(struct dquot *dquot) ...@@ -741,7 +741,7 @@ void dqput(struct dquot *dquot)
if (!atomic_read(&dquot->dq_count)) { if (!atomic_read(&dquot->dq_count)) {
quota_error(dquot->dq_sb, "trying to free free dquot of %s %d", quota_error(dquot->dq_sb, "trying to free free dquot of %s %d",
quotatypes[dquot->dq_id.type], quotatypes[dquot->dq_id.type],
from_kqid(&init_user_ns, dquot->dq_id)); from_kqid(dquot->dq_sb->s_user_ns, dquot->dq_id));
BUG(); BUG();
} }
#endif #endif
......
...@@ -25,8 +25,10 @@ MODULE_LICENSE("GPL"); ...@@ -25,8 +25,10 @@ MODULE_LICENSE("GPL");
static int get_index(struct qtree_mem_dqinfo *info, struct kqid qid, int depth) static int get_index(struct qtree_mem_dqinfo *info, struct kqid qid, int depth)
{ {
unsigned int epb = info->dqi_usable_bs >> 2; unsigned int epb = info->dqi_usable_bs >> 2;
qid_t id = from_kqid(&init_user_ns, qid); qid_t id = from_kqid(info->dqi_sb->s_user_ns, qid);
if (id == (qid_t)-1)
return -EOVERFLOW;
depth = info->dqi_qtree_depth - depth - 1; depth = info->dqi_qtree_depth - depth - 1;
while (depth--) while (depth--)
id /= epb; id /= epb;
...@@ -292,7 +294,7 @@ static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, ...@@ -292,7 +294,7 @@ static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,
uint *treeblk, int depth) uint *treeblk, int depth)
{ {
char *buf = getdqbuf(info->dqi_usable_bs); char *buf = getdqbuf(info->dqi_usable_bs);
int ret = 0, newson = 0, newact = 0; int ret = 0, newson = 0, newact = 0, index;
__le32 *ref; __le32 *ref;
uint newblk; uint newblk;
...@@ -314,7 +316,12 @@ static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, ...@@ -314,7 +316,12 @@ static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,
} }
} }
ref = (__le32 *)buf; ref = (__le32 *)buf;
newblk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]); index = get_index(info, dquot->dq_id, depth);
if (index < 0) {
ret = index;
goto out_buf;
}
newblk = le32_to_cpu(ref[index]);
if (!newblk) if (!newblk)
newson = 1; newson = 1;
if (depth == info->dqi_qtree_depth - 1) { if (depth == info->dqi_qtree_depth - 1) {
...@@ -322,8 +329,7 @@ static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, ...@@ -322,8 +329,7 @@ static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,
if (newblk) { if (newblk) {
quota_error(dquot->dq_sb, "Inserting already present " quota_error(dquot->dq_sb, "Inserting already present "
"quota entry (block %u)", "quota entry (block %u)",
le32_to_cpu(ref[get_index(info, le32_to_cpu(ref[index]));
dquot->dq_id, depth)]));
ret = -EIO; ret = -EIO;
goto out_buf; goto out_buf;
} }
...@@ -333,8 +339,7 @@ static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, ...@@ -333,8 +339,7 @@ static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,
ret = do_insert_tree(info, dquot, &newblk, depth+1); ret = do_insert_tree(info, dquot, &newblk, depth+1);
} }
if (newson && ret >= 0) { if (newson && ret >= 0) {
ref[get_index(info, dquot->dq_id, depth)] = ref[index] = cpu_to_le32(newblk);
cpu_to_le32(newblk);
ret = write_blk(info, *treeblk, buf); ret = write_blk(info, *treeblk, buf);
} else if (newact && ret < 0) { } else if (newact && ret < 0) {
put_free_dqblk(info, buf, *treeblk); put_free_dqblk(info, buf, *treeblk);
...@@ -384,8 +389,10 @@ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) ...@@ -384,8 +389,10 @@ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
} }
} }
spin_lock(&dq_data_lock); spin_lock(&dq_data_lock);
info->dqi_ops->mem2disk_dqblk(ddquot, dquot); ret = info->dqi_ops->mem2disk_dqblk(ddquot, dquot);
spin_unlock(&dq_data_lock); spin_unlock(&dq_data_lock);
if (ret)
goto out_free;
ret = sb->s_op->quota_write(sb, type, ddquot, info->dqi_entry_size, ret = sb->s_op->quota_write(sb, type, ddquot, info->dqi_entry_size,
dquot->dq_off); dquot->dq_off);
if (ret != info->dqi_entry_size) { if (ret != info->dqi_entry_size) {
...@@ -396,8 +403,9 @@ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) ...@@ -396,8 +403,9 @@ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
ret = 0; ret = 0;
} }
dqstats_inc(DQST_WRITES); dqstats_inc(DQST_WRITES);
kfree(ddquot);
out_free:
kfree(ddquot);
return ret; return ret;
} }
EXPORT_SYMBOL(qtree_write_dquot); EXPORT_SYMBOL(qtree_write_dquot);
...@@ -468,7 +476,7 @@ static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, ...@@ -468,7 +476,7 @@ static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,
uint *blk, int depth) uint *blk, int depth)
{ {
char *buf = getdqbuf(info->dqi_usable_bs); char *buf = getdqbuf(info->dqi_usable_bs);
int ret = 0; int ret = 0, index;
uint newblk; uint newblk;
__le32 *ref = (__le32 *)buf; __le32 *ref = (__le32 *)buf;
...@@ -480,7 +488,12 @@ static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, ...@@ -480,7 +488,12 @@ static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,
*blk); *blk);
goto out_buf; goto out_buf;
} }
newblk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]); index = get_index(info, dquot->dq_id, depth);
if (index < 0) {
ret = index;
goto out_buf;
}
newblk = le32_to_cpu(ref[index]);
if (depth == info->dqi_qtree_depth - 1) { if (depth == info->dqi_qtree_depth - 1) {
ret = free_dqentry(info, dquot, newblk); ret = free_dqentry(info, dquot, newblk);
newblk = 0; newblk = 0;
...@@ -489,7 +502,7 @@ static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, ...@@ -489,7 +502,7 @@ static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,
} }
if (ret >= 0 && !newblk) { if (ret >= 0 && !newblk) {
int i; int i;
ref[get_index(info, dquot->dq_id, depth)] = cpu_to_le32(0); ref[index] = cpu_to_le32(0);
/* Block got empty? */ /* Block got empty? */
for (i = 0; i < (info->dqi_usable_bs >> 2) && !ref[i]; i++) for (i = 0; i < (info->dqi_usable_bs >> 2) && !ref[i]; i++)
; ;
...@@ -548,7 +561,7 @@ static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info, ...@@ -548,7 +561,7 @@ static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info,
if (i == qtree_dqstr_in_blk(info)) { if (i == qtree_dqstr_in_blk(info)) {
quota_error(dquot->dq_sb, quota_error(dquot->dq_sb,
"Quota for id %u referenced but not present", "Quota for id %u referenced but not present",
from_kqid(&init_user_ns, dquot->dq_id)); from_kqid(dquot->dq_sb->s_user_ns, dquot->dq_id));
ret = -EIO; ret = -EIO;
goto out_buf; goto out_buf;
} else { } else {
...@@ -565,7 +578,7 @@ static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info, ...@@ -565,7 +578,7 @@ static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info,
struct dquot *dquot, uint blk, int depth) struct dquot *dquot, uint blk, int depth)
{ {
char *buf = getdqbuf(info->dqi_usable_bs); char *buf = getdqbuf(info->dqi_usable_bs);
loff_t ret = 0; loff_t ret = 0, index;
__le32 *ref = (__le32 *)buf; __le32 *ref = (__le32 *)buf;
if (!buf) if (!buf)
...@@ -577,7 +590,12 @@ static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info, ...@@ -577,7 +590,12 @@ static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info,
goto out_buf; goto out_buf;
} }
ret = 0; ret = 0;
blk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]); index = get_index(info, dquot->dq_id, depth);
if (index < 0) {
ret = index;
goto out_buf;
}
blk = le32_to_cpu(ref[index]);
if (!blk) /* No reference? */ if (!blk) /* No reference? */
goto out_buf; goto out_buf;
if (depth < info->dqi_qtree_depth - 1) if (depth < info->dqi_qtree_depth - 1)
...@@ -602,7 +620,7 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) ...@@ -602,7 +620,7 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
struct super_block *sb = dquot->dq_sb; struct super_block *sb = dquot->dq_sb;
loff_t offset; loff_t offset;
char *ddquot; char *ddquot;
int ret = 0; int ret = 0, err;
#ifdef __QUOTA_QT_PARANOIA #ifdef __QUOTA_QT_PARANOIA
/* Invalidated quota? */ /* Invalidated quota? */
...@@ -618,7 +636,7 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) ...@@ -618,7 +636,7 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
if (offset < 0) if (offset < 0)
quota_error(sb,"Can't read quota structure " quota_error(sb,"Can't read quota structure "
"for id %u", "for id %u",
from_kqid(&init_user_ns, from_kqid(sb->s_user_ns,
dquot->dq_id)); dquot->dq_id));
dquot->dq_off = 0; dquot->dq_off = 0;
set_bit(DQ_FAKE_B, &dquot->dq_flags); set_bit(DQ_FAKE_B, &dquot->dq_flags);
...@@ -637,15 +655,17 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) ...@@ -637,15 +655,17 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
if (ret >= 0) if (ret >= 0)
ret = -EIO; ret = -EIO;
quota_error(sb, "Error while reading quota structure for id %u", quota_error(sb, "Error while reading quota structure for id %u",
from_kqid(&init_user_ns, dquot->dq_id)); from_kqid(sb->s_user_ns, dquot->dq_id));
set_bit(DQ_FAKE_B, &dquot->dq_flags); set_bit(DQ_FAKE_B, &dquot->dq_flags);
memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk)); memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk));
kfree(ddquot); kfree(ddquot);
goto out; goto out;
} }
spin_lock(&dq_data_lock); spin_lock(&dq_data_lock);
info->dqi_ops->disk2mem_dqblk(dquot, ddquot); err = info->dqi_ops->disk2mem_dqblk(dquot, ddquot);
if (!dquot->dq_dqb.dqb_bhardlimit && if (err)
ret = err;
else if (!dquot->dq_dqb.dqb_bhardlimit &&
!dquot->dq_dqb.dqb_bsoftlimit && !dquot->dq_dqb.dqb_bsoftlimit &&
!dquot->dq_dqb.dqb_ihardlimit && !dquot->dq_dqb.dqb_ihardlimit &&
!dquot->dq_dqb.dqb_isoftlimit) !dquot->dq_dqb.dqb_isoftlimit)
......
...@@ -56,15 +56,20 @@ static int v1_read_dqblk(struct dquot *dquot) ...@@ -56,15 +56,20 @@ static int v1_read_dqblk(struct dquot *dquot)
{ {
int type = dquot->dq_id.type; int type = dquot->dq_id.type;
struct v1_disk_dqblk dqblk; struct v1_disk_dqblk dqblk;
qid_t qid;
if (!sb_dqopt(dquot->dq_sb)->files[type]) if (!sb_dqopt(dquot->dq_sb)->files[type])
return -EINVAL; return -EINVAL;
qid = from_kqid(dquot->dq_sb->s_user_ns, dquot->dq_id);
if (qid == (qid_t)-1)
return -EOVERFLOW;
/* Set structure to 0s in case read fails/is after end of file */ /* Set structure to 0s in case read fails/is after end of file */
memset(&dqblk, 0, sizeof(struct v1_disk_dqblk)); memset(&dqblk, 0, sizeof(struct v1_disk_dqblk));
dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type, (char *)&dqblk, dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type, (char *)&dqblk,
sizeof(struct v1_disk_dqblk), sizeof(struct v1_disk_dqblk),
v1_dqoff(from_kqid(&init_user_ns, dquot->dq_id))); v1_dqoff(qid));
v1_disk2mem_dqblk(&dquot->dq_dqb, &dqblk); v1_disk2mem_dqblk(&dquot->dq_dqb, &dqblk);
if (dquot->dq_dqb.dqb_bhardlimit == 0 && if (dquot->dq_dqb.dqb_bhardlimit == 0 &&
...@@ -82,6 +87,10 @@ static int v1_commit_dqblk(struct dquot *dquot) ...@@ -82,6 +87,10 @@ static int v1_commit_dqblk(struct dquot *dquot)
short type = dquot->dq_id.type; short type = dquot->dq_id.type;
ssize_t ret; ssize_t ret;
struct v1_disk_dqblk dqblk; struct v1_disk_dqblk dqblk;
qid_t qid = from_kqid(dquot->dq_sb->s_user_ns, dquot->dq_id);
if (qid == (qid_t)-1)
return -EOVERFLOW;
v1_mem2disk_dqblk(&dqblk, &dquot->dq_dqb); v1_mem2disk_dqblk(&dqblk, &dquot->dq_dqb);
if (((type == USRQUOTA) && uid_eq(dquot->dq_id.uid, GLOBAL_ROOT_UID)) || if (((type == USRQUOTA) && uid_eq(dquot->dq_id.uid, GLOBAL_ROOT_UID)) ||
...@@ -95,7 +104,7 @@ static int v1_commit_dqblk(struct dquot *dquot) ...@@ -95,7 +104,7 @@ static int v1_commit_dqblk(struct dquot *dquot)
if (sb_dqopt(dquot->dq_sb)->files[type]) if (sb_dqopt(dquot->dq_sb)->files[type])
ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type, ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type,
(char *)&dqblk, sizeof(struct v1_disk_dqblk), (char *)&dqblk, sizeof(struct v1_disk_dqblk),
v1_dqoff(from_kqid(&init_user_ns, dquot->dq_id))); v1_dqoff(qid));
if (ret != sizeof(struct v1_disk_dqblk)) { if (ret != sizeof(struct v1_disk_dqblk)) {
quota_error(dquot->dq_sb, "dquota write failed"); quota_error(dquot->dq_sb, "dquota write failed");
if (ret >= 0) if (ret >= 0)
......
...@@ -23,11 +23,11 @@ MODULE_LICENSE("GPL"); ...@@ -23,11 +23,11 @@ MODULE_LICENSE("GPL");
#define __QUOTA_V2_PARANOIA #define __QUOTA_V2_PARANOIA
static void v2r0_mem2diskdqb(void *dp, struct dquot *dquot); static int v2r0_mem2diskdqb(void *dp, struct dquot *dquot);
static void v2r0_disk2memdqb(struct dquot *dquot, void *dp); static int v2r0_disk2memdqb(struct dquot *dquot, void *dp);
static int v2r0_is_id(void *dp, struct dquot *dquot); static int v2r0_is_id(void *dp, struct dquot *dquot);
static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot); static int v2r1_mem2diskdqb(void *dp, struct dquot *dquot);
static void v2r1_disk2memdqb(struct dquot *dquot, void *dp); static int v2r1_disk2memdqb(struct dquot *dquot, void *dp);
static int v2r1_is_id(void *dp, struct dquot *dquot); static int v2r1_is_id(void *dp, struct dquot *dquot);
static struct qtree_fmt_operations v2r0_qtree_ops = { static struct qtree_fmt_operations v2r0_qtree_ops = {
...@@ -177,7 +177,7 @@ static int v2_write_file_info(struct super_block *sb, int type) ...@@ -177,7 +177,7 @@ static int v2_write_file_info(struct super_block *sb, int type)
return 0; return 0;
} }
static void v2r0_disk2memdqb(struct dquot *dquot, void *dp) static int v2r0_disk2memdqb(struct dquot *dquot, void *dp)
{ {
struct v2r0_disk_dqblk *d = dp, empty; struct v2r0_disk_dqblk *d = dp, empty;
struct mem_dqblk *m = &dquot->dq_dqb; struct mem_dqblk *m = &dquot->dq_dqb;
...@@ -195,14 +195,19 @@ static void v2r0_disk2memdqb(struct dquot *dquot, void *dp) ...@@ -195,14 +195,19 @@ static void v2r0_disk2memdqb(struct dquot *dquot, void *dp)
empty.dqb_itime = cpu_to_le64(1); empty.dqb_itime = cpu_to_le64(1);
if (!memcmp(&empty, dp, sizeof(struct v2r0_disk_dqblk))) if (!memcmp(&empty, dp, sizeof(struct v2r0_disk_dqblk)))
m->dqb_itime = 0; m->dqb_itime = 0;
return 0;
} }
static void v2r0_mem2diskdqb(void *dp, struct dquot *dquot) static int v2r0_mem2diskdqb(void *dp, struct dquot *dquot)
{ {
struct v2r0_disk_dqblk *d = dp; struct v2r0_disk_dqblk *d = dp;
struct mem_dqblk *m = &dquot->dq_dqb; struct mem_dqblk *m = &dquot->dq_dqb;
struct qtree_mem_dqinfo *info = struct qtree_mem_dqinfo *info =
sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv; sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv;
qid_t qid = from_kqid(dquot->dq_sb->s_user_ns, dquot->dq_id);
if (qid == (qid_t)-1)
return -EOVERFLOW;
d->dqb_ihardlimit = cpu_to_le32(m->dqb_ihardlimit); d->dqb_ihardlimit = cpu_to_le32(m->dqb_ihardlimit);
d->dqb_isoftlimit = cpu_to_le32(m->dqb_isoftlimit); d->dqb_isoftlimit = cpu_to_le32(m->dqb_isoftlimit);
...@@ -212,9 +217,10 @@ static void v2r0_mem2diskdqb(void *dp, struct dquot *dquot) ...@@ -212,9 +217,10 @@ static void v2r0_mem2diskdqb(void *dp, struct dquot *dquot)
d->dqb_bsoftlimit = cpu_to_le32(v2_stoqb(m->dqb_bsoftlimit)); d->dqb_bsoftlimit = cpu_to_le32(v2_stoqb(m->dqb_bsoftlimit));
d->dqb_curspace = cpu_to_le64(m->dqb_curspace); d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
d->dqb_btime = cpu_to_le64(m->dqb_btime); d->dqb_btime = cpu_to_le64(m->dqb_btime);
d->dqb_id = cpu_to_le32(from_kqid(&init_user_ns, dquot->dq_id)); d->dqb_id = cpu_to_le32(qid);
if (qtree_entry_unused(info, dp)) if (qtree_entry_unused(info, dp))
d->dqb_itime = cpu_to_le64(1); d->dqb_itime = cpu_to_le64(1);
return 0;
} }
static int v2r0_is_id(void *dp, struct dquot *dquot) static int v2r0_is_id(void *dp, struct dquot *dquot)
...@@ -222,15 +228,18 @@ static int v2r0_is_id(void *dp, struct dquot *dquot) ...@@ -222,15 +228,18 @@ static int v2r0_is_id(void *dp, struct dquot *dquot)
struct v2r0_disk_dqblk *d = dp; struct v2r0_disk_dqblk *d = dp;
struct qtree_mem_dqinfo *info = struct qtree_mem_dqinfo *info =
sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv; sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv;
struct kqid qid;
if (qtree_entry_unused(info, dp)) if (qtree_entry_unused(info, dp))
return 0; return 0;
return qid_eq(make_kqid(&init_user_ns, dquot->dq_id.type, qid = make_kqid(dquot->dq_sb->s_user_ns, dquot->dq_id.type,
le32_to_cpu(d->dqb_id)), le32_to_cpu(d->dqb_id));
dquot->dq_id); if (!qid_valid(qid))
return 0;
return qid_eq(qid, dquot->dq_id);
} }
static void v2r1_disk2memdqb(struct dquot *dquot, void *dp) static int v2r1_disk2memdqb(struct dquot *dquot, void *dp)
{ {
struct v2r1_disk_dqblk *d = dp, empty; struct v2r1_disk_dqblk *d = dp, empty;
struct mem_dqblk *m = &dquot->dq_dqb; struct mem_dqblk *m = &dquot->dq_dqb;
...@@ -248,14 +257,19 @@ static void v2r1_disk2memdqb(struct dquot *dquot, void *dp) ...@@ -248,14 +257,19 @@ static void v2r1_disk2memdqb(struct dquot *dquot, void *dp)
empty.dqb_itime = cpu_to_le64(1); empty.dqb_itime = cpu_to_le64(1);
if (!memcmp(&empty, dp, sizeof(struct v2r1_disk_dqblk))) if (!memcmp(&empty, dp, sizeof(struct v2r1_disk_dqblk)))
m->dqb_itime = 0; m->dqb_itime = 0;
return 0;
} }
static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot) static int v2r1_mem2diskdqb(void *dp, struct dquot *dquot)
{ {
struct v2r1_disk_dqblk *d = dp; struct v2r1_disk_dqblk *d = dp;
struct mem_dqblk *m = &dquot->dq_dqb; struct mem_dqblk *m = &dquot->dq_dqb;
struct qtree_mem_dqinfo *info = struct qtree_mem_dqinfo *info =
sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv; sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv;
qid_t qid = from_kqid(dquot->dq_sb->s_user_ns, dquot->dq_id);
if (qid == (qid_t)-1)
return -EOVERFLOW;
d->dqb_ihardlimit = cpu_to_le64(m->dqb_ihardlimit); d->dqb_ihardlimit = cpu_to_le64(m->dqb_ihardlimit);
d->dqb_isoftlimit = cpu_to_le64(m->dqb_isoftlimit); d->dqb_isoftlimit = cpu_to_le64(m->dqb_isoftlimit);
...@@ -265,9 +279,10 @@ static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot) ...@@ -265,9 +279,10 @@ static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot)
d->dqb_bsoftlimit = cpu_to_le64(v2_stoqb(m->dqb_bsoftlimit)); d->dqb_bsoftlimit = cpu_to_le64(v2_stoqb(m->dqb_bsoftlimit));
d->dqb_curspace = cpu_to_le64(m->dqb_curspace); d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
d->dqb_btime = cpu_to_le64(m->dqb_btime); d->dqb_btime = cpu_to_le64(m->dqb_btime);
d->dqb_id = cpu_to_le32(from_kqid(&init_user_ns, dquot->dq_id)); d->dqb_id = cpu_to_le32(qid);
if (qtree_entry_unused(info, dp)) if (qtree_entry_unused(info, dp))
d->dqb_itime = cpu_to_le64(1); d->dqb_itime = cpu_to_le64(1);
return 0;
} }
static int v2r1_is_id(void *dp, struct dquot *dquot) static int v2r1_is_id(void *dp, struct dquot *dquot)
...@@ -278,7 +293,7 @@ static int v2r1_is_id(void *dp, struct dquot *dquot) ...@@ -278,7 +293,7 @@ static int v2r1_is_id(void *dp, struct dquot *dquot)
if (qtree_entry_unused(info, dp)) if (qtree_entry_unused(info, dp))
return 0; return 0;
return qid_eq(make_kqid(&init_user_ns, dquot->dq_id.type, return qid_eq(make_kqid(dquot->dq_sb->s_user_ns, dquot->dq_id.type,
le32_to_cpu(d->dqb_id)), le32_to_cpu(d->dqb_id)),
dquot->dq_id); dquot->dq_id);
} }
......
...@@ -18,8 +18,8 @@ struct dquot; ...@@ -18,8 +18,8 @@ struct dquot;
/* Operations */ /* Operations */
struct qtree_fmt_operations { struct qtree_fmt_operations {
void (*mem2disk_dqblk)(void *disk, struct dquot *dquot); /* Convert given entry from in memory format to disk one */ int (*mem2disk_dqblk)(void *disk, struct dquot *dquot); /* Convert given entry from in memory format to disk one */
void (*disk2mem_dqblk)(struct dquot *dquot, void *disk); /* Convert given entry from disk format to in memory one */ int (*disk2mem_dqblk)(struct dquot *dquot, void *disk); /* Convert given entry from disk format to in memory one */
int (*is_id)(void *disk, struct dquot *dquot); /* Is this structure for given id? */ int (*is_id)(void *disk, struct dquot *dquot); /* Is this structure for given id? */
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment