Re: Possibly wrong BIO usage in ide_multwrite

From: Christophe Saout
Date: Sun Jan 04 2004 - 23:07:05 EST


Hi Bartlomiej,

I've been playing with the code a bit.

I simple (but not really cleaner) solution to my original problem that
is minimal invasive is to use an unused field from struct request, in
this case nr_cbio_segments. It actually really counts the remaining
segments, only in rq->bio instead of rq->cbio. (The bio_kmap_irq
in ide_map_buffer prevents us from using anything else than rq->bio to
walk the request).

This segment count is then used to correctly restore the bi_idx fields
before ending requests instead of assuming they were zero.

(Well, I just also see that you could probably drop the scratch buffer
and just copy rq->cbio to rq->bio before ending the request... brrr,
no, that's just too ugly...)

BTW, what was ide_multwrite expected to return? These if clauses in
multwrite_intr are never executed.

Please don't shoot me for this proposal.


--- linux.orig/drivers/ide/ide-disk.c 2004-01-04 23:29:01.000000000 +0100
+++ linux/drivers/ide/ide-disk.c 2004-01-04 23:32:32.000000000 +0100
@@ -279,7 +279,7 @@
* all bvecs in this one.
*/
if (++bio->bi_idx >= bio->bi_vcnt) {
- bio->bi_idx = 0;
+ bio->bi_idx = bio->bi_vcnt - bio->nr_cbio_segments;
bio = bio->bi_next;
}

@@ -288,7 +288,8 @@
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;
}
}
@@ -312,6 +313,7 @@
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 +324,10 @@
* of the request
*/
if (rq->nr_sectors) {
- if (ide_multwrite(drive, drive->mult_count))
+ if (ide_multwrite(drive, drive->mult_count)) {
+ bio->bi_idx = bio->bi_vcnt - bio->nr_cbio_segments;
return ide_stopped;
+ }
ide_set_handler(drive, &multwrite_intr, WAIT_CMD, NULL);
return ide_started;
}
@@ -333,6 +337,7 @@
* we can end the original request.
*/
if (!rq->nr_sectors) { /* all done? */
+ bio->bi_idx = bio->bi_vcnt - bio->nr_cbio_segments;
rq = hwgroup->rq;
ide_end_request(drive, 1, rq->nr_sectors);
return ide_stopped;

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/