From: Mykola Golub Date: Wed, 12 Dec 2018 15:42:49 +0000 (+0000) Subject: librbd: disable image mirroring when moving to trash X-Git-Tag: v13.2.7~299^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=604a48f9e9876198999bca6331bb43b4ab319700;p=ceph.git librbd: disable image mirroring when moving to trash And enable when restoring if mirror pool mode set. Fixes: https://tracker.ceph.com/issues/37596 Signed-off-by: Mykola Golub (cherry picked from commit 6844a52ebbc45a046b4a94909b48bc4fc0c305c7) Conflicts: src/librbd/api/Trash.cc (the code is in src/librbd/internal.cc) --- diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index 2e08b5e92310..ed9f9ac330b8 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -48,6 +48,7 @@ #include "librbd/io/ReadResult.h" #include "librbd/journal/Types.h" #include "librbd/managed_lock/Types.h" +#include "librbd/mirror/DisableRequest.h" #include "librbd/mirror/EnableRequest.h" #include "librbd/operation/TrimRequest.h" #include "librbd/trash/MoveRequest.h" @@ -125,6 +126,86 @@ bool compare_by_name(const child_info_t& c1, const child_info_t& c2) return false; } +int disable_mirroring(ImageCtx *ictx) { + if (!ictx->test_features(RBD_FEATURE_JOURNALING)) { + return 0; + } + + cls::rbd::MirrorImage mirror_image; + int r = cls_client::mirror_image_get(&ictx->md_ctx, ictx->id, &mirror_image); + if (r == -ENOENT) { + ldout(ictx->cct, 10) << "mirroring is not enabled for this image" << dendl; + return 0; + } + + if (r < 0) { + lderr(ictx->cct) << "failed to retrieve mirror image: " << cpp_strerror(r) + << dendl; + return r; + } + + ldout(ictx->cct, 10) << dendl; + + C_SaferCond ctx; + auto req = mirror::DisableRequest<>::create(ictx, false, true, &ctx); + req->send(); + r = ctx.wait(); + if (r < 0) { + lderr(ictx->cct) << "failed to disable mirroring: " << cpp_strerror(r) + << dendl; + return r; + } + + return 0; +} + +int enable_mirroring(IoCtx &io_ctx, const std::string &image_id) { + auto cct = reinterpret_cast(io_ctx.cct()); + + uint64_t features; + int r = cls_client::get_features(&io_ctx, util::header_name(image_id), + CEPH_NOSNAP, &features); + if (r < 0) { + lderr(cct) << "failed to retrieve features: " << cpp_strerror(r) << dendl; + return r; + } + + if ((features & RBD_FEATURE_JOURNALING) == 0) { + return 0; + } + + cls::rbd::MirrorMode mirror_mode; + r = cls_client::mirror_mode_get(&io_ctx, &mirror_mode); + if (r < 0 && r != -ENOENT) { + lderr(cct) << "failed to retrieve mirror mode: " << cpp_strerror(r) + << dendl; + return r; + } + + if (mirror_mode != cls::rbd::MIRROR_MODE_POOL) { + ldout(cct, 10) << "not pool mirroring mode" << dendl; + return 0; + } + + ldout(cct, 10) << dendl; + + ThreadPool *thread_pool; + ContextWQ *op_work_queue; + ImageCtx::get_thread_pool_instance(cct, &thread_pool, &op_work_queue); + C_SaferCond ctx; + auto req = mirror::EnableRequest<>::create(io_ctx, image_id, "", + op_work_queue, &ctx); + req->send(); + r = ctx.wait(); + if (r < 0) { + lderr(cct) << "failed to enable mirroring: " << cpp_strerror(r) + << dendl; + return r; + } + + return 0; +} + } // anonymous namespace int detect_format(IoCtx &io_ctx, const string &name, @@ -1409,6 +1490,12 @@ bool compare_by_name(const child_info_t& c1, const child_info_t& c2) } ictx->owner_lock.put_read(); + r = disable_mirroring(ictx); + if (r < 0) { + ictx->state->close(); + return r; + } + utime_t delete_time{ceph_clock_now()}; utime_t deferment_end_time{delete_time}; deferment_end_time += delay; @@ -1603,6 +1690,11 @@ bool compare_by_name(const child_info_t& c1, const child_info_t& c2) return r; } + r = enable_mirroring(io_ctx, image_id); + if (r < 0) { + // not fatal -- ignore + } + ldout(cct, 2) << "removing image from trash..." << dendl; r = cls_client::trash_remove(&io_ctx, image_id); if (r < 0 && r != -ENOENT) { diff --git a/src/test/librbd/test_mirroring.cc b/src/test/librbd/test_mirroring.cc index ce21e3f87567..bade0e7f74e4 100644 --- a/src/test/librbd/test_mirroring.cc +++ b/src/test/librbd/test_mirroring.cc @@ -263,6 +263,45 @@ public: ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_DISABLED)); } + void check_trash_move_restore(rbd_mirror_mode_t mirror_mode, + bool enable_mirroring) { + + ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, mirror_mode)); + + int order = 20; + uint64_t features = RBD_FEATURE_EXCLUSIVE_LOCK | RBD_FEATURE_JOURNALING; + ASSERT_EQ(0, m_rbd.create2(m_ioctx, image_name.c_str(), 4096, features, + &order)); + librbd::Image image; + ASSERT_EQ(0, m_rbd.open(m_ioctx, image, image_name.c_str())); + + if (enable_mirroring) { + ASSERT_EQ(0, image.mirror_image_enable()); + } + + std::string image_id; + ASSERT_EQ(0, image.get_id(&image_id)); + + ASSERT_EQ(0, m_rbd.trash_move(m_ioctx, image_name.c_str(), 100)); + + librbd::mirror_image_info_t mirror_image; + ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image, sizeof(mirror_image))); + ASSERT_EQ(mirror_image.state, RBD_MIRROR_IMAGE_DISABLED); + + ASSERT_EQ(0, m_rbd.trash_restore(m_ioctx, image_id.c_str(), "")); + + ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image, sizeof(mirror_image))); + if (mirror_mode == RBD_MIRROR_MODE_POOL) { + ASSERT_EQ(mirror_image.state, RBD_MIRROR_IMAGE_ENABLED); + } else { + ASSERT_EQ(mirror_image.state, RBD_MIRROR_IMAGE_DISABLED); + } + + image.close(); + ASSERT_EQ(0, m_rbd.remove(m_ioctx, image_name.c_str())); + ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_DISABLED)); + } + void setup_mirror_peer(librados::IoCtx &io_ctx, librbd::Image &image) { ASSERT_EQ(0, image.snap_create("sync-point-snap")); @@ -619,6 +658,18 @@ TEST_F(TestMirroring, RemoveImage_With_MirrorImageDemoted) { true, true); } +TEST_F(TestMirroring, TrashMoveRestore_PoolMode) { + check_trash_move_restore(RBD_MIRROR_MODE_POOL, false); +} + +TEST_F(TestMirroring, TrashMoveRestore_ImageMode_MirroringDisabled) { + check_trash_move_restore(RBD_MIRROR_MODE_IMAGE, false); +} + +TEST_F(TestMirroring, TrashMoveRestore_ImageMode_MirroringEnabled) { + check_trash_move_restore(RBD_MIRROR_MODE_IMAGE, true); +} + TEST_F(TestMirroring, MirrorStatusList) { std::vector features_vec(5, RBD_FEATURE_EXCLUSIVE_LOCK | RBD_FEATURE_JOURNALING);