From a3e47311b5422526a738aec59b53a97d92d19dbd Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 20 Jul 2011 11:08:56 -0700 Subject: [PATCH] mds: add mds_debug_subtrees option Verify that replayed ESubtreeMap events match what we have. Signed-off-by: Sage Weil --- src/common/config.cc | 1 + src/common/config.h | 1 + src/mds/MDCache.h | 3 ++ src/mds/journal.cc | 87 +++++++++++++++++++++++++++++++++++++++++++- src/vstart.sh | 1 + 5 files changed, 92 insertions(+), 1 deletion(-) diff --git a/src/common/config.cc b/src/common/config.cc index 597bcbe6d4549..5b5194a1912ac 100644 --- a/src/common/config.cc +++ b/src/common/config.cc @@ -308,6 +308,7 @@ struct config_option config_optionsp[] = { OPTION(mds_debug_scatterstat, OPT_BOOL, false), OPTION(mds_debug_frag, OPT_BOOL, false), OPTION(mds_debug_auth_pins, OPT_BOOL, false), + OPTION(mds_debug_subtrees, OPT_BOOL, false), OPTION(mds_kill_mdstable_at, OPT_INT, 0), OPTION(mds_kill_export_at, OPT_INT, 0), OPTION(mds_kill_import_at, OPT_INT, 0), diff --git a/src/common/config.h b/src/common/config.h index 5468e1074337c..54608e9a40139 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -373,6 +373,7 @@ public: bool mds_debug_scatterstat; bool mds_debug_frag; bool mds_debug_auth_pins; + bool mds_debug_subtrees; int mds_kill_mdstable_at; int mds_kill_export_at; int mds_kill_import_at; diff --git a/src/mds/MDCache.h b/src/mds/MDCache.h index fcbc17759d4e2..e102779669503 100644 --- a/src/mds/MDCache.h +++ b/src/mds/MDCache.h @@ -568,6 +568,9 @@ public: return subtrees[dir].empty(); } void remove_subtree(CDir *dir); + bool is_subtree(CDir *root) { + return subtrees.count(root); + } void get_subtree_bounds(CDir *root, set& bounds); void get_wouldbe_subtree_bounds(CDir *root, set& bounds); void verify_subtree_bounds(CDir *root, const set& bounds); diff --git a/src/mds/journal.cc b/src/mds/journal.cc index 64d7c4f8af219..6fe73f46163ae 100644 --- a/src/mds/journal.cc +++ b/src/mds/journal.cc @@ -1099,7 +1099,92 @@ void ESubtreeMap::replay(MDS *mds) // suck up the subtree map? if (mds->mdcache->is_subtrees()) { - dout(10) << "ESubtreeMap.replay -- ignoring, already have import map" << dendl; + dout(10) << "ESubtreeMap.replay -- i already have import map; verifying" << dendl; + int errors = 0; + + for (map >::iterator p = subtrees.begin(); + p != subtrees.end(); + ++p) { + CDir *dir = mds->mdcache->get_dirfrag(p->first); + if (!dir) { + mds->clog.error() << " replayed ESubtreeMap at " << get_start_off() + << " subtree root " << p->first << " not in cache"; + ++errors; + continue; + } + + if (!mds->mdcache->is_subtree(dir)) { + mds->clog.error() << " replayed ESubtreeMap at " << get_start_off() + << " subtree root " << p->first << " not a subtree in cache"; + ++errors; + continue; + } + if (dir->get_dir_auth().first != mds->whoami) { + mds->clog.error() << " replayed ESubtreeMap at " << get_start_off() + << " subtree root " << p->first + << " is not mine in cache (it's " << dir->get_dir_auth() << ")"; + ++errors; + continue; + } + + set bounds; + mds->mdcache->get_subtree_bounds(dir, bounds); + for (vector::iterator q = p->second.begin(); q != p->second.end(); ++q) { + CDir *b = mds->mdcache->get_dirfrag(*q); + if (!b) { + mds->clog.error() << " replayed ESubtreeMap at " << get_start_off() + << " subtree " << p->first << " bound " << *q << " not in cache"; + ++errors; + continue; + } + if (bounds.count(b) == 0) { + mds->clog.error() << " replayed ESubtreeMap at " << get_start_off() + << " subtree " << p->first << " bound " << *q << " not a bound in cache"; + ++errors; + continue; + } + bounds.erase(b); + } + for (set::iterator q = bounds.begin(); q != bounds.end(); ++q) { + mds->clog.error() << " replayed ESubtreeMap at " << get_start_off() + << " subtree " << p->first << " has extra bound in cache " << (*q)->dirfrag(); + ++errors; + } + + if (ambiguous_subtrees.count(p->first)) { + if (!mds->mdcache->have_ambiguous_import(p->first)) { + mds->clog.error() << " replayed ESubtreeMap at " << get_start_off() + << " subtree " << p->first << " is ambiguous but is not in our cache"; + ++errors; + } + } else { + if (mds->mdcache->have_ambiguous_import(p->first)) { + mds->clog.error() << " replayed ESubtreeMap at " << get_start_off() + << " subtree " << p->first << " is not ambiguous but is in our cache"; + ++errors; + } + } + } + + list subs; + mds->mdcache->list_subtrees(subs); + for (list::iterator p = subs.begin(); p != subs.end(); ++p) { + CDir *dir = *p; + if (dir->get_dir_auth().first != mds->whoami) + continue; + if (subtrees.count(dir->dirfrag()) == 0) { + mds->clog.error() << " replayed ESubtreeMap at " << get_start_off() + << " does not include cache subtree " << dir->dirfrag(); + ++errors; + } + } + + if (errors) { + dout(0) << "journal subtrees: " << subtrees << dendl; + dout(0) << "journal ambig_subtrees: " << ambiguous_subtrees << dendl; + mds->mdcache->show_subtrees(); + assert(!g_conf->mds_debug_subtrees || errors == 0); + } return; } diff --git a/src/vstart.sh b/src/vstart.sh index 906b3f4e293e1..d8fac39fba65b 100755 --- a/src/vstart.sh +++ b/src/vstart.sh @@ -279,6 +279,7 @@ $DAEMONOPTS $CMDSDEBUG mds debug frag = true mds debug auth pins = true + mds debug subtrees = true [osd] $DAEMONOPTS osd class tmp = out -- 2.39.5