From e7f5e53cde3b586701ff8e759a941986c17af1a8 Mon Sep 17 00:00:00 2001 From: Adam Kupczyk Date: Wed, 31 Jul 2019 13:31:04 +0200 Subject: [PATCH] tools/ceph-bluestore-tool: add commands free-dump and free-score Signed-off-by: Adam Kupczyk --- doc/man/8/ceph-bluestore-tool.rst | 14 +++++++ src/os/bluestore/BlueStore.cc | 42 ++++++++++++++++++++ src/os/bluestore/BlueStore.h | 2 + src/os/bluestore/bluestore_tool.cc | 64 +++++++++++++++++++++++++++++- 4 files changed, 120 insertions(+), 2 deletions(-) diff --git a/doc/man/8/ceph-bluestore-tool.rst b/doc/man/8/ceph-bluestore-tool.rst index bc1058809eb..0ad5c20c3d6 100644 --- a/doc/man/8/ceph-bluestore-tool.rst +++ b/doc/man/8/ceph-bluestore-tool.rst @@ -22,6 +22,7 @@ Synopsis | **ceph-bluestore-tool** bluefs-bdev-new-wal --path *osd path* --dev-target *new-device* | **ceph-bluestore-tool** bluefs-bdev-new-db --path *osd path* --dev-target *new-device* | **ceph-bluestore-tool** bluefs-bdev-migrate --path *osd path* --dev-target *new-device* --devs-source *device1* [--devs-source *device2*] +| **ceph-bluestore-tool** free-dump|free-score --path *osd path* [ --allocator block/bluefs-wal/bluefs-db/bluefs-slow ] Description @@ -81,6 +82,15 @@ Commands Show device label(s). +:command:`free-dump` --path *osd path* [ --allocator block/bluefs-wal/bluefs-db/bluefs-slow ] + + Dump all free regions in allocator. + +:command:`free-score` --path *osd path* [ --allocator block/bluefs-wal/bluefs-db/bluefs-slow ] + + Give a [0-1] number that represents quality of fragmentation in allocator. + 0 represents case when all free space is in one chunk. 1 represents worst possible fragmentation. + Options ======= @@ -117,6 +127,10 @@ Options deep scrub/repair (read and validate object data, not just metadata) +.. option:: --allocator *name* + + Useful for *free-dump* and *free-score* actions. Selects allocator(s). + Device labels ============= diff --git a/src/os/bluestore/BlueStore.cc b/src/os/bluestore/BlueStore.cc index 305ea688187..3e7e175fb8c 100644 --- a/src/os/bluestore/BlueStore.cc +++ b/src/os/bluestore/BlueStore.cc @@ -6661,6 +6661,48 @@ int BlueStore::umount() return 0; } +int BlueStore::cold_open() +{ + int r = _open_path(); + if (r < 0) + return r; + r = _open_fsid(false); + if (r < 0) + goto out_path; + + r = _read_fsid(&fsid); + if (r < 0) + goto out_fsid; + + r = _lock_fsid(); + if (r < 0) + goto out_fsid; + + r = _open_bdev(false); + if (r < 0) + goto out_fsid; + r = _open_db_and_around(true); + if (r < 0) { + goto out_bdev; + } + return 0; + out_bdev: + _close_bdev(); + out_fsid: + _close_fsid(); + out_path: + _close_path(); + return r; +} +int BlueStore::cold_close() +{ + _close_db_and_around(); + _close_bdev(); + _close_fsid(); + _close_path(); + return 0; +} + static void apply(uint64_t off, uint64_t len, uint64_t granularity, diff --git a/src/os/bluestore/BlueStore.h b/src/os/bluestore/BlueStore.h index f711d0ceeac..319c159db64 100644 --- a/src/os/bluestore/BlueStore.h +++ b/src/os/bluestore/BlueStore.h @@ -2437,6 +2437,8 @@ public: int write_meta(const std::string& key, const std::string& value) override; int read_meta(const std::string& key, std::string *value) override; + int cold_open(); + int cold_close(); int fsck(bool deep) override { return _fsck(deep, false); diff --git a/src/os/bluestore/bluestore_tool.cc b/src/os/bluestore/bluestore_tool.cc index bdc5869b512..4b7c707319f 100644 --- a/src/os/bluestore/bluestore_tool.cc +++ b/src/os/bluestore/bluestore_tool.cc @@ -18,6 +18,7 @@ #include "os/bluestore/BlueFS.h" #include "os/bluestore/BlueStore.h" +#include "common/admin_socket.h" namespace po = boost::program_options; @@ -224,6 +225,7 @@ int main(int argc, char **argv) string action; string log_file; string key, value; + vector allocs_name; int log_level = 30; bool fsck_deep = false; po::options_description po_options("Options"); @@ -239,10 +241,26 @@ int main(int argc, char **argv) ("deep", po::value(&fsck_deep), "deep fsck (read all data)") ("key,k", po::value(&key), "label metadata key name") ("value,v", po::value(&value), "label metadata value") + ("allocator", po::value>(&allocs_name), "allocator to inspect: 'block'/'bluefs-wal'/'bluefs-db'/'bluefs-slow'") ; po::options_description po_positional("Positional options"); po_positional.add_options() - ("command", po::value(&action), "fsck, repair, bluefs-export, bluefs-bdev-sizes, bluefs-bdev-expand, bluefs-bdev-new-db, bluefs-bdev-new-wal, bluefs-bdev-migrate, show-label, set-label-key, rm-label-key, prime-osd-dir, bluefs-log-dump") + ("command", po::value(&action), + "fsck, " + "repair, " + "bluefs-export, " + "bluefs-bdev-sizes, " + "bluefs-bdev-expand, " + "bluefs-bdev-new-db, " + "bluefs-bdev-new-wal, " + "bluefs-bdev-migrate, " + "show-label, " + "set-label-key, " + "rm-label-key, " + "prime-osd-dir, " + "bluefs-log-dump, " + "free-dump, " + "free-score") ; po::options_description po_all("All options"); po_all.add(po_options).add(po_positional); @@ -357,7 +375,24 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } } - + if (action == "free-score" || action == "free-dump") { + if (path.empty()) { + cerr << "must specify bluestore path" << std::endl; + exit(EXIT_FAILURE); + } + for (auto name : allocs_name) { + if (!name.empty() && + name != "block" && + name != "bluefs-db" && + name != "bluefs-wal" && + name != "bluefs-slow") { + cerr << "unknown allocator '" << name << "'" << std::endl; + exit(EXIT_FAILURE); + } + } + if (allocs_name.empty()) + allocs_name = vector{"block", "bluefs-db", "bluefs-wal", "bluefs-slow"}; + } vector args; if (log_file.size()) { args.push_back("--log-file"); @@ -792,6 +827,31 @@ int main(int argc, char **argv) } return r; } + } else if (action == "free-dump" || action == "free-score") { + AdminSocket *admin_socket = g_ceph_context->get_admin_socket(); + ceph_assert(admin_socket); + std::string action_name = action == "free-dump" ? "dump" : "score"; + validate_path(cct.get(), path, false); + BlueStore bluestore(cct.get(), path); + int r = bluestore.cold_open(); + if (r < 0) { + cerr << "error from cold_open: " << cpp_strerror(r) << std::endl; + exit(EXIT_FAILURE); + } + + for (auto alloc_name : allocs_name) { + ceph::bufferlist out; + bool b = admin_socket->execute_command( + "{\"prefix\": \"bluestore allocator " + action_name + " " + alloc_name + "\"}", out); + if (!b) { + cerr << "failure querying '" << alloc_name << "'" << std::endl; + exit(EXIT_FAILURE); + } + cout << alloc_name << ":" << std::endl; + cout << std::string(out.c_str(),out.length()) << std::endl; + } + + bluestore.cold_close(); } else { cerr << "unrecognized action " << action << std::endl; return 1; -- 2.39.5