From 0e502d3baeb2468ae5b37dee8f8093be0aacbc14 Mon Sep 17 00:00:00 2001 From: Adam Kupczyk Date: Tue, 2 Nov 2021 16:56:10 +0100 Subject: [PATCH] os/objectstore/test: Add test for data corruption in file truncation Test for https://tracker.ceph.com/issues/53129 Signed-off-by: Adam Kupczyk (cherry picked from commit 1f7771d4a77ebb271b939b3893d7607d964796f0) --- src/test/objectstore/test_bluefs.cc | 89 +++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/src/test/objectstore/test_bluefs.cc b/src/test/objectstore/test_bluefs.cc index 6f274db61657b..9eeed9913ef91 100644 --- a/src/test/objectstore/test_bluefs.cc +++ b/src/test/objectstore/test_bluefs.cc @@ -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 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 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 args; argv_to_vec(argc, (const char **)argv, args); -- 2.39.5