]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/image/CloseRequest.cc
update sources to v12.1.0
[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"
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"
14
15#define dout_subsys ceph_subsys_rbd
16#undef dout_prefix
17#define dout_prefix *_dout << "librbd::image::CloseRequest: "
18
19namespace librbd {
20namespace image {
21
22using util::create_async_context_callback;
23using util::create_context_callback;
24
25template <typename I>
26CloseRequest<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);
30}
31
32template <typename I>
33void CloseRequest<I>::send() {
31f18b77 34 send_block_image_watcher();
7c673cae
FG
35}
36
37template <typename I>
31f18b77
FG
38void CloseRequest<I>::send_block_image_watcher() {
39 if (m_image_ctx->image_watcher == nullptr) {
40 send_shut_down_update_watchers();
41 return;
42 }
43
7c673cae
FG
44 CephContext *cct = m_image_ctx->cct;
45 ldout(cct, 10) << this << " " << __func__ << dendl;
46
31f18b77
FG
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));
7c673cae
FG
50}
51
52template <typename I>
31f18b77 53void CloseRequest<I>::handle_block_image_watcher(int r) {
7c673cae
FG
54 CephContext *cct = m_image_ctx->cct;
55 ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl;
56
31f18b77 57 send_shut_down_update_watchers();
7c673cae
FG
58}
59
60template <typename I>
31f18b77 61void CloseRequest<I>::send_shut_down_update_watchers() {
7c673cae
FG
62 CephContext *cct = m_image_ctx->cct;
63 ldout(cct, 10) << this << " " << __func__ << dendl;
64
31f18b77
FG
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)));
7c673cae
FG
68}
69
70template <typename I>
31f18b77 71void CloseRequest<I>::handle_shut_down_update_watchers(int r) {
7c673cae
FG
72 CephContext *cct = m_image_ctx->cct;
73 ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl;
74
75 save_result(r);
76 if (r < 0) {
31f18b77 77 lderr(cct) << "failed to shut down update watchers: " << cpp_strerror(r)
7c673cae
FG
78 << dendl;
79 }
80
81 send_shut_down_io_queue();
82}
83
84template <typename I>
85void CloseRequest<I>::send_shut_down_io_queue() {
86 CephContext *cct = m_image_ctx->cct;
87 ldout(cct, 10) << this << " " << __func__ << dendl;
88
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));
92}
93
94template <typename I>
95void 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;
98
99 send_shut_down_exclusive_lock();
100}
101
102template <typename I>
103void CloseRequest<I>::send_shut_down_exclusive_lock() {
104 {
105 RWLock::WLocker owner_locker(m_image_ctx->owner_lock);
106 m_exclusive_lock = m_image_ctx->exclusive_lock;
107
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;
113 }
114 }
115
116 if (m_exclusive_lock == nullptr) {
117 send_flush();
118 return;
119 }
120
121 CephContext *cct = m_image_ctx->cct;
122 ldout(cct, 10) << this << " " << __func__ << dendl;
123
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));
128}
129
130template <typename I>
131void 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;
134
135 {
136 RWLock::RLocker owner_locker(m_image_ctx->owner_lock);
137 assert(m_image_ctx->exclusive_lock == nullptr);
138
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);
143 }
144
145 delete m_exclusive_lock;
146 m_exclusive_lock = nullptr;
147
148 save_result(r);
149 if (r < 0) {
150 lderr(cct) << "failed to shut down exclusive lock: " << cpp_strerror(r)
151 << dendl;
152 }
31f18b77
FG
153
154 send_unregister_image_watcher();
7c673cae
FG
155}
156
157template <typename I>
158void CloseRequest<I>::send_flush() {
159 CephContext *cct = m_image_ctx->cct;
160 ldout(cct, 10) << this << " " << __func__ << dendl;
161
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)));
166}
167
168template <typename I>
169void CloseRequest<I>::handle_flush(int r) {
170 CephContext *cct = m_image_ctx->cct;
171 ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl;
172
173 if (r < 0) {
174 lderr(cct) << "failed to flush IO: " << cpp_strerror(r) << dendl;
175 }
31f18b77
FG
176 send_unregister_image_watcher();
177}
178
179template <typename I>
180void CloseRequest<I>::send_unregister_image_watcher() {
181 if (m_image_ctx->image_watcher == nullptr) {
182 send_flush_readahead();
183 return;
184 }
185
186 CephContext *cct = m_image_ctx->cct;
187 ldout(cct, 10) << this << " " << __func__ << dendl;
188
189 m_image_ctx->image_watcher->unregister_watch(create_context_callback<
190 CloseRequest<I>, &CloseRequest<I>::handle_unregister_image_watcher>(this));
191}
192
193template <typename I>
194void CloseRequest<I>::handle_unregister_image_watcher(int r) {
195 CephContext *cct = m_image_ctx->cct;
196 ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl;
197
198 save_result(r);
199 if (r < 0) {
200 lderr(cct) << "failed to unregister image watcher: " << cpp_strerror(r)
201 << dendl;
202 }
203
7c673cae
FG
204 send_flush_readahead();
205}
206
207template <typename I>
208void CloseRequest<I>::send_flush_readahead() {
209 CephContext *cct = m_image_ctx->cct;
210 ldout(cct, 10) << this << " " << __func__ << dendl;
211
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)));
215}
216
217template <typename I>
218void CloseRequest<I>::handle_flush_readahead(int r) {
219 CephContext *cct = m_image_ctx->cct;
220 ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl;
221
222 send_shut_down_cache();
223}
224
225template <typename I>
226void CloseRequest<I>::send_shut_down_cache() {
227 CephContext *cct = m_image_ctx->cct;
228 ldout(cct, 10) << this << " " << __func__ << dendl;
229
230 m_image_ctx->shut_down_cache(create_context_callback<
231 CloseRequest<I>, &CloseRequest<I>::handle_shut_down_cache>(this));
232}
233
234template <typename I>
235void CloseRequest<I>::handle_shut_down_cache(int r) {
236 CephContext *cct = m_image_ctx->cct;
237 ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl;
238
239 save_result(r);
240 if (r < 0) {
241 lderr(cct) << "failed to shut down cache: " << cpp_strerror(r) << dendl;
242 }
243 send_flush_op_work_queue();
244}
245
246template <typename I>
247void CloseRequest<I>::send_flush_op_work_queue() {
248 CephContext *cct = m_image_ctx->cct;
249 ldout(cct, 10) << this << " " << __func__ << dendl;
250
251 m_image_ctx->op_work_queue->queue(create_context_callback<
252 CloseRequest<I>, &CloseRequest<I>::handle_flush_op_work_queue>(this), 0);
253}
254
255template <typename I>
256void 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;
259 send_close_parent();
260}
261
262template <typename I>
263void CloseRequest<I>::send_close_parent() {
264 if (m_image_ctx->parent == nullptr) {
265 send_flush_image_watcher();
266 return;
267 }
268
269 CephContext *cct = m_image_ctx->cct;
270 ldout(cct, 10) << this << " " << __func__ << dendl;
271
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)));
275}
276
277template <typename I>
278void CloseRequest<I>::handle_close_parent(int r) {
279 CephContext *cct = m_image_ctx->cct;
280 ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl;
281
282 delete m_image_ctx->parent;
283 save_result(r);
284 if (r < 0) {
285 lderr(cct) << "error closing parent image: " << cpp_strerror(r) << dendl;
286 }
287 send_flush_image_watcher();
288}
289
290template <typename I>
291void CloseRequest<I>::send_flush_image_watcher() {
292 if (m_image_ctx->image_watcher == nullptr) {
293 finish();
294 return;
295 }
296
297 m_image_ctx->image_watcher->flush(create_context_callback<
298 CloseRequest<I>, &CloseRequest<I>::handle_flush_image_watcher>(this));
299}
300
301template <typename I>
302void CloseRequest<I>::handle_flush_image_watcher(int r) {
303 CephContext *cct = m_image_ctx->cct;
304 ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl;
305
306 if (r < 0) {
307 lderr(cct) << "error flushing image watcher: " << cpp_strerror(r) << dendl;
308 }
309 save_result(r);
310 finish();
311}
312
313template <typename I>
314void CloseRequest<I>::finish() {
315 m_image_ctx->shutdown();
316 m_on_finish->complete(m_error_result);
317 delete this;
318}
319
320} // namespace image
321} // namespace librbd
322
323template class librbd::image::CloseRequest<librbd::ImageCtx>;