aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/scsi/zfcp_aux.c
diff options
context:
space:
mode:
authorSwen Schillig <swen@vnet.ibm.com>2008-05-19 06:17:37 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-06-05 10:27:13 -0400
commitd26ab06ede83287f99067fee3034c5455a75faf9 (patch)
tree6070ae50cded8086ceab61092348790b39876146 /drivers/s390/scsi/zfcp_aux.c
parent15424921222f2bed0aa92ef1e8bc94f753d2c6ea (diff)
[SCSI] zfcp: receiving an unsolicted status can lead to I/O stall
Processing of an unsolicted status request can lead to a locking race of the request_queue's queue_lock during the recreation of the used up status read request while still in interrupt context of the response handler. Detaching the 'refill' of the long running status read requests from the handler to a scheduled work is solving this issue. In addition, each refill-run is trying to re-establish the full amount of status read requests, which might have failed in earlier runs. Signed-off-by: Swen Schillig <swen@vnet.ibm.com> Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/s390/scsi/zfcp_aux.c')
-rw-r--r--drivers/s390/scsi/zfcp_aux.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index d23027a2f2f0..41635b13ccb1 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -970,6 +970,27 @@ static void zfcp_dummy_release(struct device *dev)
970 return; 970 return;
971} 971}
972 972
973int zfcp_status_read_refill(struct zfcp_adapter *adapter)
974{
975 while (atomic_read(&adapter->stat_miss) > 0)
976 if (zfcp_fsf_status_read(adapter, ZFCP_WAIT_FOR_SBAL))
977 break;
978 else
979 atomic_dec(&adapter->stat_miss);
980
981 if (ZFCP_STATUS_READS_RECOM <= atomic_read(&adapter->stat_miss)) {
982 zfcp_erp_adapter_reopen(adapter, 0, 103, NULL);
983 return 1;
984 }
985 return 0;
986}
987
988static void _zfcp_status_read_scheduler(struct work_struct *work)
989{
990 zfcp_status_read_refill(container_of(work, struct zfcp_adapter,
991 stat_work));
992}
993
973/* 994/*
974 * Enqueues an adapter at the end of the adapter list in the driver data. 995 * Enqueues an adapter at the end of the adapter list in the driver data.
975 * All adapter internal structures are set up. 996 * All adapter internal structures are set up.
@@ -1063,6 +1084,7 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
1063 1084
1064 /* initialize lock of associated request queue */ 1085 /* initialize lock of associated request queue */
1065 rwlock_init(&adapter->request_queue.queue_lock); 1086 rwlock_init(&adapter->request_queue.queue_lock);
1087 INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler);
1066 1088
1067 /* mark adapter unusable as long as sysfs registration is not complete */ 1089 /* mark adapter unusable as long as sysfs registration is not complete */
1068 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); 1090 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
@@ -1123,6 +1145,7 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
1123 int retval = 0; 1145 int retval = 0;
1124 unsigned long flags; 1146 unsigned long flags;
1125 1147
1148 cancel_work_sync(&adapter->stat_work);
1126 zfcp_adapter_scsi_unregister(adapter); 1149 zfcp_adapter_scsi_unregister(adapter);
1127 device_unregister(&adapter->generic_services); 1150 device_unregister(&adapter->generic_services);
1128 zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev); 1151 zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev);