From 46d574d0baea1c3249136538c321d7eac2861286 Mon Sep 17 00:00:00 2001 From: sageweil Date: Thu, 9 Aug 2007 19:18:32 +0000 Subject: [PATCH] fixed up freezing.. not it takes an auth_pin and is just better git-svn-id: https://ceph.svn.sf.net/svnroot/ceph@1608 29311d96-e01e-0410-9327-a35deaab8ce9 --- branches/sage/mds/mds/CDir.cc | 99 +++++++++++++++---------------- branches/sage/mds/mds/CDir.h | 33 +++++------ branches/sage/mds/mds/CInode.h | 5 +- branches/sage/mds/mds/MDCache.cc | 8 ++- branches/sage/mds/mds/Migrator.cc | 4 +- 5 files changed, 76 insertions(+), 73 deletions(-) diff --git a/branches/sage/mds/mds/CDir.cc b/branches/sage/mds/mds/CDir.cc index 0847e867879d4..e91e1b48b84db 100644 --- a/branches/sage/mds/mds/CDir.cc +++ b/branches/sage/mds/mds/CDir.cc @@ -1322,8 +1322,10 @@ void CDir::auth_unpin() assert(auth_pins >= 0); // pending freeze? - if (auth_pins + nested_auth_pins == 0) - on_freezeable(); + if (state_test(STATE_FREEZINGTREE|STATE_FREEZINGDIR) && + auth_pins == 1 && + nested_auth_pins == 0) + finish_waiting(WAIT_FREEZEABLE); // nest? if (is_subtree_root()) return; // no. @@ -1341,9 +1343,10 @@ void CDir::adjust_nested_auth_pins(int inc) assert(nested_auth_pins >= 0); // pending freeze? - if (is_freezeable()) - on_freezeable(); - // on freezeable_dir too? FIXME + if (state_test(STATE_FREEZINGTREE|STATE_FREEZINGDIR) && + auth_pins == 1 && + nested_auth_pins == 0) + finish_waiting(WAIT_FREEZEABLE); // adjust my inode? if (is_subtree_root()) @@ -1359,21 +1362,6 @@ void CDir::adjust_nested_auth_pins(int inc) * FREEZING */ -void CDir::on_freezeable() -{ - // check for anything pending freezeable - - /* NOTE: this will be called on deeper dirs first, walking up toward - the root, meaning that deeper freeze attempts will succeed first. - */ - /* NOTE: the first of these will likely freeze the dir, and unmark - FREEZING. additional ones will re-flag FREEZING. this isn't - particularly graceful, and might cause problems if the first one - needs to know about other waiters.... FIXME? */ - - finish_waiting(WAIT_FREEZEABLE); -} - // FREEZE TREE class C_MDS_FreezeTree : public Context { @@ -1393,24 +1381,29 @@ void CDir::freeze_tree(Context *c) { assert(!is_frozen()); assert(!is_freezing()); + + auth_pin(); if (is_freezeable()) { - _freeze_tree(c); + _freeze_tree(); + auth_unpin(); + if (c) { + c->finish(0); + delete c; + } } else { state_set(STATE_FREEZINGTREE); - dout(10) << "freeze_tree + wait " << *this << endl; - - // need to wait for auth pins to expire + dout(10) << "freeze_tree waiting " << *this << endl; add_waiter(WAIT_FREEZEABLE, new C_MDS_FreezeTree(this, c)); } } -void CDir::_freeze_tree(Context *c) +void CDir::_freeze_tree() { dout(10) << "_freeze_tree " << *this << endl; - // there shouldn't be any conflicting auth_pins. - assert(is_freezeable_dir()); + // there shouldn't be any conflicting auth_pins (except the 'freezing' one) + assert(is_freezeable(true)); // twiddle state state_clear(STATE_FREEZINGTREE); // actually, this may get set again by next context? @@ -1419,13 +1412,7 @@ void CDir::_freeze_tree(Context *c) // auth_pin inode for duration of freeze, if we are not a subtree root. if (is_auth() && !is_subtree_root()) - inode->auth_pin(); - - // continue to frozen land - if (c) { - c->finish(0); - delete c; - } + inode->auth_pin(); } void CDir::freeze_tree_finish(Context *c) @@ -1439,16 +1426,20 @@ void CDir::freeze_tree_finish(Context *c) } // freezeable now? - if (!is_freezeable()) { - // wait again! + if (!is_freezeable(true)) { dout(10) << "freeze_tree_finish still waiting " << *this << endl; - state_set(STATE_FREEZINGTREE); + assert(state_test(STATE_FREEZINGTREE)); add_waiter(WAIT_FREEZEABLE, new C_MDS_FreezeTree(this, c)); return; } dout(10) << "freeze_tree_finish " << *this << endl; - _freeze_tree(c); + _freeze_tree(); + auth_unpin(); + if (c) { + c->finish(0); + delete c; + } } void CDir::unfreeze_tree() @@ -1470,6 +1461,7 @@ void CDir::unfreeze_tree() // freezing. stop it. assert(state_test(STATE_FREEZINGTREE)); state_clear(STATE_FREEZINGTREE); + auth_unpin(); // cancel freeze waiters finish_waiting(WAIT_UNFREEZE); @@ -1539,32 +1531,33 @@ void CDir::freeze_dir(Context *c) assert(!is_frozen()); assert(!is_freezing()); + auth_pin(); if (is_freezeable_dir()) { - _freeze_dir(c); + _freeze_dir(); + auth_unpin(); + if (c) { + c->finish(0); + delete c; + } } else { state_set(STATE_FREEZINGDIR); dout(10) << "freeze_dir + wait " << *this << endl; - - // need to wait for auth pins to expire add_waiter(WAIT_FREEZEABLE, new C_MDS_FreezeDir(this, c)); } } -void CDir::_freeze_dir(Context *c) +void CDir::_freeze_dir() { dout(10) << "_freeze_dir " << *this << endl; + assert(is_freezeable_dir(true)); + state_clear(STATE_FREEZINGDIR); state_set(STATE_FROZENDIR); get(PIN_FROZEN); if (is_auth() && !is_subtree_root()) inode->auth_pin(); // auth_pin for duration of freeze - - if (c) { - c->finish(0); - delete c; - } } void CDir::freeze_dir_finish(Context *c) @@ -1578,8 +1571,7 @@ void CDir::freeze_dir_finish(Context *c) } // freezeable now? - if (!is_freezeable_dir()) { - // wait again! + if (!is_freezeable_dir(true)) { dout(10) << "freeze_dir_finish still waiting " << *this << endl; state_set(STATE_FREEZINGDIR); add_waiter(WAIT_FREEZEABLE, new C_MDS_FreezeDir(this, c)); @@ -1587,7 +1579,13 @@ void CDir::freeze_dir_finish(Context *c) } // freeze now - _freeze_dir(c); + dout(10) << "freeze_dir_finish " << *this << endl; + _freeze_dir(); + auth_unpin(); + if (c) { + c->finish(0); + delete c; + } } void CDir::unfreeze_dir() @@ -1608,6 +1606,7 @@ void CDir::unfreeze_dir() // still freezing. stop. assert(state_test(STATE_FREEZINGDIR)); state_clear(STATE_FREEZINGDIR); + auth_unpin(); // cancel freeze waiters finish_waiting(WAIT_UNFREEZE); diff --git a/branches/sage/mds/mds/CDir.h b/branches/sage/mds/mds/CDir.h index 1a0dbe2af0d2c..e4ac2f2a5c82f 100644 --- a/branches/sage/mds/mds/CDir.h +++ b/branches/sage/mds/mds/CDir.h @@ -172,21 +172,21 @@ protected: int num_dirty; // state - version_t version; - version_t committing_version; - version_t committed_version; - version_t committed_version_equivalent; // in case of, e.g., temporary file - version_t projected_version; + version_t version; + version_t committing_version; + version_t committed_version; + version_t committed_version_equivalent; // in case of, e.g., temporary file + version_t projected_version; // lock nesting, freeze - int auth_pins; - int nested_auth_pins; - int request_pins; + int auth_pins; + int nested_auth_pins; + int request_pins; // cache control (defined for authority; hints for replicas) - int dir_rep; - set dir_rep_by; // if dir_rep == REP_LIST + int dir_rep; + set dir_rep_by; // if dir_rep == REP_LIST // popularity dirfrag_load_vec_t pop_me; @@ -393,17 +393,16 @@ public: void auth_pin(); void auth_unpin(); void adjust_nested_auth_pins(int inc); - void on_freezeable(); // -- freezing -- void freeze_tree(Context *c); void freeze_tree_finish(Context *c); void unfreeze_tree(); - void _freeze_tree(Context *c=0); + void _freeze_tree(); void freeze_dir(Context *c); void freeze_dir_finish(Context *c); - void _freeze_dir(Context *c=0); + void _freeze_dir(); void unfreeze_dir(); bool is_freezing() { return is_freezing_tree() || is_freezing_dir(); } @@ -416,9 +415,9 @@ public: bool is_frozen_tree_root() { return state & STATE_FROZENTREE; } bool is_frozen_dir() { return state & STATE_FROZENDIR; } - bool is_freezeable() { + bool is_freezeable(bool freezing=false) { // no nested auth pins. - if (auth_pins > 0 || nested_auth_pins > 0) + if ((auth_pins-freezing) > 0 || nested_auth_pins > 0) return false; // inode must not be frozen. @@ -427,8 +426,8 @@ public: return true; } - bool is_freezeable_dir() { - if (auth_pins > 0) + bool is_freezeable_dir(bool freezing=false) { + if ((auth_pins-freezing) > 0) return false; // if not subtree root, inode must not be frozen (tree--frozen_dir is okay). diff --git a/branches/sage/mds/mds/CInode.h b/branches/sage/mds/mds/CInode.h index 912823cf86321..6cd1e69c51241 100644 --- a/branches/sage/mds/mds/CInode.h +++ b/branches/sage/mds/mds/CInode.h @@ -146,9 +146,10 @@ public: frag_t pick_dirfrag(const string &dn); bool has_dirfrags() { return !dirfrags.empty(); } CDir* get_dirfrag(frag_t fg) { - if (dirfrags.count(fg)) + if (dirfrags.count(fg)) { + assert(dirfragtree.is_leaf(fg)); return dirfrags[fg]; - else + } else return 0; } void get_dirfrags_under(frag_t fg, list& ls); diff --git a/branches/sage/mds/mds/MDCache.cc b/branches/sage/mds/mds/MDCache.cc index 878577cce3a19..9825e111851fe 100644 --- a/branches/sage/mds/mds/MDCache.cc +++ b/branches/sage/mds/mds/MDCache.cc @@ -5528,12 +5528,16 @@ void MDCache::adjust_dir_fragments(CInode *diri, frag_t basefrag, int bits, dout(10) << "adjust_dir_fragments " << basefrag << " " << bits << " on " << *diri << endl; + // yuck. we may have discovered the inode while it was being fragmented. + if (!diri->dirfragtree.is_leaf(basefrag)) + diri->dirfragtree.force_to_leaf(basefrag); + + CDir *base = diri->get_or_open_dirfrag(this, basefrag); + // adjust fragtree diri->dirfragtree.split(basefrag, bits); dout(10) << " new fragtree is " << diri->dirfragtree << endl; - CDir *base = diri->get_or_open_dirfrag(this, basefrag); - if (bits > 0) { if (base) { CDir *baseparent = base->get_parent_dir(); diff --git a/branches/sage/mds/mds/Migrator.cc b/branches/sage/mds/mds/Migrator.cc index 9f30de72d4c09..a9cbf9f7b7c8e 100644 --- a/branches/sage/mds/mds/Migrator.cc +++ b/branches/sage/mds/mds/Migrator.cc @@ -307,7 +307,7 @@ void Migrator::handle_mds_failure_or_stop(int who) CDir *dir = mds->mdcache->get_dirfrag(df); if (import_peer[df] == who) { - switch (import_state[df]) { + switch (q->second) { case IMPORT_DISCOVERING: dout(10) << "import state=discovering : clearing state" << endl; import_state.erase(df); @@ -324,7 +324,7 @@ void Migrator::handle_mds_failure_or_stop(int who) break; case IMPORT_PREPPING: - if (import_state[df] == IMPORT_PREPPING) { + if (q->second == IMPORT_PREPPING) { dout(10) << "import state=prepping : unpinning base+bounds " << *dir << endl; } assert(dir); -- 2.39.5