diff options
Diffstat (limited to 'src/mds/Migrator.cc')
-rw-r--r-- | src/mds/Migrator.cc | 126 |
1 files changed, 101 insertions, 25 deletions
diff --git a/src/mds/Migrator.cc b/src/mds/Migrator.cc index cb77282e384..6b12f710db4 100644 --- a/src/mds/Migrator.cc +++ b/src/mds/Migrator.cc @@ -268,12 +268,12 @@ void Migrator::export_try_cancel(CDir *dir, bool notify_peer) case EXPORT_LOCKING: dout(10) << "export state=locking : dropping locks and removing auth_pin" << dendl; num_locking_exports--; - it->second.state = EXPORT_CANCELLED; + it->second.set_state(EXPORT_CANCELLED); dir->auth_unpin(this); break; case EXPORT_DISCOVERING: dout(10) << "export state=discovering : canceling freeze and removing auth_pin" << dendl; - it->second.state = EXPORT_CANCELLED; + it->second.set_state(EXPORT_CANCELLED); dir->unfreeze_tree(); // cancel the freeze dir->auth_unpin(this); if (notify_peer && @@ -286,7 +286,7 @@ void Migrator::export_try_cancel(CDir *dir, bool notify_peer) case EXPORT_FREEZING: dout(10) << "export state=freezing : canceling freeze" << dendl; - it->second.state = EXPORT_CANCELLED; + it->second.set_state(EXPORT_CANCELLED); dir->unfreeze_tree(); // cancel the freeze if (dir->is_subtree_root()) mdcache->try_subtree_merge(dir); @@ -301,13 +301,13 @@ void Migrator::export_try_cancel(CDir *dir, bool notify_peer) // NOTE: state order reversal, warning comes after prepping case EXPORT_WARNING: dout(10) << "export state=warning : unpinning bounds, unfreezing, notifying" << dendl; - it->second.state = EXPORT_CANCELLING; + it->second.set_state(EXPORT_CANCELLING); // fall-thru case EXPORT_PREPPING: if (state != EXPORT_WARNING) { dout(10) << "export state=prepping : unpinning bounds, unfreezing" << dendl; - it->second.state = EXPORT_CANCELLED; + it->second.set_state(EXPORT_CANCELLED); } { @@ -340,7 +340,7 @@ void Migrator::export_try_cancel(CDir *dir, bool notify_peer) case EXPORT_EXPORTING: dout(10) << "export state=exporting : reversing, and unfreezing" << dendl; - it->second.state = EXPORT_CANCELLING; + it->second.set_state(EXPORT_CANCELLING); export_reverse(dir, it->second); break; @@ -865,7 +865,7 @@ void Migrator::export_dir(CDir *dir, mds_rank_t dest) ceph_assert(export_state.count(dir) == 0); export_state_t& stat = export_state[dir]; num_locking_exports++; - stat.state = EXPORT_LOCKING; + stat.set_state(EXPORT_LOCKING); stat.peer = dest; stat.tid = mdr->reqid.tid; stat.mut = mdr; @@ -1140,7 +1140,7 @@ void Migrator::dispatch_export_dir(const MDRequestRef& mdr, int count) if (results.size() == 1 && results.front().first == dir) { num_locking_exports--; - it->second.state = EXPORT_DISCOVERING; + it->second.set_state(EXPORT_DISCOVERING); // send ExportDirDiscover (ask target) filepath path; dir->inode->make_path(path); @@ -1191,7 +1191,7 @@ void Migrator::dispatch_export_dir(const MDRequestRef& mdr, int count) ceph_assert(export_state.count(sub) == 0); auto& stat = export_state[sub]; num_locking_exports++; - stat.state = EXPORT_LOCKING; + stat.set_state(EXPORT_LOCKING); stat.peer = dest; stat.tid = _mdr->reqid.tid; stat.mut = _mdr; @@ -1244,7 +1244,7 @@ void Migrator::handle_export_discover_ack(const cref_t<MExportDirDiscoverAck> &m if (m->is_success()) { // move to freezing the subtree - it->second.state = EXPORT_FREEZING; + it->second.set_state(EXPORT_FREEZING); auto&& mdr = boost::static_pointer_cast<MDRequestImpl>(std::move(it->second.mut)); ceph_assert(!it->second.mut); // should have been moved out of @@ -1427,18 +1427,18 @@ void Migrator::export_frozen(CDir *dir, uint64_t tid) } // send. - it->second.state = EXPORT_PREPPING; + it->second.set_state(EXPORT_PREPPING); mds->send_message_mds(prep, it->second.peer); ceph_assert(g_conf()->mds_kill_export_at != 4); // make sure any new instantiations of caps are flushed out ceph_assert(it->second.warning_ack_waiting.empty()); - set<client_t> export_client_set; - get_export_client_set(dir, export_client_set); + ceph_assert(it->second.export_client_set.empty()); + get_export_client_set(dir, it->second.export_client_set); MDSGatherBuilder gather(g_ceph_context); - mds->server->flush_client_sessions(export_client_set, gather); + mds->server->flush_client_sessions(it->second.export_client_set, gather); if (gather.has_subs()) { it->second.warning_ack_waiting.insert(MDS_RANK_NONE); gather.set_finisher(new C_M_ExportSessionsFlushed(this, dir, it->second.tid)); @@ -1537,7 +1537,7 @@ void Migrator::handle_export_prep_ack(const cref_t<MExportDirPrepAck> &m) } - it->second.state = EXPORT_WARNING; + it->second.set_state(EXPORT_WARNING); ceph_assert(g_conf()->mds_kill_export_at != 6); // nobody to warn? @@ -1587,8 +1587,8 @@ void Migrator::export_go_synced(CDir *dir, uint64_t tid) dout(7) << *dir << " to " << dest << dendl; mdcache->show_subtrees(); - - it->second.state = EXPORT_EXPORTING; + + it->second.set_state(EXPORT_EXPORTING); ceph_assert(g_conf()->mds_kill_export_at != 7); ceph_assert(dir->is_frozen_tree_root()); @@ -1933,7 +1933,7 @@ void Migrator::handle_export_ack(const cref_t<MExportDirAck> &m) auto bp = m->imported_caps.cbegin(); decode(it->second.peer_imported, bp); - it->second.state = EXPORT_LOGGINGFINISH; + it->second.set_state(EXPORT_LOGGINGFINISH); ceph_assert(g_conf()->mds_kill_export_at != 9); set<CDir*> bounds; mdcache->get_subtree_bounds(dir, bounds); @@ -1957,10 +1957,10 @@ void Migrator::handle_export_ack(const cref_t<MExportDirAck> &m) // this keeps authority().first in sync with subtree auth state in the journal. mdcache->adjust_subtree_auth(dir, it->second.peer, mds->get_nodeid()); + ceph_assert(g_conf()->mds_kill_export_at != 10); // log export completion, then finish (unfreeze, trigger finish context, etc.) mds->mdlog->submit_entry(le, new C_MDS_ExportFinishLogged(this, dir)); mds->mdlog->flush(); - ceph_assert(g_conf()->mds_kill_export_at != 10); } void Migrator::export_notify_abort(CDir *dir, export_state_t& stat, set<CDir*>& bounds) @@ -1970,7 +1970,7 @@ void Migrator::export_notify_abort(CDir *dir, export_state_t& stat, set<CDir*>& ceph_assert(stat.state == EXPORT_CANCELLING); if (stat.notify_ack_waiting.empty()) { - stat.state = EXPORT_CANCELLED; + stat.set_state(EXPORT_CANCELLED); return; } @@ -2095,7 +2095,7 @@ void Migrator::export_logged_finish(CDir *dir) } // wait for notifyacks - stat.state = EXPORT_NOTIFYING; + stat.set_state(EXPORT_NOTIFYING); ceph_assert(g_conf()->mds_kill_export_at != 11); // no notifies to wait for? @@ -2844,7 +2844,6 @@ void Migrator::import_reverse(CDir *dir) dout(7) << *dir << dendl; import_state_t& stat = import_state[dir->dirfrag()]; - stat.state = IMPORT_ABORTING; set<CDir*> bounds; mdcache->get_subtree_bounds(dir, bounds); @@ -2950,10 +2949,14 @@ void Migrator::import_reverse(CDir *dir) } in->put(CInode::PIN_IMPORTINGCAPS); } + } + + if (stat.state == IMPORT_LOGGINGSTART || stat.state == IMPORT_ACKING) { for (auto& p : stat.session_map) { Session *session = p.second.first; session->dec_importing(); } + mds->server->close_forced_opened_sessions(stat.session_map); } // log our failure @@ -2962,6 +2965,7 @@ void Migrator::import_reverse(CDir *dir) mdcache->trim(num_dentries); // try trimming dentries // notify bystanders; wait in aborting state + stat.state = IMPORT_ABORTING; import_notify_abort(dir, bounds); } @@ -3054,10 +3058,9 @@ void Migrator::import_logged_start(dirfrag_t df, CDir *dir, mds_rank_t from, dout(7) << *dir << dendl; map<dirfrag_t, import_state_t>::iterator it = import_state.find(dir->dirfrag()); - if (it == import_state.end() || - it->second.state != IMPORT_LOGGINGSTART) { + ceph_assert(it != import_state.end()); + if (it->second.state != IMPORT_LOGGINGSTART) { dout(7) << "import " << df << " must have aborted" << dendl; - mds->server->finish_force_open_sessions(imported_session_map); return; } @@ -3217,6 +3220,79 @@ void Migrator::import_finish(CDir *dir, bool notify, bool last) } } +void Migrator::dump_export_states(Formatter *f) +{ + f->open_array_section("states"); + for (const auto& [dir, state] : export_state) { + f->open_object_section("state"); + + f->dump_unsigned("tid", state.tid); + + dir->dump(f, CDir::DUMP_PATH | CDir::DUMP_DIRFRAG); + + f->dump_string("state", get_export_statename(state.state)); + + f->open_object_section("state_history"); + for (const auto& [s, _1] : state.state_history) { + f->open_object_section(get_export_statename(s)); + f->dump_stream("start_at") << state.get_start_time(s); + f->dump_float("time_spent", state.get_time_spent(s)); + f->close_section(); + } + f->close_section(); + + f->dump_int("peer", state.peer); + + switch (state.state) { + case EXPORT_DISCOVERING: + case EXPORT_FREEZING: + f->dump_stream("last_cum_auth_pins_change") << state.last_cum_auth_pins_change; + f->dump_int("last_cum_auth_pins", state.last_cum_auth_pins); + f->dump_int("num_remote_waiters", state.num_remote_waiters); + + break; + + case EXPORT_PREPPING: + case EXPORT_WARNING: + f->open_array_section("flushed_clients"); + for (const auto &client : state.export_client_set) + f->dump_int("client", client.v); + f->close_section(); + + f->open_array_section("warning_ack_waiting"); + for (const auto &rank : state.warning_ack_waiting) + f->dump_int("rank", rank); + f->close_section(); + + if (state.state == EXPORT_PREPPING) + break; + // fall-thru + + case EXPORT_EXPORTING: + case EXPORT_LOGGINGFINISH: + case EXPORT_NOTIFYING: + f->open_array_section("notify_ack_waiting"); + for (const auto &rank : state.notify_ack_waiting) + f->dump_int("rank", rank); + f->close_section(); + + break; + + default: + break; + } + + if (state.state >= EXPORT_DISCOVERING) { + f->dump_unsigned("approx_size", state.approx_size); + f->dump_unsigned("unfreeze_tree_waiters", dir->count_unfreeze_tree_waiters()); + f->dump_float("freeze_tree_time", state.get_freeze_tree_time()); + } + + f->close_section(); + } + f->close_section(); +} + void Migrator::decode_import_inode(CDentry *dn, bufferlist::const_iterator& blp, mds_rank_t oldauth, LogSegment *ls, map<CInode*, map<client_t,Capability::Export> >& peer_exports, |