ksm: fix ksm module for RHEL6.5 and later

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Dave,

Please check the patch.

--
Regards
Qiao Nuohan
From 3d313aaf5d9fedd91e81ac596fe407614dd57de1 Mon Sep 17 00:00:00 2001
From: Qiao Nuohan <qiaonuohan@xxxxxxxxxxxxxx>
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@xxxxxxxxxxxxxx>
---
 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
@@ -1,6 +1,7 @@
 /*
- * Copyright (C) 2013 FUJITSU LIMITED
+ * Copyright (C) 2013-2014 FUJITSU LIMITED
  * Author: Zhang Yanfei <zhangyanfei@xxxxxxxxxxxxxx>
+ * Signed-off-by: Qiao Nuohan <qiaonuohan@xxxxxxxxxxxxxx>
  *
  * 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
@@ -22,7 +23,7 @@ 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 },
 };
 
@@ -35,7 +36,8 @@ 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))
@@ -50,27 +52,30 @@ 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) { }
 
@@ -139,15 +144,17 @@ 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.",
@@ -159,88 +166,129 @@ 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);
@@ -259,10 +307,6 @@ 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);
@@ -272,41 +316,51 @@ 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;
@@ -315,7 +369,7 @@ 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);
@@ -327,10 +381,16 @@ 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;
@@ -339,6 +399,41 @@ 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

--
Crash-utility mailing list
Crash-utility@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/crash-utility

[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux