From 2273a54793ea89e957a527375d8338a4ea6328ec2486a6ee251fc97960baf8b9 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Thu, 23 Jan 2014 16:05:49 +0000 Subject: [PATCH 1/4] - Start daemons on demand via udev rules because the guest services are optional. - If systemd is used daemons live in libdir, they are not usercallable apps - Add hv_fcopy_daemon for post 13.1 releases (fate#315887) OBS-URL: https://build.opensuse.org/package/show/Virtualization/hyper-v?expand=0&rev=82 --- hyper-v.changes | 12 ++ hyper-v.include.linux.hyperv.h | 47 +++++++ hyper-v.spec | 89 ++++++++++--- hyper-v.tools.hv.hv_fcopy_daemon.c | 200 +++++++++++++++++++++++++++++ 4 files changed, 328 insertions(+), 20 deletions(-) create mode 100644 hyper-v.tools.hv.hv_fcopy_daemon.c diff --git a/hyper-v.changes b/hyper-v.changes index 9ca2ea8..38aa81f 100644 --- a/hyper-v.changes +++ b/hyper-v.changes @@ -1,3 +1,15 @@ +------------------------------------------------------------------- +Thu Jan 23 17:00:54 CET 2014 - ohering@suse.de + +- Start daemons on demand via udev rules because the guest services + are optional. +- If systemd is used daemons live in libdir, they are not usercallable apps + +------------------------------------------------------------------- +Thu Jan 16 11:09:34 CET 2014 - ohering@suse.de + +- Add hv_fcopy_daemon for post 13.1 releases (fate#315887) + ------------------------------------------------------------------- Wed Dec 18 14:46:37 CET 2013 - ohering@suse.de diff --git a/hyper-v.include.linux.hyperv.h b/hyper-v.include.linux.hyperv.h index d120550..6e66087 100644 --- a/hyper-v.include.linux.hyperv.h +++ b/hyper-v.include.linux.hyperv.h @@ -26,6 +26,7 @@ #define _HYPERV_H #include +#include /* @@ -84,6 +85,52 @@ struct hv_vss_msg { }; } __attribute__((packed)); + +/* + * Implementation of a host to guest copy facility. + */ + +#define FCOPY_VERSION_0 0 +#define FCOPY_CURRENT_VERSION FCOPY_VERSION_0 +#define W_MAX_PATH 260 + +enum hv_fcopy_op { + START_FILE_COPY = 0, + WRITE_TO_FILE, + COMPLETE_FCOPY, + CANCEL_FCOPY, +}; + +struct hv_fcopy_hdr { + __u32 operation; + uuid_le service_id0; /* currently unused */ + uuid_le service_id1; /* currently unused */ +} __attribute__((packed)); + +#define OVER_WRITE 0x1 +#define CREATE_PATH 0x2 + +struct hv_start_fcopy { + struct hv_fcopy_hdr hdr; + __u16 file_name[W_MAX_PATH]; + __u16 path_name[W_MAX_PATH]; + __u32 copy_flags; + __u64 file_size; +} __attribute__((packed)); + +/* + * The file is chunked into fragments. + */ +#define DATA_FRAGMENT (6 * 1024) + +struct hv_do_fcopy { + struct hv_fcopy_hdr hdr; + __u64 offset; + __u32 size; + __u8 data[DATA_FRAGMENT]; +}; + + /* * An implementation of HyperV key value pair (KVP) functionality for Linux. * diff --git a/hyper-v.spec b/hyper-v.spec index d98e002..70af620 100644 --- a/hyper-v.spec +++ b/hyper-v.spec @@ -1,7 +1,7 @@ # # spec file for package hyper-v # -# Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,6 +18,7 @@ %define hv_kvp_daemon hv_kvp_daemon %define hv_vss_daemon hv_vss_daemon +%define hv_fcopy_daemon hv_fcopy_daemon %define helper_dir /usr/lib/%{name} Name: hyper-v @@ -50,6 +51,7 @@ Source10: hyper-v.tools.hv.hv_kvp_daemon.c Source11: hyper-v.init.sh Source12: hyper-v.tools.hv.hv_vss_daemon.c Source13: hyper-v.init.vss.sh +Source14: hyper-v.tools.hv.hv_fcopy_daemon.c Source20: hyper-v.tools.hv.hv_get_dhcp_info.sh Source21: hyper-v.tools.hv.hv_get_dns_info.sh Source22: hyper-v.tools.hv.hv_set_ifconfig.sh @@ -65,10 +67,12 @@ cp -avL %{S:5} kvptest.ps1.txt cp -vL %{S:9} %{hv_kvp_daemon}.h cp -vL %{S:10} %{hv_kvp_daemon}.c cp -vL %{S:12} %{hv_vss_daemon}.c +cp -vL %{S:14} %{hv_fcopy_daemon}.c %build sed -i~ '/#include /d' %{hv_kvp_daemon}.c sed -i~ '/#include /d' %{hv_vss_daemon}.c +sed -i~ '/#include /d' %{hv_fcopy_daemon}.c gcc \ $RPM_OPT_FLAGS \ -Wno-unused-variable \ @@ -91,12 +95,28 @@ gcc \ -DCN_VSS_IDX=0xa \ -DCN_VSS_VAL=0x1 \ -o %{hv_vss_daemon} +gcc \ + $RPM_OPT_FLAGS \ + -Wno-unused-variable \ + -Wno-pointer-sign \ + -D_GNU_SOURCE \ + -g \ + %{hv_fcopy_daemon}.c \ + -include %{hv_kvp_daemon}.h \ + -o %{hv_fcopy_daemon} %install -mkdir -p $RPM_BUILD_ROOT/usr/sbin -install -m755 %{hv_kvp_daemon} $RPM_BUILD_ROOT/usr/sbin -install -m755 %{hv_vss_daemon} $RPM_BUILD_ROOT/usr/sbin +%if %{use_systemd} +# It is not a callable app anyway, so move it out of the way +bindir=%{helper_dir}/bin +%else +bindir=/usr/sbin +%endif +mkdir -p $RPM_BUILD_ROOT${bindir} mkdir -p $RPM_BUILD_ROOT%{helper_dir}/bin +install -m755 %{hv_kvp_daemon} $RPM_BUILD_ROOT${bindir} +install -m755 %{hv_vss_daemon} $RPM_BUILD_ROOT${bindir} +install -m755 %{hv_fcopy_daemon} $RPM_BUILD_ROOT${bindir} cp -avL %{S:20} $RPM_BUILD_ROOT%{helper_dir}/bin/hv_get_dhcp_info cp -avL %{S:21} $RPM_BUILD_ROOT%{helper_dir}/bin/hv_get_dns_info cp -avL %{S:22} $RPM_BUILD_ROOT%{helper_dir}/bin/hv_set_ifconfig @@ -105,18 +125,19 @@ chmod 755 $RPM_BUILD_ROOT%{helper_dir}/bin/* d=$RPM_BUILD_ROOT%{_unitdir} mkdir -vp ${d} # -cat > ${d}/%{hv_kvp_daemon}.service <<'EOF' +cat > ${d}/%{hv_kvp_daemon}.service < ${d}/%{hv_vss_daemon}.service <<'EOF' +cat > ${d}/%{hv_vss_daemon}.service < ${d}/%{hv_fcopy_daemon}.service < ${d}/%{hv_kvp_daemon}.rules < ${d}/%{hv_vss_daemon}.rules < ${d}/%{hv_fcopy_daemon}.rules < + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int target_fd; +static char target_fname[W_MAX_PATH]; + +static int hv_start_fcopy(struct hv_start_fcopy *smsg) +{ + int error = HV_E_FAIL; + char *q, *p; + + /* + * If possile append a path seperator to the path. + */ + if (strlen((char *)smsg->path_name) < (W_MAX_PATH - 2)) + strcat((char *)smsg->path_name, "/"); + + p = (char *)smsg->path_name; + snprintf(target_fname, sizeof(target_fname), "%s/%s", + (char *)smsg->path_name, 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) + goto done; + } + + target_fd = open(target_fname, O_RDWR | O_CREAT | O_CLOEXEC, 0744); + if (target_fd == -1) { + syslog(LOG_INFO, "Open Failed: %s", strerror(errno)); + goto done; + } + + error = 0; +done: + return error; +} + +static int hv_copy_data(struct hv_do_fcopy *cpmsg) +{ + ssize_t bytes_written; + + bytes_written = pwrite(target_fd, cpmsg->data, cpmsg->size, + cpmsg->offset); + + if (bytes_written != cpmsg->size) + return HV_E_FAIL; + + return 0; +} + +static int hv_copy_finished(void) +{ + close(target_fd); + return 0; +} +static int hv_copy_cancel(void) +{ + close(target_fd); + unlink(target_fname); + return 0; + +} + +int main(void) +{ + int fd, fcopy_fd, len; + int error = 0; + int version = FCOPY_CURRENT_VERSION; + char *buffer[4096 * 2]; + struct hv_fcopy_hdr *in_msg; + + if (daemon(1, 0)) { + syslog(LOG_ERR, "daemon() failed; error: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + openlog("HV_FCOPY", 0, LOG_USER); + syslog(LOG_INFO, "HV_FCOPY starting; pid is:%d", getpid()); + + fcopy_fd = open("/dev/hv_fcopy", O_RDWR); + + if (fcopy_fd < 0) { + syslog(LOG_ERR, "open /dev/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) { + if (!error) { + syslog(LOG_ERR, "Read error: %s", + strerror(errno)); + error = HV_E_FAIL; + } + 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); + } + } +} From 13b3a21a905f88493a83fdede90f12f537a1a96891708e726d7d0db8b49e33a9 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Thu, 23 Jan 2014 16:37:21 +0000 Subject: [PATCH 2/4] hv_fcopy_daemon needs uuid.h, work around sles11 failure OBS-URL: https://build.opensuse.org/package/show/Virtualization/hyper-v?expand=0&rev=83 --- hyper-v.spec | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hyper-v.spec b/hyper-v.spec index 70af620..f6d5deb 100644 --- a/hyper-v.spec +++ b/hyper-v.spec @@ -95,6 +95,7 @@ gcc \ -DCN_VSS_IDX=0xa \ -DCN_VSS_VAL=0x1 \ -o %{hv_vss_daemon} +%if %{use_systemd} gcc \ $RPM_OPT_FLAGS \ -Wno-unused-variable \ @@ -104,6 +105,7 @@ gcc \ %{hv_fcopy_daemon}.c \ -include %{hv_kvp_daemon}.h \ -o %{hv_fcopy_daemon} +%endif %install %if %{use_systemd} @@ -116,7 +118,9 @@ mkdir -p $RPM_BUILD_ROOT${bindir} mkdir -p $RPM_BUILD_ROOT%{helper_dir}/bin install -m755 %{hv_kvp_daemon} $RPM_BUILD_ROOT${bindir} install -m755 %{hv_vss_daemon} $RPM_BUILD_ROOT${bindir} +%if %{use_systemd} install -m755 %{hv_fcopy_daemon} $RPM_BUILD_ROOT${bindir} +%endif cp -avL %{S:20} $RPM_BUILD_ROOT%{helper_dir}/bin/hv_get_dhcp_info cp -avL %{S:21} $RPM_BUILD_ROOT%{helper_dir}/bin/hv_get_dns_info cp -avL %{S:22} $RPM_BUILD_ROOT%{helper_dir}/bin/hv_set_ifconfig From 94c31de49b9c668375e250109813e64f1244d396b2f28383e9066de965e1859f Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Thu, 23 Jan 2014 16:45:34 +0000 Subject: [PATCH 3/4] provide private uuid_le type to fix sles11 build OBS-URL: https://build.opensuse.org/package/show/Virtualization/hyper-v?expand=0&rev=84 --- hyper-v.include.linux.hyperv.h | 5 ++++- hyper-v.spec | 4 ---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/hyper-v.include.linux.hyperv.h b/hyper-v.include.linux.hyperv.h index 6e66087..16ffdca 100644 --- a/hyper-v.include.linux.hyperv.h +++ b/hyper-v.include.linux.hyperv.h @@ -26,7 +26,10 @@ #define _HYPERV_H #include -#include +/* from linux/uuid.h */ +typedef struct { + __u8 b[16]; +} uuid_le; /* diff --git a/hyper-v.spec b/hyper-v.spec index f6d5deb..70af620 100644 --- a/hyper-v.spec +++ b/hyper-v.spec @@ -95,7 +95,6 @@ gcc \ -DCN_VSS_IDX=0xa \ -DCN_VSS_VAL=0x1 \ -o %{hv_vss_daemon} -%if %{use_systemd} gcc \ $RPM_OPT_FLAGS \ -Wno-unused-variable \ @@ -105,7 +104,6 @@ gcc \ %{hv_fcopy_daemon}.c \ -include %{hv_kvp_daemon}.h \ -o %{hv_fcopy_daemon} -%endif %install %if %{use_systemd} @@ -118,9 +116,7 @@ mkdir -p $RPM_BUILD_ROOT${bindir} mkdir -p $RPM_BUILD_ROOT%{helper_dir}/bin install -m755 %{hv_kvp_daemon} $RPM_BUILD_ROOT${bindir} install -m755 %{hv_vss_daemon} $RPM_BUILD_ROOT${bindir} -%if %{use_systemd} install -m755 %{hv_fcopy_daemon} $RPM_BUILD_ROOT${bindir} -%endif cp -avL %{S:20} $RPM_BUILD_ROOT%{helper_dir}/bin/hv_get_dhcp_info cp -avL %{S:21} $RPM_BUILD_ROOT%{helper_dir}/bin/hv_get_dns_info cp -avL %{S:22} $RPM_BUILD_ROOT%{helper_dir}/bin/hv_set_ifconfig From e057412d0a249e1d07769c019c1cd53ee6df28175364e3eeb5e931caaffcc424 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Mon, 27 Jan 2014 14:44:11 +0000 Subject: [PATCH 4/4] hyper-v.tools.hv.hv_fcopy_daemon.c OBS-URL: https://build.opensuse.org/package/show/Virtualization/hyper-v?expand=0&rev=85 --- hyper-v.changes | 1 + 1 file changed, 1 insertion(+) diff --git a/hyper-v.changes b/hyper-v.changes index 38aa81f..0a0f2a7 100644 --- a/hyper-v.changes +++ b/hyper-v.changes @@ -9,6 +9,7 @@ Thu Jan 23 17:00:54 CET 2014 - ohering@suse.de Thu Jan 16 11:09:34 CET 2014 - ohering@suse.de - Add hv_fcopy_daemon for post 13.1 releases (fate#315887) + hyper-v.tools.hv.hv_fcopy_daemon.c ------------------------------------------------------------------- Wed Dec 18 14:46:37 CET 2013 - ohering@suse.de