Commit 22dd6d35 authored by Darrick J. Wong's avatar Darrick J. Wong Committed by Linus Torvalds

block: invalidate the page cache when issuing BLKZEROOUT

Patch series "fallocate for block devices", v11.

This is a patchset to fix page cache coherency with BLKZEROOUT and
implement fallocate for block devices.

The first patch is a fix to the existing BLKZEROOUT ioctl to invalidate
the page cache if the zeroing command to the underlying device succeeds.
Without this patch we still have the pagecache coherence bug that's been
in the kernel forever.

The second patch changes the internal block device functions to reject
attempts to discard or zeroout that are not aligned to the logical block
size.  Previously, we only checked that the start/len parameters were
512-byte aligned, which caused kernel BUG_ONs for unaligned IOs to 4k-LBA

The third patch creates an fallocate handler for block devices, wires up
the FALLOC_FL_PUNCH_HOLE flag to zeroing-discard, and connects
FALLOC_FL_ZERO_RANGE to write-same so that we can have a consistent
fallocate interface between files and block devices.  It also allows the
combination of PUNCH_HOLE and NO_HIDE_STALE to invoke non-zeroing discard.

Test cases for the new block device fallocate are now in xfstests as

This patch (of 3):

Invalidate the page cache (as a regular O_DIRECT write would do) to avoid
returning stale cache contents at a later time.

Link: default avatarDarrick J. Wong <>
Reviewed-by: default avatarChristoph Hellwig <>
Reviewed-by: Martin K. Petersen's avatarMartin K. Petersen <>
Reviewed-by: default avatarBart Van Assche <>
Reviewed-by: default avatarHannes Reinecke <>
Cc: Theodore Ts'o <>
Cc: Mike Snitzer <>
Cc: Brian Foster <>
Cc: Jens Axboe <>
Signed-off-by: default avatarAndrew Morton <>
Signed-off-by: default avatarLinus Torvalds <>
parent 0cc482ee
......@@ -225,7 +225,8 @@ static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode,
unsigned long arg)
uint64_t range[2];
uint64_t start, len;
struct address_space *mapping;
uint64_t start, end, len;
if (!(mode & FMODE_WRITE))
return -EBADF;
......@@ -235,18 +236,23 @@ static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode,
start = range[0];
len = range[1];
end = start + len - 1;
if (start & 511)
return -EINVAL;
if (len & 511)
return -EINVAL;
start >>= 9;
len >>= 9;
if (start + len > (i_size_read(bdev->bd_inode) >> 9))
if (end >= (uint64_t)i_size_read(bdev->bd_inode))
return -EINVAL;
if (end < start)
return -EINVAL;
return blkdev_issue_zeroout(bdev, start, len, GFP_KERNEL, false);
/* Invalidate the page cache, including dirty pages */
mapping = bdev->bd_inode->i_mapping;
truncate_inode_pages_range(mapping, start, end);
return blkdev_issue_zeroout(bdev, start >> 9, len >> 9, GFP_KERNEL,
static int put_ushort(unsigned long arg, unsigned short val)
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