From d1c82d55827e985dce811e46928cf6850abea390 Mon Sep 17 00:00:00 2001 From: Yuan Lu Date: Fri, 19 Jun 2020 18:27:34 +0800 Subject: [PATCH] librbd: enable image cache after getting exclusive lock Signed-off-by: Peterson, Scott Signed-off-by: Li, Xiaoyan Signed-off-by: Lu, Yuan Signed-off-by: Chamarthy, Mahati --- src/librbd/CMakeLists.txt | 4 +- src/librbd/ExclusiveLock.cc | 5 +- src/librbd/ImageCtx.h | 8 +- src/librbd/api/Migration.cc | 1 + src/librbd/cache/Utils.h | 4 + src/librbd/cache/rwl/ImageCacheState.cc | 3 +- src/librbd/cache/rwl/ImageCacheState.h | 3 +- .../exclusive_lock/PostAcquireRequest.cc | 66 ++++++++- .../exclusive_lock/PostAcquireRequest.h | 12 +- .../exclusive_lock/PreReleaseRequest.cc | 37 +++++ src/librbd/exclusive_lock/PreReleaseRequest.h | 6 + src/librbd/io/ImageRequest.cc | 2 +- .../test_mock_PostAcquireRequest.cc | 130 ++++++++++++++++++ .../test_mock_PreReleaseRequest.cc | 59 ++++++++ .../object_map/test_mock_UpdateRequest.cc | 2 +- src/test/librbd/test_Migration.cc | 5 +- src/test/librbd/test_fixture.cc | 18 +++ src/test/librbd/test_fixture.h | 2 + src/test/librbd/test_internal.cc | 24 ++-- src/test/librbd/test_librbd.cc | 124 ++++++++++------- src/test/librbd/test_mirroring.cc | 4 +- src/test/librbd/test_mock_ExclusiveLock.cc | 3 +- src/test/librbd/test_mock_fixture.cc | 11 ++ src/test/librbd/test_support.cc | 8 ++ src/test/librbd/test_support.h | 2 + 25 files changed, 464 insertions(+), 79 deletions(-) diff --git a/src/librbd/CMakeLists.txt b/src/librbd/CMakeLists.txt index c0d0120ce3d45..65e98ad1f369d 100644 --- a/src/librbd/CMakeLists.txt +++ b/src/librbd/CMakeLists.txt @@ -43,6 +43,8 @@ set(librbd_internal_srcs cache/ObjectCacherObjectDispatch.cc cache/ObjectCacherWriteback.cc cache/PassthroughImageCache.cc + cache/rwl/InitRequest.cc + cache/rwl/ShutdownRequest.cc cache/WriteAroundObjectDispatch.cc deep_copy/ImageCopyRequest.cc deep_copy/MetadataCopyRequest.cc @@ -194,13 +196,11 @@ if(WITH_RBD_RWL) set(librbd_internal_srcs ${librbd_internal_srcs} cache/rwl/ImageCacheState.cc - cache/rwl/InitRequest.cc cache/rwl/LogEntry.cc cache/rwl/LogMap.cc cache/rwl/LogOperation.cc cache/rwl/ReadRequest.cc cache/rwl/Request.cc - cache/rwl/ShutdownRequest.cc cache/rwl/SyncPoint.cc cache/rwl/Types.cc cache/ReplicatedWriteLog.cc) diff --git a/src/librbd/ExclusiveLock.cc b/src/librbd/ExclusiveLock.cc index bdf67238df3da..20f594b88c885 100644 --- a/src/librbd/ExclusiveLock.cc +++ b/src/librbd/ExclusiveLock.cc @@ -1,6 +1,7 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab +#include "librbd/cache/Utils.h" #include "librbd/ExclusiveLock.h" #include "librbd/ImageCtx.h" #include "librbd/ImageWatcher.h" @@ -203,8 +204,10 @@ void ExclusiveLock::handle_init_complete(int r, uint64_t features, on_finish->complete(r); }); + bool rwl_enabled = cache::util::is_rwl_enabled(m_image_ctx); if (m_image_ctx.clone_copy_on_read || - (features & RBD_FEATURE_JOURNALING) != 0) { + (features & RBD_FEATURE_JOURNALING) != 0 || + rwl_enabled) { m_image_dispatch->set_require_lock(io::DIRECTION_BOTH, on_finish); } else { m_image_dispatch->set_require_lock(io::DIRECTION_WRITE, on_finish); diff --git a/src/librbd/ImageCtx.h b/src/librbd/ImageCtx.h index 26d993e4c2562..c8c3caf97aba5 100644 --- a/src/librbd/ImageCtx.h +++ b/src/librbd/ImageCtx.h @@ -57,12 +57,7 @@ namespace librbd { template class PluginRegistry; namespace asio { struct ContextWQ; } - namespace cache { - template class ImageCache; - namespace rwl { - template class ImageCacheState; - } // namespace rwl - } // namespace cache + namespace cache { template class ImageCache; } namespace exclusive_lock { struct Policy; } namespace io { class AioCompletion; @@ -182,7 +177,6 @@ namespace librbd { file_layout_t layout; cache::ImageCache *image_cache = nullptr; - cache::rwl::ImageCacheState *cache_state = nullptr; Readahead readahead; std::atomic total_bytes_read = {0}; diff --git a/src/librbd/api/Migration.cc b/src/librbd/api/Migration.cc index 85733c4cab1db..ec07122588808 100644 --- a/src/librbd/api/Migration.cc +++ b/src/librbd/api/Migration.cc @@ -401,6 +401,7 @@ int Migration::prepare(librados::IoCtx& io_ctx, return -ENOSYS; } features &= ~RBD_FEATURES_INTERNAL; + features &= ~RBD_FEATURE_DIRTY_CACHE; features |= RBD_FEATURE_MIGRATING; opts.set(RBD_IMAGE_OPTION_FEATURES, features); diff --git a/src/librbd/cache/Utils.h b/src/librbd/cache/Utils.h index aa08bcba1c6d8..99752529072ea 100644 --- a/src/librbd/cache/Utils.h +++ b/src/librbd/cache/Utils.h @@ -11,7 +11,11 @@ namespace util { template bool is_rwl_enabled(T& image_ctx) { +#if defined(WITH_RBD_RWL) return image_ctx.config.template get_val("rbd_rwl_enabled"); +#else + return false; +#endif } } // namespace util diff --git a/src/librbd/cache/rwl/ImageCacheState.cc b/src/librbd/cache/rwl/ImageCacheState.cc index 5c491b190d289..945e39ed82e00 100644 --- a/src/librbd/cache/rwl/ImageCacheState.cc +++ b/src/librbd/cache/rwl/ImageCacheState.cc @@ -2,6 +2,7 @@ // vim: ts=8 sw=2 smarttab #include "librbd/cache/Types.h" +#include "librbd/cache/Utils.h" #include "librbd/cache/rwl/ImageCacheState.h" #include "librbd/ImageCtx.h" #include "librbd/Operations.h" @@ -111,7 +112,7 @@ ImageCacheState* ImageCacheState::get_image_cache_state( IMAGE_CACHE_STATE, &cache_state_str); } - bool rwl_enabled = image_ctx->config.template get_val("rbd_rwl_enabled"); + bool rwl_enabled = cache::util::is_rwl_enabled(*image_ctx); bool cache_desired = rwl_enabled; cache_desired &= !image_ctx->read_only; cache_desired &= !image_ctx->test_features(RBD_FEATURE_MIGRATING); diff --git a/src/librbd/cache/rwl/ImageCacheState.h b/src/librbd/cache/rwl/ImageCacheState.h index f2c82cfefdd28..751978e76ec4f 100644 --- a/src/librbd/cache/rwl/ImageCacheState.h +++ b/src/librbd/cache/rwl/ImageCacheState.h @@ -47,7 +47,8 @@ public: void dump(ceph::Formatter *f) const; - static void get_image_cache_state(ImageCtxT* image_ctx, Context *on_finish); + static ImageCacheState* get_image_cache_state( + ImageCtxT* image_ctx, int &r); bool is_valid(); }; diff --git a/src/librbd/exclusive_lock/PostAcquireRequest.cc b/src/librbd/exclusive_lock/PostAcquireRequest.cc index 7075090b55c4d..6c920cc8aa6a4 100644 --- a/src/librbd/exclusive_lock/PostAcquireRequest.cc +++ b/src/librbd/exclusive_lock/PostAcquireRequest.cc @@ -7,6 +7,8 @@ #include "common/dout.h" #include "common/errno.h" #include "include/stringify.h" +#include "librbd/cache/rwl/InitRequest.h" +#include "librbd/cache/rwl/ShutdownRequest.h" #include "librbd/ExclusiveLock.h" #include "librbd/ImageCtx.h" #include "librbd/ImageState.h" @@ -114,7 +116,7 @@ void PostAcquireRequest::send_open_journal() { } if (!journal_enabled) { apply(); - finish(); + send_open_image_cache(); return; } @@ -172,11 +174,73 @@ void PostAcquireRequest::handle_allocate_journal_tag(int r) { return; } + send_open_image_cache(); +} + +template +void PostAcquireRequest::send_open_image_cache() { + CephContext *cct = m_image_ctx.cct; + ldout(cct, 10) << dendl; + + using klass = PostAcquireRequest; + Context *ctx = create_async_context_callback( + m_image_ctx, create_context_callback< + klass, &klass::handle_open_image_cache>(this)); + cache::rwl::InitRequest *req = cache::rwl::InitRequest::create( + m_image_ctx, ctx); + req->send(); +} + +template +void PostAcquireRequest::handle_open_image_cache(int r) { + CephContext *cct = m_image_ctx.cct; + ldout(cct, 10) << "r=" << r << dendl; + + save_result(r); + if (r < 0) { + lderr(cct) << "failed to open image cache: " << cpp_strerror(r) + << dendl; + send_close_image_cache(); + return; + } + finish(); } +template +void PostAcquireRequest::send_close_image_cache() { + if (m_image_ctx.image_cache == nullptr) { + send_close_journal(); + } + + using klass = PostAcquireRequest; + Context *ctx = create_context_callback( + this); + cache::rwl::ShutdownRequest *req = cache::rwl::ShutdownRequest::create( + m_image_ctx, ctx); + req->send(); +} + +template +void PostAcquireRequest::handle_close_image_cache(int r) { + CephContext *cct = m_image_ctx.cct; + ldout(cct, 10) << "r=" << r << dendl; + + save_result(r); + if (r < 0) { + lderr(cct) << "failed to close image_cache: " << cpp_strerror(r) << dendl; + } + + send_close_journal(); +} + template void PostAcquireRequest::send_close_journal() { + if (m_journal == nullptr) { + send_close_object_map(); + return; + } + CephContext *cct = m_image_ctx.cct; ldout(cct, 10) << dendl; diff --git a/src/librbd/exclusive_lock/PostAcquireRequest.h b/src/librbd/exclusive_lock/PostAcquireRequest.h index 06fdce394bcf1..f908634263211 100644 --- a/src/librbd/exclusive_lock/PostAcquireRequest.h +++ b/src/librbd/exclusive_lock/PostAcquireRequest.h @@ -48,7 +48,11 @@ private: * ALLOCATE_JOURNAL_TAG * * | * * * | * * - * | v v + * v * * + * OPEN_IMAGE_CACHE * * + * | * * * + * | * * * + * | v v v * | CLOSE_JOURNAL * | | * | v @@ -91,6 +95,12 @@ private: void send_close_object_map(); void handle_close_object_map(int r); + void send_open_image_cache(); + void handle_open_image_cache(int r); + + void send_close_image_cache(); + void handle_close_image_cache(int r); + void apply(); void revert(); diff --git a/src/librbd/exclusive_lock/PreReleaseRequest.cc b/src/librbd/exclusive_lock/PreReleaseRequest.cc index 06a04f5c80ff6..fb1aa8322fb90 100644 --- a/src/librbd/exclusive_lock/PreReleaseRequest.cc +++ b/src/librbd/exclusive_lock/PreReleaseRequest.cc @@ -5,6 +5,7 @@ #include "common/AsyncOpTracker.h" #include "common/dout.h" #include "common/errno.h" +#include "librbd/cache/rwl/ShutdownRequest.h" #include "librbd/ExclusiveLock.h" #include "librbd/ImageState.h" #include "librbd/ImageWatcher.h" @@ -156,6 +157,42 @@ void PreReleaseRequest::handle_wait_for_ops(int r) { CephContext *cct = m_image_ctx.cct; ldout(cct, 10) << dendl; + send_shut_down_image_cache(); +} + +template +void PreReleaseRequest::send_shut_down_image_cache() { + CephContext *cct = m_image_ctx.cct; + ldout(cct, 10) << dendl; + + /* Shut down existing image cache whether the feature bit is on or not */ + if (!m_image_ctx.image_cache) { + send_invalidate_cache(); + return; + } + std::shared_lock owner_lock{m_image_ctx.owner_lock}; + Context *ctx = create_async_context_callback(m_image_ctx, create_context_callback< + PreReleaseRequest, + &PreReleaseRequest::handle_shut_down_image_cache>(this)); + cache::rwl::ShutdownRequest *req = cache::rwl::ShutdownRequest::create( + m_image_ctx, ctx); + req->send(); +} + +template +void PreReleaseRequest::handle_shut_down_image_cache(int r) { + CephContext *cct = m_image_ctx.cct; + ldout(cct, 10) << "r=" << r << dendl; + + if (r < 0) { + lderr(cct) << "failed to shut down image cache: " << cpp_strerror(r) + << dendl; + m_image_dispatch->unset_require_lock(io::DIRECTION_BOTH); + save_result(r); + finish(); + return; + } + send_invalidate_cache(); } diff --git a/src/librbd/exclusive_lock/PreReleaseRequest.h b/src/librbd/exclusive_lock/PreReleaseRequest.h index 66d1b0155b0d4..6063683e2d6b0 100644 --- a/src/librbd/exclusive_lock/PreReleaseRequest.h +++ b/src/librbd/exclusive_lock/PreReleaseRequest.h @@ -49,6 +49,9 @@ private: * WAIT_FOR_OPS * | * v + * SHUT_DOWN_IMAGE_CACHE + * | + * v * INVALIDATE_CACHE * | * v @@ -94,6 +97,9 @@ private: void send_wait_for_ops(); void handle_wait_for_ops(int r); + void send_shut_down_image_cache(); + void handle_shut_down_image_cache(int r); + void send_invalidate_cache(); void handle_invalidate_cache(int r); diff --git a/src/librbd/io/ImageRequest.cc b/src/librbd/io/ImageRequest.cc index e8b824f0ee6f7..ec1f36bc92cd1 100644 --- a/src/librbd/io/ImageRequest.cc +++ b/src/librbd/io/ImageRequest.cc @@ -754,7 +754,7 @@ void ImageFlushRequest::send_image_cache_request() { AioCompletion *aio_comp = this->m_aio_comp; aio_comp->set_request_count(1); C_AioRequest *req_comp = new C_AioRequest(aio_comp); - image_ctx.image_cache->aio_flush(librbd::io::FLUSH_SOURCE_USER, req_comp); + image_ctx.image_cache->aio_flush(m_flush_source, req_comp); } template diff --git a/src/test/librbd/exclusive_lock/test_mock_PostAcquireRequest.cc b/src/test/librbd/exclusive_lock/test_mock_PostAcquireRequest.cc index b18269236a7c4..9379e3ecf8955 100644 --- a/src/test/librbd/exclusive_lock/test_mock_PostAcquireRequest.cc +++ b/src/test/librbd/exclusive_lock/test_mock_PostAcquireRequest.cc @@ -3,6 +3,7 @@ #include "test/librbd/test_mock_fixture.h" #include "test/librbd/test_support.h" +#include "test/librbd/mock/cache/MockImageCache.h" #include "test/librbd/mock/MockImageCtx.h" #include "test/librbd/mock/MockImageState.h" #include "test/librbd/mock/MockJournal.h" @@ -10,8 +11,11 @@ #include "test/librbd/mock/MockObjectMap.h" #include "test/librados_test_stub/MockTestMemIoCtxImpl.h" #include "test/librados_test_stub/MockTestMemRadosClient.h" +#include "librbd/cache/rwl/InitRequest.h" +#include "librbd/cache/rwl/ShutdownRequest.h" #include "librbd/exclusive_lock/PostAcquireRequest.h" #include "librbd/image/RefreshRequest.h" + #include "gmock/gmock.h" #include "gtest/gtest.h" #include @@ -57,6 +61,52 @@ struct RefreshRequest { RefreshRequest *RefreshRequest::s_instance = nullptr; } // namespace image + +namespace cache { +namespace rwl { + +template<> +struct InitRequest { + static InitRequest *s_instance; + Context *on_finish = nullptr; + + static InitRequest *create(librbd::MockTestImageCtx &image_ctx, + Context *on_finish) { + ceph_assert(s_instance != nullptr); + s_instance->on_finish = on_finish; + return s_instance; + } + + InitRequest() { + s_instance = this; + } + MOCK_METHOD0(send, void()); +}; + +InitRequest *InitRequest::s_instance = nullptr; + +template<> +struct ShutdownRequest { + static ShutdownRequest *s_instance; + Context *on_finish = nullptr; + + static ShutdownRequest *create(librbd::MockTestImageCtx &image_ctx, + Context *on_finish) { + ceph_assert(s_instance != nullptr); + s_instance->on_finish = on_finish; + return s_instance; + } + + ShutdownRequest() { + s_instance = this; + } + MOCK_METHOD0(send, void()); +}; + +ShutdownRequest *ShutdownRequest::s_instance = nullptr; + +} // namespace rwl +} // namespace cache } // namespace librbd // template definitions @@ -88,6 +138,8 @@ class TestMockExclusiveLockPostAcquireRequest : public TestMockFixture { public: typedef PostAcquireRequest MockPostAcquireRequest; typedef librbd::image::RefreshRequest MockRefreshRequest; + typedef librbd::cache::rwl::InitRequest MockInitRequest; + typedef librbd::cache::rwl::ShutdownRequest MockShutdownRequest; void expect_test_features(MockTestImageCtx &mock_image_ctx, uint64_t features, bool enabled) { @@ -172,6 +224,18 @@ public: EXPECT_CALL(*mock_image_ctx.state, handle_prepare_lock_complete()); } + void expect_init_image_cache(MockTestImageCtx &mock_image_ctx, + MockInitRequest &mock_init_request, int r) { + EXPECT_CALL(mock_init_request, send()) + .WillOnce(FinishRequest(&mock_init_request, r, &mock_image_ctx)); + } + + void expect_close_image_cache(MockTestImageCtx &mock_image_ctx, + MockShutdownRequest &mock_shutdown_request, int r) { + EXPECT_CALL(mock_shutdown_request, send()) + .WillOnce(FinishRequest(&mock_shutdown_request, r, &mock_image_ctx)); + } + }; TEST_F(TestMockExclusiveLockPostAcquireRequest, Success) { @@ -203,6 +267,8 @@ TEST_F(TestMockExclusiveLockPostAcquireRequest, Success) { expect_get_journal_policy(mock_image_ctx, mock_journal_policy); expect_allocate_journal_tag(mock_image_ctx, mock_journal_policy, 0); + MockInitRequest mock_init_request; + expect_init_image_cache(mock_image_ctx, mock_init_request, 0); C_SaferCond acquire_ctx; C_SaferCond ctx; MockPostAcquireRequest *req = MockPostAcquireRequest::create(mock_image_ctx, @@ -233,6 +299,9 @@ TEST_F(TestMockExclusiveLockPostAcquireRequest, SuccessRefresh) { mock_image_ctx.image_lock, false); expect_handle_prepare_lock_complete(mock_image_ctx); + MockInitRequest mock_init_request; + expect_init_image_cache(mock_image_ctx, mock_init_request, 0); + C_SaferCond acquire_ctx; C_SaferCond ctx; MockPostAcquireRequest *req = MockPostAcquireRequest::create(mock_image_ctx, @@ -264,6 +333,9 @@ TEST_F(TestMockExclusiveLockPostAcquireRequest, SuccessJournalDisabled) { mock_image_ctx.image_lock, false); expect_handle_prepare_lock_complete(mock_image_ctx); + MockInitRequest mock_init_request; + expect_init_image_cache(mock_image_ctx, mock_init_request, 0); + C_SaferCond acquire_ctx; C_SaferCond ctx; MockPostAcquireRequest *req = MockPostAcquireRequest::create(mock_image_ctx, @@ -300,6 +372,9 @@ TEST_F(TestMockExclusiveLockPostAcquireRequest, SuccessObjectMapDisabled) { expect_get_journal_policy(mock_image_ctx, mock_journal_policy); expect_allocate_journal_tag(mock_image_ctx, mock_journal_policy, 0); + MockInitRequest mock_init_request; + expect_init_image_cache(mock_image_ctx, mock_init_request, 0); + C_SaferCond acquire_ctx; C_SaferCond ctx; MockPostAcquireRequest *req = MockPostAcquireRequest::create(mock_image_ctx, @@ -354,6 +429,9 @@ TEST_F(TestMockExclusiveLockPostAcquireRequest, RefreshLockDisabled) { mock_image_ctx.image_lock, false); expect_handle_prepare_lock_complete(mock_image_ctx); + MockInitRequest mock_init_request; + expect_init_image_cache(mock_image_ctx, mock_init_request, 0); + C_SaferCond acquire_ctx; C_SaferCond ctx; MockPostAcquireRequest *req = MockPostAcquireRequest::create(mock_image_ctx, @@ -442,6 +520,55 @@ TEST_F(TestMockExclusiveLockPostAcquireRequest, AllocateJournalTagError) { ASSERT_EQ(-EPERM, ctx.wait()); } +TEST_F(TestMockExclusiveLockPostAcquireRequest, InitImageCacheError) { + REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK); + + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + expect_op_work_queue(mock_image_ctx); + + InSequence seq; + expect_is_refresh_required(mock_image_ctx, false); + + MockObjectMap mock_object_map; + expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, true); + expect_create_object_map(mock_image_ctx, &mock_object_map); + expect_open_object_map(mock_image_ctx, mock_object_map, 0); + + MockJournal mock_journal; + MockJournalPolicy mock_journal_policy; + expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING, + mock_image_ctx.image_lock, true); + expect_get_journal_policy(mock_image_ctx, mock_journal_policy); + expect_journal_disabled(mock_journal_policy, false); + expect_create_journal(mock_image_ctx, &mock_journal); + expect_handle_prepare_lock_complete(mock_image_ctx); + expect_open_journal(mock_image_ctx, mock_journal, 0); + expect_get_journal_policy(mock_image_ctx, mock_journal_policy); + expect_allocate_journal_tag(mock_image_ctx, mock_journal_policy, 0); + + MockInitRequest mock_init_request; + expect_init_image_cache(mock_image_ctx, mock_init_request, -ENOENT); + + cache::MockImageCache mock_image_cache; + mock_image_ctx.image_cache = &mock_image_cache; + MockShutdownRequest mock_shutdown_request; + expect_close_image_cache(mock_image_ctx, mock_shutdown_request, 0); + + expect_close_journal(mock_image_ctx, mock_journal); + expect_close_object_map(mock_image_ctx, mock_object_map); + + C_SaferCond acquire_ctx; + C_SaferCond ctx; + MockPostAcquireRequest *req = MockPostAcquireRequest::create(mock_image_ctx, + &acquire_ctx, + &ctx); + req->send(); + ASSERT_EQ(-ENOENT, ctx.wait()); +} + TEST_F(TestMockExclusiveLockPostAcquireRequest, OpenObjectMapError) { REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP); @@ -499,6 +626,9 @@ TEST_F(TestMockExclusiveLockPostAcquireRequest, OpenObjectMapTooBig) { expect_get_journal_policy(mock_image_ctx, mock_journal_policy); expect_allocate_journal_tag(mock_image_ctx, mock_journal_policy, 0); + MockInitRequest mock_init_request; + expect_init_image_cache(mock_image_ctx, mock_init_request, 0); + C_SaferCond acquire_ctx; C_SaferCond ctx; MockPostAcquireRequest *req = MockPostAcquireRequest::create(mock_image_ctx, diff --git a/src/test/librbd/exclusive_lock/test_mock_PreReleaseRequest.cc b/src/test/librbd/exclusive_lock/test_mock_PreReleaseRequest.cc index 9812a31b818d4..d56ee1155f625 100644 --- a/src/test/librbd/exclusive_lock/test_mock_PreReleaseRequest.cc +++ b/src/test/librbd/exclusive_lock/test_mock_PreReleaseRequest.cc @@ -1,8 +1,10 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab +#include "librbd/cache/rwl/ShutdownRequest.h" #include "test/librbd/test_mock_fixture.h" #include "test/librbd/test_support.h" +#include "test/librbd/mock/cache/MockImageCache.h" #include "test/librbd/mock/MockImageCtx.h" #include "test/librbd/mock/MockJournal.h" #include "test/librbd/mock/MockObjectMap.h" @@ -11,6 +13,7 @@ #include "common/AsyncOpTracker.h" #include "librbd/exclusive_lock/ImageDispatch.h" #include "librbd/exclusive_lock/PreReleaseRequest.h" + #include "gmock/gmock.h" #include "gtest/gtest.h" #include @@ -35,6 +38,31 @@ struct ImageDispatch { }; } // namespace exclusive_lock + +namespace cache { +namespace rwl { +template<> +struct ShutdownRequest { + static ShutdownRequest *s_instance; + Context *on_finish = nullptr; + + static ShutdownRequest *create(librbd::MockTestImageCtx &image_ctx, + Context *on_finish) { + ceph_assert(s_instance != nullptr); + s_instance->on_finish = on_finish; + return s_instance; + } + + ShutdownRequest() { + s_instance = this; + } + MOCK_METHOD0(send, void()); +}; + +ShutdownRequest *ShutdownRequest::s_instance = nullptr; + +} // namespace rwl +} // namespace cache } // namespace librbd // template definitions @@ -65,6 +93,7 @@ class TestMockExclusiveLockPreReleaseRequest : public TestMockFixture { public: typedef ImageDispatch MockImageDispatch; typedef PreReleaseRequest MockPreReleaseRequest; + typedef librbd::cache::rwl::ShutdownRequest MockShutdownRequest; void expect_complete_context(MockContext &mock_context, int r) { EXPECT_CALL(mock_context, complete(r)); @@ -118,6 +147,12 @@ public: .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue)); } + void expect_close_image_cache(MockTestImageCtx &mock_image_ctx, + MockShutdownRequest &mock_shutdown_req, int r) { + EXPECT_CALL(mock_shutdown_req, send()) + .WillOnce(FinishRequest(&mock_shutdown_req, r, &mock_image_ctx)); + } + void expect_invalidate_cache(MockTestImageCtx &mock_image_ctx, int r) { EXPECT_CALL(*mock_image_ctx.io_object_dispatcher, invalidate_cache(_)) @@ -158,6 +193,12 @@ TEST_F(TestMockExclusiveLockPreReleaseRequest, Success) { expect_cancel_op_requests(mock_image_ctx, 0); MockImageDispatch mock_image_dispatch; expect_set_require_lock(mock_image_ctx, mock_image_dispatch, 0); + + cache::MockImageCache mock_image_cache; + mock_image_ctx.image_cache = &mock_image_cache; + MockShutdownRequest mock_shutdown_request; + expect_close_image_cache(mock_image_ctx, mock_shutdown_request, 0); + expect_invalidate_cache(mock_image_ctx, 0); expect_flush_notifies(mock_image_ctx); @@ -194,6 +235,12 @@ TEST_F(TestMockExclusiveLockPreReleaseRequest, SuccessJournalDisabled) { InSequence seq; expect_prepare_lock(mock_image_ctx); expect_cancel_op_requests(mock_image_ctx, 0); + + cache::MockImageCache mock_image_cache; + mock_image_ctx.image_cache = &mock_image_cache; + MockShutdownRequest mock_shutdown_request; + expect_close_image_cache(mock_image_ctx, mock_shutdown_request, 0); + expect_invalidate_cache(mock_image_ctx, 0); expect_flush_notifies(mock_image_ctx); @@ -225,6 +272,12 @@ TEST_F(TestMockExclusiveLockPreReleaseRequest, SuccessObjectMapDisabled) { InSequence seq; expect_cancel_op_requests(mock_image_ctx, 0); + + cache::MockImageCache mock_image_cache; + mock_image_ctx.image_cache = &mock_image_cache; + MockShutdownRequest mock_shutdown_request; + expect_close_image_cache(mock_image_ctx, mock_shutdown_request, 0); + expect_invalidate_cache(mock_image_ctx, 0); expect_flush_notifies(mock_image_ctx); @@ -251,6 +304,12 @@ TEST_F(TestMockExclusiveLockPreReleaseRequest, Blacklisted) { expect_cancel_op_requests(mock_image_ctx, 0); MockImageDispatch mock_image_dispatch; expect_set_require_lock(mock_image_ctx, mock_image_dispatch, -EBLACKLISTED); + + cache::MockImageCache mock_image_cache; + mock_image_ctx.image_cache = &mock_image_cache; + MockShutdownRequest mock_shutdown_request; + expect_close_image_cache(mock_image_ctx, mock_shutdown_request, 0); + expect_invalidate_cache(mock_image_ctx, -EBLACKLISTED); expect_flush_notifies(mock_image_ctx); diff --git a/src/test/librbd/object_map/test_mock_UpdateRequest.cc b/src/test/librbd/object_map/test_mock_UpdateRequest.cc index 20683ac6957ea..c240dec00046e 100644 --- a/src/test/librbd/object_map/test_mock_UpdateRequest.cc +++ b/src/test/librbd/object_map/test_mock_UpdateRequest.cc @@ -234,6 +234,7 @@ TEST_F(TestMockObjectMapUpdateRequest, BatchUpdate) { no_progress)); ASSERT_EQ(0, acquire_exclusive_lock(*ictx)); + expect_unlock_exclusive_lock(*ictx); InSequence seq; expect_update(ictx, CEPH_NOSNAP, 0, 262144, OBJECT_NONEXISTENT, OBJECT_EXISTS, 0); @@ -241,7 +242,6 @@ TEST_F(TestMockObjectMapUpdateRequest, BatchUpdate) { OBJECT_EXISTS, 0); expect_update(ictx, CEPH_NOSNAP, 524288, 712312, OBJECT_NONEXISTENT, OBJECT_EXISTS, 0); - expect_unlock_exclusive_lock(*ictx); ceph::shared_mutex object_map_lock = ceph::make_shared_mutex("lock"); ceph::BitVector<2> object_map; diff --git a/src/test/librbd/test_Migration.cc b/src/test/librbd/test_Migration.cc index f6a631a907044..73ae1483cb08d 100644 --- a/src/test/librbd/test_Migration.cc +++ b/src/test/librbd/test_Migration.cc @@ -271,8 +271,8 @@ struct TestMigration : public TestFixture { } void flush() { - ASSERT_EQ(0, api::Io<>::flush(*m_ref_ictx)); - ASSERT_EQ(0, api::Io<>::flush(*m_ictx)); + ASSERT_EQ(0, TestFixture::flush_writeback_cache(m_ref_ictx)); + ASSERT_EQ(0, TestFixture::flush_writeback_cache(m_ictx)); } void snap_create(const std::string &snap_name) { @@ -540,6 +540,7 @@ librados::IoCtx TestMigration::_other_pool_ioctx; TEST_F(TestMigration, Empty) { uint64_t features = m_ictx->features ^ RBD_FEATURE_LAYERING; + features &= ~RBD_FEATURE_DIRTY_CACHE; ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_FEATURES, features)); migrate(m_ioctx, m_image_name); diff --git a/src/test/librbd/test_fixture.cc b/src/test/librbd/test_fixture.cc index 15409d5676ffd..76055e698cab5 100644 --- a/src/test/librbd/test_fixture.cc +++ b/src/test/librbd/test_fixture.cc @@ -1,11 +1,13 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab +#include "common/Cond.h" #include "test/librbd/test_fixture.h" #include "test/librbd/test_support.h" #include "include/stringify.h" #include "librbd/ExclusiveLock.h" #include "librbd/ImageState.h" #include "librbd/ImageWatcher.h" +#include "librbd/io/ImageDispatchSpec.h" #include "librbd/Operations.h" #include "librbd/api/Io.h" #include "cls/lock/cls_lock_client.h" @@ -144,3 +146,19 @@ int TestFixture::acquire_exclusive_lock(librbd::ImageCtx &ictx) { ceph_assert(ictx.exclusive_lock != nullptr); return ictx.exclusive_lock->is_lock_owner() ? 0 : -EINVAL; } + +int TestFixture::flush_writeback_cache(librbd::ImageCtx *image_ctx) { + if (image_ctx->test_features(RBD_FEATURE_DIRTY_CACHE)) { + // cache exists. Close to flush data + C_SaferCond ctx; + auto aio_comp = librbd::io::AioCompletion::create_and_start( + &ctx, image_ctx, librbd::io::AIO_TYPE_FLUSH); + auto req = librbd::io::ImageDispatchSpec<>::create_flush( + *image_ctx, librbd::io::IMAGE_DISPATCH_LAYER_INTERNAL_START, aio_comp, + librbd::io::FLUSH_SOURCE_INTERNAL, {}); + req->send(); + return ctx.wait(); + } else { + return librbd::api::Io<>::flush(*image_ctx); + } +} diff --git a/src/test/librbd/test_fixture.h b/src/test/librbd/test_fixture.h index 508e4405c6cf3..d3bd7b8121eff 100644 --- a/src/test/librbd/test_fixture.h +++ b/src/test/librbd/test_fixture.h @@ -36,6 +36,8 @@ public: const std::string &cookie); int unlock_image(); + int flush_writeback_cache(librbd::ImageCtx *image_ctx); + int acquire_exclusive_lock(librbd::ImageCtx &ictx); static std::string _pool_name; diff --git a/src/test/librbd/test_internal.cc b/src/test/librbd/test_internal.cc index 3164e3e7b7eff..222bca832ea52 100644 --- a/src/test/librbd/test_internal.cc +++ b/src/test/librbd/test_internal.cc @@ -538,7 +538,12 @@ TEST_F(TestInternal, Metadata) { map pairs; r = librbd::metadata_list(ictx, "", 0, &pairs); ASSERT_EQ(0, r); - ASSERT_EQ(5u, pairs.size()); + + uint8_t original_pairs_num = 0; + if (ictx->test_features(RBD_FEATURE_DIRTY_CACHE)) { + original_pairs_num = 1; + } + ASSERT_EQ(original_pairs_num + 5, pairs.size()); r = ictx->operations->metadata_remove("abcd"); ASSERT_EQ(0, r); r = ictx->operations->metadata_remove("xyz"); @@ -546,7 +551,7 @@ TEST_F(TestInternal, Metadata) { pairs.clear(); r = librbd::metadata_list(ictx, "", 0, &pairs); ASSERT_EQ(0, r); - ASSERT_EQ(3u, pairs.size()); + ASSERT_EQ(original_pairs_num + 3, pairs.size()); string val; r = librbd::metadata_get(ictx, it->first, &val); ASSERT_EQ(0, r); @@ -611,6 +616,7 @@ TEST_F(TestInternal, SnapshotCopyup) ASSERT_EQ(256, api::Io<>::write(*ictx2, 256, bl.length(), bufferlist{bl}, 0)); + ASSERT_EQ(0, flush_writeback_cache(ictx2)); librados::IoCtx snap_ctx; snap_ctx.dup(ictx2->data_ctx); snap_ctx.snap_set_read(CEPH_SNAPDIR); @@ -752,8 +758,9 @@ TEST_F(TestInternal, SnapshotCopyupZeros) bufferlist bl; bl.append(std::string(256, '1')); - ASSERT_EQ(256, api::Io<>::write(*ictx2, 256, bl.length(), bufferlist{bl}, - 0)); + ASSERT_EQ(256, api::Io<>::write(*ictx2, 256, bl.length(), bufferlist{bl}, 0)); + + ASSERT_EQ(0, flush_writeback_cache(ictx2)); librados::IoCtx snap_ctx; snap_ctx.dup(ictx2->data_ctx); @@ -1106,7 +1113,7 @@ TEST_F(TestInternal, WriteFullCopyup) { bl.append(std::string(1 << ictx->order, '1')); ASSERT_EQ((ssize_t)bl.length(), api::Io<>::write(*ictx, 0, bl.length(), bufferlist{bl}, 0)); - ASSERT_EQ(0, api::Io<>::flush(*ictx)); + ASSERT_EQ(0, flush_writeback_cache(ictx)); ASSERT_EQ(0, create_snapshot("snap1", true)); @@ -1417,7 +1424,8 @@ TEST_F(TestInternal, FlattenNoEmptyObjects) ASSERT_EQ(TEST_IO_SIZE, image.write(itr->second, TEST_IO_SIZE, bl)); } - ASSERT_EQ(0, image.flush()); + ASSERT_EQ(0, image.close()); + ASSERT_EQ(0, m_rbd.open(m_ioctx, image, m_image_name.c_str(), NULL)); bufferlist readbl; printf("verify written data by reading\n"); @@ -1602,7 +1610,7 @@ TEST_F(TestInternal, Sparsify) { api::Io<>::write(*ictx, (1 << ictx->order) * 10 + 4096 * 10, bl2.length(), bufferlist{bl2}, 0)); - ASSERT_EQ(0, api::Io<>::flush(*ictx)); + ASSERT_EQ(0, flush_writeback_cache(ictx)); ASSERT_EQ(0, ictx->operations->sparsify(4096, no_op)); @@ -1690,7 +1698,7 @@ TEST_F(TestInternal, SparsifyClone) { ASSERT_EQ((ssize_t)bl.length(), api::Io<>::write(*ictx, (1 << ictx->order) * 10, bl.length(), bufferlist{bl}, 0)); - ASSERT_EQ(0, api::Io<>::flush(*ictx)); + ASSERT_EQ(0, flush_writeback_cache(ictx)); ASSERT_EQ(0, ictx->operations->sparsify(4096, no_op)); diff --git a/src/test/librbd/test_librbd.cc b/src/test/librbd/test_librbd.cc index 1a4e41c0f2c2a..9218da393a9f9 100644 --- a/src/test/librbd/test_librbd.cc +++ b/src/test/librbd/test_librbd.cc @@ -198,7 +198,7 @@ public: rados_shutdown(_cluster); _rados.wait_for_latest_osdmap(); _pool_names.insert(_pool_names.end(), _unique_pool_names.begin(), - _unique_pool_names.end()); + _unique_pool_names.end()); for (size_t i = 1; i < _pool_names.size(); ++i) { ASSERT_EQ(0, _rados.pool_delete(_pool_names[i].c_str())); } @@ -217,6 +217,26 @@ public: return value == "true"; } + bool is_skip_partial_discard_enabled(rbd_image_t image) { + if (is_skip_partial_discard_enabled()) { + rbd_flush(image); + uint64_t features; + EXPECT_EQ(0, rbd_get_features(image, &features)); + return !(features & RBD_FEATURE_DIRTY_CACHE); + } + return false; + } + + bool is_skip_partial_discard_enabled(librbd::Image& image) { + if (is_skip_partial_discard_enabled()) { + image.flush(); + uint64_t features; + EXPECT_EQ(0, image.features(&features)); + return !(features & RBD_FEATURE_DIRTY_CACHE); + } + return false; + } + void validate_object_map(rbd_image_t image, bool *passed) { uint64_t flags; ASSERT_EQ(0, rbd_get_flags(image, &flags)); @@ -984,7 +1004,7 @@ TEST_F(TestLibRBD, TestCopy) ASSERT_EQ(0, rbd_copy(image, ioctx, name2.c_str())); ASSERT_EQ(2, test_ls(ioctx, 2, name.c_str(), name2.c_str())); ASSERT_EQ(0, rbd_open(ioctx, name2.c_str(), &image2, NULL)); - ASSERT_EQ(0, rbd_metadata_list(image2, "", 70, keys, &keys_len, vals, + ASSERT_EQ(0, rbd_metadata_list(image2, "key", 70, keys, &keys_len, vals, &vals_len)); ASSERT_EQ(keys_len, sum_key_len); ASSERT_EQ(vals_len, sum_value_len); @@ -1005,7 +1025,7 @@ TEST_F(TestLibRBD, TestCopy) keys_len = sizeof(keys); vals_len = sizeof(vals); ASSERT_EQ(0, rbd_open(ioctx, name3.c_str(), &image3, NULL)); - ASSERT_EQ(0, rbd_metadata_list(image3, "", 70, keys, &keys_len, vals, + ASSERT_EQ(0, rbd_metadata_list(image3, "key", 70, keys, &keys_len, vals, &vals_len)); ASSERT_EQ(keys_len, sum_key_len); ASSERT_EQ(vals_len, sum_value_len); @@ -1168,7 +1188,7 @@ TEST_F(TestLibRBD, TestDeepCopy) BOOST_SCOPE_EXIT_ALL( (&image2) ) { ASSERT_EQ(0, rbd_close(image2)); }; - ASSERT_EQ(0, rbd_metadata_list(image2, "", 70, keys, &keys_len, vals, + ASSERT_EQ(0, rbd_metadata_list(image2, "key", 70, keys, &keys_len, vals, &vals_len)); ASSERT_EQ(keys_len, sum_key_len); ASSERT_EQ(vals_len, sum_value_len); @@ -1192,7 +1212,7 @@ TEST_F(TestLibRBD, TestDeepCopy) BOOST_SCOPE_EXIT_ALL( (&image3) ) { ASSERT_EQ(0, rbd_close(image3)); }; - ASSERT_EQ(0, rbd_metadata_list(image3, "", 70, keys, &keys_len, vals, + ASSERT_EQ(0, rbd_metadata_list(image3, "key", 70, keys, &keys_len, vals, &vals_len)); ASSERT_EQ(keys_len, sum_key_len); ASSERT_EQ(vals_len, sum_value_len); @@ -1228,7 +1248,7 @@ TEST_F(TestLibRBD, TestDeepCopy) BOOST_SCOPE_EXIT_ALL( (&image5) ) { ASSERT_EQ(0, rbd_close(image5)); }; - ASSERT_EQ(0, rbd_metadata_list(image5, "", 70, keys, &keys_len, vals, + ASSERT_EQ(0, rbd_metadata_list(image5, "key", 70, keys, &keys_len, vals, &vals_len)); ASSERT_EQ(keys_len, sum_key_len); ASSERT_EQ(vals_len, sum_value_len); @@ -1253,7 +1273,7 @@ TEST_F(TestLibRBD, TestDeepCopy) BOOST_SCOPE_EXIT_ALL( (&image6) ) { ASSERT_EQ(0, rbd_close(image6)); }; - ASSERT_EQ(0, rbd_metadata_list(image6, "", 70, keys, &keys_len, vals, + ASSERT_EQ(0, rbd_metadata_list(image6, "key", 70, keys, &keys_len, vals, &vals_len)); ASSERT_EQ(keys_len, sum_key_len); ASSERT_EQ(vals_len, sum_value_len); @@ -1941,8 +1961,6 @@ TEST_F(TestLibRBD, TestIO) rados_ioctx_t ioctx; rados_ioctx_create(_cluster, m_pool_name.c_str(), &ioctx); - bool skip_discard = is_skip_partial_discard_enabled(); - rbd_image_t image; int order = 0; std::string name = get_temp_image_name(); @@ -1951,7 +1969,9 @@ TEST_F(TestLibRBD, TestIO) ASSERT_EQ(0, create_image(ioctx, name.c_str(), size, &order)); ASSERT_EQ(0, rados_conf_set(_cluster, "rbd_read_from_replica_policy", "balance")); ASSERT_EQ(0, rbd_open(ioctx, name.c_str(), &image, NULL)); - + + bool skip_discard = is_skip_partial_discard_enabled(image); + char test_data[TEST_IO_SIZE + 1]; char zero_data[TEST_IO_SIZE + 1]; char mismatch_data[TEST_IO_SIZE + 1]; @@ -2063,8 +2083,6 @@ TEST_F(TestLibRBD, TestIOWithIOHint) rados_ioctx_t ioctx; rados_ioctx_create(_cluster, m_pool_name.c_str(), &ioctx); - bool skip_discard = is_skip_partial_discard_enabled(); - rbd_image_t image; int order = 0; std::string name = get_temp_image_name(); @@ -2073,6 +2091,8 @@ TEST_F(TestLibRBD, TestIOWithIOHint) ASSERT_EQ(0, create_image(ioctx, name.c_str(), size, &order)); ASSERT_EQ(0, rbd_open(ioctx, name.c_str(), &image, NULL)); + bool skip_discard = is_skip_partial_discard_enabled(image); + char test_data[TEST_IO_SIZE + 1]; char zero_data[TEST_IO_SIZE + 1]; char mismatch_data[TEST_IO_SIZE + 1]; @@ -2209,8 +2229,6 @@ TEST_F(TestLibRBD, TestDataPoolIO) std::string data_pool_name = create_pool(true); - bool skip_discard = is_skip_partial_discard_enabled(); - rbd_image_t image; std::string name = get_temp_image_name(); uint64_t size = 2 << 20; @@ -2237,6 +2255,8 @@ TEST_F(TestLibRBD, TestDataPoolIO) ASSERT_EQ(0, rbd_open(ioctx, name.c_str(), &image, NULL)); ASSERT_NE(-1, rbd_get_data_pool_id(image)); + bool skip_discard = is_skip_partial_discard_enabled(image); + char test_data[TEST_IO_SIZE + 1]; char zero_data[TEST_IO_SIZE + 1]; int i; @@ -2685,8 +2705,6 @@ TEST_F(TestLibRBD, TestIOPP) librados::IoCtx ioctx; ASSERT_EQ(0, _rados.ioctx_create(m_pool_name.c_str(), ioctx)); - bool skip_discard = is_skip_partial_discard_enabled(); - { librbd::RBD rbd; librbd::Image image; @@ -2697,6 +2715,8 @@ TEST_F(TestLibRBD, TestIOPP) ASSERT_EQ(0, create_image_pp(rbd, ioctx, name.c_str(), size, &order)); ASSERT_EQ(0, rbd.open(ioctx, image, name.c_str(), NULL)); + bool skip_discard = this->is_skip_partial_discard_enabled(image); + char test_data[TEST_IO_SIZE + 1]; char zero_data[TEST_IO_SIZE + 1]; int i; @@ -3050,7 +3070,7 @@ TEST_F(TestLibRBD, TestClone) printf("sizes and overlaps are good between parent and child\n"); // check key/value pairs in child image - ASSERT_EQ(0, rbd_metadata_list(child, "", 70, keys, &keys_len, vals, + ASSERT_EQ(0, rbd_metadata_list(child, "key", 70, keys, &keys_len, vals, &vals_len)); ASSERT_EQ(sum_key_len, keys_len); ASSERT_EQ(sum_value_len, vals_len); @@ -3184,7 +3204,7 @@ TEST_F(TestLibRBD, TestClone2) printf("made and opened clone \"child\"\n"); // check key/value pairs in child image - ASSERT_EQ(0, rbd_metadata_list(child, "", 70, keys, &keys_len, vals, + ASSERT_EQ(0, rbd_metadata_list(child, "key", 70, keys, &keys_len, vals, &vals_len)); ASSERT_EQ(sum_key_len, keys_len); ASSERT_EQ(sum_value_len, vals_len); @@ -3950,8 +3970,6 @@ TYPED_TEST(DiffIterateTest, DiffIterate) librados::IoCtx ioctx; ASSERT_EQ(0, this->_rados.ioctx_create(this->m_pool_name.c_str(), ioctx)); - bool skip_discard = this->is_skip_partial_discard_enabled(); - { librbd::RBD rbd; librbd::Image image; @@ -3962,6 +3980,8 @@ TYPED_TEST(DiffIterateTest, DiffIterate) ASSERT_EQ(0, create_image_pp(rbd, ioctx, name.c_str(), size, &order)); ASSERT_EQ(0, rbd.open(ioctx, image, name.c_str(), NULL)); + bool skip_discard = this->is_skip_partial_discard_enabled(image); + uint64_t object_size = 0; if (this->whole_object) { object_size = 1 << order; @@ -4097,11 +4117,10 @@ TYPED_TEST(DiffIterateTest, DiffIterateDiscard) TYPED_TEST(DiffIterateTest, DiffIterateStress) { + REQUIRE(!is_rbd_rwl_enabled((CephContext *)this->_rados.cct())); librados::IoCtx ioctx; ASSERT_EQ(0, this->_rados.ioctx_create(this->m_pool_name.c_str(), ioctx)); - bool skip_discard = this->is_skip_partial_discard_enabled(); - librbd::RBD rbd; librbd::Image image; int order = 0; @@ -4111,6 +4130,8 @@ TYPED_TEST(DiffIterateTest, DiffIterateStress) ASSERT_EQ(0, create_image_pp(rbd, ioctx, name.c_str(), size, &order)); ASSERT_EQ(0, rbd.open(ioctx, image, name.c_str(), NULL)); + bool skip_discard = this->is_skip_partial_discard_enabled(image); + uint64_t object_size = 0; if (this->whole_object) { object_size = 1 << order; @@ -4221,8 +4242,6 @@ TYPED_TEST(DiffIterateTest, DiffIterateIgnoreParent) librados::IoCtx ioctx; ASSERT_EQ(0, this->_rados.ioctx_create(this->m_pool_name.c_str(), ioctx)); - bool skip_discard = this->is_skip_partial_discard_enabled(); - librbd::RBD rbd; librbd::Image image; std::string name = this->get_temp_image_name(); @@ -4232,6 +4251,8 @@ TYPED_TEST(DiffIterateTest, DiffIterateIgnoreParent) ASSERT_EQ(0, create_image_pp(rbd, ioctx, name.c_str(), size, &order)); ASSERT_EQ(0, rbd.open(ioctx, image, name.c_str(), NULL)); + bool skip_discard = this->is_skip_partial_discard_enabled(image); + uint64_t object_size = 0; if (this->whole_object) { object_size = 1 << order; @@ -4272,8 +4293,6 @@ TYPED_TEST(DiffIterateTest, DiffIterateCallbackError) librados::IoCtx ioctx; ASSERT_EQ(0, this->_rados.ioctx_create(this->m_pool_name.c_str(), ioctx)); - bool skip_discard = this->is_skip_partial_discard_enabled(); - { librbd::RBD rbd; librbd::Image image; @@ -4284,6 +4303,8 @@ TYPED_TEST(DiffIterateTest, DiffIterateCallbackError) ASSERT_EQ(0, create_image_pp(rbd, ioctx, name.c_str(), size, &order)); ASSERT_EQ(0, rbd.open(ioctx, image, name.c_str(), NULL)); + bool skip_discard = this->is_skip_partial_discard_enabled(image); + interval_set exists; interval_set one; scribble(image, 10, 102400, skip_discard, &exists, &one); @@ -4304,8 +4325,6 @@ TYPED_TEST(DiffIterateTest, DiffIterateParentDiscard) librados::IoCtx ioctx; ASSERT_EQ(0, this->_rados.ioctx_create(this->m_pool_name.c_str(), ioctx)); - bool skip_discard = this->is_skip_partial_discard_enabled(); - librbd::RBD rbd; librbd::Image image; std::string name = this->get_temp_image_name(); @@ -4315,6 +4334,8 @@ TYPED_TEST(DiffIterateTest, DiffIterateParentDiscard) ASSERT_EQ(0, create_image_pp(rbd, ioctx, name.c_str(), size, &order)); ASSERT_EQ(0, rbd.open(ioctx, image, name.c_str(), NULL)); + bool skip_discard = this->is_skip_partial_discard_enabled(image); + uint64_t object_size = 0; if (this->whole_object) { object_size = 1 << order; @@ -5413,7 +5434,7 @@ TEST_F(TestLibRBD, Metadata) memset_rand(keys, keys_len); memset_rand(vals, vals_len); - ASSERT_EQ(0, rbd_metadata_list(image, "", 0, keys, &keys_len, vals, + ASSERT_EQ(0, rbd_metadata_list(image, "key", 0, keys, &keys_len, vals, &vals_len)); ASSERT_EQ(0U, keys_len); ASSERT_EQ(0U, vals_len); @@ -5430,13 +5451,13 @@ TEST_F(TestLibRBD, Metadata) ASSERT_EQ(-ERANGE, rbd_metadata_get(image1, "key1", value, &value_len)); ASSERT_EQ(value_len, strlen("value1") + 1); - ASSERT_EQ(-ERANGE, rbd_metadata_list(image1, "", 0, keys, &keys_len, vals, + ASSERT_EQ(-ERANGE, rbd_metadata_list(image1, "key", 0, keys, &keys_len, vals, &vals_len)); keys_len = sizeof(keys); vals_len = sizeof(vals); memset_rand(keys, keys_len); memset_rand(vals, vals_len); - ASSERT_EQ(0, rbd_metadata_list(image1, "", 0, keys, &keys_len, vals, + ASSERT_EQ(0, rbd_metadata_list(image1, "key", 0, keys, &keys_len, vals, &vals_len)); ASSERT_EQ(keys_len, strlen("key1") + 1 + strlen("key2") + 1); ASSERT_EQ(vals_len, strlen("value1") + 1 + strlen("value2") + 1); @@ -5449,7 +5470,7 @@ TEST_F(TestLibRBD, Metadata) ASSERT_EQ(-ENOENT, rbd_metadata_remove(image1, "key3")); value_len = sizeof(value); ASSERT_EQ(-ENOENT, rbd_metadata_get(image1, "key3", value, &value_len)); - ASSERT_EQ(0, rbd_metadata_list(image1, "", 0, keys, &keys_len, vals, + ASSERT_EQ(0, rbd_metadata_list(image1, "key", 0, keys, &keys_len, vals, &vals_len)); ASSERT_EQ(keys_len, strlen("key2") + 1); ASSERT_EQ(vals_len, strlen("value2") + 1); @@ -5473,7 +5494,7 @@ TEST_F(TestLibRBD, Metadata) vals_len = sizeof(vals); memset_rand(keys, keys_len); memset_rand(vals, vals_len); - ASSERT_EQ(0, rbd_metadata_list(image1, "", 0, keys, &keys_len, vals, + ASSERT_EQ(0, rbd_metadata_list(image1, "key", 0, keys, &keys_len, vals, &vals_len)); ASSERT_EQ(keys_len, strlen("key1") + 1 + strlen("key2") + 1 + strlen("key3") + 1); @@ -5491,7 +5512,7 @@ TEST_F(TestLibRBD, Metadata) vals_len = sizeof(vals); memset_rand(keys, keys_len); memset_rand(vals, vals_len); - ASSERT_EQ(0, rbd_metadata_list(image1, "", 0, keys, &keys_len, vals, + ASSERT_EQ(0, rbd_metadata_list(image1, "key", 0, keys, &keys_len, vals, &vals_len)); ASSERT_EQ(keys_len, strlen("key1") + 1 + strlen("key2") + 1 + strlen("key3") + 1); @@ -5519,7 +5540,7 @@ TEST_F(TestLibRBD, Metadata) vals_len = sizeof(vals); memset_rand(keys, keys_len); memset_rand(vals, vals_len); - ASSERT_EQ(0, rbd_metadata_list(image2, "", 0, keys, &keys_len, vals, + ASSERT_EQ(0, rbd_metadata_list(image2, "key", 0, keys, &keys_len, vals, &vals_len)); ASSERT_EQ(keys_len, strlen("key1") + 1 + strlen("key2") + 1 + strlen("key3") + 1 + strlen("key4") + 1); @@ -5530,7 +5551,7 @@ TEST_F(TestLibRBD, Metadata) ASSERT_STREQ(vals + strlen("value1") + 1 + strlen("value2") + 1 + strlen("value3") + 1, "value4"); - ASSERT_EQ(0, rbd_metadata_list(image1, "", 0, keys, &keys_len, vals, + ASSERT_EQ(0, rbd_metadata_list(image1, "key", 0, keys, &keys_len, vals, &vals_len)); ASSERT_EQ(keys_len, strlen("key1") + 1 + strlen("key2") + 1 + strlen("key3") + 1); @@ -5543,19 +5564,19 @@ TEST_F(TestLibRBD, Metadata) vals_len = strlen("value1") + 1; memset_rand(keys, keys_len); memset_rand(vals, vals_len); - ASSERT_EQ(0, rbd_metadata_list(image2, "", 1, keys, &keys_len, vals, + ASSERT_EQ(0, rbd_metadata_list(image2, "key", 1, keys, &keys_len, vals, &vals_len)); ASSERT_EQ(keys_len, strlen("key1") + 1); ASSERT_EQ(vals_len, strlen("value1") + 1); ASSERT_STREQ(keys, "key1"); ASSERT_STREQ(vals, "value1"); - ASSERT_EQ(-ERANGE, rbd_metadata_list(image2, "", 2, keys, &keys_len, vals, + ASSERT_EQ(-ERANGE, rbd_metadata_list(image2, "key", 2, keys, &keys_len, vals, &vals_len)); ASSERT_EQ(keys_len, strlen("key1") + 1 + strlen("key2") + 1); ASSERT_EQ(vals_len, strlen("value1") + 1 + strlen("value2") + 1); - ASSERT_EQ(-ERANGE, rbd_metadata_list(image2, "", 0, keys, &keys_len, vals, + ASSERT_EQ(-ERANGE, rbd_metadata_list(image2, "key", 0, keys, &keys_len, vals, &vals_len)); ASSERT_EQ(keys_len, strlen("key1") + 1 + strlen("key2") + 1 + strlen("key3") + 1 + strlen("key4") + 1); @@ -5598,14 +5619,14 @@ TEST_F(TestLibRBD, MetadataPP) librbd::Image image1; ASSERT_EQ(0, rbd.open(ioctx, image1, name.c_str(), NULL)); map pairs; - ASSERT_EQ(0, image1.metadata_list("", 0, &pairs)); + ASSERT_EQ(0, image1.metadata_list("key", 0, &pairs)); ASSERT_TRUE(pairs.empty()); ASSERT_EQ(0, image1.metadata_set("key1", "value1")); ASSERT_EQ(0, image1.metadata_set("key2", "value2")); ASSERT_EQ(0, image1.metadata_get("key1", &value)); ASSERT_EQ(0, strcmp("value1", value.c_str())); - ASSERT_EQ(0, image1.metadata_list("", 0, &pairs)); + ASSERT_EQ(0, image1.metadata_list("key", 0, &pairs)); ASSERT_EQ(2U, pairs.size()); ASSERT_EQ(0, strncmp("value1", pairs["key1"].c_str(), 6)); ASSERT_EQ(0, strncmp("value2", pairs["key2"].c_str(), 6)); @@ -5614,7 +5635,7 @@ TEST_F(TestLibRBD, MetadataPP) ASSERT_EQ(0, image1.metadata_remove("key1")); ASSERT_EQ(-ENOENT, image1.metadata_remove("key3")); ASSERT_TRUE(image1.metadata_get("key3", &value) < 0); - ASSERT_EQ(0, image1.metadata_list("", 0, &pairs)); + ASSERT_EQ(0, image1.metadata_list("key", 0, &pairs)); ASSERT_EQ(1U, pairs.size()); ASSERT_EQ(0, strncmp("value2", pairs["key2"].c_str(), 6)); @@ -5631,14 +5652,14 @@ TEST_F(TestLibRBD, MetadataPP) pairs.clear(); ASSERT_EQ(0, image1.metadata_set("key1", "value1")); ASSERT_EQ(0, image1.metadata_set("key3", "value3")); - ASSERT_EQ(0, image1.metadata_list("", 0, &pairs)); + ASSERT_EQ(0, image1.metadata_list("key", 0, &pairs)); ASSERT_EQ(3U, pairs.size()); ASSERT_EQ(0, strncmp("value1", pairs["key1"].c_str(), 6)); ASSERT_EQ(0, strncmp("value2", pairs["key2"].c_str(), 6)); ASSERT_EQ(0, strncmp("value3", pairs["key3"].c_str(), 6)); ASSERT_EQ(0, image1.snap_set(NULL)); - ASSERT_EQ(0, image1.metadata_list("", 0, &pairs)); + ASSERT_EQ(0, image1.metadata_list("key", 0, &pairs)); ASSERT_EQ(3U, pairs.size()); ASSERT_EQ(0, strncmp("value1", pairs["key1"].c_str(), 6)); ASSERT_EQ(0, strncmp("value2", pairs["key2"].c_str(), 6)); @@ -5653,10 +5674,10 @@ TEST_F(TestLibRBD, MetadataPP) ASSERT_EQ(0, rbd.open(ioctx, image2, cname.c_str(), NULL)); ASSERT_EQ(0, image2.metadata_set("key4", "value4")); pairs.clear(); - ASSERT_EQ(0, image2.metadata_list("", 0, &pairs)); + ASSERT_EQ(0, image2.metadata_list("key", 0, &pairs)); ASSERT_EQ(4U, pairs.size()); pairs.clear(); - ASSERT_EQ(0, image1.metadata_list("", 0, &pairs)); + ASSERT_EQ(0, image1.metadata_list("key", 0, &pairs)); ASSERT_EQ(3U, pairs.size()); ASSERT_EQ(-ENOENT, image1.metadata_get("key4", &value)); } @@ -5949,8 +5970,6 @@ TEST_F(TestLibRBD, BlockingAIO) librados::IoCtx ioctx; ASSERT_EQ(0, _rados.ioctx_create(m_pool_name.c_str(), ioctx)); - bool skip_discard = is_skip_partial_discard_enabled(); - librbd::RBD rbd; std::string name = get_temp_image_name(); uint64_t size = 1 << 20; @@ -5968,6 +5987,8 @@ TEST_F(TestLibRBD, BlockingAIO) librbd::Image image; ASSERT_EQ(0, rbd.open(ioctx, image, name.c_str(), NULL)); + bool skip_discard = this->is_skip_partial_discard_enabled(image); + bufferlist bl; ASSERT_EQ(0, image.write(0, bl.length(), bl)); @@ -6826,6 +6847,7 @@ TEST_F(TestLibRBD, ExclusiveLock) TEST_F(TestLibRBD, BreakLock) { REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK); + REQUIRE(!is_rbd_rwl_enabled((CephContext *)_rados.cct())); static char buf[10]; @@ -6877,8 +6899,6 @@ TEST_F(TestLibRBD, BreakLock) TEST_F(TestLibRBD, DiscardAfterWrite) { - REQUIRE(!is_skip_partial_discard_enabled()); - librados::IoCtx ioctx; ASSERT_EQ(0, _rados.ioctx_create(m_pool_name.c_str(), ioctx)); @@ -6891,6 +6911,10 @@ TEST_F(TestLibRBD, DiscardAfterWrite) librbd::Image image; ASSERT_EQ(0, rbd.open(ioctx, image, name.c_str(), NULL)); + if (this->is_skip_partial_discard_enabled(image)) { + return; + } + // enable writeback cache ASSERT_EQ(0, image.flush()); diff --git a/src/test/librbd/test_mirroring.cc b/src/test/librbd/test_mirroring.cc index e3277a0a25185..840ac33b11952 100644 --- a/src/test/librbd/test_mirroring.cc +++ b/src/test/librbd/test_mirroring.cc @@ -1377,7 +1377,7 @@ TEST_F(TestMirroring, SnapshotImageState) ASSERT_EQ(features & ~RBD_FEATURES_IMPLICIT_ENABLE, image_state.features); ASSERT_EQ(1U, image_state.snapshots.size()); ASSERT_EQ("snap", image_state.snapshots.begin()->second.name); - ASSERT_TRUE(image_state.metadata.empty()); + uint8_t original_pairs_num = image_state.metadata.size(); { C_SaferCond cond; @@ -1413,7 +1413,7 @@ TEST_F(TestMirroring, SnapshotImageState) ASSERT_EQ(image_name, image_state.name); ASSERT_EQ(features & ~RBD_FEATURES_IMPLICIT_ENABLE, image_state.features); - ASSERT_EQ(10U, image_state.metadata.size()); + ASSERT_EQ(original_pairs_num + 10, image_state.metadata.size()); for (int i = 0; i < 10; i++) { auto &bl = image_state.metadata[stringify(i)]; ASSERT_EQ(0, strncmp(std::string(1024, 'A' + i).c_str(), bl.c_str(), diff --git a/src/test/librbd/test_mock_ExclusiveLock.cc b/src/test/librbd/test_mock_ExclusiveLock.cc index c0693f78a1d01..65f7da64e605b 100644 --- a/src/test/librbd/test_mock_ExclusiveLock.cc +++ b/src/test/librbd/test_mock_ExclusiveLock.cc @@ -262,7 +262,8 @@ public: void expect_set_require_lock(MockExclusiveLockImageCtx &mock_image_ctx, MockImageDispatch &mock_image_dispatch) { if (mock_image_ctx.clone_copy_on_read || - (mock_image_ctx.features & RBD_FEATURE_JOURNALING) != 0) { + (mock_image_ctx.features & RBD_FEATURE_JOURNALING) != 0 || + is_rbd_rwl_enabled(mock_image_ctx.cct)) { expect_set_require_lock(mock_image_dispatch, io::DIRECTION_BOTH); } else { expect_set_require_lock(mock_image_dispatch, io::DIRECTION_WRITE); diff --git a/src/test/librbd/test_mock_fixture.cc b/src/test/librbd/test_mock_fixture.cc index 166175c9bd441..d2a6837c6eb1a 100644 --- a/src/test/librbd/test_mock_fixture.cc +++ b/src/test/librbd/test_mock_fixture.cc @@ -55,6 +55,17 @@ void TestMockFixture::expect_unlock_exclusive_lock(librbd::ImageCtx &ictx) { EXPECT_CALL(get_mock_io_ctx(ictx.md_ctx), exec(_, _, StrEq("lock"), StrEq("unlock"), _, _, _, _)) .WillRepeatedly(DoDefault()); + if (ictx.test_features(RBD_FEATURE_DIRTY_CACHE)) { + EXPECT_CALL(get_mock_io_ctx(ictx.md_ctx), + exec(ictx.header_oid, _, StrEq("rbd"), StrEq("set_features"), _, _, _, _)) + .WillOnce(DoDefault()); + EXPECT_CALL(get_mock_io_ctx(ictx.md_ctx), + exec(ictx.header_oid, _, StrEq("rbd"), StrEq("metadata_set"), _, _, _, _)) + .WillOnce(DoDefault()); + EXPECT_CALL(get_mock_io_ctx(ictx.md_ctx), + exec(ictx.header_oid, _, StrEq("rbd"), StrEq("metadata_remove"), _, _, _, _)) + .WillOnce(DoDefault()); + } } void TestMockFixture::expect_op_work_queue(librbd::MockImageCtx &mock_image_ctx) { diff --git a/src/test/librbd/test_support.cc b/src/test/librbd/test_support.cc index e74068e6600a1..25b34436bb18e 100644 --- a/src/test/librbd/test_support.cc +++ b/src/test/librbd/test_support.cc @@ -3,6 +3,7 @@ #include "test/librbd/test_support.h" #include "include/rbd_types.h" #include "gtest/gtest.h" +#include "common/ceph_context.h" #include bool get_features(uint64_t *features) { @@ -126,3 +127,10 @@ bool is_librados_test_stub(librados::Rados &rados) { return fsid == "00000000-1111-2222-3333-444444444444"; } +bool is_rbd_rwl_enabled(ceph::common::CephContext *cct) { +#if defined(WITH_RBD_RWL) + return cct->_conf.get_val("rbd_rwl_enabled"); +#else + return false; +#endif +} diff --git a/src/test/librbd/test_support.h b/src/test/librbd/test_support.h index abb7c4702cd19..a428d32b393bd 100644 --- a/src/test/librbd/test_support.h +++ b/src/test/librbd/test_support.h @@ -26,6 +26,8 @@ int create_image_data_pool(librados::Rados &rados, std::string &data_pool, bool bool is_librados_test_stub(librados::Rados &rados); +bool is_rbd_rwl_enabled(ceph::common::CephContext *ctx); + #define REQUIRE(x) { \ if (!(x)) { \ std::cout << "SKIPPING" << std::endl; \ -- 2.39.5