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

librbd: cannot copy all image-metas if we have more than 64 key/value pairs #18328

Merged
merged 2 commits into from Oct 27, 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
26 changes: 18 additions & 8 deletions src/librbd/internal.cc
Expand Up @@ -1900,18 +1900,28 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) {
return -EINVAL;
}
int r;
const uint32_t MAX_KEYS = 64;
map<string, bufferlist> pairs;
std::string last_key = "";
bool more_results = true;

r = cls_client::metadata_list(&src->md_ctx, src->header_oid, "", 0, &pairs);
if (r < 0 && r != -EOPNOTSUPP && r != -EIO) {
lderr(cct) << "couldn't list metadata: " << cpp_strerror(r) << dendl;
return r;
} else if (r == 0 && !pairs.empty()) {
r = cls_client::metadata_set(&dest->md_ctx, dest->header_oid, pairs);
if (r < 0) {
lderr(cct) << "couldn't set metadata: " << cpp_strerror(r) << dendl;
while (more_results) {
r = cls_client::metadata_list(&src->md_ctx, src->header_oid, last_key, 0, &pairs);
if (r < 0 && r != -EOPNOTSUPP && r != -EIO) {
lderr(cct) << "couldn't list metadata: " << cpp_strerror(r) << dendl;
return r;
} else if (r == 0 && !pairs.empty()) {
r = cls_client::metadata_set(&dest->md_ctx, dest->header_oid, pairs);
if (r < 0) {
lderr(cct) << "couldn't set metadata: " << cpp_strerror(r) << dendl;
return r;
}

last_key = pairs.rbegin()->first;
}

more_results = (pairs.size() == MAX_KEYS);
pairs.clear();
}

ZTracer::Trace trace;
Expand Down
97 changes: 96 additions & 1 deletion src/test/librbd/test_librbd.cc
Expand Up @@ -933,6 +933,8 @@ TEST_F(TestLibRBD, TestCopy)
rados_ioctx_create(_cluster, create_pool(true).c_str(), &ioctx);

rbd_image_t image;
rbd_image_t image2;
rbd_image_t image3;
int order = 0;
std::string name = get_temp_image_name();
std::string name2 = get_temp_image_name();
Expand All @@ -943,13 +945,69 @@ TEST_F(TestLibRBD, TestCopy)
ASSERT_EQ(0, create_image(ioctx, name.c_str(), size, &order));
ASSERT_EQ(0, rbd_open(ioctx, name.c_str(), &image, NULL));
ASSERT_EQ(1, test_ls(ioctx, 1, name.c_str()));

size_t sum_key_len = 0;
size_t sum_value_len = 0;
std::string key;
std::string val;
for (int i = 1; i <= 70; i++) {
key = "key" + stringify(i);
val = "value" + stringify(i);
ASSERT_EQ(0, rbd_metadata_set(image, key.c_str(), val.c_str()));

sum_key_len += (key.size() + 1);
sum_value_len += (val.size() + 1);
}

char keys[1024];
char vals[1024];
size_t keys_len = sizeof(keys);
size_t vals_len = sizeof(vals);

char value[1024];
size_t value_len = sizeof(value);

ASSERT_EQ(0, rbd_copy(image, ioctx, name2.c_str()));
ASSERT_EQ(2, test_ls(ioctx, 2, name.c_str(), name2.c_str()));
ASSERT_EQ(0, rbd_open(ioctx, name2.c_str(), &image2, NULL));
ASSERT_EQ(0, rbd_metadata_list(image2, "", 70, keys, &keys_len, vals,
&vals_len));
ASSERT_EQ(keys_len, sum_key_len);
ASSERT_EQ(vals_len, sum_value_len);

for (int i = 1; i <= 70; i++) {
key = "key" + stringify(i);
val = "value" + stringify(i);
ASSERT_EQ(0, rbd_metadata_get(image2, key.c_str(), value, &value_len));
ASSERT_STREQ(val.c_str(), value);

value_len = sizeof(value);
}

ASSERT_EQ(0, rbd_copy_with_progress(image, ioctx, name3.c_str(),
print_progress_percent, NULL));
ASSERT_EQ(3, test_ls(ioctx, 3, name.c_str(), name2.c_str(), name3.c_str()));

keys_len = sizeof(keys);
vals_len = sizeof(vals);
ASSERT_EQ(0, rbd_open(ioctx, name3.c_str(), &image3, NULL));
ASSERT_EQ(0, rbd_metadata_list(image3, "", 70, keys, &keys_len, vals,
&vals_len));
ASSERT_EQ(keys_len, sum_key_len);
ASSERT_EQ(vals_len, sum_value_len);

for (int i = 1; i <= 70; i++) {
key = "key" + stringify(i);
val = "value" + stringify(i);
ASSERT_EQ(0, rbd_metadata_get(image3, key.c_str(), value, &value_len));
ASSERT_STREQ(val.c_str(), value);

value_len = sizeof(value);
}

ASSERT_EQ(0, rbd_close(image));
ASSERT_EQ(0, rbd_close(image2));
ASSERT_EQ(0, rbd_close(image3));
rados_ioctx_destroy(ioctx);
}

Expand All @@ -972,6 +1030,8 @@ TEST_F(TestLibRBD, TestCopyPP)
{
librbd::RBD rbd;
librbd::Image image;
librbd::Image image2;
librbd::Image image3;
int order = 0;
std::string name = get_temp_image_name();
std::string name2 = get_temp_image_name();
Expand All @@ -981,12 +1041,47 @@ TEST_F(TestLibRBD, TestCopyPP)

ASSERT_EQ(0, create_image_pp(rbd, ioctx, name.c_str(), size, &order));
ASSERT_EQ(0, rbd.open(ioctx, image, name.c_str(), NULL));

std::string key;
std::string val;
for (int i = 1; i <= 70; i++) {
key = "key" + stringify(i);
val = "value" + stringify(i);
ASSERT_EQ(0, image.metadata_set(key, val));
}

ASSERT_EQ(1, test_ls_pp(rbd, ioctx, 1, name.c_str()));
ASSERT_EQ(0, image.copy(ioctx, name2.c_str()));
ASSERT_EQ(2, test_ls_pp(rbd, ioctx, 2, name.c_str(), name2.c_str()));
ASSERT_EQ(0, rbd.open(ioctx, image2, name2.c_str(), NULL));

map<string, bufferlist> pairs;
std::string value;
ASSERT_EQ(0, image2.metadata_list("", 70, &pairs));
ASSERT_EQ(70U, pairs.size());

for (int i = 1; i <= 70; i++) {
key = "key" + stringify(i);
val = "value" + stringify(i);
ASSERT_EQ(0, image2.metadata_get(key.c_str(), &value));
ASSERT_STREQ(val.c_str(), value.c_str());
}

ASSERT_EQ(0, image.copy_with_progress(ioctx, name3.c_str(), pp));
ASSERT_EQ(3, test_ls_pp(rbd, ioctx, 3, name.c_str(), name2.c_str(),
name3.c_str()));
name3.c_str()));
ASSERT_EQ(0, rbd.open(ioctx, image3, name3.c_str(), NULL));

pairs.clear();
ASSERT_EQ(0, image3.metadata_list("", 70, &pairs));
ASSERT_EQ(70U, pairs.size());

for (int i = 1; i <= 70; i++) {
key = "key" + stringify(i);
val = "value" + stringify(i);
ASSERT_EQ(0, image3.metadata_get(key.c_str(), &value));
ASSERT_STREQ(val.c_str(), value.c_str());
}
}

ioctx.close();
Expand Down