From: Mykola Golub Date: Fri, 23 Oct 2015 09:38:08 +0000 (+0300) Subject: librbd: API: options on image create X-Git-Tag: v10.0.1~81^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=c3be44ed8f9d99d7257156f2e0bf7ef6ea1b5761;p=ceph.git librbd: API: options on image create Pass options as key/value configuration pairs on image create instead of expanding rbd_create/rbd_clone/rbd_copy for every possible configuration override. Fixes: #13504 Signed-off-by: Mykola Golub --- diff --git a/src/include/rbd/librbd.h b/src/include/rbd/librbd.h index 2eb3aa5e9542..ba64219d3be7 100644 --- a/src/include/rbd/librbd.h +++ b/src/include/rbd/librbd.h @@ -52,6 +52,7 @@ extern "C" { 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); @@ -76,6 +77,30 @@ typedef struct { 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, @@ -102,6 +127,8 @@ CEPH_RBD_API int rbd_create2(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); @@ -109,6 +136,9 @@ CEPH_RBD_API int rbd_clone2(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, 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, @@ -172,11 +202,18 @@ CEPH_RBD_API int rbd_rebuild_object_map(rbd_image_t image, 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, diff --git a/src/include/rbd/librbd.hpp b/src/include/rbd/librbd.hpp index 0c41b8e184a6..a64ffa6b58ca 100644 --- a/src/include/rbd/librbd.hpp +++ b/src/include/rbd/librbd.hpp @@ -29,6 +29,7 @@ namespace librbd { 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); @@ -86,12 +87,16 @@ public: 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); @@ -102,6 +107,27 @@ private: 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: @@ -130,9 +156,12 @@ 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; diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index 5ef44e1adb35..b61018d391d8 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -33,6 +33,7 @@ #include #include +#include #include "include/assert.h" #define dout_subsys ceph_subsys_rbd @@ -442,6 +443,156 @@ int invoke_async_request(ImageCtx *ictx, const std::string& request_type, return io_ctx.tmap_update(RBD_DIRECTORY, cmdbl); } + typedef boost::variant image_option_value_t; + typedef std::map image_options_t; + typedef std::shared_ptr image_options_ref; + + enum image_option_type_t { + STR, + UINT64, + }; + + const std::map 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(opts_); + } + + void image_options_create_ref(rbd_image_options_t* opts, + rbd_image_options_t orig) + { + image_options_ref* orig_ = static_cast(orig); + image_options_ref* opts_ = new image_options_ref(*orig_); + + *opts = static_cast(opts_); + } + + void image_options_destroy(rbd_image_options_t opts) + { + image_options_ref* opts_ = static_cast(opts); + + delete opts_; + } + + int image_options_set(rbd_image_options_t opts, int optname, + const std::string& optval) + { + image_options_ref* opts_ = static_cast(opts); + + std::map::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(opts); + + std::map::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(opts); + + std::map::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(j->second); + return 0; + } + + int image_options_get(rbd_image_options_t opts, int optname, uint64_t* optval) + { + image_options_ref* opts_ = static_cast(opts); + + std::map::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(j->second); + return 0; + } + + int image_options_unset(rbd_image_options_t opts, int optname) + { + image_options_ref* opts_ = static_cast(opts); + + std::map::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(opts); + + (*opts_)->clear(); + } + + bool image_options_is_empty(rbd_image_options_t opts) + { + image_options_ref* opts_ = static_cast(opts); + + return (*opts_)->empty(); + } + void rollback_object(ImageCtx *ictx, uint64_t snap_id, const string& oid, SimpleThrottle& throttle) { @@ -1229,15 +1380,59 @@ reprotect_and_return_err: 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; @@ -1254,12 +1449,12 @@ reprotect_and_return_err: 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; } @@ -1275,7 +1470,7 @@ reprotect_and_return_err: } // 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; } @@ -1289,21 +1484,43 @@ reprotect_and_return_err: 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(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, @@ -2614,25 +2831,40 @@ reprotect_and_return_err: } 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(order)); ImageCtx *dest = new librbd::ImageCtx(destname, "", NULL, dest_md_ctx, false); diff --git a/src/librbd/internal.h b/src/librbd/internal.h index 4245b43f8108..3197c8e5d29d 100644 --- a/src/librbd/internal.h +++ b/src/librbd/internal.h @@ -77,6 +77,21 @@ namespace librbd { 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& names); int list_children(ImageCtx *ictx, @@ -86,10 +101,14 @@ namespace librbd { 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); @@ -127,7 +146,7 @@ namespace librbd { 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); diff --git a/src/librbd/librbd.cc b/src/librbd/librbd.cc index 7f7ad40575fb..d3c4b02552cc 100644 --- a/src/librbd/librbd.cc +++ b/src/librbd/librbd.cc @@ -304,6 +304,16 @@ namespace librbd { return r; } + int RBD::create4(IoCtx& io_ctx, const char *name, uint64_t size, + ImageOptions& opts) + { + TracepointProvider::initialize(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) @@ -328,6 +338,17 @@ namespace librbd { 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(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(get_cct(io_ctx)); @@ -404,6 +425,60 @@ namespace librbd { 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 */ @@ -560,8 +635,9 @@ namespace librbd { { 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; } @@ -577,12 +653,23 @@ namespace librbd { 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; } @@ -597,6 +684,17 @@ namespace librbd { 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; @@ -1053,6 +1151,69 @@ extern "C" void rbd_version(int *major, int *minor, int *extra) *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) { @@ -1135,6 +1296,19 @@ extern "C" int rbd_create3(rados_ioctx_t p, const char *name, 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(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) @@ -1166,6 +1340,21 @@ extern "C" int rbd_clone2(rados_ioctx_t p_ioctx, const char *p_name, 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(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; @@ -1198,8 +1387,9 @@ extern "C" int rbd_copy(rbd_image_t image, rados_ioctx_t dest_p, 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; } @@ -1215,6 +1405,20 @@ extern "C" int rbd_copy2(rbd_image_t srcp, rbd_image_t destp) 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) @@ -1223,8 +1427,9 @@ extern "C" int rbd_copy_with_progress(rbd_image_t image, rados_ioctx_t dest_p, 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; } @@ -1241,6 +1446,22 @@ extern "C" int rbd_copy_with_progress2(rbd_image_t srcp, rbd_image_t destp, 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; diff --git a/src/pybind/rbd.py b/src/pybind/rbd.py index 9b8664ca14c8..8ff074a9ff89 100644 --- a/src/pybind/rbd.py +++ b/src/pybind/rbd.py @@ -65,6 +65,12 @@ RBD_FEATURES_SINGLE_CLIENT = (RBD_FEATURE_EXCLUSIVE_LOCK | 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 @@ -257,11 +263,37 @@ class RBD(object): 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), @@ -277,7 +309,7 @@ class RBD(object): 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. @@ -295,6 +327,10 @@ class RBD(object): :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` @@ -308,11 +344,39 @@ class RBD(object): 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') @@ -632,7 +696,8 @@ class Image(object): 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. @@ -640,11 +705,51 @@ class Image(object): :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)) diff --git a/src/tracing/librbd.tp b/src/tracing/librbd.tp index 542084918e2f..f6e1cb1b0bb2 100644 --- a/src/tracing/librbd.tp +++ b/src/tracing/librbd.tp @@ -305,6 +305,29 @@ TRACEPOINT_EVENT(librbd, create3_exit, ) ) +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, @@ -671,6 +694,36 @@ TRACEPOINT_EVENT(librbd, copy2_exit, ) ) +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, @@ -874,6 +927,36 @@ TRACEPOINT_EVENT(librbd, clone2_exit, ) ) +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,