From 8e9035443322f8cbdb8c7aff5da0d1c7599a2592 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Tue, 11 Sep 2018 21:52:05 -0400 Subject: [PATCH] librbd: fixed assert when flattening clone with zero overlap Fixes: http://tracker.ceph.com/issues/35702 Signed-off-by: Jason Dillaman --- src/librbd/Operations.cc | 1 - src/librbd/operation/FlattenRequest.cc | 2 +- src/test/librbd/test_librbd.cc | 32 ++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/librbd/Operations.cc b/src/librbd/Operations.cc index 8a0b00b2ab531..e670b8523fb4c 100644 --- a/src/librbd/Operations.cc +++ b/src/librbd/Operations.cc @@ -402,7 +402,6 @@ void Operations::execute_flatten(ProgressContext &prog_ctx, } ::SnapContext snapc = m_image_ctx.snapc; - ceph_assert(m_image_ctx.parent != NULL); uint64_t overlap; int r = m_image_ctx.get_parent_overlap(CEPH_NOSNAP, &overlap); diff --git a/src/librbd/operation/FlattenRequest.cc b/src/librbd/operation/FlattenRequest.cc index 0b861ebe59d01..2f3225c64ae5c 100644 --- a/src/librbd/operation/FlattenRequest.cc +++ b/src/librbd/operation/FlattenRequest.cc @@ -169,7 +169,7 @@ bool FlattenRequest::send_update_header() { RWLock::RLocker parent_locker(image_ctx.parent_lock); // stop early if the parent went away - it just means // another flatten finished first, so this one is useless. - if (!image_ctx.parent) { + if (image_ctx.parent_md.spec.pool_id == -1) { ldout(cct, 5) << "image already flattened" << dendl; return true; } diff --git a/src/test/librbd/test_librbd.cc b/src/test/librbd/test_librbd.cc index 478fbd4c099c2..9ab40bd8d5e0b 100644 --- a/src/test/librbd/test_librbd.cc +++ b/src/test/librbd/test_librbd.cc @@ -7005,6 +7005,38 @@ TEST_F(TestLibRBD, TestGetModifyTimestamp) rados_ioctx_destroy(ioctx); } +TEST_F(TestLibRBD, ZeroOverlapFlatten) { + REQUIRE_FEATURE(RBD_FEATURE_LAYERING); + + librados::IoCtx ioctx; + ASSERT_EQ(0, _rados.ioctx_create(m_pool_name.c_str(), ioctx)); + + librbd::RBD rbd; + librbd::Image parent_image; + std::string name = get_temp_image_name(); + + uint64_t size = 1; + int order = 0; + + ASSERT_EQ(0, create_image_pp(rbd, ioctx, name.c_str(), size, &order)); + ASSERT_EQ(0, rbd.open(ioctx, parent_image, name.c_str(), NULL)); + + uint64_t features; + ASSERT_EQ(0, parent_image.features(&features)); + + ASSERT_EQ(0, parent_image.snap_create("snap")); + ASSERT_EQ(0, parent_image.snap_protect("snap")); + + std::string clone_name = this->get_temp_image_name(); + ASSERT_EQ(0, rbd.clone(ioctx, name.c_str(), "snap", ioctx, clone_name.c_str(), + features, &order)); + + librbd::Image clone_image; + ASSERT_EQ(0, rbd.open(ioctx, clone_image, clone_name.c_str(), NULL)); + ASSERT_EQ(0, clone_image.resize(0)); + ASSERT_EQ(0, clone_image.flatten()); +} + // poorman's ceph_assert() namespace ceph { void __ceph_assert_fail(const char *assertion, const char *file, int line, -- 2.39.5