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