From ee8d2c7884a001cddc6c2a6baa070c3b3c6c389b Mon Sep 17 00:00:00 2001 From: Vijayanand Jitta Date: Tue, 12 Jan 2021 00:42:08 +0530 Subject: [PATCH] ANDROID: mm: add get_each_object_track function Add and export get_each_object_track which helps in looping through all the slab objects of a page and gets the track structure of each object, also make track_item and track structure public, these will be used by the minidump module to get slab owner info. Bug: 177377077 Change-Id: Ic207fd26a122a5f1b014f4929760d064f7af0225 Signed-off-by: Vijayanand Jitta --- mm/slab.h | 29 +++++++++++++++++++++++++++++ mm/slub.c | 49 +++++++++++++++++++++++++++++++++---------------- 2 files changed, 62 insertions(+), 16 deletions(-) diff --git a/mm/slab.h b/mm/slab.h index f9977d6613d6..cf44a6cdbd9b 100644 --- a/mm/slab.h +++ b/mm/slab.h @@ -91,6 +91,24 @@ struct kmem_cache *kmalloc_slab(size_t, gfp_t); gfp_t kmalloc_fix_flags(gfp_t flags); +#ifdef CONFIG_SLUB +/* + * Tracking user of a slab. + */ +#define TRACK_ADDRS_COUNT 16 +struct track { + unsigned long addr; /* Called from address */ +#ifdef CONFIG_STACKTRACE + unsigned long addrs[TRACK_ADDRS_COUNT]; /* Called from address */ +#endif + int cpu; /* Was running on cpu */ + int pid; /* Pid context */ + unsigned long when; /* When did the operation occur */ +}; + +enum track_item { TRACK_ALLOC, TRACK_FREE }; +#endif + /* Functions provided by the slab allocators */ int __kmem_cache_create(struct kmem_cache *, slab_flags_t flags); @@ -217,10 +235,21 @@ DECLARE_STATIC_KEY_TRUE(slub_debug_enabled); DECLARE_STATIC_KEY_FALSE(slub_debug_enabled); #endif extern void print_tracking(struct kmem_cache *s, void *object); +extern unsigned long get_each_object_track(struct kmem_cache *s, + struct page *page, enum track_item alloc, + int (*fn)(const struct kmem_cache *, const void *, + const struct track *, void *), void *private); #else static inline void print_tracking(struct kmem_cache *s, void *object) { } +static inline unsigned long get_each_object_track(struct kmem_cache *s, + struct page *page, enum track_item alloc, + int (*fn)(const struct kmem_cache *, const void *, + const struct track *, void *), void *private) +{ + return 0; +} #endif /* diff --git a/mm/slub.c b/mm/slub.c index 23208b529014..e08e75f8b104 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -200,22 +200,6 @@ static inline bool kmem_cache_has_cpu_partial(struct kmem_cache *s) /* Use cmpxchg_double */ #define __CMPXCHG_DOUBLE ((slab_flags_t __force)0x40000000U) -/* - * Tracking user of a slab. - */ -#define TRACK_ADDRS_COUNT 16 -struct track { - unsigned long addr; /* Called from address */ -#ifdef CONFIG_STACKTRACE - unsigned long addrs[TRACK_ADDRS_COUNT]; /* Called from address */ -#endif - int cpu; /* Was running on cpu */ - int pid; /* Pid context */ - unsigned long when; /* When did the operation occur */ -}; - -enum track_item { TRACK_ALLOC, TRACK_FREE }; - #ifdef CONFIG_SYSFS static int sysfs_slab_add(struct kmem_cache *); static int sysfs_slab_alias(struct kmem_cache *, const char *); @@ -576,6 +560,39 @@ static struct track *get_track(struct kmem_cache *s, void *object, return kasan_reset_tag(p + alloc); } +/* + * This function will be used to loop through all the slab objects in + * a page to give track structure for each object, the function fn will + * be using this track structure and extract required info into its private + * data, the return value will be the number of track structures that are + * processed. + */ +unsigned long get_each_object_track(struct kmem_cache *s, + struct page *page, enum track_item alloc, + int (*fn)(const struct kmem_cache *, const void *, + const struct track *, void *), void *private) +{ + void *p; + struct track *t; + int ret; + unsigned long num_track = 0; + + if (!slub_debug || !(s->flags & SLAB_STORE_USER)) + return 0; + + slab_lock(page); + for_each_object(p, s, page_address(page), page->objects) { + t = get_track(s, p, alloc); + ret = fn(s, p, t, private); + if (ret < 0) + break; + num_track += 1; + } + slab_unlock(page); + return num_track; +} +EXPORT_SYMBOL_GPL(get_each_object_track); + static void set_track(struct kmem_cache *s, void *object, enum track_item alloc, unsigned long addr) {