]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
client: anchor Inode while trimming caps 19060/head
authorPatrick Donnelly <pdonnell@redhat.com>
Sun, 19 Nov 2017 23:08:18 +0000 (15:08 -0800)
committerPatrick Donnelly <pdonnell@redhat.com>
Tue, 21 Nov 2017 00:52:10 +0000 (16:52 -0800)
This prevents the Inode from being deleted until after cap trimming is
finished. In particular, this prevents remove_all_caps from being called which
screws up the traversal of caps in trim_caps.

Fixes: http://tracker.ceph.com/issues/22157
Signed-off-by: Patrick Donnelly <pdonnell@redhat.com>
src/client/Client.cc

index 678184787a2426cef9593f2817579a5bc9c4c152..5b43fad0a00e454ad4f465af7f0af8f8e632f3c2 100644 (file)
@@ -4058,9 +4058,10 @@ void Client::trim_caps(MetaSession *s, uint64_t max)
 
   uint64_t trimmed = 0;
   xlist<Cap*>::iterator p = s->caps.begin();
+  std::set<InodeRef> anchor; /* prevent put_inode from deleting all caps during traversal */
   while ((caps_size - trimmed) > max && !p.end()) {
     Cap *cap = *p;
-    Inode *in = cap->inode;
+    InodeRef in(cap->inode);
 
     // Increment p early because it will be invalidated if cap
     // is deleted inside remove_cap
@@ -4070,16 +4071,16 @@ void Client::trim_caps(MetaSession *s, uint64_t max)
       int mine = cap->issued | cap->implemented;
       int oissued = in->auth_cap ? in->auth_cap->issued : 0;
       // disposable non-auth cap
-      if (!(get_caps_used(in) & ~oissued & mine)) {
+      if (!(get_caps_used(in.get()) & ~oissued & mine)) {
        ldout(cct, 20) << " removing unused, unneeded non-auth cap on " << *in << dendl;
        remove_cap(cap, true);
+        /* N.B. no need to push onto anchor, as we are only removing one cap */
        trimmed++;
       }
     } else {
       ldout(cct, 20) << " trying to trim dentries for " << *in << dendl;
       bool all = true;
       set<Dentry*>::iterator q = in->dn_set.begin();
-      InodeRef tmp_ref(in);
       while (q != in->dn_set.end()) {
        Dentry *dn = *q++;
        if (dn->lru_is_expireable()) {
@@ -4090,6 +4091,8 @@ void Client::trim_caps(MetaSession *s, uint64_t max)
            // the end of this function.
            _schedule_invalidate_dentry_callback(dn, true);
          }
+          ldout(cct, 20) << " anchoring inode: " << in->ino << dendl;
+          anchor.insert(in);
          trim_dentry(dn);
         } else {
           ldout(cct, 20) << "  not expirable: " << dn->name << dendl;
@@ -4102,6 +4105,8 @@ void Client::trim_caps(MetaSession *s, uint64_t max)
       }
     }
   }
+  ldout(cct, 20) << " clearing anchored inodes" << dendl;
+  anchor.clear();
 
   caps_size = s->caps.size();
   if (caps_size > max)