Allow mutable features to be enabled / disabled.
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
#define LIBRBD_VER_MAJOR 0
#define LIBRBD_VER_MINOR 1
-#define LIBRBD_VER_EXTRA 9
+#define LIBRBD_VER_EXTRA 10
#define LIBRBD_VERSION(maj, min, extra) ((maj << 16) + (min << 8) + extra)
CEPH_RBD_API int rbd_get_old_format(rbd_image_t image, uint8_t *old);
CEPH_RBD_API int rbd_get_size(rbd_image_t image, uint64_t *size);
CEPH_RBD_API int rbd_get_features(rbd_image_t image, uint64_t *features);
+CEPH_RBD_API int rbd_update_features(rbd_image_t image, uint64_t features,
+ uint8_t enabled);
CEPH_RBD_API int rbd_get_stripe_unit(rbd_image_t image, uint64_t *stripe_unit);
CEPH_RBD_API int rbd_get_stripe_count(rbd_image_t image,
uint64_t *stripe_count);
int old_format(uint8_t *old);
int size(uint64_t *size);
int features(uint64_t *features);
+ int update_features(uint64_t features, bool enabled);
int overlap(uint64_t *overlap);
int get_flags(uint64_t *flags);
#include "include/stringify.h"
#include "cls/rbd/cls_rbd.h"
+#include "cls/rbd/cls_rbd_client.h"
#include "librbd/AioCompletion.h"
#include "librbd/AioRequest.h"
return 0;
}
+ int update_features(ImageCtx *ictx, uint64_t features, bool enabled)
+ {
+ int r = ictx_check(ictx);
+ if (r < 0) {
+ return r;
+ }
+
+ CephContext *cct = ictx->cct;
+ if (ictx->read_only) {
+ return -EROFS;
+ } else if (ictx->old_format) {
+ lderr(cct) << "old-format images do not support features" << dendl;
+ return -EINVAL;
+ }
+
+ if ((features & RBD_FEATURES_MUTABLE) != features) {
+ lderr(cct) << "cannot update immutable features" << dendl;
+ return -EINVAL;
+ } else if (features == 0) {
+ lderr(cct) << "update requires at least one feature" << dendl;
+ return -EINVAL;
+ }
+
+ RWLock::RLocker l(ictx->snap_lock);
+ uint64_t new_features = ictx->features | features;
+ if (!enabled) {
+ new_features = ictx->features & ~features;
+ }
+
+ if (ictx->features == new_features) {
+ return 0;
+ }
+
+ uint64_t mask = features;
+ if ((features & RBD_FEATURE_EXCLUSIVE_LOCK) != 0 && !enabled) {
+ if ((new_features & RBD_FEATURE_OBJECT_MAP) != 0) {
+ lderr(cct) << "cannot disable exclusive lock" << dendl;
+ return -EINVAL;
+ }
+ mask |= RBD_FEATURE_OBJECT_MAP;
+ } else if ((features & RBD_FEATURE_OBJECT_MAP) != 0 && enabled) {
+ if ((new_features & RBD_FEATURE_EXCLUSIVE_LOCK) == 0) {
+ lderr(cct) << "cannot enable object map" << dendl;
+ return -EINVAL;
+ }
+ mask |= RBD_FEATURE_EXCLUSIVE_LOCK;
+ }
+
+ ldout(cct, 10) << "update_features: features=" << new_features << ", mask="
+ << mask << dendl;
+ r = librbd::cls_client::set_features(&ictx->md_ctx, ictx->header_oid,
+ new_features, mask);
+ if (r < 0) {
+ lderr(cct) << "failed to update features: " << cpp_strerror(r)
+ << dendl;
+ }
+
+ notify_change(ictx->md_ctx, ictx->header_oid, ictx);
+ return 0;
+ }
+
int get_overlap(ImageCtx *ictx, uint64_t *overlap)
{
int r = ictx_check(ictx);
int get_old_format(ImageCtx *ictx, uint8_t *old);
int get_size(ImageCtx *ictx, uint64_t *size);
int get_features(ImageCtx *ictx, uint64_t *features);
+ int update_features(ImageCtx *ictx, uint64_t features, bool enabled);
int get_overlap(ImageCtx *ictx, uint64_t *overlap);
int get_parent_info(ImageCtx *ictx, std::string *parent_pool_name,
std::string *parent_name, std::string *parent_snap_name);
return r;
}
+ int Image::update_features(uint64_t features, bool enabled)
+ {
+ ImageCtx *ictx = reinterpret_cast<ImageCtx *>(ctx);
+ tracepoint(librbd, update_features_enter, ictx, features, enabled);
+ int r = librbd::update_features(ictx, features, enabled);
+ tracepoint(librbd, update_features_exit, r);
+ return r;
+ }
+
uint64_t Image::get_stripe_unit() const
{
ImageCtx *ictx = (ImageCtx *)ctx;
return r;
}
+extern "C" int rbd_update_features(rbd_image_t image, uint64_t features,
+ uint8_t enabled)
+{
+ librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
+ bool features_enabled = enabled != 0;
+ tracepoint(librbd, update_features_enter, ictx, features, features_enabled);
+ int r = librbd::update_features(ictx, features, features_enabled);
+ tracepoint(librbd, update_features_exit, r);
+ return r;
+}
+
extern "C" int rbd_get_stripe_unit(rbd_image_t image, uint64_t *stripe_unit)
{
librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
)
)
+TRACEPOINT_EVENT(librbd, update_features_enter,
+ TP_ARGS(
+ void*, imagectx,
+ uint64_t, features,
+ char, enabled),
+ TP_FIELDS(
+ ctf_integer_hex(void*, imagectx, imagectx)
+ ctf_integer(uint64_t, features, features)
+ ctf_integer(char, enabled, enabled)
+ )
+)
+
+TRACEPOINT_EVENT(librbd, update_features_exit,
+ TP_ARGS(
+ int, retval),
+ TP_FIELDS(
+ ctf_integer(int, retval, retval)
+ )
+)
+
TRACEPOINT_EVENT(librbd, get_size_enter,
TP_ARGS(
void*, imagectx,