]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/rbd_mirror/test_ImageReplayer.cc
69dabbb7bcb5d39b4531c45c59cb768162557d29
[ceph.git] / ceph / src / test / rbd_mirror / test_ImageReplayer.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph distributed storage system
5 *
6 * Copyright (C) 2016 Mirantis Inc
7 *
8 * Author: Mykola Golub <mgolub@mirantis.com>
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 */
16
17 #include "include/rados/librados.hpp"
18 #include "include/rbd/librbd.hpp"
19 #include "include/stringify.h"
20 #include "test/librbd/test_support.h"
21 #include "test/rbd_mirror/test_fixture.h"
22 #include "cls/journal/cls_journal_types.h"
23 #include "cls/journal/cls_journal_client.h"
24 #include "cls/rbd/cls_rbd_types.h"
25 #include "cls/rbd/cls_rbd_client.h"
26 #include "journal/Journaler.h"
27 #include "librbd/ExclusiveLock.h"
28 #include "librbd/ImageCtx.h"
29 #include "librbd/ImageState.h"
30 #include "librbd/Journal.h"
31 #include "librbd/Operations.h"
32 #include "librbd/Utils.h"
33 #include "librbd/internal.h"
34 #include "librbd/api/Mirror.h"
35 #include "librbd/api/Snapshot.h"
36 #include "librbd/io/AioCompletion.h"
37 #include "librbd/io/ImageRequestWQ.h"
38 #include "librbd/io/ReadResult.h"
39 #include "tools/rbd_mirror/ImageReplayer.h"
40 #include "tools/rbd_mirror/InstanceWatcher.h"
41 #include "tools/rbd_mirror/MirrorStatusUpdater.h"
42 #include "tools/rbd_mirror/PoolMetaCache.h"
43 #include "tools/rbd_mirror/Threads.h"
44 #include "tools/rbd_mirror/Throttler.h"
45 #include "tools/rbd_mirror/Types.h"
46
47 #include "test/librados/test_cxx.h"
48 #include "gtest/gtest.h"
49
50 void register_test_rbd_mirror() {
51 }
52
53 #define TEST_IO_SIZE 512
54 #define TEST_IO_COUNT 11
55
56 namespace rbd {
57 namespace mirror {
58
59 template <typename T>
60 class TestImageReplayer : public TestFixture {
61 public:
62 static const cls::rbd::MirrorImageMode MIRROR_IMAGE_MODE =
63 T::MIRROR_IMAGE_MODE;
64 static const uint64_t FEATURES = T::FEATURES;
65
66 struct C_WatchCtx : public librados::WatchCtx2 {
67 TestImageReplayer *test;
68 std::string oid;
69 ceph::mutex lock = ceph::make_mutex("C_WatchCtx::lock");
70 ceph::condition_variable cond;
71 bool notified;
72
73 C_WatchCtx(TestImageReplayer *test, const std::string &oid)
74 : test(test), oid(oid), notified(false) {
75 }
76
77 void handle_notify(uint64_t notify_id, uint64_t cookie,
78 uint64_t notifier_id, bufferlist& bl_) override {
79 bufferlist bl;
80 test->m_remote_ioctx.notify_ack(oid, notify_id, cookie, bl);
81
82 std::lock_guard locker{lock};
83 notified = true;
84 cond.notify_all();
85 }
86
87 void handle_error(uint64_t cookie, int err) override {
88 ASSERT_EQ(0, err);
89 }
90 };
91
92 TestImageReplayer()
93 : m_local_cluster(new librados::Rados()), m_watch_handle(0)
94 {
95 EXPECT_EQ("", connect_cluster_pp(*m_local_cluster.get()));
96 EXPECT_EQ(0, m_local_cluster->conf_set("rbd_cache", "false"));
97 EXPECT_EQ(0, m_local_cluster->conf_set("rbd_mirror_journal_poll_age", "1"));
98 EXPECT_EQ(0, m_local_cluster->conf_set("rbd_mirror_journal_commit_age",
99 "0.1"));
100 m_local_pool_name = get_temp_pool_name();
101 EXPECT_EQ(0, m_local_cluster->pool_create(m_local_pool_name.c_str()));
102 EXPECT_EQ(0, m_local_cluster->ioctx_create(m_local_pool_name.c_str(),
103 m_local_ioctx));
104 m_local_ioctx.application_enable("rbd", true);
105
106 EXPECT_EQ("", connect_cluster_pp(m_remote_cluster));
107 EXPECT_EQ(0, m_remote_cluster.conf_set("rbd_cache", "false"));
108
109 m_remote_pool_name = get_temp_pool_name();
110 EXPECT_EQ(0, m_remote_cluster.pool_create(m_remote_pool_name.c_str()));
111 m_remote_pool_id = m_remote_cluster.pool_lookup(m_remote_pool_name.c_str());
112 EXPECT_GE(m_remote_pool_id, 0);
113
114 EXPECT_EQ(0, m_remote_cluster.ioctx_create(m_remote_pool_name.c_str(),
115 m_remote_ioctx));
116 m_remote_ioctx.application_enable("rbd", true);
117
118 // make snap id debugging easier when local/remote have different mappings
119 uint64_t snap_id;
120 EXPECT_EQ(0, m_remote_ioctx.selfmanaged_snap_create(&snap_id));
121
122 uint64_t features = FEATURES;
123 if (MIRROR_IMAGE_MODE == cls::rbd::MIRROR_IMAGE_MODE_JOURNAL) {
124 EXPECT_EQ(0, librbd::api::Mirror<>::mode_set(m_remote_ioctx,
125 RBD_MIRROR_MODE_POOL));
126 EXPECT_EQ(0, librbd::api::Mirror<>::mode_set(m_local_ioctx,
127 RBD_MIRROR_MODE_POOL));
128 } else {
129 EXPECT_EQ(0, librbd::api::Mirror<>::mode_set(m_remote_ioctx,
130 RBD_MIRROR_MODE_IMAGE));
131 EXPECT_EQ(0, librbd::api::Mirror<>::mode_set(m_local_ioctx,
132 RBD_MIRROR_MODE_IMAGE));
133
134
135 uuid_d uuid_gen;
136 uuid_gen.generate_random();
137 std::string remote_peer_uuid = uuid_gen.to_string();
138
139 EXPECT_EQ(0, librbd::cls_client::mirror_peer_add(
140 &m_remote_ioctx, {remote_peer_uuid,
141 cls::rbd::MIRROR_PEER_DIRECTION_RX_TX,
142 "siteA", "client", m_local_mirror_uuid}));
143
144 m_pool_meta_cache.set_remote_pool_meta(
145 m_remote_ioctx.get_id(), {m_remote_mirror_uuid, remote_peer_uuid});
146 }
147
148 EXPECT_EQ(0, librbd::api::Mirror<>::uuid_get(m_remote_ioctx,
149 &m_remote_mirror_uuid));
150 EXPECT_EQ(0, librbd::api::Mirror<>::uuid_get(m_local_ioctx,
151 &m_local_mirror_uuid));
152
153 m_image_name = get_temp_image_name();
154 int order = 0;
155 EXPECT_EQ(0, librbd::create(m_remote_ioctx, m_image_name.c_str(), 1 << 22,
156 false, features, &order, 0, 0));
157
158 if (MIRROR_IMAGE_MODE != cls::rbd::MIRROR_IMAGE_MODE_JOURNAL) {
159 librbd::ImageCtx* remote_image_ctx;
160 open_remote_image(&remote_image_ctx);
161 EXPECT_EQ(0,
162 librbd::api::Mirror<>::image_enable(
163 remote_image_ctx,
164 static_cast<rbd_mirror_image_mode_t>(MIRROR_IMAGE_MODE),
165 false));
166 close_image(remote_image_ctx);
167 }
168
169 m_remote_image_id = get_image_id(m_remote_ioctx, m_image_name);
170 m_global_image_id = get_global_image_id(m_remote_ioctx, m_remote_image_id);
171
172 auto cct = reinterpret_cast<CephContext*>(m_local_ioctx.cct());
173 m_threads.reset(new Threads<>(cct));
174
175 m_image_sync_throttler.reset(new Throttler<>(
176 cct, "rbd_mirror_concurrent_image_syncs"));
177
178 m_instance_watcher = InstanceWatcher<>::create(
179 m_local_ioctx, m_threads->work_queue, nullptr,
180 m_image_sync_throttler.get());
181 m_instance_watcher->handle_acquire_leader();
182
183 EXPECT_EQ(0, m_local_ioctx.create(RBD_MIRRORING, false));
184
185 m_local_status_updater = MirrorStatusUpdater<>::create(
186 m_local_ioctx, m_threads.get(), "");
187 C_SaferCond status_updater_ctx;
188 m_local_status_updater->init(&status_updater_ctx);
189 EXPECT_EQ(0, status_updater_ctx.wait());
190 }
191
192 ~TestImageReplayer() override
193 {
194 unwatch();
195
196 m_instance_watcher->handle_release_leader();
197
198 delete m_replayer;
199 delete m_instance_watcher;
200
201 C_SaferCond status_updater_ctx;
202 m_local_status_updater->shut_down(&status_updater_ctx);
203 EXPECT_EQ(0, status_updater_ctx.wait());
204 delete m_local_status_updater;
205
206 EXPECT_EQ(0, m_remote_cluster.pool_delete(m_remote_pool_name.c_str()));
207 EXPECT_EQ(0, m_local_cluster->pool_delete(m_local_pool_name.c_str()));
208 }
209
210 void create_replayer() {
211 m_replayer = new ImageReplayer<>(m_local_ioctx, m_local_mirror_uuid,
212 m_global_image_id, m_threads.get(),
213 m_instance_watcher, m_local_status_updater,
214 nullptr, &m_pool_meta_cache);
215 m_replayer->add_peer({"peer uuid", m_remote_ioctx,
216 {m_remote_mirror_uuid, "remote mirror peer uuid"},
217 nullptr});
218 }
219
220 void start()
221 {
222 C_SaferCond cond;
223 m_replayer->start(&cond);
224 ASSERT_EQ(0, cond.wait());
225
226 create_watch_ctx();
227 }
228
229 void create_watch_ctx() {
230 std::string oid;
231 if (MIRROR_IMAGE_MODE == cls::rbd::MIRROR_IMAGE_MODE_JOURNAL) {
232 oid = ::journal::Journaler::header_oid(m_remote_image_id);
233 } else {
234 oid = librbd::util::header_name(m_remote_image_id);
235 }
236
237 ASSERT_EQ(0U, m_watch_handle);
238 ASSERT_TRUE(m_watch_ctx == nullptr);
239 m_watch_ctx = new C_WatchCtx(this, oid);
240 ASSERT_EQ(0, m_remote_ioctx.watch2(oid, &m_watch_handle, m_watch_ctx));
241 }
242
243 void unwatch() {
244 if (m_watch_handle != 0) {
245 m_remote_ioctx.unwatch2(m_watch_handle);
246 delete m_watch_ctx;
247 m_watch_ctx = nullptr;
248 m_watch_handle = 0;
249 }
250 }
251
252 void stop()
253 {
254 unwatch();
255
256 C_SaferCond cond;
257 m_replayer->stop(&cond);
258 ASSERT_EQ(0, cond.wait());
259 }
260
261 void bootstrap()
262 {
263 create_replayer();
264
265 start();
266 wait_for_replay_complete();
267 stop();
268 }
269
270 std::string get_temp_image_name()
271 {
272 return "image" + stringify(++_image_number);
273 }
274
275 std::string get_image_id(librados::IoCtx &ioctx, const string &image_name)
276 {
277 std::string obj = librbd::util::id_obj_name(image_name);
278 std::string id;
279 EXPECT_EQ(0, librbd::cls_client::get_id(&ioctx, obj, &id));
280 return id;
281 }
282
283 std::string get_global_image_id(librados::IoCtx& io_ctx,
284 const std::string& image_id) {
285 cls::rbd::MirrorImage mirror_image;
286 EXPECT_EQ(0, librbd::cls_client::mirror_image_get(&io_ctx, image_id,
287 &mirror_image));
288 return mirror_image.global_image_id;
289 }
290
291 void open_image(librados::IoCtx &ioctx, const std::string &image_name,
292 bool readonly, librbd::ImageCtx **ictxp)
293 {
294 librbd::ImageCtx *ictx = new librbd::ImageCtx(image_name.c_str(),
295 "", "", ioctx, readonly);
296 EXPECT_EQ(0, ictx->state->open(0));
297 *ictxp = ictx;
298 }
299
300 void open_local_image(librbd::ImageCtx **ictxp)
301 {
302 open_image(m_local_ioctx, m_image_name, true, ictxp);
303 }
304
305 void open_remote_image(librbd::ImageCtx **ictxp)
306 {
307 open_image(m_remote_ioctx, m_image_name, false, ictxp);
308 }
309
310 void close_image(librbd::ImageCtx *ictx)
311 {
312 ictx->state->close();
313 }
314
315 void get_commit_positions(cls::journal::ObjectPosition *master_position,
316 cls::journal::ObjectPosition *mirror_position)
317 {
318 std::string master_client_id = "";
319 std::string mirror_client_id = m_local_mirror_uuid;
320
321 m_replayer->flush();
322
323 C_SaferCond cond;
324 uint64_t minimum_set;
325 uint64_t active_set;
326 std::set<cls::journal::Client> registered_clients;
327 std::string oid = ::journal::Journaler::header_oid(m_remote_image_id);
328 cls::journal::client::get_mutable_metadata(m_remote_ioctx, oid,
329 &minimum_set, &active_set,
330 &registered_clients, &cond);
331 ASSERT_EQ(0, cond.wait());
332
333 *master_position = cls::journal::ObjectPosition();
334 *mirror_position = cls::journal::ObjectPosition();
335
336 std::set<cls::journal::Client>::const_iterator c;
337 for (c = registered_clients.begin(); c != registered_clients.end(); ++c) {
338 std::cout << __func__ << ": client: " << *c << std::endl;
339 if (c->state != cls::journal::CLIENT_STATE_CONNECTED) {
340 continue;
341 }
342 cls::journal::ObjectPositions object_positions =
343 c->commit_position.object_positions;
344 cls::journal::ObjectPositions::const_iterator p =
345 object_positions.begin();
346 if (p != object_positions.end()) {
347 if (c->id == master_client_id) {
348 ASSERT_EQ(cls::journal::ObjectPosition(), *master_position);
349 *master_position = *p;
350 } else if (c->id == mirror_client_id) {
351 ASSERT_EQ(cls::journal::ObjectPosition(), *mirror_position);
352 *mirror_position = *p;
353 }
354 }
355 }
356 }
357
358 bool wait_for_watcher_notify(int seconds)
359 {
360 if (m_watch_handle == 0) {
361 return false;
362 }
363
364 std::unique_lock locker{m_watch_ctx->lock};
365 while (!m_watch_ctx->notified) {
366 if (m_watch_ctx->cond.wait_for(locker,
367 std::chrono::seconds(seconds)) ==
368 std::cv_status::timeout) {
369 return false;
370 }
371 }
372 m_watch_ctx->notified = false;
373 return true;
374 }
375
376 int get_last_mirror_snapshot(librados::IoCtx& io_ctx,
377 const std::string& image_id,
378 uint64_t* mirror_snap_id,
379 cls::rbd::MirrorSnapshotNamespace* mirror_ns) {
380 auto header_oid = librbd::util::header_name(image_id);
381 ::SnapContext snapc;
382 int r = librbd::cls_client::get_snapcontext(&io_ctx, header_oid, &snapc);
383 if (r < 0) {
384 return r;
385 }
386
387 // stored in reverse order
388 for (auto snap_id : snapc.snaps) {
389 cls::rbd::SnapshotInfo snap_info;
390 r = librbd::cls_client::snapshot_get(&io_ctx, header_oid, snap_id,
391 &snap_info);
392 if (r < 0) {
393 return r;
394 }
395
396 auto ns = boost::get<cls::rbd::MirrorSnapshotNamespace>(
397 &snap_info.snapshot_namespace);
398 if (ns != nullptr) {
399 *mirror_snap_id = snap_id;
400 *mirror_ns = *ns;
401 return 0;
402 }
403 }
404
405 return -ENOENT;
406 }
407
408 void wait_for_journal_synced() {
409 cls::journal::ObjectPosition master_position;
410 cls::journal::ObjectPosition mirror_position;
411 for (int i = 0; i < 100; i++) {
412 get_commit_positions(&master_position, &mirror_position);
413 if (master_position == mirror_position) {
414 break;
415 }
416 wait_for_watcher_notify(1);
417 }
418
419 ASSERT_EQ(master_position, mirror_position);
420 }
421
422 void wait_for_snapshot_synced() {
423 uint64_t remote_snap_id = CEPH_NOSNAP;
424 cls::rbd::MirrorSnapshotNamespace remote_mirror_ns;
425 ASSERT_EQ(0, get_last_mirror_snapshot(m_remote_ioctx, m_remote_image_id,
426 &remote_snap_id, &remote_mirror_ns));
427
428 std::cout << "remote_snap_id=" << remote_snap_id << std::endl;
429
430 std::string local_image_id;
431 ASSERT_EQ(0, librbd::cls_client::mirror_image_get_image_id(
432 &m_local_ioctx, m_global_image_id, &local_image_id));
433
434 uint64_t local_snap_id = CEPH_NOSNAP;
435 cls::rbd::MirrorSnapshotNamespace local_mirror_ns;
436 for (int i = 0; i < 100; i++) {
437 int r = get_last_mirror_snapshot(m_local_ioctx, local_image_id,
438 &local_snap_id, &local_mirror_ns);
439 if (r == 0 &&
440 ((remote_mirror_ns.state ==
441 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY &&
442 local_mirror_ns.state ==
443 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY) ||
444 (remote_mirror_ns.state ==
445 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED &&
446 local_mirror_ns.state ==
447 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED)) &&
448 local_mirror_ns.primary_mirror_uuid == m_remote_mirror_uuid &&
449 local_mirror_ns.primary_snap_id == remote_snap_id &&
450 local_mirror_ns.complete) {
451
452 std::cout << "local_snap_id=" << local_snap_id << ", "
453 << "local_snap_ns=" << local_mirror_ns << std::endl;
454 return;
455 }
456
457 wait_for_watcher_notify(1);
458 }
459
460 ADD_FAILURE() << "failed to locate matching snapshot: "
461 << "remote_snap_id=" << remote_snap_id << ", "
462 << "remote_snap_ns=" << remote_mirror_ns << ", "
463 << "local_snap_id=" << local_snap_id << ", "
464 << "local_snap_ns=" << local_mirror_ns;
465 }
466
467 void wait_for_replay_complete()
468 {
469 if (MIRROR_IMAGE_MODE == cls::rbd::MIRROR_IMAGE_MODE_JOURNAL) {
470 wait_for_journal_synced();
471 } else {
472 wait_for_snapshot_synced();
473 }
474 }
475
476 void wait_for_stopped() {
477 for (int i = 0; i < 100; i++) {
478 if (m_replayer->is_stopped()) {
479 break;
480 }
481 wait_for_watcher_notify(1);
482 }
483 ASSERT_TRUE(m_replayer->is_stopped());
484 }
485
486 void write_test_data(librbd::ImageCtx *ictx, const char *test_data, off_t off,
487 size_t len)
488 {
489 size_t written;
490 bufferlist bl;
491 bl.append(std::string(test_data, len));
492 written = ictx->io_work_queue->write(off, len, std::move(bl), 0);
493 printf("wrote: %d\n", (int)written);
494 ASSERT_EQ(len, written);
495 }
496
497 void read_test_data(librbd::ImageCtx *ictx, const char *expected, off_t off,
498 size_t len)
499 {
500 ssize_t read;
501 char *result = (char *)malloc(len + 1);
502
503 ASSERT_NE(static_cast<char *>(NULL), result);
504 read = ictx->io_work_queue->read(
505 off, len, librbd::io::ReadResult{result, len}, 0);
506 printf("read: %d\n", (int)read);
507 ASSERT_EQ(len, static_cast<size_t>(read));
508 result[len] = '\0';
509 if (memcmp(result, expected, len)) {
510 printf("read: %s\nexpected: %s\n", result, expected);
511 ASSERT_EQ(0, memcmp(result, expected, len));
512 }
513 free(result);
514 }
515
516 void generate_test_data() {
517 for (int i = 0; i < TEST_IO_SIZE; ++i) {
518 m_test_data[i] = (char) (rand() % (126 - 33) + 33);
519 }
520 m_test_data[TEST_IO_SIZE] = '\0';
521 }
522
523 void flush(librbd::ImageCtx *ictx)
524 {
525 C_SaferCond aio_flush_ctx;
526 auto c = librbd::io::AioCompletion::create(&aio_flush_ctx);
527 c->get();
528 ictx->io_work_queue->aio_flush(c);
529 ASSERT_EQ(0, c->wait_for_complete());
530 c->put();
531
532 if (MIRROR_IMAGE_MODE == cls::rbd::MIRROR_IMAGE_MODE_JOURNAL) {
533 C_SaferCond journal_flush_ctx;
534 ictx->journal->flush_commit_position(&journal_flush_ctx);
535 ASSERT_EQ(0, journal_flush_ctx.wait());
536 } else {
537 uint64_t snap_id = CEPH_NOSNAP;
538 ASSERT_EQ(0, librbd::api::Mirror<>::image_snapshot_create(
539 ictx, &snap_id));
540 }
541
542 printf("flushed\n");
543 }
544
545 static int _image_number;
546
547 PoolMetaCache m_pool_meta_cache{g_ceph_context};
548
549 std::shared_ptr<librados::Rados> m_local_cluster;
550 std::unique_ptr<Threads<>> m_threads;
551 std::unique_ptr<Throttler<>> m_image_sync_throttler;
552 librados::Rados m_remote_cluster;
553 InstanceWatcher<> *m_instance_watcher;
554 MirrorStatusUpdater<> *m_local_status_updater;
555 std::string m_local_mirror_uuid = "local mirror uuid";
556 std::string m_remote_mirror_uuid = "remote mirror uuid";
557 std::string m_local_pool_name, m_remote_pool_name;
558 librados::IoCtx m_local_ioctx, m_remote_ioctx;
559 std::string m_image_name;
560 int64_t m_remote_pool_id;
561 std::string m_remote_image_id;
562 std::string m_global_image_id;
563 ImageReplayer<> *m_replayer = nullptr;
564 C_WatchCtx *m_watch_ctx = nullptr;
565 uint64_t m_watch_handle = 0;
566 char m_test_data[TEST_IO_SIZE + 1];
567 std::string m_journal_commit_age;
568 };
569
570 template <typename T>
571 int TestImageReplayer<T>::_image_number;
572
573 template <cls::rbd::MirrorImageMode _mirror_image_mode, uint64_t _features>
574 class TestImageReplayerParams {
575 public:
576 static const cls::rbd::MirrorImageMode MIRROR_IMAGE_MODE = _mirror_image_mode;
577 static const uint64_t FEATURES = _features;
578 };
579
580 typedef ::testing::Types<TestImageReplayerParams<
581 cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, 125>,
582 TestImageReplayerParams<
583 cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT, 1>,
584 TestImageReplayerParams<
585 cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT, 5>,
586 TestImageReplayerParams<
587 cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT, 61>,
588 TestImageReplayerParams<
589 cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT, 125>>
590 TestImageReplayerTypes;
591
592 TYPED_TEST_SUITE(TestImageReplayer, TestImageReplayerTypes);
593
594 TYPED_TEST(TestImageReplayer, Bootstrap)
595 {
596 this->bootstrap();
597 }
598
599 typedef TestImageReplayer<TestImageReplayerParams<
600 cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, 125>> TestImageReplayerJournal;
601
602 TYPED_TEST(TestImageReplayer, BootstrapErrorLocalImageExists)
603 {
604 int order = 0;
605 EXPECT_EQ(0, librbd::create(this->m_local_ioctx, this->m_image_name.c_str(),
606 1 << 22, false, 0, &order, 0, 0));
607
608 this->create_replayer();
609 C_SaferCond cond;
610 this->m_replayer->start(&cond);
611 ASSERT_EQ(-EEXIST, cond.wait());
612 }
613
614 TEST_F(TestImageReplayerJournal, BootstrapErrorNoJournal)
615 {
616 ASSERT_EQ(0, librbd::Journal<>::remove(this->m_remote_ioctx,
617 this->m_remote_image_id));
618
619 this->create_replayer();
620 C_SaferCond cond;
621 this->m_replayer->start(&cond);
622 ASSERT_EQ(-ENOENT, cond.wait());
623 }
624
625 TYPED_TEST(TestImageReplayer, BootstrapErrorMirrorDisabled)
626 {
627 // disable remote image mirroring
628 ASSERT_EQ(0, librbd::api::Mirror<>::mode_set(this->m_remote_ioctx,
629 RBD_MIRROR_MODE_IMAGE));
630 librbd::ImageCtx *ictx;
631 this->open_remote_image(&ictx);
632 ASSERT_EQ(0, librbd::api::Mirror<>::image_disable(ictx, true));
633 this->close_image(ictx);
634
635 this->create_replayer();
636 C_SaferCond cond;
637 this->m_replayer->start(&cond);
638 ASSERT_EQ(-ENOENT, cond.wait());
639 }
640
641 TYPED_TEST(TestImageReplayer, BootstrapMirrorDisabling)
642 {
643 // set remote image mirroring state to DISABLING
644 if (gtest_TypeParam_::MIRROR_IMAGE_MODE ==
645 cls::rbd::MIRROR_IMAGE_MODE_JOURNAL) {
646 ASSERT_EQ(0, librbd::api::Mirror<>::mode_set(this->m_remote_ioctx,
647 RBD_MIRROR_MODE_IMAGE));
648 librbd::ImageCtx *ictx;
649 this->open_remote_image(&ictx);
650 ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(
651 ictx, RBD_MIRROR_IMAGE_MODE_JOURNAL, false));
652 this->close_image(ictx);
653 }
654
655 cls::rbd::MirrorImage mirror_image;
656 ASSERT_EQ(0, librbd::cls_client::mirror_image_get(&this->m_remote_ioctx,
657 this->m_remote_image_id,
658 &mirror_image));
659 mirror_image.state = cls::rbd::MirrorImageState::MIRROR_IMAGE_STATE_DISABLING;
660 ASSERT_EQ(0, librbd::cls_client::mirror_image_set(&this->m_remote_ioctx,
661 this->m_remote_image_id,
662 mirror_image));
663
664 this->create_replayer();
665 C_SaferCond cond;
666 this->m_replayer->start(&cond);
667 ASSERT_EQ(-EREMOTEIO, cond.wait());
668 ASSERT_TRUE(this->m_replayer->is_stopped());
669 }
670
671 TYPED_TEST(TestImageReplayer, BootstrapDemoted)
672 {
673 // demote remote image
674 librbd::ImageCtx *ictx;
675 this->open_remote_image(&ictx);
676 ASSERT_EQ(0, librbd::api::Mirror<>::image_demote(ictx));
677 this->close_image(ictx);
678
679 this->create_replayer();
680 C_SaferCond cond;
681 this->m_replayer->start(&cond);
682 ASSERT_EQ(-EREMOTEIO, cond.wait());
683 ASSERT_TRUE(this->m_replayer->is_stopped());
684 }
685
686 TYPED_TEST(TestImageReplayer, StartInterrupted)
687 {
688 this->create_replayer();
689 C_SaferCond start_cond, stop_cond;
690 this->m_replayer->start(&start_cond);
691 this->m_replayer->stop(&stop_cond);
692 int r = start_cond.wait();
693 printf("start returned %d\n", r);
694 // TODO: improve the test to avoid this race
695 ASSERT_TRUE(r == -ECANCELED || r == 0);
696 ASSERT_EQ(0, stop_cond.wait());
697 }
698
699 TEST_F(TestImageReplayerJournal, JournalReset)
700 {
701 this->bootstrap();
702 delete this->m_replayer;
703
704 ASSERT_EQ(0, librbd::Journal<>::reset(this->m_remote_ioctx,
705 this->m_remote_image_id));
706
707 // try to recover
708 this->bootstrap();
709 }
710
711 TEST_F(TestImageReplayerJournal, ErrorNoJournal)
712 {
713 this->bootstrap();
714
715 // disable remote journal journaling
716 // (reset before disabling, so it does not fail with EBUSY)
717 ASSERT_EQ(0, librbd::Journal<>::reset(this->m_remote_ioctx,
718 this->m_remote_image_id));
719 librbd::ImageCtx *ictx;
720 this->open_remote_image(&ictx);
721 uint64_t features;
722 ASSERT_EQ(0, librbd::get_features(ictx, &features));
723 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
724 false));
725 this->close_image(ictx);
726
727 C_SaferCond cond;
728 this->m_replayer->start(&cond);
729 ASSERT_EQ(0, cond.wait());
730 }
731
732 TYPED_TEST(TestImageReplayer, StartStop)
733 {
734 this->bootstrap();
735
736 this->start();
737 this->wait_for_replay_complete();
738 this->stop();
739 }
740
741 TYPED_TEST(TestImageReplayer, WriteAndStartReplay)
742 {
743 this->bootstrap();
744
745 // Write to remote image and start replay
746
747 librbd::ImageCtx *ictx;
748
749 this->generate_test_data();
750 this->open_remote_image(&ictx);
751 for (int i = 0; i < TEST_IO_COUNT; ++i) {
752 this->write_test_data(ictx, this->m_test_data, TEST_IO_SIZE * i,
753 TEST_IO_SIZE);
754 }
755 this->flush(ictx);
756 this->close_image(ictx);
757
758 this->start();
759 this->wait_for_replay_complete();
760 this->stop();
761
762 this->open_local_image(&ictx);
763 for (int i = 0; i < TEST_IO_COUNT; ++i) {
764 this->read_test_data(ictx, this->m_test_data, TEST_IO_SIZE * i,
765 TEST_IO_SIZE);
766 }
767 this->close_image(ictx);
768 }
769
770 TYPED_TEST(TestImageReplayer, StartReplayAndWrite)
771 {
772 this->bootstrap();
773
774 // Start replay and write to remote image
775
776 librbd::ImageCtx *ictx;
777
778 this->start();
779
780 this->generate_test_data();
781 this->open_remote_image(&ictx);
782 for (int i = 0; i < TEST_IO_COUNT; ++i) {
783 this->write_test_data(ictx, this->m_test_data, TEST_IO_SIZE * i,
784 TEST_IO_SIZE);
785 }
786 this->flush(ictx);
787
788 this->wait_for_replay_complete();
789
790 for (int i = TEST_IO_COUNT; i < 2 * TEST_IO_COUNT; ++i) {
791 this->write_test_data(ictx, this->m_test_data, TEST_IO_SIZE * i,
792 TEST_IO_SIZE);
793 }
794 this->flush(ictx);
795 this->close_image(ictx);
796
797 this->wait_for_replay_complete();
798
799 this->open_local_image(&ictx);
800 for (int i = 0; i < 2 * TEST_IO_COUNT; ++i) {
801 this->read_test_data(ictx, this->m_test_data, TEST_IO_SIZE * i,
802 TEST_IO_SIZE);
803 }
804 this->close_image(ictx);
805
806 this->stop();
807 }
808
809 TEST_F(TestImageReplayerJournal, NextTag)
810 {
811 this->bootstrap();
812
813 // write, reopen, and write again to test switch to the next tag
814
815 librbd::ImageCtx *ictx;
816
817 this->start();
818
819 this->generate_test_data();
820
821 const int N = 10;
822
823 for (int j = 0; j < N; j++) {
824 this->open_remote_image(&ictx);
825 for (int i = j * TEST_IO_COUNT; i < (j + 1) * TEST_IO_COUNT; ++i) {
826 this->write_test_data(ictx, this->m_test_data, TEST_IO_SIZE * i,
827 TEST_IO_SIZE);
828 }
829 this->close_image(ictx);
830 }
831
832 this->wait_for_replay_complete();
833
834 this->open_local_image(&ictx);
835 for (int i = 0; i < N * TEST_IO_COUNT; ++i) {
836 this->read_test_data(ictx, this->m_test_data, TEST_IO_SIZE * i,
837 TEST_IO_SIZE);
838 }
839 this->close_image(ictx);
840
841 this->stop();
842 }
843
844 TYPED_TEST(TestImageReplayer, Resync)
845 {
846 this->bootstrap();
847
848 librbd::ImageCtx *ictx;
849
850 this->start();
851
852 this->generate_test_data();
853
854 this->open_remote_image(&ictx);
855 for (int i = 0; i < TEST_IO_COUNT; ++i) {
856 this->write_test_data(ictx, this->m_test_data, TEST_IO_SIZE * i,
857 TEST_IO_SIZE);
858 }
859 this->flush(ictx);
860
861 this->wait_for_replay_complete();
862
863 for (int i = TEST_IO_COUNT; i < 2 * TEST_IO_COUNT; ++i) {
864 this->write_test_data(ictx, this->m_test_data, TEST_IO_SIZE * i,
865 TEST_IO_SIZE);
866 }
867 this->flush(ictx);
868 this->close_image(ictx);
869
870 this->open_local_image(&ictx);
871 EXPECT_EQ(0, librbd::api::Mirror<>::image_resync(ictx));
872 this->close_image(ictx);
873
874 this->wait_for_stopped();
875
876 C_SaferCond cond;
877 this->m_replayer->start(&cond);
878 ASSERT_EQ(0, cond.wait());
879
880 ASSERT_TRUE(this->m_replayer->is_replaying());
881 this->wait_for_replay_complete();
882
883 this->open_local_image(&ictx);
884 for (int i = 0; i < 2 * TEST_IO_COUNT; ++i) {
885 this->read_test_data(ictx, this->m_test_data, TEST_IO_SIZE * i,
886 TEST_IO_SIZE);
887 }
888 this->close_image(ictx);
889
890 this->stop();
891 }
892
893 TYPED_TEST(TestImageReplayer, Resync_While_Stop)
894 {
895 this->bootstrap();
896
897 this->start();
898
899 this->generate_test_data();
900
901 librbd::ImageCtx *ictx;
902 this->open_remote_image(&ictx);
903 for (int i = 0; i < TEST_IO_COUNT; ++i) {
904 this->write_test_data(ictx, this->m_test_data, TEST_IO_SIZE * i,
905 TEST_IO_SIZE);
906 }
907 this->flush(ictx);
908
909 this->wait_for_replay_complete();
910
911 for (int i = TEST_IO_COUNT; i < 2 * TEST_IO_COUNT; ++i) {
912 this->write_test_data(ictx, this->m_test_data, TEST_IO_SIZE * i,
913 TEST_IO_SIZE);
914 }
915 this->flush(ictx);
916 this->close_image(ictx);
917
918 this->wait_for_replay_complete();
919
920 C_SaferCond cond;
921 this->m_replayer->stop(&cond);
922 ASSERT_EQ(0, cond.wait());
923
924 this->open_local_image(&ictx);
925 EXPECT_EQ(0, librbd::api::Mirror<>::image_resync(ictx));
926 this->close_image(ictx);
927
928 C_SaferCond cond2;
929 this->m_replayer->start(&cond2);
930 ASSERT_EQ(0, cond2.wait());
931
932 ASSERT_TRUE(this->m_replayer->is_stopped());
933
934 C_SaferCond cond3;
935 this->m_replayer->start(&cond3);
936 ASSERT_EQ(0, cond3.wait());
937
938 ASSERT_TRUE(this->m_replayer->is_replaying());
939
940 this->wait_for_replay_complete();
941
942 this->open_local_image(&ictx);
943 for (int i = 0; i < 2 * TEST_IO_COUNT; ++i) {
944 this->read_test_data(ictx, this->m_test_data, TEST_IO_SIZE * i,
945 TEST_IO_SIZE);
946 }
947 this->close_image(ictx);
948
949 this->stop();
950 }
951
952 TYPED_TEST(TestImageReplayer, Resync_StartInterrupted)
953 {
954 this->bootstrap();
955
956 librbd::ImageCtx *ictx;
957 this->open_local_image(&ictx);
958 EXPECT_EQ(0, librbd::api::Mirror<>::image_resync(ictx));
959 this->close_image(ictx);
960
961 C_SaferCond cond;
962 this->m_replayer->start(&cond);
963 ASSERT_EQ(0, cond.wait());
964
965 ASSERT_TRUE(this->m_replayer->is_stopped());
966
967 C_SaferCond cond2;
968 this->m_replayer->start(&cond2);
969 ASSERT_EQ(0, cond2.wait());
970
971 this->create_watch_ctx();
972
973 ASSERT_TRUE(this->m_replayer->is_replaying());
974
975 this->generate_test_data();
976 this->open_remote_image(&ictx);
977 for (int i = 0; i < TEST_IO_COUNT; ++i) {
978 this->write_test_data(ictx, this->m_test_data, TEST_IO_SIZE * i,
979 TEST_IO_SIZE);
980 }
981 this->flush(ictx);
982
983 this->wait_for_replay_complete();
984
985 for (int i = TEST_IO_COUNT; i < 2 * TEST_IO_COUNT; ++i) {
986 this->write_test_data(ictx, this->m_test_data, TEST_IO_SIZE * i,
987 TEST_IO_SIZE);
988 }
989 this->flush(ictx);
990 this->close_image(ictx);
991
992 this->wait_for_replay_complete();
993
994 this->open_local_image(&ictx);
995 for (int i = 0; i < 2 * TEST_IO_COUNT; ++i) {
996 this->read_test_data(ictx, this->m_test_data, TEST_IO_SIZE * i,
997 TEST_IO_SIZE);
998 }
999 this->close_image(ictx);
1000
1001 this->stop();
1002 }
1003
1004 TEST_F(TestImageReplayerJournal, MultipleReplayFailures_SingleEpoch) {
1005 this->bootstrap();
1006
1007 // inject a snapshot that cannot be unprotected
1008 librbd::ImageCtx *ictx;
1009 this->open_image(this->m_local_ioctx, this->m_image_name, false, &ictx);
1010 ictx->features &= ~RBD_FEATURE_JOURNALING;
1011 ASSERT_EQ(0, ictx->operations->snap_create(cls::rbd::UserSnapshotNamespace(),
1012 "foo"));
1013 ASSERT_EQ(0, ictx->operations->snap_protect(cls::rbd::UserSnapshotNamespace(),
1014 "foo"));
1015 ASSERT_EQ(0, librbd::cls_client::add_child(&ictx->md_ctx, RBD_CHILDREN,
1016 {ictx->md_ctx.get_id(), "",
1017 ictx->id,
1018 ictx->snap_ids[{cls::rbd::UserSnapshotNamespace(), "foo"}]},
1019 "dummy child id"));
1020 this->close_image(ictx);
1021
1022 // race failed op shut down with new ops
1023 this->open_remote_image(&ictx);
1024 for (uint64_t i = 0; i < 10; ++i) {
1025 std::shared_lock owner_locker{ictx->owner_lock};
1026 C_SaferCond request_lock;
1027 ictx->exclusive_lock->acquire_lock(&request_lock);
1028 ASSERT_EQ(0, request_lock.wait());
1029
1030 C_SaferCond append_ctx;
1031 ictx->journal->append_op_event(
1032 i,
1033 librbd::journal::EventEntry{
1034 librbd::journal::SnapUnprotectEvent{i,
1035 cls::rbd::UserSnapshotNamespace(),
1036 "foo"}},
1037 &append_ctx);
1038 ASSERT_EQ(0, append_ctx.wait());
1039
1040 C_SaferCond commit_ctx;
1041 ictx->journal->commit_op_event(i, 0, &commit_ctx);
1042 ASSERT_EQ(0, commit_ctx.wait());
1043
1044 C_SaferCond release_ctx;
1045 ictx->exclusive_lock->release_lock(&release_ctx);
1046 ASSERT_EQ(0, release_ctx.wait());
1047 }
1048
1049 for (uint64_t i = 0; i < 5; ++i) {
1050 this->start();
1051 this->wait_for_stopped();
1052 this->unwatch();
1053 }
1054 this->close_image(ictx);
1055 }
1056
1057 TEST_F(TestImageReplayerJournal, MultipleReplayFailures_MultiEpoch) {
1058 this->bootstrap();
1059
1060 // inject a snapshot that cannot be unprotected
1061 librbd::ImageCtx *ictx;
1062 this->open_image(this->m_local_ioctx, this->m_image_name, false, &ictx);
1063 ictx->features &= ~RBD_FEATURE_JOURNALING;
1064 ASSERT_EQ(0, ictx->operations->snap_create(cls::rbd::UserSnapshotNamespace(),
1065 "foo"));
1066 ASSERT_EQ(0, ictx->operations->snap_protect(cls::rbd::UserSnapshotNamespace(),
1067 "foo"));
1068 ASSERT_EQ(0, librbd::cls_client::add_child(&ictx->md_ctx, RBD_CHILDREN,
1069 {ictx->md_ctx.get_id(), "",
1070 ictx->id,
1071 ictx->snap_ids[{cls::rbd::UserSnapshotNamespace(),
1072 "foo"}]},
1073 "dummy child id"));
1074 this->close_image(ictx);
1075
1076 // race failed op shut down with new tag flush
1077 this->open_remote_image(&ictx);
1078 {
1079 std::shared_lock owner_locker{ictx->owner_lock};
1080 C_SaferCond request_lock;
1081 ictx->exclusive_lock->acquire_lock(&request_lock);
1082 ASSERT_EQ(0, request_lock.wait());
1083
1084 C_SaferCond append_ctx;
1085 ictx->journal->append_op_event(
1086 1U,
1087 librbd::journal::EventEntry{
1088 librbd::journal::SnapUnprotectEvent{1U,
1089 cls::rbd::UserSnapshotNamespace(),
1090 "foo"}},
1091 &append_ctx);
1092 ASSERT_EQ(0, append_ctx.wait());
1093
1094 C_SaferCond commit_ctx;
1095 ictx->journal->commit_op_event(1U, 0, &commit_ctx);
1096 ASSERT_EQ(0, commit_ctx.wait());
1097
1098 C_SaferCond release_ctx;
1099 ictx->exclusive_lock->release_lock(&release_ctx);
1100 ASSERT_EQ(0, release_ctx.wait());
1101 }
1102
1103 this->generate_test_data();
1104 this->write_test_data(ictx, this->m_test_data, 0, TEST_IO_SIZE);
1105
1106 for (uint64_t i = 0; i < 5; ++i) {
1107 this->start();
1108 this->wait_for_stopped();
1109 this->unwatch();
1110 }
1111 this->close_image(ictx);
1112 }
1113
1114 TEST_F(TestImageReplayerJournal, Disconnect)
1115 {
1116 this->bootstrap();
1117
1118 // Make sure rbd_mirroring_resync_after_disconnect is not set
1119 EXPECT_EQ(0, this->m_local_cluster->conf_set("rbd_mirroring_resync_after_disconnect", "false"));
1120
1121 // Test start fails if disconnected
1122
1123 librbd::ImageCtx *ictx;
1124
1125 this->generate_test_data();
1126 this->open_remote_image(&ictx);
1127 for (int i = 0; i < TEST_IO_COUNT; ++i) {
1128 this->write_test_data(ictx, this->m_test_data, TEST_IO_SIZE * i,
1129 TEST_IO_SIZE);
1130 }
1131 this->flush(ictx);
1132 this->close_image(ictx);
1133
1134 std::string oid = ::journal::Journaler::header_oid(this->m_remote_image_id);
1135 ASSERT_EQ(0,
1136 cls::journal::client::client_update_state(this->m_remote_ioctx,
1137 oid, this->m_local_mirror_uuid,
1138 cls::journal::CLIENT_STATE_DISCONNECTED));
1139
1140 C_SaferCond cond1;
1141 this->m_replayer->start(&cond1);
1142 ASSERT_EQ(-ENOTCONN, cond1.wait());
1143
1144 // Test start succeeds after resync
1145
1146 this->open_local_image(&ictx);
1147 librbd::Journal<>::request_resync(ictx);
1148 this->close_image(ictx);
1149 C_SaferCond cond2;
1150 this->m_replayer->start(&cond2);
1151 ASSERT_EQ(0, cond2.wait());
1152
1153 this->start();
1154 this->wait_for_replay_complete();
1155
1156 // Test replay stopped after disconnect
1157
1158 this->open_remote_image(&ictx);
1159 for (int i = TEST_IO_COUNT; i < 2 * TEST_IO_COUNT; ++i) {
1160 this->write_test_data(ictx, this->m_test_data, TEST_IO_SIZE * i,
1161 TEST_IO_SIZE);
1162 }
1163 this->flush(ictx);
1164 this->close_image(ictx);
1165
1166 ASSERT_EQ(0,
1167 cls::journal::client::client_update_state(this->m_remote_ioctx, oid,
1168 this->m_local_mirror_uuid,
1169 cls::journal::CLIENT_STATE_DISCONNECTED));
1170 bufferlist bl;
1171 ASSERT_EQ(0, this->m_remote_ioctx.notify2(oid, bl, 5000, NULL));
1172
1173 this->wait_for_stopped();
1174
1175 // Test start fails after disconnect
1176
1177 C_SaferCond cond3;
1178 this->m_replayer->start(&cond3);
1179 ASSERT_EQ(-ENOTCONN, cond3.wait());
1180 C_SaferCond cond4;
1181 this->m_replayer->start(&cond4);
1182 ASSERT_EQ(-ENOTCONN, cond4.wait());
1183
1184 // Test automatic resync if rbd_mirroring_resync_after_disconnect is set
1185
1186 EXPECT_EQ(0, this->m_local_cluster->conf_set("rbd_mirroring_resync_after_disconnect", "true"));
1187
1188 // Resync is flagged on first start attempt
1189 C_SaferCond cond5;
1190 this->m_replayer->start(&cond5);
1191 ASSERT_EQ(-ENOTCONN, cond5.wait());
1192
1193 C_SaferCond cond6;
1194 this->m_replayer->start(&cond6);
1195 ASSERT_EQ(0, cond6.wait());
1196 this->wait_for_replay_complete();
1197
1198 this->stop();
1199 }
1200
1201 TEST_F(TestImageReplayerJournal, UpdateFeatures)
1202 {
1203 // TODO add support to snapshot-based mirroring
1204 const uint64_t FEATURES_TO_UPDATE =
1205 RBD_FEATURE_OBJECT_MAP | RBD_FEATURE_FAST_DIFF;
1206
1207 uint64_t features;
1208 librbd::ImageCtx *ictx;
1209
1210 // Make sure the features we will update are disabled initially
1211
1212 this->open_remote_image(&ictx);
1213 ASSERT_EQ(0, librbd::get_features(ictx, &features));
1214 features &= FEATURES_TO_UPDATE;
1215 if (features) {
1216 ASSERT_EQ(0, ictx->operations->update_features(FEATURES_TO_UPDATE,
1217 false));
1218 }
1219 ASSERT_EQ(0, librbd::get_features(ictx, &features));
1220 ASSERT_EQ(0U, features & FEATURES_TO_UPDATE);
1221 this->close_image(ictx);
1222
1223 this->bootstrap();
1224
1225 this->open_remote_image(&ictx);
1226 ASSERT_EQ(0, librbd::get_features(ictx, &features));
1227 ASSERT_EQ(0U, features & FEATURES_TO_UPDATE);
1228 this->close_image(ictx);
1229
1230 this->open_local_image(&ictx);
1231 ASSERT_EQ(0, librbd::get_features(ictx, &features));
1232 ASSERT_EQ(0U, features & FEATURES_TO_UPDATE);
1233 this->close_image(ictx);
1234
1235 // Start replay and update features
1236
1237 this->start();
1238
1239 this->open_remote_image(&ictx);
1240 ASSERT_EQ(0, ictx->operations->update_features(FEATURES_TO_UPDATE,
1241 true));
1242 ASSERT_EQ(0, librbd::get_features(ictx, &features));
1243 ASSERT_EQ(FEATURES_TO_UPDATE, features & FEATURES_TO_UPDATE);
1244 this->close_image(ictx);
1245
1246 this->wait_for_replay_complete();
1247
1248 this->open_local_image(&ictx);
1249 ASSERT_EQ(0, librbd::get_features(ictx, &features));
1250 ASSERT_EQ(FEATURES_TO_UPDATE, features & FEATURES_TO_UPDATE);
1251 this->close_image(ictx);
1252
1253 this->open_remote_image(&ictx);
1254 ASSERT_EQ(0, ictx->operations->update_features(FEATURES_TO_UPDATE,
1255 false));
1256 ASSERT_EQ(0, librbd::get_features(ictx, &features));
1257 ASSERT_EQ(0U, features & FEATURES_TO_UPDATE);
1258 this->close_image(ictx);
1259
1260 this->wait_for_replay_complete();
1261
1262 this->open_local_image(&ictx);
1263 ASSERT_EQ(0, librbd::get_features(ictx, &features));
1264 ASSERT_EQ(0U, features & FEATURES_TO_UPDATE);
1265 this->close_image(ictx);
1266
1267 // Test update_features error does not stop replication
1268
1269 this->open_remote_image(&ictx);
1270 ASSERT_EQ(0, librbd::get_features(ictx, &features));
1271 ASSERT_NE(0U, features & RBD_FEATURE_EXCLUSIVE_LOCK);
1272 ASSERT_EQ(-EINVAL, ictx->operations->update_features(RBD_FEATURE_EXCLUSIVE_LOCK,
1273 false));
1274 this->generate_test_data();
1275 for (int i = 0; i < TEST_IO_COUNT; ++i) {
1276 this->write_test_data(ictx, this->m_test_data, TEST_IO_SIZE * i,
1277 TEST_IO_SIZE);
1278 }
1279 this->flush(ictx);
1280 this->close_image(ictx);
1281
1282 this->wait_for_replay_complete();
1283
1284 this->open_local_image(&ictx);
1285 for (int i = 0; i < TEST_IO_COUNT; ++i) {
1286 this->read_test_data(ictx, this->m_test_data, TEST_IO_SIZE * i,
1287 TEST_IO_SIZE);
1288 }
1289 this->close_image(ictx);
1290
1291 this->stop();
1292 }
1293
1294 TEST_F(TestImageReplayerJournal, MetadataSetRemove)
1295 {
1296 // TODO add support to snapshot-based mirroring
1297 const std::string KEY = "test_key";
1298 const std::string VALUE = "test_value";
1299
1300 librbd::ImageCtx *ictx;
1301 std::string value;
1302
1303 this->bootstrap();
1304
1305 this->start();
1306
1307 // Test metadata_set replication
1308
1309 this->open_remote_image(&ictx);
1310 ASSERT_EQ(0, ictx->operations->metadata_set(KEY, VALUE));
1311 value.clear();
1312 ASSERT_EQ(0, librbd::metadata_get(ictx, KEY, &value));
1313 ASSERT_EQ(VALUE, value);
1314 this->close_image(ictx);
1315
1316 this->wait_for_replay_complete();
1317
1318 this->open_local_image(&ictx);
1319 value.clear();
1320 ASSERT_EQ(0, librbd::metadata_get(ictx, KEY, &value));
1321 ASSERT_EQ(VALUE, value);
1322 this->close_image(ictx);
1323
1324 // Test metadata_remove replication
1325
1326 this->open_remote_image(&ictx);
1327 ASSERT_EQ(0, ictx->operations->metadata_remove(KEY));
1328 ASSERT_EQ(-ENOENT, librbd::metadata_get(ictx, KEY, &value));
1329 this->close_image(ictx);
1330
1331 this->wait_for_replay_complete();
1332
1333 this->open_local_image(&ictx);
1334 ASSERT_EQ(-ENOENT, librbd::metadata_get(ictx, KEY, &value));
1335 this->close_image(ictx);
1336
1337 this->stop();
1338 }
1339
1340 TEST_F(TestImageReplayerJournal, MirroringDelay)
1341 {
1342 // TODO add support to snapshot-based mirroring
1343 const double DELAY = 10; // set less than wait_for_replay_complete timeout
1344
1345 librbd::ImageCtx *ictx;
1346 utime_t start_time;
1347 double delay;
1348
1349 this->bootstrap();
1350
1351 ASSERT_EQ(0, this->m_local_cluster->conf_set("rbd_mirroring_replay_delay",
1352 stringify(DELAY).c_str()));
1353 this->open_local_image(&ictx);
1354 ASSERT_EQ(DELAY, ictx->mirroring_replay_delay);
1355 this->close_image(ictx);
1356
1357 this->start();
1358
1359 // Test delay
1360
1361 this->generate_test_data();
1362 this->open_remote_image(&ictx);
1363 start_time = ceph_clock_now();
1364 for (int i = 0; i < TEST_IO_COUNT; ++i) {
1365 this->write_test_data(ictx, this->m_test_data, TEST_IO_SIZE * i,
1366 TEST_IO_SIZE);
1367 }
1368 this->flush(ictx);
1369 this->close_image(ictx);
1370
1371 this->wait_for_replay_complete();
1372 delay = ceph_clock_now() - start_time;
1373 ASSERT_GE(delay, DELAY);
1374
1375 // Test stop when delaying replay
1376
1377 this->open_remote_image(&ictx);
1378 start_time = ceph_clock_now();
1379 for (int i = 0; i < TEST_IO_COUNT; ++i) {
1380 this->write_test_data(ictx, this->m_test_data, TEST_IO_SIZE * i,
1381 TEST_IO_SIZE);
1382 }
1383 this->close_image(ictx);
1384
1385 sleep(DELAY / 2);
1386 this->stop();
1387 this->start();
1388
1389 this->wait_for_replay_complete();
1390 delay = ceph_clock_now() - start_time;
1391 ASSERT_GE(delay, DELAY);
1392
1393 this->stop();
1394 }
1395
1396 TYPED_TEST(TestImageReplayer, ImageRename) {
1397 this->create_replayer();
1398 this->start();
1399
1400 librbd::ImageCtx* remote_image_ctx = nullptr;
1401 this->open_remote_image(&remote_image_ctx);
1402 auto image_name = this->get_temp_image_name();
1403 ASSERT_EQ(0, remote_image_ctx->operations->rename(image_name.c_str()));
1404 this->flush(remote_image_ctx);
1405
1406 this->wait_for_replay_complete();
1407
1408 librbd::ImageCtx* local_image_ctx = nullptr;
1409 this->open_image(this->m_local_ioctx, image_name, true, &local_image_ctx);
1410 ASSERT_EQ(image_name, local_image_ctx->name);
1411
1412 this->close_image(local_image_ctx);
1413 this->close_image(remote_image_ctx);
1414 this->stop();
1415 }
1416
1417 TYPED_TEST(TestImageReplayer, UpdateFeatures) {
1418 const uint64_t FEATURES_TO_UPDATE =
1419 RBD_FEATURE_OBJECT_MAP | RBD_FEATURE_FAST_DIFF | RBD_FEATURE_DEEP_FLATTEN;
1420 REQUIRE((this->FEATURES & FEATURES_TO_UPDATE) == FEATURES_TO_UPDATE);
1421
1422 librbd::ImageCtx* remote_image_ctx = nullptr;
1423 this->open_remote_image(&remote_image_ctx);
1424
1425 ASSERT_EQ(0, remote_image_ctx->operations->update_features(
1426 (RBD_FEATURE_OBJECT_MAP | RBD_FEATURE_FAST_DIFF), false));
1427 this->flush(remote_image_ctx);
1428
1429 this->create_replayer();
1430 this->start();
1431 this->wait_for_replay_complete();
1432
1433 librbd::ImageCtx* local_image_ctx = nullptr;
1434 this->open_local_image(&local_image_ctx);
1435 ASSERT_EQ(0U, local_image_ctx->features & (
1436 RBD_FEATURE_OBJECT_MAP | RBD_FEATURE_FAST_DIFF));
1437
1438 // enable object-map/fast-diff
1439 ASSERT_EQ(0, remote_image_ctx->operations->update_features(
1440 (RBD_FEATURE_OBJECT_MAP | RBD_FEATURE_FAST_DIFF), true));
1441 this->flush(remote_image_ctx);
1442 this->wait_for_replay_complete();
1443
1444 ASSERT_EQ(0, local_image_ctx->state->refresh());
1445 ASSERT_EQ(RBD_FEATURE_OBJECT_MAP | RBD_FEATURE_FAST_DIFF,
1446 local_image_ctx->features & (
1447 RBD_FEATURE_OBJECT_MAP | RBD_FEATURE_FAST_DIFF));
1448
1449 // disable deep-flatten
1450 ASSERT_EQ(0, remote_image_ctx->operations->update_features(
1451 RBD_FEATURE_DEEP_FLATTEN, false));
1452 this->flush(remote_image_ctx);
1453 this->wait_for_replay_complete();
1454
1455 ASSERT_EQ(0, local_image_ctx->state->refresh());
1456 ASSERT_EQ(0, local_image_ctx->features & RBD_FEATURE_DEEP_FLATTEN);
1457
1458 this->close_image(local_image_ctx);
1459 this->close_image(remote_image_ctx);
1460 this->stop();
1461 }
1462
1463 TYPED_TEST(TestImageReplayer, SnapshotUnprotect) {
1464 librbd::ImageCtx* remote_image_ctx = nullptr;
1465 this->open_remote_image(&remote_image_ctx);
1466
1467 // create a protected snapshot
1468 ASSERT_EQ(0, remote_image_ctx->operations->snap_create(
1469 cls::rbd::UserSnapshotNamespace{}, "snap1"));
1470 ASSERT_EQ(0, remote_image_ctx->operations->snap_protect(
1471 cls::rbd::UserSnapshotNamespace{}, "snap1"));
1472 this->flush(remote_image_ctx);
1473
1474 this->create_replayer();
1475 this->start();
1476 this->wait_for_replay_complete();
1477
1478 librbd::ImageCtx* local_image_ctx = nullptr;
1479 this->open_local_image(&local_image_ctx);
1480 auto local_snap_id_it = local_image_ctx->snap_ids.find({
1481 {cls::rbd::UserSnapshotNamespace{}}, "snap1"});
1482 ASSERT_NE(local_image_ctx->snap_ids.end(), local_snap_id_it);
1483 auto local_snap_id = local_snap_id_it->second;
1484 auto local_snap_info_it = local_image_ctx->snap_info.find(local_snap_id);
1485 ASSERT_NE(local_image_ctx->snap_info.end(), local_snap_info_it);
1486 ASSERT_EQ(RBD_PROTECTION_STATUS_PROTECTED,
1487 local_snap_info_it->second.protection_status);
1488
1489 // unprotect the snapshot
1490 ASSERT_EQ(0, remote_image_ctx->operations->snap_unprotect(
1491 cls::rbd::UserSnapshotNamespace{}, "snap1"));
1492 this->flush(remote_image_ctx);
1493 this->wait_for_replay_complete();
1494
1495 ASSERT_EQ(0, local_image_ctx->state->refresh());
1496 local_snap_info_it = local_image_ctx->snap_info.find(local_snap_id);
1497 ASSERT_NE(local_image_ctx->snap_info.end(), local_snap_info_it);
1498 ASSERT_EQ(RBD_PROTECTION_STATUS_UNPROTECTED,
1499 local_snap_info_it->second.protection_status);
1500
1501 this->close_image(local_image_ctx);
1502 this->close_image(remote_image_ctx);
1503 this->stop();
1504 }
1505
1506 TYPED_TEST(TestImageReplayer, SnapshotProtect) {
1507 librbd::ImageCtx* remote_image_ctx = nullptr;
1508 this->open_remote_image(&remote_image_ctx);
1509
1510 // create an unprotected snapshot
1511 ASSERT_EQ(0, remote_image_ctx->operations->snap_create(
1512 cls::rbd::UserSnapshotNamespace{}, "snap1"));
1513 this->flush(remote_image_ctx);
1514
1515 this->create_replayer();
1516 this->start();
1517 this->wait_for_replay_complete();
1518
1519 librbd::ImageCtx* local_image_ctx = nullptr;
1520 this->open_local_image(&local_image_ctx);
1521 auto local_snap_id_it = local_image_ctx->snap_ids.find({
1522 {cls::rbd::UserSnapshotNamespace{}}, "snap1"});
1523 ASSERT_NE(local_image_ctx->snap_ids.end(), local_snap_id_it);
1524 auto local_snap_id = local_snap_id_it->second;
1525 auto local_snap_info_it = local_image_ctx->snap_info.find(local_snap_id);
1526 ASSERT_NE(local_image_ctx->snap_info.end(), local_snap_info_it);
1527 ASSERT_EQ(RBD_PROTECTION_STATUS_UNPROTECTED,
1528 local_snap_info_it->second.protection_status);
1529
1530 // protect the snapshot
1531 ASSERT_EQ(0, remote_image_ctx->operations->snap_protect(
1532 cls::rbd::UserSnapshotNamespace{}, "snap1"));
1533 this->flush(remote_image_ctx);
1534 this->wait_for_replay_complete();
1535
1536 ASSERT_EQ(0, local_image_ctx->state->refresh());
1537 local_snap_info_it = local_image_ctx->snap_info.find(local_snap_id);
1538 ASSERT_NE(local_image_ctx->snap_info.end(), local_snap_info_it);
1539 ASSERT_EQ(RBD_PROTECTION_STATUS_PROTECTED,
1540 local_snap_info_it->second.protection_status);
1541
1542 this->close_image(local_image_ctx);
1543 this->close_image(remote_image_ctx);
1544 this->stop();
1545 }
1546
1547 TYPED_TEST(TestImageReplayer, SnapshotRemove) {
1548 librbd::ImageCtx* remote_image_ctx = nullptr;
1549 this->open_remote_image(&remote_image_ctx);
1550
1551 // create a user snapshot
1552 ASSERT_EQ(0, remote_image_ctx->operations->snap_create(
1553 cls::rbd::UserSnapshotNamespace{}, "snap1"));
1554 this->flush(remote_image_ctx);
1555
1556 this->create_replayer();
1557 this->start();
1558 this->wait_for_replay_complete();
1559
1560 librbd::ImageCtx* local_image_ctx = nullptr;
1561 this->open_local_image(&local_image_ctx);
1562 auto local_snap_id_it = local_image_ctx->snap_ids.find({
1563 {cls::rbd::UserSnapshotNamespace{}}, "snap1"});
1564 ASSERT_NE(local_image_ctx->snap_ids.end(), local_snap_id_it);
1565
1566 // remove the snapshot
1567 ASSERT_EQ(0, remote_image_ctx->operations->snap_remove(
1568 cls::rbd::UserSnapshotNamespace{}, "snap1"));
1569 this->flush(remote_image_ctx);
1570 this->wait_for_replay_complete();
1571
1572 ASSERT_EQ(0, local_image_ctx->state->refresh());
1573 local_snap_id_it = local_image_ctx->snap_ids.find({
1574 {cls::rbd::UserSnapshotNamespace{}}, "snap1"});
1575 ASSERT_EQ(local_image_ctx->snap_ids.end(), local_snap_id_it);
1576
1577 this->close_image(local_image_ctx);
1578 this->close_image(remote_image_ctx);
1579 this->stop();
1580 }
1581
1582 TYPED_TEST(TestImageReplayer, SnapshotRename) {
1583 librbd::ImageCtx* remote_image_ctx = nullptr;
1584 this->open_remote_image(&remote_image_ctx);
1585
1586 // create a user snapshot
1587 ASSERT_EQ(0, remote_image_ctx->operations->snap_create(
1588 cls::rbd::UserSnapshotNamespace{}, "snap1"));
1589 this->flush(remote_image_ctx);
1590
1591 this->create_replayer();
1592 this->start();
1593 this->wait_for_replay_complete();
1594
1595 librbd::ImageCtx* local_image_ctx = nullptr;
1596 this->open_local_image(&local_image_ctx);
1597 auto local_snap_id_it = local_image_ctx->snap_ids.find({
1598 {cls::rbd::UserSnapshotNamespace{}}, "snap1"});
1599 ASSERT_NE(local_image_ctx->snap_ids.end(), local_snap_id_it);
1600 auto local_snap_id = local_snap_id_it->second;
1601 auto local_snap_info_it = local_image_ctx->snap_info.find(local_snap_id);
1602 ASSERT_NE(local_image_ctx->snap_info.end(), local_snap_info_it);
1603 ASSERT_EQ(RBD_PROTECTION_STATUS_UNPROTECTED,
1604 local_snap_info_it->second.protection_status);
1605
1606 // rename the snapshot
1607 ASSERT_EQ(0, remote_image_ctx->operations->snap_rename(
1608 "snap1", "snap1-renamed"));
1609 this->flush(remote_image_ctx);
1610 this->wait_for_replay_complete();
1611
1612 ASSERT_EQ(0, local_image_ctx->state->refresh());
1613 local_snap_info_it = local_image_ctx->snap_info.find(local_snap_id);
1614 ASSERT_NE(local_image_ctx->snap_info.end(), local_snap_info_it);
1615 ASSERT_EQ("snap1-renamed", local_snap_info_it->second.name);
1616
1617 this->close_image(local_image_ctx);
1618 this->close_image(remote_image_ctx);
1619 this->stop();
1620 }
1621
1622 TYPED_TEST(TestImageReplayer, SnapshotLimit) {
1623 librbd::ImageCtx* remote_image_ctx = nullptr;
1624 this->open_remote_image(&remote_image_ctx);
1625
1626 this->create_replayer();
1627 this->start();
1628 this->wait_for_replay_complete();
1629
1630 // update the snap limit
1631 ASSERT_EQ(0, librbd::api::Snapshot<>::set_limit(remote_image_ctx, 123U));
1632 this->flush(remote_image_ctx);
1633 this->wait_for_replay_complete();
1634
1635 librbd::ImageCtx* local_image_ctx = nullptr;
1636 this->open_local_image(&local_image_ctx);
1637 uint64_t local_snap_limit;
1638 ASSERT_EQ(0, librbd::api::Snapshot<>::get_limit(local_image_ctx,
1639 &local_snap_limit));
1640 ASSERT_EQ(123U, local_snap_limit);
1641
1642 // update the limit again
1643 ASSERT_EQ(0, librbd::api::Snapshot<>::set_limit(
1644 remote_image_ctx, std::numeric_limits<uint64_t>::max()));
1645 this->flush(remote_image_ctx);
1646 this->wait_for_replay_complete();
1647
1648 ASSERT_EQ(0, librbd::api::Snapshot<>::get_limit(local_image_ctx,
1649 &local_snap_limit));
1650 ASSERT_EQ(std::numeric_limits<uint64_t>::max(), local_snap_limit);
1651
1652 this->close_image(local_image_ctx);
1653 this->close_image(remote_image_ctx);
1654 this->stop();
1655 }
1656
1657 } // namespace mirror
1658 } // namespace rbd