m_src_ictx->io_work_queue->discard(0, len, false));
}
+ void test_clone_discard() {
+ bufferlist bl;
+ bl.append(std::string(100, '1'));
+ ASSERT_EQ(static_cast<ssize_t>(bl.length()),
+ m_src_ictx->io_work_queue->write(0, bl.length(), bufferlist{bl},
+ 0));
+ ASSERT_EQ(0, m_src_ictx->io_work_queue->flush());
+
+ ASSERT_EQ(0, snap_create(*m_src_ictx, "snap"));
+ ASSERT_EQ(0, snap_protect(*m_src_ictx, "snap"));
+
+ std::string clone_name = get_temp_image_name();
+ int order = m_src_ictx->order;
+ uint64_t features;
+ ASSERT_EQ(0, librbd::get_features(m_src_ictx, &features));
+ ASSERT_EQ(0, librbd::clone(m_ioctx, m_src_ictx->name.c_str(), "snap",
+ m_ioctx, clone_name.c_str(), features, &order, 0,
+ 0));
+ close_image(m_src_ictx);
+ ASSERT_EQ(0, open_image(clone_name, &m_src_ictx));
+
+ size_t len = (1 << m_src_ictx->order) * 2;
+ ASSERT_EQ(static_cast<ssize_t>(len),
+ m_src_ictx->io_work_queue->discard(0, len, false));
+ }
+
+ void test_clone_shrink() {
+ bufferlist bl;
+ bl.append(std::string(100, '1'));
+ ASSERT_EQ(static_cast<ssize_t>(bl.length()),
+ m_src_ictx->io_work_queue->write(0, bl.length(), bufferlist{bl},
+ 0));
+ ASSERT_EQ(0, m_src_ictx->io_work_queue->flush());
+
+ ASSERT_EQ(0, snap_create(*m_src_ictx, "snap"));
+ ASSERT_EQ(0, snap_protect(*m_src_ictx, "snap"));
+
+ std::string clone_name = get_temp_image_name();
+ int order = m_src_ictx->order;
+ uint64_t features;
+ ASSERT_EQ(0, librbd::get_features(m_src_ictx, &features));
+ ASSERT_EQ(0, librbd::clone(m_ioctx, m_src_ictx->name.c_str(), "snap",
+ m_ioctx, clone_name.c_str(), features, &order, 0,
+ 0));
+ close_image(m_src_ictx);
+ ASSERT_EQ(0, open_image(clone_name, &m_src_ictx));
+
+ librbd::NoOpProgressContext no_op;
+ auto new_size = m_src_ictx->size >> 1;
+ ASSERT_EQ(0, m_src_ictx->operations->resize(new_size, true, no_op));
+ }
+
+ void test_clone() {
+ bufferlist bl;
+ bl.append(std::string(((1 << m_src_ictx->order) * 2) + 1, '1'));
+ ASSERT_EQ(static_cast<ssize_t>(bl.length()),
+ m_src_ictx->io_work_queue->write(0 * bl.length(), bl.length(),
+ bufferlist{bl}, 0));
+ ASSERT_EQ(static_cast<ssize_t>(bl.length()),
+ m_src_ictx->io_work_queue->write(2 * bl.length(), bl.length(),
+ bufferlist{bl}, 0));
+ ASSERT_EQ(0, m_src_ictx->io_work_queue->flush());
+
+ ASSERT_EQ(0, snap_create(*m_src_ictx, "snap"));
+ ASSERT_EQ(0, snap_protect(*m_src_ictx, "snap"));
+
+ std::string clone_name = get_temp_image_name();
+ int order = m_src_ictx->order;
+ uint64_t features;
+ ASSERT_EQ(0, librbd::get_features(m_src_ictx, &features));
+ ASSERT_EQ(0, librbd::clone(m_ioctx, m_src_ictx->name.c_str(), "snap",
+ m_ioctx, clone_name.c_str(), features, &order, 0,
+ 0));
+ close_image(m_src_ictx);
+ ASSERT_EQ(0, open_image(clone_name, &m_src_ictx));
+
+ bufferlist bl1;
+ bl1.append(std::string(1000, 'X'));
+ ASSERT_EQ(static_cast<ssize_t>(bl1.length()),
+ m_src_ictx->io_work_queue->write(0 * bl.length(), bl1.length(),
+ bufferlist{bl1}, 0));
+ ASSERT_EQ(static_cast<ssize_t>(bl1.length()),
+ m_src_ictx->io_work_queue->discard(bl1.length() + 10,
+ bl1.length(), false));
+ ASSERT_EQ(0, m_src_ictx->io_work_queue->flush());
+
+ ASSERT_EQ(0, snap_create(*m_src_ictx, "snap"));
+ ASSERT_EQ(0, snap_protect(*m_src_ictx, "snap"));
+
+ clone_name = get_temp_image_name();
+ ASSERT_EQ(0, librbd::clone(m_ioctx, m_src_ictx->name.c_str(), "snap",
+ m_ioctx, clone_name.c_str(), features, &order, 0,
+ 0));
+ close_image(m_src_ictx);
+ ASSERT_EQ(0, open_image(clone_name, &m_src_ictx));
+
+ ASSERT_EQ(static_cast<ssize_t>(bl1.length()),
+ m_src_ictx->io_work_queue->write(1 * bl.length(), bl1.length(),
+ bufferlist{bl1}, 0));
+ ASSERT_EQ(static_cast<ssize_t>(bl1.length()),
+ m_src_ictx->io_work_queue->discard(2 * bl1.length() + 10,
+ bl1.length(), false));
+ }
+
void test_stress() {
uint64_t initial_size, size;
{
std::cout << "snap: " << snap_name << std::endl;
ASSERT_EQ(0, snap_create(*m_src_ictx, snap_name.c_str()));
+ if (m_src_ictx->test_features(RBD_FEATURE_LAYERING) && rand() % 4) {
+ ASSERT_EQ(0, snap_protect(*m_src_ictx, snap_name.c_str()));
+
+ std::string clone_name = get_temp_image_name();
+ int order = m_src_ictx->order;
+ uint64_t features;
+ ASSERT_EQ(0, librbd::get_features(m_src_ictx, &features));
+ std::cout << "clone " << m_src_ictx->name << " -> " << clone_name
+ << std::endl;
+ ASSERT_EQ(0, librbd::clone(m_ioctx, m_src_ictx->name.c_str(),
+ snap_name.c_str(), m_ioctx,
+ clone_name.c_str(), features, &order,
+ m_src_ictx->stripe_unit,
+ m_src_ictx->stripe_count));
+ close_image(m_src_ictx);
+ ASSERT_EQ(0, open_image(clone_name, &m_src_ictx));
+ }
+
if (rand() % 2) {
librbd::NoOpProgressContext no_op;
uint64_t new_size = initial_size + rand() % size;
test_snap_discard();
}
+TEST_F(TestDeepCopy, CloneDiscard)
+{
+ REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
+
+ test_clone_discard();
+}
+
+TEST_F(TestDeepCopy, CloneShrink)
+{
+ REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
+
+ test_clone_shrink();
+}
+
+TEST_F(TestDeepCopy, Clone)
+{
+ REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
+
+ test_clone();
+}
+
TEST_F(TestDeepCopy, Stress)
{
test_stress();
test_snaps();
}
+TEST_F(TestDeepCopy, Clone_LargerDstObjSize)
+{
+ REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
+
+ uint64_t order = m_src_ictx->order + 1 + rand() % 2;
+ ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_ORDER, order));
+
+ test_clone();
+}
+
TEST_F(TestDeepCopy, Stress_LargerDstObjSize)
{
uint64_t order = m_src_ictx->order + 1 + rand() % 2;
test_snaps();
}
+TEST_F(TestDeepCopy, Clone_SmallerDstObjSize)
+{
+ REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
+
+ uint64_t order = m_src_ictx->order - 1 - rand() % 2;
+ ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_ORDER, order));
+ uint64_t stripe_unit = m_src_ictx->stripe_unit >> 2;
+ ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_STRIPE_UNIT, stripe_unit));
+
+ test_clone();
+}
+
TEST_F(TestDeepCopy, Stress_SmallerDstObjSize)
{
uint64_t order = m_src_ictx->order - 1 - rand() % 2;
test_snaps();
}
+TEST_F(TestDeepCopy, Clone_StrippingLargerDstObjSize)
+{
+ REQUIRE_FEATURE(RBD_FEATURE_LAYERING | RBD_FEATURE_STRIPINGV2);
+
+ uint64_t order = m_src_ictx->order + 1;
+ uint64_t stripe_unit = 1 << (order - 2);
+ uint64_t stripe_count = 4;
+ ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_ORDER, order));
+ ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_STRIPE_UNIT, stripe_unit));
+ ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_STRIPE_COUNT, stripe_count));
+
+ test_clone();
+}
+
TEST_F(TestDeepCopy, Stress_StrippingLargerDstObjSize)
{
REQUIRE_FEATURE(RBD_FEATURE_STRIPINGV2);
test_snaps();
}
+TEST_F(TestDeepCopy, Clone_StrippingSmallerDstObjSize)
+{
+ REQUIRE_FEATURE(RBD_FEATURE_LAYERING | RBD_FEATURE_STRIPINGV2);
+
+ uint64_t order = m_src_ictx->order - 1 - rand() % 2;
+ uint64_t stripe_unit = 1 << (order - rand() % 4);
+ uint64_t stripe_count = 2 + rand() % 14;
+ ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_ORDER, order));
+ ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_STRIPE_UNIT, stripe_unit));
+ ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_STRIPE_COUNT, stripe_count));
+
+ test_clone();
+}
+
TEST_F(TestDeepCopy, Stress_StrippingSmallerDstObjSize)
{
REQUIRE_FEATURE(RBD_FEATURE_STRIPINGV2);