convert block layer drivers to blkerr error values
Subsystems (12)
RFC PATCH 1/4 convert block layer drivers to blkerr error values
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.
drivers/block/DAC960.c +2 -2
@@ -3471,9 +3471,9 @@ static inline boolean DAC960_ProcessCompstruct 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);
drivers/block/aoe/aoeblk.c +2 -2
@@ -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 ; }
drivers/block/aoe/aoecmd.c +1 -1
@@ -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); }
drivers/block/aoe/aoedev.c +2 -2
@@ -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)
drivers/block/cciss.c +2 -1
@@ -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; }
drivers/block/cpqarray.c +1 -1
@@ -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; }
drivers/block/elevator.c +1 -1
@@ -404,7 +404,7 @@ struct request *elv_next_request(requestblkdev_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__,
drivers/block/floppy.c +5 -2
@@ -2290,11 +2290,14 @@ static int do_format(int drive, struct fstatic 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);
drivers/block/ll_rw_blk.c +12 -16
@@ -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 *bibdevname (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);
drivers/block/loop.c +1 -1
@@ -549,7 +549,7 @@ static inline void loop_handle_bio(strucdo_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); } }
drivers/block/nbd.c +3 -3
@@ -127,15 +127,15 @@ static const char *nbdcmd_to_ascii(int cstatic 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);
drivers/block/pktcdvd.c +3 -3
@@ -678,7 +678,7 @@ static int pkt_end_io_read(struct bio *bVPRINTK ("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 pacwhile (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 ;
drivers/block/rd.c +1 -1
@@ -288,7 +288,7 @@ static int rd_make_request(request_queueif (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);
drivers/block/sx8.c +1 -1
@@ -790,7 +790,7 @@ static inline void carm_round_robin(strustatic 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) &&
drivers/block/ub.c +7 -7
@@ -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);
drivers/block/umem.c +1 -1
@@ -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 ); } }
drivers/block/viodasd.c +5 -3
@@ -445,12 +445,14 @@ static void do_viodasd_request(request_qblkdev_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 */
drivers/cdrom/cdu31a.c +1 -1
@@ -1399,7 +1399,7 @@ static void do_cdu31a_request(request_quread_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);
drivers/ide/ide-cd.c +4 -3
@@ -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; }
drivers/ide/ide-io.c +4 -3
@@ -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 *driveHWGROUP (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))
drivers/md/faulty.c +2 -2
@@ -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 ; }
drivers/md/md.c +1 -1
@@ -333,7 +333,7 @@ static int super_written(struct bio *bioif (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))
drivers/md/multipath.c +3 -3
@@ -115,7 +115,7 @@ static int multipath_end_request(structreturn 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",
drivers/md/raid1.c +1 -1
@@ -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); }
drivers/md/raid10.c +1 -1
@@ -238,7 +238,7 @@ static void raid_end_bio_io(r10bio_t *r1struct 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); }
drivers/md/raid5.c +2 -2
@@ -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_tif (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 ;
drivers/md/raid6main.c +2 -2
@@ -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_tif (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 ;
drivers/message/i2o/i2o_block.c +5 -5
@@ -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(structif (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 ]));
drivers/mmc/mmc_block.c +3 -2
@@ -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);
drivers/s390/block/dasd.c +3 -1
@@ -1036,7 +1036,9 @@ dasd_int_handler(struct ccw_device *cdevstatic 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);
drivers/s390/block/dcssblk.c +1 -1
@@ -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);
drivers/s390/block/xpram.c +1 -1
@@ -321,7 +321,7 @@ static int xpram_make_request(request_quset_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);
drivers/s390/char/tape_block.c +4 -4
@@ -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);
fs/bio.c +7 -8
@@ -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 *bBUG_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;
fs/buffer.c +1 -1
@@ -2733,7 +2733,7 @@ static int end_bio_bh_io_sync(struct bioif (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); }
fs/jfs/jfs_logmgr.c +1 -1
@@ -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);
include/linux/bio.h +1 -1
@@ -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
include/linux/blkdev.h +14 -5
@@ -599,12 +599,21 @@ extern void end_that_request_last(structextern 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) {
drivers/block/pktcdvd.c static void pkt_start_write(struct pktcd · line 1052
Quoted 5 lines · Mike Christie
drivers/block/pktcdvd.c +0
-1@@ -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;
oops I messed up my git checkins and stuff. This was a accident.
include/linux/blkdev.h extern void end_that_request_last(struct · line 616
Quoted 13 lines · Mike Christie
include/linux/blkdev.h +12
-1-#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 */ +};
Do you need to add and use a BLKERR_TIMEOUT? As we can't determine the problem area for a timeout, and if it can or should be retried.
-- Patrick Mansfield
Quoted 12 lines · Patrick Mansfield
Quoted 9 lines · Mike Christie
include/linux/blkdev.h +8
-1-#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 */
Quoted 9 lines
include/linux/blkdev.h extern void end_that_request_last(struct · line 616
Quoted 4 lines
include/linux/blkdev.h +4
-0+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 */ +};Do you need to add and use a
BLKERR_TIMEOUT? As we can't determine the problem area for a timeout, and if it can or should be retried.
I was hoping we could figure this out. In the patches, if a command times out and eh kicks off I was just returning BLKERR_RETRY_DEV. This guessing occurs for a lot of errors becuase we do not know what exactly happened. the reason for the timeout could have been a device problem or transport problem. Some help in figuring this type of thing out is needed in other places.
In general, I'm a bit worried about these changes, for two overall reasons:
1) I didn't see any analysis of the ultimate end users of block layer error values: the filesystems.
2) This begins to converge with the SCSI layer's error/retry/etc. error values. Since I would eventually like to see SCSI's non-SCSI-related infrastructure "moved up", a bit -more- alignment with SCSI at this stage might be nice.
Jeff
Quoted 3 lines · Jeff Garzik
In general, I'm a bit worried about these changes, for two overall reasons:
1) I didn't see any analysis of the ultimate end users of block layer error values: the filesystems.
The filesystems or helpers they use normally did not even check the -Exyz error they were getting except for -EOPNOTSUPPORTED. They typically use the uptodate bits on the bio or buffer head.
A greater discussion on what the FS's needed and what actions they should take would be good though, I agree. They never responded in the past so I thought the MD and DM were the only interested users for now. I will post to lkml or fs-devel next time. Sorry about that.
Quoted 15 lines · Patrick Mansfield
include/linux/blkdev.h extern void end_that_request_last(struct · line 616
Quoted 13 lines · Mike Christie
include/linux/blkdev.h +12
-1-#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 */ +};
Actually, I'd really be happier if these were a bitmap rather than an enumeration. That way we can divide them easily into cause (Driver, Device or Transport) and severity (fatal or retryable), so something like dm-multipath would only be interested in errors it made sense for a path to be failed over for (i.e. all transport and driver errors).
James
Quoted 17 lines · James Bottomley
Quoted 15 lines · Patrick Mansfield
Quoted 12 lines · Mike Christie
include/linux/blkdev.h +11
-1-#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 */
Quoted 9 lines
Quoted 1 line
Quoted 1 line
+};
Actually, I'd really be happier if these were a bitmap rather than an enumeration. That way we can divide them easily into cause (Driver, Device or Transport) and severity (fatal or retryable), so something like dm-multipath would only be interested in errors it made sense for a path to be failed over for (i.e. all transport and driver errors).
Would it be good then to also extend the fail fast flag to a bit map so dm-multipath can tell scsi that scsi should handle device errors?
Quoted 2 lines · Mike Christie
Would it be good then to also extend the fail fast flag to a bit map so dm-multipath can tell scsi that scsi should handle device errors?
You mean have a REQ_FASTFAIL_{DEV,XPRT,DRV}? The slight problem is that we're already closing in on the limit for request flags (we're already up to 26, this would take us to 28 with the maximum being 32) so I'll defer to Jens on that.
James