]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: Skip tier pools in list_children and snap_unprotect 2619/head
authorAdam Crume <adamcrume@gmail.com>
Tue, 23 Sep 2014 22:41:26 +0000 (15:41 -0700)
committerAdam Crume <adamcrume@gmail.com>
Wed, 1 Oct 2014 18:31:33 +0000 (11:31 -0700)
Fixes: #8187
Signed-off-by: Adam Crume <adamcrume@gmail.com>
src/librbd/internal.cc
src/test/librbd/test_librbd.cc

index 8b4ea9e10ec801a8e56e5ba9d2f16de00601edb0..545e603e88430b16366385495ba5e0cc3bb15ef2 100644 (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) {
index 6a61f3fe3a48c2902c3c706deb7c26bac1515e22..3f565660ac3d414489abe0daf71bd4e2c3369ce4 100644 (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;