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