On Tue, Mar 12, 2024 at 08:45:27AM -0600, Christoph Hellwig wrote: > @@ -95,6 +95,8 @@ static int compat_blkpg_ioctl(struct block_device *bdev, > static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode, > unsigned long arg) > { > + sector_t bs_mask = (bdev_logical_block_size(bdev) >> SECTOR_SHIFT) - 1; > + sector_t sector, nr_sects; > uint64_t range[2]; > uint64_t start, len; > struct inode *inode = bdev->bd_inode; > @@ -105,18 +107,21 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode, > > 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))) > return -EFAULT; > > start = range[0]; > len = range[1]; > + sector = start >> SECTOR_SHIFT; > + nr_sects = len >> SECTOR_SHIFT; > > - if (start & 511) > + if (!nr_sects) > return -EINVAL; > - if (len & 511) > + if ((sector | nr_sects) & bs_mask) > return -EINVAL; > - > if (start + len > bdev_nr_bytes(bdev)) > return -EINVAL; > > @@ -124,7 +129,7 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode, > err = truncate_bdev_range(bdev, mode, start, start + len - 1); > if (err) > goto fail; > - err = blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_KERNEL); > + err = blkdev_issue_discard(bdev, sector, nr_sects, GFP_KERNEL); > fail: > filemap_invalidate_unlock(inode->i_mapping); > return err; > -- The incremental change I think you want atop this patch to keep the previous behavior: -- >8 -- diff --git b/block/ioctl.c a/block/ioctl.c index 57c8171fda93c..e14388548ab97 100644 --- b/block/ioctl.c +++ a/block/ioctl.c @@ -95,7 +95,7 @@ static int compat_blkpg_ioctl(struct block_device *bdev, static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode, unsigned long arg) { - sector_t bs_mask = (bdev_logical_block_size(bdev) >> SECTOR_SHIFT) - 1; + sector_t mask = bdev_logical_block_size(bdev) - 1; sector_t sector, nr_sects; uint64_t range[2]; uint64_t start, len; @@ -120,7 +120,7 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode, if (!nr_sects) return -EINVAL; - if ((sector | nr_sects) & bs_mask) + if ((start | len) & mask) return -EINVAL; if (start + len > bdev_nr_bytes(bdev)) return -EINVAL;