diff options
author | Jens Axboe <jens.axboe@oracle.com> | 2008-09-14 08:55:09 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2008-10-09 02:56:13 -0400 |
commit | 242f9dcb8ba6f68fcd217a119a7648a4f69290e9 (patch) | |
tree | 1bfe245ffbc50d204d76665cd8f90d85100f86a1 /drivers/scsi/scsi_error.c | |
parent | 608aeef17a91747d6303de4df5e2c2e6899a95e8 (diff) |
block: unify request timeout handling
Right now SCSI and others do their own command timeout handling.
Move those bits to the block layer.
Instead of having a timer per command, we try to be a bit more clever
and simply have one per-queue. This avoids the overhead of having to
tear down and setup a timer for each command, so it will result in a lot
less timer fiddling.
Signed-off-by: Mike Anderson <andmike@linux.vnet.ibm.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'drivers/scsi/scsi_error.c')
-rw-r--r-- | drivers/scsi/scsi_error.c | 90 |
1 files changed, 13 insertions, 77 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 39ce3aba1dac..fecefa05cb62 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -112,69 +112,8 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag) | |||
112 | } | 112 | } |
113 | 113 | ||
114 | /** | 114 | /** |
115 | * scsi_add_timer - Start timeout timer for a single scsi command. | ||
116 | * @scmd: scsi command that is about to start running. | ||
117 | * @timeout: amount of time to allow this command to run. | ||
118 | * @complete: timeout function to call if timer isn't canceled. | ||
119 | * | ||
120 | * Notes: | ||
121 | * This should be turned into an inline function. Each scsi command | ||
122 | * has its own timer, and as it is added to the queue, we set up the | ||
123 | * timer. When the command completes, we cancel the timer. | ||
124 | */ | ||
125 | void scsi_add_timer(struct scsi_cmnd *scmd, int timeout, | ||
126 | void (*complete)(struct scsi_cmnd *)) | ||
127 | { | ||
128 | |||
129 | /* | ||
130 | * If the clock was already running for this command, then | ||
131 | * first delete the timer. The timer handling code gets rather | ||
132 | * confused if we don't do this. | ||
133 | */ | ||
134 | if (scmd->eh_timeout.function) | ||
135 | del_timer(&scmd->eh_timeout); | ||
136 | |||
137 | scmd->eh_timeout.data = (unsigned long)scmd; | ||
138 | scmd->eh_timeout.expires = jiffies + timeout; | ||
139 | scmd->eh_timeout.function = (void (*)(unsigned long)) complete; | ||
140 | |||
141 | SCSI_LOG_ERROR_RECOVERY(5, printk("%s: scmd: %p, time:" | ||
142 | " %d, (%p)\n", __func__, | ||
143 | scmd, timeout, complete)); | ||
144 | |||
145 | add_timer(&scmd->eh_timeout); | ||
146 | } | ||
147 | |||
148 | /** | ||
149 | * scsi_delete_timer - Delete/cancel timer for a given function. | ||
150 | * @scmd: Cmd that we are canceling timer for | ||
151 | * | ||
152 | * Notes: | ||
153 | * This should be turned into an inline function. | ||
154 | * | ||
155 | * Return value: | ||
156 | * 1 if we were able to detach the timer. 0 if we blew it, and the | ||
157 | * timer function has already started to run. | ||
158 | */ | ||
159 | int scsi_delete_timer(struct scsi_cmnd *scmd) | ||
160 | { | ||
161 | int rtn; | ||
162 | |||
163 | rtn = del_timer(&scmd->eh_timeout); | ||
164 | |||
165 | SCSI_LOG_ERROR_RECOVERY(5, printk("%s: scmd: %p," | ||
166 | " rtn: %d\n", __func__, | ||
167 | scmd, rtn)); | ||
168 | |||
169 | scmd->eh_timeout.data = (unsigned long)NULL; | ||
170 | scmd->eh_timeout.function = NULL; | ||
171 | |||
172 | return rtn; | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * scsi_times_out - Timeout function for normal scsi commands. | 115 | * scsi_times_out - Timeout function for normal scsi commands. |
177 | * @scmd: Cmd that is timing out. | 116 | * @req: request that is timing out. |
178 | * | 117 | * |
179 | * Notes: | 118 | * Notes: |
180 | * We do not need to lock this. There is the potential for a race | 119 | * We do not need to lock this. There is the potential for a race |
@@ -182,9 +121,11 @@ int scsi_delete_timer(struct scsi_cmnd *scmd) | |||
182 | * normal completion function determines that the timer has already | 121 | * normal completion function determines that the timer has already |
183 | * fired, then it mustn't do anything. | 122 | * fired, then it mustn't do anything. |
184 | */ | 123 | */ |
185 | void scsi_times_out(struct scsi_cmnd *scmd) | 124 | enum blk_eh_timer_return scsi_times_out(struct request *req) |
186 | { | 125 | { |
187 | enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *); | 126 | struct scsi_cmnd *scmd = req->special; |
127 | enum blk_eh_timer_return (*eh_timed_out)(struct scsi_cmnd *); | ||
128 | enum blk_eh_timer_return rtn = BLK_EH_NOT_HANDLED; | ||
188 | 129 | ||
189 | scsi_log_completion(scmd, TIMEOUT_ERROR); | 130 | scsi_log_completion(scmd, TIMEOUT_ERROR); |
190 | 131 | ||
@@ -196,22 +137,20 @@ void scsi_times_out(struct scsi_cmnd *scmd) | |||
196 | eh_timed_out = NULL; | 137 | eh_timed_out = NULL; |
197 | 138 | ||
198 | if (eh_timed_out) | 139 | if (eh_timed_out) |
199 | switch (eh_timed_out(scmd)) { | 140 | rtn = eh_timed_out(scmd); |
200 | case EH_HANDLED: | 141 | switch (rtn) { |
201 | __scsi_done(scmd); | 142 | case BLK_EH_NOT_HANDLED: |
202 | return; | ||
203 | case EH_RESET_TIMER: | ||
204 | scsi_add_timer(scmd, scmd->timeout_per_command, | ||
205 | scsi_times_out); | ||
206 | return; | ||
207 | case EH_NOT_HANDLED: | ||
208 | break; | 143 | break; |
144 | default: | ||
145 | return rtn; | ||
209 | } | 146 | } |
210 | 147 | ||
211 | if (unlikely(!scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) { | 148 | if (unlikely(!scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) { |
212 | scmd->result |= DID_TIME_OUT << 16; | 149 | scmd->result |= DID_TIME_OUT << 16; |
213 | __scsi_done(scmd); | 150 | return BLK_EH_HANDLED; |
214 | } | 151 | } |
152 | |||
153 | return BLK_EH_NOT_HANDLED; | ||
215 | } | 154 | } |
216 | 155 | ||
217 | /** | 156 | /** |
@@ -1793,7 +1732,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag) | |||
1793 | 1732 | ||
1794 | blk_rq_init(NULL, &req); | 1733 | blk_rq_init(NULL, &req); |
1795 | scmd->request = &req; | 1734 | scmd->request = &req; |
1796 | memset(&scmd->eh_timeout, 0, sizeof(scmd->eh_timeout)); | ||
1797 | 1735 | ||
1798 | scmd->cmnd = req.cmd; | 1736 | scmd->cmnd = req.cmd; |
1799 | 1737 | ||
@@ -1804,8 +1742,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag) | |||
1804 | 1742 | ||
1805 | scmd->sc_data_direction = DMA_BIDIRECTIONAL; | 1743 | scmd->sc_data_direction = DMA_BIDIRECTIONAL; |
1806 | 1744 | ||
1807 | init_timer(&scmd->eh_timeout); | ||
1808 | |||
1809 | spin_lock_irqsave(shost->host_lock, flags); | 1745 | spin_lock_irqsave(shost->host_lock, flags); |
1810 | shost->tmf_in_progress = 1; | 1746 | shost->tmf_in_progress = 1; |
1811 | spin_unlock_irqrestore(shost->host_lock, flags); | 1747 | spin_unlock_irqrestore(shost->host_lock, flags); |