Fix aggregating geoms for BIO_SPEEDUP.
If the bio was split into several bios going down, completion computes bio_completed of the original bio as sum of the bio_completes of the splits. For BIO_SETUP, bio_length means something different than the length. it is the requested speedup amount, and is duplicated into the splits, which is in fact reasonable, since we cannot know how the previous activity was distributed among subordinate geoms. Obviously, the sum of n bio_length is greater than bio_length for n > 1, which triggers assert that bio_length >= bio_completed for e.g. geom_stripe and geom_raid3. Fix this by reassigning bio_completed from bio_length for completed BIO_SPEEDED, I do not think it really mattters what we return in bio_completed. Reported and tested by: pho Reviewed by: imp MFC after: 1 week Differential revision: https://reviews.freebsd.org/D23380
This commit is contained in:
parent
18dae1317e
commit
557bedea7b
@ -1134,8 +1134,11 @@ g_std_done(struct bio *bp)
|
||||
bp2->bio_completed += bp->bio_completed;
|
||||
g_destroy_bio(bp);
|
||||
bp2->bio_inbed++;
|
||||
if (bp2->bio_children == bp2->bio_inbed)
|
||||
if (bp2->bio_children == bp2->bio_inbed) {
|
||||
if (bp2->bio_cmd == BIO_SPEEDUP)
|
||||
bp2->bio_completed = bp2->bio_length;
|
||||
g_io_deliver(bp2, bp2->bio_error);
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX: maybe this is only g_slice_spoiled */
|
||||
|
@ -298,6 +298,8 @@ g_stripe_done(struct bio *bp)
|
||||
mtx_unlock(&sc->sc_lock);
|
||||
if (pbp->bio_driver1 != NULL)
|
||||
uma_zfree(g_stripe_zone, pbp->bio_driver1);
|
||||
if (bp->bio_cmd == BIO_SPEEDUP)
|
||||
pbp->bio_completed = pbp->bio_length;
|
||||
g_io_deliver(pbp, pbp->bio_error);
|
||||
} else
|
||||
mtx_unlock(&sc->sc_lock);
|
||||
|
Loading…
Reference in New Issue
Block a user