----- Original Message ----- > Hello Dave, > > > I have modified the patch by your idea. > > Please check. > > Thanks, > Pan Hello Pan, Thanks for updating this latest patch -- nice work! I have made a few changes: (1) a few name changes for clarity's sake, (2) moved the new task_table members to the end of the structure so as to not break extension modules that use it, (3) fixed the malloc() memory leak in get_task_mem_usage(), (4) fixed the access of the tgid in store_context(), which needs to be accessed and stored as a pid_t and not a ulong, (5) added the "help -T" output to show the new fields in the task_table, (6) and probably some other stuff that I've forgotten... But for the most part I have left things functionally the same. I've attached the end result, and will continue testing it tomorrow. Thanks, Dave
--- main.c.orig 2014-07-31 14:35:05.941461775 -0400 +++ main.c 2014-09-09 15:47:09.250993934 -0400 @@ -800,6 +800,7 @@ reattempt: } else if (!(pc->flags & MINIMAL_MODE)) { tt->refresh_task_table(); sort_context_array(); + sort_tgid_array(); } } if (!STREQ(pc->curcmd, pc->program_name)) --- memory.c.orig 2014-09-04 16:48:14.430966493 -0400 +++ memory.c 2014-09-09 16:32:13.103886795 -0400 @@ -225,6 +225,7 @@ static int next_module_vaddr(ulong, ulon static int next_identity_mapping(ulong, ulong *); static int vm_area_page_dump(ulong, ulong, ulong, ulong, ulong, struct reference *); +static void rss_page_types_init(void); static int dump_swap_info(ulong, ulong *, ulong *); static void swap_info_init(void); static char *get_swapdev(ulong, char *); @@ -1070,6 +1071,8 @@ vm_init(void) page_flags_init(); + rss_page_types_init(); + vt->flags |= VM_INIT; } @@ -4076,6 +4079,31 @@ in_user_stack(ulong task, ulong vaddr) } /* + * Set the const value of filepages and anonpages + * according to MM_FILEPAGES and MM_ANONPAGES. + */ +void +rss_page_types_init(void) +{ + long anonpages, filepages; + + if (VALID_MEMBER(mm_struct_rss)) + return; + + if (VALID_MEMBER(mm_struct_rss_stat)) + { + if (!enumerator_value("MM_FILEPAGES", &filepages) || + !enumerator_value("MM_ANONPAGES", &anonpages)) + { + filepages = 0; + anonpages = 1; + } + tt->filepages = filepages; + tt->anonpages = anonpages; + } +} + +/* * Fill in the task_mem_usage structure with the RSS, virtual memory size, * percent of physical memory being used, and the mm_struct address. */ @@ -4112,11 +4140,8 @@ get_task_mem_usage(ulong task, struct ta if (VALID_MEMBER(mm_struct_rss_stat)) { long anonpages, filepages; - if (!enumerator_value("MM_FILEPAGES", &filepages) || - !enumerator_value("MM_ANONPAGES", &anonpages)) { - filepages = 0; - anonpages = 1; - } + anonpages = tt->anonpages; + filepages = tt->filepages; rss += LONG(tt->mm_struct + OFFSET(mm_struct_rss_stat) + OFFSET(mm_rss_stat_count) + @@ -4129,19 +4154,33 @@ get_task_mem_usage(ulong task, struct ta /* Check whether SPLIT_RSS_COUNTING is enabled */ if (VALID_MEMBER(task_struct_rss_stat)) { - int i, sync_rss; - ulong tgid; - struct task_context *tc1; - - tgid = task_tgid(task); - - tc1 = FIRST_CONTEXT(); - for (i = 0; i < RUNNING_TASKS(); i++, tc1++) { - if (task_tgid(tc1->task) != tgid) - continue; + int sync_rss; + struct tgid_context tgid, *tgid_array, *tg, *first, *last; + tgid_array = tt->tgid_array; + tgid.tgid = task_tgid(task); + + tg = (struct tgid_context *)bsearch(&tgid, tgid_array, RUNNING_TASKS(), + sizeof(struct tgid_context), sort_by_tgid); + if (tg == NULL) + error(FATAL, "bsearch for tgid failed: task: %lx tgid: %ld\n", + task, tgid.tgid); + + /* find the first element which has the same tgid */ + first = tg; + while ((first > tgid_array) && ((first - 1)->tgid == first->tgid)) + first--; + + /* find the last element which have same tgid */ + last = tg; + while ((last < (tgid_array + (RUNNING_TASKS() - 1))) && + (last->tgid == (last + 1)->tgid)) + last++; + + while (first <= last) + { /* count 0 -> filepages */ - if (!readmem(tc1->task + + if (!readmem(first->task + OFFSET(task_struct_rss_stat) + OFFSET(task_rss_stat_count), KVADDR, &sync_rss, @@ -4153,7 +4192,7 @@ get_task_mem_usage(ulong task, struct ta rss += sync_rss; /* count 1 -> anonpages */ - if (!readmem(tc1->task + + if (!readmem(first->task + OFFSET(task_struct_rss_stat) + OFFSET(task_rss_stat_count) + sizeof(int), @@ -4164,6 +4203,10 @@ get_task_mem_usage(ulong task, struct ta continue; rss += sync_rss; + + if(first == last) + break; + first++; } } --- task.c.orig 2014-06-02 17:13:47.298954087 -0400 +++ task.c 2014-09-09 16:46:11.751853564 -0400 @@ -493,6 +493,7 @@ task_init(void) } sort_context_array(); + sort_tgid_array(); if (pc->flags & SILENT) initialize_task_state(); @@ -639,6 +640,11 @@ allocate_task_space(int cnt) malloc(cnt * sizeof(struct task_context)))) error(FATAL, "cannot malloc context array (%d tasks)", cnt); + if (!(tt->tgid_array = (struct tgid_context *) + malloc(cnt * sizeof(struct tgid_context)))) + error(FATAL, "cannot malloc tgid array (%d tasks)", + cnt); + } else { if (!(tt->task_local = (void *) realloc(tt->task_local, cnt * sizeof(void *)))) @@ -652,6 +658,13 @@ allocate_task_space(int cnt) error(FATAL, "%scannot realloc context array (%d tasks)", (pc->flags & RUNTIME) ? "" : "\n", cnt); + + if (!(tt->tgid_array = (struct tgid_context *) + realloc(tt->tgid_array, + cnt * sizeof(struct tgid_context)))) + error(FATAL, + "%scannot realloc tgid array (%d tasks)", + (pc->flags & RUNTIME) ? "" : "\n", cnt); } } @@ -2276,13 +2289,14 @@ retry_active: static struct task_context * store_context(struct task_context *tc, ulong task, char *tp) { - pid_t *pid_addr; + pid_t *pid_addr, *tgid_addr; char *comm_addr; int *processor_addr; ulong *parent_addr; ulong *mm_addr; int has_cpu; int do_verify; + struct tgid_context *tg; processor_addr = NULL; @@ -2305,6 +2319,7 @@ store_context(struct task_context *tc, u tc = tt->context_array + tt->running_tasks; pid_addr = (pid_t *)(tp + OFFSET(task_struct_pid)); + tgid_addr = (pid_t *)(tp + OFFSET(task_struct_tgid)); comm_addr = (char *)(tp + OFFSET(task_struct_comm)); if (tt->flags & THREAD_INFO) { tc->thread_info = ULONG(tp + OFFSET(task_struct_thread_info)); @@ -2330,6 +2345,14 @@ store_context(struct task_context *tc, u tc->task = task; tc->tc_next = NULL; + /* + * Fill a tgid_context structure with the data from + * the incoming task. + */ + tg = tt->tgid_array + tt->running_tasks; + tg->tgid = *tgid_addr; + tg->task = task; + if (do_verify && !verify_task(tc, do_verify)) { error(INFO, "invalid task address: %lx\n", tc->task); BZERO(tc, sizeof(struct task_context)); @@ -2445,6 +2468,31 @@ sort_context_array_by_last_run(void) } /* + * Set the tgid_context array by tgid number. + */ +void +sort_tgid_array(void) +{ + if (VALID_MEMBER(mm_struct_rss) || (!VALID_MEMBER(task_struct_rss_stat))) + return; + + qsort((void *)tt->tgid_array, (size_t)tt->running_tasks, + sizeof(struct tgid_context), sort_by_tgid); +} + +int +sort_by_tgid(const void *arg1, const void *arg2) +{ + struct tgid_context *t1, *t2; + + t1 = (struct tgid_context *)arg1; + t2 = (struct tgid_context *)arg2; + + return (t1->tgid < t2->tgid ? -1 : + t1->tgid == t2->tgid ? 0 : 1); +} + +/* * Keep a stash of the last task_struct accessed. Chances are it will * be hit several times before the next task is accessed. */ @@ -6557,6 +6605,7 @@ dump_task_table(int verbose) { int i, j, more, nr_cpus; struct task_context *tc; + struct tgid_context *tg; char buf[BUFSIZE]; int others, wrap, flen; @@ -6577,6 +6626,7 @@ dump_task_table(int verbose) fprintf(fp, " .tc_next: %lx\n", (ulong)tc->tc_next); } fprintf(fp, " context_array: %lx\n", (ulong)tt->context_array); + fprintf(fp, " tgid_array: %lx\n", (ulong)tt->tgid_array); fprintf(fp, "refresh_task_table: "); if (tt->refresh_task_table == refresh_fixed_task_table) fprintf(fp, "refresh_fixed_task_table()\n"); @@ -6671,6 +6721,8 @@ dump_task_table(int verbose) fprintf(fp, " task_struct: %lx\n", (ulong)tt->task_struct); fprintf(fp, " mm_struct: %lx\n", (ulong)tt->mm_struct); fprintf(fp, " init_pid_ns: %lx\n", tt->init_pid_ns); + fprintf(fp, " filepages: %ld\n", tt->filepages); + fprintf(fp, " anonpages: %ld\n", tt->anonpages); wrap = sizeof(void *) == SIZEOF_32BIT ? 8 : 4; @@ -6886,6 +6938,13 @@ dump_task_table(int verbose) i, tc->task, tc->pid, tc->processor, tc->ptask, (ulong)tc->mm_struct, tc->comm); } + + fprintf(fp, "\nINDEX TASK TGID (COMM)\n"); + for (i = 0; i < RUNNING_TASKS(); i++) { + tg = &tt->tgid_array[i]; + tc = task_to_context(tg->task); + fprintf(fp, "[%3d] %lx %ld (%s)\n", i, tg->task, tg->tgid, tc->comm); + } } /* --- defs.h.orig 2014-07-31 14:35:48.977460276 -0400 +++ defs.h 2014-09-09 15:46:39.315995120 -0400 @@ -762,6 +762,11 @@ struct task_context { struct task_context *tc_next; }; +struct tgid_context { /* tgid and task stored for each task */ + ulong tgid; + ulong task; +}; + struct task_table { /* kernel/local task table data */ struct task_context *current; struct task_context *context_array; @@ -795,6 +800,9 @@ struct task_table { char *thread_info; char *mm_struct; ulong init_pid_ns; + struct tgid_context *tgid_array; + long filepages; + long anonpages; }; #define TASK_INIT_DONE (0x1) @@ -4831,6 +4839,8 @@ ulong generic_get_stackbase(ulong); ulong generic_get_stacktop(ulong); void dump_task_table(int); void sort_context_array(void); +void sort_tgid_array(void); +int sort_by_tgid(const void *, const void *); int in_irq_ctx(ulonglong, int, ulong); /*
-- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility