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