scsi: fcoe: Embed fc_rport_priv in fcoe_rport structure [Linux 4.9.189]

This Linux kernel change "scsi: fcoe: Embed fc_rport_priv in fcoe_rport structure" is included in the Linux 4.9.189 release. This change is authored by Hannes Reinecke <hare [at] suse.de> on Wed Jul 24 11:00:55 2019 +0200. The commit for this change in Linux stable tree is 792f95e (patch) which is from upstream commit 023358b. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 023358b.

scsi: fcoe: Embed fc_rport_priv in fcoe_rport structure

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 <[email protected]>
Signed-off-by: Martin K. Petersen <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

There are 57 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/scsi/fcoe/fcoe_ctlr.c | 51 +++++++++++++++++--------------------------
 drivers/scsi/libfc/fc_rport.c |  5 ++++-
 include/scsi/libfcoe.h        |  1 +
 3 files changed, 25 insertions(+), 32 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c
index cc3994d..3c2f34d 100644
--- a/drivers/scsi/fcoe/fcoe_ctlr.c
+++ b/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -1984,7 +1984,7 @@ u64 fcoe_wwn_from_mac(unsigned char mac[MAX_ADDR_LEN],
  */
 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 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
  */
 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:
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 97aeadd..70e2958 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -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;

diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h
index 722d326..6be92ee 100644
--- a/include/scsi/libfcoe.h
+++ b/include/scsi/libfcoe.h
@@ -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;

Leave a Reply

Your email address will not be published. Required fields are marked *