biodone panics
Peter Edwards
peadar.edwards at gmail.com
Wed Oct 5 06:14:01 PDT 2005
Take 2 for the biodone() panics:
acd_geom_start() implements request limiting by breaking up a large
request in the passed bio into a sequence of smaller ones. As each
request is created, acd_strategy is invoked to start the IO.
However, I think this IO can complete while still issuing the child
requests, leading to the parent being retired early. (ie, when a child
operation completes, it checks if its the last operation to complete,
and, if so, retires the parent: see g_std_done.)
The attached patch makes my qemu box much more reliable (I could crash
a qemu hosted system 100% with a "tar fc" of the 6.0-BETA bootonly ISO
without the patch, and it's gone through many iterations fine with it)
Any opinions/testing results welcome.
-------------- next part --------------
Index: sys/dev/ata/atapi-cd.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/atapi-cd.c,v
retrieving revision 1.179.2.1
diff -u -r1.179.2.1 atapi-cd.c
--- sys/dev/ata/atapi-cd.c 25 Aug 2005 16:21:05 -0000 1.179.2.1
+++ sys/dev/ata/atapi-cd.c 5 Oct 2005 12:01:33 -0000
@@ -760,7 +760,7 @@
}
else {
u_int pos, size = cdp->iomax - cdp->iomax % bp->bio_to->sectorsize;
- struct bio *bp2;
+ struct bio *bp2, *first, *cur, **next = &first;
for (pos = 0; pos < bp->bio_length; pos += size) {
if (!(bp2 = g_clone_bio(bp))) {
@@ -773,7 +773,13 @@
bp2->bio_data += pos;
bp2->bio_length = MIN(size, bp->bio_length - pos);
bp2->bio_pblkno = bp2->bio_offset / bp2->bio_to->sectorsize;
- acd_strategy(bp2);
+ *next = bp2;
+ next = (struct bio **)&bp2->bio_driver1;
+ }
+ *next = 0;
+ while ((cur = first) != 0) {
+ first = (struct bio *)cur->bio_driver1;
+ acd_strategy(cur);
}
}
}
More information about the freebsd-current
mailing list