From 3854ee475a030fb5733270e0b3148ba1685779be Mon Sep 17 00:00:00 2001 From: Patrick Donnelly Date: Thu, 17 May 2018 17:06:52 -0700 Subject: [PATCH] client: delay dentry trimming until after cap traversal Fixes: http://tracker.ceph.com/issues/24137 Signed-off-by: Patrick Donnelly (cherry picked from commit 9199179799b41d9534b27bcceefc1bc9f2763bac) Conflicts: src/client/Client.cc --- src/client/Client.cc | 26 ++++++++++++++------------ src/client/Client.h | 2 +- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/client/Client.cc b/src/client/Client.cc index bf1cba22f1ac6..41eff1b4b2a24 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -4090,16 +4090,17 @@ void Client::_invalidate_kernel_dcache() } } -void Client::trim_caps(MetaSession *s, int max) +void Client::trim_caps(MetaSession *s, uint64_t max) { mds_rank_t mds = s->mds_num; - int caps_size = s->caps.size(); + size_t caps_size = s->caps.size(); ldout(cct, 10) << "trim_caps mds." << mds << " max " << max << " caps " << caps_size << dendl; - int trimmed = 0; - xlist::iterator p = s->caps.begin(); - std::set anchor; /* prevent put_inode from deleting all caps during traversal */ + uint64_t trimmed = 0; + auto p = s->caps.begin(); + std::set to_trim; /* this avoids caps other than the one we're + * looking at from getting deleted during traversal. */ while ((caps_size - trimmed) > max && !p.end()) { Cap *cap = *p; InodeRef in(cap->inode); @@ -4114,8 +4115,7 @@ void Client::trim_caps(MetaSession *s, int max) // disposable non-auth cap 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 */ + cap = (remove_cap(cap, true), nullptr); trimmed++; } } else { @@ -4132,9 +4132,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); + ldout(cct, 20) << " queueing dentry for trimming: " << dn->name << dendl; + to_trim.insert(dn); } else { ldout(cct, 20) << " not expirable: " << dn->name << dendl; all = false; @@ -4146,8 +4145,11 @@ void Client::trim_caps(MetaSession *s, int max) } } } - ldout(cct, 20) << " clearing anchored inodes" << dendl; - anchor.clear(); + ldout(cct, 20) << " trimming queued dentries: " << dendl; + for (const auto &dn : to_trim) { + trim_dentry(dn); + } + to_trim.clear(); caps_size = s->caps.size(); if (caps_size > max) diff --git a/src/client/Client.h b/src/client/Client.h index 358c183857a86..9c076214ac76b 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -537,7 +537,7 @@ protected: void trim_cache(bool trim_kernel_dcache=false); void trim_cache_for_reconnect(MetaSession *s); void trim_dentry(Dentry *dn); - void trim_caps(MetaSession *s, int max); + void trim_caps(MetaSession *s, uint64_t max); void _invalidate_kernel_dcache(); void dump_inode(Formatter *f, Inode *in, set& did, bool disconnected); -- 2.39.5