]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/exclusive_lock/PostAcquireRequest.cc
import 15.2.0 Octopus source
[ceph.git] / ceph / src / librbd / exclusive_lock / PostAcquireRequest.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/PostAcquireRequest.h"
5#include "cls/lock/cls_lock_client.h"
6#include "cls/lock/cls_lock_types.h"
7#include "common/dout.h"
8#include "common/errno.h"
9#include "common/WorkQueue.h"
10#include "include/stringify.h"
11#include "librbd/ExclusiveLock.h"
12#include "librbd/ImageCtx.h"
13#include "librbd/ImageState.h"
14#include "librbd/ImageWatcher.h"
15#include "librbd/Journal.h"
16#include "librbd/ObjectMap.h"
17#include "librbd/Utils.h"
18#include "librbd/image/RefreshRequest.h"
19#include "librbd/journal/Policy.h"
20
21#define dout_subsys ceph_subsys_rbd
22#undef dout_prefix
23#define dout_prefix *_dout << "librbd::exclusive_lock::PostAcquireRequest: " \
24 << this << " " << __func__ << ": "
25
26namespace librbd {
27namespace exclusive_lock {
28
29using util::create_async_context_callback;
30using util::create_context_callback;
31using util::create_rados_callback;
32
33template <typename I>
34PostAcquireRequest<I>* PostAcquireRequest<I>::create(I &image_ctx,
35 Context *on_acquire,
36 Context *on_finish) {
37 return new PostAcquireRequest(image_ctx, on_acquire, on_finish);
38}
39
40template <typename I>
41PostAcquireRequest<I>::PostAcquireRequest(I &image_ctx, Context *on_acquire,
42 Context *on_finish)
43 : m_image_ctx(image_ctx),
44 m_on_acquire(on_acquire),
45 m_on_finish(create_async_context_callback(image_ctx, on_finish)),
46 m_object_map(nullptr), m_journal(nullptr), m_error_result(0) {
47}
48
49template <typename I>
50PostAcquireRequest<I>::~PostAcquireRequest() {
51 if (!m_prepare_lock_completed) {
52 m_image_ctx.state->handle_prepare_lock_complete();
53 }
54 delete m_on_acquire;
55}
56
57template <typename I>
58void PostAcquireRequest<I>::send() {
59 send_refresh();
60}
61
62template <typename I>
63void PostAcquireRequest<I>::send_refresh() {
64 if (!m_image_ctx.state->is_refresh_required()) {
65 send_open_object_map();
66 return;
67 }
68
69 CephContext *cct = m_image_ctx.cct;
70 ldout(cct, 10) << dendl;
71
72 using klass = PostAcquireRequest<I>;
73 Context *ctx = create_async_context_callback(
74 m_image_ctx, create_context_callback<klass, &klass::handle_refresh>(this));
75
76 // ImageState is blocked waiting for lock to complete -- safe to directly
77 // refresh
78 image::RefreshRequest<I> *req = image::RefreshRequest<I>::create(
79 m_image_ctx, true, false, ctx);
80 req->send();
81}
82
83template <typename I>
84void PostAcquireRequest<I>::handle_refresh(int r) {
85 CephContext *cct = m_image_ctx.cct;
86 ldout(cct, 10) << "r=" << r << dendl;
87
88 if (r == -ERESTART) {
89 // next issued IO or op will (re)-refresh the image and shut down lock
90 ldout(cct, 5) << "exclusive lock dynamically disabled" << dendl;
91 r = 0;
92 } else if (r < 0) {
93 lderr(cct) << "failed to refresh image: " << cpp_strerror(r) << dendl;
94 save_result(r);
95 revert();
96 finish();
97 return;
98 }
99
100 send_open_object_map();
101}
102
103template <typename I>
104void PostAcquireRequest<I>::send_open_journal() {
105 // alert caller that we now own the exclusive lock
106 m_on_acquire->complete(0);
107 m_on_acquire = nullptr;
108
109 bool journal_enabled;
110 {
9f95a23c 111 std::shared_lock image_locker{m_image_ctx.image_lock};
7c673cae 112 journal_enabled = (m_image_ctx.test_features(RBD_FEATURE_JOURNALING,
9f95a23c 113 m_image_ctx.image_lock) &&
7c673cae
FG
114 !m_image_ctx.get_journal_policy()->journal_disabled());
115 }
116 if (!journal_enabled) {
117 apply();
118 finish();
119 return;
120 }
121
122 CephContext *cct = m_image_ctx.cct;
123 ldout(cct, 10) << dendl;
124
125 using klass = PostAcquireRequest<I>;
126 Context *ctx = create_context_callback<klass, &klass::handle_open_journal>(
127 this);
128 m_journal = m_image_ctx.create_journal();
129
130 // journal playback requires object map (if enabled) and itself
131 apply();
132
133 m_journal->open(ctx);
134}
135
136template <typename I>
137void PostAcquireRequest<I>::handle_open_journal(int r) {
138 CephContext *cct = m_image_ctx.cct;
139 ldout(cct, 10) << "r=" << r << dendl;
140
141 save_result(r);
142 if (r < 0) {
143 lderr(cct) << "failed to open journal: " << cpp_strerror(r) << dendl;
144 send_close_journal();
145 return;
146 }
147
148 send_allocate_journal_tag();
149}
150
151template <typename I>
152void PostAcquireRequest<I>::send_allocate_journal_tag() {
153 CephContext *cct = m_image_ctx.cct;
154 ldout(cct, 10) << dendl;
155
9f95a23c 156 std::shared_lock image_locker{m_image_ctx.image_lock};
7c673cae
FG
157 using klass = PostAcquireRequest<I>;
158 Context *ctx = create_context_callback<
9f95a23c 159 klass, &klass::handle_allocate_journal_tag>(this, m_journal);
7c673cae
FG
160 m_image_ctx.get_journal_policy()->allocate_tag_on_lock(ctx);
161}
162
163template <typename I>
164void PostAcquireRequest<I>::handle_allocate_journal_tag(int r) {
165 CephContext *cct = m_image_ctx.cct;
166 ldout(cct, 10) << "r=" << r << dendl;
167
168 save_result(r);
169 if (r < 0) {
170 lderr(cct) << "failed to allocate journal tag: " << cpp_strerror(r)
171 << dendl;
172 send_close_journal();
173 return;
174 }
175
176 finish();
177}
178
179template <typename I>
180void PostAcquireRequest<I>::send_close_journal() {
181 CephContext *cct = m_image_ctx.cct;
182 ldout(cct, 10) << dendl;
183
184 using klass = PostAcquireRequest<I>;
185 Context *ctx = create_context_callback<klass, &klass::handle_close_journal>(
186 this);
187 m_journal->close(ctx);
188}
189
190template <typename I>
191void PostAcquireRequest<I>::handle_close_journal(int r) {
192 CephContext *cct = m_image_ctx.cct;
193 ldout(cct, 10) << "r=" << r << dendl;
194
195 save_result(r);
196 if (r < 0) {
197 lderr(cct) << "failed to close journal: " << cpp_strerror(r) << dendl;
198 }
199
200 send_close_object_map();
201}
202
203template <typename I>
204void PostAcquireRequest<I>::send_open_object_map() {
205 if (!m_image_ctx.test_features(RBD_FEATURE_OBJECT_MAP)) {
206 send_open_journal();
207 return;
208 }
209
210 CephContext *cct = m_image_ctx.cct;
211 ldout(cct, 10) << dendl;
212
213 using klass = PostAcquireRequest<I>;
214 Context *ctx = create_context_callback<klass, &klass::handle_open_object_map>(
215 this);
216
217 m_object_map = m_image_ctx.create_object_map(CEPH_NOSNAP);
218 m_object_map->open(ctx);
219}
220
221template <typename I>
222void PostAcquireRequest<I>::handle_open_object_map(int r) {
223 CephContext *cct = m_image_ctx.cct;
224 ldout(cct, 10) << "r=" << r << dendl;
225
226 if (r < 0) {
227 lderr(cct) << "failed to open object map: " << cpp_strerror(r) << dendl;
9f95a23c 228 m_object_map->put();
7c673cae 229 m_object_map = nullptr;
11fdf7f2
TL
230
231 if (r != -EFBIG) {
232 save_result(r);
233 revert();
234 finish();
235 return;
236 }
7c673cae
FG
237 }
238
239 send_open_journal();
240}
241
242template <typename I>
243void PostAcquireRequest<I>::send_close_object_map() {
244 if (m_object_map == nullptr) {
245 revert();
246 finish();
247 return;
248 }
249
250 CephContext *cct = m_image_ctx.cct;
251 ldout(cct, 10) << dendl;
252
253 using klass = PostAcquireRequest<I>;
254 Context *ctx = create_context_callback<
255 klass, &klass::handle_close_object_map>(this);
256 m_object_map->close(ctx);
257}
258
259template <typename I>
260void PostAcquireRequest<I>::handle_close_object_map(int r) {
261 CephContext *cct = m_image_ctx.cct;
262 ldout(cct, 10) << "r=" << r << dendl;
263
11fdf7f2
TL
264 if (r < 0) {
265 lderr(cct) << "failed to close object map: " << cpp_strerror(r) << dendl;
266 }
267
7c673cae
FG
268 revert();
269 finish();
270}
271
272template <typename I>
273void PostAcquireRequest<I>::apply() {
274 {
9f95a23c 275 std::unique_lock image_locker{m_image_ctx.image_lock};
11fdf7f2 276 ceph_assert(m_image_ctx.object_map == nullptr);
7c673cae
FG
277 m_image_ctx.object_map = m_object_map;
278
11fdf7f2 279 ceph_assert(m_image_ctx.journal == nullptr);
7c673cae
FG
280 m_image_ctx.journal = m_journal;
281 }
282
283 m_prepare_lock_completed = true;
284 m_image_ctx.state->handle_prepare_lock_complete();
285}
286
287template <typename I>
288void PostAcquireRequest<I>::revert() {
9f95a23c 289 std::unique_lock image_locker{m_image_ctx.image_lock};
7c673cae
FG
290 m_image_ctx.object_map = nullptr;
291 m_image_ctx.journal = nullptr;
292
9f95a23c
TL
293 if (m_object_map) {
294 m_object_map->put();
295 }
296 if (m_journal) {
297 m_journal->put();
298 }
7c673cae 299
11fdf7f2 300 ceph_assert(m_error_result < 0);
7c673cae
FG
301}
302
303template <typename I>
304void PostAcquireRequest<I>::finish() {
305 m_on_finish->complete(m_error_result);
306 delete this;
307}
308
309} // namespace exclusive_lock
310} // namespace librbd
311
312template class librbd::exclusive_lock::PostAcquireRequest<librbd::ImageCtx>;