If we bail out of advance_pg early because there is an upcoming merge, we
still need to dispatch_context() on rctx before we drop the PG lock. And
the rctx that we submit needs to include the on_applied finisher comit
to call _finish_splits.
This is noticeable (at least) when there is a split and merge that are
both known. When we process the split, the new child is added to new_pgs.
When we get to the merge epoch, we stop early and take the bail-out
path.
Fix by adding a dispatch_context call for this path. And further make sure
that both dispatch_context callers in this function queue up the
new_pgs event.
Fixes: https://tracker.ceph.com/issues/43825
Signed-off-by: Sage Weil <sage@redhat.com>
(cherry picked from commit
14c4dbb03fe3c7fb4a0a6fa40dcb89e89fb66b3c)
Conflicts:
src/osd/OSD.cc
- where master says "rctx.transaction.register_on_applied", replaced
with nautilus equivalent: "rctx->transaction->register_on_applied"
- where master says "dispatch_context(rctx, pg, pg->get_osdmap(),
&handle)", replaced with nautilus equivalent:
"dispatch_context_transaction(*rctx, pg, &handle)"
<< " is merge source, target is " << parent
<< dendl;
pg->write_if_dirty(rctx);
+ if (!new_pgs.empty()) {
+ rctx->transaction->register_on_applied(new C_FinishSplits(this,
+ new_pgs));
+ new_pgs.clear();
+ }
dispatch_context_transaction(*rctx, pg, &handle);
pg->ch->flush();
// release backoffs explicitly, since the on_shutdown path
} else {
dout(20) << __func__ << " not ready to merge yet" << dendl;
pg->write_if_dirty(rctx);
+ if (!new_pgs.empty()) {
+ rctx->transaction->register_on_applied(new C_FinishSplits(this,
+ new_pgs));
+ new_pgs.clear();
+ }
+ dispatch_context_transaction(*rctx, pg, &handle);
pg->unlock();
// kick source(s) to get them ready
for (auto& i : children) {