}
};
- r = invoke_async_request("update_features", false,
- boost::bind(&Operations<I>::execute_update_features,
- this, features, enabled, _1, 0),
- boost::bind(&ImageWatcher<I>::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<I>::execute_update_features,
+ this, features, enabled, _1, 0),
+ boost::bind(&ImageWatcher<I>::notify_update_features,
+ m_image_ctx.image_watcher, features,
+ enabled, _1));
+ }
ldout(cct, 2) << "update_features finished" << dendl;
return r;
}
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);