Skip to contentSkip to conversation

fs: guard_bio_eod() needs to consider partitions

PATCH Superseded Greg Edwards 4 participants 8 messages Oct 24, 2017 – Nov 10, 2017 VFS

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 fs: guard_bio_eod() needs to consider partitions

guard_bio_eod() needs to look at the partition capacity, not just the capacity of the whole device, when determining if truncation is necessary.

[   60.268688] attempt to access beyond end of device
[   60.268690] unknown-block(9,1): rw=0, want=67103509, limit=67103506
[   60.268693] buffer_io_error: 2 callbacks suppressed
[   60.268696] Buffer I/O error on dev md1p7, logical block 4524305, async page read
Fixes 74d46992e0d9 ("block: replace bi_bdev with a gendisk pointer and partitions index")
---
 fs/buffer.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
fs/buffer.c +8 -1
index 170df856bdb9..989d3b085efe 100644
@@ -3055,8 +3055,15 @@ void guard_bio_eod(int op, struct bio *bio)
 	sector_t maxsector;
 	struct bio_vec *bvec = &bio->bi_io_vec[bio->bi_vcnt - 1];
 	unsigned truncated_bytes;
+	struct hd_struct *part;
+
+	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);
+	disk_put_part(part);
 
-	maxsector = get_capacity(bio->bi_disk);
 	if (!maxsector)
 		return;
 
Signature · 1 line
2.13.6
maintainer
#1 lore raw
Quoted 11 lines · Greg Edwards

guard_bio_eod() needs to look at the partition capacity, not just the capacity of the whole device, when determining if truncation is necessary.

[   60.268688] attempt to access beyond end of device
[   60.268690] unknown-block(9,1): rw=0, want=67103509, limit=67103506
[   60.268693] buffer_io_error: 2 callbacks suppressed
[   60.268696] Buffer I/O error on dev md1p7, logical block 4524305, async page read
Fixes 74d46992e0d9 ("block: replace bi_bdev with a gendisk pointer and partitions index")

That smells like a nasty source of overhead, especially on SMP boxen...

#2 lore raw
Quoted 4 lines · Al Viro
Quoted 2 lines
Fixes 74d46992e0d9 ("block: replace bi_bdev with a gendisk pointer and partitions index")

That smells like a nasty source of overhead, especially on SMP boxen...

We could just use __disk_get_part similar to the partition remapping, or just pass the block_device to guard_bio_eod.

#3 lore raw
Quoted 8 lines · Christoph Hellwig
Quoted 4 lines · Al Viro
Quoted 2 lines
Fixes 74d46992e0d9 ("block: replace bi_bdev with a gendisk pointer and partitions index")

That smells like a nasty source of overhead, especially on SMP boxen...

We could just use __disk_get_part similar to the partition remapping, or just pass the block_device to guard_bio_eod.

Do you have a preference? __disk_get_part would be isolated to guard_bio_eod. If we pass in the block_device, it would also touch all the mpage_bio_submit callers.

#4 lore raw

PATCH v2 1/1 fs: guard_bio_eod() needs to consider partitions

In reply to Greg Edwards

guard_bio_eod() needs to look at the partition capacity, not just the capacity of the whole device, when determining if truncation is necessary.

[   60.268688] attempt to access beyond end of device
[   60.268690] unknown-block(9,1): rw=0, want=67103509, limit=67103506
[   60.268693] buffer_io_error: 2 callbacks suppressed
[   60.268696] Buffer I/O error on dev md1p7, logical block 4524305, async page read
Fixes 74d46992e0d9 ("block: replace bi_bdev with a gendisk pointer and partitions index")

---
Changes from v1:
* use __disk_get_part instead of disk_get_part, similar to what blk_partition_remap does

 fs/buffer.c           | 10 +++++++++-
 include/linux/genhd.h |  1 +
 2 files changed, 10 insertions(+), 1 deletion(-)
fs/buffer.c +9 -1
index 170df856bdb9..b96f3b98a6ef 100644
@@ -3055,8 +3055,16 @@ void guard_bio_eod(int op, struct bio *bio)
 	sector_t maxsector;
 	struct bio_vec *bvec = &bio->bi_io_vec[bio->bi_vcnt - 1];
 	unsigned truncated_bytes;
+	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();
 
-	maxsector = get_capacity(bio->bi_disk);
 	if (!maxsector)
 		return;
 
include/linux/genhd.h +1 -0
index ea652bfcd675..cb8c5fd74b71 100644
@@ -242,6 +242,7 @@ static inline dev_t part_devt(struct hd_struct *part)
 	return part_to_dev(part)->devt;
 }
 
+extern struct hd_struct *__disk_get_part(struct gendisk *disk, int partno);
 extern struct hd_struct *disk_get_part(struct gendisk *disk, int partno);
 
 static inline void disk_put_part(struct hd_struct *part)
Signature · 1 line
2.13.6
#5 lore raw
Quoted 9 lines · Greg Edwards

guard_bio_eod() needs to look at the partition capacity, not just the capacity of the whole device, when determining if truncation is necessary.

[   60.268688] attempt to access beyond end of device
[   60.268690] unknown-block(9,1): rw=0, want=67103509, limit=67103506
[   60.268693] buffer_io_error: 2 callbacks suppressed
[   60.268696] Buffer I/O error on dev md1p7, logical block 4524305, async page read
Quoted 6 lines
Fixes 74d46992e0d9 ("block: replace bi_bdev with a gendisk pointer and partitions index")

---
Changes from v1:
* use __disk_get_part instead of disk_get_part, similar to what blk_partition_remap does

Al, Christoph,

Any thoughts on this version?

It would be nice to get this fixed before 4.14 goes out, as this is a regression from previous releases.

Greg

#7 lore raw
Quoted 6 lines · Christoph Hellwig

This looks good to me:

Jens, can you pick it up through the block tree given that is where the issue was introduced?

I picked it up, and marked it for 4.13 stable as well.

Signature · 1 line
Jens Axboe