From: Si-Wei Liu <si-wei.liu@oracle.com>
To: qiudayu@archeros.com, jasowang@redhat.com, mst@redhat.com
Cc: eperezma@redhat.com, lingshan.zhu@intel.com,
qemu-devel@nongnu.org, lulu@redhat.com
Subject: Re: [PATCH RESEND v3] vdpa: reset the backend device in the end of vhost_net_stop()
Date: Thu, 31 Mar 2022 18:12:14 -0700 [thread overview]
Message-ID: <0055bb0b-6c24-9a25-83f2-08ea2b3fe0e6@oracle.com> (raw)
In-Reply-To: <1648718713-7637-1-git-send-email-qiudayu@archeros.com>
On 3/31/2022 2:25 AM, qiudayu@archeros.com wrote:
> From: Michael Qiu <qiudayu@archeros.com>
>
> Currently, when VM poweroff, it will trigger vdpa
> device(such as mlx bluefield2 VF) reset many times(with 1 datapath
> queue pair and one control queue, triggered 3 times), this
> leads to below issue:
>
> vhost VQ 2 ring restore failed: -22: Invalid argument (22)
>
> This because in vhost_net_stop(), it will stop all vhost device bind to
> this virtio device, and in vhost_dev_stop(), qemu tries to stop the device
> , then stop the queue: vhost_virtqueue_stop().
>
> In vhost_dev_stop(), it resets the device, which clear some flags
> in low level driver, and in next loop(stop other vhost backends),
> qemu try to stop the queue corresponding to the vhost backend,
> the driver finds that the VQ is invalied, this is the root cause.
>
> To solve the issue, vdpa should set vring unready, and
> remove reset ops in device stop: vhost_dev_start(hdev, false).
>
> and implement a new function vhost_dev_reset, only reset backend
> device after all vhost(per-queue) stoped.
>
> Signed-off-by: Michael Qiu<qiudayu@archeros.com>
> Acked-by: Jason Wang <jasowang@redhat.com>
> ---
> v3 --> v2:
> Call vhost_dev_reset() at the end of vhost_net_stop().
>
> Since the vDPA device need re-add the status bit
> VIRTIO_CONFIG_S_ACKNOWLEDGE and VIRTIO_CONFIG_S_DRIVER,
> simply, add them inside vhost_vdpa_reset_device, and
> the only way calling vhost_vdpa_reset_device is in
> vhost_net_stop(), so it keeps the same behavior as before.
>
> v2 --> v1:
> Implement a new function vhost_dev_reset,
> reset the backend kernel device at last.
> ---
> hw/net/vhost_net.c | 24 +++++++++++++++++++++---
> hw/virtio/vhost-vdpa.c | 15 +++++++++------
> hw/virtio/vhost.c | 15 ++++++++++++++-
> include/hw/virtio/vhost.h | 1 +
> 4 files changed, 45 insertions(+), 10 deletions(-)
>
> diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> index 30379d2..422c9bf 100644
> --- a/hw/net/vhost_net.c
> +++ b/hw/net/vhost_net.c
> @@ -325,7 +325,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
> int total_notifiers = data_queue_pairs * 2 + cvq;
> VirtIONet *n = VIRTIO_NET(dev);
> int nvhosts = data_queue_pairs + cvq;
> - struct vhost_net *net;
> + struct vhost_net *net = NULL;
> int r, e, i, index_end = data_queue_pairs * 2;
> NetClientState *peer;
>
> @@ -391,8 +391,17 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
> err_start:
> while (--i >= 0) {
> peer = qemu_get_peer(ncs , i);
> - vhost_net_stop_one(get_vhost_net(peer), dev);
> +
> + net = get_vhost_net(peer);
> +
> + vhost_net_stop_one(net, dev);
> }
> +
> + /* We only reset backend vdpa device */
> + if (net && net->dev.vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA) {
I would reset the device anyway regardless the first vhost_dev. Some
ioctl calls may have well changed device state in vhost_dev_start() that
has no way to get back than reset.
> + vhost_dev_reset(&net->dev);
I would move this to the end as it's more sensible to reset the device
after guest notifier is disabled.
> + }
> +
> e = k->set_guest_notifiers(qbus->parent, total_notifiers, false);
> if (e < 0) {
> fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", e);
> @@ -410,6 +419,7 @@ void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs,
> VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
> VirtIONet *n = VIRTIO_NET(dev);
> NetClientState *peer;
> + struct vhost_net *net = NULL;
> int total_notifiers = data_queue_pairs * 2 + cvq;
> int nvhosts = data_queue_pairs + cvq;
> int i, r;
> @@ -420,7 +430,15 @@ void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs,
> } else {
> peer = qemu_get_peer(ncs, n->max_queue_pairs);
> }
> - vhost_net_stop_one(get_vhost_net(peer), dev);
> +
> + net = get_vhost_net(peer);
> +
> + vhost_net_stop_one(net, dev);
> + }
> +
> + /* We only reset backend vdpa device */
> + if (net && net->dev.vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA) {
Yikes, I think it needs some code refactoring here without having to
check VHOST_BACKEND_TYPE_VDPA explicitly. Historically the
.vhost_reset_device() op was misnamed: it was initially meant for
RESET_OWNER but never got used. Could you add a new .vhost_reset_owner()
op to VhostOps (via another patch) and rename properly, e.g. from
vhost_kernel_reset_device() to vhost_kernel_reset_owner()? For
vhost_user_reset_device(), you can safely factor out the
VHOST_USER_RESET_OWNER case to a new vhost_user_reset_owner() function,
and only reset the device in vhost_user_reset_device() depending on the
VHOST_USER_PROTOCOL_F_RESET_DEVICE protocol feature.
With this change, vhost_reset_device will be effectively a no-op on
vhost_kernel (NULL) and vhost_user (only applicable to vhost-user-scsi
backend which supports VHOST_USER_PROTOCOL_F_RESET_DEVICE).
> + vhost_dev_reset(&net->dev);
I would move this to the end as it's more sensible to reset the device
after guest notifier is disabled.
> }
>
> r = k->set_guest_notifiers(qbus->parent, total_notifiers, false);
> diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
> index c5ed7a3..3ef0199 100644
> --- a/hw/virtio/vhost-vdpa.c
> +++ b/hw/virtio/vhost-vdpa.c
> @@ -708,6 +708,11 @@ static int vhost_vdpa_reset_device(struct vhost_dev *dev)
>
> ret = vhost_vdpa_call(dev, VHOST_VDPA_SET_STATUS, &status);
> trace_vhost_vdpa_reset_device(dev, status);
> +
> + /* Add back this status, so that the device could work next time*/
> + vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE |
> + VIRTIO_CONFIG_S_DRIVER);
> +
Hmmm, this might not be the ideal place, but I'm fine to leave it as-is.
It would need some more future work in code refactoring for e.g. live
migration and error recovery.
Thanks,
-Siwei
> return ret;
> }
>
> @@ -719,14 +724,14 @@ static int vhost_vdpa_get_vq_index(struct vhost_dev *dev, int idx)
> return idx;
> }
>
> -static int vhost_vdpa_set_vring_ready(struct vhost_dev *dev)
> +static int vhost_vdpa_set_vring_ready(struct vhost_dev *dev, unsigned int ready)
> {
> int i;
> trace_vhost_vdpa_set_vring_ready(dev);
> for (i = 0; i < dev->nvqs; ++i) {
> struct vhost_vring_state state = {
> .index = dev->vq_index + i,
> - .num = 1,
> + .num = ready,
> };
> vhost_vdpa_call(dev, VHOST_VDPA_SET_VRING_ENABLE, &state);
> }
> @@ -1088,8 +1093,9 @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
> if (unlikely(!ok)) {
> return -1;
> }
> - vhost_vdpa_set_vring_ready(dev);
> + vhost_vdpa_set_vring_ready(dev, 1);
> } else {
> + vhost_vdpa_set_vring_ready(dev, 0);
> ok = vhost_vdpa_svqs_stop(dev);
> if (unlikely(!ok)) {
> return -1;
> @@ -1105,9 +1111,6 @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
> memory_listener_register(&v->listener, &address_space_memory);
> return vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
> } else {
> - vhost_vdpa_reset_device(dev);
> - vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE |
> - VIRTIO_CONFIG_S_DRIVER);
> memory_listener_unregister(&v->listener);
>
> return 0;
> diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
> index b643f42..7e0cdb6 100644
> --- a/hw/virtio/vhost.c
> +++ b/hw/virtio/vhost.c
> @@ -1820,7 +1820,6 @@ fail_features:
> void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev)
> {
> int i;
> -
> /* should only be called after backend is connected */
> assert(hdev->vhost_ops);
>
> @@ -1854,3 +1853,17 @@ int vhost_net_set_backend(struct vhost_dev *hdev,
>
> return -ENOSYS;
> }
> +
> +int vhost_dev_reset(struct vhost_dev *hdev)
> +{
> + int ret = 0;
> +
> + /* should only be called after backend is connected */
> + assert(hdev->vhost_ops);
> +
> + if (hdev->vhost_ops->vhost_reset_device) {
> + ret = hdev->vhost_ops->vhost_reset_device(hdev);
> + }
> +
> + return ret;
> +}
> diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
> index 58a73e7..b8b7c20 100644
> --- a/include/hw/virtio/vhost.h
> +++ b/include/hw/virtio/vhost.h
> @@ -114,6 +114,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
> void vhost_dev_cleanup(struct vhost_dev *hdev);
> int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev);
> void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev);
> +int vhost_dev_reset(struct vhost_dev *hdev);
> int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev);
> void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev);
>
next prev parent reply other threads:[~2022-04-01 1:14 UTC|newest]
Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-23 8:42 [PATCH] vdpa: Avoid reset when stop device 08005325
2022-03-23 9:20 ` Jason Wang
2022-03-25 6:32 ` Si-Wei Liu
[not found] ` <fe13304f-0a18-639e-580d-ce6eb7daecab@archeros.com>
2022-03-25 19:19 ` Si-Wei Liu
[not found] ` <6fbf82a9-39ce-f179-5e4b-384123ca542c@archeros.com>
2022-03-25 19:59 ` Si-Wei Liu
2022-03-30 8:52 ` Jason Wang
2022-03-30 9:53 ` Michael Qiu
2022-03-30 10:02 ` [PATCH v2] vdpa: reset the backend device in stage of stop last vhost device 08005325
2022-03-30 10:52 ` Michael S. Tsirkin
2022-03-31 1:39 ` Michael Qiu
2022-03-31 0:15 ` Si-Wei Liu
2022-03-31 4:01 ` Michael Qiu
2022-03-31 4:02 ` Michael Qiu
2022-03-31 5:19 ` [PATCH v3] vdpa: reset the backend device in the end of vhost_net_stop() 08005325
2022-03-31 8:55 ` Jason Wang
2022-03-31 9:12 ` Maxime Coquelin
2022-03-31 9:22 ` Michael Qiu
2022-04-01 2:55 ` Jason Wang
2022-03-31 9:25 ` [PATCH RESEND " qiudayu
2022-03-31 10:19 ` Michael Qiu
[not found] ` <6245804d.1c69fb81.3c35c.d7efSMTPIN_ADDED_BROKEN@mx.google.com>
2022-03-31 20:32 ` Michael S. Tsirkin
2022-04-01 1:12 ` Si-Wei Liu [this message]
2022-04-01 1:45 ` Michael Qiu
2022-04-01 1:31 ` [PATCH v4] " Michael Qiu
2022-04-01 2:53 ` Jason Wang
2022-04-01 3:20 ` Michael Qiu
2022-04-01 23:07 ` Si-Wei Liu
2022-04-02 2:20 ` Jason Wang
2022-04-02 3:53 ` Michael Qiu
2022-04-06 0:56 ` Si-Wei Liu
2022-04-07 7:50 ` Jason Wang
[not found] ` <6247c8f5.1c69fb81.848e0.8b49SMTPIN_ADDED_BROKEN@mx.google.com>
2022-04-07 7:52 ` Jason Wang
[not found] ` <62466fff.1c69fb81.8817a.d813SMTPIN_ADDED_BROKEN@mx.google.com>
2022-04-02 1:48 ` Jason Wang
2022-04-02 3:43 ` Michael Qiu
2022-04-01 11:06 ` [PATCH 0/3] Refactor vhost device reset Michael Qiu
2022-04-01 11:06 ` [PATCH 1/3] vhost: Refactor vhost_reset_device() in VhostOps Michael Qiu
2022-04-02 0:44 ` Si-Wei Liu
2022-04-02 2:08 ` Michael Qiu
2022-04-02 2:38 ` Jason Wang
2022-04-02 5:14 ` Michael Qiu
[not found] ` <6247dc22.1c69fb81.4244.a88bSMTPIN_ADDED_BROKEN@mx.google.com>
2022-04-07 7:35 ` Jason Wang
2022-04-08 8:38 ` Michael Qiu
2022-04-08 17:17 ` Si-Wei Liu
2022-04-11 8:51 ` Jason Wang
2022-04-01 11:06 ` [PATCH 2/3] vhost: add vhost_dev_reset() Michael Qiu
2022-04-02 0:48 ` Si-Wei Liu
2022-04-01 11:06 ` [PATCH 3/3 v5] vdpa: reset the backend device in the end of vhost_net_stop() Michael Qiu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=0055bb0b-6c24-9a25-83f2-08ea2b3fe0e6@oracle.com \
--to=si-wei.liu@oracle.com \
--cc=eperezma@redhat.com \
--cc=jasowang@redhat.com \
--cc=lingshan.zhu@intel.com \
--cc=lulu@redhat.com \
--cc=mst@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=qiudayu@archeros.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).