ceph: define struct for dir entry in readdir reply
This avoids defining multiple arrays for entries in readdir reply Signed-off-by: Yan, Zheng <zyan@redhat.com>
This commit is contained in:
parent
a78600e7c4
commit
2a5beea3f1
|
@ -416,9 +416,9 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
|
||||||
fi->last_name = NULL;
|
fi->last_name = NULL;
|
||||||
fi->next_offset = 2;
|
fi->next_offset = 2;
|
||||||
} else {
|
} else {
|
||||||
err = note_last_dentry(fi,
|
struct ceph_mds_reply_dir_entry *rde =
|
||||||
rinfo->dir_dname[rinfo->dir_nr-1],
|
rinfo->dir_entries + (rinfo->dir_nr-1);
|
||||||
rinfo->dir_dname_len[rinfo->dir_nr-1],
|
err = note_last_dentry(fi, rde->name, rde->name_len,
|
||||||
fi->next_offset + rinfo->dir_nr);
|
fi->next_offset + rinfo->dir_nr);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
@ -431,24 +431,21 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
|
||||||
|
|
||||||
ctx->pos = ceph_make_fpos(frag, off);
|
ctx->pos = ceph_make_fpos(frag, off);
|
||||||
while (off >= fi->offset && off - fi->offset < rinfo->dir_nr) {
|
while (off >= fi->offset && off - fi->offset < rinfo->dir_nr) {
|
||||||
struct ceph_mds_reply_inode *in =
|
struct ceph_mds_reply_dir_entry *rde =
|
||||||
rinfo->dir_in[off - fi->offset].in;
|
rinfo->dir_entries + (off - fi->offset);
|
||||||
struct ceph_vino vino;
|
struct ceph_vino vino;
|
||||||
ino_t ino;
|
ino_t ino;
|
||||||
|
|
||||||
dout("readdir off %d (%d/%d) -> %lld '%.*s' %p\n",
|
dout("readdir off %d (%d/%d) -> %lld '%.*s' %p\n",
|
||||||
off, off - fi->offset, rinfo->dir_nr, ctx->pos,
|
off, off - fi->offset, rinfo->dir_nr, ctx->pos,
|
||||||
rinfo->dir_dname_len[off - fi->offset],
|
rde->name_len, rde->name, &rde->inode.in);
|
||||||
rinfo->dir_dname[off - fi->offset], in);
|
BUG_ON(!rde->inode.in);
|
||||||
BUG_ON(!in);
|
ftype = le32_to_cpu(rde->inode.in->mode) >> 12;
|
||||||
ftype = le32_to_cpu(in->mode) >> 12;
|
vino.ino = le64_to_cpu(rde->inode.in->ino);
|
||||||
vino.ino = le64_to_cpu(in->ino);
|
vino.snap = le64_to_cpu(rde->inode.in->snapid);
|
||||||
vino.snap = le64_to_cpu(in->snapid);
|
|
||||||
ino = ceph_vino_to_ino(vino);
|
ino = ceph_vino_to_ino(vino);
|
||||||
if (!dir_emit(ctx,
|
if (!dir_emit(ctx, rde->name, rde->name_len,
|
||||||
rinfo->dir_dname[off - fi->offset],
|
ceph_translate_ino(inode->i_sb, ino), ftype)) {
|
||||||
rinfo->dir_dname_len[off - fi->offset],
|
|
||||||
ceph_translate_ino(inode->i_sb, ino), ftype)) {
|
|
||||||
dout("filldir stopping us...\n");
|
dout("filldir stopping us...\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1308,12 +1308,13 @@ static int readdir_prepopulate_inodes_only(struct ceph_mds_request *req,
|
||||||
int i, err = 0;
|
int i, err = 0;
|
||||||
|
|
||||||
for (i = 0; i < rinfo->dir_nr; i++) {
|
for (i = 0; i < rinfo->dir_nr; i++) {
|
||||||
|
struct ceph_mds_reply_dir_entry *rde = rinfo->dir_entries + i;
|
||||||
struct ceph_vino vino;
|
struct ceph_vino vino;
|
||||||
struct inode *in;
|
struct inode *in;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
vino.ino = le64_to_cpu(rinfo->dir_in[i].in->ino);
|
vino.ino = le64_to_cpu(rde->inode.in->ino);
|
||||||
vino.snap = le64_to_cpu(rinfo->dir_in[i].in->snapid);
|
vino.snap = le64_to_cpu(rde->inode.in->snapid);
|
||||||
|
|
||||||
in = ceph_get_inode(req->r_dentry->d_sb, vino);
|
in = ceph_get_inode(req->r_dentry->d_sb, vino);
|
||||||
if (IS_ERR(in)) {
|
if (IS_ERR(in)) {
|
||||||
|
@ -1321,7 +1322,7 @@ static int readdir_prepopulate_inodes_only(struct ceph_mds_request *req,
|
||||||
dout("new_inode badness got %d\n", err);
|
dout("new_inode badness got %d\n", err);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
rc = fill_inode(in, NULL, &rinfo->dir_in[i], NULL, session,
|
rc = fill_inode(in, NULL, &rde->inode, NULL, session,
|
||||||
req->r_request_started, -1,
|
req->r_request_started, -1,
|
||||||
&req->r_caps_reservation);
|
&req->r_caps_reservation);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
|
@ -1433,14 +1434,15 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
|
||||||
|
|
||||||
/* FIXME: release caps/leases if error occurs */
|
/* FIXME: release caps/leases if error occurs */
|
||||||
for (i = 0; i < rinfo->dir_nr; i++) {
|
for (i = 0; i < rinfo->dir_nr; i++) {
|
||||||
|
struct ceph_mds_reply_dir_entry *rde = rinfo->dir_entries + i;
|
||||||
struct ceph_vino vino;
|
struct ceph_vino vino;
|
||||||
|
|
||||||
dname.name = rinfo->dir_dname[i];
|
dname.name = rde->name;
|
||||||
dname.len = rinfo->dir_dname_len[i];
|
dname.len = rde->name_len;
|
||||||
dname.hash = full_name_hash(dname.name, dname.len);
|
dname.hash = full_name_hash(dname.name, dname.len);
|
||||||
|
|
||||||
vino.ino = le64_to_cpu(rinfo->dir_in[i].in->ino);
|
vino.ino = le64_to_cpu(rde->inode.in->ino);
|
||||||
vino.snap = le64_to_cpu(rinfo->dir_in[i].in->snapid);
|
vino.snap = le64_to_cpu(rde->inode.in->snapid);
|
||||||
|
|
||||||
retry_lookup:
|
retry_lookup:
|
||||||
dn = d_lookup(parent, &dname);
|
dn = d_lookup(parent, &dname);
|
||||||
|
@ -1486,7 +1488,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = fill_inode(in, NULL, &rinfo->dir_in[i], NULL, session,
|
ret = fill_inode(in, NULL, &rde->inode, NULL, session,
|
||||||
req->r_request_started, -1,
|
req->r_request_started, -1,
|
||||||
&req->r_caps_reservation);
|
&req->r_caps_reservation);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
@ -1522,8 +1524,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
|
||||||
di = dn->d_fsdata;
|
di = dn->d_fsdata;
|
||||||
di->offset = ceph_make_fpos(frag, i + req->r_readdir_offset);
|
di->offset = ceph_make_fpos(frag, i + req->r_readdir_offset);
|
||||||
|
|
||||||
update_dentry_lease(dn, rinfo->dir_dlease[i],
|
update_dentry_lease(dn, rde->lease, req->r_session,
|
||||||
req->r_session,
|
|
||||||
req->r_request_started);
|
req->r_request_started);
|
||||||
|
|
||||||
if (err == 0 && skipped == 0 && cache_ctl.index >= 0) {
|
if (err == 0 && skipped == 0 && cache_ctl.index >= 0) {
|
||||||
|
|
|
@ -186,12 +186,9 @@ static int parse_reply_info_dir(void **p, void *end,
|
||||||
if (num == 0)
|
if (num == 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
BUG_ON(!info->dir_in);
|
BUG_ON(!info->dir_entries);
|
||||||
info->dir_dname = (void *)(info->dir_in + num);
|
if ((unsigned long)(info->dir_entries + num) >
|
||||||
info->dir_dname_len = (void *)(info->dir_dname + num);
|
(unsigned long)info->dir_entries + info->dir_buf_size) {
|
||||||
info->dir_dlease = (void *)(info->dir_dname_len + num);
|
|
||||||
if ((unsigned long)(info->dir_dlease + num) >
|
|
||||||
(unsigned long)info->dir_in + info->dir_buf_size) {
|
|
||||||
pr_err("dir contents are larger than expected\n");
|
pr_err("dir contents are larger than expected\n");
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
goto bad;
|
goto bad;
|
||||||
|
@ -199,19 +196,19 @@ static int parse_reply_info_dir(void **p, void *end,
|
||||||
|
|
||||||
info->dir_nr = num;
|
info->dir_nr = num;
|
||||||
while (num) {
|
while (num) {
|
||||||
|
struct ceph_mds_reply_dir_entry *rde = info->dir_entries + i;
|
||||||
/* dentry */
|
/* dentry */
|
||||||
ceph_decode_need(p, end, sizeof(u32)*2, bad);
|
ceph_decode_need(p, end, sizeof(u32)*2, bad);
|
||||||
info->dir_dname_len[i] = ceph_decode_32(p);
|
rde->name_len = ceph_decode_32(p);
|
||||||
ceph_decode_need(p, end, info->dir_dname_len[i], bad);
|
ceph_decode_need(p, end, rde->name_len, bad);
|
||||||
info->dir_dname[i] = *p;
|
rde->name = *p;
|
||||||
*p += info->dir_dname_len[i];
|
*p += rde->name_len;
|
||||||
dout("parsed dir dname '%.*s'\n", info->dir_dname_len[i],
|
dout("parsed dir dname '%.*s'\n", rde->name_len, rde->name);
|
||||||
info->dir_dname[i]);
|
rde->lease = *p;
|
||||||
info->dir_dlease[i] = *p;
|
|
||||||
*p += sizeof(struct ceph_mds_reply_lease);
|
*p += sizeof(struct ceph_mds_reply_lease);
|
||||||
|
|
||||||
/* inode */
|
/* inode */
|
||||||
err = parse_reply_info_in(p, end, &info->dir_in[i], features);
|
err = parse_reply_info_in(p, end, &rde->inode, features);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out_bad;
|
goto out_bad;
|
||||||
i++;
|
i++;
|
||||||
|
@ -345,9 +342,9 @@ static int parse_reply_info(struct ceph_msg *msg,
|
||||||
|
|
||||||
static void destroy_reply_info(struct ceph_mds_reply_info_parsed *info)
|
static void destroy_reply_info(struct ceph_mds_reply_info_parsed *info)
|
||||||
{
|
{
|
||||||
if (!info->dir_in)
|
if (!info->dir_entries)
|
||||||
return;
|
return;
|
||||||
free_pages((unsigned long)info->dir_in, get_order(info->dir_buf_size));
|
free_pages((unsigned long)info->dir_entries, get_order(info->dir_buf_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1656,8 +1653,7 @@ int ceph_alloc_readdir_reply_buffer(struct ceph_mds_request *req,
|
||||||
struct ceph_inode_info *ci = ceph_inode(dir);
|
struct ceph_inode_info *ci = ceph_inode(dir);
|
||||||
struct ceph_mds_reply_info_parsed *rinfo = &req->r_reply_info;
|
struct ceph_mds_reply_info_parsed *rinfo = &req->r_reply_info;
|
||||||
struct ceph_mount_options *opt = req->r_mdsc->fsc->mount_options;
|
struct ceph_mount_options *opt = req->r_mdsc->fsc->mount_options;
|
||||||
size_t size = sizeof(*rinfo->dir_in) + sizeof(*rinfo->dir_dname_len) +
|
size_t size = sizeof(struct ceph_mds_reply_dir_entry);
|
||||||
sizeof(*rinfo->dir_dname) + sizeof(*rinfo->dir_dlease);
|
|
||||||
int order, num_entries;
|
int order, num_entries;
|
||||||
|
|
||||||
spin_lock(&ci->i_ceph_lock);
|
spin_lock(&ci->i_ceph_lock);
|
||||||
|
@ -1668,14 +1664,14 @@ int ceph_alloc_readdir_reply_buffer(struct ceph_mds_request *req,
|
||||||
|
|
||||||
order = get_order(size * num_entries);
|
order = get_order(size * num_entries);
|
||||||
while (order >= 0) {
|
while (order >= 0) {
|
||||||
rinfo->dir_in = (void*)__get_free_pages(GFP_KERNEL |
|
rinfo->dir_entries = (void*)__get_free_pages(GFP_KERNEL |
|
||||||
__GFP_NOWARN,
|
__GFP_NOWARN,
|
||||||
order);
|
order);
|
||||||
if (rinfo->dir_in)
|
if (rinfo->dir_entries)
|
||||||
break;
|
break;
|
||||||
order--;
|
order--;
|
||||||
}
|
}
|
||||||
if (!rinfo->dir_in)
|
if (!rinfo->dir_entries)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
num_entries = (PAGE_SIZE << order) / size;
|
num_entries = (PAGE_SIZE << order) / size;
|
||||||
|
|
|
@ -47,6 +47,13 @@ struct ceph_mds_reply_info_in {
|
||||||
u32 pool_ns_len;
|
u32 pool_ns_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ceph_mds_reply_dir_entry {
|
||||||
|
char *name;
|
||||||
|
u32 name_len;
|
||||||
|
struct ceph_mds_reply_lease *lease;
|
||||||
|
struct ceph_mds_reply_info_in inode;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* parsed info about an mds reply, including information about
|
* parsed info about an mds reply, including information about
|
||||||
* either: 1) the target inode and/or its parent directory and dentry,
|
* either: 1) the target inode and/or its parent directory and dentry,
|
||||||
|
@ -73,11 +80,8 @@ struct ceph_mds_reply_info_parsed {
|
||||||
struct ceph_mds_reply_dirfrag *dir_dir;
|
struct ceph_mds_reply_dirfrag *dir_dir;
|
||||||
size_t dir_buf_size;
|
size_t dir_buf_size;
|
||||||
int dir_nr;
|
int dir_nr;
|
||||||
char **dir_dname;
|
|
||||||
u32 *dir_dname_len;
|
|
||||||
struct ceph_mds_reply_lease **dir_dlease;
|
|
||||||
struct ceph_mds_reply_info_in *dir_in;
|
|
||||||
u8 dir_complete, dir_end;
|
u8 dir_complete, dir_end;
|
||||||
|
struct ceph_mds_reply_dir_entry *dir_entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* for create results */
|
/* for create results */
|
||||||
|
|
Loading…
Reference in New Issue