]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
crimson/os/seastore: use laddr_hint_t to allocate the laddr
authorZhang Song <zhangsong02@qianxin.com>
Tue, 26 Aug 2025 03:36:07 +0000 (11:36 +0800)
committerXuehan Xu <xuxuehan@qianxin.com>
Thu, 21 May 2026 07:32:55 +0000 (15:32 +0800)
Signed-off-by: Zhang Song <zhangsong02@qianxin.com>
Signed-off-by: Xuehan Xu <xuxuehan@qianxin.com>
src/crimson/os/seastore/collection_manager/flat_collection_manager.cc
src/crimson/os/seastore/lba/btree_lba_manager.cc
src/crimson/os/seastore/lba/btree_lba_manager.h
src/crimson/os/seastore/lba_manager.h
src/crimson/os/seastore/object_data_handler.cc
src/crimson/os/seastore/onode.h
src/crimson/os/seastore/transaction_manager.cc
src/crimson/os/seastore/transaction_manager.h
src/crimson/tools/store_nbd/tm_driver.cc
src/test/crimson/seastore/test_btree_lba_manager.cc
src/test/crimson/seastore/test_transaction_manager.cc

index 26d579cfbd9d3bb5c47544b008ae90e0f66b7f33..5f3e8ed272c38f8a0dd616f05035b4217a23ccd2 100644 (file)
@@ -31,7 +31,7 @@ FlatCollectionManager::mkfs(Transaction &t)
 
   logger().debug("FlatCollectionManager: {}", __func__);
   return tm.alloc_non_data_extent<CollectionNode>(
-    t, L_ADDR_MIN, MIN_FLAT_BLOCK_SIZE
+    t, laddr_hint_t::create_global_md_hint(), MIN_FLAT_BLOCK_SIZE
   ).si_then([](auto&& root_extent) {
     coll_root_t coll_root = coll_root_t(
       root_extent->get_laddr(),
@@ -78,7 +78,7 @@ FlatCollectionManager::create(coll_root_t &coll_root, Transaction &t,
        // collections would create a ton of other problems as well
        assert(new_size < MAX_FLAT_BLOCK_SIZE);
         return tm.alloc_non_data_extent<CollectionNode>(
-         t, L_ADDR_MIN, new_size
+         t, laddr_hint_t::create_global_md_hint(), new_size
        ).si_then([=, this, &coll_root, &t] (auto &&root_extent) {
           coll_root.update(root_extent->get_laddr(), root_extent->get_length());
 
index 446f48063b6c0c13c196bdba5deaa57c48aec4b3..f1016b0d2633eeb2f4a9cde888c3338285d0fbbb 100644 (file)
@@ -378,21 +378,22 @@ BtreeLBAManager::search_insert_position_ret
 BtreeLBAManager::search_insert_position(
   op_context_t c,
   LBABtree &btree,
-  laddr_t hint,
+  laddr_hint_t hint,
   extent_len_t length,
   alloc_policy_t policy)
 {
   LOG_PREFIX(BtreeLBAManager::search_insert_position);
   auto lookup_attempts = stats.num_alloc_extents_iter_nexts;
   using OptIter = std::optional<LBABtree::iterator>;
+  // TODO: handle conflict condition and policy
   return seastar::do_with(
-    hint, OptIter(std::nullopt),
+    hint.addr, OptIter(std::nullopt),
     [this, c, &btree, hint, length, lookup_attempts, policy, FNAME]
     (laddr_t &last_end, OptIter &insert_iter)
   {
     return LBABtree::iterate_repeat(
       c,
-      btree.upper_bound_right(c, hint),
+      btree.upper_bound_right(c, hint.addr),
       [this, c, hint, length, lookup_attempts, policy,
        &last_end, &insert_iter, FNAME](auto &iter)
     {
@@ -400,7 +401,7 @@ BtreeLBAManager::search_insert_position(
       if (iter.is_end() ||
          iter.get_key() >= (last_end + length)) {
        if (policy == alloc_policy_t::deterministic) {
-         ceph_assert(hint == last_end);
+         ceph_assert(hint.addr == last_end);
        }
        DEBUGT("hint: {}~0x{:x}, allocated laddr: {}, insert position: {}, "
               "done with {} attempts",
@@ -427,11 +428,11 @@ BtreeLBAManager::search_insert_position(
 BtreeLBAManager::alloc_mappings_ret
 BtreeLBAManager::alloc_contiguous_mappings(
   Transaction &t,
-  laddr_t hint,
+  laddr_hint_t hint,
   std::vector<alloc_mapping_info_t> &alloc_infos,
   alloc_policy_t policy)
 {
-  ceph_assert(hint != L_ADDR_NULL);
+  ceph_assert(hint.addr != L_ADDR_NULL);
   extent_len_t total_len = 0;
   for (auto &info : alloc_infos) {
     assert(info.key == L_ADDR_NULL);
@@ -460,11 +461,11 @@ BtreeLBAManager::alloc_contiguous_mappings(
 BtreeLBAManager::alloc_mappings_ret
 BtreeLBAManager::alloc_sparse_mappings(
   Transaction &t,
-  laddr_t hint,
+  laddr_hint_t hint,
   std::vector<alloc_mapping_info_t> &alloc_infos,
   alloc_policy_t policy)
 {
-  ceph_assert(hint != L_ADDR_NULL);
+  ceph_assert(hint.addr != L_ADDR_NULL);
 #ifndef NDEBUG
   assert(alloc_infos.front().key != L_ADDR_NULL);
   for (size_t i = 1; i < alloc_infos.size(); i++) {
@@ -474,7 +475,7 @@ BtreeLBAManager::alloc_sparse_mappings(
     assert(prev.key + prev.value.len <= cur.key);
   }
 #endif
-  auto total_len = hint.get_byte_distance<extent_len_t>(
+  auto total_len = hint.addr.get_byte_distance<extent_len_t>(
     alloc_infos.back().key + alloc_infos.back().value.len);
   auto c = get_context(t);
   return with_btree<LBABtree>(
@@ -486,7 +487,7 @@ BtreeLBAManager::alloc_sparse_mappings(
     ).si_then([this, c, hint, &alloc_infos, &btree, policy](auto res) {
       if (policy != alloc_policy_t::deterministic) {
        for (auto &info : alloc_infos) {
-         auto offset = info.key.get_byte_distance<extent_len_t>(hint);
+         auto offset = info.key.get_byte_distance<extent_len_t>(hint.addr);
          info.key = (res.laddr + offset).checked_to_laddr();
        }
       } // deterministic guarantees hint == res.laddr
index ae0f135d74e1732384fb76c4589d4129cf54ed9f..d8d824216241d861865ef21c8274bec61cb328bc 100644 (file)
@@ -83,7 +83,7 @@ public:
 
   alloc_extent_ret reserve_region(
     Transaction &t,
-    laddr_t hint,
+    laddr_hint_t hint,
     extent_len_t len) final
   {
     std::vector<alloc_mapping_info_t> alloc_infos = {
@@ -114,7 +114,7 @@ public:
 
   alloc_extent_ret alloc_extent(
     Transaction &t,
-    laddr_t hint,
+    laddr_hint_t hint,
     LogicalChildNode &ext,
     extent_ref_count_t refcount) final
   {
@@ -138,7 +138,7 @@ public:
 
   alloc_extents_ret alloc_extents(
     Transaction &t,
-    laddr_t hint,
+    laddr_hint_t hint,
     std::vector<LogicalChildNodeRef> extents,
     extent_ref_count_t refcount) final
   {
@@ -351,7 +351,7 @@ private:
   search_insert_position_ret search_insert_position(
     op_context_t c,
     LBABtree &btree,
-    laddr_t hint,
+    laddr_hint_t hint,
     extent_len_t length,
     alloc_policy_t policy);
 
@@ -369,7 +369,7 @@ private:
    */
   alloc_mappings_ret alloc_contiguous_mappings(
     Transaction &t,
-    laddr_t hint,
+    laddr_hint_t hint,
     std::vector<alloc_mapping_info_t> &alloc_infos,
     alloc_policy_t policy);
 
@@ -384,7 +384,7 @@ private:
    */
   alloc_mappings_ret alloc_sparse_mappings(
     Transaction &t,
-    laddr_t hint,
+    laddr_hint_t hint,
     std::vector<alloc_mapping_info_t> &alloc_infos,
     alloc_policy_t policy);
 
index 52490bc90152d71d8ab0799b11e05bf788639185..1b066b575ed5133ed3bb9cb0a5477e20a5408c29 100644 (file)
@@ -72,7 +72,7 @@ public:
   using alloc_extent_ret = alloc_extent_iertr::future<LBACursorRef>;
   virtual alloc_extent_ret alloc_extent(
     Transaction &t,
-    laddr_t hint,
+    laddr_hint_t hint,
     LogicalChildNode &nextent,
     extent_ref_count_t refcount) = 0;
 
@@ -80,7 +80,7 @@ public:
     std::vector<LBACursorRef>>;
   virtual alloc_extents_ret alloc_extents(
     Transaction &t,
-    laddr_t hint,
+    laddr_hint_t hint,
     std::vector<LogicalChildNodeRef> extents,
     extent_ref_count_t refcount) = 0;
   /*
@@ -116,7 +116,7 @@ public:
 
   virtual alloc_extent_ret reserve_region(
     Transaction &t,
-    laddr_t hint,
+    laddr_hint_t hint,
     extent_len_t len) = 0;
 
   /*
index dee214fc25645c9bae60b2a02347e00276a860a1..a9932b0dbd8b7eb92693ffca48b102e91b551583 100644 (file)
@@ -268,7 +268,8 @@ ObjectDataHandler::write_ret do_zero(
       ctx.tm.get_block_size() - data.tailbl->length());
     auto extents = co_await ctx.tm.alloc_data_extents<ObjectDataBlock>(
       ctx.t,
-      (overwrite_range.aligned_end - ctx.tm.get_block_size()).checked_to_laddr(),
+      laddr_hint_t::create_as_fixed(
+        (overwrite_range.aligned_end - ctx.tm.get_block_size()).checked_to_laddr()),
       ctx.tm.get_block_size(),
       std::move(zero_pos)
     ).handle_error_interruptible(
@@ -318,7 +319,7 @@ ObjectDataHandler::write_ret do_zero(
       ctx.tm.get_block_size() - data.headbl->length());
     auto extents = co_await ctx.tm.alloc_data_extents<ObjectDataBlock>(
        ctx.t,
-       overwrite_range.aligned_begin,
+       laddr_hint_t::create_as_fixed(overwrite_range.aligned_begin),
        ctx.tm.get_block_size(),
        std::move(zero_pos)
     ).handle_error_interruptible(
@@ -355,7 +356,7 @@ ObjectDataHandler::clone_ret do_clonerange(
     data.merge_head(ctx.tm.get_block_size());
     auto extents = co_await ctx.tm.alloc_data_extents<ObjectDataBlock>(
       ctx.t,
-      overwrite_range.aligned_begin,
+      laddr_hint_t::create_as_fixed(overwrite_range.aligned_begin),
       ctx.tm.get_block_size(),
       std::move(write_pos)
     ).handle_error_interruptible(
@@ -435,7 +436,7 @@ ObjectDataHandler::write_ret do_write(
   assert(data.bl);
   return ctx.tm.alloc_data_extents<ObjectDataBlock>(
     ctx.t,
-    overwrite_range.aligned_begin,
+    laddr_hint_t::create_as_fixed(overwrite_range.aligned_begin),
     overwrite_range.aligned_end.template get_byte_distance<
       extent_len_t>(overwrite_range.aligned_begin),
     std::move(write_pos)
index 00856d40a9ce965509cdb838097fa42153df9b03..e03537e6689012cf36d81af27da0ba6d83b0b1d5 100644 (file)
@@ -136,13 +136,11 @@ public:
   virtual void unset_need_cow(Transaction&) = 0;
   virtual void swap_layout(Transaction&, Onode&) = 0;
 
-  laddr_t get_metadata_hint(uint64_t block_size = laddr_t::UNIT_SIZE) const {
-    // TODO: return laddr_hint_t
-    return get_hint(block_size, /*is_metadata*/true).addr;
+  laddr_hint_t get_metadata_hint(uint64_t block_size = laddr_t::UNIT_SIZE) const {
+    return get_hint(block_size, /*is_metadata*/true);
   }
-  laddr_t get_data_hint(uint64_t block_size = laddr_t::UNIT_SIZE) const {
-    // TODO: return laddr_hint_t
-    return get_hint(block_size, /*is_metadata*/false).addr;
+  laddr_hint_t get_data_hint(uint64_t block_size = laddr_t::UNIT_SIZE) const {
+    return get_hint(block_size, /*is_metadata*/false);
   }
   laddr_hint_t get_metadata_clone_hint(uint64_t block_size = laddr_t::UNIT_SIZE) const {
     return get_clone_hint(block_size, /*is_metadata*/true);
index 9d65239e8617f4db8050b414c07c41223d94351c..52bcb187abf691df434c3a450f41310075ddd222 100644 (file)
@@ -728,7 +728,8 @@ TransactionManager::rewrite_logical_extent(
        ceph_assert(refcount != 0);
        auto cursor = co_await lba_manager->alloc_extent(
          t,
-         (extent->get_laddr() + off).checked_to_laddr(),
+          laddr_hint_t::create_as_fixed(
+            (extent->get_laddr() + off).checked_to_laddr()),
          *nextent,
          refcount
        );
index 3bf6abf8db522a7b0adc62a6208399e1d58443a2..5a834ea4b0dcb3d4d900bc5c7ccbdfbd6657bd76 100644 (file)
@@ -523,7 +523,7 @@ public:
   template <typename T>
   alloc_extent_ret<T> alloc_non_data_extent(
     Transaction &t,
-    laddr_t laddr_hint,
+    laddr_hint_t laddr_hint,
     extent_len_t len,
     placement_hint_t placement_hint = placement_hint_t::HOT) {
     static_assert(is_logical_metadata_type(T::TYPE));
@@ -563,7 +563,7 @@ public:
   template <typename T>
   alloc_extents_ret<T> alloc_data_extents(
     Transaction &t,
-    laddr_t laddr_hint,
+    laddr_hint_t laddr_hint,
     extent_len_t len,
     std::optional<LBAMapping> pos = std::nullopt,
     placement_hint_t placement_hint = placement_hint_t::HOT) {
@@ -583,7 +583,8 @@ public:
     }
     if (pos) {
       // laddr_hint is determined
-      auto off = laddr_hint;
+      assert(laddr_hint.condition == laddr_conflict_condition_t::all_at_never);
+      auto off = laddr_hint.addr;
       for (auto &extent : exts) {
        extent->set_laddr(off);
        off = (off + extent->get_length()).checked_to_laddr();
@@ -639,7 +640,7 @@ public:
   using reserve_extent_ret = reserve_extent_iertr::future<LBAMapping>;
   reserve_extent_ret reserve_region(
     Transaction &t,
-    laddr_t hint,
+    laddr_hint_t hint,
     extent_len_t len) {
     LOG_PREFIX(TransactionManager::reserve_region);
     SUBDEBUGT(seastore_tm, "hint {}~0x{:x} ...", t, hint, len);
@@ -792,7 +793,7 @@ public:
    alloc_extents_iertr::future<std::vector<TCachedExtentRef<T>>>
    alloc_extents(
      Transaction &t,
-     laddr_t hint,
+     laddr_hint_t hint,
      extent_len_t len,
      int num) {
      LOG_PREFIX(TransactionManager::alloc_extents);
@@ -921,7 +922,7 @@ public:
   using init_root_meta_ret = init_root_meta_iertr::future<>;
   init_root_meta_ret init_root_meta(Transaction &t) {
     return alloc_non_data_extent<RootMetaBlock>(
-      t, L_ADDR_MIN, RootMetaBlock::SIZE
+      t, laddr_hint_t::create_as_fixed(L_ADDR_MIN), RootMetaBlock::SIZE
     ).si_then([this, &t](auto meta) {
       meta->set_meta(RootMetaBlock::meta_t{});
       return cache->get_root(t
index b74d8d6444fc5e1e9abcdf3afcfc42b7fd0de6ce..894dd27fa70b94240eefaffa3ad87ea41b5cc46d 100644 (file)
@@ -34,7 +34,10 @@ seastar::future<> TMDriver::write(
           crimson::ct_error::pass_further_all{}
         ).si_then([this, offset, &t, &ptr] {
           logger().debug("dec_ref complete");
-          return tm->alloc_data_extents<TestBlock>(t, laddr_t::from_byte_offset(offset), ptr.length());
+          return tm->alloc_data_extents<TestBlock>(
+           t,
+           laddr_hint_t::create_as_fixed(laddr_t::from_byte_offset(offset)),
+           ptr.length());
         }).si_then([this, offset, &t, &ptr](auto extents) mutable {
          boost::ignore_unused(offset);  // avoid clang warning;
          auto off = offset;
index c5710f41d87415b46a2011bd302c75c5c125ab80..432b1f3cadb271a0800f6785b8e6d054f7686599 100644 (file)
@@ -543,7 +543,7 @@ struct btree_lba_manager_test : btree_test_base {
 
   auto alloc_mappings(
     test_transaction_t &t,
-    laddr_t hint,
+    laddr_t addr,
     size_t len) {
     auto rets = with_trans_intr(
       *t.t,
@@ -557,7 +557,11 @@ struct btree_lba_manager_test : btree_test_base {
        return seastar::do_with(
          std::vector<LogicalChildNodeRef>(
            extents.begin(), extents.end()),
-         [this, &t, hint](auto &extents) {
+         [this, &t, addr](auto &extents) {
+         laddr_hint_t hint;
+         hint.addr = addr;
+         hint.condition = laddr_conflict_condition_t::all_at_object_content;
+         hint.policy = laddr_conflict_policy_t::linear_search;
          return lba_manager->alloc_extents(t, hint, std::move(extents), EXTENT_DEFAULT_REF_COUNT);
        });
       }).unsafe_get();
index 1579ae110c7a95744d78b754cc8f82b491be225f..040beb967bf51ad23ff27bef38319989728e26bc 100644 (file)
@@ -448,10 +448,15 @@ struct transaction_manager_test_t :
 
   TestBlockRef alloc_extent(
     test_transaction_t &t,
-    laddr_t hint,
+    laddr_t addr,
     extent_len_t len,
     char contents) {
     auto extents = with_trans_intr(*(t.t), [&](auto& trans) {
+      laddr_hint_t hint;
+      hint.addr = addr;
+      hint.condition = laddr_conflict_condition_t::all_at_object_content;
+      hint.policy = laddr_conflict_policy_t::gen_random;
+      hint.block_size = laddr_t::UNIT_SIZE;
       return tm->alloc_data_extents<TestBlock>(trans, hint, len);
     }).unsafe_get();
     assert(extents.size() == 1);
@@ -459,7 +464,7 @@ struct transaction_manager_test_t :
     extent_len_t allocated_len = 0;
     extent->set_contents(contents);
     EXPECT_FALSE(test_mappings.contains(extent->get_laddr(), t.mapping_delta));
-    test_mappings.alloced(hint, *extent, t.mapping_delta);
+    test_mappings.alloced(addr, *extent, t.mapping_delta);
     allocated_len += extent->get_length();
     EXPECT_EQ(len, allocated_len);
     return extent;
@@ -467,10 +472,15 @@ struct transaction_manager_test_t :
 
   std::vector<TestBlockRef> alloc_extents(
     test_transaction_t &t,
-    laddr_t hint,
+    laddr_t addr,
     extent_len_t len,
     char contents) {
     auto extents = with_trans_intr(*(t.t), [&](auto& trans) {
+      laddr_hint_t hint;
+      hint.addr = addr;
+      hint.condition = laddr_conflict_condition_t::all_at_object_content;
+      hint.policy = laddr_conflict_policy_t::gen_random;
+      hint.block_size = laddr_t::UNIT_SIZE;
       return tm->alloc_data_extents<TestBlock>(trans, hint, len);
     }).unsafe_get();
     size_t length = 0;
@@ -479,7 +489,7 @@ struct transaction_manager_test_t :
       extent->set_contents(contents);
       length += extent->get_length();
       EXPECT_FALSE(test_mappings.contains(extent->get_laddr(), t.mapping_delta));
-      test_mappings.alloced(hint, *extent, t.mapping_delta);
+      test_mappings.alloced(addr, *extent, t.mapping_delta);
       exts.push_back(extent->template cast<TestBlock>());
     }
     EXPECT_EQ(len, length);
@@ -488,12 +498,17 @@ struct transaction_manager_test_t :
 
   void alloc_extents_deemed_fail(
     test_transaction_t &t,
-    laddr_t hint,
+    laddr_t addr,
     extent_len_t len,
     char contents)
   {
     std::cout << __func__ << std::endl;
     auto fut = with_trans_intr(*(t.t), [&](auto& trans) {
+      laddr_hint_t hint;
+      hint.addr = addr;
+      hint.condition = laddr_conflict_condition_t::all_at_object_content;
+      hint.policy = laddr_conflict_policy_t::gen_random;
+      hint.block_size = laddr_t::UNIT_SIZE;
       return tm->alloc_data_extents<TestBlock>(trans, hint, len);
     });
     fut.unsafe_wait();
@@ -867,8 +882,13 @@ struct transaction_manager_test_t :
                boost::make_counting_iterator(0),
                boost::make_counting_iterator(num),
                [&t, this, size](auto) {
+                 laddr_hint_t hint;
+                 hint.addr = L_ADDR_MIN;
+                 hint.condition = laddr_conflict_condition_t::all_at_object_content;
+                 hint.policy = laddr_conflict_policy_t::gen_random;
+                 hint.block_size = laddr_t::UNIT_SIZE;
                  return tm->alloc_data_extents<TestBlock>(
-                   *(t.t), L_ADDR_MIN, size
+                   *(t.t), hint, size
                  ).si_then([&t, this, size](auto extents) {
                    extent_len_t length = 0;
                    for (auto &extent : extents) {
@@ -1266,7 +1286,11 @@ struct transaction_manager_test_t :
             o_len - new_offset - new_len)
         }
       ).si_then([this, new_offset, new_len, o_laddr, &t, &bl](auto ret) {
-        return tm->alloc_data_extents<TestBlock>(t, (o_laddr + new_offset).checked_to_laddr(), new_len
+        return tm->alloc_data_extents<TestBlock>(
+         t,
+         laddr_hint_t::create_as_fixed(
+           (o_laddr + new_offset).checked_to_laddr()),
+         new_len
         ).si_then([this, ret = std::move(ret), new_len,
                    new_offset, o_laddr, &t, &bl](auto extents) mutable {
          assert(extents.size() == 1);
@@ -1300,7 +1324,11 @@ struct transaction_manager_test_t :
             o_len - new_offset - new_len)
         }
       ).si_then([this, new_offset, new_len, o_laddr, &t, &bl](auto ret) {
-        return tm->alloc_data_extents<TestBlock>(t, (o_laddr + new_offset).checked_to_laddr(), new_len
+        return tm->alloc_data_extents<TestBlock>(
+         t,
+         laddr_hint_t::create_as_fixed(
+           (o_laddr + new_offset).checked_to_laddr()),
+         new_len
         ).si_then([this, ret = std::move(ret), new_offset, new_len,
                    o_laddr, &t, &bl](auto extents) mutable {
          assert(extents.size() == 1);
@@ -1329,7 +1357,11 @@ struct transaction_manager_test_t :
             new_offset)
         }
       ).si_then([this, new_offset, new_len, o_laddr, &t, &bl](auto ret) {
-        return tm->alloc_data_extents<TestBlock>(t, (o_laddr + new_offset).checked_to_laddr(), new_len
+        return tm->alloc_data_extents<TestBlock>(
+         t,
+         laddr_hint_t::create_as_fixed(
+           (o_laddr + new_offset).checked_to_laddr()),
+         new_len
         ).si_then([this, ret = std::move(ret), new_len, o_laddr, &t, &bl]
           (auto extents) mutable {
          assert(extents.size() == 1);
@@ -1471,12 +1503,12 @@ struct transaction_manager_test_t :
   void test_clone_and_remap_pin() {
     run_async([this] {
       disable_max_extent_size();
-      laddr_t l_offset = get_laddr_hint(32 << 10);
+      laddr_t l_offset = L_ADDR_MIN.with_local_clone_id(10);
       size_t l_len = 32 << 10;
-      laddr_t r_offset = get_laddr_hint(64 << 10);
+      laddr_t r_offset = L_ADDR_MIN.with_local_clone_id(20);
       size_t r_len = 32 << 10;
-      laddr_t l_clone_offset = get_laddr_hint(96 << 10);
-      laddr_t r_clone_offset = get_laddr_hint(128 << 10);
+      laddr_t l_clone_offset = L_ADDR_MIN.with_local_clone_id(30);
+      laddr_t r_clone_offset = L_ADDR_MIN.with_local_clone_id(40);
       {
        auto t = create_transaction();
        auto lext = alloc_extent(t, l_offset, l_len);