Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

scsi: lpfc: correct rcu unlock issue in lpfc_nvme_info_show

Many of the exit cases were not releasing the rcu read lock. Corrected the
exit paths.

Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
Tested-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

James Smart and committed by
Martin K. Petersen
79080d34 e2a8be56

+19 -13
+19 -13
drivers/scsi/lpfc/lpfc_attr.c
··· 355 355 phba->sli4_hba.io_xri_max, 356 356 lpfc_sli4_get_els_iocb_cnt(phba)); 357 357 if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 358 - goto buffer_done; 358 + goto rcu_unlock_buf_done; 359 359 360 360 /* Port state is only one of two values for now. */ 361 361 if (localport->port_id) ··· 371 371 wwn_to_u64(vport->fc_nodename.u.wwn), 372 372 localport->port_id, statep); 373 373 if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 374 - goto buffer_done; 374 + goto rcu_unlock_buf_done; 375 375 376 376 list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { 377 377 nrport = NULL; ··· 398 398 399 399 /* Tab in to show lport ownership. */ 400 400 if (strlcat(buf, "NVME RPORT ", PAGE_SIZE) >= PAGE_SIZE) 401 - goto buffer_done; 401 + goto rcu_unlock_buf_done; 402 402 if (phba->brd_no >= 10) { 403 403 if (strlcat(buf, " ", PAGE_SIZE) >= PAGE_SIZE) 404 - goto buffer_done; 404 + goto rcu_unlock_buf_done; 405 405 } 406 406 407 407 scnprintf(tmp, sizeof(tmp), "WWPN x%llx ", 408 408 nrport->port_name); 409 409 if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 410 - goto buffer_done; 410 + goto rcu_unlock_buf_done; 411 411 412 412 scnprintf(tmp, sizeof(tmp), "WWNN x%llx ", 413 413 nrport->node_name); 414 414 if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 415 - goto buffer_done; 415 + goto rcu_unlock_buf_done; 416 416 417 417 scnprintf(tmp, sizeof(tmp), "DID x%06x ", 418 418 nrport->port_id); 419 419 if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 420 - goto buffer_done; 420 + goto rcu_unlock_buf_done; 421 421 422 422 /* An NVME rport can have multiple roles. */ 423 423 if (nrport->port_role & FC_PORT_ROLE_NVME_INITIATOR) { 424 424 if (strlcat(buf, "INITIATOR ", PAGE_SIZE) >= PAGE_SIZE) 425 - goto buffer_done; 425 + goto rcu_unlock_buf_done; 426 426 } 427 427 if (nrport->port_role & FC_PORT_ROLE_NVME_TARGET) { 428 428 if (strlcat(buf, "TARGET ", PAGE_SIZE) >= PAGE_SIZE) 429 - goto buffer_done; 429 + goto rcu_unlock_buf_done; 430 430 } 431 431 if (nrport->port_role & FC_PORT_ROLE_NVME_DISCOVERY) { 432 432 if (strlcat(buf, "DISCSRVC ", PAGE_SIZE) >= PAGE_SIZE) 433 - goto buffer_done; 433 + goto rcu_unlock_buf_done; 434 434 } 435 435 if (nrport->port_role & ~(FC_PORT_ROLE_NVME_INITIATOR | 436 436 FC_PORT_ROLE_NVME_TARGET | ··· 438 438 scnprintf(tmp, sizeof(tmp), "UNKNOWN ROLE x%x", 439 439 nrport->port_role); 440 440 if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 441 - goto buffer_done; 441 + goto rcu_unlock_buf_done; 442 442 } 443 443 444 444 scnprintf(tmp, sizeof(tmp), "%s\n", statep); 445 445 if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 446 - goto buffer_done; 446 + goto rcu_unlock_buf_done; 447 447 } 448 448 rcu_read_unlock(); 449 449 ··· 505 505 atomic_read(&lport->cmpl_fcp_err)); 506 506 strlcat(buf, tmp, PAGE_SIZE); 507 507 508 - buffer_done: 508 + /* RCU is already unlocked. */ 509 + goto buffer_done; 510 + 511 + rcu_unlock_buf_done: 512 + rcu_read_unlock(); 513 + 514 + buffer_done: 509 515 len = strnlen(buf, PAGE_SIZE); 510 516 511 517 if (unlikely(len >= (PAGE_SIZE - 1))) {