[PATCH] fix vmstat handling
by vinayak menon
From: Vinayak Menon <vinayakm.list(a)gmail.com>
With kernels where LRUs are moved to node and thus vm_stat is
split into zone and node, crash utility fails to show the vmstat with "kmem
-V", and the "CACHED" of kmem -i is shown as zero.
Signed-off-by: Vinayak Menon <vinayakm.list(a)gmail.com>
---
memory.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 76 insertions(+), 21 deletions(-)
diff --git a/memory.c b/memory.c
index ebd671a..3097558 100644
--- a/memory.c
+++ b/memory.c
@@ -17340,30 +17340,43 @@ vm_stat_init(void)
int c ATTRIBUTE_UNUSED;
struct gnu_request *req;
char *start;
- long enum_value;
+ long enum_value, zc = -1;
+ int split_vmstat = 0, ni = 0;
if (vt->flags & VM_STAT)
return TRUE;
- if ((vt->nr_vm_stat_items == -1) || !symbol_exists("vm_stat"))
+ if ((vt->nr_vm_stat_items == -1) ||
+ (!symbol_exists("vm_stat") && !symbol_exists("vm_zone_stat")))
goto bailout;
/*
* look for type: type = atomic_long_t []
*/
if (LKCD_KERNTYPES()) {
- if (!symbol_exists("vm_stat"))
+ if ((!symbol_exists("vm_stat") &&
+ !symbol_exists("vm_zone_stat")))
goto bailout;
/*
* Just assume that vm_stat is an array; there is
* no symbol info in a kerntypes file.
*/
} else {
- if (!symbol_exists("vm_stat") ||
- get_symbol_type("vm_stat", NULL, NULL) != TYPE_CODE_ARRAY)
+ if (symbol_exists("vm_stat") &&
+ get_symbol_type("vm_stat", NULL, NULL) == TYPE_CODE_ARRAY) {
+ vt->nr_vm_stat_items =
+ get_array_length("vm_stat", NULL, 0);
+ } else if (symbol_exists("vm_zone_stat") &&
+ get_symbol_type("vm_zone_stat",
+ NULL, NULL) == TYPE_CODE_ARRAY) {
+ vt->nr_vm_stat_items =
+ get_array_length("vm_zone_stat", NULL, 0)
+ + get_array_length("vm_node_stat", NULL, 0);
+ split_vmstat = 1;
+ enumerator_value("NR_VM_ZONE_STAT_ITEMS", &zc);
+ } else {
goto bailout;
-
- vt->nr_vm_stat_items = get_array_length("vm_stat", NULL, 0);
+ }
}
open_tmpfile();
@@ -17372,6 +17385,14 @@ vm_stat_init(void)
req->name = "zone_stat_item";
req->flags = GNU_PRINT_ENUMERATORS;
gdb_interface(req);
+
+ if (split_vmstat) {
+ req->command = GNU_GET_DATATYPE;
+ req->name = "node_stat_item";
+ req->flags = GNU_PRINT_ENUMERATORS;
+ gdb_interface(req);
+ }
+
FREEBUF(req);
stringlen = 1;
@@ -17383,11 +17404,17 @@ vm_stat_init(void)
continue;
clean_line(buf);
c = parse_line(buf, arglist);
- if (STREQ(arglist[0], "NR_VM_ZONE_STAT_ITEMS")) {
+ if ((!split_vmstat &&
+ STREQ(arglist[0], "NR_VM_ZONE_STAT_ITEMS")) ||
+ (split_vmstat &&
+ STREQ(arglist[0], "NR_VM_NODE_STAT_ITEMS"))) {
if (LKCD_KERNTYPES())
vt->nr_vm_stat_items =
MAX(atoi(arglist[2]), count);
break;
+ } else if (split_vmstat &&
+ STREQ(arglist[0], "NR_VM_ZONE_STAT_ITEMS")) {
+ continue;
} else {
stringlen += strlen(arglist[0]);
count++;
@@ -17409,18 +17436,24 @@ vm_stat_init(void)
if (strstr(buf, "{") || strstr(buf, "}"))
continue;
c = parse_line(buf, arglist);
- if (enumerator_value(arglist[0], &enum_value))
- i = enum_value;
- else {
+ if (!enumerator_value(arglist[0], &enum_value)) {
close_tmpfile();
goto bailout;
}
+
+ i = ni + enum_value;
+ if (!ni && (enum_value == zc)) {
+ ni = zc;
+ continue;
+ }
+
if (i < vt->nr_vm_stat_items) {
vt->vm_stat_items[i] = start;
strcpy(start, arglist[0]);
start += strlen(arglist[0]) + 1;
}
}
+
close_tmpfile();
vt->flags |= VM_STAT;
@@ -17443,39 +17476,61 @@ dump_vm_stat(char *item, long *retval, ulong zone)
ulong *vp;
ulong location;
int i, maxlen, len;
+ long tc, zc = 0, nc = 0;
+ int split_vmstat = 0;
if (!vm_stat_init()) {
if (!item)
if (CRASHDEBUG(1))
- error(INFO,
+ error(INFO,
"vm_stat not available in this kernel\n");
return FALSE;
}
buf = GETBUF(sizeof(ulong) * vt->nr_vm_stat_items);
- location = zone ? zone : symbol_value("vm_stat");
-
- readmem(location, KVADDR, buf,
- sizeof(ulong) * vt->nr_vm_stat_items,
- "vm_stat", FAULT_ON_ERROR);
+ if (symbol_exists("vm_node_stat") && symbol_exists("vm_zone_stat"))
+ split_vmstat = 1;
+ else
+ location = zone ? zone : symbol_value("vm_stat");
+
+ if (split_vmstat) {
+ enumerator_value("NR_VM_ZONE_STAT_ITEMS", &zc);
+ location = zone ? zone : symbol_value("vm_zone_stat");
+ readmem(location, KVADDR, buf,
+ sizeof(ulong) * zc,
+ "vm_zone_stat", FAULT_ON_ERROR);
+ if (!zone) {
+ location = symbol_value("vm_node_stat");
+ enumerator_value("NR_VM_NODE_STAT_ITEMS", &nc);
+ readmem(location, KVADDR, buf + (sizeof(ulong) * zc),
+ sizeof(ulong) * nc,
+ "vm_node_stat", FAULT_ON_ERROR);
+ }
+ tc = zc + nc;
+ } else {
+ readmem(location, KVADDR, buf,
+ sizeof(ulong) * vt->nr_vm_stat_items,
+ "vm_stat", FAULT_ON_ERROR);
+ tc = vt->nr_vm_stat_items;
+ }
if (!item) {
if (!zone)
fprintf(fp, " VM_STAT:\n");
- for (i = maxlen = 0; i < vt->nr_vm_stat_items; i++)
+ for (i = maxlen = 0; i < tc; i++)
if ((len = strlen(vt->vm_stat_items[i])) > maxlen)
maxlen = len;
vp = (ulong *)buf;
- for (i = 0; i < vt->nr_vm_stat_items; i++)
- fprintf(fp, "%s%s: %ld\n",
+ for (i = 0; i < tc; i++)
+ fprintf(fp, "%s%s: %ld\n",
space(maxlen - strlen(vt->vm_stat_items[i])),
vt->vm_stat_items[i], vp[i]);
return TRUE;
}
vp = (ulong *)buf;
- for (i = 0; i < vt->nr_vm_stat_items; i++) {
+ for (i = 0; i < tc; i++) {
if (STREQ(vt->vm_stat_items[i], item)) {
*retval = vp[i];
return TRUE;
6 years, 10 months
[PATCH] fix "ps -l"
by vinayak menon
fix segfault when executing "ps -l".
Signed-off-by: Vinayak Menon <vinayakm.list(a)gmail.com>
---
task.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/task.c b/task.c
index 5754159..f2628b7 100644
--- a/task.c
+++ b/task.c
@@ -3485,7 +3485,7 @@ show_last_run(struct task_context *tc, struct psinfo *psi)
sprintf(format, "[%c%dll%c] ", '%', c,
pc->output_radix == 10 ? 'u' : 'x');
- if (psi) {
+ if (psi && psi->cpus) {
for (c = others = 0; c < kt->cpus; c++) {
if (!NUM_IN_BITMAP(psi->cpus, c))
continue;
--
6 years, 10 months
[PATCH 0/1] Add option to filter disks with no I/O in progress
by Oleksandr Natalenko
While analyzing vmcores the first thing that people do when they want
to check disk I/O is something like this:
crash> dev -d | awk '$5 != 0'
Since there might be lots of disks, this makes scrolling through them
much easier.
I think we should have this option implemented for dev command itself.
Oleksandr Natalenko (1):
dev: add option to filter disks with no I/O
dev.c | 27 +++++++++++++++++++--------
help.c | 1 +
2 files changed, 20 insertions(+), 8 deletions(-)
--
2.15.0
6 years, 10 months
[PATCH RFC 00/14] Minor code cleanups, round zero
by Oleksandr Natalenko
I've managed to instigate clang to build some pieces
of crash-utility code, and it showed unpleasant things
which I'd like to bring into your attention.
The patch bomb contains only minor nitpicks to check
whether I should continue with doing this kind of nasty job
further using static analysis tools, various compilers
and common sense.
Oleksandr Natalenko (14):
tools: fix non-literal NULL conversion
memory: do not compare unsigned expression with negative value
memory: use & for a bitwise operation
task: remove extra parentheses in equality comparison
x86_64: clarify logical operator precedence
lkcd_v1: address of an array always evaluates to true
lkcd_v2_v3: address of an array always evaluates to true
lkcd_v5: address of an array always evaluates to true
lkcd_v7: address of an array always evaluates to true
lkcd_v8: address of an array always evaluates to true
qemu-load: remove unused function get_le64()
sadump: block_size is always non-negative
task: format string should be never empty
symbols: format string should be never empty
lkcd_v1.c | 2 +-
lkcd_v2_v3.c | 2 +-
lkcd_v5.c | 2 +-
lkcd_v7.c | 2 +-
lkcd_v8.c | 2 +-
memory.c | 8 ++++----
qemu-load.c | 8 --------
sadump.c | 3 ---
symbols.c | 9 +++++----
task.c | 20 +++++++++++---------
tools.c | 2 +-
x86_64.c | 4 ++--
12 files changed, 28 insertions(+), 36 deletions(-)
--
2.14.3
6 years, 10 months