]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/librbd/test_mock_ExclusiveLock.cc
update sources to v12.1.1
[ceph.git] / ceph / src / test / librbd / test_mock_ExclusiveLock.cc
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"
7 #include "librbd/ExclusiveLock.h"
8 #include "librbd/ManagedLock.h"
9 #include "librbd/exclusive_lock/PreAcquireRequest.h"
10 #include "librbd/exclusive_lock/PostAcquireRequest.h"
11 #include "librbd/exclusive_lock/PreReleaseRequest.h"
12 #include "gmock/gmock.h"
13 #include "gtest/gtest.h"
14 #include <list>
15
16 namespace librbd {
17
18 namespace {
19
20 struct MockExclusiveLockImageCtx : public MockImageCtx {
21 ContextWQ *op_work_queue;
22
23 MockExclusiveLockImageCtx(ImageCtx &image_ctx) : MockImageCtx(image_ctx) {
24 op_work_queue = image_ctx.op_work_queue;
25 }
26 };
27
28 } // anonymous namespace
29
30 namespace watcher {
31 template <>
32 struct Traits<MockExclusiveLockImageCtx> {
33 typedef librbd::MockImageWatcher Watcher;
34 };
35 }
36
37 template <>
38 struct ManagedLock<MockExclusiveLockImageCtx> {
39 ManagedLock(librados::IoCtx& ioctx, ContextWQ *work_queue,
40 const std::string& oid, librbd::MockImageWatcher *watcher,
41 managed_lock::Mode mode, bool blacklist_on_break_lock,
42 uint32_t blacklist_expire_seconds)
43 : m_lock("ManagedLock::m_lock") {
44 }
45
46 virtual ~ManagedLock() = default;
47
48 mutable Mutex m_lock;
49
50 virtual void shutdown_handler(int r, Context *) = 0;
51 virtual void pre_acquire_lock_handler(Context *) = 0;
52 virtual void post_acquire_lock_handler(int, Context *) = 0;
53 virtual void pre_release_lock_handler(bool, Context *) = 0;
54 virtual void post_release_lock_handler(bool, int, Context *) = 0;
55 virtual void post_reacquire_lock_handler(int, Context *) = 0;
56
57 MOCK_CONST_METHOD0(is_lock_owner, bool());
58
59 MOCK_METHOD1(shut_down, void(Context*));
60 MOCK_METHOD1(acquire_lock, void(Context*));
61
62 void set_state_uninitialized() {
63 }
64
65 MOCK_METHOD0(set_state_initializing, void());
66 MOCK_METHOD0(set_state_unlocked, void());
67 MOCK_METHOD0(set_state_waiting_for_lock, void());
68 MOCK_METHOD0(set_state_post_acquiring, void());
69
70 MOCK_CONST_METHOD0(is_state_shutdown, bool());
71 MOCK_CONST_METHOD0(is_state_acquiring, bool());
72 MOCK_CONST_METHOD0(is_state_post_acquiring, bool());
73 MOCK_CONST_METHOD0(is_state_releasing, bool());
74 MOCK_CONST_METHOD0(is_state_pre_releasing, bool());
75 MOCK_CONST_METHOD0(is_state_locked, bool());
76 MOCK_CONST_METHOD0(is_state_waiting_for_lock, bool());
77
78 MOCK_CONST_METHOD0(is_action_acquire_lock, bool());
79 MOCK_METHOD0(execute_next_action, void());
80
81 };
82
83 namespace exclusive_lock {
84
85 using librbd::ImageWatcher;
86
87 template<typename T>
88 struct BaseRequest {
89 static std::list<T *> s_requests;
90 Context *on_lock_unlock = nullptr;
91 Context *on_finish = nullptr;
92
93 static T* create(MockExclusiveLockImageCtx &image_ctx,
94 Context *on_lock_unlock, Context *on_finish) {
95 assert(!s_requests.empty());
96 T* req = s_requests.front();
97 req->on_lock_unlock = on_lock_unlock;
98 req->on_finish = on_finish;
99 s_requests.pop_front();
100 return req;
101 }
102
103 BaseRequest() {
104 s_requests.push_back(reinterpret_cast<T*>(this));
105 }
106 };
107
108 template<typename T>
109 std::list<T *> BaseRequest<T>::s_requests;
110
111 template <>
112 struct PreAcquireRequest<MockExclusiveLockImageCtx> : public BaseRequest<PreAcquireRequest<MockExclusiveLockImageCtx> > {
113 static PreAcquireRequest<MockExclusiveLockImageCtx> *create(
114 MockExclusiveLockImageCtx &image_ctx, Context *on_finish) {
115 return BaseRequest::create(image_ctx, nullptr, on_finish);
116 }
117 MOCK_METHOD0(send, void());
118 };
119
120 template <>
121 struct PostAcquireRequest<MockExclusiveLockImageCtx> : public BaseRequest<PostAcquireRequest<MockExclusiveLockImageCtx> > {
122 MOCK_METHOD0(send, void());
123 };
124
125 template <>
126 struct PreReleaseRequest<MockExclusiveLockImageCtx> : public BaseRequest<PreReleaseRequest<MockExclusiveLockImageCtx> > {
127 static PreReleaseRequest<MockExclusiveLockImageCtx> *create(
128 MockExclusiveLockImageCtx &image_ctx, bool shutting_down,
129 AsyncOpTracker &async_op_tracker, Context *on_finish) {
130 return BaseRequest::create(image_ctx, nullptr, on_finish);
131 }
132 MOCK_METHOD0(send, void());
133 };
134
135 } // namespace exclusive_lock
136 } // namespace librbd
137
138 // template definitions
139 #include "librbd/ExclusiveLock.cc"
140
141 ACTION_P(FinishLockUnlock, request) {
142 if (request->on_lock_unlock != nullptr) {
143 request->on_lock_unlock->complete(0);
144 }
145 }
146
147 ACTION_P2(CompleteRequest, request, ret) {
148 request->on_finish->complete(ret);
149 }
150
151 namespace librbd {
152
153 using ::testing::_;
154 using ::testing::DoAll;
155 using ::testing::Invoke;
156 using ::testing::InSequence;
157 using ::testing::Return;
158
159 class TestMockExclusiveLock : public TestMockFixture {
160 public:
161 typedef ManagedLock<MockExclusiveLockImageCtx> MockManagedLock;
162 typedef ExclusiveLock<MockExclusiveLockImageCtx> MockExclusiveLock;
163 typedef exclusive_lock::PreAcquireRequest<MockExclusiveLockImageCtx> MockPreAcquireRequest;
164 typedef exclusive_lock::PostAcquireRequest<MockExclusiveLockImageCtx> MockPostAcquireRequest;
165 typedef exclusive_lock::PreReleaseRequest<MockExclusiveLockImageCtx> MockPreReleaseRequest;
166
167 void expect_set_state_initializing(MockManagedLock &managed_lock) {
168 EXPECT_CALL(managed_lock, set_state_initializing());
169 }
170
171 void expect_set_state_unlocked(MockManagedLock &managed_lock) {
172 EXPECT_CALL(managed_lock, set_state_unlocked());
173 }
174
175 void expect_set_state_waiting_for_lock(MockManagedLock &managed_lock) {
176 EXPECT_CALL(managed_lock, set_state_waiting_for_lock());
177 }
178
179 void expect_is_state_acquiring(MockManagedLock &managed_lock, bool ret_val) {
180 EXPECT_CALL(managed_lock, is_state_acquiring())
181 .WillOnce(Return(ret_val));
182 }
183
184 void expect_is_state_waiting_for_lock(MockManagedLock &managed_lock,
185 bool ret_val) {
186 EXPECT_CALL(managed_lock, is_state_waiting_for_lock())
187 .WillOnce(Return(ret_val));
188 }
189
190 void expect_is_state_pre_releasing(MockManagedLock &managed_lock,
191 bool ret_val) {
192 EXPECT_CALL(managed_lock, is_state_pre_releasing())
193 .WillOnce(Return(ret_val));
194 }
195
196 void expect_is_state_releasing(MockManagedLock &managed_lock, bool ret_val) {
197 EXPECT_CALL(managed_lock, is_state_releasing())
198 .WillOnce(Return(ret_val));
199 }
200
201 void expect_is_state_locked(MockManagedLock &managed_lock, bool ret_val) {
202 EXPECT_CALL(managed_lock, is_state_locked())
203 .WillOnce(Return(ret_val));
204 }
205
206 void expect_is_state_shutdown(MockManagedLock &managed_lock, bool ret_val) {
207 EXPECT_CALL(managed_lock, is_state_shutdown())
208 .WillOnce(Return(ret_val));
209 }
210
211 void expect_is_action_acquire_lock(MockManagedLock &managed_lock,
212 bool ret_val) {
213 EXPECT_CALL(managed_lock, is_action_acquire_lock())
214 .WillOnce(Return(ret_val));
215 }
216
217 void expect_set_require_lock(MockExclusiveLockImageCtx &mock_image_ctx,
218 io::Direction direction, bool enabled) {
219 EXPECT_CALL(*mock_image_ctx.io_work_queue, set_require_lock(direction,
220 enabled));
221 }
222
223 void expect_block_writes(MockExclusiveLockImageCtx &mock_image_ctx) {
224 EXPECT_CALL(*mock_image_ctx.io_work_queue, block_writes(_))
225 .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
226 if (mock_image_ctx.clone_copy_on_read ||
227 (mock_image_ctx.features & RBD_FEATURE_JOURNALING) != 0) {
228 expect_set_require_lock(mock_image_ctx, io::DIRECTION_BOTH, true);
229 } else {
230 expect_set_require_lock(mock_image_ctx, io::DIRECTION_WRITE, true);
231 }
232 }
233
234 void expect_unblock_writes(MockExclusiveLockImageCtx &mock_image_ctx) {
235 expect_set_require_lock(mock_image_ctx, io::DIRECTION_BOTH, false);
236 EXPECT_CALL(*mock_image_ctx.io_work_queue, unblock_writes());
237 }
238
239 void expect_prepare_lock_complete(MockExclusiveLockImageCtx &mock_image_ctx) {
240 EXPECT_CALL(*mock_image_ctx.state, handle_prepare_lock_complete());
241 }
242
243 void expect_pre_acquire_request(MockPreAcquireRequest &pre_acquire_request,
244 int r) {
245 EXPECT_CALL(pre_acquire_request, send())
246 .WillOnce(CompleteRequest(&pre_acquire_request, r));
247 }
248
249 void expect_post_acquire_request(MockPostAcquireRequest &post_acquire_request,
250 int r) {
251 EXPECT_CALL(post_acquire_request, send())
252 .WillOnce(CompleteRequest(&post_acquire_request, r));
253 }
254
255 void expect_pre_release_request(MockPreReleaseRequest &pre_release_request,
256 int r) {
257 EXPECT_CALL(pre_release_request, send())
258 .WillOnce(CompleteRequest(&pre_release_request, r));
259 }
260
261 void expect_notify_request_lock(MockExclusiveLockImageCtx &mock_image_ctx,
262 MockExclusiveLock &mock_exclusive_lock) {
263 EXPECT_CALL(*mock_image_ctx.image_watcher, notify_request_lock());
264 }
265
266 void expect_notify_acquired_lock(MockExclusiveLockImageCtx &mock_image_ctx) {
267 EXPECT_CALL(*mock_image_ctx.image_watcher, notify_acquired_lock())
268 .Times(1);
269 }
270
271 void expect_notify_released_lock(MockExclusiveLockImageCtx &mock_image_ctx) {
272 EXPECT_CALL(*mock_image_ctx.image_watcher, notify_released_lock())
273 .Times(1);
274 }
275
276 void expect_flush_notifies(MockExclusiveLockImageCtx &mock_image_ctx) {
277 EXPECT_CALL(*mock_image_ctx.image_watcher, flush(_))
278 .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
279 }
280
281 void expect_shut_down(MockManagedLock &managed_lock) {
282 EXPECT_CALL(managed_lock, shut_down(_))
283 .WillOnce(CompleteContext(0, static_cast<ContextWQ*>(nullptr)));
284 }
285
286 int when_init(MockExclusiveLockImageCtx &mock_image_ctx,
287 MockExclusiveLock &exclusive_lock) {
288 C_SaferCond ctx;
289 {
290 RWLock::WLocker owner_locker(mock_image_ctx.owner_lock);
291 exclusive_lock.init(mock_image_ctx.features, &ctx);
292 }
293 return ctx.wait();
294 }
295
296 int when_pre_acquire_lock_handler(MockManagedLock &managed_lock) {
297 C_SaferCond ctx;
298 managed_lock.pre_acquire_lock_handler(&ctx);
299 return ctx.wait();
300 }
301
302 int when_post_acquire_lock_handler(MockManagedLock &managed_lock, int r) {
303 C_SaferCond ctx;
304 managed_lock.post_acquire_lock_handler(r, &ctx);
305 return ctx.wait();
306 }
307
308 int when_pre_release_lock_handler(MockManagedLock &managed_lock,
309 bool shutting_down) {
310 C_SaferCond ctx;
311 managed_lock.pre_release_lock_handler(shutting_down, &ctx);
312 return ctx.wait();
313 }
314
315 int when_post_release_lock_handler(MockManagedLock &managed_lock,
316 bool shutting_down, int r) {
317 C_SaferCond ctx;
318 managed_lock.post_release_lock_handler(shutting_down, r, &ctx);
319 return ctx.wait();
320 }
321
322 int when_post_reacquire_lock_handler(MockManagedLock &managed_lock, int r) {
323 C_SaferCond ctx;
324 managed_lock.post_reacquire_lock_handler(r, &ctx);
325 return ctx.wait();
326 }
327
328 int when_shut_down(MockExclusiveLockImageCtx &mock_image_ctx,
329 MockExclusiveLock &exclusive_lock) {
330 C_SaferCond ctx;
331 {
332 RWLock::WLocker owner_locker(mock_image_ctx.owner_lock);
333 exclusive_lock.shut_down(&ctx);
334 }
335 return ctx.wait();
336 }
337
338 bool is_lock_owner(MockExclusiveLockImageCtx &mock_image_ctx,
339 MockExclusiveLock &exclusive_lock) {
340 RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
341 return exclusive_lock.is_lock_owner();
342 }
343 };
344
345 TEST_F(TestMockExclusiveLock, StateTransitions) {
346 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
347
348 librbd::ImageCtx *ictx;
349 ASSERT_EQ(0, open_image(m_image_name, &ictx));
350
351 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
352 MockExclusiveLock exclusive_lock(mock_image_ctx);
353 expect_op_work_queue(mock_image_ctx);
354
355 InSequence seq;
356 expect_set_state_initializing(exclusive_lock);
357 expect_block_writes(mock_image_ctx);
358 expect_set_state_unlocked(exclusive_lock);
359 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
360
361 // (try) acquire lock
362 MockPreAcquireRequest try_lock_pre_acquire;
363 expect_pre_acquire_request(try_lock_pre_acquire, 0);
364 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
365
366 MockPostAcquireRequest try_lock_post_acquire;
367 expect_post_acquire_request(try_lock_post_acquire, 0);
368 expect_is_state_acquiring(exclusive_lock, true);
369 expect_notify_acquired_lock(mock_image_ctx);
370 expect_unblock_writes(mock_image_ctx);
371 ASSERT_EQ(0, when_post_acquire_lock_handler(exclusive_lock, 0));
372
373 // release lock
374 MockPreReleaseRequest pre_request_release;
375 expect_pre_release_request(pre_request_release, 0);
376 ASSERT_EQ(0, when_pre_release_lock_handler(exclusive_lock, false));
377
378 expect_is_state_pre_releasing(exclusive_lock, false);
379 expect_is_state_releasing(exclusive_lock, true);
380 expect_notify_released_lock(mock_image_ctx);
381 ASSERT_EQ(0, when_post_release_lock_handler(exclusive_lock, false, 0));
382
383 // (try) acquire lock
384 MockPreAcquireRequest request_lock_pre_acquire;
385 expect_pre_acquire_request(request_lock_pre_acquire, 0);
386 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
387
388 MockPostAcquireRequest request_lock_post_acquire;
389 expect_post_acquire_request(request_lock_post_acquire, 0);
390 expect_is_state_acquiring(exclusive_lock, true);
391 expect_notify_acquired_lock(mock_image_ctx);
392 expect_unblock_writes(mock_image_ctx);
393 ASSERT_EQ(0, when_post_acquire_lock_handler(exclusive_lock, 0));
394
395 // shut down (and release)
396 expect_shut_down(exclusive_lock);
397 expect_is_state_waiting_for_lock(exclusive_lock, false);
398 ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock));
399
400 MockPreReleaseRequest shutdown_pre_release;
401 expect_pre_release_request(shutdown_pre_release, 0);
402 ASSERT_EQ(0, when_pre_release_lock_handler(exclusive_lock, true));
403
404 expect_unblock_writes(mock_image_ctx);
405 expect_notify_released_lock(mock_image_ctx);
406 ASSERT_EQ(0, when_post_release_lock_handler(exclusive_lock, true, 0));
407 }
408
409 TEST_F(TestMockExclusiveLock, TryLockAlreadyLocked) {
410 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
411
412 librbd::ImageCtx *ictx;
413 ASSERT_EQ(0, open_image(m_image_name, &ictx));
414
415 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
416 MockExclusiveLock exclusive_lock(mock_image_ctx);
417 expect_op_work_queue(mock_image_ctx);
418
419 InSequence seq;
420 expect_set_state_initializing(exclusive_lock);
421 expect_block_writes(mock_image_ctx);
422 expect_set_state_unlocked(exclusive_lock);
423 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
424
425 // try acquire lock
426 MockPreAcquireRequest try_lock_pre_acquire;
427 expect_pre_acquire_request(try_lock_pre_acquire, 0);
428 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
429
430 expect_is_state_acquiring(exclusive_lock, true);
431 expect_prepare_lock_complete(mock_image_ctx);
432 expect_is_action_acquire_lock(exclusive_lock, false);
433 ASSERT_EQ(0, when_post_acquire_lock_handler(exclusive_lock, -EAGAIN));
434 }
435
436 TEST_F(TestMockExclusiveLock, TryLockError) {
437 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
438
439 librbd::ImageCtx *ictx;
440 ASSERT_EQ(0, open_image(m_image_name, &ictx));
441
442 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
443 MockExclusiveLock exclusive_lock(mock_image_ctx);
444 expect_op_work_queue(mock_image_ctx);
445
446 InSequence seq;
447 expect_set_state_initializing(exclusive_lock);
448 expect_block_writes(mock_image_ctx);
449 expect_set_state_unlocked(exclusive_lock);
450 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
451
452 // try acquire lock
453 MockPreAcquireRequest try_lock_pre_acquire;
454 expect_pre_acquire_request(try_lock_pre_acquire, 0);
455 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
456
457 expect_is_state_acquiring(exclusive_lock, true);
458 expect_prepare_lock_complete(mock_image_ctx);
459 expect_is_action_acquire_lock(exclusive_lock, false);
460 ASSERT_EQ(-EBUSY, when_post_acquire_lock_handler(exclusive_lock, -EBUSY));
461 }
462
463 TEST_F(TestMockExclusiveLock, AcquireLockAlreadyLocked) {
464 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
465
466 librbd::ImageCtx *ictx;
467 ASSERT_EQ(0, open_image(m_image_name, &ictx));
468
469 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
470 MockExclusiveLock exclusive_lock(mock_image_ctx);
471 expect_op_work_queue(mock_image_ctx);
472
473 InSequence seq;
474 expect_set_state_initializing(exclusive_lock);
475 expect_block_writes(mock_image_ctx);
476 expect_set_state_unlocked(exclusive_lock);
477 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
478
479 // acquire lock
480 MockPreAcquireRequest try_lock_pre_acquire;
481 expect_pre_acquire_request(try_lock_pre_acquire, 0);
482 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
483
484 expect_is_state_acquiring(exclusive_lock, true);
485 expect_prepare_lock_complete(mock_image_ctx);
486 expect_is_action_acquire_lock(exclusive_lock, true);
487 expect_set_state_waiting_for_lock(exclusive_lock);
488 expect_notify_request_lock(mock_image_ctx, exclusive_lock);
489 ASSERT_EQ(-ECANCELED, when_post_acquire_lock_handler(exclusive_lock,
490 -EAGAIN));
491 }
492
493 TEST_F(TestMockExclusiveLock, AcquireLockBusy) {
494 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
495
496 librbd::ImageCtx *ictx;
497 ASSERT_EQ(0, open_image(m_image_name, &ictx));
498
499 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
500 MockExclusiveLock exclusive_lock(mock_image_ctx);
501 expect_op_work_queue(mock_image_ctx);
502
503 InSequence seq;
504 expect_set_state_initializing(exclusive_lock);
505 expect_block_writes(mock_image_ctx);
506 expect_set_state_unlocked(exclusive_lock);
507 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
508
509 // acquire lock
510 MockPreAcquireRequest try_lock_pre_acquire;
511 expect_pre_acquire_request(try_lock_pre_acquire, 0);
512 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
513
514 expect_is_state_acquiring(exclusive_lock, true);
515 expect_prepare_lock_complete(mock_image_ctx);
516 expect_is_action_acquire_lock(exclusive_lock, true);
517 expect_set_state_waiting_for_lock(exclusive_lock);
518 expect_notify_request_lock(mock_image_ctx, exclusive_lock);
519 ASSERT_EQ(-ECANCELED, when_post_acquire_lock_handler(exclusive_lock,
520 -EBUSY));
521 }
522
523 TEST_F(TestMockExclusiveLock, AcquireLockError) {
524 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
525
526 librbd::ImageCtx *ictx;
527 ASSERT_EQ(0, open_image(m_image_name, &ictx));
528
529 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
530 MockExclusiveLock exclusive_lock(mock_image_ctx);
531 expect_op_work_queue(mock_image_ctx);
532
533 InSequence seq;
534 expect_set_state_initializing(exclusive_lock);
535 expect_block_writes(mock_image_ctx);
536 expect_set_state_unlocked(exclusive_lock);
537 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
538
539 // acquire lock
540 MockPreAcquireRequest try_lock_pre_acquire;
541 expect_pre_acquire_request(try_lock_pre_acquire, 0);
542 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
543
544 expect_is_state_acquiring(exclusive_lock, true);
545 expect_prepare_lock_complete(mock_image_ctx);
546 expect_is_action_acquire_lock(exclusive_lock, true);
547 ASSERT_EQ(-EBLACKLISTED, when_post_acquire_lock_handler(exclusive_lock,
548 -EBLACKLISTED));
549 }
550
551 TEST_F(TestMockExclusiveLock, PostAcquireLockError) {
552 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
553
554 librbd::ImageCtx *ictx;
555 ASSERT_EQ(0, open_image(m_image_name, &ictx));
556
557 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
558 MockExclusiveLock exclusive_lock(mock_image_ctx);
559 expect_op_work_queue(mock_image_ctx);
560
561 InSequence seq;
562 expect_set_state_initializing(exclusive_lock);
563 expect_block_writes(mock_image_ctx);
564 expect_set_state_unlocked(exclusive_lock);
565 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
566
567 // (try) acquire lock
568 MockPreAcquireRequest request_lock_pre_acquire;
569 expect_pre_acquire_request(request_lock_pre_acquire, 0);
570 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
571
572 MockPostAcquireRequest request_lock_post_acquire;
573 expect_post_acquire_request(request_lock_post_acquire, -EPERM);
574 expect_is_state_acquiring(exclusive_lock, true);
575 ASSERT_EQ(-EPERM, when_post_acquire_lock_handler(exclusive_lock, 0));
576 }
577
578 TEST_F(TestMockExclusiveLock, PreReleaseLockError) {
579 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
580
581 librbd::ImageCtx *ictx;
582 ASSERT_EQ(0, open_image(m_image_name, &ictx));
583
584 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
585 MockExclusiveLock exclusive_lock(mock_image_ctx);
586 expect_op_work_queue(mock_image_ctx);
587
588 InSequence seq;
589 expect_set_state_initializing(exclusive_lock);
590 expect_block_writes(mock_image_ctx);
591 expect_set_state_unlocked(exclusive_lock);
592 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
593
594 // release lock
595 MockPreReleaseRequest pre_request_release;
596 expect_pre_release_request(pre_request_release, -EINVAL);
597 ASSERT_EQ(-EINVAL, when_pre_release_lock_handler(exclusive_lock, false));
598
599 expect_is_state_pre_releasing(exclusive_lock, true);
600 ASSERT_EQ(-EINVAL, when_post_release_lock_handler(exclusive_lock, false,
601 -EINVAL));
602 }
603
604 TEST_F(TestMockExclusiveLock, ReacquireLock) {
605 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
606
607 librbd::ImageCtx *ictx;
608 ASSERT_EQ(0, open_image(m_image_name, &ictx));
609
610 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
611 MockExclusiveLock exclusive_lock(mock_image_ctx);
612 expect_op_work_queue(mock_image_ctx);
613
614 InSequence seq;
615 expect_set_state_initializing(exclusive_lock);
616 expect_block_writes(mock_image_ctx);
617 expect_set_state_unlocked(exclusive_lock);
618 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
619
620 // (try) acquire lock
621 MockPreAcquireRequest try_lock_pre_acquire;
622 expect_pre_acquire_request(try_lock_pre_acquire, 0);
623 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
624
625 MockPostAcquireRequest try_lock_post_acquire;
626 expect_post_acquire_request(try_lock_post_acquire, 0);
627 expect_is_state_acquiring(exclusive_lock, true);
628 expect_notify_acquired_lock(mock_image_ctx);
629 expect_unblock_writes(mock_image_ctx);
630 ASSERT_EQ(0, when_post_acquire_lock_handler(exclusive_lock, 0));
631
632 // reacquire lock
633 expect_notify_acquired_lock(mock_image_ctx);
634 ASSERT_EQ(0, when_post_reacquire_lock_handler(exclusive_lock, 0));
635
636 // shut down (and release)
637 expect_shut_down(exclusive_lock);
638 expect_is_state_waiting_for_lock(exclusive_lock, false);
639 ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock));
640
641 MockPreReleaseRequest shutdown_pre_release;
642 expect_pre_release_request(shutdown_pre_release, 0);
643 ASSERT_EQ(0, when_pre_release_lock_handler(exclusive_lock, true));
644
645 expect_unblock_writes(mock_image_ctx);
646 expect_notify_released_lock(mock_image_ctx);
647 ASSERT_EQ(0, when_post_release_lock_handler(exclusive_lock, true, 0));
648 }
649
650 TEST_F(TestMockExclusiveLock, BlockRequests) {
651 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
652
653 librbd::ImageCtx *ictx;
654 ASSERT_EQ(0, open_image(m_image_name, &ictx));
655
656 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
657 MockExclusiveLock exclusive_lock(mock_image_ctx);
658
659 expect_op_work_queue(mock_image_ctx);
660
661 InSequence seq;
662 expect_set_state_initializing(exclusive_lock);
663 expect_block_writes(mock_image_ctx);
664 expect_set_state_unlocked(exclusive_lock);
665 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
666
667 int ret_val;
668 expect_is_state_shutdown(exclusive_lock, false);
669 expect_is_state_locked(exclusive_lock, true);
670 ASSERT_TRUE(exclusive_lock.accept_requests(&ret_val));
671 ASSERT_EQ(0, ret_val);
672
673 exclusive_lock.block_requests(-EROFS);
674 expect_is_state_shutdown(exclusive_lock, false);
675 expect_is_state_locked(exclusive_lock, true);
676 ASSERT_FALSE(exclusive_lock.accept_requests(&ret_val));
677 ASSERT_EQ(-EROFS, ret_val);
678
679 exclusive_lock.unblock_requests();
680 expect_is_state_shutdown(exclusive_lock, false);
681 expect_is_state_locked(exclusive_lock, true);
682 ASSERT_TRUE(exclusive_lock.accept_requests(&ret_val));
683 ASSERT_EQ(0, ret_val);
684 }
685
686 } // namespace librbd
687