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