diff options
Diffstat (limited to 'drivers/md/md.c')
| -rw-r--r-- | drivers/md/md.c | 38 | 
1 files changed, 33 insertions, 5 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 46b3a044ead..cb20d0b0555 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2087,6 +2087,7 @@ static void sync_sbs(mddev_t * mddev, int nospares)  	/* First make sure individual recovery_offsets are correct */  	list_for_each_entry(rdev, &mddev->disks, same_set) {  		if (rdev->raid_disk >= 0 && +		    mddev->delta_disks >= 0 &&  		    !test_bit(In_sync, &rdev->flags) &&  		    mddev->curr_resync_completed > rdev->recovery_offset)  				rdev->recovery_offset = mddev->curr_resync_completed; @@ -3001,6 +3002,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 +3055,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)); @@ -5895,6 +5921,7 @@ static int md_open(struct block_device *bdev, fmode_t mode)  	atomic_inc(&mddev->openers);  	mutex_unlock(&mddev->open_mutex); +	check_disk_size_change(mddev->gendisk, bdev);   out:  	return err;  } @@ -6846,6 +6873,7 @@ void md_do_sync(mddev_t *mddev)  			rcu_read_lock();  			list_for_each_entry_rcu(rdev, &mddev->disks, same_set)  				if (rdev->raid_disk >= 0 && +				    mddev->delta_disks >= 0 &&  				    !test_bit(Faulty, &rdev->flags) &&  				    !test_bit(In_sync, &rdev->flags) &&  				    rdev->recovery_offset < mddev->curr_resync)  |