Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rbd-mirror A/A: introduce basic image mapping policy #15691

Merged
merged 2 commits into from
Aug 18, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
159 changes: 159 additions & 0 deletions src/cls/rbd/cls_rbd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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

/**
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
38 changes: 38 additions & 0 deletions src/cls/rbd/cls_rbd_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
12 changes: 12 additions & 0 deletions src/cls/rbd/cls_rbd_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
45 changes: 45 additions & 0 deletions src/cls/rbd/cls_rbd_types.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
27 changes: 27 additions & 0 deletions src/cls/rbd/cls_rbd_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions src/test/encoding/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions src/tools/rbd_mirror/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ set(rbd_mirror_internal
ServiceDaemon.cc
Threads.cc
types.cc
image_map/LoadRequest.cc
image_map/UpdateRequest.cc
image_replayer/BootstrapRequest.cc
image_replayer/CloseImageRequest.cc
image_replayer/CreateImageRequest.cc
Expand All @@ -38,6 +40,7 @@ set(rbd_mirror_internal
image_sync/SyncPointPruneRequest.cc
pool_watcher/RefreshImagesRequest.cc
service_daemon/Types.cc)

add_library(rbd_mirror_internal STATIC
${rbd_mirror_internal})

Expand Down