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