OPTION(rbd_default_order, OPT_INT, 22)
OPTION(rbd_default_stripe_count, OPT_U64, 0) // changing requires stripingv2 feature
OPTION(rbd_default_stripe_unit, OPT_U64, 0) // changing to non-object size requires stripingv2 feature
-OPTION(rbd_default_features, OPT_INT, 61) // only applies to format 2 images
- // +1 for layering, +2 for stripingv2,
- // +4 for exclusive lock, +8 for object map
- // +16 for fast-diff, +32 for deep-flatten,
- // +64 for journaling, +128 for data pool
+SAFE_OPTION(rbd_default_features, OPT_STR, "layering,exclusive-lock,object-map,fast-diff,deep-flatten") // only applies to format 2 images
OPTION(rbd_default_data_pool, OPT_STR, "") // optional default pool for storing image data blocks
OPTION(rbd_default_map_options, OPT_STR, "") // default rbd map -o / --options
#define RBD_FEATURE_JOURNALING (1ULL<<6)
#define RBD_FEATURE_DATA_POOL (1ULL<<7)
+#define RBD_FEATURES_DEFAULT (RBD_FEATURE_LAYERING | \
+ RBD_FEATURE_EXCLUSIVE_LOCK | \
+ RBD_FEATURE_OBJECT_MAP | \
+ RBD_FEATURE_FAST_DIFF | \
+ RBD_FEATURE_DEEP_FLATTEN)
+
+#define RBD_FEATURE_NAME_LAYERING "layering"
+#define RBD_FEATURE_NAME_STRIPINGV2 "striping"
+#define RBD_FEATURE_NAME_EXCLUSIVE_LOCK "exclusive-lock"
+#define RBD_FEATURE_NAME_OBJECT_MAP "object-map"
+#define RBD_FEATURE_NAME_FAST_DIFF "fast-diff"
+#define RBD_FEATURE_NAME_DEEP_FLATTEN "deep-flatten"
+#define RBD_FEATURE_NAME_JOURNALING "journaling"
+#define RBD_FEATURE_NAME_DATA_POOL "data-pool"
+
/// features that make an image inaccessible for read or write by
/// clients that don't understand them
#define RBD_FEATURES_INCOMPATIBLE (RBD_FEATURE_LAYERING | \
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
+
#include "librbd/Utils.h"
#include "include/rbd_types.h"
#include "include/stringify.h"
+#include "include/rbd/features.h"
+#include "common/dout.h"
+
+#define dout_subsys ceph_subsys_rbd
+#undef dout_prefix
+#define dout_prefix *_dout << "librbd: "
namespace librbd {
namespace util {
return id;
}
+uint64_t parse_rbd_default_features(CephContext* cct)
+{
+ int ret = 0;
+ uint64_t value = 0;
+ auto str_val = cct->_conf->get_val<std::string>("rbd_default_features");
+ try {
+ value = boost::lexical_cast<decltype(value)>(str_val);
+ } catch (const boost::bad_lexical_cast& ) {
+ map<std::string, int> conf_vals = {{RBD_FEATURE_NAME_LAYERING, RBD_FEATURE_LAYERING},
+ {RBD_FEATURE_NAME_STRIPINGV2, RBD_FEATURE_STRIPINGV2},
+ {RBD_FEATURE_NAME_EXCLUSIVE_LOCK, RBD_FEATURE_EXCLUSIVE_LOCK},
+ {RBD_FEATURE_NAME_OBJECT_MAP, RBD_FEATURE_OBJECT_MAP},
+ {RBD_FEATURE_NAME_FAST_DIFF, RBD_FEATURE_FAST_DIFF},
+ {RBD_FEATURE_NAME_DEEP_FLATTEN, RBD_FEATURE_DEEP_FLATTEN},
+ {RBD_FEATURE_NAME_JOURNALING, RBD_FEATURE_JOURNALING},
+ {RBD_FEATURE_NAME_DATA_POOL, RBD_FEATURE_DATA_POOL},
+ };
+ std::vector<std::string> strs;
+ boost::split(strs, str_val, boost::is_any_of(","));
+ for (auto feature: strs) {
+ boost::trim(feature);
+ if (conf_vals.find(feature) != conf_vals.end()) {
+ value += conf_vals[feature];
+ } else {
+ ret = -EINVAL;
+ ldout(cct, 1) << "Warning: unknown rbd feature " << feature << dendl;
+ }
+ }
+ if (value == 0 && ret == -EINVAL)
+ value = RBD_FEATURES_DEFAULT;
+ }
+ return value;
+}
+
} // namespace util
+
} // namespace librbd
Context *m_on_finish = nullptr;
};
+uint64_t parse_rbd_default_features(CephContext* cct);
+
} // namespace util
+
} // namespace librbd
#endif // CEPH_LIBRBD_UTILS_H
m_objmap_name = ObjectMap::object_map_name(m_image_id, CEPH_NOSNAP);
if (image_options.get(RBD_IMAGE_OPTION_FEATURES, &m_features) != 0) {
- m_features = m_cct->_conf->rbd_default_features;
+ m_features = util::parse_rbd_default_features(m_cct);
}
uint64_t features_clear = 0;
{
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;
+ uint64_t features = old_format ? 0 : librbd::util::parse_rbd_default_features(cct);
return create(io_ctx, imgname, size, old_format, features, order, 0, 0);
}
--image-feature arg image features
[layering(+), striping, exclusive-lock(+*),
object-map(+*), fast-diff(+*), deep-flatten(+-),
- journaling(*)]
+ journaling(*), data-pool]
--image-shared shared image
--stripe-unit arg stripe unit
--stripe-count arg stripe count
--image-feature arg image features
[layering(+), striping, exclusive-lock(+*),
object-map(+*), fast-diff(+*), deep-flatten(+-),
- journaling(*)]
+ journaling(*), data-pool]
--image-shared shared image
--stripe-unit arg stripe unit
--stripe-count arg stripe count
--image-feature arg image features
[layering(+), striping, exclusive-lock(+*),
object-map(+*), fast-diff(+*), deep-flatten(+-),
- journaling(*)]
+ journaling(*), data-pool]
--image-shared shared image
--stripe-unit arg stripe unit
--stripe-count arg stripe count
(example: [<pool-name>/]<image-name>)
<features> image features
[layering, striping, exclusive-lock, object-map,
- fast-diff, deep-flatten, journaling]
+ fast-diff, deep-flatten, journaling, data-pool]
Optional arguments
-p [ --pool ] arg pool name
(example: [<pool-name>/]<image-name>)
<features> image features
[layering, striping, exclusive-lock, object-map,
- fast-diff, deep-flatten, journaling]
+ fast-diff, deep-flatten, journaling, data-pool]
Optional arguments
-p [ --pool ] arg pool name
--image-feature arg image features
[layering(+), striping, exclusive-lock(+*),
object-map(+*), fast-diff(+*), deep-flatten(+-),
- journaling(*)]
+ journaling(*), data-pool]
--image-shared shared image
--stripe-unit arg stripe unit
--stripe-count arg stripe count
m_remote_ioctx));
m_image_name = get_temp_image_name();
- uint64_t features = g_ceph_context->_conf->rbd_default_features;
+ uint64_t features = librbd::util::parse_rbd_default_features(g_ceph_context);
features |= RBD_FEATURE_EXCLUSIVE_LOCK | RBD_FEATURE_JOURNALING;
int order = 0;
EXPECT_EQ(0, librbd::create(m_remote_ioctx, m_image_name.c_str(), 1 << 22,
void create_image(const string &pool_name, bool mirrored=true,
string *image_name=nullptr) {
- uint64_t features = g_ceph_context->_conf->rbd_default_features;
+ uint64_t features = librbd::util::parse_rbd_default_features(g_ceph_context);
string name = "image" + stringify(++m_image_number);
if (mirrored) {
features |= RBD_FEATURE_EXCLUSIVE_LOCK | RBD_FEATURE_JOURNALING;
ictx->state->close();
}
- uint64_t features = g_ceph_context->_conf->rbd_default_features;
+ uint64_t features = librbd::util::parse_rbd_default_features(g_ceph_context);
string name = "clone" + stringify(++m_image_number);
if (mirrored) {
features |= RBD_FEATURE_EXCLUSIVE_LOCK | RBD_FEATURE_JOURNALING;
#include "tools/rbd/ArgumentTypes.h"
#include "tools/rbd/Shell.h"
+#include "tools/rbd/Utils.h"
#include "include/rbd/features.h"
#include "common/config.h"
#include "common/strtol.h"
namespace po = boost::program_options;
const std::map<uint64_t, std::string> ImageFeatures::FEATURE_MAPPING = {
- {RBD_FEATURE_LAYERING, "layering"},
- {RBD_FEATURE_STRIPINGV2, "striping"},
- {RBD_FEATURE_EXCLUSIVE_LOCK, "exclusive-lock"},
- {RBD_FEATURE_OBJECT_MAP, "object-map"},
- {RBD_FEATURE_FAST_DIFF, "fast-diff"},
- {RBD_FEATURE_DEEP_FLATTEN, "deep-flatten"},
- {RBD_FEATURE_JOURNALING, "journaling"}};
+ {RBD_FEATURE_LAYERING, RBD_FEATURE_NAME_LAYERING},
+ {RBD_FEATURE_STRIPINGV2, RBD_FEATURE_NAME_STRIPINGV2},
+ {RBD_FEATURE_EXCLUSIVE_LOCK, RBD_FEATURE_NAME_EXCLUSIVE_LOCK},
+ {RBD_FEATURE_OBJECT_MAP, RBD_FEATURE_NAME_OBJECT_MAP},
+ {RBD_FEATURE_FAST_DIFF, RBD_FEATURE_NAME_FAST_DIFF},
+ {RBD_FEATURE_DEEP_FLATTEN, RBD_FEATURE_NAME_DEEP_FLATTEN},
+ {RBD_FEATURE_JOURNALING, RBD_FEATURE_NAME_JOURNALING},
+ {RBD_FEATURE_DATA_POOL, RBD_FEATURE_NAME_DATA_POOL},
+};
Format::Formatter Format::create_formatter(bool pretty) const {
if (value == "json") {
std::string suffix;
if (append_suffix) {
- if ((pair.first & g_conf->rbd_default_features) != 0) {
+ if ((pair.first & rbd::utils::parse_rbd_default_features(g_ceph_context)) != 0) {
suffix += "+";
}
if ((pair.first & RBD_FEATURES_MUTABLE) != 0) {
#include "global/global_context.h"
#include <iostream>
#include <boost/regex.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
namespace rbd {
namespace utils {
if (vm.count(at::IMAGE_FEATURES)) {
features = vm[at::IMAGE_FEATURES].as<uint64_t>();
features_specified = true;
+ } else {
+ features = parse_rbd_default_features(g_ceph_context);
}
if (vm.count(at::IMAGE_STRIPE_UNIT)) {
return buf;
}
+// FIXME (asheplyakov): use function from librbd/Utils.cc
+
+uint64_t parse_rbd_default_features(CephContext* cct)
+{
+ int ret = 0;
+ uint64_t value = 0;
+ auto features = cct->_conf->get_val<std::string>("rbd_default_features");
+ try {
+ value = boost::lexical_cast<decltype(value)>(features);
+ } catch (const boost::bad_lexical_cast& ) {
+ map<std::string, int> conf_vals = {{RBD_FEATURE_NAME_LAYERING, RBD_FEATURE_LAYERING},
+ {RBD_FEATURE_NAME_STRIPINGV2, RBD_FEATURE_STRIPINGV2},
+ {RBD_FEATURE_NAME_EXCLUSIVE_LOCK, RBD_FEATURE_EXCLUSIVE_LOCK},
+ {RBD_FEATURE_NAME_OBJECT_MAP, RBD_FEATURE_OBJECT_MAP},
+ {RBD_FEATURE_NAME_FAST_DIFF, RBD_FEATURE_FAST_DIFF},
+ {RBD_FEATURE_NAME_DEEP_FLATTEN, RBD_FEATURE_DEEP_FLATTEN},
+ {RBD_FEATURE_NAME_JOURNALING, RBD_FEATURE_JOURNALING},
+ {RBD_FEATURE_NAME_DATA_POOL, RBD_FEATURE_DATA_POOL},
+ };
+ std::vector<std::string> strs;
+ boost::split(strs, features, boost::is_any_of(","));
+ for (auto feature: strs) {
+ boost::trim(feature);
+ if (conf_vals.find(feature) != conf_vals.end()) {
+ value += conf_vals[feature];
+ } else {
+ ret = -EINVAL;
+ std::cerr << "Warning: unknown rbd feature " << feature << std::endl;
+ }
+ }
+ if (value == 0 && ret == -EINVAL)
+ value = RBD_FEATURES_DEFAULT;
+ }
+ return value;
+}
+
} // namespace utils
} // namespace rbd
std::string timestr(time_t t);
+// duplicate here to not include librbd_internal lib
+uint64_t parse_rbd_default_features(CephContext* cct);
+
} // namespace utils
} // namespace rbd