From: Jason Dillaman Date: Tue, 16 Aug 2016 16:28:09 +0000 (-0400) Subject: librbd: helper state machine to update lock cookie X-Git-Tag: v11.0.1~392^2~7 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=d523df8dafac472f95233805d3a82edb3b3b02ea;p=ceph.git librbd: helper state machine to update lock cookie Signed-off-by: Jason Dillaman --- diff --git a/src/librbd/CMakeLists.txt b/src/librbd/CMakeLists.txt index 974dcac94b71..1630c4695bef 100644 --- a/src/librbd/CMakeLists.txt +++ b/src/librbd/CMakeLists.txt @@ -27,6 +27,7 @@ set(librbd_internal_srcs Operations.cc Utils.cc exclusive_lock/AcquireRequest.cc + exclusive_lock/ReacquireRequest.cc exclusive_lock/ReleaseRequest.cc exclusive_lock/StandardPolicy.cc image/CloseRequest.cc diff --git a/src/librbd/Makefile.am b/src/librbd/Makefile.am index 57585b7c24cc..9204d4faf160 100644 --- a/src/librbd/Makefile.am +++ b/src/librbd/Makefile.am @@ -32,6 +32,7 @@ librbd_internal_la_SOURCES = \ librbd/Operations.cc \ librbd/Utils.cc \ librbd/exclusive_lock/AcquireRequest.cc \ + librbd/exclusive_lock/ReacquireRequest.cc \ librbd/exclusive_lock/ReleaseRequest.cc \ librbd/exclusive_lock/StandardPolicy.cc \ librbd/image/CloseRequest.cc \ @@ -123,6 +124,7 @@ noinst_HEADERS += \ librbd/WatchNotifyTypes.h \ librbd/exclusive_lock/AcquireRequest.h \ librbd/exclusive_lock/Policy.h \ + librbd/exclusive_lock/ReacquireRequest.h \ librbd/exclusive_lock/ReleaseRequest.h \ librbd/exclusive_lock/StandardPolicy.h \ librbd/image/CloseRequest.h \ diff --git a/src/librbd/exclusive_lock/ReacquireRequest.cc b/src/librbd/exclusive_lock/ReacquireRequest.cc new file mode 100644 index 000000000000..e847f65bf877 --- /dev/null +++ b/src/librbd/exclusive_lock/ReacquireRequest.cc @@ -0,0 +1,72 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "librbd/exclusive_lock/ReacquireRequest.h" +#include "cls/lock/cls_lock_client.h" +#include "cls/lock/cls_lock_types.h" +#include "common/dout.h" +#include "common/errno.h" +#include "librbd/ExclusiveLock.h" +#include "librbd/ImageCtx.h" +#include "librbd/Utils.h" + +#define dout_subsys ceph_subsys_rbd +#undef dout_prefix +#define dout_prefix *_dout << "librbd::exclusive_lock::ReacquireRequest: " \ + << this << ": " << __func__ + +namespace librbd { +namespace exclusive_lock { + +using librbd::util::create_rados_safe_callback; + +template +ReacquireRequest::ReacquireRequest(I &image_ctx, + const std::string &old_cookie, + const std::string &new_cookie, + Context *on_finish) + : m_image_ctx(image_ctx), m_old_cookie(old_cookie), m_new_cookie(new_cookie), + m_on_finish(on_finish) { +} + +template +void ReacquireRequest::send() { + set_cookie(); +} + +template +void ReacquireRequest::set_cookie() { + CephContext *cct = m_image_ctx.cct; + ldout(cct, 10) << dendl; + + librados::ObjectWriteOperation op; + rados::cls::lock::set_cookie(&op, RBD_LOCK_NAME, LOCK_EXCLUSIVE, m_old_cookie, + ExclusiveLock<>::WATCHER_LOCK_TAG, m_new_cookie); + + librados::AioCompletion *rados_completion = create_rados_safe_callback< + ReacquireRequest, &ReacquireRequest::handle_set_cookie>(this); + int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid, + rados_completion, &op); + assert(r == 0); + rados_completion->release(); +} + +template +void ReacquireRequest::handle_set_cookie(int r) { + CephContext *cct = m_image_ctx.cct; + ldout(cct, 10) << ": r=" << r << dendl; + + if (r == -EOPNOTSUPP) { + ldout(cct, 10) << ": OSD doesn't support updating lock" << dendl; + } else if (r < 0) { + lderr(cct) << ": failed to update lock: " << cpp_strerror(r) << dendl; + } + + m_on_finish->complete(r); + delete this; +} + +} // namespace exclusive_lock +} // namespace librbd + +template class librbd::exclusive_lock::ReacquireRequest; diff --git a/src/librbd/exclusive_lock/ReacquireRequest.h b/src/librbd/exclusive_lock/ReacquireRequest.h new file mode 100644 index 000000000000..2718befa45bf --- /dev/null +++ b/src/librbd/exclusive_lock/ReacquireRequest.h @@ -0,0 +1,63 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_LIBRBD_EXCLUSIVE_LOCK_REACQUIRE_REQUEST_H +#define CEPH_LIBRBD_EXCLUSIVE_LOCK_REACQUIRE_REQUEST_H + +#include "include/int_types.h" +#include + +class Context; + +namespace librbd { + +class ImageCtx; + +namespace exclusive_lock { + +template +class ReacquireRequest { +public: + + static ReacquireRequest *create(ImageCtxT &image_ctx, + const std::string &old_cookie, + const std::string &new_cookie, + Context *on_finish) { + return new ReacquireRequest(image_ctx, old_cookie, new_cookie, on_finish); + } + + ReacquireRequest(ImageCtxT &image_ctx, const std::string &old_cookie, + const std::string &new_cookie, Context *on_finish); + + void send(); + +private: + /** + * @verbatim + * + * + * | + * v + * SET_COOKIE + * | + * v + * + * + * @endverbatim + */ + ImageCtxT &m_image_ctx; + std::string m_old_cookie; + std::string m_new_cookie; + Context *m_on_finish; + + void set_cookie(); + void handle_set_cookie(int r); + +}; + +} // namespace exclusive_lock +} // namespace librbd + +extern template class librbd::exclusive_lock::ReacquireRequest; + +#endif // CEPH_LIBRBD_EXCLUSIVE_LOCK_REACQUIRE_REQUEST_H diff --git a/src/test/Makefile-client.am b/src/test/Makefile-client.am index d3b9613544b4..28361dfbcd2d 100644 --- a/src/test/Makefile-client.am +++ b/src/test/Makefile-client.am @@ -390,6 +390,7 @@ unittest_librbd_SOURCES = \ test/librbd/test_mock_Journal.cc \ test/librbd/test_mock_ObjectWatcher.cc \ test/librbd/exclusive_lock/test_mock_AcquireRequest.cc \ + test/librbd/exclusive_lock/test_mock_ReacquireRequest.cc \ test/librbd/exclusive_lock/test_mock_ReleaseRequest.cc \ test/librbd/image/test_mock_RefreshRequest.cc \ test/librbd/journal/test_mock_Replay.cc \ diff --git a/src/test/librbd/CMakeLists.txt b/src/test/librbd/CMakeLists.txt index a85c2b16eda4..6c01358444ae 100644 --- a/src/test/librbd/CMakeLists.txt +++ b/src/test/librbd/CMakeLists.txt @@ -30,6 +30,7 @@ set(unittest_librbd_srcs test_mock_Journal.cc test_mock_ObjectWatcher.cc exclusive_lock/test_mock_AcquireRequest.cc + exclusive_lock/test_mock_ReacquireRequest.cc exclusive_lock/test_mock_ReleaseRequest.cc image/test_mock_RefreshRequest.cc journal/test_mock_Replay.cc diff --git a/src/test/librbd/exclusive_lock/test_mock_ReacquireRequest.cc b/src/test/librbd/exclusive_lock/test_mock_ReacquireRequest.cc new file mode 100644 index 000000000000..cd0da24ab609 --- /dev/null +++ b/src/test/librbd/exclusive_lock/test_mock_ReacquireRequest.cc @@ -0,0 +1,112 @@ +// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "test/librbd/test_mock_fixture.h" +#include "test/librbd/test_support.h" +#include "test/librbd/mock/MockImageCtx.h" +#include "test/librbd/mock/MockImageState.h" +#include "test/librados_test_stub/MockTestMemIoCtxImpl.h" +#include "test/librados_test_stub/MockTestMemRadosClient.h" +#include "cls/lock/cls_lock_ops.h" +#include "librbd/ExclusiveLock.h" +#include "librbd/exclusive_lock/ReacquireRequest.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include +#include + +namespace librbd { +namespace { + +struct MockTestImageCtx : public librbd::MockImageCtx { + MockTestImageCtx(librbd::ImageCtx &image_ctx) + : librbd::MockImageCtx(image_ctx) { + } +}; + +} // anonymous namespace +} // namespace librbd + +// template definitions +#include "librbd/exclusive_lock/ReacquireRequest.cc" + +namespace librbd { +namespace exclusive_lock { + +using ::testing::_; +using ::testing::InSequence; +using ::testing::Return; +using ::testing::StrEq; + +class TestMockExclusiveLockReacquireRequest : public TestMockFixture { +public: + typedef ReacquireRequest MockReacquireRequest; + typedef ExclusiveLock MockExclusiveLock; + + void expect_set_cookie(MockTestImageCtx &mock_image_ctx, int r) { + EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), + exec(mock_image_ctx.header_oid, _, StrEq("lock"), + StrEq("set_cookie"), _, _, _)) + .WillOnce(Return(r)); + } +}; + +TEST_F(TestMockExclusiveLockReacquireRequest, Success) { + REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK); + + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + + InSequence seq; + expect_set_cookie(mock_image_ctx, 0); + + C_SaferCond ctx; + MockReacquireRequest *req = MockReacquireRequest::create(mock_image_ctx, + "old cookie", + "new cookie", &ctx); + req->send(); + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockExclusiveLockReacquireRequest, NotSupported) { + REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK); + + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + + InSequence seq; + expect_set_cookie(mock_image_ctx, -EOPNOTSUPP); + + C_SaferCond ctx; + MockReacquireRequest *req = MockReacquireRequest::create(mock_image_ctx, + "old cookie", + "new cookie", &ctx); + req->send(); + ASSERT_EQ(-EOPNOTSUPP, ctx.wait()); +} + +TEST_F(TestMockExclusiveLockReacquireRequest, Error) { + REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK); + + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + + InSequence seq; + expect_set_cookie(mock_image_ctx, -EBUSY); + + C_SaferCond ctx; + MockReacquireRequest *req = MockReacquireRequest::create(mock_image_ctx, + "old cookie", + "new cookie", &ctx); + req->send(); + ASSERT_EQ(-EBUSY, ctx.wait()); +} + +} // namespace exclusive_lock +} // namespace librbd