]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2016 SUSE LINUX GmbH | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License version 2.1, as published by the Free Software | |
11 | * Foundation. See file COPYING. | |
12 | * | |
13 | */ | |
14 | #include "test/librbd/test_fixture.h" | |
15 | #include "test/librbd/test_support.h" | |
16 | #include "librbd/ExclusiveLock.h" | |
17 | #include "librbd/ImageState.h" | |
18 | #include "librbd/ImageWatcher.h" | |
19 | #include "librbd/internal.h" | |
20 | #include "librbd/ObjectMap.h" | |
21 | #include "librbd/Operations.h" | |
22 | #include "librbd/io/AioCompletion.h" | |
23 | #include "librbd/io/ImageRequest.h" | |
24 | #include "librbd/io/ImageRequestWQ.h" | |
25 | #include "librbd/journal/Types.h" | |
26 | #include "journal/Journaler.h" | |
27 | #include "journal/Settings.h" | |
28 | #include <boost/scope_exit.hpp> | |
29 | #include <boost/assign/list_of.hpp> | |
30 | #include <utility> | |
31 | #include <vector> | |
32 | ||
33 | void register_test_mirroring() { | |
34 | } | |
35 | ||
36 | class TestMirroring : public TestFixture { | |
37 | public: | |
38 | ||
39 | TestMirroring() {} | |
40 | ||
41 | ||
42 | void TearDown() override { | |
43 | unlock_image(); | |
44 | ||
45 | TestFixture::TearDown(); | |
46 | } | |
47 | ||
48 | void SetUp() override { | |
49 | ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), m_ioctx)); | |
50 | } | |
51 | ||
52 | std::string image_name = "mirrorimg1"; | |
53 | ||
54 | void check_mirror_image_enable(rbd_mirror_mode_t mirror_mode, | |
55 | uint64_t features, | |
56 | int expected_r, | |
57 | rbd_mirror_image_state_t mirror_state) { | |
58 | ||
59 | ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_DISABLED)); | |
60 | ||
61 | int order = 20; | |
62 | ASSERT_EQ(0, m_rbd.create2(m_ioctx, image_name.c_str(), 4096, features, &order)); | |
63 | librbd::Image image; | |
64 | ASSERT_EQ(0, m_rbd.open(m_ioctx, image, image_name.c_str())); | |
65 | ||
66 | ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, mirror_mode)); | |
67 | ||
68 | ASSERT_EQ(expected_r, image.mirror_image_enable()); | |
69 | ||
70 | librbd::mirror_image_info_t mirror_image; | |
71 | ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image, sizeof(mirror_image))); | |
72 | ASSERT_EQ(mirror_state, mirror_image.state); | |
73 | ||
74 | librbd::mirror_image_status_t status; | |
75 | ASSERT_EQ(0, image.mirror_image_get_status(&status, sizeof(status))); | |
76 | ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, status.state); | |
77 | ||
78 | ASSERT_EQ(0, image.close()); | |
79 | ASSERT_EQ(0, m_rbd.remove(m_ioctx, image_name.c_str())); | |
80 | ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_DISABLED)); | |
81 | } | |
82 | ||
83 | void check_mirror_image_disable(rbd_mirror_mode_t mirror_mode, | |
84 | uint64_t features, | |
85 | int expected_r, | |
86 | rbd_mirror_image_state_t mirror_state) { | |
87 | ||
88 | ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_POOL)); | |
89 | ||
90 | int order = 20; | |
91 | ASSERT_EQ(0, m_rbd.create2(m_ioctx, image_name.c_str(), 4096, features, &order)); | |
92 | librbd::Image image; | |
93 | ASSERT_EQ(0, m_rbd.open(m_ioctx, image, image_name.c_str())); | |
94 | ||
95 | ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, mirror_mode)); | |
96 | ||
97 | ASSERT_EQ(expected_r, image.mirror_image_disable(false)); | |
98 | ||
99 | librbd::mirror_image_info_t mirror_image; | |
100 | ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image, sizeof(mirror_image))); | |
101 | ASSERT_EQ(mirror_state, mirror_image.state); | |
102 | ||
103 | librbd::mirror_image_status_t status; | |
104 | ASSERT_EQ(0, image.mirror_image_get_status(&status, sizeof(status))); | |
105 | ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, status.state); | |
106 | ||
107 | ASSERT_EQ(0, image.close()); | |
108 | ASSERT_EQ(0, m_rbd.remove(m_ioctx, image_name.c_str())); | |
109 | ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_DISABLED)); | |
110 | } | |
111 | ||
112 | void check_mirroring_status(size_t *images_count) { | |
113 | std::map<std::string, librbd::mirror_image_status_t> images; | |
114 | ASSERT_EQ(0, m_rbd.mirror_image_status_list(m_ioctx, "", 4096, &images)); | |
115 | ||
116 | std::map<librbd::mirror_image_status_state_t, int> states; | |
117 | ASSERT_EQ(0, m_rbd.mirror_image_status_summary(m_ioctx, &states)); | |
118 | size_t states_count = 0; | |
119 | for (auto &s : states) { | |
120 | states_count += s.second; | |
121 | } | |
122 | ASSERT_EQ(images.size(), states_count); | |
123 | ||
124 | *images_count = images.size(); | |
125 | } | |
126 | ||
127 | void check_mirroring_on_create(uint64_t features, | |
128 | rbd_mirror_mode_t mirror_mode, | |
129 | rbd_mirror_image_state_t mirror_state) { | |
130 | ||
131 | ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, mirror_mode)); | |
132 | ||
133 | size_t mirror_images_count = 0; | |
134 | check_mirroring_status(&mirror_images_count); | |
135 | ||
136 | int order = 20; | |
137 | ASSERT_EQ(0, m_rbd.create2(m_ioctx, image_name.c_str(), 4096, features, &order)); | |
138 | librbd::Image image; | |
139 | ASSERT_EQ(0, m_rbd.open(m_ioctx, image, image_name.c_str())); | |
140 | ||
141 | librbd::mirror_image_info_t mirror_image; | |
142 | ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image, sizeof(mirror_image))); | |
143 | ASSERT_EQ(mirror_state, mirror_image.state); | |
144 | ||
145 | librbd::mirror_image_status_t status; | |
146 | ASSERT_EQ(0, image.mirror_image_get_status(&status, sizeof(status))); | |
147 | ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, status.state); | |
148 | ||
149 | size_t mirror_images_new_count = 0; | |
150 | check_mirroring_status(&mirror_images_new_count); | |
151 | if (mirror_mode == RBD_MIRROR_MODE_POOL && | |
152 | mirror_state == RBD_MIRROR_IMAGE_ENABLED) { | |
153 | ASSERT_EQ(mirror_images_new_count, mirror_images_count + 1); | |
154 | } else { | |
155 | ASSERT_EQ(mirror_images_new_count, mirror_images_count); | |
156 | } | |
157 | ||
158 | ASSERT_EQ(0, image.close()); | |
159 | ASSERT_EQ(0, m_rbd.remove(m_ioctx, image_name.c_str())); | |
160 | ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_DISABLED)); | |
161 | ||
162 | check_mirroring_status(&mirror_images_new_count); | |
163 | ASSERT_EQ(mirror_images_new_count, mirror_images_count); | |
164 | } | |
165 | ||
166 | void check_mirroring_on_update_features(uint64_t init_features, | |
167 | bool enable, bool enable_mirroring, | |
168 | uint64_t features, int expected_r, | |
169 | rbd_mirror_mode_t mirror_mode, | |
170 | rbd_mirror_image_state_t mirror_state) { | |
171 | ||
172 | ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, mirror_mode)); | |
173 | ||
174 | int order = 20; | |
175 | ASSERT_EQ(0, m_rbd.create2(m_ioctx, image_name.c_str(), 4096, init_features, &order)); | |
176 | librbd::Image image; | |
177 | ASSERT_EQ(0, m_rbd.open(m_ioctx, image, image_name.c_str())); | |
178 | ||
179 | if (enable_mirroring) { | |
180 | ASSERT_EQ(0, image.mirror_image_enable()); | |
181 | } | |
182 | ||
183 | ASSERT_EQ(expected_r, image.update_features(features, enable)); | |
184 | ||
185 | librbd::mirror_image_info_t mirror_image; | |
186 | ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image, sizeof(mirror_image))); | |
187 | ASSERT_EQ(mirror_state, mirror_image.state); | |
188 | ||
189 | librbd::mirror_image_status_t status; | |
190 | ASSERT_EQ(0, image.mirror_image_get_status(&status, sizeof(status))); | |
191 | ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, status.state); | |
192 | ||
193 | ASSERT_EQ(0, image.close()); | |
194 | ASSERT_EQ(0, m_rbd.remove(m_ioctx, image_name.c_str())); | |
195 | ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_DISABLED)); | |
196 | } | |
197 | ||
198 | void setup_images_with_mirror_mode(rbd_mirror_mode_t mirror_mode, | |
199 | std::vector<uint64_t>& features_vec) { | |
200 | ||
201 | ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, mirror_mode)); | |
202 | ||
203 | int id = 1; | |
204 | int order = 20; | |
205 | for (const auto& features : features_vec) { | |
206 | std::stringstream img_name("img_"); | |
207 | img_name << id++; | |
208 | std::string img_name_str = img_name.str(); | |
209 | ASSERT_EQ(0, m_rbd.create2(m_ioctx, img_name_str.c_str(), 2048, features, &order)); | |
210 | } | |
211 | } | |
212 | ||
213 | void check_mirroring_on_mirror_mode_set(rbd_mirror_mode_t mirror_mode, | |
214 | std::vector<rbd_mirror_image_state_t>& states_vec) { | |
215 | ||
216 | ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, mirror_mode)); | |
217 | ||
218 | std::vector< std::tuple<std::string, rbd_mirror_image_state_t> > images; | |
219 | int id = 1; | |
220 | for (const auto& mirror_state : states_vec) { | |
221 | std::stringstream img_name("img_"); | |
222 | img_name << id++; | |
223 | std::string img_name_str = img_name.str(); | |
224 | librbd::Image image; | |
225 | ASSERT_EQ(0, m_rbd.open(m_ioctx, image, img_name_str.c_str())); | |
226 | images.push_back(std::make_tuple(img_name_str, mirror_state)); | |
227 | ||
228 | librbd::mirror_image_info_t mirror_image; | |
229 | ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image, sizeof(mirror_image))); | |
230 | ASSERT_EQ(mirror_state, mirror_image.state); | |
231 | ||
232 | librbd::mirror_image_status_t status; | |
233 | ASSERT_EQ(0, image.mirror_image_get_status(&status, sizeof(status))); | |
234 | ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, status.state); | |
235 | ||
236 | ASSERT_EQ(0, image.close()); | |
237 | ASSERT_EQ(0, m_rbd.remove(m_ioctx, img_name_str.c_str())); | |
238 | } | |
239 | } | |
240 | ||
241 | void check_remove_image(rbd_mirror_mode_t mirror_mode, uint64_t features, | |
242 | bool enable_mirroring, bool demote = false) { | |
243 | ||
244 | ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, mirror_mode)); | |
245 | ||
246 | int order = 20; | |
247 | ASSERT_EQ(0, m_rbd.create2(m_ioctx, image_name.c_str(), 4096, features, | |
248 | &order)); | |
249 | librbd::Image image; | |
250 | ASSERT_EQ(0, m_rbd.open(m_ioctx, image, image_name.c_str())); | |
251 | ||
252 | if (enable_mirroring) { | |
253 | ASSERT_EQ(0, image.mirror_image_enable()); | |
254 | } | |
255 | ||
256 | if (demote) { | |
257 | ASSERT_EQ(0, image.mirror_image_demote()); | |
258 | ASSERT_EQ(0, image.mirror_image_disable(true)); | |
259 | } | |
260 | ||
261 | image.close(); | |
262 | ASSERT_EQ(0, m_rbd.remove(m_ioctx, image_name.c_str())); | |
263 | ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_DISABLED)); | |
264 | } | |
265 | ||
266 | void setup_mirror_peer(librados::IoCtx &io_ctx, librbd::Image &image) { | |
267 | ASSERT_EQ(0, image.snap_create("sync-point-snap")); | |
268 | ||
269 | std::string image_id; | |
270 | ASSERT_EQ(0, get_image_id(image, &image_id)); | |
271 | ||
272 | librbd::journal::MirrorPeerClientMeta peer_client_meta( | |
273 | "remote-image-id", {{{}, "sync-point-snap", boost::none}}, {}); | |
274 | librbd::journal::ClientData client_data(peer_client_meta); | |
275 | ||
276 | journal::Journaler journaler(io_ctx, image_id, "peer-client", {}); | |
277 | C_SaferCond init_ctx; | |
278 | journaler.init(&init_ctx); | |
279 | ASSERT_EQ(-ENOENT, init_ctx.wait()); | |
280 | ||
281 | bufferlist client_data_bl; | |
282 | ::encode(client_data, client_data_bl); | |
283 | ASSERT_EQ(0, journaler.register_client(client_data_bl)); | |
284 | ||
285 | C_SaferCond shut_down_ctx; | |
286 | journaler.shut_down(&shut_down_ctx); | |
287 | ASSERT_EQ(0, shut_down_ctx.wait()); | |
288 | } | |
289 | ||
290 | }; | |
291 | ||
292 | TEST_F(TestMirroring, EnableImageMirror_In_MirrorModeImage) { | |
293 | uint64_t features = 0; | |
294 | features |= RBD_FEATURE_OBJECT_MAP; | |
295 | features |= RBD_FEATURE_EXCLUSIVE_LOCK; | |
296 | features |= RBD_FEATURE_JOURNALING; | |
297 | check_mirror_image_enable(RBD_MIRROR_MODE_IMAGE, features, 0, | |
298 | RBD_MIRROR_IMAGE_ENABLED); | |
299 | } | |
300 | ||
301 | TEST_F(TestMirroring, EnableImageMirror_In_MirrorModePool) { | |
302 | uint64_t features = 0; | |
303 | features |= RBD_FEATURE_OBJECT_MAP; | |
304 | features |= RBD_FEATURE_EXCLUSIVE_LOCK; | |
305 | features |= RBD_FEATURE_JOURNALING; | |
306 | check_mirror_image_enable(RBD_MIRROR_MODE_POOL, features, -EINVAL, | |
307 | RBD_MIRROR_IMAGE_ENABLED); | |
308 | } | |
309 | ||
310 | TEST_F(TestMirroring, EnableImageMirror_In_MirrorModeDisabled) { | |
311 | uint64_t features = 0; | |
312 | features |= RBD_FEATURE_OBJECT_MAP; | |
313 | features |= RBD_FEATURE_EXCLUSIVE_LOCK; | |
314 | features |= RBD_FEATURE_JOURNALING; | |
315 | check_mirror_image_enable(RBD_MIRROR_MODE_DISABLED, features, -EINVAL, | |
316 | RBD_MIRROR_IMAGE_DISABLED); | |
317 | } | |
318 | ||
319 | TEST_F(TestMirroring, DisableImageMirror_In_MirrorModeImage) { | |
320 | uint64_t features = 0; | |
321 | features |= RBD_FEATURE_OBJECT_MAP; | |
322 | features |= RBD_FEATURE_EXCLUSIVE_LOCK; | |
323 | features |= RBD_FEATURE_JOURNALING; | |
324 | check_mirror_image_disable(RBD_MIRROR_MODE_IMAGE, features, 0, | |
325 | RBD_MIRROR_IMAGE_DISABLED); | |
326 | } | |
327 | ||
328 | TEST_F(TestMirroring, DisableImageMirror_In_MirrorModePool) { | |
329 | uint64_t features = 0; | |
330 | features |= RBD_FEATURE_OBJECT_MAP; | |
331 | features |= RBD_FEATURE_EXCLUSIVE_LOCK; | |
332 | features |= RBD_FEATURE_JOURNALING; | |
333 | check_mirror_image_disable(RBD_MIRROR_MODE_POOL, features, -EINVAL, | |
334 | RBD_MIRROR_IMAGE_ENABLED); | |
335 | } | |
336 | ||
337 | TEST_F(TestMirroring, DisableImageMirror_In_MirrorModeDisabled) { | |
338 | uint64_t features = 0; | |
339 | features |= RBD_FEATURE_OBJECT_MAP; | |
340 | features |= RBD_FEATURE_EXCLUSIVE_LOCK; | |
341 | features |= RBD_FEATURE_JOURNALING; | |
342 | check_mirror_image_disable(RBD_MIRROR_MODE_DISABLED, features, -EINVAL, | |
343 | RBD_MIRROR_IMAGE_DISABLED); | |
344 | } | |
345 | ||
346 | TEST_F(TestMirroring, DisableImageMirrorWithPeer) { | |
347 | REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); | |
348 | ||
349 | ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_IMAGE)); | |
350 | ||
351 | uint64_t features = RBD_FEATURE_EXCLUSIVE_LOCK | RBD_FEATURE_JOURNALING; | |
352 | int order = 20; | |
353 | ASSERT_EQ(0, m_rbd.create2(m_ioctx, image_name.c_str(), 4096, features, | |
354 | &order)); | |
355 | ||
356 | librbd::Image image; | |
357 | ASSERT_EQ(0, m_rbd.open(m_ioctx, image, image_name.c_str())); | |
358 | ASSERT_EQ(0, image.mirror_image_enable()); | |
359 | ||
360 | setup_mirror_peer(m_ioctx, image); | |
361 | ||
362 | ASSERT_EQ(0, image.mirror_image_disable(false)); | |
363 | ||
364 | std::vector<librbd::snap_info_t> snaps; | |
365 | ASSERT_EQ(0, image.snap_list(snaps)); | |
366 | ASSERT_TRUE(snaps.empty()); | |
367 | ||
368 | librbd::mirror_image_info_t mirror_image; | |
369 | ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image, | |
370 | sizeof(mirror_image))); | |
371 | ASSERT_EQ(RBD_MIRROR_IMAGE_DISABLED, mirror_image.state); | |
372 | ||
373 | librbd::mirror_image_status_t status; | |
374 | ASSERT_EQ(0, image.mirror_image_get_status(&status, sizeof(status))); | |
375 | ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, status.state); | |
376 | ||
377 | ASSERT_EQ(0, image.close()); | |
378 | ASSERT_EQ(0, m_rbd.remove(m_ioctx, image_name.c_str())); | |
379 | ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_DISABLED)); | |
380 | } | |
381 | ||
382 | TEST_F(TestMirroring, DisableJournalingWithPeer) { | |
383 | REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); | |
384 | ||
385 | ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_POOL)); | |
386 | ||
387 | uint64_t features = RBD_FEATURE_EXCLUSIVE_LOCK | RBD_FEATURE_JOURNALING; | |
388 | int order = 20; | |
389 | ASSERT_EQ(0, m_rbd.create2(m_ioctx, image_name.c_str(), 4096, features, | |
390 | &order)); | |
391 | ||
392 | librbd::Image image; | |
393 | ASSERT_EQ(0, m_rbd.open(m_ioctx, image, image_name.c_str())); | |
394 | ||
395 | setup_mirror_peer(m_ioctx, image); | |
396 | ||
397 | ASSERT_EQ(0, image.update_features(RBD_FEATURE_JOURNALING, false)); | |
398 | ||
399 | std::vector<librbd::snap_info_t> snaps; | |
400 | ASSERT_EQ(0, image.snap_list(snaps)); | |
401 | ASSERT_TRUE(snaps.empty()); | |
402 | ||
403 | librbd::mirror_image_info_t mirror_image; | |
404 | ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image, | |
405 | sizeof(mirror_image))); | |
406 | ASSERT_EQ(RBD_MIRROR_IMAGE_DISABLED, mirror_image.state); | |
407 | ||
408 | librbd::mirror_image_status_t status; | |
409 | ASSERT_EQ(0, image.mirror_image_get_status(&status, sizeof(status))); | |
410 | ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, status.state); | |
411 | ||
412 | ASSERT_EQ(0, image.close()); | |
413 | ASSERT_EQ(0, m_rbd.remove(m_ioctx, image_name.c_str())); | |
414 | ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_DISABLED)); | |
415 | } | |
416 | ||
417 | TEST_F(TestMirroring, EnableImageMirror_WithoutJournaling) { | |
418 | uint64_t features = 0; | |
419 | features |= RBD_FEATURE_OBJECT_MAP; | |
420 | features |= RBD_FEATURE_EXCLUSIVE_LOCK; | |
421 | check_mirror_image_enable(RBD_MIRROR_MODE_DISABLED, features, -EINVAL, | |
422 | RBD_MIRROR_IMAGE_DISABLED); | |
423 | } | |
424 | ||
425 | TEST_F(TestMirroring, CreateImage_In_MirrorModeDisabled) { | |
426 | uint64_t features = 0; | |
427 | features |= RBD_FEATURE_OBJECT_MAP; | |
428 | features |= RBD_FEATURE_EXCLUSIVE_LOCK; | |
429 | features |= RBD_FEATURE_JOURNALING; | |
430 | check_mirroring_on_create(features, RBD_MIRROR_MODE_DISABLED, | |
431 | RBD_MIRROR_IMAGE_DISABLED); | |
432 | } | |
433 | ||
434 | TEST_F(TestMirroring, CreateImage_In_MirrorModeImage) { | |
435 | uint64_t features = 0; | |
436 | features |= RBD_FEATURE_OBJECT_MAP; | |
437 | features |= RBD_FEATURE_EXCLUSIVE_LOCK; | |
438 | features |= RBD_FEATURE_JOURNALING; | |
439 | check_mirroring_on_create(features, RBD_MIRROR_MODE_IMAGE, | |
440 | RBD_MIRROR_IMAGE_DISABLED); | |
441 | } | |
442 | ||
443 | TEST_F(TestMirroring, CreateImage_In_MirrorModePool) { | |
444 | uint64_t features = 0; | |
445 | features |= RBD_FEATURE_OBJECT_MAP; | |
446 | features |= RBD_FEATURE_EXCLUSIVE_LOCK; | |
447 | features |= RBD_FEATURE_JOURNALING; | |
448 | check_mirroring_on_create(features, RBD_MIRROR_MODE_POOL, | |
449 | RBD_MIRROR_IMAGE_ENABLED); | |
450 | } | |
451 | ||
452 | TEST_F(TestMirroring, CreateImage_In_MirrorModePool_WithoutJournaling) { | |
453 | uint64_t features = 0; | |
454 | features |= RBD_FEATURE_OBJECT_MAP; | |
455 | features |= RBD_FEATURE_EXCLUSIVE_LOCK; | |
456 | check_mirroring_on_create(features, RBD_MIRROR_MODE_POOL, | |
457 | RBD_MIRROR_IMAGE_DISABLED); | |
458 | } | |
459 | ||
460 | TEST_F(TestMirroring, CreateImage_In_MirrorModeImage_WithoutJournaling) { | |
461 | uint64_t features = 0; | |
462 | features |= RBD_FEATURE_OBJECT_MAP; | |
463 | features |= RBD_FEATURE_EXCLUSIVE_LOCK; | |
464 | check_mirroring_on_create(features, RBD_MIRROR_MODE_IMAGE, | |
465 | RBD_MIRROR_IMAGE_DISABLED); | |
466 | } | |
467 | ||
468 | TEST_F(TestMirroring, EnableJournaling_In_MirrorModeDisabled) { | |
469 | uint64_t init_features = 0; | |
470 | init_features |= RBD_FEATURE_OBJECT_MAP; | |
471 | init_features |= RBD_FEATURE_EXCLUSIVE_LOCK; | |
472 | uint64_t features = RBD_FEATURE_JOURNALING; | |
473 | check_mirroring_on_update_features(init_features, true, false, features, 0, | |
474 | RBD_MIRROR_MODE_DISABLED, RBD_MIRROR_IMAGE_DISABLED); | |
475 | } | |
476 | ||
477 | TEST_F(TestMirroring, EnableJournaling_In_MirrorModeImage) { | |
478 | uint64_t init_features = 0; | |
479 | init_features |= RBD_FEATURE_OBJECT_MAP; | |
480 | init_features |= RBD_FEATURE_EXCLUSIVE_LOCK; | |
481 | uint64_t features = RBD_FEATURE_JOURNALING; | |
482 | check_mirroring_on_update_features(init_features, true, false, features, 0, | |
483 | RBD_MIRROR_MODE_IMAGE, RBD_MIRROR_IMAGE_DISABLED); | |
484 | } | |
485 | ||
486 | TEST_F(TestMirroring, EnableJournaling_In_MirrorModePool) { | |
487 | uint64_t init_features = 0; | |
488 | init_features |= RBD_FEATURE_OBJECT_MAP; | |
489 | init_features |= RBD_FEATURE_EXCLUSIVE_LOCK; | |
490 | uint64_t features = RBD_FEATURE_JOURNALING; | |
491 | check_mirroring_on_update_features(init_features, true, false, features, 0, | |
492 | RBD_MIRROR_MODE_POOL, RBD_MIRROR_IMAGE_ENABLED); | |
493 | } | |
494 | ||
495 | TEST_F(TestMirroring, DisableJournaling_In_MirrorModePool) { | |
496 | uint64_t init_features = 0; | |
497 | init_features |= RBD_FEATURE_OBJECT_MAP; | |
498 | init_features |= RBD_FEATURE_EXCLUSIVE_LOCK; | |
499 | init_features |= RBD_FEATURE_JOURNALING; | |
500 | uint64_t features = RBD_FEATURE_JOURNALING; | |
501 | check_mirroring_on_update_features(init_features, false, false, features, 0, | |
502 | RBD_MIRROR_MODE_POOL, RBD_MIRROR_IMAGE_DISABLED); | |
503 | } | |
504 | ||
505 | TEST_F(TestMirroring, DisableJournaling_In_MirrorModeImage) { | |
506 | uint64_t init_features = 0; | |
507 | init_features |= RBD_FEATURE_OBJECT_MAP; | |
508 | init_features |= RBD_FEATURE_EXCLUSIVE_LOCK; | |
509 | init_features |= RBD_FEATURE_JOURNALING; | |
510 | uint64_t features = RBD_FEATURE_JOURNALING; | |
511 | check_mirroring_on_update_features(init_features, false, true, features, -EINVAL, | |
512 | RBD_MIRROR_MODE_IMAGE, RBD_MIRROR_IMAGE_ENABLED); | |
513 | } | |
514 | ||
515 | TEST_F(TestMirroring, MirrorModeSet_DisabledMode_To_PoolMode) { | |
516 | std::vector<uint64_t> features_vec; | |
517 | features_vec.push_back(RBD_FEATURE_EXCLUSIVE_LOCK); | |
518 | features_vec.push_back(RBD_FEATURE_EXCLUSIVE_LOCK | RBD_FEATURE_JOURNALING); | |
519 | ||
520 | setup_images_with_mirror_mode(RBD_MIRROR_MODE_DISABLED, features_vec); | |
521 | ||
522 | std::vector<rbd_mirror_image_state_t> states_vec; | |
523 | states_vec.push_back(RBD_MIRROR_IMAGE_DISABLED); | |
524 | states_vec.push_back(RBD_MIRROR_IMAGE_ENABLED); | |
525 | check_mirroring_on_mirror_mode_set(RBD_MIRROR_MODE_POOL, states_vec); | |
526 | } | |
527 | ||
528 | TEST_F(TestMirroring, MirrorModeSet_PoolMode_To_DisabledMode) { | |
529 | std::vector<uint64_t> features_vec; | |
530 | features_vec.push_back(RBD_FEATURE_EXCLUSIVE_LOCK); | |
531 | features_vec.push_back(RBD_FEATURE_EXCLUSIVE_LOCK | RBD_FEATURE_JOURNALING); | |
532 | ||
533 | setup_images_with_mirror_mode(RBD_MIRROR_MODE_POOL, features_vec); | |
534 | ||
535 | std::vector<rbd_mirror_image_state_t> states_vec; | |
536 | states_vec.push_back(RBD_MIRROR_IMAGE_DISABLED); | |
537 | states_vec.push_back(RBD_MIRROR_IMAGE_DISABLED); | |
538 | check_mirroring_on_mirror_mode_set(RBD_MIRROR_MODE_DISABLED, states_vec); | |
539 | } | |
540 | ||
541 | TEST_F(TestMirroring, MirrorModeSet_DisabledMode_To_ImageMode) { | |
542 | std::vector<uint64_t> features_vec; | |
543 | features_vec.push_back(RBD_FEATURE_EXCLUSIVE_LOCK); | |
544 | features_vec.push_back(RBD_FEATURE_EXCLUSIVE_LOCK | RBD_FEATURE_JOURNALING); | |
545 | ||
546 | setup_images_with_mirror_mode(RBD_MIRROR_MODE_DISABLED, features_vec); | |
547 | ||
548 | std::vector<rbd_mirror_image_state_t> states_vec; | |
549 | states_vec.push_back(RBD_MIRROR_IMAGE_DISABLED); | |
550 | states_vec.push_back(RBD_MIRROR_IMAGE_DISABLED); | |
551 | check_mirroring_on_mirror_mode_set(RBD_MIRROR_MODE_IMAGE, states_vec); | |
552 | } | |
553 | ||
554 | ||
555 | TEST_F(TestMirroring, MirrorModeSet_PoolMode_To_ImageMode) { | |
556 | std::vector<uint64_t> features_vec; | |
557 | features_vec.push_back(RBD_FEATURE_EXCLUSIVE_LOCK); | |
558 | features_vec.push_back(RBD_FEATURE_EXCLUSIVE_LOCK | RBD_FEATURE_JOURNALING); | |
559 | ||
560 | setup_images_with_mirror_mode(RBD_MIRROR_MODE_POOL, features_vec); | |
561 | ||
562 | std::vector<rbd_mirror_image_state_t> states_vec; | |
563 | states_vec.push_back(RBD_MIRROR_IMAGE_DISABLED); | |
564 | states_vec.push_back(RBD_MIRROR_IMAGE_ENABLED); | |
565 | check_mirroring_on_mirror_mode_set(RBD_MIRROR_MODE_IMAGE, states_vec); | |
566 | } | |
567 | ||
568 | TEST_F(TestMirroring, MirrorModeSet_ImageMode_To_PoolMode) { | |
569 | std::vector<uint64_t> features_vec; | |
570 | features_vec.push_back(RBD_FEATURE_EXCLUSIVE_LOCK); | |
571 | features_vec.push_back(RBD_FEATURE_EXCLUSIVE_LOCK | RBD_FEATURE_JOURNALING); | |
572 | ||
573 | setup_images_with_mirror_mode(RBD_MIRROR_MODE_IMAGE, features_vec); | |
574 | ||
575 | std::vector<rbd_mirror_image_state_t> states_vec; | |
576 | states_vec.push_back(RBD_MIRROR_IMAGE_DISABLED); | |
577 | states_vec.push_back(RBD_MIRROR_IMAGE_ENABLED); | |
578 | check_mirroring_on_mirror_mode_set(RBD_MIRROR_MODE_POOL, states_vec); | |
579 | } | |
580 | ||
581 | TEST_F(TestMirroring, MirrorModeSet_ImageMode_To_DisabledMode) { | |
582 | std::vector<uint64_t> features_vec; | |
583 | features_vec.push_back(RBD_FEATURE_EXCLUSIVE_LOCK); | |
584 | features_vec.push_back(RBD_FEATURE_EXCLUSIVE_LOCK | RBD_FEATURE_JOURNALING); | |
585 | ||
586 | setup_images_with_mirror_mode(RBD_MIRROR_MODE_POOL, features_vec); | |
587 | ||
588 | ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_IMAGE)); | |
589 | ASSERT_EQ(-EINVAL, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_DISABLED)); | |
590 | ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_POOL)); | |
591 | ||
592 | std::vector<rbd_mirror_image_state_t> states_vec; | |
593 | states_vec.push_back(RBD_MIRROR_IMAGE_DISABLED); | |
594 | states_vec.push_back(RBD_MIRROR_IMAGE_DISABLED); | |
595 | check_mirroring_on_mirror_mode_set(RBD_MIRROR_MODE_DISABLED, states_vec); | |
596 | } | |
597 | ||
598 | TEST_F(TestMirroring, RemoveImage_With_MirrorImageEnabled) { | |
599 | check_remove_image(RBD_MIRROR_MODE_IMAGE, | |
600 | RBD_FEATURE_EXCLUSIVE_LOCK | RBD_FEATURE_JOURNALING, | |
601 | true); | |
602 | } | |
603 | ||
604 | TEST_F(TestMirroring, RemoveImage_With_MirrorImageDisabled) { | |
605 | check_remove_image(RBD_MIRROR_MODE_IMAGE, | |
606 | RBD_FEATURE_EXCLUSIVE_LOCK | RBD_FEATURE_JOURNALING, | |
607 | false); | |
608 | } | |
609 | ||
610 | TEST_F(TestMirroring, RemoveImage_With_ImageWithoutJournal) { | |
611 | check_remove_image(RBD_MIRROR_MODE_IMAGE, | |
612 | RBD_FEATURE_EXCLUSIVE_LOCK, | |
613 | false); | |
614 | } | |
615 | ||
616 | TEST_F(TestMirroring, RemoveImage_With_MirrorImageDemoted) { | |
617 | check_remove_image(RBD_MIRROR_MODE_IMAGE, | |
618 | RBD_FEATURE_EXCLUSIVE_LOCK | RBD_FEATURE_JOURNALING, | |
619 | true, true); | |
620 | } | |
621 | ||
622 | TEST_F(TestMirroring, MirrorStatusList) { | |
623 | std::vector<uint64_t> | |
624 | features_vec(5, RBD_FEATURE_EXCLUSIVE_LOCK | RBD_FEATURE_JOURNALING); | |
625 | setup_images_with_mirror_mode(RBD_MIRROR_MODE_POOL, features_vec); | |
626 | ||
627 | std::string last_read = ""; | |
628 | std::map<std::string, librbd::mirror_image_status_t> images; | |
629 | ASSERT_EQ(0, m_rbd.mirror_image_status_list(m_ioctx, last_read, 2, &images)); | |
630 | ASSERT_EQ(2U, images.size()); | |
631 | ||
632 | last_read = images.rbegin()->first; | |
633 | images.clear(); | |
634 | ASSERT_EQ(0, m_rbd.mirror_image_status_list(m_ioctx, last_read, 2, &images)); | |
635 | ASSERT_EQ(2U, images.size()); | |
636 | ||
637 | last_read = images.rbegin()->first; | |
638 | images.clear(); | |
639 | ASSERT_EQ(0, m_rbd.mirror_image_status_list(m_ioctx, last_read, 4096, &images)); | |
640 | ASSERT_EQ(1U, images.size()); | |
641 | ||
642 | last_read = images.rbegin()->first; | |
643 | images.clear(); | |
644 | ASSERT_EQ(0, m_rbd.mirror_image_status_list(m_ioctx, last_read, 4096, &images)); | |
645 | ASSERT_EQ(0U, images.size()); | |
646 | } | |
647 | ||
648 | TEST_F(TestMirroring, RemoveBootstrapped) | |
649 | { | |
650 | ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_POOL)); | |
651 | ||
652 | uint64_t features = RBD_FEATURE_EXCLUSIVE_LOCK | RBD_FEATURE_JOURNALING; | |
653 | int order = 20; | |
654 | ASSERT_EQ(0, m_rbd.create2(m_ioctx, image_name.c_str(), 4096, features, | |
655 | &order)); | |
656 | librbd::Image image; | |
657 | ASSERT_EQ(0, m_rbd.open(m_ioctx, image, image_name.c_str())); | |
658 | ASSERT_EQ(-EBUSY, m_rbd.remove(m_ioctx, image_name.c_str())); | |
659 | ||
660 | // simulate the image is open by rbd-mirror bootstrap | |
661 | uint64_t handle; | |
662 | struct MirrorWatcher : public librados::WatchCtx2 { | |
663 | MirrorWatcher(librados::IoCtx &ioctx) : m_ioctx(ioctx) { | |
664 | } | |
665 | void handle_notify(uint64_t notify_id, uint64_t cookie, | |
666 | uint64_t notifier_id, bufferlist& bl) override { | |
667 | // received IMAGE_UPDATED notification from remove | |
668 | m_notified = true; | |
669 | m_ioctx.notify_ack(RBD_MIRRORING, notify_id, cookie, bl); | |
670 | } | |
671 | void handle_error(uint64_t cookie, int err) override { | |
672 | } | |
673 | librados::IoCtx &m_ioctx; | |
674 | bool m_notified = false; | |
675 | } watcher(m_ioctx); | |
676 | ASSERT_EQ(0, m_ioctx.create(RBD_MIRRORING, false)); | |
677 | ASSERT_EQ(0, m_ioctx.watch2(RBD_MIRRORING, &handle, &watcher)); | |
678 | // now remove should succeed | |
679 | ASSERT_EQ(0, m_rbd.remove(m_ioctx, image_name.c_str())); | |
680 | ASSERT_EQ(0, m_ioctx.unwatch2(handle)); | |
681 | ASSERT_TRUE(watcher.m_notified); | |
682 | ASSERT_EQ(0, image.close()); | |
683 | } | |
684 | ||
685 | TEST_F(TestMirroring, AioPromoteDemote) { | |
686 | std::list<std::string> image_names; | |
687 | for (size_t idx = 0; idx < 10; ++idx) { | |
688 | image_names.push_back(get_temp_image_name()); | |
689 | } | |
690 | ||
691 | ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_IMAGE)); | |
692 | ||
693 | // create mirror images | |
694 | int order = 20; | |
695 | std::list<librbd::Image> images; | |
696 | for (auto &image_name : image_names) { | |
697 | ASSERT_EQ(0, m_rbd.create2(m_ioctx, image_name.c_str(), 2048, | |
698 | RBD_FEATURE_EXCLUSIVE_LOCK | | |
699 | RBD_FEATURE_JOURNALING, | |
700 | &order)); | |
701 | ||
702 | images.emplace_back(); | |
703 | ASSERT_EQ(0, m_rbd.open(m_ioctx, images.back(), image_name.c_str())); | |
704 | ASSERT_EQ(0, images.back().mirror_image_enable()); | |
705 | } | |
706 | ||
707 | // demote all images | |
708 | std::list<librbd::RBD::AioCompletion *> aio_comps; | |
709 | for (auto &image : images) { | |
710 | aio_comps.push_back(new librbd::RBD::AioCompletion(nullptr, nullptr)); | |
711 | ASSERT_EQ(0, image.aio_mirror_image_demote(aio_comps.back())); | |
712 | } | |
713 | for (auto aio_comp : aio_comps) { | |
714 | ASSERT_EQ(0, aio_comp->wait_for_complete()); | |
715 | ASSERT_EQ(1, aio_comp->is_complete()); | |
716 | ASSERT_EQ(0, aio_comp->get_return_value()); | |
717 | aio_comp->release(); | |
718 | } | |
719 | aio_comps.clear(); | |
720 | ||
721 | // verify demotions | |
722 | for (auto &image : images) { | |
723 | librbd::mirror_image_info_t mirror_image; | |
724 | ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image, | |
725 | sizeof(mirror_image))); | |
726 | ASSERT_FALSE(mirror_image.primary); | |
727 | } | |
728 | ||
729 | // promote all images | |
730 | for (auto &image : images) { | |
731 | aio_comps.push_back(new librbd::RBD::AioCompletion(nullptr, nullptr)); | |
732 | ASSERT_EQ(0, image.aio_mirror_image_promote(false, aio_comps.back())); | |
733 | } | |
734 | for (auto aio_comp : aio_comps) { | |
735 | ASSERT_EQ(0, aio_comp->wait_for_complete()); | |
736 | ASSERT_EQ(1, aio_comp->is_complete()); | |
737 | ASSERT_EQ(0, aio_comp->get_return_value()); | |
738 | aio_comp->release(); | |
739 | } | |
740 | ||
741 | // verify promotions | |
742 | for (auto &image : images) { | |
743 | librbd::mirror_image_info_t mirror_image; | |
744 | ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image, | |
745 | sizeof(mirror_image))); | |
746 | ASSERT_TRUE(mirror_image.primary); | |
747 | } | |
748 | } | |
749 | ||
750 | TEST_F(TestMirroring, AioGetInfo) { | |
751 | std::list<std::string> image_names; | |
752 | for (size_t idx = 0; idx < 10; ++idx) { | |
753 | image_names.push_back(get_temp_image_name()); | |
754 | } | |
755 | ||
756 | ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_POOL)); | |
757 | ||
758 | // create mirror images | |
759 | int order = 20; | |
760 | std::list<librbd::Image> images; | |
761 | for (auto &image_name : image_names) { | |
762 | ASSERT_EQ(0, m_rbd.create2(m_ioctx, image_name.c_str(), 2048, | |
763 | RBD_FEATURE_EXCLUSIVE_LOCK | | |
764 | RBD_FEATURE_JOURNALING, | |
765 | &order)); | |
766 | ||
767 | images.emplace_back(); | |
768 | ASSERT_EQ(0, m_rbd.open(m_ioctx, images.back(), image_name.c_str())); | |
769 | } | |
770 | ||
771 | std::list<librbd::RBD::AioCompletion *> aio_comps; | |
772 | std::list<librbd::mirror_image_info_t> infos; | |
773 | for (auto &image : images) { | |
774 | aio_comps.push_back(new librbd::RBD::AioCompletion(nullptr, nullptr)); | |
775 | infos.emplace_back(); | |
776 | ASSERT_EQ(0, image.aio_mirror_image_get_info(&infos.back(), | |
777 | sizeof(infos.back()), | |
778 | aio_comps.back())); | |
779 | } | |
780 | for (auto aio_comp : aio_comps) { | |
781 | ASSERT_EQ(0, aio_comp->wait_for_complete()); | |
782 | ASSERT_EQ(1, aio_comp->is_complete()); | |
783 | ASSERT_EQ(0, aio_comp->get_return_value()); | |
784 | aio_comp->release(); | |
785 | } | |
786 | aio_comps.clear(); | |
787 | ||
788 | for (auto &info : infos) { | |
789 | ASSERT_NE("", info.global_id); | |
790 | ASSERT_EQ(RBD_MIRROR_IMAGE_ENABLED, info.state); | |
791 | ASSERT_TRUE(info.primary); | |
792 | } | |
793 | } | |
794 | ||
795 | TEST_F(TestMirroring, AioGetStatus) { | |
796 | std::list<std::string> image_names; | |
797 | for (size_t idx = 0; idx < 10; ++idx) { | |
798 | image_names.push_back(get_temp_image_name()); | |
799 | } | |
800 | ||
801 | ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_POOL)); | |
802 | ||
803 | // create mirror images | |
804 | int order = 20; | |
805 | std::list<librbd::Image> images; | |
806 | for (auto &image_name : image_names) { | |
807 | ASSERT_EQ(0, m_rbd.create2(m_ioctx, image_name.c_str(), 2048, | |
808 | RBD_FEATURE_EXCLUSIVE_LOCK | | |
809 | RBD_FEATURE_JOURNALING, | |
810 | &order)); | |
811 | ||
812 | images.emplace_back(); | |
813 | ASSERT_EQ(0, m_rbd.open(m_ioctx, images.back(), image_name.c_str())); | |
814 | } | |
815 | ||
816 | std::list<librbd::RBD::AioCompletion *> aio_comps; | |
817 | std::list<librbd::mirror_image_status_t> statuses; | |
818 | for (auto &image : images) { | |
819 | aio_comps.push_back(new librbd::RBD::AioCompletion(nullptr, nullptr)); | |
820 | statuses.emplace_back(); | |
821 | ASSERT_EQ(0, image.aio_mirror_image_get_status(&statuses.back(), | |
822 | sizeof(statuses.back()), | |
823 | aio_comps.back())); | |
824 | } | |
825 | for (auto aio_comp : aio_comps) { | |
826 | ASSERT_EQ(0, aio_comp->wait_for_complete()); | |
827 | ASSERT_EQ(1, aio_comp->is_complete()); | |
828 | ASSERT_EQ(0, aio_comp->get_return_value()); | |
829 | aio_comp->release(); | |
830 | } | |
831 | aio_comps.clear(); | |
832 | ||
833 | for (auto &status : statuses) { | |
834 | ASSERT_NE("", status.name); | |
835 | ASSERT_NE("", status.info.global_id); | |
836 | ASSERT_EQ(RBD_MIRROR_IMAGE_ENABLED, status.info.state); | |
837 | ASSERT_TRUE(status.info.primary); | |
838 | ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, status.state); | |
839 | ASSERT_EQ("status not found", status.description); | |
840 | ASSERT_FALSE(status.up); | |
841 | ASSERT_EQ(0, status.last_update); | |
842 | } | |
843 | } |