]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #pragma once | |
5 | ||
20effc67 TL |
6 | #include <random> |
7 | ||
8 | #include "crimson/os/seastore/logging.h" | |
9 | ||
f67539c2 TL |
10 | #include "crimson/os/seastore/onode_manager/staged-fltree/node_extent_manager.h" |
11 | #include "crimson/os/seastore/onode_manager/staged-fltree/node_delta_recorder.h" | |
12 | ||
13 | /** | |
14 | * seastore.h | |
15 | * | |
16 | * Seastore backend implementations. | |
17 | */ | |
18 | ||
19 | namespace crimson::os::seastore::onode { | |
20 | ||
21 | class SeastoreSuper final: public Super { | |
22 | public: | |
23 | SeastoreSuper(Transaction& t, RootNodeTracker& tracker, | |
24 | laddr_t root_addr, TransactionManager& tm) | |
25 | : Super(t, tracker), root_addr{root_addr}, tm{tm} {} | |
26 | ~SeastoreSuper() override = default; | |
27 | protected: | |
28 | laddr_t get_root_laddr() const override { | |
29 | return root_addr; | |
30 | } | |
20effc67 TL |
31 | void write_root_laddr(context_t c, laddr_t addr) override { |
32 | LOG_PREFIX(OTree::Seastore); | |
33 | SUBDEBUGT(seastore_onode, "update root {:#x} ...", c.t, addr); | |
34 | root_addr = addr; | |
35 | tm.write_onode_root(c.t, addr); | |
f67539c2 | 36 | } |
20effc67 | 37 | private: |
f67539c2 | 38 | laddr_t root_addr; |
20effc67 | 39 | TransactionManager &tm; |
f67539c2 TL |
40 | }; |
41 | ||
42 | class SeastoreNodeExtent final: public NodeExtent { | |
43 | public: | |
44 | SeastoreNodeExtent(ceph::bufferptr &&ptr) | |
45 | : NodeExtent(std::move(ptr)) {} | |
46 | SeastoreNodeExtent(const SeastoreNodeExtent& other) | |
47 | : NodeExtent(other) {} | |
48 | ~SeastoreNodeExtent() override = default; | |
20effc67 TL |
49 | |
50 | constexpr static extent_types_t TYPE = extent_types_t::ONODE_BLOCK_STAGED; | |
51 | extent_types_t get_type() const override { | |
52 | return TYPE; | |
53 | } | |
54 | ||
f67539c2 TL |
55 | protected: |
56 | NodeExtentRef mutate(context_t, DeltaRecorderURef&&) override; | |
57 | ||
58 | DeltaRecorder* get_recorder() const override { | |
59 | return recorder.get(); | |
60 | } | |
61 | ||
62 | CachedExtentRef duplicate_for_write() override { | |
63 | return CachedExtentRef(new SeastoreNodeExtent(*this)); | |
64 | } | |
f67539c2 TL |
65 | ceph::bufferlist get_delta() override { |
66 | assert(recorder); | |
67 | return recorder->get_delta(); | |
68 | } | |
69 | void apply_delta(const ceph::bufferlist&) override; | |
20effc67 | 70 | |
f67539c2 TL |
71 | private: |
72 | DeltaRecorderURef recorder; | |
73 | }; | |
74 | ||
20effc67 TL |
75 | class TransactionManagerHandle : public NodeExtentManager { |
76 | public: | |
77 | TransactionManagerHandle(TransactionManager &tm) : tm{tm} {} | |
78 | TransactionManager &tm; | |
79 | }; | |
80 | ||
81 | template <bool INJECT_EAGAIN=false> | |
82 | class SeastoreNodeExtentManager final: public TransactionManagerHandle { | |
f67539c2 | 83 | public: |
20effc67 TL |
84 | SeastoreNodeExtentManager( |
85 | TransactionManager &tm, laddr_t min, double p_eagain) | |
86 | : TransactionManagerHandle(tm), addr_min{min}, p_eagain{p_eagain} { | |
87 | if constexpr (INJECT_EAGAIN) { | |
88 | assert(p_eagain > 0.0 && p_eagain < 1.0); | |
89 | } else { | |
90 | assert(p_eagain == 0.0); | |
91 | } | |
92 | } | |
93 | ||
f67539c2 | 94 | ~SeastoreNodeExtentManager() override = default; |
20effc67 TL |
95 | |
96 | void set_generate_eagain(bool enable) { | |
97 | generate_eagain = enable; | |
98 | } | |
99 | ||
f67539c2 TL |
100 | protected: |
101 | bool is_read_isolated() const override { return true; } | |
102 | ||
20effc67 TL |
103 | read_iertr::future<NodeExtentRef> read_extent( |
104 | Transaction& t, laddr_t addr) override { | |
105 | SUBTRACET(seastore_onode, "reading at {:#x} ...", t, addr); | |
106 | if constexpr (INJECT_EAGAIN) { | |
107 | if (trigger_eagain()) { | |
108 | SUBDEBUGT(seastore_onode, "reading at {:#x}: trigger eagain", t, addr); | |
109 | t.test_set_conflict(); | |
110 | return read_iertr::make_ready_future<NodeExtentRef>(); | |
111 | } | |
112 | } | |
113 | return tm.read_extent<SeastoreNodeExtent>(t, addr | |
114 | ).si_then([addr, &t](auto&& e) -> read_iertr::future<NodeExtentRef> { | |
115 | SUBTRACET(seastore_onode, | |
116 | "read {}B at {:#x} -- {}", | |
117 | t, e->get_length(), e->get_laddr(), *e); | |
f67539c2 | 118 | assert(e->get_laddr() == addr); |
f67539c2 | 119 | std::ignore = addr; |
20effc67 | 120 | return read_iertr::make_ready_future<NodeExtentRef>(e); |
f67539c2 TL |
121 | }); |
122 | } | |
123 | ||
20effc67 TL |
124 | alloc_iertr::future<NodeExtentRef> alloc_extent( |
125 | Transaction& t, laddr_t hint, extent_len_t len) override { | |
126 | SUBTRACET(seastore_onode, "allocating {}B with hint {:#x} ...", t, len, hint); | |
127 | if constexpr (INJECT_EAGAIN) { | |
128 | if (trigger_eagain()) { | |
129 | SUBDEBUGT(seastore_onode, "allocating {}B: trigger eagain", t, len); | |
130 | t.test_set_conflict(); | |
131 | return alloc_iertr::make_ready_future<NodeExtentRef>(); | |
132 | } | |
133 | } | |
134 | return tm.alloc_extent<SeastoreNodeExtent>(t, hint, len | |
135 | ).si_then([len, &t](auto extent) { | |
136 | SUBDEBUGT(seastore_onode, | |
137 | "allocated {}B at {:#x} -- {}", | |
138 | t, extent->get_length(), extent->get_laddr(), *extent); | |
139 | if (!extent->is_initial_pending()) { | |
140 | SUBERRORT(seastore_onode, | |
141 | "allocated {}B but got invalid extent: {}", | |
142 | t, len, *extent); | |
143 | ceph_abort("fatal error"); | |
144 | } | |
f67539c2 TL |
145 | assert(extent->get_length() == len); |
146 | std::ignore = len; | |
147 | return NodeExtentRef(extent); | |
148 | }); | |
149 | } | |
150 | ||
20effc67 TL |
151 | retire_iertr::future<> retire_extent( |
152 | Transaction& t, NodeExtentRef _extent) override { | |
153 | LogicalCachedExtentRef extent = _extent; | |
154 | auto addr = extent->get_laddr(); | |
155 | auto len = extent->get_length(); | |
156 | SUBDEBUGT(seastore_onode, | |
157 | "retiring {}B at {:#x} -- {} ...", | |
158 | t, len, addr, *extent); | |
159 | if constexpr (INJECT_EAGAIN) { | |
160 | if (trigger_eagain()) { | |
161 | SUBDEBUGT(seastore_onode, | |
162 | "retiring {}B at {:#x} -- {} : trigger eagain", | |
163 | t, len, addr, *extent); | |
164 | t.test_set_conflict(); | |
165 | return retire_iertr::now(); | |
166 | } | |
167 | } | |
168 | return tm.dec_ref(t, extent).si_then([addr, len, &t] (unsigned cnt) { | |
169 | assert(cnt == 0); | |
170 | SUBTRACET(seastore_onode, "retired {}B at {:#x} ...", t, len, addr); | |
171 | }); | |
172 | } | |
173 | ||
174 | getsuper_iertr::future<Super::URef> get_super( | |
f67539c2 | 175 | Transaction& t, RootNodeTracker& tracker) override { |
20effc67 TL |
176 | SUBTRACET(seastore_onode, "get root ...", t); |
177 | if constexpr (INJECT_EAGAIN) { | |
178 | if (trigger_eagain()) { | |
179 | SUBDEBUGT(seastore_onode, "get root: trigger eagain", t); | |
180 | t.test_set_conflict(); | |
181 | return getsuper_iertr::make_ready_future<Super::URef>(); | |
182 | } | |
183 | } | |
184 | return tm.read_onode_root(t).si_then([this, &t, &tracker](auto root_addr) { | |
185 | SUBTRACET(seastore_onode, "got root {:#x}", t, root_addr); | |
f67539c2 TL |
186 | return Super::URef(new SeastoreSuper(t, tracker, root_addr, tm)); |
187 | }); | |
188 | } | |
189 | ||
190 | std::ostream& print(std::ostream& os) const override { | |
20effc67 TL |
191 | os << "SeastoreNodeExtentManager"; |
192 | if constexpr (INJECT_EAGAIN) { | |
193 | os << "(p_eagain=" << p_eagain << ")"; | |
194 | } | |
195 | return os; | |
f67539c2 TL |
196 | } |
197 | ||
198 | private: | |
20effc67 TL |
199 | static LOG_PREFIX(OTree::Seastore); |
200 | ||
f67539c2 | 201 | const laddr_t addr_min; |
20effc67 TL |
202 | |
203 | // XXX: conditional members by INJECT_EAGAIN | |
204 | bool trigger_eagain() { | |
205 | if (generate_eagain) { | |
206 | double dice = rd(); | |
207 | assert(rd.min() == 0); | |
208 | dice /= rd.max(); | |
209 | return dice <= p_eagain; | |
210 | } else { | |
211 | return false; | |
212 | } | |
213 | } | |
214 | bool generate_eagain = true; | |
215 | std::random_device rd; | |
216 | double p_eagain; | |
f67539c2 TL |
217 | }; |
218 | ||
219 | } |