]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
crimson/os/seastore: hide the complexity of extent indirection
authorYingxin Cheng <yingxin.cheng@intel.com>
Mon, 4 Nov 2024 02:47:08 +0000 (10:47 +0800)
committerYingxin Cheng <yingxin.cheng@intel.com>
Thu, 28 Nov 2024 01:32:51 +0000 (09:32 +0800)
Make it easier for TM::read_pin() users to consume extent without
worrying about the indirections.

This basically reverts 9cdcd06caadef6cdca64a974c6525ba300c1e289

Signed-off-by: Yingxin Cheng <yingxin.cheng@intel.com>
src/crimson/os/seastore/collection_manager/flat_collection_manager.cc
src/crimson/os/seastore/object_data_handler.cc
src/crimson/os/seastore/omap_manager/btree/omap_btree_node_impl.cc
src/crimson/os/seastore/onode_manager/staged-fltree/node_extent_manager/seastore.h
src/crimson/os/seastore/transaction_manager.h
src/crimson/tools/store_nbd/tm_driver.cc
src/test/crimson/seastore/test_object_data_handler.cc
src/test/crimson/seastore/test_transaction_manager.cc

index c32dc66619a0792ee62611ca7e19d05698760f4c..866b5bf350cf5f8292df113eb0700de2253396a5 100644 (file)
@@ -51,8 +51,11 @@ FlatCollectionManager::get_coll_root(const coll_root_t &coll_root, Transaction &
     cc.t,
     coll_root.get_location(),
     coll_root.get_size()
-  ).si_then([](auto&& e) {
-    return get_root_iertr::make_ready_future<CollectionNodeRef>(std::move(e));
+  ).si_then([](auto maybe_indirect_extent) {
+    assert(!maybe_indirect_extent.is_indirect());
+    assert(!maybe_indirect_extent.is_clone);
+    return get_root_iertr::make_ready_future<CollectionNodeRef>(
+        std::move(maybe_indirect_extent.extent));
   });
 }
 
index 20f86da5d3debd40b0d2f358a875891f6909ceb7..83bb2c08af843ff576bdcf0e070363251cc4d4a4 100644 (file)
@@ -859,15 +859,14 @@ operate_ret operate_left(context_t ctx, LBAMappingRef &pin, const overwrite_plan
         std::nullopt,
         std::nullopt);
     } else {
-      extent_len_t off = pin->get_intermediate_offset();
       return ctx.tm.read_pin<ObjectDataBlock>(
        ctx.t, pin->duplicate()
-      ).si_then([prepend_len, off](auto left_extent) {
+      ).si_then([prepend_len](auto maybe_indirect_left_extent) {
         return get_iertr::make_ready_future<operate_ret_bare>(
           std::nullopt,
           std::make_optional(bufferptr(
-            left_extent->get_bptr(),
-            off,
+            maybe_indirect_left_extent.get_bptr(),
+            0,
             prepend_len)));
       });
     }
@@ -888,16 +887,15 @@ operate_ret operate_left(context_t ctx, LBAMappingRef &pin, const overwrite_plan
         std::move(left_to_write_extent),
         std::nullopt);
     } else {
-      extent_len_t off = pin->get_intermediate_offset();
       return ctx.tm.read_pin<ObjectDataBlock>(
        ctx.t, pin->duplicate()
-      ).si_then([prepend_offset=extent_len + off, prepend_len,
+      ).si_then([prepend_offset=extent_len, prepend_len,
                  left_to_write_extent=std::move(left_to_write_extent)]
-                (auto left_extent) mutable {
+                (auto left_maybe_indirect_extent) mutable {
         return get_iertr::make_ready_future<operate_ret_bare>(
           std::move(left_to_write_extent),
           std::make_optional(bufferptr(
-            left_extent->get_bptr(),
+            left_maybe_indirect_extent.get_bptr(),
             prepend_offset,
             prepend_len)));
       });
@@ -944,15 +942,15 @@ operate_ret operate_right(context_t ctx, LBAMappingRef &pin, const overwrite_pla
     } else {
       auto append_offset =
        overwrite_plan.data_end.get_byte_distance<
-         extent_len_t>(right_pin_begin)
-         + pin->get_intermediate_offset();
+         extent_len_t>(right_pin_begin);
       return ctx.tm.read_pin<ObjectDataBlock>(
        ctx.t, pin->duplicate()
-      ).si_then([append_offset, append_len](auto right_extent) {
+      ).si_then([append_offset, append_len]
+                (auto right_maybe_indirect_extent) {
         return get_iertr::make_ready_future<operate_ret_bare>(
           std::nullopt,
           std::make_optional(bufferptr(
-            right_extent->get_bptr(),
+            right_maybe_indirect_extent.get_bptr(),
             append_offset,
             append_len)));
       });
@@ -976,17 +974,16 @@ operate_ret operate_right(context_t ctx, LBAMappingRef &pin, const overwrite_pla
     } else {
       auto append_offset =
        overwrite_plan.data_end.get_byte_distance<
-         extent_len_t>(right_pin_begin)
-         + pin->get_intermediate_offset();
+         extent_len_t>(right_pin_begin);
       return ctx.tm.read_pin<ObjectDataBlock>(
        ctx.t, pin->duplicate()
       ).si_then([append_offset, append_len,
                  right_to_write_extent=std::move(right_to_write_extent)]
-                (auto right_extent) mutable {
+                (auto maybe_indirect_right_extent) mutable {
         return get_iertr::make_ready_future<operate_ret_bare>(
           std::move(right_to_write_extent),
           std::make_optional(bufferptr(
-            right_extent->get_bptr(),
+            maybe_indirect_right_extent.get_bptr(),
             append_offset,
             append_len)));
       });
@@ -1136,12 +1133,12 @@ ObjectDataHandler::clear_ret ObjectDataHandler::trim_data_reservation(
               ctx.t,
               pin.duplicate()
             ).si_then([ctx, size, pin_offset, append_len, roundup_size,
-                      &pin, &object_data, &to_write](auto extent) {
+                      &pin, &object_data, &to_write](auto maybe_indirect_extent) {
               bufferlist bl;
              bl.append(
                bufferptr(
-                 extent->get_bptr(),
-                 pin.get_intermediate_offset(),
+                 maybe_indirect_extent.get_bptr(),
+                 0,
                  size - pin_offset
              ));
               bl.append_zero(append_len);
@@ -1501,83 +1498,54 @@ ObjectDataHandler::read_ret ObjectDataHandler::read(
             pins,
             [FNAME, ctx, l_start, l_end,
              &l_current, &ret](auto &pin) -> read_iertr::future<> {
-            auto pin_key = pin->get_key();
-            if (l_current == l_start) {
-              ceph_assert(l_current >= pin_key);
-            } else {
+            auto pin_start = pin->get_key();
+            if (l_current == l_start) { // first pin may skip head
+              ceph_assert(l_current.get_aligned_laddr() >= pin_start);
+            } else { // non-first pin must match start
               assert(l_current > l_start);
-              ceph_assert(l_current == pin_key);
+              ceph_assert(l_current == pin_start);
             }
+
             ceph_assert(l_current < l_end);
             auto pin_len = pin->get_length();
             assert(pin_len > 0);
-            laddr_offset_t l_pin_end = pin_key + pin_len;
-            ceph_assert(l_current < l_pin_end);
-            laddr_offset_t l_current_end = std::min(l_pin_end, l_end);
+            laddr_offset_t pin_end = pin_start + pin_len;
+            assert(l_current < pin_end);
+            laddr_offset_t l_current_end = std::min(pin_end, l_end);
+            extent_len_t read_len =
+              l_current_end.get_byte_distance<extent_len_t>(l_current);
+
             if (pin->get_val().is_zero()) {
               DEBUGT("got {}~{} from zero-pin {}~{}",
                 ctx.t,
                 l_current,
-                l_current_end.get_byte_distance<loffset_t>(l_current),
-                pin_key,
+                read_len,
+                pin_start,
                 pin_len);
-              ret.append_zero(
-               l_current_end.get_byte_distance<
-                 extent_len_t>(l_current));
+              ret.append_zero(read_len);
               l_current = l_current_end;
               return seastar::now();
             }
 
             // non-zero pin
-            bool is_indirect = pin->is_indirect();
-            laddr_t e_key;
-            extent_len_t e_len;
-            extent_len_t e_off;
-            if (is_indirect) {
-              e_key = pin->get_intermediate_base();
-              e_len = pin->get_intermediate_length();
-              e_off = pin->get_intermediate_offset();
-              DEBUGT("reading {}~{} from indirect-pin {}~{}, direct-pin {}~{}(off={})",
-                ctx.t,
-                l_current,
-               l_current_end.get_byte_distance<extent_len_t>(l_current),
-                pin_key,
-                pin_len,
-                e_key,
-                e_len,
-                e_off);
-              assert(e_key <= pin->get_intermediate_key());
-              assert(e_off + pin_len <= e_len);
-            } else {
-              DEBUGT("reading {}~{} from pin {}~{}",
-                ctx.t,
-                l_current,
-               l_current_end.get_byte_distance<
-                  extent_len_t>(l_current),
-                pin_key,
-                pin_len);
-              e_key = pin_key;
-              e_len = pin_len;
-              e_off = 0;
-            }
-            extent_len_t e_current_off = (l_current + e_off)
-               .template get_byte_distance<extent_len_t>(pin_key);
+            DEBUGT("reading {}~{} from pin {}~{}",
+              ctx.t,
+              l_current,
+              read_len,
+              pin_start,
+              pin_len);
+            extent_len_t e_current_off =
+              l_current.template get_byte_distance<extent_len_t>(pin_start);
             return ctx.tm.read_pin<ObjectDataBlock>(
               ctx.t,
               std::move(pin)
             ).si_then([&ret, &l_current, l_current_end,
-#ifndef NDEBUG
-                       e_key, e_len, e_current_off](auto extent) {
-#else
-                       e_current_off](auto extent) {
-#endif
-              assert(e_key == extent->get_laddr());
-              assert(e_len == extent->get_length());
+                       e_current_off, read_len](auto maybe_indirect_extent) {
               ret.append(
                 bufferptr(
-                  extent->get_bptr(),
+                  maybe_indirect_extent.get_bptr(),
                   e_current_off,
-                  l_current_end.get_byte_distance<extent_len_t>(l_current)));
+                  read_len));
               l_current = l_current_end;
               return seastar::now();
             }).handle_error_interruptible(
index 8d06accef1ea18993b43fcec0d8d522a2d80d49c..df97f394a0d12ba6ffdcc123b2403ca5a1420b15 100644 (file)
@@ -734,23 +734,28 @@ omap_load_extent(omap_context_t oc, laddr_t laddr, depth_t depth)
 {
   ceph_assert(depth > 0);
   if (depth > 1) {
-    return oc.tm.read_extent<OMapInnerNode>(oc.t, laddr,
-      OMAP_INNER_BLOCK_SIZE)
-      .handle_error_interruptible(
+    return oc.tm.read_extent<OMapInnerNode>(
+        oc.t, laddr, OMAP_INNER_BLOCK_SIZE
+    ).handle_error_interruptible(
       omap_load_extent_iertr::pass_further{},
       crimson::ct_error::assert_all{ "Invalid error in omap_load_extent" }
-    ).si_then(
-      [](auto&& e) {
-      return seastar::make_ready_future<OMapNodeRef>(std::move(e));
+    ).si_then([](auto maybe_indirect_extent) {
+      assert(!maybe_indirect_extent.is_indirect());
+      assert(!maybe_indirect_extent.is_clone);
+      return seastar::make_ready_future<OMapNodeRef>(
+          std::move(maybe_indirect_extent.extent));
     });
   } else {
-    return oc.tm.read_extent<OMapLeafNode>(oc.t, laddr, OMAP_LEAF_BLOCK_SIZE
+    return oc.tm.read_extent<OMapLeafNode>(
+        oc.t, laddr, OMAP_LEAF_BLOCK_SIZE
     ).handle_error_interruptible(
       omap_load_extent_iertr::pass_further{},
       crimson::ct_error::assert_all{ "Invalid error in omap_load_extent" }
-    ).si_then(
-      [](auto&& e) {
-      return seastar::make_ready_future<OMapNodeRef>(std::move(e));
+    ).si_then([](auto maybe_indirect_extent) {
+      assert(!maybe_indirect_extent.is_indirect());
+      assert(!maybe_indirect_extent.is_clone);
+      return seastar::make_ready_future<OMapNodeRef>(
+          std::move(maybe_indirect_extent.extent));
     });
   }
 }
index 9230051cc50de69c00cd021d5b26131079f7b079..b5d674ffcaaaaca7f36a76d92c18072e01e05b15 100644 (file)
@@ -111,10 +111,14 @@ class SeastoreNodeExtentManager final: public TransactionManagerHandle {
       }
     }
     return tm.read_extent<SeastoreNodeExtent>(t, addr
-    ).si_then([addr, &t](auto&& e) -> read_iertr::future<NodeExtentRef> {
+    ).si_then([addr, &t](auto maybe_indirect_extent)
+              -> read_iertr::future<NodeExtentRef> {
+      auto e = maybe_indirect_extent.extent;
       SUBTRACET(seastore_onode,
           "read {}B at {} -- {}",
           t, e->get_length(), e->get_laddr(), *e);
+      assert(!maybe_indirect_extent.is_indirect());
+      assert(!maybe_indirect_extent.is_clone);
       assert(e->get_laddr() == addr);
       std::ignore = addr;
       return read_iertr::make_ready_future<NodeExtentRef>(e);
index e81ce5533364a1139be0f625b903111b0bafa3e0..b2e500d9d9ca527af86bfc5ba1b0b495a383c728 100644 (file)
@@ -136,6 +136,38 @@ public:
     });
   }
 
+  /**
+   * maybe_indirect_extent_t
+   *
+   * Contains necessary information in case the extent is loaded from an
+   * indirect pin.
+   */
+  struct indirect_info_t {
+    extent_len_t intermediate_offset = 0;
+    extent_len_t length = 0;
+  };
+  template <typename T>
+  struct maybe_indirect_extent_t {
+    TCachedExtentRef<T> extent;
+    std::optional<indirect_info_t> maybe_indirect_info;
+    bool is_clone = false;
+
+    bool is_indirect() const {
+      return maybe_indirect_info.has_value();
+    }
+
+    ceph::bufferptr get_bptr() const {
+      if (is_indirect()) {
+        return ceph::bufferptr(
+            extent->get_bptr(),
+            maybe_indirect_info->intermediate_offset,
+            maybe_indirect_info->length);
+      } else {
+        return extent->get_bptr();
+      }
+    }
+  };
+
   /**
    * read_extent
    *
@@ -143,8 +175,8 @@ public:
    */
   using read_extent_iertr = get_pin_iertr;
   template <typename T>
-  using read_extent_ret = read_extent_iertr::future<
-    TCachedExtentRef<T>>;
+  using read_extent_ret =
+    read_extent_iertr::future<maybe_indirect_extent_t<T>>;
   template <typename T>
   read_extent_ret<T> read_extent(
     Transaction &t,
@@ -192,10 +224,16 @@ public:
   }
 
   template <typename T>
-  base_iertr::future<TCachedExtentRef<T>> read_pin(
+  base_iertr::future<maybe_indirect_extent_t<T>> read_pin(
     Transaction &t,
     LBAMappingRef pin)
   {
+    bool is_clone = pin->is_clone();
+    std::optional<indirect_info_t> maybe_indirect_info;
+    if (pin->is_indirect()) {
+      maybe_indirect_info = indirect_info_t{
+        pin->get_intermediate_offset(), pin->get_length()};
+    }
     LOG_PREFIX(TransactionManager::read_pin);
     SUBDEBUGT(seastore_tm, "{} {} ...", t, T::TYPE, *pin);
     auto fut = base_iertr::make_ready_future<LBAMappingRef>();
@@ -223,9 +261,16 @@ public:
       } else {
        return this->pin_to_extent<T>(t, std::move(std::get<0>(ret)));
       }
-    }).si_then([FNAME, &t](TCachedExtentRef<T> ext) {
-      SUBDEBUGT(seastore_tm, "got {}", t, *ext);
-      return ext;
+    }).si_then([FNAME, maybe_indirect_info, is_clone, &t](TCachedExtentRef<T> ext) {
+      if (maybe_indirect_info.has_value()) {
+        SUBDEBUGT(seastore_tm, "got indirect +0x{:x}~0x{:x} is_clone={} {}",
+                  t, maybe_indirect_info->intermediate_offset,
+                  maybe_indirect_info->length, is_clone, *ext);
+      } else {
+        SUBDEBUGT(seastore_tm, "got direct is_clone={} {}",
+                  t, is_clone, *ext);
+      }
+      return maybe_indirect_extent_t<T>{ext, maybe_indirect_info, is_clone};
     });
   }
 
@@ -355,7 +400,8 @@ public:
   }
 
   template <typename T>
-  read_extent_ret<T> get_mutable_extent_by_laddr(
+  get_pin_iertr::future<TCachedExtentRef<T>>
+  get_mutable_extent_by_laddr(
       Transaction &t,
       laddr_t laddr,
       extent_len_t len) {
@@ -367,8 +413,11 @@ public:
       ceph_assert(!pin->is_clone());
       ceph_assert(pin->get_length() == len);
       return this->read_pin<T>(t, std::move(pin));
-    }).si_then([this, &t, FNAME](auto extent) {
-      auto ext = get_mutable_extent(t, extent)->template cast<T>();
+    }).si_then([this, &t, FNAME](auto maybe_indirect_extent) {
+      assert(!maybe_indirect_extent.is_indirect());
+      assert(!maybe_indirect_extent.is_clone);
+      auto ext = get_mutable_extent(
+          t, maybe_indirect_extent.extent)->template cast<T>();
       SUBDEBUGT(seastore_tm, "got mutable {}", t, *ext);
       return read_extent_iertr::make_ready_future<TCachedExtentRef<T>>(
        std::move(ext));
@@ -431,6 +480,7 @@ public:
       // The according extent might be stable or pending.
       auto fut = base_iertr::now();
       if (!pin->is_indirect()) {
+        ceph_assert(!pin->is_clone());
        if (!pin->is_parent_viewable()) {
          if (pin->is_parent_valid()) {
            pin = pin->refresh_with_pending_parent();
@@ -451,7 +501,12 @@ public:
 
        fut = fut.si_then([this, &t, &pin] {
          if (full_extent_integrity_check) {
-           return read_pin<T>(t, pin->duplicate());
+           return read_pin<T>(t, pin->duplicate()
+            ).si_then([](auto maybe_indirect_extent) {
+              assert(!maybe_indirect_extent.is_indirect());
+              assert(!maybe_indirect_extent.is_clone);
+              return maybe_indirect_extent.extent;
+            });
          } else {
            auto ret = get_extent_if_linked<T>(t, pin->duplicate());
            if (ret.index() == 1) {
@@ -685,8 +740,11 @@ public:
       t
     ).si_then([&t, this](auto root) {
       return read_extent<RootMetaBlock>(t, root->root.meta);
-    }).si_then([key, &t](auto mblock) {
+    }).si_then([key, &t](auto maybe_indirect_extent) {
       LOG_PREFIX(TransactionManager::read_root_meta);
+      assert(!maybe_indirect_extent.is_indirect());
+      assert(!maybe_indirect_extent.is_clone);
+      auto& mblock = maybe_indirect_extent.extent;
       auto meta = mblock->get_meta();
       auto iter = meta.find(key);
       if (iter == meta.end()) {
@@ -744,7 +802,10 @@ public:
       t
     ).si_then([this, &t](RootBlockRef root) {
       return read_extent<RootMetaBlock>(t, root->root.meta);
-    }).si_then([this, key, value, &t](auto mblock) {
+    }).si_then([this, key, value, &t](auto maybe_indirect_extent) {
+      assert(!maybe_indirect_extent.is_indirect());
+      assert(!maybe_indirect_extent.is_clone);
+      auto& mblock = maybe_indirect_extent.extent;
       mblock = get_mutable_extent(t, mblock
        )->template cast<RootMetaBlock>();
 
@@ -878,6 +939,8 @@ private:
     extent_types_t type)
   {
     ceph_assert(!pin->parent_modified());
+    assert(!pin->is_indirect());
+    // Note: pin might be a clone
     auto v = pin->get_logical_extent(t);
     // checking the lba child must be atomic with creating
     // and linking the absent child
index 7af0d996caa3b9d051e276aaa01769bed59d2270..389ecd78afc1edc087790011871a5635365c3693 100644 (file)
@@ -82,11 +82,14 @@ TMDriver::read_extents_ret TMDriver::read_extents(
            return tm->read_pin<TestBlock>(
              t,
              std::move(pin)
-           ).si_then([&ret](auto ref) mutable {
-             ret.push_back(std::make_pair(ref->get_laddr(), ref));
+           ).si_then([&ret](auto maybe_indirect_extent) mutable {
+             assert(!maybe_indirect_extent.is_indirect());
+             assert(!maybe_indirect_extent.is_clone);
+             auto& e = maybe_indirect_extent.extent;
+             ret.push_back(std::make_pair(e->get_laddr(), e));
              logger().debug(
                "read_extents: got extent {}",
-               *ref);
+               *e);
              return seastar::now();
            });
          }).si_then([&ret] {
index 5dbc3748e5b9351ec950bbc62a7b0225c8eadafb..e7374d1d9b8bb02ba0c6c3b9583cc27a4f387e6d 100644 (file)
@@ -264,10 +264,13 @@ struct object_data_handler_test_t:
     auto &layout = onode->get_layout();
     auto odata = layout.object_data.get();
     auto obase = odata.get_reserved_data_base();
-    auto ext = with_trans_intr(t, [&](auto& trans) {
+    auto maybe_indirect_ext = with_trans_intr(t, [&](auto& trans) {
       return tm->read_extent<ObjectDataBlock>(
        trans, (obase + addr).checked_to_laddr(), len);
     }).unsafe_get();
+    EXPECT_FALSE(maybe_indirect_ext.is_clone);
+    EXPECT_FALSE(maybe_indirect_ext.is_indirect());
+    auto ext = maybe_indirect_ext.extent;
     EXPECT_EQ((obase + addr).checked_to_laddr(), ext->get_laddr());
     return ext;
   }
index 2d20c5fff945895116ca6006638819fec7b2874d..7ee05f111e7b604dddc1e0d5c3a6cec1c688ec9e 100644 (file)
@@ -506,9 +506,10 @@ struct transaction_manager_test_t :
     ceph_assert(test_mappings.contains(addr, t.mapping_delta));
     ceph_assert(test_mappings.get(addr, t.mapping_delta).desc.len == len);
 
-    auto ext = with_trans_intr(*(t.t), [&](auto& trans) {
+    auto maybe_indirect_ext = with_trans_intr(*(t.t), [&](auto& trans) {
       return tm->read_pin<TestBlock>(trans, std::move(pin));
     }).unsafe_get();
+    auto ext = maybe_indirect_ext.extent;
     EXPECT_EQ(addr, ext->get_laddr());
     return ext;
   }
@@ -520,9 +521,10 @@ struct transaction_manager_test_t :
     ceph_assert(test_mappings.contains(addr, t.mapping_delta));
     ceph_assert(test_mappings.get(addr, t.mapping_delta).desc.len == len);
 
-    auto ext = with_trans_intr(*(t.t), [&](auto& trans) {
+    auto maybe_indirect_ext = with_trans_intr(*(t.t), [&](auto& trans) {
       return tm->read_extent<TestBlock>(trans, addr, len);
     }).unsafe_get();
+    auto ext = maybe_indirect_ext.extent;
     EXPECT_EQ(addr, ext->get_laddr());
     return ext;
   }
@@ -533,11 +535,10 @@ struct transaction_manager_test_t :
     ceph_assert(test_mappings.contains(addr, t.mapping_delta));
 
     using ertr = with_trans_ertr<TransactionManager::read_extent_iertr>;
-    using ret = ertr::future<TestBlockRef>;
     auto ext = with_trans_intr(*(t.t), [&](auto& trans) {
       return tm->read_extent<TestBlock>(trans, addr);
-    }).safe_then([](auto ext) -> ret {
-      return ertr::make_ready_future<TestBlockRef>(ext);
+    }).safe_then([](auto ret) {
+      return ertr::make_ready_future<TestBlockRef>(ret.extent);
     }).handle_error(
       [](const crimson::ct_error::eagain &e) {
        return seastar::make_ready_future<TestBlockRef>();
@@ -560,11 +561,10 @@ struct transaction_manager_test_t :
     ceph_assert(test_mappings.get(addr, t.mapping_delta).desc.len == len);
 
     using ertr = with_trans_ertr<TransactionManager::read_extent_iertr>;
-    using ret = ertr::future<TestBlockRef>;
     auto ext = with_trans_intr(*(t.t), [&](auto& trans) {
       return tm->read_extent<TestBlock>(trans, addr, len);
-    }).safe_then([](auto ext) -> ret {
-      return ertr::make_ready_future<TestBlockRef>(ext);
+    }).safe_then([](auto ret) {
+      return ertr::make_ready_future<TestBlockRef>(ret.extent);
     }).handle_error(
       [](const crimson::ct_error::eagain &e) {
        return seastar::make_ready_future<TestBlockRef>();
@@ -583,14 +583,13 @@ struct transaction_manager_test_t :
     test_transaction_t &t,
     LBAMappingRef &&pin) {
     using ertr = with_trans_ertr<TransactionManager::base_iertr>;
-    using ret = ertr::future<TestBlockRef>;
     bool indirect = pin->is_indirect();
     auto addr = pin->get_key();
     auto im_addr = indirect ? pin->get_intermediate_base() : L_ADDR_NULL;
     auto ext = with_trans_intr(*(t.t), [&](auto& trans) {
       return tm->read_pin<TestBlock>(trans, std::move(pin));
-    }).safe_then([](auto ext) -> ret {
-      return ertr::make_ready_future<TestBlockRef>(ext);
+    }).safe_then([](auto ret) {
+      return ertr::make_ready_future<TestBlockRef>(ret.extent);
     }).handle_error(
       [](const crimson::ct_error::eagain &e) {
        return seastar::make_ready_future<TestBlockRef>();