]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
ceph: stop on-going cached readdir if mds revokes FILE_SHARED cap
authorYan, Zheng <zyan@redhat.com>
Wed, 6 Sep 2017 02:15:16 +0000 (10:15 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Wed, 6 Sep 2017 17:57:00 +0000 (19:57 +0200)
If directory's FILE_SHARED cap get revoked, dentry in the directory
can get spliced into other directory (Eg, other client move the
dentry into directory B, then we do readdir on directory B). So we
should stop on-going cached readdir. this can be achieved by marking
dir not complete, because __dcache_readdir() checks dir completeness
before emitting each dentry.

Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
fs/ceph/caps.c

index 7a79450328026e462feb449b80b90febd66c99c8..157fe59fbabe5c9f5608d4e186154c8372643d6f 100644 (file)
@@ -490,13 +490,14 @@ static void __check_cap_issue(struct ceph_inode_info *ci, struct ceph_cap *cap,
        }
 
        /*
-        * if we are newly issued FILE_SHARED, mark dir not complete; we
-        * don't know what happened to this directory while we didn't
-        * have the cap.
+        * If FILE_SHARED is newly issued, mark dir not complete. We don't
+        * know what happened to this directory while we didn't have the cap.
+        * If FILE_SHARED is being revoked, also mark dir not complete. It
+        * stops on-going cached readdir.
         */
-       if ((issued & CEPH_CAP_FILE_SHARED) &&
-           (had & CEPH_CAP_FILE_SHARED) == 0) {
-               ci->i_shared_gen++;
+       if ((issued & CEPH_CAP_FILE_SHARED) != (had & CEPH_CAP_FILE_SHARED)) {
+               if (issued & CEPH_CAP_FILE_SHARED)
+                       ci->i_shared_gen++;
                if (S_ISDIR(ci->vfs_inode.i_mode)) {
                        dout(" marking %p NOT complete\n", &ci->vfs_inode);
                        __ceph_dir_clear_complete(ci);