Re: [PATCH] files: support dump file page cache

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

 



Sorry,Ijust realized that my email setting is not correct.

Resend patch file here.

Dave,

This patch add -M and -m option for file commands, which allow to dump
page cache for a file.

Please review and let me know your comments. Thanks!

Here is the usage,

1. Dump a process page cache number, default is crash, also work with given pid,

crash> files -M

PID: 22710  TASK: ffff8801077153e0  CPU: 1   COMMAND: "crash"

ROOT: /    CWD: /auto/home2/yango/workspace/crash

FD    ADDR-SPACE      PGCACHE-PGS         INODE       TYPE PATH

   0 ffff8801031edbe8         0        ffff8801031edaa0 CHR  /2

   1 ffff8801031edbe8         0        ffff8801031edaa0 CHR  /2

   2 ffff8801031edbe8         0        ffff8801031edaa0 CHR  /2

   3 ffff880139bf8950         0        ffff880139bf8808 CHR  /null

   4 ffff88011e561390         0        ffff88011e561248 CHR  /crash

   5 ffff88012f8345f0       37910      ffff88012f8344a8 REG
/usr/lib/debug/lib/modules/3.11.10-301.fc20.x86_64/vmlinux

   [snipped..........................]


2. Dump pages in a given addr-space, this exmaple is ffff88012f8345f0
from above output.
     page flags could indicates the dirty pages for fsync stress debugging,

crash> files -m ffff88012f8345f0

Address Space ffff88012f8345f0 : 37910 pages in page cache

       PAGE       PHYSICAL      MAPPING       INDEX CNT FLAGS

ffffea0001f5bc40 7d6f1000 ffff88012f8345f0        0  2 3ff0000000086c
referenced,uptodate,lru,active,private

ffffea0001f5bc80 7d6f2000 ffff88012f8345f0        1  2 3ff0000000082c
referenced,uptodate,lru,private

..............................[snipped...].........................................................................

ffffea00016226c0 5889b000 ffff88012f8345f0     9414  2 3ff0000000086c
referenced,uptodate,lru,active,private

ffffea000224f480 893d2000 ffff88012f8345f0     9415  2 3ff0000000086c
referenced,uptodate,lru,active,private

3. For each files doesn't work with -m but it work with -M

crash> foreach files -m

foreach: foreach files command does not support -m option

So we can use foreach to find which process or files have most page
cache number,

crash> foreach files -M | grep REG | sort -k3 -n | tail -10

20 ffff880137a70be0         2        ffff880137a70a98 REG  /ffinLFoAy

   4 ffff880037630de0        131       ffff880037630c98 REG
/var/log/audit/audit.log

   4 ffff880037630de0        131       ffff880037630c98 REG
/var/log/audit/audit.log

36 ffff8801352e91d8        574       ffff8801352e9090 REG
/var/log/journal/2d6f0d3073ff4a60b1e52a8e38e48feb/user-530.journal

34 ffff8801352e81f8        590       ffff8801352e80b0 REG
/var/log/journal/2d6f0d3073ff4a60b1e52a8e38e48feb/user-42.journal

   5 ffff8800a90219c8       9816       ffff8800a9021880 REG
/usr/lib/debug/lib/modules/3.11.10-301.fc20.x86_64/vmlinux

13 ffff880135267198       14051      ffff880135267050 REG
/var/log/journal/2d6f0d3073ff4a60b1e52a8e38e48feb/system.journal

   5 ffff88012f8345f0       37910      ffff88012f8344a8 REG
/usr/lib/debug/lib/modules/3.11.10-301.fc20.x86_64/vmlinux

   1 ffff8800704f3d80       59468      ffff8800704f3c38 REG
/ws/irqstat/nohup.out

   2 ffff8800704f3d80       59468      ffff8800704f3c38 REG
/ws/irqstat/nohup.out


With these commands, we can easily to debug some page cache flush
stress issue, and find out which process or files had the problem.



From 759d4f4cdedf4c6b2a4f0f914253f3e147950db5 Mon Sep 17 00:00:00 2001
From: Yong Yang <yangoliver@xxxxxxxxx>
Date: Sat, 13 Jun 2015 04:45:14 +0800
Subject: [PATCH] files: support dump file page caches

Added two options in files command,

1. -M option, which allows dump page cache number for each files
2. -m option, which could dump each pages in given address mapping

The foreach command also could work with -M, so that we can easily
find which process hold most page cache pages within the system.

Signed-off-by: Yong Yang <yangoliver@xxxxxxxxx>
---
 defs.h    |  3 +++
 filesys.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++--------------
 memory.c  | 50 +++++++++++++++++++++++++++++++++++++
 task.c    | 25 ++++++++++++++++---
 4 files changed, 140 insertions(+), 22 deletions(-)

diff --git a/defs.h b/defs.h
index d2a8215..048c248 100644
--- a/defs.h
+++ b/defs.h
@@ -1111,6 +1111,7 @@ extern struct machdep_table *machdep;
 #define FOREACH_a_FLAG   (0x4000000)
 #define FOREACH_G_FLAG   (0x8000000)
 #define FOREACH_F_FLAG2 (0x10000000)
+#define FOREACH_M_FLAG  (0x20000000)
 
 #define FOREACH_PS_EXCLUSIVE \
   (FOREACH_g_FLAG|FOREACH_a_FLAG|FOREACH_t_FLAG|FOREACH_c_FLAG|FOREACH_p_FLAG|FOREACH_l_FLAG|FOREACH_r_FLAG|FOREACH_m_FLAG)
@@ -2598,6 +2599,7 @@ struct load_module {
 #define PRINT_SINGLE_VMA  (0x80)
 #define PRINT_RADIX_10   (0x100)
 #define PRINT_RADIX_16   (0x200)
+#define PRINT_PAGES      (0x400)
 
 #define MIN_PAGE_SIZE  (4096)
 
@@ -4769,6 +4771,7 @@ int file_dump(ulong, ulong, ulong, int, int);
 #define DUMP_INODE_ONLY  2
 #define DUMP_DENTRY_ONLY 4
 #define DUMP_EMPTY_FILE  8
+#define DUMP_FILE_PAGE   16
 #endif  /* !GDB_COMMON */
 int same_file(char *, char *);
 #ifndef GDB_COMMON
diff --git a/filesys.c b/filesys.c
index 0573fe6..da8c930 100644
--- a/filesys.c
+++ b/filesys.c
@@ -2187,11 +2187,12 @@ cmd_files(void)
 	int subsequent;
 	struct reference reference, *ref;
 	char *refarg;
+	int open_flags = 0;
 
         ref = NULL;
         refarg = NULL;
 
-        while ((c = getopt(argcnt, args, "d:R:")) != EOF) {
+        while ((c = getopt(argcnt, args, "d:R:m:M")) != EOF) {
                 switch(c)
 		{
 		case 'R':
@@ -2209,7 +2210,13 @@ cmd_files(void)
 			value = htol(optarg, FAULT_ON_ERROR, NULL);
 			display_dentry_info(value);
 			return;
-
+		case 'm':
+			value = htol(optarg, FAULT_ON_ERROR, NULL);
+			dump_file_address_mappings(value);
+			return;
+		case 'M':
+			open_flags |= PRINT_PAGES;
+			break;
 		default:
 			argerrs++;
 			break;
@@ -2222,7 +2229,9 @@ cmd_files(void)
 	if (!args[optind]) {
 		if (!ref)
 			print_task_header(fp, CURRENT_CONTEXT(), 0);
-		open_files_dump(CURRENT_TASK(), 0, ref);
+
+		open_files_dump(CURRENT_TASK(), open_flags, ref);
+
 		return;
 	}
 
@@ -2241,7 +2250,7 @@ cmd_files(void)
                         for (tc = pid_to_context(value); tc; tc = tc->tc_next) {
                                 if (!ref)
                                         print_task_header(fp, tc, subsequent);
-                                open_files_dump(tc->task, 0, ref);
+                                open_files_dump(tc->task, open_flags, ref);
                                 fprintf(fp, "\n");
                         }
                         break;
@@ -2249,7 +2258,7 @@ cmd_files(void)
                 case STR_TASK:
                         if (!ref)
                                 print_task_header(fp, tc, subsequent);
-                        open_files_dump(tc->task, 0, ref);
+                        open_files_dump(tc->task, open_flags, ref);
                         break;
 
                 case STR_INVALID:
@@ -2321,6 +2330,7 @@ open_files_dump(ulong task, int flags, struct reference *ref)
 	char buf4[BUFSIZE];
 	char root_pwd[BUFSIZE];
 	int root_pwd_printed = 0;
+	int file_dump_flags = 0;
 
 	BZERO(root_pathname, BUFSIZE);
 	BZERO(pwd_pathname, BUFSIZE);
@@ -2329,15 +2339,27 @@ open_files_dump(ulong task, int flags, struct reference *ref)
 		fdtable_buf = GETBUF(SIZE(fdtable));
 	fill_task_struct(task);
 
-	sprintf(files_header, " FD%s%s%s%s%s%s%sTYPE%sPATH\n",
-		space(MINSPACE),
-		mkstring(buf1, VADDR_PRLEN, CENTER|LJUST, "FILE"),
-		space(MINSPACE),
-		mkstring(buf2, VADDR_PRLEN, CENTER|LJUST, "DENTRY"),
-		space(MINSPACE),
-		mkstring(buf3, VADDR_PRLEN, CENTER|LJUST, "INODE"),
-		space(MINSPACE),
-		space(MINSPACE));
+	if (flags & PRINT_PAGES) {
+		sprintf(files_header, " FD%s%s%s%s%s%s%sTYPE%sPATH\n",
+			space(MINSPACE),
+			mkstring(buf1, VADDR_PRLEN, CENTER|LJUST, "ADDR-SPACE"),
+			space(MINSPACE),
+			mkstring(buf2, VADDR_PRLEN, CENTER|LJUST, "PGCACHE-PGS"),
+			space(MINSPACE),
+			mkstring(buf3, VADDR_PRLEN, CENTER|LJUST, "INODE"),
+			space(MINSPACE),
+			space(MINSPACE));
+	} else {
+		sprintf(files_header, " FD%s%s%s%s%s%s%sTYPE%sPATH\n",
+			space(MINSPACE),
+			mkstring(buf1, VADDR_PRLEN, CENTER|LJUST, "FILE"),
+			space(MINSPACE),
+			mkstring(buf2, VADDR_PRLEN, CENTER|LJUST, "DENTRY"),
+			space(MINSPACE),
+			mkstring(buf3, VADDR_PRLEN, CENTER|LJUST, "INODE"),
+			space(MINSPACE),
+			space(MINSPACE));
+	}
 
 	tc = task_to_context(task);
 
@@ -2523,6 +2545,9 @@ open_files_dump(ulong task, int flags, struct reference *ref)
 		return;
 	}
 
+	file_dump_flags = flags & PRINT_PAGES ?
+	    DUMP_FILE_PAGE : (DUMP_FULL_NAME|DUMP_EMPTY_FILE);
+
 	j = 0;
 	for (;;) {
 		unsigned long set;
@@ -2539,8 +2564,7 @@ open_files_dump(ulong task, int flags, struct reference *ref)
 
 				if (ref && file) {
 					open_tmpfile();
-                                        if (file_dump(file, 0, 0, i,
-                                            DUMP_FULL_NAME|DUMP_EMPTY_FILE)) {
+                                        if (file_dump(file, 0, 0, i, file_dump_flags)) {
 						BZERO(buf4, BUFSIZE);
 						rewind(pc->tmpfile);
 						ret = fgets(buf4, BUFSIZE, 
@@ -2558,8 +2582,7 @@ open_files_dump(ulong task, int flags, struct reference *ref)
 						fprintf(fp, "%s", files_header);
 						header_printed = 1;
 					}
-					file_dump(file, 0, 0, i, 
-						DUMP_FULL_NAME|DUMP_EMPTY_FILE);
+					file_dump(file, 0, 0, i, file_dump_flags);
 				}
 			}
 			i++;
@@ -2754,6 +2777,8 @@ file_dump(ulong file, ulong dentry, ulong inode, int fd, int flags)
 	char buf1[BUFSIZE];
 	char buf2[BUFSIZE];
 	char buf3[BUFSIZE];
+	ulong i_mapping = 0;
+	ulong count = 0;
 
 	file_buf = NULL;
 
@@ -2863,6 +2888,29 @@ file_dump(ulong file, ulong dentry, ulong inode, int fd, int flags)
 				type, 
 				space(MINSPACE),
 				pathname+1);
+		} else if (flags & DUMP_FILE_PAGE) {
+
+			i_mapping = ULONG(inode_buf + OFFSET(inode_i_mapping));
+			count = get_page_tree_count(i_mapping);
+
+                        fprintf(fp, "%3d%s%s%s%s%s%s%s%s%s%s\n",
+                                fd,
+                                space(MINSPACE),
+				mkstring(buf1, VADDR_PRLEN,
+				CENTER|RJUST|LONG_HEX,
+				MKSTR(i_mapping)),
+                                space(MINSPACE),
+				mkstring(buf2, VADDR_PRLEN,
+				CENTER|RJUST|LONG_DEC,
+				MKSTR(count)),
+                                space(MINSPACE),
+				mkstring(buf3, VADDR_PRLEN,
+				CENTER|RJUST|LONG_HEX,
+				MKSTR(inode)),
+                                space(MINSPACE),
+                                type,
+                                space(MINSPACE),
+                                pathname);
 		} else {
                         fprintf(fp, "%3d%s%s%s%s%s%s%s%s%s%s\n",
                                 fd,
diff --git a/memory.c b/memory.c
index 700cbf4..def29a0 100644
--- a/memory.c
+++ b/memory.c
@@ -132,6 +132,7 @@ struct searchinfo {
 	char buf[BUFSIZE];
 };
 
+void dump_file_address_mappings(ulong);
 static char *memtype_string(int, int);
 static char *error_handle_string(ulong);
 static void dump_mem_map(struct meminfo *);
@@ -6161,6 +6162,55 @@ translate_page_flags(char *buffer, ulong flags)
 }
 
 /*
+ * The address space file mapping radix tree walker.
+ */
+void
+dump_file_address_mappings(ulong i_mapping)
+{
+	ulong radix_tree_rnode;
+	ulong root_rnode;
+	ulong index, count, ret;
+	struct radix_tree_pair rtp;
+	struct meminfo meminfo;
+
+
+	root_rnode = i_mapping + OFFSET(radix_tree_root_rnode);
+
+	count = do_radix_tree(root_rnode, RADIX_TREE_COUNT, NULL);
+
+	fprintf(fp,
+	    "Address Space %lx : %ld pages in page cache\n\n", i_mapping, count);
+
+	/* Now walk the tree, counting all the pages in the tree */
+	for (index = 0; index <= count; index++) {
+		rtp.index = index;
+	        if (do_radix_tree(root_rnode, RADIX_TREE_SEARCH, &rtp)) {
+			meminfo.spec_addr = (ulong)rtp.value;
+			meminfo.memtype = KVADDR;
+			meminfo.flags = ADDRESS_SPECIFIED;
+			dump_mem_map_SPARSEMEM(&meminfo);
+		}
+	}
+
+	return;
+}
+
+/* Get the page count for the specific mapping */
+long
+get_page_tree_count(ulong i_mapping)
+{
+	ulong   radix_tree_rnode;
+	ulong	root_rnode;
+	ulong   count;
+
+	root_rnode = i_mapping + OFFSET(radix_tree_root_rnode);
+
+	count = do_radix_tree(root_rnode, RADIX_TREE_COUNT, NULL);
+
+	return count;
+}
+
+/*
  *  dump_page_hash_table() displays the entries in each page_hash_table.
  */
 
diff --git a/task.c b/task.c
index bc7911b..6e8d7e6 100644
--- a/task.c
+++ b/task.c
@@ -5601,7 +5601,7 @@ cmd_foreach(void)
 	BZERO(&foreach_data, sizeof(struct foreach_data));
 	fd = &foreach_data;
 
-        while ((c = getopt(argcnt, args, "R:vomlgersStTpukcfFxhdaG")) != EOF) {
+        while ((c = getopt(argcnt, args, "R:vomMlgersStTpukcfFxhdaG")) != EOF) {
                 switch(c)
 		{
 		case 'R':
@@ -5625,6 +5625,10 @@ cmd_foreach(void)
 			fd->flags |= FOREACH_m_FLAG;
 			break;
 
+		case 'M':
+			fd->flags |= FOREACH_M_FLAG;
+			break;
+
 		case 'l':
 			fd->flags |= FOREACH_l_FLAG;
 			break;
@@ -6129,6 +6133,13 @@ foreach(struct foreach_data *fd)
 			print_header = FALSE;
 			break;
 
+		case FOREACH_FILES:
+			if (fd->flags & FOREACH_m_FLAG)
+				error(FATAL,
+				    "foreach files command does not "
+				    "support -m option\n");
+			break;
+
 		case FOREACH_TEST:
 			break;
 		}
@@ -6355,9 +6366,15 @@ foreach(struct foreach_data *fd)
 
 			case FOREACH_FILES:
 				pc->curcmd = "files";
-				open_files_dump(tc->task, 
-					fd->flags & FOREACH_i_FLAG ?
-					PRINT_INODES : 0, 
+				cmdflags = 0;
+
+				if (fd->flags & FOREACH_i_FLAG)
+					cmdflags |= PRINT_INODES;
+				if (fd->flags & FOREACH_M_FLAG)
+					cmdflags |= PRINT_PAGES;
+
+				open_files_dump(tc->task,
+					cmdflags,
 					fd->reference ? ref : NULL);
 				break;
 
-- 
1.9.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