scrub_scan,
pgpct_request,
ecrep_request,
+ snap_trim_initiate,
last_op
};
"scrub_scan",
"pgpct_request",
"ecrep_request",
+ "snap_trim_initiate",
};
// prevent the addition of OperationTypeCode-s with no matching OP_NAMES entry:
return {};
}
};
+
+ template <>
+ struct EventBackendRegistry<osd::SnapTrimInitiate> {
+ static std::tuple<> get_backends() {
+ return {};
+ }
+ };
}
namespace crimson::osd {
f->close_section();
}
+void SnapTrimInitiate::print(std::ostream &lhs) const
+{
+ fmt::print(lhs, "SnapTrimInitiate(pgid={})", pg->get_pgid());
+}
+
+void SnapTrimInitiate::dump_detail(Formatter *f) const
+{
+ Formatter::ObjectSection section(*f, "SnapTrimInitiate");
+ f->dump_stream("pgid") << pg->get_pgid();
+}
+
+seastar::future<> SnapTrimInitiate::start()
+{
+ logger().debug("{}: start", *this);
+ pg->initiate_snap_trim();
+ logger().debug("{}: complete", *this);
+ co_return;
+}
+
} // namespace crimson::osd
#include <iostream>
#include <seastar/core/future.hh>
+#include "common/fmt_common.h"
#include "crimson/osd/object_context_loader.h"
#include "crimson/osd/osdmap_gate.h"
#include "crimson/osd/osd_operation.h"
> tracking_events;
};
+class SnapTrimInitiate final : public PhasedOperationT<SnapTrimInitiate> {
+public:
+ static constexpr OperationTypeCode type =
+ OperationTypeCode::snap_trim_initiate;
+
+ SnapTrimInitiate(Ref<PG> pg) : pg(std::move(pg)) {}
+
+ void print(std::ostream &) const final;
+ void dump_detail(ceph::Formatter* f) const final;
+ seastar::future<> start();
+
+ template <typename FormatContext>
+ auto fmt_print_ctx(FormatContext& ctx) const {
+ return fmt::format_to(ctx.out(), "SnapTrimInitiate(pgid={})",
+ pg->get_pgid());
+ }
+
+private:
+ Ref<PG> pg;
+ PipelineHandle handle;
+
+public:
+ PipelineHandle& get_handle() { return handle; }
+
+ std::tuple<
+ StartEvent,
+ CompletionEvent
+ > tracking_events;
+};
+
} // namespace crimson::osd
#if FMT_VERSION >= 90000
}
void PG::on_active_actmap()
+{
+ logger().debug("{}: {}", *this, __func__);
+ initiate_snap_trim();
+}
+
+void PG::initiate_snap_trim()
{
logger().debug("{}: {} snap_trimq={}", *this, __func__, snap_trimq);
peering_state.state_clear(PG_STATE_SNAPTRIM_ERROR);
logger().info("{}: {} scrubbing, deferring snap trim", *this, __func__);
return;
}
- // loops until snap_trimq is empty or SNAPTRIM_ERROR.
+ if (snap_trimq.empty()) {
+ return;
+ }
Ref<PG> pg_ref = this;
std::ignore = interruptor::with_interruption([this] {
return interruptor::repeat(
return trim_snap(to_trim, needs_pause);
}
).then_interruptible([this] {
- logger().debug("{}: PG::on_active_actmap() finished trimming",
+ logger().debug("{}: PG::initiate_snap_trim() finished trimming",
*this);
peering_state.state_clear(PG_STATE_SNAPTRIM);
peering_state.state_clear(PG_STATE_SNAPTRIM_ERROR);
&& !snap_trimq.empty()
&& !peering_state.state_test(PG_STATE_SNAPTRIM)) {
logger().info("{}: scrub complete, retriggering snap trim", *this);
- on_active_actmap();
+ (void) shard_services.start_operation<SnapTrimInitiate>(this);
}
}
bool needs_pause);
/// Re-trigger snap trimming after scrub completion. Snap trimming is
/// deferred while the PG is scrubbing; call this from notify_scrub_end()
- /// to resume.
+ /// to resume. Spawns a SnapTrimInitiate operation to avoid nesting
+ /// interrupt conditions.
void kick_snap_trim();
+ /// Initiate the snap trim loop with all state checks. Called from
+ /// SnapTrimInitiate and on_active_actmap().
+ void initiate_snap_trim();
private:
PG_OSDMapGate osdmap_gate;
friend class WatchTimeoutRequest;
friend class SnapTrimEvent;
friend class SnapTrimObjSubEvent;
+ friend class SnapTrimInitiate;
friend ECBackend;
private: