*op_event = &m_op_events[op_tid];
(*op_event)->on_start_safe = on_safe;
- return new C_OpOnComplete(this, op_tid);
+
+ Context *on_op_complete = new C_OpOnComplete(this, op_tid);
+ (*op_event)->on_op_complete = on_op_complete;
+ return on_op_complete;
}
template <typename I>
// skipped upon error -- so clean up if non-null
delete op_event.on_op_finish_event;
+ if (r == -ERESTART) {
+ delete op_event.on_op_complete;
+ }
if (op_event.on_finish_ready != nullptr) {
op_event.on_finish_ready->complete(0);
template<typename T>
struct BaseRequest {
static std::list<T *> s_requests;
- Context *on_lock_unlock;
- Context *on_finish;
+ Context *on_lock_unlock = nullptr;
+ Context *on_finish = nullptr;
static T* create(MockImageCtx &image_ctx, const std::string &cookie,
Context *on_lock_unlock, Context *on_finish) {
#include "librbd/ExclusiveLock.cc"
template class librbd::ExclusiveLock<librbd::MockImageCtx>;
+ACTION_P(FinishLockUnlock, request) {
+ if (request->on_lock_unlock != nullptr) {
+ request->on_lock_unlock->complete(0);
+ }
+}
+
namespace librbd {
using ::testing::_;
+using ::testing::DoAll;
using ::testing::Invoke;
using ::testing::InSequence;
using ::testing::Return;
MockAcquireRequest &acquire_request, int r) {
expect_get_watch_handle(mock_image_ctx);
EXPECT_CALL(acquire_request, send())
- .WillOnce(FinishRequest(&acquire_request, r, &mock_image_ctx));
+ .WillOnce(DoAll(FinishLockUnlock(&acquire_request),
+ FinishRequest(&acquire_request, r, &mock_image_ctx)));
if (r == 0) {
expect_notify_acquired_lock(mock_image_ctx);
expect_unblock_writes(mock_image_ctx);
MockReleaseRequest &release_request, int r,
bool shutting_down = false) {
EXPECT_CALL(release_request, send())
- .WillOnce(FinishRequest(&release_request, r, &mock_image_ctx));
+ .WillOnce(DoAll(FinishLockUnlock(&release_request),
+ FinishRequest(&release_request, r, &mock_image_ctx)));
if (r == 0) {
if (shutting_down) {
expect_unblock_writes(mock_image_ctx);
// fail the try_lock
ASSERT_EQ(0, wait_for_send_ctx1.wait());
+ try_lock_acquire.on_lock_unlock->complete(0);
try_lock_acquire.on_finish->complete(-EINVAL);
ASSERT_EQ(-EINVAL, try_request_ctx1.wait());
// proceed with the release
ASSERT_EQ(0, wait_for_send_ctx2.wait());
+ release.on_lock_unlock->complete(0);
release.on_finish->complete(0);
ASSERT_EQ(0, release_lock_ctx1.wait());