]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: helper state machine to update lock cookie
authorJason Dillaman <dillaman@redhat.com>
Tue, 16 Aug 2016 16:28:09 +0000 (12:28 -0400)
committerJason Dillaman <dillaman@redhat.com>
Mon, 30 Jan 2017 14:20:36 +0000 (09:20 -0500)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
(cherry picked from commit d523df8dafac472f95233805d3a82edb3b3b02ea)

src/librbd/CMakeLists.txt
src/librbd/Makefile.am
src/librbd/exclusive_lock/ReacquireRequest.cc [new file with mode: 0644]
src/librbd/exclusive_lock/ReacquireRequest.h [new file with mode: 0644]
src/test/Makefile-client.am
src/test/librbd/CMakeLists.txt
src/test/librbd/exclusive_lock/test_mock_ReacquireRequest.cc [new file with mode: 0644]

index 8254a2e8126e03f9d55f4d9a446badc55c11031c..8a09ae038bd94b59b38b64f54ce69026be0e5f03 100644 (file)
@@ -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
index 8cc8fe47dfc88ecff6b0414be54bc0392761eb37..b9030e191a853f22c6aae5e5c0fee599dc851b28 100644 (file)
@@ -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 \
@@ -119,6 +120,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 (file)
index 0000000..e847f65
--- /dev/null
@@ -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 <typename I>
+ReacquireRequest<I>::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 <typename I>
+void ReacquireRequest<I>::send() {
+  set_cookie();
+}
+
+template <typename I>
+void ReacquireRequest<I>::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<I>, &ReacquireRequest<I>::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 <typename I>
+void ReacquireRequest<I>::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<librbd::ImageCtx>;
diff --git a/src/librbd/exclusive_lock/ReacquireRequest.h b/src/librbd/exclusive_lock/ReacquireRequest.h
new file mode 100644 (file)
index 0000000..2718bef
--- /dev/null
@@ -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 <string>
+
+class Context;
+
+namespace librbd {
+
+class ImageCtx;
+
+namespace exclusive_lock {
+
+template <typename ImageCtxT = ImageCtx>
+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
+   *
+   * <start>
+   *    |
+   *    v
+   * SET_COOKIE
+   *    |
+   *    v
+   * <finish>
+   *
+   * @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<librbd::ImageCtx>;
+
+#endif // CEPH_LIBRBD_EXCLUSIVE_LOCK_REACQUIRE_REQUEST_H
index bf20a35b5f5f85926778cbcd2521ce0a53c19bec..28a365c9fbd0f2dde70a701700a48a561ec4bb78 100644 (file)
@@ -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 \
index 06d091092b888b6d3a85256ba0aac385f59610f3..4e0f92b9581f19bd809129733d4e0d1c4ac83e59 100644 (file)
@@ -24,6 +24,7 @@ set(unittest_librbd_srcs
   test_mock_ObjectMap.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 (file)
index 0000000..cd0da24
--- /dev/null
@@ -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 <arpa/inet.h>
+#include <list>
+
+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<MockTestImageCtx> MockReacquireRequest;
+  typedef ExclusiveLock<MockTestImageCtx> 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