]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
cls_rbd: mirror_image_list should return global image id 8297/head
authorJason Dillaman <dillaman@redhat.com>
Thu, 24 Mar 2016 12:46:54 +0000 (08:46 -0400)
committerJason Dillaman <dillaman@redhat.com>
Thu, 24 Mar 2016 13:02:13 +0000 (09:02 -0400)
The global image id is needed to crosslink images when an image is
replicated between multiple clusters.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/cls/rbd/cls_rbd.cc
src/cls/rbd/cls_rbd_client.cc
src/cls/rbd/cls_rbd_client.h
src/test/cls_rbd/test_cls_rbd.cc
src/tools/rbd_mirror/PoolWatcher.cc

index 036ad8a6830f3fb622e234d9ff4ea736bc5b5e46..67f0aa87e57117e5d834855260ba8957e64e42a4 100644 (file)
@@ -3046,28 +3046,6 @@ int write_peer(cls_method_context_t hctx, const std::string &id,
   return 0;
 }
 
-int image_list_ids(cls_method_context_t hctx, vector<string> *image_ids) {
-  string last_read = IMAGE_KEY_PREFIX;
-  int max_read = RBD_MAX_KEYS_READ;
-  int r = max_read;
-  while (r == max_read) {
-    set<string> keys;
-    r = cls_cxx_map_get_keys(hctx, last_read, max_read, &keys);
-    if (r < 0) {
-      CLS_ERR("error reading mirrored images: %s", cpp_strerror(r).c_str());
-      return r;
-    }
-
-    for (auto &image_key : keys) {
-      if (0 != image_key.compare(0, IMAGE_KEY_PREFIX.size(), IMAGE_KEY_PREFIX)) {
-       return 0;
-      }
-      image_ids->push_back(image_key.substr(IMAGE_KEY_PREFIX.size()));
-    }
-  }
-  return 0;
-}
-
 int image_get(cls_method_context_t hctx, const string &image_id,
              cls::rbd::MirrorImage *mirror_image) {
   bufferlist bl;
@@ -3486,21 +3464,66 @@ int mirror_peer_set_cluster(cls_method_context_t hctx, bufferlist *in,
 
 /**
  * Input:
- * none
+ * @param start_after which name to begin listing after
+ *        (use the empty string to start at the beginning)
+ * @param max_return the maximum number of names to list
  *
  * Output:
- * @param std::vector<std::string>: collection of image_ids
+ * @param std::map<std::string, std::string>: local id to global id map
  * @returns 0 on success, negative error code on failure
  */
 int mirror_image_list(cls_method_context_t hctx, bufferlist *in,
                     bufferlist *out) {
-  vector<string> image_ids;
-  int r = mirror::image_list_ids(hctx, &image_ids);
-  if (r < 0) {
-    return r;
+  std::string start_after;
+  uint64_t max_return;
+  try {
+    bufferlist::iterator iter = in->begin();
+    ::decode(start_after, iter);
+    ::decode(max_return, iter);
+  } catch (const buffer::error &err) {
+    return -EINVAL;
+  }
+
+  int max_read = RBD_MAX_KEYS_READ;
+  int r = max_read;
+  std::map<std::string, std::string> mirror_images;
+  std::string last_read = mirror::image_key(start_after);
+
+  while (r == max_read && mirror_images.size() < max_return) {
+    std::map<std::string, bufferlist> vals;
+    CLS_LOG(20, "last_read = '%s'", last_read.c_str());
+    r = cls_cxx_map_get_vals(hctx, last_read, mirror::IMAGE_KEY_PREFIX,
+                            max_read, &vals);
+    if (r < 0) {
+      CLS_ERR("error reading mirror image directory by name: %s",
+              cpp_strerror(r).c_str());
+      return r;
+    }
+
+    for (auto it = vals.begin(); it != vals.end(); ++it) {
+      const std::string &image_id =
+        it->first.substr(mirror::IMAGE_KEY_PREFIX.size());
+      cls::rbd::MirrorImage mirror_image;
+      bufferlist::iterator iter = it->second.begin();
+      try {
+       ::decode(mirror_image, iter);
+      } catch (const buffer::error &err) {
+       CLS_ERR("could not decode mirror image payload of image '%s'",
+                image_id.c_str());
+       return -EIO;
+      }
+
+      mirror_images[image_id] = mirror_image.global_image_id;
+      if (mirror_images.size() >= max_return) {
+       break;
+      }
+    }
+    if (!vals.empty()) {
+      last_read = mirror::image_key(mirror_images.rbegin()->first);
+    }
   }
 
-  ::encode(image_ids, *out);
+  ::encode(mirror_images, *out);
   return 0;
 }
 
index 30b872b4d8c16647dab30782c64fb07866e6a984..a3dc011503416d421396ddd2b6aa53ecd2db3a83 100644 (file)
@@ -1132,8 +1132,12 @@ namespace librbd {
     }
 
     int mirror_image_list(librados::IoCtx *ioctx,
-                         std::vector<std::string> *image_ids) {
+                         const std::string &start, uint64_t max_return,
+                         std::map<std::string, std::string> *mirror_image_ids) {
       bufferlist in_bl;
+      ::encode(start, in_bl);
+      ::encode(max_return, in_bl);
+
       bufferlist out_bl;
       int r = ioctx->exec(RBD_MIRRORING, "rbd", "mirror_image_list", in_bl,
                          out_bl);
@@ -1141,10 +1145,9 @@ namespace librbd {
         return r;
       }
 
-      image_ids->clear();
       try {
         bufferlist::iterator bl_it = out_bl.begin();
-        ::decode(*image_ids, bl_it);
+        ::decode(*mirror_image_ids, bl_it);
       } catch (const buffer::error &err) {
         return -EBADMSG;
       }
index 3248f78998c8318cb53904b0762ef47a9e6c3f8f..de9ac7cf8189c60081f3fda30ec3186c8f283ec8 100644 (file)
@@ -228,7 +228,8 @@ namespace librbd {
                                 const std::string &uuid,
                                 const std::string &cluster_name);
     int mirror_image_list(librados::IoCtx *ioctx,
-                         std::vector<std::string> *image_ids);
+                         const std::string &start, uint64_t max_return,
+                          std::map<std::string, std::string> *mirror_image_ids);
     int mirror_image_get(librados::IoCtx *ioctx, const std::string &image_id,
                         cls::rbd::MirrorImage *mirror_image);
     int mirror_image_set(librados::IoCtx *ioctx, const std::string &image_id,
index cd8283e541011b0dc16fc19b0fd3ad0a5567f71b..a2055ecc3b364f6a8d7055de3554e09f535419d7 100644 (file)
@@ -1373,8 +1373,8 @@ TEST_F(TestClsRbd, mirror_image) {
   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
   ioctx.remove(RBD_MIRRORING);
 
-  vector<string> image_ids;
-  ASSERT_EQ(-ENOENT, mirror_image_list(&ioctx, &image_ids));
+  std::map<std::string, std::string> mirror_image_ids;
+  ASSERT_EQ(-ENOENT, mirror_image_list(&ioctx, "", 0, &mirror_image_ids));
 
   cls::rbd::MirrorImage image1("uuid1", cls::rbd::MIRROR_IMAGE_STATE_ENABLED);
   cls::rbd::MirrorImage image2("uuid2", cls::rbd::MIRROR_IMAGE_STATE_DISABLING);
@@ -1394,17 +1394,21 @@ TEST_F(TestClsRbd, mirror_image) {
   ASSERT_EQ(0, mirror_image_get(&ioctx, "image_id3", &read_image));
   ASSERT_EQ(read_image, image3);
 
-  ASSERT_EQ(0, mirror_image_list(&ioctx, &image_ids));
-  vector<string> expected_image_ids = {
-    {"image_id1"}, {"image_id2"}, {"image_id3"}};
-  ASSERT_EQ(expected_image_ids, image_ids);
+  ASSERT_EQ(0, mirror_image_list(&ioctx, "", 1, &mirror_image_ids));
+  std::map<std::string, std::string> expected_mirror_image_ids = {
+    {"image_id1", "uuid1"}};
+  ASSERT_EQ(expected_mirror_image_ids, mirror_image_ids);
+
+  ASSERT_EQ(0, mirror_image_list(&ioctx, "image_id1", 2, &mirror_image_ids));
+  expected_mirror_image_ids = {{"image_id2", "uuid2"}, {"image_id3", "uuid3"}};
+  ASSERT_EQ(expected_mirror_image_ids, mirror_image_ids);
 
   ASSERT_EQ(0, mirror_image_remove(&ioctx, "image_id2"));
   ASSERT_EQ(-EBUSY, mirror_image_remove(&ioctx, "image_id1"));
 
-  ASSERT_EQ(0, mirror_image_list(&ioctx, &image_ids));
-  expected_image_ids = {{"image_id1"}, {"image_id3"}};
-  ASSERT_EQ(expected_image_ids, image_ids);
+  ASSERT_EQ(0, mirror_image_list(&ioctx, "", 3, &mirror_image_ids));
+  expected_mirror_image_ids = {{"image_id1", "uuid1"}, {"image_id3", "uuid3"}};
+  ASSERT_EQ(expected_mirror_image_ids, mirror_image_ids);
 
   image1.state = cls::rbd::MIRROR_IMAGE_STATE_DISABLING;
   image3.state = cls::rbd::MIRROR_IMAGE_STATE_DISABLING;
@@ -1415,7 +1419,7 @@ TEST_F(TestClsRbd, mirror_image) {
   ASSERT_EQ(0, mirror_image_remove(&ioctx, "image_id1"));
   ASSERT_EQ(0, mirror_image_remove(&ioctx, "image_id3"));
 
-  ASSERT_EQ(0, mirror_image_list(&ioctx, &image_ids));
-  expected_image_ids = {};
-  ASSERT_EQ(expected_image_ids, image_ids);
+  ASSERT_EQ(0, mirror_image_list(&ioctx, "", 3, &mirror_image_ids));
+  expected_mirror_image_ids = {};
+  ASSERT_EQ(expected_mirror_image_ids, mirror_image_ids);
 }
index 74b54cd544f5c70bb9246f5bd816d48a0fd6c8b5..2e147f7f34d2a0e4e8b44769ae0dfacce1e2ca1b 100644 (file)
@@ -105,19 +105,28 @@ void PoolWatcher::refresh_images(bool reschedule)
       continue;
     }
 
-    // only format 2 images can be mirrored, so only check the format
-    // 2 rbd_directory structure
-    std::vector<std::string> image_ids;
-    r = mirror_image_list(&ioctx, &image_ids);
-    if (r < 0) {
-      derr << "error listing mirrored images in pool " << pool_name << ": "
-           << cpp_strerror(r) << dendl;
-      continue;
-    }
+    std::set<std::string> image_ids;
+    std::string last_read = "";
+    int max_read = 1024;
+    do {
+      std::map<std::string, std::string> mirror_images;
+      r =  mirror_image_list(&ioctx, last_read, max_read, &mirror_images);
+      if (r < 0) {
+        derr << "error listing mirrored image directory: "
+             << cpp_strerror(r) << dendl;
+        continue;
+      }
+      for (auto it = mirror_images.begin(); it != mirror_images.end(); ++it) {
+        image_ids.insert(it->first);
+      }
+      if (!mirror_images.empty()) {
+        last_read = mirror_images.rbegin()->first;
+      }
+      r = mirror_images.size();
+    } while (r == max_read);
 
     if (!image_ids.empty()) {
-      std::set<std::string> image_set(image_ids.begin(), image_ids.end());
-      images[pool_id] = std::move(image_set);
+      images[pool_id] = std::move(image_ids);
     }
   }