[failures] mm-report-per-page-metadata-information.patch removed from -mm tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The quilt patch titled
     Subject: mm: report per-page metadata information
has been removed from the -mm tree.  Its filename was
     mm-report-per-page-metadata-information.patch

This patch was dropped because it had testing failures

------------------------------------------------------
From: Sourav Panda <souravpanda@xxxxxxxxxx>
Subject: mm: report per-page metadata information
Date: Mon, 29 Jan 2024 14:42:04 -0800

Adds two new per-node fields, namely nr_page_metadata and
nr_page_metadata_boot, to /sys/devices/system/node/nodeN/vmstat and a
global PageMetadata field to /proc/meminfo.  This information can be used
by users to see how much memory is being used by per-page metadata, which
can vary depending on build configuration, machine architecture, and
system use.

Per-page metadata is the amount of memory that Linux needs in order to
manage memory at the page granularity.  The majority of such memory is
used by "struct page" and "page_ext" data structures.  In contrast to most
other memory consumption statistics, per-page metadata might not be
included in MemTotal.  For example, MemTotal does not include memblock
allocations but includes buddy allocations.  In this patch, exported field
nr_page_metadata in /sys/devices/system/node/nodeN/vmstat would
exclusively track buddy allocations while nr_page_metadata_boot would
exclusively track memblock allocations.  Furthermore, PageMetadata in
/proc/meminfo would exclusively track buddy allocations allowing it to be
compared against MemTotal.

This memory depends on build configurations, machine architectures, and
the way system is used:

Build configuration may include extra fields into "struct page", and
enable / disable "page_ext".  Machine architecture defines base page
sizes.  For example 4K x86, 8K SPARC, 64K ARM64 (optionally), etc.  The
per-page metadata overhead is smaller on machines with larger page sizes. 
System use can change per-page overhead by using vmemmap optimizations
with hugetlb pages, and emulated pmem devdax pages.  Also, boot parameters
can determine whether page_ext is needed to be allocated.  This memory can
be part of MemTotal or be outside MemTotal depending on whether the memory
was hot-plugged, booted with, or hugetlb memory was returned back to the
system.

Link: https://lkml.kernel.org/r/20240129224204.1812062-2-souravpanda@xxxxxxxxxx
Signed-off-by: Sourav Panda <souravpanda@xxxxxxxxxx>
Suggested-by: Pasha Tatashin <pasha.tatashin@xxxxxxxxxx>
Cc: Alexey Dobriyan <adobriyan@xxxxxxxxx>
Cc: Bjorn Helgaas <bhelgaas@xxxxxxxxxx>
Cc: Chen Linxuan <chenlinxuan@xxxxxxxxxxxxx>
Cc: David Hildenbrand <david@xxxxxxxxxx>
Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
Cc: Ivan Babrou <ivan@xxxxxxxxxxxxxx>
Cc: Johannes Weiner <hannes@xxxxxxxxxxx>
Cc: Jonathan Corbet <corbet@xxxxxxx>
Cc: Kefeng Wang <wangkefeng.wang@xxxxxxxxxx>
Cc: Kirill A. Shutemov <kirill.shutemov@xxxxxxxxxxxxxxx>
Cc: Liam R. Howlett <Liam.Howlett@xxxxxxxxxx>
Cc: Matthew Wilcox (Oracle) <willy@xxxxxxxxxxxxx>
Cc: Mike Rapoport (IBM) <rppt@xxxxxxxxxx>
Cc: Muchun Song <muchun.song@xxxxxxxxx>
Cc: "Rafael J. Wysocki" <rafael@xxxxxxxxxx>
Cc: Randy Dunlap <rdunlap@xxxxxxxxxxxxx>
Cc: Shakeel Butt <shakeelb@xxxxxxxxxx>
Cc: Suren Baghdasaryan <surenb@xxxxxxxxxx>
Cc: Tomas Mudrunka <tomas.mudrunka@xxxxxxxxx>
Cc: Vlastimil Babka <vbabka@xxxxxxx>
Cc: Wei Xu <weixugc@xxxxxxxxxx>
Cc: Yang Yang <yang.yang29@xxxxxxxxxx>
Cc: Yosry Ahmed <yosryahmed@xxxxxxxxxx>
Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
---

 Documentation/filesystems/proc.rst |    3 ++
 fs/proc/meminfo.c                  |    4 +++
 include/linux/mmzone.h             |    4 +++
 include/linux/vmstat.h             |    4 +++
 mm/hugetlb_vmemmap.c               |   19 ++++++++++++----
 mm/mm_init.c                       |    5 +++-
 mm/page_alloc.c                    |    1 
 mm/page_ext.c                      |   32 +++++++++++++++++++--------
 mm/sparse-vmemmap.c                |    8 ++++++
 mm/sparse.c                        |    7 +++++
 mm/vmstat.c                        |   26 +++++++++++++++++++++
 11 files changed, 98 insertions(+), 15 deletions(-)

--- a/Documentation/filesystems/proc.rst~mm-report-per-page-metadata-information
+++ a/Documentation/filesystems/proc.rst
@@ -993,6 +993,7 @@ Example output. You may not have all of
     AnonPages:       4654780 kB
     Mapped:           266244 kB
     Shmem:              9976 kB
+    PageMetadata:     513419 kB
     KReclaimable:     517708 kB
     Slab:             660044 kB
     SReclaimable:     517708 kB
@@ -1095,6 +1096,8 @@ Mapped
               files which have been mmapped, such as libraries
 Shmem
               Total memory used by shared memory (shmem) and tmpfs
+PageMetadata
+              Memory used for per-page metadata
 KReclaimable
               Kernel allocations that the kernel will attempt to reclaim
               under memory pressure. Includes SReclaimable (below), and other
--- a/fs/proc/meminfo.c~mm-report-per-page-metadata-information
+++ a/fs/proc/meminfo.c
@@ -39,6 +39,7 @@ static int meminfo_proc_show(struct seq_
 	long available;
 	unsigned long pages[NR_LRU_LISTS];
 	unsigned long sreclaimable, sunreclaim;
+	unsigned long nr_page_metadata;
 	int lru;
 
 	si_meminfo(&i);
@@ -57,6 +58,8 @@ static int meminfo_proc_show(struct seq_
 	sreclaimable = global_node_page_state_pages(NR_SLAB_RECLAIMABLE_B);
 	sunreclaim = global_node_page_state_pages(NR_SLAB_UNRECLAIMABLE_B);
 
+	nr_page_metadata = global_node_page_state_pages(NR_PAGE_METADATA);
+
 	show_val_kb(m, "MemTotal:       ", i.totalram);
 	show_val_kb(m, "MemFree:        ", i.freeram);
 	show_val_kb(m, "MemAvailable:   ", available);
@@ -104,6 +107,7 @@ static int meminfo_proc_show(struct seq_
 	show_val_kb(m, "Mapped:         ",
 		    global_node_page_state(NR_FILE_MAPPED));
 	show_val_kb(m, "Shmem:          ", i.sharedram);
+	show_val_kb(m, "PageMetadata:   ", nr_page_metadata);
 	show_val_kb(m, "KReclaimable:   ", sreclaimable +
 		    global_node_page_state(NR_KERNEL_MISC_RECLAIMABLE));
 	show_val_kb(m, "Slab:           ", sreclaimable + sunreclaim);
--- a/include/linux/mmzone.h~mm-report-per-page-metadata-information
+++ a/include/linux/mmzone.h
@@ -214,6 +214,10 @@ enum node_stat_item {
 	PGDEMOTE_KSWAPD,
 	PGDEMOTE_DIRECT,
 	PGDEMOTE_KHUGEPAGED,
+	NR_PAGE_METADATA,	/* Page metadata size (struct page and page_ext)
+				 * in pages
+				 */
+	NR_PAGE_METADATA_BOOT,	/* NR_PAGE_METADATA for bootmem */
 	NR_VM_NODE_STAT_ITEMS
 };
 
--- a/include/linux/vmstat.h~mm-report-per-page-metadata-information
+++ a/include/linux/vmstat.h
@@ -632,4 +632,8 @@ static inline void lruvec_stat_sub_folio
 {
 	lruvec_stat_mod_folio(folio, idx, -folio_nr_pages(folio));
 }
+
+void __init mod_node_early_perpage_metadata(int nid, long delta);
+void __init store_early_perpage_metadata(void);
+
 #endif /* _LINUX_VMSTAT_H */
--- a/mm/hugetlb_vmemmap.c~mm-report-per-page-metadata-information
+++ a/mm/hugetlb_vmemmap.c
@@ -184,10 +184,14 @@ static int vmemmap_remap_range(unsigned
  */
 static inline void free_vmemmap_page(struct page *page)
 {
-	if (PageReserved(page))
+	if (PageReserved(page)) {
 		free_bootmem_page(page);
-	else
+		mod_node_page_state(page_pgdat(page), NR_PAGE_METADATA_BOOT,
+				    -1);
+	} else {
 		__free_page(page);
+		mod_node_page_state(page_pgdat(page), NR_PAGE_METADATA, -1);
+	}
 }
 
 /* Free a list of the vmemmap pages */
@@ -338,6 +342,7 @@ static int vmemmap_remap_free(unsigned l
 		copy_page(page_to_virt(walk.reuse_page),
 			  (void *)walk.reuse_addr);
 		list_add(&walk.reuse_page->lru, vmemmap_pages);
+		mod_node_page_state(NODE_DATA(nid), NR_PAGE_METADATA, 1);
 	}
 
 	/*
@@ -384,14 +389,20 @@ static int alloc_vmemmap_page_list(unsig
 	unsigned long nr_pages = (end - start) >> PAGE_SHIFT;
 	int nid = page_to_nid((struct page *)start);
 	struct page *page, *next;
+	int i;
 
-	while (nr_pages--) {
+	for (i = 0; i < nr_pages; i++) {
 		page = alloc_pages_node(nid, gfp_mask, 0);
-		if (!page)
+		if (!page) {
+			mod_node_page_state(NODE_DATA(nid), NR_PAGE_METADATA,
+					    i);
 			goto out;
+		}
 		list_add(&page->lru, list);
 	}
 
+	mod_node_page_state(NODE_DATA(nid), NR_PAGE_METADATA, nr_pages);
+
 	return 0;
 out:
 	list_for_each_entry_safe(page, next, list, lru)
--- a/mm/mm_init.c~mm-report-per-page-metadata-information
+++ a/mm/mm_init.c
@@ -20,6 +20,7 @@
 #include <linux/nmi.h>
 #include <linux/buffer_head.h>
 #include <linux/kmemleak.h>
+#include <linux/vmstat.h>
 #include <linux/kfence.h>
 #include <linux/page_ext.h>
 #include <linux/pti.h>
@@ -1644,7 +1645,7 @@ static void __init alloc_node_mem_map(st
 	start = pgdat->node_start_pfn & ~(MAX_ORDER_NR_PAGES - 1);
 	offset = pgdat->node_start_pfn - start;
 	/*
-		 * The zone's endpoints aren't required to be MAX_PAGE_ORDER
+	 * The zone's endpoints aren't required to be MAX_PAGE_ORDER
 	 * aligned but the node_mem_map endpoints must be in order
 	 * for the buddy allocator to function correctly.
 	 */
@@ -1656,6 +1657,8 @@ static void __init alloc_node_mem_map(st
 		panic("Failed to allocate %ld bytes for node %d memory map\n",
 		      size, pgdat->node_id);
 	pgdat->node_mem_map = map + offset;
+		mod_node_early_perpage_metadata(pgdat->node_id,
+						DIV_ROUND_UP(size, PAGE_SIZE));
 	pr_debug("%s: node %d, pgdat %08lx, node_mem_map %08lx\n",
 		 __func__, pgdat->node_id, (unsigned long)pgdat,
 		 (unsigned long)pgdat->node_mem_map);
--- a/mm/page_alloc.c~mm-report-per-page-metadata-information
+++ a/mm/page_alloc.c
@@ -5638,6 +5638,7 @@ void __init setup_per_cpu_pageset(void)
 	for_each_online_pgdat(pgdat)
 		pgdat->per_cpu_nodestats =
 			alloc_percpu(struct per_cpu_nodestat);
+	store_early_perpage_metadata();
 }
 
 __meminit void zone_pcp_init(struct zone *zone)
--- a/mm/page_ext.c~mm-report-per-page-metadata-information
+++ a/mm/page_ext.c
@@ -201,6 +201,8 @@ static int __init alloc_node_page_ext(in
 		return -ENOMEM;
 	NODE_DATA(nid)->node_page_ext = base;
 	total_usage += table_size;
+	mod_node_page_state(NODE_DATA(nid), NR_PAGE_METADATA_BOOT,
+			    DIV_ROUND_UP(table_size, PAGE_SIZE));
 	return 0;
 }
 
@@ -255,12 +257,15 @@ static void *__meminit alloc_page_ext(si
 	void *addr = NULL;
 
 	addr = alloc_pages_exact_nid(nid, size, flags);
-	if (addr) {
+	if (addr)
 		kmemleak_alloc(addr, size, 1, flags);
-		return addr;
-	}
+	else
+		addr = vzalloc_node(size, nid);
 
-	addr = vzalloc_node(size, nid);
+	if (addr) {
+		mod_node_page_state(NODE_DATA(nid), NR_PAGE_METADATA,
+				    DIV_ROUND_UP(size, PAGE_SIZE));
+	}
 
 	return addr;
 }
@@ -303,18 +308,27 @@ static int __meminit init_section_page_e
 
 static void free_page_ext(void *addr)
 {
+	size_t table_size;
+	struct page *page;
+	struct pglist_data *pgdat;
+
+	table_size = page_ext_size * PAGES_PER_SECTION;
+
 	if (is_vmalloc_addr(addr)) {
+		page = vmalloc_to_page(addr);
+		pgdat = page_pgdat(page);
 		vfree(addr);
 	} else {
-		struct page *page = virt_to_page(addr);
-		size_t table_size;
-
-		table_size = page_ext_size * PAGES_PER_SECTION;
-
+		page = virt_to_page(addr);
+		pgdat = page_pgdat(page);
 		BUG_ON(PageReserved(page));
 		kmemleak_free(addr);
 		free_pages_exact(addr, table_size);
 	}
+
+	mod_node_page_state(pgdat, NR_PAGE_METADATA,
+			    -1L * (DIV_ROUND_UP(table_size, PAGE_SIZE)));
+
 }
 
 static void __free_page_ext(unsigned long pfn)
--- a/mm/sparse.c~mm-report-per-page-metadata-information
+++ a/mm/sparse.c
@@ -14,7 +14,7 @@
 #include <linux/swap.h>
 #include <linux/swapops.h>
 #include <linux/bootmem_info.h>
-
+#include <linux/vmstat.h>
 #include "internal.h"
 #include <asm/dma.h>
 
@@ -465,6 +465,9 @@ static void __init sparse_buffer_init(un
 	 */
 	sparsemap_buf = memmap_alloc(size, section_map_size(), addr, nid, true);
 	sparsemap_buf_end = sparsemap_buf + size;
+#ifndef CONFIG_SPARSEMEM_VMEMMAP
+	mod_node_early_perpage_metadata(nid, DIV_ROUND_UP(size, PAGE_SIZE));
+#endif
 }
 
 static void __init sparse_buffer_fini(void)
@@ -641,6 +644,8 @@ static void depopulate_section_memmap(un
 	unsigned long start = (unsigned long) pfn_to_page(pfn);
 	unsigned long end = start + nr_pages * sizeof(struct page);
 
+	mod_node_page_state(page_pgdat(pfn_to_page(pfn)), NR_PAGE_METADATA,
+			    -1L * (DIV_ROUND_UP(end - start, PAGE_SIZE)));
 	vmemmap_free(start, end, altmap);
 }
 static void free_map_bootmem(struct page *memmap)
--- a/mm/sparse-vmemmap.c~mm-report-per-page-metadata-information
+++ a/mm/sparse-vmemmap.c
@@ -469,5 +469,13 @@ struct page * __meminit __populate_secti
 	if (r < 0)
 		return NULL;
 
+	if (system_state == SYSTEM_BOOTING) {
+		mod_node_page_state(NODE_DATA(nid), NR_PAGE_METADATA_BOOT,
+				    DIV_ROUND_UP(end - start, PAGE_SIZE));
+	} else {
+		mod_node_page_state(NODE_DATA(nid), NR_PAGE_METADATA,
+				    DIV_ROUND_UP(end - start, PAGE_SIZE));
+	}
+
 	return pfn_to_page(pfn);
 }
--- a/mm/vmstat.c~mm-report-per-page-metadata-information
+++ a/mm/vmstat.c
@@ -1253,6 +1253,9 @@ const char * const vmstat_text[] = {
 	"pgdemote_direct",
 	"pgdemote_khugepaged",
 
+	"nr_page_metadata",
+	"nr_page_metadata_boot",
+
 	/* enum writeback_stat_item counters */
 	"nr_dirty_threshold",
 	"nr_dirty_background_threshold",
@@ -2279,4 +2282,27 @@ static int __init extfrag_debug_init(voi
 }
 
 module_init(extfrag_debug_init);
+
 #endif
+
+/*
+ * Page metadata size (struct page and page_ext) in pages
+ */
+static unsigned long early_perpage_metadata[MAX_NUMNODES] __initdata;
+
+void __init mod_node_early_perpage_metadata(int nid, long delta)
+{
+	early_perpage_metadata[nid] += delta;
+}
+
+void __init store_early_perpage_metadata(void)
+{
+	int nid;
+	struct pglist_data *pgdat;
+
+	for_each_online_pgdat(pgdat) {
+		nid = pgdat->node_id;
+		mod_node_page_state(NODE_DATA(nid), NR_PAGE_METADATA_BOOT,
+				    early_perpage_metadata[nid]);
+	}
+}
_

Patches currently in -mm which might be from souravpanda@xxxxxxxxxx are






[Index of Archives]     [Kernel Archive]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]

  Powered by Linux