block: add rq->resid_len
authorTejun Heo <tj@kernel.org>
Thu, 7 May 2009 13:24:37 +0000 (22:24 +0900)
committerJens Axboe <jens.axboe@oracle.com>
Mon, 11 May 2009 07:50:53 +0000 (09:50 +0200)
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>
16 files changed:
block/bsg.c
block/scsi_ioctl.c
drivers/block/cciss.c
drivers/block/ub.c
drivers/ide/ide-atapi.c
drivers/ide/ide-cd.c
drivers/ide/ide-tape.c
drivers/message/fusion/mptsas.c
drivers/scsi/libsas/sas_expander.c
drivers/scsi/libsas/sas_host_smp.c
drivers/scsi/mpt2sas/mpt2sas_transport.c
drivers/scsi/scsi_lib.c
drivers/scsi/sg.c
drivers/scsi/st.c
fs/exofs/osd.c
include/linux/blkdev.h

index 206060e795da4324732835bf5012afca4ac7d43f..2d746e34f4c24c1a0c70e627af78955ef9681af9 100644 (file)
@@ -445,14 +445,14 @@ static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr,
        }
 
        if (rq->next_rq) {
-               hdr->dout_resid = rq->data_len;
-               hdr->din_resid = rq->next_rq->data_len;
+               hdr->dout_resid = rq->resid_len;
+               hdr->din_resid = rq->next_rq->resid_len;
                blk_rq_unmap_user(bidi_bio);
                blk_put_request(rq->next_rq);
        } else if (rq_data_dir(rq) == READ)
-               hdr->din_resid = rq->data_len;
+               hdr->din_resid = rq->resid_len;
        else
-               hdr->dout_resid = rq->data_len;
+               hdr->dout_resid = rq->resid_len;
 
        /*
         * If the request generated a negative error number, return it
index 58cf4560f742fefb84c46bd96bc7eb0c10aebb6f..a9670dd4b5de034cf2130f2fa0f552eda1bd80c5 100644 (file)
@@ -230,7 +230,7 @@ static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
        hdr->info = 0;
        if (hdr->masked_status || hdr->host_status || hdr->driver_status)
                hdr->info |= SG_INFO_CHECK;
-       hdr->resid = rq->data_len;
+       hdr->resid = rq->resid_len;
        hdr->sb_len_wr = 0;
 
        if (rq->sense_len && hdr->sbp) {
index 4d4d5e0d3fa64af15faf87a3a78c2a3b0396ef9c..f22d4932433fed0d0b90fb2c457079f1afbddda0 100644 (file)
@@ -1299,7 +1299,6 @@ static void cciss_softirq_done(struct request *rq)
 {
        CommandList_struct *cmd = rq->completion_data;
        ctlr_info_t *h = hba[cmd->ctlr];
-       unsigned int nr_bytes;
        unsigned long flags;
        u64bit temp64;
        int i, ddir;
@@ -1321,15 +1320,11 @@ static void cciss_softirq_done(struct request *rq)
        printk("Done with %p\n", rq);
 #endif                         /* CCISS_DEBUG */
 
-       /*
-        * Store the full size and set the residual count for pc requests
-        */
-       nr_bytes = blk_rq_bytes(rq);
+       /* set the residual count for pc requests */
        if (blk_pc_request(rq))
-               rq->data_len = cmd->err_info->ResidualCnt;
+               rq->resid_len = cmd->err_info->ResidualCnt;
 
-       if (blk_end_request(rq, (rq->errors == 0) ? 0 : -EIO, nr_bytes))
-               BUG();
+       blk_end_request_all(rq, (rq->errors == 0) ? 0 : -EIO);
 
        spin_lock_irqsave(&h->lock, flags);
        cmd_free(h, cmd, 1);
@@ -2691,7 +2686,7 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd,
                        printk(KERN_WARNING "cciss: cmd %p has"
                               " completed with data underrun "
                               "reported\n", cmd);
-                       cmd->rq->data_len = cmd->err_info->ResidualCnt;
+                       cmd->rq->resid_len = cmd->err_info->ResidualCnt;
                }
                break;
        case CMD_DATA_OVERRUN:
index 689cd27ac890afff8c39dc11bdac5e605e37816c..8c2cc71327e3f47f9d04ae16927fcd972110f44a 100644 (file)
@@ -783,10 +783,8 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 
        if (cmd->error == 0) {
                if (blk_pc_request(rq)) {
-                       if (cmd->act_len >= rq->data_len)
-                               rq->data_len = 0;
-                       else
-                               rq->data_len -= cmd->act_len;
+                       if (cmd->act_len < rq->data_len)
+                               rq->resid_len = rq->data_len - cmd->act_len;
                        scsi_status = 0;
                } else {
                        if (cmd->act_len != cmd->len) {
index afe5a4323879314b91198f5133fb19c230cea21f..e4a02a05fc8192cf23e323c2eba1f23004ae5d24 100644 (file)
@@ -367,7 +367,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
        /* No more interrupts */
        if ((stat & ATA_DRQ) == 0) {
                int uptodate, error;
-               unsigned int done;
 
                debug_log("Packet command completed, %d bytes transferred\n",
                          pc->xferred);
@@ -406,12 +405,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
                if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & ATA_DSC) == 0)
                        dsc = 1;
 
-               /*
-                * ->pc_callback() might change rq->data_len for
-                * residual count, cache total length.
-                */
-               done = blk_rq_bytes(rq);
-
                /* Command finished - Call the callback function */
                uptodate = drive->pc_callback(drive, dsc);
 
@@ -431,7 +424,7 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
                        error = uptodate ? 0 : -EIO;
                }
 
-               ide_complete_rq(drive, error, done);
+               ide_complete_rq(drive, error, blk_rq_bytes(rq));
                return ide_stopped;
        }
 
index 673628790f1088c3e70d6e2eb131f0cd730fcdf3..8bbe222c5e42357bc70e842905718fae638bd9fe 100644 (file)
@@ -519,7 +519,7 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,
                error = blk_execute_rq(drive->queue, info->disk, rq, 0);
 
                if (buffer)
-                       *bufflen = rq->data_len;
+                       *bufflen = rq->resid_len;
 
                flags = rq->cmd_flags;
                blk_put_request(rq);
@@ -707,11 +707,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
 
 out_end:
        if (blk_pc_request(rq) && rc == 0) {
-               unsigned int dlen = rq->data_len;
-
-               rq->data_len = 0;
-
-               if (blk_end_request(rq, 0, dlen))
+               if (blk_end_request(rq, 0, rq->data_len))
                        BUG();
 
                hwif->rq = NULL;
@@ -740,9 +736,10 @@ out_end:
                        nsectors = 1;
 
                if (blk_fs_request(rq) == 0) {
-                       rq->data_len -= (cmd->nbytes - cmd->nleft);
+                       rq->resid_len = rq->data_len -
+                               (cmd->nbytes - cmd->nleft);
                        if (uptodate == 0 && (cmd->tf_flags & IDE_TFLAG_WRITE))
-                               rq->data_len += cmd->last_xfer_len;
+                               rq->resid_len += cmd->last_xfer_len;
                }
 
                ide_complete_rq(drive, uptodate ? 0 : -EIO, nsectors << 9);
index 7149224d1fe98a5046f626c22e2e8403b3096ec1..65c5b705883aba80eb20d68d3a89c1f1cb98261e 100644 (file)
@@ -380,7 +380,7 @@ static int ide_tape_callback(ide_drive_t *drive, int dsc)
                }
 
                tape->first_frame += blocks;
-               rq->data_len -= blocks * tape->blk_size;
+               rq->resid_len = rq->data_len - blocks * tape->blk_size;
 
                if (pc->error) {
                        uptodate = 0;
@@ -903,7 +903,7 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int size)
        blk_execute_rq(drive->queue, tape->disk, rq, 0);
 
        /* calculate the number of transferred bytes and update buffer state */
-       size -= rq->data_len;
+       size -= rq->resid_len;
        tape->cur = tape->buf;
        if (cmd == REQ_IDETAPE_READ)
                tape->valid = size;
index a9019f081b971b888464166c407a4c8aabb9da30..5d5f34715de45520d7862f3f634e079858e2db99 100644 (file)
@@ -1357,8 +1357,7 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
                smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
                memcpy(req->sense, smprep, sizeof(*smprep));
                req->sense_len = sizeof(*smprep);
-               req->data_len = 0;
-               rsp->data_len -= smprep->ResponseDataLength;
+               rsp->resid_len = rsp->data_len - smprep->ResponseDataLength;
        } else {
                printk(MYIOC_s_ERR_FMT "%s: smp passthru reply failed to be returned\n",
                    ioc->name, __func__);
index 3da02e4367884b4f8fcc1015811b55b0bf88a968..6605ec905cc03e78bd87a1aefc30cbbe355b508b 100644 (file)
@@ -1936,12 +1936,8 @@ int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
                               bio_data(rsp->bio), rsp->data_len);
        if (ret > 0) {
                /* positive number is the untransferred residual */
-               rsp->data_len = ret;
-               req->data_len = 0;
+               rsp->resid_len = ret;
                ret = 0;
-       } else if (ret == 0) {
-               rsp->data_len = 0;
-               req->data_len = 0;
        }
 
        return ret;
index d110a366c48a13f7e8372ac81c1a15de05c40efa..89952edd0be37477dc4dda13334079511440cd8a 100644 (file)
@@ -134,7 +134,7 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
 {
        u8 *req_data = NULL, *resp_data = NULL, *buf;
        struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
-       int error = -EINVAL, resp_data_len = rsp->data_len;
+       int error = -EINVAL;
 
        /* eight is the minimum size for request and response frames */
        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,
        resp_data[1] = req_data[1];
        resp_data[2] = SMP_RESP_FUNC_UNK;
 
+       req->resid_len = req->data_len;
+       rsp->resid_len = rsp->data_len;
+
        switch (req_data[1]) {
        case SMP_REPORT_GENERAL:
-               req->data_len -= 8;
-               resp_data_len -= 32;
+               req->resid_len -= 8;
+               rsp->resid_len -= 32;
                resp_data[2] = SMP_RESP_FUNC_ACC;
                resp_data[9] = sas_ha->num_phys;
                break;
 
        case SMP_REPORT_MANUF_INFO:
-               req->data_len -= 8;
-               resp_data_len -= 64;
+               req->resid_len -= 8;
+               rsp->resid_len -= 64;
                resp_data[2] = SMP_RESP_FUNC_ACC;
                memcpy(resp_data + 12, shost->hostt->name,
                       SAS_EXPANDER_VENDOR_ID_LEN);
@@ -199,13 +202,13 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
                break;
 
        case SMP_DISCOVER:
-               req->data_len -= 16;
-               if ((int)req->data_len < 0) {
-                       req->data_len = 0;
+               req->resid_len -= 16;
+               if ((int)req->resid_len < 0) {
+                       req->resid_len = 0;
                        error = -EINVAL;
                        goto out;
                }
-               resp_data_len -= 56;
+               rsp->resid_len -= 56;
                sas_host_smp_discover(sas_ha, resp_data, req_data[9]);
                break;
 
@@ -215,13 +218,13 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
                break;
 
        case SMP_REPORT_PHY_SATA:
-               req->data_len -= 16;
-               if ((int)req->data_len < 0) {
-                       req->data_len = 0;
+               req->resid_len -= 16;
+               if ((int)req->resid_len < 0) {
+                       req->resid_len = 0;
                        error = -EINVAL;
                        goto out;
                }
-               resp_data_len -= 60;
+               rsp->resid_len -= 60;
                sas_report_phy_sata(sas_ha, resp_data, req_data[9]);
                break;
 
@@ -238,13 +241,13 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
                break;
 
        case SMP_PHY_CONTROL:
-               req->data_len -= 44;
-               if ((int)req->data_len < 0) {
-                       req->data_len = 0;
+               req->resid_len -= 44;
+               if ((int)req->resid_len < 0) {
+                       req->resid_len = 0;
                        error = -EINVAL;
                        goto out;
                }
-               resp_data_len -= 8;
+               rsp->resid_len -= 8;
                sas_phy_control(sas_ha, req_data[9], req_data[10],
                                req_data[32] >> 4, req_data[33] >> 4,
                                resp_data);
@@ -265,7 +268,6 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
        flush_kernel_dcache_page(bio_page(rsp->bio));
        kunmap_atomic(buf - bio_offset(rsp->bio), KM_USER0);
        local_irq_enable();
-       rsp->data_len = resp_data_len;
 
  out:
        kfree(req_data);
index e03dc0b1e1a0f906d1393fbc82a0157f9e2ee49e..53759c566bfed73e183201f9c5b0489a1d5a5af1 100644 (file)
@@ -1170,9 +1170,7 @@ transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
 
                memcpy(req->sense, mpi_reply, sizeof(*mpi_reply));
                req->sense_len = sizeof(*mpi_reply);
-               req->data_len = 0;
-               rsp->data_len -= mpi_reply->ResponseDataLength;
-
+               rsp->resid_len = rsp->data_len - mpi_reply->ResponseDataLength;
        } else {
                dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
                    "%s - no reply\n", ioc->name, __func__));
index aa9fc572e45fa4848aa93d2fb0ebfc725193cace..7d49ef589f3367de90f4cdaa50646200bb312d4d 100644 (file)
@@ -240,11 +240,11 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
         * is invalid.  Prevent the garbage from being misinterpreted
         * and prevent security leaks by zeroing out the excess data.
         */
-       if (unlikely(req->data_len > 0 && req->data_len <= bufflen))
-               memset(buffer + (bufflen - req->data_len), 0, req->data_len);
+       if (unlikely(req->resid_len > 0 && req->resid_len <= bufflen))
+               memset(buffer + (bufflen - req->resid_len), 0, req->resid_len);
 
        if (resid)
-               *resid = req->data_len;
+               *resid = req->resid_len;
        ret = req->errors;
  out:
        blk_put_request(req);
@@ -549,7 +549,7 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int error,
                int leftover = (req->hard_nr_sectors << 9);
 
                if (blk_pc_request(req))
-                       leftover = req->data_len;
+                       leftover = req->resid_len;
 
                /* kill remainder if no retrys */
                if (error && scsi_noretry_cmd(cmd))
@@ -673,11 +673,11 @@ void scsi_release_buffers(struct scsi_cmnd *cmd)
 EXPORT_SYMBOL(scsi_release_buffers);
 
 /*
- * Bidi commands Must be complete as a whole, both sides at once.
- * If part of the bytes were written and lld returned
- * scsi_in()->resid and/or scsi_out()->resid this information will be left
- * in req->data_len and req->next_rq->data_len. The upper-layer driver can
- * decide what to do with this information.
+ * Bidi commands Must be complete as a whole, both sides at once.  If
+ * part of the bytes were written and lld returned scsi_in()->resid
+ * and/or scsi_out()->resid this information will be left in
+ * req->resid_len and req->next_rq->resid_len. The upper-layer driver
+ * can decide what to do with this information.
  */
 static void scsi_end_bidi_request(struct scsi_cmnd *cmd)
 {
@@ -685,8 +685,8 @@ static void scsi_end_bidi_request(struct scsi_cmnd *cmd)
        unsigned int dlen = req->data_len;
        unsigned int next_dlen = req->next_rq->data_len;
 
-       req->data_len = scsi_out(cmd)->resid;
-       req->next_rq->data_len = scsi_in(cmd)->resid;
+       req->resid_len = scsi_out(cmd)->resid;
+       req->next_rq->resid_len = scsi_in(cmd)->resid;
 
        /* The req and req->next_rq have not been completed */
        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)
                        scsi_end_bidi_request(cmd);
                        return;
                }
-               req->data_len = scsi_get_resid(cmd);
+               req->resid_len = scsi_get_resid(cmd);
        }
 
        BUG_ON(blk_bidi_rq(req)); /* bidi not support for !blk_pc_request yet */
index 82312df9b0bfb9fba684eb9f4e7922a19b645b5d..dec4c70677dee667be8f0481f7455327662b07ab 100644 (file)
@@ -1260,7 +1260,7 @@ static void sg_rq_end_io(struct request *rq, int uptodate)
 
        sense = rq->sense;
        result = rq->errors;
-       resid = rq->data_len;
+       resid = rq->resid_len;
 
        SCSI_LOG_TIMEOUT(4, printk("sg_cmd_done: %s, pack_id=%d, res=0x%x\n",
                sdp->disk->disk_name, srp->header.pack_id, result));
index eb24efea8f1450ad9dabdf7a08aa3ada2b0e675d..8681b708344f0130265eba1e3a34456fd1258abe 100644 (file)
@@ -463,7 +463,7 @@ static void st_scsi_execute_end(struct request *req, int uptodate)
        struct scsi_tape *STp = SRpnt->stp;
 
        STp->buffer->cmdstat.midlevel_result = SRpnt->result = req->errors;
-       STp->buffer->cmdstat.residual = req->data_len;
+       STp->buffer->cmdstat.residual = req->resid_len;
 
        if (SRpnt->waiting)
                complete(SRpnt->waiting);
index b249ae97fb15bfb24e1835a41d351110c7ae3ef9..06ca92672eb5d6118ee644074019a650a96125f3 100644 (file)
@@ -50,10 +50,10 @@ int exofs_check_ok_resid(struct osd_request *or, u64 *in_resid, u64 *out_resid)
 
        /* FIXME: should be include in osd_sense_info */
        if (in_resid)
-               *in_resid = or->in.req ? or->in.req->data_len : 0;
+               *in_resid = or->in.req ? or->in.req->resid_len : 0;
 
        if (out_resid)
-               *out_resid = or->out.req ? or->out.req->data_len : 0;
+               *out_resid = or->out.req ? or->out.req->resid_len : 0;
 
        return ret;
 }
index 3a5b1bd6582c3ec69ad157315b259f9b032a59f6..6a967cad89fa6299e26682b16199e7dddb5d83a8 100644 (file)
@@ -229,6 +229,7 @@ struct request {
        unsigned int data_len;
        unsigned int extra_len; /* length of alignment and padding */
        unsigned int sense_len;
+       unsigned int resid_len; /* residual count */
        void *sense;
 
        unsigned long deadline;