]>
Commit | Line | Data |
---|---|---|
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 | ||
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() { | |
31f18b77 | 34 | send_block_image_watcher(); |
7c673cae FG |
35 | } |
36 | ||
37 | template <typename I> | |
31f18b77 FG |
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 | ||
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 | ||
52 | template <typename I> | |
31f18b77 | 53 | void 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 | ||
60 | template <typename I> | |
31f18b77 | 61 | void 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 | ||
70 | template <typename I> | |
31f18b77 | 71 | void 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 | ||
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 | } | |
31f18b77 FG |
153 | |
154 | send_unregister_image_watcher(); | |
7c673cae FG |
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 | } | |
31f18b77 FG |
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 | ||
7c673cae FG |
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>; |