]> www.infradead.org Git - users/jedix/linux-maple.git/commit
qla2xxx: Test and clear FCPORT_UPDATE_NEEDED atomically.
authorDavid Jeffery <djeffery@redhat.com>
Thu, 11 Oct 2012 00:09:24 +0000 (05:39 +0530)
committerJerry Snitselaar <jerry.snitselaar@oracle.com>
Thu, 29 Nov 2012 22:18:24 +0000 (15:18 -0700)
commite6286fae32c9e90e0975ba59c28b9893ef8ade14
tree98a3b4089356f4c916b10bba4092e712c4048d9e
parentb63be94bd28c8648b766a8e92463aaf68494d383
qla2xxx: Test and clear FCPORT_UPDATE_NEEDED atomically.

When the qla2xxx driver loses access to multiple, remote ports, there is a race
condition which can occur which will keep the request stuck on a scsi request
queue indefinitely.

While testing path loss, a customer encountered a case where the loss of the FC
connection could result in a process which sent a command through the sg driver
becoming hung and unresponsive.  It had sent a command to one of the now
unreachable LUNs, and the command and its request never completes.

But this isn't a case of the target and LUNs being blocked.  From a vmcore, the
FC transport still considered the port as in a working, FC_PORTSTATE_ONLINE
state.  Instead, the request was on the queue, but the target structure was in
blocked state.  qla2xxx's queuecommand function was returning
SCSI_MLQUEUE_TARGET_BUSY, causing the request to keep being requeued and retried
without ever advancing.  The qla2xxx driver was rejecting the command with
SCSI_MLQUEUE_TARGET_BUSY because its internal port state for this port was in
FCS_DEVICE_LOST state.  This should not happen.  qla2xxx should not think the
port is lost while the fc transport thinks the device is in good, working order.

This bad state occurred do to a race condition with how the FCPORT_UPDATE_NEEDED
bit is set in qla2x00_schedule_rport_del(), and how it is cleared in
qla2x00_do_dpc().  The problem port has its drport pointer set, but it has never
been processed by the driver to inform the fc transport that the port has been
lost.  qla2x00_schedule_rport_del() sets drport, and then sets the
FCPORT_UPDATE_NEEDED bit.  In qla2x00_do_dpc(), the port lists are walked and
any drport pointer is handled and the fc transport informed of the port loss,
then the FCPORT_UPDATE_NEEDED bit is cleared.  This leaves a race where the
dpc thread is processing one port removal, another port removal is marked
with a call to qla2x00_schedule_rport_del(), and the dpc thread clears the
bit for both removals, even though only the first removal was actually
handled.  Until another event occurs to set FCPORT_UPDATE_NEEDED, the later
port removal is never finished and qla2xxx stays in a bad state which causes
requests to become stuck on request queues.

The attached patch updates the driver to test and clear FCPORT_UPDATE_NEEDED
atomically.  This ensures the port state changes are processed and not lost.
If a race occurs, the dpc thread will walk the ports an extra time as
FCPORT_UPDATE_NEEDED will have become set again.

JIRA Key: V2632FC-283

Acked-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
Acked-by: Armen Baloyan <armen.baloyan@qlogic.com>
Signed-off-by: Chad Dupuis <chad.dupuis@qlogic.com>
Signed-off-by: Saurav Kashyap <saurav.kashyap@qlogic.com>
Signed-off-by: Jerry Snitselaar <jerry.snitselaar@oracle.com>
drivers/scsi/qla2xxx/qla_os.c