From: Adam Kupczyk Date: Mon, 10 Jun 2024 16:03:24 +0000 (+0000) Subject: os/bluestore: Add admin socket commands to inspect onode metadata X-Git-Tag: v20.3.0~9^2~2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=86bd353f5dcf9d60cbd00848b5fc636f4594529c;p=ceph.git os/bluestore: Add admin socket commands to inspect onode metadata Add admin socket commands: 1) bluestore collections Lists collections. 2) bluestore list [start object] [max count] Lists collection coll starting from object (optional). Default 100 entries. 0 = unlimited. 3) bluestore onode metadata Prints onode metadata as seen by BlueStore. It might happen (usually in tests) that 2 BlueStore instances are created at the same time. Since admin commands are unique, it fails to register. Use first register to detect whether we can register at all. Signed-off-by: Adam Kupczyk --- diff --git a/src/crimson/os/alienstore/CMakeLists.txt b/src/crimson/os/alienstore/CMakeLists.txt index 5ecde78b5ff72..2ba396d93fa85 100644 --- a/src/crimson/os/alienstore/CMakeLists.txt +++ b/src/crimson/os/alienstore/CMakeLists.txt @@ -62,6 +62,7 @@ set(alien_store_srcs ${PROJECT_SOURCE_DIR}/src/os/bluestore/Writer.cc ${PROJECT_SOURCE_DIR}/src/os/bluestore/Compression.cc ${PROJECT_SOURCE_DIR}/src/os/bluestore/BlueStore_debug.cc + ${PROJECT_SOURCE_DIR}/src/os/bluestore/BlueAdmin.cc ${PROJECT_SOURCE_DIR}/src/os/memstore/MemStore.cc) add_library(crimson-alienstore STATIC diff --git a/src/os/CMakeLists.txt b/src/os/CMakeLists.txt index c98d09b24e2cc..4a96f4290d61c 100644 --- a/src/os/CMakeLists.txt +++ b/src/os/CMakeLists.txt @@ -28,6 +28,7 @@ if(WITH_BLUESTORE) bluestore/HybridAllocator.cc bluestore/Writer.cc bluestore/Compression.cc + bluestore/BlueAdmin.cc ) endif(WITH_BLUESTORE) diff --git a/src/os/bluestore/BlueAdmin.cc b/src/os/bluestore/BlueAdmin.cc new file mode 100644 index 0000000000000..e765c8d907d37 --- /dev/null +++ b/src/os/bluestore/BlueAdmin.cc @@ -0,0 +1,150 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "BlueAdmin.h" +#include "common/pretty_binary.h" +#include "common/debug.h" +#include +#include +#include + +#define dout_subsys ceph_subsys_bluestore +#define dout_context store.cct + +using ceph::bufferlist; +using ceph::Formatter; +using ceph::common::cmd_getval; + +BlueStore::SocketHook::SocketHook(BlueStore& store) + : store(store) +{ + AdminSocket *admin_socket = store.cct->get_admin_socket(); + if (admin_socket) { + int r = admin_socket->register_command( + "bluestore collections", + this, + "list all collections"); + if (r != 0) { + dout(1) << __func__ << " cannot register SocketHook" << dendl; + return; + } + r = admin_socket->register_command( + "bluestore list " + "name=collection,type=CephString,req=true " + "name=start,type=CephString,req=false " + "name=max,type=CephInt,req=false", + this, + "list objects in specific collection"); + ceph_assert(r == 0); + r = admin_socket->register_command( + "bluestore onode metadata " + "name=object_name,type=CephString,req=true", + this, + "print object internals"); + ceph_assert(r == 0); + } +} + +BlueStore::SocketHook::~SocketHook() +{ + AdminSocket *admin_socket = store.cct->get_admin_socket(); + if (admin_socket) { + admin_socket->unregister_commands(this); + } +} + +int BlueStore::SocketHook::call( + std::string_view command, + const cmdmap_t& cmdmap, + const bufferlist& inbl, + Formatter *f, + std::ostream& ss, + bufferlist& out) +{ + int r = 0; + if (command == "bluestore collections") { + std::vector collections; + store.list_collections(collections); + std::stringstream result; + for (const auto& c : collections) { + result << c << std::endl; + } + out.append(result.str()); + return 0; + } else if (command == "bluestore list") { + std::string coll; + std::string start; + int64_t max; + cmd_getval(cmdmap, "collection", coll); + cmd_getval(cmdmap, "start", start); + if (!cmd_getval(cmdmap, "max", max)) { + max = 100; + } + if (max == 0) { + max = std::numeric_limits::max(); + } + coll_t c; + if (c.parse(coll) == false) { + ss << "Cannot parse collection" << std::endl; + return -EINVAL; + } + BlueStore::CollectionRef col = store._get_collection(c); + if (!col) { + ss << "No such collection" << std::endl; + return -ENOENT; + } + ghobject_t start_object; + if (start.length() > 0) { + if (start_object.parse(start) == false) { + ss << "Cannot parse start object"; + return -EINVAL; + } + } + std::vector list; + { + std::shared_lock l(col->lock); + r = store._collection_list(col.get(), start_object, ghobject_t::get_max(), + max, false, &list, nullptr); + } + if (r != 0) { + return 0; + } + std::stringstream result; + for (auto& obj : list) { + result << obj << std::endl; + } + out.append(result.str()); + return 0; + } else if (command == "bluestore onode metadata") { + std::string object_name; + cmd_getval(cmdmap, "object_name", object_name); + ghobject_t object; + if (!object.parse(object_name)) { + ss << "Cannot parse object" << std::endl; + return -EINVAL; + } + std::shared_lock l(store.coll_lock); + for (const auto& cp : store.coll_map) { + if (cp.second->contains(object)) { + std::shared_lock l(cp.second->lock); + OnodeRef o = cp.second->get_onode(object, false); + if (!o || !o->exists) { + ss << "Object not found" << std::endl; + return -ENOENT; + } + o->extent_map.fault_range(store.db, 0, 0xffffffff); + using P = BlueStore::printer; + std::stringstream result; + result << o->print(P::PTR + P::DISK + P::USE + P::BUF + P::CHK + P::ATTRS) << std::endl; + out.append(result.str()); + return 0; + } + } + r = -ENOENT; + ss << "No collection that can hold such object" << std::endl; + } else { + ss << "Invalid command" << std::endl; + r = -ENOSYS; + } + return r; +} diff --git a/src/os/bluestore/BlueAdmin.h b/src/os/bluestore/BlueAdmin.h new file mode 100644 index 0000000000000..9b870775ce9b0 --- /dev/null +++ b/src/os/bluestore/BlueAdmin.h @@ -0,0 +1,30 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_OSD_BLUEADMIN_H +#define CEPH_OSD_BLUEADMIN_H + + +#include "BlueStore.h" +#include "common/admin_socket.h" + +using std::string; +using std::to_string; + +using ceph::bufferlist; +using ceph::Formatter; + +class BlueStore::SocketHook : public AdminSocketHook { + BlueStore& store; + +public: + SocketHook(BlueStore& store); + virtual ~SocketHook(); + int call(std::string_view command, + const cmdmap_t& cmdmap, + const bufferlist& inbl, + Formatter *f, + std::ostream& ss, + bufferlist& out) override; +}; +#endif diff --git a/src/os/bluestore/BlueStore.cc b/src/os/bluestore/BlueStore.cc index 89c1795d59bcf..2d238e8043bed 100644 --- a/src/os/bluestore/BlueStore.cc +++ b/src/os/bluestore/BlueStore.cc @@ -59,6 +59,7 @@ #include "kv/KeyValueHistogram.h" #include "Writer.h" #include "Compression.h" +#include "BlueAdmin.h" #if defined(WITH_LTTNG) #define TRACEPOINT_DEFINE @@ -5673,10 +5674,13 @@ BlueStore::BlueStore(CephContext *cct, cct->_conf.add_observer(this); set_cache_shards(1); bluestore_bdev_label_require_all = cct->_conf.get_val("bluestore_bdev_label_require_all"); + asok_hook = new SocketHook(*this); } BlueStore::~BlueStore() { + delete asok_hook; + asok_hook = nullptr; cct->_conf.remove_observer(this); _shutdown_logger(); ceph_assert(!mounted); diff --git a/src/os/bluestore/BlueStore.h b/src/os/bluestore/BlueStore.h index be4fa407081f2..8c2daedc7e595 100644 --- a/src/os/bluestore/BlueStore.h +++ b/src/os/bluestore/BlueStore.h @@ -58,6 +58,7 @@ #include "bluestore_common.h" #include "BlueFS.h" #include "common/EventTrace.h" +#include "common/admin_socket.h" #ifdef WITH_BLKIN #include "common/zipkin_trace.h" @@ -2531,6 +2532,10 @@ private: bool per_pool_stat_collection = true; + class SocketHook; + friend class SocketHook; + AdminSocketHook* asok_hook = nullptr; + struct MempoolThread : public Thread { public: BlueStore *store; diff --git a/src/test/objectstore/store_test_fixture.cc b/src/test/objectstore/store_test_fixture.cc index 3f9b93a3e24cd..62a199ceaeb97 100644 --- a/src/test/objectstore/store_test_fixture.cc +++ b/src/test/objectstore/store_test_fixture.cc @@ -41,7 +41,7 @@ void StoreTestFixture::SetUp() cerr << __func__ << ": unable to create " << data_dir << ": " << cpp_strerror(r) << std::endl; } ASSERT_EQ(0, r); - + store.reset(nullptr); store = ObjectStore::create(g_ceph_context, type, data_dir,