diff options
author | Swen Schillig <swen@vnet.ibm.com> | 2009-08-18 09:43:14 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-09-05 09:49:18 -0400 |
commit | 058b8647892ed49ba6a0d2c0966a72e20e2e69ff (patch) | |
tree | ba8baad2244bbacc5974207fb2274fb6c355d385 /drivers/s390 | |
parent | bd63eaf4b8d783e6033930e377e516169abcadc4 (diff) |
[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>
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/scsi/zfcp_def.h | 3 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 3 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 26 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 6 |
4 files changed, 10 insertions, 28 deletions
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index c1becfc1e7f..944f67754ee 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
@@ -248,7 +248,6 @@ enum zfcp_wka_status { | |||
248 | 248 | ||
249 | /* FSF request status (this does not have a common part) */ | 249 | /* FSF request status (this does not have a common part) */ |
250 | #define ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT 0x00000002 | 250 | #define ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT 0x00000002 |
251 | #define ZFCP_STATUS_FSFREQ_COMPLETED 0x00000004 | ||
252 | #define ZFCP_STATUS_FSFREQ_ERROR 0x00000008 | 251 | #define ZFCP_STATUS_FSFREQ_ERROR 0x00000008 |
253 | #define ZFCP_STATUS_FSFREQ_CLEANUP 0x00000010 | 252 | #define ZFCP_STATUS_FSFREQ_CLEANUP 0x00000010 |
254 | #define ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED 0x00000040 | 253 | #define ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED 0x00000040 |
@@ -532,7 +531,7 @@ struct zfcp_fsf_req { | |||
532 | u8 sbale_curr; /* current SBALE during creation | 531 | u8 sbale_curr; /* current SBALE during creation |
533 | of request */ | 532 | of request */ |
534 | u8 sbal_response; /* SBAL used in interrupt */ | 533 | u8 sbal_response; /* SBAL used in interrupt */ |
535 | wait_queue_head_t completion_wq; /* can be used by a routine | 534 | struct completion completion; /* can be used by a routine |
536 | to wait for completion */ | 535 | to wait for completion */ |
537 | u32 status; /* status of this request */ | 536 | u32 status; /* status of this request */ |
538 | u32 fsf_command; /* FSF Command copy */ | 537 | u32 fsf_command; /* FSF Command copy */ |
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 39e4dd15453..a377e2f9125 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
@@ -485,8 +485,7 @@ static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act) | |||
485 | } | 485 | } |
486 | if (act->status & ZFCP_STATUS_ERP_TIMEDOUT) | 486 | if (act->status & ZFCP_STATUS_ERP_TIMEDOUT) |
487 | zfcp_rec_dbf_event_action("erscf_2", act); | 487 | zfcp_rec_dbf_event_action("erscf_2", act); |
488 | if (act->fsf_req->status & (ZFCP_STATUS_FSFREQ_COMPLETED | | 488 | if (act->fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) |
489 | ZFCP_STATUS_FSFREQ_DISMISSED)) | ||
490 | act->fsf_req = NULL; | 489 | act->fsf_req = NULL; |
491 | } else | 490 | } else |
492 | act->fsf_req = NULL; | 491 | act->fsf_req = NULL; |
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 7ca2995aaf6..ed06a1d17b7 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -444,23 +444,11 @@ static void zfcp_fsf_req_complete(struct zfcp_fsf_req *req) | |||
444 | 444 | ||
445 | if (req->erp_action) | 445 | if (req->erp_action) |
446 | zfcp_erp_notify(req->erp_action, 0); | 446 | zfcp_erp_notify(req->erp_action, 0); |
447 | req->status |= ZFCP_STATUS_FSFREQ_COMPLETED; | ||
448 | 447 | ||
449 | if (likely(req->status & ZFCP_STATUS_FSFREQ_CLEANUP)) | 448 | if (likely(req->status & ZFCP_STATUS_FSFREQ_CLEANUP)) |
450 | zfcp_fsf_req_free(req); | 449 | zfcp_fsf_req_free(req); |
451 | else | 450 | else |
452 | /* notify initiator waiting for the requests completion */ | 451 | complete(&req->completion); |
453 | /* | ||
454 | * FIXME: Race! We must not access fsf_req here as it might have been | ||
455 | * cleaned up already due to the set ZFCP_STATUS_FSFREQ_COMPLETED | ||
456 | * flag. It's an improbable case. But, we have the same paranoia for | ||
457 | * the cleanup flag already. | ||
458 | * Might better be handled using complete()? | ||
459 | * (setting the flag and doing wakeup ought to be atomic | ||
460 | * with regard to checking the flag as long as waitqueue is | ||
461 | * part of the to be released structure) | ||
462 | */ | ||
463 | wake_up(&req->completion_wq); | ||
464 | } | 452 | } |
465 | 453 | ||
466 | /** | 454 | /** |
@@ -733,7 +721,7 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter, | |||
733 | 721 | ||
734 | INIT_LIST_HEAD(&req->list); | 722 | INIT_LIST_HEAD(&req->list); |
735 | init_timer(&req->timer); | 723 | init_timer(&req->timer); |
736 | init_waitqueue_head(&req->completion_wq); | 724 | init_completion(&req->completion); |
737 | 725 | ||
738 | req->adapter = adapter; | 726 | req->adapter = adapter; |
739 | req->fsf_command = fsf_cmd; | 727 | req->fsf_command = fsf_cmd; |
@@ -1309,8 +1297,7 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter, | |||
1309 | retval = zfcp_fsf_req_send(req); | 1297 | retval = zfcp_fsf_req_send(req); |
1310 | spin_unlock_bh(&adapter->req_q_lock); | 1298 | spin_unlock_bh(&adapter->req_q_lock); |
1311 | if (!retval) | 1299 | if (!retval) |
1312 | wait_event(req->completion_wq, | 1300 | wait_for_completion(&req->completion); |
1313 | req->status & ZFCP_STATUS_FSFREQ_COMPLETED); | ||
1314 | 1301 | ||
1315 | zfcp_fsf_req_free(req); | 1302 | zfcp_fsf_req_free(req); |
1316 | return retval; | 1303 | return retval; |
@@ -1405,8 +1392,8 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter, | |||
1405 | spin_unlock_bh(&adapter->req_q_lock); | 1392 | spin_unlock_bh(&adapter->req_q_lock); |
1406 | 1393 | ||
1407 | if (!retval) | 1394 | if (!retval) |
1408 | wait_event(req->completion_wq, | 1395 | wait_for_completion(&req->completion); |
1409 | req->status & ZFCP_STATUS_FSFREQ_COMPLETED); | 1396 | |
1410 | zfcp_fsf_req_free(req); | 1397 | zfcp_fsf_req_free(req); |
1411 | 1398 | ||
1412 | return retval; | 1399 | return retval; |
@@ -2572,8 +2559,7 @@ out: | |||
2572 | spin_unlock_bh(&adapter->req_q_lock); | 2559 | spin_unlock_bh(&adapter->req_q_lock); |
2573 | 2560 | ||
2574 | if (!retval) { | 2561 | if (!retval) { |
2575 | wait_event(req->completion_wq, | 2562 | wait_for_completion(&req->completion); |
2576 | req->status & ZFCP_STATUS_FSFREQ_COMPLETED); | ||
2577 | return req; | 2563 | return req; |
2578 | } | 2564 | } |
2579 | return ERR_PTR(retval); | 2565 | return ERR_PTR(retval); |
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 0bd80a90426..0de059161b3 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c | |||
@@ -206,8 +206,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | |||
206 | if (!abrt_req) | 206 | if (!abrt_req) |
207 | return FAILED; | 207 | return FAILED; |
208 | 208 | ||
209 | wait_event(abrt_req->completion_wq, | 209 | wait_for_completion(&abrt_req->completion); |
210 | abrt_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); | ||
211 | 210 | ||
212 | if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) | 211 | if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) |
213 | dbf_tag = "okay"; | 212 | dbf_tag = "okay"; |
@@ -246,8 +245,7 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags) | |||
246 | if (!fsf_req) | 245 | if (!fsf_req) |
247 | return FAILED; | 246 | return FAILED; |
248 | 247 | ||
249 | wait_event(fsf_req->completion_wq, | 248 | wait_for_completion(&fsf_req->completion); |
250 | fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); | ||
251 | 249 | ||
252 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) { | 250 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) { |
253 | zfcp_scsi_dbf_event_devreset("fail", tm_flags, unit, scpnt); | 251 | zfcp_scsi_dbf_event_devreset("fail", tm_flags, unit, scpnt); |