[Crash-utility] [PATCH] files: support dump file page cache
oliver yang
yangoliver at gmail.com
Sat Jun 13 08:39:40 UTC 2015
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.
>
>
-------------- next part --------------
From 759d4f4cdedf4c6b2a4f0f914253f3e147950db5 Mon Sep 17 00:00:00 2001
From: Yong Yang <yangoliver at gmail.com>
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 at gmail.com>
---
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
More information about the Crash-utility
mailing list