]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/exclusive_lock/PreReleaseRequest.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / librbd / exclusive_lock / PreReleaseRequest.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/exclusive_lock/PreReleaseRequest.h"
31f18b77 5#include "common/AsyncOpTracker.h"
7c673cae
FG
6#include "common/dout.h"
7#include "common/errno.h"
8#include "librbd/ExclusiveLock.h"
9#include "librbd/ImageState.h"
10#include "librbd/ImageWatcher.h"
11#include "librbd/Journal.h"
12#include "librbd/ObjectMap.h"
13#include "librbd/Utils.h"
14#include "librbd/io/ImageRequestWQ.h"
11fdf7f2 15#include "librbd/io/ObjectDispatcher.h"
7c673cae
FG
16
17#define dout_subsys ceph_subsys_rbd
18#undef dout_prefix
19#define dout_prefix *_dout << "librbd::exclusive_lock::PreReleaseRequest: " \
20 << this << " " << __func__ << ": "
21
22namespace librbd {
23namespace exclusive_lock {
24
25using util::create_async_context_callback;
26using util::create_context_callback;
27
28template <typename I>
31f18b77
FG
29PreReleaseRequest<I>* PreReleaseRequest<I>::create(
30 I &image_ctx, bool shutting_down, AsyncOpTracker &async_op_tracker,
31 Context *on_finish) {
32 return new PreReleaseRequest(image_ctx, shutting_down, async_op_tracker,
33 on_finish);
7c673cae
FG
34}
35
36template <typename I>
37PreReleaseRequest<I>::PreReleaseRequest(I &image_ctx, bool shutting_down,
31f18b77 38 AsyncOpTracker &async_op_tracker,
7c673cae 39 Context *on_finish)
31f18b77
FG
40 : m_image_ctx(image_ctx), m_shutting_down(shutting_down),
41 m_async_op_tracker(async_op_tracker),
42 m_on_finish(create_async_context_callback(image_ctx, on_finish)) {
7c673cae
FG
43}
44
45template <typename I>
46PreReleaseRequest<I>::~PreReleaseRequest() {
47 if (!m_shutting_down) {
48 m_image_ctx.state->handle_prepare_lock_complete();
49 }
50}
51
52template <typename I>
53void PreReleaseRequest<I>::send() {
54 send_prepare_lock();
55}
56
57template <typename I>
58void PreReleaseRequest<I>::send_prepare_lock() {
59 if (m_shutting_down) {
60 send_cancel_op_requests();
61 return;
62 }
63
64 CephContext *cct = m_image_ctx.cct;
65 ldout(cct, 10) << dendl;
66
67 // release the lock if the image is not busy performing other actions
68 Context *ctx = create_context_callback<
69 PreReleaseRequest<I>, &PreReleaseRequest<I>::handle_prepare_lock>(this);
70 m_image_ctx.state->prepare_lock(ctx);
71}
72
73template <typename I>
74void PreReleaseRequest<I>::handle_prepare_lock(int r) {
75 CephContext *cct = m_image_ctx.cct;
76 ldout(cct, 10) << "r=" << r << dendl;
77
78 send_cancel_op_requests();
79}
80
81template <typename I>
82void PreReleaseRequest<I>::send_cancel_op_requests() {
83 CephContext *cct = m_image_ctx.cct;
84 ldout(cct, 10) << dendl;
85
86 using klass = PreReleaseRequest<I>;
87 Context *ctx = create_context_callback<
88 klass, &klass::handle_cancel_op_requests>(this);
89 m_image_ctx.cancel_async_requests(ctx);
90}
91
92template <typename I>
93void PreReleaseRequest<I>::handle_cancel_op_requests(int r) {
94 CephContext *cct = m_image_ctx.cct;
95 ldout(cct, 10) << "r=" << r << dendl;
96
11fdf7f2 97 ceph_assert(r == 0);
7c673cae
FG
98
99 send_block_writes();
100}
101
102template <typename I>
103void PreReleaseRequest<I>::send_block_writes() {
104 CephContext *cct = m_image_ctx.cct;
105 ldout(cct, 10) << dendl;
106
107 using klass = PreReleaseRequest<I>;
108 Context *ctx = create_context_callback<
109 klass, &klass::handle_block_writes>(this);
110
111 {
112 RWLock::RLocker owner_locker(m_image_ctx.owner_lock);
224ce89b
WB
113 // setting the lock as required will automatically cause the IO
114 // queue to re-request the lock if any IO is queued
115 if (m_image_ctx.clone_copy_on_read ||
116 m_image_ctx.test_features(RBD_FEATURE_JOURNALING)) {
117 m_image_ctx.io_work_queue->set_require_lock(io::DIRECTION_BOTH, true);
118 } else {
119 m_image_ctx.io_work_queue->set_require_lock(io::DIRECTION_WRITE, true);
7c673cae
FG
120 }
121 m_image_ctx.io_work_queue->block_writes(ctx);
122 }
123}
124
125template <typename I>
126void PreReleaseRequest<I>::handle_block_writes(int r) {
127 CephContext *cct = m_image_ctx.cct;
128 ldout(cct, 10) << "r=" << r << dendl;
129
130 if (r == -EBLACKLISTED) {
131 // allow clean shut down if blacklisted
132 lderr(cct) << "failed to block writes because client is blacklisted"
133 << dendl;
134 } else if (r < 0) {
135 lderr(cct) << "failed to block writes: " << cpp_strerror(r) << dendl;
136 m_image_ctx.io_work_queue->unblock_writes();
137 save_result(r);
138 finish();
139 return;
140 }
141
31f18b77
FG
142 send_wait_for_ops();
143}
144
145template <typename I>
146void PreReleaseRequest<I>::send_wait_for_ops() {
147 CephContext *cct = m_image_ctx.cct;
148 ldout(cct, 10) << dendl;
149
150 Context *ctx = create_context_callback<
151 PreReleaseRequest<I>, &PreReleaseRequest<I>::handle_wait_for_ops>(this);
152 m_async_op_tracker.wait_for_ops(ctx);
153}
154
155template <typename I>
156void PreReleaseRequest<I>::handle_wait_for_ops(int r) {
157 CephContext *cct = m_image_ctx.cct;
158 ldout(cct, 10) << dendl;
159
11fdf7f2 160 send_invalidate_cache();
7c673cae
FG
161}
162
163template <typename I>
11fdf7f2 164void PreReleaseRequest<I>::send_invalidate_cache() {
7c673cae 165 CephContext *cct = m_image_ctx.cct;
11fdf7f2 166 ldout(cct, 10) << dendl;
7c673cae
FG
167
168 RWLock::RLocker owner_lock(m_image_ctx.owner_lock);
11fdf7f2 169 Context *ctx = create_context_callback<
7c673cae 170 PreReleaseRequest<I>,
11fdf7f2
TL
171 &PreReleaseRequest<I>::handle_invalidate_cache>(this);
172 m_image_ctx.io_object_dispatcher->invalidate_cache(ctx);
7c673cae
FG
173}
174
175template <typename I>
176void PreReleaseRequest<I>::handle_invalidate_cache(int r) {
177 CephContext *cct = m_image_ctx.cct;
178 ldout(cct, 10) << "r=" << r << dendl;
179
11fdf7f2 180 if (r < 0 && r != -EBLACKLISTED && r != -EBUSY) {
7c673cae
FG
181 lderr(cct) << "failed to invalidate cache: " << cpp_strerror(r)
182 << dendl;
183 m_image_ctx.io_work_queue->unblock_writes();
184 save_result(r);
185 finish();
186 return;
187 }
188
189 send_flush_notifies();
190}
191
192template <typename I>
193void PreReleaseRequest<I>::send_flush_notifies() {
194 CephContext *cct = m_image_ctx.cct;
195 ldout(cct, 10) << dendl;
196
197 using klass = PreReleaseRequest<I>;
198 Context *ctx =
199 create_context_callback<klass, &klass::handle_flush_notifies>(this);
200 m_image_ctx.image_watcher->flush(ctx);
201}
202
203template <typename I>
204void PreReleaseRequest<I>::handle_flush_notifies(int r) {
205 CephContext *cct = m_image_ctx.cct;
206 ldout(cct, 10) << dendl;
207
11fdf7f2 208 ceph_assert(r == 0);
7c673cae
FG
209 send_close_journal();
210}
211
212template <typename I>
213void PreReleaseRequest<I>::send_close_journal() {
214 {
215 RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
216 std::swap(m_journal, m_image_ctx.journal);
217 }
218
219 if (m_journal == nullptr) {
220 send_close_object_map();
221 return;
222 }
223
224 CephContext *cct = m_image_ctx.cct;
225 ldout(cct, 10) << dendl;
226
227 using klass = PreReleaseRequest<I>;
228 Context *ctx = create_context_callback<klass, &klass::handle_close_journal>(
229 this);
230 m_journal->close(ctx);
231}
232
233template <typename I>
234void PreReleaseRequest<I>::handle_close_journal(int r) {
235 CephContext *cct = m_image_ctx.cct;
236 ldout(cct, 10) << "r=" << r << dendl;
237
238 if (r < 0) {
239 // error implies some journal events were not flushed -- continue
240 lderr(cct) << "failed to close journal: " << cpp_strerror(r) << dendl;
241 }
242
243 delete m_journal;
244
245 send_close_object_map();
246}
247
248template <typename I>
249void PreReleaseRequest<I>::send_close_object_map() {
250 {
251 RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
252 std::swap(m_object_map, m_image_ctx.object_map);
253 }
254
255 if (m_object_map == nullptr) {
256 send_unlock();
257 return;
258 }
259
260 CephContext *cct = m_image_ctx.cct;
261 ldout(cct, 10) << dendl;
262
263 using klass = PreReleaseRequest<I>;
264 Context *ctx = create_context_callback<
265 klass, &klass::handle_close_object_map>(this);
266 m_object_map->close(ctx);
267}
268
269template <typename I>
270void PreReleaseRequest<I>::handle_close_object_map(int r) {
271 CephContext *cct = m_image_ctx.cct;
272 ldout(cct, 10) << "r=" << r << dendl;
273
11fdf7f2
TL
274 if (r < 0) {
275 lderr(cct) << "failed to close object map: " << cpp_strerror(r) << dendl;
276 }
7c673cae 277
11fdf7f2 278 delete m_object_map;
7c673cae
FG
279 send_unlock();
280}
281
282template <typename I>
283void PreReleaseRequest<I>::send_unlock() {
284 CephContext *cct = m_image_ctx.cct;
285 ldout(cct, 10) << dendl;
286
287 finish();
288}
289
290template <typename I>
291void PreReleaseRequest<I>::finish() {
292 m_on_finish->complete(m_error_result);
293 delete this;
294}
295
296} // namespace exclusive_lock
297} // namespace librbd
298
299template class librbd::exclusive_lock::PreReleaseRequest<librbd::ImageCtx>;