summaryrefslogtreecommitdiff
path: root/sys-utils
diff options
context:
space:
mode:
authorLaMont Jones <lamont@debian.org>2010-08-02 23:02:28 -0600
committerLaMont Jones <lamont@debian.org>2010-08-02 23:02:28 -0600
commit0864d694ca05ea9383ef09bc1bc3a182e15e2ffa (patch)
tree2e5237f1d4e2cac2efad97ce31abc386c1e37b6d /sys-utils
parent3cbdfd84fde6159d7778e70618fbbc8df219cafe (diff)
parent6c91f5e3e1de32c45ea0b38227ce35eb43eb2ebc (diff)
downloadutil-linux-old-0864d694ca05ea9383ef09bc1bc3a182e15e2ffa.tar.gz
Merge remote branch 'origin/master'
Conflicts: mount/Makefile.am sys-utils/ipcs.c tests/ts/blkid/images-fs/befs.img.bz2 tests/ts/blkid/images-fs/ddf-raid.img.bz2
Diffstat (limited to 'sys-utils')
-rw-r--r--sys-utils/.gitignore5
-rw-r--r--sys-utils/Makefile.am34
-rw-r--r--sys-utils/fallocate.c5
-rw-r--r--sys-utils/flock.14
-rw-r--r--sys-utils/flock.c2
-rw-r--r--sys-utils/fsfreeze.875
-rw-r--r--sys-utils/fsfreeze.c132
-rw-r--r--sys-utils/ipcrm.c2
-rw-r--r--sys-utils/ipcs.c74
-rw-r--r--sys-utils/lscpu.19
-rw-r--r--sys-utils/lscpu.c683
-rw-r--r--sys-utils/rdev.8207
-rw-r--r--sys-utils/rdev.c279
-rw-r--r--sys-utils/tunelp.c6
14 files changed, 700 insertions, 817 deletions
diff --git a/sys-utils/.gitignore b/sys-utils/.gitignore
index 7985d7a5..7af5ffbf 100644
--- a/sys-utils/.gitignore
+++ b/sys-utils/.gitignore
@@ -4,6 +4,7 @@ cytune
dmesg
fallocate
flock
+fsfreeze
i386.8
ia64.8
ipcmk
@@ -23,11 +24,8 @@ pivot_root
ppc32.8
ppc64.8
ppc.8
-ramsize.8
-rdev
readprofile
renice
-rootflags.8
rtcwake
s390.8
s390x.8
@@ -40,5 +38,4 @@ sparc.8
switch_root
tunelp
unshare
-vidmode.8
x86_64.8
diff --git a/sys-utils/Makefile.am b/sys-utils/Makefile.am
index 76828cc1..166d7188 100644
--- a/sys-utils/Makefile.am
+++ b/sys-utils/Makefile.am
@@ -10,12 +10,19 @@ dist_man_MANS = flock.1 ipcrm.1 ipcs.1 ipcmk.1 renice.1 setsid.1 \
if LINUX
bin_PROGRAMS += dmesg
-sbin_PROGRAMS += ctrlaltdel
-usrbin_exec_PROGRAMS += cytune setarch lscpu
+sbin_PROGRAMS += ctrlaltdel fsfreeze
+usrbin_exec_PROGRAMS += cytune setarch
usrsbin_exec_PROGRAMS += ldattach tunelp rtcwake
dist_man_MANS += dmesg.1 ctrlaltdel.8 cytune.8 setarch.8 \
- ldattach.8 lscpu.1 tunelp.8 rtcwake.8
+ ldattach.8 tunelp.8 rtcwake.8 fsfreeze.8
+
+if HAVE_CPU_SET_T
+usrbin_exec_PROGRAMS += lscpu
+lscpu_SOURCES = lscpu.c $(top_srcdir)/lib/cpuset.c
+dist_man_MANS += lscpu.1
+endif
+
endif
cytune_SOURCES = cytune.c cyclades.h
@@ -23,9 +30,10 @@ tunelp_SOURCES = tunelp.c lp.h
info_TEXINFOS = ipc.texi
+
if BUILD_FALLOCATE
usrbin_exec_PROGRAMS += fallocate
-fallocate_SOURCES = fallocate.c ../lib/strtosize.c
+fallocate_SOURCES = fallocate.c $(top_srcdir)/lib/strtosize.c
dist_man_MANS += fallocate.1
endif
@@ -49,13 +57,6 @@ bin_PROGRAMS += arch
dist_man_MANS += arch.1
endif
-RDEV_LINKS =
-if BUILD_RDEV
-usrsbin_exec_PROGRAMS += rdev
-RDEV_LINKS += ramsize vidmode rootflags
-dist_man_MANS += rdev.8
-endif
-
SETARCH_LINKS = linux32 linux64
if ARCH_S390
@@ -83,21 +84,14 @@ if ARCH_HPPA
SETARCH_LINKS += parisc parisc64 parisc32
endif
-RDEV_MAN_LINKS = $(RDEV_LINKS:=.8)
SETARCH_MAN_LINKS = $(SETARCH_LINKS:=.8)
man_MANS = $(RDEV_MAN_LINKS) $(SETARCH_MAN_LINKS)
CLEANFILES = $(man_MANS)
-$(RDEV_MAN_LINKS): rdev.8
- echo ".so man8/rdev.8" > $@
-
-$(SETARCH_MAN_LINKS): setarch.8
- echo ".so man8/setarch.8" > $@
+$(SETARCH_MAN_LINKS):
+ $(AM_V_GEN)echo ".so man8/setarch.8" > $@
install-exec-hook:
- for I in $(RDEV_LINKS); do \
- cd $(DESTDIR)$(usrsbin_execdir) && ln -sf rdev $$I ; \
- done
for I in $(SETARCH_LINKS); do \
cd $(DESTDIR)$(usrbin_execdir) && ln -sf setarch $$I ; \
done
diff --git a/sys-utils/fallocate.c b/sys-utils/fallocate.c
index e41643a2..d1f43c24 100644
--- a/sys-utils/fallocate.c
+++ b/sys-utils/fallocate.c
@@ -122,6 +122,11 @@ int main(int argc, char **argv)
fname = argv[optind++];
+ if (optind != argc) {
+ warnx(_("unexpected number of arguments"));
+ usage(stderr);
+ }
+
fd = open(fname, O_WRONLY|O_CREAT, 0644);
if (fd < 0)
err(EXIT_FAILURE, _("%s: open failed"), fname);
diff --git a/sys-utils/flock.1 b/sys-utils/flock.1
index 6d60ff71..6ae584bd 100644
--- a/sys-utils/flock.1
+++ b/sys-utils/flock.1
@@ -51,11 +51,11 @@ used the following manner:
.PP
\fC(
.br
- flock -s 200
+ flock -s 9
.br
# ... commands executed under lock ...
.br
-) 200>/var/lock/mylockfile\fP
+) 9>/var/lock/mylockfile\fP
.PP
The mode used to open the file doesn't matter to \fBflock\fP; using
\fC>\fP or \fP>>\fP allows the lockfile to be created if it does not
diff --git a/sys-utils/flock.c b/sys-utils/flock.c
index 75c007c7..1f1c563b 100644
--- a/sys-utils/flock.c
+++ b/sys-utils/flock.c
@@ -253,7 +253,7 @@ int main(int argc, char *argv[])
memset(&sa, 0, sizeof sa);
sa.sa_handler = timeout_handler;
- sa.sa_flags = SA_ONESHOT;
+ sa.sa_flags = SA_RESETHAND;
sigaction(SIGALRM, &sa, &old_sa);
setitimer(ITIMER_REAL, &timeout, &old_timer);
diff --git a/sys-utils/fsfreeze.8 b/sys-utils/fsfreeze.8
new file mode 100644
index 00000000..4408bddd
--- /dev/null
+++ b/sys-utils/fsfreeze.8
@@ -0,0 +1,75 @@
+.\" -*- nroff -*-
+.TH FSFREEZE 8 "May 2010"
+.SH NAME
+fsfreeze \- suspend access to an filesystem (Linux Ext3/4, ReiserFS, JFS, XFS).
+.SH SYNOPSIS
+.B fsfreeze
+.RB \-f
+.I mountpoint
+
+.B fsfreeze
+.RB \-u
+.I mountpoint
+
+.SH DESCRIPTION
+.B fsfreeze
+suspends and resumes access to an filesystem
+.PP
+.B fsfreeze
+halts new access to the filesystem and creates a stable image on disk.
+.B fsfreeze
+is intended to be used with hardware RAID devices that support the creation
+of snapshots.
+.PP
+.B fsfreeze
+is unncessary for
+.B device-mapper
+devices. The device-mapper (and LVM)
+automatically freezes filesystem on the device when a snapshot creation is requested.
+For more details see the
+.BR dmsetup (8)
+man page.
+.PP
+The
+.I mount-point
+argument is the pathname of the directory where the filesystem
+is mounted.
+The filesystem must be mounted to be frozen (see
+.BR mount (8)).
+.SH OPTIONS
+.IP "\fB\-h, \-\-help\fP"
+Print help and exit.
+.IP "\fB\-f, \-\-freeze\fP"
+This option requests the specified a filesystem to be frozen from new
+modifications. When this is selected, all ongoing transactions in the
+filesystem are allowed to complete, new write system calls are halted, other
+calls which modify the filesystem are halted, and all dirty data, metadata, and
+log information are written to disk. Any process attempting to write to the
+frozen filesystem will block waiting for the filesystem to be unfrozen.
+
+Note that even after freezing, the on-disk filesystem can contain
+information on files that are still in the process of unlinking.
+These files will not be unlinked until the filesystem is unfrozen
+or a clean mount of the snapshot is complete.
+.IP "\fB\-u, \-\-unfreeze\fP
+This option is used to un-freeze the filesystem and allow operations to
+continue. Any filesystem modifications that were blocked by the freeze are
+unblocked and allowed to complete.
+.SH AUTHOR
+.PP
+Written by Hajime Taira.
+.SH NOTES
+.PP
+This man page based on xfs_freeze.
+One of
+.B \-f
+or
+.B \-u
+must be supplied to
+.BR fsfreeze .
+.SH SEE ALSO
+.BR mount (8)
+.SH AVAILABILITY
+The fsfreeze command is part of the util-linux-ng package and is available from
+ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/.
+
diff --git a/sys-utils/fsfreeze.c b/sys-utils/fsfreeze.c
new file mode 100644
index 00000000..4ca6e5e2
--- /dev/null
+++ b/sys-utils/fsfreeze.c
@@ -0,0 +1,132 @@
+/*
+ * fsfreeze.c -- Filesystem freeze/unfreeze IO for Linux
+ *
+ * Copyright (C) 2010 Hajime Taira <htaira@redhat.com>
+ * Masatake Yamato <yamato@redhat.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 1 or
+ * (at your option) any later version.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <getopt.h>
+#include <err.h>
+
+#include "blkdev.h"
+#include "nls.h"
+#include "c.h"
+
+static int freeze_f(int fd)
+{
+ return ioctl(fd, FIFREEZE, 0);
+}
+
+static int unfreeze_f(int fd)
+{
+ return ioctl(fd, FITHAW, 0);
+}
+
+static void __attribute__((__noreturn__)) usage(FILE *out)
+{
+ fprintf(out, _("Usage: %s [options] <mount point>\n\nOptions:\n"),
+ program_invocation_short_name);
+
+ fprintf(out, _(
+ " -h, --help this help\n"
+ " -f, --freeze freeze the filesystem\n"
+ " -u, --unfreeze unfreeze the filesystem\n"));
+
+ fprintf(out, _("\nFor more information see fsfreeze(8).\n"));
+
+ exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
+}
+
+int main(int argc, char **argv)
+{
+ int fd = -1, c;
+ int freeze = -1, rc = EXIT_FAILURE;
+ char *path;
+ struct stat sb;
+
+ struct option longopts[] = {
+ { "help", 0, 0, 'h' },
+ { "freeze", 0, 0, 'f' },
+ { "unfreeze", 0, 0, 'u' },
+ { NULL, 0, 0, 0 }
+ };
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ while ((c = getopt_long(argc, argv, "hfu", longopts, NULL)) != -1) {
+ switch(c) {
+ case 'h':
+ usage(stdout);
+ break;
+ case 'f':
+ freeze = TRUE;
+ break;
+ case 'u':
+ freeze = FALSE;
+ break;
+ default:
+ usage(stderr);
+ break;
+ }
+ }
+
+ if (freeze == -1)
+ errx(EXIT_FAILURE, _("no action specified"));
+ if (optind == argc)
+ errx(EXIT_FAILURE, _("no filename specified"));
+ path = argv[optind++];
+
+ if (optind != argc) {
+ warnx(_("unexpected number of arguments"));
+ usage(stderr);
+ }
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ err(EXIT_FAILURE, _("%s: open failed"), path);
+
+ if (fstat(fd, &sb) == -1) {
+ warn(_("%s: fstat failed"), path);
+ goto done;
+ }
+
+ if (!S_ISDIR(sb.st_mode)) {
+ warnx(_("%s: is not a directory"), path);
+ goto done;
+ }
+
+ if (freeze) {
+ if (freeze_f(fd)) {
+ warn(_("%s: freeze failed"), path);
+ goto done;
+ }
+ } else {
+ if (unfreeze_f(fd)) {
+ warn(_("%s: unfreeze failed"), path);
+ goto done;
+ }
+ }
+
+ rc = EXIT_SUCCESS;
+done:
+ if (fd >= 0)
+ close(fd);
+ return rc;
+}
+
diff --git a/sys-utils/ipcrm.c b/sys-utils/ipcrm.c
index f07eac82..e8d6ba61 100644
--- a/sys-utils/ipcrm.c
+++ b/sys-utils/ipcrm.c
@@ -176,8 +176,6 @@ int main(int argc, char **argv)
/* make sure the option is in range */
if (c != 'q' && c != 'm' && c != 's') {
- fprintf(stderr, _("%s: illegal option -- %c\n"),
- prog, c);
usage(prog);
error++;
return error;
diff --git a/sys-utils/ipcs.c b/sys-utils/ipcs.c
index 99ad09d7..0a950f66 100644
--- a/sys-utils/ipcs.c
+++ b/sys-utils/ipcs.c
@@ -109,26 +109,41 @@ void print_shm (int id);
void print_msg (int id);
void print_sem (int id);
-static char *progname;
-
static void
usage(int rc) {
- printf (_("usage : %s -asmq -tclup \n"), progname);
- printf (_("\t%s [-s -m -q] -i id\n"), progname);
- printf (_("\t%s -h for help.\n"), progname);
+ printf (_("Usage: %1$s [-asmq] [-t|-c|-l|-u|-p]\n"
+ " %1$s [-s|-m|-q] -i id\n"
+ " %1$s -h for help\n"),
+ program_invocation_short_name);
exit(rc);
}
static void
help (int rc) {
- printf (_("%s provides information on ipc facilities for"
- " which you have read access.\n"), progname);
- printf (_("Resource Specification:\n\t-m : shared_mem\n\t-q : messages\n"));
- printf (_("\t-s : semaphores\n\t-a : all (default)\n"));
- printf (_("Output Format:\n\t-t : time\n\t-p : pid\n\t-c : creator\n"));
- printf (_("\t-l : limits\n\t-u : summary\n"));
- printf (_("-i id [-s -q -m] : details on resource identified by id\n"));
- usage(rc);
+ printf (_("Usage: %1$s [resource]... [output-format]\n"
+ " %1$s [resource] -i id\n\n"),
+ program_invocation_short_name);
+
+ printf (_("Provide information on IPC facilities for which you "
+ "have read access.\n\n"));
+
+ printf (_(
+ " -h display this help\n"
+ " -i id print details on resource identified by id\n\n"));
+
+ printf (_("Resource options:\n"
+ " -m shared memory segments\n"
+ " -q message queues\n"
+ " -s semaphores\n"
+ " -a all (default)\n\n"));
+
+ printf (_("Output format:\n"
+ " -t time\n"
+ " -p pid\n"
+ " -c creator\n"
+ " -l limits\n"
+ " -u summary\n"));
+ exit(rc);
}
int
@@ -141,7 +156,6 @@ main (int argc, char **argv) {
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
- progname = argv[0];
while ((opt = getopt (argc, argv, options)) != -1) {
switch (opt) {
case 'i':
@@ -274,11 +288,25 @@ void do_shm (char format)
case STATUS:
printf (_("------ Shared Memory Status --------\n"));
- printf (_("segments allocated %d\n"), shm_info.used_ids);
- printf (_("pages allocated %ld\n"), shm_info.shm_tot);
- printf (_("pages resident %ld\n"), shm_info.shm_rss);
- printf (_("pages swapped %ld\n"), shm_info.shm_swp);
- printf (_("Swap performance: %ld attempts\t %ld successes\n"),
+ /* TRANSLATORS: This output format is mantained for backward compatibility
+ as ipcs is used in scripts. For consistency with the rest, the translated
+ form can follow this model:
+
+ "segments allocated = %d\n"
+ "pages allocated = %ld\n"
+ "pages resident = %ld\n"
+ "pages swapped = %ld\n"
+ "swap performance = %ld attempts, %ld successes\n"
+ */
+ printf (_("segments allocated %d\n"
+ "pages allocated %ld\n"
+ "pages resident %ld\n"
+ "pages swapped %ld\n"
+ "Swap performance: %ld attempts\t %ld successes\n"),
+ shm_info.used_ids,
+ shm_info.shm_tot,
+ shm_info.shm_rss,
+ shm_info.shm_swp,
shm_info.swap_attempts, shm_info.swap_successes);
return;
@@ -296,7 +324,7 @@ void do_shm (char format)
break;
case PID:
- printf (_("------ Shared Memory Creator/Last-op --------\n"));
+ printf (_("------ Shared Memory Creator/Last-op PIDs --------\n"));
printf ("%-10s %-10s %-10s %-10s\n",
_("shmid"),_("owner"),_("cpid"),_("lpid"));
break;
@@ -487,14 +515,14 @@ void do_msg (char format)
case LIMITS:
if ((msgctl (0, IPC_INFO, (struct msqid_ds *) (void *) &msginfo)) < 0 )
return;
- printf (_("------ Messages: Limits --------\n"));
+ printf (_("------ Messages Limits --------\n"));
printf (_("max queues system wide = %d\n"), msginfo.msgmni);
printf (_("max size of message (bytes) = %d\n"), msginfo.msgmax);
printf (_("default max size of queue (bytes) = %d\n"), msginfo.msgmnb);
return;
case STATUS:
- printf (_("------ Messages: Status --------\n"));
+ printf (_("------ Messages Status --------\n"));
#ifndef __FreeBSD_kernel__
printf (_("allocated queues = %d\n"), msginfo.msgpool);
printf (_("used headers = %d\n"), msginfo.msgmap);
@@ -503,7 +531,7 @@ void do_msg (char format)
return;
case CREATOR:
- printf (_("------ Message Queues: Creators/Owners --------\n"));
+ printf (_("------ Message Queues Creators/Owners --------\n"));
printf ("%-10s %-10s %-10s %-10s %-10s %-10s\n",
_("msqid"),_("perms"),_("cuid"),_("cgid"),_("uid"),_("gid"));
break;
diff --git a/sys-utils/lscpu.1 b/sys-utils/lscpu.1
index 2b8d33b1..4f78ee6b 100644
--- a/sys-utils/lscpu.1
+++ b/sys-utils/lscpu.1
@@ -23,12 +23,15 @@ Print a help message.
.BR \-p , " \-\-parse"
Print out in parsable instead of printable format.
.SH BUGS
-The program at the moment does not handle the system installed with
-different types of physical processors.
+The basic overview about CPU family, model, etc. is always based on the first
+CPU only.
Sometimes in Xen Dom0 kernel reports wrong data.
.SH AUTHOR
+.nf
Cai Qian <qcai@redhat.com>
+Karel Zak <kzak@redhat.com>
+.fi
.SH AVAILABILITY
-The setarch command is part of the util-linux-ng package and is available from
+The lscpu command is part of the util-linux-ng package and is available from
ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/.
diff --git a/sys-utils/lscpu.c b/sys-utils/lscpu.c
index 77a3e5c2..74f5e781 100644
--- a/sys-utils/lscpu.c
+++ b/sys-utils/lscpu.c
@@ -31,28 +31,18 @@
#include <unistd.h>
#include <stdarg.h>
+#include "cpuset.h"
#include "nls.h"
#define CACHE_MAX 100
/* /sys paths */
-#define _PATH_SYS_SYSTEM "sys/devices/system"
-#define _PATH_SYS_CPU0 _PATH_SYS_SYSTEM "/cpu/cpu0"
-#define _PATH_PROC_XEN "proc/xen"
+#define _PATH_SYS_SYSTEM "/sys/devices/system"
+#define _PATH_SYS_CPU _PATH_SYS_SYSTEM "/cpu"
+#define _PATH_PROC_XEN "/proc/xen"
#define _PATH_PROC_XENCAP _PATH_PROC_XEN "/capabilities"
-#define _PATH_PROC_CPUINFO "proc/cpuinfo"
-#define _PATH_PROC_PCIDEVS "proc/bus/pci/devices"
-
-int have_topology;
-int have_cache;
-int have_node;
-
-/* cache(s) description */
-struct ca_desc {
- char *caname;
- char *casize;
- int camap;
-};
+#define _PATH_PROC_CPUINFO "/proc/cpuinfo"
+#define _PATH_PROC_PCIDEVS "/proc/bus/pci/devices"
/* virtualization types */
enum {
@@ -87,17 +77,17 @@ enum {
MODE_LONG = (1 << 3)
};
-/* CPU(s) description */
-struct cpu_desc {
- /* counters */
- int ct_cpu;
- int ct_thread;
- int ct_core;
- int ct_socket;
- int ct_node;
- int ct_cache;
-
- /* who is who */
+/* cache(s) description */
+struct cpu_cache {
+ char *name;
+ char *size;
+
+ int nsharedmaps;
+ cpu_set_t **sharedmaps;
+};
+
+/* global description */
+struct lscpu_desc {
char *arch;
char *vendor;
char *family;
@@ -105,78 +95,137 @@ struct cpu_desc {
char *virtflag; /* virtualization flag (vmx, svm) */
int hyper; /* hypervisor vendor ID */
int virtype; /* VIRT_PARA|FULL|NONE ? */
-
- /* caches */
- struct ca_desc cache[CACHE_MAX];
-
- /* misc */
char *mhz;
char *stepping;
char *flags;
-
int mode; /* rm, lm or/and tm */
- /* NUMA */
- int *nodecpu;
+ int ncpus; /* number of CPUs */
+
+ int nnodes; /* number of NUMA modes */
+ cpu_set_t **nodemaps; /* array with NUMA nodes */
+
+ /* sockets -- based on core_siblings (internal kernel map of cpuX's
+ * hardware threads within the same physical_package_id (socket)) */
+ int nsockets; /* number of all sockets */
+ cpu_set_t **socketmaps; /* unique core_siblings */
+
+ /* cores -- based on thread_siblings (internel kernel map of cpuX's
+ * hardware threads within the same core as cpuX) */
+ int ncores; /* number of all cores */
+ cpu_set_t **coremaps; /* unique thread_siblings */
+
+ int nthreads; /* number of threads */
+
+ int ncaches;
+ struct cpu_cache *caches;
};
-char pathbuf[PATH_MAX] = "/";
+static size_t sysrootlen;
+static char pathbuf[PATH_MAX];
+static int maxcpus; /* size in bits of kernel cpu mask */
-static void path_scanstr(char *result, const char *path, ...)
- __attribute__ ((__format__ (__printf__, 2, 3)));
+static FILE *path_fopen(const char *mode, int exit_on_err, const char *path, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+static void path_getstr(char *result, size_t len, const char *path, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+static int path_getnum(const char *path, ...)
+ __attribute__ ((__format__ (__printf__, 1, 2)));
static int path_exist(const char *path, ...)
__attribute__ ((__format__ (__printf__, 1, 2)));
-static int path_sibling(const char *path, ...)
+static cpu_set_t *path_cpuset(const char *path, ...)
__attribute__ ((__format__ (__printf__, 1, 2)));
+static const char *
+path_vcreate(const char *path, va_list ap)
+{
+ if (sysrootlen)
+ vsnprintf(pathbuf + sysrootlen,
+ sizeof(pathbuf) - sysrootlen, path, ap);
+ else
+ vsnprintf(pathbuf, sizeof(pathbuf), path, ap);
+ return pathbuf;
+}
+
static FILE *
-xfopen(const char *path, const char *mode)
+path_vfopen(const char *mode, int exit_on_error, const char *path, va_list ap)
{
- FILE *fd = fopen(path, mode);
- if (!fd)
- err(EXIT_FAILURE, _("error: %s"), path);
- return fd;
+ FILE *f;
+ const char *p = path_vcreate(path, ap);
+
+ f = fopen(p, mode);
+ if (!f && exit_on_error)
+ err(EXIT_FAILURE, _("error: cannot open %s"), p);
+ return f;
}
static FILE *
-path_vfopen(const char *mode, const char *path, va_list ap)
+path_fopen(const char *mode, int exit_on_error, const char *path, ...)
{
- vsnprintf(pathbuf, sizeof(pathbuf), path, ap);
- return xfopen(pathbuf, mode);
+ FILE *fd;
+ va_list ap;
+
+ va_start(ap, path);
+ fd = path_vfopen("r", exit_on_error, path, ap);
+ va_end(ap);
+
+ return fd;
}
static void
-path_scanstr(char *result, const char *path, ...)
+path_getstr(char *result, size_t len, const char *path, ...)
{
FILE *fd;
va_list ap;
va_start(ap, path);
- fd = path_vfopen("r", path, ap);
+ fd = path_vfopen("r", 1, path, ap);
va_end(ap);
- if (fscanf(fd, "%s", result) != 1) {
+ if (!fgets(result, len, fd))
+ err(EXIT_FAILURE, _("failed to read: %s"), pathbuf);
+ fclose(fd);
+
+ len = strlen(result);
+ if (result[len - 1] == '\n')
+ result[len - 1] = '\0';
+}
+
+static int
+path_getnum(const char *path, ...)
+{
+ FILE *fd;
+ va_list ap;
+ int result;
+
+ va_start(ap, path);
+ fd = path_vfopen("r", 1, path, ap);
+ va_end(ap);
+
+ if (fscanf(fd, "%d", &result) != 1) {
if (ferror(fd))
- err(EXIT_FAILURE, _("error: %s"), pathbuf);
+ err(EXIT_FAILURE, _("failed to read: %s"), pathbuf);
else
- errx(EXIT_FAILURE, _("error parse: %s"), pathbuf);
+ errx(EXIT_FAILURE, _("parse error: %s"), pathbuf);
}
fclose(fd);
+ return result;
}
static int
path_exist(const char *path, ...)
{
va_list ap;
+ const char *p;
va_start(ap, path);
- vsnprintf(pathbuf, sizeof(pathbuf), path, ap);
+ p = path_vcreate(path, ap);
va_end(ap);
- return access(pathbuf, F_OK) == 0;
+ return access(p, F_OK) == 0;
}
-char *
+static char *
xstrdup(const char *str)
{
char *s = strdup(str);
@@ -185,33 +234,35 @@ xstrdup(const char *str)
return s;
}
-/* count the set bit in a mapping file */
-static int
-path_sibling(const char *path, ...)
+static cpu_set_t *
+path_cpuset(const char *path, ...)
{
- int c, n;
- int result = 0;
- char s[2];
- FILE *fp;
+ FILE *fd;
va_list ap;
+ cpu_set_t *set;
+ size_t setsize, len = maxcpus * 7;
+ char buf[len];
va_start(ap, path);
- fp = path_vfopen("r", path, ap);
+ fd = path_vfopen("r", 1, path, ap);
va_end(ap);
- while ((c = fgetc(fp)) != EOF) {
- if (isxdigit(c)) {
- s[0] = c;
- s[1] = '\0';
- for (n = strtol(s, NULL, 16); n > 0; n /= 2) {
- if (n % 2)
- result++;
- }
- }
- }
- fclose(fp);
+ if (!fgets(buf, len, fd))
+ err(EXIT_FAILURE, _("failed to read: %s"), pathbuf);
+ fclose(fd);
- return result;
+ len = strlen(buf);
+ if (buf[len - 1] == '\n')
+ buf[len - 1] = '\0';
+
+ set = cpuset_alloc(maxcpus, &setsize, NULL);
+ if (!set)
+ err(EXIT_FAILURE, _("failed to callocate cpu set"));
+
+ if (cpumask_parse(buf, set, setsize))
+ errx(EXIT_FAILURE, _("failed to parse CPU mask %s"), buf);
+
+ return set;
}
/* Lookup a pattern and get the value from cpuinfo.
@@ -256,53 +307,64 @@ int lookup(char *line, char *pattern, char **value)
}
static void
-read_basicinfo(struct cpu_desc *cpu)
+read_basicinfo(struct lscpu_desc *desc)
{
- FILE *fp = xfopen(_PATH_PROC_CPUINFO, "r");
+ FILE *fp = path_fopen("r", 1, _PATH_PROC_CPUINFO);
char buf[BUFSIZ];
struct utsname utsbuf;
/* architecture */
if (uname(&utsbuf) == -1)
err(EXIT_FAILURE, _("error: uname failed"));
- cpu->arch = xstrdup(utsbuf.machine);
+ desc->arch = xstrdup(utsbuf.machine);
/* count CPU(s) */
- while(path_exist(_PATH_SYS_SYSTEM "/cpu/cpu%d", cpu->ct_cpu))
- cpu->ct_cpu++;
+ while(path_exist(_PATH_SYS_SYSTEM "/cpu/cpu%d", desc->ncpus))
+ desc->ncpus++;
/* details */
while (fgets(buf, sizeof(buf), fp) != NULL) {
/* IA64 */
- if (lookup(buf, "vendor", &cpu->vendor)) ;
- else if (lookup(buf, "vendor_id", &cpu->vendor)) ;
+ if (lookup(buf, "vendor", &desc->vendor)) ;
+ else if (lookup(buf, "vendor_id", &desc->vendor)) ;
/* IA64 */
- else if (lookup(buf, "family", &cpu->family)) ;
- else if (lookup(buf, "cpu family", &cpu->family)) ;
- else if (lookup(buf, "model", &cpu->model)) ;
- else if (lookup(buf, "stepping", &cpu->stepping)) ;
- else if (lookup(buf, "cpu MHz", &cpu->mhz)) ;
- else if (lookup(buf, "flags", &cpu->flags)) ;
+ else if (lookup(buf, "family", &desc->family)) ;
+ else if (lookup(buf, "cpu family", &desc->family)) ;
+ else if (lookup(buf, "model", &desc->model)) ;
+ else if (lookup(buf, "stepping", &desc->stepping)) ;
+ else if (lookup(buf, "cpu MHz", &desc->mhz)) ;
+ else if (lookup(buf, "flags", &desc->flags)) ;
else
continue;
}
- if (cpu->flags) {
- snprintf(buf, sizeof(buf), " %s ", cpu->flags);
+ if (desc->flags) {
+ snprintf(buf, sizeof(buf), " %s ", desc->flags);
if (strstr(buf, " svm "))
- cpu->virtflag = strdup("svm");
+ desc->virtflag = strdup("svm");
else if (strstr(buf, " vmx "))
- cpu->virtflag = strdup("vmx");
+ desc->virtflag = strdup("vmx");
if (strstr(buf, " rm "))
- cpu->mode |= MODE_REAL;
+ desc->mode |= MODE_REAL;
if (strstr(buf, " tm "))
- cpu->mode |= MODE_TRANSPARENT;
+ desc->mode |= MODE_TRANSPARENT;
if (strstr(buf, " lm "))
- cpu->mode |= MODE_LONG;
+ desc->mode |= MODE_LONG;
}
fclose(fp);
+
+ if (path_exist(_PATH_SYS_SYSTEM "/cpu/kernel_max"))
+ maxcpus = path_getnum(_PATH_SYS_SYSTEM "/cpu/kernel_max");
+
+ else if (!sysrootlen)
+ /* the root is '/' so we are working with data from the current kernel */
+ maxcpus = get_max_number_of_cpus();
+ else
+ /* we are reading some /sys snapshot instead of the real /sys,
+ * let's use any crazy number... */
+ maxcpus = desc->ncpus > 2048 ? desc->ncpus : 2048;
}
static int
@@ -312,7 +374,7 @@ has_pci_device(int vendor, int device)
int num, fn, ven, dev;
int res = 1;
- f = fopen(_PATH_PROC_PCIDEVS, "r");
+ f = path_fopen("r", 0, _PATH_PROC_PCIDEVS);
if (!f)
return 0;
@@ -364,7 +426,7 @@ cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx,
}
static void
-read_hypervisor_cpuid(struct cpu_desc *cpu)
+read_hypervisor_cpuid(struct lscpu_desc *desc)
{
unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0;
char hyper_vendor_id[13];
@@ -381,32 +443,32 @@ read_hypervisor_cpuid(struct cpu_desc *cpu)
return;
if (!strncmp("XenVMMXenVMM", hyper_vendor_id, 12))
- cpu->hyper = HYPER_XEN;
+ desc->hyper = HYPER_XEN;
else if (!strncmp("KVMKVMKVM", hyper_vendor_id, 9))
- cpu->hyper = HYPER_KVM;
+ desc->hyper = HYPER_KVM;
else if (!strncmp("Microsoft Hv", hyper_vendor_id, 12))
- cpu->hyper = HYPER_MSHV;
+ desc->hyper = HYPER_MSHV;
}
#else /* ! __x86_64__ */
static void
-read_hypervisor_cpuid(struct cpu_desc *cpu)
+read_hypervisor_cpuid(struct lscpu_desc *desc)
{
}
#endif
static void
-read_hypervisor(struct cpu_desc *cpu)
+read_hypervisor(struct lscpu_desc *desc)
{
- read_hypervisor_cpuid(cpu);
+ read_hypervisor_cpuid(desc);
- if (cpu->hyper)
+ if (desc->hyper)
/* hvm */
- cpu->virtype = VIRT_FULL;
+ desc->virtype = VIRT_FULL;
- else if (!access(_PATH_PROC_XEN, F_OK)) {
+ else if (path_exist(_PATH_PROC_XEN)) {
/* Xen para-virt or dom0 */
- FILE *fd = fopen(_PATH_PROC_XENCAP, "r");
+ FILE *fd = path_fopen("r", 0, _PATH_PROC_XENCAP);
int dom0 = 0;
if (fd) {
@@ -417,123 +479,179 @@ read_hypervisor(struct cpu_desc *cpu)
dom0 = 1;
fclose(fd);
}
- cpu->virtype = dom0 ? VIRT_NONE : VIRT_PARA;
- cpu->hyper = HYPER_XEN;
+ desc->virtype = dom0 ? VIRT_NONE : VIRT_PARA;
+ desc->hyper = HYPER_XEN;
} else if (has_pci_device(0x5853, 0x0001)) {
/* Xen full-virt on non-x86_64 */
- cpu->hyper = HYPER_XEN;
- cpu->virtype = VIRT_FULL;
+ desc->hyper = HYPER_XEN;
+ desc->virtype = VIRT_FULL;
}
}
-static void
-read_topology(struct cpu_desc *cpu)
+/* add @set to the @ary, unnecesary set is deallocated. */
+static int add_cpuset_to_array(cpu_set_t **ary, int *items, cpu_set_t *set)
{
- /* number of threads */
- cpu->ct_thread = path_sibling(
- _PATH_SYS_CPU0 "/topology/thread_siblings");
+ int i;
+ size_t setsize = CPU_ALLOC_SIZE(maxcpus);
- /* number of cores */
- cpu->ct_core = path_sibling(
- _PATH_SYS_CPU0 "/topology/core_siblings")
- / cpu->ct_thread;
+ if (!ary)
+ return -1;
- /* number of sockets */
- cpu->ct_socket = cpu->ct_cpu / cpu->ct_core / cpu->ct_thread;
+ for (i = 0; i < *items; i++) {
+ if (CPU_EQUAL_S(setsize, set, ary[i]))
+ break;
+ }
+ if (i == *items) {
+ ary[*items] = set;
+ ++*items;
+ return 0;
+ }
+ CPU_FREE(set);
+ return 1;
}
static void
-read_cache(struct cpu_desc *cpu)
+read_topology(struct lscpu_desc *desc, int num)
{
- char buf[256];
- DIR *dp;
- struct dirent *dir;
- int level, type;
+ cpu_set_t *thread_siblings, *core_siblings;
- dp = opendir(_PATH_SYS_CPU0 "/cache");
- if (dp == NULL)
- err(EXIT_FAILURE, _("error: %s"), _PATH_SYS_CPU0 "/cache");
+ if (!path_exist(_PATH_SYS_CPU "/cpu%d/topology/thread_siblings", num))
+ return;
- while ((dir = readdir(dp)) != NULL) {
- if (!strcmp(dir->d_name, ".")
- || !strcmp(dir->d_name, ".."))
- continue;
+ thread_siblings = path_cpuset(_PATH_SYS_CPU
+ "/cpu%d/topology/thread_siblings", num);
+ core_siblings = path_cpuset(_PATH_SYS_CPU
+ "/cpu%d/topology/core_siblings", num);
+ if (num == 0) {
+ int ncores, nsockets, nthreads;
+ size_t setsize = CPU_ALLOC_SIZE(maxcpus);
+
+ /* threads within one core */
+ nthreads = CPU_COUNT_S(setsize, thread_siblings);
+ /* cores within one socket */
+ ncores = CPU_COUNT_S(setsize, core_siblings) / nthreads;
+ /* number of sockets */
+ nsockets = desc->ncpus / nthreads / ncores;
+ /* all threads */
+ desc->nthreads = nsockets * ncores * nthreads;
+
+ desc->socketmaps = calloc(nsockets, sizeof(cpu_set_t *));
+ if (!desc->socketmaps)
+ err(EXIT_FAILURE, _("error: calloc failed"));
+ desc->coremaps = calloc(ncores * nsockets, sizeof(cpu_set_t *));
+ if (!desc->coremaps)
+ err(EXIT_FAILURE, _("error: calloc failed"));
+ }
- /* cache type */
- path_scanstr(buf, _PATH_SYS_CPU0 "/cache/%s/type", dir->d_name);
- if (!strcmp(buf, "Data"))
- type = 'd';
- else if (!strcmp(buf, "Instruction"))
- type = 'i';
- else
- type = 0;
+ add_cpuset_to_array(desc->socketmaps, &desc->nsockets, core_siblings);
+ add_cpuset_to_array(desc->coremaps, &desc->ncores, thread_siblings);
+}
- /* cache level */
- path_scanstr(buf, _PATH_SYS_CPU0 "/cache/%s/level", dir->d_name);
- level = atoi(buf);
+static int
+cachecmp(const void *a, const void *b)
+{
+ struct cpu_cache *c1 = (struct cpu_cache *) a;
+ struct cpu_cache *c2 = (struct cpu_cache *) b;
- if (type)
- snprintf(buf, sizeof(buf), "L%d%c", level, type);
- else
- snprintf(buf, sizeof(buf), "L%d", level);
+ return strcmp(c2->name, c1->name);
+}
+
+static void
+read_cache(struct lscpu_desc *desc, int num)
+{
+ char buf[256];
+ int i;
- cpu->cache[cpu->ct_cache].caname = xstrdup(buf);
+ if (num == 0) {
+ while(path_exist(_PATH_SYS_SYSTEM "/cpu/cpu%d/cache/index%d",
+ num, desc->ncaches))
+ desc->ncaches++;
- /* cache size */
- path_scanstr(buf, _PATH_SYS_CPU0 "/cache/%s/size", dir->d_name);
- cpu->cache[cpu->ct_cache].casize = xstrdup(buf);
+ if (!desc->ncaches)
+ return;
+
+ desc->caches = calloc(desc->ncaches, sizeof(*desc->caches));
+ if (!desc->caches)
+ err(EXIT_FAILURE, _("calloc failed"));
+ }
+ for (i = 0; i < desc->ncaches; i++) {
+ struct cpu_cache *ca = &desc->caches[i];
+ cpu_set_t *map;
+
+ if (!ca->name) {
+ int type, level;
+
+ /* cache type */
+ path_getstr(buf, sizeof(buf),
+ _PATH_SYS_CPU "/cpu%d/cache/index%d/type",
+ num, i);
+ if (!strcmp(buf, "Data"))
+ type = 'd';
+ else if (!strcmp(buf, "Instruction"))
+ type = 'i';
+ else
+ type = 0;
+
+ /* cache level */
+ level = path_getnum(_PATH_SYS_CPU "/cpu%d/cache/index%d/level",
+ num, i);
+ if (type)
+ snprintf(buf, sizeof(buf), "L%d%c", level, type);
+ else
+ snprintf(buf, sizeof(buf), "L%d", level);
+
+ ca->name = xstrdup(buf);
+
+ /* cache size */
+ path_getstr(buf, sizeof(buf),
+ _PATH_SYS_CPU "/cpu%d/cache/index%d/size",
+ num, i);
+ ca->size = xstrdup(buf);
+ }
/* information about how CPUs share different caches */
- cpu->cache[cpu->ct_cache].camap = path_sibling(
- _PATH_SYS_CPU0 "/cache/%s/shared_cpu_map",
- dir->d_name);
- cpu->ct_cache++;
+ map = path_cpuset(_PATH_SYS_CPU "/cpu%d/cache/index%d/shared_cpu_map",
+ num, i);
+
+ if (!ca->sharedmaps) {
+ ca->sharedmaps = calloc(desc->ncpus, sizeof(cpu_set_t *));
+ if (!ca->sharedmaps)
+ err(EXIT_FAILURE, _("error: calloc failed"));
+ }
+
+ add_cpuset_to_array(ca->sharedmaps, &ca->nsharedmaps, map);
}
}
static void
-read_nodes(struct cpu_desc *cpu)
+read_nodes(struct lscpu_desc *desc)
{
int i;
/* number of NUMA node */
- while (path_exist(_PATH_SYS_SYSTEM "/node/node%d", cpu->ct_node))
- cpu->ct_node++;
+ while (path_exist(_PATH_SYS_SYSTEM "/node/node%d", desc->nnodes))
+ desc->nnodes++;
+
+ if (!desc->nnodes)
+ return;
- cpu->nodecpu = (int *) malloc(cpu->ct_node * sizeof(int));
- if (!cpu->nodecpu)
- err(EXIT_FAILURE, _("error: malloc failed"));
+ desc->nodemaps = calloc(desc->nnodes, sizeof(cpu_set_t *));
+ if (!desc->nodemaps)
+ err(EXIT_FAILURE, _("error: calloc failed"));
/* information about how nodes share different CPUs */
- for (i = 0; i < cpu->ct_node; i++)
- cpu->nodecpu[i] = path_sibling(
+ for (i = 0; i < desc->nnodes; i++)
+ desc->nodemaps[i] = path_cpuset(
_PATH_SYS_SYSTEM "/node/node%d/cpumap",
i);
}
static void
-check_system(void)
-{
- /* Read through sysfs. */
- if (access(_PATH_SYS_SYSTEM, F_OK))
- errx(EXIT_FAILURE,
- _("error: /sys filesystem is not accessable."));
-
- if (!access(_PATH_SYS_SYSTEM "/node", F_OK))
- have_node = 1;
-
- if (!access(_PATH_SYS_CPU0 "/topology/thread_siblings", F_OK))
- have_topology = 1;
-
- if (!access(_PATH_SYS_CPU0 "/cache", F_OK))
- have_cache = 1;
-}
-
-static void
-print_parsable(struct cpu_desc *cpu)
+print_parsable(struct lscpu_desc *desc)
{
int i, j;
+ size_t setsize = CPU_ALLOC_SIZE(maxcpus);
printf(_(
"# The following is the parsable format, which can be fed to other\n"
@@ -541,50 +659,66 @@ print_parsable(struct cpu_desc *cpu)
"# starting from zero.\n"
"# CPU,Core,Socket,Node"));
- if (have_cache) {
+ if (desc->ncaches) {
/* separator between CPU topology and cache information */
putchar(',');
- for (i = cpu->ct_cache - 1; i >= 0; i--)
- printf(",%s", cpu->cache[i].caname);
+ for (i = desc->ncaches - 1; i >= 0; i--)
+ printf(",%s", desc->caches[i].name);
}
putchar('\n');
- for (i = 0; i < cpu->ct_cpu; i++) {
+ for (i = 0; i < desc->ncpus; i++) {
+
+ /* #CPU */
printf("%d", i);
- if (have_topology)
- printf(",%d,%d",
- i / cpu->ct_thread,
- i / cpu->ct_core / cpu->ct_thread);
- else
- printf(",,");
+ /* Core */
+ for (j = 0; j < desc->ncores; j++) {
+ if (CPU_ISSET_S(i, setsize, desc->coremaps[j])) {
+ printf(",%d", j);
+ break;
+ }
+ }
+ if (j == desc->ncores)
+ putchar(',');
- if (have_node) {
- int c = 0;
+ /* Socket */
+ for (j = 0; j < desc->nsockets; j++) {
+ if (CPU_ISSET_S(i, setsize, desc->socketmaps[j])) {
+ printf(",%d", j);
+ break;
+ }
+ }
+ if (j == desc->nsockets)
+ putchar(',');
- for (j = 0; j < cpu->ct_node; j++) {
- c += cpu->nodecpu[j];
- if (i < c) {
- printf(",%d", j);
- break;
- }
+ /* Nodes */
+ for (j = 0; j < desc->nnodes; j++) {
+ if (CPU_ISSET_S(i, setsize, desc->nodemaps[j])) {
+ printf(",%d", j);
+ break;
}
- } else
+ }
+ if (j == desc->nnodes)
putchar(',');
- if (have_cache) {
+ if (desc->ncaches)
putchar(',');
- for (j = cpu->ct_cache - 1; j >= 0; j--) {
- /* If shared_cpu_map is 0, all CPUs share the same
- cache. */
- if (cpu->cache[j].camap == 0)
- cpu->cache[j].camap = cpu->ct_core *
- cpu->ct_thread;
+ /* Caches */
+ for (j = desc->ncaches - 1; j >= 0; j--) {
+ struct cpu_cache *ca = &desc->caches[j];
+ int x;
- printf(",%d", i / cpu->cache[j].camap);
+ for (x = 0; x < ca->nsharedmaps; x++) {
+ if (CPU_ISSET_S(i, setsize, ca->sharedmaps[x])) {
+ printf(",%d", x);
+ break;
+ }
}
+ if (x == ca->nsharedmaps)
+ putchar(',');
}
putchar('\n');
}
@@ -596,22 +730,25 @@ print_parsable(struct cpu_desc *cpu)
#define print_n(_key, _val) printf("%-23s%d\n", _key, _val)
static void
-print_readable(struct cpu_desc *cpu)
+print_readable(struct lscpu_desc *desc)
{
- print_s("Architecture:", cpu->arch);
+ char buf[512];
+ int i;
+
+ print_s(_("Architecture:"), desc->arch);
- if (cpu->mode & (MODE_REAL | MODE_TRANSPARENT | MODE_LONG)) {
+ if (desc->mode & (MODE_REAL | MODE_TRANSPARENT | MODE_LONG)) {
char buf[64], *p = buf;
- if (cpu->mode & MODE_REAL) {
+ if (desc->mode & MODE_REAL) {
strcpy(p, "16-bit, ");
p += 8;
}
- if (cpu->mode & MODE_TRANSPARENT) {
+ if (desc->mode & MODE_TRANSPARENT) {
strcpy(p, "32-bit, ");
p += 8;
}
- if (cpu->mode & MODE_LONG) {
+ if (desc->mode & MODE_LONG) {
strcpy(p, "64-bit, ");
p += 8;
}
@@ -619,44 +756,57 @@ print_readable(struct cpu_desc *cpu)
print_s(_("CPU op-mode(s):"), buf);
}
- print_n("CPU(s):", cpu->ct_cpu);
+ print_n(_("CPU(s):"), desc->ncpus);
- if (have_topology) {
- print_n(_("Thread(s) per core:"), cpu->ct_thread);
- print_n(_("Core(s) per socket:"), cpu->ct_core);
- print_n(_("CPU socket(s):"), cpu->ct_socket);
+ if (desc->nsockets) {
+ print_n(_("Thread(s) per core:"), desc->nthreads / desc->ncores);
+ print_n(_("Core(s) per socket:"), desc->ncores / desc->nsockets);
+ print_n(_("CPU socket(s):"), desc->nsockets);
}
- if (have_node)
- print_n(_("NUMA node(s):"), cpu->ct_node);
- if (cpu->vendor)
- print_s(_("Vendor ID:"), cpu->vendor);
- if (cpu->family)
- print_s(_("CPU family:"), cpu->family);
- if (cpu->model)
- print_s(_("Model:"), cpu->model);
- if (cpu->stepping)
- print_s(_("Stepping:"), cpu->stepping);
- if (cpu->mhz)
- print_s(_("CPU MHz:"), cpu->mhz);
- if (cpu->virtflag) {
- if (!strcmp(cpu->virtflag, "svm"))
+ if (desc->nnodes)
+ print_n(_("NUMA node(s):"), desc->nnodes);
+ if (desc->vendor)
+ print_s(_("Vendor ID:"), desc->vendor);
+ if (desc->family)
+ print_s(_("CPU family:"), desc->family);
+ if (desc->model)
+ print_s(_("Model:"), desc->model);
+ if (desc->stepping)
+ print_s(_("Stepping:"), desc->stepping);
+ if (desc->mhz)
+ print_s(_("CPU MHz:"), desc->mhz);
+ if (desc->virtflag) {
+ if (!strcmp(desc->virtflag, "svm"))
print_s(_("Virtualization:"), "AMD-V");
- else if (!strcmp(cpu->virtflag, "vmx"))
+ else if (!strcmp(desc->virtflag, "vmx"))
print_s(_("Virtualization:"), "VT-x");
}
- if (cpu->hyper) {
- print_s(_("Hypervisor vendor:"), hv_vendors[cpu->hyper]);
- print_s(_("Virtualization type:"), virt_types[cpu->virtype]);
+ if (desc->hyper) {
+ print_s(_("Hypervisor vendor:"), hv_vendors[desc->hyper]);
+ print_s(_("Virtualization type:"), virt_types[desc->virtype]);
}
- if (have_cache) {
+ if (desc->ncaches) {
char buf[512];
int i;
- for (i = cpu->ct_cache - 1; i >= 0; i--) {
+ for (i = desc->ncaches - 1; i >= 0; i--) {
snprintf(buf, sizeof(buf),
- _("%s cache:"), cpu->cache[i].caname);
- print_s(buf, cpu->cache[i].casize);
+ _("%s cache:"), desc->caches[i].name);
+ print_s(buf, desc->caches[i].size);
+ }
+ }
+
+ if (desc->nnodes) {
+ size_t setbuflen = 7 * maxcpus;
+ char setbuf[setbuflen];
+
+ for (i = 0; i < desc->nnodes; i++) {
+ snprintf(buf, sizeof(buf), _("NUMA node%d CPU(s):"), i);
+ print_s(buf, cpulist_create(
+ setbuf, setbuflen,
+ desc->nodemaps[i],
+ CPU_ALLOC_SIZE(maxcpus)));
}
}
}
@@ -673,19 +823,10 @@ void usage(int rc)
exit(rc);
}
-static int
-ca_compare(const void *a, const void *b)
-{
- struct ca_desc *cache1 = (struct ca_desc *) a;
- struct ca_desc *cache2 = (struct ca_desc *) b;
-
- return strcmp(cache2->caname, cache1->caname);
-}
-
int main(int argc, char *argv[])
{
- struct cpu_desc _cpu, *cpu = &_cpu;
- int parsable = 0, c;
+ struct lscpu_desc _desc, *desc = &_desc;
+ int parsable = 0, c, i;
struct option longopts[] = {
{ "help", no_argument, 0, 'h' },
@@ -694,7 +835,7 @@ int main(int argc, char *argv[])
{ NULL, 0, 0, 0 }
};
- setlocale(LC_MESSAGES, "");
+ setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
@@ -706,39 +847,35 @@ int main(int argc, char *argv[])
parsable = 1;
break;
case 's':
+ sysrootlen = strlen(optarg);
strncpy(pathbuf, optarg, sizeof(pathbuf));
+ pathbuf[sizeof(pathbuf) - 1] = '\0';
break;
default:
usage(EXIT_FAILURE);
}
}
- if (chdir(pathbuf) == -1)
- errx(EXIT_FAILURE,
- _("error: change working directory to %s."), pathbuf);
+ memset(desc, 0, sizeof(*desc));
- memset(cpu, 0, sizeof(*cpu));
+ read_basicinfo(desc);
- check_system();
+ for (i = 0; i < desc->ncpus; i++) {
+ read_topology(desc, i);
+ read_cache(desc, i);
+ }
- read_basicinfo(cpu);
+ qsort(desc->caches, desc->ncaches, sizeof(struct cpu_cache), cachecmp);
- if (have_topology)
- read_topology(cpu);
- if (have_cache) {
- read_cache(cpu);
- qsort(cpu->cache, cpu->ct_cache, sizeof(struct ca_desc), ca_compare);
- }
- if (have_node)
- read_nodes(cpu);
+ read_nodes(desc);
- read_hypervisor(cpu);
+ read_hypervisor(desc);
/* Show time! */
if (parsable)
- print_parsable(cpu);
+ print_parsable(desc);
else
- print_readable(cpu);
+ print_readable(desc);
return EXIT_SUCCESS;
}
diff --git a/sys-utils/rdev.8 b/sys-utils/rdev.8
deleted file mode 100644
index 16d6420f..00000000
--- a/sys-utils/rdev.8
+++ /dev/null
@@ -1,207 +0,0 @@
-.\" Copyright 1992, 1993 Rickard E. Faith (faith@cs.unc.edu)
-.\" May be distributed under the GNU General Public License
-.\" Changes from sct@dcs.ed.ac.uk added Sat Oct 9 09:54:00 1993.
-.TH RDEV 8 "20 November 1993" "Linux 0.99" "Linux Programmer's Manual"
-.SH NAME
-rdev \- query/set image root device, RAM disk size, or video mode
-.SH SYNOPSIS
-.B rdev
-.RB [ \-Rrvh ]
-.RB [ \-o
-.IR offset ]
-.RI [ image
-.RI [ value
-.RI [ offset ]]]
-.br
-.B rdev
-.RB [ \-o
-.IR offset ]
-.RI [ image
-.RI [ root_device
-.RI [ offset ]]]
-.br
-.B ramsize
-.RB [ \-o
-.IR offset ]
-.RI [ image
-.RI [ size
-.RI [ offset ]]]
-.br
-.B vidmode
-.RB [ \-o
-.IR offset ]
-.RI [ image
-.RI [ mode
-.RI [ offset ]]]
-.br
-.B rootflags
-.RB [ \-o
-.IR offset ]
-.RI [ image
-.RI [ flags
-.RI [ offset ]]]
-.SH DESCRIPTION
-With no arguments,
-.B rdev
-outputs an
-.I /etc/mtab
-line for the current root file system.
-With no arguments,
-.BR ramsize ", " vidmode ", and " rootflags
-print usage information.
-
-In a bootable image for the Linux kernel on i386, there are several pairs
-of bytes which specify the root device, the video mode, and the size of
-the RAM disk. These pairs of bytes, by default, begin
-at offset 504 (decimal) in the kernel image:
-
-.nf
-.RS
- 498 Root flags
-(500 and 502 Reserved)
- 504 RAM Disk Size
- 506 VGA Mode
- 508 Root Device
-(510 Boot Signature)
-.RE
-.fi
-
-.B rdev
-will change these values.
-
-Typical values for the
-.I image
-parameter, which is a bootable Linux kernel image, might be:
-
-.nf
-.RS
-/vmlinux
-/vmunix
-/boot/bzImage-2.4.0
-/dev/fd0
-/dev/fd1
-.RE
-.fi
-
-When using the
-.B rdev
-command, the
-.I root_device
-parameter might be something like:
-
-.nf
-.RS
-/dev/hda1
-/dev/hdf13
-/dev/sda2
-/dev/sdc4
-/dev/ida/c0d0p1
-.RE
-.fi
-
-One may also specify the device by a comma-separated pair
-of decimal integers
-.IR major , minor .
-
-For the
-.B ramsize
-command, the
-.I size
-parameter specifies the size of the RAM disk in kilobytes. 2.0.x kernels
-and newer dynamically allocate the ramdisk and do not need this setting.
-
-For the
-.B rootflags
-command, the
-.I flags
-parameter contains extra information used when mounting root.
-Currently the only effect of these flags is to force the kernel to
-mount the root filesystem in readonly mode if
-.I flags
-is non-zero.
-
-For the
-.B vidmode
-command, the
-.I mode
-parameter specifies the video mode:
-
-.nf
-.RS
--3 = Prompt
--2 = Extended VGA
--1 = Normal VGA
- 0 = as if "0" was pressed at the prompt
- 1 = as if "1" was pressed at the prompt
- 2 = as if "2" was pressed at the prompt
- n = as if "n" was pressed at the prompt
-.RE
-.fi
-
-If the
-.I value
-is not specified, the
-.I image
-will be examined to determine the current settings.
-.SH OPTIONS
-.TP
-.B \-r
-Causes
-.B rdev
-to act like
-.BR ramsize
-(Not relevant for 2.0.x and newer kernels).
-.TP
-.B \-R
-Causes
-.B rdev
-to act like
-.BR rootflags .
-.TP
-.B \-v
-Causes
-.B rdev
-to act like
-.BR vidmode .
-.TP
-.B \-h
-Provides help.
-.SH BUGS
-The
-.B rdev
-utility, when used other than to find a name for the current root device,
-is an ancient hack that works by patching a kernel image at a magic offset
-with magic numbers. It does not work on architectures other than i386.
-Its use is strongly discouraged. Use a boot loader like SysLinux or LILO
-instead.
-.SH HISTORY
-At offset 502 there used to be the device number of the swap device
-(in Linux 0.12), and "rdev -s" or "swapdev" would set this.
-However, since Linux 0.95 this constant is not used any longer,
-and the swap device is specified using the
-.BR swapon (2)
-system call.
-
-At offset 504 there used to be the size of the ramdisk in kilobytes.
-One would specify a size, and this much was grabbed off the top of memory.
-In Linux 1.1.39 it became also possible to set this value on the kernel
-command line.
-In Linux 1.3.48 the ramdisk setup was changed. Ramdisk memory is now
-taken from the buffer cache, so that the ramdisk can grow dynamically.
-The interpretation of the ramdisk word was changed to a word of which
-the high order bit is a prompt flag (1: prompt for ramdisk:
-"VFS: Insert ramdisk floppy and press ENTER" - this is needed with a
-two-floppy boot), the next bit a load flag (1: load ramdisk),
-and the low order 11 bits give the starting block number of the
-root filesystem image (so that one can have a single floppy boot).
-See also
-.IR linux/Documentation/ramdisk.txt .
-.SH AUTHORS
-.nf
-Originally by Werner Almesberger (almesber@nessie.cs.id.ethz.ch)
-Modified by Peter MacDonald (pmacdona@sanjuan.UVic.CA)
-rootflags support added by Stephen Tweedie (sct@dcs.ed.ac.uk)
-.fi
-.SH AVAILABILITY
-The rdev command is part of the util-linux-ng package and is available from
-ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/.
diff --git a/sys-utils/rdev.c b/sys-utils/rdev.c
deleted file mode 100644
index 14fac814..00000000
--- a/sys-utils/rdev.c
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
-
- rdev.c - query/set root device.
-
--------------------------------------------------------------------------
-
-Date: Sun, 27 Dec 1992 15:55:31 +0000
-Subject: Re: rdev
-From: almesber@nessie.cs.id.ethz.ch (Werner Almesberger)
-To: Rik Faith <faith@cs.unc.edu>
-
-There are quite a few versions of rdev:
-
- - the original rootdev that only printed the current root device, by
- Linus.
- - rdev that does what rootdev did and that also allows you to change
- the root (and swap) device, by me.
- - rdev got renamed to setroot and I think even to rootdev on various
- distributions.
- - Peter MacDonald added video mode and RAM disk setting and included
- this version on SLS, called rdev again. I've attached his rdev.c to
- this mail.
-
--------------------------------------------------------------------------
-
-Date: 11 Mar 92 21:37:37 GMT
-Subject: rdev - query/set root device
-From: almesber@nessie.cs.id.ethz.ch (Werner Almesberger)
-Organization: Swiss Federal Institute of Technology (ETH), Zurich, CH
-
-With all that socket, X11, disk driver and FS hacking going on, apparently
-nobody has found time to address one of the minor nuisances of life: set-
-ting the root FS device is still somewhat cumbersome. I've written a little
-utility which can read and set the root device in boot images:
-
-rdev accepts an optional offset argument, just in case the address should
-ever move from 508. If called without arguments, rdev outputs an mtab line
-for the current root FS, just like /etc/rootdev does.
-
-ramsize sets the size of the ramdisk. If size is zero, no ramdisk is used.
-
-vidmode sets the default video mode at bootup time. -1 uses default video
-mode, -2 uses menu.
-
--------------------------------------------------------------------------
-
-Sun Dec 27 10:42:16 1992: Minor usage changes, faith@cs.unc.edu.
-Tue Mar 30 09:31:52 1993: rdev -Rn to set root readonly flag, sct@dcs.ed.ac.uk
-Wed Jun 22 21:12:29 1994: Applied patches from Dave
- (gentzel@nova.enet.dec.com) to prevent dereferencing
- the NULL pointer, faith@cs.unc.edu
-1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
-- added Native Language Support
-
--------------------------------------------------------------------------
-
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include "nls.h"
-
-/* rdev.c - query/set root device. */
-
-static void
-usage(void) {
-
- puts(_("usage: rdev [ -rv ] [ -o OFFSET ] [ IMAGE [ VALUE [ OFFSET ] ] ]"));
- puts(_(" rdev /dev/fd0 (or rdev /linux, etc.) displays the current ROOT device"));
- puts(_(" rdev /dev/fd0 /dev/hda2 sets ROOT to /dev/hda2"));
- puts(_(" rdev -R /dev/fd0 1 set the ROOTFLAGS (readonly status)"));
- puts(_(" rdev -r /dev/fd0 627 set the RAMDISK size"));
- puts(_(" rdev -v /dev/fd0 1 set the bootup VIDEOMODE"));
- puts(_(" rdev -o N ... use the byte offset N"));
- puts(_(" rootflags ... same as rdev -R"));
- puts(_(" ramsize ... same as rdev -r"));
- puts(_(" vidmode ... same as rdev -v"));
- puts(_("Note: video modes are: -3=Ask, -2=Extended, -1=NormalVga, 1=key1, 2=key2,..."));
- puts(_(" use -R 1 to mount root readonly, -R 0 for read/write."));
- exit(-1);
-}
-
-
-#define DEFAULT_OFFSET 508
-
-
-static void
-die(char *msg) {
- perror(msg);
- exit(1);
-}
-
-/* Earlier rdev fails on /dev/ida/c0d0p1 so we allow for
- recursion in /dev. -- Paul Clements */
-/* In fact devfs needs deep recursion. */
-
-static int
-find_dev_recursive(char *dirnamebuf, int number) {
- DIR *dp;
- struct dirent *dir;
- struct stat s;
- int dirnamelen = 0;
-
- if ((dp = opendir(dirnamebuf)) == NULL)
- die("opendir");
- dirnamelen = strlen(dirnamebuf);
- while ((dir = readdir(dp)) != NULL) {
- if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, ".."))
- continue;
- if (dirnamelen + 1 + strlen(dir->d_name) > PATH_MAX)
- continue;
- dirnamebuf[dirnamelen] = '/';
- strcpy(dirnamebuf+dirnamelen+1, dir->d_name);
- if (lstat(dirnamebuf, &s) < 0)
- continue;
- if ((s.st_mode & S_IFMT) == S_IFBLK && s.st_rdev == number)
- return 1;
- if ((s.st_mode & S_IFMT) == S_IFDIR &&
- find_dev_recursive(dirnamebuf, number))
- return 1;
- }
- dirnamebuf[dirnamelen] = 0;
- closedir(dp);
- return 0;
-}
-
-static char *
-find_dev(int number) {
- static char name[PATH_MAX+1];
-
- if (!number)
- return "Boot device";
- strcpy(name, "/dev");
- if (find_dev_recursive(name, number))
- return name;
- sprintf(name, "0x%04x", number);
- return name;
-}
-
-/* The enum values are significant, things are stored in this order,
- see bootsect.S */
-enum { RDEV, VIDMODE, RAMSIZE, __swapdev__, __syssize__, ROOTFLAGS };
-char *cmdnames[6] = { "rdev", "vidmode", "ramsize", "",
- "", "rootflags"};
-char *desc[6] = { "Root device", "Video mode", "Ramsize", "",
- "", "Root flags"};
-#define shift(n) argv+=n,argc-=n
-
-int
-main(int argc, char **argv) {
- int image, offset, dev_nr, i, newoffset=-1;
- char *ptr;
- unsigned short val, have_val;
- struct stat s;
- int cmd;
-
- setlocale(LC_ALL, "");
- bindtextdomain(PACKAGE, LOCALEDIR);
- textdomain(PACKAGE);
-
- /* use the command name to figure out what we have to do - ugly */
- cmd = RDEV;
- if ((ptr = strrchr(argv[0],'/')) != NULL)
- ptr++;
- else
- ptr = argv[0];
- for (i=0; i<=5; i++) {
- if (!strcmp(ptr,cmdnames[i])) {
- cmd = i;
- break;
- }
- }
-
- while (argc > 1) {
- if (argv[1][0] != '-')
- break;
- switch (argv[1][1]) {
- case 'R':
- cmd = ROOTFLAGS;
- shift(1);
- break;
- case 'r':
- cmd = RAMSIZE;
- shift(1);
- break;
- case 'v':
- cmd = VIDMODE;
- shift(1);
- break;
- case 'o':
- if (argv[1][2]) {
- newoffset = atoi(argv[1]+2);
- shift(1);
- break;
- } else if (argc > 2) {
- newoffset = atoi(argv[2]);
- shift(2);
- break;
- }
- /* Fall through. . . */
- default:
- usage();
- }
- }
-
- /* Here the only sensible way of using rdev */
- if (argc == 1) {
- if (cmd == RDEV) {
- if (stat("/",&s) < 0) die("/");
- printf("%s /\n", find_dev(s.st_dev));
- exit(0);
- }
- usage();
- }
-
- if (argc > 4)
- usage();
-
- /* Ancient garbage.. */
- offset = DEFAULT_OFFSET-cmd*2;
- if (newoffset >= 0)
- offset = newoffset;
- if (argc == 4)
- offset = atoi(argv[3]);
-
- have_val = 0;
-
- if (argc >= 3) {
- if (cmd == RDEV) {
- if (isdigit(*argv[2])) {
- /* earlier: specify offset */
- /* now: specify major,minor */
- char *p;
- unsigned int ma,mi;
- if ((p = strchr(argv[2], ',')) == NULL)
- die(_("missing comma"));
- ma = atoi(argv[2]);
- mi = atoi(p+1);
- val = ((ma<<8) | mi);
- } else {
- char *device = argv[2];
- if (stat(device,&s) < 0)
- die(device);
- val = s.st_rdev;
- }
- } else {
- val = atoi(argv[2]);
- }
- have_val = 1;
- }
-
- if (have_val) {
- if ((image = open(argv[1],O_WRONLY)) < 0) die(argv[1]);
- if (lseek(image,offset,0) < 0) die("lseek");
- if (write(image,(char *)&val,2) != 2) die(argv[1]);
- if (close(image) < 0) die("close");
- } else {
- if ((image = open(argv[1],O_RDONLY)) < 0) die(argv[1]);
- if (lseek(image,offset,0) < 0) die("lseek");
- dev_nr = 0;
- if (read(image,(char *)&dev_nr,2) != 2) die(argv[1]);
- if (close(image) < 0) die("close");
- fputs(desc[cmd], stdout);
- if (cmd == RDEV)
- printf(" %s\n", find_dev(dev_nr));
- else
- printf(" %d\n", dev_nr);
- }
- return 0;
-}
diff --git a/sys-utils/tunelp.c b/sys-utils/tunelp.c
index 619cf422..00ad5b76 100644
--- a/sys-utils/tunelp.c
+++ b/sys-utils/tunelp.c
@@ -81,7 +81,7 @@ print_usage(char *progname) {
static void
print_version(char *progname) {
- printf("%s (%s)\n", progname, PACKAGE_STRING);
+ printf(_("%s (%s)\n"), progname, PACKAGE_STRING);
}
static void *
@@ -256,7 +256,7 @@ main (int argc, char ** argv) {
status = 0xdeadbeef;
retval = ioctl(fd, LPGETSTATUS - offset, &status);
if (retval < 0)
- perror("LPGETSTATUS error");
+ perror(_("LPGETSTATUS error"));
else {
if (status == 0xdeadbeef) /* a few 1.1.7x kernels will do this */
status = retval;
@@ -271,7 +271,7 @@ main (int argc, char ** argv) {
} else
#endif /* LPGETSTATUS */
if (ioctl(fd, cmds->op - offset, cmds->val) < 0) {
- perror("tunelp: ioctl");
+ perror(_("tunelp: ioctl failed"));
}
cmdst = cmds;
cmds = cmds->next;