From 71dcee745b2b40388375e4d0a2987d69beb09304 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Wed, 11 Mar 2015 16:07:41 -0400 Subject: [PATCH] cls_rbd: add set_features class method Allow certain mutable feature flags to be updated within an image. Signed-off-by: Jason Dillaman --- src/cls/rbd/cls_rbd.cc | 58 ++++++++++++++++++++++++++++++++++++++ src/include/rbd/features.h | 3 ++ 2 files changed, 61 insertions(+) diff --git a/src/cls/rbd/cls_rbd.cc b/src/cls/rbd/cls_rbd.cc index 677cfe0d01196..6bd5999060d1d 100644 --- a/src/cls/rbd/cls_rbd.cc +++ b/src/cls/rbd/cls_rbd.cc @@ -64,6 +64,7 @@ CLS_NAME(rbd) cls_handle_t h_class; cls_method_handle_t h_create; cls_method_handle_t h_get_features; +cls_method_handle_t h_set_features; cls_method_handle_t h_get_size; cls_method_handle_t h_set_size; cls_method_handle_t h_get_parent; @@ -323,6 +324,60 @@ int get_features(cls_method_context_t hctx, bufferlist *in, bufferlist *out) return 0; } +/** + * set the image features + * + * Input: + * @params features image features + * @params mask image feature mask + * + * Output: + * none + * + * @returns 0 on success, negative error code upon failure + */ +int set_features(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +{ + uint64_t features; + uint64_t mask; + bufferlist::iterator iter = in->begin(); + try { + ::decode(features, iter); + ::decode(mask, iter); + } catch (const buffer::error &err) { + 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; + int r = read_key(hctx, "features", &orig_features); + if (r < 0 && r != -ENOENT) { + CLS_ERR("Could not read image's features off disk: %s", + cpp_strerror(r).c_str()); + return r; + } + + features = (orig_features & ~mask) | (features & mask); + CLS_LOG(10, "set_features features=%" PRIu64 " orig_features=%" PRIu64, + features, orig_features); + + bufferlist bl; + ::encode(features, bl); + r = cls_cxx_map_set_val(hctx, "features", &bl); + if (r < 0) { + CLS_ERR("error updating features: %s", cpp_strerror(r).c_str()); + return r; + } + return 0; +} + /** * check that given feature(s) are set * @@ -2501,6 +2556,9 @@ void __cls_init() cls_register_cxx_method(h_class, "get_features", CLS_METHOD_RD, get_features, &h_get_features); + cls_register_cxx_method(h_class, "set_features", + CLS_METHOD_RD | CLS_METHOD_WR, + set_features, &h_set_features); cls_register_cxx_method(h_class, "get_size", CLS_METHOD_RD, get_size, &h_get_size); diff --git a/src/include/rbd/features.h b/src/include/rbd/features.h index 1d170679d49dd..39abb396224cb 100644 --- a/src/include/rbd/features.h +++ b/src/include/rbd/features.h @@ -18,4 +18,7 @@ RBD_FEATURE_EXCLUSIVE_LOCK | \ RBD_FEATURE_OBJECT_MAP) +#define RBD_FEATURES_MUTABLE (RBD_FEATURE_EXCLUSIVE_LOCK | \ + RBD_FEATURE_OBJECT_MAP) + #endif -- 2.39.5