ceph: always get rstat from auth mds
authorYan, Zheng <zyan@redhat.com>
Wed, 25 Apr 2018 09:30:23 +0000 (17:30 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 4 Jun 2018 18:45:55 +0000 (20:45 +0200)
rstat is not tracked by capability. client can't know if rstat from
non-auth mds is uptodate or not.

Link: http://tracker.ceph.com/issues/23538
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
fs/ceph/caps.c
fs/ceph/inode.c
fs/ceph/xattr.c
include/linux/ceph/ceph_fs.h

index 23dbfae..1b9f611 100644 (file)
@@ -69,6 +69,8 @@ static char *gcap_string(char *s, int c)
                *s++ = 'w';
        if (c & CEPH_CAP_GBUFFER)
                *s++ = 'b';
+       if (c & CEPH_CAP_GWREXTEND)
+               *s++ = 'a';
        if (c & CEPH_CAP_GLAZYIO)
                *s++ = 'l';
        return s;
index ae05692..ec9441c 100644 (file)
@@ -854,6 +854,18 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
                }
        }
 
+       /* layout and rstat are not tracked by capability, update them if
+        * the inode info is from auth mds */
+       if (new_version || (info->cap.flags & CEPH_CAP_FLAG_AUTH)) {
+               if (S_ISDIR(inode->i_mode)) {
+                       ci->i_dir_layout = iinfo->dir_layout;
+                       ci->i_rbytes = le64_to_cpu(info->rbytes);
+                       ci->i_rfiles = le64_to_cpu(info->rfiles);
+                       ci->i_rsubdirs = le64_to_cpu(info->rsubdirs);
+                       ceph_decode_timespec(&ci->i_rctime, &info->rctime);
+               }
+       }
+
        /* xattrs */
        /* note that if i_xattrs.len <= 4, i_xattrs.data will still be NULL. */
        if ((ci->i_xattrs.version == 0 || !(issued & CEPH_CAP_XATTR_EXCL))  &&
@@ -919,14 +931,9 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
                inode->i_op = &ceph_dir_iops;
                inode->i_fop = &ceph_dir_fops;
 
-               ci->i_dir_layout = iinfo->dir_layout;
 
                ci->i_files = le64_to_cpu(info->files);
                ci->i_subdirs = le64_to_cpu(info->subdirs);
-               ci->i_rbytes = le64_to_cpu(info->rbytes);
-               ci->i_rfiles = le64_to_cpu(info->rfiles);
-               ci->i_rsubdirs = le64_to_cpu(info->rsubdirs);
-               ceph_decode_timespec(&ci->i_rctime, &info->rctime);
                break;
        default:
                pr_err("fill_inode %llx.%llx BAD mode 0%o\n",
@@ -2178,6 +2185,7 @@ int __ceph_do_getattr(struct inode *inode, struct page *locked_page,
        struct ceph_fs_client *fsc = ceph_sb_to_client(inode->i_sb);
        struct ceph_mds_client *mdsc = fsc->mdsc;
        struct ceph_mds_request *req;
+       int mode;
        int err;
 
        if (ceph_snap(inode) == CEPH_SNAPDIR) {
@@ -2190,7 +2198,8 @@ int __ceph_do_getattr(struct inode *inode, struct page *locked_page,
        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);
+       mode = (mask & CEPH_STAT_RSTAT) ? USE_AUTH_MDS : USE_ANY_MDS;
+       req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_GETATTR, mode);
        if (IS_ERR(req))
                return PTR_ERR(req);
        req->r_inode = inode;
index f7dcafb..5bc8edb 100644 (file)
@@ -56,6 +56,7 @@ struct ceph_vxattr {
 
 #define VXATTR_FLAG_READONLY           (1<<0)
 #define VXATTR_FLAG_HIDDEN             (1<<1)
+#define VXATTR_FLAG_RSTAT              (1<<2)
 
 /* layouts */
 
@@ -265,14 +266,16 @@ static size_t ceph_vxattrcb_quota_max_files(struct ceph_inode_info *ci,
 #define CEPH_XATTR_NAME2(_type, _name, _name2) \
        XATTR_CEPH_PREFIX #_type "." #_name "." #_name2
 
-#define XATTR_NAME_CEPH(_type, _name)                                  \
+#define XATTR_NAME_CEPH(_type, _name, _flags)                          \
        {                                                               \
                .name = CEPH_XATTR_NAME(_type, _name),                  \
                .name_size = sizeof (CEPH_XATTR_NAME(_type, _name)), \
                .getxattr_cb = ceph_vxattrcb_ ## _type ## _ ## _name, \
-               .exists_cb = NULL,                              \
-               .flags = VXATTR_FLAG_READONLY,                  \
+               .exists_cb = NULL,                                      \
+               .flags = (VXATTR_FLAG_READONLY | _flags),               \
        }
+#define XATTR_RSTAT_FIELD(_type, _name)                        \
+       XATTR_NAME_CEPH(_type, _name, VXATTR_FLAG_RSTAT)
 #define XATTR_LAYOUT_FIELD(_type, _name, _field)                       \
        {                                                               \
                .name = CEPH_XATTR_NAME2(_type, _name, _field), \
@@ -303,14 +306,14 @@ static struct ceph_vxattr ceph_dir_vxattrs[] = {
        XATTR_LAYOUT_FIELD(dir, layout, object_size),
        XATTR_LAYOUT_FIELD(dir, layout, pool),
        XATTR_LAYOUT_FIELD(dir, layout, pool_namespace),
-       XATTR_NAME_CEPH(dir, entries),
-       XATTR_NAME_CEPH(dir, files),
-       XATTR_NAME_CEPH(dir, subdirs),
-       XATTR_NAME_CEPH(dir, rentries),
-       XATTR_NAME_CEPH(dir, rfiles),
-       XATTR_NAME_CEPH(dir, rsubdirs),
-       XATTR_NAME_CEPH(dir, rbytes),
-       XATTR_NAME_CEPH(dir, rctime),
+       XATTR_NAME_CEPH(dir, entries, 0),
+       XATTR_NAME_CEPH(dir, files, 0),
+       XATTR_NAME_CEPH(dir, subdirs, 0),
+       XATTR_RSTAT_FIELD(dir, rentries),
+       XATTR_RSTAT_FIELD(dir, rfiles),
+       XATTR_RSTAT_FIELD(dir, rsubdirs),
+       XATTR_RSTAT_FIELD(dir, rbytes),
+       XATTR_RSTAT_FIELD(dir, rctime),
        {
                .name = "ceph.quota",
                .name_size = sizeof("ceph.quota"),
@@ -807,7 +810,10 @@ ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value,
        /* let's see if a virtual xattr was requested */
        vxattr = ceph_match_vxattr(inode, name);
        if (vxattr) {
-               err = ceph_do_getattr(inode, 0, true);
+               int mask = 0;
+               if (vxattr->flags & VXATTR_FLAG_RSTAT)
+                       mask |= CEPH_STAT_RSTAT;
+               err = ceph_do_getattr(inode, mask, true);
                if (err)
                        return err;
                err = -ENODATA;
index 7ecfc88..4903deb 100644 (file)
@@ -628,6 +628,7 @@ int ceph_flags_to_mode(int flags);
                                 CEPH_CAP_XATTR_SHARED)
 #define CEPH_STAT_CAP_INLINE_DATA (CEPH_CAP_FILE_SHARED | \
                                   CEPH_CAP_FILE_RD)
+#define CEPH_STAT_RSTAT CEPH_CAP_FILE_WREXTEND
 
 #define CEPH_CAP_ANY_SHARED (CEPH_CAP_AUTH_SHARED |                    \
                              CEPH_CAP_LINK_SHARED |                    \