From: Jason Dillaman Date: Mon, 3 Nov 2014 21:51:06 +0000 (-0500) Subject: librbd: differentiate between R/O vs R/W RBD features X-Git-Tag: v0.92~20^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=6176ec5fde2a68296849fd91f1f7fd50730087a7;p=ceph.git librbd: differentiate between R/O vs R/W RBD features The new RBD exclusive lock feature should be treated as a feature that is only applied when the image is opened in R/W mode. Older clients will need to handle the updated cls_rbd::get_features method in order to properly determine the incompatible features for an image depending on the current mode. Signed-off-by: Jason Dillaman --- diff --git a/src/cls/rbd/cls_rbd.cc b/src/cls/rbd/cls_rbd.cc index 68d960627125..866823f024ba 100644 --- a/src/cls/rbd/cls_rbd.cc +++ b/src/cls/rbd/cls_rbd.cc @@ -282,10 +282,14 @@ int create(cls_method_context_t hctx, bufferlist *in, bufferlist *out) int get_features(cls_method_context_t hctx, bufferlist *in, bufferlist *out) { uint64_t features, snap_id; + bool read_only = false; bufferlist::iterator iter = in->begin(); try { ::decode(snap_id, iter); + if (!iter.end()) { + ::decode(read_only, iter); + } } catch (const buffer::error &err) { return -EINVAL; } @@ -309,7 +313,8 @@ int get_features(cls_method_context_t hctx, bufferlist *in, bufferlist *out) features = snap.features; } - uint64_t incompatible = features & RBD_FEATURES_INCOMPATIBLE; + uint64_t incompatible = (read_only ? features & RBD_FEATURES_INCOMPATIBLE : + features & RBD_FEATURES_RW_INCOMPATIBLE); ::encode(features, *out); ::encode(incompatible, *out); diff --git a/src/cls/rbd/cls_rbd_client.cc b/src/cls/rbd/cls_rbd_client.cc index 7bc596a3ec60..8bbb1ccc2c42 100644 --- a/src/cls/rbd/cls_rbd_client.cc +++ b/src/cls/rbd/cls_rbd_client.cc @@ -47,7 +47,7 @@ namespace librbd { } int get_mutable_metadata(librados::IoCtx *ioctx, const std::string &oid, - uint64_t *size, uint64_t *features, + bool read_only, uint64_t *size, uint64_t *features, uint64_t *incompatible_features, map *lockers, @@ -68,11 +68,15 @@ namespace librbd { bufferlist sizebl, featuresbl, parentbl, empty; snapid_t snap = CEPH_NOSNAP; ::encode(snap, sizebl); - ::encode(snap, featuresbl); - ::encode(snap, parentbl); op.exec("rbd", "get_size", sizebl); + + ::encode(snap, featuresbl); + ::encode(read_only, featuresbl); op.exec("rbd", "get_features", featuresbl); + op.exec("rbd", "get_snapcontext", empty); + + ::encode(snap, parentbl); op.exec("rbd", "get_parent", parentbl); rados::cls::lock::get_lock_info_start(&op, RBD_LOCK_NAME); diff --git a/src/cls/rbd/cls_rbd_client.h b/src/cls/rbd/cls_rbd_client.h index 34cc45b83909..10073e578c48 100644 --- a/src/cls/rbd/cls_rbd_client.h +++ b/src/cls/rbd/cls_rbd_client.h @@ -19,7 +19,7 @@ namespace librbd { int get_immutable_metadata(librados::IoCtx *ioctx, const std::string &oid, std::string *object_prefix, uint8_t *order); int get_mutable_metadata(librados::IoCtx *ioctx, const std::string &oid, - uint64_t *size, uint64_t *features, + bool read_only, uint64_t *size, uint64_t *features, uint64_t *incompatible_features, map *lockers, diff --git a/src/include/rbd/features.h b/src/include/rbd/features.h index 9b28b5749953..7e35baac348e 100644 --- a/src/include/rbd/features.h +++ b/src/include/rbd/features.h @@ -5,9 +5,14 @@ #define RBD_FEATURE_STRIPINGV2 (1<<1) #define RBD_FEATURE_EXCLUSIVE_LOCK (1<<2) -#define RBD_FEATURES_INCOMPATIBLE (RBD_FEATURE_LAYERING|RBD_FEATURE_STRIPINGV2|\ - RBD_FEATURE_EXCLUSIVE_LOCK) -#define RBD_FEATURES_ALL (RBD_FEATURE_LAYERING|RBD_FEATURE_STRIPINGV2|\ - RBD_FEATURE_EXCLUSIVE_LOCK) +#define RBD_FEATURES_INCOMPATIBLE (RBD_FEATURE_LAYERING | \ + RBD_FEATURE_STRIPINGV2) + +#define RBD_FEATURES_RW_INCOMPATIBLE (RBD_FEATURES_INCOMPATIBLE | \ + RBD_FEATURE_EXCLUSIVE_LOCK) + +#define RBD_FEATURES_ALL (RBD_FEATURE_LAYERING | \ + RBD_FEATURE_STRIPINGV2 | \ + RBD_FEATURE_EXCLUSIVE_LOCK) #endif diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index 7794d986f261..e645fd883189 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -1849,7 +1849,9 @@ reprotect_and_return_err: } else { do { uint64_t incompatible_features; + bool read_only = ictx->read_only || ictx->snap_id != CEPH_NOSNAP; r = cls_client::get_mutable_metadata(&ictx->md_ctx, ictx->header_oid, + read_only, &ictx->size, &ictx->features, &incompatible_features, &ictx->lockers, diff --git a/src/test/cls_rbd/test_cls_rbd.cc b/src/test/cls_rbd/test_cls_rbd.cc index 31d7df0cd801..bef5fe141b54 100644 --- a/src/test/cls_rbd/test_cls_rbd.cc +++ b/src/test/cls_rbd/test_cls_rbd.cc @@ -48,6 +48,7 @@ using ::librbd::cls_client::set_protection_status; using ::librbd::cls_client::get_stripe_unit_count; using ::librbd::cls_client::set_stripe_unit_count; using ::librbd::cls_client::old_snapshot_add; +using ::librbd::cls_client::get_mutable_metadata; static char *random_buf(size_t len) { @@ -887,3 +888,38 @@ TEST_F(TestClsRbd, stripingv2) ioctx.close(); } + +TEST_F(TestClsRbd, get_mutable_metadata_features) +{ + librados::IoCtx ioctx; + ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx)); + + string oid = get_temp_image_name(); + ASSERT_EQ(0, create_image(&ioctx, oid, 10, 22, RBD_FEATURE_EXCLUSIVE_LOCK, + oid)); + + uint64_t size, features, incompatible_features; + std::map lockers; + bool exclusive_lock; + std::string lock_tag; + ::SnapContext snapc; + parent_info parent; + + ASSERT_EQ(0, get_mutable_metadata(&ioctx, oid, true, &size, &features, + &incompatible_features, &lockers, + &exclusive_lock, &lock_tag, &snapc, + &parent)); + ASSERT_EQ(static_cast(RBD_FEATURE_EXCLUSIVE_LOCK), features); + ASSERT_EQ(0U, incompatible_features); + + ASSERT_EQ(0, get_mutable_metadata(&ioctx, oid, false, &size, &features, + &incompatible_features, &lockers, + &exclusive_lock, &lock_tag, &snapc, + &parent)); + ASSERT_EQ(static_cast(RBD_FEATURE_EXCLUSIVE_LOCK), features); + ASSERT_EQ(static_cast(RBD_FEATURE_EXCLUSIVE_LOCK), + incompatible_features); + + ioctx.close(); +}