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: v12.2.13~180^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=f2e51d77e4dd2efa5befaa248fce52642c71f252;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 bd77bb439f8..cf89789bcb8 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -43,6 +43,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" @@ -109,6 +110,85 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { return 0; } +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 @@ -1376,29 +1456,16 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { return -EBUSY; } } - } + ictx->owner_lock.put_read(); - BOOST_SCOPE_EXIT_ALL(ictx, cct) { - if (ictx == nullptr) - return; - - bool is_locked = ictx->exclusive_lock != nullptr && - ictx->exclusive_lock->is_lock_owner(); - if (is_locked) { - C_SaferCond ctx; - auto exclusive_lock = ictx->exclusive_lock; - exclusive_lock->shut_down(&ctx); - ictx->owner_lock.put_read(); - int r = ctx.wait(); - if (r < 0) { - lderr(cct) << "error shutting down exclusive lock" << dendl; - } - delete exclusive_lock; - } else { - ictx->owner_lock.put_read(); + r = disable_mirroring(ictx); + if (r < 0) { + ictx->state->close(); + return r; } + ictx->state->close(); - }; + } ldout(cct, 2) << "adding image entry to rbd_trash" << dendl; utime_t ts = ceph_clock_now(); @@ -1596,6 +1663,11 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { 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 837ef2b88fa..be8fa343b43 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);