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