mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
block: introduce blk_validate_byte_range()
In preparation to further changes extract a helper function out of blk_ioctl_discard() that validates if we can do IO against the given range of disk byte addresses. Signed-off-by: Pavel Begunkov <asml.silence@gmail.com> Link: https://lore.kernel.org/r/19a7779323c71e742a2f511e4cf49efcfd68cfd4.1726072086.git.asml.silence@gmail.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
a12c883a0a
commit
7a07210bbc
@ -92,41 +92,54 @@ static int compat_blkpg_ioctl(struct block_device *bdev,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that [start, start + len) is a valid range from the block device's
|
||||||
|
* perspective, including verifying that it can be correctly translated into
|
||||||
|
* logical block addresses.
|
||||||
|
*/
|
||||||
|
static int blk_validate_byte_range(struct block_device *bdev,
|
||||||
|
uint64_t start, uint64_t len)
|
||||||
|
{
|
||||||
|
unsigned int bs_mask = bdev_logical_block_size(bdev) - 1;
|
||||||
|
uint64_t end;
|
||||||
|
|
||||||
|
if ((start | len) & bs_mask)
|
||||||
|
return -EINVAL;
|
||||||
|
if (!len)
|
||||||
|
return -EINVAL;
|
||||||
|
if (check_add_overflow(start, len, &end) || end > bdev_nr_bytes(bdev))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode,
|
static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode,
|
||||||
unsigned long arg)
|
unsigned long arg)
|
||||||
{
|
{
|
||||||
unsigned int bs_mask = bdev_logical_block_size(bdev) - 1;
|
uint64_t range[2], start, len;
|
||||||
uint64_t range[2], start, len, end;
|
|
||||||
struct bio *prev = NULL, *bio;
|
struct bio *prev = NULL, *bio;
|
||||||
sector_t sector, nr_sects;
|
sector_t sector, nr_sects;
|
||||||
struct blk_plug plug;
|
struct blk_plug plug;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!(mode & BLK_OPEN_WRITE))
|
|
||||||
return -EBADF;
|
|
||||||
|
|
||||||
if (!bdev_max_discard_sectors(bdev))
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
if (bdev_read_only(bdev))
|
|
||||||
return -EPERM;
|
|
||||||
|
|
||||||
if (copy_from_user(range, (void __user *)arg, sizeof(range)))
|
if (copy_from_user(range, (void __user *)arg, sizeof(range)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
start = range[0];
|
start = range[0];
|
||||||
len = range[1];
|
len = range[1];
|
||||||
|
|
||||||
if (!len)
|
if (!bdev_max_discard_sectors(bdev))
|
||||||
return -EINVAL;
|
return -EOPNOTSUPP;
|
||||||
if ((start | len) & bs_mask)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (check_add_overflow(start, len, &end) ||
|
if (!(mode & BLK_OPEN_WRITE))
|
||||||
end > bdev_nr_bytes(bdev))
|
return -EBADF;
|
||||||
return -EINVAL;
|
if (bdev_read_only(bdev))
|
||||||
|
return -EPERM;
|
||||||
|
err = blk_validate_byte_range(bdev, start, len);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
filemap_invalidate_lock(bdev->bd_mapping);
|
filemap_invalidate_lock(bdev->bd_mapping);
|
||||||
err = truncate_bdev_range(bdev, mode, start, end - 1);
|
err = truncate_bdev_range(bdev, mode, start, start + len - 1);
|
||||||
if (err)
|
if (err)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user