typedef void *rbd_snap_t;
typedef void *rbd_image_t;
+typedef void *rbd_image_options_t;
typedef int (*librbd_progress_fn_t)(uint64_t offset, uint64_t total, void *ptr);
CEPH_RBD_API void rbd_version(int *major, int *minor, int *extra);
+/* image options */
+enum {
+ RBD_IMAGE_OPTION_FORMAT = 0,
+ RBD_IMAGE_OPTION_FEATURES = 1,
+ RBD_IMAGE_OPTION_ORDER = 2,
+ RBD_IMAGE_OPTION_STRIPE_UNIT = 3,
+ RBD_IMAGE_OPTION_STRIPE_COUNT = 4,
+};
+
+CEPH_RBD_API void rbd_image_options_create(rbd_image_options_t* opts);
+CEPH_RBD_API void rbd_image_options_destroy(rbd_image_options_t opts);
+CEPH_RBD_API int rbd_image_options_set_string(rbd_image_options_t opts,
+ int optname, const char* optval);
+CEPH_RBD_API int rbd_image_options_set_uint64(rbd_image_options_t opts,
+ int optname, uint64_t optval);
+CEPH_RBD_API int rbd_image_options_get_string(rbd_image_options_t opts,
+ int optname, char* optval,
+ size_t maxlen);
+CEPH_RBD_API int rbd_image_options_get_uint64(rbd_image_options_t opts,
+ int optname, uint64_t* optval);
+CEPH_RBD_API int rbd_image_options_unset(rbd_image_options_t opts, int optname);
+CEPH_RBD_API void rbd_image_options_clear(rbd_image_options_t opts);
+CEPH_RBD_API int rbd_image_options_is_empty(rbd_image_options_t opts);
+
/* images */
CEPH_RBD_API int rbd_list(rados_ioctx_t io, char *names, size_t *size);
CEPH_RBD_API int rbd_create(rados_ioctx_t io, const char *name, uint64_t size,
CEPH_RBD_API int rbd_create3(rados_ioctx_t io, const char *name, uint64_t size,
uint64_t features, int *order,
uint64_t stripe_unit, uint64_t stripe_count);
+CEPH_RBD_API int rbd_create4(rados_ioctx_t io, const char *name, uint64_t size,
+ rbd_image_options_t opts);
CEPH_RBD_API int rbd_clone(rados_ioctx_t p_ioctx, const char *p_name,
const char *p_snapname, rados_ioctx_t c_ioctx,
const char *c_name, uint64_t features, int *c_order);
const char *p_snapname, rados_ioctx_t c_ioctx,
const char *c_name, uint64_t features, int *c_order,
uint64_t stripe_unit, int stripe_count);
+CEPH_RBD_API int rbd_clone3(rados_ioctx_t p_ioctx, const char *p_name,
+ const char *p_snapname, rados_ioctx_t c_ioctx,
+ const char *c_name, rbd_image_options_t c_opts);
CEPH_RBD_API int rbd_remove(rados_ioctx_t io, const char *name);
CEPH_RBD_API int rbd_remove_with_progress(rados_ioctx_t io, const char *name,
librbd_progress_fn_t cb,
CEPH_RBD_API int rbd_copy(rbd_image_t image, rados_ioctx_t dest_io_ctx,
const char *destname);
CEPH_RBD_API int rbd_copy2(rbd_image_t src, rbd_image_t dest);
+CEPH_RBD_API int rbd_copy3(rbd_image_t src, rados_ioctx_t dest_io_ctx,
+ const char *destname, rbd_image_options_t dest_opts);
CEPH_RBD_API int rbd_copy_with_progress(rbd_image_t image, rados_ioctx_t dest_p,
const char *destname,
librbd_progress_fn_t cb, void *cbdata);
CEPH_RBD_API int rbd_copy_with_progress2(rbd_image_t src, rbd_image_t dest,
librbd_progress_fn_t cb, void *cbdata);
+CEPH_RBD_API int rbd_copy_with_progress3(rbd_image_t image,
+ rados_ioctx_t dest_p,
+ const char *destname,
+ rbd_image_options_t dest_opts,
+ librbd_progress_fn_t cb, void *cbdata);
/* snapshots */
CEPH_RBD_API int rbd_snap_list(rbd_image_t image, rbd_snap_info_t *snaps,
using librados::IoCtx;
class Image;
+ class ImageOptions;
typedef void *image_ctx_t;
typedef void *completion_t;
typedef void (*callback_t)(completion_t cb, void *arg);
int create3(IoCtx& io_ctx, const char *name, uint64_t size,
uint64_t features, int *order,
uint64_t stripe_unit, uint64_t stripe_count);
+ int create4(IoCtx& io_ctx, const char *name, uint64_t size,
+ ImageOptions& opts);
int clone(IoCtx& p_ioctx, const char *p_name, const char *p_snapname,
IoCtx& c_ioctx, const char *c_name, uint64_t features,
int *c_order);
int clone2(IoCtx& p_ioctx, const char *p_name, const char *p_snapname,
IoCtx& c_ioctx, const char *c_name, uint64_t features,
int *c_order, uint64_t stripe_unit, int stripe_count);
+ int clone3(IoCtx& p_ioctx, const char *p_name, const char *p_snapname,
+ IoCtx& c_ioctx, const char *c_name, ImageOptions& opts);
int remove(IoCtx& io_ctx, const char *name);
int remove_with_progress(IoCtx& io_ctx, const char *name, ProgressContext& pctx);
int rename(IoCtx& src_io_ctx, const char *srcname, const char *destname);
const RBD& operator=(const RBD& rhs);
};
+class CEPH_RBD_API ImageOptions {
+public:
+ ImageOptions();
+ ImageOptions(rbd_image_options_t opts);
+ ~ImageOptions();
+
+ int set(int optname, const std::string& optval);
+ int set(int optname, uint64_t optval);
+ int get(int optname, std::string* optval) const;
+ int get(int optname, uint64_t* optval) const;
+ int unset(int optname);
+ void clear();
+ bool empty() const;
+
+private:
+ friend class RBD;
+ friend class Image;
+
+ rbd_image_options_t opts;
+};
+
class CEPH_RBD_API Image
{
public:
int copy(IoCtx& dest_io_ctx, const char *destname);
int copy2(Image& dest);
+ int copy3(IoCtx& dest_io_ctx, const char *destname, ImageOptions& opts);
int copy_with_progress(IoCtx& dest_io_ctx, const char *destname,
ProgressContext &prog_ctx);
int copy_with_progress2(Image& dest, ProgressContext &prog_ctx);
+ int copy_with_progress3(IoCtx& dest_io_ctx, const char *destname,
+ ImageOptions& opts, ProgressContext &prog_ctx);
/* striping */
uint64_t get_stripe_unit() const;
#include <boost/bind.hpp>
#include <boost/scope_exit.hpp>
+#include <boost/variant.hpp>
#include "include/assert.h"
#define dout_subsys ceph_subsys_rbd
return io_ctx.tmap_update(RBD_DIRECTORY, cmdbl);
}
+ typedef boost::variant<std::string,uint64_t> image_option_value_t;
+ typedef std::map<int,image_option_value_t> image_options_t;
+ typedef std::shared_ptr<image_options_t> image_options_ref;
+
+ enum image_option_type_t {
+ STR,
+ UINT64,
+ };
+
+ const std::map<int, image_option_type_t> IMAGE_OPTIONS_TYPE_MAPPING = {
+ {RBD_IMAGE_OPTION_FORMAT, UINT64},
+ {RBD_IMAGE_OPTION_FEATURES, UINT64},
+ {RBD_IMAGE_OPTION_ORDER, UINT64},
+ {RBD_IMAGE_OPTION_STRIPE_UNIT, UINT64},
+ {RBD_IMAGE_OPTION_STRIPE_COUNT, UINT64},
+ };
+
+ void image_options_create(rbd_image_options_t* opts)
+ {
+ image_options_ref* opts_ = new image_options_ref(new image_options_t());
+
+ *opts = static_cast<rbd_image_options_t>(opts_);
+ }
+
+ void image_options_create_ref(rbd_image_options_t* opts,
+ rbd_image_options_t orig)
+ {
+ image_options_ref* orig_ = static_cast<image_options_ref*>(orig);
+ image_options_ref* opts_ = new image_options_ref(*orig_);
+
+ *opts = static_cast<rbd_image_options_t>(opts_);
+ }
+
+ void image_options_destroy(rbd_image_options_t opts)
+ {
+ image_options_ref* opts_ = static_cast<image_options_ref*>(opts);
+
+ delete opts_;
+ }
+
+ int image_options_set(rbd_image_options_t opts, int optname,
+ const std::string& optval)
+ {
+ image_options_ref* opts_ = static_cast<image_options_ref*>(opts);
+
+ std::map<int, image_option_type_t>::const_iterator i =
+ IMAGE_OPTIONS_TYPE_MAPPING.find(optname);
+
+ if (i == IMAGE_OPTIONS_TYPE_MAPPING.end() || i->second != STR) {
+ return -EINVAL;
+ }
+
+ (*opts_->get())[optname] = optval;
+ return 0;
+ }
+
+ int image_options_set(rbd_image_options_t opts, int optname, uint64_t optval)
+ {
+ image_options_ref* opts_ = static_cast<image_options_ref*>(opts);
+
+ std::map<int, image_option_type_t>::const_iterator i =
+ IMAGE_OPTIONS_TYPE_MAPPING.find(optname);
+
+ if (i == IMAGE_OPTIONS_TYPE_MAPPING.end() || i->second != UINT64) {
+ return -EINVAL;
+ }
+
+ (*opts_->get())[optname] = optval;
+ return 0;
+ }
+
+ int image_options_get(rbd_image_options_t opts, int optname,
+ std::string* optval)
+ {
+ image_options_ref* opts_ = static_cast<image_options_ref*>(opts);
+
+ std::map<int, image_option_type_t>::const_iterator i =
+ IMAGE_OPTIONS_TYPE_MAPPING.find(optname);
+
+ if (i == IMAGE_OPTIONS_TYPE_MAPPING.end() || i->second != STR) {
+ return -EINVAL;
+ }
+
+ image_options_t::const_iterator j = (*opts_)->find(optname);
+
+ if (j == (*opts_)->end()) {
+ return -ENOENT;
+ }
+
+ *optval = boost::get<std::string>(j->second);
+ return 0;
+ }
+
+ int image_options_get(rbd_image_options_t opts, int optname, uint64_t* optval)
+ {
+ image_options_ref* opts_ = static_cast<image_options_ref*>(opts);
+
+ std::map<int, image_option_type_t>::const_iterator i =
+ IMAGE_OPTIONS_TYPE_MAPPING.find(optname);
+
+ if (i == IMAGE_OPTIONS_TYPE_MAPPING.end() || i->second != UINT64) {
+ return -EINVAL;
+ }
+
+ image_options_t::const_iterator j = (*opts_)->find(optname);
+
+ if (j == (*opts_)->end()) {
+ return -ENOENT;
+ }
+
+ *optval = boost::get<uint64_t>(j->second);
+ return 0;
+ }
+
+ int image_options_unset(rbd_image_options_t opts, int optname)
+ {
+ image_options_ref* opts_ = static_cast<image_options_ref*>(opts);
+
+ std::map<int, image_option_type_t>::const_iterator i =
+ IMAGE_OPTIONS_TYPE_MAPPING.find(optname);
+
+ if (i == IMAGE_OPTIONS_TYPE_MAPPING.end()) {
+ assert((*opts_)->find(optname) == (*opts_)->end());
+ return -EINVAL;
+ }
+
+ image_options_t::const_iterator j = (*opts_)->find(optname);
+
+ if (j == (*opts_)->end()) {
+ return -ENOENT;
+ }
+
+ (*opts_)->erase(j);
+ return 0;
+ }
+
+ void image_options_clear(rbd_image_options_t opts)
+ {
+ image_options_ref* opts_ = static_cast<image_options_ref*>(opts);
+
+ (*opts_)->clear();
+ }
+
+ bool image_options_is_empty(rbd_image_options_t opts)
+ {
+ image_options_ref* opts_ = static_cast<image_options_ref*>(opts);
+
+ return (*opts_)->empty();
+ }
+
void rollback_object(ImageCtx *ictx, uint64_t snap_id, const string& oid,
SimpleThrottle& throttle)
{
if (!order)
return -EINVAL;
+ uint64_t order_ = *order;
+ uint64_t format = old_format ? 1 : 2;
+ ImageOptions opts;
+ int r;
+
+ r = opts.set(RBD_IMAGE_OPTION_FORMAT, format);
+ assert(r == 0);
+ r = opts.set(RBD_IMAGE_OPTION_FEATURES, features);
+ assert(r == 0);
+ r = opts.set(RBD_IMAGE_OPTION_ORDER, order_);
+ assert(r == 0);
+ r = opts.set(RBD_IMAGE_OPTION_STRIPE_UNIT, stripe_unit);
+ assert(r == 0);
+ r = opts.set(RBD_IMAGE_OPTION_STRIPE_COUNT, stripe_count);
+ assert(r == 0);
+
+ r = create(io_ctx, imgname, size, opts);
+
+ int r1 = opts.get(RBD_IMAGE_OPTION_ORDER, &order_);
+ assert(r1 == 0);
+ *order = order_;
+
+ return r;
+ }
+
+ int create(IoCtx& io_ctx, const char *imgname, uint64_t size,
+ ImageOptions& opts)
+ {
CephContext *cct = (CephContext *)io_ctx.cct();
+
+ uint64_t format = cct->_conf->rbd_default_format;
+ opts.get(RBD_IMAGE_OPTION_FORMAT, &format);
+ bool old_format = format == 1;
+
+ uint64_t features;
+ if (opts.get(RBD_IMAGE_OPTION_FEATURES, &features) != 0) {
+ features = old_format ? 0 : cct->_conf->rbd_default_features;
+ }
+ uint64_t stripe_unit = 0;
+ uint64_t stripe_count = 0;
+ opts.get(RBD_IMAGE_OPTION_STRIPE_UNIT, &stripe_unit);
+ opts.get(RBD_IMAGE_OPTION_STRIPE_COUNT, &stripe_count);
+
+ uint64_t order = 0;
+ opts.get(RBD_IMAGE_OPTION_ORDER, &order);
+
ldout(cct, 20) << "create " << &io_ctx << " name = " << imgname
<< " size = " << size << " old_format = " << old_format
- << " features = " << features << " order = " << *order
+ << " features = " << features << " order = " << order
<< " stripe_unit = " << stripe_unit
<< " stripe_count = " << stripe_count
<< dendl;
-
if (features & ~RBD_FEATURES_ALL) {
lderr(cct) << "librbd does not support requested features." << dendl;
return -ENOSYS;
return -EEXIST;
}
- if (!*order)
- *order = cct->_conf->rbd_default_order;
- if (!*order)
- *order = RBD_DEFAULT_OBJ_ORDER;
+ if (!order)
+ order = cct->_conf->rbd_default_order;
+ if (!order)
+ order = RBD_DEFAULT_OBJ_ORDER;
- if (*order > 25 || *order < 12) {
+ if (order > 25 || order < 12) {
lderr(cct) << "order must be in the range [12, 25]" << dendl;
return -EDOM;
}
}
// normalize for default striping
- if (stripe_unit == (1ull << *order) && stripe_count == 1) {
+ if (stripe_unit == (1ull << order) && stripe_count == 1) {
stripe_unit = 0;
stripe_count = 0;
}
return -EINVAL;
if (old_format) {
- if (stripe_unit && stripe_unit != (1ull << *order))
+ if (stripe_unit && stripe_unit != (1ull << order))
return -EINVAL;
if (stripe_count && stripe_count != 1)
return -EINVAL;
- return create_v1(io_ctx, imgname, bid, size, *order);
+ r = create_v1(io_ctx, imgname, bid, size, order);
} else {
- return create_v2(io_ctx, imgname, bid, size, *order, features,
- stripe_unit, stripe_count);
+ r = create_v2(io_ctx, imgname, bid, size, order, features, stripe_unit,
+ stripe_count);
}
+
+ int r1 = opts.set(RBD_IMAGE_OPTION_ORDER, order);
+ assert(r1 == 0);
+
+ return r;
}
/*
* Parent may be in different pool, hence different IoCtx
*/
+ int clone(IoCtx& p_ioctx, const char *p_name, const char *p_snap_name,
+ IoCtx& c_ioctx, const char *c_name, ImageOptions& c_opts)
+ {
+ int order = 0;
+ uint64_t features = 0;
+ uint64_t stripe_unit = 0;
+ uint64_t stripe_count = 0;
+ c_opts.get(RBD_IMAGE_OPTION_FEATURES, &features);
+ c_opts.get(RBD_IMAGE_OPTION_STRIPE_UNIT, &stripe_unit);
+ c_opts.get(RBD_IMAGE_OPTION_STRIPE_COUNT, &stripe_count);
+
+ int r = clone(p_ioctx, p_name, p_snap_name, c_ioctx, c_name, features,
+ &order, stripe_unit, stripe_count);
+ c_opts.set(RBD_IMAGE_OPTION_ORDER, static_cast<uint64_t>(order));
+ return r;
+ }
+
int clone(IoCtx& p_ioctx, const char *p_name, const char *p_snap_name,
IoCtx& c_ioctx, const char *c_name,
uint64_t features, int *c_order,
}
int copy(ImageCtx *src, IoCtx& dest_md_ctx, const char *destname,
- ProgressContext &prog_ctx)
+ ImageOptions& opts, ProgressContext &prog_ctx)
{
CephContext *cct = (CephContext *)dest_md_ctx.cct();
ldout(cct, 20) << "copy " << src->name
<< (src->snap_name.length() ? "@" + src->snap_name : "")
<< " -> " << destname << dendl;
- int order = src->order;
src->snap_lock.get_read();
- uint64_t src_features = src->features;
+ uint64_t features = src->features;
uint64_t src_size = src->get_image_size(src->snap_id);
src->snap_lock.put_read();
+ uint64_t stripe_unit = src->stripe_unit;
+ uint64_t stripe_count = src->stripe_count;
+ opts.get(RBD_IMAGE_OPTION_FEATURES, &features);
+ opts.get(RBD_IMAGE_OPTION_STRIPE_UNIT, &stripe_unit);
+ opts.get(RBD_IMAGE_OPTION_STRIPE_COUNT, &stripe_count);
+ int order = src->order;
+ uint64_t opt_order = 0;
+ if (opts.get(RBD_IMAGE_OPTION_ORDER, &opt_order)) {
+ order = opt_order;
+ }
+
+ if (features & ~RBD_FEATURES_ALL) {
+ lderr(cct) << "librbd does not support requested features" << dendl;
+ return -ENOSYS;
+ }
int r = create(dest_md_ctx, destname, src_size, src->old_format,
- src_features, &order, src->stripe_unit, src->stripe_count);
+ features, &order, stripe_unit, stripe_count);
if (r < 0) {
lderr(cct) << "header creation failed" << dendl;
return r;
}
+ opts.set(RBD_IMAGE_OPTION_ORDER, static_cast<uint64_t>(order));
ImageCtx *dest = new librbd::ImageCtx(destname, "", NULL,
dest_md_ctx, false);
bool has_parent(int64_t parent_pool_id, uint64_t off, uint64_t overlap);
+ void image_options_create(rbd_image_options_t* opts);
+ void image_options_create_ref(rbd_image_options_t* opts,
+ rbd_image_options_t orig);
+ void image_options_destroy(rbd_image_options_t opts);
+ int image_options_set(rbd_image_options_t opts, int optname,
+ const std::string& optval);
+ int image_options_set(rbd_image_options_t opts, int optname, uint64_t optval);
+ int image_options_get(rbd_image_options_t opts, int optname,
+ std::string* optval);
+ int image_options_get(rbd_image_options_t opts, int optname,
+ uint64_t* optval);
+ int image_options_unset(rbd_image_options_t opts, int optname);
+ void image_options_clear(rbd_image_options_t opts);
+ bool image_options_is_empty(rbd_image_options_t opts);
+
int snap_set(ImageCtx *ictx, const char *snap_name);
int list(librados::IoCtx& io_ctx, std::vector<std::string>& names);
int list_children(ImageCtx *ictx,
int create(librados::IoCtx& io_ctx, const char *imgname, uint64_t size,
bool old_format, uint64_t features, int *order,
uint64_t stripe_unit, uint64_t stripe_count);
+ int create(IoCtx& io_ctx, const char *imgname, uint64_t size,
+ ImageOptions& opts);
int clone(IoCtx& p_ioctx, const char *p_name, const char *p_snap_name,
IoCtx& c_ioctx, const char *c_name,
uint64_t features, int *c_order,
uint64_t stripe_unit, int stripe_count);
+ int clone(IoCtx& p_ioctx, const char *p_name, const char *p_snap_name,
+ IoCtx& c_ioctx, const char *c_name, ImageOptions& c_opts);
int rename(librados::IoCtx& io_ctx, const char *srcname, const char *dstname);
int info(ImageCtx *ictx, image_info_t& info, size_t image_size);
int get_old_format(ImageCtx *ictx, uint8_t *old);
int ictx_check(ImageCtx *ictx, bool owner_locked=false);
int ictx_refresh(ImageCtx *ictx);
int copy(ImageCtx *ictx, IoCtx& dest_md_ctx, const char *destname,
- ProgressContext &prog_ctx);
+ ImageOptions& opts, ProgressContext &prog_ctx);
int copy(ImageCtx *src, ImageCtx *dest, ProgressContext &prog_ctx);
int open_parent(ImageCtx *ictx);
return r;
}
+ int RBD::create4(IoCtx& io_ctx, const char *name, uint64_t size,
+ ImageOptions& opts)
+ {
+ TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
+ tracepoint(librbd, create4_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, opts.opts);
+ int r = librbd::create(io_ctx, name, size, opts);
+ tracepoint(librbd, create4_exit, r);
+ return r;
+ }
+
int RBD::clone(IoCtx& p_ioctx, const char *p_name, const char *p_snap_name,
IoCtx& c_ioctx, const char *c_name, uint64_t features,
int *c_order)
return r;
}
+ int RBD::clone3(IoCtx& p_ioctx, const char *p_name, const char *p_snap_name,
+ IoCtx& c_ioctx, const char *c_name, ImageOptions& c_opts)
+ {
+ TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioctx));
+ tracepoint(librbd, clone3_enter, p_ioctx.get_pool_name().c_str(), p_ioctx.get_id(), p_name, p_snap_name, c_ioctx.get_pool_name().c_str(), c_ioctx.get_id(), c_name, c_opts.opts);
+ int r = librbd::clone(p_ioctx, p_name, p_snap_name, c_ioctx, c_name,
+ c_opts);
+ tracepoint(librbd, clone3_exit, r);
+ return r;
+ }
+
int RBD::remove(IoCtx& io_ctx, const char *name)
{
TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
delete this;
}
+ /*
+ ImageOptions
+ */
+
+ ImageOptions::ImageOptions()
+ {
+ librbd::image_options_create(&opts);
+ }
+
+ ImageOptions::ImageOptions(rbd_image_options_t opts_)
+ {
+ librbd::image_options_create_ref(&opts, opts_);
+ }
+
+ ImageOptions::~ImageOptions()
+ {
+ librbd::image_options_destroy(opts);
+ }
+
+ int ImageOptions::set(int optname, const std::string& optval)
+ {
+ return librbd::image_options_set(opts, optname, optval);
+ }
+
+ int ImageOptions::set(int optname, uint64_t optval)
+ {
+ return librbd::image_options_set(opts, optname, optval);
+ }
+
+ int ImageOptions::get(int optname, std::string* optval) const
+ {
+ return librbd::image_options_get(opts, optname, optval);
+ }
+
+ int ImageOptions::get(int optname, uint64_t* optval) const
+ {
+ return librbd::image_options_get(opts, optname, optval);
+ }
+
+ int ImageOptions::unset(int optname)
+ {
+ return librbd::image_options_unset(opts, optname);
+ }
+
+ void ImageOptions::clear()
+ {
+ librbd::image_options_clear(opts);
+ }
+
+ bool ImageOptions::empty() const
+ {
+ return librbd::image_options_is_empty(opts);
+ }
+
/*
Image
*/
{
ImageCtx *ictx = (ImageCtx *)ctx;
tracepoint(librbd, copy_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname);
+ ImageOptions opts;
librbd::NoOpProgressContext prog_ctx;
- int r = librbd::copy(ictx, dest_io_ctx, destname, prog_ctx);
+ int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx);
tracepoint(librbd, copy_exit, r);
return r;
}
return r;
}
+ int Image::copy3(IoCtx& dest_io_ctx, const char *destname, ImageOptions& opts)
+ {
+ ImageCtx *ictx = (ImageCtx *)ctx;
+ tracepoint(librbd, copy3_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, opts.opts);
+ librbd::NoOpProgressContext prog_ctx;
+ int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx);
+ tracepoint(librbd, copy3_exit, r);
+ return r;
+ }
+
int Image::copy_with_progress(IoCtx& dest_io_ctx, const char *destname,
librbd::ProgressContext &pctx)
{
ImageCtx *ictx = (ImageCtx *)ctx;
tracepoint(librbd, copy_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname);
- int r = librbd::copy(ictx, dest_io_ctx, destname, pctx);
+ ImageOptions opts;
+ int r = librbd::copy(ictx, dest_io_ctx, destname, opts, pctx);
tracepoint(librbd, copy_exit, r);
return r;
}
return r;
}
+ int Image::copy_with_progress3(IoCtx& dest_io_ctx, const char *destname,
+ ImageOptions& opts,
+ librbd::ProgressContext &pctx)
+ {
+ ImageCtx *ictx = (ImageCtx *)ctx;
+ tracepoint(librbd, copy3_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, opts.opts);
+ int r = librbd::copy(ictx, dest_io_ctx, destname, opts, pctx);
+ tracepoint(librbd, copy3_exit, r);
+ return r;
+ }
+
int Image::flatten()
{
ImageCtx *ictx = (ImageCtx *)ctx;
*extra = LIBRBD_VER_EXTRA;
}
+extern "C" void rbd_image_options_create(rbd_image_options_t* opts)
+{
+ librbd::image_options_create(opts);
+}
+
+extern "C" void rbd_image_options_destroy(rbd_image_options_t opts)
+{
+ librbd::image_options_destroy(opts);
+}
+
+extern "C" int rbd_image_options_set_string(rbd_image_options_t opts, int optname,
+ const char* optval)
+{
+ return librbd::image_options_set(opts, optname, optval);
+}
+
+extern "C" int rbd_image_options_set_uint64(rbd_image_options_t opts, int optname,
+ uint64_t optval)
+{
+ return librbd::image_options_set(opts, optname, optval);
+}
+
+extern "C" int rbd_image_options_get_string(rbd_image_options_t opts, int optname,
+ char* optval, size_t maxlen)
+{
+ std::string optval_;
+
+ int r = librbd::image_options_get(opts, optname, &optval_);
+
+ if (r < 0) {
+ return r;
+ }
+
+ if (optval_.size() >= maxlen) {
+ return -E2BIG;
+ }
+
+ strncpy(optval, optval_.c_str(), maxlen);
+
+ return 0;
+}
+
+extern "C" int rbd_image_options_get_uint64(rbd_image_options_t opts, int optname,
+ uint64_t* optval)
+{
+ return librbd::image_options_get(opts, optname, optval);
+}
+
+extern "C" int rbd_image_options_unset(rbd_image_options_t opts, int optname)
+{
+ return librbd::image_options_unset(opts, optname);
+}
+
+extern "C" void rbd_image_options_clear(rbd_image_options_t opts)
+{
+ librbd::image_options_clear(opts);
+}
+
+extern "C" int rbd_image_options_is_empty(rbd_image_options_t opts)
+{
+ return librbd::image_options_is_empty(opts);
+}
+
/* images */
extern "C" int rbd_list(rados_ioctx_t p, char *names, size_t *size)
{
return r;
}
+extern "C" int rbd_create4(rados_ioctx_t p, const char *name,
+ uint64_t size, rbd_image_options_t opts)
+{
+ librados::IoCtx io_ctx;
+ librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
+ TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
+ tracepoint(librbd, create4_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, opts);
+ librbd::ImageOptions opts_(opts);
+ int r = librbd::create(io_ctx, name, size, opts_);
+ tracepoint(librbd, create4_exit, r);
+ return r;
+}
+
extern "C" int rbd_clone(rados_ioctx_t p_ioctx, const char *p_name,
const char *p_snap_name, rados_ioctx_t c_ioctx,
const char *c_name, uint64_t features, int *c_order)
return r;
}
+extern "C" int rbd_clone3(rados_ioctx_t p_ioctx, const char *p_name,
+ const char *p_snap_name, rados_ioctx_t c_ioctx,
+ const char *c_name, rbd_image_options_t c_opts)
+{
+ librados::IoCtx p_ioc, c_ioc;
+ librados::IoCtx::from_rados_ioctx_t(p_ioctx, p_ioc);
+ librados::IoCtx::from_rados_ioctx_t(c_ioctx, c_ioc);
+ TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioc));
+ tracepoint(librbd, clone3_enter, p_ioc.get_pool_name().c_str(), p_ioc.get_id(), p_name, p_snap_name, c_ioc.get_pool_name().c_str(), c_ioc.get_id(), c_name, c_opts);
+ librbd::ImageOptions c_opts_(c_opts);
+ int r = librbd::clone(p_ioc, p_name, p_snap_name, c_ioc, c_name, c_opts_);
+ tracepoint(librbd, clone3_exit, r);
+ return r;
+}
+
extern "C" int rbd_remove(rados_ioctx_t p, const char *name)
{
librados::IoCtx io_ctx;
librados::IoCtx dest_io_ctx;
librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
tracepoint(librbd, copy_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname);
+ librbd::ImageOptions opts;
librbd::NoOpProgressContext prog_ctx;
- int r = librbd::copy(ictx, dest_io_ctx, destname, prog_ctx);
+ int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx);
tracepoint(librbd, copy_exit, r);
return r;
}
return r;
}
+extern "C" int rbd_copy3(rbd_image_t image, rados_ioctx_t dest_p,
+ const char *destname, rbd_image_options_t c_opts)
+{
+ librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
+ librados::IoCtx dest_io_ctx;
+ librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
+ tracepoint(librbd, copy3_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, c_opts);
+ librbd::ImageOptions c_opts_(c_opts);
+ librbd::NoOpProgressContext prog_ctx;
+ int r = librbd::copy(ictx, dest_io_ctx, destname, c_opts_, prog_ctx);
+ tracepoint(librbd, copy3_exit, r);
+ return r;
+}
+
extern "C" int rbd_copy_with_progress(rbd_image_t image, rados_ioctx_t dest_p,
const char *destname,
librbd_progress_fn_t fn, void *data)
librados::IoCtx dest_io_ctx;
librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
tracepoint(librbd, copy_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname);
+ librbd::ImageOptions opts;
librbd::CProgressContext prog_ctx(fn, data);
- int ret = librbd::copy(ictx, dest_io_ctx, destname, prog_ctx);
+ int ret = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx);
tracepoint(librbd, copy_exit, ret);
return ret;
}
return ret;
}
+extern "C" int rbd_copy_with_progress3(rbd_image_t image, rados_ioctx_t dest_p,
+ const char *destname,
+ rbd_image_options_t dest_opts,
+ librbd_progress_fn_t fn, void *data)
+{
+ librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
+ librados::IoCtx dest_io_ctx;
+ librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
+ tracepoint(librbd, copy_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname);
+ librbd::ImageOptions dest_opts_(dest_opts);
+ librbd::CProgressContext prog_ctx(fn, data);
+ int ret = librbd::copy(ictx, dest_io_ctx, destname, dest_opts_, prog_ctx);
+ tracepoint(librbd, copy_exit, ret);
+ return ret;
+}
+
extern "C" int rbd_flatten(rbd_image_t image)
{
librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
RBD_FLAG_OBJECT_MAP_INVALID = 1
+RBD_IMAGE_OPTION_FORMAT = 0
+RBD_IMAGE_OPTION_FEATURES = 1
+RBD_IMAGE_OPTION_ORDER = 2
+RBD_IMAGE_OPTION_STRIPE_UNIT = 3
+RBD_IMAGE_OPTION_STRIPE_COUNT = 4
+
class Error(Exception):
pass
if not hasattr(self.librbd, 'rbd_create2'):
raise FunctionNotSupported('installed version of librbd does'
' not support format 2 images')
+ has_create4 = hasattr(self.librbd, 'rbd_create4')
has_create3 = hasattr(self.librbd, 'rbd_create3')
if (stripe_unit != 0 or stripe_count != 0) and not has_create3:
raise FunctionNotSupported('installed version of librbd does'
' not support stripe unit or count')
- if has_create3:
+ if has_create4:
+ format = old_format and 1 or 2
+ opts = c_void_p()
+ self.librbd.rbd_image_options_create(byref(opts))
+ self.librbd.rbd_image_options_set_uint64(opts,
+ RBD_IMAGE_OPTION_FORMAT,
+ c_uint64(format))
+ self.librbd.rbd_image_options_set_uint64(opts,
+ RBD_IMAGE_OPTION_FEATURES,
+ c_uint64(features))
+ self.librbd.rbd_image_options_set_uint64(opts,
+ RBD_IMAGE_OPTION_ORDER,
+ c_uint64(order))
+ self.librbd.rbd_image_options_set_uint64(opts,
+ RBD_IMAGE_OPTION_STRIPE_UNIT,
+ c_uint64(stripe_unit))
+ self.librbd.rbd_image_options_set_uint64(opts,
+ RBD_IMAGE_OPTION_STRIPE_COUNT,
+ c_uint64(stripe_count))
+ ret = self.librbd.rbd_create4(ioctx.io, c_char_p(name),
+ c_uint64(size), opts)
+ self.librbd.rbd_image_options_get_uint64(opts,
+ RBD_IMAGE_OPTION_ORDER,
+ byref(c_uint64(order)))
+ self.librbd.rbd_image_options_destroy(opts)
+ elif has_create3:
ret = self.librbd.rbd_create3(ioctx.io, c_char_p(name),
c_uint64(size),
c_uint64(features),
raise make_ex(ret, 'error creating image')
def clone(self, p_ioctx, p_name, p_snapname, c_ioctx, c_name,
- features=0, order=None):
+ features=0, order=None, stripe_unit=0, stripe_count=0):
"""
Clone a parent rbd snapshot into a COW sparse child.
:type features: int
:param order: the image is split into (2**order) byte objects
:type order: int
+ :param stripe_unit: stripe unit in bytes (default 0 for object size)
+ :type stripe_unit: int
+ :param stripe_count: objects to stripe over before looping
+ :type stripe_count: int
:raises: :class:`TypeError`
:raises: :class:`InvalidArgument`
:raises: :class:`ImageExists`
if not isinstance(c_name, str):
raise TypeError('child name must be a string')
- ret = self.librbd.rbd_clone(p_ioctx.io, c_char_p(p_name),
- c_char_p(p_snapname),
- c_ioctx.io, c_char_p(c_name),
- c_uint64(features),
- byref(c_int(order)))
+ has_clone3 = hasattr(self.librbd, 'rbd_clone3')
+ if (stripe_unit != 0 or stripe_count != 0) and not has_clone3:
+ raise FunctionNotSupported('installed version of librbd does'
+ ' not support stripe unit or count')
+ if has_clone3:
+ opts = c_void_p()
+ self.librbd.rbd_image_options_create(byref(opts))
+ self.librbd.rbd_image_options_set_uint64(opts,
+ RBD_IMAGE_OPTION_FEATURES,
+ c_uint64(features))
+ self.librbd.rbd_image_options_set_uint64(opts,
+ RBD_IMAGE_OPTION_ORDER,
+ c_uint64(order))
+ self.librbd.rbd_image_options_set_uint64(opts,
+ RBD_IMAGE_OPTION_STRIPE_UNIT,
+ c_uint64(stripe_unit))
+ self.librbd.rbd_image_options_set_uint64(opts,
+ RBD_IMAGE_OPTION_STRIPE_COUNT,
+ c_uint64(stripe_count))
+ ret = self.librbd.rbd_clone3(p_ioctx.io, c_char_p(p_name),
+ c_char_p(p_snapname),
+ c_ioctx.io, c_char_p(c_name),
+ opts)
+ self.librbd.rbd_image_options_get_uint64(opts,
+ RBD_IMAGE_OPTION_ORDER,
+ byref(c_uint64(order)))
+ self.librbd.rbd_image_options_destroy(opts)
+ else:
+ ret = self.librbd.rbd_clone(p_ioctx.io, c_char_p(p_name),
+ c_char_p(p_snapname),
+ c_ioctx.io, c_char_p(c_name),
+ c_uint64(features),
+ byref(c_int(order)))
if ret < 0:
raise make_ex(ret, 'error creating clone')
raise make_ex(ret, 'error getting lock status for image' % (self.name))
return owner.value == 1
- def copy(self, dest_ioctx, dest_name):
+ def copy(self, dest_ioctx, dest_name, features=0, order=None, stripe_unit=0,
+ stripe_count=0):
"""
Copy the image to another location.
:type dest_ioctx: :class:`rados.Ioctx`
:param dest_name: the name of the copy
:type dest_name: str
+ :param features: bitmask of features to enable; if set, must include layering
+ :type features: int
+ :param order: the image is split into (2**order) byte objects
+ :type order: int
+ :param stripe_unit: stripe unit in bytes (default 0 for object size)
+ :type stripe_unit: int
+ :param stripe_count: objects to stripe over before looping
+ :type stripe_count: int
+ :raises: :class:`TypeError`
+ :raises: :class:`InvalidArgument`
:raises: :class:`ImageExists`
+ :raises: :class:`FunctionNotSupported`
+ :raises: :class:`ArgumentOutOfRange`
"""
+ if order is None:
+ order = 0
if not isinstance(dest_name, str):
raise TypeError('dest_name must be a string')
- ret = self.librbd.rbd_copy(self.image, dest_ioctx.io, c_char_p(dest_name))
+ has_copy3 = hasattr(self.librbd, 'rbd_copy3')
+ if (stripe_unit != 0 or stripe_count != 0) and not has_copy3:
+ raise FunctionNotSupported('installed version of librbd does'
+ ' not support stripe unit or count')
+ if has_copy3:
+ opts = c_void_p()
+ self.librbd.rbd_image_options_create(byref(opts))
+ self.librbd.rbd_image_options_set_uint64(opts,
+ RBD_IMAGE_OPTION_FEATURES,
+ c_uint64(features))
+ self.librbd.rbd_image_options_set_uint64(opts,
+ RBD_IMAGE_OPTION_ORDER,
+ c_uint64(order))
+ self.librbd.rbd_image_options_set_uint64(opts,
+ RBD_IMAGE_OPTION_STRIPE_UNIT,
+ c_uint64(stripe_unit))
+ self.librbd.rbd_image_options_set_uint64(opts,
+ RBD_IMAGE_OPTION_STRIPE_COUNT,
+ c_uint64(stripe_count))
+ ret = self.librbd.rbd_copy3(self.image, dest_ioctx.io,
+ c_char_p(dest_name), opts)
+ self.librbd.rbd_image_options_get_uint64(opts,
+ RBD_IMAGE_OPTION_ORDER,
+ byref(c_uint64(order)))
+ self.librbd.rbd_image_options_destroy(opts)
+ else:
+ ret = self.librbd.rbd_copy(self.image, dest_ioctx.io, c_char_p(dest_name))
if ret < 0:
raise make_ex(ret, 'error copying image %s to %s' % (self.name, dest_name))
)
)
+TRACEPOINT_EVENT(librbd, create4_enter,
+ TP_ARGS(
+ const char*, pool_name,
+ int64_t, id,
+ const char*, imgname,
+ uint64_t, size,
+ void*, opts),
+ TP_FIELDS(
+ ctf_string(pool_name, pool_name)
+ ctf_integer(int64_t, id, id)
+ ctf_string(imgname, imgname)
+ ctf_integer_hex(void*, opts, opts)
+ )
+)
+
+TRACEPOINT_EVENT(librbd, create4_exit,
+ TP_ARGS(
+ int, retval),
+ TP_FIELDS(
+ ctf_integer(int, retval, retval)
+ )
+)
+
TRACEPOINT_EVENT(librbd, remove_enter,
TP_ARGS(
const char*, pool_name,
)
)
+TRACEPOINT_EVENT(librbd, copy3_enter,
+ TP_ARGS(
+ void*, src_imagectx,
+ const char*, src_name,
+ const char*, src_snap_name,
+ char, src_read_only,
+ const char*, dst_pool_name,
+ uint64_t, dst_id,
+ const char*, dst_name,
+ void*, opts),
+ TP_FIELDS(
+ ctf_integer_hex(void*, src_imagectx, src_imagectx)
+ ctf_string(src_name, src_name)
+ ctf_string(src_snap_name, src_snap_name)
+ ctf_integer(char, src_read_only, src_read_only)
+ ctf_string(dst_pool_name, dst_pool_name)
+ ctf_integer(uint64_t, dst_id, dst_id)
+ ctf_string(dst_name, dst_name)
+ ctf_integer_hex(void*, opts, opts)
+ )
+)
+
+TRACEPOINT_EVENT(librbd, copy3_exit,
+ TP_ARGS(
+ int, retval),
+ TP_FIELDS(
+ ctf_integer(int, retval, retval)
+ )
+)
+
TRACEPOINT_EVENT(librbd, resize_enter,
TP_ARGS(
void*, imagectx,
)
)
+TRACEPOINT_EVENT(librbd, clone3_enter,
+ TP_ARGS(
+ const char*, parent_pool_name,
+ uint64_t, parent_id,
+ const char*, parent_name,
+ const char*, parent_snap_name,
+ const char*, child_pool_name,
+ uint64_t, child_id,
+ const char*, child_name,
+ void*, opts),
+ TP_FIELDS(
+ ctf_string(parent_pool_name, parent_pool_name)
+ ctf_integer(uint64_t, parent_id, parent_id)
+ ctf_string(parent_name, parent_name)
+ ctf_string(parent_snap_name, parent_snap_name)
+ ctf_string(child_pool_name, child_pool_name)
+ ctf_integer(uint64_t, child_id, child_id)
+ ctf_string(child_name, child_name)
+ ctf_integer_hex(void*, opts, opts)
+ )
+)
+
+TRACEPOINT_EVENT(librbd, clone3_exit,
+ TP_ARGS(
+ int, retval),
+ TP_FIELDS(
+ ctf_integer(int, retval, retval)
+ )
+)
+
TRACEPOINT_EVENT(librbd, flatten_enter,
TP_ARGS(
void*, imagectx,