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