]> 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>
Tue, 23 Aug 2016 16:23:07 +0000 (12:23 -0400)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
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 974dcac94b715a5d3447fe5339bb1b3747eeaf3b..1630c4695befa2efeddbb3b54907fb1d4e602260 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 57585b7c24cc5edf449fc642d7b907981ebd49e6..9204d4faf1608c36e6a757078bf662248a8471a2 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 \
@@ -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 (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 d3b9613544b4842702fdbafee830839c06bb8a8f..28361dfbcd2d490fe4e516d1ce5e6ed064e2ceff 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 a85c2b16eda499db91991430b20eb00b8467924d..6c01358444ae27b19b7f1df9a08b102efe618099 100644 (file)
@@ -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 (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