Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c3a4d78c authored by Tejun Heo's avatar Tejun Heo Committed by Jens Axboe
Browse files

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: default avatarTejun 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: default avatarJens Axboe <jens.axboe@oracle.com>
parent 9720aef2
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -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
+1 −1
Original line number Diff line number Diff line
@@ -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) {
+4 −9
Original line number Diff line number Diff line
@@ -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:
+2 −4
Original line number Diff line number Diff line
@@ -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) {
+1 −8
Original line number Diff line number Diff line
@@ -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;
	}

Loading