template std::unique_ptr<AdminSocketHook> make_asok_hook<InjectMDataErrorHook>(
crimson::osd::ShardServices&);
+
+/**
+ * An InFlightOps admin hook: dump current in-flight operations
+ */
+class DumpInFlightOpsHook : public AdminSocketHook {
+public:
+ explicit DumpInFlightOpsHook(const crimson::osd::OSDOperationRegistry& op_registry) :
+ AdminSocketHook{"dump_ops_in_flight", "", "show the ops currently in flight"},
+ op_registry(op_registry)
+ {}
+ seastar::future<tell_result_t> call(const cmdmap_t&,
+ std::string_view format,
+ ceph::bufferlist&& input) const final
+ {
+ logger().warn("{}", __func__);
+ unique_ptr<Formatter> f{Formatter::create(format, "json-pretty", "json-pretty")};
+ f->open_object_section("ops_in_flight");
+ op_registry.dump_client_requests(f.get());
+ f->close_section();
+ f->dump_int("num_ops", 0);
+ return seastar::make_ready_future<tell_result_t>(std::move(f));
+ }
+private:
+ const crimson::osd::OSDOperationRegistry& op_registry;
+};
+template std::unique_ptr<AdminSocketHook>
+make_asok_hook<DumpInFlightOpsHook>(const crimson::osd::OSDOperationRegistry& op_registry);
+
} // namespace crimson::admin
class InjectMDataErrorHook;
class OsdStatusHook;
class SendBeaconHook;
+class DumpInFlightOpsHook;
template<class Hook, class... Args>
std::unique_ptr<AdminSocketHook> make_asok_hook(Args&&... args);
f->close_section();
}
+namespace detail {
+void dump_time_event(const char* name,
+ const utime_t& timestamp,
+ ceph::Formatter* f)
+{
+ assert(f);
+ f->open_object_section("time_event");
+ f->dump_string("name", name);
+ f->dump_stream("initiated_at") << timestamp;
+ f->close_section();
+}
+
+void dump_blocking_event(const char* name,
+ const utime_t& timestamp,
+ const Blocker* const blocker,
+ ceph::Formatter* f)
+{
+ assert(f);
+ f->open_object_section("blocking_event");
+ f->dump_string("name", name);
+ f->dump_stream("initiated_at") << timestamp;
+ if (blocker) {
+ blocker->dump(f);
+ }
+ f->close_section();
}
+} // namespace detail
+} // namespace crimson
seastar::make_exception_future<V>(e));
}
+namespace detail {
+void dump_time_event(const char* name,
+ const utime_t& timestamp,
+ ceph::Formatter* f);
+void dump_blocking_event(const char* name,
+ const utime_t& timestamp,
+ const Blocker* blocker,
+ ceph::Formatter* f);
+} // namespace detail
+
/**
* Provides an interface for dumping diagnostic information about
* why a particular op is not making progress.
void handle(T&, const Operation&) override {
timestamp = ceph_clock_now();
}
- private:
utime_t timestamp;
} internal_backend;
+
+ void dump(ceph::Formatter *f) const {
+ detail::dump_time_event(typeid(T).name(), internal_backend.timestamp, f);
+ }
};
const OpT& op;
};
+
+ void dump(ceph::Formatter *f) const {
+ detail::dump_blocking_event(typeid(T).name(),
+ internal_backend.timestamp,
+ internal_backend.blocker,
+ f);
+ }
};
virtual ~BlockerT() = default;
// PG commands
asok->register_command(make_asok_hook<pg::QueryCommand>(*this));
asok->register_command(make_asok_hook<pg::MarkUnfoundLostCommand>(*this));
+ // ops commands
+ asok->register_command(make_asok_hook<DumpInFlightOpsHook>(
+ std::as_const(get_shard_services().registry)));
});
}
#include "osd_operation.h"
#include "common/Formatter.h"
+#include "crimson/common/log.h"
+#include "crimson/osd/osd_operations/client_request.h"
+
+namespace {
+ seastar::logger& logger() {
+ return crimson::get_logger(ceph_subsys_osd);
+ }
+}
namespace crimson::osd {
+size_t OSDOperationRegistry::dump_client_requests(ceph::Formatter* f) const
+{
+ const auto& client_registry =
+ get_registry<static_cast<size_t>(ClientRequest::type)>();
+ logger().warn("{} num_ops={}", __func__, std::size(client_registry));
+ for (const auto& op : client_registry) {
+ op.dump(f);
+ }
+ return std::size(client_registry);
+}
+
OperationThrottler::OperationThrottler(ConfigProxy &conf)
: scheduler(crimson::osd::scheduler::make_scheduler(conf))
{
/**
* Maintains a set of lists of all active ops.
*/
-using OSDOperationRegistry = OperationRegistryT<
+struct OSDOperationRegistry : OperationRegistryT<
static_cast<size_t>(OperationTypeCode::last_op)
- >;
-
+> {
+ size_t dump_client_requests(ceph::Formatter* f) const;
+};
/**
* Throttles set of currently running operations
*
void ClientRequest::dump_detail(Formatter *f) const
{
+ logger().debug("{}: dumping", *this);
+ std::apply([f] (auto... event) {
+ (..., event.dump(f));
+ }, tracking_events);
}
ClientRequest::ConnectionPipeline &ClientRequest::cp()