Commit d2e45eac authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Fix raid "bio too big" failures

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.
parent 94e77119
...@@ -369,6 +369,20 @@ void blk_queue_hardsect_size(request_queue_t *q, unsigned short size) ...@@ -369,6 +369,20 @@ void blk_queue_hardsect_size(request_queue_t *q, unsigned short size)
q->hardsect_size = 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 * blk_queue_segment_boundary - set boundary rules for segment merging
* @q: the request queue for the device * @q: the request queue for the device
...@@ -2804,6 +2818,7 @@ EXPORT_SYMBOL(blk_queue_max_phys_segments); ...@@ -2804,6 +2818,7 @@ EXPORT_SYMBOL(blk_queue_max_phys_segments);
EXPORT_SYMBOL(blk_queue_max_hw_segments); EXPORT_SYMBOL(blk_queue_max_hw_segments);
EXPORT_SYMBOL(blk_queue_max_segment_size); EXPORT_SYMBOL(blk_queue_max_segment_size);
EXPORT_SYMBOL(blk_queue_hardsect_size); EXPORT_SYMBOL(blk_queue_hardsect_size);
EXPORT_SYMBOL(blk_queue_stack_limits);
EXPORT_SYMBOL(blk_queue_segment_boundary); EXPORT_SYMBOL(blk_queue_segment_boundary);
EXPORT_SYMBOL(blk_queue_dma_alignment); EXPORT_SYMBOL(blk_queue_dma_alignment);
EXPORT_SYMBOL(blk_rq_map_sg); EXPORT_SYMBOL(blk_rq_map_sg);
......
...@@ -114,6 +114,8 @@ static int linear_run (mddev_t *mddev) ...@@ -114,6 +114,8 @@ static int linear_run (mddev_t *mddev)
} }
disk->rdev = rdev; disk->rdev = rdev;
blk_queue_stack_limits(mddev->queue,
rdev->bdev->bd_disk->queue);
disk->size = rdev->size; disk->size = rdev->size;
mddev->array_size += rdev->size; mddev->array_size += rdev->size;
......
...@@ -272,6 +272,8 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) ...@@ -272,6 +272,8 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
for (path=0; path<mddev->raid_disks; path++) for (path=0; path<mddev->raid_disks; path++)
if ((p=conf->multipaths+path)->rdev == NULL) { if ((p=conf->multipaths+path)->rdev == NULL) {
p->rdev = rdev; p->rdev = rdev;
blk_queue_stack_limits(mddev->queue,
rdev->bdev->bd_disk->queue);
conf->working_disks++; conf->working_disks++;
rdev->raid_disk = path; rdev->raid_disk = path;
rdev->in_sync = 1; rdev->in_sync = 1;
...@@ -409,6 +411,8 @@ static int multipath_run (mddev_t *mddev) ...@@ -409,6 +411,8 @@ static int multipath_run (mddev_t *mddev)
disk = conf->multipaths + disk_idx; disk = conf->multipaths + disk_idx;
disk->rdev = rdev; disk->rdev = rdev;
blk_queue_stack_limits(mddev->queue,
rdev->bdev->bd_disk->queue);
if (!rdev->faulty) if (!rdev->faulty)
conf->working_disks++; conf->working_disks++;
} }
......
...@@ -113,6 +113,8 @@ static int create_strip_zones (mddev_t *mddev) ...@@ -113,6 +113,8 @@ static int create_strip_zones (mddev_t *mddev)
goto abort; goto abort;
} }
zone->dev[j] = rdev1; zone->dev[j] = rdev1;
blk_queue_stack_limits(mddev->queue,
rdev1->bdev->bd_disk->queue);
if (!smallest || (rdev1->size <smallest->size)) if (!smallest || (rdev1->size <smallest->size))
smallest = rdev1; smallest = rdev1;
cnt++; cnt++;
...@@ -293,7 +295,6 @@ static int raid0_run (mddev_t *mddev) ...@@ -293,7 +295,6 @@ static int raid0_run (mddev_t *mddev)
conf->hash_spacing++; conf->hash_spacing++;
} }
blk_queue_max_sectors(mddev->queue, mddev->chunk_size >> 9);
blk_queue_merge_bvec(mddev->queue, raid0_mergeable_bvec); blk_queue_merge_bvec(mddev->queue, raid0_mergeable_bvec);
return 0; return 0;
......
...@@ -678,6 +678,8 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) ...@@ -678,6 +678,8 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
for (mirror=0; mirror < mddev->raid_disks; mirror++) for (mirror=0; mirror < mddev->raid_disks; mirror++)
if ( !(p=conf->mirrors+mirror)->rdev) { if ( !(p=conf->mirrors+mirror)->rdev) {
p->rdev = rdev; p->rdev = rdev;
blk_queue_stack_limits(mddev->queue,
rdev->bdev->bd_disk->queue);
p->head_position = 0; p->head_position = 0;
rdev->raid_disk = mirror; rdev->raid_disk = mirror;
found = 1; found = 1;
...@@ -1076,6 +1078,8 @@ static int run(mddev_t *mddev) ...@@ -1076,6 +1078,8 @@ static int run(mddev_t *mddev)
disk = conf->mirrors + disk_idx; disk = conf->mirrors + disk_idx;
disk->rdev = rdev; disk->rdev = rdev;
blk_queue_stack_limits(mddev->queue,
rdev->bdev->bd_disk->queue);
disk->head_position = 0; disk->head_position = 0;
if (!rdev->faulty && rdev->in_sync) if (!rdev->faulty && rdev->in_sync)
conf->working_disks++; conf->working_disks++;
......
...@@ -547,6 +547,7 @@ extern void blk_queue_max_phys_segments(request_queue_t *, unsigned short); ...@@ -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_hw_segments(request_queue_t *, unsigned short);
extern void blk_queue_max_segment_size(request_queue_t *, unsigned int); 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_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_segment_boundary(request_queue_t *, unsigned long);
extern void blk_queue_prep_rq(request_queue_t *, prep_rq_fn *pfn); 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 *); extern void blk_queue_merge_bvec(request_queue_t *, merge_bvec_fn *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment