summaryrefslogtreecommitdiff
path: root/fs/ceph/inode.c
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2014-09-16 17:46:17 +0400
committerIlya Dryomov <idryomov@redhat.com>2014-10-14 21:03:38 +0400
commit508b32d8661b12da4c9ca41a9b2054e1dc92fa7e (patch)
tree81b68ad636814b6ffbc3af1be01276a038b50759 /fs/ceph/inode.c
parentb76f82398c1017e303d87760e22125714010207f (diff)
downloadlinux-508b32d8661b12da4c9ca41a9b2054e1dc92fa7e.tar.xz
ceph: request xattrs if xattr_version is zero
Following sequence of events can happen. - Client releases an inode, queues cap release message. - A 'lookup' reply brings the same inode back, but the reply doesn't contain xattrs because MDS didn't receive the cap release message and thought client already has up-to-data xattrs. The fix is force sending a getattr request to MDS if xattrs_version is 0. The getattr mask is set to CEPH_STAT_CAP_XATTR, so MDS knows client does not have xattr. Signed-off-by: Yan, Zheng <zyan@redhat.com>
Diffstat (limited to 'fs/ceph/inode.c')
-rw-r--r--fs/ceph/inode.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 04c89c266cec..5fbd0adb5724 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -766,7 +766,7 @@ static int fill_inode(struct inode *inode,
/* xattrs */
/* note that if i_xattrs.len <= 4, i_xattrs.data will still be NULL. */
- if ((issued & CEPH_CAP_XATTR_EXCL) == 0 &&
+ if ((ci->i_xattrs.version == 0 || !(issued & CEPH_CAP_XATTR_EXCL)) &&
le64_to_cpu(info->xattr_version) > ci->i_xattrs.version) {
if (ci->i_xattrs.blob)
ceph_buffer_put(ci->i_xattrs.blob);
@@ -1907,7 +1907,7 @@ out_put:
* Verify that we have a lease on the given mask. If not,
* do a getattr against an mds.
*/
-int ceph_do_getattr(struct inode *inode, int mask)
+int ceph_do_getattr(struct inode *inode, int mask, bool force)
{
struct ceph_fs_client *fsc = ceph_sb_to_client(inode->i_sb);
struct ceph_mds_client *mdsc = fsc->mdsc;
@@ -1920,7 +1920,7 @@ int ceph_do_getattr(struct inode *inode, int mask)
}
dout("do_getattr inode %p mask %s mode 0%o\n", inode, ceph_cap_string(mask), inode->i_mode);
- if (ceph_caps_issued_mask(ceph_inode(inode), mask, 1))
+ if (!force && ceph_caps_issued_mask(ceph_inode(inode), mask, 1))
return 0;
req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_GETATTR, USE_ANY_MDS);
@@ -1948,7 +1948,7 @@ int ceph_permission(struct inode *inode, int mask)
if (mask & MAY_NOT_BLOCK)
return -ECHILD;
- err = ceph_do_getattr(inode, CEPH_CAP_AUTH_SHARED);
+ err = ceph_do_getattr(inode, CEPH_CAP_AUTH_SHARED, false);
if (!err)
err = generic_permission(inode, mask);
@@ -1966,7 +1966,7 @@ int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry,
struct ceph_inode_info *ci = ceph_inode(inode);
int err;
- err = ceph_do_getattr(inode, CEPH_STAT_CAP_INODE_ALL);
+ err = ceph_do_getattr(inode, CEPH_STAT_CAP_INODE_ALL, false);
if (!err) {
generic_fillattr(inode, stat);
stat->ino = ceph_translate_ino(inode->i_sb, inode->i_ino);