mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-28 20:02:17 +00:00
scsi: lpfc: Fix Fabric hostname registration if system hostname changes
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>
This commit is contained in:
parent
f3d0a8acc5
commit
e3ba04c9ba
5 changed files with 46 additions and 13 deletions
|
@ -1223,6 +1223,8 @@ struct lpfc_hba {
|
||||||
#define LPFC_POLL_HB 1 /* slowpath heartbeat */
|
#define LPFC_POLL_HB 1 /* slowpath heartbeat */
|
||||||
#define LPFC_POLL_FASTPATH 0 /* called from fastpath */
|
#define LPFC_POLL_FASTPATH 0 /* called from fastpath */
|
||||||
#define LPFC_POLL_SLOWPATH 1 /* called from slowpath */
|
#define LPFC_POLL_SLOWPATH 1 /* called from slowpath */
|
||||||
|
|
||||||
|
char os_host_name[MAXHOSTNAMELEN];
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct Scsi_Host *
|
static inline struct Scsi_Host *
|
||||||
|
|
|
@ -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_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_ns_cmd(struct lpfc_vport *, int, uint8_t, uint32_t);
|
||||||
int lpfc_fdmi_cmd(struct lpfc_vport *, struct lpfc_nodelist *, int, 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_tmo(struct timer_list *);
|
||||||
void lpfc_delayed_disc_timeout_handler(struct lpfc_vport *);
|
void lpfc_delayed_disc_timeout_handler(struct lpfc_vport *);
|
||||||
|
|
||||||
|
|
|
@ -1511,7 +1511,7 @@ lpfc_vport_symbolic_node_name(struct lpfc_vport *vport, char *symbol,
|
||||||
if (strlcat(symbol, tmp, size) >= size)
|
if (strlcat(symbol, tmp, size) >= size)
|
||||||
goto buffer_done;
|
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)
|
if (strlcat(symbol, tmp, size) >= size)
|
||||||
goto buffer_done;
|
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.
|
* @vport: pointer to a host virtual N_Port data structure.
|
||||||
*
|
*
|
||||||
* Called from hbeat timeout routine to check if the number of discovered
|
* Check how many mapped NPorts we are connected to
|
||||||
* ports has changed. If so, re-register thar port Attribute.
|
* Check if our hostname changed
|
||||||
|
* Called from hbeat timeout routine to check if any FDMI parameters
|
||||||
|
* changed. If so, re-register those Attributes.
|
||||||
*/
|
*/
|
||||||
void
|
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_hba *phba = vport->phba;
|
||||||
struct lpfc_nodelist *ndlp;
|
struct lpfc_nodelist *ndlp;
|
||||||
|
@ -2020,17 +2022,41 @@ lpfc_fdmi_num_disc_check(struct lpfc_vport *vport)
|
||||||
if (!(vport->fc_flag & FC_FABRIC))
|
if (!(vport->fc_flag & FC_FABRIC))
|
||||||
return;
|
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))
|
if (!(vport->fdmi_port_mask & LPFC_FDMI_PORT_ATTR_num_disc))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Check if the number of mapped NPorts changed */
|
||||||
cnt = lpfc_find_map_node(vport);
|
cnt = lpfc_find_map_node(vport);
|
||||||
if (cnt == vport->fdmi_num_disc)
|
if (cnt == vport->fdmi_num_disc)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ndlp = lpfc_findnode_did(vport, FDMI_DID);
|
|
||||||
if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (vport->port_type == LPFC_PHYSICAL_PORT) {
|
if (vport->port_type == LPFC_PHYSICAL_PORT) {
|
||||||
lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPA,
|
lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPA,
|
||||||
LPFC_FDMI_PORT_ATTR_num_disc);
|
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;
|
ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
|
||||||
memset(ae, 0, 256);
|
memset(ae, 0, 256);
|
||||||
|
|
||||||
snprintf(ae->un.AttrString, sizeof(ae->un.AttrString), "%s",
|
scnprintf(ae->un.AttrString, sizeof(ae->un.AttrString), "%s",
|
||||||
init_utsname()->nodename);
|
vport->phba->os_host_name);
|
||||||
|
|
||||||
len = strnlen(ae->un.AttrString, sizeof(ae->un.AttrString));
|
len = strnlen(ae->un.AttrString, sizeof(ae->un.AttrString));
|
||||||
len += (len & 3) ? (4 - (len & 3)) : 4;
|
len += (len & 3) ? (4 - (len & 3)) : 4;
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <linux/kthread.h>
|
#include <linux/kthread.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/lockdep.h>
|
#include <linux/lockdep.h>
|
||||||
|
#include <linux/utsname.h>
|
||||||
|
|
||||||
#include <scsi/scsi.h>
|
#include <scsi/scsi.h>
|
||||||
#include <scsi/scsi_device.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);
|
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;
|
return;
|
||||||
out:
|
out:
|
||||||
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
|
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
|
||||||
|
|
|
@ -1362,7 +1362,7 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba)
|
||||||
if (vports != NULL)
|
if (vports != NULL)
|
||||||
for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
|
for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
|
||||||
lpfc_rcv_seq_check_edtov(vports[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);
|
lpfc_destroy_vport_work_array(phba, vports);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue