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/ConfigWatcher.h"
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"
14 #include "librbd/asio/ContextWQ.h"
15 #include "librbd/io/AioCompletion.h"
16 #include "librbd/io/ImageDispatcher.h"
17 #include "librbd/io/ImageDispatchSpec.h"
18 #include "librbd/io/ObjectDispatcherInterface.h"
20 #define dout_subsys ceph_subsys_rbd
22 #define dout_prefix *_dout << "librbd::image::CloseRequest: "
27 using util::create_async_context_callback
;
28 using util::create_context_callback
;
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) {
34 ceph_assert(image_ctx
!= nullptr);
38 void CloseRequest
<I
>::send() {
39 if (m_image_ctx
->config_watcher
!= nullptr) {
40 m_image_ctx
->config_watcher
->shut_down();
42 delete m_image_ctx
->config_watcher
;
43 m_image_ctx
->config_watcher
= nullptr;
46 send_block_image_watcher();
50 void CloseRequest
<I
>::send_block_image_watcher() {
51 if (m_image_ctx
->image_watcher
== nullptr) {
52 send_shut_down_update_watchers();
56 CephContext
*cct
= m_image_ctx
->cct
;
57 ldout(cct
, 10) << this << " " << __func__
<< dendl
;
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));
65 void CloseRequest
<I
>::handle_block_image_watcher(int r
) {
66 CephContext
*cct
= m_image_ctx
->cct
;
67 ldout(cct
, 10) << this << " " << __func__
<< ": r=" << r
<< dendl
;
69 send_shut_down_update_watchers();
73 void CloseRequest
<I
>::send_shut_down_update_watchers() {
74 CephContext
*cct
= m_image_ctx
->cct
;
75 ldout(cct
, 10) << this << " " << __func__
<< dendl
;
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)));
83 void CloseRequest
<I
>::handle_shut_down_update_watchers(int r
) {
84 CephContext
*cct
= m_image_ctx
->cct
;
85 ldout(cct
, 10) << this << " " << __func__
<< ": r=" << r
<< dendl
;
89 lderr(cct
) << "failed to shut down update watchers: " << cpp_strerror(r
)
97 void CloseRequest
<I
>::send_flush() {
98 CephContext
*cct
= m_image_ctx
->cct
;
99 ldout(cct
, 10) << this << " " << __func__
<< dendl
;
101 std::shared_lock owner_locker
{m_image_ctx
->owner_lock
};
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
,
106 auto req
= io::ImageDispatchSpec::create_flush(
107 *m_image_ctx
, io::IMAGE_DISPATCH_LAYER_API_START
, aio_comp
,
108 io::FLUSH_SOURCE_SHUTDOWN
, {});
112 template <typename I
>
113 void CloseRequest
<I
>::handle_flush(int r
) {
114 CephContext
*cct
= m_image_ctx
->cct
;
115 ldout(cct
, 10) << this << " " << __func__
<< ": r=" << r
<< dendl
;
118 lderr(cct
) << "failed to flush IO: " << cpp_strerror(r
) << dendl
;
121 send_shut_down_exclusive_lock();
124 template <typename I
>
125 void CloseRequest
<I
>::send_shut_down_exclusive_lock() {
127 std::unique_lock owner_locker
{m_image_ctx
->owner_lock
};
128 m_exclusive_lock
= m_image_ctx
->exclusive_lock
;
130 // if reading a snapshot -- possible object map is open
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();
134 m_image_ctx
->object_map
= nullptr;
138 if (m_exclusive_lock
== nullptr) {
139 send_unregister_image_watcher();
143 CephContext
*cct
= m_image_ctx
->cct
;
144 ldout(cct
, 10) << this << " " << __func__
<< dendl
;
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));
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
;
158 std::shared_lock owner_locker
{m_image_ctx
->owner_lock
};
159 ceph_assert(m_image_ctx
->exclusive_lock
== nullptr);
161 // object map and journal closed during exclusive lock shutdown
162 std::shared_lock image_locker
{m_image_ctx
->image_lock
};
163 ceph_assert(m_image_ctx
->journal
== nullptr);
164 ceph_assert(m_image_ctx
->object_map
== nullptr);
167 m_exclusive_lock
->put();
168 m_exclusive_lock
= nullptr;
172 lderr(cct
) << "failed to shut down exclusive lock: " << cpp_strerror(r
)
176 send_unregister_image_watcher();
179 template <typename I
>
180 void CloseRequest
<I
>::send_unregister_image_watcher() {
181 if (m_image_ctx
->image_watcher
== nullptr) {
182 send_flush_readahead();
186 CephContext
*cct
= m_image_ctx
->cct
;
187 ldout(cct
, 10) << this << " " << __func__
<< dendl
;
189 m_image_ctx
->image_watcher
->unregister_watch(create_context_callback
<
190 CloseRequest
<I
>, &CloseRequest
<I
>::handle_unregister_image_watcher
>(this));
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
;
200 lderr(cct
) << "failed to unregister image watcher: " << cpp_strerror(r
)
204 send_flush_readahead();
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
;
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)));
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
;
222 send_shut_down_image_dispatcher();
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
;
230 m_image_ctx
->io_image_dispatcher
->shut_down(create_context_callback
<
232 &CloseRequest
<I
>::handle_shut_down_image_dispatcher
>(this));
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
;
242 lderr(cct
) << "failed to shut down image dispatcher: "
243 << cpp_strerror(r
) << dendl
;
246 send_shut_down_object_dispatcher();
249 template <typename I
>
250 void CloseRequest
<I
>::send_shut_down_object_dispatcher() {
251 CephContext
*cct
= m_image_ctx
->cct
;
252 ldout(cct
, 10) << this << " " << __func__
<< dendl
;
254 m_image_ctx
->io_object_dispatcher
->shut_down(create_context_callback
<
256 &CloseRequest
<I
>::handle_shut_down_object_dispatcher
>(this));
259 template <typename I
>
260 void CloseRequest
<I
>::handle_shut_down_object_dispatcher(int r
) {
261 CephContext
*cct
= m_image_ctx
->cct
;
262 ldout(cct
, 10) << this << " " << __func__
<< ": r=" << r
<< dendl
;
266 lderr(cct
) << "failed to shut down object dispatcher: "
267 << cpp_strerror(r
) << dendl
;
270 send_flush_op_work_queue();
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
;
278 m_image_ctx
->op_work_queue
->queue(create_context_callback
<
279 CloseRequest
<I
>, &CloseRequest
<I
>::handle_flush_op_work_queue
>(this), 0);
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
;
289 template <typename I
>
290 void CloseRequest
<I
>::send_close_parent() {
291 if (m_image_ctx
->parent
== nullptr) {
292 send_flush_image_watcher();
296 CephContext
*cct
= m_image_ctx
->cct
;
297 ldout(cct
, 10) << this << " " << __func__
<< dendl
;
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)));
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
;
309 m_image_ctx
->parent
= nullptr;
312 lderr(cct
) << "error closing parent image: " << cpp_strerror(r
) << dendl
;
314 send_flush_image_watcher();
317 template <typename I
>
318 void CloseRequest
<I
>::send_flush_image_watcher() {
319 if (m_image_ctx
->image_watcher
== nullptr) {
324 m_image_ctx
->image_watcher
->flush(create_context_callback
<
325 CloseRequest
<I
>, &CloseRequest
<I
>::handle_flush_image_watcher
>(this));
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
;
334 lderr(cct
) << "error flushing image watcher: " << cpp_strerror(r
) << dendl
;
340 template <typename I
>
341 void CloseRequest
<I
>::finish() {
342 m_image_ctx
->shutdown();
343 m_on_finish
->complete(m_error_result
);
348 } // namespace librbd
350 template class librbd::image::CloseRequest
<librbd::ImageCtx
>;