]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
BlueStore/allocator: Add ability to dump free allocations via admin socket interface.
authorAdam Kupczyk <akupczyk@redhat.com>
Fri, 2 Aug 2019 11:54:13 +0000 (13:54 +0200)
committerNeha Ojha <nojha@redhat.com>
Wed, 7 Aug 2019 19:53:58 +0000 (15:53 -0400)
Signed-off-by: Adam Kupczyk <akupczyk@redhat.com>
(cherry picked from commit 278055d35ae3ca2eb06f59f4712ad9ce5d843d86)

src/os/bluestore/Allocator.cc
src/os/bluestore/Allocator.h

index 56854a056b8a2be0f0a68c5b950f422589dd5f1e..7326b74c8a78eec24466a86c830d8885ffb5adaf 100644 (file)
@@ -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 command, cmdmap_t& cmdmap,
+            std::string 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;
 }
 
 
index 1bb95e945df7f4245b7ad564e0d36e43e01870df..297bd65584f6ccb8f849a74167adea01f7c92953 100644 (file)
@@ -63,6 +63,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