From: Christophe Saout The intent of these are to clarify the meaning of the bio fields in the bi_end_io function (since we are already mostly there). After these small modifications bio->bi_idx and the corresponding bio_iovec(bio)->bv_offset point to the beginning of the completed data, together with the nr_bytes argument you know exactly what data was finished, e.g. when you can't track it otherwise (or it would be unnecessary expensive). Apart from that it's a nice-to-have. The first mini-patch moves the update of bio_iovec(bio)->bv_offset and ->bv_len after the call of bi_end_io where bi_idx gets updated so they get updated together. Ok with Jens. The second part of the patch modifies the multwrite hack in PIO non- taskfile ide disk code. It modifies the bi_idx field to walk the bios and doesn't reset it correctly before ending the request. The patch uses the segment counter in the request field to correctly restore the bi_idx field before ending the request. Can't possibly break anything since it's working on the local request copy ("scratchpad") anyway. Also does this in legacy/pdc4030.c (similar code). The code modified here is going to die anyway any trying to fix it would be too invasive. Ok with Bartlomiej. drivers/block/ll_rw_blk.c | 6 +++--- drivers/ide/ide-disk.c | 25 ++++++++++--------------- drivers/ide/legacy/pdc4030.c | 18 ++++++++++++++++-- 3 files changed, 29 insertions(+), 20 deletions(-) diff -puN drivers/block/ll_rw_blk.c~bio_endio-clarifications drivers/block/ll_rw_blk.c --- 25/drivers/block/ll_rw_blk.c~bio_endio-clarifications 2004-01-06 09:26:05.000000000 -0800 +++ 25-akpm/drivers/block/ll_rw_blk.c 2004-01-06 09:26:05.000000000 -0800 @@ -2505,8 +2505,6 @@ static int __end_that_request_first(stru * not a complete bvec done */ if (unlikely(nbytes > nr_bytes)) { - bio_iovec_idx(bio, idx)->bv_offset += nr_bytes; - bio_iovec_idx(bio, idx)->bv_len -= nr_bytes; bio_nbytes += nr_bytes; total_bytes += nr_bytes; break; @@ -2542,7 +2540,9 @@ static int __end_that_request_first(stru */ if (bio_nbytes) { bio_endio(bio, bio_nbytes, error); - req->bio->bi_idx += next_idx; + bio->bi_idx += next_idx; + bio_iovec(bio)->bv_offset += nr_bytes; + bio_iovec(bio)->bv_len -= nr_bytes; } blk_recalc_rq_sectors(req, total_bytes >> 9); diff -puN drivers/ide/ide-disk.c~bio_endio-clarifications drivers/ide/ide-disk.c --- 25/drivers/ide/ide-disk.c~bio_endio-clarifications 2004-01-06 09:26:05.000000000 -0800 +++ 25-akpm/drivers/ide/ide-disk.c 2004-01-06 09:26:05.000000000 -0800 @@ -251,7 +251,7 @@ static ide_startstop_t write_intr (ide_d * is shorter or smaller than the BH segment then we should be OKAY. * This is only valid if we can rewind the rq->current_nr_sectors counter. */ -int ide_multwrite (ide_drive_t *drive, unsigned int mcount) +void ide_multwrite (ide_drive_t *drive, unsigned int mcount) { ide_hwgroup_t *hwgroup = HWGROUP(drive); struct request *rq = &hwgroup->wrq; @@ -279,7 +279,7 @@ int ide_multwrite (ide_drive_t *drive, u * all bvecs in this one. */ if (++bio->bi_idx >= bio->bi_vcnt) { - bio->bi_idx = 0; + bio->bi_idx = bio->bi_vcnt - rq->nr_cbio_segments; bio = bio->bi_next; } @@ -288,7 +288,8 @@ int ide_multwrite (ide_drive_t *drive, u mcount = 0; } else { rq->bio = bio; - rq->current_nr_sectors = bio_iovec(bio)->bv_len >> 9; + rq->nr_cbio_segments = bio_segments(bio); + rq->current_nr_sectors = bio_cur_sectors(bio); rq->hard_cur_sectors = rq->current_nr_sectors; } } @@ -300,8 +301,6 @@ int ide_multwrite (ide_drive_t *drive, u taskfile_output_data(drive, buffer, nsect<<7); ide_unmap_buffer(rq, buffer, &flags); } while (mcount); - - return 0; } /* @@ -312,6 +311,7 @@ static ide_startstop_t multwrite_intr (i ide_hwgroup_t *hwgroup = HWGROUP(drive); ide_hwif_t *hwif = HWIF(drive); struct request *rq = &hwgroup->wrq; + struct bio *bio = rq->bio; u8 stat; stat = hwif->INB(IDE_STATUS_REG); @@ -322,8 +322,7 @@ static ide_startstop_t multwrite_intr (i * of the request */ if (rq->nr_sectors) { - if (ide_multwrite(drive, drive->mult_count)) - return ide_stopped; + ide_multwrite(drive, drive->mult_count); ide_set_handler(drive, &multwrite_intr, WAIT_CMD, NULL); return ide_started; } @@ -333,14 +332,17 @@ static ide_startstop_t multwrite_intr (i * we can end the original request. */ if (!rq->nr_sectors) { /* all done? */ + bio->bi_idx = bio->bi_vcnt - rq->nr_cbio_segments; rq = hwgroup->rq; ide_end_request(drive, 1, rq->nr_sectors); return ide_stopped; } } + bio->bi_idx = bio->bi_vcnt - rq->nr_cbio_segments; /* the original code did this here (?) */ return ide_stopped; } + bio->bi_idx = bio->bi_vcnt - rq->nr_cbio_segments; return DRIVER(drive)->error(drive, "multwrite_intr", stat); } @@ -519,14 +521,7 @@ ide_startstop_t __ide_do_rw_disk (ide_dr */ hwgroup->wrq = *rq; /* scratchpad */ ide_set_handler(drive, &multwrite_intr, WAIT_CMD, NULL); - if (ide_multwrite(drive, drive->mult_count)) { - unsigned long flags; - spin_lock_irqsave(&ide_lock, flags); - hwgroup->handler = NULL; - del_timer(&hwgroup->timer); - spin_unlock_irqrestore(&ide_lock, flags); - return ide_stopped; - } + ide_multwrite(drive, drive->mult_count); } else { unsigned long flags; char *to = ide_map_buffer(rq, &flags); diff -puN drivers/ide/legacy/pdc4030.c~bio_endio-clarifications drivers/ide/legacy/pdc4030.c --- 25/drivers/ide/legacy/pdc4030.c~bio_endio-clarifications 2004-01-06 09:26:05.000000000 -0800 +++ 25-akpm/drivers/ide/legacy/pdc4030.c 2004-01-06 09:26:05.000000000 -0800 @@ -443,7 +443,12 @@ read_next: static ide_startstop_t promise_complete_pollfunc(ide_drive_t *drive) { ide_hwgroup_t *hwgroup = HWGROUP(drive); +#ifdef CONFIG_IDE_TASKFILE_IO struct request *rq = hwgroup->rq; +#else + struct request *rq = &hwgroup->wrq; + struct bio *bio = rq->bio; +#endif if ((HWIF(drive)->INB(IDE_STATUS_REG)) & BUSY_STAT) { if (time_before(jiffies, hwgroup->poll_timeout)) { @@ -472,6 +477,8 @@ static ide_startstop_t promise_complete_ while (rq->bio != rq->cbio) (void) DRIVER(drive)->end_request(drive, 1, bio_sectors(rq->bio)); #else + bio->bi_idx = bio->bi_vcnt - rq->nr_cbio_segments; + rq = hwgroup->rq; DRIVER(drive)->end_request(drive, 1, rq->hard_nr_sectors); #endif return ide_stopped; @@ -530,7 +537,7 @@ static void promise_multwrite (ide_drive * all bvecs in this one. */ if (++bio->bi_idx >= bio->bi_vcnt) { - bio->bi_idx = 0; + bio->bi_idx = bio->bi_vcnt - rq->nr_cbio_segments; bio = bio->bi_next; } @@ -539,7 +546,8 @@ static void promise_multwrite (ide_drive mcount = 0; } else { rq->bio = bio; - rq->current_nr_sectors = bio_iovec(bio)->bv_len >> 9; + rq->nr_cbio_segments = bio_segments(bio); + rq->current_nr_sectors = bio_cur_sectors(bio); rq->hard_cur_sectors = rq->current_nr_sectors; } } @@ -561,6 +569,9 @@ static ide_startstop_t promise_write_pol ide_hwgroup_t *hwgroup = HWGROUP(drive); #ifdef CONFIG_IDE_TASKFILE_IO struct request *rq = hwgroup->rq; +#else + struct request *rq = &hwgroup->wrq; + struct bio *bio = rq->bio; #endif if (HWIF(drive)->INB(IDE_NSECTOR_REG) != 0) { @@ -575,6 +586,9 @@ static ide_startstop_t promise_write_pol } hwgroup->poll_timeout = 0; printk(KERN_ERR "%s: write timed-out!\n",drive->name); +#ifndef CONFIG_IDE_TASKFILE_IO + bio->bi_idx = bio->bi_vcnt - rq->nr_cbio_segments; +#endif return DRIVER(drive)->error(drive, "write timeout", HWIF(drive)->INB(IDE_STATUS_REG)); } _