diff options
author | Yan, Zheng <zyan@redhat.com> | 2014-09-16 09:46:17 -0400 |
---|---|---|
committer | Ilya Dryomov <idryomov@redhat.com> | 2014-10-14 13:03:38 -0400 |
commit | 508b32d8661b12da4c9ca41a9b2054e1dc92fa7e (patch) | |
tree | 81b68ad636814b6ffbc3af1be01276a038b50759 /fs/ceph/xattr.c | |
parent | b76f82398c1017e303d87760e22125714010207f (diff) |
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/xattr.c')
-rw-r--r-- | fs/ceph/xattr.c | 29 |
1 files changed, 10 insertions, 19 deletions
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index 12f58d22e017..a87510f89ade 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c | |||
@@ -736,24 +736,20 @@ ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value, | |||
736 | dout("getxattr %p ver=%lld index_ver=%lld\n", inode, | 736 | dout("getxattr %p ver=%lld index_ver=%lld\n", inode, |
737 | ci->i_xattrs.version, ci->i_xattrs.index_version); | 737 | ci->i_xattrs.version, ci->i_xattrs.index_version); |
738 | 738 | ||
739 | if (__ceph_caps_issued_mask(ci, CEPH_CAP_XATTR_SHARED, 1) && | 739 | if (ci->i_xattrs.version == 0 || |
740 | (ci->i_xattrs.index_version >= ci->i_xattrs.version)) { | 740 | !__ceph_caps_issued_mask(ci, CEPH_CAP_XATTR_SHARED, 1)) { |
741 | goto get_xattr; | ||
742 | } else { | ||
743 | spin_unlock(&ci->i_ceph_lock); | 741 | spin_unlock(&ci->i_ceph_lock); |
744 | /* get xattrs from mds (if we don't already have them) */ | 742 | /* get xattrs from mds (if we don't already have them) */ |
745 | err = ceph_do_getattr(inode, CEPH_STAT_CAP_XATTR); | 743 | err = ceph_do_getattr(inode, CEPH_STAT_CAP_XATTR, true); |
746 | if (err) | 744 | if (err) |
747 | return err; | 745 | return err; |
746 | spin_lock(&ci->i_ceph_lock); | ||
748 | } | 747 | } |
749 | 748 | ||
750 | spin_lock(&ci->i_ceph_lock); | ||
751 | |||
752 | err = __build_xattrs(inode); | 749 | err = __build_xattrs(inode); |
753 | if (err < 0) | 750 | if (err < 0) |
754 | goto out; | 751 | goto out; |
755 | 752 | ||
756 | get_xattr: | ||
757 | err = -ENODATA; /* == ENOATTR */ | 753 | err = -ENODATA; /* == ENOATTR */ |
758 | xattr = __get_xattr(ci, name); | 754 | xattr = __get_xattr(ci, name); |
759 | if (!xattr) | 755 | if (!xattr) |
@@ -798,23 +794,18 @@ ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size) | |||
798 | dout("listxattr %p ver=%lld index_ver=%lld\n", inode, | 794 | dout("listxattr %p ver=%lld index_ver=%lld\n", inode, |
799 | ci->i_xattrs.version, ci->i_xattrs.index_version); | 795 | ci->i_xattrs.version, ci->i_xattrs.index_version); |
800 | 796 | ||
801 | if (__ceph_caps_issued_mask(ci, CEPH_CAP_XATTR_SHARED, 1) && | 797 | if (ci->i_xattrs.version == 0 || |
802 | (ci->i_xattrs.index_version >= ci->i_xattrs.version)) { | 798 | !__ceph_caps_issued_mask(ci, CEPH_CAP_XATTR_SHARED, 1)) { |
803 | goto list_xattr; | ||
804 | } else { | ||
805 | spin_unlock(&ci->i_ceph_lock); | 799 | spin_unlock(&ci->i_ceph_lock); |
806 | err = ceph_do_getattr(inode, CEPH_STAT_CAP_XATTR); | 800 | err = ceph_do_getattr(inode, CEPH_STAT_CAP_XATTR, true); |
807 | if (err) | 801 | if (err) |
808 | return err; | 802 | return err; |
803 | spin_lock(&ci->i_ceph_lock); | ||
809 | } | 804 | } |
810 | 805 | ||
811 | spin_lock(&ci->i_ceph_lock); | ||
812 | |||
813 | err = __build_xattrs(inode); | 806 | err = __build_xattrs(inode); |
814 | if (err < 0) | 807 | if (err < 0) |
815 | goto out; | 808 | goto out; |
816 | |||
817 | list_xattr: | ||
818 | /* | 809 | /* |
819 | * Start with virtual dir xattr names (if any) (including | 810 | * Start with virtual dir xattr names (if any) (including |
820 | * terminating '\0' characters for each). | 811 | * terminating '\0' characters for each). |
@@ -968,7 +959,7 @@ int __ceph_setxattr(struct dentry *dentry, const char *name, | |||
968 | retry: | 959 | retry: |
969 | issued = __ceph_caps_issued(ci, NULL); | 960 | issued = __ceph_caps_issued(ci, NULL); |
970 | dout("setxattr %p issued %s\n", inode, ceph_cap_string(issued)); | 961 | dout("setxattr %p issued %s\n", inode, ceph_cap_string(issued)); |
971 | if (!(issued & CEPH_CAP_XATTR_EXCL)) | 962 | if (ci->i_xattrs.version == 0 || !(issued & CEPH_CAP_XATTR_EXCL)) |
972 | goto do_sync; | 963 | goto do_sync; |
973 | __build_xattrs(inode); | 964 | __build_xattrs(inode); |
974 | 965 | ||
@@ -1077,7 +1068,7 @@ retry: | |||
1077 | issued = __ceph_caps_issued(ci, NULL); | 1068 | issued = __ceph_caps_issued(ci, NULL); |
1078 | dout("removexattr %p issued %s\n", inode, ceph_cap_string(issued)); | 1069 | dout("removexattr %p issued %s\n", inode, ceph_cap_string(issued)); |
1079 | 1070 | ||
1080 | if (!(issued & CEPH_CAP_XATTR_EXCL)) | 1071 | if (ci->i_xattrs.version == 0 || !(issued & CEPH_CAP_XATTR_EXCL)) |
1081 | goto do_sync; | 1072 | goto do_sync; |
1082 | __build_xattrs(inode); | 1073 | __build_xattrs(inode); |
1083 | 1074 | ||