From 491da5173fc33fec944865f0e2e9a506ec71fc5b Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Mon, 1 Dec 2014 21:54:52 +0800 Subject: [PATCH] client: invalidate kernel dentries one by one Our trick to trim the whole kernel dentry tree does not work for 3.18+ kernel. The fix is trim kernel dentries one by one. Fixes: #9997 Signed-off-by: Yan, Zheng --- src/client/Client.cc | 34 ++++++++++++++-------------------- src/client/Client.h | 2 +- 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/src/client/Client.cc b/src/client/Client.cc index 6b43ccce3896..42611f0f93da 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -543,7 +543,7 @@ void Client::trim_cache_for_reconnect(MetaSession *s) << " trimmed " << trimmed << " dentries" << dendl; if (s->caps.size() > 0) - _invalidate_kernel_dcache(); + _invalidate_kernel_dcache(s); } void Client::trim_dentry(Dentry *dn) @@ -3277,16 +3277,19 @@ void Client::remove_session_caps(MetaSession *s) sync_cond.Signal(); } -void Client::_invalidate_kernel_dcache() +void Client::_invalidate_kernel_dcache(MetaSession *s) { - // notify kernel to invalidate top level directory entries. As a side effect, - // unused inodes underneath these entries get pruned. - if (dentry_invalidate_cb && root->dir) { - for (ceph::unordered_map::iterator p = root->dir->dentries.begin(); - p != root->dir->dentries.end(); - ++p) { - if (p->second->inode) - _schedule_invalidate_dentry_callback(p->second, false); + if (!dentry_invalidate_cb) + return; + + for (xlist::iterator p = s->caps.begin(); !p.end(); ++p) { + Inode *in = (*p)->inode; + if (in->dn_set.empty()) + continue; + for (set::iterator q = in->dn_set.begin(); + q != in->dn_set.end(); + ++q) { + _schedule_invalidate_dentry_callback(*q, false); } } } @@ -3320,14 +3323,8 @@ void Client::trim_caps(MetaSession *s, int max) while (q != in->dn_set.end()) { Dentry *dn = *q++; if (dn->lru_is_expireable()) { - if (dn->dir->parent_inode->ino == MDS_INO_ROOT) { - // Only issue one of these per DN for inodes in root: handle - // others more efficiently by calling for root-child DNs at - // the end of this function. - _schedule_invalidate_dentry_callback(dn, true); - } + _schedule_invalidate_dentry_callback(dn, false); trim_dentry(dn); - } else { ldout(cct, 20) << " not expirable: " << dn->name << dendl; all = false; @@ -3348,9 +3345,6 @@ void Client::trim_caps(MetaSession *s, int max) } } s->s_cap_iterator = NULL; - - if (s->caps.size() > max) - _invalidate_kernel_dcache(); } void Client::mark_caps_dirty(Inode *in, int caps) diff --git a/src/client/Client.h b/src/client/Client.h index 4afc206077d5..ada58e248081 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -429,7 +429,7 @@ protected: void trim_cache_for_reconnect(MetaSession *s); void trim_dentry(Dentry *dn); void trim_caps(MetaSession *s, int max); - void _invalidate_kernel_dcache(); + void _invalidate_kernel_dcache(MetaSession *s); void dump_inode(Formatter *f, Inode *in, set& did, bool disconnected); void dump_cache(Formatter *f); // debug -- 2.47.3