]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/librbd/object_map/test_mock_UpdateRequest.cc
bump version to 18.2.4-pve3
[ceph.git] / ceph / src / test / librbd / object_map / test_mock_UpdateRequest.cc
CommitLineData
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#include "test/librbd/test_mock_fixture.h"
5#include "test/librbd/test_support.h"
6#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
7#include "common/bit_vector.hpp"
8#include "librbd/ImageState.h"
9#include "librbd/internal.h"
10#include "librbd/ObjectMap.h"
11#include "librbd/Operations.h"
11fdf7f2 12#include "librbd/api/Image.h"
7c673cae
FG
13#include "librbd/object_map/UpdateRequest.h"
14#include "gmock/gmock.h"
15#include "gtest/gtest.h"
16
17namespace librbd {
18namespace object_map {
19
20using ::testing::_;
21using ::testing::DoDefault;
3efd9988 22using ::testing::InSequence;
7c673cae
FG
23using ::testing::Return;
24using ::testing::StrEq;
25
26class TestMockObjectMapUpdateRequest : public TestMockFixture {
27public:
3efd9988
FG
28 void expect_update(librbd::ImageCtx *ictx, uint64_t snap_id,
29 uint64_t start_object_no, uint64_t end_object_no,
30 uint8_t new_state,
31 const boost::optional<uint8_t>& current_state, int r) {
32 bufferlist bl;
11fdf7f2
TL
33 encode(start_object_no, bl);
34 encode(end_object_no, bl);
35 encode(new_state, bl);
36 encode(current_state, bl);
3efd9988 37
7c673cae
FG
38 std::string oid(ObjectMap<>::object_map_name(ictx->id, snap_id));
39 if (snap_id == CEPH_NOSNAP) {
40 EXPECT_CALL(get_mock_io_ctx(ictx->md_ctx),
f67539c2
TL
41 exec(oid, _, StrEq("lock"), StrEq("assert_locked"), _, _, _,
42 _))
7c673cae
FG
43 .WillOnce(DoDefault());
44 }
45
46 if (r < 0) {
47 EXPECT_CALL(get_mock_io_ctx(ictx->md_ctx),
3efd9988 48 exec(oid, _, StrEq("rbd"), StrEq("object_map_update"),
f67539c2 49 ContentsEqual(bl), _, _, _))
7c673cae
FG
50 .WillOnce(Return(r));
51 } else {
52 EXPECT_CALL(get_mock_io_ctx(ictx->md_ctx),
3efd9988 53 exec(oid, _, StrEq("rbd"), StrEq("object_map_update"),
f67539c2 54 ContentsEqual(bl), _, _, _))
7c673cae
FG
55 .WillOnce(DoDefault());
56 }
57 }
58
59 void expect_invalidate(librbd::ImageCtx *ictx) {
60 EXPECT_CALL(get_mock_io_ctx(ictx->md_ctx),
f67539c2
TL
61 exec(ictx->header_oid, _, StrEq("rbd"), StrEq("set_flags"), _,
62 _, _, _))
7c673cae
FG
63 .WillOnce(DoDefault());
64 }
65};
66
67TEST_F(TestMockObjectMapUpdateRequest, UpdateInMemory) {
68 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
69
70 librbd::ImageCtx *ictx;
71 ASSERT_EQ(0, open_image(m_image_name, &ictx));
72
73 librbd::NoOpProgressContext no_progress;
74 ASSERT_EQ(0, ictx->operations->resize(4 << ictx->order, true, no_progress));
75 ASSERT_EQ(0, acquire_exclusive_lock(*ictx));
76
9f95a23c 77 ceph::shared_mutex object_map_lock = ceph::make_shared_mutex("lock");
7c673cae
FG
78 ceph::BitVector<2> object_map;
79 object_map.resize(4);
80 for (uint64_t i = 0; i < object_map.size(); ++i) {
81 object_map[i] = i % 4;
82 }
83
84 C_SaferCond cond_ctx;
85 AsyncRequest<> *req = new UpdateRequest<>(
9f95a23c
TL
86 *ictx, &object_map_lock, &object_map, CEPH_NOSNAP, 0, object_map.size(),
87 OBJECT_NONEXISTENT, OBJECT_EXISTS, {}, false, &cond_ctx);
7c673cae 88 {
9f95a23c
TL
89 std::shared_lock image_locker{ictx->image_lock};
90 std::unique_lock object_map_locker{object_map_lock};
7c673cae
FG
91 req->send();
92 }
93 ASSERT_EQ(0, cond_ctx.wait());
94
95 for (uint64_t i = 0; i < object_map.size(); ++i) {
96 if (i % 4 == OBJECT_EXISTS || i % 4 == OBJECT_EXISTS_CLEAN) {
97 ASSERT_EQ(OBJECT_NONEXISTENT, object_map[i]);
98 } else {
99 ASSERT_EQ(i % 4, object_map[i]);
100 }
101 }
102}
103
104TEST_F(TestMockObjectMapUpdateRequest, UpdateHeadOnDisk) {
105 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
106
107 librbd::ImageCtx *ictx;
108 ASSERT_EQ(0, open_image(m_image_name, &ictx));
109 ASSERT_EQ(0, acquire_exclusive_lock(*ictx));
110
3efd9988 111 expect_update(ictx, CEPH_NOSNAP, 0, 1, OBJECT_NONEXISTENT, OBJECT_EXISTS, 0);
7c673cae 112
9f95a23c
TL
113 ceph::shared_mutex object_map_lock =
114 ceph::make_shared_mutex("lock");
7c673cae
FG
115 ceph::BitVector<2> object_map;
116 object_map.resize(1);
117
118 C_SaferCond cond_ctx;
119 AsyncRequest<> *req = new UpdateRequest<>(
9f95a23c
TL
120 *ictx, &object_map_lock, &object_map, CEPH_NOSNAP, 0, object_map.size(),
121 OBJECT_NONEXISTENT, OBJECT_EXISTS, {}, false, &cond_ctx);
7c673cae 122 {
9f95a23c
TL
123 std::shared_lock image_locker{ictx->image_lock};
124 std::unique_lock object_map_locker{object_map_lock};
7c673cae
FG
125 req->send();
126 }
127 ASSERT_EQ(0, cond_ctx.wait());
128
129 expect_unlock_exclusive_lock(*ictx);
130}
131
132TEST_F(TestMockObjectMapUpdateRequest, UpdateSnapOnDisk) {
133 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
134
135 librbd::ImageCtx *ictx;
136 ASSERT_EQ(0, open_image(m_image_name, &ictx));
137 ASSERT_EQ(0, snap_create(*ictx, "snap1"));
11fdf7f2
TL
138 ASSERT_EQ(0, librbd::api::Image<>::snap_set(ictx,
139 cls::rbd::UserSnapshotNamespace(),
140 "snap1"));
7c673cae
FG
141
142 uint64_t snap_id = ictx->snap_id;
3efd9988 143 expect_update(ictx, snap_id, 0, 1, OBJECT_NONEXISTENT, OBJECT_EXISTS, 0);
7c673cae 144
9f95a23c
TL
145 ceph::shared_mutex object_map_lock =
146 ceph::make_shared_mutex("lock");
7c673cae
FG
147 ceph::BitVector<2> object_map;
148 object_map.resize(1);
149
150 C_SaferCond cond_ctx;
151 AsyncRequest<> *req = new UpdateRequest<>(
9f95a23c
TL
152 *ictx, &object_map_lock, &object_map, snap_id, 0, object_map.size(),
153 OBJECT_NONEXISTENT, OBJECT_EXISTS, {}, false, &cond_ctx);
7c673cae 154 {
9f95a23c
TL
155 std::shared_lock image_locker{ictx->image_lock};
156 std::unique_lock object_map_locker{object_map_lock};
7c673cae
FG
157 req->send();
158 }
159 ASSERT_EQ(0, cond_ctx.wait());
160
161 expect_unlock_exclusive_lock(*ictx);
162}
163
164TEST_F(TestMockObjectMapUpdateRequest, UpdateOnDiskError) {
165 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
166
167 librbd::ImageCtx *ictx;
168 ASSERT_EQ(0, open_image(m_image_name, &ictx));
169 ASSERT_EQ(0, acquire_exclusive_lock(*ictx));
170
3efd9988
FG
171 expect_update(ictx, CEPH_NOSNAP, 0, 1, OBJECT_NONEXISTENT, OBJECT_EXISTS,
172 -EINVAL);
7c673cae
FG
173 expect_invalidate(ictx);
174
9f95a23c 175 ceph::shared_mutex object_map_lock = ceph::make_shared_mutex("lock");
7c673cae
FG
176 ceph::BitVector<2> object_map;
177 object_map.resize(1);
178
179 C_SaferCond cond_ctx;
180 AsyncRequest<> *req = new UpdateRequest<>(
9f95a23c
TL
181 *ictx, &object_map_lock, &object_map, CEPH_NOSNAP, 0, object_map.size(),
182 OBJECT_NONEXISTENT, OBJECT_EXISTS, {}, false, &cond_ctx);
7c673cae 183 {
9f95a23c
TL
184 std::shared_lock image_locker{ictx->image_lock};
185 std::unique_lock object_map_locker{object_map_lock};
7c673cae
FG
186 req->send();
187 }
188 ASSERT_EQ(0, cond_ctx.wait());
189
190 expect_unlock_exclusive_lock(*ictx);
191}
192
193TEST_F(TestMockObjectMapUpdateRequest, RebuildSnapOnDisk) {
194 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
195
196 librbd::ImageCtx *ictx;
197 ASSERT_EQ(0, open_image(m_image_name, &ictx));
198 ASSERT_EQ(0, snap_create(*ictx, "snap1"));
199 ASSERT_EQ(0, ictx->state->refresh_if_required());
200 ASSERT_EQ(CEPH_NOSNAP, ictx->snap_id);
201
202 uint64_t snap_id = ictx->snap_info.rbegin()->first;
3efd9988
FG
203 expect_update(ictx, snap_id, 0, 1, OBJECT_EXISTS_CLEAN,
204 boost::optional<uint8_t>(), 0);
7c673cae
FG
205 expect_unlock_exclusive_lock(*ictx);
206
9f95a23c 207 ceph::shared_mutex object_map_lock = ceph::make_shared_mutex("lock");
7c673cae
FG
208 ceph::BitVector<2> object_map;
209 object_map.resize(1);
210
211 C_SaferCond cond_ctx;
212 AsyncRequest<> *req = new UpdateRequest<>(
9f95a23c
TL
213 *ictx, &object_map_lock, &object_map, snap_id, 0, object_map.size(),
214 OBJECT_EXISTS_CLEAN, boost::optional<uint8_t>(), {}, false, &cond_ctx);
7c673cae 215 {
9f95a23c
TL
216 std::shared_lock image_locker{ictx->image_lock};
217 std::unique_lock object_map_locker{object_map_lock};
7c673cae
FG
218 req->send();
219 }
220 ASSERT_EQ(0, cond_ctx.wait());
221
222 // do not update the in-memory map if rebuilding a snapshot
223 ASSERT_NE(OBJECT_EXISTS_CLEAN, object_map[0]);
224}
225
3efd9988
FG
226TEST_F(TestMockObjectMapUpdateRequest, BatchUpdate) {
227 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
228
229 librbd::ImageCtx *ictx;
230 ASSERT_EQ(0, open_image(m_image_name, &ictx));
231
232 librbd::NoOpProgressContext no_progress;
233 ASSERT_EQ(0, ictx->operations->resize(712312 * ictx->get_object_size(), false,
234 no_progress));
235 ASSERT_EQ(0, acquire_exclusive_lock(*ictx));
236
f67539c2 237 expect_unlock_exclusive_lock(*ictx);
3efd9988
FG
238 InSequence seq;
239 expect_update(ictx, CEPH_NOSNAP, 0, 262144, OBJECT_NONEXISTENT, OBJECT_EXISTS,
240 0);
241 expect_update(ictx, CEPH_NOSNAP, 262144, 524288, OBJECT_NONEXISTENT,
242 OBJECT_EXISTS, 0);
243 expect_update(ictx, CEPH_NOSNAP, 524288, 712312, OBJECT_NONEXISTENT,
244 OBJECT_EXISTS, 0);
3efd9988 245
9f95a23c 246 ceph::shared_mutex object_map_lock = ceph::make_shared_mutex("lock");
3efd9988
FG
247 ceph::BitVector<2> object_map;
248 object_map.resize(712312);
249
250 C_SaferCond cond_ctx;
251 AsyncRequest<> *req = new UpdateRequest<>(
9f95a23c
TL
252 *ictx, &object_map_lock, &object_map, CEPH_NOSNAP, 0, object_map.size(),
253 OBJECT_NONEXISTENT, OBJECT_EXISTS, {}, false, &cond_ctx);
3efd9988 254 {
9f95a23c
TL
255 std::shared_lock image_locker{ictx->image_lock};
256 std::unique_lock object_map_locker{object_map_lock};
3efd9988
FG
257 req->send();
258 }
259 ASSERT_EQ(0, cond_ctx.wait());
260}
261
91327a77
AA
262TEST_F(TestMockObjectMapUpdateRequest, IgnoreMissingObjectMap) {
263 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
264
265 librbd::ImageCtx *ictx;
266 ASSERT_EQ(0, open_image(m_image_name, &ictx));
267 ASSERT_EQ(0, acquire_exclusive_lock(*ictx));
268
269 expect_update(ictx, CEPH_NOSNAP, 0, 1, OBJECT_NONEXISTENT, OBJECT_EXISTS,
270 -ENOENT);
271
9f95a23c 272 ceph::shared_mutex object_map_lock = ceph::make_shared_mutex("lock");
91327a77
AA
273 ceph::BitVector<2> object_map;
274 object_map.resize(1);
275
276 C_SaferCond cond_ctx;
277 AsyncRequest<> *req = new UpdateRequest<>(
9f95a23c
TL
278 *ictx, &object_map_lock, &object_map, CEPH_NOSNAP, 0, object_map.size(),
279 OBJECT_NONEXISTENT, OBJECT_EXISTS, {}, true, &cond_ctx);
91327a77 280 {
9f95a23c
TL
281 std::shared_lock image_locker{ictx->image_lock};
282 std::unique_lock object_map_locker{object_map_lock};
91327a77
AA
283 req->send();
284 }
285 ASSERT_EQ(0, cond_ctx.wait());
286
287 expect_unlock_exclusive_lock(*ictx);
288}
289
7c673cae
FG
290} // namespace object_map
291} // namespace librbd