diff options
author | Tejun Heo <tj@kernel.org> | 2009-05-07 09:24:37 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2009-05-11 03:50:53 -0400 |
commit | c3a4d78c580de4edc9ef0f7c59812fb02ceb037f (patch) | |
tree | 916ca44287100707508678e2cc0eff0c43b9ca39 /drivers/scsi | |
parent | 9720aef2539c10e3a872e9a92beec225030d99db (diff) |
block: add rq->resid_len
rq->data_len served two purposes - the length of data buffer on issue
and the residual count on completion. This duality creates some
headaches.
First of all, block layer and low level drivers can't really determine
what rq->data_len contains while a request is executing. It could be
the total request length or it coulde be anything else one of the
lower layers is using to keep track of residual count. This
complicates things because blk_rq_bytes() and thus
[__]blk_end_request_all() relies on rq->data_len for PC commands.
Drivers which want to report residual count should first cache the
total request length, update rq->data_len and then complete the
request with the cached data length.
Secondly, it makes requests default to reporting full residual count,
ie. reporting that no data transfer occurred. The residual count is
an exception not the norm; however, the driver should clear
rq->data_len to zero to signify the normal cases while leaving it
alone means no data transfer occurred at all. This reverse default
behavior complicates code unnecessarily and renders block PC on some
drivers (ide-tape/floppy) unuseable.
This patch adds rq->resid_len which is used only for residual count.
While at it, remove now unnecessasry blk_rq_bytes() caching in
ide_pc_intr() as rq->data_len is not changed anymore.
Boaz : spotted missing conversion in osd
Sergei : spotted too early conversion to blk_rq_bytes() in ide-tape
[ Impact: cleanup residual count handling, report 0 resid by default ]
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
Cc: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Cc: Borislav Petkov <petkovbb@googlemail.com>
Cc: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Cc: Mike Miller <mike.miller@hp.com>
Cc: Eric Moore <Eric.Moore@lsi.com>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Cc: Doug Gilbert <dgilbert@interlog.com>
Cc: Mike Miller <mike.miller@hp.com>
Cc: Eric Moore <Eric.Moore@lsi.com>
Cc: Darrick J. Wong <djwong@us.ibm.com>
Cc: Pete Zaitcev <zaitcev@redhat.com>
Cc: Boaz Harrosh <bharrosh@panasas.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/libsas/sas_expander.c | 6 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_host_smp.c | 38 | ||||
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_transport.c | 4 | ||||
-rw-r--r-- | drivers/scsi/scsi_lib.c | 24 | ||||
-rw-r--r-- | drivers/scsi/sg.c | 2 | ||||
-rw-r--r-- | drivers/scsi/st.c | 2 |
6 files changed, 36 insertions, 40 deletions
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 3da02e436788..6605ec905cc0 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c | |||
@@ -1936,12 +1936,8 @@ int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
1936 | bio_data(rsp->bio), rsp->data_len); | 1936 | bio_data(rsp->bio), rsp->data_len); |
1937 | if (ret > 0) { | 1937 | if (ret > 0) { |
1938 | /* positive number is the untransferred residual */ | 1938 | /* positive number is the untransferred residual */ |
1939 | rsp->data_len = ret; | 1939 | rsp->resid_len = ret; |
1940 | req->data_len = 0; | ||
1941 | ret = 0; | 1940 | ret = 0; |
1942 | } else if (ret == 0) { | ||
1943 | rsp->data_len = 0; | ||
1944 | req->data_len = 0; | ||
1945 | } | 1941 | } |
1946 | 1942 | ||
1947 | return ret; | 1943 | return ret; |
diff --git a/drivers/scsi/libsas/sas_host_smp.c b/drivers/scsi/libsas/sas_host_smp.c index d110a366c48a..89952edd0be3 100644 --- a/drivers/scsi/libsas/sas_host_smp.c +++ b/drivers/scsi/libsas/sas_host_smp.c | |||
@@ -134,7 +134,7 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req, | |||
134 | { | 134 | { |
135 | u8 *req_data = NULL, *resp_data = NULL, *buf; | 135 | u8 *req_data = NULL, *resp_data = NULL, *buf; |
136 | struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost); | 136 | struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost); |
137 | int error = -EINVAL, resp_data_len = rsp->data_len; | 137 | int error = -EINVAL; |
138 | 138 | ||
139 | /* eight is the minimum size for request and response frames */ | 139 | /* eight is the minimum size for request and response frames */ |
140 | if (req->data_len < 8 || rsp->data_len < 8) | 140 | if (req->data_len < 8 || rsp->data_len < 8) |
@@ -176,17 +176,20 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req, | |||
176 | resp_data[1] = req_data[1]; | 176 | resp_data[1] = req_data[1]; |
177 | resp_data[2] = SMP_RESP_FUNC_UNK; | 177 | resp_data[2] = SMP_RESP_FUNC_UNK; |
178 | 178 | ||
179 | req->resid_len = req->data_len; | ||
180 | rsp->resid_len = rsp->data_len; | ||
181 | |||
179 | switch (req_data[1]) { | 182 | switch (req_data[1]) { |
180 | case SMP_REPORT_GENERAL: | 183 | case SMP_REPORT_GENERAL: |
181 | req->data_len -= 8; | 184 | req->resid_len -= 8; |
182 | resp_data_len -= 32; | 185 | rsp->resid_len -= 32; |
183 | resp_data[2] = SMP_RESP_FUNC_ACC; | 186 | resp_data[2] = SMP_RESP_FUNC_ACC; |
184 | resp_data[9] = sas_ha->num_phys; | 187 | resp_data[9] = sas_ha->num_phys; |
185 | break; | 188 | break; |
186 | 189 | ||
187 | case SMP_REPORT_MANUF_INFO: | 190 | case SMP_REPORT_MANUF_INFO: |
188 | req->data_len -= 8; | 191 | req->resid_len -= 8; |
189 | resp_data_len -= 64; | 192 | rsp->resid_len -= 64; |
190 | resp_data[2] = SMP_RESP_FUNC_ACC; | 193 | resp_data[2] = SMP_RESP_FUNC_ACC; |
191 | memcpy(resp_data + 12, shost->hostt->name, | 194 | memcpy(resp_data + 12, shost->hostt->name, |
192 | SAS_EXPANDER_VENDOR_ID_LEN); | 195 | SAS_EXPANDER_VENDOR_ID_LEN); |
@@ -199,13 +202,13 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req, | |||
199 | break; | 202 | break; |
200 | 203 | ||
201 | case SMP_DISCOVER: | 204 | case SMP_DISCOVER: |
202 | req->data_len -= 16; | 205 | req->resid_len -= 16; |
203 | if ((int)req->data_len < 0) { | 206 | if ((int)req->resid_len < 0) { |
204 | req->data_len = 0; | 207 | req->resid_len = 0; |
205 | error = -EINVAL; | 208 | error = -EINVAL; |
206 | goto out; | 209 | goto out; |
207 | } | 210 | } |
208 | resp_data_len -= 56; | 211 | rsp->resid_len -= 56; |
209 | sas_host_smp_discover(sas_ha, resp_data, req_data[9]); | 212 | sas_host_smp_discover(sas_ha, resp_data, req_data[9]); |
210 | break; | 213 | break; |
211 | 214 | ||
@@ -215,13 +218,13 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req, | |||
215 | break; | 218 | break; |
216 | 219 | ||
217 | case SMP_REPORT_PHY_SATA: | 220 | case SMP_REPORT_PHY_SATA: |
218 | req->data_len -= 16; | 221 | req->resid_len -= 16; |
219 | if ((int)req->data_len < 0) { | 222 | if ((int)req->resid_len < 0) { |
220 | req->data_len = 0; | 223 | req->resid_len = 0; |
221 | error = -EINVAL; | 224 | error = -EINVAL; |
222 | goto out; | 225 | goto out; |
223 | } | 226 | } |
224 | resp_data_len -= 60; | 227 | rsp->resid_len -= 60; |
225 | sas_report_phy_sata(sas_ha, resp_data, req_data[9]); | 228 | sas_report_phy_sata(sas_ha, resp_data, req_data[9]); |
226 | break; | 229 | break; |
227 | 230 | ||
@@ -238,13 +241,13 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req, | |||
238 | break; | 241 | break; |
239 | 242 | ||
240 | case SMP_PHY_CONTROL: | 243 | case SMP_PHY_CONTROL: |
241 | req->data_len -= 44; | 244 | req->resid_len -= 44; |
242 | if ((int)req->data_len < 0) { | 245 | if ((int)req->resid_len < 0) { |
243 | req->data_len = 0; | 246 | req->resid_len = 0; |
244 | error = -EINVAL; | 247 | error = -EINVAL; |
245 | goto out; | 248 | goto out; |
246 | } | 249 | } |
247 | resp_data_len -= 8; | 250 | rsp->resid_len -= 8; |
248 | sas_phy_control(sas_ha, req_data[9], req_data[10], | 251 | sas_phy_control(sas_ha, req_data[9], req_data[10], |
249 | req_data[32] >> 4, req_data[33] >> 4, | 252 | req_data[32] >> 4, req_data[33] >> 4, |
250 | resp_data); | 253 | resp_data); |
@@ -265,7 +268,6 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req, | |||
265 | flush_kernel_dcache_page(bio_page(rsp->bio)); | 268 | flush_kernel_dcache_page(bio_page(rsp->bio)); |
266 | kunmap_atomic(buf - bio_offset(rsp->bio), KM_USER0); | 269 | kunmap_atomic(buf - bio_offset(rsp->bio), KM_USER0); |
267 | local_irq_enable(); | 270 | local_irq_enable(); |
268 | rsp->data_len = resp_data_len; | ||
269 | 271 | ||
270 | out: | 272 | out: |
271 | kfree(req_data); | 273 | kfree(req_data); |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c index e03dc0b1e1a0..53759c566bfe 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_transport.c +++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c | |||
@@ -1170,9 +1170,7 @@ transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
1170 | 1170 | ||
1171 | memcpy(req->sense, mpi_reply, sizeof(*mpi_reply)); | 1171 | memcpy(req->sense, mpi_reply, sizeof(*mpi_reply)); |
1172 | req->sense_len = sizeof(*mpi_reply); | 1172 | req->sense_len = sizeof(*mpi_reply); |
1173 | req->data_len = 0; | 1173 | rsp->resid_len = rsp->data_len - mpi_reply->ResponseDataLength; |
1174 | rsp->data_len -= mpi_reply->ResponseDataLength; | ||
1175 | |||
1176 | } else { | 1174 | } else { |
1177 | dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT | 1175 | dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT |
1178 | "%s - no reply\n", ioc->name, __func__)); | 1176 | "%s - no reply\n", ioc->name, __func__)); |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index aa9fc572e45f..7d49ef589f33 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -240,11 +240,11 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, | |||
240 | * is invalid. Prevent the garbage from being misinterpreted | 240 | * is invalid. Prevent the garbage from being misinterpreted |
241 | * and prevent security leaks by zeroing out the excess data. | 241 | * and prevent security leaks by zeroing out the excess data. |
242 | */ | 242 | */ |
243 | if (unlikely(req->data_len > 0 && req->data_len <= bufflen)) | 243 | if (unlikely(req->resid_len > 0 && req->resid_len <= bufflen)) |
244 | memset(buffer + (bufflen - req->data_len), 0, req->data_len); | 244 | memset(buffer + (bufflen - req->resid_len), 0, req->resid_len); |
245 | 245 | ||
246 | if (resid) | 246 | if (resid) |
247 | *resid = req->data_len; | 247 | *resid = req->resid_len; |
248 | ret = req->errors; | 248 | ret = req->errors; |
249 | out: | 249 | out: |
250 | blk_put_request(req); | 250 | blk_put_request(req); |
@@ -549,7 +549,7 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int error, | |||
549 | int leftover = (req->hard_nr_sectors << 9); | 549 | int leftover = (req->hard_nr_sectors << 9); |
550 | 550 | ||
551 | if (blk_pc_request(req)) | 551 | if (blk_pc_request(req)) |
552 | leftover = req->data_len; | 552 | leftover = req->resid_len; |
553 | 553 | ||
554 | /* kill remainder if no retrys */ | 554 | /* kill remainder if no retrys */ |
555 | if (error && scsi_noretry_cmd(cmd)) | 555 | if (error && scsi_noretry_cmd(cmd)) |
@@ -673,11 +673,11 @@ void scsi_release_buffers(struct scsi_cmnd *cmd) | |||
673 | EXPORT_SYMBOL(scsi_release_buffers); | 673 | EXPORT_SYMBOL(scsi_release_buffers); |
674 | 674 | ||
675 | /* | 675 | /* |
676 | * Bidi commands Must be complete as a whole, both sides at once. | 676 | * Bidi commands Must be complete as a whole, both sides at once. If |
677 | * If part of the bytes were written and lld returned | 677 | * part of the bytes were written and lld returned scsi_in()->resid |
678 | * scsi_in()->resid and/or scsi_out()->resid this information will be left | 678 | * and/or scsi_out()->resid this information will be left in |
679 | * in req->data_len and req->next_rq->data_len. The upper-layer driver can | 679 | * req->resid_len and req->next_rq->resid_len. The upper-layer driver |
680 | * decide what to do with this information. | 680 | * can decide what to do with this information. |
681 | */ | 681 | */ |
682 | static void scsi_end_bidi_request(struct scsi_cmnd *cmd) | 682 | static void scsi_end_bidi_request(struct scsi_cmnd *cmd) |
683 | { | 683 | { |
@@ -685,8 +685,8 @@ static void scsi_end_bidi_request(struct scsi_cmnd *cmd) | |||
685 | unsigned int dlen = req->data_len; | 685 | unsigned int dlen = req->data_len; |
686 | unsigned int next_dlen = req->next_rq->data_len; | 686 | unsigned int next_dlen = req->next_rq->data_len; |
687 | 687 | ||
688 | req->data_len = scsi_out(cmd)->resid; | 688 | req->resid_len = scsi_out(cmd)->resid; |
689 | req->next_rq->data_len = scsi_in(cmd)->resid; | 689 | req->next_rq->resid_len = scsi_in(cmd)->resid; |
690 | 690 | ||
691 | /* The req and req->next_rq have not been completed */ | 691 | /* The req and req->next_rq have not been completed */ |
692 | BUG_ON(blk_end_bidi_request(req, 0, dlen, next_dlen)); | 692 | BUG_ON(blk_end_bidi_request(req, 0, dlen, next_dlen)); |
@@ -778,7 +778,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) | |||
778 | scsi_end_bidi_request(cmd); | 778 | scsi_end_bidi_request(cmd); |
779 | return; | 779 | return; |
780 | } | 780 | } |
781 | req->data_len = scsi_get_resid(cmd); | 781 | req->resid_len = scsi_get_resid(cmd); |
782 | } | 782 | } |
783 | 783 | ||
784 | BUG_ON(blk_bidi_rq(req)); /* bidi not support for !blk_pc_request yet */ | 784 | BUG_ON(blk_bidi_rq(req)); /* bidi not support for !blk_pc_request yet */ |
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 82312df9b0bf..dec4c70677de 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
@@ -1260,7 +1260,7 @@ static void sg_rq_end_io(struct request *rq, int uptodate) | |||
1260 | 1260 | ||
1261 | sense = rq->sense; | 1261 | sense = rq->sense; |
1262 | result = rq->errors; | 1262 | result = rq->errors; |
1263 | resid = rq->data_len; | 1263 | resid = rq->resid_len; |
1264 | 1264 | ||
1265 | SCSI_LOG_TIMEOUT(4, printk("sg_cmd_done: %s, pack_id=%d, res=0x%x\n", | 1265 | SCSI_LOG_TIMEOUT(4, printk("sg_cmd_done: %s, pack_id=%d, res=0x%x\n", |
1266 | sdp->disk->disk_name, srp->header.pack_id, result)); | 1266 | sdp->disk->disk_name, srp->header.pack_id, result)); |
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index eb24efea8f14..8681b708344f 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c | |||
@@ -463,7 +463,7 @@ static void st_scsi_execute_end(struct request *req, int uptodate) | |||
463 | struct scsi_tape *STp = SRpnt->stp; | 463 | struct scsi_tape *STp = SRpnt->stp; |
464 | 464 | ||
465 | STp->buffer->cmdstat.midlevel_result = SRpnt->result = req->errors; | 465 | STp->buffer->cmdstat.midlevel_result = SRpnt->result = req->errors; |
466 | STp->buffer->cmdstat.residual = req->data_len; | 466 | STp->buffer->cmdstat.residual = req->resid_len; |
467 | 467 | ||
468 | if (SRpnt->waiting) | 468 | if (SRpnt->waiting) |
469 | complete(SRpnt->waiting); | 469 | complete(SRpnt->waiting); |