diff options
author | James Smart <james.smart@emulex.com> | 2014-09-03 12:57:19 -0400 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2014-09-16 12:10:10 -0400 |
commit | 12838e74f5164054fd7d5f5201a846ebb9755471 (patch) | |
tree | bc4a17eba4e0670723735ebf1701ea0bcc97ef58 /drivers/scsi/lpfc | |
parent | 2f6fa2c911167e7a3fda130689a36f55b39ed86d (diff) |
lpfc: fix race between LOGO/PLOGI handling causing NULL pointer
Fix race between LOGO/PLOGI handling causing NULL pointer
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: Dick Kennedy <dick.kennedy@emulex.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_disc.h | 6 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 7 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 19 |
3 files changed, 30 insertions, 2 deletions
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index 1a6fe524940d..6977027979be 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h | |||
@@ -78,7 +78,8 @@ struct lpfc_nodelist { | |||
78 | struct list_head nlp_listp; | 78 | struct list_head nlp_listp; |
79 | struct lpfc_name nlp_portname; | 79 | struct lpfc_name nlp_portname; |
80 | struct lpfc_name nlp_nodename; | 80 | struct lpfc_name nlp_nodename; |
81 | uint32_t nlp_flag; /* entry flags */ | 81 | uint32_t nlp_flag; /* entry flags */ |
82 | uint32_t nlp_add_flag; /* additional flags */ | ||
82 | uint32_t nlp_DID; /* FC D_ID of entry */ | 83 | uint32_t nlp_DID; /* FC D_ID of entry */ |
83 | uint32_t nlp_last_elscmd; /* Last ELS cmd sent */ | 84 | uint32_t nlp_last_elscmd; /* Last ELS cmd sent */ |
84 | uint16_t nlp_type; | 85 | uint16_t nlp_type; |
@@ -157,6 +158,9 @@ struct lpfc_node_rrq { | |||
157 | #define NLP_FIRSTBURST 0x40000000 /* Target supports FirstBurst */ | 158 | #define NLP_FIRSTBURST 0x40000000 /* Target supports FirstBurst */ |
158 | #define NLP_RPI_REGISTERED 0x80000000 /* nlp_rpi is valid */ | 159 | #define NLP_RPI_REGISTERED 0x80000000 /* nlp_rpi is valid */ |
159 | 160 | ||
161 | /* Defines for nlp_add_flag (uint32) */ | ||
162 | #define NLP_IN_DEV_LOSS 0x00000001 /* Dev Loss processing in progress */ | ||
163 | |||
160 | /* ndlp usage management macros */ | 164 | /* ndlp usage management macros */ |
161 | #define NLP_CHK_NODE_ACT(ndlp) (((ndlp)->nlp_usg_map \ | 165 | #define NLP_CHK_NODE_ACT(ndlp) (((ndlp)->nlp_usg_map \ |
162 | & NLP_USG_NODE_ACT_BIT) \ | 166 | & NLP_USG_NODE_ACT_BIT) \ |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 30ec80f32d1a..9d03e7250fb4 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -6693,6 +6693,13 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
6693 | 6693 | ||
6694 | phba->fc_stat.elsRcvFrame++; | 6694 | phba->fc_stat.elsRcvFrame++; |
6695 | 6695 | ||
6696 | /* | ||
6697 | * Do not process any unsolicited ELS commands | ||
6698 | * if the ndlp is in DEV_LOSS | ||
6699 | */ | ||
6700 | if (ndlp->nlp_add_flag & NLP_IN_DEV_LOSS) | ||
6701 | goto dropit; | ||
6702 | |||
6696 | elsiocb->context1 = lpfc_nlp_get(ndlp); | 6703 | elsiocb->context1 = lpfc_nlp_get(ndlp); |
6697 | elsiocb->vport = vport; | 6704 | elsiocb->vport = vport; |
6698 | 6705 | ||
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index d178aee02b49..2d929a5e8354 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -153,6 +153,16 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
153 | put_device(&rport->dev); | 153 | put_device(&rport->dev); |
154 | return; | 154 | return; |
155 | } | 155 | } |
156 | |||
157 | put_node = rdata->pnode != NULL; | ||
158 | put_rport = ndlp->rport != NULL; | ||
159 | rdata->pnode = NULL; | ||
160 | ndlp->rport = NULL; | ||
161 | if (put_node) | ||
162 | lpfc_nlp_put(ndlp); | ||
163 | if (put_rport) | ||
164 | put_device(&rport->dev); | ||
165 | return; | ||
156 | } | 166 | } |
157 | 167 | ||
158 | evtp = &ndlp->dev_loss_evt; | 168 | evtp = &ndlp->dev_loss_evt; |
@@ -161,6 +171,7 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
161 | return; | 171 | return; |
162 | 172 | ||
163 | evtp->evt_arg1 = lpfc_nlp_get(ndlp); | 173 | evtp->evt_arg1 = lpfc_nlp_get(ndlp); |
174 | ndlp->nlp_add_flag |= NLP_IN_DEV_LOSS; | ||
164 | 175 | ||
165 | spin_lock_irq(&phba->hbalock); | 176 | spin_lock_irq(&phba->hbalock); |
166 | /* We need to hold the node by incrementing the reference | 177 | /* We need to hold the node by incrementing the reference |
@@ -201,8 +212,10 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) | |||
201 | 212 | ||
202 | rport = ndlp->rport; | 213 | rport = ndlp->rport; |
203 | 214 | ||
204 | if (!rport) | 215 | if (!rport) { |
216 | ndlp->nlp_add_flag &= ~NLP_IN_DEV_LOSS; | ||
205 | return fcf_inuse; | 217 | return fcf_inuse; |
218 | } | ||
206 | 219 | ||
207 | rdata = rport->dd_data; | 220 | rdata = rport->dd_data; |
208 | name = (uint8_t *) &ndlp->nlp_portname; | 221 | name = (uint8_t *) &ndlp->nlp_portname; |
@@ -235,6 +248,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) | |||
235 | put_rport = ndlp->rport != NULL; | 248 | put_rport = ndlp->rport != NULL; |
236 | rdata->pnode = NULL; | 249 | rdata->pnode = NULL; |
237 | ndlp->rport = NULL; | 250 | ndlp->rport = NULL; |
251 | ndlp->nlp_add_flag &= ~NLP_IN_DEV_LOSS; | ||
238 | if (put_node) | 252 | if (put_node) |
239 | lpfc_nlp_put(ndlp); | 253 | lpfc_nlp_put(ndlp); |
240 | if (put_rport) | 254 | if (put_rport) |
@@ -250,6 +264,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) | |||
250 | *name, *(name+1), *(name+2), *(name+3), | 264 | *name, *(name+1), *(name+2), *(name+3), |
251 | *(name+4), *(name+5), *(name+6), *(name+7), | 265 | *(name+4), *(name+5), *(name+6), *(name+7), |
252 | ndlp->nlp_DID); | 266 | ndlp->nlp_DID); |
267 | ndlp->nlp_add_flag &= ~NLP_IN_DEV_LOSS; | ||
253 | return fcf_inuse; | 268 | return fcf_inuse; |
254 | } | 269 | } |
255 | 270 | ||
@@ -259,6 +274,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) | |||
259 | put_rport = ndlp->rport != NULL; | 274 | put_rport = ndlp->rport != NULL; |
260 | rdata->pnode = NULL; | 275 | rdata->pnode = NULL; |
261 | ndlp->rport = NULL; | 276 | ndlp->rport = NULL; |
277 | ndlp->nlp_add_flag &= ~NLP_IN_DEV_LOSS; | ||
262 | if (put_node) | 278 | if (put_node) |
263 | lpfc_nlp_put(ndlp); | 279 | lpfc_nlp_put(ndlp); |
264 | if (put_rport) | 280 | if (put_rport) |
@@ -297,6 +313,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) | |||
297 | put_rport = ndlp->rport != NULL; | 313 | put_rport = ndlp->rport != NULL; |
298 | rdata->pnode = NULL; | 314 | rdata->pnode = NULL; |
299 | ndlp->rport = NULL; | 315 | ndlp->rport = NULL; |
316 | ndlp->nlp_add_flag &= ~NLP_IN_DEV_LOSS; | ||
300 | if (put_node) | 317 | if (put_node) |
301 | lpfc_nlp_put(ndlp); | 318 | lpfc_nlp_put(ndlp); |
302 | if (put_rport) | 319 | if (put_rport) |