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 responsiblity 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