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: NeilBrown <neilb@suse.de>
This commit is contained in:
parent
b16b1b6cd0
commit
6508fdbf40
1 changed files with 32 additions and 24 deletions
|
@ -3164,12 +3164,40 @@ raid10_size(struct mddev *mddev, sector_t sectors, int raid_disks)
|
||||||
return size << conf->chunk_shift;
|
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)
|
static struct r10conf *setup_conf(struct mddev *mddev)
|
||||||
{
|
{
|
||||||
struct r10conf *conf = NULL;
|
struct r10conf *conf = NULL;
|
||||||
int nc, fc, fo;
|
int nc, fc, fo;
|
||||||
sector_t stride, size;
|
|
||||||
int err = -EINVAL;
|
int err = -EINVAL;
|
||||||
|
|
||||||
if (mddev->new_chunk_sectors < (PAGE_SIZE >> 9) ||
|
if (mddev->new_chunk_sectors < (PAGE_SIZE >> 9) ||
|
||||||
|
@ -3219,28 +3247,7 @@ static struct r10conf *setup_conf(struct mddev *mddev)
|
||||||
if (!conf->r10bio_pool)
|
if (!conf->r10bio_pool)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
size = mddev->dev_sectors >> conf->chunk_shift;
|
calc_sectors(conf, mddev->dev_sectors);
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
spin_lock_init(&conf->device_lock);
|
spin_lock_init(&conf->device_lock);
|
||||||
INIT_LIST_HEAD(&conf->retry_list);
|
INIT_LIST_HEAD(&conf->retry_list);
|
||||||
|
@ -3468,7 +3475,8 @@ static int raid10_resize(struct mddev *mddev, sector_t sectors)
|
||||||
mddev->recovery_cp = oldsize;
|
mddev->recovery_cp = oldsize;
|
||||||
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
|
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;
|
mddev->resync_max_sectors = size;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue