]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/objectstore/test_bluefs.cc
bump version to 15.2.4-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 };
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
144TEST(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
176TEST(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
208TEST(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
261void 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
297void 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
314void 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
342bool writes_done = false;
343
344void 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
355void do_join(std::thread& t)
356{
357 t.join();
358}
359
360void 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
371TEST(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
406TEST(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
434TEST(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
469TEST(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
522TEST(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
575TEST(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
613TEST(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
651TEST(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
693int 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}