From: NeilBrown <neilb@cse.unsw.edu.au>

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 <smallest->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++;

_