[PATCH] kmem option to display pages per migrate type
by vinayak menon
Hi Dave,
Please share your thoughts on adding a -m option to kmem to display
the free pages per migrate type.
This is similar to /proc/pagetypeinfo.
Sample output (without formatting). Patch attached.
crash>
Free pages count per migrate type at order [0-10]:
Node 0, zone Normal, type Unmovable 155 172 92
39 20 8 10 15 7 3 1
Node 0, zone HighMem, type Unmovable 1 2 0
0 0 0 0 0 0 0 0
Node 0, zone Movable, type Unmovable 0 0 0
0 0 0 0 0 0 0 0
Node 0, zone Normal, type Reclaimable 9 3 0
0 1 1 0 0 0 0 0
Node 0, zone HighMem, type Reclaimable 0 0 0
0 0 0 0 0 0 0 0
Node 0, zone Movable, type Reclaimable 0 0 0
0 0 0 0 0 0 0 0
Node 0, zone Normal, type Movable 7 68 35
253 137 38 16 4 0 0 66
Node 0, zone HighMem, type Movable 0 1 0
0 0 0 0 0 0 0 0
Node 0, zone Movable, type Movable 0 0 0
0 0 0 0 0 0 0 0
Node 0, zone Normal, type Reserve 0 0 0
0 0 0 0 0 0 0 1
Node 0, zone HighMem, type Reserve 11 7 5
1 0 0 0 0 0 0 0
Node 0, zone Movable, type Reserve 0 0 0
0 0 0 0 0 0 0 0
Node 0, zone Normal, type Isolate 0 0 0
0 0 0 0 0 0 0 0
Node 0, zone HighMem, type Isolate 0 0 0
0 0 0 0 0 0 0 0
Node 0, zone Movable, type Isolate 0 0 0
0 0 0 0 0 0 0 0
diff --git a/crash-6.0.8/help.c b/crash-6.0.8/help.c
index 6d6ac5e..9ad6c00 100755
--- a/crash-6.0.8/help.c
+++ b/crash-6.0.8/help.c
@@ -5147,7 +5147,7 @@ NULL
char *help_kmem[] = {
"kmem",
"kernel memory",
-"[-f|-F|-p|-c|-C|-i|-s|-S|-v|-V|-n|-z-o] [slab] [[-P] address]\n"
+"[-f|-F|-p|-c|-C|-i|-s|-S|-v|-V|-n|-m|-z-o] [slab] [[-P] address]\n"
" [-g [flags]]",
" This command displays information about the use of kernel memory.\n",
" -f displays the contents of the system free memory headers.",
@@ -5174,6 +5174,8 @@ char *help_kmem[] = {
" values to translate them into kernel virtual addresses.",
" -g displays the enumerator value of all bits in the page
structure's",
" \"flags\" field.",
+" -m displays the number of pages per migrate type for all
orders, for all",
+" nodes.",
" flags when used with -g, translates all bits in this hexadecimal page",
" structure flags value into its enumerator values.",
" slab when used with -s or -S, limits the command to only the
slab cache",
@@ -5605,6 +5607,24 @@ char *help_kmem[] = {
" PG_slab 7 0000080",
" PG_head 14 0004000",
" %s>",
+"\n Display pages per migrate type for all orders, for all nodes:\n",
+" %s> kmem -m",
+" Free pages count per migrate type at order [0-10]:",
+" Node 0, zone Normal, type Unmovable 155 172 92
39 20 8 10 15 7 3 1",
+" Node 0, zone HighMem, type Unmovable 1 2 0
0 0 0 0 0 0 0 0",
+" Node 0, zone Movable, type Unmovable 0 0 0
0 0 0 0 0 0 0 0",
+" Node 0, zone Normal, type Reclaimable 9 3 0
0 1 1 0 0 0 0 0",
+" Node 0, zone HighMem, type Reclaimable 0 0 0
0 0 0 0 0 0 0 0",
+" Node 0, zone Movable, type Reclaimable 0 0 0
0 0 0 0 0 0 0 0",
+" Node 0, zone Normal, type Movable 7 68 35
253 137 38 16 4 0 0 66",
+" Node 0, zone HighMem, type Movable 0 1 0
0 0 0 0 0 0 0 0",
+" Node 0, zone Movable, type Movable 0 0 0
0 0 0 0 0 0 0 0",
+" Node 0, zone Normal, type Reserve 0 0 0
0 0 0 0 0 0 0 1",
+" Node 0, zone HighMem, type Reserve 11 7 5
1 0 0 0 0 0 0 0",
+" Node 0, zone Movable, type Reserve 0 0 0
0 0 0 0 0 0 0 0",
+" Node 0, zone Normal, type Isolate 0 0 0
0 0 0 0 0 0 0 0",
+" Node 0, zone HighMem, type Isolate 0 0 0
0 0 0 0 0 0 0 0",
+" Node 0, zone Movable, type Isolate 0 0 0
0 0 0 0 0 0 0 0",
NULL
};
diff --git a/crash-6.0.8/memory.c b/crash-6.0.8/memory.c
index 02a6de1..e03db84 100755
--- a/crash-6.0.8/memory.c
+++ b/crash-6.0.8/memory.c
@@ -264,6 +264,7 @@ static int verify_pfn(ulong);
static void dump_per_cpu_offsets(void);
static void dump_page_flags(ulonglong);
static ulong kmem_cache_nodelists(ulong);
+static void dump_pgtype_info(void);
/*
* Memory display modes specific to this file.
@@ -4044,6 +4045,8 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm)
* -c displays the number of pages in the page_hash_table.
* -C displays all entries in the page_hash_table.
* -i displays informational data shown by /proc/meminfo.
+ * -m displays information on the number of pages per migrate type
+ * for all orders, for all nodes.
*
* -P forces address to be defined as a physical address
* address when used with -f, the address can be either a page pointer
@@ -4090,7 +4093,7 @@ cmd_kmem(void)
int i;
int c;
int sflag, Sflag, pflag, fflag, Fflag, vflag, zflag, oflag, gflag;
- int nflag, cflag, Cflag, iflag, lflag, Lflag, Pflag, Vflag;
+ int nflag, cflag, Cflag, iflag, lflag, Lflag, Pflag, Vflag, mflag;
struct meminfo meminfo;
ulonglong value[MAXARGS];
char buf[BUFSIZE];
@@ -4100,12 +4103,12 @@ cmd_kmem(void)
spec_addr = 0;
sflag = Sflag = pflag = fflag = Fflag = Pflag = zflag = oflag = 0;
vflag = Cflag = cflag = iflag = nflag = lflag = Lflag = Vflag = 0;
- gflag = 0;
+ gflag = mflag = 0;
escape = FALSE;
BZERO(&meminfo, sizeof(struct meminfo));
BZERO(&value[0], sizeof(ulonglong)*MAXARGS);
- while ((c = getopt(argcnt, args, "gI:sSFfpvczCinl:L:PVo")) != EOF) {
+ while ((c = getopt(argcnt, args, "gI:sSFfpvczCinml:L:PVo")) != EOF) {
switch(c)
{
case 'V':
@@ -4206,6 +4209,10 @@ cmd_kmem(void)
gflag = 1;
break;
+ case 'm':
+ mflag = 1;
+ break;
+
default:
argerrs++;
break;
@@ -4215,8 +4222,8 @@ cmd_kmem(void)
if (argerrs)
cmd_usage(pc->curcmd, SYNOPSIS);
- if ((sflag + Sflag + pflag + fflag + Fflag + Vflag + oflag +
- vflag + Cflag + cflag + iflag + lflag + Lflag + gflag) > 1) {
+ if ((sflag + Sflag + pflag + fflag + Fflag + Vflag + oflag + vflag +
+ Cflag + cflag + iflag + lflag + Lflag + gflag + mflag) > 1) {
error(INFO, "only one flag allowed!\n");
cmd_usage(pc->curcmd, SYNOPSIS);
}
@@ -4444,9 +4451,12 @@ cmd_kmem(void)
if (gflag == 1)
dump_page_flags(0);
+ if (mflag == 1)
+ dump_pgtype_info();
+
if (!(sflag + Sflag + pflag + fflag + Fflag + vflag +
Vflag + zflag + oflag + cflag + Cflag + iflag +
- nflag + lflag + Lflag + gflag + meminfo.calls))
+ nflag + lflag + Lflag + gflag + mflag + meminfo.calls))
cmd_usage(pc->curcmd, SYNOPSIS);
}
@@ -7051,6 +7061,163 @@ bailout:
return total_free;
}
+static void dump_pgtype_info(void)
+{
+ int n, m, z, o;
+ int list_count = 0;
+ int free_cnt = 0;
+ int mtype_sym = 0;
+ int mtype_len = 0;
+ ulong *mtypes;
+ ulong node_zones;
+ ulong temp;
+ ulong freelist;
+ ulong *free_ptr;
+ char *free_list_buf;
+ char name_buf[BUFSIZE];
+ char buf[BUFSIZE];
+ struct node_table *nt;
+ struct list_data list_data;
+
+ if (!(vt->flags & (NODES|ZONES)))
+ error(FATAL,
+ "dump_pgtype_info called without (NODES|ZONES)\n");
+
+ if (!VALID_STRUCT(zone))
+ error(FATAL,
+ "zone struct not available in this kernel\n");
+
+ if (VALID_STRUCT(free_area)) {
+ if (SIZE(free_area) == (3 * sizeof(ulong)))
+ error(FATAL,
+ "free_area type not supported by command\n");
+ else
+ list_count = MEMBER_SIZE("free_area",
+ "free_list")/SIZE(list_head);
+ } else
+ error(FATAL,
+ "free_area structure not found\n");
+
+ free_list_buf = GETBUF(SIZE(list_head));
+
+ do {
+ if (symbol_exists("migratetype_names") &&
+ (get_symbol_type("migratetype_names",
+ NULL, NULL) == TYPE_CODE_ARRAY)) {
+
+ open_tmpfile();
+ sprintf(buf, "whatis migratetype_names");
+ if (!gdb_pass_through(buf, fp, GNU_RETURN_ON_ERROR)) {
+ close_tmpfile();
+ break;
+ }
+
+ rewind(pc->tmpfile);
+ while (fgets(buf, BUFSIZE, pc->tmpfile)) {
+ if (STRNEQ(buf, "type = "))
+ break;
+ }
+ close_tmpfile();
+
+ if (!strstr(buf, "char *") ||
+ (count_chars(buf, '[') != 1) ||
+ (count_chars(buf, ']') != 1))
+ break;
+
+ mtype_len = get_array_length("migratetype_names",
+ NULL, 0);
+
+ mtypes = (ulong *)GETBUF(mtype_len * sizeof(ulong));
+
+ readmem(symbol_value("migratetype_names"),
+ KVADDR, mtypes,
+ (mtype_len * sizeof(ulong)),
+ NULL, FAULT_ON_ERROR);
+
+ mtype_sym = 1;
+ }
+ } while (0);
+
+ fprintf(fp, "%-43s [%d-%d]:",
+ "Free pages count per migrate type at order",
+ 0, vt->nr_free_areas - 1);
+
+ fprintf(fp, "\n");
+
+ for (n = 0; n < vt->numnodes; n++) {
+ nt = &vt->node_table[n];
+ node_zones = nt->pgdat + OFFSET(pglist_data_node_zones);
+
+ for (m = 0; m < list_count; m++) {
+
+ for (z = 0; z < vt->nr_zones; z++) {
+ readmem((node_zones + (z * SIZE(zone)))
+ + OFFSET(zone_name), KVADDR, &temp,
+ sizeof(void *), "node_zones name",
+ FAULT_ON_ERROR);
+ read_string(temp, name_buf, BUFSIZE-1);
+
+ fprintf(fp, "Node %4d, ", nt->node_id);
+ fprintf(fp, "zone %8s, ", name_buf);
+
+ if (mtype_sym) {
+ read_string(mtypes[m],
+ name_buf, BUFSIZE-1);
+ fprintf(fp, "type %12s ", name_buf);
+ } else
+ fprintf(fp, "type %12d ", m);
+
+ for (o = 0; o < vt->nr_free_areas; o++) {
+ freelist =
+ (node_zones + (z * SIZE(zone)))
+ + (OFFSET(zone_free_area) +
+ (o * SIZE(free_area))) +
+ (m * SIZE(list_head));
+
+ readmem(freelist, KVADDR, free_list_buf,
+ SIZE(list_head),
+ "free_area free_list",
+ FAULT_ON_ERROR);
+
+ free_ptr = (ulong *)free_list_buf;
+
+ if (!(*free_ptr) ||
+ (*free_ptr == freelist)) {
+ fprintf(fp, "%6lu ", 0);
+ continue;
+ }
+
+ BZERO(&list_data,
+ sizeof(struct list_data));
+ list_data.flags = RETURN_ON_DUPLICATE;
+ list_data.start = *free_ptr;
+ list_data.end = freelist;
+ list_data.list_head_offset =
+ OFFSET(page_lru) +
+ OFFSET(list_head_next);
+
+ free_cnt = do_list(&list_data);
+ if (free_cnt < 0) {
+ error(pc->curcmd_flags &
+ IGNORE_ERRORS ? INFO : FATAL,
+ "corrupted free list\n");
+ free_cnt = 0;
+ }
+
+ fprintf(fp, "%6lu ", free_cnt);
+ }
+ fprintf(fp, "\n");
+ }
+ }
+ node_zones + OFFSET(zone_free_area);
+ }
+
+ FREEBUF(free_list_buf);
+
+ if (mtype_sym)
+ FREEBUF(mtypes);
+}
+
/*
* dump_kmeminfo displays basic memory use information typically shown
* by /proc/meminfo, and then some...
--
1.7.6
11 years, 5 months
Throw read error on vmcore produced by ARM soc.
by Li Haifeng
Hi, list.
I use crash-utility to analyse crash dump core from ARM soc. When I
execute command below, I get the error "crash: read error: kernel
virtual address: c0c1e040 type: "first vmap_area va_start"". I also
test it by gdb. It works fine. The Linux kernel's version is v3.0.8.
hfli@pc1935:~/work/crash-utility$ ./crash vmlinux Vmcore
crash 6.1.4
Copyright (C) 2002-2013 Red Hat, Inc.
Copyright (C) 2004, 2005, 2006, 2010 IBM Corporation
Copyright (C) 1999-2006 Hewlett-Packard Co
Copyright (C) 2005, 2006, 2011, 2012 Fujitsu Limited
Copyright (C) 2006, 2007 VA Linux Systems Japan K.K.
Copyright (C) 2005, 2011 NEC Corporation
Copyright (C) 1999, 2002, 2007 Silicon Graphics, Inc.
Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
This program is free software, covered by the GNU General Public License,
and you are welcome to change it and/or distribute copies of it under
certain conditions. Enter "help copying" to see the conditions.
This program has absolutely no warranty. Enter "help warranty" for details.
GNU gdb (GDB) 7.3.1
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-elf-linux"...
crash: read error: kernel virtual address: c0c1e040 type: "first
vmap_area va_start"
Errors like the one above typically occur when the kernel and memory source
do not match. These are the files being used:
KERNEL: vmlinux
DUMPFILE: Vmcore
--------------------------------------------------------------------------------------------
GDB works fine.
hfli@pc1935:~/work/crash-utility$ ./gdb-7.5/gdb/gdb vmlinux Vmcore
GNU gdb (GDB) 7.5
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86 --target=arm-linux-gnueabi".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/hfli/work/crash-utility/vmlinux...done.
warning: exec file is newer than core file.
[New LWP 332]
#0 0xc0158de0 in sysrq_handle_crash (key=99) at drivers/tty/sysrq.c:134
warning: Source file is more recent than executable.
134 *killer = 1;
(gdb)
Any suggestion will be appreciate.
Thanks.
11 years, 5 months
[PATCH] fix bug of gdb involved by gdb-7.3.1.patch
by qiaonuohan
Hi Dave,
The newly modification of gdb involved some bug. When using mount,
crash prints the following message.
<cut>
crash> mount
mount: invalid structure member offset: mount_mnt_devname
FILE: filesys.c LINE: 1396 FUNCTION: show_mounts()
[./crash] error trace: 45dbf7 => 49dc02 => 49af31 => 502cdd
MOUNT SUPERBLK TYPE DEVNAME DIRNAME
502cdd: OFFSET_verify+189
49af31: show_mounts+785
49dc02: cmd_mount+1234
45dbf7: exec_command+919
mount: invalid structure member offset: mount_mnt_devname
FILE: filesys.c LINE: 1396 FUNCTION: show_mounts()
crash>
<cut>
Then I try to find what caused the bug. I found a wrong number is returned
when using "STRUCT_SIZE_INIT(mount, "mount");".
and then I referred to the changelog to see what had happened, and I guess
from changelog, the bug is related to
<cut>
- Patch to the internal gdb_get_datatype() function to return the
typecode and length of integer variables.
(adrian.wenl(a)gmail.com, anderson(a)redhat.com)
<cut>
So I made the patch to fix it.
--
--
Regards
Qiao Nuohan
11 years, 5 months
[ANNOUNCE] crash-6.1.5 is available
by Dave Anderson
Download from: http://people.redhat.com/anderson
Changelog:
- Fix for the ARM "irq" command. Without the patch, on 2.6.34 and
later kernels configured with CONFIG_SPARSE_IRQ, the command fails
with the error message "irq: cannot determine number of IRQs".
(Jan.Karlsson(a)sonymobile.com)
- Fix for a segmentation violation generated during invocation while
parsing a makedumpfile-created "flat-format" vmcore-incomplete file.
Without the patch, the crash session would display the error message
"crash: unable to seek dump file vmcore-incomplete", followed by a
segmentation violation.
(anderson(a)redhat.com)
- Fix for a segmentation violation generated by the "kmem -s" option
when encountering a corrupted array_cache structure that contains
a bogus "avail" count that is greater than the maximum legitimate
limit value. Without the patch, the "kmem -s" command would print
a warning message regarding the invalid array_cache, complete the
command normally, and then generate a segmentation violation when
freeing buffers used by the command.
(anderson(a)redhat.com)
- Update to the "kmem -s" function to include the errors found in slab
structures to the display of total errors found when the command
completes. Without the patch, invalid list_head pointers, bad
inuse counters, and bad s_mem pointers were not added to the total
number of errors found.
(anderson(a)redhat.com)
- Fix for "crash --osrelease <dumpfile>" and "crash --log <dumpfile>"
when run on an ARM compressed kdump with a crash binary that was built
with "make target=ARM" on an x86 or x86_64 host. Without the patch,
if the compressed kdump header version is 4 or 5, "crash --osrelease"
fails with the error message "crash: compressed kdump: cannot lseek
dump vmcoreinfo" followed by "unknown", and "crash --log" fails with
the error message "crash: <dumpfile>: no VMCOREINFO section".
(anderson(a)redhat.com)
- Enhancement to the "swap" command to display the swap_info_struct
address of each configured swap device. The output has been changed
to display the address in the first column, and the variable-length
device name has been moved to the last column.
(anderson(a)redhat.com)
- Fix for the "kmem -[sS]" options on kernels that configured with both
CONFIG_SLUB and CONFIG_NODES_SHIFT, and that are running on hardware
that generates NUMA nodes that contain no memory. Without the patch,
both command options fail immediately with the message "kmem: invalid
kernel virtual address: 8 type: kmem_cache_node nr_partial".
(anderson(a)redhat.com)
- Increment the PPC64 NR_CPUS maximum value from 1024 to 2048.
(anderson(a)redhat.com)
- Strip the ".isra." and ".part." appendages to cloned text symbol
names, which seem to have been introduced by gcc-4.6.0. To keep
them intact, a "--no_strip" command line option has been added.
(anderson(a)redhat.com)
- Patch to the internal gdb_get_datatype() function to return the
typecode and length of integer variables.
(adrian.wenl(a)gmail.com, anderson(a)redhat.com)
- Fix for the "dev -d" option on Linux 3.6 and later kernels. Without
the patch the option fails with the message "dev: invalid structure
member offset: request_queue_rq".
(holzheu(a)linux.vnet.ibm.com)
- Export the red/black tree utility functions rb_first(), rb_parent(),
rb_right(), rb_left(), rp_next() and rb_last(). Without the patch,
they are statically declared and only used by the "runq" command.
(qiaonuohan(a)cn.fujitsu.com)
- Implemented a new "timer -r" option that displays the hrtimer queues,
supporting all versions from Linux 2.6.16 to the present.
(qiaonuohan(a)cn.fujitsu.com, anderson(a)redhat.com)
- Fix for "kmem -s" on Linux 3.8 and later kernels that are configured
with CONFIG_SLAB. The kmem_cache.array[] length has been extended to
store the nodelist pointers, so the original method to determine the
per-cpu array limit can go out-of-range. Without the patch, during
session initialization there may be a message that indicates "crash:
invalid kernel virtual address: <address> type: array cache limit",
followed by "crash: unable to initialize kmem slab cache subsystem";
if those messages do get shown, then "kmem -s" will subsequently fail
during runtime with the message "kmem: kmem cache slab subsystem not
available".
(qiaonuohan(a)cn.fujitsu.com)
- Two Xen hypervisor fixes:
(1) Fix console buffer content length calculation:
Xen changeset 26447 (x86: re-introduce map_domain_page() et
al) once again altered virtual address space. The current
algorithm calculating its start could not cope with that
change. New version establishes this value on the base of
image start address and is more generic.
(2) Improve calculation of beginning of virtual address space:
Function displaying console buffer always assumes its content
length equal to console buffer size. This is not true and
sometimes it sends garbage to the screen. This patch fixes
this issue.
(daniel.kiper(a)oracle.com)
- Fix for the ARM "vtop" command when run on a module address. Without
the patch, the command fails with error message "vtop: ambiguous
address: <module-address> (requires -u or -k)".
(anderson(a)redhat.com)
- Add the "--active" command line option to the crash(8) man page
and to the "crash [-h|--help]" output.
(anderson(a)redhat.com)
- Add the "--buildinfo" command line option to the crash(8) man page
and to the "crash [-h|--help]" output.
(anderson(a)redhat.com)
- Remove the unadvertised and unnecessary "--data_debug" command line
option, given that it is the default setting.
(anderson(a)redhat.com)
- Remove the unadvertised and obsolete "--no_namelist_gzip" command
line option.
(anderson(a)redhat.com)
- Add the "-g [namelist]" command line option to the crash(8) man page
and to the "crash [-h|--help]" output.
(anderson(a)redhat.com)
- Remove the unadvertised and never-implemented "--shadow_page_tables"
command line option.
(anderson(a)redhat.com)
- Fix for the ARM "vtop" command when run on a user virtual address
of the panic task. Prior to Linux 3.3, the panic task's pgd gets
overwritten with a pgd that identity-maps the whole address space,
and therefore crash loses the capability of translating any user
virtual address into its original physical address.
(mika.westerberg(a)iki.fi)
- Fix to prevent the ARM linker mapping symbols "$d" and "$a" from
being added to the list of symbols from kernel modules. Without the
patch, the two symbols would only be rejected from the base kernel's
symbol list, but would be added to the symbol list of individual
kernel modules.
(mika.westerberg(a)iki.fi)
- Fix for the X86_64 "bt" command to recognize that the kernel was
built with CONFIG_FRAME_POINTER on Linux 3.7 and later kernels
that are configured with CONFIG_FUNCTION_TRACER. In those kernels,
the special 4-byte NOP instruction that can be overwritten during
runtime for dynamic ftracing has been moved to the very beginning
of each function, before the function preamble. Without the patch,
the test that checks the function preamble to determine whether
CONFIG_FRAME_POINTER was configured would fail, which could
potentially lead to less reliable backtraces.
(anderson(a)redhat.com)
11 years, 5 months
Question about crashkernel parameter on cmdline
by Li Haifeng
Hi, list.
I am running kexec-tools on ARM soc to dump vmcore file. In my case,
the crashkernel parameter of crash kernel 's cmdline is
"crashkernel=20M@10M". Then in bash of crash kernel, "echo c >
/proc/sysrq-trigger", and the capture kernel launches. But it will
fail on initializing /proc/vmcore. Because it trigger
"WARN_ON(pfn_valid(pfn))" in __arm_ioremap_pfn_caller()
@arch/arm/mm/ioremap.c.
I check the reason as follows.
#define pfn_valid(pfn) ((pfn) >= ARCH_PFN_OFFSET && ((pfn) -
ARCH_PFN_OFFSET) < max_mapnr)
To my case, pfn:x01d00, ARCH_PFN_OFFSET:0, max_mapnr:0x1300.
So pfn-ARCH_PFN_OFFSET is less than max_mapnr, and the
WARN_ON(pfn_valid(pfn)) is triggered on.
I want to know, to ignore this warning, whether I should comment this
WARN_ON() in kernel source code for my case.
And another doubt, will this warning corrupt my dumpfile? Because,
when I use the crash utility to analyse this vmcore, many errors
throw.
Any suggestion will be appreciate.
Thanks.
11 years, 5 months
A possible "dev -d" fix for newer kernels
by John Blackwood
I noticed that on newer kernels, the "dev -d" command is failing.
Seems like the 'rq' field in the request_queue structure is now
called 'root_rl'.
The little change in the patch below seems to fix this problem,
at least for me on i686 & x86_64. (I was using crash 6.1.4.)
crash> dev -d
MAJOR GENDISK NAME REQUEST QUEUE TOTAL ASYNC SYNC DRV
dev: invalid structure member offset: request_queue_rq
FILE: dev.c LINE: 3807 FUNCTION: get_diskio_1()
[/sbin/crash] error trace: 45dd17 => 4d6432 => 4d5eba => 4ff0fd
4ff0fd: OFFSET_verify+189
4d5eba: get_diskio_1+58
4d6432: display_all_diskio+1090
45dd17: exec_command+919
dev: invalid structure member offset: request_queue_rq
FILE: dev.c LINE: 3807 FUNCTION: get_diskio_1()
Index: b/dev.c
===================================================================
--- a/dev.c
+++ b/dev.c
@@ -4051,6 +4051,9 @@ void diskio_init(void)
MEMBER_OFFSET_INIT(request_queue_in_flight, "request_queue",
"in_flight");
MEMBER_OFFSET_INIT(request_queue_rq, "request_queue", "rq");
+ if (INVALID_MEMBER(request_queue_rq))
+ MEMBER_OFFSET_INIT(request_queue_rq,
+ "request_queue", "root_rl");
MEMBER_OFFSET_INIT(subsys_private_klist_devices, "subsys_private",
"klist_devices");
MEMBER_OFFSET_INIT(subsystem_kset, "subsystem", "kset");
11 years, 5 months
[PATCH] Add -m option to kmem
by Zhang Yanfei
kmem -m is used for displaying information of all ksm pages or
some ksm pages for specified ksm stable tree node addresses
The information includes:
- physical address of ksm page,
- pid of tasks using this ksm page,
- counts of ksm page references for each task
for example:
crash> kmem -m ffff8803573964c0
PID: 15864 16781
793005000: 8713 5584
ffff8803573964c0 is the address of ksm stable tree node.
task 15864 has 8713 virtual pages mapping the page with address 793005000.
task 16781 has 5584 virtual pages mapping the page with address 793005000.
P.S.
This patch is based on the patch from Qiao(qiaonuohan(a)cn.fujitsu.com)
0001-make-rbtree-manipulation-functions-global.patch
Because this patch also uses rb_tree operations.
Signed-off-by: Zhang Yanfei <zhangyanfei(a)cn.fujitsu.com>
---
defs.h | 6 ++
help.c | 19 +++++++-
memory.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
symbols.c | 12 +++++
4 files changed, 189 insertions(+), 8 deletions(-)
diff --git a/defs.h b/defs.h
index 2993f2b..f6996be 100755
--- a/defs.h
+++ b/defs.h
@@ -1848,6 +1848,12 @@ struct offset_table { /* stash of commonly-used offsets */
long vmap_area_list;
long vmap_area_flags;
long vmap_area_vm;
+ long stable_node_node;
+ long stable_node_hlist;
+ long stable_node_kpfn;
+ long rmap_item_mm;
+ long rmap_item_address;
+ long rmap_item_hlist;
};
struct size_table { /* stash of commonly-used sizes */
diff --git a/help.c b/help.c
index c542743..bb5b675 100755
--- a/help.c
+++ b/help.c
@@ -5148,7 +5148,7 @@ char *help_kmem[] = {
"kmem",
"kernel memory",
"[-f|-F|-p|-c|-C|-i|-s|-S|-v|-V|-n|-z-o] [slab] [[-P] address]\n"
-" [-g [flags]]",
+" [-g [flags] [-m [address]]",
" This command displays information about the use of kernel memory.\n",
" -f displays the contents of the system free memory headers.",
" also verifies that the page count equals nr_free_pages.",
@@ -5174,6 +5174,11 @@ char *help_kmem[] = {
" values to translate them into kernel virtual addresses.",
" -g displays the enumerator value of all bits in the page structure's",
" \"flags\" field.",
+" -m displays information of all ksm pages or some ksm pages for",
+" specified ksm stable tree node addresses. The information contains:",
+" physical address of ksm page",
+" pid of tasks using this ksm page",
+" counts of ksm page references for each task",
" flags when used with -g, translates all bits in this hexadecimal page",
" structure flags value into its enumerator values.",
" slab when used with -s or -S, limits the command to only the slab cache",
@@ -5204,7 +5209,10 @@ char *help_kmem[] = {
" the page address is displayed if it is contained with the list.",
" address when used with -v, the address can be a mapped kernel virtual",
" address or physical address; the mapped region containing the",
-" address is displayed.\n",
+" address is displayed.",
+" address when used with -m, the address should be a ksm stable tree node",
+" address; the information of the ksm page hanging off this node",
+" is displayed.\n",
" All address arguments above must be expressed in hexadecimal format.",
"\nEXAMPLES",
" Display memory usage information:\n",
@@ -5605,6 +5613,13 @@ char *help_kmem[] = {
" PG_slab 7 0000080",
" PG_head 14 0004000",
" %s>",
+"\n Display information of ksm pages:\n",
+" %s> kmem -m ffff88086f22eec0 ffff8803573964c0",
+" PID: 16781 ",
+" 75e6af000: 2 ",
+"",
+" PID: 15864 16781 ",
+" 793005000: 8713 5584 ",
NULL
};
diff --git a/memory.c b/memory.c
index 02a6de1..bd9146f 100755
--- a/memory.c
+++ b/memory.c
@@ -264,6 +264,7 @@ static int verify_pfn(ulong);
static void dump_per_cpu_offsets(void);
static void dump_page_flags(ulonglong);
static ulong kmem_cache_nodelists(ulong);
+static void dump_ksm(struct meminfo *);
/*
* Memory display modes specific to this file.
@@ -1012,6 +1013,16 @@ vm_init(void)
PG_reserved_flag_init();
PG_slab_flag_init();
+ if (STRUCT_EXISTS("stable_node")) {
+ MEMBER_OFFSET_INIT(stable_node_node, "stable_node", "node");
+ MEMBER_OFFSET_INIT(stable_node_hlist, "stable_node", "hlist");
+ MEMBER_OFFSET_INIT(stable_node_kpfn, "stable_node", "kpfn");
+ MEMBER_OFFSET_INIT(stable_node_node, "stable_node", "node");
+ MEMBER_OFFSET_INIT(rmap_item_mm, "rmap_item", "mm");
+ MEMBER_OFFSET_INIT(rmap_item_address, "rmap_item", "address");
+ ANON_MEMBER_OFFSET_INIT(rmap_item_hlist, "rmap_item", "hlist");
+ }
+
vt->flags |= VM_INIT;
}
@@ -4090,22 +4101,24 @@ cmd_kmem(void)
int i;
int c;
int sflag, Sflag, pflag, fflag, Fflag, vflag, zflag, oflag, gflag;
- int nflag, cflag, Cflag, iflag, lflag, Lflag, Pflag, Vflag;
+ int nflag, cflag, Cflag, iflag, lflag, Lflag, Pflag, Vflag, mflag;
struct meminfo meminfo;
ulonglong value[MAXARGS];
char buf[BUFSIZE];
char *p1;
int spec_addr, escape;
+ ulong ksm_pages_shared;
spec_addr = 0;
sflag = Sflag = pflag = fflag = Fflag = Pflag = zflag = oflag = 0;
vflag = Cflag = cflag = iflag = nflag = lflag = Lflag = Vflag = 0;
- gflag = 0;
+ gflag = mflag = 0;
escape = FALSE;
+ ksm_pages_shared = 0;
BZERO(&meminfo, sizeof(struct meminfo));
BZERO(&value[0], sizeof(ulonglong)*MAXARGS);
- while ((c = getopt(argcnt, args, "gI:sSFfpvczCinl:L:PVo")) != EOF) {
+ while ((c = getopt(argcnt, args, "gI:sSFfpvczCinl:L:PVom")) != EOF) {
switch(c)
{
case 'V':
@@ -4206,6 +4219,12 @@ cmd_kmem(void)
gflag = 1;
break;
+ case 'm':
+ if (INVALID_MEMBER(stable_node_node))
+ option_not_supported(c);
+ mflag = 1;
+ break;
+
default:
argerrs++;
break;
@@ -4216,7 +4235,8 @@ cmd_kmem(void)
cmd_usage(pc->curcmd, SYNOPSIS);
if ((sflag + Sflag + pflag + fflag + Fflag + Vflag + oflag +
- vflag + Cflag + cflag + iflag + lflag + Lflag + gflag) > 1) {
+ vflag + Cflag + cflag + iflag + lflag + Lflag + gflag +
+ mflag) > 1) {
error(INFO, "only one flag allowed!\n");
cmd_usage(pc->curcmd, SYNOPSIS);
}
@@ -4224,6 +4244,15 @@ cmd_kmem(void)
if (sflag || Sflag || !(vt->flags & KMEM_CACHE_INIT))
kmem_cache_init();
+ if (mflag) {
+ get_symbol_data("ksm_pages_shared", sizeof(ulong),
+ &ksm_pages_shared);
+ if (!ksm_pages_shared) {
+ fprintf(fp, "ksm may not be enabled\n");
+ return;
+ }
+ }
+
while (args[optind]) {
if (hexadecimal(args[optind], 0)) {
value[spec_addr++] =
@@ -4347,6 +4376,13 @@ cmd_kmem(void)
gflag++;
}
+ if (mflag) {
+ meminfo.spec_addr = value[i];
+ meminfo.flags = ADDRESS_SPECIFIED;
+ dump_ksm(&meminfo);
+ mflag++;
+ }
+
/*
* no value arguments allowed!
*/
@@ -4358,7 +4394,7 @@ cmd_kmem(void)
}
if (!(sflag + Sflag + pflag + fflag + vflag + cflag +
- lflag + Lflag + gflag)) {
+ lflag + Lflag + gflag + mflag)) {
meminfo.spec_addr = value[i];
meminfo.flags = ADDRESS_SPECIFIED;
if (meminfo.calls++)
@@ -4444,9 +4480,12 @@ cmd_kmem(void)
if (gflag == 1)
dump_page_flags(0);
+ if (mflag == 1)
+ dump_ksm(NULL);
+
if (!(sflag + Sflag + pflag + fflag + Fflag + vflag +
Vflag + zflag + oflag + cflag + Cflag + iflag +
- nflag + lflag + Lflag + gflag + meminfo.calls))
+ nflag + lflag + Lflag + gflag + mflag + meminfo.calls))
cmd_usage(pc->curcmd, SYNOPSIS);
}
@@ -15799,6 +15838,115 @@ dump_page_flags(ulonglong flags)
close_tmpfile();
}
+struct page_ref {
+ ulong mm;
+ ulong pid;
+ int ref;
+};
+
+/*
+ * dump_ksm() displays information of ksm pages.
+ */
+static void
+dump_ksm(struct meminfo *mi)
+{
+ ulong root_stable_tree, stable_node, kpfn;
+ ulong rmap_item, mm, paddr;
+ struct rb_root *root;
+ struct rb_node *node;
+ ulong first, next;
+ struct task_context *tc;
+ int i, ref_size, refs, found;
+ struct page_ref *ref;
+
+ if (!symbol_exists("root_stable_tree")) {
+ error(INFO, "cannot determine ksm stable tree address from root_stable_tree\n");
+ return;
+ }
+ root_stable_tree = symbol_value("root_stable_tree");
+ root = (struct rb_root *)root_stable_tree;
+
+ refs = 0;
+ ref_size = sizeof(struct page_ref) * RUNNING_TASKS();
+ ref = (struct page_ref *)GETBUF(ref_size);
+ BZERO(ref, ref_size);
+
+ found = mi ? 0 : -1;
+ for (node = rb_first(root); node; node = rb_next(node)) {
+ stable_node = (ulong) node - OFFSET(stable_node_node);
+ if (CRASHDEBUG(1))
+ fprintf(fp, " stable_node = %lx\n", stable_node);
+
+ readmem(stable_node + OFFSET(stable_node_hlist),
+ KVADDR, &first, sizeof(ulong),
+ "stable_node hlist", FAULT_ON_ERROR);
+
+ if (found == 0 && mi->spec_addr == stable_node)
+ found = 1;
+ if (found == 0)
+ continue;
+
+ readmem(stable_node + OFFSET(stable_node_kpfn),
+ KVADDR, &kpfn, sizeof(ulong),
+ "stable_node kpfn", FAULT_ON_ERROR);
+ paddr = kpfn << PAGE_SHIFT;
+
+ readmem(stable_node + OFFSET(stable_node_hlist),
+ KVADDR, &first, sizeof(ulong),
+ "stable_node hlist", FAULT_ON_ERROR);
+
+ next = first;
+ while (next) {
+ rmap_item = next - OFFSET(rmap_item_hlist);
+ readmem(rmap_item + OFFSET(rmap_item_mm),
+ KVADDR, &mm, sizeof(ulong),
+ "rmap_item mm", FAULT_ON_ERROR);
+
+ for (i = 0; i < refs; i++) {
+ if (ref[i].mm == mm) {
+ ref[i].ref += 1;
+ goto next;
+ }
+ }
+
+ tc = FIRST_CONTEXT();
+ for (i = 0; i < RUNNING_TASKS(); i++, tc++) {
+ if (tc->mm_struct == mm) {
+ ref[refs].mm = mm;
+ ref[refs].pid = tc->pid;
+ ref[refs++].ref = 1;
+ break;
+ }
+ }
+
+next:
+ readmem(next + OFFSET(hlist_node_next),
+ KVADDR, &next, sizeof(ulong),
+ "hlist_node next", FAULT_ON_ERROR);
+ };
+
+ if (refs)
+ fprintf(fp, " PID: ");
+ for (i = 0; i < refs; i++)
+ fprintf(fp, "%5ld ", ref[i].pid);
+ if (refs)
+ fprintf(fp, "\n%16lx: ", paddr);
+ for (i = 0; i < refs; i++)
+ fprintf(fp, "%5d ", ref[i].ref);
+ if (refs)
+ fprintf(fp, "\n\n");
+ refs = 0;
+
+ if (found == 1)
+ break;
+ }
+
+ if (found == 0)
+ fprintf(fp, "address 0x%llx cannot specify a stable node\n",
+ mi->spec_addr);
+
+ FREEBUF(ref);
+}
/*
* Support for slub.c slab cache.
diff --git a/symbols.c b/symbols.c
index 4fb397c..6c730ad 100755
--- a/symbols.c
+++ b/symbols.c
@@ -8860,6 +8860,18 @@ dump_offset_table(char *spec, ulong makestruct)
OFFSET(rt_rq_highest_prio));
fprintf(fp, " rt_rq_rt_nr_running: %ld\n",
OFFSET(rt_rq_rt_nr_running));
+ fprintf(fp, " stable_node_node: %ld\n",
+ OFFSET(stable_node_node));
+ fprintf(fp, " stable_node_hlist: %ld\n",
+ OFFSET(stable_node_hlist));
+ fprintf(fp, " stable_node_kpfn: %ld\n",
+ OFFSET(stable_node_kpfn));
+ fprintf(fp, " rmap_item_mm: %ld\n",
+ OFFSET(rmap_item_mm));
+ fprintf(fp, " rmap_item_address: %ld\n",
+ OFFSET(rmap_item_address));
+ fprintf(fp, " rmap_item_hlist: %ld\n",
+ OFFSET(rmap_item_hlist));
fprintf(fp, "\n size_table:\n");
fprintf(fp, " page: %ld\n", SIZE(page));
--
1.7.1
11 years, 5 months
Function parameters from stack frames
by Alexandr Terekhov
Hello,
I'm working now on task of obtaining function parameters from stack frames.
Can't say that it's really possible to get every parameter of every function,
but some of them are available.
My idea was the following: at start we have "reliable" register RSP, after that
I'm starting to parse frame:
push %rbp
mov %rsp,%rbp
push %r13
push %r12
push %rbx
hence we have rbx, r12, r13 "reliable" registers and so on.
At the end of frame we have the following:
mov %r13,%rcx
mov %rax,%rdx
mov %r12,%rsi
mov %rbx,%rdi
callq *%r8
Source is callee-save register, destination is parameter register. Then the next frame:
mov %rbx, -0x28(%rbp)
mov %r12, -0x20(%rbp)
mov %r13, -0x18(%rbp)
mov %r14, -0x10(%rbp)
and we have 3 of 4 parameters in stack. (RDI which is RBX, RSI which is R12, RCX which is R13).
I've already written this logic (and not only this - there are a lot of heuristics),
but I only have one single dump to test is. So I'd like to ask you all to provide some dumps
for testing (preferably RedHat kernels).
It would be great to get nested IRQs, different exceptions:
* double fault
* stack fault
that is something with stack switch (IST). This logic has not been written yet.
Thanks in advance.
Alexandr
11 years, 5 months
Re: [Crash-utility] Why module's global symbol cannot be displayed in crash? [ARM]
by Dave Anderson
----- Original Message -----
> After your fix, the module could show module address now.
> However I don't know whether this showing is correct or not...
> For while I want to check the module's defined global variant like
> below, I just find it is not being mapped yet...
> But this variant definition is very straightforward, like:
> int cctdev_major = 0;
>
>
> crash> sym cctdev_major
> bf16564d (B) cctdev_major
> crash> vtop -k bf16564d
> VIRTUAL PHYSICAL
> bf16564d (not mapped)
>
> PAGE DIRECTORY: c0004000
> PGD: c0006fc4 => 1f3cdc11
> PMD: c0006fc4 => 1f3cdc11
> PTE: 1f3cd594 => 0
>
> I don't know what is going wrong there, and I am planning to manually
> print out symbols' address before trigger the dump, and to see
> whether they could be aligned.
>
> Do you have some better idea how to fix it?...
No, not really, I'm not an ARM guy...
But it's possible/probable that the "vtop" translation on kernel module
virtual (vmalloc) addresses may not be working correctly. I also noted
yesterday that "vtop" on user-space virtual addresses fails pretty miserably
most of the time. Both arm_kvtop() and arm_uvtop() both end up calling the
common arm_vtop() function, so I'm guessing that it's the culprit.
Dave
11 years, 5 months
How to parse out kmem output?
by Lei Wen
Hi list,
I am current tracking one issue related with memory.
What I want to know if a kernel address which is alloced by kmalloc,
1. whether that address is already freed or not
2. if not freed, could I know which task or struct is owning that range?
I am also try to use the kmem command to get more info,
but I don't know the meaning for its output...
Like "CACHE"/"ALLOCATED"/"TOTAL"/"SLABS" member,
what are they referring to?
And according to "FREE / [ALLOCATED]" as below, does it
mean that 0xe1416acc already be freed?
crash> kmem -S 0xe1416acc
CACHE NAME OBJSIZE ALLOCATED TOTAL SLABS SSIZE
e0002400 kmalloc-2048 2048 156 160 10 32k
SLAB MEMORY NODE TOTAL ALLOCATED FREE
c1628200 e1410000 0 12 12 0
FREE / [ALLOCATED]
[e1410000]
[e1410800]
[e1411000]
[e1411800]
e1412000 (cpu 0 cache)
e1412800 (cpu 0 cache)
e1413000 (cpu 0 cache)
e1413800 (cpu 0 cache)
e1414000 (cpu 0 cache)
e1414800 (cpu 0 cache)
e1415000 (cpu 0 cache)
[e1415800]
crash>
Also seems current kmem only support SLAB, right?
If memory is allocated with like SLUB or SLOB, could the kmem
still handle it?
Thanks,
Lei
11 years, 5 months