summary refs log tree commit diff
path: root/drivers/hv/hv_snapshot.c
diff options
context:
space:
mode:
authorVitaly Kuznetsov <vkuznets@redhat.com>2015-04-11 18:07:57 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-05-24 12:17:41 -0700
commitcd8dc0548511efff7a97d978f989ce67a883f9a5 (patch)
tree19f8d9d160bec2423561ba39a0722ea551c2c162 /drivers/hv/hv_snapshot.c
parentf5722b9bd418e29b7429bd9a43bd100599b26d4f (diff)
downloadlinux-cd8dc0548511efff7a97d978f989ce67a883f9a5.tar.gz
Drivers: hv: vss: full handshake support
Introduce VSS_OP_REGISTER1 to support kernel replying to the negotiation
message with its own version.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Tested-by: Alex Ng <alexng@microsoft.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/hv/hv_snapshot.c')
-rw-r--r--drivers/hv/hv_snapshot.c49
1 files changed, 37 insertions, 12 deletions
diff --git a/drivers/hv/hv_snapshot.c b/drivers/hv/hv_snapshot.c
index 2c8c246d09eb..ee1762b39bf2 100644
--- a/drivers/hv/hv_snapshot.c
+++ b/drivers/hv/hv_snapshot.c
@@ -59,6 +59,11 @@ static struct {
 
 static void vss_respond_to_host(int error);
 
+/*
+ * This state maintains the version number registered by the daemon.
+ */
+static int dm_reg_value;
+
 static const char vss_devname[] = "vmbus/hv_vss";
 static __u8 *recv_buffer;
 static struct hvutil_transport *hvt;
@@ -89,6 +94,29 @@ static void vss_timeout_func(struct work_struct *dummy)
 			hv_vss_onchannelcallback);
 }
 
+static int vss_handle_handshake(struct hv_vss_msg *vss_msg)
+{
+	u32 our_ver = VSS_OP_REGISTER1;
+
+	switch (vss_msg->vss_hdr.operation) {
+	case VSS_OP_REGISTER:
+		/* Daemon doesn't expect us to reply */
+		dm_reg_value = VSS_OP_REGISTER;
+		break;
+	case VSS_OP_REGISTER1:
+		/* Daemon expects us to reply with our own version*/
+		if (hvutil_transport_send(hvt, &our_ver, sizeof(our_ver)))
+			return -EFAULT;
+		dm_reg_value = VSS_OP_REGISTER1;
+		break;
+	default:
+		return -EINVAL;
+	}
+	vss_transaction.state = HVUTIL_READY;
+	pr_info("VSS daemon registered\n");
+	return 0;
+}
+
 static int vss_on_msg(void *msg, int len)
 {
 	struct hv_vss_msg *vss_msg = (struct hv_vss_msg *)msg;
@@ -96,18 +124,15 @@ static int vss_on_msg(void *msg, int len)
 	if (len != sizeof(*vss_msg))
 		return -EINVAL;
 
-	/*
-	 * Don't process registration messages if we're in the middle of
-	 * a transaction processing.
-	 */
-	if (vss_transaction.state > HVUTIL_READY &&
-	    vss_msg->vss_hdr.operation == VSS_OP_REGISTER)
-		return -EINVAL;
-
-	if (vss_transaction.state == HVUTIL_DEVICE_INIT &&
-	    vss_msg->vss_hdr.operation == VSS_OP_REGISTER) {
-		pr_info("VSS daemon registered\n");
-		vss_transaction.state = HVUTIL_READY;
+	if (vss_msg->vss_hdr.operation == VSS_OP_REGISTER ||
+	    vss_msg->vss_hdr.operation == VSS_OP_REGISTER1) {
+		/*
+		 * Don't process registration messages if we're in the middle
+		 * of a transaction processing.
+		 */
+		if (vss_transaction.state > HVUTIL_READY)
+			return -EINVAL;
+		return vss_handle_handshake(vss_msg);
 	} else if (vss_transaction.state == HVUTIL_USERSPACE_REQ) {
 		vss_transaction.state = HVUTIL_USERSPACE_RECV;
 		if (cancel_delayed_work_sync(&vss_timeout_work)) {