]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
scsi: lpfc: Fix Fabric hostname registration if system hostname changes
authorJames Smart <jsmart2021@gmail.com>
Wed, 18 Dec 2019 23:58:02 +0000 (15:58 -0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Sat, 21 Dec 2019 18:42:42 +0000 (13:42 -0500)
There are reports of multiple ports on the same system displaying different
hostnames in fabric FDMI displays.

Currently, the driver registers the hostname at initialization and obtains
the hostname via init_utsname()->nodename queried at the time the FC link
comes up. Unfortunately, if the machine hostname is updated after
initialization, such as via DHCP or admin command, the value registered
initially will be incorrect.

Fix by having the driver save the hostname that was registered with FDMI.
The driver then runs a heartbeat action that will check the hostname.  If
the name changes, reregister the FMDI data.

The hostname is used in RSNN_NN, FDMI RPA and FDMI RHBA.

Link: https://lore.kernel.org/r/20191218235808.31922-5-jsmart2021@gmail.com
Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_crtn.h
drivers/scsi/lpfc/lpfc_ct.c
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_init.c

index 935f988041989bb1ef667b8c7d343bd49d785ee4..04d73e2be373e3376f1e0427eb1671ea47d6c150 100644 (file)
@@ -1223,6 +1223,8 @@ struct lpfc_hba {
 #define LPFC_POLL_HB   1               /* slowpath heartbeat */
 #define LPFC_POLL_FASTPATH     0       /* called from fastpath */
 #define LPFC_POLL_SLOWPATH     1       /* called from slowpath */
+
+       char os_host_name[MAXHOSTNAMELEN];
 };
 
 static inline struct Scsi_Host *
index ee353c84a0972f62eef2d8ef2754bdef743a0693..25d3dd39bc0540abacdfa99dfbd5fa8a383b668e 100644 (file)
@@ -180,7 +180,7 @@ int lpfc_issue_gidft(struct lpfc_vport *vport);
 int lpfc_get_gidft_type(struct lpfc_vport *vport, struct lpfc_iocbq *iocbq);
 int lpfc_ns_cmd(struct lpfc_vport *, int, uint8_t, uint32_t);
 int lpfc_fdmi_cmd(struct lpfc_vport *, struct lpfc_nodelist *, int, uint32_t);
-void lpfc_fdmi_num_disc_check(struct lpfc_vport *);
+void lpfc_fdmi_change_check(struct lpfc_vport *vport);
 void lpfc_delayed_disc_tmo(struct timer_list *);
 void lpfc_delayed_disc_timeout_handler(struct lpfc_vport *);
 
index 1b4dbb28fb4194b4e86c3a2edcec68b4e3283efa..58b35a1442c1610f74187ed44e3a575a63e65766 100644 (file)
@@ -1511,7 +1511,7 @@ lpfc_vport_symbolic_node_name(struct lpfc_vport *vport, char *symbol,
        if (strlcat(symbol, tmp, size) >= size)
                goto buffer_done;
 
-       scnprintf(tmp, sizeof(tmp), " HN:%s", init_utsname()->nodename);
+       scnprintf(tmp, sizeof(tmp), " HN:%s", vport->phba->os_host_name);
        if (strlcat(symbol, tmp, size) >= size)
                goto buffer_done;
 
@@ -2000,14 +2000,16 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 
 
 /**
- * lpfc_fdmi_num_disc_check - Check how many mapped NPorts we are connected to
+ * lpfc_fdmi_change_check - Check for changed FDMI parameters
  * @vport: pointer to a host virtual N_Port data structure.
  *
- * Called from hbeat timeout routine to check if the number of discovered
- * ports has changed. If so, re-register thar port Attribute.
+ * Check how many mapped NPorts we are connected to
+ * Check if our hostname changed
+ * Called from hbeat timeout routine to check if any FDMI parameters
+ * changed. If so, re-register those Attributes.
  */
 void
-lpfc_fdmi_num_disc_check(struct lpfc_vport *vport)
+lpfc_fdmi_change_check(struct lpfc_vport *vport)
 {
        struct lpfc_hba *phba = vport->phba;
        struct lpfc_nodelist *ndlp;
@@ -2020,17 +2022,41 @@ lpfc_fdmi_num_disc_check(struct lpfc_vport *vport)
        if (!(vport->fc_flag & FC_FABRIC))
                return;
 
+       ndlp = lpfc_findnode_did(vport, FDMI_DID);
+       if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
+               return;
+
+       /* Check if system hostname changed */
+       if (strcmp(phba->os_host_name, init_utsname()->nodename)) {
+               memset(phba->os_host_name, 0, sizeof(phba->os_host_name));
+               scnprintf(phba->os_host_name, sizeof(phba->os_host_name), "%s",
+                         init_utsname()->nodename);
+               lpfc_ns_cmd(vport, SLI_CTNS_RSNN_NN, 0, 0);
+
+               /* Since this effects multiple HBA and PORT attributes, we need
+                * de-register and go thru the whole FDMI registration cycle.
+                * DHBA -> DPRT -> RHBA -> RPA  (physical port)
+                * DPRT -> RPRT (vports)
+                */
+               if (vport->port_type == LPFC_PHYSICAL_PORT)
+                       lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA, 0);
+               else
+                       lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DPRT, 0);
+
+               /* Since this code path registers all the port attributes
+                * we can just return without further checking.
+                */
+               return;
+       }
+
        if (!(vport->fdmi_port_mask & LPFC_FDMI_PORT_ATTR_num_disc))
                return;
 
+       /* Check if the number of mapped NPorts changed */
        cnt = lpfc_find_map_node(vport);
        if (cnt == vport->fdmi_num_disc)
                return;
 
-       ndlp = lpfc_findnode_did(vport, FDMI_DID);
-       if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
-               return;
-
        if (vport->port_type == LPFC_PHYSICAL_PORT) {
                lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPA,
                              LPFC_FDMI_PORT_ATTR_num_disc);
@@ -2618,8 +2644,8 @@ lpfc_fdmi_port_attr_host_name(struct lpfc_vport *vport,
        ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
        memset(ae, 0, 256);
 
-       snprintf(ae->un.AttrString, sizeof(ae->un.AttrString), "%s",
-                init_utsname()->nodename);
+       scnprintf(ae->un.AttrString, sizeof(ae->un.AttrString), "%s",
+                 vport->phba->os_host_name);
 
        len = strnlen(ae->un.AttrString, sizeof(ae->un.AttrString));
        len += (len & 3) ? (4 - (len & 3)) : 4;
index 85ada3deb47dc6f8d2c79177b8b4f63357ad7ee5..dcc8999c6a683ba50fa542b9a6df2a61ca2804cb 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/kthread.h>
 #include <linux/interrupt.h>
 #include <linux/lockdep.h>
+#include <linux/utsname.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
@@ -3315,6 +3316,10 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
                lpfc_sli4_clear_fcf_rr_bmask(phba);
        }
 
+       /* Prepare for LINK up registrations */
+       memset(phba->os_host_name, 0, sizeof(phba->os_host_name));
+       scnprintf(phba->os_host_name, sizeof(phba->os_host_name), "%s",
+                 init_utsname()->nodename);
        return;
 out:
        lpfc_vport_set_state(vport, FC_VPORT_FAILED);
index 6298b17290989d1f04458864756b0952aa131572..633ca46b0e4b04a796ea071eefee46ff6ec57178 100644 (file)
@@ -1362,7 +1362,7 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba)
        if (vports != NULL)
                for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
                        lpfc_rcv_seq_check_edtov(vports[i]);
-                       lpfc_fdmi_num_disc_check(vports[i]);
+                       lpfc_fdmi_change_check(vports[i]);
                }
        lpfc_destroy_vport_work_array(phba, vports);