aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2009-05-07 09:24:37 -0400
committerJens Axboe <jens.axboe@oracle.com>2009-05-11 03:50:53 -0400
commitc3a4d78c580de4edc9ef0f7c59812fb02ceb037f (patch)
tree916ca44287100707508678e2cc0eff0c43b9ca39 /drivers/block
parent9720aef2539c10e3a872e9a92beec225030d99db (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/block')
-rw-r--r--drivers/block/cciss.c13
-rw-r--r--drivers/block/ub.c6
2 files changed, 6 insertions, 13 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 4d4d5e0d3fa6..f22d4932433f 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1299,7 +1299,6 @@ static void cciss_softirq_done(struct request *rq)
1299{ 1299{
1300 CommandList_struct *cmd = rq->completion_data; 1300 CommandList_struct *cmd = rq->completion_data;
1301 ctlr_info_t *h = hba[cmd->ctlr]; 1301 ctlr_info_t *h = hba[cmd->ctlr];
1302 unsigned int nr_bytes;
1303 unsigned long flags; 1302 unsigned long flags;
1304 u64bit temp64; 1303 u64bit temp64;
1305 int i, ddir; 1304 int i, ddir;
@@ -1321,15 +1320,11 @@ static void cciss_softirq_done(struct request *rq)
1321 printk("Done with %p\n", rq); 1320 printk("Done with %p\n", rq);
1322#endif /* CCISS_DEBUG */ 1321#endif /* CCISS_DEBUG */
1323 1322
1324 /* 1323 /* set the residual count for pc requests */
1325 * Store the full size and set the residual count for pc requests
1326 */
1327 nr_bytes = blk_rq_bytes(rq);
1328 if (blk_pc_request(rq)) 1324 if (blk_pc_request(rq))
1329 rq->data_len = cmd->err_info->ResidualCnt; 1325 rq->resid_len = cmd->err_info->ResidualCnt;
1330 1326
1331 if (blk_end_request(rq, (rq->errors == 0) ? 0 : -EIO, nr_bytes)) 1327 blk_end_request_all(rq, (rq->errors == 0) ? 0 : -EIO);
1332 BUG();
1333 1328
1334 spin_lock_irqsave(&h->lock, flags); 1329 spin_lock_irqsave(&h->lock, flags);
1335 cmd_free(h, cmd, 1); 1330 cmd_free(h, cmd, 1);
@@ -2691,7 +2686,7 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd,
2691 printk(KERN_WARNING "cciss: cmd %p has" 2686 printk(KERN_WARNING "cciss: cmd %p has"
2692 " completed with data underrun " 2687 " completed with data underrun "
2693 "reported\n", cmd); 2688 "reported\n", cmd);
2694 cmd->rq->data_len = cmd->err_info->ResidualCnt; 2689 cmd->rq->resid_len = cmd->err_info->ResidualCnt;
2695 } 2690 }
2696 break; 2691 break;
2697 case CMD_DATA_OVERRUN: 2692 case CMD_DATA_OVERRUN:
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index 689cd27ac890..8c2cc71327e3 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -783,10 +783,8 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
783 783
784 if (cmd->error == 0) { 784 if (cmd->error == 0) {
785 if (blk_pc_request(rq)) { 785 if (blk_pc_request(rq)) {
786 if (cmd->act_len >= rq->data_len) 786 if (cmd->act_len < rq->data_len)
787 rq->data_len = 0; 787 rq->resid_len = rq->data_len - cmd->act_len;
788 else
789 rq->data_len -= cmd->act_len;
790 scsi_status = 0; 788 scsi_status = 0;
791 } else { 789 } else {
792 if (cmd->act_len != cmd->len) { 790 if (cmd->act_len != cmd->len) {