]> git.hungrycats.org Git - linux/commitdiff
[PATCH] Fix raid "bio too big" failures
authorAndrew Morton <akpm@osdl.org>
Thu, 14 Aug 2003 17:06:18 +0000 (10:06 -0700)
committerLinus Torvalds <torvalds@home.osdl.org>
Thu, 14 Aug 2003 17:06:18 +0000 (10:06 -0700)
From: Neil Brown <neilb@cse.unsw.edu.au>

Fix "bio too big" problem with md

Whenever a device is attached to an md device, we make sure the sector
limits of the md device do not exceed those of the added device.

drivers/block/ll_rw_blk.c
drivers/md/linear.c
drivers/md/multipath.c
drivers/md/raid0.c
drivers/md/raid1.c
include/linux/blkdev.h

index 0764cd36b5790e0d37cf6e8974a3107a2c546c15..d7b2ede867604ad173bd526b31d0b0d2579590ef 100644 (file)
@@ -369,6 +369,20 @@ void blk_queue_hardsect_size(request_queue_t *q, unsigned short size)
        q->hardsect_size = size;
 }
 
+/**
+ * blk_queue_stack_limits - inherit underlying queue limits for stacked drivers
+ * @t: the stacking driver (top)
+ * @b:  the underlying device (bottom)
+ **/
+void blk_queue_stack_limits(request_queue_t *t, request_queue_t *b)
+{
+       t->max_sectors = min(t->max_sectors,b->max_sectors);
+       t->max_phys_segments = min(t->max_phys_segments,b->max_phys_segments);
+       t->max_hw_segments = min(t->max_hw_segments,b->max_hw_segments);
+       t->max_segment_size = min(t->max_segment_size,b->max_segment_size);
+       t->hardsect_size = max(t->hardsect_size,b->hardsect_size);
+}
+
 /**
  * blk_queue_segment_boundary - set boundary rules for segment merging
  * @q:  the request queue for the device
@@ -2804,6 +2818,7 @@ EXPORT_SYMBOL(blk_queue_max_phys_segments);
 EXPORT_SYMBOL(blk_queue_max_hw_segments);
 EXPORT_SYMBOL(blk_queue_max_segment_size);
 EXPORT_SYMBOL(blk_queue_hardsect_size);
+EXPORT_SYMBOL(blk_queue_stack_limits);
 EXPORT_SYMBOL(blk_queue_segment_boundary);
 EXPORT_SYMBOL(blk_queue_dma_alignment);
 EXPORT_SYMBOL(blk_rq_map_sg);
index afc5b3705a8c846239bc406ffad2b90874d0b001..9da446a143ec57e9e8a16e1817814f3a84e81ddb 100644 (file)
@@ -114,6 +114,8 @@ static int linear_run (mddev_t *mddev)
                }
 
                disk->rdev = rdev;
+               blk_queue_stack_limits(mddev->queue,
+                                      rdev->bdev->bd_disk->queue);
                disk->size = rdev->size;
                mddev->array_size += rdev->size;
 
index 8d04138441015ba2b8615ea0a7ef7a0290e6f196..4d19a4bd68089598f4546fd38cea75830d02af73 100644 (file)
@@ -272,6 +272,8 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
        for (path=0; path<mddev->raid_disks; path++) 
                if ((p=conf->multipaths+path)->rdev == NULL) {
                        p->rdev = rdev;
+                       blk_queue_stack_limits(mddev->queue,
+                                              rdev->bdev->bd_disk->queue);
                        conf->working_disks++;
                        rdev->raid_disk = path;
                        rdev->in_sync = 1;
@@ -409,6 +411,8 @@ 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);
                if (!rdev->faulty) 
                        conf->working_disks++;
        }
index a3a768082de2f185cdb6054fabcfc74c143674af..26b23d06e3d54dc1dcf748756727deae6a0c8dd4 100644 (file)
@@ -113,6 +113,8 @@ static int create_strip_zones (mddev_t *mddev)
                        goto abort;
                }
                zone->dev[j] = rdev1;
+               blk_queue_stack_limits(mddev->queue,
+                                      rdev1->bdev->bd_disk->queue);
                if (!smallest || (rdev1->size <smallest->size))
                        smallest = rdev1;
                cnt++;
@@ -293,7 +295,6 @@ static int raid0_run (mddev_t *mddev)
                conf->hash_spacing++;
        }
 
-       blk_queue_max_sectors(mddev->queue, mddev->chunk_size >> 9);
        blk_queue_merge_bvec(mddev->queue, raid0_mergeable_bvec);
        return 0;
 
index 56e6030ec2f652af71b9a31b9b59e65257c9a924..cb7acbfb87cf7dec5803a7f1a8893e67f07e701f 100644 (file)
@@ -678,6 +678,8 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
        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);
                        p->head_position = 0;
                        rdev->raid_disk = mirror;
                        found = 1;
@@ -1076,6 +1078,8 @@ 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);
                disk->head_position = 0;
                if (!rdev->faulty && rdev->in_sync)
                        conf->working_disks++;
index 2f272b79d9e04da6db71317463b0ca2e4922877f..a5c8772b646396e064219af65b05c4052b7058c6 100644 (file)
@@ -547,6 +547,7 @@ extern void blk_queue_max_phys_segments(request_queue_t *, unsigned short);
 extern void blk_queue_max_hw_segments(request_queue_t *, unsigned short);
 extern void blk_queue_max_segment_size(request_queue_t *, unsigned int);
 extern void blk_queue_hardsect_size(request_queue_t *, unsigned short);
+extern void blk_queue_stack_limits(request_queue_t *t, request_queue_t *b);
 extern void blk_queue_segment_boundary(request_queue_t *, unsigned long);
 extern void blk_queue_prep_rq(request_queue_t *, prep_rq_fn *pfn);
 extern void blk_queue_merge_bvec(request_queue_t *, merge_bvec_fn *);