|
|
95ec45 |
commit 5ebdf2fe3f1aca661ed1a13a6aa45e3c27d228c2
|
|
|
95ec45 |
Author: Nathan Scott <nathans@redhat.com>
|
|
|
95ec45 |
Date: Thu Feb 13 14:12:49 2014 +1100
|
|
|
95ec45 |
|
|
|
95ec45 |
Fix valgrind errors in pmdalinux /proc/stat refresh
|
|
|
95ec45 |
|
|
|
95ec45 |
This one has bugged me for a long time, and I finally needed to spend
|
|
|
95ec45 |
some time hunting an obscure memory corruption in pmdalinux - so got
|
|
|
95ec45 |
to revisit this properly.
|
|
|
95ec45 |
|
|
|
95ec45 |
There were a few small problems in refresh_proc_stat causing valgrind
|
|
|
95ec45 |
to report "invalid read of zero size". Most problematic was the code
|
|
|
95ec45 |
reading the stat buffer initially, which slightly confuses the offset
|
|
|
95ec45 |
and size combo in passing a buffer pointer to read(2). The realloc
|
|
|
95ec45 |
call here also happened to allocate 8x the (small) memory it wanted,
|
|
|
95ec45 |
accidently multiplying the size by sizeof(char).
|
|
|
95ec45 |
|
|
|
95ec45 |
The nbufindex calculation also ended up with one more line than was
|
|
|
95ec45 |
in the buffer, which was OK because it always created an empty line
|
|
|
95ec45 |
at the end of it (which doesn't actually exist in /proc/stat).
|
|
|
95ec45 |
|
|
|
95ec45 |
Finally, added some small improvements to the handling of ENOMEM for
|
|
|
95ec45 |
these global stat buffers, and removed a double-memset on the initial
|
|
|
95ec45 |
call (which callocs a zeroed buffer).
|
|
|
95ec45 |
|
|
|
95ec45 |
diff --git a/src/pmdas/linux/proc_stat.c b/src/pmdas/linux/proc_stat.c
|
|
|
95ec45 |
index f4e001c..234b713 100644
|
|
|
95ec45 |
--- a/src/pmdas/linux/proc_stat.c
|
|
|
95ec45 |
+++ b/src/pmdas/linux/proc_stat.c
|
|
|
95ec45 |
@@ -1,7 +1,7 @@
|
|
|
95ec45 |
/*
|
|
|
95ec45 |
* Linux /proc/stat metrics cluster
|
|
|
95ec45 |
*
|
|
|
95ec45 |
- * Copyright (c) 2012 Red Hat.
|
|
|
95ec45 |
+ * Copyright (c) 2012-2014 Red Hat.
|
|
|
95ec45 |
* Copyright (c) 2008-2009 Aconex. All Rights Reserved.
|
|
|
95ec45 |
* Copyright (c) 2000,2004-2008 Silicon Graphics, Inc. All Rights Reserved.
|
|
|
95ec45 |
*
|
|
|
95ec45 |
@@ -39,22 +39,28 @@ refresh_proc_stat(proc_cpuinfo_t *proc_cpuinfo, proc_stat_t *proc_stat)
|
|
|
95ec45 |
static char **bufindex;
|
|
|
95ec45 |
static int nbufindex;
|
|
|
95ec45 |
static int maxbufindex;
|
|
|
95ec45 |
+ int size;
|
|
|
95ec45 |
int n;
|
|
|
95ec45 |
int i;
|
|
|
95ec45 |
int j;
|
|
|
95ec45 |
|
|
|
95ec45 |
- if (fd >= 0)
|
|
|
95ec45 |
- lseek(fd, 0, SEEK_SET);
|
|
|
95ec45 |
- else
|
|
|
95ec45 |
+ if (fd >= 0) {
|
|
|
95ec45 |
+ if (lseek(fd, 0, SEEK_SET) < 0)
|
|
|
95ec45 |
+ return -oserror();
|
|
|
95ec45 |
+ } else {
|
|
|
95ec45 |
if ((fd = open("/proc/stat", O_RDONLY)) < 0)
|
|
|
95ec45 |
return -oserror();
|
|
|
95ec45 |
+ }
|
|
|
95ec45 |
|
|
|
95ec45 |
for (n=0;;) {
|
|
|
95ec45 |
- if (n >= maxstatbuf) {
|
|
|
95ec45 |
- maxstatbuf += 512;
|
|
|
95ec45 |
- statbuf = (char *)realloc(statbuf, maxstatbuf * sizeof(char));
|
|
|
95ec45 |
+ while (n >= maxstatbuf) {
|
|
|
95ec45 |
+ size = maxstatbuf + 512;
|
|
|
95ec45 |
+ if ((statbuf = (char *)realloc(statbuf, size)) == NULL)
|
|
|
95ec45 |
+ return -ENOMEM;
|
|
|
95ec45 |
+ maxstatbuf = size;
|
|
|
95ec45 |
}
|
|
|
95ec45 |
- if ((i = read(fd, statbuf+n, 512)) > 0)
|
|
|
95ec45 |
+ size = (statbuf + maxstatbuf) - (statbuf + n);
|
|
|
95ec45 |
+ if ((i = read(fd, statbuf + n, size)) > 0)
|
|
|
95ec45 |
n += i;
|
|
|
95ec45 |
else
|
|
|
95ec45 |
break;
|
|
|
95ec45 |
@@ -62,20 +68,24 @@ refresh_proc_stat(proc_cpuinfo_t *proc_cpuinfo, proc_stat_t *proc_stat)
|
|
|
95ec45 |
statbuf[n] = '\0';
|
|
|
95ec45 |
|
|
|
95ec45 |
if (bufindex == NULL) {
|
|
|
95ec45 |
+ size = 4 * sizeof(char *);
|
|
|
95ec45 |
+ if ((bufindex = (char **)malloc(size)) == NULL)
|
|
|
95ec45 |
+ return -ENOMEM;
|
|
|
95ec45 |
maxbufindex = 4;
|
|
|
95ec45 |
- bufindex = (char **)malloc(maxbufindex * sizeof(char *));
|
|
|
95ec45 |
}
|
|
|
95ec45 |
|
|
|
95ec45 |
nbufindex = 0;
|
|
|
95ec45 |
- bufindex[nbufindex++] = statbuf;
|
|
|
95ec45 |
+ bufindex[nbufindex] = statbuf;
|
|
|
95ec45 |
for (i=0; i < n; i++) {
|
|
|
95ec45 |
- if (statbuf[i] == '\n') {
|
|
|
95ec45 |
+ if (statbuf[i] == '\n' || statbuf[i] == '\0') {
|
|
|
95ec45 |
statbuf[i] = '\0';
|
|
|
95ec45 |
- if (nbufindex >= maxbufindex) {
|
|
|
95ec45 |
+ if (nbufindex + 1 >= maxbufindex) {
|
|
|
95ec45 |
+ size = (maxbufindex + 4) * sizeof(char *);
|
|
|
95ec45 |
+ if ((bufindex = (char **)realloc(bufindex, size)) == NULL)
|
|
|
95ec45 |
+ return -ENOMEM;
|
|
|
95ec45 |
maxbufindex += 4;
|
|
|
95ec45 |
- bufindex = (char **)realloc(bufindex, maxbufindex * sizeof(char *));
|
|
|
95ec45 |
}
|
|
|
95ec45 |
- bufindex[nbufindex++] = statbuf + i + 1;
|
|
|
95ec45 |
+ bufindex[++nbufindex] = statbuf + i + 1;
|
|
|
95ec45 |
}
|
|
|
95ec45 |
}
|
|
|
95ec45 |
|
|
|
95ec45 |
@@ -130,19 +140,19 @@ refresh_proc_stat(proc_cpuinfo_t *proc_cpuinfo, proc_stat_t *proc_stat)
|
|
|
95ec45 |
proc_stat->n_steal = calloc(1, n);
|
|
|
95ec45 |
proc_stat->n_guest = calloc(1, n);
|
|
|
95ec45 |
}
|
|
|
95ec45 |
-
|
|
|
95ec45 |
- /* reset per-node stats */
|
|
|
95ec45 |
- n = proc_cpuinfo->node_indom->it_numinst * sizeof(unsigned long long);
|
|
|
95ec45 |
- memset(proc_stat->n_user, 0, n);
|
|
|
95ec45 |
- memset(proc_stat->n_nice, 0, n);
|
|
|
95ec45 |
- memset(proc_stat->n_sys, 0, n);
|
|
|
95ec45 |
- memset(proc_stat->n_idle, 0, n);
|
|
|
95ec45 |
- memset(proc_stat->n_wait, 0, n);
|
|
|
95ec45 |
- memset(proc_stat->n_irq, 0, n);
|
|
|
95ec45 |
- memset(proc_stat->n_sirq, 0, n);
|
|
|
95ec45 |
- memset(proc_stat->n_steal, 0, n);
|
|
|
95ec45 |
- memset(proc_stat->n_guest, 0, n);
|
|
|
95ec45 |
-
|
|
|
95ec45 |
+ else {
|
|
|
95ec45 |
+ /* reset per-node stats */
|
|
|
95ec45 |
+ n = proc_cpuinfo->node_indom->it_numinst * sizeof(unsigned long long);
|
|
|
95ec45 |
+ memset(proc_stat->n_user, 0, n);
|
|
|
95ec45 |
+ memset(proc_stat->n_nice, 0, n);
|
|
|
95ec45 |
+ memset(proc_stat->n_sys, 0, n);
|
|
|
95ec45 |
+ memset(proc_stat->n_idle, 0, n);
|
|
|
95ec45 |
+ memset(proc_stat->n_wait, 0, n);
|
|
|
95ec45 |
+ memset(proc_stat->n_irq, 0, n);
|
|
|
95ec45 |
+ memset(proc_stat->n_sirq, 0, n);
|
|
|
95ec45 |
+ memset(proc_stat->n_steal, 0, n);
|
|
|
95ec45 |
+ memset(proc_stat->n_guest, 0, n);
|
|
|
95ec45 |
+ }
|
|
|
95ec45 |
/*
|
|
|
95ec45 |
* cpu 95379 4 20053 6502503
|
|
|
95ec45 |
* 2.6 kernels have 3 additional fields
|
|
|
95ec45 |
|
|
|
95ec45 |
commit f5eaeea7900390ae007f5ed3375cadc6ca86497e
|
|
|
95ec45 |
Author: Nathan Scott <nathans@redhat.com>
|
|
|
95ec45 |
Date: Thu Feb 13 14:20:52 2014 +1100
|
|
|
95ec45 |
|
|
|
95ec45 |
Fix s390x platform issues in /proc/cpuinfo parser
|
|
|
95ec45 |
|
|
|
95ec45 |
The format of /proc/cpuinfo on s390x is nothing like any other
|
|
|
95ec45 |
platform. We cannot attempt to push it through the same code
|
|
|
95ec45 |
path, it simply has nothing in common. If we try (as we used to)
|
|
|
95ec45 |
things fall apart when we use the (negative) cpu number local
|
|
|
95ec45 |
variable to index into the cpuinfo array.
|
|
|
95ec45 |
|
|
|
95ec45 |
Resolved by adding in some defensive code to short-circuit the
|
|
|
95ec45 |
decoding logic when an unexpected file format is seen.
|
|
|
95ec45 |
|
|
|
95ec45 |
diff --git a/src/pmdas/linux/proc_cpuinfo.c b/src/pmdas/linux/proc_cpuinfo.c
|
|
|
95ec45 |
index 6380bc2..d0aa52a 100644
|
|
|
95ec45 |
--- a/src/pmdas/linux/proc_cpuinfo.c
|
|
|
95ec45 |
+++ b/src/pmdas/linux/proc_cpuinfo.c
|
|
|
95ec45 |
@@ -1,7 +1,7 @@
|
|
|
95ec45 |
/*
|
|
|
95ec45 |
* Linux /proc/cpuinfo metrics cluster
|
|
|
95ec45 |
*
|
|
|
95ec45 |
- * Copyright (c) 2013 Red Hat.
|
|
|
95ec45 |
+ * Copyright (c) 2013-2014 Red Hat.
|
|
|
95ec45 |
* Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
|
|
|
95ec45 |
* Portions Copyright (c) 2001 Gilly Ran (gilly@exanet.com) - for the
|
|
|
95ec45 |
* portions supporting the Alpha platform. All rights reserved.
|
|
|
95ec45 |
@@ -185,6 +185,9 @@ refresh_proc_cpuinfo(proc_cpuinfo_t *proc_cpuinfo)
|
|
|
95ec45 |
}
|
|
|
95ec45 |
#endif
|
|
|
95ec45 |
|
|
|
95ec45 |
+ if (cpunum < 0 || cpunum >= proc_cpuinfo->cpuindom->it_numinst)
|
|
|
95ec45 |
+ continue;
|
|
|
95ec45 |
+
|
|
|
95ec45 |
info = &proc_cpuinfo->cpuinfo[cpunum];
|
|
|
95ec45 |
|
|
|
95ec45 |
/* note: order is important due to strNcmp comparisons */
|