1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
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"
18 #define dout_subsys ceph_subsys_rbd
20 #define dout_prefix *_dout << "librbd::image::CloseRequest: "
25 using util::create_async_context_callback
;
26 using util::create_context_callback
;
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);
36 void CloseRequest
<I
>::send() {
37 send_block_image_watcher();
41 void CloseRequest
<I
>::send_block_image_watcher() {
42 if (m_image_ctx
->image_watcher
== nullptr) {
43 send_shut_down_update_watchers();
47 CephContext
*cct
= m_image_ctx
->cct
;
48 ldout(cct
, 10) << this << " " << __func__
<< dendl
;
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));
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
;
60 send_shut_down_update_watchers();
64 void CloseRequest
<I
>::send_shut_down_update_watchers() {
65 CephContext
*cct
= m_image_ctx
->cct
;
66 ldout(cct
, 10) << this << " " << __func__
<< dendl
;
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)));
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
;
80 lderr(cct
) << "failed to shut down update watchers: " << cpp_strerror(r
)
84 send_shut_down_io_queue();
88 void CloseRequest
<I
>::send_shut_down_io_queue() {
89 CephContext
*cct
= m_image_ctx
->cct
;
90 ldout(cct
, 10) << this << " " << __func__
<< dendl
;
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));
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
;
102 send_shut_down_exclusive_lock();
105 template <typename I
>
106 void CloseRequest
<I
>::send_shut_down_exclusive_lock() {
108 RWLock::WLocker
owner_locker(m_image_ctx
->owner_lock
);
109 m_exclusive_lock
= m_image_ctx
->exclusive_lock
;
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;
119 if (m_exclusive_lock
== nullptr) {
124 CephContext
*cct
= m_image_ctx
->cct
;
125 ldout(cct
, 10) << this << " " << __func__
<< dendl
;
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));
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
;
139 RWLock::RLocker
owner_locker(m_image_ctx
->owner_lock
);
140 ceph_assert(m_image_ctx
->exclusive_lock
== nullptr);
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);
148 delete m_exclusive_lock
;
149 m_exclusive_lock
= nullptr;
153 lderr(cct
) << "failed to shut down exclusive lock: " << cpp_strerror(r
)
157 send_unregister_image_watcher();
160 template <typename I
>
161 void CloseRequest
<I
>::send_flush() {
162 CephContext
*cct
= m_image_ctx
->cct
;
163 ldout(cct
, 10) << this << " " << __func__
<< dendl
;
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
,
170 auto req
= io::ImageDispatchSpec
<I
>::create_flush_request(
171 *m_image_ctx
, aio_comp
, io::FLUSH_SOURCE_INTERNAL
, {});
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
;
182 lderr(cct
) << "failed to flush IO: " << cpp_strerror(r
) << dendl
;
184 send_unregister_image_watcher();
187 template <typename I
>
188 void CloseRequest
<I
>::send_unregister_image_watcher() {
189 if (m_image_ctx
->image_watcher
== nullptr) {
190 send_flush_readahead();
194 CephContext
*cct
= m_image_ctx
->cct
;
195 ldout(cct
, 10) << this << " " << __func__
<< dendl
;
197 m_image_ctx
->image_watcher
->unregister_watch(create_context_callback
<
198 CloseRequest
<I
>, &CloseRequest
<I
>::handle_unregister_image_watcher
>(this));
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
;
208 lderr(cct
) << "failed to unregister image watcher: " << cpp_strerror(r
)
212 send_flush_readahead();
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
;
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)));
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
;
230 send_shut_down_object_dispatcher();
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
;
238 m_image_ctx
->io_object_dispatcher
->shut_down(create_context_callback
<
240 &CloseRequest
<I
>::handle_shut_down_object_dispatcher
>(this));
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
;
250 lderr(cct
) << "failed to shut down object dispatcher: "
251 << cpp_strerror(r
) << dendl
;
253 send_flush_op_work_queue();
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
;
261 m_image_ctx
->op_work_queue
->queue(create_context_callback
<
262 CloseRequest
<I
>, &CloseRequest
<I
>::handle_flush_op_work_queue
>(this), 0);
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
;
272 template <typename I
>
273 void CloseRequest
<I
>::send_close_parent() {
274 if (m_image_ctx
->parent
== nullptr) {
275 send_flush_image_watcher();
279 CephContext
*cct
= m_image_ctx
->cct
;
280 ldout(cct
, 10) << this << " " << __func__
<< dendl
;
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)));
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
;
292 delete m_image_ctx
->parent
;
293 m_image_ctx
->parent
= nullptr;
296 lderr(cct
) << "error closing parent image: " << cpp_strerror(r
) << dendl
;
298 send_flush_image_watcher();
301 template <typename I
>
302 void CloseRequest
<I
>::send_flush_image_watcher() {
303 if (m_image_ctx
->image_watcher
== nullptr) {
308 m_image_ctx
->image_watcher
->flush(create_context_callback
<
309 CloseRequest
<I
>, &CloseRequest
<I
>::handle_flush_image_watcher
>(this));
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
;
318 lderr(cct
) << "error flushing image watcher: " << cpp_strerror(r
) << dendl
;
324 template <typename I
>
325 void CloseRequest
<I
>::finish() {
326 m_image_ctx
->shutdown();
327 m_on_finish
->complete(m_error_result
);
332 } // namespace librbd
334 template class librbd::image::CloseRequest
<librbd::ImageCtx
>;