From: Yifan Li <liyifan21@xiaomi.com>
To: <akpm@linux-foundation.org>, <david@kernel.org>
Cc: <linux-mm@kvack.org>, <linux-fsdevel@vger.kernel.org>,
<linux-kernel@vger.kernel.org>, Yifan Li <liyifan21@xiaomi.com>
Subject: [RFC PATCH 1/1] mm: page_frag: account page_frag pages in vmstat and meminfo
Date: Sat, 10 Oct 2026 10:59:40 +0800 [thread overview]
Message-ID: <20261010025941.1253-2-liyifan21@xiaomi.com> (raw)
In-Reply-To: <20261010025941.1253-1-liyifan21@xiaomi.com>
The page_frag allocator backs sk_buff->head and the frags portion of
skb_shared_info for the network stack and NIC drivers, but pages
obtained from it are not accounted by any memory statistics counter.
Unlike slab (NR_SLAB_*) or page_pool, page_frag pages are invisible
to tools that derive "LostRAM = MemTotal - (sum of accounted memory)",
which inflates LostRAM and makes memory diagnosis misleading.
Pages enter the cache through a single entry point,
__page_frag_cache_refill(), so account them there. Decrement when the
cache page is freed via __page_frag_cache_drain() and page_frag_free().
Expose the counter, in pages, as "nr_page_frag" in /proc/vmstat and
"PageFrag" in /proc/meminfo so that page_frag memory is classified
instead of being counted as LostRAM.
Known limitation: a cache page handed over to an skb frags array is
released via put_page() (kfree_skb -> __skb_frag_unref ->
put_netmem -> put_page), bypassing page_frag_free(), so the counter
can over-count under network load. Covering that open release path
requires marking the page and accounting at the common free path;
that will be posted separately for discussion.
Verified on an arm64 Android device with 4K pages: at boot, PageFrag
in /proc/meminfo reports 14432 kB, consistent with nr_page_frag
(3608 pages) in /proc/vmstat.
Signed-off-by: Yifan Li <liyifan21@xiaomi.com>
---
fs/proc/meminfo.c | 1 +
include/linux/mmzone.h | 1 +
mm/page_frag_cache.c | 14 ++++++++++++--
mm/vmstat.c | 1 +
4 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c
index b2813ff13..73241c3a3 100644
--- a/fs/proc/meminfo.c
+++ b/fs/proc/meminfo.c
@@ -108,6 +108,7 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
show_val_kb(m, "Slab: ", sreclaimable + sunreclaim);
show_val_kb(m, "SReclaimable: ", sreclaimable);
show_val_kb(m, "SUnreclaim: ", sunreclaim);
+ show_val_kb(m, "PageFrag: ", global_node_page_state(NR_PAGE_FRAG));
seq_printf(m, "KernelStack: %8lu kB\n",
global_node_page_state(NR_KERNEL_STACK_KB));
#ifdef CONFIG_SHADOW_CALL_STACK
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 94f9c3ff5..636f6ecb7 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -333,6 +333,7 @@ enum node_stat_item {
NR_KERNEL_FILE_PAGES,
NR_GPU_ACTIVE, /* Pages assigned to GPU objects */
NR_GPU_RECLAIM, /* Pages in shrinkable GPU pools */
+ NR_PAGE_FRAG,
NR_VM_NODE_STAT_ITEMS
};
diff --git a/mm/page_frag_cache.c b/mm/page_frag_cache.c
index e63efe78b..4f768093c 100644
--- a/mm/page_frag_cache.c
+++ b/mm/page_frag_cache.c
@@ -18,6 +18,7 @@
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/page_frag_cache.h>
+#include <linux/vmstat.h>
#include "page_alloc.h"
static unsigned long encoded_page_create(struct page *page, unsigned int order,
@@ -67,6 +68,9 @@ static struct page *__page_frag_cache_refill(struct page_frag_cache *nc,
nc->encoded_page = page ?
encoded_page_create(page, order, page_is_pfmemalloc(page)) : 0;
+ if (page)
+ mod_node_page_state(page_pgdat(page), NR_PAGE_FRAG,
+ 1L << order);
return page;
}
@@ -85,8 +89,11 @@ void __page_frag_cache_drain(struct page *page, unsigned int count)
{
VM_BUG_ON_PAGE(page_ref_count(page) == 0, page);
- if (page_ref_sub_and_test(page, count))
+ if (page_ref_sub_and_test(page, count)) {
+ mod_node_page_state(page_pgdat(page), NR_PAGE_FRAG,
+ -(1L << compound_order(page)));
free_frozen_pages(page, compound_order(page));
+ }
}
EXPORT_SYMBOL(__page_frag_cache_drain);
@@ -165,7 +172,10 @@ void page_frag_free(void *addr)
{
struct page *page = virt_to_head_page(addr);
- if (unlikely(put_page_testzero(page)))
+ if (unlikely(put_page_testzero(page))) {
+ mod_node_page_state(page_pgdat(page), NR_PAGE_FRAG,
+ -(1L << compound_order(page)));
free_frozen_pages(page, compound_order(page));
+ }
}
EXPORT_SYMBOL(page_frag_free);
diff --git a/mm/vmstat.c b/mm/vmstat.c
index cb5771453..883137cb6 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -1311,6 +1311,7 @@ const char * const vmstat_text[] = {
[I(NR_KERNEL_FILE_PAGES)] = "nr_kernel_file_pages",
[I(NR_GPU_ACTIVE)] = "nr_gpu_active",
[I(NR_GPU_RECLAIM)] = "nr_gpu_reclaim",
+ [I(NR_PAGE_FRAG)] = "nr_page_frag",
#undef I
/* system-wide enum vm_stat_item counters */
--
2.46.0.windows.1
#/******±¾Óʼþ¼°Æä¸½¼þº¬ÓÐСÃ×¹«Ë¾µÄ±£ÃÜÐÅÏ¢£¬½öÏÞÓÚ·¢Ë͸øÉÏÃæµØÖ·ÖÐÁгöµÄ¸öÈË»òȺ×é¡£½ûÖ¹ÈÎºÎÆäËûÈËÒÔÈκÎÐÎʽʹÓ㨰üÀ¨µ«²»ÏÞÓÚÈ«²¿»ò²¿·ÖµØÐ¹Â¶¡¢¸´ÖÆ¡¢»òÉ¢·¢£©±¾ÓʼþÖеÄÐÅÏ¢¡£Èç¹ûÄú´íÊÕÁ˱¾Óʼþ£¬ÇëÄúÁ¢¼´µç»°»òÓʼþ֪ͨ·¢¼þÈ˲¢É¾³ý±¾Óʼþ£¡ This e-mail and its attachments contain confidential information from XIAOMI, which is intended only for the person or entity whose address is listed above. Any use of the information contained herein in any way (including, but not limited to, total or partial disclosure, reproduction, or dissemination) by persons other than the intended recipient(s) is prohibited. If you receive this e-mail in error, please notify the sender by phone or email immediately and delete it!******/#
next prev parent reply other threads:[~2026-10-10 3:00 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-10 2:59 [RFC PATCH 0/1] " Yifan Li
2026-10-10 2:59 ` Yifan Li [this message]
2026-10-12 10:36 ` David Hildenbrand (Arm)
2026-10-12 11:27 ` Pedro Falcato
2026-10-12 13:34 ` David Hildenbrand (Arm)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261010025941.1253-2-liyifan21@xiaomi.com \
--to=liyifan21@xiaomi.com \
--cc=akpm@linux-foundation.org \
--cc=david@kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®