]> git.proxmox.com Git - ceph.git/blob - ceph/src/tools/rbd_mirror/image_map/LoadRequest.cc
import ceph 16.2.7
[ceph.git] / ceph / src / tools / rbd_mirror / image_map / LoadRequest.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 "common/debug.h"
5 #include "common/errno.h"
6
7 #include "librbd/Utils.h"
8 #include "include/rbd_types.h"
9 #include "cls/rbd/cls_rbd_client.h"
10
11 #include "UpdateRequest.h"
12 #include "LoadRequest.h"
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_map::LoadRequest: " \
18 << this << " " << __func__
19
20 namespace rbd {
21 namespace mirror {
22 namespace image_map {
23
24 static const uint32_t MAX_RETURN = 1024;
25
26 using librbd::util::create_rados_callback;
27 using librbd::util::create_context_callback;
28
29 template<typename I>
30 LoadRequest<I>::LoadRequest(librados::IoCtx &ioctx,
31 std::map<std::string, cls::rbd::MirrorImageMap> *image_mapping,
32 Context *on_finish)
33 : m_ioctx(ioctx),
34 m_image_mapping(image_mapping),
35 m_on_finish(on_finish) {
36 }
37
38 template<typename I>
39 void LoadRequest<I>::send() {
40 dout(20) << dendl;
41
42 image_map_list();
43 }
44
45 template<typename I>
46 void LoadRequest<I>::image_map_list() {
47 dout(20) << dendl;
48
49 librados::ObjectReadOperation op;
50 librbd::cls_client::mirror_image_map_list_start(&op, m_start_after, MAX_RETURN);
51
52 librados::AioCompletion *aio_comp = create_rados_callback<
53 LoadRequest, &LoadRequest::handle_image_map_list>(this);
54
55 m_out_bl.clear();
56 int r = m_ioctx.aio_operate(RBD_MIRROR_LEADER, aio_comp, &op, &m_out_bl);
57 ceph_assert(r == 0);
58 aio_comp->release();
59 }
60
61 template<typename I>
62 void LoadRequest<I>::handle_image_map_list(int r) {
63 dout(20) << ": r=" << r << dendl;
64
65 std::map<std::string, cls::rbd::MirrorImageMap> image_mapping;
66 if (r == 0) {
67 auto it = m_out_bl.cbegin();
68 r = librbd::cls_client::mirror_image_map_list_finish(&it, &image_mapping);
69 }
70
71 if (r < 0) {
72 derr << ": failed to get image map: " << cpp_strerror(r) << dendl;
73 finish(r);
74 return;
75 }
76
77 m_image_mapping->insert(image_mapping.begin(), image_mapping.end());
78
79 if (image_mapping.size() == MAX_RETURN) {
80 m_start_after = image_mapping.rbegin()->first;
81 image_map_list();
82 return;
83 }
84
85 mirror_image_list();
86 }
87
88 template<typename I>
89 void LoadRequest<I>::mirror_image_list() {
90 dout(20) << dendl;
91
92 librados::ObjectReadOperation op;
93 librbd::cls_client::mirror_image_list_start(&op, m_start_after, MAX_RETURN);
94
95 m_out_bl.clear();
96 librados::AioCompletion *aio_comp = create_rados_callback<
97 LoadRequest<I>,
98 &LoadRequest<I>::handle_mirror_image_list>(this);
99 int r = m_ioctx.aio_operate(RBD_MIRRORING, aio_comp, &op, &m_out_bl);
100 ceph_assert(r == 0);
101 aio_comp->release();
102 }
103
104 template<typename I>
105 void LoadRequest<I>::handle_mirror_image_list(int r) {
106 dout(20) << ": r=" << r << dendl;
107
108 std::map<std::string, std::string> ids;
109 if (r == 0) {
110 auto it = m_out_bl.cbegin();
111 r = librbd::cls_client::mirror_image_list_finish(&it, &ids);
112 }
113
114 if (r < 0 && r != -ENOENT) {
115 derr << "failed to list mirrored images: " << cpp_strerror(r) << dendl;
116 finish(r);
117 return;
118 }
119
120 for (auto &id : ids) {
121 m_global_image_ids.emplace(id.second);
122 }
123
124 if (ids.size() == MAX_RETURN) {
125 m_start_after = ids.rbegin()->first;
126 mirror_image_list();
127 return;
128 }
129
130 cleanup_image_map();
131 }
132
133 template<typename I>
134 void LoadRequest<I>::cleanup_image_map() {
135 dout(20) << dendl;
136
137 std::set<std::string> map_removals;
138
139 auto it = m_image_mapping->begin();
140 while (it != m_image_mapping->end()) {
141 if (m_global_image_ids.count(it->first) > 0) {
142 ++it;
143 continue;
144 }
145 map_removals.emplace(it->first);
146 it = m_image_mapping->erase(it);
147 }
148
149 if (map_removals.size() == 0) {
150 finish(0);
151 return;
152 }
153
154 auto ctx = create_context_callback<
155 LoadRequest<I>,
156 &LoadRequest<I>::finish>(this);
157 image_map::UpdateRequest<I> *req = image_map::UpdateRequest<I>::create(
158 m_ioctx, {}, std::move(map_removals), ctx);
159 req->send();
160 }
161
162 template<typename I>
163 void LoadRequest<I>::finish(int r) {
164 dout(20) << ": r=" << r << dendl;
165
166 m_on_finish->complete(r);
167 delete this;
168 }
169
170 } // namespace image_map
171 } // namespace mirror
172 } // namespace rbd
173
174 template class rbd::mirror::image_map::LoadRequest<librbd::ImageCtx>;