Compile failure (gcc 2.96 bug?). 2.5.42 raid0.c
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
"David" == David Mansfield <[email protected]> writes:
David> Trying to compile 2.5.42 I encountered the following error, David> which looks a lot like a GCC bug. I did a 'make mrproper; make David> oldconfig; make bzImage' and it still failed.
(lots of gcc internal structure dump deleted here)
Yes it's a GCC optimiser bug. I'm surprised I didn't see it: I tried a whole heap of different compilers on that code, and had problems only on the earlier similar code in raid0_run().
I didn't try redhat's compilers (I run debian) but didn't expect the behaviour to be that different.
Anyway, please apply this patch (which also fixes the chunk overlap problems).
drivers/md/raid0.c +30 -9
@@ -162,6 +162,29 @@return 1 ; } +/** +* raid0_mergeable_bvec -- tell bio layer if a two requests can be merged +* @q: request queue +* @bio: the buffer head that's been built up so far +* @biovec: the request that could be merged to it. +* +* Return 1 if the merge is not permitted (because the +* result would cross a chunk boundary), 0 otherwise. +*/ +static int raid0_mergeable_bvec (request_queue_t *q,struct bio *bio,struct bio_vec *biovec) +{ +mddev_t *mddev = q->queuedata; +sector_t block; +unsigned int chunk_size; +unsigned int bio_sz; + + chunk_size = mddev->chunk_size >>10 ; + block = bio->bi_sector >>1 ; + bio_sz = (bio->bi_size + biovec->bv_len) >>10 ; + +return chunk_size < ((block & (chunk_size -1 )) + bio_sz); +} +static int raid0_run (mddev_t *mddev) {unsigned cur=0 , i=0 , nb_zone;
@@ -233,6 +256,8 @@ conf->hash_table[i++].zone1 = conf->strip_zone + cur; size -= (conf->smallest->size - zone0_size); } +blk_queue_max_sectors (&mddev->queue, mddev->chunk_size >>9 ); +blk_queue_merge_bvec (&mddev->queue, raid0_mergeable_bvec);return 0 ; out_free_zone_conf:
@@ -262,13 +287,6 @@return 0 ; } -/* -* FIXME - We assume some things here : -* - requested buffers NEVER bigger than chunk size, -* - requested buffers NEVER cross stripes limits. -* Of course, those facts may not be valid anymore (and surely won't...) -* Hey guys, there's some work out there ;-) -*/ static int raid0_make_request (request_queue_t *q,struct bio *bio) {mddev_t *mddev = q->queuedata;
@@ -286,13 +304,16 @@ { +#if __GNUC__ <3 + volatile +#endif sector_t x = block;sector_div (x, (unsigned long )conf->smallest->size); hash = conf->hash_table + x; } -/* Sanity check */ -if (chunk_size < (block & (chunk_size -1 )) + (bio->bi_size >>10 )) +/* Sanity check -- queue functions should prevent this happening */ +if (unlikely (chunk_size < (block & (chunk_size -1 )) + (bio->bi_size >>10 ))) goto bad_map;if (!hash)