-Wflex-array-member-not-at-end was introduced in GCC-14, and we are
getting ready to enable it, globally.

Use the new TRAILING_OVERLAP() helper to fix the following warning:

drivers/net/virtio_net.c:429:46: warning: structure containing a flexible array 
member is not at the end of another structure [-Wflex-array-member-not-at-end]

This helper creates a union between a flexible-array member (FAM)
and a set of members that would otherwise follow it (in this case
`u8 rss_hash_key_data[VIRTIO_NET_RSS_MAX_KEY_SIZE];`). This
overlays the trailing members (rss_hash_key_data) onto the FAM
(hash_key_data) while keeping the FAM and the start of MEMBERS aligned.
The static_assert() ensures this alignment remains, and it's
intentionally placed inmediately after `struct virtnet_info` (no
blank line in between).

Notice that due to tail padding in flexible `struct
virtio_net_rss_config_trailer`, `rss_trailer.hash_key_data`
(at offset 83 in struct virtnet_info) and `rss_hash_key_data` (at
offset 84 in struct virtnet_info) are misaligned by one byte. See
below:

struct virtio_net_rss_config_trailer {
        __le16                     max_tx_vq;            /*     0     2 */
        __u8                       hash_key_length;      /*     2     1 */
        __u8                       hash_key_data[];      /*     3     0 */

        /* size: 4, cachelines: 1, members: 3 */
        /* padding: 1 */
        /* last cacheline: 4 bytes */
};

struct virtnet_info {
...
        struct virtio_net_rss_config_trailer rss_trailer; /*    80     4 */

        /* XXX last struct has 1 byte of padding */

        u8                         rss_hash_key_data[40]; /*    84    40 */
...
        /* size: 832, cachelines: 13, members: 48 */
        /* sum members: 801, holes: 8, sum holes: 31 */
        /* paddings: 2, sum paddings: 5 */
};

After changes, those members are correctly aligned at offset 795:

struct virtnet_info {
...
        union {
                struct virtio_net_rss_config_trailer rss_trailer; /*   792     
4 */
                struct {
                        unsigned char __offset_to_hash_key_data[3]; /*   792    
 3 */
                        u8         rss_hash_key_data[40]; /*   795    40 */
                };                                       /*   792    43 */
        };                                               /*   792    44 */
...
        /* size: 840, cachelines: 14, members: 47 */
        /* sum members: 801, holes: 8, sum holes: 35 */
        /* padding: 4 */
        /* paddings: 1, sum paddings: 4 */
        /* last cacheline: 8 bytes */
};

As a last note `struct virtio_net_rss_config_hdr *rss_hdr;` is also
moved to the end, since it seems those three members should stick
around together. :)

Signed-off-by: Gustavo A. R. Silva <gustavo...@kernel.org>
---

This should probably include the following tag:

        Fixes: ed3100e90d0d ("virtio_net: Use new RSS config structs")

but I'd like to hear some feedback, first.

Thanks!

 drivers/net/virtio_net.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 975bdc5dab84..f4964a18a214 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -425,9 +425,6 @@ struct virtnet_info {
        u16 rss_indir_table_size;
        u32 rss_hash_types_supported;
        u32 rss_hash_types_saved;
-       struct virtio_net_rss_config_hdr *rss_hdr;
-       struct virtio_net_rss_config_trailer rss_trailer;
-       u8 rss_hash_key_data[VIRTIO_NET_RSS_MAX_KEY_SIZE];
 
        /* Has control virtqueue */
        bool has_cvq;
@@ -493,7 +490,16 @@ struct virtnet_info {
        struct failover *failover;
 
        u64 device_stats_cap;
+
+       struct virtio_net_rss_config_hdr *rss_hdr;
+
+       /* Must be last --ends in a flexible-array member. */
+       TRAILING_OVERLAP(struct virtio_net_rss_config_trailer, rss_trailer, 
hash_key_data,
+               u8 rss_hash_key_data[VIRTIO_NET_RSS_MAX_KEY_SIZE];
+       );
 };
+static_assert(offsetof(struct virtnet_info, rss_trailer.hash_key_data) ==
+             offsetof(struct virtnet_info, rss_hash_key_data));
 
 struct padded_vnet_hdr {
        struct virtio_net_hdr_v1_hash hdr;
-- 
2.43.0


Reply via email to