diff options
Diffstat (limited to 'mm/page_owner.c')
-rw-r--r-- | mm/page_owner.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/mm/page_owner.c b/mm/page_owner.c index 31169b3e7f06..28c519fc9372 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) @@ -713,6 +719,47 @@ 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, +}; + +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)) { @@ -723,6 +770,13 @@ 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); + debugfs_create_file("page_owner_threshold", 0600, NULL, NULL, + &proc_page_owner_threshold); + + page_owner_stack_threshold = 0; + return 0; } late_initcall(pageowner_init) |