Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * An implementation of the host initiated guest snapshot for Hyper-V.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2013, Microsoft, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Author : K. Y. Srinivasan <kys@microsoft.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <sys/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <sys/poll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <sys/ioctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <sys/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <sys/sysmacros.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <mntent.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <linux/major.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #include <linux/hyperv.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include <syslog.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #include <getopt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #include <stdbool.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #include <dirent.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) static bool fs_frozen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) /* Don't use syslog() in the function since that can cause write to disk */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) static int vss_do_freeze(char *dir, unsigned int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	int ret, fd = open(dir, O_RDONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	if (fd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	ret = ioctl(fd, cmd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	 * If a partition is mounted more than once, only the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	 * FREEZE/THAW can succeed and the later ones will get
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	 * EBUSY/EINVAL respectively: there could be 2 cases:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	 * 1) a user may mount the same partition to different directories
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	 *  by mistake or on purpose;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	 * 2) The subvolume of btrfs appears to have the same partition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	 * mounted more than once.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 		if ((cmd == FIFREEZE && errno == EBUSY) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 		    (cmd == FITHAW && errno == EINVAL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 			close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	return !!ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) static bool is_dev_loop(const char *blkname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	char *buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	DIR *dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	struct dirent *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	bool ret = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	buffer = malloc(PATH_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	if (!buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		syslog(LOG_ERR, "Can't allocate memory!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		exit(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	snprintf(buffer, PATH_MAX, "%s/loop", blkname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	if (!access(buffer, R_OK | X_OK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		ret = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		goto free_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	} else if (errno != ENOENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		syslog(LOG_ERR, "Can't access: %s; error:%d %s!",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		       buffer, errno, strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	snprintf(buffer, PATH_MAX, "%s/slaves", blkname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	dir = opendir(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	if (!dir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		if (errno != ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 			syslog(LOG_ERR, "Can't opendir: %s; error:%d %s!",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 			       buffer, errno, strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		goto free_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	while ((entry = readdir(dir)) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		if (strcmp(entry->d_name, ".") == 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 		    strcmp(entry->d_name, "..") == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		snprintf(buffer, PATH_MAX, "%s/slaves/%s", blkname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 			 entry->d_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		if (is_dev_loop(buffer)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 			ret = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	closedir(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) free_buffer:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	free(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static int vss_operate(int operation)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	char match[] = "/dev/";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	FILE *mounts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	struct mntent *ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	struct stat sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	char errdir[1024] = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	char blkdir[23]; /* /sys/dev/block/XXX:XXX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	unsigned int cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	int error = 0, root_seen = 0, save_errno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	switch (operation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	case VSS_OP_FREEZE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		cmd = FIFREEZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	case VSS_OP_THAW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		cmd = FITHAW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	mounts = setmntent("/proc/mounts", "r");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	if (mounts == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	while ((ent = getmntent(mounts))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		if (strncmp(ent->mnt_fsname, match, strlen(match)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		if (stat(ent->mnt_fsname, &sb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 			syslog(LOG_ERR, "Can't stat: %s; error:%d %s!",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 			       ent->mnt_fsname, errno, strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 			sprintf(blkdir, "/sys/dev/block/%d:%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 				major(sb.st_rdev), minor(sb.st_rdev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 			if (is_dev_loop(blkdir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		if (hasmntopt(ent, MNTOPT_RO) != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		if (strcmp(ent->mnt_type, "vfat") == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		if (strcmp(ent->mnt_dir, "/") == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 			root_seen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		error |= vss_do_freeze(ent->mnt_dir, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		if (operation == VSS_OP_FREEZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 			if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 				goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 			fs_frozen = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	endmntent(mounts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	if (root_seen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		error |= vss_do_freeze("/", cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		if (operation == VSS_OP_FREEZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 			if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 				goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 			fs_frozen = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	if (operation == VSS_OP_THAW && !error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		fs_frozen = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	save_errno = errno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	if (ent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		strncpy(errdir, ent->mnt_dir, sizeof(errdir)-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		endmntent(mounts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	vss_operate(VSS_OP_THAW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	fs_frozen = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	/* Call syslog after we thaw all filesystems */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	if (ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		syslog(LOG_ERR, "FREEZE of %s failed; error:%d %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		       errdir, save_errno, strerror(save_errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		syslog(LOG_ERR, "FREEZE of / failed; error:%d %s", save_errno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		       strerror(save_errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) void print_usage(char *argv[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	fprintf(stderr, "Usage: %s [options]\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 		"Options are:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		"  -n, --no-daemon        stay in foreground, don't daemonize\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		"  -h, --help             print this help\n", argv[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) int main(int argc, char *argv[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	int vss_fd = -1, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	struct pollfd pfd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	int	op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	struct hv_vss_msg vss_msg[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	int daemonize = 1, long_index = 0, opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	int in_handshake;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	__u32 kernel_modver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	static struct option long_options[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		{"help",	no_argument,	   0,  'h' },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 		{"no-daemon",	no_argument,	   0,  'n' },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 		{0,		0,		   0,  0   }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	while ((opt = getopt_long(argc, argv, "hn", long_options,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 				  &long_index)) != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		switch (opt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		case 'n':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 			daemonize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		case 'h':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 			print_usage(argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 			exit(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 			print_usage(argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 			exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	if (daemonize && daemon(1, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	openlog("Hyper-V VSS", 0, LOG_USER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	syslog(LOG_INFO, "VSS starting; pid is:%d", getpid());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) reopen_vss_fd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	if (vss_fd != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 		close(vss_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	if (fs_frozen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		if (vss_operate(VSS_OP_THAW) || fs_frozen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 			syslog(LOG_ERR, "failed to thaw file system: err=%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 			       errno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 			exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	in_handshake = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	vss_fd = open("/dev/vmbus/hv_vss", O_RDWR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	if (vss_fd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		syslog(LOG_ERR, "open /dev/vmbus/hv_vss failed; error: %d %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		       errno, strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 		exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	 * Register ourselves with the kernel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	vss_msg->vss_hdr.operation = VSS_OP_REGISTER1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	len = write(vss_fd, vss_msg, sizeof(struct hv_vss_msg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	if (len < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		syslog(LOG_ERR, "registration to kernel failed; error: %d %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		       errno, strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 		close(vss_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 		exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	pfd.fd = vss_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		pfd.events = POLLIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 		pfd.revents = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		if (poll(&pfd, 1, -1) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 			syslog(LOG_ERR, "poll failed; error:%d %s", errno, strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 			if (errno == EINVAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 				close(vss_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 				exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		len = read(vss_fd, vss_msg, sizeof(struct hv_vss_msg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		if (in_handshake) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 			if (len != sizeof(kernel_modver)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 				syslog(LOG_ERR, "invalid version negotiation");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 				exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 			kernel_modver = *(__u32 *)vss_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 			in_handshake = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 			syslog(LOG_INFO, "VSS: kernel module version: %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 			       kernel_modver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		if (len != sizeof(struct hv_vss_msg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 			syslog(LOG_ERR, "read failed; error:%d %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 			       errno, strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 			goto reopen_vss_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		op = vss_msg->vss_hdr.operation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 		error =  HV_S_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 		switch (op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 		case VSS_OP_FREEZE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 		case VSS_OP_THAW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 			error = vss_operate(op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 			syslog(LOG_INFO, "VSS: op=%s: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 				op == VSS_OP_FREEZE ? "FREEZE" : "THAW",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 				error ? "failed" : "succeeded");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 			if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 				error = HV_E_FAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 				syslog(LOG_ERR, "op=%d failed!", op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 				syslog(LOG_ERR, "report it with these files:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 				syslog(LOG_ERR, "/etc/fstab and /proc/mounts");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 		case VSS_OP_HOT_BACKUP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 			syslog(LOG_INFO, "VSS: op=CHECK HOT BACKUP\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 			syslog(LOG_ERR, "Illegal op:%d\n", op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		 * The write() may return an error due to the faked VSS_OP_THAW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		 * message upon hibernation. Ignore the error by resetting the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 		 * dev file, i.e. closing and re-opening it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 		vss_msg->error = error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 		len = write(vss_fd, vss_msg, sizeof(struct hv_vss_msg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		if (len != sizeof(struct hv_vss_msg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 			syslog(LOG_ERR, "write failed; error: %d %s", errno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 			       strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 			goto reopen_vss_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	close(vss_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	exit(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }