xref: /openbmc/linux/tools/hv/hv_vss_daemon.c (revision 8dd06ef34b6e2f41b29fbf5fc1663780f2524285)
143aa3132SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
296dd86faSK. Y. Srinivasan /*
396dd86faSK. Y. Srinivasan  * An implementation of the host initiated guest snapshot for Hyper-V.
496dd86faSK. Y. Srinivasan  *
596dd86faSK. Y. Srinivasan  * Copyright (C) 2013, Microsoft, Inc.
696dd86faSK. Y. Srinivasan  * Author : K. Y. Srinivasan <kys@microsoft.com>
796dd86faSK. Y. Srinivasan  */
896dd86faSK. Y. Srinivasan 
996dd86faSK. Y. Srinivasan 
1096dd86faSK. Y. Srinivasan #include <sys/types.h>
1196dd86faSK. Y. Srinivasan #include <sys/poll.h>
127b413b65SOlaf Hering #include <sys/ioctl.h>
13ea81fdf0SAlex Ng #include <sys/stat.h>
141330fc35SDexuan Cui #include <sys/sysmacros.h>
157b413b65SOlaf Hering #include <fcntl.h>
1696dd86faSK. Y. Srinivasan #include <stdio.h>
17d3d1ee3aSOlaf Hering #include <mntent.h>
1896dd86faSK. Y. Srinivasan #include <stdlib.h>
1996dd86faSK. Y. Srinivasan #include <unistd.h>
2096dd86faSK. Y. Srinivasan #include <string.h>
2196dd86faSK. Y. Srinivasan #include <ctype.h>
2296dd86faSK. Y. Srinivasan #include <errno.h>
237b413b65SOlaf Hering #include <linux/fs.h>
24ea81fdf0SAlex Ng #include <linux/major.h>
2596dd86faSK. Y. Srinivasan #include <linux/hyperv.h>
2696dd86faSK. Y. Srinivasan #include <syslog.h>
27170f4beaSVitaly Kuznetsov #include <getopt.h>
2807136793SVitaly Kuznetsov #include <stdbool.h>
2907136793SVitaly Kuznetsov #include <dirent.h>
3096dd86faSK. Y. Srinivasan 
31*9fc3c01aSDexuan Cui static bool fs_frozen;
32*9fc3c01aSDexuan Cui 
334f689190SDexuan Cui /* Don't use syslog() in the function since that can cause write to disk */
vss_do_freeze(char * dir,unsigned int cmd)344f689190SDexuan Cui static int vss_do_freeze(char *dir, unsigned int cmd)
357b413b65SOlaf Hering {
367b413b65SOlaf Hering 	int ret, fd = open(dir, O_RDONLY);
377b413b65SOlaf Hering 
387b413b65SOlaf Hering 	if (fd < 0)
397b413b65SOlaf Hering 		return 1;
404f689190SDexuan Cui 
417b413b65SOlaf Hering 	ret = ioctl(fd, cmd, 0);
424f689190SDexuan Cui 
434f689190SDexuan Cui 	/*
444f689190SDexuan Cui 	 * If a partition is mounted more than once, only the first
454f689190SDexuan Cui 	 * FREEZE/THAW can succeed and the later ones will get
464f689190SDexuan Cui 	 * EBUSY/EINVAL respectively: there could be 2 cases:
472d35c660SAdrian Vladu 	 * 1) a user may mount the same partition to different directories
484f689190SDexuan Cui 	 *  by mistake or on purpose;
494f689190SDexuan Cui 	 * 2) The subvolume of btrfs appears to have the same partition
504f689190SDexuan Cui 	 * mounted more than once.
514f689190SDexuan Cui 	 */
524f689190SDexuan Cui 	if (ret) {
534f689190SDexuan Cui 		if ((cmd == FIFREEZE && errno == EBUSY) ||
544f689190SDexuan Cui 		    (cmd == FITHAW && errno == EINVAL)) {
554f689190SDexuan Cui 			close(fd);
564f689190SDexuan Cui 			return 0;
574f689190SDexuan Cui 		}
584f689190SDexuan Cui 	}
594f689190SDexuan Cui 
607b413b65SOlaf Hering 	close(fd);
617b413b65SOlaf Hering 	return !!ret;
627b413b65SOlaf Hering }
637b413b65SOlaf Hering 
is_dev_loop(const char * blkname)6407136793SVitaly Kuznetsov static bool is_dev_loop(const char *blkname)
6507136793SVitaly Kuznetsov {
6607136793SVitaly Kuznetsov 	char *buffer;
6707136793SVitaly Kuznetsov 	DIR *dir;
6807136793SVitaly Kuznetsov 	struct dirent *entry;
6907136793SVitaly Kuznetsov 	bool ret = false;
7007136793SVitaly Kuznetsov 
7107136793SVitaly Kuznetsov 	buffer = malloc(PATH_MAX);
7207136793SVitaly Kuznetsov 	if (!buffer) {
7307136793SVitaly Kuznetsov 		syslog(LOG_ERR, "Can't allocate memory!");
7407136793SVitaly Kuznetsov 		exit(1);
7507136793SVitaly Kuznetsov 	}
7607136793SVitaly Kuznetsov 
7707136793SVitaly Kuznetsov 	snprintf(buffer, PATH_MAX, "%s/loop", blkname);
7807136793SVitaly Kuznetsov 	if (!access(buffer, R_OK | X_OK)) {
7907136793SVitaly Kuznetsov 		ret = true;
8007136793SVitaly Kuznetsov 		goto free_buffer;
8107136793SVitaly Kuznetsov 	} else if (errno != ENOENT) {
8207136793SVitaly Kuznetsov 		syslog(LOG_ERR, "Can't access: %s; error:%d %s!",
8307136793SVitaly Kuznetsov 		       buffer, errno, strerror(errno));
8407136793SVitaly Kuznetsov 	}
8507136793SVitaly Kuznetsov 
8607136793SVitaly Kuznetsov 	snprintf(buffer, PATH_MAX, "%s/slaves", blkname);
8707136793SVitaly Kuznetsov 	dir = opendir(buffer);
8807136793SVitaly Kuznetsov 	if (!dir) {
8907136793SVitaly Kuznetsov 		if (errno != ENOENT)
9007136793SVitaly Kuznetsov 			syslog(LOG_ERR, "Can't opendir: %s; error:%d %s!",
9107136793SVitaly Kuznetsov 			       buffer, errno, strerror(errno));
9207136793SVitaly Kuznetsov 		goto free_buffer;
9307136793SVitaly Kuznetsov 	}
9407136793SVitaly Kuznetsov 
9507136793SVitaly Kuznetsov 	while ((entry = readdir(dir)) != NULL) {
9607136793SVitaly Kuznetsov 		if (strcmp(entry->d_name, ".") == 0 ||
9707136793SVitaly Kuznetsov 		    strcmp(entry->d_name, "..") == 0)
9807136793SVitaly Kuznetsov 			continue;
9907136793SVitaly Kuznetsov 
10007136793SVitaly Kuznetsov 		snprintf(buffer, PATH_MAX, "%s/slaves/%s", blkname,
10107136793SVitaly Kuznetsov 			 entry->d_name);
10207136793SVitaly Kuznetsov 		if (is_dev_loop(buffer)) {
10307136793SVitaly Kuznetsov 			ret = true;
10407136793SVitaly Kuznetsov 			break;
10507136793SVitaly Kuznetsov 		}
10607136793SVitaly Kuznetsov 	}
10707136793SVitaly Kuznetsov 	closedir(dir);
10807136793SVitaly Kuznetsov free_buffer:
10907136793SVitaly Kuznetsov 	free(buffer);
11007136793SVitaly Kuznetsov 	return ret;
11107136793SVitaly Kuznetsov }
11207136793SVitaly Kuznetsov 
vss_operate(int operation)11396dd86faSK. Y. Srinivasan static int vss_operate(int operation)
11496dd86faSK. Y. Srinivasan {
115d3d1ee3aSOlaf Hering 	char match[] = "/dev/";
116d3d1ee3aSOlaf Hering 	FILE *mounts;
117d3d1ee3aSOlaf Hering 	struct mntent *ent;
118ea81fdf0SAlex Ng 	struct stat sb;
1194ce50e94SVaughan Cao 	char errdir[1024] = {0};
12007136793SVitaly Kuznetsov 	char blkdir[23]; /* /sys/dev/block/XXX:XXX */
1217b413b65SOlaf Hering 	unsigned int cmd;
1227a401744SVitaly Kuznetsov 	int error = 0, root_seen = 0, save_errno = 0;
12396dd86faSK. Y. Srinivasan 
12496dd86faSK. Y. Srinivasan 	switch (operation) {
12596dd86faSK. Y. Srinivasan 	case VSS_OP_FREEZE:
1267b413b65SOlaf Hering 		cmd = FIFREEZE;
12796dd86faSK. Y. Srinivasan 		break;
12896dd86faSK. Y. Srinivasan 	case VSS_OP_THAW:
1297b413b65SOlaf Hering 		cmd = FITHAW;
13096dd86faSK. Y. Srinivasan 		break;
131eb8905b8SOlaf Hering 	default:
132eb8905b8SOlaf Hering 		return -1;
13396dd86faSK. Y. Srinivasan 	}
13496dd86faSK. Y. Srinivasan 
135d3d1ee3aSOlaf Hering 	mounts = setmntent("/proc/mounts", "r");
136d3d1ee3aSOlaf Hering 	if (mounts == NULL)
137eb8905b8SOlaf Hering 		return -1;
13896dd86faSK. Y. Srinivasan 
139d3d1ee3aSOlaf Hering 	while ((ent = getmntent(mounts))) {
140d3d1ee3aSOlaf Hering 		if (strncmp(ent->mnt_fsname, match, strlen(match)))
14196dd86faSK. Y. Srinivasan 			continue;
14207136793SVitaly Kuznetsov 		if (stat(ent->mnt_fsname, &sb)) {
14307136793SVitaly Kuznetsov 			syslog(LOG_ERR, "Can't stat: %s; error:%d %s!",
14407136793SVitaly Kuznetsov 			       ent->mnt_fsname, errno, strerror(errno));
14507136793SVitaly Kuznetsov 		} else {
14607136793SVitaly Kuznetsov 			sprintf(blkdir, "/sys/dev/block/%d:%d",
14707136793SVitaly Kuznetsov 				major(sb.st_rdev), minor(sb.st_rdev));
14807136793SVitaly Kuznetsov 			if (is_dev_loop(blkdir))
149ea81fdf0SAlex Ng 				continue;
15007136793SVitaly Kuznetsov 		}
1519e5db05aSVitaly Kuznetsov 		if (hasmntopt(ent, MNTOPT_RO) != NULL)
15210b637b4SOlaf Hering 			continue;
153f33b2155SK. Y. Srinivasan 		if (strcmp(ent->mnt_type, "vfat") == 0)
154f33b2155SK. Y. Srinivasan 			continue;
155d3d1ee3aSOlaf Hering 		if (strcmp(ent->mnt_dir, "/") == 0) {
156d3d1ee3aSOlaf Hering 			root_seen = 1;
157d3d1ee3aSOlaf Hering 			continue;
15896dd86faSK. Y. Srinivasan 		}
1594f689190SDexuan Cui 		error |= vss_do_freeze(ent->mnt_dir, cmd);
160*9fc3c01aSDexuan Cui 		if (operation == VSS_OP_FREEZE) {
161*9fc3c01aSDexuan Cui 			if (error)
1624f689190SDexuan Cui 				goto err;
163*9fc3c01aSDexuan Cui 			fs_frozen = true;
164*9fc3c01aSDexuan Cui 		}
165d3d1ee3aSOlaf Hering 	}
166d3d1ee3aSOlaf Hering 
1674ce50e94SVaughan Cao 	endmntent(mounts);
1684ce50e94SVaughan Cao 
169d3d1ee3aSOlaf Hering 	if (root_seen) {
1704f689190SDexuan Cui 		error |= vss_do_freeze("/", cmd);
171*9fc3c01aSDexuan Cui 		if (operation == VSS_OP_FREEZE) {
172*9fc3c01aSDexuan Cui 			if (error)
1734f689190SDexuan Cui 				goto err;
174*9fc3c01aSDexuan Cui 			fs_frozen = true;
175d3d1ee3aSOlaf Hering 		}
176*9fc3c01aSDexuan Cui 	}
177*9fc3c01aSDexuan Cui 
178*9fc3c01aSDexuan Cui 	if (operation == VSS_OP_THAW && !error)
179*9fc3c01aSDexuan Cui 		fs_frozen = false;
18096dd86faSK. Y. Srinivasan 
1817a401744SVitaly Kuznetsov 	goto out;
1824f689190SDexuan Cui err:
1837a401744SVitaly Kuznetsov 	save_errno = errno;
1844ce50e94SVaughan Cao 	if (ent) {
1854ce50e94SVaughan Cao 		strncpy(errdir, ent->mnt_dir, sizeof(errdir)-1);
1864ce50e94SVaughan Cao 		endmntent(mounts);
1874ce50e94SVaughan Cao 	}
1884f689190SDexuan Cui 	vss_operate(VSS_OP_THAW);
189*9fc3c01aSDexuan Cui 	fs_frozen = false;
1907a401744SVitaly Kuznetsov 	/* Call syslog after we thaw all filesystems */
1917a401744SVitaly Kuznetsov 	if (ent)
1927a401744SVitaly Kuznetsov 		syslog(LOG_ERR, "FREEZE of %s failed; error:%d %s",
1934ce50e94SVaughan Cao 		       errdir, save_errno, strerror(save_errno));
1947a401744SVitaly Kuznetsov 	else
1957a401744SVitaly Kuznetsov 		syslog(LOG_ERR, "FREEZE of / failed; error:%d %s", save_errno,
1967a401744SVitaly Kuznetsov 		       strerror(save_errno));
1977a401744SVitaly Kuznetsov out:
1984f689190SDexuan Cui 	return error;
19996dd86faSK. Y. Srinivasan }
20096dd86faSK. Y. Srinivasan 
print_usage(char * argv[])201170f4beaSVitaly Kuznetsov void print_usage(char *argv[])
202170f4beaSVitaly Kuznetsov {
203170f4beaSVitaly Kuznetsov 	fprintf(stderr, "Usage: %s [options]\n"
204170f4beaSVitaly Kuznetsov 		"Options are:\n"
205170f4beaSVitaly Kuznetsov 		"  -n, --no-daemon        stay in foreground, don't daemonize\n"
206170f4beaSVitaly Kuznetsov 		"  -h, --help             print this help\n", argv[0]);
207170f4beaSVitaly Kuznetsov }
208170f4beaSVitaly Kuznetsov 
main(int argc,char * argv[])209170f4beaSVitaly Kuznetsov int main(int argc, char *argv[])
21096dd86faSK. Y. Srinivasan {
211*9fc3c01aSDexuan Cui 	int vss_fd = -1, len;
21296dd86faSK. Y. Srinivasan 	int error;
21396dd86faSK. Y. Srinivasan 	struct pollfd pfd;
21496dd86faSK. Y. Srinivasan 	int	op;
215f5722b9bSVitaly Kuznetsov 	struct hv_vss_msg vss_msg[1];
216170f4beaSVitaly Kuznetsov 	int daemonize = 1, long_index = 0, opt;
217*9fc3c01aSDexuan Cui 	int in_handshake;
218cd8dc054SVitaly Kuznetsov 	__u32 kernel_modver;
21996dd86faSK. Y. Srinivasan 
220170f4beaSVitaly Kuznetsov 	static struct option long_options[] = {
221170f4beaSVitaly Kuznetsov 		{"help",	no_argument,	   0,  'h' },
222170f4beaSVitaly Kuznetsov 		{"no-daemon",	no_argument,	   0,  'n' },
223170f4beaSVitaly Kuznetsov 		{0,		0,		   0,  0   }
224170f4beaSVitaly Kuznetsov 	};
225170f4beaSVitaly Kuznetsov 
226170f4beaSVitaly Kuznetsov 	while ((opt = getopt_long(argc, argv, "hn", long_options,
227170f4beaSVitaly Kuznetsov 				  &long_index)) != -1) {
228170f4beaSVitaly Kuznetsov 		switch (opt) {
229170f4beaSVitaly Kuznetsov 		case 'n':
230170f4beaSVitaly Kuznetsov 			daemonize = 0;
231170f4beaSVitaly Kuznetsov 			break;
232170f4beaSVitaly Kuznetsov 		case 'h':
233b0995156SAdrian Vladu 			print_usage(argv);
234b0995156SAdrian Vladu 			exit(0);
235170f4beaSVitaly Kuznetsov 		default:
236170f4beaSVitaly Kuznetsov 			print_usage(argv);
237170f4beaSVitaly Kuznetsov 			exit(EXIT_FAILURE);
238170f4beaSVitaly Kuznetsov 		}
239170f4beaSVitaly Kuznetsov 	}
240170f4beaSVitaly Kuznetsov 
241170f4beaSVitaly Kuznetsov 	if (daemonize && daemon(1, 0))
242eb8905b8SOlaf Hering 		return 1;
243eb8905b8SOlaf Hering 
24496dd86faSK. Y. Srinivasan 	openlog("Hyper-V VSS", 0, LOG_USER);
24596dd86faSK. Y. Srinivasan 	syslog(LOG_INFO, "VSS starting; pid is:%d", getpid());
24696dd86faSK. Y. Srinivasan 
247*9fc3c01aSDexuan Cui reopen_vss_fd:
248*9fc3c01aSDexuan Cui 	if (vss_fd != -1)
249*9fc3c01aSDexuan Cui 		close(vss_fd);
250*9fc3c01aSDexuan Cui 	if (fs_frozen) {
251*9fc3c01aSDexuan Cui 		if (vss_operate(VSS_OP_THAW) || fs_frozen) {
252*9fc3c01aSDexuan Cui 			syslog(LOG_ERR, "failed to thaw file system: err=%d",
253*9fc3c01aSDexuan Cui 			       errno);
254*9fc3c01aSDexuan Cui 			exit(EXIT_FAILURE);
255*9fc3c01aSDexuan Cui 		}
256*9fc3c01aSDexuan Cui 	}
257*9fc3c01aSDexuan Cui 
258*9fc3c01aSDexuan Cui 	in_handshake = 1;
259f5722b9bSVitaly Kuznetsov 	vss_fd = open("/dev/vmbus/hv_vss", O_RDWR);
260f5722b9bSVitaly Kuznetsov 	if (vss_fd < 0) {
261f5722b9bSVitaly Kuznetsov 		syslog(LOG_ERR, "open /dev/vmbus/hv_vss failed; error: %d %s",
2625c289269STomas Hozza 		       errno, strerror(errno));
26396dd86faSK. Y. Srinivasan 		exit(EXIT_FAILURE);
26496dd86faSK. Y. Srinivasan 	}
26596dd86faSK. Y. Srinivasan 	/*
26696dd86faSK. Y. Srinivasan 	 * Register ourselves with the kernel.
26796dd86faSK. Y. Srinivasan 	 */
268f5722b9bSVitaly Kuznetsov 	vss_msg->vss_hdr.operation = VSS_OP_REGISTER1;
26996dd86faSK. Y. Srinivasan 
270f5722b9bSVitaly Kuznetsov 	len = write(vss_fd, vss_msg, sizeof(struct hv_vss_msg));
27196dd86faSK. Y. Srinivasan 	if (len < 0) {
272f5722b9bSVitaly Kuznetsov 		syslog(LOG_ERR, "registration to kernel failed; error: %d %s",
273f5722b9bSVitaly Kuznetsov 		       errno, strerror(errno));
274f5722b9bSVitaly Kuznetsov 		close(vss_fd);
27596dd86faSK. Y. Srinivasan 		exit(EXIT_FAILURE);
27696dd86faSK. Y. Srinivasan 	}
27796dd86faSK. Y. Srinivasan 
278f5722b9bSVitaly Kuznetsov 	pfd.fd = vss_fd;
27996dd86faSK. Y. Srinivasan 
28096dd86faSK. Y. Srinivasan 	while (1) {
28196dd86faSK. Y. Srinivasan 		pfd.events = POLLIN;
28296dd86faSK. Y. Srinivasan 		pfd.revents = 0;
2839561d479STomas Hozza 
2849561d479STomas Hozza 		if (poll(&pfd, 1, -1) < 0) {
2859561d479STomas Hozza 			syslog(LOG_ERR, "poll failed; error:%d %s", errno, strerror(errno));
2869561d479STomas Hozza 			if (errno == EINVAL) {
287f5722b9bSVitaly Kuznetsov 				close(vss_fd);
2889561d479STomas Hozza 				exit(EXIT_FAILURE);
2899561d479STomas Hozza 			}
2909561d479STomas Hozza 			else
2919561d479STomas Hozza 				continue;
2929561d479STomas Hozza 		}
29396dd86faSK. Y. Srinivasan 
294f5722b9bSVitaly Kuznetsov 		len = read(vss_fd, vss_msg, sizeof(struct hv_vss_msg));
29596dd86faSK. Y. Srinivasan 
296cd8dc054SVitaly Kuznetsov 		if (in_handshake) {
297cd8dc054SVitaly Kuznetsov 			if (len != sizeof(kernel_modver)) {
298cd8dc054SVitaly Kuznetsov 				syslog(LOG_ERR, "invalid version negotiation");
299cd8dc054SVitaly Kuznetsov 				exit(EXIT_FAILURE);
300cd8dc054SVitaly Kuznetsov 			}
301cd8dc054SVitaly Kuznetsov 			kernel_modver = *(__u32 *)vss_msg;
302cd8dc054SVitaly Kuznetsov 			in_handshake = 0;
303cd8dc054SVitaly Kuznetsov 			syslog(LOG_INFO, "VSS: kernel module version: %d",
304cd8dc054SVitaly Kuznetsov 			       kernel_modver);
305cd8dc054SVitaly Kuznetsov 			continue;
306cd8dc054SVitaly Kuznetsov 		}
307cd8dc054SVitaly Kuznetsov 
308f5722b9bSVitaly Kuznetsov 		if (len != sizeof(struct hv_vss_msg)) {
309f5722b9bSVitaly Kuznetsov 			syslog(LOG_ERR, "read failed; error:%d %s",
310f5722b9bSVitaly Kuznetsov 			       errno, strerror(errno));
311*9fc3c01aSDexuan Cui 			goto reopen_vss_fd;
31296dd86faSK. Y. Srinivasan 		}
31396dd86faSK. Y. Srinivasan 
31496dd86faSK. Y. Srinivasan 		op = vss_msg->vss_hdr.operation;
31596dd86faSK. Y. Srinivasan 		error =  HV_S_OK;
31696dd86faSK. Y. Srinivasan 
31796dd86faSK. Y. Srinivasan 		switch (op) {
31896dd86faSK. Y. Srinivasan 		case VSS_OP_FREEZE:
31996dd86faSK. Y. Srinivasan 		case VSS_OP_THAW:
32096dd86faSK. Y. Srinivasan 			error = vss_operate(op);
3214f689190SDexuan Cui 			syslog(LOG_INFO, "VSS: op=%s: %s\n",
3224f689190SDexuan Cui 				op == VSS_OP_FREEZE ? "FREEZE" : "THAW",
3234f689190SDexuan Cui 				error ? "failed" : "succeeded");
3244f689190SDexuan Cui 
3254f689190SDexuan Cui 			if (error) {
32696dd86faSK. Y. Srinivasan 				error = HV_E_FAIL;
3274f689190SDexuan Cui 				syslog(LOG_ERR, "op=%d failed!", op);
3284f689190SDexuan Cui 				syslog(LOG_ERR, "report it with these files:");
3294f689190SDexuan Cui 				syslog(LOG_ERR, "/etc/fstab and /proc/mounts");
3304f689190SDexuan Cui 			}
33196dd86faSK. Y. Srinivasan 			break;
332db886e4dSAlex Ng 		case VSS_OP_HOT_BACKUP:
333db886e4dSAlex Ng 			syslog(LOG_INFO, "VSS: op=CHECK HOT BACKUP\n");
334db886e4dSAlex Ng 			break;
33596dd86faSK. Y. Srinivasan 		default:
33696dd86faSK. Y. Srinivasan 			syslog(LOG_ERR, "Illegal op:%d\n", op);
33796dd86faSK. Y. Srinivasan 		}
338*9fc3c01aSDexuan Cui 
339*9fc3c01aSDexuan Cui 		/*
340*9fc3c01aSDexuan Cui 		 * The write() may return an error due to the faked VSS_OP_THAW
341*9fc3c01aSDexuan Cui 		 * message upon hibernation. Ignore the error by resetting the
342*9fc3c01aSDexuan Cui 		 * dev file, i.e. closing and re-opening it.
343*9fc3c01aSDexuan Cui 		 */
34496dd86faSK. Y. Srinivasan 		vss_msg->error = error;
345a689d251SDexuan Cui 		len = write(vss_fd, vss_msg, sizeof(struct hv_vss_msg));
346f5722b9bSVitaly Kuznetsov 		if (len != sizeof(struct hv_vss_msg)) {
347f5722b9bSVitaly Kuznetsov 			syslog(LOG_ERR, "write failed; error: %d %s", errno,
348f5722b9bSVitaly Kuznetsov 			       strerror(errno));
349*9fc3c01aSDexuan Cui 			goto reopen_vss_fd;
35096dd86faSK. Y. Srinivasan 		}
35196dd86faSK. Y. Srinivasan 	}
35296dd86faSK. Y. Srinivasan 
353f5722b9bSVitaly Kuznetsov 	close(vss_fd);
354f5722b9bSVitaly Kuznetsov 	exit(0);
35596dd86faSK. Y. Srinivasan }
356