]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/image/CloseRequest.cc
bump version to 18.2.2-pve1
[ceph.git] / ceph / src / librbd / image / CloseRequest.cc
CommitLineData
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
24namespace librbd {
25namespace image {
26
27using util::create_async_context_callback;
28using util::create_context_callback;
29
30template <typename I>
31CloseRequest<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
37template <typename I>
38void 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
49template <typename I>
31f18b77
FG
50void 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
64template <typename I>
31f18b77 65void 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
72template <typename I>
31f18b77 73void 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
82template <typename I>
31f18b77 83void 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
96template <typename I>
f67539c2 97void 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
112template <typename I>
f67539c2 113void 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
124template <typename I>
125void 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
152template <typename I>
153void 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
179template <typename I>
180void 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
193template <typename I>
194void 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
207template <typename I>
208void 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
217template <typename I>
218void 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
225template <typename I>
226void 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
235template <typename I>
236void 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
249template <typename I>
11fdf7f2 250void 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
259template <typename I>
11fdf7f2 260void 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
273template <typename I>
274void 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
282template <typename I>
283void 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
289template <typename I>
290void 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
304template <typename I>
305void 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
317template <typename I>
318void 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
328template <typename I>
329void 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
340template <typename I>
341void 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
350template class librbd::image::CloseRequest<librbd::ImageCtx>;