summary refs log tree commit diff
path: root/tools
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-14 16:43:47 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-14 16:43:47 -0800
commit6ae840e7cc4be0be3aa40d9f67c35c75cfc67d83 (patch)
tree9c83c87a8670ef678d95f8d6f76a07f24a09a49f /tools
parente6b5be2be4e30037eb551e0ed09dd97bd00d85d3 (diff)
parent91905b6f4afe51e23a3f58df93e4cdc5e49cf40c (diff)
downloadlinux-6ae840e7cc4be0be3aa40d9f67c35c75cfc67d83.tar.gz
Merge tag 'char-misc-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc driver updates from Greg KH:
 "Here's the big char/misc driver update for 3.19-rc1

  Lots of little things all over the place in different drivers, and a
  new subsystem, "coresight" has been added.  Full details are in the
  shortlog"

* tag 'char-misc-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (73 commits)
  parport: parport_pc, do not remove parent devices early
  spmi: Remove shutdown/suspend/resume kernel-doc
  carma-fpga-program: drop videobuf dependency
  carma-fpga: drop videobuf dependency
  carma-fpga-program.c: fix compile errors
  i8k: Fix temperature bug handling in i8k_get_temp()
  cxl: Name interrupts in /proc/interrupt
  CXL: Return error to PSL if IRQ demultiplexing fails & print clearer warning
  coresight-replicator: remove .owner field for driver
  coresight: fixed comments in coresight.h
  coresight: fix typo in comment in coresight-priv.h
  coresight: bindings for coresight drivers
  coresight: Adding ABI documentation
  w1: support auto-load of w1_bq27000 module.
  w1: avoid potential u16 overflow
  cn: verify msg->len before making callback
  mei: export fw status registers through sysfs
  mei: read and print all six FW status registers
  mei: txe: add cherrytrail device id
  mei: kill cached host and me csr values
  ...
Diffstat (limited to 'tools')
-rw-r--r--tools/hv/hv_fcopy_daemon.c33
-rw-r--r--tools/hv/hv_kvp_daemon.c48
-rw-r--r--tools/hv/hv_vss_daemon.c95
3 files changed, 159 insertions, 17 deletions
diff --git a/tools/hv/hv_fcopy_daemon.c b/tools/hv/hv_fcopy_daemon.c
index 8f96b3ee0724..f437d739f37d 100644
--- a/tools/hv/hv_fcopy_daemon.c
+++ b/tools/hv/hv_fcopy_daemon.c
@@ -33,6 +33,7 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <dirent.h>
+#include <getopt.h>
 
 static int target_fd;
 static char target_fname[W_MAX_PATH];
@@ -126,15 +127,43 @@ static int hv_copy_cancel(void)
 
 }
 
-int main(void)
+void print_usage(char *argv[])
+{
+	fprintf(stderr, "Usage: %s [options]\n"
+		"Options are:\n"
+		"  -n, --no-daemon        stay in foreground, don't daemonize\n"
+		"  -h, --help             print this help\n", argv[0]);
+}
+
+int main(int argc, char *argv[])
 {
 	int fd, fcopy_fd, len;
 	int error;
+	int daemonize = 1, long_index = 0, opt;
 	int version = FCOPY_CURRENT_VERSION;
 	char *buffer[4096 * 2];
 	struct hv_fcopy_hdr *in_msg;
 
-	if (daemon(1, 0)) {
+	static struct option long_options[] = {
+		{"help",	no_argument,	   0,  'h' },
+		{"no-daemon",	no_argument,	   0,  'n' },
+		{0,		0,		   0,  0   }
+	};
+
+	while ((opt = getopt_long(argc, argv, "hn", long_options,
+				  &long_index)) != -1) {
+		switch (opt) {
+		case 'n':
+			daemonize = 0;
+			break;
+		case 'h':
+		default:
+			print_usage(argv);
+			exit(EXIT_FAILURE);
+		}
+	}
+
+	if (daemonize && daemon(1, 0)) {
 		syslog(LOG_ERR, "daemon() failed; error: %s", strerror(errno));
 		exit(EXIT_FAILURE);
 	}
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 4088b816a3ee..6a6432a20a1d 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -43,6 +43,7 @@
 #include <fcntl.h>
 #include <dirent.h>
 #include <net/if.h>
+#include <getopt.h>
 
 /*
  * KVP protocol: The user mode component first registers with the
@@ -1417,7 +1418,15 @@ netlink_send(int fd, struct cn_msg *msg)
 	return sendmsg(fd, &message, 0);
 }
 
-int main(void)
+void print_usage(char *argv[])
+{
+	fprintf(stderr, "Usage: %s [options]\n"
+		"Options are:\n"
+		"  -n, --no-daemon        stay in foreground, don't daemonize\n"
+		"  -h, --help             print this help\n", argv[0]);
+}
+
+int main(int argc, char *argv[])
 {
 	int fd, len, nl_group;
 	int error;
@@ -1435,9 +1444,30 @@ int main(void)
 	struct hv_kvp_ipaddr_value *kvp_ip_val;
 	char *kvp_recv_buffer;
 	size_t kvp_recv_buffer_len;
+	int daemonize = 1, long_index = 0, opt;
+
+	static struct option long_options[] = {
+		{"help",	no_argument,	   0,  'h' },
+		{"no-daemon",	no_argument,	   0,  'n' },
+		{0,		0,		   0,  0   }
+	};
+
+	while ((opt = getopt_long(argc, argv, "hn", long_options,
+				  &long_index)) != -1) {
+		switch (opt) {
+		case 'n':
+			daemonize = 0;
+			break;
+		case 'h':
+		default:
+			print_usage(argv);
+			exit(EXIT_FAILURE);
+		}
+	}
 
-	if (daemon(1, 0))
+	if (daemonize && daemon(1, 0))
 		return 1;
+
 	openlog("KVP", 0, LOG_USER);
 	syslog(LOG_INFO, "KVP starting; pid is:%d", getpid());
 
@@ -1529,8 +1559,15 @@ int main(void)
 				addr_p, &addr_l);
 
 		if (len < 0) {
+			int saved_errno = errno;
 			syslog(LOG_ERR, "recvfrom failed; pid:%u error:%d %s",
 					addr.nl_pid, errno, strerror(errno));
+
+			if (saved_errno == ENOBUFS) {
+				syslog(LOG_ERR, "receive error: ignored");
+				continue;
+			}
+
 			close(fd);
 			return -1;
 		}
@@ -1733,8 +1770,15 @@ kvp_done:
 
 		len = netlink_send(fd, incoming_cn_msg);
 		if (len < 0) {
+			int saved_errno = errno;
 			syslog(LOG_ERR, "net_link send failed; error: %d %s", errno,
 					strerror(errno));
+
+			if (saved_errno == ENOMEM || saved_errno == ENOBUFS) {
+				syslog(LOG_ERR, "send error: ignored");
+				continue;
+			}
+
 			exit(EXIT_FAILURE);
 		}
 	}
diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c
index 6a213b8cd7b9..5e63f70bd956 100644
--- a/tools/hv/hv_vss_daemon.c
+++ b/tools/hv/hv_vss_daemon.c
@@ -36,6 +36,7 @@
 #include <linux/hyperv.h>
 #include <linux/netlink.h>
 #include <syslog.h>
+#include <getopt.h>
 
 static struct sockaddr_nl addr;
 
@@ -44,35 +45,51 @@ static struct sockaddr_nl addr;
 #endif
 
 
-static int vss_do_freeze(char *dir, unsigned int cmd, char *fs_op)
+/* Don't use syslog() in the function since that can cause write to disk */
+static int vss_do_freeze(char *dir, unsigned int cmd)
 {
 	int ret, fd = open(dir, O_RDONLY);
 
 	if (fd < 0)
 		return 1;
+
 	ret = ioctl(fd, cmd, 0);
-	syslog(LOG_INFO, "VSS: %s of %s: %s\n", fs_op, dir, strerror(errno));
+
+	/*
+	 * If a partition is mounted more than once, only the first
+	 * FREEZE/THAW can succeed and the later ones will get
+	 * EBUSY/EINVAL respectively: there could be 2 cases:
+	 * 1) a user may mount the same partition to differnt directories
+	 *  by mistake or on purpose;
+	 * 2) The subvolume of btrfs appears to have the same partition
+	 * mounted more than once.
+	 */
+	if (ret) {
+		if ((cmd == FIFREEZE && errno == EBUSY) ||
+		    (cmd == FITHAW && errno == EINVAL)) {
+			close(fd);
+			return 0;
+		}
+	}
+
 	close(fd);
 	return !!ret;
 }
 
 static int vss_operate(int operation)
 {
-	char *fs_op;
 	char match[] = "/dev/";
 	FILE *mounts;
 	struct mntent *ent;
 	unsigned int cmd;
-	int error = 0, root_seen = 0;
+	int error = 0, root_seen = 0, save_errno = 0;
 
 	switch (operation) {
 	case VSS_OP_FREEZE:
 		cmd = FIFREEZE;
-		fs_op = "freeze";
 		break;
 	case VSS_OP_THAW:
 		cmd = FITHAW;
-		fs_op = "thaw";
 		break;
 	default:
 		return -1;
@@ -85,7 +102,7 @@ static int vss_operate(int operation)
 	while ((ent = getmntent(mounts))) {
 		if (strncmp(ent->mnt_fsname, match, strlen(match)))
 			continue;
-		if (strcmp(ent->mnt_type, "iso9660") == 0)
+		if (hasmntopt(ent, MNTOPT_RO) != NULL)
 			continue;
 		if (strcmp(ent->mnt_type, "vfat") == 0)
 			continue;
@@ -93,14 +110,30 @@ static int vss_operate(int operation)
 			root_seen = 1;
 			continue;
 		}
-		error |= vss_do_freeze(ent->mnt_dir, cmd, fs_op);
+		error |= vss_do_freeze(ent->mnt_dir, cmd);
+		if (error && operation == VSS_OP_FREEZE)
+			goto err;
 	}
-	endmntent(mounts);
 
 	if (root_seen) {
-		error |= vss_do_freeze("/", cmd, fs_op);
+		error |= vss_do_freeze("/", cmd);
+		if (error && operation == VSS_OP_FREEZE)
+			goto err;
 	}
 
+	goto out;
+err:
+	save_errno = errno;
+	vss_operate(VSS_OP_THAW);
+	/* Call syslog after we thaw all filesystems */
+	if (ent)
+		syslog(LOG_ERR, "FREEZE of %s failed; error:%d %s",
+		       ent->mnt_dir, save_errno, strerror(save_errno));
+	else
+		syslog(LOG_ERR, "FREEZE of / failed; error:%d %s", save_errno,
+		       strerror(save_errno));
+out:
+	endmntent(mounts);
 	return error;
 }
 
@@ -131,7 +164,15 @@ static int netlink_send(int fd, struct cn_msg *msg)
 	return sendmsg(fd, &message, 0);
 }
 
-int main(void)
+void print_usage(char *argv[])
+{
+	fprintf(stderr, "Usage: %s [options]\n"
+		"Options are:\n"
+		"  -n, --no-daemon        stay in foreground, don't daemonize\n"
+		"  -h, --help             print this help\n", argv[0]);
+}
+
+int main(int argc, char *argv[])
 {
 	int fd, len, nl_group;
 	int error;
@@ -143,8 +184,28 @@ int main(void)
 	struct hv_vss_msg *vss_msg;
 	char *vss_recv_buffer;
 	size_t vss_recv_buffer_len;
+	int daemonize = 1, long_index = 0, opt;
+
+	static struct option long_options[] = {
+		{"help",	no_argument,	   0,  'h' },
+		{"no-daemon",	no_argument,	   0,  'n' },
+		{0,		0,		   0,  0   }
+	};
+
+	while ((opt = getopt_long(argc, argv, "hn", long_options,
+				  &long_index)) != -1) {
+		switch (opt) {
+		case 'n':
+			daemonize = 0;
+			break;
+		case 'h':
+		default:
+			print_usage(argv);
+			exit(EXIT_FAILURE);
+		}
+	}
 
-	if (daemon(1, 0))
+	if (daemonize && daemon(1, 0))
 		return 1;
 
 	openlog("Hyper-V VSS", 0, LOG_USER);
@@ -249,8 +310,16 @@ int main(void)
 		case VSS_OP_FREEZE:
 		case VSS_OP_THAW:
 			error = vss_operate(op);
-			if (error)
+			syslog(LOG_INFO, "VSS: op=%s: %s\n",
+				op == VSS_OP_FREEZE ? "FREEZE" : "THAW",
+				error ? "failed" : "succeeded");
+
+			if (error) {
 				error = HV_E_FAIL;
+				syslog(LOG_ERR, "op=%d failed!", op);
+				syslog(LOG_ERR, "report it with these files:");
+				syslog(LOG_ERR, "/etc/fstab and /proc/mounts");
+			}
 			break;
 		default:
 			syslog(LOG_ERR, "Illegal op:%d\n", op);