diff options
Diffstat (limited to 'mm/slub.c')
-rw-r--r-- | mm/slub.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/mm/slub.c b/mm/slub.c index ca7143fe25b5..63fe43c8d332 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1455,7 +1455,8 @@ static __always_inline bool slab_free_hook(struct kmem_cache *s, void *x) } static inline bool slab_free_freelist_hook(struct kmem_cache *s, - void **head, void **tail) + void **head, void **tail, + int *cnt) { void *object; @@ -1490,6 +1491,12 @@ static inline bool slab_free_freelist_hook(struct kmem_cache *s, *head = object; if (!*tail) *tail = object; + } else { + /* + * Adjust the reconstructed freelist depth + * accordingly if object's reuse is delayed. + */ + --(*cnt); } } while (object != old_tail); @@ -3049,7 +3056,7 @@ static __always_inline void slab_free(struct kmem_cache *s, struct page *page, * With KASAN enabled slab_free_freelist_hook modifies the freelist * to remove objects, whose reuse must be delayed. */ - if (slab_free_freelist_hook(s, &head, &tail)) + if (slab_free_freelist_hook(s, &head, &tail, &cnt)) do_slab_free(s, page, head, tail, cnt, addr); } @@ -3727,8 +3734,8 @@ static int kmem_cache_open(struct kmem_cache *s, slab_flags_t flags) if (alloc_kmem_cache_cpus(s)) return 0; - free_kmem_cache_nodes(s); error: + __kmem_cache_release(s); return -EINVAL; } |