mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2026-01-27 12:47:24 +01:00
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 commit41a2ee75aa("btrfs: introduce per-inode file extent tree"), then became hidden since commit3d7db6e8bd("btrfs: don't allocate file extent tree for non regular files") and then visible again after commit8679d2687c("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 fallocate -n -o 1M -l 2M $MNT/file1 umount $MNT mount $DEV $MNT len=$((1 * 1024 * 1024)) fallocate -o 1M -l $len $MNT/file1 du --bytes $MNT/file1 umount $MNT mount $DEV $MNT 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:41a2ee75aa("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>
This commit is contained in:
parent
953902e4fb
commit
3b1a4a59a2
|
|
@ -2854,12 +2854,22 @@ static int btrfs_fallocate_update_isize(struct inode *inode,
|
|||
{
|
||||
struct btrfs_trans_handle *trans;
|
||||
struct btrfs_root *root = BTRFS_I(inode)->root;
|
||||
u64 range_start;
|
||||
u64 range_end;
|
||||
int ret;
|
||||
int ret2;
|
||||
|
||||
if (mode & FALLOC_FL_KEEP_SIZE || end <= i_size_read(inode))
|
||||
return 0;
|
||||
|
||||
range_start = round_down(i_size_read(inode), root->fs_info->sectorsize);
|
||||
range_end = round_up(end, root->fs_info->sectorsize);
|
||||
|
||||
ret = btrfs_inode_set_file_extent_range(BTRFS_I(inode), range_start,
|
||||
range_end - range_start);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
trans = btrfs_start_transaction(root, 1);
|
||||
if (IS_ERR(trans))
|
||||
return PTR_ERR(trans);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user