Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

scsi: fc: Avoid -Wflex-array-member-not-at-end warnings

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

So, in order to avoid ending up with a flexible-array member in the
middle of multiple other structs, we use the '__struct_group()' helper
to create a new tagged 'struct fc_df_desc_fpin_reg_hdr'. This structure
groups together all the members of the flexible 'struct
fc_df_desc_fpin_reg' except the flexible array.

As a result, the array is effectively separated from the rest of the
members without modifying the memory layout of the flexible structure.
We then change the type of the middle struct members currently causing
trouble from 'struct fc_df_desc_fpin_reg' to 'struct
fc_df_desc_fpin_reg_hdr'.

We also want to ensure that in case new members need to be added to the
flexible structure, they are always included within the newly created
tagged struct. For this, we use '_Static_assert()'. This ensures that
the memory layout for both the flexible structure and the new tagged
struct is the same after any changes.

This approach avoids having to implement 'struct fc_df_desc_fpin_reg_hdr'
as a completely separate structure, thus preventing having to maintain
two independent but basically identical structures, closing the door
to potential bugs in the future.

The above is also done for flexible structures 'struct fc_els_rdf' and
'struct fc_els_rdf_resp'

So, with these changes, fix the following warnings:
drivers/scsi/lpfc/lpfc_hw4.h:4936:41: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
drivers/scsi/lpfc/lpfc_hw4.h:4942:41: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
drivers/scsi/lpfc/lpfc_hw4.h:4947:41: 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>
Link: https://lore.kernel.org/r/aK6hbQLyQlvlySf8@kspp
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Justin Tee <justin.tee@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Gustavo A. R. Silva and committed by
Martin K. Petersen
44b6169a bee3554d

+43 -23
+1 -1
drivers/scsi/lpfc/lpfc_els.c
··· 3762 3762 memset(prdf, 0, cmdsize); 3763 3763 prdf->rdf.fpin_cmd = ELS_RDF; 3764 3764 prdf->rdf.desc_len = cpu_to_be32(sizeof(struct lpfc_els_rdf_req) - 3765 - sizeof(struct fc_els_rdf)); 3765 + sizeof(struct fc_els_rdf_hdr)); 3766 3766 prdf->reg_d1.reg_desc.desc_tag = cpu_to_be32(ELS_DTAG_FPIN_REGISTER); 3767 3767 prdf->reg_d1.reg_desc.desc_len = cpu_to_be32( 3768 3768 FC_TLV_DESC_LENGTH_FROM_SZ(prdf->reg_d1));
+3 -3
drivers/scsi/lpfc/lpfc_hw4.h
··· 4909 4909 4910 4910 #define ELS_RDF_REG_TAG_CNT 4 4911 4911 struct lpfc_els_rdf_reg_desc { 4912 - struct fc_df_desc_fpin_reg reg_desc; /* descriptor header */ 4912 + struct fc_df_desc_fpin_reg_hdr reg_desc; /* descriptor header */ 4913 4913 __be32 desc_tags[ELS_RDF_REG_TAG_CNT]; 4914 4914 /* tags in reg_desc */ 4915 4915 }; 4916 4916 4917 4917 struct lpfc_els_rdf_req { 4918 - struct fc_els_rdf rdf; /* hdr up to descriptors */ 4918 + struct fc_els_rdf_hdr rdf; /* hdr up to descriptors */ 4919 4919 struct lpfc_els_rdf_reg_desc reg_d1; /* 1st descriptor */ 4920 4920 }; 4921 4921 4922 4922 struct lpfc_els_rdf_rsp { 4923 - struct fc_els_rdf_resp rdf_resp; /* hdr up to descriptors */ 4923 + struct fc_els_rdf_resp_hdr rdf_resp; /* hdr up to descriptors */ 4924 4924 struct lpfc_els_rdf_reg_desc reg_d1; /* 1st descriptor */ 4925 4925 }; 4926 4926
+39 -19
include/uapi/scsi/fc/fc_els.h
··· 11 11 #include <linux/types.h> 12 12 #include <asm/byteorder.h> 13 13 14 + #ifdef __KERNEL__ 15 + #include <linux/stddef.h> /* for offsetof */ 16 + #else 17 + #include <stddef.h> /* for offsetof */ 18 + #endif 19 + 14 20 /* 15 21 * Fibre Channel Switch - Enhanced Link Services definitions. 16 22 * From T11 FC-LS Rev 1.2 June 7, 2005. ··· 1115 1109 1116 1110 /* Diagnostic Function Descriptor - FPIN Registration */ 1117 1111 struct fc_df_desc_fpin_reg { 1118 - __be32 desc_tag; /* FPIN Registration (0x00030001) */ 1119 - __be32 desc_len; /* Length of Descriptor (in bytes). 1120 - * Size of descriptor excluding 1121 - * desc_tag and desc_len fields. 1122 - */ 1123 - __be32 count; /* Number of desc_tags elements */ 1112 + /* New members MUST be added within the __struct_group() macro below. */ 1113 + __struct_group(fc_df_desc_fpin_reg_hdr, __hdr, /* no attrs */, 1114 + __be32 desc_tag; /* FPIN Registration (0x00030001) */ 1115 + __be32 desc_len; /* Length of Descriptor (in bytes). 1116 + * Size of descriptor excluding 1117 + * desc_tag and desc_len fields. 1118 + */ 1119 + __be32 count; /* Number of desc_tags elements */ 1120 + ); 1124 1121 __be32 desc_tags[]; /* Array of Descriptor Tags. 1125 1122 * Each tag indicates a function 1126 1123 * supported by the N_Port (request) ··· 1133 1124 * See ELS_FN_DTAG_xxx for tag values. 1134 1125 */ 1135 1126 }; 1127 + _Static_assert(offsetof(struct fc_df_desc_fpin_reg, desc_tags) == sizeof(struct fc_df_desc_fpin_reg_hdr), 1128 + "struct member likely outside of __struct_group()"); 1136 1129 1137 1130 /* 1138 1131 * ELS_RDF - Register Diagnostic Functions 1139 1132 */ 1140 1133 struct fc_els_rdf { 1141 - __u8 fpin_cmd; /* command (0x19) */ 1142 - __u8 fpin_zero[3]; /* specified as zero - part of cmd */ 1143 - __be32 desc_len; /* Length of Descriptor List (in bytes). 1144 - * Size of ELS excluding fpin_cmd, 1145 - * fpin_zero and desc_len fields. 1146 - */ 1134 + /* New members MUST be added within the __struct_group() macro below. */ 1135 + __struct_group(fc_els_rdf_hdr, __hdr, /* no attrs */, 1136 + __u8 fpin_cmd; /* command (0x19) */ 1137 + __u8 fpin_zero[3]; /* specified as zero - part of cmd */ 1138 + __be32 desc_len; /* Length of Descriptor List (in bytes). 1139 + * Size of ELS excluding fpin_cmd, 1140 + * fpin_zero and desc_len fields. 1141 + */ 1142 + ); 1147 1143 struct fc_tlv_desc desc[]; /* Descriptor list */ 1148 1144 }; 1145 + _Static_assert(offsetof(struct fc_els_rdf, desc) == sizeof(struct fc_els_rdf_hdr), 1146 + "struct member likely outside of __struct_group()"); 1149 1147 1150 1148 /* 1151 1149 * ELS RDF LS_ACC Response. 1152 1150 */ 1153 1151 struct fc_els_rdf_resp { 1154 - struct fc_els_ls_acc acc_hdr; 1155 - __be32 desc_list_len; /* Length of response (in 1156 - * bytes). Excludes acc_hdr 1157 - * and desc_list_len fields. 1158 - */ 1159 - struct fc_els_lsri_desc lsri; 1152 + /* New members MUST be added within the __struct_group() macro below. */ 1153 + __struct_group(fc_els_rdf_resp_hdr, __hdr, /* no attrs */, 1154 + struct fc_els_ls_acc acc_hdr; 1155 + __be32 desc_list_len; /* Length of response (in 1156 + * bytes). Excludes acc_hdr 1157 + * and desc_list_len fields. 1158 + */ 1159 + struct fc_els_lsri_desc lsri; 1160 + ); 1160 1161 struct fc_tlv_desc desc[]; /* Supported Descriptor list */ 1161 1162 }; 1162 - 1163 + _Static_assert(offsetof(struct fc_els_rdf_resp, desc) == sizeof(struct fc_els_rdf_resp_hdr), 1164 + "struct member likely outside of __struct_group()"); 1163 1165 1164 1166 /* 1165 1167 * Diagnostic Capability Descriptors for EDC ELS