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