]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
os/objectstore/test: Add test for data corruption in file truncation
authorAdam Kupczyk <akupczyk@redhat.com>
Tue, 2 Nov 2021 15:56:10 +0000 (16:56 +0100)
committerAdam Kupczyk <akupczyk@redhat.com>
Wed, 2 Feb 2022 13:04:52 +0000 (14:04 +0100)
Test for https://tracker.ceph.com/issues/53129

Signed-off-by: Adam Kupczyk <akupczyk@redhat.com>
(cherry picked from commit 1f7771d4a77ebb271b939b3893d7607d964796f0)

src/test/objectstore/test_bluefs.cc

index 6f274db61657bdfe6e568184f275db8bd154f50f..9eeed9913ef914a37b289269d0871fa902807f20 100644 (file)
@@ -909,6 +909,95 @@ TEST(BlueFS, test_tracker_50965) {
   fs.umount();
 }
 
+TEST(BlueFS, test_truncate_stable_53129) {
+
+  ConfSaver conf(g_ceph_context->_conf);
+  conf.SetVal("bluefs_min_flush_size", "65536");
+  conf.ApplyChanges();
+
+  uint64_t size_wal = 1048576 * 64;
+  TempBdev bdev_wal{size_wal};
+  uint64_t size_db = 1048576 * 128;
+  TempBdev bdev_db{size_db};
+  uint64_t size_slow = 1048576 * 256;
+  TempBdev bdev_slow{size_slow};
+
+  BlueFS fs(g_ceph_context);
+  ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_WAL,  bdev_wal.path,  false, 0));
+  fs.add_block_extent(BlueFS::BDEV_WAL, 1048576, size_wal - 1048576);
+  ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB,   bdev_db.path,   false, 0));
+  fs.add_block_extent(BlueFS::BDEV_DB, 1048576, size_db - 1048576);
+  ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_SLOW, bdev_slow.path, false, 0));
+  fs.add_block_extent(BlueFS::BDEV_SLOW, 1048576, size_slow - 1048576);
+
+  uuid_d fsid;
+  ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, true, true }));
+  ASSERT_EQ(0, fs.mount());
+  ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, true, true }));
+
+  string dir_slow = "dir.slow";
+  ASSERT_EQ(0, fs.mkdir(dir_slow));
+  string dir_db = "dir_db";
+  ASSERT_EQ(0, fs.mkdir(dir_db));
+
+  string file_slow = "file";
+  BlueFS::FileWriter *h_slow;
+  ASSERT_EQ(0, fs.open_for_write(dir_slow, file_slow, &h_slow, false));
+  ASSERT_NE(nullptr, h_slow);
+
+  string file_db = "file";
+  BlueFS::FileWriter *h_db;
+  ASSERT_EQ(0, fs.open_for_write(dir_db, file_db, &h_db, false));
+  ASSERT_NE(nullptr, h_db);
+
+  bufferlist bl1;
+  std::unique_ptr<char[]> buf1 = gen_buffer(70000);
+  bufferptr bp1 = buffer::claim_char(70000, buf1.get());
+  bl1.push_back(bp1);
+  // add 70000 bytes
+  h_slow->append(bl1.c_str(), bl1.length());
+  fs.flush(h_slow);
+  // and truncate to 60000 bytes
+  fs.truncate(h_slow, 60000);
+
+  // write something to file on DB device
+  bufferlist bl2;
+  std::unique_ptr<char[]> buf2 = gen_buffer(1000);
+  bufferptr bp2 = buffer::claim_char(1000, buf2.get());
+  bl2.push_back(bp2);
+  h_db->append(bl2.c_str(), bl2.length());
+  // and force bluefs log to flush
+  fs.fsync(h_db);
+
+  // This is the actual test point.
+  // We completed truncate, and we expect
+  // - size to be 60000
+  // - data to be stable on slow device
+  // OR
+  // - size = 0 or file does not exist
+  // - dev_dirty is irrelevant
+  bool h_slow_dev_dirty = fs.debug_get_is_dev_dirty(h_slow, BlueFS::BDEV_SLOW);
+  // Imagine power goes down here.
+
+  fs.close_writer(h_slow);
+  fs.close_writer(h_db);
+
+  fs.umount();
+
+  ASSERT_EQ(0, fs.mount());
+  ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, true, true }));
+
+  uint64_t size;
+  utime_t mtime;
+  ASSERT_EQ(0, fs.stat("dir.slow", "file", &size, &mtime));
+  // check file size 60000
+  ASSERT_EQ(size, 60000);
+  // check that dev_dirty was false (data stable on media)
+  ASSERT_EQ(h_slow_dev_dirty, false);
+
+  fs.umount();
+}
+
 int main(int argc, char **argv) {
   vector<const char*> args;
   argv_to_vec(argc, (const char **)argv, args);