qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] block/vhost-user-blk: Fix hang on boot for some odd guests


From: Raphael Norwitz
Subject: Re: [PATCH] block/vhost-user-blk: Fix hang on boot for some odd guests
Date: Tue, 18 Apr 2023 05:13:11 +0000

Hey Andrey - apologies for the late reply here.

It sounds like you are dealing with a buggy guest, rather than a QEMU issue.

> On Apr 10, 2023, at 11:39 AM, Andrey Ryabinin <arbn@yandex-team.com> wrote:
> 
> 
> 
> On 4/10/23 10:35, Andrey Ryabinin wrote:
>> Some guests hang on boot when using the vhost-user-blk-pci device,
>> but boot normally when using the virtio-blk device. The problem occurs
>> because the guest advertises VIRTIO_F_VERSION_1 but kicks the virtqueue
>> before setting VIRTIO_CONFIG_S_DRIVER_OK, causing vdev->start_on_kick to

Virtio 1.1 Section 3.1.1, says during setup “[t]he driver MUST NOT notify the 
device before setting DRIVER_OK.”

Therefore what you are describing is buggy guest behavior. Sounds like the 
driver should be made to either
- not advertise VIRTIO_F_VERSION_1
- not kick before setting VIRTIO_CONFIG_S_DRIVER_OK

If anything, the virtio-blk virtio_blk_handle_output() function should probably 
check start_on_kick?

>> be false in vhost_user_blk_handle_output() and preventing the device from
>> starting.
>> 
>> Fix this by removing the check for vdev->start_on_kick to ensure
>> that the device starts after the kick. This aligns the behavior of
>> 'vhost-user-blk-pci' device with 'virtio-blk' as it does the similar
>> thing in its virtio_blk_handle_output() function.
>> 
>> Fixes: 110b9463d5c8 ("vhost-user-blk: start vhost when guest kicks")
>> Signed-off-by: Andrey Ryabinin <arbn@yandex-team.com>
>> ---
>> hw/block/vhost-user-blk.c | 4 ----
>> 1 file changed, 4 deletions(-)
>> 
>> diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
>> index aff4d2b8cbd..448ead448f3 100644
>> --- a/hw/block/vhost-user-blk.c
>> +++ b/hw/block/vhost-user-blk.c
>> @@ -279,10 +279,6 @@ static void vhost_user_blk_handle_output(VirtIODevice 
>> *vdev, VirtQueue *vq)
>>     Error *local_err = NULL;
>>     int i, ret;
>> 
>> -    if (!vdev->start_on_kick) {
>> -        return;
>> -    }
>> -
>>     if (!s->connected) {
>>         return;
>>     }
> 
> 
> After looking a bit closer to this ->start_on_kick thing ( commit 
> badaf79cfdbd ("virtio: Introduce started flag to VirtioDevice")
> and follow ups) I'm starting to think that removing it entirely would be the 
> right thing to do here.
> The whole reason for it was to add special case for !VIRTIO_F_VERSION_1 
> guests.

The virtio 1.0 spec section 2.1.2 explicitly says: "The device MUST NOT consume 
buffers or notify the driver before DRIVER_OK.”

Your change here would make QEMU violate this condition. I don’t know what the 
danger is but I assume that wording is there for a reason.

Unless MST or Cornellia (CCed) say otherwise I don’t think this is the correct 
approach.

> If we making start on kick thing for misbehaving VIRTIO_F_VERSION_1 guests 
> too, than the flag is no longer required,
> so we can do following:
> 
> ---
> hw/block/vhost-user-blk.c  |  4 ----
> hw/virtio/virtio-qmp.c     |  2 +-
> hw/virtio/virtio.c         | 21 ++-------------------
> include/hw/virtio/virtio.h |  5 -----
> 4 files changed, 3 insertions(+), 29 deletions(-)
> 
> diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
> index aff4d2b8cbd..448ead448f3 100644
> --- a/hw/block/vhost-user-blk.c
> +++ b/hw/block/vhost-user-blk.c
> @@ -279,10 +279,6 @@ static void vhost_user_blk_handle_output(VirtIODevice 
> *vdev, VirtQueue *vq)
>     Error *local_err = NULL;
>     int i, ret;
> 
> -    if (!vdev->start_on_kick) {
> -        return;
> -    }
> -
>     if (!s->connected) {
>         return;
>     }
> diff --git a/hw/virtio/virtio-qmp.c b/hw/virtio/virtio-qmp.c
> index e4d4bece2d7..4865819cd2f 100644
> --- a/hw/virtio/virtio-qmp.c
> +++ b/hw/virtio/virtio-qmp.c
> @@ -773,7 +773,7 @@ VirtioStatus *qmp_x_query_virtio_status(const char *path, 
> Error **errp)
>     status->disabled = vdev->disabled;
>     status->use_started = vdev->use_started;
>     status->started = vdev->started;
> -    status->start_on_kick = vdev->start_on_kick;
> +    status->start_on_kick = true;
>     status->disable_legacy_check = vdev->disable_legacy_check;
>     status->bus_name = g_strdup(vdev->bus_name);
>     status->use_guest_notifier_mask = vdev->use_guest_notifier_mask;
> diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
> index f35178f5fcd..218584eae85 100644
> --- a/hw/virtio/virtio.c
> +++ b/hw/virtio/virtio.c
> @@ -2126,7 +2126,6 @@ void virtio_reset(void *opaque)
>         k->reset(vdev);
>     }
> 
> -    vdev->start_on_kick = false;
>     vdev->started = false;
>     vdev->broken = false;
>     vdev->guest_features = 0;
> @@ -2248,9 +2247,7 @@ static void virtio_queue_notify_vq(VirtQueue *vq)
>         trace_virtio_queue_notify(vdev, vq - vdev->vq, vq);
>         vq->handle_output(vdev, vq);
> 
> -        if (unlikely(vdev->start_on_kick)) {
> -            virtio_set_started(vdev, true);
> -        }
> +        virtio_set_started(vdev, true);
>     }
> }
> 
> @@ -2268,9 +2265,7 @@ void virtio_queue_notify(VirtIODevice *vdev, int n)
>     } else if (vq->handle_output) {
>         vq->handle_output(vdev, vq);
> 
> -        if (unlikely(vdev->start_on_kick)) {
> -            virtio_set_started(vdev, true);
> -        }
> +        virtio_set_started(vdev, true);
>     }
> }
> 
> @@ -2881,12 +2876,6 @@ int virtio_set_features(VirtIODevice *vdev, uint64_t 
> val)
>             }
>         }
>     }
> -    if (!ret) {
> -        if (!virtio_device_started(vdev, vdev->status) &&
> -            !virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
> -            vdev->start_on_kick = true;
> -        }
> -    }
>     return ret;
> }
> 
> @@ -3039,11 +3028,6 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int 
> version_id)
>         }
>     }
> 
> -    if (!virtio_device_started(vdev, vdev->status) &&
> -        !virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
> -        vdev->start_on_kick = true;
> -    }
> -
>     RCU_READ_LOCK_GUARD();
>     for (i = 0; i < num; i++) {
>         if (vdev->vq[i].vring.desc) {
> @@ -3162,7 +3146,6 @@ void virtio_init(VirtIODevice *vdev, uint16_t 
> device_id, size_t config_size)
>             g_malloc0(sizeof(*vdev->vector_queues) * nvectors);
>     }
> 
> -    vdev->start_on_kick = false;
>     vdev->started = false;
>     vdev->vhost_started = false;
>     vdev->device_id = device_id;
> diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
> index 77c6c55929f..5742876b4fa 100644
> --- a/include/hw/virtio/virtio.h
> +++ b/include/hw/virtio/virtio.h
> @@ -144,7 +144,6 @@ struct VirtIODevice
>      */
>     bool use_started;
>     bool started;
> -    bool start_on_kick; /* when virtio 1.0 feature has not been negotiated */
>     bool disable_legacy_check;
>     bool vhost_started;
>     VMChangeStateEntry *vmstate;
> @@ -460,10 +459,6 @@ static inline bool 
> virtio_device_should_start(VirtIODevice *vdev, uint8_t status
> 
> static inline void virtio_set_started(VirtIODevice *vdev, bool started)
> {
> -    if (started) {
> -        vdev->start_on_kick = false;
> -    }
> -
>     if (vdev->use_started) {
>         vdev->started = started;
>     }
> -- 
> 2.39.2


reply via email to

[Prev in Thread] Current Thread [Next in Thread]