]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
iomap: add a separate bio_set for iomap_split_ioend
authorChristoph Hellwig <hch@lst.de>
Mon, 29 Jun 2026 12:52:29 +0000 (14:52 +0200)
committerChristian Brauner <brauner@kernel.org>
Fri, 31 Jul 2026 09:49:09 +0000 (11:49 +0200)
iomap_split_ioend can split bios that already come from
iomap_ioend_bioset and thus deadlock when the bioset is exhausted.

Add a separate bio_set to avoid this deadlock.

Christian Brauner <brauner@kernel.org> says:
Mark iomap_ioend_split_bioset static as it is only used in ioend.c,
fixing the sparse warning reported by the kernel test robot.

Fixes: 5fcbd555d483 ("iomap: split bios to zone append limits in the submission handlers")
Signed-off-by: Christoph Hellwig <hch@lst.de>
Link: https://patch.msgid.link/20260629125229.3400726-1-hch@lst.de
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
fs/iomap/ioend.c

index 30468d51b5ad7a86d160204d21acfb595a02ed62..fb636dce43afe3129158e09bf4a5ffb8c853f2f0 100644 (file)
@@ -13,6 +13,7 @@
 
 struct bio_set iomap_ioend_bioset;
 EXPORT_SYMBOL_GPL(iomap_ioend_bioset);
+static struct bio_set iomap_ioend_split_bioset;
 
 struct iomap_ioend *iomap_init_ioend(struct inode *inode,
                struct bio *bio, loff_t file_offset, u16 ioend_flags)
@@ -488,7 +489,8 @@ struct iomap_ioend *iomap_split_ioend(struct iomap_ioend *ioend,
        sector_offset = ALIGN_DOWN(sector_offset << SECTOR_SHIFT,
                        i_blocksize(ioend->io_inode)) >> SECTOR_SHIFT;
 
-       split = bio_split(bio, sector_offset, GFP_NOFS, &iomap_ioend_bioset);
+       split = bio_split(bio, sector_offset, GFP_NOFS,
+                       &iomap_ioend_split_bioset);
        if (IS_ERR(split))
                return ERR_CAST(split);
        split->bi_private = bio->bi_private;
@@ -511,8 +513,23 @@ EXPORT_SYMBOL_GPL(iomap_split_ioend);
 
 static int __init iomap_ioend_init(void)
 {
-       return bioset_init(&iomap_ioend_bioset, 4 * (PAGE_SIZE / SECTOR_SIZE),
+       const unsigned int nr_mempool_entries = 4 * (PAGE_SIZE / SECTOR_SIZE);
+       int error;
+
+       error = bioset_init(&iomap_ioend_bioset, nr_mempool_entries,
                           offsetof(struct iomap_ioend, io_bio),
                           BIOSET_NEED_BVECS);
+       if (error)
+               return error;
+       error = bioset_init(&iomap_ioend_split_bioset, nr_mempool_entries,
+                          offsetof(struct iomap_ioend, io_bio),
+                          BIOSET_NEED_BVECS);
+       if (error)
+               goto out_exit_ioend_bioset;
+       return 0;
+
+out_exit_ioend_bioset:
+       bioset_exit(&iomap_ioend_bioset);
+       return error;
 }
 fs_initcall(iomap_ioend_init);