From 207452180bcaa432b6bbf5f717756f308212e72e Mon Sep 17 00:00:00 2001 From: Greg Farnum Date: Wed, 27 Oct 2010 14:48:37 -0700 Subject: [PATCH] mds: add function MDCache::trim_non_auth_subtree Trims the subtree rooted at the given dir from cache, except for those portions linking to directories on other MDSes. Meant for use during replay. --- src/mds/MDCache.cc | 65 ++++++++++++++++++++++++++++++++++++++++++++++ src/mds/MDCache.h | 1 + 2 files changed, 66 insertions(+) diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index e9d8036452918..1f51a05346113 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -5164,6 +5164,71 @@ void MDCache::trim_non_auth() show_subtrees(); } +/** + * Recursively trim the subtree rooted at directory to remove all + * CInodes/CDentrys/CDirs that aren't links to remote MDSes, or ancestors + * of those links. This is used to clear invalid data out of the cache. + * Note that it doesn't clear the passed-in directory, since that's not + * always safe. + */ +bool MDCache::trim_non_auth_subtree(CDir *directory) +{ + dout(10) << "trim_non_auth_subtree " << directory << dendl; + bool keep_directory = false; + CDir::map_t::iterator j = directory->begin(); + CDir::map_t::iterator i = j; + while (j != directory->end()) { + i = j++; + CDentry *dn = i->second; + dout(10) << "Checking dentry " << dn << dendl; + CDentry::linkage_t *dnl = dn->get_linkage(); + if (dnl->is_primary()) { // check for subdirectories, etc + CInode *in = dnl->get_inode(); + bool keep_inode = false; + if (in->is_dir()) { + list subdirs; + in->get_dirfrags(subdirs); + for (list::iterator subdir = subdirs.begin(); + subdir != subdirs.end(); + ++subdir) { + if ((*subdir)->is_subtree_root()) { + keep_inode = true; + dout(10) << "subdir " << *subdir << "is kept!" << dendl; + } + else { + if (trim_non_auth_subtree(*subdir)) + keep_inode = true; + else { + in->close_dirfrag((*subdir)->get_frag()); + directory->state_clear(CDir::STATE_COMPLETE); // now incomplete! + } + } + } + + } + if (!keep_inode) { // remove it! + dout(20) << "removing inode " << in << " with dentry" << dn << dendl; + directory->unlink_inode(dn); + remove_inode(in); + directory->remove_dentry(dn); + } else { + dout(20) << "keeping inode " << in << "with dentry " << dn <is_remote()) + directory->unlink_inode(dn); + directory->remove_dentry(dn); + } + } + /** + * We've now checked all our children and deleted those that need it. + * Now return to caller, and tell them if *we're* a keeper. + */ + return keep_directory; +} + /* This function DOES put the passed message before returning */ void MDCache::handle_cache_expire(MCacheExpire *m) { diff --git a/src/mds/MDCache.h b/src/mds/MDCache.h index 34c96c2cefa95..1e1705591af1c 100644 --- a/src/mds/MDCache.h +++ b/src/mds/MDCache.h @@ -829,6 +829,7 @@ public: map& expiremap); void send_expire_messages(map& expiremap); void trim_non_auth(); // trim out trimmable non-auth items + bool trim_non_auth_subtree(CDir *directory); void trim_client_leases(); void check_memory_usage(); -- 2.39.5