Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2a5beea3 authored by Yan, Zheng's avatar Yan, Zheng Committed by Ilya Dryomov
Browse files

ceph: define struct for dir entry in readdir reply



This avoids defining multiple arrays for entries in readdir reply

Signed-off-by: default avatarYan, Zheng <zyan@redhat.com>
parent a78600e7
Loading
Loading
Loading
Loading
+12 −15
Original line number Diff line number Diff line
@@ -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;
@@ -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;
+11 −10
Original line number Diff line number Diff line
@@ -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)) {
@@ -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) {
@@ -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);
@@ -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) {
@@ -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) {
+19 −23
Original line number Diff line number Diff line
@@ -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;
@@ -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++;
@@ -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));
}


@@ -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);
@@ -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;
+8 −4
Original line number Diff line number Diff line
@@ -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,
@@ -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 */