X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Fcls%2Frbd%2Fcls_rbd_client.cc;fp=src%2Fceph%2Fsrc%2Fcls%2Frbd%2Fcls_rbd_client.cc;h=0a3ee5555d570c9208ef35693056b770211060d6;hb=812ff6ca9fcd3e629e49d4328905f33eee8ca3f5;hp=0000000000000000000000000000000000000000;hpb=15280273faafb77777eab341909a3f495cf248d9;p=stor4nfv.git diff --git a/src/ceph/src/cls/rbd/cls_rbd_client.cc b/src/ceph/src/cls/rbd/cls_rbd_client.cc new file mode 100644 index 0000000..0a3ee55 --- /dev/null +++ b/src/ceph/src/cls/rbd/cls_rbd_client.cc @@ -0,0 +1,2127 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "cls/rbd/cls_rbd_client.h" +#include "cls/lock/cls_lock_client.h" +#include "include/buffer.h" +#include "include/encoding.h" +#include "include/rbd_types.h" +#include "include/rados/librados.hpp" + +#include + +namespace librbd { + namespace cls_client { + + void get_immutable_metadata_start(librados::ObjectReadOperation *op) { + bufferlist bl, empty_bl; + snapid_t snap = CEPH_NOSNAP; + ::encode(snap, bl); + op->exec("rbd", "get_size", bl); + op->exec("rbd", "get_object_prefix", empty_bl); + } + + int get_immutable_metadata_finish(bufferlist::iterator *it, + std::string *object_prefix, + uint8_t *order) { + try { + uint64_t size; + // get_size + ::decode(*order, *it); + ::decode(size, *it); + // get_object_prefix + ::decode(*object_prefix, *it); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + + } + + int get_immutable_metadata(librados::IoCtx *ioctx, const std::string &oid, + std::string *object_prefix, uint8_t *order) + { + librados::ObjectReadOperation op; + get_immutable_metadata_start(&op); + + bufferlist out_bl; + int r = ioctx->operate(oid, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator it = out_bl.begin(); + return get_immutable_metadata_finish(&it, object_prefix, order); + } + + void get_mutable_metadata_start(librados::ObjectReadOperation *op, + bool read_only) { + snapid_t snap = CEPH_NOSNAP; + bufferlist size_bl; + ::encode(snap, size_bl); + op->exec("rbd", "get_size", size_bl); + + bufferlist features_bl; + ::encode(snap, features_bl); + ::encode(read_only, features_bl); + op->exec("rbd", "get_features", features_bl); + + bufferlist empty_bl; + op->exec("rbd", "get_snapcontext", empty_bl); + + bufferlist parent_bl; + ::encode(snap, parent_bl); + op->exec("rbd", "get_parent", parent_bl); + + rados::cls::lock::get_lock_info_start(op, RBD_LOCK_NAME); + } + + int get_mutable_metadata_finish(bufferlist::iterator *it, + uint64_t *size, uint64_t *features, + uint64_t *incompatible_features, + std::map *lockers, + bool *exclusive_lock, std::string *lock_tag, + ::SnapContext *snapc, ParentInfo *parent) { + assert(size); + assert(features); + assert(incompatible_features); + assert(lockers); + assert(exclusive_lock); + assert(snapc); + assert(parent); + + try { + uint8_t order; + // get_size + ::decode(order, *it); + ::decode(*size, *it); + // get_features + ::decode(*features, *it); + ::decode(*incompatible_features, *it); + // get_snapcontext + ::decode(*snapc, *it); + // get_parent + ::decode(parent->spec.pool_id, *it); + ::decode(parent->spec.image_id, *it); + ::decode(parent->spec.snap_id, *it); + ::decode(parent->overlap, *it); + + // get_lock_info + ClsLockType lock_type = LOCK_NONE; + int r = rados::cls::lock::get_lock_info_finish(it, lockers, &lock_type, + lock_tag); + if (r == -EOPNOTSUPP) { + r = 0; + } + if (r == 0) { + *exclusive_lock = (lock_type == LOCK_EXCLUSIVE); + } + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int get_mutable_metadata(librados::IoCtx *ioctx, const std::string &oid, + bool read_only, uint64_t *size, uint64_t *features, + uint64_t *incompatible_features, + map *lockers, + bool *exclusive_lock, + string *lock_tag, + ::SnapContext *snapc, + ParentInfo *parent) + { + librados::ObjectReadOperation op; + get_mutable_metadata_start(&op, read_only); + + bufferlist out_bl; + int r = ioctx->operate(oid, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator it = out_bl.begin(); + return get_mutable_metadata_finish(&it, size, features, + incompatible_features, lockers, + exclusive_lock, lock_tag, snapc, + parent); + } + + void create_image(librados::ObjectWriteOperation *op, uint64_t size, + uint8_t order, uint64_t features, + const std::string &object_prefix, int64_t data_pool_id) + { + bufferlist bl; + ::encode(size, bl); + ::encode(order, bl); + ::encode(features, bl); + ::encode(object_prefix, bl); + ::encode(data_pool_id, bl); + + op->exec("rbd", "create", bl); + } + + int create_image(librados::IoCtx *ioctx, const std::string &oid, + uint64_t size, uint8_t order, uint64_t features, + const std::string &object_prefix, int64_t data_pool_id) + { + librados::ObjectWriteOperation op; + create_image(&op, size, order, features, object_prefix, data_pool_id); + + return ioctx->operate(oid, &op); + } + + int get_features(librados::IoCtx *ioctx, const std::string &oid, + snapid_t snap_id, uint64_t *features) + { + bufferlist inbl, outbl; + ::encode(snap_id, inbl); + + int r = ioctx->exec(oid, "rbd", "get_features", inbl, outbl); + if (r < 0) + return r; + + try { + bufferlist::iterator iter = outbl.begin(); + ::decode(*features, iter); + } catch (const buffer::error &err) { + return -EBADMSG; + } + + return 0; + } + + void set_features(librados::ObjectWriteOperation *op, uint64_t features, + uint64_t mask) + { + bufferlist bl; + ::encode(features, bl); + ::encode(mask, bl); + + op->exec("rbd", "set_features", bl); + } + + int set_features(librados::IoCtx *ioctx, const std::string &oid, + uint64_t features, uint64_t mask) + { + librados::ObjectWriteOperation op; + set_features(&op, features, mask); + + return ioctx->operate(oid, &op); + } + + int get_object_prefix(librados::IoCtx *ioctx, const std::string &oid, + std::string *object_prefix) + { + bufferlist inbl, outbl; + int r = ioctx->exec(oid, "rbd", "get_object_prefix", inbl, outbl); + if (r < 0) + return r; + + try { + bufferlist::iterator iter = outbl.begin(); + ::decode(*object_prefix, iter); + } catch (const buffer::error &err) { + return -EBADMSG; + } + + return 0; + } + + void get_data_pool_start(librados::ObjectReadOperation *op) { + bufferlist bl; + op->exec("rbd", "get_data_pool", bl); + } + + int get_data_pool_finish(bufferlist::iterator *it, int64_t *data_pool_id) { + try { + ::decode(*data_pool_id, *it); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int get_data_pool(librados::IoCtx *ioctx, const std::string &oid, + int64_t *data_pool_id) { + librados::ObjectReadOperation op; + get_data_pool_start(&op); + + bufferlist out_bl; + int r = ioctx->operate(oid, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator it = out_bl.begin(); + return get_data_pool_finish(&it, data_pool_id); + } + + int get_size(librados::IoCtx *ioctx, const std::string &oid, + snapid_t snap_id, uint64_t *size, uint8_t *order) + { + bufferlist inbl, outbl; + ::encode(snap_id, inbl); + + int r = ioctx->exec(oid, "rbd", "get_size", inbl, outbl); + if (r < 0) + return r; + + try { + bufferlist::iterator iter = outbl.begin(); + ::decode(*order, iter); + ::decode(*size, iter); + } catch (const buffer::error &err) { + return -EBADMSG; + } + + return 0; + } + + int set_size(librados::IoCtx *ioctx, const std::string &oid, + uint64_t size) + { + librados::ObjectWriteOperation op; + set_size(&op, size); + return ioctx->operate(oid, &op); + } + + void set_size(librados::ObjectWriteOperation *op, uint64_t size) + { + bufferlist bl; + ::encode(size, bl); + op->exec("rbd", "set_size", bl); + } + + int get_parent(librados::IoCtx *ioctx, const std::string &oid, + snapid_t snap_id, ParentSpec *pspec, + uint64_t *parent_overlap) + { + bufferlist inbl, outbl; + ::encode(snap_id, inbl); + + int r = ioctx->exec(oid, "rbd", "get_parent", inbl, outbl); + if (r < 0) + return r; + + try { + bufferlist::iterator iter = outbl.begin(); + ::decode(pspec->pool_id, iter); + ::decode(pspec->image_id, iter); + ::decode(pspec->snap_id, iter); + ::decode(*parent_overlap, iter); + } catch (const buffer::error &err) { + return -EBADMSG; + } + + return 0; + } + + int set_parent(librados::IoCtx *ioctx, const std::string &oid, + const ParentSpec &pspec, uint64_t parent_overlap) + { + librados::ObjectWriteOperation op; + set_parent(&op, pspec, parent_overlap); + return ioctx->operate(oid, &op); + } + + void set_parent(librados::ObjectWriteOperation *op, + const ParentSpec &pspec, uint64_t parent_overlap) { + bufferlist in_bl; + ::encode(pspec.pool_id, in_bl); + ::encode(pspec.image_id, in_bl); + ::encode(pspec.snap_id, in_bl); + ::encode(parent_overlap, in_bl); + + op->exec("rbd", "set_parent", in_bl); + } + + void get_flags_start(librados::ObjectReadOperation *op, + const std::vector &snap_ids) { + bufferlist in_bl; + ::encode(static_cast(CEPH_NOSNAP), in_bl); + + op->exec("rbd", "get_flags", in_bl); + for (size_t i = 0; i < snap_ids.size(); ++i) { + bufferlist snap_bl; + ::encode(snap_ids[i], snap_bl); + op->exec("rbd", "get_flags", snap_bl); + } + + } + + int get_flags_finish(bufferlist::iterator *it, uint64_t *flags, + const std::vector &snap_ids, + std::vector *snap_flags) { + snap_flags->resize(snap_ids.size()); + try { + ::decode(*flags, *it); + for (size_t i = 0; i < snap_flags->size(); ++i) { + ::decode((*snap_flags)[i], *it); + } + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int get_flags(librados::IoCtx *ioctx, const std::string &oid, + uint64_t *flags, const std::vector &snap_ids, + vector *snap_flags) + { + librados::ObjectReadOperation op; + get_flags_start(&op, snap_ids); + + bufferlist out_bl; + int r = ioctx->operate(oid, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator it = out_bl.begin(); + return get_flags_finish(&it, flags, snap_ids, snap_flags); + } + + void set_flags(librados::ObjectWriteOperation *op, snapid_t snap_id, + uint64_t flags, uint64_t mask) + { + bufferlist inbl; + ::encode(flags, inbl); + ::encode(mask, inbl); + ::encode(snap_id, inbl); + op->exec("rbd", "set_flags", inbl); + } + + int remove_parent(librados::IoCtx *ioctx, const std::string &oid) + { + librados::ObjectWriteOperation op; + remove_parent(&op); + return ioctx->operate(oid, &op); + } + + void remove_parent(librados::ObjectWriteOperation *op) + { + bufferlist inbl; + op->exec("rbd", "remove_parent", inbl); + } + + int add_child(librados::IoCtx *ioctx, const std::string &oid, + const ParentSpec &pspec, const std::string &c_imageid) + { + librados::ObjectWriteOperation op; + add_child(&op, pspec, c_imageid); + return ioctx->operate(oid, &op); + } + + void add_child(librados::ObjectWriteOperation *op, + const ParentSpec pspec, const std::string &c_imageid) + { + bufferlist in; + ::encode(pspec.pool_id, in); + ::encode(pspec.image_id, in); + ::encode(pspec.snap_id, in); + ::encode(c_imageid, in); + + op->exec("rbd", "add_child", in); + } + + void remove_child(librados::ObjectWriteOperation *op, + const ParentSpec &pspec, const std::string &c_imageid) + { + bufferlist in; + ::encode(pspec.pool_id, in); + ::encode(pspec.image_id, in); + ::encode(pspec.snap_id, in); + ::encode(c_imageid, in); + op->exec("rbd", "remove_child", in); + } + + int remove_child(librados::IoCtx *ioctx, const std::string &oid, + const ParentSpec &pspec, const std::string &c_imageid) + { + librados::ObjectWriteOperation op; + remove_child(&op, pspec, c_imageid); + return ioctx->operate(oid, &op); + } + + void get_children_start(librados::ObjectReadOperation *op, + const ParentSpec &pspec) { + bufferlist in_bl; + ::encode(pspec.pool_id, in_bl); + ::encode(pspec.image_id, in_bl); + ::encode(pspec.snap_id, in_bl); + op->exec("rbd", "get_children", in_bl); + } + + int get_children_finish(bufferlist::iterator *it, + std::set* children) { + try { + ::decode(*children, *it); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int get_children(librados::IoCtx *ioctx, const std::string &oid, + const ParentSpec &pspec, set& children) + { + librados::ObjectReadOperation op; + get_children_start(&op, pspec); + + bufferlist out_bl; + int r = ioctx->operate(oid, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator it = out_bl.begin(); + return get_children_finish(&it, &children); + } + + void snapshot_add(librados::ObjectWriteOperation *op, snapid_t snap_id, + const std::string &snap_name, const cls::rbd::SnapshotNamespace &snap_namespace) + { + bufferlist bl; + ::encode(snap_name, bl); + ::encode(snap_id, bl); + ::encode(cls::rbd::SnapshotNamespaceOnDisk(snap_namespace), bl); + op->exec("rbd", "snapshot_add", bl); + } + + void snapshot_remove(librados::ObjectWriteOperation *op, snapid_t snap_id) + { + bufferlist bl; + ::encode(snap_id, bl); + op->exec("rbd", "snapshot_remove", bl); + } + + void snapshot_rename(librados::ObjectWriteOperation *op, + snapid_t src_snap_id, + const std::string &dst_name) + { + bufferlist bl; + ::encode(src_snap_id, bl); + ::encode(dst_name, bl); + op->exec("rbd", "snapshot_rename", bl); + } + + int get_snapcontext(librados::IoCtx *ioctx, const std::string &oid, + ::SnapContext *snapc) + { + bufferlist inbl, outbl; + + int r = ioctx->exec(oid, "rbd", "get_snapcontext", inbl, outbl); + if (r < 0) + return r; + + try { + bufferlist::iterator iter = outbl.begin(); + ::decode(*snapc, iter); + } catch (const buffer::error &err) { + return -EBADMSG; + } + + if (!snapc->is_valid()) + return -EBADMSG; + + return 0; + } + + void snapshot_list_start(librados::ObjectReadOperation *op, + const std::vector &ids) { + for (auto snap_id : ids) { + bufferlist bl1, bl2, bl3, bl4; + ::encode(snap_id, bl1); + op->exec("rbd", "get_snapshot_name", bl1); + ::encode(snap_id, bl2); + op->exec("rbd", "get_size", bl2); + ::encode(snap_id, bl3); + op->exec("rbd", "get_parent", bl3); + ::encode(snap_id, bl4); + op->exec("rbd", "get_protection_status", bl4); + } + } + + int snapshot_list_finish(bufferlist::iterator *it, + const std::vector &ids, + std::vector *names, + std::vector *sizes, + std::vector *parents, + std::vector *protection_statuses) + { + names->resize(ids.size()); + sizes->resize(ids.size()); + parents->resize(ids.size()); + protection_statuses->resize(ids.size()); + try { + for (size_t i = 0; i < names->size(); ++i) { + uint8_t order; + // get_snapshot_name + ::decode((*names)[i], *it); + // get_size + ::decode(order, *it); + ::decode((*sizes)[i], *it); + // get_parent + ::decode((*parents)[i].spec.pool_id, *it); + ::decode((*parents)[i].spec.image_id, *it); + ::decode((*parents)[i].spec.snap_id, *it); + ::decode((*parents)[i].overlap, *it); + // get_protection_status + ::decode((*protection_statuses)[i], *it); + } + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int snapshot_list(librados::IoCtx *ioctx, const std::string &oid, + const std::vector &ids, + std::vector *names, + std::vector *sizes, + std::vector *parents, + std::vector *protection_statuses) + { + librados::ObjectReadOperation op; + snapshot_list_start(&op, ids); + + bufferlist out_bl; + int r = ioctx->operate(oid, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator it = out_bl.begin(); + return snapshot_list_finish(&it, ids, names, sizes, parents, + protection_statuses); + } + + void snapshot_timestamp_list_start(librados::ObjectReadOperation *op, + const std::vector &ids) + { + for (auto snap_id : ids) { + bufferlist bl; + ::encode(snap_id, bl); + op->exec("rbd", "get_snapshot_timestamp", bl); + } + } + + int snapshot_timestamp_list_finish(bufferlist::iterator *it, + const std::vector &ids, + std::vector *timestamps) + { + timestamps->resize(ids.size()); + try { + for (size_t i = 0; i < timestamps->size(); ++i) { + utime_t t; + ::decode(t, *it); + (*timestamps)[i] = t; + } + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int snapshot_timestamp_list(librados::IoCtx *ioctx, const std::string &oid, + const std::vector &ids, + std::vector *timestamps) + { + librados::ObjectReadOperation op; + snapshot_timestamp_list_start(&op, ids); + + bufferlist out_bl; + int r = ioctx->operate(oid, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator it = out_bl.begin(); + return snapshot_timestamp_list_finish(&it, ids, timestamps); + } + + void snapshot_namespace_list_start(librados::ObjectReadOperation *op, + const std::vector &ids) + { + for (auto snap_id : ids) { + bufferlist bl; + ::encode(snap_id, bl); + op->exec("rbd", "get_snapshot_namespace", bl); + } + } + + int snapshot_namespace_list_finish(bufferlist::iterator *it, + const std::vector &ids, + std::vector *namespaces) + { + namespaces->resize(ids.size()); + try { + for (size_t i = 0; i < namespaces->size(); ++i) { + cls::rbd::SnapshotNamespaceOnDisk e; + ::decode(e, *it); + (*namespaces)[i] = e.snapshot_namespace; + } + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int snapshot_namespace_list(librados::IoCtx *ioctx, const std::string &oid, + const std::vector &ids, + std::vector *namespaces) + { + librados::ObjectReadOperation op; + snapshot_namespace_list_start(&op, ids); + + bufferlist out_bl; + int r = ioctx->operate(oid, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator it = out_bl.begin(); + return snapshot_namespace_list_finish(&it, ids, namespaces); + } + + void old_snapshot_add(librados::ObjectWriteOperation *op, + snapid_t snap_id, const std::string &snap_name) + { + bufferlist bl; + ::encode(snap_name, bl); + ::encode(snap_id, bl); + op->exec("rbd", "snap_add", bl); + } + + void old_snapshot_remove(librados::ObjectWriteOperation *op, + const std::string &snap_name) + { + bufferlist bl; + ::encode(snap_name, bl); + op->exec("rbd", "snap_remove", bl); + } + + void old_snapshot_rename(librados::ObjectWriteOperation *op, + snapid_t src_snap_id, const std::string &dst_name) + { + bufferlist bl; + ::encode(src_snap_id, bl); + ::encode(dst_name, bl); + op->exec("rbd", "snap_rename", bl); + } + + void old_snapshot_list_start(librados::ObjectReadOperation *op) { + bufferlist in_bl; + op->exec("rbd", "snap_list", in_bl); + } + + int old_snapshot_list_finish(bufferlist::iterator *it, + std::vector *names, + std::vector *sizes, + ::SnapContext *snapc) { + try { + uint32_t num_snaps; + ::decode(snapc->seq, *it); + ::decode(num_snaps, *it); + + names->resize(num_snaps); + sizes->resize(num_snaps); + snapc->snaps.resize(num_snaps); + for (uint32_t i = 0; i < num_snaps; ++i) { + ::decode(snapc->snaps[i], *it); + ::decode((*sizes)[i], *it); + ::decode((*names)[i], *it); + } + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int old_snapshot_list(librados::IoCtx *ioctx, const std::string &oid, + std::vector *names, + std::vector *sizes, + ::SnapContext *snapc) + { + librados::ObjectReadOperation op; + old_snapshot_list_start(&op); + + bufferlist out_bl; + int r = ioctx->operate(oid, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator it = out_bl.begin(); + return old_snapshot_list_finish(&it, names, sizes, snapc); + } + + void get_all_features_start(librados::ObjectReadOperation *op) { + bufferlist in; + op->exec("rbd", "get_all_features", in); + } + + int get_all_features_finish(bufferlist::iterator *it, + uint64_t *all_features) { + try { + ::decode(*all_features, *it); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int get_all_features(librados::IoCtx *ioctx, const std::string &oid, + uint64_t *all_features) { + librados::ObjectReadOperation op; + get_all_features_start(&op); + + bufferlist out_bl; + int r = ioctx->operate(oid, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator it = out_bl.begin(); + return get_all_features_finish(&it, all_features); + } + + int copyup(librados::IoCtx *ioctx, const std::string &oid, + bufferlist data) { + bufferlist out; + return ioctx->exec(oid, "rbd", "copyup", data, out); + } + + int get_protection_status(librados::IoCtx *ioctx, const std::string &oid, + snapid_t snap_id, uint8_t *protection_status) + { + bufferlist in, out; + ::encode(snap_id.val, in); + + int r = ioctx->exec(oid, "rbd", "get_protection_status", in, out); + if (r < 0) + return r; + + try { + bufferlist::iterator iter = out.begin(); + ::decode(*protection_status, iter); + } catch (const buffer::error &err) { + return -EBADMSG; + } + + return 0; + } + + int set_protection_status(librados::IoCtx *ioctx, const std::string &oid, + snapid_t snap_id, uint8_t protection_status) + { + // TODO remove + librados::ObjectWriteOperation op; + set_protection_status(&op, snap_id, protection_status); + return ioctx->operate(oid, &op); + } + + void set_protection_status(librados::ObjectWriteOperation *op, + snapid_t snap_id, uint8_t protection_status) + { + bufferlist in; + ::encode(snap_id, in); + ::encode(protection_status, in); + op->exec("rbd", "set_protection_status", in); + } + + int snapshot_get_limit(librados::IoCtx *ioctx, const std::string &oid, + uint64_t *limit) + { + bufferlist in, out; + int r = ioctx->exec(oid, "rbd", "snapshot_get_limit", in, out); + + if (r < 0) { + return r; + } + + try { + bufferlist::iterator iter = out.begin(); + ::decode(*limit, iter); + } catch (const buffer::error &err) { + return -EBADMSG; + } + + return 0; + } + + void snapshot_set_limit(librados::ObjectWriteOperation *op, uint64_t limit) + { + bufferlist in; + ::encode(limit, in); + op->exec("rbd", "snapshot_set_limit", in); + } + + void get_stripe_unit_count_start(librados::ObjectReadOperation *op) { + bufferlist empty_bl; + op->exec("rbd", "get_stripe_unit_count", empty_bl); + } + + int get_stripe_unit_count_finish(bufferlist::iterator *it, + uint64_t *stripe_unit, + uint64_t *stripe_count) { + assert(stripe_unit); + assert(stripe_count); + + try { + ::decode(*stripe_unit, *it); + ::decode(*stripe_count, *it); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int get_stripe_unit_count(librados::IoCtx *ioctx, const std::string &oid, + uint64_t *stripe_unit, uint64_t *stripe_count) + { + librados::ObjectReadOperation op; + get_stripe_unit_count_start(&op); + + bufferlist out_bl; + int r = ioctx->operate(oid, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator it = out_bl.begin(); + return get_stripe_unit_count_finish(&it, stripe_unit, stripe_count); + } + + void set_stripe_unit_count(librados::ObjectWriteOperation *op, + uint64_t stripe_unit, uint64_t stripe_count) + { + bufferlist bl; + ::encode(stripe_unit, bl); + ::encode(stripe_count, bl); + + op->exec("rbd", "set_stripe_unit_count", bl); + } + + int set_stripe_unit_count(librados::IoCtx *ioctx, const std::string &oid, + uint64_t stripe_unit, uint64_t stripe_count) + { + librados::ObjectWriteOperation op; + set_stripe_unit_count(&op, stripe_unit, stripe_count); + + return ioctx->operate(oid, &op); + } + + void get_create_timestamp_start(librados::ObjectReadOperation *op) { + bufferlist empty_bl; + op->exec("rbd", "get_create_timestamp", empty_bl); + } + + int get_create_timestamp_finish(bufferlist::iterator *it, + utime_t *timestamp) { + assert(timestamp); + + try { + ::decode(*timestamp, *it); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int get_create_timestamp(librados::IoCtx *ioctx, const std::string &oid, + utime_t *timestamp) + { + librados::ObjectReadOperation op; + get_create_timestamp_start(&op); + + bufferlist out_bl; + int r = ioctx->operate(oid, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator it = out_bl.begin(); + return get_create_timestamp_finish(&it, timestamp); + } + + /************************ rbd_id object methods ************************/ + + void get_id_start(librados::ObjectReadOperation *op) { + bufferlist empty_bl; + op->exec("rbd", "get_id", empty_bl); + } + + int get_id_finish(bufferlist::iterator *it, std::string *id) { + try { + ::decode(*id, *it); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int get_id(librados::IoCtx *ioctx, const std::string &oid, std::string *id) + { + librados::ObjectReadOperation op; + get_id_start(&op); + + bufferlist out_bl; + int r = ioctx->operate(oid, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator it = out_bl.begin(); + return get_id_finish(&it, id); + } + + void set_id(librados::ObjectWriteOperation *op, const std::string id) + { + bufferlist bl; + ::encode(id, bl); + op->exec("rbd", "set_id", bl); + } + + int set_id(librados::IoCtx *ioctx, const std::string &oid, std::string id) + { + librados::ObjectWriteOperation op; + set_id(&op, id); + + return ioctx->operate(oid, &op); + } + + /******************** rbd_directory object methods ********************/ + + void dir_get_id_start(librados::ObjectReadOperation *op, + const std::string &image_name) { + bufferlist bl; + ::encode(image_name, bl); + + op->exec("rbd", "dir_get_id", bl); + } + + int dir_get_id_finish(bufferlist::iterator *iter, std::string *image_id) { + try { + ::decode(*image_id, *iter); + } catch (const buffer::error &err) { + return -EBADMSG; + } + + return 0; + } + + int dir_get_id(librados::IoCtx *ioctx, const std::string &oid, + const std::string &name, std::string *id) { + librados::ObjectReadOperation op; + dir_get_id_start(&op, name); + + bufferlist out_bl; + int r = ioctx->operate(oid, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator iter = out_bl.begin(); + return dir_get_id_finish(&iter, id); + } + + void dir_get_name_start(librados::ObjectReadOperation *op, + const std::string &id) { + bufferlist in_bl; + ::encode(id, in_bl); + op->exec("rbd", "dir_get_name", in_bl); + } + + int dir_get_name_finish(bufferlist::iterator *it, std::string *name) { + try { + ::decode(*name, *it); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int dir_get_name(librados::IoCtx *ioctx, const std::string &oid, + const std::string &id, std::string *name) { + librados::ObjectReadOperation op; + dir_get_name_start(&op, id); + + bufferlist out_bl; + int r = ioctx->operate(oid, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator it = out_bl.begin(); + return dir_get_name_finish(&it, name); + } + + void dir_list_start(librados::ObjectReadOperation *op, + const std::string &start, uint64_t max_return) + { + bufferlist in_bl; + ::encode(start, in_bl); + ::encode(max_return, in_bl); + + op->exec("rbd", "dir_list", in_bl); + } + + int dir_list_finish(bufferlist::iterator *it, map *images) + { + try { + ::decode(*images, *it); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int dir_list(librados::IoCtx *ioctx, const std::string &oid, + const std::string &start, uint64_t max_return, + map *images) + { + librados::ObjectReadOperation op; + dir_list_start(&op, start, max_return); + + bufferlist out_bl; + int r = ioctx->operate(oid, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator iter = out_bl.begin(); + return dir_list_finish(&iter, images); + } + + void dir_add_image(librados::ObjectWriteOperation *op, + const std::string &name, const std::string &id) + { + bufferlist bl; + ::encode(name, bl); + ::encode(id, bl); + op->exec("rbd", "dir_add_image", bl); + } + + int dir_add_image(librados::IoCtx *ioctx, const std::string &oid, + const std::string &name, const std::string &id) + { + librados::ObjectWriteOperation op; + dir_add_image(&op, name, id); + + return ioctx->operate(oid, &op); + } + + int dir_remove_image(librados::IoCtx *ioctx, const std::string &oid, + const std::string &name, const std::string &id) + { + librados::ObjectWriteOperation op; + dir_remove_image(&op, name, id); + + return ioctx->operate(oid, &op); + } + + void dir_remove_image(librados::ObjectWriteOperation *op, + const std::string &name, const std::string &id) + { + bufferlist bl; + ::encode(name, bl); + ::encode(id, bl); + + op->exec("rbd", "dir_remove_image", bl); + } + + void dir_rename_image(librados::ObjectWriteOperation *op, + const std::string &src, const std::string &dest, + const std::string &id) + { + bufferlist in; + ::encode(src, in); + ::encode(dest, in); + ::encode(id, in); + op->exec("rbd", "dir_rename_image", in); + } + + void object_map_load_start(librados::ObjectReadOperation *op) { + bufferlist in_bl; + op->exec("rbd", "object_map_load", in_bl); + } + + int object_map_load_finish(bufferlist::iterator *it, + ceph::BitVector<2> *object_map) { + try { + ::decode(*object_map, *it); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int object_map_load(librados::IoCtx *ioctx, const std::string &oid, + ceph::BitVector<2> *object_map) + { + librados::ObjectReadOperation op; + object_map_load_start(&op); + + bufferlist out_bl; + int r = ioctx->operate(oid, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator it = out_bl.begin(); + return object_map_load_finish(&it, object_map); + } + + void object_map_save(librados::ObjectWriteOperation *rados_op, + const ceph::BitVector<2> &object_map) + { + ceph::BitVector<2> object_map_copy(object_map); + object_map_copy.set_crc_enabled(false); + + bufferlist in; + ::encode(object_map_copy, in); + rados_op->exec("rbd", "object_map_save", in); + } + + void object_map_resize(librados::ObjectWriteOperation *rados_op, + uint64_t object_count, uint8_t default_state) + { + bufferlist in; + ::encode(object_count, in); + ::encode(default_state, in); + rados_op->exec("rbd", "object_map_resize", in); + } + + void object_map_update(librados::ObjectWriteOperation *rados_op, + uint64_t start_object_no, uint64_t end_object_no, + uint8_t new_object_state, + const boost::optional ¤t_object_state) + { + bufferlist in; + ::encode(start_object_no, in); + ::encode(end_object_no, in); + ::encode(new_object_state, in); + ::encode(current_object_state, in); + rados_op->exec("rbd", "object_map_update", in); + } + + void object_map_snap_add(librados::ObjectWriteOperation *rados_op) + { + bufferlist in; + rados_op->exec("rbd", "object_map_snap_add", in); + } + + void object_map_snap_remove(librados::ObjectWriteOperation *rados_op, + const ceph::BitVector<2> &object_map) + { + ceph::BitVector<2> object_map_copy(object_map); + object_map_copy.set_crc_enabled(false); + + bufferlist in; + ::encode(object_map_copy, in); + rados_op->exec("rbd", "object_map_snap_remove", in); + } + + void metadata_set(librados::ObjectWriteOperation *op, + const map &data) + { + bufferlist bl; + ::encode(data, bl); + + op->exec("rbd", "metadata_set", bl); + } + + int metadata_set(librados::IoCtx *ioctx, const std::string &oid, + const map &data) + { + librados::ObjectWriteOperation op; + metadata_set(&op, data); + + return ioctx->operate(oid, &op); + } + + void metadata_remove(librados::ObjectWriteOperation *op, + const std::string &key) + { + bufferlist bl; + ::encode(key, bl); + + op->exec("rbd", "metadata_remove", bl); + } + + int metadata_remove(librados::IoCtx *ioctx, const std::string &oid, + const std::string &key) + { + librados::ObjectWriteOperation op; + metadata_remove(&op, key); + + return ioctx->operate(oid, &op); + } + + int metadata_list(librados::IoCtx *ioctx, const std::string &oid, + const std::string &start, uint64_t max_return, + map *pairs) + { + librados::ObjectReadOperation op; + metadata_list_start(&op, start, max_return); + + bufferlist out_bl; + int r = ioctx->operate(oid, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator it = out_bl.begin(); + return metadata_list_finish(&it, pairs); + } + + void metadata_list_start(librados::ObjectReadOperation *op, + const std::string &start, uint64_t max_return) + { + bufferlist in_bl; + ::encode(start, in_bl); + ::encode(max_return, in_bl); + op->exec("rbd", "metadata_list", in_bl); + } + + int metadata_list_finish(bufferlist::iterator *it, + std::map *pairs) + { + assert(pairs); + try { + ::decode(*pairs, *it); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int metadata_get(librados::IoCtx *ioctx, const std::string &oid, + const std::string &key, string *s) + { + assert(s); + bufferlist in, out; + ::encode(key, in); + int r = ioctx->exec(oid, "rbd", "metadata_get", in, out); + if (r < 0) + return r; + + bufferlist::iterator iter = out.begin(); + try { + ::decode(*s, iter); + } catch (const buffer::error &err) { + return -EBADMSG; + } + + return 0; + } + + void mirror_uuid_get_start(librados::ObjectReadOperation *op) { + bufferlist bl; + op->exec("rbd", "mirror_uuid_get", bl); + } + + int mirror_uuid_get_finish(bufferlist::iterator *it, + std::string *uuid) { + try { + ::decode(*uuid, *it); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int mirror_uuid_get(librados::IoCtx *ioctx, std::string *uuid) { + librados::ObjectReadOperation op; + mirror_uuid_get_start(&op); + + bufferlist out_bl; + int r = ioctx->operate(RBD_MIRRORING, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator it = out_bl.begin(); + r = mirror_uuid_get_finish(&it, uuid); + if (r < 0) { + return r; + } + return 0; + } + + int mirror_uuid_set(librados::IoCtx *ioctx, const std::string &uuid) { + bufferlist in_bl; + ::encode(uuid, in_bl); + + bufferlist out_bl; + int r = ioctx->exec(RBD_MIRRORING, "rbd", "mirror_uuid_set", in_bl, + out_bl); + if (r < 0) { + return r; + } + return 0; + } + + void mirror_mode_get_start(librados::ObjectReadOperation *op) { + bufferlist bl; + op->exec("rbd", "mirror_mode_get", bl); + } + + int mirror_mode_get_finish(bufferlist::iterator *it, + cls::rbd::MirrorMode *mirror_mode) { + try { + uint32_t mirror_mode_decode; + ::decode(mirror_mode_decode, *it); + *mirror_mode = static_cast(mirror_mode_decode); + } catch (const buffer::error &err) { + return -EBADMSG; + } + + return 0; + } + + int mirror_mode_get(librados::IoCtx *ioctx, + cls::rbd::MirrorMode *mirror_mode) { + librados::ObjectReadOperation op; + mirror_mode_get_start(&op); + + bufferlist out_bl; + int r = ioctx->operate(RBD_MIRRORING, &op, &out_bl); + if (r == -ENOENT) { + *mirror_mode = cls::rbd::MIRROR_MODE_DISABLED; + return 0; + } else if (r < 0) { + return r; + } + + bufferlist::iterator it = out_bl.begin(); + r = mirror_mode_get_finish(&it, mirror_mode); + if (r < 0) { + return r; + } + return 0; + } + + int mirror_mode_set(librados::IoCtx *ioctx, + cls::rbd::MirrorMode mirror_mode) { + bufferlist in_bl; + ::encode(static_cast(mirror_mode), in_bl); + + bufferlist out_bl; + int r = ioctx->exec(RBD_MIRRORING, "rbd", "mirror_mode_set", in_bl, + out_bl); + if (r < 0) { + return r; + } + return 0; + } + + int mirror_peer_list(librados::IoCtx *ioctx, + std::vector *peers) { + bufferlist in_bl; + bufferlist out_bl; + int r = ioctx->exec(RBD_MIRRORING, "rbd", "mirror_peer_list", in_bl, + out_bl); + if (r < 0) { + return r; + } + + peers->clear(); + try { + bufferlist::iterator bl_it = out_bl.begin(); + ::decode(*peers, bl_it); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int mirror_peer_add(librados::IoCtx *ioctx, const std::string &uuid, + const std::string &cluster_name, + const std::string &client_name, int64_t pool_id) { + cls::rbd::MirrorPeer peer(uuid, cluster_name, client_name, pool_id); + bufferlist in_bl; + ::encode(peer, in_bl); + + bufferlist out_bl; + int r = ioctx->exec(RBD_MIRRORING, "rbd", "mirror_peer_add", in_bl, + out_bl); + if (r < 0) { + return r; + } + return 0; + } + + int mirror_peer_remove(librados::IoCtx *ioctx, + const std::string &uuid) { + bufferlist in_bl; + ::encode(uuid, in_bl); + + bufferlist out_bl; + int r = ioctx->exec(RBD_MIRRORING, "rbd", "mirror_peer_remove", in_bl, + out_bl); + if (r < 0) { + return r; + } + return 0; + } + + int mirror_peer_set_client(librados::IoCtx *ioctx, + const std::string &uuid, + const std::string &client_name) { + bufferlist in_bl; + ::encode(uuid, in_bl); + ::encode(client_name, in_bl); + + bufferlist out_bl; + int r = ioctx->exec(RBD_MIRRORING, "rbd", "mirror_peer_set_client", + in_bl, out_bl); + if (r < 0) { + return r; + } + return 0; + } + + int mirror_peer_set_cluster(librados::IoCtx *ioctx, + const std::string &uuid, + const std::string &cluster_name) { + bufferlist in_bl; + ::encode(uuid, in_bl); + ::encode(cluster_name, in_bl); + + bufferlist out_bl; + int r = ioctx->exec(RBD_MIRRORING, "rbd", "mirror_peer_set_cluster", + in_bl, out_bl); + if (r < 0) { + return r; + } + return 0; + } + + void mirror_image_list_start(librados::ObjectReadOperation *op, + const std::string &start, uint64_t max_return) + { + bufferlist in_bl; + ::encode(start, in_bl); + ::encode(max_return, in_bl); + op->exec("rbd", "mirror_image_list", in_bl); + } + + int mirror_image_list_finish(bufferlist::iterator *it, + std::map *mirror_image_ids) + { + try { + ::decode(*mirror_image_ids, *it); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int mirror_image_list(librados::IoCtx *ioctx, + const std::string &start, uint64_t max_return, + std::map *mirror_image_ids) { + librados::ObjectReadOperation op; + mirror_image_list_start(&op, start, max_return); + + bufferlist out_bl; + int r = ioctx->operate(RBD_MIRRORING, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator bl_it = out_bl.begin(); + return mirror_image_list_finish(&bl_it, mirror_image_ids); + } + + void mirror_image_get_image_id_start(librados::ObjectReadOperation *op, + const std::string &global_image_id) { + bufferlist in_bl; + ::encode(global_image_id, in_bl); + op->exec( "rbd", "mirror_image_get_image_id", in_bl); + } + + int mirror_image_get_image_id_finish(bufferlist::iterator *it, + std::string *image_id) { + try { + ::decode(*image_id, *it); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int mirror_image_get_image_id(librados::IoCtx *ioctx, + const std::string &global_image_id, + std::string *image_id) { + librados::ObjectReadOperation op; + mirror_image_get_image_id_start(&op, global_image_id); + + bufferlist out_bl; + int r = ioctx->operate(RBD_MIRRORING, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator it = out_bl.begin(); + return mirror_image_get_image_id_finish(&it, image_id); + } + + int mirror_image_get(librados::IoCtx *ioctx, const std::string &image_id, + cls::rbd::MirrorImage *mirror_image) { + librados::ObjectReadOperation op; + mirror_image_get_start(&op, image_id); + + bufferlist out_bl; + int r = ioctx->operate(RBD_MIRRORING, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator iter = out_bl.begin(); + r = mirror_image_get_finish(&iter, mirror_image); + if (r < 0) { + return r; + } + return 0; + } + + void mirror_image_get_start(librados::ObjectReadOperation *op, + const std::string &image_id) { + bufferlist in_bl; + ::encode(image_id, in_bl); + + op->exec("rbd", "mirror_image_get", in_bl); + } + + int mirror_image_get_finish(bufferlist::iterator *iter, + cls::rbd::MirrorImage *mirror_image) { + try { + ::decode(*mirror_image, *iter); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + void mirror_image_set(librados::ObjectWriteOperation *op, + const std::string &image_id, + const cls::rbd::MirrorImage &mirror_image) { + bufferlist bl; + ::encode(image_id, bl); + ::encode(mirror_image, bl); + + op->exec("rbd", "mirror_image_set", bl); + } + + int mirror_image_set(librados::IoCtx *ioctx, const std::string &image_id, + const cls::rbd::MirrorImage &mirror_image) { + librados::ObjectWriteOperation op; + mirror_image_set(&op, image_id, mirror_image); + + int r = ioctx->operate(RBD_MIRRORING, &op); + if (r < 0) { + return r; + } + return 0; + } + + void mirror_image_remove(librados::ObjectWriteOperation *op, + const std::string &image_id) { + bufferlist bl; + ::encode(image_id, bl); + + op->exec("rbd", "mirror_image_remove", bl); + } + + int mirror_image_remove(librados::IoCtx *ioctx, const std::string &image_id) { + librados::ObjectWriteOperation op; + mirror_image_remove(&op, image_id); + + int r = ioctx->operate(RBD_MIRRORING, &op); + if (r < 0) { + return r; + } + return 0; + } + + int mirror_image_status_set(librados::IoCtx *ioctx, + const std::string &global_image_id, + const cls::rbd::MirrorImageStatus &status) { + librados::ObjectWriteOperation op; + mirror_image_status_set(&op, global_image_id, status); + return ioctx->operate(RBD_MIRRORING, &op); + } + + void mirror_image_status_set(librados::ObjectWriteOperation *op, + const std::string &global_image_id, + const cls::rbd::MirrorImageStatus &status) { + bufferlist bl; + ::encode(global_image_id, bl); + ::encode(status, bl); + op->exec("rbd", "mirror_image_status_set", bl); + } + + int mirror_image_status_remove(librados::IoCtx *ioctx, + const std::string &global_image_id) { + librados::ObjectWriteOperation op; + mirror_image_status_remove(&op, global_image_id); + return ioctx->operate(RBD_MIRRORING, &op); + } + + void mirror_image_status_remove(librados::ObjectWriteOperation *op, + const std::string &global_image_id) { + bufferlist bl; + ::encode(global_image_id, bl); + op->exec("rbd", "mirror_image_status_remove", bl); + } + + int mirror_image_status_get(librados::IoCtx *ioctx, + const std::string &global_image_id, + cls::rbd::MirrorImageStatus *status) { + librados::ObjectReadOperation op; + mirror_image_status_get_start(&op, global_image_id); + + bufferlist out_bl; + int r = ioctx->operate(RBD_MIRRORING, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator iter = out_bl.begin(); + r = mirror_image_status_get_finish(&iter, status); + if (r < 0) { + return r; + } + return 0; + } + + void mirror_image_status_get_start(librados::ObjectReadOperation *op, + const std::string &global_image_id) { + bufferlist bl; + ::encode(global_image_id, bl); + op->exec("rbd", "mirror_image_status_get", bl); + } + + int mirror_image_status_get_finish(bufferlist::iterator *iter, + cls::rbd::MirrorImageStatus *status) { + try { + ::decode(*status, *iter); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int mirror_image_status_list(librados::IoCtx *ioctx, + const std::string &start, uint64_t max_return, + std::map *images, + std::map *statuses) { + librados::ObjectReadOperation op; + mirror_image_status_list_start(&op, start, max_return); + + bufferlist out_bl; + int r = ioctx->operate(RBD_MIRRORING, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator iter = out_bl.begin(); + r = mirror_image_status_list_finish(&iter, images, statuses); + if (r < 0) { + return r; + } + return 0; + } + + void mirror_image_status_list_start(librados::ObjectReadOperation *op, + const std::string &start, + uint64_t max_return) { + bufferlist bl; + ::encode(start, bl); + ::encode(max_return, bl); + op->exec("rbd", "mirror_image_status_list", bl); + } + + int mirror_image_status_list_finish(bufferlist::iterator *iter, + std::map *images, + std::map *statuses) { + images->clear(); + statuses->clear(); + try { + ::decode(*images, *iter); + ::decode(*statuses, *iter); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int mirror_image_status_get_summary(librados::IoCtx *ioctx, + std::map *states) { + librados::ObjectReadOperation op; + mirror_image_status_get_summary_start(&op); + + bufferlist out_bl; + int r = ioctx->operate(RBD_MIRRORING, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator iter = out_bl.begin(); + r = mirror_image_status_get_summary_finish(&iter, states); + if (r < 0) { + return r; + } + return 0; + } + + void mirror_image_status_get_summary_start( + librados::ObjectReadOperation *op) { + bufferlist bl; + op->exec("rbd", "mirror_image_status_get_summary", bl); + } + + int mirror_image_status_get_summary_finish(bufferlist::iterator *iter, + std::map *states) { + try { + ::decode(*states, *iter); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int mirror_image_status_remove_down(librados::IoCtx *ioctx) { + librados::ObjectWriteOperation op; + mirror_image_status_remove_down(&op); + return ioctx->operate(RBD_MIRRORING, &op); + } + + void mirror_image_status_remove_down(librados::ObjectWriteOperation *op) { + bufferlist bl; + op->exec("rbd", "mirror_image_status_remove_down", bl); + } + + void mirror_instances_list_start(librados::ObjectReadOperation *op) { + bufferlist bl; + op->exec("rbd", "mirror_instances_list", bl); + } + + int mirror_instances_list_finish(bufferlist::iterator *iter, + std::vector *instance_ids) { + instance_ids->clear(); + try { + ::decode(*instance_ids, *iter); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int mirror_instances_list(librados::IoCtx *ioctx, + std::vector *instance_ids) { + librados::ObjectReadOperation op; + mirror_instances_list_start(&op); + + bufferlist out_bl; + int r = ioctx->operate(RBD_MIRROR_LEADER, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator iter = out_bl.begin(); + r = mirror_instances_list_finish(&iter, instance_ids); + if (r < 0) { + return r; + } + return 0; + } + + void mirror_instances_add(librados::ObjectWriteOperation *op, + const std::string &instance_id) { + bufferlist bl; + ::encode(instance_id, bl); + op->exec("rbd", "mirror_instances_add", bl); + } + + int mirror_instances_add(librados::IoCtx *ioctx, + const std::string &instance_id) { + librados::ObjectWriteOperation op; + mirror_instances_add(&op, instance_id); + return ioctx->operate(RBD_MIRROR_LEADER, &op); + } + + void mirror_instances_remove(librados::ObjectWriteOperation *op, + const std::string &instance_id) { + bufferlist bl; + ::encode(instance_id, bl); + op->exec("rbd", "mirror_instances_remove", bl); + } + + int mirror_instances_remove(librados::IoCtx *ioctx, + const std::string &instance_id) { + librados::ObjectWriteOperation op; + mirror_instances_remove(&op, instance_id); + return ioctx->operate(RBD_MIRROR_LEADER, &op); + } + + // Consistency groups functions + int group_create(librados::IoCtx *ioctx, const std::string &oid) + { + bufferlist bl, bl2; + + return ioctx->exec(oid, "rbd", "group_create", bl, bl2); + } + + int group_dir_list(librados::IoCtx *ioctx, const std::string &oid, + const std::string &start, uint64_t max_return, + map *cgs) + { + bufferlist in, out; + ::encode(start, in); + ::encode(max_return, in); + int r = ioctx->exec(oid, "rbd", "group_dir_list", in, out); + if (r < 0) + return r; + + bufferlist::iterator iter = out.begin(); + try { + ::decode(*cgs, iter); + } catch (const buffer::error &err) { + return -EBADMSG; + } + + return 0; + } + + int group_dir_add(librados::IoCtx *ioctx, const std::string &oid, + const std::string &name, const std::string &id) + { + bufferlist in, out; + ::encode(name, in); + ::encode(id, in); + return ioctx->exec(oid, "rbd", "group_dir_add", in, out); + } + + int group_dir_remove(librados::IoCtx *ioctx, const std::string &oid, + const std::string &name, const std::string &id) + { + bufferlist in, out; + ::encode(name, in); + ::encode(id, in); + return ioctx->exec(oid, "rbd", "group_dir_remove", in, out); + } + + int group_image_remove(librados::IoCtx *ioctx, const std::string &oid, + const cls::rbd::GroupImageSpec &spec) + { + bufferlist bl, bl2; + ::encode(spec, bl); + + return ioctx->exec(oid, "rbd", "group_image_remove", bl, bl2); + } + + int group_image_list(librados::IoCtx *ioctx, + const std::string &oid, + const cls::rbd::GroupImageSpec &start, + uint64_t max_return, + std::vector *images) + { + bufferlist bl, bl2; + ::encode(start, bl); + ::encode(max_return, bl); + + int r = ioctx->exec(oid, "rbd", "group_image_list", bl, bl2); + if (r < 0) + return r; + + bufferlist::iterator iter = bl2.begin(); + try { + ::decode(*images, iter); + } catch (const buffer::error &err) { + return -EBADMSG; + } + + return 0; + } + + int group_image_set(librados::IoCtx *ioctx, const std::string &oid, + const cls::rbd::GroupImageStatus &st) + { + bufferlist bl, bl2; + ::encode(st, bl); + + return ioctx->exec(oid, "rbd", "group_image_set", bl, bl2); + } + + int image_add_group(librados::IoCtx *ioctx, const std::string &oid, + const cls::rbd::GroupSpec &group_spec) + { + bufferlist bl, bl2; + ::encode(group_spec, bl); + + return ioctx->exec(oid, "rbd", "image_add_group", bl, bl2); + } + + int image_remove_group(librados::IoCtx *ioctx, const std::string &oid, + const cls::rbd::GroupSpec &group_spec) + { + bufferlist bl, bl2; + ::encode(group_spec, bl); + + return ioctx->exec(oid, "rbd", "image_remove_group", bl, bl2); + } + + void image_get_group_start(librados::ObjectReadOperation *op) + { + bufferlist in_bl; + op->exec("rbd", "image_get_group", in_bl); + } + + int image_get_group_finish(bufferlist::iterator *iter, + cls::rbd::GroupSpec *group_spec) + { + try { + ::decode(*group_spec, *iter); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int image_get_group(librados::IoCtx *ioctx, const std::string &oid, + cls::rbd::GroupSpec *group_spec) + { + librados::ObjectReadOperation op; + image_get_group_start(&op); + + bufferlist out_bl; + int r = ioctx->operate(oid, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator iter = out_bl.begin(); + return image_get_group_finish(&iter, group_spec); + } + + // rbd_trash functions + void trash_add(librados::ObjectWriteOperation *op, + const std::string &id, + const cls::rbd::TrashImageSpec &trash_spec) + { + bufferlist bl; + ::encode(id, bl); + ::encode(trash_spec, bl); + op->exec("rbd", "trash_add", bl); + } + + int trash_add(librados::IoCtx *ioctx, const std::string &id, + const cls::rbd::TrashImageSpec &trash_spec) + { + librados::ObjectWriteOperation op; + trash_add(&op, id, trash_spec); + + return ioctx->operate(RBD_TRASH, &op); + } + + void trash_remove(librados::ObjectWriteOperation *op, + const std::string &id) + { + bufferlist bl; + ::encode(id, bl); + op->exec("rbd", "trash_remove", bl); + } + + int trash_remove(librados::IoCtx *ioctx, const std::string &id) + { + librados::ObjectWriteOperation op; + trash_remove(&op, id); + + return ioctx->operate(RBD_TRASH, &op); + } + + void trash_list_start(librados::ObjectReadOperation *op, + const std::string &start, uint64_t max_return) + { + bufferlist bl; + ::encode(start, bl); + ::encode(max_return, bl); + op->exec("rbd", "trash_list", bl); + } + + int trash_list_finish(bufferlist::iterator *it, + map *entries) + { + assert(entries); + + try { + ::decode(*entries, *it); + } catch (const buffer::error &err) { + return -EBADMSG; + } + + return 0; + } + + int trash_list(librados::IoCtx *ioctx, + const std::string &start, uint64_t max_return, + map *entries) + { + librados::ObjectReadOperation op; + trash_list_start(&op, start, max_return); + + bufferlist out_bl; + int r = ioctx->operate(RBD_TRASH, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator iter = out_bl.begin(); + return trash_list_finish(&iter, entries); + } + + void trash_get_start(librados::ObjectReadOperation *op, + const std::string &id) + { + bufferlist bl; + ::encode(id, bl); + op->exec("rbd", "trash_get", bl); + } + + int trash_get_finish(bufferlist::iterator *it, + cls::rbd::TrashImageSpec *trash_spec) { + assert(trash_spec); + try { + ::decode(*trash_spec, *it); + } catch (const buffer::error &err) { + return -EBADMSG; + } + + return 0; + } + + + int trash_get(librados::IoCtx *ioctx, const std::string &id, + cls::rbd::TrashImageSpec *trash_spec) + { + librados::ObjectReadOperation op; + trash_get_start(&op, id); + + bufferlist out_bl; + int r = ioctx->operate(RBD_TRASH, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator it = out_bl.begin(); + return trash_get_finish(&it, trash_spec); + } + + } // namespace cls_client +} // namespace librbd