]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #include <iostream> | |
5 | #include "common/hostname.h" | |
6 | #include "test/librbd/test_mock_fixture.h" | |
7 | #include "test/librbd/test_support.h" | |
8 | #include "test/librbd/mock/MockImageCtx.h" | |
9 | #include "include/rbd/librbd.hpp" | |
10 | #include "librbd/cache/pwl/AbstractWriteLog.h" | |
11 | #include "librbd/cache/pwl/ImageCacheState.h" | |
12 | #include "librbd/cache/pwl/Types.h" | |
13 | #include "librbd/cache/ImageWriteback.h" | |
14 | #include "librbd/plugin/Api.h" | |
15 | ||
16 | namespace librbd { | |
17 | namespace { | |
18 | ||
19 | struct MockContextSSD : public C_SaferCond { | |
20 | MOCK_METHOD1(complete, void(int)); | |
21 | MOCK_METHOD1(finish, void(int)); | |
22 | ||
23 | void do_complete(int r) { | |
24 | C_SaferCond::complete(r); | |
25 | } | |
26 | }; | |
27 | ||
28 | } // anonymous namespace | |
29 | ||
30 | namespace util { | |
31 | ||
32 | inline ImageCtx *get_image_ctx(MockImageCtx *image_ctx) { | |
33 | return image_ctx->image_ctx; | |
34 | } | |
35 | ||
36 | } // namespace util | |
37 | } // namespace librbd | |
38 | ||
39 | #include "librbd/cache/pwl/AbstractWriteLog.cc" | |
40 | #include "librbd/cache/pwl/ssd/WriteLog.cc" | |
41 | template class librbd::cache::pwl::ssd::WriteLog<librbd::MockImageCtx>; | |
42 | ||
43 | // template definitions | |
44 | #include "librbd/cache/ImageWriteback.cc" | |
45 | #include "librbd/cache/pwl/ImageCacheState.cc" | |
46 | #include "librbd/cache/pwl/Request.cc" | |
47 | #include "librbd/plugin/Api.cc" | |
48 | #include "librbd/cache/pwl/ssd/Request.cc" | |
49 | ||
50 | namespace librbd { | |
51 | namespace cache { | |
52 | namespace pwl { | |
53 | ||
54 | using ::testing::_; | |
55 | using ::testing::DoDefault; | |
56 | using ::testing::InSequence; | |
57 | using ::testing::Invoke; | |
58 | ||
59 | typedef io::Extent Extent; | |
60 | typedef io::Extents Extents; | |
61 | ||
62 | struct TestMockCacheSSDWriteLog : public TestMockFixture { | |
63 | typedef librbd::cache::pwl::ssd::WriteLog<librbd::MockImageCtx> MockSSDWriteLog; | |
64 | typedef librbd::cache::pwl::ImageCacheState<librbd::MockImageCtx> MockImageCacheStateSSD; | |
65 | typedef librbd::cache::ImageWriteback<librbd::MockImageCtx> MockImageWriteback; | |
66 | typedef librbd::plugin::Api<librbd::MockImageCtx> MockApi; | |
67 | ||
68 | MockImageCacheStateSSD *get_cache_state( | |
69 | MockImageCtx& mock_image_ctx, MockApi& mock_api) { | |
70 | MockImageCacheStateSSD *ssd_state = new MockImageCacheStateSSD( | |
71 | &mock_image_ctx, mock_api); | |
72 | return ssd_state; | |
73 | } | |
74 | ||
75 | void validate_cache_state(librbd::ImageCtx *image_ctx, | |
76 | MockImageCacheStateSSD &state, | |
77 | bool present, bool empty, bool clean, | |
78 | string host, string path, | |
79 | uint64_t size) { | |
f67539c2 TL |
80 | ASSERT_EQ(present, state.present); |
81 | ASSERT_EQ(empty, state.empty); | |
82 | ASSERT_EQ(clean, state.clean); | |
83 | ||
84 | ASSERT_EQ(host, state.host); | |
85 | ASSERT_EQ(path, state.path); | |
86 | ASSERT_EQ(size, state.size); | |
f67539c2 TL |
87 | } |
88 | ||
89 | void expect_context_complete(MockContextSSD& mock_context, int r) { | |
90 | EXPECT_CALL(mock_context, complete(r)) | |
91 | .WillRepeatedly(Invoke([&mock_context](int r) { | |
92 | mock_context.do_complete(r); | |
93 | })); | |
94 | } | |
95 | ||
96 | void expect_metadata_set(MockImageCtx& mock_image_ctx) { | |
97 | EXPECT_CALL(*mock_image_ctx.operations, execute_metadata_set(_, _, _)) | |
98 | .WillRepeatedly(Invoke([](std::string key, std::string val, Context* ctx) { | |
99 | ctx->complete(0); | |
100 | })); | |
101 | } | |
102 | ||
103 | void expect_metadata_remove(MockImageCtx& mock_image_ctx) { | |
104 | EXPECT_CALL(*mock_image_ctx.operations, execute_metadata_remove(_, _)) | |
105 | .WillRepeatedly(Invoke([](std::string key, Context* ctx) { | |
106 | ctx->complete(0); | |
107 | })); | |
108 | } | |
109 | }; | |
110 | ||
111 | TEST_F(TestMockCacheSSDWriteLog, init_state_write) { | |
112 | librbd::ImageCtx *ictx; | |
113 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
114 | ||
115 | MockImageCtx mock_image_ctx(*ictx); | |
116 | MockApi mock_api; | |
117 | MockImageCacheStateSSD image_cache_state(&mock_image_ctx, mock_api); | |
118 | ||
119 | validate_cache_state(ictx, image_cache_state, false, true, true, "", "", 0); | |
120 | ||
121 | image_cache_state.empty = false; | |
122 | image_cache_state.clean = false; | |
2a845540 | 123 | ceph::mutex lock = ceph::make_mutex("MockImageCacheStateSSD lock"); |
f67539c2 TL |
124 | MockContextSSD finish_ctx; |
125 | expect_metadata_set(mock_image_ctx); | |
126 | expect_context_complete(finish_ctx, 0); | |
2a845540 TL |
127 | std::unique_lock locker(lock); |
128 | image_cache_state.write_image_cache_state(locker, &finish_ctx); | |
129 | ASSERT_FALSE(locker.owns_lock()); | |
f67539c2 TL |
130 | ASSERT_EQ(0, finish_ctx.wait()); |
131 | } | |
132 | ||
f67539c2 TL |
133 | TEST_F(TestMockCacheSSDWriteLog, init_state_json_write) { |
134 | librbd::ImageCtx *ictx; | |
135 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
136 | ||
137 | MockImageCtx mock_image_ctx(*ictx); | |
f67539c2 | 138 | MockApi mock_api; |
33c7a0ef | 139 | MockImageCacheStateSSD image_cache_state(&mock_image_ctx, mock_api); |
f67539c2 | 140 | |
33c7a0ef TL |
141 | string strf = "{ \"present\": true, \"empty\": false, \"clean\": false, \ |
142 | \"host\": \"testhost\", \ | |
143 | \"path\": \"/tmp\", \ | |
144 | \"mode\": \"ssd\", \ | |
145 | \"size\": 1024 }"; | |
146 | json_spirit::mValue json_root; | |
147 | ASSERT_TRUE(json_spirit::read(strf.c_str(), json_root)); | |
148 | ASSERT_TRUE(image_cache_state.init_from_metadata(json_root)); | |
f67539c2 TL |
149 | validate_cache_state(ictx, image_cache_state, true, false, false, |
150 | "testhost", "/tmp", 1024); | |
151 | ||
152 | MockContextSSD finish_ctx; | |
153 | expect_metadata_remove(mock_image_ctx); | |
154 | expect_context_complete(finish_ctx, 0); | |
155 | image_cache_state.clear_image_cache_state(&finish_ctx); | |
156 | ASSERT_EQ(0, finish_ctx.wait()); | |
157 | } | |
158 | ||
159 | TEST_F(TestMockCacheSSDWriteLog, init_shutdown) { | |
160 | librbd::ImageCtx *ictx; | |
161 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
162 | ||
163 | MockImageCtx mock_image_ctx(*ictx); | |
164 | MockImageWriteback mock_image_writeback(mock_image_ctx); | |
165 | MockApi mock_api; | |
166 | MockSSDWriteLog ssd( | |
167 | mock_image_ctx, get_cache_state(mock_image_ctx, mock_api), | |
168 | mock_image_writeback, mock_api); | |
169 | MockContextSSD finish_ctx1; | |
170 | expect_op_work_queue(mock_image_ctx); | |
171 | expect_metadata_set(mock_image_ctx); | |
172 | ||
173 | expect_context_complete(finish_ctx1, 0); | |
174 | ssd.init(&finish_ctx1); | |
175 | ASSERT_EQ(0, finish_ctx1.wait()); | |
176 | ||
177 | MockContextSSD finish_ctx2; | |
178 | expect_context_complete(finish_ctx2, 0); | |
179 | ssd.shut_down(&finish_ctx2); | |
180 | ASSERT_EQ(0, finish_ctx2.wait()); | |
181 | } | |
182 | ||
183 | TEST_F(TestMockCacheSSDWriteLog, write) { | |
184 | librbd::ImageCtx *ictx; | |
185 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
186 | ||
187 | MockImageCtx mock_image_ctx(*ictx); | |
188 | MockImageWriteback mock_image_writeback(mock_image_ctx); | |
189 | MockApi mock_api; | |
190 | MockSSDWriteLog ssd( | |
191 | mock_image_ctx, get_cache_state(mock_image_ctx, mock_api), | |
192 | mock_image_writeback, mock_api); | |
193 | ||
194 | MockContextSSD finish_ctx1; | |
195 | expect_op_work_queue(mock_image_ctx); | |
196 | expect_metadata_set(mock_image_ctx); | |
197 | expect_context_complete(finish_ctx1, 0); | |
198 | ssd.init(&finish_ctx1); | |
199 | ASSERT_EQ(0, finish_ctx1.wait()); | |
200 | ||
201 | MockContextSSD finish_ctx2; | |
202 | expect_context_complete(finish_ctx2, 0); | |
203 | Extents image_extents{{0, 4096}}; | |
204 | bufferlist bl; | |
205 | bl.append(std::string(4096, '1')); | |
206 | int fadvise_flags = 0; | |
207 | ssd.write(std::move(image_extents), std::move(bl), fadvise_flags, &finish_ctx2); | |
208 | ASSERT_EQ(0, finish_ctx2.wait()); | |
209 | ||
210 | MockContextSSD finish_ctx3; | |
211 | expect_context_complete(finish_ctx3, 0); | |
212 | ssd.shut_down(&finish_ctx3); | |
213 | ASSERT_EQ(0, finish_ctx3.wait()); | |
214 | } | |
215 | ||
216 | TEST_F(TestMockCacheSSDWriteLog, read_hit_ssd_cache) { | |
217 | librbd::ImageCtx *ictx; | |
218 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
219 | ||
220 | MockImageCtx mock_image_ctx(*ictx); | |
221 | MockImageWriteback mock_image_writeback(mock_image_ctx); | |
222 | MockApi mock_api; | |
223 | MockSSDWriteLog ssd( | |
224 | mock_image_ctx, get_cache_state(mock_image_ctx, mock_api), | |
225 | mock_image_writeback, mock_api); | |
226 | expect_op_work_queue(mock_image_ctx); | |
227 | expect_metadata_set(mock_image_ctx); | |
228 | ||
229 | MockContextSSD finish_ctx1; | |
230 | expect_context_complete(finish_ctx1, 0); | |
231 | ssd.init(&finish_ctx1); | |
232 | ASSERT_EQ(0, finish_ctx1.wait()); | |
233 | ||
234 | MockContextSSD finish_ctx2; | |
235 | expect_context_complete(finish_ctx2, 0); | |
236 | Extents image_extents{{0, 4096}}; | |
237 | bufferlist bl; | |
238 | bl.append(std::string(4096, '1')); | |
239 | bufferlist bl_copy = bl; | |
240 | int fadvise_flags = 0; | |
241 | ssd.write(std::move(image_extents), std::move(bl), | |
242 | fadvise_flags, &finish_ctx2); | |
243 | ASSERT_EQ(0, finish_ctx2.wait()); | |
244 | ||
245 | MockContextSSD finish_ctx_read; | |
246 | expect_context_complete(finish_ctx_read, 0); | |
247 | Extents image_extents_read{{0, 4096}}; | |
248 | bufferlist read_bl; | |
249 | ssd.read(std::move(image_extents_read), &read_bl, | |
250 | fadvise_flags, &finish_ctx_read); | |
251 | ASSERT_EQ(0, finish_ctx_read.wait()); | |
252 | ASSERT_EQ(4096, read_bl.length()); | |
253 | ASSERT_TRUE(bl_copy.contents_equal(read_bl)); | |
254 | ||
255 | MockContextSSD finish_ctx3; | |
256 | expect_context_complete(finish_ctx3, 0); | |
257 | ssd.shut_down(&finish_ctx3); | |
258 | ASSERT_EQ(0, finish_ctx3.wait()); | |
259 | } | |
260 | ||
261 | TEST_F(TestMockCacheSSDWriteLog, read_hit_part_ssd_cache) { | |
262 | librbd::ImageCtx *ictx; | |
263 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
264 | ||
265 | MockImageCtx mock_image_ctx(*ictx); | |
266 | MockImageWriteback mock_image_writeback(mock_image_ctx); | |
267 | MockApi mock_api; | |
268 | MockSSDWriteLog ssd( | |
269 | mock_image_ctx, get_cache_state(mock_image_ctx, mock_api), | |
270 | mock_image_writeback, mock_api); | |
271 | expect_op_work_queue(mock_image_ctx); | |
272 | expect_metadata_set(mock_image_ctx); | |
273 | ||
274 | MockContextSSD finish_ctx1; | |
275 | expect_context_complete(finish_ctx1, 0); | |
276 | ssd.init(&finish_ctx1); | |
277 | ASSERT_EQ(0, finish_ctx1.wait()); | |
278 | ||
279 | MockContextSSD finish_ctx2; | |
280 | expect_context_complete(finish_ctx2, 0); | |
281 | Extents image_extents{{0, 8192}}; | |
282 | bufferlist bl; | |
283 | bl.append(std::string(8192, '1')); | |
284 | bufferlist bl_copy = bl; | |
285 | int fadvise_flags = 0; | |
286 | ssd.write(std::move(image_extents), std::move(bl), | |
287 | fadvise_flags, &finish_ctx2); | |
288 | ASSERT_EQ(0, finish_ctx2.wait()); | |
289 | ||
290 | MockContextSSD finish_ctx_read; | |
291 | Extents image_extents_read{{4096, 4096}}; | |
292 | bufferlist hit_bl; | |
293 | bl_copy.begin(4095).copy(4096, hit_bl); | |
294 | expect_context_complete(finish_ctx_read, 0); | |
295 | bufferlist read_bl; | |
296 | ssd.read(std::move(image_extents_read), &read_bl, | |
297 | fadvise_flags, &finish_ctx_read); | |
298 | ASSERT_EQ(0, finish_ctx_read.wait()); | |
299 | ASSERT_EQ(4096, read_bl.length()); | |
300 | bufferlist read_bl_hit; | |
301 | read_bl.begin(0).copy(4096, read_bl_hit); | |
302 | ASSERT_TRUE(hit_bl.contents_equal(read_bl_hit)); | |
303 | ||
304 | MockContextSSD finish_ctx3; | |
305 | expect_context_complete(finish_ctx3, 0); | |
306 | ssd.shut_down(&finish_ctx3); | |
307 | ASSERT_EQ(0, finish_ctx3.wait()); | |
308 | } | |
309 | ||
310 | TEST_F(TestMockCacheSSDWriteLog, read_miss_ssd_cache) { | |
311 | librbd::ImageCtx *ictx; | |
312 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
313 | ||
314 | MockImageCtx mock_image_ctx(*ictx); | |
315 | MockImageWriteback mock_image_writeback(mock_image_ctx); | |
316 | MockApi mock_api; | |
317 | MockSSDWriteLog ssd( | |
318 | mock_image_ctx, get_cache_state(mock_image_ctx, mock_api), | |
319 | mock_image_writeback, mock_api); | |
320 | expect_op_work_queue(mock_image_ctx); | |
321 | expect_metadata_set(mock_image_ctx); | |
322 | ||
323 | MockContextSSD finish_ctx1; | |
324 | expect_context_complete(finish_ctx1, 0); | |
325 | ssd.init(&finish_ctx1); | |
326 | ASSERT_EQ(0, finish_ctx1.wait()); | |
327 | ||
328 | MockContextSSD finish_ctx2; | |
329 | expect_context_complete(finish_ctx2, 0); | |
330 | Extents image_extents{{0, 4096}}; | |
331 | bufferlist bl; | |
332 | bl.append(std::string(4096, '1')); | |
333 | int fadvise_flags = 0; | |
334 | ssd.write(std::move(image_extents), std::move(bl), | |
335 | fadvise_flags, &finish_ctx2); | |
336 | ASSERT_EQ(0, finish_ctx2.wait()); | |
337 | ||
338 | MockContextSSD finish_ctx_read; | |
339 | Extents image_extents_read{{4096, 4096}}; | |
340 | expect_context_complete(finish_ctx_read, 4096); | |
341 | bufferlist read_bl; | |
342 | ASSERT_EQ(0, read_bl.length()); | |
343 | ssd.read(std::move(image_extents_read), &read_bl, | |
344 | fadvise_flags, &finish_ctx_read); | |
345 | ASSERT_EQ(4096, finish_ctx_read.wait()); | |
346 | ASSERT_EQ(4096, read_bl.length()); | |
347 | ||
348 | MockContextSSD finish_ctx3; | |
349 | expect_context_complete(finish_ctx3, 0); | |
350 | ssd.shut_down(&finish_ctx3); | |
351 | ASSERT_EQ(0, finish_ctx3.wait()); | |
352 | } | |
353 | ||
354 | TEST_F(TestMockCacheSSDWriteLog, compare_and_write_compare_matched) { | |
355 | librbd::ImageCtx *ictx; | |
356 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
357 | ||
358 | MockImageCtx mock_image_ctx(*ictx); | |
359 | MockImageWriteback mock_image_writeback(mock_image_ctx); | |
360 | MockApi mock_api; | |
361 | MockSSDWriteLog ssd( | |
362 | mock_image_ctx, get_cache_state(mock_image_ctx, mock_api), | |
363 | mock_image_writeback, mock_api); | |
364 | expect_op_work_queue(mock_image_ctx); | |
365 | expect_metadata_set(mock_image_ctx); | |
366 | ||
367 | MockContextSSD finish_ctx1; | |
368 | expect_context_complete(finish_ctx1, 0); | |
369 | ssd.init(&finish_ctx1); | |
370 | ASSERT_EQ(0, finish_ctx1.wait()); | |
371 | ||
372 | MockContextSSD finish_ctx2; | |
373 | expect_context_complete(finish_ctx2, 0); | |
374 | Extents image_extents{{0, 4096}}; | |
375 | bufferlist bl1; | |
376 | bl1.append(std::string(4096, '1')); | |
377 | bufferlist com_bl = bl1; | |
378 | int fadvise_flags = 0; | |
379 | ssd.write(std::move(image_extents), std::move(bl1), fadvise_flags, &finish_ctx2); | |
380 | ASSERT_EQ(0, finish_ctx2.wait()); | |
381 | ||
382 | MockContextSSD finish_ctx_cw; | |
383 | bufferlist bl2; | |
384 | bl2.append(std::string(4096, '2')); | |
385 | bufferlist bl2_copy = bl2; | |
386 | uint64_t mismatch_offset = -1; | |
387 | expect_context_complete(finish_ctx_cw, 0); | |
388 | ssd.compare_and_write({{0, 4096}}, std::move(com_bl), std::move(bl2), | |
389 | &mismatch_offset, fadvise_flags, &finish_ctx_cw); | |
390 | ASSERT_EQ(0, finish_ctx_cw.wait()); | |
391 | ASSERT_EQ(0, mismatch_offset); | |
392 | ||
393 | MockContextSSD finish_ctx_read; | |
394 | bufferlist read_bl; | |
395 | expect_context_complete(finish_ctx_read, 0); | |
396 | ssd.read({{0, 4096}}, &read_bl, fadvise_flags, &finish_ctx_read); | |
397 | ASSERT_EQ(0, finish_ctx_read.wait()); | |
398 | ASSERT_EQ(4096, read_bl.length()); | |
399 | ASSERT_TRUE(bl2_copy.contents_equal(read_bl)); | |
400 | ||
401 | MockContextSSD finish_ctx3; | |
402 | expect_context_complete(finish_ctx3, 0); | |
403 | ssd.shut_down(&finish_ctx3); | |
404 | ||
405 | ASSERT_EQ(0, finish_ctx3.wait()); | |
406 | } | |
407 | ||
408 | TEST_F(TestMockCacheSSDWriteLog, compare_and_write_compare_failed) { | |
409 | librbd::ImageCtx *ictx; | |
410 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
411 | ||
412 | MockImageCtx mock_image_ctx(*ictx); | |
413 | MockImageWriteback mock_image_writeback(mock_image_ctx); | |
414 | MockApi mock_api; | |
415 | MockSSDWriteLog ssd( | |
416 | mock_image_ctx, get_cache_state(mock_image_ctx, mock_api), | |
417 | mock_image_writeback, mock_api); | |
418 | expect_op_work_queue(mock_image_ctx); | |
419 | expect_metadata_set(mock_image_ctx); | |
420 | ||
421 | MockContextSSD finish_ctx1; | |
422 | expect_context_complete(finish_ctx1, 0); | |
423 | ssd.init(&finish_ctx1); | |
424 | ASSERT_EQ(0, finish_ctx1.wait()); | |
425 | ||
426 | MockContextSSD finish_ctx2; | |
427 | expect_context_complete(finish_ctx2, 0); | |
428 | Extents image_extents{{0, 4096}}; | |
429 | bufferlist bl1; | |
430 | bl1.append(std::string(4096, '1')); | |
431 | bufferlist bl1_copy = bl1; | |
432 | int fadvise_flags = 0; | |
433 | ssd.write(std::move(image_extents), std::move(bl1), fadvise_flags, &finish_ctx2); | |
434 | ASSERT_EQ(0, finish_ctx2.wait()); | |
435 | ||
436 | MockContextSSD finish_ctx_cw; | |
437 | bufferlist bl2; | |
438 | bl2.append(std::string(4096, '2')); | |
439 | bufferlist com_bl = bl2; | |
440 | uint64_t mismatch_offset = -1; | |
441 | expect_context_complete(finish_ctx_cw, -EILSEQ); | |
442 | ssd.compare_and_write({{0, 4096}}, std::move(com_bl), std::move(bl2), | |
443 | &mismatch_offset, fadvise_flags, &finish_ctx_cw); | |
444 | ASSERT_EQ(-EILSEQ, finish_ctx_cw.wait()); | |
445 | ASSERT_EQ(0, mismatch_offset); | |
446 | ||
447 | MockContextSSD finish_ctx_read; | |
448 | bufferlist read_bl; | |
449 | expect_context_complete(finish_ctx_read, 0); | |
450 | ssd.read({{0, 4096}}, &read_bl, fadvise_flags, &finish_ctx_read); | |
451 | ASSERT_EQ(0, finish_ctx_read.wait()); | |
452 | ASSERT_EQ(4096, read_bl.length()); | |
453 | ASSERT_TRUE(bl1_copy.contents_equal(read_bl)); | |
454 | ||
455 | MockContextSSD finish_ctx3; | |
456 | expect_context_complete(finish_ctx3, 0); | |
457 | ssd.shut_down(&finish_ctx3); | |
458 | ASSERT_EQ(0, finish_ctx3.wait()); | |
459 | } | |
460 | ||
461 | TEST_F(TestMockCacheSSDWriteLog, writesame) { | |
462 | librbd::ImageCtx *ictx; | |
463 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
464 | ||
465 | MockImageCtx mock_image_ctx(*ictx); | |
466 | MockImageWriteback mock_image_writeback(mock_image_ctx); | |
467 | MockApi mock_api; | |
468 | MockSSDWriteLog ssd( | |
469 | mock_image_ctx, get_cache_state(mock_image_ctx, mock_api), | |
470 | mock_image_writeback, mock_api); | |
471 | expect_op_work_queue(mock_image_ctx); | |
472 | expect_metadata_set(mock_image_ctx); | |
473 | ||
474 | MockContextSSD finish_ctx1; | |
475 | expect_context_complete(finish_ctx1, 0); | |
476 | ssd.init(&finish_ctx1); | |
477 | ASSERT_EQ(0, finish_ctx1.wait()); | |
478 | ||
479 | MockContextSSD finish_ctx2; | |
480 | expect_context_complete(finish_ctx2, 0); | |
481 | bufferlist bl, test_bl; | |
482 | bl.append(std::string(512, '1')); | |
483 | test_bl.append(std::string(4096, '1')); | |
484 | int fadvise_flags = 0; | |
485 | ssd.writesame(0, 4096, std::move(bl), fadvise_flags, &finish_ctx2); | |
486 | ASSERT_EQ(0, finish_ctx2.wait()); | |
487 | ||
488 | MockContextSSD finish_ctx_read; | |
489 | bufferlist read_bl; | |
490 | expect_context_complete(finish_ctx_read, 0); | |
491 | ssd.read({{0, 4096}}, &read_bl, fadvise_flags, &finish_ctx_read); | |
492 | ASSERT_EQ(0, finish_ctx_read.wait()); | |
493 | ASSERT_EQ(4096, read_bl.length()); | |
494 | ASSERT_TRUE(test_bl.contents_equal(read_bl)); | |
495 | ||
496 | MockContextSSD finish_ctx3; | |
497 | expect_context_complete(finish_ctx3, 0); | |
498 | ssd.shut_down(&finish_ctx3); | |
499 | ||
500 | ASSERT_EQ(0, finish_ctx3.wait()); | |
501 | } | |
502 | ||
503 | TEST_F(TestMockCacheSSDWriteLog, discard) { | |
504 | librbd::ImageCtx *ictx; | |
505 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
506 | ||
507 | MockImageCtx mock_image_ctx(*ictx); | |
508 | MockImageWriteback mock_image_writeback(mock_image_ctx); | |
509 | MockApi mock_api; | |
510 | MockSSDWriteLog ssd( | |
511 | mock_image_ctx, get_cache_state(mock_image_ctx, mock_api), | |
512 | mock_image_writeback, mock_api); | |
513 | expect_op_work_queue(mock_image_ctx); | |
514 | expect_metadata_set(mock_image_ctx); | |
515 | ||
516 | MockContextSSD finish_ctx1; | |
517 | expect_context_complete(finish_ctx1, 0); | |
518 | ssd.init(&finish_ctx1); | |
519 | ASSERT_EQ(0, finish_ctx1.wait()); | |
520 | ||
521 | MockContextSSD finish_ctx2; | |
522 | expect_context_complete(finish_ctx2, 0); | |
523 | Extents image_extents{{0, 4096}}; | |
524 | bufferlist bl; | |
525 | bl.append(std::string(4096, '1')); | |
526 | bufferlist bl_copy = bl; | |
527 | int fadvise_flags = 0; | |
528 | ssd.write(std::move(image_extents), std::move(bl), fadvise_flags, &finish_ctx2); | |
529 | ASSERT_EQ(0, finish_ctx2.wait()); | |
530 | ||
531 | MockContextSSD finish_ctx_discard; | |
532 | expect_context_complete(finish_ctx_discard, 0); | |
533 | ssd.discard(0, 4096, 1, &finish_ctx_discard); | |
534 | ASSERT_EQ(0, finish_ctx_discard.wait()); | |
535 | ||
536 | MockContextSSD finish_ctx_read; | |
537 | bufferlist read_bl; | |
538 | expect_context_complete(finish_ctx_read, 0); | |
539 | ssd.read({{0, 4096}}, &read_bl, fadvise_flags, &finish_ctx_read); | |
540 | ASSERT_EQ(0, finish_ctx_read.wait()); | |
541 | ASSERT_EQ(4096, read_bl.length()); | |
542 | ASSERT_TRUE(read_bl.is_zero()); | |
543 | ||
544 | MockContextSSD finish_ctx3; | |
545 | expect_context_complete(finish_ctx3, 0); | |
546 | ssd.shut_down(&finish_ctx3); | |
547 | ||
548 | ASSERT_EQ(0, finish_ctx3.wait()); | |
549 | } | |
550 | ||
551 | TEST_F(TestMockCacheSSDWriteLog, invalidate) { | |
552 | librbd::ImageCtx *ictx; | |
553 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
554 | ||
555 | MockImageCtx mock_image_ctx(*ictx); | |
556 | MockImageWriteback mock_image_writeback(mock_image_ctx); | |
557 | MockApi mock_api; | |
558 | MockSSDWriteLog ssd( | |
559 | mock_image_ctx, get_cache_state(mock_image_ctx, mock_api), | |
560 | mock_image_writeback, mock_api); | |
561 | expect_op_work_queue(mock_image_ctx); | |
562 | expect_metadata_set(mock_image_ctx); | |
563 | ||
564 | MockContextSSD finish_ctx1; | |
565 | expect_context_complete(finish_ctx1, 0); | |
566 | ssd.init(&finish_ctx1); | |
567 | ASSERT_EQ(0, finish_ctx1.wait()); | |
568 | ||
569 | MockContextSSD finish_ctx2; | |
570 | expect_context_complete(finish_ctx2, 0); | |
571 | Extents image_extents{{0, 4096}}; | |
572 | bufferlist bl; | |
573 | bl.append(std::string(4096, '1')); | |
574 | bufferlist bl_copy = bl; | |
575 | int fadvise_flags = 0; | |
576 | ssd.write(std::move(image_extents), std::move(bl), fadvise_flags, &finish_ctx2); | |
577 | ASSERT_EQ(0, finish_ctx2.wait()); | |
578 | ||
579 | MockContextSSD finish_ctx_invalidate; | |
580 | expect_context_complete(finish_ctx_invalidate, 0); | |
581 | ssd.invalidate(&finish_ctx_invalidate); | |
582 | ASSERT_EQ(0, finish_ctx_invalidate.wait()); | |
583 | ||
584 | MockContextSSD finish_ctx3; | |
585 | expect_context_complete(finish_ctx3, 0); | |
586 | ssd.shut_down(&finish_ctx3); | |
587 | ||
588 | ASSERT_EQ(0, finish_ctx3.wait()); | |
589 | } | |
590 | ||
591 | TEST_F(TestMockCacheSSDWriteLog, flush) { | |
592 | librbd::ImageCtx *ictx; | |
593 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
594 | ||
595 | MockImageCtx mock_image_ctx(*ictx); | |
596 | MockImageWriteback mock_image_writeback(mock_image_ctx); | |
597 | MockApi mock_api; | |
598 | MockSSDWriteLog ssd( | |
599 | mock_image_ctx, get_cache_state(mock_image_ctx, mock_api), | |
600 | mock_image_writeback, mock_api); | |
601 | ||
602 | expect_op_work_queue(mock_image_ctx); | |
603 | expect_metadata_set(mock_image_ctx); | |
604 | ||
605 | MockContextSSD finish_ctx1; | |
606 | expect_context_complete(finish_ctx1, 0); | |
607 | ssd.init(&finish_ctx1); | |
608 | ASSERT_EQ(0, finish_ctx1.wait()); | |
609 | ||
610 | MockContextSSD finish_ctx2; | |
611 | expect_context_complete(finish_ctx2, 0); | |
612 | Extents image_extents{{0, 4096}}; | |
613 | bufferlist bl; | |
614 | bl.append(std::string(4096, '1')); | |
615 | bufferlist bl_copy = bl; | |
616 | int fadvise_flags = 0; | |
617 | ssd.write(std::move(image_extents), std::move(bl), fadvise_flags, &finish_ctx2); | |
618 | ASSERT_EQ(0, finish_ctx2.wait()); | |
619 | ||
620 | MockContextSSD finish_ctx_flush; | |
621 | expect_context_complete(finish_ctx_flush, 0); | |
622 | ssd.flush(&finish_ctx_flush); | |
623 | ASSERT_EQ(0, finish_ctx_flush.wait()); | |
624 | ||
625 | MockContextSSD finish_ctx3; | |
626 | expect_context_complete(finish_ctx3, 0); | |
627 | ssd.shut_down(&finish_ctx3); | |
628 | ||
629 | ASSERT_EQ(0, finish_ctx3.wait()); | |
630 | } | |
631 | ||
632 | TEST_F(TestMockCacheSSDWriteLog, flush_source_shutdown) { | |
633 | librbd::ImageCtx *ictx; | |
634 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
635 | ||
636 | MockImageCtx mock_image_ctx(*ictx); | |
637 | MockImageWriteback mock_image_writeback(mock_image_ctx); | |
638 | MockApi mock_api; | |
639 | MockSSDWriteLog ssd( | |
640 | mock_image_ctx, get_cache_state(mock_image_ctx, mock_api), | |
641 | mock_image_writeback, mock_api); | |
642 | ||
643 | expect_op_work_queue(mock_image_ctx); | |
644 | expect_metadata_set(mock_image_ctx); | |
645 | ||
646 | MockContextSSD finish_ctx1; | |
647 | expect_context_complete(finish_ctx1, 0); | |
648 | ssd.init(&finish_ctx1); | |
649 | ASSERT_EQ(0, finish_ctx1.wait()); | |
650 | ||
651 | MockContextSSD finish_ctx2; | |
652 | expect_context_complete(finish_ctx2, 0); | |
653 | Extents image_extents{{0, 4096}}; | |
654 | bufferlist bl; | |
655 | bl.append(std::string(4096, '1')); | |
656 | int fadvise_flags = 0; | |
657 | ssd.write(std::move(image_extents), std::move(bl), fadvise_flags, &finish_ctx2); | |
658 | ASSERT_EQ(0, finish_ctx2.wait()); | |
659 | ||
660 | MockContextSSD finish_ctx_flush; | |
661 | expect_context_complete(finish_ctx_flush, 0); | |
662 | ssd.flush(io::FLUSH_SOURCE_SHUTDOWN, &finish_ctx_flush); | |
663 | ASSERT_EQ(0, finish_ctx_flush.wait()); | |
664 | ||
665 | MockContextSSD finish_ctx3; | |
666 | expect_context_complete(finish_ctx3, 0); | |
667 | ssd.shut_down(&finish_ctx3); | |
668 | ASSERT_EQ(0, finish_ctx3.wait()); | |
669 | } | |
670 | ||
671 | ||
672 | TEST_F(TestMockCacheSSDWriteLog, flush_source_internal) { | |
673 | librbd::ImageCtx *ictx; | |
674 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
675 | ||
676 | MockImageCtx mock_image_ctx(*ictx); | |
677 | MockImageWriteback mock_image_writeback(mock_image_ctx); | |
678 | MockApi mock_api; | |
679 | MockSSDWriteLog ssd( | |
680 | mock_image_ctx, get_cache_state(mock_image_ctx, mock_api), | |
681 | mock_image_writeback, mock_api); | |
682 | ||
683 | expect_op_work_queue(mock_image_ctx); | |
684 | expect_metadata_set(mock_image_ctx); | |
685 | ||
686 | MockContextSSD finish_ctx1; | |
687 | expect_context_complete(finish_ctx1, 0); | |
688 | ssd.init(&finish_ctx1); | |
689 | ASSERT_EQ(0, finish_ctx1.wait()); | |
690 | ||
691 | MockContextSSD finish_ctx2; | |
692 | expect_context_complete(finish_ctx2, 0); | |
693 | Extents image_extents{{0, 4096}}; | |
694 | bufferlist bl; | |
695 | bl.append(std::string(4096, '1')); | |
696 | int fadvise_flags = 0; | |
697 | ssd.write(std::move(image_extents), std::move(bl), fadvise_flags, &finish_ctx2); | |
698 | ASSERT_EQ(0, finish_ctx2.wait()); | |
699 | ||
700 | MockContextSSD finish_ctx_flush; | |
701 | expect_context_complete(finish_ctx_flush, 0); | |
702 | ssd.flush(io::FLUSH_SOURCE_INTERNAL, &finish_ctx_flush); | |
703 | ASSERT_EQ(0, finish_ctx_flush.wait()); | |
704 | ||
705 | MockContextSSD finish_ctx3; | |
706 | expect_context_complete(finish_ctx3, 0); | |
707 | ssd.shut_down(&finish_ctx3); | |
708 | ASSERT_EQ(0, finish_ctx3.wait()); | |
709 | } | |
710 | ||
711 | TEST_F(TestMockCacheSSDWriteLog, flush_source_user) { | |
712 | librbd::ImageCtx *ictx; | |
713 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
714 | ||
715 | MockImageCtx mock_image_ctx(*ictx); | |
716 | MockImageWriteback mock_image_writeback(mock_image_ctx); | |
717 | MockApi mock_api; | |
718 | MockSSDWriteLog ssd( | |
719 | mock_image_ctx, get_cache_state(mock_image_ctx, mock_api), | |
720 | mock_image_writeback, mock_api); | |
721 | expect_op_work_queue(mock_image_ctx); | |
722 | expect_metadata_set(mock_image_ctx); | |
723 | ||
724 | MockContextSSD finish_ctx1; | |
725 | expect_context_complete(finish_ctx1, 0); | |
726 | ssd.init(&finish_ctx1); | |
727 | ASSERT_EQ(0, finish_ctx1.wait()); | |
728 | ||
729 | MockContextSSD finish_ctx2; | |
730 | expect_context_complete(finish_ctx2, 0); | |
731 | Extents image_extents{{0, 4096}}; | |
732 | bufferlist bl; | |
733 | bl.append(std::string(4096, '1')); | |
734 | int fadvise_flags = 0; | |
735 | ssd.write(std::move(image_extents), std::move(bl), fadvise_flags, &finish_ctx2); | |
736 | ASSERT_EQ(0, finish_ctx2.wait()); | |
737 | ||
738 | usleep(10000); | |
739 | MockContextSSD finish_ctx_flush; | |
740 | expect_context_complete(finish_ctx_flush, 0); | |
741 | ssd.flush(io::FLUSH_SOURCE_USER, &finish_ctx_flush); | |
742 | ASSERT_EQ(0, finish_ctx_flush.wait()); | |
743 | ||
744 | MockContextSSD finish_ctx3; | |
745 | expect_context_complete(finish_ctx3, 0); | |
746 | Extents image_extents2{{0, 4096}}; | |
747 | bufferlist bl2; | |
748 | bl2.append(std::string(4096, '1')); | |
749 | int fadvise_flags2 = 0; | |
750 | ssd.write(std::move(image_extents2), std::move(bl2), fadvise_flags2, &finish_ctx3); | |
751 | ASSERT_EQ(0, finish_ctx3.wait()); | |
752 | ||
753 | MockContextSSD finish_ctx4; | |
754 | expect_context_complete(finish_ctx4, 0); | |
755 | ssd.shut_down(&finish_ctx4); | |
756 | ASSERT_EQ(0, finish_ctx4.wait()); | |
757 | } | |
758 | ||
759 | } // namespace pwl | |
760 | } // namespace cache | |
761 | } // namespace librbd |