panfy.fnst | 19 Aug 13:28 2014

improve ps performance

hello dave,
this patch for improving ps performance,when on RHEL 7 OS create 100k 
processes, the original ps command spends 51873.6s, after applying my 
patch, the time is reduced to 10.2s.

>From 0095be2c68b4154110b348ba5cbbe7dcb36c746d Mon Sep 17 00:00:00 2001
From: panfengyun <panfy.fnst <at> cn.fujitsu.com>
Date: Mon, 18 Aug 2014 14:59:43 +0800
Subject: [PATCH] improve ps performance

When a core file contains numerous tasks, especilly on RHEL 7, it will spend too
much time when using ps command to display tasks. The following three parts can
be modified to improve the performance.
    1. the task_mm() function and the is_kernel_thread() function have been
       called repeatedly.
    2. the task_to_pid() function and the task_to_context() function contains
       unnecessary cycle.
    3. at the get_task_mem_usage() function, repeated get the value of filepages
       and spend much time at FOR statement.

Please check the patch to see detailed information.

I test the patch on two OS, and the result is like below(using the following two
command to create processes):
    1. on RHEL 6, using "./test2.sh 10 10000" to create 100k processes, the
       original ps command spends 179.9s, after applying my patch, the time is
       reduced to 9.5s.
    2. on RHEL 7, using "./test2.sh 100 1000" to create 100k processes, the
(Continue reading)

qiaonuohan | 19 Aug 03:52 2014

ps: improve performance

Hello dave,

This patch is used to improve ps command performance, especilly on RHEL 7.
And the author is Pan Fengyun <panfy.fnst <at> cn.fujitsu.com>.

Please check.

-- 
Regards
Qiao Nuohan
>From 0095be2c68b4154110b348ba5cbbe7dcb36c746d Mon Sep 17 00:00:00 2001
From: panfengyun <panfy.fnst <at> cn.fujitsu.com>
Date: Mon, 18 Aug 2014 14:59:43 +0800
Subject: [PATCH] improve ps performance

When a core file contains numerous tasks, especilly on RHEL 7, it will spend too
much time when using ps command to display tasks. The following three parts can
be modified to improve the performance.
    1. the task_mm() function and the is_kernel_thread() function have been
       called repeatedly.
    2. the task_to_pid() function and the task_to_context() function contains
       unnecessary cycle.
    3. at the get_task_mem_usage() function, repeated get the value of filepages
       and spend much time at FOR statement.

Please check the patch to see detailed information.

I test the patch on two OS, and the result is like below(using the following two
(Continue reading)

Ku, Eugene | 29 Jul 18:10 2014

Debuginfo packages for Ubuntu 12.04

Hello,

 

I am working on a product that supports Ubuntu 12.04 LTS.  Ubuntu 12.04 LTS has delivered many different versions of Linux kernel.  In order to run crash to analyze crash dump from Ubuntu 12.04 LTS, we need a matching debugging Linux kernel module, vmlinux.  Do you know if there is repository for all released Ubuntu kernel debuginfo packages?  I have searched Ubunut and Debian web sites but could not find such a site.  The closest thing I have found is http://ddebs.ubuntu.com/pool/main/l/linux/; however it only has linux-image-3.2.0-* ddeb packages.  For Ubuntu 12.04 LTS it has delivered 3.2.0-*, 3.5.0-* and 3.8.0-* kernels.  These ddeb packages are also huge, more than 600MB each.  If there is a repository for vmlinux files only, that will be even better.

 

Please advise.  Thank you so much.

 

Eugene

<div>
<div class="WordSection1">
<p class="MsoNormal">Hello,<p></p></p>
<p class="MsoNormal"><p>&nbsp;</p></p>
<p class="MsoNormal">I am working on a product that supports Ubuntu 12.04 LTS.&nbsp; Ubuntu 12.04 LTS has delivered many different versions of Linux kernel.&nbsp; In order to run crash to analyze crash dump from Ubuntu 12.04 LTS, we need a matching debugging Linux kernel
 module, vmlinux.&nbsp; Do you know if there is repository for all released Ubuntu kernel debuginfo packages?&nbsp; I have searched Ubunut and Debian web sites but could not find such a site.&nbsp; The closest thing I have found is
<a href="http://ddebs.ubuntu.com/pool/main/l/linux/">http://ddebs.ubuntu.com/pool/main/l/linux/</a>; however it only has linux-image-3.2.0-* ddeb packages.&nbsp; For Ubuntu 12.04 LTS it has delivered 3.2.0-*, 3.5.0-* and 3.8.0-* kernels.&nbsp; These ddeb packages are
 also huge, more than 600MB each.&nbsp; If there is a repository for vmlinux files only, that will be even better.<p></p></p>
<p class="MsoNormal"><p>&nbsp;</p></p>
<p class="MsoNormal">Please advise.&nbsp; Thank you so much.<p></p></p>
<p class="MsoNormal"><p>&nbsp;</p></p>
<p class="MsoNormal">Eugene<p></p></p>
</div>
</div>
qiaonuohan | 22 Jul 11:26 2014

display slabs in cpu partial list for slub

Hello Dave,

Please check this patch. It is used for slub to display slabs in
kmem_cache_cpu.partial list.

I can only get it test on RHEL7.0GA right now. Would you please
help get some other test? Thanks a lot.

-- 
Regards
Qiao Nuohan
From f47f195e4c5e9d3b0e013f6f68b9f1e9d0cf58fa Mon Sep 17 00:00:00 2001
From: qiaonuohan <qiaonuohan <at> cn.fujitsu.com>
Date: Tue, 22 Jul 2014 05:18:53 -0400
Subject: [PATCH] display slabs in cpu partial list for slub

The following kernel commit adds per cpu partial list.

commit 49e2258586b423684f03c278149ab46d8f8b6700
Author: Christoph Lameter <cl <at> linux.com>
Date:   Tue Aug 9 16:12:27 2011 -0500

    slub: per cpu cache for partial pages

This patch is used for slub. It will display slabs in per cpu partial pages.
---
 defs.h   |  1 +
 memory.c | 51 +++++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 46 insertions(+), 6 deletions(-)

diff --git a/defs.h b/defs.h
index 44df6ae..1798d7b 100755
--- a/defs.h
+++ b/defs.h
 <at>  <at>  -1661,6 +1661,7  <at>  <at>  struct offset_table {                    /* stash of commonly-used offsets */
         long kmem_cache_cpu_freelist;
         long kmem_cache_cpu_page;
         long kmem_cache_cpu_node;
+	long kmem_cache_cpu_partial;
 	long kmem_cache_flags;
 	long zone_nr_active;
 	long zone_nr_inactive;
diff --git a/memory.c b/memory.c
index c97dd39..8a16426 100755
--- a/memory.c
+++ b/memory.c
 <at>  <at>  -271,6 +271,7  <at>  <at>  static long count_partial(ulong, struct meminfo *);
 static ulong get_freepointer(struct meminfo *, void *);
 static int count_free_objects(struct meminfo *, ulong);
 char *is_slab_page(struct meminfo *, char *);
+static void do_cpu_partial_slub(struct meminfo *, int);
 static void do_node_lists_slub(struct meminfo *, ulong, int);
 static int devmem_is_restricted(void);
 static int switch_to_proc_kcore(void);
 <at>  <at>  -392,6 +393,8  <at>  <at>  vm_init(void)
 	MEMBER_OFFSET_INIT(page_next, "page", "next");
 	if (VALID_MEMBER(page_next)) 
 		MEMBER_OFFSET_INIT(page_prev, "page", "prev");
+	if (INVALID_MEMBER(page_next))
+		ANON_MEMBER_OFFSET_INIT(page_next, "page", "next");

 	MEMBER_OFFSET_INIT(page_list, "page", "list");
 	if (VALID_MEMBER(page_list)) {
 <at>  <at>  -675,6 +678,7  <at>  <at>  vm_init(void)
 		MEMBER_OFFSET_INIT(kmem_cache_cpu_freelist, "kmem_cache_cpu", "freelist");
 		MEMBER_OFFSET_INIT(kmem_cache_cpu_page, "kmem_cache_cpu", "page");
 		MEMBER_OFFSET_INIT(kmem_cache_cpu_node, "kmem_cache_cpu", "node");
+		MEMBER_OFFSET_INIT(kmem_cache_cpu_partial, "kmem_cache_cpu", "partial");
 		ANON_MEMBER_OFFSET_INIT(page_inuse, "page", "inuse");
 		ANON_MEMBER_OFFSET_INIT(page_offset, "page", "offset");
 		ANON_MEMBER_OFFSET_INIT(page_slab, "page", "slab");
 <at>  <at>  -17324,6 +17328,34  <at>  <at>  bailout:
 	return FALSE;
 }

+static void
+do_cpu_partial_slub(struct meminfo *si, int cpu)
+{
+	ulong cpu_slab_ptr;
+	void *partial;
+
+	cpu_slab_ptr = ULONG(si->cache_buf + OFFSET(kmem_cache_cpu_slab)) +
+				kt->__per_cpu_offset[cpu];
+	readmem(cpu_slab_ptr + OFFSET(kmem_cache_cpu_partial), KVADDR,
+		&partial, sizeof(void *), "kmem_cache_cpu.partial",
+		RETURN_ON_ERROR);
+
+	fprintf(fp, "CPU %d PARTIAL:\n%s", cpu,
+		partial ? "" : "  (empty)\n");
+
+	/*
+	 * kmem_cache_cpu.partial points to the first page of per cpu partial
+	 * list.
+	 */ 
+	while (partial) {
+		si->slab = (ulong)partial;
+		do_slab_slub(si, VERBOSE);
+
+		readmem((ulong)partial + OFFSET(page_next), KVADDR, &partial,
+			sizeof(void *), "page.next", RETURN_ON_ERROR);
+
+	}
+}

 static void
 do_kmem_cache_slub(struct meminfo *si)  
 <at>  <at>  -17337,19 +17369,26  <at>  <at>  do_kmem_cache_slub(struct meminfo *si)
 	per_cpu = (ulong *)GETBUF(sizeof(ulong) * vt->numnodes);

         for (i = 0; i < kt->cpus; i++) {
+		cpu_slab_ptr = ULONG(si->cache_buf + OFFSET(kmem_cache_cpu_slab)) +
+				kt->__per_cpu_offset[i];
+		fprintf(fp, "KMEM_CACHE_CPU    CPU\n%lx%s%3d\n", cpu_slab_ptr,
+			space(VADDR_PRLEN > 8 ? 2 : 10), i);
+
 		cpu_slab_ptr = get_cpu_slab_ptr(si, i, NULL);

 		fprintf(fp, "CPU %d SLAB:\n%s", i, 
 			cpu_slab_ptr ? "" : "  (empty)\n");

-                if (!cpu_slab_ptr)
-                        continue;
+                if (cpu_slab_ptr) {
+                	if ((n = page_to_nid(cpu_slab_ptr)) >= 0)
+				per_cpu[n]++;

-                if ((n = page_to_nid(cpu_slab_ptr)) >= 0)
-			per_cpu[n]++;
+			si->slab = cpu_slab_ptr;
+			do_slab_slub(si, VERBOSE);
+		}

-		si->slab = cpu_slab_ptr;
-		do_slab_slub(si, VERBOSE);
+		if (VALID_MEMBER(kmem_cache_cpu_partial))
+			do_cpu_partial_slub(si, i);

 		if (received_SIGINT())
 			restart(0);
-- 
1.8.3.1

From f47f195e4c5e9d3b0e013f6f68b9f1e9d0cf58fa Mon Sep 17 00:00:00 2001
From: qiaonuohan <qiaonuohan <at> cn.fujitsu.com>
Date: Tue, 22 Jul 2014 05:18:53 -0400
Subject: [PATCH] display slabs in cpu partial list for slub

The following kernel commit adds per cpu partial list.

commit 49e2258586b423684f03c278149ab46d8f8b6700
Author: Christoph Lameter <cl <at> linux.com>
Date:   Tue Aug 9 16:12:27 2011 -0500

    slub: per cpu cache for partial pages

This patch is used for slub. It will display slabs in per cpu partial pages.
---
 defs.h   |  1 +
 memory.c | 51 +++++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 46 insertions(+), 6 deletions(-)

diff --git a/defs.h b/defs.h
index 44df6ae..1798d7b 100755
--- a/defs.h
+++ b/defs.h
 <at>  <at>  -1661,6 +1661,7  <at>  <at>  struct offset_table {                    /* stash of commonly-used offsets */
         long kmem_cache_cpu_freelist;
         long kmem_cache_cpu_page;
         long kmem_cache_cpu_node;
+	long kmem_cache_cpu_partial;
 	long kmem_cache_flags;
 	long zone_nr_active;
 	long zone_nr_inactive;
diff --git a/memory.c b/memory.c
index c97dd39..8a16426 100755
--- a/memory.c
+++ b/memory.c
 <at>  <at>  -271,6 +271,7  <at>  <at>  static long count_partial(ulong, struct meminfo *);
 static ulong get_freepointer(struct meminfo *, void *);
 static int count_free_objects(struct meminfo *, ulong);
 char *is_slab_page(struct meminfo *, char *);
+static void do_cpu_partial_slub(struct meminfo *, int);
 static void do_node_lists_slub(struct meminfo *, ulong, int);
 static int devmem_is_restricted(void);
 static int switch_to_proc_kcore(void);
 <at>  <at>  -392,6 +393,8  <at>  <at>  vm_init(void)
 	MEMBER_OFFSET_INIT(page_next, "page", "next");
 	if (VALID_MEMBER(page_next)) 
 		MEMBER_OFFSET_INIT(page_prev, "page", "prev");
+	if (INVALID_MEMBER(page_next))
+		ANON_MEMBER_OFFSET_INIT(page_next, "page", "next");

 	MEMBER_OFFSET_INIT(page_list, "page", "list");
 	if (VALID_MEMBER(page_list)) {
 <at>  <at>  -675,6 +678,7  <at>  <at>  vm_init(void)
 		MEMBER_OFFSET_INIT(kmem_cache_cpu_freelist, "kmem_cache_cpu", "freelist");
 		MEMBER_OFFSET_INIT(kmem_cache_cpu_page, "kmem_cache_cpu", "page");
 		MEMBER_OFFSET_INIT(kmem_cache_cpu_node, "kmem_cache_cpu", "node");
+		MEMBER_OFFSET_INIT(kmem_cache_cpu_partial, "kmem_cache_cpu", "partial");
 		ANON_MEMBER_OFFSET_INIT(page_inuse, "page", "inuse");
 		ANON_MEMBER_OFFSET_INIT(page_offset, "page", "offset");
 		ANON_MEMBER_OFFSET_INIT(page_slab, "page", "slab");
 <at>  <at>  -17324,6 +17328,34  <at>  <at>  bailout:
 	return FALSE;
 }

+static void
+do_cpu_partial_slub(struct meminfo *si, int cpu)
+{
+	ulong cpu_slab_ptr;
+	void *partial;
+
+	cpu_slab_ptr = ULONG(si->cache_buf + OFFSET(kmem_cache_cpu_slab)) +
+				kt->__per_cpu_offset[cpu];
+	readmem(cpu_slab_ptr + OFFSET(kmem_cache_cpu_partial), KVADDR,
+		&partial, sizeof(void *), "kmem_cache_cpu.partial",
+		RETURN_ON_ERROR);
+
+	fprintf(fp, "CPU %d PARTIAL:\n%s", cpu,
+		partial ? "" : "  (empty)\n");
+
+	/*
+	 * kmem_cache_cpu.partial points to the first page of per cpu partial
+	 * list.
+	 */ 
+	while (partial) {
+		si->slab = (ulong)partial;
+		do_slab_slub(si, VERBOSE);
+
+		readmem((ulong)partial + OFFSET(page_next), KVADDR, &partial,
+			sizeof(void *), "page.next", RETURN_ON_ERROR);
+
+	}
+}

 static void
 do_kmem_cache_slub(struct meminfo *si)  
 <at>  <at>  -17337,19 +17369,26  <at>  <at>  do_kmem_cache_slub(struct meminfo *si)
 	per_cpu = (ulong *)GETBUF(sizeof(ulong) * vt->numnodes);

         for (i = 0; i < kt->cpus; i++) {
+		cpu_slab_ptr = ULONG(si->cache_buf + OFFSET(kmem_cache_cpu_slab)) +
+				kt->__per_cpu_offset[i];
+		fprintf(fp, "KMEM_CACHE_CPU    CPU\n%lx%s%3d\n", cpu_slab_ptr,
+			space(VADDR_PRLEN > 8 ? 2 : 10), i);
+
 		cpu_slab_ptr = get_cpu_slab_ptr(si, i, NULL);

 		fprintf(fp, "CPU %d SLAB:\n%s", i, 
 			cpu_slab_ptr ? "" : "  (empty)\n");

-                if (!cpu_slab_ptr)
-                        continue;
+                if (cpu_slab_ptr) {
+                	if ((n = page_to_nid(cpu_slab_ptr)) >= 0)
+				per_cpu[n]++;

-                if ((n = page_to_nid(cpu_slab_ptr)) >= 0)
-			per_cpu[n]++;
+			si->slab = cpu_slab_ptr;
+			do_slab_slub(si, VERBOSE);
+		}

-		si->slab = cpu_slab_ptr;
-		do_slab_slub(si, VERBOSE);
+		if (VALID_MEMBER(kmem_cache_cpu_partial))
+			do_cpu_partial_slub(si, i);

 		if (received_SIGINT())
 			restart(0);
--

-- 
1.8.3.1

Dave Anderson | 17 Jul 18:04 2014
Picon

[PATCH] crash-gcore-command extension module: ARM64 support


Hello Daisuke,

Attached is a patch to introduce support for the ARM64 architecture
for the gcore extension module.   

The patch is fairly straight-forward other than the fact that on
ARM64 machines, the chain of headers included from the crash utility's
"defs.h" looks like this:

  /usr/include/crash/defs.h 
    /usr/include/signal.h 
      /usr/include/sys/ucontext.h 
        /usr/include/sys/procfs.h 

The <sys/procfs.h> file defines several of the ELF-related structures that
are hard-coded in gcore_defs.h, causing compile failures due to duplicate 
structure declarations.

Note that the <sys/ucontext.h> file on the other three architectures does 
not #include <sys/procfs.h> so there are no conflicts.  It would be possible
to move all architectures to include <sys/procfs.h>, but for example, that 
would also bring in the <sys/user.h> definition of the user_regs_struct,
which in turn causes a myriad of register name mismatches in gcore_x86.c.
So for the sake of simplicity, wherever there is an ARM64-only duplicate
structure or definition in gcore_defs.h, I've encapsulated them by:

  #if defined(X86) || defined(X86_64) || defined(ARM)

Also, there are two generic fixes, one where the gcore module fails on
Linux 3.11 and later kernels due to a structure member name change,
and another that changes the getopt() return variable to an "int" instead
of a "char".

Here are the details:

  gcore.mk:

    - Introduce ARM64 as a supported architecture
    - Add libgcore/gcore_arm64 to GCORE_CFILES

  gcore.c:

    - In cmd_gcore() change "c" type to "int" to correctly match
      the return type of getopt(); without it, the while loop
      spins indefinitely on ARM64.
    - In gcore_offset_table_init(), account for the Linux 3.11 
      structure member name-change from ns_proxy.pid_ns to 
      ns_proxy.pid_ns_for_children; without it, the gcore command
      fails during initialization.

  libgcore/gcore_defs.h:

    - Add ARM64 ELF- and REGSET_VIEW-related #defines required for
      each architecture.
    - Account for variable page sizes in ARM64.
    - Restrict the hard-coded ELF_NGREG, elf_siginfo, elf_prstatus, 
      __kernel_old_uid_t and __kernel_old_gid_t, and elf_prsinfo 
      definitions to X86, X86_64 and ARM architectures.
    - Add ARM64 thread_struct_fpsmid_state and thread_struct_tp_value
      offsets to gcore_offset_table.

  libgcore/gcore_coredump.c:

    - In fill_prstatus_note(), account for the ARM64 usage of 
      "user_pt_regs" structure instead of the "user_regs_struct" 
      used by the other architectures.

  libgcore/gcore_arm64.c:

    - Implement ARM64-specific user_regset and user_regset_view
      structures and all required support functions.

Please accept these changes into an new package version.

Thanks,
  Dave
  
Attachment (gcore_arm64.patch): text/x-patch, 12 KiB

Hello Daisuke,

Attached is a patch to introduce support for the ARM64 architecture
for the gcore extension module.   

The patch is fairly straight-forward other than the fact that on
ARM64 machines, the chain of headers included from the crash utility's
"defs.h" looks like this:

  /usr/include/crash/defs.h 
    /usr/include/signal.h 
      /usr/include/sys/ucontext.h 
        /usr/include/sys/procfs.h 

The <sys/procfs.h> file defines several of the ELF-related structures that
are hard-coded in gcore_defs.h, causing compile failures due to duplicate 
structure declarations.

Note that the <sys/ucontext.h> file on the other three architectures does 
not #include <sys/procfs.h> so there are no conflicts.  It would be possible
to move all architectures to include <sys/procfs.h>, but for example, that 
would also bring in the <sys/user.h> definition of the user_regs_struct,
which in turn causes a myriad of register name mismatches in gcore_x86.c.
So for the sake of simplicity, wherever there is an ARM64-only duplicate
structure or definition in gcore_defs.h, I've encapsulated them by:

  #if defined(X86) || defined(X86_64) || defined(ARM)

Also, there are two generic fixes, one where the gcore module fails on
Linux 3.11 and later kernels due to a structure member name change,
and another that changes the getopt() return variable to an "int" instead
of a "char".

Here are the details:

  gcore.mk:

    - Introduce ARM64 as a supported architecture
    - Add libgcore/gcore_arm64 to GCORE_CFILES

  gcore.c:

    - In cmd_gcore() change "c" type to "int" to correctly match
      the return type of getopt(); without it, the while loop
      spins indefinitely on ARM64.
    - In gcore_offset_table_init(), account for the Linux 3.11 
      structure member name-change from ns_proxy.pid_ns to 
      ns_proxy.pid_ns_for_children; without it, the gcore command
      fails during initialization.

  libgcore/gcore_defs.h:

    - Add ARM64 ELF- and REGSET_VIEW-related #defines required for
      each architecture.
    - Account for variable page sizes in ARM64.
    - Restrict the hard-coded ELF_NGREG, elf_siginfo, elf_prstatus, 
      __kernel_old_uid_t and __kernel_old_gid_t, and elf_prsinfo 
      definitions to X86, X86_64 and ARM architectures.
    - Add ARM64 thread_struct_fpsmid_state and thread_struct_tp_value
      offsets to gcore_offset_table.

  libgcore/gcore_coredump.c:

    - In fill_prstatus_note(), account for the ARM64 usage of 
      "user_pt_regs" structure instead of the "user_regs_struct" 
      used by the other architectures.

  libgcore/gcore_arm64.c:

    - Implement ARM64-specific user_regset and user_regset_view
      structures and all required support functions.

Please accept these changes into an new package version.

Thanks,
  Dave
  
Buland Kumar Singh | 9 Jul 21:03 2014
Picon

Negative NR_WRITEBACK counter

Hello Everyone,

I am analysing a kernel crash dump (vmcore) captured from RHEL-5
kernel version (2.6.18-371.4.1.el5) and found that the value of
"NR_WRITEBACK" counter is negative (-126).

$ rpm -q crash
crash-7.0.6-2.el6.x86_64

crash> sys | grep -e RELEASE -e MACHINE -e MEMORY
     RELEASE: 2.6.18-371.4.1.el5
     MACHINE: x86_64  (3000 Mhz)
      MEMORY: 31.5 GB

crash> kmem -z | grep  -e ZONE -e NR_WRITEBACK
NODE: 0  ZONE: 0  ADDR: ffff810000032000  NAME: "DMA"
       NR_WRITEBACK: 0
NODE: 0  ZONE: 1  ADDR: ffff810000032b00  NAME: "DMA32"
       NR_WRITEBACK: 0
NODE: 0  ZONE: 2  ADDR: ffff810000033600  NAME: "Normal"
       NR_WRITEBACK: -126          <<<<
NODE: 0  ZONE: 3  ADDR: ffff810000034100  NAME: "HighMem"

crash> kmem -V | grep -e NR_WRITEBACK
       NR_WRITEBACK: -126          <<<<

crash> vm_stat
vm_stat = $1 =
 {{
    counter = 1106459
  }, {
    counter = 2940354
  }, {
    counter = 6341366
  }, {
    counter = 301750
  }, {
    counter = 245858
  }, {
    counter = 438
  }, {
    counter = -126  // NR_WRITEBACK <<<<
  }, {
    counter = 0
  }, {
    counter = 0
  }, {
    counter = 19687071384
  }, {
    counter = 0
  }, {
    counter = 0
  }, {
    counter = 29247123
  }, {
    counter = 19687071384
  }, {
    counter = 0
  }}

As we're running a 64 bit kernel and the counters are signed long,
so this is very unlikely to be a counter overflow. I need pointers
and suggestions to determine the *cause* of negative counter from
vmcore.

Additional Information:

$ git show ce866b34ae1b7f1ce60234cf65855886ac7e7d30
[..]
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 6fed520..a7b3dcb 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
<at> <at> -49,9 +49,6 <at> <at> static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
        get_page_state_node(&ps, nid);
        __get_zone_counts(&active, &inactive, &free, NODE_DATA(nid));
 
-       /* Check for negative values in these approximate counters */
-       if ((long)ps.nr_writeback < 0)
-               ps.nr_writeback = 0;
 
        n = sprintf(buf, "\n"
                       "Node %d MemTotal:     %8lu kB\n"
[..]

Thank you !

--
BKS
<div><div dir="ltr"><span>Hello Everyone,<br><br>I am analysing a kernel crash dump (vmcore) captured from RHEL-5<br>kernel version (2.6.18-371.4.1.el5) and found that the value of<br>
"NR_WRITEBACK" counter is negative (-126).<br><br>$ rpm -q crash<br>crash-7.0.6-2.el6.x86_64<br><br>crash&gt; sys | grep -e RELEASE -e MACHINE -e MEMORY<br>&nbsp; &nbsp; &nbsp;RELEASE: 2.6.18-371.4.1.el5<br>&nbsp; &nbsp; &nbsp;MACHINE: x86_64 &nbsp;(3000 Mhz)<br>
&nbsp; &nbsp; &nbsp; MEMORY: 31.5 GB<br><br>crash&gt; kmem -z | grep &nbsp;-e ZONE -e NR_WRITEBACK<br>NODE: 0 &nbsp;ZONE: 0 &nbsp;ADDR: ffff810000032000 &nbsp;NAME: "DMA"<br>&nbsp; &nbsp; &nbsp; &nbsp;NR_WRITEBACK: 0<br>NODE: 0 &nbsp;ZONE: 1 &nbsp;ADDR: ffff810000032b00 &nbsp;NAME: "DMA32"<br>
&nbsp; &nbsp; &nbsp; &nbsp;NR_WRITEBACK: 0<br>NODE: 0 &nbsp;ZONE: 2 &nbsp;ADDR: ffff810000033600 &nbsp;NAME: "Normal"<br>&nbsp; &nbsp; &nbsp; &nbsp;NR_WRITEBACK: -126 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;&lt;&lt;&lt;<br>NODE: 0 &nbsp;ZONE: 3 &nbsp;ADDR: ffff810000034100 &nbsp;NAME: "HighMem"<br><br>crash&gt; kmem -V | grep -e NR_WRITEBACK<br>&nbsp; &nbsp; &nbsp; &nbsp;NR_WRITEBACK: -126 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;&lt;&lt;&lt;<br><br>crash&gt; vm_stat<br>vm_stat = $1 =<br>&nbsp;{{<br>&nbsp; &nbsp; counter = 1106459<br>&nbsp; }, {<br>&nbsp; &nbsp; counter = 2940354<br>&nbsp; }, {<br>
&nbsp; &nbsp; counter = 6341366<br>&nbsp; }, {<br>&nbsp; &nbsp; counter = 301750<br>&nbsp; }, {<br>&nbsp; &nbsp; counter = 245858<br>&nbsp; }, {<br>&nbsp; &nbsp; counter = 438<br>&nbsp; }, {<br>&nbsp; &nbsp; counter = -126 &nbsp;// NR_WRITEBACK &lt;&lt;&lt;&lt;<br>&nbsp; }, {<br>&nbsp; &nbsp; counter = 0<br>&nbsp; }, {<br>
&nbsp; &nbsp; counter = 0<br>&nbsp; }, {<br>&nbsp; &nbsp; counter = 19687071384<br>&nbsp; }, {<br>&nbsp; &nbsp; counter = 0<br>&nbsp; }, {<br>&nbsp; &nbsp; counter = 0<br>&nbsp; }, {<br>&nbsp; &nbsp; counter = 29247123<br>&nbsp; }, {<br>&nbsp; &nbsp; counter = 19687071384<br>&nbsp; }, {<br>&nbsp; &nbsp; counter = 0<br>&nbsp; }}<br><br>As we're running a 64 bit kernel and the counters are signed long,<br>so this is very unlikely to be a counter overflow. I need pointers<br>and suggestions to determine the *cause* of negative counter from<br>vmcore.<br><br>Additional Information:<br><br>$ git show ce866b34ae1b7f1ce60234cf65855886ac7e7d30<br>[..]<br>diff --git a/drivers/base/node.c b/drivers/base/node.c<br>index 6fed520..a7b3dcb 100644<br>--- a/drivers/base/node.c<br>+++ b/drivers/base/node.c<br>
 <at>  <at>  -49,9 +49,6  <at>  <at>  static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)<br>&nbsp; &nbsp; &nbsp; &nbsp; get_page_state_node(&amp;ps, nid);<br>&nbsp; &nbsp; &nbsp; &nbsp; __get_zone_counts(&amp;active, &amp;inactive, &amp;free, NODE_DATA(nid));<br>
&nbsp;<br>- &nbsp; &nbsp; &nbsp; /* Check for negative values in these approximate counters */<br>- &nbsp; &nbsp; &nbsp; if ((long)ps.nr_writeback &lt; 0)<br>- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ps.nr_writeback = 0;<br>&nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; n = sprintf(buf, "\n"<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;"Node %d MemTotal: &nbsp; &nbsp; %8lu kB\n"<br>
[..]<br><br>Thank you !<span class="sew1hz9tqnvigwn"></span><span class="sew1hz9tqnvigwn"></span><br><br>-- <br>BKS</span></div></div>
Karlsson, Jan | 4 Jul 11:37 2014

Re: crash-utility <at> redhat.com, anderson <at> redhat.com

Hi

I have not seen anything like this before, so I cannot really help you with the problem. You should however be
aware the in this case Crash is built as a 32-bit executable and must be built in that way to work properly. So
you should look for missing 32-bit libraries.

Jan

Jan Karlsson
Senior Software Engineer
System Assurance

Sony Mobile Communications
Tel: +46 703 062 174
jan.karlsson <at> sonymobile.com

sonymobile.com

-----Original Message-----
From: Yu Chen [mailto:chenyu105 <at> gmail.com] 
Sent: den 4 juli 2014 06:40
To: ext-mika.1.westerberg <at> nokia.com; Karlsson, Jan; Fänge, Thomas
Subject: crash-utility <at> redhat.com, anderson <at> redhat.com

Hi all!
I am trying to compile crash-7.0.7  on x86_64 host  for arm.
(x86 binary to analyze ARM dumpfiles)
Here's the failure information:

-bash-4.1$ make target=arm
TARGET: ARM
 CRASH: 7.0.7
   GDB: 7.6
...
checking for gcc... gcc
checking for C compiler default output file name... a.out checking whether the C compiler works... yes
checking whether we are cross compiling... no checking for objcopy... objcopy checking for objdump...
objdump checking for readelf... readelf checking for arm-elf-linux-cc... no checking for
arm-elf-linux-gcc... no checking for arm-elf-linux-c++... no checking for arm-elf-linux-g++... no
checking for arm-elf-linux-cxx... no checking for arm-elf-linux-gxx... no checking for
arm-elf-linux-gcc... no checking for arm-elf-linux-gcj... no

...
checking for library containing waddstr... no
configure: WARNING: no enhanced curses library found; disabling TUI checking for library containing
tgetent... no
configure: error: no termcap library found
make[3]: *** [configure-gdb] Error 1
make[2]: *** [all] Error 2

crash build failed

make[1]: *** [gdb_merge] Error 1
make: *** [all] Error 2

I thought the reason for  above error  message was due to lack of  termcap library. However, the termcap
library could be found on my host machine:

-bash-4.1$ find . -name "*termcap*"
./libtermcap.so.2
./libtermcap.so.2.0.8
-bash-4.1$ pwd
/lib64
-bash-4.1$ uname -a
Linux localhost.localdomain 2.6.32-220.el6.x86_64 #1 SMP Mon Sep 3
07:34:44 EDT 2012 x86_64 x86_64 x86_64 GNU/Linux

After I copyed x86_64 libtermcap.a into /lib64 ,the error message still exist.

I am confused if crash should be cross compiled in this situation?
Or is there any step I  should take before compile crash?

Many  thanks !

--
Crash-utility mailing list
Crash-utility <at> redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
Dave Anderson | 19 Jun 19:51 2014
Picon

ARM64 support for EPPIC


Hi Luc,

I posted the attached patch as an issue on your code.google.com eppic page.
It allows the eppic.so module to be built, loaded, and run scripts (at least
very simple ones).  I'm presuming that there's no other arch-specific stuff
that needs to be done.

Thanks,
  Dave

qiaonuohan | 13 Jun 13:14 2014

ksm: fix ksm module for RHEL6.5 and later

Hello Dave,

Please check the patch.

-- 
Regards
Qiao Nuohan
From 3d313aaf5d9fedd91e81ac596fe407614dd57de1 Mon Sep 17 00:00:00 2001
From: Qiao Nuohan <qiaonuohan <at> cn.fujitsu.com>
Date: Wed, 11 Jun 2014 10:01:21 +0800
Subject: [PATCH] Fix ksm.c

Because of the following kernel patch, 'root_stable_tree' and 
'struct stable_node' are changed. 

<cut>
ef53d16cded7f89b3843b7a96970dab897843ea5
90bd6fd31c8097ee4ddcb74b7e08363134863de5
4146d2d673e8d6abf9b30a5b5dd8cd95f29632eb
<cut>

Another two change are listed below.

1. add mm_struct's address for the task.
ksm displayed ksm page's messages like below
<cut>
            PAGE: ffffea000451f180
     STABLE_NODE: ffff88004866b6c0
PHYSICAL ADDRESS: 1147c6000
             PID: 1318  MAPPINGS: 7707
             PID: 1297  MAPPINGS: 4965

<cut>

Now, MM item is added to show the mm_struct's address related to task, like
below
<cut>
            PAGE: ffffea000451f180
     STABLE_NODE: ffff88004866b6c0
PHYSICAL ADDRESS: 1147c6000
             PID: 1318  MAPPINGS: 7707  MM: ffff88007f8abe80
             PID: 1297  MAPPINGS: 4965  MM: ffff88007f8aa580

<cut>

2. the task that uses ksm pages may have exited. this patch will change to
show the exited task's "MAPPINGS" and "MM" like below
<cut>
            PAGE: ffffea000292ca40
     STABLE_NODE: ffff88009fe8e9c0
PHYSICAL ADDRESS: a4b29000
             PID: -  MAPPINGS: 1  MM: ffff880115f28000
             PID: -  MAPPINGS: 1  MM: ffff8800cdd7a580
<cut>
task has exited, so PID is "-"

Signed-off-by: Qiao Nuohan <qiaonuohan <at> cn.fujitsu.com>
---
 extensions/ksm.c | 289 ++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 192 insertions(+), 97 deletions(-)

diff --git a/extensions/ksm.c b/extensions/ksm.c
index ce02318..ef97c92 100644
--- a/extensions/ksm.c
+++ b/extensions/ksm.c
 <at>  <at>  -1,6 +1,7  <at>  <at> 
 /*
- * Copyright (C) 2013 FUJITSU LIMITED
+ * Copyright (C) 2013-2014 FUJITSU LIMITED
  * Author: Zhang Yanfei <zhangyanfei <at> cn.fujitsu.com>
+ * Signed-off-by: Qiao Nuohan <qiaonuohan <at> cn.fujitsu.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 <at>  <at>  -22,7 +23,7  <at>  <at>  void cmd_ksm(void);
 char *help_ksm[];

 static struct command_table_entry command_table[] = {
-        { "ksm", cmd_ksm, help_ksm, 0},          
+        { "ksm", cmd_ksm, help_ksm, 0},
         { NULL },
 };

 <at>  <at>  -35,7 +36,8  <at>  <at>  struct ksm_offset_table {
 	long rmap_item_hlist;
 } ksm_offset_table;

-#define KSM_ASSIGN_OFFSET(X)   (ksm_offset_table.X)
+#define KSM_ASSIGN_OFFSET(X) (ksm_offset_table.X)
+#define KSM_INVALID_MEMBER(X) (ksm_offset_table.X == INVALID_OFFSET)
 #define KSM_MEMBER_OFFSET_INIT(X, Y, Z) (KSM_ASSIGN_OFFSET(X) = MEMBER_OFFSET(Y, Z))
 #define KSM_ANON_MEMBER_OFFSET_INIT(X, Y, Z) (KSM_ASSIGN_OFFSET(X) = ANON_MEMBER_OFFSET(Y, Z))
 #define KSM_OFFSET(X)  (OFFSET_verify(ksm_offset_table.X, (char *)__FUNCTION__, __FILE__,
__LINE__, #X))
 <at>  <at>  -50,27 +52,30  <at>  <at>  struct page_ref {
         ulong mm;
         ulong pid;
         int ref;
+	struct page_ref *next;
 };

 static void dump_ksm(struct meminfo *);

 void __attribute__((constructor))
 ksm_init(void) /* Register the command set. */
-{ 
+{
 	if (STRUCT_EXISTS("stable_node")) {
 		KSM_MEMBER_OFFSET_INIT(stable_node_node, "stable_node", "node");
+		if (KSM_INVALID_MEMBER(stable_node_node))
+			KSM_ANON_MEMBER_OFFSET_INIT(stable_node_node, "stable_node", "node");
+
 		KSM_MEMBER_OFFSET_INIT(stable_node_hlist, "stable_node", "hlist");
 		KSM_MEMBER_OFFSET_INIT(stable_node_kpfn, "stable_node", "kpfn");
-		KSM_MEMBER_OFFSET_INIT(stable_node_node, "stable_node", "node");
 		KSM_MEMBER_OFFSET_INIT(rmap_item_mm, "rmap_item", "mm");
 		KSM_MEMBER_OFFSET_INIT(rmap_item_address, "rmap_item", "address");
 		KSM_ANON_MEMBER_OFFSET_INIT(rmap_item_hlist, "rmap_item", "hlist");
 	} else
-		error(FATAL, "ksm_init: stable_node does not exist\n"); 
+		error(FATAL, "ksm_init: stable_node does not exist\n");

        	register_extension(command_table);
 }
- 
+
 void __attribute__((destructor))
 ksm_fini(void) { }

 <at>  <at>  -139,15 +144,17  <at>  <at>  cmd_ksm(void)
 }

 char *help_ksm[] = {
-        "ksm", 
+        "ksm",
         "kernel samepage merging (KSM) information",
-        "[-v] [[-p] address ...]",                   
- 
+        "[-v] [[-p] address ...]",
+
         "  This command displays information about all KSM pages currently",
         "  in use.  For each KSM page, the display includes its stable_node",
-        "  address, its page struct address, its physical address, the TGID/PID", 
-        "  for each task that is using the page, and the number of mappings in",
-        "  the task's address space for the page.",
+        "  address, its page struct address, its physical address, the TGID/PID",
+        "  for each task that is using the page, the number of mappings in the",
+        "  task's address space for the page, and the mm_struct address of the",
+        "  task. If pid is '-', the task has exited and the ksm page has not",
+        "  been removed.",
         " ",
         "       -v  also dump each virtual address in a PID's virtual address",
         "           space that maps the KSM page.",
 <at>  <at>  -159,88 +166,129  <at>  <at>  char *help_ksm[] = {
         "\nEXAMPLE",
         "  Display information about all KSM pages:\n",
         "    %s> ksm",
-//      "    STABLE_NODE     : ffff8806248c2d80",
-//      "    PAGE            : ffffea000ae7f6a8",
-//      "    PHYSICAL ADDRESS: 31db43000",
-        "                PAGE: ffffea000ae7f6a8",
-        "         STABLE_NODE: ffff8806248c2d80",
-        "    PHYSICAL ADDRESS: 31db43000",
-        "                 PID: 2205  MAPPINGS: 2",
+        "                PAGE: ffffea000451f180",
+        "         STABLE_NODE: ffff88004866b6c0",
+        "    PHYSICAL ADDRESS: 1147c6000",
+        "                 PID: 1318  MAPPINGS: 7707  MM: ffff88007f8abe80",
+        "                 PID: 1297  MAPPINGS: 4965  MM: ffff88007f8aa580",
         "",
-//      "    STABLE_NODE     : ffff880624aa57b8",
-//      "    PAGE            : ffffea000ae800f0",
-//      "    PHYSICAL ADDRESS: 31db72000",
-        "                PAGE: ffffea000ae800f0",
-        "         STABLE_NODE: ffff880624aa57b8",
-        "    PHYSICAL ADDRESS: 31db72000",
-        "                 PID: 2205  MAPPINGS: 2",
+        "                PAGE: ffffea0003413c40",
+        "         STABLE_NODE: ffff880117bfbfc0",
+        "    PHYSICAL ADDRESS: d04f1000",
+        "                 PID: 1297  MAPPINGS: 1  MM: ffff88007f8aa580",
+        "                 PID: 1318  MAPPINGS: 1  MM: ffff88007f8abe80",
         "",
-//      "    STABLE_NODE     : ffff8806248c2dd0",
-//      "    PAGE            : ffffea000ae7f8d8",
-//      "    PHYSICAL ADDRESS: 31db4d000",
-        "                PAGE: ffffea000ae7f8d8",
-        "         STABLE_NODE: ffff8806248c2dd0",
-        "    PHYSICAL ADDRESS: 31db4d000",
-        "                 PID: 2205  MAPPINGS: 2",
+        "                PAGE: ffffea00021e9880",
+        "         STABLE_NODE: ffff880054ee1f30",
+        "    PHYSICAL ADDRESS: 87a62000",
+        "                 PID: 1297  MAPPINGS: 2  MM: ffff88007f8aa580",
         "    ...",
         "",
         "  Display all information about the KSM page whose physical",
-        "  address is 0x626e60000:\n",
-        "    %s> ksm -v 626e60000",
-        "                PAGE: ffffea0015882500",
-        "         STABLE_NODE: ffff88028b2af3d0",
-        "    PHYSICAL ADDRESS: 626e60000",
-        "                 PID: 2603  MAPPINGS: 8",
+        "  address is 0xffffea000168cd00:\n",
+        "    %s> ksm -v ffffea000168cd00",
+        "                PAGE: ffffea000168cd00",
+        "         STABLE_NODE: ffff88007153ce10",
+        "    PHYSICAL ADDRESS: 5a334000",
+        "                 PID: 1297  MAPPINGS: 4  MM: ffff88007f8aa580",
         "                 VIRTUAL:",
-        "                 7ff46bcb4000",
-        "                 7ff46bcad000",
-        "                 7ff46bc9f000",
-        "                 7ff46bc7c000",
-        "                 7ff46bc6e000",
-        "                 7ff46bc67000",
-        "                 7ff46bc60000",
-        "                 7ff46bc59000",
+        "                 7f8cb91f9000",
+        "                 7f8cb8f28000",
+        "                 7f8cb7abf000",
+        "                 7f8cb79c7000",
+        "",
+        "                 PID: 1318  MAPPINGS: 4  MM: ffff88007f8abe80",
+        "                 VIRTUAL:",
+        "                 7f7ca0703000",
+        "                 7f7c9f15e000",
+        "                 7f7c9ef8f000",
+        "                 7f7c9e96b000",
         NULL
 };

+/*
+ * find the page_ref whose mm is same as mm
+ */
+static struct page_ref *
+find_match_ref(struct page_ref *ref_list, ulong mm)
+{
+	struct page_ref *next_ref = ref_list;
+
+	while (next_ref) {
+		if (next_ref->mm == mm) {
+			break;
+		} else {
+			next_ref = next_ref->next;
+		}
+	}
+
+	return next_ref;
+}

 /*
- * dump_ksm() displays information of ksm pages.
+ * get the pid of the task that mm_struct belongs to, if not find,
+ * return (ulong)-1
  */
+static ulong
+find_pid(ulong mm)
+{
+	struct task_context *tc;
+	int i;
+	ulong pid = -1;
+
+	tc = FIRST_CONTEXT();
+	for (i = 0; i < RUNNING_TASKS(); i++, tc++) {
+		if (tc->mm_struct == mm) {
+			pid = tc->pid;
+			break;
+		}
+	}
+
+	return pid;
+}
+
 static void
-dump_ksm(struct meminfo *mi)
+add_to_ref_list(struct page_ref **ref_list_ptr, struct page_ref *ref)
 {
-	ulong root_stable_tree, stable_node, kpfn;
+	ref->next = *ref_list_ptr;
+	*ref_list_ptr = ref;
+}
+
+static void
+clean_ref_list(struct page_ref *ref_list)
+{
+	struct page_ref *tmp_ref, *next_ref;
+
+	tmp_ref = ref_list;
+
+	while (tmp_ref) {
+		next_ref = tmp_ref->next;
+		FREEBUF(tmp_ref);
+		tmp_ref = next_ref;
+	}
+}
+
+/*
+ * dump the ksm pages from the stable tree
+ */
+static void
+dump_stable_tree(struct meminfo *mi, struct rb_root *root)
+{
+	ulong 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;
+	int found;
+	struct page_ref *ref_list;
 	ulong page, address;

-	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 && mi->flags & ADDRESS_SPECIFIED) ? 0 : -1;
+
 	for (node = rb_first(root); node; node = rb_next(node)) {
 		stable_node = (ulong) node - KSM_OFFSET(stable_node_node);
 		if (CRASHDEBUG(1))
 			fprintf(fp, "  stable_node = %lx\n", stable_node);

-		readmem(stable_node + KSM_OFFSET(stable_node_hlist),
-			KVADDR, &first, sizeof(ulong),
-			"stable_node hlist", FAULT_ON_ERROR);
 		readmem(stable_node + KSM_OFFSET(stable_node_kpfn),
 			KVADDR, &kpfn, sizeof(ulong),
 			"stable_node kpfn", FAULT_ON_ERROR);
 <at>  <at>  -259,10 +307,6  <at>  <at>  dump_ksm(struct meminfo *mi)
 		if (found == 0)
 			continue;

-//		fprintf(fp, "STABLE_NODE     : %lx\n", stable_node);
-//		fprintf(fp, "PAGE            : %lx\n", page);
-//		fprintf(fp, "PHYSICAL ADDRESS: %lx\n\n", paddr);
-
 		fprintf(fp, "            PAGE: %lx\n", page);
 		fprintf(fp, "     STABLE_NODE: %lx\n", stable_node);
 		fprintf(fp, "PHYSICAL ADDRESS: %lx\n", paddr);
 <at>  <at>  -272,41 +316,51  <at>  <at>  dump_ksm(struct meminfo *mi)
 			"stable_node hlist", FAULT_ON_ERROR);

 		next = first;
+		ref_list = NULL;
+		struct page_ref *tmp_ref = NULL;
+
 		while (next) {
 			rmap_item = next - KSM_OFFSET(rmap_item_hlist);
 			readmem(rmap_item + KSM_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;
-				}
+			//get the page_ref whose mm is equal to rmap_item's mm
+			tmp_ref = find_match_ref(ref_list, mm);
+			if (tmp_ref) {
+				tmp_ref->ref += 1;
+			} else {
+				//create a new page_ref
+				tmp_ref = (struct page_ref *)GETBUF(
+						sizeof(struct page_ref));
+				tmp_ref->mm = mm;
+				tmp_ref->pid = find_pid(mm);
+				tmp_ref->ref = 1;
+
+				add_to_ref_list(&ref_list, tmp_ref);
 			}

-next:
 			readmem(next + OFFSET(hlist_node_next),
 				KVADDR, &next, sizeof(ulong),
 				"hlist_node next", FAULT_ON_ERROR);
 		};

-		for (i = 0; i < refs; i++) {
-			fprintf(fp, "             PID: %ld ", ref[i].pid);
-			fprintf(fp, " MAPPINGS: %d\n", ref[i].ref);
+		tmp_ref = ref_list;
+		while (tmp_ref) {
+			if (tmp_ref->pid == (ulong)-1) {
+				/*
+				 * the task has exited, but the ksm pages has
+				 * not been cleared yet.
+				 */
+				fprintf(fp, "             PID: - ");
+			} else {
+				fprintf(fp, "             PID: %ld ", tmp_ref->pid);
+			}
+			fprintf(fp, " MAPPINGS: %d ", tmp_ref->ref);
+			fprintf(fp, " MM: %lx\n", tmp_ref->mm);

 			if (!(mi && mi->flags & VERBOSE))
-				continue;
+				goto next_ref;

 			fprintf(fp, "             VIRTUAL:\n");
 			next = first;
 <at>  <at>  -315,7 +369,7  <at>  <at>  next:
 				readmem(rmap_item + KSM_OFFSET(rmap_item_mm),
 					KVADDR, &mm, sizeof(ulong),
 					"rmap_item mm", FAULT_ON_ERROR);
-				if (ref[i].mm == mm) {
+				if (tmp_ref->mm == mm) {
 					readmem(rmap_item + KSM_OFFSET(rmap_item_address),
 						KVADDR, &address, sizeof(ulong),
 						"rmap_item address", FAULT_ON_ERROR);
 <at>  <at>  -327,10 +381,16  <at>  <at>  next:
 					"hlist_node next", FAULT_ON_ERROR);
 			}
 			fprintf(fp, "\n");
+
+next_ref:
+			tmp_ref = tmp_ref->next;
 		}
+
+		//clear all page_ref
+		clean_ref_list(ref_list);
+
 		if (!(mi && mi->flags & VERBOSE))
 			fprintf(fp, "\n");
-		refs = 0;

 		if (found == 1)
 			break;
 <at>  <at>  -339,6 +399,41  <at>  <at>  next:
 	if (found == 0)
 		fprintf(fp, "address 0x%llx cannot specify a ksm stable tree node\n",
 			mi->spec_addr);
+}

-	FREEBUF(ref);
+/*
+ * dump_ksm() displays information of ksm pages.
+ */
+static void
+dump_ksm(struct meminfo *mi)
+{
+	ulong root_stable_tree_ptr;
+	ulong ksm_nr_node_ids_ptr;
+	int ksm_nr_node_ids;
+	struct rb_root *root;
+	int i;
+
+	if (!symbol_exists("root_stable_tree")) {
+		error(INFO, "cannot determine ksm stable tree address from root_stable_tree\n");
+		return;
+	}
+	root_stable_tree_ptr = symbol_value("root_stable_tree");
+
+	if (symbol_exists("ksm_nr_node_ids")) {
+		//root_stable_tree_ptr is an array of stable tree root
+		ksm_nr_node_ids_ptr = symbol_value("ksm_nr_node_ids");
+		readmem(ksm_nr_node_ids_ptr, KVADDR, &ksm_nr_node_ids,
+			sizeof(ksm_nr_node_ids), "ksm_nr_node_ids",
+			FAULT_ON_ERROR);
+
+		readmem(root_stable_tree_ptr, KVADDR, &root, sizeof(ulong),
+			"first stable tree root", FAULT_ON_ERROR);
+		
+		for (i = 0; i < ksm_nr_node_ids; i++) {
+			dump_stable_tree(mi, root + i);
+		}
+	} else {
+		root = (struct rb_root *)root_stable_tree_ptr;
+		dump_stable_tree(mi, root);
+	}
 }
-- 
1.8.5.3

From 3d313aaf5d9fedd91e81ac596fe407614dd57de1 Mon Sep 17 00:00:00 2001
From: Qiao Nuohan <qiaonuohan <at> cn.fujitsu.com>
Date: Wed, 11 Jun 2014 10:01:21 +0800
Subject: [PATCH] Fix ksm.c

Because of the following kernel patch, 'root_stable_tree' and 
'struct stable_node' are changed. 

<cut>
ef53d16cded7f89b3843b7a96970dab897843ea5
90bd6fd31c8097ee4ddcb74b7e08363134863de5
4146d2d673e8d6abf9b30a5b5dd8cd95f29632eb
<cut>

Another two change are listed below.

1. add mm_struct's address for the task.
ksm displayed ksm page's messages like below
<cut>
            PAGE: ffffea000451f180
     STABLE_NODE: ffff88004866b6c0
PHYSICAL ADDRESS: 1147c6000
             PID: 1318  MAPPINGS: 7707
             PID: 1297  MAPPINGS: 4965

<cut>

Now, MM item is added to show the mm_struct's address related to task, like
below
<cut>
            PAGE: ffffea000451f180
     STABLE_NODE: ffff88004866b6c0
PHYSICAL ADDRESS: 1147c6000
             PID: 1318  MAPPINGS: 7707  MM: ffff88007f8abe80
             PID: 1297  MAPPINGS: 4965  MM: ffff88007f8aa580

<cut>

2. the task that uses ksm pages may have exited. this patch will change to
show the exited task's "MAPPINGS" and "MM" like below
<cut>
            PAGE: ffffea000292ca40
     STABLE_NODE: ffff88009fe8e9c0
PHYSICAL ADDRESS: a4b29000
             PID: -  MAPPINGS: 1  MM: ffff880115f28000
             PID: -  MAPPINGS: 1  MM: ffff8800cdd7a580
<cut>
task has exited, so PID is "-"

Signed-off-by: Qiao Nuohan <qiaonuohan <at> cn.fujitsu.com>
---
 extensions/ksm.c | 289 ++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 192 insertions(+), 97 deletions(-)

diff --git a/extensions/ksm.c b/extensions/ksm.c
index ce02318..ef97c92 100644
--- a/extensions/ksm.c
+++ b/extensions/ksm.c
 <at>  <at>  -1,6 +1,7  <at>  <at> 
 /*
- * Copyright (C) 2013 FUJITSU LIMITED
+ * Copyright (C) 2013-2014 FUJITSU LIMITED
  * Author: Zhang Yanfei <zhangyanfei <at> cn.fujitsu.com>
+ * Signed-off-by: Qiao Nuohan <qiaonuohan <at> cn.fujitsu.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 <at>  <at>  -22,7 +23,7  <at>  <at>  void cmd_ksm(void);
 char *help_ksm[];

 static struct command_table_entry command_table[] = {
-        { "ksm", cmd_ksm, help_ksm, 0},          
+        { "ksm", cmd_ksm, help_ksm, 0},
         { NULL },
 };

 <at>  <at>  -35,7 +36,8  <at>  <at>  struct ksm_offset_table {
 	long rmap_item_hlist;
 } ksm_offset_table;

-#define KSM_ASSIGN_OFFSET(X)   (ksm_offset_table.X)
+#define KSM_ASSIGN_OFFSET(X) (ksm_offset_table.X)
+#define KSM_INVALID_MEMBER(X) (ksm_offset_table.X == INVALID_OFFSET)
 #define KSM_MEMBER_OFFSET_INIT(X, Y, Z) (KSM_ASSIGN_OFFSET(X) = MEMBER_OFFSET(Y, Z))
 #define KSM_ANON_MEMBER_OFFSET_INIT(X, Y, Z) (KSM_ASSIGN_OFFSET(X) = ANON_MEMBER_OFFSET(Y, Z))
 #define KSM_OFFSET(X)  (OFFSET_verify(ksm_offset_table.X, (char *)__FUNCTION__, __FILE__,
__LINE__, #X))
 <at>  <at>  -50,27 +52,30  <at>  <at>  struct page_ref {
         ulong mm;
         ulong pid;
         int ref;
+	struct page_ref *next;
 };

 static void dump_ksm(struct meminfo *);

 void __attribute__((constructor))
 ksm_init(void) /* Register the command set. */
-{ 
+{
 	if (STRUCT_EXISTS("stable_node")) {
 		KSM_MEMBER_OFFSET_INIT(stable_node_node, "stable_node", "node");
+		if (KSM_INVALID_MEMBER(stable_node_node))
+			KSM_ANON_MEMBER_OFFSET_INIT(stable_node_node, "stable_node", "node");
+
 		KSM_MEMBER_OFFSET_INIT(stable_node_hlist, "stable_node", "hlist");
 		KSM_MEMBER_OFFSET_INIT(stable_node_kpfn, "stable_node", "kpfn");
-		KSM_MEMBER_OFFSET_INIT(stable_node_node, "stable_node", "node");
 		KSM_MEMBER_OFFSET_INIT(rmap_item_mm, "rmap_item", "mm");
 		KSM_MEMBER_OFFSET_INIT(rmap_item_address, "rmap_item", "address");
 		KSM_ANON_MEMBER_OFFSET_INIT(rmap_item_hlist, "rmap_item", "hlist");
 	} else
-		error(FATAL, "ksm_init: stable_node does not exist\n"); 
+		error(FATAL, "ksm_init: stable_node does not exist\n");

        	register_extension(command_table);
 }
- 
+
 void __attribute__((destructor))
 ksm_fini(void) { }

 <at>  <at>  -139,15 +144,17  <at>  <at>  cmd_ksm(void)
 }

 char *help_ksm[] = {
-        "ksm", 
+        "ksm",
         "kernel samepage merging (KSM) information",
-        "[-v] [[-p] address ...]",                   
- 
+        "[-v] [[-p] address ...]",
+
         "  This command displays information about all KSM pages currently",
         "  in use.  For each KSM page, the display includes its stable_node",
-        "  address, its page struct address, its physical address, the TGID/PID", 
-        "  for each task that is using the page, and the number of mappings in",
-        "  the task's address space for the page.",
+        "  address, its page struct address, its physical address, the TGID/PID",
+        "  for each task that is using the page, the number of mappings in the",
+        "  task's address space for the page, and the mm_struct address of the",
+        "  task. If pid is '-', the task has exited and the ksm page has not",
+        "  been removed.",
         " ",
         "       -v  also dump each virtual address in a PID's virtual address",
         "           space that maps the KSM page.",
 <at>  <at>  -159,88 +166,129  <at>  <at>  char *help_ksm[] = {
         "\nEXAMPLE",
         "  Display information about all KSM pages:\n",
         "    %s> ksm",
-//      "    STABLE_NODE     : ffff8806248c2d80",
-//      "    PAGE            : ffffea000ae7f6a8",
-//      "    PHYSICAL ADDRESS: 31db43000",
-        "                PAGE: ffffea000ae7f6a8",
-        "         STABLE_NODE: ffff8806248c2d80",
-        "    PHYSICAL ADDRESS: 31db43000",
-        "                 PID: 2205  MAPPINGS: 2",
+        "                PAGE: ffffea000451f180",
+        "         STABLE_NODE: ffff88004866b6c0",
+        "    PHYSICAL ADDRESS: 1147c6000",
+        "                 PID: 1318  MAPPINGS: 7707  MM: ffff88007f8abe80",
+        "                 PID: 1297  MAPPINGS: 4965  MM: ffff88007f8aa580",
         "",
-//      "    STABLE_NODE     : ffff880624aa57b8",
-//      "    PAGE            : ffffea000ae800f0",
-//      "    PHYSICAL ADDRESS: 31db72000",
-        "                PAGE: ffffea000ae800f0",
-        "         STABLE_NODE: ffff880624aa57b8",
-        "    PHYSICAL ADDRESS: 31db72000",
-        "                 PID: 2205  MAPPINGS: 2",
+        "                PAGE: ffffea0003413c40",
+        "         STABLE_NODE: ffff880117bfbfc0",
+        "    PHYSICAL ADDRESS: d04f1000",
+        "                 PID: 1297  MAPPINGS: 1  MM: ffff88007f8aa580",
+        "                 PID: 1318  MAPPINGS: 1  MM: ffff88007f8abe80",
         "",
-//      "    STABLE_NODE     : ffff8806248c2dd0",
-//      "    PAGE            : ffffea000ae7f8d8",
-//      "    PHYSICAL ADDRESS: 31db4d000",
-        "                PAGE: ffffea000ae7f8d8",
-        "         STABLE_NODE: ffff8806248c2dd0",
-        "    PHYSICAL ADDRESS: 31db4d000",
-        "                 PID: 2205  MAPPINGS: 2",
+        "                PAGE: ffffea00021e9880",
+        "         STABLE_NODE: ffff880054ee1f30",
+        "    PHYSICAL ADDRESS: 87a62000",
+        "                 PID: 1297  MAPPINGS: 2  MM: ffff88007f8aa580",
         "    ...",
         "",
         "  Display all information about the KSM page whose physical",
-        "  address is 0x626e60000:\n",
-        "    %s> ksm -v 626e60000",
-        "                PAGE: ffffea0015882500",
-        "         STABLE_NODE: ffff88028b2af3d0",
-        "    PHYSICAL ADDRESS: 626e60000",
-        "                 PID: 2603  MAPPINGS: 8",
+        "  address is 0xffffea000168cd00:\n",
+        "    %s> ksm -v ffffea000168cd00",
+        "                PAGE: ffffea000168cd00",
+        "         STABLE_NODE: ffff88007153ce10",
+        "    PHYSICAL ADDRESS: 5a334000",
+        "                 PID: 1297  MAPPINGS: 4  MM: ffff88007f8aa580",
         "                 VIRTUAL:",
-        "                 7ff46bcb4000",
-        "                 7ff46bcad000",
-        "                 7ff46bc9f000",
-        "                 7ff46bc7c000",
-        "                 7ff46bc6e000",
-        "                 7ff46bc67000",
-        "                 7ff46bc60000",
-        "                 7ff46bc59000",
+        "                 7f8cb91f9000",
+        "                 7f8cb8f28000",
+        "                 7f8cb7abf000",
+        "                 7f8cb79c7000",
+        "",
+        "                 PID: 1318  MAPPINGS: 4  MM: ffff88007f8abe80",
+        "                 VIRTUAL:",
+        "                 7f7ca0703000",
+        "                 7f7c9f15e000",
+        "                 7f7c9ef8f000",
+        "                 7f7c9e96b000",
         NULL
 };

+/*
+ * find the page_ref whose mm is same as mm
+ */
+static struct page_ref *
+find_match_ref(struct page_ref *ref_list, ulong mm)
+{
+	struct page_ref *next_ref = ref_list;
+
+	while (next_ref) {
+		if (next_ref->mm == mm) {
+			break;
+		} else {
+			next_ref = next_ref->next;
+		}
+	}
+
+	return next_ref;
+}

 /*
- * dump_ksm() displays information of ksm pages.
+ * get the pid of the task that mm_struct belongs to, if not find,
+ * return (ulong)-1
  */
+static ulong
+find_pid(ulong mm)
+{
+	struct task_context *tc;
+	int i;
+	ulong pid = -1;
+
+	tc = FIRST_CONTEXT();
+	for (i = 0; i < RUNNING_TASKS(); i++, tc++) {
+		if (tc->mm_struct == mm) {
+			pid = tc->pid;
+			break;
+		}
+	}
+
+	return pid;
+}
+
 static void
-dump_ksm(struct meminfo *mi)
+add_to_ref_list(struct page_ref **ref_list_ptr, struct page_ref *ref)
 {
-	ulong root_stable_tree, stable_node, kpfn;
+	ref->next = *ref_list_ptr;
+	*ref_list_ptr = ref;
+}
+
+static void
+clean_ref_list(struct page_ref *ref_list)
+{
+	struct page_ref *tmp_ref, *next_ref;
+
+	tmp_ref = ref_list;
+
+	while (tmp_ref) {
+		next_ref = tmp_ref->next;
+		FREEBUF(tmp_ref);
+		tmp_ref = next_ref;
+	}
+}
+
+/*
+ * dump the ksm pages from the stable tree
+ */
+static void
+dump_stable_tree(struct meminfo *mi, struct rb_root *root)
+{
+	ulong 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;
+	int found;
+	struct page_ref *ref_list;
 	ulong page, address;

-	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 && mi->flags & ADDRESS_SPECIFIED) ? 0 : -1;
+
 	for (node = rb_first(root); node; node = rb_next(node)) {
 		stable_node = (ulong) node - KSM_OFFSET(stable_node_node);
 		if (CRASHDEBUG(1))
 			fprintf(fp, "  stable_node = %lx\n", stable_node);

-		readmem(stable_node + KSM_OFFSET(stable_node_hlist),
-			KVADDR, &first, sizeof(ulong),
-			"stable_node hlist", FAULT_ON_ERROR);
 		readmem(stable_node + KSM_OFFSET(stable_node_kpfn),
 			KVADDR, &kpfn, sizeof(ulong),
 			"stable_node kpfn", FAULT_ON_ERROR);
 <at>  <at>  -259,10 +307,6  <at>  <at>  dump_ksm(struct meminfo *mi)
 		if (found == 0)
 			continue;

-//		fprintf(fp, "STABLE_NODE     : %lx\n", stable_node);
-//		fprintf(fp, "PAGE            : %lx\n", page);
-//		fprintf(fp, "PHYSICAL ADDRESS: %lx\n\n", paddr);
-
 		fprintf(fp, "            PAGE: %lx\n", page);
 		fprintf(fp, "     STABLE_NODE: %lx\n", stable_node);
 		fprintf(fp, "PHYSICAL ADDRESS: %lx\n", paddr);
 <at>  <at>  -272,41 +316,51  <at>  <at>  dump_ksm(struct meminfo *mi)
 			"stable_node hlist", FAULT_ON_ERROR);

 		next = first;
+		ref_list = NULL;
+		struct page_ref *tmp_ref = NULL;
+
 		while (next) {
 			rmap_item = next - KSM_OFFSET(rmap_item_hlist);
 			readmem(rmap_item + KSM_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;
-				}
+			//get the page_ref whose mm is equal to rmap_item's mm
+			tmp_ref = find_match_ref(ref_list, mm);
+			if (tmp_ref) {
+				tmp_ref->ref += 1;
+			} else {
+				//create a new page_ref
+				tmp_ref = (struct page_ref *)GETBUF(
+						sizeof(struct page_ref));
+				tmp_ref->mm = mm;
+				tmp_ref->pid = find_pid(mm);
+				tmp_ref->ref = 1;
+
+				add_to_ref_list(&ref_list, tmp_ref);
 			}

-next:
 			readmem(next + OFFSET(hlist_node_next),
 				KVADDR, &next, sizeof(ulong),
 				"hlist_node next", FAULT_ON_ERROR);
 		};

-		for (i = 0; i < refs; i++) {
-			fprintf(fp, "             PID: %ld ", ref[i].pid);
-			fprintf(fp, " MAPPINGS: %d\n", ref[i].ref);
+		tmp_ref = ref_list;
+		while (tmp_ref) {
+			if (tmp_ref->pid == (ulong)-1) {
+				/*
+				 * the task has exited, but the ksm pages has
+				 * not been cleared yet.
+				 */
+				fprintf(fp, "             PID: - ");
+			} else {
+				fprintf(fp, "             PID: %ld ", tmp_ref->pid);
+			}
+			fprintf(fp, " MAPPINGS: %d ", tmp_ref->ref);
+			fprintf(fp, " MM: %lx\n", tmp_ref->mm);

 			if (!(mi && mi->flags & VERBOSE))
-				continue;
+				goto next_ref;

 			fprintf(fp, "             VIRTUAL:\n");
 			next = first;
 <at>  <at>  -315,7 +369,7  <at>  <at>  next:
 				readmem(rmap_item + KSM_OFFSET(rmap_item_mm),
 					KVADDR, &mm, sizeof(ulong),
 					"rmap_item mm", FAULT_ON_ERROR);
-				if (ref[i].mm == mm) {
+				if (tmp_ref->mm == mm) {
 					readmem(rmap_item + KSM_OFFSET(rmap_item_address),
 						KVADDR, &address, sizeof(ulong),
 						"rmap_item address", FAULT_ON_ERROR);
 <at>  <at>  -327,10 +381,16  <at>  <at>  next:
 					"hlist_node next", FAULT_ON_ERROR);
 			}
 			fprintf(fp, "\n");
+
+next_ref:
+			tmp_ref = tmp_ref->next;
 		}
+
+		//clear all page_ref
+		clean_ref_list(ref_list);
+
 		if (!(mi && mi->flags & VERBOSE))
 			fprintf(fp, "\n");
-		refs = 0;

 		if (found == 1)
 			break;
 <at>  <at>  -339,6 +399,41  <at>  <at>  next:
 	if (found == 0)
 		fprintf(fp, "address 0x%llx cannot specify a ksm stable tree node\n",
 			mi->spec_addr);
+}

-	FREEBUF(ref);
+/*
+ * dump_ksm() displays information of ksm pages.
+ */
+static void
+dump_ksm(struct meminfo *mi)
+{
+	ulong root_stable_tree_ptr;
+	ulong ksm_nr_node_ids_ptr;
+	int ksm_nr_node_ids;
+	struct rb_root *root;
+	int i;
+
+	if (!symbol_exists("root_stable_tree")) {
+		error(INFO, "cannot determine ksm stable tree address from root_stable_tree\n");
+		return;
+	}
+	root_stable_tree_ptr = symbol_value("root_stable_tree");
+
+	if (symbol_exists("ksm_nr_node_ids")) {
+		//root_stable_tree_ptr is an array of stable tree root
+		ksm_nr_node_ids_ptr = symbol_value("ksm_nr_node_ids");
+		readmem(ksm_nr_node_ids_ptr, KVADDR, &ksm_nr_node_ids,
+			sizeof(ksm_nr_node_ids), "ksm_nr_node_ids",
+			FAULT_ON_ERROR);
+
+		readmem(root_stable_tree_ptr, KVADDR, &root, sizeof(ulong),
+			"first stable tree root", FAULT_ON_ERROR);
+		
+		for (i = 0; i < ksm_nr_node_ids; i++) {
+			dump_stable_tree(mi, root + i);
+		}
+	} else {
+		root = (struct rb_root *)root_stable_tree_ptr;
+		dump_stable_tree(mi, root);
+	}
 }
--

-- 
1.8.5.3

David Mair | 13 Jun 07:07 2014

[PATCH] Fix for some command-line cases an unintended unlink of a file crash didn't create and a leftover temporary

When the crash command line includes two filenames where one is a
compressed kernel and the other is a debuginfo file and they appear in
that order then if the uncompressed temporary version of the kernel is
actually larger than the debuginfo then crash will end with an error but
will also unlink the debuginfo file and will not clean up the (intended
temporary) uncompressed copy of the kernel.

This patch at least fixes the unintended unlink and leaving the
temporary present. It doesn't fix the failure to start but that's
because the wrong files are assumed the debuginfo and kernel. The size
case that led to this discovery is probably rare.

The cause is that evidence of a temporary file to unlink is that there
is a value in pc->namelist and pc->namelist_orig (or pc->namelist_debug
and pc->namelist_orig_debug) but when the file size test in
select_namelist() results in the pc->namelist copy to pc->namelist_debug
the _orig is not copied as well so the implied file to unlink is the one
set in pc->namelist (the debuginfo filename now).

The patch causes a populated namelist_orig value to be swapped with
namelist_debug_orig if the namelist value is copied to namelist_debug.

    Signed-off-by: David Mair <dmair <at> suse.com>
---
 symbols.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/symbols.c b/symbols.c
index 4c6fbf4..e1ed719 100644
--- a/symbols.c
+++ b/symbols.c
 <at>  <at>  -3520,6 +3520,7  <at>  <at>  int
 select_namelist(char *new)
 {
        struct stat stat1, stat2;
+       char *namecp;

        if (pc->server_namelist) {
                pc->namelist_debug = new;
 <at>  <at>  -3533,6 +3534,12  <at>  <at>  select_namelist(char *new)

        if (stat1.st_size > stat2.st_size) {
                pc->namelist_debug = pc->namelist;
+               if (pc->namelist_orig)
+               {
+                       namecp = pc->namelist_debug_orig;
+                       pc->namelist_debug_orig = pc->namelist_orig;
+                       pc->namelist_orig = namecp;
+               }
                pc->namelist = new;
        } else if (stat2.st_size > stat1.st_size)
                pc->namelist_debug = new;

Don Slutz | 11 Jun 19:28 2014
Picon

[PATCH 1/1] xendump: Use off_t not long for 32bit code

This enables crash to handle xen dumps that are larger then 4G
in size in 32bit mode.

Signed-off-by: Don Slutz <dslutz <at> verizon.com>
---
This is the same as was sent as an attachment.  Just a clean top post.

 x86.c     | 10 ++++-----
 x86_64.c  | 10 ++++-----
 xendump.c | 74 +++++++++++++++++++++++++++++++++------------------------------
 xendump.h |  6 +++---
 4 files changed, 52 insertions(+), 48 deletions(-)

diff --git a/x86.c b/x86.c
index 833a11b..608bb88 100644
--- a/x86.c
+++ b/x86.c
 <at>  <at>  -4897,7 +4897,7  <at>  <at>  x86_xendump_p2m_create(struct xendump_data *xd)
 		    "MEMBER_OFFSET(vcpu_guest_context, ctrlreg): %ld\n",
 			ctrlreg_offset);

-	offset = (off_t)xd->xc_core.header.xch_ctxt_offset + 
+	offset = xd->xc_core.header.xch_ctxt_offset +
 		(off_t)ctrlreg_offset;

 	if (lseek(xd->xfd, offset, SEEK_SET) == -1)
 <at>  <at>  -4997,7 +4997,7  <at>  <at>  x86_pvops_xendump_p2m_create(struct xendump_data *xd)
 		    "MEMBER_OFFSET(vcpu_guest_context, ctrlreg): %ld\n",
 			ctrlreg_offset);

-	offset = (off_t)xd->xc_core.header.xch_ctxt_offset + 
+	offset = xd->xc_core.header.xch_ctxt_offset +
 		(off_t)ctrlreg_offset;

 	if (lseek(xd->xfd, offset, SEEK_SET) == -1)
 <at>  <at>  -5369,7 +5369,7  <at>  <at>  x86_xendump_panic_task(struct xendump_data *xd)
 	    INVALID_MEMBER(cpu_user_regs_esp))
 		return NO_TASK;

-        offset = (off_t)xd->xc_core.header.xch_ctxt_offset +
+        offset = xd->xc_core.header.xch_ctxt_offset +
                 (off_t)OFFSET(vcpu_guest_context_user_regs) +
 		(off_t)OFFSET(cpu_user_regs_esp);

 <at>  <at>  -5419,7 +5419,7  <at>  <at>  x86_get_xendump_regs(struct xendump_data *xd, struct bt_info *bt, ulong *eip, ul
             INVALID_MEMBER(cpu_user_regs_esp))
                 goto generic;

-        offset = (off_t)xd->xc_core.header.xch_ctxt_offset +
+        offset = xd->xc_core.header.xch_ctxt_offset +
                 (off_t)OFFSET(vcpu_guest_context_user_regs) +
                 (off_t)OFFSET(cpu_user_regs_esp);
         if (lseek(xd->xfd, offset, SEEK_SET) == -1)
 <at>  <at>  -5427,7 +5427,7  <at>  <at>  x86_get_xendump_regs(struct xendump_data *xd, struct bt_info *bt, ulong *eip, ul
         if (read(xd->xfd, &xesp, sizeof(ulong)) != sizeof(ulong))
                 goto generic;

-        offset = (off_t)xd->xc_core.header.xch_ctxt_offset +
+        offset = xd->xc_core.header.xch_ctxt_offset +
                 (off_t)OFFSET(vcpu_guest_context_user_regs) +
                 (off_t)OFFSET(cpu_user_regs_eip);
         if (lseek(xd->xfd, offset, SEEK_SET) == -1)
diff --git a/x86_64.c b/x86_64.c
index f4a3e8b..a2e4636 100644
--- a/x86_64.c
+++ b/x86_64.c
 <at>  <at>  -6184,7 +6184,7  <at>  <at>  x86_64_xendump_p2m_create(struct xendump_data *xd)
 		    "MEMBER_OFFSET(vcpu_guest_context, ctrlreg): %ld\n",
 			ctrlreg_offset);

-	offset = (off_t)xd->xc_core.header.xch_ctxt_offset + 
+	offset = xd->xc_core.header.xch_ctxt_offset +
 		(off_t)ctrlreg_offset;

 	if (lseek(xd->xfd, offset, SEEK_SET) == -1)
 <at>  <at>  -6270,7 +6270,7  <at>  <at>  x86_64_pvops_xendump_p2m_create(struct xendump_data *xd)
 		    "MEMBER_OFFSET(vcpu_guest_context, ctrlreg): %ld\n",
 			ctrlreg_offset);

-	offset = (off_t)xd->xc_core.header.xch_ctxt_offset + 
+	offset = xd->xc_core.header.xch_ctxt_offset +
 		(off_t)ctrlreg_offset;

 	if (lseek(xd->xfd, offset, SEEK_SET) == -1)
 <at>  <at>  -6601,7 +6601,7  <at>  <at>  x86_64_xendump_panic_task(struct xendump_data *xd)
 	    INVALID_MEMBER(cpu_user_regs_esp))
 		return NO_TASK;

-        offset = (off_t)xd->xc_core.header.xch_ctxt_offset +
+        offset = xd->xc_core.header.xch_ctxt_offset +
                 (off_t)OFFSET(vcpu_guest_context_user_regs) +
 		(off_t)OFFSET(cpu_user_regs_rsp);

 <at>  <at>  -6653,7 +6653,7  <at>  <at>  x86_64_get_xendump_regs(struct xendump_data *xd, struct bt_info *bt, ulong *rip,
             INVALID_MEMBER(cpu_user_regs_rsp))
                 goto generic;

-        offset = (off_t)xd->xc_core.header.xch_ctxt_offset +
+        offset = xd->xc_core.header.xch_ctxt_offset +
                 (off_t)OFFSET(vcpu_guest_context_user_regs) +
                 (off_t)OFFSET(cpu_user_regs_rsp);
         if (lseek(xd->xfd, offset, SEEK_SET) == -1)
 <at>  <at>  -6661,7 +6661,7  <at>  <at>  x86_64_get_xendump_regs(struct xendump_data *xd, struct bt_info *bt, ulong *rip,
         if (read(xd->xfd, &xrsp, sizeof(ulong)) != sizeof(ulong))
                 goto generic;

-        offset = (off_t)xd->xc_core.header.xch_ctxt_offset +
+        offset = xd->xc_core.header.xch_ctxt_offset +
                 (off_t)OFFSET(vcpu_guest_context_user_regs) +
                 (off_t)OFFSET(cpu_user_regs_rip);
         if (lseek(xd->xfd, offset, SEEK_SET) == -1)
diff --git a/xendump.c b/xendump.c
index 6d6b51e..9d78916 100644
--- a/xendump.c
+++ b/xendump.c
 <at>  <at>  -126,9 +126,9  <at>  <at>  xc_core_verify(char *file, char *buf)
 	xd->xc_core.header.xch_magic = xcp->xch_magic;
 	xd->xc_core.header.xch_nr_vcpus = xcp->xch_nr_vcpus;
 	xd->xc_core.header.xch_nr_pages = xcp->xch_nr_pages;
-	xd->xc_core.header.xch_ctxt_offset = (ulong)xcp->xch_ctxt_offset;
-	xd->xc_core.header.xch_index_offset = (ulong)xcp->xch_index_offset;
-	xd->xc_core.header.xch_pages_offset = (ulong)xcp->xch_pages_offset;
+	xd->xc_core.header.xch_ctxt_offset = (off_t)xcp->xch_ctxt_offset;
+	xd->xc_core.header.xch_index_offset = (off_t)xcp->xch_index_offset;
+	xd->xc_core.header.xch_pages_offset = (off_t)xcp->xch_pages_offset;

         xd->flags |= (XENDUMP_LOCAL | XC_CORE_ORIG | XC_CORE_P2M_CREATE);

 <at>  <at>  -187,7 +187,7  <at>  <at>  xc_core_read(void *bufptr, int cnt, ulong addr, physaddr_t paddr)
 	    PFN_NOT_FOUND)
 		return READ_ERROR;

-	offset = (off_t)xd->xc_core.header.xch_pages_offset +
+	offset = xd->xc_core.header.xch_pages_offset +
 		((off_t)(page_index) * (off_t)xd->page_size);

 	if (lseek(xd->xfd, offset, SEEK_SET) == -1) 
 <at>  <at>  -852,7 +852,7  <at>  <at>  read_xendump_hyper(int fd, void *bufptr, int cnt, ulong addr, physaddr_t paddr)
         if ((page_index = xc_core_mfn_to_page_index(pfn)) == PFN_NOT_FOUND)
                 return READ_ERROR;

-        offset = (off_t)xd->xc_core.header.xch_pages_offset +
+        offset = xd->xc_core.header.xch_pages_offset +
                 ((off_t)(page_index) * (off_t)xd->page_size);

         if (lseek(xd->xfd, offset, SEEK_SET) == -1)
 <at>  <at>  -1040,15 +1040,15  <at>  <at>  xendump_memory_dump(FILE *fp)
 	fprintf(fp, "             xch_nr_pages: %d (0x%x)\n",
 		xd->xc_core.header.xch_nr_pages,
 		xd->xc_core.header.xch_nr_pages);
-	fprintf(fp, "          xch_ctxt_offset: %ld (0x%lx)\n", 
-		xd->xc_core.header.xch_ctxt_offset,
-		xd->xc_core.header.xch_ctxt_offset);
-	fprintf(fp, "         xch_index_offset: %ld (0x%lx)\n",
-		xd->xc_core.header.xch_index_offset,
-		xd->xc_core.header.xch_index_offset);
-	fprintf(fp, "         xch_pages_offset: %ld (0x%lx)\n",
-		xd->xc_core.header.xch_pages_offset,
-		xd->xc_core.header.xch_pages_offset);
+	fprintf(fp, "          xch_ctxt_offset: %llu (0x%llx)\n",
+		(ulonglong)xd->xc_core.header.xch_ctxt_offset,
+		(ulonglong)xd->xc_core.header.xch_ctxt_offset);
+	fprintf(fp, "         xch_index_offset: %llu (0x%llx)\n",
+		(ulonglong)xd->xc_core.header.xch_index_offset,
+		(ulonglong)xd->xc_core.header.xch_index_offset);
+	fprintf(fp, "         xch_pages_offset: %llu (0x%llx)\n",
+		(ulonglong)xd->xc_core.header.xch_pages_offset,
+		(ulonglong)xd->xc_core.header.xch_pages_offset);

 	fprintf(fp, "                elf_class: %s\n", xd->xc_core.elf_class == ELFCLASS64 ? "ELFCLASS64" :
 		xd->xc_core.elf_class == ELFCLASS32 ? "ELFCLASS32" : "n/a");
 <at>  <at>  -1285,7 +1285,7  <at>  <at>  xc_core_mfn_to_page(ulong mfn, char *pgbuf)
 	if (xd->flags & XC_CORE_ELF)
 		return xc_core_elf_mfn_to_page(mfn, pgbuf);

-        if (lseek(xd->xfd, (off_t)xd->xc_core.header.xch_index_offset,
+        if (lseek(xd->xfd, xd->xc_core.header.xch_index_offset,
             SEEK_SET) == -1) {
                 error(INFO, "cannot lseek to page index\n");
 		return NULL;
 <at>  <at>  -1325,7 +1325,7  <at>  <at>  xc_core_mfn_to_page(ulong mfn, char *pgbuf)
 		return NULL;
 	}

-        if (lseek(xd->xfd, (off_t)xd->xc_core.header.xch_pages_offset,
+        if (lseek(xd->xfd, xd->xc_core.header.xch_pages_offset,
             SEEK_SET) == -1) {
                 error(INFO, "cannot lseek to xch_pages_offset\n");
 		return NULL;
 <at>  <at>  -1400,7 +1400,7  <at>  <at>  xc_core_elf_mfn_to_page(ulong mfn, char *pgbuf)
 		return NULL;
 	}

-        if (lseek(xd->xfd, (off_t)xd->xc_core.header.xch_pages_offset,
+        if (lseek(xd->xfd, xd->xc_core.header.xch_pages_offset,
             SEEK_SET) == -1)
                 error(FATAL, "cannot lseek to xch_pages_offset\n");

 <at>  <at>  -1434,7 +1434,7  <at>  <at>  xc_core_mfn_to_page_index(ulong mfn)
 	if (xd->flags & XC_CORE_ELF)
 		return xc_core_elf_mfn_to_page_index(mfn);

-        if (lseek(xd->xfd, (off_t)xd->xc_core.header.xch_index_offset,
+        if (lseek(xd->xfd, xd->xc_core.header.xch_index_offset,
             SEEK_SET) == -1) {
                 error(INFO, "cannot lseek to page index\n");
                 return MFN_NOT_FOUND;
 <at>  <at>  -1527,7 +1527,7  <at>  <at>  xc_core_mfns(ulong arg, FILE *ofp)
         ulonglong tmp64[MAX_BATCH_SIZE];
 	size_t size;

-        if (lseek(xd->xfd, (off_t)xd->xc_core.header.xch_index_offset,
+        if (lseek(xd->xfd, xd->xc_core.header.xch_index_offset,
             SEEK_SET) == -1) {
                 error(INFO, "cannot lseek to page index\n");
 		return FALSE;
 <at>  <at>  -1677,7 +1677,7  <at>  <at>  xc_core_pfn_to_page_index(ulong pfn)

 	p2m_idx = xd->xc_core.p2m_frame_index_list[idx];

-	if (lseek(xd->xfd, (off_t)xd->xc_core.header.xch_pages_offset,
+	if (lseek(xd->xfd, xd->xc_core.header.xch_pages_offset,
             SEEK_SET) == -1) {
                 error(INFO, "cannot lseek to xch_pages_offset\n");
                 return PFN_NOT_FOUND;
 <at>  <at>  -1801,7 +1801,7  <at>  <at>  xc_core_pfn_valid(ulong pfn)
 	if (pfn >= (ulong)xd->xc_core.header.xch_nr_pages)
 		return FALSE;

-        offset = (off_t)xd->xc_core.header.xch_index_offset;
+        offset = xd->xc_core.header.xch_index_offset;

 	if (xd->flags & XC_CORE_64BIT_HOST)
 		offset += (off_t)(pfn * sizeof(ulonglong));
 <at>  <at>  -2542,25 +2542,27  <at>  <at>  xc_core_dump_Elf32_Shdr(Elf32_Off offset, int store)
 		return;

 	if (STREQ(name, ".xen_prstatus"))
-		xd->xc_core.header.xch_ctxt_offset = 
-			(unsigned long)shdr.sh_offset;
+		xd->xc_core.header.xch_ctxt_offset =
+			(off_t)shdr.sh_offset;

 	if (STREQ(name, ".xen_shared_info"))
 		xd->xc_core.shared_info_offset = (off_t)shdr.sh_offset;

 	if (STREQ(name, ".xen_pfn")) {
-		xd->xc_core.header.xch_index_offset = shdr.sh_offset;
+		xd->xc_core.header.xch_index_offset =
+			(off_t)shdr.sh_offset;
 		xd->flags |= (XC_CORE_NO_P2M|XC_CORE_PFN_CREATE);
 	}

 	if (STREQ(name, ".xen_p2m")) {
-		xd->xc_core.header.xch_index_offset = shdr.sh_offset;
+		xd->xc_core.header.xch_index_offset =
+			(off_t)shdr.sh_offset;
 		xd->flags |= XC_CORE_P2M_CREATE;
 	}

 	if (STREQ(name, ".xen_pages"))
-		xd->xc_core.header.xch_pages_offset = 
-			(unsigned long)shdr.sh_offset;
+		xd->xc_core.header.xch_pages_offset =
+			(off_t)shdr.sh_offset;

 	if (STREQ(name, ".xen_ia64_mapped_regs"))
 		xd->xc_core.ia64_mapped_regs_offset = 
 <at>  <at>  -2642,25 +2644,27  <at>  <at>  xc_core_dump_Elf64_Shdr(Elf64_Off offset, int store)
 		return;

 	if (STREQ(name, ".xen_prstatus"))
-		xd->xc_core.header.xch_ctxt_offset = 
-			(unsigned long)shdr.sh_offset;
+		xd->xc_core.header.xch_ctxt_offset =
+			(off_t)shdr.sh_offset;

 	if (STREQ(name, ".xen_shared_info"))
 		xd->xc_core.shared_info_offset = (off_t)shdr.sh_offset;

 	if (STREQ(name, ".xen_pfn")) {
-		xd->xc_core.header.xch_index_offset = shdr.sh_offset;
+		xd->xc_core.header.xch_index_offset =
+			(off_t)shdr.sh_offset;
 		xd->flags |= (XC_CORE_NO_P2M|XC_CORE_PFN_CREATE);
 	}

 	if (STREQ(name, ".xen_p2m")) {
-		xd->xc_core.header.xch_index_offset = shdr.sh_offset;
+		xd->xc_core.header.xch_index_offset =
+			(off_t)shdr.sh_offset;
 		xd->flags |= XC_CORE_P2M_CREATE;
 	}

 	if (STREQ(name, ".xen_pages"))
-		xd->xc_core.header.xch_pages_offset = 
-			(unsigned long)shdr.sh_offset;
+		xd->xc_core.header.xch_pages_offset =
+			(off_t)shdr.sh_offset;

 	if (STREQ(name, ".xen_ia64_mapped_regs"))
 		xd->xc_core.ia64_mapped_regs_offset = 
 <at>  <at>  -2814,7 +2818,7  <at>  <at>  xc_core_elf_pfn_init(void)
 		chunk = xd->xc_core.header.xch_nr_pages/INDEX_PFN_COUNT;

 		for (i = c = 0; i < INDEX_PFN_COUNT; i++, c += chunk) {
-			offset = (off_t)xd->xc_core.header.xch_index_offset +
+			offset = xd->xc_core.header.xch_index_offset +
 				(off_t)(c * sizeof(uint64_t));

 	        	if (lseek(xd->xfd, offset, SEEK_SET) == -1)
 <at>  <at>  -2834,7 +2838,7  <at>  <at>  xc_core_elf_pfn_init(void)
 		chunk = xd->xc_core.header.xch_nr_pages/INDEX_PFN_COUNT;
 	
 		for (i = c = 0; i < INDEX_PFN_COUNT; i++, c += chunk) {
-			offset = (off_t)xd->xc_core.header.xch_index_offset +
+			offset = xd->xc_core.header.xch_index_offset +
 				(off_t)(c * sizeof(struct xen_dumpcore_p2m));

 	        	if (lseek(xd->xfd, offset, SEEK_SET) == -1)
diff --git a/xendump.h b/xendump.h
index 9ece4da..17aae37 100644
--- a/xendump.h
+++ b/xendump.h
 <at>  <at>  -42,9 +42,9  <at>  <at>  struct xen_core_header {
     unsigned int xch_magic;
     unsigned int xch_nr_vcpus;
     unsigned int xch_nr_pages;
-    unsigned long xch_ctxt_offset;
-    unsigned long xch_index_offset;
-    unsigned long xch_pages_offset;
+    off_t xch_ctxt_offset;
+    off_t xch_index_offset;
+    off_t xch_pages_offset;
 };

 struct pfn_offset_cache {
--

-- 
1.8.4


Gmane