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