]>
Commit | Line | Data |
---|---|---|
1e59de90 TL |
1 | #include "crimson/osd/object_context_loader.h" |
2 | #include "osd/osd_types_fmt.h" | |
3 | ||
4 | SET_SUBSYS(osd); | |
5 | ||
6 | namespace crimson::osd { | |
7 | ||
8 | using crimson::common::local_conf; | |
9 | ||
10 | template<RWState::State State> | |
11 | ObjectContextLoader::load_obc_iertr::future<> | |
12 | ObjectContextLoader::with_head_obc(ObjectContextRef obc, | |
13 | bool existed, | |
14 | with_obc_func_t&& func) | |
15 | { | |
16 | LOG_PREFIX(ObjectContextLoader::with_head_obc); | |
17 | DEBUGDPP("object {}", dpp, obc->get_oid()); | |
18 | assert(obc->is_head()); | |
19 | obc->append_to(obc_set_accessing); | |
20 | return obc->with_lock<State, IOInterruptCondition>( | |
21 | [existed=existed, obc=obc, func=std::move(func), this] { | |
22 | return get_or_load_obc<State>(obc, existed) | |
23 | .safe_then_interruptible( | |
24 | [func = std::move(func)](auto obc) { | |
25 | return std::move(func)(std::move(obc)); | |
26 | }); | |
27 | }).finally([FNAME, this, obc=std::move(obc)] { | |
28 | DEBUGDPP("released object {}", dpp, obc->get_oid()); | |
29 | obc->remove_from(obc_set_accessing); | |
30 | }); | |
31 | } | |
32 | ||
33 | template<RWState::State State> | |
34 | ObjectContextLoader::load_obc_iertr::future<> | |
35 | ObjectContextLoader::with_clone_obc(hobject_t oid, | |
36 | with_obc_func_t&& func) | |
37 | { | |
38 | LOG_PREFIX(ObjectContextLoader::with_clone_obc); | |
39 | assert(!oid.is_head()); | |
40 | return with_obc<RWState::RWREAD>( | |
41 | oid.get_head(), | |
42 | [FNAME, oid, func=std::move(func), this](auto head) mutable | |
43 | -> load_obc_iertr::future<> { | |
44 | if (!head->obs.exists) { | |
45 | ERRORDPP("head doesn't exist for object {}", dpp, head->obs.oi.soid); | |
46 | return load_obc_iertr::future<>{ | |
47 | crimson::ct_error::enoent::make() | |
48 | }; | |
49 | } | |
50 | return this->with_clone_obc_only<State>(std::move(head), | |
51 | oid, | |
52 | std::move(func)); | |
53 | }); | |
54 | } | |
55 | ||
56 | template<RWState::State State> | |
57 | ObjectContextLoader::load_obc_iertr::future<> | |
58 | ObjectContextLoader::with_clone_obc_only(ObjectContextRef head, | |
59 | hobject_t oid, | |
60 | with_obc_func_t&& func) | |
61 | { | |
62 | LOG_PREFIX(ObjectContextLoader::with_clone_obc_only); | |
63 | auto coid = resolve_oid(head->get_head_ss(), oid); | |
64 | if (!coid) { | |
65 | ERRORDPP("clone {} not found", dpp, oid); | |
66 | return load_obc_iertr::future<>{ | |
67 | crimson::ct_error::enoent::make() | |
68 | }; | |
69 | } | |
70 | auto [clone, existed] = obc_registry.get_cached_obc(*coid); | |
71 | return clone->template with_lock<State, IOInterruptCondition>( | |
72 | [existed=existed, clone=std::move(clone), | |
73 | func=std::move(func), head=std::move(head), this]() | |
74 | -> load_obc_iertr::future<> { | |
75 | auto loaded = get_or_load_obc<State>(clone, existed); | |
76 | return loaded.safe_then_interruptible( | |
77 | [func = std::move(func)](auto clone) { | |
78 | return std::move(func)(std::move(clone)); | |
79 | }); | |
80 | }); | |
81 | } | |
82 | ||
83 | template<RWState::State State> | |
84 | ObjectContextLoader::load_obc_iertr::future<> | |
85 | ObjectContextLoader::with_head_and_clone_obc( | |
86 | hobject_t oid, | |
87 | with_both_obc_func_t&& func) | |
88 | { | |
89 | LOG_PREFIX(ObjectContextLoader::with_head_and_clone_obc); | |
90 | assert(!oid.is_head()); | |
91 | return with_obc<RWState::RWREAD>( | |
92 | oid.get_head(), | |
93 | [FNAME, oid, func=std::move(func), this](auto head) mutable | |
94 | -> load_obc_iertr::future<> { | |
95 | if (!head->obs.exists) { | |
96 | ERRORDPP("head doesn't exist for object {}", dpp, head->obs.oi.soid); | |
97 | return load_obc_iertr::future<>{ | |
98 | crimson::ct_error::enoent::make() | |
99 | }; | |
100 | } | |
101 | auto coid = resolve_oid(head->get_head_ss(), oid); | |
102 | if (!coid) { | |
103 | ERRORDPP("clone {} not found", dpp, oid); | |
104 | return load_obc_iertr::future<>{ | |
105 | crimson::ct_error::enoent::make() | |
106 | }; | |
107 | } | |
108 | auto [clone, existed] = obc_registry.get_cached_obc(*coid); | |
109 | return clone->template with_lock<State, IOInterruptCondition>( | |
110 | [existed=existed, clone=std::move(clone), | |
111 | func=std::move(func), head=std::move(head), this]() | |
112 | -> load_obc_iertr::future<> { | |
113 | auto loaded = get_or_load_obc<State>(clone, existed); | |
114 | return loaded.safe_then_interruptible( | |
115 | [func = std::move(func), head=std::move(head)](auto clone) { | |
116 | return std::move(func)(std::move(head), std::move(clone)); | |
117 | }); | |
118 | }); | |
119 | }); | |
120 | } | |
121 | ||
122 | template<RWState::State State> | |
123 | ObjectContextLoader::load_obc_iertr::future<> | |
124 | ObjectContextLoader::with_obc(hobject_t oid, | |
125 | with_obc_func_t&& func) | |
126 | { | |
127 | if (oid.is_head()) { | |
128 | auto [obc, existed] = | |
129 | obc_registry.get_cached_obc(std::move(oid)); | |
130 | return with_head_obc<State>(std::move(obc), | |
131 | existed, | |
132 | std::move(func)); | |
133 | } else { | |
134 | return with_clone_obc<State>(oid, std::move(func)); | |
135 | } | |
136 | } | |
137 | ||
138 | ObjectContextLoader::load_obc_iertr::future<ObjectContextRef> | |
139 | ObjectContextLoader::load_obc(ObjectContextRef obc) | |
140 | { | |
141 | LOG_PREFIX(ObjectContextLoader::load_obc); | |
142 | return backend.load_metadata(obc->get_oid()) | |
143 | .safe_then_interruptible( | |
144 | [FNAME, this, obc=std::move(obc)](auto md) | |
145 | -> load_obc_ertr::future<ObjectContextRef> { | |
146 | const hobject_t& oid = md->os.oi.soid; | |
147 | DEBUGDPP("loaded obs {} for {}", dpp, md->os.oi, oid); | |
148 | if (oid.is_head()) { | |
149 | if (!md->ssc) { | |
150 | ERRORDPP("oid {} missing snapsetcontext", dpp, oid); | |
151 | return crimson::ct_error::object_corrupted::make(); | |
152 | } | |
153 | obc->set_head_state(std::move(md->os), | |
154 | std::move(md->ssc)); | |
155 | } else { | |
156 | obc->set_clone_state(std::move(md->os)); | |
157 | } | |
158 | DEBUGDPP("returning obc {} for {}", dpp, obc->obs.oi, obc->obs.oi.soid); | |
159 | return load_obc_ertr::make_ready_future<ObjectContextRef>(obc); | |
160 | }); | |
161 | } | |
162 | ||
163 | template<RWState::State State> | |
164 | ObjectContextLoader::load_obc_iertr::future<ObjectContextRef> | |
165 | ObjectContextLoader::get_or_load_obc(ObjectContextRef obc, | |
166 | bool existed) | |
167 | { | |
168 | LOG_PREFIX(ObjectContextLoader::get_or_load_obc); | |
169 | auto loaded = | |
170 | load_obc_iertr::make_ready_future<ObjectContextRef>(obc); | |
171 | if (existed) { | |
172 | DEBUGDPP("cache hit on {}", dpp, obc->get_oid()); | |
173 | } else { | |
174 | DEBUGDPP("cache miss on {}", dpp, obc->get_oid()); | |
175 | loaded = | |
176 | obc->template with_promoted_lock<State, IOInterruptCondition>( | |
177 | [obc, this] { | |
178 | return load_obc(obc); | |
179 | }); | |
180 | } | |
181 | return loaded; | |
182 | } | |
183 | ||
184 | ObjectContextLoader::load_obc_iertr::future<> | |
185 | ObjectContextLoader::reload_obc(ObjectContext& obc) const | |
186 | { | |
187 | LOG_PREFIX(ObjectContextLoader::reload_obc); | |
188 | assert(obc.is_head()); | |
189 | return backend.load_metadata(obc.get_oid()) | |
190 | .safe_then_interruptible<false>( | |
191 | [FNAME, this, &obc](auto md)-> load_obc_ertr::future<> { | |
192 | DEBUGDPP("reloaded obs {} for {}", dpp, md->os.oi, obc.get_oid()); | |
193 | if (!md->ssc) { | |
194 | ERRORDPP("oid {} missing snapsetcontext", dpp, obc.get_oid()); | |
195 | return crimson::ct_error::object_corrupted::make(); | |
196 | } | |
197 | obc.set_head_state(std::move(md->os), std::move(md->ssc)); | |
198 | return load_obc_ertr::now(); | |
199 | }); | |
200 | } | |
201 | ||
202 | void ObjectContextLoader::notify_on_change(bool is_primary) | |
203 | { | |
204 | LOG_PREFIX(ObjectContextLoader::notify_on_change); | |
205 | DEBUGDPP("is_primary: {}", dpp, is_primary); | |
206 | for (auto& obc : obc_set_accessing) { | |
207 | DEBUGDPP("interrupting obc: {}", dpp, obc.get_oid()); | |
208 | obc.interrupt(::crimson::common::actingset_changed(is_primary)); | |
209 | } | |
210 | } | |
211 | ||
212 | // explicitly instantiate the used instantiations | |
213 | template ObjectContextLoader::load_obc_iertr::future<> | |
214 | ObjectContextLoader::with_obc<RWState::RWNONE>(hobject_t, | |
215 | with_obc_func_t&&); | |
216 | ||
217 | template ObjectContextLoader::load_obc_iertr::future<> | |
218 | ObjectContextLoader::with_obc<RWState::RWREAD>(hobject_t, | |
219 | with_obc_func_t&&); | |
220 | ||
221 | template ObjectContextLoader::load_obc_iertr::future<> | |
222 | ObjectContextLoader::with_obc<RWState::RWWRITE>(hobject_t, | |
223 | with_obc_func_t&&); | |
224 | ||
225 | template ObjectContextLoader::load_obc_iertr::future<> | |
226 | ObjectContextLoader::with_obc<RWState::RWEXCL>(hobject_t, | |
227 | with_obc_func_t&&); | |
228 | ||
229 | template ObjectContextLoader::load_obc_iertr::future<> | |
230 | ObjectContextLoader::with_head_and_clone_obc<RWState::RWWRITE>( | |
231 | hobject_t, | |
232 | with_both_obc_func_t&&); | |
233 | } |