]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #include "librbd/exclusive_lock/PostAcquireRequest.h" | |
5 | #include "cls/lock/cls_lock_client.h" | |
6 | #include "cls/lock/cls_lock_types.h" | |
7 | #include "common/dout.h" | |
8 | #include "common/errno.h" | |
9 | #include "common/WorkQueue.h" | |
10 | #include "include/stringify.h" | |
11 | #include "librbd/ExclusiveLock.h" | |
12 | #include "librbd/ImageCtx.h" | |
13 | #include "librbd/ImageState.h" | |
14 | #include "librbd/ImageWatcher.h" | |
15 | #include "librbd/Journal.h" | |
16 | #include "librbd/ObjectMap.h" | |
17 | #include "librbd/Utils.h" | |
18 | #include "librbd/image/RefreshRequest.h" | |
19 | #include "librbd/journal/Policy.h" | |
20 | ||
21 | #define dout_subsys ceph_subsys_rbd | |
22 | #undef dout_prefix | |
23 | #define dout_prefix *_dout << "librbd::exclusive_lock::PostAcquireRequest: " \ | |
24 | << this << " " << __func__ << ": " | |
25 | ||
26 | namespace librbd { | |
27 | namespace exclusive_lock { | |
28 | ||
29 | using util::create_async_context_callback; | |
30 | using util::create_context_callback; | |
31 | using util::create_rados_callback; | |
32 | ||
33 | template <typename I> | |
34 | PostAcquireRequest<I>* PostAcquireRequest<I>::create(I &image_ctx, | |
35 | Context *on_acquire, | |
36 | Context *on_finish) { | |
37 | return new PostAcquireRequest(image_ctx, on_acquire, on_finish); | |
38 | } | |
39 | ||
40 | template <typename I> | |
41 | PostAcquireRequest<I>::PostAcquireRequest(I &image_ctx, Context *on_acquire, | |
42 | Context *on_finish) | |
43 | : m_image_ctx(image_ctx), | |
44 | m_on_acquire(on_acquire), | |
45 | m_on_finish(create_async_context_callback(image_ctx, on_finish)), | |
46 | m_object_map(nullptr), m_journal(nullptr), m_error_result(0) { | |
47 | } | |
48 | ||
49 | template <typename I> | |
50 | PostAcquireRequest<I>::~PostAcquireRequest() { | |
51 | if (!m_prepare_lock_completed) { | |
52 | m_image_ctx.state->handle_prepare_lock_complete(); | |
53 | } | |
54 | delete m_on_acquire; | |
55 | } | |
56 | ||
57 | template <typename I> | |
58 | void PostAcquireRequest<I>::send() { | |
59 | send_refresh(); | |
60 | } | |
61 | ||
62 | template <typename I> | |
63 | void PostAcquireRequest<I>::send_refresh() { | |
64 | if (!m_image_ctx.state->is_refresh_required()) { | |
65 | send_open_object_map(); | |
66 | return; | |
67 | } | |
68 | ||
69 | CephContext *cct = m_image_ctx.cct; | |
70 | ldout(cct, 10) << dendl; | |
71 | ||
72 | using klass = PostAcquireRequest<I>; | |
73 | Context *ctx = create_async_context_callback( | |
74 | m_image_ctx, create_context_callback<klass, &klass::handle_refresh>(this)); | |
75 | ||
76 | // ImageState is blocked waiting for lock to complete -- safe to directly | |
77 | // refresh | |
78 | image::RefreshRequest<I> *req = image::RefreshRequest<I>::create( | |
79 | m_image_ctx, true, false, ctx); | |
80 | req->send(); | |
81 | } | |
82 | ||
83 | template <typename I> | |
84 | void PostAcquireRequest<I>::handle_refresh(int r) { | |
85 | CephContext *cct = m_image_ctx.cct; | |
86 | ldout(cct, 10) << "r=" << r << dendl; | |
87 | ||
88 | if (r == -ERESTART) { | |
89 | // next issued IO or op will (re)-refresh the image and shut down lock | |
90 | ldout(cct, 5) << "exclusive lock dynamically disabled" << dendl; | |
91 | r = 0; | |
92 | } else if (r < 0) { | |
93 | lderr(cct) << "failed to refresh image: " << cpp_strerror(r) << dendl; | |
94 | save_result(r); | |
95 | revert(); | |
96 | finish(); | |
97 | return; | |
98 | } | |
99 | ||
100 | send_open_object_map(); | |
101 | } | |
102 | ||
103 | template <typename I> | |
104 | void PostAcquireRequest<I>::send_open_journal() { | |
105 | // alert caller that we now own the exclusive lock | |
106 | m_on_acquire->complete(0); | |
107 | m_on_acquire = nullptr; | |
108 | ||
109 | bool journal_enabled; | |
110 | { | |
9f95a23c | 111 | std::shared_lock image_locker{m_image_ctx.image_lock}; |
7c673cae | 112 | journal_enabled = (m_image_ctx.test_features(RBD_FEATURE_JOURNALING, |
9f95a23c | 113 | m_image_ctx.image_lock) && |
7c673cae FG |
114 | !m_image_ctx.get_journal_policy()->journal_disabled()); |
115 | } | |
116 | if (!journal_enabled) { | |
117 | apply(); | |
118 | finish(); | |
119 | return; | |
120 | } | |
121 | ||
122 | CephContext *cct = m_image_ctx.cct; | |
123 | ldout(cct, 10) << dendl; | |
124 | ||
125 | using klass = PostAcquireRequest<I>; | |
126 | Context *ctx = create_context_callback<klass, &klass::handle_open_journal>( | |
127 | this); | |
128 | m_journal = m_image_ctx.create_journal(); | |
129 | ||
130 | // journal playback requires object map (if enabled) and itself | |
131 | apply(); | |
132 | ||
133 | m_journal->open(ctx); | |
134 | } | |
135 | ||
136 | template <typename I> | |
137 | void PostAcquireRequest<I>::handle_open_journal(int r) { | |
138 | CephContext *cct = m_image_ctx.cct; | |
139 | ldout(cct, 10) << "r=" << r << dendl; | |
140 | ||
141 | save_result(r); | |
142 | if (r < 0) { | |
143 | lderr(cct) << "failed to open journal: " << cpp_strerror(r) << dendl; | |
144 | send_close_journal(); | |
145 | return; | |
146 | } | |
147 | ||
148 | send_allocate_journal_tag(); | |
149 | } | |
150 | ||
151 | template <typename I> | |
152 | void PostAcquireRequest<I>::send_allocate_journal_tag() { | |
153 | CephContext *cct = m_image_ctx.cct; | |
154 | ldout(cct, 10) << dendl; | |
155 | ||
9f95a23c | 156 | std::shared_lock image_locker{m_image_ctx.image_lock}; |
7c673cae FG |
157 | using klass = PostAcquireRequest<I>; |
158 | Context *ctx = create_context_callback< | |
9f95a23c | 159 | klass, &klass::handle_allocate_journal_tag>(this, m_journal); |
7c673cae FG |
160 | m_image_ctx.get_journal_policy()->allocate_tag_on_lock(ctx); |
161 | } | |
162 | ||
163 | template <typename I> | |
164 | void PostAcquireRequest<I>::handle_allocate_journal_tag(int r) { | |
165 | CephContext *cct = m_image_ctx.cct; | |
166 | ldout(cct, 10) << "r=" << r << dendl; | |
167 | ||
168 | save_result(r); | |
169 | if (r < 0) { | |
170 | lderr(cct) << "failed to allocate journal tag: " << cpp_strerror(r) | |
171 | << dendl; | |
172 | send_close_journal(); | |
173 | return; | |
174 | } | |
175 | ||
176 | finish(); | |
177 | } | |
178 | ||
179 | template <typename I> | |
180 | void PostAcquireRequest<I>::send_close_journal() { | |
181 | CephContext *cct = m_image_ctx.cct; | |
182 | ldout(cct, 10) << dendl; | |
183 | ||
184 | using klass = PostAcquireRequest<I>; | |
185 | Context *ctx = create_context_callback<klass, &klass::handle_close_journal>( | |
186 | this); | |
187 | m_journal->close(ctx); | |
188 | } | |
189 | ||
190 | template <typename I> | |
191 | void PostAcquireRequest<I>::handle_close_journal(int r) { | |
192 | CephContext *cct = m_image_ctx.cct; | |
193 | ldout(cct, 10) << "r=" << r << dendl; | |
194 | ||
195 | save_result(r); | |
196 | if (r < 0) { | |
197 | lderr(cct) << "failed to close journal: " << cpp_strerror(r) << dendl; | |
198 | } | |
199 | ||
200 | send_close_object_map(); | |
201 | } | |
202 | ||
203 | template <typename I> | |
204 | void PostAcquireRequest<I>::send_open_object_map() { | |
205 | if (!m_image_ctx.test_features(RBD_FEATURE_OBJECT_MAP)) { | |
206 | send_open_journal(); | |
207 | return; | |
208 | } | |
209 | ||
210 | CephContext *cct = m_image_ctx.cct; | |
211 | ldout(cct, 10) << dendl; | |
212 | ||
213 | using klass = PostAcquireRequest<I>; | |
214 | Context *ctx = create_context_callback<klass, &klass::handle_open_object_map>( | |
215 | this); | |
216 | ||
217 | m_object_map = m_image_ctx.create_object_map(CEPH_NOSNAP); | |
218 | m_object_map->open(ctx); | |
219 | } | |
220 | ||
221 | template <typename I> | |
222 | void PostAcquireRequest<I>::handle_open_object_map(int r) { | |
223 | CephContext *cct = m_image_ctx.cct; | |
224 | ldout(cct, 10) << "r=" << r << dendl; | |
225 | ||
226 | if (r < 0) { | |
227 | lderr(cct) << "failed to open object map: " << cpp_strerror(r) << dendl; | |
9f95a23c | 228 | m_object_map->put(); |
7c673cae | 229 | m_object_map = nullptr; |
11fdf7f2 TL |
230 | |
231 | if (r != -EFBIG) { | |
232 | save_result(r); | |
233 | revert(); | |
234 | finish(); | |
235 | return; | |
236 | } | |
7c673cae FG |
237 | } |
238 | ||
239 | send_open_journal(); | |
240 | } | |
241 | ||
242 | template <typename I> | |
243 | void PostAcquireRequest<I>::send_close_object_map() { | |
244 | if (m_object_map == nullptr) { | |
245 | revert(); | |
246 | finish(); | |
247 | return; | |
248 | } | |
249 | ||
250 | CephContext *cct = m_image_ctx.cct; | |
251 | ldout(cct, 10) << dendl; | |
252 | ||
253 | using klass = PostAcquireRequest<I>; | |
254 | Context *ctx = create_context_callback< | |
255 | klass, &klass::handle_close_object_map>(this); | |
256 | m_object_map->close(ctx); | |
257 | } | |
258 | ||
259 | template <typename I> | |
260 | void PostAcquireRequest<I>::handle_close_object_map(int r) { | |
261 | CephContext *cct = m_image_ctx.cct; | |
262 | ldout(cct, 10) << "r=" << r << dendl; | |
263 | ||
11fdf7f2 TL |
264 | if (r < 0) { |
265 | lderr(cct) << "failed to close object map: " << cpp_strerror(r) << dendl; | |
266 | } | |
267 | ||
7c673cae FG |
268 | revert(); |
269 | finish(); | |
270 | } | |
271 | ||
272 | template <typename I> | |
273 | void PostAcquireRequest<I>::apply() { | |
274 | { | |
9f95a23c | 275 | std::unique_lock image_locker{m_image_ctx.image_lock}; |
11fdf7f2 | 276 | ceph_assert(m_image_ctx.object_map == nullptr); |
7c673cae FG |
277 | m_image_ctx.object_map = m_object_map; |
278 | ||
11fdf7f2 | 279 | ceph_assert(m_image_ctx.journal == nullptr); |
7c673cae FG |
280 | m_image_ctx.journal = m_journal; |
281 | } | |
282 | ||
283 | m_prepare_lock_completed = true; | |
284 | m_image_ctx.state->handle_prepare_lock_complete(); | |
285 | } | |
286 | ||
287 | template <typename I> | |
288 | void PostAcquireRequest<I>::revert() { | |
9f95a23c | 289 | std::unique_lock image_locker{m_image_ctx.image_lock}; |
7c673cae FG |
290 | m_image_ctx.object_map = nullptr; |
291 | m_image_ctx.journal = nullptr; | |
292 | ||
9f95a23c TL |
293 | if (m_object_map) { |
294 | m_object_map->put(); | |
295 | } | |
296 | if (m_journal) { | |
297 | m_journal->put(); | |
298 | } | |
7c673cae | 299 | |
11fdf7f2 | 300 | ceph_assert(m_error_result < 0); |
7c673cae FG |
301 | } |
302 | ||
303 | template <typename I> | |
304 | void PostAcquireRequest<I>::finish() { | |
305 | m_on_finish->complete(m_error_result); | |
306 | delete this; | |
307 | } | |
308 | ||
309 | } // namespace exclusive_lock | |
310 | } // namespace librbd | |
311 | ||
312 | template class librbd::exclusive_lock::PostAcquireRequest<librbd::ImageCtx>; |