nmeter: fix block i/o count on newer Linux kernels
authorDenys Vlasenko <vda.linux@googlemail.com>
Tue, 1 Nov 2011 22:34:46 +0000 (23:34 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Tue, 1 Nov 2011 22:34:46 +0000 (23:34 +0100)
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
procps/nmeter.c

index 9999559..ed54790 100644 (file)
@@ -274,30 +274,56 @@ static int rdval_loadavg(const char* p, ullong *vec, ...)
 //   1  2 3   4         5        6(rd)  7      8     9     10(wr) 11     12 13     14
 //   3  0 hda 51292 14441 841783 926052 25717 79650 843256 3029804 0 148459 3956933
 //   3  1 hda1 0 0 0 0 <- ignore if only 4 fields
+// Linux 3.0 (maybe earlier) started printing full stats for hda1 too.
+// Had to add code which skips such devices.
 static int rdval_diskstats(const char* p, ullong *vec)
 {
-       ullong rd = rd; // for compiler
-       int indexline = 0;
+       char devname[32];
+       unsigned devname_len = 0;
+       int value_idx = 0;
+
        vec[0] = 0;
        vec[1] = 0;
        while (1) {
-               indexline++;
-               while (*p == ' ' || *p == '\t') p++;
-               if (*p == '\0') break;
+               value_idx++;
+               while (*p == ' ' || *p == '\t')
+                       p++;
+               if (*p == '\0')
+                       break;
                if (*p == '\n') {
-                       indexline = 0;
+                       value_idx = 0;
                        p++;
                        continue;
                }
-               if (indexline == 6) {
-                       rd = strtoull(p, NULL, 10);
-               } else if (indexline == 10) {
-                       vec[0] += rd;  // TODO: *sectorsize (don't know how to find out sectorsize)
+               if (value_idx == 3) {
+                       char *end = strchrnul(p, ' ');
+                       /* If this a hda1-like device (same prefix as last one + digit)? */
+                       if (devname_len && strncmp(devname, p, devname_len) == 0 && isdigit(p[devname_len])) {
+                               p = end;
+                               goto skip_line; /* skip entire line */
+                       }
+                       /* It is not. Remember the name for future checks */
+                       devname_len = end - p;
+                       if (devname_len > sizeof(devname)-1)
+                               devname_len = sizeof(devname)-1;
+                       strncpy(devname, p, devname_len);
+                       /* devname[devname_len] = '\0'; - not really needed */
+                       p = end;
+               } else
+               if (value_idx == 6) {
+                       // TODO: *sectorsize (don't know how to find out sectorsize)
+                       vec[0] += strtoull(p, NULL, 10);
+               } else
+               if (value_idx == 10) {
+                       // TODO: *sectorsize (don't know how to find out sectorsize)
                        vec[1] += strtoull(p, NULL, 10);
-                       while (*p != '\n' && *p != '\0') p++;
+ skip_line:
+                       while (*p != '\n' && *p != '\0')
+                               p++;
                        continue;
                }
-               while (*p > ' ') p++; // skip over value
+               while ((unsigned char)(*p) > ' ') // skip over value
+                       p++;
        }
        return 0;
 }