]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/api/Group.cc
bump version to 12.1.2-pve1
[ceph.git] / ceph / src / librbd / api / Group.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/api/Group.h"
5#include "common/errno.h"
6#include "librbd/ImageState.h"
7#include "librbd/Utils.h"
8#include "librbd/io/AioCompletion.h"
9
10#define dout_subsys ceph_subsys_rbd
11#undef dout_prefix
12#define dout_prefix *_dout << "librbd::api::Group: " << __func__ << ": "
13
14using std::map;
15using std::pair;
16using std::set;
17using std::string;
18using std::vector;
19// list binds to list() here, so std::list is explicitly used below
20
21using ceph::bufferlist;
22using librados::snap_t;
23using librados::IoCtx;
24using librados::Rados;
25
26namespace librbd {
27namespace api {
28
29// Consistency groups functions
30
31template <typename I>
32int Group<I>::create(librados::IoCtx& io_ctx, const char *group_name)
33{
34 CephContext *cct = (CephContext *)io_ctx.cct();
35
36 Rados rados(io_ctx);
37 uint64_t bid = rados.get_instance_id();
38
39 uint32_t extra = rand() % 0xFFFFFFFF;
40 ostringstream bid_ss;
41 bid_ss << std::hex << bid << std::hex << extra;
42 string id = bid_ss.str();
43
44 ldout(cct, 2) << "adding consistency group to directory..." << dendl;
45
46 int r = cls_client::group_dir_add(&io_ctx, RBD_GROUP_DIRECTORY, group_name,
47 id);
48 if (r < 0) {
49 lderr(cct) << "error adding consistency group to directory: "
50 << cpp_strerror(r)
51 << dendl;
52 return r;
53 }
54 string header_oid = util::group_header_name(id);
55
56 r = cls_client::group_create(&io_ctx, header_oid);
57 if (r < 0) {
58 lderr(cct) << "error writing header: " << cpp_strerror(r) << dendl;
59 goto err_remove_from_dir;
60 }
61
62 return 0;
63
64err_remove_from_dir:
65 int remove_r = cls_client::group_dir_remove(&io_ctx, RBD_GROUP_DIRECTORY,
66 group_name, id);
67 if (remove_r < 0) {
68 lderr(cct) << "error cleaning up consistency group from rbd_directory "
69 << "object after creation failed: " << cpp_strerror(remove_r)
70 << dendl;
71 }
72
73 return r;
74}
75
76template <typename I>
77int Group<I>::remove(librados::IoCtx& io_ctx, const char *group_name)
78{
79 CephContext *cct((CephContext *)io_ctx.cct());
80 ldout(cct, 20) << "io_ctx=" << &io_ctx << " " << group_name << dendl;
81
82 std::vector<group_image_status_t> images;
83 int r = image_list(io_ctx, group_name, &images);
84 if (r < 0 && r != -ENOENT) {
85 lderr(cct) << "error listing group images" << dendl;
86 return r;
87 }
88
89 for (auto i : images) {
90 librados::Rados rados(io_ctx);
91 IoCtx image_ioctx;
92 rados.ioctx_create2(i.pool, image_ioctx);
93 r = image_remove(io_ctx, group_name, image_ioctx, i.name.c_str());
94 if (r < 0 && r != -ENOENT) {
95 lderr(cct) << "error removing image from a group" << dendl;
96 return r;
97 }
98 }
99
100 std::string group_id;
101 r = cls_client::dir_get_id(&io_ctx, RBD_GROUP_DIRECTORY,
102 std::string(group_name), &group_id);
103 if (r < 0 && r != -ENOENT) {
104 lderr(cct) << "error getting id of group" << dendl;
105 return r;
106 }
107
108 string header_oid = util::group_header_name(group_id);
109
110 r = io_ctx.remove(header_oid);
111 if (r < 0 && r != -ENOENT) {
112 lderr(cct) << "error removing header: " << cpp_strerror(-r) << dendl;
113 return r;
114 }
115
116 r = cls_client::group_dir_remove(&io_ctx, RBD_GROUP_DIRECTORY, group_name,
117 group_id);
118 if (r < 0 && r != -ENOENT) {
119 lderr(cct) << "error removing group from directory" << dendl;
120 return r;
121 }
122
123 return 0;
124}
125
126template <typename I>
127int Group<I>::list(IoCtx& io_ctx, vector<string> *names)
128{
129 CephContext *cct = (CephContext *)io_ctx.cct();
130 ldout(cct, 20) << "io_ctx=" << &io_ctx << dendl;
131
132 int max_read = 1024;
133 string last_read = "";
134 int r;
135 do {
136 map<string, string> groups;
137 r = cls_client::group_dir_list(&io_ctx, RBD_GROUP_DIRECTORY, last_read,
138 max_read, &groups);
139 if (r < 0) {
31f18b77
FG
140 if (r != -ENOENT) {
141 lderr(cct) << "error listing group in directory: "
142 << cpp_strerror(r) << dendl;
143 } else {
144 r = 0;
145 }
7c673cae
FG
146 return r;
147 }
148 for (pair<string, string> group : groups) {
149 names->push_back(group.first);
150 }
151 if (!groups.empty()) {
152 last_read = groups.rbegin()->first;
153 }
154 r = groups.size();
155 } while (r == max_read);
156
157 return 0;
158}
159
160template <typename I>
161int Group<I>::image_add(librados::IoCtx& group_ioctx, const char *group_name,
162 librados::IoCtx& image_ioctx, const char *image_name)
163{
164 CephContext *cct = (CephContext *)group_ioctx.cct();
165 ldout(cct, 20) << "io_ctx=" << &group_ioctx
166 << " group name " << group_name << " image "
167 << &image_ioctx << " name " << image_name << dendl;
168
169 string group_id;
170
171 int r = cls_client::dir_get_id(&group_ioctx, RBD_GROUP_DIRECTORY, group_name,
172 &group_id);
173 if (r < 0) {
174 lderr(cct) << "error reading consistency group id object: "
175 << cpp_strerror(r)
176 << dendl;
177 return r;
178 }
179 string group_header_oid = util::group_header_name(group_id);
180
181
182 ldout(cct, 20) << "adding image to group name " << group_name
183 << " group id " << group_header_oid << dendl;
184
185 string image_id;
186
187 r = cls_client::dir_get_id(&image_ioctx, RBD_DIRECTORY, image_name,
188 &image_id);
189 if (r < 0) {
190 lderr(cct) << "error reading image id object: "
191 << cpp_strerror(-r) << dendl;
192 return r;
193 }
194
195 string image_header_oid = util::header_name(image_id);
196
197 ldout(cct, 20) << "adding image " << image_name
198 << " image id " << image_header_oid << dendl;
199
200 cls::rbd::GroupImageStatus incomplete_st(
201 image_id, image_ioctx.get_id(),
202 cls::rbd::GROUP_IMAGE_LINK_STATE_INCOMPLETE);
203 cls::rbd::GroupImageStatus attached_st(
204 image_id, image_ioctx.get_id(), cls::rbd::GROUP_IMAGE_LINK_STATE_ATTACHED);
205
206 r = cls_client::group_image_set(&group_ioctx, group_header_oid,
207 incomplete_st);
208
209 cls::rbd::GroupSpec group_spec(group_id, group_ioctx.get_id());
210
211 if (r < 0) {
212 lderr(cct) << "error adding image reference to consistency group: "
213 << cpp_strerror(-r) << dendl;
214 return r;
215 }
216
217 r = cls_client::image_add_group(&image_ioctx, image_header_oid, group_spec);
218 if (r < 0) {
219 lderr(cct) << "error adding group reference to image: "
220 << cpp_strerror(-r) << dendl;
221 cls::rbd::GroupImageSpec spec(image_id, image_ioctx.get_id());
222 cls_client::group_image_remove(&group_ioctx, group_header_oid, spec);
223 // Ignore errors in the clean up procedure.
224 return r;
225 }
226
227 r = cls_client::group_image_set(&group_ioctx, group_header_oid,
228 attached_st);
229
230 return r;
231}
232
233template <typename I>
234int Group<I>::image_remove(librados::IoCtx& group_ioctx, const char *group_name,
235 librados::IoCtx& image_ioctx, const char *image_name)
236{
237 CephContext *cct = (CephContext *)group_ioctx.cct();
238 ldout(cct, 20) << "io_ctx=" << &group_ioctx
239 << " group name " << group_name << " image "
240 << &image_ioctx << " name " << image_name << dendl;
241
242 string image_id;
243 int r = cls_client::dir_get_id(&image_ioctx, RBD_DIRECTORY, image_name,
244 &image_id);
245 if (r < 0) {
246 lderr(cct) << "error reading image id object: "
247 << cpp_strerror(-r) << dendl;
248 return r;
249 }
250
251 return Group<I>::image_remove_by_id(group_ioctx, group_name, image_ioctx,
252 image_id.c_str());
253}
254
255template <typename I>
256int Group<I>::image_remove_by_id(librados::IoCtx& group_ioctx,
257 const char *group_name,
258 librados::IoCtx& image_ioctx,
259 const char *image_id)
260{
261 CephContext *cct = (CephContext *)group_ioctx.cct();
262 ldout(cct, 20) << "group_remove_image_by_id " << &group_ioctx
263 << " group name " << group_name << " image "
264 << &image_ioctx << " id " << image_id << dendl;
265
266 string group_id;
267
268 int r = cls_client::dir_get_id(&group_ioctx, RBD_GROUP_DIRECTORY, group_name,
269 &group_id);
270 if (r < 0) {
271 lderr(cct) << "error reading consistency group id object: "
272 << cpp_strerror(r)
273 << dendl;
274 return r;
275 }
276 string group_header_oid = util::group_header_name(group_id);
277
278 ldout(cct, 20) << "adding image to group name " << group_name
279 << " group id " << group_header_oid << dendl;
280
281 string image_header_oid = util::header_name(image_id);
282
283 ldout(cct, 20) << "removing " << " image id " << image_header_oid << dendl;
284
285 cls::rbd::GroupSpec group_spec(group_id, group_ioctx.get_id());
286
287 cls::rbd::GroupImageStatus incomplete_st(
288 image_id, image_ioctx.get_id(),
289 cls::rbd::GROUP_IMAGE_LINK_STATE_INCOMPLETE);
290
291 cls::rbd::GroupImageSpec spec(image_id, image_ioctx.get_id());
292
293 r = cls_client::group_image_set(&group_ioctx, group_header_oid,
294 incomplete_st);
295
296 if (r < 0) {
297 lderr(cct) << "couldn't put image into removing state: "
298 << cpp_strerror(-r) << dendl;
299 return r;
300 }
301
302 r = cls_client::image_remove_group(&image_ioctx, image_header_oid,
303 group_spec);
304 if ((r < 0) && (r != -ENOENT)) {
305 lderr(cct) << "couldn't remove group reference from image"
306 << cpp_strerror(-r) << dendl;
307 return r;
308 }
309
310 r = cls_client::group_image_remove(&group_ioctx, group_header_oid, spec);
311 if (r < 0) {
312 lderr(cct) << "couldn't remove image from group"
313 << cpp_strerror(-r) << dendl;
314 return r;
315 }
316
317 return 0;
318}
319
320template <typename I>
321int Group<I>::image_list(librados::IoCtx& group_ioctx,
322 const char *group_name,
323 std::vector<group_image_status_t> *images)
324{
325 CephContext *cct = (CephContext *)group_ioctx.cct();
326 ldout(cct, 20) << "io_ctx=" << &group_ioctx
327 << " group name " << group_name << dendl;
328
329 string group_id;
330
331 int r = cls_client::dir_get_id(&group_ioctx, RBD_GROUP_DIRECTORY,
332 group_name, &group_id);
333 if (r < 0) {
334 lderr(cct) << "error reading consistency group id object: "
335 << cpp_strerror(r)
336 << dendl;
337 return r;
338 }
339 string group_header_oid = util::group_header_name(group_id);
340
341 ldout(cct, 20) << "listing images in group name "
342 << group_name << " group id " << group_header_oid << dendl;
343
344 std::vector<cls::rbd::GroupImageStatus> image_ids;
345
346 const int max_read = 1024;
347 do {
348 std::vector<cls::rbd::GroupImageStatus> image_ids_page;
349 cls::rbd::GroupImageSpec start_last;
350
351 r = cls_client::group_image_list(&group_ioctx, group_header_oid,
352 start_last, max_read, &image_ids_page);
353
354 if (r < 0) {
355 lderr(cct) << "error reading image list from consistency group: "
356 << cpp_strerror(-r) << dendl;
357 return r;
358 }
359 image_ids.insert(image_ids.end(),
360 image_ids_page.begin(), image_ids_page.end());
361
362 if (image_ids_page.size() > 0)
363 start_last = image_ids_page.rbegin()->spec;
364
365 r = image_ids_page.size();
366 } while (r == max_read);
367
368 for (auto i : image_ids) {
369 librados::Rados rados(group_ioctx);
370 IoCtx ioctx;
371 rados.ioctx_create2(i.spec.pool_id, ioctx);
372 std::string image_name;
373 r = cls_client::dir_get_name(&ioctx, RBD_DIRECTORY,
374 i.spec.image_id, &image_name);
375 if (r < 0) {
376 return r;
377 }
378
379 images->push_back(
380 group_image_status_t {
381 image_name,
382 i.spec.pool_id,
383 static_cast<group_image_state_t>(i.state)});
384 }
385
386 return 0;
387}
388
389template <typename I>
390int Group<I>::image_get_group(I *ictx, group_spec_t *group_spec)
391{
392 int r = ictx->state->refresh_if_required();
393 if (r < 0)
394 return r;
395
396 if (-1 != ictx->group_spec.pool_id) {
397 librados::Rados rados(ictx->md_ctx);
398 IoCtx ioctx;
399 rados.ioctx_create2(ictx->group_spec.pool_id, ioctx);
400
401 std::string group_name;
402 r = cls_client::dir_get_name(&ioctx, RBD_GROUP_DIRECTORY,
403 ictx->group_spec.group_id, &group_name);
404 if (r < 0)
405 return r;
406 group_spec->pool = ictx->group_spec.pool_id;
407 group_spec->name = group_name;
408 } else {
409 group_spec->pool = -1;
410 group_spec->name = "";
411 }
412
413 return 0;
414}
415
416} // namespace api
417} // namespace librbd
418
419template class librbd::api::Group<librbd::ImageCtx>;