On Friday 21 January 2005 9:01 am, Kevin Corry wrote: > On Friday 21 January 2005 8:47 am, Lars Marowsky-Bree wrote: > > This looks like md on DM breakage, which Jens has just fixed in our > > kernel. I'm not sure whether he has submitted it upstream yet, but you > > can give it a try. > > > > Does the attached patch apply & fix the problem for you? > > > > If md resides on top of a driver using bio_clone() (such as dm), it > > will oops the kernel due to md submitting a botched bio that has a > > veclist but doesn't have bio->bi_max_vecs set. > > Is there a specific scenario that causes the kernel to oops if an MD device > is made of DM devices? EVMS has been using this kind of configuration for a > couple years, and we've never noticed a problem with it. Also, syrius > mentioned on IRC that this problem only started occurring with -ac10, and > that -ac8 worked fine. I'm checking out the diffs between those two > versions to see what else might have changed. Ok, here's the excerpt from the -ac10 patch that probably exposed the bug in MD. So it looks like a cloned bio no longer uses the original bio's bvec, which makes Lars' explination make a bit more sense. :) So, try Lars' patch with your -ac10 kernel and see if that fixes it. If so, we should forward that to Alan and make sure he includes it. I'll also check the latest -mm and -bk to see if these patches need to be merged upstream before 2.6.11 final. diff -Naurp linux-2.6.10-ac9/fs/bio.c linux-2.6.10-ac10/fs/bio.c --- linux-2.6.10-ac9/fs/bio.c 2004-12-24 15:35:00.000000000 -0600 +++ linux-2.6.10-ac10/fs/bio.c 2005-01-21 08:50:27.000000000 -0600 @@ -98,12 +98,7 @@ void bio_destructor(struct bio *bio) BIO_BUG_ON(pool_idx >= BIOVEC_NR_POOLS); - /* - * cloned bio doesn't own the veclist - */ - if (!bio_flagged(bio, BIO_CLONED)) - mempool_free(bio->bi_io_vec, bp->pool); - + mempool_free(bio->bi_io_vec, bp->pool); mempool_free(bio, bio_pool); } @@ -210,7 +205,9 @@ inline int bio_hw_segments(request_queue */ inline void __bio_clone(struct bio *bio, struct bio *bio_src) { - bio->bi_io_vec = bio_src->bi_io_vec; + request_queue_t *q = bdev_get_queue(bio_src->bi_bdev); + + memcpy(bio->bi_io_vec, bio_src->bi_io_vec, bio_src->bi_max_vecs * sizeof(struct bio_vec)); bio->bi_sector = bio_src->bi_sector; bio->bi_bdev = bio_src->bi_bdev; @@ -222,21 +219,9 @@ inline void __bio_clone(struct bio *bio, * for the clone */ bio->bi_vcnt = bio_src->bi_vcnt; - bio->bi_idx = bio_src->bi_idx; - if (bio_flagged(bio, BIO_SEG_VALID)) { - bio->bi_phys_segments = bio_src->bi_phys_segments; - bio->bi_hw_segments = bio_src->bi_hw_segments; - bio->bi_flags |= (1 << BIO_SEG_VALID); - } bio->bi_size = bio_src->bi_size; - - /* - * cloned bio does not own the bio_vec, so users cannot fiddle with - * it. clear bi_max_vecs and clear the BIO_POOL_BITS to make this - * apparent - */ - bio->bi_max_vecs = 0; - bio->bi_flags &= (BIO_POOL_MASK - 1); + bio_phys_segments(q, bio); + bio_hw_segments(q, bio); } /** @@ -248,7 +233,7 @@ inline void __bio_clone(struct bio *bio, */ struct bio *bio_clone(struct bio *bio, int gfp_mask) { - struct bio *b = bio_alloc(gfp_mask, 0); + struct bio *b = bio_alloc(gfp_mask, bio->bi_max_vecs); if (b) __bio_clone(b, bio); -- Kevin Corry kevcorry@xxxxxxxxxx http://evms.sourceforge.net/ - To unsubscribe from this list: send the line "unsubscribe linux-raid" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html