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