summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Durgin <josh.durgin@inktank.com>2013-05-16 15:28:40 -0700
committerJosh Durgin <josh.durgin@inktank.com>2013-05-16 15:37:58 -0700
commit49c04c623466df45003ed2a18445c354c424a078 (patch)
treefa2b87b56fbe0008703ad21f4e1037a1a5c5928b
parent4d7058fe2254f335969f05bef649b1a27d470aa4 (diff)
downloadceph-49c04c623466df45003ed2a18445c354c424a078.tar.gz
librbd: make image creation defaults configurable
Programs using older versions of the image creation functions can't set newer parameters like image format and fancier striping. Setting these options lets them use all the new functionality without being patched and recompiled to use e.g. rbd_create3(). This is particularly useful for things like qemu-img, which does not know how to create format 2 images yet. Refs: #5067 backport: cuttlefish, bobtail Signed-off-by: Josh Durgin <josh.durgin@inktank.com> (cherry picked from commit aacc9adc4e9ca90bbe73ac153cc754a3a5b2c0a1)
-rw-r--r--src/common/config_opts.h23
-rw-r--r--src/librbd/internal.cc25
-rw-r--r--src/librbd/internal.h2
-rw-r--r--src/librbd/librbd.cc10
-rw-r--r--src/test/pybind/test_rbd.py90
5 files changed, 142 insertions, 8 deletions
diff --git a/src/common/config_opts.h b/src/common/config_opts.h
index 4987fa481da..34e2cabd8d0 100644
--- a/src/common/config_opts.h
+++ b/src/common/config_opts.h
@@ -440,6 +440,7 @@ OPTION(journal_queue_max_bytes, OPT_INT, 32 << 20)
OPTION(journal_align_min_size, OPT_INT, 64 << 10) // align data payloads >= this.
OPTION(journal_replay_from, OPT_INT, 0)
OPTION(journal_zero_on_create, OPT_BOOL, false)
+
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
@@ -448,6 +449,28 @@ OPTION(rbd_cache_target_dirty, OPT_LONGLONG, 16<<20) // target dirty limit in by
OPTION(rbd_cache_max_dirty_age, OPT_FLOAT, 1.0) // seconds in cache before writeback starts
OPTION(rbd_cache_block_writes_upfront, OPT_BOOL, false) // whether to block writes to the cache before the aio_write call completes (true), or block before the aio completion is called (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")
diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc
index bdbb39bef6c..9236fe28467 100644
--- a/src/librbd/internal.cc
+++ b/src/librbd/internal.cc
@@ -788,6 +788,15 @@ reprotect_and_return_err:
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)
@@ -820,6 +829,11 @@ reprotect_and_return_err:
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;
@@ -827,8 +841,12 @@ reprotect_and_return_err:
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) {
@@ -940,7 +958,8 @@ reprotect_and_return_err:
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;
diff --git a/src/librbd/internal.h b/src/librbd/internal.h
index f1392f690a2..9f618a4beae 100644
--- a/src/librbd/internal.h
+++ b/src/librbd/internal.h
@@ -81,6 +81,8 @@ namespace librbd {
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 clone(IoCtx& p_ioctx, const char *p_name, const char *p_snap_name,
diff --git a/src/librbd/librbd.cc b/src/librbd/librbd.cc
index 02d8fbf3211..78435ab5dfd 100644
--- a/src/librbd/librbd.cc
+++ b/src/librbd/librbd.cc
@@ -115,7 +115,7 @@ namespace librbd {
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,
@@ -128,7 +128,8 @@ namespace librbd {
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,
@@ -533,7 +534,7 @@ extern "C" int rbd_create(rados_ioctx_t p, const char *name, uint64_t size, int
{
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,
@@ -552,7 +553,8 @@ extern "C" int rbd_create3(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,
diff --git a/src/test/pybind/test_rbd.py b/src/test/pybind/test_rbd.py
index 2d1a78431a9..5dcc3c65f0b 100644
--- a/src/test/pybind/test_rbd.py
+++ b/src/test/pybind/test_rbd.py
@@ -8,7 +8,8 @@ from nose.tools import eq_ as eq, assert_raises
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
@@ -66,6 +67,93 @@ def test_create():
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: