diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2014-06-08 02:24:07 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2014-06-08 02:24:07 -0400 |
commit | a292241cccb7e20e8b997a9a44177e7c98141859 (patch) | |
tree | a0b0bb95e7dce3233a2d8b203f9e326cdec7a00e /tools/hv | |
parent | d49cb7aeebb974713f9f7ab2991352d3050b095b (diff) | |
parent | 68807a0c2015cb40df4869e16651f0ce5cc14d52 (diff) |
Merge branch 'next' into for-linus
Prepare input updates for 3.16.
Diffstat (limited to 'tools/hv')
-rw-r--r-- | tools/hv/Makefile | 13 | ||||
-rw-r--r-- | tools/hv/hv_fcopy_daemon.c | 197 | ||||
-rw-r--r-- | tools/hv/hv_vss_daemon.c | 2 |
3 files changed, 212 insertions, 0 deletions
diff --git a/tools/hv/Makefile b/tools/hv/Makefile new file mode 100644 index 000000000000..bd22f786a60c --- /dev/null +++ b/tools/hv/Makefile | |||
@@ -0,0 +1,13 @@ | |||
1 | # Makefile for Hyper-V tools | ||
2 | |||
3 | CC = $(CROSS_COMPILE)gcc | ||
4 | PTHREAD_LIBS = -lpthread | ||
5 | WARNINGS = -Wall -Wextra | ||
6 | CFLAGS = $(WARNINGS) -g $(PTHREAD_LIBS) | ||
7 | |||
8 | all: hv_kvp_daemon hv_vss_daemon | ||
9 | %: %.c | ||
10 | $(CC) $(CFLAGS) -o $@ $^ | ||
11 | |||
12 | clean: | ||
13 | $(RM) hv_kvp_daemon hv_vss_daemon | ||
diff --git a/tools/hv/hv_fcopy_daemon.c b/tools/hv/hv_fcopy_daemon.c new file mode 100644 index 000000000000..fba1c75aa484 --- /dev/null +++ b/tools/hv/hv_fcopy_daemon.c | |||
@@ -0,0 +1,197 @@ | |||
1 | /* | ||
2 | * An implementation of host to guest copy functionality for Linux. | ||
3 | * | ||
4 | * Copyright (C) 2014, Microsoft, Inc. | ||
5 | * | ||
6 | * Author : K. Y. Srinivasan <kys@microsoft.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License version 2 as published | ||
10 | * by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
15 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
16 | * details. | ||
17 | */ | ||
18 | |||
19 | |||
20 | #include <sys/types.h> | ||
21 | #include <sys/socket.h> | ||
22 | #include <sys/poll.h> | ||
23 | #include <linux/types.h> | ||
24 | #include <linux/kdev_t.h> | ||
25 | #include <stdio.h> | ||
26 | #include <stdlib.h> | ||
27 | #include <unistd.h> | ||
28 | #include <string.h> | ||
29 | #include <ctype.h> | ||
30 | #include <errno.h> | ||
31 | #include <linux/hyperv.h> | ||
32 | #include <syslog.h> | ||
33 | #include <sys/stat.h> | ||
34 | #include <fcntl.h> | ||
35 | #include <dirent.h> | ||
36 | |||
37 | static int target_fd; | ||
38 | static char target_fname[W_MAX_PATH]; | ||
39 | |||
40 | static int hv_start_fcopy(struct hv_start_fcopy *smsg) | ||
41 | { | ||
42 | int error = HV_E_FAIL; | ||
43 | char *q, *p; | ||
44 | |||
45 | /* | ||
46 | * If possile append a path seperator to the path. | ||
47 | */ | ||
48 | if (strlen((char *)smsg->path_name) < (W_MAX_PATH - 2)) | ||
49 | strcat((char *)smsg->path_name, "/"); | ||
50 | |||
51 | p = (char *)smsg->path_name; | ||
52 | snprintf(target_fname, sizeof(target_fname), "%s/%s", | ||
53 | (char *)smsg->path_name, smsg->file_name); | ||
54 | |||
55 | syslog(LOG_INFO, "Target file name: %s", target_fname); | ||
56 | /* | ||
57 | * Check to see if the path is already in place; if not, | ||
58 | * create if required. | ||
59 | */ | ||
60 | while ((q = strchr(p, '/')) != NULL) { | ||
61 | if (q == p) { | ||
62 | p++; | ||
63 | continue; | ||
64 | } | ||
65 | *q = '\0'; | ||
66 | if (access((char *)smsg->path_name, F_OK)) { | ||
67 | if (smsg->copy_flags & CREATE_PATH) { | ||
68 | if (mkdir((char *)smsg->path_name, 0755)) { | ||
69 | syslog(LOG_ERR, "Failed to create %s", | ||
70 | (char *)smsg->path_name); | ||
71 | goto done; | ||
72 | } | ||
73 | } else { | ||
74 | syslog(LOG_ERR, "Invalid path: %s", | ||
75 | (char *)smsg->path_name); | ||
76 | goto done; | ||
77 | } | ||
78 | } | ||
79 | p = q + 1; | ||
80 | *q = '/'; | ||
81 | } | ||
82 | |||
83 | if (!access(target_fname, F_OK)) { | ||
84 | syslog(LOG_INFO, "File: %s exists", target_fname); | ||
85 | if (!(smsg->copy_flags & OVER_WRITE)) { | ||
86 | error = HV_ERROR_ALREADY_EXISTS; | ||
87 | goto done; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | target_fd = open(target_fname, O_RDWR | O_CREAT | O_CLOEXEC, 0744); | ||
92 | if (target_fd == -1) { | ||
93 | syslog(LOG_INFO, "Open Failed: %s", strerror(errno)); | ||
94 | goto done; | ||
95 | } | ||
96 | |||
97 | error = 0; | ||
98 | done: | ||
99 | return error; | ||
100 | } | ||
101 | |||
102 | static int hv_copy_data(struct hv_do_fcopy *cpmsg) | ||
103 | { | ||
104 | ssize_t bytes_written; | ||
105 | |||
106 | bytes_written = pwrite(target_fd, cpmsg->data, cpmsg->size, | ||
107 | cpmsg->offset); | ||
108 | |||
109 | if (bytes_written != cpmsg->size) | ||
110 | return HV_E_FAIL; | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static int hv_copy_finished(void) | ||
116 | { | ||
117 | close(target_fd); | ||
118 | return 0; | ||
119 | } | ||
120 | static int hv_copy_cancel(void) | ||
121 | { | ||
122 | close(target_fd); | ||
123 | unlink(target_fname); | ||
124 | return 0; | ||
125 | |||
126 | } | ||
127 | |||
128 | int main(void) | ||
129 | { | ||
130 | int fd, fcopy_fd, len; | ||
131 | int error; | ||
132 | int version = FCOPY_CURRENT_VERSION; | ||
133 | char *buffer[4096 * 2]; | ||
134 | struct hv_fcopy_hdr *in_msg; | ||
135 | |||
136 | if (daemon(1, 0)) { | ||
137 | syslog(LOG_ERR, "daemon() failed; error: %s", strerror(errno)); | ||
138 | exit(EXIT_FAILURE); | ||
139 | } | ||
140 | |||
141 | openlog("HV_FCOPY", 0, LOG_USER); | ||
142 | syslog(LOG_INFO, "HV_FCOPY starting; pid is:%d", getpid()); | ||
143 | |||
144 | fcopy_fd = open("/dev/vmbus/hv_fcopy", O_RDWR); | ||
145 | |||
146 | if (fcopy_fd < 0) { | ||
147 | syslog(LOG_ERR, "open /dev/vmbus/hv_fcopy failed; error: %d %s", | ||
148 | errno, strerror(errno)); | ||
149 | exit(EXIT_FAILURE); | ||
150 | } | ||
151 | |||
152 | /* | ||
153 | * Register with the kernel. | ||
154 | */ | ||
155 | if ((write(fcopy_fd, &version, sizeof(int))) != sizeof(int)) { | ||
156 | syslog(LOG_ERR, "Registration failed: %s", strerror(errno)); | ||
157 | exit(EXIT_FAILURE); | ||
158 | } | ||
159 | |||
160 | while (1) { | ||
161 | /* | ||
162 | * In this loop we process fcopy messages after the | ||
163 | * handshake is complete. | ||
164 | */ | ||
165 | len = pread(fcopy_fd, buffer, (4096 * 2), 0); | ||
166 | if (len < 0) { | ||
167 | syslog(LOG_ERR, "pread failed: %s", strerror(errno)); | ||
168 | exit(EXIT_FAILURE); | ||
169 | } | ||
170 | in_msg = (struct hv_fcopy_hdr *)buffer; | ||
171 | |||
172 | switch (in_msg->operation) { | ||
173 | case START_FILE_COPY: | ||
174 | error = hv_start_fcopy((struct hv_start_fcopy *)in_msg); | ||
175 | break; | ||
176 | case WRITE_TO_FILE: | ||
177 | error = hv_copy_data((struct hv_do_fcopy *)in_msg); | ||
178 | break; | ||
179 | case COMPLETE_FCOPY: | ||
180 | error = hv_copy_finished(); | ||
181 | break; | ||
182 | case CANCEL_FCOPY: | ||
183 | error = hv_copy_cancel(); | ||
184 | break; | ||
185 | |||
186 | default: | ||
187 | syslog(LOG_ERR, "Unknown operation: %d", | ||
188 | in_msg->operation); | ||
189 | |||
190 | } | ||
191 | |||
192 | if (pwrite(fcopy_fd, &error, sizeof(int), 0) != sizeof(int)) { | ||
193 | syslog(LOG_ERR, "pwrite failed: %s", strerror(errno)); | ||
194 | exit(EXIT_FAILURE); | ||
195 | } | ||
196 | } | ||
197 | } | ||
diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c index 520de3304571..6a213b8cd7b9 100644 --- a/tools/hv/hv_vss_daemon.c +++ b/tools/hv/hv_vss_daemon.c | |||
@@ -87,6 +87,8 @@ static int vss_operate(int operation) | |||
87 | continue; | 87 | continue; |
88 | if (strcmp(ent->mnt_type, "iso9660") == 0) | 88 | if (strcmp(ent->mnt_type, "iso9660") == 0) |
89 | continue; | 89 | continue; |
90 | if (strcmp(ent->mnt_type, "vfat") == 0) | ||
91 | continue; | ||
90 | if (strcmp(ent->mnt_dir, "/") == 0) { | 92 | if (strcmp(ent->mnt_dir, "/") == 0) { |
91 | root_seen = 1; | 93 | root_seen = 1; |
92 | continue; | 94 | continue; |