]> git.apps.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>
Wed, 20 Jul 2016 02:38:53 +0000 (10:38 +0800)
Signed-off-by: Yan, Zheng <zyan@redhat.com>
(cherry picked from commit f180ad149ab510626fcd6cbd8221f550f9858126)

src/client/Client.cc
src/client/Client.h

index 1a514ed55b88ca8e1a50663d6696d5322a845067..e6fd7510d4c9f31e1bf843048ed00cfa6d2900cc 100644 (file)
@@ -1799,8 +1799,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);
     }
   }
 }
@@ -4794,7 +4796,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();
 
@@ -4803,22 +4805,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);
+    }
   }
 }
 
@@ -4929,7 +4940,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();
 }
@@ -10812,6 +10823,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 10fe5ccf6a5a91cff91b0ebf8c7d97871f6eeb86..4ad1b73c99dec6d3394478f1b3ca6db0f37ca888 100644 (file)
@@ -663,7 +663,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);