diff --git a/block/bio.c b/block/bio.c index 5057047194c4..bbbcd1d2f85d 100644 --- a/block/bio.c +++ b/block/bio.c @@ -530,11 +530,13 @@ struct bio *bio_alloc_bioset(struct block_device *bdev, unsigned short nr_vecs, struct bio *bio = NULL; gfp_t saved_gfp = gfp; void *p; + static DEFINE_MUTEX(bio_alloc_lock); /* should not use nobvec bioset for nr_vecs > 0 */ if (WARN_ON_ONCE(!mempool_initialized(&bs->bvec_pool) && nr_vecs > 0)) return NULL; + mutex_lock(&bio_alloc_lock); gfp = try_alloc_gfp(gfp); if (bs->cache && nr_vecs <= BIO_INLINE_VECS) { /* @@ -570,8 +572,10 @@ struct bio *bio_alloc_bioset(struct block_device *bdev, unsigned short nr_vecs, * Give up if we are not allow to sleep as non-blocking mempool * allocations just go back to the slab allocation. */ - if (!(saved_gfp & __GFP_DIRECT_RECLAIM)) + if (!(saved_gfp & __GFP_DIRECT_RECLAIM)) { + mutex_unlock(&bio_alloc_lock); return NULL; + } punt_bios_to_rescuer(bs); @@ -594,6 +598,7 @@ struct bio *bio_alloc_bioset(struct block_device *bdev, unsigned short nr_vecs, else bio_init(bio, bdev, bvecs, nr_vecs, opf); bio->bi_pool = bs; + mutex_unlock(&bio_alloc_lock); return bio; } EXPORT_SYMBOL(bio_alloc_bioset);