Commit d4589b2
btrfs: mark dirty extent range for out of bound prealloc extents
In btrfs_fallocate(), when the allocated range overlaps with a prealloc
extent and the extent starts after i_size, the range doesn't get marked
dirty in file_extent_tree. This results in persisting an incorrect
disk_i_size for the inode when not using the no-holes feature.
This is reproducible since commit 41a2ee7 ("btrfs: introduce
per-inode file extent tree"), then became hidden since commit 3d7db6e
("btrfs: don't allocate file extent tree for non regular files") and then
visible again after commit 8679d26 ("btrfs: initialize
inode::file_extent_tree after i_mode has been set"), which fixes the
previous commit.
The following reproducer triggers the problem:
$ cat test.sh
MNT=/mnt/test
DEV=/dev/vdb
mkdir -p $MNT
mkfs.btrfs -f -O ^no-holes $DEV
mount $DEV $MNT
touch $MNT/file1
# Add a 2M extent at the file offset 1M without increasing i_size.
fallocate -n -o 1M -l 2M $MNT/file1
# Unmount and mount again to clear the in-memory extent tree.
umount $MNT
mount $DEV $MNT
# Use a length that fits within the range of the previously allocated
# extent. We want the next fallocate to only increase the i_size.
len=$((1 * 1024 * 1024))
# fallocate on the prealloc extent to change i_size.
fallocate -o 1M -l $len $MNT/file1
# Check the file size, expecting 2M.
du --bytes $MNT/file1
# Unmount and mount again the fs.
umount $MNT
mount $DEV $MNT
# The file size should be the same as before (2M).
du --bytes $MNT/file1
umount $MNT
Running the reproducer gives the following result:
$ ./test.sh
(...)
2097152 /mnt/test/file1
1048576 /mnt/test/file1
The difference is exactly 1048576 as we assigned.
Fix by adding a call to btrfs_inode_set_file_extent_range() in
btrfs_fallocate_update_isize().
Fixes: 41a2ee7 ("btrfs: introduce per-inode file extent tree")
Signed-off-by: austinchang <austinchang@synology.com>
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>1 parent 27e8fcc commit d4589b2
1 file changed
+10
-0
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2857 | 2857 | | |
2858 | 2858 | | |
2859 | 2859 | | |
| 2860 | + | |
| 2861 | + | |
2860 | 2862 | | |
2861 | 2863 | | |
2862 | 2864 | | |
2863 | 2865 | | |
2864 | 2866 | | |
2865 | 2867 | | |
| 2868 | + | |
| 2869 | + | |
| 2870 | + | |
| 2871 | + | |
| 2872 | + | |
| 2873 | + | |
| 2874 | + | |
| 2875 | + | |
2866 | 2876 | | |
2867 | 2877 | | |
2868 | 2878 | | |
| |||
0 commit comments