#include "os/bluestore/BlueFS.h"
-string get_temp_bdev(uint64_t size)
-{
- static int n = 0;
- string fn = "ceph_test_bluefs.tmp.block." + stringify(getpid())
- + "." + stringify(++n);
- int fd = ::open(fn.c_str(), O_CREAT|O_RDWR|O_TRUNC, 0644);
- ceph_assert(fd >= 0);
- int r = ::ftruncate(fd, size);
- ceph_assert(r >= 0);
- ::close(fd);
- return fn;
-}
-
std::unique_ptr<char[]> gen_buffer(uint64_t size)
{
std::unique_ptr<char[]> buffer = std::make_unique<char[]>(size);
return buffer;
}
-
-void rm_temp_bdev(string f)
-{
- ::unlink(f.c_str());
-}
+class TempBdev {
+public:
+ TempBdev(uint64_t size)
+ : path{get_temp_bdev(size)}
+ {}
+ ~TempBdev() {
+ rm_temp_bdev(path);
+ }
+ const std::string path;
+private:
+ static string get_temp_bdev(uint64_t size)
+ {
+ static int n = 0;
+ string fn = "ceph_test_bluefs.tmp.block." + stringify(getpid())
+ + "." + stringify(++n);
+ int fd = ::open(fn.c_str(), O_CREAT|O_RDWR|O_TRUNC, 0644);
+ ceph_assert(fd >= 0);
+ int r = ::ftruncate(fd, size);
+ ceph_assert(r >= 0);
+ ::close(fd);
+ return fn;
+ }
+ static void rm_temp_bdev(string f)
+ {
+ ::unlink(f.c_str());
+ }
+};
TEST(BlueFS, mkfs) {
uint64_t size = 1048576 * 128;
- string fn = get_temp_bdev(size);
+ TempBdev bdev{size};
uuid_d fsid;
BlueFS fs(g_ceph_context);
- ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, fn, false));
+ ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false));
fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576);
- ASSERT_EQ(0, fs.mkfs(fsid));
- rm_temp_bdev(fn);
+ ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false }));
}
TEST(BlueFS, mkfs_mount) {
uint64_t size = 1048576 * 128;
- string fn = get_temp_bdev(size);
+ TempBdev bdev{size};
BlueFS fs(g_ceph_context);
- ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, fn, false));
+ ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false));
fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576);
uuid_d fsid;
- ASSERT_EQ(0, fs.mkfs(fsid));
+ ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false }));
ASSERT_EQ(0, fs.mount());
+ ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false }));
ASSERT_EQ(fs.get_total(BlueFS::BDEV_DB), size - 1048576);
ASSERT_LT(fs.get_free(BlueFS::BDEV_DB), size - 1048576);
fs.umount();
- rm_temp_bdev(fn);
+}
+
+TEST(BlueFS, mkfs_mount_duplicate_gift) {
+ uint64_t size = 1048576 * 128;
+ TempBdev bdev{ size };
+ {
+ BlueFS fs(g_ceph_context);
+ ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false));
+ fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576);
+ uuid_d fsid;
+ ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false }));
+ ASSERT_EQ(0, fs.mount());
+
+ {
+ BlueFS::FileWriter *h;
+ ASSERT_EQ(0, fs.mkdir("dir"));
+ ASSERT_EQ(0, fs.open_for_write("dir", "file1", &h, false));
+ h->append("foo", 3);
+ h->append("bar", 3);
+ h->append("baz", 3);
+ fs.fsync(h);
+ fs.close_writer(h);
+ }
+
+ fs.umount();
+ }
+
+ {
+ BlueFS fs(g_ceph_context);
+ ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false));
+ ASSERT_EQ(0, fs.mount());
+ // free allocation presumably allocated for file1
+ fs.debug_inject_duplicate_gift(BlueFS::BDEV_DB, 5 * 1048576, 1048576);
+ {
+ // overwrite file1 with file2
+ BlueFS::FileWriter *h;
+ ASSERT_EQ(0, fs.open_for_write("dir", "file2", &h, false));
+ h->append("foo", 3);
+ h->append("bar", 3);
+ h->append("baz", 3);
+ fs.fsync(h);
+ fs.close_writer(h);
+ }
+ fs.umount();
+ }
+
+ g_ceph_context->_conf.set_val_or_die("bluefs_log_replay_check_allocations", "true");
+ g_ceph_context->_conf.apply_changes(nullptr);
+
+ {
+ // this should fail
+ BlueFS fs(g_ceph_context);
+ ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false));
+ ASSERT_NE(0, fs.mount());
+ }
}
TEST(BlueFS, write_read) {
uint64_t size = 1048576 * 128;
- string fn = get_temp_bdev(size);
+ TempBdev bdev{size};
BlueFS fs(g_ceph_context);
- ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, fn, false));
+ ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false));
fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576);
uuid_d fsid;
- ASSERT_EQ(0, fs.mkfs(fsid));
+ ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false }));
ASSERT_EQ(0, fs.mount());
+ ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false }));
{
BlueFS::FileWriter *h;
ASSERT_EQ(0, fs.mkdir("dir"));
delete h;
}
fs.umount();
- rm_temp_bdev(fn);
}
TEST(BlueFS, small_appends) {
uint64_t size = 1048576 * 128;
- string fn = get_temp_bdev(size);
+ TempBdev bdev{size};
BlueFS fs(g_ceph_context);
- ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, fn, false));
+ ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false));
fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576);
uuid_d fsid;
- ASSERT_EQ(0, fs.mkfs(fsid));
+ ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false }));
ASSERT_EQ(0, fs.mount());
+ ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false }));
{
BlueFS::FileWriter *h;
ASSERT_EQ(0, fs.mkdir("dir"));
fs.close_writer(h);
}
fs.umount();
- rm_temp_bdev(fn);
}
TEST(BlueFS, very_large_write) {
// we'll write a ~3G file, so allocate more than that for the whole fs
uint64_t size = 1048576 * 1024 * 8ull;
- string fn = get_temp_bdev(size);
+ TempBdev bdev{size};
BlueFS fs(g_ceph_context);
bool old = g_ceph_context->_conf.get_val<bool>("bluefs_buffered_io");
g_ceph_context->_conf.set_val("bluefs_buffered_io", "false");
- ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, fn, false));
+ ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false));
fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576);
uuid_d fsid;
- ASSERT_EQ(0, fs.mkfs(fsid));
+ ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false }));
ASSERT_EQ(0, fs.mount());
+ ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false }));
char buf[1048571]; // this is biggish, but intentionally not evenly aligned
for (unsigned i = 0; i < sizeof(buf); ++i) {
buf[i] = i;
fs.umount();
g_ceph_context->_conf.set_val("bluefs_buffered_io", stringify((int)old));
-
- rm_temp_bdev(fn);
}
#define ALLOC_SIZE 4096
TEST(BlueFS, test_flush_1) {
uint64_t size = 1048576 * 128;
- string fn = get_temp_bdev(size);
+ TempBdev bdev{size};
g_ceph_context->_conf.set_val(
"bluefs_alloc_size",
"65536");
g_ceph_context->_conf.apply_changes(nullptr);
BlueFS fs(g_ceph_context);
- ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, fn, false));
+ ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false));
fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576);
uuid_d fsid;
- ASSERT_EQ(0, fs.mkfs(fsid));
+ ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false }));
ASSERT_EQ(0, fs.mount());
+ ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false }));
{
std::vector<std::thread> write_thread_multiple;
uint64_t effective_size = size - (32 * 1048576); // leaving the last 32 MB for log compaction
join_all(write_thread_multiple);
}
fs.umount();
- rm_temp_bdev(fn);
}
TEST(BlueFS, test_flush_2) {
uint64_t size = 1048576 * 256;
- string fn = get_temp_bdev(size);
+ TempBdev bdev{size};
g_ceph_context->_conf.set_val(
"bluefs_alloc_size",
"65536");
g_ceph_context->_conf.apply_changes(nullptr);
BlueFS fs(g_ceph_context);
- ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, fn, false));
+ ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false));
fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576);
uuid_d fsid;
- ASSERT_EQ(0, fs.mkfs(fsid));
+ ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false }));
ASSERT_EQ(0, fs.mount());
+ ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false }));
{
uint64_t effective_size = size - (128 * 1048576); // leaving the last 32 MB for log compaction
uint64_t per_thread_bytes = (effective_size/(NUM_WRITERS));
join_all(write_thread_multiple);
}
fs.umount();
- rm_temp_bdev(fn);
}
TEST(BlueFS, test_flush_3) {
uint64_t size = 1048576 * 256;
- string fn = get_temp_bdev(size);
+ TempBdev bdev{size};
g_ceph_context->_conf.set_val(
"bluefs_alloc_size",
"65536");
g_ceph_context->_conf.apply_changes(nullptr);
BlueFS fs(g_ceph_context);
- ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, fn, false));
+ ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false));
fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576);
uuid_d fsid;
- ASSERT_EQ(0, fs.mkfs(fsid));
+ ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false }));
ASSERT_EQ(0, fs.mount());
+ ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false }));
{
std::vector<std::thread> write_threads;
uint64_t effective_size = size - (64 * 1048576); // leaving the last 11 MB for log compaction
join_all(sync_threads);
}
fs.umount();
- rm_temp_bdev(fn);
}
TEST(BlueFS, test_simple_compaction_sync) {
"bluefs_compact_log_sync",
"true");
uint64_t size = 1048576 * 128;
- string fn = get_temp_bdev(size);
+ TempBdev bdev{size};
BlueFS fs(g_ceph_context);
- ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, fn, false));
+ ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false));
fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576);
uuid_d fsid;
- ASSERT_EQ(0, fs.mkfs(fsid));
+ ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false }));
ASSERT_EQ(0, fs.mount());
+ ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false }));
{
for (int i=0; i<10; i++) {
string dir = "dir.";
string file = "file.";
file.append(to_string(j));
fs.unlink(dir, file);
- fs.flush_log();
+ fs.sync_metadata();
}
ASSERT_EQ(0, fs.rmdir(dir));
- fs.flush_log();
+ fs.sync_metadata();
}
}
fs.compact_log();
fs.umount();
- rm_temp_bdev(fn);
}
TEST(BlueFS, test_simple_compaction_async) {
"bluefs_compact_log_sync",
"false");
uint64_t size = 1048576 * 128;
- string fn = get_temp_bdev(size);
+ TempBdev bdev{size};
BlueFS fs(g_ceph_context);
- ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, fn, false));
+ ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false));
fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576);
uuid_d fsid;
- ASSERT_EQ(0, fs.mkfs(fsid));
+ ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false }));
ASSERT_EQ(0, fs.mount());
+ ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false }));
{
for (int i=0; i<10; i++) {
string dir = "dir.";
string file = "file.";
file.append(to_string(j));
fs.unlink(dir, file);
- fs.flush_log();
+ fs.sync_metadata();
}
ASSERT_EQ(0, fs.rmdir(dir));
- fs.flush_log();
+ fs.sync_metadata();
}
}
fs.compact_log();
fs.umount();
- rm_temp_bdev(fn);
}
TEST(BlueFS, test_compaction_sync) {
uint64_t size = 1048576 * 128;
- string fn = get_temp_bdev(size);
+ TempBdev bdev{size};
g_ceph_context->_conf.set_val(
"bluefs_alloc_size",
"65536");
"true");
BlueFS fs(g_ceph_context);
- ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, fn, false));
+ ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false));
fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576);
uuid_d fsid;
- ASSERT_EQ(0, fs.mkfs(fsid));
+ ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false }));
ASSERT_EQ(0, fs.mount());
+ ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false }));
{
std::vector<std::thread> write_threads;
uint64_t effective_size = size - (32 * 1048576); // leaving the last 32 MB for log compaction
fs.compact_log();
}
fs.umount();
- rm_temp_bdev(fn);
}
TEST(BlueFS, test_compaction_async) {
uint64_t size = 1048576 * 128;
- string fn = get_temp_bdev(size);
+ TempBdev bdev{size};
g_ceph_context->_conf.set_val(
"bluefs_alloc_size",
"65536");
"false");
BlueFS fs(g_ceph_context);
- ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, fn, false));
+ ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false));
fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576);
uuid_d fsid;
- ASSERT_EQ(0, fs.mkfs(fsid));
+ ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false }));
ASSERT_EQ(0, fs.mount());
+ ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false }));
{
std::vector<std::thread> write_threads;
uint64_t effective_size = size - (32 * 1048576); // leaving the last 32 MB for log compaction
fs.compact_log();
}
fs.umount();
- rm_temp_bdev(fn);
}
TEST(BlueFS, test_replay) {
uint64_t size = 1048576 * 128;
- string fn = get_temp_bdev(size);
+ TempBdev bdev{size};
g_ceph_context->_conf.set_val(
"bluefs_alloc_size",
"65536");
"false");
BlueFS fs(g_ceph_context);
- ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, fn, false));
+ ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false));
fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size - 1048576);
uuid_d fsid;
- ASSERT_EQ(0, fs.mkfs(fsid));
+ ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false }));
ASSERT_EQ(0, fs.mount());
+ ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false }));
{
std::vector<std::thread> write_threads;
uint64_t effective_size = size - (32 * 1048576); // leaving the last 32 MB for log compaction
fs.umount();
// remount and check log can replay safe?
ASSERT_EQ(0, fs.mount());
+ ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false }));
fs.umount();
- rm_temp_bdev(fn);
}
int main(int argc, char **argv) {