Skip to content

Commit f8ba6c6

Browse files
authored
Merge pull request ceph#61314 from aclamk/wip-aclamk-bluefs-truncate-fix
os/bluestore: Fix BlueFS::truncate()
2 parents 262221d + 7f36010 commit f8ba6c6

File tree

4 files changed

+92
-2
lines changed

4 files changed

+92
-2
lines changed

src/os/bluestore/BlueFS.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1706,7 +1706,8 @@ int BlueFS::_replay(bool noop, bool to_stdout)
17061706
<< " fnode=" << fnode
17071707
<< " delta=" << delta
17081708
<< dendl;
1709-
ceph_assert(delta.offset == fnode.allocated);
1709+
// be leanient, if there is no extents just produce error message
1710+
ceph_assert(delta.offset == fnode.allocated || delta.extents.empty());
17101711
}
17111712
if (cct->_conf->bluefs_log_replay_check_allocations) {
17121713
int r = _check_allocations(fnode,
@@ -3830,6 +3831,7 @@ int BlueFS::truncate(FileWriter *h, uint64_t offset)/*_WF_L*/
38303831
fnode.size = offset;
38313832
fnode.allocated = new_allocated;
38323833
fnode.reset_delta();
3834+
fnode.recalc_allocated();
38333835
log.t.op_file_update(fnode);
38343836
// sad, but is_dirty must be set to signal flushing of the log
38353837
h->file->is_dirty = true;

src/os/bluestore/bluefs_types.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,9 @@ mempool::bluefs::vector<bluefs_extent_t>::iterator bluefs_fnode_t::seek(
154154
assert(it != extents_index.begin());
155155
--it;
156156
assert(offset >= *it);
157-
p += it - extents_index.begin();
157+
uint32_t skip = it - extents_index.begin();
158+
ceph_assert(skip <= extents.size());
159+
p += skip;
158160
offset -= *it;
159161
}
160162

src/os/bluestore/bluefs_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ struct bluefs_fnode_t {
8989
void recalc_allocated() {
9090
allocated = 0;
9191
extents_index.reserve(extents.size());
92+
extents_index.clear();
9293
for (auto& p : extents) {
9394
extents_index.emplace_back(allocated);
9495
allocated += p.length;

src/test/objectstore/test_bluefs.cc

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1608,6 +1608,91 @@ TEST(BlueFS, test_log_runway_advance_seq) {
16081608
fs.compact_log();
16091609
}
16101610

1611+
TEST(BlueFS, test_69481_truncate_corrupts_log) {
1612+
uint64_t size = 1048576 * 128;
1613+
TempBdev bdev{size};
1614+
BlueFS fs(g_ceph_context);
1615+
ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false));
1616+
uuid_d fsid;
1617+
ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false }));
1618+
ASSERT_EQ(0, fs.mount());
1619+
ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false }));
1620+
1621+
BlueFS::FileWriter *f = nullptr;
1622+
BlueFS::FileWriter *a = nullptr;
1623+
ASSERT_EQ(0, fs.mkdir("dir"));
1624+
ASSERT_EQ(0, fs.open_for_write("dir", "test-file", &f, false));
1625+
ASSERT_EQ(0, fs.open_for_write("dir", "just-allocate", &a, false));
1626+
1627+
// create 4 distinct extents in file f
1628+
// a is here only to prevent f from merging extents together
1629+
fs.preallocate(f->file, 0, 0x10000);
1630+
fs.preallocate(a->file, 0, 0x10000);
1631+
fs.preallocate(f->file, 0, 0x20000);
1632+
fs.preallocate(a->file, 0, 0x20000);
1633+
fs.preallocate(f->file, 0, 0x30000);
1634+
fs.preallocate(a->file, 0, 0x30000);
1635+
fs.preallocate(f->file, 0, 0x40000);
1636+
fs.preallocate(a->file, 0, 0x40000);
1637+
fs.close_writer(a);
1638+
1639+
fs.truncate(f, 0);
1640+
fs.fsync(f);
1641+
1642+
bufferlist bl;
1643+
bl.append(std::string(" ", 0x15678));
1644+
f->append(bl);
1645+
fs.truncate(f, 0x15678);
1646+
fs.fsync(f);
1647+
fs.close_writer(f);
1648+
1649+
fs.umount();
1650+
// remount to verify
1651+
ASSERT_EQ(0, fs.mount());
1652+
fs.umount();
1653+
}
1654+
1655+
TEST(BlueFS, test_69481_truncate_asserts) {
1656+
uint64_t size = 1048576 * 128;
1657+
TempBdev bdev{size};
1658+
BlueFS fs(g_ceph_context);
1659+
ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false));
1660+
uuid_d fsid;
1661+
ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false }));
1662+
ASSERT_EQ(0, fs.mount());
1663+
ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false }));
1664+
1665+
BlueFS::FileWriter *f = nullptr;
1666+
BlueFS::FileWriter *a = nullptr;
1667+
ASSERT_EQ(0, fs.mkdir("dir"));
1668+
ASSERT_EQ(0, fs.open_for_write("dir", "test-file", &f, false));
1669+
ASSERT_EQ(0, fs.open_for_write("dir", "just-allocate", &a, false));
1670+
1671+
// create 4 distinct extents in file f
1672+
// a is here only to prevent f from merging extents together
1673+
fs.preallocate(f->file, 0, 0x10000);
1674+
fs.preallocate(a->file, 0, 0x10000);
1675+
fs.preallocate(f->file, 0, 0x20000);
1676+
fs.preallocate(a->file, 0, 0x20000);
1677+
fs.preallocate(f->file, 0, 0x30000);
1678+
fs.preallocate(a->file, 0, 0x30000);
1679+
fs.preallocate(f->file, 0, 0x40000);
1680+
fs.preallocate(a->file, 0, 0x40000);
1681+
fs.close_writer(a);
1682+
1683+
fs.truncate(f, 0);
1684+
fs.fsync(f);
1685+
1686+
bufferlist bl;
1687+
bl.append(std::string(" ", 0x35678));
1688+
f->append(bl);
1689+
fs.truncate(f, 0x35678);
1690+
fs.fsync(f);
1691+
fs.close_writer(f);
1692+
1693+
fs.umount();
1694+
}
1695+
16111696
int main(int argc, char **argv) {
16121697
auto args = argv_to_vec(argc, argv);
16131698
map<string,string> defaults = {

0 commit comments

Comments
 (0)