From 07e6eb0b169365ce80ee505a18708f6c331caec8 Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Thu, 20 Nov 2025 22:06:18 +0300 Subject: [PATCH] Return no_inode_stats feature back --- src/blockstore/blockstore_heap.cpp | 57 +++++++++++++++++++++++++++++- src/blockstore/blockstore_heap.h | 3 ++ src/blockstore/blockstore_impl.cpp | 1 + 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/blockstore/blockstore_heap.cpp b/src/blockstore/blockstore_heap.cpp index 776ad87c..c12aa666 100644 --- a/src/blockstore/blockstore_heap.cpp +++ b/src/blockstore/blockstore_heap.cpp @@ -216,7 +216,7 @@ uint64_t blockstore_heap_t::get_pg_id(inode_t inode, uint64_t stripe) uint64_t pg_num = 0; uint64_t pool_id = (inode >> (64-POOL_ID_BITS)); auto sh_it = pool_shard_settings.find(pool_id); - if (sh_it != pool_shard_settings.end()) + if (sh_it != pool_shard_settings.end() && sh_it->second.pg_count > 0) { // like map_to_pg() pg_num = (stripe / sh_it->second.pg_stripe_size) % sh_it->second.pg_count + 1; @@ -1919,6 +1919,9 @@ bool blockstore_heap_t::is_data_used(uint64_t location) void blockstore_heap_t::use_data(inode_t inode, uint64_t location) { + auto sh_it = pool_shard_settings.find(INODE_POOL(inode)); + if (sh_it != pool_shard_settings.end() && sh_it->second.no_inode_stats) + inode = (INODE_POOL(inode) << POOL_ID_BITS); assert(!data_alloc->get(location / dsk->data_block_size)); data_alloc->set(location / dsk->data_block_size, true); inode_space_stats[inode] += dsk->data_block_size; @@ -1927,6 +1930,9 @@ void blockstore_heap_t::use_data(inode_t inode, uint64_t location) void blockstore_heap_t::free_data(inode_t inode, uint64_t location) { + auto sh_it = pool_shard_settings.find(INODE_POOL(inode)); + if (sh_it != pool_shard_settings.end() && sh_it->second.no_inode_stats) + inode = (INODE_POOL(inode) << POOL_ID_BITS); assert(data_alloc->get(location / dsk->data_block_size)); data_alloc->set(location / dsk->data_block_size, false); inode_space_stats[inode] -= dsk->data_block_size; @@ -2156,6 +2162,55 @@ uint64_t blockstore_heap_t::get_fsynced_lsn() return dsk->disable_meta_fsync && dsk->disable_journal_fsync ? completed_lsn : fsynced_lsn; } +void blockstore_heap_t::set_no_inode_stats(const std::vector & pool_ids) +{ + for (auto & ps: pool_shard_settings) + { + ps.second.no_inode_stats *= 2; + } + for (auto pool_id: pool_ids) + { + pool_shard_settings[pool_id].no_inode_stats |= 1; + } + for (auto & ps: pool_shard_settings) + { + // Recalculate if changed + if (ps.second.no_inode_stats == 2 || ps.second.no_inode_stats == 1) + recalc_inode_space_stats(ps.first, ps.second.no_inode_stats == 1); + ps.second.no_inode_stats &= 1; + } +} + +void blockstore_heap_t::recalc_inode_space_stats(uint64_t pool_id, bool per_inode) +{ + auto & ps = pool_shard_settings.at(pool_id); + auto sp_begin = inode_space_stats.lower_bound((pool_id << (64-POOL_ID_BITS))); + auto sp_end = inode_space_stats.lower_bound(((pool_id+1) << (64-POOL_ID_BITS))); + inode_space_stats.erase(sp_begin, sp_end); + uint32_t pg_count = ps.pg_count ? ps.pg_count : 1; + for (uint32_t pg_num = 1; pg_num <= pg_count; pg_num++) + { + auto & pg_idx = block_index[(pool_id << (64-POOL_ID_BITS)) | pg_num]; + for (auto & ip: pg_idx) + { + uint64_t space_id = per_inode ? ip.first : (pool_id << (64-POOL_ID_BITS)); + inode_map_iterate(ip.second, [&](heap_list_item_t *li) + { + uint32_t used_big = UINT32_MAX; + for (auto wr = &li->entry; wr && !wr->is_garbage(); wr = prev(wr)) + { + if ((wr->type() == BS_HEAP_BIG_WRITE || wr->type() == BS_HEAP_BIG_INTENT) && + wr->big().block_num != used_big) + { + inode_space_stats[space_id] += dsk->data_block_size; + used_big = wr->big().block_num; + } + } + }); + } + } +} + // sizeof(robin_hood_map) is 56 bytes which is quite a bit of overhead for us if an inode has, say, only 1 object. // small-size-optimized inode_maps utilize the fact that malloc returns 16-byte aligned pointers on 64-bit systems // and allow to reduce memory usage when some inodes on the OSD have a very low number of objects. 4 lower bits diff --git a/src/blockstore/blockstore_heap.h b/src/blockstore/blockstore_heap.h index e6097bbc..90c0ef82 100644 --- a/src/blockstore/blockstore_heap.h +++ b/src/blockstore/blockstore_heap.h @@ -19,6 +19,7 @@ struct pool_shard_settings_t { uint32_t pg_count; uint32_t pg_stripe_size; + uint32_t no_inode_stats; }; #define BS_HEAP_TYPE 0x07 @@ -249,6 +250,8 @@ public: bool recheck_small_writes(std::function)> read_buffer, int queue_depth); // reshard database according to the pool's PG count void reshard(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size); + void set_no_inode_stats(const std::vector & pool_ids); + void recalc_inode_space_stats(uint64_t pool_id, bool per_inode); // read an object entry and lock it against removal // in the future, may become asynchronous heap_entry_t *lock_and_read_entry(object_id oid); diff --git a/src/blockstore/blockstore_impl.cpp b/src/blockstore/blockstore_impl.cpp index 4d8cbe06..9225e5ea 100644 --- a/src/blockstore/blockstore_impl.cpp +++ b/src/blockstore/blockstore_impl.cpp @@ -350,6 +350,7 @@ void blockstore_impl_t::process_list(blockstore_op_t *op) void blockstore_impl_t::set_no_inode_stats(const std::vector & pool_ids) { + heap->set_no_inode_stats(pool_ids); } void blockstore_impl_t::dump_diagnostics()