summaryrefslogtreecommitdiffstats
path: root/sys/dev/ata/atapi-cd.c
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/dev/ata/atapi-cd.c
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/dev/ata/atapi-cd.c')
-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