aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/raid10.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2010-06-15 04:36:03 -0400
committerNeilBrown <neilb@suse.de>2010-06-23 23:33:24 -0400
commite93f68a1fc6244c05ad8fae28e75835ec74ab34e (patch)
treed282978aac8f6fcec512be2a6e61287bbb6241b1 /drivers/md/raid10.c
parent0544a21db02c1d8883158fd6f323364f830a120a (diff)
md: fix handling of array level takeover that re-arranges devices.
Most array level changes leave the list of devices largely unchanged, possibly causing one at the end to become redundant. However conversions between RAID0 and RAID10 need to renumber all devices (except 0). This renumbering is currently being done in the ->run method when the new personality takes over. However this is too late as the common code in md.c might already have invalidated some of the devices if they had a ->raid_disk number that appeared to high. Moving it into the ->takeover method is too early as the array is still active at that time and wrong ->raid_disk numbers could cause confusion. So add a ->new_raid_disk field to mdk_rdev_s and use it to communicate the new raid_disk number. Now the common code knows exactly which devices need to be renumbered, and which can be invalidated, and can do it all at a convenient time when the array is suspend. It can also update some symlinks in sysfs which previously were not be updated correctly. Reported-by: Maciej Trela <maciej.trela@intel.com> Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/raid10.c')
-rw-r--r--drivers/md/raid10.c19
1 files changed, 5 insertions, 14 deletions
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 6d420cb487b..1bab3559f3e 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -2241,7 +2241,6 @@ static conf_t *setup_conf(mddev_t *mddev)
2241 if (!conf->thread) 2241 if (!conf->thread)
2242 goto out; 2242 goto out;
2243 2243
2244 conf->scale_disks = 0;
2245 conf->mddev = mddev; 2244 conf->mddev = mddev;
2246 return conf; 2245 return conf;
2247 2246
@@ -2300,11 +2299,6 @@ static int run(mddev_t *mddev)
2300 if (disk_idx >= conf->raid_disks 2299 if (disk_idx >= conf->raid_disks
2301 || disk_idx < 0) 2300 || disk_idx < 0)
2302 continue; 2301 continue;
2303 if (conf->scale_disks) {
2304 disk_idx *= conf->scale_disks;
2305 rdev->raid_disk = disk_idx;
2306 /* MOVE 'rd%d' link !! */
2307 }
2308 disk = conf->mirrors + disk_idx; 2302 disk = conf->mirrors + disk_idx;
2309 2303
2310 disk->rdev = rdev; 2304 disk->rdev = rdev;
@@ -2435,13 +2429,6 @@ static void *raid10_takeover_raid0(mddev_t *mddev)
2435 return ERR_PTR(-EINVAL); 2429 return ERR_PTR(-EINVAL);
2436 } 2430 }
2437 2431
2438 /* Update slot numbers to obtain
2439 * degraded raid10 with missing mirrors
2440 */
2441 list_for_each_entry(rdev, &mddev->disks, same_set) {
2442 rdev->raid_disk *= 2;
2443 }
2444
2445 /* Set new parameters */ 2432 /* Set new parameters */
2446 mddev->new_level = 10; 2433 mddev->new_level = 10;
2447 /* new layout: far_copies = 1, near_copies = 2 */ 2434 /* new layout: far_copies = 1, near_copies = 2 */
@@ -2454,7 +2441,11 @@ static void *raid10_takeover_raid0(mddev_t *mddev)
2454 mddev->recovery_cp = MaxSector; 2441 mddev->recovery_cp = MaxSector;
2455 2442
2456 conf = setup_conf(mddev); 2443 conf = setup_conf(mddev);
2457 conf->scale_disks = 2; 2444 if (!IS_ERR(conf))
2445 list_for_each_entry(rdev, &mddev->disks, same_set)
2446 if (rdev->raid_disk >= 0)
2447 rdev->new_raid_disk = rdev->raid_disk * 2;
2448
2458 return conf; 2449 return conf;
2459} 2450}
2460 2451