From 16a9dac1678613b45fab9576b8bc4368a58c7434 Mon Sep 17 00:00:00 2001 From: Adam Kupczyk Date: Mon, 5 Aug 2019 15:15:07 +0200 Subject: [PATCH] BlueStore/allocator: Add command to inspect how much BlueStore's block can go to BlueFS. Signed-off-by: Adam Kupczyk --- src/os/bluestore/BlueFS.cc | 82 +++++++++++++++++++++++++++++++++++ src/os/bluestore/BlueFS.h | 11 +++++ src/os/bluestore/BlueStore.cc | 19 ++++++++ src/os/bluestore/BlueStore.h | 2 +- 4 files changed, 113 insertions(+), 1 deletion(-) diff --git a/src/os/bluestore/BlueFS.cc b/src/os/bluestore/BlueFS.cc index e5d9174730c3b..8d765e257262d 100644 --- a/src/os/bluestore/BlueFS.cc +++ b/src/os/bluestore/BlueFS.cc @@ -10,6 +10,7 @@ #include "BlockDevice.h" #include "Allocator.h" #include "include/ceph_assert.h" +#include "common/admin_socket.h" #define dout_context cct #define dout_subsys ceph_subsys_bluefs @@ -42,6 +43,78 @@ static void slow_discard_cb(void *priv, void* priv2) { bluefs->handle_discard(BlueFS::BDEV_SLOW, *tmp); } +class BlueFS::SocketHook : public AdminSocketHook { + BlueFS* bluefs; +public: + static BlueFS::SocketHook* create(BlueFS* bluefs) + { + BlueFS::SocketHook* hook = nullptr; + AdminSocket* admin_socket = bluefs->cct->get_admin_socket(); + if (admin_socket) { + hook = new BlueFS::SocketHook(bluefs); + int r = admin_socket->register_command("bluestore bluefs available", + "bluestore bluefs available " + "name=alloc_size,type=CephInt,req=false", + hook, + "Report available space for bluefs. " + "If alloc_size set, make simulation."); + if (r != 0) { + ldout(bluefs->cct, 1) << __func__ << " cannot register SocketHook" << dendl; + delete hook; + hook = nullptr; + } + } + return hook; + } + + ~SocketHook() { + AdminSocket* admin_socket = bluefs->cct->get_admin_socket(); + int r = admin_socket->unregister_command("bluestore bluefs available"); + ceph_assert(r == 0); + } +private: + SocketHook(BlueFS* bluefs) : + bluefs(bluefs) {} + 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 bluefs available") { + int64_t alloc_size = 0; + cmd_getval(bluefs->cct, cmdmap, "alloc_size", alloc_size); + if ((alloc_size & (alloc_size - 1)) != 0) { + ss << "Invalid allocation size:'" << alloc_size << std::endl; + } + if (alloc_size == 0) + alloc_size = bluefs->cct->_conf->bluefs_alloc_size; + Formatter *f = Formatter::create(format, "json-pretty", "json-pretty"); + f->open_object_section("bluefs_available_space"); + for (unsigned dev = BDEV_WAL; dev <= BDEV_SLOW; dev++) { + if (bluefs->bdev[dev]) { + f->open_object_section("dev"); + f->dump_string("device", bluefs->get_device_name(dev)); + ceph_assert(bluefs->alloc[dev]); + f->dump_int("free", bluefs->alloc[dev]->get_free()); + f->close_section(); + } + } + size_t extra_space = 0; + if (bluefs->slow_dev_expander) { + extra_space = bluefs->slow_dev_expander->available_freespace(alloc_size); + } + f->dump_int("available_from_bluestore", extra_space); + f->close_section(); + f->flush(ss); + delete f; + } else { + ss << "Invalid command" << std::endl; + r = false; + } + out.append(ss); + return r; + } +}; + BlueFS::BlueFS(CephContext* cct) : cct(cct), bdev(MAX_BDEV), @@ -51,10 +124,12 @@ BlueFS::BlueFS(CephContext* cct) discard_cb[BDEV_WAL] = wal_discard_cb; discard_cb[BDEV_DB] = db_discard_cb; discard_cb[BDEV_SLOW] = slow_discard_cb; + asok_hook = SocketHook::create(this); } BlueFS::~BlueFS() { + delete asok_hook; for (auto p : ioc) { if (p) p->aio_wait(); @@ -2472,6 +2547,13 @@ void BlueFS::flush_bdev() } } +const char* BlueFS::get_device_name(unsigned id) +{ + if (id >= MAX_BDEV) return "BDEV_INV"; + const char* names[] = {"BDEV_WAL", "BDEV_DB", "BDEV_SLOW", "BDEV_NEWWAL", "BDEV_NEWDB"}; + return names[id]; +} + int BlueFS::_expand_slow_device(uint64_t need, PExtentVector& extents) { int r = -ENOSPC; diff --git a/src/os/bluestore/BlueFS.h b/src/os/bluestore/BlueFS.h index c0b4795613595..ce43da2d82b64 100644 --- a/src/os/bluestore/BlueFS.h +++ b/src/os/bluestore/BlueFS.h @@ -63,6 +63,13 @@ public: uint64_t min_size, uint64_t size, PExtentVector& extents) = 0; + /** Reports amount of space that can be transferred to BlueFS. + * This gives either current state, when alloc_size is currently used + * BlueFS's size, or simulation when alloc_size is different. + * @params + * alloc_size - allocation unit size to check + */ + virtual size_t available_freespace(uint64_t alloc_size) = 0; }; class BlueFS { @@ -305,6 +312,9 @@ private: BlueFSDeviceExpander* slow_dev_expander = nullptr; + class SocketHook; + SocketHook* asok_hook = nullptr; + void _init_logger(); void _shutdown_logger(); void _update_logger_stats(); @@ -318,6 +328,7 @@ private: void _drop_link(FileRef f); int _get_slow_device_id() { return bdev[BDEV_SLOW] ? BDEV_SLOW : BDEV_DB; } + const char* get_device_name(unsigned id); int _expand_slow_device(uint64_t min_size, PExtentVector& extents); int _allocate(uint8_t bdev, uint64_t len, bluefs_fnode_t* node); diff --git a/src/os/bluestore/BlueStore.cc b/src/os/bluestore/BlueStore.cc index 3e7e175fb8cf8..b2f17fe07bba0 100644 --- a/src/os/bluestore/BlueStore.cc +++ b/src/os/bluestore/BlueStore.cc @@ -5619,6 +5619,25 @@ int BlueStore::allocate_bluefs_freespace( return 0; } +size_t BlueStore::available_freespace(uint64_t alloc_size) { + size_t total = 0; + auto iterated_allocation = [&](size_t off, size_t len) { + //only count in size that is alloc_size aligned + size_t dist_to_alignment; + size_t offset_in_block = off & (alloc_size - 1); + if (offset_in_block == 0) + dist_to_alignment = 0; + else + dist_to_alignment = alloc_size - offset_in_block; + if (dist_to_alignment >= len) + return; + len -= dist_to_alignment; + total += p2align(len, alloc_size); + }; + alloc->dump(iterated_allocation); + return total; +} + int64_t BlueStore::_get_bluefs_size_delta(uint64_t bluefs_free, uint64_t bluefs_total) { float bluefs_free_ratio = (float)bluefs_free / (float)bluefs_total; diff --git a/src/os/bluestore/BlueStore.h b/src/os/bluestore/BlueStore.h index 319c159db64fb..edd34f07093d7 100644 --- a/src/os/bluestore/BlueStore.h +++ b/src/os/bluestore/BlueStore.h @@ -3036,7 +3036,7 @@ private: PExtentVector& extents) override { return allocate_bluefs_freespace(min_size, size, &extents); }; - + size_t available_freespace(uint64_t alloc_size) override; inline bool _use_rotational_settings(); }; -- 2.39.5