]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
os/bluestore: Add unittest for BlueFS::truncate()
authorAdam Kupczyk <akupczyk@ibm.com>
Wed, 23 Oct 2024 11:57:01 +0000 (11:57 +0000)
committerAdam Kupczyk <akupczyk@ibm.com>
Fri, 17 Jan 2025 08:41:21 +0000 (08:41 +0000)
Add unittest for some truncate scenarios.

Fixes: https://tracker.ceph.com/issues/68385 (addendum)
Signed-off-by: Adam Kupczyk <akupczyk@ibm.com>
(cherry picked from commit 612f24b41fb44e478d6c1cc867dfa0720197793f)

src/test/objectstore/test_bluefs.cc

index 6d3ff1218a437576dd452b43dadefbc3610cd88f..9c9921d02e3248c2afdfb90fccd5657dd5d4cfb0 100644 (file)
@@ -1401,161 +1401,81 @@ TEST(BlueFS, test_concurrent_dir_link_and_compact_log_56210) {
   }
 }
 
-TEST(BlueFS, test_log_runway) {
-  uint64_t max_log_runway = 65536;
-  ConfSaver conf(g_ceph_context->_conf);
-  conf.SetVal("bluefs_compact_log_sync", "false");
-  conf.SetVal("bluefs_min_log_runway", "32768");
-  conf.SetVal("bluefs_max_log_runway", std::to_string(max_log_runway).c_str());
-  conf.ApplyChanges();
-
-  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, 1048576));
+TEST(BlueFS, truncate_drops_allocations) {
+  constexpr uint64_t K = 1024;
+  constexpr uint64_t M = 1024 * K;
   uuid_d 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 }));
-  // longer transaction than current runway
-  std::string longdir(max_log_runway, 'a');
-  fs.mkdir(longdir);
-  {
-    BlueFS::FileWriter *h;
-    ASSERT_EQ(0, fs.mkdir("dir"));
-    ASSERT_EQ(0, fs.open_for_write("dir", "file", &h, false));
-    h->append("foo", 3);
-    h->append("bar", 3);
-    h->append("baz", 3);
-    fs.fsync(h);
-    fs.close_writer(h);
-  }
-  fs.umount(true);
-  fs.mount();
+  const char* DIR_NAME="dir";
+  const char* FILE_NAME="file1";
+  struct {
+    uint64_t preallocated_size;
+    uint64_t write_size;
+    uint64_t truncate_to;
+    uint64_t allocated_after_truncate;
+    uint64_t slow_size = 0;
+    uint64_t slow_alloc_size = 64*K;
+    uint64_t db_size = 128*M;
+    uint64_t db_alloc_size = 1*M;
+  } scenarios [] = {
+    // on DB(which is SLOW) : 1 => 1, 64K remains
+    { 1*M, 1, 1, 64*K },
+    // on DB(which is SLOW), alloc 4K : 1 => 1, 4K remains
+    { 1*M, 1, 1, 4*K, 0, 4*K },
+    // on DB(which is SLOW), truncation on AU boundary : 128K => 128K, 128K remains
+    { 1*M, 128*K, 128*K, 128*K },
+    // on DB(which is SLOW), no prealloc, truncation to 0 : 1666K => 0, 0 remains
+    { 0, 1666*K, 0, 0 },
+    // on DB, truncate to 123K, expect 1M occupied
+    { 1234*K, 123*K, 123*K, 1*M, 128*M, 64*K, 10*M, 1*M },
+    // on DB, truncate to 0, expect 0 occupied
+    { 1234*K, 345*K, 0, 0, 128*M, 64*K, 10*M, 1*M },
+    // on DB, truncate to AU boundary, expect exactly 1M occupied
+    { 1234*K, 1123*K, 1*M, 1*M, 128*M, 64*K, 10*M, 1*M },
+    // on DB and SLOW, truncate only data on SLOW
+    { 0, 10*M+1, 10*M+1, 10*M+64*K, 128*M, 64*K, 10*M, 1*M },
+    // on DB and SLOW, preallocate and truncate only data on SLOW
+    { 6*M, 12*M, 10*M+1, 10*M+64*K, 128*M, 64*K, 10*M, 1*M },
+    // on DB and SLOW, preallocate and truncate all in SLOW and some on DB
+    // note! prealloc 6M is important, one allocation for 12M will fallback to SLOW
+    // in 6M + 6M we can be sure that 6M is on DB and 6M is on SLOW
+    { 6*M, 12*M, 3*M+1, 4*M, 128*M, 64*K, 11*M, 1*M },
+  };
+  for (auto& s : scenarios) {
+    ConfSaver conf(g_ceph_context->_conf);
+    conf.SetVal("bluefs_shared_alloc_size", stringify(s.slow_alloc_size).c_str());
+    conf.SetVal("bluefs_alloc_size", stringify(s.db_alloc_size).c_str());
 
-  std::vector<std::string> ls;
-  fs.readdir("dir", &ls);
-  ASSERT_EQ(ls.front(), "file"); 
-  uint64_t file_size = 0;
-  utime_t mtime;
-  fs.stat("dir", "file", &file_size, &mtime);
-  ASSERT_EQ(file_size, 9);
-}
+    g_ceph_context->_conf.set_val("bluefs_shared_alloc_size", stringify(s.slow_alloc_size));
+    g_ceph_context->_conf.set_val("bluefs_alloc_size", stringify(s.db_alloc_size));
+    TempBdev bdev_db{s.db_size};
+    TempBdev bdev_slow{s.slow_size};
 
-TEST(BlueFS, test_log_runway_2) {
-  uint64_t max_log_runway = 65536;
-  ConfSaver conf(g_ceph_context->_conf);
-  conf.SetVal("bluefs_compact_log_sync", "false");
-  conf.SetVal("bluefs_min_log_runway", "32768");
-  conf.SetVal("bluefs_max_log_runway", std::to_string(max_log_runway).c_str());
-  conf.ApplyChanges();
+    BlueFS fs(g_ceph_context);
+    if (s.db_size != 0) {
+      ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev_db.path, false, 0));
+    }
+    if (s.slow_size != 0) {
+      ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_SLOW, bdev_slow.path, false, 0));
+    }
 
-  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, 1048576));
-  uuid_d 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 }));
-  // longer transaction than current runway
-  size_t name_length = max_log_runway * 2;
-  std::string longdir(name_length, 'a');
-  std::string longfile(name_length, 'b');
-  {
-    BlueFS::FileWriter *h;
-    ASSERT_EQ(0, fs.mkdir(longdir));
-    ASSERT_EQ(0, fs.open_for_write(longdir, longfile, &h, false));
-    h->append("canary", 6);
-    fs.fsync(h);
-    fs.close_writer(h);
-    fs.sync_metadata(true);
-  }
-  {
+    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"));
-    ASSERT_EQ(0, fs.open_for_write("dir", "file", &h, false));
-    h->append("foo", 3);
-    h->append("bar", 3);
-    h->append("baz", 3);
+    ASSERT_EQ(0, fs.open_for_write(DIR_NAME, FILE_NAME, &h, false));
+    uint64_t pre = fs.get_used();
+    ASSERT_EQ(0, fs.preallocate(h->file, 0, s.preallocated_size));
+    const std::string content(s.write_size, 'x');
+    h->append(content.c_str(), content.length());
     fs.fsync(h);
-    fs.close_writer(h);
-  }
-  fs.umount(true);
-  fs.mount();
-
-  std::vector<std::string> ls;
-  fs.readdir("dir", &ls);
-  ASSERT_EQ(ls.front(), "file");
-  uint64_t file_size = 0;
-  utime_t mtime;
-  fs.stat("dir", "file", &file_size, &mtime);
-  ASSERT_EQ(file_size, 9);
-  fs.stat(longdir, longfile, &file_size, &mtime);
-  ASSERT_EQ(file_size, 6);
-
-  std::vector<std::string> ls_longdir;
-  fs.readdir(longdir, &ls_longdir);
-  ASSERT_EQ(ls_longdir.front(), longfile);
-}
-
-TEST(BlueFS, test_log_runway_3) {
-  uint64_t max_log_runway = 65536;
-  ConfSaver conf(g_ceph_context->_conf);
-  conf.SetVal("bluefs_alloc_size", "4096");
-  conf.SetVal("bluefs_shared_alloc_size", "4096");
-  conf.SetVal("bluefs_compact_log_sync", "false");
-  conf.SetVal("bluefs_min_log_runway", "32768");
-  conf.SetVal("bluefs_max_log_runway", std::to_string(max_log_runway).c_str());
-  conf.ApplyChanges();
-
-  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, 1048576));
-  uuid_d 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 }));
-  // longer transaction than current runway
-  for (size_t m = 0; m < 40; m++) {
-    std::string longdir(max_log_runway + m, 'A' + m);
-    std::string longfile(max_log_runway + m, 'A' + m);
-    BlueFS::FileWriter *h;
-    ASSERT_EQ(0, fs.mkdir(longdir));
-    ASSERT_EQ(0, fs.open_for_write(longdir, longfile, &h, false));
-    h->append("canary", 6);
-    fs.fsync(h);
-    fs.close_writer(h);
-    fs.sync_metadata(true);
-  }
-  {
-    BlueFS::FileWriter *h;
-    ASSERT_EQ(0, fs.mkdir("dir"));
-    ASSERT_EQ(0, fs.open_for_write("dir", "file", &h, false));
-    h->append("foo", 3);
-    h->append("bar", 3);
-    h->append("baz", 3);
+    ASSERT_EQ(0, fs.truncate(h, s.truncate_to));
     fs.fsync(h);
+    uint64_t post = fs.get_used();
     fs.close_writer(h);
-  }
-  fs.umount(true);
-  fs.mount();
+    EXPECT_EQ(pre, post - s.allocated_after_truncate);
 
-  std::vector<std::string> ls;
-  fs.readdir("dir", &ls);
-  ASSERT_EQ(ls.front(), "file");
-  uint64_t file_size = 0;
-  utime_t mtime;
-  fs.stat("dir", "file", &file_size, &mtime);
-  ASSERT_EQ(file_size, 9);
-  for (size_t m = 0; m < 40; m++) {
-    uint64_t file_size = 0;
-    utime_t mtime;
-    std::string longdir(max_log_runway + m, 'A' + m);
-    std::string longfile(max_log_runway + m, 'A' + m);
-    fs.stat(longdir, longfile, &file_size, &mtime);
-    ASSERT_EQ(file_size, 6);
+    fs.umount();
   }
 }