From: Sebastien Date: Wed, 11 Jul 2012 19:31:14 +0000 (+0200) Subject: Persistent device names support added to sar and iostat (option -j) X-Git-Tag: v10.1.1~8 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4100c28155997134670cae3731de853a9410767e;p=sysstat Persistent device names support added to sar and iostat (option -j) Option -j added to sar and iostat to add support for persistent device names. Mail from Peter Schiffer (pschiffe@redhat.com) 22/06/2012: I need to implement another feature for sysstat and I would like to hear your opinion. Pretty device names, such as sda, vda, ... are not persistent and in some specific situations kernel can assign different names for the same device between reboots. To prevent this confusion, persistent device names exists. Those names are in /dev/disk/by-xxx folders... You are probably aware of this.. So, currently, sar -d -p and iostat are displaying the pretty device names. I would like to add new option, which would take one argument specifying the type of persistent name, and then, sar -d -p and iostat would display the device names in that persistent name, e.g.: $ iostat -some_option label ... Device: tps Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn my-root 11.62 276.70 198.97 2938654 2113160 main-home 16.62 73.21 109.78 777506 1165856 It would work like this: I wouldn't bound the type of name, rather I would check whether the specified type inserted by user exists like folder: /dev/disk/by-label (in that particular example). If yes, I would resolve links in that folder until I found the device I was looking for and display that name.. It should be straightforward. My questions are: how would you name the option? And where would you put the common code for sar and iostat? Also, do you have any comments or ideas? --- diff --git a/CHANGES b/CHANGES index 2d10aee..ea4e283 100644 --- a/CHANGES +++ b/CHANGES @@ -1,9 +1,12 @@ Changes: xxxx/xx/xx: Version 10.1.1 - Sebastien Godard (sysstat orange.fr) - * Added option -[0-9]* to sar to show data of that days ago. + * [Peter Schiffer]: Persistent device names support added to + sar and iostat (option -j). + * Added option -[0-9]+ to sar to show data of that days ago. * [Peter Schiffer]: sar: Use /sys/dev/block/major:minor links to determine devices real name. + * sar and iostat manual pages updated. 2012/05/16: Version 10.0.5 - Sebastien Godard (sysstat orange.fr) * [Alain Chereau]: Options -g and -T added to iostat. These diff --git a/common.c b/common.c index ea8267d..97d5907 100644 --- a/common.c +++ b/common.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include "version.h" #include "common.h" @@ -47,6 +49,9 @@ unsigned int hz; /* Number of bit shifts to convert pages to kB */ unsigned int kb_shift; +/* Type of persistent device names used in sar and iostat */ +char persistent_name_type[MAX_FILE_LEN]; + /* *************************************************************************** * Print sysstat version number and exit. @@ -680,3 +685,241 @@ void compute_ext_disk_stats(struct stats_disk *sdc, struct stats_disk *sdp, ((sdc->rd_sect - sdp->rd_sect) + (sdc->wr_sect - sdp->wr_sect)) / ((double) (sdc->nr_ios - sdp->nr_ios)) : 0.0; } + +/* + *************************************************************************** + * Convert in-place input string to lowercase. + * + * IN: + * @str String to be converted. + * + * OUT: + * @str String in lowercase. + * + * RETURNS: + * String in lowercase. + *************************************************************************** +*/ +char *strtolower(char *str) +{ + char *cp = str; + + while (*cp) { + *cp = tolower(*cp); + cp++; + } + + return(str); +} + +/* + *************************************************************************** + * Get persistent type name directory from type. + * + * IN: + * @type Persistent type name (UUID, LABEL, etc.) + * + * RETURNS: + * Path to the persistent type name directory, or NULL if access is denied. + *************************************************************************** +*/ +char *get_persistent_type_dir(char *type) +{ + static char dir[32]; + + snprintf(dir, 32, "%s-%s", DEV_DISK_BY, type); + + if (access(dir, R_OK)) { + return (NULL); + } + + return (dir); +} + +/* + *************************************************************************** + * Get persistent name absolute path. + * + * IN: + * @name Persistent name. + * + * RETURNS: + * Path to the persistent name, or NULL if file doesn't exist. + *************************************************************************** +*/ +char *get_persistent_name_path(char *name) +{ + static char path[PATH_MAX]; + + snprintf(path, PATH_MAX, "%s/%s", + get_persistent_type_dir(persistent_name_type), name); + + if (access(path, F_OK)) { + return (NULL); + } + + return (path); +} + +/* + *************************************************************************** + * Get files from persistent type name directory. + * + * RETURNS: + * List of files in the persistent type name directory in alphabetical order. + *************************************************************************** +*/ +char **get_persistent_names(void) +{ + int n, i, k = 0; + char *dir; + char **files = NULL; + struct dirent **namelist; + + /* Get directory name for selected persistent type */ + dir = get_persistent_type_dir(persistent_name_type); + if (!dir) + return (NULL); + + n = scandir(dir, &namelist, NULL, alphasort); + if (n < 0) + return (NULL); + + /* If directory is empty, it contains 2 entries: "." and ".." */ + if (n <= 2) + /* Free list and return NULL */ + goto free_list; + + /* Ignore the "." and "..", but keep place for one last NULL. */ + files = (char **) calloc(n - 1, sizeof(char *)); + if (!files) + goto free_list; + + /* + * i is for traversing namelist, k is for files. + * i != k because we are ignoring "." and ".." entries. + */ + for (i = 0; i < n; i++) { + /* Ignore "." and "..". */ + if (!strcmp(".", namelist[i]->d_name) || + !strcmp("..", namelist[i]->d_name)) + continue; + + files[k] = (char *) calloc(strlen(namelist[i]->d_name) + 1, sizeof(char)); + if (!files[k]) + continue; + + strcpy(files[k++], namelist[i]->d_name); + } + files[k] = NULL; + +free_list: + + for (i = 0; i < n; i++) { + free(namelist[i]); + } + free(namelist); + + return (files); +} + +/* + *************************************************************************** + * Get persistent name from pretty name. + * + * IN: + * @pretty Pretty name (e.g. sda, sda1, ..). + * + * RETURNS: + * Persistent name. + *************************************************************************** +*/ +char *get_persistent_name_from_pretty(char *pretty) +{ + int i = -1; + ssize_t r; + char *link, *name; + char **persist_names; + char target[PATH_MAX]; + static char persist_name[FILENAME_MAX]; + + persist_name[0] = '\0'; + + /* Get list of files from persistent type name directory */ + persist_names = get_persistent_names(); + if (!persist_names) + return (NULL); + + while (persist_names[++i]) { + /* Get absolute path for current persistent name */ + link = get_persistent_name_path(persist_names[i]); + if (!link) + continue; + + /* Persistent name is usually a symlink: Read it... */ + r = readlink(link, target, PATH_MAX); + if ((r <= 0) || (r >= PATH_MAX)) + continue; + + target[r] = '\0'; + + /* ... and get device pretty name it points at */ + name = basename(target); + if (!name || (name[0] == '\0')) + continue; + + if (!strncmp(name, pretty, FILENAME_MAX)) { + /* We have found pretty name for current persistent one */ + strncpy(persist_name, persist_names[i], FILENAME_MAX); + persist_name[FILENAME_MAX - 1] = '\0'; + break; + } + } + + i = -1; + while (persist_names[++i]) { + free (persist_names[i]); + } + free (persist_names); + + if (strlen(persist_name) <= 0) + return (NULL); + + return persist_name; +} + +/* + *************************************************************************** + * Get pretty name (sda, sda1...) from persistent name. + * + * IN: + * @persistent Persistent name. + * + * RETURNS: + * Pretty name. + *************************************************************************** +*/ +char *get_pretty_name_from_persistent(char *persistent) +{ + ssize_t r; + char *link, *pretty, target[PATH_MAX]; + + /* Get absolute path for persistent name */ + link = get_persistent_name_path(persistent); + if (!link) + return (NULL); + + /* Persistent name is usually a symlink: Read it... */ + r = readlink(link, target, PATH_MAX); + if ((r <= 0) || (r >= PATH_MAX)) + return (NULL); + + target[r] = '\0'; + + /* ... and get device pretty name it points at */ + pretty = basename(target); + if (!pretty || (pretty[0] == '\0')) + return (NULL); + + return pretty; +} diff --git a/common.h b/common.h index b70ea66..4bad2c0 100644 --- a/common.h +++ b/common.h @@ -1,6 +1,6 @@ /* * sysstat: System performance tools for Linux - * (C) 1999-2011 by Sebastien Godard (sysstat orange.fr) + * (C) 1999-2012 by Sebastien Godard (sysstat orange.fr) */ #ifndef _COMMON_H @@ -13,7 +13,6 @@ #include /* For __CPU_SETSIZE */ #include "rd_stats.h" - /* *************************************************************************** * Various keywords and constants @@ -61,6 +60,7 @@ #define DEVMAP_DIR "/dev/mapper" #define DEVICES "/proc/devices" #define SYSFS_USBDEV "/sys/bus/usb/devices" +#define DEV_DISK_BY "/dev/disk/by" #define SYSFS_IDVENDOR "idVendor" #define SYSFS_IDPRODUCT "idProduct" #define SYSFS_BMAXPOWER "bMaxPower" @@ -83,7 +83,6 @@ #define DIGITS "0123456789" - /* *************************************************************************** * Macro functions definitions. @@ -116,7 +115,7 @@ /* * Under very special circumstances, STDOUT may become unavailable. - * This is what we try to guess here + * This is what we try to guess here. */ #define TEST_STDOUT(_fd_) do { \ if (write(_fd_, "", 0) == -1) { \ @@ -125,7 +124,6 @@ } \ } while (0) - #define MINIMUM(a,b) ((a) < (b) ? (a) : (b)) #ifdef DEBUG @@ -148,6 +146,9 @@ extern unsigned int kb_shift; #define KB_TO_PG(k) ((k) >> kb_shift) #define PG_TO_KB(k) ((k) << kb_shift) +/* Type of persistent device names used in sar and iostat */ +extern char persistent_name_type[MAX_FILE_LEN]; + /* *************************************************************************** * Structures definitions @@ -162,7 +163,6 @@ struct ext_disk_stats { double arqsz; }; - /* *************************************************************************** * Functions prototypes @@ -192,6 +192,12 @@ extern time_t get_time(struct tm *, int); unsigned long long get_per_cpu_interval(struct stats_cpu *, struct stats_cpu *); +extern char * + get_persistent_name_from_pretty(char *); +extern char * + get_persistent_type_dir(char *); +extern char * + get_pretty_name_from_persistent(char *); extern int get_sysfs_dev_nr(int); extern int @@ -208,6 +214,8 @@ extern int print_gal_header(struct tm *, char *, char *, char *, char *, int); extern void print_version(void); +extern char * + strtolower(char *); #ifdef DEBUG extern void sysstat_panic(const char *, int); diff --git a/iostat.c b/iostat.c index 61fb2a6..d50cbf9 100644 --- a/iostat.c +++ b/iostat.c @@ -86,11 +86,13 @@ void usage(char *progname) #ifdef DEBUG fprintf(stderr, _("Options are:\n" "[ -c ] [ -d ] [ -h ] [ -N ] [ -k | -m ] [ -t ] [ -V ] [ -x ] [ -z ]\n" + "[ -j { ID | LABEL | PATH | UUID | ... } [ [...] | ALL ] ]\n" "[ [ [ -T ] -g ] { [...] | ALL } ]\n" "[ -p [ [,...] | ALL ] ] [ --debuginfo ]\n")); #else fprintf(stderr, _("Options are:\n" "[ -c ] [ -d ] [ -h ] [ -N ] [ -k | -m ] [ -t ] [ -V ] [ -x ] [ -z ]\n" + "[ -j { ID | LABEL | PATH | UUID | ... } [ [...] | ALL ] ]\n" "[ [ [ -T ] -g ] { [...] | ALL } ]\n" "[ -p [ [,...] | ALL ] ]\n")); #endif @@ -909,13 +911,14 @@ void write_ext_stat(int curr, unsigned long long itv, int fctr, struct io_hdr_stats *shi, struct io_stats *ioi, struct io_stats *ioj) { + char *devname = NULL; struct stats_disk sdc, sdp; struct ext_disk_stats xds; double r_await, w_await; /* * Counters overflows are possible, but don't need to be handled in - * a special way: the difference is still properly calculated if the + * a special way: The difference is still properly calculated if the * result is of the same type as the two values. * Exception is field rq_ticks which is incremented by the number of * I/O in progress times the number of milliseconds spent doing I/O. @@ -948,11 +951,17 @@ void write_ext_stat(int curr, unsigned long long itv, int fctr, ((double) (ioi->wr_ios - ioj->wr_ios)) : 0.0; /* Print device name */ + if (DISPLAY_PERSIST_NAME_I(flags)) { + devname = get_persistent_name_from_pretty(shi->name); + } + if (!devname) { + devname = shi->name; + } if (DISPLAY_HUMAN_READ(flags)) { - printf("%s\n%13s", shi->name, ""); + printf("%s\n%13s", devname, ""); } else { - printf("%-13s", shi->name); + printf("%-13s", devname); } /* rrq/s wrq/s r/s w/s rsec wsec rqsz qusz await r_await w_await svctm %util */ @@ -972,8 +981,8 @@ void write_ext_stat(int curr, unsigned long long itv, int fctr, xds.svctm, /* * Again: Ticks in milliseconds. - * In the case of a device group, shi->used is the nr of devices in the group. - * Else shi->used equals 1. + * In the case of a device group (option -g), shi->used is the number of + * devices in the group. Else shi->used equals 1. */ shi->used ? xds.util / 10.0 / (double) shi->used : xds.util / 10.0); /* shi->used should never be null here */ @@ -996,14 +1005,21 @@ void write_basic_stat(int curr, unsigned long long itv, int fctr, struct io_hdr_stats *shi, struct io_stats *ioi, struct io_stats *ioj) { + char *devname = NULL; unsigned long long rd_sec, wr_sec; /* Print device name */ + if (DISPLAY_PERSIST_NAME_I(flags)) { + devname = get_persistent_name_from_pretty(shi->name); + } + if (!devname) { + devname = shi->name; + } if (DISPLAY_HUMAN_READ(flags)) { - printf("%s\n%13s", shi->name, ""); + printf("%s\n%13s", devname, ""); } else { - printf("%-13s", shi->name); + printf("%-13s", devname); } /* Print stats coming from /sys or /proc/diskstats */ @@ -1275,7 +1291,7 @@ int main(int argc, char **argv) struct utsname header; struct io_dlist *st_dev_list_i; struct tm rectime; - char *t; + char *t, *persist_devname, *devname; #ifdef USE_NLS /* Init National Language Support */ @@ -1305,8 +1321,16 @@ int main(int argc, char **argv) flags |= I_D_PART_ALL; } else { + devname = device_name(t); + if (DISPLAY_PERSIST_NAME_I(flags)) { + /* Get device persistent name */ + persist_devname = get_pretty_name_from_persistent(devname); + if (persist_devname != NULL) { + devname = persist_devname; + } + } /* Store device name */ - i = update_dev_list(&dlist_idx, device_name(t)); + i = update_dev_list(&dlist_idx, devname); st_dev_list_i = st_dev_list + i; st_dev_list_i->disp_part = TRUE; } @@ -1343,6 +1367,31 @@ int main(int argc, char **argv) } group_nr++; } + + else if (!strcmp(argv[opt], "-j")) { + if (argv[++opt]) { + if (strnlen(argv[opt], MAX_FILE_LEN) >= MAX_FILE_LEN - 1) { + usage(argv[0]); + } + strncpy(persistent_name_type, argv[opt], MAX_FILE_LEN - 1); + persistent_name_type[MAX_FILE_LEN - 1] = '\0'; + strtolower(persistent_name_type); + /* Check that this is a valid type of persistent device name */ + if (!get_persistent_type_dir(persistent_name_type)) { + fprintf(stderr, _("Invalid type of persistent device name\n")); + exit(1); + } + /* + * Persistent names are usually long: Display + * them as human readable by default. + */ + flags |= I_D_PERSIST_NAME + I_D_HUMAN_READ; + opt++; + } + else { + usage(argv[0]); + } + } #ifdef DEBUG else if (!strcmp(argv[opt], "--debuginfo")) { @@ -1438,8 +1487,15 @@ int main(int argc, char **argv) flags |= I_D_UNFILTERED; if (strcmp(argv[opt], K_ALL)) { - /* Store device name */ - update_dev_list(&dlist_idx, device_name(argv[opt++])); + /* Store device name entered on the command line */ + devname = device_name(argv[opt++]); + if (DISPLAY_PERSIST_NAME_I(flags)) { + persist_devname = get_pretty_name_from_persistent(devname); + if (persist_devname != NULL) { + devname = persist_devname; + } + } + update_dev_list(&dlist_idx, devname); } else { opt++; diff --git a/iostat.h b/iostat.h index fa2ca21..281689d 100644 --- a/iostat.h +++ b/iostat.h @@ -22,7 +22,7 @@ #define I_D_PARTITIONS 0x00400 #define I_F_HAS_DISKSTATS 0x00800 #define I_D_HUMAN_READ 0x01000 -/* Unused 0x02000 */ +#define I_D_PERSIST_NAME 0x02000 /* Unused 0x04000 */ /* Unused 0x08000 */ #define I_D_DEVMAP_NAME 0x10000 @@ -43,6 +43,7 @@ #define DISPLAY_PARTITIONS(m) (((m) & I_D_PARTITIONS) == I_D_PARTITIONS) #define HAS_DISKSTATS(m) (((m) & I_F_HAS_DISKSTATS) == I_F_HAS_DISKSTATS) #define DISPLAY_HUMAN_READ(m) (((m) & I_D_HUMAN_READ) == I_D_HUMAN_READ) +#define DISPLAY_PERSIST_NAME_I(m) (((m) & I_D_PERSIST_NAME) == I_D_PERSIST_NAME) #define DISPLAY_DEVMAP_NAME(m) (((m) & I_D_DEVMAP_NAME) == I_D_DEVMAP_NAME) #define DISPLAY_ISO(m) (((m) & I_D_ISO) == I_D_ISO) #define DISPLAY_GROUP_TOTAL_ONLY(m) (((m) & I_D_GROUP_TOTAL_ONLY) == I_D_GROUP_TOTAL_ONLY) diff --git a/json_stats.c b/json_stats.c index 3acd18f..6fa0314 100644 --- a/json_stats.c +++ b/json_stats.c @@ -1,6 +1,6 @@ /* * json_stats.c: Funtions used by sadf to display statistics in JSON format. - * (C) 1999-2011 by Sebastien GODARD (sysstat orange.fr) + * (C) 1999-2012 by Sebastien GODARD (sysstat orange.fr) * *************************************************************************** * This program is free software; you can redistribute it and/or modify it * @@ -665,7 +665,7 @@ __print_funct_t json_print_disk_stats(struct activity *a, int curr, int tab, struct stats_disk *sdc, *sdp; struct ext_disk_stats xds; int sep = FALSE; - char *dev_name; + char *dev_name, *persist_dev_name; xprintf(tab++, "\"disk\": ["); @@ -683,16 +683,26 @@ __print_funct_t json_print_disk_stats(struct activity *a, int curr, int tab, compute_ext_disk_stats(sdc, sdp, itv, &xds); dev_name = NULL; + persist_dev_name = NULL; - if ((USE_PRETTY_OPTION(flags)) && (sdc->major == dm_major)) { - dev_name = transform_devmapname(sdc->major, sdc->minor); + if (DISPLAY_PERSIST_NAME_S(flags)) { + persist_dev_name = get_persistent_name_from_pretty(get_devname(sdc->major, sdc->minor, TRUE)); } - - if (!dev_name) { - dev_name = get_devname(sdc->major, sdc->minor, - USE_PRETTY_OPTION(flags)); + + if (persist_dev_name) { + dev_name = persist_dev_name; } + else { + if ((USE_PRETTY_OPTION(flags)) && (sdc->major == dm_major)) { + dev_name = transform_devmapname(sdc->major, sdc->minor); + } + if (!dev_name) { + dev_name = get_devname(sdc->major, sdc->minor, + USE_PRETTY_OPTION(flags)); + } + } + if (sep) { printf(",\n"); } diff --git a/man/iostat.in b/man/iostat.in index 768c4ec..066a779 100644 --- a/man/iostat.in +++ b/man/iostat.in @@ -1,10 +1,13 @@ -.TH IOSTAT 1 "MAY 2012" Linux "Linux User's Manual" -*- nroff -*- +.TH IOSTAT 1 "JULY 2012" Linux "Linux User's Manual" -*- nroff -*- .SH NAME iostat \- Report Central Processing Unit (CPU) statistics and input/output statistics for devices and partitions. .SH SYNOPSIS .ie 'yes'@WITH_DEBUG@' \{ .B iostat [ -c ] [ -d ] [ --debuginfo ] [ -h ] [ -N ] [ -k | -m ] [ -t ] [ -V ] [ -x ] [ -z ] +.B [ -j { ID | LABEL | PATH | UUID | ... } [ +.I device +.B [...] | ALL ] ] .B [ [ [ -T ] -g .I group_name .B ] { @@ -19,6 +22,9 @@ statistics for devices and partitions. .\} .el \{ .B iostat [ -c ] [ -d ] [ -h ] [ -N ] [ -k | -m ] [ -t ] [ -V ] [ -x ] [ -z ] +.B [ -j { ID | LABEL | PATH | UUID | ... } [ +.I device +.B [...] | ALL ] ] .B [ [ [ -T ] -g .I group_name .B ] { @@ -284,6 +290,17 @@ keyword means that all the block devices defined by the system shall be included in the group. .IP -h Make the Device Utilization Report easier to read by a human. +.IP "-j { ID | LABEL | PATH | UUID | ... } [ device [...] | ALL ]" +Display persistent device names. Options +.BR ID , +.BR LABEL , +etc. specify the type of the persistent name. These options are not limited, +only prerequisite is that directory with required persistent names is present in +.IR /dev/disk . +Optionally, multiple devices can be specified in the chosen persistent name type. +Because persistent device names are usually long, option +.B -h +is enabled implicitly with this option. .IP -k Display statistics in kilobytes per second. .IP -m @@ -299,7 +316,10 @@ and all its partitions are displayed. Last, the .B ALL keyword indicates that statistics have to be displayed for all the block devices and partitions defined by the system, including those that have -never been used. +never been used. If option +.B -j +is defined before this option, devices entered on the command line can be +specified with the chosen persistent name type. .IP -T This option must be used with option -g and indicates that only global statistics for the group are to be displayed, and not statistics for @@ -387,6 +407,9 @@ contains statistics for block devices. .I /proc/self/mountstats contains statistics for network filesystems. + +.I /dev/disk +contains persistent device names. .SH AUTHOR Sebastien Godard (sysstat orange.fr) .SH SEE ALSO diff --git a/man/sar.in b/man/sar.in index 47a3c15..0314b00 100644 --- a/man/sar.in +++ b/man/sar.in @@ -1,4 +1,4 @@ -.TH SAR 1 "JUNE 2012" Linux "Linux User's Manual" -*- nroff -*- +.TH SAR 1 "JULY 2012" Linux "Linux User's Manual" -*- nroff -*- .SH NAME sar \- Collect, report, or save system activity information. .SH SYNOPSIS @@ -6,6 +6,7 @@ sar \- Collect, report, or save system activity information. .I interval .B ] [ -p ] [ -q ] [ -r ] [ -R ] [ -S ] [ -t ] [ -u [ ALL ] ] [ -v ] [ -V ] [ -w ] [ -W ] [ -y ] +.B [ -j { ID | LABEL | PATH | UUID | ... } ] .B [ -m { .I keyword .B [,...] | ALL } ] @@ -254,7 +255,8 @@ is the major number of the device and .B n its minor number. Device names may also be pretty-printed if option -p -is used (see below). +is used or persistent device names can be printed if option -j is used +(see below). Note that disk activity depends on sadc options "-S DISK" and "-S XDISK" to be collected. The following values are displayed: @@ -370,6 +372,16 @@ the first 16 interrupts are to be reported, whereas the keyword indicates that statistics from all interrupts, including potential APIC interrupt sources, are to be reported. Note that interrupt statistics depend on sadc option "-S INT" to be collected. +.IP "-j { ID | LABEL | PATH | UUID | ... }" +Display persistent device names. Use this option in conjunction with option -d. +Options +.BR ID , +.BR LABEL , +etc. specify the type of the persistent name. These options are not limited, +only prerequisite is that directory with required persistent names is present in +.IR /dev/disk . +If persistent name is not found for the device, the device name +is pretty-printed (see option -p below). .IP "-m { keyword [,...] | ALL }" Report power management statistics. Note that these statistics depend on sadc option "-S POWER" to be collected. diff --git a/nls/sysstat.pot b/nls/sysstat.pot index 8374733..2f61331 100644 --- a/nls/sysstat.pot +++ b/nls/sysstat.pot @@ -8,43 +8,44 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: sysstat orange.fr\n" -"POT-Creation-Date: 2012-05-08 21:39+0200\n" +"POT-Creation-Date: 2012-07-01 21:33+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" +"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: cifsiostat.c:69 iostat.c:84 mpstat.c:86 nfsiostat.c:68 pidstat.c:78 -#: sar.c:90 +#: sadf_misc.c:595 #, c-format -msgid "Usage: %s [ options ] [ [ ] ]\n" +msgid "System activity data file: %s (%#x)\n" msgstr "" -#: cifsiostat.c:73 nfsiostat.c:72 +#: sadf_misc.c:604 #, c-format -msgid "" -"Options are:\n" -"[ --debuginfo ] [ -h ] [ -k | -m ] [ -t ] [ -V ]\n" +msgid "Host: " msgstr "" -#: cifsiostat.c:76 nfsiostat.c:75 +#: sadf_misc.c:610 #, c-format -msgid "" -"Options are:\n" -"[ -h ] [ -k | -m ] [ -t ] [ -V ]\n" +msgid "Size of a long int: %d\n" msgstr "" -#: common.c:57 +#: sadf_misc.c:612 #, c-format -msgid "sysstat version %s\n" +msgid "List of activities:\n" msgstr "" -#: ioconf.c:491 rd_stats.c:68 rd_stats.c:2120 sa_common.c:1061 sadc.c:623 -#: sadc.c:632 sadc.c:693 +#: sadf_misc.c:625 #, c-format -msgid "Cannot open %s: %s\n" +msgid "\t[Unknown activity format]" +msgstr "" + +#: iostat.c:84 cifsiostat.c:69 mpstat.c:86 sar.c:90 pidstat.c:78 +#: nfsiostat.c:68 +#, c-format +msgid "Usage: %s [ options ] [ [ ] ]\n" msgstr "" #: iostat.c:87 @@ -70,107 +71,57 @@ msgstr "" msgid "Cannot find disk data\n" msgstr "" -#: mpstat.c:89 -#, c-format -msgid "" -"Options are:\n" -"[ -A ] [ -I { SUM | CPU | SCPU | ALL } ] [ -u ]\n" -"[ -P { [,...] | ON | ALL } ] [ -V ]\n" -msgstr "" - -#: mpstat.c:582 pidstat.c:1822 sar.c:381 -msgid "Average:" -msgstr "" - -#: mpstat.c:929 +#: sadc.c:81 #, c-format -msgid "Not that many processors!\n" +msgid "Usage: %s [ options ] [ [ ] ] [ ]\n" msgstr "" -#: pidstat.c:81 +#: sadc.c:84 #, c-format msgid "" "Options are:\n" -"[ -C ] [ -d ] [ -h ] [ -I ] [ -l ] [ -r ] [ -s ]\n" -"[ -t ] [ -u ] [ -V ] [ -w ]\n" -"[ -p { [,...] | SELF | ALL } ] [ -T { TASK | CHILD | ALL } ]\n" -msgstr "" - -#: pidstat.c:199 sar.c:1013 -#, c-format -msgid "Requested activities not available\n" -msgstr "" - -#: pr_stats.c:2319 pr_stats.c:2332 -msgid "Summary" -msgstr "" - -#: pr_stats.c:2370 -msgid "Other devices not listed here" +"[ -C ] [ -F ] [ -L ] [ -V ]\n" +"[ -S { INT | DISK | IPV6 | POWER | SNMP | XDISK | ALL | XALL } ]\n" msgstr "" -#: rd_stats.c:2166 +#: sadc.c:223 #, c-format -msgid "Cannot handle so many processors!\n" +msgid "Cannot write data to system activity file: %s\n" msgstr "" -#: sa_common.c:870 +#: sadc.c:510 #, c-format -msgid "Error while reading system activity file: %s\n" +msgid "Cannot write system activity file header: %s\n" msgstr "" -#: sa_common.c:880 +#: sadc.c:623 sadc.c:632 sadc.c:693 ioconf.c:491 rd_stats.c:68 rd_stats.c:2120 +#: sa_common.c:1107 #, c-format -msgid "End of system activity file unexpected\n" +msgid "Cannot open %s: %s\n" msgstr "" -#: sa_common.c:898 +#: sadc.c:807 #, c-format -msgid "File created using sar/sadc from sysstat version %d.%d.%d" +msgid "Cannot append data to that file (%s)\n" msgstr "" -#: sa_common.c:929 +#: common.c:57 #, c-format -msgid "Invalid system activity file: %s\n" +msgid "sysstat version %s\n" msgstr "" -#: sa_common.c:936 +#: cifsiostat.c:73 nfsiostat.c:72 #, c-format msgid "" -"Current sysstat version can no longer read the format of this file (%#x)\n" -msgstr "" - -#: sa_common.c:1168 -#, c-format -msgid "Requested activities not available in file %s\n" -msgstr "" - -#: sadc.c:81 -#, c-format -msgid "Usage: %s [ options ] [ [ ] ] [ ]\n" +"Options are:\n" +"[ --debuginfo ] [ -h ] [ -k | -m ] [ -t ] [ -V ]\n" msgstr "" -#: sadc.c:84 +#: cifsiostat.c:76 nfsiostat.c:75 #, c-format msgid "" "Options are:\n" -"[ -C ] [ -F ] [ -L ] [ -V ]\n" -"[ -S { INT | DISK | IPV6 | POWER | SNMP | XDISK | ALL | XALL } ]\n" -msgstr "" - -#: sadc.c:223 -#, c-format -msgid "Cannot write data to system activity file: %s\n" -msgstr "" - -#: sadc.c:510 -#, c-format -msgid "Cannot write system activity file header: %s\n" -msgstr "" - -#: sadc.c:807 -#, c-format -msgid "Cannot append data to that file (%s)\n" +"[ -h ] [ -k | -m ] [ -t ] [ -V ]\n" msgstr "" #: sadf.c:86 @@ -187,29 +138,21 @@ msgid "" "[ -- ]\n" msgstr "" -#: sadf_misc.c:595 -#, c-format -msgid "System activity data file: %s (%#x)\n" -msgstr "" - -#: sadf_misc.c:604 -#, c-format -msgid "Host: " -msgstr "" - -#: sadf_misc.c:610 +#: mpstat.c:89 #, c-format -msgid "Size of a long int: %d\n" +msgid "" +"Options are:\n" +"[ -A ] [ -I { SUM | CPU | SCPU | ALL } ] [ -u ]\n" +"[ -P { [,...] | ON | ALL } ] [ -V ]\n" msgstr "" -#: sadf_misc.c:612 -#, c-format -msgid "List of activities:\n" +#: mpstat.c:581 sar.c:381 pidstat.c:1822 +msgid "Average:" msgstr "" -#: sadf_misc.c:625 +#: mpstat.c:928 #, c-format -msgid "\t[Unknown activity format]" +msgid "Not that many processors!\n" msgstr "" #: sar.c:105 @@ -220,7 +163,7 @@ msgid "" "[ -R ] [ -S ] [ -t ] [ -u [ ALL ] ] [ -v ] [ -V ] [ -w ] [ -W ] [ -y ]\n" "[ -I { [,...] | SUM | ALL | XALL } ] [ -P { [,...] | ALL } ]\n" "[ -m { [,...] | ALL } ] [ -n { [,...] | ALL } ]\n" -"[ -o [ ] | -f [ ] ]\n" +"[ -o [ ] | -f [ ] | -[0-9]+ ]\n" "[ -i ] [ -s [ ] ] [ -e [ ] ]\n" msgstr "" @@ -363,17 +306,75 @@ msgstr "" msgid "Inconsistent input data\n" msgstr "" -#: sar.c:1260 +#: sar.c:1013 pidstat.c:199 +#, c-format +msgid "Requested activities not available\n" +msgstr "" + +#: sar.c:1268 #, c-format msgid "-f and -o options are mutually exclusive\n" msgstr "" -#: sar.c:1266 +#: sar.c:1274 #, c-format msgid "Not reading from a system activity file (use -f option)\n" msgstr "" -#: sar.c:1393 +#: sar.c:1406 #, c-format msgid "Cannot find the data collector (%s)\n" msgstr "" + +#: rd_stats.c:2166 +#, c-format +msgid "Cannot handle so many processors!\n" +msgstr "" + +#: pr_stats.c:2319 pr_stats.c:2332 +msgid "Summary" +msgstr "" + +#: pr_stats.c:2370 +msgid "Other devices not listed here" +msgstr "" + +#: sa_common.c:916 +#, c-format +msgid "Error while reading system activity file: %s\n" +msgstr "" + +#: sa_common.c:926 +#, c-format +msgid "End of system activity file unexpected\n" +msgstr "" + +#: sa_common.c:944 +#, c-format +msgid "File created using sar/sadc from sysstat version %d.%d.%d" +msgstr "" + +#: sa_common.c:975 +#, c-format +msgid "Invalid system activity file: %s\n" +msgstr "" + +#: sa_common.c:982 +#, c-format +msgid "" +"Current sysstat version can no longer read the format of this file (%#x)\n" +msgstr "" + +#: sa_common.c:1214 +#, c-format +msgid "Requested activities not available in file %s\n" +msgstr "" + +#: pidstat.c:81 +#, c-format +msgid "" +"Options are:\n" +"[ -C ] [ -d ] [ -h ] [ -I ] [ -l ] [ -r ] [ -s ]\n" +"[ -t ] [ -u ] [ -V ] [ -w ]\n" +"[ -p { [,...] | SELF | ALL } ] [ -T { TASK | CHILD | ALL } ]\n" +msgstr "" diff --git a/pr_stats.c b/pr_stats.c index a1ceab6..b3415e6 100644 --- a/pr_stats.c +++ b/pr_stats.c @@ -1,6 +1,6 @@ /* * pr_stats.c: Functions used by sar to display statistics - * (C) 1999-2011 by Sebastien GODARD (sysstat orange.fr) + * (C) 1999-2012 by Sebastien GODARD (sysstat orange.fr) * *************************************************************************** * This program is free software; you can redistribute it and/or modify it * @@ -812,7 +812,7 @@ __print_funct_t print_disk_stats(struct activity *a, int prev, int curr, int i, j; struct stats_disk *sdc, *sdp; struct ext_disk_stats xds; - char *dev_name; + char *dev_name, *persist_dev_name; if (dis) { printf("\n%-11s DEV tps rd_sec/s wr_sec/s avgrq-sz" @@ -834,14 +834,24 @@ __print_funct_t print_disk_stats(struct activity *a, int prev, int curr, compute_ext_disk_stats(sdc, sdp, itv, &xds); dev_name = NULL; + persist_dev_name = NULL; - if ((USE_PRETTY_OPTION(flags)) && (sdc->major == dm_major)) { - dev_name = transform_devmapname(sdc->major, sdc->minor); + if (DISPLAY_PERSIST_NAME_S(flags)) { + persist_dev_name = get_persistent_name_from_pretty(get_devname(sdc->major, sdc->minor, TRUE)); } + + if (persist_dev_name) { + dev_name = persist_dev_name; + } + else { + if ((USE_PRETTY_OPTION(flags)) && (sdc->major == dm_major)) { + dev_name = transform_devmapname(sdc->major, sdc->minor); + } - if (!dev_name) { - dev_name = get_devname(sdc->major, sdc->minor, - USE_PRETTY_OPTION(flags)); + if (!dev_name) { + dev_name = get_devname(sdc->major, sdc->minor, + USE_PRETTY_OPTION(flags)); + } } printf("%-11s %9s %9.2f %9.2f %9.2f %9.2f %9.2f %9.2f %9.2f %9.2f\n", diff --git a/rndr_stats.c b/rndr_stats.c index 037ed30..a886552 100644 --- a/rndr_stats.c +++ b/rndr_stats.c @@ -961,7 +961,7 @@ __print_funct_t render_disk_stats(struct activity *a, int isdb, char *pre, int i, j; struct stats_disk *sdc, *sdp; struct ext_disk_stats xds; - char *dev_name; + char *dev_name, *persist_dev_name; int pt_newlin = (DISPLAY_HORIZONTALLY(flags) ? PT_NOFLAG : PT_NEWLIN); @@ -979,14 +979,24 @@ __print_funct_t render_disk_stats(struct activity *a, int isdb, char *pre, compute_ext_disk_stats(sdc, sdp, itv, &xds); dev_name = NULL; + persist_dev_name = NULL; - if ((USE_PRETTY_OPTION(flags)) && (sdc->major == dm_major)) { - dev_name = transform_devmapname(sdc->major, sdc->minor); + if (DISPLAY_PERSIST_NAME_S(flags)) { + persist_dev_name = get_persistent_name_from_pretty(get_devname(sdc->major, sdc->minor, TRUE)); } + + if (persist_dev_name) { + dev_name = persist_dev_name; + } + else { + if ((USE_PRETTY_OPTION(flags)) && (sdc->major == dm_major)) { + dev_name = transform_devmapname(sdc->major, sdc->minor); + } - if (!dev_name) { - dev_name = get_devname(sdc->major, sdc->minor, - USE_PRETTY_OPTION(flags)); + if (!dev_name) { + dev_name = get_devname(sdc->major, sdc->minor, + USE_PRETTY_OPTION(flags)); + } } render(isdb, pre, PT_NOFLAG, diff --git a/sa.h b/sa.h index 3bac346..f81f17b 100644 --- a/sa.h +++ b/sa.h @@ -84,20 +84,22 @@ #define S_F_PER_PROC 0x00000400 #define S_F_HORIZONTALLY 0x00000800 #define S_F_COMMENT 0x00001000 - -#define WANT_SINCE_BOOT(m) (((m) & S_F_SINCE_BOOT) == S_F_SINCE_BOOT) -#define WANT_SA_ROTAT(m) (((m) & S_F_SA_ROTAT) == S_F_SA_ROTAT) -#define USE_PRETTY_OPTION(m) (((m) & S_F_DEV_PRETTY) == S_F_DEV_PRETTY) -#define FORCE_FILE(m) (((m) & S_F_FORCE_FILE) == S_F_FORCE_FILE) -#define INTERVAL_SET(m) (((m) & S_F_INTERVAL_SET) == S_F_INTERVAL_SET) -#define PRINT_TRUE_TIME(m) (((m) & S_F_TRUE_TIME) == S_F_TRUE_TIME) -#define LOCK_FILE(m) (((m) & S_F_LOCK_FILE) == S_F_LOCK_FILE) -#define PRINT_SEC_EPOCH(m) (((m) & S_F_SEC_EPOCH) == S_F_SEC_EPOCH) -#define DISPLAY_HDR_ONLY(m) (((m) & S_F_HDR_ONLY) == S_F_HDR_ONLY) -#define FILE_LOCKED(m) (((m) & S_F_FILE_LOCKED) == S_F_FILE_LOCKED) -#define WANT_PER_PROC(m) (((m) & S_F_PER_PROC) == S_F_PER_PROC) -#define DISPLAY_HORIZONTALLY(m) (((m) & S_F_HORIZONTALLY) == S_F_HORIZONTALLY) -#define DISPLAY_COMMENT(m) (((m) & S_F_COMMENT) == S_F_COMMENT) +#define S_F_PERSIST_NAME 0x00002000 + +#define WANT_SINCE_BOOT(m) (((m) & S_F_SINCE_BOOT) == S_F_SINCE_BOOT) +#define WANT_SA_ROTAT(m) (((m) & S_F_SA_ROTAT) == S_F_SA_ROTAT) +#define USE_PRETTY_OPTION(m) (((m) & S_F_DEV_PRETTY) == S_F_DEV_PRETTY) +#define FORCE_FILE(m) (((m) & S_F_FORCE_FILE) == S_F_FORCE_FILE) +#define INTERVAL_SET(m) (((m) & S_F_INTERVAL_SET) == S_F_INTERVAL_SET) +#define PRINT_TRUE_TIME(m) (((m) & S_F_TRUE_TIME) == S_F_TRUE_TIME) +#define LOCK_FILE(m) (((m) & S_F_LOCK_FILE) == S_F_LOCK_FILE) +#define PRINT_SEC_EPOCH(m) (((m) & S_F_SEC_EPOCH) == S_F_SEC_EPOCH) +#define DISPLAY_HDR_ONLY(m) (((m) & S_F_HDR_ONLY) == S_F_HDR_ONLY) +#define FILE_LOCKED(m) (((m) & S_F_FILE_LOCKED) == S_F_FILE_LOCKED) +#define WANT_PER_PROC(m) (((m) & S_F_PER_PROC) == S_F_PER_PROC) +#define DISPLAY_HORIZONTALLY(m) (((m) & S_F_HORIZONTALLY) == S_F_HORIZONTALLY) +#define DISPLAY_COMMENT(m) (((m) & S_F_COMMENT) == S_F_COMMENT) +#define DISPLAY_PERSIST_NAME_S(m) (((m) & S_F_PERSIST_NAME) == S_F_PERSIST_NAME) #define AO_F_NULL 0x00000000 diff --git a/sa_common.c b/sa_common.c index 18a08f9..52a8704 100644 --- a/sa_common.c +++ b/sa_common.c @@ -1232,7 +1232,7 @@ void check_file_actlst(int *ifd, char *dfile, struct activity *act[], * @flags Common flags and system state. * * RETURNS: - * 0 on success, 1 otherwise. + * 0 on success. *************************************************************************** */ int parse_sar_opt(char *argv[], int *opt, struct activity *act[], @@ -1285,6 +1285,31 @@ int parse_sar_opt(char *argv[], int *opt, struct activity *act[], act[p]->options |= AO_SELECTED; break; + case 'j': + if (argv[*opt + 1]) { + (*opt)++; + if (strnlen(argv[*opt], MAX_FILE_LEN) >= MAX_FILE_LEN - 1) + return 1; + + strncpy(persistent_name_type, argv[*opt], MAX_FILE_LEN - 1); + persistent_name_type[MAX_FILE_LEN - 1] = '\0'; + strtolower(persistent_name_type); + if (!get_persistent_type_dir(persistent_name_type)) { + fprintf(stderr, _("Invalid type of persistent device name\n")); + return 2; + } + /* + * If persistent device name doesn't exist for device, use + * its pretty name. + */ + *flags |= S_F_PERSIST_NAME + S_F_DEV_PRETTY; + return 0; + } + else { + return 1; + } + break; + case 'p': *flags |= S_F_DEV_PRETTY; break; diff --git a/sadf.c b/sadf.c index 70b284b..0b14f85 100644 --- a/sadf.c +++ b/sadf.c @@ -1,6 +1,6 @@ /* * sadf: system activity data formatter - * (C) 1999-2011 by Sebastien GODARD (sysstat orange.fr) + * (C) 1999-2012 by Sebastien GODARD (sysstat orange.fr) * *************************************************************************** * This program is free software; you can redistribute it and/or modify it * @@ -1334,7 +1334,7 @@ void read_stats_from_file(char dfile[]) int main(int argc, char **argv) { int opt = 1, sar_options = 0; - int i; + int i, rc; char dfile[MAX_FILE_LEN]; struct tm rectime; @@ -1425,8 +1425,11 @@ int main(int argc, char **argv) else if (!strncmp(argv[opt], "-", 1)) { /* Other options not previously tested */ if (sar_options) { - if (parse_sar_opt(argv, &opt, act, &flags, C_SADF)) { - usage(argv[0]); + if ((rc = parse_sar_opt(argv, &opt, act, &flags, C_SADF)) != 0) { + if (rc == 1) { + usage(argv[0]); + } + exit(1); } } else { diff --git a/sar.c b/sar.c index 2a03aba..d86bf30 100644 --- a/sar.c +++ b/sar.c @@ -1,6 +1,6 @@ /* * sar: report system activity - * (C) 1999-2011 by Sebastien GODARD (sysstat orange.fr) + * (C) 1999-2012 by Sebastien GODARD (sysstat orange.fr) * *************************************************************************** * This program is free software; you can redistribute it and/or modify it * @@ -107,6 +107,7 @@ void usage(char *progname) "[ -R ] [ -S ] [ -t ] [ -u [ ALL ] ] [ -v ] [ -V ] [ -w ] [ -W ] [ -y ]\n" "[ -I { [,...] | SUM | ALL | XALL } ] [ -P { [,...] | ALL } ]\n" "[ -m { [,...] | ALL } ] [ -n { [,...] | ALL } ]\n" + "[ -j { ID | LABEL | PATH | UUID | ... } ]\n" "[ -o [ ] | -f [ ] | -[0-9]+ ]\n" "[ -i ] [ -s [ ] ] [ -e [ ] ]\n")); exit(1); @@ -1081,7 +1082,7 @@ void read_stats(void) */ int main(int argc, char **argv) { - int i, opt = 1, args_idx = 2; + int i, rc, opt = 1, args_idx = 2; int fd[2]; int day_offset = 0; char from_file[MAX_FILE_LEN], to_file[MAX_FILE_LEN]; @@ -1216,8 +1217,11 @@ int main(int argc, char **argv) else if (!strncmp(argv[opt], "-", 1)) { /* Other options not previously tested */ - if (parse_sar_opt(argv, &opt, act, &flags, C_SAR)) { - usage(argv[0]); + if ((rc = parse_sar_opt(argv, &opt, act, &flags, C_SAR)) != 0) { + if (rc == 1) { + usage(argv[0]); + } + exit(1); } opt++; } diff --git a/xml_stats.c b/xml_stats.c index 7c9ff58..92e06a3 100644 --- a/xml_stats.c +++ b/xml_stats.c @@ -1,6 +1,6 @@ /* * xml_stats.c: Funtions used by sadf to display statistics in XML. - * (C) 1999-2011 by Sebastien GODARD (sysstat orange.fr) + * (C) 1999-2012 by Sebastien GODARD (sysstat orange.fr) * *************************************************************************** * This program is free software; you can redistribute it and/or modify it * @@ -648,7 +648,7 @@ __print_funct_t xml_print_disk_stats(struct activity *a, int curr, int tab, int i, j; struct stats_disk *sdc, *sdp; struct ext_disk_stats xds; - char *dev_name; + char *dev_name, *persist_dev_name; xprintf(tab, ""); tab++; @@ -667,14 +667,24 @@ __print_funct_t xml_print_disk_stats(struct activity *a, int curr, int tab, compute_ext_disk_stats(sdc, sdp, itv, &xds); dev_name = NULL; + persist_dev_name = NULL; - if ((USE_PRETTY_OPTION(flags)) && (sdc->major == dm_major)) { - dev_name = transform_devmapname(sdc->major, sdc->minor); + if (DISPLAY_PERSIST_NAME_S(flags)) { + persist_dev_name = get_persistent_name_from_pretty(get_devname(sdc->major, sdc->minor, TRUE)); } + + if (persist_dev_name) { + dev_name = persist_dev_name; + } + else { + if ((USE_PRETTY_OPTION(flags)) && (sdc->major == dm_major)) { + dev_name = transform_devmapname(sdc->major, sdc->minor); + } - if (!dev_name) { - dev_name = get_devname(sdc->major, sdc->minor, - USE_PRETTY_OPTION(flags)); + if (!dev_name) { + dev_name = get_devname(sdc->major, sdc->minor, + USE_PRETTY_OPTION(flags)); + } } xprintf(tab, "