diff options
author | LaMont Jones <lamont@debian.org> | 2010-08-02 23:02:28 -0600 |
---|---|---|
committer | LaMont Jones <lamont@debian.org> | 2010-08-02 23:02:28 -0600 |
commit | 0864d694ca05ea9383ef09bc1bc3a182e15e2ffa (patch) | |
tree | 2e5237f1d4e2cac2efad97ce31abc386c1e37b6d /sys-utils | |
parent | 3cbdfd84fde6159d7778e70618fbbc8df219cafe (diff) | |
parent | 6c91f5e3e1de32c45ea0b38227ce35eb43eb2ebc (diff) | |
download | util-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/.gitignore | 5 | ||||
-rw-r--r-- | sys-utils/Makefile.am | 34 | ||||
-rw-r--r-- | sys-utils/fallocate.c | 5 | ||||
-rw-r--r-- | sys-utils/flock.1 | 4 | ||||
-rw-r--r-- | sys-utils/flock.c | 2 | ||||
-rw-r--r-- | sys-utils/fsfreeze.8 | 75 | ||||
-rw-r--r-- | sys-utils/fsfreeze.c | 132 | ||||
-rw-r--r-- | sys-utils/ipcrm.c | 2 | ||||
-rw-r--r-- | sys-utils/ipcs.c | 74 | ||||
-rw-r--r-- | sys-utils/lscpu.1 | 9 | ||||
-rw-r--r-- | sys-utils/lscpu.c | 683 | ||||
-rw-r--r-- | sys-utils/rdev.8 | 207 | ||||
-rw-r--r-- | sys-utils/rdev.c | 279 | ||||
-rw-r--r-- | sys-utils/tunelp.c | 6 |
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; |