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

Commit 6508fdbf authored by NeilBrown's avatar NeilBrown
Browse files

md/raid10: set dev_sectors properly when resizing devices in array.



raid10 stores dev_sectors in 'conf' separately from the one in
'mddev' because it can have a very significant effect on block
addressing and so need to be updated carefully.

However raid10_resize isn't updating it at all!

To update it correctly, we need to make sure it is a proper
multiple of the chunksize taking various details of the layout
in to account.
This calculation is currently done in setup_conf.   So split it
out from there and call it from raid10_resize as well.
Then set conf->dev_sectors properly.

Signed-off-by: default avatarNeilBrown <neilb@suse.de>
parent b16b1b6c
Loading
Loading
Loading
Loading
+32 −24
Original line number Diff line number Diff line
@@ -3164,12 +3164,40 @@ raid10_size(struct mddev *mddev, sector_t sectors, int raid_disks)
	return size << conf->chunk_shift;
}

static void calc_sectors(struct r10conf *conf, sector_t size)
{
	/* Calculate the number of sectors-per-device that will
	 * actually be used, and set conf->dev_sectors and
	 * conf->stride
	 */

	size = size >> conf->chunk_shift;
	sector_div(size, conf->far_copies);
	size = size * conf->raid_disks;
	sector_div(size, conf->near_copies);
	/* 'size' is now the number of chunks in the array */
	/* calculate "used chunks per device" */
	size = size * conf->copies;

	/* We need to round up when dividing by raid_disks to
	 * get the stride size.
	 */
	size = DIV_ROUND_UP_SECTOR_T(size, conf->raid_disks);

	conf->dev_sectors = size << conf->chunk_shift;

	if (conf->far_offset)
		conf->stride = 1 << conf->chunk_shift;
	else {
		sector_div(size, conf->near_copies);
		conf->stride = size << conf->chunk_shift;
	}
}

static struct r10conf *setup_conf(struct mddev *mddev)
{
	struct r10conf *conf = NULL;
	int nc, fc, fo;
	sector_t stride, size;
	int err = -EINVAL;

	if (mddev->new_chunk_sectors < (PAGE_SIZE >> 9) ||
@@ -3219,28 +3247,7 @@ static struct r10conf *setup_conf(struct mddev *mddev)
	if (!conf->r10bio_pool)
		goto out;

	size = mddev->dev_sectors >> conf->chunk_shift;
	sector_div(size, fc);
	size = size * conf->raid_disks;
	sector_div(size, nc);
	/* 'size' is now the number of chunks in the array */
	/* calculate "used chunks per device" in 'stride' */
	stride = size * conf->copies;

	/* We need to round up when dividing by raid_disks to
	 * get the stride size.
	 */
	stride += conf->raid_disks - 1;
	sector_div(stride, conf->raid_disks);

	conf->dev_sectors = stride << conf->chunk_shift;

	if (fo)
		stride = 1;
	else
		sector_div(stride, fc);
	conf->stride = stride << conf->chunk_shift;

	calc_sectors(conf, mddev->dev_sectors);

	spin_lock_init(&conf->device_lock);
	INIT_LIST_HEAD(&conf->retry_list);
@@ -3468,7 +3475,8 @@ static int raid10_resize(struct mddev *mddev, sector_t sectors)
		mddev->recovery_cp = oldsize;
		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
	}
	mddev->dev_sectors = sectors;
	calc_sectors(conf, sectors);
	mddev->dev_sectors = conf->dev_sectors;
	mddev->resync_max_sectors = size;
	return 0;
}