* [PATCH v5 1/3] lib/stackdepot: Add a refcount field in stack_record
2023-05-16 14:03 [PATCH v5 0/3] page_owner: print stacks and their counter Oscar Salvador
@ 2023-05-16 14:03 ` Oscar Salvador
2023-05-16 14:03 ` [PATCH v5 2/3] mm, page_owner: Add page_owner_stacks file to print out only stacks and their counte Oscar Salvador
2023-05-16 14:03 ` [PATCH v5 3/3] mm,page_owner: Filter out stacks by a threshold counter Oscar Salvador
2 siblings, 0 replies; 5+ messages in thread
From: Oscar Salvador @ 2023-05-16 14:03 UTC (permalink / raw)
To: Andrew Morton
Cc: linux-kernel, linux-mm, Michal Hocko, Vlastimil Babka,
Eric Dumazet, Waiman Long, Suren Baghdasaryan, Marco Elver,
Andrey Konovalov, Alexander Potapenko, Oscar Salvador
We want to filter out page_owner output and print only those
stacks that have been repeated beyond a certain threshold.
This gives us the chance to get rid of a lot of noise.
In order to do that, we need to keep track of how many repeated stacks
(for allocation) do we have, so we add a new refcount_t field
in the stack_record struct.
Note that this might increase the size of the struct for some
architectures.
E.g: x86_64 is not affected due to alignment, but x86 32bits might.
The alternative would be to have some kind of struct like this:
struct track_stacks {
struct stack_record *stack;
struct track_stacks *next;
refcount_t stack_count;
But ithat would imply to perform more allocations and glue everything
together, which would make the code more complex, so I think that
going with a new field in the struct stack_record is good enough.
Note that on __set_page_owner_handle(), page_owner->handle is set,
and on __reset_page_owner(), page_owner->free_handle is set.
We are interested in page_owner->handle, so when __set_page_owner()
gets called, we derive the stack_record struct from page_owner->handle,
and we increment its refcount_t field; and when __reset_page_owner()
gets called, we derive its stack_record from page_owner->handle()
and we decrement its refcount_t field.
Signed-off-by: Oscar Salvador <osalvador@suse.de>
---
include/linux/stackdepot.h | 2 ++
lib/stackdepot.c | 53 +++++++++++++++++++++++++++++++-------
mm/page_owner.c | 6 +++++
3 files changed, 51 insertions(+), 10 deletions(-)
diff --git a/include/linux/stackdepot.h b/include/linux/stackdepot.h
index e58306783d8e..6ba4fcdb0c5f 100644
--- a/include/linux/stackdepot.h
+++ b/include/linux/stackdepot.h
@@ -94,6 +94,8 @@ static inline int stack_depot_early_init(void) { return 0; }
depot_stack_handle_t __stack_depot_save(unsigned long *entries,
unsigned int nr_entries,
gfp_t gfp_flags, bool can_alloc);
+void stack_depot_inc_count(depot_stack_handle_t handle);
+void stack_depot_dec_count(depot_stack_handle_t handle);
/**
* stack_depot_save - Save a stack trace to stack depot
diff --git a/lib/stackdepot.c b/lib/stackdepot.c
index 2f5aa851834e..bc4a9cd25834 100644
--- a/lib/stackdepot.c
+++ b/lib/stackdepot.c
@@ -60,6 +60,7 @@ struct stack_record {
u32 hash; /* Hash in the hash table */
u32 size; /* Number of stored frames */
union handle_parts handle;
+ refcount_t count; /* Number of the same repeated stacks */
unsigned long entries[]; /* Variable-sized array of frames */
};
@@ -305,6 +306,7 @@ depot_alloc_stack(unsigned long *entries, int size, u32 hash, void **prealloc)
stack->handle.offset = pool_offset >> DEPOT_STACK_ALIGN;
stack->handle.valid = 1;
stack->handle.extra = 0;
+ refcount_set(&stack->count, 1);
memcpy(stack->entries, entries, flex_array_size(stack, entries, size));
pool_offset += required_size;
/*
@@ -457,8 +459,7 @@ depot_stack_handle_t stack_depot_save(unsigned long *entries,
}
EXPORT_SYMBOL_GPL(stack_depot_save);
-unsigned int stack_depot_fetch(depot_stack_handle_t handle,
- unsigned long **entries)
+static struct stack_record *stack_depot_getstack(depot_stack_handle_t handle)
{
union handle_parts parts = { .handle = handle };
/*
@@ -470,6 +471,26 @@ unsigned int stack_depot_fetch(depot_stack_handle_t handle,
size_t offset = parts.offset << DEPOT_STACK_ALIGN;
struct stack_record *stack;
+ if (!handle)
+ return NULL;
+
+ if (parts.pool_index > pool_index_cached) {
+ WARN(1, "pool index %d out of bounds (%d) for stack id %08x\n",
+ parts.pool_index, pool_index_cached, handle);
+ return NULL;
+ }
+ pool = stack_pools[parts.pool_index];
+ if (!pool)
+ return NULL;
+ stack = pool + offset;
+ return stack;
+}
+
+unsigned int stack_depot_fetch(depot_stack_handle_t handle,
+ unsigned long **entries)
+{
+ struct stack_record *stack;
+
*entries = NULL;
/*
* Let KMSAN know *entries is initialized. This shall prevent false
@@ -480,21 +501,33 @@ unsigned int stack_depot_fetch(depot_stack_handle_t handle,
if (!handle)
return 0;
- if (parts.pool_index > pool_index_cached) {
- WARN(1, "pool index %d out of bounds (%d) for stack id %08x\n",
- parts.pool_index, pool_index_cached, handle);
- return 0;
- }
- pool = stack_pools[parts.pool_index];
- if (!pool)
+ stack = stack_depot_getstack(handle);
+ if (!stack)
return 0;
- stack = pool + offset;
*entries = stack->entries;
return stack->size;
}
EXPORT_SYMBOL_GPL(stack_depot_fetch);
+void stack_depot_inc_count(depot_stack_handle_t handle)
+{
+ struct stack_record *stack = NULL;
+
+ stack = stack_depot_getstack(handle);
+ if (stack)
+ refcount_inc(&stack->count);
+}
+
+void stack_depot_dec_count(depot_stack_handle_t handle)
+{
+ struct stack_record *stack = NULL;
+
+ stack = stack_depot_getstack(handle);
+ if (stack)
+ refcount_dec(&stack->count);
+}
+
void stack_depot_print(depot_stack_handle_t stack)
{
unsigned long *entries;
diff --git a/mm/page_owner.c b/mm/page_owner.c
index 31169b3e7f06..2d5d07013e4e 100644
--- a/mm/page_owner.c
+++ b/mm/page_owner.c
@@ -139,6 +139,7 @@ void __reset_page_owner(struct page *page, unsigned short order)
int i;
struct page_ext *page_ext;
depot_stack_handle_t handle;
+ depot_stack_handle_t alloc_handle;
struct page_owner *page_owner;
u64 free_ts_nsec = local_clock();
@@ -146,6 +147,9 @@ void __reset_page_owner(struct page *page, unsigned short order)
if (unlikely(!page_ext))
return;
+ page_owner = get_page_owner(page_ext);
+ alloc_handle = page_owner->handle;
+
handle = save_stack(GFP_NOWAIT | __GFP_NOWARN);
for (i = 0; i < (1 << order); i++) {
__clear_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags);
@@ -155,6 +159,7 @@ void __reset_page_owner(struct page *page, unsigned short order)
page_ext = page_ext_next(page_ext);
}
page_ext_put(page_ext);
+ stack_depot_dec_count(alloc_handle);
}
static inline void __set_page_owner_handle(struct page_ext *page_ext,
@@ -196,6 +201,7 @@ noinline void __set_page_owner(struct page *page, unsigned short order,
return;
__set_page_owner_handle(page_ext, handle, order, gfp_mask);
page_ext_put(page_ext);
+ stack_depot_inc_count(handle);
}
void __set_page_owner_migrate_reason(struct page *page, int reason)
--
2.35.3
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH v5 2/3] mm, page_owner: Add page_owner_stacks file to print out only stacks and their counte
2023-05-16 14:03 [PATCH v5 0/3] page_owner: print stacks and their counter Oscar Salvador
2023-05-16 14:03 ` [PATCH v5 1/3] lib/stackdepot: Add a refcount field in stack_record Oscar Salvador
@ 2023-05-16 14:03 ` Oscar Salvador
2023-05-16 14:03 ` [PATCH v5 3/3] mm,page_owner: Filter out stacks by a threshold counter Oscar Salvador
2 siblings, 0 replies; 5+ messages in thread
From: Oscar Salvador @ 2023-05-16 14:03 UTC (permalink / raw)
To: Andrew Morton
Cc: linux-kernel, linux-mm, Michal Hocko, Vlastimil Babka,
Eric Dumazet, Waiman Long, Suren Baghdasaryan, Marco Elver,
Andrey Konovalov, Alexander Potapenko, Oscar Salvador
We might be only interested in knowing about stacks <-> count
relationship, so instead of having to fiddle with page_owner
output and screen through pfns, let us add a new file called
'page_owner_stacks' that does just that.
By cating such file, we will get all the stacktraces followed by
its counter, so we can have a more global view.
Signed-off-by: Oscar Salvador <osalvador@suse.de>
---
include/linux/stackdepot.h | 6 ++++
lib/stackdepot.c | 72 ++++++++++++++++++++++++++++++++++++++
mm/page_owner.c | 27 ++++++++++++++
3 files changed, 105 insertions(+)
diff --git a/include/linux/stackdepot.h b/include/linux/stackdepot.h
index 6ba4fcdb0c5f..7e9d0e9ec66b 100644
--- a/include/linux/stackdepot.h
+++ b/include/linux/stackdepot.h
@@ -112,6 +112,12 @@ void stack_depot_dec_count(depot_stack_handle_t handle);
depot_stack_handle_t stack_depot_save(unsigned long *entries,
unsigned int nr_entries, gfp_t gfp_flags);
+#ifdef CONFIG_PAGE_OWNER
+void *stack_start(struct seq_file *m, loff_t *ppos);
+void *stack_next(struct seq_file *m, void *v, loff_t *ppos);
+int stack_print(struct seq_file *m, void *v);
+#endif
+
/**
* stack_depot_fetch - Fetch a stack trace from stack depot
*
diff --git a/lib/stackdepot.c b/lib/stackdepot.c
index bc4a9cd25834..c4af2e946500 100644
--- a/lib/stackdepot.c
+++ b/lib/stackdepot.c
@@ -29,6 +29,7 @@
#include <linux/types.h>
#include <linux/memblock.h>
#include <linux/kasan-enabled.h>
+#include <linux/seq_file.h>
#define DEPOT_HANDLE_BITS (sizeof(depot_stack_handle_t) * 8)
@@ -486,6 +487,77 @@ static struct stack_record *stack_depot_getstack(depot_stack_handle_t handle)
return stack;
}
+#ifdef CONFIG_PAGE_OWNER
+void *stack_start(struct seq_file *m, loff_t *ppos)
+{
+ unsigned long *table = m->private;
+ struct stack_record **stacks, *stack;
+
+ /* First time */
+ if (*ppos == 0)
+ *table = 0;
+
+ if (*ppos == -1UL)
+ return NULL;
+
+ stacks = &stack_table[*table];
+ stack = (struct stack_record *)stacks;
+
+ return stack;
+}
+
+void *stack_next(struct seq_file *m, void *v, loff_t *ppos)
+{
+ unsigned long *table = m->private;
+ unsigned long nr_table = *table;
+ struct stack_record *next = NULL, *stack = v, **stacks;
+ unsigned long stack_table_entries = stack_hash_mask + 1;
+
+ if (!stack) {
+new_table:
+ /* New table */
+ nr_table++;
+ if (nr_table >= stack_table_entries)
+ goto out;
+ stacks = &stack_table[nr_table];
+ stack = (struct stack_record *)stacks;
+ next = stack;
+ } else {
+ next = stack->next;
+ }
+
+ if (!next)
+ goto new_table;
+
+out:
+ *table = nr_table;
+ *ppos = (nr_table >= stack_table_entries) ? -1UL : *ppos + 1;
+ return next;
+}
+
+int stack_print(struct seq_file *m, void *v)
+{
+ char *buf;
+ int ret = 0;
+ struct stack_record *stack = v;
+
+ if (!stack->size || stack->size < 0 ||
+ stack->size > PAGE_SIZE || stack->handle.valid != 1 ||
+ refcount_read(&stack->count) < 1)
+ return 0;
+
+ buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+ ret += stack_trace_snprint(buf, PAGE_SIZE, stack->entries, stack->size, 0);
+ scnprintf(buf + ret, PAGE_SIZE - ret, "stack count: %d\n\n",
+ refcount_read(&stack->count));
+ seq_printf(m, buf);
+ seq_puts(m, "\n\n");
+ kfree(buf);
+
+ return 0;
+}
+#endif
+
unsigned int stack_depot_fetch(depot_stack_handle_t handle,
unsigned long **entries)
{
diff --git a/mm/page_owner.c b/mm/page_owner.c
index 2d5d07013e4e..2d97f6b34ea6 100644
--- a/mm/page_owner.c
+++ b/mm/page_owner.c
@@ -719,6 +719,30 @@ static const struct file_operations proc_page_owner_operations = {
.llseek = lseek_page_owner,
};
+static void stack_stop(struct seq_file *m, void *v)
+{
+}
+
+static const struct seq_operations page_owner_stack_op = {
+ .start = stack_start,
+ .next = stack_next,
+ .stop = stack_stop,
+ .show = stack_print
+};
+
+static int page_owner_stack_open(struct inode *inode, struct file *file)
+{
+ return seq_open_private(file, &page_owner_stack_op,
+ sizeof(unsigned long));
+}
+
+const struct file_operations page_owner_stack_operations = {
+ .open = page_owner_stack_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
static int __init pageowner_init(void)
{
if (!static_branch_unlikely(&page_owner_inited)) {
@@ -729,6 +753,9 @@ static int __init pageowner_init(void)
debugfs_create_file("page_owner", 0400, NULL, NULL,
&proc_page_owner_operations);
+ debugfs_create_file("page_owner_stacks", 0400, NULL, NULL,
+ &page_owner_stack_operations);
+
return 0;
}
late_initcall(pageowner_init)
--
2.35.3
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH v5 3/3] mm,page_owner: Filter out stacks by a threshold counter
2023-05-16 14:03 [PATCH v5 0/3] page_owner: print stacks and their counter Oscar Salvador
2023-05-16 14:03 ` [PATCH v5 1/3] lib/stackdepot: Add a refcount field in stack_record Oscar Salvador
2023-05-16 14:03 ` [PATCH v5 2/3] mm, page_owner: Add page_owner_stacks file to print out only stacks and their counte Oscar Salvador
@ 2023-05-16 14:03 ` Oscar Salvador
2 siblings, 0 replies; 5+ messages in thread
From: Oscar Salvador @ 2023-05-16 14:03 UTC (permalink / raw)
To: Andrew Morton
Cc: linux-kernel, linux-mm, Michal Hocko, Vlastimil Babka,
Eric Dumazet, Waiman Long, Suren Baghdasaryan, Marco Elver,
Andrey Konovalov, Alexander Potapenko, Oscar Salvador
We want to be able to filter out the output on a threshold basis,
in this way we can get rid of a lot of noise and focus only on those
stacks which have an allegedly high counter.
We can control the threshold value by a new file called
'page_owner_threshold', which is 0 by default.
Signed-off-by: Oscar Salvador <osalvador@suse.de>
---
lib/stackdepot.c | 5 ++++-
mm/page_owner.c | 21 +++++++++++++++++++++
2 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/lib/stackdepot.c b/lib/stackdepot.c
index c4af2e946500..7053221ce1d8 100644
--- a/lib/stackdepot.c
+++ b/lib/stackdepot.c
@@ -488,6 +488,9 @@ static struct stack_record *stack_depot_getstack(depot_stack_handle_t handle)
}
#ifdef CONFIG_PAGE_OWNER
+
+extern unsigned long page_owner_stack_threshold;
+
void *stack_start(struct seq_file *m, loff_t *ppos)
{
unsigned long *table = m->private;
@@ -543,7 +546,7 @@ int stack_print(struct seq_file *m, void *v)
if (!stack->size || stack->size < 0 ||
stack->size > PAGE_SIZE || stack->handle.valid != 1 ||
- refcount_read(&stack->count) < 1)
+ refcount_read(&stack->count) < page_owner_stack_threshold)
return 0;
buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
diff --git a/mm/page_owner.c b/mm/page_owner.c
index 2d97f6b34ea6..28c519fc9372 100644
--- a/mm/page_owner.c
+++ b/mm/page_owner.c
@@ -743,6 +743,23 @@ const struct file_operations page_owner_stack_operations = {
.release = seq_release,
};
+unsigned long page_owner_stack_threshold;
+
+int page_owner_threshold_get(void *data, u64 *val)
+{
+ *val = page_owner_stack_threshold;
+ return 0;
+}
+
+int page_owner_threshold_set(void *data, u64 val)
+{
+ page_owner_stack_threshold = val;
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(proc_page_owner_threshold, &page_owner_threshold_get,
+ &page_owner_threshold_set, "%llu");
+
static int __init pageowner_init(void)
{
if (!static_branch_unlikely(&page_owner_inited)) {
@@ -755,6 +772,10 @@ static int __init pageowner_init(void)
debugfs_create_file("page_owner_stacks", 0400, NULL, NULL,
&page_owner_stack_operations);
+ debugfs_create_file("page_owner_threshold", 0600, NULL, NULL,
+ &proc_page_owner_threshold);
+
+ page_owner_stack_threshold = 0;
return 0;
}
--
2.35.3
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v5 1/3] lib/stackdepot: Add a refcount field in stack_record
2023-05-16 18:25 [PATCH v5 0/3] page_owner: print stacks and their counter Oscar Salvador
@ 2023-05-16 18:25 ` Oscar Salvador
0 siblings, 0 replies; 5+ messages in thread
From: Oscar Salvador @ 2023-05-16 18:25 UTC (permalink / raw)
To: Andrew Morton
Cc: linux-kernel, linux-mm, Michal Hocko, Vlastimil Babka,
Waiman Long, Suren Baghdasaryan, Marco Elver, Andrey Konovalov,
Eric Dumazet, Alexander Potapenko, Oscar Salvador
We want to filter out page_owner output and print only those
stacks that have been repeated beyond a certain threshold.
This gives us the chance to get rid of a lot of noise.
In order to do that, we need to keep track of how many repeated stacks
(for allocation) do we have, so we add a new refcount_t field
in the stack_record struct.
Note that this might increase the size of the struct for some
architectures.
E.g: x86_64 is not affected due to alignment, but x86 32bits might.
The alternative would be to have some kind of struct like this:
struct track_stacks {
struct stack_record *stack;
struct track_stacks *next;
refcount_t stack_count;
But ithat would imply to perform more allocations and glue everything
together, which would make the code more complex, so I think that
going with a new field in the struct stack_record is good enough.
Note that on __set_page_owner_handle(), page_owner->handle is set,
and on __reset_page_owner(), page_owner->free_handle is set.
We are interested in page_owner->handle, so when __set_page_owner()
gets called, we derive the stack_record struct from page_owner->handle,
and we increment its refcount_t field; and when __reset_page_owner()
gets called, we derive its stack_record from page_owner->handle()
and we decrement its refcount_t field.
Signed-off-by: Oscar Salvador <osalvador@suse.de>
---
include/linux/stackdepot.h | 2 ++
lib/stackdepot.c | 53 +++++++++++++++++++++++++++++++-------
mm/page_owner.c | 6 +++++
3 files changed, 51 insertions(+), 10 deletions(-)
diff --git a/include/linux/stackdepot.h b/include/linux/stackdepot.h
index e58306783d8e..6ba4fcdb0c5f 100644
--- a/include/linux/stackdepot.h
+++ b/include/linux/stackdepot.h
@@ -94,6 +94,8 @@ static inline int stack_depot_early_init(void) { return 0; }
depot_stack_handle_t __stack_depot_save(unsigned long *entries,
unsigned int nr_entries,
gfp_t gfp_flags, bool can_alloc);
+void stack_depot_inc_count(depot_stack_handle_t handle);
+void stack_depot_dec_count(depot_stack_handle_t handle);
/**
* stack_depot_save - Save a stack trace to stack depot
diff --git a/lib/stackdepot.c b/lib/stackdepot.c
index 2f5aa851834e..bc4a9cd25834 100644
--- a/lib/stackdepot.c
+++ b/lib/stackdepot.c
@@ -60,6 +60,7 @@ struct stack_record {
u32 hash; /* Hash in the hash table */
u32 size; /* Number of stored frames */
union handle_parts handle;
+ refcount_t count; /* Number of the same repeated stacks */
unsigned long entries[]; /* Variable-sized array of frames */
};
@@ -305,6 +306,7 @@ depot_alloc_stack(unsigned long *entries, int size, u32 hash, void **prealloc)
stack->handle.offset = pool_offset >> DEPOT_STACK_ALIGN;
stack->handle.valid = 1;
stack->handle.extra = 0;
+ refcount_set(&stack->count, 1);
memcpy(stack->entries, entries, flex_array_size(stack, entries, size));
pool_offset += required_size;
/*
@@ -457,8 +459,7 @@ depot_stack_handle_t stack_depot_save(unsigned long *entries,
}
EXPORT_SYMBOL_GPL(stack_depot_save);
-unsigned int stack_depot_fetch(depot_stack_handle_t handle,
- unsigned long **entries)
+static struct stack_record *stack_depot_getstack(depot_stack_handle_t handle)
{
union handle_parts parts = { .handle = handle };
/*
@@ -470,6 +471,26 @@ unsigned int stack_depot_fetch(depot_stack_handle_t handle,
size_t offset = parts.offset << DEPOT_STACK_ALIGN;
struct stack_record *stack;
+ if (!handle)
+ return NULL;
+
+ if (parts.pool_index > pool_index_cached) {
+ WARN(1, "pool index %d out of bounds (%d) for stack id %08x\n",
+ parts.pool_index, pool_index_cached, handle);
+ return NULL;
+ }
+ pool = stack_pools[parts.pool_index];
+ if (!pool)
+ return NULL;
+ stack = pool + offset;
+ return stack;
+}
+
+unsigned int stack_depot_fetch(depot_stack_handle_t handle,
+ unsigned long **entries)
+{
+ struct stack_record *stack;
+
*entries = NULL;
/*
* Let KMSAN know *entries is initialized. This shall prevent false
@@ -480,21 +501,33 @@ unsigned int stack_depot_fetch(depot_stack_handle_t handle,
if (!handle)
return 0;
- if (parts.pool_index > pool_index_cached) {
- WARN(1, "pool index %d out of bounds (%d) for stack id %08x\n",
- parts.pool_index, pool_index_cached, handle);
- return 0;
- }
- pool = stack_pools[parts.pool_index];
- if (!pool)
+ stack = stack_depot_getstack(handle);
+ if (!stack)
return 0;
- stack = pool + offset;
*entries = stack->entries;
return stack->size;
}
EXPORT_SYMBOL_GPL(stack_depot_fetch);
+void stack_depot_inc_count(depot_stack_handle_t handle)
+{
+ struct stack_record *stack = NULL;
+
+ stack = stack_depot_getstack(handle);
+ if (stack)
+ refcount_inc(&stack->count);
+}
+
+void stack_depot_dec_count(depot_stack_handle_t handle)
+{
+ struct stack_record *stack = NULL;
+
+ stack = stack_depot_getstack(handle);
+ if (stack)
+ refcount_dec(&stack->count);
+}
+
void stack_depot_print(depot_stack_handle_t stack)
{
unsigned long *entries;
diff --git a/mm/page_owner.c b/mm/page_owner.c
index 31169b3e7f06..2d5d07013e4e 100644
--- a/mm/page_owner.c
+++ b/mm/page_owner.c
@@ -139,6 +139,7 @@ void __reset_page_owner(struct page *page, unsigned short order)
int i;
struct page_ext *page_ext;
depot_stack_handle_t handle;
+ depot_stack_handle_t alloc_handle;
struct page_owner *page_owner;
u64 free_ts_nsec = local_clock();
@@ -146,6 +147,9 @@ void __reset_page_owner(struct page *page, unsigned short order)
if (unlikely(!page_ext))
return;
+ page_owner = get_page_owner(page_ext);
+ alloc_handle = page_owner->handle;
+
handle = save_stack(GFP_NOWAIT | __GFP_NOWARN);
for (i = 0; i < (1 << order); i++) {
__clear_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags);
@@ -155,6 +159,7 @@ void __reset_page_owner(struct page *page, unsigned short order)
page_ext = page_ext_next(page_ext);
}
page_ext_put(page_ext);
+ stack_depot_dec_count(alloc_handle);
}
static inline void __set_page_owner_handle(struct page_ext *page_ext,
@@ -196,6 +201,7 @@ noinline void __set_page_owner(struct page *page, unsigned short order,
return;
__set_page_owner_handle(page_ext, handle, order, gfp_mask);
page_ext_put(page_ext);
+ stack_depot_inc_count(handle);
}
void __set_page_owner_migrate_reason(struct page *page, int reason)
--
2.35.3
^ permalink raw reply [flat|nested] 5+ messages in thread