[SCSI] zfcp: Replace fsf_req wait_queue with completion
The combination wait_queue/wakeup in conjunction with the flag
ZFCP_STATUS_FSFREQ_COMPLETED to signal the completion of an fsfreq
was not race-safe and can be better solved by a completion.
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@suse.de>
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 7ca2995..ed06a1d 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -444,23 +444,11 @@
if (req->erp_action)
zfcp_erp_notify(req->erp_action, 0);
- req->status |= ZFCP_STATUS_FSFREQ_COMPLETED;
if (likely(req->status & ZFCP_STATUS_FSFREQ_CLEANUP))
zfcp_fsf_req_free(req);
else
- /* notify initiator waiting for the requests completion */
- /*
- * FIXME: Race! We must not access fsf_req here as it might have been
- * cleaned up already due to the set ZFCP_STATUS_FSFREQ_COMPLETED
- * flag. It's an improbable case. But, we have the same paranoia for
- * the cleanup flag already.
- * Might better be handled using complete()?
- * (setting the flag and doing wakeup ought to be atomic
- * with regard to checking the flag as long as waitqueue is
- * part of the to be released structure)
- */
- wake_up(&req->completion_wq);
+ complete(&req->completion);
}
/**
@@ -733,7 +721,7 @@
INIT_LIST_HEAD(&req->list);
init_timer(&req->timer);
- init_waitqueue_head(&req->completion_wq);
+ init_completion(&req->completion);
req->adapter = adapter;
req->fsf_command = fsf_cmd;
@@ -1309,8 +1297,7 @@
retval = zfcp_fsf_req_send(req);
spin_unlock_bh(&adapter->req_q_lock);
if (!retval)
- wait_event(req->completion_wq,
- req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+ wait_for_completion(&req->completion);
zfcp_fsf_req_free(req);
return retval;
@@ -1405,8 +1392,8 @@
spin_unlock_bh(&adapter->req_q_lock);
if (!retval)
- wait_event(req->completion_wq,
- req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+ wait_for_completion(&req->completion);
+
zfcp_fsf_req_free(req);
return retval;
@@ -2572,8 +2559,7 @@
spin_unlock_bh(&adapter->req_q_lock);
if (!retval) {
- wait_event(req->completion_wq,
- req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+ wait_for_completion(&req->completion);
return req;
}
return ERR_PTR(retval);