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