lkml.org 
[lkml]   [2020]   [Sep]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.4 34/72] Drivers: hv: vmbus: hibernation: do not hang forever in vmbus_bus_resume()
    Date
    From: Dexuan Cui <decui@microsoft.com>

    [ Upstream commit 19873eec7e13fda140a0ebc75d6664e57c00bfb1 ]

    After we Stop and later Start a VM that uses Accelerated Networking (NIC
    SR-IOV), currently the VF vmbus device's Instance GUID can change, so after
    vmbus_bus_resume() -> vmbus_request_offers(), vmbus_onoffer() can not find
    the original vmbus channel of the VF, and hence we can't complete()
    vmbus_connection.ready_for_resume_event in check_ready_for_resume_event(),
    and the VM hangs in vmbus_bus_resume() forever.

    Fix the issue by adding a timeout, so the resuming can still succeed, and
    the saved state is not lost, and according to my test, the user can disable
    Accelerated Networking and then will be able to SSH into the VM for
    further recovery. Also prevent the VM in question from suspending again.

    The host will be fixed so in future the Instance GUID will stay the same
    across hibernation.

    Fixes: d8bd2d442bb2 ("Drivers: hv: vmbus: Resume after fixing up old primary channels")
    Signed-off-by: Dexuan Cui <decui@microsoft.com>
    Reviewed-by: Michael Kelley <mikelley@microsoft.com>
    Link: https://lore.kernel.org/r/20200905025555.45614-1-decui@microsoft.com
    Signed-off-by: Wei Liu <wei.liu@kernel.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/hv/vmbus_drv.c | 9 +++++++--
    1 file changed, 7 insertions(+), 2 deletions(-)

    diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
    index 24c38e44ed3bc..2d2568dac2a66 100644
    --- a/drivers/hv/vmbus_drv.c
    +++ b/drivers/hv/vmbus_drv.c
    @@ -2231,7 +2231,10 @@ static int vmbus_bus_suspend(struct device *dev)
    if (atomic_read(&vmbus_connection.nr_chan_close_on_suspend) > 0)
    wait_for_completion(&vmbus_connection.ready_for_suspend_event);

    - WARN_ON(atomic_read(&vmbus_connection.nr_chan_fixup_on_resume) != 0);
    + if (atomic_read(&vmbus_connection.nr_chan_fixup_on_resume) != 0) {
    + pr_err("Can not suspend due to a previous failed resuming\n");
    + return -EBUSY;
    + }

    mutex_lock(&vmbus_connection.channel_mutex);

    @@ -2305,7 +2308,9 @@ static int vmbus_bus_resume(struct device *dev)

    vmbus_request_offers();

    - wait_for_completion(&vmbus_connection.ready_for_resume_event);
    + if (wait_for_completion_timeout(
    + &vmbus_connection.ready_for_resume_event, 10 * HZ) == 0)
    + pr_err("Some vmbus device is missing after suspending?\n");

    /* Reset the event for the next suspend. */
    reinit_completion(&vmbus_connection.ready_for_suspend_event);
    --
    2.25.1


    \
     
     \ /
      Last update: 2020-09-21 18:49    [W:4.299 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site