f->dump_bool("creating", creating);
}
-std::pair<seastar::future<Ref<PG>>, bool>
+PGMap::wait_for_pg_ret
PGMap::wait_for_pg(PGCreationBlockingEvent::TriggerI&& trigger, spg_t pgid)
{
if (auto pg = get_pg(pgid)) {
- return make_pair(seastar::make_ready_future<Ref<PG>>(pg), true);
+ return make_pair(
+ wait_for_pg_fut(wait_for_pg_ertr::ready_future_marker{}, pg),
+ true);
} else {
auto &state = pgs_creating.emplace(pgid, pgid).first->second;
return make_pair(
- // TODO: add to blocker Trigger-taking make_blocking_future
- trigger.maybe_record_blocking(state.promise.get_shared_future(), state),
- state.creating);
+ wait_for_pg_fut(
+ trigger.maybe_record_blocking(state.promise.get_shared_future(), state)
+ ), state.creating);
}
}
pgs.emplace(pgid, pg);
}
+void PGMap::pg_creation_canceled(spg_t pgid)
+{
+ logger().debug("PGMap::pg_creation_canceled: {}", pgid);
+ ceph_assert(!pgs.count(pgid));
+
+ auto creating_iter = pgs_creating.find(pgid);
+ ceph_assert(creating_iter != pgs_creating.end());
+ auto promise = std::move(creating_iter->second.promise);
+ pgs_creating.erase(creating_iter);
+ promise.set_exception(
+ crimson::ct_error::ecanceled::exception_ptr()
+ );
+}
+
PGMap::~PGMap() {}
}
* Get future for pg with a bool indicating whether it's already being
* created.
*/
- std::pair<seastar::future<Ref<PG>>, bool>
- wait_for_pg(PGCreationBlockingEvent::TriggerI&&, spg_t pgid);
+ using wait_for_pg_ertr = crimson::errorator<
+ crimson::ct_error::ecanceled>;
+ using wait_for_pg_fut = wait_for_pg_ertr::future<Ref<PG>>;
+ using wait_for_pg_ret = std::pair<wait_for_pg_fut, bool>;
+ wait_for_pg_ret wait_for_pg(PGCreationBlockingEvent::TriggerI&&, spg_t pgid);
/**
* get PG in non-blocking manner
*/
void pg_loaded(spg_t pgid, Ref<PG> pg);
+ /**
+ * Cancel pending creation of pgid.
+ */
+ void pg_creation_canceled(spg_t pgid);
+
pgs_t& get_pgs() { return pgs; }
const pgs_t& get_pgs() const { return pgs; }
auto get_pg_count() const { return pgs.size(); }
return shard_services.get_or_create_pg(
std::move(trigger),
opref.get_pgid(), opref.get_epoch(),
- std::move(opref.get_create_info()));
- }).then([&logger, &shard_services, &opref](Ref<PG> pgref) {
+ std::move(opref.get_create_info())
+ );
+ }).safe_then([&logger, &shard_services, &opref](Ref<PG> pgref) {
logger.debug("{}: have_pg", opref);
return opref.with_pg(shard_services, pgref);
- }).then([op=std::move(op)] {});
+ }).handle_error(
+ crimson::ct_error::ecanceled::handle([&logger, &opref](auto) {
+ logger.debug("{}: pg creation canceled, dropping", opref);
+ return seastar::now();
+ })
+ ).then([op=std::move(op)] {});
});
}
auto &&trigger) {
return shard_services.wait_for_pg(
std::move(trigger), opref.get_pgid());
- }).then([&logger, &shard_services, &opref](Ref<PG> pgref) {
+ }).safe_then([&logger, &shard_services, &opref](Ref<PG> pgref) {
logger.debug("{}: have_pg", opref);
return opref.with_pg(shard_services, pgref);
- }).then([op=std::move(op)] {});
+ }).handle_error(
+ crimson::ct_error::ecanceled::handle([&logger, &opref](auto) {
+ logger.debug("{}: pg creation canceled, dropping", opref);
+ return seastar::now();
+ })
+ ).then([op=std::move(op)] {});
});
}
"{} ignoring pgid {}, pool dne",
__func__,
pgid);
+ local_state.pg_map.pg_creation_canceled(pgid);
return seastar::make_ready_future<
std::tuple<Ref<PG>, OSDMapService::cached_map_t>
>(std::make_tuple(Ref<PG>(), startmap));
"{} dropping {} create, pool does not have CREATING flag set",
__func__,
pgid);
+ local_state.pg_map.pg_creation_canceled(pgid);
return seastar::make_ready_future<
std::tuple<Ref<PG>, OSDMapService::cached_map_t>
>(std::make_tuple(Ref<PG>(), startmap));
}
-seastar::future<Ref<PG>>
+ShardServices::get_or_create_pg_ret
ShardServices::get_or_create_pg(
PGMap::PGCreationBlockingEvent::TriggerI&& trigger,
spg_t pgid,
}
return std::move(fut);
} else {
- return seastar::make_ready_future<Ref<PG>>(
+ return get_or_create_pg_ret(
+ get_or_create_pg_ertr::ready_future_marker{},
local_state.pg_map.get_pg(pgid));
}
}
-seastar::future<Ref<PG>> ShardServices::wait_for_pg(
+ShardServices::wait_for_pg_ret
+ShardServices::wait_for_pg(
PGMap::PGCreationBlockingEvent::TriggerI&& trigger, spg_t pgid)
{
return local_state.pg_map.wait_for_pg(std::move(trigger), pgid).first;
bool do_create);
seastar::future<Ref<PG>> handle_pg_create_info(
std::unique_ptr<PGCreateInfo> info);
- seastar::future<Ref<PG>> get_or_create_pg(
+
+ using get_or_create_pg_ertr = PGMap::wait_for_pg_ertr;
+ using get_or_create_pg_ret = get_or_create_pg_ertr::future<Ref<PG>>;
+ get_or_create_pg_ret get_or_create_pg(
PGMap::PGCreationBlockingEvent::TriggerI&&,
spg_t pgid,
epoch_t epoch,
std::unique_ptr<PGCreateInfo> info);
- seastar::future<Ref<PG>> wait_for_pg(
+
+ using wait_for_pg_ertr = PGMap::wait_for_pg_ertr;
+ using wait_for_pg_ret = wait_for_pg_ertr::future<Ref<PG>>;
+ wait_for_pg_ret wait_for_pg(
PGMap::PGCreationBlockingEvent::TriggerI&&, spg_t pgid);
seastar::future<Ref<PG>> load_pg(spg_t pgid);