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

Commit 4985d6f9 authored by Yan, Zheng's avatar Yan, Zheng Committed by Ilya Dryomov
Browse files

ceph: handle the new nfiles/nsubdirs fields in cap message

Without these new fields, stale st_size is returned in following
case.

1. MDS modifies a directory
2. MDS issues CEPH_CAP_ANY_SHARED to client
3. The client satifies stat(2) by its cached metadata. set st_size
   to "i_files + i_subdirs".

Link: http://tracker.ceph.com/issues/23855


Signed-off-by: default avatar"Yan, Zheng" <zyan@redhat.com>
Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
parent a1c6b835
Loading
Loading
Loading
Loading
+34 −5
Original line number Diff line number Diff line
@@ -3030,6 +3030,10 @@ struct cap_extra_info {
	u64 inline_version;
	void *inline_data;
	u32 inline_len;
	/* dirstat */
	bool dirstat_valid;
	u64 nfiles;
	u64 nsubdirs;
	/* currently issued */
	int issued;
};
@@ -3154,6 +3158,11 @@ static void handle_cap_grant(struct inode *inode,
				    &ctime, &mtime, &atime);
	}

	if ((newcaps & CEPH_CAP_FILE_SHARED) && extra_info->dirstat_valid) {
		ci->i_files = extra_info->nfiles;
		ci->i_subdirs = extra_info->nsubdirs;
	}

	if (newcaps & (CEPH_CAP_ANY_FILE_RD | CEPH_CAP_ANY_FILE_WR)) {
		/* file layout may have changed */
		s64 old_pool = ci->i_layout.pool_id;
@@ -3741,6 +3750,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
	struct ceph_mds_cap_peer *peer = NULL;
	struct ceph_snap_realm *realm = NULL;
	int op;
	int msg_version = le16_to_cpu(msg->hdr.version);
	u32 seq, mseq;
	struct ceph_vino vino;
	void *snaptrace;
@@ -3765,7 +3775,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
	snaptrace_len = le32_to_cpu(h->snap_trace_len);
	p = snaptrace + snaptrace_len;

	if (le16_to_cpu(msg->hdr.version) >= 2) {
	if (msg_version >= 2) {
		u32 flock_len;
		ceph_decode_32_safe(&p, end, flock_len, bad);
		if (p + flock_len > end)
@@ -3773,7 +3783,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
		p += flock_len;
	}

	if (le16_to_cpu(msg->hdr.version) >= 3) {
	if (msg_version >= 3) {
		if (op == CEPH_CAP_OP_IMPORT) {
			if (p + sizeof(*peer) > end)
				goto bad;
@@ -3785,7 +3795,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
		}
	}

	if (le16_to_cpu(msg->hdr.version) >= 4) {
	if (msg_version >= 4) {
		ceph_decode_64_safe(&p, end, extra_info.inline_version, bad);
		ceph_decode_32_safe(&p, end, extra_info.inline_len, bad);
		if (p + extra_info.inline_len > end)
@@ -3794,7 +3804,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
		p += extra_info.inline_len;
	}

	if (le16_to_cpu(msg->hdr.version) >= 5) {
	if (msg_version >= 5) {
		struct ceph_osd_client	*osdc = &mdsc->fsc->client->osdc;
		u32			epoch_barrier;

@@ -3802,7 +3812,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
		ceph_osdc_update_epoch_barrier(osdc, epoch_barrier);
	}

	if (le16_to_cpu(msg->hdr.version) >= 8) {
	if (msg_version >= 8) {
		u64 flush_tid;
		u32 caller_uid, caller_gid;
		u32 pool_ns_len;
@@ -3822,6 +3832,25 @@ void ceph_handle_caps(struct ceph_mds_session *session,
		}
	}

	if (msg_version >= 11) {
		struct ceph_timespec *btime;
		u64 change_attr;
		u32 flags;

		/* version >= 9 */
		if (p + sizeof(*btime) > end)
			goto bad;
		btime = p;
		p += sizeof(*btime);
		ceph_decode_64_safe(&p, end, change_attr, bad);
		/* version >= 10 */
		ceph_decode_32_safe(&p, end, flags, bad);
		/* version >= 11 */
		extra_info.dirstat_valid = true;
		ceph_decode_64_safe(&p, end, extra_info.nfiles, bad);
		ceph_decode_64_safe(&p, end, extra_info.nsubdirs, bad);
	}

	/* lookup ino */
	inode = ceph_find_inode(mdsc->fsc->sb, vino);
	ci = ceph_inode(inode);