[dm-devel] [RFC PATCH 1/4] convert block layer drivers to blkerr error values

Mike Christie michaelc at cs.wisc.edu
Wed Aug 24 09:03:58 UTC 2005


The current -Exyz errors are not descriptive enough to
allow upper layers like DM and MD to decide how to
handle IO errors. In many cases all we get is a -EIO.
The following path introduces BLK* error values for
use with the bio_endio and end_that_request* functions
(end_request keeps uptodate). I converted all the
users in this patch except scsi and dm. Those will
be in the next patches.

This patch will break all out of tree drivers.
I was not sure if it was better to start clean
or keep support for 1, 0, Exyz and whatever
else some drivers were sending sometimes. If
you want I can just redefine the BLKERR values to
fit into the existing tests then have driver
like dm-multipath check for both BLKERR and -Exyz
errors.

This is just a RFC and it has actually been sent to lkml
in the past so since I really want to make sure it will
work for SCSI amd dm-multipath I am just sending it here.
I will break this patch up and send it to lkml and
the maintainers of these drivers in the future.

Signed-off-by: Mike Christie <michaelc at cs.wisc.edu>

diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -3471,9 +3471,9 @@ static inline boolean DAC960_ProcessComp
 	struct request *Request = Command->Request;
 	int UpToDate;
 
-	UpToDate = 0;
+	UpToDate = BLKERR_IO;
 	if (SuccessfulIO)
-		UpToDate = 1;
+		UpToDate = BLK_SUCCESS;
 
 	pci_unmap_sg(Command->Controller->PCIDevice, Command->cmd_sglist,
 		Command->SegmentCount, Command->DmaDirection);
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -133,7 +133,7 @@ aoeblk_make_request(request_queue_t *q, 
 	if (buf == NULL) {
 		printk(KERN_INFO "aoe: aoeblk_make_request: buf allocation "
 			"failure\n");
-		bio_endio(bio, bio->bi_size, -ENOMEM);
+		bio_endio(bio, bio->bi_size, BLKERR_RETRY_DRV);
 		return 0;
 	}
 	memset(buf, 0, sizeof(*buf));
@@ -153,7 +153,7 @@ aoeblk_make_request(request_queue_t *q, 
 			d->aoemajor, d->aoeminor);
 		spin_unlock_irqrestore(&d->lock, flags);
 		mempool_free(buf, d->bufpool);
-		bio_endio(bio, bio->bi_size, -ENXIO);
+		bio_endio(bio, bio->bi_size, BLKERR_FATAL_DEV);
 		return 0;
 	}
 
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -478,7 +478,7 @@ aoecmd_ata_rsp(struct sk_buff *skb)
 				disk_stat_add(disk, read_sectors, n_sect);
 			}
 			disk_stat_add(disk, io_ticks, duration);
-			n = (buf->flags & BUFFL_FAIL) ? -EIO : 0;
+			n = (buf->flags & BUFFL_FAIL) ? BLKERR_IO : BLK_SUCCESS;
 			bio_endio(buf->bio, buf->bio->bi_size, n);
 			mempool_free(buf, d->bufpool);
 		}
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c
--- a/drivers/block/aoe/aoedev.c
+++ b/drivers/block/aoe/aoedev.c
@@ -79,7 +79,7 @@ aoedev_downdev(struct aoedev *d)
 		bio = buf->bio;
 		if (--buf->nframesout == 0) {
 			mempool_free(buf, d->bufpool);
-			bio_endio(bio, bio->bi_size, -EIO);
+			bio_endio(bio, bio->bi_size, BLKERR_IO);
 		}
 	}
 	d->inprocess = NULL;
@@ -89,7 +89,7 @@ aoedev_downdev(struct aoedev *d)
 		list_del(d->bufq.next);
 		bio = buf->bio;
 		mempool_free(buf, d->bufpool);
-		bio_endio(bio, bio->bi_size, -EIO);
+		bio_endio(bio, bio->bi_size, BLKERR_IO);
 	}
 
 	if (d->nopen)
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1913,7 +1913,8 @@ static inline void complete_buffers(stru
 
 		bio->bi_next = NULL; 
 		blk_finished_io(len);
-		bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO);
+		bio_endio(bio, nr_sectors << 9,
+			  status ? BLK_SUCCESS : BLKERR_IO);
 		bio = xbh;
 	}
 
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -992,7 +992,7 @@ static inline void complete_buffers(stru
 		bio->bi_next = NULL;
 		
 		blk_finished_io(nr_sectors);
-		bio_endio(bio, nr_sectors << 9, ok ? 0 : -EIO);
+		bio_endio(bio, nr_sectors << 9, ok ? BLK_SUCCESS : BLKERR_IO);
 
 		bio = xbh;
 	}
diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c
--- a/drivers/block/elevator.c
+++ b/drivers/block/elevator.c
@@ -404,7 +404,7 @@ struct request *elv_next_request(request
 
 			blkdev_dequeue_request(rq);
 			rq->flags |= REQ_QUIET;
-			end_that_request_chunk(rq, 0, nr_bytes);
+			end_that_request_chunk(rq, BLKERR_IO, nr_bytes);
 			end_that_request_last(rq);
 		} else {
 			printk(KERN_ERR "%s: bad return=%d\n", __FUNCTION__,
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -2290,11 +2290,14 @@ static int do_format(int drive, struct f
 static void floppy_end_request(struct request *req, int uptodate)
 {
 	unsigned int nr_sectors = current_count_sectors;
+	int err = BLK_SUCCESS;
 
 	/* current_count_sectors can be zero if transfer failed */
-	if (!uptodate)
+	if (!uptodate) {
+		err = BLKERR_IO;
 		nr_sectors = req->current_nr_sectors;
-	if (end_that_request_first(req, uptodate, nr_sectors))
+	}
+	if (end_that_request_first(req, err, nr_sectors))
 		return;
 	add_disk_randomness(req->rq_disk);
 	floppy_off((long)req->rq_disk->private_data);
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -2551,7 +2551,7 @@ static int __make_request(request_queue_
 
 	barrier = bio_barrier(bio);
 	if (unlikely(barrier) && (q->ordered == QUEUE_ORDERED_NONE)) {
-		err = -EOPNOTSUPP;
+		err = BLKERR_NOTSUPP;
 		goto end_io;
 	}
 
@@ -2860,7 +2860,7 @@ void generic_make_request(struct bio *bi
 				bdevname(bio->bi_bdev, b),
 				(long long) bio->bi_sector);
 end_io:
-			bio_endio(bio, bio->bi_size, -EIO);
+			bio_endio(bio, bio->bi_size, BLKERR_IO);
 			break;
 		}
 
@@ -2996,29 +2996,23 @@ static void blk_recalc_rq_sectors(struct
 	}
 }
 
-static int __end_that_request_first(struct request *req, int uptodate,
+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;
 
 	/*
-	 * 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 != BLK_SUCCESS) {
 		if (blk_fs_request(req) && !(req->flags & REQ_QUIET))
-			printk("end_request: I/O error, dev %s, sector %llu\n",
+			printk("end_request: I/O error %d, dev %s, sector "
+				"%llu\n", error,
 				req->rq_disk ? req->rq_disk->disk_name : "?",
 				(unsigned long long)req->sector);
 	}
@@ -3099,7 +3093,7 @@ static int __end_that_request_first(stru
 /**
  * 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
+ * @uptodate: a block layer error value
  * @nr_sectors: number of sectors to end I/O on
  *
  * Description:
@@ -3120,7 +3114,7 @@ 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
+ * @uptodate: a block layer error value
  * @nr_bytes: number of bytes to complete
  *
  * Description:
@@ -3174,7 +3168,9 @@ EXPORT_SYMBOL(end_that_request_last);
 
 void end_request(struct request *req, int uptodate)
 {
-	if (!end_that_request_first(req, uptodate, req->hard_cur_sectors)) {
+	int err = uptodate ? BLK_SUCCESS : BLKERR_IO;
+
+	if (!end_that_request_first(req, err, req->hard_cur_sectors)) {
 		add_disk_randomness(req->rq_disk);
 		blkdev_dequeue_request(req);
 		end_that_request_last(req);
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -549,7 +549,7 @@ static inline void loop_handle_bio(struc
 		do_loop_switch(lo, bio->bi_private);
 		bio_put(bio);
 	} else {
-		int ret = do_bio_filebacked(lo, bio);
+		int ret = do_bio_filebacked(lo, bio) ? BLKERR_IO : BLK_SUCCESS;
 		bio_endio(bio, bio->bi_size, ret);
 	}
 }
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -127,15 +127,15 @@ static const char *nbdcmd_to_ascii(int c
 
 static void nbd_end_request(struct request *req)
 {
-	int uptodate = (req->errors == 0) ? 1 : 0;
+	int err = (req->errors == 0) ? BLK_SUCCESS : BLKERR_IO;
 	request_queue_t *q = req->q;
 	unsigned long flags;
 
 	dprintk(DBG_BLKDEV, "%s: request %p: %s\n", req->rq_disk->disk_name,
-			req, uptodate? "done": "failed");
+			req, err == BLK_SUCCESS ? "done": "failed");
 
 	spin_lock_irqsave(q->queue_lock, flags);
-	if (!end_that_request_first(req, uptodate, req->nr_sectors)) {
+	if (!end_that_request_first(req, err, req->nr_sectors)) {
 		end_that_request_last(req);
 	}
 	spin_unlock_irqrestore(q->queue_lock, flags);
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -678,7 +678,7 @@ static int pkt_end_io_read(struct bio *b
 	VPRINTK("pkt_end_io_read: bio=%p sec0=%llx sec=%llx err=%d\n", bio,
 		(unsigned long long)pkt->sector, (unsigned long long)bio->bi_sector, err);
 
-	if (err)
+	if (err != BLK_SUCCESS)
 		atomic_inc(&pkt->io_errors);
 	if (atomic_dec_and_test(&pkt->io_wait)) {
 		atomic_inc(&pkt->run_sm);
@@ -1049,7 +1049,6 @@ static void pkt_start_write(struct pktcd
 	pkt->w_bio->bi_max_vecs = PACKET_MAX_SIZE;
 	pkt->w_bio->bi_sector = pkt->sector;
 	pkt->w_bio->bi_bdev = pd->bdev;
-	pkt->w_bio->bi_end_io = pkt_end_io_packet_write;
 	pkt->w_bio->bi_private = pkt;
 	for (f = 0; f < pkt->frames; f++) {
 		if ((f + 1 < pkt->frames) && (pages[f + 1] == pages[f]) &&
@@ -1081,7 +1080,8 @@ static void pkt_finish_packet(struct pac
 	while (bio) {
 		next = bio->bi_next;
 		bio->bi_next = NULL;
-		bio_endio(bio, bio->bi_size, uptodate ? 0 : -EIO);
+		bio_endio(bio, bio->bi_size,
+			  uptodate ? BLK_SUCCESS : BLKERR_IO);
 		bio = next;
 	}
 	pkt->orig_bios = pkt->orig_bios_tail = NULL;
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -288,7 +288,7 @@ static int rd_make_request(request_queue
 	if (ret)
 		goto fail;
 
-	bio_endio(bio, bio->bi_size, 0);
+	bio_endio(bio, bio->bi_size, BLK_SUCCESS);
 	return 0;
 fail:
 	bio_io_error(bio, bio->bi_size);
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
--- a/drivers/block/sx8.c
+++ b/drivers/block/sx8.c
@@ -790,7 +790,7 @@ static inline void carm_round_robin(stru
 static inline void carm_end_rq(struct carm_host *host, struct carm_request *crq,
 			int is_ok)
 {
-	carm_end_request_queued(host, crq, is_ok);
+	carm_end_request_queued(host, crq, is_ok ? BLK_SUCCESS : BLKERR_IO);
 	if (CARM_MAX_Q == 1)
 		carm_round_robin(host);
 	else if ((host->n_msgs <= CARM_MSG_LOW_WATER) &&
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -765,7 +765,7 @@ static int ub_bd_rq_fn_1(struct ub_lun *
 
 	if (atomic_read(&sc->poison) || lun->changed) {
 		blkdev_dequeue_request(rq);
-		ub_end_rq(rq, 0);
+		ub_end_rq(rq, BLKERR_IO);
 		return 0;
 	}
 
@@ -782,7 +782,7 @@ static int ub_bd_rq_fn_1(struct ub_lun *
 	}
 	if (rc != 0) {
 		ub_put_cmd(lun, cmd);
-		ub_end_rq(rq, 0);
+		ub_end_rq(rq, BLKERR_IO);
 		return 0;
 	}
 	cmd->state = UB_CMDST_INIT;
@@ -793,7 +793,7 @@ static int ub_bd_rq_fn_1(struct ub_lun *
 	cmd->tag = sc->tagcnt++;
 	if ((rc = ub_submit_scsi(sc, cmd)) != 0) {
 		ub_put_cmd(lun, cmd);
-		ub_end_rq(rq, 0);
+		ub_end_rq(rq, BLKERR_IO);
 		return 0;
 	}
 
@@ -823,7 +823,7 @@ static int ub_cmd_build_block(struct ub_
 	n_elem = blk_rq_map_sg(q, rq, sg);
 	if (n_elem <= 0) {
 		ub_put_cmd(lun, cmd);
-		ub_end_rq(rq, 0);
+		ub_end_rq(rq, BLKERR_IO);
 		blk_start_queue(q);
 		return 0;		/* request with no s/g entries? */
 	}
@@ -832,7 +832,7 @@ static int ub_cmd_build_block(struct ub_
 		printk(KERN_WARNING "%s: request with %d segments\n",
 		    sc->name, n_elem);
 		ub_put_cmd(lun, cmd);
-		ub_end_rq(rq, 0);
+		ub_end_rq(rq, BLKERR_IO);
 		blk_start_queue(q);
 		return 0;
 	}
@@ -930,9 +930,9 @@ static void ub_rw_cmd_done(struct ub_dev
 	}
 
 	if (cmd->error == 0)
-		uptodate = 1;
+		uptodate = BLK_SUCCESS;
 	else
-		uptodate = 0;
+		uptodate = BLKERR_IO;
 
 	ub_put_cmd(lun, cmd);
 	ub_end_rq(rq, uptodate);
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -543,7 +543,7 @@ static void process_page(unsigned long d
 
 		return_bio = bio->bi_next;
 		bio->bi_next = NULL;
-		bio_endio(bio, bio->bi_size, 0);
+		bio_endio(bio, bio->bi_size, BLK_SUCCESS);
 	}
 }
 
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
--- a/drivers/block/viodasd.c
+++ b/drivers/block/viodasd.c
@@ -445,12 +445,14 @@ static void do_viodasd_request(request_q
 		blkdev_dequeue_request(req);
 		/* check that request contains a valid command */
 		if (!blk_fs_request(req)) {
-			viodasd_end_request(req, 0, req->hard_nr_sectors);
+			viodasd_end_request(req, BLKERR_IO,
+					    req->hard_nr_sectors);
 			continue;
 		}
 		/* Try sending the request */
 		if (send_request(req) != 0)
-			viodasd_end_request(req, 0, req->hard_nr_sectors);
+			viodasd_end_request(req, BLKERR_IO,
+					    req->hard_nr_sectors);
 	}
 }
 
@@ -656,7 +658,7 @@ static int viodasd_handle_read_write(str
 	}
 	qlock = req->q->queue_lock;
 	spin_lock_irqsave(qlock, irq_flags);
-	viodasd_end_request(req, !error, num_sect);
+	viodasd_end_request(req, error ? BLKERR_IO : BLK_SUCCESS, num_sect);
 	spin_unlock_irqrestore(qlock, irq_flags);
 
 	/* Finally, try to get more requests off of this device's queue */
diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
--- a/drivers/cdrom/cdu31a.c
+++ b/drivers/cdrom/cdu31a.c
@@ -1399,7 +1399,7 @@ static void do_cdu31a_request(request_qu
 		read_data_block(req->buffer, block, nblock, res_reg, &res_size);
 
 		if (res_reg[0] != 0x20) {
-			if (!end_that_request_first(req, 1, nblock)) {
+			if (!end_that_request_first(req, BLK_SUCCESS, nblock)) {
 				spin_lock_irq(q->queue_lock);
 				blkdev_dequeue_request(req);
 				end_that_request_last(req);
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -613,7 +613,8 @@ static void cdrom_end_request (ide_drive
 			 * now end failed request
 			 */
 			spin_lock_irqsave(&ide_lock, flags);
-			end_that_request_chunk(failed, 0, failed->data_len);
+			end_that_request_chunk(failed, BLKERR_IO,
+					       failed->data_len);
 			end_that_request_last(failed);
 			spin_unlock_irqrestore(&ide_lock, flags);
 		}
@@ -1636,7 +1637,7 @@ static ide_startstop_t cdrom_newpc_intr(
 			return ide_error(drive, "dma error", stat);
 		}
 
-		end_that_request_chunk(rq, 1, rq->data_len);
+		end_that_request_chunk(rq, BLK_SUCCESS, rq->data_len);
 		rq->data_len = 0;
 		goto end_request;
 	}
@@ -1710,7 +1711,7 @@ static ide_startstop_t cdrom_newpc_intr(
 		rq->data_len -= blen;
 
 		if (rq->bio)
-			end_that_request_chunk(rq, 1, blen);
+			end_that_request_chunk(rq, BLK_SUCCESS, blen);
 		else
 			rq->data += blen;
 	}
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -58,6 +58,7 @@
 int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate,
 		      int nr_sectors)
 {
+	int err = uptodate ? BLK_SUCCESS : BLKERR_IO;
 	int ret = 1;
 
 	BUG_ON(!(rq->flags & REQ_STARTED));
@@ -66,10 +67,10 @@ int __ide_end_request(ide_drive_t *drive
 	 * if failfast is set on a request, override number of sectors and
 	 * complete the whole request right now
 	 */
-	if (blk_noretry_request(rq) && end_io_error(uptodate))
+	if (blk_noretry_request(rq) && err != BLK_SUCCESS)
 		nr_sectors = rq->hard_nr_sectors;
 
-	if (!blk_fs_request(rq) && end_io_error(uptodate) && !rq->errors)
+	if (!blk_fs_request(rq) && (err != BLK_SUCCESS) && !rq->errors)
 		rq->errors = -EIO;
 
 	/*
@@ -81,7 +82,7 @@ int __ide_end_request(ide_drive_t *drive
 		HWGROUP(drive)->hwif->ide_dma_on(drive);
 	}
 
-	if (!end_that_request_first(rq, uptodate, nr_sectors)) {
+	if (!end_that_request_first(rq, err, nr_sectors)) {
 		add_disk_randomness(rq->rq_disk);
 
 		if (blk_rq_tagged(rq))
diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c
--- a/drivers/md/faulty.c
+++ b/drivers/md/faulty.c
@@ -76,7 +76,7 @@ static int faulty_fail(struct bio *bio, 
 		bio_put(bio);
 
 	clear_bit(BIO_UPTODATE, &b->bi_flags);
-	return (b->bi_end_io)(b, bytes_done, -EIO);
+	return (b->bi_end_io)(b, bytes_done, BLKERR_IO);
 }
 
 typedef struct faulty_conf {
@@ -179,7 +179,7 @@ static int make_request(request_queue_t 
 			/* special case - don't decrement, don't generic_make_request,
 			 * just fail immediately
 			 */
-			bio_endio(bio, bio->bi_size, -EIO);
+			bio_endio(bio, bio->bi_size, BLKERR_IO);
 			return 0;
 		}
 
diff --git a/drivers/md/md.c b/drivers/md/md.c
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -333,7 +333,7 @@ static int super_written(struct bio *bio
 	if (bio->bi_size)
 		return 1;
 
-	if (error || !test_bit(BIO_UPTODATE, &bio->bi_flags))
+	if (error != BLK_SUCCESS || !test_bit(BIO_UPTODATE, &bio->bi_flags))
 		md_error(rdev->mddev, rdev);
 
 	if (atomic_dec_and_test(&rdev->mddev->pending_writes))
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -115,7 +115,7 @@ static int multipath_end_request(struct 
 		return 1;
 
 	if (uptodate)
-		multipath_end_bh_io(mp_bh, 0);
+		multipath_end_bh_io(mp_bh, BLK_SUCCESS);
 	else if (!bio_rw_ahead(bio)) {
 		/*
 		 * oops, IO error:
@@ -184,7 +184,7 @@ static int multipath_make_request (reque
 
 	mp_bh->path = multipath_map(conf);
 	if (mp_bh->path < 0) {
-		bio_endio(bio, bio->bi_size, -EIO);
+		bio_endio(bio, bio->bi_size, BLKERR_IO);
 		mempool_free(mp_bh, conf->pool);
 		return 0;
 	}
@@ -405,7 +405,7 @@ static void multipathd (mddev_t *mddev)
 				" error for block %llu\n",
 				bdevname(bio->bi_bdev,b),
 				(unsigned long long)bio->bi_sector);
-			multipath_end_bh_io(mp_bh, -EIO);
+			multipath_end_bh_io(mp_bh, BLKERR_IO);
 		} else {
 			printk(KERN_ERR "multipath: %s: redirecting sector %llu"
 				" to another IO path\n",
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -223,7 +223,7 @@ static void raid_end_bio_io(r1bio_t *r1_
 	struct bio *bio = r1_bio->master_bio;
 
 	bio_endio(bio, bio->bi_size,
-		test_bit(R1BIO_Uptodate, &r1_bio->state) ? 0 : -EIO);
+		test_bit(R1BIO_Uptodate, &r1_bio->state) ? BLK_SUCCESS : BLKERR_IO);
 	free_r1bio(r1_bio);
 }
 
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -238,7 +238,7 @@ static void raid_end_bio_io(r10bio_t *r1
 	struct bio *bio = r10_bio->master_bio;
 
 	bio_endio(bio, bio->bi_size,
-		test_bit(R10BIO_Uptodate, &r10_bio->state) ? 0 : -EIO);
+		test_bit(R10BIO_Uptodate, &r10_bio->state) ? BLK_SUCCESS : BLKERR_IO);
 	free_r10bio(r10_bio);
 }
 
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -1249,7 +1249,7 @@ static void handle_stripe(struct stripe_
 		return_bi = bi->bi_next;
 		bi->bi_next = NULL;
 		bi->bi_size = 0;
-		bi->bi_end_io(bi, bytes, 0);
+		bi->bi_end_io(bi, bytes, BLK_SUCCESS);
 	}
 	for (i=disks; i-- ;) {
 		int rw;
@@ -1469,7 +1469,7 @@ static int make_request (request_queue_t
 		if ( bio_data_dir(bi) == WRITE )
 			md_write_end(mddev);
 		bi->bi_size = 0;
-		bi->bi_end_io(bi, bytes, 0);
+		bi->bi_end_io(bi, bytes, BLK_SUCCESS);
 	}
 	spin_unlock_irq(&conf->device_lock);
 	return 0;
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -1408,7 +1408,7 @@ static void handle_stripe(struct stripe_
 		return_bi = bi->bi_next;
 		bi->bi_next = NULL;
 		bi->bi_size = 0;
-		bi->bi_end_io(bi, bytes, 0);
+		bi->bi_end_io(bi, bytes, BLK_SUCCESS);
 	}
 	for (i=disks; i-- ;) {
 		int rw;
@@ -1628,7 +1628,7 @@ static int make_request (request_queue_t
 		if ( bio_data_dir(bi) == WRITE )
 			md_write_end(mddev);
 		bi->bi_size = 0;
-		bi->bi_end_io(bi, bytes, 0);
+		bi->bi_end_io(bi, bytes, BLK_SUCCESS);
 	}
 	spin_unlock_irq(&conf->device_lock);
 	return 0;
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -438,7 +438,7 @@ static void i2o_block_delayed_request_fn
 /**
  *	i2o_block_end_request - Post-processing of completed commands
  *	@req: request which should be completed
- *	@uptodate: 1 for success, 0 for I/O error, < 0 for specific error
+ *	@uptodate: A BLKERR_* value or BLK_SUCCESS
  *	@nr_bytes: number of bytes to complete
  *
  *	Mark the request as complete. The lock must not be held when entering.
@@ -458,8 +458,8 @@ static void i2o_block_end_request(struct
 		if (blk_pc_request(req))
 			leftover = req->data_len;
 
-		if (end_io_error(uptodate))
-			end_that_request_chunk(req, 0, leftover);
+		if (uptodate != BLK_SUCCESS)
+			end_that_request_chunk(req, uptodate, leftover);
 	}
 
 	add_disk_randomness(req->rq_disk);
@@ -494,7 +494,7 @@ static int i2o_block_reply(struct i2o_co
 			   struct i2o_message *msg)
 {
 	struct request *req;
-	int uptodate = 1;
+	int uptodate = BLK_SUCCESS;
 
 	req = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt));
 	if (unlikely(!req)) {
@@ -527,7 +527,7 @@ static int i2o_block_reply(struct i2o_co
 
 		req->errors++;
 
-		uptodate = 0;
+		uptodate = BLKERR_IO;
 	}
 
 	i2o_block_end_request(req, uptodate, le32_to_cpu(msg->body[1]));
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -247,7 +247,8 @@ static int mmc_blk_issue_rq(struct mmc_q
 		 * A block was successfully transferred.
 		 */
 		spin_lock_irq(&md->lock);
-		ret = end_that_request_chunk(req, 1, brq.data.bytes_xfered);
+		ret = end_that_request_chunk(req, BLK_SUCCESS,
+					     brq.data.bytes_xfered);
 		if (!ret) {
 			/*
 			 * The whole request completed successfully.
@@ -274,7 +275,7 @@ static int mmc_blk_issue_rq(struct mmc_q
 	 */
 	spin_lock_irq(&md->lock);
 	do {
-		ret = end_that_request_chunk(req, 0,
+		ret = end_that_request_chunk(req, BLKERR_IO,
 				req->current_nr_sectors << 9);
 	} while (ret);
 
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -1036,7 +1036,9 @@ dasd_int_handler(struct ccw_device *cdev
 static inline void
 dasd_end_request(struct request *req, int uptodate)
 {
-	if (end_that_request_first(req, uptodate, req->hard_nr_sectors))
+	int err = !uptodate ? BLKERR_IO : BLK_SUCCESS;
+
+	if (end_that_request_first(req, err, req->hard_nr_sectors))
 		BUG();
 	add_disk_randomness(req->rq_disk);
 	end_that_request_last(req);
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -675,7 +675,7 @@ dcssblk_make_request(request_queue_t *q,
 		}
 		bytes_done += bvec->bv_len;
 	}
-	bio_endio(bio, bytes_done, 0);
+	bio_endio(bio, bytes_done, BLK_SUCCESS);
 	return 0;
 fail:
 	bio_io_error(bio, bio->bi_size);
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
--- a/drivers/s390/block/xpram.c
+++ b/drivers/s390/block/xpram.c
@@ -321,7 +321,7 @@ static int xpram_make_request(request_qu
 	set_bit(BIO_UPTODATE, &bio->bi_flags);
 	bytes = bio->bi_size;
 	bio->bi_size = 0;
-	bio->bi_end_io(bio, bytes, 0);
+	bio->bi_end_io(bio, bytes, BLK_SUCCESS);
 	return 0;
 fail:
 	bio_io_error(bio, bio->bi_size);
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -91,7 +91,7 @@ __tapeblock_end_request(struct tape_requ
 
 	device = ccw_req->device;
 	req = (struct request *) data;
-	tapeblock_end_request(req, ccw_req->rc == 0);
+	tapeblock_end_request(req, ccw_req->rc == 0 ? BLK_SUCCESS : BLKERR_IO);
 	if (ccw_req->rc == 0)
 		/* Update position. */
 		device->blk_data.block_position =
@@ -119,7 +119,7 @@ tapeblock_start_request(struct tape_devi
 	ccw_req = device->discipline->bread(device, req);
 	if (IS_ERR(ccw_req)) {
 		DBF_EVENT(1, "TBLOCK: bread failed\n");
-		tapeblock_end_request(req, 0);
+		tapeblock_end_request(req, BLKERR_IO);
 		return PTR_ERR(ccw_req);
 	}
 	ccw_req->callback = __tapeblock_end_request;
@@ -132,7 +132,7 @@ tapeblock_start_request(struct tape_devi
 		 * Start/enqueueing failed. No retries in
 		 * this case.
 		 */
-		tapeblock_end_request(req, 0);
+		tapeblock_end_request(req, BLKERR_IO);
 		device->discipline->free_bread(ccw_req);
 	}
 
@@ -175,7 +175,7 @@ tapeblock_requeue(void *data) {
 		if (rq_data_dir(req) == WRITE) {
 			DBF_EVENT(1, "TBLOCK: Rejecting write request\n");
 			blkdev_dequeue_request(req);
-			tapeblock_end_request(req, 0);
+			tapeblock_end_request(req, BLKERR_IO);
 			continue;
 		}
 		spin_unlock_irq(&device->blk_data.request_queue_lock);
diff --git a/fs/bio.c b/fs/bio.c
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -664,7 +664,7 @@ struct bio *bio_map_user(request_queue_t
 	/*
 	 * don't support partial mappings
 	 */
-	bio_endio(bio, bio->bi_size, 0);
+	bio_endio(bio, bio->bi_size, BLK_SUCCESS);
 	bio_unmap_user(bio);
 	return ERR_PTR(-EINVAL);
 }
@@ -837,14 +837,13 @@ void bio_check_pages_dirty(struct bio *b
  *   bio_endio() will end I/O on @bytes_done number of bytes. This may be
  *   just a partial part of the bio, or it may be the whole bio. bio_endio()
  *   is the preferred way to end I/O on a bio, it takes care of decrementing
- *   bi_size and clearing BIO_UPTODATE on error. @error is 0 on success, and
- *   and one of the established -Exxxx (-EIO, for instance) error values in
- *   case something went wrong. Noone should call bi_end_io() directly on
+ *   bi_size and clearing BIO_UPTODATE on error. @error is a block layer error
+ *   value defined in blkdev.h. Noone should call bi_end_io() directly on
  *   a bio unless they own it and thus know that it has an end_io function.
  **/
 void bio_endio(struct bio *bio, unsigned int bytes_done, int error)
 {
-	if (error)
+	if (error != BLK_SUCCESS)
 		clear_bit(BIO_UPTODATE, &bio->bi_flags);
 
 	if (unlikely(bytes_done > bio->bi_size)) {
@@ -874,7 +873,7 @@ static int bio_pair_end_1(struct bio * b
 {
 	struct bio_pair *bp = container_of(bi, struct bio_pair, bio1);
 
-	if (err)
+	if (err != BLK_SUCCESS)
 		bp->error = err;
 
 	if (bi->bi_size)
@@ -888,7 +887,7 @@ static int bio_pair_end_2(struct bio * b
 {
 	struct bio_pair *bp = container_of(bi, struct bio_pair, bio2);
 
-	if (err)
+	if (err != BLK_SUCCESS)
 		bp->error = err;
 
 	if (bi->bi_size)
@@ -912,7 +911,7 @@ struct bio_pair *bio_split(struct bio *b
 	BUG_ON(bi->bi_vcnt != 1);
 	BUG_ON(bi->bi_idx != 0);
 	atomic_set(&bp->cnt, 3);
-	bp->error = 0;
+	bp->error = BLK_SUCCESS;
 	bp->bio1 = *bi;
 	bp->bio2 = *bi;
 	bp->bio2.bi_sector += first_sectors;
diff --git a/fs/buffer.c b/fs/buffer.c
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2733,7 +2733,7 @@ static int end_bio_bh_io_sync(struct bio
 	if (bio->bi_size)
 		return 1;
 
-	if (err == -EOPNOTSUPP) {
+	if (err == BLKERR_NOTSUPP) {
 		set_bit(BIO_EOPNOTSUPP, &bio->bi_flags);
 		set_bit(BH_Eopnotsupp, &bh->b_state);
 	}
diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
--- a/fs/jfs/jfs_logmgr.c
+++ b/fs/jfs/jfs_logmgr.c
@@ -2157,7 +2157,7 @@ static void lbmStartIO(struct lbuf * bp)
 	/* check if journaling to disk has been disabled */
 	if (log->no_integrity) {
 		bio->bi_size = 0;
-		lbmIODone(bio, 0, 0);
+		lbmIODone(bio, 0, BLKERR_IO);
 	} else {
 		submit_bio(WRITE_SYNC, bio);
 		INCREMENT(lmStat.submitted);
diff --git a/include/linux/bio.h b/include/linux/bio.h
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -222,7 +222,7 @@ struct bio {
 #define BIO_SEG_BOUNDARY(q, b1, b2) \
 	BIOVEC_SEG_BOUNDARY((q), __BVEC_END((b1)), __BVEC_START((b2)))
 
-#define bio_io_error(bio, bytes) bio_endio((bio), (bytes), -EIO)
+#define bio_io_error(bio, bytes) bio_endio((bio), (bytes), BLKERR_IO)
 
 /*
  * drivers should not use the __ version unless they _really_ want to
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -599,12 +599,21 @@ extern void end_that_request_last(struct
 extern void end_request(struct request *req, int uptodate);
 
 /*
- * end_that_request_first/chunk() takes an uptodate argument. we account
- * any value <= as an io error. 0 means -EIO for compatability reasons,
- * any other < 0 value is the direct error type. An uptodate value of
- * 1 indicates successful io completion
+ * Error values that users of end_that_request_first/chunk,
+ * bio_endio/bi_end_io should use to indicate I/O completion status.
  */
-#define end_io_error(uptodate)	(unlikely((uptodate) <= 0))
+enum {
+	BLK_SUCCESS = 0,	/* Must be zero for compat with old usage */
+	BLKERR_IO,		/* Generic I/O error */
+	BLKERR_NOTSUPP,		/* Operation is not supported */
+	BLKERR_WOULDBLOCK,	/* Operation would block */
+	BLKERR_FATAL_DRV,	/* Fatal driver error */
+	BLKERR_FATAL_DEV,	/* Fatal device error */
+	BLKERR_FATAL_XPT,	/* Fatal transport error */
+	BLKERR_RETRY_DRV,	/* Driver error, I/O may be retried */
+	BLKERR_RETRY_DEV,	/* Device error, I/O may be retried */
+	BLKERR_RETRY_XPT,	/* Transport error, I/O may retried */
+};
 
 static inline void blkdev_dequeue_request(struct request *req)
 {





More information about the dm-devel mailing list