}
}
+Cache::get_extent_by_type_ret
+Cache::_get_absent_extent_by_type(
+ Transaction &t,
+ extent_types_t type,
+ paddr_t offset,
+ laddr_t laddr,
+ extent_len_t length,
+ extent_init_func_t &&extent_init_func)
+{
+ LOG_PREFIX(Cache::_get_absent_extent_by_type);
+
+#ifndef NDEBUG
+ {
+ CachedExtentRef ret;
+ auto r = t.get_extent(offset, &ret);
+ if (r != Transaction::get_extent_ret::ABSENT) {
+ SUBERRORT(seastore_cache, "unexpected non-absent extent {}", t, *ret);
+ ceph_abort();
+ }
+ assert(!query_cache(offset));
+ }
+#endif
+
+ const auto t_src = t.get_src();
+
+ // partial read
+ CachedExtentRef ret;
+ switch (type) {
+ case extent_types_t::ROOT:
+ ceph_assert(0 == "ROOT is never directly read");
+ break;
+ case extent_types_t::BACKREF_INTERNAL:
+ ret = CachedExtent::make_cached_extent_ref<
+ backref::BackrefInternalNode>(length);
+ break;
+ case extent_types_t::BACKREF_LEAF:
+ ret = CachedExtent::make_cached_extent_ref<
+ backref::BackrefLeafNode>(length);
+ break;
+ case extent_types_t::LADDR_INTERNAL:
+ ret = CachedExtent::make_cached_extent_ref<
+ lba::LBAInternalNode>(length);
+ break;
+ case extent_types_t::LADDR_LEAF:
+ ret = CachedExtent::make_cached_extent_ref<
+ lba::LBALeafNode>(length);
+ break;
+ case extent_types_t::ROOT_META:
+ ret = CachedExtent::make_cached_extent_ref<
+ RootMetaBlock>(length);
+ break;
+ case extent_types_t::OMAP_INNER:
+ ret = CachedExtent::make_cached_extent_ref<
+ omap_manager::OMapInnerNode>(length);
+ break;
+ case extent_types_t::OMAP_LEAF:
+ ret = CachedExtent::make_cached_extent_ref<
+ omap_manager::OMapLeafNode>(length);
+ break;
+ case extent_types_t::COLL_BLOCK:
+ ret = CachedExtent::make_cached_extent_ref<
+ collection_manager::CollectionNode>(length);
+ break;
+ case extent_types_t::ONODE_BLOCK_STAGED:
+ ret = CachedExtent::make_cached_extent_ref<
+ onode::SeastoreNodeExtent>(length);
+ break;
+ case extent_types_t::OBJECT_DATA_BLOCK:
+ ret = CachedExtent::make_cached_extent_ref<ObjectDataBlock>(length);
+ break;
+ case extent_types_t::RETIRED_PLACEHOLDER:
+ ceph_assert(0 == "impossible");
+ break;
+ case extent_types_t::TEST_BLOCK:
+ ret = CachedExtent::make_cached_extent_ref<TestBlock>(length);
+ break;
+ case extent_types_t::TEST_BLOCK_PHYSICAL:
+ ret = CachedExtent::make_cached_extent_ref<TestBlockPhysical>(length);
+ break;
+ case extent_types_t::NONE:
+ ceph_assert(0 == "NONE is an invalid extent type");
+ break;
+ default:
+ ceph_assert(0 == "impossible");
+ }
+ ret->init(CachedExtent::extent_state_t::CLEAN,
+ offset,
+ PLACEMENT_HINT_NULL,
+ NULL_GENERATION,
+ TRANS_ID_NULL);
+ DEBUGT("{} length=0x{:x} is absent, add extent ... -- {}",
+ t, type, length, *ret);
+ add_extent(ret);
+ extent_init_func(*ret);
+ cache_access_stats_t& access_stats = get_by_ext(
+ get_by_src(stats.access_by_src_ext, t_src),
+ type);
+ ++access_stats.load_absent;
+ ++stats.access.load_absent;
+ t.add_to_read_set(CachedExtentRef(ret));
+ touch_extent_fully(*ret, &t_src, t.get_cache_hint());
+ return trans_intr::make_interruptible(
+ read_extent(std::move(ret), 0, length, &t_src
+ ).safe_then([laddr](auto extent) {
+ if (extent->is_logical()) {
+ extent->template cast<LogicalCachedExtent>()->set_laddr(laddr);
+ }
+ return extent;
+ })
+ );
+}
+
Cache::get_extent_ertr::future<CachedExtentRef>
Cache::do_get_caching_extent_by_type(
extent_types_t type,
extent_len_t partial_off,
extent_len_t partial_len,
Func &&extent_init_func) {
- CachedExtentRef ret;
LOG_PREFIX(Cache::get_absent_extent);
#ifndef NDEBUG
- auto r = t.get_extent(offset, &ret);
- if (r != Transaction::get_extent_ret::ABSENT) {
- SUBERRORT(seastore_cache, "unexpected non-absent extent {}", t, *ret);
- ceph_abort();
+ {
+ CachedExtentRef ret;
+ auto r = t.get_extent(offset, &ret);
+ if (r != Transaction::get_extent_ret::ABSENT) {
+ SUBERRORT(seastore_cache, "unexpected non-absent extent {}", t, *ret);
+ ceph_abort();
+ }
}
#endif
SUBTRACET(seastore_cache, "{} {}~0x{:x} is absent on t, query cache ...",
t, T::TYPE, offset, length);
const auto t_src = t.get_src();
- auto f = [&t, this, partial_off, partial_len, t_src](CachedExtent &ext) {
- // XXX: is_stable_dirty() may not be linked in lba tree
- assert(ext.is_stable());
- assert(T::TYPE == ext.get_type());
- cache_access_stats_t& access_stats = get_by_ext(
- get_by_src(stats.access_by_src_ext, t_src),
- T::TYPE);
- ++access_stats.load_absent;
- ++stats.access.load_absent;
-
- t.add_to_read_set(CachedExtentRef(&ext));
- touch_extent_by_range(
- ext, &t_src, t.get_cache_hint(),
- partial_off, partial_len);
- };
+
+ // partial read
+ TCachedExtentRef<T> ret = CachedExtent::make_cached_extent_ref<T>(length);
+ ret->init(CachedExtent::extent_state_t::CLEAN,
+ offset,
+ PLACEMENT_HINT_NULL,
+ NULL_GENERATION,
+ TRANS_ID_NULL);
+ SUBDEBUG(seastore_cache,
+ "{} {}~0x{:x} is absent, add extent and reading range 0x{:x}~0x{:x} ... -- {}",
+ T::TYPE, offset, length, partial_off, partial_len, *ret);
+ add_extent(ret);
+ extent_init_func(*ret);
+ cache_access_stats_t& access_stats = get_by_ext(
+ get_by_src(stats.access_by_src_ext, t_src),
+ T::TYPE);
+ ++access_stats.load_absent;
+ ++stats.access.load_absent;
+ t.add_to_read_set(CachedExtentRef(ret));
+ touch_extent_by_range(
+ *ret, &t_src, t.get_cache_hint(),
+ partial_off, partial_len);
return trans_intr::make_interruptible(
- do_get_caching_extent<T>(
- offset, length, partial_off, partial_len,
- std::forward<Func>(extent_init_func), std::move(f), &t_src)
- );
+ read_extent<T>(std::move(ret), partial_off, partial_len, &t_src));
}
/*
paddr_t offset,
laddr_t laddr,
extent_len_t length,
- extent_init_func_t &&extent_init_func
- ) {
- LOG_PREFIX(Cache::_get_absent_extent_by_type);
-
-#ifndef NDEBUG
- CachedExtentRef ret;
- auto r = t.get_extent(offset, &ret);
- if (r != Transaction::get_extent_ret::ABSENT) {
- SUBERRORT(seastore_cache, "unexpected non-absent extent {}", t, *ret);
- ceph_abort();
- }
-#endif
-
- SUBTRACET(seastore_cache, "{} {}~0x{:x} {} is absent on t, query cache ...",
- t, type, offset, length, laddr);
- const auto t_src = t.get_src();
- auto f = [&t, this, t_src](CachedExtent &ext) {
- // XXX: is_stable_dirty() may not be linked in lba tree
- assert(ext.is_stable());
- cache_access_stats_t& access_stats = get_by_ext(
- get_by_src(stats.access_by_src_ext, t_src),
- ext.get_type());
- ++access_stats.load_absent;
- ++stats.access.load_absent;
-
- t.add_to_read_set(CachedExtentRef(&ext));
- touch_extent_fully(ext, &t_src, t.get_cache_hint());
- };
- return trans_intr::make_interruptible(
- do_get_caching_extent_by_type(
- type, offset, laddr, length,
- std::move(extent_init_func), std::move(f), &t_src)
- );
- }
+ extent_init_func_t &&extent_init_func);
backref_entryrefs_by_seq_t backref_entryrefs_by_seq;
backref_entry_mset_t backref_entry_mset;
/// also see do_read_extent_maybe_partial().
///
/// May return an invalid extent due to transaction conflict.
- template <typename T>
- read_extent_ret<T> read_extent(
- TCachedExtentRef<T>&& extent,
+ get_extent_ertr::future<CachedExtentRef> _read_extent(
+ CachedExtentRef &&extent,
extent_len_t offset,
extent_len_t length,
- const Transaction::src_t* p_src
- ) {
+ const Transaction::src_t *p_src)
+ {
LOG_PREFIX(Cache::read_extent);
assert(extent->state == CachedExtent::extent_state_t::EXIST_CLEAN ||
extent->state == CachedExtent::extent_state_t::CLEAN);
offset, length, *extent);
}
extent->complete_io();
- return get_extent_ertr::make_ready_future<TCachedExtentRef<T>>(
+ return get_extent_ertr::make_ready_future<CachedExtentRef>(
std::move(extent));
},
get_extent_ertr::pass_further{},
);
}
+ template <typename T>
+ read_extent_ret<T> read_extent(
+ TCachedExtentRef<T>&& extent,
+ extent_len_t offset,
+ extent_len_t length,
+ const Transaction::src_t* p_src
+ ) {
+ return _read_extent(std::move(extent), offset, length, p_src
+ ).safe_then([](auto extent) {
+ return extent->template cast<T>();
+ });
+ }
+
// Extents in cache may contain placeholders
CachedExtentRef query_cache(paddr_t offset) {
if (auto iter = extents_index.find_offset(offset);