From: NeilBrown As no md personalities honour the merge_bvec_fn of underlying devices, we must make sure never to submit a bio larger than 1 page when a merge_bvec_fn is defined. raid5 already does this (it never submits bios larger than one page). With this patch, all other raid personalities limit their max_sectors when a merge_bvec_fn is present. 25-akpm/drivers/md/linear.c | 9 +++++++++ 25-akpm/drivers/md/multipath.c | 19 +++++++++++++++++++ 25-akpm/drivers/md/raid0.c | 10 ++++++++++ 25-akpm/drivers/md/raid1.c | 18 ++++++++++++++++++ 4 files changed, 56 insertions(+) diff -puN drivers/md/linear.c~md-1-limit_max_sectors drivers/md/linear.c --- 25/drivers/md/linear.c~md-1-limit_max_sectors Mon Nov 24 12:49:55 2003 +++ 25-akpm/drivers/md/linear.c Mon Nov 24 12:49:55 2003 @@ -113,8 +113,17 @@ static int linear_run (mddev_t *mddev) } disk->rdev = rdev; + blk_queue_stack_limits(mddev->queue, rdev->bdev->bd_disk->queue); + /* as we don't honour merge_bvec_fn, we must never risk + * violating it, so limit ->max_sector to one PAGE, as + * a one page request is never in violation. + */ + if (rdev->bdev->bd_disk->queue->merge_bvec_fn && + mddev->queue->max_sectors > (PAGE_SIZE>>9)) + mddev->queue->max_sectors = (PAGE_SIZE>>9); + disk->size = rdev->size; mddev->array_size += rdev->size; diff -puN drivers/md/multipath.c~md-1-limit_max_sectors drivers/md/multipath.c --- 25/drivers/md/multipath.c~md-1-limit_max_sectors Mon Nov 24 12:49:55 2003 +++ 25-akpm/drivers/md/multipath.c Mon Nov 24 12:49:55 2003 @@ -273,6 +273,17 @@ static int multipath_add_disk(mddev_t *m p->rdev = rdev; blk_queue_stack_limits(mddev->queue, rdev->bdev->bd_disk->queue); + + /* as we don't honour merge_bvec_fn, we must never risk + * violating it, so limit ->max_sector to one PAGE, as + * a one page request is never in violation. + * (Note: it is very unlikely that a device with + * merge_bvec_fn will be involved in multipath.) + */ + if (rdev->bdev->bd_disk->queue->merge_bvec_fn && + mddev->queue->max_sectors > (PAGE_SIZE>>9)) + mddev->queue->max_sectors = (PAGE_SIZE>>9); + conf->working_disks++; rdev->raid_disk = path; rdev->in_sync = 1; @@ -410,8 +421,16 @@ static int multipath_run (mddev_t *mddev disk = conf->multipaths + disk_idx; disk->rdev = rdev; + blk_queue_stack_limits(mddev->queue, rdev->bdev->bd_disk->queue); + /* as we don't honour merge_bvec_fn, we must never risk + * violating it, not that we ever expect a device with + * a merge_bvec_fn to be involved in multipath */ + if (rdev->bdev->bd_disk->queue->merge_bvec_fn && + mddev->queue->max_sectors > (PAGE_SIZE>>9)) + mddev->queue->max_sectors = (PAGE_SIZE>>9); + if (!rdev->faulty) conf->working_disks++; } diff -puN drivers/md/raid0.c~md-1-limit_max_sectors drivers/md/raid0.c --- 25/drivers/md/raid0.c~md-1-limit_max_sectors Mon Nov 24 12:49:55 2003 +++ 25-akpm/drivers/md/raid0.c Mon Nov 24 12:49:55 2003 @@ -112,8 +112,18 @@ static int create_strip_zones (mddev_t * goto abort; } zone->dev[j] = rdev1; + blk_queue_stack_limits(mddev->queue, rdev1->bdev->bd_disk->queue); + /* as we don't honour merge_bvec_fn, we must never risk + * violating it, so limit ->max_sector to one PAGE, as + * a one page request is never in violation. + */ + + if (rdev1->bdev->bd_disk->queue->merge_bvec_fn && + mddev->queue->max_sectors > (PAGE_SIZE>>9)) + mddev->queue->max_sectors = (PAGE_SIZE>>9); + if (!smallest || (rdev1->size size)) smallest = rdev1; cnt++; diff -puN drivers/md/raid1.c~md-1-limit_max_sectors drivers/md/raid1.c --- 25/drivers/md/raid1.c~md-1-limit_max_sectors Mon Nov 24 12:49:55 2003 +++ 25-akpm/drivers/md/raid1.c Mon Nov 24 12:49:55 2003 @@ -677,8 +677,17 @@ static int raid1_add_disk(mddev_t *mddev for (mirror=0; mirror < mddev->raid_disks; mirror++) if ( !(p=conf->mirrors+mirror)->rdev) { p->rdev = rdev; + blk_queue_stack_limits(mddev->queue, rdev->bdev->bd_disk->queue); + /* as we don't honour merge_bvec_fn, we must never risk + * violating it, so limit ->max_sector to one PAGE, as + * a one page request is never in violation. + */ + if (rdev->bdev->bd_disk->queue->merge_bvec_fn && + mddev->queue->max_sectors > (PAGE_SIZE>>9)) + mddev->queue->max_sectors = (PAGE_SIZE>>9); + p->head_position = 0; rdev->raid_disk = mirror; found = 1; @@ -1077,8 +1086,17 @@ static int run(mddev_t *mddev) disk = conf->mirrors + disk_idx; disk->rdev = rdev; + blk_queue_stack_limits(mddev->queue, rdev->bdev->bd_disk->queue); + /* as we don't honour merge_bvec_fn, we must never risk + * violating it, so limit ->max_sector to one PAGE, as + * a one page request is never in violation. + */ + if (rdev->bdev->bd_disk->queue->merge_bvec_fn && + mddev->queue->max_sectors > (PAGE_SIZE>>9)) + mddev->queue->max_sectors = (PAGE_SIZE>>9); + disk->head_position = 0; if (!rdev->faulty && rdev->in_sync) conf->working_disks++; _