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