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:
Yan, Zheng 2016-04-28 09:37:39 +08:00 committed by Ilya Dryomov
parent a78600e7c4
commit 2a5beea3f1
4 changed files with 50 additions and 52 deletions

View File

@ -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;
} }

View File

@ -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) {

View File

@ -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;

View File

@ -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 */