]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: cls_rbd_parent on-disk struct supports namespaces
authorJason Dillaman <dillaman@redhat.com>
Mon, 20 Aug 2018 11:47:51 +0000 (07:47 -0400)
committerJason Dillaman <dillaman@redhat.com>
Wed, 19 Sep 2018 12:04:12 +0000 (08:04 -0400)
If the OSDs are required to be Nautilus or later, it will automatically break
backwards compatibility of the structure to support pool namespaces.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/cls/rbd/cls_rbd.cc
src/cls/rbd/cls_rbd.h
src/tools/ceph-dencoder/types.h

index 1cee8b904d6666e97597849577c32dcb21c2a190..0d747db59b45ab3ba2d2682e384cdf49c749ac35 100644 (file)
@@ -66,6 +66,19 @@ CLS_NAME(rbd)
 #define RBD_DIR_NAME_KEY_PREFIX "name_"
 #define RBD_METADATA_KEY_PREFIX "metadata_"
 
+namespace {
+
+uint64_t get_encode_features(cls_method_context_t hctx) {
+  uint64_t features = 0;
+  int8_t require_osd_release = cls_get_required_osd_release(hctx);
+  if (require_osd_release >= CEPH_RELEASE_NAUTILUS) {
+    features |= CEPH_FEATURE_SERVER_NAUTILUS;
+  }
+  return features;
+}
+
+} // anonymous namespace
+
 static int snap_read_header(cls_method_context_t hctx, bufferlist& bl)
 {
   unsigned snap_count = 0;
@@ -153,6 +166,20 @@ static int write_key(cls_method_context_t hctx, const string &key, const T &t) {
   return 0;
 }
 
+template <typename T>
+static int write_key(cls_method_context_t hctx, const string &key, const T &t,
+                     uint64_t features) {
+  bufferlist bl;
+  encode(t, bl, features);
+
+  int r = cls_cxx_map_set_val(hctx, key, &bl);
+  if (r < 0) {
+    CLS_ERR("failed to set omap key: %s", key.c_str());
+    return r;
+  }
+  return 0;
+}
+
 static int remove_key(cls_method_context_t hctx, const string &key) {
   int r = cls_cxx_map_remove_key(hctx, key);
   if (r < 0 && r != -ENOENT) {
@@ -801,13 +828,10 @@ int set_size(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
       r = 0;
     if (r < 0)
       return r;
-    if (parent.exists() && parent.overlap > size) {
-      bufferlist parentbl;
-      parent.overlap = size;
-      encode(parent, parentbl);
-      r = cls_cxx_map_set_val(hctx, "parent", &parentbl);
+    if (parent.exists() && parent.head_overlap.value_or(0ULL) > size) {
+      parent.head_overlap = size;
+      r = write_key(hctx, "parent", parent, get_encode_features(hctx));
       if (r < 0) {
-       CLS_ERR("error writing parent: %s", cpp_strerror(r).c_str());
        return r;
       }
     }
@@ -1398,10 +1422,10 @@ int get_parent(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
     }
   }
 
-  encode(parent.pool, *out);
-  encode(parent.id, *out);
-  encode(parent.snapid, *out);
-  encode(parent.overlap, *out);
+  encode(parent.pool_id, *out);
+  encode(parent.image_id, *out);
+  encode(parent.snap_id, *out);
+  encode(parent.head_overlap.value_or(0ULL), *out);
   return 0;
 }
 
@@ -1459,9 +1483,10 @@ int set_parent(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
   r = read_key(hctx, "parent", &parent);
   if (r == 0) {
     CLS_LOG(20, "set_parent existing parent pool=%llu id=%s snapid=%llu"
-            "overlap=%llu", (unsigned long long)parent.pool, parent.id.c_str(),
-           (unsigned long long)parent.snapid.val,
-           (unsigned long long)parent.overlap);
+            "overlap=%llu", (unsigned long long)parent.pool_id,
+            parent.image_id.c_str(),
+           (unsigned long long)parent.snap_id.val,
+           (unsigned long long)parent.head_overlap.value_or(0ULL));
     return -EEXIST;
   }
 
@@ -1471,15 +1496,12 @@ int set_parent(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
   if (r < 0)
     return r;
 
-  bufferlist parentbl;
-  parent.pool = pool;
-  parent.id = id;
-  parent.snapid = snapid;
-  parent.overlap = std::min(our_size, size);
-  encode(parent, parentbl);
-  r = cls_cxx_map_set_val(hctx, "parent", &parentbl);
+  parent.pool_id = pool;
+  parent.image_id = id;
+  parent.snap_id = snapid;
+  parent.head_overlap = std::min(our_size, size);
+  r = write_key(hctx, "parent", parent, get_encode_features(hctx));
   if (r < 0) {
-    CLS_ERR("error writing parent: %s", cpp_strerror(r).c_str());
     return r;
   }
 
@@ -1511,7 +1533,7 @@ int remove_parent(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
   }
 
   auto flatten_lambda = [hctx, features](const cls_rbd_snap& snap_meta) {
-    if (snap_meta.parent.pool != -1) {
+    if (snap_meta.parent.pool_id != -1) {
       if ((features & RBD_FEATURE_DEEP_FLATTEN) != 0ULL) {
         // remove parent reference from snapshot
         cls_rbd_snap snap_meta_copy = snap_meta;
@@ -2246,7 +2268,7 @@ int snapshot_remove(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
   auto remove_lambda =
     [snap_id, &has_child_snaps, &has_trash_snaps](const cls_rbd_snap& snap_meta) {
       if (snap_meta.id != snap_id) {
-        if (snap_meta.parent.pool != -1) {
+        if (snap_meta.parent.pool_id != -1) {
           has_child_snaps = true;
         }
         if (cls::rbd::get_snap_namespace_type(snap_meta.snapshot_namespace) ==
@@ -2267,7 +2289,7 @@ int snapshot_remove(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
   if (r < 0 && r != -ENOENT) {
     return r;
   }
-  bool has_parent = (r >= 0 && parent.pool != -1);
+  bool has_parent = (r >= 0 && parent.pool_id != -1);
 
   uint64_t op_features_mask = 0ULL;
   if (!has_child_snaps && !has_parent) {
index 37f9a5efcf84b49b36070087284e42a57afd3c59..202ff97b7216686d0b6bca9b63fa2160fb6ec227 100644 (file)
 
 /// information about our parent image, if any
 struct cls_rbd_parent {
-  int64_t pool;        ///< parent pool id
-  string id;           ///< parent image id
-  snapid_t snapid;     ///< parent snapid we refer to
-  uint64_t overlap;    ///< portion of this image mapped onto parent (bytes)
+  int64_t pool_id = -1;
+  std::string pool_namespace;
+  std::string image_id;
+  snapid_t snap_id = CEPH_NOSNAP;
+  std::optional<uint64_t> head_overlap = std::nullopt;
 
-  /// true if our parent pointer information is defined
-  bool exists() const {
-    return snapid != CEPH_NOSNAP && pool >= 0 && id.length() > 0 && overlap > 0;
+  cls_rbd_parent() {
+  }
+  cls_rbd_parent(const cls::rbd::ParentImageSpec& parent_image_spec,
+                 const std::optional<uint64_t>& head_overlap)
+    : pool_id(parent_image_spec.pool_id),
+      pool_namespace(parent_image_spec.pool_namespace),
+      image_id(parent_image_spec.image_id), snap_id(parent_image_spec.snap_id),
+      head_overlap(head_overlap) {
   }
 
-  cls_rbd_parent() : pool(-1), snapid(CEPH_NOSNAP), overlap(0) {}
+  inline bool exists() const {
+    return (pool_id >= 0 && !image_id.empty() && snap_id != CEPH_NOSNAP);
+  }
 
-  void encode(bufferlist& bl) const {
-    ENCODE_START(1, 1, bl);
-    encode(pool, bl);
-    encode(id, bl);
-    encode(snapid, bl);
-    encode(overlap, bl);
+  inline bool operator==(const cls_rbd_parent& rhs) const {
+    return (pool_id == rhs.pool_id &&
+            pool_namespace == rhs.pool_namespace &&
+            image_id == rhs.image_id &&
+            snap_id == rhs.snap_id);
+  }
+  inline bool operator!=(const cls_rbd_parent& rhs) const {
+    return !(*this == rhs);
+  }
+
+  void encode(bufferlist& bl, uint64_t features) const {
+    // NOTE: remove support for version 1 after Nautilus EOLed
+    uint8_t version = 1;
+    if ((features & CEPH_FEATURE_SERVER_NAUTILUS) != 0ULL) {
+      // break backwards compatability when using nautilus or later OSDs
+      version = 2;
+    }
+
+    ENCODE_START(version, version, bl);
+    encode(pool_id, bl);
+    if (version >= 2) {
+      encode(pool_namespace, bl);
+    }
+    encode(image_id, bl);
+    encode(snap_id, bl);
+    if (version == 1) {
+      encode(head_overlap.value_or(0ULL), bl);
+    } else {
+      encode(head_overlap, bl);
+    }
     ENCODE_FINISH(bl);
   }
+
   void decode(bufferlist::const_iterator& bl) {
-    DECODE_START(1, bl);
-    decode(pool, bl);
-    decode(id, bl);
-    decode(snapid, bl);
-    decode(overlap, bl);
+    DECODE_START(2, bl);
+    decode(pool_id, bl);
+    if (struct_v >= 2) {
+      decode(pool_namespace, bl);
+    }
+    decode(image_id, bl);
+    decode(snap_id, bl);
+    if (struct_v == 1) {
+      uint64_t overlap;
+      decode(overlap, bl);
+      head_overlap = overlap;
+    } else {
+      decode(head_overlap, bl);
+    }
     DECODE_FINISH(bl);
   }
+
   void dump(Formatter *f) const {
-    f->dump_int("pool", pool);
-    f->dump_string("id", id);
-    f->dump_unsigned("snapid", snapid);
-    f->dump_unsigned("overlap", overlap);
+    f->dump_int("pool_id", pool_id);
+    f->dump_string("pool_namespace", pool_namespace);
+    f->dump_string("image_id", image_id);
+    f->dump_unsigned("snap_id", snap_id);
+    if (head_overlap) {
+      f->dump_unsigned("head_overlap", *head_overlap);
+    }
   }
+
   static void generate_test_instances(list<cls_rbd_parent*>& o) {
-    o.push_back(new cls_rbd_parent);
-    cls_rbd_parent *t = new cls_rbd_parent;
-    t->pool = 1;
-    t->id = "foo";
-    t->snapid = 3;
-    t->overlap = 500;
-    o.push_back(t);
+    o.push_back(new cls_rbd_parent{});
+    o.push_back(new cls_rbd_parent{{1, "", "image id", 234}, {}});
+    o.push_back(new cls_rbd_parent{{1, "", "image id", 234}, {123}});
+    o.push_back(new cls_rbd_parent{{1, "ns", "image id", 234}, {123}});
   }
 };
-WRITE_CLASS_ENCODER(cls_rbd_parent)
+WRITE_CLASS_ENCODER_FEATURES(cls_rbd_parent)
 
 struct cls_rbd_snap {
   snapid_t id = CEPH_NOSNAP;
@@ -82,7 +126,7 @@ struct cls_rbd_snap {
     encode(image_size, bl);
     uint64_t features = 0;
     encode(features, bl); // unused -- preserve ABI
-    encode(parent, bl);
+    encode(parent, bl, 0);
     encode(protection_status, bl);
     encode(flags, bl);
     encode(snapshot_namespace, bl);
@@ -154,10 +198,7 @@ struct cls_rbd_snap {
     t->id = 2;
     t->name = "snap2";
     t->image_size = 12345678;
-    t->parent.pool = 1;
-    t->parent.id = "parent";
-    t->parent.snapid = 456;
-    t->parent.overlap = 12345;
+    t->parent = {{1, "", "parent", 456}, 12345};
     t->protection_status = RBD_PROTECTION_STATUS_PROTECTED;
     t->flags = 14;
     t->timestamp = utime_t();
index d8a5dd00d3c2c5fc7cbcdae74123a7c5139115b7..b56110df2a2c32c56708fc47ea7fb730656cfe5f 100644 (file)
@@ -461,7 +461,7 @@ TYPE(rgw_data_sync_status)
 
 #ifdef WITH_RBD
 #include "cls/rbd/cls_rbd.h"
-TYPE(cls_rbd_parent)
+TYPE_FEATUREFUL(cls_rbd_parent)
 TYPE(cls_rbd_snap)
 
 #include "cls/rbd/cls_rbd_types.h"