Blame view
tools/hv/hv_vss_daemon.c
6.09 KB
96dd86fa5 Drivers: hv: Add ... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
/* * An implementation of the host initiated guest snapshot for Hyper-V. * * * Copyright (C) 2013, 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> |
96dd86fa5 Drivers: hv: Add ... |
22 |
#include <sys/poll.h> |
7b413b655 tools: hv: use FI... |
23 |
#include <sys/ioctl.h> |
7b413b655 tools: hv: use FI... |
24 |
#include <fcntl.h> |
96dd86fa5 Drivers: hv: Add ... |
25 |
#include <stdio.h> |
d3d1ee3ab tools: hv: use ge... |
26 |
#include <mntent.h> |
96dd86fa5 Drivers: hv: Add ... |
27 28 29 30 31 |
#include <stdlib.h> #include <unistd.h> #include <string.h> #include <ctype.h> #include <errno.h> |
7b413b655 tools: hv: use FI... |
32 |
#include <linux/fs.h> |
96dd86fa5 Drivers: hv: Add ... |
33 |
#include <linux/hyperv.h> |
96dd86fa5 Drivers: hv: Add ... |
34 |
#include <syslog.h> |
170f4bea2 tools: hv: introd... |
35 |
#include <getopt.h> |
96dd86fa5 Drivers: hv: Add ... |
36 |
|
4f689190b Tools: hv: vssdae... |
37 38 |
/* Don't use syslog() in the function since that can cause write to disk */ static int vss_do_freeze(char *dir, unsigned int cmd) |
7b413b655 tools: hv: use FI... |
39 40 41 42 43 |
{ int ret, fd = open(dir, O_RDONLY); if (fd < 0) return 1; |
4f689190b Tools: hv: vssdae... |
44 |
|
7b413b655 tools: hv: use FI... |
45 |
ret = ioctl(fd, cmd, 0); |
4f689190b Tools: hv: vssdae... |
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
/* * If a partition is mounted more than once, only the first * FREEZE/THAW can succeed and the later ones will get * EBUSY/EINVAL respectively: there could be 2 cases: * 1) a user may mount the same partition to differnt directories * by mistake or on purpose; * 2) The subvolume of btrfs appears to have the same partition * mounted more than once. */ if (ret) { if ((cmd == FIFREEZE && errno == EBUSY) || (cmd == FITHAW && errno == EINVAL)) { close(fd); return 0; } } |
7b413b655 tools: hv: use FI... |
63 64 65 |
close(fd); return !!ret; } |
96dd86fa5 Drivers: hv: Add ... |
66 67 |
static int vss_operate(int operation) { |
d3d1ee3ab tools: hv: use ge... |
68 69 70 |
char match[] = "/dev/"; FILE *mounts; struct mntent *ent; |
4ce50e949 hv: hypervvssd: c... |
71 |
char errdir[1024] = {0}; |
7b413b655 tools: hv: use FI... |
72 |
unsigned int cmd; |
7a401744d Tools: hv: vssdae... |
73 |
int error = 0, root_seen = 0, save_errno = 0; |
96dd86fa5 Drivers: hv: Add ... |
74 75 76 |
switch (operation) { case VSS_OP_FREEZE: |
7b413b655 tools: hv: use FI... |
77 |
cmd = FIFREEZE; |
96dd86fa5 Drivers: hv: Add ... |
78 79 |
break; case VSS_OP_THAW: |
7b413b655 tools: hv: use FI... |
80 |
cmd = FITHAW; |
96dd86fa5 Drivers: hv: Add ... |
81 |
break; |
eb8905b8f Tools: hv: fix wa... |
82 83 |
default: return -1; |
96dd86fa5 Drivers: hv: Add ... |
84 |
} |
d3d1ee3ab tools: hv: use ge... |
85 86 |
mounts = setmntent("/proc/mounts", "r"); if (mounts == NULL) |
eb8905b8f Tools: hv: fix wa... |
87 |
return -1; |
96dd86fa5 Drivers: hv: Add ... |
88 |
|
0e2726392 Tools: hv: Fix a ... |
89 |
while ((ent = getmntent(mounts))) { |
d3d1ee3ab tools: hv: use ge... |
90 |
if (strncmp(ent->mnt_fsname, match, strlen(match))) |
96dd86fa5 Drivers: hv: Add ... |
91 |
continue; |
9e5db05aa Tools: hv: vssdae... |
92 |
if (hasmntopt(ent, MNTOPT_RO) != NULL) |
10b637b4c tools: hv: skip i... |
93 |
continue; |
f33b21554 Tools: hv: vssdae... |
94 95 |
if (strcmp(ent->mnt_type, "vfat") == 0) continue; |
d3d1ee3ab tools: hv: use ge... |
96 97 98 99 |
if (strcmp(ent->mnt_dir, "/") == 0) { root_seen = 1; continue; } |
4f689190b Tools: hv: vssdae... |
100 101 102 |
error |= vss_do_freeze(ent->mnt_dir, cmd); if (error && operation == VSS_OP_FREEZE) goto err; |
96dd86fa5 Drivers: hv: Add ... |
103 |
} |
96dd86fa5 Drivers: hv: Add ... |
104 |
|
4ce50e949 hv: hypervvssd: c... |
105 |
endmntent(mounts); |
d3d1ee3ab tools: hv: use ge... |
106 |
if (root_seen) { |
4f689190b Tools: hv: vssdae... |
107 108 109 |
error |= vss_do_freeze("/", cmd); if (error && operation == VSS_OP_FREEZE) goto err; |
d3d1ee3ab tools: hv: use ge... |
110 |
} |
96dd86fa5 Drivers: hv: Add ... |
111 |
|
7a401744d Tools: hv: vssdae... |
112 |
goto out; |
4f689190b Tools: hv: vssdae... |
113 |
err: |
7a401744d Tools: hv: vssdae... |
114 |
save_errno = errno; |
4ce50e949 hv: hypervvssd: c... |
115 116 117 118 |
if (ent) { strncpy(errdir, ent->mnt_dir, sizeof(errdir)-1); endmntent(mounts); } |
4f689190b Tools: hv: vssdae... |
119 |
vss_operate(VSS_OP_THAW); |
7a401744d Tools: hv: vssdae... |
120 121 122 |
/* Call syslog after we thaw all filesystems */ if (ent) syslog(LOG_ERR, "FREEZE of %s failed; error:%d %s", |
4ce50e949 hv: hypervvssd: c... |
123 |
errdir, save_errno, strerror(save_errno)); |
7a401744d Tools: hv: vssdae... |
124 125 126 127 |
else syslog(LOG_ERR, "FREEZE of / failed; error:%d %s", save_errno, strerror(save_errno)); out: |
4f689190b Tools: hv: vssdae... |
128 |
return error; |
96dd86fa5 Drivers: hv: Add ... |
129 |
} |
170f4bea2 tools: hv: introd... |
130 131 132 133 134 135 136 137 138 139 140 141 142 |
void print_usage(char *argv[]) { fprintf(stderr, "Usage: %s [options] " "Options are: " " -n, --no-daemon stay in foreground, don't daemonize " " -h, --help print this help ", argv[0]); } int main(int argc, char *argv[]) |
96dd86fa5 Drivers: hv: Add ... |
143 |
{ |
f5722b9bd Tools: hv: vss: u... |
144 |
int vss_fd, len; |
96dd86fa5 Drivers: hv: Add ... |
145 |
int error; |
96dd86fa5 Drivers: hv: Add ... |
146 |
struct pollfd pfd; |
96dd86fa5 Drivers: hv: Add ... |
147 |
int op; |
f5722b9bd Tools: hv: vss: u... |
148 |
struct hv_vss_msg vss_msg[1]; |
170f4bea2 tools: hv: introd... |
149 |
int daemonize = 1, long_index = 0, opt; |
cd8dc0548 Drivers: hv: vss:... |
150 151 |
int in_handshake = 1; __u32 kernel_modver; |
170f4bea2 tools: hv: introd... |
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
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); } } |
96dd86fa5 Drivers: hv: Add ... |
171 |
|
170f4bea2 tools: hv: introd... |
172 |
if (daemonize && daemon(1, 0)) |
eb8905b8f Tools: hv: fix wa... |
173 |
return 1; |
96dd86fa5 Drivers: hv: Add ... |
174 175 |
openlog("Hyper-V VSS", 0, LOG_USER); syslog(LOG_INFO, "VSS starting; pid is:%d", getpid()); |
f5722b9bd Tools: hv: vss: u... |
176 177 178 179 |
vss_fd = open("/dev/vmbus/hv_vss", O_RDWR); if (vss_fd < 0) { syslog(LOG_ERR, "open /dev/vmbus/hv_vss failed; error: %d %s", errno, strerror(errno)); |
d12e14692 tools: hv: Check ... |
180 181 |
exit(EXIT_FAILURE); } |
96dd86fa5 Drivers: hv: Add ... |
182 183 184 |
/* * Register ourselves with the kernel. */ |
f5722b9bd Tools: hv: vss: u... |
185 |
vss_msg->vss_hdr.operation = VSS_OP_REGISTER1; |
96dd86fa5 Drivers: hv: Add ... |
186 |
|
f5722b9bd Tools: hv: vss: u... |
187 |
len = write(vss_fd, vss_msg, sizeof(struct hv_vss_msg)); |
96dd86fa5 Drivers: hv: Add ... |
188 |
if (len < 0) { |
f5722b9bd Tools: hv: vss: u... |
189 190 191 |
syslog(LOG_ERR, "registration to kernel failed; error: %d %s", errno, strerror(errno)); close(vss_fd); |
96dd86fa5 Drivers: hv: Add ... |
192 193 |
exit(EXIT_FAILURE); } |
f5722b9bd Tools: hv: vss: u... |
194 |
pfd.fd = vss_fd; |
96dd86fa5 Drivers: hv: Add ... |
195 196 |
while (1) { |
96dd86fa5 Drivers: hv: Add ... |
197 198 |
pfd.events = POLLIN; pfd.revents = 0; |
9561d4793 tools: hv: Check ... |
199 200 201 202 |
if (poll(&pfd, 1, -1) < 0) { syslog(LOG_ERR, "poll failed; error:%d %s", errno, strerror(errno)); if (errno == EINVAL) { |
f5722b9bd Tools: hv: vss: u... |
203 |
close(vss_fd); |
9561d4793 tools: hv: Check ... |
204 205 206 207 208 |
exit(EXIT_FAILURE); } else continue; } |
96dd86fa5 Drivers: hv: Add ... |
209 |
|
f5722b9bd Tools: hv: vss: u... |
210 |
len = read(vss_fd, vss_msg, sizeof(struct hv_vss_msg)); |
96dd86fa5 Drivers: hv: Add ... |
211 |
|
cd8dc0548 Drivers: hv: vss:... |
212 213 214 215 216 217 218 219 220 221 222 |
if (in_handshake) { if (len != sizeof(kernel_modver)) { syslog(LOG_ERR, "invalid version negotiation"); exit(EXIT_FAILURE); } kernel_modver = *(__u32 *)vss_msg; in_handshake = 0; syslog(LOG_INFO, "VSS: kernel module version: %d", kernel_modver); continue; } |
f5722b9bd Tools: hv: vss: u... |
223 224 225 226 227 |
if (len != sizeof(struct hv_vss_msg)) { syslog(LOG_ERR, "read failed; error:%d %s", errno, strerror(errno)); close(vss_fd); return EXIT_FAILURE; |
5edf5ee42 tools: hv: fix ch... |
228 |
} |
96dd86fa5 Drivers: hv: Add ... |
229 230 231 232 233 234 235 |
op = vss_msg->vss_hdr.operation; error = HV_S_OK; switch (op) { case VSS_OP_FREEZE: case VSS_OP_THAW: error = vss_operate(op); |
4f689190b Tools: hv: vssdae... |
236 237 238 239 240 241 |
syslog(LOG_INFO, "VSS: op=%s: %s ", op == VSS_OP_FREEZE ? "FREEZE" : "THAW", error ? "failed" : "succeeded"); if (error) { |
96dd86fa5 Drivers: hv: Add ... |
242 |
error = HV_E_FAIL; |
4f689190b Tools: hv: vssdae... |
243 244 245 246 |
syslog(LOG_ERR, "op=%d failed!", op); syslog(LOG_ERR, "report it with these files:"); syslog(LOG_ERR, "/etc/fstab and /proc/mounts"); } |
96dd86fa5 Drivers: hv: Add ... |
247 |
break; |
db886e4d2 Drivers: hv: util... |
248 249 250 251 |
case VSS_OP_HOT_BACKUP: syslog(LOG_INFO, "VSS: op=CHECK HOT BACKUP "); break; |
96dd86fa5 Drivers: hv: Add ... |
252 253 254 255 256 |
default: syslog(LOG_ERR, "Illegal op:%d ", op); } vss_msg->error = error; |
a689d2510 tools: hv: vss: f... |
257 |
len = write(vss_fd, vss_msg, sizeof(struct hv_vss_msg)); |
f5722b9bd Tools: hv: vss: u... |
258 259 260 |
if (len != sizeof(struct hv_vss_msg)) { syslog(LOG_ERR, "write failed; error: %d %s", errno, strerror(errno)); |
96dd86fa5 Drivers: hv: Add ... |
261 262 263 |
exit(EXIT_FAILURE); } } |
f5722b9bd Tools: hv: vss: u... |
264 265 |
close(vss_fd); exit(0); |
96dd86fa5 Drivers: hv: Add ... |
266 |
} |