diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/hv/hv_kvp_daemon.c | 16 | ||||
| -rw-r--r-- | tools/hv/hv_vss_daemon.c | 249 | ||||
| -rw-r--r-- | tools/power/x86/turbostat/turbostat.c | 5 | ||||
| -rwxr-xr-x | tools/testing/ktest/ktest.pl | 14 | 
4 files changed, 277 insertions, 7 deletions
| diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index c800ea4c8bf..5a1f6489d18 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c @@ -102,6 +102,10 @@ static struct utsname uts_buf;  #define MAX_FILE_NAME 100  #define ENTRIES_PER_BLOCK 50 +#ifndef SOL_NETLINK +#define SOL_NETLINK 270 +#endif +  struct kvp_record {  	char key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];  	char value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; @@ -1407,7 +1411,7 @@ netlink_send(int fd, struct cn_msg *msg)  int main(void)  { -	int fd, len, sock_opt; +	int fd, len, nl_group;  	int error;  	struct cn_msg *message;  	struct pollfd pfd; @@ -1443,7 +1447,7 @@ int main(void)  	addr.nl_family = AF_NETLINK;  	addr.nl_pad = 0;  	addr.nl_pid = 0; -	addr.nl_groups = CN_KVP_IDX; +	addr.nl_groups = 0;  	error = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); @@ -1452,8 +1456,8 @@ int main(void)  		close(fd);  		exit(EXIT_FAILURE);  	} -	sock_opt = addr.nl_groups; -	setsockopt(fd, 270, 1, &sock_opt, sizeof(sock_opt)); +	nl_group = CN_KVP_IDX; +	setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &nl_group, sizeof(nl_group));  	/*  	 * Register ourselves with the kernel.  	 */ @@ -1499,6 +1503,10 @@ int main(void)  		}  		incoming_msg = (struct nlmsghdr *)kvp_recv_buffer; + +		if (incoming_msg->nlmsg_type != NLMSG_DONE) +			continue; +  		incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg);  		hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data; diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c new file mode 100644 index 00000000000..fea03a3edaf --- /dev/null +++ b/tools/hv/hv_vss_daemon.c @@ -0,0 +1,249 @@ +/* + * An implementation of the host initiated guest snapshot for Hyper-V. + * + * + * Copyright (C) 2013, Microsoft, Inc. + * Author : K. Y. Srinivasan <kys@microsoft.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT.  See the GNU General Public License for more + * details. + * + */ + + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/poll.h> +#include <sys/ioctl.h> +#include <linux/types.h> +#include <fcntl.h> +#include <stdio.h> +#include <mntent.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> +#include <arpa/inet.h> +#include <linux/fs.h> +#include <linux/connector.h> +#include <linux/hyperv.h> +#include <linux/netlink.h> +#include <syslog.h> + +static char vss_recv_buffer[4096]; +static char vss_send_buffer[4096]; +static struct sockaddr_nl addr; + +#ifndef SOL_NETLINK +#define SOL_NETLINK 270 +#endif + + +static int vss_do_freeze(char *dir, unsigned int cmd, char *fs_op) +{ +	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)); +	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; + +	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; +	} + +	mounts = setmntent("/proc/mounts", "r"); +	if (mounts == NULL) +		return -1; + +	while ((ent = getmntent(mounts))) { +		if (strncmp(ent->mnt_fsname, match, strlen(match))) +			continue; +		if (strcmp(ent->mnt_type, "iso9660") == 0) +			continue; +		if (strcmp(ent->mnt_dir, "/") == 0) { +			root_seen = 1; +			continue; +		} +		error |= vss_do_freeze(ent->mnt_dir, cmd, fs_op); +	} +	endmntent(mounts); + +	if (root_seen) { +		error |= vss_do_freeze("/", cmd, fs_op); +	} + +	return error; +} + +static int netlink_send(int fd, struct cn_msg *msg) +{ +	struct nlmsghdr *nlh; +	unsigned int size; +	struct msghdr message; +	char buffer[64]; +	struct iovec iov[2]; + +	size = NLMSG_SPACE(sizeof(struct cn_msg) + msg->len); + +	nlh = (struct nlmsghdr *)buffer; +	nlh->nlmsg_seq = 0; +	nlh->nlmsg_pid = getpid(); +	nlh->nlmsg_type = NLMSG_DONE; +	nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(*nlh)); +	nlh->nlmsg_flags = 0; + +	iov[0].iov_base = nlh; +	iov[0].iov_len = sizeof(*nlh); + +	iov[1].iov_base = msg; +	iov[1].iov_len = size; + +	memset(&message, 0, sizeof(message)); +	message.msg_name = &addr; +	message.msg_namelen = sizeof(addr); +	message.msg_iov = iov; +	message.msg_iovlen = 2; + +	return sendmsg(fd, &message, 0); +} + +int main(void) +{ +	int fd, len, nl_group; +	int error; +	struct cn_msg *message; +	struct pollfd pfd; +	struct nlmsghdr *incoming_msg; +	struct cn_msg	*incoming_cn_msg; +	int	op; +	struct hv_vss_msg *vss_msg; + +	if (daemon(1, 0)) +		return 1; + +	openlog("Hyper-V VSS", 0, LOG_USER); +	syslog(LOG_INFO, "VSS starting; pid is:%d", getpid()); + +	fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); +	if (fd < 0) { +		syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd); +		exit(EXIT_FAILURE); +	} +	addr.nl_family = AF_NETLINK; +	addr.nl_pad = 0; +	addr.nl_pid = 0; +	addr.nl_groups = 0; + + +	error = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); +	if (error < 0) { +		syslog(LOG_ERR, "bind failed; error:%d", error); +		close(fd); +		exit(EXIT_FAILURE); +	} +	nl_group = CN_VSS_IDX; +	setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &nl_group, sizeof(nl_group)); +	/* +	 * Register ourselves with the kernel. +	 */ +	message = (struct cn_msg *)vss_send_buffer; +	message->id.idx = CN_VSS_IDX; +	message->id.val = CN_VSS_VAL; +	message->ack = 0; +	vss_msg = (struct hv_vss_msg *)message->data; +	vss_msg->vss_hdr.operation = VSS_OP_REGISTER; + +	message->len = sizeof(struct hv_vss_msg); + +	len = netlink_send(fd, message); +	if (len < 0) { +		syslog(LOG_ERR, "netlink_send failed; error:%d", len); +		close(fd); +		exit(EXIT_FAILURE); +	} + +	pfd.fd = fd; + +	while (1) { +		struct sockaddr *addr_p = (struct sockaddr *) &addr; +		socklen_t addr_l = sizeof(addr); +		pfd.events = POLLIN; +		pfd.revents = 0; +		poll(&pfd, 1, -1); + +		len = recvfrom(fd, vss_recv_buffer, sizeof(vss_recv_buffer), 0, +				addr_p, &addr_l); + +		if (len < 0) { +			syslog(LOG_ERR, "recvfrom failed; pid:%u error:%d %s", +					addr.nl_pid, errno, strerror(errno)); +			close(fd); +			return -1; +		} + +		if (addr.nl_pid) { +			syslog(LOG_WARNING, +				"Received packet from untrusted pid:%u", +				addr.nl_pid); +			continue; +		} + +		incoming_msg = (struct nlmsghdr *)vss_recv_buffer; + +		if (incoming_msg->nlmsg_type != NLMSG_DONE) +			continue; + +		incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg); +		vss_msg = (struct hv_vss_msg *)incoming_cn_msg->data; +		op = vss_msg->vss_hdr.operation; +		error =  HV_S_OK; + +		switch (op) { +		case VSS_OP_FREEZE: +		case VSS_OP_THAW: +			error = vss_operate(op); +			if (error) +				error = HV_E_FAIL; +			break; +		default: +			syslog(LOG_ERR, "Illegal op:%d\n", op); +		} +		vss_msg->error = error; +		len = netlink_send(fd, incoming_cn_msg); +		if (len < 0) { +			syslog(LOG_ERR, "net_link send failed; error:%d", len); +			exit(EXIT_FAILURE); +		} +	} + +} diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 6f3214ed444..321e066a075 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -1421,6 +1421,7 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model)  	case 0x3C:	/* HSW */  	case 0x3F:	/* HSW */  	case 0x45:	/* HSW */ +	case 0x46:	/* HSW */  		return 1;  	case 0x2E:	/* Nehalem-EX Xeon - Beckton */  	case 0x2F:	/* Westmere-EX Xeon - Eagleton */ @@ -1515,6 +1516,7 @@ void rapl_probe(unsigned int family, unsigned int model)  	case 0x3C:	/* HSW */  	case 0x3F:	/* HSW */  	case 0x45:	/* HSW */ +	case 0x46:	/* HSW */  		do_rapl = RAPL_PKG | RAPL_CORES | RAPL_GFX;  		break;  	case 0x2D: @@ -1754,6 +1756,7 @@ int is_snb(unsigned int family, unsigned int model)  	case 0x3C:	/* HSW */  	case 0x3F:	/* HSW */  	case 0x45:	/* HSW */ +	case 0x46:	/* HSW */  		return 1;  	}  	return 0; @@ -2276,7 +2279,7 @@ int main(int argc, char **argv)  	cmdline(argc, argv);  	if (verbose) -		fprintf(stderr, "turbostat v3.2 February 11, 2013" +		fprintf(stderr, "turbostat v3.3 March 15, 2013"  			" - Len Brown <lenb@kernel.org>\n");  	turbostat_init(); diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 4e67d52eb3a..0d7fd8b5154 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -73,6 +73,7 @@ my $ktest_config;  my $version;  my $have_version = 0;  my $machine; +my $last_machine;  my $ssh_user;  my $tmpdir;  my $builddir; @@ -108,6 +109,7 @@ my $scp_to_target;  my $scp_to_target_install;  my $power_off;  my $grub_menu; +my $last_grub_menu;  my $grub_file;  my $grub_number;  my $grub_reboot; @@ -1538,7 +1540,9 @@ sub run_scp_mod {  sub get_grub2_index { -    return if (defined($grub_number)); +    return if (defined($grub_number) && defined($last_grub_menu) && +	       $last_grub_menu eq $grub_menu && defined($last_machine) && +	       $last_machine eq $machine);      doprint "Find grub2 menu ... ";      $grub_number = -1; @@ -1565,6 +1569,8 @@ sub get_grub2_index {      die "Could not find '$grub_menu' in $grub_file on $machine"  	if (!$found);      doprint "$grub_number\n"; +    $last_grub_menu = $grub_menu; +    $last_machine = $machine;  }  sub get_grub_index { @@ -1577,7 +1583,9 @@ sub get_grub_index {      if ($reboot_type ne "grub") {  	return;      } -    return if (defined($grub_number)); +    return if (defined($grub_number) && defined($last_grub_menu) && +	       $last_grub_menu eq $grub_menu && defined($last_machine) && +	       $last_machine eq $machine);      doprint "Find grub menu ... ";      $grub_number = -1; @@ -1604,6 +1612,8 @@ sub get_grub_index {      die "Could not find '$grub_menu' in /boot/grub/menu on $machine"  	if (!$found);      doprint "$grub_number\n"; +    $last_grub_menu = $grub_menu; +    $last_machine = $machine;  }  sub wait_for_input |