summaryrefslogtreecommitdiffstats
path: root/src/test/crimson/seastore/test_extmap_manager.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/crimson/seastore/test_extmap_manager.cc')
-rw-r--r--src/test/crimson/seastore/test_extmap_manager.cc283
1 files changed, 283 insertions, 0 deletions
diff --git a/src/test/crimson/seastore/test_extmap_manager.cc b/src/test/crimson/seastore/test_extmap_manager.cc
new file mode 100644
index 000000000..8b2588011
--- /dev/null
+++ b/src/test/crimson/seastore/test_extmap_manager.cc
@@ -0,0 +1,283 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "test/crimson/gtest_seastar.h"
+#include "test/crimson/seastore/transaction_manager_test_state.h"
+
+#include "crimson/os/seastore/cache.h"
+#include "crimson/os/seastore/transaction_manager.h"
+#include "crimson/os/seastore/segment_manager.h"
+#include "crimson/os/seastore/extentmap_manager.h"
+
+#include "test/crimson/seastore/test_block.h"
+
+using namespace crimson;
+using namespace crimson::os;
+using namespace crimson::os::seastore;
+
+namespace {
+ [[maybe_unused]] seastar::logger& logger() {
+ return crimson::get_logger(ceph_subsys_test);
+ }
+}
+
+
+struct extentmap_manager_test_t :
+ public seastar_test_suite_t,
+ TMTestState {
+
+ ExtentMapManagerRef extmap_manager;
+
+ extentmap_manager_test_t() {}
+
+ seastar::future<> set_up_fut() final {
+ return tm_setup().then([this] {
+ extmap_manager = extentmap_manager::create_extentmap_manager(*tm);
+ return seastar::now();
+ });
+ }
+
+ seastar::future<> tear_down_fut() final {
+ return tm_teardown().then([this] {
+ extmap_manager.reset();
+ return seastar::now();
+ });
+ }
+
+ using test_extmap_t = std::map<uint32_t, lext_map_val_t>;
+ test_extmap_t test_ext_mappings;
+
+ extent_mapping_t insert_extent(
+ extmap_root_t &extmap_root,
+ Transaction &t,
+ uint32_t lo,
+ lext_map_val_t val) {
+ auto extent = extmap_manager->add_lextent(extmap_root, t, lo, val).unsafe_get0();
+ EXPECT_EQ(lo, extent.logical_offset);
+ EXPECT_EQ(val.laddr, extent.laddr);
+ EXPECT_EQ(val.length, extent.length);
+ test_ext_mappings.emplace(extent.logical_offset,
+ lext_map_val_t{extent.laddr, extent.length});
+ return extent;
+ }
+
+ extent_map_list_t find_extent(
+ extmap_root_t &extmap_root,
+ Transaction &t,
+ uint32_t lo,
+ uint32_t len) {
+ auto extent = extmap_manager->find_lextent(extmap_root, t, lo, len).unsafe_get0();
+ EXPECT_EQ(lo, extent.front().logical_offset);
+ EXPECT_EQ(len, extent.front().length);
+ return extent;
+ }
+
+ extent_map_list_t findno_extent(
+ extmap_root_t &extmap_root,
+ Transaction &t,
+ uint32_t lo,
+ uint32_t len) {
+ auto extent = extmap_manager->find_lextent(extmap_root, t, lo, len).unsafe_get0();
+ EXPECT_EQ(extent.empty(), true);
+ return extent;
+ }
+
+ void rm_extent(
+ extmap_root_t &extmap_root,
+ Transaction &t,
+ uint32_t lo,
+ lext_map_val_t val ) {
+ auto ret = extmap_manager->rm_lextent(extmap_root, t, lo, val).unsafe_get0();
+ EXPECT_TRUE(ret);
+ test_ext_mappings.erase(lo);
+ }
+
+ void check_mappings(extmap_root_t &extmap_root, Transaction &t) {
+ for (const auto& [lo, ext]: test_ext_mappings){
+ const auto ext_list = find_extent(extmap_root, t, lo, ext.length);
+ ASSERT_EQ(ext_list.size(), 1);
+ const auto& ext_map = ext_list.front();
+ EXPECT_EQ(ext.laddr, ext_map.laddr);
+ EXPECT_EQ(ext.length, ext_map.length);
+ }
+ }
+
+ void check_mappings(extmap_root_t &extmap_root) {
+ auto t = tm->create_transaction();
+ check_mappings(extmap_root, *t);
+ }
+
+ void replay() {
+ logger().debug("{}: begin", __func__);
+ restart();
+ extmap_manager = extentmap_manager::create_extentmap_manager(*tm);
+ logger().debug("{}: end", __func__);
+ }
+
+
+};
+
+TEST_F(extentmap_manager_test_t, basic)
+{
+ run_async([this] {
+ extmap_root_t extmap_root(0, L_ADDR_NULL);
+ {
+ auto t = tm->create_transaction();
+ extmap_root = extmap_manager->initialize_extmap(*t).unsafe_get0();
+ tm->submit_transaction(std::move(t)).unsafe_get();
+ }
+
+ uint32_t len = 4096;
+ uint32_t lo = 0x1 * len;
+ {
+ auto t = tm->create_transaction();
+ logger().debug("first transaction");
+ [[maybe_unused]] auto addref = insert_extent(extmap_root, *t, lo, {lo, len});
+ [[maybe_unused]] auto seekref = find_extent(extmap_root, *t, lo, len);
+ tm->submit_transaction(std::move(t)).unsafe_get();
+ }
+ {
+ auto t = tm->create_transaction();
+ logger().debug("second transaction");
+ auto seekref = find_extent(extmap_root, *t, lo, len);
+ rm_extent(extmap_root, *t, lo, {seekref.front().laddr, len});
+ [[maybe_unused]] auto seekref2 = findno_extent(extmap_root, *t, lo, len);
+ tm->submit_transaction(std::move(t)).unsafe_get();
+ }
+ {
+ auto t = tm->create_transaction();
+ logger().debug("third transaction");
+ [[maybe_unused]] auto seekref = findno_extent(extmap_root, *t, lo, len);
+ tm->submit_transaction(std::move(t)).unsafe_get();
+ }
+ });
+}
+
+TEST_F(extentmap_manager_test_t, force_leafnode_split)
+{
+ run_async([this] {
+ extmap_root_t extmap_root(0, L_ADDR_NULL);
+ {
+ auto t = tm->create_transaction();
+ extmap_root = extmap_manager->initialize_extmap(*t).unsafe_get0();
+ tm->submit_transaction(std::move(t)).unsafe_get();
+ }
+ uint32_t len = 4096;
+ uint32_t lo = 0;
+ for (unsigned i = 0; i < 40; i++) {
+ auto t = tm->create_transaction();
+ logger().debug("opened transaction");
+ for (unsigned j = 0; j < 10; ++j) {
+ [[maybe_unused]] auto addref = insert_extent(extmap_root, *t, lo, {lo, len});
+ lo += len;
+ if ((i % 20 == 0) && (j == 5)) {
+ check_mappings(extmap_root, *t);
+ }
+ }
+ logger().debug("force split submit transaction i = {}", i);
+ tm->submit_transaction(std::move(t)).unsafe_get();
+ check_mappings(extmap_root);
+ }
+ });
+
+}
+
+TEST_F(extentmap_manager_test_t, force_leafnode_split_merge)
+{
+ run_async([this] {
+ extmap_root_t extmap_root(0, L_ADDR_NULL);
+ {
+ auto t = tm->create_transaction();
+ extmap_root = extmap_manager->initialize_extmap(*t).unsafe_get0();
+ tm->submit_transaction(std::move(t)).unsafe_get();
+ }
+ uint32_t len = 4096;
+ uint32_t lo = 0;
+ for (unsigned i = 0; i < 80; i++) {
+ auto t = tm->create_transaction();
+ logger().debug("opened split_merge transaction");
+ for (unsigned j = 0; j < 5; ++j) {
+ [[maybe_unused]] auto addref = insert_extent(extmap_root, *t, lo, {lo, len});
+ lo += len;
+ if ((i % 10 == 0) && (j == 3)) {
+ check_mappings(extmap_root, *t);
+ }
+ }
+ logger().debug("submitting transaction");
+ tm->submit_transaction(std::move(t)).unsafe_get();
+ if (i % 50 == 0) {
+ check_mappings(extmap_root);
+ }
+ }
+ auto t = tm->create_transaction();
+ int i = 0;
+ for (auto iter = test_ext_mappings.begin(); iter != test_ext_mappings.end();) {
+ auto [lo, ext] = *iter;
+ ++iter;
+ if (i % 3 != 0) {
+ rm_extent(extmap_root, *t, lo, ext);
+ }
+ i++;
+
+ if (i % 10 == 0) {
+ logger().debug("submitting transaction i= {}", i);
+ tm->submit_transaction(std::move(t)).unsafe_get();
+ t = tm->create_transaction();
+ }
+ if (i % 100 == 0) {
+ logger().debug("check_mappings i= {}", i);
+ check_mappings(extmap_root, *t);
+ check_mappings(extmap_root);
+ }
+ }
+ logger().debug("finally submitting transaction ");
+ tm->submit_transaction(std::move(t)).unsafe_get();
+ });
+}
+
+TEST_F(extentmap_manager_test_t, force_leafnode_split_merge_replay)
+{
+ run_async([this] {
+ extmap_root_t extmap_root(0, L_ADDR_NULL);
+ {
+ auto t = tm->create_transaction();
+ extmap_root = extmap_manager->initialize_extmap(*t).unsafe_get0();
+ tm->submit_transaction(std::move(t)).unsafe_get();
+ replay();
+ }
+ uint32_t len = 4096;
+ uint32_t lo = 0;
+ for (unsigned i = 0; i < 50; i++) {
+ auto t = tm->create_transaction();
+ logger().debug("opened split_merge transaction");
+ for (unsigned j = 0; j < 5; ++j) {
+ [[maybe_unused]] auto addref = insert_extent(extmap_root, *t, lo, {lo, len});
+ lo += len;
+ }
+ logger().debug("submitting transaction");
+ tm->submit_transaction(std::move(t)).unsafe_get();
+ }
+ replay();
+ auto t = tm->create_transaction();
+ int i = 0;
+ for (auto iter = test_ext_mappings.begin(); iter != test_ext_mappings.end();) {
+ auto [lo, ext] = *iter;
+ ++iter;
+ rm_extent(extmap_root, *t, lo, ext);
+ i++;
+
+ if (i % 10 == 0) {
+ logger().debug("submitting transaction i= {}", i);
+ tm->submit_transaction(std::move(t)).unsafe_get();
+ t = tm->create_transaction();
+ }
+ if (i% 100 == 0){
+ check_mappings(extmap_root);
+ }
+ }
+ logger().debug("finally submitting transaction ");
+ tm->submit_transaction(std::move(t)).unsafe_get();
+ replay();
+ check_mappings(extmap_root);
+ });
+}