scsi: fcoe: Embed fc_rport_priv in fcoe_rport structure
authorHannes Reinecke <hare@suse.de>
Wed, 24 Jul 2019 09:00:55 +0000 (11:00 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 11 Aug 2019 10:22:12 +0000 (12:22 +0200)
commit 023358b136d490ca91735ac6490db3741af5a8bd upstream.

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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/scsi/fcoe/fcoe_ctlr.c
drivers/scsi/libfc/fc_rport.c
include/scsi/libfcoe.h

index cc3994d..3c2f34d 100644 (file)
@@ -1984,7 +1984,7 @@ EXPORT_SYMBOL_GPL(fcoe_wwn_from_mac);
  */
 static inline struct fcoe_rport *fcoe_ctlr_rport(struct fc_rport_priv *rdata)
 {
-       return (struct fcoe_rport *)(rdata + 1);
+       return container_of(rdata, struct fcoe_rport, rdata);
 }
 
 /**
@@ -2244,7 +2244,7 @@ static void fcoe_ctlr_vn_start(struct fcoe_ctlr *fip)
  */
 static int fcoe_ctlr_vn_parse(struct fcoe_ctlr *fip,
                              struct sk_buff *skb,
-                             struct fc_rport_priv *rdata)
+                             struct fcoe_rport *frport)
 {
        struct fip_header *fiph;
        struct fip_desc *desc = NULL;
@@ -2252,16 +2252,12 @@ static int fcoe_ctlr_vn_parse(struct fcoe_ctlr *fip,
        struct fip_wwn_desc *wwn = NULL;
        struct fip_vn_desc *vn = NULL;
        struct fip_size_desc *size = NULL;
-       struct fcoe_rport *frport;
        size_t rlen;
        size_t dlen;
        u32 desc_mask = 0;
        u32 dtype;
        u8 sub;
 
-       memset(rdata, 0, sizeof(*rdata) + sizeof(*frport));
-       frport = fcoe_ctlr_rport(rdata);
-
        fiph = (struct fip_header *)skb->data;
        frport->flags = ntohs(fiph->fip_flags);
 
@@ -2324,15 +2320,17 @@ static int fcoe_ctlr_vn_parse(struct fcoe_ctlr *fip,
                        if (dlen != sizeof(struct fip_wwn_desc))
                                goto len_err;
                        wwn = (struct fip_wwn_desc *)desc;
-                       rdata->ids.node_name = get_unaligned_be64(&wwn->fd_wwn);
+                       frport->rdata.ids.node_name =
+                               get_unaligned_be64(&wwn->fd_wwn);
                        break;
                case FIP_DT_VN_ID:
                        if (dlen != sizeof(struct fip_vn_desc))
                                goto len_err;
                        vn = (struct fip_vn_desc *)desc;
                        memcpy(frport->vn_mac, vn->fd_mac, ETH_ALEN);
-                       rdata->ids.port_id = ntoh24(vn->fd_fc_id);
-                       rdata->ids.port_name = get_unaligned_be64(&vn->fd_wwpn);
+                       frport->rdata.ids.port_id = ntoh24(vn->fd_fc_id);
+                       frport->rdata.ids.port_name =
+                               get_unaligned_be64(&vn->fd_wwpn);
                        break;
                case FIP_DT_FC4F:
                        if (dlen != sizeof(struct fip_fc4_feat))
@@ -2670,16 +2668,13 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
 {
        struct fip_header *fiph;
        enum fip_vn2vn_subcode sub;
-       struct {
-               struct fc_rport_priv rdata;
-               struct fcoe_rport frport;
-       } buf;
+       struct fcoe_rport frport = { };
        int rc;
 
        fiph = (struct fip_header *)skb->data;
        sub = fiph->fip_subcode;
 
-       rc = fcoe_ctlr_vn_parse(fip, skb, &buf.rdata);
+       rc = fcoe_ctlr_vn_parse(fip, skb, &frport);
        if (rc) {
                LIBFCOE_FIP_DBG(fip, "vn_recv vn_parse error %d\n", rc);
                goto drop;
@@ -2688,19 +2683,19 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
        mutex_lock(&fip->ctlr_mutex);
        switch (sub) {
        case FIP_SC_VN_PROBE_REQ:
-               fcoe_ctlr_vn_probe_req(fip, &buf.rdata);
+               fcoe_ctlr_vn_probe_req(fip, &frport.rdata);
                break;
        case FIP_SC_VN_PROBE_REP:
-               fcoe_ctlr_vn_probe_reply(fip, &buf.rdata);
+               fcoe_ctlr_vn_probe_reply(fip, &frport.rdata);
                break;
        case FIP_SC_VN_CLAIM_NOTIFY:
-               fcoe_ctlr_vn_claim_notify(fip, &buf.rdata);
+               fcoe_ctlr_vn_claim_notify(fip, &frport.rdata);
                break;
        case FIP_SC_VN_CLAIM_REP:
-               fcoe_ctlr_vn_claim_resp(fip, &buf.rdata);
+               fcoe_ctlr_vn_claim_resp(fip, &frport.rdata);
                break;
        case FIP_SC_VN_BEACON:
-               fcoe_ctlr_vn_beacon(fip, &buf.rdata);
+               fcoe_ctlr_vn_beacon(fip, &frport.rdata);
                break;
        default:
                LIBFCOE_FIP_DBG(fip, "vn_recv unknown subcode %d\n", sub);
@@ -2724,22 +2719,18 @@ drop:
  */
 static int fcoe_ctlr_vlan_parse(struct fcoe_ctlr *fip,
                              struct sk_buff *skb,
-                             struct fc_rport_priv *rdata)
+                             struct fcoe_rport *frport)
 {
        struct fip_header *fiph;
        struct fip_desc *desc = NULL;
        struct fip_mac_desc *macd = NULL;
        struct fip_wwn_desc *wwn = NULL;
-       struct fcoe_rport *frport;
        size_t rlen;
        size_t dlen;
        u32 desc_mask = 0;
        u32 dtype;
        u8 sub;
 
-       memset(rdata, 0, sizeof(*rdata) + sizeof(*frport));
-       frport = fcoe_ctlr_rport(rdata);
-
        fiph = (struct fip_header *)skb->data;
        frport->flags = ntohs(fiph->fip_flags);
 
@@ -2793,7 +2784,8 @@ static int fcoe_ctlr_vlan_parse(struct fcoe_ctlr *fip,
                        if (dlen != sizeof(struct fip_wwn_desc))
                                goto len_err;
                        wwn = (struct fip_wwn_desc *)desc;
-                       rdata->ids.node_name = get_unaligned_be64(&wwn->fd_wwn);
+                       frport->rdata.ids.node_name =
+                               get_unaligned_be64(&wwn->fd_wwn);
                        break;
                default:
                        LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x "
@@ -2904,22 +2896,19 @@ static int fcoe_ctlr_vlan_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
 {
        struct fip_header *fiph;
        enum fip_vlan_subcode sub;
-       struct {
-               struct fc_rport_priv rdata;
-               struct fcoe_rport frport;
-       } buf;
+       struct fcoe_rport frport = { };
        int rc;
 
        fiph = (struct fip_header *)skb->data;
        sub = fiph->fip_subcode;
-       rc = fcoe_ctlr_vlan_parse(fip, skb, &buf.rdata);
+       rc = fcoe_ctlr_vlan_parse(fip, skb, &frport);
        if (rc) {
                LIBFCOE_FIP_DBG(fip, "vlan_recv vlan_parse error %d\n", rc);
                goto drop;
        }
        mutex_lock(&fip->ctlr_mutex);
        if (sub == FIP_SC_VL_REQ)
-               fcoe_ctlr_vlan_disc_reply(fip, &buf.rdata);
+               fcoe_ctlr_vlan_disc_reply(fip, &frport.rdata);
        mutex_unlock(&fip->ctlr_mutex);
 
 drop:
index 97aeadd..70e2958 100644 (file)
@@ -127,12 +127,15 @@ static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport,
                                             u32 port_id)
 {
        struct fc_rport_priv *rdata;
+       size_t rport_priv_size = sizeof(*rdata);
 
        rdata = lport->tt.rport_lookup(lport, port_id);
        if (rdata)
                return rdata;
 
-       rdata = kzalloc(sizeof(*rdata) + lport->rport_priv_size, GFP_KERNEL);
+       if (lport->rport_priv_size > 0)
+               rport_priv_size = lport->rport_priv_size;
+       rdata = kzalloc(rport_priv_size, GFP_KERNEL);
        if (!rdata)
                return NULL;
 
index 722d326..6be92ee 100644 (file)
@@ -241,6 +241,7 @@ struct fcoe_fcf {
  * @vn_mac:    VN_Node assigned MAC address for data
  */
 struct fcoe_rport {
+       struct fc_rport_priv rdata;
        unsigned long time;
        u16 fcoe_len;
        u16 flags;