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 <vjitta@codeaurora.org>
This commit is contained in:
Vijayanand Jitta 2021-01-12 00:42:08 +05:30 committed by Suren Baghdasaryan
parent db158b4ae0
commit ee8d2c7884
2 changed files with 62 additions and 16 deletions

View File

@ -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
/*

View File

@ -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)
{