Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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/ImageRequestWQ.h"
14
15 #define dout_subsys ceph_subsys_rbd
16 #undef dout_prefix
17 #define dout_prefix *_dout << "librbd::image::CloseRequest: "
18
19 namespace librbd {
20 namespace image {
21
22 using util::create_async_context_callback;
23 using util::create_context_callback;
24
25 template <typename I>
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);
30 }
31
32 template <typename I>
33 void CloseRequest<I>::send() {
34   send_block_image_watcher();
35 }
36
37 template <typename I>
38 void CloseRequest<I>::send_block_image_watcher() {
39   if (m_image_ctx->image_watcher == nullptr) {
40     send_shut_down_update_watchers();
41     return;
42   }
43
44   CephContext *cct = m_image_ctx->cct;
45   ldout(cct, 10) << this << " " << __func__ << dendl;
46
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));
50 }
51
52 template <typename I>
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;
56
57   send_shut_down_update_watchers();
58 }
59
60 template <typename I>
61 void CloseRequest<I>::send_shut_down_update_watchers() {
62   CephContext *cct = m_image_ctx->cct;
63   ldout(cct, 10) << this << " " << __func__ << dendl;
64
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)));
68 }
69
70 template <typename I>
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;
74
75   save_result(r);
76   if (r < 0) {
77     lderr(cct) << "failed to shut down update watchers: " << cpp_strerror(r)
78                << dendl;
79   }
80
81   send_shut_down_io_queue();
82 }
83
84 template <typename I>
85 void 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
94 template <typename I>
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;
98
99   send_shut_down_exclusive_lock();
100 }
101
102 template <typename I>
103 void 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
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;
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   }
153
154   send_unregister_image_watcher();
155 }
156
157 template <typename I>
158 void 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
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;
172
173   if (r < 0) {
174     lderr(cct) << "failed to flush IO: " << cpp_strerror(r) << dendl;
175   }
176   send_unregister_image_watcher();
177 }
178
179 template <typename I>
180 void 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
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;
197
198   save_result(r);
199   if (r < 0) {
200     lderr(cct) << "failed to unregister image watcher: " << cpp_strerror(r)
201                << dendl;
202   }
203
204   send_flush_readahead();
205 }
206
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;
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
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;
221
222   send_shut_down_cache();
223 }
224
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;
229
230   m_image_ctx->shut_down_cache(create_context_callback<
231     CloseRequest<I>, &CloseRequest<I>::handle_shut_down_cache>(this));
232 }
233
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;
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
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;
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
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;
259   send_close_parent();
260 }
261
262 template <typename I>
263 void 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
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;
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
290 template <typename I>
291 void 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
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;
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
313 template <typename I>
314 void 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
323 template class librbd::image::CloseRequest<librbd::ImageCtx>;