From: Patrick Donnelly Date: Sun, 19 Nov 2017 23:08:18 +0000 (-0800) Subject: client: anchor Inode while trimming caps X-Git-Tag: v12.2.3~142^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=4dda1b6ead6b1f04f996403881f61e9b7d94dba0;p=ceph.git client: anchor Inode while trimming caps 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 (cherry picked from commit 1439337e949c9fcb7d15eb38c22d19eb57d3d0f2) --- diff --git a/src/client/Client.cc b/src/client/Client.cc index 1d9277a61b6..55c00695db6 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -4068,9 +4068,10 @@ void Client::trim_caps(MetaSession *s, int max) int trimmed = 0; xlist::iterator p = s->caps.begin(); + std::set 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 @@ -4080,16 +4081,16 @@ void Client::trim_caps(MetaSession *s, int 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::iterator q = in->dn_set.begin(); - InodeRef tmp_ref(in); while (q != in->dn_set.end()) { Dentry *dn = *q++; if (dn->lru_is_expireable()) { @@ -4100,6 +4101,8 @@ void Client::trim_caps(MetaSession *s, int 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; @@ -4112,6 +4115,8 @@ void Client::trim_caps(MetaSession *s, int max) } } } + ldout(cct, 20) << " clearing anchored inodes" << dendl; + anchor.clear(); if (s->caps.size() > max) _invalidate_kernel_dcache();