namespace crimson::osd {
+PG::interruptible_future<>
+PG::SnapTrimMutex::lock(SnapTrimEvent &st_event) noexcept
+{
+ return st_event.enter_stage<interruptor>(wait_pg
+ ).then_interruptible([this] {
+ return mutex.lock();
+ });
+}
+
void SnapTrimEvent::SubOpBlocker::dump_detail(Formatter *f) const
{
f->open_array_section("dependent_operations");
}).then_interruptible([this] {
return enter_stage<interruptor>(
pp().get_obc);
+ }).then_interruptible([this] {
+ return pg->snaptrim_mutex.lock(*this);
}).then_interruptible([this] {
return enter_stage<interruptor>(
pp().process);
if (to_trim.empty()) {
// the legit ENOENT -> done
logger().debug("{}: to_trim is empty! Stopping iteration", *this);
+ pg->snaptrim_mutex.unlock();
return snap_trim_iertr::make_ready_future<seastar::stop_iteration>(
seastar::stop_iteration::yes);
}
- for (const auto& object : to_trim) {
- logger().debug("{}: trimming {}", *this, object);
- auto [op, fut] = shard_services.start_operation_may_interrupt<
- interruptor, SnapTrimObjSubEvent>(
- pg,
- object,
- snapid);
- subop_blocker.emplace_back(
- op->get_id(),
- std::move(fut)
- );
- }
- return enter_stage<interruptor>(
- wait_subop
- ).then_interruptible([this] {
+ return [&shard_services, this](const auto &to_trim) {
+ for (const auto& object : to_trim) {
+ logger().debug("{}: trimming {}", *this, object);
+ auto [op, fut] = shard_services.start_operation_may_interrupt<
+ interruptor, SnapTrimObjSubEvent>(
+ pg,
+ object,
+ snapid);
+ subop_blocker.emplace_back(
+ op->get_id(),
+ std::move(fut)
+ );
+ }
+ return interruptor::now();
+ }(to_trim).then_interruptible([this] {
+ return enter_stage<interruptor>(wait_subop);
+ }).then_interruptible([this] {
logger().debug("{}: awaiting completion", *this);
return subop_blocker.wait_completion();
- }).safe_then_interruptible([this] {
+ }).finally([this] {
+ pg->snaptrim_mutex.unlock();
+ }).safe_then_interruptible([this] {
if (!needs_pause) {
return interruptor::now();
}
class OSD;
class ShardServices;
-class PG;
// trim up to `max` objects for snapshot `snapid
class SnapTrimEvent final : public PhasedOperationT<SnapTrimEvent> {
CommonPGPipeline::GetOBC::BlockingEvent,
CommonPGPipeline::Process::BlockingEvent,
WaitSubop::BlockingEvent,
+ PG::SnapTrimMutex::WaitPG::BlockingEvent,
WaitTrimTimer::BlockingEvent,
CompletionEvent
> tracking_events;
+
+ friend class PG::SnapTrimMutex;
};
// remove single object. a SnapTrimEvent can create multiple subrequests.
namespace crimson::osd {
class OpsExecuter;
class BackfillRecovery;
+class SnapTrimEvent;
class PG : public boost::intrusive_ref_counter<
PG,
eversion_t &version);
private:
+
+ struct SnapTrimMutex {
+ struct WaitPG : OrderedConcurrentPhaseT<WaitPG> {
+ static constexpr auto type_name = "SnapTrimEvent::wait_pg";
+ } wait_pg;
+ seastar::shared_mutex mutex;
+
+ interruptible_future<> lock(SnapTrimEvent &st_event) noexcept;
+
+ void unlock() noexcept {
+ mutex.unlock();
+ }
+ } snaptrim_mutex;
+
using do_osd_ops_ertr = crimson::errorator<
crimson::ct_error::eagain>;
using do_osd_ops_iertr =