^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * An implementation of host to guest copy functionality for Linux.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2014, Microsoft, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Author : K. Y. Srinivasan <kys@microsoft.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <sys/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/hyperv.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/limits.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <syslog.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <sys/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <getopt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static int target_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static char target_fname[PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static unsigned long long filesize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static int hv_start_fcopy(struct hv_start_fcopy *smsg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) int error = HV_E_FAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) char *q, *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) filesize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) p = (char *)smsg->path_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) snprintf(target_fname, sizeof(target_fname), "%s/%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) (char *)smsg->path_name, (char *)smsg->file_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) syslog(LOG_INFO, "Target file name: %s", target_fname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * Check to see if the path is already in place; if not,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * create if required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) while ((q = strchr(p, '/')) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if (q == p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) p++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) *q = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) if (access((char *)smsg->path_name, F_OK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if (smsg->copy_flags & CREATE_PATH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (mkdir((char *)smsg->path_name, 0755)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) syslog(LOG_ERR, "Failed to create %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) (char *)smsg->path_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) syslog(LOG_ERR, "Invalid path: %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) (char *)smsg->path_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) p = q + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) *q = '/';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (!access(target_fname, F_OK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) syslog(LOG_INFO, "File: %s exists", target_fname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (!(smsg->copy_flags & OVER_WRITE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) error = HV_ERROR_ALREADY_EXISTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) target_fd = open(target_fname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0744);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (target_fd == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) syslog(LOG_INFO, "Open Failed: %s", strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) target_fname[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static int hv_copy_data(struct hv_do_fcopy *cpmsg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) ssize_t bytes_written;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) bytes_written = pwrite(target_fd, cpmsg->data, cpmsg->size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) cpmsg->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) filesize += cpmsg->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (bytes_written != cpmsg->size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) switch (errno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) case ENOSPC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) ret = HV_ERROR_DISK_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) ret = HV_E_FAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) syslog(LOG_ERR, "pwrite failed to write %llu bytes: %ld (%s)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) filesize, (long)bytes_written, strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * Reset target_fname to "" in the two below functions for hibernation: if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * the fcopy operation is aborted by hibernation, the daemon should remove the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * partially-copied file; to achieve this, the hv_utils driver always fakes a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * CANCEL_FCOPY message upon suspend, and later when the VM resumes back,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * the daemon calls hv_copy_cancel() to remove the file; if a file is copied
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * successfully before suspend, hv_copy_finished() must reset target_fname to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * avoid that the file can be incorrectly removed upon resume, since the faked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * CANCEL_FCOPY message is spurious in this case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static int hv_copy_finished(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) close(target_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) target_fname[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static int hv_copy_cancel(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) close(target_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (strlen(target_fname) > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) unlink(target_fname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) target_fname[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) void print_usage(char *argv[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) fprintf(stderr, "Usage: %s [options]\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) "Options are:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) " -n, --no-daemon stay in foreground, don't daemonize\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) " -h, --help print this help\n", argv[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) int main(int argc, char *argv[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) int fcopy_fd = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) int daemonize = 1, long_index = 0, opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) int version = FCOPY_CURRENT_VERSION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct hv_fcopy_hdr hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct hv_start_fcopy start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct hv_do_fcopy copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) __u32 kernel_modver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) } buffer = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) int in_handshake;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) static struct option long_options[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {"help", no_argument, 0, 'h' },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {"no-daemon", no_argument, 0, 'n' },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {0, 0, 0, 0 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) while ((opt = getopt_long(argc, argv, "hn", long_options,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) &long_index)) != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) switch (opt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) case 'n':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) daemonize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) case 'h':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) print_usage(argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (daemonize && daemon(1, 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) syslog(LOG_ERR, "daemon() failed; error: %s", strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) openlog("HV_FCOPY", 0, LOG_USER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) syslog(LOG_INFO, "starting; pid is:%d", getpid());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) reopen_fcopy_fd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (fcopy_fd != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) close(fcopy_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /* Remove any possible partially-copied file on error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) hv_copy_cancel();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) in_handshake = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) fcopy_fd = open("/dev/vmbus/hv_fcopy", O_RDWR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (fcopy_fd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) syslog(LOG_ERR, "open /dev/vmbus/hv_fcopy failed; error: %d %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) errno, strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * Register with the kernel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if ((write(fcopy_fd, &version, sizeof(int))) != sizeof(int)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) syslog(LOG_ERR, "Registration failed: %s", strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * In this loop we process fcopy messages after the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * handshake is complete.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) ssize_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) len = pread(fcopy_fd, &buffer, sizeof(buffer), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (len < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) syslog(LOG_ERR, "pread failed: %s", strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) goto reopen_fcopy_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (in_handshake) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (len != sizeof(buffer.kernel_modver)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) syslog(LOG_ERR, "invalid version negotiation");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) in_handshake = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) syslog(LOG_INFO, "kernel module version: %u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) buffer.kernel_modver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) switch (buffer.hdr.operation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) case START_FILE_COPY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) error = hv_start_fcopy(&buffer.start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) case WRITE_TO_FILE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) error = hv_copy_data(&buffer.copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) case COMPLETE_FCOPY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) error = hv_copy_finished();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) case CANCEL_FCOPY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) error = hv_copy_cancel();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) error = HV_E_FAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) syslog(LOG_ERR, "Unknown operation: %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) buffer.hdr.operation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * pwrite() may return an error due to the faked CANCEL_FCOPY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * message upon hibernation. Ignore the error by resetting the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * dev file, i.e. closing and re-opening it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (pwrite(fcopy_fd, &error, sizeof(int), 0) != sizeof(int)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) syslog(LOG_ERR, "pwrite failed: %s", strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) goto reopen_fcopy_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }