ANDROID: mm: add GCMA sysfs stats

Add GCMA statistics for stored, loaded, evicted, cached and discarded
pages.

Bug: 236887352
Bug: 391879760
Change-Id: I7238ad6a0ab357402cda3f2357b1a731c50c597a
Signed-off-by: Minchan Kim <minchan@google.com>
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
This commit is contained in:
Suren Baghdasaryan
2025-02-27 13:01:38 -08:00
committed by Carlos Llamas
parent ccf872ebe4
commit 80a603a57a
5 changed files with 134 additions and 0 deletions
+7
View File
@@ -998,6 +998,13 @@ config GCMA
If unsure, say "n".
config GCMA_SYSFS
bool "GCMA information through sysfs interface"
depends on GCMA && SYSFS
help
This option exposes some sysfs attributes to get information
from GCMA.
config MEM_SOFT_DIRTY
bool "Track memory changes"
depends on CHECKPOINT_RESTORE && HAVE_ARCH_SOFT_DIRTY && PROC_FS
+1
View File
@@ -120,6 +120,7 @@ obj-$(CONFIG_Z3FOLD) += z3fold.o
obj-$(CONFIG_GENERIC_EARLY_IOREMAP) += early_ioremap.o
obj-$(CONFIG_CMA) += cma.o
obj-$(CONFIG_GCMA) += gcma.o
obj-$(CONFIG_GCMA_SYSFS) += gcma_sysfs.o
obj-$(CONFIG_NUMA) += numa.o
obj-$(CONFIG_NUMA_MEMBLKS) += numa_memblks.o
obj-$(CONFIG_NUMA_EMU) += numa_emulation.o
+9
View File
@@ -13,6 +13,7 @@
#include <linux/idr.h>
#include <linux/slab.h>
#include <linux/xarray.h>
#include "gcma_sysfs.h"
/*
* page->page_type : area id
@@ -360,6 +361,7 @@ static struct page *gcma_alloc_page(void)
ClearPageGCMAFree(page);
set_page_count(page, 1);
spin_unlock(&area->free_pages_lock);
gcma_stat_inc(CACHED_PAGE);
break;
}
@@ -380,6 +382,7 @@ static void __gcma_free_page(struct page *page)
static void gcma_free_page(struct page *page)
{
__gcma_free_page(page);
gcma_stat_dec(CACHED_PAGE);
}
static inline void gcma_get_page(struct page *page)
@@ -473,6 +476,7 @@ static void isolate_gcma_page(struct gcma_inode *inode, struct page *page)
page_area_lock(page);
reset_gcma_page(page);
page_area_unlock(page);
gcma_stat_dec(CACHED_PAGE);
}
/*
@@ -584,6 +588,7 @@ again:
xa_unlock(&inode->pages);
isolate_gcma_page(inode, page);
gcma_stat_inc(DISCARDED_PAGE);
put_gcma_inode(inode);
}
local_irq_enable();
@@ -708,6 +713,8 @@ static void evict_gcma_lru_pages(unsigned long nr_request)
}
nr_evicted += isolated;
}
gcma_stat_add(EVICTED_PAGE, nr_evicted);
}
static void evict_gcma_pages(struct work_struct *work)
@@ -804,6 +811,7 @@ copy:
else
rotate_lru_page(g_page);
gcma_stat_inc(STORED_PAGE);
out_unlock:
/*
* If inode was just created but failed to add gcma page,
@@ -849,6 +857,7 @@ static int gcma_cc_load_page(int hash_id, struct cleancache_filekey key,
xa_unlock_irq(&inode->pages);
put_gcma_inode(inode);
gcma_stat_inc(LOADED_PAGE);
return 0;
}
+92
View File
@@ -0,0 +1,92 @@
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include "gcma_sysfs.h"
extern struct kobject *vendor_mm_kobj;
static struct kobject gcma_kobj;
static atomic64_t gcma_stats[NUM_OF_GCMA_STAT];
void gcma_stat_inc(enum gcma_stat_type type)
{
atomic64_inc(&gcma_stats[type]);
}
void gcma_stat_dec(enum gcma_stat_type type)
{
atomic64_dec(&gcma_stats[type]);
}
void gcma_stat_add(enum gcma_stat_type type, unsigned long delta)
{
atomic64_add(delta, &gcma_stats[type]);
}
/*
* This all compiles without CONFIG_SYSFS, but is a waste of space.
*/
#define GCMA_ATTR_RO(_name) \
static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
static ssize_t stored_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
return sysfs_emit(buf, "%llu\n", (u64)atomic64_read(&gcma_stats[STORED_PAGE]));
}
GCMA_ATTR_RO(stored);
static ssize_t loaded_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
return sysfs_emit(buf, "%llu\n", (u64)atomic64_read(&gcma_stats[LOADED_PAGE]));
}
GCMA_ATTR_RO(loaded);
static ssize_t evicted_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
return sysfs_emit(buf, "%llu\n", (u64)atomic64_read(&gcma_stats[EVICTED_PAGE]));
}
GCMA_ATTR_RO(evicted);
static ssize_t cached_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
return sysfs_emit(buf, "%llu\n", (u64)atomic64_read(&gcma_stats[CACHED_PAGE]));
}
GCMA_ATTR_RO(cached);
static ssize_t discarded_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
return sysfs_emit(buf, "%llu\n", (u64)atomic64_read(&gcma_stats[DISCARDED_PAGE]));
}
GCMA_ATTR_RO(discarded);
static struct attribute *gcma_attrs[] = {
&stored_attr.attr,
&loaded_attr.attr,
&evicted_attr.attr,
&cached_attr.attr,
&discarded_attr.attr,
NULL,
};
ATTRIBUTE_GROUPS(gcma);
static void gcma_kobj_release(struct kobject *obj)
{
/* Never released the static objects */
}
static struct kobj_type gcma_ktype = {
.release = gcma_kobj_release,
.sysfs_ops = &kobj_sysfs_ops,
.default_groups = gcma_groups,
};
static int __init gcma_sysfs_init(void)
{
return kobject_init_and_add(&gcma_kobj, &gcma_ktype, mm_kobj, "gcma");
}
subsys_initcall(gcma_sysfs_init);
+25
View File
@@ -0,0 +1,25 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __GCMA_SYSFS_H__
#define __GCMA_SYSFS_H__
enum gcma_stat_type {
STORED_PAGE,
LOADED_PAGE,
EVICTED_PAGE,
CACHED_PAGE,
DISCARDED_PAGE,
NUM_OF_GCMA_STAT,
};
#ifdef CONFIG_GCMA_SYSFS
void gcma_stat_inc(enum gcma_stat_type type);
void gcma_stat_dec(enum gcma_stat_type type);
void gcma_stat_add(enum gcma_stat_type type, unsigned long delta);
#else /* CONFIG_GCMA_SYSFS */
static inline void gcma_stat_inc(enum gcma_stat_type type) {}
static inline void gcma_stat_dec(enum gcma_stat_type type) {}
static inline void gcma_stat_add(enum gcma_stat_type type,
unsigned long delta) {}
#endif /* CONFIG_GCMA_SYSFS */
#endif