From 554db8d88dc4149a1698cb31c64b2a5c6f29f4ee Mon Sep 17 00:00:00 2001 From: Xuehan Xu Date: Mon, 6 Nov 2023 18:33:01 +0800 Subject: [PATCH] crimson/os/seastore/transaction_manager: TransactionManager::alloc_extent(s) may return enospc Signed-off-by: Xuehan Xu --- src/crimson/common/errorator.h | 17 +++++++++++ src/crimson/os/seastore/cache.h | 13 ++++---- .../flat_collection_manager.cc | 5 +++- .../os/seastore/extent_placement_manager.h | 20 ++++++++----- .../os/seastore/object_data_handler.cc | 21 +++++++++---- .../omap_manager/btree/btree_omap_manager.cc | 10 +++++-- .../btree/omap_btree_node_impl.cc | 30 +++++++++++++++---- .../node_extent_manager/seastore.h | 5 +++- .../random_block_manager/block_rb_manager.cc | 3 ++ src/crimson/os/seastore/transaction_manager.h | 9 +++++- .../seastore/test_transaction_manager.cc | 15 ++++++++-- 11 files changed, 116 insertions(+), 32 deletions(-) diff --git a/src/crimson/common/errorator.h b/src/crimson/common/errorator.h index c5d63d5b9c1d5..656af5813560f 100644 --- a/src/crimson/common/errorator.h +++ b/src/crimson/common/errorator.h @@ -200,6 +200,23 @@ struct unthrowable_wrapper : error_t> { } }; + class assert_failure { + const char* const msg = nullptr; + public: + template + assert_failure(const char (&msg)[N]) + : msg(msg) { + } + assert_failure() = default; + + void operator()(const unthrowable_wrapper&) { + if (msg) { + ceph_abort(msg); + } else { + ceph_abort(); + } + } + }; private: // can be used only to initialize the `instance` member diff --git a/src/crimson/os/seastore/cache.h b/src/crimson/os/seastore/cache.h index a6aeb357148f4..75463f465fe14 100644 --- a/src/crimson/os/seastore/cache.h +++ b/src/crimson/os/seastore/cache.h @@ -884,17 +884,20 @@ public: #else auto result = epm.alloc_new_non_data_extent(t, T::TYPE, length, hint, gen); #endif - auto ret = CachedExtent::make_cached_extent_ref(std::move(result.bp)); + if (!result) { + return nullptr; + } + auto ret = CachedExtent::make_cached_extent_ref(std::move(result->bp)); ret->init(CachedExtent::extent_state_t::INITIAL_WRITE_PENDING, - result.paddr, + result->paddr, hint, - result.gen, + result->gen, t.get_trans_id()); t.add_fresh_extent(ret); SUBDEBUGT(seastore_cache, "allocated {} {}B extent at {}, hint={}, gen={} -- {}", - t, T::TYPE, length, result.paddr, - hint, rewrite_gen_printer_t{result.gen}, *ret); + t, T::TYPE, length, result->paddr, + hint, rewrite_gen_printer_t{result->gen}, *ret); return ret; } /** diff --git a/src/crimson/os/seastore/collection_manager/flat_collection_manager.cc b/src/crimson/os/seastore/collection_manager/flat_collection_manager.cc index 81353655694ee..c32dc66619a07 100644 --- a/src/crimson/os/seastore/collection_manager/flat_collection_manager.cc +++ b/src/crimson/os/seastore/collection_manager/flat_collection_manager.cc @@ -88,7 +88,10 @@ FlatCollectionManager::create(coll_root_t &coll_root, Transaction &t, }).si_then([] (auto) { return create_iertr::make_ready_future<>(); }); - }); + }).handle_error_interruptible( + crimson::ct_error::enospc::assert_failure{"unexpected enospc"}, + create_iertr::pass_further{} + ); } case CollectionNode::create_result_t::SUCCESS: { return create_iertr::make_ready_future<>(); diff --git a/src/crimson/os/seastore/extent_placement_manager.h b/src/crimson/os/seastore/extent_placement_manager.h index 70dbc428d10bf..b1a4de2ef457a 100644 --- a/src/crimson/os/seastore/extent_placement_manager.h +++ b/src/crimson/os/seastore/extent_placement_manager.h @@ -279,7 +279,7 @@ public: bufferptr bp; rewrite_gen_t gen; }; - alloc_result_t alloc_new_non_data_extent( + std::optional alloc_new_non_data_extent( Transaction& t, extent_types_t type, extent_len_t length, @@ -298,11 +298,6 @@ public: data_category_t category = get_extent_category(type); gen = adjust_generation(category, type, hint, gen); - // XXX: bp might be extended to point to different memory (e.g. PMem) - // according to the allocator. - auto bp = ceph::bufferptr( - buffer::create_page_aligned(length)); - bp.zero(); paddr_t addr; #ifdef UNIT_TESTS_BUILT if (unlikely(external_paddr.has_value())) { @@ -320,7 +315,18 @@ public: generation_to_writer(gen)]->alloc_paddr(length); } assert(!(category == data_category_t::DATA)); - return {addr, std::move(bp), gen}; + + if (addr.is_null()) { + return std::nullopt; + } + + // XXX: bp might be extended to point to different memory (e.g. PMem) + // according to the allocator. + auto bp = ceph::bufferptr( + buffer::create_page_aligned(length)); + bp.zero(); + + return alloc_result_t{addr, std::move(bp), gen}; } std::list alloc_new_data_extents( diff --git a/src/crimson/os/seastore/object_data_handler.cc b/src/crimson/os/seastore/object_data_handler.cc index 5e49a48a18809..39c0be33d6de4 100644 --- a/src/crimson/os/seastore/object_data_handler.cc +++ b/src/crimson/os/seastore/object_data_handler.cc @@ -543,7 +543,10 @@ ObjectDataHandler::write_ret do_insertions( auto iter = region.bl->cbegin(); iter.copy(region.len, extent->get_bptr().c_str()); return ObjectDataHandler::write_iertr::now(); - }); + }).handle_error_interruptible( + crimson::ct_error::enospc::assert_failure{"unexpected enospc"}, + ObjectDataHandler::write_iertr::pass_further{} + ); } else if (region.is_zero()) { DEBUGT("reserving: {}~{}", ctx.t, @@ -564,7 +567,10 @@ ObjectDataHandler::write_ret do_insertions( } ceph_assert(pin->get_key() == region.addr); return ObjectDataHandler::write_iertr::now(); - }); + }).handle_error_interruptible( + crimson::ct_error::enospc::assert_failure{"unexpected enospc"}, + ObjectDataHandler::write_iertr::pass_further{} + ); } else { ceph_abort("impossible"); return ObjectDataHandler::write_iertr::now(); @@ -1057,7 +1063,10 @@ ObjectDataHandler::write_ret ObjectDataHandler::prepare_data_reservation( pin->get_key(), pin->get_length()); return write_iertr::now(); - }); + }).handle_error_interruptible( + crimson::ct_error::enospc::assert_failure{"unexpected enospc"}, + write_iertr::pass_further{} + ); } } @@ -1677,12 +1686,12 @@ ObjectDataHandler::clone_ret ObjectDataHandler::clone_extents( return TransactionManager::reserve_extent_iertr::now(); }); }); - }, + } + ).handle_error_interruptible( ObjectDataHandler::write_iertr::pass_further{}, crimson::ct_error::assert_all{ "object_data_handler::clone invalid error" - } - ); + }); } ObjectDataHandler::clone_ret ObjectDataHandler::clone( diff --git a/src/crimson/os/seastore/omap_manager/btree/btree_omap_manager.cc b/src/crimson/os/seastore/omap_manager/btree/btree_omap_manager.cc index c182965764eec..046cc286208b2 100644 --- a/src/crimson/os/seastore/omap_manager/btree/btree_omap_manager.cc +++ b/src/crimson/os/seastore/omap_manager/btree/btree_omap_manager.cc @@ -32,7 +32,10 @@ BtreeOMapManager::initialize_omap(Transaction &t, laddr_t hint) t.get_omap_tree_stats().depth = 1u; t.get_omap_tree_stats().extents_num_delta++; return initialize_omap_iertr::make_ready_future(omap_root); - }); + }).handle_error_interruptible( + crimson::ct_error::enospc::assert_failure{"unexpected enospc"}, + TransactionManager::alloc_extent_iertr::pass_further{} + ); } BtreeOMapManager::get_root_ret @@ -65,7 +68,10 @@ BtreeOMapManager::handle_root_split( oc.t.get_omap_tree_stats().depth = omap_root.depth; ++(oc.t.get_omap_tree_stats().extents_num_delta); return seastar::now(); - }); + }).handle_error_interruptible( + crimson::ct_error::enospc::assert_failure{"unexpected enospc"}, + TransactionManager::alloc_extent_iertr::pass_further{} + ); } BtreeOMapManager::handle_root_merge_ret diff --git a/src/crimson/os/seastore/omap_manager/btree/omap_btree_node_impl.cc b/src/crimson/os/seastore/omap_manager/btree/omap_btree_node_impl.cc index c932f6d590c10..96a1e3bdefe7e 100644 --- a/src/crimson/os/seastore/omap_manager/btree/omap_btree_node_impl.cc +++ b/src/crimson/os/seastore/omap_manager/btree/omap_btree_node_impl.cc @@ -338,7 +338,10 @@ OMapInnerNode:: make_split_children(omap_context_t oc) return split_children_ret( interruptible::ready_future_marker{}, std::make_tuple(left, right, split_into(*left, *right))); - }); + }).handle_error_interruptible( + crimson::ct_error::enospc::assert_failure{"unexpected enospc"}, + split_children_iertr::pass_further{} + ); } OMapInnerNode::full_merge_ret @@ -353,7 +356,10 @@ OMapInnerNode::make_full_merge(omap_context_t oc, OMapNodeRef right) return full_merge_ret( interruptible::ready_future_marker{}, std::move(replacement)); - }); + }).handle_error_interruptible( + crimson::ct_error::enospc::assert_failure{"unexpected enospc"}, + full_merge_iertr::pass_further{} + ); } OMapInnerNode::make_balanced_ret @@ -373,7 +379,10 @@ OMapInnerNode::make_balanced(omap_context_t oc, OMapNodeRef _right) std::make_tuple(replacement_left, replacement_right, balance_into_new_nodes(*this, right, *replacement_left, *replacement_right))); - }); + }).handle_error_interruptible( + crimson::ct_error::enospc::assert_failure{"unexpected enospc"}, + make_balanced_iertr::pass_further{} + ); } OMapInnerNode::merge_entry_ret @@ -670,7 +679,10 @@ OMapLeafNode::make_split_children(omap_context_t oc) return split_children_ret( interruptible::ready_future_marker{}, std::make_tuple(left, right, split_into(*left, *right))); - }); + }).handle_error_interruptible( + crimson::ct_error::enospc::assert_failure{"unexpected enospc"}, + split_children_iertr::pass_further{} + ); } OMapLeafNode::full_merge_ret @@ -685,7 +697,10 @@ OMapLeafNode::make_full_merge(omap_context_t oc, OMapNodeRef right) return full_merge_ret( interruptible::ready_future_marker{}, std::move(replacement)); - }); + }).handle_error_interruptible( + crimson::ct_error::enospc::assert_failure{"unexpected enospc"}, + full_merge_iertr::pass_further{} + ); } OMapLeafNode::make_balanced_ret @@ -706,7 +721,10 @@ OMapLeafNode::make_balanced(omap_context_t oc, OMapNodeRef _right) balance_into_new_nodes( *this, right, *replacement_left, *replacement_right))); - }); + }).handle_error_interruptible( + crimson::ct_error::enospc::assert_failure{"unexpected enospc"}, + make_balanced_iertr::pass_further{} + ); } diff --git a/src/crimson/os/seastore/onode_manager/staged-fltree/node_extent_manager/seastore.h b/src/crimson/os/seastore/onode_manager/staged-fltree/node_extent_manager/seastore.h index cff67f9cf51f8..fb8fe54271d3e 100644 --- a/src/crimson/os/seastore/onode_manager/staged-fltree/node_extent_manager/seastore.h +++ b/src/crimson/os/seastore/onode_manager/staged-fltree/node_extent_manager/seastore.h @@ -145,7 +145,10 @@ class SeastoreNodeExtentManager final: public TransactionManagerHandle { assert(extent->get_length() == len); std::ignore = len; return NodeExtentRef(extent); - }); + }).handle_error_interruptible( + crimson::ct_error::enospc::assert_failure{"unexpected enospc"}, + alloc_iertr::pass_further{} + ); } retire_iertr::future<> retire_extent( diff --git a/src/crimson/os/seastore/random_block_manager/block_rb_manager.cc b/src/crimson/os/seastore/random_block_manager/block_rb_manager.cc index 6bae96f84a5ad..cca520a9bfea3 100644 --- a/src/crimson/os/seastore/random_block_manager/block_rb_manager.cc +++ b/src/crimson/os/seastore/random_block_manager/block_rb_manager.cc @@ -51,6 +51,9 @@ paddr_t BlockRBManager::alloc_extent(size_t size) LOG_PREFIX(BlockRBManager::alloc_extent); assert(allocator); auto alloc = allocator->alloc_extent(size); + if (!alloc) { + return P_ADDR_NULL; + } ceph_assert((*alloc).num_intervals() == 1); auto extent = (*alloc).begin(); ceph_assert(size == extent.get_len()); diff --git a/src/crimson/os/seastore/transaction_manager.h b/src/crimson/os/seastore/transaction_manager.h index 4bacd78fe60b4..7720469c28215 100644 --- a/src/crimson/os/seastore/transaction_manager.h +++ b/src/crimson/os/seastore/transaction_manager.h @@ -284,7 +284,8 @@ public: * Allocates a new block of type T with the minimum lba range of size len * greater than laddr_hint. */ - using alloc_extent_iertr = LBAManager::alloc_extent_iertr; + using alloc_extent_iertr = LBAManager::alloc_extent_iertr::extend< + crimson::ct_error::enospc>; template using alloc_extent_ret = alloc_extent_iertr::future>; template @@ -302,6 +303,9 @@ public: len, placement_hint, INIT_GENERATION); + if (!ext) { + return crimson::ct_error::enospc::make(); + } return lba_manager->alloc_extent( t, laddr_hint, @@ -341,6 +345,9 @@ public: len, placement_hint, INIT_GENERATION); + if (exts.empty()) { + return crimson::ct_error::enospc::make(); + } return seastar::do_with( std::move(exts), laddr_hint, diff --git a/src/test/crimson/seastore/test_transaction_manager.cc b/src/test/crimson/seastore/test_transaction_manager.cc index c33c9ffce4bc5..378644dafa840 100644 --- a/src/test/crimson/seastore/test_transaction_manager.cc +++ b/src/test/crimson/seastore/test_transaction_manager.cc @@ -1135,7 +1135,10 @@ struct transaction_manager_test_t : std::move(lpin), std::move(ext), std::move(rpin))); }); }); - }); + }).handle_error_interruptible( + crimson::ct_error::enospc::assert_failure{"unexpected enospc"}, + crimson::ct_error::pass_further_all{} + ); }); } else if (new_offset == 0 && o_len != new_offset + new_len) { return tm->remap_pin( @@ -1164,7 +1167,10 @@ struct transaction_manager_test_t : nullptr, std::move(ext), std::move(rpin))); }); }); - }); + }).handle_error_interruptible( + crimson::ct_error::enospc::assert_failure{"unexpected enospc"}, + crimson::ct_error::pass_further_all{} + ); } else if (new_offset != 0 && o_len == new_offset + new_len) { return tm->remap_pin( t, @@ -1191,7 +1197,10 @@ struct transaction_manager_test_t : std::move(lpin), std::move(ext), nullptr)); }); }); - }); + }).handle_error_interruptible( + crimson::ct_error::enospc::assert_failure{"unexpected enospc"}, + crimson::ct_error::pass_further_all{} + ); } else { ceph_abort("impossible"); return _overwrite_pin_iertr::make_ready_future< -- 2.39.5