* [PATCH 1/8][next] block: blk_types.h: Use struct_group_tagged() in flex struct bio
2025-02-24 9:53 [PATCH 0/8][next] Avoid a couple hundred -Wflex-array-member-not-at-end warnings Gustavo A. R. Silva
@ 2025-02-24 9:55 ` Gustavo A. R. Silva
2025-02-24 16:39 ` Christoph Hellwig
2025-02-24 9:56 ` [PATCH 2/8][next] md/raid5-ppl: Avoid -Wflex-array-member-not-at-end warning Gustavo A. R. Silva
` (6 subsequent siblings)
7 siblings, 1 reply; 15+ messages in thread
From: Gustavo A. R. Silva @ 2025-02-24 9:55 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, linux-kernel, Gustavo A. R. Silva, linux-hardening
Use the `struct_group_tagged()` helper to create a new tagged
`struct bio_hdr`. This structure groups together all the members of
the flexible `struct bio` except the flexible array `bi_inline_vecs`.
As a result, the array is effectively separated from the rest of the
members without modifying the memory layout of the flexible structure.
This new tagged struct will be used to fix problematic declarations
of middle-flex-arrays in composite structs, like these[1][2][3], for
instance.
[1] https://git.kernel.org/linus/a7e8997ae18c42d3
[2] https://git.kernel.org/linus/c1ddb29709e675ea
[3] https://git.kernel.org/linus/57be3d3562ca4aa6
Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
---
include/linux/blk_types.h | 84 ++++++++++++++++++++-------------------
1 file changed, 44 insertions(+), 40 deletions(-)
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index dce7615c35e7..9182750457a8 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -212,62 +212,65 @@ typedef unsigned int blk_qc_t;
* stacking drivers)
*/
struct bio {
- struct bio *bi_next; /* request queue link */
- struct block_device *bi_bdev;
- blk_opf_t bi_opf; /* bottom bits REQ_OP, top bits
- * req_flags.
- */
- unsigned short bi_flags; /* BIO_* below */
- unsigned short bi_ioprio;
- enum rw_hint bi_write_hint;
- blk_status_t bi_status;
- atomic_t __bi_remaining;
-
- struct bvec_iter bi_iter;
-
- union {
- /* for polled bios: */
- blk_qc_t bi_cookie;
- /* for plugged zoned writes only: */
- unsigned int __bi_nr_segments;
- };
- bio_end_io_t *bi_end_io;
- void *bi_private;
+ /* New members MUST be added within the struct_group() macro below. */
+ struct_group_tagged(bio_hdr, __hdr,
+ struct bio *bi_next; /* request queue link */
+ struct block_device *bi_bdev;
+ blk_opf_t bi_opf; /* bottom bits REQ_OP, top bits
+ * req_flags.
+ */
+ unsigned short bi_flags; /* BIO_* below */
+ unsigned short bi_ioprio;
+ enum rw_hint bi_write_hint;
+ blk_status_t bi_status;
+ atomic_t __bi_remaining;
+
+ struct bvec_iter bi_iter;
+
+ union {
+ /* for polled bios: */
+ blk_qc_t bi_cookie;
+ /* for plugged zoned writes only: */
+ unsigned int __bi_nr_segments;
+ };
+ bio_end_io_t *bi_end_io;
+ void *bi_private;
#ifdef CONFIG_BLK_CGROUP
- /*
- * Represents the association of the css and request_queue for the bio.
- * If a bio goes direct to device, it will not have a blkg as it will
- * not have a request_queue associated with it. The reference is put
- * on release of the bio.
- */
- struct blkcg_gq *bi_blkg;
- struct bio_issue bi_issue;
+ /*
+ * Represents the association of the css and request_queue for the bio.
+ * If a bio goes direct to device, it will not have a blkg as it will
+ * not have a request_queue associated with it. The reference is put
+ * on release of the bio.
+ */
+ struct blkcg_gq *bi_blkg;
+ struct bio_issue bi_issue;
#ifdef CONFIG_BLK_CGROUP_IOCOST
- u64 bi_iocost_cost;
+ u64 bi_iocost_cost;
#endif
#endif
#ifdef CONFIG_BLK_INLINE_ENCRYPTION
- struct bio_crypt_ctx *bi_crypt_context;
+ struct bio_crypt_ctx *bi_crypt_context;
#endif
#if defined(CONFIG_BLK_DEV_INTEGRITY)
- struct bio_integrity_payload *bi_integrity; /* data integrity */
+ struct bio_integrity_payload *bi_integrity; /* data integrity */
#endif
- unsigned short bi_vcnt; /* how many bio_vec's */
+ unsigned short bi_vcnt; /* how many bio_vec's */
- /*
- * Everything starting with bi_max_vecs will be preserved by bio_reset()
- */
+ /*
+ * Everything starting with bi_max_vecs will be preserved by bio_reset()
+ */
- unsigned short bi_max_vecs; /* max bvl_vecs we can hold */
+ unsigned short bi_max_vecs; /* max bvl_vecs we can hold */
- atomic_t __bi_cnt; /* pin count */
+ atomic_t __bi_cnt; /* pin count */
- struct bio_vec *bi_io_vec; /* the actual vec list */
+ struct bio_vec *bi_io_vec; /* the actual vec list */
- struct bio_set *bi_pool;
+ struct bio_set *bi_pool;
+ );
/*
* We can inline a number of vecs at the end of the bio, to avoid
@@ -276,6 +279,8 @@ struct bio {
*/
struct bio_vec bi_inline_vecs[];
};
+static_assert(offsetof(struct bio, bi_inline_vecs) == sizeof(struct bio_hdr),
+ "struct member likely outside of struct_group_tagged()");
#define BIO_RESET_BYTES offsetof(struct bio, bi_max_vecs)
#define BIO_MAX_SECTORS (UINT_MAX >> SECTOR_SHIFT)
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH 1/8][next] block: blk_types.h: Use struct_group_tagged() in flex struct bio
2025-02-24 9:55 ` [PATCH 1/8][next] block: blk_types.h: Use struct_group_tagged() in flex struct bio Gustavo A. R. Silva
@ 2025-02-24 16:39 ` Christoph Hellwig
0 siblings, 0 replies; 15+ messages in thread
From: Christoph Hellwig @ 2025-02-24 16:39 UTC (permalink / raw)
To: Gustavo A. R. Silva
Cc: Jens Axboe, linux-block, linux-kernel, linux-hardening
On Mon, Feb 24, 2025 at 08:25:08PM +1030, Gustavo A. R. Silva wrote:
> Use the `struct_group_tagged()` helper to create a new tagged
> `struct bio_hdr`. This structure groups together all the members of
> the flexible `struct bio` except the flexible array `bi_inline_vecs`.
> As a result, the array is effectively separated from the rest of the
> members without modifying the memory layout of the flexible structure.
>
> This new tagged struct will be used to fix problematic declarations
> of middle-flex-arrays in composite structs, like these[1][2][3], for
> instance.
Well, I guess this goes with the context-less nvme patch. I think
you're much better off just removing the bi_inline_vecs array entirely,
and just add a new structure for bio + inline vecs for the few callers
that dynamically allocate the bio and actually have inline vecs.
Similar to what I did here for the bio integrity payload:
https://lore.kernel.org/linux-block/20250131122436.1317268-4-hch@lst.de/
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 2/8][next] md/raid5-ppl: Avoid -Wflex-array-member-not-at-end warning
2025-02-24 9:53 [PATCH 0/8][next] Avoid a couple hundred -Wflex-array-member-not-at-end warnings Gustavo A. R. Silva
2025-02-24 9:55 ` [PATCH 1/8][next] block: blk_types.h: Use struct_group_tagged() in flex struct bio Gustavo A. R. Silva
@ 2025-02-24 9:56 ` Gustavo A. R. Silva
2025-02-24 9:57 ` [PATCH 3/8][next] xfs: Avoid -Wflex-array-member-not-at-end warnings Gustavo A. R. Silva
` (5 subsequent siblings)
7 siblings, 0 replies; 15+ messages in thread
From: Gustavo A. R. Silva @ 2025-02-24 9:56 UTC (permalink / raw)
To: Song Liu, Yu Kuai
Cc: linux-raid, linux-kernel, Gustavo A. R. Silva, linux-hardening
-Wflex-array-member-not-at-end was introduced in GCC-14, and we are
getting ready to enable it, globally.
Change the type of the middle struct member currently causing trouble from
`struct bio` to `struct bio_hdr`.
We also use `container_of()` whenever we need to retrieve a pointer to
the flexible structure `struct bio`, through which we can access the
flexible-array member in it, if necessary.
With these changes fix the following warning:
drivers/md/raid5-ppl.c:153:20: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
---
drivers/md/raid5-ppl.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/md/raid5-ppl.c b/drivers/md/raid5-ppl.c
index c0fb335311aa..f4333c644b67 100644
--- a/drivers/md/raid5-ppl.c
+++ b/drivers/md/raid5-ppl.c
@@ -150,7 +150,7 @@ struct ppl_io_unit {
bool submitted; /* true if write to log started */
/* inline bio and its biovec for submitting the iounit */
- struct bio bio;
+ struct bio_hdr bio;
struct bio_vec biovec[PPL_IO_INLINE_BVECS];
};
@@ -250,8 +250,8 @@ static struct ppl_io_unit *ppl_new_iounit(struct ppl_log *log,
INIT_LIST_HEAD(&io->stripe_list);
atomic_set(&io->pending_stripes, 0);
atomic_set(&io->pending_flushes, 0);
- bio_init(&io->bio, log->rdev->bdev, io->biovec, PPL_IO_INLINE_BVECS,
- REQ_OP_WRITE | REQ_FUA);
+ bio_init(container_of(&io->bio, struct bio, __hdr), log->rdev->bdev,
+ io->biovec, PPL_IO_INLINE_BVECS, REQ_OP_WRITE | REQ_FUA);
pplhdr = page_address(io->header_page);
clear_page(pplhdr);
@@ -430,7 +430,7 @@ static void ppl_submit_iounit(struct ppl_io_unit *io)
struct ppl_log *log = io->log;
struct ppl_conf *ppl_conf = log->ppl_conf;
struct ppl_header *pplhdr = page_address(io->header_page);
- struct bio *bio = &io->bio;
+ struct bio *bio = container_of(&io->bio, struct bio, __hdr);
struct stripe_head *sh;
int i;
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 3/8][next] xfs: Avoid -Wflex-array-member-not-at-end warnings
2025-02-24 9:53 [PATCH 0/8][next] Avoid a couple hundred -Wflex-array-member-not-at-end warnings Gustavo A. R. Silva
2025-02-24 9:55 ` [PATCH 1/8][next] block: blk_types.h: Use struct_group_tagged() in flex struct bio Gustavo A. R. Silva
2025-02-24 9:56 ` [PATCH 2/8][next] md/raid5-ppl: Avoid -Wflex-array-member-not-at-end warning Gustavo A. R. Silva
@ 2025-02-24 9:57 ` Gustavo A. R. Silva
2025-02-24 19:12 ` Darrick J. Wong
2025-02-24 21:45 ` Dave Chinner
2025-02-24 9:58 ` [PATCH 4/8][next] erofs: " Gustavo A. R. Silva
` (4 subsequent siblings)
7 siblings, 2 replies; 15+ messages in thread
From: Gustavo A. R. Silva @ 2025-02-24 9:57 UTC (permalink / raw)
To: Carlos Maiolino, Darrick J. Wong
Cc: linux-xfs, linux-kernel, Gustavo A. R. Silva, linux-hardening
-Wflex-array-member-not-at-end was introduced in GCC-14, and we are
getting ready to enable it, globally.
Change the type of the middle struct members currently causing trouble
from `struct bio` to `struct bio_hdr`.
We also use `container_of()` whenever we need to retrieve a pointer to
the flexible structure `struct bio`, through which we can access the
flexible-array member in it, if necessary.
With these changes fix 27 of the following warnings:
fs/xfs/xfs_log_priv.h:208:33: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
---
fs/xfs/xfs_log.c | 15 +++++++++------
fs/xfs/xfs_log_priv.h | 2 +-
2 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index f8851ff835de..7e8b71f64a46 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -1245,7 +1245,7 @@ xlog_ioend_work(
}
xlog_state_done_syncing(iclog);
- bio_uninit(&iclog->ic_bio);
+ bio_uninit(container_of(&iclog->ic_bio, struct bio, __hdr));
/*
* Drop the lock to signal that we are done. Nothing references the
@@ -1663,7 +1663,8 @@ xlog_write_iclog(
* writeback throttle from throttling log writes behind background
* metadata writeback and causing priority inversions.
*/
- bio_init(&iclog->ic_bio, log->l_targ->bt_bdev, iclog->ic_bvec,
+ bio_init(container_of(&iclog->ic_bio, struct bio, __hdr),
+ log->l_targ->bt_bdev, iclog->ic_bvec,
howmany(count, PAGE_SIZE),
REQ_OP_WRITE | REQ_META | REQ_SYNC | REQ_IDLE);
iclog->ic_bio.bi_iter.bi_sector = log->l_logBBstart + bno;
@@ -1692,7 +1693,8 @@ xlog_write_iclog(
iclog->ic_flags &= ~(XLOG_ICL_NEED_FLUSH | XLOG_ICL_NEED_FUA);
- if (xlog_map_iclog_data(&iclog->ic_bio, iclog->ic_data, count))
+ if (xlog_map_iclog_data(container_of(&iclog->ic_bio, struct bio, __hdr),
+ iclog->ic_data, count))
goto shutdown;
if (is_vmalloc_addr(iclog->ic_data))
@@ -1705,16 +1707,17 @@ xlog_write_iclog(
if (bno + BTOBB(count) > log->l_logBBsize) {
struct bio *split;
- split = bio_split(&iclog->ic_bio, log->l_logBBsize - bno,
+ split = bio_split(container_of(&iclog->ic_bio, struct bio, __hdr),
+ log->l_logBBsize - bno,
GFP_NOIO, &fs_bio_set);
- bio_chain(split, &iclog->ic_bio);
+ bio_chain(split, container_of(&iclog->ic_bio, struct bio, __hdr));
submit_bio(split);
/* restart at logical offset zero for the remainder */
iclog->ic_bio.bi_iter.bi_sector = log->l_logBBstart;
}
- submit_bio(&iclog->ic_bio);
+ submit_bio(container_of(&iclog->ic_bio, struct bio, __hdr));
return;
shutdown:
xlog_force_shutdown(log, SHUTDOWN_LOG_IO_ERROR);
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index f3d78869e5e5..32abc48aef24 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -205,7 +205,7 @@ typedef struct xlog_in_core {
#endif
struct semaphore ic_sema;
struct work_struct ic_end_io_work;
- struct bio ic_bio;
+ struct bio_hdr ic_bio;
struct bio_vec ic_bvec[];
} xlog_in_core_t;
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH 3/8][next] xfs: Avoid -Wflex-array-member-not-at-end warnings
2025-02-24 9:57 ` [PATCH 3/8][next] xfs: Avoid -Wflex-array-member-not-at-end warnings Gustavo A. R. Silva
@ 2025-02-24 19:12 ` Darrick J. Wong
2025-02-24 21:45 ` Dave Chinner
1 sibling, 0 replies; 15+ messages in thread
From: Darrick J. Wong @ 2025-02-24 19:12 UTC (permalink / raw)
To: Gustavo A. R. Silva
Cc: Carlos Maiolino, linux-xfs, linux-kernel, linux-hardening
On Mon, Feb 24, 2025 at 08:27:44PM +1030, Gustavo A. R. Silva wrote:
> -Wflex-array-member-not-at-end was introduced in GCC-14, and we are
> getting ready to enable it, globally.
>
> Change the type of the middle struct members currently causing trouble
> from `struct bio` to `struct bio_hdr`.
>
> We also use `container_of()` whenever we need to retrieve a pointer to
> the flexible structure `struct bio`, through which we can access the
> flexible-array member in it, if necessary.
>
> With these changes fix 27 of the following warnings:
>
> fs/xfs/xfs_log_priv.h:208:33: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
>
> Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
> ---
> fs/xfs/xfs_log.c | 15 +++++++++------
> fs/xfs/xfs_log_priv.h | 2 +-
> 2 files changed, 10 insertions(+), 7 deletions(-)
>
> diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
> index f8851ff835de..7e8b71f64a46 100644
> --- a/fs/xfs/xfs_log.c
> +++ b/fs/xfs/xfs_log.c
> @@ -1245,7 +1245,7 @@ xlog_ioend_work(
> }
>
> xlog_state_done_syncing(iclog);
> - bio_uninit(&iclog->ic_bio);
> + bio_uninit(container_of(&iclog->ic_bio, struct bio, __hdr));
>
> /*
> * Drop the lock to signal that we are done. Nothing references the
> @@ -1663,7 +1663,8 @@ xlog_write_iclog(
> * writeback throttle from throttling log writes behind background
> * metadata writeback and causing priority inversions.
> */
> - bio_init(&iclog->ic_bio, log->l_targ->bt_bdev, iclog->ic_bvec,
> + bio_init(container_of(&iclog->ic_bio, struct bio, __hdr),
> + log->l_targ->bt_bdev, iclog->ic_bvec,
> howmany(count, PAGE_SIZE),
> REQ_OP_WRITE | REQ_META | REQ_SYNC | REQ_IDLE);
> iclog->ic_bio.bi_iter.bi_sector = log->l_logBBstart + bno;
> @@ -1692,7 +1693,8 @@ xlog_write_iclog(
>
> iclog->ic_flags &= ~(XLOG_ICL_NEED_FLUSH | XLOG_ICL_NEED_FUA);
>
> - if (xlog_map_iclog_data(&iclog->ic_bio, iclog->ic_data, count))
> + if (xlog_map_iclog_data(container_of(&iclog->ic_bio, struct bio, __hdr),
> + iclog->ic_data, count))
> goto shutdown;
>
> if (is_vmalloc_addr(iclog->ic_data))
> @@ -1705,16 +1707,17 @@ xlog_write_iclog(
> if (bno + BTOBB(count) > log->l_logBBsize) {
> struct bio *split;
>
> - split = bio_split(&iclog->ic_bio, log->l_logBBsize - bno,
> + split = bio_split(container_of(&iclog->ic_bio, struct bio, __hdr),
> + log->l_logBBsize - bno,
> GFP_NOIO, &fs_bio_set);
> - bio_chain(split, &iclog->ic_bio);
> + bio_chain(split, container_of(&iclog->ic_bio, struct bio, __hdr));
> submit_bio(split);
>
> /* restart at logical offset zero for the remainder */
> iclog->ic_bio.bi_iter.bi_sector = log->l_logBBstart;
> }
>
> - submit_bio(&iclog->ic_bio);
> + submit_bio(container_of(&iclog->ic_bio, struct bio, __hdr));
> return;
> shutdown:
> xlog_force_shutdown(log, SHUTDOWN_LOG_IO_ERROR);
> diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
> index f3d78869e5e5..32abc48aef24 100644
> --- a/fs/xfs/xfs_log_priv.h
> +++ b/fs/xfs/xfs_log_priv.h
> @@ -205,7 +205,7 @@ typedef struct xlog_in_core {
> #endif
> struct semaphore ic_sema;
> struct work_struct ic_end_io_work;
> - struct bio ic_bio;
> + struct bio_hdr ic_bio;
What struct is this?
$ git grep 'struct bio_hdr' include/
$
(Please always send the core code change patches to the xfs list.)
--D
> struct bio_vec ic_bvec[];
> } xlog_in_core_t;
>
> --
> 2.43.0
>
>
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH 3/8][next] xfs: Avoid -Wflex-array-member-not-at-end warnings
2025-02-24 9:57 ` [PATCH 3/8][next] xfs: Avoid -Wflex-array-member-not-at-end warnings Gustavo A. R. Silva
2025-02-24 19:12 ` Darrick J. Wong
@ 2025-02-24 21:45 ` Dave Chinner
1 sibling, 0 replies; 15+ messages in thread
From: Dave Chinner @ 2025-02-24 21:45 UTC (permalink / raw)
To: Gustavo A. R. Silva
Cc: Carlos Maiolino, Darrick J. Wong, linux-xfs, linux-kernel,
linux-hardening
On Mon, Feb 24, 2025 at 08:27:44PM +1030, Gustavo A. R. Silva wrote:
> -Wflex-array-member-not-at-end was introduced in GCC-14, and we are
> getting ready to enable it, globally.
>
> Change the type of the middle struct members currently causing trouble
> from `struct bio` to `struct bio_hdr`.
What's this bio_hdr thing? You haven't sent the patch to the XFS
list, so we cannot review this for correctness. Please cc the
-entire- patch set to -all- recipients so we can see the whole
change in it's full context.
> We also use `container_of()` whenever we need to retrieve a pointer to
> the flexible structure `struct bio`, through which we can access the
> flexible-array member in it, if necessary.
>
> With these changes fix 27 of the following warnings:
>
> fs/xfs/xfs_log_priv.h:208:33: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
>
> Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
> ---
> fs/xfs/xfs_log.c | 15 +++++++++------
> fs/xfs/xfs_log_priv.h | 2 +-
> 2 files changed, 10 insertions(+), 7 deletions(-)
>
> diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
> index f8851ff835de..7e8b71f64a46 100644
> --- a/fs/xfs/xfs_log.c
> +++ b/fs/xfs/xfs_log.c
> @@ -1245,7 +1245,7 @@ xlog_ioend_work(
> }
>
> xlog_state_done_syncing(iclog);
> - bio_uninit(&iclog->ic_bio);
> + bio_uninit(container_of(&iclog->ic_bio, struct bio, __hdr));
This is a pretty nasty conversion. The code is obviously correct
right now - the bio uses an external bvec table, so has no
associated allocated bvec space and so the bio isn't flexibly
sized.
Making the code more complex for humans to understand and get
right because "the compiler is dumb" is a bad tradeoff.
I also think this is a really nasty way of fixing the problem;
casting the fixed size structure to a flex sized structure that can
overlap other parent structure fields really isn't a good solution.
IMO, it is a recipe for unexpected memory corruption when the bio
isn't set up properly by the caller or there are bugs in the way the
bio is iterated/processed....
> return;
> shutdown:
> xlog_force_shutdown(log, SHUTDOWN_LOG_IO_ERROR);
> diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
> index f3d78869e5e5..32abc48aef24 100644
> --- a/fs/xfs/xfs_log_priv.h
> +++ b/fs/xfs/xfs_log_priv.h
> @@ -205,7 +205,7 @@ typedef struct xlog_in_core {
> #endif
> struct semaphore ic_sema;
> struct work_struct ic_end_io_work;
> - struct bio ic_bio;
> + struct bio_hdr ic_bio;
> struct bio_vec ic_bvec[];
But then there is the bigger question: ic_bvec is a *fixed size*
that is allocated at mount time. The fact it is defined as a
flexible array is the problem here, not the embedding of a struct
bio. i.e. we've used a flex array to optimise away an extra
allocation in a non-performance sensitive path.
Hence if we had done it this way:
struct bvec *ic_bvecs;
struct bio ic_bio; // must be last
};
and use another allocation for ic_bvecs in xlog_alloc_log() (similar
to how we do the separate allocation of the *ic_data buffer that is
mapped into ic_bio at IO time), then none of the code that accesses
ic_bio for IO purposes needs to change and the compiler warnings go
away. That's a much cleaner solution that requires no extra
cognitive load on developers to maintain in correct working order.
-Dave.
--
Dave Chinner
david@fromorbit.com
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 4/8][next] erofs: Avoid -Wflex-array-member-not-at-end warnings
2025-02-24 9:53 [PATCH 0/8][next] Avoid a couple hundred -Wflex-array-member-not-at-end warnings Gustavo A. R. Silva
` (2 preceding siblings ...)
2025-02-24 9:57 ` [PATCH 3/8][next] xfs: Avoid -Wflex-array-member-not-at-end warnings Gustavo A. R. Silva
@ 2025-02-24 9:58 ` Gustavo A. R. Silva
2025-02-24 9:59 ` [PATCH 5/8][next] btrfs: " Gustavo A. R. Silva
` (3 subsequent siblings)
7 siblings, 0 replies; 15+ messages in thread
From: Gustavo A. R. Silva @ 2025-02-24 9:58 UTC (permalink / raw)
To: Gao Xiang, Chao Yu, Yue Hu, Jeffle Xu, Sandeep Dhavale
Cc: linux-erofs, linux-kernel, Gustavo A. R. Silva, linux-hardening
-Wflex-array-member-not-at-end was introduced in GCC-14, and we are
getting ready to enable it, globally.
Change the type of the middle struct member currently causing trouble from
`struct bio` to `struct bio_hdr`.
We also use `container_of()` whenever we need to retrieve a pointer to
the flexible structure `struct bio`, through which we can access the
flexible-array member in it, if necessary.
With these changes fix the following warnings:
fs/erofs/fileio.c:10:20: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
fs/erofs/fscache.c:179:20: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
---
fs/erofs/fileio.c | 25 +++++++++++++++----------
fs/erofs/fscache.c | 13 +++++++------
2 files changed, 22 insertions(+), 16 deletions(-)
diff --git a/fs/erofs/fileio.c b/fs/erofs/fileio.c
index 0ffd1c63beeb..3080963caf78 100644
--- a/fs/erofs/fileio.c
+++ b/fs/erofs/fileio.c
@@ -7,7 +7,7 @@
struct erofs_fileio_rq {
struct bio_vec bvecs[16];
- struct bio bio;
+ struct bio_hdr bio;
struct kiocb iocb;
struct super_block *sb;
};
@@ -26,20 +26,21 @@ static void erofs_fileio_ki_complete(struct kiocb *iocb, long ret)
if (ret > 0) {
if (ret != rq->bio.bi_iter.bi_size) {
- bio_advance(&rq->bio, ret);
- zero_fill_bio(&rq->bio);
+ bio_advance(container_of(&rq->bio, struct bio, __hdr),
+ ret);
+ zero_fill_bio(container_of(&rq->bio, struct bio, __hdr));
}
ret = 0;
}
if (rq->bio.bi_end_io) {
- rq->bio.bi_end_io(&rq->bio);
+ rq->bio.bi_end_io(container_of(&rq->bio, struct bio, __hdr));
} else {
- bio_for_each_folio_all(fi, &rq->bio) {
+ bio_for_each_folio_all(fi, container_of(&rq->bio, struct bio, __hdr)) {
DBG_BUGON(folio_test_uptodate(fi.folio));
erofs_onlinefolio_end(fi.folio, ret);
}
}
- bio_uninit(&rq->bio);
+ bio_uninit(container_of(&rq->bio, struct bio, __hdr));
kfree(rq);
}
@@ -68,7 +69,8 @@ static struct erofs_fileio_rq *erofs_fileio_rq_alloc(struct erofs_map_dev *mdev)
struct erofs_fileio_rq *rq = kzalloc(sizeof(*rq),
GFP_KERNEL | __GFP_NOFAIL);
- bio_init(&rq->bio, NULL, rq->bvecs, ARRAY_SIZE(rq->bvecs), REQ_OP_READ);
+ bio_init(container_of(&rq->bio, struct bio, __hdr), NULL, rq->bvecs,
+ ARRAY_SIZE(rq->bvecs), REQ_OP_READ);
rq->iocb.ki_filp = mdev->m_dif->file;
rq->sb = mdev->m_sb;
return rq;
@@ -76,12 +78,13 @@ static struct erofs_fileio_rq *erofs_fileio_rq_alloc(struct erofs_map_dev *mdev)
struct bio *erofs_fileio_bio_alloc(struct erofs_map_dev *mdev)
{
- return &erofs_fileio_rq_alloc(mdev)->bio;
+ return container_of(&erofs_fileio_rq_alloc(mdev)->bio, struct bio, __hdr);
}
void erofs_fileio_submit_bio(struct bio *bio)
{
- return erofs_fileio_rq_submit(container_of(bio, struct erofs_fileio_rq,
+ return erofs_fileio_rq_submit(container_of(&bio->__hdr,
+ struct erofs_fileio_rq,
bio));
}
@@ -150,7 +153,9 @@ static int erofs_fileio_scan_folio(struct erofs_fileio *io, struct folio *folio)
}
if (!attached++)
erofs_onlinefolio_split(folio);
- if (!bio_add_folio(&io->rq->bio, folio, len, cur))
+ if (!bio_add_folio(container_of(&io->rq->bio,
+ struct bio, __hdr),
+ folio, len, cur))
goto io_retry;
io->dev.m_pa += len;
}
diff --git a/fs/erofs/fscache.c b/fs/erofs/fscache.c
index ce3d8737df85..719ec96c8f22 100644
--- a/fs/erofs/fscache.c
+++ b/fs/erofs/fscache.c
@@ -176,7 +176,7 @@ static int erofs_fscache_read_io_async(struct fscache_cookie *cookie,
struct erofs_fscache_bio {
struct erofs_fscache_io io;
- struct bio bio; /* w/o bdev to share bio_add_page/endio() */
+ struct bio_hdr bio; /* w/o bdev to share bio_add_page/endio() */
struct bio_vec bvecs[BIO_MAX_VECS];
};
@@ -187,7 +187,7 @@ static void erofs_fscache_bio_endio(void *priv,
if (IS_ERR_VALUE(transferred_or_error))
io->bio.bi_status = errno_to_blk_status(transferred_or_error);
- io->bio.bi_end_io(&io->bio);
+ io->bio.bi_end_io(container_of(&io->bio, struct bio, __hdr));
BUILD_BUG_ON(offsetof(struct erofs_fscache_bio, io) != 0);
erofs_fscache_io_put(&io->io);
}
@@ -197,17 +197,18 @@ struct bio *erofs_fscache_bio_alloc(struct erofs_map_dev *mdev)
struct erofs_fscache_bio *io;
io = kmalloc(sizeof(*io), GFP_KERNEL | __GFP_NOFAIL);
- bio_init(&io->bio, NULL, io->bvecs, BIO_MAX_VECS, REQ_OP_READ);
+ bio_init(container_of(&io->bio, struct bio, __hdr), NULL, io->bvecs,
+ BIO_MAX_VECS, REQ_OP_READ);
io->io.private = mdev->m_dif->fscache->cookie;
io->io.end_io = erofs_fscache_bio_endio;
refcount_set(&io->io.ref, 1);
- return &io->bio;
+ return container_of(&io->bio, struct bio, __hdr);
}
void erofs_fscache_submit_bio(struct bio *bio)
{
- struct erofs_fscache_bio *io = container_of(bio,
- struct erofs_fscache_bio, bio);
+ struct erofs_fscache_bio *io =
+ container_of(&bio->__hdr, struct erofs_fscache_bio, bio);
int ret;
iov_iter_bvec(&io->io.iter, ITER_DEST, io->bvecs, bio->bi_vcnt,
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 5/8][next] btrfs: Avoid -Wflex-array-member-not-at-end warnings
2025-02-24 9:53 [PATCH 0/8][next] Avoid a couple hundred -Wflex-array-member-not-at-end warnings Gustavo A. R. Silva
` (3 preceding siblings ...)
2025-02-24 9:58 ` [PATCH 4/8][next] erofs: " Gustavo A. R. Silva
@ 2025-02-24 9:59 ` Gustavo A. R. Silva
2025-02-24 10:00 ` [PATCH 6/8][next] nvme: target: " Gustavo A. R. Silva
` (2 subsequent siblings)
7 siblings, 0 replies; 15+ messages in thread
From: Gustavo A. R. Silva @ 2025-02-24 9:59 UTC (permalink / raw)
To: Chris Mason, Josef Bacik, David Sterba
Cc: linux-btrfs, linux-kernel, Gustavo A. R. Silva, linux-hardening
-Wflex-array-member-not-at-end was introduced in GCC-14, and we are
getting ready to enable it, globally.
Change the type of the middle struct member currently causing trouble
from `struct bio` to `struct bio_hdr`.
We also use `container_of()` whenever we need to retrieve a pointer to
the flexible structure `struct bio`, through which we can access the
flexible-array member in it, if necessary.
With these changes fix 32 of the following warnings:
fs/btrfs/volumes.h:178:20: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
---
fs/btrfs/disk-io.c | 4 ++--
fs/btrfs/volumes.h | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index f09db62e61a1..2fbaaa9ab3e3 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -3963,7 +3963,7 @@ static void btrfs_end_empty_barrier(struct bio *bio)
*/
static void write_dev_flush(struct btrfs_device *device)
{
- struct bio *bio = &device->flush_bio;
+ struct bio *bio = container_of(&device->flush_bio, struct bio, __hdr);
device->last_flush_error = BLK_STS_OK;
@@ -3982,7 +3982,7 @@ static void write_dev_flush(struct btrfs_device *device)
*/
static bool wait_dev_flush(struct btrfs_device *device)
{
- struct bio *bio = &device->flush_bio;
+ struct bio *bio = container_of(&device->flush_bio, struct bio, __hdr);
if (!test_and_clear_bit(BTRFS_DEV_STATE_FLUSH_SENT, &device->dev_state))
return false;
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 120f65e21eeb..6eb55103b3d1 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -175,7 +175,7 @@ struct btrfs_device {
u64 commit_bytes_used;
/* Bio used for flushing device barriers */
- struct bio flush_bio;
+ struct bio_hdr flush_bio;
struct completion flush_wait;
/* per-device scrub information */
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 6/8][next] nvme: target: Avoid -Wflex-array-member-not-at-end warnings
2025-02-24 9:53 [PATCH 0/8][next] Avoid a couple hundred -Wflex-array-member-not-at-end warnings Gustavo A. R. Silva
` (4 preceding siblings ...)
2025-02-24 9:59 ` [PATCH 5/8][next] btrfs: " Gustavo A. R. Silva
@ 2025-02-24 10:00 ` Gustavo A. R. Silva
2025-02-24 14:19 ` Christoph Hellwig
2025-02-24 10:00 ` [PATCH 7/8][next] md/raid5: " Gustavo A. R. Silva
2025-02-24 10:01 ` [PATCH 8/8][next] bcache: " Gustavo A. R. Silva
7 siblings, 1 reply; 15+ messages in thread
From: Gustavo A. R. Silva @ 2025-02-24 10:00 UTC (permalink / raw)
To: Christoph Hellwig, Sagi Grimberg, Chaitanya Kulkarni
Cc: linux-nvme, linux-kernel, Gustavo A. R. Silva, linux-hardening
-Wflex-array-member-not-at-end was introduced in GCC-14, and we are
getting ready to enable it, globally.
Change the type of the middle struct members currently causing trouble
from `struct bio` to `struct bio_hdr`.
We also use `container_of()` whenever we need to retrieve a pointer to
the flexible structure `struct bio`, through which we can access the
flexible-array member in it, if necessary.
With these changes fix 38 of the following warnings:
drivers/nvme/target/nvmet.h:455:49: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
drivers/nvme/target/nvmet.h:462:49: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
---
drivers/nvme/target/nvmet.h | 4 ++--
drivers/nvme/target/passthru.c | 2 +-
drivers/nvme/target/zns.c | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index 4be8d22d2d8d..13ee8026d3d8 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -452,14 +452,14 @@ struct nvmet_req {
struct work_struct work;
} f;
struct {
- struct bio inline_bio;
+ struct bio_hdr inline_bio;
struct request *rq;
struct work_struct work;
bool use_workqueue;
} p;
#ifdef CONFIG_BLK_DEV_ZONED
struct {
- struct bio inline_bio;
+ struct bio_hdr inline_bio;
struct work_struct zmgmt_work;
} z;
#endif /* CONFIG_BLK_DEV_ZONED */
diff --git a/drivers/nvme/target/passthru.c b/drivers/nvme/target/passthru.c
index 26e2907ce8bb..bff52252ffb9 100644
--- a/drivers/nvme/target/passthru.c
+++ b/drivers/nvme/target/passthru.c
@@ -268,7 +268,7 @@ static int nvmet_passthru_map_sg(struct nvmet_req *req, struct request *rq)
return -EINVAL;
if (nvmet_use_inline_bvec(req)) {
- bio = &req->p.inline_bio;
+ bio = container_of(&req->p.inline_bio, struct bio, __hdr);
bio_init(bio, NULL, req->inline_bvec,
ARRAY_SIZE(req->inline_bvec), req_op(rq));
} else {
diff --git a/drivers/nvme/target/zns.c b/drivers/nvme/target/zns.c
index 29a60fabfcc8..afedbd984d39 100644
--- a/drivers/nvme/target/zns.c
+++ b/drivers/nvme/target/zns.c
@@ -570,7 +570,7 @@ void nvmet_bdev_execute_zone_append(struct nvmet_req *req)
}
if (nvmet_use_inline_bvec(req)) {
- bio = &req->z.inline_bio;
+ bio = container_of(&req->z.inline_bio, struct bio, __hdr);
bio_init(bio, req->ns->bdev, req->inline_bvec,
ARRAY_SIZE(req->inline_bvec), opf);
} else {
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH 6/8][next] nvme: target: Avoid -Wflex-array-member-not-at-end warnings
2025-02-24 10:00 ` [PATCH 6/8][next] nvme: target: " Gustavo A. R. Silva
@ 2025-02-24 14:19 ` Christoph Hellwig
2025-02-25 1:51 ` Gustavo A. R. Silva
0 siblings, 1 reply; 15+ messages in thread
From: Christoph Hellwig @ 2025-02-24 14:19 UTC (permalink / raw)
To: Gustavo A. R. Silva
Cc: Christoph Hellwig, Sagi Grimberg, Chaitanya Kulkarni, linux-nvme,
linux-kernel, linux-hardening
On Mon, Feb 24, 2025 at 08:30:10PM +1030, Gustavo A. R. Silva wrote:
> -Wflex-array-member-not-at-end was introduced in GCC-14, and we are
> getting ready to enable it, globally.
>
> Change the type of the middle struct members currently causing trouble
> from `struct bio` to `struct bio_hdr`.
>
> We also use `container_of()` whenever we need to retrieve a pointer to
> the flexible structure `struct bio`, through which we can access the
> flexible-array member in it, if necessary.
>
> With these changes fix 38 of the following warnings:
>
> drivers/nvme/target/nvmet.h:455:49: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
> drivers/nvme/target/nvmet.h:462:49: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
>
I'm not sure where you bio_hdr structure comes from, but maybe that's
because you annoyingly split CC over the series, and by the number of
patches probably also bundled unrelated changes.
In general our first resort here should be to move embedded bio to the
of containing structures. If that's not possible you'll need to explain
why.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 6/8][next] nvme: target: Avoid -Wflex-array-member-not-at-end warnings
2025-02-24 14:19 ` Christoph Hellwig
@ 2025-02-25 1:51 ` Gustavo A. R. Silva
0 siblings, 0 replies; 15+ messages in thread
From: Gustavo A. R. Silva @ 2025-02-25 1:51 UTC (permalink / raw)
To: Christoph Hellwig, Gustavo A. R. Silva
Cc: Sagi Grimberg, Chaitanya Kulkarni, linux-nvme, linux-kernel,
linux-hardening
On 25/02/25 00:49, Christoph Hellwig wrote:
> On Mon, Feb 24, 2025 at 08:30:10PM +1030, Gustavo A. R. Silva wrote:
>> -Wflex-array-member-not-at-end was introduced in GCC-14, and we are
>> getting ready to enable it, globally.
>>
>> Change the type of the middle struct members currently causing trouble
>> from `struct bio` to `struct bio_hdr`.
>>
>> We also use `container_of()` whenever we need to retrieve a pointer to
>> the flexible structure `struct bio`, through which we can access the
>> flexible-array member in it, if necessary.
>>
>> With these changes fix 38 of the following warnings:
>>
>> drivers/nvme/target/nvmet.h:455:49: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
>> drivers/nvme/target/nvmet.h:462:49: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
>>
>
> I'm not sure where you bio_hdr structure comes from, but maybe that's
> because you annoyingly split CC over the series, and by the number of
> patches probably also bundled unrelated changes.
Ugh, yes, I messed up my script just before creating the series.
>
> In general our first resort here should be to move embedded bio to the
> of containing structures. If that's not possible you'll need to explain
> why.
>
Yes. Also, thanks for the feedback in your other response. I'll try to
follow that approach and see how it goes.
--
Gustavo
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 7/8][next] md/raid5: Avoid -Wflex-array-member-not-at-end warnings
2025-02-24 9:53 [PATCH 0/8][next] Avoid a couple hundred -Wflex-array-member-not-at-end warnings Gustavo A. R. Silva
` (5 preceding siblings ...)
2025-02-24 10:00 ` [PATCH 6/8][next] nvme: target: " Gustavo A. R. Silva
@ 2025-02-24 10:00 ` Gustavo A. R. Silva
2025-02-24 10:01 ` [PATCH 8/8][next] bcache: " Gustavo A. R. Silva
7 siblings, 0 replies; 15+ messages in thread
From: Gustavo A. R. Silva @ 2025-02-24 10:00 UTC (permalink / raw)
To: Song Liu, Yu Kuai
Cc: linux-raid, linux-kernel, Gustavo A. R. Silva, linux-hardening
-Wflex-array-member-not-at-end was introduced in GCC-14, and we are
getting ready to enable it, globally.
Change the type of the middle struct members currently causing trouble
from `struct bio` to `struct bio_hdr`.
We also use `container_of()` whenever we need to retrieve a pointer to
the flexible structure `struct bio`, through which we can access the
flexible-array member in it, if necessary.
With these changes fix 10 of the following warnings:
drivers/md/raid5.h:262:33: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
drivers/md/raid5.h:262:38: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
---
drivers/md/raid5.c | 10 +++++-----
drivers/md/raid5.h | 2 +-
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 5c79429acc64..76981d8cbc5d 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -1178,8 +1178,8 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
again:
dev = &sh->dev[i];
- bi = &dev->req;
- rbi = &dev->rreq; /* For writing to replacement */
+ bi = container_of(&dev->req, struct bio, __hdr);
+ rbi = container_of(&dev->rreq, struct bio, __hdr); /* For writing to replacement */
rdev = conf->disks[i].rdev;
rrdev = conf->disks[i].replacement;
@@ -2720,7 +2720,7 @@ static void raid5_end_read_request(struct bio * bi)
sector_t s;
for (i=0 ; i<disks; i++)
- if (bi == &sh->dev[i].req)
+ if (bi == container_of(&sh->dev[i].req, struct bio, __hdr))
break;
pr_debug("end_read_request %llu/%d, count: %d, error %d.\n",
@@ -2848,11 +2848,11 @@ static void raid5_end_write_request(struct bio *bi)
int replacement = 0;
for (i = 0 ; i < disks; i++) {
- if (bi == &sh->dev[i].req) {
+ if (bi == container_of(&sh->dev[i].req, struct bio, __hdr)) {
rdev = conf->disks[i].rdev;
break;
}
- if (bi == &sh->dev[i].rreq) {
+ if (bi == container_of(&sh->dev[i].rreq, struct bio, __hdr)) {
rdev = conf->disks[i].replacement;
if (rdev)
replacement = 1;
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h
index eafc6e9ed6ee..3df59302e953 100644
--- a/drivers/md/raid5.h
+++ b/drivers/md/raid5.h
@@ -259,7 +259,7 @@ struct stripe_head {
/* rreq and rvec are used for the replacement device when
* writing data to both devices.
*/
- struct bio req, rreq;
+ struct bio_hdr req, rreq;
struct bio_vec vec, rvec;
struct page *page, *orig_page;
unsigned int offset; /* offset of the page */
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 8/8][next] bcache: Avoid -Wflex-array-member-not-at-end warnings
2025-02-24 9:53 [PATCH 0/8][next] Avoid a couple hundred -Wflex-array-member-not-at-end warnings Gustavo A. R. Silva
` (6 preceding siblings ...)
2025-02-24 10:00 ` [PATCH 7/8][next] md/raid5: " Gustavo A. R. Silva
@ 2025-02-24 10:01 ` Gustavo A. R. Silva
2025-02-24 14:04 ` Coly Li
7 siblings, 1 reply; 15+ messages in thread
From: Gustavo A. R. Silva @ 2025-02-24 10:01 UTC (permalink / raw)
To: Coly Li, Kent Overstreet
Cc: linux-bcache, linux-kernel, Gustavo A. R. Silva, linux-hardening
-Wflex-array-member-not-at-end was introduced in GCC-14, and we are
getting ready to enable it, globally.
Change the type of the middle struct members currently causing trouble
from `struct bio` to `struct bio_hdr`.
We also use `container_of()` whenever we need to retrieve a pointer to
the flexible structure `struct bio`, through which we can access the
flexible-array member in it, if necessary.
With these changes fix 112 of the following warnings:
drivers/md/bcache/bcache.h:233:33: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
drivers/md/bcache/bcache.h:241:33: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
drivers/md/bcache/bcache.h:242:33: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
drivers/md/bcache/bcache.h:308:33: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
drivers/md/bcache/bcache.h:422:33: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
drivers/md/bcache/bcache.h:639:33: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
drivers/md/bcache/journal.h:152:33: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
drivers/md/bcache/journal.h:156:33: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
---
drivers/md/bcache/bcache.h | 4 ++--
drivers/md/bcache/journal.c | 10 +++++-----
drivers/md/bcache/journal.h | 4 ++--
drivers/md/bcache/super.c | 8 +++++---
4 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h
index 785b0d9008fa..328023e90eb2 100644
--- a/drivers/md/bcache/bcache.h
+++ b/drivers/md/bcache/bcache.h
@@ -305,7 +305,7 @@ struct cached_dev {
struct cache_sb sb;
struct cache_sb_disk *sb_disk;
- struct bio sb_bio;
+ struct bio_hdr sb_bio;
struct bio_vec sb_bv[1];
struct closure sb_write;
struct semaphore sb_write_mutex;
@@ -419,7 +419,7 @@ struct cache {
struct cache_set *set;
struct cache_sb sb;
struct cache_sb_disk *sb_disk;
- struct bio sb_bio;
+ struct bio_hdr sb_bio;
struct bio_vec sb_bv[1];
struct kobject kobj;
diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c
index 7ff14bd2feb8..2ead129f7758 100644
--- a/drivers/md/bcache/journal.c
+++ b/drivers/md/bcache/journal.c
@@ -36,7 +36,7 @@ static int journal_read_bucket(struct cache *ca, struct list_head *list,
unsigned int bucket_index)
{
struct journal_device *ja = &ca->journal;
- struct bio *bio = &ja->bio;
+ struct bio *bio = container_of(&ja->bio, struct bio, __hdr);
struct journal_replay *i;
struct jset *j, *data = ca->set->journal.w[0].data;
@@ -571,7 +571,7 @@ static void btree_flush_write(struct cache_set *c)
static void journal_discard_endio(struct bio *bio)
{
struct journal_device *ja =
- container_of(bio, struct journal_device, discard_bio);
+ container_of(&bio->__hdr, struct journal_device, discard_bio);
struct cache *ca = container_of(ja, struct cache, journal);
atomic_set(&ja->discard_in_flight, DISCARD_DONE);
@@ -585,13 +585,13 @@ static void journal_discard_work(struct work_struct *work)
struct journal_device *ja =
container_of(work, struct journal_device, discard_work);
- submit_bio(&ja->discard_bio);
+ submit_bio(container_of(&ja->discard_bio, struct bio, __hdr));
}
static void do_journal_discard(struct cache *ca)
{
struct journal_device *ja = &ca->journal;
- struct bio *bio = &ja->discard_bio;
+ struct bio *bio = container_of(&ja->discard_bio, struct bio, __hdr);
if (!ca->discard) {
ja->discard_idx = ja->last_idx;
@@ -787,7 +787,7 @@ static CLOSURE_CALLBACK(journal_write_unlocked)
for (i = 0; i < KEY_PTRS(k); i++) {
ca = c->cache;
- bio = &ca->journal.bio;
+ bio = container_of(&ca->journal.bio, struct bio, __hdr);
atomic_long_add(sectors, &ca->meta_sectors_written);
diff --git a/drivers/md/bcache/journal.h b/drivers/md/bcache/journal.h
index cd316b4a1e95..b4ff5269aee3 100644
--- a/drivers/md/bcache/journal.h
+++ b/drivers/md/bcache/journal.h
@@ -149,11 +149,11 @@ struct journal_device {
atomic_t discard_in_flight;
struct work_struct discard_work;
- struct bio discard_bio;
+ struct bio_hdr discard_bio;
struct bio_vec discard_bv;
/* Bio for journal reads/writes to this device */
- struct bio bio;
+ struct bio_hdr bio;
struct bio_vec bv[8];
};
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index e42f1400cea9..cd1342355cf2 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -337,7 +337,7 @@ static CLOSURE_CALLBACK(bch_write_bdev_super_unlock)
void bch_write_bdev_super(struct cached_dev *dc, struct closure *parent)
{
struct closure *cl = &dc->sb_write;
- struct bio *bio = &dc->sb_bio;
+ struct bio *bio = container_of(&dc->sb_bio, struct bio, __hdr);
down(&dc->sb_write_mutex);
closure_init(cl, parent);
@@ -374,7 +374,7 @@ void bcache_write_super(struct cache_set *c)
{
struct closure *cl = &c->sb_write;
struct cache *ca = c->cache;
- struct bio *bio = &ca->sb_bio;
+ struct bio *bio = container_of(&ca->sb_bio, struct bio, __hdr);
unsigned int version = BCACHE_SB_VERSION_CDEV_WITH_UUID;
down(&c->sb_write_mutex);
@@ -2230,7 +2230,9 @@ 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(container_of(&ca->journal.bio, struct bio, __hdr), NULL,
+ container_of(&ca->journal.bio, struct bio, __hdr)->bi_inline_vecs,
+ 8, 0);
/*
* when ca->sb.njournal_buckets is not zero, journal exists,
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH 8/8][next] bcache: Avoid -Wflex-array-member-not-at-end warnings
2025-02-24 10:01 ` [PATCH 8/8][next] bcache: " Gustavo A. R. Silva
@ 2025-02-24 14:04 ` Coly Li
0 siblings, 0 replies; 15+ messages in thread
From: Coly Li @ 2025-02-24 14:04 UTC (permalink / raw)
To: Gustavo A. R. Silva
Cc: Kent Overstreet, linux-bcache, linux-kernel, linux-hardening
On Mon, Feb 24, 2025 at 08:31:26PM +0800, Gustavo A. R. Silva wrote:
> -Wflex-array-member-not-at-end was introduced in GCC-14, and we are
> getting ready to enable it, globally.
>
> Change the type of the middle struct members currently causing trouble
> from `struct bio` to `struct bio_hdr`.
>
> We also use `container_of()` whenever we need to retrieve a pointer to
> the flexible structure `struct bio`, through which we can access the
> flexible-array member in it, if necessary.
>
> With these changes fix 112 of the following warnings:
>
> drivers/md/bcache/bcache.h:233:33: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
> drivers/md/bcache/bcache.h:241:33: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
> drivers/md/bcache/bcache.h:242:33: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
> drivers/md/bcache/bcache.h:308:33: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
> drivers/md/bcache/bcache.h:422:33: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
> drivers/md/bcache/bcache.h:639:33: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
> drivers/md/bcache/journal.h:152:33: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
> drivers/md/bcache/journal.h:156:33: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
>
> Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
Hi Gustavo,
each struct bio followed by a struct bio_vec at the location where
struct bio is embedded into middle of a structure. So the general
flex-array-in-middle issue doesn't exist here indeed.
I don't suggest to introduce extra complication in bcache code.
How about to improve the checking script, if there is no following
struct bio_vec after struct bio, then that should be something really
suspicious.
Thanks.
Coly Li
> ---
> drivers/md/bcache/bcache.h | 4 ++--
> drivers/md/bcache/journal.c | 10 +++++-----
> drivers/md/bcache/journal.h | 4 ++--
> drivers/md/bcache/super.c | 8 +++++---
> 4 files changed, 14 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h
> index 785b0d9008fa..328023e90eb2 100644
> --- a/drivers/md/bcache/bcache.h
> +++ b/drivers/md/bcache/bcache.h
> @@ -305,7 +305,7 @@ struct cached_dev {
>
> struct cache_sb sb;
> struct cache_sb_disk *sb_disk;
> - struct bio sb_bio;
> + struct bio_hdr sb_bio;
> struct bio_vec sb_bv[1];
> struct closure sb_write;
> struct semaphore sb_write_mutex;
> @@ -419,7 +419,7 @@ struct cache {
> struct cache_set *set;
> struct cache_sb sb;
> struct cache_sb_disk *sb_disk;
> - struct bio sb_bio;
> + struct bio_hdr sb_bio;
> struct bio_vec sb_bv[1];
>
> struct kobject kobj;
> diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c
> index 7ff14bd2feb8..2ead129f7758 100644
> --- a/drivers/md/bcache/journal.c
> +++ b/drivers/md/bcache/journal.c
> @@ -36,7 +36,7 @@ static int journal_read_bucket(struct cache *ca, struct list_head *list,
> unsigned int bucket_index)
> {
> struct journal_device *ja = &ca->journal;
> - struct bio *bio = &ja->bio;
> + struct bio *bio = container_of(&ja->bio, struct bio, __hdr);
>
> struct journal_replay *i;
> struct jset *j, *data = ca->set->journal.w[0].data;
> @@ -571,7 +571,7 @@ static void btree_flush_write(struct cache_set *c)
> static void journal_discard_endio(struct bio *bio)
> {
> struct journal_device *ja =
> - container_of(bio, struct journal_device, discard_bio);
> + container_of(&bio->__hdr, struct journal_device, discard_bio);
> struct cache *ca = container_of(ja, struct cache, journal);
>
> atomic_set(&ja->discard_in_flight, DISCARD_DONE);
> @@ -585,13 +585,13 @@ static void journal_discard_work(struct work_struct *work)
> struct journal_device *ja =
> container_of(work, struct journal_device, discard_work);
>
> - submit_bio(&ja->discard_bio);
> + submit_bio(container_of(&ja->discard_bio, struct bio, __hdr));
> }
>
> static void do_journal_discard(struct cache *ca)
> {
> struct journal_device *ja = &ca->journal;
> - struct bio *bio = &ja->discard_bio;
> + struct bio *bio = container_of(&ja->discard_bio, struct bio, __hdr);
>
> if (!ca->discard) {
> ja->discard_idx = ja->last_idx;
> @@ -787,7 +787,7 @@ static CLOSURE_CALLBACK(journal_write_unlocked)
>
> for (i = 0; i < KEY_PTRS(k); i++) {
> ca = c->cache;
> - bio = &ca->journal.bio;
> + bio = container_of(&ca->journal.bio, struct bio, __hdr);
>
> atomic_long_add(sectors, &ca->meta_sectors_written);
>
> diff --git a/drivers/md/bcache/journal.h b/drivers/md/bcache/journal.h
> index cd316b4a1e95..b4ff5269aee3 100644
> --- a/drivers/md/bcache/journal.h
> +++ b/drivers/md/bcache/journal.h
> @@ -149,11 +149,11 @@ struct journal_device {
> atomic_t discard_in_flight;
>
> struct work_struct discard_work;
> - struct bio discard_bio;
> + struct bio_hdr discard_bio;
> struct bio_vec discard_bv;
>
> /* Bio for journal reads/writes to this device */
> - struct bio bio;
> + struct bio_hdr bio;
> struct bio_vec bv[8];
> };
>
> diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
> index e42f1400cea9..cd1342355cf2 100644
> --- a/drivers/md/bcache/super.c
> +++ b/drivers/md/bcache/super.c
> @@ -337,7 +337,7 @@ static CLOSURE_CALLBACK(bch_write_bdev_super_unlock)
> void bch_write_bdev_super(struct cached_dev *dc, struct closure *parent)
> {
> struct closure *cl = &dc->sb_write;
> - struct bio *bio = &dc->sb_bio;
> + struct bio *bio = container_of(&dc->sb_bio, struct bio, __hdr);
>
> down(&dc->sb_write_mutex);
> closure_init(cl, parent);
> @@ -374,7 +374,7 @@ void bcache_write_super(struct cache_set *c)
> {
> struct closure *cl = &c->sb_write;
> struct cache *ca = c->cache;
> - struct bio *bio = &ca->sb_bio;
> + struct bio *bio = container_of(&ca->sb_bio, struct bio, __hdr);
> unsigned int version = BCACHE_SB_VERSION_CDEV_WITH_UUID;
>
> down(&c->sb_write_mutex);
> @@ -2230,7 +2230,9 @@ 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(container_of(&ca->journal.bio, struct bio, __hdr), NULL,
> + container_of(&ca->journal.bio, struct bio, __hdr)->bi_inline_vecs,
> + 8, 0);
>
> /*
> * when ca->sb.njournal_buckets is not zero, journal exists,
> --
> 2.43.0
>
--
Coly Li
^ permalink raw reply [flat|nested] 15+ messages in thread