Introduce FCOPY_VERSION_1 to support kernel replying to the negotiation message with its own version.
Unified · Split
| @@ -62,6 +62,10 @@ static DECLARE_WORK(fcopy_send_work, fcopy_send_data); · 61 unmodified lines | ||
| 62 | 62 | static const char fcopy_devname[] = "vmbus/hv_fcopy"; |
| 63 | 63 | static u8 *recv_buffer; |
| 64 | 64 | static struct hvutil_transport *hvt; |
| 65 | +/* | |
| 66 | + * This state maintains the version number registered by the daemon. | |
| 67 | + */ | |
| 68 | +static int dm_reg_value; | |
| 65 | 69 | |
| 66 | 70 | static void fcopy_timeout_func(struct work_struct *dummy) |
| 67 | 71 | { |
| @@ -81,8 +85,18 @@ static void fcopy_timeout_func(struct work_struct *dummy) · 13 unmodified lines | ||
| 81 | 85 | |
| 82 | 86 | static int fcopy_handle_handshake(u32 version) |
| 83 | 87 | { |
| 88 | + u32 our_ver = FCOPY_CURRENT_VERSION; | |
| 89 | + | |
| 84 | 90 | switch (version) { |
| 85 | − case FCOPY_CURRENT_VERSION: | |
| 91 | + case FCOPY_VERSION_0: | |
| 92 | + /* Daemon doesn't expect us to reply */ | |
| 93 | + dm_reg_value = version; | |
| 94 | + break; | |
| 95 | + case FCOPY_VERSION_1: | |
| 96 | + /* Daemon expects us to reply with our own version */ | |
| 97 | + if (hvutil_transport_send(hvt, &our_ver, sizeof(our_ver))) | |
| 98 | + return -EFAULT; | |
| 99 | + dm_reg_value = version; | |
| 86 | 100 | break; |
| 87 | 101 | default: |
| 88 | 102 | /* |
| @@ -105,7 +105,8 @@ struct hv_vss_msg { · 104 unmodified lines | ||
| 105 | 105 | */ |
| 106 | 106 | |
| 107 | 107 | #define FCOPY_VERSION_0 0 |
| 108 | −#define FCOPY_CURRENT_VERSION FCOPY_VERSION_0 | |
| 108 | +#define FCOPY_VERSION_1 1 | |
| 109 | +#define FCOPY_CURRENT_VERSION FCOPY_VERSION_1 | |
| 109 | 110 | #define W_MAX_PATH 260 |
| 110 | 111 | |
| 111 | 112 | enum hv_fcopy_op { |
| @@ -137,6 +137,8 @@ int main(int argc, char *argv[]) · 136 unmodified lines | ||
| 137 | 137 | int version = FCOPY_CURRENT_VERSION; |
| 138 | 138 | char *buffer[4096 * 2]; |
| 139 | 139 | struct hv_fcopy_hdr *in_msg; |
| 140 | + int in_handshake = 1; | |
| 141 | + __u32 kernel_modver; | |
| 140 | 142 | |
| 141 | 143 | static struct option long_options[] = { |
| 142 | 144 | {"help", no_argument, 0, 'h' }, |
| @@ -191,6 +193,19 @@ int main(int argc, char *argv[]) · 48 unmodified lines | ||
| 191 | 193 | syslog(LOG_ERR, "pread failed: %s", strerror(errno)); |
| 192 | 194 | exit(EXIT_FAILURE); |
| 193 | 195 | } |
| 196 | + | |
| 197 | + if (in_handshake) { | |
| 198 | + if (len != sizeof(kernel_modver)) { | |
| 199 | + syslog(LOG_ERR, "invalid version negotiation"); | |
| 200 | + exit(EXIT_FAILURE); | |
| 201 | + } | |
| 202 | + kernel_modver = *(__u32 *)buffer; | |
| 203 | + in_handshake = 0; | |
| 204 | + syslog(LOG_INFO, "HV_FCOPY: kernel module version: %d", | |
| 205 | + kernel_modver); | |
| 206 | + continue; | |
| 207 | + } | |
| 208 | + | |
| 194 | 209 | in_msg = (struct hv_fcopy_hdr *)buffer; |
| 195 | 210 | |
| 196 | 211 | switch (in_msg->operation) { |