summaryrefslogtreecommitdiff
path: root/src/crimson/os/seastore/cache.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/crimson/os/seastore/cache.h')
-rw-r--r--src/crimson/os/seastore/cache.h233
1 files changed, 139 insertions, 94 deletions
diff --git a/src/crimson/os/seastore/cache.h b/src/crimson/os/seastore/cache.h
index 0b4a50afed7..a63162a45a0 100644
--- a/src/crimson/os/seastore/cache.h
+++ b/src/crimson/os/seastore/cache.h
@@ -83,6 +83,15 @@ namespace crimson::os::seastore {
* CachedExtent::delta_written(paddr_t) with the address of the start
* of the record
* - Complete all promises with the final record start paddr_t
+ *
+ *
+ * Cache logs
+ *
+ * levels:
+ * - INFO: major initiation, closing operations
+ * - DEBUG: major extent related operations, INFO details
+ * - TRACE: DEBUG details
+ * - seastore_t logs
*/
class Cache {
public:
@@ -111,8 +120,8 @@ public:
return on_transaction_destruct(t);
}
);
- SUBDEBUGT(seastore_cache, "created name={}, source={}, is_weak={}",
- *ret, name, src, is_weak);
+ SUBDEBUGT(seastore_t, "created name={}, source={}, is_weak={}",
+ *ret, name, src, is_weak);
return ret;
}
@@ -120,25 +129,16 @@ public:
void reset_transaction_preserve_handle(Transaction &t) {
LOG_PREFIX(Cache::reset_transaction_preserve_handle);
if (t.did_reset()) {
+ SUBTRACET(seastore_t, "reset", t);
++(get_by_src(stats.trans_created_by_src, t.get_src()));
}
t.reset_preserve_handle(last_commit);
- SUBDEBUGT(seastore_cache, "reset", t);
- }
-
- /**
- * drop_from_cache
- *
- * Drop extent from cache. Intended for use when
- * ref refers to a logically dead extent as during
- * replay.
- */
- void drop_from_cache(CachedExtentRef ref) {
- remove_extent(ref);
}
/// Declare ref retired in t
void retire_extent(Transaction &t, CachedExtentRef ref) {
+ LOG_PREFIX(Cache::retire_extent);
+ SUBDEBUGT(seastore_cache, "retire extent -- {}", t, *ref);
t.add_to_retired_set(ref);
}
@@ -163,6 +163,8 @@ public:
* returns t.root and assume it is already present/read in t
*/
RootBlockRef get_root_fast(Transaction &t) {
+ LOG_PREFIX(Cache::get_root_fast);
+ SUBTRACET(seastore_cache, "root already on t -- {}", t, *t.root);
assert(t.root);
return t.root;
}
@@ -185,8 +187,11 @@ public:
const src_ext_t* p_metric_key, ///< [in] cache query metric key
Func &&extent_init_func ///< [in] init func for extent
) {
+ LOG_PREFIX(Cache::get_extent);
auto cached = query_cache(offset, p_metric_key);
if (!cached) {
+ SUBDEBUG(seastore_cache,
+ "{} {}~{} is absent, reading ...", T::TYPE, offset, length);
auto ret = CachedExtent::make_cached_extent_ref<T>(
alloc_cache_buf(length));
ret->set_paddr(offset);
@@ -199,6 +204,9 @@ public:
// extent PRESENT in cache
if (cached->get_type() == extent_types_t::RETIRED_PLACEHOLDER) {
+ SUBDEBUG(seastore_cache,
+ "{} {}~{} is absent(placeholder), reading ...",
+ T::TYPE, offset, length);
auto ret = CachedExtent::make_cached_extent_ref<T>(
alloc_cache_buf(length));
ret->set_paddr(offset);
@@ -216,6 +224,9 @@ public:
return read_extent<T>(
std::move(ret));
} else {
+ SUBTRACE(seastore_cache,
+ "{} {}~{} is present in cache -- {}",
+ T::TYPE, offset, length, *cached);
auto ret = TCachedExtentRef<T>(static_cast<T*>(cached.get()));
return ret->wait_io(
).then([ret=std::move(ret)]() mutable
@@ -253,11 +264,14 @@ public:
CachedExtentRef ret;
LOG_PREFIX(Cache::get_extent_if_cached);
auto result = t.get_extent(offset, &ret);
- if (result != Transaction::get_extent_ret::ABSENT) {
- // including get_extent_ret::RETIRED
- SUBDEBUGT(seastore_cache,
- "Found extent at offset {} on transaction: {}",
- t, offset, *ret);
+ if (result == Transaction::get_extent_ret::RETIRED) {
+ SUBDEBUGT(seastore_cache, "{} {} is retired on t -- {}",
+ t, type, offset, *ret);
+ return get_extent_if_cached_iertr::make_ready_future<
+ CachedExtentRef>(ret);
+ } else if (result == Transaction::get_extent_ret::PRESENT) {
+ SUBTRACET(seastore_cache, "{} {} is present on t -- {}",
+ t, type, offset, *ret);
return get_extent_if_cached_iertr::make_ready_future<
CachedExtentRef>(ret);
}
@@ -268,17 +282,15 @@ public:
if (!ret ||
// retired_placeholder is not really cached yet
ret->get_type() == extent_types_t::RETIRED_PLACEHOLDER) {
- SUBDEBUGT(seastore_cache,
- "No extent at offset {}, retired_placeholder: {}",
- t, offset, !!ret);
+ SUBDEBUGT(seastore_cache, "{} {} is absent{}",
+ t, type, offset, !!ret ? "(placeholder)" : "");
return get_extent_if_cached_iertr::make_ready_future<
CachedExtentRef>();
}
// present in cache and is not a retired_placeholder
- SUBDEBUGT(seastore_cache,
- "Found extent at offset {} in cache: {}",
- t, offset, *ret);
+ SUBDEBUGT(seastore_cache, "{} {} is present in cache -- {}",
+ t, type, offset, *ret);
t.add_to_read_set(ret);
touch_extent(*ret);
return ret->wait_io().then([ret] {
@@ -308,29 +320,33 @@ public:
LOG_PREFIX(Cache::get_extent);
auto result = t.get_extent(offset, &ret);
if (result != Transaction::get_extent_ret::ABSENT) {
+ SUBTRACET(seastore_cache, "{} {}~{} is {} on t -- {}",
+ t,
+ T::TYPE,
+ offset,
+ length,
+ result == Transaction::get_extent_ret::PRESENT ? "present" : "retired",
+ *ret);
assert(result != Transaction::get_extent_ret::RETIRED);
- SUBDEBUGT(seastore_cache,
- "Found extent at offset {} on transaction: {}",
- t, offset, *ret);
return seastar::make_ready_future<TCachedExtentRef<T>>(
ret->cast<T>());
} else {
+ SUBTRACET(seastore_cache, "{} {}~{} is absent on t, query cache ...",
+ t, T::TYPE, offset, length);
auto metric_key = std::make_pair(t.get_src(), T::TYPE);
return trans_intr::make_interruptible(
get_extent<T>(
offset, length, &metric_key,
std::forward<Func>(extent_init_func))
- ).si_then([this, FNAME, offset, &t](auto ref) {
+ ).si_then([this, FNAME, offset, length, &t](auto ref) {
(void)this; // silence incorrect clang warning about capture
if (!ref->is_valid()) {
- SUBDEBUGT(seastore_cache, "got invalid extent: {}", t, ref);
+ SUBDEBUGT(seastore_cache, "{} {}~{} is invalid -- {}",
+ t, T::TYPE, offset, length, *ref);
++(get_by_src(stats.trans_conflicts_by_unknown, t.get_src()));
mark_transaction_conflicted(t, *ref);
return get_extent_iertr::make_ready_future<TCachedExtentRef<T>>();
} else {
- SUBDEBUGT(seastore_cache,
- "Read extent at offset {} in cache: {}",
- t, offset, *ref);
touch_extent(*ref);
t.add_to_read_set(ref);
return get_extent_iertr::make_ready_future<TCachedExtentRef<T>>(
@@ -347,13 +363,6 @@ public:
return get_extent<T>(t, offset, length, [](T &){});
}
-
- /**
- * get_extent_by_type
- *
- * Based on type, instantiate the correct concrete type
- * and read in the extent at location offset~length.
- */
private:
// This is a workaround std::move_only_function not being available,
// not really worth generalizing at this time.
@@ -399,14 +408,22 @@ private:
paddr_t offset,
laddr_t laddr,
seastore_off_t length,
- extent_init_func_t &&extent_init_func) {
+ extent_init_func_t &&extent_init_func
+ ) {
+ LOG_PREFIX(Cache::get_extent_by_type);
CachedExtentRef ret;
auto status = t.get_extent(offset, &ret);
if (status == Transaction::get_extent_ret::RETIRED) {
+ SUBDEBUGT(seastore_cache, "{} {}~{} {} is retired on t -- {}",
+ t, type, offset, length, laddr, *ret);
return seastar::make_ready_future<CachedExtentRef>();
} else if (status == Transaction::get_extent_ret::PRESENT) {
+ SUBTRACET(seastore_cache, "{} {}~{} {} is present on t -- {}",
+ t, type, offset, length, laddr, *ret);
return seastar::make_ready_future<CachedExtentRef>(ret);
} else {
+ SUBTRACET(seastore_cache, "{} {}~{} {} is absent on t, query cache ...",
+ t, type, offset, length, laddr);
auto src = t.get_src();
return trans_intr::make_interruptible(
_get_extent_by_type(
@@ -414,8 +431,8 @@ private:
std::move(extent_init_func))
).si_then([=, &t](CachedExtentRef ret) {
if (!ret->is_valid()) {
- LOG_PREFIX(Cache::get_extent_by_type);
- SUBDEBUGT(seastore_cache, "got invalid extent: {}", t, ret);
+ SUBDEBUGT(seastore_cache, "{} {}~{} {} is invalid -- {}",
+ t, type, offset, length, laddr, *ret);
++(get_by_src(stats.trans_conflicts_by_unknown, t.get_src()));
mark_transaction_conflicted(t, *ret.get());
return get_extent_ertr::make_ready_future<CachedExtentRef>();
@@ -430,6 +447,12 @@ private:
}
public:
+ /**
+ * get_extent_by_type
+ *
+ * Based on type, instantiate the correct concrete type
+ * and read in the extent at location offset~length.
+ */
template <typename Func>
get_extent_by_type_ret get_extent_by_type(
Transaction &t, ///< [in] transaction
@@ -470,6 +493,9 @@ public:
seastore_off_t length, ///< [in] length
bool delayed = false ///< [in] whether the paddr allocation of extent is delayed
) {
+ LOG_PREFIX(Cache::alloc_new_extent);
+ SUBDEBUGT(seastore_cache, "allocate {} {}B, delay={}",
+ t, T::TYPE, length, delayed);
auto ret = CachedExtent::make_cached_extent_ref<T>(
alloc_cache_buf(length));
t.add_fresh_extent(ret, delayed);
@@ -477,20 +503,23 @@ public:
return ret;
}
- void clear_lru() {
- lru.clear();
- }
-
void mark_delayed_extent_inline(
Transaction& t,
- LogicalCachedExtentRef& ref) {
+ LogicalCachedExtentRef& ref
+ ) {
+ LOG_PREFIX(Cache::mark_delayed_extent_inline);
+ SUBDEBUGT(seastore_cache, "-- {}", t, *ref);
t.mark_delayed_extent_inline(ref);
}
void mark_delayed_extent_ool(
Transaction& t,
LogicalCachedExtentRef& ref,
- paddr_t final_addr) {
+ paddr_t final_addr
+ ) {
+ LOG_PREFIX(Cache::mark_delayed_extent_ool);
+ SUBDEBUGT(seastore_cache, "final_addr={} -- {}",
+ t, final_addr, *ref);
t.mark_delayed_extent_ool(ref, final_addr);
}
@@ -598,26 +627,56 @@ public:
Transaction &t,
F &&f)
{
+ LOG_PREFIX(Cache::init_cached_extents);
+ SUBINFOT(seastore_cache,
+ "start with {}({}B) extents, {} dirty, from {}",
+ t,
+ extents.size(),
+ extents.get_bytes(),
+ dirty.size(),
+ get_oldest_dirty_from().value_or(journal_seq_t{}));
+
// journal replay should has been finished at this point,
// Cache::root should have been inserted to the dirty list
assert(root->is_dirty());
- std::vector<CachedExtentRef> dirty;
+ std::vector<CachedExtentRef> _dirty;
for (auto &e : extents) {
- dirty.push_back(CachedExtentRef(&e));
+ _dirty.push_back(CachedExtentRef(&e));
}
return seastar::do_with(
std::forward<F>(f),
- std::move(dirty),
- [&t](auto &f, auto &refs) mutable {
- return trans_intr::do_for_each(
- refs,
- [&t, &f](auto &e) { return f(t, e); });
- }).handle_error_interruptible(
- init_cached_extents_iertr::pass_further{},
- crimson::ct_error::assert_all{
- "Invalid error in Cache::init_cached_extents"
- }
- );
+ std::move(_dirty),
+ [this, FNAME, &t](auto &f, auto &refs) mutable
+ {
+ return trans_intr::do_for_each(
+ refs,
+ [this, FNAME, &t, &f](auto &e)
+ {
+ SUBTRACET(seastore_cache, "inspecting extent ... -- {}", t, *e);
+ return f(t, e
+ ).si_then([this, FNAME, &t, e](bool is_alive) {
+ if (!is_alive) {
+ SUBDEBUGT(seastore_cache, "extent is not alive, remove -- {}", t, *e);
+ remove_extent(e);
+ } else {
+ SUBDEBUGT(seastore_cache, "extent is alive -- {}", t, *e);
+ }
+ });
+ });
+ }).handle_error_interruptible(
+ init_cached_extents_iertr::pass_further{},
+ crimson::ct_error::assert_all{
+ "Invalid error in Cache::init_cached_extents"
+ }
+ ).si_then([this, FNAME, &t] {
+ SUBINFOT(seastore_cache,
+ "finish with {}({}B) extents, {} dirty, from {}",
+ t,
+ extents.size(),
+ extents.get_bytes(),
+ dirty.size(),
+ get_oldest_dirty_from().value_or(journal_seq_t{}));
+ });
}
/**
@@ -743,6 +802,10 @@ private:
public:
LRU(size_t capacity) : capacity(capacity) {}
+ size_t get_capacity() const {
+ return capacity;
+ }
+
size_t get_current_contents_bytes() const {
return contents;
}
@@ -797,49 +860,29 @@ private:
uint64_t hit = 0;
};
- /**
- * effort_t
- *
- * Count the number of extents involved in the effort and the total bytes of
- * them.
- *
- * Each effort_t represents the effort of a set of extents involved in the
- * transaction, classified by read, mutate, retire and allocate behaviors,
- * see XXX_trans_efforts_t.
- */
- struct effort_t {
- uint64_t extents = 0;
- uint64_t bytes = 0;
-
- void increment(uint64_t extent_len) {
- ++extents;
- bytes += extent_len;
- }
- };
-
template <typename CounterT>
using counter_by_extent_t = std::array<CounterT, EXTENT_TYPES_MAX>;
struct invalid_trans_efforts_t {
- effort_t read;
- effort_t mutate;
+ io_stat_t read;
+ io_stat_t mutate;
uint64_t mutate_delta_bytes = 0;
- effort_t retire;
- effort_t fresh;
- effort_t fresh_ool_written;
+ io_stat_t retire;
+ io_stat_t fresh;
+ io_stat_t fresh_ool_written;
counter_by_extent_t<uint64_t> num_trans_invalidated;
uint64_t num_ool_records = 0;
uint64_t ool_record_bytes = 0;
};
struct commit_trans_efforts_t {
- counter_by_extent_t<effort_t> read_by_ext;
- counter_by_extent_t<effort_t> mutate_by_ext;
+ counter_by_extent_t<io_stat_t> read_by_ext;
+ counter_by_extent_t<io_stat_t> mutate_by_ext;
counter_by_extent_t<uint64_t> delta_bytes_by_ext;
- counter_by_extent_t<effort_t> retire_by_ext;
- counter_by_extent_t<effort_t> fresh_invalid_by_ext; // inline but is already invalid (retired)
- counter_by_extent_t<effort_t> fresh_inline_by_ext;
- counter_by_extent_t<effort_t> fresh_ool_by_ext;
+ counter_by_extent_t<io_stat_t> retire_by_ext;
+ counter_by_extent_t<io_stat_t> fresh_invalid_by_ext; // inline but is already invalid (retired)
+ counter_by_extent_t<io_stat_t> fresh_inline_by_ext;
+ counter_by_extent_t<io_stat_t> fresh_ool_by_ext;
uint64_t num_trans = 0; // the number of inline records
uint64_t num_ool_records = 0;
uint64_t ool_record_padding_bytes = 0;
@@ -849,7 +892,7 @@ private:
};
struct success_read_trans_efforts_t {
- effort_t read;
+ io_stat_t read;
uint64_t num_trans = 0;
};
@@ -995,12 +1038,14 @@ private:
extent->get_bptr()
).safe_then(
[extent=std::move(extent)]() mutable {
+ LOG_PREFIX(Cache::read_extent);
extent->state = CachedExtent::extent_state_t::CLEAN;
/* TODO: crc should be checked against LBA manager */
extent->last_committed_crc = extent->get_crc32c();
extent->on_clean_read();
extent->complete_io();
+ SUBDEBUG(seastore_cache, "read extent done -- {}", *extent);
return get_extent_ertr::make_ready_future<TCachedExtentRef<T>>(
std::move(extent));
},