ceph: fix dir_lease_is_valid()
authorYan, Zheng <zyan@redhat.com>
Wed, 22 May 2019 09:26:27 +0000 (17:26 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 8 Jul 2019 12:01:42 +0000 (14:01 +0200)
It should call __ceph_dentry_dir_lease_touch() under dentry->d_lock.
Besides, ceph_dentry(dentry) can be NULL when called by LOOKUP_RCU
d_revalidate()

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

index 0637149..1271024 100644 (file)
@@ -1512,18 +1512,26 @@ static int __dir_lease_try_check(const struct dentry *dentry)
 static int dir_lease_is_valid(struct inode *dir, struct dentry *dentry)
 {
        struct ceph_inode_info *ci = ceph_inode(dir);
-       struct ceph_dentry_info *di = ceph_dentry(dentry);
-       int valid = 0;
+       int valid;
+       int shared_gen;
 
        spin_lock(&ci->i_ceph_lock);
-       if (atomic_read(&ci->i_shared_gen) == di->lease_shared_gen)
-               valid = __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1);
+       valid = __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1);
+       shared_gen = atomic_read(&ci->i_shared_gen);
        spin_unlock(&ci->i_ceph_lock);
-       if (valid)
-               __ceph_dentry_dir_lease_touch(di);
-       dout("dir_lease_is_valid dir %p v%u dentry %p v%u = %d\n",
-            dir, (unsigned)atomic_read(&ci->i_shared_gen),
-            dentry, (unsigned)di->lease_shared_gen, valid);
+       if (valid) {
+               struct ceph_dentry_info *di;
+               spin_lock(&dentry->d_lock);
+               di = ceph_dentry(dentry);
+               if (dir == d_inode(dentry->d_parent) &&
+                   di && di->lease_shared_gen == shared_gen)
+                       __ceph_dentry_dir_lease_touch(di);
+               else
+                       valid = 0;
+               spin_unlock(&dentry->d_lock);
+       }
+       dout("dir_lease_is_valid dir %p v%u dentry %p = %d\n",
+            dir, (unsigned)atomic_read(&ci->i_shared_gen), dentry, valid);
        return valid;
 }