aboutsummaryrefslogtreecommitdiffstats
path: root/lib/alloc_tag.c
diff options
context:
space:
mode:
authorSuren Baghdasaryan <[email protected]>2024-10-24 16:23:18 +0000
committerAndrew Morton <[email protected]>2024-11-07 22:25:17 +0000
commitb7fc16a16b0850e41b88eae0edfa4c085c012347 (patch)
tree78d5980ac97ec2e068e8e60ee65094bb2cf92211 /lib/alloc_tag.c
parentalloc_tag: support for page allocation tag compression (diff)
downloadkernel-b7fc16a16b0850e41b88eae0edfa4c085c012347.tar.gz
kernel-b7fc16a16b0850e41b88eae0edfa4c085c012347.zip
mm/codetag: uninline and move pgalloc_tag_copy and pgalloc_tag_split
pgalloc_tag_copy() and pgalloc_tag_split() are sizable and outside of any performance-critical paths, so it should be fine to uninline them. Also move their declarations into pgalloc_tag.h which seems like a more appropriate place for them. No functional changes other than uninlining. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Suren Baghdasaryan <[email protected]> Suggested-by: Andrew Morton <[email protected]> Acked-by: Yu Zhao <[email protected]> Cc: Kent Overstreet <[email protected]> Cc: Pasha Tatashin <[email protected]> Cc: Sourav Panda <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
Diffstat (limited to 'lib/alloc_tag.c')
-rw-r--r--lib/alloc_tag.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/lib/alloc_tag.c b/lib/alloc_tag.c
index d38a4b2a551d..2414a7ee7ec7 100644
--- a/lib/alloc_tag.c
+++ b/lib/alloc_tag.c
@@ -163,6 +163,54 @@ size_t alloc_tag_top_users(struct codetag_bytes *tags, size_t count, bool can_sl
return nr;
}
+void pgalloc_tag_split(struct folio *folio, int old_order, int new_order)
+{
+ int i;
+ struct alloc_tag *tag;
+ unsigned int nr_pages = 1 << new_order;
+
+ if (!mem_alloc_profiling_enabled())
+ return;
+
+ tag = pgalloc_tag_get(&folio->page);
+ if (!tag)
+ return;
+
+ for (i = nr_pages; i < (1 << old_order); i += nr_pages) {
+ union pgtag_ref_handle handle;
+ union codetag_ref ref;
+
+ if (get_page_tag_ref(folio_page(folio, i), &ref, &handle)) {
+ /* Set new reference to point to the original tag */
+ alloc_tag_ref_set(&ref, tag);
+ update_page_tag_ref(handle, &ref);
+ put_page_tag_ref(handle);
+ }
+ }
+}
+
+void pgalloc_tag_copy(struct folio *new, struct folio *old)
+{
+ union pgtag_ref_handle handle;
+ union codetag_ref ref;
+ struct alloc_tag *tag;
+
+ tag = pgalloc_tag_get(&old->page);
+ if (!tag)
+ return;
+
+ if (!get_page_tag_ref(&new->page, &ref, &handle))
+ return;
+
+ /* Clear the old ref to the original allocation tag. */
+ clear_page_tag_ref(&old->page);
+ /* Decrement the counters of the tag on get_new_folio. */
+ alloc_tag_sub(&ref, folio_size(new));
+ __alloc_tag_ref_set(&ref, tag);
+ update_page_tag_ref(handle, &ref);
+ put_page_tag_ref(handle);
+}
+
static void shutdown_mem_profiling(bool remove_file)
{
if (mem_alloc_profiling_enabled())