Ming Lei
2014-May-30 02:49 UTC
[PATCH] block: virtio_blk: don't hold spin lock during world switch
Firstly, it isn't necessary to hold lock of vblk->vq_lock when notifying hypervisor about queued I/O. Secondly, virtqueue_notify() will cause world switch and it may take long time on some hypervisors(such as, qemu-arm), so it isn't good to hold the lock and block other vCPUs. On arm64 quad core VM(qemu-kvm), the patch can increase I/O performance a lot with VIRTIO_RING_F_EVENT_IDX enabled: - without the patch: 14K IOPS - with the patch: 34K IOPS fio script: [global] direct=1 bsrange=4k-4k timeout=10 numjobs=4 ioengine=libaio iodepth=64 filename=/dev/vdc group_reporting=1 [f1] rw=randread Cc: Rusty Russell <rusty at rustcorp.com.au> Cc: "Michael S. Tsirkin" <mst at redhat.com> Cc: virtualization at lists.linux-foundation.org Signed-off-by: Ming Lei <ming.lei at canonical.com> --- drivers/block/virtio_blk.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 9f340fa..a6f5424 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -162,6 +162,7 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req) unsigned int num; const bool last = (req->cmd_flags & REQ_END) != 0; int err; + bool notify = false; BUG_ON(req->nr_phys_segments + 2 > vblk->sg_elems); @@ -214,10 +215,12 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req) return BLK_MQ_RQ_QUEUE_ERROR; } - if (last) - virtqueue_kick(vblk->vq); - + if (last && virtqueue_kick_prepare(vblk->vq)) + notify = true; spin_unlock_irqrestore(&vblk->vq_lock, flags); + + if (notify) + virtqueue_notify(vblk->vq); return BLK_MQ_RQ_QUEUE_OK; } -- 1.7.9.5
Jens Axboe
2014-May-30 03:19 UTC
[PATCH] block: virtio_blk: don't hold spin lock during world switch
On 2014-05-29 20:49, Ming Lei wrote:> Firstly, it isn't necessary to hold lock of vblk->vq_lock > when notifying hypervisor about queued I/O. > > Secondly, virtqueue_notify() will cause world switch and > it may take long time on some hypervisors(such as, qemu-arm), > so it isn't good to hold the lock and block other vCPUs. > > On arm64 quad core VM(qemu-kvm), the patch can increase I/O > performance a lot with VIRTIO_RING_F_EVENT_IDX enabled: > - without the patch: 14K IOPS > - with the patch: 34K IOPSPatch looks good to me. I don't see a hit on my qemu-kvm testing, but it definitely makes sense and I can see it hurting in other places. -- Jens Axboe
Ming Lei
2014-May-30 03:34 UTC
[PATCH] block: virtio_blk: don't hold spin lock during world switch
On Fri, May 30, 2014 at 11:19 AM, Jens Axboe <axboe at kernel.dk> wrote:> On 2014-05-29 20:49, Ming Lei wrote: >> >> Firstly, it isn't necessary to hold lock of vblk->vq_lock >> when notifying hypervisor about queued I/O. >> >> Secondly, virtqueue_notify() will cause world switch and >> it may take long time on some hypervisors(such as, qemu-arm), >> so it isn't good to hold the lock and block other vCPUs. >> >> On arm64 quad core VM(qemu-kvm), the patch can increase I/O >> performance a lot with VIRTIO_RING_F_EVENT_IDX enabled: >> - without the patch: 14K IOPS >> - with the patch: 34K IOPS > > > Patch looks good to me. I don't see a hit on my qemu-kvm testing, but it > definitely makes sense and I can see it hurting in other places.It isn't easy to observe the improvement on x86 VM, especially with few vCPUs, because qemu-system-x86_64 only takes several microseconds to handle the notification, but on arm64, it may take hundreds of microseconds, so the improvement is obvious on arm VM. I hope this patch can be merged, at least arm VM can benefit from it. Thanks, -- Ming Lei
Rusty Russell
2014-May-30 06:05 UTC
[PATCH] block: virtio_blk: don't hold spin lock during world switch
Ming Lei <ming.lei at canonical.com> writes:> Firstly, it isn't necessary to hold lock of vblk->vq_lock > when notifying hypervisor about queued I/O. > > Secondly, virtqueue_notify() will cause world switch and > it may take long time on some hypervisors(such as, qemu-arm), > so it isn't good to hold the lock and block other vCPUs. > > On arm64 quad core VM(qemu-kvm), the patch can increase I/O > performance a lot with VIRTIO_RING_F_EVENT_IDX enabled: > - without the patch: 14K IOPS > - with the patch: 34K IOPS > > fio script: > [global] > direct=1 > bsrange=4k-4k > timeout=10 > numjobs=4 > ioengine=libaio > iodepth=64 > > filename=/dev/vdc > group_reporting=1 > > [f1] > rw=randread > > Cc: Rusty Russell <rusty at rustcorp.com.au> > Cc: "Michael S. Tsirkin" <mst at redhat.com> > Cc: virtualization at lists.linux-foundation.org > Signed-off-by: Ming Lei <ming.lei at canonical.com>Acked-by: Rusty Russell <rusty at rustcorp.com.au> Thanks! Rusty.
Michael S. Tsirkin
2014-May-30 15:27 UTC
[PATCH] block: virtio_blk: don't hold spin lock during world switch
On Fri, May 30, 2014 at 10:49:29AM +0800, Ming Lei wrote:> Firstly, it isn't necessary to hold lock of vblk->vq_lock > when notifying hypervisor about queued I/O. > > Secondly, virtqueue_notify() will cause world switch and > it may take long time on some hypervisors(such as, qemu-arm), > so it isn't good to hold the lock and block other vCPUs. > > On arm64 quad core VM(qemu-kvm), the patch can increase I/O > performance a lot with VIRTIO_RING_F_EVENT_IDX enabled: > - without the patch: 14K IOPS > - with the patch: 34K IOPS > > fio script: > [global] > direct=1 > bsrange=4k-4k > timeout=10 > numjobs=4 > ioengine=libaio > iodepth=64 > > filename=/dev/vdc > group_reporting=1 > > [f1] > rw=randread > > Cc: Rusty Russell <rusty at rustcorp.com.au> > Cc: "Michael S. Tsirkin" <mst at redhat.com> > Cc: virtualization at lists.linux-foundation.org > Signed-off-by: Ming Lei <ming.lei at canonical.com>Acked-by: Michael S. Tsirkin <mst at redhat.com>> --- > drivers/block/virtio_blk.c | 9 ++++++--- > 1 file changed, 6 insertions(+), 3 deletions(-) > > diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c > index 9f340fa..a6f5424 100644 > --- a/drivers/block/virtio_blk.c > +++ b/drivers/block/virtio_blk.c > @@ -162,6 +162,7 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req) > unsigned int num; > const bool last = (req->cmd_flags & REQ_END) != 0; > int err; > + bool notify = false; > > BUG_ON(req->nr_phys_segments + 2 > vblk->sg_elems); > > @@ -214,10 +215,12 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req) > return BLK_MQ_RQ_QUEUE_ERROR; > } > > - if (last) > - virtqueue_kick(vblk->vq); > - > + if (last && virtqueue_kick_prepare(vblk->vq)) > + notify = true; > spin_unlock_irqrestore(&vblk->vq_lock, flags); > + > + if (notify) > + virtqueue_notify(vblk->vq); > return BLK_MQ_RQ_QUEUE_OK; > } > > -- > 1.7.9.5
Reasonably Related Threads
- [PATCH] block: virtio_blk: don't hold spin lock during world switch
- [PATCH] block: virtio_blk: don't hold spin lock during world switch
- [PATCH] block: virtio_blk: don't hold spin lock during world switch
- [PATCH] block: virtio_blk: don't hold spin lock during world switch
- [PATCH 3.13 077/198] block: virtio_blk: don't hold spin lock during world switch