aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/scsi/zfcp_fsf.c
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/s390/scsi/zfcp_fsf.c
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/s390/scsi/zfcp_fsf.c')
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c79
1 files changed, 22 insertions, 57 deletions
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