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

Commit 01ee22b4 authored by NeilBrown's avatar NeilBrown
Browse files

md: raid5: check stripe cache is large enough in start_reshape



In reshape cases that do not change the number of devices,
start_reshape is called without first calling check_reshape.

Currently, the check that the stripe_cache is large enough is
only done in check_reshape.  It should be in start_reshape too.

Signed-off-by: default avatarNeilBrown <neilb@suse.de>
parent d6e412ea
Loading
Loading
Loading
Loading
+27 −17
Original line number Diff line number Diff line
@@ -4845,6 +4845,29 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors)
	return 0;
}

static int check_stripe_cache(mddev_t *mddev)
{
	/* Can only proceed if there are plenty of stripe_heads.
	 * We need a minimum of one full stripe,, and for sensible progress
	 * it is best to have about 4 times that.
	 * If we require 4 times, then the default 256 4K stripe_heads will
	 * allow for chunk sizes up to 256K, which is probably OK.
	 * If the chunk size is greater, user-space should request more
	 * stripe_heads first.
	 */
	raid5_conf_t *conf = mddev->private;
	if (((mddev->chunk_sectors << 9) / STRIPE_SIZE) * 4
	    > conf->max_nr_stripes ||
	    ((mddev->new_chunk_sectors << 9) / STRIPE_SIZE) * 4
	    > conf->max_nr_stripes) {
		printk(KERN_WARNING "raid5: reshape: not enough stripes.  Needed %lu\n",
		       ((max(mddev->chunk_sectors, mddev->new_chunk_sectors) << 9)
			/ STRIPE_SIZE)*4);
		return 0;
	}
	return 1;
}

static int raid5_check_reshape(mddev_t *mddev)
{
	raid5_conf_t *conf = mddev->private;
@@ -4871,24 +4894,8 @@ static int raid5_check_reshape(mddev_t *mddev)
			return -EINVAL;
	}

	/* Can only proceed if there are plenty of stripe_heads.
	 * We need a minimum of one full stripe,, and for sensible progress
	 * it is best to have about 4 times that.
	 * If we require 4 times, then the default 256 4K stripe_heads will
	 * allow for chunk sizes up to 256K, which is probably OK.
	 * If the chunk size is greater, user-space should request more
	 * stripe_heads first.
	 */
	if (((mddev->chunk_sectors << 9) / STRIPE_SIZE) * 4
		> conf->max_nr_stripes ||
	    ((mddev->new_chunk_sectors << 9) / STRIPE_SIZE) * 4
		> conf->max_nr_stripes) {
		printk(KERN_WARNING "raid5: reshape: not enough stripes.  Needed %lu\n",
		       (max(mddev->chunk_sectors << 9,
			mddev->new_chunk_sectors << 9)
			/ STRIPE_SIZE)*4);
	if (!check_stripe_cache(mddev))
		return -ENOSPC;
	}

	return resize_stripes(conf, conf->raid_disks + mddev->delta_disks);
}
@@ -4904,6 +4911,9 @@ static int raid5_start_reshape(mddev_t *mddev)
	if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
		return -EBUSY;

	if (!check_stripe_cache(mddev))
		return -ENOSPC;

	list_for_each_entry(rdev, &mddev->disks, same_set)
		if (rdev->raid_disk < 0 &&
		    !test_bit(Faulty, &rdev->flags))