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/ImageRequestWQ.h"
15 #define dout_subsys ceph_subsys_rbd
17 #define dout_prefix *_dout << "librbd::image::CloseRequest: "
22 using util::create_async_context_callback
;
23 using util::create_context_callback
;
26 CloseRequest
<I
>::CloseRequest(I
*image_ctx
, Context
*on_finish
)
27 : m_image_ctx(image_ctx
), m_on_finish(on_finish
), m_error_result(0),
28 m_exclusive_lock(nullptr) {
29 assert(image_ctx
!= nullptr);
33 void CloseRequest
<I
>::send() {
34 send_block_image_watcher();
38 void CloseRequest
<I
>::send_block_image_watcher() {
39 if (m_image_ctx
->image_watcher
== nullptr) {
40 send_shut_down_update_watchers();
44 CephContext
*cct
= m_image_ctx
->cct
;
45 ldout(cct
, 10) << this << " " << __func__
<< dendl
;
47 // prevent incoming requests from our peers
48 m_image_ctx
->image_watcher
->block_notifies(create_context_callback
<
49 CloseRequest
<I
>, &CloseRequest
<I
>::handle_block_image_watcher
>(this));
53 void CloseRequest
<I
>::handle_block_image_watcher(int r
) {
54 CephContext
*cct
= m_image_ctx
->cct
;
55 ldout(cct
, 10) << this << " " << __func__
<< ": r=" << r
<< dendl
;
57 send_shut_down_update_watchers();
61 void CloseRequest
<I
>::send_shut_down_update_watchers() {
62 CephContext
*cct
= m_image_ctx
->cct
;
63 ldout(cct
, 10) << this << " " << __func__
<< dendl
;
65 m_image_ctx
->state
->shut_down_update_watchers(create_async_context_callback(
66 *m_image_ctx
, create_context_callback
<
67 CloseRequest
<I
>, &CloseRequest
<I
>::handle_shut_down_update_watchers
>(this)));
71 void CloseRequest
<I
>::handle_shut_down_update_watchers(int r
) {
72 CephContext
*cct
= m_image_ctx
->cct
;
73 ldout(cct
, 10) << this << " " << __func__
<< ": r=" << r
<< dendl
;
77 lderr(cct
) << "failed to shut down update watchers: " << cpp_strerror(r
)
81 send_shut_down_io_queue();
85 void CloseRequest
<I
>::send_shut_down_io_queue() {
86 CephContext
*cct
= m_image_ctx
->cct
;
87 ldout(cct
, 10) << this << " " << __func__
<< dendl
;
89 RWLock::RLocker
owner_locker(m_image_ctx
->owner_lock
);
90 m_image_ctx
->io_work_queue
->shut_down(create_context_callback
<
91 CloseRequest
<I
>, &CloseRequest
<I
>::handle_shut_down_io_queue
>(this));
95 void CloseRequest
<I
>::handle_shut_down_io_queue(int r
) {
96 CephContext
*cct
= m_image_ctx
->cct
;
97 ldout(cct
, 10) << this << " " << __func__
<< ": r=" << r
<< dendl
;
99 send_shut_down_exclusive_lock();
102 template <typename I
>
103 void CloseRequest
<I
>::send_shut_down_exclusive_lock() {
105 RWLock::WLocker
owner_locker(m_image_ctx
->owner_lock
);
106 m_exclusive_lock
= m_image_ctx
->exclusive_lock
;
108 // if reading a snapshot -- possible object map is open
109 RWLock::WLocker
snap_locker(m_image_ctx
->snap_lock
);
110 if (m_exclusive_lock
== nullptr) {
111 delete m_image_ctx
->object_map
;
112 m_image_ctx
->object_map
= nullptr;
116 if (m_exclusive_lock
== nullptr) {
121 CephContext
*cct
= m_image_ctx
->cct
;
122 ldout(cct
, 10) << this << " " << __func__
<< dendl
;
124 // in-flight IO will be flushed and in-flight requests will be canceled
125 // before releasing lock
126 m_exclusive_lock
->shut_down(create_context_callback
<
127 CloseRequest
<I
>, &CloseRequest
<I
>::handle_shut_down_exclusive_lock
>(this));
130 template <typename I
>
131 void CloseRequest
<I
>::handle_shut_down_exclusive_lock(int r
) {
132 CephContext
*cct
= m_image_ctx
->cct
;
133 ldout(cct
, 10) << this << " " << __func__
<< ": r=" << r
<< dendl
;
136 RWLock::RLocker
owner_locker(m_image_ctx
->owner_lock
);
137 assert(m_image_ctx
->exclusive_lock
== nullptr);
139 // object map and journal closed during exclusive lock shutdown
140 RWLock::RLocker
snap_locker(m_image_ctx
->snap_lock
);
141 assert(m_image_ctx
->journal
== nullptr);
142 assert(m_image_ctx
->object_map
== nullptr);
145 delete m_exclusive_lock
;
146 m_exclusive_lock
= nullptr;
150 lderr(cct
) << "failed to shut down exclusive lock: " << cpp_strerror(r
)
154 send_unregister_image_watcher();
157 template <typename I
>
158 void CloseRequest
<I
>::send_flush() {
159 CephContext
*cct
= m_image_ctx
->cct
;
160 ldout(cct
, 10) << this << " " << __func__
<< dendl
;
162 RWLock::RLocker
owner_locker(m_image_ctx
->owner_lock
);
163 m_image_ctx
->flush(create_async_context_callback(
164 *m_image_ctx
, create_context_callback
<
165 CloseRequest
<I
>, &CloseRequest
<I
>::handle_flush
>(this)));
168 template <typename I
>
169 void CloseRequest
<I
>::handle_flush(int r
) {
170 CephContext
*cct
= m_image_ctx
->cct
;
171 ldout(cct
, 10) << this << " " << __func__
<< ": r=" << r
<< dendl
;
174 lderr(cct
) << "failed to flush IO: " << cpp_strerror(r
) << dendl
;
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_cache();
225 template <typename I
>
226 void CloseRequest
<I
>::send_shut_down_cache() {
227 CephContext
*cct
= m_image_ctx
->cct
;
228 ldout(cct
, 10) << this << " " << __func__
<< dendl
;
230 m_image_ctx
->shut_down_cache(create_context_callback
<
231 CloseRequest
<I
>, &CloseRequest
<I
>::handle_shut_down_cache
>(this));
234 template <typename I
>
235 void CloseRequest
<I
>::handle_shut_down_cache(int r
) {
236 CephContext
*cct
= m_image_ctx
->cct
;
237 ldout(cct
, 10) << this << " " << __func__
<< ": r=" << r
<< dendl
;
241 lderr(cct
) << "failed to shut down cache: " << cpp_strerror(r
) << dendl
;
243 send_flush_op_work_queue();
246 template <typename I
>
247 void CloseRequest
<I
>::send_flush_op_work_queue() {
248 CephContext
*cct
= m_image_ctx
->cct
;
249 ldout(cct
, 10) << this << " " << __func__
<< dendl
;
251 m_image_ctx
->op_work_queue
->queue(create_context_callback
<
252 CloseRequest
<I
>, &CloseRequest
<I
>::handle_flush_op_work_queue
>(this), 0);
255 template <typename I
>
256 void CloseRequest
<I
>::handle_flush_op_work_queue(int r
) {
257 CephContext
*cct
= m_image_ctx
->cct
;
258 ldout(cct
, 10) << this << " " << __func__
<< ": r=" << r
<< dendl
;
262 template <typename I
>
263 void CloseRequest
<I
>::send_close_parent() {
264 if (m_image_ctx
->parent
== nullptr) {
265 send_flush_image_watcher();
269 CephContext
*cct
= m_image_ctx
->cct
;
270 ldout(cct
, 10) << this << " " << __func__
<< dendl
;
272 m_image_ctx
->parent
->state
->close(create_async_context_callback(
273 *m_image_ctx
, create_context_callback
<
274 CloseRequest
<I
>, &CloseRequest
<I
>::handle_close_parent
>(this)));
277 template <typename I
>
278 void CloseRequest
<I
>::handle_close_parent(int r
) {
279 CephContext
*cct
= m_image_ctx
->cct
;
280 ldout(cct
, 10) << this << " " << __func__
<< ": r=" << r
<< dendl
;
282 delete m_image_ctx
->parent
;
285 lderr(cct
) << "error closing parent image: " << cpp_strerror(r
) << dendl
;
287 send_flush_image_watcher();
290 template <typename I
>
291 void CloseRequest
<I
>::send_flush_image_watcher() {
292 if (m_image_ctx
->image_watcher
== nullptr) {
297 m_image_ctx
->image_watcher
->flush(create_context_callback
<
298 CloseRequest
<I
>, &CloseRequest
<I
>::handle_flush_image_watcher
>(this));
301 template <typename I
>
302 void CloseRequest
<I
>::handle_flush_image_watcher(int r
) {
303 CephContext
*cct
= m_image_ctx
->cct
;
304 ldout(cct
, 10) << this << " " << __func__
<< ": r=" << r
<< dendl
;
307 lderr(cct
) << "error flushing image watcher: " << cpp_strerror(r
) << dendl
;
313 template <typename I
>
314 void CloseRequest
<I
>::finish() {
315 m_image_ctx
->shutdown();
316 m_on_finish
->complete(m_error_result
);
321 } // namespace librbd
323 template class librbd::image::CloseRequest
<librbd::ImageCtx
>;