From: Mykola Golub Date: Mon, 20 Aug 2018 12:39:30 +0000 (+0300) Subject: librbd: journaling unable request can not be sent to remote lock owner X-Git-Tag: v12.2.9~90^2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=9e0509843fdd4d61768258fb80e327d8294dcb9e;p=ceph.git librbd: journaling unable request can not be sent to remote lock owner Fixes: http://tracker.ceph.com/issues/26939 Signed-off-by: Mykola Golub (cherry picked from commit 985535bae74106aec1938813bdb18661967f468f) --- diff --git a/src/librbd/Operations.cc b/src/librbd/Operations.cc index 6a1bd3ec0257e..bc118915dc407 100644 --- a/src/librbd/Operations.cc +++ b/src/librbd/Operations.cc @@ -1314,12 +1314,31 @@ int Operations::update_features(uint64_t features, bool enabled) { } }; - r = invoke_async_request("update_features", false, - boost::bind(&Operations::execute_update_features, - this, features, enabled, _1, 0), - boost::bind(&ImageWatcher::notify_update_features, - m_image_ctx.image_watcher, features, - enabled, _1)); + // The journal options are not passed to the lock owner in the + // update features request. Therefore, if journaling is being + // enabled, the lock should be locally acquired instead of + // attempting to send the request to the peer. + if (enabled && (features & RBD_FEATURE_JOURNALING) != 0) { + C_SaferCond cond_ctx; + { + RWLock::RLocker owner_lock(m_image_ctx.owner_lock); + r = prepare_image_update(true); + if (r < 0) { + return -EROFS; + } + + execute_update_features(features, enabled, &cond_ctx, 0); + } + + r = cond_ctx.wait(); + } else { + r = invoke_async_request("update_features", false, + boost::bind(&Operations::execute_update_features, + this, features, enabled, _1, 0), + boost::bind(&ImageWatcher::notify_update_features, + m_image_ctx.image_watcher, features, + enabled, _1)); + } ldout(cct, 2) << "update_features finished" << dendl; return r; } diff --git a/src/test/librbd/test_librbd.cc b/src/test/librbd/test_librbd.cc index 16509ae9caf30..67e348a40cdc9 100644 --- a/src/test/librbd/test_librbd.cc +++ b/src/test/librbd/test_librbd.cc @@ -4262,6 +4262,47 @@ TEST_F(TestLibRBD, SnapRemoveViaLockOwner) ASSERT_TRUE(lock_owner); } +TEST_F(TestLibRBD, EnableJournalingViaLockOwner) +{ + REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); + + librados::IoCtx ioctx; + ASSERT_EQ(0, _rados.ioctx_create(m_pool_name.c_str(), ioctx)); + + librbd::RBD rbd; + std::string name = get_temp_image_name(); + uint64_t size = 2 << 20; + int order = 0; + ASSERT_EQ(0, create_image_pp(rbd, ioctx, name.c_str(), size, &order)); + + librbd::Image image1; + ASSERT_EQ(0, rbd.open(ioctx, image1, name.c_str(), NULL)); + + bufferlist bl; + ASSERT_EQ(0, image1.write(0, 0, bl)); + + bool lock_owner; + ASSERT_EQ(0, image1.is_exclusive_lock_owner(&lock_owner)); + ASSERT_TRUE(lock_owner); + + librbd::Image image2; + ASSERT_EQ(0, rbd.open(ioctx, image2, name.c_str(), NULL)); + + ASSERT_EQ(0, image2.update_features(RBD_FEATURE_JOURNALING, false)); + + ASSERT_EQ(0, image1.is_exclusive_lock_owner(&lock_owner)); + ASSERT_TRUE(lock_owner); + ASSERT_EQ(0, image2.is_exclusive_lock_owner(&lock_owner)); + ASSERT_FALSE(lock_owner); + + ASSERT_EQ(0, image2.update_features(RBD_FEATURE_JOURNALING, true)); + + ASSERT_EQ(0, image1.is_exclusive_lock_owner(&lock_owner)); + ASSERT_FALSE(lock_owner); + ASSERT_EQ(0, image2.is_exclusive_lock_owner(&lock_owner)); + ASSERT_TRUE(lock_owner); +} + TEST_F(TestLibRBD, SnapRemove2) { REQUIRE_FEATURE(RBD_FEATURE_LAYERING);