Skip to content

Commit

Permalink
md/raid10: set dev_sectors properly when resizing devices in array.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
NeilBrown committed May 17, 2012
1 parent b16b1b6 commit 6508fdb
Showing 1 changed file with 32 additions and 24 deletions.
56 changes: 32 additions & 24 deletions drivers/md/raid10.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) ||
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down

0 comments on commit 6508fdb

Please sign in to comment.