Skip to content

Commit

Permalink
block: count physical segments through multipage biovecs
Browse files Browse the repository at this point in the history
As it's now possible for biovecs to have multiple pages,
__blk_recalc_rq_segments() should also support iterating biovecs
using bio_for_each_page() for each bio. Otherwise kernel could
occasionally crash with the following bug, especially when tested
with virtio-blk.

------------[ cut here ]------------
kernel BUG at drivers/block/virtio_blk.c:172!
CPU: 1 PID: 13523 Comm: mount Not tainted 3.18.0+ torvalds#106
Call Trace:
 [<ffffffff814ddb78>] __blk_mq_run_hw_queue+0x1b8/0x310
 [<ffffffff814de53d>] blk_mq_run_hw_queue+0x6d/0x90
 [<ffffffff814df49d>] blk_mq_insert_requests+0xfd/0x2c0
 [<ffffffff814e03bb>] blk_mq_flush_plug_list+0x12b/0x140
 [<ffffffff814d4aa1>] blk_flush_plug_list+0xb1/0x200
 [<ffffffff814d51a8>] blk_finish_plug+0x18/0x50
 [<ffffffff813845de>] _xfs_buf_ioapply+0x2fe/0x3e0
 [<ffffffff813858a6>] ? xfs_bwrite+0x46/0x80
 [<ffffffff81384de2>] xfs_buf_submit_wait+0xb2/0x6d0
 [<ffffffff813858a6>] xfs_bwrite+0x46/0x80
 [<ffffffff813bba44>] xlog_bwrite+0xc4/0x160
 [<ffffffff813bcb5b>] xlog_write_log_records+0x1ab/0x240
 [<ffffffff813bcd00>] xlog_clear_stale_blocks+0x110/0x1e0
 [<ffffffff813bd10b>] xlog_find_tail+0x33b/0x430
 [<ffffffff813c3a7e>] xlog_recover+0x1e/0xf0
 [<ffffffff813af73c>] xfs_log_mount+0x28c/0x300
 [<ffffffff813a4dc5>] xfs_mountfs+0x4a5/0x9c0
 [<ffffffff813a9672>] xfs_fs_fill_super+0x312/0x390
 [<ffffffff812237a4>] mount_bdev+0x1a4/0x1e0
 [<ffffffff813a9360>] ? xfs_finish_flags+0x170/0x170
 [<ffffffff813a7255>] xfs_fs_mount+0x15/0x20
 [<ffffffff81224129>] mount_fs+0x39/0x1b0
 [<ffffffff811c7495>] ? __alloc_percpu+0x15/0x20
 [<ffffffff8124372b>] vfs_kern_mount+0x6b/0x150
 [<ffffffff81246680>] do_mount+0x210/0xb90
 [<ffffffff811d181f>] ? might_fault+0x5f/0xb0
 [<ffffffff8124733b>] SyS_mount+0x8b/0xe0
 [<ffffffff817e3092>] system_call_fastpath+0x12/0x17
RIP [<ffffffff81620c27>] virtio_queue_rq+0x277/0x280
---[ end trace d56c2abcb8ac6962 ]---

Signed-off-by: Dongsu Park <[email protected]>
  • Loading branch information
Dongsu Park committed Dec 29, 2014
1 parent a84a484 commit 14b230b
Showing 1 changed file with 9 additions and 7 deletions.
16 changes: 9 additions & 7 deletions block/blk-merge.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
bool no_sg_merge)
{
unsigned nr_phys_segs = 0;
struct bio_vec bvec;
struct bvec_iter iter;

if (!bio)
return 0;
Expand All @@ -195,14 +197,14 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
return 1;

for_each_bio(bio) {
struct bvec_iter iter = bio->bi_iter;

while (iter.bi_size) {
struct bio_vec bv = bio_iter_iovec(bio, iter);
unsigned nbytes = blk_max_segment(q, &bv);
bio_for_each_page(bvec, bio, iter) {
while (iter.bi_size) {
struct bio_vec bv = bio_iter_iovec(bio, iter);
unsigned nbytes = blk_max_segment(q, &bv);

nr_phys_segs++;
bio_advance_iter(bio, &iter, nbytes);
nr_phys_segs++;
bio_advance_iter(bio, &iter, nbytes);
}
}
}

Expand Down

0 comments on commit 14b230b

Please sign in to comment.