}
template <typename I>
-void ExclusiveLock<I>::set_require_lock(io::Direction direction,
+void ExclusiveLock<I>::set_require_lock(bool init_shutdown,
+ io::Direction direction,
Context* on_finish) {
- m_image_dispatch->set_require_lock(direction, on_finish);
+ m_image_dispatch->set_require_lock(init_shutdown, direction, on_finish);
}
template <typename I>
if (m_image_ctx.clone_copy_on_read ||
(features & RBD_FEATURE_JOURNALING) != 0 ||
rwl_enabled) {
- m_image_dispatch->set_require_lock(io::DIRECTION_BOTH, on_finish);
+ m_image_dispatch->set_require_lock(true, io::DIRECTION_BOTH, on_finish);
} else {
- m_image_dispatch->set_require_lock(io::DIRECTION_WRITE, on_finish);
+ m_image_dispatch->set_require_lock(true, io::DIRECTION_WRITE, on_finish);
}
}
int *ret_val) const;
bool accept_ops() const;
- void set_require_lock(io::Direction direction, Context* on_finish);
+ void set_require_lock(bool init_shutdown, io::Direction direction,
+ Context* on_finish);
void unset_require_lock(io::Direction direction);
void block_requests(int r);
}
template <typename I>
-void ImageDispatch<I>::set_require_lock(io::Direction direction,
+void ImageDispatch<I>::set_require_lock(bool init_shutdown,
+ io::Direction direction,
Context* on_finish) {
// pause any matching IO from proceeding past this layer
set_require_lock(direction, true);
on_finish, util::get_image_ctx(m_image_ctx), io::AIO_TYPE_FLUSH);
auto req = io::ImageDispatchSpec::create_flush(
*m_image_ctx, io::IMAGE_DISPATCH_LAYER_EXCLUSIVE_LOCK, aio_comp,
- io::FLUSH_SOURCE_EXCLUSIVE_LOCK, {});
+ (init_shutdown ?
+ io::FLUSH_SOURCE_EXCLUSIVE_LOCK_SKIP_REFRESH :
+ io::FLUSH_SOURCE_EXCLUSIVE_LOCK), {});
req->send();
}
return io::IMAGE_DISPATCH_LAYER_EXCLUSIVE_LOCK;
}
- void set_require_lock(io::Direction direction, Context* on_finish);
+ void set_require_lock(bool init_shutdown,
+ io::Direction direction, Context* on_finish);
void unset_require_lock(io::Direction direction);
void shut_down(Context* on_finish) override;
// queue to re-request the lock if any IO is queued
if (m_image_ctx.clone_copy_on_read ||
m_image_ctx.test_features(RBD_FEATURE_JOURNALING)) {
- m_image_dispatch->set_require_lock(io::DIRECTION_BOTH, ctx);
+ m_image_dispatch->set_require_lock(m_shutting_down,
+ io::DIRECTION_BOTH, ctx);
} else {
- m_image_dispatch->set_require_lock(io::DIRECTION_WRITE, ctx);
+ m_image_dispatch->set_require_lock(m_shutting_down,
+ io::DIRECTION_WRITE, ctx);
}
}
send_v2_block_writes();
});
m_image_ctx.exclusive_lock->set_require_lock(
- librbd::io::DIRECTION_BOTH, ctx);
+ true, librbd::io::DIRECTION_BOTH, ctx);
return;
}
template <>
struct ImageDispatch<MockTestImageCtx> {
- MOCK_METHOD2(set_require_lock, void(io::Direction, Context*));
+ MOCK_METHOD3(set_require_lock, void(bool init_shutdown, io::Direction,
+ Context*));
MOCK_METHOD1(unset_require_lock, void(io::Direction));
};
}
void expect_set_require_lock(MockImageDispatch &mock_image_dispatch,
+ bool init_shutdown,
librbd::io::Direction direction, int r) {
- EXPECT_CALL(mock_image_dispatch, set_require_lock(direction, _))
- .WillOnce(WithArg<1>(Invoke([r](Context* ctx) { ctx->complete(r); })));
+ EXPECT_CALL(mock_image_dispatch, set_require_lock(init_shutdown,
+ direction, _))
+ .WillOnce(WithArg<2>(Invoke([r](Context* ctx) { ctx->complete(r); })));
}
void expect_set_require_lock(MockTestImageCtx &mock_image_ctx,
- MockImageDispatch &mock_image_dispatch, int r) {
+ MockImageDispatch &mock_image_dispatch,
+ bool init_shutdown, int r) {
expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
((mock_image_ctx.features & RBD_FEATURE_JOURNALING) != 0));
if (mock_image_ctx.clone_copy_on_read ||
(mock_image_ctx.features & RBD_FEATURE_JOURNALING) != 0) {
- expect_set_require_lock(mock_image_dispatch, librbd::io::DIRECTION_BOTH,
- r);
+ expect_set_require_lock(mock_image_dispatch, init_shutdown,
+ librbd::io::DIRECTION_BOTH, r);
} else {
- expect_set_require_lock(mock_image_dispatch, librbd::io::DIRECTION_WRITE,
- r);
+ expect_set_require_lock(mock_image_dispatch, init_shutdown,
+ librbd::io::DIRECTION_WRITE, r);
}
}
expect_prepare_lock(mock_image_ctx);
expect_cancel_op_requests(mock_image_ctx, 0);
MockImageDispatch mock_image_dispatch;
- expect_set_require_lock(mock_image_ctx, mock_image_dispatch, 0);
+ expect_set_require_lock(mock_image_ctx, mock_image_dispatch, false, 0);
cache::MockImageCache mock_image_cache;
mock_image_ctx.image_cache = &mock_image_cache;
MockTestImageCtx mock_image_ctx(*ictx);
MockImageDispatch mock_image_dispatch;
- expect_set_require_lock(mock_image_ctx, mock_image_dispatch, 0);
+ expect_set_require_lock(mock_image_ctx, mock_image_dispatch, false, 0);
expect_op_work_queue(mock_image_ctx);
InSequence seq;
MockTestImageCtx mock_image_ctx(*ictx);
MockImageDispatch mock_image_dispatch;
- expect_set_require_lock(mock_image_ctx, mock_image_dispatch, 0);
+ expect_set_require_lock(mock_image_ctx, mock_image_dispatch, true, 0);
expect_op_work_queue(mock_image_ctx);
InSequence seq;
expect_prepare_lock(mock_image_ctx);
expect_cancel_op_requests(mock_image_ctx, 0);
MockImageDispatch mock_image_dispatch;
- expect_set_require_lock(mock_image_ctx, mock_image_dispatch, -EBLOCKLISTED);
+ expect_set_require_lock(mock_image_ctx, mock_image_dispatch, false,
+ -EBLOCKLISTED);
cache::MockImageCache mock_image_cache;
mock_image_ctx.image_cache = &mock_image_cache;
InSequence seq;
expect_cancel_op_requests(mock_image_ctx, 0);
MockImageDispatch mock_image_dispatch;
- expect_set_require_lock(mock_image_ctx, mock_image_dispatch, -EINVAL);
+ expect_set_require_lock(mock_image_ctx, mock_image_dispatch, true, -EINVAL);
expect_unset_require_lock(mock_image_dispatch);
C_SaferCond ctx;
ASSERT_EQ(-EINVAL, ctx.wait());
}
-TEST_F(TestMockExclusiveLockPreReleaseRequest, UnlockError) {
- REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
- librbd::ImageCtx *ictx;
- ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
- MockTestImageCtx mock_image_ctx(*ictx);
-
- expect_op_work_queue(mock_image_ctx);
-
- InSequence seq;
- expect_cancel_op_requests(mock_image_ctx, 0);
- MockImageDispatch mock_image_dispatch;
- expect_set_require_lock(mock_image_ctx, mock_image_dispatch, 0);
- expect_invalidate_cache(mock_image_ctx, 0);
-
- expect_flush_notifies(mock_image_ctx);
-
- C_SaferCond ctx;
- MockPreReleaseRequest *req = MockPreReleaseRequest::create(
- mock_image_ctx, &mock_image_dispatch, true, m_async_op_tracker, &ctx);
- req->send();
- ASSERT_EQ(0, ctx.wait());
-}
-
} // namespace exclusive_lock
} // namespace librbd
void expect_set_require_lock(MockExclusiveLock &mock_exclusive_lock,
librbd::io::Direction direction) {
- EXPECT_CALL(mock_exclusive_lock, set_require_lock(direction, _))
- .WillOnce(WithArg<1>(Invoke([](Context* ctx) { ctx->complete(0); })));
+ EXPECT_CALL(mock_exclusive_lock, set_require_lock(true, direction, _))
+ .WillOnce(WithArg<2>(Invoke([](Context* ctx) { ctx->complete(0); })));
}
void expect_unset_require_lock(MockExclusiveLock &mock_exclusive_lock,
MOCK_METHOD0(accept_ops, bool());
MOCK_METHOD0(get_unlocked_op_error, int());
- MOCK_METHOD2(set_require_lock, void(io::Direction, Context*));
+ MOCK_METHOD3(set_require_lock, void(bool init_shutdown, io::Direction,
+ Context*));
MOCK_METHOD1(unset_require_lock, void(io::Direction));
MOCK_METHOD1(start_op, Context*(int*));
return io::IMAGE_DISPATCH_LAYER_EXCLUSIVE_LOCK;
}
- MOCK_METHOD2(set_require_lock, void(io::Direction, Context*));
+ MOCK_METHOD3(set_require_lock, void(bool, io::Direction, Context*));
MOCK_METHOD1(unset_require_lock, void(io::Direction));
};
}
void expect_set_require_lock(MockImageDispatch &mock_image_dispatch,
- io::Direction direction) {
- EXPECT_CALL(mock_image_dispatch, set_require_lock(direction, _))
- .WillOnce(WithArg<1>(Invoke([](Context* ctx) { ctx->complete(0); })));
+ bool init_shutdown, io::Direction direction) {
+ EXPECT_CALL(mock_image_dispatch, set_require_lock(init_shutdown,
+ direction, _))
+ .WillOnce(WithArg<2>(Invoke([](Context* ctx) { ctx->complete(0); })));
}
void expect_set_require_lock(MockExclusiveLockImageCtx &mock_image_ctx,
- MockImageDispatch &mock_image_dispatch) {
+ MockImageDispatch &mock_image_dispatch,
+ bool init_shutdown) {
if (mock_image_ctx.clone_copy_on_read ||
(mock_image_ctx.features & RBD_FEATURE_JOURNALING) != 0 ||
is_rbd_rwl_enabled(mock_image_ctx.cct)) {
- expect_set_require_lock(mock_image_dispatch, io::DIRECTION_BOTH);
+ expect_set_require_lock(mock_image_dispatch, init_shutdown,
+ io::DIRECTION_BOTH);
} else {
- expect_set_require_lock(mock_image_dispatch, io::DIRECTION_WRITE);
+ expect_set_require_lock(mock_image_dispatch, init_shutdown,
+ io::DIRECTION_WRITE);
}
}
MockImageDispatch mock_image_dispatch;
expect_block_writes(mock_image_ctx, mock_image_dispatch);
expect_register_dispatch(mock_image_ctx);
- expect_set_require_lock(mock_image_ctx, mock_image_dispatch);
+ expect_set_require_lock(mock_image_ctx, mock_image_dispatch, true);
expect_unblock_writes(mock_image_ctx);
expect_set_state_unlocked(exclusive_lock);
ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
MockImageDispatch mock_image_dispatch;
expect_block_writes(mock_image_ctx, mock_image_dispatch);
expect_register_dispatch(mock_image_ctx);
- expect_set_require_lock(mock_image_ctx, mock_image_dispatch);
+ expect_set_require_lock(mock_image_ctx, mock_image_dispatch, true);
expect_unblock_writes(mock_image_ctx);
expect_set_state_unlocked(exclusive_lock);
ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
MockImageDispatch mock_image_dispatch;
expect_block_writes(mock_image_ctx, mock_image_dispatch);
expect_register_dispatch(mock_image_ctx);
- expect_set_require_lock(mock_image_ctx, mock_image_dispatch);
+ expect_set_require_lock(mock_image_ctx, mock_image_dispatch, true);
expect_unblock_writes(mock_image_ctx);
expect_set_state_unlocked(exclusive_lock);
ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
MockImageDispatch mock_image_dispatch;
expect_block_writes(mock_image_ctx, mock_image_dispatch);
expect_register_dispatch(mock_image_ctx);
- expect_set_require_lock(mock_image_ctx, mock_image_dispatch);
+ expect_set_require_lock(mock_image_ctx, mock_image_dispatch, true);
expect_unblock_writes(mock_image_ctx);
expect_set_state_unlocked(exclusive_lock);
ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
MockImageDispatch mock_image_dispatch;
expect_block_writes(mock_image_ctx, mock_image_dispatch);
expect_register_dispatch(mock_image_ctx);
- expect_set_require_lock(mock_image_ctx, mock_image_dispatch);
+ expect_set_require_lock(mock_image_ctx, mock_image_dispatch, true);
expect_unblock_writes(mock_image_ctx);
expect_set_state_unlocked(exclusive_lock);
ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
MockImageDispatch mock_image_dispatch;
expect_block_writes(mock_image_ctx, mock_image_dispatch);
expect_register_dispatch(mock_image_ctx);
- expect_set_require_lock(mock_image_ctx, mock_image_dispatch);
+ expect_set_require_lock(mock_image_ctx, mock_image_dispatch, true);
expect_unblock_writes(mock_image_ctx);
expect_set_state_unlocked(exclusive_lock);
ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
MockImageDispatch mock_image_dispatch;
expect_block_writes(mock_image_ctx, mock_image_dispatch);
expect_register_dispatch(mock_image_ctx);
- expect_set_require_lock(mock_image_ctx, mock_image_dispatch);
+ expect_set_require_lock(mock_image_ctx, mock_image_dispatch, true);
expect_unblock_writes(mock_image_ctx);
expect_set_state_unlocked(exclusive_lock);
ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
MockImageDispatch mock_image_dispatch;
expect_block_writes(mock_image_ctx, mock_image_dispatch);
expect_register_dispatch(mock_image_ctx);
- expect_set_require_lock(mock_image_ctx, mock_image_dispatch);
+ expect_set_require_lock(mock_image_ctx, mock_image_dispatch, true);
expect_unblock_writes(mock_image_ctx);
expect_set_state_unlocked(exclusive_lock);
ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
MockImageDispatch mock_image_dispatch;
expect_block_writes(mock_image_ctx, mock_image_dispatch);
expect_register_dispatch(mock_image_ctx);
- expect_set_require_lock(mock_image_ctx, mock_image_dispatch);
+ expect_set_require_lock(mock_image_ctx, mock_image_dispatch, true);
expect_unblock_writes(mock_image_ctx);
expect_set_state_unlocked(exclusive_lock);
ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
MockImageDispatch mock_image_dispatch;
expect_block_writes(mock_image_ctx, mock_image_dispatch);
expect_register_dispatch(mock_image_ctx);
- expect_set_require_lock(mock_image_ctx, mock_image_dispatch);
+ expect_set_require_lock(mock_image_ctx, mock_image_dispatch, true);
expect_unblock_writes(mock_image_ctx);
expect_set_state_unlocked(exclusive_lock);
ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));