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

scsi: fcoe: Embed fc_rport_priv in fcoe_rport structure

Gcc-9 complains for a memset across pointer boundaries, which happens as
the code tries to allocate a flexible array on the stack. Turns out we
cannot do this without relying on gcc-isms, so with this patch we'll embed
the fc_rport_priv structure into fcoe_rport, can use the normal
'container_of' outcast, and will only have to do a memset over one
structure.

Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Hannes Reinecke and committed by
Martin K. Petersen
023358b1 f3e4ff28

+25 -32
+20 -31
drivers/scsi/fcoe/fcoe_ctlr.c
··· 2005 2005 */ 2006 2006 static inline struct fcoe_rport *fcoe_ctlr_rport(struct fc_rport_priv *rdata) 2007 2007 { 2008 - return (struct fcoe_rport *)(rdata + 1); 2008 + return container_of(rdata, struct fcoe_rport, rdata); 2009 2009 } 2010 2010 2011 2011 /** ··· 2269 2269 */ 2270 2270 static int fcoe_ctlr_vn_parse(struct fcoe_ctlr *fip, 2271 2271 struct sk_buff *skb, 2272 - struct fc_rport_priv *rdata) 2272 + struct fcoe_rport *frport) 2273 2273 { 2274 2274 struct fip_header *fiph; 2275 2275 struct fip_desc *desc = NULL; ··· 2277 2277 struct fip_wwn_desc *wwn = NULL; 2278 2278 struct fip_vn_desc *vn = NULL; 2279 2279 struct fip_size_desc *size = NULL; 2280 - struct fcoe_rport *frport; 2281 2280 size_t rlen; 2282 2281 size_t dlen; 2283 2282 u32 desc_mask = 0; 2284 2283 u32 dtype; 2285 2284 u8 sub; 2286 - 2287 - memset(rdata, 0, sizeof(*rdata) + sizeof(*frport)); 2288 - frport = fcoe_ctlr_rport(rdata); 2289 2285 2290 2286 fiph = (struct fip_header *)skb->data; 2291 2287 frport->flags = ntohs(fiph->fip_flags); ··· 2345 2349 if (dlen != sizeof(struct fip_wwn_desc)) 2346 2350 goto len_err; 2347 2351 wwn = (struct fip_wwn_desc *)desc; 2348 - rdata->ids.node_name = get_unaligned_be64(&wwn->fd_wwn); 2352 + frport->rdata.ids.node_name = 2353 + get_unaligned_be64(&wwn->fd_wwn); 2349 2354 break; 2350 2355 case FIP_DT_VN_ID: 2351 2356 if (dlen != sizeof(struct fip_vn_desc)) 2352 2357 goto len_err; 2353 2358 vn = (struct fip_vn_desc *)desc; 2354 2359 memcpy(frport->vn_mac, vn->fd_mac, ETH_ALEN); 2355 - rdata->ids.port_id = ntoh24(vn->fd_fc_id); 2356 - rdata->ids.port_name = get_unaligned_be64(&vn->fd_wwpn); 2360 + frport->rdata.ids.port_id = ntoh24(vn->fd_fc_id); 2361 + frport->rdata.ids.port_name = 2362 + get_unaligned_be64(&vn->fd_wwpn); 2357 2363 break; 2358 2364 case FIP_DT_FC4F: 2359 2365 if (dlen != sizeof(struct fip_fc4_feat)) ··· 2736 2738 { 2737 2739 struct fip_header *fiph; 2738 2740 enum fip_vn2vn_subcode sub; 2739 - struct { 2740 - struct fc_rport_priv rdata; 2741 - struct fcoe_rport frport; 2742 - } buf; 2741 + struct fcoe_rport frport = { }; 2743 2742 int rc, vlan_id = 0; 2744 2743 2745 2744 fiph = (struct fip_header *)skb->data; ··· 2752 2757 goto drop; 2753 2758 } 2754 2759 2755 - rc = fcoe_ctlr_vn_parse(fip, skb, &buf.rdata); 2760 + rc = fcoe_ctlr_vn_parse(fip, skb, &frport); 2756 2761 if (rc) { 2757 2762 LIBFCOE_FIP_DBG(fip, "vn_recv vn_parse error %d\n", rc); 2758 2763 goto drop; ··· 2761 2766 mutex_lock(&fip->ctlr_mutex); 2762 2767 switch (sub) { 2763 2768 case FIP_SC_VN_PROBE_REQ: 2764 - fcoe_ctlr_vn_probe_req(fip, &buf.rdata); 2769 + fcoe_ctlr_vn_probe_req(fip, &frport.rdata); 2765 2770 break; 2766 2771 case FIP_SC_VN_PROBE_REP: 2767 - fcoe_ctlr_vn_probe_reply(fip, &buf.rdata); 2772 + fcoe_ctlr_vn_probe_reply(fip, &frport.rdata); 2768 2773 break; 2769 2774 case FIP_SC_VN_CLAIM_NOTIFY: 2770 - fcoe_ctlr_vn_claim_notify(fip, &buf.rdata); 2775 + fcoe_ctlr_vn_claim_notify(fip, &frport.rdata); 2771 2776 break; 2772 2777 case FIP_SC_VN_CLAIM_REP: 2773 - fcoe_ctlr_vn_claim_resp(fip, &buf.rdata); 2778 + fcoe_ctlr_vn_claim_resp(fip, &frport.rdata); 2774 2779 break; 2775 2780 case FIP_SC_VN_BEACON: 2776 - fcoe_ctlr_vn_beacon(fip, &buf.rdata); 2781 + fcoe_ctlr_vn_beacon(fip, &frport.rdata); 2777 2782 break; 2778 2783 default: 2779 2784 LIBFCOE_FIP_DBG(fip, "vn_recv unknown subcode %d\n", sub); ··· 2797 2802 */ 2798 2803 static int fcoe_ctlr_vlan_parse(struct fcoe_ctlr *fip, 2799 2804 struct sk_buff *skb, 2800 - struct fc_rport_priv *rdata) 2805 + struct fcoe_rport *frport) 2801 2806 { 2802 2807 struct fip_header *fiph; 2803 2808 struct fip_desc *desc = NULL; 2804 2809 struct fip_mac_desc *macd = NULL; 2805 2810 struct fip_wwn_desc *wwn = NULL; 2806 - struct fcoe_rport *frport; 2807 2811 size_t rlen; 2808 2812 size_t dlen; 2809 2813 u32 desc_mask = 0; 2810 2814 u32 dtype; 2811 2815 u8 sub; 2812 - 2813 - memset(rdata, 0, sizeof(*rdata) + sizeof(*frport)); 2814 - frport = fcoe_ctlr_rport(rdata); 2815 2816 2816 2817 fiph = (struct fip_header *)skb->data; 2817 2818 frport->flags = ntohs(fiph->fip_flags); ··· 2862 2871 if (dlen != sizeof(struct fip_wwn_desc)) 2863 2872 goto len_err; 2864 2873 wwn = (struct fip_wwn_desc *)desc; 2865 - rdata->ids.node_name = get_unaligned_be64(&wwn->fd_wwn); 2874 + frport->rdata.ids.node_name = 2875 + get_unaligned_be64(&wwn->fd_wwn); 2866 2876 break; 2867 2877 default: 2868 2878 LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x " ··· 2974 2982 { 2975 2983 struct fip_header *fiph; 2976 2984 enum fip_vlan_subcode sub; 2977 - struct { 2978 - struct fc_rport_priv rdata; 2979 - struct fcoe_rport frport; 2980 - } buf; 2985 + struct fcoe_rport frport = { }; 2981 2986 int rc; 2982 2987 2983 2988 fiph = (struct fip_header *)skb->data; 2984 2989 sub = fiph->fip_subcode; 2985 - rc = fcoe_ctlr_vlan_parse(fip, skb, &buf.rdata); 2990 + rc = fcoe_ctlr_vlan_parse(fip, skb, &frport); 2986 2991 if (rc) { 2987 2992 LIBFCOE_FIP_DBG(fip, "vlan_recv vlan_parse error %d\n", rc); 2988 2993 goto drop; 2989 2994 } 2990 2995 mutex_lock(&fip->ctlr_mutex); 2991 2996 if (sub == FIP_SC_VL_REQ) 2992 - fcoe_ctlr_vlan_disc_reply(fip, &buf.rdata); 2997 + fcoe_ctlr_vlan_disc_reply(fip, &frport.rdata); 2993 2998 mutex_unlock(&fip->ctlr_mutex); 2994 2999 2995 3000 drop:
+4 -1
drivers/scsi/libfc/fc_rport.c
··· 128 128 struct fc_rport_priv *fc_rport_create(struct fc_lport *lport, u32 port_id) 129 129 { 130 130 struct fc_rport_priv *rdata; 131 + size_t rport_priv_size = sizeof(*rdata); 131 132 132 133 lockdep_assert_held(&lport->disc.disc_mutex); 133 134 ··· 136 135 if (rdata) 137 136 return rdata; 138 137 139 - rdata = kzalloc(sizeof(*rdata) + lport->rport_priv_size, GFP_KERNEL); 138 + if (lport->rport_priv_size > 0) 139 + rport_priv_size = lport->rport_priv_size; 140 + rdata = kzalloc(rport_priv_size, GFP_KERNEL); 140 141 if (!rdata) 141 142 return NULL; 142 143
+1
include/scsi/libfcoe.h
··· 229 229 * @vn_mac: VN_Node assigned MAC address for data 230 230 */ 231 231 struct fcoe_rport { 232 + struct fc_rport_priv rdata; 232 233 unsigned long time; 233 234 u16 fcoe_len; 234 235 u16 flags;