]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
rbd-mirror: track on-disk image to instance map
authorVenky Shankar <vshankar@redhat.com>
Mon, 31 Jul 2017 05:58:11 +0000 (01:58 -0400)
committerVenky Shankar <vshankar@redhat.com>
Fri, 18 Aug 2017 12:49:04 +0000 (08:49 -0400)
Signed-off-by: Venky Shankar <vshankar@redhat.com>
src/cls/rbd/cls_rbd.cc
src/cls/rbd/cls_rbd_client.cc
src/cls/rbd/cls_rbd_client.h
src/cls/rbd/cls_rbd_types.cc
src/cls/rbd/cls_rbd_types.h
src/test/encoding/types.h

index 0c2d7aee595ec4ac52acc82cab009019225fe8dc..2ab186bf6aa2fd68fee21f50f6a3834ea56f3853 100644 (file)
@@ -3132,6 +3132,7 @@ static const std::string IMAGE_KEY_PREFIX("image_");
 static const std::string GLOBAL_KEY_PREFIX("global_");
 static const std::string STATUS_GLOBAL_KEY_PREFIX("status_global_");
 static const std::string INSTANCE_KEY_PREFIX("instance_");
+static const std::string MIRROR_IMAGE_MAP_KEY_PREFIX("image_map_");
 
 std::string peer_key(const std::string &uuid) {
   return PEER_KEY_PREFIX + uuid;
@@ -3153,6 +3154,10 @@ std::string instance_key(const string &instance_id) {
   return INSTANCE_KEY_PREFIX + instance_id;
 }
 
+std::string mirror_image_map_key(const string& global_image_id) {
+  return MIRROR_IMAGE_MAP_KEY_PREFIX + global_image_id;
+}
+
 int uuid_get(cls_method_context_t hctx, std::string *mirror_uuid) {
   bufferlist mirror_uuid_bl;
   int r = cls_cxx_map_get_val(hctx, mirror::UUID, &mirror_uuid_bl);
@@ -3689,6 +3694,53 @@ int instances_remove(cls_method_context_t hctx, const string &instance_id) {
   return 0;
 }
 
+int mirror_image_map_list(cls_method_context_t hctx,
+                          const std::string &start_after,
+                          uint64_t max_return,
+                          std::map<std::string, cls::rbd::MirrorImageMap> *image_mapping) {
+  bool more = true;
+  std::string last_read = mirror_image_map_key(start_after);
+
+  while (more && image_mapping->size() < max_return) {
+    std::map<std::string, bufferlist> vals;
+    CLS_LOG(20, "last read: '%s'", last_read.c_str());
+
+    int max_read = MIN(RBD_MAX_KEYS_READ, max_return - image_mapping->size());
+    int r = cls_cxx_map_get_vals(hctx, last_read, MIRROR_IMAGE_MAP_KEY_PREFIX,
+                                 max_read, &vals, &more);
+    if (r < 0) {
+      CLS_ERR("error reading image map: %s", cpp_strerror(r).c_str());
+      return r;
+    }
+
+    if (vals.empty()) {
+      return 0;
+    }
+
+    for (auto it = vals.begin(); it != vals.end(); ++it) {
+      const std::string &global_image_id =
+        it->first.substr(MIRROR_IMAGE_MAP_KEY_PREFIX.size());
+
+      cls::rbd::MirrorImageMap mirror_image_map;
+      bufferlist::iterator iter = it->second.begin();
+      try {
+        ::decode(mirror_image_map, iter);
+      } catch (const buffer::error &err) {
+        CLS_ERR("could not decode image map payload: %s", cpp_strerror(r).c_str());
+        return -EINVAL;
+      }
+
+      image_mapping->insert(std::make_pair(global_image_id, mirror_image_map));
+    }
+
+    if (!vals.empty()) {
+      last_read = mirror_image_map_key(vals.rbegin()->first);
+    }
+  }
+
+  return 0;
+}
+
 } // namespace mirror
 
 /**
@@ -4427,6 +4479,101 @@ int mirror_instances_remove(cls_method_context_t hctx, bufferlist *in,
   return 0;
 }
 
+/**
+ * Input:
+ * @param start_after: key to start after
+ * @param max_return: max return items
+ *
+ * Output:
+ * @param std::map<std::string, cls::rbd::MirrorImageMap>: image mapping
+ * @returns 0 on success, negative error code on failure
+ */
+int mirror_image_map_list(cls_method_context_t hctx, bufferlist *in,
+                          bufferlist *out) {
+  std::string start_after;
+  uint64_t max_return;
+  try {
+    bufferlist::iterator it = in->begin();
+    ::decode(start_after, it);
+    ::decode(max_return, it);
+  } catch (const buffer::error &err) {
+    return -EINVAL;
+  }
+
+  std::map<std::string, cls::rbd::MirrorImageMap> image_mapping;
+  int r = mirror::mirror_image_map_list(hctx, start_after, max_return, &image_mapping);
+  if (r < 0) {
+    return r;
+  }
+
+  ::encode(image_mapping, *out);
+  return 0;
+}
+
+/**
+ * Input:
+ * @param global_image_id: global image id
+ * @param image_map: image map
+ *
+ * Output:
+ * @returns 0 on success, negative error code on failure
+ */
+int mirror_image_map_update(cls_method_context_t hctx, bufferlist *in,
+                            bufferlist *out) {
+  std::string global_image_id;
+  cls::rbd::MirrorImageMap image_map;
+
+  try {
+    bufferlist::iterator it = in->begin();
+    ::decode(global_image_id, it);
+    ::decode(image_map, it);
+  } catch (const buffer::error &err) {
+    return -EINVAL;
+  }
+
+  bufferlist bl;
+  ::encode(image_map, bl);
+
+  const std::string key = mirror::mirror_image_map_key(global_image_id);
+  int r = cls_cxx_map_set_val(hctx, key, &bl);
+  if (r < 0) {
+    CLS_ERR("error updating image map %s: %s", key.c_str(),
+            cpp_strerror(r).c_str());
+    return r;
+  }
+
+  return 0;
+}
+
+/**
+ * Input:
+ * @param global_image_id: global image id
+ *
+ * Output:
+ * @returns 0 on success, negative error code on failure
+ */
+int mirror_image_map_remove(cls_method_context_t hctx, bufferlist *in,
+                            bufferlist *out) {
+  std::string global_image_id;
+
+  try {
+    bufferlist::iterator it = in->begin();
+    ::decode(global_image_id, it);
+  } catch (const buffer::error &err) {
+    return -EINVAL;
+  }
+
+  const std::string key = mirror::mirror_image_map_key(global_image_id);
+  int r = cls_cxx_map_remove_key(hctx, key);
+  if (r < 0 && r != -ENOENT) {
+    CLS_ERR("error removing image map %s: %s", key.c_str(),
+            cpp_strerror(r).c_str());
+    return r;
+  }
+
+  return 0;
+}
+
 /**
  * Initialize the header with basic metadata.
  * Everything is stored as key/value pairs as omaps in the header object.
@@ -5196,6 +5343,9 @@ CLS_INIT(rbd)
   cls_method_handle_t h_mirror_instances_list;
   cls_method_handle_t h_mirror_instances_add;
   cls_method_handle_t h_mirror_instances_remove;
+  cls_method_handle_t h_mirror_image_map_list;
+  cls_method_handle_t h_mirror_image_map_update;
+  cls_method_handle_t h_mirror_image_map_remove;
   cls_method_handle_t h_group_create;
   cls_method_handle_t h_group_dir_list;
   cls_method_handle_t h_group_dir_add;
@@ -5447,6 +5597,15 @@ CLS_INIT(rbd)
                           CLS_METHOD_RD | CLS_METHOD_WR,
                           mirror_instances_remove,
                           &h_mirror_instances_remove);
+  cls_register_cxx_method(h_class, "mirror_image_map_list",
+                          CLS_METHOD_RD, mirror_image_map_list,
+                          &h_mirror_image_map_list);
+  cls_register_cxx_method(h_class, "mirror_image_map_update",
+                          CLS_METHOD_WR, mirror_image_map_update,
+                          &h_mirror_image_map_update);
+  cls_register_cxx_method(h_class, "mirror_image_map_remove",
+                          CLS_METHOD_WR, mirror_image_map_remove,
+                          &h_mirror_image_map_remove);
   /* methods for the consistency groups feature */
   cls_register_cxx_method(h_class, "group_create",
                          CLS_METHOD_RD | CLS_METHOD_WR,
index 0a3ee5555d570c9208ef35693056b770211060d6..8da8b8d5a3215e643e8ad85f9f86be35ae492f85 100644 (file)
@@ -1870,6 +1870,44 @@ namespace librbd {
       return ioctx->operate(RBD_MIRROR_LEADER, &op);
     }
 
+    void mirror_image_map_list_start(librados::ObjectReadOperation *op,
+                                     const std::string &start_after,
+                                     uint64_t max_read) {
+      bufferlist bl;
+      ::encode(start_after, bl);
+      ::encode(max_read, bl);
+
+      op->exec("rbd", "mirror_image_map_list", bl);
+    }
+
+    int mirror_image_map_list_finish(bufferlist::iterator *iter,
+                                     std::map<std::string, cls::rbd::MirrorImageMap> *image_mapping) {
+      try {
+        ::decode(*image_mapping, *iter);
+      } catch (const buffer::error &err) {
+        return -EBADMSG;
+      }
+      return 0;
+    }
+
+    void mirror_image_map_update(librados::ObjectWriteOperation *op,
+                                 const std::string &global_image_id,
+                                 const cls::rbd::MirrorImageMap &image_map) {
+      bufferlist bl;
+      ::encode(global_image_id, bl);
+      ::encode(image_map, bl);
+
+      op->exec("rbd", "mirror_image_map_update", bl);
+    }
+
+    void mirror_image_map_remove(librados::ObjectWriteOperation *op,
+                                 const std::string &global_image_id) {
+      bufferlist bl;
+      ::encode(global_image_id, bl);
+
+      op->exec("rbd", "mirror_image_map_remove", bl);
+    }
+
     // Consistency groups functions
     int group_create(librados::IoCtx *ioctx, const std::string &oid)
     {
index ed2c02c714e10c1a40921ae8d9f3a90bd0c12831..d84351ece24b2ec2a63207e7fa3419c1b7960b37 100644 (file)
@@ -382,6 +382,18 @@ namespace librbd {
     int mirror_instances_remove(librados::IoCtx *ioctx,
                                 const std::string &instance_id);
 
+    // image mapping related routines
+    void mirror_image_map_list_start(librados::ObjectReadOperation *op,
+                                     const std::string &start_after,
+                                     uint64_t max_read);
+    int mirror_image_map_list_finish(bufferlist::iterator *iter,
+                                     std::map<std::string, cls::rbd::MirrorImageMap> *image_mapping);
+    void mirror_image_map_update(librados::ObjectWriteOperation *op,
+                                 const std::string &global_image_id,
+                                 const cls::rbd::MirrorImageMap &image_map);
+    void mirror_image_map_remove(librados::ObjectWriteOperation *op,
+                                 const std::string &global_image_id);
+
     // Consistency groups functions
     int group_create(librados::IoCtx *ioctx, const std::string &oid);
     int group_dir_list(librados::IoCtx *ioctx, const std::string &oid,
index 81b12a0fc0b1d290bdf0891ce081f2a494526a41..e02582da13d0400da5b2e64a7caeec14948ba2b7 100644 (file)
@@ -479,5 +479,50 @@ void TrashImageSpec::dump(Formatter *f) const {
   f->dump_unsigned("deferment_end_time", deferment_end_time);
 }
 
+void MirrorImageMap::encode(bufferlist &bl) const {
+  ENCODE_START(1, 1, bl);
+  ::encode(instance_id, bl);
+  ::encode(data, bl);
+  ENCODE_FINISH(bl);
+}
+
+void MirrorImageMap::decode(bufferlist::iterator &it) {
+  DECODE_START(1, it);
+  ::decode(instance_id, it);
+  ::decode(data, it);
+  DECODE_FINISH(it);
+}
+
+void MirrorImageMap::dump(Formatter *f) const {
+  f->dump_string("instance_id", instance_id);
+
+  std::stringstream data_ss;
+  data.hexdump(data_ss);
+  f->dump_string("data", data_ss.str());
+}
+
+void MirrorImageMap::generate_test_instances(
+  std::list<MirrorImageMap*> &o) {
+  bufferlist data;
+  data.append(std::string(128, '1'));
+
+  o.push_back(new MirrorImageMap("uuid-123", data));
+  o.push_back(new MirrorImageMap("uuid-abc", data));
+}
+
+bool MirrorImageMap::operator==(const MirrorImageMap &rhs) const {
+  return instance_id == rhs.instance_id && data.contents_equal(data);
+}
+
+bool MirrorImageMap::operator<(const MirrorImageMap &rhs) const {
+  return  instance_id < rhs.instance_id;
+}
+
+std::ostream& operator<<(std::ostream& os,
+                         const MirrorImageMap &image_map) {
+  return os << "["
+            << "instance_id=" << image_map.instance_id << "]";
+}
+
 } // namespace rbd
 } // namespace cls
index 7d8d1abcad2dd5c6d8704547d7647e12c9408db6..a7924e3253d484e96a9fb01d77aed5b656f14ceb 100644 (file)
@@ -364,6 +364,33 @@ struct TrashImageSpec {
 };
 WRITE_CLASS_ENCODER(TrashImageSpec);
 
+struct MirrorImageMap {
+  MirrorImageMap() {
+  }
+
+  MirrorImageMap(const std::string &instance_id,
+                 const bufferlist &data)
+    : instance_id(instance_id),
+      data(data) {
+  }
+
+  std::string instance_id;
+  bufferlist data;
+
+  void encode(bufferlist &bl) const;
+  void decode(bufferlist::iterator &it);
+  void dump(Formatter *f) const;
+
+  static void generate_test_instances(std::list<MirrorImageMap*> &o);
+
+  bool operator==(const MirrorImageMap &rhs) const;
+  bool operator<(const MirrorImageMap &rhs) const;
+};
+
+std::ostream& operator<<(std::ostream& os, const MirrorImageMap &image_map);
+
+WRITE_CLASS_ENCODER(MirrorImageMap);
+
 } // namespace rbd
 } // namespace cls
 
index b4da4cadd355f1f57549bb2be7b4479185445cc3..2a5db3e3c7e8f45978a03508a6ce2c0115b4c7ca 100644 (file)
@@ -397,6 +397,7 @@ TYPE(cls_rbd_snap)
 #include "cls/rbd/cls_rbd_types.h"
 TYPE(cls::rbd::MirrorPeer)
 TYPE(cls::rbd::MirrorImage)
+TYPE(cls::rbd::MirrorImageMap)
 #endif
 
 #endif