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

Commit 25933abd authored by Herb Shiu's avatar Herb Shiu Committed by Sage Weil
Browse files

ceph: Handle file locks in replies from the MDS.



Previously the kernel client incorrectly assumed everything was a directory.

Signed-off-by: default avatarHerb Shiu <herb_shiu@tcloudcomputing.com>
Acked-by: default avatarGreg Farnum <gregf@hq.newdream.net>
Signed-off-by: default avatarSage Weil <sage@newdream.net>
parent 884ea892
Loading
Loading
Loading
Loading
+37 −4
Original line number Diff line number Diff line
@@ -201,6 +201,38 @@ out_bad:
	return err;
}

/*
 * parse fcntl F_GETLK results
 */
static int parse_reply_info_filelock(void **p, void *end,
                struct ceph_mds_reply_info_parsed *info)
{
	if (*p + sizeof(*info->filelock_reply) > end)
		goto bad;

	info->filelock_reply = *p;
	*p += sizeof(*info->filelock_reply);

	if (unlikely(*p != end))
		goto bad;
	return 0;

bad:
	return -EIO;
}

/*
 * parse extra results
 */
static int parse_reply_info_extra(void **p, void *end,
                struct ceph_mds_reply_info_parsed *info)
{
	if (info->head->op == CEPH_MDS_OP_GETFILELOCK)
		return parse_reply_info_filelock(p, end, info);
	else
		return parse_reply_info_dir(p, end, info);
}

/*
 * parse entire mds reply
 */
@@ -223,10 +255,10 @@ static int parse_reply_info(struct ceph_msg *msg,
			goto out_bad;
	}

	/* dir content */
	/* extra */
	ceph_decode_32_safe(&p, end, len, bad);
	if (len > 0) {
		err = parse_reply_info_dir(&p, p+len, info);
		err = parse_reply_info_extra(&p, p+len, info);
		if (err < 0)
			goto out_bad;
	}
@@ -2074,7 +2106,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)

	mutex_lock(&session->s_mutex);
	if (err < 0) {
		pr_err("mdsc_handle_reply got corrupt reply mds%d\n", mds);
		pr_err("mdsc_handle_reply got corrupt reply mds%d(tid:%lld)\n", mds, tid);
		ceph_msg_dump(msg);
		goto out_err;
	}
@@ -2094,7 +2126,8 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
	mutex_lock(&req->r_fill_mutex);
	err = ceph_fill_trace(mdsc->fsc->sb, req, req->r_session);
	if (err == 0) {
		if (result == 0 && rinfo->dir_nr)
		if (result == 0 && req->r_op != CEPH_MDS_OP_GETFILELOCK &&
		    rinfo->dir_nr)
			ceph_readdir_prepopulate(req, req->r_session);
		ceph_unreserve_caps(mdsc, &req->r_caps_reservation);
	}
+21 −10
Original line number Diff line number Diff line
@@ -42,19 +42,28 @@ struct ceph_mds_reply_info_in {
};

/*
 * parsed info about an mds reply, including information about the
 * target inode and/or its parent directory and dentry, and directory
 * contents (for readdir results).
 * parsed info about an mds reply, including information about
 * either: 1) the target inode and/or its parent directory and dentry,
 * and directory contents (for readdir results), or
 * 2) the file range lock info (for fcntl F_GETLK results).
 */
struct ceph_mds_reply_info_parsed {
	struct ceph_mds_reply_head    *head;

	/* trace */
	struct ceph_mds_reply_info_in diri, targeti;
	struct ceph_mds_reply_dirfrag *dirfrag;
	char                          *dname;
	u32                           dname_len;
	struct ceph_mds_reply_lease   *dlease;

	/* extra */
	union {
		/* for fcntl F_GETLK results */
		struct ceph_filelock *filelock_reply;

		/* for readdir results */
		struct {
			struct ceph_mds_reply_dirfrag *dir_dir;
			int                           dir_nr;
			char                          **dir_dname;
@@ -62,6 +71,8 @@ struct ceph_mds_reply_info_parsed {
			struct ceph_mds_reply_lease   **dir_dlease;
			struct ceph_mds_reply_info_in *dir_in;
			u8                            dir_complete, dir_end;
		};
	};

	/* encoded blob describing snapshot contexts for certain
	   operations (e.g., open) */