Loading fs/ceph/dir.c +12 −15 Original line number Diff line number Diff line Loading @@ -416,9 +416,9 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx) fi->last_name = NULL; fi->next_offset = 2; } else { err = note_last_dentry(fi, rinfo->dir_dname[rinfo->dir_nr-1], rinfo->dir_dname_len[rinfo->dir_nr-1], struct ceph_mds_reply_dir_entry *rde = rinfo->dir_entries + (rinfo->dir_nr-1); err = note_last_dentry(fi, rde->name, rde->name_len, fi->next_offset + rinfo->dir_nr); if (err) return err; Loading @@ -431,23 +431,20 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx) ctx->pos = ceph_make_fpos(frag, off); while (off >= fi->offset && off - fi->offset < rinfo->dir_nr) { struct ceph_mds_reply_inode *in = rinfo->dir_in[off - fi->offset].in; struct ceph_mds_reply_dir_entry *rde = rinfo->dir_entries + (off - fi->offset); struct ceph_vino vino; ino_t ino; dout("readdir off %d (%d/%d) -> %lld '%.*s' %p\n", off, off - fi->offset, rinfo->dir_nr, ctx->pos, rinfo->dir_dname_len[off - fi->offset], rinfo->dir_dname[off - fi->offset], in); BUG_ON(!in); ftype = le32_to_cpu(in->mode) >> 12; vino.ino = le64_to_cpu(in->ino); vino.snap = le64_to_cpu(in->snapid); rde->name_len, rde->name, &rde->inode.in); BUG_ON(!rde->inode.in); ftype = le32_to_cpu(rde->inode.in->mode) >> 12; vino.ino = le64_to_cpu(rde->inode.in->ino); vino.snap = le64_to_cpu(rde->inode.in->snapid); ino = ceph_vino_to_ino(vino); if (!dir_emit(ctx, rinfo->dir_dname[off - fi->offset], rinfo->dir_dname_len[off - fi->offset], if (!dir_emit(ctx, rde->name, rde->name_len, ceph_translate_ino(inode->i_sb, ino), ftype)) { dout("filldir stopping us...\n"); return 0; Loading fs/ceph/inode.c +11 −10 Original line number Diff line number Diff line Loading @@ -1308,12 +1308,13 @@ static int readdir_prepopulate_inodes_only(struct ceph_mds_request *req, int i, err = 0; for (i = 0; i < rinfo->dir_nr; i++) { struct ceph_mds_reply_dir_entry *rde = rinfo->dir_entries + i; struct ceph_vino vino; struct inode *in; int rc; vino.ino = le64_to_cpu(rinfo->dir_in[i].in->ino); vino.snap = le64_to_cpu(rinfo->dir_in[i].in->snapid); vino.ino = le64_to_cpu(rde->inode.in->ino); vino.snap = le64_to_cpu(rde->inode.in->snapid); in = ceph_get_inode(req->r_dentry->d_sb, vino); if (IS_ERR(in)) { Loading @@ -1321,7 +1322,7 @@ static int readdir_prepopulate_inodes_only(struct ceph_mds_request *req, dout("new_inode badness got %d\n", err); 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_caps_reservation); if (rc < 0) { Loading Loading @@ -1433,14 +1434,15 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req, /* FIXME: release caps/leases if error occurs */ for (i = 0; i < rinfo->dir_nr; i++) { struct ceph_mds_reply_dir_entry *rde = rinfo->dir_entries + i; struct ceph_vino vino; dname.name = rinfo->dir_dname[i]; dname.len = rinfo->dir_dname_len[i]; dname.name = rde->name; dname.len = rde->name_len; dname.hash = full_name_hash(dname.name, dname.len); vino.ino = le64_to_cpu(rinfo->dir_in[i].in->ino); vino.snap = le64_to_cpu(rinfo->dir_in[i].in->snapid); vino.ino = le64_to_cpu(rde->inode.in->ino); vino.snap = le64_to_cpu(rde->inode.in->snapid); retry_lookup: dn = d_lookup(parent, &dname); Loading Loading @@ -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_caps_reservation); if (ret < 0) { Loading Loading @@ -1522,8 +1524,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req, di = dn->d_fsdata; di->offset = ceph_make_fpos(frag, i + req->r_readdir_offset); update_dentry_lease(dn, rinfo->dir_dlease[i], req->r_session, update_dentry_lease(dn, rde->lease, req->r_session, req->r_request_started); if (err == 0 && skipped == 0 && cache_ctl.index >= 0) { Loading fs/ceph/mds_client.c +19 −23 Original line number Diff line number Diff line Loading @@ -186,12 +186,9 @@ static int parse_reply_info_dir(void **p, void *end, if (num == 0) goto done; BUG_ON(!info->dir_in); info->dir_dname = (void *)(info->dir_in + num); info->dir_dname_len = (void *)(info->dir_dname + num); 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) { BUG_ON(!info->dir_entries); if ((unsigned long)(info->dir_entries + num) > (unsigned long)info->dir_entries + info->dir_buf_size) { pr_err("dir contents are larger than expected\n"); WARN_ON(1); goto bad; Loading @@ -199,19 +196,19 @@ static int parse_reply_info_dir(void **p, void *end, info->dir_nr = num; while (num) { struct ceph_mds_reply_dir_entry *rde = info->dir_entries + i; /* dentry */ ceph_decode_need(p, end, sizeof(u32)*2, bad); info->dir_dname_len[i] = ceph_decode_32(p); ceph_decode_need(p, end, info->dir_dname_len[i], bad); info->dir_dname[i] = *p; *p += info->dir_dname_len[i]; dout("parsed dir dname '%.*s'\n", info->dir_dname_len[i], info->dir_dname[i]); info->dir_dlease[i] = *p; rde->name_len = ceph_decode_32(p); ceph_decode_need(p, end, rde->name_len, bad); rde->name = *p; *p += rde->name_len; dout("parsed dir dname '%.*s'\n", rde->name_len, rde->name); rde->lease = *p; *p += sizeof(struct ceph_mds_reply_lease); /* 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) goto out_bad; i++; Loading Loading @@ -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) { if (!info->dir_in) if (!info->dir_entries) 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)); } Loading Loading @@ -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_mds_reply_info_parsed *rinfo = &req->r_reply_info; struct ceph_mount_options *opt = req->r_mdsc->fsc->mount_options; size_t size = sizeof(*rinfo->dir_in) + sizeof(*rinfo->dir_dname_len) + sizeof(*rinfo->dir_dname) + sizeof(*rinfo->dir_dlease); size_t size = sizeof(struct ceph_mds_reply_dir_entry); int order, num_entries; spin_lock(&ci->i_ceph_lock); Loading @@ -1668,14 +1664,14 @@ int ceph_alloc_readdir_reply_buffer(struct ceph_mds_request *req, order = get_order(size * num_entries); while (order >= 0) { rinfo->dir_in = (void*)__get_free_pages(GFP_KERNEL | rinfo->dir_entries = (void*)__get_free_pages(GFP_KERNEL | __GFP_NOWARN, order); if (rinfo->dir_in) if (rinfo->dir_entries) break; order--; } if (!rinfo->dir_in) if (!rinfo->dir_entries) return -ENOMEM; num_entries = (PAGE_SIZE << order) / size; Loading fs/ceph/mds_client.h +8 −4 Original line number Diff line number Diff line Loading @@ -47,6 +47,13 @@ struct ceph_mds_reply_info_in { 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 * either: 1) the target inode and/or its parent directory and dentry, Loading @@ -73,11 +80,8 @@ struct ceph_mds_reply_info_parsed { struct ceph_mds_reply_dirfrag *dir_dir; size_t dir_buf_size; 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; struct ceph_mds_reply_dir_entry *dir_entries; }; /* for create results */ Loading Loading
fs/ceph/dir.c +12 −15 Original line number Diff line number Diff line Loading @@ -416,9 +416,9 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx) fi->last_name = NULL; fi->next_offset = 2; } else { err = note_last_dentry(fi, rinfo->dir_dname[rinfo->dir_nr-1], rinfo->dir_dname_len[rinfo->dir_nr-1], struct ceph_mds_reply_dir_entry *rde = rinfo->dir_entries + (rinfo->dir_nr-1); err = note_last_dentry(fi, rde->name, rde->name_len, fi->next_offset + rinfo->dir_nr); if (err) return err; Loading @@ -431,23 +431,20 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx) ctx->pos = ceph_make_fpos(frag, off); while (off >= fi->offset && off - fi->offset < rinfo->dir_nr) { struct ceph_mds_reply_inode *in = rinfo->dir_in[off - fi->offset].in; struct ceph_mds_reply_dir_entry *rde = rinfo->dir_entries + (off - fi->offset); struct ceph_vino vino; ino_t ino; dout("readdir off %d (%d/%d) -> %lld '%.*s' %p\n", off, off - fi->offset, rinfo->dir_nr, ctx->pos, rinfo->dir_dname_len[off - fi->offset], rinfo->dir_dname[off - fi->offset], in); BUG_ON(!in); ftype = le32_to_cpu(in->mode) >> 12; vino.ino = le64_to_cpu(in->ino); vino.snap = le64_to_cpu(in->snapid); rde->name_len, rde->name, &rde->inode.in); BUG_ON(!rde->inode.in); ftype = le32_to_cpu(rde->inode.in->mode) >> 12; vino.ino = le64_to_cpu(rde->inode.in->ino); vino.snap = le64_to_cpu(rde->inode.in->snapid); ino = ceph_vino_to_ino(vino); if (!dir_emit(ctx, rinfo->dir_dname[off - fi->offset], rinfo->dir_dname_len[off - fi->offset], if (!dir_emit(ctx, rde->name, rde->name_len, ceph_translate_ino(inode->i_sb, ino), ftype)) { dout("filldir stopping us...\n"); return 0; Loading
fs/ceph/inode.c +11 −10 Original line number Diff line number Diff line Loading @@ -1308,12 +1308,13 @@ static int readdir_prepopulate_inodes_only(struct ceph_mds_request *req, int i, err = 0; for (i = 0; i < rinfo->dir_nr; i++) { struct ceph_mds_reply_dir_entry *rde = rinfo->dir_entries + i; struct ceph_vino vino; struct inode *in; int rc; vino.ino = le64_to_cpu(rinfo->dir_in[i].in->ino); vino.snap = le64_to_cpu(rinfo->dir_in[i].in->snapid); vino.ino = le64_to_cpu(rde->inode.in->ino); vino.snap = le64_to_cpu(rde->inode.in->snapid); in = ceph_get_inode(req->r_dentry->d_sb, vino); if (IS_ERR(in)) { Loading @@ -1321,7 +1322,7 @@ static int readdir_prepopulate_inodes_only(struct ceph_mds_request *req, dout("new_inode badness got %d\n", err); 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_caps_reservation); if (rc < 0) { Loading Loading @@ -1433,14 +1434,15 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req, /* FIXME: release caps/leases if error occurs */ for (i = 0; i < rinfo->dir_nr; i++) { struct ceph_mds_reply_dir_entry *rde = rinfo->dir_entries + i; struct ceph_vino vino; dname.name = rinfo->dir_dname[i]; dname.len = rinfo->dir_dname_len[i]; dname.name = rde->name; dname.len = rde->name_len; dname.hash = full_name_hash(dname.name, dname.len); vino.ino = le64_to_cpu(rinfo->dir_in[i].in->ino); vino.snap = le64_to_cpu(rinfo->dir_in[i].in->snapid); vino.ino = le64_to_cpu(rde->inode.in->ino); vino.snap = le64_to_cpu(rde->inode.in->snapid); retry_lookup: dn = d_lookup(parent, &dname); Loading Loading @@ -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_caps_reservation); if (ret < 0) { Loading Loading @@ -1522,8 +1524,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req, di = dn->d_fsdata; di->offset = ceph_make_fpos(frag, i + req->r_readdir_offset); update_dentry_lease(dn, rinfo->dir_dlease[i], req->r_session, update_dentry_lease(dn, rde->lease, req->r_session, req->r_request_started); if (err == 0 && skipped == 0 && cache_ctl.index >= 0) { Loading
fs/ceph/mds_client.c +19 −23 Original line number Diff line number Diff line Loading @@ -186,12 +186,9 @@ static int parse_reply_info_dir(void **p, void *end, if (num == 0) goto done; BUG_ON(!info->dir_in); info->dir_dname = (void *)(info->dir_in + num); info->dir_dname_len = (void *)(info->dir_dname + num); 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) { BUG_ON(!info->dir_entries); if ((unsigned long)(info->dir_entries + num) > (unsigned long)info->dir_entries + info->dir_buf_size) { pr_err("dir contents are larger than expected\n"); WARN_ON(1); goto bad; Loading @@ -199,19 +196,19 @@ static int parse_reply_info_dir(void **p, void *end, info->dir_nr = num; while (num) { struct ceph_mds_reply_dir_entry *rde = info->dir_entries + i; /* dentry */ ceph_decode_need(p, end, sizeof(u32)*2, bad); info->dir_dname_len[i] = ceph_decode_32(p); ceph_decode_need(p, end, info->dir_dname_len[i], bad); info->dir_dname[i] = *p; *p += info->dir_dname_len[i]; dout("parsed dir dname '%.*s'\n", info->dir_dname_len[i], info->dir_dname[i]); info->dir_dlease[i] = *p; rde->name_len = ceph_decode_32(p); ceph_decode_need(p, end, rde->name_len, bad); rde->name = *p; *p += rde->name_len; dout("parsed dir dname '%.*s'\n", rde->name_len, rde->name); rde->lease = *p; *p += sizeof(struct ceph_mds_reply_lease); /* 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) goto out_bad; i++; Loading Loading @@ -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) { if (!info->dir_in) if (!info->dir_entries) 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)); } Loading Loading @@ -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_mds_reply_info_parsed *rinfo = &req->r_reply_info; struct ceph_mount_options *opt = req->r_mdsc->fsc->mount_options; size_t size = sizeof(*rinfo->dir_in) + sizeof(*rinfo->dir_dname_len) + sizeof(*rinfo->dir_dname) + sizeof(*rinfo->dir_dlease); size_t size = sizeof(struct ceph_mds_reply_dir_entry); int order, num_entries; spin_lock(&ci->i_ceph_lock); Loading @@ -1668,14 +1664,14 @@ int ceph_alloc_readdir_reply_buffer(struct ceph_mds_request *req, order = get_order(size * num_entries); while (order >= 0) { rinfo->dir_in = (void*)__get_free_pages(GFP_KERNEL | rinfo->dir_entries = (void*)__get_free_pages(GFP_KERNEL | __GFP_NOWARN, order); if (rinfo->dir_in) if (rinfo->dir_entries) break; order--; } if (!rinfo->dir_in) if (!rinfo->dir_entries) return -ENOMEM; num_entries = (PAGE_SIZE << order) / size; Loading
fs/ceph/mds_client.h +8 −4 Original line number Diff line number Diff line Loading @@ -47,6 +47,13 @@ struct ceph_mds_reply_info_in { 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 * either: 1) the target inode and/or its parent directory and dentry, Loading @@ -73,11 +80,8 @@ struct ceph_mds_reply_info_parsed { struct ceph_mds_reply_dirfrag *dir_dir; size_t dir_buf_size; 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; struct ceph_mds_reply_dir_entry *dir_entries; }; /* for create results */ Loading