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 <dmonak...@openvz.org>
---
 block/ioctl.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/block/ioctl.c b/block/ioctl.c
index 7b88820..d1fea45 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -202,10 +202,15 @@ 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;
 
        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 +221,15 @@ 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);
+
+       mapping = bdev->bd_inode->i_mapping;
+       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,
-- 
2.9.3

Reply via email to