]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/librbd/test_Migration.cc
import ceph quincy 17.2.6
[ceph.git] / ceph / src / test / librbd / test_Migration.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/librados/test.h"
5 #include "test/librbd/test_fixture.h"
6 #include "test/librbd/test_support.h"
7 #include "librbd/ImageState.h"
8 #include "librbd/Operations.h"
9 #include "librbd/api/Group.h"
10 #include "librbd/api/Image.h"
11 #include "librbd/api/Io.h"
12 #include "librbd/api/Migration.h"
13 #include "librbd/api/Mirror.h"
14 #include "librbd/api/Namespace.h"
15 #include "librbd/api/Snapshot.h"
16 #include "librbd/image/AttachChildRequest.h"
17 #include "librbd/image/AttachParentRequest.h"
18 #include "librbd/internal.h"
19 #include "librbd/io/ReadResult.h"
20 #include "common/Cond.h"
21 #include <boost/scope_exit.hpp>
22
23 void register_test_migration() {
24 }
25
26 namespace librbd {
27
28 struct TestMigration : public TestFixture {
29 static void SetUpTestCase() {
30 TestFixture::SetUpTestCase();
31
32 _other_pool_name = get_temp_pool_name("test-librbd-");
33 ASSERT_EQ(0, _rados.pool_create(_other_pool_name.c_str()));
34 }
35
36 static void TearDownTestCase() {
37 ASSERT_EQ(0, _rados.pool_delete(_other_pool_name.c_str()));
38
39 TestFixture::TearDownTestCase();
40 }
41
42 void SetUp() override {
43 TestFixture::SetUp();
44
45 ASSERT_EQ(0, _rados.ioctx_create(_other_pool_name.c_str(),
46 _other_pool_ioctx));
47
48 open_image(m_ioctx, m_image_name, &m_ictx);
49 m_image_id = m_ictx->id;
50
51 std::string ref_image_name = get_temp_image_name();
52 ASSERT_EQ(0, create_image_pp(m_rbd, m_ioctx, ref_image_name, m_ictx->size));
53 EXPECT_EQ(0, _rados.ioctx_create2(m_ioctx.get_id(), m_ref_ioctx));
54 open_image(m_ref_ioctx, ref_image_name, &m_ref_ictx);
55
56 resize(20 * (1 << 22));
57 }
58
59 void TearDown() override {
60 if (m_ref_ictx != nullptr) {
61 close_image(m_ref_ictx);
62 }
63 if (m_ictx != nullptr) {
64 close_image(m_ictx);
65 }
66
67 _other_pool_ioctx.close();
68
69 TestFixture::TearDown();
70 }
71
72 void compare(const std::string &description = "") {
73 std::vector<librbd::snap_info_t> src_snaps, dst_snaps;
74
75 EXPECT_EQ(m_ref_ictx->size, m_ictx->size);
76 EXPECT_EQ(0, librbd::api::Snapshot<>::list(m_ref_ictx, src_snaps));
77 EXPECT_EQ(0, librbd::api::Snapshot<>::list(m_ictx, dst_snaps));
78 EXPECT_EQ(src_snaps.size(), dst_snaps.size());
79 for (size_t i = 0; i <= src_snaps.size(); i++) {
80 const char *src_snap_name = nullptr;
81 const char *dst_snap_name = nullptr;
82 if (i < src_snaps.size()) {
83 EXPECT_EQ(src_snaps[i].name, dst_snaps[i].name);
84 src_snap_name = src_snaps[i].name.c_str();
85 dst_snap_name = dst_snaps[i].name.c_str();
86 }
87 EXPECT_EQ(0, librbd::api::Image<>::snap_set(
88 m_ref_ictx, cls::rbd::UserSnapshotNamespace(),
89 src_snap_name));
90 EXPECT_EQ(0, librbd::api::Image<>::snap_set(
91 m_ictx, cls::rbd::UserSnapshotNamespace(),
92 dst_snap_name));
93 compare_snaps(
94 description + " snap: " + (src_snap_name ? src_snap_name : "null"),
95 m_ref_ictx, m_ictx);
96 }
97 }
98
99 void compare_snaps(const std::string &description, librbd::ImageCtx *src_ictx,
100 librbd::ImageCtx *dst_ictx) {
101 uint64_t src_size, dst_size;
102 {
103 std::shared_lock src_locker{src_ictx->image_lock};
104 std::shared_lock dst_locker{dst_ictx->image_lock};
105 src_size = src_ictx->get_image_size(src_ictx->snap_id);
106 dst_size = dst_ictx->get_image_size(dst_ictx->snap_id);
107 }
108 if (src_size != dst_size) {
109 std::cout << description << ": size differs" << std::endl;
110 EXPECT_EQ(src_size, dst_size);
111 }
112
113 if (dst_ictx->test_features(RBD_FEATURE_LAYERING)) {
114 bool flags_set;
115 std::shared_lock dst_locker{dst_ictx->image_lock};
116 EXPECT_EQ(0, dst_ictx->test_flags(dst_ictx->snap_id,
117 RBD_FLAG_OBJECT_MAP_INVALID,
118 dst_ictx->image_lock, &flags_set));
119 EXPECT_FALSE(flags_set);
120 }
121
122 ssize_t read_size = 1 << src_ictx->order;
123 uint64_t offset = 0;
124 while (offset < src_size) {
125 read_size = std::min(read_size, static_cast<ssize_t>(src_size - offset));
126
127 bufferptr src_ptr(read_size);
128 bufferlist src_bl;
129 src_bl.push_back(src_ptr);
130 librbd::io::ReadResult src_result{&src_bl};
131 EXPECT_EQ(read_size, api::Io<>::read(
132 *src_ictx, offset, read_size,
133 librbd::io::ReadResult{src_result}, 0));
134
135 bufferptr dst_ptr(read_size);
136 bufferlist dst_bl;
137 dst_bl.push_back(dst_ptr);
138 librbd::io::ReadResult dst_result{&dst_bl};
139 EXPECT_EQ(read_size, api::Io<>::read(
140 *dst_ictx, offset, read_size,
141 librbd::io::ReadResult{dst_result}, 0));
142
143 if (!src_bl.contents_equal(dst_bl)) {
144 std::cout << description
145 << ", block " << offset << "~" << read_size << " differs"
146 << std::endl;
147 std::cout << "src block: " << src_ictx->id << ": " << std::endl; src_bl.hexdump(std::cout);
148 std::cout << "dst block: " << dst_ictx->id << ": " << std::endl; dst_bl.hexdump(std::cout);
149 }
150 EXPECT_TRUE(src_bl.contents_equal(dst_bl));
151 offset += read_size;
152 }
153 }
154
155 void open_image(librados::IoCtx& io_ctx, const std::string &name,
156 const std::string &id, bool read_only, int flags,
157 librbd::ImageCtx **ictx) {
158 *ictx = new librbd::ImageCtx(name, id, nullptr, io_ctx, read_only);
159 m_ictxs.insert(*ictx);
160
161 ASSERT_EQ(0, (*ictx)->state->open(flags));
162 (*ictx)->discard_granularity_bytes = 0;
163 }
164
165 void open_image(librados::IoCtx& io_ctx, const std::string &name,
166 librbd::ImageCtx **ictx) {
167 open_image(io_ctx, name, "", false, 0, ictx);
168 }
169
170 void migration_prepare(librados::IoCtx& dst_io_ctx,
171 const std::string &dst_name, int r = 0) {
172 std::cout << __func__ << std::endl;
173
174 close_image(m_ictx);
175 m_ictx = nullptr;
176
177 EXPECT_EQ(r, librbd::api::Migration<>::prepare(m_ioctx, m_image_name,
178 dst_io_ctx, dst_name,
179 m_opts));
180 if (r == 0) {
181 open_image(dst_io_ctx, dst_name, &m_ictx);
182 } else {
183 open_image(m_ioctx, m_image_name, &m_ictx);
184 }
185 compare("after prepare");
186 }
187
188 void migration_execute(librados::IoCtx& io_ctx, const std::string &name,
189 int r = 0) {
190 std::cout << __func__ << std::endl;
191
192 librbd::NoOpProgressContext no_op;
193 EXPECT_EQ(r, librbd::api::Migration<>::execute(io_ctx, name, no_op));
194 }
195
196 void migration_abort(librados::IoCtx& io_ctx, const std::string &name,
197 int r = 0) {
198 std::cout << __func__ << std::endl;
199
200 std::string dst_name = m_ictx->name;
201 close_image(m_ictx);
202 m_ictx = nullptr;
203
204 librbd::NoOpProgressContext no_op;
205 EXPECT_EQ(r, librbd::api::Migration<>::abort(io_ctx, name, no_op));
206
207 if (r == 0) {
208 open_image(m_ioctx, m_image_name, &m_ictx);
209 } else {
210 open_image(m_ioctx, dst_name, &m_ictx);
211 }
212
213 compare("after abort");
214 }
215
216 void migration_commit(librados::IoCtx& io_ctx, const std::string &name) {
217 std::cout << __func__ << std::endl;
218
219 librbd::NoOpProgressContext no_op;
220 EXPECT_EQ(0, librbd::api::Migration<>::commit(io_ctx, name, no_op));
221
222 compare("after commit");
223 }
224
225 void migration_status(librbd::image_migration_state_t state) {
226 librbd::image_migration_status_t status;
227 EXPECT_EQ(0, librbd::api::Migration<>::status(m_ioctx, m_image_name,
228 &status));
229 EXPECT_EQ(status.source_pool_id, m_ioctx.get_id());
230 EXPECT_EQ(status.source_pool_namespace, m_ioctx.get_namespace());
231 EXPECT_EQ(status.source_image_name, m_image_name);
232 EXPECT_EQ(status.source_image_id, m_image_id);
233 EXPECT_EQ(status.dest_pool_id, m_ictx->md_ctx.get_id());
234 EXPECT_EQ(status.dest_pool_namespace, m_ictx->md_ctx.get_namespace());
235 EXPECT_EQ(status.dest_image_name, m_ictx->name);
236 EXPECT_EQ(status.dest_image_id, m_ictx->id);
237 EXPECT_EQ(status.state, state);
238 }
239
240 void migrate(librados::IoCtx& dst_io_ctx, const std::string &dst_name) {
241 migration_prepare(dst_io_ctx, dst_name);
242 migration_status(RBD_IMAGE_MIGRATION_STATE_PREPARED);
243 migration_execute(dst_io_ctx, dst_name);
244 migration_status(RBD_IMAGE_MIGRATION_STATE_EXECUTED);
245 migration_commit(dst_io_ctx, dst_name);
246 }
247
248 void write(uint64_t off, uint64_t len, char c) {
249 std::cout << "write: " << c << " " << off << "~" << len << std::endl;
250
251 bufferlist ref_bl;
252 ref_bl.append(std::string(len, c));
253 ASSERT_EQ(static_cast<ssize_t>(len),
254 api::Io<>::write(*m_ref_ictx, off, len, std::move(ref_bl), 0));
255 bufferlist bl;
256 bl.append(std::string(len, c));
257 ASSERT_EQ(static_cast<ssize_t>(len),
258 api::Io<>::write(*m_ictx, off, len, std::move(bl), 0));
259 }
260
261 void discard(uint64_t off, uint64_t len) {
262 std::cout << "discard: " << off << "~" << len << std::endl;
263
264 ASSERT_EQ(static_cast<ssize_t>(len),
265 api::Io<>::discard(*m_ref_ictx, off, len, false));
266 ASSERT_EQ(static_cast<ssize_t>(len),
267 api::Io<>::discard(*m_ictx, off, len, false));
268 }
269
270 void flush() {
271 ASSERT_EQ(0, TestFixture::flush_writeback_cache(m_ref_ictx));
272 ASSERT_EQ(0, TestFixture::flush_writeback_cache(m_ictx));
273 }
274
275 void snap_create(const std::string &snap_name) {
276 std::cout << "snap_create: " << snap_name << std::endl;
277
278 flush();
279
280 ASSERT_EQ(0, TestFixture::snap_create(*m_ref_ictx, snap_name));
281 ASSERT_EQ(0, TestFixture::snap_create(*m_ictx, snap_name));
282 }
283
284 void snap_protect(const std::string &snap_name) {
285 std::cout << "snap_protect: " << snap_name << std::endl;
286
287 ASSERT_EQ(0, TestFixture::snap_protect(*m_ref_ictx, snap_name));
288 ASSERT_EQ(0, TestFixture::snap_protect(*m_ictx, snap_name));
289 }
290
291 void clone(const std::string &snap_name) {
292 snap_protect(snap_name);
293
294 int order = m_ref_ictx->order;
295 uint64_t features;
296 ASSERT_EQ(0, librbd::get_features(m_ref_ictx, &features));
297
298 std::string ref_clone_name = get_temp_image_name();
299 std::string clone_name = get_temp_image_name();
300
301 std::cout << "clone " << m_ictx->name << " -> " << clone_name
302 << std::endl;
303
304 ASSERT_EQ(0, librbd::clone(m_ref_ictx->md_ctx, m_ref_ictx->name.c_str(),
305 snap_name.c_str(), m_ref_ioctx,
306 ref_clone_name.c_str(), features, &order,
307 m_ref_ictx->stripe_unit,
308 m_ref_ictx->stripe_count));
309
310 ASSERT_EQ(0, librbd::clone(m_ictx->md_ctx, m_ictx->name.c_str(),
311 snap_name.c_str(), m_ioctx,
312 clone_name.c_str(), features, &order,
313 m_ictx->stripe_unit,
314 m_ictx->stripe_count));
315
316 close_image(m_ref_ictx);
317 open_image(m_ref_ioctx, ref_clone_name, &m_ref_ictx);
318
319 close_image(m_ictx);
320 open_image(m_ioctx, clone_name, &m_ictx);
321 m_image_name = m_ictx->name;
322 m_image_id = m_ictx->id;
323 }
324
325 void resize(uint64_t size) {
326 std::cout << "resize: " << size << std::endl;
327
328 librbd::NoOpProgressContext no_op;
329 ASSERT_EQ(0, m_ref_ictx->operations->resize(size, true, no_op));
330 ASSERT_EQ(0, m_ictx->operations->resize(size, true, no_op));
331 }
332
333 void test_no_snaps() {
334 uint64_t len = (1 << m_ictx->order) * 2 + 1;
335 write(0 * len, len, '1');
336 write(2 * len, len, '1');
337 flush();
338 }
339
340 void test_snaps() {
341 uint64_t len = (1 << m_ictx->order) * 2 + 1;
342 write(0 * len, len, '1');
343 snap_create("snap1");
344 write(1 * len, len, '1');
345
346 write(0 * len, 1000, 'X');
347 discard(1000 + 10, 1000);
348
349 snap_create("snap2");
350
351 write(1 * len, 1000, 'X');
352 discard(2 * len + 10, 1000);
353
354 uint64_t size = m_ictx->size;
355
356 resize(size << 1);
357
358 write(size - 1, len, '2');
359
360 snap_create("snap3");
361
362 resize(size);
363
364 discard(size - 1, 1);
365
366 flush();
367 }
368
369 void test_clone() {
370 uint64_t len = (1 << m_ictx->order) * 2 + 1;
371 write(0 * len, len, 'X');
372 write(2 * len, len, 'X');
373
374 snap_create("snap");
375 clone("snap");
376
377 write(0, 1000, 'X');
378 discard(1010, 1000);
379
380 snap_create("snap");
381 clone("snap");
382
383 write(1000, 1000, 'X');
384 discard(2010, 1000);
385
386 flush();
387 }
388
389 template <typename L>
390 void test_migrate_parent(uint32_t clone_format, L&& test) {
391 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
392
393 std::string prev_clone_format;
394 ASSERT_EQ(0, _rados.conf_get("rbd_default_clone_format",
395 prev_clone_format));
396 ASSERT_EQ(0, _rados.conf_set("rbd_default_clone_format",
397 stringify(clone_format).c_str()));
398 BOOST_SCOPE_EXIT_TPL(&prev_clone_format) {
399 _rados.conf_set("rbd_default_clone_format", prev_clone_format.c_str());
400 } BOOST_SCOPE_EXIT_END;
401
402 write(0, 10, 'A');
403 snap_create("snap1");
404 snap_protect("snap1");
405
406 int order = m_ictx->order;
407 uint64_t features;
408 ASSERT_EQ(0, librbd::get_features(m_ictx, &features));
409
410 std::string clone_name = get_temp_image_name();
411 ASSERT_EQ(0, librbd::clone(m_ictx->md_ctx, m_ictx->name.c_str(), "snap1",
412 m_ioctx, clone_name.c_str(), features, &order,
413 m_ictx->stripe_unit, m_ictx->stripe_count));
414
415 librbd::ImageCtx *child_ictx;
416 open_image(m_ioctx, clone_name, &child_ictx);
417
418 test(child_ictx);
419
420 ASSERT_EQ(0, child_ictx->state->refresh());
421
422 bufferlist bl;
423 bufferptr ptr(10);
424 bl.push_back(ptr);
425 librbd::io::ReadResult result{&bl};
426 ASSERT_EQ(10, api::Io<>::read(
427 *child_ictx, 0, 10, librbd::io::ReadResult{result}, 0));
428 bufferlist ref_bl;
429 ref_bl.append(std::string(10, 'A'));
430 ASSERT_TRUE(ref_bl.contents_equal(bl));
431 close_image(child_ictx);
432 }
433
434 void test_stress(const std::string &snap_name_prefix = "snap",
435 char start_char = 'A') {
436 uint64_t initial_size = m_ictx->size;
437
438 int nsnaps = 4;
439 const char *c = getenv("TEST_RBD_MIGRATION_STRESS_NSNAPS");
440 if (c != NULL) {
441 std::stringstream ss(c);
442 ASSERT_TRUE(ss >> nsnaps);
443 }
444
445 int nwrites = 4;
446 c = getenv("TEST_RBD_MIGRATION_STRESS_NWRITES");
447 if (c != NULL) {
448 std::stringstream ss(c);
449 ASSERT_TRUE(ss >> nwrites);
450 }
451
452 for (int i = 0; i < nsnaps; i++) {
453 for (int j = 0; j < nwrites; j++) {
454 size_t len = rand() % ((1 << m_ictx->order) * 2);
455 ASSERT_GT(m_ictx->size, len);
456 uint64_t off = std::min(static_cast<uint64_t>(rand() % m_ictx->size),
457 static_cast<uint64_t>(m_ictx->size - len));
458 write(off, len, start_char + i);
459
460 len = rand() % ((1 << m_ictx->order) * 2);
461 ASSERT_GT(m_ictx->size, len);
462 off = std::min(static_cast<uint64_t>(rand() % m_ictx->size),
463 static_cast<uint64_t>(m_ictx->size - len));
464 discard(off, len);
465 }
466
467 std::string snap_name = snap_name_prefix + stringify(i);
468 snap_create(snap_name);
469
470 if (m_ictx->test_features(RBD_FEATURE_LAYERING) &&
471 !m_ictx->test_features(RBD_FEATURE_MIGRATING) &&
472 rand() % 4) {
473 clone(snap_name);
474 }
475
476 if (rand() % 2) {
477 librbd::NoOpProgressContext no_op;
478 uint64_t new_size = initial_size + rand() % m_ictx->size;
479 resize(new_size);
480 ASSERT_EQ(new_size, m_ictx->size);
481 }
482 }
483 flush();
484 }
485
486 void test_stress2(bool concurrent) {
487 test_stress();
488
489 migration_prepare(m_ioctx, m_image_name);
490 migration_status(RBD_IMAGE_MIGRATION_STATE_PREPARED);
491
492 std::thread user([this]() {
493 test_stress("user", 'a');
494 for (int i = 0; i < 5; i++) {
495 uint64_t off = (i + 1) * m_ictx->size / 10;
496 uint64_t len = m_ictx->size / 40;
497 write(off, len, '1' + i);
498
499 off += len / 4;
500 len /= 2;
501 discard(off, len);
502 }
503 flush();
504 });
505
506 if (concurrent) {
507 librados::IoCtx io_ctx;
508 EXPECT_EQ(0, _rados.ioctx_create2(m_ioctx.get_id(), io_ctx));
509 migration_execute(io_ctx, m_image_name);
510 io_ctx.close();
511 user.join();
512 } else {
513 user.join();
514 compare("before execute");
515 migration_execute(m_ioctx, m_image_name);
516 }
517
518 migration_status(RBD_IMAGE_MIGRATION_STATE_EXECUTED);
519 migration_commit(m_ioctx, m_image_name);
520 }
521
522 static std::string _other_pool_name;
523 static librados::IoCtx _other_pool_ioctx;
524
525 std::string m_image_id;
526 librbd::ImageCtx *m_ictx = nullptr;
527 librados::IoCtx m_ref_ioctx;
528 librbd::ImageCtx *m_ref_ictx = nullptr;
529 librbd::ImageOptions m_opts;
530 };
531
532 std::string TestMigration::_other_pool_name;
533 librados::IoCtx TestMigration::_other_pool_ioctx;
534
535 TEST_F(TestMigration, Empty)
536 {
537 uint64_t features = m_ictx->features ^ RBD_FEATURE_LAYERING;
538 features &= ~RBD_FEATURE_DIRTY_CACHE;
539 ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_FEATURES, features));
540
541 migrate(m_ioctx, m_image_name);
542
543 ASSERT_EQ(features, m_ictx->features);
544 }
545
546 TEST_F(TestMigration, OtherName)
547 {
548 std::string name = get_temp_image_name();
549
550 migrate(m_ioctx, name);
551
552 ASSERT_EQ(name, m_ictx->name);
553 }
554
555 TEST_F(TestMigration, OtherPool)
556 {
557 migrate(_other_pool_ioctx, m_image_name);
558
559 ASSERT_EQ(_other_pool_ioctx.get_id(), m_ictx->md_ctx.get_id());
560 }
561
562 TEST_F(TestMigration, OtherNamespace)
563 {
564 ASSERT_EQ(0, librbd::api::Namespace<>::create(_other_pool_ioctx, "ns1"));
565 _other_pool_ioctx.set_namespace("ns1");
566
567 migrate(_other_pool_ioctx, m_image_name);
568
569 ASSERT_EQ(_other_pool_ioctx.get_id(), m_ictx->md_ctx.get_id());
570 ASSERT_EQ(_other_pool_ioctx.get_namespace(), m_ictx->md_ctx.get_namespace());
571 _other_pool_ioctx.set_namespace("");
572 }
573
574 TEST_F(TestMigration, DataPool)
575 {
576 ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_DATA_POOL,
577 _other_pool_ioctx.get_pool_name().c_str()));
578
579 migrate(m_ioctx, m_image_name);
580
581 ASSERT_EQ(_other_pool_ioctx.get_id(), m_ictx->data_ctx.get_id());
582 }
583
584 TEST_F(TestMigration, AbortAfterPrepare)
585 {
586 migration_prepare(m_ioctx, m_image_name);
587 migration_status(RBD_IMAGE_MIGRATION_STATE_PREPARED);
588 migration_abort(m_ioctx, m_image_name);
589 }
590
591 TEST_F(TestMigration, AbortAfterFailedPrepare)
592 {
593 ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_DATA_POOL, "INVALID_POOL"));
594
595 migration_prepare(m_ioctx, m_image_name, -ENOENT);
596
597 // Migration is automatically aborted if prepare failed
598 }
599
600 TEST_F(TestMigration, AbortAfterExecute)
601 {
602 migration_prepare(m_ioctx, m_image_name);
603 migration_status(RBD_IMAGE_MIGRATION_STATE_PREPARED);
604 migration_execute(m_ioctx, m_image_name);
605 migration_status(RBD_IMAGE_MIGRATION_STATE_EXECUTED);
606 migration_abort(m_ioctx, m_image_name);
607 }
608
609 TEST_F(TestMigration, OtherPoolAbortAfterExecute)
610 {
611 migration_prepare(_other_pool_ioctx, m_image_name);
612 migration_status(RBD_IMAGE_MIGRATION_STATE_PREPARED);
613 migration_execute(_other_pool_ioctx, m_image_name);
614 migration_status(RBD_IMAGE_MIGRATION_STATE_EXECUTED);
615 migration_abort(_other_pool_ioctx, m_image_name);
616 }
617
618 TEST_F(TestMigration, OtherNamespaceAbortAfterExecute)
619 {
620 ASSERT_EQ(0, librbd::api::Namespace<>::create(_other_pool_ioctx, "ns2"));
621 _other_pool_ioctx.set_namespace("ns2");
622
623 migration_prepare(_other_pool_ioctx, m_image_name);
624 migration_status(RBD_IMAGE_MIGRATION_STATE_PREPARED);
625 migration_execute(_other_pool_ioctx, m_image_name);
626 migration_status(RBD_IMAGE_MIGRATION_STATE_EXECUTED);
627 migration_abort(_other_pool_ioctx, m_image_name);
628
629 _other_pool_ioctx.set_namespace("");
630 ASSERT_EQ(0, librbd::api::Namespace<>::remove(_other_pool_ioctx, "ns2"));
631 }
632
633 TEST_F(TestMigration, MirroringSamePool)
634 {
635 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
636
637 ASSERT_EQ(0, librbd::api::Mirror<>::mode_set(m_ioctx, RBD_MIRROR_MODE_IMAGE));
638
639 ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(
640 m_ictx, RBD_MIRROR_IMAGE_MODE_JOURNAL, false));
641 librbd::mirror_image_info_t info;
642 ASSERT_EQ(0, librbd::api::Mirror<>::image_get_info(m_ictx, &info));
643 ASSERT_EQ(RBD_MIRROR_IMAGE_ENABLED, info.state);
644
645 migrate(m_ioctx, m_image_name);
646
647 ASSERT_EQ(0, librbd::api::Mirror<>::image_get_info(m_ictx, &info));
648 ASSERT_EQ(RBD_MIRROR_IMAGE_ENABLED, info.state);
649 }
650
651 TEST_F(TestMigration, MirroringAbort)
652 {
653 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
654
655 ASSERT_EQ(0, librbd::api::Mirror<>::mode_set(m_ioctx, RBD_MIRROR_MODE_IMAGE));
656
657 ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(
658 m_ictx, RBD_MIRROR_IMAGE_MODE_JOURNAL, false));
659 librbd::mirror_image_info_t info;
660 ASSERT_EQ(0, librbd::api::Mirror<>::image_get_info(m_ictx, &info));
661 ASSERT_EQ(RBD_MIRROR_IMAGE_ENABLED, info.state);
662
663 migration_prepare(m_ioctx, m_image_name);
664 migration_status(RBD_IMAGE_MIGRATION_STATE_PREPARED);
665 ASSERT_EQ(0, librbd::api::Mirror<>::image_get_info(m_ictx, &info));
666 ASSERT_EQ(RBD_MIRROR_IMAGE_DISABLED, info.state);
667
668 migration_abort(m_ioctx, m_image_name);
669
670 ASSERT_EQ(0, librbd::api::Mirror<>::image_get_info(m_ictx, &info));
671 ASSERT_EQ(RBD_MIRROR_IMAGE_ENABLED, info.state);
672 }
673
674 TEST_F(TestMigration, MirroringOtherPoolDisabled)
675 {
676 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
677
678 ASSERT_EQ(0, librbd::api::Mirror<>::mode_set(m_ioctx, RBD_MIRROR_MODE_IMAGE));
679
680 ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(
681 m_ictx, RBD_MIRROR_IMAGE_MODE_JOURNAL, false));
682 librbd::mirror_image_info_t info;
683 ASSERT_EQ(0, librbd::api::Mirror<>::image_get_info(m_ictx, &info));
684 ASSERT_EQ(RBD_MIRROR_IMAGE_ENABLED, info.state);
685
686 migrate(_other_pool_ioctx, m_image_name);
687
688 ASSERT_EQ(0, librbd::api::Mirror<>::image_get_info(m_ictx, &info));
689 ASSERT_EQ(RBD_MIRROR_IMAGE_DISABLED, info.state);
690 }
691
692 TEST_F(TestMigration, MirroringOtherPoolEnabled)
693 {
694 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
695
696 ASSERT_EQ(0, librbd::api::Mirror<>::mode_set(m_ioctx, RBD_MIRROR_MODE_IMAGE));
697 ASSERT_EQ(0, librbd::api::Mirror<>::mode_set(_other_pool_ioctx,
698 RBD_MIRROR_MODE_IMAGE));
699
700 ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(
701 m_ictx, RBD_MIRROR_IMAGE_MODE_JOURNAL, false));
702 librbd::mirror_image_info_t info;
703 ASSERT_EQ(0, librbd::api::Mirror<>::image_get_info(m_ictx, &info));
704 ASSERT_EQ(RBD_MIRROR_IMAGE_ENABLED, info.state);
705
706 migrate(_other_pool_ioctx, m_image_name);
707
708 ASSERT_EQ(0, librbd::api::Mirror<>::image_get_info(m_ictx, &info));
709 ASSERT_EQ(RBD_MIRROR_IMAGE_ENABLED, info.state);
710 }
711
712 TEST_F(TestMigration, MirroringPool)
713 {
714 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
715
716 ASSERT_EQ(0, librbd::api::Mirror<>::mode_set(_other_pool_ioctx,
717 RBD_MIRROR_MODE_POOL));
718 librbd::mirror_image_info_t info;
719 ASSERT_EQ(0, librbd::api::Mirror<>::image_get_info(m_ictx, &info));
720 ASSERT_EQ(RBD_MIRROR_IMAGE_DISABLED, info.state);
721
722 migrate(_other_pool_ioctx, m_image_name);
723
724 ASSERT_EQ(0, librbd::api::Mirror<>::image_get_info(m_ictx, &info));
725 ASSERT_EQ(RBD_MIRROR_IMAGE_ENABLED, info.state);
726 }
727
728 TEST_F(TestMigration, Group)
729 {
730 REQUIRE_FORMAT_V2();
731
732 ASSERT_EQ(0, librbd::api::Group<>::create(m_ioctx, "123"));
733 ASSERT_EQ(0, librbd::api::Group<>::image_add(m_ioctx, "123", m_ioctx,
734 m_image_name.c_str()));
735 librbd::group_info_t info;
736 ASSERT_EQ(0, librbd::api::Group<>::image_get_group(m_ictx, &info));
737
738 std::string name = get_temp_image_name();
739
740 migrate(m_ioctx, name);
741
742 ASSERT_EQ(0, librbd::api::Group<>::image_get_group(m_ictx, &info));
743 ASSERT_EQ(info.name, "123");
744
745 ASSERT_EQ(0, librbd::api::Group<>::image_remove(m_ioctx, "123", m_ioctx,
746 name.c_str()));
747 ASSERT_EQ(0, librbd::api::Group<>::remove(m_ioctx, "123"));
748 }
749
750 TEST_F(TestMigration, GroupAbort)
751 {
752 REQUIRE_FORMAT_V2();
753
754 ASSERT_EQ(0, librbd::api::Group<>::create(m_ioctx, "123"));
755 ASSERT_EQ(0, librbd::api::Group<>::image_add(m_ioctx, "123", m_ioctx,
756 m_image_name.c_str()));
757 librbd::group_info_t info;
758 ASSERT_EQ(0, librbd::api::Group<>::image_get_group(m_ictx, &info));
759
760 std::string name = get_temp_image_name();
761
762 migration_prepare(m_ioctx, name);
763 migration_status(RBD_IMAGE_MIGRATION_STATE_PREPARED);
764
765 ASSERT_EQ(0, librbd::api::Group<>::image_get_group(m_ictx, &info));
766 ASSERT_EQ(info.name, "123");
767
768 migration_abort(m_ioctx, m_image_name);
769
770 ASSERT_EQ(0, librbd::api::Group<>::image_get_group(m_ictx, &info));
771 ASSERT_EQ(info.name, "123");
772
773 ASSERT_EQ(0, librbd::api::Group<>::image_remove(m_ioctx, "123", m_ioctx,
774 m_image_name.c_str()));
775 ASSERT_EQ(0, librbd::api::Group<>::remove(m_ioctx, "123"));
776 }
777
778 TEST_F(TestMigration, NoSnaps)
779 {
780 test_no_snaps();
781 migrate(m_ioctx, m_image_name);
782 }
783
784 TEST_F(TestMigration, NoSnapsOtherPool)
785 {
786 test_no_snaps();
787
788 test_no_snaps();
789 migrate(_other_pool_ioctx, m_image_name);
790 }
791
792 TEST_F(TestMigration, NoSnapsDataPool)
793 {
794 test_no_snaps();
795
796 ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_DATA_POOL,
797 _other_pool_ioctx.get_pool_name().c_str()));
798 migrate(m_ioctx, m_image_name);
799
800 EXPECT_EQ(_other_pool_ioctx.get_id(), m_ictx->data_ctx.get_id());
801 }
802
803 TEST_F(TestMigration, NoSnapsShrinkAfterPrepare)
804 {
805 test_no_snaps();
806
807 migration_prepare(m_ioctx, m_image_name);
808 migration_status(RBD_IMAGE_MIGRATION_STATE_PREPARED);
809
810 resize(m_ictx->size >> 1);
811
812 migration_execute(m_ioctx, m_image_name);
813 migration_status(RBD_IMAGE_MIGRATION_STATE_EXECUTED);
814 migration_commit(m_ioctx, m_image_name);
815 }
816
817 TEST_F(TestMigration, NoSnapsShrinkToZeroBeforePrepare)
818 {
819 test_no_snaps();
820 resize(0);
821
822 migrate(m_ioctx, m_image_name);
823 }
824
825 TEST_F(TestMigration, NoSnapsShrinkToZeroAfterPrepare)
826 {
827 test_no_snaps();
828
829 migration_prepare(m_ioctx, m_image_name);
830 migration_status(RBD_IMAGE_MIGRATION_STATE_PREPARED);
831
832 resize(0);
833
834 migration_execute(m_ioctx, m_image_name);
835 migration_status(RBD_IMAGE_MIGRATION_STATE_EXECUTED);
836 migration_commit(m_ioctx, m_image_name);
837 }
838
839 TEST_F(TestMigration, NoSnapsExpandAfterPrepare)
840 {
841 test_no_snaps();
842
843 migration_prepare(m_ioctx, m_image_name);
844 migration_status(RBD_IMAGE_MIGRATION_STATE_PREPARED);
845
846 resize(m_ictx->size << 1);
847
848 migration_execute(m_ioctx, m_image_name);
849 migration_status(RBD_IMAGE_MIGRATION_STATE_EXECUTED);
850 migration_commit(m_ioctx, m_image_name);
851 }
852
853 TEST_F(TestMigration, NoSnapsSnapAfterPrepare)
854 {
855 test_no_snaps();
856
857 migration_prepare(m_ioctx, m_image_name);
858 migration_status(RBD_IMAGE_MIGRATION_STATE_PREPARED);
859
860 snap_create("after_prepare_snap");
861 resize(m_ictx->size >> 1);
862 write(0, 1000, '*');
863
864 migration_execute(m_ioctx, m_image_name);
865 migration_status(RBD_IMAGE_MIGRATION_STATE_EXECUTED);
866 migration_commit(m_ioctx, m_image_name);
867 }
868
869 TEST_F(TestMigration, Snaps)
870 {
871 test_snaps();
872 migrate(m_ioctx, m_image_name);
873 }
874
875 TEST_F(TestMigration, SnapsOtherPool)
876 {
877 test_snaps();
878
879 test_no_snaps();
880 migrate(_other_pool_ioctx, m_image_name);
881
882 EXPECT_EQ(_other_pool_ioctx.get_id(), m_ictx->md_ctx.get_id());
883 }
884
885 TEST_F(TestMigration, SnapsDataPool)
886 {
887 test_snaps();
888
889 ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_DATA_POOL,
890 _other_pool_ioctx.get_pool_name().c_str()));
891 migrate(m_ioctx, m_image_name);
892
893 EXPECT_EQ(_other_pool_ioctx.get_id(), m_ictx->data_ctx.get_id());
894 }
895
896 TEST_F(TestMigration, SnapsShrinkAfterPrepare)
897 {
898 test_snaps();
899
900 migration_prepare(m_ioctx, m_image_name);
901 migration_status(RBD_IMAGE_MIGRATION_STATE_PREPARED);
902
903 resize(m_ictx->size >> 1);
904
905 migration_execute(m_ioctx, m_image_name);
906 migration_status(RBD_IMAGE_MIGRATION_STATE_EXECUTED);
907 migration_commit(m_ioctx, m_image_name);
908 }
909
910 TEST_F(TestMigration, SnapsShrinkToZeroBeforePrepare)
911 {
912 test_snaps();
913 resize(0);
914
915 migrate(m_ioctx, m_image_name);
916 }
917
918 TEST_F(TestMigration, SnapsShrinkToZeroAfterPrepare)
919 {
920 test_snaps();
921
922 migration_prepare(m_ioctx, m_image_name);
923 migration_status(RBD_IMAGE_MIGRATION_STATE_PREPARED);
924
925 resize(0);
926
927 migration_execute(m_ioctx, m_image_name);
928 migration_status(RBD_IMAGE_MIGRATION_STATE_EXECUTED);
929 migration_commit(m_ioctx, m_image_name);
930 }
931
932 TEST_F(TestMigration, SnapsExpandAfterPrepare)
933 {
934 test_snaps();
935
936 migration_prepare(m_ioctx, m_image_name);
937 migration_status(RBD_IMAGE_MIGRATION_STATE_PREPARED);
938
939 auto size = m_ictx->size;
940 resize(size << 1);
941 write(size, 1000, '*');
942
943 migration_execute(m_ioctx, m_image_name);
944 migration_status(RBD_IMAGE_MIGRATION_STATE_EXECUTED);
945 migration_commit(m_ioctx, m_image_name);
946 }
947
948 TEST_F(TestMigration, SnapsExpandAfterPrepare2)
949 {
950 auto size = m_ictx->size;
951
952 write(size >> 1, 10, 'X');
953 snap_create("snap1");
954 resize(size >> 1);
955
956 migration_prepare(m_ioctx, m_image_name);
957 migration_status(RBD_IMAGE_MIGRATION_STATE_PREPARED);
958
959 resize(size);
960 write(size >> 1, 5, 'Y');
961
962 compare("before execute");
963
964 migration_execute(m_ioctx, m_image_name);
965 migration_status(RBD_IMAGE_MIGRATION_STATE_EXECUTED);
966 migration_commit(m_ioctx, m_image_name);
967 }
968
969 TEST_F(TestMigration, SnapsSnapAfterPrepare)
970 {
971 test_snaps();
972
973 migration_prepare(m_ioctx, m_image_name);
974 migration_status(RBD_IMAGE_MIGRATION_STATE_PREPARED);
975
976 auto ictx = new librbd::ImageCtx(m_ictx->name.c_str(), "", "snap3", m_ioctx,
977 false);
978 ASSERT_EQ(0, ictx->state->open(0));
979 EXPECT_EQ(0, librbd::api::Image<>::snap_set(
980 m_ref_ictx, cls::rbd::UserSnapshotNamespace(), "snap3"));
981 compare_snaps("opened after prepare snap3", m_ref_ictx, ictx);
982 EXPECT_EQ(0, librbd::api::Image<>::snap_set(
983 m_ref_ictx, cls::rbd::UserSnapshotNamespace(), nullptr));
984 EXPECT_EQ(0, ictx->state->close());
985
986 snap_create("after_prepare_snap");
987 resize(m_ictx->size >> 1);
988 write(0, 1000, '*');
989
990 migration_execute(m_ioctx, m_image_name);
991 migration_status(RBD_IMAGE_MIGRATION_STATE_EXECUTED);
992 migration_commit(m_ioctx, m_image_name);
993 }
994
995 TEST_F(TestMigration, SnapsSnapExpandAfterPrepare)
996 {
997 test_snaps();
998
999 migration_prepare(m_ioctx, m_image_name);
1000 migration_status(RBD_IMAGE_MIGRATION_STATE_PREPARED);
1001
1002 snap_create("after_prepare_snap");
1003 auto size = m_ictx->size;
1004 resize(size << 1);
1005 write(size, 1000, '*');
1006
1007 migration_execute(m_ioctx, m_image_name);
1008 migration_status(RBD_IMAGE_MIGRATION_STATE_EXECUTED);
1009 migration_commit(m_ioctx, m_image_name);
1010 }
1011
1012 TEST_F(TestMigration, Clone)
1013 {
1014 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
1015
1016 test_clone();
1017 migrate(m_ioctx, m_image_name);
1018 }
1019
1020 TEST_F(TestMigration, CloneParent) {
1021 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
1022
1023 snap_create("snap");
1024
1025 librbd::linked_image_spec_t expected_parent_image;
1026 expected_parent_image.image_id = m_ictx->id;
1027 expected_parent_image.image_name = m_ictx->name;
1028
1029 auto it = m_ictx->snap_ids.find({cls::rbd::UserSnapshotNamespace{}, "snap"});
1030 ASSERT_TRUE(it != m_ictx->snap_ids.end());
1031
1032 librbd::snap_spec_t expected_parent_snap;
1033 expected_parent_snap.id = it->second;
1034
1035 clone("snap");
1036 migration_prepare(m_ioctx, m_image_name);
1037
1038 librbd::linked_image_spec_t parent_image;
1039 librbd::snap_spec_t parent_snap;
1040 ASSERT_EQ(0, librbd::api::Image<>::get_parent(m_ictx, &parent_image,
1041 &parent_snap));
1042 ASSERT_EQ(expected_parent_image.image_id, parent_image.image_id);
1043 ASSERT_EQ(expected_parent_image.image_name, parent_image.image_name);
1044 ASSERT_EQ(expected_parent_snap.id, parent_snap.id);
1045
1046 migration_abort(m_ioctx, m_image_name);
1047 }
1048
1049
1050 TEST_F(TestMigration, CloneUpdateAfterPrepare)
1051 {
1052 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
1053
1054 write(0, 10, 'X');
1055 snap_create("snap");
1056 clone("snap");
1057
1058 migration_prepare(m_ioctx, m_image_name);
1059
1060 write(0, 1, 'Y');
1061
1062 migration_execute(m_ioctx, m_image_name);
1063 migration_commit(m_ioctx, m_image_name);
1064 }
1065
1066 TEST_F(TestMigration, TriggerAssertSnapcSeq)
1067 {
1068 auto size = m_ictx->size;
1069
1070 write((size >> 1) + 0, 10, 'A');
1071 snap_create("snap1");
1072 write((size >> 1) + 1, 10, 'B');
1073
1074 migration_prepare(m_ioctx, m_image_name);
1075
1076 // copyup => deep copy (first time)
1077 write((size >> 1) + 2, 10, 'C');
1078
1079 // preserve data before resizing
1080 snap_create("snap2");
1081
1082 // decrease head overlap
1083 resize(size >> 1);
1084
1085 // migrate object => deep copy (second time) => assert_snapc_seq => -ERANGE
1086 migration_execute(m_ioctx, m_image_name);
1087 migration_commit(m_ioctx, m_image_name);
1088 }
1089
1090 TEST_F(TestMigration, SnapTrimBeforePrepare)
1091 {
1092 auto size = m_ictx->size;
1093
1094 write(size >> 1, 10, 'A');
1095 snap_create("snap1");
1096 resize(size >> 1);
1097
1098 migration_prepare(m_ioctx, m_image_name);
1099
1100 resize(size);
1101 snap_create("snap3");
1102 write(size >> 1, 10, 'B');
1103 snap_create("snap4");
1104 resize(size >> 1);
1105
1106 migration_execute(m_ioctx, m_image_name);
1107 migration_commit(m_ioctx, m_image_name);
1108 }
1109
1110 TEST_F(TestMigration, AbortInUseImage) {
1111 migration_prepare(m_ioctx, m_image_name);
1112 migration_status(RBD_IMAGE_MIGRATION_STATE_PREPARED);
1113
1114 librbd::NoOpProgressContext no_op;
1115 EXPECT_EQ(-EBUSY, librbd::api::Migration<>::abort(m_ioctx, m_ictx->name,
1116 no_op));
1117 }
1118
1119 TEST_F(TestMigration, AbortWithoutSnapshots) {
1120 test_no_snaps();
1121 migration_prepare(m_ioctx, m_image_name);
1122 migration_status(RBD_IMAGE_MIGRATION_STATE_PREPARED);
1123 test_no_snaps();
1124 migration_abort(m_ioctx, m_image_name);
1125 }
1126
1127 TEST_F(TestMigration, AbortWithSnapshots) {
1128 test_snaps();
1129 migration_prepare(m_ioctx, m_image_name);
1130 migration_status(RBD_IMAGE_MIGRATION_STATE_PREPARED);
1131
1132 test_no_snaps();
1133 flush();
1134 ASSERT_EQ(0, TestFixture::snap_create(*m_ictx, "dst-only-snap"));
1135
1136 test_no_snaps();
1137
1138 migration_abort(m_ioctx, m_image_name);
1139 }
1140
1141 TEST_F(TestMigration, CloneV1Parent)
1142 {
1143 const uint32_t CLONE_FORMAT = 1;
1144 test_migrate_parent(
1145 CLONE_FORMAT, [this](librbd::ImageCtx *) {
1146 migrate(m_ioctx, m_image_name);
1147 });
1148 }
1149
1150 TEST_F(TestMigration, CloneV2Parent)
1151 {
1152 const uint32_t CLONE_FORMAT = 2;
1153 test_migrate_parent(
1154 CLONE_FORMAT, [this](librbd::ImageCtx *) {
1155 migrate(m_ioctx, m_image_name);
1156 });
1157 }
1158
1159 TEST_F(TestMigration, CloneV1ParentAbort)
1160 {
1161 const uint32_t CLONE_FORMAT = 1;
1162 test_migrate_parent(
1163 CLONE_FORMAT, [this](librbd::ImageCtx *) {
1164 migration_prepare(m_ioctx, m_image_name);
1165 migration_abort(m_ioctx, m_image_name);
1166 });
1167 }
1168
1169 TEST_F(TestMigration, CloneV2ParentAbort)
1170 {
1171 const uint32_t CLONE_FORMAT = 2;
1172 test_migrate_parent(
1173 CLONE_FORMAT, [this](librbd::ImageCtx *) {
1174 migration_prepare(m_ioctx, m_image_name);
1175 migration_abort(m_ioctx, m_image_name);
1176 });
1177 }
1178
1179 TEST_F(TestMigration, CloneV1ParentAbortFixIncompleteChildReattach)
1180 {
1181 const uint32_t CLONE_FORMAT = 1;
1182 test_migrate_parent(
1183 CLONE_FORMAT, [this](librbd::ImageCtx *child_ictx) {
1184 auto src_image_id = m_ictx->id;
1185 migration_prepare(m_ioctx, m_image_name);
1186 // Attach the child to both source and destination
1187 // to emulate a crash when re-attaching the child
1188 librbd::ImageCtx *src_ictx;
1189 open_image(m_ioctx, "", src_image_id, false,
1190 librbd::OPEN_FLAG_IGNORE_MIGRATING, &src_ictx);
1191 C_SaferCond cond;
1192 auto req = librbd::image::AttachChildRequest<>::create(
1193 child_ictx, src_ictx, src_ictx->snaps[0], nullptr, 0,
1194 CLONE_FORMAT, &cond);
1195 req->send();
1196 ASSERT_EQ(0, cond.wait());
1197 close_image(src_ictx);
1198 migration_abort(m_ioctx, m_image_name);
1199 });
1200 }
1201
1202 TEST_F(TestMigration, CloneV1ParentAbortFixParentReattach)
1203 {
1204 const uint32_t CLONE_FORMAT = 1;
1205 test_migrate_parent(
1206 CLONE_FORMAT, [this](librbd::ImageCtx *child_ictx) {
1207 auto src_image_id = m_ictx->id;
1208 migration_prepare(m_ioctx, m_image_name);
1209 // Re-attach the child back to the source to emulate a crash
1210 // after the parent reattach but before the child reattach
1211 librbd::ImageCtx *src_ictx;
1212 open_image(m_ioctx, "", src_image_id, false,
1213 librbd::OPEN_FLAG_IGNORE_MIGRATING, &src_ictx);
1214 C_SaferCond cond;
1215 auto req = librbd::image::AttachChildRequest<>::create(
1216 child_ictx, src_ictx, src_ictx->snaps[0], m_ictx,
1217 m_ictx->snaps[0], CLONE_FORMAT, &cond);
1218 req->send();
1219 ASSERT_EQ(0, cond.wait());
1220 close_image(src_ictx);
1221 migration_abort(m_ioctx, m_image_name);
1222 });
1223 }
1224
1225 TEST_F(TestMigration, CloneV1ParentAbortRelinkNotNeeded)
1226 {
1227 const uint32_t CLONE_FORMAT = 1;
1228 test_migrate_parent(
1229 CLONE_FORMAT, [this](librbd::ImageCtx *child_ictx) {
1230 auto src_image_id = m_ictx->id;
1231 auto parent_spec = child_ictx->parent_md.spec;
1232 parent_spec.image_id = m_ictx->id;
1233 parent_spec.snap_id = m_ictx->snaps[0];
1234 auto parent_overlap = child_ictx->parent_md.overlap;
1235 migration_prepare(m_ioctx, m_image_name);
1236 // Relink the child back to emulate a crash
1237 // before relinking the child
1238 C_SaferCond cond;
1239 auto req = librbd::image::AttachParentRequest<>::create(
1240 *child_ictx, parent_spec, parent_overlap, true, &cond);
1241 req->send();
1242 ASSERT_EQ(0, cond.wait());
1243 librbd::ImageCtx *src_ictx;
1244 open_image(m_ioctx, "", src_image_id, false,
1245 librbd::OPEN_FLAG_IGNORE_MIGRATING, &src_ictx);
1246 C_SaferCond cond1;
1247 auto req1 = librbd::image::AttachChildRequest<>::create(
1248 child_ictx, src_ictx, src_ictx->snaps[0], m_ictx,
1249 m_ictx->snaps[0], CLONE_FORMAT, &cond1);
1250 req1->send();
1251 ASSERT_EQ(0, cond1.wait());
1252 close_image(src_ictx);
1253 migration_abort(m_ioctx, m_image_name);
1254 });
1255 }
1256
1257 TEST_F(TestMigration, CloneV2ParentAbortFixIncompleteChildReattach)
1258 {
1259 const uint32_t CLONE_FORMAT = 2;
1260 test_migrate_parent(
1261 CLONE_FORMAT, [this](librbd::ImageCtx *child_ictx) {
1262 auto src_image_id = m_ictx->id;
1263 migration_prepare(m_ioctx, m_image_name);
1264 // Attach the child to both source and destination
1265 // to emulate a crash when re-attaching the child
1266 librbd::ImageCtx *src_ictx;
1267 open_image(m_ioctx, "", src_image_id, false,
1268 librbd::OPEN_FLAG_IGNORE_MIGRATING, &src_ictx);
1269 C_SaferCond cond;
1270 auto req = librbd::image::AttachChildRequest<>::create(
1271 child_ictx, src_ictx, src_ictx->snaps[0], nullptr, 0,
1272 CLONE_FORMAT, &cond);
1273 req->send();
1274 ASSERT_EQ(0, cond.wait());
1275 close_image(src_ictx);
1276 migration_abort(m_ioctx, m_image_name);
1277 });
1278 }
1279
1280 TEST_F(TestMigration, CloneV2ParentAbortFixParentReattach)
1281 {
1282 const uint32_t CLONE_FORMAT = 2;
1283 test_migrate_parent(
1284 CLONE_FORMAT, [this](librbd::ImageCtx *child_ictx) {
1285 auto src_image_id = m_ictx->id;
1286 migration_prepare(m_ioctx, m_image_name);
1287 // Re-attach the child back to the source to emulate a crash
1288 // after the parent reattach but before the child reattach
1289 librbd::ImageCtx *src_ictx;
1290 open_image(m_ioctx, "", src_image_id, false,
1291 librbd::OPEN_FLAG_IGNORE_MIGRATING, &src_ictx);
1292 C_SaferCond cond;
1293 auto req = librbd::image::AttachChildRequest<>::create(
1294 child_ictx, src_ictx, src_ictx->snaps[0], m_ictx,
1295 m_ictx->snaps[0], CLONE_FORMAT, &cond);
1296 req->send();
1297 ASSERT_EQ(0, cond.wait());
1298 close_image(src_ictx);
1299 migration_abort(m_ioctx, m_image_name);
1300 });
1301 }
1302
1303 TEST_F(TestMigration, CloneV2ParentAbortRelinkNotNeeded)
1304 {
1305 const uint32_t CLONE_FORMAT = 2;
1306 test_migrate_parent(
1307 CLONE_FORMAT, [this](librbd::ImageCtx *child_ictx) {
1308 auto src_image_id = m_ictx->id;
1309 auto parent_spec = child_ictx->parent_md.spec;
1310 parent_spec.image_id = m_ictx->id;
1311 parent_spec.snap_id = m_ictx->snaps[0];
1312 auto parent_overlap = child_ictx->parent_md.overlap;
1313 migration_prepare(m_ioctx, m_image_name);
1314 // Relink the child back to emulate a crash
1315 // before relinking the child
1316 C_SaferCond cond;
1317 auto req = librbd::image::AttachParentRequest<>::create(
1318 *child_ictx, parent_spec, parent_overlap, true, &cond);
1319 req->send();
1320 ASSERT_EQ(0, cond.wait());
1321 librbd::ImageCtx *src_ictx;
1322 open_image(m_ioctx, "", src_image_id, false,
1323 librbd::OPEN_FLAG_IGNORE_MIGRATING, &src_ictx);
1324 C_SaferCond cond1;
1325 auto req1 = librbd::image::AttachChildRequest<>::create(
1326 child_ictx, src_ictx, src_ictx->snaps[0], m_ictx,
1327 m_ictx->snaps[0], CLONE_FORMAT, &cond1);
1328 req1->send();
1329 ASSERT_EQ(0, cond1.wait());
1330 close_image(src_ictx);
1331 migration_abort(m_ioctx, m_image_name);
1332 });
1333 }
1334
1335 TEST_F(TestMigration, StressNoMigrate)
1336 {
1337 test_stress();
1338
1339 compare();
1340 }
1341
1342 TEST_F(TestMigration, Stress)
1343 {
1344 test_stress();
1345
1346 migrate(m_ioctx, m_image_name);
1347 }
1348
1349 TEST_F(TestMigration, Stress2)
1350 {
1351 test_stress2(false);
1352 }
1353
1354 TEST_F(TestMigration, StressLive)
1355 {
1356 test_stress2(true);
1357 }
1358
1359 } // namespace librbd