]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
client: close dirfrag when trying to trim an inode 3269/head
authorYan, Zheng <zyan@redhat.com>
Fri, 26 Dec 2014 08:27:25 +0000 (16:27 +0800)
committerYan, Zheng <zyan@redhat.com>
Sat, 3 Jan 2015 03:41:06 +0000 (11:41 +0800)
Fixes: #10387
Signed-off-by: Yan, Zheng <zyan@redhat.com>
src/client/Client.cc
src/client/Client.h

index cd3ae55b9b90ed6fe3ae5adaf9cfb65e95d25f18..b69cc8a03b1bb0bc324ca2829667718ad226612d 100644 (file)
@@ -4145,8 +4145,24 @@ void Client::_schedule_invalidate_dentry_callback(Dentry *dn, bool del)
     async_dentry_invalidator.queue(new C_Client_DentryInvalidate(this, dn, del));
 }
 
-void Client::_invalidate_inode_parents(Inode *in)
+void Client::_try_to_trim_inode(Inode *in)
 {
+  int ref = in->get_num_ref();
+
+  if (in->dir && !in->dir->dentry_list.empty()) {
+    for (xlist<Dentry*>::iterator p = in->dir->dentry_list.begin();
+       !p.end(); ) {
+      Dentry *dn = *p;
+      ++p;
+      if (dn->lru_is_expireable())
+       unlink(dn, false, false);  // close dir, drop dentry
+    }
+    --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++;
@@ -4291,7 +4307,7 @@ void Client::handle_cap_grant(MetaSession *session, Inode *in, Cap *cap, MClient
 
   // may drop inode's last ref
   if (deleted_inode)
-    _invalidate_inode_parents(in);
+    _try_to_trim_inode(in);
 
   m->put();
 }
index 0cb4c20bc1122902109db3d97a3f97136a2e68af..7e55748525433d32baeb0a31be4f92f43639b11b 100644 (file)
@@ -546,7 +546,7 @@ protected:
 
   void _schedule_invalidate_dentry_callback(Dentry *dn, bool del);
   void _async_dentry_invalidate(vinodeno_t dirino, vinodeno_t ino, string& name);
-  void _invalidate_inode_parents(Inode *in);
+  void _try_to_trim_inode(Inode *in);
 
   void _schedule_invalidate_callback(Inode *in, int64_t off, int64_t len, bool keep_caps);
   void _invalidate_inode_cache(Inode *in);