Skip to content

Commit

Permalink
block: Hold invalidate_lock in BLKRESETZONE ioctl
Browse files Browse the repository at this point in the history
When BLKRESETZONE ioctl and data read race, the data read leaves stale
page cache. The commit e511350 ("block: Discard page cache of zone
reset target range") added page cache truncation to avoid stale page
cache after the ioctl. However, the stale page cache still can be read
during the reset zone operation for the ioctl. To avoid the stale page
cache completely, hold invalidate_lock of the block device file mapping.

Fixes: e511350 ("block: Discard page cache of zone reset target range")
Signed-off-by: Shin'ichiro Kawasaki <[email protected]>
Cc: [email protected] # v5.15
Reviewed-by: Jan Kara <[email protected]>
Reviewed-by: Ming Lei <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Jens Axboe <[email protected]>
  • Loading branch information
kawasaki authored and axboe committed Nov 11, 2021
1 parent b131f20 commit 86399ea
Showing 1 changed file with 5 additions and 10 deletions.
15 changes: 5 additions & 10 deletions block/blk-zoned.c
Original file line number Diff line number Diff line change
Expand Up @@ -429,9 +429,10 @@ int blkdev_zone_mgmt_ioctl(struct block_device *bdev, fmode_t mode,
op = REQ_OP_ZONE_RESET;

/* Invalidate the page cache, including dirty pages. */
filemap_invalidate_lock(bdev->bd_inode->i_mapping);
ret = blkdev_truncate_zone_range(bdev, mode, &zrange);
if (ret)
return ret;
goto fail;
break;
case BLKOPENZONE:
op = REQ_OP_ZONE_OPEN;
Expand All @@ -449,15 +450,9 @@ int blkdev_zone_mgmt_ioctl(struct block_device *bdev, fmode_t mode,
ret = blkdev_zone_mgmt(bdev, op, zrange.sector, zrange.nr_sectors,
GFP_KERNEL);

/*
* Invalidate the page cache again for zone reset: writes can only be
* direct for zoned devices so concurrent writes would not add any page
* to the page cache after/during reset. The page cache may be filled
* again due to concurrent reads though and dropping the pages for
* these is fine.
*/
if (!ret && cmd == BLKRESETZONE)
ret = blkdev_truncate_zone_range(bdev, mode, &zrange);
fail:
if (cmd == BLKRESETZONE)
filemap_invalidate_unlock(bdev->bd_inode->i_mapping);

return ret;
}
Expand Down

0 comments on commit 86399ea

Please sign in to comment.