From: Jason Dillaman Date: Thu, 24 Mar 2016 12:46:54 +0000 (-0400) Subject: cls_rbd: mirror_image_list should return global image id X-Git-Tag: v10.1.1~117^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=206cf5a56dd23d43fc098efea2346a7ddff33eaf;p=ceph.git cls_rbd: mirror_image_list should return global image id The global image id is needed to crosslink images when an image is replicated between multiple clusters. Signed-off-by: Jason Dillaman --- diff --git a/src/cls/rbd/cls_rbd.cc b/src/cls/rbd/cls_rbd.cc index 036ad8a6830f..67f0aa87e571 100644 --- a/src/cls/rbd/cls_rbd.cc +++ b/src/cls/rbd/cls_rbd.cc @@ -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 *image_ids) { - string last_read = IMAGE_KEY_PREFIX; - int max_read = RBD_MAX_KEYS_READ; - int r = max_read; - while (r == max_read) { - set 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: collection of image_ids + * @param std::map: 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 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 mirror_images; + std::string last_read = mirror::image_key(start_after); + + while (r == max_read && mirror_images.size() < max_return) { + std::map 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; } diff --git a/src/cls/rbd/cls_rbd_client.cc b/src/cls/rbd/cls_rbd_client.cc index 30b872b4d8c1..a3dc01150341 100644 --- a/src/cls/rbd/cls_rbd_client.cc +++ b/src/cls/rbd/cls_rbd_client.cc @@ -1132,8 +1132,12 @@ namespace librbd { } int mirror_image_list(librados::IoCtx *ioctx, - std::vector *image_ids) { + const std::string &start, uint64_t max_return, + std::map *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; } diff --git a/src/cls/rbd/cls_rbd_client.h b/src/cls/rbd/cls_rbd_client.h index 3248f78998c8..de9ac7cf8189 100644 --- a/src/cls/rbd/cls_rbd_client.h +++ b/src/cls/rbd/cls_rbd_client.h @@ -228,7 +228,8 @@ namespace librbd { const std::string &uuid, const std::string &cluster_name); int mirror_image_list(librados::IoCtx *ioctx, - std::vector *image_ids); + const std::string &start, uint64_t max_return, + std::map *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, diff --git a/src/test/cls_rbd/test_cls_rbd.cc b/src/test/cls_rbd/test_cls_rbd.cc index cd8283e54101..a2055ecc3b36 100644 --- a/src/test/cls_rbd/test_cls_rbd.cc +++ b/src/test/cls_rbd/test_cls_rbd.cc @@ -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 image_ids; - ASSERT_EQ(-ENOENT, mirror_image_list(&ioctx, &image_ids)); + std::map 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 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 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); } diff --git a/src/tools/rbd_mirror/PoolWatcher.cc b/src/tools/rbd_mirror/PoolWatcher.cc index 74b54cd544f5..2e147f7f34d2 100644 --- a/src/tools/rbd_mirror/PoolWatcher.cc +++ b/src/tools/rbd_mirror/PoolWatcher.cc @@ -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 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 image_ids; + std::string last_read = ""; + int max_read = 1024; + do { + std::map 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 image_set(image_ids.begin(), image_ids.end()); - images[pool_id] = std::move(image_set); + images[pool_id] = std::move(image_ids); } }