]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/test/objectstore/test_bluefs.cc
import 15.2.0 Octopus source
[ceph.git] / ceph / src / test / objectstore / test_bluefs.cc
index 60e51a12d22814e1be82598f0710388ec8f2924b..ef838ab124f2f1294f3b08da025973097b27c857 100644 (file)
 
 #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);
@@ -39,47 +26,124 @@ std::unique_ptr<char[]> gen_buffer(uint64_t 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"));
@@ -100,18 +164,18 @@ TEST(BlueFS, write_read) {
     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"));
@@ -132,23 +196,23 @@ TEST(BlueFS, small_appends) {
     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;
@@ -183,8 +247,6 @@ TEST(BlueFS, very_large_write) {
   fs.umount();
 
   g_ceph_context->_conf.set_val("bluefs_buffered_io", stringify((int)old));
-
-  rm_temp_bdev(fn);
 }
 
 #define ALLOC_SIZE 4096
@@ -301,18 +363,19 @@ void join_all(std::vector<std::thread>& v)
 
 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
@@ -331,23 +394,23 @@ TEST(BlueFS, test_flush_1) {
     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));
@@ -359,23 +422,23 @@ TEST(BlueFS, test_flush_2) {
     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
@@ -394,7 +457,6 @@ TEST(BlueFS, test_flush_3) {
     join_all(sync_threads);
   }
   fs.umount();
-  rm_temp_bdev(fn);
 }
 
 TEST(BlueFS, test_simple_compaction_sync) {
@@ -402,14 +464,15 @@ 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.";
@@ -439,15 +502,14 @@ TEST(BlueFS, test_simple_compaction_sync) {
           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) {
@@ -455,14 +517,15 @@ 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.";
@@ -492,20 +555,19 @@ TEST(BlueFS, test_simple_compaction_async) {
           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");
@@ -514,11 +576,12 @@ TEST(BlueFS, test_compaction_sync) {
     "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
@@ -538,12 +601,11 @@ TEST(BlueFS, test_compaction_sync) {
     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");
@@ -552,11 +614,12 @@ TEST(BlueFS, test_compaction_async) {
     "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
@@ -576,12 +639,11 @@ TEST(BlueFS, test_compaction_async) {
     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");
@@ -590,11 +652,12 @@ TEST(BlueFS, test_replay) {
     "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
@@ -616,8 +679,8 @@ TEST(BlueFS, test_replay) {
   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) {