From: Jason Dillaman Date: Fri, 10 Jul 2015 01:26:01 +0000 (-0400) Subject: tests: add journal support to RBD test cases X-Git-Tag: v10.0.1~52^2~20 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=a39fcf9e9eb6a3bdfd60693d5bc4dfd1c9c690b5;p=ceph.git tests: add journal support to RBD test cases Signed-off-by: Jason Dillaman --- diff --git a/src/test/librbd/test_ImageWatcher.cc b/src/test/librbd/test_ImageWatcher.cc index 4c72913e2d8e..216e9557546b 100644 --- a/src/test/librbd/test_ImageWatcher.cc +++ b/src/test/librbd/test_ImageWatcher.cc @@ -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)); +} diff --git a/src/test/librbd/test_internal.cc b/src/test/librbd/test_internal.cc index 559bf2b39849..e35e90ffb292 100644 --- a/src/test/librbd/test_internal.cc +++ b/src/test/librbd/test_internal.cc @@ -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); diff --git a/src/test/run-rbd-tests b/src/test/run-rbd-tests index ac9ca714aecb..82d106e90120 100755 --- a/src/test/run-rbd-tests +++ b/src/test/run-rbd-tests @@ -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 diff --git a/src/test/run-rbd-unit-tests.sh b/src/test/run-rbd-unit-tests.sh index 09edb415270c..7bd27ef2dbb8 100755 --- a/src/test/run-rbd-unit-tests.sh +++ b/src/test/run-rbd-unit-tests.sh @@ -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