diff options
| author | Vlastimil Babka <vbabka@suse.cz> | 2025-03-06 09:46:34 +0100 |
|---|---|---|
| committer | Vlastimil Babka <vbabka@suse.cz> | 2025-03-20 10:33:38 +0100 |
| commit | dea2d9221e83ea02b45a60ab88284cd3bb4bb2a4 (patch) | |
| tree | 0391b6707ca2cd787f5937f285eb715375bda3c1 /mm/slub.c | |
| parent | 747e2cf137f44058a093d3226bf83974d9d117e7 (diff) | |
| parent | c9f8f1242a4c3e48adc6c3cf6b31c1ffbaa49943 (diff) | |
| download | ath-dea2d9221e83ea02b45a60ab88284cd3bb4bb2a4.tar.gz | |
Merge branch 'slab/for-6.15/kfree_rcu_tiny' into slab/for-next
Merge the slab feature branch kfree_rcu_tiny for 6.15:
- Move the TINY_RCU kvfree_rcu() implementation from RCU to SLAB
subsystem and cleanup its integration.
Diffstat (limited to 'mm/slub.c')
| -rw-r--r-- | mm/slub.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/mm/slub.c b/mm/slub.c index 6493b26f08cf5..5eac408e818e4 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -19,6 +19,7 @@ #include <linux/bitops.h> #include <linux/slab.h> #include "slab.h" +#include <linux/vmalloc.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/kasan.h> @@ -4757,6 +4758,51 @@ static void free_large_kmalloc(struct folio *folio, void *object) folio_put(folio); } +/* + * Given an rcu_head embedded within an object obtained from kvmalloc at an + * offset < 4k, free the object in question. + */ +void kvfree_rcu_cb(struct rcu_head *head) +{ + void *obj = head; + struct folio *folio; + struct slab *slab; + struct kmem_cache *s; + void *slab_addr; + + if (is_vmalloc_addr(obj)) { + obj = (void *) PAGE_ALIGN_DOWN((unsigned long)obj); + vfree(obj); + return; + } + + folio = virt_to_folio(obj); + if (!folio_test_slab(folio)) { + /* + * rcu_head offset can be only less than page size so no need to + * consider folio order + */ + obj = (void *) PAGE_ALIGN_DOWN((unsigned long)obj); + free_large_kmalloc(folio, obj); + return; + } + + slab = folio_slab(folio); + s = slab->slab_cache; + slab_addr = folio_address(folio); + + if (is_kfence_address(obj)) { + obj = kfence_object_start(obj); + } else { + unsigned int idx = __obj_to_index(s, slab_addr, obj); + + obj = slab_addr + s->size * idx; + obj = fixup_red_left(s, obj); + } + + slab_free(s, slab, obj, _RET_IP_); +} + /** * kfree - free previously allocated memory * @object: pointer returned by kmalloc() or kmem_cache_alloc() |
