OPTION(journal_replay_from, OPT_INT, 0)
OPTION(journal_zero_on_create, OPT_BOOL, false)
OPTION(journal_ignore_corruption, OPT_BOOL, false) // assume journal is not corrupt
+
OPTION(rbd_cache, OPT_BOOL, false) // whether to enable caching (writeback unless rbd_cache_max_dirty is 0)
OPTION(rbd_cache_writethrough_until_flush, OPT_BOOL, false) // whether to make writeback caching writethrough until flush is called, to be sure the user of librbd will send flushs so that writeback is safe
OPTION(rbd_cache_size, OPT_LONGLONG, 32<<20) // cache size in bytes
OPTION(rbd_balance_snap_reads, OPT_BOOL, false)
OPTION(rbd_localize_snap_reads, OPT_BOOL, false)
+/*
+ * The following options change the behavior for librbd's image creation methods that
+ * don't require all of the parameters. These are provided so that older programs
+ * can take advantage of newer features without being rewritten to use new versions
+ * of the image creation functions.
+ *
+ * rbd_create()/RBD::create() are affected by all of these options.
+ *
+ * rbd_create2()/RBD::create2() and rbd_clone()/RBD::clone() are affected by:
+ * - rbd_default_order
+ * - rbd_default_stripe_count
+ * - rbd_default_stripe_size
+ *
+ * rbd_create3()/RBD::create3() and rbd_clone2/RBD::clone2() are only
+ * affected by rbd_default_order.
+ */
+OPTION(rbd_default_format, OPT_INT, 1)
+OPTION(rbd_default_order, OPT_INT, 22)
+OPTION(rbd_default_stripe_count, OPT_U64, 1) // changing requires stripingv2 feature
+OPTION(rbd_default_stripe_unit, OPT_U64, 4194304) // changing to non-object size requires stripingv2 feature
+OPTION(rbd_default_features, OPT_INT, 3) // 1 for layering, 3 for layering+stripingv2. only applies to format 2 images
+
OPTION(nss_db_path, OPT_STR, "") // path to nss db
OPTION(rgw_data, OPT_STR, "/var/lib/ceph/radosgw/$cluster-$id")
return r;
}
+ 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);
+ }
+
int create(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)
if (!order)
return -EINVAL;
+ if (!*order)
+ *order = cct->_conf->rbd_default_order;
+ if (!*order)
+ *order = RBD_DEFAULT_OBJ_ORDER;
+
if (*order && (*order > 64 || *order < 12)) {
lderr(cct) << "order must be in the range [12, 64]" << dendl;
return -EDOM;
uint64_t bid = rbd_assign_bid(io_ctx);
- if (!*order)
- *order = RBD_DEFAULT_OBJ_ORDER;
+ // if striping is enabled, use possibly custom defaults
+ if (!old_format && (features & RBD_FEATURE_STRIPINGV2) &&
+ !stripe_unit && !stripe_count) {
+ stripe_unit = cct->_conf->rbd_default_stripe_unit;
+ stripe_count = cct->_conf->rbd_default_stripe_count;
+ }
// normalize for default striping
if (stripe_unit == (1ull << *order) && stripe_count == 1) {
if (!order)
order = p_imctx->order;
- r = create(c_ioctx, c_name, size, false, features, &order, stripe_unit, stripe_count);
+ r = create(c_ioctx, c_name, size, false, features, &order,
+ stripe_unit, stripe_count);
if (r < 0) {
lderr(cct) << "error creating child: " << cpp_strerror(r) << dendl;
goto err_close_parent;
int list(librados::IoCtx& io_ctx, std::vector<std::string>& names);
int list_children(ImageCtx *ictx,
std::set<pair<std::string, std::string> > & names);
+ int create(librados::IoCtx& io_ctx, const char *imgname, uint64_t size,
+ int *order);
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 RBD::create(IoCtx& io_ctx, const char *name, uint64_t size, int *order)
{
- return librbd::create(io_ctx, name, size, true, 0, order, 0, 0);
+ return librbd::create(io_ctx, name, size, order);
}
int RBD::create2(IoCtx& io_ctx, const char *name, uint64_t size,
uint64_t features, int *order, uint64_t stripe_unit,
uint64_t stripe_count)
{
- return librbd::create(io_ctx, name, size, false, features, order, stripe_unit, stripe_count);
+ return librbd::create(io_ctx, name, size, false, features, order,
+ stripe_unit, stripe_count);
}
int RBD::clone(IoCtx& p_ioctx, const char *p_name, const char *p_snap_name,
{
librados::IoCtx io_ctx;
librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
- return librbd::create(io_ctx, name, size, true, 0, order, 0, 0);
+ return librbd::create(io_ctx, name, size, order);
}
extern "C" int rbd_create2(rados_ioctx_t p, const char *name,
{
librados::IoCtx io_ctx;
librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
- return librbd::create(io_ctx, name, size, false, features, order, stripe_unit, stripe_count);
+ return librbd::create(io_ctx, name, size, false, features, order,
+ stripe_unit, stripe_count);
}
extern "C" int rbd_clone(rados_ioctx_t p_ioctx, const char *p_name,
from rados import Rados
from rbd import (RBD, Image, ImageNotFound, InvalidArgument, ImageExists,
ImageBusy, ImageHasSnapshots, ReadOnlyImage,
- FunctionNotSupported, RBD_FEATURE_LAYERING)
+ FunctionNotSupported, ArgumentOutOfRange,
+ RBD_FEATURE_LAYERING, RBD_FEATURE_STRIPINGV2)
rados = None
create_image()
remove_image()
+def check_default_params(format, order=None, features=None, stripe_count=None,
+ stripe_unit=None, exception=None):
+ global rados
+ global ioctx
+ orig_vals = {}
+ for k in ['rbd_default_format', 'rbd_default_order', 'rbd_default_features',
+ 'rbd_default_stripe_count', 'rbd_default_stripe_unit']:
+ orig_vals[k] = rados.conf_get(k)
+ try:
+ rados.conf_set('rbd_default_format', str(format))
+ if order is not None:
+ rados.conf_set('rbd_default_order', str(order or 0))
+ if features is not None:
+ rados.conf_set('rbd_default_features', str(features or 0))
+ if stripe_count is not None:
+ rados.conf_set('rbd_default_stripe_count', str(stripe_count or 0))
+ if stripe_unit is not None:
+ rados.conf_set('rbd_default_stripe_unit', str(stripe_unit or 0))
+ if exception is None:
+ RBD().create(ioctx, IMG_NAME, IMG_SIZE)
+ try:
+ with Image(ioctx, IMG_NAME) as image:
+ eq(format == 1, image.old_format())
+
+ expected_order = order
+ if not order:
+ expected_order = 22
+ actual_order = image.stat()['order']
+ eq(expected_order, actual_order)
+
+ expected_features = features
+ if expected_features is None or format == 1:
+ expected_features = 0 if format == 1 else 3
+ eq(expected_features, image.features())
+
+ expected_stripe_count = stripe_count
+ if not expected_stripe_count or format == 1 or \
+ features & RBD_FEATURE_STRIPINGV2 == 0:
+ expected_stripe_count = 1
+ eq(expected_stripe_count, image.stripe_count())
+
+ expected_stripe_unit = stripe_unit
+ if not expected_stripe_unit or format == 1 or \
+ features & RBD_FEATURE_STRIPINGV2 == 0:
+ expected_stripe_unit = 1 << actual_order
+ eq(expected_stripe_unit, image.stripe_unit())
+ finally:
+ RBD().remove(ioctx, IMG_NAME)
+ else:
+ assert_raises(exception, RBD().create, ioctx, IMG_NAME, IMG_SIZE)
+ finally:
+ for k, v in orig_vals.iteritems():
+ rados.conf_set(k, v)
+
+def test_create_defaults():
+ # basic format 1 and 2
+ check_default_params(1)
+ check_default_params(2)
+ # default order still works
+ check_default_params(1, 0)
+ check_default_params(2, 0)
+ # invalid order
+ check_default_params(1, 11, exception=ArgumentOutOfRange)
+ check_default_params(2, 11, exception=ArgumentOutOfRange)
+ check_default_params(1, 65, exception=ArgumentOutOfRange)
+ check_default_params(2, 65, exception=ArgumentOutOfRange)
+ # striping and features are ignored for format 1
+ check_default_params(1, 20, 0, 1, 1)
+ check_default_params(1, 20, 3, 1, 1)
+ check_default_params(1, 20, 0, 0, 0)
+ # striping is ignored if stripingv2 is not set
+ check_default_params(2, 20, 0, 1, 1 << 20)
+ check_default_params(2, 20, RBD_FEATURE_LAYERING, 1, 1 << 20)
+ check_default_params(2, 20, 0, 0, 0)
+ # striping with stripingv2 is fine
+ check_default_params(2, 20, RBD_FEATURE_STRIPINGV2, 1, 1 << 16)
+ check_default_params(2, 20, RBD_FEATURE_STRIPINGV2, 10, 1 << 20)
+ check_default_params(2, 20, RBD_FEATURE_STRIPINGV2, 10, 1 << 16)
+ # make sure invalid combinations of stripe unit and order are still invalid
+ check_default_params(2, 20, RBD_FEATURE_STRIPINGV2, exception=InvalidArgument)
+ check_default_params(2, 22, RBD_FEATURE_STRIPINGV2, 10, 1 << 50, exception=InvalidArgument)
+ check_default_params(2, 22, RBD_FEATURE_STRIPINGV2, 10, 100, exception=InvalidArgument)
+ check_default_params(2, 22, RBD_FEATURE_STRIPINGV2, 0, 1, exception=InvalidArgument)
+ check_default_params(2, 22, RBD_FEATURE_STRIPINGV2, 1, 0, exception=InvalidArgument)
+ # 0 stripe unit and count are still ignored
+ check_default_params(2, 22, RBD_FEATURE_STRIPINGV2, 0, 0)
+
def test_context_manager():
with Rados(conffile='') as cluster:
with cluster.open_ioctx('rbd') as ioctx: