Skip to content

Commit da5c263

Browse files
committed
mds/quiesce: overdrive an export if it hasn't frozen the tree yet
Just like with the fragmenting, we should abort an ongoing export if a quiesce is attempted for the directory. To minimize the stress for the system, we only allow the abort if the export hasn't yet managed to freeze the tree. If that is the case, then quiesce will have to wait for the export to finish. Fixes: https://tracker.ceph.com/issues/66123 Signed-off-by: Leonid Usov <[email protected]>
1 parent b1cb6d9 commit da5c263

File tree

3 files changed

+31
-5
lines changed

3 files changed

+31
-5
lines changed

src/mds/MDCache.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13758,6 +13758,7 @@ void MDCache::dispatch_quiesce_inode(const MDRequestRef& mdr)
1375813758
dout(25) << " iterating " << *dir << dendl;
1375913759
// overdrive syncrhonously since we aren't yet on the waiting list
1376013760
quiesce_overdrive_fragmenting(dir, false);
13761+
migrator->quiesce_overdrive_export(dir);
1376113762
for (auto& [dnk, dn] : *dir) {
1376213763
dout(25) << " evaluating (" << dnk << ", " << *dn << ")" << dendl;
1376313764
auto* in = dn->get_projected_inode();
@@ -13795,6 +13796,7 @@ void MDCache::dispatch_quiesce_inode(const MDRequestRef& mdr)
1379513796
}
1379613797
}
1379713798
if (gather.has_subs()) {
13799+
mdr->mark_event("quiescing children");
1379813800
dout(20) << __func__ << ": waiting for sub-ops to gather" << dendl;
1379913801
gather.activate();
1380013802
return;

src/mds/Migrator.cc

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,20 @@ void Migrator::find_stale_export_freeze()
242242
}
243243
}
244244

245+
void Migrator::quiesce_overdrive_export(CDir *dir) {
246+
map<CDir*, export_state_t>::iterator it = export_state.find(dir);
247+
if (it == export_state.end()) {
248+
return;
249+
}
250+
auto state = it->second.state;
251+
if (state <= EXPORT_FREEZING) {
252+
dout(10) << "will try to cancel in state: (" << state << ") " << get_export_statename(state) << dendl;
253+
export_try_cancel(dir, true);
254+
} else {
255+
dout(10) << "won't cancel in state: (" << state << ") " << get_export_statename(state) << dendl;
256+
}
257+
}
258+
245259
void Migrator::export_try_cancel(CDir *dir, bool notify_peer)
246260
{
247261
dout(10) << *dir << dendl;
@@ -1229,13 +1243,18 @@ void Migrator::handle_export_discover_ack(const cref_t<MExportDirDiscoverAck> &m
12291243
ceph_assert(it->second.state == EXPORT_DISCOVERING);
12301244

12311245
if (m->is_success()) {
1246+
// move to freezing the subtree
1247+
it->second.state = EXPORT_FREEZING;
1248+
auto&& mdr = boost::static_pointer_cast<MDRequestImpl>(std::move(it->second.mut));
1249+
ceph_assert(!it->second.mut); // should have been moved out of
1250+
12321251
// release locks to avoid deadlock
1233-
MDRequestRef mdr = static_cast<MDRequestImpl*>(it->second.mut.get());
12341252
ceph_assert(mdr);
1253+
// We should only call request_finish after we changed the state.
1254+
// Other requests may run as part of the finish here, so we want them
1255+
// to see this export in the updated state.
12351256
mdcache->request_finish(mdr);
1236-
it->second.mut.reset();
1237-
// freeze the subtree
1238-
it->second.state = EXPORT_FREEZING;
1257+
12391258
dir->auth_unpin(this);
12401259
ceph_assert(g_conf()->mds_kill_export_at != 3);
12411260

@@ -2388,7 +2407,11 @@ void Migrator::handle_export_cancel(const cref_t<MExportDirCancel> &m)
23882407
dirfrag_t df = m->get_dirfrag();
23892408
map<dirfrag_t,import_state_t>::iterator it = import_state.find(df);
23902409
if (it == import_state.end()) {
2391-
ceph_abort_msg("got export_cancel in weird state");
2410+
// don't assert here: we could NACK a discovery and also
2411+
// receive an async cancel.
2412+
// In general, it shouldn't be fatal error to receive a cancel
2413+
// for an opration we don't know about.
2414+
dout(3) << "got export_cancel for an unknown fragment " << df << dendl;
23922415
} else if (it->second.state == IMPORT_DISCOVERING) {
23932416
import_reverse_discovering(df);
23942417
} else if (it->second.state == IMPORT_DISCOVERED) {

src/mds/Migrator.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ class Migrator {
182182
void handle_mds_failure_or_stop(mds_rank_t who);
183183

184184
void audit();
185+
void quiesce_overdrive_export(CDir *dir);
185186

186187
// -- import/export --
187188
// exporter

0 commit comments

Comments
 (0)