@@ -17,6 +17,9 @@
#ifdef CONFIG_CMA
#include <linux/cma.h>
#endif
+#ifdef CONFIG_MEMORY_METADATA
+#include <asm/memory_metadata.h>
+#endif
#include <asm/page.h>
#include "internal.h"
@@ -167,6 +170,11 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
show_val_kb(m, "CmaFree: ",
global_zone_page_state(NR_FREE_CMA_PAGES));
#endif
+#ifdef CONFIG_MEMORY_METADATA
+ show_val_kb(m, "MetadataTotal: ", totalmetadata_pages);
+ show_val_kb(m, "MetadataFree: ",
+ global_zone_page_state(NR_FREE_METADATA_PAGES));
+#endif
#ifdef CONFIG_UNACCEPTED_MEMORY
show_val_kb(m, "Unaccepted: ",
@@ -4,6 +4,8 @@
#include <linux/gfp.h>
+extern unsigned long totalmetadata_pages;
+
#ifndef CONFIG_MEMORY_METADATA
static inline bool metadata_storage_enabled(void)
{
@@ -160,6 +160,7 @@ enum zone_stat_item {
#ifdef CONFIG_UNACCEPTED_MEMORY
NR_UNACCEPTED,
#endif
+ NR_FREE_METADATA_PAGES,
NR_VM_ZONE_STAT_ITEMS };
enum node_stat_item {
@@ -914,6 +915,9 @@ struct zone {
#ifdef CONFIG_CMA
unsigned long cma_pages;
#endif
+#ifdef CONFIG_MEMORY_METADATA
+ unsigned long metadata_pages;
+#endif
const char *name;
@@ -1026,6 +1030,15 @@ static inline unsigned long zone_cma_pages(struct zone *zone)
#endif
}
+static inline unsigned long zone_metadata_pages(struct zone *zone)
+{
+#ifdef CONFIG_MEMORY_METADATA
+ return zone->metadata_pages;
+#else
+ return 0;
+#endif
+}
+
static inline unsigned long zone_end_pfn(const struct zone *zone)
{
return zone->zone_start_pfn + zone->spanned_pages;
@@ -493,6 +493,8 @@ static inline void __mod_zone_freepage_state(struct zone *zone, int nr_pages,
__mod_zone_page_state(zone, NR_FREE_PAGES, nr_pages);
if (is_migrate_cma(migratetype))
__mod_zone_page_state(zone, NR_FREE_CMA_PAGES, nr_pages);
+ if (is_migrate_metadata(migratetype))
+ __mod_zone_page_state(zone, NR_FREE_METADATA_PAGES, nr_pages);
}
extern const char * const vmstat_text[];
@@ -2202,9 +2202,14 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order,
* pages are ordered properly.
*/
list_add_tail(&page->pcp_list, list);
- if (is_migrate_cma(get_pcppage_migratetype(page)))
+ if (is_migrate_cma(get_pcppage_migratetype(page))) {
__mod_zone_page_state(zone, NR_FREE_CMA_PAGES,
-(1 << order));
+ }
+ if (is_migrate_metadata(get_pcppage_migratetype(page))) {
+ __mod_zone_page_state(zone, NR_FREE_METADATA_PAGES,
+ -(1 << order));
+ }
}
__mod_zone_page_state(zone, NR_FREE_PAGES, -(i << order));
@@ -2894,6 +2899,10 @@ static inline long __zone_watermark_unusable_free(struct zone *z,
#ifdef CONFIG_UNACCEPTED_MEMORY
unusable_free += zone_page_state(z, NR_UNACCEPTED);
#endif
+#ifdef CONFIG_MEMORY_METADATA
+ if (!(alloc_flags & ALLOC_FROM_METADATA))
+ unusable_free += zone_page_state(z, NR_FREE_METADATA_PAGES);
+#endif
return unusable_free;
}
@@ -2974,6 +2983,13 @@ bool __zone_watermark_ok(struct zone *z, unsigned int order, unsigned long mark,
return true;
}
#endif
+
+#ifdef CONFIG_MEMORY_METADATA
+ if ((alloc_flags & ALLOC_FROM_METADATA) &&
+ !free_area_empty(area, MIGRATE_METADATA)) {
+ return true;
+ }
+#endif
if ((alloc_flags & (ALLOC_HIGHATOMIC|ALLOC_OOM)) &&
!free_area_empty(area, MIGRATE_HIGHATOMIC)) {
return true;
@@ -333,7 +333,8 @@ void pagetypeinfo_showmixedcount_print(struct seq_file *m,
page_owner = get_page_owner(page_ext);
page_mt = gfp_migratetype(page_owner->gfp_mask);
if (pageblock_mt != page_mt) {
- if (is_migrate_cma(pageblock_mt))
+ if (is_migrate_cma(pageblock_mt) ||
+ is_migrate_metadata(pageblock_mt))
count[MIGRATE_MOVABLE]++;
else
count[pageblock_mt]++;
@@ -22,6 +22,7 @@ atomic_long_t _totalram_pages __read_mostly;
EXPORT_SYMBOL(_totalram_pages);
unsigned long totalreserve_pages __read_mostly;
unsigned long totalcma_pages __read_mostly;
+unsigned long totalmetadata_pages __read_mostly;
static inline void show_node(struct zone *zone)
{
@@ -423,6 +424,9 @@ void __show_mem(unsigned int filter, nodemask_t *nodemask, int max_zone_idx)
#ifdef CONFIG_CMA
printk("%lu pages cma reserved\n", totalcma_pages);
#endif
+#ifdef CONFIG_MEMORY_METADATA
+ printk("%lu pages metadata reserved\n", totalmetadata_pages);
+#endif
#ifdef CONFIG_MEMORY_FAILURE
printk("%lu pages hwpoisoned\n", atomic_long_read(&num_poisoned_pages));
#endif
@@ -1184,6 +1184,7 @@ const char * const vmstat_text[] = {
#ifdef CONFIG_UNACCEPTED_MEMORY
"nr_unaccepted",
#endif
+ "nr_free_metadata",
/* enum numa_stat_item counters */
#ifdef CONFIG_NUMA
@@ -1695,7 +1696,8 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
"\n spanned %lu"
"\n present %lu"
"\n managed %lu"
- "\n cma %lu",
+ "\n cma %lu"
+ "\n metadata %lu",
zone_page_state(zone, NR_FREE_PAGES),
zone->watermark_boost,
min_wmark_pages(zone),
@@ -1704,7 +1706,8 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
zone->spanned_pages,
zone->present_pages,
zone_managed_pages(zone),
- zone_cma_pages(zone));
+ zone_cma_pages(zone),
+ zone_metadata_pages(zone));
seq_printf(m,
"\n protection: (%ld",
@@ -1909,6 +1912,7 @@ int vmstat_refresh(struct ctl_table *table, int write,
switch (i) {
case NR_ZONE_WRITE_PENDING:
case NR_FREE_CMA_PAGES:
+ case NR_FREE_METADATA_PAGES:
continue;
}
val = atomic_long_read(&vm_zone_stat[i]);
Keep track of the total number of metadata pages available in the system, as well as the per-zone pages. Opportunistically add braces to an "if" block from rmqueue_bulk() where the body contains multiple lines of code. Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com> --- fs/proc/meminfo.c | 8 ++++++++ include/asm-generic/memory_metadata.h | 2 ++ include/linux/mmzone.h | 13 +++++++++++++ include/linux/vmstat.h | 2 ++ mm/page_alloc.c | 18 +++++++++++++++++- mm/page_owner.c | 3 ++- mm/show_mem.c | 4 ++++ mm/vmstat.c | 8 ++++++-- 8 files changed, 54 insertions(+), 4 deletions(-)