diff options
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/raid10.c | 67 |
1 files changed, 49 insertions, 18 deletions
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 1c90005ab343..f102e88fc785 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -3253,26 +3253,64 @@ static void calc_sectors(struct r10conf *conf, sector_t size) | |||
3253 | } | 3253 | } |
3254 | } | 3254 | } |
3255 | 3255 | ||
3256 | enum geo_type {geo_new, geo_old, geo_start}; | ||
3257 | static int setup_geo(struct geom *geo, struct mddev *mddev, enum geo_type new) | ||
3258 | { | ||
3259 | int nc, fc, fo; | ||
3260 | int layout, chunk, disks; | ||
3261 | switch (new) { | ||
3262 | case geo_old: | ||
3263 | layout = mddev->layout; | ||
3264 | chunk = mddev->chunk_sectors; | ||
3265 | disks = mddev->raid_disks - mddev->delta_disks; | ||
3266 | break; | ||
3267 | case geo_new: | ||
3268 | layout = mddev->new_layout; | ||
3269 | chunk = mddev->new_chunk_sectors; | ||
3270 | disks = mddev->raid_disks; | ||
3271 | break; | ||
3272 | default: /* avoid 'may be unused' warnings */ | ||
3273 | case geo_start: /* new when starting reshape - raid_disks not | ||
3274 | * updated yet. */ | ||
3275 | layout = mddev->new_layout; | ||
3276 | chunk = mddev->new_chunk_sectors; | ||
3277 | disks = mddev->raid_disks + mddev->delta_disks; | ||
3278 | break; | ||
3279 | } | ||
3280 | if (layout >> 17) | ||
3281 | return -1; | ||
3282 | if (chunk < (PAGE_SIZE >> 9) || | ||
3283 | !is_power_of_2(chunk)) | ||
3284 | return -2; | ||
3285 | nc = layout & 255; | ||
3286 | fc = (layout >> 8) & 255; | ||
3287 | fo = layout & (1<<16); | ||
3288 | geo->raid_disks = disks; | ||
3289 | geo->near_copies = nc; | ||
3290 | geo->far_copies = fc; | ||
3291 | geo->far_offset = fo; | ||
3292 | geo->chunk_mask = chunk - 1; | ||
3293 | geo->chunk_shift = ffz(~chunk); | ||
3294 | return nc*fc; | ||
3295 | } | ||
3296 | |||
3256 | static struct r10conf *setup_conf(struct mddev *mddev) | 3297 | static struct r10conf *setup_conf(struct mddev *mddev) |
3257 | { | 3298 | { |
3258 | struct r10conf *conf = NULL; | 3299 | struct r10conf *conf = NULL; |
3259 | int nc, fc, fo; | ||
3260 | int err = -EINVAL; | 3300 | int err = -EINVAL; |
3301 | struct geom geo; | ||
3302 | int copies; | ||
3303 | |||
3304 | copies = setup_geo(&geo, mddev, geo_new); | ||
3261 | 3305 | ||
3262 | if (mddev->new_chunk_sectors < (PAGE_SIZE >> 9) || | 3306 | if (copies == -2) { |
3263 | !is_power_of_2(mddev->new_chunk_sectors)) { | ||
3264 | printk(KERN_ERR "md/raid10:%s: chunk size must be " | 3307 | printk(KERN_ERR "md/raid10:%s: chunk size must be " |
3265 | "at least PAGE_SIZE(%ld) and be a power of 2.\n", | 3308 | "at least PAGE_SIZE(%ld) and be a power of 2.\n", |
3266 | mdname(mddev), PAGE_SIZE); | 3309 | mdname(mddev), PAGE_SIZE); |
3267 | goto out; | 3310 | goto out; |
3268 | } | 3311 | } |
3269 | 3312 | ||
3270 | nc = mddev->new_layout & 255; | 3313 | if (copies < 2 || copies > mddev->raid_disks) { |
3271 | fc = (mddev->new_layout >> 8) & 255; | ||
3272 | fo = mddev->new_layout & (1<<16); | ||
3273 | |||
3274 | if ((nc*fc) <2 || (nc*fc) > mddev->raid_disks || | ||
3275 | (mddev->new_layout >> 17)) { | ||
3276 | printk(KERN_ERR "md/raid10:%s: unsupported raid10 layout: 0x%8x\n", | 3314 | printk(KERN_ERR "md/raid10:%s: unsupported raid10 layout: 0x%8x\n", |
3277 | mdname(mddev), mddev->new_layout); | 3315 | mdname(mddev), mddev->new_layout); |
3278 | goto out; | 3316 | goto out; |
@@ -3292,15 +3330,8 @@ static struct r10conf *setup_conf(struct mddev *mddev) | |||
3292 | if (!conf->tmppage) | 3330 | if (!conf->tmppage) |
3293 | goto out; | 3331 | goto out; |
3294 | 3332 | ||
3295 | 3333 | conf->geo = geo; | |
3296 | conf->geo.raid_disks = mddev->raid_disks; | 3334 | conf->copies = copies; |
3297 | conf->geo.near_copies = nc; | ||
3298 | conf->geo.far_copies = fc; | ||
3299 | conf->copies = nc*fc; | ||
3300 | conf->geo.far_offset = fo; | ||
3301 | conf->geo.chunk_mask = mddev->new_chunk_sectors - 1; | ||
3302 | conf->geo.chunk_shift = ffz(~mddev->new_chunk_sectors); | ||
3303 | |||
3304 | conf->r10bio_pool = mempool_create(NR_RAID10_BIOS, r10bio_pool_alloc, | 3335 | conf->r10bio_pool = mempool_create(NR_RAID10_BIOS, r10bio_pool_alloc, |
3305 | r10bio_pool_free, conf); | 3336 | r10bio_pool_free, conf); |
3306 | if (!conf->r10bio_pool) | 3337 | if (!conf->r10bio_pool) |