This allows more requests to fit in the descriptor ring. Copying 1.7M kernel image 100 times (with sync between) Before: totsegs = 55661 totlen = 148859962 avg. 2674 After: totsegs = 36097 totlen = 139439355 avg: 3862 Unfortunately, this coalescing is done at blk_rq_map_sg() which is too late to be optimal: requests have already been limited to the value set by blk_queue_max_hw_segments(). For us, that value reflects the number of sg slots we can handle (ie. after clustering). I suspect other drivers have the same issue. Jens? (This patch is a one liner + temporary stats-gathering cruft for show) Signed-off-by: Rusty Russell <rusty@xxxxxxxxxxxxxxx> --- drivers/block/virtio_blk.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff -r 35ec755dd1d6 drivers/block/virtio_blk.c --- a/drivers/block/virtio_blk.c Wed Nov 12 22:41:12 2008 +1030 +++ b/drivers/block/virtio_blk.c Fri Nov 14 11:06:03 2008 +1030 @@ -37,6 +37,8 @@ struct virtio_blk_outhdr out_hdr; u8 status; }; + +static unsigned long totlen, totsegs; static void blk_done(struct virtqueue *vq) { @@ -102,7 +104,6 @@ sg_set_buf(&vblk->sg[0], &vbr->out_hdr, sizeof(vbr->out_hdr)); num = blk_rq_map_sg(q, vbr->req, vblk->sg+1); sg_set_buf(&vblk->sg[num+1], &vbr->status, sizeof(vbr->status)); - if (rq_data_dir(vbr->req) == WRITE) { vbr->out_hdr.type |= VIRTIO_BLK_T_OUT; out = 1 + num; @@ -111,6 +112,13 @@ vbr->out_hdr.type |= VIRTIO_BLK_T_IN; out = 1; in = 1 + num; + } + + totsegs += out + in + 1; + { + unsigned int i; + for (i = 0; i < num+2; i++) + totlen += vblk->sg[i].length; } if (vblk->vq->vq_ops->add_buf(vblk->vq, vblk->sg, out, in, vbr)) { @@ -176,6 +184,9 @@ geo->sectors = 1 << 5; geo->cylinders = get_capacity(bd->bd_disk) >> 11; } + + printk("totsegs = %lu totlen = %lu\n", totsegs, totlen); + totsegs = totlen = 0; return 0; } @@ -260,6 +271,9 @@ /* If barriers are supported, tell block layer that queue is ordered */ if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER)) blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL); + + /* Gather adjacent buffers to minimize sg length. */ + queue_flag_set(QUEUE_FLAG_CLUSTER, vblk->disk->queue); /* If disk is read-only in the host, the guest should obey */ if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO)) _______________________________________________ Virtualization mailing list Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/virtualization