diff options
author | Adrian Hunter <adrian.hunter@nokia.com> | 2010-08-11 17:17:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-12 11:43:30 -0400 |
commit | 8d57a98ccd0b4489003473979da8f5a1363ba7a3 (patch) | |
tree | 2982997ce66bb6a92c020b7189966c3097095fd7 /block | |
parent | 93caf8e69eac763f6a20cf253ace8e7fc1ab7953 (diff) |
block: add secure discard
Secure discard is the same as discard except that all copies of the
discarded sectors (perhaps created by garbage collection) must also be
erased.
Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
Acked-by: Jens Axboe <axboe@kernel.dk>
Cc: Kyungmin Park <kmpark@infradead.org>
Cc: Madhusudhan Chikkature <madhu.cr@ti.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Ben Gardiner <bengardiner@nanometrics.ca>
Cc: <linux-mmc@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'block')
-rw-r--r-- | block/blk-core.c | 5 | ||||
-rw-r--r-- | block/blk-lib.c | 6 | ||||
-rw-r--r-- | block/compat_ioctl.c | 1 | ||||
-rw-r--r-- | block/elevator.c | 6 | ||||
-rw-r--r-- | block/ioctl.c | 15 |
5 files changed, 27 insertions, 6 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index 7da630e25ae7..ee1a1e7e63cc 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
@@ -1514,7 +1514,10 @@ static inline void __generic_make_request(struct bio *bio) | |||
1514 | if (bio_check_eod(bio, nr_sectors)) | 1514 | if (bio_check_eod(bio, nr_sectors)) |
1515 | goto end_io; | 1515 | goto end_io; |
1516 | 1516 | ||
1517 | if ((bio->bi_rw & REQ_DISCARD) && !blk_queue_discard(q)) { | 1517 | if ((bio->bi_rw & REQ_DISCARD) && |
1518 | (!blk_queue_discard(q) || | ||
1519 | ((bio->bi_rw & REQ_SECURE) && | ||
1520 | !blk_queue_secdiscard(q)))) { | ||
1518 | err = -EOPNOTSUPP; | 1521 | err = -EOPNOTSUPP; |
1519 | goto end_io; | 1522 | goto end_io; |
1520 | } | 1523 | } |
diff --git a/block/blk-lib.c b/block/blk-lib.c index c1fc55a83ba1..c392029a104e 100644 --- a/block/blk-lib.c +++ b/block/blk-lib.c | |||
@@ -62,6 +62,12 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, | |||
62 | max_discard_sectors &= ~(disc_sects - 1); | 62 | max_discard_sectors &= ~(disc_sects - 1); |
63 | } | 63 | } |
64 | 64 | ||
65 | if (flags & BLKDEV_IFL_SECURE) { | ||
66 | if (!blk_queue_secdiscard(q)) | ||
67 | return -EOPNOTSUPP; | ||
68 | type |= DISCARD_SECURE; | ||
69 | } | ||
70 | |||
65 | while (nr_sects && !ret) { | 71 | while (nr_sects && !ret) { |
66 | bio = bio_alloc(gfp_mask, 1); | 72 | bio = bio_alloc(gfp_mask, 1); |
67 | if (!bio) { | 73 | if (!bio) { |
diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index d53085637731..119f07b74dc0 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c | |||
@@ -703,6 +703,7 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) | |||
703 | case BLKFLSBUF: | 703 | case BLKFLSBUF: |
704 | case BLKROSET: | 704 | case BLKROSET: |
705 | case BLKDISCARD: | 705 | case BLKDISCARD: |
706 | case BLKSECDISCARD: | ||
706 | /* | 707 | /* |
707 | * the ones below are implemented in blkdev_locked_ioctl, | 708 | * the ones below are implemented in blkdev_locked_ioctl, |
708 | * but we call blkdev_ioctl, which gets the lock for us | 709 | * but we call blkdev_ioctl, which gets the lock for us |
diff --git a/block/elevator.c b/block/elevator.c index 816a7c8d6394..ec585c9554d3 100644 --- a/block/elevator.c +++ b/block/elevator.c | |||
@@ -83,6 +83,12 @@ int elv_rq_merge_ok(struct request *rq, struct bio *bio) | |||
83 | return 0; | 83 | return 0; |
84 | 84 | ||
85 | /* | 85 | /* |
86 | * Don't merge discard requests and secure discard requests | ||
87 | */ | ||
88 | if ((bio->bi_rw & REQ_SECURE) != (rq->bio->bi_rw & REQ_SECURE)) | ||
89 | return 0; | ||
90 | |||
91 | /* | ||
86 | * different data direction or already started, don't merge | 92 | * different data direction or already started, don't merge |
87 | */ | 93 | */ |
88 | if (bio_data_dir(bio) != rq_data_dir(rq)) | 94 | if (bio_data_dir(bio) != rq_data_dir(rq)) |
diff --git a/block/ioctl.c b/block/ioctl.c index 09fd7f1ef23a..d8052f0dabd3 100644 --- a/block/ioctl.c +++ b/block/ioctl.c | |||
@@ -114,8 +114,10 @@ static int blkdev_reread_part(struct block_device *bdev) | |||
114 | } | 114 | } |
115 | 115 | ||
116 | static int blk_ioctl_discard(struct block_device *bdev, uint64_t start, | 116 | static int blk_ioctl_discard(struct block_device *bdev, uint64_t start, |
117 | uint64_t len) | 117 | uint64_t len, int secure) |
118 | { | 118 | { |
119 | unsigned long flags = BLKDEV_IFL_WAIT; | ||
120 | |||
119 | if (start & 511) | 121 | if (start & 511) |
120 | return -EINVAL; | 122 | return -EINVAL; |
121 | if (len & 511) | 123 | if (len & 511) |
@@ -125,8 +127,9 @@ static int blk_ioctl_discard(struct block_device *bdev, uint64_t start, | |||
125 | 127 | ||
126 | if (start + len > (bdev->bd_inode->i_size >> 9)) | 128 | if (start + len > (bdev->bd_inode->i_size >> 9)) |
127 | return -EINVAL; | 129 | return -EINVAL; |
128 | return blkdev_issue_discard(bdev, start, len, GFP_KERNEL, | 130 | if (secure) |
129 | BLKDEV_IFL_WAIT); | 131 | flags |= BLKDEV_IFL_SECURE; |
132 | return blkdev_issue_discard(bdev, start, len, GFP_KERNEL, flags); | ||
130 | } | 133 | } |
131 | 134 | ||
132 | static int put_ushort(unsigned long arg, unsigned short val) | 135 | static int put_ushort(unsigned long arg, unsigned short val) |
@@ -213,7 +216,8 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, | |||
213 | set_device_ro(bdev, n); | 216 | set_device_ro(bdev, n); |
214 | return 0; | 217 | return 0; |
215 | 218 | ||
216 | case BLKDISCARD: { | 219 | case BLKDISCARD: |
220 | case BLKSECDISCARD: { | ||
217 | uint64_t range[2]; | 221 | uint64_t range[2]; |
218 | 222 | ||
219 | if (!(mode & FMODE_WRITE)) | 223 | if (!(mode & FMODE_WRITE)) |
@@ -222,7 +226,8 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, | |||
222 | if (copy_from_user(range, (void __user *)arg, sizeof(range))) | 226 | if (copy_from_user(range, (void __user *)arg, sizeof(range))) |
223 | return -EFAULT; | 227 | return -EFAULT; |
224 | 228 | ||
225 | return blk_ioctl_discard(bdev, range[0], range[1]); | 229 | return blk_ioctl_discard(bdev, range[0], range[1], |
230 | cmd == BLKSECDISCARD); | ||
226 | } | 231 | } |
227 | 232 | ||
228 | case HDIO_GETGEO: { | 233 | case HDIO_GETGEO: { |