diff options
Diffstat (limited to 'drivers/md/md.c')
| -rw-r--r-- | drivers/md/md.c | 35 | 
1 files changed, 30 insertions, 5 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 4edcda8f486..4869128bf74 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3001,6 +3001,9 @@ level_store(mddev_t *mddev, const char *buf, size_t len)  		return -EINVAL;  	} +	list_for_each_entry(rdev, &mddev->disks, same_set) +		rdev->new_raid_disk = rdev->raid_disk; +  	/* ->takeover must set new_* and/or delta_disks  	 * if it succeeds, and may set them when it fails.  	 */ @@ -3051,13 +3054,35 @@ level_store(mddev_t *mddev, const char *buf, size_t len)  		mddev->safemode = 0;  	} -	module_put(mddev->pers->owner); -	/* Invalidate devices that are now superfluous */ -	list_for_each_entry(rdev, &mddev->disks, same_set) -		if (rdev->raid_disk >= mddev->raid_disks) { -			rdev->raid_disk = -1; +	list_for_each_entry(rdev, &mddev->disks, same_set) { +		char nm[20]; +		if (rdev->raid_disk < 0) +			continue; +		if (rdev->new_raid_disk > mddev->raid_disks) +			rdev->new_raid_disk = -1; +		if (rdev->new_raid_disk == rdev->raid_disk) +			continue; +		sprintf(nm, "rd%d", rdev->raid_disk); +		sysfs_remove_link(&mddev->kobj, nm); +	} +	list_for_each_entry(rdev, &mddev->disks, same_set) { +		if (rdev->raid_disk < 0) +			continue; +		if (rdev->new_raid_disk == rdev->raid_disk) +			continue; +		rdev->raid_disk = rdev->new_raid_disk; +		if (rdev->raid_disk < 0)  			clear_bit(In_sync, &rdev->flags); +		else { +			char nm[20]; +			sprintf(nm, "rd%d", rdev->raid_disk); +			if(sysfs_create_link(&mddev->kobj, &rdev->kobj, nm)) +				printk("md: cannot register %s for %s after level change\n", +				       nm, mdname(mddev));  		} +	} + +	module_put(mddev->pers->owner);  	mddev->pers = pers;  	mddev->private = priv;  	strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));  |