From: Jason Dillaman Date: Wed, 9 Dec 2015 04:14:49 +0000 (-0500) Subject: tests: adjust test cases to refactored librbd X-Git-Tag: v10.0.2~35^2~3 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=2a4aad5ffb4f06a5f3371256dbcbb1c3c9d04e55;p=ceph.git tests: adjust test cases to refactored librbd Signed-off-by: Jason Dillaman --- diff --git a/src/test/Makefile-client.am b/src/test/Makefile-client.am index 9a3f888a4ad5..d44a977a5a3a 100644 --- a/src/test/Makefile-client.am +++ b/src/test/Makefile-client.am @@ -406,10 +406,12 @@ noinst_HEADERS += \ test/librbd/test_support.h \ test/librbd/mock/MockAioImageRequestWQ.h \ test/librbd/mock/MockContextWQ.h \ + test/librbd/mock/MockExclusiveLock.h \ test/librbd/mock/MockImageCtx.h \ test/librbd/mock/MockImageWatcher.h \ test/librbd/mock/MockJournal.h \ test/librbd/mock/MockObjectMap.h \ + test/librbd/mock/MockReadahead.h \ test/librbd/object_map/mock/MockInvalidateRequest.h if LINUX diff --git a/src/test/librbd/exclusive_lock/test_mock_AcquireRequest.cc b/src/test/librbd/exclusive_lock/test_mock_AcquireRequest.cc index 6d276f811a74..31e17a0385c9 100644 --- a/src/test/librbd/exclusive_lock/test_mock_AcquireRequest.cc +++ b/src/test/librbd/exclusive_lock/test_mock_AcquireRequest.cc @@ -149,9 +149,10 @@ TEST_F(TestMockExclusiveLockAcquireRequest, Success) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); - InSequence seq; MockImageCtx mock_image_ctx(*ictx); + expect_op_work_queue(mock_image_ctx); + InSequence seq; expect_lock(mock_image_ctx, 0); MockJournal mock_journal; @@ -179,9 +180,10 @@ TEST_F(TestMockExclusiveLockAcquireRequest, SuccessJournalDisabled) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); - InSequence seq; MockImageCtx mock_image_ctx(*ictx); + expect_op_work_queue(mock_image_ctx); + InSequence seq; expect_lock(mock_image_ctx, 0); expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING, false); @@ -206,9 +208,10 @@ TEST_F(TestMockExclusiveLockAcquireRequest, SuccessObjectMapDisabled) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); - InSequence seq; MockImageCtx mock_image_ctx(*ictx); + expect_op_work_queue(mock_image_ctx); + InSequence seq; expect_lock(mock_image_ctx, 0); MockJournal mock_journal; @@ -232,15 +235,15 @@ TEST_F(TestMockExclusiveLockAcquireRequest, LockBusy) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); - InSequence seq; MockImageCtx mock_image_ctx(*ictx); + expect_op_work_queue(mock_image_ctx); + InSequence seq; expect_lock(mock_image_ctx, -EBUSY); expect_get_lock_info(mock_image_ctx, 0, entity_name_t::CLIENT(1), "1.2.3.4", "auto 123", MockExclusiveLock::WATCHER_LOCK_TAG, LOCK_EXCLUSIVE); expect_list_watchers(mock_image_ctx, 0, "dead client", 123); - expect_op_work_queue(mock_image_ctx); expect_blacklist_add(mock_image_ctx, 0); expect_break_lock(mock_image_ctx, 0); expect_lock(mock_image_ctx, -ENOENT); @@ -259,9 +262,10 @@ TEST_F(TestMockExclusiveLockAcquireRequest, GetLockInfoError) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); - InSequence seq; MockImageCtx mock_image_ctx(*ictx); + expect_op_work_queue(mock_image_ctx); + InSequence seq; expect_lock(mock_image_ctx, -EBUSY); expect_get_lock_info(mock_image_ctx, -EINVAL, entity_name_t::CLIENT(1), "", "", "", LOCK_EXCLUSIVE); @@ -280,9 +284,10 @@ TEST_F(TestMockExclusiveLockAcquireRequest, GetLockInfoEmpty) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); - InSequence seq; MockImageCtx mock_image_ctx(*ictx); + expect_op_work_queue(mock_image_ctx); + InSequence seq; expect_lock(mock_image_ctx, -EBUSY); expect_get_lock_info(mock_image_ctx, -ENOENT, entity_name_t::CLIENT(1), "", "", "", LOCK_EXCLUSIVE); @@ -302,9 +307,10 @@ TEST_F(TestMockExclusiveLockAcquireRequest, GetLockInfoExternalTag) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); - InSequence seq; MockImageCtx mock_image_ctx(*ictx); + expect_op_work_queue(mock_image_ctx); + InSequence seq; expect_lock(mock_image_ctx, -EBUSY); expect_get_lock_info(mock_image_ctx, 0, entity_name_t::CLIENT(1), "1.2.3.4", "auto 123", "external tag", LOCK_EXCLUSIVE); @@ -323,9 +329,10 @@ TEST_F(TestMockExclusiveLockAcquireRequest, GetLockInfoShared) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); - InSequence seq; MockImageCtx mock_image_ctx(*ictx); + expect_op_work_queue(mock_image_ctx); + InSequence seq; expect_lock(mock_image_ctx, -EBUSY); expect_get_lock_info(mock_image_ctx, 0, entity_name_t::CLIENT(1), "1.2.3.4", "auto 123", MockExclusiveLock::WATCHER_LOCK_TAG, @@ -345,9 +352,10 @@ TEST_F(TestMockExclusiveLockAcquireRequest, GetLockInfoExternalCookie) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); - InSequence seq; MockImageCtx mock_image_ctx(*ictx); + expect_op_work_queue(mock_image_ctx); + InSequence seq; expect_lock(mock_image_ctx, -EBUSY); expect_get_lock_info(mock_image_ctx, 0, entity_name_t::CLIENT(1), "1.2.3.4", "external cookie", MockExclusiveLock::WATCHER_LOCK_TAG, @@ -367,9 +375,10 @@ TEST_F(TestMockExclusiveLockAcquireRequest, GetWatchersError) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); - InSequence seq; MockImageCtx mock_image_ctx(*ictx); + expect_op_work_queue(mock_image_ctx); + InSequence seq; expect_lock(mock_image_ctx, -EBUSY); expect_get_lock_info(mock_image_ctx, 0, entity_name_t::CLIENT(1), "1.2.3.4", "auto 123", MockExclusiveLock::WATCHER_LOCK_TAG, @@ -390,9 +399,10 @@ TEST_F(TestMockExclusiveLockAcquireRequest, GetWatchersAlive) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); - InSequence seq; MockImageCtx mock_image_ctx(*ictx); + expect_op_work_queue(mock_image_ctx); + InSequence seq; expect_lock(mock_image_ctx, -EBUSY); expect_get_lock_info(mock_image_ctx, 0, entity_name_t::CLIENT(1), "1.2.3.4", "auto 123", MockExclusiveLock::WATCHER_LOCK_TAG, @@ -413,16 +423,16 @@ TEST_F(TestMockExclusiveLockAcquireRequest, BlacklistDisabled) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); - InSequence seq; MockImageCtx mock_image_ctx(*ictx); + expect_op_work_queue(mock_image_ctx); mock_image_ctx.blacklist_on_break_lock = false; + InSequence seq; expect_lock(mock_image_ctx, -EBUSY); expect_get_lock_info(mock_image_ctx, 0, entity_name_t::CLIENT(1), "1.2.3.4", "auto 123", MockExclusiveLock::WATCHER_LOCK_TAG, LOCK_EXCLUSIVE); expect_list_watchers(mock_image_ctx, 0, "dead client", 123); - expect_op_work_queue(mock_image_ctx); expect_break_lock(mock_image_ctx, 0); expect_lock(mock_image_ctx, -ENOENT); @@ -440,15 +450,15 @@ TEST_F(TestMockExclusiveLockAcquireRequest, BlacklistError) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); - InSequence seq; MockImageCtx mock_image_ctx(*ictx); + expect_op_work_queue(mock_image_ctx); + InSequence seq; expect_lock(mock_image_ctx, -EBUSY); expect_get_lock_info(mock_image_ctx, 0, entity_name_t::CLIENT(1), "1.2.3.4", "auto 123", MockExclusiveLock::WATCHER_LOCK_TAG, LOCK_EXCLUSIVE); expect_list_watchers(mock_image_ctx, 0, "dead client", 123); - expect_op_work_queue(mock_image_ctx); expect_blacklist_add(mock_image_ctx, -EINVAL); C_SaferCond ctx; @@ -465,15 +475,15 @@ TEST_F(TestMockExclusiveLockAcquireRequest, BreakLockMissing) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); - InSequence seq; MockImageCtx mock_image_ctx(*ictx); + expect_op_work_queue(mock_image_ctx); + InSequence seq; expect_lock(mock_image_ctx, -EBUSY); expect_get_lock_info(mock_image_ctx, 0, entity_name_t::CLIENT(1), "1.2.3.4", "auto 123", MockExclusiveLock::WATCHER_LOCK_TAG, LOCK_EXCLUSIVE); expect_list_watchers(mock_image_ctx, 0, "dead client", 123); - expect_op_work_queue(mock_image_ctx); expect_blacklist_add(mock_image_ctx, 0); expect_break_lock(mock_image_ctx, -ENOENT); expect_lock(mock_image_ctx, -EINVAL); @@ -492,15 +502,15 @@ TEST_F(TestMockExclusiveLockAcquireRequest, BreakLockError) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); - InSequence seq; MockImageCtx mock_image_ctx(*ictx); + expect_op_work_queue(mock_image_ctx); + InSequence seq; expect_lock(mock_image_ctx, -EBUSY); expect_get_lock_info(mock_image_ctx, 0, entity_name_t::CLIENT(1), "1.2.3.4", "auto 123", MockExclusiveLock::WATCHER_LOCK_TAG, LOCK_EXCLUSIVE); expect_list_watchers(mock_image_ctx, 0, "dead client", 123); - expect_op_work_queue(mock_image_ctx); expect_blacklist_add(mock_image_ctx, 0); expect_break_lock(mock_image_ctx, -EINVAL); diff --git a/src/test/librbd/exclusive_lock/test_mock_ReleaseRequest.cc b/src/test/librbd/exclusive_lock/test_mock_ReleaseRequest.cc index 3be3a084bd1e..09595afdca51 100644 --- a/src/test/librbd/exclusive_lock/test_mock_ReleaseRequest.cc +++ b/src/test/librbd/exclusive_lock/test_mock_ReleaseRequest.cc @@ -59,9 +59,10 @@ TEST_F(TestMockExclusiveLockReleaseRequest, Success) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); - InSequence seq; MockImageCtx mock_image_ctx(*ictx); + expect_op_work_queue(mock_image_ctx); + InSequence seq; expect_cancel_op_requests(mock_image_ctx, 0); MockJournal *mock_journal = new MockJournal(); @@ -69,7 +70,7 @@ TEST_F(TestMockExclusiveLockReleaseRequest, Success) { expect_close_journal(mock_image_ctx, *mock_journal, -EINVAL); MockObjectMap *mock_object_map = new MockObjectMap(); - mock_image_ctx.object_map_ptr = mock_object_map; + mock_image_ctx.object_map = mock_object_map; expect_unlock_object_map(mock_image_ctx, *mock_object_map); expect_unlock(mock_image_ctx, 0); @@ -88,13 +89,14 @@ TEST_F(TestMockExclusiveLockReleaseRequest, SuccessJournalDisabled) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); - InSequence seq; MockImageCtx mock_image_ctx(*ictx); + expect_op_work_queue(mock_image_ctx); + InSequence seq; expect_cancel_op_requests(mock_image_ctx, 0); MockObjectMap *mock_object_map = new MockObjectMap(); - mock_image_ctx.object_map_ptr = mock_object_map; + mock_image_ctx.object_map = mock_object_map; expect_unlock_object_map(mock_image_ctx, *mock_object_map); expect_unlock(mock_image_ctx, 0); @@ -113,9 +115,10 @@ TEST_F(TestMockExclusiveLockReleaseRequest, SuccessObjectMapDisabled) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); - InSequence seq; MockImageCtx mock_image_ctx(*ictx); + expect_op_work_queue(mock_image_ctx); + InSequence seq; expect_cancel_op_requests(mock_image_ctx, 0); expect_unlock(mock_image_ctx, 0); @@ -134,9 +137,10 @@ TEST_F(TestMockExclusiveLockReleaseRequest, UnlockError) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); - InSequence seq; MockImageCtx mock_image_ctx(*ictx); + expect_op_work_queue(mock_image_ctx); + InSequence seq; expect_cancel_op_requests(mock_image_ctx, 0); expect_unlock(mock_image_ctx, -EINVAL); diff --git a/src/test/librbd/mock/MockAioImageRequestWQ.h b/src/test/librbd/mock/MockAioImageRequestWQ.h index cd34807e9d78..c4dbd3bece18 100644 --- a/src/test/librbd/mock/MockAioImageRequestWQ.h +++ b/src/test/librbd/mock/MockAioImageRequestWQ.h @@ -11,6 +11,8 @@ namespace librbd { struct MockAioImageRequestWQ { MOCK_METHOD1(block_writes, void(Context *)); MOCK_METHOD0(unblock_writes, void()); + + MOCK_CONST_METHOD0(writes_empty, bool()); }; } // namespace librbd diff --git a/src/test/librbd/mock/MockExclusiveLock.h b/src/test/librbd/mock/MockExclusiveLock.h new file mode 100644 index 000000000000..8227d3edb190 --- /dev/null +++ b/src/test/librbd/mock/MockExclusiveLock.h @@ -0,0 +1,25 @@ +// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_TEST_LIBRBD_MOCK_EXCLUSIVE_LOCK_H +#define CEPH_TEST_LIBRBD_MOCK_EXCLUSIVE_LOCK_H + +#include "include/int_types.h" +#include "include/rados/librados.hpp" +#include "gmock/gmock.h" + +class Context; + +namespace librbd { + +struct MockExclusiveLock { + MOCK_CONST_METHOD0(is_lock_owner, bool()); + + MOCK_METHOD1(assert_header_locked, void(librados::ObjectWriteOperation *)); + + MOCK_METHOD1(shut_down, void(Context*)); +}; + +} // namespace librbd + +#endif // CEPH_TEST_LIBRBD_MOCK_EXCLUSIVE_LOCK_H diff --git a/src/test/librbd/mock/MockImageCtx.h b/src/test/librbd/mock/MockImageCtx.h index 893aa993cb0c..bd29d498fd48 100644 --- a/src/test/librbd/mock/MockImageCtx.h +++ b/src/test/librbd/mock/MockImageCtx.h @@ -6,9 +6,11 @@ #include "test/librbd/mock/MockAioImageRequestWQ.h" #include "test/librbd/mock/MockContextWQ.h" +#include "test/librbd/mock/MockExclusiveLock.h" #include "test/librbd/mock/MockImageWatcher.h" #include "test/librbd/mock/MockJournal.h" #include "test/librbd/mock/MockObjectMap.h" +#include "test/librbd/mock/MockReadahead.h" #include "common/RWLock.h" #include "librbd/ImageCtx.h" #include "gmock/gmock.h" @@ -38,7 +40,8 @@ struct MockImageCtx { layout(image_ctx.layout), aio_work_queue(new MockAioImageRequestWQ()), op_work_queue(new MockContextWQ()), - image_watcher(NULL), object_map_ptr(NULL), journal(NULL), + parent(NULL), image_watcher(NULL), object_map(NULL), + exclusive_lock(NULL), journal(NULL), concurrent_management_ops(image_ctx.concurrent_management_ops), blacklist_on_break_lock(image_ctx.blacklist_on_break_lock), blacklist_expire_seconds(image_ctx.blacklist_expire_seconds) @@ -87,13 +90,17 @@ struct MockImageCtx { uint64_t in_size, parent_info parent, uint8_t protection_status, uint64_t flags)); MOCK_METHOD2(rm_snap, void(std::string in_snap_name, librados::snap_t id)); + MOCK_METHOD1(flush, void(Context *)); + MOCK_METHOD1(flush_copyup, void(Context *)); + + MOCK_METHOD1(shut_down_cache, void(Context *)); MOCK_CONST_METHOD1(test_features, bool(uint64_t test_features)); MOCK_METHOD1(cancel_async_requests, void(Context*)); - MOCK_METHOD0(create_object_map, MockObjectMap*()); + MOCK_METHOD1(create_object_map, MockObjectMap*(uint64_t)); MOCK_METHOD0(create_journal, MockJournal*()); ImageCtx *image_ctx; @@ -131,10 +138,13 @@ struct MockImageCtx { MockAioImageRequestWQ *aio_work_queue; MockContextWQ *op_work_queue; - MockImageWatcher *image_watcher; - MockObjectMap object_map; // TODO replace with ptr - MockObjectMap *object_map_ptr; // TODO + MockReadahead readahead; + MockImageCtx *parent; + + MockImageWatcher *image_watcher; + MockObjectMap *object_map; + MockExclusiveLock *exclusive_lock; MockJournal *journal; int concurrent_management_ops; diff --git a/src/test/librbd/mock/MockImageWatcher.h b/src/test/librbd/mock/MockImageWatcher.h index eaacaeb1bebc..20164eafa3cc 100644 --- a/src/test/librbd/mock/MockImageWatcher.h +++ b/src/test/librbd/mock/MockImageWatcher.h @@ -9,10 +9,12 @@ namespace librbd { struct MockImageWatcher { - MOCK_CONST_METHOD0(is_lock_owner, bool()); - MOCK_CONST_METHOD1(is_lock_supported, bool(const RWLock &)); - MOCK_METHOD1(assert_header_locked, void (librados::ObjectWriteOperation *)); + MOCK_METHOD0(unregister_watch, void()); + MOCK_CONST_METHOD0(get_watch_handle, uint64_t()); + + MOCK_METHOD0(notify_acquired_lock, void()); + MOCK_METHOD0(notify_released_lock, void()); MOCK_METHOD0(notify_request_lock, void()); }; diff --git a/src/test/librbd/mock/MockObjectMap.h b/src/test/librbd/mock/MockObjectMap.h index bde034f2aab5..78c036ce2130 100644 --- a/src/test/librbd/mock/MockObjectMap.h +++ b/src/test/librbd/mock/MockObjectMap.h @@ -11,9 +11,10 @@ namespace librbd { struct MockObjectMap { MOCK_CONST_METHOD1(enabled, bool(const RWLock &object_map_lock)); + MOCK_METHOD1(open, void(Context *on_finish)); + MOCK_METHOD1(lock, void(Context *on_finish)); MOCK_METHOD1(unlock, void(Context *on_finish)); - MOCK_METHOD2(refresh, void(uint64_t snap_id, Context *on_finish)); MOCK_METHOD2(snapshot_add, void(uint64_t snap_id, Context *on_finish)); MOCK_METHOD2(snapshot_remove, void(uint64_t snap_id, Context *on_finish)); diff --git a/src/test/librbd/mock/MockReadahead.h b/src/test/librbd/mock/MockReadahead.h new file mode 100644 index 000000000000..b73b4627c006 --- /dev/null +++ b/src/test/librbd/mock/MockReadahead.h @@ -0,0 +1,21 @@ +// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_TEST_LIBRBD_MOCK_READAHEAD_H +#define CEPH_TEST_LIBRBD_MOCK_READAHEAD_H + +#include "include/int_types.h" +#include "gmock/gmock.h" + +class Context; + +namespace librbd { + +struct MockReadahead { + MOCK_METHOD1(set_max_readahead_size, void(uint64_t)); + MOCK_METHOD1(wait_for_pending, void(Context *)); +}; + +} // namespace librbd + +#endif // CEPH_TEST_LIBRBD_MOCK_READAHEAD_H diff --git a/src/test/librbd/object_map/test_mock_RefreshRequest.cc b/src/test/librbd/object_map/test_mock_RefreshRequest.cc index 043ad351f0e5..2af4517036a8 100644 --- a/src/test/librbd/object_map/test_mock_RefreshRequest.cc +++ b/src/test/librbd/object_map/test_mock_RefreshRequest.cc @@ -83,14 +83,6 @@ public: (*object_map)[i] = rand() % 3; } } - - void when_apply_refresh_request(MockImageCtx &mock_image_ctx, - MockRefreshRequest *req) { - RWLock::WLocker snap_locker(mock_image_ctx.snap_lock); - RWLock::WLocker object_map_locker(mock_image_ctx.object_map_lock); - expect_get_image_size(mock_image_ctx, mock_image_ctx.image_ctx->size); - req->apply(); - } }; TEST_F(TestMockObjectMapRefreshRequest, Success) { @@ -110,10 +102,10 @@ TEST_F(TestMockObjectMapRefreshRequest, Success) { InSequence seq; expect_get_image_size(mock_image_ctx, mock_image_ctx.image_ctx->size); expect_object_map_load(mock_image_ctx, &on_disk_object_map, 0); + expect_get_image_size(mock_image_ctx, mock_image_ctx.image_ctx->size); req->send(); ASSERT_EQ(0, ctx.wait()); - when_apply_refresh_request(mock_image_ctx, req); ASSERT_EQ(on_disk_object_map, object_map); } @@ -137,11 +129,10 @@ TEST_F(TestMockObjectMapRefreshRequest, LoadError) { MockInvalidateRequest invalidate_request; expect_invalidate_request(mock_image_ctx, invalidate_request); + expect_get_image_size(mock_image_ctx, mock_image_ctx.image_ctx->size); req->send(); ASSERT_EQ(0, ctx.wait()); - - when_apply_refresh_request(mock_image_ctx, req); } TEST_F(TestMockObjectMapRefreshRequest, LoadCorrupt) { @@ -166,11 +157,10 @@ TEST_F(TestMockObjectMapRefreshRequest, LoadCorrupt) { expect_invalidate_request(mock_image_ctx, invalidate_request); expect_truncate_request(mock_image_ctx); expect_object_map_resize(mock_image_ctx, on_disk_object_map.size(), 0); + expect_get_image_size(mock_image_ctx, mock_image_ctx.image_ctx->size); req->send(); ASSERT_EQ(0, ctx.wait()); - - when_apply_refresh_request(mock_image_ctx, req); } TEST_F(TestMockObjectMapRefreshRequest, TooSmall) { @@ -196,11 +186,10 @@ TEST_F(TestMockObjectMapRefreshRequest, TooSmall) { MockInvalidateRequest invalidate_request; expect_invalidate_request(mock_image_ctx, invalidate_request); expect_object_map_resize(mock_image_ctx, on_disk_object_map.size(), 0); + expect_get_image_size(mock_image_ctx, mock_image_ctx.image_ctx->size); req->send(); ASSERT_EQ(0, ctx.wait()); - - when_apply_refresh_request(mock_image_ctx, req); } TEST_F(TestMockObjectMapRefreshRequest, TooLarge) { @@ -223,10 +212,9 @@ TEST_F(TestMockObjectMapRefreshRequest, TooLarge) { InSequence seq; expect_get_image_size(mock_image_ctx, mock_image_ctx.image_ctx->size); expect_object_map_load(mock_image_ctx, &large_object_map, 0); + expect_get_image_size(mock_image_ctx, mock_image_ctx.image_ctx->size); req->send(); ASSERT_EQ(0, ctx.wait()); - - when_apply_refresh_request(mock_image_ctx, req); } TEST_F(TestMockObjectMapRefreshRequest, ResizeError) { @@ -252,38 +240,10 @@ TEST_F(TestMockObjectMapRefreshRequest, ResizeError) { MockInvalidateRequest invalidate_request; expect_invalidate_request(mock_image_ctx, invalidate_request); expect_object_map_resize(mock_image_ctx, on_disk_object_map.size(), -ESTALE); + expect_get_image_size(mock_image_ctx, mock_image_ctx.image_ctx->size); req->send(); ASSERT_EQ(0, ctx.wait()); - - when_apply_refresh_request(mock_image_ctx, req); -} - -TEST_F(TestMockObjectMapRefreshRequest, StaleRefresh) { - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockImageCtx mock_image_ctx(*ictx); - - C_SaferCond ctx; - ceph::BitVector<2> object_map; - MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, &object_map, - TEST_SNAP_ID, &ctx); - ASSERT_THROW(when_apply_refresh_request(mock_image_ctx, req), - ceph::FailedAssertion); -} - -TEST_F(TestMockObjectMapRefreshRequest, Discard) { - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockImageCtx mock_image_ctx(*ictx); - - C_SaferCond ctx; - ceph::BitVector<2> object_map; - MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, &object_map, - TEST_SNAP_ID, &ctx); - req->discard(); } } // namespace object_map diff --git a/src/test/librbd/object_map/test_mock_ResizeRequest.cc b/src/test/librbd/object_map/test_mock_ResizeRequest.cc index 8bc9f007d4fe..197fabeb60b9 100644 --- a/src/test/librbd/object_map/test_mock_ResizeRequest.cc +++ b/src/test/librbd/object_map/test_mock_ResizeRequest.cc @@ -6,6 +6,7 @@ #include "test/librados_test_stub/MockTestMemIoCtxImpl.h" #include "common/bit_vector.hpp" #include "librbd/internal.h" +#include "librbd/ObjectMap.h" #include "librbd/object_map/ResizeRequest.h" #include "gmock/gmock.h" #include "gtest/gtest.h" diff --git a/src/test/librbd/object_map/test_mock_SnapshotCreateRequest.cc b/src/test/librbd/object_map/test_mock_SnapshotCreateRequest.cc index e3ebab31e513..e76c1927de2d 100644 --- a/src/test/librbd/object_map/test_mock_SnapshotCreateRequest.cc +++ b/src/test/librbd/object_map/test_mock_SnapshotCreateRequest.cc @@ -6,6 +6,7 @@ #include "test/librados_test_stub/MockTestMemIoCtxImpl.h" #include "common/bit_vector.hpp" #include "librbd/internal.h" +#include "librbd/ObjectMap.h" #include "librbd/object_map/SnapshotCreateRequest.h" #include "gmock/gmock.h" #include "gtest/gtest.h" diff --git a/src/test/librbd/object_map/test_mock_SnapshotRemoveRequest.cc b/src/test/librbd/object_map/test_mock_SnapshotRemoveRequest.cc index 3bf622815d02..224a43d68d44 100644 --- a/src/test/librbd/object_map/test_mock_SnapshotRemoveRequest.cc +++ b/src/test/librbd/object_map/test_mock_SnapshotRemoveRequest.cc @@ -5,7 +5,9 @@ #include "test/librbd/test_support.h" #include "test/librados_test_stub/MockTestMemIoCtxImpl.h" #include "common/bit_vector.hpp" +#include "librbd/ImageState.h" #include "librbd/internal.h" +#include "librbd/ObjectMap.h" #include "librbd/object_map/SnapshotRemoveRequest.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -75,7 +77,7 @@ TEST_F(TestMockObjectMapSnapshotRemoveRequest, Success) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); uint64_t snap_id = ictx->snap_info.rbegin()->first; if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) { @@ -104,7 +106,7 @@ TEST_F(TestMockObjectMapSnapshotRemoveRequest, LoadMapError) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); uint64_t snap_id = ictx->snap_info.rbegin()->first; expect_load_map(ictx, snap_id, -EINVAL); @@ -131,7 +133,7 @@ TEST_F(TestMockObjectMapSnapshotRemoveRequest, RemoveSnapshotMissing) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); uint64_t snap_id = ictx->snap_info.rbegin()->first; expect_load_map(ictx, snap_id, 0); @@ -158,7 +160,7 @@ TEST_F(TestMockObjectMapSnapshotRemoveRequest, RemoveSnapshotError) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); uint64_t snap_id = ictx->snap_info.rbegin()->first; expect_load_map(ictx, snap_id, 0); @@ -186,7 +188,7 @@ TEST_F(TestMockObjectMapSnapshotRemoveRequest, RemoveMapMissing) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); uint64_t snap_id = ictx->snap_info.rbegin()->first; if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) { @@ -215,7 +217,7 @@ TEST_F(TestMockObjectMapSnapshotRemoveRequest, RemoveMapError) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); uint64_t snap_id = ictx->snap_info.rbegin()->first; if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) { @@ -244,7 +246,7 @@ TEST_F(TestMockObjectMapSnapshotRemoveRequest, ScrubCleanObjects) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); uint64_t snap_id = ictx->snap_info.rbegin()->first; diff --git a/src/test/librbd/object_map/test_mock_SnapshotRollbackRequest.cc b/src/test/librbd/object_map/test_mock_SnapshotRollbackRequest.cc index 42782fbd087e..25c615bf328f 100644 --- a/src/test/librbd/object_map/test_mock_SnapshotRollbackRequest.cc +++ b/src/test/librbd/object_map/test_mock_SnapshotRollbackRequest.cc @@ -4,6 +4,7 @@ #include "test/librbd/test_mock_fixture.h" #include "test/librbd/test_support.h" #include "test/librados_test_stub/MockTestMemIoCtxImpl.h" +#include "librbd/ImageState.h" #include "librbd/internal.h" #include "librbd/ObjectMap.h" #include "librbd/object_map/SnapshotRollbackRequest.h" @@ -66,7 +67,7 @@ TEST_F(TestMockObjectMapSnapshotRollbackRequest, Success) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); uint64_t snap_id = ictx->snap_info.rbegin()->first; expect_read_map(ictx, snap_id, 0); @@ -87,7 +88,7 @@ TEST_F(TestMockObjectMapSnapshotRollbackRequest, ReadMapError) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); uint64_t snap_id = ictx->snap_info.rbegin()->first; expect_read_map(ictx, snap_id, -ENOENT); @@ -115,7 +116,7 @@ TEST_F(TestMockObjectMapSnapshotRollbackRequest, WriteMapError) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); uint64_t snap_id = ictx->snap_info.rbegin()->first; expect_read_map(ictx, snap_id, 0); diff --git a/src/test/librbd/object_map/test_mock_UpdateRequest.cc b/src/test/librbd/object_map/test_mock_UpdateRequest.cc index 902e4a17e516..bc5cafab9102 100644 --- a/src/test/librbd/object_map/test_mock_UpdateRequest.cc +++ b/src/test/librbd/object_map/test_mock_UpdateRequest.cc @@ -5,7 +5,9 @@ #include "test/librbd/test_support.h" #include "test/librados_test_stub/MockTestMemIoCtxImpl.h" #include "common/bit_vector.hpp" +#include "librbd/ImageState.h" #include "librbd/internal.h" +#include "librbd/ObjectMap.h" #include "librbd/object_map/UpdateRequest.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -168,7 +170,7 @@ TEST_F(TestMockObjectMapUpdateRequest, RebuildSnapOnDisk) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); ASSERT_EQ(CEPH_NOSNAP, ictx->snap_id); uint64_t snap_id = ictx->snap_info.rbegin()->first; diff --git a/src/test/librbd/operation/test_mock_SnapshotCreateRequest.cc b/src/test/librbd/operation/test_mock_SnapshotCreateRequest.cc index 8ae12d0b60f0..d9c8cce9eae4 100644 --- a/src/test/librbd/operation/test_mock_SnapshotCreateRequest.cc +++ b/src/test/librbd/operation/test_mock_SnapshotCreateRequest.cc @@ -7,6 +7,7 @@ #include "test/librados_test_stub/MockTestMemIoCtxImpl.h" #include "common/bit_vector.hpp" #include "librbd/internal.h" +#include "librbd/ObjectMap.h" #include "librbd/operation/SnapshotCreateRequest.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -34,10 +35,10 @@ public: } void expect_verify_lock_ownership(MockImageCtx &mock_image_ctx) { - EXPECT_CALL(*mock_image_ctx.image_watcher, is_lock_supported(_)) - .WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_image_ctx.image_watcher, is_lock_owner()) - .WillRepeatedly(Return(true)); + if (mock_image_ctx.exclusive_lock != nullptr) { + EXPECT_CALL(*mock_image_ctx.exclusive_lock, is_lock_owner()) + .WillRepeatedly(Return(true)); + } } void expect_allocate_snap_id(MockImageCtx &mock_image_ctx, int r) { @@ -61,8 +62,9 @@ public: } void expect_snap_create(MockImageCtx &mock_image_ctx, int r) { - if (!mock_image_ctx.old_format) { - EXPECT_CALL(*mock_image_ctx.image_watcher, assert_header_locked(_)) + if (!mock_image_ctx.old_format && + mock_image_ctx.exclusive_lock != nullptr) { + EXPECT_CALL(*mock_image_ctx.exclusive_lock, assert_header_locked(_)) .Times(r == -ESTALE ? 2 : 1); } @@ -81,11 +83,8 @@ public: } void expect_object_map_snap_create(MockImageCtx &mock_image_ctx) { - bool enabled = mock_image_ctx.image_ctx->test_features(RBD_FEATURE_OBJECT_MAP); - EXPECT_CALL(mock_image_ctx.object_map, enabled(_)) - .WillOnce(Return(enabled)); - if (enabled) { - EXPECT_CALL(mock_image_ctx.object_map, snapshot_add(_, _)) + if (mock_image_ctx.object_map != nullptr) { + EXPECT_CALL(*mock_image_ctx.object_map, snapshot_add(_, _)) .WillOnce(WithArg<1>(CompleteContext( 0, mock_image_ctx.image_ctx->op_work_queue))); } @@ -111,6 +110,16 @@ TEST_F(TestMockOperationSnapshotCreateRequest, Success) { MockImageCtx mock_image_ctx(*ictx); + MockExclusiveLock mock_exclusive_lock; + if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + } + + MockObjectMap mock_object_map; + if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) { + mock_image_ctx.object_map = &mock_object_map; + } + expect_verify_lock_ownership(mock_image_ctx); expect_op_work_queue(mock_image_ctx); @@ -138,6 +147,11 @@ TEST_F(TestMockOperationSnapshotCreateRequest, AllocateSnapIdError) { MockImageCtx mock_image_ctx(*ictx); + MockExclusiveLock mock_exclusive_lock; + if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + } + expect_verify_lock_ownership(mock_image_ctx); expect_op_work_queue(mock_image_ctx); @@ -162,6 +176,16 @@ TEST_F(TestMockOperationSnapshotCreateRequest, CreateSnapStale) { MockImageCtx mock_image_ctx(*ictx); + MockExclusiveLock mock_exclusive_lock; + if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + } + + MockObjectMap mock_object_map; + if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) { + mock_image_ctx.object_map = &mock_object_map; + } + expect_verify_lock_ownership(mock_image_ctx); expect_op_work_queue(mock_image_ctx); @@ -188,6 +212,11 @@ TEST_F(TestMockOperationSnapshotCreateRequest, CreateSnapError) { MockImageCtx mock_image_ctx(*ictx); + MockExclusiveLock mock_exclusive_lock; + if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + } + expect_verify_lock_ownership(mock_image_ctx); expect_op_work_queue(mock_image_ctx); @@ -213,6 +242,11 @@ TEST_F(TestMockOperationSnapshotCreateRequest, ReleaseSnapIdError) { MockImageCtx mock_image_ctx(*ictx); + MockExclusiveLock mock_exclusive_lock; + if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + } + expect_verify_lock_ownership(mock_image_ctx); expect_op_work_queue(mock_image_ctx); diff --git a/src/test/librbd/operation/test_mock_SnapshotProtectRequest.cc b/src/test/librbd/operation/test_mock_SnapshotProtectRequest.cc index e77ceb22f87d..3c64d2738811 100644 --- a/src/test/librbd/operation/test_mock_SnapshotProtectRequest.cc +++ b/src/test/librbd/operation/test_mock_SnapshotProtectRequest.cc @@ -6,6 +6,7 @@ #include "test/librbd/mock/MockImageCtx.h" #include "test/librados_test_stub/MockTestMemIoCtxImpl.h" #include "common/bit_vector.hpp" +#include "librbd/ImageState.h" #include "librbd/internal.h" #include "librbd/operation/SnapshotProtectRequest.h" #include "gmock/gmock.h" @@ -61,7 +62,7 @@ TEST_F(TestMockOperationSnapshotProtectRequest, Success) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); MockImageCtx mock_image_ctx(*ictx); @@ -88,7 +89,7 @@ TEST_F(TestMockOperationSnapshotProtectRequest, GetSnapIdMissing) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); MockImageCtx mock_image_ctx(*ictx); @@ -113,7 +114,7 @@ TEST_F(TestMockOperationSnapshotProtectRequest, IsSnapProtectedError) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); MockImageCtx mock_image_ctx(*ictx); @@ -139,7 +140,7 @@ TEST_F(TestMockOperationSnapshotProtectRequest, SnapAlreadyProtected) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); MockImageCtx mock_image_ctx(*ictx); @@ -165,7 +166,7 @@ TEST_F(TestMockOperationSnapshotProtectRequest, SetProtectionStateError) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); MockImageCtx mock_image_ctx(*ictx); diff --git a/src/test/librbd/operation/test_mock_SnapshotRemoveRequest.cc b/src/test/librbd/operation/test_mock_SnapshotRemoveRequest.cc index 323f95b6bc56..122f4bf1761b 100644 --- a/src/test/librbd/operation/test_mock_SnapshotRemoveRequest.cc +++ b/src/test/librbd/operation/test_mock_SnapshotRemoveRequest.cc @@ -6,6 +6,7 @@ #include "test/librbd/mock/MockImageCtx.h" #include "test/librados_test_stub/MockTestMemIoCtxImpl.h" #include "common/bit_vector.hpp" +#include "librbd/ImageState.h" #include "librbd/internal.h" #include "librbd/operation/SnapshotRemoveRequest.h" #include "gmock/gmock.h" @@ -49,11 +50,8 @@ public: } void expect_object_map_snap_remove(MockImageCtx &mock_image_ctx, int r) { - bool enabled = mock_image_ctx.image_ctx->test_features(RBD_FEATURE_OBJECT_MAP); - EXPECT_CALL(mock_image_ctx.object_map, enabled(_)) - .WillOnce(Return(enabled)); - if (enabled) { - EXPECT_CALL(mock_image_ctx.object_map, snapshot_remove(_, _)) + if (mock_image_ctx.object_map != nullptr) { + EXPECT_CALL(*mock_image_ctx.object_map, snapshot_remove(_, _)) .WillOnce(WithArg<1>(CompleteContext( r, mock_image_ctx.image_ctx->op_work_queue))); } @@ -87,8 +85,10 @@ public: return; } - EXPECT_CALL(*mock_image_ctx.image_watcher, is_lock_owner()) - .WillRepeatedly(Return(false)); + if (mock_image_ctx.exclusive_lock != nullptr) { + EXPECT_CALL(*mock_image_ctx.exclusive_lock, is_lock_owner()) + .WillRepeatedly(Return(false)); + } } void expect_snap_remove(MockImageCtx &mock_image_ctx, int r) { @@ -120,10 +120,20 @@ TEST_F(TestMockOperationSnapshotRemoveRequest, Success) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); MockImageCtx mock_image_ctx(*ictx); + MockExclusiveLock mock_exclusive_lock; + if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + } + + MockObjectMap mock_object_map; + if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) { + mock_image_ctx.object_map = &mock_object_map; + } + expect_op_work_queue(mock_image_ctx); ::testing::InSequence seq; @@ -163,10 +173,20 @@ TEST_F(TestMockOperationSnapshotRemoveRequest, FlattenedCloneRemovesChild) { librbd::NoOpProgressContext prog_ctx; ASSERT_EQ(0, librbd::flatten(ictx, prog_ctx)); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); MockImageCtx mock_image_ctx(*ictx); + MockExclusiveLock mock_exclusive_lock; + if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + } + + MockObjectMap mock_object_map; + if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) { + mock_image_ctx.object_map = &mock_object_map; + } + expect_op_work_queue(mock_image_ctx); uint64_t snap_id = ictx->snap_info.rbegin()->first; @@ -194,10 +214,15 @@ TEST_F(TestMockOperationSnapshotRemoveRequest, ObjectMapSnapRemoveError) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); MockImageCtx mock_image_ctx(*ictx); + MockObjectMap mock_object_map; + if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) { + mock_image_ctx.object_map = &mock_object_map; + } + expect_op_work_queue(mock_image_ctx); ::testing::InSequence seq; @@ -218,10 +243,15 @@ TEST_F(TestMockOperationSnapshotRemoveRequest, RemoveChildParentError) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); MockImageCtx mock_image_ctx(*ictx); + MockObjectMap mock_object_map; + if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) { + mock_image_ctx.object_map = &mock_object_map; + } + expect_op_work_queue(mock_image_ctx); ::testing::InSequence seq; @@ -262,10 +292,15 @@ TEST_F(TestMockOperationSnapshotRemoveRequest, RemoveChildError) { librbd::NoOpProgressContext prog_ctx; ASSERT_EQ(0, librbd::flatten(ictx, prog_ctx)); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); MockImageCtx mock_image_ctx(*ictx); + MockObjectMap mock_object_map; + if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) { + mock_image_ctx.object_map = &mock_object_map; + } + expect_op_work_queue(mock_image_ctx); uint64_t snap_id = ictx->snap_info.rbegin()->first; @@ -287,10 +322,20 @@ TEST_F(TestMockOperationSnapshotRemoveRequest, RemoveSnapError) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); MockImageCtx mock_image_ctx(*ictx); + MockExclusiveLock mock_exclusive_lock; + if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + } + + MockObjectMap mock_object_map; + if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) { + mock_image_ctx.object_map = &mock_object_map; + } + expect_op_work_queue(mock_image_ctx); ::testing::InSequence seq; diff --git a/src/test/librbd/operation/test_mock_SnapshotUnprotectRequest.cc b/src/test/librbd/operation/test_mock_SnapshotUnprotectRequest.cc index 7ec65b48ae0e..07cb296a41f2 100644 --- a/src/test/librbd/operation/test_mock_SnapshotUnprotectRequest.cc +++ b/src/test/librbd/operation/test_mock_SnapshotUnprotectRequest.cc @@ -8,6 +8,7 @@ #include "test/librados_test_stub/MockTestMemRadosClient.h" #include "include/rados/librados.hpp" #include "common/bit_vector.hpp" +#include "librbd/ImageState.h" #include "librbd/internal.h" #include "librbd/operation/SnapshotUnprotectRequest.h" #include "gmock/gmock.h" @@ -105,7 +106,7 @@ TEST_F(TestMockOperationSnapshotUnprotectRequest, Success) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); MockImageCtx mock_image_ctx(*ictx); @@ -138,7 +139,7 @@ TEST_F(TestMockOperationSnapshotUnprotectRequest, GetSnapIdMissing) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); MockImageCtx mock_image_ctx(*ictx); @@ -163,7 +164,7 @@ TEST_F(TestMockOperationSnapshotUnprotectRequest, IsSnapUnprotectedError) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); MockImageCtx mock_image_ctx(*ictx); @@ -189,7 +190,7 @@ TEST_F(TestMockOperationSnapshotUnprotectRequest, SnapAlreadyUnprotected) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); MockImageCtx mock_image_ctx(*ictx); @@ -215,7 +216,7 @@ TEST_F(TestMockOperationSnapshotUnprotectRequest, SetProtectionStatusError) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); MockImageCtx mock_image_ctx(*ictx); @@ -244,7 +245,7 @@ TEST_F(TestMockOperationSnapshotUnprotectRequest, ChildrenExist) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, librbd::snap_create(ictx, "snap1")); - ASSERT_EQ(0, librbd::ictx_check(ictx)); + ASSERT_EQ(0, ictx->state->refresh_if_required()); MockImageCtx mock_image_ctx(*ictx); diff --git a/src/test/librbd/test_ImageWatcher.cc b/src/test/librbd/test_ImageWatcher.cc index 0bba8109d6a8..c816853ac4d8 100644 --- a/src/test/librbd/test_ImageWatcher.cc +++ b/src/test/librbd/test_ImageWatcher.cc @@ -45,44 +45,6 @@ public: { } - struct LockListener : public librbd::ImageWatcher::Listener { - Mutex lock; - Cond cond; - size_t releasing_lock_count; - size_t lock_updated_count; - bool lock_owner; - - LockListener() - : lock("lock"), releasing_lock_count(0), lock_updated_count(0), - lock_owner(false) { - } - - virtual bool handle_requested_lock() { - return true; - } - virtual void handle_lock_updated( - librbd::ImageWatcher::LockUpdateState state) { - Mutex::Locker locker(lock); - ++lock_updated_count; - - switch (state) { - case librbd::ImageWatcher::LOCK_UPDATE_STATE_NOT_SUPPORTED: - case librbd::ImageWatcher::LOCK_UPDATE_STATE_UNLOCKED: - case librbd::ImageWatcher::LOCK_UPDATE_STATE_NOTIFICATION: - lock_owner = false; - break; - case librbd::ImageWatcher::LOCK_UPDATE_STATE_RELEASING: - lock_owner = false; - ++releasing_lock_count; - break; - case librbd::ImageWatcher::LOCK_UPDATE_STATE_LOCKED: - lock_owner = true; - break; - } - cond.Signal(); - } - }; - class WatchCtx : public librados::WatchCtx2 { public: WatchCtx(TestImageWatcher &parent) : m_parent(parent), m_handle(0) {} @@ -165,39 +127,11 @@ public: return 0; } - void register_lock_listener(librbd::ImageCtx &ictx) { - ictx.image_watcher->register_listener(&m_lock_listener); - } - int register_image_watch(librbd::ImageCtx &ictx) { m_watch_ctx = new WatchCtx(*this); return m_watch_ctx->watch(ictx); } - bool wait_for_releasing_lock(librbd::ImageCtx &ictx) { - Mutex::Locker locker(m_lock_listener.lock); - while (m_lock_listener.releasing_lock_count == 0) { - if (m_lock_listener.cond.WaitInterval(ictx.cct, m_lock_listener.lock, - utime_t(10, 0)) != 0) { - return false; - } - } - m_lock_listener.releasing_lock_count = 0; - return true; - } - - bool wait_for_lock_updated(librbd::ImageCtx &ictx) { - Mutex::Locker locker(m_lock_listener.lock); - while (m_lock_listener.lock_updated_count == 0) { - if (m_lock_listener.cond.WaitInterval(ictx.cct, m_lock_listener.lock, - utime_t(10, 0)) != 0) { - return false; - } - } - m_lock_listener.lock_updated_count = 0; - return true; - } - bool wait_for_notifies(librbd::ImageCtx &ictx) { Mutex::Locker l(m_callback_lock); while (m_notifies.size() < m_notify_acks.size()) { @@ -271,8 +205,6 @@ public: WatchCtx *m_watch_ctx; - LockListener m_lock_listener; - NotifyOps m_notifies; NotifyOpPayloads m_notify_payloads; NotifyOpPayloads m_notify_acks; @@ -357,487 +289,58 @@ struct RebuildObjectMapTask { } }; -TEST_F(TestImageWatcher, IsLockSupported) { - REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - RWLock::WLocker l(ictx->owner_lock); - ASSERT_TRUE(ictx->image_watcher); - ASSERT_TRUE(ictx->image_watcher->is_lock_supported()); - - ictx->read_only = true; - ASSERT_FALSE(ictx->image_watcher->is_lock_supported()); - ictx->read_only = false; - - ictx->features &= ~RBD_FEATURE_EXCLUSIVE_LOCK; - ASSERT_FALSE(ictx->image_watcher->is_lock_supported()); - ictx->features |= RBD_FEATURE_EXCLUSIVE_LOCK; - - ictx->snap_id = 1234; - ASSERT_FALSE(ictx->image_watcher->is_lock_supported()); - ictx->snap_id = CEPH_NOSNAP; -} - -TEST_F(TestImageWatcher, TryLock) { - REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - ASSERT_TRUE(ictx->image_watcher); - - { - RWLock::WLocker l(ictx->owner_lock); - ASSERT_EQ(0, ictx->image_watcher->try_lock()); - ASSERT_TRUE(ictx->image_watcher->is_lock_owner()); - } - - std::map lockers; - ClsLockType lock_type; - ASSERT_EQ(0, rados::cls::lock::get_lock_info(&m_ioctx, ictx->header_oid, - RBD_LOCK_NAME, &lockers, - &lock_type, NULL)); - ASSERT_EQ(LOCK_EXCLUSIVE, lock_type); - ASSERT_EQ(1U, lockers.size()); -} - -TEST_F(TestImageWatcher, TryLockNotifyAnnounceLocked) { +TEST_F(TestImageWatcher, NotifyRequestLock) { REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK); librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, register_image_watch(*ictx)); - m_notify_acks = {{NOTIFY_OP_ACQUIRED_LOCK, {}}}; - { - RWLock::WLocker l(ictx->owner_lock); - ASSERT_EQ(0, ictx->image_watcher->try_lock()); - } + m_notify_acks = {{NOTIFY_OP_REQUEST_LOCK, {}}}; + ictx->image_watcher->notify_request_lock(); ASSERT_TRUE(wait_for_notifies(*ictx)); NotifyOps expected_notify_ops; - expected_notify_ops += NOTIFY_OP_ACQUIRED_LOCK; + expected_notify_ops += NOTIFY_OP_REQUEST_LOCK; ASSERT_EQ(expected_notify_ops, m_notifies); } -TEST_F(TestImageWatcher, TryLockWithTimedOutOwner) { - REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK); - - // use new Rados connection due to blacklisting - librados::Rados rados; - ASSERT_EQ("", connect_cluster_pp(rados)); - - librados::IoCtx io_ctx; - ASSERT_EQ(0, rados.ioctx_create(_pool_name.c_str(), io_ctx)); - librbd::ImageCtx *ictx = new librbd::ImageCtx(m_image_name.c_str(), "", NULL, - io_ctx, false); - ASSERT_EQ(0, librbd::open_image(ictx)); - ASSERT_EQ(0, lock_image(*ictx, LOCK_EXCLUSIVE, "auto 1234")); - librbd::close_image(ictx); - io_ctx.close(); - - // no watcher on the locked image means we can break the lock - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - RWLock::WLocker l(ictx->owner_lock); - ASSERT_EQ(0, ictx->image_watcher->try_lock()); - ASSERT_TRUE(ictx->image_watcher->is_lock_owner()); - - rados.test_blacklist_self(false); -} - -TEST_F(TestImageWatcher, TryLockWithUserExclusiveLock) { - REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - ASSERT_EQ(0, lock_image(*ictx, LOCK_EXCLUSIVE, "manually locked")); - - RWLock::WLocker l(ictx->owner_lock); - ASSERT_EQ(-EBUSY, ictx->image_watcher->try_lock()); - ASSERT_FALSE(ictx->image_watcher->is_lock_owner()); - - ASSERT_EQ(0, unlock_image()); - ASSERT_EQ(0, ictx->image_watcher->try_lock()); - ASSERT_TRUE(ictx->image_watcher->is_lock_owner()); -} - -TEST_F(TestImageWatcher, TryLockWithUserSharedLocked) { - REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - ASSERT_EQ(0, lock_image(*ictx, LOCK_SHARED, "manually locked")); - - RWLock::WLocker l(ictx->owner_lock); - ASSERT_EQ(-EBUSY, ictx->image_watcher->try_lock()); - ASSERT_FALSE(ictx->image_watcher->is_lock_owner()); - - ASSERT_EQ(0, unlock_image()); - ASSERT_EQ(0, ictx->image_watcher->try_lock()); - ASSERT_TRUE(ictx->image_watcher->is_lock_owner()); -} - -TEST_F(TestImageWatcher, ReleaseLockNotLocked) { - REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - RWLock::WLocker l(ictx->owner_lock); - ASSERT_EQ(0, ictx->image_watcher->release_lock()); -} - -TEST_F(TestImageWatcher, ReleaseLockNotifies) { +TEST_F(TestImageWatcher, NotifyReleasedLock) { REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK); librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, register_image_watch(*ictx)); - m_notify_acks = {{NOTIFY_OP_ACQUIRED_LOCK, {}}}; - { - RWLock::WLocker l(ictx->owner_lock); - ASSERT_EQ(0, ictx->image_watcher->try_lock()); - } - ASSERT_TRUE(wait_for_notifies(*ictx)); + m_notify_acks = {{NOTIFY_OP_RELEASED_LOCK, {}}}; + ictx->image_watcher->notify_released_lock(); - m_notify_acks += std::make_pair(NOTIFY_OP_RELEASED_LOCK, bufferlist()); - { - RWLock::WLocker l(ictx->owner_lock); - ASSERT_EQ(0, ictx->image_watcher->release_lock()); - } ASSERT_TRUE(wait_for_notifies(*ictx)); NotifyOps expected_notify_ops; - expected_notify_ops += NOTIFY_OP_ACQUIRED_LOCK, NOTIFY_OP_RELEASED_LOCK; + expected_notify_ops += NOTIFY_OP_RELEASED_LOCK; ASSERT_EQ(expected_notify_ops, m_notifies); } -TEST_F(TestImageWatcher, ReleaseLockBrokenLock) { +TEST_F(TestImageWatcher, NotifyAcquiredLock) { REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK); librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); - RWLock::WLocker l(ictx->owner_lock); - ASSERT_EQ(0, ictx->image_watcher->try_lock()); - - std::map lockers; - ClsLockType lock_type; - ASSERT_EQ(0, rados::cls::lock::get_lock_info(&m_ioctx, ictx->header_oid, - RBD_LOCK_NAME, &lockers, - &lock_type, NULL)); - ASSERT_EQ(1U, lockers.size()); - ASSERT_EQ(0, rados::cls::lock::break_lock(&m_ioctx, ictx->header_oid, - RBD_LOCK_NAME, - lockers.begin()->first.cookie, - lockers.begin()->first.locker)); - - ASSERT_EQ(0, ictx->image_watcher->release_lock()); -} - -TEST_F(TestImageWatcher, RequestLock) { - REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_EQ(0, register_image_watch(*ictx)); - register_lock_listener(*ictx); m_notify_acks = {{NOTIFY_OP_ACQUIRED_LOCK, {}}}; - - { - RWLock::RLocker owner_locker(ictx->owner_lock); - ictx->image_watcher->request_lock(); - } + ictx->image_watcher->notify_acquired_lock(); ASSERT_TRUE(wait_for_notifies(*ictx)); - NotifyOps expected_notify_ops; - expected_notify_ops += NOTIFY_OP_ACQUIRED_LOCK; - ASSERT_EQ(expected_notify_ops, m_notifies); - { - RWLock::RLocker owner_locker(ictx->owner_lock); - ASSERT_TRUE(ictx->image_watcher->is_lock_owner()); - } -} - -TEST_F(TestImageWatcher, RequestLockFromPeer) { - REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - ASSERT_EQ(0, register_image_watch(*ictx)); - ASSERT_EQ(0, lock_image(*ictx, LOCK_EXCLUSIVE, - "auto " + stringify(m_watch_ctx->get_handle()))); - - register_lock_listener(*ictx); - m_notify_acks = {{NOTIFY_OP_REQUEST_LOCK, create_response_message(0)}}; - - { - RWLock::RLocker owner_locker(ictx->owner_lock); - ictx->image_watcher->request_lock(); - } - - ASSERT_TRUE(wait_for_notifies(*ictx)); NotifyOps expected_notify_ops; - expected_notify_ops += NOTIFY_OP_REQUEST_LOCK; - ASSERT_EQ(expected_notify_ops, m_notifies); - - ASSERT_EQ(0, unlock_image()); - - { - Mutex::Locker l(m_callback_lock); - m_notifies.clear(); - m_notify_acks = {{NOTIFY_OP_RELEASED_LOCK,{}}}; - } - - bufferlist bl; - { - ENCODE_START(1, 1, bl); - ::encode(NOTIFY_OP_RELEASED_LOCK, bl); - ENCODE_FINISH(bl); - } - ASSERT_EQ(0, m_ioctx.notify2(ictx->header_oid, bl, 5000, NULL)); - ASSERT_TRUE(wait_for_lock_updated(*ictx)); - - { - Mutex::Locker l(m_callback_lock); - m_notifies.clear(); - m_notify_acks = {{NOTIFY_OP_ACQUIRED_LOCK, {}}}; - } - - { - RWLock::RLocker owner_lock(ictx->owner_lock); - ictx->image_watcher->request_lock(); - } - - ASSERT_TRUE(wait_for_notifies(*ictx)); - expected_notify_ops.clear(); expected_notify_ops += NOTIFY_OP_ACQUIRED_LOCK; ASSERT_EQ(expected_notify_ops, m_notifies); - - { - RWLock::RLocker owner_locker(ictx->owner_lock); - ASSERT_TRUE(ictx->image_watcher->is_lock_owner()); - } -} - -TEST_F(TestImageWatcher, RequestLockTimedOut) { - REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - ASSERT_EQ(0, register_image_watch(*ictx)); - ASSERT_EQ(0, lock_image(*ictx, LOCK_EXCLUSIVE, - "auto " + stringify(m_watch_ctx->get_handle()))); - - register_lock_listener(*ictx); - m_notify_acks = {{NOTIFY_OP_REQUEST_LOCK, {}}}; - - { - RWLock::RLocker owner_locker(ictx->owner_lock); - ictx->image_watcher->request_lock(); - } - - ASSERT_TRUE(wait_for_notifies(*ictx)); - NotifyOps expected_notify_ops; - expected_notify_ops += NOTIFY_OP_REQUEST_LOCK; - ASSERT_EQ(expected_notify_ops, m_notifies); - - // should resend when empty ack returned - { - Mutex::Locker l(m_callback_lock); - m_notifies.clear(); - } - ASSERT_TRUE(wait_for_notifies(*ictx)); - - { - Mutex::Locker l(m_callback_lock); - ASSERT_EQ(0, unlock_image()); - m_notifies.clear(); - m_notify_acks = {{NOTIFY_OP_ACQUIRED_LOCK, {}}}; - } - - ASSERT_TRUE(wait_for_notifies(*ictx)); - ASSERT_TRUE(wait_for_lock_updated(*ictx)); - - { - RWLock::RLocker owner_locker(ictx->owner_lock); - ASSERT_TRUE(ictx->image_watcher->is_lock_owner()); - } -} - -TEST_F(TestImageWatcher, RequestLockIgnored) { - REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - ASSERT_EQ(0, register_image_watch(*ictx)); - ASSERT_EQ(0, lock_image(*ictx, LOCK_EXCLUSIVE, - "auto " + stringify(m_watch_ctx->get_handle()))); - - register_lock_listener(*ictx); - m_notify_acks = {{NOTIFY_OP_REQUEST_LOCK, create_response_message(0)}}; - - int orig_notify_timeout = ictx->cct->_conf->client_notify_timeout; - ictx->cct->_conf->set_val("client_notify_timeout", "0"); - BOOST_SCOPE_EXIT( (ictx)(orig_notify_timeout) ) { - ictx->cct->_conf->set_val("client_notify_timeout", - stringify(orig_notify_timeout)); - } BOOST_SCOPE_EXIT_END; - - { - RWLock::RLocker owner_locker(ictx->owner_lock); - ictx->image_watcher->request_lock(); - } - - ASSERT_TRUE(wait_for_notifies(*ictx)); - NotifyOps expected_notify_ops; - expected_notify_ops += NOTIFY_OP_REQUEST_LOCK; - ASSERT_EQ(expected_notify_ops, m_notifies); - - // after the request times out -- it will be resent - { - Mutex::Locker l(m_callback_lock); - m_notifies.clear(); - } - ASSERT_TRUE(wait_for_notifies(*ictx)); - ASSERT_EQ(expected_notify_ops, m_notifies); - - { - Mutex::Locker l(m_callback_lock); - ASSERT_EQ(0, unlock_image()); - m_notifies.clear(); - m_notify_acks = {{NOTIFY_OP_ACQUIRED_LOCK, {}}}; - } - - ASSERT_TRUE(wait_for_notifies(*ictx)); - ASSERT_TRUE(wait_for_lock_updated(*ictx)); - - { - RWLock::RLocker owner_locker(ictx->owner_lock); - ASSERT_TRUE(ictx->image_watcher->is_lock_owner()); - } -} - -TEST_F(TestImageWatcher, RequestLockTryLockRace) { - REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - ASSERT_EQ(0, register_image_watch(*ictx)); - ASSERT_EQ(0, lock_image(*ictx, LOCK_EXCLUSIVE, - "auto " + stringify(m_watch_ctx->get_handle()))); - - register_lock_listener(*ictx); - m_notify_acks = {{NOTIFY_OP_REQUEST_LOCK, create_response_message(0)}}; - - { - RWLock::RLocker owner_locker(ictx->owner_lock); - ictx->image_watcher->request_lock(); - } - - ASSERT_TRUE(wait_for_notifies(*ictx)); - NotifyOps expected_notify_ops; - expected_notify_ops += NOTIFY_OP_REQUEST_LOCK; - ASSERT_EQ(expected_notify_ops, m_notifies); - - { - Mutex::Locker l(m_callback_lock); - m_notifies.clear(); - m_notify_acks = {{NOTIFY_OP_RELEASED_LOCK, {}}}; - } - - bufferlist bl; - { - ENCODE_START(1, 1, bl); - ::encode(NOTIFY_OP_RELEASED_LOCK, bl); - ENCODE_FINISH(bl); - } - ASSERT_EQ(0, m_ioctx.notify2(ictx->header_oid, bl, 5000, NULL)); - - // after losing race -- it will re-request - ASSERT_TRUE(wait_for_notifies(*ictx)); - - { - RWLock::RLocker owner_locker(ictx->owner_lock); - ASSERT_FALSE(ictx->image_watcher->is_lock_owner()); - } - - { - Mutex::Locker l(m_callback_lock); - ASSERT_EQ(0, unlock_image()); - m_notifies.clear(); - m_notify_acks = {{NOTIFY_OP_RELEASED_LOCK, {}}}; - } - - ASSERT_EQ(0, m_ioctx.notify2(ictx->header_oid, bl, 5000, NULL)); - ASSERT_TRUE(wait_for_lock_updated(*ictx)); - - { - Mutex::Locker l(m_callback_lock); - m_notifies.clear(); - m_notify_acks = {{NOTIFY_OP_ACQUIRED_LOCK, {}}}; - } - - { - RWLock::RLocker owner_lock(ictx->owner_lock); - ictx->image_watcher->request_lock(); - } - - ASSERT_TRUE(wait_for_lock_updated(*ictx)); - ASSERT_TRUE(wait_for_notifies(*ictx)); - - { - RWLock::RLocker owner_locker(ictx->owner_lock); - ASSERT_TRUE(ictx->image_watcher->is_lock_owner()); - } -} - -TEST_F(TestImageWatcher, RequestLockTryLockFailed) { - REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - ASSERT_EQ(0, register_image_watch(*ictx)); - ASSERT_EQ(0, lock_image(*ictx, LOCK_SHARED, "manually 1234")); - - register_lock_listener(*ictx); - m_notify_acks = {{NOTIFY_OP_REQUEST_LOCK, {}}}; - - { - RWLock::RLocker owner_locker(ictx->owner_lock); - ictx->image_watcher->request_lock(); - } - - ASSERT_TRUE(wait_for_notifies(*ictx)); - NotifyOps expected_notify_ops; - expected_notify_ops += NOTIFY_OP_REQUEST_LOCK; - ASSERT_EQ(expected_notify_ops, m_notifies); - - // should resend when error encountered - { - Mutex::Locker l(m_callback_lock); - m_notifies.clear(); - } - ASSERT_TRUE(wait_for_notifies(*ictx)); - - { - Mutex::Locker l(m_callback_lock); - ASSERT_EQ(0, unlock_image()); - m_notifies.clear(); - m_notify_acks = {{NOTIFY_OP_ACQUIRED_LOCK, {}}}; - } - - ASSERT_TRUE(wait_for_notifies(*ictx)); } TEST_F(TestImageWatcher, NotifyHeaderUpdate) { @@ -1216,47 +719,3 @@ TEST_F(TestImageWatcher, NotifyAsyncRequestTimedOut) { ASSERT_EQ(-ERESTART, flatten_task.result); } -TEST_F(TestImageWatcher, PeerRequestsLock) { - REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - ASSERT_EQ(0, register_image_watch(*ictx)); - - register_lock_listener(*ictx); - m_notify_acks = {{NOTIFY_OP_ACQUIRED_LOCK, {}}}; - - { - RWLock::RLocker owner_locker(ictx->owner_lock); - ictx->image_watcher->request_lock(); - } - - ASSERT_TRUE(wait_for_notifies(*ictx)); - - { - RWLock::RLocker owner_locker(ictx->owner_lock); - ASSERT_TRUE(ictx->image_watcher->is_lock_owner()); - } - - // if journaling is enabled, ensure we wait for it to replay since - // it will block our peer request - std::string buffer(256, '1'); - ictx->aio_work_queue->write(0, buffer.size(), buffer.c_str(), 0); - - { - Mutex::Locker l(m_callback_lock); - m_notifies.clear(); - m_notify_acks = {{NOTIFY_OP_RELEASED_LOCK, {}}}; - } - - bufferlist bl; - { - ENCODE_START(1, 1, bl); - ::encode(NOTIFY_OP_REQUEST_LOCK, bl); - ENCODE_FINISH(bl); - } - ASSERT_EQ(0, m_ioctx.notify2(ictx->header_oid, bl, 5000, NULL)); - - ASSERT_TRUE(wait_for_releasing_lock(*ictx)); - ASSERT_TRUE(wait_for_notifies(*ictx)); -} diff --git a/src/test/librbd/test_JournalReplay.cc b/src/test/librbd/test_JournalReplay.cc index 0b6374763f9d..c5a6ad63d414 100644 --- a/src/test/librbd/test_JournalReplay.cc +++ b/src/test/librbd/test_JournalReplay.cc @@ -6,6 +6,7 @@ #include "librbd/AioCompletion.h" #include "librbd/AioImageRequest.h" #include "librbd/AioImageRequestWQ.h" +#include "librbd/ExclusiveLock.h" #include "librbd/ImageCtx.h" #include "librbd/ImageWatcher.h" #include "librbd/Journal.h" @@ -17,38 +18,13 @@ void register_test_journal_replay() { class TestJournalReplay : public TestFixture { public: - struct Listener : public librbd::ImageWatcher::Listener{ - Mutex lock; - Cond cond; - - Listener() : lock("TestJournalReplay::Listener::lock") { - } - virtual bool handle_requested_lock() { - return true; - } - virtual void handle_releasing_lock() { - } - virtual void handle_lock_updated( - librbd::ImageWatcher::LockUpdateState state) { - Mutex::Locker locker(lock); - cond.Signal(); - } - }; - - void wait_for_lock_owner(librbd::ImageCtx *ictx) { - Listener listener; - ictx->image_watcher->register_listener(&listener); + int when_acquired_lock(librbd::ImageCtx *ictx) { + C_SaferCond lock_ctx; { - RWLock::RLocker owner_locker(ictx->owner_lock); - while (!ictx->image_watcher->is_lock_owner()) { - ictx->owner_lock.put_read(); - listener.lock.Lock(); - listener.cond.Wait(listener.lock); - listener.lock.Unlock(); - ictx->owner_lock.get_read(); - } + RWLock::WLocker owner_locker(ictx->owner_lock); + ictx->exclusive_lock->request_lock(&lock_ctx); } - ictx->image_watcher->unregister_listener(&listener); + return lock_ctx.wait(); } }; @@ -59,7 +35,6 @@ TEST_F(TestJournalReplay, AioDiscardEvent) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); ictx->features &= ~RBD_FEATURE_JOURNALING; - ASSERT_EQ(0, ictx->close_journal(true)); std::string payload(4096, '1'); librbd::AioCompletion *aio_comp = new librbd::AioCompletion(); @@ -84,14 +59,7 @@ TEST_F(TestJournalReplay, AioDiscardEvent) { // inject a discard operation into the journal ASSERT_EQ(0, open_image(m_image_name, &ictx)); - { - RWLock::WLocker owner_locker(ictx->owner_lock); - ictx->image_watcher->request_lock(); - } - wait_for_lock_owner(ictx); - - ictx->journal->open(); - ictx->journal->wait_for_journal_ready(); + ASSERT_EQ(0, when_acquired_lock(ictx)); librbd::journal::EventEntry event_entry( librbd::journal::AioDiscardEvent(0, payload.size())); @@ -100,11 +68,10 @@ TEST_F(TestJournalReplay, AioDiscardEvent) { RWLock::RLocker owner_locker(ictx->owner_lock); ictx->journal->append_io_event(NULL, event_entry, requests, 0, 0, true); } - ASSERT_EQ(0, ictx->journal->close()); // re-open the journal so that it replays the new entry - ictx->journal->open(); - ictx->journal->wait_for_journal_ready(); + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + ASSERT_EQ(0, when_acquired_lock(ictx)); aio_comp = new librbd::AioCompletion(); ictx->aio_work_queue->aio_read(aio_comp, 0, read_payload.size(), @@ -120,14 +87,7 @@ TEST_F(TestJournalReplay, AioWriteEvent) { // inject a write operation into the journal librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); - { - RWLock::WLocker owner_locker(ictx->owner_lock); - ictx->image_watcher->request_lock(); - } - wait_for_lock_owner(ictx); - - ictx->journal->open(); - ictx->journal->wait_for_journal_ready(); + ASSERT_EQ(0, when_acquired_lock(ictx)); std::string payload(4096, '1'); bufferlist payload_bl; @@ -139,11 +99,10 @@ TEST_F(TestJournalReplay, AioWriteEvent) { RWLock::RLocker owner_locker(ictx->owner_lock); ictx->journal->append_io_event(NULL, event_entry, requests, 0, 0, true); } - ASSERT_EQ(0, ictx->journal->close()); // re-open the journal so that it replays the new entry - ictx->journal->open(); - ictx->journal->wait_for_journal_ready(); + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + ASSERT_EQ(0, when_acquired_lock(ictx)); std::string read_payload(4096, '\0'); librbd::AioCompletion *aio_comp = new librbd::AioCompletion(); @@ -159,15 +118,9 @@ TEST_F(TestJournalReplay, AioFlushEvent) { // inject a flush operation into the journal librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - { - RWLock::WLocker owner_locker(ictx->owner_lock); - ictx->image_watcher->request_lock(); - } - wait_for_lock_owner(ictx); - ictx->journal->open(); - ictx->journal->wait_for_journal_ready(); + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + ASSERT_EQ(0, when_acquired_lock(ictx)); librbd::journal::AioFlushEvent aio_flush_event; librbd::journal::EventEntry event_entry(aio_flush_event); @@ -176,7 +129,6 @@ TEST_F(TestJournalReplay, AioFlushEvent) { RWLock::RLocker owner_locker(ictx->owner_lock); ictx->journal->append_io_event(NULL, event_entry, requests, 0, 0, true); } - ASSERT_EQ(0, ictx->journal->close()); // start an AIO write op librbd::Journal *journal = ictx->journal; @@ -192,8 +144,8 @@ TEST_F(TestJournalReplay, AioFlushEvent) { ictx->journal = journal; // re-open the journal so that it replays the new entry - ictx->journal->open(); - ictx->journal->wait_for_journal_ready(); + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + ASSERT_EQ(0, when_acquired_lock(ictx)); ASSERT_TRUE(aio_comp->is_complete()); ASSERT_EQ(0, aio_comp->wait_for_complete()); diff --git a/src/test/librbd/test_ObjectMap.cc b/src/test/librbd/test_ObjectMap.cc index 5457b9974fd1..b3b19e45ccd3 100644 --- a/src/test/librbd/test_ObjectMap.cc +++ b/src/test/librbd/test_ObjectMap.cc @@ -2,6 +2,7 @@ // vim: ts=8 sw=2 smarttab #include "test/librbd/test_fixture.h" #include "test/librbd/test_support.h" +#include "librbd/ExclusiveLock.h" #include "librbd/ImageCtx.h" #include "librbd/ImageWatcher.h" #include "librbd/internal.h" @@ -14,6 +15,13 @@ void register_test_object_map() { class TestObjectMap : public TestFixture { public: + + int when_open_object_map(librbd::ImageCtx *ictx) { + C_SaferCond ctx; + librbd::ObjectMap object_map(*ictx, ictx->snap_id); + object_map.open(&ctx); + return ctx.wait(); + } }; TEST_F(TestObjectMap, RefreshInvalidatesWhenCorrupt) { @@ -23,21 +31,19 @@ TEST_F(TestObjectMap, RefreshInvalidatesWhenCorrupt) { ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_FALSE(ictx->test_flags(RBD_FLAG_OBJECT_MAP_INVALID)); + C_SaferCond lock_ctx; { RWLock::WLocker owner_locker(ictx->owner_lock); - ASSERT_EQ(0, ictx->image_watcher->try_lock()); + ictx->exclusive_lock->try_lock(&lock_ctx); } + ASSERT_EQ(0, lock_ctx.wait()); std::string oid = librbd::ObjectMap::object_map_name(ictx->id, CEPH_NOSNAP); bufferlist bl; bl.append("corrupt"); ASSERT_EQ(0, ictx->data_ctx.write_full(oid, bl)); - { - RWLock::RLocker owner_locker(ictx->owner_lock); - RWLock::WLocker snap_locker(ictx->snap_lock); - ictx->object_map.refresh(CEPH_NOSNAP); - } + ASSERT_EQ(0, when_open_object_map(ictx)); ASSERT_TRUE(ictx->test_flags(RBD_FLAG_OBJECT_MAP_INVALID)); } @@ -48,10 +54,12 @@ TEST_F(TestObjectMap, RefreshInvalidatesWhenTooSmall) { ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_FALSE(ictx->test_flags(RBD_FLAG_OBJECT_MAP_INVALID)); + C_SaferCond lock_ctx; { RWLock::WLocker owner_locker(ictx->owner_lock); - ASSERT_EQ(0, ictx->image_watcher->try_lock()); + ictx->exclusive_lock->try_lock(&lock_ctx); } + ASSERT_EQ(0, lock_ctx.wait()); librados::ObjectWriteOperation op; librbd::cls_client::object_map_resize(&op, 0, OBJECT_NONEXISTENT); @@ -59,11 +67,7 @@ TEST_F(TestObjectMap, RefreshInvalidatesWhenTooSmall) { std::string oid = librbd::ObjectMap::object_map_name(ictx->id, CEPH_NOSNAP); ASSERT_EQ(0, ictx->data_ctx.operate(oid, &op)); - { - RWLock::RLocker owner_locker(ictx->owner_lock); - RWLock::WLocker snap_locker(ictx->snap_lock); - ictx->object_map.refresh(CEPH_NOSNAP); - } + ASSERT_EQ(0, when_open_object_map(ictx)); ASSERT_TRUE(ictx->test_flags(RBD_FLAG_OBJECT_MAP_INVALID)); } @@ -74,21 +78,19 @@ TEST_F(TestObjectMap, InvalidateFlagOnDisk) { ASSERT_EQ(0, open_image(m_image_name, &ictx)); ASSERT_FALSE(ictx->test_flags(RBD_FLAG_OBJECT_MAP_INVALID)); + C_SaferCond lock_ctx; { RWLock::WLocker owner_locker(ictx->owner_lock); - ASSERT_EQ(0, ictx->image_watcher->try_lock()); + ictx->exclusive_lock->try_lock(&lock_ctx); } + ASSERT_EQ(0, lock_ctx.wait()); std::string oid = librbd::ObjectMap::object_map_name(ictx->id, CEPH_NOSNAP); bufferlist bl; bl.append("corrupt"); ASSERT_EQ(0, ictx->data_ctx.write_full(oid, bl)); - { - RWLock::RLocker owner_locker(ictx->owner_lock); - RWLock::WLocker snap_locker(ictx->snap_lock); - ictx->object_map.refresh(CEPH_NOSNAP); - } + ASSERT_EQ(0, when_open_object_map(ictx)); ASSERT_TRUE(ictx->test_flags(RBD_FLAG_OBJECT_MAP_INVALID)); ASSERT_EQ(0, open_image(m_image_name, &ictx)); @@ -110,11 +112,7 @@ TEST_F(TestObjectMap, InvalidateFlagInMemoryOnly) { corrupt_bl.append("corrupt"); ASSERT_EQ(0, ictx->data_ctx.write_full(oid, corrupt_bl)); - { - RWLock::RLocker owner_locker(ictx->owner_lock); - RWLock::WLocker snap_locker(ictx->snap_lock); - ictx->object_map.refresh(CEPH_NOSNAP); - } + ASSERT_EQ(0, when_open_object_map(ictx)); ASSERT_TRUE(ictx->test_flags(RBD_FLAG_OBJECT_MAP_INVALID)); ASSERT_EQ(0, ictx->data_ctx.write_full(oid, valid_bl)); diff --git a/src/test/librbd/test_fixture.cc b/src/test/librbd/test_fixture.cc index 9be0f1b93f80..8c6a4b9e3925 100644 --- a/src/test/librbd/test_fixture.cc +++ b/src/test/librbd/test_fixture.cc @@ -4,6 +4,8 @@ #include "test/librbd/test_support.h" #include "include/stringify.h" #include "librbd/AioImageRequestWQ.h" +#include "librbd/ExclusiveLock.h" +#include "librbd/ImageState.h" #include "librbd/ImageWatcher.h" #include "cls/lock/cls_lock_client.h" #include "cls/lock/cls_lock_types.h" @@ -46,7 +48,7 @@ void TestFixture::TearDown() { unlock_image(); for (std::set::iterator iter = m_ictxs.begin(); iter != m_ictxs.end(); ++iter) { - librbd::close_image(*iter); + (*iter)->state->close(); } m_ioctx.close(); @@ -56,12 +58,14 @@ int TestFixture::open_image(const std::string &image_name, librbd::ImageCtx **ictx) { *ictx = new librbd::ImageCtx(image_name.c_str(), "", NULL, m_ioctx, false); m_ictxs.insert(*ictx); - return librbd::open_image(*ictx); + + return (*ictx)->state->open(); } void TestFixture::close_image(librbd::ImageCtx *ictx) { m_ictxs.erase(ictx); - librbd::close_image(ictx); + + ictx->state->close(); } int TestFixture::lock_image(librbd::ImageCtx &ictx, ClsLockType lock_type, @@ -93,5 +97,6 @@ int TestFixture::acquire_exclusive_lock(librbd::ImageCtx &ictx) { } RWLock::RLocker owner_locker(ictx.owner_lock); - return ictx.image_watcher->is_lock_owner() ? 0 : -EINVAL; + assert(ictx.exclusive_lock != nullptr); + return ictx.exclusive_lock->is_lock_owner() ? 0 : -EINVAL; } diff --git a/src/test/librbd/test_internal.cc b/src/test/librbd/test_internal.cc index f8f5702d267b..d2884c6fed72 100644 --- a/src/test/librbd/test_internal.cc +++ b/src/test/librbd/test_internal.cc @@ -5,6 +5,7 @@ #include "librbd/AioCompletion.h" #include "librbd/AioImageRequest.h" #include "librbd/AioImageRequestWQ.h" +#include "librbd/ExclusiveLock.h" #include "librbd/ImageWatcher.h" #include "librbd/internal.h" #include "librbd/ObjectMap.h" @@ -79,11 +80,12 @@ TEST_F(TestInternal, IsExclusiveLockOwner) { ASSERT_EQ(0, librbd::is_exclusive_lock_owner(ictx, &is_owner)); ASSERT_FALSE(is_owner); + C_SaferCond ctx; { RWLock::WLocker l(ictx->owner_lock); - ASSERT_EQ(0, ictx->image_watcher->try_lock()); + ictx->exclusive_lock->try_lock(&ctx); } - + ASSERT_EQ(0, ctx.wait()); ASSERT_EQ(0, librbd::is_exclusive_lock_owner(ictx, &is_owner)); ASSERT_TRUE(is_owner); } @@ -295,10 +297,16 @@ TEST_F(TestInternal, CancelAsyncResize) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); + C_SaferCond ctx; { RWLock::WLocker l(ictx->owner_lock); - ASSERT_EQ(0, ictx->image_watcher->try_lock()); - ASSERT_TRUE(ictx->image_watcher->is_lock_owner()); + ictx->exclusive_lock->try_lock(&ctx); + } + + ASSERT_EQ(0, ctx.wait()); + { + RWLock::RLocker owner_locker(ictx->owner_lock); + ASSERT_TRUE(ictx->exclusive_lock->is_lock_owner()); } uint64_t size; @@ -331,12 +339,16 @@ TEST_F(TestInternal, MultipleResize) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); - { - RWLock::WLocker l(ictx->owner_lock); - if (ictx->image_watcher->is_lock_supported()) { - ASSERT_EQ(0, ictx->image_watcher->try_lock()); - ASSERT_TRUE(ictx->image_watcher->is_lock_owner()); + if (ictx->exclusive_lock != nullptr) { + C_SaferCond ctx; + { + RWLock::WLocker l(ictx->owner_lock); + ictx->exclusive_lock->try_lock(&ctx); } + + RWLock::RLocker owner_locker(ictx->owner_lock); + ASSERT_EQ(0, ctx.wait()); + ASSERT_TRUE(ictx->exclusive_lock->is_lock_owner()); } uint64_t size; @@ -506,8 +518,7 @@ TEST_F(TestInternal, SnapshotCopyup) bufferlist read_bl; read_bl.push_back(read_ptr); - std::list snaps = boost::assign::list_of( - "snap1")("snap2")(""); + std::list snaps = {"snap1", "snap2", ""}; for (std::list::iterator it = snaps.begin(); it != snaps.end(); ++it) { const char *snap_name = it->empty() ? NULL : it->c_str(); @@ -530,8 +541,14 @@ TEST_F(TestInternal, SnapshotCopyup) it != snaps.begin() && snap_name != NULL) { state = OBJECT_EXISTS_CLEAN; } + + librbd::ObjectMap object_map(*ictx2, ictx2->snap_id); + C_SaferCond ctx; + object_map.open(&ctx); + ASSERT_EQ(0, ctx.wait()); + RWLock::WLocker object_map_locker(ictx2->object_map_lock); - ASSERT_EQ(state, ictx2->object_map[0]); + ASSERT_EQ(state, object_map[0]); } } } diff --git a/src/test/librbd/test_librbd.cc b/src/test/librbd/test_librbd.cc index 59da12d57573..7b84d359d2c8 100644 --- a/src/test/librbd/test_librbd.cc +++ b/src/test/librbd/test_librbd.cc @@ -2826,16 +2826,16 @@ TEST_F(TestLibRBD, RebuildObjectMapViaLockOwner) librbd::Image image1; ASSERT_EQ(0, rbd.open(ioctx, image1, name.c_str(), NULL)); - uint64_t flags; - ASSERT_EQ(0, image1.get_flags(&flags)); - ASSERT_TRUE((flags & RBD_FLAG_OBJECT_MAP_INVALID) != 0); - bool lock_owner; bl.clear(); ASSERT_EQ(0, image1.write(0, 0, bl)); ASSERT_EQ(0, image1.is_exclusive_lock_owner(&lock_owner)); ASSERT_TRUE(lock_owner); + uint64_t flags; + ASSERT_EQ(0, image1.get_flags(&flags)); + ASSERT_TRUE((flags & RBD_FLAG_OBJECT_MAP_INVALID) != 0); + librbd::Image image2; ASSERT_EQ(0, rbd.open(ioctx, image2, name.c_str(), NULL)); ASSERT_EQ(0, image2.is_exclusive_lock_owner(&lock_owner)); @@ -3406,6 +3406,12 @@ TEST_F(TestLibRBD, RebuildObjectMap) librbd::Image image1; ASSERT_EQ(0, rbd.open(ioctx, image1, name.c_str(), NULL)); + bool lock_owner; + bl.clear(); + ASSERT_EQ(0, image1.write(0, 0, bl)); + ASSERT_EQ(0, image1.is_exclusive_lock_owner(&lock_owner)); + ASSERT_TRUE(lock_owner); + uint64_t flags; ASSERT_EQ(0, image1.get_flags(&flags)); ASSERT_TRUE((flags & RBD_FLAG_OBJECT_MAP_INVALID) != 0); diff --git a/src/test/librbd/test_mock_ExclusiveLock.cc b/src/test/librbd/test_mock_ExclusiveLock.cc index 29ba0eccf46a..56b2701295c0 100644 --- a/src/test/librbd/test_mock_ExclusiveLock.cc +++ b/src/test/librbd/test_mock_ExclusiveLock.cc @@ -58,6 +58,7 @@ namespace librbd { using ::testing::_; using ::testing::Invoke; using ::testing::InSequence; +using ::testing::Return; class TestMockExclusiveLock : public TestMockFixture { public: @@ -65,6 +66,11 @@ public: typedef exclusive_lock::AcquireRequest MockAcquireRequest; typedef exclusive_lock::ReleaseRequest MockReleaseRequest; + void expect_get_watch_handle(MockImageCtx &mock_image_ctx) { + EXPECT_CALL(*mock_image_ctx.image_watcher, get_watch_handle()) + .WillRepeatedly(Return(1234567890)); + } + void expect_block_writes(MockImageCtx &mock_image_ctx) { EXPECT_CALL(*mock_image_ctx.aio_work_queue, block_writes(_)) .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue)); @@ -76,9 +82,11 @@ public: void expect_acquire_lock(MockImageCtx &mock_image_ctx, MockAcquireRequest &acquire_request, int r) { + expect_get_watch_handle(mock_image_ctx); EXPECT_CALL(acquire_request, send()) .WillOnce(FinishRequest(&acquire_request, r, &mock_image_ctx)); if (r == 0) { + expect_notify_acquired_lock(mock_image_ctx); expect_unblock_writes(mock_image_ctx); } } @@ -94,6 +102,10 @@ public: if (!shutting_down && r < 0) { expect_unblock_writes(mock_image_ctx); } + if (r == 0) { + expect_notify_released_lock(mock_image_ctx); + expect_writes_empty(mock_image_ctx); + } } void expect_notify_request_lock(MockImageCtx &mock_image_ctx, @@ -103,6 +115,21 @@ public: &MockExclusiveLock::handle_lock_released)); } + void expect_notify_acquired_lock(MockImageCtx &mock_image_ctx) { + EXPECT_CALL(*mock_image_ctx.image_watcher, notify_acquired_lock()) + .Times(1); + } + + void expect_notify_released_lock(MockImageCtx &mock_image_ctx) { + EXPECT_CALL(*mock_image_ctx.image_watcher, notify_released_lock()) + .Times(1); + } + + void expect_writes_empty(MockImageCtx &mock_image_ctx) { + EXPECT_CALL(*mock_image_ctx.aio_work_queue, writes_empty()) + .WillRepeatedly(Return(true)); + } + int when_init(MockImageCtx &mock_image_ctx, MockExclusiveLock &exclusive_lock) { C_SaferCond ctx; @@ -110,7 +137,6 @@ public: RWLock::WLocker owner_locker(mock_image_ctx.owner_lock); exclusive_lock.init(&ctx); } - exclusive_lock.set_watch_handle(123); return ctx.wait(); } @@ -127,7 +153,7 @@ public: MockExclusiveLock &exclusive_lock) { C_SaferCond ctx; { - RWLock::WLocker owner_locker(mock_image_ctx.owner_lock); + RWLock::RLocker owner_locker(mock_image_ctx.owner_lock); exclusive_lock.request_lock(&ctx); } return ctx.wait(); @@ -188,6 +214,7 @@ TEST_F(TestMockExclusiveLock, StateTransitions) { ASSERT_TRUE(is_lock_owner(mock_image_ctx, exclusive_lock)); MockReleaseRequest shutdown_release; + expect_op_work_queue(mock_image_ctx); expect_release_lock(mock_image_ctx, shutdown_release, 0, true); ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock)); ASSERT_FALSE(is_lock_owner(mock_image_ctx, exclusive_lock)); @@ -213,6 +240,7 @@ TEST_F(TestMockExclusiveLock, TryLockLockedState) { ASSERT_EQ(0, when_try_lock(mock_image_ctx, exclusive_lock)); MockReleaseRequest shutdown_release; + expect_op_work_queue(mock_image_ctx); expect_release_lock(mock_image_ctx, shutdown_release, 0, true); ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock)); } @@ -260,6 +288,7 @@ TEST_F(TestMockExclusiveLock, TryLockBusy) { ASSERT_FALSE(is_lock_owner(mock_image_ctx, exclusive_lock)); expect_unblock_writes(mock_image_ctx); + expect_op_work_queue(mock_image_ctx); ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock)); } @@ -284,6 +313,7 @@ TEST_F(TestMockExclusiveLock, TryLockError) { ASSERT_FALSE(is_lock_owner(mock_image_ctx, exclusive_lock)); expect_unblock_writes(mock_image_ctx); + expect_op_work_queue(mock_image_ctx); ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock)); } @@ -306,6 +336,7 @@ TEST_F(TestMockExclusiveLock, RequestLockLockedState) { ASSERT_EQ(0, when_try_lock(mock_image_ctx, exclusive_lock)); MockReleaseRequest shutdown_release; + expect_op_work_queue(mock_image_ctx); expect_release_lock(mock_image_ctx, shutdown_release, 0, true); ASSERT_EQ(0, when_request_lock(mock_image_ctx, exclusive_lock)); @@ -334,6 +365,7 @@ TEST_F(TestMockExclusiveLock, RequestLockBlacklist) { ASSERT_FALSE(is_lock_owner(mock_image_ctx, exclusive_lock)); expect_unblock_writes(mock_image_ctx); + expect_op_work_queue(mock_image_ctx); ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock)); } @@ -362,6 +394,7 @@ TEST_F(TestMockExclusiveLock, RequestLockBusy) { ASSERT_TRUE(is_lock_owner(mock_image_ctx, exclusive_lock)); MockReleaseRequest shutdown_release; + expect_op_work_queue(mock_image_ctx); expect_release_lock(mock_image_ctx, shutdown_release, 0, true); ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock)); } @@ -391,6 +424,7 @@ TEST_F(TestMockExclusiveLock, RequestLockError) { ASSERT_TRUE(is_lock_owner(mock_image_ctx, exclusive_lock)); MockReleaseRequest shutdown_release; + expect_op_work_queue(mock_image_ctx); expect_release_lock(mock_image_ctx, shutdown_release, 0, true); ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock)); } @@ -412,6 +446,7 @@ TEST_F(TestMockExclusiveLock, ReleaseLockUnlockedState) { ASSERT_EQ(0, when_release_lock(mock_image_ctx, exclusive_lock)); expect_unblock_writes(mock_image_ctx); + expect_op_work_queue(mock_image_ctx); ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock)); } @@ -440,6 +475,7 @@ TEST_F(TestMockExclusiveLock, ReleaseLockError) { ASSERT_TRUE(is_lock_owner(mock_image_ctx, exclusive_lock)); MockReleaseRequest shutdown_release; + expect_op_work_queue(mock_image_ctx); expect_release_lock(mock_image_ctx, shutdown_release, 0, true); ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock)); ASSERT_FALSE(is_lock_owner(mock_image_ctx, exclusive_lock)); @@ -461,6 +497,7 @@ TEST_F(TestMockExclusiveLock, ConcurrentRequests) { MockAcquireRequest try_lock_acquire; C_SaferCond wait_for_send_ctx1; + expect_get_watch_handle(mock_image_ctx); EXPECT_CALL(try_lock_acquire, send()) .WillOnce(Notify(&wait_for_send_ctx1)); @@ -472,6 +509,8 @@ TEST_F(TestMockExclusiveLock, ConcurrentRequests) { expect_block_writes(mock_image_ctx); EXPECT_CALL(release, send()) .WillOnce(Notify(&wait_for_send_ctx2)); + expect_notify_released_lock(mock_image_ctx); + expect_writes_empty(mock_image_ctx); C_SaferCond try_request_ctx1; { @@ -482,7 +521,7 @@ TEST_F(TestMockExclusiveLock, ConcurrentRequests) { C_SaferCond request_lock_ctx1; C_SaferCond request_lock_ctx2; { - RWLock::WLocker owner_locker(mock_image_ctx.owner_lock); + RWLock::RLocker owner_locker(mock_image_ctx.owner_lock); exclusive_lock.request_lock(&request_lock_ctx1); exclusive_lock.request_lock(&request_lock_ctx2); } @@ -495,7 +534,7 @@ TEST_F(TestMockExclusiveLock, ConcurrentRequests) { C_SaferCond request_lock_ctx3; { - RWLock::WLocker owner_locker(mock_image_ctx.owner_lock); + RWLock::RLocker owner_locker(mock_image_ctx.owner_lock); exclusive_lock.request_lock(&request_lock_ctx3); } @@ -515,6 +554,7 @@ TEST_F(TestMockExclusiveLock, ConcurrentRequests) { ASSERT_EQ(0, release_lock_ctx1.wait()); expect_unblock_writes(mock_image_ctx); + expect_op_work_queue(mock_image_ctx); ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock)); }