]>
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/image/CloseRequest.h" | |
5 | #include "common/dout.h" | |
6 | #include "common/errno.h" | |
f6b5b4d7 | 7 | #include "librbd/ConfigWatcher.h" |
7c673cae FG |
8 | #include "librbd/ExclusiveLock.h" |
9 | #include "librbd/ImageCtx.h" | |
10 | #include "librbd/ImageState.h" | |
11 | #include "librbd/ImageWatcher.h" | |
12 | #include "librbd/ObjectMap.h" | |
13 | #include "librbd/Utils.h" | |
f67539c2 | 14 | #include "librbd/asio/ContextWQ.h" |
11fdf7f2 | 15 | #include "librbd/io/AioCompletion.h" |
f67539c2 | 16 | #include "librbd/io/ImageDispatcher.h" |
11fdf7f2 | 17 | #include "librbd/io/ImageDispatchSpec.h" |
f67539c2 | 18 | #include "librbd/io/ObjectDispatcherInterface.h" |
7c673cae FG |
19 | |
20 | #define dout_subsys ceph_subsys_rbd | |
21 | #undef dout_prefix | |
22 | #define dout_prefix *_dout << "librbd::image::CloseRequest: " | |
23 | ||
24 | namespace librbd { | |
25 | namespace image { | |
26 | ||
27 | using util::create_async_context_callback; | |
28 | using util::create_context_callback; | |
29 | ||
30 | template <typename I> | |
31 | CloseRequest<I>::CloseRequest(I *image_ctx, Context *on_finish) | |
32 | : m_image_ctx(image_ctx), m_on_finish(on_finish), m_error_result(0), | |
33 | m_exclusive_lock(nullptr) { | |
11fdf7f2 | 34 | ceph_assert(image_ctx != nullptr); |
7c673cae FG |
35 | } |
36 | ||
37 | template <typename I> | |
38 | void CloseRequest<I>::send() { | |
f6b5b4d7 TL |
39 | if (m_image_ctx->config_watcher != nullptr) { |
40 | m_image_ctx->config_watcher->shut_down(); | |
41 | ||
42 | delete m_image_ctx->config_watcher; | |
43 | m_image_ctx->config_watcher = nullptr; | |
44 | } | |
45 | ||
31f18b77 | 46 | send_block_image_watcher(); |
7c673cae FG |
47 | } |
48 | ||
49 | template <typename I> | |
31f18b77 FG |
50 | void CloseRequest<I>::send_block_image_watcher() { |
51 | if (m_image_ctx->image_watcher == nullptr) { | |
52 | send_shut_down_update_watchers(); | |
53 | return; | |
54 | } | |
55 | ||
7c673cae FG |
56 | CephContext *cct = m_image_ctx->cct; |
57 | ldout(cct, 10) << this << " " << __func__ << dendl; | |
58 | ||
31f18b77 FG |
59 | // prevent incoming requests from our peers |
60 | m_image_ctx->image_watcher->block_notifies(create_context_callback< | |
61 | CloseRequest<I>, &CloseRequest<I>::handle_block_image_watcher>(this)); | |
7c673cae FG |
62 | } |
63 | ||
64 | template <typename I> | |
31f18b77 | 65 | void CloseRequest<I>::handle_block_image_watcher(int r) { |
7c673cae FG |
66 | CephContext *cct = m_image_ctx->cct; |
67 | ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl; | |
68 | ||
31f18b77 | 69 | send_shut_down_update_watchers(); |
7c673cae FG |
70 | } |
71 | ||
72 | template <typename I> | |
31f18b77 | 73 | void CloseRequest<I>::send_shut_down_update_watchers() { |
7c673cae FG |
74 | CephContext *cct = m_image_ctx->cct; |
75 | ldout(cct, 10) << this << " " << __func__ << dendl; | |
76 | ||
31f18b77 FG |
77 | m_image_ctx->state->shut_down_update_watchers(create_async_context_callback( |
78 | *m_image_ctx, create_context_callback< | |
79 | CloseRequest<I>, &CloseRequest<I>::handle_shut_down_update_watchers>(this))); | |
7c673cae FG |
80 | } |
81 | ||
82 | template <typename I> | |
31f18b77 | 83 | void CloseRequest<I>::handle_shut_down_update_watchers(int r) { |
7c673cae FG |
84 | CephContext *cct = m_image_ctx->cct; |
85 | ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl; | |
86 | ||
87 | save_result(r); | |
88 | if (r < 0) { | |
31f18b77 | 89 | lderr(cct) << "failed to shut down update watchers: " << cpp_strerror(r) |
7c673cae FG |
90 | << dendl; |
91 | } | |
92 | ||
f67539c2 | 93 | send_flush(); |
7c673cae FG |
94 | } |
95 | ||
96 | template <typename I> | |
f67539c2 | 97 | void CloseRequest<I>::send_flush() { |
7c673cae FG |
98 | CephContext *cct = m_image_ctx->cct; |
99 | ldout(cct, 10) << this << " " << __func__ << dendl; | |
100 | ||
9f95a23c | 101 | std::shared_lock owner_locker{m_image_ctx->owner_lock}; |
f67539c2 TL |
102 | auto ctx = create_context_callback< |
103 | CloseRequest<I>, &CloseRequest<I>::handle_flush>(this); | |
104 | auto aio_comp = io::AioCompletion::create_and_start(ctx, m_image_ctx, | |
105 | io::AIO_TYPE_FLUSH); | |
106 | auto req = io::ImageDispatchSpec::create_flush( | |
107 | *m_image_ctx, io::IMAGE_DISPATCH_LAYER_API_START, aio_comp, | |
108 | io::FLUSH_SOURCE_SHUTDOWN, {}); | |
109 | req->send(); | |
7c673cae FG |
110 | } |
111 | ||
112 | template <typename I> | |
f67539c2 | 113 | void CloseRequest<I>::handle_flush(int r) { |
7c673cae FG |
114 | CephContext *cct = m_image_ctx->cct; |
115 | ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl; | |
116 | ||
f67539c2 TL |
117 | if (r < 0) { |
118 | lderr(cct) << "failed to flush IO: " << cpp_strerror(r) << dendl; | |
119 | } | |
120 | ||
7c673cae FG |
121 | send_shut_down_exclusive_lock(); |
122 | } | |
123 | ||
124 | template <typename I> | |
125 | void CloseRequest<I>::send_shut_down_exclusive_lock() { | |
126 | { | |
9f95a23c | 127 | std::unique_lock owner_locker{m_image_ctx->owner_lock}; |
7c673cae FG |
128 | m_exclusive_lock = m_image_ctx->exclusive_lock; |
129 | ||
130 | // if reading a snapshot -- possible object map is open | |
9f95a23c TL |
131 | std::unique_lock image_locker{m_image_ctx->image_lock}; |
132 | if (m_exclusive_lock == nullptr && m_image_ctx->object_map) { | |
133 | m_image_ctx->object_map->put(); | |
7c673cae FG |
134 | m_image_ctx->object_map = nullptr; |
135 | } | |
136 | } | |
137 | ||
138 | if (m_exclusive_lock == nullptr) { | |
f67539c2 | 139 | send_unregister_image_watcher(); |
7c673cae FG |
140 | return; |
141 | } | |
142 | ||
143 | CephContext *cct = m_image_ctx->cct; | |
144 | ldout(cct, 10) << this << " " << __func__ << dendl; | |
145 | ||
146 | // in-flight IO will be flushed and in-flight requests will be canceled | |
147 | // before releasing lock | |
148 | m_exclusive_lock->shut_down(create_context_callback< | |
149 | CloseRequest<I>, &CloseRequest<I>::handle_shut_down_exclusive_lock>(this)); | |
150 | } | |
151 | ||
152 | template <typename I> | |
153 | void CloseRequest<I>::handle_shut_down_exclusive_lock(int r) { | |
154 | CephContext *cct = m_image_ctx->cct; | |
155 | ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl; | |
156 | ||
157 | { | |
9f95a23c | 158 | std::shared_lock owner_locker{m_image_ctx->owner_lock}; |
11fdf7f2 | 159 | ceph_assert(m_image_ctx->exclusive_lock == nullptr); |
7c673cae FG |
160 | |
161 | // object map and journal closed during exclusive lock shutdown | |
9f95a23c | 162 | std::shared_lock image_locker{m_image_ctx->image_lock}; |
11fdf7f2 TL |
163 | ceph_assert(m_image_ctx->journal == nullptr); |
164 | ceph_assert(m_image_ctx->object_map == nullptr); | |
7c673cae FG |
165 | } |
166 | ||
9f95a23c | 167 | m_exclusive_lock->put(); |
7c673cae FG |
168 | m_exclusive_lock = nullptr; |
169 | ||
170 | save_result(r); | |
171 | if (r < 0) { | |
172 | lderr(cct) << "failed to shut down exclusive lock: " << cpp_strerror(r) | |
173 | << dendl; | |
174 | } | |
31f18b77 FG |
175 | |
176 | send_unregister_image_watcher(); | |
7c673cae FG |
177 | } |
178 | ||
31f18b77 FG |
179 | template <typename I> |
180 | void CloseRequest<I>::send_unregister_image_watcher() { | |
181 | if (m_image_ctx->image_watcher == nullptr) { | |
182 | send_flush_readahead(); | |
183 | return; | |
184 | } | |
185 | ||
186 | CephContext *cct = m_image_ctx->cct; | |
187 | ldout(cct, 10) << this << " " << __func__ << dendl; | |
188 | ||
189 | m_image_ctx->image_watcher->unregister_watch(create_context_callback< | |
190 | CloseRequest<I>, &CloseRequest<I>::handle_unregister_image_watcher>(this)); | |
191 | } | |
192 | ||
193 | template <typename I> | |
194 | void CloseRequest<I>::handle_unregister_image_watcher(int r) { | |
195 | CephContext *cct = m_image_ctx->cct; | |
196 | ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl; | |
197 | ||
198 | save_result(r); | |
199 | if (r < 0) { | |
200 | lderr(cct) << "failed to unregister image watcher: " << cpp_strerror(r) | |
201 | << dendl; | |
202 | } | |
203 | ||
7c673cae FG |
204 | send_flush_readahead(); |
205 | } | |
206 | ||
207 | template <typename I> | |
208 | void CloseRequest<I>::send_flush_readahead() { | |
209 | CephContext *cct = m_image_ctx->cct; | |
210 | ldout(cct, 10) << this << " " << __func__ << dendl; | |
211 | ||
212 | m_image_ctx->readahead.wait_for_pending(create_async_context_callback( | |
213 | *m_image_ctx, create_context_callback< | |
214 | CloseRequest<I>, &CloseRequest<I>::handle_flush_readahead>(this))); | |
215 | } | |
216 | ||
217 | template <typename I> | |
218 | void CloseRequest<I>::handle_flush_readahead(int r) { | |
219 | CephContext *cct = m_image_ctx->cct; | |
220 | ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl; | |
221 | ||
f67539c2 TL |
222 | send_shut_down_image_dispatcher(); |
223 | } | |
224 | ||
225 | template <typename I> | |
226 | void CloseRequest<I>::send_shut_down_image_dispatcher() { | |
227 | CephContext *cct = m_image_ctx->cct; | |
228 | ldout(cct, 10) << this << " " << __func__ << dendl; | |
229 | ||
230 | m_image_ctx->io_image_dispatcher->shut_down(create_context_callback< | |
231 | CloseRequest<I>, | |
232 | &CloseRequest<I>::handle_shut_down_image_dispatcher>(this)); | |
233 | } | |
234 | ||
235 | template <typename I> | |
236 | void CloseRequest<I>::handle_shut_down_image_dispatcher(int r) { | |
237 | CephContext *cct = m_image_ctx->cct; | |
238 | ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl; | |
239 | ||
240 | save_result(r); | |
241 | if (r < 0) { | |
242 | lderr(cct) << "failed to shut down image dispatcher: " | |
243 | << cpp_strerror(r) << dendl; | |
244 | } | |
245 | ||
11fdf7f2 | 246 | send_shut_down_object_dispatcher(); |
7c673cae FG |
247 | } |
248 | ||
249 | template <typename I> | |
11fdf7f2 | 250 | void CloseRequest<I>::send_shut_down_object_dispatcher() { |
7c673cae FG |
251 | CephContext *cct = m_image_ctx->cct; |
252 | ldout(cct, 10) << this << " " << __func__ << dendl; | |
253 | ||
11fdf7f2 TL |
254 | m_image_ctx->io_object_dispatcher->shut_down(create_context_callback< |
255 | CloseRequest<I>, | |
256 | &CloseRequest<I>::handle_shut_down_object_dispatcher>(this)); | |
7c673cae FG |
257 | } |
258 | ||
259 | template <typename I> | |
11fdf7f2 | 260 | void CloseRequest<I>::handle_shut_down_object_dispatcher(int r) { |
7c673cae FG |
261 | CephContext *cct = m_image_ctx->cct; |
262 | ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl; | |
263 | ||
264 | save_result(r); | |
265 | if (r < 0) { | |
11fdf7f2 TL |
266 | lderr(cct) << "failed to shut down object dispatcher: " |
267 | << cpp_strerror(r) << dendl; | |
7c673cae | 268 | } |
f67539c2 | 269 | |
7c673cae FG |
270 | send_flush_op_work_queue(); |
271 | } | |
272 | ||
273 | template <typename I> | |
274 | void CloseRequest<I>::send_flush_op_work_queue() { | |
275 | CephContext *cct = m_image_ctx->cct; | |
276 | ldout(cct, 10) << this << " " << __func__ << dendl; | |
277 | ||
278 | m_image_ctx->op_work_queue->queue(create_context_callback< | |
279 | CloseRequest<I>, &CloseRequest<I>::handle_flush_op_work_queue>(this), 0); | |
280 | } | |
281 | ||
282 | template <typename I> | |
283 | void CloseRequest<I>::handle_flush_op_work_queue(int r) { | |
284 | CephContext *cct = m_image_ctx->cct; | |
285 | ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl; | |
286 | send_close_parent(); | |
287 | } | |
288 | ||
289 | template <typename I> | |
290 | void CloseRequest<I>::send_close_parent() { | |
291 | if (m_image_ctx->parent == nullptr) { | |
292 | send_flush_image_watcher(); | |
293 | return; | |
294 | } | |
295 | ||
296 | CephContext *cct = m_image_ctx->cct; | |
297 | ldout(cct, 10) << this << " " << __func__ << dendl; | |
298 | ||
299 | m_image_ctx->parent->state->close(create_async_context_callback( | |
300 | *m_image_ctx, create_context_callback< | |
301 | CloseRequest<I>, &CloseRequest<I>::handle_close_parent>(this))); | |
302 | } | |
303 | ||
304 | template <typename I> | |
305 | void CloseRequest<I>::handle_close_parent(int r) { | |
306 | CephContext *cct = m_image_ctx->cct; | |
307 | ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl; | |
308 | ||
11fdf7f2 | 309 | m_image_ctx->parent = nullptr; |
7c673cae FG |
310 | save_result(r); |
311 | if (r < 0) { | |
312 | lderr(cct) << "error closing parent image: " << cpp_strerror(r) << dendl; | |
313 | } | |
314 | send_flush_image_watcher(); | |
315 | } | |
316 | ||
317 | template <typename I> | |
318 | void CloseRequest<I>::send_flush_image_watcher() { | |
319 | if (m_image_ctx->image_watcher == nullptr) { | |
320 | finish(); | |
321 | return; | |
322 | } | |
323 | ||
324 | m_image_ctx->image_watcher->flush(create_context_callback< | |
325 | CloseRequest<I>, &CloseRequest<I>::handle_flush_image_watcher>(this)); | |
326 | } | |
327 | ||
328 | template <typename I> | |
329 | void CloseRequest<I>::handle_flush_image_watcher(int r) { | |
330 | CephContext *cct = m_image_ctx->cct; | |
331 | ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl; | |
332 | ||
333 | if (r < 0) { | |
334 | lderr(cct) << "error flushing image watcher: " << cpp_strerror(r) << dendl; | |
335 | } | |
336 | save_result(r); | |
337 | finish(); | |
338 | } | |
339 | ||
340 | template <typename I> | |
341 | void CloseRequest<I>::finish() { | |
342 | m_image_ctx->shutdown(); | |
343 | m_on_finish->complete(m_error_result); | |
344 | delete this; | |
345 | } | |
346 | ||
347 | } // namespace image | |
348 | } // namespace librbd | |
349 | ||
350 | template class librbd::image::CloseRequest<librbd::ImageCtx>; |