]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/ImageState.cc
Import ceph 15.2.8
[ceph.git] / ceph / src / librbd / ImageState.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/ImageState.h"
5#include "include/rbd/librbd.hpp"
6#include "common/dout.h"
7#include "common/errno.h"
8#include "common/Cond.h"
9#include "common/WorkQueue.h"
10#include "librbd/ImageCtx.h"
11#include "librbd/Utils.h"
12#include "librbd/image/CloseRequest.h"
13#include "librbd/image/OpenRequest.h"
14#include "librbd/image/RefreshRequest.h"
15#include "librbd/image/SetSnapRequest.h"
16
17#define dout_subsys ceph_subsys_rbd
18#undef dout_prefix
19#define dout_prefix *_dout << "librbd::ImageState: " << this << " "
20
21namespace librbd {
22
23using util::create_async_context_callback;
24using util::create_context_callback;
25
26class ImageUpdateWatchers {
27public:
28
11fdf7f2 29 explicit ImageUpdateWatchers(CephContext *cct) : m_cct(cct),
9f95a23c 30 m_lock(ceph::make_mutex(util::unique_lock_name("librbd::ImageUpdateWatchers::m_lock", this))) {
7c673cae
FG
31 }
32
33 ~ImageUpdateWatchers() {
11fdf7f2
TL
34 ceph_assert(m_watchers.empty());
35 ceph_assert(m_in_flight.empty());
36 ceph_assert(m_pending_unregister.empty());
37 ceph_assert(m_on_shut_down_finish == nullptr);
7c673cae
FG
38
39 destroy_work_queue();
40 }
41
42 void flush(Context *on_finish) {
43 ldout(m_cct, 20) << "ImageUpdateWatchers::" << __func__ << dendl;
44 {
9f95a23c 45 std::lock_guard locker{m_lock};
7c673cae 46 if (!m_in_flight.empty()) {
9f95a23c 47 Context *ctx = new LambdaContext(
7c673cae
FG
48 [this, on_finish](int r) {
49 ldout(m_cct, 20) << "ImageUpdateWatchers::" << __func__
50 << ": completing flush" << dendl;
51 on_finish->complete(r);
52 });
53 m_work_queue->queue(ctx, 0);
54 return;
55 }
56 }
57 ldout(m_cct, 20) << "ImageUpdateWatchers::" << __func__
58 << ": completing flush" << dendl;
59 on_finish->complete(0);
60 }
61
62 void shut_down(Context *on_finish) {
63 ldout(m_cct, 20) << "ImageUpdateWatchers::" << __func__ << dendl;
64 {
9f95a23c 65 std::lock_guard locker{m_lock};
11fdf7f2 66 ceph_assert(m_on_shut_down_finish == nullptr);
7c673cae
FG
67 m_watchers.clear();
68 if (!m_in_flight.empty()) {
69 m_on_shut_down_finish = on_finish;
70 return;
71 }
72 }
73 ldout(m_cct, 20) << "ImageUpdateWatchers::" << __func__
74 << ": completing shut down" << dendl;
75 on_finish->complete(0);
76 }
77
78 void register_watcher(UpdateWatchCtx *watcher, uint64_t *handle) {
79 ldout(m_cct, 20) << __func__ << ": watcher=" << watcher << dendl;
80
9f95a23c 81 std::lock_guard locker{m_lock};
11fdf7f2 82 ceph_assert(m_on_shut_down_finish == nullptr);
7c673cae
FG
83
84 create_work_queue();
85
86 *handle = m_next_handle++;
87 m_watchers.insert(std::make_pair(*handle, watcher));
88 }
89
90 void unregister_watcher(uint64_t handle, Context *on_finish) {
91 ldout(m_cct, 20) << "ImageUpdateWatchers::" << __func__ << ": handle="
92 << handle << dendl;
93 int r = 0;
94 {
9f95a23c 95 std::lock_guard locker{m_lock};
7c673cae
FG
96 auto it = m_watchers.find(handle);
97 if (it == m_watchers.end()) {
98 r = -ENOENT;
99 } else {
100 if (m_in_flight.find(handle) != m_in_flight.end()) {
11fdf7f2 101 ceph_assert(m_pending_unregister.find(handle) == m_pending_unregister.end());
7c673cae
FG
102 m_pending_unregister[handle] = on_finish;
103 on_finish = nullptr;
104 }
105 m_watchers.erase(it);
106 }
107 }
108
109 if (on_finish) {
110 ldout(m_cct, 20) << "ImageUpdateWatchers::" << __func__
111 << ": completing unregister" << dendl;
112 on_finish->complete(r);
113 }
114 }
115
116 void notify() {
117 ldout(m_cct, 20) << "ImageUpdateWatchers::" << __func__ << dendl;
118
9f95a23c 119 std::lock_guard locker{m_lock};
7c673cae
FG
120 for (auto it : m_watchers) {
121 send_notify(it.first, it.second);
122 }
123 }
124
125 void send_notify(uint64_t handle, UpdateWatchCtx *watcher) {
9f95a23c 126 ceph_assert(ceph_mutex_is_locked(m_lock));
7c673cae
FG
127
128 ldout(m_cct, 20) << "ImageUpdateWatchers::" << __func__ << ": handle="
129 << handle << ", watcher=" << watcher << dendl;
130
131 m_in_flight.insert(handle);
132
9f95a23c 133 Context *ctx = new LambdaContext(
7c673cae
FG
134 [this, handle, watcher](int r) {
135 handle_notify(handle, watcher);
136 });
137
138 m_work_queue->queue(ctx, 0);
139 }
140
141 void handle_notify(uint64_t handle, UpdateWatchCtx *watcher) {
142
143 ldout(m_cct, 20) << "ImageUpdateWatchers::" << __func__ << ": handle="
144 << handle << ", watcher=" << watcher << dendl;
145
146 watcher->handle_notify();
147
148 Context *on_unregister_finish = nullptr;
149 Context *on_shut_down_finish = nullptr;
150
151 {
9f95a23c 152 std::lock_guard locker{m_lock};
7c673cae
FG
153
154 auto in_flight_it = m_in_flight.find(handle);
11fdf7f2 155 ceph_assert(in_flight_it != m_in_flight.end());
7c673cae
FG
156 m_in_flight.erase(in_flight_it);
157
158 // If there is no more in flight notifications for this watcher
159 // and it is pending unregister, complete it now.
160 if (m_in_flight.find(handle) == m_in_flight.end()) {
161 auto it = m_pending_unregister.find(handle);
162 if (it != m_pending_unregister.end()) {
163 on_unregister_finish = it->second;
164 m_pending_unregister.erase(it);
165 }
166 }
167
168 if (m_in_flight.empty()) {
11fdf7f2 169 ceph_assert(m_pending_unregister.empty());
7c673cae
FG
170 if (m_on_shut_down_finish != nullptr) {
171 std::swap(m_on_shut_down_finish, on_shut_down_finish);
172 }
173 }
174 }
175
176 if (on_unregister_finish != nullptr) {
177 ldout(m_cct, 20) << "ImageUpdateWatchers::" << __func__
178 << ": completing unregister" << dendl;
179 on_unregister_finish->complete(0);
180 }
181
182 if (on_shut_down_finish != nullptr) {
183 ldout(m_cct, 20) << "ImageUpdateWatchers::" << __func__
184 << ": completing shut down" << dendl;
185 on_shut_down_finish->complete(0);
186 }
187 }
188
189private:
190 class ThreadPoolSingleton : public ThreadPool {
191 public:
192 explicit ThreadPoolSingleton(CephContext *cct)
193 : ThreadPool(cct, "librbd::ImageUpdateWatchers::thread_pool", "tp_librbd",
194 1) {
195 start();
196 }
197 ~ThreadPoolSingleton() override {
198 stop();
199 }
200 };
201
202 CephContext *m_cct;
9f95a23c 203 ceph::mutex m_lock;
7c673cae
FG
204 ContextWQ *m_work_queue = nullptr;
205 std::map<uint64_t, UpdateWatchCtx*> m_watchers;
206 uint64_t m_next_handle = 0;
207 std::multiset<uint64_t> m_in_flight;
208 std::map<uint64_t, Context*> m_pending_unregister;
209 Context *m_on_shut_down_finish = nullptr;
210
211 void create_work_queue() {
212 if (m_work_queue != nullptr) {
213 return;
214 }
11fdf7f2
TL
215 auto& thread_pool = m_cct->lookup_or_create_singleton_object<
216 ThreadPoolSingleton>("librbd::ImageUpdateWatchers::thread_pool",
217 false, m_cct);
7c673cae 218 m_work_queue = new ContextWQ("librbd::ImageUpdateWatchers::op_work_queue",
11fdf7f2
TL
219 m_cct->_conf.get_val<uint64_t>("rbd_op_thread_timeout"),
220 &thread_pool);
7c673cae
FG
221 }
222
223 void destroy_work_queue() {
224 if (m_work_queue == nullptr) {
225 return;
226 }
227 m_work_queue->drain();
228 delete m_work_queue;
229 }
230};
231
232template <typename I>
233ImageState<I>::ImageState(I *image_ctx)
234 : m_image_ctx(image_ctx), m_state(STATE_UNINITIALIZED),
9f95a23c 235 m_lock(ceph::make_mutex(util::unique_lock_name("librbd::ImageState::m_lock", this))),
7c673cae 236 m_last_refresh(0), m_refresh_seq(0),
11fdf7f2 237 m_update_watchers(new ImageUpdateWatchers(image_ctx->cct)) {
7c673cae
FG
238}
239
240template <typename I>
241ImageState<I>::~ImageState() {
11fdf7f2 242 ceph_assert(m_state == STATE_UNINITIALIZED || m_state == STATE_CLOSED);
7c673cae
FG
243 delete m_update_watchers;
244}
245
246template <typename I>
11fdf7f2 247int ImageState<I>::open(uint64_t flags) {
7c673cae 248 C_SaferCond ctx;
11fdf7f2 249 open(flags, &ctx);
7c673cae
FG
250
251 int r = ctx.wait();
252 if (r < 0) {
253 delete m_image_ctx;
254 }
255 return r;
256}
257
258template <typename I>
11fdf7f2 259void ImageState<I>::open(uint64_t flags, Context *on_finish) {
7c673cae
FG
260 CephContext *cct = m_image_ctx->cct;
261 ldout(cct, 20) << __func__ << dendl;
262
9f95a23c 263 m_lock.lock();
11fdf7f2
TL
264 ceph_assert(m_state == STATE_UNINITIALIZED);
265 m_open_flags = flags;
7c673cae
FG
266
267 Action action(ACTION_TYPE_OPEN);
268 action.refresh_seq = m_refresh_seq;
269
270 execute_action_unlock(action, on_finish);
271}
272
273template <typename I>
274int ImageState<I>::close() {
275 C_SaferCond ctx;
276 close(&ctx);
277
278 int r = ctx.wait();
279 delete m_image_ctx;
280 return r;
281}
282
283template <typename I>
284void ImageState<I>::close(Context *on_finish) {
285 CephContext *cct = m_image_ctx->cct;
286 ldout(cct, 20) << __func__ << dendl;
287
9f95a23c 288 m_lock.lock();
11fdf7f2 289 ceph_assert(!is_closed());
7c673cae
FG
290
291 Action action(ACTION_TYPE_CLOSE);
292 action.refresh_seq = m_refresh_seq;
293 execute_action_unlock(action, on_finish);
294}
295
296template <typename I>
297void ImageState<I>::handle_update_notification() {
9f95a23c 298 std::lock_guard locker{m_lock};
7c673cae
FG
299 ++m_refresh_seq;
300
301 CephContext *cct = m_image_ctx->cct;
302 ldout(cct, 20) << __func__ << ": refresh_seq = " << m_refresh_seq << ", "
303 << "last_refresh = " << m_last_refresh << dendl;
304
9f95a23c
TL
305 switch (m_state) {
306 case STATE_UNINITIALIZED:
307 case STATE_CLOSED:
308 case STATE_OPENING:
309 case STATE_CLOSING:
310 ldout(cct, 5) << "dropping update notification to watchers" << dendl;
311 return;
312 default:
313 break;
7c673cae 314 }
9f95a23c
TL
315
316 m_update_watchers->notify();
7c673cae
FG
317}
318
319template <typename I>
320bool ImageState<I>::is_refresh_required() const {
9f95a23c 321 std::lock_guard locker{m_lock};
7c673cae
FG
322 return (m_last_refresh != m_refresh_seq || find_pending_refresh() != nullptr);
323}
324
325template <typename I>
326int ImageState<I>::refresh() {
327 C_SaferCond refresh_ctx;
328 refresh(&refresh_ctx);
329 return refresh_ctx.wait();
330}
331
332template <typename I>
333void ImageState<I>::refresh(Context *on_finish) {
334 CephContext *cct = m_image_ctx->cct;
335 ldout(cct, 20) << __func__ << dendl;
336
9f95a23c 337 m_lock.lock();
7c673cae 338 if (is_closed()) {
9f95a23c 339 m_lock.unlock();
7c673cae
FG
340 on_finish->complete(-ESHUTDOWN);
341 return;
342 }
343
344 Action action(ACTION_TYPE_REFRESH);
345 action.refresh_seq = m_refresh_seq;
346 execute_action_unlock(action, on_finish);
347}
348
349template <typename I>
350int ImageState<I>::refresh_if_required() {
351 C_SaferCond ctx;
352 {
9f95a23c 353 m_lock.lock();
7c673cae
FG
354 Action action(ACTION_TYPE_REFRESH);
355 action.refresh_seq = m_refresh_seq;
356
357 auto refresh_action = find_pending_refresh();
358 if (refresh_action != nullptr) {
359 // if a refresh is in-flight, delay until it is finished
360 action = *refresh_action;
361 } else if (m_last_refresh == m_refresh_seq) {
9f95a23c 362 m_lock.unlock();
7c673cae
FG
363 return 0;
364 } else if (is_closed()) {
9f95a23c 365 m_lock.unlock();
7c673cae
FG
366 return -ESHUTDOWN;
367 }
368
369 execute_action_unlock(action, &ctx);
370 }
371
372 return ctx.wait();
373}
374
375template <typename I>
376const typename ImageState<I>::Action *
377ImageState<I>::find_pending_refresh() const {
9f95a23c 378 ceph_assert(ceph_mutex_is_locked(m_lock));
7c673cae
FG
379
380 auto it = std::find_if(m_actions_contexts.rbegin(),
381 m_actions_contexts.rend(),
382 [](const ActionContexts& action_contexts) {
383 return (action_contexts.first == ACTION_TYPE_REFRESH);
384 });
385 if (it != m_actions_contexts.rend()) {
386 return &it->first;
387 }
388 return nullptr;
389}
390
391template <typename I>
11fdf7f2 392void ImageState<I>::snap_set(uint64_t snap_id, Context *on_finish) {
7c673cae 393 CephContext *cct = m_image_ctx->cct;
11fdf7f2 394 ldout(cct, 20) << __func__ << ": snap_id=" << snap_id << dendl;
7c673cae
FG
395
396 Action action(ACTION_TYPE_SET_SNAP);
11fdf7f2 397 action.snap_id = snap_id;
7c673cae 398
9f95a23c 399 m_lock.lock();
7c673cae
FG
400 execute_action_unlock(action, on_finish);
401}
402
403template <typename I>
404void ImageState<I>::prepare_lock(Context *on_ready) {
405 CephContext *cct = m_image_ctx->cct;
406 ldout(cct, 10) << __func__ << dendl;
407
9f95a23c 408 m_lock.lock();
7c673cae 409 if (is_closed()) {
9f95a23c 410 m_lock.unlock();
7c673cae
FG
411 on_ready->complete(-ESHUTDOWN);
412 return;
413 }
414
415 Action action(ACTION_TYPE_LOCK);
416 action.on_ready = on_ready;
417 execute_action_unlock(action, nullptr);
418}
419
420template <typename I>
421void ImageState<I>::handle_prepare_lock_complete() {
422 CephContext *cct = m_image_ctx->cct;
423 ldout(cct, 10) << __func__ << dendl;
424
9f95a23c 425 m_lock.lock();
7c673cae 426 if (m_state != STATE_PREPARING_LOCK) {
9f95a23c 427 m_lock.unlock();
7c673cae
FG
428 return;
429 }
430
431 complete_action_unlock(STATE_OPEN, 0);
432}
433
434template <typename I>
435int ImageState<I>::register_update_watcher(UpdateWatchCtx *watcher,
436 uint64_t *handle) {
437 CephContext *cct = m_image_ctx->cct;
438 ldout(cct, 20) << __func__ << dendl;
439
440 m_update_watchers->register_watcher(watcher, handle);
441
442 ldout(cct, 20) << __func__ << ": handle=" << *handle << dendl;
443 return 0;
444}
445
446template <typename I>
9f95a23c
TL
447void ImageState<I>::unregister_update_watcher(uint64_t handle,
448 Context *on_finish) {
7c673cae
FG
449 CephContext *cct = m_image_ctx->cct;
450 ldout(cct, 20) << __func__ << ": handle=" << handle << dendl;
451
9f95a23c
TL
452 m_update_watchers->unregister_watcher(handle, on_finish);
453}
454
455template <typename I>
456int ImageState<I>::unregister_update_watcher(uint64_t handle) {
7c673cae 457 C_SaferCond ctx;
9f95a23c 458 unregister_update_watcher(handle, &ctx);
7c673cae
FG
459 return ctx.wait();
460}
461
462template <typename I>
463void ImageState<I>::flush_update_watchers(Context *on_finish) {
464 CephContext *cct = m_image_ctx->cct;
465 ldout(cct, 20) << __func__ << dendl;
466
467 m_update_watchers->flush(on_finish);
468}
469
470template <typename I>
471void ImageState<I>::shut_down_update_watchers(Context *on_finish) {
472 CephContext *cct = m_image_ctx->cct;
473 ldout(cct, 20) << __func__ << dendl;
474
475 m_update_watchers->shut_down(on_finish);
476}
477
478template <typename I>
479bool ImageState<I>::is_transition_state() const {
480 switch (m_state) {
481 case STATE_UNINITIALIZED:
482 case STATE_OPEN:
483 case STATE_CLOSED:
484 return false;
485 case STATE_OPENING:
486 case STATE_CLOSING:
487 case STATE_REFRESHING:
488 case STATE_SETTING_SNAP:
489 case STATE_PREPARING_LOCK:
490 break;
491 }
492 return true;
493}
494
495template <typename I>
496bool ImageState<I>::is_closed() const {
9f95a23c 497 ceph_assert(ceph_mutex_is_locked(m_lock));
7c673cae
FG
498
499 return ((m_state == STATE_CLOSED) ||
500 (!m_actions_contexts.empty() &&
501 m_actions_contexts.back().first.action_type == ACTION_TYPE_CLOSE));
502}
503
504template <typename I>
505void ImageState<I>::append_context(const Action &action, Context *context) {
9f95a23c 506 ceph_assert(ceph_mutex_is_locked(m_lock));
7c673cae
FG
507
508 ActionContexts *action_contexts = nullptr;
509 for (auto &action_ctxs : m_actions_contexts) {
510 if (action == action_ctxs.first) {
511 action_contexts = &action_ctxs;
512 break;
513 }
514 }
515
516 if (action_contexts == nullptr) {
517 m_actions_contexts.push_back({action, {}});
518 action_contexts = &m_actions_contexts.back();
519 }
520
521 if (context != nullptr) {
522 action_contexts->second.push_back(context);
523 }
524}
525
526template <typename I>
527void ImageState<I>::execute_next_action_unlock() {
9f95a23c 528 ceph_assert(ceph_mutex_is_locked(m_lock));
11fdf7f2 529 ceph_assert(!m_actions_contexts.empty());
7c673cae
FG
530 switch (m_actions_contexts.front().first.action_type) {
531 case ACTION_TYPE_OPEN:
532 send_open_unlock();
533 return;
534 case ACTION_TYPE_CLOSE:
535 send_close_unlock();
536 return;
537 case ACTION_TYPE_REFRESH:
538 send_refresh_unlock();
539 return;
540 case ACTION_TYPE_SET_SNAP:
541 send_set_snap_unlock();
542 return;
543 case ACTION_TYPE_LOCK:
544 send_prepare_lock_unlock();
545 return;
546 }
11fdf7f2 547 ceph_abort();
7c673cae
FG
548}
549
550template <typename I>
551void ImageState<I>::execute_action_unlock(const Action &action,
552 Context *on_finish) {
9f95a23c 553 ceph_assert(ceph_mutex_is_locked(m_lock));
7c673cae
FG
554
555 append_context(action, on_finish);
556 if (!is_transition_state()) {
557 execute_next_action_unlock();
558 } else {
9f95a23c 559 m_lock.unlock();
7c673cae
FG
560 }
561}
562
563template <typename I>
564void ImageState<I>::complete_action_unlock(State next_state, int r) {
9f95a23c 565 ceph_assert(ceph_mutex_is_locked(m_lock));
11fdf7f2 566 ceph_assert(!m_actions_contexts.empty());
7c673cae
FG
567
568 ActionContexts action_contexts(std::move(m_actions_contexts.front()));
569 m_actions_contexts.pop_front();
570
571 m_state = next_state;
9f95a23c 572 m_lock.unlock();
7c673cae
FG
573
574 for (auto ctx : action_contexts.second) {
575 ctx->complete(r);
576 }
577
578 if (next_state != STATE_UNINITIALIZED && next_state != STATE_CLOSED) {
9f95a23c 579 m_lock.lock();
7c673cae
FG
580 if (!is_transition_state() && !m_actions_contexts.empty()) {
581 execute_next_action_unlock();
582 } else {
9f95a23c 583 m_lock.unlock();
7c673cae
FG
584 }
585 }
586}
587
588template <typename I>
589void ImageState<I>::send_open_unlock() {
9f95a23c 590 ceph_assert(ceph_mutex_is_locked(m_lock));
7c673cae
FG
591 CephContext *cct = m_image_ctx->cct;
592 ldout(cct, 10) << this << " " << __func__ << dendl;
593
594 m_state = STATE_OPENING;
595
596 Context *ctx = create_async_context_callback(
597 *m_image_ctx, create_context_callback<
598 ImageState<I>, &ImageState<I>::handle_open>(this));
599 image::OpenRequest<I> *req = image::OpenRequest<I>::create(
11fdf7f2 600 m_image_ctx, m_open_flags, ctx);
7c673cae 601
9f95a23c 602 m_lock.unlock();
7c673cae
FG
603 req->send();
604}
605
606template <typename I>
607void ImageState<I>::handle_open(int r) {
608 CephContext *cct = m_image_ctx->cct;
609 ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl;
610
611 if (r < 0 && r != -ENOENT) {
612 lderr(cct) << "failed to open image: " << cpp_strerror(r) << dendl;
613 }
614
9f95a23c 615 m_lock.lock();
7c673cae
FG
616 complete_action_unlock(r < 0 ? STATE_UNINITIALIZED : STATE_OPEN, r);
617}
618
619template <typename I>
620void ImageState<I>::send_close_unlock() {
9f95a23c 621 ceph_assert(ceph_mutex_is_locked(m_lock));
7c673cae
FG
622 CephContext *cct = m_image_ctx->cct;
623 ldout(cct, 10) << this << " " << __func__ << dendl;
624
625 m_state = STATE_CLOSING;
626
627 Context *ctx = create_context_callback<
628 ImageState<I>, &ImageState<I>::handle_close>(this);
629 image::CloseRequest<I> *req = image::CloseRequest<I>::create(
630 m_image_ctx, ctx);
631
9f95a23c 632 m_lock.unlock();
7c673cae
FG
633 req->send();
634}
635
636template <typename I>
637void ImageState<I>::handle_close(int r) {
638 CephContext *cct = m_image_ctx->cct;
639 ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl;
640
641 if (r < 0) {
642 lderr(cct) << "error occurred while closing image: " << cpp_strerror(r)
643 << dendl;
644 }
645
9f95a23c 646 m_lock.lock();
7c673cae
FG
647 complete_action_unlock(STATE_CLOSED, r);
648}
649
650template <typename I>
651void ImageState<I>::send_refresh_unlock() {
9f95a23c 652 ceph_assert(ceph_mutex_is_locked(m_lock));
7c673cae
FG
653 CephContext *cct = m_image_ctx->cct;
654 ldout(cct, 10) << this << " " << __func__ << dendl;
655
656 m_state = STATE_REFRESHING;
11fdf7f2 657 ceph_assert(!m_actions_contexts.empty());
7c673cae 658 auto &action_context = m_actions_contexts.front().first;
11fdf7f2 659 ceph_assert(action_context.action_type == ACTION_TYPE_REFRESH);
7c673cae
FG
660
661 Context *ctx = create_async_context_callback(
662 *m_image_ctx, create_context_callback<
663 ImageState<I>, &ImageState<I>::handle_refresh>(this));
664 image::RefreshRequest<I> *req = image::RefreshRequest<I>::create(
665 *m_image_ctx, false, false, ctx);
666
9f95a23c 667 m_lock.unlock();
7c673cae
FG
668 req->send();
669}
670
671template <typename I>
672void ImageState<I>::handle_refresh(int r) {
673 CephContext *cct = m_image_ctx->cct;
674 ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl;
675
9f95a23c 676 m_lock.lock();
11fdf7f2 677 ceph_assert(!m_actions_contexts.empty());
7c673cae
FG
678
679 ActionContexts &action_contexts(m_actions_contexts.front());
11fdf7f2
TL
680 ceph_assert(action_contexts.first.action_type == ACTION_TYPE_REFRESH);
681 ceph_assert(m_last_refresh <= action_contexts.first.refresh_seq);
7c673cae
FG
682
683 if (r == -ERESTART) {
684 ldout(cct, 5) << "incomplete refresh: not updating sequence" << dendl;
685 r = 0;
686 } else {
687 m_last_refresh = action_contexts.first.refresh_seq;
688 }
689
690 complete_action_unlock(STATE_OPEN, r);
691}
692
693template <typename I>
694void ImageState<I>::send_set_snap_unlock() {
9f95a23c 695 ceph_assert(ceph_mutex_is_locked(m_lock));
7c673cae
FG
696
697 m_state = STATE_SETTING_SNAP;
698
11fdf7f2 699 ceph_assert(!m_actions_contexts.empty());
7c673cae 700 ActionContexts &action_contexts(m_actions_contexts.front());
11fdf7f2 701 ceph_assert(action_contexts.first.action_type == ACTION_TYPE_SET_SNAP);
7c673cae
FG
702
703 CephContext *cct = m_image_ctx->cct;
704 ldout(cct, 10) << this << " " << __func__ << ": "
11fdf7f2 705 << "snap_id=" << action_contexts.first.snap_id << dendl;
7c673cae
FG
706
707 Context *ctx = create_async_context_callback(
708 *m_image_ctx, create_context_callback<
709 ImageState<I>, &ImageState<I>::handle_set_snap>(this));
710 image::SetSnapRequest<I> *req = image::SetSnapRequest<I>::create(
11fdf7f2 711 *m_image_ctx, action_contexts.first.snap_id, ctx);
7c673cae 712
9f95a23c 713 m_lock.unlock();
7c673cae
FG
714 req->send();
715}
716
717template <typename I>
718void ImageState<I>::handle_set_snap(int r) {
719 CephContext *cct = m_image_ctx->cct;
720 ldout(cct, 10) << this << " " << __func__ << " r=" << r << dendl;
721
722 if (r < 0 && r != -ENOENT) {
723 lderr(cct) << "failed to set snapshot: " << cpp_strerror(r) << dendl;
724 }
725
9f95a23c 726 m_lock.lock();
7c673cae
FG
727 complete_action_unlock(STATE_OPEN, r);
728}
729
730template <typename I>
731void ImageState<I>::send_prepare_lock_unlock() {
732 CephContext *cct = m_image_ctx->cct;
733 ldout(cct, 10) << this << " " << __func__ << dendl;
734
9f95a23c 735 ceph_assert(ceph_mutex_is_locked(m_lock));
7c673cae
FG
736 m_state = STATE_PREPARING_LOCK;
737
11fdf7f2 738 ceph_assert(!m_actions_contexts.empty());
7c673cae 739 ActionContexts &action_contexts(m_actions_contexts.front());
11fdf7f2 740 ceph_assert(action_contexts.first.action_type == ACTION_TYPE_LOCK);
7c673cae
FG
741
742 Context *on_ready = action_contexts.first.on_ready;
9f95a23c 743 m_lock.unlock();
7c673cae
FG
744
745 if (on_ready == nullptr) {
746 complete_action_unlock(STATE_OPEN, 0);
747 return;
748 }
749
750 // wake up the lock handler now that its safe to proceed
751 on_ready->complete(0);
752}
753
754} // namespace librbd
755
756template class librbd::ImageState<librbd::ImageCtx>;