Commit 9215aeea authored by Yan, Zheng's avatar Yan, Zheng
Browse files

ceph: check inode caps in ceph_d_revalidate



Some inodes in readdir reply may have no caps. Getattr mds request
for these inodes can return -ESTALE. The fix is consider dentry that
links to inode with no caps as invalid. Invalid dentry causes a
lookup request to send to the mds, the MDS will send caps back.

Signed-off-by: default avatarYan, Zheng <zheng.z.yan@intel.com>
parent ca18bede
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -891,6 +891,18 @@ static int __ceph_is_any_caps(struct ceph_inode_info *ci)
	return !RB_EMPTY_ROOT(&ci->i_caps) || ci->i_cap_exporting_mds >= 0;
}

int ceph_is_any_caps(struct inode *inode)
{
	struct ceph_inode_info *ci = ceph_inode(inode);
	int ret;

	spin_lock(&ci->i_ceph_lock);
	ret = __ceph_is_any_caps(ci);
	spin_unlock(&ci->i_ceph_lock);

	return ret;
}

/*
 * Remove a cap.  Take steps to deal with a racing iterate_session_caps.
 *
+8 −3
Original line number Diff line number Diff line
@@ -1041,14 +1041,19 @@ static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)
		valid = 1;
	} else if (dentry_lease_is_valid(dentry) ||
		   dir_lease_is_valid(dir, dentry)) {
		if (dentry->d_inode)
			valid = ceph_is_any_caps(dentry->d_inode);
		else
			valid = 1;
	}

	dout("d_revalidate %p %s\n", dentry, valid ? "valid" : "invalid");
	if (valid)
	if (valid) {
		ceph_dentry_lru_touch(dentry);
	else
	} else {
		ceph_dir_clear_complete(dir);
		d_drop(dentry);
	}
	iput(dir);
	return valid;
}
+1 −0
Original line number Diff line number Diff line
@@ -782,6 +782,7 @@ extern int ceph_add_cap(struct inode *inode,
extern void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release);
extern void ceph_put_cap(struct ceph_mds_client *mdsc,
			 struct ceph_cap *cap);
extern int ceph_is_any_caps(struct inode *inode);

extern void __queue_cap_release(struct ceph_mds_session *session, u64 ino,
				u64 cap_id, u32 migrate_seq, u32 issue_seq);