Merge pull request #2619 from ceph/wip-8187

librbd: Skip tier pools in list_children and snap_unprotect

Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
This commit is contained in:
Josh Durgin 2014-10-01 12:53:53 -07:00
commit ea434804b1
2 changed files with 139 additions and 1 deletions

View File

@ -418,10 +418,20 @@ namespace librbd {
for (std::list<string>::const_iterator it = pools.begin();
it != pools.end(); ++it) {
int64_t pool_id = rados.pool_lookup(it->c_str());
int64_t base_tier;
int r = rados.pool_get_base_tier(pool_id, &base_tier);
if (r < 0) {
return r;
}
if (base_tier != pool_id) {
// pool is a cache; skip it
continue;
}
IoCtx ioctx;
rados.ioctx_create(it->c_str(), ioctx);
set<string> image_ids;
int r = cls_client::get_children(&ioctx, RBD_CHILDREN,
r = cls_client::get_children(&ioctx, RBD_CHILDREN,
parent_spec, image_ids);
if (r < 0 && r != -ENOENT) {
lderr(cct) << "Error reading list of children from pool " << *it
@ -637,6 +647,16 @@ namespace librbd {
rados.pool_list(pools);
std::set<std::string> children;
for (std::list<std::string>::const_iterator it = pools.begin(); it != pools.end(); ++it) {
int64_t pool_id = rados.pool_lookup(it->c_str());
int64_t base_tier;
r = rados.pool_get_base_tier(pool_id, &base_tier);
if (r < 0) {
return r;
}
if (base_tier != pool_id) {
// pool is a cache; skip it
continue;
}
IoCtx pool_ioctx;
r = rados.ioctx_create(it->c_str(), pool_ioctx);
if (r < 0) {

View File

@ -1330,6 +1330,124 @@ TEST(LibRBD, ListChildren)
ASSERT_EQ(0, destroy_one_pool(pool_name2, &cluster));
}
TEST(LibRBD, ListChildrenTiered)
{
rados_t cluster;
string pool_name1 = get_temp_pool_name();
ASSERT_EQ("", create_one_pool(pool_name1, &cluster));
string pool_name2 = get_temp_pool_name();
ASSERT_EQ("", create_one_pool(pool_name2, &cluster));
string pool_name3 = get_temp_pool_name();
ASSERT_EQ("", create_one_pool(pool_name3, &cluster));
std::string cmdstr = "{\"prefix\": \"osd tier add\", \"pool\": \"" +
pool_name1 + "\", \"tierpool\":\"" + pool_name3 + "\", \"force_nonempty\":\"\"}";
char *cmd[1];
cmd[0] = (char *)cmdstr.c_str();
ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, NULL, 0, NULL, 0));
cmdstr = "{\"prefix\": \"osd tier cache-mode\", \"pool\": \"" +
pool_name3 + "\", \"mode\":\"writeback\"}";
cmd[0] = (char *)cmdstr.c_str();
ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, NULL, 0, NULL, 0));
cmdstr = "{\"prefix\": \"osd tier set-overlay\", \"pool\": \"" +
pool_name1 + "\", \"overlaypool\":\"" + pool_name3 + "\"}";
cmd[0] = (char *)cmdstr.c_str();
ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, NULL, 0, NULL, 0));
EXPECT_EQ(0, rados_wait_for_latest_osdmap(cluster));
rados_ioctx_t ioctx1, ioctx2;
rados_ioctx_create(cluster, pool_name1.c_str(), &ioctx1);
rados_ioctx_create(cluster, pool_name2.c_str(), &ioctx2);
int features = RBD_FEATURE_LAYERING;
rbd_image_t parent;
int order = 0;
// make a parent to clone from
ASSERT_EQ(0, create_image_full(ioctx1, "parent", 4<<20, &order,
false, features));
ASSERT_EQ(0, rbd_open(ioctx1, "parent", &parent, NULL));
// create a snapshot, reopen as the parent we're interested in
ASSERT_EQ(0, rbd_snap_create(parent, "parent_snap"));
ASSERT_EQ(0, rbd_snap_set(parent, "parent_snap"));
ASSERT_EQ(0, rbd_snap_protect(parent, "parent_snap"));
ASSERT_EQ(0, rbd_close(parent));
ASSERT_EQ(0, rbd_open(ioctx1, "parent", &parent, "parent_snap"));
ASSERT_EQ(0, rbd_clone(ioctx1, "parent", "parent_snap", ioctx2, "child1",
features, &order));
test_list_children(parent, 1, pool_name2.c_str(), "child1");
ASSERT_EQ(0, rbd_clone(ioctx1, "parent", "parent_snap", ioctx1, "child2",
features, &order));
test_list_children(parent, 2, pool_name2.c_str(), "child1",
pool_name1.c_str(), "child2");
// read from the cache to populate it
rbd_image_t tier_image;
ASSERT_EQ(0, rbd_open(ioctx1, "child2", &tier_image, NULL));
size_t len = 4 * 1024 * 1024;
char* buf = (char*)malloc(len);
ssize_t size = rbd_read(tier_image, 0, len, buf);
ASSERT_GT(size, 0);
free(buf);
ASSERT_EQ(0, rbd_close(tier_image));
ASSERT_EQ(0, rbd_clone(ioctx1, "parent", "parent_snap", ioctx2, "child3",
features, &order));
test_list_children(parent, 3, pool_name2.c_str(), "child1",
pool_name1.c_str(), "child2",
pool_name2.c_str(), "child3");
ASSERT_EQ(0, rbd_clone(ioctx1, "parent", "parent_snap", ioctx2, "child4",
features, &order));
test_list_children(parent, 4, pool_name2.c_str(), "child1",
pool_name1.c_str(), "child2",
pool_name2.c_str(), "child3",
pool_name2.c_str(), "child4");
ASSERT_EQ(0, rbd_remove(ioctx2, "child1"));
test_list_children(parent, 3,
pool_name1.c_str(), "child2",
pool_name2.c_str(), "child3",
pool_name2.c_str(), "child4");
ASSERT_EQ(0, rbd_remove(ioctx2, "child3"));
test_list_children(parent, 2,
pool_name1.c_str(), "child2",
pool_name2.c_str(), "child4");
ASSERT_EQ(0, rbd_remove(ioctx2, "child4"));
test_list_children(parent, 1,
pool_name1.c_str(), "child2");
ASSERT_EQ(0, rbd_remove(ioctx1, "child2"));
test_list_children(parent, 0);
ASSERT_EQ(0, rbd_snap_unprotect(parent, "parent_snap"));
ASSERT_EQ(0, rbd_snap_remove(parent, "parent_snap"));
ASSERT_EQ(0, rbd_close(parent));
ASSERT_EQ(0, rbd_remove(ioctx1, "parent"));
rados_ioctx_destroy(ioctx1);
rados_ioctx_destroy(ioctx2);
// destroy_one_pool also closes the cluster; do this one step at a time
cmdstr = "{\"prefix\": \"osd tier remove-overlay\", \"pool\": \"" +
pool_name1 + "\"}";
cmd[0] = (char *)cmdstr.c_str();
ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, NULL, 0, NULL, 0));
cmdstr = "{\"prefix\": \"osd tier remove\", \"pool\": \"" +
pool_name1 + "\", \"tierpool\":\"" + pool_name3 + "\"}";
cmd[0] = (char *)cmdstr.c_str();
ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, NULL, 0, NULL, 0));
ASSERT_EQ(0, rados_pool_delete(cluster, pool_name3.c_str()));
ASSERT_EQ(0, rados_pool_delete(cluster, pool_name1.c_str()));
ASSERT_EQ(0, destroy_one_pool(pool_name2, &cluster));
}
TEST(LibRBD, LockingPP)
{
librados::Rados rados;