]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
client: invalidate snap inodes after removing snapshot
authorYan, Zheng <zyan@redhat.com>
Mon, 11 Jul 2016 03:07:01 +0000 (11:07 +0800)
committerYan, Zheng <zyan@redhat.com>
Fri, 15 Jul 2016 01:11:49 +0000 (09:11 +0800)
Signed-off-by: Yan, Zheng <zyan@redhat.com>
src/client/Client.cc
src/client/Client.h

index 5ee8aedcce55d42bb12a759d4d32859d9294d62e..fae1fecea3af79a7c75cda08a95e22b67168627b 100644 (file)
@@ -1779,8 +1779,10 @@ void Client::put_request(MetaRequest *request)
 
     if (other_in) {
       if (other_in->dir &&
-         (op == CEPH_MDS_OP_RMDIR || op == CEPH_MDS_OP_RENAME))
-       _try_to_trim_inode(other_in.get());
+         (op == CEPH_MDS_OP_RMDIR ||
+          op == CEPH_MDS_OP_RENAME ||
+          op == CEPH_MDS_OP_RMSNAP))
+       _try_to_trim_inode(other_in.get(), false);
     }
   }
 }
@@ -4797,7 +4799,7 @@ void Client::_schedule_invalidate_dentry_callback(Dentry *dn, bool del)
     async_dentry_invalidator.queue(new C_Client_DentryInvalidate(this, dn, del));
 }
 
-void Client::_try_to_trim_inode(Inode *in)
+void Client::_try_to_trim_inode(Inode *in, bool sched_inval)
 {
   int ref = in->get_num_ref();
 
@@ -4806,22 +4808,31 @@ void Client::_try_to_trim_inode(Inode *in)
         p != in->dir->dentries.end(); ) {
       Dentry *dn = p->second;
       ++p;
+      /* rmsnap removes whole subtree, need trim inodes recursively.
+       * we don't need to invalidate dentries recursively. because
+       * invalidating a directory dentry effectively invalidate
+       * whole subtree */
+      if (in->snapid != CEPH_NOSNAP && dn->inode && dn->inode->is_dir())
+       _try_to_trim_inode(dn->inode.get(), false);
+
       if (dn->lru_is_expireable())
-       unlink(dn, false, false);  // close dir, drop dentry
+       unlink(dn, true, false);  // keep dir, drop dentry
+    }
+    if (in->dir->dentries.empty()) {
+      close_dir(in->dir);
+      --ref;
     }
-    --ref;
   }
-  // make sure inode was not freed when closing dir
-  if (ref == 0)
-    return;
 
-  set<Dentry*>::iterator q = in->dn_set.begin();
-  while (q != in->dn_set.end()) {
-    Dentry *dn = *q++;
-    // FIXME: we play lots of unlink/link tricks when handling MDS replies,
-    //        so in->dn_set doesn't always reflect the state of kernel's dcache.
-    _schedule_invalidate_dentry_callback(dn, true);
-    unlink(dn, true, true);
+  if (ref > 0 && in->ll_ref > 0 && sched_inval) {
+    set<Dentry*>::iterator q = in->dn_set.begin();
+    while (q != in->dn_set.end()) {
+      Dentry *dn = *q++;
+      // FIXME: we play lots of unlink/link tricks when handling MDS replies,
+      //        so in->dn_set doesn't always reflect the state of kernel's dcache.
+      _schedule_invalidate_dentry_callback(dn, true);
+      unlink(dn, true, true);
+    }
   }
 }
 
@@ -4932,7 +4943,7 @@ void Client::handle_cap_grant(MetaSession *session, Inode *in, Cap *cap, MClient
 
   // may drop inode's last ref
   if (deleted_inode)
-    _try_to_trim_inode(in);
+    _try_to_trim_inode(in, true);
 
   m->put();
 }
@@ -10905,6 +10916,7 @@ int Client::_rmdir(Inode *dir, const char *name, int uid, int gid)
     req->set_other_inode(in.get());
   } else {
     unlink(de, true, true);
+    req->set_other_inode(in.get());
   }
 
   res = make_request(req, uid, gid);
index 075b841f2fa1d3dbc676b58646fefcba1ae0c111..775cfdcd4f58ca76bc3614303a5a3d66e06ed0c1 100644 (file)
@@ -657,7 +657,7 @@ protected:
 
   void _schedule_invalidate_dentry_callback(Dentry *dn, bool del);
   void _async_dentry_invalidate(vinodeno_t dirino, vinodeno_t ino, string& name);
-  void _try_to_trim_inode(Inode *in);
+  void _try_to_trim_inode(Inode *in, bool sched_inval);
 
   void _schedule_invalidate_callback(Inode *in, int64_t off, int64_t len);
   void _invalidate_inode_cache(Inode *in);