]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/rbd_mirror/test_ImageSync.cc
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / test / rbd_mirror / test_ImageSync.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "test/rbd_mirror/test_fixture.h"
5 #include "include/stringify.h"
6 #include "include/rbd/librbd.hpp"
7 #include "journal/Journaler.h"
8 #include "journal/Settings.h"
9 #include "librbd/ExclusiveLock.h"
10 #include "librbd/ImageCtx.h"
11 #include "librbd/ImageState.h"
12 #include "librbd/internal.h"
13 #include "librbd/Operations.h"
14 #include "librbd/io/ImageRequestWQ.h"
15 #include "librbd/io/ReadResult.h"
16 #include "librbd/journal/Types.h"
17 #include "tools/rbd_mirror/ImageSync.h"
18 #include "tools/rbd_mirror/Threads.h"
19
20 void register_test_image_sync() {
21 }
22
23 namespace rbd {
24 namespace mirror {
25
26 namespace {
27
28 void scribble(librbd::ImageCtx *image_ctx, int num_ops, size_t max_size)
29 {
30 max_size = MIN(image_ctx->size, max_size);
31 for (int i=0; i<num_ops; i++) {
32 uint64_t off = rand() % (image_ctx->size - max_size + 1);
33 uint64_t len = 1 + rand() % max_size;
34
35 if (rand() % 4 == 0) {
36 ASSERT_EQ((int)len, image_ctx->io_work_queue->discard(off, len, image_ctx->skip_partial_discard));
37 } else {
38 bufferlist bl;
39 bl.append(std::string(len, '1'));
40 ASSERT_EQ((int)len, image_ctx->io_work_queue->write(off, len,
41 std::move(bl), 0));
42 }
43 }
44
45 RWLock::RLocker owner_locker(image_ctx->owner_lock);
46 ASSERT_EQ(0, image_ctx->flush());
47 }
48
49 } // anonymous namespace
50 class TestImageSync : public TestFixture {
51 public:
52
53 void SetUp() override {
54 TestFixture::SetUp();
55 create_and_open(m_local_io_ctx, &m_local_image_ctx);
56 create_and_open(m_remote_io_ctx, &m_remote_image_ctx);
57
58 m_remote_journaler = new ::journal::Journaler(
59 m_threads->work_queue, m_threads->timer, &m_threads->timer_lock,
60 m_remote_io_ctx, m_remote_image_ctx->id, "mirror-uuid", {});
61
62 m_client_meta = {"image-id"};
63
64 librbd::journal::ClientData client_data(m_client_meta);
65 bufferlist client_data_bl;
66 ::encode(client_data, client_data_bl);
67
68 ASSERT_EQ(0, m_remote_journaler->register_client(client_data_bl));
69 }
70
71 void TearDown() override {
72 TestFixture::TearDown();
73 delete m_remote_journaler;
74 }
75
76 void create_and_open(librados::IoCtx &io_ctx, librbd::ImageCtx **image_ctx) {
77 librbd::RBD rbd;
78 ASSERT_EQ(0, create_image(rbd, io_ctx, m_image_name, m_image_size));
79 ASSERT_EQ(0, open_image(io_ctx, m_image_name, image_ctx));
80
81 C_SaferCond ctx;
82 {
83 RWLock::RLocker owner_locker((*image_ctx)->owner_lock);
84 (*image_ctx)->exclusive_lock->try_acquire_lock(&ctx);
85 }
86 ASSERT_EQ(0, ctx.wait());
87 ASSERT_TRUE((*image_ctx)->exclusive_lock->is_lock_owner());
88 }
89
90 ImageSync<> *create_request(Context *ctx) {
91 return new ImageSync<>(m_local_image_ctx, m_remote_image_ctx,
92 m_threads->timer, &m_threads->timer_lock,
93 "mirror-uuid", m_remote_journaler, &m_client_meta,
94 m_threads->work_queue, ctx);
95 }
96
97 librbd::ImageCtx *m_remote_image_ctx;
98 librbd::ImageCtx *m_local_image_ctx;
99 ::journal::Journaler *m_remote_journaler;
100 librbd::journal::MirrorPeerClientMeta m_client_meta;
101 };
102
103 TEST_F(TestImageSync, Empty) {
104 C_SaferCond ctx;
105 ImageSync<> *request = create_request(&ctx);
106 request->send();
107 ASSERT_EQ(0, ctx.wait());
108
109 ASSERT_EQ(0U, m_client_meta.sync_points.size());
110 ASSERT_EQ(0, m_remote_image_ctx->state->refresh());
111 ASSERT_EQ(0U, m_remote_image_ctx->snap_ids.size());
112 ASSERT_EQ(0, m_local_image_ctx->state->refresh());
113 ASSERT_EQ(1U, m_local_image_ctx->snap_ids.size()); // deleted on journal replay
114 }
115
116 TEST_F(TestImageSync, Simple) {
117 scribble(m_remote_image_ctx, 10, 102400);
118
119 C_SaferCond ctx;
120 ImageSync<> *request = create_request(&ctx);
121 request->send();
122 ASSERT_EQ(0, ctx.wait());
123
124 int64_t object_size = std::min<int64_t>(
125 m_remote_image_ctx->size, 1 << m_remote_image_ctx->order);
126 bufferlist read_remote_bl;
127 read_remote_bl.append(std::string(object_size, '1'));
128 bufferlist read_local_bl;
129 read_local_bl.append(std::string(object_size, '1'));
130
131 for (uint64_t offset = 0; offset < m_remote_image_ctx->size;
132 offset += object_size) {
133 ASSERT_LE(0, m_remote_image_ctx->io_work_queue->read(
134 offset, object_size,
135 librbd::io::ReadResult{&read_remote_bl}, 0));
136 ASSERT_LE(0, m_local_image_ctx->io_work_queue->read(
137 offset, object_size,
138 librbd::io::ReadResult{&read_local_bl}, 0));
139 ASSERT_TRUE(read_remote_bl.contents_equal(read_local_bl));
140 }
141 }
142
143 TEST_F(TestImageSync, Resize) {
144 int64_t object_size = std::min<int64_t>(
145 m_remote_image_ctx->size, 1 << m_remote_image_ctx->order);
146
147 uint64_t off = 0;
148 uint64_t len = object_size / 10;
149
150 bufferlist bl;
151 bl.append(std::string(len, '1'));
152 ASSERT_EQ((int)len, m_remote_image_ctx->io_work_queue->write(off, len,
153 std::move(bl),
154 0));
155 {
156 RWLock::RLocker owner_locker(m_remote_image_ctx->owner_lock);
157 ASSERT_EQ(0, m_remote_image_ctx->flush());
158 }
159
160 ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap", nullptr));
161
162 uint64_t size = object_size - 1;
163 librbd::NoOpProgressContext no_op_progress_ctx;
164 ASSERT_EQ(0, m_remote_image_ctx->operations->resize(size, true,
165 no_op_progress_ctx));
166
167 C_SaferCond ctx;
168 ImageSync<> *request = create_request(&ctx);
169 request->send();
170 ASSERT_EQ(0, ctx.wait());
171
172 bufferlist read_remote_bl;
173 read_remote_bl.append(std::string(len, '\0'));
174 bufferlist read_local_bl;
175 read_local_bl.append(std::string(len, '\0'));
176
177 ASSERT_LE(0, m_remote_image_ctx->io_work_queue->read(
178 off, len, librbd::io::ReadResult{&read_remote_bl}, 0));
179 ASSERT_LE(0, m_local_image_ctx->io_work_queue->read(
180 off, len, librbd::io::ReadResult{&read_local_bl}, 0));
181
182 ASSERT_TRUE(read_remote_bl.contents_equal(read_local_bl));
183 }
184
185 TEST_F(TestImageSync, Discard) {
186 int64_t object_size = std::min<int64_t>(
187 m_remote_image_ctx->size, 1 << m_remote_image_ctx->order);
188
189 uint64_t off = 0;
190 uint64_t len = object_size / 10;
191
192 bufferlist bl;
193 bl.append(std::string(len, '1'));
194 ASSERT_EQ((int)len, m_remote_image_ctx->io_work_queue->write(off, len,
195 std::move(bl),
196 0));
197 {
198 RWLock::RLocker owner_locker(m_remote_image_ctx->owner_lock);
199 ASSERT_EQ(0, m_remote_image_ctx->flush());
200 }
201
202 ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap", nullptr));
203
204 ASSERT_EQ((int)len - 2, m_remote_image_ctx->io_work_queue->discard(off + 1,
205 len - 2, m_remote_image_ctx->skip_partial_discard));
206 {
207 RWLock::RLocker owner_locker(m_remote_image_ctx->owner_lock);
208 ASSERT_EQ(0, m_remote_image_ctx->flush());
209 }
210
211 C_SaferCond ctx;
212 ImageSync<> *request = create_request(&ctx);
213 request->send();
214 ASSERT_EQ(0, ctx.wait());
215
216 bufferlist read_remote_bl;
217 read_remote_bl.append(std::string(object_size, '\0'));
218 bufferlist read_local_bl;
219 read_local_bl.append(std::string(object_size, '\0'));
220
221 ASSERT_LE(0, m_remote_image_ctx->io_work_queue->read(
222 off, len, librbd::io::ReadResult{&read_remote_bl}, 0));
223 ASSERT_LE(0, m_local_image_ctx->io_work_queue->read(
224 off, len, librbd::io::ReadResult{&read_local_bl}, 0));
225
226 ASSERT_TRUE(read_remote_bl.contents_equal(read_local_bl));
227 }
228
229 TEST_F(TestImageSync, SnapshotStress) {
230 std::list<std::string> snap_names;
231
232 const int num_snaps = 4;
233 for (int idx = 0; idx <= num_snaps; ++idx) {
234 scribble(m_remote_image_ctx, 10, 102400);
235
236 librbd::NoOpProgressContext no_op_progress_ctx;
237 uint64_t size = 1 + rand() % m_image_size;
238 ASSERT_EQ(0, m_remote_image_ctx->operations->resize(size, true,
239 no_op_progress_ctx));
240 ASSERT_EQ(0, m_remote_image_ctx->state->refresh());
241
242 if (idx < num_snaps) {
243 snap_names.push_back("snap" + stringify(idx + 1));
244 ASSERT_EQ(0, create_snap(m_remote_image_ctx, snap_names.back().c_str(),
245 nullptr));
246 } else {
247 snap_names.push_back("");
248 }
249 }
250
251 C_SaferCond ctx;
252 ImageSync<> *request = create_request(&ctx);
253 request->send();
254 ASSERT_EQ(0, ctx.wait());
255
256 int64_t object_size = std::min<int64_t>(
257 m_remote_image_ctx->size, 1 << m_remote_image_ctx->order);
258 bufferlist read_remote_bl;
259 read_remote_bl.append(std::string(object_size, '1'));
260 bufferlist read_local_bl;
261 read_local_bl.append(std::string(object_size, '1'));
262
263 for (auto &snap_name : snap_names) {
264 uint64_t remote_size;
265 {
266 C_SaferCond ctx;
267 m_remote_image_ctx->state->snap_set(cls::rbd::UserSnapshotNamespace(),
268 snap_name,
269 &ctx);
270 ASSERT_EQ(0, ctx.wait());
271
272 RWLock::RLocker remote_snap_locker(m_remote_image_ctx->snap_lock);
273 remote_size = m_remote_image_ctx->get_image_size(
274 m_remote_image_ctx->snap_id);
275 }
276
277 uint64_t local_size;
278 {
279 C_SaferCond ctx;
280 m_local_image_ctx->state->snap_set(cls::rbd::UserSnapshotNamespace(),
281 snap_name,
282 &ctx);
283 ASSERT_EQ(0, ctx.wait());
284
285 RWLock::RLocker snap_locker(m_local_image_ctx->snap_lock);
286 local_size = m_local_image_ctx->get_image_size(
287 m_local_image_ctx->snap_id);
288 ASSERT_FALSE(m_local_image_ctx->test_flags(RBD_FLAG_OBJECT_MAP_INVALID,
289 m_local_image_ctx->snap_lock));
290 }
291
292 ASSERT_EQ(remote_size, local_size);
293
294 for (uint64_t offset = 0; offset < remote_size; offset += object_size) {
295 ASSERT_LE(0, m_remote_image_ctx->io_work_queue->read(
296 offset, object_size,
297 librbd::io::ReadResult{&read_remote_bl}, 0));
298 ASSERT_LE(0, m_local_image_ctx->io_work_queue->read(
299 offset, object_size,
300 librbd::io::ReadResult{&read_local_bl}, 0));
301 ASSERT_TRUE(read_remote_bl.contents_equal(read_local_bl));
302 }
303 }
304 }
305
306 } // namespace mirror
307 } // namespace rbd