Commit 12838e74 authored by James Smart's avatar James Smart Committed by Christoph Hellwig

lpfc: fix race between LOGO/PLOGI handling causing NULL pointer

Fix race between LOGO/PLOGI handling causing NULL pointer
Signed-off-by: default avatarJames Smart <james.smart@emulex.com>
Signed-off-by: default avatarDick Kennedy <dick.kennedy@emulex.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent 2f6fa2c9
...@@ -79,6 +79,7 @@ struct lpfc_nodelist { ...@@ -79,6 +79,7 @@ struct lpfc_nodelist {
struct lpfc_name nlp_portname; struct lpfc_name nlp_portname;
struct lpfc_name nlp_nodename; struct lpfc_name nlp_nodename;
uint32_t nlp_flag; /* entry flags */ uint32_t nlp_flag; /* entry flags */
uint32_t nlp_add_flag; /* additional flags */
uint32_t nlp_DID; /* FC D_ID of entry */ uint32_t nlp_DID; /* FC D_ID of entry */
uint32_t nlp_last_elscmd; /* Last ELS cmd sent */ uint32_t nlp_last_elscmd; /* Last ELS cmd sent */
uint16_t nlp_type; uint16_t nlp_type;
...@@ -157,6 +158,9 @@ struct lpfc_node_rrq { ...@@ -157,6 +158,9 @@ struct lpfc_node_rrq {
#define NLP_FIRSTBURST 0x40000000 /* Target supports FirstBurst */ #define NLP_FIRSTBURST 0x40000000 /* Target supports FirstBurst */
#define NLP_RPI_REGISTERED 0x80000000 /* nlp_rpi is valid */ #define NLP_RPI_REGISTERED 0x80000000 /* nlp_rpi is valid */
/* Defines for nlp_add_flag (uint32) */
#define NLP_IN_DEV_LOSS 0x00000001 /* Dev Loss processing in progress */
/* ndlp usage management macros */ /* ndlp usage management macros */
#define NLP_CHK_NODE_ACT(ndlp) (((ndlp)->nlp_usg_map \ #define NLP_CHK_NODE_ACT(ndlp) (((ndlp)->nlp_usg_map \
& NLP_USG_NODE_ACT_BIT) \ & NLP_USG_NODE_ACT_BIT) \
......
...@@ -6693,6 +6693,13 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -6693,6 +6693,13 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
phba->fc_stat.elsRcvFrame++; phba->fc_stat.elsRcvFrame++;
/*
* Do not process any unsolicited ELS commands
* if the ndlp is in DEV_LOSS
*/
if (ndlp->nlp_add_flag & NLP_IN_DEV_LOSS)
goto dropit;
elsiocb->context1 = lpfc_nlp_get(ndlp); elsiocb->context1 = lpfc_nlp_get(ndlp);
elsiocb->vport = vport; elsiocb->vport = vport;
......
...@@ -153,6 +153,16 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) ...@@ -153,6 +153,16 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
put_device(&rport->dev); put_device(&rport->dev);
return; return;
} }
put_node = rdata->pnode != NULL;
put_rport = ndlp->rport != NULL;
rdata->pnode = NULL;
ndlp->rport = NULL;
if (put_node)
lpfc_nlp_put(ndlp);
if (put_rport)
put_device(&rport->dev);
return;
} }
evtp = &ndlp->dev_loss_evt; evtp = &ndlp->dev_loss_evt;
...@@ -161,6 +171,7 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) ...@@ -161,6 +171,7 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
return; return;
evtp->evt_arg1 = lpfc_nlp_get(ndlp); evtp->evt_arg1 = lpfc_nlp_get(ndlp);
ndlp->nlp_add_flag |= NLP_IN_DEV_LOSS;
spin_lock_irq(&phba->hbalock); spin_lock_irq(&phba->hbalock);
/* We need to hold the node by incrementing the reference /* We need to hold the node by incrementing the reference
...@@ -201,8 +212,10 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) ...@@ -201,8 +212,10 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
rport = ndlp->rport; rport = ndlp->rport;
if (!rport) if (!rport) {
ndlp->nlp_add_flag &= ~NLP_IN_DEV_LOSS;
return fcf_inuse; return fcf_inuse;
}
rdata = rport->dd_data; rdata = rport->dd_data;
name = (uint8_t *) &ndlp->nlp_portname; name = (uint8_t *) &ndlp->nlp_portname;
...@@ -235,6 +248,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) ...@@ -235,6 +248,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
put_rport = ndlp->rport != NULL; put_rport = ndlp->rport != NULL;
rdata->pnode = NULL; rdata->pnode = NULL;
ndlp->rport = NULL; ndlp->rport = NULL;
ndlp->nlp_add_flag &= ~NLP_IN_DEV_LOSS;
if (put_node) if (put_node)
lpfc_nlp_put(ndlp); lpfc_nlp_put(ndlp);
if (put_rport) if (put_rport)
...@@ -250,6 +264,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) ...@@ -250,6 +264,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
*name, *(name+1), *(name+2), *(name+3), *name, *(name+1), *(name+2), *(name+3),
*(name+4), *(name+5), *(name+6), *(name+7), *(name+4), *(name+5), *(name+6), *(name+7),
ndlp->nlp_DID); ndlp->nlp_DID);
ndlp->nlp_add_flag &= ~NLP_IN_DEV_LOSS;
return fcf_inuse; return fcf_inuse;
} }
...@@ -259,6 +274,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) ...@@ -259,6 +274,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
put_rport = ndlp->rport != NULL; put_rport = ndlp->rport != NULL;
rdata->pnode = NULL; rdata->pnode = NULL;
ndlp->rport = NULL; ndlp->rport = NULL;
ndlp->nlp_add_flag &= ~NLP_IN_DEV_LOSS;
if (put_node) if (put_node)
lpfc_nlp_put(ndlp); lpfc_nlp_put(ndlp);
if (put_rport) if (put_rport)
...@@ -297,6 +313,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) ...@@ -297,6 +313,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
put_rport = ndlp->rport != NULL; put_rport = ndlp->rport != NULL;
rdata->pnode = NULL; rdata->pnode = NULL;
ndlp->rport = NULL; ndlp->rport = NULL;
ndlp->nlp_add_flag &= ~NLP_IN_DEV_LOSS;
if (put_node) if (put_node)
lpfc_nlp_put(ndlp); lpfc_nlp_put(ndlp);
if (put_rport) if (put_rport)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment