Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Vitaly Kuznetsov and committed by
Greg Kroah-Hartman
cd8dc054 f5722b9b

+56 -12
+37 -12
drivers/hv/hv_snapshot.c
··· 59 59 60 60 static void vss_respond_to_host(int error); 61 61 62 + /* 63 + * This state maintains the version number registered by the daemon. 64 + */ 65 + static int dm_reg_value; 66 + 62 67 static const char vss_devname[] = "vmbus/hv_vss"; 63 68 static __u8 *recv_buffer; 64 69 static struct hvutil_transport *hvt; ··· 94 89 hv_vss_onchannelcallback); 95 90 } 96 91 92 + static int vss_handle_handshake(struct hv_vss_msg *vss_msg) 93 + { 94 + u32 our_ver = VSS_OP_REGISTER1; 95 + 96 + switch (vss_msg->vss_hdr.operation) { 97 + case VSS_OP_REGISTER: 98 + /* Daemon doesn't expect us to reply */ 99 + dm_reg_value = VSS_OP_REGISTER; 100 + break; 101 + case VSS_OP_REGISTER1: 102 + /* Daemon expects us to reply with our own version*/ 103 + if (hvutil_transport_send(hvt, &our_ver, sizeof(our_ver))) 104 + return -EFAULT; 105 + dm_reg_value = VSS_OP_REGISTER1; 106 + break; 107 + default: 108 + return -EINVAL; 109 + } 110 + vss_transaction.state = HVUTIL_READY; 111 + pr_info("VSS daemon registered\n"); 112 + return 0; 113 + } 114 + 97 115 static int vss_on_msg(void *msg, int len) 98 116 { 99 117 struct hv_vss_msg *vss_msg = (struct hv_vss_msg *)msg; ··· 124 96 if (len != sizeof(*vss_msg)) 125 97 return -EINVAL; 126 98 127 - /* 128 - * Don't process registration messages if we're in the middle of 129 - * a transaction processing. 130 - */ 131 - if (vss_transaction.state > HVUTIL_READY && 132 - vss_msg->vss_hdr.operation == VSS_OP_REGISTER) 133 - return -EINVAL; 134 - 135 - if (vss_transaction.state == HVUTIL_DEVICE_INIT && 136 - vss_msg->vss_hdr.operation == VSS_OP_REGISTER) { 137 - pr_info("VSS daemon registered\n"); 138 - vss_transaction.state = HVUTIL_READY; 99 + if (vss_msg->vss_hdr.operation == VSS_OP_REGISTER || 100 + vss_msg->vss_hdr.operation == VSS_OP_REGISTER1) { 101 + /* 102 + * Don't process registration messages if we're in the middle 103 + * of a transaction processing. 104 + */ 105 + if (vss_transaction.state > HVUTIL_READY) 106 + return -EINVAL; 107 + return vss_handle_handshake(vss_msg); 139 108 } else if (vss_transaction.state == HVUTIL_USERSPACE_REQ) { 140 109 vss_transaction.state = HVUTIL_USERSPACE_RECV; 141 110 if (cancel_delayed_work_sync(&vss_timeout_work)) {
+5
include/uapi/linux/hyperv.h
··· 45 45 46 46 #define VSS_OP_REGISTER 128 47 47 48 + /* 49 + Daemon code with full handshake support. 50 + */ 51 + #define VSS_OP_REGISTER1 129 52 + 48 53 enum hv_vss_op { 49 54 VSS_OP_CREATE = 0, 50 55 VSS_OP_DELETE,
+14
tools/hv/hv_vss_daemon.c
··· 148 148 int op; 149 149 struct hv_vss_msg vss_msg[1]; 150 150 int daemonize = 1, long_index = 0, opt; 151 + int in_handshake = 1; 152 + __u32 kernel_modver; 151 153 152 154 static struct option long_options[] = { 153 155 {"help", no_argument, 0, 'h' }, ··· 212 210 } 213 211 214 212 len = read(vss_fd, vss_msg, sizeof(struct hv_vss_msg)); 213 + 214 + if (in_handshake) { 215 + if (len != sizeof(kernel_modver)) { 216 + syslog(LOG_ERR, "invalid version negotiation"); 217 + exit(EXIT_FAILURE); 218 + } 219 + kernel_modver = *(__u32 *)vss_msg; 220 + in_handshake = 0; 221 + syslog(LOG_INFO, "VSS: kernel module version: %d", 222 + kernel_modver); 223 + continue; 224 + } 215 225 216 226 if (len != sizeof(struct hv_vss_msg)) { 217 227 syslog(LOG_ERR, "read failed; error:%d %s",