cregit-Linux how code gets into the kernel

Release 4.7 tools/hv/hv_fcopy_daemon.c

Directory: tools/hv
/*
 * An implementation of host to guest copy functionality for Linux.
 *
 * Copyright (C) 2014, Microsoft, Inc.
 *
 * Author : K. Y. Srinivasan <kys@microsoft.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published
 * by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
 * NON INFRINGEMENT.  See the GNU General Public License for more
 * details.
 */


#include <sys/types.h>
#include <sys/socket.h>
#include <sys/poll.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <linux/hyperv.h>
#include <syslog.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <getopt.h>


static int target_fd;

static char target_fname[W_MAX_PATH];

static unsigned long long filesize;


static int hv_start_fcopy(struct hv_start_fcopy *smsg) { int error = HV_E_FAIL; char *q, *p; filesize = 0; p = (char *)smsg->path_name; snprintf(target_fname, sizeof(target_fname), "%s/%s", (char *)smsg->path_name, (char *)smsg->file_name); syslog(LOG_INFO, "Target file name: %s", target_fname); /* * Check to see if the path is already in place; if not, * create if required. */ while ((q = strchr(p, '/')) != NULL) { if (q == p) { p++; continue; } *q = '\0'; if (access((char *)smsg->path_name, F_OK)) { if (smsg->copy_flags & CREATE_PATH) { if (mkdir((char *)smsg->path_name, 0755)) { syslog(LOG_ERR, "Failed to create %s", (char *)smsg->path_name); goto done; } } else { syslog(LOG_ERR, "Invalid path: %s", (char *)smsg->path_name); goto done; } } p = q + 1; *q = '/'; } if (!access(target_fname, F_OK)) { syslog(LOG_INFO, "File: %s exists", target_fname); if (!(smsg->copy_flags & OVER_WRITE)) { error = HV_ERROR_ALREADY_EXISTS; goto done; } } target_fd = open(target_fname, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0744); if (target_fd == -1) { syslog(LOG_INFO, "Open Failed: %s", strerror(errno)); goto done; } error = 0; done: return error; }

Contributors

PersonTokensPropCommitsCommitProp
ky srinivasanky srinivasan28496.60%240.00%
vitaly kuznetsovvitaly kuznetsov41.36%120.00%
olaf heringolaf hering41.36%120.00%
yue zhangyue zhang20.68%120.00%
Total294100.00%5100.00%


static int hv_copy_data(struct hv_do_fcopy *cpmsg) { ssize_t bytes_written; int ret = 0; bytes_written = pwrite(target_fd, cpmsg->data, cpmsg->size, cpmsg->offset); filesize += cpmsg->size; if (bytes_written != cpmsg->size) { switch (errno) { case ENOSPC: ret = HV_ERROR_DISK_FULL; break; default: ret = HV_E_FAIL; break; } syslog(LOG_ERR, "pwrite failed to write %llu bytes: %ld (%s)", filesize, (long)bytes_written, strerror(errno)); } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
olaf heringolaf hering5254.17%150.00%
ky srinivasanky srinivasan4445.83%150.00%
Total96100.00%2100.00%


static int hv_copy_finished(void) { close(target_fd); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
ky srinivasanky srinivasan16100.00%1100.00%
Total16100.00%1100.00%


static int hv_copy_cancel(void) { close(target_fd); unlink(target_fname); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
ky srinivasanky srinivasan21100.00%1100.00%
Total21100.00%1100.00%


void print_usage(char *argv[]) { fprintf(stderr, "Usage: %s [options]\n" "Options are:\n" " -n, --no-daemon stay in foreground, don't daemonize\n" " -h, --help print this help\n", argv[0]); }

Contributors

PersonTokensPropCommitsCommitProp
vitaly kuznetsovvitaly kuznetsov25100.00%1100.00%
Total25100.00%1100.00%


int main(int argc, char *argv[]) { int fcopy_fd, len; int error; int daemonize = 1, long_index = 0, opt; int version = FCOPY_CURRENT_VERSION; char *buffer[4096 * 2]; struct hv_fcopy_hdr *in_msg; int in_handshake = 1; __u32 kernel_modver; static struct option long_options[] = { {"help", no_argument, 0, 'h' }, {"no-daemon", no_argument, 0, 'n' }, {0, 0, 0, 0 } }; while ((opt = getopt_long(argc, argv, "hn", long_options, &long_index)) != -1) { switch (opt) { case 'n': daemonize = 0; break; case 'h': default: print_usage(argv); exit(EXIT_FAILURE); } } if (daemonize && daemon(1, 0)) { syslog(LOG_ERR, "daemon() failed; error: %s", strerror(errno)); exit(EXIT_FAILURE); } openlog("HV_FCOPY", 0, LOG_USER); syslog(LOG_INFO, "starting; pid is:%d", getpid()); fcopy_fd = open("/dev/vmbus/hv_fcopy", O_RDWR); if (fcopy_fd < 0) { syslog(LOG_ERR, "open /dev/vmbus/hv_fcopy failed; error: %d %s", errno, strerror(errno)); exit(EXIT_FAILURE); } /* * Register with the kernel. */ if ((write(fcopy_fd, &version, sizeof(int))) != sizeof(int)) { syslog(LOG_ERR, "Registration failed: %s", strerror(errno)); exit(EXIT_FAILURE); } while (1) { /* * In this loop we process fcopy messages after the * handshake is complete. */ len = pread(fcopy_fd, buffer, (4096 * 2), 0); if (len < 0) { syslog(LOG_ERR, "pread failed: %s", strerror(errno)); exit(EXIT_FAILURE); } if (in_handshake) { if (len != sizeof(kernel_modver)) { syslog(LOG_ERR, "invalid version negotiation"); exit(EXIT_FAILURE); } kernel_modver = *(__u32 *)buffer; in_handshake = 0; syslog(LOG_INFO, "kernel module version: %d", kernel_modver); continue; } in_msg = (struct hv_fcopy_hdr *)buffer; switch (in_msg->operation) { case START_FILE_COPY: error = hv_start_fcopy((struct hv_start_fcopy *)in_msg); break; case WRITE_TO_FILE: error = hv_copy_data((struct hv_do_fcopy *)in_msg); break; case COMPLETE_FCOPY: error = hv_copy_finished(); break; case CANCEL_FCOPY: error = hv_copy_cancel(); break; default: syslog(LOG_ERR, "Unknown operation: %d", in_msg->operation); } if (pwrite(fcopy_fd, &error, sizeof(int), 0) != sizeof(int)) { syslog(LOG_ERR, "pwrite failed: %s", strerror(errno)); exit(EXIT_FAILURE); } } }

Contributors

PersonTokensPropCommitsCommitProp
ky srinivasanky srinivasan32665.46%125.00%
vitaly kuznetsovvitaly kuznetsov17034.14%250.00%
olaf heringolaf hering20.40%125.00%
Total498100.00%4100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
ky srinivasanky srinivasan75173.70%225.00%
vitaly kuznetsovvitaly kuznetsov20219.82%337.50%
olaf heringolaf hering646.28%225.00%
yue zhangyue zhang20.20%112.50%
Total1019100.00%8100.00%
Directory: tools/hv
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}