From 71d01ae43167ce2dd9045421f256f3fccd6e4f34 Mon Sep 17 00:00:00 2001 From: Yingxin Cheng Date: Tue, 18 May 2021 15:55:41 +0800 Subject: [PATCH] crimson/onode-staged-tree: extend SeastoreNodeExtentManager to test eagain Signed-off-by: Yingxin Cheng --- .../staged-fltree/node_extent_manager.cc | 10 ++- .../staged-fltree/node_extent_manager.h | 2 +- .../node_extent_manager/seastore.cc | 4 +- .../node_extent_manager/seastore.h | 75 +++++++++++++++++-- 4 files changed, 80 insertions(+), 11 deletions(-) diff --git a/src/crimson/os/seastore/onode_manager/staged-fltree/node_extent_manager.cc b/src/crimson/os/seastore/onode_manager/staged-fltree/node_extent_manager.cc index c379aad3139be..e0c83bf524e55 100644 --- a/src/crimson/os/seastore/onode_manager/staged-fltree/node_extent_manager.cc +++ b/src/crimson/os/seastore/onode_manager/staged-fltree/node_extent_manager.cc @@ -30,9 +30,15 @@ NodeExtentManagerURef NodeExtentManager::create_dummy(bool is_sync) } NodeExtentManagerURef NodeExtentManager::create_seastore( - TransactionManager& tm, laddr_t min_laddr) + TransactionManager& tm, laddr_t min_laddr, double p_eagain) { - return NodeExtentManagerURef(new SeastoreNodeExtentManager(tm, min_laddr)); + if (p_eagain == 0.0) { + return NodeExtentManagerURef( + new SeastoreNodeExtentManager(tm, min_laddr, p_eagain)); + } else { + return NodeExtentManagerURef( + new SeastoreNodeExtentManager(tm, min_laddr, p_eagain)); + } } } diff --git a/src/crimson/os/seastore/onode_manager/staged-fltree/node_extent_manager.h b/src/crimson/os/seastore/onode_manager/staged-fltree/node_extent_manager.h index 5673db0b4fb72..4304f0ed51e07 100644 --- a/src/crimson/os/seastore/onode_manager/staged-fltree/node_extent_manager.h +++ b/src/crimson/os/seastore/onode_manager/staged-fltree/node_extent_manager.h @@ -87,7 +87,7 @@ class NodeExtentManager { static NodeExtentManagerURef create_dummy(bool is_sync); static NodeExtentManagerURef create_seastore( - TransactionManager& tm, laddr_t min_laddr = L_ADDR_MIN); + TransactionManager& tm, laddr_t min_laddr = L_ADDR_MIN, double p_eagain = 0.0); }; inline std::ostream& operator<<(std::ostream& os, const NodeExtentManager& nm) { return nm.print(os); diff --git a/src/crimson/os/seastore/onode_manager/staged-fltree/node_extent_manager/seastore.cc b/src/crimson/os/seastore/onode_manager/staged-fltree/node_extent_manager/seastore.cc index d34f99c76ca39..528acb8f13157 100644 --- a/src/crimson/os/seastore/onode_manager/staged-fltree/node_extent_manager/seastore.cc +++ b/src/crimson/os/seastore/onode_manager/staged-fltree/node_extent_manager/seastore.cc @@ -48,8 +48,8 @@ NodeExtentRef SeastoreNodeExtent::mutate( context_t c, DeltaRecorderURef&& _recorder) { DEBUGT("mutate {:#x} ...", c.t, get_laddr()); - auto nm = static_cast(&c.nm); - auto extent = nm->get_tm().get_mutable_extent(c.t, this); + auto p_handle = static_cast(&c.nm); + auto extent = p_handle->tm.get_mutable_extent(c.t, this); auto ret = extent->cast(); // A replayed extent may already have an empty recorder, we discard it for // simplicity. 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 71c35476b60d1..da5ed1cde13e1 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 @@ -3,6 +3,8 @@ #pragma once +#include + #include "crimson/os/seastore/logging.h" #include "crimson/os/seastore/onode_manager/staged-fltree/node_extent_manager.h" @@ -66,18 +68,43 @@ class SeastoreNodeExtent final: public NodeExtent { DeltaRecorderURef recorder; }; -class SeastoreNodeExtentManager final: public NodeExtentManager { +class TransactionManagerHandle : public NodeExtentManager { public: - SeastoreNodeExtentManager(TransactionManager& tm, laddr_t min) - : tm{tm}, addr_min{min} {}; + TransactionManagerHandle(TransactionManager& tm) : tm{tm} {} + TransactionManager& tm; +}; + +template +class SeastoreNodeExtentManager final: public TransactionManagerHandle { + public: + SeastoreNodeExtentManager( + TransactionManager& tm, laddr_t min, double p_eagain) + : TransactionManagerHandle(tm), addr_min{min}, p_eagain{p_eagain} { + if constexpr (INJECT_EAGAIN) { + assert(p_eagain > 0.0 && p_eagain < 1.0); + } else { + assert(p_eagain == 0.0); + } + } + ~SeastoreNodeExtentManager() override = default; - TransactionManager& get_tm() { return tm; } + + void set_generate_eagain(bool enable) { + generate_eagain = enable; + } + protected: bool is_read_isolated() const override { return true; } read_ertr::future read_extent( Transaction& t, laddr_t addr, extent_len_t len) override { TRACET("reading {}B at {:#x} ...", t, len, addr); + if constexpr (INJECT_EAGAIN) { + if (trigger_eagain()) { + DEBUGT("reading {}B at {:#x}: trigger eagain", t, len, addr); + return crimson::ct_error::eagain::make(); + } + } return tm.read_extent(t, addr, len ).safe_then([addr, len, &t](auto&& e) { TRACET("read {}B at {:#x}", t, e->get_length(), e->get_laddr()); @@ -92,6 +119,12 @@ class SeastoreNodeExtentManager final: public NodeExtentManager { alloc_ertr::future alloc_extent( Transaction& t, extent_len_t len) override { TRACET("allocating {}B ...", t, len); + if constexpr (INJECT_EAGAIN) { + if (trigger_eagain()) { + DEBUGT("allocating {}B: trigger eagain", t, len); + return crimson::ct_error::eagain::make(); + } + } return tm.alloc_extent(t, addr_min, len ).safe_then([len, &t](auto extent) { DEBUGT("allocated {}B at {:#x}", @@ -108,6 +141,12 @@ class SeastoreNodeExtentManager final: public NodeExtentManager { auto addr = extent->get_laddr(); auto len = extent->get_length(); DEBUGT("retiring {}B at {:#x} ...", t, len, addr); + if constexpr (INJECT_EAGAIN) { + if (trigger_eagain()) { + DEBUGT("retiring {}B at {:#x}: trigger eagain", t, len, addr); + return crimson::ct_error::eagain::make(); + } + } return tm.dec_ref(t, extent).safe_then([addr, len, &t] (unsigned cnt) { assert(cnt == 0); TRACET("retired {}B at {:#x} ...", t, len, addr); @@ -117,6 +156,12 @@ class SeastoreNodeExtentManager final: public NodeExtentManager { getsuper_ertr::future get_super( Transaction& t, RootNodeTracker& tracker) override { TRACET("get root ...", t); + if constexpr (INJECT_EAGAIN) { + if (trigger_eagain()) { + DEBUGT("get root: trigger eagain", t); + return crimson::ct_error::eagain::make(); + } + } return tm.read_onode_root(t).safe_then([this, &t, &tracker](auto root_addr) { TRACET("got root {:#x}", t, root_addr); return Super::URef(new SeastoreSuper(t, tracker, root_addr, tm)); @@ -124,14 +169,32 @@ class SeastoreNodeExtentManager final: public NodeExtentManager { } std::ostream& print(std::ostream& os) const override { - return os << "SeastoreNodeExtentManager"; + os << "SeastoreNodeExtentManager"; + if constexpr (INJECT_EAGAIN) { + os << "(p_eagain=" << p_eagain << ")"; + } + return os; } private: static LOG_PREFIX(OTree::Seastore); - TransactionManager& tm; const laddr_t addr_min; + + // XXX: conditional members by INJECT_EAGAIN + bool trigger_eagain() { + if (generate_eagain) { + double dice = rd(); + assert(rd.min() == 0); + dice /= rd.max(); + return dice <= p_eagain; + } else { + return false; + } + } + bool generate_eagain = true; + std::random_device rd; + double p_eagain; }; } -- 2.39.5