]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/librbd/test_mock_ExclusiveLock.cc
2a3388bdb39a04bc94b63113161a7de78cbd56d8
[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_on_read(MockExclusiveLockImageCtx &mock_image_ctx) {
218 EXPECT_CALL(*mock_image_ctx.io_work_queue, set_require_lock_on_read());
219 }
220
221 void expect_clear_require_lock_on_read(MockExclusiveLockImageCtx &mock_image_ctx) {
222 EXPECT_CALL(*mock_image_ctx.io_work_queue, clear_require_lock_on_read());
223 }
224
225 void expect_block_writes(MockExclusiveLockImageCtx &mock_image_ctx) {
226 EXPECT_CALL(*mock_image_ctx.io_work_queue, block_writes(_))
227 .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
228 if ((mock_image_ctx.features & RBD_FEATURE_JOURNALING) != 0) {
229 expect_set_require_lock_on_read(mock_image_ctx);
230 }
231 }
232
233 void expect_unblock_writes(MockExclusiveLockImageCtx &mock_image_ctx) {
234 expect_clear_require_lock_on_read(mock_image_ctx);
235 EXPECT_CALL(*mock_image_ctx.io_work_queue, unblock_writes());
236 }
237
238 void expect_prepare_lock_complete(MockExclusiveLockImageCtx &mock_image_ctx) {
239 EXPECT_CALL(*mock_image_ctx.state, handle_prepare_lock_complete());
240 }
241
242 void expect_pre_acquire_request(MockPreAcquireRequest &pre_acquire_request,
243 int r) {
244 EXPECT_CALL(pre_acquire_request, send())
245 .WillOnce(CompleteRequest(&pre_acquire_request, r));
246 }
247
248 void expect_post_acquire_request(MockPostAcquireRequest &post_acquire_request,
249 int r) {
250 EXPECT_CALL(post_acquire_request, send())
251 .WillOnce(CompleteRequest(&post_acquire_request, r));
252 }
253
254 void expect_pre_release_request(MockPreReleaseRequest &pre_release_request,
255 int r) {
256 EXPECT_CALL(pre_release_request, send())
257 .WillOnce(CompleteRequest(&pre_release_request, r));
258 }
259
260 void expect_notify_request_lock(MockExclusiveLockImageCtx &mock_image_ctx,
261 MockExclusiveLock &mock_exclusive_lock) {
262 EXPECT_CALL(*mock_image_ctx.image_watcher, notify_request_lock());
263 }
264
265 void expect_notify_acquired_lock(MockExclusiveLockImageCtx &mock_image_ctx) {
266 EXPECT_CALL(*mock_image_ctx.image_watcher, notify_acquired_lock())
267 .Times(1);
268 }
269
270 void expect_notify_released_lock(MockExclusiveLockImageCtx &mock_image_ctx) {
271 EXPECT_CALL(*mock_image_ctx.image_watcher, notify_released_lock())
272 .Times(1);
273 }
274
275 void expect_is_lock_request_needed(MockExclusiveLockImageCtx &mock_image_ctx, bool ret) {
276 EXPECT_CALL(*mock_image_ctx.io_work_queue, is_lock_request_needed())
277 .WillRepeatedly(Return(ret));
278 }
279
280 void expect_flush_notifies(MockExclusiveLockImageCtx &mock_image_ctx) {
281 EXPECT_CALL(*mock_image_ctx.image_watcher, flush(_))
282 .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
283 }
284
285 void expect_shut_down(MockManagedLock &managed_lock) {
286 EXPECT_CALL(managed_lock, shut_down(_))
287 .WillOnce(CompleteContext(0, static_cast<ContextWQ*>(nullptr)));
288 }
289
290 int when_init(MockExclusiveLockImageCtx &mock_image_ctx,
291 MockExclusiveLock &exclusive_lock) {
292 C_SaferCond ctx;
293 {
294 RWLock::WLocker owner_locker(mock_image_ctx.owner_lock);
295 exclusive_lock.init(mock_image_ctx.features, &ctx);
296 }
297 return ctx.wait();
298 }
299
300 int when_pre_acquire_lock_handler(MockManagedLock &managed_lock) {
301 C_SaferCond ctx;
302 managed_lock.pre_acquire_lock_handler(&ctx);
303 return ctx.wait();
304 }
305
306 int when_post_acquire_lock_handler(MockManagedLock &managed_lock, int r) {
307 C_SaferCond ctx;
308 managed_lock.post_acquire_lock_handler(r, &ctx);
309 return ctx.wait();
310 }
311
312 int when_pre_release_lock_handler(MockManagedLock &managed_lock,
313 bool shutting_down) {
314 C_SaferCond ctx;
315 managed_lock.pre_release_lock_handler(shutting_down, &ctx);
316 return ctx.wait();
317 }
318
319 int when_post_release_lock_handler(MockManagedLock &managed_lock,
320 bool shutting_down, int r) {
321 C_SaferCond ctx;
322 managed_lock.post_release_lock_handler(shutting_down, r, &ctx);
323 return ctx.wait();
324 }
325
326 int when_post_reacquire_lock_handler(MockManagedLock &managed_lock, int r) {
327 C_SaferCond ctx;
328 managed_lock.post_reacquire_lock_handler(r, &ctx);
329 return ctx.wait();
330 }
331
332 int when_shut_down(MockExclusiveLockImageCtx &mock_image_ctx,
333 MockExclusiveLock &exclusive_lock) {
334 C_SaferCond ctx;
335 {
336 RWLock::WLocker owner_locker(mock_image_ctx.owner_lock);
337 exclusive_lock.shut_down(&ctx);
338 }
339 return ctx.wait();
340 }
341
342 bool is_lock_owner(MockExclusiveLockImageCtx &mock_image_ctx,
343 MockExclusiveLock &exclusive_lock) {
344 RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
345 return exclusive_lock.is_lock_owner();
346 }
347 };
348
349 TEST_F(TestMockExclusiveLock, StateTransitions) {
350 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
351
352 librbd::ImageCtx *ictx;
353 ASSERT_EQ(0, open_image(m_image_name, &ictx));
354
355 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
356 MockExclusiveLock exclusive_lock(mock_image_ctx);
357 expect_op_work_queue(mock_image_ctx);
358
359 InSequence seq;
360 expect_set_state_initializing(exclusive_lock);
361 expect_block_writes(mock_image_ctx);
362 expect_set_state_unlocked(exclusive_lock);
363 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
364
365 // (try) acquire lock
366 MockPreAcquireRequest try_lock_pre_acquire;
367 expect_pre_acquire_request(try_lock_pre_acquire, 0);
368 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
369
370 MockPostAcquireRequest try_lock_post_acquire;
371 expect_post_acquire_request(try_lock_post_acquire, 0);
372 expect_is_state_acquiring(exclusive_lock, true);
373 expect_notify_acquired_lock(mock_image_ctx);
374 expect_unblock_writes(mock_image_ctx);
375 ASSERT_EQ(0, when_post_acquire_lock_handler(exclusive_lock, 0));
376
377 // release lock
378 MockPreReleaseRequest pre_request_release;
379 expect_pre_release_request(pre_request_release, 0);
380 ASSERT_EQ(0, when_pre_release_lock_handler(exclusive_lock, false));
381
382 expect_is_state_pre_releasing(exclusive_lock, false);
383 expect_is_state_releasing(exclusive_lock, true);
384 expect_notify_released_lock(mock_image_ctx);
385 expect_is_lock_request_needed(mock_image_ctx, false);
386 ASSERT_EQ(0, when_post_release_lock_handler(exclusive_lock, false, 0));
387
388 // (try) acquire lock
389 MockPreAcquireRequest request_lock_pre_acquire;
390 expect_pre_acquire_request(request_lock_pre_acquire, 0);
391 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
392
393 MockPostAcquireRequest request_lock_post_acquire;
394 expect_post_acquire_request(request_lock_post_acquire, 0);
395 expect_is_state_acquiring(exclusive_lock, true);
396 expect_notify_acquired_lock(mock_image_ctx);
397 expect_unblock_writes(mock_image_ctx);
398 ASSERT_EQ(0, when_post_acquire_lock_handler(exclusive_lock, 0));
399
400 // shut down (and release)
401 expect_shut_down(exclusive_lock);
402 expect_is_state_waiting_for_lock(exclusive_lock, false);
403 ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock));
404
405 MockPreReleaseRequest shutdown_pre_release;
406 expect_pre_release_request(shutdown_pre_release, 0);
407 ASSERT_EQ(0, when_pre_release_lock_handler(exclusive_lock, true));
408
409 expect_unblock_writes(mock_image_ctx);
410 expect_notify_released_lock(mock_image_ctx);
411 ASSERT_EQ(0, when_post_release_lock_handler(exclusive_lock, true, 0));
412 }
413
414 TEST_F(TestMockExclusiveLock, TryLockAlreadyLocked) {
415 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
416
417 librbd::ImageCtx *ictx;
418 ASSERT_EQ(0, open_image(m_image_name, &ictx));
419
420 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
421 MockExclusiveLock exclusive_lock(mock_image_ctx);
422 expect_op_work_queue(mock_image_ctx);
423
424 InSequence seq;
425 expect_set_state_initializing(exclusive_lock);
426 expect_block_writes(mock_image_ctx);
427 expect_set_state_unlocked(exclusive_lock);
428 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
429
430 // try acquire lock
431 MockPreAcquireRequest try_lock_pre_acquire;
432 expect_pre_acquire_request(try_lock_pre_acquire, 0);
433 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
434
435 expect_is_state_acquiring(exclusive_lock, true);
436 expect_prepare_lock_complete(mock_image_ctx);
437 expect_is_action_acquire_lock(exclusive_lock, false);
438 ASSERT_EQ(0, when_post_acquire_lock_handler(exclusive_lock, -EAGAIN));
439 }
440
441 TEST_F(TestMockExclusiveLock, TryLockError) {
442 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
443
444 librbd::ImageCtx *ictx;
445 ASSERT_EQ(0, open_image(m_image_name, &ictx));
446
447 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
448 MockExclusiveLock exclusive_lock(mock_image_ctx);
449 expect_op_work_queue(mock_image_ctx);
450
451 InSequence seq;
452 expect_set_state_initializing(exclusive_lock);
453 expect_block_writes(mock_image_ctx);
454 expect_set_state_unlocked(exclusive_lock);
455 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
456
457 // try acquire lock
458 MockPreAcquireRequest try_lock_pre_acquire;
459 expect_pre_acquire_request(try_lock_pre_acquire, 0);
460 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
461
462 expect_is_state_acquiring(exclusive_lock, true);
463 expect_prepare_lock_complete(mock_image_ctx);
464 expect_is_action_acquire_lock(exclusive_lock, false);
465 ASSERT_EQ(-EBUSY, when_post_acquire_lock_handler(exclusive_lock, -EBUSY));
466 }
467
468 TEST_F(TestMockExclusiveLock, AcquireLockAlreadyLocked) {
469 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
470
471 librbd::ImageCtx *ictx;
472 ASSERT_EQ(0, open_image(m_image_name, &ictx));
473
474 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
475 MockExclusiveLock exclusive_lock(mock_image_ctx);
476 expect_op_work_queue(mock_image_ctx);
477
478 InSequence seq;
479 expect_set_state_initializing(exclusive_lock);
480 expect_block_writes(mock_image_ctx);
481 expect_set_state_unlocked(exclusive_lock);
482 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
483
484 // acquire lock
485 MockPreAcquireRequest try_lock_pre_acquire;
486 expect_pre_acquire_request(try_lock_pre_acquire, 0);
487 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
488
489 expect_is_state_acquiring(exclusive_lock, true);
490 expect_prepare_lock_complete(mock_image_ctx);
491 expect_is_action_acquire_lock(exclusive_lock, true);
492 expect_set_state_waiting_for_lock(exclusive_lock);
493 expect_notify_request_lock(mock_image_ctx, exclusive_lock);
494 ASSERT_EQ(-ECANCELED, when_post_acquire_lock_handler(exclusive_lock,
495 -EAGAIN));
496 }
497
498 TEST_F(TestMockExclusiveLock, AcquireLockBusy) {
499 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
500
501 librbd::ImageCtx *ictx;
502 ASSERT_EQ(0, open_image(m_image_name, &ictx));
503
504 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
505 MockExclusiveLock exclusive_lock(mock_image_ctx);
506 expect_op_work_queue(mock_image_ctx);
507
508 InSequence seq;
509 expect_set_state_initializing(exclusive_lock);
510 expect_block_writes(mock_image_ctx);
511 expect_set_state_unlocked(exclusive_lock);
512 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
513
514 // acquire lock
515 MockPreAcquireRequest try_lock_pre_acquire;
516 expect_pre_acquire_request(try_lock_pre_acquire, 0);
517 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
518
519 expect_is_state_acquiring(exclusive_lock, true);
520 expect_prepare_lock_complete(mock_image_ctx);
521 expect_is_action_acquire_lock(exclusive_lock, true);
522 expect_set_state_waiting_for_lock(exclusive_lock);
523 expect_notify_request_lock(mock_image_ctx, exclusive_lock);
524 ASSERT_EQ(-ECANCELED, when_post_acquire_lock_handler(exclusive_lock,
525 -EBUSY));
526 }
527
528 TEST_F(TestMockExclusiveLock, AcquireLockError) {
529 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
530
531 librbd::ImageCtx *ictx;
532 ASSERT_EQ(0, open_image(m_image_name, &ictx));
533
534 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
535 MockExclusiveLock exclusive_lock(mock_image_ctx);
536 expect_op_work_queue(mock_image_ctx);
537
538 InSequence seq;
539 expect_set_state_initializing(exclusive_lock);
540 expect_block_writes(mock_image_ctx);
541 expect_set_state_unlocked(exclusive_lock);
542 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
543
544 // acquire lock
545 MockPreAcquireRequest try_lock_pre_acquire;
546 expect_pre_acquire_request(try_lock_pre_acquire, 0);
547 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
548
549 expect_is_state_acquiring(exclusive_lock, true);
550 expect_prepare_lock_complete(mock_image_ctx);
551 expect_is_action_acquire_lock(exclusive_lock, true);
552 ASSERT_EQ(-EBLACKLISTED, when_post_acquire_lock_handler(exclusive_lock,
553 -EBLACKLISTED));
554 }
555
556 TEST_F(TestMockExclusiveLock, PostAcquireLockError) {
557 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
558
559 librbd::ImageCtx *ictx;
560 ASSERT_EQ(0, open_image(m_image_name, &ictx));
561
562 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
563 MockExclusiveLock exclusive_lock(mock_image_ctx);
564 expect_op_work_queue(mock_image_ctx);
565
566 InSequence seq;
567 expect_set_state_initializing(exclusive_lock);
568 expect_block_writes(mock_image_ctx);
569 expect_set_state_unlocked(exclusive_lock);
570 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
571
572 // (try) acquire lock
573 MockPreAcquireRequest request_lock_pre_acquire;
574 expect_pre_acquire_request(request_lock_pre_acquire, 0);
575 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
576
577 MockPostAcquireRequest request_lock_post_acquire;
578 expect_post_acquire_request(request_lock_post_acquire, -EPERM);
579 expect_is_state_acquiring(exclusive_lock, true);
580 ASSERT_EQ(-EPERM, when_post_acquire_lock_handler(exclusive_lock, 0));
581 }
582
583 TEST_F(TestMockExclusiveLock, PreReleaseLockError) {
584 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
585
586 librbd::ImageCtx *ictx;
587 ASSERT_EQ(0, open_image(m_image_name, &ictx));
588
589 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
590 MockExclusiveLock exclusive_lock(mock_image_ctx);
591 expect_op_work_queue(mock_image_ctx);
592
593 InSequence seq;
594 expect_set_state_initializing(exclusive_lock);
595 expect_block_writes(mock_image_ctx);
596 expect_set_state_unlocked(exclusive_lock);
597 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
598
599 // release lock
600 MockPreReleaseRequest pre_request_release;
601 expect_pre_release_request(pre_request_release, -EINVAL);
602 ASSERT_EQ(-EINVAL, when_pre_release_lock_handler(exclusive_lock, false));
603
604 expect_is_state_pre_releasing(exclusive_lock, true);
605 ASSERT_EQ(-EINVAL, when_post_release_lock_handler(exclusive_lock, false,
606 -EINVAL));
607 }
608
609 TEST_F(TestMockExclusiveLock, ReacquireLock) {
610 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
611
612 librbd::ImageCtx *ictx;
613 ASSERT_EQ(0, open_image(m_image_name, &ictx));
614
615 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
616 MockExclusiveLock exclusive_lock(mock_image_ctx);
617 expect_op_work_queue(mock_image_ctx);
618
619 InSequence seq;
620 expect_set_state_initializing(exclusive_lock);
621 expect_block_writes(mock_image_ctx);
622 expect_set_state_unlocked(exclusive_lock);
623 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
624
625 // (try) acquire lock
626 MockPreAcquireRequest try_lock_pre_acquire;
627 expect_pre_acquire_request(try_lock_pre_acquire, 0);
628 ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
629
630 MockPostAcquireRequest try_lock_post_acquire;
631 expect_post_acquire_request(try_lock_post_acquire, 0);
632 expect_is_state_acquiring(exclusive_lock, true);
633 expect_notify_acquired_lock(mock_image_ctx);
634 expect_unblock_writes(mock_image_ctx);
635 ASSERT_EQ(0, when_post_acquire_lock_handler(exclusive_lock, 0));
636
637 // reacquire lock
638 expect_notify_acquired_lock(mock_image_ctx);
639 ASSERT_EQ(0, when_post_reacquire_lock_handler(exclusive_lock, 0));
640
641 // shut down (and release)
642 expect_shut_down(exclusive_lock);
643 expect_is_state_waiting_for_lock(exclusive_lock, false);
644 ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock));
645
646 MockPreReleaseRequest shutdown_pre_release;
647 expect_pre_release_request(shutdown_pre_release, 0);
648 ASSERT_EQ(0, when_pre_release_lock_handler(exclusive_lock, true));
649
650 expect_unblock_writes(mock_image_ctx);
651 expect_notify_released_lock(mock_image_ctx);
652 ASSERT_EQ(0, when_post_release_lock_handler(exclusive_lock, true, 0));
653 }
654
655 TEST_F(TestMockExclusiveLock, BlockRequests) {
656 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
657
658 librbd::ImageCtx *ictx;
659 ASSERT_EQ(0, open_image(m_image_name, &ictx));
660
661 MockExclusiveLockImageCtx mock_image_ctx(*ictx);
662 MockExclusiveLock exclusive_lock(mock_image_ctx);
663
664 expect_op_work_queue(mock_image_ctx);
665
666 InSequence seq;
667 expect_set_state_initializing(exclusive_lock);
668 expect_block_writes(mock_image_ctx);
669 expect_set_state_unlocked(exclusive_lock);
670 ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
671
672 int ret_val;
673 expect_is_state_shutdown(exclusive_lock, false);
674 expect_is_state_locked(exclusive_lock, true);
675 ASSERT_TRUE(exclusive_lock.accept_requests(&ret_val));
676 ASSERT_EQ(0, ret_val);
677
678 exclusive_lock.block_requests(-EROFS);
679 expect_is_state_shutdown(exclusive_lock, false);
680 expect_is_state_locked(exclusive_lock, true);
681 ASSERT_FALSE(exclusive_lock.accept_requests(&ret_val));
682 ASSERT_EQ(-EROFS, ret_val);
683
684 exclusive_lock.unblock_requests();
685 expect_is_state_shutdown(exclusive_lock, false);
686 expect_is_state_locked(exclusive_lock, true);
687 ASSERT_TRUE(exclusive_lock.accept_requests(&ret_val));
688 ASSERT_EQ(0, ret_val);
689 }
690
691 } // namespace librbd
692