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