ceph: use lookup request to revalidate dentry
authorYan, Zheng <zyan@redhat.com>
Thu, 17 Mar 2016 06:41:59 +0000 (14:41 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Fri, 25 Mar 2016 17:51:56 +0000 (18:51 +0100)
If dentry has no lease, ceph_d_revalidate() previously return 0.
This causes VFS to invalidate the dentry and create a new dentry
for later lookup. Invalidating a dentry also detach any underneath
mount points. So mount point inside cephfs can disapear mystically
(even the mount point is not modified by other hosts).

The fix is using lookup request to revalidate dentry without lease.
This can partly solve the mount points disapear issue (as long as
the mount point is not modified by other hosts)

Signed-off-by: Yan, Zheng <zyan@redhat.com>
fs/ceph/dir.c
fs/ceph/inode.c

index c37820bcb66bacc57894401428989fb9db5e6998..d6c13f9c931793cc9901e6d892200432c05bd4f4 100644 (file)
@@ -1111,6 +1111,40 @@ static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)
                        valid = 1;
        }
 
+       if (!valid) {
+               struct ceph_mds_client *mdsc =
+                       ceph_sb_to_client(dir->i_sb)->mdsc;
+               struct ceph_mds_request *req;
+               int op, mask, err;
+
+               op = ceph_snap(dir) == CEPH_SNAPDIR ?
+                       CEPH_MDS_OP_LOOKUPSNAP : CEPH_MDS_OP_LOOKUP;
+               req = ceph_mdsc_create_request(mdsc, op, USE_ANY_MDS);
+               if (!IS_ERR(req)) {
+                       req->r_dentry = dget(dentry);
+                       req->r_num_caps = 2;
+
+                       mask = CEPH_STAT_CAP_INODE | CEPH_CAP_AUTH_SHARED;
+                       if (ceph_security_xattr_wanted(dir))
+                               mask |= CEPH_CAP_XATTR_SHARED;
+                       req->r_args.getattr.mask = mask;
+
+                       req->r_locked_dir = dir;
+                       err = ceph_mdsc_do_request(mdsc, NULL, req);
+                       if (err == 0 || err == -ENOENT) {
+                               if (dentry == req->r_dentry) {
+                                       valid = !d_unhashed(dentry);
+                               } else {
+                                       d_invalidate(req->r_dentry);
+                                       err = -EAGAIN;
+                               }
+                       }
+                       ceph_mdsc_put_request(req);
+                       dout("d_revalidate %p lookup result=%d\n",
+                            dentry, err);
+               }
+       }
+
        dout("d_revalidate %p %s\n", dentry, valid ? "valid" : "invalid");
        if (valid) {
                ceph_dentry_lru_touch(dentry);
index 8b136dc0bc1396688998c968a54a086b87d00782..ed58b168904a9c2425badda5ff50a05832249705 100644 (file)
@@ -1265,6 +1265,7 @@ retry_lookup:
                        dout(" %p links to %p %llx.%llx, not %llx.%llx\n",
                             dn, d_inode(dn), ceph_vinop(d_inode(dn)),
                             ceph_vinop(in));
+                       d_invalidate(dn);
                        have_lease = false;
                }