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

Configure Feed

Select the types of activity you want to include in your feed.

Drivers: hv: Remove fcopy driver

As the new fcopy driver using uio is introduced, remove obsolete driver
and application.

Signed-off-by: Saurabh Sengar <ssengar@linux.microsoft.com>
Reviewed-by: Long Li <longli@microsoft.com>
Link: https://lore.kernel.org/r/1711788723-8593-7-git-send-email-ssengar@linux.microsoft.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Saurabh Sengar and committed by
Greg Kroah-Hartman
ec314f61 82b0945c

+1 -706
+1 -1
drivers/hv/Makefile
··· 10 10 hv.o connection.o channel.o \ 11 11 channel_mgmt.o ring_buffer.o hv_trace.o 12 12 hv_vmbus-$(CONFIG_HYPERV_TESTING) += hv_debugfs.o 13 - hv_utils-y := hv_util.o hv_kvp.o hv_snapshot.o hv_fcopy.o hv_utils_transport.o 13 + hv_utils-y := hv_util.o hv_kvp.o hv_snapshot.o hv_utils_transport.o 14 14 15 15 # Code that must be built-in 16 16 obj-$(subst m,y,$(CONFIG_HYPERV)) += hv_common.o
-427
drivers/hv/hv_fcopy.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - /* 3 - * An implementation of file copy service. 4 - * 5 - * Copyright (C) 2014, Microsoft, Inc. 6 - * 7 - * Author : K. Y. Srinivasan <ksrinivasan@novell.com> 8 - */ 9 - 10 - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 11 - 12 - #include <linux/nls.h> 13 - #include <linux/workqueue.h> 14 - #include <linux/hyperv.h> 15 - #include <linux/sched.h> 16 - #include <asm/hyperv-tlfs.h> 17 - 18 - #include "hyperv_vmbus.h" 19 - #include "hv_utils_transport.h" 20 - 21 - #define WIN8_SRV_MAJOR 1 22 - #define WIN8_SRV_MINOR 1 23 - #define WIN8_SRV_VERSION (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR) 24 - 25 - #define FCOPY_VER_COUNT 1 26 - static const int fcopy_versions[] = { 27 - WIN8_SRV_VERSION 28 - }; 29 - 30 - #define FW_VER_COUNT 1 31 - static const int fw_versions[] = { 32 - UTIL_FW_VERSION 33 - }; 34 - 35 - /* 36 - * Global state maintained for transaction that is being processed. 37 - * For a class of integration services, including the "file copy service", 38 - * the specified protocol is a "request/response" protocol which means that 39 - * there can only be single outstanding transaction from the host at any 40 - * given point in time. We use this to simplify memory management in this 41 - * driver - we cache and process only one message at a time. 42 - * 43 - * While the request/response protocol is guaranteed by the host, we further 44 - * ensure this by serializing packet processing in this driver - we do not 45 - * read additional packets from the VMBUs until the current packet is fully 46 - * handled. 47 - */ 48 - 49 - static struct { 50 - int state; /* hvutil_device_state */ 51 - int recv_len; /* number of bytes received. */ 52 - struct hv_fcopy_hdr *fcopy_msg; /* current message */ 53 - struct vmbus_channel *recv_channel; /* chn we got the request */ 54 - u64 recv_req_id; /* request ID. */ 55 - } fcopy_transaction; 56 - 57 - static void fcopy_respond_to_host(int error); 58 - static void fcopy_send_data(struct work_struct *dummy); 59 - static void fcopy_timeout_func(struct work_struct *dummy); 60 - static DECLARE_DELAYED_WORK(fcopy_timeout_work, fcopy_timeout_func); 61 - static DECLARE_WORK(fcopy_send_work, fcopy_send_data); 62 - static const char fcopy_devname[] = "vmbus/hv_fcopy"; 63 - static u8 *recv_buffer; 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; 69 - 70 - static void fcopy_poll_wrapper(void *channel) 71 - { 72 - /* Transaction is finished, reset the state here to avoid races. */ 73 - fcopy_transaction.state = HVUTIL_READY; 74 - tasklet_schedule(&((struct vmbus_channel *)channel)->callback_event); 75 - } 76 - 77 - static void fcopy_timeout_func(struct work_struct *dummy) 78 - { 79 - /* 80 - * If the timer fires, the user-mode component has not responded; 81 - * process the pending transaction. 82 - */ 83 - fcopy_respond_to_host(HV_E_FAIL); 84 - hv_poll_channel(fcopy_transaction.recv_channel, fcopy_poll_wrapper); 85 - } 86 - 87 - static void fcopy_register_done(void) 88 - { 89 - pr_debug("FCP: userspace daemon registered\n"); 90 - hv_poll_channel(fcopy_transaction.recv_channel, fcopy_poll_wrapper); 91 - } 92 - 93 - static int fcopy_handle_handshake(u32 version) 94 - { 95 - u32 our_ver = FCOPY_CURRENT_VERSION; 96 - 97 - switch (version) { 98 - case FCOPY_VERSION_0: 99 - /* Daemon doesn't expect us to reply */ 100 - dm_reg_value = version; 101 - break; 102 - case FCOPY_VERSION_1: 103 - /* Daemon expects us to reply with our own version */ 104 - if (hvutil_transport_send(hvt, &our_ver, sizeof(our_ver), 105 - fcopy_register_done)) 106 - return -EFAULT; 107 - dm_reg_value = version; 108 - break; 109 - default: 110 - /* 111 - * For now we will fail the registration. 112 - * If and when we have multiple versions to 113 - * deal with, we will be backward compatible. 114 - * We will add this code when needed. 115 - */ 116 - return -EINVAL; 117 - } 118 - pr_debug("FCP: userspace daemon ver. %d connected\n", version); 119 - return 0; 120 - } 121 - 122 - static void fcopy_send_data(struct work_struct *dummy) 123 - { 124 - struct hv_start_fcopy *smsg_out = NULL; 125 - int operation = fcopy_transaction.fcopy_msg->operation; 126 - struct hv_start_fcopy *smsg_in; 127 - void *out_src; 128 - int rc, out_len; 129 - 130 - /* 131 - * The strings sent from the host are encoded in 132 - * utf16; convert it to utf8 strings. 133 - * The host assures us that the utf16 strings will not exceed 134 - * the max lengths specified. We will however, reserve room 135 - * for the string terminating character - in the utf16s_utf8s() 136 - * function we limit the size of the buffer where the converted 137 - * string is placed to W_MAX_PATH -1 to guarantee 138 - * that the strings can be properly terminated! 139 - */ 140 - 141 - switch (operation) { 142 - case START_FILE_COPY: 143 - out_len = sizeof(struct hv_start_fcopy); 144 - smsg_out = kzalloc(sizeof(*smsg_out), GFP_KERNEL); 145 - if (!smsg_out) 146 - return; 147 - 148 - smsg_out->hdr.operation = operation; 149 - smsg_in = (struct hv_start_fcopy *)fcopy_transaction.fcopy_msg; 150 - 151 - utf16s_to_utf8s((wchar_t *)smsg_in->file_name, W_MAX_PATH, 152 - UTF16_LITTLE_ENDIAN, 153 - (__u8 *)&smsg_out->file_name, W_MAX_PATH - 1); 154 - 155 - utf16s_to_utf8s((wchar_t *)smsg_in->path_name, W_MAX_PATH, 156 - UTF16_LITTLE_ENDIAN, 157 - (__u8 *)&smsg_out->path_name, W_MAX_PATH - 1); 158 - 159 - smsg_out->copy_flags = smsg_in->copy_flags; 160 - smsg_out->file_size = smsg_in->file_size; 161 - out_src = smsg_out; 162 - break; 163 - 164 - case WRITE_TO_FILE: 165 - out_src = fcopy_transaction.fcopy_msg; 166 - out_len = sizeof(struct hv_do_fcopy); 167 - break; 168 - default: 169 - out_src = fcopy_transaction.fcopy_msg; 170 - out_len = fcopy_transaction.recv_len; 171 - break; 172 - } 173 - 174 - fcopy_transaction.state = HVUTIL_USERSPACE_REQ; 175 - rc = hvutil_transport_send(hvt, out_src, out_len, NULL); 176 - if (rc) { 177 - pr_debug("FCP: failed to communicate to the daemon: %d\n", rc); 178 - if (cancel_delayed_work_sync(&fcopy_timeout_work)) { 179 - fcopy_respond_to_host(HV_E_FAIL); 180 - fcopy_transaction.state = HVUTIL_READY; 181 - } 182 - } 183 - kfree(smsg_out); 184 - } 185 - 186 - /* 187 - * Send a response back to the host. 188 - */ 189 - 190 - static void 191 - fcopy_respond_to_host(int error) 192 - { 193 - struct icmsg_hdr *icmsghdr; 194 - u32 buf_len; 195 - struct vmbus_channel *channel; 196 - u64 req_id; 197 - 198 - /* 199 - * Copy the global state for completing the transaction. Note that 200 - * only one transaction can be active at a time. This is guaranteed 201 - * by the file copy protocol implemented by the host. Furthermore, 202 - * the "transaction active" state we maintain ensures that there can 203 - * only be one active transaction at a time. 204 - */ 205 - 206 - buf_len = fcopy_transaction.recv_len; 207 - channel = fcopy_transaction.recv_channel; 208 - req_id = fcopy_transaction.recv_req_id; 209 - 210 - icmsghdr = (struct icmsg_hdr *) 211 - &recv_buffer[sizeof(struct vmbuspipe_hdr)]; 212 - 213 - if (channel->onchannel_callback == NULL) 214 - /* 215 - * We have raced with util driver being unloaded; 216 - * silently return. 217 - */ 218 - return; 219 - 220 - icmsghdr->status = error; 221 - icmsghdr->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; 222 - vmbus_sendpacket(channel, recv_buffer, buf_len, req_id, 223 - VM_PKT_DATA_INBAND, 0); 224 - } 225 - 226 - void hv_fcopy_onchannelcallback(void *context) 227 - { 228 - struct vmbus_channel *channel = context; 229 - u32 recvlen; 230 - u64 requestid; 231 - struct hv_fcopy_hdr *fcopy_msg; 232 - struct icmsg_hdr *icmsghdr; 233 - int fcopy_srv_version; 234 - 235 - if (fcopy_transaction.state > HVUTIL_READY) 236 - return; 237 - 238 - if (vmbus_recvpacket(channel, recv_buffer, HV_HYP_PAGE_SIZE * 2, &recvlen, &requestid)) { 239 - pr_err_ratelimited("Fcopy request received. Could not read into recv buf\n"); 240 - return; 241 - } 242 - 243 - if (!recvlen) 244 - return; 245 - 246 - /* Ensure recvlen is big enough to read header data */ 247 - if (recvlen < ICMSG_HDR) { 248 - pr_err_ratelimited("Fcopy request received. Packet length too small: %d\n", 249 - recvlen); 250 - return; 251 - } 252 - 253 - icmsghdr = (struct icmsg_hdr *)&recv_buffer[ 254 - sizeof(struct vmbuspipe_hdr)]; 255 - 256 - if (icmsghdr->icmsgtype == ICMSGTYPE_NEGOTIATE) { 257 - if (vmbus_prep_negotiate_resp(icmsghdr, 258 - recv_buffer, recvlen, 259 - fw_versions, FW_VER_COUNT, 260 - fcopy_versions, FCOPY_VER_COUNT, 261 - NULL, &fcopy_srv_version)) { 262 - 263 - pr_info("FCopy IC version %d.%d\n", 264 - fcopy_srv_version >> 16, 265 - fcopy_srv_version & 0xFFFF); 266 - } 267 - } else if (icmsghdr->icmsgtype == ICMSGTYPE_FCOPY) { 268 - /* Ensure recvlen is big enough to contain hv_fcopy_hdr */ 269 - if (recvlen < ICMSG_HDR + sizeof(struct hv_fcopy_hdr)) { 270 - pr_err_ratelimited("Invalid Fcopy hdr. Packet length too small: %u\n", 271 - recvlen); 272 - return; 273 - } 274 - fcopy_msg = (struct hv_fcopy_hdr *)&recv_buffer[ICMSG_HDR]; 275 - 276 - /* 277 - * Stash away this global state for completing the 278 - * transaction; note transactions are serialized. 279 - */ 280 - 281 - fcopy_transaction.recv_len = recvlen; 282 - fcopy_transaction.recv_req_id = requestid; 283 - fcopy_transaction.fcopy_msg = fcopy_msg; 284 - 285 - if (fcopy_transaction.state < HVUTIL_READY) { 286 - /* Userspace is not registered yet */ 287 - fcopy_respond_to_host(HV_E_FAIL); 288 - return; 289 - } 290 - fcopy_transaction.state = HVUTIL_HOSTMSG_RECEIVED; 291 - 292 - /* 293 - * Send the information to the user-level daemon. 294 - */ 295 - schedule_work(&fcopy_send_work); 296 - schedule_delayed_work(&fcopy_timeout_work, 297 - HV_UTIL_TIMEOUT * HZ); 298 - return; 299 - } else { 300 - pr_err_ratelimited("Fcopy request received. Invalid msg type: %d\n", 301 - icmsghdr->icmsgtype); 302 - return; 303 - } 304 - icmsghdr->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; 305 - vmbus_sendpacket(channel, recv_buffer, recvlen, requestid, 306 - VM_PKT_DATA_INBAND, 0); 307 - } 308 - 309 - /* Callback when data is received from userspace */ 310 - static int fcopy_on_msg(void *msg, int len) 311 - { 312 - int *val = (int *)msg; 313 - 314 - if (len != sizeof(int)) 315 - return -EINVAL; 316 - 317 - if (fcopy_transaction.state == HVUTIL_DEVICE_INIT) 318 - return fcopy_handle_handshake(*val); 319 - 320 - if (fcopy_transaction.state != HVUTIL_USERSPACE_REQ) 321 - return -EINVAL; 322 - 323 - /* 324 - * Complete the transaction by forwarding the result 325 - * to the host. But first, cancel the timeout. 326 - */ 327 - if (cancel_delayed_work_sync(&fcopy_timeout_work)) { 328 - fcopy_transaction.state = HVUTIL_USERSPACE_RECV; 329 - fcopy_respond_to_host(*val); 330 - hv_poll_channel(fcopy_transaction.recv_channel, 331 - fcopy_poll_wrapper); 332 - } 333 - 334 - return 0; 335 - } 336 - 337 - static void fcopy_on_reset(void) 338 - { 339 - /* 340 - * The daemon has exited; reset the state. 341 - */ 342 - fcopy_transaction.state = HVUTIL_DEVICE_INIT; 343 - 344 - if (cancel_delayed_work_sync(&fcopy_timeout_work)) 345 - fcopy_respond_to_host(HV_E_FAIL); 346 - } 347 - 348 - int hv_fcopy_init(struct hv_util_service *srv) 349 - { 350 - recv_buffer = srv->recv_buffer; 351 - fcopy_transaction.recv_channel = srv->channel; 352 - fcopy_transaction.recv_channel->max_pkt_size = HV_HYP_PAGE_SIZE * 2; 353 - 354 - /* 355 - * When this driver loads, the user level daemon that 356 - * processes the host requests may not yet be running. 357 - * Defer processing channel callbacks until the daemon 358 - * has registered. 359 - */ 360 - fcopy_transaction.state = HVUTIL_DEVICE_INIT; 361 - 362 - hvt = hvutil_transport_init(fcopy_devname, 0, 0, 363 - fcopy_on_msg, fcopy_on_reset); 364 - if (!hvt) 365 - return -EFAULT; 366 - 367 - return 0; 368 - } 369 - 370 - static void hv_fcopy_cancel_work(void) 371 - { 372 - cancel_delayed_work_sync(&fcopy_timeout_work); 373 - cancel_work_sync(&fcopy_send_work); 374 - } 375 - 376 - int hv_fcopy_pre_suspend(void) 377 - { 378 - struct vmbus_channel *channel = fcopy_transaction.recv_channel; 379 - struct hv_fcopy_hdr *fcopy_msg; 380 - 381 - /* 382 - * Fake a CANCEL_FCOPY message for the user space daemon in case the 383 - * daemon is in the middle of copying some file. It doesn't matter if 384 - * there is already a message pending to be delivered to the user 385 - * space since we force fcopy_transaction.state to be HVUTIL_READY, so 386 - * the user space daemon's write() will fail with EINVAL (see 387 - * fcopy_on_msg()), and the daemon will reset the device by closing 388 - * and re-opening it. 389 - */ 390 - fcopy_msg = kzalloc(sizeof(*fcopy_msg), GFP_KERNEL); 391 - if (!fcopy_msg) 392 - return -ENOMEM; 393 - 394 - tasklet_disable(&channel->callback_event); 395 - 396 - fcopy_msg->operation = CANCEL_FCOPY; 397 - 398 - hv_fcopy_cancel_work(); 399 - 400 - /* We don't care about the return value. */ 401 - hvutil_transport_send(hvt, fcopy_msg, sizeof(*fcopy_msg), NULL); 402 - 403 - kfree(fcopy_msg); 404 - 405 - fcopy_transaction.state = HVUTIL_READY; 406 - 407 - /* tasklet_enable() will be called in hv_fcopy_pre_resume(). */ 408 - return 0; 409 - } 410 - 411 - int hv_fcopy_pre_resume(void) 412 - { 413 - struct vmbus_channel *channel = fcopy_transaction.recv_channel; 414 - 415 - tasklet_enable(&channel->callback_event); 416 - 417 - return 0; 418 - } 419 - 420 - void hv_fcopy_deinit(void) 421 - { 422 - fcopy_transaction.state = HVUTIL_DEVICE_DYING; 423 - 424 - hv_fcopy_cancel_work(); 425 - 426 - hvutil_transport_destroy(hvt); 427 - }
-12
drivers/hv/hv_util.c
··· 154 154 .util_deinit = hv_vss_deinit, 155 155 }; 156 156 157 - static struct hv_util_service util_fcopy = { 158 - .util_cb = hv_fcopy_onchannelcallback, 159 - .util_init = hv_fcopy_init, 160 - .util_pre_suspend = hv_fcopy_pre_suspend, 161 - .util_pre_resume = hv_fcopy_pre_resume, 162 - .util_deinit = hv_fcopy_deinit, 163 - }; 164 - 165 157 static void perform_shutdown(struct work_struct *dummy) 166 158 { 167 159 orderly_poweroff(true); ··· 691 699 /* VSS GUID */ 692 700 { HV_VSS_GUID, 693 701 .driver_data = (unsigned long)&util_vss 694 - }, 695 - /* File copy GUID */ 696 - { HV_FCOPY_GUID, 697 - .driver_data = (unsigned long)&util_fcopy 698 702 }, 699 703 { }, 700 704 };
-266
tools/hv/hv_fcopy_daemon.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - /* 3 - * An implementation of host to guest copy functionality for Linux. 4 - * 5 - * Copyright (C) 2014, Microsoft, Inc. 6 - * 7 - * Author : K. Y. Srinivasan <kys@microsoft.com> 8 - */ 9 - 10 - 11 - #include <sys/types.h> 12 - #include <stdio.h> 13 - #include <stdlib.h> 14 - #include <unistd.h> 15 - #include <string.h> 16 - #include <errno.h> 17 - #include <linux/hyperv.h> 18 - #include <linux/limits.h> 19 - #include <syslog.h> 20 - #include <sys/stat.h> 21 - #include <fcntl.h> 22 - #include <getopt.h> 23 - 24 - static int target_fd; 25 - static char target_fname[PATH_MAX]; 26 - static unsigned long long filesize; 27 - 28 - static int hv_start_fcopy(struct hv_start_fcopy *smsg) 29 - { 30 - int error = HV_E_FAIL; 31 - char *q, *p; 32 - 33 - filesize = 0; 34 - p = (char *)smsg->path_name; 35 - snprintf(target_fname, sizeof(target_fname), "%s/%s", 36 - (char *)smsg->path_name, (char *)smsg->file_name); 37 - 38 - syslog(LOG_INFO, "Target file name: %s", target_fname); 39 - /* 40 - * Check to see if the path is already in place; if not, 41 - * create if required. 42 - */ 43 - while ((q = strchr(p, '/')) != NULL) { 44 - if (q == p) { 45 - p++; 46 - continue; 47 - } 48 - *q = '\0'; 49 - if (access((char *)smsg->path_name, F_OK)) { 50 - if (smsg->copy_flags & CREATE_PATH) { 51 - if (mkdir((char *)smsg->path_name, 0755)) { 52 - syslog(LOG_ERR, "Failed to create %s", 53 - (char *)smsg->path_name); 54 - goto done; 55 - } 56 - } else { 57 - syslog(LOG_ERR, "Invalid path: %s", 58 - (char *)smsg->path_name); 59 - goto done; 60 - } 61 - } 62 - p = q + 1; 63 - *q = '/'; 64 - } 65 - 66 - if (!access(target_fname, F_OK)) { 67 - syslog(LOG_INFO, "File: %s exists", target_fname); 68 - if (!(smsg->copy_flags & OVER_WRITE)) { 69 - error = HV_ERROR_ALREADY_EXISTS; 70 - goto done; 71 - } 72 - } 73 - 74 - target_fd = open(target_fname, 75 - O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0744); 76 - if (target_fd == -1) { 77 - syslog(LOG_INFO, "Open Failed: %s", strerror(errno)); 78 - goto done; 79 - } 80 - 81 - error = 0; 82 - done: 83 - if (error) 84 - target_fname[0] = '\0'; 85 - return error; 86 - } 87 - 88 - static int hv_copy_data(struct hv_do_fcopy *cpmsg) 89 - { 90 - ssize_t bytes_written; 91 - int ret = 0; 92 - 93 - bytes_written = pwrite(target_fd, cpmsg->data, cpmsg->size, 94 - cpmsg->offset); 95 - 96 - filesize += cpmsg->size; 97 - if (bytes_written != cpmsg->size) { 98 - switch (errno) { 99 - case ENOSPC: 100 - ret = HV_ERROR_DISK_FULL; 101 - break; 102 - default: 103 - ret = HV_E_FAIL; 104 - break; 105 - } 106 - syslog(LOG_ERR, "pwrite failed to write %llu bytes: %ld (%s)", 107 - filesize, (long)bytes_written, strerror(errno)); 108 - } 109 - 110 - return ret; 111 - } 112 - 113 - /* 114 - * Reset target_fname to "" in the two below functions for hibernation: if 115 - * the fcopy operation is aborted by hibernation, the daemon should remove the 116 - * partially-copied file; to achieve this, the hv_utils driver always fakes a 117 - * CANCEL_FCOPY message upon suspend, and later when the VM resumes back, 118 - * the daemon calls hv_copy_cancel() to remove the file; if a file is copied 119 - * successfully before suspend, hv_copy_finished() must reset target_fname to 120 - * avoid that the file can be incorrectly removed upon resume, since the faked 121 - * CANCEL_FCOPY message is spurious in this case. 122 - */ 123 - static int hv_copy_finished(void) 124 - { 125 - close(target_fd); 126 - target_fname[0] = '\0'; 127 - return 0; 128 - } 129 - static int hv_copy_cancel(void) 130 - { 131 - close(target_fd); 132 - if (strlen(target_fname) > 0) { 133 - unlink(target_fname); 134 - target_fname[0] = '\0'; 135 - } 136 - return 0; 137 - 138 - } 139 - 140 - void print_usage(char *argv[]) 141 - { 142 - fprintf(stderr, "Usage: %s [options]\n" 143 - "Options are:\n" 144 - " -n, --no-daemon stay in foreground, don't daemonize\n" 145 - " -h, --help print this help\n", argv[0]); 146 - } 147 - 148 - int main(int argc, char *argv[]) 149 - { 150 - int fcopy_fd = -1; 151 - int error; 152 - int daemonize = 1, long_index = 0, opt; 153 - int version = FCOPY_CURRENT_VERSION; 154 - union { 155 - struct hv_fcopy_hdr hdr; 156 - struct hv_start_fcopy start; 157 - struct hv_do_fcopy copy; 158 - __u32 kernel_modver; 159 - } buffer = { }; 160 - int in_handshake; 161 - 162 - static struct option long_options[] = { 163 - {"help", no_argument, 0, 'h' }, 164 - {"no-daemon", no_argument, 0, 'n' }, 165 - {0, 0, 0, 0 } 166 - }; 167 - 168 - while ((opt = getopt_long(argc, argv, "hn", long_options, 169 - &long_index)) != -1) { 170 - switch (opt) { 171 - case 'n': 172 - daemonize = 0; 173 - break; 174 - case 'h': 175 - default: 176 - print_usage(argv); 177 - exit(EXIT_FAILURE); 178 - } 179 - } 180 - 181 - if (daemonize && daemon(1, 0)) { 182 - syslog(LOG_ERR, "daemon() failed; error: %s", strerror(errno)); 183 - exit(EXIT_FAILURE); 184 - } 185 - 186 - openlog("HV_FCOPY", 0, LOG_USER); 187 - syslog(LOG_INFO, "starting; pid is:%d", getpid()); 188 - 189 - reopen_fcopy_fd: 190 - if (fcopy_fd != -1) 191 - close(fcopy_fd); 192 - /* Remove any possible partially-copied file on error */ 193 - hv_copy_cancel(); 194 - in_handshake = 1; 195 - fcopy_fd = open("/dev/vmbus/hv_fcopy", O_RDWR); 196 - 197 - if (fcopy_fd < 0) { 198 - syslog(LOG_ERR, "open /dev/vmbus/hv_fcopy failed; error: %d %s", 199 - errno, strerror(errno)); 200 - exit(EXIT_FAILURE); 201 - } 202 - 203 - /* 204 - * Register with the kernel. 205 - */ 206 - if ((write(fcopy_fd, &version, sizeof(int))) != sizeof(int)) { 207 - syslog(LOG_ERR, "Registration failed: %s", strerror(errno)); 208 - exit(EXIT_FAILURE); 209 - } 210 - 211 - while (1) { 212 - /* 213 - * In this loop we process fcopy messages after the 214 - * handshake is complete. 215 - */ 216 - ssize_t len; 217 - 218 - len = pread(fcopy_fd, &buffer, sizeof(buffer), 0); 219 - if (len < 0) { 220 - syslog(LOG_ERR, "pread failed: %s", strerror(errno)); 221 - goto reopen_fcopy_fd; 222 - } 223 - 224 - if (in_handshake) { 225 - if (len != sizeof(buffer.kernel_modver)) { 226 - syslog(LOG_ERR, "invalid version negotiation"); 227 - exit(EXIT_FAILURE); 228 - } 229 - in_handshake = 0; 230 - syslog(LOG_INFO, "kernel module version: %u", 231 - buffer.kernel_modver); 232 - continue; 233 - } 234 - 235 - switch (buffer.hdr.operation) { 236 - case START_FILE_COPY: 237 - error = hv_start_fcopy(&buffer.start); 238 - break; 239 - case WRITE_TO_FILE: 240 - error = hv_copy_data(&buffer.copy); 241 - break; 242 - case COMPLETE_FCOPY: 243 - error = hv_copy_finished(); 244 - break; 245 - case CANCEL_FCOPY: 246 - error = hv_copy_cancel(); 247 - break; 248 - 249 - default: 250 - error = HV_E_FAIL; 251 - syslog(LOG_ERR, "Unknown operation: %d", 252 - buffer.hdr.operation); 253 - 254 - } 255 - 256 - /* 257 - * pwrite() may return an error due to the faked CANCEL_FCOPY 258 - * message upon hibernation. Ignore the error by resetting the 259 - * dev file, i.e. closing and re-opening it. 260 - */ 261 - if (pwrite(fcopy_fd, &error, sizeof(int), 0) != sizeof(int)) { 262 - syslog(LOG_ERR, "pwrite failed: %s", strerror(errno)); 263 - goto reopen_fcopy_fd; 264 - } 265 - } 266 - }