Message ID | 20211109104723.835533-3-shinichiro.kawasaki@wdc.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | block: Fix stale page cache of discard or zero out ioctl | expand |
On Tue 09-11-21 19:47:23, Shin'ichiro Kawasaki wrote: > When BLKZEROOUT ioctl and data read race, the data read leaves stale > page cache. To avoid the stale page cache, hold invalidate_lock of the > block device file mapping. The stale page cache is observed when > blktests test case block/009 is modified to call "blkdiscard -z" command > and repeated hundreds of times. > > This patch can be applied back to the stable kernel version v5.15.y. > Rework is required for older stable kernels. > > Fixes: 22dd6d356628 ("block: invalidate the page cache when issuing BLKZEROOUT") > Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com> > Cc: stable@vger.kernel.org # v5.15 Looks good to me. Feel free to add: Reviewed-by: Jan Kara <jack@suse.cz> Honza > --- > block/ioctl.c | 12 +++++++++--- > 1 file changed, 9 insertions(+), 3 deletions(-) > > diff --git a/block/ioctl.c b/block/ioctl.c > index 9fa87f64f703..0a1d10ac2e1a 100644 > --- a/block/ioctl.c > +++ b/block/ioctl.c > @@ -154,6 +154,7 @@ static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode, > { > uint64_t range[2]; > uint64_t start, end, len; > + struct inode *inode = bdev->bd_inode; > int err; > > if (!(mode & FMODE_WRITE)) > @@ -176,12 +177,17 @@ static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode, > return -EINVAL; > > /* Invalidate the page cache, including dirty pages */ > + filemap_invalidate_lock(inode->i_mapping); > err = truncate_bdev_range(bdev, mode, start, end); > if (err) > - return err; > + goto fail; > + > + err = blkdev_issue_zeroout(bdev, start >> 9, len >> 9, GFP_KERNEL, > + BLKDEV_ZERO_NOUNMAP); > > - return blkdev_issue_zeroout(bdev, start >> 9, len >> 9, GFP_KERNEL, > - BLKDEV_ZERO_NOUNMAP); > +fail: > + filemap_invalidate_unlock(inode->i_mapping); > + return err; > } > > static int put_ushort(unsigned short __user *argp, unsigned short val) > -- > 2.33.1 >
diff --git a/block/ioctl.c b/block/ioctl.c index 9fa87f64f703..0a1d10ac2e1a 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -154,6 +154,7 @@ static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode, { uint64_t range[2]; uint64_t start, end, len; + struct inode *inode = bdev->bd_inode; int err; if (!(mode & FMODE_WRITE)) @@ -176,12 +177,17 @@ static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode, return -EINVAL; /* Invalidate the page cache, including dirty pages */ + filemap_invalidate_lock(inode->i_mapping); err = truncate_bdev_range(bdev, mode, start, end); if (err) - return err; + goto fail; + + err = blkdev_issue_zeroout(bdev, start >> 9, len >> 9, GFP_KERNEL, + BLKDEV_ZERO_NOUNMAP); - return blkdev_issue_zeroout(bdev, start >> 9, len >> 9, GFP_KERNEL, - BLKDEV_ZERO_NOUNMAP); +fail: + filemap_invalidate_unlock(inode->i_mapping); + return err; } static int put_ushort(unsigned short __user *argp, unsigned short val)
When BLKZEROOUT ioctl and data read race, the data read leaves stale page cache. To avoid the stale page cache, hold invalidate_lock of the block device file mapping. The stale page cache is observed when blktests test case block/009 is modified to call "blkdiscard -z" command and repeated hundreds of times. This patch can be applied back to the stable kernel version v5.15.y. Rework is required for older stable kernels. Fixes: 22dd6d356628 ("block: invalidate the page cache when issuing BLKZEROOUT") Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com> Cc: stable@vger.kernel.org # v5.15 --- block/ioctl.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)