]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commit
os/bluestore: Fix BlueFS::truncate() 60237/head
authorAdam Kupczyk <akupczyk@ibm.com>
Fri, 10 Jan 2025 08:26:54 +0000 (08:26 +0000)
committerAdam Kupczyk <akupczyk@ibm.com>
Fri, 17 Jan 2025 08:41:24 +0000 (08:41 +0000)
commit7bbfbe711dbe72a4bd5217fc1359a45697e5fd85
tree7ede39b9a4a3187fd4915ae5c36fd32c14f0490a
parentdc5bc47e67f02219551eafeb2c83e75d7e268b8e
os/bluestore: Fix BlueFS::truncate()

In `struct bluefs_fnode_t` there is a vector `extents` and
the vector `extents_index` that is a log2 seek cache.

Until modifications to truncate() we never removed extents from files.
Modified truncate() did not update extents_index.

For example 10 extents long files when truncated to 0 will have:
0 extents, 10 extents_index.
After writing some data to file:
1 extents, 11 extents_index.

Now, `bluefs_fnode_t::seek` will binary search extents_index,
lets say it located seek at item #3.
It will then jump up from #0 extent (that exists) to #3 extent which
does not exist at.
The worst part is that code is now broken, as #3 != extent.end().

There are 3 parts of the fix:
1) assert in `bluefs_fnode_t::seek` to protect against
   jumping outside extents
2) code in BlueFS::truncate to sync up `extents_index` with `extents`
3) dampening down assert in _replay to give a way out of cases
   where incorrect "offset 12345" (12345 is file size) instead of
   "offset 20000" (allocations occupied) was written to log.

Fixes: https://tracker.ceph.com/issues/69481
Signed-off-by: Adam Kupczyk <akupczyk@ibm.com>
(cherry picked from commit 7f3601089d41bfc23f530c7bf3fb7efad2d055ec)
src/os/bluestore/BlueFS.cc
src/os/bluestore/bluefs_types.cc
src/os/bluestore/bluefs_types.h