Skip to content

Commit c691e4b

Browse files
Ming Leiaxboe
authored andcommitted
bio: fix kmemleak false positives from percpu bio alloc cache
When a bio is allocated from the mempool with REQ_ALLOC_CACHE set and later completed, bio_put() places it into the per-cpu bio_alloc_cache via bio_put_percpu_cache() instead of freeing it back to the mempool/slab. The slab allocation remains tracked by kmemleak, but the only reference to the bio is through the percpu cache's free_list, which kmemleak fails to trace through percpu memory. This causes kmemleak to report the cached bios as unreferenced objects. Use symmetric kmemleak_free()/kmemleak_alloc() calls to properly track bios across percpu cache transitions: - bio_put_percpu_cache: call kmemleak_free() when a bio enters the cache, unregistering it from kmemleak tracking. - bio_alloc_percpu_cache: call kmemleak_alloc() when a bio is taken from the cache for reuse, re-registering it so that genuine leaks of reused bios remain detectable. - __bio_alloc_cache_prune: call kmemleak_alloc() before bio_free() so that kmem_cache_free()'s internal kmemleak_free() has a matching allocation to pair with. Tested-by: Yi Zhang <yi.zhang@redhat.com> Signed-off-by: Ming Lei <ming.lei@redhat.com> Link: https://patch.msgid.link/20260326144058.2392319-1-ming.lei@redhat.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent f91ffe8 commit c691e4b

1 file changed

Lines changed: 14 additions & 0 deletions

File tree

block/bio.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/highmem.h>
1919
#include <linux/blk-crypto.h>
2020
#include <linux/xarray.h>
21+
#include <linux/kmemleak.h>
2122

2223
#include <trace/events/block.h>
2324
#include "blk.h"
@@ -116,6 +117,11 @@ static inline unsigned int bs_bio_slab_size(struct bio_set *bs)
116117
return bs->front_pad + sizeof(struct bio) + bs->back_pad;
117118
}
118119

120+
static inline void *bio_slab_addr(struct bio *bio)
121+
{
122+
return (void *)bio - bio->bi_pool->front_pad;
123+
}
124+
119125
static struct kmem_cache *bio_find_or_create_slab(struct bio_set *bs)
120126
{
121127
unsigned int size = bs_bio_slab_size(bs);
@@ -486,6 +492,9 @@ static struct bio *bio_alloc_percpu_cache(struct bio_set *bs)
486492
cache->nr--;
487493
put_cpu();
488494
bio->bi_pool = bs;
495+
496+
kmemleak_alloc(bio_slab_addr(bio),
497+
kmem_cache_size(bs->bio_slab), 1, GFP_NOIO);
489498
return bio;
490499
}
491500

@@ -728,6 +737,9 @@ static int __bio_alloc_cache_prune(struct bio_alloc_cache *cache,
728737
while ((bio = cache->free_list) != NULL) {
729738
cache->free_list = bio->bi_next;
730739
cache->nr--;
740+
kmemleak_alloc(bio_slab_addr(bio),
741+
kmem_cache_size(bio->bi_pool->bio_slab),
742+
1, GFP_KERNEL);
731743
bio_free(bio);
732744
if (++i == nr)
733745
break;
@@ -791,13 +803,15 @@ static inline void bio_put_percpu_cache(struct bio *bio)
791803
bio->bi_bdev = NULL;
792804
cache->free_list = bio;
793805
cache->nr++;
806+
kmemleak_free(bio_slab_addr(bio));
794807
} else if (in_hardirq()) {
795808
lockdep_assert_irqs_disabled();
796809

797810
bio_uninit(bio);
798811
bio->bi_next = cache->free_list_irq;
799812
cache->free_list_irq = bio;
800813
cache->nr_irq++;
814+
kmemleak_free(bio_slab_addr(bio));
801815
} else {
802816
goto out_free;
803817
}

0 commit comments

Comments
 (0)