Commit da5f1096 authored by Brian Foster's avatar Brian Foster Committed by Dave Chinner

xfs: flush the range before zero range conversion

XFS currently discards delalloc blocks within the target range of a
zero range request. Unaligned start and end offsets are zeroed
through the page cache and the internal, aligned blocks are
converted to unwritten extents.

If EOF is page aligned and covered by a delayed allocation extent.
The inode size is not updated until I/O completion. If a zero range
request discards a delalloc range that covers page aligned EOF as
such, the inode size update never occurs. For example:

$ rm -f /mnt/file
$ xfs_io -fc "pwrite 0 64k" -c "zero 60k 4k" /mnt/file
$ stat -c "%s" /mnt/file
65536
$ umount /mnt
$ mount <dev> /mnt
$ stat -c "%s" /mnt/file
61440

Update xfs_zero_file_space() to flush the range rather than discard
delalloc blocks to ensure that inode size updates occur
appropriately.

[dchinner: Note that this is really a workaround to avoid the
underlying problems. More work is needed (and ongoing) to fix those
issues so this fix is being added as a temporary stop-gap measure. ]
Signed-off-by: default avatarBrian Foster <bfoster@redhat.com>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
parent 07d08681
...@@ -1392,14 +1392,14 @@ xfs_zero_file_space( ...@@ -1392,14 +1392,14 @@ xfs_zero_file_space(
if (start_boundary < end_boundary - 1) { if (start_boundary < end_boundary - 1) {
/* /*
* punch out delayed allocation blocks and the page cache over * Writeback the range to ensure any inode size updates due to
* the conversion range * appending writes make it to disk (otherwise we could just
* punch out the delalloc blocks).
*/ */
xfs_ilock(ip, XFS_ILOCK_EXCL); error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
error = xfs_bmap_punch_delalloc_range(ip, start_boundary, end_boundary - 1);
XFS_B_TO_FSBT(mp, start_boundary), if (error)
XFS_B_TO_FSB(mp, end_boundary - start_boundary)); goto out;
xfs_iunlock(ip, XFS_ILOCK_EXCL);
truncate_pagecache_range(VFS_I(ip), start_boundary, truncate_pagecache_range(VFS_I(ip), start_boundary,
end_boundary - 1); end_boundary - 1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment