return -EINVAL;
}
- if ((mask & RBD_FEATURES_MUTABLE) != mask) {
- CLS_ERR("Attempting to set immutable feature: %" PRIu64,
- mask & ~RBD_FEATURES_MUTABLE);
- return -EINVAL;
- }
-
// check that features exists to make sure this is a header object
// that was created correctly
uint64_t orig_features = 0;
return r;
}
+ uint64_t changed_features = (orig_features ^ features) & mask;
+ uint64_t enabled_features = changed_features & features;
+ if ((enabled_features & RBD_FEATURES_MUTABLE) != enabled_features) {
+ CLS_ERR("Attempting to enable immutable feature: %" PRIu64,
+ enabled_features & ~RBD_FEATURES_MUTABLE);
+ return -EINVAL;
+ }
+
+ uint64_t disabled_features = changed_features & orig_features;
+ uint64_t disable_mask = (RBD_FEATURES_MUTABLE | RBD_FEATURES_DISABLE_ONLY);
+ if ((disabled_features & disable_mask) != disabled_features) {
+ CLS_ERR("Attempting to disable immutable feature: %" PRIu64,
+ enabled_features & ~disable_mask);
+ return -EINVAL;
+ }
+
features = (orig_features & ~mask) | (features & mask);
CLS_LOG(10, "set_features features=%" PRIu64 " orig_features=%" PRIu64,
features, orig_features);
RBD_FEATURE_FAST_DIFF | \
RBD_FEATURE_JOURNALING)
+/// features that may be dynamically disabled
+#define RBD_FEATURES_DISABLE_ONLY (RBD_FEATURE_DEEP_FLATTEN)
+
/// features that only work when used with a single client
/// using the image for writes
#define RBD_FEATURES_SINGLE_CLIENT (RBD_FEATURE_EXCLUSIVE_LOCK | \
return r;
}
- if ((features & RBD_FEATURES_MUTABLE) != features) {
+ uint64_t disable_mask = (RBD_FEATURES_MUTABLE |
+ RBD_FEATURES_DISABLE_ONLY);
+ if ((enabled && (features & RBD_FEATURES_MUTABLE) != features) ||
+ (!enabled && (features & disable_mask) != features)) {
lderr(cct) << "cannot update immutable features" << dendl;
return -EINVAL;
} else if (features == 0) {
lderr(cct) << "cannot disable exclusive lock" << dendl;
return -EINVAL;
}
- features_mask |= RBD_FEATURE_OBJECT_MAP;
+ features_mask |= (RBD_FEATURE_OBJECT_MAP |
+ RBD_FEATURE_JOURNALING);
}
if ((features & RBD_FEATURE_OBJECT_MAP) != 0) {
if ((new_features & RBD_FEATURE_FAST_DIFF) != 0) {
--order arg object order [12 <= order <= 25]
--object-size arg object size in B/K/M [4K <= object size <= 32M]
--image-feature arg image features
- [layering(+), striping(+), exclusive-lock(*),
- object-map(*), fast-diff(*), deep-flatten,
+ [layering(+), striping, exclusive-lock(+*),
+ object-map(+*), fast-diff(+*), deep-flatten(+-),
journaling(*)]
--image-shared shared image
--stripe-unit arg stripe unit
Image Features:
(*) supports enabling/disabling on existing images
+ (-) supports disabling-only on existing images
(+) enabled by default for new images if features not specified
rbd help copy
--order arg object order [12 <= order <= 25]
--object-size arg object size in B/K/M [4K <= object size <= 32M]
--image-feature arg image features
- [layering(+), striping(+), exclusive-lock(*),
- object-map(*), fast-diff(*), deep-flatten,
+ [layering(+), striping, exclusive-lock(+*),
+ object-map(+*), fast-diff(+*), deep-flatten(+-),
journaling(*)]
--image-shared shared image
--stripe-unit arg stripe unit
Image Features:
(*) supports enabling/disabling on existing images
+ (-) supports disabling-only on existing images
(+) enabled by default for new images if features not specified
rbd help create
--order arg object order [12 <= order <= 25]
--object-size arg object size in B/K/M [4K <= object size <= 32M]
--image-feature arg image features
- [layering(+), striping(+), exclusive-lock(*),
- object-map(*), fast-diff(*), deep-flatten,
+ [layering(+), striping, exclusive-lock(+*),
+ object-map(+*), fast-diff(+*), deep-flatten(+-),
journaling(*)]
--image-shared shared image
--stripe-unit arg stripe unit
Image Features:
(*) supports enabling/disabling on existing images
+ (-) supports disabling-only on existing images
(+) enabled by default for new images if features not specified
rbd help diff
--order arg object order [12 <= order <= 25]
--object-size arg object size in B/K/M [4K <= object size <= 32M]
--image-feature arg image features
- [layering(+), striping(+), exclusive-lock(*),
- object-map(*), fast-diff(*), deep-flatten,
+ [layering(+), striping, exclusive-lock(+*),
+ object-map(+*), fast-diff(+*), deep-flatten(+-),
journaling(*)]
--image-shared shared image
--stripe-unit arg stripe unit
Image Features:
(*) supports enabling/disabling on existing images
+ (-) supports disabling-only on existing images
(+) enabled by default for new images if features not specified
rbd help import-diff
ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
string oid = get_temp_image_name();
- ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, 0, oid));
+ uint64_t base_features = RBD_FEATURE_LAYERING | RBD_FEATURE_DEEP_FLATTEN;
+ ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, base_features, oid));
uint64_t features = RBD_FEATURES_MUTABLE;
uint64_t mask = RBD_FEATURES_MUTABLE;
uint64_t actual_features;
ASSERT_EQ(0, get_features(&ioctx, oid, CEPH_NOSNAP, &actual_features));
- uint64_t expected_features = RBD_FEATURES_MUTABLE;
+ uint64_t expected_features = RBD_FEATURES_MUTABLE | base_features;
ASSERT_EQ(expected_features, actual_features);
features = 0;
ASSERT_EQ(0, get_features(&ioctx, oid, CEPH_NOSNAP, &actual_features));
- expected_features = RBD_FEATURES_MUTABLE & ~RBD_FEATURE_OBJECT_MAP;
+ expected_features = (RBD_FEATURES_MUTABLE | base_features) &
+ ~RBD_FEATURE_OBJECT_MAP;
ASSERT_EQ(expected_features, actual_features);
- mask = RBD_FEATURE_LAYERING;
- ASSERT_EQ(-EINVAL, set_features(&ioctx, oid, features, mask));
+ ASSERT_EQ(0, set_features(&ioctx, oid, 0, RBD_FEATURE_DEEP_FLATTEN));
+ ASSERT_EQ(-EINVAL, set_features(&ioctx, oid, RBD_FEATURE_DEEP_FLATTEN,
+ RBD_FEATURE_DEEP_FLATTEN));
+
+ ASSERT_EQ(-EINVAL, set_features(&ioctx, oid, 0, RBD_FEATURE_LAYERING));
}
TEST_F(TestClsRbd, mirror) {
return;
}
+ uint64_t features;
+ ASSERT_EQ(0, image.features(&features));
+
// must provide a single feature
ASSERT_EQ(-EINVAL, image.update_features(0, true));
ASSERT_EQ(0U, flags);
ASSERT_EQ(0, image.update_features(RBD_FEATURE_EXCLUSIVE_LOCK, false));
+
+ if ((features & RBD_FEATURE_DEEP_FLATTEN) != 0) {
+ ASSERT_EQ(0, image.update_features(RBD_FEATURE_DEEP_FLATTEN, false));
+ }
+ ASSERT_EQ(-EINVAL, image.update_features(RBD_FEATURE_DEEP_FLATTEN, true));
}
TEST_F(TestLibRBD, RebuildObjectMap)
std::string suffix;
if (append_suffix) {
- if ((pair.first & RBD_FEATURES_MUTABLE) != 0) {
- suffix += "*";
- }
if ((pair.first & g_conf->rbd_default_features) != 0) {
suffix += "+";
}
+ if ((pair.first & RBD_FEATURES_MUTABLE) != 0) {
+ suffix += "*";
+ } else if ((pair.first & RBD_FEATURES_DISABLE_ONLY) != 0) {
+ suffix += "-";
+ }
if (!suffix.empty()) {
suffix = "(" + suffix + ")";
}
std::ostringstream oss;
oss << "Image Features:" << std::endl
<< " (*) supports enabling/disabling on existing images" << std::endl
+ << " (-) supports disabling-only on existing images" << std::endl
<< " (+) enabled by default for new images if features not specified"
<< std::endl;
return oss.str();