]>
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 | #include <stdio.h> | |
5 | #include <string.h> | |
6 | #include <iostream> | |
7 | #include <time.h> | |
8 | #include <fcntl.h> | |
9 | #include <unistd.h> | |
91327a77 | 10 | #include <random> |
7c673cae FG |
11 | #include <thread> |
12 | #include "global/global_init.h" | |
13 | #include "common/ceph_argparse.h" | |
14 | #include "include/stringify.h" | |
11fdf7f2 | 15 | #include "include/scope_guard.h" |
7c673cae FG |
16 | #include "common/errno.h" |
17 | #include <gtest/gtest.h> | |
18 | ||
19 | #include "os/bluestore/BlueFS.h" | |
20 | ||
11fdf7f2 | 21 | std::unique_ptr<char[]> gen_buffer(uint64_t size) |
7c673cae | 22 | { |
11fdf7f2 TL |
23 | std::unique_ptr<char[]> buffer = std::make_unique<char[]>(size); |
24 | std::independent_bits_engine<std::default_random_engine, CHAR_BIT, unsigned char> e; | |
25 | std::generate(buffer.get(), buffer.get()+size, std::ref(e)); | |
7c673cae FG |
26 | return buffer; |
27 | } | |
28 | ||
9f95a23c TL |
29 | class TempBdev { |
30 | public: | |
31 | TempBdev(uint64_t size) | |
32 | : path{get_temp_bdev(size)} | |
33 | {} | |
34 | ~TempBdev() { | |
35 | rm_temp_bdev(path); | |
36 | } | |
37 | const std::string path; | |
38 | private: | |
39 | static string get_temp_bdev(uint64_t size) | |
40 | { | |
41 | static int n = 0; | |
42 | string fn = "ceph_test_bluefs.tmp.block." + stringify(getpid()) | |
43 | + "." + stringify(++n); | |
44 | int fd = ::open(fn.c_str(), O_CREAT|O_RDWR|O_TRUNC, 0644); | |
45 | ceph_assert(fd >= 0); | |
46 | int r = ::ftruncate(fd, size); | |
47 | ceph_assert(r >= 0); | |
48 | ::close(fd); | |
49 | return fn; | |
50 | } | |
51 | static void rm_temp_bdev(string f) | |
52 | { | |
53 | ::unlink(f.c_str()); | |
54 | } | |
55 | }; | |
7c673cae FG |
56 | |
57 | TEST(BlueFS, mkfs) { | |
58 | uint64_t size = 1048576 * 128; | |
9f95a23c | 59 | TempBdev bdev{size}; |
7c673cae FG |
60 | uuid_d fsid; |
61 | BlueFS fs(g_ceph_context); | |
9f95a23c | 62 | ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false)); |
7c673cae | 63 | fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576); |
9f95a23c | 64 | ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false })); |
7c673cae FG |
65 | } |
66 | ||
67 | TEST(BlueFS, mkfs_mount) { | |
68 | uint64_t size = 1048576 * 128; | |
9f95a23c | 69 | TempBdev bdev{size}; |
7c673cae | 70 | BlueFS fs(g_ceph_context); |
9f95a23c | 71 | ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false)); |
7c673cae FG |
72 | fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576); |
73 | uuid_d fsid; | |
9f95a23c | 74 | ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false })); |
7c673cae | 75 | ASSERT_EQ(0, fs.mount()); |
9f95a23c | 76 | ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false })); |
7c673cae FG |
77 | ASSERT_EQ(fs.get_total(BlueFS::BDEV_DB), size - 1048576); |
78 | ASSERT_LT(fs.get_free(BlueFS::BDEV_DB), size - 1048576); | |
79 | fs.umount(); | |
9f95a23c TL |
80 | } |
81 | ||
82 | TEST(BlueFS, mkfs_mount_duplicate_gift) { | |
83 | uint64_t size = 1048576 * 128; | |
84 | TempBdev bdev{ size }; | |
e306af50 | 85 | bluefs_extent_t dup_ext; |
9f95a23c TL |
86 | { |
87 | BlueFS fs(g_ceph_context); | |
88 | ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false)); | |
89 | fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576); | |
90 | uuid_d fsid; | |
91 | ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false })); | |
92 | ASSERT_EQ(0, fs.mount()); | |
93 | ||
94 | { | |
95 | BlueFS::FileWriter *h; | |
96 | ASSERT_EQ(0, fs.mkdir("dir")); | |
97 | ASSERT_EQ(0, fs.open_for_write("dir", "file1", &h, false)); | |
98 | h->append("foo", 3); | |
99 | h->append("bar", 3); | |
100 | h->append("baz", 3); | |
101 | fs.fsync(h); | |
e306af50 TL |
102 | ceph_assert(h->file->fnode.extents.size() > 0); |
103 | dup_ext = h->file->fnode.extents[0]; | |
104 | ceph_assert(dup_ext.bdev == BlueFS::BDEV_DB); | |
9f95a23c TL |
105 | fs.close_writer(h); |
106 | } | |
107 | ||
108 | fs.umount(); | |
109 | } | |
110 | ||
111 | { | |
112 | BlueFS fs(g_ceph_context); | |
113 | ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false)); | |
114 | ASSERT_EQ(0, fs.mount()); | |
115 | // free allocation presumably allocated for file1 | |
e306af50 TL |
116 | std::cout << "duplicate extent: " << std::hex |
117 | << dup_ext.offset << "~" << dup_ext.length | |
118 | << std::dec << std::endl; | |
119 | fs.debug_inject_duplicate_gift(BlueFS::BDEV_DB, dup_ext.offset, dup_ext.length); | |
9f95a23c TL |
120 | { |
121 | // overwrite file1 with file2 | |
122 | BlueFS::FileWriter *h; | |
123 | ASSERT_EQ(0, fs.open_for_write("dir", "file2", &h, false)); | |
124 | h->append("foo", 3); | |
125 | h->append("bar", 3); | |
126 | h->append("baz", 3); | |
127 | fs.fsync(h); | |
128 | fs.close_writer(h); | |
129 | } | |
130 | fs.umount(); | |
131 | } | |
132 | ||
133 | g_ceph_context->_conf.set_val_or_die("bluefs_log_replay_check_allocations", "true"); | |
134 | g_ceph_context->_conf.apply_changes(nullptr); | |
135 | ||
136 | { | |
137 | // this should fail | |
138 | BlueFS fs(g_ceph_context); | |
139 | ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false)); | |
140 | ASSERT_NE(0, fs.mount()); | |
141 | } | |
7c673cae FG |
142 | } |
143 | ||
144 | TEST(BlueFS, write_read) { | |
145 | uint64_t size = 1048576 * 128; | |
9f95a23c | 146 | TempBdev bdev{size}; |
7c673cae | 147 | BlueFS fs(g_ceph_context); |
9f95a23c | 148 | ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false)); |
7c673cae FG |
149 | fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576); |
150 | uuid_d fsid; | |
9f95a23c | 151 | ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false })); |
7c673cae | 152 | ASSERT_EQ(0, fs.mount()); |
9f95a23c | 153 | ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false })); |
7c673cae FG |
154 | { |
155 | BlueFS::FileWriter *h; | |
156 | ASSERT_EQ(0, fs.mkdir("dir")); | |
157 | ASSERT_EQ(0, fs.open_for_write("dir", "file", &h, false)); | |
158 | h->append("foo", 3); | |
159 | h->append("bar", 3); | |
160 | h->append("baz", 3); | |
161 | fs.fsync(h); | |
162 | fs.close_writer(h); | |
163 | } | |
164 | { | |
165 | BlueFS::FileReader *h; | |
166 | ASSERT_EQ(0, fs.open_for_read("dir", "file", &h)); | |
167 | bufferlist bl; | |
168 | BlueFS::FileReaderBuffer buf(4096); | |
169 | ASSERT_EQ(9, fs.read(h, &buf, 0, 1024, &bl, NULL)); | |
170 | ASSERT_EQ(0, strncmp("foobarbaz", bl.c_str(), 9)); | |
171 | delete h; | |
172 | } | |
173 | fs.umount(); | |
7c673cae FG |
174 | } |
175 | ||
176 | TEST(BlueFS, small_appends) { | |
177 | uint64_t size = 1048576 * 128; | |
9f95a23c | 178 | TempBdev bdev{size}; |
7c673cae | 179 | BlueFS fs(g_ceph_context); |
9f95a23c | 180 | ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false)); |
7c673cae FG |
181 | fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576); |
182 | uuid_d fsid; | |
9f95a23c | 183 | ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false })); |
7c673cae | 184 | ASSERT_EQ(0, fs.mount()); |
9f95a23c | 185 | ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false })); |
7c673cae FG |
186 | { |
187 | BlueFS::FileWriter *h; | |
188 | ASSERT_EQ(0, fs.mkdir("dir")); | |
189 | ASSERT_EQ(0, fs.open_for_write("dir", "file", &h, false)); | |
190 | for (unsigned i = 0; i < 10000; ++i) { | |
191 | h->append("abcdeabcdeabcdeabcdeabcdeabc", 23); | |
192 | } | |
193 | fs.fsync(h); | |
194 | fs.close_writer(h); | |
195 | } | |
196 | { | |
197 | BlueFS::FileWriter *h; | |
198 | ASSERT_EQ(0, fs.open_for_write("dir", "file_sync", &h, false)); | |
199 | for (unsigned i = 0; i < 1000; ++i) { | |
200 | h->append("abcdeabcdeabcdeabcdeabcdeabc", 23); | |
31f18b77 | 201 | ASSERT_EQ(0, fs.fsync(h)); |
7c673cae FG |
202 | } |
203 | fs.close_writer(h); | |
204 | } | |
205 | fs.umount(); | |
7c673cae FG |
206 | } |
207 | ||
494da23a TL |
208 | TEST(BlueFS, very_large_write) { |
209 | // we'll write a ~3G file, so allocate more than that for the whole fs | |
210 | uint64_t size = 1048576 * 1024 * 8ull; | |
9f95a23c | 211 | TempBdev bdev{size}; |
494da23a TL |
212 | BlueFS fs(g_ceph_context); |
213 | ||
214 | bool old = g_ceph_context->_conf.get_val<bool>("bluefs_buffered_io"); | |
215 | g_ceph_context->_conf.set_val("bluefs_buffered_io", "false"); | |
216 | ||
9f95a23c | 217 | ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false)); |
494da23a TL |
218 | fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576); |
219 | uuid_d fsid; | |
9f95a23c | 220 | ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false })); |
494da23a | 221 | ASSERT_EQ(0, fs.mount()); |
9f95a23c | 222 | ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false })); |
494da23a TL |
223 | char buf[1048571]; // this is biggish, but intentionally not evenly aligned |
224 | for (unsigned i = 0; i < sizeof(buf); ++i) { | |
225 | buf[i] = i; | |
226 | } | |
227 | { | |
228 | BlueFS::FileWriter *h; | |
229 | ASSERT_EQ(0, fs.mkdir("dir")); | |
230 | ASSERT_EQ(0, fs.open_for_write("dir", "bigfile", &h, false)); | |
231 | for (unsigned i = 0; i < 3*1024*1048576ull / sizeof(buf); ++i) { | |
232 | h->append(buf, sizeof(buf)); | |
233 | } | |
234 | fs.fsync(h); | |
235 | fs.close_writer(h); | |
236 | } | |
237 | { | |
238 | BlueFS::FileReader *h; | |
239 | ASSERT_EQ(0, fs.open_for_read("dir", "bigfile", &h)); | |
240 | bufferlist bl; | |
241 | BlueFS::FileReaderBuffer readbuf(10485760); | |
242 | for (unsigned i = 0; i < 3*1024*1048576ull / sizeof(buf); ++i) { | |
243 | bl.clear(); | |
244 | fs.read(h, &readbuf, i * sizeof(buf), sizeof(buf), &bl, NULL); | |
245 | int r = memcmp(buf, bl.c_str(), sizeof(buf)); | |
246 | if (r) { | |
247 | cerr << "read got mismatch at offset " << i*sizeof(buf) << " r " << r | |
248 | << std::endl; | |
249 | } | |
250 | ASSERT_EQ(0, r); | |
251 | } | |
252 | delete h; | |
253 | } | |
254 | fs.umount(); | |
255 | ||
256 | g_ceph_context->_conf.set_val("bluefs_buffered_io", stringify((int)old)); | |
494da23a TL |
257 | } |
258 | ||
7c673cae FG |
259 | #define ALLOC_SIZE 4096 |
260 | ||
261 | void write_data(BlueFS &fs, uint64_t rationed_bytes) | |
262 | { | |
7c673cae FG |
263 | int j=0, r=0; |
264 | uint64_t written_bytes = 0; | |
265 | rationed_bytes -= ALLOC_SIZE; | |
266 | stringstream ss; | |
267 | string dir = "dir."; | |
268 | ss << std::this_thread::get_id(); | |
269 | dir.append(ss.str()); | |
270 | dir.append("."); | |
271 | dir.append(to_string(j)); | |
272 | ASSERT_EQ(0, fs.mkdir(dir)); | |
273 | while (1) { | |
274 | string file = "file."; | |
275 | file.append(to_string(j)); | |
11fdf7f2 | 276 | BlueFS::FileWriter *h; |
7c673cae | 277 | ASSERT_EQ(0, fs.open_for_write(dir, file, &h, false)); |
11fdf7f2 TL |
278 | ASSERT_NE(nullptr, h); |
279 | auto sg = make_scope_guard([&fs, h] { fs.close_writer(h); }); | |
7c673cae | 280 | bufferlist bl; |
11fdf7f2 TL |
281 | std::unique_ptr<char[]> buf = gen_buffer(ALLOC_SIZE); |
282 | bufferptr bp = buffer::claim_char(ALLOC_SIZE, buf.get()); | |
7c673cae FG |
283 | bl.push_back(bp); |
284 | h->append(bl.c_str(), bl.length()); | |
285 | r = fs.fsync(h); | |
286 | if (r < 0) { | |
7c673cae FG |
287 | break; |
288 | } | |
11fdf7f2 | 289 | written_bytes += g_conf()->bluefs_alloc_size; |
7c673cae | 290 | j++; |
11fdf7f2 | 291 | if ((rationed_bytes - written_bytes) <= g_conf()->bluefs_alloc_size) { |
7c673cae FG |
292 | break; |
293 | } | |
294 | } | |
295 | } | |
296 | ||
297 | void create_single_file(BlueFS &fs) | |
298 | { | |
299 | BlueFS::FileWriter *h; | |
300 | stringstream ss; | |
301 | string dir = "dir.test"; | |
302 | ASSERT_EQ(0, fs.mkdir(dir)); | |
303 | string file = "testfile"; | |
304 | ASSERT_EQ(0, fs.open_for_write(dir, file, &h, false)); | |
305 | bufferlist bl; | |
11fdf7f2 TL |
306 | std::unique_ptr<char[]> buf = gen_buffer(ALLOC_SIZE); |
307 | bufferptr bp = buffer::claim_char(ALLOC_SIZE, buf.get()); | |
7c673cae FG |
308 | bl.push_back(bp); |
309 | h->append(bl.c_str(), bl.length()); | |
310 | fs.fsync(h); | |
311 | fs.close_writer(h); | |
312 | } | |
313 | ||
314 | void write_single_file(BlueFS &fs, uint64_t rationed_bytes) | |
315 | { | |
7c673cae | 316 | stringstream ss; |
11fdf7f2 TL |
317 | const string dir = "dir.test"; |
318 | const string file = "testfile"; | |
7c673cae FG |
319 | uint64_t written_bytes = 0; |
320 | rationed_bytes -= ALLOC_SIZE; | |
321 | while (1) { | |
11fdf7f2 | 322 | BlueFS::FileWriter *h; |
7c673cae | 323 | ASSERT_EQ(0, fs.open_for_write(dir, file, &h, false)); |
11fdf7f2 TL |
324 | ASSERT_NE(nullptr, h); |
325 | auto sg = make_scope_guard([&fs, h] { fs.close_writer(h); }); | |
7c673cae | 326 | bufferlist bl; |
11fdf7f2 TL |
327 | std::unique_ptr<char[]> buf = gen_buffer(ALLOC_SIZE); |
328 | bufferptr bp = buffer::claim_char(ALLOC_SIZE, buf.get()); | |
7c673cae FG |
329 | bl.push_back(bp); |
330 | h->append(bl.c_str(), bl.length()); | |
11fdf7f2 | 331 | int r = fs.fsync(h); |
7c673cae | 332 | if (r < 0) { |
7c673cae FG |
333 | break; |
334 | } | |
11fdf7f2 TL |
335 | written_bytes += g_conf()->bluefs_alloc_size; |
336 | if ((rationed_bytes - written_bytes) <= g_conf()->bluefs_alloc_size) { | |
7c673cae FG |
337 | break; |
338 | } | |
339 | } | |
340 | } | |
341 | ||
342 | bool writes_done = false; | |
343 | ||
344 | void sync_fs(BlueFS &fs) | |
345 | { | |
346 | while (1) { | |
347 | if (writes_done == true) | |
348 | break; | |
1911f103 | 349 | fs.sync_metadata(false); |
7c673cae FG |
350 | sleep(1); |
351 | } | |
352 | } | |
353 | ||
354 | ||
355 | void do_join(std::thread& t) | |
356 | { | |
357 | t.join(); | |
358 | } | |
359 | ||
360 | void join_all(std::vector<std::thread>& v) | |
361 | { | |
362 | std::for_each(v.begin(),v.end(),do_join); | |
363 | } | |
364 | ||
365 | #define NUM_WRITERS 3 | |
366 | #define NUM_SYNC_THREADS 1 | |
367 | ||
368 | #define NUM_SINGLE_FILE_WRITERS 1 | |
369 | #define NUM_MULTIPLE_FILE_WRITERS 2 | |
370 | ||
371 | TEST(BlueFS, test_flush_1) { | |
372 | uint64_t size = 1048576 * 128; | |
9f95a23c | 373 | TempBdev bdev{size}; |
11fdf7f2 | 374 | g_ceph_context->_conf.set_val( |
7c673cae FG |
375 | "bluefs_alloc_size", |
376 | "65536"); | |
11fdf7f2 | 377 | g_ceph_context->_conf.apply_changes(nullptr); |
7c673cae FG |
378 | |
379 | BlueFS fs(g_ceph_context); | |
9f95a23c | 380 | ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false)); |
7c673cae FG |
381 | fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576); |
382 | uuid_d fsid; | |
9f95a23c | 383 | ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false })); |
7c673cae | 384 | ASSERT_EQ(0, fs.mount()); |
9f95a23c | 385 | ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false })); |
7c673cae FG |
386 | { |
387 | std::vector<std::thread> write_thread_multiple; | |
388 | uint64_t effective_size = size - (32 * 1048576); // leaving the last 32 MB for log compaction | |
389 | uint64_t per_thread_bytes = (effective_size/(NUM_MULTIPLE_FILE_WRITERS + NUM_SINGLE_FILE_WRITERS)); | |
390 | for (int i=0; i<NUM_MULTIPLE_FILE_WRITERS ; i++) { | |
391 | write_thread_multiple.push_back(std::thread(write_data, std::ref(fs), per_thread_bytes)); | |
392 | } | |
393 | ||
394 | create_single_file(fs); | |
395 | std::vector<std::thread> write_thread_single; | |
396 | for (int i=0; i<NUM_SINGLE_FILE_WRITERS; i++) { | |
397 | write_thread_single.push_back(std::thread(write_single_file, std::ref(fs), per_thread_bytes)); | |
398 | } | |
399 | ||
400 | join_all(write_thread_single); | |
401 | join_all(write_thread_multiple); | |
402 | } | |
403 | fs.umount(); | |
7c673cae FG |
404 | } |
405 | ||
406 | TEST(BlueFS, test_flush_2) { | |
407 | uint64_t size = 1048576 * 256; | |
9f95a23c | 408 | TempBdev bdev{size}; |
11fdf7f2 | 409 | g_ceph_context->_conf.set_val( |
7c673cae FG |
410 | "bluefs_alloc_size", |
411 | "65536"); | |
11fdf7f2 | 412 | g_ceph_context->_conf.apply_changes(nullptr); |
7c673cae FG |
413 | |
414 | BlueFS fs(g_ceph_context); | |
9f95a23c | 415 | ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false)); |
7c673cae FG |
416 | fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576); |
417 | uuid_d fsid; | |
9f95a23c | 418 | ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false })); |
7c673cae | 419 | ASSERT_EQ(0, fs.mount()); |
9f95a23c | 420 | ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false })); |
7c673cae FG |
421 | { |
422 | uint64_t effective_size = size - (128 * 1048576); // leaving the last 32 MB for log compaction | |
423 | uint64_t per_thread_bytes = (effective_size/(NUM_WRITERS)); | |
424 | std::vector<std::thread> write_thread_multiple; | |
425 | for (int i=0; i<NUM_WRITERS; i++) { | |
426 | write_thread_multiple.push_back(std::thread(write_data, std::ref(fs), per_thread_bytes)); | |
427 | } | |
428 | ||
429 | join_all(write_thread_multiple); | |
430 | } | |
431 | fs.umount(); | |
7c673cae FG |
432 | } |
433 | ||
434 | TEST(BlueFS, test_flush_3) { | |
435 | uint64_t size = 1048576 * 256; | |
9f95a23c | 436 | TempBdev bdev{size}; |
11fdf7f2 | 437 | g_ceph_context->_conf.set_val( |
7c673cae FG |
438 | "bluefs_alloc_size", |
439 | "65536"); | |
11fdf7f2 | 440 | g_ceph_context->_conf.apply_changes(nullptr); |
7c673cae FG |
441 | |
442 | BlueFS fs(g_ceph_context); | |
9f95a23c | 443 | ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false)); |
7c673cae FG |
444 | fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576); |
445 | uuid_d fsid; | |
9f95a23c | 446 | ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false })); |
7c673cae | 447 | ASSERT_EQ(0, fs.mount()); |
9f95a23c | 448 | ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false })); |
7c673cae FG |
449 | { |
450 | std::vector<std::thread> write_threads; | |
451 | uint64_t effective_size = size - (64 * 1048576); // leaving the last 11 MB for log compaction | |
452 | uint64_t per_thread_bytes = (effective_size/(NUM_WRITERS)); | |
453 | for (int i=0; i<NUM_WRITERS; i++) { | |
454 | write_threads.push_back(std::thread(write_data, std::ref(fs), per_thread_bytes)); | |
455 | } | |
456 | ||
457 | std::vector<std::thread> sync_threads; | |
458 | for (int i=0; i<NUM_SYNC_THREADS; i++) { | |
459 | sync_threads.push_back(std::thread(sync_fs, std::ref(fs))); | |
460 | } | |
461 | ||
462 | join_all(write_threads); | |
463 | writes_done = true; | |
464 | join_all(sync_threads); | |
465 | } | |
466 | fs.umount(); | |
7c673cae FG |
467 | } |
468 | ||
469 | TEST(BlueFS, test_simple_compaction_sync) { | |
11fdf7f2 | 470 | g_ceph_context->_conf.set_val( |
7c673cae FG |
471 | "bluefs_compact_log_sync", |
472 | "true"); | |
473 | uint64_t size = 1048576 * 128; | |
9f95a23c | 474 | TempBdev bdev{size}; |
7c673cae FG |
475 | |
476 | BlueFS fs(g_ceph_context); | |
9f95a23c | 477 | ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false)); |
7c673cae FG |
478 | fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576); |
479 | uuid_d fsid; | |
9f95a23c | 480 | ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false })); |
7c673cae | 481 | ASSERT_EQ(0, fs.mount()); |
9f95a23c | 482 | ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false })); |
7c673cae | 483 | { |
7c673cae FG |
484 | for (int i=0; i<10; i++) { |
485 | string dir = "dir."; | |
486 | dir.append(to_string(i)); | |
487 | ASSERT_EQ(0, fs.mkdir(dir)); | |
488 | for (int j=0; j<10; j++) { | |
489 | string file = "file."; | |
490 | file.append(to_string(j)); | |
11fdf7f2 | 491 | BlueFS::FileWriter *h; |
7c673cae | 492 | ASSERT_EQ(0, fs.open_for_write(dir, file, &h, false)); |
11fdf7f2 TL |
493 | ASSERT_NE(nullptr, h); |
494 | auto sg = make_scope_guard([&fs, h] { fs.close_writer(h); }); | |
7c673cae | 495 | bufferlist bl; |
11fdf7f2 TL |
496 | std::unique_ptr<char[]> buf = gen_buffer(4096); |
497 | bufferptr bp = buffer::claim_char(4096, buf.get()); | |
7c673cae FG |
498 | bl.push_back(bp); |
499 | h->append(bl.c_str(), bl.length()); | |
500 | fs.fsync(h); | |
7c673cae FG |
501 | } |
502 | } | |
503 | } | |
7c673cae FG |
504 | { |
505 | for (int i=0; i<10; i+=2) { | |
506 | string dir = "dir."; | |
507 | dir.append(to_string(i)); | |
11fdf7f2 | 508 | for (int j=0; j<10; j++) { |
7c673cae FG |
509 | string file = "file."; |
510 | file.append(to_string(j)); | |
511 | fs.unlink(dir, file); | |
1911f103 | 512 | fs.sync_metadata(false); |
7c673cae | 513 | } |
11fdf7f2 | 514 | ASSERT_EQ(0, fs.rmdir(dir)); |
1911f103 | 515 | fs.sync_metadata(false); |
7c673cae FG |
516 | } |
517 | } | |
518 | fs.compact_log(); | |
519 | fs.umount(); | |
7c673cae FG |
520 | } |
521 | ||
522 | TEST(BlueFS, test_simple_compaction_async) { | |
11fdf7f2 | 523 | g_ceph_context->_conf.set_val( |
7c673cae FG |
524 | "bluefs_compact_log_sync", |
525 | "false"); | |
526 | uint64_t size = 1048576 * 128; | |
9f95a23c | 527 | TempBdev bdev{size}; |
7c673cae FG |
528 | |
529 | BlueFS fs(g_ceph_context); | |
9f95a23c | 530 | ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false)); |
7c673cae FG |
531 | fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576); |
532 | uuid_d fsid; | |
9f95a23c | 533 | ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false })); |
7c673cae | 534 | ASSERT_EQ(0, fs.mount()); |
9f95a23c | 535 | ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false })); |
7c673cae | 536 | { |
7c673cae FG |
537 | for (int i=0; i<10; i++) { |
538 | string dir = "dir."; | |
539 | dir.append(to_string(i)); | |
540 | ASSERT_EQ(0, fs.mkdir(dir)); | |
541 | for (int j=0; j<10; j++) { | |
542 | string file = "file."; | |
543 | file.append(to_string(j)); | |
11fdf7f2 | 544 | BlueFS::FileWriter *h; |
7c673cae | 545 | ASSERT_EQ(0, fs.open_for_write(dir, file, &h, false)); |
11fdf7f2 TL |
546 | ASSERT_NE(nullptr, h); |
547 | auto sg = make_scope_guard([&fs, h] { fs.close_writer(h); }); | |
7c673cae | 548 | bufferlist bl; |
11fdf7f2 TL |
549 | std::unique_ptr<char[]> buf = gen_buffer(4096); |
550 | bufferptr bp = buffer::claim_char(4096, buf.get()); | |
7c673cae FG |
551 | bl.push_back(bp); |
552 | h->append(bl.c_str(), bl.length()); | |
553 | fs.fsync(h); | |
7c673cae FG |
554 | } |
555 | } | |
556 | } | |
7c673cae FG |
557 | { |
558 | for (int i=0; i<10; i+=2) { | |
559 | string dir = "dir."; | |
560 | dir.append(to_string(i)); | |
11fdf7f2 | 561 | for (int j=0; j<10; j++) { |
7c673cae FG |
562 | string file = "file."; |
563 | file.append(to_string(j)); | |
564 | fs.unlink(dir, file); | |
1911f103 | 565 | fs.sync_metadata(false); |
7c673cae | 566 | } |
11fdf7f2 | 567 | ASSERT_EQ(0, fs.rmdir(dir)); |
1911f103 | 568 | fs.sync_metadata(false); |
7c673cae FG |
569 | } |
570 | } | |
571 | fs.compact_log(); | |
572 | fs.umount(); | |
7c673cae FG |
573 | } |
574 | ||
575 | TEST(BlueFS, test_compaction_sync) { | |
576 | uint64_t size = 1048576 * 128; | |
9f95a23c | 577 | TempBdev bdev{size}; |
11fdf7f2 | 578 | g_ceph_context->_conf.set_val( |
7c673cae FG |
579 | "bluefs_alloc_size", |
580 | "65536"); | |
11fdf7f2 | 581 | g_ceph_context->_conf.set_val( |
7c673cae FG |
582 | "bluefs_compact_log_sync", |
583 | "true"); | |
584 | ||
585 | BlueFS fs(g_ceph_context); | |
9f95a23c | 586 | ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false)); |
7c673cae FG |
587 | fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576); |
588 | uuid_d fsid; | |
9f95a23c | 589 | ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false })); |
7c673cae | 590 | ASSERT_EQ(0, fs.mount()); |
9f95a23c | 591 | ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false })); |
7c673cae FG |
592 | { |
593 | std::vector<std::thread> write_threads; | |
594 | uint64_t effective_size = size - (32 * 1048576); // leaving the last 32 MB for log compaction | |
595 | uint64_t per_thread_bytes = (effective_size/(NUM_WRITERS)); | |
596 | for (int i=0; i<NUM_WRITERS; i++) { | |
597 | write_threads.push_back(std::thread(write_data, std::ref(fs), per_thread_bytes)); | |
598 | } | |
599 | ||
600 | std::vector<std::thread> sync_threads; | |
601 | for (int i=0; i<NUM_SYNC_THREADS; i++) { | |
602 | sync_threads.push_back(std::thread(sync_fs, std::ref(fs))); | |
603 | } | |
604 | ||
605 | join_all(write_threads); | |
606 | writes_done = true; | |
607 | join_all(sync_threads); | |
608 | fs.compact_log(); | |
609 | } | |
610 | fs.umount(); | |
7c673cae FG |
611 | } |
612 | ||
613 | TEST(BlueFS, test_compaction_async) { | |
614 | uint64_t size = 1048576 * 128; | |
9f95a23c | 615 | TempBdev bdev{size}; |
11fdf7f2 | 616 | g_ceph_context->_conf.set_val( |
7c673cae FG |
617 | "bluefs_alloc_size", |
618 | "65536"); | |
11fdf7f2 | 619 | g_ceph_context->_conf.set_val( |
7c673cae FG |
620 | "bluefs_compact_log_sync", |
621 | "false"); | |
622 | ||
623 | BlueFS fs(g_ceph_context); | |
9f95a23c | 624 | ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false)); |
7c673cae FG |
625 | fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576); |
626 | uuid_d fsid; | |
9f95a23c | 627 | ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false })); |
7c673cae | 628 | ASSERT_EQ(0, fs.mount()); |
9f95a23c | 629 | ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false })); |
7c673cae FG |
630 | { |
631 | std::vector<std::thread> write_threads; | |
632 | uint64_t effective_size = size - (32 * 1048576); // leaving the last 32 MB for log compaction | |
633 | uint64_t per_thread_bytes = (effective_size/(NUM_WRITERS)); | |
634 | for (int i=0; i<NUM_WRITERS; i++) { | |
635 | write_threads.push_back(std::thread(write_data, std::ref(fs), per_thread_bytes)); | |
636 | } | |
637 | ||
638 | std::vector<std::thread> sync_threads; | |
639 | for (int i=0; i<NUM_SYNC_THREADS; i++) { | |
640 | sync_threads.push_back(std::thread(sync_fs, std::ref(fs))); | |
641 | } | |
642 | ||
643 | join_all(write_threads); | |
644 | writes_done = true; | |
645 | join_all(sync_threads); | |
646 | fs.compact_log(); | |
647 | } | |
648 | fs.umount(); | |
7c673cae FG |
649 | } |
650 | ||
651 | TEST(BlueFS, test_replay) { | |
652 | uint64_t size = 1048576 * 128; | |
9f95a23c | 653 | TempBdev bdev{size}; |
11fdf7f2 | 654 | g_ceph_context->_conf.set_val( |
7c673cae FG |
655 | "bluefs_alloc_size", |
656 | "65536"); | |
11fdf7f2 | 657 | g_ceph_context->_conf.set_val( |
7c673cae FG |
658 | "bluefs_compact_log_sync", |
659 | "false"); | |
660 | ||
661 | BlueFS fs(g_ceph_context); | |
9f95a23c | 662 | ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false)); |
7c673cae FG |
663 | fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576); |
664 | uuid_d fsid; | |
9f95a23c | 665 | ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false })); |
7c673cae | 666 | ASSERT_EQ(0, fs.mount()); |
9f95a23c | 667 | ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false })); |
7c673cae FG |
668 | { |
669 | std::vector<std::thread> write_threads; | |
670 | uint64_t effective_size = size - (32 * 1048576); // leaving the last 32 MB for log compaction | |
671 | uint64_t per_thread_bytes = (effective_size/(NUM_WRITERS)); | |
672 | for (int i=0; i<NUM_WRITERS; i++) { | |
673 | write_threads.push_back(std::thread(write_data, std::ref(fs), per_thread_bytes)); | |
674 | } | |
675 | ||
676 | std::vector<std::thread> sync_threads; | |
677 | for (int i=0; i<NUM_SYNC_THREADS; i++) { | |
678 | sync_threads.push_back(std::thread(sync_fs, std::ref(fs))); | |
679 | } | |
680 | ||
681 | join_all(write_threads); | |
682 | writes_done = true; | |
683 | join_all(sync_threads); | |
684 | fs.compact_log(); | |
685 | } | |
686 | fs.umount(); | |
687 | // remount and check log can replay safe? | |
31f18b77 | 688 | ASSERT_EQ(0, fs.mount()); |
9f95a23c | 689 | ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false })); |
7c673cae | 690 | fs.umount(); |
7c673cae FG |
691 | } |
692 | ||
693 | int main(int argc, char **argv) { | |
694 | vector<const char*> args; | |
695 | argv_to_vec(argc, (const char **)argv, args); | |
7c673cae | 696 | |
11fdf7f2 TL |
697 | map<string,string> defaults = { |
698 | { "debug_bluefs", "1/20" }, | |
699 | { "debug_bdev", "1/20" } | |
700 | }; | |
7c673cae | 701 | |
11fdf7f2 | 702 | auto cct = global_init(&defaults, args, CEPH_ENTITY_TYPE_CLIENT, |
7c673cae | 703 | CODE_ENVIRONMENT_UTILITY, |
11fdf7f2 | 704 | CINIT_FLAG_NO_DEFAULT_CONFIG_FILE); |
7c673cae | 705 | common_init_finish(g_ceph_context); |
11fdf7f2 | 706 | g_ceph_context->_conf.set_val( |
7c673cae FG |
707 | "enable_experimental_unrecoverable_data_corrupting_features", |
708 | "*"); | |
11fdf7f2 | 709 | g_ceph_context->_conf.apply_changes(nullptr); |
7c673cae FG |
710 | |
711 | ::testing::InitGoogleTest(&argc, argv); | |
712 | return RUN_ALL_TESTS(); | |
713 | } |