aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAndreas Herrmann <aherrman@de.ibm.com>2005-06-13 07:20:35 -0400
committerJames Bottomley <jejb@mulgrave.(none)>2005-06-13 22:32:48 -0400
commit1db2c9c0931a53fe013db55fd2ff58859db31e8d (patch)
tree1134627ac98d91896dcdb161d5df7ecef60a4de3 /drivers
parent64b29a130901d5b8578e9f602cf2dae56aaff224 (diff)
[SCSI] zfcp: fix bug during adapter shutdown
Fixes a race between zfcp_fsf_req_dismiss_all and zfcp_qdio_reqid_check. During adapter shutdown it occurred that a request was cleaned up twice. First during its normal completion. Second when dismiss_all was called. The fix is to serialize access to fsf request list between zfcp_fsf_req_dismiss_all and zfcp_qdio_reqid_check and delete a fsf request from the list if its completion is triggered. (Additionally a rwlock was replaced by a spinlock and fsf_req_cleanup was eliminated.) Signed-off-by: Andreas Herrmann <aherrman@de.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/s390/scsi/zfcp_aux.c8
-rw-r--r--drivers/s390/scsi/zfcp_def.h2
-rw-r--r--drivers/s390/scsi/zfcp_erp.c4
-rw-r--r--drivers/s390/scsi/zfcp_ext.h2
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c79
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c28
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c2
7 files changed, 45 insertions, 80 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 6bb4d332b474..c999042dae15 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -520,7 +520,7 @@ zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command,
520 520
521 out: 521 out:
522 if (fsf_req != NULL) 522 if (fsf_req != NULL)
523 zfcp_fsf_req_cleanup(fsf_req); 523 zfcp_fsf_req_free(fsf_req);
524 524
525 if ((adapter != NULL) && (retval != -ENXIO)) 525 if ((adapter != NULL) && (retval != -ENXIO))
526 zfcp_adapter_put(adapter); 526 zfcp_adapter_put(adapter);
@@ -1149,7 +1149,7 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
1149 INIT_LIST_HEAD(&adapter->port_remove_lh); 1149 INIT_LIST_HEAD(&adapter->port_remove_lh);
1150 1150
1151 /* initialize list of fsf requests */ 1151 /* initialize list of fsf requests */
1152 rwlock_init(&adapter->fsf_req_list_lock); 1152 spin_lock_init(&adapter->fsf_req_list_lock);
1153 INIT_LIST_HEAD(&adapter->fsf_req_list_head); 1153 INIT_LIST_HEAD(&adapter->fsf_req_list_head);
1154 1154
1155 /* initialize abort lock */ 1155 /* initialize abort lock */
@@ -1234,9 +1234,9 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
1234 zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev); 1234 zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev);
1235 dev_set_drvdata(&adapter->ccw_device->dev, NULL); 1235 dev_set_drvdata(&adapter->ccw_device->dev, NULL);
1236 /* sanity check: no pending FSF requests */ 1236 /* sanity check: no pending FSF requests */
1237 read_lock_irqsave(&adapter->fsf_req_list_lock, flags); 1237 spin_lock_irqsave(&adapter->fsf_req_list_lock, flags);
1238 retval = !list_empty(&adapter->fsf_req_list_head); 1238 retval = !list_empty(&adapter->fsf_req_list_head);
1239 read_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); 1239 spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
1240 if (retval) { 1240 if (retval) {
1241 ZFCP_LOG_NORMAL("bug: adapter %s (%p) still in use, " 1241 ZFCP_LOG_NORMAL("bug: adapter %s (%p) still in use, "
1242 "%i requests outstanding\n", 1242 "%i requests outstanding\n",
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 37982058e4d9..bfbbb825f9ab 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -861,7 +861,7 @@ struct zfcp_adapter {
861 u32 ports; /* number of remote ports */ 861 u32 ports; /* number of remote ports */
862 struct timer_list scsi_er_timer; /* SCSI err recovery watch */ 862 struct timer_list scsi_er_timer; /* SCSI err recovery watch */
863 struct list_head fsf_req_list_head; /* head of FSF req list */ 863 struct list_head fsf_req_list_head; /* head of FSF req list */
864 rwlock_t fsf_req_list_lock; /* lock for ops on list of 864 spinlock_t fsf_req_list_lock; /* lock for ops on list of
865 FSF requests */ 865 FSF requests */
866 atomic_t fsf_reqs_active; /* # active FSF reqs */ 866 atomic_t fsf_reqs_active; /* # active FSF reqs */
867 struct zfcp_qdio_queue request_queue; /* request queue */ 867 struct zfcp_qdio_queue request_queue; /* request queue */
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 41c67e1ec4f7..6d73891eec9e 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -891,7 +891,7 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
891 891
892 if (erp_action->fsf_req) { 892 if (erp_action->fsf_req) {
893 /* take lock to ensure that request is not being deleted meanwhile */ 893 /* take lock to ensure that request is not being deleted meanwhile */
894 write_lock(&adapter->fsf_req_list_lock); 894 spin_lock(&adapter->fsf_req_list_lock);
895 /* check whether fsf req does still exist */ 895 /* check whether fsf req does still exist */
896 list_for_each_entry(fsf_req, &adapter->fsf_req_list_head, list) 896 list_for_each_entry(fsf_req, &adapter->fsf_req_list_head, list)
897 if (fsf_req == erp_action->fsf_req) 897 if (fsf_req == erp_action->fsf_req)
@@ -934,7 +934,7 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
934 */ 934 */
935 erp_action->fsf_req = NULL; 935 erp_action->fsf_req = NULL;
936 } 936 }
937 write_unlock(&adapter->fsf_req_list_lock); 937 spin_unlock(&adapter->fsf_req_list_lock);
938 } else 938 } else
939 debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq"); 939 debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq");
940 940
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index d5fd43352071..8f0da2e02a47 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -116,7 +116,7 @@ extern int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *,
116 struct timer_list*, int); 116 struct timer_list*, int);
117extern int zfcp_fsf_req_complete(struct zfcp_fsf_req *); 117extern int zfcp_fsf_req_complete(struct zfcp_fsf_req *);
118extern void zfcp_fsf_incoming_els(struct zfcp_fsf_req *); 118extern void zfcp_fsf_incoming_els(struct zfcp_fsf_req *);
119extern void zfcp_fsf_req_cleanup(struct zfcp_fsf_req *); 119extern void zfcp_fsf_req_free(struct zfcp_fsf_req *);
120extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_command_task_management( 120extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_command_task_management(
121 struct zfcp_adapter *, struct zfcp_unit *, u8, int); 121 struct zfcp_adapter *, struct zfcp_unit *, u8, int);
122extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command( 122extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 21a6d7633475..56b2ea97da1f 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -61,7 +61,6 @@ static int zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *);
61static int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *); 61static int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *);
62static int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *); 62static int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *);
63static void zfcp_fsf_req_dismiss(struct zfcp_fsf_req *); 63static void zfcp_fsf_req_dismiss(struct zfcp_fsf_req *);
64static void zfcp_fsf_req_free(struct zfcp_fsf_req *);
65 64
66/* association between FSF command and FSF QTCB type */ 65/* association between FSF command and FSF QTCB type */
67static u32 fsf_qtcb_type[] = { 66static u32 fsf_qtcb_type[] = {
@@ -149,13 +148,13 @@ zfcp_fsf_req_alloc(mempool_t *pool, int req_flags)
149 * 148 *
150 * locks: none 149 * locks: none
151 */ 150 */
152static void 151void
153zfcp_fsf_req_free(struct zfcp_fsf_req *fsf_req) 152zfcp_fsf_req_free(struct zfcp_fsf_req *fsf_req)
154{ 153{
155 if (likely(fsf_req->pool != NULL)) 154 if (likely(fsf_req->pool != NULL))
156 mempool_free(fsf_req, fsf_req->pool); 155 mempool_free(fsf_req, fsf_req->pool);
157 else 156 else
158 kfree(fsf_req); 157 kfree(fsf_req);
159} 158}
160 159
161/* 160/*
@@ -170,30 +169,21 @@ zfcp_fsf_req_free(struct zfcp_fsf_req *fsf_req)
170int 169int
171zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) 170zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
172{ 171{
173 int retval = 0;
174 struct zfcp_fsf_req *fsf_req, *tmp; 172 struct zfcp_fsf_req *fsf_req, *tmp;
173 unsigned long flags;
174 LIST_HEAD(remove_queue);
175 175
176 list_for_each_entry_safe(fsf_req, tmp, &adapter->fsf_req_list_head, 176 spin_lock_irqsave(&adapter->fsf_req_list_lock, flags);
177 list) 177 list_splice_init(&adapter->fsf_req_list_head, &remove_queue);
178 zfcp_fsf_req_dismiss(fsf_req); 178 atomic_set(&adapter->fsf_reqs_active, 0);
179 /* wait_event_timeout? */ 179 spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
180 while (!list_empty(&adapter->fsf_req_list_head)) {
181 ZFCP_LOG_DEBUG("fsf req list of adapter %s not yet empty\n",
182 zfcp_get_busid_by_adapter(adapter));
183 /* wait for woken intiators to clean up their requests */
184 msleep(jiffies_to_msecs(ZFCP_FSFREQ_CLEANUP_TIMEOUT));
185 }
186 180
187 /* consistency check */ 181 list_for_each_entry_safe(fsf_req, tmp, &remove_queue, list) {
188 if (atomic_read(&adapter->fsf_reqs_active)) { 182 list_del(&fsf_req->list);
189 ZFCP_LOG_NORMAL("bug: There are still %d FSF requests pending " 183 zfcp_fsf_req_dismiss(fsf_req);
190 "on adapter %s after cleanup.\n",
191 atomic_read(&adapter->fsf_reqs_active),
192 zfcp_get_busid_by_adapter(adapter));
193 atomic_set(&adapter->fsf_reqs_active, 0);
194 } 184 }
195 185
196 return retval; 186 return 0;
197} 187}
198 188
199/* 189/*
@@ -226,10 +216,6 @@ zfcp_fsf_req_complete(struct zfcp_fsf_req *fsf_req)
226{ 216{
227 int retval = 0; 217 int retval = 0;
228 int cleanup; 218 int cleanup;
229 struct zfcp_adapter *adapter = fsf_req->adapter;
230
231 /* do some statistics */
232 atomic_dec(&adapter->fsf_reqs_active);
233 219
234 if (unlikely(fsf_req->fsf_command == FSF_QTCB_UNSOLICITED_STATUS)) { 220 if (unlikely(fsf_req->fsf_command == FSF_QTCB_UNSOLICITED_STATUS)) {
235 ZFCP_LOG_DEBUG("Status read response received\n"); 221 ZFCP_LOG_DEBUG("Status read response received\n");
@@ -260,7 +246,7 @@ zfcp_fsf_req_complete(struct zfcp_fsf_req *fsf_req)
260 * lock must not be held here since it will be 246 * lock must not be held here since it will be
261 * grabed by the called routine, too 247 * grabed by the called routine, too
262 */ 248 */
263 zfcp_fsf_req_cleanup(fsf_req); 249 zfcp_fsf_req_free(fsf_req);
264 } else { 250 } else {
265 /* notify initiator waiting for the requests completion */ 251 /* notify initiator waiting for the requests completion */
266 ZFCP_LOG_TRACE("waking initiator of FSF request %p\n",fsf_req); 252 ZFCP_LOG_TRACE("waking initiator of FSF request %p\n",fsf_req);
@@ -936,7 +922,7 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
936 922
937 if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { 923 if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
938 mempool_free(status_buffer, adapter->pool.data_status_read); 924 mempool_free(status_buffer, adapter->pool.data_status_read);
939 zfcp_fsf_req_cleanup(fsf_req); 925 zfcp_fsf_req_free(fsf_req);
940 goto out; 926 goto out;
941 } 927 }
942 928
@@ -1033,7 +1019,7 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
1033 break; 1019 break;
1034 } 1020 }
1035 mempool_free(status_buffer, adapter->pool.data_status_read); 1021 mempool_free(status_buffer, adapter->pool.data_status_read);
1036 zfcp_fsf_req_cleanup(fsf_req); 1022 zfcp_fsf_req_free(fsf_req);
1037 /* 1023 /*
1038 * recycle buffer and start new request repeat until outbound 1024 * recycle buffer and start new request repeat until outbound
1039 * queue is empty or adapter shutdown is requested 1025 * queue is empty or adapter shutdown is requested
@@ -2258,7 +2244,7 @@ zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter,
2258 wait_event(fsf_req->completion_wq, 2244 wait_event(fsf_req->completion_wq,
2259 fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); 2245 fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
2260 del_timer_sync(timer); 2246 del_timer_sync(timer);
2261 zfcp_fsf_req_cleanup(fsf_req); 2247 zfcp_fsf_req_free(fsf_req);
2262 out: 2248 out:
2263 kfree(timer); 2249 kfree(timer);
2264 return retval; 2250 return retval;
@@ -4607,7 +4593,7 @@ zfcp_fsf_req_wait_and_cleanup(struct zfcp_fsf_req *fsf_req,
4607 *status = fsf_req->status; 4593 *status = fsf_req->status;
4608 4594
4609 /* cleanup request */ 4595 /* cleanup request */
4610 zfcp_fsf_req_cleanup(fsf_req); 4596 zfcp_fsf_req_free(fsf_req);
4611 out: 4597 out:
4612 return retval; 4598 return retval;
4613} 4599}
@@ -4806,9 +4792,9 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
4806 inc_seq_no = 0; 4792 inc_seq_no = 0;
4807 4793
4808 /* put allocated FSF request at list tail */ 4794 /* put allocated FSF request at list tail */
4809 write_lock_irqsave(&adapter->fsf_req_list_lock, flags); 4795 spin_lock_irqsave(&adapter->fsf_req_list_lock, flags);
4810 list_add_tail(&fsf_req->list, &adapter->fsf_req_list_head); 4796 list_add_tail(&fsf_req->list, &adapter->fsf_req_list_head);
4811 write_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); 4797 spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
4812 4798
4813 /* figure out expiration time of timeout and start timeout */ 4799 /* figure out expiration time of timeout and start timeout */
4814 if (unlikely(timer)) { 4800 if (unlikely(timer)) {
@@ -4852,9 +4838,9 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
4852 */ 4838 */
4853 if (timer) 4839 if (timer)
4854 del_timer(timer); 4840 del_timer(timer);
4855 write_lock_irqsave(&adapter->fsf_req_list_lock, flags); 4841 spin_lock_irqsave(&adapter->fsf_req_list_lock, flags);
4856 list_del(&fsf_req->list); 4842 list_del(&fsf_req->list);
4857 write_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); 4843 spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
4858 /* 4844 /*
4859 * adjust the number of free SBALs in request queue as well as 4845 * adjust the number of free SBALs in request queue as well as
4860 * position of first one 4846 * position of first one
@@ -4892,25 +4878,4 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
4892 return retval; 4878 return retval;
4893} 4879}
4894 4880
4895/*
4896 * function: zfcp_fsf_req_cleanup
4897 *
4898 * purpose: cleans up an FSF request and removes it from the specified list
4899 *
4900 * returns:
4901 *
4902 * assumption: no pending SB in SBALEs other than QTCB
4903 */
4904void
4905zfcp_fsf_req_cleanup(struct zfcp_fsf_req *fsf_req)
4906{
4907 struct zfcp_adapter *adapter = fsf_req->adapter;
4908 unsigned long flags;
4909
4910 write_lock_irqsave(&adapter->fsf_req_list_lock, flags);
4911 list_del(&fsf_req->list);
4912 write_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
4913 zfcp_fsf_req_free(fsf_req);
4914}
4915
4916#undef ZFCP_LOG_AREA 4881#undef ZFCP_LOG_AREA
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index fb218dd9d934..24e16ec331d9 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -446,37 +446,37 @@ int
446zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, void *sbale_addr) 446zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, void *sbale_addr)
447{ 447{
448 struct zfcp_fsf_req *fsf_req; 448 struct zfcp_fsf_req *fsf_req;
449 int retval = 0;
450 449
451 /* invalid (per convention used in this driver) */ 450 /* invalid (per convention used in this driver) */
452 if (unlikely(!sbale_addr)) { 451 if (unlikely(!sbale_addr)) {
453 ZFCP_LOG_NORMAL("bug: invalid reqid\n"); 452 ZFCP_LOG_NORMAL("bug: invalid reqid\n");
454 retval = -EINVAL; 453 return -EINVAL;
455 goto out;
456 } 454 }
457 455
458 /* valid request id and thus (hopefully :) valid fsf_req address */ 456 /* valid request id and thus (hopefully :) valid fsf_req address */
459 fsf_req = (struct zfcp_fsf_req *) sbale_addr; 457 fsf_req = (struct zfcp_fsf_req *) sbale_addr;
460 458
459 /* serialize with zfcp_fsf_req_dismiss_all */
460 spin_lock(&adapter->fsf_req_list_lock);
461 if (list_empty(&adapter->fsf_req_list_head)) {
462 spin_unlock(&adapter->fsf_req_list_lock);
463 return 0;
464 }
465 list_del(&fsf_req->list);
466 atomic_dec(&adapter->fsf_reqs_active);
467 spin_unlock(&adapter->fsf_req_list_lock);
468
461 if (unlikely(adapter != fsf_req->adapter)) { 469 if (unlikely(adapter != fsf_req->adapter)) {
462 ZFCP_LOG_NORMAL("bug: invalid reqid (fsf_req=%p, " 470 ZFCP_LOG_NORMAL("bug: invalid reqid (fsf_req=%p, "
463 "fsf_req->adapter=%p, adapter=%p)\n", 471 "fsf_req->adapter=%p, adapter=%p)\n",
464 fsf_req, fsf_req->adapter, adapter); 472 fsf_req, fsf_req->adapter, adapter);
465 retval = -EINVAL; 473 return -EINVAL;
466 goto out;
467 }
468
469 ZFCP_LOG_TRACE("fsf_req at %p, QTCB at %p\n", fsf_req, fsf_req->qtcb);
470 if (likely(fsf_req->qtcb)) {
471 ZFCP_LOG_TRACE("hex dump of QTCB:\n");
472 ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) fsf_req->qtcb,
473 sizeof(struct fsf_qtcb));
474 } 474 }
475 475
476 /* finish the FSF request */ 476 /* finish the FSF request */
477 zfcp_fsf_req_complete(fsf_req); 477 zfcp_fsf_req_complete(fsf_req);
478 out: 478
479 return retval; 479 return 0;
480} 480}
481 481
482/** 482/**
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index e21b547fd427..c6f69fc475a2 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -575,7 +575,7 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
575 *(u64 *) & new_fsf_req->qtcb->header.fsf_status_qual.word[0]; 575 *(u64 *) & new_fsf_req->qtcb->header.fsf_status_qual.word[0];
576 dbf_fsf_qual[1] = 576 dbf_fsf_qual[1] =
577 *(u64 *) & new_fsf_req->qtcb->header.fsf_status_qual.word[2]; 577 *(u64 *) & new_fsf_req->qtcb->header.fsf_status_qual.word[2];
578 zfcp_fsf_req_cleanup(new_fsf_req); 578 zfcp_fsf_req_free(new_fsf_req);
579#else 579#else
580 retval = zfcp_fsf_req_wait_and_cleanup(new_fsf_req, 580 retval = zfcp_fsf_req_wait_and_cleanup(new_fsf_req,
581 ZFCP_UNINTERRUPTIBLE, &status); 581 ZFCP_UNINTERRUPTIBLE, &status);