]> git.proxmox.com Git - ceph.git/blob - ceph/src/crimson/osd/object_context_loader.cc
0a4d74c0d70c7e51e9c4185975b4dd208313ced1
[ceph.git] / ceph / src / crimson / osd / object_context_loader.cc
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_clone_obc_direct(
86 hobject_t oid,
87 with_both_obc_func_t&& func)
88 {
89 LOG_PREFIX(ObjectContextLoader::with_clone_obc_direct);
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 #ifndef NDEBUG
102 auto &ss = head->get_head_ss();
103 auto cit = std::find(
104 std::begin(ss.clones), std::end(ss.clones), oid.snap);
105 assert(cit != std::end(ss.clones));
106 #endif
107 auto [clone, existed] = obc_registry.get_cached_obc(oid);
108 return clone->template with_lock<State, IOInterruptCondition>(
109 [existed=existed, clone=std::move(clone),
110 func=std::move(func), head=std::move(head), this]()
111 -> load_obc_iertr::future<> {
112 auto loaded = get_or_load_obc<State>(clone, existed);
113 return loaded.safe_then_interruptible(
114 [func = std::move(func), head=std::move(head)](auto clone) {
115 return std::move(func)(std::move(head), std::move(clone));
116 });
117 });
118 });
119 }
120
121 template<RWState::State State>
122 ObjectContextLoader::load_obc_iertr::future<>
123 ObjectContextLoader::with_obc(hobject_t oid,
124 with_obc_func_t&& func)
125 {
126 if (oid.is_head()) {
127 auto [obc, existed] =
128 obc_registry.get_cached_obc(std::move(oid));
129 return with_head_obc<State>(std::move(obc),
130 existed,
131 std::move(func));
132 } else {
133 return with_clone_obc<State>(oid, std::move(func));
134 }
135 }
136
137 ObjectContextLoader::load_obc_iertr::future<ObjectContextRef>
138 ObjectContextLoader::load_obc(ObjectContextRef obc)
139 {
140 LOG_PREFIX(ObjectContextLoader::load_obc);
141 return backend.load_metadata(obc->get_oid())
142 .safe_then_interruptible(
143 [FNAME, this, obc=std::move(obc)](auto md)
144 -> load_obc_ertr::future<ObjectContextRef> {
145 const hobject_t& oid = md->os.oi.soid;
146 DEBUGDPP("loaded obs {} for {}", dpp, md->os.oi, oid);
147 if (oid.is_head()) {
148 if (!md->ssc) {
149 ERRORDPP("oid {} missing snapsetcontext", dpp, oid);
150 return crimson::ct_error::object_corrupted::make();
151 }
152 obc->set_head_state(std::move(md->os),
153 std::move(md->ssc));
154 } else {
155 obc->set_clone_state(std::move(md->os));
156 }
157 DEBUGDPP("returning obc {} for {}", dpp, obc->obs.oi, obc->obs.oi.soid);
158 return load_obc_ertr::make_ready_future<ObjectContextRef>(obc);
159 });
160 }
161
162 template<RWState::State State>
163 ObjectContextLoader::load_obc_iertr::future<ObjectContextRef>
164 ObjectContextLoader::get_or_load_obc(ObjectContextRef obc,
165 bool existed)
166 {
167 LOG_PREFIX(ObjectContextLoader::get_or_load_obc);
168 auto loaded =
169 load_obc_iertr::make_ready_future<ObjectContextRef>(obc);
170 if (existed) {
171 DEBUGDPP("cache hit on {}", dpp, obc->get_oid());
172 } else {
173 DEBUGDPP("cache miss on {}", dpp, obc->get_oid());
174 loaded =
175 obc->template with_promoted_lock<State, IOInterruptCondition>(
176 [obc, this] {
177 return load_obc(obc);
178 });
179 }
180 return loaded;
181 }
182
183 ObjectContextLoader::load_obc_iertr::future<>
184 ObjectContextLoader::reload_obc(ObjectContext& obc) const
185 {
186 LOG_PREFIX(ObjectContextLoader::reload_obc);
187 assert(obc.is_head());
188 return backend.load_metadata(obc.get_oid())
189 .safe_then_interruptible<false>(
190 [FNAME, this, &obc](auto md)-> load_obc_ertr::future<> {
191 DEBUGDPP("reloaded obs {} for {}", dpp, md->os.oi, obc.get_oid());
192 if (!md->ssc) {
193 ERRORDPP("oid {} missing snapsetcontext", dpp, obc.get_oid());
194 return crimson::ct_error::object_corrupted::make();
195 }
196 obc.set_head_state(std::move(md->os), std::move(md->ssc));
197 return load_obc_ertr::now();
198 });
199 }
200
201 void ObjectContextLoader::notify_on_change(bool is_primary)
202 {
203 LOG_PREFIX(ObjectContextLoader::notify_on_change);
204 DEBUGDPP("is_primary: {}", dpp, is_primary);
205 for (auto& obc : obc_set_accessing) {
206 DEBUGDPP("interrupting obc: {}", dpp, obc.get_oid());
207 obc.interrupt(::crimson::common::actingset_changed(is_primary));
208 }
209 }
210
211 // explicitly instantiate the used instantiations
212 template ObjectContextLoader::load_obc_iertr::future<>
213 ObjectContextLoader::with_obc<RWState::RWNONE>(hobject_t,
214 with_obc_func_t&&);
215
216 template ObjectContextLoader::load_obc_iertr::future<>
217 ObjectContextLoader::with_obc<RWState::RWREAD>(hobject_t,
218 with_obc_func_t&&);
219
220 template ObjectContextLoader::load_obc_iertr::future<>
221 ObjectContextLoader::with_obc<RWState::RWWRITE>(hobject_t,
222 with_obc_func_t&&);
223
224 template ObjectContextLoader::load_obc_iertr::future<>
225 ObjectContextLoader::with_obc<RWState::RWEXCL>(hobject_t,
226 with_obc_func_t&&);
227
228 template ObjectContextLoader::load_obc_iertr::future<>
229 ObjectContextLoader::with_clone_obc_direct<RWState::RWWRITE>(
230 hobject_t,
231 with_both_obc_func_t&&);
232 }