diff options
-rw-r--r-- | drivers/md/raid10.c | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 23de2144ee13..96f365968306 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -39,6 +39,7 @@ | |||
39 | * far_copies (stored in second byte of layout) | 39 | * far_copies (stored in second byte of layout) |
40 | * far_offset (stored in bit 16 of layout ) | 40 | * far_offset (stored in bit 16 of layout ) |
41 | * use_far_sets (stored in bit 17 of layout ) | 41 | * use_far_sets (stored in bit 17 of layout ) |
42 | * use_far_sets_bugfixed (stored in bit 18 of layout ) | ||
42 | * | 43 | * |
43 | * The data to be stored is divided into chunks using chunksize. Each device | 44 | * The data to be stored is divided into chunks using chunksize. Each device |
44 | * is divided into far_copies sections. In each section, chunks are laid out | 45 | * is divided into far_copies sections. In each section, chunks are laid out |
@@ -1497,6 +1498,8 @@ static void status(struct seq_file *seq, struct mddev *mddev) | |||
1497 | seq_printf(seq, " %d offset-copies", conf->geo.far_copies); | 1498 | seq_printf(seq, " %d offset-copies", conf->geo.far_copies); |
1498 | else | 1499 | else |
1499 | seq_printf(seq, " %d far-copies", conf->geo.far_copies); | 1500 | seq_printf(seq, " %d far-copies", conf->geo.far_copies); |
1501 | if (conf->geo.far_set_size != conf->geo.raid_disks) | ||
1502 | seq_printf(seq, " %d devices per set", conf->geo.far_set_size); | ||
1500 | } | 1503 | } |
1501 | seq_printf(seq, " [%d/%d] [", conf->geo.raid_disks, | 1504 | seq_printf(seq, " [%d/%d] [", conf->geo.raid_disks, |
1502 | conf->geo.raid_disks - mddev->degraded); | 1505 | conf->geo.raid_disks - mddev->degraded); |
@@ -3394,7 +3397,7 @@ static int setup_geo(struct geom *geo, struct mddev *mddev, enum geo_type new) | |||
3394 | disks = mddev->raid_disks + mddev->delta_disks; | 3397 | disks = mddev->raid_disks + mddev->delta_disks; |
3395 | break; | 3398 | break; |
3396 | } | 3399 | } |
3397 | if (layout >> 18) | 3400 | if (layout >> 19) |
3398 | return -1; | 3401 | return -1; |
3399 | if (chunk < (PAGE_SIZE >> 9) || | 3402 | if (chunk < (PAGE_SIZE >> 9) || |
3400 | !is_power_of_2(chunk)) | 3403 | !is_power_of_2(chunk)) |
@@ -3406,7 +3409,22 @@ static int setup_geo(struct geom *geo, struct mddev *mddev, enum geo_type new) | |||
3406 | geo->near_copies = nc; | 3409 | geo->near_copies = nc; |
3407 | geo->far_copies = fc; | 3410 | geo->far_copies = fc; |
3408 | geo->far_offset = fo; | 3411 | geo->far_offset = fo; |
3409 | geo->far_set_size = (layout & (1<<17)) ? disks / fc : disks; | 3412 | switch (layout >> 17) { |
3413 | case 0: /* original layout. simple but not always optimal */ | ||
3414 | geo->far_set_size = disks; | ||
3415 | break; | ||
3416 | case 1: /* "improved" layout which was buggy. Hopefully no-one is | ||
3417 | * actually using this, but leave code here just in case.*/ | ||
3418 | geo->far_set_size = disks/fc; | ||
3419 | WARN(geo->far_set_size < fc, | ||
3420 | "This RAID10 layout does not provide data safety - please backup and create new array\n"); | ||
3421 | break; | ||
3422 | case 2: /* "improved" layout fixed to match documentation */ | ||
3423 | geo->far_set_size = fc * nc; | ||
3424 | break; | ||
3425 | default: /* Not a valid layout */ | ||
3426 | return -1; | ||
3427 | } | ||
3410 | geo->chunk_mask = chunk - 1; | 3428 | geo->chunk_mask = chunk - 1; |
3411 | geo->chunk_shift = ffz(~chunk); | 3429 | geo->chunk_shift = ffz(~chunk); |
3412 | return nc*fc; | 3430 | return nc*fc; |