]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/librbd/deep_copy/test_mock_SnapshotCopyRequest.cc
import ceph 15.2.10
[ceph.git] / ceph / src / test / librbd / deep_copy / test_mock_SnapshotCopyRequest.cc
CommitLineData
11fdf7f2
TL
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 "include/rbd/librbd.hpp"
6#include "librbd/ImageCtx.h"
7#include "librbd/ImageState.h"
8#include "librbd/Operations.h"
9#include "librbd/deep_copy/SetHeadRequest.h"
10#include "librbd/deep_copy/SnapshotCopyRequest.h"
11#include "librbd/deep_copy/SnapshotCreateRequest.h"
12#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
13#include "test/librbd/mock/MockImageCtx.h"
14#include "test/librbd/test_support.h"
15
16namespace librbd {
17
18namespace {
19
20struct MockTestImageCtx : public librbd::MockImageCtx {
21 explicit MockTestImageCtx(librbd::ImageCtx &image_ctx)
22 : librbd::MockImageCtx(image_ctx) {
23 }
24};
25
26} // anonymous namespace
27
28namespace deep_copy {
29
30template <>
31class SetHeadRequest<librbd::MockTestImageCtx> {
32public:
33 static SetHeadRequest* s_instance;
34 Context *on_finish;
35
36 static SetHeadRequest* create(librbd::MockTestImageCtx *image_ctx,
37 uint64_t size,
38 const cls::rbd::ParentImageSpec &parent_spec,
39 uint64_t parent_overlap, Context *on_finish) {
40 ceph_assert(s_instance != nullptr);
41 s_instance->on_finish = on_finish;
42 return s_instance;
43 }
44
45 SetHeadRequest() {
46 s_instance = this;
47 }
48
49 MOCK_METHOD0(send, void());
50};
51
52template <>
53struct SnapshotCreateRequest<librbd::MockTestImageCtx> {
54 static SnapshotCreateRequest* s_instance;
55 static SnapshotCreateRequest* create(librbd::MockTestImageCtx* image_ctx,
56 const std::string &snap_name,
57 const cls::rbd::SnapshotNamespace &snap_namespace,
58 uint64_t size,
59 const cls::rbd::ParentImageSpec &parent_spec,
60 uint64_t parent_overlap,
61 Context *on_finish) {
62 ceph_assert(s_instance != nullptr);
63 s_instance->on_finish = on_finish;
64 return s_instance;
65 }
66
67 Context *on_finish = nullptr;
68
69 SnapshotCreateRequest() {
70 s_instance = this;
71 }
72
73 MOCK_METHOD0(send, void());
74};
75
76SetHeadRequest<librbd::MockTestImageCtx>* SetHeadRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
77SnapshotCreateRequest<librbd::MockTestImageCtx>* SnapshotCreateRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
78
79} // namespace deep_copy
80} // namespace librbd
81
82// template definitions
83#include "librbd/deep_copy/SnapshotCopyRequest.cc"
84template class librbd::deep_copy::SnapshotCopyRequest<librbd::MockTestImageCtx>;
85
86namespace librbd {
87namespace deep_copy {
88
89using ::testing::_;
90using ::testing::DoAll;
91using ::testing::DoDefault;
92using ::testing::InSequence;
93using ::testing::Invoke;
94using ::testing::InvokeWithoutArgs;
95using ::testing::Return;
96using ::testing::ReturnNew;
97using ::testing::SetArgPointee;
98using ::testing::StrEq;
99using ::testing::WithArg;
100
101class TestMockDeepCopySnapshotCopyRequest : public TestMockFixture {
102public:
103 typedef SetHeadRequest<librbd::MockTestImageCtx> MockSetHeadRequest;
104 typedef SnapshotCopyRequest<librbd::MockTestImageCtx> MockSnapshotCopyRequest;
105 typedef SnapshotCreateRequest<librbd::MockTestImageCtx> MockSnapshotCreateRequest;
106
107 librbd::ImageCtx *m_src_image_ctx;
108 librbd::ImageCtx *m_dst_image_ctx;
109 ThreadPool *m_thread_pool;
110 ContextWQ *m_work_queue;
111
112 librbd::SnapSeqs m_snap_seqs;
113
114 void SetUp() override {
115 TestMockFixture::SetUp();
116
117 ASSERT_EQ(0, open_image(m_image_name, &m_src_image_ctx));
118
119 librbd::RBD rbd;
120 std::string dst_image_name = get_temp_image_name();
121 ASSERT_EQ(0, create_image_pp(rbd, m_ioctx, dst_image_name, m_image_size));
122 ASSERT_EQ(0, open_image(dst_image_name, &m_dst_image_ctx));
123
124 librbd::ImageCtx::get_thread_pool_instance(m_src_image_ctx->cct,
125 &m_thread_pool, &m_work_queue);
126 }
127
128 void prepare_exclusive_lock(librbd::MockImageCtx &mock_image_ctx,
129 librbd::MockExclusiveLock &mock_exclusive_lock) {
130 if ((mock_image_ctx.features & RBD_FEATURE_EXCLUSIVE_LOCK) == 0) {
131 return;
132 }
133 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
134 }
135
136 void expect_test_features(librbd::MockImageCtx &mock_image_ctx) {
137 EXPECT_CALL(mock_image_ctx, test_features(_, _))
138 .WillRepeatedly(WithArg<0>(Invoke([&mock_image_ctx](uint64_t features) {
139 return (mock_image_ctx.features & features) != 0;
140 })));
141 EXPECT_CALL(mock_image_ctx, test_features(_))
142 .WillRepeatedly(WithArg<0>(Invoke([&mock_image_ctx](uint64_t features) {
143 return (mock_image_ctx.features & features) != 0;
144 })));
145 }
146
147 void expect_start_op(librbd::MockExclusiveLock &mock_exclusive_lock) {
148 if ((m_src_image_ctx->features & RBD_FEATURE_EXCLUSIVE_LOCK) == 0) {
149 return;
150 }
9f95a23c 151 EXPECT_CALL(mock_exclusive_lock, start_op(_)).WillOnce(Return(new LambdaContext([](int){})));
11fdf7f2
TL
152 }
153
154 void expect_get_snap_namespace(librbd::MockTestImageCtx &mock_image_ctx,
155 uint64_t snap_id) {
156 EXPECT_CALL(mock_image_ctx, get_snap_namespace(snap_id, _))
9f95a23c
TL
157 .WillOnce(Invoke([&mock_image_ctx](uint64_t snap_id,
158 cls::rbd::SnapshotNamespace* snap_ns) {
159 auto it = mock_image_ctx.snap_info.find(snap_id);
160 *snap_ns = it->second.snap_namespace;
161 return 0;
162 }));
11fdf7f2
TL
163 }
164
165 void expect_snap_create(librbd::MockTestImageCtx &mock_image_ctx,
166 MockSnapshotCreateRequest &mock_snapshot_create_request,
167 const std::string &snap_name, uint64_t snap_id, int r) {
168 EXPECT_CALL(mock_snapshot_create_request, send())
169 .WillOnce(DoAll(Invoke([&mock_image_ctx, snap_id, snap_name]() {
170 inject_snap(mock_image_ctx, snap_id, snap_name);
171 }),
172 Invoke([this, &mock_snapshot_create_request, r]() {
173 m_work_queue->queue(mock_snapshot_create_request.on_finish, r);
174 })));
175 }
176
177 void expect_snap_remove(librbd::MockTestImageCtx &mock_image_ctx,
178 const std::string &snap_name, int r) {
179 EXPECT_CALL(*mock_image_ctx.operations, execute_snap_remove(_, StrEq(snap_name), _))
180 .WillOnce(WithArg<2>(Invoke([this, r](Context *ctx) {
181 m_work_queue->queue(ctx, r);
182 })));
183 }
184
185 void expect_snap_protect(librbd::MockTestImageCtx &mock_image_ctx,
186 const std::string &snap_name, int r) {
187 EXPECT_CALL(*mock_image_ctx.operations, execute_snap_protect(_, StrEq(snap_name), _))
188 .WillOnce(WithArg<2>(Invoke([this, r](Context *ctx) {
189 m_work_queue->queue(ctx, r);
190 })));
191 }
192
193 void expect_snap_unprotect(librbd::MockTestImageCtx &mock_image_ctx,
194 const std::string &snap_name, int r) {
195 EXPECT_CALL(*mock_image_ctx.operations, execute_snap_unprotect(_, StrEq(snap_name), _))
196 .WillOnce(WithArg<2>(Invoke([this, r](Context *ctx) {
197 m_work_queue->queue(ctx, r);
198 })));
199 }
200
201 void expect_snap_is_protected(librbd::MockTestImageCtx &mock_image_ctx,
202 uint64_t snap_id, bool is_protected, int r) {
203 EXPECT_CALL(mock_image_ctx, is_snap_protected(snap_id, _))
204 .WillOnce(DoAll(SetArgPointee<1>(is_protected),
205 Return(r)));
206 }
207
208 void expect_snap_is_unprotected(librbd::MockTestImageCtx &mock_image_ctx,
209 uint64_t snap_id, bool is_unprotected, int r) {
210 EXPECT_CALL(mock_image_ctx, is_snap_unprotected(snap_id, _))
211 .WillOnce(DoAll(SetArgPointee<1>(is_unprotected),
212 Return(r)));
213 }
214
215 void expect_set_head(MockSetHeadRequest &mock_set_head_request, int r) {
216 EXPECT_CALL(mock_set_head_request, send())
217 .WillOnce(Invoke([&mock_set_head_request, r]() {
218 mock_set_head_request.on_finish->complete(r);
219 }));
220 }
221
222 static void inject_snap(librbd::MockTestImageCtx &mock_image_ctx,
223 uint64_t snap_id, const std::string &snap_name) {
224 mock_image_ctx.snap_ids[{cls::rbd::UserSnapshotNamespace(),
225 snap_name}] = snap_id;
226 }
227
228 MockSnapshotCopyRequest *create_request(
229 librbd::MockTestImageCtx &mock_src_image_ctx,
9f95a23c
TL
230 librbd::MockTestImageCtx &mock_dst_image_ctx,
231 librados::snap_t src_snap_id_start,
232 librados::snap_t src_snap_id_end,
233 librados::snap_t dst_snap_id_start,
234 Context *on_finish) {
11fdf7f2 235 return new MockSnapshotCopyRequest(&mock_src_image_ctx, &mock_dst_image_ctx,
9f95a23c
TL
236 src_snap_id_start, src_snap_id_end,
237 dst_snap_id_start, false, m_work_queue,
11fdf7f2
TL
238 &m_snap_seqs, on_finish);
239 }
240
9f95a23c
TL
241 int create_snap(librbd::ImageCtx *image_ctx,
242 const cls::rbd::SnapshotNamespace& snap_ns,
243 const std::string &snap_name, bool protect) {
244 int r = image_ctx->operations->snap_create(snap_ns, snap_name.c_str());
11fdf7f2
TL
245 if (r < 0) {
246 return r;
247 }
248
249 if (protect) {
9f95a23c
TL
250 EXPECT_TRUE(boost::get<cls::rbd::UserSnapshotNamespace>(&snap_ns) !=
251 nullptr);
252 r = image_ctx->operations->snap_protect(snap_ns, snap_name.c_str());
11fdf7f2
TL
253 if (r < 0) {
254 return r;
255 }
256 }
257
258 r = image_ctx->state->refresh();
259 if (r < 0) {
260 return r;
261 }
262 return 0;
263 }
264
9f95a23c
TL
265 int create_snap(librbd::ImageCtx *image_ctx, const std::string &snap_name,
266 bool protect = false) {
267 return create_snap(image_ctx, cls::rbd::UserSnapshotNamespace{}, snap_name,
268 protect);
269 }
270
11fdf7f2
TL
271 void validate_snap_seqs(const librbd::SnapSeqs &snap_seqs) {
272 ASSERT_EQ(snap_seqs, m_snap_seqs);
273 }
274};
275
276TEST_F(TestMockDeepCopySnapshotCopyRequest, Empty) {
277 librbd::MockTestImageCtx mock_src_image_ctx(*m_src_image_ctx);
278 librbd::MockTestImageCtx mock_dst_image_ctx(*m_dst_image_ctx);
279 MockSetHeadRequest mock_set_head_request;
280
281 librbd::MockExclusiveLock mock_exclusive_lock;
282 prepare_exclusive_lock(mock_dst_image_ctx, mock_exclusive_lock);
283
284 expect_test_features(mock_dst_image_ctx);
285
286 InSequence seq;
287 expect_set_head(mock_set_head_request, 0);
288
289 C_SaferCond ctx;
290 MockSnapshotCopyRequest *request = create_request(mock_src_image_ctx,
9f95a23c
TL
291 mock_dst_image_ctx, 0,
292 CEPH_NOSNAP, 0, &ctx);
11fdf7f2
TL
293 request->send();
294 ASSERT_EQ(0, ctx.wait());
295
296 validate_snap_seqs({});
297}
298
299TEST_F(TestMockDeepCopySnapshotCopyRequest, SnapCreate) {
300 ASSERT_EQ(0, create_snap(m_src_image_ctx, "snap1"));
301 ASSERT_EQ(0, create_snap(m_src_image_ctx, "snap2"));
302
303 uint64_t src_snap_id1 = m_src_image_ctx->snap_ids[
304 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
305 uint64_t src_snap_id2 = m_src_image_ctx->snap_ids[
306 {cls::rbd::UserSnapshotNamespace(), "snap2"}];
307
308 librbd::MockTestImageCtx mock_src_image_ctx(*m_src_image_ctx);
309 librbd::MockTestImageCtx mock_dst_image_ctx(*m_dst_image_ctx);
310 MockSnapshotCreateRequest mock_snapshot_create_request;
311 MockSetHeadRequest mock_set_head_request;
312
313 librbd::MockExclusiveLock mock_exclusive_lock;
314 prepare_exclusive_lock(mock_dst_image_ctx, mock_exclusive_lock);
315
316 expect_test_features(mock_dst_image_ctx);
317
318 InSequence seq;
319 expect_get_snap_namespace(mock_src_image_ctx, src_snap_id1);
320 expect_start_op(mock_exclusive_lock);
321 expect_snap_create(mock_dst_image_ctx, mock_snapshot_create_request, "snap1", 12, 0);
322 expect_get_snap_namespace(mock_src_image_ctx, src_snap_id2);
323 expect_start_op(mock_exclusive_lock);
324 expect_snap_create(mock_dst_image_ctx, mock_snapshot_create_request, "snap2", 14, 0);
325 expect_snap_is_protected(mock_src_image_ctx, src_snap_id1, false, 0);
326 expect_snap_is_protected(mock_src_image_ctx, src_snap_id2, false, 0);
327 expect_set_head(mock_set_head_request, 0);
328
329 C_SaferCond ctx;
330 MockSnapshotCopyRequest *request = create_request(mock_src_image_ctx,
9f95a23c
TL
331 mock_dst_image_ctx, 0,
332 CEPH_NOSNAP, 0, &ctx);
11fdf7f2
TL
333 request->send();
334 ASSERT_EQ(0, ctx.wait());
335
336 validate_snap_seqs({{src_snap_id1, 12}, {src_snap_id2, 14}});
337}
338
339TEST_F(TestMockDeepCopySnapshotCopyRequest, SnapCreateError) {
340 ASSERT_EQ(0, create_snap(m_src_image_ctx, "snap1"));
341
342 librbd::MockTestImageCtx mock_src_image_ctx(*m_src_image_ctx);
343 librbd::MockTestImageCtx mock_dst_image_ctx(*m_dst_image_ctx);
344 MockSnapshotCreateRequest mock_snapshot_create_request;
345
346 librbd::MockExclusiveLock mock_exclusive_lock;
347 prepare_exclusive_lock(mock_dst_image_ctx, mock_exclusive_lock);
348
349 uint64_t src_snap_id1 = mock_src_image_ctx.snap_ids[
350 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
351
352 expect_test_features(mock_dst_image_ctx);
353
354 InSequence seq;
355 expect_get_snap_namespace(mock_src_image_ctx, src_snap_id1);
356 expect_start_op(mock_exclusive_lock);
357 expect_snap_create(mock_dst_image_ctx, mock_snapshot_create_request, "snap1",
358 12, -EINVAL);
359
360 C_SaferCond ctx;
361 MockSnapshotCopyRequest *request = create_request(mock_src_image_ctx,
9f95a23c
TL
362 mock_dst_image_ctx, 0,
363 CEPH_NOSNAP, 0, &ctx);
11fdf7f2
TL
364 request->send();
365 ASSERT_EQ(-EINVAL, ctx.wait());
366}
367
368TEST_F(TestMockDeepCopySnapshotCopyRequest, SnapCreateCancel) {
369 ASSERT_EQ(0, create_snap(m_src_image_ctx, "snap1"));
370
371 librbd::MockTestImageCtx mock_src_image_ctx(*m_src_image_ctx);
372 librbd::MockTestImageCtx mock_dst_image_ctx(*m_dst_image_ctx);
373 MockSnapshotCreateRequest mock_snapshot_create_request;
374
375 librbd::MockExclusiveLock mock_exclusive_lock;
376 prepare_exclusive_lock(mock_dst_image_ctx, mock_exclusive_lock);
377
378 uint64_t src_snap_id1 = m_src_image_ctx->snap_ids[
379 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
380 expect_get_snap_namespace(mock_src_image_ctx, src_snap_id1);
381
382 C_SaferCond ctx;
383 MockSnapshotCopyRequest *request = create_request(mock_src_image_ctx,
9f95a23c
TL
384 mock_dst_image_ctx, 0,
385 CEPH_NOSNAP, 0, &ctx);
11fdf7f2
TL
386 expect_test_features(mock_dst_image_ctx);
387
388 InSequence seq;
389 expect_start_op(mock_exclusive_lock);
390 EXPECT_CALL(mock_snapshot_create_request, send())
391 .WillOnce(DoAll(InvokeWithoutArgs([request]() {
392 request->cancel();
393 }),
394 Invoke([this, &mock_snapshot_create_request]() {
395 m_work_queue->queue(mock_snapshot_create_request.on_finish, 0);
396 })));
397
398 request->send();
399 ASSERT_EQ(-ECANCELED, ctx.wait());
400}
401
402TEST_F(TestMockDeepCopySnapshotCopyRequest, SnapRemoveAndCreate) {
403 ASSERT_EQ(0, create_snap(m_src_image_ctx, "snap1"));
404 ASSERT_EQ(0, create_snap(m_dst_image_ctx, "snap1"));
405
406 uint64_t src_snap_id1 = m_src_image_ctx->snap_ids[
407 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
408 uint64_t dst_snap_id1 = m_dst_image_ctx->snap_ids[
409 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
410
411 librbd::MockTestImageCtx mock_src_image_ctx(*m_src_image_ctx);
412 librbd::MockTestImageCtx mock_dst_image_ctx(*m_dst_image_ctx);
413 MockSnapshotCreateRequest mock_snapshot_create_request;
414 MockSetHeadRequest mock_set_head_request;
415
416 librbd::MockExclusiveLock mock_exclusive_lock;
417 prepare_exclusive_lock(mock_dst_image_ctx, mock_exclusive_lock);
418
419 expect_test_features(mock_dst_image_ctx);
420
421 InSequence seq;
422 expect_snap_is_unprotected(mock_dst_image_ctx,
423 m_dst_image_ctx->snap_ids[
424 {cls::rbd::UserSnapshotNamespace(), "snap1"}],
425 true, 0);
426 expect_get_snap_namespace(mock_dst_image_ctx, dst_snap_id1);
427 expect_start_op(mock_exclusive_lock);
428 expect_snap_remove(mock_dst_image_ctx, "snap1", 0);
429 expect_get_snap_namespace(mock_src_image_ctx, src_snap_id1);
430 expect_start_op(mock_exclusive_lock);
431 expect_snap_create(mock_dst_image_ctx, mock_snapshot_create_request, "snap1", 12, 0);
432 expect_snap_is_protected(mock_src_image_ctx, src_snap_id1, false, 0);
433 expect_set_head(mock_set_head_request, 0);
434
435 C_SaferCond ctx;
436 MockSnapshotCopyRequest *request = create_request(mock_src_image_ctx,
9f95a23c
TL
437 mock_dst_image_ctx, 0,
438 CEPH_NOSNAP, 0, &ctx);
11fdf7f2
TL
439 request->send();
440 ASSERT_EQ(0, ctx.wait());
441
442 validate_snap_seqs({{src_snap_id1, 12}});
443}
444
445TEST_F(TestMockDeepCopySnapshotCopyRequest, SnapRemoveError) {
446 ASSERT_EQ(0, create_snap(m_dst_image_ctx, "snap1"));
447
448 librbd::MockTestImageCtx mock_src_image_ctx(*m_src_image_ctx);
449 librbd::MockTestImageCtx mock_dst_image_ctx(*m_dst_image_ctx);
450
451 librbd::MockExclusiveLock mock_exclusive_lock;
452 prepare_exclusive_lock(mock_dst_image_ctx, mock_exclusive_lock);
453
454 uint64_t dst_snap_id1 = m_dst_image_ctx->snap_ids[
455 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
456
457 expect_test_features(mock_dst_image_ctx);
458
459 InSequence seq;
460 expect_snap_is_unprotected(mock_dst_image_ctx,
461 m_dst_image_ctx->snap_ids[
462 {cls::rbd::UserSnapshotNamespace(), "snap1"}],
463 true, 0);
464 expect_get_snap_namespace(mock_dst_image_ctx, dst_snap_id1);
465 expect_start_op(mock_exclusive_lock);
466 expect_snap_remove(mock_dst_image_ctx, "snap1", -EINVAL);
467
468 C_SaferCond ctx;
469 MockSnapshotCopyRequest *request = create_request(mock_src_image_ctx,
9f95a23c
TL
470 mock_dst_image_ctx, 0,
471 CEPH_NOSNAP, 0, &ctx);
11fdf7f2
TL
472 request->send();
473 ASSERT_EQ(-EINVAL, ctx.wait());
474}
475
476TEST_F(TestMockDeepCopySnapshotCopyRequest, SnapUnprotect) {
477 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
478
479 ASSERT_EQ(0, create_snap(m_src_image_ctx, "snap1", true));
480 ASSERT_EQ(0, create_snap(m_dst_image_ctx, "snap1", true));
481
482 uint64_t src_snap_id1 = m_src_image_ctx->snap_ids[
483 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
484 uint64_t dst_snap_id1 = m_dst_image_ctx->snap_ids[
485 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
486 m_snap_seqs[src_snap_id1] = dst_snap_id1;
487
488 librbd::MockTestImageCtx mock_src_image_ctx(*m_src_image_ctx);
489 librbd::MockTestImageCtx mock_dst_image_ctx(*m_dst_image_ctx);
490 MockSetHeadRequest mock_set_head_request;
491
492 librbd::MockExclusiveLock mock_exclusive_lock;
493 prepare_exclusive_lock(mock_dst_image_ctx, mock_exclusive_lock);
494
495 expect_test_features(mock_dst_image_ctx);
496
497 InSequence seq;
498 expect_snap_is_unprotected(mock_dst_image_ctx, dst_snap_id1, false, 0);
499 expect_snap_is_unprotected(mock_src_image_ctx, src_snap_id1, true, 0);
500 expect_start_op(mock_exclusive_lock);
501 expect_snap_unprotect(mock_dst_image_ctx, "snap1", 0);
502 expect_get_snap_namespace(mock_dst_image_ctx, dst_snap_id1);
503 expect_get_snap_namespace(mock_src_image_ctx, src_snap_id1);
504 expect_snap_is_protected(mock_src_image_ctx, src_snap_id1, false, 0);
505 expect_set_head(mock_set_head_request, 0);
506
507 C_SaferCond ctx;
508 MockSnapshotCopyRequest *request = create_request(mock_src_image_ctx,
9f95a23c
TL
509 mock_dst_image_ctx, 0,
510 CEPH_NOSNAP, 0, &ctx);
11fdf7f2
TL
511 request->send();
512 ASSERT_EQ(0, ctx.wait());
513
514 validate_snap_seqs({{src_snap_id1, dst_snap_id1}});
515}
516
517TEST_F(TestMockDeepCopySnapshotCopyRequest, SnapUnprotectError) {
518 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
519
520 ASSERT_EQ(0, create_snap(m_src_image_ctx, "snap1", true));
521 ASSERT_EQ(0, create_snap(m_dst_image_ctx, "snap1", true));
522
523 uint64_t src_snap_id1 = m_src_image_ctx->snap_ids[
524 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
525 uint64_t dst_snap_id1 = m_dst_image_ctx->snap_ids[
526 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
527 m_snap_seqs[src_snap_id1] = dst_snap_id1;
528
529 librbd::MockTestImageCtx mock_src_image_ctx(*m_src_image_ctx);
530 librbd::MockTestImageCtx mock_dst_image_ctx(*m_dst_image_ctx);
531
532 librbd::MockExclusiveLock mock_exclusive_lock;
533 prepare_exclusive_lock(mock_dst_image_ctx, mock_exclusive_lock);
534
535 expect_test_features(mock_dst_image_ctx);
536
537 InSequence seq;
538 expect_snap_is_unprotected(mock_dst_image_ctx, dst_snap_id1, false, 0);
539 expect_snap_is_unprotected(mock_src_image_ctx, src_snap_id1, true, 0);
540 expect_start_op(mock_exclusive_lock);
541 expect_snap_unprotect(mock_dst_image_ctx, "snap1", -EBUSY);
542
543 C_SaferCond ctx;
544 MockSnapshotCopyRequest *request = create_request(mock_src_image_ctx,
9f95a23c
TL
545 mock_dst_image_ctx, 0,
546 CEPH_NOSNAP, 0, &ctx);
11fdf7f2
TL
547 request->send();
548 ASSERT_EQ(-EBUSY, ctx.wait());
549}
550
551TEST_F(TestMockDeepCopySnapshotCopyRequest, SnapUnprotectCancel) {
552 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
553
554 ASSERT_EQ(0, create_snap(m_src_image_ctx, "snap1", true));
555 ASSERT_EQ(0, create_snap(m_dst_image_ctx, "snap1", true));
556
557 uint64_t src_snap_id1 = m_src_image_ctx->snap_ids[
558 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
559 uint64_t dst_snap_id1 = m_dst_image_ctx->snap_ids[
560 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
561 m_snap_seqs[src_snap_id1] = dst_snap_id1;
562
563 librbd::MockTestImageCtx mock_src_image_ctx(*m_src_image_ctx);
564 librbd::MockTestImageCtx mock_dst_image_ctx(*m_dst_image_ctx);
565
566 librbd::MockExclusiveLock mock_exclusive_lock;
567 prepare_exclusive_lock(mock_dst_image_ctx, mock_exclusive_lock);
568
569 C_SaferCond ctx;
570 MockSnapshotCopyRequest *request = create_request(mock_src_image_ctx,
9f95a23c
TL
571 mock_dst_image_ctx, 0,
572 CEPH_NOSNAP, 0, &ctx);
11fdf7f2
TL
573 expect_test_features(mock_dst_image_ctx);
574
575 InSequence seq;
576 expect_snap_is_unprotected(mock_dst_image_ctx, dst_snap_id1, false, 0);
577 expect_snap_is_unprotected(mock_src_image_ctx, src_snap_id1, true, 0);
578 expect_start_op(mock_exclusive_lock);
579 EXPECT_CALL(*mock_dst_image_ctx.operations,
580 execute_snap_unprotect(_, StrEq("snap1"), _))
581 .WillOnce(DoAll(InvokeWithoutArgs([request]() {
582 request->cancel();
583 }),
584 WithArg<2>(Invoke([this](Context *ctx) {
585 m_work_queue->queue(ctx, 0);
586 }))));
587
588 request->send();
589 ASSERT_EQ(-ECANCELED, ctx.wait());
590}
591
592TEST_F(TestMockDeepCopySnapshotCopyRequest, SnapUnprotectRemove) {
593 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
594
595 ASSERT_EQ(0, create_snap(m_src_image_ctx, "snap1", true));
596 ASSERT_EQ(0, create_snap(m_dst_image_ctx, "snap1", true));
597
598 uint64_t src_snap_id1 = m_src_image_ctx->snap_ids[
599 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
600 uint64_t dst_snap_id1 = m_dst_image_ctx->snap_ids[
601 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
602
603 librbd::MockTestImageCtx mock_src_image_ctx(*m_src_image_ctx);
604 librbd::MockTestImageCtx mock_dst_image_ctx(*m_dst_image_ctx);
605 MockSnapshotCreateRequest mock_snapshot_create_request;
606 MockSetHeadRequest mock_set_head_request;
607
608 librbd::MockExclusiveLock mock_exclusive_lock;
609 prepare_exclusive_lock(mock_dst_image_ctx, mock_exclusive_lock);
610
611 expect_test_features(mock_dst_image_ctx);
612
613 InSequence seq;
614 expect_snap_is_unprotected(mock_dst_image_ctx,
615 m_dst_image_ctx->snap_ids[
616 {cls::rbd::UserSnapshotNamespace(), "snap1"}],
617 false, 0);
618 expect_start_op(mock_exclusive_lock);
619 expect_snap_unprotect(mock_dst_image_ctx, "snap1", 0);
620 expect_get_snap_namespace(mock_dst_image_ctx, dst_snap_id1);
621 expect_start_op(mock_exclusive_lock);
622 expect_snap_remove(mock_dst_image_ctx, "snap1", 0);
623 expect_get_snap_namespace(mock_src_image_ctx, src_snap_id1);
624 expect_start_op(mock_exclusive_lock);
625 expect_snap_create(mock_dst_image_ctx, mock_snapshot_create_request, "snap1",
626 12, 0);
627 expect_snap_is_protected(mock_src_image_ctx, src_snap_id1, false, 0);
628 expect_set_head(mock_set_head_request, 0);
629
630 C_SaferCond ctx;
631 MockSnapshotCopyRequest *request = create_request(mock_src_image_ctx,
9f95a23c
TL
632 mock_dst_image_ctx, 0,
633 CEPH_NOSNAP, 0, &ctx);
11fdf7f2
TL
634 request->send();
635 ASSERT_EQ(0, ctx.wait());
636
637 validate_snap_seqs({{src_snap_id1, 12}});
638}
639
640TEST_F(TestMockDeepCopySnapshotCopyRequest, SnapCreateProtect) {
641 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
642
643 ASSERT_EQ(0, create_snap(m_src_image_ctx, "snap1", true));
644
645 uint64_t src_snap_id1 = m_src_image_ctx->snap_ids[
646 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
647
648 librbd::MockTestImageCtx mock_src_image_ctx(*m_src_image_ctx);
649 librbd::MockTestImageCtx mock_dst_image_ctx(*m_dst_image_ctx);
650 MockSnapshotCreateRequest mock_snapshot_create_request;
651 MockSetHeadRequest mock_set_head_request;
652
653 librbd::MockExclusiveLock mock_exclusive_lock;
654 prepare_exclusive_lock(mock_dst_image_ctx, mock_exclusive_lock);
655
656 expect_test_features(mock_dst_image_ctx);
657
658 InSequence seq;
659 expect_get_snap_namespace(mock_src_image_ctx, src_snap_id1);
660 expect_start_op(mock_exclusive_lock);
661 expect_snap_create(mock_dst_image_ctx, mock_snapshot_create_request, "snap1",
662 12, 0);
663 expect_snap_is_protected(mock_src_image_ctx, src_snap_id1, true, 0);
664 expect_snap_is_protected(mock_dst_image_ctx, 12, false, 0);
665 expect_start_op(mock_exclusive_lock);
666 expect_snap_protect(mock_dst_image_ctx, "snap1", 0);
667 expect_set_head(mock_set_head_request, 0);
668
669 C_SaferCond ctx;
670 MockSnapshotCopyRequest *request = create_request(mock_src_image_ctx,
9f95a23c
TL
671 mock_dst_image_ctx, 0,
672 CEPH_NOSNAP, 0, &ctx);
11fdf7f2
TL
673 request->send();
674 ASSERT_EQ(0, ctx.wait());
675
676 validate_snap_seqs({{src_snap_id1, 12}});
677}
678
679TEST_F(TestMockDeepCopySnapshotCopyRequest, SnapProtect) {
680 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
681
682 ASSERT_EQ(0, create_snap(m_src_image_ctx, "snap1", true));
683 ASSERT_EQ(0, create_snap(m_dst_image_ctx, "snap1", true));
684
685 uint64_t src_snap_id1 = m_src_image_ctx->snap_ids[
686 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
687 uint64_t dst_snap_id1 = m_dst_image_ctx->snap_ids[
688 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
689 m_snap_seqs[src_snap_id1] = dst_snap_id1;
690
691 librbd::MockTestImageCtx mock_src_image_ctx(*m_src_image_ctx);
692 librbd::MockTestImageCtx mock_dst_image_ctx(*m_dst_image_ctx);
693 MockSetHeadRequest mock_set_head_request;
694
695 librbd::MockExclusiveLock mock_exclusive_lock;
696 prepare_exclusive_lock(mock_dst_image_ctx, mock_exclusive_lock);
697
698 expect_test_features(mock_dst_image_ctx);
699
700 InSequence seq;
701 expect_snap_is_unprotected(mock_dst_image_ctx, dst_snap_id1, true, 0);
702 expect_get_snap_namespace(mock_dst_image_ctx, dst_snap_id1);
703 expect_get_snap_namespace(mock_src_image_ctx, src_snap_id1);
704 expect_snap_is_protected(mock_src_image_ctx, src_snap_id1, true, 0);
705 expect_snap_is_protected(mock_dst_image_ctx, dst_snap_id1, false, 0);
706 expect_start_op(mock_exclusive_lock);
707 expect_snap_protect(mock_dst_image_ctx, "snap1", 0);
708 expect_set_head(mock_set_head_request, 0);
709
710 C_SaferCond ctx;
711 MockSnapshotCopyRequest *request = create_request(mock_src_image_ctx,
9f95a23c
TL
712 mock_dst_image_ctx, 0,
713 CEPH_NOSNAP, 0, &ctx);
11fdf7f2
TL
714 request->send();
715 ASSERT_EQ(0, ctx.wait());
716
717 validate_snap_seqs({{src_snap_id1, dst_snap_id1}});
718}
719
720TEST_F(TestMockDeepCopySnapshotCopyRequest, SnapProtectError) {
721 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
722
723 ASSERT_EQ(0, create_snap(m_src_image_ctx, "snap1", true));
724 ASSERT_EQ(0, create_snap(m_dst_image_ctx, "snap1", true));
725
726 uint64_t src_snap_id1 = m_src_image_ctx->snap_ids[
727 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
728 uint64_t dst_snap_id1 = m_dst_image_ctx->snap_ids[
729 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
730 m_snap_seqs[src_snap_id1] = dst_snap_id1;
731
732 librbd::MockTestImageCtx mock_src_image_ctx(*m_src_image_ctx);
733 librbd::MockTestImageCtx mock_dst_image_ctx(*m_dst_image_ctx);
734
735 librbd::MockExclusiveLock mock_exclusive_lock;
736 prepare_exclusive_lock(mock_dst_image_ctx, mock_exclusive_lock);
737
738 expect_test_features(mock_dst_image_ctx);
739
740 InSequence seq;
741 expect_snap_is_unprotected(mock_dst_image_ctx, dst_snap_id1, true, 0);
742 expect_get_snap_namespace(mock_dst_image_ctx, dst_snap_id1);
743 expect_get_snap_namespace(mock_src_image_ctx, src_snap_id1);
744 expect_snap_is_protected(mock_src_image_ctx, src_snap_id1, true, 0);
745 expect_snap_is_protected(mock_dst_image_ctx, dst_snap_id1, false, 0);
746 expect_start_op(mock_exclusive_lock);
747 expect_snap_protect(mock_dst_image_ctx, "snap1", -EINVAL);
748
749 C_SaferCond ctx;
750 MockSnapshotCopyRequest *request = create_request(mock_src_image_ctx,
9f95a23c
TL
751 mock_dst_image_ctx, 0,
752 CEPH_NOSNAP, 0, &ctx);
11fdf7f2
TL
753 request->send();
754 ASSERT_EQ(-EINVAL, ctx.wait());
755}
756
757TEST_F(TestMockDeepCopySnapshotCopyRequest, SnapProtectCancel) {
758 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
759
760 ASSERT_EQ(0, create_snap(m_src_image_ctx, "snap1", true));
761 ASSERT_EQ(0, create_snap(m_dst_image_ctx, "snap1", true));
762
763 uint64_t src_snap_id1 = m_src_image_ctx->snap_ids[
764 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
765 uint64_t dst_snap_id1 = m_dst_image_ctx->snap_ids[
766 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
767 m_snap_seqs[src_snap_id1] = dst_snap_id1;
768
769 librbd::MockTestImageCtx mock_src_image_ctx(*m_src_image_ctx);
770 librbd::MockTestImageCtx mock_dst_image_ctx(*m_dst_image_ctx);
771
772 librbd::MockExclusiveLock mock_exclusive_lock;
773 prepare_exclusive_lock(mock_dst_image_ctx, mock_exclusive_lock);
774
775 C_SaferCond ctx;
776 MockSnapshotCopyRequest *request = create_request(mock_src_image_ctx,
9f95a23c
TL
777 mock_dst_image_ctx, 0,
778 CEPH_NOSNAP, 0, &ctx);
11fdf7f2
TL
779 expect_test_features(mock_dst_image_ctx);
780
781 InSequence seq;
782 expect_snap_is_unprotected(mock_dst_image_ctx, dst_snap_id1, true, 0);
783 expect_get_snap_namespace(mock_dst_image_ctx, dst_snap_id1);
784 expect_get_snap_namespace(mock_src_image_ctx, src_snap_id1);
785 expect_snap_is_protected(mock_src_image_ctx, src_snap_id1, true, 0);
786 expect_snap_is_protected(mock_dst_image_ctx, dst_snap_id1, false, 0);
787 expect_start_op(mock_exclusive_lock);
788 EXPECT_CALL(*mock_dst_image_ctx.operations,
789 execute_snap_protect(_, StrEq("snap1"), _))
790 .WillOnce(DoAll(InvokeWithoutArgs([request]() {
791 request->cancel();
792 }),
793 WithArg<2>(Invoke([this](Context *ctx) {
794 m_work_queue->queue(ctx, 0);
795 }))));
796
797 request->send();
798 ASSERT_EQ(-ECANCELED, ctx.wait());
799}
800
801TEST_F(TestMockDeepCopySnapshotCopyRequest, SetHeadError) {
802 librbd::MockTestImageCtx mock_src_image_ctx(*m_src_image_ctx);
803 librbd::MockTestImageCtx mock_dst_image_ctx(*m_dst_image_ctx);
804 MockSetHeadRequest mock_set_head_request;
805
806 librbd::MockExclusiveLock mock_exclusive_lock;
807 prepare_exclusive_lock(mock_dst_image_ctx, mock_exclusive_lock);
808
809 expect_test_features(mock_dst_image_ctx);
810
811 InSequence seq;
812 expect_set_head(mock_set_head_request, -EINVAL);
813
814 C_SaferCond ctx;
815 MockSnapshotCopyRequest *request = create_request(mock_src_image_ctx,
9f95a23c
TL
816 mock_dst_image_ctx, 0,
817 CEPH_NOSNAP, 0, &ctx);
11fdf7f2
TL
818 request->send();
819 ASSERT_EQ(-EINVAL, ctx.wait());
820}
821
822TEST_F(TestMockDeepCopySnapshotCopyRequest, NoSetHead) {
823 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
824
825 ASSERT_EQ(0, create_snap(m_src_image_ctx, "snap1", true));
826
827 uint64_t src_snap_id1 = m_src_image_ctx->snap_ids[
828 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
829
830 librbd::MockTestImageCtx mock_src_image_ctx(*m_src_image_ctx);
831 librbd::MockTestImageCtx mock_dst_image_ctx(*m_dst_image_ctx);
832 MockSnapshotCreateRequest mock_snapshot_create_request;
833
834 librbd::MockExclusiveLock mock_exclusive_lock;
835 prepare_exclusive_lock(mock_dst_image_ctx, mock_exclusive_lock);
836
837 expect_test_features(mock_dst_image_ctx);
838
839 InSequence seq;
840 expect_get_snap_namespace(mock_src_image_ctx, src_snap_id1);
841 expect_start_op(mock_exclusive_lock);
842 expect_snap_create(mock_dst_image_ctx, mock_snapshot_create_request, "snap1",
843 12, 0);
844 expect_snap_is_protected(mock_src_image_ctx, src_snap_id1, false, 0);
845
846 C_SaferCond ctx;
847 MockSnapshotCopyRequest *request = create_request(mock_src_image_ctx,
9f95a23c
TL
848 mock_dst_image_ctx,0,
849 src_snap_id1, 0, &ctx);
11fdf7f2
TL
850 request->send();
851 ASSERT_EQ(0, ctx.wait());
852
853 validate_snap_seqs({{src_snap_id1, 12}});
854}
855
9f95a23c
TL
856TEST_F(TestMockDeepCopySnapshotCopyRequest, StartEndLimit) {
857 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
858
859 ASSERT_EQ(0, create_snap(m_src_image_ctx, "snap1", false));
860 ASSERT_EQ(0, create_snap(m_src_image_ctx, "snap2", false));
861 ASSERT_EQ(0, create_snap(m_src_image_ctx,
862 {cls::rbd::MirrorSnapshotNamespace{
863 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY,
864 {"peer uuid1"}, "", CEPH_NOSNAP}},
865 "snap3", false));
866 auto src_snap_id1 = m_src_image_ctx->snaps[2];
867 auto src_snap_id2 = m_src_image_ctx->snaps[1];
868 auto src_snap_id3 = m_src_image_ctx->snaps[0];
869
870 ASSERT_EQ(0, create_snap(m_dst_image_ctx, "snap0", true));
871 ASSERT_EQ(0, create_snap(m_dst_image_ctx, "snap1", false));
872 ASSERT_EQ(0, create_snap(m_dst_image_ctx, "snap3", false));
873 auto dst_snap_id1 = m_dst_image_ctx->snaps[1];
874 auto dst_snap_id3 = m_dst_image_ctx->snaps[0];
875
876 librbd::MockTestImageCtx mock_src_image_ctx(*m_src_image_ctx);
877 librbd::MockTestImageCtx mock_dst_image_ctx(*m_dst_image_ctx);
878 MockSnapshotCreateRequest mock_snapshot_create_request;
879
880 librbd::MockExclusiveLock mock_exclusive_lock;
881 prepare_exclusive_lock(mock_dst_image_ctx, mock_exclusive_lock);
882
883 expect_test_features(mock_dst_image_ctx);
884
885 InSequence seq;
886 expect_snap_is_unprotected(mock_dst_image_ctx, dst_snap_id3,
887 true, 0);
888
889 expect_get_snap_namespace(mock_dst_image_ctx, dst_snap_id3);
890 expect_start_op(mock_exclusive_lock);
891 expect_snap_remove(mock_dst_image_ctx, "snap3", 0);
892
893 expect_get_snap_namespace(mock_src_image_ctx, src_snap_id2);
894 expect_start_op(mock_exclusive_lock);
895 expect_snap_create(mock_dst_image_ctx, mock_snapshot_create_request, "snap2",
896 12, 0);
897 expect_get_snap_namespace(mock_src_image_ctx, src_snap_id3);
898
899 expect_snap_is_protected(mock_src_image_ctx, src_snap_id2, false, 0);
900 expect_snap_is_protected(mock_src_image_ctx, src_snap_id3, false, 0);
901
902 MockSetHeadRequest mock_set_head_request;
903 expect_set_head(mock_set_head_request, 0);
904
905 C_SaferCond ctx;
906 MockSnapshotCopyRequest *request = create_request(mock_src_image_ctx,
907 mock_dst_image_ctx,
908 src_snap_id1,
909 src_snap_id3,
910 dst_snap_id1, &ctx);
911 request->send();
912 ASSERT_EQ(0, ctx.wait());
913
914 validate_snap_seqs({{src_snap_id2, 12}, {src_snap_id3, CEPH_NOSNAP}});
915}
916
11fdf7f2
TL
917} // namespace deep_copy
918} // namespace librbd