Add an accounting of amount of stack pages that has been faulted is currently in use. Example use case: $ cat /proc/vmstat | grep stack nr_kernel_stack 18684 nr_dynamic_stacks_faults 156 The above shows that the kernel stacks use total 18684KiB, out of which 156KiB were faulted in. Given that the pre-allocated stacks are 4KiB, we can determine the total number of tasks: tasks = (nr_kernel_stack - nr_dynamic_stacks_faults) / 4 = 4632. The amount of kernel stack memory without dynamic stack on this machine woud be: 4632 * 16 KiB = 74,112 KiB Therefore, in this example dynamic stacks save: 55,428 KiB Signed-off-by: Pasha Tatashin <pasha.tatashin@xxxxxxxxxx> --- include/linux/mmzone.h | 3 +++ kernel/fork.c | 13 ++++++++++++- mm/vmstat.c | 3 +++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index a497f189d988..ba4f1d148c3f 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -198,6 +198,9 @@ enum node_stat_item { NR_FOLL_PIN_ACQUIRED, /* via: pin_user_page(), gup flag: FOLL_PIN */ NR_FOLL_PIN_RELEASED, /* pages returned via unpin_user_page() */ NR_KERNEL_STACK_KB, /* measured in KiB */ +#ifdef CONFIG_DYNAMIC_STACK + NR_DYNAMIC_STACKS_FAULTS_KB, /* KiB of faulted kernel stack memory */ +#endif #if IS_ENABLED(CONFIG_SHADOW_CALL_STACK) NR_KERNEL_SCS_KB, /* measured in KiB */ #endif diff --git a/kernel/fork.c b/kernel/fork.c index 63e1fd661e17..2520583d160a 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -343,6 +343,9 @@ void dynamic_stack_refill_pages(void) mod_lruvec_page_state(page, NR_KERNEL_STACK_KB, PAGE_SIZE / 1024); + mod_lruvec_page_state(page, + NR_DYNAMIC_STACKS_FAULTS_KB, + PAGE_SIZE / 1024); page = alloc_pages(THREADINFO_GFP & ~__GFP_ACCOUNT, 0); if (unlikely(!page)) @@ -771,9 +774,17 @@ static void account_kernel_stack(struct task_struct *tsk, int account) int i, nr_pages; nr_pages = vm->nr_pages; - for (i = 0; i < nr_pages; i++) + for (i = 0; i < nr_pages; i++) { mod_lruvec_page_state(vm->pages[i], NR_KERNEL_STACK_KB, account * (PAGE_SIZE / 1024)); +#ifdef CONFIG_DYNAMIC_STACK + if (i >= THREAD_PREALLOC_PAGES) { + mod_lruvec_page_state(vm->pages[i], + NR_DYNAMIC_STACKS_FAULTS_KB, + account * (PAGE_SIZE / 1024)); + } +#endif + } } else { void *stack = task_stack_page(tsk); diff --git a/mm/vmstat.c b/mm/vmstat.c index db79935e4a54..1ad6eede3d85 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -1237,6 +1237,9 @@ const char * const vmstat_text[] = { "nr_foll_pin_acquired", "nr_foll_pin_released", "nr_kernel_stack", +#ifdef CONFIG_DYNAMIC_STACK + "nr_dynamic_stacks_faults", +#endif #if IS_ENABLED(CONFIG_SHADOW_CALL_STACK) "nr_shadow_call_stack", #endif -- 2.44.0.278.ge034bb2e1d-goog