From: Venky Shankar Date: Mon, 31 Jul 2017 05:58:11 +0000 (-0400) Subject: rbd-mirror: track on-disk image to instance map X-Git-Tag: v13.0.0~73^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=64fa2c12c767f799913bab75f89540da3b236128;p=ceph.git rbd-mirror: track on-disk image to instance map Signed-off-by: Venky Shankar --- diff --git a/src/cls/rbd/cls_rbd.cc b/src/cls/rbd/cls_rbd.cc index 0c2d7aee595e..2ab186bf6aa2 100644 --- a/src/cls/rbd/cls_rbd.cc +++ b/src/cls/rbd/cls_rbd.cc @@ -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 *image_mapping) { + bool more = true; + std::string last_read = mirror_image_map_key(start_after); + + while (more && image_mapping->size() < max_return) { + std::map 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: 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 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, diff --git a/src/cls/rbd/cls_rbd_client.cc b/src/cls/rbd/cls_rbd_client.cc index 0a3ee5555d57..8da8b8d5a321 100644 --- a/src/cls/rbd/cls_rbd_client.cc +++ b/src/cls/rbd/cls_rbd_client.cc @@ -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 *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) { diff --git a/src/cls/rbd/cls_rbd_client.h b/src/cls/rbd/cls_rbd_client.h index ed2c02c714e1..d84351ece24b 100644 --- a/src/cls/rbd/cls_rbd_client.h +++ b/src/cls/rbd/cls_rbd_client.h @@ -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 *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, diff --git a/src/cls/rbd/cls_rbd_types.cc b/src/cls/rbd/cls_rbd_types.cc index 81b12a0fc0b1..e02582da13d0 100644 --- a/src/cls/rbd/cls_rbd_types.cc +++ b/src/cls/rbd/cls_rbd_types.cc @@ -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 &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 diff --git a/src/cls/rbd/cls_rbd_types.h b/src/cls/rbd/cls_rbd_types.h index 7d8d1abcad2d..a7924e3253d4 100644 --- a/src/cls/rbd/cls_rbd_types.h +++ b/src/cls/rbd/cls_rbd_types.h @@ -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 &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 diff --git a/src/test/encoding/types.h b/src/test/encoding/types.h index b4da4cadd355..2a5db3e3c7e8 100644 --- a/src/test/encoding/types.h +++ b/src/test/encoding/types.h @@ -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