} rbd_mirror_image_status_state_t;
typedef struct {
+ char *name;
+ rbd_mirror_image_info_t info;
rbd_mirror_image_status_state_t state;
char *description;
time_t last_update;
const char *uuid,
const char *cluster_name);
CEPH_RBD_API int rbd_mirror_image_status_list(rados_ioctx_t io_ctx,
- const char *start, size_t max, char **image_names,
- rbd_mirror_image_info_t *images, rbd_mirror_image_status_t *image_statuses,
- size_t *len);
+ const char *start_id, size_t max,
+ char **image_ids,
+ rbd_mirror_image_status_t *images,
+ size_t *len);
+CEPH_RBD_API void rbd_mirror_image_status_list_cleanup(char **image_ids,
+ rbd_mirror_image_status_t *images, size_t len);
CEPH_RBD_API int rbd_mirror_image_status_summary(rados_ioctx_t io_ctx,
rbd_mirror_image_status_state_t *states, int *counts, size_t *maxlen);
rbd_mirror_image_info_t *mirror_image_info,
size_t info_size);
CEPH_RBD_API int rbd_mirror_image_get_status(rbd_image_t image,
- rbd_mirror_image_status_t *mirror_image_status, size_t info_size);
+ rbd_mirror_image_status_t *mirror_image_status,
+ size_t status_size);
#ifdef __cplusplus
}
typedef rbd_mirror_image_status_state_t mirror_image_status_state_t;
typedef struct {
+ std::string name;
+ mirror_image_info_t info;
mirror_image_status_state_t state;
std::string description;
time_t last_update;
const std::string &client_name);
int mirror_peer_set_cluster(IoCtx& io_ctx, const std::string &uuid,
const std::string &cluster_name);
- int mirror_image_status_list(IoCtx& io_ctx, const std::string &start,
- size_t max, std::map<std::string, mirror_image_info_t> *images,
- std::map<std::string, mirror_image_status_t> *statuses);
+ int mirror_image_status_list(IoCtx& io_ctx, const std::string &start_id,
+ size_t max, std::map<std::string, mirror_image_status_t> *images);
int mirror_image_status_summary(IoCtx& io_ctx,
std::map<mirror_image_status_state_t, int> *states);
return -ERANGE;
}
+ mirror_image_info_t info;
+ int r = mirror_image_get_info(ictx, &info, sizeof(info));
+ if (r < 0) {
+ return r;
+ }
+
cls::rbd::MirrorImageStatus
s(cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN, "status not found");
- cls::rbd::MirrorImage image;
- int r = cls_client::mirror_image_get(&ictx->md_ctx, ictx->id, &image);
+ r = cls_client::mirror_image_status_get(&ictx->md_ctx, info.global_id, &s);
if (r < 0 && r != -ENOENT) {
- lderr(cct) << "failed to retrieve mirroring state: " << cpp_strerror(r)
- << dendl;
+ lderr(cct) << "failed to retrieve image mirror status: "
+ << cpp_strerror(r) << dendl;
return r;
}
- if (r == 0) {
- r = cls_client::mirror_image_status_get(&ictx->md_ctx,
- image.global_image_id, &s);
- if (r < 0 && r != -ENOENT) {
- lderr(cct) << "failed to retrieve image mirror status: "
- << cpp_strerror(r) << dendl;
- return r;
- }
- }
-
*status = mirror_image_status_t{
+ ictx->name,
+ info,
static_cast<mirror_image_status_state_t>(s.state),
s.description,
s.last_update.sec(),
return 0;
}
- int mirror_image_status_list(IoCtx& io_ctx, const std::string &start,
- size_t max, std::map<std::string, mirror_image_info_t> *images,
- std::map<std::string, mirror_image_status_t> *statuses) {
+ int mirror_image_status_list(IoCtx& io_ctx, const std::string &start_id,
+ size_t max, std::map<std::string, mirror_image_status_t> *images) {
CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
int r;
map<std::string, cls::rbd::MirrorImage> images_;
map<std::string, cls::rbd::MirrorImageStatus> statuses_;
- r = librbd::cls_client::mirror_image_status_list(&io_ctx, start, max,
+ r = librbd::cls_client::mirror_image_status_list(&io_ctx, start_id, max,
&images_, &statuses_);
if (r < 0) {
lderr(cct) << "Failed to list mirror image statuses: "
return r;
}
- cls::rbd::MirrorImageStatus
- unknown_status(cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN, "status not found");
+ cls::rbd::MirrorImageStatus unknown_status(
+ cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN, "status not found");
for (auto it = images_.begin(); it != images_.end(); ++it) {
auto &image_id = it->first;
<< ", using image id as name" << dendl;
image_name = image_id;
}
- (*images)[image_name] = mirror_image_info_t{
- info.global_image_id,
- static_cast<mirror_image_state_t>(info.state),
- false}; // XXX: To set "primary" properly would require additional call.
auto s_it = statuses_.find(image_id);
auto &s = s_it != statuses_.end() ? s_it->second : unknown_status;
- (*statuses)[image_name] = mirror_image_status_t{
+ (*images)[image_id] = mirror_image_status_t{
+ image_name,
+ mirror_image_info_t{
+ info.global_image_id,
+ static_cast<mirror_image_state_t>(info.state),
+ false}, // XXX: To set "primary" right would require an additional call.
static_cast<mirror_image_status_state_t>(s.state),
s.description,
s.last_update.sec(),
const std::string &client_name);
int mirror_peer_set_cluster(IoCtx& io_ctx, const std::string &uuid,
const std::string &cluster_name);
- int mirror_image_status_list(IoCtx& io_ctx, const std::string &start,
- size_t max, std::map<std::string, mirror_image_info_t> *images,
- std::map<std::string, mirror_image_status_t> *statuses);
+ int mirror_image_status_list(IoCtx& io_ctx, const std::string &start_id,
+ size_t max, std::map<std::string, mirror_image_status_t> *images);
int mirror_image_status_summary(IoCtx& io_ctx,
std::map<mirror_image_status_state_t, int> *states);
void mirror_image_status_cpp_to_c(const librbd::mirror_image_status_t &cpp_status,
rbd_mirror_image_status_t *c_status) {
+ c_status->name = strdup(cpp_status.name.c_str());
+ mirror_image_info_cpp_to_c(cpp_status.info, &c_status->info);
c_status->state = cpp_status.state;
c_status->description = strdup(cpp_status.description.c_str());
c_status->last_update = cpp_status.last_update;
return librbd::mirror_peer_set_cluster(io_ctx, uuid, cluster_name);
}
- int RBD::mirror_image_status_list(IoCtx& io_ctx, const std::string &start,
- size_t max, std::map<std::string, mirror_image_info_t> *images,
- std::map<std::string, mirror_image_status_t> *statuses) {
- return librbd::mirror_image_status_list(io_ctx, start, max, images,
- statuses);
+ int RBD::mirror_image_status_list(IoCtx& io_ctx, const std::string &start_id,
+ size_t max, std::map<std::string, mirror_image_status_t> *images) {
+ return librbd::mirror_image_status_list(io_ctx, start_id, max, images);
}
int RBD::mirror_image_status_summary(IoCtx& io_ctx,
return librbd::mirror_peer_set_cluster(io_ctx, uuid, cluster_name);
}
-extern "C" int rbd_mirror_image_status_list(rados_ioctx_t p, const char *start,
- size_t max, char **image_names, rbd_mirror_image_info_t *images,
- rbd_mirror_image_status_t *statuses, size_t *len) {
+extern "C" int rbd_mirror_image_status_list(rados_ioctx_t p,
+ const char *start_id, size_t max, char **image_ids,
+ rbd_mirror_image_status_t *images, size_t *len) {
librados::IoCtx io_ctx;
librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
- std::map<std::string, librbd::mirror_image_info_t> cpp_images;
- std::map<std::string, librbd::mirror_image_status_t> cpp_statuses;
+ std::map<std::string, librbd::mirror_image_status_t> cpp_images;
- int r = librbd::mirror_image_status_list(io_ctx, start, max, &cpp_images,
- &cpp_statuses);
+ int r = librbd::mirror_image_status_list(io_ctx, start_id, max, &cpp_images);
if (r < 0) {
return r;
}
size_t i = 0;
for (auto &it : cpp_images) {
assert(i < max);
- const std::string &image_name = it.first;
- image_names[i] = strdup(image_name.c_str());
- mirror_image_info_cpp_to_c(it.second, &images[i]);
- mirror_image_status_cpp_to_c(cpp_statuses[image_name], &statuses[i]);
+ const std::string &image_id = it.first;
+ image_ids[i] = strdup(image_id.c_str());
+ mirror_image_status_cpp_to_c(it.second, &images[i]);
i++;
}
*len = i;
return 0;
}
+extern "C" void rbd_mirror_image_status_list_cleanup(char **image_ids,
+ rbd_mirror_image_status_t *images, size_t len) {
+ for (size_t i = 0; i < len; i++) {
+ free(image_ids[i]);
+ free(images[i].name);
+ free(images[i].info.global_id);
+ free(images[i].description);
+ }
+}
+
extern "C" int rbd_mirror_image_status_summary(rados_ioctx_t p,
rbd_mirror_image_status_state_t *states, int *counts, size_t *maxlen) {
}
void check_mirroring_status(size_t *images_count) {
- std::map<std::string, librbd::mirror_image_info_t> images;
- std::map<std::string, librbd::mirror_image_status_t> statuses;
- ASSERT_EQ(0, m_rbd.mirror_image_status_list(m_ioctx, "", 4096, &images,
- &statuses));
- ASSERT_EQ(images.size(), statuses.size());
+ std::map<std::string, librbd::mirror_image_status_t> images;
+ ASSERT_EQ(0, m_rbd.mirror_image_status_list(m_ioctx, "", 4096, &images));
std::map<librbd::mirror_image_status_state_t, int> states;
ASSERT_EQ(0, m_rbd.mirror_image_status_summary(m_ioctx, &states));
false);
}
+TEST_F(TestMirroring, MirrorStatusList) {
+ std::vector<uint64_t>
+ features_vec(5, RBD_FEATURE_EXCLUSIVE_LOCK | RBD_FEATURE_JOURNALING);
+ setup_images_with_mirror_mode(RBD_MIRROR_MODE_POOL, features_vec);
+
+ std::string last_read = "";
+ std::map<std::string, librbd::mirror_image_status_t> images;
+ ASSERT_EQ(0, m_rbd.mirror_image_status_list(m_ioctx, last_read, 2, &images));
+ ASSERT_EQ(2U, images.size());
+
+ last_read = images.rbegin()->first;
+ images.clear();
+ ASSERT_EQ(0, m_rbd.mirror_image_status_list(m_ioctx, last_read, 2, &images));
+ ASSERT_EQ(2U, images.size());
+
+ last_read = images.rbegin()->first;
+ images.clear();
+ ASSERT_EQ(0, m_rbd.mirror_image_status_list(m_ioctx, last_read, 4096, &images));
+ ASSERT_EQ(1U, images.size());
+
+ last_read = images.rbegin()->first;
+ images.clear();
+ ASSERT_EQ(0, m_rbd.mirror_image_status_list(m_ioctx, last_read, 4096, &images));
+ ASSERT_EQ(0U, images.size());
+}
return r;
}
- librbd::mirror_image_info_t mirror_image;
- r = image.mirror_image_get_info(&mirror_image, sizeof(mirror_image));
- if (r < 0) {
- std::cerr << "rbd: failed to get global image id for image " << image_name
- << ": " << cpp_strerror(r) << std::endl;
- return r;
- }
-
- if (mirror_image.global_id.empty()) {
- std::cerr << "rbd: failed to get global image id for image " << image_name
- << std::endl;
- return -EINVAL;
- }
-
librbd::mirror_image_status_t status;
r = image.mirror_image_get_status(&status, sizeof(status));
if (r < 0) {
if (formatter != nullptr) {
formatter->open_object_section("image");
formatter->dump_string("name", image_name);
- formatter->dump_string("global_id", mirror_image.global_id);
+ formatter->dump_string("global_id", status.info.global_id);
formatter->dump_string("state", state);
formatter->dump_string("description", status.description);
formatter->dump_string("last_update", last_update);
formatter->flush(std::cout);
} else {
std::cout << image_name << ":\n"
- << " global_id: " << mirror_image.global_id << "\n"
+ << " global_id: " << status.info.global_id << "\n"
<< " state: " << state << "\n"
<< " description: " << status.description << "\n"
<< " last_update: " << last_update << std::endl;
std::string last_read = "";
int max_read = 1024;
do {
- map<std::string, librbd::mirror_image_info_t> mirror_images;
- map<std::string, librbd::mirror_image_status_t> statuses;
+ map<std::string, librbd::mirror_image_status_t> mirror_images;
r = rbd.mirror_image_status_list(io_ctx, last_read, max_read,
- &mirror_images, &statuses);
+ &mirror_images);
if (r < 0) {
std::cerr << "rbd: failed to list mirrored image directory: "
<< cpp_strerror(r) << std::endl;
return r;
}
for (auto it = mirror_images.begin(); it != mirror_images.end(); ++it) {
- const std::string &image_name = it->first;
- std::string &global_image_id = it->second.global_id;
- librbd::mirror_image_status_t &status = statuses[image_name];
+ librbd::mirror_image_status_t &status = it->second;
+ const std::string &image_name = status.name;
+ std::string &global_image_id = status.info.global_id;
std::string state = utils::mirror_image_status_state(status);
std::string last_update = utils::timestr(status.last_update);