return enter_stage<>(
peering_pp(*pg).process
).then([this, FNAME] {
+ // pg may have been deleted while this op was queued; see PG::do_delete_work.
+ if (pg->is_deleted()) {
+ DEBUG("{}: pg is deleted, skipping advance", *this);
+ return seastar::now();
+ }
+
/*
* PGAdvanceMap is scheduled at pg creation and when
* broadcasting new osdmaps to pgs. We are not able to serialize
t.remove(coll_ref->get_cid(), pgid.make_snapmapper_oid());
t.remove(coll_ref->get_cid(), pgmeta_oid);
t.remove_collection(coll_ref->get_cid());
+ /*
+ * Mark the PG as fully deleted *before* dispatching the final
+ * RMCOLL transaction. A PGAdvanceMap may already have been queued
+ * (with a Ref<PG>) by an earlier broadcast_map_to_pgs while this
+ * PG was still in pg_map, and is now sitting behind these
+ * DeleteSome events on the peering pipeline. Setting the deleted
+ * flag now lets that queued PGAdvanceMap detect the situation and
+ * skip itself instead of issuing ops on a collection that is
+ * about to disappear.
+ */
+ peering_state.set_delete_complete();
(void) crimson::os::with_store_do_transaction(
shard_services.get_store(store_index),
coll_ref,
bool is_backfilling() const final {
return peering_state.is_backfilling();
}
+ bool is_deleted() const {
+ return peering_state.is_deleted();
+ }
uint64_t get_last_user_version() const {
return get_info().last_user_version;
}