Skip to content

Commit

Permalink
scsi: lpfc: Fix Fabric hostname registration if system hostname changes
Browse files Browse the repository at this point in the history
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/[email protected]
Signed-off-by: Dick Kennedy <[email protected]>
Signed-off-by: James Smart <[email protected]>
Signed-off-by: Martin K. Petersen <[email protected]>
  • Loading branch information
jsmart-gh authored and martinkpetersen committed Dec 21, 2019
1 parent f3d0a8a commit e3ba04c
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 13 deletions.
2 changes: 2 additions & 0 deletions drivers/scsi/lpfc/lpfc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *
Expand Down
2 changes: 1 addition & 1 deletion drivers/scsi/lpfc/lpfc_crtn.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);

Expand Down
48 changes: 37 additions & 11 deletions drivers/scsi/lpfc/lpfc_ct.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions drivers/scsi/lpfc/lpfc_hbadisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion drivers/scsi/lpfc/lpfc_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down

0 comments on commit e3ba04c

Please sign in to comment.