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