aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-01-29 08:51:32 +1100
committerLinus Torvalds <torvalds@linux-foundation.org>2008-01-29 08:51:32 +1100
commitf0f0052069989b80d2a3e50c9cd2f2a650bc1aea (patch)
tree40ff39bc341aed8318a54d1bd61a381f41844f71
parent68fbda7de07e56eb90dd6e58a162527411b388b1 (diff)
parenta65b58663d983e588aed8d1bfc75edaac2527fa7 (diff)
Merge branch 'blk-end-request' of git://git.kernel.dk/linux-2.6-block
* 'blk-end-request' of git://git.kernel.dk/linux-2.6-block: (30 commits) blk_end_request: changing xsysace (take 4) blk_end_request: changing ub (take 4) blk_end_request: cleanup of request completion (take 4) blk_end_request: cleanup 'uptodate' related code (take 4) blk_end_request: remove/unexport end_that_request_* (take 4) blk_end_request: changing scsi (take 4) blk_end_request: add bidi completion interface (take 4) blk_end_request: changing ide-cd (take 4) blk_end_request: add callback feature (take 4) blk_end_request: changing ide normal caller (take 4) blk_end_request: changing cpqarray (take 4) blk_end_request: changing cciss (take 4) blk_end_request: changing ide-scsi (take 4) blk_end_request: changing s390 (take 4) blk_end_request: changing mmc (take 4) blk_end_request: changing i2o_block (take 4) blk_end_request: changing viocd (take 4) blk_end_request: changing xen-blkfront (take 4) blk_end_request: changing viodasd (take 4) blk_end_request: changing sx8 (take 4) ...
-rw-r--r--arch/arm/plat-omap/mailbox.c16
-rw-r--r--arch/um/drivers/ubd_kern.c16
-rw-r--r--block/ll_rw_blk.c298
-rw-r--r--drivers/block/DAC960.c11
-rw-r--r--drivers/block/cciss.c25
-rw-r--r--drivers/block/cpqarray.c36
-rw-r--r--drivers/block/floppy.c16
-rw-r--r--drivers/block/nbd.c8
-rw-r--r--drivers/block/ps3disk.c12
-rw-r--r--drivers/block/sunvdc.c11
-rw-r--r--drivers/block/sx8.c58
-rw-r--r--drivers/block/ub.c10
-rw-r--r--drivers/block/viodasd.c15
-rw-r--r--drivers/block/xen-blkfront.c10
-rw-r--r--drivers/block/xsysace.c5
-rw-r--r--drivers/cdrom/viocd.c15
-rw-r--r--drivers/ide/ide-cd.c55
-rw-r--r--drivers/ide/ide-io.c25
-rw-r--r--drivers/message/i2o/i2o_block.c20
-rw-r--r--drivers/mmc/card/block.c24
-rw-r--r--drivers/mmc/card/queue.c4
-rw-r--r--drivers/s390/block/dasd.c17
-rw-r--r--drivers/s390/char/tape_block.c13
-rw-r--r--drivers/scsi/ide-scsi.c8
-rw-r--r--drivers/scsi/scsi_lib.c31
-rw-r--r--include/linux/blkdev.h31
26 files changed, 416 insertions, 374 deletions
diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c
index 45a77df668f..1945ddfec18 100644
--- a/arch/arm/plat-omap/mailbox.c
+++ b/arch/arm/plat-omap/mailbox.c
@@ -116,8 +116,8 @@ static void mbox_tx_work(struct work_struct *work)
}
spin_lock(q->queue_lock);
- blkdev_dequeue_request(rq);
- end_that_request_last(rq, 0);
+ if (__blk_end_request(rq, 0, 0))
+ BUG();
spin_unlock(q->queue_lock);
}
}
@@ -149,10 +149,8 @@ static void mbox_rx_work(struct work_struct *work)
msg = (mbox_msg_t) rq->data;
- spin_lock_irqsave(q->queue_lock, flags);
- blkdev_dequeue_request(rq);
- end_that_request_last(rq, 0);
- spin_unlock_irqrestore(q->queue_lock, flags);
+ if (blk_end_request(rq, 0, 0))
+ BUG();
mbox->rxq->callback((void *)msg);
}
@@ -263,10 +261,8 @@ omap_mbox_read(struct device *dev, struct device_attribute *attr, char *buf)
*p = (mbox_msg_t) rq->data;
- spin_lock_irqsave(q->queue_lock, flags);
- blkdev_dequeue_request(rq);
- end_that_request_last(rq, 0);
- spin_unlock_irqrestore(q->queue_lock, flags);
+ if (blk_end_request(rq, 0, 0))
+ BUG();
if (unlikely(mbox_seq_test(mbox, *p))) {
pr_info("mbox: Illegal seq bit!(%08x) ignored\n", *p);
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index b1a77b11f08..99f9f9605e9 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -475,17 +475,9 @@ static void do_ubd_request(struct request_queue * q);
/* Only changed by ubd_init, which is an initcall. */
int thread_fd = -1;
-static void ubd_end_request(struct request *req, int bytes, int uptodate)
+static void ubd_end_request(struct request *req, int bytes, int error)
{
- if (!end_that_request_first(req, uptodate, bytes >> 9)) {
- struct ubd *dev = req->rq_disk->private_data;
- unsigned long flags;
-
- add_disk_randomness(req->rq_disk);
- spin_lock_irqsave(&dev->lock, flags);
- end_that_request_last(req, uptodate);
- spin_unlock_irqrestore(&dev->lock, flags);
- }
+ blk_end_request(req, error, bytes);
}
/* Callable only from interrupt context - otherwise you need to do
@@ -493,10 +485,10 @@ static void ubd_end_request(struct request *req, int bytes, int uptodate)
static inline void ubd_finish(struct request *req, int bytes)
{
if(bytes < 0){
- ubd_end_request(req, 0, 0);
+ ubd_end_request(req, 0, -EIO);
return;
}
- ubd_end_request(req, bytes, 1);
+ ubd_end_request(req, bytes, 0);
}
static LIST_HEAD(restart);
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index b901db63f6a..c16fdfed8c6 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -347,7 +347,6 @@ unsigned blk_ordered_req_seq(struct request *rq)
void blk_ordered_complete_seq(struct request_queue *q, unsigned seq, int error)
{
struct request *rq;
- int uptodate;
if (error && !q->orderr)
q->orderr = error;
@@ -361,15 +360,11 @@ void blk_ordered_complete_seq(struct request_queue *q, unsigned seq, int error)
/*
* Okay, sequence complete.
*/
- uptodate = 1;
- if (q->orderr)
- uptodate = q->orderr;
-
q->ordseq = 0;
rq = q->orig_bar_rq;
- end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
- end_that_request_last(rq, uptodate);
+ if (__blk_end_request(rq, q->orderr, blk_rq_bytes(rq)))
+ BUG();
}
static void pre_flush_end_io(struct request *rq, int error)
@@ -486,9 +481,9 @@ int blk_do_ordered(struct request_queue *q, struct request **rqp)
* ORDERED_NONE while this request is on it.
*/
blkdev_dequeue_request(rq);
- end_that_request_first(rq, -EOPNOTSUPP,
- rq->hard_nr_sectors);
- end_that_request_last(rq, -EOPNOTSUPP);
+ if (__blk_end_request(rq, -EOPNOTSUPP,
+ blk_rq_bytes(rq)))
+ BUG();
*rqp = NULL;
return 0;
}
@@ -3437,29 +3432,36 @@ static void blk_recalc_rq_sectors(struct request *rq, int nsect)
}
}
-static int __end_that_request_first(struct request *req, int uptodate,
+/**
+ * __end_that_request_first - end I/O on a request
+ * @req: the request being processed
+ * @error: 0 for success, < 0 for error
+ * @nr_bytes: number of bytes to complete
+ *
+ * Description:
+ * Ends I/O on a number of bytes attached to @req, and sets it up
+ * for the next range of segments (if any) in the cluster.
+ *
+ * Return:
+ * 0 - we are done with this request, call end_that_request_last()
+ * 1 - still buffers pending for this request
+ **/
+static int __end_that_request_first(struct request *req, int error,
int nr_bytes)
{
- int total_bytes, bio_nbytes, error, next_idx = 0;
+ int total_bytes, bio_nbytes, next_idx = 0;
struct bio *bio;
blk_add_trace_rq(req->q, req, BLK_TA_COMPLETE);
/*
- * extend uptodate bool to allow < 0 value to be direct io error
- */
- error = 0;
- if (end_io_error(uptodate))
- error = !uptodate ? -EIO : uptodate;
-
- /*
* for a REQ_BLOCK_PC request, we want to carry any eventual
* sense key with us all the way through
*/
if (!blk_pc_request(req))
req->errors = 0;
- if (!uptodate) {
+ if (error) {
if (blk_fs_request(req) && !(req->cmd_flags & REQ_QUIET))
printk("end_request: I/O error, dev %s, sector %llu\n",
req->rq_disk ? req->rq_disk->disk_name : "?",
@@ -3553,49 +3555,6 @@ static int __end_that_request_first(struct request *req, int uptodate,
return 1;
}
-/**
- * end_that_request_first - end I/O on a request
- * @req: the request being processed
- * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error
- * @nr_sectors: number of sectors to end I/O on
- *
- * Description:
- * Ends I/O on a number of sectors attached to @req, and sets it up
- * for the next range of segments (if any) in the cluster.
- *
- * Return:
- * 0 - we are done with this request, call end_that_request_last()
- * 1 - still buffers pending for this request
- **/
-int end_that_request_first(struct request *req, int uptodate, int nr_sectors)
-{
- return __end_that_request_first(req, uptodate, nr_sectors << 9);
-}
-
-EXPORT_SYMBOL(end_that_request_first);
-
-/**
- * end_that_request_chunk - end I/O on a request
- * @req: the request being processed
- * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error
- * @nr_bytes: number of bytes to complete
- *
- * Description:
- * Ends I/O on a number of bytes attached to @req, and sets it up
- * for the next range of segments (if any). Like end_that_request_first(),
- * but deals with bytes instead of sectors.
- *
- * Return:
- * 0 - we are done with this request, call end_that_request_last()
- * 1 - still buffers pending for this request
- **/
-int end_that_request_chunk(struct request *req, int uptodate, int nr_bytes)
-{
- return __end_that_request_first(req, uptodate, nr_bytes);
-}
-
-EXPORT_SYMBOL(end_that_request_chunk);
-
/*
* splice the completion data to a local structure and hand off to
* process_completion_queue() to complete the requests
@@ -3675,17 +3634,15 @@ EXPORT_SYMBOL(blk_complete_request);
/*
* queue lock must be held
*/
-void end_that_request_last(struct request *req, int uptodate)
+static void end_that_request_last(struct request *req, int error)
{
struct gendisk *disk = req->rq_disk;
- int error;
- /*
- * extend uptodate bool to allow < 0 value to be direct io error
- */
- error = 0;
- if (end_io_error(uptodate))
- error = !uptodate ? -EIO : uptodate;
+ if (blk_rq_tagged(req))
+ blk_queue_end_tag(req->q, req);
+
+ if (blk_queued_rq(req))
+ blkdev_dequeue_request(req);
if (unlikely(laptop_mode) && blk_fs_request(req))
laptop_io_completion();
@@ -3704,32 +3661,54 @@ void end_that_request_last(struct request *req, int uptodate)
disk_round_stats(disk);
disk->in_flight--;
}
+
if (req->end_io)
req->end_io(req, error);
- else
+ else {
+ if (blk_bidi_rq(req))
+ __blk_put_request(req->next_rq->q, req->next_rq);
+
__blk_put_request(req->q, req);
+ }
}
-EXPORT_SYMBOL(end_that_request_last);
-
static inline void __end_request(struct request *rq, int uptodate,
- unsigned int nr_bytes, int dequeue)
+ unsigned int nr_bytes)
{
- if (!end_that_request_chunk(rq, uptodate, nr_bytes)) {
- if (dequeue)
- blkdev_dequeue_request(rq);
- add_disk_randomness(rq->rq_disk);
- end_that_request_last(rq, uptodate);
- }
+ int error = 0;
+
+ if (uptodate <= 0)
+ error = uptodate ? uptodate : -EIO;
+
+ __blk_end_request(rq, error, nr_bytes);
}
-static unsigned int rq_byte_size(struct request *rq)
+/**
+ * blk_rq_bytes - Returns bytes left to complete in the entire request
+ **/
+unsigned int blk_rq_bytes(struct request *rq)
{
if (blk_fs_request(rq))
return rq->hard_nr_sectors << 9;
return rq->data_len;
}
+EXPORT_SYMBOL_GPL(blk_rq_bytes);
+
+/**
+ * blk_rq_cur_bytes - Returns bytes left to complete in the current segment
+ **/
+unsigned int blk_rq_cur_bytes(struct request *rq)
+{
+ if (blk_fs_request(rq))
+ return rq->current_nr_sectors << 9;
+
+ if (rq->bio)
+ return rq->bio->bi_size;
+
+ return rq->data_len;
+}
+EXPORT_SYMBOL_GPL(blk_rq_cur_bytes);
/**
* end_queued_request - end all I/O on a queued request
@@ -3744,7 +3723,7 @@ static unsigned int rq_byte_size(struct request *rq)
**/
void end_queued_request(struct request *rq, int uptodate)
{
- __end_request(rq, uptodate, rq_byte_size(rq), 1);
+ __end_request(rq, uptodate, blk_rq_bytes(rq));
}
EXPORT_SYMBOL(end_queued_request);
@@ -3761,7 +3740,7 @@ EXPORT_SYMBOL(end_queued_request);
**/
void end_dequeued_request(struct request *rq, int uptodate)
{
- __end_request(rq, uptodate, rq_byte_size(rq), 0);
+ __end_request(rq, uptodate, blk_rq_bytes(rq));
}
EXPORT_SYMBOL(end_dequeued_request);
@@ -3787,10 +3766,159 @@ EXPORT_SYMBOL(end_dequeued_request);
**/
void end_request(struct request *req, int uptodate)
{
- __end_request(req, uptodate, req->hard_cur_sectors << 9, 1);
+ __end_request(req, uptodate, req->hard_cur_sectors << 9);
}
EXPORT_SYMBOL(end_request);
+/**
+ * blk_end_io - Generic end_io function to complete a request.
+ * @rq: the request being processed
+ * @error: 0 for success, < 0 for error
+ * @nr_bytes: number of bytes to complete @rq
+ * @bidi_bytes: number of bytes to complete @rq->next_rq
+ * @drv_callback: function called between completion of bios in the request
+ * and completion of the request.
+ * If the callback returns non 0, this helper returns without
+ * completion of the request.
+ *
+ * Description:
+ * Ends I/O on a number of bytes attached to @rq and @rq->next_rq.
+ * If @rq has leftover, sets it up for the next range of segments.
+ *
+ * Return:
+ * 0 - we are done with this request
+ * 1 - this request is not freed yet, it still has pending buffers.
+ **/
+static int blk_end_io(struct request *rq, int error, int nr_bytes,
+ int bidi_bytes, int (drv_callback)(struct request *))
+{
+ struct request_queue *q = rq->q;
+ unsigned long flags = 0UL;
+
+ if (blk_fs_request(rq) || blk_pc_request(rq)) {
+ if (__end_that_request_first(rq, error, nr_bytes))
+ return 1;
+
+ /* Bidi request must be completed as a whole */
+ if (blk_bidi_rq(rq) &&
+ __end_that_request_first(rq->next_rq, error, bidi_bytes))
+ return 1;
+ }
+
+ /* Special feature for tricky drivers */
+ if (drv_callback && drv_callback(rq))
+ return 1;
+
+ add_disk_randomness(rq->rq_disk);
+
+ spin_lock_irqsave(q->queue_lock, flags);
+ end_that_request_last(rq, error);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
+ return 0;
+}
+
+/**
+ * blk_end_request - Helper function for drivers to complete the request.
+ * @rq: the request being processed
+ * @error: 0 for success, < 0 for error
+ * @nr_bytes: number of bytes to complete
+ *
+ * Description:
+ * Ends I/O on a number of bytes attached to @rq.
+ * If @rq has leftover, sets it up for the next range of segments.
+ *
+ * Return:
+ * 0 - we are done with this request
+ * 1 - still buffers pending for this request
+ **/
+int blk_end_request(struct request *rq, int error, int nr_bytes)
+{
+ return blk_end_io(rq, error, nr_bytes, 0, NULL);
+}
+EXPORT_SYMBOL_GPL(blk_end_request);
+
+/**
+ * __blk_end_request - Helper function for drivers to complete the request.
+ * @rq: the request being processed
+ * @error: 0 for success, < 0 for error
+ * @nr_bytes: number of bytes to complete
+ *
+ * Description:
+ * Must be called with queue lock held unlike blk_end_request().
+ *
+ * Return:
+ * 0 - we are done with this request
+ * 1 - still buffers pending for this request
+ **/
+int __blk_end_request(struct request *rq, int error, int nr_bytes)
+{
+ if (blk_fs_request(rq) || blk_pc_request(rq)) {
+ if (__end_that_request_first(rq, error, nr_bytes))
+ return 1;
+ }
+
+ add_disk_randomness(rq->rq_disk);
+
+ end_that_request_last(rq, error);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(__blk_end_request);
+
+/**
+ * blk_end_bidi_request - Helper function for drivers to complete bidi request.
+ * @rq: the bidi request being processed
+ * @error: 0 for success, < 0 for error
+ * @nr_bytes: number of bytes to complete @rq
+ * @bidi_bytes: number of bytes to complete @rq->next_rq
+ *
+ * Description:
+ * Ends I/O on a number of bytes attached to @rq and @rq->next_rq.
+ *
+ * Return:
+ * 0 - we are done with this request
+ * 1 - still buffers pending for this request
+ **/
+int blk_end_bidi_request(struct request *rq, int error, int nr_bytes,
+ int bidi_bytes)
+{
+ return blk_end_io(rq, error, nr_bytes, bidi_bytes, NULL);
+}
+EXPORT_SYMBOL_GPL(blk_end_bidi_request);
+
+/**
+ * blk_end_request_callback - Special helper function for tricky drivers
+ * @rq: the request being processed
+ * @error: 0 for success, < 0 for error
+ * @nr_bytes: number of bytes to complete
+ * @drv_callback: function called between completion of bios in the request
+ * and completion of the request.
+ * If the callback returns non 0, this helper returns without
+ * completion of the request.
+ *
+ * Description:
+ * Ends I/O on a number of bytes attached to @rq.
+ * If @rq has leftover, sets it up for the next range of segments.
+ *
+ * This special helper function is used only for existing tricky drivers.
+ * (e.g. cdrom_newpc_intr() of ide-cd)
+ * This interface will be removed when such drivers are rewritten.
+ * Don't use this interface in other places anymore.
+ *
+ * Return:
+ * 0 - we are done with this request
+ * 1 - this request is not freed yet.
+ * this request still has pending buffers or
+ * the driver doesn't want to finish this request yet.
+ **/
+int blk_end_request_callback(struct request *rq, int error, int nr_bytes,
+ int (drv_callback)(struct request *))
+{
+ return blk_end_io(rq, error, nr_bytes, 0, drv_callback);
+}
+EXPORT_SYMBOL_GPL(blk_end_request_callback);
+
static void blk_rq_bio_prep(struct request_queue *q, struct request *rq,
struct bio *bio)
{
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 9030c373ce6..cd03473f354 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -3455,19 +3455,12 @@ static inline bool DAC960_ProcessCompletedRequest(DAC960_Command_T *Command,
bool SuccessfulIO)
{
struct request *Request = Command->Request;
- int UpToDate;
-
- UpToDate = 0;
- if (SuccessfulIO)
- UpToDate = 1;
+ int Error = SuccessfulIO ? 0 : -EIO;
pci_unmap_sg(Command->Controller->PCIDevice, Command->cmd_sglist,
Command->SegmentCount, Command->DmaDirection);
- if (!end_that_request_first(Request, UpToDate, Command->BlockCount)) {
- add_disk_randomness(Request->rq_disk);
- end_that_request_last(Request, UpToDate);
-
+ if (!__blk_end_request(Request, Error, Command->BlockCount << 9)) {
if (Command->Completion) {
complete(Command->Completion);
Command->Completion = NULL;
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 509b6490413..ef50068def8 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1187,17 +1187,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
}
}
-static inline void complete_buffers(struct bio *bio, int status)
-{
- while (bio) {
- struct bio *xbh = bio->bi_next;
-
- bio->bi_next = NULL;
- bio_endio(bio, status ? 0 : -EIO);
- bio = xbh;
- }
-}
-
static void cciss_check_queues(ctlr_info_t *h)
{
int start_queue = h->next_to_run;
@@ -1263,21 +1252,14 @@ static void cciss_softirq_done(struct request *rq)
pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
}
- complete_buffers(rq->bio, (rq->errors == 0));
-
- if (blk_fs_request(rq)) {
- const int rw = rq_data_dir(rq);
-
- disk_stat_add(rq->rq_disk, sectors[rw], rq->nr_sectors);
- }
-
#ifdef CCISS_DEBUG
printk("Done with %p\n", rq);
#endif /* CCISS_DEBUG */
- add_disk_randomness(rq->rq_disk);
+ if (blk_end_request(rq, (rq->errors == 0) ? 0 : -EIO, blk_rq_bytes(rq)))
+ BUG();
+
spin_lock_irqsave(&h->lock, flags);
- end_that_request_last(rq, (rq->errors == 0));
cmd_free(h, cmd, 1);
cciss_check_queues(h);
spin_unlock_irqrestore(&h->lock, flags);
@@ -2544,7 +2526,6 @@ after_error_processing:
}
cmd->rq->data_len = 0;
cmd->rq->completion_data = cmd;
- blk_add_trace_rq(cmd->rq->q, cmd->rq, BLK_TA_COMPLETE);
blk_complete_request(cmd->rq);
}
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index c8132d95879..69199185ff4 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -167,7 +167,6 @@ static void start_io(ctlr_info_t *h);
static inline void addQ(cmdlist_t **Qptr, cmdlist_t *c);
static inline cmdlist_t *removeQ(cmdlist_t **Qptr, cmdlist_t *c);
-static inline void complete_buffers(struct bio *bio, int ok);
static inline void complete_command(cmdlist_t *cmd, int timeout);
static irqreturn_t do_ida_intr(int irq, void *dev_id);
@@ -980,26 +979,13 @@ static void start_io(ctlr_info_t *h)
}
}
-static inline void complete_buffers(struct bio *bio, int ok)
-{
- struct bio *xbh;
-
- while (bio) {
- xbh = bio->bi_next;
- bio->bi_next = NULL;
-
- bio_endio(bio, ok ? 0 : -EIO);
-
- bio = xbh;
- }
-}
/*
* Mark all buffers that cmd was responsible for
*/
static inline void complete_command(cmdlist_t *cmd, int timeout)
{
struct request *rq = cmd->rq;
- int ok=1;
+ int error = 0;
int i, ddir;
if (cmd->req.hdr.rcode & RCODE_NONFATAL &&
@@ -1011,16 +997,17 @@ static inline void complete_command(cmdlist_t *cmd, int timeout)
if (cmd->req.hdr.rcode & RCODE_FATAL) {
printk(KERN_WARNING "Fatal error on ida/c%dd%d\n",
cmd->ctlr, cmd->hdr.unit);
- ok = 0;
+ error = -EIO;
}
if (cmd->req.hdr.rcode & RCODE_INVREQ) {
printk(KERN_WARNING "Invalid request on ida/c%dd%d = (cmd=%x sect=%d cnt=%d sg=%d ret=%x)\n",
cmd->ctlr, cmd->hdr.unit, cmd->req.hdr.cmd,
cmd->req.hdr.blk, cmd->req.hdr.blk_cnt,
cmd->req.hdr.sg_cnt, cmd->req.hdr.rcode);
- ok = 0;
+ error = -EIO;
}
- if (timeout) ok = 0;
+ if (timeout)
+ error = -EIO;
/* unmap the DMA mapping for all the scatter gather elements */
if (cmd->req.hdr.cmd == IDA_READ)
ddir = PCI_DMA_FROMDEVICE;
@@ -1030,18 +1017,9 @@ static inline void complete_command(cmdlist_t *cmd, int timeout)
pci_unmap_page(hba[cmd->ctlr]->pci_dev, cmd->req.sg[i].addr,
cmd->req.sg[i].size, ddir);
- complete_buffers(rq->bio, ok);
-
- if (blk_fs_request(rq)) {
- const int rw = rq_data_dir(rq);
-
- disk_stat_add(rq->rq_disk, sectors[rw], rq->nr_sectors);
- }
-
- add_disk_randomness(rq->rq_disk);
-
DBGPX(printk("Done with %p\n", rq););
- end_that_request_last(rq, ok ? 1 : -EIO);
+ if (__blk_end_request(rq, error, blk_rq_bytes(rq)))
+ BUG();
}
/*
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 639ed14bb08..32c79a55511 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -2287,21 +2287,19 @@ static int do_format(int drive, struct format_descr *tmp_format_req)
* =============================
*/
-static void floppy_end_request(struct request *req, int uptodate)
+static void floppy_end_request(struct request *req, int error)
{
unsigned int nr_sectors = current_count_sectors;
+ unsigned int drive = (unsigned long)req->rq_disk->private_data;
/* current_count_sectors can be zero if transfer failed */
- if (!uptodate)
+ if (error)
nr_sectors = req->current_nr_sectors;
- if (end_that_request_first(req, uptodate, nr_sectors))
+ if (__blk_end_request(req, error, nr_sectors << 9))
return;
- add_disk_randomness(req->rq_disk);
- floppy_off((long)req->rq_disk->private_data);
- blkdev_dequeue_request(req);
- end_that_request_last(req, uptodate);
/* We're done with the request */
+ floppy_off(drive);
current_req = NULL;
}
@@ -2332,7 +2330,7 @@ static void request_done(int uptodate)
/* unlock chained buffers */
spin_lock_irqsave(q->queue_lock, flags);
- floppy_end_request(req, 1);
+ floppy_end_request(req, 0);
spin_unlock_irqrestore(q->queue_lock, flags);
} else {
if (rq_data_dir(req) == WRITE) {
@@ -2346,7 +2344,7 @@ static void request_done(int uptodate)
DRWE->last_error_generation = DRS->generation;
}
spin_lock_irqsave(q->queue_lock, flags);
- floppy_end_request(req, 0);
+ floppy_end_request(req, -EIO);
spin_unlock_irqrestore(q->queue_lock, flags);
}
}
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index ba9b17e507e..ae3106045ee 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -100,17 +100,15 @@ static const char *nbdcmd_to_ascii(int cmd)
static void nbd_end_request(struct request *req)
{
- int uptodate = (req->errors == 0) ? 1 : 0;
+ int error = req->errors ? -EIO : 0;
struct request_queue *q = req->q;
unsigned long flags;
dprintk(DBG_BLKDEV, "%s: request %p: %s\n", req->rq_disk->disk_name,
- req, uptodate? "done": "failed");
+ req, error ? "failed" : "done");
spin_lock_irqsave(q->queue_lock, flags);
- if (!end_that_request_first(req, uptodate, req->nr_sectors)) {
- end_that_request_last(req, uptodate);
- }
+ __blk_end_request(req, error, req->nr_sectors << 9);
spin_unlock_irqrestore(q->queue_lock, flags);
}
diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c
index e354bfc070e..7483f947f0e 100644
--- a/drivers/block/ps3disk.c
+++ b/drivers/block/ps3disk.c
@@ -229,7 +229,7 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data)
struct ps3_storage_device *dev = data;
struct ps3disk_private *priv;
struct request *req;
- int res, read, uptodate;
+ int res, read, error;
u64 tag, status;
unsigned long num_sectors;
const char *op;
@@ -270,21 +270,17 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data)
if (status) {
dev_dbg(&dev->sbd.core, "%s:%u: %s failed 0x%lx\n", __func__,
__LINE__, op, status);
- uptodate = 0;
+ error = -EIO;
} else {
dev_dbg(&dev->sbd.core, "%s:%u: %s completed\n", __func__,
__LINE__, op);
- uptodate = 1;
+ error = 0;
if (read)
ps3disk_scatter_gather(dev, req, 0);
}
spin_lock(&priv->lock);
- if (!end_that_request_first(req, uptodate, num_sectors)) {
- add_disk_randomness(req->rq_disk);
- blkdev_dequeue_request(req);
- end_that_request_last(req, uptodate);
- }
+ __blk_end_request(req, error, num_sectors << 9);
priv->req = NULL;
ps3disk_do_request(dev, priv->queue);
spin_unlock(&priv->lock);
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
index fac4c6cd04f..66e30155b0a 100644
--- a/drivers/block/sunvdc.c
+++ b/drivers/block/sunvdc.c
@@ -212,12 +212,9 @@ static void vdc_end_special(struct vdc_port *port, struct vio_disk_desc *desc)
vdc_finish(&port->vio, -err, WAITING_FOR_GEN_CMD);
}
-static void vdc_end_request(struct request *req, int uptodate, int num_sectors)
+static void vdc_end_request(struct request *req, int error, int num_sectors)
{
- if (end_that_request_first(req, uptodate, num_sectors))
- return;
- add_disk_randomness(req->rq_disk);
- end_that_request_last(req, uptodate);
+ __blk_end_request(req, error, num_sectors << 9);
}
static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr,
@@ -242,7 +239,7 @@ static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr,
rqe->req = NULL;
- vdc_end_request(req, !desc->status, desc->size >> 9);
+ vdc_end_request(req, (desc->status ? -EIO : 0), desc->size >> 9);
if (blk_queue_stopped(port->disk->queue))
blk_start_queue(port->disk->queue);
@@ -456,7 +453,7 @@ static void do_vdc_request(struct request_queue *q)
blkdev_dequeue_request(req);
if (__send_request(req) < 0)
- vdc_end_request(req, 0, req->hard_nr_sectors);
+ vdc_end_request(req, -EIO, req->hard_nr_sectors);
}
}
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
index 52dc5e13171..cd5674b63fa 100644
--- a/drivers/block/sx8.c
+++ b/drivers/block/sx8.c
@@ -744,16 +744,14 @@ static unsigned int carm_fill_get_fw_ver(struct carm_host *host,
static inline void carm_end_request_queued(struct carm_host *host,
struct carm_request *crq,
- int uptodate)
+ int error)
{
struct request *req = crq->rq;
int rc;
- rc = end_that_request_first(req, uptodate, req->hard_nr_sectors);
+ rc = __blk_end_request(req, error, blk_rq_bytes(req));
assert(rc == 0);
- end_that_request_last(req, uptodate);
-
rc = carm_put_request(host, crq);
assert(rc == 0);
}
@@ -793,9 +791,9 @@ static inline void carm_round_robin(struct carm_host *host)
}
static inline void carm_end_rq(struct carm_host *host, struct carm_request *crq,
- int is_ok)
+ int error)
{
- carm_end_request_queued(host, crq, is_ok);
+ carm_end_request_queued(host, crq, error);
if (max_queue == 1)
carm_round_robin(host);
else if ((host->n_msgs <= CARM_MSG_LOW_WATER) &&
@@ -873,14 +871,14 @@ queue_one_request:
sg = &crq->sg[0];
n_elem = blk_rq_map_sg(q, rq, sg);
if (n_elem <= 0) {
- carm_end_rq(host, crq, 0);
+ carm_end_rq(host, crq, -EIO);
return; /* request with no s/g entries? */
}
/* map scatterlist to PCI bus addresses */
n_elem = pci_map_sg(host->pdev, sg, n_elem, pci_dir);
if (n_elem <= 0) {
- carm_end_rq(host, crq, 0);
+ carm_end_rq(host, crq, -EIO);
return; /* request with no s/g entries? */
}
crq->n_elem = n_elem;
@@ -941,7 +939,7 @@ queue_one_request:
static void carm_handle_array_info(struct carm_host *host,
struct carm_