| From 21befa74690c2395e5575a2fa5c6879fb02a3715 Mon Sep 17 00:00:00 2001 |
| From: Steffen Maier <maier@linux.ibm.com> |
| Date: Tue, 26 Mar 2019 14:37:00 +0100 |
| Subject: scsi: zfcp: reduce flood of fcrscn1 trace records on multi-element |
| RSCN |
| |
| [ Upstream commit c8206579175c34a2546de8a74262456278a7795a ] |
| |
| If an incoming ELS of type RSCN contains more than one element, zfcp |
| suboptimally causes repeated erp trigger NOP trace records for each |
| previously failed port. These could be ports that went away. It loops over |
| each RSCN element, and for each of those in an inner loop over all |
| zfcp_ports. |
| |
| The trigger to recover failed ports should be just the reception of some |
| RSCN, no matter how many elements it has. So we can loop over failed ports |
| separately, and only then loop over each RSCN element to handle the |
| non-failed ports. |
| |
| The call chain was: |
| |
| zfcp_fc_incoming_rscn |
| for (i = 1; i < no_entries; i++) |
| _zfcp_fc_incoming_rscn |
| list_for_each_entry(port, &adapter->port_list, list) |
| if (masked port->d_id match) zfcp_fc_test_link |
| if (!port->d_id) zfcp_erp_port_reopen "fcrscn1" <=== |
| |
| In order the reduce the "flooding" of the REC trace area in such cases, we |
| factor out handling the failed ports to be outside of the entries loop: |
| |
| zfcp_fc_incoming_rscn |
| if (no_entries > 1) <=== |
| list_for_each_entry(port, &adapter->port_list, list) <=== |
| if (!port->d_id) zfcp_erp_port_reopen "fcrscn1" <=== |
| for (i = 1; i < no_entries; i++) |
| _zfcp_fc_incoming_rscn |
| list_for_each_entry(port, &adapter->port_list, list) |
| if (masked port->d_id match) zfcp_fc_test_link |
| |
| Abbreviated example trace records before this code change: |
| |
| Tag : fcrscn1 |
| WWPN : 0x500507630310d327 |
| ERP want : 0x02 |
| ERP need : 0x02 |
| |
| Tag : fcrscn1 |
| WWPN : 0x500507630310d327 |
| ERP want : 0x02 |
| ERP need : 0x00 NOP => superfluous trace record |
| |
| The last trace entry repeats if there are more than 2 RSCN elements. |
| |
| Signed-off-by: Steffen Maier <maier@linux.ibm.com> |
| Reviewed-by: Benjamin Block <bblock@linux.ibm.com> |
| Reviewed-by: Jens Remus <jremus@linux.ibm.com> |
| Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> |
| Signed-off-by: Sasha Levin (Microsoft) <sashal@kernel.org> |
| --- |
| drivers/s390/scsi/zfcp_fc.c | 21 +++++++++++++++++---- |
| 1 file changed, 17 insertions(+), 4 deletions(-) |
| |
| diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c |
| index ca218c82321f..0c5fd722a72d 100644 |
| --- a/drivers/s390/scsi/zfcp_fc.c |
| +++ b/drivers/s390/scsi/zfcp_fc.c |
| @@ -240,10 +240,6 @@ static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, |
| list_for_each_entry(port, &adapter->port_list, list) { |
| if ((port->d_id & range) == (ntoh24(page->rscn_fid) & range)) |
| zfcp_fc_test_link(port); |
| - if (!port->d_id) |
| - zfcp_erp_port_reopen(port, |
| - ZFCP_STATUS_COMMON_ERP_FAILED, |
| - "fcrscn1"); |
| } |
| read_unlock_irqrestore(&adapter->port_list_lock, flags); |
| } |
| @@ -251,6 +247,7 @@ static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, |
| static void zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req) |
| { |
| struct fsf_status_read_buffer *status_buffer = (void *)fsf_req->data; |
| + struct zfcp_adapter *adapter = fsf_req->adapter; |
| struct fc_els_rscn *head; |
| struct fc_els_rscn_page *page; |
| u16 i; |
| @@ -264,6 +261,22 @@ static void zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req) |
| no_entries = be16_to_cpu(head->rscn_plen) / |
| sizeof(struct fc_els_rscn_page); |
| |
| + if (no_entries > 1) { |
| + /* handle failed ports */ |
| + unsigned long flags; |
| + struct zfcp_port *port; |
| + |
| + read_lock_irqsave(&adapter->port_list_lock, flags); |
| + list_for_each_entry(port, &adapter->port_list, list) { |
| + if (port->d_id) |
| + continue; |
| + zfcp_erp_port_reopen(port, |
| + ZFCP_STATUS_COMMON_ERP_FAILED, |
| + "fcrscn1"); |
| + } |
| + read_unlock_irqrestore(&adapter->port_list_lock, flags); |
| + } |
| + |
| for (i = 1; i < no_entries; i++) { |
| /* skip head and start with 1st element */ |
| page++; |
| -- |
| 2.19.1 |
| |