]> granicus.if.org Git - sysstat/commitdiff
Persistent device names support added to sar and iostat (option -j)
authorSebastien <seb@kluane.home>
Wed, 11 Jul 2012 19:31:14 +0000 (21:31 +0200)
committerSebastien <seb@kluane.home>
Wed, 11 Jul 2012 19:31:14 +0000 (21:31 +0200)
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?

16 files changed:
CHANGES
common.c
common.h
iostat.c
iostat.h
json_stats.c
man/iostat.in
man/sar.in
nls/sysstat.pot
pr_stats.c
rndr_stats.c
sa.h
sa_common.c
sadf.c
sar.c
xml_stats.c

diff --git a/CHANGES b/CHANGES
index 2d10aeecd13d3d33eb04a2774263cdcb6b5218f1..ea4e2832753e22957aca8503c57773ff7ad28bbe 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,9 +1,12 @@
 Changes:
 
 xxxx/xx/xx: Version 10.1.1 - Sebastien Godard (sysstat <at> 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 <at> orange.fr)
        * [Alain Chereau]: Options -g and -T added to iostat. These
index ea8267d34c4bb4d88bfc987b5789e61e6bb622d0..97d59072093647eb18d5a3dc24b1137f82ab95c7 100644 (file)
--- a/common.c
+++ b/common.c
@@ -28,6 +28,8 @@
 #include <sys/ioctl.h>
 #include <sys/types.h>
 #include <dirent.h>
+#include <ctype.h>
+#include <libgen.h>
 
 #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;
+}
index b70ea6628cfd62a2c0e0f500ade362905dfcd6b2..4bad2c0eadde7c7a6145d5f176062cc343f7c438 100644 (file)
--- a/common.h
+++ b/common.h
@@ -1,6 +1,6 @@
 /*
  * sysstat: System performance tools for Linux
- * (C) 1999-2011 by Sebastien Godard (sysstat <at> orange.fr)
+ * (C) 1999-2012 by Sebastien Godard (sysstat <at> orange.fr)
  */
 
 #ifndef _COMMON_H
@@ -13,7 +13,6 @@
 #include <sched.h>     /* 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.
 
 /*
  * 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) { \
                                        }                               \
                                } 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);
index 61fb2a6e5ed66b61e18e465885da3959a49f0a32..d50cbf91d4d99176249c397cc338e6a9699086b7 100644 (file)
--- 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 | ... } [ <device> [...] | ALL ] ]\n"
                          "[ [ [ -T ] -g <group_name> ] { <device> [...] | ALL } ]\n"
                          "[ -p [ <device> [,...] | 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 | ... } [ <device> [...] | ALL ] ]\n"
                          "[ [ [ -T ] -g <group_name> ] { <device> [...] | ALL } ]\n"
                          "[ -p [ <device> [,...] | 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++;
index fa2ca21144d35983dd8d73535f36b058ababee16..281689d44de59079c41e68721406d4fa6abe4eed 100644 (file)
--- 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)
index 3acd18fd21225732c88a0f0cc48ea7ed688f163b..6fa031476b1caa5c9d01d07e186b7dfa97822bec 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * json_stats.c: Funtions used by sadf to display statistics in JSON format.
- * (C) 1999-2011 by Sebastien GODARD (sysstat <at> orange.fr)
+ * (C) 1999-2012 by Sebastien GODARD (sysstat <at> 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");
                }
index 768c4ecb5c17949e09763ea815fb157745e4c572..066a779e17c58f735b335e965f01a41ad30da4a7 100644 (file)
@@ -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 <at> orange.fr)
 .SH SEE ALSO
index 47a3c15f80af7b5cce2c89bcb6d0f8bbec0ea4d4..0314b0013cddc3af1460b794d5f945ea3b68775f 100644 (file)
@@ -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.
index 83747339862ebe456670f4d01fae2ad64196b222..2f61331ab8c9dd975e55fadca678e5c67d488b75 100644 (file)
@@ -8,43 +8,44 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: sysstat <at> 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 <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\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 ] [ <interval> [ <count> ] ]\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 ] [ <interval> [ <count> ] ]\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 { <cpu> [,...] | 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 ] [ <interval> [ <count> ] ] [ <outfile> ]\n"
 msgstr ""
 
-#: pidstat.c:81
+#: sadc.c:84
 #, c-format
 msgid ""
 "Options are:\n"
-"[ -C <command> ] [ -d ] [ -h ] [ -I ] [ -l ] [ -r ] [ -s ]\n"
-"[ -t ] [ -u ] [ -V ] [ -w ]\n"
-"[ -p { <pid> [,...] | 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 <comment> ] [ -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 ] [ <interval> [ <count> ] ] [ <outfile> ]\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 <comment> ] [ -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 ""
 "[ -- <sar_options> ]\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 { <cpu> [,...] | 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 { <int> [,...] | SUM | ALL | XALL } ] [ -P { <cpu> [,...] | ALL } ]\n"
 "[ -m { <keyword> [,...] | ALL } ] [ -n { <keyword> [,...] | ALL } ]\n"
-"[ -o [ <filename> ] | -f [ <filename> ] ]\n"
+"[ -o [ <filename> ] | -f [ <filename> ] | -[0-9]+ ]\n"
 "[ -i <interval> ] [ -s [ <hh:mm:ss> ] ] [ -e [ <hh:mm:ss> ] ]\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 <command> ] [ -d ] [ -h ] [ -I ] [ -l ] [ -r ] [ -s ]\n"
+"[ -t ] [ -u ] [ -V ] [ -w ]\n"
+"[ -p { <pid> [,...] | SELF | ALL } ] [ -T { TASK | CHILD | ALL } ]\n"
+msgstr ""
index a1ceab69830dd9927130d2a5fede1291ffe19e23..b3415e623f9c404964b9871fa736267bbeb9c6b1 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * pr_stats.c: Functions used by sar to display statistics
- * (C) 1999-2011 by Sebastien GODARD (sysstat <at> orange.fr)
+ * (C) 1999-2012 by Sebastien GODARD (sysstat <at> 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",
index 037ed3064f5df3667fd2ff8dbb243cd92d159528..a8865527e6d4c201984be89e265734bea5983fbe 100644 (file)
@@ -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 3bac346fefabdb676c0b0cb30a9744e330c4f1ac..f81f17baf47fdfe942ff920e752fc0cc9c575873 100644 (file)
--- a/sa.h
+++ b/sa.h
 #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
 
index 18a08f9fd563c59bff6c0a1b1feb74e7311cad25..52a87046fb2d9b87b68e4975d771fad5dc7bd61a 100644 (file)
@@ -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 70b284b6c65d5057de9f842ada166adbdde79dbc..0b14f8593976586eb80893a85b9cf15a64459c98 100644 (file)
--- a/sadf.c
+++ b/sadf.c
@@ -1,6 +1,6 @@
 /*
  * sadf: system activity data formatter
- * (C) 1999-2011 by Sebastien GODARD (sysstat <at> orange.fr)
+ * (C) 1999-2012 by Sebastien GODARD (sysstat <at> 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 2a03abad04abb2fa50f561898df2f16a30a1579f..d86bf3041f857092297bfb71315d48b71c789acb 100644 (file)
--- a/sar.c
+++ b/sar.c
@@ -1,6 +1,6 @@
 /*
  * sar: report system activity
- * (C) 1999-2011 by Sebastien GODARD (sysstat <at> orange.fr)
+ * (C) 1999-2012 by Sebastien GODARD (sysstat <at> 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 { <int> [,...] | SUM | ALL | XALL } ] [ -P { <cpu> [,...] | ALL } ]\n"
                          "[ -m { <keyword> [,...] | ALL } ] [ -n { <keyword> [,...] | ALL } ]\n"
+                         "[ -j { ID | LABEL | PATH | UUID | ... } ]\n"
                          "[ -o [ <filename> ] | -f [ <filename> ] | -[0-9]+ ]\n"
                          "[ -i <interval> ] [ -s [ <hh:mm:ss> ] ] [ -e [ <hh:mm:ss> ] ]\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++;
                }
index 7c9ff5867f52ee8a95b05bd6c77a084c32e852f8..92e06a3e250f386906ed0ac582db194849fd1da6 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * xml_stats.c: Funtions used by sadf to display statistics in XML.
- * (C) 1999-2011 by Sebastien GODARD (sysstat <at> orange.fr)
+ * (C) 1999-2012 by Sebastien GODARD (sysstat <at> 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, "<disk per=\"second\">");
        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, "<disk-device dev=\"%s\" "