From 278055d35ae3ca2eb06f59f4712ad9ce5d843d86 Mon Sep 17 00:00:00 2001 From: Adam Kupczyk Date: Fri, 2 Aug 2019 13:54:13 +0200 Subject: [PATCH] BlueStore/allocator: Add ability to dump free allocations via admin socket interface. Signed-off-by: Adam Kupczyk --- src/os/bluestore/Allocator.cc | 80 ++++++++++++++++++++++++++++++++++- src/os/bluestore/Allocator.h | 3 ++ 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/src/os/bluestore/Allocator.cc b/src/os/bluestore/Allocator.cc index 56854a056b8..748589fac22 100644 --- a/src/os/bluestore/Allocator.cc +++ b/src/os/bluestore/Allocator.cc @@ -5,9 +5,86 @@ #include "StupidAllocator.h" #include "BitmapAllocator.h" #include "common/debug.h" - +#include "common/admin_socket.h" #define dout_subsys ceph_subsys_bluestore +class Allocator::SocketHook : public AdminSocketHook { + Allocator *alloc; + + std::string name; +public: + explicit SocketHook(Allocator *alloc, const std::string& _name) : alloc(alloc), name(_name) + { + AdminSocket *admin_socket = g_ceph_context->get_admin_socket(); + if (name.empty()) { + name = to_string((uintptr_t)this); + } + if (admin_socket) { + int r = admin_socket->register_command(("bluestore allocator dump " + name).c_str(), + ("bluestore allocator dump " + name).c_str(), + this, + "dump allocator free regions"); + if (r != 0) + alloc = nullptr; //some collision, disable + if (alloc) { + r = admin_socket->register_command(("bluestore allocator score " + name).c_str(), + ("bluestore allocator score " + name).c_str(), + this, + "give score on allocator fragmentation (0-no fragmentation, 1-absolute fragmentation)"); + ceph_assert(r == 0); + } + } + } + ~SocketHook() + { + AdminSocket *admin_socket = g_ceph_context->get_admin_socket(); + if (admin_socket && alloc) { + int r = admin_socket->unregister_command(("bluestore allocator dump " + name).c_str()); + ceph_assert(r == 0); + r = admin_socket->unregister_command(("bluestore allocator score " + name).c_str()); + ceph_assert(r == 0); + } + } + + bool call(std::string_view command, const cmdmap_t& cmdmap, + std::string_view format, bufferlist& out) override { + stringstream ss; + bool r = true; + if (command == "bluestore allocator dump " + name) { + Formatter *f = Formatter::create(format, "json-pretty", "json-pretty"); + f->open_array_section("free_regions"); + auto iterated_allocation = [&](size_t off, size_t len) { + ceph_assert(len > 0); + f->open_object_section("free"); + char off_hex[30]; + char len_hex[30]; + snprintf(off_hex, sizeof(off_hex) - 1, "0x%lx", off); + snprintf(len_hex, sizeof(len_hex) - 1, "0x%lx", len); + f->dump_string("offset", off_hex); + f->dump_string("length", len_hex); + f->close_section(); + }; + alloc->dump(iterated_allocation); + + + f->close_section(); + f->flush(ss); + } else if (command == "bluestore allocator score " + name) { + Formatter *f = Formatter::create(format, "json-pretty", "json-pretty"); + f->open_object_section("fragmentation_score"); + f->dump_float("fragmentation_rating", alloc->get_fragmentation_score()); + f->close_section(); + f->flush(ss); + delete f; + } else { + ss << "Invalid command" << std::endl; + r = false; + } + out.append(ss); + return r; + } + +}; Allocator::Allocator(const std::string& name) { asok_hook = new SocketHook(this, name); @@ -16,6 +93,7 @@ Allocator::Allocator(const std::string& name) Allocator::~Allocator() { + delete asok_hook; } diff --git a/src/os/bluestore/Allocator.h b/src/os/bluestore/Allocator.h index 6877a3bbce7..61299bf5876 100644 --- a/src/os/bluestore/Allocator.h +++ b/src/os/bluestore/Allocator.h @@ -61,6 +61,9 @@ public: static Allocator *create(CephContext* cct, string type, int64_t size, int64_t block_size, const std::string& name = ""); +private: + class SocketHook; + SocketHook* asok_hook = nullptr; }; #endif -- 2.39.5