With recent kernels without CONFIG_NUMA (including Fedora 32-bit),
the vm_stat_init() function aborts when getting numa_stat_item
enum items, (probably) because it is not defined.
crash> kmem -V
double free or corruption (!prev)
Aborted (core dumped)
We can avoid the abort by checking whether the length of the
vm_numa_stat array is also not zero.
This patch tested OK with the following kernels:
4.17.0-0.rc5.git3.1.fc29.i686
4.18.0-0.rc5.git4.1.fc29.x86_64
3.10.0-862.el7.x86_64
Signed-off-by: Kazuhito Hagio <k-hagio(a)ab.jp.nec.com>
---
defs.h | 1 +
memory.c | 10 ++++++----
symbols.c | 4 ++++
3 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/defs.h b/defs.h
index f569a62..6fdb478 100644
--- a/defs.h
+++ b/defs.h
@@ -2220,6 +2220,7 @@ struct array_table {
int height_to_maxnodes;
int task_struct_rlim;
int signal_struct_rlim;
+ int vm_numa_stat;
};
/*
diff --git a/memory.c b/memory.c
index 7c0cb5f..e02ba68 100644
--- a/memory.c
+++ b/memory.c
@@ -17454,11 +17454,12 @@ vm_stat_init(void)
} else if (symbol_exists("vm_zone_stat") &&
get_symbol_type("vm_zone_stat",
NULL, NULL) == TYPE_CODE_ARRAY) {
- if (symbol_exists("vm_numa_stat")) {
+ if (symbol_exists("vm_numa_stat") &&
+ get_array_length("vm_numa_stat", NULL, 0)) {
vt->nr_vm_stat_items =
get_array_length("vm_zone_stat", NULL, 0)
+ get_array_length("vm_node_stat", NULL, 0)
- + get_array_length("vm_numa_stat", NULL, 0);
+ + ARRAY_LENGTH(vm_numa_stat);
split_vmstat = 2;
enumerator_value("NR_VM_ZONE_STAT_ITEMS", &zone_cnt);
enumerator_value("NR_VM_NODE_STAT_ITEMS", &node_cnt);
@@ -17599,7 +17600,7 @@ dump_vm_stat(char *item, long *retval, ulong zone)
buf = GETBUF(sizeof(ulong) * vt->nr_vm_stat_items);
if (symbol_exists("vm_node_stat") &&
symbol_exists("vm_zone_stat") &&
- symbol_exists("vm_numa_stat"))
+ symbol_exists("vm_numa_stat") && ARRAY_LENGTH(vm_numa_stat))
split_vmstat = 2;
else if (symbol_exists("vm_node_stat") &&
symbol_exists("vm_zone_stat"))
split_vmstat = 1;
@@ -17666,7 +17667,8 @@ dump_vm_stat(char *item, long *retval, ulong zone)
if (!zone) {
if ((i == node_start) && symbol_exists("vm_node_stat"))
fprintf(fp, "\n VM_NODE_STAT:\n");
- if ((i == numa_start) && symbol_exists("vm_numa_stat"))
+ if ((i == numa_start) && symbol_exists("vm_numa_stat")
+ && ARRAY_LENGTH(vm_numa_stat))
fprintf(fp, "\n VM_NUMA_STAT:\n");
}
fprintf(fp, "%s%s: %ld\n",
diff --git a/symbols.c b/symbols.c
index df84ee2..bee60ba 100644
--- a/symbols.c
+++ b/symbols.c
@@ -8457,6 +8457,8 @@ builtin_array_length(char *s, int len, int *two_dim)
lenptr = &array_table.task_struct_rlim;
else if (STREQ(s, "signal_struct.rlim"))
lenptr = &array_table.signal_struct_rlim;
+ else if (STREQ(s, "vm_numa_stat"))
+ lenptr = &array_table.vm_numa_stat;
if (!lenptr) /* not stored */
return(len);
@@ -10594,6 +10596,8 @@ dump_offset_table(char *spec, ulong makestruct)
ARRAY_LENGTH(task_struct_rlim));
fprintf(fp, " signal_struct_rlim: %d\n",
ARRAY_LENGTH(signal_struct_rlim));
+ fprintf(fp, " vm_numa_stat: %d\n",
+ ARRAY_LENGTH(vm_numa_stat));
if (spec) {
int in_size_table, in_array_table, arrays, offsets, sizes;
--
1.8.3.1