]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
os/bluestore/bluefs: Fix data corruption in truncate()
authorAdam Kupczyk <akupczyk@redhat.com>
Tue, 2 Nov 2021 15:57:32 +0000 (16:57 +0100)
committerAdam Kupczyk <akupczyk@redhat.com>
Wed, 3 Nov 2021 06:49:33 +0000 (07:49 +0100)
It is possible to create condition in which a BlueFS contains file that is corrupted.
It can happen when BlueFS replay log is on device A and we just wrote to device B and truncated file.

Scenario:
1) write to file h1 on SLOW device
2) flush h1 (initiate transfer, but no fdatasync yet)
3) truncate h1
4) write to file h2 on DB
5) fsync h2 (forces replay log to be written, after fdatasync to DB)
6) poweroff

Fixes: https://tracker.ceph.com/issues/53129
Signed-off-by: Adam Kupczyk <akupczyk@redhat.com>
src/os/bluestore/BlueFS.cc
src/test/objectstore/test_bluefs.cc

index f34996be3e000f9d685d05f73133f4bba3aa6018..f125bc15bf04d8cd78043e6b6c61572bbdb5d774 100644 (file)
@@ -2923,6 +2923,7 @@ int BlueFS::_truncate(FileWriter *h, uint64_t offset)
     ceph_abort_msg("truncate up not supported");
   }
   ceph_assert(h->file->fnode.size >= offset);
+  _flush_bdev_safely(h);
   vselector->sub_usage(h->file->vselector_hint, h->file->fnode.size);
   h->file->fnode.size = offset;
   vselector->add_usage(h->file->vselector_hint, h->file->fnode.size);
index 799996da17fc6b5d0c35d4add62a864947be910f..58bd1ad16e4774131a001e0986c322827aa467cd 100644 (file)
@@ -842,9 +842,9 @@ TEST(BlueFS, test_truncate_stable_53129) {
   TempBdev bdev_slow{size_slow};
 
   BlueFS fs(g_ceph_context);
-  ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_WAL,  "wal",  false, 0));
-  ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB,   "db",   false, 0));
-  ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_SLOW, "slow", false, 0));
+  ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_WAL,  bdev_wal.path,  false, 0));
+  ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB,   bdev_db.path,   false, 0));
+  ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_SLOW, bdev_slow.path, false, 0));
   uuid_d fsid;
   ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, true, true }));
   ASSERT_EQ(0, fs.mount());