Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 322216
b: refs/heads/master
c: c6e6663
h: refs/heads/master
v: v3
  • Loading branch information
Paolo Bonzini authored and Jens Axboe committed Aug 2, 2012
1 parent 02a6477 commit 64e4485
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 11 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f6ff53d3611b564661896be23369b54d84941a0e
refs/heads/master: c6e666345e1b79c62ba82339cc7d55a89cb73f88
34 changes: 24 additions & 10 deletions trunk/block/blk-lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
struct request_queue *q = bdev_get_queue(bdev);
int type = REQ_WRITE | REQ_DISCARD;
unsigned int max_discard_sectors;
unsigned int granularity;
unsigned int granularity, alignment, mask;
struct bio_batch bb;
struct bio *bio;
int ret = 0;
Expand All @@ -57,10 +57,12 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,

/* Zero-sector (unknown) and one-sector granularities are the same. */
granularity = max(q->limits.discard_granularity >> 9, 1U);
mask = granularity - 1;
alignment = (bdev_discard_alignment(bdev) >> 9) & mask;

/*
* Ensure that max_discard_sectors is of the proper
* granularity
* granularity, so that requests stay aligned after a split.
*/
max_discard_sectors = min(q->limits.max_discard_sectors, UINT_MAX >> 9);
max_discard_sectors = round_down(max_discard_sectors, granularity);
Expand All @@ -80,25 +82,37 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
bb.wait = &wait;

while (nr_sects) {
unsigned int req_sects;
sector_t end_sect;

bio = bio_alloc(gfp_mask, 1);
if (!bio) {
ret = -ENOMEM;
break;
}

req_sects = min_t(sector_t, nr_sects, max_discard_sectors);

/*
* If splitting a request, and the next starting sector would be
* misaligned, stop the discard at the previous aligned sector.
*/
end_sect = sector + req_sects;
if (req_sects < nr_sects && (end_sect & mask) != alignment) {
end_sect =
round_down(end_sect - alignment, granularity)
+ alignment;
req_sects = end_sect - sector;
}

bio->bi_sector = sector;
bio->bi_end_io = bio_batch_end_io;
bio->bi_bdev = bdev;
bio->bi_private = &bb;

if (nr_sects > max_discard_sectors) {
bio->bi_size = max_discard_sectors << 9;
nr_sects -= max_discard_sectors;
sector += max_discard_sectors;
} else {
bio->bi_size = nr_sects << 9;
nr_sects = 0;
}
bio->bi_size = req_sects << 9;
nr_sects -= req_sects;
sector = end_sect;

atomic_inc(&bb.done);
submit_bio(type, bio);
Expand Down
10 changes: 10 additions & 0 deletions trunk/include/linux/blkdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -1139,6 +1139,16 @@ static inline int queue_limit_discard_alignment(struct queue_limits *lim, sector
& (lim->discard_granularity - 1);
}

static inline int bdev_discard_alignment(struct block_device *bdev)
{
struct request_queue *q = bdev_get_queue(bdev);

if (bdev != bdev->bd_contains)
return bdev->bd_part->discard_alignment;

return q->limits.discard_alignment;
}

static inline unsigned int queue_discard_zeroes_data(struct request_queue *q)
{
if (q->limits.max_discard_sectors && q->limits.discard_zeroes_data == 1)
Expand Down

0 comments on commit 64e4485

Please sign in to comment.