diff options
| author | Christoph Hellwig <hch@lst.de> | 2020-03-25 16:48:40 +0100 | 
|---|---|---|
| committer | Jens Axboe <axboe@kernel.dk> | 2020-03-25 09:50:08 -0600 | 
| commit | 29125ed624eeb3ac2eb7bca313a8de29c1c84dcd (patch) | |
| tree | 1d728350d5aef28aa3ac2a343d8768292427d066 /block | |
| parent | 1b4d4dbdaeb7087122a39d3fb9ae32487e001b6c (diff) | |
| download | linux-29125ed624eeb3ac2eb7bca313a8de29c1c84dcd.tar.bz2 | |
block: move guard_bio_eod to bio.c
This is bio layer functionality and not related to buffer heads.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block')
| -rw-r--r-- | block/bio.c | 43 | 
1 files changed, 43 insertions, 0 deletions
diff --git a/block/bio.c b/block/bio.c index bc9152977bf0..11e6aac35092 100644 --- a/block/bio.c +++ b/block/bio.c @@ -589,6 +589,49 @@ void bio_truncate(struct bio *bio, unsigned new_size)  }  /** + * guard_bio_eod - truncate a BIO to fit the block device + * @bio:	bio to truncate + * + * This allows us to do IO even on the odd last sectors of a device, even if the + * block size is some multiple of the physical sector size. + * + * We'll just truncate the bio to the size of the device, and clear the end of + * the buffer head manually.  Truly out-of-range accesses will turn into actual + * I/O errors, this only handles the "we need to be able to do I/O at the final + * sector" case. + */ +void guard_bio_eod(struct bio *bio) +{ +	sector_t maxsector; +	struct hd_struct *part; + +	rcu_read_lock(); +	part = __disk_get_part(bio->bi_disk, bio->bi_partno); +	if (part) +		maxsector = part_nr_sects_read(part); +	else +		maxsector = get_capacity(bio->bi_disk); +	rcu_read_unlock(); + +	if (!maxsector) +		return; + +	/* +	 * If the *whole* IO is past the end of the device, +	 * let it through, and the IO layer will turn it into +	 * an EIO. +	 */ +	if (unlikely(bio->bi_iter.bi_sector >= maxsector)) +		return; + +	maxsector -= bio->bi_iter.bi_sector; +	if (likely((bio->bi_iter.bi_size >> 9) <= maxsector)) +		return; + +	bio_truncate(bio, maxsector << 9); +} + +/**   * bio_put - release a reference to a bio   * @bio:   bio to release reference to   *  |