uint64_t stripe_count, uint8_t journal_order,
uint8_t journal_splay_width, const std::string &journal_pool,
const std::string &non_primary_global_image_id,
- const std::string &primary_mirror_uuid)
+ const std::string &primary_mirror_uuid,
+ bool negotiate_features)
{
ostringstream bid_ss;
uint32_t extra;
goto err_remove_id;
}
+ if (negotiate_features) {
+ uint64_t all_features = 0;
+ r = cls_client::get_all_features(&io_ctx, RBD_DIRECTORY, &all_features);
+ if (r < 0) {
+ ldout(cct, 10) << "error retrieving server supported features set: "
+ << cpp_strerror(r) << dendl;
+ } else if ((features & all_features) != features) {
+ features &= all_features;
+ ldout(cct, 10) << "limiting default features set to server supported: "
+ << features << dendl;
+ }
+ }
+
oss << RBD_DATA_PREFIX << id;
header_oid = util::header_name(id);
r = cls_client::create_image(&io_ctx, header_oid, size, order,
int create(librados::IoCtx& io_ctx, const char *imgname, uint64_t size,
int *order)
{
- CephContext *cct = (CephContext *)io_ctx.cct();
- bool old_format = cct->_conf->rbd_default_format == 1;
- uint64_t features = old_format ? 0 : cct->_conf->rbd_default_features;
- return create(io_ctx, imgname, size, old_format, features, order, 0, 0);
+ uint64_t order_ = *order;
+ ImageOptions opts;
+
+ int r = opts.set(RBD_IMAGE_OPTION_ORDER, order_);
+ 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,
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 features = 0;
+ bool negotiate_features = false;
+ if (!old_format && opts.get(RBD_IMAGE_OPTION_FEATURES, &features) != 0) {
+ features = cct->_conf->rbd_default_features;
+ negotiate_features = true;
}
+
uint64_t stripe_unit = 0;
uint64_t stripe_count = 0;
opts.get(RBD_IMAGE_OPTION_STRIPE_UNIT, &stripe_unit);
r = create_v2(io_ctx, imgname, bid, size, order, features, stripe_unit,
stripe_count, journal_order, journal_splay_width,
journal_pool, non_primary_global_image_id,
- primary_mirror_uuid);
+ primary_mirror_uuid, negotiate_features);
}
int r1 = opts.set(RBD_IMAGE_OPTION_ORDER, order);
return -ENOSYS;
}
use_p_features = false;
+ } else {
+ // inherit default features -- ensure layering is enabled
+ if ((cct->_conf->rbd_default_features & RBD_FEATURE_LAYERING) !=
+ RBD_FEATURE_LAYERING) {
+ lderr(cct) << "clone image must support layering" << dendl;
+ return -EINVAL;
+ }
}
// make sure child doesn't already exist, in either format
uint8_t journal_splay_width,
const std::string &journal_pool,
const std::string &non_primary_global_image_id,
- const std::string &primary_mirror_uuid);
+ const std::string &primary_mirror_uuid,
+ bool negotiate_features);
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,
order = g_conf->rbd_default_order;
}
+ bool features_set = false;
if (vm.count(at::IMAGE_FEATURES)) {
features = vm[at::IMAGE_FEATURES].as<uint64_t>();
features_specified = true;
+ features_set = true;
} else {
features = g_conf->rbd_default_features;
}
return -EINVAL;
}
features |= RBD_FEATURE_STRIPINGV2;
- } else {
- if (features_specified && ((features & RBD_FEATURE_STRIPINGV2) != 0)) {
+ features_set = true;
+ } else if ((features & RBD_FEATURE_STRIPINGV2) != 0) {
+ if (features_specified) {
std::cerr << "must specify both of stripe-unit and stripe-count when specify striping features" << std::endl;
return -EINVAL;
}
+
features &= ~RBD_FEATURE_STRIPINGV2;
+ features_set = true;
}
if (vm.count(at::IMAGE_SHARED) && vm[at::IMAGE_SHARED].as<bool>()) {
features &= ~RBD_FEATURES_SINGLE_CLIENT;
+ features_set = true;
}
if (get_format) {
}
opts->set(RBD_IMAGE_OPTION_ORDER, order);
- opts->set(RBD_IMAGE_OPTION_FEATURES, features);
+ if (features_set) {
+ opts->set(RBD_IMAGE_OPTION_FEATURES, features);
+ }
opts->set(RBD_IMAGE_OPTION_STRIPE_UNIT, stripe_unit);
opts->set(RBD_IMAGE_OPTION_STRIPE_COUNT, stripe_count);
namespace at = argument_types;
namespace po = boost::program_options;
-int do_clone(librbd::RBD &rbd, librados::IoCtx &p_ioctx,
- const char *p_name, const char *p_snapname,
- librados::IoCtx &c_ioctx, const char *c_name,
- librbd::ImageOptions& opts) {
- uint64_t features;
- int r = opts.get(RBD_IMAGE_OPTION_FEATURES, &features);
- assert(r == 0);
-
- if ((features & RBD_FEATURE_LAYERING) != RBD_FEATURE_LAYERING) {
- return -EINVAL;
- }
-
- return rbd.clone3(p_ioctx, p_name, p_snapname, c_ioctx, c_name, opts);
-}
-
void get_arguments(po::options_description *positional,
po::options_description *options) {
at::add_snap_spec_options(positional, options, at::ARGUMENT_MODIFIER_SOURCE);
return r;
}
+ uint64_t features;
+ r = opts.get(RBD_IMAGE_OPTION_FEATURES, &features);
+ if (r != -ENOENT) {
+ if ((features & RBD_FEATURE_LAYERING) != RBD_FEATURE_LAYERING) {
+ std::cerr << "rbd: clone image must support layering" << std::endl;
+ return -EINVAL;
+ }
+ }
+
librbd::RBD rbd;
- r = do_clone(rbd, io_ctx, image_name.c_str(), snap_name.c_str(), dst_io_ctx,
- dst_image_name.c_str(), opts);
+ r = rbd.clone3(io_ctx, image_name.c_str(), snap_name.c_str(), dst_io_ctx,
+ dst_image_name.c_str(), opts);
if (r < 0) {
std::cerr << "rbd: clone error: " << cpp_strerror(r) << std::endl;
return r;
return librbd::create_v2(io_ctx, imgname, bid, size, order, features,
stripe_unit, stripe_count, journal_order,
journal_splay_width, journal_pool,
- non_primary_global_image_id, primary_mirror_uuid);
+ non_primary_global_image_id, primary_mirror_uuid,
+ false);
}
template <typename I>