inode->adjust_nested_auth_pins(-1, NULL);
// unpin parent of frozen dir/tree?
- if (inode->is_auth() && (is_frozen_tree_root() || is_frozen_dir()))
- inode->auth_unpin(this);
+ if (inode->is_auth()) {
+ assert(!is_frozen_tree_root());
+ if (is_frozen_dir())
+ inode->auth_unpin(this);
+ }
}
if (was_subtree && !is_subtree_root()) {
dout(10) << " old subtree root, adjusting auth_pins" << dendl;
inode->adjust_nested_auth_pins(1, NULL);
// pin parent of frozen dir/tree?
- if (inode->is_auth() && (is_frozen_tree_root() || is_frozen_dir()))
- inode->auth_pin(this);
+ if (inode->is_auth()) {
+ assert(!is_frozen_tree_root());
+ if (is_frozen_dir())
+ inode->auth_pin(this);
+ }
}
// newly single auth?
state_clear(STATE_FREEZINGTREE); // actually, this may get set again by next context?
--num_freezing_trees;
}
+
+ if (is_auth()) {
+ mds_authority_t auth;
+ bool was_subtree = is_subtree_root();
+ if (was_subtree) {
+ auth = get_dir_auth();
+ } else {
+ // temporarily prevent parent subtree from becoming frozen.
+ inode->auth_pin(this);
+ // create new subtree
+ auth = authority();
+ }
+
+ assert(auth.first >= 0);
+ assert(auth.second == CDIR_AUTH_UNKNOWN);
+ auth.second = auth.first;
+ inode->mdcache->adjust_subtree_auth(this, auth);
+ if (!was_subtree)
+ inode->auth_unpin(this);
+ }
+
state_set(STATE_FROZENTREE);
++num_frozen_trees;
get(PIN_FROZEN);
-
- // auth_pin inode for duration of freeze, if we are not a subtree root.
- if (is_auth() && !is_subtree_root())
- inode->auth_pin(this);
}
void CDir::unfreeze_tree()
put(PIN_FROZEN);
- // unpin (may => FREEZEABLE) FIXME: is this order good?
- if (is_auth() && !is_subtree_root())
- inode->auth_unpin(this);
+ if (is_auth()) {
+ // must be subtree
+ assert(is_subtree_root());
+ // for debug purpose, caller should ensure 'dir_auth.second == dir_auth.first'
+ mds_authority_t auth = get_dir_auth();
+ assert(auth.first >= 0);
+ assert(auth.second == auth.first);
+ auth.second = CDIR_AUTH_UNKNOWN;
+ inode->mdcache->adjust_subtree_auth(this, auth);
+ }
// waiters?
finish_waiting(WAIT_UNFREEZE);
dout(10) << "export state=freezing : canceling freeze" << dendl;
it->second.state = EXPORT_CANCELLED;
dir->unfreeze_tree(); // cancel the freeze
+ if (dir->is_subtree_root())
+ cache->try_subtree_merge(dir);
if (notify_peer &&
(!mds->is_cluster_degraded() ||
mds->mdsmap->is_clientreplay_or_active_or_stopping(it->second.peer))) // tell them.
}
}
dir->unfreeze_tree();
- cache->adjust_subtree_auth(dir, mds->get_nodeid());
cache->try_subtree_merge(dir);
if (notify_peer &&
(!mds->is_cluster_degraded() ||
// adjust auth back to the exporter
cache->adjust_subtree_auth(dir, q->second.peer);
- cache->try_subtree_merge(dir);
// notify bystanders ; wait in aborting state
import_state[df].state = IMPORT_ABORTING;
dout(10) << "faking export_notify_ack from mds." << who
<< " on aborting import " << *dir << " from mds." << q->second.peer
<< dendl;
- if (q->second.bystanders.empty()) {
+ if (q->second.bystanders.empty())
import_reverse_unfreeze(dir);
- }
}
}
}
!diri->nestlock.can_wrlock(-1)) {
dout(7) << "export_dir couldn't acquire all needed locks, failing. "
<< *dir << dendl;
-
// .. unwind ..
dir->unfreeze_tree();
- dir->state_clear(CDir::STATE_EXPORTING);
+ cache->try_subtree_merge(dir);
mds->send_message_mds(new MExportDirCancel(dir->dirfrag(), it->second.tid), it->second.peer);
-
export_state.erase(it);
+
+ dir->state_clear(CDir::STATE_EXPORTING);
+ cache->maybe_send_pending_resolves();
return;
}
cache->show_subtrees();
+ // CDir::_freeze_tree() should have forced it into subtree.
+ assert(dir->get_dir_auth() == mds_authority_t(mds->get_nodeid(), mds->get_nodeid()));
// note the bounds.
- // force it into a subtree by listing auth as <me,me>.
- cache->adjust_subtree_auth(dir, mds->get_nodeid(), mds->get_nodeid());
set<CDir*> bounds;
cache->get_subtree_bounds(dir, bounds);
bd->state_clear(CDir::STATE_EXPORTBOUND);
}
- // adjust auth, with possible subtree merge.
- cache->adjust_subtree_auth(dir, mds->get_nodeid());
- cache->try_subtree_merge(dir);
-
// notify bystanders
export_notify_abort(dir, bounds);
+ // unfreeze tree, with possible subtree merge.
+ cache->adjust_subtree_auth(dir, mds->get_nodeid(), mds->get_nodeid());
+
// process delayed expires
cache->process_delayed_expire(dir);
-
- // unfreeze
+
dir->unfreeze_tree();
+ cache->try_subtree_merge(dir);
// revoke/resume stale caps
for (auto in : to_eval) {
// finish export (adjust local cache state)
int num_dentries = 0;
- C_ContextsBase<MDSInternalContextBase, MDSInternalContextGather> *fin = new C_ContextsBase<MDSInternalContextBase, MDSInternalContextGather>(g_ceph_context);
+ list<MDSInternalContextBase*> finished;
finish_export_dir(dir, ceph_clock_now(), it->second.peer,
- it->second.peer_imported, fin->contexts, &num_dentries);
-
+ it->second.peer_imported, finished, &num_dentries);
+
+ assert(!dir->is_auth());
+ cache->adjust_subtree_auth(dir, it->second.peer);
+
// unpin bounds
set<CDir*> bounds;
cache->get_subtree_bounds(dir, bounds);
if (dir->state_test(CDir::STATE_AUXSUBTREE))
dir->state_clear(CDir::STATE_AUXSUBTREE);
- // adjust auth, with possible subtree merge.
+ // discard delayed expires
+ cache->discard_delayed_expire(dir);
+
+ dout(7) << "export_finish unfreezing" << dendl;
+
+ // unfreeze tree, with possible subtree merge.
// (we do this _after_ removing EXPORTBOUND pins, to allow merges)
- cache->adjust_subtree_auth(dir, it->second.peer);
+ dir->unfreeze_tree();
cache->try_subtree_merge(dir);
// no more auth subtree? clear scatter dirty
!dir->get_inode()->has_subtree_root_dirfrag(mds->get_nodeid())) {
dir->get_inode()->clear_scatter_dirty();
// wake up scatter_nudge waiters
- dir->get_inode()->take_waiting(CInode::WAIT_ANY_MASK, fin->contexts);
+ dir->get_inode()->take_waiting(CInode::WAIT_ANY_MASK, finished);
}
- dir->add_waiter(CDir::WAIT_UNFREEZE, fin);
-
- // unfreeze
- dout(7) << "export_finish unfreezing" << dendl;
- dir->unfreeze_tree();
-
- // discard delayed expires
- cache->discard_delayed_expire(dir);
+ if (!finished.empty())
+ mds->queue_waiters(finished);
MutationRef mut = it->second.mut;
// remove from exporting list, clean up state
import_remove_pins(dir, bounds);
// adjust auth back to the exportor
cache->adjust_subtree_auth(dir, it->second.peer);
- cache->try_subtree_merge(dir);
import_reverse_unfreeze(dir);
} else {
assert(0 == "got export_cancel in weird state");
// log our failure
mds->mdlog->start_submit_entry(new EImportFinish(dir, false)); // log failure
- cache->try_subtree_merge(dir);
-
cache->trim(-1, num_dentries); // try trimming dentries
// notify bystanders; wait in aborting state
void Migrator::import_reverse_unfreeze(CDir *dir)
{
- assert(dir);
dout(7) << "import_reverse_unfreeze " << *dir << dendl;
- dir->unfreeze_tree();
+ assert(!dir->is_auth());
cache->discard_delayed_expire(dir);
+ dir->unfreeze_tree();
+ if (dir->is_subtree_root())
+ cache->try_subtree_merge(dir);
import_reverse_final(dir);
}
assert(it != import_state.end());
assert(it->second.state == IMPORT_ACKING || it->second.state == IMPORT_FINISHING);
+ if (it->second.state == IMPORT_ACKING) {
+ assert(dir->is_auth());
+ cache->adjust_subtree_auth(dir, mds->get_nodeid(), mds->get_nodeid());
+ }
+
// log finish
assert(g_conf->mds_kill_import_at != 9);
MutationRef mut = it->second.mut;
import_state.erase(it);
- // adjust auth, with possible subtree merge.
- cache->adjust_subtree_auth(dir, mds->get_nodeid());
-
mds->mdlog->start_submit_entry(new EImportFinish(dir, true));
- cache->try_subtree_merge(dir);
-
// process delayed expires
cache->process_delayed_expire(dir);
- // ok now unfreeze (and thus kick waiters)
+ // unfreeze tree, with possible subtree merge.
dir->unfreeze_tree();
+ cache->try_subtree_merge(dir);
+
cache->show_subtrees();
//audit(); // this fails, bc we munge up the subtree map during handle_import_map (resolve phase)