]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/librbd/test_mock_ManagedLock.cc
import ceph quincy 17.2.6
[ceph.git] / ceph / src / test / librbd / test_mock_ManagedLock.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 "librbd/ManagedLock.h"
7 #include "librbd/managed_lock/AcquireRequest.h"
8 #include "librbd/managed_lock/BreakRequest.h"
9 #include "librbd/managed_lock/GetLockerRequest.h"
10 #include "librbd/managed_lock/ReacquireRequest.h"
11 #include "librbd/managed_lock/ReleaseRequest.h"
12 #include "gmock/gmock.h"
13 #include "gtest/gtest.h"
14 #include <list>
15
16 using namespace std;
17
18 namespace librbd {
19
20 struct MockManagedLockImageCtx : public MockImageCtx {
21 explicit MockManagedLockImageCtx(ImageCtx &image_ctx) : MockImageCtx(image_ctx) {}
22 };
23
24 namespace watcher {
25 template <>
26 struct Traits<MockManagedLockImageCtx> {
27 typedef librbd::MockImageWatcher Watcher;
28 };
29 }
30
31 struct MockMockManagedLock : public ManagedLock<MockManagedLockImageCtx> {
32 MockMockManagedLock(librados::IoCtx& ioctx, AsioEngine& asio_engine,
33 const std::string& oid, librbd::MockImageWatcher *watcher,
34 managed_lock::Mode mode, bool blocklist_on_break_lock,
35 uint32_t blocklist_expire_seconds)
36 : ManagedLock<MockManagedLockImageCtx>(ioctx, asio_engine, oid, watcher,
37 librbd::managed_lock::EXCLUSIVE, true, 0) {
38 };
39 virtual ~MockMockManagedLock() = default;
40
41 MOCK_METHOD2(post_reacquire_lock_handler, void(int, Context*));
42
43 MOCK_METHOD2(pre_release_lock_handler, void(bool, Context*));
44 MOCK_METHOD3(post_release_lock_handler, void(bool, int, Context*));
45 };
46
47 namespace managed_lock {
48
49 template<typename T>
50 struct BaseRequest {
51 static std::list<T *> s_requests;
52 Context *on_finish = nullptr;
53
54 static T* create(librados::IoCtx& ioctx, MockImageWatcher *watcher,
55 const std::string& oid, const std::string& cookie,
56 Context *on_finish) {
57 ceph_assert(!s_requests.empty());
58 T* req = s_requests.front();
59 req->on_finish = on_finish;
60 s_requests.pop_front();
61 return req;
62 }
63
64 BaseRequest() {
65 s_requests.push_back(reinterpret_cast<T*>(this));
66 }
67 };
68
69 template<typename T>
70 std::list<T *> BaseRequest<T>::s_requests;
71
72 template <>
73 struct AcquireRequest<MockManagedLockImageCtx>
74 : public BaseRequest<AcquireRequest<MockManagedLockImageCtx> > {
75 static AcquireRequest* create(librados::IoCtx& ioctx,
76 MockImageWatcher *watcher,
77 AsioEngine& asio_engine,
78 const std::string& oid,
79 const std::string& cookie,
80 bool exclusive, bool blocklist_on_break_lock,
81 uint32_t blocklist_expire_seconds,
82 Context *on_finish) {
83 return BaseRequest::create(ioctx, watcher, oid, cookie, on_finish);
84 }
85
86 MOCK_METHOD0(send, void());
87 };
88
89 template <>
90 struct ReacquireRequest<MockManagedLockImageCtx> : public BaseRequest<ReacquireRequest<MockManagedLockImageCtx> > {
91 static ReacquireRequest* create(librados::IoCtx &ioctx, const std::string& oid,
92 const string& old_cookie, const std::string& new_cookie,
93 bool exclusive, Context *on_finish) {
94 return BaseRequest::create(ioctx, nullptr, oid, new_cookie,
95 on_finish);
96 }
97
98 MOCK_METHOD0(send, void());
99 };
100
101 template <>
102 struct ReleaseRequest<MockManagedLockImageCtx> : public BaseRequest<ReleaseRequest<MockManagedLockImageCtx> > {
103 static ReleaseRequest* create(librados::IoCtx& ioctx, MockImageWatcher *watcher,
104 asio::ContextWQ *work_queue,
105 const std::string& oid,
106 const std::string& cookie, Context *on_finish) {
107 return BaseRequest::create(ioctx, watcher, oid, cookie, on_finish);
108 }
109 MOCK_METHOD0(send, void());
110 };
111
112 template <>
113 struct GetLockerRequest<MockManagedLockImageCtx> {
114 static GetLockerRequest* create(librados::IoCtx& ioctx,
115 const std::string& oid, bool exclusive,
116 Locker *locker, Context *on_finish) {
117 ceph_abort_msg("unexpected call");
118 }
119
120 void send() {
121 ceph_abort_msg("unexpected call");
122 }
123 };
124
125 template <>
126 struct BreakRequest<MockManagedLockImageCtx> {
127 static BreakRequest* create(librados::IoCtx& ioctx,
128 AsioEngine& asio_engine,
129 const std::string& oid, const Locker &locker,
130 bool exclusive, bool blocklist_locker,
131 uint32_t blocklist_expire_seconds,
132 bool force_break_lock, Context *on_finish) {
133 ceph_abort_msg("unexpected call");
134 }
135
136 void send() {
137 ceph_abort_msg("unexpected call");
138 }
139 };
140
141 } // namespace managed_lock
142 } // namespace librbd
143
144 // template definitions
145 #include "librbd/ManagedLock.cc"
146 template class librbd::ManagedLock<librbd::MockManagedLockImageCtx>;
147
148
149 ACTION_P3(QueueRequest, request, r, wq) {
150 if (request->on_finish != nullptr) {
151 if (wq != nullptr) {
152 wq->queue(request->on_finish, r);
153 } else {
154 request->on_finish->complete(r);
155 }
156 }
157 }
158
159 ACTION_P2(QueueContext, r, wq) {
160 wq->queue(arg0, r);
161 }
162
163 ACTION_P(Notify, ctx) {
164 ctx->complete(0);
165 }
166
167 namespace librbd {
168
169 using ::testing::_;
170 using ::testing::DoAll;
171 using ::testing::Invoke;
172 using ::testing::InSequence;
173 using ::testing::Return;
174 using ::testing::WithArg;
175
176 class TestMockManagedLock : public TestMockFixture {
177 public:
178 typedef ManagedLock<MockManagedLockImageCtx> MockManagedLock;
179 typedef managed_lock::AcquireRequest<MockManagedLockImageCtx> MockAcquireRequest;
180 typedef managed_lock::ReacquireRequest<MockManagedLockImageCtx> MockReacquireRequest;
181 typedef managed_lock::ReleaseRequest<MockManagedLockImageCtx> MockReleaseRequest;
182
183 void expect_get_watch_handle(MockImageWatcher &mock_watcher,
184 uint64_t watch_handle = 1234567890) {
185 EXPECT_CALL(mock_watcher, get_watch_handle())
186 .WillOnce(Return(watch_handle));
187 }
188
189 void expect_acquire_lock(MockImageWatcher &watcher,
190 asio::ContextWQ *work_queue,
191 MockAcquireRequest &acquire_request, int r) {
192 expect_get_watch_handle(watcher);
193 EXPECT_CALL(acquire_request, send())
194 .WillOnce(QueueRequest(&acquire_request, r, work_queue));
195 }
196
197 void expect_release_lock(asio::ContextWQ *work_queue,
198 MockReleaseRequest &release_request, int r) {
199 EXPECT_CALL(release_request, send())
200 .WillOnce(QueueRequest(&release_request, r, work_queue));
201 }
202
203 void expect_reacquire_lock(MockImageWatcher& watcher,
204 asio::ContextWQ *work_queue,
205 MockReacquireRequest &mock_reacquire_request,
206 int r) {
207 EXPECT_CALL(mock_reacquire_request, send())
208 .WillOnce(QueueRequest(&mock_reacquire_request, r, work_queue));
209 }
210
211 void expect_flush_notifies(MockImageWatcher *mock_watcher) {
212 EXPECT_CALL(*mock_watcher, flush(_))
213 .WillOnce(CompleteContext(0, (asio::ContextWQ *)nullptr));
214 }
215
216 void expect_post_reacquired_lock_handler(MockImageWatcher& watcher,
217 MockMockManagedLock &managed_lock, uint64_t &client_id) {
218 expect_get_watch_handle(watcher);
219 EXPECT_CALL(managed_lock, post_reacquire_lock_handler(_, _))
220 .WillOnce(Invoke([&client_id](int r, Context *on_finish){
221 if (r >= 0) {
222 client_id = 98765;
223 }
224 on_finish->complete(r);}));
225 }
226
227 void expect_pre_release_lock_handler(MockMockManagedLock &managed_lock,
228 bool shutting_down, int r) {
229 EXPECT_CALL(managed_lock, pre_release_lock_handler(shutting_down, _))
230 .WillOnce(WithArg<1>(Invoke([r](Context *on_finish){
231 on_finish->complete(r);
232 })));
233 }
234
235 void expect_post_release_lock_handler(MockMockManagedLock &managed_lock,
236 bool shutting_down, int expect_r,
237 int r) {
238 EXPECT_CALL(managed_lock, post_release_lock_handler(shutting_down, expect_r, _))
239 .WillOnce(WithArg<2>(Invoke([r](Context *on_finish){
240 on_finish->complete(r);
241 })));
242 }
243
244 int when_acquire_lock(MockManagedLock &managed_lock) {
245 C_SaferCond ctx;
246 {
247 managed_lock.acquire_lock(&ctx);
248 }
249 return ctx.wait();
250 }
251 int when_release_lock(MockManagedLock &managed_lock) {
252 C_SaferCond ctx;
253 {
254 managed_lock.release_lock(&ctx);
255 }
256 return ctx.wait();
257 }
258 int when_shut_down(MockManagedLock &managed_lock) {
259 C_SaferCond ctx;
260 {
261 managed_lock.shut_down(&ctx);
262 }
263 return ctx.wait();
264 }
265
266 bool is_lock_owner(MockManagedLock &managed_lock) {
267 return managed_lock.is_lock_owner();
268 }
269 };
270
271 TEST_F(TestMockManagedLock, StateTransitions) {
272 librbd::ImageCtx *ictx;
273 ASSERT_EQ(0, open_image(m_image_name, &ictx));
274
275 MockManagedLockImageCtx mock_image_ctx(*ictx);
276 MockManagedLock managed_lock(ictx->md_ctx, *ictx->asio_engine,
277 ictx->header_oid, mock_image_ctx.image_watcher,
278 librbd::managed_lock::EXCLUSIVE, true, 0);
279 InSequence seq;
280
281 MockAcquireRequest request_lock_acquire1;
282 expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, request_lock_acquire1, 0);
283 ASSERT_EQ(0, when_acquire_lock(managed_lock));
284 ASSERT_TRUE(is_lock_owner(managed_lock));
285
286 MockReleaseRequest request_release;
287 expect_release_lock(ictx->op_work_queue, request_release, 0);
288 ASSERT_EQ(0, when_release_lock(managed_lock));
289 ASSERT_FALSE(is_lock_owner(managed_lock));
290
291 MockAcquireRequest request_lock_acquire2;
292 expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, request_lock_acquire2, 0);
293 ASSERT_EQ(0, when_acquire_lock(managed_lock));
294 ASSERT_TRUE(is_lock_owner(managed_lock));
295
296 MockReleaseRequest shutdown_release;
297 expect_release_lock(ictx->op_work_queue, shutdown_release, 0);
298 ASSERT_EQ(0, when_shut_down(managed_lock));
299 ASSERT_FALSE(is_lock_owner(managed_lock));
300 }
301
302 TEST_F(TestMockManagedLock, AcquireLockLockedState) {
303 librbd::ImageCtx *ictx;
304 ASSERT_EQ(0, open_image(m_image_name, &ictx));
305
306 MockManagedLockImageCtx mock_image_ctx(*ictx);
307 MockManagedLock managed_lock(ictx->md_ctx, *ictx->asio_engine,
308 ictx->header_oid, mock_image_ctx.image_watcher,
309 librbd::managed_lock::EXCLUSIVE, true, 0);
310 InSequence seq;
311
312 MockAcquireRequest try_lock_acquire;
313 expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, try_lock_acquire, 0);
314 ASSERT_EQ(0, when_acquire_lock(managed_lock));
315 ASSERT_EQ(0, when_acquire_lock(managed_lock));
316
317 MockReleaseRequest shutdown_release;
318 expect_release_lock(ictx->op_work_queue, shutdown_release, 0);
319 ASSERT_EQ(0, when_shut_down(managed_lock));
320 }
321
322 TEST_F(TestMockManagedLock, AcquireLockAlreadyLocked) {
323 librbd::ImageCtx *ictx;
324 ASSERT_EQ(0, open_image(m_image_name, &ictx));
325
326 MockManagedLockImageCtx mock_image_ctx(*ictx);
327 MockManagedLock managed_lock(ictx->md_ctx, *ictx->asio_engine,
328 ictx->header_oid, mock_image_ctx.image_watcher,
329 librbd::managed_lock::EXCLUSIVE, true, 0);
330 InSequence seq;
331
332 MockAcquireRequest try_lock_acquire;
333 expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, try_lock_acquire, -EAGAIN);
334 ASSERT_EQ(-EAGAIN, when_acquire_lock(managed_lock));
335 ASSERT_FALSE(is_lock_owner(managed_lock));
336
337 ASSERT_EQ(0, when_shut_down(managed_lock));
338 }
339
340 TEST_F(TestMockManagedLock, AcquireLockBusy) {
341 librbd::ImageCtx *ictx;
342 ASSERT_EQ(0, open_image(m_image_name, &ictx));
343
344 MockManagedLockImageCtx mock_image_ctx(*ictx);
345 MockManagedLock managed_lock(ictx->md_ctx, *ictx->asio_engine,
346 ictx->header_oid, mock_image_ctx.image_watcher,
347 librbd::managed_lock::EXCLUSIVE, true, 0);
348 InSequence seq;
349
350 MockAcquireRequest try_lock_acquire;
351 expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, try_lock_acquire, -EBUSY);
352 ASSERT_EQ(-EBUSY, when_acquire_lock(managed_lock));
353 ASSERT_FALSE(is_lock_owner(managed_lock));
354
355 ASSERT_EQ(0, when_shut_down(managed_lock));
356 }
357
358 TEST_F(TestMockManagedLock, AcquireLockError) {
359 librbd::ImageCtx *ictx;
360 ASSERT_EQ(0, open_image(m_image_name, &ictx));
361
362 MockManagedLockImageCtx mock_image_ctx(*ictx);
363 MockManagedLock managed_lock(ictx->md_ctx, *ictx->asio_engine,
364 ictx->header_oid, mock_image_ctx.image_watcher,
365 librbd::managed_lock::EXCLUSIVE, true, 0);
366 InSequence seq;
367
368 MockAcquireRequest try_lock_acquire;
369 expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, try_lock_acquire, -EINVAL);
370
371 ASSERT_EQ(-EINVAL, when_acquire_lock(managed_lock));
372 ASSERT_FALSE(is_lock_owner(managed_lock));
373
374 ASSERT_EQ(0, when_shut_down(managed_lock));
375 }
376
377 TEST_F(TestMockManagedLock, AcquireLockBlocklist) {
378 librbd::ImageCtx *ictx;
379 ASSERT_EQ(0, open_image(m_image_name, &ictx));
380
381 MockManagedLockImageCtx mock_image_ctx(*ictx);
382 MockManagedLock managed_lock(ictx->md_ctx, *ictx->asio_engine,
383 ictx->header_oid, mock_image_ctx.image_watcher,
384 librbd::managed_lock::EXCLUSIVE, true, 0);
385 InSequence seq;
386
387 // will abort after seeing blocklist error (avoid infinite request loop)
388 MockAcquireRequest request_lock_acquire;
389 expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, request_lock_acquire, -EBLOCKLISTED);
390 ASSERT_EQ(-EBLOCKLISTED, when_acquire_lock(managed_lock));
391 ASSERT_FALSE(is_lock_owner(managed_lock));
392
393 ASSERT_EQ(0, when_shut_down(managed_lock));
394 }
395
396 TEST_F(TestMockManagedLock, ReleaseLockUnlockedState) {
397 librbd::ImageCtx *ictx;
398 ASSERT_EQ(0, open_image(m_image_name, &ictx));
399
400 MockManagedLockImageCtx mock_image_ctx(*ictx);
401 MockManagedLock managed_lock(ictx->md_ctx, *ictx->asio_engine,
402 ictx->header_oid, mock_image_ctx.image_watcher,
403 librbd::managed_lock::EXCLUSIVE, true, 0);
404 InSequence seq;
405
406 ASSERT_EQ(0, when_release_lock(managed_lock));
407
408 ASSERT_EQ(0, when_shut_down(managed_lock));
409 }
410
411 TEST_F(TestMockManagedLock, ReleaseLockBlocklist) {
412 librbd::ImageCtx *ictx;
413 ASSERT_EQ(0, open_image(m_image_name, &ictx));
414
415 MockManagedLockImageCtx mock_image_ctx(*ictx);
416 MockMockManagedLock managed_lock(ictx->md_ctx, *ictx->asio_engine,
417 ictx->header_oid, mock_image_ctx.image_watcher,
418 librbd::managed_lock::EXCLUSIVE, true, 0);
419 InSequence seq;
420
421 MockAcquireRequest try_lock_acquire;
422 expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, try_lock_acquire, 0);
423 ASSERT_EQ(0, when_acquire_lock(managed_lock));
424
425 expect_pre_release_lock_handler(managed_lock, false, -EBLOCKLISTED);
426 expect_post_release_lock_handler(managed_lock, false, -EBLOCKLISTED, -EBLOCKLISTED);
427 ASSERT_EQ(-EBLOCKLISTED, when_release_lock(managed_lock));
428 ASSERT_FALSE(is_lock_owner(managed_lock));
429
430 ASSERT_EQ(0, when_shut_down(managed_lock));
431 }
432
433 TEST_F(TestMockManagedLock, ReleaseLockError) {
434 librbd::ImageCtx *ictx;
435 ASSERT_EQ(0, open_image(m_image_name, &ictx));
436
437 MockManagedLockImageCtx mock_image_ctx(*ictx);
438 MockManagedLock managed_lock(ictx->md_ctx, *ictx->asio_engine,
439 ictx->header_oid, mock_image_ctx.image_watcher,
440 librbd::managed_lock::EXCLUSIVE, true, 0);
441 InSequence seq;
442
443 MockAcquireRequest try_lock_acquire;
444 expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, try_lock_acquire, 0);
445 ASSERT_EQ(0, when_acquire_lock(managed_lock));
446
447 MockReleaseRequest release;
448 expect_release_lock(ictx->op_work_queue, release, -EINVAL);
449
450 ASSERT_EQ(-EINVAL, when_release_lock(managed_lock));
451 ASSERT_TRUE(is_lock_owner(managed_lock));
452
453 MockReleaseRequest shutdown_release;
454 expect_release_lock(ictx->op_work_queue, shutdown_release, 0);
455 ASSERT_EQ(0, when_shut_down(managed_lock));
456 ASSERT_FALSE(is_lock_owner(managed_lock));
457 }
458
459 TEST_F(TestMockManagedLock, ConcurrentRequests) {
460 librbd::ImageCtx *ictx;
461 ASSERT_EQ(0, open_image(m_image_name, &ictx));
462
463 MockManagedLockImageCtx mock_image_ctx(*ictx);
464 MockManagedLock managed_lock(ictx->md_ctx, *ictx->asio_engine,
465 ictx->header_oid, mock_image_ctx.image_watcher,
466 librbd::managed_lock::EXCLUSIVE, true, 0);
467 InSequence seq;
468
469 expect_get_watch_handle(*mock_image_ctx.image_watcher);
470
471 C_SaferCond wait_for_send_ctx1;
472 MockAcquireRequest acquire_error;
473 EXPECT_CALL(acquire_error, send())
474 .WillOnce(Notify(&wait_for_send_ctx1));
475
476 MockAcquireRequest request_acquire;
477 expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, request_acquire, 0);
478
479 MockReleaseRequest release;
480 C_SaferCond wait_for_send_ctx2;
481 EXPECT_CALL(release, send())
482 .WillOnce(Notify(&wait_for_send_ctx2));
483
484 C_SaferCond acquire_request_ctx1;
485 managed_lock.acquire_lock(&acquire_request_ctx1);
486
487 C_SaferCond acquire_lock_ctx1;
488 C_SaferCond acquire_lock_ctx2;
489 managed_lock.acquire_lock(&acquire_lock_ctx1);
490 managed_lock.acquire_lock(&acquire_lock_ctx2);
491
492 // fail the try_lock
493 ASSERT_EQ(0, wait_for_send_ctx1.wait());
494 acquire_error.on_finish->complete(-EINVAL);
495 ASSERT_EQ(-EINVAL, acquire_request_ctx1.wait());
496
497 C_SaferCond acquire_lock_ctx3;
498 managed_lock.acquire_lock(&acquire_lock_ctx3);
499
500 C_SaferCond release_lock_ctx1;
501 managed_lock.release_lock(&release_lock_ctx1);
502
503 // all three pending request locks should complete
504 ASSERT_EQ(-EINVAL, acquire_lock_ctx1.wait());
505 ASSERT_EQ(-EINVAL, acquire_lock_ctx2.wait());
506 ASSERT_EQ(0, acquire_lock_ctx3.wait());
507
508 // proceed with the release
509 ASSERT_EQ(0, wait_for_send_ctx2.wait());
510 release.on_finish->complete(0);
511 ASSERT_EQ(0, release_lock_ctx1.wait());
512
513 ASSERT_EQ(0, when_shut_down(managed_lock));
514 }
515
516 TEST_F(TestMockManagedLock, ReacquireLock) {
517 librbd::ImageCtx *ictx;
518 ASSERT_EQ(0, open_image(m_image_name, &ictx));
519
520 MockManagedLockImageCtx mock_image_ctx(*ictx);
521 MockManagedLock managed_lock(ictx->md_ctx, *ictx->asio_engine,
522 ictx->header_oid, mock_image_ctx.image_watcher,
523 librbd::managed_lock::EXCLUSIVE, true, 0);
524 InSequence seq;
525
526 MockAcquireRequest request_lock_acquire;
527 expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, request_lock_acquire, 0);
528 ASSERT_EQ(0, when_acquire_lock(managed_lock));
529 ASSERT_TRUE(is_lock_owner(managed_lock));
530
531 MockReacquireRequest mock_reacquire_request;
532 C_SaferCond reacquire_ctx;
533 expect_get_watch_handle(*mock_image_ctx.image_watcher, 98765);
534 expect_reacquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, mock_reacquire_request, 0);
535 managed_lock.reacquire_lock(&reacquire_ctx);
536 ASSERT_EQ(0, reacquire_ctx.wait());
537
538 MockReleaseRequest shutdown_release;
539 expect_release_lock(ictx->op_work_queue, shutdown_release, 0);
540 ASSERT_EQ(0, when_shut_down(managed_lock));
541 ASSERT_FALSE(is_lock_owner(managed_lock));
542 }
543
544 TEST_F(TestMockManagedLock, AttemptReacquireBlocklistedLock) {
545 librbd::ImageCtx *ictx;
546 ASSERT_EQ(0, open_image(m_image_name, &ictx));
547
548 MockManagedLockImageCtx mock_image_ctx(*ictx);
549 MockManagedLock managed_lock(ictx->md_ctx, *ictx->asio_engine,
550 ictx->header_oid, mock_image_ctx.image_watcher,
551 librbd::managed_lock::EXCLUSIVE, true, 0);
552 InSequence seq;
553
554 MockAcquireRequest request_lock_acquire;
555 expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue,
556 request_lock_acquire, 0);
557 ASSERT_EQ(0, when_acquire_lock(managed_lock));
558 ASSERT_TRUE(is_lock_owner(managed_lock));
559
560 expect_get_watch_handle(*mock_image_ctx.image_watcher, 0);
561
562 MockReleaseRequest request_release;
563 expect_release_lock(ictx->op_work_queue, request_release, 0);
564
565 expect_get_watch_handle(*mock_image_ctx.image_watcher, 0);
566
567 managed_lock.reacquire_lock(nullptr);
568
569 ASSERT_EQ(0, when_shut_down(managed_lock));
570 ASSERT_FALSE(is_lock_owner(managed_lock));
571 }
572
573 TEST_F(TestMockManagedLock, ReacquireBlocklistedLock) {
574 librbd::ImageCtx *ictx;
575 ASSERT_EQ(0, open_image(m_image_name, &ictx));
576
577 MockManagedLockImageCtx mock_image_ctx(*ictx);
578 MockManagedLock managed_lock(ictx->md_ctx, *ictx->asio_engine,
579 ictx->header_oid, mock_image_ctx.image_watcher,
580 librbd::managed_lock::EXCLUSIVE, true, 0);
581 InSequence seq;
582
583 MockAcquireRequest request_lock_acquire;
584 expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue,
585 request_lock_acquire, 0);
586 ASSERT_EQ(0, when_acquire_lock(managed_lock));
587 ASSERT_TRUE(is_lock_owner(managed_lock));
588
589 expect_get_watch_handle(*mock_image_ctx.image_watcher, 0);
590
591 MockReleaseRequest request_release;
592 expect_release_lock(ictx->op_work_queue, request_release, 0);
593
594 MockAcquireRequest request_lock_reacquire;
595 expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue,
596 request_lock_reacquire, 0);
597 ASSERT_EQ(0, when_acquire_lock(managed_lock));
598 ASSERT_TRUE(is_lock_owner(managed_lock));
599
600 C_SaferCond reacquire_ctx;
601 managed_lock.reacquire_lock(&reacquire_ctx);
602 ASSERT_EQ(0, reacquire_ctx.wait());
603
604 MockReleaseRequest shutdown_release;
605 expect_release_lock(ictx->op_work_queue, shutdown_release, 0);
606 ASSERT_EQ(0, when_shut_down(managed_lock));
607 ASSERT_FALSE(is_lock_owner(managed_lock));
608 }
609
610 TEST_F(TestMockManagedLock, ReacquireLockError) {
611 librbd::ImageCtx *ictx;
612 ASSERT_EQ(0, open_image(m_image_name, &ictx));
613
614 MockManagedLockImageCtx mock_image_ctx(*ictx);
615 MockManagedLock managed_lock(ictx->md_ctx, *ictx->asio_engine,
616 ictx->header_oid, mock_image_ctx.image_watcher,
617 librbd::managed_lock::EXCLUSIVE, true, 0);
618 InSequence seq;
619
620 MockAcquireRequest request_lock_acquire;
621 expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, request_lock_acquire, 0);
622 ASSERT_EQ(0, when_acquire_lock(managed_lock));
623 ASSERT_TRUE(is_lock_owner(managed_lock));
624
625 MockReacquireRequest mock_reacquire_request;
626 C_SaferCond reacquire_ctx;
627 expect_get_watch_handle(*mock_image_ctx.image_watcher, 98765);
628 expect_reacquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, mock_reacquire_request, -EOPNOTSUPP);
629
630 MockReleaseRequest reacquire_lock_release;
631 expect_release_lock(ictx->op_work_queue, reacquire_lock_release, 0);
632
633 MockAcquireRequest reacquire_lock_acquire;
634 expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, reacquire_lock_acquire, 0);
635
636 managed_lock.reacquire_lock(&reacquire_ctx);
637 ASSERT_EQ(0, reacquire_ctx.wait());
638
639 MockReleaseRequest shutdown_release;
640 expect_release_lock(ictx->op_work_queue, shutdown_release, 0);
641 ASSERT_EQ(0, when_shut_down(managed_lock));
642 ASSERT_FALSE(is_lock_owner(managed_lock));
643 }
644
645 TEST_F(TestMockManagedLock, ReacquireWithSameCookie) {
646 librbd::ImageCtx *ictx;
647 ASSERT_EQ(0, open_image(m_image_name, &ictx));
648
649 MockManagedLockImageCtx mock_image_ctx(*ictx);
650 MockMockManagedLock managed_lock(ictx->md_ctx, *ictx->asio_engine,
651 ictx->header_oid, mock_image_ctx.image_watcher,
652 librbd::managed_lock::EXCLUSIVE, true, 0);
653 InSequence seq;
654
655 MockAcquireRequest request_lock_acquire;
656 expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, request_lock_acquire, 0);
657 ASSERT_EQ(0, when_acquire_lock(managed_lock));
658 ASSERT_TRUE(is_lock_owner(managed_lock));
659
660 // watcher with same cookie after rewatch
661 uint64_t client_id = 0;
662 C_SaferCond reacquire_ctx;
663 expect_post_reacquired_lock_handler(*mock_image_ctx.image_watcher, managed_lock, client_id);
664 managed_lock.reacquire_lock(&reacquire_ctx);
665 ASSERT_LT(0U, client_id);
666 ASSERT_TRUE(is_lock_owner(managed_lock));
667
668 MockReleaseRequest shutdown_release;
669 expect_pre_release_lock_handler(managed_lock, true, 0);
670 expect_release_lock(ictx->op_work_queue, shutdown_release, 0);
671 expect_post_release_lock_handler(managed_lock, true, 0, 0);
672 ASSERT_EQ(0, when_shut_down(managed_lock));
673 }
674
675 TEST_F(TestMockManagedLock, ShutDownWhileWaiting) {
676 librbd::ImageCtx *ictx;
677 ASSERT_EQ(0, open_image(m_image_name, &ictx));
678
679 MockManagedLockImageCtx mock_image_ctx(*ictx);
680 MockMockManagedLock managed_lock(ictx->md_ctx, *ictx->asio_engine,
681 ictx->header_oid, mock_image_ctx.image_watcher,
682 librbd::managed_lock::EXCLUSIVE, true, 0);
683
684 InSequence seq;
685
686 expect_get_watch_handle(*mock_image_ctx.image_watcher, 0);
687
688 C_SaferCond acquire_ctx;
689 managed_lock.acquire_lock(&acquire_ctx);
690
691 ASSERT_EQ(0, when_shut_down(managed_lock));
692 ASSERT_EQ(-ESHUTDOWN, acquire_ctx.wait());
693 ASSERT_FALSE(is_lock_owner(managed_lock));
694 }
695
696 } // namespace librbd