From: Jason Dillaman Date: Wed, 11 Mar 2015 20:07:41 +0000 (-0400) Subject: cls_rbd: add set_features class method X-Git-Tag: v9.0.0~37^2~9 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=71dcee745b2b40388375e4d0a2987d69beb09304;p=ceph.git cls_rbd: add set_features class method Allow certain mutable feature flags to be updated within an image. Signed-off-by: Jason Dillaman --- diff --git a/src/cls/rbd/cls_rbd.cc b/src/cls/rbd/cls_rbd.cc index 677cfe0d011..6bd5999060d 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 1d170679d49..39abb396224 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