diff --git a/drivers/hv/hv_snapshot.c b/drivers/hv/hv_snapshot.c index fde45865579a..c4013c859bcd 100644 --- a/drivers/hv/hv_snapshot.c +++ b/drivers/hv/hv_snapshot.c @@ -67,11 +67,11 @@ static const char vss_devname[] = "vmbus/hv_vss"; static __u8 *recv_buffer; static struct hvutil_transport *hvt; -static void vss_send_op(struct work_struct *dummy); static void vss_timeout_func(struct work_struct *dummy); +static void vss_handle_request(struct work_struct *dummy); static DECLARE_DELAYED_WORK(vss_timeout_work, vss_timeout_func); -static DECLARE_WORK(vss_send_op_work, vss_send_op); +static DECLARE_WORK(vss_handle_request_work, vss_handle_request); static void vss_poll_wrapper(void *channel) { @@ -156,8 +156,7 @@ static int vss_on_msg(void *msg, int len) return 0; } - -static void vss_send_op(struct work_struct *dummy) +static void vss_send_op(void) { int op = vss_transaction.msg->vss_hdr.operation; int rc; @@ -174,6 +173,9 @@ static void vss_send_op(struct work_struct *dummy) vss_msg->vss_hdr.operation = op; vss_transaction.state = HVUTIL_USERSPACE_REQ; + + schedule_delayed_work(&vss_timeout_work, VSS_USERSPACE_TIMEOUT); + rc = hvutil_transport_send(hvt, vss_msg, sizeof(*vss_msg), NULL); if (rc) { pr_warn("VSS: failed to communicate to the daemon: %d\n", rc); @@ -188,6 +190,40 @@ static void vss_send_op(struct work_struct *dummy) return; } +static void vss_handle_request(struct work_struct *dummy) +{ + switch (vss_transaction.msg->vss_hdr.operation) { + /* + * Initiate a "freeze/thaw" operation in the guest. + * We respond to the host once the operation is complete. + * + * We send the message to the user space daemon and the operation is + * performed in the daemon. + */ + case VSS_OP_THAW: + case VSS_OP_FREEZE: + if (vss_transaction.state < HVUTIL_READY) { + /* Userspace is not registered yet */ + vss_respond_to_host(HV_E_FAIL); + return; + } + vss_transaction.state = HVUTIL_HOSTMSG_RECEIVED; + vss_send_op(); + return; + case VSS_OP_HOT_BACKUP: + vss_transaction.msg->vss_cf.flags = VSS_HBU_NO_AUTO_RECOVERY; + break; + case VSS_OP_GET_DM_INFO: + vss_transaction.msg->dm_info.flags = 0; + break; + default: + break; + } + + vss_respond_to_host(0); + hv_poll_channel(vss_transaction.recv_channel, vss_poll_wrapper); +} + /* * Send a response back to the host. */ @@ -272,48 +308,8 @@ void hv_vss_onchannelcallback(void *context) vss_transaction.recv_req_id = requestid; vss_transaction.msg = (struct hv_vss_msg *)vss_msg; - switch (vss_msg->vss_hdr.operation) { - /* - * Initiate a "freeze/thaw" - * operation in the guest. - * We respond to the host once - * the operation is complete. - * - * We send the message to the - * user space daemon and the - * operation is performed in - * the daemon. - */ - case VSS_OP_FREEZE: - case VSS_OP_THAW: - if (vss_transaction.state < HVUTIL_READY) { - /* Userspace is not registered yet */ - vss_respond_to_host(HV_E_FAIL); - return; - } - vss_transaction.state = HVUTIL_HOSTMSG_RECEIVED; - schedule_work(&vss_send_op_work); - schedule_delayed_work(&vss_timeout_work, - VSS_USERSPACE_TIMEOUT); - return; - - case VSS_OP_HOT_BACKUP: - vss_msg->vss_cf.flags = - VSS_HBU_NO_AUTO_RECOVERY; - vss_respond_to_host(0); - return; - - case VSS_OP_GET_DM_INFO: - vss_msg->dm_info.flags = 0; - vss_respond_to_host(0); - return; - - default: - vss_respond_to_host(0); - return; - - } - + schedule_work(&vss_handle_request_work); + return; } icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION @@ -364,6 +360,6 @@ void hv_vss_deinit(void) { vss_transaction.state = HVUTIL_DEVICE_DYING; cancel_delayed_work_sync(&vss_timeout_work); - cancel_work_sync(&vss_send_op_work); + cancel_work_sync(&vss_handle_request_work); hvutil_transport_destroy(hvt); }