All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH/RFC 0/2] new chcpu tool
@ 2011-08-15 15:24 Heiko Carstens
  2011-08-15 15:24 ` [PATCH/RFC 1/2] cpuset: add option to allow cpulist_parse() to fail Heiko Carstens
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Heiko Carstens @ 2011-08-15 15:24 UTC (permalink / raw)
  To: Karel Zak; +Cc: util-linux

This patch set introduces a new chcpu tool to util-linux. chcpu lets a user
configure CPUs. In this first version all that is possible is to enable or
disable CPUs (set them online of offline).
This is quite useful if you work a lot with virtual servers, since
enabling and disabling cpus manually via sysfs becomes tiring.

This first version is kept very simple so that I can easily change things
based on feedback/criticism before I add more functionality.
More features that I would like to add are

- rescan cpus: trigger the kernel to trigger a rescan of cpus. Necessary
  because not all hypervisors on s390 generate a guest event if a new
  cpu becomes visible to a guest.

- configure/deconfigure cpus: if cpus are offline the resources taken by
  the hypervisor can be freed if the cpus are deconfigured. Makes sense
  if a cpus are given dedicated to a logical partition. Deconfigured cpus
  can be given to other logical partitions.

- set dispatch mode: if the underlying hypervisor is PR/SM (LPAR hypervisor)
  it is possible to configure it's scheduling algorithm for the virtual cpus
  of the own logical partition.

Other architectures might add own features...

Any feedback and/or criticism would be welcome.

A usage example with a logical partition with 20 virtual cpus:

[root@r35lp37]# chcpu --help

Usage:
 chcpu [options] [cpu-list]

Options:
  -h, --help         print this help
  -e, --enable       enable cpus
  -d, --disable      disable cpus
  -v, --verbose      explain what is being done
  -V, --version      output version information and exit

[root@r35lp37]# cat /proc/cpuinfo
vendor_id       : IBM/S390
# processors    : 4
bogomips per cpu: 14367.00
features        : esan3 zarch stfle msa ldisp eimm dfp etf3eh highgprs 
processor 1: version = 00,  identification = 279F25,  machine = 2817
processor 10: version = 00,  identification = 279F25,  machine = 2817
processor 11: version = 00,  identification = 279F25,  machine = 2817
processor 12: version = 00,  identification = 279F25,  machine = 2817

[root@r35lp37]# ./chcpu -v -e 0-20
CPU 0 enabled
CPU 1 already enabled
CPU 2 enabled
CPU 3 enabled
CPU 4 enabled
CPU 5 enabled
CPU 6 enabled
CPU 7 enabled
CPU 8 enabled
CPU 9 enabled
CPU 10 already enabled
CPU 11 already enabled
CPU 12 already enabled
CPU 13 enabled
CPU 14 enabled
CPU 15 enabled
CPU 16 enabled
CPU 17 enabled
CPU 18 enabled
CPU 19 enabled
CPU 20 does not exist

[root@r35lp37]# cat /proc/cpuinfo 
vendor_id       : IBM/S390
# processors    : 20
bogomips per cpu: 14367.00
features        : esan3 zarch stfle msa ldisp eimm dfp etf3eh highgprs 
processor 0: version = 00,  identification = 279F25,  machine = 2817
processor 1: version = 00,  identification = 279F25,  machine = 2817
processor 2: version = 00,  identification = 279F25,  machine = 2817
processor 3: version = 00,  identification = 279F25,  machine = 2817
processor 4: version = 00,  identification = 279F25,  machine = 2817
processor 5: version = 00,  identification = 279F25,  machine = 2817
processor 6: version = 00,  identification = 279F25,  machine = 2817
processor 7: version = 00,  identification = 279F25,  machine = 2817
processor 8: version = 00,  identification = 279F25,  machine = 2817
processor 9: version = 00,  identification = 279F25,  machine = 2817
processor 10: version = 00,  identification = 279F25,  machine = 2817
processor 11: version = 00,  identification = 279F25,  machine = 2817
processor 12: version = 00,  identification = 279F25,  machine = 2817
processor 13: version = 00,  identification = 279F25,  machine = 2817
processor 14: version = 00,  identification = 279F25,  machine = 2817
processor 15: version = 00,  identification = 279F25,  machine = 2817
processor 16: version = 00,  identification = 279F25,  machine = 2817
processor 17: version = 00,  identification = 279F25,  machine = 2817
processor 18: version = 00,  identification = 279F25,  machine = 2817
processor 19: version = 00,  identification = 279F25,  machine = 2817

Thanks,
Heiko

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH/RFC 1/2] cpuset: add option to allow cpulist_parse() to fail
  2011-08-15 15:24 [PATCH/RFC 0/2] new chcpu tool Heiko Carstens
@ 2011-08-15 15:24 ` Heiko Carstens
  2011-08-15 15:24 ` [PATCH/RFC 2/2] chcpu: new tool Heiko Carstens
  2011-08-22 12:06 ` [PATCH] new chcpu tool Heiko Carstens
  2 siblings, 0 replies; 9+ messages in thread
From: Heiko Carstens @ 2011-08-15 15:24 UTC (permalink / raw)
  To: Karel Zak; +Cc: util-linux, Heiko Carstens

From: Heiko Carstens <heiko.carstens@de.ibm.com>

This is a preparation patch for chcpu. If a cpu should be added to
a cpu_set where the cpu doesn't fit into the cpu_set this got silently
ignored.
Since the cpu-list is user space provided it should be checked if cpus
are specified that are completely out of range of the system.
In order to do that add a parameter which specifies if cpulist_parse()
should fail if it parses a cpu-list with "impossible" cpus.
The current callers have been converted so they behave like before.

Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
---
 include/cpuset.h     |    2 +-
 lib/cpuset.c         |    7 +++++--
 schedutils/taskset.c |    2 +-
 sys-utils/lscpu.c    |    2 +-
 4 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/include/cpuset.h b/include/cpuset.h
index 9364660..f65c0ca 100644
--- a/include/cpuset.h
+++ b/include/cpuset.h
@@ -67,7 +67,7 @@ extern cpu_set_t *cpuset_alloc(int ncpus, size_t *setsize, size_t *nbits);
 extern void cpuset_free(cpu_set_t *set);
 
 extern char *cpulist_create(char *str, size_t len, cpu_set_t *set, size_t setsize);
-extern int cpulist_parse(const char *str, cpu_set_t *set, size_t setsize);
+extern int cpulist_parse(const char *str, cpu_set_t *set, size_t setsize, int fail);
 
 extern char *cpumask_create(char *str, size_t len, cpu_set_t *set, size_t setsize);
 extern int cpumask_parse(const char *str, cpu_set_t *set, size_t setsize);
diff --git a/lib/cpuset.c b/lib/cpuset.c
index 8aa296a..dd31f52 100644
--- a/lib/cpuset.c
+++ b/lib/cpuset.c
@@ -264,8 +264,9 @@ int cpumask_parse(const char *str, cpu_set_t *set, size_t setsize)
 /*
  * Parses string with CPUs mask.
  */
-int cpulist_parse(const char *str, cpu_set_t *set, size_t setsize)
+int cpulist_parse(const char *str, cpu_set_t *set, size_t setsize, int fail)
 {
+	size_t max = cpuset_nbits(setsize);
 	const char *p, *q;
 	q = str;
 
@@ -297,6 +298,8 @@ int cpulist_parse(const char *str, cpu_set_t *set, size_t setsize)
 		if (!(a <= b))
 			return 1;
 		while (a <= b) {
+			if (fail && (a >= max))
+				return 1;
 			CPU_SET_S(a, setsize, set);
 			a += s;
 		}
@@ -359,7 +362,7 @@ int main(int argc, char *argv[])
 	if (mask)
 		rc = cpumask_parse(mask, set, setsize);
 	else
-		rc = cpulist_parse(range, set, setsize);
+		rc = cpulist_parse(range, set, setsize, 0);
 
 	if (rc)
 		errx(EXIT_FAILURE, "failed to parse string: %s", mask ? : range);
diff --git a/schedutils/taskset.c b/schedutils/taskset.c
index 1457c65..085675d 100644
--- a/schedutils/taskset.c
+++ b/schedutils/taskset.c
@@ -208,7 +208,7 @@ int main(int argc, char **argv)
 		ts.get_only = 1;
 
 	else if (ts.use_list) {
-		if (cpulist_parse(argv[optind], new_set, new_setsize))
+		if (cpulist_parse(argv[optind], new_set, new_setsize, 0))
 			errx(EXIT_FAILURE, _("failed to parse CPU list: %s"),
 			     argv[optind]);
 	} else if (cpumask_parse(argv[optind], new_set, new_setsize)) {
diff --git a/sys-utils/lscpu.c b/sys-utils/lscpu.c
index 50daf3c..12779f1 100644
--- a/sys-utils/lscpu.c
+++ b/sys-utils/lscpu.c
@@ -304,7 +304,7 @@ path_cpuparse(int islist, const char *path, va_list ap)
 		err(EXIT_FAILURE, _("failed to callocate cpu set"));
 
 	if (islist) {
-		if (cpulist_parse(buf, set, setsize))
+		if (cpulist_parse(buf, set, setsize, 0))
 			errx(EXIT_FAILURE, _("failed to parse CPU list %s"), buf);
 	} else {
 		if (cpumask_parse(buf, set, setsize))
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH/RFC 2/2] chcpu: new tool
  2011-08-15 15:24 [PATCH/RFC 0/2] new chcpu tool Heiko Carstens
  2011-08-15 15:24 ` [PATCH/RFC 1/2] cpuset: add option to allow cpulist_parse() to fail Heiko Carstens
@ 2011-08-15 15:24 ` Heiko Carstens
  2011-08-31  9:44   ` Karel Zak
  2011-08-22 12:06 ` [PATCH] new chcpu tool Heiko Carstens
  2 siblings, 1 reply; 9+ messages in thread
From: Heiko Carstens @ 2011-08-15 15:24 UTC (permalink / raw)
  To: Karel Zak; +Cc: util-linux, Heiko Carstens

From: Heiko Carstens <heiko.carstens@de.ibm.com>

The chcpu lets a user configure CPUs. In this first version all that
is possible is to enable or disable CPUs (set them online of offline).
This is quite useful if you work a lot with virtual servers, since
enabling and disabling cpus via sysfs becomes tiring.

Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
---
 sys-utils/.gitignore  |    1 +
 sys-utils/Makefile.am |    3 +
 sys-utils/chcpu.1     |   56 ++++++++++++
 sys-utils/chcpu.c     |  222 +++++++++++++++++++++++++++++++++++++++++++++++++
 sys-utils/lscpu.1     |    2 +
 5 files changed, 284 insertions(+), 0 deletions(-)
 create mode 100644 sys-utils/chcpu.1
 create mode 100644 sys-utils/chcpu.c

diff --git a/sys-utils/.gitignore b/sys-utils/.gitignore
index 3ae7e4a..febeb38 100644
--- a/sys-utils/.gitignore
+++ b/sys-utils/.gitignore
@@ -41,3 +41,4 @@ switch_root
 tunelp
 unshare
 x86_64.8
+chcpu
diff --git a/sys-utils/Makefile.am b/sys-utils/Makefile.am
index feb5888..da05dac 100644
--- a/sys-utils/Makefile.am
+++ b/sys-utils/Makefile.am
@@ -21,6 +21,9 @@ if HAVE_CPU_SET_T
 usrbin_exec_PROGRAMS += lscpu
 lscpu_SOURCES = lscpu.c $(top_srcdir)/lib/cpuset.c $(top_srcdir)/lib/strutils.c
 dist_man_MANS += lscpu.1
+sbin_PROGRAMS += chcpu
+chcpu_SOURCES = chcpu.c $(top_srcdir)/lib/cpuset.c
+dist_man_MANS += chcpu.1
 endif
 
 endif
diff --git a/sys-utils/chcpu.1 b/sys-utils/chcpu.1
new file mode 100644
index 0000000..0b9e98a
--- /dev/null
+++ b/sys-utils/chcpu.1
@@ -0,0 +1,56 @@
+.TH CHCPU 1 "August 2011" Linux "User Manuals"
+.SH NAME
+chcpu \- CPU configuration utility
+.SH SYNOPSIS
+.B chcpu
+.RB [ \-hvV ]
+.RB [ \-d
+.IR cpulist ]
+.RB [ \-e
+.IR cpulist ]
+.SH DESCRIPTION
+.B chcpu
+is used to configure CPUs. It can enable and disable CPUs by writing to the
+per CPU sysfs file attributes.
+Some options have a \fIcpu-list\fP argument. A \fIcpu-list\fP may specify
+multiple CPUs, separated by comma, and ranges.  For example,
+.BR 0,5,7,9-11 .
+.SH OPTIONS
+The --disable and --enable options are mutually exclusive.
+.TP
+.BR \-d , " \-\-disable " \fIcpu-list\fP
+disable all CPUs specified with \fIcpu-list\fP. If
+.BR chcpu
+fails to disable a CPU specified in the \fIcpu-list\fP it will skip that
+CPU and continue with the next one until all specified CPUs have been
+processed.
+.TP
+.BR \-e , " \-\-enable " \fIcpu-list\fP
+enable all CPUs specified with \fIcpu-list\fP. If
+.BR chcpu
+fails to enable a CPU specified in the \fIcpu-list\fP it will skip that
+CPU and continue with the next one until all specified CPUs have been
+processed.
+.TP
+.BR \-h , " \-\-help"
+Print a help text and exit.
+.TP
+.BR \-v , " \-\-verbose"
+Verbose execution. When specified
+.B chcpu
+will output the result of the configuration changes for each CPU.
+.TP
+.BR \-V , " \-\-version"
+Output version information and exit.
+.SH AUTHOR
+.nf
+Heiko Carstens <heiko.carstens@de.ibm.com>
+.fi
+.SH COPYRIGHT
+Copyright IBM Corp. 2011
+.br
+.SH "SEE ALSO"
+.BR lscpu (1)
+.SH AVAILABILITY
+The chcpu command is part of the util-linux package and is available from
+ftp://ftp.kernel.org/pub/linux/utils/util-linux/.
diff --git a/sys-utils/chcpu.c b/sys-utils/chcpu.c
new file mode 100644
index 0000000..6e4392d
--- /dev/null
+++ b/sys-utils/chcpu.c
@@ -0,0 +1,222 @@
+/*
+ * chcpu - CPU configuration tool
+ *
+ * Copyright IBM Corp. 2011
+ * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "cpuset.h"
+#include "nls.h"
+#include "xalloc.h"
+#include "c.h"
+#include "strutils.h"
+#include "bitops.h"
+
+#define _PATH_SYS_CPU	"/sys/devices/system/cpu"
+
+static char pathbuf[PATH_MAX];
+static int verbose;
+
+enum {
+	CMD_CPU_ENABLE	= 0,
+	CMD_CPU_DISABLE,
+};
+
+static int path_open(mode_t mode, const char *path, ...)
+{
+	va_list ap;
+	int fd;
+
+	va_start(ap, path);
+	vsnprintf(pathbuf, sizeof(pathbuf), path, ap);
+	va_end(ap);
+	fd = open(pathbuf, mode);
+	if (fd == -1)
+		err(EXIT_FAILURE, "error: cannot open %s", pathbuf);
+	return fd;
+}
+
+static int path_exist(const char *path, ...)
+{
+	va_list ap;
+
+	va_start(ap, path);
+	vsnprintf(pathbuf, sizeof(pathbuf), path, ap);
+	va_end(ap);
+	return access(pathbuf, F_OK) == 0;
+}
+
+static void print_v(const char *str, ...)
+{
+	va_list ap;
+
+	if (!verbose)
+		return;
+	va_start(ap, str);
+	vprintf(str, ap);
+	va_end(ap);
+}
+
+static int cpu_enable(cpu_set_t *cpu_set, size_t setsize, int enable)
+{
+	unsigned int cpu;
+	int fd, rc;
+	char c;
+
+	for (cpu = 0; cpu < setsize; cpu++) {
+		if (!CPU_ISSET(cpu, cpu_set))
+			continue;
+		if (!path_exist(_PATH_SYS_CPU "/cpu%d", cpu)) {
+			print_v(_("CPU %d does not exist\n"), cpu);
+			continue;
+		}
+		if (!path_exist(_PATH_SYS_CPU "/cpu%d/online", cpu)) {
+			print_v(_("CPU %d is not hot pluggable\n"), cpu);
+			continue;
+		}
+		fd = path_open(O_RDWR, _PATH_SYS_CPU "/cpu%d/online", cpu);
+		if (read(fd, &c, 1) == -1)
+			err(EXIT_FAILURE, "error: cannot read from %s", pathbuf);
+		if ((c == '1') && (enable == 1)) {
+			print_v(_("CPU %d already enabled\n"), cpu);
+			continue;
+		}
+		if ((c == '0') && (enable == 0)) {
+			print_v(_("CPU %d already disabled\n"), cpu);
+			continue;
+		}
+		if (enable) {
+			rc = write(fd, "1", 1);
+			if (rc == -1)
+				print_v(_("CPU %d enable failed (%s)\n"), cpu,
+					strerror(errno));
+			else
+				print_v(_("CPU %d enabled\n"), cpu);
+		} else {
+			rc = write(fd, "0", 1);
+			if (rc == -1)
+				print_v(_("CPU %d disable failed (%s)\n"), cpu,
+					strerror(errno));
+			else
+				print_v(_("CPU %d disabled\n"), cpu);
+		}
+		close(fd);
+	}
+	return EXIT_SUCCESS;
+}
+
+static void __attribute__((__noreturn__)) usage(FILE *out)
+{
+	fprintf(out, _(
+		"\nUsage:\n"
+		" %s [options] [cpu-list]\n"), program_invocation_short_name);
+
+	puts(_(	"\nOptions:\n"
+		"  -h, --help         print this help\n"
+		"  -e, --enable       enable cpus\n"
+		"  -d, --disable      disable cpus\n"
+		"  -v, --verbose      explain what is being done\n"
+		"  -V, --version      output version information and exit\n"));
+
+	exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
+}
+
+int main(int argc, char *argv[])
+{
+	cpu_set_t *cpu_set;
+	unsigned int ncpus;
+	size_t setsize;
+	int cmd = -1;
+	int c;
+
+	static const struct option longopts[] = {
+		{ "disable",	required_argument, 0, 'd' },
+		{ "enable",	required_argument, 0, 'e' },
+		{ "help",	no_argument,       0, 'h' },
+		{ "verbose",	no_argument,       0, 'v' },
+		{ "version",	no_argument,       0, 'V' },
+		{ NULL,		0, 0, 0 }
+	};
+
+	setlocale(LC_ALL, "");
+	bindtextdomain(PACKAGE, LOCALEDIR);
+	textdomain(PACKAGE);
+
+	ncpus = get_max_number_of_cpus();
+	if (ncpus <= 0)
+		errx(EXIT_FAILURE, _("cannot determine NR_CPUS; aborting"));
+	setsize = CPU_ALLOC_SIZE(ncpus);
+	cpu_set = CPU_ALLOC(ncpus);
+	if (!cpu_set)
+		err(EXIT_FAILURE, _("cpuset_alloc failed"));
+
+	while ((c = getopt_long(argc, argv, "he:d:vV", longopts, NULL)) != -1) {
+		if (cmd != -1 && strchr("de", c))
+			errx(EXIT_FAILURE,
+			     _("disable and enable are mutually exclusive"));
+		switch (c) {
+		case 'h':
+			usage(stdout);
+		case 'e':
+			cmd = CMD_CPU_ENABLE;
+			if (cpulist_parse(argv[optind - 1], cpu_set, setsize, 1))
+				errx(EXIT_FAILURE, _("failed to parse CPU list: %s"),
+				     argv[optind -1 ]);
+			break;
+		case 'd':
+			cmd = CMD_CPU_DISABLE;
+			if (cpulist_parse(argv[optind - 1], cpu_set, setsize, 1))
+				errx(EXIT_FAILURE, _("failed to parse CPU list: %s"),
+				     argv[optind -1 ]);
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		case 'V':
+			printf(_("%s from %s\n"), program_invocation_short_name,
+			       PACKAGE_STRING);
+			return EXIT_SUCCESS;
+		default:
+			usage(stderr);
+		}
+	}
+
+	if ((argc == 1) || (argc != optind))
+		usage(stderr);
+
+	switch (cmd) {
+	case CMD_CPU_ENABLE:
+		return cpu_enable(cpu_set, ncpus, 1);
+	case CMD_CPU_DISABLE:
+		return cpu_enable(cpu_set, ncpus, 0);
+	}
+	return EXIT_SUCCESS;
+}
diff --git a/sys-utils/lscpu.1 b/sys-utils/lscpu.1
index 4795e91..39246c9 100644
--- a/sys-utils/lscpu.1
+++ b/sys-utils/lscpu.1
@@ -56,6 +56,8 @@ Sometimes in Xen Dom0 the kernel reports wrong data.
 Cai Qian <qcai@redhat.com>
 Karel Zak <kzak@redhat.com>
 .fi
+.SH "SEE ALSO"
+.BR chcpu (1)
 .SH AVAILABILITY
 The lscpu command is part of the util-linux package and is available from
 ftp://ftp.kernel.org/pub/linux/utils/util-linux/.
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH] new chcpu tool
  2011-08-15 15:24 [PATCH/RFC 0/2] new chcpu tool Heiko Carstens
  2011-08-15 15:24 ` [PATCH/RFC 1/2] cpuset: add option to allow cpulist_parse() to fail Heiko Carstens
  2011-08-15 15:24 ` [PATCH/RFC 2/2] chcpu: new tool Heiko Carstens
@ 2011-08-22 12:06 ` Heiko Carstens
  2011-08-22 13:28   ` Karel Zak
  2 siblings, 1 reply; 9+ messages in thread
From: Heiko Carstens @ 2011-08-22 12:06 UTC (permalink / raw)
  To: Karel Zak; +Cc: util-linux

Hi Karel,

here is an updated version of the chcpu tool that includes all the features
I described in my previous mail.
Do you think it would be ok to have it in util-linux? Or should it live
somewhere else?

The rationale why I think it should be within util-linux is simply that
lscpu is already there. Parts of the tool are architecture/hypervisor
dependent, but some things are useful for most architectures, I think.
At least for those architectures that support virtualization quite a few
features are (or will be) common.

Another reason for trying to add it to util-linux is that we want to avoid
doing the same mistake we did already with the "lsmem" and "chmem" tools
which can configure hotplug memory. These tools are completely architecture
independent, but we put them into our "s390-tools" package.
I think both of them should live in util-linux instead... But that's
something we could address later anyway :)

Anyway, what do you think?

Thanks,
Heiko

----

Subject: [PATCH] chcpu: new tool

From: Heiko Carstens <heiko.carstens@de.ibm.com>

chcpu can modify the logical state of CPUs. It can enable and disable CPUs,
scan for new CPUs, change the CPU dispatching mode of the underlying
hypervisor and request (configure) or give logical CPUs back (deconfigure)
to the the underlying hypervisor.

This is quite useful if you work a lot with virtual servers, since doing all
the configuration stuff directly via sysfs becomes a pain.

Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
---

 sys-utils/.gitignore  |    1 
 sys-utils/Makefile.am |    3 
 sys-utils/chcpu.1     |   94 +++++++++++++
 sys-utils/chcpu.c     |  337 ++++++++++++++++++++++++++++++++++++++++++++++++++
 sys-utils/lscpu.1     |    2 
 5 files changed, 437 insertions(+)

diff --git a/sys-utils/.gitignore b/sys-utils/.gitignore
index 3ae7e4a..febeb38 100644
--- a/sys-utils/.gitignore
+++ b/sys-utils/.gitignore
@@ -41,3 +41,4 @@ switch_root
 tunelp
 unshare
 x86_64.8
+chcpu
diff --git a/sys-utils/Makefile.am b/sys-utils/Makefile.am
index feb5888..da05dac 100644
--- a/sys-utils/Makefile.am
+++ b/sys-utils/Makefile.am
@@ -21,6 +21,9 @@ if HAVE_CPU_SET_T
 usrbin_exec_PROGRAMS += lscpu
 lscpu_SOURCES = lscpu.c $(top_srcdir)/lib/cpuset.c $(top_srcdir)/lib/strutils.c
 dist_man_MANS += lscpu.1
+sbin_PROGRAMS += chcpu
+chcpu_SOURCES = chcpu.c $(top_srcdir)/lib/cpuset.c
+dist_man_MANS += chcpu.1
 endif
 
 endif
diff --git a/sys-utils/chcpu.1 b/sys-utils/chcpu.1
new file mode 100644
index 0000000..9417a72
--- /dev/null
+++ b/sys-utils/chcpu.1
@@ -0,0 +1,94 @@
+.TH CHCPU 1 "August 2011" Linux "User Manuals"
+.SH NAME
+chcpu \- CPU configuration utility
+.SH SYNOPSIS
+.B chcpu
+\fB-c\fP|\fB\-d\fP|\fB\-e\fP|\fB\-g\fP
+.IR cpu-list
+.br
+.B
+\fBchcpu \-p\fP \fImode\fP
+.br
+.B chcpu
+.RB [ \-rhV\ ]
+.br
+.SH DESCRIPTION
+.B chcpu
+can modify the logical state of CPUs. It can enable and disable CPUs, scan
+for new CPUs, change the CPU dispatching mode of the underlying hypervisor
+and request (configure) or give logical CPUs back (deconfigure) to the
+the underlying hypervisor.
+
+Some options have a \fIcpu-list\fP argument. A \fIcpu-list\fP may specify
+multiple CPUs, separated by comma, and ranges.  For example,
+.BR 0,5,7,9-11 .
+.SH OPTIONS
+The --configure, --deconfigure, --disable, --dispatch, --enable and --rescan
+options are mutually exclusive.
+.TP
+.BR \-c , " \-\-configure " <\fIcpu-list\fP>
+Configure all CPUs specified with \fIcpu-list\fP. If
+.BR chcpu
+fails to configure a CPU specified in the \fIcpu-list\fP it will skip that
+CPU and continue with the next one until all specified CPUs have been
+processed.
+.br
+Configuring a CPU means that the underlying hypervisor is informed that
+a logical CPU within a guest should be used. If the hypervisor has enough
+resources the request will succeed.
+.TP
+.BR \-d , " \-\-disable " <\fIcpu-list\fP>
+Disable all CPUs specified with \fIcpu-list\fP. If
+.BR chcpu
+fails to disable a CPU specified in the \fIcpu-list\fP it will skip that
+CPU and continue with the next one until all specified CPUs have been
+processed.
+.br
+When a CPU has been disabled its state is offline.
+.TP
+.BR \-e , " \-\-enable " <\fIcpu-list\fP>
+Enable all CPUs specified with \fIcpu-list\fP. If
+.BR chcpu
+fails to enable a CPU specified in the \fIcpu-list\fP it will skip that
+CPU and continue with the next one until all specified CPUs have been
+processed.
+.br
+When a CPU has been enabled its state is online.
+.TP
+.BR \-g , " \-\-deconfigure " <\fIcpu-list\fP>
+Deconfigure all CPUs specified with \fIcpu-list\fP. If
+.BR chcpu
+fails to deconfigure a CPU specified in the \fIcpu-list\fP it will skip
+that CPU and continue with the next one until all specified CPUs have been
+processed. Only disabled (offline) CPUs can be deconfigured.
+.br
+Deconfiguring a CPU means that the underlying hypervisor is informed that
+the CPU will not be used anymore and that the hypervisor can add the CPU
+back to its CPU pool.
+.TP
+.BR \-h , " \-\-help"
+Print a help text and exit.
+.TP
+.BR \-p , " \-\-dispatch " <\fImode\fP>
+Set the CPU dispatching \fImode\fP if the underlying hypervisor supports this.
+\fImode\fP may be horizontal or vertical.
+.TP
+.BR \-r , " \-\-rescan"
+Trigger a rescan of CPUs. If new CPUs have been attached to the system the
+kernel will detect them. On some systems no event will be generated if a
+CPU gets attached. In that case a CPU rescan must be manually triggered.
+.TP
+.BR \-V , " \-\-version"
+Output version information and exit.
+.SH AUTHOR
+.nf
+Heiko Carstens <heiko.carstens@de.ibm.com>
+.fi
+.SH COPYRIGHT
+Copyright IBM Corp. 2011
+.br
+.SH "SEE ALSO"
+.BR lscpu (1)
+.SH AVAILABILITY
+The chcpu command is part of the util-linux package and is available from
+ftp://ftp.kernel.org/pub/linux/utils/util-linux/.
diff --git a/sys-utils/chcpu.c b/sys-utils/chcpu.c
new file mode 100644
index 0000000..2d5725f
--- /dev/null
+++ b/sys-utils/chcpu.c
@@ -0,0 +1,337 @@
+/*
+ * chcpu - CPU configuration tool
+ *
+ * Copyright IBM Corp. 2011
+ * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "cpuset.h"
+#include "nls.h"
+#include "xalloc.h"
+#include "c.h"
+#include "strutils.h"
+#include "bitops.h"
+
+#define _PATH_SYS_CPU		"/sys/devices/system/cpu"
+#define _PATH_SYS_CPU_RESCAN	_PATH_SYS_CPU "/rescan"
+#define _PATH_SYS_CPU_DISPATCH	_PATH_SYS_CPU "/dispatching"
+
+static char pathbuf[PATH_MAX];
+
+enum {
+	CMD_CPU_ENABLE	= 0,
+	CMD_CPU_DISABLE,
+	CMD_CPU_CONFIGURE,
+	CMD_CPU_DECONFIGURE,
+	CMD_CPU_RESCAN,
+	CMD_CPU_DISPATCH_HORIZONTAL,
+	CMD_CPU_DISPATCH_VERTICAL,
+};
+
+static int path_open(mode_t mode, const char *path, ...)
+{
+	va_list ap;
+	int fd;
+
+	va_start(ap, path);
+	vsnprintf(pathbuf, sizeof(pathbuf), path, ap);
+	va_end(ap);
+	fd = open(pathbuf, mode);
+	if (fd == -1)
+		err(EXIT_FAILURE, "error: cannot open %s", pathbuf);
+	return fd;
+}
+
+static int path_exist(const char *path, ...)
+{
+	va_list ap;
+
+	va_start(ap, path);
+	vsnprintf(pathbuf, sizeof(pathbuf), path, ap);
+	va_end(ap);
+	return access(pathbuf, F_OK) == 0;
+}
+
+static int cpu_enable(cpu_set_t *cpu_set, size_t setsize, int enable)
+{
+	unsigned int cpu;
+	int fd, rc;
+	char c;
+
+	for (cpu = 0; cpu < setsize; cpu++) {
+		if (!CPU_ISSET(cpu, cpu_set))
+			continue;
+		if (!path_exist(_PATH_SYS_CPU "/cpu%d", cpu)) {
+			printf(_("CPU %d does not exist\n"), cpu);
+			continue;
+		}
+		if (!path_exist(_PATH_SYS_CPU "/cpu%d/online", cpu)) {
+			printf(_("CPU %d is not hot pluggable\n"), cpu);
+			continue;
+		}
+		fd = path_open(O_RDWR, _PATH_SYS_CPU "/cpu%d/online", cpu);
+		if (read(fd, &c, 1) == -1)
+			err(EXIT_FAILURE, "error: cannot read from %s", pathbuf);
+		if ((c == '1') && (enable == 1)) {
+			printf(_("CPU %d is already enabled\n"), cpu);
+			continue;
+		}
+		if ((c == '0') && (enable == 0)) {
+			printf(_("CPU %d is already disabled\n"), cpu);
+			continue;
+		}
+		if (enable) {
+			rc = write(fd, "1", 1);
+			if (rc == -1)
+				printf(_("CPU %d enable failed (%s)\n"), cpu,
+					strerror(errno));
+			else
+				printf(_("CPU %d enabled\n"), cpu);
+		} else {
+			rc = write(fd, "0", 1);
+			if (rc == -1)
+				printf(_("CPU %d disable failed (%s)\n"), cpu,
+					strerror(errno));
+			else
+				printf(_("CPU %d disabled\n"), cpu);
+		}
+		close(fd);
+	}
+	return EXIT_SUCCESS;
+}
+
+static int cpu_rescan(void)
+{
+	int fd;
+
+	if (!path_exist(_PATH_SYS_CPU_RESCAN))
+		errx(EXIT_FAILURE, _("This system does not support rescanning of CPUs"));
+	fd = path_open(O_WRONLY, _PATH_SYS_CPU_RESCAN);
+	if (write(fd, "1", 1) == -1)
+		err(EXIT_FAILURE, _("Failed to trigger rescan of CPUs"));
+	close(fd);
+	return EXIT_SUCCESS;
+}
+
+static int cpu_set_dispatch(int mode)
+{
+	int fd;
+
+	if (!path_exist(_PATH_SYS_CPU_DISPATCH))
+		errx(EXIT_FAILURE, _("This system does not support setting "
+				     "the dispatching mode of CPUs"));
+	fd = path_open(O_WRONLY, _PATH_SYS_CPU_DISPATCH);
+	if (mode == 0) {
+		if (write(fd, "0", 1) == -1)
+			err(EXIT_FAILURE, _("Failed to set horizontal dispatch mode"));
+		printf(_("Succesfully set horizontal dispatching mode\n"));
+	} else {
+		if (write(fd, "1", 1) == -1)
+			err(EXIT_FAILURE, _("Failed to set vertical dispatch mode"));
+		printf(_("Succesfully set vertical dispatching mode\n"));
+	}
+	close(fd);
+	return EXIT_SUCCESS;
+}
+
+static int cpu_configure(cpu_set_t *cpu_set, size_t setsize, int configure)
+{
+	unsigned int cpu;
+	int fd, rc;
+	char c;
+
+	for (cpu = 0; cpu < setsize; cpu++) {
+		if (!CPU_ISSET(cpu, cpu_set))
+			continue;
+		if (!path_exist(_PATH_SYS_CPU "/cpu%d", cpu)) {
+			printf(_("CPU %d does not exist\n"), cpu);
+			continue;
+		}
+		if (!path_exist(_PATH_SYS_CPU "/cpu%d/configure", cpu)) {
+			printf(_("CPU %d is not configurable\n"), cpu);
+			continue;
+		}
+		fd = path_open(O_RDWR, _PATH_SYS_CPU "/cpu%d/configure", cpu);
+		if (read(fd, &c, 1) == -1)
+			err(EXIT_FAILURE, "error: cannot read from %s", pathbuf);
+		if ((c == '1') && (configure == 1)) {
+			printf(_("CPU %d is already configured\n"), cpu);
+			continue;
+		}
+		if ((c == '0') && (configure == 0)) {
+			printf(_("CPU %d is already deconfigured\n"), cpu);
+			continue;
+		}
+		if (configure) {
+			rc = write(fd, "1", 1);
+			if (rc == -1)
+				printf(_("CPU %d configure failed (%s)\n"), cpu,
+					strerror(errno));
+			else
+				printf(_("CPU %d configured\n"), cpu);
+		} else {
+			rc = write(fd, "0", 1);
+			if (rc == -1)
+				printf(_("CPU %d deconfigure failed (%s)\n"), cpu,
+					strerror(errno));
+			else
+				printf(_("CPU %d deconfigured\n"), cpu);
+		}
+		close(fd);
+	}
+	return EXIT_SUCCESS;
+}
+
+static void __attribute__((__noreturn__)) usage(FILE *out)
+{
+	fprintf(out, _(
+		"\nUsage:\n"
+		" %s [options]\n"), program_invocation_short_name);
+
+	puts(_(	"\nOptions:\n"
+		"  -h, --help                    print this help\n"
+		"  -e, --enable <cpu-list>       enable cpus\n"
+		"  -d, --disable <cpu-list>      disable cpus\n"
+		"  -c, --configure <cpu-list>    configure cpus\n"
+		"  -g, --deconfigure <cpu-list>  deconfigure cpus\n"
+		"  -p, --dispatch <mode>         set dispatching mode\n"
+		"  -r, --rescan                  trigger rescan of cpus\n"
+		"  -V, --version                 output version information and exit\n"));
+
+	exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
+}
+
+int main(int argc, char *argv[])
+{
+	cpu_set_t *cpu_set;
+	unsigned int ncpus;
+	size_t setsize;
+	int cmd = -1;
+	int c;
+
+	static const struct option longopts[] = {
+		{ "configure",	required_argument, 0, 'c' },
+		{ "deconfigure",required_argument, 0, 'g' },
+		{ "disable",	required_argument, 0, 'd' },
+		{ "dispatch",	required_argument, 0, 'p' },
+		{ "enable",	required_argument, 0, 'e' },
+		{ "help",	no_argument,       0, 'h' },
+		{ "rescan",	no_argument,       0, 'r' },
+		{ "version",	no_argument,       0, 'V' },
+		{ NULL,		0, 0, 0 }
+	};
+
+	setlocale(LC_ALL, "");
+	bindtextdomain(PACKAGE, LOCALEDIR);
+	textdomain(PACKAGE);
+
+	ncpus = get_max_number_of_cpus();
+	if (ncpus <= 0)
+		errx(EXIT_FAILURE, _("cannot determine NR_CPUS; aborting"));
+	setsize = CPU_ALLOC_SIZE(ncpus);
+	cpu_set = CPU_ALLOC(ncpus);
+	if (!cpu_set)
+		err(EXIT_FAILURE, _("cpuset_alloc failed"));
+
+	while ((c = getopt_long(argc, argv, "c:d:e:g:hp:rV", longopts, NULL)) != -1) {
+		if (cmd != -1 && strchr("cdegpr", c))
+			errx(EXIT_FAILURE,
+			     _("configure, deconfigure, disable, dispatch, enable "
+			       "and rescan are mutually exclusive"));
+		switch (c) {
+		case 'c':
+			cmd = CMD_CPU_CONFIGURE;
+			if (cpulist_parse(argv[optind - 1], cpu_set, setsize, 1))
+				errx(EXIT_FAILURE, _("failed to parse CPU list: %s"),
+				     argv[optind -1 ]);
+			break;
+		case 'd':
+			cmd = CMD_CPU_DISABLE;
+			if (cpulist_parse(argv[optind - 1], cpu_set, setsize, 1))
+				errx(EXIT_FAILURE, _("failed to parse CPU list: %s"),
+				     argv[optind -1 ]);
+			break;
+		case 'e':
+			cmd = CMD_CPU_ENABLE;
+			if (cpulist_parse(argv[optind - 1], cpu_set, setsize, 1))
+				errx(EXIT_FAILURE, _("failed to parse CPU list: %s"),
+				     argv[optind -1 ]);
+			break;
+		case 'g':
+			cmd = CMD_CPU_DECONFIGURE;
+			if (cpulist_parse(argv[optind - 1], cpu_set, setsize, 1))
+				errx(EXIT_FAILURE, _("failed to parse CPU list: %s"),
+				     argv[optind -1 ]);
+			break;
+		case 'h':
+			usage(stdout);
+		case 'p':
+			if (strcmp("horizontal", argv[optind - 1]) == 0)
+				cmd = CMD_CPU_DISPATCH_HORIZONTAL;
+			else if (strcmp("vertical", argv[optind - 1]) == 0)
+				cmd = CMD_CPU_DISPATCH_VERTICAL;
+			else
+				errx(EXIT_FAILURE, _("unsupported argument: %s"),
+				     argv[optind -1 ]);
+			break;
+		case 'r':
+			cmd = CMD_CPU_RESCAN;
+			break;
+		case 'V':
+			printf(_("%s from %s\n"), program_invocation_short_name,
+			       PACKAGE_STRING);
+			return EXIT_SUCCESS;
+		default:
+			usage(stderr);
+		}
+	}
+
+	if ((argc == 1) || (argc != optind))
+		usage(stderr);
+
+	switch (cmd) {
+	case CMD_CPU_ENABLE:
+		return cpu_enable(cpu_set, ncpus, 1);
+	case CMD_CPU_DISABLE:
+		return cpu_enable(cpu_set, ncpus, 0);
+	case CMD_CPU_CONFIGURE:
+		return cpu_configure(cpu_set, ncpus, 1);
+	case CMD_CPU_DECONFIGURE:
+		return cpu_configure(cpu_set, ncpus, 0);
+	case CMD_CPU_RESCAN:
+		return cpu_rescan();
+	case CMD_CPU_DISPATCH_HORIZONTAL:
+		return cpu_set_dispatch(0);
+	case CMD_CPU_DISPATCH_VERTICAL:
+		return cpu_set_dispatch(1);
+	}
+	return EXIT_SUCCESS;
+}
diff --git a/sys-utils/lscpu.1 b/sys-utils/lscpu.1
index 4795e91..39246c9 100644
--- a/sys-utils/lscpu.1
+++ b/sys-utils/lscpu.1
@@ -56,6 +56,8 @@ Sometimes in Xen Dom0 the kernel reports wrong data.
 Cai Qian <qcai@redhat.com>
 Karel Zak <kzak@redhat.com>
 .fi
+.SH "SEE ALSO"
+.BR chcpu (1)
 .SH AVAILABILITY
 The lscpu command is part of the util-linux package and is available from
 ftp://ftp.kernel.org/pub/linux/utils/util-linux/.

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH] new chcpu tool
  2011-08-22 12:06 ` [PATCH] new chcpu tool Heiko Carstens
@ 2011-08-22 13:28   ` Karel Zak
  2011-08-23  8:45     ` Heiko Carstens
  0 siblings, 1 reply; 9+ messages in thread
From: Karel Zak @ 2011-08-22 13:28 UTC (permalink / raw)
  To: Heiko Carstens; +Cc: util-linux

On Mon, Aug 22, 2011 at 02:06:41PM +0200, Heiko Carstens wrote:
> Do you think it would be ok to have it in util-linux? Or should it live
> somewhere else?

It makes sense to have it in util-linux. I'm going to merge it after
v2.20 release.

> Another reason for trying to add it to util-linux is that we want to avoid
> doing the same mistake we did already with the "lsmem" and "chmem" tools
> which can configure hotplug memory. These tools are completely architecture
> independent, but we put them into our "s390-tools" package.
> I think both of them should live in util-linux instead... But that's
> something we could address later anyway :)

 OK :-)

> +static int path_exist(const char *path, ...)

 It seems that we need to move the path_*() functions from lscpu(1) to
 lib/ and hare the stuff.

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] new chcpu tool
  2011-08-22 13:28   ` Karel Zak
@ 2011-08-23  8:45     ` Heiko Carstens
  2011-08-31  9:56       ` Karel Zak
  0 siblings, 1 reply; 9+ messages in thread
From: Heiko Carstens @ 2011-08-23  8:45 UTC (permalink / raw)
  To: Karel Zak; +Cc: util-linux

On Mon, Aug 22, 2011 at 03:28:17PM +0200, Karel Zak wrote:
> On Mon, Aug 22, 2011 at 02:06:41PM +0200, Heiko Carstens wrote:
> > Do you think it would be ok to have it in util-linux? Or should it live
> > somewhere else?
> 
> It makes sense to have it in util-linux. I'm going to merge it after
> v2.20 release.

Ok, great!

I set up a chcpu git branch where you could pull the chcpu stuff easily:

  git://git.kernel.org/pub/scm/linux/kernel/git/heiko/util-linux.git chcpu

It contains just the two patches posted here and doesn't interfer with the
lscpu branch that is also there.

Heiko Carstens (2):
      cpuset: add option to allow cpulist_parse() to fail
      chcpu: new tool

 include/cpuset.h      |    2 +-
 lib/cpuset.c          |    7 +-
 schedutils/taskset.c  |    2 +-
 sys-utils/.gitignore  |    1 +
 sys-utils/Makefile.am |    3 +
 sys-utils/chcpu.1     |   94 ++++++++++++++
 sys-utils/chcpu.c     |  337 +++++++++++++++++++++++++++++++++++++++++++++++++
 sys-utils/lscpu.1     |    2 +
 sys-utils/lscpu.c     |    2 +-
 9 files changed, 445 insertions(+), 5 deletions(-)
 create mode 100644 sys-utils/chcpu.1
 create mode 100644 sys-utils/chcpu.c

> > +static int path_exist(const char *path, ...)
> 
>  It seems that we need to move the path_*() functions from lscpu(1) to
>  lib/ and hare the stuff.

Yes, I thought so as well. But laziness won ;)

Thanks,
Heiko

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH/RFC 2/2] chcpu: new tool
  2011-08-15 15:24 ` [PATCH/RFC 2/2] chcpu: new tool Heiko Carstens
@ 2011-08-31  9:44   ` Karel Zak
  2011-08-31  9:47     ` Karel Zak
  0 siblings, 1 reply; 9+ messages in thread
From: Karel Zak @ 2011-08-31  9:44 UTC (permalink / raw)
  To: Heiko Carstens; +Cc: util-linux

On Mon, Aug 15, 2011 at 05:24:55PM +0200, Heiko Carstens wrote:
> +	if ((argc == 1) || (argc != optind))
> +		usage(stderr);
> +
> +	switch (cmd) {
> +	case CMD_CPU_ENABLE:
> +		return cpu_enable(cpu_set, ncpus, 1);
> +	case CMD_CPU_DISABLE:
> +		return cpu_enable(cpu_set, ncpus, 0);
> +	}

 What about to add CMD_CPU_SHOW and use it as a default if --enable/disable
 is not specified? 
 
 I know that you can use lscpu, but it's not intuitive... see for example 
 ionice, nice or so. You can see the current status and then change it.

 It's trivial change to the cpu_enable() function.

    Karel


-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH/RFC 2/2] chcpu: new tool
  2011-08-31  9:44   ` Karel Zak
@ 2011-08-31  9:47     ` Karel Zak
  0 siblings, 0 replies; 9+ messages in thread
From: Karel Zak @ 2011-08-31  9:47 UTC (permalink / raw)
  To: Heiko Carstens; +Cc: util-linux

On Wed, Aug 31, 2011 at 11:44:33AM +0200, Karel Zak wrote:
> On Mon, Aug 15, 2011 at 05:24:55PM +0200, Heiko Carstens wrote:
> > +	if ((argc == 1) || (argc != optind))
> > +		usage(stderr);
> > +
> > +	switch (cmd) {
> > +	case CMD_CPU_ENABLE:
> > +		return cpu_enable(cpu_set, ncpus, 1);
> > +	case CMD_CPU_DISABLE:
> > +		return cpu_enable(cpu_set, ncpus, 0);
> > +	}
> 
>  What about to add CMD_CPU_SHOW and use it as a default if --enable/disable
>  is not specified? 

 Ah... I see your updated version now. Sorry. Ignore my note about
 CMD_CPU_SHOW :-) It will be better to use lscpu. 

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] new chcpu tool
  2011-08-23  8:45     ` Heiko Carstens
@ 2011-08-31  9:56       ` Karel Zak
  0 siblings, 0 replies; 9+ messages in thread
From: Karel Zak @ 2011-08-31  9:56 UTC (permalink / raw)
  To: Heiko Carstens; +Cc: util-linux

On Tue, Aug 23, 2011 at 10:45:40AM +0200, Heiko Carstens wrote:
> I set up a chcpu git branch where you could pull the chcpu stuff easily:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/heiko/util-linux.git chcpu

 Merged to my private repository. The hera server at kernel.org is
 still off-line so I'll push it later. Thanks!

    Karel
-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2011-08-31  9:56 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-15 15:24 [PATCH/RFC 0/2] new chcpu tool Heiko Carstens
2011-08-15 15:24 ` [PATCH/RFC 1/2] cpuset: add option to allow cpulist_parse() to fail Heiko Carstens
2011-08-15 15:24 ` [PATCH/RFC 2/2] chcpu: new tool Heiko Carstens
2011-08-31  9:44   ` Karel Zak
2011-08-31  9:47     ` Karel Zak
2011-08-22 12:06 ` [PATCH] new chcpu tool Heiko Carstens
2011-08-22 13:28   ` Karel Zak
2011-08-23  8:45     ` Heiko Carstens
2011-08-31  9:56       ` Karel Zak

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.