From 443b0a4f72e2c4cb6d906537163da4209ecf3bd5 Mon Sep 17 00:00:00 2001 From: Ming Lin Date: Tue, 16 Dec 2014 20:41:35 -0800 Subject: [PATCH] virtio_blk: allow blk-mq to merge scatter gather lists As it's now possible to have arbitrary number of segments, mq-capable block drivers should set BLK_MQ_F_SG_MERGE in q->queue_flags. Especially virtio_blk must do it, __blk_segment_map_sg() may create too large sg lists. When QUEUE_FLAG_NO_SG_MERGE turned on, such sg lists could later trigger BUG_ON(total_sg > vq->vring.num) in virtqueue_add(). [ 26.763457] ------------[ cut here ]------------ [ 26.764147] kernel BUG at /home/mlin/linux/drivers/virtio/virtio_ring.c:160! [ 26.765010] invalid opcode: 0000 [#1] PREEMPT SMP [ 26.765273] Modules linked in: [ 26.765273] CPU: 3 PID: 25 Comm: kworker/u8:1 Not tainted 3.18.0-00030-g141405f #73 [ 26.765273] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.7.5.1-0-g8936dbb-20141113_115728-nilsson.home.kraxel.org 04/01/2014 [ 26.765273] Workqueue: writeback bdi_writeback_workfn (flush-254:0) [ 26.765273] task: ffff88001ebf0950 ti: ffff88001ebfc000 task.ti: ffff88001ebfc000 [ 26.765273] RIP: 0010:[] [] virtqueue_add_sgs+0x70/0x2fe [ 26.765273] RSP: 0000:ffff88001ebff6a8 EFLAGS: 00010002 [ 26.765273] RAX: 0000000000000000 RBX: ffff88001e1ad000 RCX: ffffea0000698540 [ 26.765273] RDX: ffffea0000698500 RSI: ffff88001ebff7c8 RDI: ffff88001ebff748 [ 26.765273] RBP: ffff88001ebff708 R08: ffff88001d911330 R09: 0000000000000020 [ 26.765273] R10: 0000160000000000 R11: ffff88001d7f0000 R12: ffff88001ebff7c8 [ 26.765273] R13: 0000000000000002 R14: 0000000000000082 R15: 0000000000000003 [ 26.777232] FS: 0000000000000000(0000) GS:ffff88001fd80000(0000) knlGS:0000000000000000 [ 26.777232] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 26.777232] CR2: 00007fd84f9e5000 CR3: 000000001cf6a000 CR4: 00000000000006e0 [ 26.777232] Stack: [ 26.777232] ffff88000000007f ffff880000000020 ffff88001ebff7d8 ffff88001d911330 [ 26.777232] 01ffea0000000003 0000007f00000080 0000000000000418 0000000000000000 [ 26.777232] ffff88001ebff748 ffff88001d911360 0000000000000002 ffff88001d911330 [ 26.777232] Call Trace: [ 26.777232] [] __virtblk_add_req+0x137/0x149 [ 26.777232] [] ? part_round_stats+0x52/0x59 [ 26.777232] [] ? __blk_segment_map_sg+0xbd/0x190 [ 26.777232] [] ? blk_rq_map_sg+0xb6/0x1cc [ 26.777232] [] virtio_queue_rq+0x14e/0x1ee [ 26.777232] [] __blk_mq_run_hw_queue+0x1ac/0x2ad [ 26.777232] [] blk_mq_run_hw_queue+0x3d/0x77 [ 26.777232] [] blk_mq_insert_requests+0x103/0x156 [ 26.777232] [] blk_mq_flush_plug_list+0xeb/0xfa [ 26.777232] [] blk_flush_plug_list+0xb8/0x1e1 [ 26.777232] [] blk_finish_plug+0x16/0x38 [ 26.777232] [] ext4_writepages+0x973/0xb66 [ 26.777232] [] do_writepages+0x1e/0x2c [ 26.777232] [] __writeback_single_inode+0x84/0x298 [ 26.777232] [] ? wake_up_bit+0x25/0x2a [ 26.777232] [] writeback_sb_inodes+0x1fc/0x33d [ 26.777232] [] __writeback_inodes_wb+0x74/0xb9 [ 26.777232] [] wb_writeback+0x14c/0x2eb [ 26.777232] [] ? global_dirty_limits+0x1b/0x117 [ 26.777232] [] bdi_writeback_workfn+0x1f6/0x40c [ 26.777232] [] process_one_work+0x1ca/0x376 [ 26.777232] [] worker_thread+0x267/0x366 [ 26.777232] [] ? process_scheduled_works+0x2f/0x2f [ 26.777232] [] kthread+0xd2/0xda [ 26.777232] [] ? ldsem_down_write+0x6/0x19f [ 26.777232] [] ? kthread_freezable_should_stop+0x48/0x48 [ 26.777232] [] ret_from_fork+0x7c/0xb0 [ 26.777232] [] ? kthread_freezable_should_stop+0x48/0x48 Signed-off-by: Ming Lin [dpark: added a precise description] Signed-off-by: Dongsu Park --- drivers/block/virtio_blk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 7ef7c098708fc4..ed27194916a932 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -626,7 +626,7 @@ static int virtblk_probe(struct virtio_device *vdev) vblk->tag_set.ops = &virtio_mq_ops; vblk->tag_set.queue_depth = virtblk_queue_depth; vblk->tag_set.numa_node = NUMA_NO_NODE; - vblk->tag_set.flags = BLK_MQ_F_SHOULD_MERGE; + vblk->tag_set.flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_SG_MERGE; vblk->tag_set.cmd_size = sizeof(struct virtblk_req) + sizeof(struct scatterlist) * sg_elems;