]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/librbd/test_mock_ExclusiveLock.cc
bump version to 18.2.2-pve1
[ceph.git] / ceph / src / test / librbd / test_mock_ExclusiveLock.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4#include "test/librbd/test_mock_fixture.h"
5#include "test/librbd/test_support.h"
6#include "test/librbd/mock/MockImageCtx.h"
92f5a8d4 7#include "test/librbd/mock/exclusive_lock/MockPolicy.h"
f67539c2 8#include "test/librbd/mock/io/MockImageDispatch.h"
7c673cae
FG
9#include "librbd/ExclusiveLock.h"
10#include "librbd/ManagedLock.h"
f67539c2 11#include "librbd/exclusive_lock/ImageDispatch.h"
7c673cae
FG
12#include "librbd/exclusive_lock/PreAcquireRequest.h"
13#include "librbd/exclusive_lock/PostAcquireRequest.h"
14#include "librbd/exclusive_lock/PreReleaseRequest.h"
15#include "gmock/gmock.h"
16#include "gtest/gtest.h"
17#include <list>
9f95a23c 18#include <boost/scope_exit.hpp>
7c673cae
FG
19
20namespace librbd {
21
22namespace {
23
24struct MockExclusiveLockImageCtx : public MockImageCtx {
f67539c2 25 asio::ContextWQ *op_work_queue;
7c673cae
FG
26
27 MockExclusiveLockImageCtx(ImageCtx &image_ctx) : MockImageCtx(image_ctx) {
28 op_work_queue = image_ctx.op_work_queue;
29 }
30};
31
32} // anonymous namespace
33
34namespace watcher {
35template <>
36struct Traits<MockExclusiveLockImageCtx> {
37 typedef librbd::MockImageWatcher Watcher;
38};
39}
40
41template <>
42struct ManagedLock<MockExclusiveLockImageCtx> {
f67539c2 43 ManagedLock(librados::IoCtx& ioctx, AsioEngine& asio_engine,
7c673cae 44 const std::string& oid, librbd::MockImageWatcher *watcher,
f67539c2
TL
45 managed_lock::Mode mode, bool blocklist_on_break_lock,
46 uint32_t blocklist_expire_seconds)
9f95a23c 47 {}
7c673cae
FG
48
49 virtual ~ManagedLock() = default;
50
9f95a23c 51 mutable ceph::mutex m_lock = ceph::make_mutex("ManagedLock::m_lock");
7c673cae
FG
52
53 virtual void shutdown_handler(int r, Context *) = 0;
54 virtual void pre_acquire_lock_handler(Context *) = 0;
55 virtual void post_acquire_lock_handler(int, Context *) = 0;
56 virtual void pre_release_lock_handler(bool, Context *) = 0;
57 virtual void post_release_lock_handler(bool, int, Context *) = 0;
31f18b77 58 virtual void post_reacquire_lock_handler(int, Context *) = 0;
7c673cae
FG
59
60 MOCK_CONST_METHOD0(is_lock_owner, bool());
61
62 MOCK_METHOD1(shut_down, void(Context*));
63 MOCK_METHOD1(acquire_lock, void(Context*));
64
65 void set_state_uninitialized() {
66 }
67
68 MOCK_METHOD0(set_state_initializing, void());
69 MOCK_METHOD0(set_state_unlocked, void());
70 MOCK_METHOD0(set_state_waiting_for_lock, void());
71 MOCK_METHOD0(set_state_post_acquiring, void());
72
73 MOCK_CONST_METHOD0(is_state_shutdown, bool());
74 MOCK_CONST_METHOD0(is_state_acquiring, bool());
75 MOCK_CONST_METHOD0(is_state_post_acquiring, bool());
76 MOCK_CONST_METHOD0(is_state_releasing, bool());
77 MOCK_CONST_METHOD0(is_state_pre_releasing, bool());
78 MOCK_CONST_METHOD0(is_state_locked, bool());
79 MOCK_CONST_METHOD0(is_state_waiting_for_lock, bool());
80
81 MOCK_CONST_METHOD0(is_action_acquire_lock, bool());
82 MOCK_METHOD0(execute_next_action, void());
83
84};
85
86namespace exclusive_lock {
87
88using librbd::ImageWatcher;
89
90template<typename T>
91struct BaseRequest {
92 static std::list<T *> s_requests;
93 Context *on_lock_unlock = nullptr;
94 Context *on_finish = nullptr;
95
96 static T* create(MockExclusiveLockImageCtx &image_ctx,
97 Context *on_lock_unlock, Context *on_finish) {
11fdf7f2 98 ceph_assert(!s_requests.empty());
7c673cae
FG
99 T* req = s_requests.front();
100 req->on_lock_unlock = on_lock_unlock;
101 req->on_finish = on_finish;
102 s_requests.pop_front();
103 return req;
104 }
105
106 BaseRequest() {
107 s_requests.push_back(reinterpret_cast<T*>(this));
108 }
109};
110
111template<typename T>
112std::list<T *> BaseRequest<T>::s_requests;
113
f67539c2
TL
114template<>
115struct ImageDispatch<MockExclusiveLockImageCtx>
116 : public librbd::io::MockImageDispatch {
117 static ImageDispatch* s_instance;
118 static ImageDispatch* create(MockExclusiveLockImageCtx*) {
119 ceph_assert(s_instance != nullptr);
120 return s_instance;
121 }
122
123 void destroy() {
124 }
125
126 ImageDispatch() {
127 s_instance = this;
128 }
129
130 io::ImageDispatchLayer get_dispatch_layer() const override {
131 return io::IMAGE_DISPATCH_LAYER_EXCLUSIVE_LOCK;
132 }
133
134 MOCK_METHOD3(set_require_lock, void(bool, io::Direction, Context*));
135 MOCK_METHOD1(unset_require_lock, void(io::Direction));
136
137};
138
139ImageDispatch<MockExclusiveLockImageCtx>* ImageDispatch<MockExclusiveLockImageCtx>::s_instance = nullptr;
140
7c673cae
FG
141template <>
142struct PreAcquireRequest<MockExclusiveLockImageCtx> : public BaseRequest<PreAcquireRequest<MockExclusiveLockImageCtx> > {
143 static PreAcquireRequest<MockExclusiveLockImageCtx> *create(
144 MockExclusiveLockImageCtx &image_ctx, Context *on_finish) {
145 return BaseRequest::create(image_ctx, nullptr, on_finish);
146 }
147 MOCK_METHOD0(send, void());
148};
149
150template <>
151struct PostAcquireRequest<MockExclusiveLockImageCtx> : public BaseRequest<PostAcquireRequest<MockExclusiveLockImageCtx> > {
152 MOCK_METHOD0(send, void());
153};
154
155template <>
156struct PreReleaseRequest<MockExclusiveLockImageCtx> : public BaseRequest<PreReleaseRequest<MockExclusiveLockImageCtx> > {
157 static PreReleaseRequest<MockExclusiveLockImageCtx> *create(
f67539c2
TL
158 MockExclusiveLockImageCtx &image_ctx,
159 ImageDispatch<MockExclusiveLockImageCtx>* ImageDispatch,
160 bool shutting_down, AsyncOpTracker &async_op_tracker,
161 Context *on_finish) {
7c673cae
FG
162 return BaseRequest::create(image_ctx, nullptr, on_finish);
163 }
164 MOCK_METHOD0(send, void());
165};
166
167} // namespace exclusive_lock
168} // namespace librbd
169
170// template definitions
171#include "librbd/ExclusiveLock.cc"
172
173ACTION_P(FinishLockUnlock, request) {
174 if (request->on_lock_unlock != nullptr) {
175 request->on_lock_unlock->complete(0);
176 }
177}
178
179ACTION_P2(CompleteRequest, request, ret) {
180 request->on_finish->complete(ret);
181}
182
183namespace librbd {
184
185using ::testing::_;
186using ::testing::DoAll;
187using ::testing::Invoke;
188using ::testing::InSequence;
189using ::testing::Return;
f67539c2 190using ::testing::WithArg;
7c673cae
FG
191
192class TestMockExclusiveLock : public TestMockFixture {
193public:
194 typedef ManagedLock<MockExclusiveLockImageCtx> MockManagedLock;
195 typedef ExclusiveLock<MockExclusiveLockImageCtx> MockExclusiveLock;
f67539c2 196 typedef exclusive_lock::ImageDispatch<MockExclusiveLockImageCtx> MockImageDispatch;
7c673cae
FG
197 typedef exclusive_lock::PreAcquireRequest<MockExclusiveLockImageCtx> MockPreAcquireRequest;
198 typedef exclusive_lock::PostAcquireRequest<MockExclusiveLockImageCtx> MockPostAcquireRequest;
199 typedef exclusive_lock::PreReleaseRequest<MockExclusiveLockImageCtx> MockPreReleaseRequest;
200
f67539c2 201
9f95a23c
TL
202 void expect_set_state_initializing(MockManagedLock *managed_lock) {
203 EXPECT_CALL(*managed_lock, set_state_initializing());
7c673cae
FG
204 }
205
9f95a23c
TL
206 void expect_set_state_unlocked(MockManagedLock *managed_lock) {
207 EXPECT_CALL(*managed_lock, set_state_unlocked());
7c673cae
FG
208 }
209
9f95a23c
TL
210 void expect_set_state_waiting_for_lock(MockManagedLock *managed_lock) {
211 EXPECT_CALL(*managed_lock, set_state_waiting_for_lock());
7c673cae
FG
212 }
213
9f95a23c
TL
214 void expect_set_state_post_acquiring(MockManagedLock *managed_lock) {
215 EXPECT_CALL(*managed_lock, set_state_post_acquiring());
11fdf7f2
TL
216 }
217
9f95a23c
TL
218 void expect_is_state_acquiring(MockManagedLock *managed_lock, bool ret_val) {
219 EXPECT_CALL(*managed_lock, is_state_acquiring())
7c673cae
FG
220 .WillOnce(Return(ret_val));
221 }
222
9f95a23c 223 void expect_is_state_waiting_for_lock(MockManagedLock *managed_lock,
7c673cae 224 bool ret_val) {
9f95a23c 225 EXPECT_CALL(*managed_lock, is_state_waiting_for_lock())
7c673cae
FG
226 .WillOnce(Return(ret_val));
227 }
228
9f95a23c 229 void expect_is_state_pre_releasing(MockManagedLock *managed_lock,
7c673cae 230 bool ret_val) {
9f95a23c 231 EXPECT_CALL(*managed_lock, is_state_pre_releasing())
7c673cae
FG
232 .WillOnce(Return(ret_val));
233 }
234
9f95a23c
TL
235 void expect_is_state_releasing(MockManagedLock *managed_lock, bool ret_val) {
236 EXPECT_CALL(*managed_lock, is_state_releasing())
7c673cae
FG
237 .WillOnce(Return(ret_val));
238 }
239
9f95a23c
TL
240 void expect_is_state_locked(MockManagedLock *managed_lock, bool ret_val) {
241 EXPECT_CALL(*managed_lock, is_state_locked())
7c673cae
FG
242 .WillOnce(Return(ret_val));
243 }
244
9f95a23c
TL
245 void expect_is_state_shutdown(MockManagedLock *managed_lock, bool ret_val) {
246 EXPECT_CALL(*managed_lock, is_state_shutdown())
7c673cae
FG
247 .WillOnce(Return(ret_val));
248 }
249
9f95a23c 250 void expect_is_action_acquire_lock(MockManagedLock *managed_lock,
7c673cae 251 bool ret_val) {
9f95a23c 252 EXPECT_CALL(*managed_lock, is_action_acquire_lock())
7c673cae
FG
253 .WillOnce(Return(ret_val));
254 }
255
f67539c2
TL
256 void expect_set_require_lock(MockImageDispatch &mock_image_dispatch,
257 bool init_shutdown, io::Direction direction) {
258 EXPECT_CALL(mock_image_dispatch, set_require_lock(init_shutdown,
259 direction, _))
260 .WillOnce(WithArg<2>(Invoke([](Context* ctx) { ctx->complete(0); })));
7c673cae
FG
261 }
262
f67539c2
TL
263 void expect_set_require_lock(MockExclusiveLockImageCtx &mock_image_ctx,
264 MockImageDispatch &mock_image_dispatch,
265 bool init_shutdown) {
224ce89b 266 if (mock_image_ctx.clone_copy_on_read ||
f67539c2
TL
267 (mock_image_ctx.features & RBD_FEATURE_JOURNALING) != 0 ||
268 is_rbd_pwl_enabled(mock_image_ctx.cct)) {
269 expect_set_require_lock(mock_image_dispatch, init_shutdown,
270 io::DIRECTION_BOTH);
224ce89b 271 } else {
f67539c2
TL
272 expect_set_require_lock(mock_image_dispatch, init_shutdown,
273 io::DIRECTION_WRITE);
7c673cae
FG
274 }
275 }
276
f67539c2
TL
277 void expect_unset_require_lock(MockImageDispatch &mock_image_dispatch) {
278 EXPECT_CALL(mock_image_dispatch, unset_require_lock(io::DIRECTION_BOTH));
279 }
280
281 void expect_register_dispatch(MockExclusiveLockImageCtx &mock_image_ctx) {
282 EXPECT_CALL(*mock_image_ctx.io_image_dispatcher, register_dispatch(_));
283 }
284
285 void expect_shut_down_dispatch(MockExclusiveLockImageCtx &mock_image_ctx) {
286 EXPECT_CALL(*mock_image_ctx.io_image_dispatcher, shut_down_dispatch(_, _))
287 .WillOnce(WithArg<1>(Invoke([](Context* ctx) {
288 ctx->complete(0);
289 })));
7c673cae
FG
290 }
291
292 void expect_prepare_lock_complete(MockExclusiveLockImageCtx &mock_image_ctx) {
293 EXPECT_CALL(*mock_image_ctx.state, handle_prepare_lock_complete());
294 }
295
296 void expect_pre_acquire_request(MockPreAcquireRequest &pre_acquire_request,
297 int r) {
298 EXPECT_CALL(pre_acquire_request, send())
299 .WillOnce(CompleteRequest(&pre_acquire_request, r));
300 }
301
9f95a23c 302 void expect_post_acquire_request(MockExclusiveLock *mock_exclusive_lock,
11fdf7f2 303 MockPostAcquireRequest &post_acquire_request,
7c673cae
FG
304 int r) {
305 EXPECT_CALL(post_acquire_request, send())
11fdf7f2
TL
306 .WillOnce(DoAll(FinishLockUnlock(&post_acquire_request),
307 CompleteRequest(&post_acquire_request, r)));
308 expect_set_state_post_acquiring(mock_exclusive_lock);
7c673cae
FG
309 }
310
311 void expect_pre_release_request(MockPreReleaseRequest &pre_release_request,
312 int r) {
313 EXPECT_CALL(pre_release_request, send())
314 .WillOnce(CompleteRequest(&pre_release_request, r));
315 }
316
317 void expect_notify_request_lock(MockExclusiveLockImageCtx &mock_image_ctx,
9f95a23c 318 MockExclusiveLock *mock_exclusive_lock) {
7c673cae
FG
319 EXPECT_CALL(*mock_image_ctx.image_watcher, notify_request_lock());
320 }
321
322 void expect_notify_acquired_lock(MockExclusiveLockImageCtx &mock_image_ctx) {
323 EXPECT_CALL(*mock_image_ctx.image_watcher, notify_acquired_lock())
324 .Times(1);
325 }
326
327 void expect_notify_released_lock(MockExclusiveLockImageCtx &mock_image_ctx) {
328 EXPECT_CALL(*mock_image_ctx.image_watcher, notify_released_lock())
329 .Times(1);
330 }
331
7c673cae
FG
332 void expect_flush_notifies(MockExclusiveLockImageCtx &mock_image_ctx) {
333 EXPECT_CALL(*mock_image_ctx.image_watcher, flush(_))
334 .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
335 }
336
9f95a23c
TL
337 void expect_shut_down(MockManagedLock *managed_lock) {
338 EXPECT_CALL(*managed_lock, shut_down(_))
f67539c2 339 .WillOnce(CompleteContext(0, static_cast<asio::ContextWQ*>(nullptr)));
7c673cae
FG
340 }
341
92f5a8d4
TL
342 void expect_accept_blocked_request(
343 MockExclusiveLockImageCtx &mock_image_ctx,
344 exclusive_lock::MockPolicy &policy,
345 exclusive_lock::OperationRequestType request_type, bool value) {
346 EXPECT_CALL(mock_image_ctx, get_exclusive_lock_policy())
347 .WillOnce(Return(&policy));
348 EXPECT_CALL(policy, accept_blocked_request(request_type))
349 .WillOnce(Return(value));
350 }
351
7c673cae 352 int when_init(MockExclusiveLockImageCtx &mock_image_ctx,
9f95a23c 353 MockExclusiveLock *exclusive_lock) {
7c673cae
FG
354 C_SaferCond ctx;
355 {
9f95a23c
TL
356 std::unique_lock owner_locker{mock_image_ctx.owner_lock};
357 exclusive_lock->init(mock_image_ctx.features, &ctx);
7c673cae
FG
358 }
359 return ctx.wait();
360 }
361
9f95a23c 362 int when_pre_acquire_lock_handler(MockManagedLock *managed_lock) {
7c673cae 363 C_SaferCond ctx;
9f95a23c 364 managed_lock->pre_acquire_lock_handler(&ctx);
7c673cae
FG
365 return ctx.wait();
366 }
367
9f95a23c 368 int when_post_acquire_lock_handler(MockManagedLock *managed_lock, int r) {
7c673cae 369 C_SaferCond ctx;
9f95a23c 370 managed_lock->post_acquire_lock_handler(r, &ctx);
7c673cae
FG
371 return ctx.wait();
372 }
373
9f95a23c 374 int when_pre_release_lock_handler(MockManagedLock *managed_lock,
7c673cae
FG
375 bool shutting_down) {
376 C_SaferCond ctx;
9f95a23c 377 managed_lock->pre_release_lock_handler(shutting_down, &ctx);
7c673cae
FG
378 return ctx.wait();
379 }
380
9f95a23c 381 int when_post_release_lock_handler(MockManagedLock *managed_lock,
7c673cae
FG
382 bool shutting_down, int r) {
383 C_SaferCond ctx;
9f95a23c 384 managed_lock->post_release_lock_handler(shutting_down, r, &ctx);
7c673cae
FG
385 return ctx.wait();
386 }
387
9f95a23c 388 int when_post_reacquire_lock_handler(MockManagedLock *managed_lock, int r) {
31f18b77 389 C_SaferCond ctx;
9f95a23c 390 managed_lock->post_reacquire_lock_handler(r, &ctx);
31f18b77
FG
391 return ctx.wait();
392 }
393
7c673cae 394 int when_shut_down(MockExclusiveLockImageCtx &mock_image_ctx,
9f95a23c 395 MockExclusiveLock *exclusive_lock) {
7c673cae
FG
396 C_SaferCond ctx;
397 {
9f95a23c
TL
398 std::unique_lock owner_locker{mock_image_ctx.owner_lock};
399 exclusive_lock->shut_down(&ctx);
7c673cae
FG
400 }
401 return ctx.wait();
402 }
403
404 bool is_lock_owner(MockExclusiveLockImageCtx &mock_image_ctx,
9f95a23c
TL
405 MockExclusiveLock *exclusive_lock) {
406 std::shared_lock owner_locker{mock_image_ctx.owner_lock};
407 return exclusive_lock->is_lock_owner();
7c673cae
FG
408 }
409};
410
411TEST_F(TestMockExclusiveLock, StateTransitions) {
412 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
413
414 librbd::ImageCtx *ictx;
415 ASSERT_EQ(0, open_image(m_image_name, &ictx));
416
417 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
9f95a23c 418 MockExclusiveLock *exclusive_lock = new MockExclusiveLock(mock_image_ctx);
7c673cae
FG
419 expect_op_work_queue(mock_image_ctx);
420
9f95a23c
TL
421 BOOST_SCOPE_EXIT(&exclusive_lock) {
422 exclusive_lock->put();
423 } BOOST_SCOPE_EXIT_END
424
7c673cae
FG
425 InSequence seq;
426 expect_set_state_initializing(exclusive_lock);
f67539c2
TL
427 MockImageDispatch mock_image_dispatch;
428 expect_register_dispatch(mock_image_ctx);
429 expect_set_require_lock(mock_image_ctx, mock_image_dispatch, true);
7c673cae
FG
430 expect_set_state_unlocked(exclusive_lock);
431 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
432
433 // (try) acquire lock
434 MockPreAcquireRequest try_lock_pre_acquire;
435 expect_pre_acquire_request(try_lock_pre_acquire, 0);
436 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
437
438 MockPostAcquireRequest try_lock_post_acquire;
11fdf7f2 439 expect_post_acquire_request(exclusive_lock, try_lock_post_acquire, 0);
7c673cae
FG
440 expect_is_state_acquiring(exclusive_lock, true);
441 expect_notify_acquired_lock(mock_image_ctx);
f67539c2 442 expect_unset_require_lock(mock_image_dispatch);
7c673cae
FG
443 ASSERT_EQ(0, when_post_acquire_lock_handler(exclusive_lock, 0));
444
445 // release lock
446 MockPreReleaseRequest pre_request_release;
447 expect_pre_release_request(pre_request_release, 0);
448 ASSERT_EQ(0, when_pre_release_lock_handler(exclusive_lock, false));
449
450 expect_is_state_pre_releasing(exclusive_lock, false);
451 expect_is_state_releasing(exclusive_lock, true);
452 expect_notify_released_lock(mock_image_ctx);
7c673cae
FG
453 ASSERT_EQ(0, when_post_release_lock_handler(exclusive_lock, false, 0));
454
455 // (try) acquire lock
456 MockPreAcquireRequest request_lock_pre_acquire;
457 expect_pre_acquire_request(request_lock_pre_acquire, 0);
458 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
459
460 MockPostAcquireRequest request_lock_post_acquire;
11fdf7f2 461 expect_post_acquire_request(exclusive_lock, request_lock_post_acquire, 0);
7c673cae
FG
462 expect_is_state_acquiring(exclusive_lock, true);
463 expect_notify_acquired_lock(mock_image_ctx);
f67539c2 464 expect_unset_require_lock(mock_image_dispatch);
7c673cae
FG
465 ASSERT_EQ(0, when_post_acquire_lock_handler(exclusive_lock, 0));
466
467 // shut down (and release)
468 expect_shut_down(exclusive_lock);
469 expect_is_state_waiting_for_lock(exclusive_lock, false);
470 ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock));
471
472 MockPreReleaseRequest shutdown_pre_release;
473 expect_pre_release_request(shutdown_pre_release, 0);
474 ASSERT_EQ(0, when_pre_release_lock_handler(exclusive_lock, true));
475
f67539c2 476 expect_shut_down_dispatch(mock_image_ctx);
7c673cae
FG
477 expect_notify_released_lock(mock_image_ctx);
478 ASSERT_EQ(0, when_post_release_lock_handler(exclusive_lock, true, 0));
479}
480
481TEST_F(TestMockExclusiveLock, TryLockAlreadyLocked) {
482 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
483
484 librbd::ImageCtx *ictx;
485 ASSERT_EQ(0, open_image(m_image_name, &ictx));
486
487 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
9f95a23c 488 MockExclusiveLock *exclusive_lock = new MockExclusiveLock(mock_image_ctx);
7c673cae
FG
489 expect_op_work_queue(mock_image_ctx);
490
9f95a23c
TL
491 BOOST_SCOPE_EXIT(&exclusive_lock) {
492 exclusive_lock->put();
493 } BOOST_SCOPE_EXIT_END
494
7c673cae 495 expect_set_state_initializing(exclusive_lock);
f67539c2
TL
496 MockImageDispatch mock_image_dispatch;
497 expect_register_dispatch(mock_image_ctx);
498 expect_set_require_lock(mock_image_ctx, mock_image_dispatch, true);
7c673cae
FG
499 expect_set_state_unlocked(exclusive_lock);
500 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
501
502 // try acquire lock
503 MockPreAcquireRequest try_lock_pre_acquire;
504 expect_pre_acquire_request(try_lock_pre_acquire, 0);
505 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
506
507 expect_is_state_acquiring(exclusive_lock, true);
508 expect_prepare_lock_complete(mock_image_ctx);
509 expect_is_action_acquire_lock(exclusive_lock, false);
510 ASSERT_EQ(0, when_post_acquire_lock_handler(exclusive_lock, -EAGAIN));
511}
512
513TEST_F(TestMockExclusiveLock, TryLockError) {
514 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
515
516 librbd::ImageCtx *ictx;
517 ASSERT_EQ(0, open_image(m_image_name, &ictx));
518
519 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
9f95a23c 520 MockExclusiveLock *exclusive_lock = new MockExclusiveLock(mock_image_ctx);
7c673cae
FG
521 expect_op_work_queue(mock_image_ctx);
522
9f95a23c
TL
523 BOOST_SCOPE_EXIT(&exclusive_lock) {
524 exclusive_lock->put();
525 } BOOST_SCOPE_EXIT_END
526
7c673cae
FG
527 InSequence seq;
528 expect_set_state_initializing(exclusive_lock);
f67539c2
TL
529 MockImageDispatch mock_image_dispatch;
530 expect_register_dispatch(mock_image_ctx);
531 expect_set_require_lock(mock_image_ctx, mock_image_dispatch, true);
7c673cae
FG
532 expect_set_state_unlocked(exclusive_lock);
533 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
534
535 // try acquire lock
536 MockPreAcquireRequest try_lock_pre_acquire;
537 expect_pre_acquire_request(try_lock_pre_acquire, 0);
538 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
539
540 expect_is_state_acquiring(exclusive_lock, true);
541 expect_prepare_lock_complete(mock_image_ctx);
542 expect_is_action_acquire_lock(exclusive_lock, false);
543 ASSERT_EQ(-EBUSY, when_post_acquire_lock_handler(exclusive_lock, -EBUSY));
544}
545
546TEST_F(TestMockExclusiveLock, AcquireLockAlreadyLocked) {
547 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
548
549 librbd::ImageCtx *ictx;
550 ASSERT_EQ(0, open_image(m_image_name, &ictx));
551
552 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
9f95a23c 553 MockExclusiveLock *exclusive_lock = new MockExclusiveLock(mock_image_ctx);
7c673cae
FG
554 expect_op_work_queue(mock_image_ctx);
555
9f95a23c
TL
556 BOOST_SCOPE_EXIT(&exclusive_lock) {
557 exclusive_lock->put();
558 } BOOST_SCOPE_EXIT_END
559
7c673cae
FG
560 InSequence seq;
561 expect_set_state_initializing(exclusive_lock);
f67539c2
TL
562 MockImageDispatch mock_image_dispatch;
563 expect_register_dispatch(mock_image_ctx);
564 expect_set_require_lock(mock_image_ctx, mock_image_dispatch, true);
7c673cae
FG
565 expect_set_state_unlocked(exclusive_lock);
566 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
567
568 // acquire lock
569 MockPreAcquireRequest try_lock_pre_acquire;
570 expect_pre_acquire_request(try_lock_pre_acquire, 0);
571 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
572
573 expect_is_state_acquiring(exclusive_lock, true);
574 expect_prepare_lock_complete(mock_image_ctx);
575 expect_is_action_acquire_lock(exclusive_lock, true);
576 expect_set_state_waiting_for_lock(exclusive_lock);
577 expect_notify_request_lock(mock_image_ctx, exclusive_lock);
578 ASSERT_EQ(-ECANCELED, when_post_acquire_lock_handler(exclusive_lock,
579 -EAGAIN));
580}
581
582TEST_F(TestMockExclusiveLock, AcquireLockBusy) {
583 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
584
585 librbd::ImageCtx *ictx;
586 ASSERT_EQ(0, open_image(m_image_name, &ictx));
587
588 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
9f95a23c 589 MockExclusiveLock *exclusive_lock = new MockExclusiveLock(mock_image_ctx);
7c673cae
FG
590 expect_op_work_queue(mock_image_ctx);
591
9f95a23c
TL
592 BOOST_SCOPE_EXIT(&exclusive_lock) {
593 exclusive_lock->put();
594 } BOOST_SCOPE_EXIT_END
595
7c673cae
FG
596 InSequence seq;
597 expect_set_state_initializing(exclusive_lock);
f67539c2
TL
598 MockImageDispatch mock_image_dispatch;
599 expect_register_dispatch(mock_image_ctx);
600 expect_set_require_lock(mock_image_ctx, mock_image_dispatch, true);
7c673cae
FG
601 expect_set_state_unlocked(exclusive_lock);
602 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
603
604 // acquire lock
605 MockPreAcquireRequest try_lock_pre_acquire;
606 expect_pre_acquire_request(try_lock_pre_acquire, 0);
607 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
608
609 expect_is_state_acquiring(exclusive_lock, true);
610 expect_prepare_lock_complete(mock_image_ctx);
611 expect_is_action_acquire_lock(exclusive_lock, true);
612 expect_set_state_waiting_for_lock(exclusive_lock);
613 expect_notify_request_lock(mock_image_ctx, exclusive_lock);
614 ASSERT_EQ(-ECANCELED, when_post_acquire_lock_handler(exclusive_lock,
615 -EBUSY));
616}
617
618TEST_F(TestMockExclusiveLock, AcquireLockError) {
619 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
620
621 librbd::ImageCtx *ictx;
622 ASSERT_EQ(0, open_image(m_image_name, &ictx));
623
624 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
9f95a23c 625 MockExclusiveLock *exclusive_lock = new MockExclusiveLock(mock_image_ctx);
7c673cae
FG
626 expect_op_work_queue(mock_image_ctx);
627
9f95a23c
TL
628 BOOST_SCOPE_EXIT(&exclusive_lock) {
629 exclusive_lock->put();
630 } BOOST_SCOPE_EXIT_END
631
7c673cae
FG
632 InSequence seq;
633 expect_set_state_initializing(exclusive_lock);
f67539c2
TL
634 MockImageDispatch mock_image_dispatch;
635 expect_register_dispatch(mock_image_ctx);
636 expect_set_require_lock(mock_image_ctx, mock_image_dispatch, true);
7c673cae
FG
637 expect_set_state_unlocked(exclusive_lock);
638 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
639
640 // acquire lock
641 MockPreAcquireRequest try_lock_pre_acquire;
642 expect_pre_acquire_request(try_lock_pre_acquire, 0);
643 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
644
645 expect_is_state_acquiring(exclusive_lock, true);
646 expect_prepare_lock_complete(mock_image_ctx);
647 expect_is_action_acquire_lock(exclusive_lock, true);
f67539c2
TL
648 ASSERT_EQ(-EBLOCKLISTED, when_post_acquire_lock_handler(exclusive_lock,
649 -EBLOCKLISTED));
7c673cae
FG
650}
651
652TEST_F(TestMockExclusiveLock, PostAcquireLockError) {
653 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
654
655 librbd::ImageCtx *ictx;
656 ASSERT_EQ(0, open_image(m_image_name, &ictx));
657
658 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
9f95a23c 659 MockExclusiveLock *exclusive_lock = new MockExclusiveLock(mock_image_ctx);
7c673cae
FG
660 expect_op_work_queue(mock_image_ctx);
661
9f95a23c
TL
662 BOOST_SCOPE_EXIT(&exclusive_lock) {
663 exclusive_lock->put();
664 } BOOST_SCOPE_EXIT_END
665
7c673cae
FG
666 InSequence seq;
667 expect_set_state_initializing(exclusive_lock);
f67539c2
TL
668 MockImageDispatch mock_image_dispatch;
669 expect_register_dispatch(mock_image_ctx);
670 expect_set_require_lock(mock_image_ctx, mock_image_dispatch, true);
7c673cae
FG
671 expect_set_state_unlocked(exclusive_lock);
672 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
673
674 // (try) acquire lock
675 MockPreAcquireRequest request_lock_pre_acquire;
676 expect_pre_acquire_request(request_lock_pre_acquire, 0);
677 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
678
679 MockPostAcquireRequest request_lock_post_acquire;
11fdf7f2
TL
680 expect_post_acquire_request(exclusive_lock, request_lock_post_acquire,
681 -EPERM);
7c673cae
FG
682 expect_is_state_acquiring(exclusive_lock, true);
683 ASSERT_EQ(-EPERM, when_post_acquire_lock_handler(exclusive_lock, 0));
684}
685
686TEST_F(TestMockExclusiveLock, PreReleaseLockError) {
687 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
688
689 librbd::ImageCtx *ictx;
690 ASSERT_EQ(0, open_image(m_image_name, &ictx));
691
692 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
9f95a23c 693 MockExclusiveLock *exclusive_lock = new MockExclusiveLock(mock_image_ctx);
7c673cae
FG
694 expect_op_work_queue(mock_image_ctx);
695
9f95a23c
TL
696 BOOST_SCOPE_EXIT(&exclusive_lock) {
697 exclusive_lock->put();
698 } BOOST_SCOPE_EXIT_END
699
7c673cae
FG
700 InSequence seq;
701 expect_set_state_initializing(exclusive_lock);
f67539c2
TL
702 MockImageDispatch mock_image_dispatch;
703 expect_register_dispatch(mock_image_ctx);
704 expect_set_require_lock(mock_image_ctx, mock_image_dispatch, true);
7c673cae
FG
705 expect_set_state_unlocked(exclusive_lock);
706 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
707
708 // release lock
709 MockPreReleaseRequest pre_request_release;
710 expect_pre_release_request(pre_request_release, -EINVAL);
711 ASSERT_EQ(-EINVAL, when_pre_release_lock_handler(exclusive_lock, false));
712
713 expect_is_state_pre_releasing(exclusive_lock, true);
714 ASSERT_EQ(-EINVAL, when_post_release_lock_handler(exclusive_lock, false,
715 -EINVAL));
716}
717
31f18b77
FG
718TEST_F(TestMockExclusiveLock, ReacquireLock) {
719 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
720
721 librbd::ImageCtx *ictx;
722 ASSERT_EQ(0, open_image(m_image_name, &ictx));
723
724 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
9f95a23c 725 MockExclusiveLock *exclusive_lock = new MockExclusiveLock(mock_image_ctx);
31f18b77
FG
726 expect_op_work_queue(mock_image_ctx);
727
9f95a23c
TL
728 BOOST_SCOPE_EXIT(&exclusive_lock) {
729 exclusive_lock->put();
730 } BOOST_SCOPE_EXIT_END
731
31f18b77
FG
732 InSequence seq;
733 expect_set_state_initializing(exclusive_lock);
f67539c2
TL
734 MockImageDispatch mock_image_dispatch;
735 expect_register_dispatch(mock_image_ctx);
736 expect_set_require_lock(mock_image_ctx, mock_image_dispatch, true);
31f18b77
FG
737 expect_set_state_unlocked(exclusive_lock);
738 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
739
740 // (try) acquire lock
741 MockPreAcquireRequest try_lock_pre_acquire;
742 expect_pre_acquire_request(try_lock_pre_acquire, 0);
743 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
744
745 MockPostAcquireRequest try_lock_post_acquire;
11fdf7f2 746 expect_post_acquire_request(exclusive_lock, try_lock_post_acquire, 0);
31f18b77
FG
747 expect_is_state_acquiring(exclusive_lock, true);
748 expect_notify_acquired_lock(mock_image_ctx);
f67539c2 749 expect_unset_require_lock(mock_image_dispatch);
31f18b77
FG
750 ASSERT_EQ(0, when_post_acquire_lock_handler(exclusive_lock, 0));
751
752 // reacquire lock
753 expect_notify_acquired_lock(mock_image_ctx);
754 ASSERT_EQ(0, when_post_reacquire_lock_handler(exclusive_lock, 0));
755
756 // shut down (and release)
757 expect_shut_down(exclusive_lock);
758 expect_is_state_waiting_for_lock(exclusive_lock, false);
759 ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock));
760
761 MockPreReleaseRequest shutdown_pre_release;
762 expect_pre_release_request(shutdown_pre_release, 0);
763 ASSERT_EQ(0, when_pre_release_lock_handler(exclusive_lock, true));
764
f67539c2 765 expect_shut_down_dispatch(mock_image_ctx);
31f18b77
FG
766 expect_notify_released_lock(mock_image_ctx);
767 ASSERT_EQ(0, when_post_release_lock_handler(exclusive_lock, true, 0));
768}
769
7c673cae
FG
770TEST_F(TestMockExclusiveLock, BlockRequests) {
771 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
772
773 librbd::ImageCtx *ictx;
774 ASSERT_EQ(0, open_image(m_image_name, &ictx));
775
776 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
9f95a23c
TL
777
778 MockExclusiveLock *exclusive_lock = new MockExclusiveLock(mock_image_ctx);
92f5a8d4 779 exclusive_lock::MockPolicy mock_exclusive_lock_policy;
7c673cae
FG
780
781 expect_op_work_queue(mock_image_ctx);
782
9f95a23c
TL
783 BOOST_SCOPE_EXIT(&exclusive_lock) {
784 exclusive_lock->put();
785 } BOOST_SCOPE_EXIT_END
786
7c673cae
FG
787 InSequence seq;
788 expect_set_state_initializing(exclusive_lock);
f67539c2
TL
789 MockImageDispatch mock_image_dispatch;
790 expect_register_dispatch(mock_image_ctx);
791 expect_set_require_lock(mock_image_ctx, mock_image_dispatch, true);
7c673cae
FG
792 expect_set_state_unlocked(exclusive_lock);
793 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
794
795 int ret_val;
796 expect_is_state_shutdown(exclusive_lock, false);
797 expect_is_state_locked(exclusive_lock, true);
9f95a23c 798 ASSERT_TRUE(exclusive_lock->accept_request(
92f5a8d4 799 exclusive_lock::OPERATION_REQUEST_TYPE_GENERAL, &ret_val));
7c673cae
FG
800 ASSERT_EQ(0, ret_val);
801
9f95a23c 802 exclusive_lock->block_requests(-EROFS);
7c673cae
FG
803 expect_is_state_shutdown(exclusive_lock, false);
804 expect_is_state_locked(exclusive_lock, true);
92f5a8d4
TL
805 expect_accept_blocked_request(mock_image_ctx, mock_exclusive_lock_policy,
806 exclusive_lock::OPERATION_REQUEST_TYPE_GENERAL,
807 false);
9f95a23c 808 ASSERT_FALSE(exclusive_lock->accept_request(
92f5a8d4 809 exclusive_lock::OPERATION_REQUEST_TYPE_GENERAL, &ret_val));
7c673cae
FG
810 ASSERT_EQ(-EROFS, ret_val);
811
92f5a8d4
TL
812 expect_is_state_shutdown(exclusive_lock, false);
813 expect_is_state_locked(exclusive_lock, true);
814 expect_accept_blocked_request(
815 mock_image_ctx, mock_exclusive_lock_policy,
816 exclusive_lock::OPERATION_REQUEST_TYPE_TRASH_SNAP_REMOVE, true);
9f95a23c 817 ASSERT_TRUE(exclusive_lock->accept_request(
92f5a8d4
TL
818 exclusive_lock::OPERATION_REQUEST_TYPE_TRASH_SNAP_REMOVE,
819 &ret_val));
820 ASSERT_EQ(0, ret_val);
821
9f95a23c 822 exclusive_lock->unblock_requests();
7c673cae
FG
823 expect_is_state_shutdown(exclusive_lock, false);
824 expect_is_state_locked(exclusive_lock, true);
9f95a23c 825 ASSERT_TRUE(exclusive_lock->accept_request(
92f5a8d4 826 exclusive_lock::OPERATION_REQUEST_TYPE_GENERAL, &ret_val));
7c673cae
FG
827 ASSERT_EQ(0, ret_val);
828}
829
830} // namespace librbd
831