summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorpeadar <peadar@FreeBSD.org>2005-10-09 21:11:05 +0000
committerpeadar <peadar@FreeBSD.org>2005-10-09 21:11:05 +0000
commit60fb64c30e9b2c543b4e89c17d7ee8d4570e9dcc (patch)
tree48f1adfdb334dd861d074d9c38e23b6c53d6c5c0 /sys
parent6210e62129dd5f6332e7445b51c62f600aeb5c74 (diff)
downloadFreeBSD-src-60fb64c30e9b2c543b4e89c17d7ee8d4570e9dcc.zip
FreeBSD-src-60fb64c30e9b2c543b4e89c17d7ee8d4570e9dcc.tar.gz
When breaking up a large request into smaller ones for the strategy
routine, create all the child bio objects before starting the requests, rather than starting them as created. This closes a race whereby some number of child operations could complete before the rest were ever created, and prematurely freeing the parent bio. This fixes the panics installing in VMWare and qemu
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ata/atapi-cd.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c
index 16a188a..f737fe3 100644
--- a/sys/dev/ata/atapi-cd.c
+++ b/sys/dev/ata/atapi-cd.c
@@ -760,7 +760,7 @@ acd_geom_start(struct bio *bp)
}
else {
u_int pos, size = cdp->iomax - cdp->iomax % bp->bio_to->sectorsize;
- struct bio *bp2;
+ struct bio *bp2, *first, **next = &first;
for (pos = 0; pos < bp->bio_length; pos += size) {
if (!(bp2 = g_clone_bio(bp))) {
@@ -773,6 +773,12 @@ acd_geom_start(struct bio *bp)
bp2->bio_data += pos;
bp2->bio_length = MIN(size, bp->bio_length - pos);
bp2->bio_pblkno = bp2->bio_offset / bp2->bio_to->sectorsize;
+ *next = bp2;
+ next = (struct bio **)&bp2->bio_driver1;
+ }
+ *next = NULL;
+ while ((bp2 = first) != NULL) {
+ first = (struct bio *)bp2->bio_driver1;
acd_strategy(bp2);
}
}
OpenPOWER on IntegriCloud