RE: [PATCH v3 2/4] hv_utils: Support host-initiated restart request

From: Michael Kelley
Date: Sat Jan 25 2020 - 23:57:06 EST


From: Dexuan Cui <decui@xxxxxxxxxxxxx> Sent: Saturday, January 25, 2020 11:54 AM
>
> The hv_utils driver currently supports a "shutdown" operation initiated
> from the Hyper-V host. Newer versions of Hyper-V also support a "restart"
> operation. So add support for the updated protocol version that has
> "restart" support, and perform a clean reboot when such a message is
> received from Hyper-V.
>
> To test the restart functionality, run this PowerShell command on the
> Hyper-V host:
>
> Restart-VM <vmname> -Type Reboot
>
> Signed-off-by: Dexuan Cui <decui@xxxxxxxxxxxxx>
>
> ---
> Changes in v2:
> It's the same as v1.
>
> Changes in v3 (I addressed Michael's comments):
> Used a better version of changelog from Michael.
> Added a comment about the meaning of shutdown_msg->flags.
> Call schedule_work() at the end of the function for consistency.
>
> drivers/hv/hv_util.c | 32 +++++++++++++++++++++++++++++++-
> 1 file changed, 31 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
> index 766bd8457346..d815bea0fda3 100644
> --- a/drivers/hv/hv_util.c
> +++ b/drivers/hv/hv_util.c
> @@ -24,6 +24,8 @@
>
> #define SD_MAJOR 3
> #define SD_MINOR 0
> +#define SD_MINOR_1 1
> +#define SD_VERSION_3_1 (SD_MAJOR << 16 | SD_MINOR_1)
> #define SD_VERSION (SD_MAJOR << 16 | SD_MINOR)
>
> #define SD_MAJOR_1 1
> @@ -50,8 +52,9 @@ static int sd_srv_version;
> static int ts_srv_version;
> static int hb_srv_version;
>
> -#define SD_VER_COUNT 2
> +#define SD_VER_COUNT 3
> static const int sd_versions[] = {
> + SD_VERSION_3_1,
> SD_VERSION,
> SD_VERSION_1
> };
> @@ -118,17 +121,28 @@ static void perform_shutdown(struct work_struct *dummy)
> orderly_poweroff(true);
> }
>
> +static void perform_restart(struct work_struct *dummy)
> +{
> + orderly_reboot();
> +}
> +
> /*
> * Perform the shutdown operation in a thread context.
> */
> static DECLARE_WORK(shutdown_work, perform_shutdown);
>
> +/*
> + * Perform the restart operation in a thread context.
> + */
> +static DECLARE_WORK(restart_work, perform_restart);
> +
> static void shutdown_onchannelcallback(void *context)
> {
> struct vmbus_channel *channel = context;
> u32 recvlen;
> u64 requestid;
> bool execute_shutdown = false;
> + bool execute_reboot = false;
> u8 *shut_txf_buf = util_shutdown.recv_buffer;
>
> struct shutdown_msg_data *shutdown_msg;
> @@ -157,6 +171,12 @@ static void shutdown_onchannelcallback(void *context)
> sizeof(struct vmbuspipe_hdr) +
> sizeof(struct icmsg_hdr)];
>
> + /*
> + * shutdown_msg->flags can be 0 (shut down), 2(reboot),
> + * or 4(hibernate). It may bitwise-OR 1, which means
> + * performing the request by force. Linux always tries
> + * to perform the request by force.
> + */
> switch (shutdown_msg->flags) {
> case 0:
> case 1:
> @@ -166,6 +186,14 @@ static void shutdown_onchannelcallback(void *context)
> pr_info("Shutdown request received -"
> " graceful shutdown initiated\n");
> break;
> + case 2:
> + case 3:
> + icmsghdrp->status = HV_S_OK;
> + execute_reboot = true;
> +
> + pr_info("Restart request received -"
> + " graceful restart initiated\n");
> + break;
> default:
> icmsghdrp->status = HV_E_FAIL;
> execute_shutdown = false;
> @@ -186,6 +214,8 @@ static void shutdown_onchannelcallback(void *context)
>
> if (execute_shutdown == true)
> schedule_work(&shutdown_work);
> + if (execute_reboot == true)
> + schedule_work(&restart_work);

This works, and responds to my comment. But FWIW, a more compact
approach would be to drop the boolean execute_shutdown, execute_restart,
etc. local variables and have just this local variable:

struct work_struct *work_to_do = NULL;

In the "case" branches do:

work_to_do = &shutdown_work;

or
work_to_do = &restart_work;

Then at the bottom of the function, just do:

if (work_to_do)
schedule_work(work_to_do);

Patch 3 of this series would then be a little simpler as well.

> }
>
> /*
> --
> 2.19.1