]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
tests: add journal support to RBD test cases
authorJason Dillaman <dillaman@redhat.com>
Fri, 10 Jul 2015 01:26:01 +0000 (21:26 -0400)
committerJason Dillaman <dillaman@redhat.com>
Fri, 13 Nov 2015 04:26:26 +0000 (23:26 -0500)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/test/librbd/test_ImageWatcher.cc
src/test/librbd/test_internal.cc
src/test/run-rbd-tests
src/test/run-rbd-unit-tests.sh

index 4c72913e2d8ec5404df8cbdf92ccbaabc5c175ba..216e9557546b110a2a54ec7fbfa0b15ec4ba3207 100644 (file)
@@ -45,6 +45,34 @@ public:
   {
   }
 
+  struct LockListener : public librbd::ImageWatcher::Listener {
+    Mutex lock;
+    Cond cond;
+    size_t releasing_lock_count;
+    size_t lock_updated_count;
+    bool lock_owner;
+
+    LockListener()
+      : lock("lock"), releasing_lock_count(0), lock_updated_count(0),
+        lock_owner(false) {
+    }
+
+    virtual bool handle_requested_lock() {
+      return true;
+    }
+    virtual void handle_releasing_lock() {
+      Mutex::Locker locker(lock);
+      ++releasing_lock_count;
+      cond.Signal();
+    }
+    virtual void handle_lock_updated(bool _lock_supported, bool _lock_owner) {
+      Mutex::Locker locker(lock);
+      ++lock_updated_count;
+      lock_owner = _lock_owner;
+      cond.Signal();
+    }
+  };
+
   class WatchCtx : public librados::WatchCtx2 {
   public:
     WatchCtx(TestImageWatcher &parent) : m_parent(parent), m_handle(0) {}
@@ -127,11 +155,39 @@ public:
     return 0;
   }
 
+  void register_lock_listener(librbd::ImageCtx &ictx) {
+    ictx.image_watcher->register_listener(&m_lock_listener);
+  }
+
   int register_image_watch(librbd::ImageCtx &ictx) {
     m_watch_ctx = new WatchCtx(*this);
     return m_watch_ctx->watch(ictx);
   }
 
+  bool wait_for_releasing_lock(librbd::ImageCtx &ictx) {
+    Mutex::Locker locker(m_lock_listener.lock);
+    while (m_lock_listener.releasing_lock_count == 0) {
+      if (m_lock_listener.cond.WaitInterval(ictx.cct, m_lock_listener.lock,
+                                            utime_t(10, 0)) != 0) {
+        return false;
+      }
+    }
+    m_lock_listener.releasing_lock_count = 0;
+    return true;
+  }
+
+  bool wait_for_lock_updated(librbd::ImageCtx &ictx) {
+    Mutex::Locker locker(m_lock_listener.lock);
+    while (m_lock_listener.lock_updated_count == 0) {
+      if (m_lock_listener.cond.WaitInterval(ictx.cct, m_lock_listener.lock,
+                                            utime_t(10, 0)) != 0) {
+        return false;
+      }
+    }
+    m_lock_listener.lock_updated_count = 0;
+    return true;
+  }
+
   bool wait_for_notifies(librbd::ImageCtx &ictx) {
     Mutex::Locker l(m_callback_lock);
     while (m_notifies.size() < m_notify_acks.size()) {
@@ -205,6 +261,8 @@ public:
 
   WatchCtx *m_watch_ctx;
 
+  LockListener m_lock_listener;
+
   NotifyOps m_notifies;
   NotifyOpPayloads m_notify_payloads;
   NotifyOpPayloads m_notify_acks;
@@ -311,14 +369,6 @@ TEST_F(TestImageWatcher, IsLockSupported) {
   ictx->snap_id = CEPH_NOSNAP;
 }
 
-TEST_F(TestImageWatcher, WritesSuspended) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-  ASSERT_TRUE(ictx->aio_work_queue->writes_suspended());
-}
-
 TEST_F(TestImageWatcher, TryLock) {
   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
 
@@ -422,17 +472,17 @@ TEST_F(TestImageWatcher, TryLockWithUserSharedLocked) {
   ASSERT_TRUE(ictx->image_watcher->is_lock_owner());
 }
 
-TEST_F(TestImageWatcher, UnlockNotLocked) {
+TEST_F(TestImageWatcher, ReleaseLockNotLocked) {
   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
 
   librbd::ImageCtx *ictx;
   ASSERT_EQ(0, open_image(m_image_name, &ictx));
 
   RWLock::WLocker l(ictx->owner_lock);
-  ASSERT_EQ(0, ictx->image_watcher->unlock());
+  ASSERT_EQ(0, ictx->image_watcher->release_lock());
 }
 
-TEST_F(TestImageWatcher, UnlockNotifyReleaseLock) {
+TEST_F(TestImageWatcher, ReleaseLockNotifies) {
   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
 
   librbd::ImageCtx *ictx;
@@ -450,7 +500,7 @@ TEST_F(TestImageWatcher, UnlockNotifyReleaseLock) {
   m_notify_acks += std::make_pair(NOTIFY_OP_RELEASED_LOCK, bufferlist());
   {
     RWLock::WLocker l(ictx->owner_lock);
-    ASSERT_EQ(0, ictx->image_watcher->unlock());
+    ASSERT_EQ(0, ictx->image_watcher->release_lock());
   }
   ASSERT_TRUE(wait_for_notifies(*ictx));
 
@@ -459,7 +509,7 @@ TEST_F(TestImageWatcher, UnlockNotifyReleaseLock) {
   ASSERT_EQ(expected_notify_ops, m_notifies);
 }
 
-TEST_F(TestImageWatcher, UnlockBrokenLock) {
+TEST_F(TestImageWatcher, ReleaseLockBrokenLock) {
   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
 
   librbd::ImageCtx *ictx;
@@ -480,21 +530,47 @@ TEST_F(TestImageWatcher, UnlockBrokenLock) {
                                            lockers.begin()->first.cookie,
                                            lockers.begin()->first.locker));
 
-  ASSERT_EQ(0, ictx->image_watcher->unlock());
+  ASSERT_EQ(0, ictx->image_watcher->release_lock());
 }
 
 TEST_F(TestImageWatcher, RequestLock) {
   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
 
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+  ASSERT_EQ(0, register_image_watch(*ictx));
+
+  register_lock_listener(*ictx);
+  m_notify_acks = {{NOTIFY_OP_ACQUIRED_LOCK, bufferlist()}};
+
+  {
+    RWLock::RLocker owner_locker(ictx->owner_lock);
+    ictx->image_watcher->request_lock();
+  }
+
+  ASSERT_TRUE(wait_for_notifies(*ictx));
+  NotifyOps expected_notify_ops;
+  expected_notify_ops += NOTIFY_OP_ACQUIRED_LOCK;
+  ASSERT_EQ(expected_notify_ops, m_notifies);
+
+  {
+    RWLock::RLocker owner_locker(ictx->owner_lock);
+    ASSERT_TRUE(ictx->image_watcher->is_lock_owner());
+  }
+}
+
+TEST_F(TestImageWatcher, RequestLockFromPeer) {
+  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
   librbd::ImageCtx *ictx;
   ASSERT_EQ(0, open_image(m_image_name, &ictx));
   ASSERT_EQ(0, register_image_watch(*ictx));
   ASSERT_EQ(0, lock_image(*ictx, LOCK_EXCLUSIVE,
                          "auto " + stringify(m_watch_ctx->get_handle())));
 
+  register_lock_listener(*ictx);
   m_notify_acks = {{NOTIFY_OP_REQUEST_LOCK, create_response_message(0)}};
 
-  ASSERT_TRUE(ictx->aio_work_queue->writes_suspended());
   {
     RWLock::RLocker owner_locker(ictx->owner_lock);
     ictx->image_watcher->request_lock();
@@ -510,8 +586,7 @@ TEST_F(TestImageWatcher, RequestLock) {
   {
     Mutex::Locker l(m_callback_lock);
     m_notifies.clear();
-    m_notify_acks = {{NOTIFY_OP_RELEASED_LOCK,{}},
-                     {NOTIFY_OP_ACQUIRED_LOCK,{}}};
+    m_notify_acks = {{NOTIFY_OP_RELEASED_LOCK,{}}};
   }
 
   bufferlist bl;
@@ -521,13 +596,28 @@ TEST_F(TestImageWatcher, RequestLock) {
     ENCODE_FINISH(bl);
   }
   ASSERT_EQ(0, m_ioctx.notify2(ictx->header_oid, bl, 5000, NULL));
+  ASSERT_TRUE(wait_for_lock_updated(*ictx));
+
+  {
+    Mutex::Locker l(m_callback_lock);
+    m_notifies.clear();
+    m_notify_acks = {{NOTIFY_OP_ACQUIRED_LOCK, bufferlist()}};
+  }
+
+  {
+    RWLock::RLocker owner_lock(ictx->owner_lock);
+    ictx->image_watcher->request_lock();
+  }
 
   ASSERT_TRUE(wait_for_notifies(*ictx));
   expected_notify_ops.clear();
-  expected_notify_ops += NOTIFY_OP_RELEASED_LOCK, NOTIFY_OP_ACQUIRED_LOCK;
+  expected_notify_ops += NOTIFY_OP_ACQUIRED_LOCK;
   ASSERT_EQ(expected_notify_ops, m_notifies);
 
-  ASSERT_FALSE(ictx->aio_work_queue->writes_suspended());
+  {
+    RWLock::RLocker owner_locker(ictx->owner_lock);
+    ASSERT_TRUE(ictx->image_watcher->is_lock_owner());
+  }
 }
 
 TEST_F(TestImageWatcher, RequestLockTimedOut) {
@@ -539,9 +629,9 @@ TEST_F(TestImageWatcher, RequestLockTimedOut) {
   ASSERT_EQ(0, lock_image(*ictx, LOCK_EXCLUSIVE,
                          "auto " + stringify(m_watch_ctx->get_handle())));
 
+  register_lock_listener(*ictx);
   m_notify_acks = {{NOTIFY_OP_REQUEST_LOCK, {}}};
 
-  ASSERT_TRUE(ictx->aio_work_queue->writes_suspended());
   {
     RWLock::RLocker owner_locker(ictx->owner_lock);
     ictx->image_watcher->request_lock();
@@ -558,7 +648,6 @@ TEST_F(TestImageWatcher, RequestLockTimedOut) {
     m_notifies.clear();
   }
   ASSERT_TRUE(wait_for_notifies(*ictx));
-  ASSERT_TRUE(ictx->aio_work_queue->writes_suspended());
 
   {
     Mutex::Locker l(m_callback_lock);
@@ -568,7 +657,12 @@ TEST_F(TestImageWatcher, RequestLockTimedOut) {
   }
 
   ASSERT_TRUE(wait_for_notifies(*ictx));
-  ASSERT_FALSE(ictx->aio_work_queue->writes_suspended());
+  ASSERT_TRUE(wait_for_lock_updated(*ictx));
+
+  {
+    RWLock::RLocker owner_locker(ictx->owner_lock);
+    ASSERT_TRUE(ictx->image_watcher->is_lock_owner());
+  }
 }
 
 TEST_F(TestImageWatcher, RequestLockIgnored) {
@@ -580,6 +674,7 @@ TEST_F(TestImageWatcher, RequestLockIgnored) {
   ASSERT_EQ(0, lock_image(*ictx, LOCK_EXCLUSIVE,
                          "auto " + stringify(m_watch_ctx->get_handle())));
 
+  register_lock_listener(*ictx);
   m_notify_acks = {{NOTIFY_OP_REQUEST_LOCK, create_response_message(0)}};
 
   int orig_notify_timeout = ictx->cct->_conf->client_notify_timeout;
@@ -589,7 +684,6 @@ TEST_F(TestImageWatcher, RequestLockIgnored) {
                               stringify(orig_notify_timeout));
   } BOOST_SCOPE_EXIT_END;
 
-  ASSERT_TRUE(ictx->aio_work_queue->writes_suspended());
   {
     RWLock::RLocker owner_locker(ictx->owner_lock);
     ictx->image_watcher->request_lock();
@@ -616,7 +710,12 @@ TEST_F(TestImageWatcher, RequestLockIgnored) {
   }
 
   ASSERT_TRUE(wait_for_notifies(*ictx));
-  ASSERT_FALSE(ictx->aio_work_queue->writes_suspended());
+  ASSERT_TRUE(wait_for_lock_updated(*ictx));
+
+  {
+    RWLock::RLocker owner_locker(ictx->owner_lock);
+    ASSERT_TRUE(ictx->image_watcher->is_lock_owner());
+  }
 }
 
 TEST_F(TestImageWatcher, RequestLockTryLockRace) {
@@ -628,11 +727,11 @@ TEST_F(TestImageWatcher, RequestLockTryLockRace) {
   ASSERT_EQ(0, lock_image(*ictx, LOCK_EXCLUSIVE,
                           "auto " + stringify(m_watch_ctx->get_handle())));
 
+  register_lock_listener(*ictx);
   m_notify_acks = {{NOTIFY_OP_REQUEST_LOCK, create_response_message(0)}};
 
   {
     RWLock::RLocker owner_locker(ictx->owner_lock);
-    ictx->image_watcher->flag_aio_ops_pending();
     ictx->image_watcher->request_lock();
   }
 
@@ -667,14 +766,30 @@ TEST_F(TestImageWatcher, RequestLockTryLockRace) {
     Mutex::Locker l(m_callback_lock);
     ASSERT_EQ(0, unlock_image());
     m_notifies.clear();
-    m_notify_acks = {
-      {NOTIFY_OP_RELEASED_LOCK, bufferlist()},
-      {NOTIFY_OP_ACQUIRED_LOCK, bufferlist()}};
+    m_notify_acks = {{NOTIFY_OP_RELEASED_LOCK, bufferlist()}};
   }
 
   ASSERT_EQ(0, m_ioctx.notify2(ictx->header_oid, bl, 5000, NULL));
+  ASSERT_TRUE(wait_for_lock_updated(*ictx));
+
+  {
+    Mutex::Locker l(m_callback_lock);
+    m_notifies.clear();
+    m_notify_acks = {{NOTIFY_OP_ACQUIRED_LOCK, bufferlist()}};
+  }
+
+  {
+    RWLock::RLocker owner_lock(ictx->owner_lock);
+    ictx->image_watcher->request_lock();
+  }
+
+  ASSERT_TRUE(wait_for_lock_updated(*ictx));
   ASSERT_TRUE(wait_for_notifies(*ictx));
-  ASSERT_FALSE(ictx->aio_work_queue->writes_suspended());
+
+  {
+    RWLock::RLocker owner_locker(ictx->owner_lock);
+    ASSERT_TRUE(ictx->image_watcher->is_lock_owner());
+  }
 }
 
 TEST_F(TestImageWatcher, RequestLockTryLockFailed) {
@@ -685,9 +800,9 @@ TEST_F(TestImageWatcher, RequestLockTryLockFailed) {
   ASSERT_EQ(0, register_image_watch(*ictx));
   ASSERT_EQ(0, lock_image(*ictx, LOCK_SHARED, "manually 1234"));
 
+  register_lock_listener(*ictx);
   m_notify_acks = {{NOTIFY_OP_REQUEST_LOCK, {}}};
 
-  ASSERT_TRUE(ictx->aio_work_queue->writes_suspended());
   {
     RWLock::RLocker owner_locker(ictx->owner_lock);
     ictx->image_watcher->request_lock();
@@ -704,7 +819,6 @@ TEST_F(TestImageWatcher, RequestLockTryLockFailed) {
     m_notifies.clear();
   }
   ASSERT_TRUE(wait_for_notifies(*ictx));
-  ASSERT_TRUE(ictx->aio_work_queue->writes_suspended());
 
   {
     Mutex::Locker l(m_callback_lock);
@@ -714,7 +828,6 @@ TEST_F(TestImageWatcher, RequestLockTryLockFailed) {
   }
 
   ASSERT_TRUE(wait_for_notifies(*ictx));
-  ASSERT_FALSE(ictx->aio_work_queue->writes_suspended());
 }
 
 TEST_F(TestImageWatcher, NotifyHeaderUpdate) {
@@ -1032,3 +1145,48 @@ TEST_F(TestImageWatcher, NotifyAsyncRequestTimedOut) {
   ASSERT_TRUE(thread.timed_join(boost::posix_time::seconds(10)));
   ASSERT_EQ(-ERESTART, flatten_task.result);
 }
+
+TEST_F(TestImageWatcher, PeerRequestsLock) {
+  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+  ASSERT_EQ(0, register_image_watch(*ictx));
+
+  register_lock_listener(*ictx);
+  m_notify_acks = {{NOTIFY_OP_ACQUIRED_LOCK, bufferlist()}};
+
+  {
+    RWLock::RLocker owner_locker(ictx->owner_lock);
+    ictx->image_watcher->request_lock();
+  }
+
+  ASSERT_TRUE(wait_for_notifies(*ictx));
+
+  {
+    RWLock::RLocker owner_locker(ictx->owner_lock);
+    ASSERT_TRUE(ictx->image_watcher->is_lock_owner());
+  }
+
+  // if journaling is enabled, ensure we wait for it to replay since
+  // it will block our peer request
+  std::string buffer(256, '1');
+  ictx->aio_work_queue->write(0, buffer.size(), buffer.c_str(), 0);
+
+  {
+    Mutex::Locker l(m_callback_lock);
+    m_notifies.clear();
+    m_notify_acks = {{NOTIFY_OP_RELEASED_LOCK, bufferlist()}};
+  }
+
+  bufferlist bl;
+  {
+    ENCODE_START(1, 1, bl);
+    ::encode(NOTIFY_OP_REQUEST_LOCK, bl);
+    ENCODE_FINISH(bl);
+  }
+  ASSERT_EQ(0, m_ioctx.notify2(ictx->header_oid, bl, 5000, NULL));
+
+  ASSERT_TRUE(wait_for_releasing_lock(*ictx));
+  ASSERT_TRUE(wait_for_notifies(*ictx));
+}
index 559bf2b398498174d09e736918ff9731685d5e84..e35e90ffb29223b4d8ab1e607a1fe4deef51628a 100644 (file)
@@ -656,12 +656,11 @@ TEST_F(TestInternal, ShrinkFlushesCache) {
   librbd::ImageCtx *ictx;
   ASSERT_EQ(0, open_image(m_image_name, &ictx));
 
-  {
-    RWLock::WLocker owner_locker(ictx->owner_lock);
-    ASSERT_EQ(0, ictx->image_watcher->try_lock());
-  }
-
   std::string buffer(4096, '1');
+
+  // ensure write-path is initialized
+  ictx->aio_work_queue->write(0, buffer.size(), buffer.c_str(), 0);
+
   C_SaferCond cond_ctx;
   librbd::AioCompletion *c =
     librbd::aio_create_completion_internal(&cond_ctx, librbd::rbd_ctx_cb);
index ac9ca714aecb1c7c88771dc0c0b4e92fcecfca4b..82d106e90120e0c91989c65c8ee5913115841073 100755 (executable)
@@ -41,7 +41,7 @@ run_admin_socket_tests
 export RBD_CREATE_ARGS="--image-format 2"
 run_cli_tests
 
-for i in 0 1 5 13 29 45
+for i in 0 1 5 13 29 109
 do
     export RBD_FEATURES=$i
     run_api_tests
index 09edb415270c0ad95d708368356e93fb43bb36d7..7bd27ef2dbb8d2e5b0666850853ee679bb153fe3 100755 (executable)
@@ -7,7 +7,7 @@ export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$CEPH_SRC/.libs"
 PATH="$CEPH_SRC:$PATH"
 
 unittest_librbd
-for i in 0 1 5 29 45
+for i in 0 1 5 29 109
 do
     RBD_FEATURES=$i unittest_librbd
 done