scsi: lpfc: correct rcu unlock issue in lpfc_nvme_info_show
authorJames Smart <jsmart2021@gmail.com>
Tue, 7 May 2019 00:26:48 +0000 (17:26 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 14 May 2019 00:32:50 +0000 (20:32 -0400)
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>
drivers/scsi/lpfc/lpfc_attr.c

index 31b963a..d4c65e2 100644 (file)
@@ -355,7 +355,7 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
                  phba->sli4_hba.io_xri_max,
                  lpfc_sli4_get_els_iocb_cnt(phba));
        if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
-               goto buffer_done;
+               goto rcu_unlock_buf_done;
 
        /* Port state is only one of two values for now. */
        if (localport->port_id)
@@ -371,7 +371,7 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
                  wwn_to_u64(vport->fc_nodename.u.wwn),
                  localport->port_id, statep);
        if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
-               goto buffer_done;
+               goto rcu_unlock_buf_done;
 
        list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
                nrport = NULL;
@@ -398,39 +398,39 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
 
                /* Tab in to show lport ownership. */
                if (strlcat(buf, "NVME RPORT       ", PAGE_SIZE) >= PAGE_SIZE)
-                       goto buffer_done;
+                       goto rcu_unlock_buf_done;
                if (phba->brd_no >= 10) {
                        if (strlcat(buf, " ", PAGE_SIZE) >= PAGE_SIZE)
-                               goto buffer_done;
+                               goto rcu_unlock_buf_done;
                }
 
                scnprintf(tmp, sizeof(tmp), "WWPN x%llx ",
                          nrport->port_name);
                if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
-                       goto buffer_done;
+                       goto rcu_unlock_buf_done;
 
                scnprintf(tmp, sizeof(tmp), "WWNN x%llx ",
                          nrport->node_name);
                if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
-                       goto buffer_done;
+                       goto rcu_unlock_buf_done;
 
                scnprintf(tmp, sizeof(tmp), "DID x%06x ",
                          nrport->port_id);
                if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
-                       goto buffer_done;
+                       goto rcu_unlock_buf_done;
 
                /* An NVME rport can have multiple roles. */
                if (nrport->port_role & FC_PORT_ROLE_NVME_INITIATOR) {
                        if (strlcat(buf, "INITIATOR ", PAGE_SIZE) >= PAGE_SIZE)
-                               goto buffer_done;
+                               goto rcu_unlock_buf_done;
                }
                if (nrport->port_role & FC_PORT_ROLE_NVME_TARGET) {
                        if (strlcat(buf, "TARGET ", PAGE_SIZE) >= PAGE_SIZE)
-                               goto buffer_done;
+                               goto rcu_unlock_buf_done;
                }
                if (nrport->port_role & FC_PORT_ROLE_NVME_DISCOVERY) {
                        if (strlcat(buf, "DISCSRVC ", PAGE_SIZE) >= PAGE_SIZE)
-                               goto buffer_done;
+                               goto rcu_unlock_buf_done;
                }
                if (nrport->port_role & ~(FC_PORT_ROLE_NVME_INITIATOR |
                                          FC_PORT_ROLE_NVME_TARGET |
@@ -438,12 +438,12 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
                        scnprintf(tmp, sizeof(tmp), "UNKNOWN ROLE x%x",
                                  nrport->port_role);
                        if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
-                               goto buffer_done;
+                               goto rcu_unlock_buf_done;
                }
 
                scnprintf(tmp, sizeof(tmp), "%s\n", statep);
                if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
-                       goto buffer_done;
+                       goto rcu_unlock_buf_done;
        }
        rcu_read_unlock();
 
@@ -505,7 +505,13 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
                  atomic_read(&lport->cmpl_fcp_err));
        strlcat(buf, tmp, PAGE_SIZE);
 
-buffer_done:
+       /* RCU is already unlocked. */
+       goto buffer_done;
+
+ rcu_unlock_buf_done:
+       rcu_read_unlock();
+
+ buffer_done:
        len = strnlen(buf, PAGE_SIZE);
 
        if (unlikely(len >= (PAGE_SIZE - 1))) {