From db1b9566e25b8683fe47fce2f4c86f54c89ea266 Mon Sep 17 00:00:00 2001 From: Xuehan Xu Date: Tue, 11 Jul 2023 17:48:53 +0800 Subject: [PATCH] crimson/os/seastore/transaction_manager: remap indirect mappings Signed-off-by: Xuehan Xu (cherry picked from commit e2c0ebec76aec12e8af6558fff22657acf64bd5d) --- src/crimson/os/seastore/lba_manager.h | 10 +++ .../lba_manager/btree/btree_lba_manager.h | 8 ++ src/crimson/os/seastore/transaction_manager.h | 82 ++++++++++++++----- 3 files changed, 79 insertions(+), 21 deletions(-) diff --git a/src/crimson/os/seastore/lba_manager.h b/src/crimson/os/seastore/lba_manager.h index 21933672e7efa..85ca6a5eb82d7 100644 --- a/src/crimson/os/seastore/lba_manager.h +++ b/src/crimson/os/seastore/lba_manager.h @@ -129,6 +129,16 @@ public: Transaction &t, laddr_t addr) = 0; + /** + * Increments ref count on extent + * + * @return returns resulting refcount + */ + virtual ref_ret incref_extent( + Transaction &t, + laddr_t addr, + int delta) = 0; + /** * Should be called after replay on each cached extent. * Implementation must initialize the LBAMapping on any diff --git a/src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.h b/src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.h index 403bcd05d3991..c14cb2682d9dd 100644 --- a/src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.h +++ b/src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.h @@ -276,6 +276,14 @@ public: return update_refcount(t, addr, 1); } + ref_ret incref_extent( + Transaction &t, + laddr_t addr, + int delta) final { + ceph_assert(delta > 0); + return update_refcount(t, addr, delta, false); + } + /** * init_cached_extent * diff --git a/src/crimson/os/seastore/transaction_manager.h b/src/crimson/os/seastore/transaction_manager.h index 8d5ca1c567cff..51d66e2f3818f 100644 --- a/src/crimson/os/seastore/transaction_manager.h +++ b/src/crimson/os/seastore/transaction_manager.h @@ -349,19 +349,31 @@ public: t, pin->get_val(), T::TYPE ).si_then([this, &t, remaps, original_laddr = pin->get_key(), + intermediate_base = pin->is_indirect() + ? pin->get_intermediate_base() + : L_ADDR_NULL, + intermediate_key = pin->is_indirect() + ? pin->get_intermediate_key() + : L_ADDR_NULL, original_paddr = pin->get_val(), original_len = pin->get_length()](auto ext) { std::optional original_bptr; LOG_PREFIX(TransactionManager::remap_pin); SUBDEBUGT(seastore_tm, "original laddr: {}, original paddr: {}, original length: {}," + " intermediate_base: {}, intermediate_key: {}," " remap to {} extents", - t, original_laddr, original_paddr, original_len, remaps.size()); + t, original_laddr, original_paddr, original_len, + intermediate_base, intermediate_key, remaps.size()); + ceph_assert( + (intermediate_base == L_ADDR_NULL) + == (intermediate_key == L_ADDR_NULL)); if (ext) { // FIXME: cannot and will not remap a dirty extent for now. ceph_assert(!ext->is_dirty()); ceph_assert(!ext->is_mutable()); - ceph_assert(ext->get_length() == original_len); + ceph_assert(ext->get_length() >= original_len); + ceph_assert(ext->get_paddr() == original_paddr); original_bptr = ext->get_bptr(); } return seastar::do_with( @@ -369,16 +381,19 @@ public: 0, std::move(original_bptr), std::vector(remaps.begin(), remaps.end()), - [this, &t, original_laddr, original_paddr, original_len] + [this, &t, original_laddr, original_paddr, + original_len, intermediate_base, intermediate_key] (auto &ret, auto &count, auto &original_bptr, auto &remaps) { return dec_ref(t, original_laddr - ).si_then([this, &t, &original_bptr, &ret, &count, &remaps, + ).si_then([this, &t, &original_bptr, &ret, &count, + &remaps, intermediate_base, intermediate_key, original_laddr, original_paddr, original_len](auto) { return trans_intr::do_for_each( remaps.begin(), remaps.end(), - [this, &t, &original_bptr, &ret, &count, - original_laddr, original_paddr, original_len](auto &remap) { + [this, &t, &original_bptr, &ret, + &count, intermediate_base, intermediate_key, + original_laddr, original_paddr, original_len](auto &remap) { LOG_PREFIX(TransactionManager::remap_pin); auto remap_offset = remap.offset; auto remap_len = remap.len; @@ -398,13 +413,24 @@ public: remap_paddr, remap_len, original_laddr, + intermediate_base, + intermediate_key, std::move(original_bptr) ).si_then([&ret, &count, remap_laddr](auto &&npin) { ceph_assert(npin->get_key() == remap_laddr); ret[count++] = std::move(npin); }); }); - }).handle_error_interruptible( + }).si_then([this, &t, intermediate_base, intermediate_key] { + if (N > 1 && intermediate_key != L_ADDR_NULL) { + return lba_manager->incref_extent( + t, intermediate_base, N - 1 + ).si_then([](auto) { + return seastar::now(); + }); + } + return LBAManager::ref_iertr::now(); + }).handle_error_interruptible( remap_pin_iertr::pass_further{}, crimson::ct_error::assert_all{ "TransactionManager::remap_pin hit invalid error" @@ -809,26 +835,40 @@ private: paddr_t remap_paddr, extent_len_t remap_length, laddr_t original_laddr, + laddr_t intermediate_base, + laddr_t intermediate_key, std::optional &&original_bptr) { LOG_PREFIX(TransactionManager::alloc_remapped_extent); SUBDEBUG(seastore_tm, "alloc remapped extent: remap_laddr: {}, " "remap_paddr: {}, remap_length: {}, has data in cache: {} ", remap_laddr, remap_paddr, remap_length, original_bptr.has_value() ? "true":"false"); - auto ext = cache->alloc_remapped_extent( - t, - remap_laddr, - remap_paddr, - remap_length, - original_laddr, - std::move(original_bptr)); - return lba_manager->alloc_extent( - t, - remap_laddr, - remap_length, - remap_paddr, - *ext - ).si_then([remap_laddr, remap_length, remap_paddr](auto &&ref) { + TCachedExtentRef ext; + auto fut = LBAManager::alloc_extent_iertr::make_ready_future< + LBAMappingRef>(); + assert((intermediate_key == L_ADDR_NULL) + == (intermediate_base == L_ADDR_NULL)); + if (intermediate_key == L_ADDR_NULL) { + // remapping direct mapping + ext = cache->alloc_remapped_extent( + t, + remap_laddr, + remap_paddr, + remap_length, + original_laddr, + std::move(original_bptr)); + fut = lba_manager->alloc_extent( + t, remap_laddr, remap_length, remap_paddr, *ext); + } else { + fut = lba_manager->clone_extent( + t, + remap_laddr, + remap_length, + intermediate_key, + remap_paddr, + intermediate_base); + } + return fut.si_then([remap_laddr, remap_length, remap_paddr](auto &&ref) { assert(ref->get_key() == remap_laddr); assert(ref->get_val() == remap_paddr); assert(ref->get_length() == remap_length); -- 2.39.5