]> git.proxmox.com Git - ceph.git/blob - ceph/src/tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.cc
b26ac05e9429fbfb55bd8262dd74935f44126b5f
[ceph.git] / ceph / src / tools / rbd_mirror / image_replayer / PrepareLocalImageRequest.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.h"
5 #include "include/rados/librados.hpp"
6 #include "cls/rbd/cls_rbd_client.h"
7 #include "common/errno.h"
8 #include "librbd/ImageCtx.h"
9 #include "librbd/Journal.h"
10 #include "librbd/Utils.h"
11 #include "tools/rbd_mirror/Threads.h"
12 #include <type_traits>
13
14 #define dout_context g_ceph_context
15 #define dout_subsys ceph_subsys_rbd_mirror
16 #undef dout_prefix
17 #define dout_prefix *_dout << "rbd::mirror::image_replayer::" \
18 << "PrepareLocalImageRequest: " << this << " " \
19 << __func__ << ": "
20
21 namespace rbd {
22 namespace mirror {
23 namespace image_replayer {
24
25 using librbd::util::create_context_callback;
26 using librbd::util::create_rados_callback;
27
28 template <typename I>
29 void PrepareLocalImageRequest<I>::send() {
30 dout(20) << dendl;
31 get_local_image_id();
32 }
33
34 template <typename I>
35 void PrepareLocalImageRequest<I>::get_local_image_id() {
36 dout(20) << dendl;
37
38 // attempt to cross-reference a local image by the global image id
39 librados::ObjectReadOperation op;
40 librbd::cls_client::mirror_image_get_image_id_start(&op, m_global_image_id);
41
42 m_out_bl.clear();
43 librados::AioCompletion *aio_comp = create_rados_callback<
44 PrepareLocalImageRequest<I>,
45 &PrepareLocalImageRequest<I>::handle_get_local_image_id>(
46 this);
47 int r = m_io_ctx.aio_operate(RBD_MIRRORING, aio_comp, &op, &m_out_bl);
48 assert(r == 0);
49 aio_comp->release();
50 }
51
52 template <typename I>
53 void PrepareLocalImageRequest<I>::handle_get_local_image_id(int r) {
54 if (r == 0) {
55 bufferlist::iterator iter = m_out_bl.begin();
56 r = librbd::cls_client::mirror_image_get_image_id_finish(
57 &iter, m_local_image_id);
58 }
59
60 dout(20) << "r=" << r << ", "
61 << "local_image_id=" << *m_local_image_id << dendl;
62
63 if (r < 0) {
64 if (r == -ENOENT) {
65 dout(10) << "image not registered locally" << dendl;
66 } else {
67 derr << "failed to retrieve local image id: " << cpp_strerror(r)
68 << dendl;
69 }
70 finish(r);
71 return;
72 }
73
74 get_mirror_state();
75 }
76
77 template <typename I>
78 void PrepareLocalImageRequest<I>::get_mirror_state() {
79 dout(20) << dendl;
80
81 librados::ObjectReadOperation op;
82 librbd::cls_client::mirror_image_get_start(&op, *m_local_image_id);
83
84 m_out_bl.clear();
85 librados::AioCompletion *aio_comp = create_rados_callback<
86 PrepareLocalImageRequest<I>,
87 &PrepareLocalImageRequest<I>::handle_get_mirror_state>(this);
88 int r = m_io_ctx.aio_operate(RBD_MIRRORING, aio_comp, &op, &m_out_bl);
89 assert(r == 0);
90 aio_comp->release();
91 }
92
93 template <typename I>
94 void PrepareLocalImageRequest<I>::handle_get_mirror_state(int r) {
95 dout(20) << ": r=" << r << dendl;
96
97 cls::rbd::MirrorImage mirror_image;
98 if (r == 0) {
99 bufferlist::iterator iter = m_out_bl.begin();
100 r = librbd::cls_client::mirror_image_get_finish(&iter, &mirror_image);
101 }
102
103 if (r < 0) {
104 derr << "failed to retrieve image mirror state: " << cpp_strerror(r)
105 << dendl;
106 finish(r);
107 return;
108 }
109
110 // TODO save current mirror state to determine if we should
111 // delete a partially formed image
112 // (e.g. MIRROR_IMAGE_STATE_CREATING/DELETING)
113
114 get_tag_owner();
115 }
116
117 template <typename I>
118 void PrepareLocalImageRequest<I>::get_tag_owner() {
119 // deduce the class type for the journal to support unit tests
120 using Journal = typename std::decay<
121 typename std::remove_pointer<decltype(std::declval<I>().journal)>
122 ::type>::type;
123
124 dout(20) << dendl;
125
126 Context *ctx = create_context_callback<
127 PrepareLocalImageRequest<I>,
128 &PrepareLocalImageRequest<I>::handle_get_tag_owner>(this);
129 Journal::get_tag_owner(m_io_ctx, *m_local_image_id, m_tag_owner,
130 m_work_queue, ctx);
131 }
132
133 template <typename I>
134 void PrepareLocalImageRequest<I>::handle_get_tag_owner(int r) {
135 dout(20) << "r=" << r << ", "
136 << "tag_owner=" << *m_tag_owner << dendl;
137
138 if (r < 0) {
139 derr << "failed to retrieve journal tag owner: " << cpp_strerror(r)
140 << dendl;
141 finish(r);
142 return;
143 }
144
145 finish(0);
146 }
147
148 template <typename I>
149 void PrepareLocalImageRequest<I>::finish(int r) {
150 dout(20) << "r=" << r << dendl;
151
152 m_on_finish->complete(r);
153 delete this;
154 }
155
156 } // namespace image_replayer
157 } // namespace mirror
158 } // namespace rbd
159
160 template class rbd::mirror::image_replayer::PrepareLocalImageRequest<librbd::ImageCtx>;