* [Qemu-devel] [PATCH v1 0/2] virtio-scsi: dataplane: one fix and one optimization
@ 2014-11-11 1:17 Ming Lei
2014-11-11 1:17 ` [Qemu-devel] [PATCH v1 1/2] virtio-scsi: dataplane: fix allocation for 'cmd_vrings' Ming Lei
2014-11-11 1:17 ` [Qemu-devel] [PATCH v1 2/2] virtio-scsi: dataplane: notify guest as batch Ming Lei
0 siblings, 2 replies; 11+ messages in thread
From: Ming Lei @ 2014-11-11 1:17 UTC (permalink / raw)
To: qemu-devel, Paolo Bonzini, Stefan Hajnoczi, Kevin Wolf
Cc: Fam Zheng, Anthony Liguori, Michael S. Tsirkin
Hi,
The 1st patch fixes an allocation problem.
The 2nd one supresses writing eventfd a lot(~30K/sec in my test).
V1:
- use g_new() in 1/2
- avoid to dereference VIRTIO_SCSI() directly 2/2
- add build check on queue depth
Thanks,
Ming Lei
^ permalink raw reply [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH v1 1/2] virtio-scsi: dataplane: fix allocation for 'cmd_vrings'
2014-11-11 1:17 [Qemu-devel] [PATCH v1 0/2] virtio-scsi: dataplane: one fix and one optimization Ming Lei
@ 2014-11-11 1:17 ` Ming Lei
2014-11-11 1:28 ` Fam Zheng
2014-11-11 11:03 ` Paolo Bonzini
2014-11-11 1:17 ` [Qemu-devel] [PATCH v1 2/2] virtio-scsi: dataplane: notify guest as batch Ming Lei
1 sibling, 2 replies; 11+ messages in thread
From: Ming Lei @ 2014-11-11 1:17 UTC (permalink / raw)
To: qemu-devel, Paolo Bonzini, Stefan Hajnoczi, Kevin Wolf
Cc: Ming Lei, Fam Zheng, Anthony Liguori, Michael S. Tsirkin
The size of each element should be sizeof(VirtIOSCSIVring *).
Signed-off-by: Ming Lei <ming.lei@canonical.com>
---
hw/scsi/virtio-scsi-dataplane.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c
index 855439e..df17229 100644
--- a/hw/scsi/virtio-scsi-dataplane.c
+++ b/hw/scsi/virtio-scsi-dataplane.c
@@ -239,7 +239,7 @@ void virtio_scsi_dataplane_start(VirtIOSCSI *s)
if (!s->event_vring) {
goto fail_vrings;
}
- s->cmd_vrings = g_malloc0(sizeof(VirtIOSCSIVring) * vs->conf.num_queues);
+ s->cmd_vrings = g_new(VirtIOSCSIVring *, vs->conf.num_queues);
for (i = 0; i < vs->conf.num_queues; i++) {
s->cmd_vrings[i] =
virtio_scsi_vring_init(s, vs->cmd_vqs[i],
--
1.7.9.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH v1 2/2] virtio-scsi: dataplane: notify guest as batch
2014-11-11 1:17 [Qemu-devel] [PATCH v1 0/2] virtio-scsi: dataplane: one fix and one optimization Ming Lei
2014-11-11 1:17 ` [Qemu-devel] [PATCH v1 1/2] virtio-scsi: dataplane: fix allocation for 'cmd_vrings' Ming Lei
@ 2014-11-11 1:17 ` Ming Lei
2014-11-11 1:52 ` Fam Zheng
2014-11-11 17:28 ` Stefan Hajnoczi
1 sibling, 2 replies; 11+ messages in thread
From: Ming Lei @ 2014-11-11 1:17 UTC (permalink / raw)
To: qemu-devel, Paolo Bonzini, Stefan Hajnoczi, Kevin Wolf
Cc: Ming Lei, Fam Zheng, Anthony Liguori, Michael S. Tsirkin
It isn't necessery to notify guest each time when one request
is completed, and it should be enough to just notify one time
for each running of virtio_scsi_iothread_handle_cmd().
This patch supresses about 30K/sec write on eventfd.
Signed-off-by: Ming Lei <ming.lei@canonical.com>
---
hw/scsi/virtio-scsi-dataplane.c | 4 +++-
hw/scsi/virtio-scsi.c | 26 +++++++++++++++++++++++++-
include/hw/virtio/virtio-scsi.h | 4 ++++
3 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c
index df17229..294515a 100644
--- a/hw/scsi/virtio-scsi-dataplane.c
+++ b/hw/scsi/virtio-scsi-dataplane.c
@@ -62,6 +62,7 @@ static VirtIOSCSIVring *virtio_scsi_vring_init(VirtIOSCSI *s,
aio_set_event_notifier(s->ctx, &r->host_notifier, handler);
r->parent = s;
+ r->qid = n;
if (!vring_setup(&r->vring, VIRTIO_DEVICE(s), n)) {
fprintf(stderr, "virtio-scsi: VRing setup failed\n");
@@ -95,7 +96,8 @@ void virtio_scsi_vring_push_notify(VirtIOSCSIReq *req)
{
vring_push(&req->vring->vring, &req->elem,
req->qsgl.size + req->resp_iov.size);
- event_notifier_set(&req->vring->guest_notifier);
+ req->dev->pending_guest_notify |= 1 << (req->vring->qid - 2);
+ qemu_bh_schedule(req->dev->guest_notify_bh);
}
static void virtio_scsi_iothread_handle_ctrl(EventNotifier *notifier)
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 6e34a2c..98411ef 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -86,6 +86,21 @@ static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
virtio_scsi_free_req(req);
}
+static void notify_guest_bh(void *opaque)
+{
+ VirtIOSCSI *s = opaque;
+ unsigned int qid;
+ uint64_t pending = s->pending_guest_notify;
+
+ s->pending_guest_notify = 0;
+
+ while ((qid = ffsl(pending))) {
+ qid--;
+ event_notifier_set(&s->cmd_vrings[qid]->guest_notifier);
+ pending &= ~(1 << qid);
+ }
+}
+
static void virtio_scsi_bad_req(void)
{
error_report("wrong size for virtio-scsi headers");
@@ -824,7 +839,12 @@ void virtio_scsi_common_realize(DeviceState *dev, Error **errp,
}
if (s->conf.iothread) {
- virtio_scsi_set_iothread(VIRTIO_SCSI(s), s->conf.iothread);
+ VirtIOSCSI *vis = VIRTIO_SCSI(s);
+
+ QEMU_BUILD_BUG_ON(VIRTIO_PCI_QUEUE_MAX > 64);
+ virtio_scsi_set_iothread(vis, s->conf.iothread);
+ vis->pending_guest_notify = 0;
+ vis->guest_notify_bh = aio_bh_new(vis->ctx, notify_guest_bh, vis);
}
}
@@ -901,7 +921,11 @@ void virtio_scsi_common_unrealize(DeviceState *dev, Error **errp)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);
+ VirtIOSCSI *s = VIRTIO_SCSI(vs);
+ if (vs->conf.iothread) {
+ qemu_bh_delete(s->guest_notify_bh);
+ }
g_free(vs->cmd_vqs);
virtio_cleanup(vdev);
}
diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
index 9e1a49c..5e6c57e 100644
--- a/include/hw/virtio/virtio-scsi.h
+++ b/include/hw/virtio/virtio-scsi.h
@@ -163,6 +163,7 @@ typedef struct {
Vring vring;
EventNotifier host_notifier;
EventNotifier guest_notifier;
+ uint32_t qid;
} VirtIOSCSIVring;
typedef struct VirtIOSCSICommon {
@@ -198,6 +199,9 @@ typedef struct VirtIOSCSI {
bool dataplane_fenced;
Error *blocker;
Notifier migration_state_notifier;
+
+ QEMUBH *guest_notify_bh;
+ uint64_t pending_guest_notify;
} VirtIOSCSI;
typedef struct VirtIOSCSIReq {
--
1.7.9.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] [PATCH v1 1/2] virtio-scsi: dataplane: fix allocation for 'cmd_vrings'
2014-11-11 1:17 ` [Qemu-devel] [PATCH v1 1/2] virtio-scsi: dataplane: fix allocation for 'cmd_vrings' Ming Lei
@ 2014-11-11 1:28 ` Fam Zheng
2014-11-11 11:03 ` Paolo Bonzini
1 sibling, 0 replies; 11+ messages in thread
From: Fam Zheng @ 2014-11-11 1:28 UTC (permalink / raw)
To: Ming Lei
Cc: Kevin Wolf, Anthony Liguori, Michael S. Tsirkin, qemu-devel,
Stefan Hajnoczi, Paolo Bonzini
On Tue, 11/11 09:17, Ming Lei wrote:
> The size of each element should be sizeof(VirtIOSCSIVring *).
>
> Signed-off-by: Ming Lei <ming.lei@canonical.com>
> ---
> hw/scsi/virtio-scsi-dataplane.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c
> index 855439e..df17229 100644
> --- a/hw/scsi/virtio-scsi-dataplane.c
> +++ b/hw/scsi/virtio-scsi-dataplane.c
> @@ -239,7 +239,7 @@ void virtio_scsi_dataplane_start(VirtIOSCSI *s)
> if (!s->event_vring) {
> goto fail_vrings;
> }
> - s->cmd_vrings = g_malloc0(sizeof(VirtIOSCSIVring) * vs->conf.num_queues);
> + s->cmd_vrings = g_new(VirtIOSCSIVring *, vs->conf.num_queues);
> for (i = 0; i < vs->conf.num_queues; i++) {
> s->cmd_vrings[i] =
> virtio_scsi_vring_init(s, vs->cmd_vqs[i],
> --
> 1.7.9.5
>
Reviewed-by: Fam Zheng <famz@redhat.com>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] [PATCH v1 2/2] virtio-scsi: dataplane: notify guest as batch
2014-11-11 1:17 ` [Qemu-devel] [PATCH v1 2/2] virtio-scsi: dataplane: notify guest as batch Ming Lei
@ 2014-11-11 1:52 ` Fam Zheng
2014-11-11 2:29 ` Ming Lei
2014-11-11 17:28 ` Stefan Hajnoczi
1 sibling, 1 reply; 11+ messages in thread
From: Fam Zheng @ 2014-11-11 1:52 UTC (permalink / raw)
To: Ming Lei
Cc: Kevin Wolf, Anthony Liguori, Michael S. Tsirkin, qemu-devel,
Stefan Hajnoczi, Paolo Bonzini
On Tue, 11/11 09:17, Ming Lei wrote:
> It isn't necessery to notify guest each time when one request
> is completed, and it should be enough to just notify one time
> for each running of virtio_scsi_iothread_handle_cmd().
>
> This patch supresses about 30K/sec write on eventfd.
>
> Signed-off-by: Ming Lei <ming.lei@canonical.com>
> ---
> hw/scsi/virtio-scsi-dataplane.c | 4 +++-
> hw/scsi/virtio-scsi.c | 26 +++++++++++++++++++++++++-
> include/hw/virtio/virtio-scsi.h | 4 ++++
> 3 files changed, 32 insertions(+), 2 deletions(-)
>
> diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c
> index df17229..294515a 100644
> --- a/hw/scsi/virtio-scsi-dataplane.c
> +++ b/hw/scsi/virtio-scsi-dataplane.c
> @@ -62,6 +62,7 @@ static VirtIOSCSIVring *virtio_scsi_vring_init(VirtIOSCSI *s,
> aio_set_event_notifier(s->ctx, &r->host_notifier, handler);
>
> r->parent = s;
> + r->qid = n;
>
> if (!vring_setup(&r->vring, VIRTIO_DEVICE(s), n)) {
> fprintf(stderr, "virtio-scsi: VRing setup failed\n");
> @@ -95,7 +96,8 @@ void virtio_scsi_vring_push_notify(VirtIOSCSIReq *req)
> {
> vring_push(&req->vring->vring, &req->elem,
> req->qsgl.size + req->resp_iov.size);
> - event_notifier_set(&req->vring->guest_notifier);
> + req->dev->pending_guest_notify |= 1 << (req->vring->qid - 2);
> + qemu_bh_schedule(req->dev->guest_notify_bh);
> }
>
> static void virtio_scsi_iothread_handle_ctrl(EventNotifier *notifier)
> diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
> index 6e34a2c..98411ef 100644
> --- a/hw/scsi/virtio-scsi.c
> +++ b/hw/scsi/virtio-scsi.c
> @@ -86,6 +86,21 @@ static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
> virtio_scsi_free_req(req);
> }
>
> +static void notify_guest_bh(void *opaque)
> +{
> + VirtIOSCSI *s = opaque;
> + unsigned int qid;
> + uint64_t pending = s->pending_guest_notify;
> +
> + s->pending_guest_notify = 0;
> +
> + while ((qid = ffsl(pending))) {
> + qid--;
> + event_notifier_set(&s->cmd_vrings[qid]->guest_notifier);
Don't we need to handle ctrlq and eventq as well?
> + pending &= ~(1 << qid);
> + }
> +}
> +
> static void virtio_scsi_bad_req(void)
> {
> error_report("wrong size for virtio-scsi headers");
> @@ -824,7 +839,12 @@ void virtio_scsi_common_realize(DeviceState *dev, Error **errp,
> }
>
> if (s->conf.iothread) {
> - virtio_scsi_set_iothread(VIRTIO_SCSI(s), s->conf.iothread);
> + VirtIOSCSI *vis = VIRTIO_SCSI(s);
> +
> + QEMU_BUILD_BUG_ON(VIRTIO_PCI_QUEUE_MAX > 64);
> + virtio_scsi_set_iothread(vis, s->conf.iothread);
> + vis->pending_guest_notify = 0;
> + vis->guest_notify_bh = aio_bh_new(vis->ctx, notify_guest_bh, vis);
> }
> }
>
> @@ -901,7 +921,11 @@ void virtio_scsi_common_unrealize(DeviceState *dev, Error **errp)
> {
> VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);
> + VirtIOSCSI *s = VIRTIO_SCSI(vs);
>
> + if (vs->conf.iothread) {
> + qemu_bh_delete(s->guest_notify_bh);
> + }
> g_free(vs->cmd_vqs);
> virtio_cleanup(vdev);
> }
> diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
> index 9e1a49c..5e6c57e 100644
> --- a/include/hw/virtio/virtio-scsi.h
> +++ b/include/hw/virtio/virtio-scsi.h
> @@ -163,6 +163,7 @@ typedef struct {
> Vring vring;
> EventNotifier host_notifier;
> EventNotifier guest_notifier;
> + uint32_t qid;
Could this "bool notify_pending"? In this case pending_guest_notify in
VirtIOSCSI is not necessary. I guess looking into no more than 64
VirtIOSCSIVring elements in guest_notify_bh is not _that_ expensive so it's not
worth the complexity.
> } VirtIOSCSIVring;
>
> typedef struct VirtIOSCSICommon {
> @@ -198,6 +199,9 @@ typedef struct VirtIOSCSI {
> bool dataplane_fenced;
> Error *blocker;
> Notifier migration_state_notifier;
> +
> + QEMUBH *guest_notify_bh;
> + uint64_t pending_guest_notify;
Fam
> } VirtIOSCSI;
>
> typedef struct VirtIOSCSIReq {
> --
> 1.7.9.5
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] [PATCH v1 2/2] virtio-scsi: dataplane: notify guest as batch
2014-11-11 1:52 ` Fam Zheng
@ 2014-11-11 2:29 ` Ming Lei
2014-11-11 2:52 ` Fam Zheng
0 siblings, 1 reply; 11+ messages in thread
From: Ming Lei @ 2014-11-11 2:29 UTC (permalink / raw)
To: Fam Zheng
Cc: Kevin Wolf, Anthony Liguori, Michael S. Tsirkin, qemu-devel,
Stefan Hajnoczi, Paolo Bonzini
On Tue, Nov 11, 2014 at 9:52 AM, Fam Zheng <famz@redhat.com> wrote:
> On Tue, 11/11 09:17, Ming Lei wrote:
>> It isn't necessery to notify guest each time when one request
>> is completed, and it should be enough to just notify one time
>> for each running of virtio_scsi_iothread_handle_cmd().
>>
>> This patch supresses about 30K/sec write on eventfd.
>>
>> Signed-off-by: Ming Lei <ming.lei@canonical.com>
>> ---
>> hw/scsi/virtio-scsi-dataplane.c | 4 +++-
>> hw/scsi/virtio-scsi.c | 26 +++++++++++++++++++++++++-
>> include/hw/virtio/virtio-scsi.h | 4 ++++
>> 3 files changed, 32 insertions(+), 2 deletions(-)
>>
>> diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c
>> index df17229..294515a 100644
>> --- a/hw/scsi/virtio-scsi-dataplane.c
>> +++ b/hw/scsi/virtio-scsi-dataplane.c
>> @@ -62,6 +62,7 @@ static VirtIOSCSIVring *virtio_scsi_vring_init(VirtIOSCSI *s,
>> aio_set_event_notifier(s->ctx, &r->host_notifier, handler);
>>
>> r->parent = s;
>> + r->qid = n;
>>
>> if (!vring_setup(&r->vring, VIRTIO_DEVICE(s), n)) {
>> fprintf(stderr, "virtio-scsi: VRing setup failed\n");
>> @@ -95,7 +96,8 @@ void virtio_scsi_vring_push_notify(VirtIOSCSIReq *req)
>> {
>> vring_push(&req->vring->vring, &req->elem,
>> req->qsgl.size + req->resp_iov.size);
>> - event_notifier_set(&req->vring->guest_notifier);
>> + req->dev->pending_guest_notify |= 1 << (req->vring->qid - 2);
>> + qemu_bh_schedule(req->dev->guest_notify_bh);
>> }
>>
>> static void virtio_scsi_iothread_handle_ctrl(EventNotifier *notifier)
>> diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
>> index 6e34a2c..98411ef 100644
>> --- a/hw/scsi/virtio-scsi.c
>> +++ b/hw/scsi/virtio-scsi.c
>> @@ -86,6 +86,21 @@ static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
>> virtio_scsi_free_req(req);
>> }
>>
>> +static void notify_guest_bh(void *opaque)
>> +{
>> + VirtIOSCSI *s = opaque;
>> + unsigned int qid;
>> + uint64_t pending = s->pending_guest_notify;
>> +
>> + s->pending_guest_notify = 0;
>> +
>> + while ((qid = ffsl(pending))) {
>> + qid--;
>> + event_notifier_set(&s->cmd_vrings[qid]->guest_notifier);
>
> Don't we need to handle ctrlq and eventq as well?
Most of times no frequent activity in ctrl and event vq, so it isn't
necessary to make them involved.
>
>> + pending &= ~(1 << qid);
>> + }
>> +}
>> +
>> static void virtio_scsi_bad_req(void)
>> {
>> error_report("wrong size for virtio-scsi headers");
>> @@ -824,7 +839,12 @@ void virtio_scsi_common_realize(DeviceState *dev, Error **errp,
>> }
>>
>> if (s->conf.iothread) {
>> - virtio_scsi_set_iothread(VIRTIO_SCSI(s), s->conf.iothread);
>> + VirtIOSCSI *vis = VIRTIO_SCSI(s);
>> +
>> + QEMU_BUILD_BUG_ON(VIRTIO_PCI_QUEUE_MAX > 64);
>> + virtio_scsi_set_iothread(vis, s->conf.iothread);
>> + vis->pending_guest_notify = 0;
>> + vis->guest_notify_bh = aio_bh_new(vis->ctx, notify_guest_bh, vis);
>> }
>> }
>>
>> @@ -901,7 +921,11 @@ void virtio_scsi_common_unrealize(DeviceState *dev, Error **errp)
>> {
>> VirtIODevice *vdev = VIRTIO_DEVICE(dev);
>> VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);
>> + VirtIOSCSI *s = VIRTIO_SCSI(vs);
>>
>> + if (vs->conf.iothread) {
>> + qemu_bh_delete(s->guest_notify_bh);
>> + }
>> g_free(vs->cmd_vqs);
>> virtio_cleanup(vdev);
>> }
>> diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
>> index 9e1a49c..5e6c57e 100644
>> --- a/include/hw/virtio/virtio-scsi.h
>> +++ b/include/hw/virtio/virtio-scsi.h
>> @@ -163,6 +163,7 @@ typedef struct {
>> Vring vring;
>> EventNotifier host_notifier;
>> EventNotifier guest_notifier;
>> + uint32_t qid;
>
> Could this "bool notify_pending"? In this case pending_guest_notify in
> VirtIOSCSI is not necessary. I guess looking into no more than 64
> VirtIOSCSIVring elements in guest_notify_bh is not _that_ expensive so it's not
> worth the complexity.
We need to know which queue the pending notifier is sent to in BH
handler, and 64 is the limit for queue number, not element number.
Actually it is a bit expensive, and 30K/sec write syscall is wasted in
the unnecessary & repeated notifying.
And the similar approach is applied in virtio-blk dataplane too, :-)
Thanks,
Ming Lei
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] [PATCH v1 2/2] virtio-scsi: dataplane: notify guest as batch
2014-11-11 2:29 ` Ming Lei
@ 2014-11-11 2:52 ` Fam Zheng
2014-11-11 3:08 ` Ming Lei
0 siblings, 1 reply; 11+ messages in thread
From: Fam Zheng @ 2014-11-11 2:52 UTC (permalink / raw)
To: Ming Lei
Cc: Kevin Wolf, Anthony Liguori, Michael S. Tsirkin, qemu-devel,
Stefan Hajnoczi, Paolo Bonzini
On Tue, 11/11 10:29, Ming Lei wrote:
> On Tue, Nov 11, 2014 at 9:52 AM, Fam Zheng <famz@redhat.com> wrote:
> > On Tue, 11/11 09:17, Ming Lei wrote:
> >> It isn't necessery to notify guest each time when one request
> >> is completed, and it should be enough to just notify one time
> >> for each running of virtio_scsi_iothread_handle_cmd().
> >>
> >> This patch supresses about 30K/sec write on eventfd.
> >>
> >> Signed-off-by: Ming Lei <ming.lei@canonical.com>
> >> ---
> >> hw/scsi/virtio-scsi-dataplane.c | 4 +++-
> >> hw/scsi/virtio-scsi.c | 26 +++++++++++++++++++++++++-
> >> include/hw/virtio/virtio-scsi.h | 4 ++++
> >> 3 files changed, 32 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c
> >> index df17229..294515a 100644
> >> --- a/hw/scsi/virtio-scsi-dataplane.c
> >> +++ b/hw/scsi/virtio-scsi-dataplane.c
> >> @@ -62,6 +62,7 @@ static VirtIOSCSIVring *virtio_scsi_vring_init(VirtIOSCSI *s,
> >> aio_set_event_notifier(s->ctx, &r->host_notifier, handler);
> >>
> >> r->parent = s;
> >> + r->qid = n;
> >>
> >> if (!vring_setup(&r->vring, VIRTIO_DEVICE(s), n)) {
> >> fprintf(stderr, "virtio-scsi: VRing setup failed\n");
> >> @@ -95,7 +96,8 @@ void virtio_scsi_vring_push_notify(VirtIOSCSIReq *req)
> >> {
> >> vring_push(&req->vring->vring, &req->elem,
> >> req->qsgl.size + req->resp_iov.size);
> >> - event_notifier_set(&req->vring->guest_notifier);
> >> + req->dev->pending_guest_notify |= 1 << (req->vring->qid - 2);
> >> + qemu_bh_schedule(req->dev->guest_notify_bh);
> >> }
> >>
> >> static void virtio_scsi_iothread_handle_ctrl(EventNotifier *notifier)
> >> diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
> >> index 6e34a2c..98411ef 100644
> >> --- a/hw/scsi/virtio-scsi.c
> >> +++ b/hw/scsi/virtio-scsi.c
> >> @@ -86,6 +86,21 @@ static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
> >> virtio_scsi_free_req(req);
> >> }
> >>
> >> +static void notify_guest_bh(void *opaque)
> >> +{
> >> + VirtIOSCSI *s = opaque;
> >> + unsigned int qid;
> >> + uint64_t pending = s->pending_guest_notify;
> >> +
> >> + s->pending_guest_notify = 0;
> >> +
> >> + while ((qid = ffsl(pending))) {
> >> + qid--;
> >> + event_notifier_set(&s->cmd_vrings[qid]->guest_notifier);
> >
> > Don't we need to handle ctrlq and eventq as well?
>
> Most of times no frequent activity in ctrl and event vq, so it isn't
> necessary to make them involved.
I mean virtio_scsi_vring_push_notify is not only used to notify cmd, it should
also work for ctrl and event, because its caller virtio_scsi_complete_req is
also called in virtio_scsi_handle_ctrl_req and virtio_scsi_push_event.
>
> >
> >> + pending &= ~(1 << qid);
> >> + }
> >> +}
> >> +
> >> static void virtio_scsi_bad_req(void)
> >> {
> >> error_report("wrong size for virtio-scsi headers");
> >> @@ -824,7 +839,12 @@ void virtio_scsi_common_realize(DeviceState *dev, Error **errp,
> >> }
> >>
> >> if (s->conf.iothread) {
> >> - virtio_scsi_set_iothread(VIRTIO_SCSI(s), s->conf.iothread);
> >> + VirtIOSCSI *vis = VIRTIO_SCSI(s);
> >> +
> >> + QEMU_BUILD_BUG_ON(VIRTIO_PCI_QUEUE_MAX > 64);
> >> + virtio_scsi_set_iothread(vis, s->conf.iothread);
> >> + vis->pending_guest_notify = 0;
> >> + vis->guest_notify_bh = aio_bh_new(vis->ctx, notify_guest_bh, vis);
> >> }
> >> }
> >>
> >> @@ -901,7 +921,11 @@ void virtio_scsi_common_unrealize(DeviceState *dev, Error **errp)
> >> {
> >> VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> >> VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);
> >> + VirtIOSCSI *s = VIRTIO_SCSI(vs);
> >>
> >> + if (vs->conf.iothread) {
> >> + qemu_bh_delete(s->guest_notify_bh);
> >> + }
> >> g_free(vs->cmd_vqs);
> >> virtio_cleanup(vdev);
> >> }
> >> diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
> >> index 9e1a49c..5e6c57e 100644
> >> --- a/include/hw/virtio/virtio-scsi.h
> >> +++ b/include/hw/virtio/virtio-scsi.h
> >> @@ -163,6 +163,7 @@ typedef struct {
> >> Vring vring;
> >> EventNotifier host_notifier;
> >> EventNotifier guest_notifier;
> >> + uint32_t qid;
> >
> > Could this "bool notify_pending"? In this case pending_guest_notify in
> > VirtIOSCSI is not necessary. I guess looking into no more than 64
> > VirtIOSCSIVring elements in guest_notify_bh is not _that_ expensive so it's not
> > worth the complexity.
>
> We need to know which queue the pending notifier is sent to in BH
> handler, and 64 is the limit for queue number, not element number.
>
> Actually it is a bit expensive, and 30K/sec write syscall is wasted in
> the unnecessary & repeated notifying.
>
> And the similar approach is applied in virtio-blk dataplane too, :-)
>
I mean something like:
diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
index 9e1a49c..5e6c57e 100644
--- a/include/hw/virtio/virtio-scsi.h
+++ b/include/hw/virtio/virtio-scsi.h
@@ -163,6 +163,7 @@ typedef struct {
Vring vring;
EventNotifier host_notifier;
EventNotifier guest_notifier;
+ bool notify_pending;
@@ -95,7 +96,8 @@ void virtio_scsi_vring_push_notify(VirtIOSCSIReq *req)
{
vring_push(&req->vring->vring, &req->elem,
req->qsgl.size + req->resp_iov.size);
- event_notifier_set(&req->vring->guest_notifier);
+ req->vring->pending_notify = true;
+ qemu_bh_schedule(req->dev->guest_notify_bh);
}
And in notify_guest_bh you go through all the vrings and call
event_notifier_set on those with vring->pending_notify == true.
Fam
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] [PATCH v1 2/2] virtio-scsi: dataplane: notify guest as batch
2014-11-11 2:52 ` Fam Zheng
@ 2014-11-11 3:08 ` Ming Lei
0 siblings, 0 replies; 11+ messages in thread
From: Ming Lei @ 2014-11-11 3:08 UTC (permalink / raw)
To: Fam Zheng
Cc: Kevin Wolf, Anthony Liguori, Michael S. Tsirkin, qemu-devel,
Stefan Hajnoczi, Paolo Bonzini
On Tue, Nov 11, 2014 at 10:52 AM, Fam Zheng <famz@redhat.com> wrote:
> On Tue, 11/11 10:29, Ming Lei wrote:
>> On Tue, Nov 11, 2014 at 9:52 AM, Fam Zheng <famz@redhat.com> wrote:
>> > On Tue, 11/11 09:17, Ming Lei wrote:
>> >> It isn't necessery to notify guest each time when one request
>> >> is completed, and it should be enough to just notify one time
>> >> for each running of virtio_scsi_iothread_handle_cmd().
>> >>
>> >> This patch supresses about 30K/sec write on eventfd.
>> >>
>> >> Signed-off-by: Ming Lei <ming.lei@canonical.com>
>> >> ---
>> >> hw/scsi/virtio-scsi-dataplane.c | 4 +++-
>> >> hw/scsi/virtio-scsi.c | 26 +++++++++++++++++++++++++-
>> >> include/hw/virtio/virtio-scsi.h | 4 ++++
>> >> 3 files changed, 32 insertions(+), 2 deletions(-)
>> >>
>> >> diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c
>> >> index df17229..294515a 100644
>> >> --- a/hw/scsi/virtio-scsi-dataplane.c
>> >> +++ b/hw/scsi/virtio-scsi-dataplane.c
>> >> @@ -62,6 +62,7 @@ static VirtIOSCSIVring *virtio_scsi_vring_init(VirtIOSCSI *s,
>> >> aio_set_event_notifier(s->ctx, &r->host_notifier, handler);
>> >>
>> >> r->parent = s;
>> >> + r->qid = n;
>> >>
>> >> if (!vring_setup(&r->vring, VIRTIO_DEVICE(s), n)) {
>> >> fprintf(stderr, "virtio-scsi: VRing setup failed\n");
>> >> @@ -95,7 +96,8 @@ void virtio_scsi_vring_push_notify(VirtIOSCSIReq *req)
>> >> {
>> >> vring_push(&req->vring->vring, &req->elem,
>> >> req->qsgl.size + req->resp_iov.size);
>> >> - event_notifier_set(&req->vring->guest_notifier);
>> >> + req->dev->pending_guest_notify |= 1 << (req->vring->qid - 2);
>> >> + qemu_bh_schedule(req->dev->guest_notify_bh);
>> >> }
>> >>
>> >> static void virtio_scsi_iothread_handle_ctrl(EventNotifier *notifier)
>> >> diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
>> >> index 6e34a2c..98411ef 100644
>> >> --- a/hw/scsi/virtio-scsi.c
>> >> +++ b/hw/scsi/virtio-scsi.c
>> >> @@ -86,6 +86,21 @@ static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
>> >> virtio_scsi_free_req(req);
>> >> }
>> >>
>> >> +static void notify_guest_bh(void *opaque)
>> >> +{
>> >> + VirtIOSCSI *s = opaque;
>> >> + unsigned int qid;
>> >> + uint64_t pending = s->pending_guest_notify;
>> >> +
>> >> + s->pending_guest_notify = 0;
>> >> +
>> >> + while ((qid = ffsl(pending))) {
>> >> + qid--;
>> >> + event_notifier_set(&s->cmd_vrings[qid]->guest_notifier);
>> >
>> > Don't we need to handle ctrlq and eventq as well?
>>
>> Most of times no frequent activity in ctrl and event vq, so it isn't
>> necessary to make them involved.
>
> I mean virtio_scsi_vring_push_notify is not only used to notify cmd, it should
> also work for ctrl and event, because its caller virtio_scsi_complete_req is
> also called in virtio_scsi_handle_ctrl_req and virtio_scsi_push_event.
>
>>
>> >
>> >> + pending &= ~(1 << qid);
>> >> + }
>> >> +}
>> >> +
>> >> static void virtio_scsi_bad_req(void)
>> >> {
>> >> error_report("wrong size for virtio-scsi headers");
>> >> @@ -824,7 +839,12 @@ void virtio_scsi_common_realize(DeviceState *dev, Error **errp,
>> >> }
>> >>
>> >> if (s->conf.iothread) {
>> >> - virtio_scsi_set_iothread(VIRTIO_SCSI(s), s->conf.iothread);
>> >> + VirtIOSCSI *vis = VIRTIO_SCSI(s);
>> >> +
>> >> + QEMU_BUILD_BUG_ON(VIRTIO_PCI_QUEUE_MAX > 64);
>> >> + virtio_scsi_set_iothread(vis, s->conf.iothread);
>> >> + vis->pending_guest_notify = 0;
>> >> + vis->guest_notify_bh = aio_bh_new(vis->ctx, notify_guest_bh, vis);
>> >> }
>> >> }
>> >>
>> >> @@ -901,7 +921,11 @@ void virtio_scsi_common_unrealize(DeviceState *dev, Error **errp)
>> >> {
>> >> VirtIODevice *vdev = VIRTIO_DEVICE(dev);
>> >> VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);
>> >> + VirtIOSCSI *s = VIRTIO_SCSI(vs);
>> >>
>> >> + if (vs->conf.iothread) {
>> >> + qemu_bh_delete(s->guest_notify_bh);
>> >> + }
>> >> g_free(vs->cmd_vqs);
>> >> virtio_cleanup(vdev);
>> >> }
>> >> diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
>> >> index 9e1a49c..5e6c57e 100644
>> >> --- a/include/hw/virtio/virtio-scsi.h
>> >> +++ b/include/hw/virtio/virtio-scsi.h
>> >> @@ -163,6 +163,7 @@ typedef struct {
>> >> Vring vring;
>> >> EventNotifier host_notifier;
>> >> EventNotifier guest_notifier;
>> >> + uint32_t qid;
>> >
>> > Could this "bool notify_pending"? In this case pending_guest_notify in
>> > VirtIOSCSI is not necessary. I guess looking into no more than 64
>> > VirtIOSCSIVring elements in guest_notify_bh is not _that_ expensive so it's not
>> > worth the complexity.
>>
>> We need to know which queue the pending notifier is sent to in BH
>> handler, and 64 is the limit for queue number, not element number.
>>
>> Actually it is a bit expensive, and 30K/sec write syscall is wasted in
>> the unnecessary & repeated notifying.
>>
>> And the similar approach is applied in virtio-blk dataplane too, :-)
>>
>
> I mean something like:
>
> diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
> index 9e1a49c..5e6c57e 100644
> --- a/include/hw/virtio/virtio-scsi.h
> +++ b/include/hw/virtio/virtio-scsi.h
> @@ -163,6 +163,7 @@ typedef struct {
> Vring vring;
> EventNotifier host_notifier;
> EventNotifier guest_notifier;
> + bool notify_pending;
>
> @@ -95,7 +96,8 @@ void virtio_scsi_vring_push_notify(VirtIOSCSIReq *req)
> {
> vring_push(&req->vring->vring, &req->elem,
> req->qsgl.size + req->resp_iov.size);
> - event_notifier_set(&req->vring->guest_notifier);
> + req->vring->pending_notify = true;
> + qemu_bh_schedule(req->dev->guest_notify_bh);
> }
>
> And in notify_guest_bh you go through all the vrings and call
> event_notifier_set on those with vring->pending_notify == true.
You are right, and I missed ctrl and event vq, and it should be
simpler to introduce vring->pending_notify.
Will do that in v2, thanks.
Thanks,
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] [PATCH v1 1/2] virtio-scsi: dataplane: fix allocation for 'cmd_vrings'
2014-11-11 1:17 ` [Qemu-devel] [PATCH v1 1/2] virtio-scsi: dataplane: fix allocation for 'cmd_vrings' Ming Lei
2014-11-11 1:28 ` Fam Zheng
@ 2014-11-11 11:03 ` Paolo Bonzini
1 sibling, 0 replies; 11+ messages in thread
From: Paolo Bonzini @ 2014-11-11 11:03 UTC (permalink / raw)
To: Ming Lei, qemu-devel, Stefan Hajnoczi, Kevin Wolf
Cc: Fam Zheng, Anthony Liguori, Michael S. Tsirkin
On 11/11/2014 02:17, Ming Lei wrote:
> The size of each element should be sizeof(VirtIOSCSIVring *).
>
> Signed-off-by: Ming Lei <ming.lei@canonical.com>
> ---
> hw/scsi/virtio-scsi-dataplane.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c
> index 855439e..df17229 100644
> --- a/hw/scsi/virtio-scsi-dataplane.c
> +++ b/hw/scsi/virtio-scsi-dataplane.c
> @@ -239,7 +239,7 @@ void virtio_scsi_dataplane_start(VirtIOSCSI *s)
> if (!s->event_vring) {
> goto fail_vrings;
> }
> - s->cmd_vrings = g_malloc0(sizeof(VirtIOSCSIVring) * vs->conf.num_queues);
> + s->cmd_vrings = g_new(VirtIOSCSIVring *, vs->conf.num_queues);
> for (i = 0; i < vs->conf.num_queues; i++) {
> s->cmd_vrings[i] =
> virtio_scsi_vring_init(s, vs->cmd_vqs[i],
>
Applied, thanks.
Paolo
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] [PATCH v1 2/2] virtio-scsi: dataplane: notify guest as batch
2014-11-11 1:17 ` [Qemu-devel] [PATCH v1 2/2] virtio-scsi: dataplane: notify guest as batch Ming Lei
2014-11-11 1:52 ` Fam Zheng
@ 2014-11-11 17:28 ` Stefan Hajnoczi
2014-11-12 2:33 ` Ming Lei
1 sibling, 1 reply; 11+ messages in thread
From: Stefan Hajnoczi @ 2014-11-11 17:28 UTC (permalink / raw)
To: Ming Lei
Cc: Kevin Wolf, Fam Zheng, Michael S. Tsirkin, qemu-devel,
Anthony Liguori, Paolo Bonzini
[-- Attachment #1: Type: text/plain, Size: 1527 bytes --]
On Tue, Nov 11, 2014 at 09:17:10AM +0800, Ming Lei wrote:
> +static void notify_guest_bh(void *opaque)
> +{
> + VirtIOSCSI *s = opaque;
> + unsigned int qid;
> + uint64_t pending = s->pending_guest_notify;
> +
> + s->pending_guest_notify = 0;
> +
> + while ((qid = ffsl(pending))) {
> + qid--;
> + event_notifier_set(&s->cmd_vrings[qid]->guest_notifier);
> + pending &= ~(1 << qid);
> + }
> +}
Looks like we're not honoring virtio's usual interrupt mitigation
mechanism (e.g. EVENT_IDX) for virtio-scsi. Why is
vring_should_notify() not used?
> +
> static void virtio_scsi_bad_req(void)
> {
> error_report("wrong size for virtio-scsi headers");
> @@ -824,7 +839,12 @@ void virtio_scsi_common_realize(DeviceState *dev, Error **errp,
> }
>
> if (s->conf.iothread) {
> - virtio_scsi_set_iothread(VIRTIO_SCSI(s), s->conf.iothread);
> + VirtIOSCSI *vis = VIRTIO_SCSI(s);
> +
> + QEMU_BUILD_BUG_ON(VIRTIO_PCI_QUEUE_MAX > 64);
> + virtio_scsi_set_iothread(vis, s->conf.iothread);
> + vis->pending_guest_notify = 0;
> + vis->guest_notify_bh = aio_bh_new(vis->ctx, notify_guest_bh, vis);
Have you checked state transitions like PCI or virtio reset? They need
to cancel the BH and clear ->pending_guest_notify.
There is also a transition from dataplane to non-dataplane mode for live
migration.
Please make sure no interrupts are dropped or stale data is kept across
these transitions.
[-- Attachment #2: Type: application/pgp-signature, Size: 473 bytes --]
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] [PATCH v1 2/2] virtio-scsi: dataplane: notify guest as batch
2014-11-11 17:28 ` Stefan Hajnoczi
@ 2014-11-12 2:33 ` Ming Lei
0 siblings, 0 replies; 11+ messages in thread
From: Ming Lei @ 2014-11-12 2:33 UTC (permalink / raw)
To: Stefan Hajnoczi
Cc: Kevin Wolf, Fam Zheng, Michael S. Tsirkin, qemu-devel,
Anthony Liguori, Paolo Bonzini
On Wed, Nov 12, 2014 at 1:28 AM, Stefan Hajnoczi <stefanha@redhat.com> wrote:
> On Tue, Nov 11, 2014 at 09:17:10AM +0800, Ming Lei wrote:
>> +static void notify_guest_bh(void *opaque)
>> +{
>> + VirtIOSCSI *s = opaque;
>> + unsigned int qid;
>> + uint64_t pending = s->pending_guest_notify;
>> +
>> + s->pending_guest_notify = 0;
>> +
>> + while ((qid = ffsl(pending))) {
>> + qid--;
>> + event_notifier_set(&s->cmd_vrings[qid]->guest_notifier);
>> + pending &= ~(1 << qid);
>> + }
>> +}
>
> Looks like we're not honoring virtio's usual interrupt mitigation
> mechanism (e.g. EVENT_IDX) for virtio-scsi. Why is
> vring_should_notify() not used?
Yes, that should be used, but in virtio-blk, BH still can suppress
about ~13K/sec write(), and for virtio-scsi, it should be more since
there may be more queues.
>
>> +
>> static void virtio_scsi_bad_req(void)
>> {
>> error_report("wrong size for virtio-scsi headers");
>> @@ -824,7 +839,12 @@ void virtio_scsi_common_realize(DeviceState *dev, Error **errp,
>> }
>>
>> if (s->conf.iothread) {
>> - virtio_scsi_set_iothread(VIRTIO_SCSI(s), s->conf.iothread);
>> + VirtIOSCSI *vis = VIRTIO_SCSI(s);
>> +
>> + QEMU_BUILD_BUG_ON(VIRTIO_PCI_QUEUE_MAX > 64);
>> + virtio_scsi_set_iothread(vis, s->conf.iothread);
>> + vis->pending_guest_notify = 0;
>> + vis->guest_notify_bh = aio_bh_new(vis->ctx, notify_guest_bh, vis);
>
> Have you checked state transitions like PCI or virtio reset? They need
> to cancel the BH and clear ->pending_guest_notify.
>
> There is also a transition from dataplane to non-dataplane mode for live
> migration.
>
> Please make sure no interrupts are dropped or stale data is kept across
> these transitions.
Good catch, and I will make sure that in next version, and virtio-blk
dataplane need to consider that too.
Thanks,
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2014-11-12 2:33 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-11 1:17 [Qemu-devel] [PATCH v1 0/2] virtio-scsi: dataplane: one fix and one optimization Ming Lei
2014-11-11 1:17 ` [Qemu-devel] [PATCH v1 1/2] virtio-scsi: dataplane: fix allocation for 'cmd_vrings' Ming Lei
2014-11-11 1:28 ` Fam Zheng
2014-11-11 11:03 ` Paolo Bonzini
2014-11-11 1:17 ` [Qemu-devel] [PATCH v1 2/2] virtio-scsi: dataplane: notify guest as batch Ming Lei
2014-11-11 1:52 ` Fam Zheng
2014-11-11 2:29 ` Ming Lei
2014-11-11 2:52 ` Fam Zheng
2014-11-11 3:08 ` Ming Lei
2014-11-11 17:28 ` Stefan Hajnoczi
2014-11-12 2:33 ` Ming Lei
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).