summaryrefslogtreecommitdiffstats
path: root/block/ioctl.c
diff options
context:
space:
mode:
authorDmitry Monakhov <dmonakhov@openvz.org>2017-10-24 18:44:57 -0600
committerJens Axboe <axboe@kernel.dk>2017-10-24 18:44:57 -0600
commit351499a172c0c5fc52d65ee2c62b344f369ea02a (patch)
treef4ae426a9204fe49711a0d79f57d825fc7063706 /block/ioctl.c
parent75bc5f06617fe1bc9a79ba9e3baccdcae3743404 (diff)
downloadlinux-351499a172c0c5fc52d65ee2c62b344f369ea02a.tar.bz2
block: Invalidate cache on discard v2
It is reasonable drop page cache on discard, otherwise that pages may be written by writeback second later, so thin provision devices will not be happy. This seems to be a security leak in case of secure discard case. Also add check for queue_discard flag on early stage. Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block/ioctl.c')
-rw-r--r--block/ioctl.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/block/ioctl.c b/block/ioctl.c
index 0de02ee67eed..c0fc32bd8ed1 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -202,10 +202,16 @@ static int blk_ioctl_discard(struct block_device *bdev, fmode_t mode,
{
uint64_t range[2];
uint64_t start, len;
+ struct request_queue *q = bdev_get_queue(bdev);
+ struct address_space *mapping = bdev->bd_inode->i_mapping;
+
if (!(mode & FMODE_WRITE))
return -EBADF;
+ if (!blk_queue_discard(q))
+ return -EOPNOTSUPP;
+
if (copy_from_user(range, (void __user *)arg, sizeof(range)))
return -EFAULT;
@@ -216,12 +222,12 @@ static int blk_ioctl_discard(struct block_device *bdev, fmode_t mode,
return -EINVAL;
if (len & 511)
return -EINVAL;
- start >>= 9;
- len >>= 9;
- if (start + len > (i_size_read(bdev->bd_inode) >> 9))
+ if (start + len > i_size_read(bdev->bd_inode))
return -EINVAL;
- return blkdev_issue_discard(bdev, start, len, GFP_KERNEL, flags);
+ truncate_inode_pages_range(mapping, start, start + len);
+ return blkdev_issue_discard(bdev, start >> 9, len >> 9,
+ GFP_KERNEL, flags);
}
static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode,