From: Xuehan Xu Date: Wed, 21 Feb 2024 06:52:41 +0000 (+0800) Subject: crimson/os/seastore/lba_manager: add the alloc_extents interface X-Git-Tag: testing/wip-lusov-testing-20240611.123850-squid~50^2~5 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=52a934138ab1dcaa4fa6afe2be949d59bb07281f;p=ceph-ci.git crimson/os/seastore/lba_manager: add the alloc_extents interface This is necessary because continuous data may be splitted into multiple extents if the size of each data extent is constrained Signed-off-by: Xuehan Xu (cherry picked from commit ab916224e3e254e31025fb1723ca7e1147dee2c7) --- diff --git a/src/crimson/os/seastore/lba_manager.h b/src/crimson/os/seastore/lba_manager.h index 8794bc9405d..e46298dd44f 100644 --- a/src/crimson/os/seastore/lba_manager.h +++ b/src/crimson/os/seastore/lba_manager.h @@ -88,6 +88,14 @@ public: LogicalCachedExtent &nextent, extent_ref_count_t refcount = EXTENT_DEFAULT_REF_COUNT) = 0; + using alloc_extents_ret = alloc_extent_iertr::future< + std::vector>; + virtual alloc_extents_ret alloc_extents( + Transaction &t, + laddr_t hint, + std::vector extents, + extent_ref_count_t refcount) = 0; + virtual alloc_extent_ret clone_mapping( Transaction &t, laddr_t hint, diff --git a/src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.cc b/src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.cc index c2980d4a41b..74364d6245c 100644 --- a/src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.cc +++ b/src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.cc @@ -300,16 +300,17 @@ BtreeLBAManager::_get_mapping( }); } -BtreeLBAManager::alloc_extent_ret -BtreeLBAManager::_alloc_extent( +BtreeLBAManager::alloc_extents_ret +BtreeLBAManager::_alloc_extents( Transaction &t, laddr_t hint, - extent_len_t len, - pladdr_t addr, - uint32_t checksum, - LogicalCachedExtent* nextent, + std::vector &alloc_infos, extent_ref_count_t refcount) { + extent_len_t total_len = 0; + for (auto &info : alloc_infos) { + total_len += info.len; + } struct state_t { laddr_t last_end; @@ -319,77 +320,98 @@ BtreeLBAManager::_alloc_extent( state_t(laddr_t hint) : last_end(hint) {} }; - LOG_PREFIX(BtreeLBAManager::_alloc_extent); - TRACET("{}~{}, hint={}, refcount={}", t, addr, len, hint, refcount); + LOG_PREFIX(BtreeLBAManager::_alloc_extents); + TRACET("{}~{}, hint={}, num of extents: {}, refcount={}", + t, alloc_infos.front().val, total_len, hint, alloc_infos.size(), refcount); auto c = get_context(t); - ++stats.num_alloc_extents; + stats.num_alloc_extents += alloc_infos.size(); auto lookup_attempts = stats.num_alloc_extents_iter_nexts; - return crimson::os::seastore::with_btree_state( - cache, - c, - hint, - [this, FNAME, c, hint, len, addr, lookup_attempts, - &t, nextent, refcount, checksum](auto &btree, auto &state) { + return seastar::do_with( + std::vector(), + [this, FNAME, &alloc_infos, hint, &t, total_len, c, + lookup_attempts, refcount](auto &rets) { + return crimson::os::seastore::with_btree_state( + cache, + c, + hint, + [this, c, hint, total_len, addr=alloc_infos.front().val, &rets, refcount, + lookup_attempts, &t, &alloc_infos, FNAME](auto &btree, auto &state) { return LBABtree::iterate_repeat( c, btree.upper_bound_right(c, hint), - [this, &state, len, addr, &t, hint, FNAME, lookup_attempts](auto &pos) { - ++stats.num_alloc_extents_iter_nexts; - if (pos.is_end()) { - DEBUGT("{}~{}, hint={}, state: end, done with {} attempts, insert at {}", - t, addr, len, hint, - stats.num_alloc_extents_iter_nexts - lookup_attempts, - state.last_end); - state.insert_iter = pos; - return typename LBABtree::iterate_repeat_ret_inner( - interruptible::ready_future_marker{}, - seastar::stop_iteration::yes); - } else if (pos.get_key() >= (state.last_end + len)) { - DEBUGT("{}~{}, hint={}, state: {}~{}, done with {} attempts, insert at {} -- {}", - t, addr, len, hint, - pos.get_key(), pos.get_val().len, - stats.num_alloc_extents_iter_nexts - lookup_attempts, - state.last_end, - pos.get_val()); - state.insert_iter = pos; - return typename LBABtree::iterate_repeat_ret_inner( - interruptible::ready_future_marker{}, - seastar::stop_iteration::yes); - } else { - state.last_end = pos.get_key() + pos.get_val().len; - TRACET("{}~{}, hint={}, state: {}~{}, repeat ... -- {}", - t, addr, len, hint, - pos.get_key(), pos.get_val().len, - pos.get_val()); - return typename LBABtree::iterate_repeat_ret_inner( - interruptible::ready_future_marker{}, - seastar::stop_iteration::no); - } - }).si_then([FNAME, c, addr, len, hint, &btree, - &state, nextent, refcount, checksum] { + [this, &state, total_len, addr, &t, hint, + lookup_attempts, FNAME](auto &pos) { + ++stats.num_alloc_extents_iter_nexts; + if (pos.is_end()) { + DEBUGT("{}~{}, hint={}, state: end, done with {} attempts, insert at {}", + t, addr, total_len, hint, + stats.num_alloc_extents_iter_nexts - lookup_attempts, + state.last_end); + state.insert_iter = pos; + return typename LBABtree::iterate_repeat_ret_inner( + interruptible::ready_future_marker{}, + seastar::stop_iteration::yes); + } else if (pos.get_key() >= (state.last_end + total_len)) { + DEBUGT("{}~{}, hint={}, state: {}~{}, done with {} attempts, insert at {} -- {}", + t, addr, total_len, hint, + pos.get_key(), pos.get_val().len, + stats.num_alloc_extents_iter_nexts - lookup_attempts, + state.last_end, + pos.get_val()); + state.insert_iter = pos; + return typename LBABtree::iterate_repeat_ret_inner( + interruptible::ready_future_marker{}, + seastar::stop_iteration::yes); + } else { + state.last_end = pos.get_key() + pos.get_val().len; + TRACET("{}~{}, hint={}, state: {}~{}, repeat ... -- {}", + t, addr, total_len, hint, + pos.get_key(), pos.get_val().len, + pos.get_val()); + return typename LBABtree::iterate_repeat_ret_inner( + interruptible::ready_future_marker{}, + seastar::stop_iteration::no); + } + }).si_then([c, addr, hint, &btree, &state, &alloc_infos, + total_len, &rets, refcount, FNAME] { + return trans_intr::do_for_each( + alloc_infos, + [c, addr, hint, &btree, &state, FNAME, + total_len, &rets, refcount](auto &alloc_info) { return btree.insert( c, *state.insert_iter, state.last_end, - lba_map_val_t{len, pladdr_t(addr), refcount, checksum}, - nextent - ).si_then([&state, FNAME, c, addr, len, hint, nextent](auto &&p) { + lba_map_val_t{ + alloc_info.len, + pladdr_t(alloc_info.val), + refcount, + alloc_info.checksum}, + alloc_info.extent + ).si_then([&state, c, addr, total_len, hint, FNAME, + &alloc_info, &rets](auto &&p) { auto [iter, inserted] = std::move(p); TRACET("{}~{}, hint={}, inserted at {}", - c.trans, addr, len, hint, state.last_end); - if (nextent) { - ceph_assert(addr.is_paddr()); - nextent->set_laddr(iter.get_key()); + c.trans, addr, total_len, hint, state.last_end); + if (alloc_info.extent) { + ceph_assert(alloc_info.val.is_paddr()); + alloc_info.extent->set_laddr(iter.get_key()); } ceph_assert(inserted); - state.ret = iter; + rets.emplace_back(iter.get_pin(c)); + return iter.next(c).si_then([&state, &alloc_info](auto it) { + state.insert_iter = it; + state.last_end += alloc_info.len; + }); }); }); - }).si_then([c](auto &&state) { + }); + }).si_then([&rets](auto &&state) { return alloc_extent_iertr::make_ready_future< - LBAMappingRef>(state.ret->get_pin(c)); + std::vector>(std::move(rets)); }); + }); } static bool is_lba_node(const CachedExtent &e) 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 2641e940ee4..c43d60dcb5b 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 @@ -214,19 +214,35 @@ public: Transaction &t, laddr_t offset) final; + + struct alloc_mapping_info_t { + extent_len_t len = 0; + pladdr_t val; + uint32_t checksum = 0; + LogicalCachedExtent* extent = nullptr; + }; + alloc_extent_ret reserve_region( Transaction &t, laddr_t hint, - extent_len_t len) + extent_len_t len) final { - return _alloc_extent( - t, - hint, - len, - P_ADDR_ZERO, - 0, - nullptr, - EXTENT_DEFAULT_REF_COUNT); + std::vector alloc_infos = { + alloc_mapping_info_t{len, P_ADDR_ZERO, 0, nullptr}}; + return seastar::do_with( + std::move(alloc_infos), + [&t, hint, this](auto &alloc_infos) { + return _alloc_extents( + t, + hint, + alloc_infos, + EXTENT_DEFAULT_REF_COUNT + ).si_then([](auto mappings) { + assert(mappings.size() == 1); + auto mapping = std::move(mappings.front()); + return mapping; + }); + }); } alloc_extent_ret clone_mapping( @@ -234,36 +250,45 @@ public: laddr_t hint, extent_len_t len, laddr_t intermediate_key, - laddr_t intermediate_base) + laddr_t intermediate_base) final { assert(intermediate_key != L_ADDR_NULL); assert(intermediate_base != L_ADDR_NULL); - return _alloc_extent( - t, - hint, - len, - intermediate_key, - 0, // crc will only be used and checked with LBA direct mappings + std::vector alloc_infos = { + alloc_mapping_info_t{ + len, + intermediate_key, + 0, // crc will only be used and checked with LBA direct mappings // also see pin_to_extent(_by_type) - nullptr, - EXTENT_DEFAULT_REF_COUNT - ).si_then([&t, this, intermediate_base](auto indirect_mapping) { - assert(indirect_mapping->is_indirect()); - return update_refcount(t, intermediate_base, 1, false - ).si_then([imapping=std::move(indirect_mapping)](auto res) mutable { - auto mapping = std::move(res.mapping); - ceph_assert(mapping->is_stable()); - mapping->make_indirect( - imapping->get_key(), - imapping->get_length(), - imapping->get_intermediate_key()); - return seastar::make_ready_future< - LBAMappingRef>(std::move(mapping)); - }); - }).handle_error_interruptible( - crimson::ct_error::input_output_error::pass_further{}, - crimson::ct_error::assert_all{"unexpect enoent"} - ); + nullptr}}; + return seastar::do_with( + std::move(alloc_infos), + [this, &t, intermediate_base, hint](auto &alloc_infos) { + return _alloc_extents( + t, + hint, + alloc_infos, + EXTENT_DEFAULT_REF_COUNT + ).si_then([&t, this, intermediate_base](auto mappings) { + assert(mappings.size() == 1); + auto indirect_mapping = std::move(mappings.front()); + assert(indirect_mapping->is_indirect()); + return update_refcount(t, intermediate_base, 1, false + ).si_then([imapping=std::move(indirect_mapping)](auto p) mutable { + auto mapping = std::move(p.mapping); + ceph_assert(mapping->is_stable()); + mapping->make_indirect( + imapping->get_key(), + imapping->get_length(), + imapping->get_intermediate_key()); + return seastar::make_ready_future< + LBAMappingRef>(std::move(mapping)); + }); + }).handle_error_interruptible( + crimson::ct_error::input_output_error::pass_further{}, + crimson::ct_error::assert_all{"unexpect enoent"} + ); + }); } alloc_extent_ret alloc_extent( @@ -274,14 +299,43 @@ public: { // The real checksum will be updated upon transaction commit assert(ext.get_last_committed_crc() == 0); - return _alloc_extent( - t, - hint, - ext.get_length(), - ext.get_paddr(), - ext.get_last_committed_crc(), - &ext, - refcount); + std::vector alloc_infos = {{ + ext.get_length(), ext.get_paddr(), ext.get_last_committed_crc(), &ext}}; + return seastar::do_with( + std::move(alloc_infos), + [this, &t, hint, refcount](auto &alloc_infos) { + return _alloc_extents( + t, + hint, + alloc_infos, + refcount + ).si_then([](auto mappings) { + assert(mappings.size() == 1); + auto mapping = std::move(mappings.front()); + return mapping; + }); + }); + } + + alloc_extents_ret alloc_extents( + Transaction &t, + laddr_t hint, + std::vector extents, + extent_ref_count_t refcount) final + { + std::vector alloc_infos; + for (auto &extent : extents) { + alloc_infos.emplace_back(alloc_mapping_info_t{ + extent->get_length(), + pladdr_t(extent->get_paddr()), + extent->get_last_committed_crc(), + extent.get()}); + } + return seastar::do_with( + std::move(alloc_infos), + [this, &t, hint, refcount](auto &alloc_infos) { + return _alloc_extents(t, hint, alloc_infos, refcount); + }); } ref_ret decref_extent( @@ -409,13 +463,10 @@ private: update_func_t &&f, LogicalCachedExtent*); - alloc_extent_ret _alloc_extent( + alloc_extents_ret _alloc_extents( Transaction &t, laddr_t hint, - extent_len_t len, - pladdr_t addr, - uint32_t checksum, - LogicalCachedExtent*, + std::vector &alloc_infos, extent_ref_count_t refcount); using _get_mapping_ret = get_mapping_iertr::future;