From 401cb1124bf330e4e7320def30f11ce4cab65022 Mon Sep 17 00:00:00 2001 From: Ning Zhang Date: Mon, 31 May 2021 13:59:42 +0800 Subject: [PATCH 2758/2944] mm, thp: add some statistics for thp reclaim stat fix #34670772 Add split_hugepage and reclaim_subpage in memory.thp_reclaim_stat. split_hugepage shows the huge pages split by thp reclaim. reclaim_subpage shows the zero subpages reclaimed by thp reclaim. Signed-off-by: Ning Zhang Reviewed-by: Gang Deng Reviewed-by: Xu Yu --- Documentation/admin-guide/mm/transhuge.rst | 9 ++++++++- include/linux/mmzone.h | 2 ++ mm/huge_memory.c | 14 ++++++++++---- mm/memcontrol.c | 20 ++++++++++++++++++-- 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/Documentation/admin-guide/mm/transhuge.rst b/Documentation/admin-guide/mm/transhuge.rst index 5333afa..915ea87 100644 --- a/Documentation/admin-guide/mm/transhuge.rst +++ b/Documentation/admin-guide/mm/transhuge.rst @@ -471,7 +471,14 @@ The queue stat can be checked like this:: cat /sys/fs/cgroup/memory/{memcg}/memory.thp_reclaim_stat -Now, it only contains the queue length of each node. +queue_length + means the queue length of each node. + +split_hugepage + means the huge pages split by thp reclaim of each node. + +reclaim_subpage + means the zero subpages reclaimed by thp reclaim of each node. We also add a controller interface to set configs for thp reclaim:: diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 6e9b01b..27ec9ce5 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -653,6 +653,8 @@ struct hugepage_reclaim { spinlock_t reclaim_queue_lock; struct list_head reclaim_queue; unsigned long reclaim_queue_len; + atomic_long_t split_hugepage; + atomic_long_t reclaim_subpage; }; #endif diff --git a/mm/huge_memory.c b/mm/huge_memory.c index ae1b9c8..933c9ee 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3483,9 +3483,12 @@ static struct page *get_reclaim_hugepage(struct hugepage_reclaim *hr_queue, } -static void reclaim_huge_page(struct lruvec *lruvec, struct page *page, int mode) +static void reclaim_huge_page(struct hugepage_reclaim *hr_queue, + struct lruvec *lruvec, struct page *page, + int mode) { struct pglist_data *pgdat = page_pgdat(page); + unsigned long reclaimed; unsigned long flags; LIST_HEAD(split_list); LIST_HEAD(keep_list); @@ -3520,7 +3523,7 @@ static void reclaim_huge_page(struct lruvec *lruvec, struct page *page, int mode unlock_page(page); list_add_tail(&page->lru, &split_list); - reclaim_zero_subpages(&split_list, &keep_list); + reclaimed = reclaim_zero_subpages(&split_list, &keep_list); spin_lock_irqsave(&pgdat->lru_lock, flags); putback_inactive_pages(lruvec, &keep_list); @@ -3530,6 +3533,9 @@ static void reclaim_huge_page(struct lruvec *lruvec, struct page *page, int mode mem_cgroup_uncharge_list(&keep_list); free_unref_page_list(&keep_list); + + atomic_long_inc(&hr_queue->split_hugepage); + atomic_long_add(reclaimed, &hr_queue->reclaim_subpage); break; default: WARN_ONCE(1, "To reclaim a huge page when thp reclaim is disable"); @@ -3570,7 +3576,7 @@ void reclaim_memcg_huge_pages(struct mem_cgroup *memcg) if (!page) continue; - reclaim_huge_page(lruvec, page, thp_reclaim); + reclaim_huge_page(hr_queue, lruvec, page, thp_reclaim); } } @@ -3620,7 +3626,7 @@ static unsigned long hugepage_reclaim_scan(struct shrinker *shrink, if (!page) continue; - reclaim_huge_page(lruvec, page, thp_reclaim); + reclaim_huge_page(hr_queue, lruvec, page, thp_reclaim); } sc->nr_scanned = nr_scanned; diff --git a/mm/memcontrol.c b/mm/memcontrol.c index fce1f01..05bcf67 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -5826,11 +5826,27 @@ static int memcg_thp_reclaim_stat_show(struct seq_file *m, void *v) int node; unsigned long len; - seq_puts(m, "queue_length"); + seq_puts(m, "queue_length\t"); for_each_node(node) { mz = mem_cgroup_nodeinfo(memcg, node); len = READ_ONCE(mz->hugepage_reclaim_queue.reclaim_queue_len); - seq_printf(m, " %8lu", len); + seq_printf(m, "%-24lu", len); + } + + seq_puts(m, "\n"); + seq_puts(m, "split_hugepage\t"); + for_each_node(node) { + mz = mem_cgroup_nodeinfo(memcg, node); + len = atomic_long_read(&mz->hugepage_reclaim_queue.split_hugepage); + seq_printf(m, "%-24lu", len); + } + + seq_puts(m, "\n"); + seq_puts(m, "reclaim_subpage\t"); + for_each_node(node) { + mz = mem_cgroup_nodeinfo(memcg, node); + len = atomic_long_read(&mz->hugepage_reclaim_queue.reclaim_subpage); + seq_printf(m, "%-24lu", len); } seq_puts(m, "\n"); -- 1.8.3.1