do_request_primary_scan() is an async coroutine. Backfill can complete
(and on_pg_clean() can destroy backfill_state) while the coroutine is
suspended in scan_for_backfill_primary(), e.g. waiting on an object
context load. Resuming and delivering PrimaryScanned then dereferences
a null backfill_state.
Discard the scan result if backfill_state is gone; the backfill has
already finished successfully.
Fixes: https://tracker.ceph.com/issues/77623
Signed-off-by: Kautilya Tripathi <kautilya.tripathi@ibm.com>
local_conf()->osd_backfill_scan_min,
local_conf()->osd_backfill_scan_max,
pg->get_peering_state().get_backfill_targets());
+ if (!backfill_state) {
+ // Backfill may finish (and tear down backfill_state) while this
+ // coroutine is suspended in scan_for_backfill_primary().
+ DEBUGDPP("primary scan result discarded, backfill finished",
+ *pg->get_dpp());
+ co_return;
+ }
using BackfillState = crimson::osd::BackfillState;
backfill_state->process_event(
BackfillState::PrimaryScanned{ std::move(bi) }.intrusive_from_this());