diff --git a/src/blockstore/blockstore_heap.cpp b/src/blockstore/blockstore_heap.cpp index cb66c63a..c4a28176 100644 --- a/src/blockstore/blockstore_heap.cpp +++ b/src/blockstore/blockstore_heap.cpp @@ -1789,9 +1789,9 @@ void blockstore_heap_t::iterate_with_stable(heap_entry_t *obj, uint64_t max_lsn, } else { - // 1) 1 2 3 ROLLBACK(2) COMMIT(3) -> impossible + // 1) 1 2 3 ROLLBACK(2) COMMIT(3) -> 3 is unstable // 2) 1 2 3 4 ROLLBACK(3) COMMIT(2) -> OK - // 3) 1 2 3 ROLLBACK(2) 3 COMMIT(3) -> first 3 shouldn't be treated as stable + // 3) 1 2 3 ROLLBACK(2) 3 COMMIT(3) -> first 3 is unstable // 4) 1 2 3 COMMIT(3) ROLLBACK(2) -> impossible // I.e. a rollback always has version >= previous commit // 5) 1 2 3 4 5 ROLLBACK(4) 5 ROLLBACK(3) @@ -2316,7 +2316,7 @@ void blockstore_heap_t::set_no_inode_stats(const std::vector & pool_id { // 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); + recalc_inode_space_stats(ps.first, ps.second.no_inode_stats == 2); ps.second.no_inode_stats &= 1; } } @@ -2327,8 +2327,8 @@ void blockstore_heap_t::recalc_inode_space_stats(uint64_t pool_id, bool per_inod 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++) + uint32_t pg_count = ps.pg_count; + for (uint32_t pg_num = pg_count ? 1 : 0; pg_num <= pg_count; pg_num++) { auto & pg_idx = block_index[(pool_id << (64-POOL_ID_BITS)) | pg_num]; for (auto & ip: pg_idx) diff --git a/src/test/test_heap.cpp b/src/test/test_heap.cpp index 80251c65..1665b108 100644 --- a/src/test/test_heap.cpp +++ b/src/test/test_heap.cpp @@ -1702,6 +1702,51 @@ void test_big_intent_csums() printf("OK test_big_intent_csums\n"); } +void test_recalc_stats() +{ + blockstore_disk_t dsk; + _test_init(dsk, false); + std::vector buffer_area(dsk.journal_device_size); + blockstore_heap_t heap(&dsk, buffer_area.data()); + heap.finish_load(); + + { + _test_big_write(heap, dsk, 1, 0, 1, 0x20000, true, 0, 0, buffer_area.data()); + _test_big_write(heap, dsk, 2, 0, 1, 0x40000, true, 0, 0, buffer_area.data()); + _test_big_write(heap, dsk, 3, 0, 1, 0x60000, true, 0, 0, buffer_area.data()); + + uint32_t mblock = 999999; + object_id oid = { .inode = INODE_WITH_POOL(1, 1), .stripe = 0 }; + uint8_t ext_bitmap[dsk.clean_entry_bitmap_size]; + memset(ext_bitmap, 0x8e, dsk.clean_entry_bitmap_size); + heap_entry_t *obj = heap.read_entry(oid); + int res = heap.add_big_intent(oid, &obj, 2, 32768, 4096, ext_bitmap, buffer_area.data()+4096, NULL, &mblock); + assert(res == 0); + assert(mblock == 0); + heap.start_block_write(mblock); + heap.complete_block_write(mblock); + heap.complete_lsn_write(obj->lsn); + + auto & space = heap.get_inode_space_stats(); + assert(space.size() == 3); + assert(heap.get_data_used_space() == 0x60000); + + heap.set_no_inode_stats({1}); + + assert(space.size() == 1); + assert(space.at(INODE_WITH_POOL(1, 0)) == 0x60000); + + heap.set_no_inode_stats({}); + + assert(space.size() == 3); + assert(space.at(INODE_WITH_POOL(1, 1)) == 0x20000); + assert(space.at(INODE_WITH_POOL(1, 2)) == 0x20000); + assert(space.at(INODE_WITH_POOL(1, 3)) == 0x20000); + } + + printf("OK test_recalc_stats\n"); +} + // FIXME: Add a test for big_intent, incl. explicit_complete with big_intent over big_write over deletion over big_write :) // FIXME: Add a test for redirect_intent @@ -1739,5 +1784,6 @@ int main(int narg, char *args[]) test_intent_write(true); test_intent_write(false); test_big_intent_csums(); + test_recalc_stats(); return 0; }