From 5769c6b449f14e582cfcf1cf80be4a301b67532f Mon Sep 17 00:00:00 2001 From: Ricardo Dias Date: Thu, 5 Jan 2017 11:23:56 +0000 Subject: [PATCH] librbd: Support for shared locking in ManagedLock Signed-off-by: Ricardo Dias --- src/librbd/ExclusiveLock.cc | 3 +- src/librbd/ManagedLock.cc | 10 +-- src/librbd/ManagedLock.h | 7 +- src/librbd/managed_lock/AcquireRequest.cc | 14 ++-- src/librbd/managed_lock/AcquireRequest.h | 5 +- src/librbd/managed_lock/GetLockerRequest.cc | 19 ++++-- src/librbd/managed_lock/GetLockerRequest.h | 7 +- src/librbd/managed_lock/ReacquireRequest.cc | 9 ++- src/librbd/managed_lock/ReacquireRequest.h | 8 ++- src/librbd/managed_lock/Types.h | 6 ++ .../managed_lock/test_mock_AcquireRequest.cc | 53 ++++++++++++--- .../test_mock_GetLockerRequest.cc | 65 ++++++++++++++++--- .../test_mock_ReacquireRequest.cc | 44 +++++++++++-- src/test/librbd/test_mock_ExclusiveLock.cc | 17 +++-- src/test/librbd/test_mock_ManagedLock.cc | 37 ++++++----- 15 files changed, 234 insertions(+), 70 deletions(-) diff --git a/src/librbd/ExclusiveLock.cc b/src/librbd/ExclusiveLock.cc index 2b1621ef60d3..7d8e19ba2962 100644 --- a/src/librbd/ExclusiveLock.cc +++ b/src/librbd/ExclusiveLock.cc @@ -26,7 +26,8 @@ using ML = ManagedLock; template ExclusiveLock::ExclusiveLock(I &image_ctx) : ML(image_ctx.md_ctx, image_ctx.op_work_queue, image_ctx.header_oid, - image_ctx.image_watcher, image_ctx.blacklist_on_break_lock, + image_ctx.image_watcher, managed_lock::EXCLUSIVE, + image_ctx.blacklist_on_break_lock, image_ctx.blacklist_expire_seconds), m_image_ctx(image_ctx), m_pre_post_callback(nullptr), m_shutting_down(false) { diff --git a/src/librbd/ManagedLock.cc b/src/librbd/ManagedLock.cc index 0a5074e28b05..18f33e184ab6 100644 --- a/src/librbd/ManagedLock.cc +++ b/src/librbd/ManagedLock.cc @@ -24,6 +24,7 @@ namespace librbd { using std::string; +using namespace managed_lock; namespace { @@ -46,7 +47,7 @@ const std::string ManagedLock::WATCHER_LOCK_TAG("internal"); template ManagedLock::ManagedLock(librados::IoCtx &ioctx, ContextWQ *work_queue, - const string& oid, Watcher *watcher, + const string& oid, Watcher *watcher, Mode mode, bool blacklist_on_break_lock, uint32_t blacklist_expire_seconds) : m_lock(util::unique_lock_name("librbd::ManagedLock::m_lock", this)), @@ -55,6 +56,7 @@ ManagedLock::ManagedLock(librados::IoCtx &ioctx, ContextWQ *work_queue, m_work_queue(work_queue), m_oid(oid), m_watcher(watcher), + m_mode(mode), m_blacklist_on_break_lock(blacklist_on_break_lock), m_blacklist_expire_seconds(blacklist_expire_seconds) { } @@ -199,7 +201,7 @@ void ManagedLock::get_locker(managed_lock::Locker *locker, ldout(m_cct, 10) << dendl; auto req = managed_lock::GetLockerRequest::create( - m_ioctx, m_oid, locker, on_finish); + m_ioctx, m_oid, m_mode == EXCLUSIVE, locker, on_finish); req->send(); } @@ -419,7 +421,7 @@ void ManagedLock::handle_pre_acquire_lock(int r) { using managed_lock::AcquireRequest; AcquireRequest* req = AcquireRequest::create( - m_ioctx, m_watcher, m_work_queue, m_oid, m_cookie, + m_ioctx, m_watcher, m_work_queue, m_oid, m_cookie, m_mode == EXCLUSIVE, m_blacklist_on_break_lock, m_blacklist_expire_seconds, util::create_context_callback< ManagedLock, &ManagedLock::handle_acquire_lock>(this)); @@ -507,7 +509,7 @@ void ManagedLock::send_reacquire_lock() { using managed_lock::ReacquireRequest; ReacquireRequest* req = ReacquireRequest::create(m_ioctx, m_oid, - m_cookie, m_new_cookie, + m_cookie, m_new_cookie, m_mode == EXCLUSIVE, util::create_context_callback< ManagedLock, &ManagedLock::handle_reacquire_lock>(this)); m_work_queue->queue(new C_SendLockRequest>(req)); diff --git a/src/librbd/ManagedLock.h b/src/librbd/ManagedLock.h index 0b4893926df5..45f06b4978e2 100644 --- a/src/librbd/ManagedLock.h +++ b/src/librbd/ManagedLock.h @@ -9,6 +9,7 @@ #include "include/rados/librados.hpp" #include "cls/lock/cls_lock_types.h" #include "librbd/watcher/Types.h" +#include "librbd/managed_lock/Types.h" #include "common/Mutex.h" #include #include @@ -33,15 +34,16 @@ public: static ManagedLock *create(librados::IoCtx& ioctx, ContextWQ *work_queue, const std::string& oid, Watcher *watcher, + managed_lock::Mode mode, bool blacklist_on_break_lock, uint32_t blacklist_expire_seconds) { - return new ManagedLock(ioctx, work_queue, oid, watcher, + return new ManagedLock(ioctx, work_queue, oid, watcher, mode, blacklist_on_break_lock, blacklist_expire_seconds); } ManagedLock(librados::IoCtx& ioctx, ContextWQ *work_queue, const std::string& oid, Watcher *watcher, - bool blacklist_on_break_lock, + managed_lock::Mode mode, bool blacklist_on_break_lock, uint32_t blacklist_expire_seconds); virtual ~ManagedLock(); @@ -161,6 +163,7 @@ private: ContextWQ *m_work_queue; std::string m_oid; Watcher *m_watcher; + managed_lock::Mode m_mode; bool m_blacklist_on_break_lock; uint32_t m_blacklist_expire_seconds; diff --git a/src/librbd/managed_lock/AcquireRequest.cc b/src/librbd/managed_lock/AcquireRequest.cc index 23b0f044ee03..d40b0c0dbfa5 100644 --- a/src/librbd/managed_lock/AcquireRequest.cc +++ b/src/librbd/managed_lock/AcquireRequest.cc @@ -38,24 +38,26 @@ AcquireRequest* AcquireRequest::create(librados::IoCtx& ioctx, ContextWQ *work_queue, const string& oid, const string& cookie, + bool exclusive, bool blacklist_on_break_lock, uint32_t blacklist_expire_seconds, Context *on_finish) { return new AcquireRequest(ioctx, watcher, work_queue, oid, cookie, - blacklist_on_break_lock, blacklist_expire_seconds, - on_finish); + exclusive, blacklist_on_break_lock, + blacklist_expire_seconds, on_finish); } template AcquireRequest::AcquireRequest(librados::IoCtx& ioctx, Watcher *watcher, ContextWQ *work_queue, const string& oid, - const string& cookie, + const string& cookie, bool exclusive, bool blacklist_on_break_lock, uint32_t blacklist_expire_seconds, Context *on_finish) : m_ioctx(ioctx), m_watcher(watcher), m_cct(reinterpret_cast(m_ioctx.cct())), m_work_queue(work_queue), m_oid(oid), m_cookie(cookie), + m_exclusive(exclusive), m_blacklist_on_break_lock(blacklist_on_break_lock), m_blacklist_expire_seconds(blacklist_expire_seconds), m_on_finish(new C_AsyncCallback(work_queue, on_finish)) { @@ -76,7 +78,8 @@ void AcquireRequest::send_get_locker() { Context *ctx = create_context_callback< AcquireRequest, &AcquireRequest::handle_get_locker>(this); - auto req = GetLockerRequest::create(m_ioctx, m_oid, &m_locker, ctx); + auto req = GetLockerRequest::create(m_ioctx, m_oid, m_exclusive, + &m_locker, ctx); req->send(); } @@ -105,7 +108,8 @@ void AcquireRequest::send_lock() { ldout(m_cct, 10) << dendl; librados::ObjectWriteOperation op; - rados::cls::lock::lock(&op, RBD_LOCK_NAME, LOCK_EXCLUSIVE, m_cookie, + rados::cls::lock::lock(&op, RBD_LOCK_NAME, + m_exclusive ? LOCK_EXCLUSIVE : LOCK_SHARED, m_cookie, ManagedLock::WATCHER_LOCK_TAG, "", utime_t(), 0); using klass = AcquireRequest; diff --git a/src/librbd/managed_lock/AcquireRequest.h b/src/librbd/managed_lock/AcquireRequest.h index fe31595df4a3..16a5be36c787 100644 --- a/src/librbd/managed_lock/AcquireRequest.h +++ b/src/librbd/managed_lock/AcquireRequest.h @@ -31,6 +31,7 @@ public: static AcquireRequest* create(librados::IoCtx& ioctx, Watcher *watcher, ContextWQ *work_queue, const std::string& oid, const std::string& cookie, + bool exclusive, bool blacklist_on_break_lock, uint32_t blacklist_expire_seconds, Context *on_finish); @@ -61,7 +62,8 @@ private: AcquireRequest(librados::IoCtx& ioctx, Watcher *watcher, ContextWQ *work_queue, const std::string& oid, - const std::string& cookie, bool blacklist_on_break_lock, + const std::string& cookie, bool exclusive, + bool blacklist_on_break_lock, uint32_t blacklist_expire_seconds, Context *on_finish); librados::IoCtx& m_ioctx; @@ -70,6 +72,7 @@ private: ContextWQ *m_work_queue; std::string m_oid; std::string m_cookie; + bool m_exclusive; bool m_blacklist_on_break_lock; uint32_t m_blacklist_expire_seconds; Context *m_on_finish; diff --git a/src/librbd/managed_lock/GetLockerRequest.cc b/src/librbd/managed_lock/GetLockerRequest.cc index 25b182743d15..9f93d305c04d 100644 --- a/src/librbd/managed_lock/GetLockerRequest.cc +++ b/src/librbd/managed_lock/GetLockerRequest.cc @@ -24,10 +24,11 @@ using util::create_rados_ack_callback; template GetLockerRequest::GetLockerRequest(librados::IoCtx& ioctx, - const std::string& oid, Locker *locker, - Context *on_finish) + const std::string& oid, bool exclusive, + Locker *locker, Context *on_finish) : m_ioctx(ioctx), m_cct(reinterpret_cast(m_ioctx.cct())), - m_oid(oid), m_locker(locker), m_on_finish(on_finish) { + m_oid(oid), m_exclusive(exclusive), m_locker(locker), + m_on_finish(on_finish) { } template @@ -61,8 +62,8 @@ void GetLockerRequest::handle_get_lockers(int r) { std::string lock_tag; if (r == 0) { bufferlist::iterator it = m_out_bl.begin(); - r = rados::cls::lock::get_lock_info_finish(&it, &lockers, - &lock_type, &lock_tag); + r = rados::cls::lock::get_lock_info_finish(&it, &lockers, &lock_type, + &lock_tag); } if (r < 0) { @@ -83,8 +84,12 @@ void GetLockerRequest::handle_get_lockers(int r) { return; } - if (lock_type == LOCK_SHARED) { - ldout(m_cct, 5) << "shared lock type detected" << dendl; + if (m_exclusive && lock_type == LOCK_SHARED) { + ldout(m_cct, 5) << "incompatible shared lock type detected" << dendl; + finish(-EBUSY); + return; + } else if (!m_exclusive && lock_type == LOCK_EXCLUSIVE) { + ldout(m_cct, 5) << "incompatible exclusive lock type detected" << dendl; finish(-EBUSY); return; } diff --git a/src/librbd/managed_lock/GetLockerRequest.h b/src/librbd/managed_lock/GetLockerRequest.h index 97373c5f6bbd..9a245d882059 100644 --- a/src/librbd/managed_lock/GetLockerRequest.h +++ b/src/librbd/managed_lock/GetLockerRequest.h @@ -23,9 +23,9 @@ template class GetLockerRequest { public: static GetLockerRequest* create(librados::IoCtx& ioctx, - const std::string& oid, + const std::string& oid, bool exclusive, Locker *locker, Context *on_finish) { - return new GetLockerRequest(ioctx, oid, locker, on_finish); + return new GetLockerRequest(ioctx, oid, exclusive, locker, on_finish); } void send(); @@ -34,13 +34,14 @@ private: librados::IoCtx &m_ioctx; CephContext *m_cct; std::string m_oid; + bool m_exclusive; Locker *m_locker; Context *m_on_finish; bufferlist m_out_bl; GetLockerRequest(librados::IoCtx& ioctx, const std::string& oid, - Locker *locker, Context *on_finish); + bool exclusive, Locker *locker, Context *on_finish); void send_get_lockers(); void handle_get_lockers(int r); diff --git a/src/librbd/managed_lock/ReacquireRequest.cc b/src/librbd/managed_lock/ReacquireRequest.cc index 33bd1db7136a..02c564d7ff4b 100644 --- a/src/librbd/managed_lock/ReacquireRequest.cc +++ b/src/librbd/managed_lock/ReacquireRequest.cc @@ -29,9 +29,10 @@ ReacquireRequest::ReacquireRequest(librados::IoCtx& ioctx, const string& oid, const string& old_cookie, const string &new_cookie, + bool exclusive, Context *on_finish) : m_ioctx(ioctx), m_oid(oid), m_old_cookie(old_cookie), - m_new_cookie(new_cookie), m_on_finish(on_finish) { + m_new_cookie(new_cookie), m_exclusive(exclusive), m_on_finish(on_finish) { } @@ -46,8 +47,10 @@ void ReacquireRequest::set_cookie() { ldout(cct, 10) << dendl; librados::ObjectWriteOperation op; - rados::cls::lock::set_cookie(&op, RBD_LOCK_NAME, LOCK_EXCLUSIVE, m_old_cookie, - ManagedLock::WATCHER_LOCK_TAG, m_new_cookie); + rados::cls::lock::set_cookie(&op, RBD_LOCK_NAME, + m_exclusive ? LOCK_EXCLUSIVE : LOCK_SHARED, + m_old_cookie, ManagedLock::WATCHER_LOCK_TAG, + m_new_cookie); librados::AioCompletion *rados_completion = create_rados_safe_callback< ReacquireRequest, &ReacquireRequest::handle_set_cookie>(this); diff --git a/src/librbd/managed_lock/ReacquireRequest.h b/src/librbd/managed_lock/ReacquireRequest.h index 60256c836de6..3f2b7d7e2110 100644 --- a/src/librbd/managed_lock/ReacquireRequest.h +++ b/src/librbd/managed_lock/ReacquireRequest.h @@ -24,13 +24,16 @@ public: const std::string& oid, const std::string& old_cookie, const std::string &new_cookie, + bool exclusive, Context *on_finish) { - return new ReacquireRequest(ioctx, oid, old_cookie, new_cookie, on_finish); + return new ReacquireRequest(ioctx, oid, old_cookie, new_cookie, exclusive, + on_finish); } ReacquireRequest(librados::IoCtx& ioctx, const std::string& oid, const std::string& old_cookie, - const std::string &new_cookie, Context *on_finish); + const std::string &new_cookie, bool exclusive, + Context *on_finish); void send(); @@ -52,6 +55,7 @@ private: std::string m_oid; std::string m_old_cookie; std::string m_new_cookie; + bool m_exclusive; Context *m_on_finish; void set_cookie(); diff --git a/src/librbd/managed_lock/Types.h b/src/librbd/managed_lock/Types.h index beb764ea5b52..01c31b6dfb72 100644 --- a/src/librbd/managed_lock/Types.h +++ b/src/librbd/managed_lock/Types.h @@ -17,6 +17,12 @@ struct Locker { uint64_t handle; }; +enum Mode { + EXCLUSIVE, + SHARED +}; + + } // namespace managed_lock } // namespace librbd diff --git a/src/test/librbd/managed_lock/test_mock_AcquireRequest.cc b/src/test/librbd/managed_lock/test_mock_AcquireRequest.cc index b99f202ffeb2..5ea9ada6a04b 100644 --- a/src/test/librbd/managed_lock/test_mock_AcquireRequest.cc +++ b/src/test/librbd/managed_lock/test_mock_AcquireRequest.cc @@ -56,7 +56,7 @@ struct GetLockerRequest { static GetLockerRequest *s_instance; static GetLockerRequest* create(librados::IoCtx& ioctx, - const std::string& oid, + const std::string& oid, bool exclusive, Locker *locker, Context *on_finish) { assert(s_instance != nullptr); s_instance->locker = locker; @@ -84,6 +84,19 @@ template class librbd::managed_lock::AcquireRequest; #include "librbd/ManagedLock.cc" template class librbd::ManagedLock; +namespace { + +MATCHER_P(IsLockType, exclusive, "") { + cls_lock_lock_op op; + bufferlist bl; + bl.share(arg); + bufferlist::iterator iter = bl.begin(); + ::decode(op, iter); + return op.type == (exclusive ? LOCK_EXCLUSIVE : LOCK_SHARED); +} + +} // anonymous namespace + namespace librbd { namespace managed_lock { @@ -105,9 +118,11 @@ public: typedef GetLockerRequest MockGetLockerRequest; typedef ManagedLock MockManagedLock; - void expect_lock(MockImageCtx &mock_image_ctx, int r) { + void expect_lock(MockImageCtx &mock_image_ctx, int r, + bool exclusive = true) { EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), - exec(mock_image_ctx.header_oid, _, StrEq("lock"), StrEq("lock"), _, _, _)) + exec(mock_image_ctx.header_oid, _, StrEq("lock"), + StrEq("lock"), IsLockType(exclusive), _, _)) .WillOnce(Return(r)); } @@ -129,7 +144,7 @@ public: } }; -TEST_F(TestMockManagedLockAcquireRequest, Success) { +TEST_F(TestMockManagedLockAcquireRequest, SuccessExclusive) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); @@ -144,7 +159,27 @@ TEST_F(TestMockManagedLockAcquireRequest, Success) { C_SaferCond ctx; MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx.md_ctx, mock_image_ctx.image_watcher, ictx->op_work_queue, mock_image_ctx.header_oid, - TEST_COOKIE, true, 0, &ctx); + TEST_COOKIE, true, true, 0, &ctx); + req->send(); + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockManagedLockAcquireRequest, SuccessShared) { + + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockImageCtx mock_image_ctx(*ictx); + MockGetLockerRequest mock_get_locker_request; + + InSequence seq; + expect_get_locker(mock_image_ctx, mock_get_locker_request, {}, 0); + expect_lock(mock_image_ctx, 0, false); + + C_SaferCond ctx; + MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx.md_ctx, + mock_image_ctx.image_watcher, ictx->op_work_queue, mock_image_ctx.header_oid, + TEST_COOKIE, false, true, 0, &ctx); req->send(); ASSERT_EQ(0, ctx.wait()); } @@ -170,7 +205,7 @@ TEST_F(TestMockManagedLockAcquireRequest, LockBusy) { C_SaferCond ctx; MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx.md_ctx, mock_image_ctx.image_watcher, ictx->op_work_queue, mock_image_ctx.header_oid, - TEST_COOKIE, true, 0, &ctx); + TEST_COOKIE, true, true, 0, &ctx); req->send(); ASSERT_EQ(-ENOENT, ctx.wait()); } @@ -188,7 +223,7 @@ TEST_F(TestMockManagedLockAcquireRequest, GetLockInfoError) { C_SaferCond ctx; MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx.md_ctx, mock_image_ctx.image_watcher, ictx->op_work_queue, mock_image_ctx.header_oid, - TEST_COOKIE, true, 0, &ctx); + TEST_COOKIE, true, true, 0, &ctx); req->send(); ASSERT_EQ(-EINVAL, ctx.wait()); } @@ -207,7 +242,7 @@ TEST_F(TestMockManagedLockAcquireRequest, GetLockInfoEmpty) { C_SaferCond ctx; MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx.md_ctx, mock_image_ctx.image_watcher, ictx->op_work_queue, mock_image_ctx.header_oid, - TEST_COOKIE, true, 0, &ctx); + TEST_COOKIE, true, true, 0, &ctx); req->send(); ASSERT_EQ(-EINVAL, ctx.wait()); } @@ -230,7 +265,7 @@ TEST_F(TestMockManagedLockAcquireRequest, BreakLockError) { C_SaferCond ctx; MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx.md_ctx, mock_image_ctx.image_watcher, ictx->op_work_queue, mock_image_ctx.header_oid, - TEST_COOKIE, true, 0, &ctx); + TEST_COOKIE, true, true, 0, &ctx); req->send(); ASSERT_EQ(-EINVAL, ctx.wait()); } diff --git a/src/test/librbd/managed_lock/test_mock_GetLockerRequest.cc b/src/test/librbd/managed_lock/test_mock_GetLockerRequest.cc index af3bb07a3696..e8b1ec76d3df 100644 --- a/src/test/librbd/managed_lock/test_mock_GetLockerRequest.cc +++ b/src/test/librbd/managed_lock/test_mock_GetLockerRequest.cc @@ -78,7 +78,7 @@ public: } }; -TEST_F(TestMockManagedLockGetLockerRequest, Success) { +TEST_F(TestMockManagedLockGetLockerRequest, SuccessExclusive) { REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK); librbd::ImageCtx *ictx; @@ -95,7 +95,34 @@ TEST_F(TestMockManagedLockGetLockerRequest, Success) { C_SaferCond ctx; Locker locker; MockGetLockerRequest *req = MockGetLockerRequest::create( - mock_image_ctx.md_ctx, mock_image_ctx.header_oid, &locker, &ctx); + mock_image_ctx.md_ctx, mock_image_ctx.header_oid, true, &locker, &ctx); + req->send(); + ASSERT_EQ(0, ctx.wait()); + + ASSERT_EQ(entity_name_t::CLIENT(1), locker.entity); + ASSERT_EQ("1.2.3.4:0/0", locker.address); + ASSERT_EQ("auto 123", locker.cookie); + ASSERT_EQ(123U, locker.handle); +} + +TEST_F(TestMockManagedLockGetLockerRequest, SuccessShared) { + 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_get_lock_info(mock_image_ctx, 0, entity_name_t::CLIENT(1), "1.2.3.4", + "auto 123", ManagedLock<>::WATCHER_LOCK_TAG, + LOCK_SHARED); + + C_SaferCond ctx; + Locker locker; + MockGetLockerRequest *req = MockGetLockerRequest::create( + mock_image_ctx.md_ctx, mock_image_ctx.header_oid, false, &locker, &ctx); req->send(); ASSERT_EQ(0, ctx.wait()); @@ -121,7 +148,7 @@ TEST_F(TestMockManagedLockGetLockerRequest, GetLockInfoError) { C_SaferCond ctx; Locker locker; MockGetLockerRequest *req = MockGetLockerRequest::create( - mock_image_ctx.md_ctx, mock_image_ctx.header_oid, &locker, &ctx); + mock_image_ctx.md_ctx, mock_image_ctx.header_oid, true, &locker, &ctx); req->send(); ASSERT_EQ(-EINVAL, ctx.wait()); } @@ -142,7 +169,7 @@ TEST_F(TestMockManagedLockGetLockerRequest, GetLockInfoEmpty) { C_SaferCond ctx; Locker locker; MockGetLockerRequest *req = MockGetLockerRequest::create( - mock_image_ctx.md_ctx, mock_image_ctx.header_oid, &locker, &ctx); + mock_image_ctx.md_ctx, mock_image_ctx.header_oid, true, &locker, &ctx); req->send(); ASSERT_EQ(-ENOENT, ctx.wait()); } @@ -163,12 +190,12 @@ TEST_F(TestMockManagedLockGetLockerRequest, GetLockInfoExternalTag) { C_SaferCond ctx; Locker locker; MockGetLockerRequest *req = MockGetLockerRequest::create( - mock_image_ctx.md_ctx, mock_image_ctx.header_oid, &locker, &ctx); + mock_image_ctx.md_ctx, mock_image_ctx.header_oid, true, &locker, &ctx); req->send(); ASSERT_EQ(-EBUSY, ctx.wait()); } -TEST_F(TestMockManagedLockGetLockerRequest, GetLockInfoShared) { +TEST_F(TestMockManagedLockGetLockerRequest, GetLockInfoIncompatibleShared) { REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK); librbd::ImageCtx *ictx; @@ -185,7 +212,29 @@ TEST_F(TestMockManagedLockGetLockerRequest, GetLockInfoShared) { C_SaferCond ctx; Locker locker; MockGetLockerRequest *req = MockGetLockerRequest::create( - mock_image_ctx.md_ctx, mock_image_ctx.header_oid, &locker, &ctx); + mock_image_ctx.md_ctx, mock_image_ctx.header_oid, true, &locker, &ctx); + req->send(); + ASSERT_EQ(-EBUSY, ctx.wait()); +} + +TEST_F(TestMockManagedLockGetLockerRequest, GetLockInfoIncompatibleExclusive) { + 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_get_lock_info(mock_image_ctx, 0, entity_name_t::CLIENT(1), "1.2.3.4", + "auto 123", ManagedLock<>::WATCHER_LOCK_TAG, + LOCK_EXCLUSIVE); + + C_SaferCond ctx; + Locker locker; + MockGetLockerRequest *req = MockGetLockerRequest::create( + mock_image_ctx.md_ctx, mock_image_ctx.header_oid, false, &locker, &ctx); req->send(); ASSERT_EQ(-EBUSY, ctx.wait()); } @@ -207,7 +256,7 @@ TEST_F(TestMockManagedLockGetLockerRequest, GetLockInfoExternalCookie) { C_SaferCond ctx; Locker locker; MockGetLockerRequest *req = MockGetLockerRequest::create( - mock_image_ctx.md_ctx, mock_image_ctx.header_oid, &locker, &ctx); + mock_image_ctx.md_ctx, mock_image_ctx.header_oid, true, &locker, &ctx); req->send(); ASSERT_EQ(-EBUSY, ctx.wait()); } diff --git a/src/test/librbd/managed_lock/test_mock_ReacquireRequest.cc b/src/test/librbd/managed_lock/test_mock_ReacquireRequest.cc index 634b35385366..103078d25268 100644 --- a/src/test/librbd/managed_lock/test_mock_ReacquireRequest.cc +++ b/src/test/librbd/managed_lock/test_mock_ReacquireRequest.cc @@ -19,6 +19,19 @@ template class librbd::managed_lock::ReacquireRequest; #include "librbd/ManagedLock.cc" template class librbd::ManagedLock; +namespace { + +MATCHER_P(IsLockType, exclusive, "") { + cls_lock_set_cookie_op op; + bufferlist bl; + bl.share(arg); + bufferlist::iterator iter = bl.begin(); + ::decode(op, iter); + return op.type == (exclusive ? LOCK_EXCLUSIVE : LOCK_SHARED); +} + +} // anonymous namespace + namespace librbd { namespace managed_lock { @@ -27,20 +40,22 @@ using ::testing::InSequence; using ::testing::Return; using ::testing::StrEq; + class TestMockManagedLockReacquireRequest : public TestMockFixture { public: typedef ReacquireRequest MockReacquireRequest; typedef ManagedLock MockManagedLock; - void expect_set_cookie(MockImageCtx &mock_image_ctx, int r) { + void expect_set_cookie(MockImageCtx &mock_image_ctx, int r, + bool exclusive = true) { EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), exec(mock_image_ctx.header_oid, _, StrEq("lock"), - StrEq("set_cookie"), _, _, _)) + StrEq("set_cookie"), IsLockType(exclusive), _, _)) .WillOnce(Return(r)); } }; -TEST_F(TestMockManagedLockReacquireRequest, Success) { +TEST_F(TestMockManagedLockReacquireRequest, SuccessExclusive) { librbd::ImageCtx *ictx; ASSERT_EQ(0, open_image(m_image_name, &ictx)); @@ -52,7 +67,24 @@ TEST_F(TestMockManagedLockReacquireRequest, Success) { C_SaferCond ctx; MockReacquireRequest *req = MockReacquireRequest::create( mock_image_ctx.md_ctx, mock_image_ctx.header_oid, "old_cookie", - "new_cookie", &ctx); + "new_cookie", true, &ctx); + req->send(); + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockManagedLockReacquireRequest, SuccessShared) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockImageCtx mock_image_ctx(*ictx); + + InSequence seq; + expect_set_cookie(mock_image_ctx, 0, false); + + C_SaferCond ctx; + MockReacquireRequest *req = MockReacquireRequest::create( + mock_image_ctx.md_ctx, mock_image_ctx.header_oid, "old_cookie", + "new_cookie", false, &ctx); req->send(); ASSERT_EQ(0, ctx.wait()); } @@ -69,7 +101,7 @@ TEST_F(TestMockManagedLockReacquireRequest, NotSupported) { C_SaferCond ctx; MockReacquireRequest *req = MockReacquireRequest::create( mock_image_ctx.md_ctx, mock_image_ctx.header_oid, "old_cookie", - "new_cookie", &ctx); + "new_cookie", true, &ctx); req->send(); ASSERT_EQ(-EOPNOTSUPP, ctx.wait()); } @@ -86,7 +118,7 @@ TEST_F(TestMockManagedLockReacquireRequest, Error) { C_SaferCond ctx; MockReacquireRequest *req = MockReacquireRequest::create( mock_image_ctx.md_ctx, mock_image_ctx.header_oid, "old_cookie", - "new_cookie", &ctx); + "new_cookie", true, &ctx); req->send(); ASSERT_EQ(-EBUSY, ctx.wait()); } diff --git a/src/test/librbd/test_mock_ExclusiveLock.cc b/src/test/librbd/test_mock_ExclusiveLock.cc index 525d95b94f05..85b5570f95f2 100644 --- a/src/test/librbd/test_mock_ExclusiveLock.cc +++ b/src/test/librbd/test_mock_ExclusiveLock.cc @@ -117,11 +117,12 @@ struct AcquireRequest : public BaseRequest struct ReacquireRequest : public BaseRequest > { static ReacquireRequest* create(librados::IoCtx &ioctx, const std::string& oid, const string& old_cookie, const std::string& new_cookie, - Context *on_finish) { - return BaseRequest::create(ioctx, nullptr, nullptr, oid, new_cookie, on_finish); + bool exclusive, Context *on_finish) { + return BaseRequest::create(ioctx, nullptr, nullptr, oid, new_cookie, + on_finish); } MOCK_METHOD0(send, void()); @@ -139,6 +141,13 @@ struct ReacquireRequest : public BaseRequest struct ReleaseRequest : public BaseRequest > { + static ReleaseRequest* create(librados::IoCtx& ioctx, MockImageWatcher *watcher, + ContextWQ *work_queue, const std::string& oid, + const std::string& cookie, Context *on_finish) { + return BaseRequest::create(ioctx, watcher, work_queue, oid, cookie, + on_finish); + } + MOCK_METHOD0(send, void()); }; diff --git a/src/test/librbd/test_mock_ManagedLock.cc b/src/test/librbd/test_mock_ManagedLock.cc index f546003b9cde..7e79aa241251 100644 --- a/src/test/librbd/test_mock_ManagedLock.cc +++ b/src/test/librbd/test_mock_ManagedLock.cc @@ -57,7 +57,7 @@ struct AcquireRequest : public BaseRequest struct ReacquireRequest : public BaseRequest > { static ReacquireRequest* create(librados::IoCtx &ioctx, const std::string& oid, const string& old_cookie, const std::string& new_cookie, - Context *on_finish) { - return BaseRequest::create(ioctx, nullptr, nullptr, oid, new_cookie, on_finish); + bool exclusive, Context *on_finish) { + return BaseRequest::create(ioctx, nullptr, nullptr, oid, new_cookie, + on_finish); } MOCK_METHOD0(send, void()); @@ -79,13 +80,19 @@ struct ReacquireRequest : public BaseRequest struct ReleaseRequest : public BaseRequest > { + static ReleaseRequest* create(librados::IoCtx& ioctx, MockImageWatcher *watcher, + ContextWQ *work_queue, const std::string& oid, + const std::string& cookie, Context *on_finish) { + return BaseRequest::create(ioctx, watcher, work_queue, oid, cookie, + on_finish); + } MOCK_METHOD0(send, void()); }; template <> struct GetLockerRequest { static GetLockerRequest* create(librados::IoCtx& ioctx, - const std::string& oid, + const std::string& oid, bool exclusive, Locker *locker, Context *on_finish) { assert(0 == "unexpected call"); } @@ -215,7 +222,7 @@ TEST_F(TestMockManagedLock, StateTransitions) { MockManagedLockImageCtx mock_image_ctx(*ictx); MockManagedLock managed_lock(ictx->md_ctx, ictx->op_work_queue, ictx->header_oid, mock_image_ctx.image_watcher, - true, 0); + librbd::managed_lock::EXCLUSIVE, true, 0); InSequence seq; MockAcquireRequest request_lock_acquire1; @@ -246,7 +253,7 @@ TEST_F(TestMockManagedLock, AcquireLockLockedState) { MockManagedLockImageCtx mock_image_ctx(*ictx); MockManagedLock managed_lock(ictx->md_ctx, ictx->op_work_queue, ictx->header_oid, mock_image_ctx.image_watcher, - true, 0); + librbd::managed_lock::EXCLUSIVE, true, 0); InSequence seq; MockAcquireRequest try_lock_acquire; @@ -266,7 +273,7 @@ TEST_F(TestMockManagedLock, AcquireLockAlreadyLocked) { MockManagedLockImageCtx mock_image_ctx(*ictx); MockManagedLock managed_lock(ictx->md_ctx, ictx->op_work_queue, ictx->header_oid, mock_image_ctx.image_watcher, - true, 0); + librbd::managed_lock::EXCLUSIVE, true, 0); InSequence seq; MockAcquireRequest try_lock_acquire; @@ -284,7 +291,7 @@ TEST_F(TestMockManagedLock, AcquireLockBusy) { MockManagedLockImageCtx mock_image_ctx(*ictx); MockManagedLock managed_lock(ictx->md_ctx, ictx->op_work_queue, ictx->header_oid, mock_image_ctx.image_watcher, - true, 0); + librbd::managed_lock::EXCLUSIVE, true, 0); InSequence seq; MockAcquireRequest try_lock_acquire; @@ -302,7 +309,7 @@ TEST_F(TestMockManagedLock, AcquireLockError) { MockManagedLockImageCtx mock_image_ctx(*ictx); MockManagedLock managed_lock(ictx->md_ctx, ictx->op_work_queue, ictx->header_oid, mock_image_ctx.image_watcher, - true, 0); + librbd::managed_lock::EXCLUSIVE, true, 0); InSequence seq; MockAcquireRequest try_lock_acquire; @@ -321,7 +328,7 @@ TEST_F(TestMockManagedLock, AcquireLockBlacklist) { MockManagedLockImageCtx mock_image_ctx(*ictx); MockManagedLock managed_lock(ictx->md_ctx, ictx->op_work_queue, ictx->header_oid, mock_image_ctx.image_watcher, - true, 0); + librbd::managed_lock::EXCLUSIVE, true, 0); InSequence seq; // will abort after seeing blacklist error (avoid infinite request loop) @@ -340,7 +347,7 @@ TEST_F(TestMockManagedLock, ReleaseLockUnlockedState) { MockManagedLockImageCtx mock_image_ctx(*ictx); MockManagedLock managed_lock(ictx->md_ctx, ictx->op_work_queue, ictx->header_oid, mock_image_ctx.image_watcher, - true, 0); + librbd::managed_lock::EXCLUSIVE, true, 0); InSequence seq; ASSERT_EQ(0, when_release_lock(managed_lock)); @@ -355,7 +362,7 @@ TEST_F(TestMockManagedLock, ReleaseLockError) { MockManagedLockImageCtx mock_image_ctx(*ictx); MockManagedLock managed_lock(ictx->md_ctx, ictx->op_work_queue, ictx->header_oid, mock_image_ctx.image_watcher, - true, 0); + librbd::managed_lock::EXCLUSIVE, true, 0); InSequence seq; MockAcquireRequest try_lock_acquire; @@ -381,7 +388,7 @@ TEST_F(TestMockManagedLock, ConcurrentRequests) { MockManagedLockImageCtx mock_image_ctx(*ictx); MockManagedLock managed_lock(ictx->md_ctx, ictx->op_work_queue, ictx->header_oid, mock_image_ctx.image_watcher, - true, 0); + librbd::managed_lock::EXCLUSIVE, true, 0); InSequence seq; expect_get_watch_handle(*mock_image_ctx.image_watcher); @@ -438,7 +445,7 @@ TEST_F(TestMockManagedLock, ReacquireLock) { MockManagedLockImageCtx mock_image_ctx(*ictx); MockManagedLock managed_lock(ictx->md_ctx, ictx->op_work_queue, ictx->header_oid, mock_image_ctx.image_watcher, - true, 0); + librbd::managed_lock::EXCLUSIVE, true, 0); InSequence seq; MockAcquireRequest request_lock_acquire; @@ -465,7 +472,7 @@ TEST_F(TestMockManagedLock, ReacquireLockError) { MockManagedLockImageCtx mock_image_ctx(*ictx); MockManagedLock managed_lock(ictx->md_ctx, ictx->op_work_queue, ictx->header_oid, mock_image_ctx.image_watcher, - true, 0); + librbd::managed_lock::EXCLUSIVE, true, 0); InSequence seq; MockAcquireRequest request_lock_acquire; -- 2.47.3