]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: assume lock is unlocked if blacklisted or object deleted
authorJason Dillaman <dillaman@redhat.com>
Thu, 30 Aug 2018 19:12:27 +0000 (15:12 -0400)
committerJason Dillaman <dillaman@redhat.com>
Wed, 3 Oct 2018 15:08:20 +0000 (11:08 -0400)
This will ensure that it's possible to potentially re-acquire the
lock should the blacklist expire before the image is closed.

Fixes: http://tracker.ceph.com/issues/34534
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
(cherry picked from commit 60064f68f5dd2bbf5fbab95564fa522335091f4a)

src/librbd/ManagedLock.cc
src/test/librbd/test_mock_ManagedLock.cc

index 6900427ccf40314f1f69547d97c6ac4660948fc8..86b63c062c364a8e1d23dc7c6ee1f1b5fdf3cb84 100644 (file)
@@ -696,12 +696,13 @@ void ManagedLock<I>::handle_release_lock(int r) {
   Mutex::Locker locker(m_lock);
   assert(m_state == STATE_RELEASING);
 
-  if (r >= 0) {
+  if (r >= 0 || r == -EBLACKLISTED || r == -ENOENT) {
     m_cookie = "";
+    m_post_next_state = STATE_UNLOCKED;
+  } else {
+    m_post_next_state = STATE_LOCKED;
   }
 
-  m_post_next_state = r < 0 ? STATE_LOCKED : STATE_UNLOCKED;
-
   m_work_queue->queue(new FunctionContext([this, r](int ret) {
     post_release_lock_handler(false, r, create_context_callback<
         ManagedLock<I>, &ManagedLock<I>::handle_post_release_lock>(this));
index f93961afbd5d1f01d0980f7284b42c2ab82cd3ea..8668485acc273210cf5d54348ce387432d3f8c2d 100644 (file)
@@ -35,7 +35,11 @@ struct MockMockManagedLock : public ManagedLock<MockManagedLockImageCtx> {
       librbd::managed_lock::EXCLUSIVE, true, 0) {
   };
   virtual ~MockMockManagedLock() = default;
+
   MOCK_METHOD2(post_reacquire_lock_handler, void(int, Context*));
+
+  MOCK_METHOD2(pre_release_lock_handler, void(bool, Context*));
+  MOCK_METHOD3(post_release_lock_handler, void(bool, int, Context*));
 };
 
 namespace managed_lock {
@@ -158,6 +162,7 @@ using ::testing::DoAll;
 using ::testing::Invoke;
 using ::testing::InSequence;
 using ::testing::Return;
+using ::testing::WithArg;
 
 class TestMockManagedLock : public TestMockFixture {
 public:
@@ -212,6 +217,23 @@ public:
         on_finish->complete(r);}));
   }
 
+  void expect_pre_release_lock_handler(MockMockManagedLock &managed_lock,
+                                       bool shutting_down, int r) {
+    EXPECT_CALL(managed_lock, pre_release_lock_handler(shutting_down, _))
+      .WillOnce(WithArg<1>(Invoke([r](Context *on_finish){
+                             on_finish->complete(r);
+                           })));
+  }
+
+  void expect_post_release_lock_handler(MockMockManagedLock &managed_lock,
+                                        bool shutting_down, int expect_r,
+                                        int r) {
+    EXPECT_CALL(managed_lock, post_release_lock_handler(shutting_down, expect_r, _))
+      .WillOnce(WithArg<2>(Invoke([r](Context *on_finish){
+                             on_finish->complete(r);
+                           })));
+  }
+
   int when_acquire_lock(MockManagedLock &managed_lock) {
     C_SaferCond ctx;
     {
@@ -379,6 +401,28 @@ TEST_F(TestMockManagedLock, ReleaseLockUnlockedState) {
   ASSERT_EQ(0, when_shut_down(managed_lock));
 }
 
+TEST_F(TestMockManagedLock, ReleaseLockBlacklist) {
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockManagedLockImageCtx mock_image_ctx(*ictx);
+  MockMockManagedLock managed_lock(ictx->md_ctx, ictx->op_work_queue,
+                                   ictx->header_oid, mock_image_ctx.image_watcher,
+                                   librbd::managed_lock::EXCLUSIVE, true, 0);
+  InSequence seq;
+
+  MockAcquireRequest try_lock_acquire;
+  expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, try_lock_acquire, 0);
+  ASSERT_EQ(0, when_acquire_lock(managed_lock));
+
+  expect_pre_release_lock_handler(managed_lock, false, -EBLACKLISTED);
+  expect_post_release_lock_handler(managed_lock, false, -EBLACKLISTED, -EBLACKLISTED);
+  ASSERT_EQ(-EBLACKLISTED, when_release_lock(managed_lock));
+  ASSERT_FALSE(is_lock_owner(managed_lock));
+
+  ASSERT_EQ(0, when_shut_down(managed_lock));
+}
+
 TEST_F(TestMockManagedLock, ReleaseLockError) {
   librbd::ImageCtx *ictx;
   ASSERT_EQ(0, open_image(m_image_name, &ictx));
@@ -549,8 +593,9 @@ TEST_F(TestMockManagedLock, ReacquireWithSameCookie) {
   ASSERT_TRUE(is_lock_owner(managed_lock));
 
   MockReleaseRequest shutdown_release;
+  expect_pre_release_lock_handler(managed_lock, true, 0);
   expect_release_lock(ictx->op_work_queue, shutdown_release, 0);
-  //ASSERT_EQ(0, when_release_lock(managed_lock));
+  expect_post_release_lock_handler(managed_lock, true, 0, 0);
   ASSERT_EQ(0, when_shut_down(managed_lock));
 }