Blame view

tools/hv/hv_vss_daemon.c 6.09 KB
96dd86fa5   K. Y. Srinivasan   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   K. Y. Srinivasan   Drivers: hv: Add ...
22
  #include <sys/poll.h>
7b413b655   Olaf Hering   tools: hv: use FI...
23
  #include <sys/ioctl.h>
7b413b655   Olaf Hering   tools: hv: use FI...
24
  #include <fcntl.h>
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
25
  #include <stdio.h>
d3d1ee3ab   Olaf Hering   tools: hv: use ge...
26
  #include <mntent.h>
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
27
28
29
30
31
  #include <stdlib.h>
  #include <unistd.h>
  #include <string.h>
  #include <ctype.h>
  #include <errno.h>
7b413b655   Olaf Hering   tools: hv: use FI...
32
  #include <linux/fs.h>
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
33
  #include <linux/hyperv.h>
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
34
  #include <syslog.h>
170f4bea2   Vitaly Kuznetsov   tools: hv: introd...
35
  #include <getopt.h>
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
36

4f689190b   Dexuan Cui   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   Olaf Hering   tools: hv: use FI...
39
40
41
42
43
  {
  	int ret, fd = open(dir, O_RDONLY);
  
  	if (fd < 0)
  		return 1;
4f689190b   Dexuan Cui   Tools: hv: vssdae...
44

7b413b655   Olaf Hering   tools: hv: use FI...
45
  	ret = ioctl(fd, cmd, 0);
4f689190b   Dexuan Cui   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   Olaf Hering   tools: hv: use FI...
63
64
65
  	close(fd);
  	return !!ret;
  }
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
66
67
  static int vss_operate(int operation)
  {
d3d1ee3ab   Olaf Hering   tools: hv: use ge...
68
69
70
  	char match[] = "/dev/";
  	FILE *mounts;
  	struct mntent *ent;
4ce50e949   Vaughan Cao   hv: hypervvssd: c...
71
  	char errdir[1024] = {0};
7b413b655   Olaf Hering   tools: hv: use FI...
72
  	unsigned int cmd;
7a401744d   Vitaly Kuznetsov   Tools: hv: vssdae...
73
  	int error = 0, root_seen = 0, save_errno = 0;
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
74
75
76
  
  	switch (operation) {
  	case VSS_OP_FREEZE:
7b413b655   Olaf Hering   tools: hv: use FI...
77
  		cmd = FIFREEZE;
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
78
79
  		break;
  	case VSS_OP_THAW:
7b413b655   Olaf Hering   tools: hv: use FI...
80
  		cmd = FITHAW;
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
81
  		break;
eb8905b8f   Olaf Hering   Tools: hv: fix wa...
82
83
  	default:
  		return -1;
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
84
  	}
d3d1ee3ab   Olaf Hering   tools: hv: use ge...
85
86
  	mounts = setmntent("/proc/mounts", "r");
  	if (mounts == NULL)
eb8905b8f   Olaf Hering   Tools: hv: fix wa...
87
  		return -1;
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
88

0e2726392   K. Y. Srinivasan   Tools: hv: Fix a ...
89
  	while ((ent = getmntent(mounts))) {
d3d1ee3ab   Olaf Hering   tools: hv: use ge...
90
  		if (strncmp(ent->mnt_fsname, match, strlen(match)))
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
91
  			continue;
9e5db05aa   Vitaly Kuznetsov   Tools: hv: vssdae...
92
  		if (hasmntopt(ent, MNTOPT_RO) != NULL)
10b637b4c   Olaf Hering   tools: hv: skip i...
93
  			continue;
f33b21554   K. Y. Srinivasan   Tools: hv: vssdae...
94
95
  		if (strcmp(ent->mnt_type, "vfat") == 0)
  			continue;
d3d1ee3ab   Olaf Hering   tools: hv: use ge...
96
97
98
99
  		if (strcmp(ent->mnt_dir, "/") == 0) {
  			root_seen = 1;
  			continue;
  		}
4f689190b   Dexuan Cui   Tools: hv: vssdae...
100
101
102
  		error |= vss_do_freeze(ent->mnt_dir, cmd);
  		if (error && operation == VSS_OP_FREEZE)
  			goto err;
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
103
  	}
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
104

4ce50e949   Vaughan Cao   hv: hypervvssd: c...
105
  	endmntent(mounts);
d3d1ee3ab   Olaf Hering   tools: hv: use ge...
106
  	if (root_seen) {
4f689190b   Dexuan Cui   Tools: hv: vssdae...
107
108
109
  		error |= vss_do_freeze("/", cmd);
  		if (error && operation == VSS_OP_FREEZE)
  			goto err;
d3d1ee3ab   Olaf Hering   tools: hv: use ge...
110
  	}
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
111

7a401744d   Vitaly Kuznetsov   Tools: hv: vssdae...
112
  	goto out;
4f689190b   Dexuan Cui   Tools: hv: vssdae...
113
  err:
7a401744d   Vitaly Kuznetsov   Tools: hv: vssdae...
114
  	save_errno = errno;
4ce50e949   Vaughan Cao   hv: hypervvssd: c...
115
116
117
118
  	if (ent) {
  		strncpy(errdir, ent->mnt_dir, sizeof(errdir)-1);
  		endmntent(mounts);
  	}
4f689190b   Dexuan Cui   Tools: hv: vssdae...
119
  	vss_operate(VSS_OP_THAW);
7a401744d   Vitaly Kuznetsov   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   Vaughan Cao   hv: hypervvssd: c...
123
  		       errdir, save_errno, strerror(save_errno));
7a401744d   Vitaly Kuznetsov   Tools: hv: vssdae...
124
125
126
127
  	else
  		syslog(LOG_ERR, "FREEZE of / failed; error:%d %s", save_errno,
  		       strerror(save_errno));
  out:
4f689190b   Dexuan Cui   Tools: hv: vssdae...
128
  	return error;
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
129
  }
170f4bea2   Vitaly Kuznetsov   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   K. Y. Srinivasan   Drivers: hv: Add ...
143
  {
f5722b9bd   Vitaly Kuznetsov   Tools: hv: vss: u...
144
  	int vss_fd, len;
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
145
  	int error;
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
146
  	struct pollfd pfd;
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
147
  	int	op;
f5722b9bd   Vitaly Kuznetsov   Tools: hv: vss: u...
148
  	struct hv_vss_msg vss_msg[1];
170f4bea2   Vitaly Kuznetsov   tools: hv: introd...
149
  	int daemonize = 1, long_index = 0, opt;
cd8dc0548   Vitaly Kuznetsov   Drivers: hv: vss:...
150
151
  	int in_handshake = 1;
  	__u32 kernel_modver;
170f4bea2   Vitaly Kuznetsov   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   K. Y. Srinivasan   Drivers: hv: Add ...
171

170f4bea2   Vitaly Kuznetsov   tools: hv: introd...
172
  	if (daemonize && daemon(1, 0))
eb8905b8f   Olaf Hering   Tools: hv: fix wa...
173
  		return 1;
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
174
175
  	openlog("Hyper-V VSS", 0, LOG_USER);
  	syslog(LOG_INFO, "VSS starting; pid is:%d", getpid());
f5722b9bd   Vitaly Kuznetsov   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   Tomas Hozza   tools: hv: Check ...
180
181
  		exit(EXIT_FAILURE);
  	}
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
182
183
184
  	/*
  	 * Register ourselves with the kernel.
  	 */
f5722b9bd   Vitaly Kuznetsov   Tools: hv: vss: u...
185
  	vss_msg->vss_hdr.operation = VSS_OP_REGISTER1;
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
186

f5722b9bd   Vitaly Kuznetsov   Tools: hv: vss: u...
187
  	len = write(vss_fd, vss_msg, sizeof(struct hv_vss_msg));
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
188
  	if (len < 0) {
f5722b9bd   Vitaly Kuznetsov   Tools: hv: vss: u...
189
190
191
  		syslog(LOG_ERR, "registration to kernel failed; error: %d %s",
  		       errno, strerror(errno));
  		close(vss_fd);
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
192
193
  		exit(EXIT_FAILURE);
  	}
f5722b9bd   Vitaly Kuznetsov   Tools: hv: vss: u...
194
  	pfd.fd = vss_fd;
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
195
196
  
  	while (1) {
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
197
198
  		pfd.events = POLLIN;
  		pfd.revents = 0;
9561d4793   Tomas Hozza   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   Vitaly Kuznetsov   Tools: hv: vss: u...
203
  				close(vss_fd);
9561d4793   Tomas Hozza   tools: hv: Check ...
204
205
206
207
208
  				exit(EXIT_FAILURE);
  			}
  			else
  				continue;
  		}
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
209

f5722b9bd   Vitaly Kuznetsov   Tools: hv: vss: u...
210
  		len = read(vss_fd, vss_msg, sizeof(struct hv_vss_msg));
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
211

cd8dc0548   Vitaly Kuznetsov   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   Vitaly Kuznetsov   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   Olaf Hering   tools: hv: fix ch...
228
  		}
96dd86fa5   K. Y. Srinivasan   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   Dexuan Cui   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   K. Y. Srinivasan   Drivers: hv: Add ...
242
  				error = HV_E_FAIL;
4f689190b   Dexuan Cui   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   K. Y. Srinivasan   Drivers: hv: Add ...
247
  			break;
db886e4d2   Alex Ng   Drivers: hv: util...
248
249
250
251
  		case VSS_OP_HOT_BACKUP:
  			syslog(LOG_INFO, "VSS: op=CHECK HOT BACKUP
  ");
  			break;
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
252
253
254
255
256
  		default:
  			syslog(LOG_ERR, "Illegal op:%d
  ", op);
  		}
  		vss_msg->error = error;
a689d2510   Dexuan Cui   tools: hv: vss: f...
257
  		len = write(vss_fd, vss_msg, sizeof(struct hv_vss_msg));
f5722b9bd   Vitaly Kuznetsov   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   K. Y. Srinivasan   Drivers: hv: Add ...
261
262
263
  			exit(EXIT_FAILURE);
  		}
  	}
f5722b9bd   Vitaly Kuznetsov   Tools: hv: vss: u...
264
265
  	close(vss_fd);
  	exit(0);
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
266
  }