]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/ManagedLock.cc
update ceph source to reef 18.2.1
[ceph.git] / ceph / src / librbd / ManagedLock.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/ManagedLock.h"
f67539c2
TL
5#include "librbd/AsioEngine.h"
6#include "librbd/ImageCtx.h"
7#include "librbd/Watcher.h"
8#include "librbd/asio/ContextWQ.h"
7c673cae
FG
9#include "librbd/managed_lock/AcquireRequest.h"
10#include "librbd/managed_lock/BreakRequest.h"
11#include "librbd/managed_lock/GetLockerRequest.h"
12#include "librbd/managed_lock/ReleaseRequest.h"
13#include "librbd/managed_lock/ReacquireRequest.h"
14#include "librbd/managed_lock/Types.h"
15#include "librbd/managed_lock/Utils.h"
7c673cae
FG
16#include "cls/lock/cls_lock_client.h"
17#include "common/dout.h"
18#include "common/errno.h"
11fdf7f2 19#include "common/Cond.h"
7c673cae
FG
20#include "librbd/Utils.h"
21
22#define dout_subsys ceph_subsys_rbd
23#undef dout_prefix
24#define dout_prefix *_dout << "librbd::ManagedLock: " << this << " " \
11fdf7f2 25 << __func__ << ": "
7c673cae
FG
26
27namespace librbd {
28
29using std::string;
30using namespace managed_lock;
31
32namespace {
33
34template <typename R>
35struct C_SendLockRequest : public Context {
36 R* request;
37 explicit C_SendLockRequest(R* request) : request(request) {
38 }
39 void finish(int r) override {
40 request->send();
41 }
42};
43
44struct C_Tracked : public Context {
45 AsyncOpTracker &tracker;
46 Context *ctx;
47 C_Tracked(AsyncOpTracker &tracker, Context *ctx)
48 : tracker(tracker), ctx(ctx) {
49 tracker.start_op();
50 }
51 ~C_Tracked() override {
52 tracker.finish_op();
53 }
54 void finish(int r) override {
55 ctx->complete(r);
56 }
57};
58
59} // anonymous namespace
60
61using librbd::util::create_context_callback;
62using librbd::util::unique_lock_name;
63using managed_lock::util::decode_lock_cookie;
64using managed_lock::util::encode_lock_cookie;
65
66template <typename I>
f67539c2 67ManagedLock<I>::ManagedLock(librados::IoCtx &ioctx, AsioEngine& asio_engine,
7c673cae 68 const string& oid, Watcher *watcher, Mode mode,
f67539c2
TL
69 bool blocklist_on_break_lock,
70 uint32_t blocklist_expire_seconds)
9f95a23c 71 : m_lock(ceph::make_mutex(unique_lock_name("librbd::ManagedLock<I>::m_lock", this))),
7c673cae 72 m_ioctx(ioctx), m_cct(reinterpret_cast<CephContext *>(ioctx.cct())),
f67539c2
TL
73 m_asio_engine(asio_engine),
74 m_work_queue(asio_engine.get_work_queue()),
7c673cae
FG
75 m_oid(oid),
76 m_watcher(watcher),
77 m_mode(mode),
f67539c2
TL
78 m_blocklist_on_break_lock(blocklist_on_break_lock),
79 m_blocklist_expire_seconds(blocklist_expire_seconds),
7c673cae
FG
80 m_state(STATE_UNLOCKED) {
81}
82
83template <typename I>
84ManagedLock<I>::~ManagedLock() {
9f95a23c 85 std::lock_guard locker{m_lock};
11fdf7f2
TL
86 ceph_assert(m_state == STATE_SHUTDOWN || m_state == STATE_UNLOCKED ||
87 m_state == STATE_UNINITIALIZED);
7c673cae
FG
88 if (m_state == STATE_UNINITIALIZED) {
89 // never initialized -- ensure any in-flight ops are complete
90 // since we wouldn't expect shut_down to be invoked
91 C_SaferCond ctx;
92 m_async_op_tracker.wait_for_ops(&ctx);
93 ctx.wait();
94 }
11fdf7f2 95 ceph_assert(m_async_op_tracker.empty());
7c673cae
FG
96}
97
98template <typename I>
99bool ManagedLock<I>::is_lock_owner() const {
9f95a23c 100 std::lock_guard locker{m_lock};
7c673cae
FG
101
102 return is_lock_owner(m_lock);
103}
104
105template <typename I>
9f95a23c 106bool ManagedLock<I>::is_lock_owner(ceph::mutex &lock) const {
7c673cae 107
9f95a23c 108 ceph_assert(ceph_mutex_is_locked(m_lock));
7c673cae
FG
109
110 bool lock_owner;
111
112 switch (m_state) {
113 case STATE_LOCKED:
114 case STATE_REACQUIRING:
115 case STATE_PRE_SHUTTING_DOWN:
116 case STATE_POST_ACQUIRING:
117 case STATE_PRE_RELEASING:
118 lock_owner = true;
119 break;
120 default:
121 lock_owner = false;
122 break;
123 }
124
1e59de90 125 ldout(m_cct, 20) << lock_owner << dendl;
7c673cae
FG
126 return lock_owner;
127}
128
129template <typename I>
130void ManagedLock<I>::shut_down(Context *on_shut_down) {
131 ldout(m_cct, 10) << dendl;
132
9f95a23c 133 std::lock_guard locker{m_lock};
11fdf7f2 134 ceph_assert(!is_state_shutdown());
91327a77
AA
135
136 if (m_state == STATE_WAITING_FOR_REGISTER) {
137 // abort stalled acquire lock state
138 ldout(m_cct, 10) << "woke up waiting (re)acquire" << dendl;
139 Action active_action = get_active_action();
11fdf7f2
TL
140 ceph_assert(active_action == ACTION_TRY_LOCK ||
141 active_action == ACTION_ACQUIRE_LOCK);
1e59de90 142 complete_active_action(STATE_UNLOCKED, -ERESTART);
91327a77
AA
143 }
144
7c673cae
FG
145 execute_action(ACTION_SHUT_DOWN, on_shut_down);
146}
147
148template <typename I>
149void ManagedLock<I>::acquire_lock(Context *on_acquired) {
150 int r = 0;
151 {
9f95a23c 152 std::lock_guard locker{m_lock};
7c673cae 153 if (is_state_shutdown()) {
1e59de90 154 r = -ERESTART;
7c673cae
FG
155 } else if (m_state != STATE_LOCKED || !m_actions_contexts.empty()) {
156 ldout(m_cct, 10) << dendl;
157 execute_action(ACTION_ACQUIRE_LOCK, on_acquired);
158 return;
159 }
160 }
161
162 if (on_acquired != nullptr) {
163 on_acquired->complete(r);
164 }
165}
166
167template <typename I>
168void ManagedLock<I>::try_acquire_lock(Context *on_acquired) {
169 int r = 0;
170 {
9f95a23c 171 std::lock_guard locker{m_lock};
7c673cae 172 if (is_state_shutdown()) {
1e59de90 173 r = -ERESTART;
7c673cae
FG
174 } else if (m_state != STATE_LOCKED || !m_actions_contexts.empty()) {
175 ldout(m_cct, 10) << dendl;
176 execute_action(ACTION_TRY_LOCK, on_acquired);
177 return;
178 }
179 }
180
181 if (on_acquired != nullptr) {
182 on_acquired->complete(r);
183 }
184}
185
186template <typename I>
187void ManagedLock<I>::release_lock(Context *on_released) {
188 int r = 0;
189 {
9f95a23c 190 std::lock_guard locker{m_lock};
7c673cae 191 if (is_state_shutdown()) {
1e59de90 192 r = -ERESTART;
7c673cae
FG
193 } else if (m_state != STATE_UNLOCKED || !m_actions_contexts.empty()) {
194 ldout(m_cct, 10) << dendl;
195 execute_action(ACTION_RELEASE_LOCK, on_released);
196 return;
197 }
198 }
199
200 if (on_released != nullptr) {
201 on_released->complete(r);
202 }
203}
204
205template <typename I>
206void ManagedLock<I>::reacquire_lock(Context *on_reacquired) {
207 {
9f95a23c 208 std::lock_guard locker{m_lock};
7c673cae 209
aee94f69
TL
210 if (m_state == STATE_WAITING_FOR_REGISTER ||
211 m_state == STATE_WAITING_FOR_LOCK) {
7c673cae 212 // restart the acquire lock process now that watch is valid
11fdf7f2 213 ldout(m_cct, 10) << "woke up waiting (re)acquire" << dendl;
7c673cae 214 Action active_action = get_active_action();
11fdf7f2
TL
215 ceph_assert(active_action == ACTION_TRY_LOCK ||
216 active_action == ACTION_ACQUIRE_LOCK);
7c673cae
FG
217 execute_next_action();
218 } else if (!is_state_shutdown() &&
219 (m_state == STATE_LOCKED ||
220 m_state == STATE_ACQUIRING ||
aee94f69 221 m_state == STATE_POST_ACQUIRING)) {
7c673cae
FG
222 // interlock the lock operation with other state ops
223 ldout(m_cct, 10) << dendl;
224 execute_action(ACTION_REACQUIRE_LOCK, on_reacquired);
225 return;
226 }
227 }
228
229 // ignore request if shutdown or not in a locked-related state
230 if (on_reacquired != nullptr) {
231 on_reacquired->complete(0);
232 }
233}
234
235template <typename I>
236void ManagedLock<I>::get_locker(managed_lock::Locker *locker,
237 Context *on_finish) {
238 ldout(m_cct, 10) << dendl;
239
240 int r;
241 {
9f95a23c 242 std::lock_guard l{m_lock};
7c673cae 243 if (is_state_shutdown()) {
1e59de90 244 r = -ERESTART;
7c673cae
FG
245 } else {
246 on_finish = new C_Tracked(m_async_op_tracker, on_finish);
247 auto req = managed_lock::GetLockerRequest<I>::create(
248 m_ioctx, m_oid, m_mode == EXCLUSIVE, locker, on_finish);
249 req->send();
250 return;
251 }
252 }
253
254 on_finish->complete(r);
255}
256
257template <typename I>
258void ManagedLock<I>::break_lock(const managed_lock::Locker &locker,
259 bool force_break_lock, Context *on_finish) {
260 ldout(m_cct, 10) << dendl;
261
262 int r;
263 {
9f95a23c 264 std::lock_guard l{m_lock};
7c673cae 265 if (is_state_shutdown()) {
1e59de90 266 r = -ERESTART;
7c673cae
FG
267 } else if (is_lock_owner(m_lock)) {
268 r = -EBUSY;
269 } else {
270 on_finish = new C_Tracked(m_async_op_tracker, on_finish);
271 auto req = managed_lock::BreakRequest<I>::create(
f67539c2
TL
272 m_ioctx, m_asio_engine, m_oid, locker, m_mode == EXCLUSIVE,
273 m_blocklist_on_break_lock, m_blocklist_expire_seconds, force_break_lock,
31f18b77 274 on_finish);
7c673cae
FG
275 req->send();
276 return;
277 }
278 }
279
280 on_finish->complete(r);
281}
282
283template <typename I>
284int ManagedLock<I>::assert_header_locked() {
285 ldout(m_cct, 10) << dendl;
286
287 librados::ObjectReadOperation op;
288 {
9f95a23c 289 std::lock_guard locker{m_lock};
7c673cae 290 rados::cls::lock::assert_locked(&op, RBD_LOCK_NAME,
f67539c2
TL
291 (m_mode == EXCLUSIVE ? ClsLockType::EXCLUSIVE :
292 ClsLockType::SHARED),
7c673cae
FG
293 m_cookie,
294 managed_lock::util::get_watcher_lock_tag());
295 }
296
297 int r = m_ioctx.operate(m_oid, &op, nullptr);
298 if (r < 0) {
f67539c2
TL
299 if (r == -EBLOCKLISTED) {
300 ldout(m_cct, 5) << "client is not lock owner -- client blocklisted"
7c673cae
FG
301 << dendl;
302 } else if (r == -ENOENT) {
303 ldout(m_cct, 5) << "client is not lock owner -- no lock detected"
304 << dendl;
305 } else if (r == -EBUSY) {
306 ldout(m_cct, 5) << "client is not lock owner -- owned by different client"
307 << dendl;
308 } else {
309 lderr(m_cct) << "failed to verify lock ownership: " << cpp_strerror(r)
310 << dendl;
311 }
312
313 return r;
314 }
315
316 return 0;
317}
318
319template <typename I>
320void ManagedLock<I>::shutdown_handler(int r, Context *on_finish) {
321 on_finish->complete(r);
322}
323
324template <typename I>
325void ManagedLock<I>::pre_acquire_lock_handler(Context *on_finish) {
326 on_finish->complete(0);
327}
328
329template <typename I>
330void ManagedLock<I>::post_acquire_lock_handler(int r, Context *on_finish) {
331 on_finish->complete(r);
332}
333
334template <typename I>
335void ManagedLock<I>::pre_release_lock_handler(bool shutting_down,
336 Context *on_finish) {
337 on_finish->complete(0);
338}
339
340template <typename I>
341void ManagedLock<I>::post_release_lock_handler(bool shutting_down, int r,
342 Context *on_finish) {
343 on_finish->complete(r);
344}
345
31f18b77
FG
346template <typename I>
347void ManagedLock<I>::post_reacquire_lock_handler(int r, Context *on_finish) {
348 on_finish->complete(r);
349}
350
7c673cae
FG
351template <typename I>
352bool ManagedLock<I>::is_transition_state() const {
353 switch (m_state) {
354 case STATE_ACQUIRING:
355 case STATE_WAITING_FOR_REGISTER:
356 case STATE_REACQUIRING:
357 case STATE_RELEASING:
358 case STATE_PRE_SHUTTING_DOWN:
359 case STATE_SHUTTING_DOWN:
360 case STATE_INITIALIZING:
361 case STATE_WAITING_FOR_LOCK:
362 case STATE_POST_ACQUIRING:
363 case STATE_PRE_RELEASING:
364 return true;
365 case STATE_UNLOCKED:
366 case STATE_LOCKED:
367 case STATE_SHUTDOWN:
368 case STATE_UNINITIALIZED:
369 break;
370 }
371 return false;
372}
373
374template <typename I>
375void ManagedLock<I>::append_context(Action action, Context *ctx) {
9f95a23c 376 ceph_assert(ceph_mutex_is_locked(m_lock));
7c673cae
FG
377
378 for (auto &action_ctxs : m_actions_contexts) {
379 if (action == action_ctxs.first) {
380 if (ctx != nullptr) {
381 action_ctxs.second.push_back(ctx);
382 }
383 return;
384 }
385 }
386
387 Contexts contexts;
388 if (ctx != nullptr) {
389 contexts.push_back(ctx);
390 }
391 m_actions_contexts.push_back({action, std::move(contexts)});
392}
393
394template <typename I>
395void ManagedLock<I>::execute_action(Action action, Context *ctx) {
9f95a23c 396 ceph_assert(ceph_mutex_is_locked(m_lock));
7c673cae
FG
397
398 append_context(action, ctx);
399 if (!is_transition_state()) {
400 execute_next_action();
401 }
402}
403
404template <typename I>
405void ManagedLock<I>::execute_next_action() {
9f95a23c 406 ceph_assert(ceph_mutex_is_locked(m_lock));
11fdf7f2 407 ceph_assert(!m_actions_contexts.empty());
7c673cae
FG
408 switch (get_active_action()) {
409 case ACTION_ACQUIRE_LOCK:
410 case ACTION_TRY_LOCK:
411 send_acquire_lock();
412 break;
413 case ACTION_REACQUIRE_LOCK:
414 send_reacquire_lock();
415 break;
416 case ACTION_RELEASE_LOCK:
417 send_release_lock();
418 break;
419 case ACTION_SHUT_DOWN:
420 send_shutdown();
421 break;
422 default:
11fdf7f2 423 ceph_abort();
7c673cae
FG
424 break;
425 }
426}
427
428template <typename I>
429typename ManagedLock<I>::Action ManagedLock<I>::get_active_action() const {
9f95a23c 430 ceph_assert(ceph_mutex_is_locked(m_lock));
11fdf7f2 431 ceph_assert(!m_actions_contexts.empty());
7c673cae
FG
432 return m_actions_contexts.front().first;
433}
434
435template <typename I>
436void ManagedLock<I>::complete_active_action(State next_state, int r) {
9f95a23c 437 ceph_assert(ceph_mutex_is_locked(m_lock));
11fdf7f2 438 ceph_assert(!m_actions_contexts.empty());
7c673cae
FG
439
440 ActionContexts action_contexts(std::move(m_actions_contexts.front()));
441 m_actions_contexts.pop_front();
442 m_state = next_state;
443
9f95a23c 444 m_lock.unlock();
7c673cae
FG
445 for (auto ctx : action_contexts.second) {
446 ctx->complete(r);
447 }
9f95a23c 448 m_lock.lock();
7c673cae
FG
449
450 if (!is_transition_state() && !m_actions_contexts.empty()) {
451 execute_next_action();
452 }
453}
454
455template <typename I>
456bool ManagedLock<I>::is_state_shutdown() const {
9f95a23c 457 ceph_assert(ceph_mutex_is_locked(m_lock));
7c673cae 458
11fdf7f2
TL
459 switch (m_state) {
460 case STATE_PRE_SHUTTING_DOWN:
461 case STATE_SHUTTING_DOWN:
462 case STATE_SHUTDOWN:
463 return true;
464 default:
465 break;
466 }
467
468 return (!m_actions_contexts.empty() &&
469 m_actions_contexts.back().first == ACTION_SHUT_DOWN);
7c673cae
FG
470}
471
472template <typename I>
473void ManagedLock<I>::send_acquire_lock() {
9f95a23c 474 ceph_assert(ceph_mutex_is_locked(m_lock));
7c673cae
FG
475 if (m_state == STATE_LOCKED) {
476 complete_active_action(STATE_LOCKED, 0);
477 return;
478 }
479
480 ldout(m_cct, 10) << dendl;
7c673cae
FG
481
482 uint64_t watch_handle = m_watcher->get_watch_handle();
483 if (watch_handle == 0) {
1e59de90
TL
484 if (m_watcher->is_blocklisted()) {
485 lderr(m_cct) << "watcher not registered - client blocklisted" << dendl;
486 complete_active_action(STATE_UNLOCKED, -EBLOCKLISTED);
487 } else {
488 lderr(m_cct) << "watcher not registered - delaying request" << dendl;
489 m_state = STATE_WAITING_FOR_REGISTER;
91327a77 490
1e59de90
TL
491 // shut down might race w/ release/re-acquire of the lock
492 if (is_state_shutdown()) {
493 complete_active_action(STATE_UNLOCKED, -ERESTART);
494 }
91327a77 495 }
7c673cae
FG
496 return;
497 }
91327a77
AA
498
499 m_state = STATE_ACQUIRING;
7c673cae
FG
500 m_cookie = encode_lock_cookie(watch_handle);
501
9f95a23c 502 m_work_queue->queue(new LambdaContext([this](int r) {
7c673cae
FG
503 pre_acquire_lock_handler(create_context_callback<
504 ManagedLock<I>, &ManagedLock<I>::handle_pre_acquire_lock>(this));
505 }));
506}
507
508template <typename I>
509void ManagedLock<I>::handle_pre_acquire_lock(int r) {
11fdf7f2 510 ldout(m_cct, 10) << "r=" << r << dendl;
7c673cae
FG
511
512 if (r < 0) {
513 handle_acquire_lock(r);
514 return;
515 }
516
517 using managed_lock::AcquireRequest;
518 AcquireRequest<I>* req = AcquireRequest<I>::create(
f67539c2
TL
519 m_ioctx, m_watcher, m_asio_engine, m_oid, m_cookie, m_mode == EXCLUSIVE,
520 m_blocklist_on_break_lock, m_blocklist_expire_seconds,
7c673cae
FG
521 create_context_callback<
522 ManagedLock<I>, &ManagedLock<I>::handle_acquire_lock>(this));
523 m_work_queue->queue(new C_SendLockRequest<AcquireRequest<I>>(req), 0);
524}
525
526template <typename I>
527void ManagedLock<I>::handle_acquire_lock(int r) {
11fdf7f2 528 ldout(m_cct, 10) << "r=" << r << dendl;
7c673cae 529
f67539c2 530 if (r == -EBUSY || r == -EAGAIN || r == -EROFS) {
11fdf7f2 531 ldout(m_cct, 5) << "unable to acquire exclusive lock" << dendl;
7c673cae 532 } else if (r < 0) {
f67539c2 533 lderr(m_cct) << "failed to acquire exclusive lock: " << cpp_strerror(r)
7c673cae
FG
534 << dendl;
535 } else {
11fdf7f2 536 ldout(m_cct, 5) << "successfully acquired exclusive lock" << dendl;
7c673cae
FG
537 }
538
539 m_post_next_state = (r < 0 ? STATE_UNLOCKED : STATE_LOCKED);
540
9f95a23c 541 m_work_queue->queue(new LambdaContext([this, r](int ret) {
7c673cae
FG
542 post_acquire_lock_handler(r, create_context_callback<
543 ManagedLock<I>, &ManagedLock<I>::handle_post_acquire_lock>(this));
544 }));
545}
546
547template <typename I>
548void ManagedLock<I>::handle_post_acquire_lock(int r) {
11fdf7f2 549 ldout(m_cct, 10) << "r=" << r << dendl;
7c673cae 550
9f95a23c 551 std::lock_guard locker{m_lock};
7c673cae
FG
552
553 if (r < 0 && m_post_next_state == STATE_LOCKED) {
554 // release_lock without calling pre and post handlers
555 revert_to_unlock_state(r);
556 } else if (r != -ECANCELED) {
557 // fail the lock request
558 complete_active_action(m_post_next_state, r);
559 }
560}
561
562template <typename I>
563void ManagedLock<I>::revert_to_unlock_state(int r) {
11fdf7f2 564 ldout(m_cct, 10) << "r=" << r << dendl;
7c673cae
FG
565
566 using managed_lock::ReleaseRequest;
567 ReleaseRequest<I>* req = ReleaseRequest<I>::create(m_ioctx, m_watcher,
568 m_work_queue, m_oid, m_cookie,
9f95a23c
TL
569 new LambdaContext([this, r](int ret) {
570 std::lock_guard locker{m_lock};
11fdf7f2 571 ceph_assert(ret == 0);
7c673cae
FG
572 complete_active_action(STATE_UNLOCKED, r);
573 }));
574 m_work_queue->queue(new C_SendLockRequest<ReleaseRequest<I>>(req));
575}
576
577template <typename I>
578void ManagedLock<I>::send_reacquire_lock() {
9f95a23c 579 ceph_assert(ceph_mutex_is_locked(m_lock));
7c673cae
FG
580
581 if (m_state != STATE_LOCKED) {
582 complete_active_action(m_state, 0);
583 return;
584 }
585
91327a77
AA
586 ldout(m_cct, 10) << dendl;
587 m_state = STATE_REACQUIRING;
588
7c673cae
FG
589 uint64_t watch_handle = m_watcher->get_watch_handle();
590 if (watch_handle == 0) {
91327a77 591 // watch (re)failed while recovering
11fdf7f2 592 lderr(m_cct) << "aborting reacquire due to invalid watch handle"
91327a77
AA
593 << dendl;
594
595 // treat double-watch failure as a lost lock and invoke the
596 // release/acquire handlers
597 release_acquire_lock();
598 complete_active_action(STATE_LOCKED, 0);
599 return;
7c673cae
FG
600 }
601
602 m_new_cookie = encode_lock_cookie(watch_handle);
f67539c2 603 if (m_cookie == m_new_cookie && m_blocklist_on_break_lock) {
11fdf7f2 604 ldout(m_cct, 10) << "skipping reacquire since cookie still valid"
7c673cae 605 << dendl;
91327a77
AA
606 auto ctx = create_context_callback<
607 ManagedLock, &ManagedLock<I>::handle_no_op_reacquire_lock>(this);
608 post_reacquire_lock_handler(0, ctx);
7c673cae
FG
609 return;
610 }
611
31f18b77
FG
612 auto ctx = create_context_callback<
613 ManagedLock, &ManagedLock<I>::handle_reacquire_lock>(this);
9f95a23c 614 ctx = new LambdaContext([this, ctx](int r) {
31f18b77
FG
615 post_reacquire_lock_handler(r, ctx);
616 });
617
7c673cae
FG
618 using managed_lock::ReacquireRequest;
619 ReacquireRequest<I>* req = ReacquireRequest<I>::create(m_ioctx, m_oid,
31f18b77 620 m_cookie, m_new_cookie, m_mode == EXCLUSIVE, ctx);
7c673cae
FG
621 m_work_queue->queue(new C_SendLockRequest<ReacquireRequest<I>>(req));
622}
623
624template <typename I>
625void ManagedLock<I>::handle_reacquire_lock(int r) {
11fdf7f2 626 ldout(m_cct, 10) << "r=" << r << dendl;
7c673cae 627
9f95a23c 628 std::lock_guard locker{m_lock};
11fdf7f2 629 ceph_assert(m_state == STATE_REACQUIRING);
7c673cae
FG
630
631 if (r < 0) {
632 if (r == -EOPNOTSUPP) {
11fdf7f2 633 ldout(m_cct, 10) << "updating lock is not supported" << dendl;
7c673cae 634 } else {
11fdf7f2 635 lderr(m_cct) << "failed to update lock cookie: " << cpp_strerror(r)
7c673cae
FG
636 << dendl;
637 }
638
91327a77 639 release_acquire_lock();
7c673cae
FG
640 } else {
641 m_cookie = m_new_cookie;
642 }
643
91327a77
AA
644 complete_active_action(STATE_LOCKED, 0);
645}
646
647template <typename I>
648void ManagedLock<I>::handle_no_op_reacquire_lock(int r) {
649 ldout(m_cct, 10) << "r=" << r << dendl;
11fdf7f2
TL
650 ceph_assert(m_state == STATE_REACQUIRING);
651 ceph_assert(r >= 0);
91327a77
AA
652 complete_active_action(STATE_LOCKED, 0);
653}
654
655template <typename I>
656void ManagedLock<I>::release_acquire_lock() {
9f95a23c 657 assert(ceph_mutex_is_locked(m_lock));
91327a77
AA
658
659 if (!is_state_shutdown()) {
660 // queue a release and re-acquire of the lock since cookie cannot
661 // be updated on older OSDs
662 execute_action(ACTION_RELEASE_LOCK, nullptr);
663
664 ceph_assert(!m_actions_contexts.empty());
665 ActionContexts &action_contexts(m_actions_contexts.front());
666
667 // reacquire completes when the request lock completes
668 Contexts contexts;
669 std::swap(contexts, action_contexts.second);
670 if (contexts.empty()) {
671 execute_action(ACTION_ACQUIRE_LOCK, nullptr);
672 } else {
673 for (auto ctx : contexts) {
674 execute_action(ACTION_ACQUIRE_LOCK, ctx);
675 }
676 }
677 }
7c673cae
FG
678}
679
680template <typename I>
681void ManagedLock<I>::send_release_lock() {
9f95a23c 682 ceph_assert(ceph_mutex_is_locked(m_lock));
7c673cae
FG
683 if (m_state == STATE_UNLOCKED) {
684 complete_active_action(STATE_UNLOCKED, 0);
685 return;
686 }
687
688 ldout(m_cct, 10) << dendl;
689 m_state = STATE_PRE_RELEASING;
690
9f95a23c 691 m_work_queue->queue(new LambdaContext([this](int r) {
7c673cae
FG
692 pre_release_lock_handler(false, create_context_callback<
693 ManagedLock<I>, &ManagedLock<I>::handle_pre_release_lock>(this));
694 }));
695}
696
697template <typename I>
698void ManagedLock<I>::handle_pre_release_lock(int r) {
11fdf7f2 699 ldout(m_cct, 10) << "r=" << r << dendl;
7c673cae
FG
700
701 {
9f95a23c 702 std::lock_guard locker{m_lock};
11fdf7f2 703 ceph_assert(m_state == STATE_PRE_RELEASING);
7c673cae
FG
704 m_state = STATE_RELEASING;
705 }
706
707 if (r < 0) {
708 handle_release_lock(r);
709 return;
710 }
711
712 using managed_lock::ReleaseRequest;
713 ReleaseRequest<I>* req = ReleaseRequest<I>::create(m_ioctx, m_watcher,
714 m_work_queue, m_oid, m_cookie,
715 create_context_callback<
716 ManagedLock<I>, &ManagedLock<I>::handle_release_lock>(this));
717 m_work_queue->queue(new C_SendLockRequest<ReleaseRequest<I>>(req), 0);
718}
719
720template <typename I>
721void ManagedLock<I>::handle_release_lock(int r) {
11fdf7f2 722 ldout(m_cct, 10) << "r=" << r << dendl;
7c673cae 723
9f95a23c 724 std::lock_guard locker{m_lock};
11fdf7f2 725 ceph_assert(m_state == STATE_RELEASING);
7c673cae 726
f67539c2 727 if (r >= 0 || r == -EBLOCKLISTED || r == -ENOENT) {
7c673cae 728 m_cookie = "";
91327a77
AA
729 m_post_next_state = STATE_UNLOCKED;
730 } else {
731 m_post_next_state = STATE_LOCKED;
7c673cae
FG
732 }
733
9f95a23c 734 m_work_queue->queue(new LambdaContext([this, r](int ret) {
7c673cae
FG
735 post_release_lock_handler(false, r, create_context_callback<
736 ManagedLock<I>, &ManagedLock<I>::handle_post_release_lock>(this));
737 }));
738}
739
740template <typename I>
741void ManagedLock<I>::handle_post_release_lock(int r) {
11fdf7f2 742 ldout(m_cct, 10) << "r=" << r << dendl;
7c673cae 743
9f95a23c 744 std::lock_guard locker{m_lock};
7c673cae
FG
745 complete_active_action(m_post_next_state, r);
746}
747
748template <typename I>
749void ManagedLock<I>::send_shutdown() {
750 ldout(m_cct, 10) << dendl;
9f95a23c 751 ceph_assert(ceph_mutex_is_locked(m_lock));
7c673cae
FG
752 if (m_state == STATE_UNLOCKED) {
753 m_state = STATE_SHUTTING_DOWN;
9f95a23c 754 m_work_queue->queue(new LambdaContext([this](int r) {
7c673cae
FG
755 shutdown_handler(r, create_context_callback<
756 ManagedLock<I>, &ManagedLock<I>::handle_shutdown>(this));
757 }));
758 return;
759 }
760
11fdf7f2 761 ceph_assert(m_state == STATE_LOCKED);
7c673cae
FG
762 m_state = STATE_PRE_SHUTTING_DOWN;
763
9f95a23c 764 m_lock.unlock();
7c673cae 765 m_work_queue->queue(new C_ShutDownRelease(this), 0);
9f95a23c 766 m_lock.lock();
7c673cae
FG
767}
768
769template <typename I>
770void ManagedLock<I>::handle_shutdown(int r) {
11fdf7f2 771 ldout(m_cct, 10) << "r=" << r << dendl;
7c673cae
FG
772
773 wait_for_tracked_ops(r);
774}
775
776template <typename I>
777void ManagedLock<I>::send_shutdown_release() {
778 ldout(m_cct, 10) << dendl;
779
9f95a23c 780 std::lock_guard locker{m_lock};
7c673cae 781
9f95a23c 782 m_work_queue->queue(new LambdaContext([this](int r) {
7c673cae
FG
783 pre_release_lock_handler(true, create_context_callback<
784 ManagedLock<I>, &ManagedLock<I>::handle_shutdown_pre_release>(this));
785 }));
786}
787
788template <typename I>
789void ManagedLock<I>::handle_shutdown_pre_release(int r) {
11fdf7f2 790 ldout(m_cct, 10) << "r=" << r << dendl;
7c673cae
FG
791
792 std::string cookie;
793 {
9f95a23c 794 std::lock_guard locker{m_lock};
7c673cae
FG
795 cookie = m_cookie;
796
11fdf7f2 797 ceph_assert(m_state == STATE_PRE_SHUTTING_DOWN);
7c673cae
FG
798 m_state = STATE_SHUTTING_DOWN;
799 }
800
801 using managed_lock::ReleaseRequest;
802 ReleaseRequest<I>* req = ReleaseRequest<I>::create(m_ioctx, m_watcher,
803 m_work_queue, m_oid, cookie,
9f95a23c 804 new LambdaContext([this, r](int l) {
11fdf7f2
TL
805 int rst = r < 0 ? r : l;
806 post_release_lock_handler(true, rst, create_context_callback<
7c673cae
FG
807 ManagedLock<I>, &ManagedLock<I>::handle_shutdown_post_release>(this));
808 }));
809 req->send();
810
811}
812
813template <typename I>
814void ManagedLock<I>::handle_shutdown_post_release(int r) {
11fdf7f2 815 ldout(m_cct, 10) << "r=" << r << dendl;
7c673cae
FG
816
817 wait_for_tracked_ops(r);
818}
819
820template <typename I>
821void ManagedLock<I>::wait_for_tracked_ops(int r) {
11fdf7f2 822 ldout(m_cct, 10) << "r=" << r << dendl;
7c673cae 823
9f95a23c 824 Context *ctx = new LambdaContext([this, r](int ret) {
7c673cae
FG
825 complete_shutdown(r);
826 });
827
828 m_async_op_tracker.wait_for_ops(ctx);
829}
830
831template <typename I>
832void ManagedLock<I>::complete_shutdown(int r) {
11fdf7f2 833 ldout(m_cct, 10) << "r=" << r << dendl;
7c673cae
FG
834
835 if (r < 0) {
836 lderr(m_cct) << "failed to shut down lock: " << cpp_strerror(r)
837 << dendl;
838 }
839
840 ActionContexts action_contexts;
841 {
9f95a23c
TL
842 std::lock_guard locker{m_lock};
843 ceph_assert(ceph_mutex_is_locked(m_lock));
11fdf7f2 844 ceph_assert(m_actions_contexts.size() == 1);
7c673cae
FG
845
846 action_contexts = std::move(m_actions_contexts.front());
847 m_actions_contexts.pop_front();
848 m_state = STATE_SHUTDOWN;
849 }
850
851 // expect to be destroyed after firing callback
852 for (auto ctx : action_contexts.second) {
853 ctx->complete(r);
854 }
855}
856
857} // namespace librbd
858
859template class librbd::ManagedLock<librbd::ImageCtx>;