xref: /freebsd/share/man/man4/hv_vss.4 (revision 1c05a6ea6b849ff95e539c31adea887c644a6a01)
1.\" Copyright (c) 2016 Microsoft Corp.
2.\" All rights reserved.
3.\"
4.\" Redistribution and use in source and binary forms, with or without
5.\" modification, are permitted provided that the following conditions
6.\" are met:
7.\" 1. Redistributions of source code must retain the above copyright
8.\"    notice, this list of conditions and the following disclaimer.
9.\" 2. Redistributions in binary form must reproduce the above copyright
10.\"    notice, this list of conditions and the following disclaimer in the
11.\"    documentation and/or other materials provided with the distribution.
12.\"
13.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23.\" SUCH DAMAGE.
24.\"
25.\" $FreeBSD$
26.Dd October 12, 2016
27.Dt HV_VSS 4
28.Os
29.Sh NAME
30.Nm hv_vss
31.Nd Hyper-V Volume Shadow Copy Service API
32.Sh SYNOPSIS
33.In dev/hyperv/hv_snapshot.h
34.Bd -literal
35#define VSS_SUCCESS		0x00000000
36#define VSS_FAIL		0x00000001
37
38enum hv_vss_op_t {
39	HV_VSS_NONE = 0,
40	HV_VSS_CHECK,
41	HV_VSS_FREEZE,
42	HV_VSS_THAW,
43	HV_VSS_COUNT
44};
45
46struct hv_vss_opt_msg {
47	uint32_t	opt;		/* operation */
48	uint32_t	status;		/* 0 for success, 1 for error */
49	uint64_t	msgid;		/* an ID used to identify the transaction */
50	uint8_t		reserved[48];	/* reserved values are all zeroes */
51};
52.Ed
53.Sh DESCRIPTION
54The freeze or thaw functionality of application is important to guarantee
55the application consistent backup. On windows platform, VSS is defined to do
56live backup. But for VM guest running on Hyper-V, the corresponding VSS is
57not defined yet. For example, a running database server instance, it knows when the
58applications' freeze/thaw should start or finish. But it is not aware of
59the freeze/thaw notification from Hyper-V host. The
60.Nm
61is designed to notify application freeze/thaw request.
62Thus, it plays a role of broker to forward the freeze/thaw command from Hyper-V host
63to userland application if it registered VSS service on
64.Fx
65VM, and sends the result back to Hyper-V host.
66.Pp
67Generally,
68.Xr hv_vss_daemon 8
69takes the responsibility to freeze/thaw UFS file system,
70and it is automatically launched after system boots. When Hyper-V host wants to
71take a snapshot of the
72.Fx
73VM, it will first send VSS capability check to
74.Fx
75VM. The
76.Nm
77received the request and forward the request to userland application if it is
78registered. Only after
79.Nm
80received the VSS_SUCCESS response from application, the
81.Xr hv_vss_daemon 8
82will be informed to check whether file system freeze/thaw is supported. Any error
83occurs during this period,
84.Nm
85will inform Hyper-V host that VSS is not supported. In addition, there is a default
86timeout limit before sending response to Hyper-V host.
87If the total response time from application and
88.Xr hv_vss_daemon 8
89exceeds this value, timeout
90will occurs and VSS unsupported is responsed to Hyper-V host.
91.Pp
92After Hyper-V host confirmed the
93.Fx
94VM supports VSS, it will send freeze request to VM, and
95.Nm
96will first forward it to application. After application finished freezing, it should
97inform
98.Nm
99and file system level freezing will be triggered by
100.Xr hv_vss_daemon 8 . After all freezing
101on both application and
102.Xr hv_vss_daemon 8
103were finished, the
104.Nm
105will inform Hyper-V host that freezing is done. Of course, there is a timeout limit as
106same as VSS capability is set to make sure freezing on
107.Fx
108VM is not hang. If there is any error occurs or timeout happened, the freezing is failed
109on Hyper-V side.
110.Pp
111Hyper-V host will send thaw request after taking the snapshot, typically, this period is
112very short in order not to block the running application.
113.Nm
114firstly thaw the file system by notifying
115.Xr hv_vss_daemon 8 ,
116then notifies user registered
117application. There is also a timeout check before sending response to Hyper-V host.
118.Pp
119All the default timeout limit used in VSS capability check, freeze or thaw is the same.
120It is 15 seconds currently.
121.Sh NOTES
122.Nm
123only support UFS currently. If any of file system partition is non UFS, the VSS capability
124check will fail. If application does not register VSS,
125.Nm
126only support backup for file system level consistent. The device should be closed before it
127was opened again. If you want to simultaneously open "/dev/hv_appvss_dev" two or more times,
128an error (-1) will be returned, and errno was set.
129.Pp
130If
131.Xr hv_vss_daemon 8
132was killed after system boots, the VSS functionality will not work.
133.Sh EXAMPLES
134The following is a complete example which does nothing except for waiting 2 seconds when
135receiving those notifications from
136.Nm
137.Bd -literal
138#include <string.h>
139#include <stdio.h>
140#include <sys/ioctl.h>
141#include <sys/param.h>
142#include <sys/ucred.h>
143#include <sys/mount.h>
144#include <sys/types.h>
145#include <unistd.h>
146#include <stdlib.h>
147#include <poll.h>
148#include <stdint.h>
149#include <syslog.h>
150#include <errno.h>
151#include <err.h>
152#include <fcntl.h>
153#include <ufs/ffs/fs.h>
154#include <paths.h>
155#include <sys/ioccom.h>
156#include <dev/hyperv/hv_snapshot.h>
157
158#define UNDEF_FREEZE_THAW	(0)
159#define FREEZE			(1)
160#define THAW			(2)
161#define CHECK			(3)
162
163#define	VSS_LOG(priority, format, args...) do	{				\\
164		if (is_debugging == 1) {					\\
165			if (is_daemon == 1)					\\
166				syslog(priority, format, ## args);		\\
167			else							\\
168				printf(format, ## args);			\\
169		} else {							\\
170			if (priority < LOG_DEBUG) {				\\
171				if (is_daemon == 1)				\\
172					syslog(priority, format, ## args);	\\
173				else						\\
174					printf(format, ## args);		\\
175			}							\\
176		}								\\
177	} while(0)
178
179#define CHECK_TIMEOUT		1
180#define CHECK_FAIL		2
181#define FREEZE_TIMEOUT		1
182#define FREEZE_FAIL		2
183#define THAW_TIMEOUT		1
184#define THAW_FAIL		2
185
186static int is_daemon        = 1;
187static int is_debugging     = 0;
188static int simu_opt_waiting = 2; // seconds
189
190#define GENERIC_OPT(TIMEOUT, FAIL)						\\
191	do {									\\
192		sleep(simu_opt_waiting);					\\
193		if (opt == CHECK_TIMEOUT) {					\\
194			sleep(simu_opt_waiting * 10);				\\
195			VSS_LOG(LOG_INFO, "%s timeout simulation\\n",		\\
196			    __func__);						\\
197			return (0);						\\
198		} else if (opt == CHECK_FAIL) {					\\
199			VSS_LOG(LOG_INFO, "%s failure simulation\\n",		\\
200			    __func__);						\\
201			return (CHECK_FAIL);					\\
202		} else {							\\
203			VSS_LOG(LOG_INFO, "%s success simulation\\n",		\\
204			    __func__);						\\
205			return (0);						\\
206		}								\\
207	} while (0)
208
209static int
210check(int opt)
211{
212	GENERIC_OPT(CHECK_TIMEOUT, CHECK_FAIL);
213}
214
215static int
216freeze(int opt)
217{
218	GENERIC_OPT(FREEZE_TIMEOUT, FREEZE_FAIL);
219}
220
221static int
222thaw(int opt)
223{
224	GENERIC_OPT(THAW_TIMEOUT, THAW_FAIL);
225}
226
227static void usage(const char* cmd) {
228	fprintf(stderr,
229	    "%s -f <0|1|2>: simulate app freeze."
230	    " 0: successful, 1: freeze timeout, 2: freeze failed\\n"
231	    " -c <0|1|2>: simulate vss feature check"
232	    " -t <0|1|2>: simulate app thaw."
233	    " 0: successful, 1: freeze timeout, 2: freeze failed\\n"
234	    " -d : enable debug mode\\n"
235	    " -n : run this tool under non-daemon mode\\n", cmd);
236}
237
238int
239main(int argc, char* argv[]) {
240	int ch, freezesimuop = 0, thawsimuop = 0, checksimuop = 0, fd, r, error;
241	uint32_t op;
242	struct pollfd app_vss_fd[1];
243	struct hv_vss_opt_msg  userdata;
244
245	while ((ch = getopt(argc, argv, "f:c:t:dnh")) != -1) {
246		switch (ch) {
247		case 'f':
248			/* Run as regular process for debugging purpose. */
249			freezesimuop = (int)strtol(optarg, NULL, 10);
250			break;
251		case 't':
252			thawsimuop = (int)strtol(optarg, NULL, 10);
253			break;
254		case 'c':
255			checksimuop = (int)strtol(optarg, NULL, 10);
256			break;
257		case 'd':
258			is_debugging = 1;
259			break;
260		case 'n':
261			is_daemon = 0;
262			break;
263		case 'h':
264		default:
265			usage(argv[0]);
266			exit(0);
267		}
268	}
269
270	openlog("APPVSS", 0, LOG_USER);
271	/* Become daemon first. */
272	if (is_daemon == 1)
273		daemon(1, 0);
274	else
275		VSS_LOG(LOG_DEBUG, "Run as regular process.\\n");
276
277	VSS_LOG(LOG_INFO, "HV_VSS starting; pid is: %d\\n", getpid());
278
279	fd = open(VSS_DEV(APP_VSS_DEV_NAME), O_RDWR);
280	if (fd < 0) {
281		VSS_LOG(LOG_ERR, "Fail to open %s, error: %d %s\\n",
282		    VSS_DEV(APP_VSS_DEV_NAME), errno, strerror(errno));
283		exit(EXIT_FAILURE);
284	}
285	app_vss_fd[0].fd     = fd;
286	app_vss_fd[0].events = POLLIN | POLLRDNORM;
287
288	while (1) {
289		r = poll(app_vss_fd, 1, INFTIM);
290
291		VSS_LOG(LOG_DEBUG, "poll returned r = %d, revent = 0x%x\\n",
292		    r, app_vss_fd[0].revents);
293
294		if (r == 0 || (r < 0 && errno == EAGAIN) ||
295		    (r < 0 && errno == EINTR)) {
296			/* Nothing to read */
297			continue;
298		}
299
300		if (r < 0) {
301			/*
302			 * For poll return failure other than EAGAIN,
303			 * we want to exit.
304			 */
305			VSS_LOG(LOG_ERR, "Poll failed.\\n");
306			perror("poll");
307			exit(EIO);
308		}
309
310		/* Read from character device */
311		error = ioctl(fd, IOCHVVSSREAD, &userdata);
312		if (error < 0) {
313			VSS_LOG(LOG_ERR, "Read failed.\\n");
314			perror("pread");
315			exit(EIO);
316		}
317
318		if (userdata.status != 0) {
319			VSS_LOG(LOG_ERR, "data read error\\n");
320			continue;
321		}
322
323		op = userdata.opt;
324
325		switch (op) {
326		case HV_VSS_CHECK:
327			error = check(checksimuop);
328			break;
329		case HV_VSS_FREEZE:
330			error = freeze(freezesimuop);
331			break;
332		case HV_VSS_THAW:
333			error = thaw(thawsimuop);
334			break;
335		default:
336			VSS_LOG(LOG_ERR, "Illegal operation: %d\\n", op);
337			error = VSS_FAIL;
338		}
339		if (error)
340			userdata.status = VSS_FAIL;
341		else
342			userdata.status = VSS_SUCCESS;
343		error = ioctl(fd, IOCHVVSSWRITE, &userdata);
344		if (error != 0) {
345			VSS_LOG(LOG_ERR, "Fail to write to device\\n");
346			exit(EXIT_FAILURE);
347		} else {
348			VSS_LOG(LOG_INFO, "Send response %d for %s to kernel\\n",
349			    userdata.status, op == HV_VSS_FREEZE ? "Freeze" :
350			    (op == HV_VSS_THAW ? "Thaw" : "Check"));
351		}
352	}
353	return 0;
354}
355.Ed
356.Sh SEE ALSO
357.Xr hv_utils 4 ,
358.Xr hv_vss_daemon 8
359.Sh HISTORY
360The daemon was introduced in October 2016 and developed by Microsoft Corp.
361.Sh AUTHORS
362.An -nosplit
363.Fx
364support for
365.Nm
366was first added by
367.An Microsoft BSD Integration Services Team Aq Mt bsdic@microsoft.com .
368