public inbox for linux-block@vger.kernel.org
 help / color / mirror / Atom feed
* remove the bi_inline_vecs field struct bio
@ 2025-09-08 10:56 Christoph Hellwig
  2025-09-08 10:56 ` [PATCH 1/2] block: add a bio_init_inline helper Christoph Hellwig
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Christoph Hellwig @ 2025-09-08 10:56 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-block

Hi Jens,

the bi_inline_vecs causes sparse to warn when a bio is embedded into a
structure, but not the last member.   This is a bit annoying but
probably not a big.  But it can be easily fixed by just removing the
member and doing pointer arithmetics in a helper, so do that.

Diffstat:
 block/bio.c                        |   10 +++++++---
 block/blk-crypto-fallback.c        |    3 +--
 block/blk-map.c                    |    8 ++++----
 drivers/md/bcache/debug.c          |    3 +--
 drivers/md/bcache/io.c             |    3 +--
 drivers/md/bcache/journal.c        |    2 +-
 drivers/md/bcache/movinggc.c       |    8 ++++----
 drivers/md/bcache/super.c          |    2 +-
 drivers/md/bcache/writeback.c      |    8 ++++----
 drivers/md/dm-bufio.c              |    2 +-
 drivers/md/dm-flakey.c             |    2 +-
 drivers/md/dm-vdo/vio.c            |    2 +-
 drivers/md/raid1.c                 |    2 +-
 drivers/md/raid10.c                |    4 ++--
 drivers/target/target_core_pscsi.c |    2 +-
 fs/bcachefs/btree_io.c             |    2 +-
 fs/bcachefs/data_update.h          |    1 -
 fs/bcachefs/journal.c              |    6 +++---
 fs/bcachefs/journal_io.c           |    2 +-
 fs/bcachefs/super-io.c             |    2 +-
 fs/squashfs/block.c                |    2 +-
 include/linux/bio.h                |    5 +++++
 include/linux/blk_types.h          |   12 +++++-------
 23 files changed, 48 insertions(+), 45 deletions(-)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 1/2] block: add a bio_init_inline helper
  2025-09-08 10:56 remove the bi_inline_vecs field struct bio Christoph Hellwig
@ 2025-09-08 10:56 ` Christoph Hellwig
  2025-09-09  8:34   ` Yu Kuai
  2025-09-09  8:43   ` John Garry
  2025-09-08 10:56 ` [PATCH 2/2] block: remove the bi_inline_vecs variable sized array from struct bio Christoph Hellwig
  2025-09-09 13:32 ` remove the bi_inline_vecs field " Jens Axboe
  2 siblings, 2 replies; 13+ messages in thread
From: Christoph Hellwig @ 2025-09-08 10:56 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-block

Just a simpler wrapper around bio_init for callers that want to
initialize a bio with inline bvecs.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 block/bio.c                        | 7 +++++--
 block/blk-crypto-fallback.c        | 3 +--
 block/blk-map.c                    | 8 ++++----
 drivers/md/bcache/debug.c          | 3 +--
 drivers/md/bcache/io.c             | 3 +--
 drivers/md/bcache/journal.c        | 2 +-
 drivers/md/bcache/movinggc.c       | 2 +-
 drivers/md/bcache/super.c          | 2 +-
 drivers/md/bcache/writeback.c      | 2 +-
 drivers/md/dm-bufio.c              | 2 +-
 drivers/md/dm-flakey.c             | 2 +-
 drivers/md/raid1.c                 | 2 +-
 drivers/md/raid10.c                | 4 ++--
 drivers/target/target_core_pscsi.c | 2 +-
 fs/bcachefs/btree_io.c             | 2 +-
 fs/bcachefs/journal.c              | 2 +-
 fs/bcachefs/journal_io.c           | 2 +-
 fs/bcachefs/super-io.c             | 2 +-
 fs/squashfs/block.c                | 2 +-
 include/linux/bio.h                | 5 +++++
 20 files changed, 32 insertions(+), 27 deletions(-)

diff --git a/block/bio.c b/block/bio.c
index 44c43b970387..bd8bf179981a 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -462,7 +462,10 @@ static struct bio *bio_alloc_percpu_cache(struct block_device *bdev,
 	cache->nr--;
 	put_cpu();
 
-	bio_init(bio, bdev, nr_vecs ? bio->bi_inline_vecs : NULL, nr_vecs, opf);
+	if (nr_vecs)
+		bio_init_inline(bio, bdev, nr_vecs, opf);
+	else
+		bio_init(bio, bdev, NULL, nr_vecs, opf);
 	bio->bi_pool = bs;
 	return bio;
 }
@@ -578,7 +581,7 @@ struct bio *bio_alloc_bioset(struct block_device *bdev, unsigned short nr_vecs,
 
 		bio_init(bio, bdev, bvl, nr_vecs, opf);
 	} else if (nr_vecs) {
-		bio_init(bio, bdev, bio->bi_inline_vecs, BIO_INLINE_VECS, opf);
+		bio_init_inline(bio, bdev, BIO_INLINE_VECS, opf);
 	} else {
 		bio_init(bio, bdev, NULL, 0, opf);
 	}
diff --git a/block/blk-crypto-fallback.c b/block/blk-crypto-fallback.c
index 005c9157ffb3..dbc2d8784dab 100644
--- a/block/blk-crypto-fallback.c
+++ b/block/blk-crypto-fallback.c
@@ -167,8 +167,7 @@ static struct bio *blk_crypto_fallback_clone_bio(struct bio *bio_src)
 	bio = bio_kmalloc(nr_segs, GFP_NOIO);
 	if (!bio)
 		return NULL;
-	bio_init(bio, bio_src->bi_bdev, bio->bi_inline_vecs, nr_segs,
-		 bio_src->bi_opf);
+	bio_init_inline(bio, bio_src->bi_bdev, nr_segs, bio_src->bi_opf);
 	if (bio_flagged(bio_src, BIO_REMAPPED))
 		bio_set_flag(bio, BIO_REMAPPED);
 	bio->bi_ioprio		= bio_src->bi_ioprio;
diff --git a/block/blk-map.c b/block/blk-map.c
index 23e5d5ebe59e..92b7e19b1a1f 100644
--- a/block/blk-map.c
+++ b/block/blk-map.c
@@ -157,7 +157,7 @@ static int bio_copy_user_iov(struct request *rq, struct rq_map_data *map_data,
 	bio = bio_kmalloc(nr_pages, gfp_mask);
 	if (!bio)
 		goto out_bmd;
-	bio_init(bio, NULL, bio->bi_inline_vecs, nr_pages, req_op(rq));
+	bio_init_inline(bio, NULL, nr_pages, req_op(rq));
 
 	if (map_data) {
 		nr_pages = 1U << map_data->page_order;
@@ -264,7 +264,7 @@ static struct bio *blk_rq_map_bio_alloc(struct request *rq,
 		bio = bio_kmalloc(nr_vecs, gfp_mask);
 		if (!bio)
 			return NULL;
-		bio_init(bio, NULL, bio->bi_inline_vecs, nr_vecs, req_op(rq));
+		bio_init_inline(bio, NULL, nr_vecs, req_op(rq));
 	}
 	return bio;
 }
@@ -326,7 +326,7 @@ static struct bio *bio_map_kern(void *data, unsigned int len, enum req_op op,
 	bio = bio_kmalloc(nr_vecs, gfp_mask);
 	if (!bio)
 		return ERR_PTR(-ENOMEM);
-	bio_init(bio, NULL, bio->bi_inline_vecs, nr_vecs, op);
+	bio_init_inline(bio, NULL, nr_vecs, op);
 	if (is_vmalloc_addr(data)) {
 		bio->bi_private = data;
 		if (!bio_add_vmalloc(bio, data, len)) {
@@ -392,7 +392,7 @@ static struct bio *bio_copy_kern(void *data, unsigned int len, enum req_op op,
 	bio = bio_kmalloc(nr_pages, gfp_mask);
 	if (!bio)
 		return ERR_PTR(-ENOMEM);
-	bio_init(bio, NULL, bio->bi_inline_vecs, nr_pages, op);
+	bio_init_inline(bio, NULL, nr_pages, op);
 
 	while (len) {
 		struct page *page;
diff --git a/drivers/md/bcache/debug.c b/drivers/md/bcache/debug.c
index 7510d1c983a5..f327456fc4e0 100644
--- a/drivers/md/bcache/debug.c
+++ b/drivers/md/bcache/debug.c
@@ -115,8 +115,7 @@ void bch_data_verify(struct cached_dev *dc, struct bio *bio)
 	check = bio_kmalloc(nr_segs, GFP_NOIO);
 	if (!check)
 		return;
-	bio_init(check, bio->bi_bdev, check->bi_inline_vecs, nr_segs,
-		 REQ_OP_READ);
+	bio_init_inline(check, bio->bi_bdev, nr_segs, REQ_OP_READ);
 	check->bi_iter.bi_sector = bio->bi_iter.bi_sector;
 	check->bi_iter.bi_size = bio->bi_iter.bi_size;
 
diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c
index 020712c5203f..2386d08bf4e4 100644
--- a/drivers/md/bcache/io.c
+++ b/drivers/md/bcache/io.c
@@ -26,8 +26,7 @@ struct bio *bch_bbio_alloc(struct cache_set *c)
 	struct bbio *b = mempool_alloc(&c->bio_meta, GFP_NOIO);
 	struct bio *bio = &b->bio;
 
-	bio_init(bio, NULL, bio->bi_inline_vecs,
-		 meta_bucket_pages(&c->cache->sb), 0);
+	bio_init_inline(bio, NULL, meta_bucket_pages(&c->cache->sb), 0);
 
 	return bio;
 }
diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c
index 7ff14bd2feb8..d50eb82ccb4f 100644
--- a/drivers/md/bcache/journal.c
+++ b/drivers/md/bcache/journal.c
@@ -615,7 +615,7 @@ static void do_journal_discard(struct cache *ca)
 
 		atomic_set(&ja->discard_in_flight, DISCARD_IN_FLIGHT);
 
-		bio_init(bio, ca->bdev, bio->bi_inline_vecs, 1, REQ_OP_DISCARD);
+		bio_init_inline(bio, ca->bdev, 1, REQ_OP_DISCARD);
 		bio->bi_iter.bi_sector	= bucket_to_sector(ca->set,
 						ca->sb.d[ja->discard_idx]);
 		bio->bi_iter.bi_size	= bucket_bytes(ca);
diff --git a/drivers/md/bcache/movinggc.c b/drivers/md/bcache/movinggc.c
index 26a6a535ec32..4fc80c6d5b31 100644
--- a/drivers/md/bcache/movinggc.c
+++ b/drivers/md/bcache/movinggc.c
@@ -79,7 +79,7 @@ static void moving_init(struct moving_io *io)
 {
 	struct bio *bio = &io->bio.bio;
 
-	bio_init(bio, NULL, bio->bi_inline_vecs,
+	bio_init_inline(bio, NULL,
 		 DIV_ROUND_UP(KEY_SIZE(&io->w->key), PAGE_SECTORS), 0);
 	bio_get(bio);
 	bio->bi_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0);
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 1492c8552255..6d250e366412 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -2236,7 +2236,7 @@ static int cache_alloc(struct cache *ca)
 	__module_get(THIS_MODULE);
 	kobject_init(&ca->kobj, &bch_cache_ktype);
 
-	bio_init(&ca->journal.bio, NULL, ca->journal.bio.bi_inline_vecs, 8, 0);
+	bio_init_inline(&ca->journal.bio, NULL, 8, 0);
 
 	/*
 	 * When the cache disk is first registered, ca->sb.njournal_buckets
diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c
index 302e75f1fc4b..36dd8f14a6df 100644
--- a/drivers/md/bcache/writeback.c
+++ b/drivers/md/bcache/writeback.c
@@ -331,7 +331,7 @@ static void dirty_init(struct keybuf_key *w)
 	struct dirty_io *io = w->private;
 	struct bio *bio = &io->bio;
 
-	bio_init(bio, NULL, bio->bi_inline_vecs,
+	bio_init_inline(bio, NULL,
 		 DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS), 0);
 	if (!io->dc->writeback_percent)
 		bio->bi_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0);
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
index ff7595caf440..8f3a23f4b168 100644
--- a/drivers/md/dm-bufio.c
+++ b/drivers/md/dm-bufio.c
@@ -1342,7 +1342,7 @@ static void use_bio(struct dm_buffer *b, enum req_op op, sector_t sector,
 		use_dmio(b, op, sector, n_sectors, offset, ioprio);
 		return;
 	}
-	bio_init(bio, b->c->bdev, bio->bi_inline_vecs, 1, op);
+	bio_init_inline(bio, b->c->bdev, 1, op);
 	bio->bi_iter.bi_sector = sector;
 	bio->bi_end_io = bio_complete;
 	bio->bi_private = b;
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c
index cf17fd46e255..08925aca838c 100644
--- a/drivers/md/dm-flakey.c
+++ b/drivers/md/dm-flakey.c
@@ -441,7 +441,7 @@ static struct bio *clone_bio(struct dm_target *ti, struct flakey_c *fc, struct b
 	if (!clone)
 		return NULL;
 
-	bio_init(clone, fc->dev->bdev, clone->bi_inline_vecs, nr_iovecs, bio->bi_opf);
+	bio_init_inline(clone, fc->dev->bdev, nr_iovecs, bio->bi_opf);
 
 	clone->bi_iter.bi_sector = flakey_map_sector(ti, bio->bi_iter.bi_sector);
 	clone->bi_private = bio;
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 408c26398321..bc11aaa38615 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -167,7 +167,7 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data)
 		bio = bio_kmalloc(RESYNC_PAGES, gfp_flags);
 		if (!bio)
 			goto out_free_bio;
-		bio_init(bio, NULL, bio->bi_inline_vecs, RESYNC_PAGES, 0);
+		bio_init_inline(bio, NULL, RESYNC_PAGES, 0);
 		r1_bio->bios[j] = bio;
 	}
 	/*
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index b60c30bfb6c7..c52ccd12d86b 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -163,14 +163,14 @@ static void * r10buf_pool_alloc(gfp_t gfp_flags, void *data)
 		bio = bio_kmalloc(RESYNC_PAGES, gfp_flags);
 		if (!bio)
 			goto out_free_bio;
-		bio_init(bio, NULL, bio->bi_inline_vecs, RESYNC_PAGES, 0);
+		bio_init_inline(bio, NULL, RESYNC_PAGES, 0);
 		r10_bio->devs[j].bio = bio;
 		if (!conf->have_replacement)
 			continue;
 		bio = bio_kmalloc(RESYNC_PAGES, gfp_flags);
 		if (!bio)
 			goto out_free_bio;
-		bio_init(bio, NULL, bio->bi_inline_vecs, RESYNC_PAGES, 0);
+		bio_init_inline(bio, NULL, RESYNC_PAGES, 0);
 		r10_bio->devs[j].repl_bio = bio;
 	}
 	/*
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c
index f991cf759836..db4e09042469 100644
--- a/drivers/target/target_core_pscsi.c
+++ b/drivers/target/target_core_pscsi.c
@@ -861,7 +861,7 @@ pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
 				bio = bio_kmalloc(nr_vecs, GFP_KERNEL);
 				if (!bio)
 					goto fail;
-				bio_init(bio, NULL, bio->bi_inline_vecs, nr_vecs,
+				bio_init_inline(bio, NULL, nr_vecs,
 					 rw ? REQ_OP_WRITE : REQ_OP_READ);
 				bio->bi_end_io = pscsi_bi_endio;
 
diff --git a/fs/bcachefs/btree_io.c b/fs/bcachefs/btree_io.c
index 590cd29f3e86..e701e6d6e321 100644
--- a/fs/bcachefs/btree_io.c
+++ b/fs/bcachefs/btree_io.c
@@ -2084,7 +2084,7 @@ int bch2_btree_node_scrub(struct btree_trans *trans,
 
 	INIT_WORK(&scrub->work, btree_node_scrub_work);
 
-	bio_init(&scrub->bio, ca->disk_sb.bdev, scrub->bio.bi_inline_vecs, vecs, REQ_OP_READ);
+	bio_init_inline(&scrub->bio, ca->disk_sb.bdev, vecs, REQ_OP_READ);
 	bch2_bio_map(&scrub->bio, scrub->buf, c->opts.btree_node_size);
 	scrub->bio.bi_iter.bi_sector	= pick.ptr.offset;
 	scrub->bio.bi_end_io		= btree_node_scrub_endio;
diff --git a/fs/bcachefs/journal.c b/fs/bcachefs/journal.c
index ddfeb0dafc9d..3dbf9faaaa4c 100644
--- a/fs/bcachefs/journal.c
+++ b/fs/bcachefs/journal.c
@@ -1634,7 +1634,7 @@ int bch2_dev_journal_init(struct bch_dev *ca, struct bch_sb *sb)
 
 		ja->bio[i]->ca = ca;
 		ja->bio[i]->buf_idx = i;
-		bio_init(&ja->bio[i]->bio, NULL, ja->bio[i]->bio.bi_inline_vecs, nr_bvecs, 0);
+		bio_init_inline(&ja->bio[i]->bio, NULL, nr_bvecs, 0);
 	}
 
 	ja->buckets = kcalloc(ja->nr, sizeof(u64), GFP_KERNEL);
diff --git a/fs/bcachefs/journal_io.c b/fs/bcachefs/journal_io.c
index 9e028dbcc3d0..ce8888d518c3 100644
--- a/fs/bcachefs/journal_io.c
+++ b/fs/bcachefs/journal_io.c
@@ -1071,7 +1071,7 @@ static int journal_read_bucket(struct bch_dev *ca,
 			bio = bio_kmalloc(nr_bvecs, GFP_KERNEL);
 			if (!bio)
 				return bch_err_throw(c, ENOMEM_journal_read_bucket);
-			bio_init(bio, ca->disk_sb.bdev, bio->bi_inline_vecs, nr_bvecs, REQ_OP_READ);
+			bio_init_inline(bio, ca->disk_sb.bdev, nr_bvecs, REQ_OP_READ);
 
 			bio->bi_iter.bi_sector = offset;
 			bch2_bio_map(bio, buf->data, sectors_read << 9);
diff --git a/fs/bcachefs/super-io.c b/fs/bcachefs/super-io.c
index 6c2e1d647403..e3fcffb93d2b 100644
--- a/fs/bcachefs/super-io.c
+++ b/fs/bcachefs/super-io.c
@@ -232,7 +232,7 @@ int bch2_sb_realloc(struct bch_sb_handle *sb, unsigned u64s)
 		if (!bio)
 			return -BCH_ERR_ENOMEM_sb_bio_realloc;
 
-		bio_init(bio, NULL, bio->bi_inline_vecs, nr_bvecs, 0);
+		bio_init_inline(bio, NULL, nr_bvecs, 0);
 
 		kfree(sb->bio);
 		sb->bio = bio;
diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c
index b69c294e3ef0..a05e3793f93a 100644
--- a/fs/squashfs/block.c
+++ b/fs/squashfs/block.c
@@ -231,7 +231,7 @@ static int squashfs_bio_read(struct super_block *sb, u64 index, int length,
 	bio = bio_kmalloc(page_count, GFP_NOIO);
 	if (!bio)
 		return -ENOMEM;
-	bio_init(bio, sb->s_bdev, bio->bi_inline_vecs, page_count, REQ_OP_READ);
+	bio_init_inline(bio, sb->s_bdev, page_count, REQ_OP_READ);
 	bio->bi_iter.bi_sector = block * (msblk->devblksize >> SECTOR_SHIFT);
 
 	for (i = 0; i < page_count; ++i) {
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 46ffac5caab7..eb7f4fbd8aa9 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -405,6 +405,11 @@ struct request_queue;
 
 void bio_init(struct bio *bio, struct block_device *bdev, struct bio_vec *table,
 	      unsigned short max_vecs, blk_opf_t opf);
+static inline void bio_init_inline(struct bio *bio, struct block_device *bdev,
+	      unsigned short max_vecs, blk_opf_t opf)
+{
+	bio_init(bio, bdev, bio->bi_inline_vecs, max_vecs, opf);
+}
 extern void bio_uninit(struct bio *);
 void bio_reset(struct bio *bio, struct block_device *bdev, blk_opf_t opf);
 void bio_chain(struct bio *, struct bio *);
-- 
2.47.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 2/2] block: remove the bi_inline_vecs variable sized array from struct bio
  2025-09-08 10:56 remove the bi_inline_vecs field struct bio Christoph Hellwig
  2025-09-08 10:56 ` [PATCH 1/2] block: add a bio_init_inline helper Christoph Hellwig
@ 2025-09-08 10:56 ` Christoph Hellwig
  2025-09-09  8:16   ` John Garry
  2025-09-09 13:32 ` remove the bi_inline_vecs field " Jens Axboe
  2 siblings, 1 reply; 13+ messages in thread
From: Christoph Hellwig @ 2025-09-08 10:56 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-block

Bios are embedded into other structures, and at least spare is unhappy
about embedding structures with variable sized arrays.  There's no
real need to the array anyway, we can replace it with a helper pointing
to the memory just behind the bio, and with the previous cleanups there
is very few site doing anything special with it.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 block/bio.c                   |  3 ++-
 drivers/md/bcache/movinggc.c  |  6 +++---
 drivers/md/bcache/writeback.c |  6 +++---
 drivers/md/dm-vdo/vio.c       |  2 +-
 fs/bcachefs/data_update.h     |  1 -
 fs/bcachefs/journal.c         |  4 ++--
 include/linux/bio.h           |  2 +-
 include/linux/blk_types.h     | 12 +++++-------
 8 files changed, 17 insertions(+), 19 deletions(-)

diff --git a/block/bio.c b/block/bio.c
index bd8bf179981a..971d96afaf8d 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -617,7 +617,8 @@ struct bio *bio_kmalloc(unsigned short nr_vecs, gfp_t gfp_mask)
 
 	if (nr_vecs > BIO_MAX_INLINE_VECS)
 		return NULL;
-	return kmalloc(struct_size(bio, bi_inline_vecs, nr_vecs), gfp_mask);
+	return kmalloc(sizeof(*bio) + nr_vecs * sizeof(struct bio_vec),
+			gfp_mask);
 }
 EXPORT_SYMBOL(bio_kmalloc);
 
diff --git a/drivers/md/bcache/movinggc.c b/drivers/md/bcache/movinggc.c
index 4fc80c6d5b31..73918e55bf04 100644
--- a/drivers/md/bcache/movinggc.c
+++ b/drivers/md/bcache/movinggc.c
@@ -145,9 +145,9 @@ static void read_moving(struct cache_set *c)
 			continue;
 		}
 
-		io = kzalloc(struct_size(io, bio.bio.bi_inline_vecs,
-					 DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS)),
-			     GFP_KERNEL);
+		io = kzalloc(sizeof(*io) + sizeof(struct bio_vec) *
+				DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS),
+				GFP_KERNEL);
 		if (!io)
 			goto err;
 
diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c
index 36dd8f14a6df..6ba73dc1a3df 100644
--- a/drivers/md/bcache/writeback.c
+++ b/drivers/md/bcache/writeback.c
@@ -536,9 +536,9 @@ static void read_dirty(struct cached_dev *dc)
 		for (i = 0; i < nk; i++) {
 			w = keys[i];
 
-			io = kzalloc(struct_size(io, bio.bi_inline_vecs,
-						DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS)),
-				     GFP_KERNEL);
+			io = kzalloc(sizeof(*io) + sizeof(struct bio_vec) *
+				DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS),
+				GFP_KERNEL);
 			if (!io)
 				goto err;
 
diff --git a/drivers/md/dm-vdo/vio.c b/drivers/md/dm-vdo/vio.c
index e7f4153e55e3..8fc22fb14196 100644
--- a/drivers/md/dm-vdo/vio.c
+++ b/drivers/md/dm-vdo/vio.c
@@ -212,7 +212,7 @@ int vio_reset_bio_with_size(struct vio *vio, char *data, int size, bio_end_io_t
 		return VDO_SUCCESS;
 
 	bio->bi_ioprio = 0;
-	bio->bi_io_vec = bio->bi_inline_vecs;
+	bio->bi_io_vec = bio_inline_vecs(bio);
 	bio->bi_max_vecs = vio->block_count + 1;
 	if (VDO_ASSERT(size <= vio_size, "specified size %d is not greater than allocated %d",
 		       size, vio_size) != VDO_SUCCESS)
diff --git a/fs/bcachefs/data_update.h b/fs/bcachefs/data_update.h
index 5e14d13568de..1b37780abfda 100644
--- a/fs/bcachefs/data_update.h
+++ b/fs/bcachefs/data_update.h
@@ -62,7 +62,6 @@ struct promote_op {
 
 	struct work_struct	work;
 	struct data_update	write;
-	struct bio_vec		bi_inline_vecs[]; /* must be last */
 };
 
 void bch2_data_update_to_text(struct printbuf *, struct data_update *);
diff --git a/fs/bcachefs/journal.c b/fs/bcachefs/journal.c
index 3dbf9faaaa4c..474e0e867b68 100644
--- a/fs/bcachefs/journal.c
+++ b/fs/bcachefs/journal.c
@@ -1627,8 +1627,8 @@ int bch2_dev_journal_init(struct bch_dev *ca, struct bch_sb *sb)
 	unsigned nr_bvecs = DIV_ROUND_UP(JOURNAL_ENTRY_SIZE_MAX, PAGE_SIZE);
 
 	for (unsigned i = 0; i < ARRAY_SIZE(ja->bio); i++) {
-		ja->bio[i] = kzalloc(struct_size(ja->bio[i], bio.bi_inline_vecs,
-				     nr_bvecs), GFP_KERNEL);
+		ja->bio[i] = kzalloc(sizeof(*ja->bio[i]) +
+				sizeof(struct bio_vec) * nr_bvecs, GFP_KERNEL);
 		if (!ja->bio[i])
 			return bch_err_throw(c, ENOMEM_dev_journal_init);
 
diff --git a/include/linux/bio.h b/include/linux/bio.h
index eb7f4fbd8aa9..27cbff5b0356 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -408,7 +408,7 @@ void bio_init(struct bio *bio, struct block_device *bdev, struct bio_vec *table,
 static inline void bio_init_inline(struct bio *bio, struct block_device *bdev,
 	      unsigned short max_vecs, blk_opf_t opf)
 {
-	bio_init(bio, bdev, bio->bi_inline_vecs, max_vecs, opf);
+	bio_init(bio, bdev, bio_inline_vecs(bio), max_vecs, opf);
 }
 extern void bio_uninit(struct bio *);
 void bio_reset(struct bio *bio, struct block_device *bdev, blk_opf_t opf);
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index 930daff207df..bbb7893e0542 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -269,18 +269,16 @@ struct bio {
 	struct bio_vec		*bi_io_vec;	/* the actual vec list */
 
 	struct bio_set		*bi_pool;
-
-	/*
-	 * We can inline a number of vecs at the end of the bio, to avoid
-	 * double allocations for a small number of bio_vecs. This member
-	 * MUST obviously be kept at the very end of the bio.
-	 */
-	struct bio_vec		bi_inline_vecs[];
 };
 
 #define BIO_RESET_BYTES		offsetof(struct bio, bi_max_vecs)
 #define BIO_MAX_SECTORS		(UINT_MAX >> SECTOR_SHIFT)
 
+static inline struct bio_vec *bio_inline_vecs(struct bio *bio)
+{
+	return (struct bio_vec *)(bio + 1);
+}
+
 /*
  * bio flags
  */
-- 
2.47.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/2] block: remove the bi_inline_vecs variable sized array from struct bio
  2025-09-08 10:56 ` [PATCH 2/2] block: remove the bi_inline_vecs variable sized array from struct bio Christoph Hellwig
@ 2025-09-09  8:16   ` John Garry
  2025-09-09  8:40     ` Yu Kuai
  2025-09-11  6:07     ` Christoph Hellwig
  0 siblings, 2 replies; 13+ messages in thread
From: John Garry @ 2025-09-09  8:16 UTC (permalink / raw)
  To: Christoph Hellwig, Jens Axboe; +Cc: linux-block

On 08/09/2025 11:56, Christoph Hellwig wrote:
> Bios are embedded into other structures, and at least spare is unhappy

sparse?

> about embedding structures with variable sized arrays.  There's no
> real need to the array anyway,

"real need for the array anyway"?

> we can replace it with a helper pointing
> to the memory just behind the bio, and with the previous cleanups there
> is very few site doing anything special with it.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>

FWIW:
Reviewed-by: John Garry <john.g.garry@oracle.com>

> ---
>   block/bio.c                   |  3 ++-
>   drivers/md/bcache/movinggc.c  |  6 +++---
>   drivers/md/bcache/writeback.c |  6 +++---
>   drivers/md/dm-vdo/vio.c       |  2 +-
>   fs/bcachefs/data_update.h     |  1 -
>   fs/bcachefs/journal.c         |  4 ++--
>   include/linux/bio.h           |  2 +-
>   include/linux/blk_types.h     | 12 +++++-------
>   8 files changed, 17 insertions(+), 19 deletions(-)
> 
> diff --git a/block/bio.c b/block/bio.c
> index bd8bf179981a..971d96afaf8d 100644
> --- a/block/bio.c
> +++ b/block/bio.c
> @@ -617,7 +617,8 @@ struct bio *bio_kmalloc(unsigned short nr_vecs, gfp_t gfp_mask)
>   
>   	if (nr_vecs > BIO_MAX_INLINE_VECS)
>   		return NULL;
> -	return kmalloc(struct_size(bio, bi_inline_vecs, nr_vecs), gfp_mask);
> +	return kmalloc(sizeof(*bio) + nr_vecs * sizeof(struct bio_vec),
> +			gfp_mask);>   }
>   EXPORT_SYMBOL(bio_kmalloc);
>   
> diff --git a/drivers/md/bcache/movinggc.c b/drivers/md/bcache/movinggc.c
> index 4fc80c6d5b31..73918e55bf04 100644
> --- a/drivers/md/bcache/movinggc.c
> +++ b/drivers/md/bcache/movinggc.c
> @@ -145,9 +145,9 @@ static void read_moving(struct cache_set *c)
>   			continue;
>   		}
>   
> -		io = kzalloc(struct_size(io, bio.bio.bi_inline_vecs,
> -					 DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS)),
> -			     GFP_KERNEL);
> +		io = kzalloc(sizeof(*io) + sizeof(struct bio_vec) *
> +				DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS),
> +				GFP_KERNEL);

this seems a common pattern, so maybe another helper (which could be 
used by bio_kmalloc)? I am not advocating it, but just putting the idea 
out there... too many helpers makes it messy IMHO

>   		if (!io)
>   			goto err;
>   
> diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c
> index 36dd8f14a6df..6ba73dc1a3df 100644
> --- a/drivers/md/bcache/writeback.c
> +++ b/drivers/md/bcache/writeback.c
> @@ -536,9 +536,9 @@ static void read_dirty(struct cached_dev *dc)
>   		for (i = 0; i < nk; i++) {
>   			w = keys[i];
>   
> -			io = kzalloc(struct_size(io, bio.bi_inline_vecs,
> -						DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS)),
> -				     GFP_KERNEL);
> +			io = kzalloc(sizeof(*io) + sizeof(struct bio_vec) *
> +				DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS),
> +				GFP_KERNEL);
>   			if (!io)
>   				goto err;
>   
> diff --git a/drivers/md/dm-vdo/vio.c b/drivers/md/dm-vdo/vio.c
> index e7f4153e55e3..8fc22fb14196 100644
> --- a/drivers/md/dm-vdo/vio.c
> +++ b/drivers/md/dm-vdo/vio.c
> @@ -212,7 +212,7 @@ int vio_reset_bio_with_size(struct vio *vio, char *data, int size, bio_end_io_t
>   		return VDO_SUCCESS;
>   
>   	bio->bi_ioprio = 0;
> -	bio->bi_io_vec = bio->bi_inline_vecs;
> +	bio->bi_io_vec = bio_inline_vecs(bio);
>   	bio->bi_max_vecs = vio->block_count + 1;
>   	if (VDO_ASSERT(size <= vio_size, "specified size %d is not greater than allocated %d",
>   		       size, vio_size) != VDO_SUCCESS)
> diff --git a/fs/bcachefs/data_update.h b/fs/bcachefs/data_update.h
> index 5e14d13568de..1b37780abfda 100644
> --- a/fs/bcachefs/data_update.h
> +++ b/fs/bcachefs/data_update.h
> @@ -62,7 +62,6 @@ struct promote_op {
>   
>   	struct work_struct	work;
>   	struct data_update	write;
> -	struct bio_vec		bi_inline_vecs[]; /* must be last */
>   };
>   
>   void bch2_data_update_to_text(struct printbuf *, struct data_update *);
> diff --git a/fs/bcachefs/journal.c b/fs/bcachefs/journal.c
> index 3dbf9faaaa4c..474e0e867b68 100644
> --- a/fs/bcachefs/journal.c
> +++ b/fs/bcachefs/journal.c
> @@ -1627,8 +1627,8 @@ int bch2_dev_journal_init(struct bch_dev *ca, struct bch_sb *sb)
>   	unsigned nr_bvecs = DIV_ROUND_UP(JOURNAL_ENTRY_SIZE_MAX, PAGE_SIZE);
>   
>   	for (unsigned i = 0; i < ARRAY_SIZE(ja->bio); i++) {
> -		ja->bio[i] = kzalloc(struct_size(ja->bio[i], bio.bi_inline_vecs,
> -				     nr_bvecs), GFP_KERNEL);
> +		ja->bio[i] = kzalloc(sizeof(*ja->bio[i]) +
> +				sizeof(struct bio_vec) * nr_bvecs, GFP_KERNEL);
>   		if (!ja->bio[i])
>   			return bch_err_throw(c, ENOMEM_dev_journal_init);
>   
> diff --git a/include/linux/bio.h b/include/linux/bio.h
> index eb7f4fbd8aa9..27cbff5b0356 100644
> --- a/include/linux/bio.h
> +++ b/include/linux/bio.h
> @@ -408,7 +408,7 @@ void bio_init(struct bio *bio, struct block_device *bdev, struct bio_vec *table,
>   static inline void bio_init_inline(struct bio *bio, struct block_device *bdev,
>   	      unsigned short max_vecs, blk_opf_t opf)
>   {
> -	bio_init(bio, bdev, bio->bi_inline_vecs, max_vecs, opf);
> +	bio_init(bio, bdev, bio_inline_vecs(bio), max_vecs, opf);
>   }
>   extern void bio_uninit(struct bio *);
>   void bio_reset(struct bio *bio, struct block_device *bdev, blk_opf_t opf);
> diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
> index 930daff207df..bbb7893e0542 100644
> --- a/include/linux/blk_types.h
> +++ b/include/linux/blk_types.h
> @@ -269,18 +269,16 @@ struct bio {
>   	struct bio_vec		*bi_io_vec;	/* the actual vec list */
>   
>   	struct bio_set		*bi_pool;
> -
> -	/*
> -	 * We can inline a number of vecs at the end of the bio, to avoid
> -	 * double allocations for a small number of bio_vecs. This member
> -	 * MUST obviously be kept at the very end of the bio.
> -	 */
> -	struct bio_vec		bi_inline_vecs[];
>   };
>   
>   #define BIO_RESET_BYTES		offsetof(struct bio, bi_max_vecs)
>   #define BIO_MAX_SECTORS		(UINT_MAX >> SECTOR_SHIFT)
>   
> +static inline struct bio_vec *bio_inline_vecs(struct bio *bio)
> +{
> +	return (struct bio_vec *)(bio + 1);
> +}
> +
>   /*
>    * bio flags
>    */


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/2] block: add a bio_init_inline helper
  2025-09-08 10:56 ` [PATCH 1/2] block: add a bio_init_inline helper Christoph Hellwig
@ 2025-09-09  8:34   ` Yu Kuai
  2025-09-09  8:43   ` John Garry
  1 sibling, 0 replies; 13+ messages in thread
From: Yu Kuai @ 2025-09-09  8:34 UTC (permalink / raw)
  To: Christoph Hellwig, Jens Axboe; +Cc: linux-block, yukuai (C)

Hi,

在 2025/09/08 18:56, Christoph Hellwig 写道:
> Just a simpler wrapper around bio_init for callers that want to
> initialize a bio with inline bvecs.
> 
> Signed-off-by: Christoph Hellwig<hch@lst.de>
> ---
>   block/bio.c                        | 7 +++++--
>   block/blk-crypto-fallback.c        | 3 +--
>   block/blk-map.c                    | 8 ++++----
>   drivers/md/bcache/debug.c          | 3 +--
>   drivers/md/bcache/io.c             | 3 +--
>   drivers/md/bcache/journal.c        | 2 +-
>   drivers/md/bcache/movinggc.c       | 2 +-
>   drivers/md/bcache/super.c          | 2 +-
>   drivers/md/bcache/writeback.c      | 2 +-
>   drivers/md/dm-bufio.c              | 2 +-
>   drivers/md/dm-flakey.c             | 2 +-
>   drivers/md/raid1.c                 | 2 +-
>   drivers/md/raid10.c                | 4 ++--
>   drivers/target/target_core_pscsi.c | 2 +-
>   fs/bcachefs/btree_io.c             | 2 +-
>   fs/bcachefs/journal.c              | 2 +-
>   fs/bcachefs/journal_io.c           | 2 +-
>   fs/bcachefs/super-io.c             | 2 +-
>   fs/squashfs/block.c                | 2 +-
>   include/linux/bio.h                | 5 +++++
>   20 files changed, 32 insertions(+), 27 deletions(-)

For raid1 and raid10

Reviewed-by: Yu Kuai <yukuai3@huawei.com>
Thanks


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/2] block: remove the bi_inline_vecs variable sized array from struct bio
  2025-09-09  8:16   ` John Garry
@ 2025-09-09  8:40     ` Yu Kuai
  2025-09-09  8:55       ` John Garry
  2025-09-11  6:12       ` Christoph Hellwig
  2025-09-11  6:07     ` Christoph Hellwig
  1 sibling, 2 replies; 13+ messages in thread
From: Yu Kuai @ 2025-09-09  8:40 UTC (permalink / raw)
  To: John Garry, Christoph Hellwig, Jens Axboe; +Cc: linux-block, yukuai (C)

Hi,

在 2025/09/09 16:16, John Garry 写道:
>> diff --git a/drivers/md/bcache/movinggc.c b/drivers/md/bcache/movinggc.c
>> index 4fc80c6d5b31..73918e55bf04 100644
>> --- a/drivers/md/bcache/movinggc.c
>> +++ b/drivers/md/bcache/movinggc.c
>> @@ -145,9 +145,9 @@ static void read_moving(struct cache_set *c)
>>               continue;
>>           }
>> -        io = kzalloc(struct_size(io, bio.bio.bi_inline_vecs,
>> -                     DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS)),
>> -                 GFP_KERNEL);
>> +        io = kzalloc(sizeof(*io) + sizeof(struct bio_vec) *
>> +                DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS),
>> +                GFP_KERNEL);
> 
> this seems a common pattern, so maybe another helper (which could be 
> used by bio_kmalloc)? I am not advocating it, but just putting the idea 
> out there... too many helpers makes it messy IMHO

Not sure how to do this, do you mean a marco to pass in the base
structure type, nr_vecs and the gfp_mask?

Thanks,
Kuai


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/2] block: add a bio_init_inline helper
  2025-09-08 10:56 ` [PATCH 1/2] block: add a bio_init_inline helper Christoph Hellwig
  2025-09-09  8:34   ` Yu Kuai
@ 2025-09-09  8:43   ` John Garry
  2025-09-11  6:10     ` Christoph Hellwig
  1 sibling, 1 reply; 13+ messages in thread
From: John Garry @ 2025-09-09  8:43 UTC (permalink / raw)
  To: Christoph Hellwig, Jens Axboe; +Cc: linux-block

On 08/09/2025 11:56, Christoph Hellwig wrote:

Reviewed-by: John Garry <john.g.garry@oracle.com>

>   void bio_init(struct bio *bio, struct block_device *bdev, struct bio_vec *table,
>   	      unsigned short max_vecs, blk_opf_t opf);
> +static inline void bio_init_inline(struct bio *bio, struct block_device *bdev,
> +	      unsigned short max_vecs, blk_opf_t opf)
> +{

I suppose that a WARN_ON(max_vecs > BIO_MAX_INLINE_VECS) could be added, 
but I don't think that we generally protect against such self-inflicted 
programming errors.

> +	bio_init(bio, bdev, bio->bi_inline_vecs, max_vecs, opf);
> +}
>   extern void bio_uninit(struct bio *);


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/2] block: remove the bi_inline_vecs variable sized array from struct bio
  2025-09-09  8:40     ` Yu Kuai
@ 2025-09-09  8:55       ` John Garry
  2025-09-09  9:10         ` Yu Kuai
  2025-09-11  6:12       ` Christoph Hellwig
  1 sibling, 1 reply; 13+ messages in thread
From: John Garry @ 2025-09-09  8:55 UTC (permalink / raw)
  To: Yu Kuai, Christoph Hellwig, Jens Axboe; +Cc: linux-block, yukuai (C)

On 09/09/2025 09:40, Yu Kuai wrote:
> 
> 在 2025/09/09 16:16, John Garry 写道:
>>> diff --git a/drivers/md/bcache/movinggc.c b/drivers/md/bcache/movinggc.c
>>> index 4fc80c6d5b31..73918e55bf04 100644
>>> --- a/drivers/md/bcache/movinggc.c
>>> +++ b/drivers/md/bcache/movinggc.c
>>> @@ -145,9 +145,9 @@ static void read_moving(struct cache_set *c)
>>>               continue;
>>>           }
>>> -        io = kzalloc(struct_size(io, bio.bio.bi_inline_vecs,
>>> -                     DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS)),
>>> -                 GFP_KERNEL);
>>> +        io = kzalloc(sizeof(*io) + sizeof(struct bio_vec) *
>>> +                DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS),
>>> +                GFP_KERNEL);
>>
>> this seems a common pattern, so maybe another helper (which could be 
>> used by bio_kmalloc)? I am not advocating it, but just putting the 
>> idea out there... too many helpers makes it messy IMHO
> 
> Not sure how to do this, do you mean a marco to pass in the base
> structure type, nr_vecs and the gfp_mask?

something like the following (which I think is messy and an imprecise 
API, so again I am not advocating it):

struct bio *bio_kmalloc(unsigned short nr_vecs, gfp_t gfp_mask)
{
	return kmalloc(sizeof(struct bio) + nr_vecs * sizeof(struct bio_vec),
gfp_mask);
}

struct bio *bio_kmalloc_inline(unsigned short nr_vecs, gfp_t gfp_mask)
{
	if (nr_vecs > BIO_MAX_INLINE_VECS)
		return NULL;
	return bio_kmalloc(nr_vecs, gfp_mask);
}


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/2] block: remove the bi_inline_vecs variable sized array from struct bio
  2025-09-09  8:55       ` John Garry
@ 2025-09-09  9:10         ` Yu Kuai
  0 siblings, 0 replies; 13+ messages in thread
From: Yu Kuai @ 2025-09-09  9:10 UTC (permalink / raw)
  To: John Garry, Yu Kuai, Christoph Hellwig, Jens Axboe
  Cc: linux-block, yukuai (C)

Hi,

在 2025/09/09 16:55, John Garry 写道:
> On 09/09/2025 09:40, Yu Kuai wrote:
>>
>> 在 2025/09/09 16:16, John Garry 写道:
>>>> diff --git a/drivers/md/bcache/movinggc.c 
>>>> b/drivers/md/bcache/movinggc.c
>>>> index 4fc80c6d5b31..73918e55bf04 100644
>>>> --- a/drivers/md/bcache/movinggc.c
>>>> +++ b/drivers/md/bcache/movinggc.c
>>>> @@ -145,9 +145,9 @@ static void read_moving(struct cache_set *c)
>>>>               continue;
>>>>           }
>>>> -        io = kzalloc(struct_size(io, bio.bio.bi_inline_vecs,
>>>> -                     DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS)),
>>>> -                 GFP_KERNEL);
>>>> +        io = kzalloc(sizeof(*io) + sizeof(struct bio_vec) *
>>>> +                DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS),
>>>> +                GFP_KERNEL);
>>>
>>> this seems a common pattern, so maybe another helper (which could be 
>>> used by bio_kmalloc)? I am not advocating it, but just putting the 
>>> idea out there... too many helpers makes it messy IMHO
>>
>> Not sure how to do this, do you mean a marco to pass in the base
>> structure type, nr_vecs and the gfp_mask?
> 
> something like the following (which I think is messy and an imprecise 
> API, so again I am not advocating it):
> 
> struct bio *bio_kmalloc(unsigned short nr_vecs, gfp_t gfp_mask)
> {
>      return kmalloc(sizeof(struct bio) + nr_vecs * sizeof(struct bio_vec),
> gfp_mask);
> }
> 
> struct bio *bio_kmalloc_inline(unsigned short nr_vecs, gfp_t gfp_mask)
> {
>      if (nr_vecs > BIO_MAX_INLINE_VECS)
>          return NULL;
>      return bio_kmalloc(nr_vecs, gfp_mask);
> }
> 
However, the caller is allocating the base structure that bio is
embedded, the above helper to return bio is still not common.

Perhaps this patch is better anyway.

Thanks,
Kuai
> 
> .
> 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: remove the bi_inline_vecs field struct bio
  2025-09-08 10:56 remove the bi_inline_vecs field struct bio Christoph Hellwig
  2025-09-08 10:56 ` [PATCH 1/2] block: add a bio_init_inline helper Christoph Hellwig
  2025-09-08 10:56 ` [PATCH 2/2] block: remove the bi_inline_vecs variable sized array from struct bio Christoph Hellwig
@ 2025-09-09 13:32 ` Jens Axboe
  2 siblings, 0 replies; 13+ messages in thread
From: Jens Axboe @ 2025-09-09 13:32 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-block


On Mon, 08 Sep 2025 12:56:37 +0200, Christoph Hellwig wrote:
> the bi_inline_vecs causes sparse to warn when a bio is embedded into a
> structure, but not the last member.   This is a bit annoying but
> probably not a big.  But it can be easily fixed by just removing the
> member and doing pointer arithmetics in a helper, so do that.
> 
> Diffstat:
>  block/bio.c                        |   10 +++++++---
>  block/blk-crypto-fallback.c        |    3 +--
>  block/blk-map.c                    |    8 ++++----
>  drivers/md/bcache/debug.c          |    3 +--
>  drivers/md/bcache/io.c             |    3 +--
>  drivers/md/bcache/journal.c        |    2 +-
>  drivers/md/bcache/movinggc.c       |    8 ++++----
>  drivers/md/bcache/super.c          |    2 +-
>  drivers/md/bcache/writeback.c      |    8 ++++----
>  drivers/md/dm-bufio.c              |    2 +-
>  drivers/md/dm-flakey.c             |    2 +-
>  drivers/md/dm-vdo/vio.c            |    2 +-
>  drivers/md/raid1.c                 |    2 +-
>  drivers/md/raid10.c                |    4 ++--
>  drivers/target/target_core_pscsi.c |    2 +-
>  fs/bcachefs/btree_io.c             |    2 +-
>  fs/bcachefs/data_update.h          |    1 -
>  fs/bcachefs/journal.c              |    6 +++---
>  fs/bcachefs/journal_io.c           |    2 +-
>  fs/bcachefs/super-io.c             |    2 +-
>  fs/squashfs/block.c                |    2 +-
>  include/linux/bio.h                |    5 +++++
>  include/linux/blk_types.h          |   12 +++++-------
>  23 files changed, 48 insertions(+), 45 deletions(-)
> 
> [...]

Applied, thanks!

[1/2] block: add a bio_init_inline helper
      commit: 70a6f71b1a77decfc5b1db426ccbe914b58adb38
[2/2] block: remove the bi_inline_vecs variable sized array from struct bio
      commit: d86eaa0f3c56da286853b698b45c8ce404291082

Best regards,
-- 
Jens Axboe




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/2] block: remove the bi_inline_vecs variable sized array from struct bio
  2025-09-09  8:16   ` John Garry
  2025-09-09  8:40     ` Yu Kuai
@ 2025-09-11  6:07     ` Christoph Hellwig
  1 sibling, 0 replies; 13+ messages in thread
From: Christoph Hellwig @ 2025-09-11  6:07 UTC (permalink / raw)
  To: John Garry; +Cc: Christoph Hellwig, Jens Axboe, linux-block

On Tue, Sep 09, 2025 at 09:16:25AM +0100, John Garry wrote:
> On 08/09/2025 11:56, Christoph Hellwig wrote:
>> Bios are embedded into other structures, and at least spare is unhappy
>
> sparse?

Yes.

>
>> about embedding structures with variable sized arrays.  There's no
>> real need to the array anyway,
>
> "real need for the array anyway"?

Yes.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/2] block: add a bio_init_inline helper
  2025-09-09  8:43   ` John Garry
@ 2025-09-11  6:10     ` Christoph Hellwig
  0 siblings, 0 replies; 13+ messages in thread
From: Christoph Hellwig @ 2025-09-11  6:10 UTC (permalink / raw)
  To: John Garry; +Cc: Christoph Hellwig, Jens Axboe, linux-block

On Tue, Sep 09, 2025 at 09:43:55AM +0100, John Garry wrote:
>> +static inline void bio_init_inline(struct bio *bio, struct block_device *bdev,
>> +	      unsigned short max_vecs, blk_opf_t opf)
>> +{
>
> I suppose that a WARN_ON(max_vecs > BIO_MAX_INLINE_VECS) could be added, 
> but I don't think that we generally protect against such self-inflicted 
> programming errors.

It's not needed because there isn't actually any such limit.
BIO_MAX_INLINE_VECS is misnamed and misguided.  Various places in the
block layer require non-passthrough bios to not have more vectors than
BIO_MAX_VECS, while BIO_MAX_INLINE_VECS is a random upper bound for
passthrough I/O without a deeper meaning.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/2] block: remove the bi_inline_vecs variable sized array from struct bio
  2025-09-09  8:40     ` Yu Kuai
  2025-09-09  8:55       ` John Garry
@ 2025-09-11  6:12       ` Christoph Hellwig
  1 sibling, 0 replies; 13+ messages in thread
From: Christoph Hellwig @ 2025-09-11  6:12 UTC (permalink / raw)
  To: Yu Kuai; +Cc: John Garry, Christoph Hellwig, Jens Axboe, linux-block,
	yukuai (C)

On Tue, Sep 09, 2025 at 04:40:33PM +0800, Yu Kuai wrote:
> Hi,
>
> 在 2025/09/09 16:16, John Garry 写道:
>>> diff --git a/drivers/md/bcache/movinggc.c b/drivers/md/bcache/movinggc.c
>>> index 4fc80c6d5b31..73918e55bf04 100644
>>> --- a/drivers/md/bcache/movinggc.c
>>> +++ b/drivers/md/bcache/movinggc.c
>>> @@ -145,9 +145,9 @@ static void read_moving(struct cache_set *c)
>>>               continue;
>>>           }
>>> -        io = kzalloc(struct_size(io, bio.bio.bi_inline_vecs,
>>> -                     DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS)),
>>> -                 GFP_KERNEL);
>>> +        io = kzalloc(sizeof(*io) + sizeof(struct bio_vec) *
>>> +                DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS),
>>> +                GFP_KERNEL);
>>
>> this seems a common pattern, so maybe another helper (which could be used 
>> by bio_kmalloc)? I am not advocating it, but just putting the idea out 
>> there... too many helpers makes it messy IMHO
>
> Not sure how to do this, do you mean a marco to pass in the base
> structure type, nr_vecs and the gfp_mask?

It's not a very common pattern, and should be even less common.
If a driver / file system wants to embed a bio into its own structure
but dynamically allocate the bio_vecs, it can simply use kmalloc_array,
or add a bio_vec VLA to its own structure and use struct_size on that.


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2025-09-11  6:13 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-08 10:56 remove the bi_inline_vecs field struct bio Christoph Hellwig
2025-09-08 10:56 ` [PATCH 1/2] block: add a bio_init_inline helper Christoph Hellwig
2025-09-09  8:34   ` Yu Kuai
2025-09-09  8:43   ` John Garry
2025-09-11  6:10     ` Christoph Hellwig
2025-09-08 10:56 ` [PATCH 2/2] block: remove the bi_inline_vecs variable sized array from struct bio Christoph Hellwig
2025-09-09  8:16   ` John Garry
2025-09-09  8:40     ` Yu Kuai
2025-09-09  8:55       ` John Garry
2025-09-09  9:10         ` Yu Kuai
2025-09-11  6:12       ` Christoph Hellwig
2025-09-11  6:07     ` Christoph Hellwig
2025-09-09 13:32 ` remove the bi_inline_vecs field " Jens Axboe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox