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.
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())
* 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 {
{
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?
// 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)
}
// 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()
// freezing. stop it.
assert(state_test(STATE_FREEZINGTREE));
state_clear(STATE_FREEZINGTREE);
+ auth_unpin();
// cancel freeze waiters
finish_waiting(WAIT_UNFREEZE);
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)
}
// 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));
}
// 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()
// still freezing. stop.
assert(state_test(STATE_FREEZINGDIR));
state_clear(STATE_FREEZINGDIR);
+ auth_unpin();
// cancel freeze waiters
finish_waiting(WAIT_UNFREEZE);
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<int> dir_rep_by; // if dir_rep == REP_LIST
+ int dir_rep;
+ set<int> dir_rep_by; // if dir_rep == REP_LIST
// popularity
dirfrag_load_vec_t pop_me;
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(); }
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.
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).