From: Venky Shankar Date: Mon, 6 Mar 2017 06:52:27 +0000 (+0530) Subject: test / librbd: move non-public api usage tests to internal X-Git-Tag: v12.0.1~165^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=373573699c3d77e7675eb829a3d5933b4d8278f8;p=ceph.git test / librbd: move non-public api usage tests to internal Signed-off-by: Venky Shankar --- diff --git a/src/test/librbd/test_fixture.cc b/src/test/librbd/test_fixture.cc index 38614c1432b..73a66f43083 100644 --- a/src/test/librbd/test_fixture.cc +++ b/src/test/librbd/test_fixture.cc @@ -19,6 +19,7 @@ std::string TestFixture::_pool_name; librados::Rados TestFixture::_rados; +rados_t TestFixture::_cluster; uint64_t TestFixture::_image_number = 0; std::string TestFixture::_data_pool; @@ -26,6 +27,7 @@ TestFixture::TestFixture() : m_image_size(0) { } void TestFixture::SetUpTestCase() { + ASSERT_EQ("", connect_cluster(&_cluster)); _pool_name = get_temp_pool_name("test-librbd-"); ASSERT_EQ("", create_one_pool_pp(_pool_name, _rados)); @@ -40,6 +42,7 @@ void TestFixture::SetUpTestCase() { } void TestFixture::TearDownTestCase() { + rados_shutdown(_cluster); if (!_data_pool.empty()) { ASSERT_EQ(0, _rados.pool_delete(_data_pool.c_str())); } diff --git a/src/test/librbd/test_fixture.h b/src/test/librbd/test_fixture.h index faa20382f65..27eea61be44 100644 --- a/src/test/librbd/test_fixture.h +++ b/src/test/librbd/test_fixture.h @@ -39,6 +39,7 @@ public: static std::string _pool_name; static librados::Rados _rados; + static rados_t _cluster; static uint64_t _image_number; static std::string _data_pool; diff --git a/src/test/librbd/test_internal.cc b/src/test/librbd/test_internal.cc index fea96009931..c262a070527 100644 --- a/src/test/librbd/test_internal.cc +++ b/src/test/librbd/test_internal.cc @@ -3,6 +3,7 @@ #include "cls/rbd/cls_rbd_types.h" #include "test/librbd/test_fixture.h" #include "test/librbd/test_support.h" +#include "include/rbd/librbd.h" #include "librbd/ExclusiveLock.h" #include "librbd/ImageState.h" #include "librbd/ImageWatcher.h" @@ -12,6 +13,7 @@ #include "librbd/io/AioCompletion.h" #include "librbd/io/ImageRequest.h" #include "librbd/io/ImageRequestWQ.h" +#include "osdc/Striper.h" #include #include #include @@ -73,6 +75,51 @@ public: } }; +void generate_random_iomap(librbd::Image &image, int num_objects, int object_size, + int max_count, map &iomap) +{ + uint64_t stripe_unit, stripe_count; + + stripe_unit = image.get_stripe_unit(); + stripe_count = image.get_stripe_count(); + + while (max_count-- > 0) { + // generate random image offset based on base random object + // number and object offset and then map that back to an + // object number based on stripe unit and count. + uint64_t ono = rand() % num_objects; + uint64_t offset = rand() % (object_size - TEST_IO_SIZE); + uint64_t imageoff = (ono * object_size) + offset; + + file_layout_t layout; + layout.object_size = object_size; + layout.stripe_unit = stripe_unit; + layout.stripe_count = stripe_count; + + vector ex; + Striper::file_to_extents(g_ceph_context, 1, &layout, imageoff, TEST_IO_SIZE, 0, ex); + + // lets not worry if IO spans multiple extents (>1 object). in such + // as case we would perform the write multiple times to the same + // offset, but we record all objects that would be generated with + // this IO. TODO: fix this if such a need is required by your + // test. + vector::iterator it; + map curr_iomap; + for (it = ex.begin(); it != ex.end(); ++it) { + if (iomap.find((*it).objectno) != iomap.end()) { + break; + } + + curr_iomap.insert(make_pair((*it).objectno, imageoff)); + } + + if (it == ex.end()) { + iomap.insert(curr_iomap.begin(), curr_iomap.end()); + } + } +} + TEST_F(TestInternal, OpenByID) { REQUIRE_FORMAT_V2(); @@ -924,3 +971,260 @@ TEST_F(TestInternal, DiffIterateCloneOverwrite) { ASSERT_EQ(one, diff); } +TEST_F(TestInternal, TestCoR) +{ + REQUIRE_FEATURE(RBD_FEATURE_LAYERING); + + std::string config_value; + ASSERT_EQ(0, _rados.conf_get("rbd_clone_copy_on_read", config_value)); + if (config_value == "false") { + std::cout << "SKIPPING due to disabled rbd_copy_on_read" << std::endl; + return; + } + + m_image_name = get_temp_image_name(); + m_image_size = 4 << 20; + + int order = 12; // smallest object size is 4K + uint64_t features; + ASSERT_TRUE(get_features(&features)); + + ASSERT_EQ(0, create_image_full_pp(m_rbd, m_ioctx, m_image_name, m_image_size, + features, false, &order)); + + librbd::Image image; + ASSERT_EQ(0, m_rbd.open(m_ioctx, image, m_image_name.c_str(), NULL)); + + librbd::image_info_t info; + ASSERT_EQ(0, image.stat(info, sizeof(info))); + + const int object_num = info.size / info.obj_size; + printf("made parent image \"%s\": %ldK (%d * %ldK)\n", m_image_name.c_str(), + (unsigned long)m_image_size, object_num, info.obj_size/1024); + + // write something into parent + char test_data[TEST_IO_SIZE + 1]; + for (int i = 0; i < TEST_IO_SIZE; ++i) { + test_data[i] = (char) (rand() % (126 - 33) + 33); + } + test_data[TEST_IO_SIZE] = '\0'; + + // generate a random map which covers every objects with random + // offset + map write_tracker; + generate_random_iomap(image, object_num, info.obj_size, 100, write_tracker); + + printf("generated random write map:\n"); + for (map::iterator itr = write_tracker.begin(); + itr != write_tracker.end(); ++itr) + printf("\t [%-8ld, %-8ld]\n", + (unsigned long)itr->first, (unsigned long)itr->second); + + bufferlist bl; + bl.append(test_data, TEST_IO_SIZE); + + printf("write data based on random map\n"); + for (map::iterator itr = write_tracker.begin(); + itr != write_tracker.end(); ++itr) { + printf("\twrite object-%-4ld\t\n", (unsigned long)itr->first); + ASSERT_EQ(TEST_IO_SIZE, image.write(itr->second, TEST_IO_SIZE, bl)); + } + + bufferlist readbl; + printf("verify written data by reading\n"); + { + map::iterator itr = write_tracker.begin(); + printf("\tread object-%-4ld\n", (unsigned long)itr->first); + ASSERT_EQ(TEST_IO_SIZE, image.read(itr->second, TEST_IO_SIZE, readbl)); + ASSERT_TRUE(readbl.contents_equal(bl)); + } + + int64_t data_pool_id = image.get_data_pool_id(); + rados_ioctx_t d_ioctx; + rados_ioctx_create2(_cluster, data_pool_id, &d_ioctx); + + const char *entry; + rados_list_ctx_t list_ctx; + set obj_checker; + ASSERT_EQ(0, rados_nobjects_list_open(d_ioctx, &list_ctx)); + while (rados_nobjects_list_next(list_ctx, &entry, NULL, NULL) != -ENOENT) { + if (strstr(entry, info.block_name_prefix)) { + const char *block_name_suffix = entry + strlen(info.block_name_prefix) + 1; + obj_checker.insert(block_name_suffix); + } + } + rados_nobjects_list_close(list_ctx); + + std::string snapname = "snap"; + std::string clonename = get_temp_image_name(); + ASSERT_EQ(0, image.snap_create(snapname.c_str())); + ASSERT_EQ(0, image.close()); + ASSERT_EQ(0, m_rbd.open(m_ioctx, image, m_image_name.c_str(), snapname.c_str())); + ASSERT_EQ(0, image.snap_protect(snapname.c_str())); + printf("made snapshot \"%s@parent_snap\" and protect it\n", m_image_name.c_str()); + + ASSERT_EQ(0, clone_image_pp(m_rbd, image, m_ioctx, m_image_name.c_str(), snapname.c_str(), + m_ioctx, clonename.c_str(), features)); + ASSERT_EQ(0, image.close()); + ASSERT_EQ(0, m_rbd.open(m_ioctx, image, clonename.c_str(), NULL)); + printf("made and opened clone \"%s\"\n", clonename.c_str()); + + printf("read from \"child\"\n"); + { + map::iterator itr = write_tracker.begin(); + printf("\tread object-%-4ld\n", (unsigned long)itr->first); + ASSERT_EQ(TEST_IO_SIZE, image.read(itr->second, TEST_IO_SIZE, readbl)); + ASSERT_TRUE(readbl.contents_equal(bl)); + } + + for (map::iterator itr = write_tracker.begin(); + itr != write_tracker.end(); ++itr) { + printf("\tread object-%-4ld\n", (unsigned long)itr->first); + ASSERT_EQ(TEST_IO_SIZE, image.read(itr->second, TEST_IO_SIZE, readbl)); + ASSERT_TRUE(readbl.contents_equal(bl)); + } + + printf("read again reversely\n"); + for (map::iterator itr = --write_tracker.end(); + itr != write_tracker.begin(); --itr) { + printf("\tread object-%-4ld\n", (unsigned long)itr->first); + ASSERT_EQ(TEST_IO_SIZE, image.read(itr->second, TEST_IO_SIZE, readbl)); + ASSERT_TRUE(readbl.contents_equal(bl)); + } + + // close child to flush all copy-on-read + ASSERT_EQ(0, image.close()); + + printf("check whether child image has the same set of objects as parent\n"); + ASSERT_EQ(0, m_rbd.open(m_ioctx, image, clonename.c_str(), NULL)); + ASSERT_EQ(0, image.stat(info, sizeof(info))); + + ASSERT_EQ(0, rados_nobjects_list_open(d_ioctx, &list_ctx)); + while (rados_nobjects_list_next(list_ctx, &entry, NULL, NULL) != -ENOENT) { + if (strstr(entry, info.block_name_prefix)) { + const char *block_name_suffix = entry + strlen(info.block_name_prefix) + 1; + set::iterator it = obj_checker.find(block_name_suffix); + ASSERT_TRUE(it != obj_checker.end()); + obj_checker.erase(it); + } + } + rados_nobjects_list_close(list_ctx); + ASSERT_TRUE(obj_checker.empty()); + ASSERT_EQ(0, image.close()); + + rados_ioctx_destroy(d_ioctx); +} + +TEST_F(TestInternal, FlattenNoEmptyObjects) +{ + REQUIRE_FEATURE(RBD_FEATURE_LAYERING); + + m_image_name = get_temp_image_name(); + m_image_size = 4 << 20; + + int order = 12; // smallest object size is 4K + uint64_t features; + ASSERT_TRUE(get_features(&features)); + + ASSERT_EQ(0, create_image_full_pp(m_rbd, m_ioctx, m_image_name, m_image_size, + features, false, &order)); + + librbd::Image image; + ASSERT_EQ(0, m_rbd.open(m_ioctx, image, m_image_name.c_str(), NULL)); + + librbd::image_info_t info; + ASSERT_EQ(0, image.stat(info, sizeof(info))); + + const int object_num = info.size / info.obj_size; + printf("made parent image \"%s\": %ldK (%d * %ldK)\n", m_image_name.c_str(), + (unsigned long)m_image_size, object_num, info.obj_size/1024); + + // write something into parent + char test_data[TEST_IO_SIZE + 1]; + for (int i = 0; i < TEST_IO_SIZE; ++i) { + test_data[i] = (char) (rand() % (126 - 33) + 33); + } + test_data[TEST_IO_SIZE] = '\0'; + + // generate a random map which covers every objects with random + // offset + map write_tracker; + generate_random_iomap(image, object_num, info.obj_size, 100, write_tracker); + + printf("generated random write map:\n"); + for (map::iterator itr = write_tracker.begin(); + itr != write_tracker.end(); ++itr) + printf("\t [%-8ld, %-8ld]\n", + (unsigned long)itr->first, (unsigned long)itr->second); + + bufferlist bl; + bl.append(test_data, TEST_IO_SIZE); + + printf("write data based on random map\n"); + for (map::iterator itr = write_tracker.begin(); + itr != write_tracker.end(); ++itr) { + printf("\twrite object-%-4ld\t\n", (unsigned long)itr->first); + ASSERT_EQ(TEST_IO_SIZE, image.write(itr->second, TEST_IO_SIZE, bl)); + } + + bufferlist readbl; + printf("verify written data by reading\n"); + { + map::iterator itr = write_tracker.begin(); + printf("\tread object-%-4ld\n", (unsigned long)itr->first); + ASSERT_EQ(TEST_IO_SIZE, image.read(itr->second, TEST_IO_SIZE, readbl)); + ASSERT_TRUE(readbl.contents_equal(bl)); + } + + int64_t data_pool_id = image.get_data_pool_id(); + rados_ioctx_t d_ioctx; + rados_ioctx_create2(_cluster, data_pool_id, &d_ioctx); + + const char *entry; + rados_list_ctx_t list_ctx; + set obj_checker; + ASSERT_EQ(0, rados_nobjects_list_open(d_ioctx, &list_ctx)); + while (rados_nobjects_list_next(list_ctx, &entry, NULL, NULL) != -ENOENT) { + if (strstr(entry, info.block_name_prefix)) { + const char *block_name_suffix = entry + strlen(info.block_name_prefix) + 1; + obj_checker.insert(block_name_suffix); + } + } + rados_nobjects_list_close(list_ctx); + + std::string snapname = "snap"; + std::string clonename = get_temp_image_name(); + ASSERT_EQ(0, image.snap_create(snapname.c_str())); + ASSERT_EQ(0, image.close()); + ASSERT_EQ(0, m_rbd.open(m_ioctx, image, m_image_name.c_str(), snapname.c_str())); + ASSERT_EQ(0, image.snap_protect(snapname.c_str())); + printf("made snapshot \"%s@parent_snap\" and protect it\n", m_image_name.c_str()); + + ASSERT_EQ(0, clone_image_pp(m_rbd, image, m_ioctx, m_image_name.c_str(), snapname.c_str(), + m_ioctx, clonename.c_str(), features)); + ASSERT_EQ(0, image.close()); + + ASSERT_EQ(0, m_rbd.open(m_ioctx, image, clonename.c_str(), NULL)); + printf("made and opened clone \"%s\"\n", clonename.c_str()); + + printf("flattening clone: \"%s\"\n", clonename.c_str()); + ASSERT_EQ(0, image.flatten()); + + printf("check whether child image has the same set of objects as parent\n"); + ASSERT_EQ(0, image.stat(info, sizeof(info))); + + ASSERT_EQ(0, rados_nobjects_list_open(d_ioctx, &list_ctx)); + while (rados_nobjects_list_next(list_ctx, &entry, NULL, NULL) != -ENOENT) { + if (strstr(entry, info.block_name_prefix)) { + const char *block_name_suffix = entry + strlen(info.block_name_prefix) + 1; + set::iterator it = obj_checker.find(block_name_suffix); + ASSERT_TRUE(it != obj_checker.end()); + obj_checker.erase(it); + } + } + rados_nobjects_list_close(list_ctx); + ASSERT_TRUE(obj_checker.empty()); + ASSERT_EQ(0, image.close()); + + rados_ioctx_destroy(d_ioctx); +} diff --git a/src/test/librbd/test_librbd.cc b/src/test/librbd/test_librbd.cc index 46f22decb0d..d65f2b38418 100644 --- a/src/test/librbd/test_librbd.cc +++ b/src/test/librbd/test_librbd.cc @@ -50,9 +50,6 @@ #include "include/interval_set.h" #include "include/stringify.h" -#include "global/global_context.h" -#include "osdc/Striper.h" - #include #include @@ -1208,11 +1205,6 @@ TEST_F(TestLibRBD, TestCreateLsRenameSnapPP) ioctx.close(); } - - -#define TEST_IO_SIZE 512 -#define TEST_IO_TO_SNAP_SIZE 80 - void simple_write_cb(rbd_completion_t cb, void *arg) { printf("write completion cb called!\n"); @@ -1289,51 +1281,6 @@ void write_test_data(rbd_image_t image, const char *test_data, uint64_t off, siz *passed = true; } -void generate_random_iomap(rbd_image_t image, int num_objects, int object_size, - int max_count, map &iomap) -{ - uint64_t stripe_unit, stripe_count; - - ASSERT_EQ(0, rbd_get_stripe_unit(image, &stripe_unit)); - ASSERT_EQ(0, rbd_get_stripe_count(image, &stripe_count)); - - while (max_count-- > 0) { - // generate random image offset based on base random object - // number and object offset and then map that back to an - // object number based on stripe unit and count. - uint64_t ono = rand() % num_objects; - uint64_t offset = rand() % (object_size - TEST_IO_SIZE); - uint64_t imageoff = (ono * object_size) + offset; - - file_layout_t layout; - layout.object_size = object_size; - layout.stripe_unit = stripe_unit; - layout.stripe_count = stripe_count; - - vector ex; - Striper::file_to_extents(g_ceph_context, 1, &layout, imageoff, TEST_IO_SIZE, 0, ex); - - // lets not worry if IO spans multiple extents (>1 object). in such - // as case we would perform the write multiple times to the same - // offset, but we record all objects that would be generated with - // this IO. TODO: fix this if such a need is required by your - // test. - vector::iterator it; - map curr_iomap; - for (it = ex.begin(); it != ex.end(); ++it) { - if (iomap.find((*it).objectno) != iomap.end()) { - break; - } - - curr_iomap.insert(make_pair((*it).objectno, imageoff)); - } - - if (it == ex.end()) { - iomap.insert(curr_iomap.begin(), curr_iomap.end()); - } - } -} - void aio_discard_test_data(rbd_image_t image, uint64_t off, uint64_t len, bool *passed) { rbd_completion_t comp; @@ -2610,151 +2557,6 @@ TEST_F(TestLibRBD, TestClone2) rados_ioctx_destroy(ioctx); } -TEST_F(TestLibRBD, TestCoR) -{ - REQUIRE_FEATURE(RBD_FEATURE_LAYERING); - - std::string config_value; - ASSERT_EQ(0, _rados.conf_get("rbd_clone_copy_on_read", config_value)); - if (config_value == "false") { - std::cout << "SKIPPING due to disabled rbd_copy_on_read" << std::endl; - return; - } - - bool old_format; - uint64_t features; - ASSERT_EQ(0, get_features(&old_format, &features)); - ASSERT_FALSE(old_format); - - rados_ioctx_t ioctx; - rados_ioctx_create(_cluster, m_pool_name.c_str(), &ioctx); - - rbd_image_t parent, child; - int order = 12; // smallest object size is 4K - const uint64_t image_size = 4<<20; - const int object_size = 1<<12; - const int object_num = image_size / object_size; - map write_tracker; - set obj_checker; - rbd_image_info_t p_info, c_info; - rados_list_ctx_t list_ctx; - const char *entry; - - // make a parent to clone from - ASSERT_EQ(0, create_image_full(ioctx, "parent", image_size, &order, false, features)); - ASSERT_EQ(0, rbd_open(ioctx, "parent", &parent, NULL)); - printf("made parent image \"parent\": %ldK (%d * %dK)\n", - (unsigned long)image_size, object_num, object_size/1024); - - // write something into parent - char test_data[TEST_IO_SIZE + 1]; - char zero_data[TEST_IO_SIZE + 1]; - int i; - - for (i = 0; i < TEST_IO_SIZE; ++i) - test_data[i] = (char) (rand() % (126 - 33) + 33); - test_data[TEST_IO_SIZE] = '\0'; - memset(zero_data, 0, sizeof(zero_data)); - - // generate a random map which covers every objects with random - // offset - generate_random_iomap(parent, object_num, object_size, 100, write_tracker); - - printf("generated random write map:\n"); - for (map::iterator itr = write_tracker.begin(); - itr != write_tracker.end(); ++itr) - printf("\t [%-8ld, %-8ld]\n", - (unsigned long)itr->first, (unsigned long)itr->second); - - printf("write data based on random map\n"); - for (map::iterator itr = write_tracker.begin(); - itr != write_tracker.end(); ++itr) { - printf("\twrite object-%-4ld\t", (unsigned long)itr->first); - ASSERT_PASSED(write_test_data, parent, test_data, itr->second, TEST_IO_SIZE, 0); - } - - for (map::iterator itr = write_tracker.begin(); - itr != write_tracker.end(); ++itr) { - printf("\tread object-%-4ld\t", (unsigned long)itr->first); - ASSERT_PASSED(read_test_data, parent, test_data, itr->second, TEST_IO_SIZE, 0); - } - - // find out what objects the parent image has generated - ASSERT_EQ(0, rbd_stat(parent, &p_info, sizeof(p_info))); - - int64_t data_pool_id = rbd_get_data_pool_id(parent); - rados_ioctx_t d_ioctx; - rados_ioctx_create2(_cluster, data_pool_id, &d_ioctx); - - ASSERT_EQ(0, rados_nobjects_list_open(d_ioctx, &list_ctx)); - while (rados_nobjects_list_next(list_ctx, &entry, NULL, NULL) != -ENOENT) { - if (strstr(entry, p_info.block_name_prefix)) { - const char *block_name_suffix = entry + strlen(p_info.block_name_prefix) + 1; - obj_checker.insert(block_name_suffix); - } - } - rados_nobjects_list_close(list_ctx); - ASSERT_EQ(obj_checker.size(), write_tracker.size()); - - // create a snapshot, reopen as the parent we're interested in and protect it - ASSERT_EQ(0, rbd_snap_create(parent, "parent_snap")); - ASSERT_EQ(0, rbd_close(parent)); - ASSERT_EQ(0, rbd_open(ioctx, "parent", &parent, "parent_snap")); - ASSERT_EQ(0, rbd_snap_protect(parent, "parent_snap")); - ASSERT_PASSED(validate_object_map, parent); - ASSERT_EQ(0, rbd_close(parent)); - printf("made snapshot \"parent@parent_snap\" and protect it\n"); - - // create a copy-on-read clone and open it - ASSERT_EQ(0, clone_image(ioctx, parent, "parent", - "parent_snap", ioctx, "child", features, &order)); - ASSERT_EQ(0, rbd_open(ioctx, "child", &child, NULL)); - printf("made and opened clone \"child\"\n"); - - printf("read from \"child\"\n"); - { - map::iterator itr = write_tracker.begin(); - printf("\tread object-%-4ld\t", (unsigned long)itr->first); - ASSERT_PASSED(read_test_data, child, test_data, itr->second, TEST_IO_SIZE, 0); - } - - for (map::iterator itr = write_tracker.begin(); - itr != write_tracker.end(); ++itr) { - printf("\tread object-%-4ld\t", (unsigned long)itr->first); - ASSERT_PASSED(read_test_data, child, test_data, itr->second, TEST_IO_SIZE, 0); - } - - printf("read again reversely\n"); - for (map::iterator itr = --write_tracker.end(); - itr != write_tracker.begin(); --itr) { - printf("\tread object-%-4ld\t", (unsigned long)itr->first); - ASSERT_PASSED(read_test_data, child, test_data, itr->second, TEST_IO_SIZE, 0); - } - - // close child to flush all copy-on-read - ASSERT_EQ(0, rbd_close(child)); - - printf("check whether child image has the same set of objects as parent\n"); - ASSERT_EQ(0, rbd_open(ioctx, "child", &child, NULL)); - ASSERT_EQ(0, rbd_stat(child, &c_info, sizeof(c_info))); - ASSERT_EQ(0, rados_nobjects_list_open(d_ioctx, &list_ctx)); - while (rados_nobjects_list_next(list_ctx, &entry, NULL, NULL) != -ENOENT) { - if (strstr(entry, c_info.block_name_prefix)) { - const char *block_name_suffix = entry + strlen(c_info.block_name_prefix) + 1; - set::iterator it = obj_checker.find(block_name_suffix); - ASSERT_TRUE(it != obj_checker.end()); - obj_checker.erase(it); - } - } - rados_nobjects_list_close(list_ctx); - ASSERT_TRUE(obj_checker.empty()); - ASSERT_PASSED(validate_object_map, child); - ASSERT_EQ(0, rbd_close(child)); - - rados_ioctx_destroy(ioctx); - rados_ioctx_destroy(d_ioctx); -} - static void test_list_children(rbd_image_t image, ssize_t num_expected, ...) { va_list ap; @@ -3898,131 +3700,6 @@ TEST_F(TestLibRBD, Flatten) ASSERT_PASSED(validate_object_map, clone_image); } -TEST_F(TestLibRBD, FlattenNoEmptyObjects) -{ - REQUIRE_FEATURE(RBD_FEATURE_LAYERING); - - rados_ioctx_t ioctx; - rados_ioctx_create(_cluster, m_pool_name.c_str(), &ioctx); - - librbd::RBD rbd; - std::string parent_name = get_temp_image_name(); - uint64_t size = 4 << 20; - int order = 13; // smallest object size is 4K - - bool old_format; - uint64_t features; - ASSERT_EQ(0, get_features(&old_format, &features)); - ASSERT_FALSE(old_format); - - // make a parent to clone from - ASSERT_EQ(0, create_image_full(ioctx, parent_name.c_str(), size, &order, - false, features)); - - rbd_image_t parent; - const int object_size = 1 << order; - const int object_num = size / object_size; - ASSERT_EQ(0, rbd_open(ioctx, parent_name.c_str(), &parent, NULL)); - printf("made parent image \"%s\": %ldK (%d * %dK)\n", parent_name.c_str(), - (unsigned long)size, object_num, object_size/1024); - - // write something into parent - char test_data[TEST_IO_SIZE + 1]; - char zero_data[TEST_IO_SIZE + 1]; - int i; - for (i = 0; i < TEST_IO_SIZE; ++i) - test_data[i] = (char) (rand() % (126 - 33) + 33); - test_data[TEST_IO_SIZE] = '\0'; - memset(zero_data, 0, sizeof(zero_data)); - - // generate a random map which covers every objects with random - // offset - map write_tracker; - generate_random_iomap(parent, object_num, object_size, 10, write_tracker); - - printf("generated random write map:\n"); - for (map::iterator itr = write_tracker.begin(); - itr != write_tracker.end(); ++itr) - printf("\t [%-8ld, %-8ld]\n", - (unsigned long)itr->first, (unsigned long)itr->second); - - printf("write data based on random map\n"); - for (map::iterator itr = write_tracker.begin(); - itr != write_tracker.end(); ++itr) { - printf("\twrite object-%-4ld\t", (unsigned long)itr->first); - ASSERT_PASSED(write_test_data, parent, test_data, itr->second, TEST_IO_SIZE, 0); - } - - for (map::iterator itr = write_tracker.begin(); - itr != write_tracker.end(); ++itr) { - printf("\tread object-%-4ld\t", (unsigned long)itr->first); - ASSERT_PASSED(read_test_data, parent, test_data, itr->second, TEST_IO_SIZE, 0); - } - - // find out what objects the parent image has generated - rbd_image_info_t p_info; - ASSERT_EQ(0, rbd_stat(parent, &p_info, sizeof(p_info))); - - int64_t data_pool_id = rbd_get_data_pool_id(parent); - rados_ioctx_t d_ioctx; - rados_ioctx_create2(_cluster, data_pool_id, &d_ioctx); - - const char *entry; - set obj_checker; - rados_list_ctx_t list_ctx; - ASSERT_EQ(0, rados_nobjects_list_open(d_ioctx, &list_ctx)); - while (rados_nobjects_list_next(list_ctx, &entry, NULL, NULL) != -ENOENT) { - if (strstr(entry, p_info.block_name_prefix)) { - const char *block_name_suffix = entry + strlen(p_info.block_name_prefix) + 1; - printf("parent object: %s\n", entry); - obj_checker.insert(block_name_suffix); - } - } - rados_nobjects_list_close(list_ctx); - ASSERT_EQ(obj_checker.size(), write_tracker.size()); - - // create a snapshot, reopen as the parent we're interested in and protect it - ASSERT_EQ(0, rbd_snap_create(parent, "parent_snap")); - ASSERT_EQ(0, rbd_close(parent)); - ASSERT_EQ(0, rbd_open(ioctx, parent_name.c_str(), &parent, "parent_snap")); - ASSERT_EQ(0, rbd_snap_protect(parent, "parent_snap")); - ASSERT_PASSED(validate_object_map, parent); - ASSERT_EQ(0, rbd_close(parent)); - printf("made snapshot and protected: \"%s@parent_snap\"\n", parent_name.c_str()); - - std::string child_name = get_temp_image_name(); - ASSERT_EQ(0, clone_image(ioctx, parent, parent_name.c_str(), - "parent_snap", ioctx, child_name.c_str(), features, &order)); - - rbd_image_t child; - ASSERT_EQ(0, rbd_open(ioctx, child_name.c_str(), &child, NULL)); - printf("made and opened clone \"%s\"\n", child_name.c_str()); - - printf("flattening clone: \"%s\"\n", child_name.c_str()); - ASSERT_EQ(0, rbd_flatten(child)); - - printf("check whether child image has the same set of objects as parent\n"); - rbd_image_info_t c_info; - ASSERT_EQ(0, rbd_stat(child, &c_info, sizeof(c_info))); - ASSERT_EQ(0, rados_nobjects_list_open(d_ioctx, &list_ctx)); - while (rados_nobjects_list_next(list_ctx, &entry, NULL, NULL) != -ENOENT) { - if (strstr(entry, c_info.block_name_prefix)) { - const char *block_name_suffix = entry + strlen(c_info.block_name_prefix) + 1; - set::iterator it = obj_checker.find(block_name_suffix); - printf("child object: %s\n", entry); - ASSERT_TRUE(it != obj_checker.end()); - obj_checker.erase(it); - } - } - rados_nobjects_list_close(list_ctx); - ASSERT_TRUE(obj_checker.empty()); - ASSERT_PASSED(validate_object_map, child); - ASSERT_EQ(0, rbd_close(child)); - - rados_ioctx_destroy(ioctx); - rados_ioctx_destroy(d_ioctx); -} - TEST_F(TestLibRBD, SnapshotLimit) { rados_ioctx_t ioctx; diff --git a/src/test/librbd/test_support.h b/src/test/librbd/test_support.h index 16e76a65147..47707b1c015 100644 --- a/src/test/librbd/test_support.h +++ b/src/test/librbd/test_support.h @@ -8,6 +8,9 @@ static const uint64_t IMAGE_STRIPE_UNIT = 65536; static const uint64_t IMAGE_STRIPE_COUNT = 16; +#define TEST_IO_SIZE 512 +#define TEST_IO_TO_SNAP_SIZE 80 + bool get_features(uint64_t *features); bool is_feature_enabled(uint64_t feature); int create_image_pp(librbd::RBD &rbd, librados::IoCtx &ioctx,