]>
Commit | Line | Data |
---|---|---|
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 | ||
16 | namespace librbd { | |
17 | ||
18 | namespace { | |
19 | ||
20 | struct MockTestImageCtx : public librbd::MockImageCtx { | |
21 | explicit MockTestImageCtx(librbd::ImageCtx &image_ctx) | |
22 | : librbd::MockImageCtx(image_ctx) { | |
23 | } | |
24 | }; | |
25 | ||
26 | } // anonymous namespace | |
27 | ||
28 | namespace deep_copy { | |
29 | ||
30 | template <> | |
31 | class SetHeadRequest<librbd::MockTestImageCtx> { | |
32 | public: | |
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 | ||
52 | template <> | |
53 | struct 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 | ||
76 | SetHeadRequest<librbd::MockTestImageCtx>* SetHeadRequest<librbd::MockTestImageCtx>::s_instance = nullptr; | |
77 | SnapshotCreateRequest<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" | |
84 | template class librbd::deep_copy::SnapshotCopyRequest<librbd::MockTestImageCtx>; | |
85 | ||
86 | namespace librbd { | |
87 | namespace deep_copy { | |
88 | ||
89 | using ::testing::_; | |
90 | using ::testing::DoAll; | |
91 | using ::testing::DoDefault; | |
92 | using ::testing::InSequence; | |
93 | using ::testing::Invoke; | |
94 | using ::testing::InvokeWithoutArgs; | |
95 | using ::testing::Return; | |
96 | using ::testing::ReturnNew; | |
97 | using ::testing::SetArgPointee; | |
98 | using ::testing::StrEq; | |
99 | using ::testing::WithArg; | |
100 | ||
101 | class TestMockDeepCopySnapshotCopyRequest : public TestMockFixture { | |
102 | public: | |
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 | ||
276 | TEST_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 | ||
299 | TEST_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 | ||
339 | TEST_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 | ||
368 | TEST_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 | ||
402 | TEST_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 | ||
445 | TEST_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 | ||
476 | TEST_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 | ||
517 | TEST_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 | ||
551 | TEST_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 | ||
592 | TEST_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 | ||
640 | TEST_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 | ||
679 | TEST_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 | ||
720 | TEST_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 | ||
757 | TEST_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 | ||
801 | TEST_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 | ||
822 | TEST_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 |
856 | TEST_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 |