]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
Client: unlink dentry for inode with llref=0
authorXiaoxi CHEN <xiaoxchen@ebay.com>
Thu, 25 Jul 2019 14:10:20 +0000 (07:10 -0700)
committerXiaoxi CHEN <xiaoxchen@ebay.com>
Fri, 26 Jul 2019 02:32:53 +0000 (19:32 -0700)
when client get notification from MDS that a file has been deleted(via
getting CEPH_CAP_LINK_SHARED cap for inode with nlink = 0), if the client
hasnt touch the inode in the past, the ll_ref will be zero.

In previous code, we only call Client::unlink when ll_ref > 0, which is wrong
and will leave the dn in cache, keeping the caps and resulting the inode stays
in stray till the dn cache is dropped by kernel.

Under certain workload(write intensive and rotate intensive), this issue can cause
stray stacking to 100k+ and causeing huge space "leaking".

Fixes: http://tracker.ceph.com/issues/40960
Signed-off-by: Xiaoxi CHEN <xiaoxchen@ebay.com>
src/client/Client.cc

index 9801747fa0df601346e25fd00da38eae09b3ba8d..fb7eb15d9527d68c568e6271cfa595e95d2c41e8 100644 (file)
@@ -5105,6 +5105,7 @@ void Client::_schedule_invalidate_dentry_callback(Dentry *dn, bool del)
 void Client::_try_to_trim_inode(Inode *in, bool sched_inval)
 {
   int ref = in->get_num_ref();
+  ldout(cct, 5) << __func__ << " in " << *in <<dendl;
 
   if (in->dir && !in->dir->dentries.empty()) {
     for (auto p = in->dir->dentries.begin();
@@ -5133,14 +5134,16 @@ void Client::_try_to_trim_inode(Inode *in, bool sched_inval)
     --ref;
   }
 
-  if (ref > 0 && in->ll_ref > 0 && sched_inval) {
+  if (ref > 0) {
     auto q = in->dentries.begin();
     while (q != in->dentries.end()) {
       Dentry *dn = *q;
       ++q;
-      // FIXME: we play lots of unlink/link tricks when handling MDS replies,
-      //        so in->dentries doesn't always reflect the state of kernel's dcache.
-      _schedule_invalidate_dentry_callback(dn, true);
+      if( in->ll_ref > 0 && sched_inval) {
+        // FIXME: we play lots of unlink/link tricks when handling MDS replies,
+        //        so in->dentries doesn't always reflect the state of kernel's dcache.
+        _schedule_invalidate_dentry_callback(dn, true);
+      }
       unlink(dn, true, true);
     }
   }