Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 63c70c4f authored by NeilBrown's avatar NeilBrown Committed by Linus Torvalds
Browse files

[PATCH] md: Split reshape handler in check_reshape and start_reshape



check_reshape checks validity and does things that can be done instantly -
like adding devices to raid1.  start_reshape initiates a restriping process to
convert the whole array.

Signed-off-by: default avatarNeil Brown <neilb@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent b578d55f
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -2594,7 +2594,7 @@ static int do_md_run(mddev_t * mddev)
	strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));

	if (mddev->reshape_position != MaxSector &&
	    pers->reshape == NULL) {
	    pers->start_reshape == NULL) {
		/* This personality cannot handle reshaping... */
		mddev->pers = NULL;
		module_put(pers->owner);
@@ -3556,14 +3556,16 @@ static int update_raid_disks(mddev_t *mddev, int raid_disks)
{
	int rv;
	/* change the number of raid disks */
	if (mddev->pers->reshape == NULL)
	if (mddev->pers->check_reshape == NULL)
		return -EINVAL;
	if (raid_disks <= 0 ||
	    raid_disks >= mddev->max_disks)
		return -EINVAL;
	if (mddev->sync_thread)
	if (mddev->sync_thread || mddev->reshape_position != MaxSector)
		return -EBUSY;
	rv = mddev->pers->reshape(mddev, raid_disks);
	mddev->delta_disks = raid_disks - mddev->raid_disks;

	rv = mddev->pers->check_reshape(mddev);
	return rv;
}

+16 −3
Original line number Diff line number Diff line
@@ -1976,7 +1976,7 @@ static int raid1_resize(mddev_t *mddev, sector_t sectors)
	return 0;
}

static int raid1_reshape(mddev_t *mddev, int raid_disks)
static int raid1_reshape(mddev_t *mddev)
{
	/* We need to:
	 * 1/ resize the r1bio_pool
@@ -1993,10 +1993,22 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
	struct pool_info *newpoolinfo;
	mirror_info_t *newmirrors;
	conf_t *conf = mddev_to_conf(mddev);
	int cnt;
	int cnt, raid_disks;

	int d, d2;

	/* Cannot change chunk_size, layout, or level */
	if (mddev->chunk_size != mddev->new_chunk ||
	    mddev->layout != mddev->new_layout ||
	    mddev->level != mddev->new_level) {
		mddev->new_chunk = mddev->chunk_size;
		mddev->new_layout = mddev->layout;
		mddev->new_level = mddev->level;
		return -EINVAL;
	}

	raid_disks = mddev->raid_disks + mddev->delta_disks;

	if (raid_disks < conf->raid_disks) {
		cnt=0;
		for (d= 0; d < conf->raid_disks; d++)
@@ -2043,6 +2055,7 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)

	mddev->degraded += (raid_disks - conf->raid_disks);
	conf->raid_disks = mddev->raid_disks = raid_disks;
	mddev->delta_disks = 0;

	conf->last_used = 0; /* just make sure it is in-range */
	lower_barrier(conf);
@@ -2084,7 +2097,7 @@ static struct mdk_personality raid1_personality =
	.spare_active	= raid1_spare_active,
	.sync_request	= sync_request,
	.resize		= raid1_resize,
	.reshape	= raid1_reshape,
	.check_reshape	= raid1_reshape,
	.quiesce	= raid1_quiesce,
};

+34 −26
Original line number Diff line number Diff line
@@ -2590,21 +2590,15 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors)
}

#ifdef CONFIG_MD_RAID5_RESHAPE
static int raid5_reshape(mddev_t *mddev, int raid_disks)
static int raid5_check_reshape(mddev_t *mddev)
{
	raid5_conf_t *conf = mddev_to_conf(mddev);
	int err;
	mdk_rdev_t *rdev;
	struct list_head *rtmp;
	int spares = 0;
	int added_devices = 0;

	if (mddev->degraded ||
	    test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
		return -EBUSY;
	if (conf->raid_disks > raid_disks)
		return -EINVAL; /* Cannot shrink array yet */
	if (conf->raid_disks == raid_disks)
	if (mddev->delta_disks < 0 ||
	    mddev->new_level != mddev->level)
		return -EINVAL; /* Cannot shrink array or change level yet */
	if (mddev->delta_disks == 0)
		return 0; /* nothing to do */

	/* Can only proceed if there are plenty of stripe_heads.
@@ -2615,30 +2609,48 @@ static int raid5_reshape(mddev_t *mddev, int raid_disks)
	 * If the chunk size is greater, user-space should request more
	 * stripe_heads first.
	 */
	if ((mddev->chunk_size / STRIPE_SIZE) * 4 > conf->max_nr_stripes) {
	if ((mddev->chunk_size / STRIPE_SIZE) * 4 > conf->max_nr_stripes ||
	    (mddev->new_chunk / STRIPE_SIZE) * 4 > conf->max_nr_stripes) {
		printk(KERN_WARNING "raid5: reshape: not enough stripes.  Needed %lu\n",
		       (mddev->chunk_size / STRIPE_SIZE)*4);
		return -ENOSPC;
	}

	err = resize_stripes(conf, conf->raid_disks + mddev->delta_disks);
	if (err)
		return err;

	/* looks like we might be able to manage this */
	return 0;
}

static int raid5_start_reshape(mddev_t *mddev)
{
	raid5_conf_t *conf = mddev_to_conf(mddev);
	mdk_rdev_t *rdev;
	struct list_head *rtmp;
	int spares = 0;
	int added_devices = 0;

	if (mddev->degraded ||
	    test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
		return -EBUSY;

	ITERATE_RDEV(mddev, rdev, rtmp)
		if (rdev->raid_disk < 0 &&
		    !test_bit(Faulty, &rdev->flags))
			spares++;
	if (conf->raid_disks + spares < raid_disks-1)

	if (spares < mddev->delta_disks-1)
		/* Not enough devices even to make a degraded array
		 * of that size
		 */
		return -EINVAL;

	err = resize_stripes(conf, raid_disks);
	if (err)
		return err;

	atomic_set(&conf->reshape_stripes, 0);
	spin_lock_irq(&conf->device_lock);
	conf->previous_raid_disks = conf->raid_disks;
	conf->raid_disks = raid_disks;
	conf->raid_disks += mddev->delta_disks;
	conf->expand_progress = 0;
	conf->expand_lo = 0;
	spin_unlock_irq(&conf->device_lock);
@@ -2660,12 +2672,8 @@ static int raid5_reshape(mddev_t *mddev, int raid_disks)
				break;
		}

	mddev->degraded = (raid_disks - conf->previous_raid_disks) - added_devices;
	mddev->new_chunk = mddev->chunk_size;
	mddev->new_layout = mddev->layout;
	mddev->new_level = mddev->level;
	mddev->raid_disks = raid_disks;
	mddev->delta_disks = raid_disks - conf->previous_raid_disks;
	mddev->degraded = (conf->raid_disks - conf->previous_raid_disks) - added_devices;
	mddev->raid_disks = conf->raid_disks;
	mddev->reshape_position = 0;
	mddev->sb_dirty = 1;

@@ -2679,7 +2687,6 @@ static int raid5_reshape(mddev_t *mddev, int raid_disks)
		mddev->recovery = 0;
		spin_lock_irq(&conf->device_lock);
		mddev->raid_disks = conf->raid_disks = conf->previous_raid_disks;
		mddev->delta_disks = 0;
		conf->expand_progress = MaxSector;
		spin_unlock_irq(&conf->device_lock);
		return -EAGAIN;
@@ -2752,7 +2759,8 @@ static struct mdk_personality raid5_personality =
	.sync_request	= sync_request,
	.resize		= raid5_resize,
#ifdef CONFIG_MD_RAID5_RESHAPE
	.reshape	= raid5_reshape,
	.check_reshape	= raid5_check_reshape,
	.start_reshape  = raid5_start_reshape,
#endif
	.quiesce	= raid5_quiesce,
};
+2 −1
Original line number Diff line number Diff line
@@ -261,7 +261,8 @@ struct mdk_personality
	int (*spare_active) (mddev_t *mddev);
	sector_t (*sync_request)(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster);
	int (*resize) (mddev_t *mddev, sector_t sectors);
	int (*reshape) (mddev_t *mddev, int raid_disks);
	int (*check_reshape) (mddev_t *mddev);
	int (*start_reshape) (mddev_t *mddev);
	int (*reconfig) (mddev_t *mddev, int layout, int chunk_size);
	/* quiesce moves between quiescence states
	 * 0 - fully active