]> git.proxmox.com Git - ceph.git/blob - ceph/src/cls/rbd/cls_rbd_client.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / cls / rbd / cls_rbd_client.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 "cls/rbd/cls_rbd_client.h"
5 #include "cls/lock/cls_lock_client.h"
6 #include "include/buffer.h"
7 #include "include/encoding.h"
8 #include "include/rbd_types.h"
9 #include "include/rados/librados.hpp"
10 #include "include/neorados/RADOS.hpp"
11 #include "common/bit_vector.hpp"
12
13 #include <errno.h>
14
15 namespace librbd {
16 namespace cls_client {
17
18 using std::map;
19 using std::set;
20 using std::string;
21
22 using ceph::bufferlist;
23 using ceph::decode;
24 using ceph::encode;
25
26 void create_image(librados::ObjectWriteOperation *op, uint64_t size,
27 uint8_t order, uint64_t features,
28 const std::string &object_prefix, int64_t data_pool_id)
29 {
30 bufferlist bl;
31 encode(size, bl);
32 encode(order, bl);
33 encode(features, bl);
34 encode(object_prefix, bl);
35 encode(data_pool_id, bl);
36
37 op->exec("rbd", "create", bl);
38 }
39
40 int create_image(librados::IoCtx *ioctx, const std::string &oid,
41 uint64_t size, uint8_t order, uint64_t features,
42 const std::string &object_prefix, int64_t data_pool_id)
43 {
44 librados::ObjectWriteOperation op;
45 create_image(&op, size, order, features, object_prefix, data_pool_id);
46
47 return ioctx->operate(oid, &op);
48 }
49
50 void get_features_start(librados::ObjectReadOperation *op, bool read_only)
51 {
52 bufferlist bl;
53 encode(static_cast<uint64_t>(CEPH_NOSNAP), bl);
54 encode(read_only, bl);
55 op->exec("rbd", "get_features", bl);
56 }
57
58 int get_features_finish(bufferlist::const_iterator *it, uint64_t *features,
59 uint64_t *incompatible_features)
60 {
61 try {
62 decode(*features, *it);
63 decode(*incompatible_features, *it);
64 } catch (const ceph::buffer::error &err) {
65 return -EBADMSG;
66 }
67
68 return 0;
69 }
70
71 int get_features(librados::IoCtx *ioctx, const std::string &oid,
72 bool read_only, uint64_t *features,
73 uint64_t *incompatible_features)
74 {
75 librados::ObjectReadOperation op;
76 get_features_start(&op, read_only);
77
78 bufferlist out_bl;
79 int r = ioctx->operate(oid, &op, &out_bl);
80 if (r < 0) {
81 return r;
82 }
83
84 auto it = out_bl.cbegin();
85 return get_features_finish(&it, features, incompatible_features);
86 }
87
88 void set_features(librados::ObjectWriteOperation *op, uint64_t features,
89 uint64_t mask)
90 {
91 bufferlist bl;
92 encode(features, bl);
93 encode(mask, bl);
94
95 op->exec("rbd", "set_features", bl);
96 }
97
98 int set_features(librados::IoCtx *ioctx, const std::string &oid,
99 uint64_t features, uint64_t mask)
100 {
101 librados::ObjectWriteOperation op;
102 set_features(&op, features, mask);
103
104 return ioctx->operate(oid, &op);
105 }
106
107 void get_object_prefix_start(librados::ObjectReadOperation *op)
108 {
109 bufferlist bl;
110 op->exec("rbd", "get_object_prefix", bl);
111 }
112
113 int get_object_prefix_finish(bufferlist::const_iterator *it,
114 std::string *object_prefix)
115 {
116 try {
117 decode(*object_prefix, *it);
118 } catch (const ceph::buffer::error &err) {
119 return -EBADMSG;
120 }
121 return 0;
122 }
123
124 int get_object_prefix(librados::IoCtx *ioctx, const std::string &oid,
125 std::string *object_prefix)
126 {
127 librados::ObjectReadOperation op;
128 get_object_prefix_start(&op);
129
130 bufferlist out_bl;
131 int r = ioctx->operate(oid, &op, &out_bl);
132 if (r < 0) {
133 return r;
134 }
135
136 auto it = out_bl.cbegin();
137 return get_object_prefix_finish(&it, object_prefix);
138 }
139
140 void get_data_pool_start(librados::ObjectReadOperation *op) {
141 bufferlist bl;
142 op->exec("rbd", "get_data_pool", bl);
143 }
144
145 int get_data_pool_finish(bufferlist::const_iterator *it, int64_t *data_pool_id) {
146 try {
147 decode(*data_pool_id, *it);
148 } catch (const ceph::buffer::error &err) {
149 return -EBADMSG;
150 }
151 return 0;
152 }
153
154 int get_data_pool(librados::IoCtx *ioctx, const std::string &oid,
155 int64_t *data_pool_id) {
156 librados::ObjectReadOperation op;
157 get_data_pool_start(&op);
158
159 bufferlist out_bl;
160 int r = ioctx->operate(oid, &op, &out_bl);
161 if (r < 0) {
162 return r;
163 }
164
165 auto it = out_bl.cbegin();
166 return get_data_pool_finish(&it, data_pool_id);
167 }
168
169 void get_size_start(librados::ObjectReadOperation *op, snapid_t snap_id)
170 {
171 bufferlist bl;
172 encode(snap_id, bl);
173 op->exec("rbd", "get_size", bl);
174 }
175
176 int get_size_finish(bufferlist::const_iterator *it, uint64_t *size,
177 uint8_t *order)
178 {
179 try {
180 decode(*order, *it);
181 decode(*size, *it);
182 } catch (const ceph::buffer::error &err) {
183 return -EBADMSG;
184 }
185 return 0;
186 }
187
188 int get_size(librados::IoCtx *ioctx, const std::string &oid,
189 snapid_t snap_id, uint64_t *size, uint8_t *order)
190 {
191 librados::ObjectReadOperation op;
192 get_size_start(&op, snap_id);
193
194 bufferlist out_bl;
195 int r = ioctx->operate(oid, &op, &out_bl);
196 if (r < 0) {
197 return r;
198 }
199
200 auto it = out_bl.cbegin();
201 return get_size_finish(&it, size, order);
202 }
203
204 int set_size(librados::IoCtx *ioctx, const std::string &oid,
205 uint64_t size)
206 {
207 librados::ObjectWriteOperation op;
208 set_size(&op, size);
209 return ioctx->operate(oid, &op);
210 }
211
212 void set_size(librados::ObjectWriteOperation *op, uint64_t size)
213 {
214 bufferlist bl;
215 encode(size, bl);
216 op->exec("rbd", "set_size", bl);
217 }
218
219 void get_flags_start(librados::ObjectReadOperation *op, snapid_t snap_id) {
220 bufferlist in_bl;
221 encode(static_cast<snapid_t>(snap_id), in_bl);
222 op->exec("rbd", "get_flags", in_bl);
223 }
224
225 int get_flags_finish(bufferlist::const_iterator *it, uint64_t *flags) {
226 try {
227 decode(*flags, *it);
228 } catch (const ceph::buffer::error &err) {
229 return -EBADMSG;
230 }
231 return 0;
232 }
233
234 int get_flags(librados::IoCtx *ioctx, const std::string &oid,
235 snapid_t snap_id, uint64_t *flags)
236 {
237 librados::ObjectReadOperation op;
238 get_flags_start(&op, snap_id);
239
240 bufferlist out_bl;
241 int r = ioctx->operate(oid, &op, &out_bl);
242 if (r < 0) {
243 return r;
244 }
245
246 auto it = out_bl.cbegin();
247 return get_flags_finish(&it, flags);
248 }
249
250 void set_flags(librados::ObjectWriteOperation *op, snapid_t snap_id,
251 uint64_t flags, uint64_t mask)
252 {
253 bufferlist inbl;
254 encode(flags, inbl);
255 encode(mask, inbl);
256 encode(snap_id, inbl);
257 op->exec("rbd", "set_flags", inbl);
258 }
259
260 void op_features_get_start(librados::ObjectReadOperation *op)
261 {
262 bufferlist in_bl;
263 op->exec("rbd", "op_features_get", in_bl);
264 }
265
266 int op_features_get_finish(bufferlist::const_iterator *it, uint64_t *op_features)
267 {
268 try {
269 decode(*op_features, *it);
270 } catch (const ceph::buffer::error &err) {
271 return -EBADMSG;
272 }
273 return 0;
274 }
275
276 int op_features_get(librados::IoCtx *ioctx, const std::string &oid,
277 uint64_t *op_features)
278 {
279 librados::ObjectReadOperation op;
280 op_features_get_start(&op);
281
282 bufferlist out_bl;
283 int r = ioctx->operate(oid, &op, &out_bl);
284 if (r < 0) {
285 return r;
286 }
287
288 auto it = out_bl.cbegin();
289 return op_features_get_finish(&it, op_features);
290 }
291
292 void op_features_set(librados::ObjectWriteOperation *op,
293 uint64_t op_features, uint64_t mask)
294 {
295 bufferlist inbl;
296 encode(op_features, inbl);
297 encode(mask, inbl);
298 op->exec("rbd", "op_features_set", inbl);
299 }
300
301 int op_features_set(librados::IoCtx *ioctx, const std::string &oid,
302 uint64_t op_features, uint64_t mask)
303 {
304 librados::ObjectWriteOperation op;
305 op_features_set(&op, op_features, mask);
306
307 return ioctx->operate(oid, &op);
308 }
309
310 void get_parent_start(librados::ObjectReadOperation *op, snapid_t snap_id)
311 {
312 bufferlist bl;
313 encode(snap_id, bl);
314 op->exec("rbd", "get_parent", bl);
315 }
316
317 int get_parent_finish(bufferlist::const_iterator *it,
318 cls::rbd::ParentImageSpec *pspec,
319 uint64_t *parent_overlap)
320 {
321 *pspec = {};
322 try {
323 decode(pspec->pool_id, *it);
324 decode(pspec->image_id, *it);
325 decode(pspec->snap_id, *it);
326 decode(*parent_overlap, *it);
327 } catch (const ceph::buffer::error &) {
328 return -EBADMSG;
329 }
330 return 0;
331 }
332
333 int get_parent(librados::IoCtx *ioctx, const std::string &oid,
334 snapid_t snap_id, cls::rbd::ParentImageSpec *pspec,
335 uint64_t *parent_overlap)
336 {
337 librados::ObjectReadOperation op;
338 get_parent_start(&op, snap_id);
339
340 bufferlist out_bl;
341 int r = ioctx->operate(oid, &op, &out_bl);
342 if (r < 0) {
343 return r;
344 }
345
346 auto it = out_bl.cbegin();
347 return get_parent_finish(&it, pspec, parent_overlap);
348 }
349
350 int set_parent(librados::IoCtx *ioctx, const std::string &oid,
351 const cls::rbd::ParentImageSpec &pspec, uint64_t parent_overlap)
352 {
353 librados::ObjectWriteOperation op;
354 set_parent(&op, pspec, parent_overlap);
355 return ioctx->operate(oid, &op);
356 }
357
358 void set_parent(librados::ObjectWriteOperation *op,
359 const cls::rbd::ParentImageSpec &pspec,
360 uint64_t parent_overlap) {
361 assert(pspec.pool_namespace.empty());
362
363 bufferlist in_bl;
364 encode(pspec.pool_id, in_bl);
365 encode(pspec.image_id, in_bl);
366 encode(pspec.snap_id, in_bl);
367 encode(parent_overlap, in_bl);
368
369 op->exec("rbd", "set_parent", in_bl);
370 }
371
372 int remove_parent(librados::IoCtx *ioctx, const std::string &oid)
373 {
374 librados::ObjectWriteOperation op;
375 remove_parent(&op);
376 return ioctx->operate(oid, &op);
377 }
378
379 void remove_parent(librados::ObjectWriteOperation *op)
380 {
381 bufferlist inbl;
382 op->exec("rbd", "remove_parent", inbl);
383 }
384
385 void parent_get_start(librados::ObjectReadOperation* op) {
386 bufferlist in_bl;
387 op->exec("rbd", "parent_get", in_bl);
388 }
389
390 int parent_get_finish(bufferlist::const_iterator* it,
391 cls::rbd::ParentImageSpec* parent_image_spec) {
392 try {
393 decode(*parent_image_spec, *it);
394 } catch (const ceph::buffer::error &) {
395 return -EBADMSG;
396 }
397 return 0;
398 }
399
400 int parent_get(librados::IoCtx* ioctx, const std::string &oid,
401 cls::rbd::ParentImageSpec* parent_image_spec) {
402 librados::ObjectReadOperation op;
403 parent_get_start(&op);
404
405 bufferlist out_bl;
406 int r = ioctx->operate(oid, &op, &out_bl);
407 if (r < 0) {
408 return r;
409 }
410
411 auto it = out_bl.cbegin();
412 r = parent_get_finish(&it, parent_image_spec);
413 if (r < 0) {
414 return r;
415 }
416 return 0;
417 }
418
419 void parent_overlap_get_start(librados::ObjectReadOperation* op,
420 snapid_t snap_id) {
421 bufferlist in_bl;
422 encode(snap_id, in_bl);
423 op->exec("rbd", "parent_overlap_get", in_bl);
424 }
425
426 int parent_overlap_get_finish(bufferlist::const_iterator* it,
427 std::optional<uint64_t>* parent_overlap) {
428 try {
429 decode(*parent_overlap, *it);
430 } catch (const ceph::buffer::error &) {
431 return -EBADMSG;
432 }
433 return 0;
434 }
435
436 int parent_overlap_get(librados::IoCtx* ioctx, const std::string &oid,
437 snapid_t snap_id,
438 std::optional<uint64_t>* parent_overlap) {
439 librados::ObjectReadOperation op;
440 parent_overlap_get_start(&op, snap_id);
441
442 bufferlist out_bl;
443 int r = ioctx->operate(oid, &op, &out_bl);
444 if (r < 0) {
445 return r;
446 }
447
448 auto it = out_bl.cbegin();
449 r = parent_overlap_get_finish(&it, parent_overlap);
450 if (r < 0) {
451 return r;
452 }
453 return 0;
454 }
455
456 void parent_attach(librados::ObjectWriteOperation* op,
457 const cls::rbd::ParentImageSpec& parent_image_spec,
458 uint64_t parent_overlap, bool reattach) {
459 bufferlist in_bl;
460 encode(parent_image_spec, in_bl);
461 encode(parent_overlap, in_bl);
462 encode(reattach, in_bl);
463 op->exec("rbd", "parent_attach", in_bl);
464 }
465
466 int parent_attach(librados::IoCtx *ioctx, const std::string &oid,
467 const cls::rbd::ParentImageSpec& parent_image_spec,
468 uint64_t parent_overlap, bool reattach) {
469 librados::ObjectWriteOperation op;
470 parent_attach(&op, parent_image_spec, parent_overlap, reattach);
471 return ioctx->operate(oid, &op);
472 }
473
474 void parent_detach(librados::ObjectWriteOperation* op) {
475 bufferlist in_bl;
476 op->exec("rbd", "parent_detach", in_bl);
477 }
478
479 int parent_detach(librados::IoCtx *ioctx, const std::string &oid) {
480 librados::ObjectWriteOperation op;
481 parent_detach(&op);
482 return ioctx->operate(oid, &op);
483 }
484
485 int add_child(librados::IoCtx *ioctx, const std::string &oid,
486 const cls::rbd::ParentImageSpec &pspec,
487 const std::string &c_imageid)
488 {
489 librados::ObjectWriteOperation op;
490 add_child(&op, pspec, c_imageid);
491 return ioctx->operate(oid, &op);
492 }
493
494 void add_child(librados::ObjectWriteOperation *op,
495 const cls::rbd::ParentImageSpec& pspec,
496 const std::string &c_imageid)
497 {
498 assert(pspec.pool_namespace.empty());
499
500 bufferlist in;
501 encode(pspec.pool_id, in);
502 encode(pspec.image_id, in);
503 encode(pspec.snap_id, in);
504 encode(c_imageid, in);
505
506 op->exec("rbd", "add_child", in);
507 }
508
509 void remove_child(librados::ObjectWriteOperation *op,
510 const cls::rbd::ParentImageSpec &pspec,
511 const std::string &c_imageid)
512 {
513 assert(pspec.pool_namespace.empty());
514
515 bufferlist in;
516 encode(pspec.pool_id, in);
517 encode(pspec.image_id, in);
518 encode(pspec.snap_id, in);
519 encode(c_imageid, in);
520 op->exec("rbd", "remove_child", in);
521 }
522
523 int remove_child(librados::IoCtx *ioctx, const std::string &oid,
524 const cls::rbd::ParentImageSpec &pspec,
525 const std::string &c_imageid)
526 {
527 librados::ObjectWriteOperation op;
528 remove_child(&op, pspec, c_imageid);
529 return ioctx->operate(oid, &op);
530 }
531
532 void get_children_start(librados::ObjectReadOperation *op,
533 const cls::rbd::ParentImageSpec &pspec) {
534 bufferlist in_bl;
535 encode(pspec.pool_id, in_bl);
536 encode(pspec.image_id, in_bl);
537 encode(pspec.snap_id, in_bl);
538 op->exec("rbd", "get_children", in_bl);
539 }
540
541 int get_children_finish(bufferlist::const_iterator *it,
542 std::set<std::string>* children) {
543 try {
544 decode(*children, *it);
545 } catch (const ceph::buffer::error &err) {
546 return -EBADMSG;
547 }
548 return 0;
549 }
550
551 int get_children(librados::IoCtx *ioctx, const std::string &oid,
552 const cls::rbd::ParentImageSpec &pspec, set<string>& children)
553 {
554 librados::ObjectReadOperation op;
555 get_children_start(&op, pspec);
556
557 bufferlist out_bl;
558 int r = ioctx->operate(oid, &op, &out_bl);
559 if (r < 0) {
560 return r;
561 }
562
563 auto it = out_bl.cbegin();
564 return get_children_finish(&it, &children);
565 }
566
567 void snapshot_get_start(librados::ObjectReadOperation *op, snapid_t snap_id)
568 {
569 bufferlist bl;
570 encode(snap_id, bl);
571 op->exec("rbd", "snapshot_get", bl);
572 }
573
574 int snapshot_get_finish(bufferlist::const_iterator* it,
575 cls::rbd::SnapshotInfo* snap_info)
576 {
577 try {
578 decode(*snap_info, *it);
579 } catch (const ceph::buffer::error &err) {
580 return -EBADMSG;
581 }
582 return 0;
583 }
584
585 int snapshot_get(librados::IoCtx *ioctx, const std::string &oid,
586 snapid_t snap_id, cls::rbd::SnapshotInfo* snap_info)
587 {
588 librados::ObjectReadOperation op;
589 snapshot_get_start(&op, snap_id);
590
591 bufferlist out_bl;
592 int r = ioctx->operate(oid, &op, &out_bl);
593 if (r < 0) {
594 return r;
595 }
596
597 auto it = out_bl.cbegin();
598 return snapshot_get_finish(&it, snap_info);
599 }
600
601 void snapshot_add(librados::ObjectWriteOperation *op, snapid_t snap_id,
602 const std::string &snap_name,
603 const cls::rbd::SnapshotNamespace &snap_namespace)
604 {
605 bufferlist bl;
606 encode(snap_name, bl);
607 encode(snap_id, bl);
608 encode(snap_namespace, bl);
609 op->exec("rbd", "snapshot_add", bl);
610 }
611
612 void snapshot_remove(librados::ObjectWriteOperation *op, snapid_t snap_id)
613 {
614 bufferlist bl;
615 encode(snap_id, bl);
616 op->exec("rbd", "snapshot_remove", bl);
617 }
618
619 void snapshot_rename(librados::ObjectWriteOperation *op,
620 snapid_t src_snap_id,
621 const std::string &dst_name)
622 {
623 bufferlist bl;
624 encode(src_snap_id, bl);
625 encode(dst_name, bl);
626 op->exec("rbd", "snapshot_rename", bl);
627 }
628
629 void snapshot_trash_add(librados::ObjectWriteOperation *op,
630 snapid_t snap_id)
631 {
632 bufferlist bl;
633 encode(snap_id, bl);
634 op->exec("rbd", "snapshot_trash_add", bl);
635 }
636
637 void get_snapcontext_start(librados::ObjectReadOperation *op)
638 {
639 bufferlist bl;
640 op->exec("rbd", "get_snapcontext", bl);
641 }
642
643 int get_snapcontext_finish(bufferlist::const_iterator *it,
644 ::SnapContext *snapc)
645 {
646 try {
647 decode(*snapc, *it);
648 } catch (const ceph::buffer::error &err) {
649 return -EBADMSG;
650 }
651 if (!snapc->is_valid()) {
652 return -EBADMSG;
653 }
654 return 0;
655 }
656
657 int get_snapcontext(librados::IoCtx *ioctx, const std::string &oid,
658 ::SnapContext *snapc)
659 {
660 librados::ObjectReadOperation op;
661 get_snapcontext_start(&op);
662
663 bufferlist out_bl;
664 int r = ioctx->operate(oid, &op, &out_bl);
665 if (r < 0) {
666 return r;
667 }
668
669 auto bl_it = out_bl.cbegin();
670 return get_snapcontext_finish(&bl_it, snapc);
671 }
672
673 void get_snapshot_name_start(librados::ObjectReadOperation *op,
674 snapid_t snap_id)
675 {
676 bufferlist bl;
677 encode(snap_id, bl);
678 op->exec("rbd", "get_snapshot_name", bl);
679 }
680
681 int get_snapshot_name_finish(bufferlist::const_iterator *it,
682 std::string *name)
683 {
684 try {
685 decode(*name, *it);
686 } catch (const ceph::buffer::error &err) {
687 return -EBADMSG;
688 }
689 return 0;
690 }
691
692 int get_snapshot_name(librados::IoCtx *ioctx, const std::string &oid,
693 snapid_t snap_id, std::string *name)
694 {
695 librados::ObjectReadOperation op;
696 get_snapshot_name_start(&op, snap_id);
697
698 bufferlist out_bl;
699 int r = ioctx->operate(oid, &op, &out_bl);
700 if (r < 0) {
701 return r;
702 }
703
704 auto it = out_bl.cbegin();
705 return get_snapshot_name_finish(&it, name);
706 }
707
708 void get_snapshot_timestamp_start(librados::ObjectReadOperation *op,
709 snapid_t snap_id)
710 {
711 bufferlist bl;
712 encode(snap_id, bl);
713 op->exec("rbd", "get_snapshot_timestamp", bl);
714 }
715
716 int get_snapshot_timestamp_finish(bufferlist::const_iterator *it,
717 utime_t *timestamp)
718 {
719 try {
720 decode(*timestamp, *it);
721 } catch (const ceph::buffer::error &err) {
722 return -EBADMSG;
723 }
724 return 0;
725 }
726
727 int get_snapshot_timestamp(librados::IoCtx *ioctx, const std::string &oid,
728 snapid_t snap_id, utime_t *timestamp)
729 {
730 librados::ObjectReadOperation op;
731 get_snapshot_timestamp_start(&op, snap_id);
732
733 bufferlist out_bl;
734 int r = ioctx->operate(oid, &op, &out_bl);
735 if (r < 0) {
736 return r;
737 }
738
739 auto it = out_bl.cbegin();
740 return get_snapshot_timestamp_finish(&it, timestamp);
741 }
742
743 void old_snapshot_add(librados::ObjectWriteOperation *op,
744 snapid_t snap_id, const std::string &snap_name)
745 {
746 bufferlist bl;
747 encode(snap_name, bl);
748 encode(snap_id, bl);
749 op->exec("rbd", "snap_add", bl);
750 }
751
752 void old_snapshot_remove(librados::ObjectWriteOperation *op,
753 const std::string &snap_name)
754 {
755 bufferlist bl;
756 encode(snap_name, bl);
757 op->exec("rbd", "snap_remove", bl);
758 }
759
760 void old_snapshot_rename(librados::ObjectWriteOperation *op,
761 snapid_t src_snap_id, const std::string &dst_name)
762 {
763 bufferlist bl;
764 encode(src_snap_id, bl);
765 encode(dst_name, bl);
766 op->exec("rbd", "snap_rename", bl);
767 }
768
769 void old_snapshot_list_start(librados::ObjectReadOperation *op) {
770 bufferlist in_bl;
771 op->exec("rbd", "snap_list", in_bl);
772 }
773
774 int old_snapshot_list_finish(bufferlist::const_iterator *it,
775 std::vector<string> *names,
776 std::vector<uint64_t> *sizes,
777 ::SnapContext *snapc) {
778 try {
779 uint32_t num_snaps;
780 decode(snapc->seq, *it);
781 decode(num_snaps, *it);
782
783 names->resize(num_snaps);
784 sizes->resize(num_snaps);
785 snapc->snaps.resize(num_snaps);
786 for (uint32_t i = 0; i < num_snaps; ++i) {
787 decode(snapc->snaps[i], *it);
788 decode((*sizes)[i], *it);
789 decode((*names)[i], *it);
790 }
791 } catch (const ceph::buffer::error &err) {
792 return -EBADMSG;
793 }
794 return 0;
795 }
796
797 int old_snapshot_list(librados::IoCtx *ioctx, const std::string &oid,
798 std::vector<string> *names,
799 std::vector<uint64_t> *sizes,
800 ::SnapContext *snapc)
801 {
802 librados::ObjectReadOperation op;
803 old_snapshot_list_start(&op);
804
805 bufferlist out_bl;
806 int r = ioctx->operate(oid, &op, &out_bl);
807 if (r < 0) {
808 return r;
809 }
810
811 auto it = out_bl.cbegin();
812 return old_snapshot_list_finish(&it, names, sizes, snapc);
813 }
814
815 void get_all_features_start(librados::ObjectReadOperation *op) {
816 bufferlist in;
817 op->exec("rbd", "get_all_features", in);
818 }
819
820 int get_all_features_finish(bufferlist::const_iterator *it,
821 uint64_t *all_features) {
822 try {
823 decode(*all_features, *it);
824 } catch (const ceph::buffer::error &err) {
825 return -EBADMSG;
826 }
827 return 0;
828 }
829
830 int get_all_features(librados::IoCtx *ioctx, const std::string &oid,
831 uint64_t *all_features) {
832 librados::ObjectReadOperation op;
833 get_all_features_start(&op);
834
835 bufferlist out_bl;
836 int r = ioctx->operate(oid, &op, &out_bl);
837 if (r < 0) {
838 return r;
839 }
840
841 auto it = out_bl.cbegin();
842 return get_all_features_finish(&it, all_features);
843 }
844
845 template <typename O>
846 void copyup(O* op, ceph::buffer::list data) {
847 op->exec("rbd", "copyup", data);
848 }
849
850 void copyup(neorados::WriteOp* op, ceph::buffer::list data) {
851 copyup<neorados::WriteOp>(op, data);
852 }
853
854 void copyup(librados::ObjectWriteOperation *op, bufferlist data) {
855 copyup<librados::ObjectWriteOperation>(op, data);
856 }
857
858 int copyup(librados::IoCtx *ioctx, const std::string &oid,
859 bufferlist data) {
860 librados::ObjectWriteOperation op;
861 copyup(&op, data);
862
863 return ioctx->operate(oid, &op);
864 }
865
866 template <typename O, typename E>
867 void sparse_copyup(O* op, const E& extent_map, ceph::buffer::list data) {
868 bufferlist bl;
869 encode(extent_map, bl);
870 encode(data, bl);
871 op->exec("rbd", "sparse_copyup", bl);
872 }
873
874 void sparse_copyup(neorados::WriteOp* op,
875 const std::vector<std::pair<uint64_t, uint64_t>>& extent_map,
876 ceph::buffer::list data) {
877 sparse_copyup<neorados::WriteOp>(op, extent_map, data);
878 }
879
880 void sparse_copyup(librados::ObjectWriteOperation *op,
881 const std::map<uint64_t, uint64_t> &extent_map,
882 bufferlist data) {
883 sparse_copyup<librados::ObjectWriteOperation>(op, extent_map, data);
884 }
885
886 int sparse_copyup(librados::IoCtx *ioctx, const std::string &oid,
887 const std::map<uint64_t, uint64_t> &extent_map,
888 bufferlist data) {
889 librados::ObjectWriteOperation op;
890 sparse_copyup(&op, extent_map, data);
891
892 return ioctx->operate(oid, &op);
893 }
894
895 void get_protection_status_start(librados::ObjectReadOperation *op,
896 snapid_t snap_id)
897 {
898 bufferlist bl;
899 encode(snap_id, bl);
900 op->exec("rbd", "get_protection_status", bl);
901 }
902
903 int get_protection_status_finish(bufferlist::const_iterator *it,
904 uint8_t *protection_status)
905 {
906 try {
907 decode(*protection_status, *it);
908 } catch (const ceph::buffer::error &) {
909 return -EBADMSG;
910 }
911 return 0;
912 }
913
914 int get_protection_status(librados::IoCtx *ioctx, const std::string &oid,
915 snapid_t snap_id, uint8_t *protection_status)
916 {
917 librados::ObjectReadOperation op;
918 get_protection_status_start(&op, snap_id);
919
920 bufferlist out_bl;
921 int r = ioctx->operate(oid, &op, &out_bl);
922 if (r < 0) {
923 return r;
924 }
925
926 auto it = out_bl.cbegin();
927 return get_protection_status_finish(&it, protection_status);
928 }
929
930 int set_protection_status(librados::IoCtx *ioctx, const std::string &oid,
931 snapid_t snap_id, uint8_t protection_status)
932 {
933 // TODO remove
934 librados::ObjectWriteOperation op;
935 set_protection_status(&op, snap_id, protection_status);
936 return ioctx->operate(oid, &op);
937 }
938
939 void set_protection_status(librados::ObjectWriteOperation *op,
940 snapid_t snap_id, uint8_t protection_status)
941 {
942 bufferlist in;
943 encode(snap_id, in);
944 encode(protection_status, in);
945 op->exec("rbd", "set_protection_status", in);
946 }
947
948 void snapshot_get_limit_start(librados::ObjectReadOperation *op)
949 {
950 bufferlist bl;
951 op->exec("rbd", "snapshot_get_limit", bl);
952 }
953
954 int snapshot_get_limit_finish(bufferlist::const_iterator *it, uint64_t *limit)
955 {
956 try {
957 decode(*limit, *it);
958 } catch (const ceph::buffer::error &err) {
959 return -EBADMSG;
960 }
961 return 0;
962 }
963
964 int snapshot_get_limit(librados::IoCtx *ioctx, const std::string &oid,
965 uint64_t *limit)
966 {
967 librados::ObjectReadOperation op;
968 snapshot_get_limit_start(&op);
969
970 bufferlist out_bl;
971 int r = ioctx->operate(oid, &op, &out_bl);
972 if (r < 0) {
973 return r;
974 }
975
976 auto it = out_bl.cbegin();
977 return snapshot_get_limit_finish(&it, limit);
978 }
979
980 void snapshot_set_limit(librados::ObjectWriteOperation *op, uint64_t limit)
981 {
982 bufferlist in;
983 encode(limit, in);
984 op->exec("rbd", "snapshot_set_limit", in);
985 }
986
987 void get_stripe_unit_count_start(librados::ObjectReadOperation *op) {
988 bufferlist empty_bl;
989 op->exec("rbd", "get_stripe_unit_count", empty_bl);
990 }
991
992 int get_stripe_unit_count_finish(bufferlist::const_iterator *it,
993 uint64_t *stripe_unit,
994 uint64_t *stripe_count) {
995 ceph_assert(stripe_unit);
996 ceph_assert(stripe_count);
997
998 try {
999 decode(*stripe_unit, *it);
1000 decode(*stripe_count, *it);
1001 } catch (const ceph::buffer::error &err) {
1002 return -EBADMSG;
1003 }
1004 return 0;
1005 }
1006
1007 int get_stripe_unit_count(librados::IoCtx *ioctx, const std::string &oid,
1008 uint64_t *stripe_unit, uint64_t *stripe_count)
1009 {
1010 librados::ObjectReadOperation op;
1011 get_stripe_unit_count_start(&op);
1012
1013 bufferlist out_bl;
1014 int r = ioctx->operate(oid, &op, &out_bl);
1015 if (r < 0) {
1016 return r;
1017 }
1018
1019 auto it = out_bl.cbegin();
1020 return get_stripe_unit_count_finish(&it, stripe_unit, stripe_count);
1021 }
1022
1023 void set_stripe_unit_count(librados::ObjectWriteOperation *op,
1024 uint64_t stripe_unit, uint64_t stripe_count)
1025 {
1026 bufferlist bl;
1027 encode(stripe_unit, bl);
1028 encode(stripe_count, bl);
1029
1030 op->exec("rbd", "set_stripe_unit_count", bl);
1031 }
1032
1033 int set_stripe_unit_count(librados::IoCtx *ioctx, const std::string &oid,
1034 uint64_t stripe_unit, uint64_t stripe_count)
1035 {
1036 librados::ObjectWriteOperation op;
1037 set_stripe_unit_count(&op, stripe_unit, stripe_count);
1038
1039 return ioctx->operate(oid, &op);
1040 }
1041
1042 void get_create_timestamp_start(librados::ObjectReadOperation *op) {
1043 bufferlist empty_bl;
1044 op->exec("rbd", "get_create_timestamp", empty_bl);
1045 }
1046
1047 int get_create_timestamp_finish(bufferlist::const_iterator *it,
1048 utime_t *timestamp) {
1049 ceph_assert(timestamp);
1050
1051 try {
1052 decode(*timestamp, *it);
1053 } catch (const ceph::buffer::error &err) {
1054 return -EBADMSG;
1055 }
1056 return 0;
1057 }
1058
1059 int get_create_timestamp(librados::IoCtx *ioctx, const std::string &oid,
1060 utime_t *timestamp)
1061 {
1062 librados::ObjectReadOperation op;
1063 get_create_timestamp_start(&op);
1064
1065 bufferlist out_bl;
1066 int r = ioctx->operate(oid, &op, &out_bl);
1067 if (r < 0) {
1068 return r;
1069 }
1070
1071 auto it = out_bl.cbegin();
1072 return get_create_timestamp_finish(&it, timestamp);
1073 }
1074
1075 void get_access_timestamp_start(librados::ObjectReadOperation *op) {
1076 bufferlist empty_bl;
1077 op->exec("rbd", "get_access_timestamp", empty_bl);
1078 }
1079
1080 int get_access_timestamp_finish(bufferlist::const_iterator *it,
1081 utime_t *timestamp) {
1082 ceph_assert(timestamp);
1083
1084 try {
1085 decode(*timestamp, *it);
1086 } catch (const ceph::buffer::error &err) {
1087 return -EBADMSG;
1088 }
1089 return 0;
1090 }
1091
1092 int get_access_timestamp(librados::IoCtx *ioctx, const std::string &oid,
1093 utime_t *timestamp)
1094 {
1095 librados::ObjectReadOperation op;
1096 get_access_timestamp_start(&op);
1097
1098 bufferlist out_bl;
1099 int r = ioctx->operate(oid, &op, &out_bl);
1100 if (r < 0) {
1101 return r;
1102 }
1103
1104 auto it = out_bl.cbegin();
1105 return get_access_timestamp_finish(&it, timestamp);
1106 }
1107
1108 void set_access_timestamp(librados::ObjectWriteOperation *op)
1109 {
1110 bufferlist empty_bl;
1111 op->exec("rbd","set_access_timestamp",empty_bl);
1112 }
1113
1114 int set_access_timestamp(librados::IoCtx *ioctx, const std::string &oid)
1115 {
1116 librados::ObjectWriteOperation op;
1117 set_access_timestamp(&op);
1118 return ioctx->operate(oid, &op);
1119 }
1120
1121 void get_modify_timestamp_start(librados::ObjectReadOperation *op) {
1122 bufferlist empty_bl;
1123 op->exec("rbd", "get_modify_timestamp", empty_bl);
1124 }
1125
1126 int get_modify_timestamp_finish(bufferlist::const_iterator *it,
1127 utime_t *timestamp) {
1128 ceph_assert(timestamp);
1129
1130 try {
1131 decode(*timestamp, *it);
1132 } catch (const ceph::buffer::error &err) {
1133 return -EBADMSG;
1134 }
1135 return 0;
1136 }
1137
1138 int get_modify_timestamp(librados::IoCtx *ioctx, const std::string &oid,
1139 utime_t *timestamp)
1140 {
1141 librados::ObjectReadOperation op;
1142 get_modify_timestamp_start(&op);
1143
1144 bufferlist out_bl;
1145 int r = ioctx->operate(oid, &op, &out_bl);
1146 if (r < 0) {
1147 return r;
1148 }
1149
1150 auto it = out_bl.cbegin();
1151 return get_modify_timestamp_finish(&it, timestamp);
1152 }
1153
1154 void set_modify_timestamp(librados::ObjectWriteOperation *op)
1155 {
1156 bufferlist empty_bl;
1157 op->exec("rbd","set_modify_timestamp",empty_bl);
1158 }
1159
1160 int set_modify_timestamp(librados::IoCtx *ioctx, const std::string &oid)
1161 {
1162 librados::ObjectWriteOperation op;
1163 set_modify_timestamp(&op);
1164 return ioctx->operate(oid, &op);
1165 }
1166
1167
1168 /************************ rbd_id object methods ************************/
1169
1170 void get_id_start(librados::ObjectReadOperation *op) {
1171 bufferlist empty_bl;
1172 op->exec("rbd", "get_id", empty_bl);
1173 }
1174
1175 int get_id_finish(bufferlist::const_iterator *it, std::string *id) {
1176 try {
1177 decode(*id, *it);
1178 } catch (const ceph::buffer::error &err) {
1179 return -EBADMSG;
1180 }
1181 return 0;
1182 }
1183
1184 int get_id(librados::IoCtx *ioctx, const std::string &oid, std::string *id)
1185 {
1186 librados::ObjectReadOperation op;
1187 get_id_start(&op);
1188
1189 bufferlist out_bl;
1190 int r = ioctx->operate(oid, &op, &out_bl);
1191 if (r < 0) {
1192 return r;
1193 }
1194
1195 auto it = out_bl.cbegin();
1196 return get_id_finish(&it, id);
1197 }
1198
1199 void set_id(librados::ObjectWriteOperation *op, const std::string &id)
1200 {
1201 bufferlist bl;
1202 encode(id, bl);
1203 op->exec("rbd", "set_id", bl);
1204 }
1205
1206 int set_id(librados::IoCtx *ioctx, const std::string &oid, const std::string &id)
1207 {
1208 librados::ObjectWriteOperation op;
1209 set_id(&op, id);
1210
1211 return ioctx->operate(oid, &op);
1212 }
1213
1214 /******************** rbd_directory object methods ********************/
1215
1216 void dir_get_id_start(librados::ObjectReadOperation *op,
1217 const std::string &image_name) {
1218 bufferlist bl;
1219 encode(image_name, bl);
1220
1221 op->exec("rbd", "dir_get_id", bl);
1222 }
1223
1224 int dir_get_id_finish(bufferlist::const_iterator *iter, std::string *image_id) {
1225 try {
1226 decode(*image_id, *iter);
1227 } catch (const ceph::buffer::error &err) {
1228 return -EBADMSG;
1229 }
1230
1231 return 0;
1232 }
1233
1234 int dir_get_id(librados::IoCtx *ioctx, const std::string &oid,
1235 const std::string &name, std::string *id) {
1236 librados::ObjectReadOperation op;
1237 dir_get_id_start(&op, name);
1238
1239 bufferlist out_bl;
1240 int r = ioctx->operate(oid, &op, &out_bl);
1241 if (r < 0) {
1242 return r;
1243 }
1244
1245 auto iter = out_bl.cbegin();
1246 return dir_get_id_finish(&iter, id);
1247 }
1248
1249 void dir_get_name_start(librados::ObjectReadOperation *op,
1250 const std::string &id) {
1251 bufferlist in_bl;
1252 encode(id, in_bl);
1253 op->exec("rbd", "dir_get_name", in_bl);
1254 }
1255
1256 int dir_get_name_finish(bufferlist::const_iterator *it, std::string *name) {
1257 try {
1258 decode(*name, *it);
1259 } catch (const ceph::buffer::error &err) {
1260 return -EBADMSG;
1261 }
1262 return 0;
1263 }
1264
1265 int dir_get_name(librados::IoCtx *ioctx, const std::string &oid,
1266 const std::string &id, std::string *name) {
1267 librados::ObjectReadOperation op;
1268 dir_get_name_start(&op, id);
1269
1270 bufferlist out_bl;
1271 int r = ioctx->operate(oid, &op, &out_bl);
1272 if (r < 0) {
1273 return r;
1274 }
1275
1276 auto it = out_bl.cbegin();
1277 return dir_get_name_finish(&it, name);
1278 }
1279
1280 void dir_list_start(librados::ObjectReadOperation *op,
1281 const std::string &start, uint64_t max_return)
1282 {
1283 bufferlist in_bl;
1284 encode(start, in_bl);
1285 encode(max_return, in_bl);
1286
1287 op->exec("rbd", "dir_list", in_bl);
1288 }
1289
1290 int dir_list_finish(bufferlist::const_iterator *it, map<string, string> *images)
1291 {
1292 try {
1293 decode(*images, *it);
1294 } catch (const ceph::buffer::error &err) {
1295 return -EBADMSG;
1296 }
1297 return 0;
1298 }
1299
1300 int dir_list(librados::IoCtx *ioctx, const std::string &oid,
1301 const std::string &start, uint64_t max_return,
1302 map<string, string> *images)
1303 {
1304 librados::ObjectReadOperation op;
1305 dir_list_start(&op, start, max_return);
1306
1307 bufferlist out_bl;
1308 int r = ioctx->operate(oid, &op, &out_bl);
1309 if (r < 0) {
1310 return r;
1311 }
1312
1313 auto iter = out_bl.cbegin();
1314 return dir_list_finish(&iter, images);
1315 }
1316
1317 void dir_add_image(librados::ObjectWriteOperation *op,
1318 const std::string &name, const std::string &id)
1319 {
1320 bufferlist bl;
1321 encode(name, bl);
1322 encode(id, bl);
1323 op->exec("rbd", "dir_add_image", bl);
1324 }
1325
1326 int dir_add_image(librados::IoCtx *ioctx, const std::string &oid,
1327 const std::string &name, const std::string &id)
1328 {
1329 librados::ObjectWriteOperation op;
1330 dir_add_image(&op, name, id);
1331
1332 return ioctx->operate(oid, &op);
1333 }
1334
1335 int dir_remove_image(librados::IoCtx *ioctx, const std::string &oid,
1336 const std::string &name, const std::string &id)
1337 {
1338 librados::ObjectWriteOperation op;
1339 dir_remove_image(&op, name, id);
1340
1341 return ioctx->operate(oid, &op);
1342 }
1343
1344 void dir_state_assert(librados::ObjectOperation *op,
1345 cls::rbd::DirectoryState directory_state)
1346 {
1347 bufferlist bl;
1348 encode(directory_state, bl);
1349 op->exec("rbd", "dir_state_assert", bl);
1350 }
1351
1352 int dir_state_assert(librados::IoCtx *ioctx, const std::string &oid,
1353 cls::rbd::DirectoryState directory_state)
1354 {
1355 librados::ObjectWriteOperation op;
1356 dir_state_assert(&op, directory_state);
1357
1358 return ioctx->operate(oid, &op);
1359 }
1360
1361 void dir_state_set(librados::ObjectWriteOperation *op,
1362 cls::rbd::DirectoryState directory_state)
1363 {
1364 bufferlist bl;
1365 encode(directory_state, bl);
1366 op->exec("rbd", "dir_state_set", bl);
1367 }
1368
1369 int dir_state_set(librados::IoCtx *ioctx, const std::string &oid,
1370 cls::rbd::DirectoryState directory_state)
1371 {
1372 librados::ObjectWriteOperation op;
1373 dir_state_set(&op, directory_state);
1374
1375 return ioctx->operate(oid, &op);
1376 }
1377
1378 void dir_remove_image(librados::ObjectWriteOperation *op,
1379 const std::string &name, const std::string &id)
1380 {
1381 bufferlist bl;
1382 encode(name, bl);
1383 encode(id, bl);
1384
1385 op->exec("rbd", "dir_remove_image", bl);
1386 }
1387
1388 void dir_rename_image(librados::ObjectWriteOperation *op,
1389 const std::string &src, const std::string &dest,
1390 const std::string &id)
1391 {
1392 bufferlist in;
1393 encode(src, in);
1394 encode(dest, in);
1395 encode(id, in);
1396 op->exec("rbd", "dir_rename_image", in);
1397 }
1398
1399 void object_map_load_start(librados::ObjectReadOperation *op) {
1400 bufferlist in_bl;
1401 op->exec("rbd", "object_map_load", in_bl);
1402 }
1403
1404 int object_map_load_finish(bufferlist::const_iterator *it,
1405 ceph::BitVector<2> *object_map) {
1406 try {
1407 decode(*object_map, *it);
1408 } catch (const ceph::buffer::error &err) {
1409 return -EBADMSG;
1410 }
1411 return 0;
1412 }
1413
1414 int object_map_load(librados::IoCtx *ioctx, const std::string &oid,
1415 ceph::BitVector<2> *object_map)
1416 {
1417 librados::ObjectReadOperation op;
1418 object_map_load_start(&op);
1419
1420 bufferlist out_bl;
1421 int r = ioctx->operate(oid, &op, &out_bl);
1422 if (r < 0) {
1423 return r;
1424 }
1425
1426 auto it = out_bl.cbegin();
1427 return object_map_load_finish(&it, object_map);
1428 }
1429
1430 void object_map_save(librados::ObjectWriteOperation *rados_op,
1431 const ceph::BitVector<2> &object_map)
1432 {
1433 ceph::BitVector<2> object_map_copy(object_map);
1434 object_map_copy.set_crc_enabled(false);
1435
1436 bufferlist in;
1437 encode(object_map_copy, in);
1438 rados_op->exec("rbd", "object_map_save", in);
1439 }
1440
1441 void object_map_resize(librados::ObjectWriteOperation *rados_op,
1442 uint64_t object_count, uint8_t default_state)
1443 {
1444 bufferlist in;
1445 encode(object_count, in);
1446 encode(default_state, in);
1447 rados_op->exec("rbd", "object_map_resize", in);
1448 }
1449
1450 void object_map_update(librados::ObjectWriteOperation *rados_op,
1451 uint64_t start_object_no, uint64_t end_object_no,
1452 uint8_t new_object_state,
1453 const boost::optional<uint8_t> &current_object_state)
1454 {
1455 bufferlist in;
1456 encode(start_object_no, in);
1457 encode(end_object_no, in);
1458 encode(new_object_state, in);
1459 encode(current_object_state, in);
1460 rados_op->exec("rbd", "object_map_update", in);
1461 }
1462
1463 void object_map_snap_add(librados::ObjectWriteOperation *rados_op)
1464 {
1465 bufferlist in;
1466 rados_op->exec("rbd", "object_map_snap_add", in);
1467 }
1468
1469 void object_map_snap_remove(librados::ObjectWriteOperation *rados_op,
1470 const ceph::BitVector<2> &object_map)
1471 {
1472 ceph::BitVector<2> object_map_copy(object_map);
1473 object_map_copy.set_crc_enabled(false);
1474
1475 bufferlist in;
1476 encode(object_map_copy, in);
1477 rados_op->exec("rbd", "object_map_snap_remove", in);
1478 }
1479
1480 void metadata_set(librados::ObjectWriteOperation *op,
1481 const map<string, bufferlist> &data)
1482 {
1483 bufferlist bl;
1484 encode(data, bl);
1485
1486 op->exec("rbd", "metadata_set", bl);
1487 }
1488
1489 int metadata_set(librados::IoCtx *ioctx, const std::string &oid,
1490 const map<string, bufferlist> &data)
1491 {
1492 librados::ObjectWriteOperation op;
1493 metadata_set(&op, data);
1494
1495 return ioctx->operate(oid, &op);
1496 }
1497
1498 void metadata_remove(librados::ObjectWriteOperation *op,
1499 const std::string &key)
1500 {
1501 bufferlist bl;
1502 encode(key, bl);
1503
1504 op->exec("rbd", "metadata_remove", bl);
1505 }
1506
1507 int metadata_remove(librados::IoCtx *ioctx, const std::string &oid,
1508 const std::string &key)
1509 {
1510 librados::ObjectWriteOperation op;
1511 metadata_remove(&op, key);
1512
1513 return ioctx->operate(oid, &op);
1514 }
1515
1516 int metadata_list(librados::IoCtx *ioctx, const std::string &oid,
1517 const std::string &start, uint64_t max_return,
1518 map<string, bufferlist> *pairs)
1519 {
1520 librados::ObjectReadOperation op;
1521 metadata_list_start(&op, start, max_return);
1522
1523 bufferlist out_bl;
1524 int r = ioctx->operate(oid, &op, &out_bl);
1525 if (r < 0) {
1526 return r;
1527 }
1528
1529 auto it = out_bl.cbegin();
1530 return metadata_list_finish(&it, pairs);
1531 }
1532
1533 void metadata_list_start(librados::ObjectReadOperation *op,
1534 const std::string &start, uint64_t max_return)
1535 {
1536 bufferlist in_bl;
1537 encode(start, in_bl);
1538 encode(max_return, in_bl);
1539 op->exec("rbd", "metadata_list", in_bl);
1540 }
1541
1542 int metadata_list_finish(bufferlist::const_iterator *it,
1543 std::map<std::string, bufferlist> *pairs)
1544 {
1545 ceph_assert(pairs);
1546 try {
1547 decode(*pairs, *it);
1548 } catch (const ceph::buffer::error &err) {
1549 return -EBADMSG;
1550 }
1551 return 0;
1552 }
1553
1554 void metadata_get_start(librados::ObjectReadOperation* op,
1555 const std::string &key) {
1556 bufferlist bl;
1557 encode(key, bl);
1558
1559 op->exec("rbd", "metadata_get", bl);
1560 }
1561
1562 int metadata_get_finish(bufferlist::const_iterator *it,
1563 std::string* value) {
1564 try {
1565 decode(*value, *it);
1566 } catch (const ceph::buffer::error &err) {
1567 return -EBADMSG;
1568 }
1569 return 0;
1570 }
1571
1572 int metadata_get(librados::IoCtx *ioctx, const std::string &oid,
1573 const std::string &key, string *s)
1574 {
1575 ceph_assert(s);
1576 librados::ObjectReadOperation op;
1577 metadata_get_start(&op, key);
1578
1579 bufferlist out_bl;
1580 int r = ioctx->operate(oid, &op, &out_bl);
1581 if (r < 0) {
1582 return r;
1583 }
1584
1585 auto it = out_bl.cbegin();
1586 r = metadata_get_finish(&it, s);
1587 if (r < 0) {
1588 return r;
1589 }
1590 return 0;
1591 }
1592
1593 void child_attach(librados::ObjectWriteOperation *op, snapid_t snap_id,
1594 const cls::rbd::ChildImageSpec& child_image)
1595 {
1596 bufferlist bl;
1597 encode(snap_id, bl);
1598 encode(child_image, bl);
1599 op->exec("rbd", "child_attach", bl);
1600 }
1601
1602 int child_attach(librados::IoCtx *ioctx, const std::string &oid,
1603 snapid_t snap_id,
1604 const cls::rbd::ChildImageSpec& child_image)
1605 {
1606 librados::ObjectWriteOperation op;
1607 child_attach(&op, snap_id, child_image);
1608
1609 int r = ioctx->operate(oid, &op);
1610 if (r < 0) {
1611 return r;
1612 }
1613 return 0;
1614 }
1615
1616 void child_detach(librados::ObjectWriteOperation *op, snapid_t snap_id,
1617 const cls::rbd::ChildImageSpec& child_image)
1618 {
1619 bufferlist bl;
1620 encode(snap_id, bl);
1621 encode(child_image, bl);
1622 op->exec("rbd", "child_detach", bl);
1623 }
1624
1625 int child_detach(librados::IoCtx *ioctx, const std::string &oid,
1626 snapid_t snap_id,
1627 const cls::rbd::ChildImageSpec& child_image)
1628 {
1629 librados::ObjectWriteOperation op;
1630 child_detach(&op, snap_id, child_image);
1631
1632 int r = ioctx->operate(oid, &op);
1633 if (r < 0) {
1634 return r;
1635 }
1636 return 0;
1637 }
1638
1639 void children_list_start(librados::ObjectReadOperation *op,
1640 snapid_t snap_id)
1641 {
1642 bufferlist bl;
1643 encode(snap_id, bl);
1644 op->exec("rbd", "children_list", bl);
1645 }
1646
1647 int children_list_finish(bufferlist::const_iterator *it,
1648 cls::rbd::ChildImageSpecs *child_images)
1649 {
1650 child_images->clear();
1651 try {
1652 decode(*child_images, *it);
1653 } catch (const ceph::buffer::error &err) {
1654 return -EBADMSG;
1655 }
1656 return 0;
1657 }
1658
1659 int children_list(librados::IoCtx *ioctx, const std::string &oid,
1660 snapid_t snap_id,
1661 cls::rbd::ChildImageSpecs *child_images)
1662 {
1663 librados::ObjectReadOperation op;
1664 children_list_start(&op, snap_id);
1665
1666 bufferlist out_bl;
1667 int r = ioctx->operate(oid, &op, &out_bl);
1668 if (r < 0) {
1669 return r;
1670 }
1671
1672 auto it = out_bl.cbegin();
1673 r = children_list_finish(&it, child_images);
1674 if (r < 0) {
1675 return r;
1676 }
1677 return 0;
1678 }
1679
1680 int migration_set(librados::IoCtx *ioctx, const std::string &oid,
1681 const cls::rbd::MigrationSpec &migration_spec) {
1682 librados::ObjectWriteOperation op;
1683 migration_set(&op, migration_spec);
1684 return ioctx->operate(oid, &op);
1685 }
1686
1687 void migration_set(librados::ObjectWriteOperation *op,
1688 const cls::rbd::MigrationSpec &migration_spec) {
1689 bufferlist bl;
1690 encode(migration_spec, bl);
1691 op->exec("rbd", "migration_set", bl);
1692 }
1693
1694 int migration_set_state(librados::IoCtx *ioctx, const std::string &oid,
1695 cls::rbd::MigrationState state,
1696 const std::string &description) {
1697 librados::ObjectWriteOperation op;
1698 migration_set_state(&op, state, description);
1699 return ioctx->operate(oid, &op);
1700 }
1701
1702 void migration_set_state(librados::ObjectWriteOperation *op,
1703 cls::rbd::MigrationState state,
1704 const std::string &description) {
1705 bufferlist bl;
1706 encode(state, bl);
1707 encode(description, bl);
1708 op->exec("rbd", "migration_set_state", bl);
1709 }
1710
1711 void migration_get_start(librados::ObjectReadOperation *op) {
1712 bufferlist bl;
1713 op->exec("rbd", "migration_get", bl);
1714 }
1715
1716 int migration_get_finish(bufferlist::const_iterator *it,
1717 cls::rbd::MigrationSpec *migration_spec) {
1718 try {
1719 decode(*migration_spec, *it);
1720 } catch (const ceph::buffer::error &err) {
1721 return -EBADMSG;
1722 }
1723 return 0;
1724 }
1725
1726 int migration_get(librados::IoCtx *ioctx, const std::string &oid,
1727 cls::rbd::MigrationSpec *migration_spec) {
1728 librados::ObjectReadOperation op;
1729 migration_get_start(&op);
1730
1731 bufferlist out_bl;
1732 int r = ioctx->operate(oid, &op, &out_bl);
1733 if (r < 0) {
1734 return r;
1735 }
1736
1737 auto iter = out_bl.cbegin();
1738 r = migration_get_finish(&iter, migration_spec);
1739 if (r < 0) {
1740 return r;
1741 }
1742 return 0;
1743 }
1744
1745 int migration_remove(librados::IoCtx *ioctx, const std::string &oid) {
1746 librados::ObjectWriteOperation op;
1747 migration_remove(&op);
1748 return ioctx->operate(oid, &op);
1749 }
1750
1751 void migration_remove(librados::ObjectWriteOperation *op) {
1752 bufferlist bl;
1753 op->exec("rbd", "migration_remove", bl);
1754 }
1755
1756 template <typename O>
1757 void assert_snapc_seq(O* op, uint64_t snapc_seq,
1758 cls::rbd::AssertSnapcSeqState state) {
1759 bufferlist bl;
1760 encode(snapc_seq, bl);
1761 encode(state, bl);
1762 op->exec("rbd", "assert_snapc_seq", bl);
1763 }
1764
1765 void assert_snapc_seq(neorados::WriteOp* op,
1766 uint64_t snapc_seq,
1767 cls::rbd::AssertSnapcSeqState state) {
1768 assert_snapc_seq<neorados::WriteOp>(op, snapc_seq, state);
1769 }
1770
1771 void assert_snapc_seq(librados::ObjectWriteOperation *op,
1772 uint64_t snapc_seq,
1773 cls::rbd::AssertSnapcSeqState state) {
1774 assert_snapc_seq<librados::ObjectWriteOperation>(op, snapc_seq, state);
1775 }
1776
1777 int assert_snapc_seq(librados::IoCtx *ioctx, const std::string &oid,
1778 uint64_t snapc_seq,
1779 cls::rbd::AssertSnapcSeqState state) {
1780 librados::ObjectWriteOperation op;
1781 assert_snapc_seq(&op, snapc_seq, state);
1782 return ioctx->operate(oid, &op);
1783 }
1784
1785 void mirror_uuid_get_start(librados::ObjectReadOperation *op) {
1786 bufferlist bl;
1787 op->exec("rbd", "mirror_uuid_get", bl);
1788 }
1789
1790 int mirror_uuid_get_finish(bufferlist::const_iterator *it,
1791 std::string *uuid) {
1792 try {
1793 decode(*uuid, *it);
1794 } catch (const ceph::buffer::error &err) {
1795 return -EBADMSG;
1796 }
1797 return 0;
1798 }
1799
1800 int mirror_uuid_get(librados::IoCtx *ioctx, std::string *uuid) {
1801 librados::ObjectReadOperation op;
1802 mirror_uuid_get_start(&op);
1803
1804 bufferlist out_bl;
1805 int r = ioctx->operate(RBD_MIRRORING, &op, &out_bl);
1806 if (r < 0) {
1807 return r;
1808 }
1809
1810 auto it = out_bl.cbegin();
1811 r = mirror_uuid_get_finish(&it, uuid);
1812 if (r < 0) {
1813 return r;
1814 }
1815 return 0;
1816 }
1817
1818 int mirror_uuid_set(librados::IoCtx *ioctx, const std::string &uuid) {
1819 bufferlist in_bl;
1820 encode(uuid, in_bl);
1821
1822 bufferlist out_bl;
1823 int r = ioctx->exec(RBD_MIRRORING, "rbd", "mirror_uuid_set", in_bl,
1824 out_bl);
1825 if (r < 0) {
1826 return r;
1827 }
1828 return 0;
1829 }
1830
1831 void mirror_mode_get_start(librados::ObjectReadOperation *op) {
1832 bufferlist bl;
1833 op->exec("rbd", "mirror_mode_get", bl);
1834 }
1835
1836 int mirror_mode_get_finish(bufferlist::const_iterator *it,
1837 cls::rbd::MirrorMode *mirror_mode) {
1838 try {
1839 uint32_t mirror_mode_decode;
1840 decode(mirror_mode_decode, *it);
1841 *mirror_mode = static_cast<cls::rbd::MirrorMode>(mirror_mode_decode);
1842 } catch (const ceph::buffer::error &err) {
1843 return -EBADMSG;
1844 }
1845
1846 return 0;
1847 }
1848
1849 int mirror_mode_get(librados::IoCtx *ioctx,
1850 cls::rbd::MirrorMode *mirror_mode) {
1851 librados::ObjectReadOperation op;
1852 mirror_mode_get_start(&op);
1853
1854 bufferlist out_bl;
1855 int r = ioctx->operate(RBD_MIRRORING, &op, &out_bl);
1856 if (r == -ENOENT) {
1857 *mirror_mode = cls::rbd::MIRROR_MODE_DISABLED;
1858 return 0;
1859 } else if (r < 0) {
1860 return r;
1861 }
1862
1863 auto it = out_bl.cbegin();
1864 r = mirror_mode_get_finish(&it, mirror_mode);
1865 if (r < 0) {
1866 return r;
1867 }
1868 return 0;
1869 }
1870
1871 int mirror_mode_set(librados::IoCtx *ioctx,
1872 cls::rbd::MirrorMode mirror_mode) {
1873 bufferlist in_bl;
1874 encode(static_cast<uint32_t>(mirror_mode), in_bl);
1875
1876 bufferlist out_bl;
1877 int r = ioctx->exec(RBD_MIRRORING, "rbd", "mirror_mode_set", in_bl,
1878 out_bl);
1879 if (r < 0) {
1880 return r;
1881 }
1882 return 0;
1883 }
1884
1885 void mirror_peer_list_start(librados::ObjectReadOperation *op) {
1886 bufferlist bl;
1887 op->exec("rbd", "mirror_peer_list", bl);
1888 }
1889
1890 int mirror_peer_list_finish(bufferlist::const_iterator *it,
1891 std::vector<cls::rbd::MirrorPeer> *peers) {
1892 peers->clear();
1893 try {
1894 decode(*peers, *it);
1895 } catch (const ceph::buffer::error &err) {
1896 return -EBADMSG;
1897 }
1898 return 0;
1899 }
1900
1901 int mirror_peer_list(librados::IoCtx *ioctx,
1902 std::vector<cls::rbd::MirrorPeer> *peers) {
1903 librados::ObjectReadOperation op;
1904 mirror_peer_list_start(&op);
1905
1906 bufferlist out_bl;
1907 int r = ioctx->operate(RBD_MIRRORING, &op, &out_bl);
1908 if (r < 0) {
1909 return r;
1910 }
1911
1912 auto it = out_bl.cbegin();
1913 r = mirror_peer_list_finish(&it, peers);
1914 if (r < 0) {
1915 return r;
1916 }
1917 return 0;
1918 }
1919
1920 int mirror_peer_ping(librados::IoCtx *ioctx,
1921 const std::string& site_name,
1922 const std::string& fsid) {
1923 librados::ObjectWriteOperation op;
1924 mirror_peer_ping(&op, site_name, fsid);
1925
1926 int r = ioctx->operate(RBD_MIRRORING, &op);
1927 if (r < 0) {
1928 return r;
1929 }
1930
1931 return 0;
1932 }
1933
1934 void mirror_peer_ping(librados::ObjectWriteOperation *op,
1935 const std::string& site_name,
1936 const std::string& fsid) {
1937 bufferlist in_bl;
1938 encode(site_name, in_bl);
1939 encode(fsid, in_bl);
1940 encode(static_cast<uint8_t>(cls::rbd::MIRROR_PEER_DIRECTION_TX), in_bl);
1941
1942 op->exec("rbd", "mirror_peer_ping", in_bl);
1943 }
1944
1945 int mirror_peer_add(librados::IoCtx *ioctx,
1946 const cls::rbd::MirrorPeer& mirror_peer) {
1947 librados::ObjectWriteOperation op;
1948 mirror_peer_add(&op, mirror_peer);
1949
1950 int r = ioctx->operate(RBD_MIRRORING, &op);
1951 if (r < 0) {
1952 return r;
1953 }
1954
1955 return 0;
1956 }
1957
1958 void mirror_peer_add(librados::ObjectWriteOperation *op,
1959 const cls::rbd::MirrorPeer& mirror_peer) {
1960 bufferlist in_bl;
1961 encode(mirror_peer, in_bl);
1962
1963 op->exec("rbd", "mirror_peer_add", in_bl);
1964 }
1965
1966 int mirror_peer_remove(librados::IoCtx *ioctx,
1967 const std::string &uuid) {
1968 bufferlist in_bl;
1969 encode(uuid, in_bl);
1970
1971 bufferlist out_bl;
1972 int r = ioctx->exec(RBD_MIRRORING, "rbd", "mirror_peer_remove", in_bl,
1973 out_bl);
1974 if (r < 0) {
1975 return r;
1976 }
1977 return 0;
1978 }
1979
1980 int mirror_peer_set_client(librados::IoCtx *ioctx,
1981 const std::string &uuid,
1982 const std::string &client_name) {
1983 bufferlist in_bl;
1984 encode(uuid, in_bl);
1985 encode(client_name, in_bl);
1986
1987 bufferlist out_bl;
1988 int r = ioctx->exec(RBD_MIRRORING, "rbd", "mirror_peer_set_client",
1989 in_bl, out_bl);
1990 if (r < 0) {
1991 return r;
1992 }
1993 return 0;
1994 }
1995
1996 int mirror_peer_set_cluster(librados::IoCtx *ioctx,
1997 const std::string &uuid,
1998 const std::string &cluster_name) {
1999 bufferlist in_bl;
2000 encode(uuid, in_bl);
2001 encode(cluster_name, in_bl);
2002
2003 bufferlist out_bl;
2004 int r = ioctx->exec(RBD_MIRRORING, "rbd", "mirror_peer_set_cluster",
2005 in_bl, out_bl);
2006 if (r < 0) {
2007 return r;
2008 }
2009 return 0;
2010 }
2011
2012 int mirror_peer_set_direction(
2013 librados::IoCtx *ioctx, const std::string &uuid,
2014 cls::rbd::MirrorPeerDirection mirror_peer_direction) {
2015 bufferlist in_bl;
2016 encode(uuid, in_bl);
2017 encode(static_cast<uint8_t>(mirror_peer_direction), in_bl);
2018
2019 bufferlist out_bl;
2020 int r = ioctx->exec(RBD_MIRRORING, "rbd", "mirror_peer_set_direction",
2021 in_bl, out_bl);
2022 if (r < 0) {
2023 return r;
2024 }
2025 return 0;
2026 }
2027
2028 void mirror_image_list_start(librados::ObjectReadOperation *op,
2029 const std::string &start, uint64_t max_return)
2030 {
2031 bufferlist in_bl;
2032 encode(start, in_bl);
2033 encode(max_return, in_bl);
2034 op->exec("rbd", "mirror_image_list", in_bl);
2035 }
2036
2037 int mirror_image_list_finish(bufferlist::const_iterator *it,
2038 std::map<string, string> *mirror_image_ids)
2039 {
2040 try {
2041 decode(*mirror_image_ids, *it);
2042 } catch (const ceph::buffer::error &err) {
2043 return -EBADMSG;
2044 }
2045 return 0;
2046 }
2047
2048 int mirror_image_list(librados::IoCtx *ioctx,
2049 const std::string &start, uint64_t max_return,
2050 std::map<std::string, std::string> *mirror_image_ids) {
2051 librados::ObjectReadOperation op;
2052 mirror_image_list_start(&op, start, max_return);
2053
2054 bufferlist out_bl;
2055 int r = ioctx->operate(RBD_MIRRORING, &op, &out_bl);
2056 if (r < 0) {
2057 return r;
2058 }
2059
2060 auto bl_it = out_bl.cbegin();
2061 return mirror_image_list_finish(&bl_it, mirror_image_ids);
2062 }
2063
2064 void mirror_image_get_image_id_start(librados::ObjectReadOperation *op,
2065 const std::string &global_image_id) {
2066 bufferlist in_bl;
2067 encode(global_image_id, in_bl);
2068 op->exec( "rbd", "mirror_image_get_image_id", in_bl);
2069 }
2070
2071 int mirror_image_get_image_id_finish(bufferlist::const_iterator *it,
2072 std::string *image_id) {
2073 try {
2074 decode(*image_id, *it);
2075 } catch (const ceph::buffer::error &err) {
2076 return -EBADMSG;
2077 }
2078 return 0;
2079 }
2080
2081 int mirror_image_get_image_id(librados::IoCtx *ioctx,
2082 const std::string &global_image_id,
2083 std::string *image_id) {
2084 librados::ObjectReadOperation op;
2085 mirror_image_get_image_id_start(&op, global_image_id);
2086
2087 bufferlist out_bl;
2088 int r = ioctx->operate(RBD_MIRRORING, &op, &out_bl);
2089 if (r < 0) {
2090 return r;
2091 }
2092
2093 auto it = out_bl.cbegin();
2094 return mirror_image_get_image_id_finish(&it, image_id);
2095 }
2096
2097 int mirror_image_get(librados::IoCtx *ioctx, const std::string &image_id,
2098 cls::rbd::MirrorImage *mirror_image) {
2099 librados::ObjectReadOperation op;
2100 mirror_image_get_start(&op, image_id);
2101
2102 bufferlist out_bl;
2103 int r = ioctx->operate(RBD_MIRRORING, &op, &out_bl);
2104 if (r < 0) {
2105 return r;
2106 }
2107
2108 auto iter = out_bl.cbegin();
2109 r = mirror_image_get_finish(&iter, mirror_image);
2110 if (r < 0) {
2111 return r;
2112 }
2113 return 0;
2114 }
2115
2116 void mirror_image_get_start(librados::ObjectReadOperation *op,
2117 const std::string &image_id) {
2118 bufferlist in_bl;
2119 encode(image_id, in_bl);
2120
2121 op->exec("rbd", "mirror_image_get", in_bl);
2122 }
2123
2124 int mirror_image_get_finish(bufferlist::const_iterator *iter,
2125 cls::rbd::MirrorImage *mirror_image) {
2126 try {
2127 decode(*mirror_image, *iter);
2128 } catch (const ceph::buffer::error &err) {
2129 return -EBADMSG;
2130 }
2131 return 0;
2132 }
2133
2134 void mirror_image_set(librados::ObjectWriteOperation *op,
2135 const std::string &image_id,
2136 const cls::rbd::MirrorImage &mirror_image) {
2137 bufferlist bl;
2138 encode(image_id, bl);
2139 encode(mirror_image, bl);
2140
2141 op->exec("rbd", "mirror_image_set", bl);
2142 }
2143
2144 int mirror_image_set(librados::IoCtx *ioctx, const std::string &image_id,
2145 const cls::rbd::MirrorImage &mirror_image) {
2146 librados::ObjectWriteOperation op;
2147 mirror_image_set(&op, image_id, mirror_image);
2148
2149 int r = ioctx->operate(RBD_MIRRORING, &op);
2150 if (r < 0) {
2151 return r;
2152 }
2153 return 0;
2154 }
2155
2156 void mirror_image_remove(librados::ObjectWriteOperation *op,
2157 const std::string &image_id) {
2158 bufferlist bl;
2159 encode(image_id, bl);
2160
2161 op->exec("rbd", "mirror_image_remove", bl);
2162 }
2163
2164 int mirror_image_remove(librados::IoCtx *ioctx, const std::string &image_id) {
2165 librados::ObjectWriteOperation op;
2166 mirror_image_remove(&op, image_id);
2167
2168 int r = ioctx->operate(RBD_MIRRORING, &op);
2169 if (r < 0) {
2170 return r;
2171 }
2172 return 0;
2173 }
2174
2175 int mirror_image_status_set(librados::IoCtx *ioctx,
2176 const std::string &global_image_id,
2177 const cls::rbd::MirrorImageSiteStatus &status) {
2178 librados::ObjectWriteOperation op;
2179 mirror_image_status_set(&op, global_image_id, status);
2180 return ioctx->operate(RBD_MIRRORING, &op);
2181 }
2182
2183 void mirror_image_status_set(librados::ObjectWriteOperation *op,
2184 const std::string &global_image_id,
2185 const cls::rbd::MirrorImageSiteStatus &status) {
2186 bufferlist bl;
2187 encode(global_image_id, bl);
2188 encode(status, bl);
2189 op->exec("rbd", "mirror_image_status_set", bl);
2190 }
2191
2192 int mirror_image_status_get(librados::IoCtx *ioctx,
2193 const std::string &global_image_id,
2194 cls::rbd::MirrorImageStatus *status) {
2195 librados::ObjectReadOperation op;
2196 mirror_image_status_get_start(&op, global_image_id);
2197
2198 bufferlist out_bl;
2199 int r = ioctx->operate(RBD_MIRRORING, &op, &out_bl);
2200 if (r < 0) {
2201 return r;
2202 }
2203
2204 auto iter = out_bl.cbegin();
2205 r = mirror_image_status_get_finish(&iter, status);
2206 if (r < 0) {
2207 return r;
2208 }
2209 return 0;
2210 }
2211
2212 void mirror_image_status_get_start(librados::ObjectReadOperation *op,
2213 const std::string &global_image_id) {
2214 bufferlist bl;
2215 encode(global_image_id, bl);
2216 op->exec("rbd", "mirror_image_status_get", bl);
2217 }
2218
2219 int mirror_image_status_get_finish(bufferlist::const_iterator *iter,
2220 cls::rbd::MirrorImageStatus *status) {
2221 try {
2222 decode(*status, *iter);
2223 } catch (const ceph::buffer::error &err) {
2224 return -EBADMSG;
2225 }
2226 return 0;
2227 }
2228
2229 int mirror_image_status_list(librados::IoCtx *ioctx,
2230 const std::string &start, uint64_t max_return,
2231 std::map<std::string, cls::rbd::MirrorImage> *images,
2232 std::map<std::string, cls::rbd::MirrorImageStatus> *statuses) {
2233 librados::ObjectReadOperation op;
2234 mirror_image_status_list_start(&op, start, max_return);
2235
2236 bufferlist out_bl;
2237 int r = ioctx->operate(RBD_MIRRORING, &op, &out_bl);
2238 if (r < 0) {
2239 return r;
2240 }
2241
2242 auto iter = out_bl.cbegin();
2243 r = mirror_image_status_list_finish(&iter, images, statuses);
2244 if (r < 0) {
2245 return r;
2246 }
2247 return 0;
2248 }
2249
2250 void mirror_image_status_list_start(librados::ObjectReadOperation *op,
2251 const std::string &start,
2252 uint64_t max_return) {
2253 bufferlist bl;
2254 encode(start, bl);
2255 encode(max_return, bl);
2256 op->exec("rbd", "mirror_image_status_list", bl);
2257 }
2258
2259 int mirror_image_status_list_finish(bufferlist::const_iterator *iter,
2260 std::map<std::string, cls::rbd::MirrorImage> *images,
2261 std::map<std::string, cls::rbd::MirrorImageStatus> *statuses) {
2262 images->clear();
2263 statuses->clear();
2264 try {
2265 decode(*images, *iter);
2266 decode(*statuses, *iter);
2267 } catch (const ceph::buffer::error &err) {
2268 return -EBADMSG;
2269 }
2270 return 0;
2271 }
2272
2273 int mirror_image_status_get_summary(
2274 librados::IoCtx *ioctx,
2275 const std::vector<cls::rbd::MirrorPeer>& mirror_peer_sites,
2276 std::map<cls::rbd::MirrorImageStatusState, int32_t> *states) {
2277 librados::ObjectReadOperation op;
2278 mirror_image_status_get_summary_start(&op, mirror_peer_sites);
2279
2280 bufferlist out_bl;
2281 int r = ioctx->operate(RBD_MIRRORING, &op, &out_bl);
2282 if (r < 0) {
2283 return r;
2284 }
2285
2286 auto iter = out_bl.cbegin();
2287 r = mirror_image_status_get_summary_finish(&iter, states);
2288 if (r < 0) {
2289 return r;
2290 }
2291 return 0;
2292 }
2293
2294 void mirror_image_status_get_summary_start(
2295 librados::ObjectReadOperation *op,
2296 const std::vector<cls::rbd::MirrorPeer>& mirror_peer_sites) {
2297 bufferlist bl;
2298 encode(mirror_peer_sites, bl);
2299 op->exec("rbd", "mirror_image_status_get_summary", bl);
2300 }
2301
2302 int mirror_image_status_get_summary_finish(
2303 bufferlist::const_iterator *iter,
2304 std::map<cls::rbd::MirrorImageStatusState, int32_t> *states) {
2305 try {
2306 decode(*states, *iter);
2307 } catch (const ceph::buffer::error &err) {
2308 return -EBADMSG;
2309 }
2310 return 0;
2311 }
2312
2313 int mirror_image_status_remove_down(librados::IoCtx *ioctx) {
2314 librados::ObjectWriteOperation op;
2315 mirror_image_status_remove_down(&op);
2316 return ioctx->operate(RBD_MIRRORING, &op);
2317 }
2318
2319 void mirror_image_status_remove_down(librados::ObjectWriteOperation *op) {
2320 bufferlist bl;
2321 op->exec("rbd", "mirror_image_status_remove_down", bl);
2322 }
2323
2324 int mirror_image_instance_get(librados::IoCtx *ioctx,
2325 const std::string &global_image_id,
2326 entity_inst_t *instance) {
2327 librados::ObjectReadOperation op;
2328 mirror_image_instance_get_start(&op, global_image_id);
2329
2330 bufferlist out_bl;
2331 int r = ioctx->operate(RBD_MIRRORING, &op, &out_bl);
2332 if (r < 0) {
2333 return r;
2334 }
2335
2336 auto iter = out_bl.cbegin();
2337 r = mirror_image_instance_get_finish(&iter, instance);
2338 if (r < 0) {
2339 return r;
2340 }
2341 return 0;
2342 }
2343
2344 void mirror_image_instance_get_start(librados::ObjectReadOperation *op,
2345 const std::string &global_image_id) {
2346 bufferlist bl;
2347 encode(global_image_id, bl);
2348 op->exec("rbd", "mirror_image_instance_get", bl);
2349 }
2350
2351 int mirror_image_instance_get_finish(bufferlist::const_iterator *iter,
2352 entity_inst_t *instance) {
2353 try {
2354 decode(*instance, *iter);
2355 } catch (const ceph::buffer::error &err) {
2356 return -EBADMSG;
2357 }
2358 return 0;
2359 }
2360
2361 int mirror_image_instance_list(
2362 librados::IoCtx *ioctx, const std::string &start, uint64_t max_return,
2363 std::map<std::string, entity_inst_t> *instances) {
2364 librados::ObjectReadOperation op;
2365 mirror_image_instance_list_start(&op, start, max_return);
2366
2367 bufferlist out_bl;
2368 int r = ioctx->operate(RBD_MIRRORING, &op, &out_bl);
2369 if (r < 0) {
2370 return r;
2371 }
2372
2373 auto iter = out_bl.cbegin();
2374 r = mirror_image_instance_list_finish(&iter, instances);
2375 if (r < 0) {
2376 return r;
2377 }
2378 return 0;
2379 }
2380
2381 void mirror_image_instance_list_start(librados::ObjectReadOperation *op,
2382 const std::string &start,
2383 uint64_t max_return) {
2384 bufferlist bl;
2385 encode(start, bl);
2386 encode(max_return, bl);
2387 op->exec("rbd", "mirror_image_instance_list", bl);
2388 }
2389
2390 int mirror_image_instance_list_finish(
2391 bufferlist::const_iterator *iter,
2392 std::map<std::string, entity_inst_t> *instances) {
2393 instances->clear();
2394 try {
2395 decode(*instances, *iter);
2396 } catch (const ceph::buffer::error &err) {
2397 return -EBADMSG;
2398 }
2399 return 0;
2400 }
2401
2402 void mirror_instances_list_start(librados::ObjectReadOperation *op) {
2403 bufferlist bl;
2404 op->exec("rbd", "mirror_instances_list", bl);
2405 }
2406
2407 int mirror_instances_list_finish(bufferlist::const_iterator *iter,
2408 std::vector<std::string> *instance_ids) {
2409 instance_ids->clear();
2410 try {
2411 decode(*instance_ids, *iter);
2412 } catch (const ceph::buffer::error &err) {
2413 return -EBADMSG;
2414 }
2415 return 0;
2416 }
2417
2418 int mirror_instances_list(librados::IoCtx *ioctx,
2419 std::vector<std::string> *instance_ids) {
2420 librados::ObjectReadOperation op;
2421 mirror_instances_list_start(&op);
2422
2423 bufferlist out_bl;
2424 int r = ioctx->operate(RBD_MIRROR_LEADER, &op, &out_bl);
2425 if (r < 0) {
2426 return r;
2427 }
2428
2429 auto iter = out_bl.cbegin();
2430 r = mirror_instances_list_finish(&iter, instance_ids);
2431 if (r < 0) {
2432 return r;
2433 }
2434 return 0;
2435 }
2436
2437 void mirror_instances_add(librados::ObjectWriteOperation *op,
2438 const std::string &instance_id) {
2439 bufferlist bl;
2440 encode(instance_id, bl);
2441 op->exec("rbd", "mirror_instances_add", bl);
2442 }
2443
2444 int mirror_instances_add(librados::IoCtx *ioctx,
2445 const std::string &instance_id) {
2446 librados::ObjectWriteOperation op;
2447 mirror_instances_add(&op, instance_id);
2448 return ioctx->operate(RBD_MIRROR_LEADER, &op);
2449 }
2450
2451 void mirror_instances_remove(librados::ObjectWriteOperation *op,
2452 const std::string &instance_id) {
2453 bufferlist bl;
2454 encode(instance_id, bl);
2455 op->exec("rbd", "mirror_instances_remove", bl);
2456 }
2457
2458 int mirror_instances_remove(librados::IoCtx *ioctx,
2459 const std::string &instance_id) {
2460 librados::ObjectWriteOperation op;
2461 mirror_instances_remove(&op, instance_id);
2462 return ioctx->operate(RBD_MIRROR_LEADER, &op);
2463 }
2464
2465 void mirror_image_map_list_start(librados::ObjectReadOperation *op,
2466 const std::string &start_after,
2467 uint64_t max_read) {
2468 bufferlist bl;
2469 encode(start_after, bl);
2470 encode(max_read, bl);
2471
2472 op->exec("rbd", "mirror_image_map_list", bl);
2473 }
2474
2475 int mirror_image_map_list_finish(bufferlist::const_iterator *iter,
2476 std::map<std::string, cls::rbd::MirrorImageMap> *image_mapping) {
2477 try {
2478 decode(*image_mapping, *iter);
2479 } catch (const ceph::buffer::error &err) {
2480 return -EBADMSG;
2481 }
2482 return 0;
2483 }
2484
2485 int mirror_image_map_list(
2486 librados::IoCtx *ioctx, const std::string &start_after,
2487 uint64_t max_read,
2488 std::map<std::string, cls::rbd::MirrorImageMap> *image_mapping) {
2489 librados::ObjectReadOperation op;
2490 mirror_image_map_list_start(&op, start_after, max_read);
2491
2492 bufferlist out_bl;
2493 int r = ioctx->operate(RBD_MIRRORING, &op, &out_bl);
2494 if (r < 0) {
2495 return r;
2496 }
2497
2498 auto iter = out_bl.cbegin();
2499 return mirror_image_map_list_finish(&iter, image_mapping);
2500 }
2501
2502 void mirror_image_map_update(librados::ObjectWriteOperation *op,
2503 const std::string &global_image_id,
2504 const cls::rbd::MirrorImageMap &image_map) {
2505 bufferlist bl;
2506 encode(global_image_id, bl);
2507 encode(image_map, bl);
2508
2509 op->exec("rbd", "mirror_image_map_update", bl);
2510 }
2511
2512 void mirror_image_map_remove(librados::ObjectWriteOperation *op,
2513 const std::string &global_image_id) {
2514 bufferlist bl;
2515 encode(global_image_id, bl);
2516
2517 op->exec("rbd", "mirror_image_map_remove", bl);
2518 }
2519
2520 void mirror_image_snapshot_unlink_peer(librados::ObjectWriteOperation *op,
2521 snapid_t snap_id,
2522 const std::string &mirror_peer_uuid) {
2523 bufferlist bl;
2524 encode(snap_id, bl);
2525 encode(mirror_peer_uuid, bl);
2526
2527 op->exec("rbd", "mirror_image_snapshot_unlink_peer", bl);
2528 }
2529
2530 int mirror_image_snapshot_unlink_peer(librados::IoCtx *ioctx,
2531 const std::string &oid,
2532 snapid_t snap_id,
2533 const std::string &mirror_peer_uuid) {
2534 librados::ObjectWriteOperation op;
2535 mirror_image_snapshot_unlink_peer(&op, snap_id, mirror_peer_uuid);
2536 return ioctx->operate(oid, &op);
2537 }
2538
2539 void mirror_image_snapshot_set_copy_progress(librados::ObjectWriteOperation *op,
2540 snapid_t snap_id, bool complete,
2541 uint64_t copy_progress) {
2542 bufferlist bl;
2543 encode(snap_id, bl);
2544 encode(complete, bl);
2545 encode(copy_progress, bl);
2546
2547 op->exec("rbd", "mirror_image_snapshot_set_copy_progress", bl);
2548 }
2549
2550 int mirror_image_snapshot_set_copy_progress(librados::IoCtx *ioctx,
2551 const std::string &oid,
2552 snapid_t snap_id, bool complete,
2553 uint64_t copy_progress) {
2554 librados::ObjectWriteOperation op;
2555 mirror_image_snapshot_set_copy_progress(&op, snap_id, complete,
2556 copy_progress);
2557 return ioctx->operate(oid, &op);
2558 }
2559
2560 // Groups functions
2561 int group_dir_list(librados::IoCtx *ioctx, const std::string &oid,
2562 const std::string &start, uint64_t max_return,
2563 map<string, string> *cgs)
2564 {
2565 bufferlist in, out;
2566 encode(start, in);
2567 encode(max_return, in);
2568 int r = ioctx->exec(oid, "rbd", "group_dir_list", in, out);
2569 if (r < 0)
2570 return r;
2571
2572 auto iter = out.cbegin();
2573 try {
2574 decode(*cgs, iter);
2575 } catch (const ceph::buffer::error &err) {
2576 return -EBADMSG;
2577 }
2578
2579 return 0;
2580 }
2581
2582 int group_dir_add(librados::IoCtx *ioctx, const std::string &oid,
2583 const std::string &name, const std::string &id)
2584 {
2585 bufferlist in, out;
2586 encode(name, in);
2587 encode(id, in);
2588 return ioctx->exec(oid, "rbd", "group_dir_add", in, out);
2589 }
2590
2591 int group_dir_rename(librados::IoCtx *ioctx, const std::string &oid,
2592 const std::string &src, const std::string &dest,
2593 const std::string &id)
2594 {
2595 bufferlist in, out;
2596 encode(src, in);
2597 encode(dest, in);
2598 encode(id, in);
2599 return ioctx->exec(oid, "rbd", "group_dir_rename", in, out);
2600 }
2601
2602 int group_dir_remove(librados::IoCtx *ioctx, const std::string &oid,
2603 const std::string &name, const std::string &id)
2604 {
2605 bufferlist in, out;
2606 encode(name, in);
2607 encode(id, in);
2608 return ioctx->exec(oid, "rbd", "group_dir_remove", in, out);
2609 }
2610
2611 int group_image_remove(librados::IoCtx *ioctx, const std::string &oid,
2612 const cls::rbd::GroupImageSpec &spec)
2613 {
2614 bufferlist bl, bl2;
2615 encode(spec, bl);
2616
2617 return ioctx->exec(oid, "rbd", "group_image_remove", bl, bl2);
2618 }
2619
2620 int group_image_list(librados::IoCtx *ioctx,
2621 const std::string &oid,
2622 const cls::rbd::GroupImageSpec &start,
2623 uint64_t max_return,
2624 std::vector<cls::rbd::GroupImageStatus> *images)
2625 {
2626 bufferlist bl, bl2;
2627 encode(start, bl);
2628 encode(max_return, bl);
2629
2630 int r = ioctx->exec(oid, "rbd", "group_image_list", bl, bl2);
2631 if (r < 0)
2632 return r;
2633
2634 auto iter = bl2.cbegin();
2635 try {
2636 decode(*images, iter);
2637 } catch (const ceph::buffer::error &err) {
2638 return -EBADMSG;
2639 }
2640
2641 return 0;
2642 }
2643
2644 int group_image_set(librados::IoCtx *ioctx, const std::string &oid,
2645 const cls::rbd::GroupImageStatus &st)
2646 {
2647 bufferlist bl, bl2;
2648 encode(st, bl);
2649
2650 return ioctx->exec(oid, "rbd", "group_image_set", bl, bl2);
2651 }
2652
2653 int image_group_add(librados::IoCtx *ioctx, const std::string &oid,
2654 const cls::rbd::GroupSpec &group_spec)
2655 {
2656 bufferlist bl, bl2;
2657 encode(group_spec, bl);
2658
2659 return ioctx->exec(oid, "rbd", "image_group_add", bl, bl2);
2660 }
2661
2662 int image_group_remove(librados::IoCtx *ioctx, const std::string &oid,
2663 const cls::rbd::GroupSpec &group_spec)
2664 {
2665 bufferlist bl, bl2;
2666 encode(group_spec, bl);
2667
2668 return ioctx->exec(oid, "rbd", "image_group_remove", bl, bl2);
2669 }
2670
2671 void image_group_get_start(librados::ObjectReadOperation *op)
2672 {
2673 bufferlist in_bl;
2674 op->exec("rbd", "image_group_get", in_bl);
2675 }
2676
2677 int image_group_get_finish(bufferlist::const_iterator *iter,
2678 cls::rbd::GroupSpec *group_spec)
2679 {
2680 try {
2681 decode(*group_spec, *iter);
2682 } catch (const ceph::buffer::error &err) {
2683 return -EBADMSG;
2684 }
2685 return 0;
2686 }
2687
2688 int image_group_get(librados::IoCtx *ioctx, const std::string &oid,
2689 cls::rbd::GroupSpec *group_spec)
2690 {
2691 librados::ObjectReadOperation op;
2692 image_group_get_start(&op);
2693
2694 bufferlist out_bl;
2695 int r = ioctx->operate(oid, &op, &out_bl);
2696 if (r < 0) {
2697 return r;
2698 }
2699
2700 auto iter = out_bl.cbegin();
2701 return image_group_get_finish(&iter, group_spec);
2702 }
2703
2704 int group_snap_set(librados::IoCtx *ioctx, const std::string &oid,
2705 const cls::rbd::GroupSnapshot &snapshot)
2706 {
2707 using ceph::encode;
2708 bufferlist inbl, outbl;
2709 encode(snapshot, inbl);
2710 int r = ioctx->exec(oid, "rbd", "group_snap_set", inbl, outbl);
2711 return r;
2712 }
2713
2714 int group_snap_remove(librados::IoCtx *ioctx, const std::string &oid,
2715 const std::string &snap_id)
2716 {
2717 using ceph::encode;
2718 bufferlist inbl, outbl;
2719 encode(snap_id, inbl);
2720 return ioctx->exec(oid, "rbd", "group_snap_remove", inbl, outbl);
2721 }
2722
2723 int group_snap_get_by_id(librados::IoCtx *ioctx, const std::string &oid,
2724 const std::string &snap_id,
2725 cls::rbd::GroupSnapshot *snapshot)
2726 {
2727 using ceph::encode;
2728 using ceph::decode;
2729 bufferlist inbl, outbl;
2730
2731 encode(snap_id, inbl);
2732 int r = ioctx->exec(oid, "rbd", "group_snap_get_by_id", inbl, outbl);
2733 if (r < 0) {
2734 return r;
2735 }
2736
2737 auto iter = outbl.cbegin();
2738 try {
2739 decode(*snapshot, iter);
2740 } catch (const ceph::buffer::error &err) {
2741 return -EBADMSG;
2742 }
2743
2744 return 0;
2745 }
2746 int group_snap_list(librados::IoCtx *ioctx, const std::string &oid,
2747 const cls::rbd::GroupSnapshot &start,
2748 uint64_t max_return,
2749 std::vector<cls::rbd::GroupSnapshot> *snapshots)
2750 {
2751 using ceph::encode;
2752 using ceph::decode;
2753 bufferlist inbl, outbl;
2754 encode(start, inbl);
2755 encode(max_return, inbl);
2756
2757 int r = ioctx->exec(oid, "rbd", "group_snap_list", inbl, outbl);
2758 if (r < 0) {
2759 return r;
2760 }
2761 auto iter = outbl.cbegin();
2762 try {
2763 decode(*snapshots, iter);
2764 } catch (const ceph::buffer::error &err) {
2765 return -EBADMSG;
2766 }
2767
2768 return 0;
2769 }
2770
2771 // rbd_trash functions
2772 void trash_add(librados::ObjectWriteOperation *op,
2773 const std::string &id,
2774 const cls::rbd::TrashImageSpec &trash_spec)
2775 {
2776 bufferlist bl;
2777 encode(id, bl);
2778 encode(trash_spec, bl);
2779 op->exec("rbd", "trash_add", bl);
2780 }
2781
2782 int trash_add(librados::IoCtx *ioctx, const std::string &id,
2783 const cls::rbd::TrashImageSpec &trash_spec)
2784 {
2785 librados::ObjectWriteOperation op;
2786 trash_add(&op, id, trash_spec);
2787
2788 return ioctx->operate(RBD_TRASH, &op);
2789 }
2790
2791 void trash_remove(librados::ObjectWriteOperation *op,
2792 const std::string &id)
2793 {
2794 bufferlist bl;
2795 encode(id, bl);
2796 op->exec("rbd", "trash_remove", bl);
2797 }
2798
2799 int trash_remove(librados::IoCtx *ioctx, const std::string &id)
2800 {
2801 librados::ObjectWriteOperation op;
2802 trash_remove(&op, id);
2803
2804 return ioctx->operate(RBD_TRASH, &op);
2805 }
2806
2807 void trash_list_start(librados::ObjectReadOperation *op,
2808 const std::string &start, uint64_t max_return)
2809 {
2810 bufferlist bl;
2811 encode(start, bl);
2812 encode(max_return, bl);
2813 op->exec("rbd", "trash_list", bl);
2814 }
2815
2816 int trash_list_finish(bufferlist::const_iterator *it,
2817 map<string, cls::rbd::TrashImageSpec> *entries)
2818 {
2819 ceph_assert(entries);
2820
2821 try {
2822 decode(*entries, *it);
2823 } catch (const ceph::buffer::error &err) {
2824 return -EBADMSG;
2825 }
2826
2827 return 0;
2828 }
2829
2830 int trash_list(librados::IoCtx *ioctx,
2831 const std::string &start, uint64_t max_return,
2832 map<string, cls::rbd::TrashImageSpec> *entries)
2833 {
2834 librados::ObjectReadOperation op;
2835 trash_list_start(&op, start, max_return);
2836
2837 bufferlist out_bl;
2838 int r = ioctx->operate(RBD_TRASH, &op, &out_bl);
2839 if (r < 0) {
2840 return r;
2841 }
2842
2843 auto iter = out_bl.cbegin();
2844 return trash_list_finish(&iter, entries);
2845 }
2846
2847 void trash_get_start(librados::ObjectReadOperation *op,
2848 const std::string &id)
2849 {
2850 bufferlist bl;
2851 encode(id, bl);
2852 op->exec("rbd", "trash_get", bl);
2853 }
2854
2855 int trash_get_finish(bufferlist::const_iterator *it,
2856 cls::rbd::TrashImageSpec *trash_spec) {
2857 ceph_assert(trash_spec);
2858 try {
2859 decode(*trash_spec, *it);
2860 } catch (const ceph::buffer::error &err) {
2861 return -EBADMSG;
2862 }
2863
2864 return 0;
2865 }
2866
2867 int trash_get(librados::IoCtx *ioctx, const std::string &id,
2868 cls::rbd::TrashImageSpec *trash_spec)
2869 {
2870 librados::ObjectReadOperation op;
2871 trash_get_start(&op, id);
2872
2873 bufferlist out_bl;
2874 int r = ioctx->operate(RBD_TRASH, &op, &out_bl);
2875 if (r < 0) {
2876 return r;
2877 }
2878
2879 auto it = out_bl.cbegin();
2880 return trash_get_finish(&it, trash_spec);
2881 }
2882
2883 void trash_state_set(librados::ObjectWriteOperation *op,
2884 const std::string &id,
2885 const cls::rbd::TrashImageState &trash_state,
2886 const cls::rbd::TrashImageState &expect_state)
2887 {
2888 bufferlist bl;
2889 encode(id, bl);
2890 encode(trash_state, bl);
2891 encode(expect_state, bl);
2892 op->exec("rbd", "trash_state_set", bl);
2893 }
2894
2895 int trash_state_set(librados::IoCtx *ioctx, const std::string &id,
2896 const cls::rbd::TrashImageState &trash_state,
2897 const cls::rbd::TrashImageState &expect_state)
2898 {
2899 librados::ObjectWriteOperation op;
2900 trash_state_set(&op, id, trash_state, expect_state);
2901
2902 return ioctx->operate(RBD_TRASH, &op);
2903 }
2904
2905 void namespace_add(librados::ObjectWriteOperation *op,
2906 const std::string &name)
2907 {
2908 bufferlist bl;
2909 encode(name, bl);
2910 op->exec("rbd", "namespace_add", bl);
2911 }
2912
2913 int namespace_add(librados::IoCtx *ioctx, const std::string &name)
2914 {
2915 librados::ObjectWriteOperation op;
2916 namespace_add(&op, name);
2917
2918 return ioctx->operate(RBD_NAMESPACE, &op);
2919 }
2920
2921 void namespace_remove(librados::ObjectWriteOperation *op,
2922 const std::string &name)
2923 {
2924 bufferlist bl;
2925 encode(name, bl);
2926 op->exec("rbd", "namespace_remove", bl);
2927 }
2928
2929 int namespace_remove(librados::IoCtx *ioctx, const std::string &name)
2930 {
2931 librados::ObjectWriteOperation op;
2932 namespace_remove(&op, name);
2933
2934 return ioctx->operate(RBD_NAMESPACE, &op);
2935 }
2936
2937 void namespace_list_start(librados::ObjectReadOperation *op,
2938 const std::string &start, uint64_t max_return)
2939 {
2940 bufferlist bl;
2941 encode(start, bl);
2942 encode(max_return, bl);
2943 op->exec("rbd", "namespace_list", bl);
2944 }
2945
2946 int namespace_list_finish(bufferlist::const_iterator *it,
2947 std::list<std::string> *entries)
2948 {
2949 ceph_assert(entries);
2950
2951 try {
2952 decode(*entries, *it);
2953 } catch (const ceph::buffer::error &err) {
2954 return -EBADMSG;
2955 }
2956
2957 return 0;
2958 }
2959
2960 int namespace_list(librados::IoCtx *ioctx,
2961 const std::string &start, uint64_t max_return,
2962 std::list<std::string> *entries)
2963 {
2964 librados::ObjectReadOperation op;
2965 namespace_list_start(&op, start, max_return);
2966
2967 bufferlist out_bl;
2968 int r = ioctx->operate(RBD_NAMESPACE, &op, &out_bl);
2969 if (r < 0) {
2970 return r;
2971 }
2972
2973 auto iter = out_bl.cbegin();
2974 return namespace_list_finish(&iter, entries);
2975 }
2976
2977 void sparsify(librados::ObjectWriteOperation *op, size_t sparse_size,
2978 bool remove_empty)
2979 {
2980 bufferlist bl;
2981 encode(sparse_size, bl);
2982 encode(remove_empty, bl);
2983 op->exec("rbd", "sparsify", bl);
2984 }
2985
2986 int sparsify(librados::IoCtx *ioctx, const std::string &oid, size_t sparse_size,
2987 bool remove_empty)
2988 {
2989 librados::ObjectWriteOperation op;
2990 sparsify(&op, sparse_size, remove_empty);
2991
2992 return ioctx->operate(oid, &op);
2993 }
2994
2995 } // namespace cls_client
2996 } // namespace librbd