aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJens Axboe2010-07-15 11:49:31 -0500
committerJens Axboe2010-08-07 11:26:33 -0500
commit10d1f9e2ccfff40665a00ea0e0a0d11e54c9cbb1 (patch)
tree222c661376d8530a1bdf4e18cf5ff84267529bb3 /block/blk-lib.c
parentf10d9f617a65905c556c3b37c9b9646ae7d04ed7 (diff)
downloadkernel-common-10d1f9e2ccfff40665a00ea0e0a0d11e54c9cbb1.tar.gz
kernel-common-10d1f9e2ccfff40665a00ea0e0a0d11e54c9cbb1.tar.xz
kernel-common-10d1f9e2ccfff40665a00ea0e0a0d11e54c9cbb1.zip
block: fix problem with sending down discard that isn't of correct granularity
If the queue doesn't have a limit set, or it just set UINT_MAX like we default to, we coud be sending down a discard request that isn't of the correct granularity if the block size is > 512b. Fix this by adjusting max_discard_sectors down to the proper alignment. Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Diffstat (limited to 'block/blk-lib.c')
-rw-r--r--block/blk-lib.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/block/blk-lib.c b/block/blk-lib.c
index e16185b0d8e..5d793e143f3 100644
--- a/block/blk-lib.c
+++ b/block/blk-lib.c
@@ -41,6 +41,7 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
41 struct request_queue *q = bdev_get_queue(bdev); 41 struct request_queue *q = bdev_get_queue(bdev);
42 int type = flags & BLKDEV_IFL_BARRIER ? 42 int type = flags & BLKDEV_IFL_BARRIER ?
43 DISCARD_BARRIER : DISCARD_NOBARRIER; 43 DISCARD_BARRIER : DISCARD_NOBARRIER;
44 unsigned int max_discard_sectors;
44 struct bio *bio; 45 struct bio *bio;
45 int ret = 0; 46 int ret = 0;
46 47
@@ -50,10 +51,18 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
50 if (!blk_queue_discard(q)) 51 if (!blk_queue_discard(q))
51 return -EOPNOTSUPP; 52 return -EOPNOTSUPP;
52 53
53 while (nr_sects && !ret) { 54 /*
54 unsigned int max_discard_sectors = 55 * Ensure that max_discard_sectors is of the proper
55 min(q->limits.max_discard_sectors, UINT_MAX >> 9); 56 * granularity
57 */
58 max_discard_sectors = min(q->limits.max_discard_sectors, UINT_MAX >> 9);
59 if (q->limits.discard_granularity) {
60 unsigned int disc_sects = q->limits.discard_granularity >> 9;
56 61
62 max_discard_sectors &= ~(disc_sects - 1);
63 }
64
65 while (nr_sects && !ret) {
57 bio = bio_alloc(gfp_mask, 1); 66 bio = bio_alloc(gfp_mask, 1);
58 if (!bio) { 67 if (!bio) {
59 ret = -ENOMEM; 68 ret = -ENOMEM;