On 20/03/2019 09:12, Hannes Reinecke wrote: > __blkdev_direct_IO_simple() is allocating a bio on the stack. > When that bio needs to be split bio_chain_endio() invokes bio_put() > on this bio, causing the kernel to crash in mempool_free() as the > bio was never allocated from a mempool in the first place. > So call bio_get() before submitting to avoid this problem. Hmm this sounds as if we're just papering over the real issue here, which is calling bio_free() for bios not allocated using bio_alloc_bioset(). How about the following untested patch: >From 9c8434e5bf81595e97ea5647437d12bfce0e37b6 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn <jthumshirn@xxxxxxx> Date: Wed, 20 Mar 2019 09:40:18 +0100 Subject: [PATCH] bio: Introduce BIO_ALLOCED flag and check it in bio_free When we're submitting a bio from stack and this ends up being split, we call bio_put(). bio_put() will eventually call bio_free() if the reference count drops to 0. But freeing the bio is wrong, as it was never allocated out of the bio's mempool. Flag each normally allocated bio as 'BIO_ALLOCATED' and skip freeing if the flag isn't set. Signed-off-by: Johannes Thumshirn <jthumshirn@xxxxxxx> --- block/bio.c | 4 ++++ include/linux/blk_types.h | 1 + 2 files changed, 5 insertions(+) diff --git a/block/bio.c b/block/bio.c index 4db1008309ed..caa8bc076377 100644 --- a/block/bio.c +++ b/block/bio.c @@ -253,6 +253,9 @@ static void bio_free(struct bio *bio) struct bio_set *bs = bio->bi_pool; void *p; + if (!bio_flagged(bio, BIO_ALLOCED)) + return; + bio_uninit(bio); if (bs) { @@ -521,6 +524,7 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, unsigned int nr_iovecs, bvl = bio->bi_inline_vecs; } + bio_set_flag(bio, BIO_ALLOCED); bio->bi_pool = bs; bio->bi_max_vecs = nr_iovecs; bio->bi_io_vec = bvl; diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index d66bf5f32610..14b4f87a1eab 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -229,6 +229,7 @@ struct bio { * of this bio. */ #define BIO_QUEUE_ENTERED 11 /* can use blk_queue_enter_live() */ #define BIO_TRACKED 12 /* set if bio goes through the rq_qos path */ +#define BIO_ALLOCED 13 /* set if the bio was allocated by bio_alloc_bioset */ /* See BVEC_POOL_OFFSET below before adding new flags */ -- 2.16.4 -- Johannes Thumshirn SUSE Labs Filesystems jthumshirn@xxxxxxx +49 911 74053 689 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg GF: Felix Imendörffer, Jane Smithard, Graham Norton HRB 21284 (AG Nürnberg) Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850