From 759d4f4cdedf4c6b2a4f0f914253f3e147950db5 Mon Sep 17 00:00:00 2001 From: Yong Yang 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 --- 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