ANDROID: staging: android: ion: Expose total heap and pool sizes via sysfs

Add sysfs attributes to track ion total heap and pool memory allocations.
The following sysfs attributes are added:

/sys/kernel/ion/total_heaps_kb
/sys/kernel/ion/total_pools_kb

Bug: 138148041
Bug: 154238995
Test: adb shell cat /sys/kernel/ion/*
Change-Id: If92770dc3389af865c619525f04d3ba0e013b244
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
This commit is contained in:
Suren Baghdasaryan 2019-11-13 10:45:00 -08:00 committed by Matthias Maennich
parent 1d77161f7d
commit 2ec79b5516
8 changed files with 136 additions and 2 deletions

View File

@ -0,0 +1,27 @@
What: /sys/kernel/ion
Date: Dec 2019
KernelVersion: 4.14.158
Contact: Suren Baghdasaryan <surenb@google.com>,
Sandeep Patil <sspatil@google.com>
Description:
The /sys/kernel/ion directory contains a snapshot of the
internal state of ION memory heaps and pools.
Users: kernel memory tuning tools
What: /sys/kernel/ion/total_heaps_kb
Date: Dec 2019
KernelVersion: 4.14.158
Contact: Suren Baghdasaryan <surenb@google.com>,
Sandeep Patil <sspatil@google.com>
Description:
The total_heaps_kb file is read-only and specifies how much
memory in Kb is allocated to ION heaps.
What: /sys/kernel/ion/total_pools_kb
Date: Dec 2019
KernelVersion: 4.14.158
Contact: Suren Baghdasaryan <surenb@google.com>,
Sandeep Patil <sspatil@google.com>
Description:
The total_pools_kb file is read-only and specifies how much
memory in Kb is allocated to ION pools.

View File

@ -97,6 +97,17 @@ static int ion_page_pool_total(struct ion_page_pool *pool, bool high)
return count << pool->order;
}
int ion_page_pool_nr_pages(struct ion_page_pool *pool)
{
int nr_total_pages;
mutex_lock(&pool->mutex);
nr_total_pages = ion_page_pool_total(pool, true);
mutex_unlock(&pool->mutex);
return nr_total_pages;
}
int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask,
int nr_to_scan)
{

View File

@ -53,6 +53,7 @@ struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order);
void ion_page_pool_destroy(struct ion_page_pool *pool);
struct page *ion_page_pool_alloc(struct ion_page_pool *pool);
void ion_page_pool_free(struct ion_page_pool *pool, struct page *page);
int ion_page_pool_nr_pages(struct ion_page_pool *pool);
/** ion_page_pool_shrink - shrinks the size of the memory cached in the pool
* @pool: the pool

View File

@ -208,6 +208,19 @@ static int ion_system_heap_shrink(struct ion_heap *heap, gfp_t gfp_mask,
return nr_total;
}
static long ion_system_get_pool_size(struct ion_heap *heap)
{
struct ion_system_heap *sys_heap;
long total_pages = 0;
int i;
sys_heap = container_of(heap, struct ion_system_heap, heap);
for (i = 0; i < NUM_ORDERS; i++)
total_pages += ion_page_pool_nr_pages(sys_heap->pools[i]);
return total_pages;
}
static void ion_system_heap_destroy_pools(struct ion_page_pool **pools)
{
int i;
@ -245,6 +258,7 @@ static struct ion_heap_ops system_heap_ops = {
.allocate = ion_system_heap_allocate,
.free = ion_system_heap_free,
.shrink = ion_system_heap_shrink,
.get_pool_size = ion_system_get_pool_size,
};
static struct ion_system_heap system_heap = {

View File

@ -424,6 +424,63 @@ void ion_device_remove_heap(struct ion_heap *heap)
}
EXPORT_SYMBOL_GPL(ion_device_remove_heap);
static ssize_t
total_heaps_kb_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf)
{
return sprintf(buf, "%llu\n",
div_u64(ion_get_total_heap_bytes(), 1024));
}
static ssize_t
total_pools_kb_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf)
{
struct ion_device *dev = internal_dev;
struct ion_heap *heap;
u64 total_pages = 0;
down_read(&dev->lock);
plist_for_each_entry(heap, &dev->heaps, node)
if (heap->ops->get_pool_size)
total_pages += heap->ops->get_pool_size(heap);
up_read(&dev->lock);
return sprintf(buf, "%llu\n", total_pages * (PAGE_SIZE / 1024));
}
static struct kobj_attribute total_heaps_kb_attr =
__ATTR_RO(total_heaps_kb);
static struct kobj_attribute total_pools_kb_attr =
__ATTR_RO(total_pools_kb);
static struct attribute *ion_device_attrs[] = {
&total_heaps_kb_attr.attr,
&total_pools_kb_attr.attr,
NULL,
};
ATTRIBUTE_GROUPS(ion_device);
static int ion_init_sysfs(void)
{
struct kobject *ion_kobj;
int ret;
ion_kobj = kobject_create_and_add("ion", kernel_kobj);
if (!ion_kobj)
return -ENOMEM;
ret = sysfs_create_groups(ion_kobj, ion_device_groups);
if (ret) {
kobject_put(ion_kobj);
return ret;
}
return 0;
}
static int ion_device_create(void)
{
struct ion_device *idev;
@ -440,8 +497,13 @@ static int ion_device_create(void)
ret = misc_register(&idev->dev);
if (ret) {
pr_err("ion: failed to register misc device.\n");
kfree(idev);
return ret;
goto err_reg;
}
ret = ion_init_sysfs();
if (ret) {
pr_err("ion: failed to add sysfs attributes.\n");
goto err_sysfs;
}
idev->debug_root = debugfs_create_dir("ion", NULL);
@ -449,5 +511,11 @@ static int ion_device_create(void)
plist_head_init(&idev->heaps);
internal_dev = idev;
return 0;
err_sysfs:
misc_deregister(&idev->dev);
err_reg:
kfree(idev);
return ret;
}
subsys_initcall(ion_device_create);

View File

@ -13,6 +13,8 @@
#include "ion_private.h"
static atomic_long_t total_heap_bytes;
/* this function should only be called while dev->lock is held */
static struct ion_buffer *ion_buffer_create(struct ion_heap *heap,
struct ion_device *dev,
@ -65,6 +67,7 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap,
INIT_LIST_HEAD(&buffer->attachments);
mutex_init(&buffer->lock);
atomic_long_add(len, &total_heap_bytes);
return buffer;
err1:
@ -215,6 +218,7 @@ int ion_buffer_destroy(struct ion_device *dev, struct ion_buffer *buffer)
}
heap = buffer->heap;
atomic_long_sub(buffer->size, &total_heap_bytes);
if (heap->flags & ION_HEAP_FLAG_DEFER_FREE)
ion_heap_freelist_add(heap, buffer);
@ -251,3 +255,8 @@ void ion_buffer_kmap_put(struct ion_buffer *buffer)
buffer->vaddr = NULL;
}
}
u64 ion_get_total_heap_bytes(void)
{
return atomic_long_read(&total_heap_bytes);
}

View File

@ -53,4 +53,6 @@ extern int ion_free(struct ion_buffer *buffer);
/* ion heap helpers */
extern int ion_heap_cleanup(struct ion_heap *heap);
u64 ion_get_total_heap_bytes(void);
#endif /* _ION_PRIVATE_H */

View File

@ -53,6 +53,7 @@ struct ion_buffer {
* struct ion_heap_ops - ops to operate on a given heap
* @allocate: allocate memory
* @free: free memory
* @get_pool_size: get pool size in pages
*
* allocate returns 0 on success, -errno on error.
* map_dma and map_kernel return pointer on success, ERR_PTR on
@ -67,6 +68,7 @@ struct ion_heap_ops {
unsigned long flags);
void (*free)(struct ion_buffer *buffer);
int (*shrink)(struct ion_heap *heap, gfp_t gfp_mask, int nr_to_scan);
long (*get_pool_size)(struct ion_heap *heap);
};
/**