Skip to content

Commit 6508fdb

Browse files
committed
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 <[email protected]>
1 parent b16b1b6 commit 6508fdb

File tree

1 file changed

+32
-24
lines changed

1 file changed

+32
-24
lines changed

drivers/md/raid10.c

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3164,12 +3164,40 @@ raid10_size(struct mddev *mddev, sector_t sectors, int raid_disks)
31643164
return size << conf->chunk_shift;
31653165
}
31663166

3167+
static void calc_sectors(struct r10conf *conf, sector_t size)
3168+
{
3169+
/* Calculate the number of sectors-per-device that will
3170+
* actually be used, and set conf->dev_sectors and
3171+
* conf->stride
3172+
*/
3173+
3174+
size = size >> conf->chunk_shift;
3175+
sector_div(size, conf->far_copies);
3176+
size = size * conf->raid_disks;
3177+
sector_div(size, conf->near_copies);
3178+
/* 'size' is now the number of chunks in the array */
3179+
/* calculate "used chunks per device" */
3180+
size = size * conf->copies;
3181+
3182+
/* We need to round up when dividing by raid_disks to
3183+
* get the stride size.
3184+
*/
3185+
size = DIV_ROUND_UP_SECTOR_T(size, conf->raid_disks);
3186+
3187+
conf->dev_sectors = size << conf->chunk_shift;
3188+
3189+
if (conf->far_offset)
3190+
conf->stride = 1 << conf->chunk_shift;
3191+
else {
3192+
sector_div(size, conf->near_copies);
3193+
conf->stride = size << conf->chunk_shift;
3194+
}
3195+
}
31673196

31683197
static struct r10conf *setup_conf(struct mddev *mddev)
31693198
{
31703199
struct r10conf *conf = NULL;
31713200
int nc, fc, fo;
3172-
sector_t stride, size;
31733201
int err = -EINVAL;
31743202

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

3222-
size = mddev->dev_sectors >> conf->chunk_shift;
3223-
sector_div(size, fc);
3224-
size = size * conf->raid_disks;
3225-
sector_div(size, nc);
3226-
/* 'size' is now the number of chunks in the array */
3227-
/* calculate "used chunks per device" in 'stride' */
3228-
stride = size * conf->copies;
3229-
3230-
/* We need to round up when dividing by raid_disks to
3231-
* get the stride size.
3232-
*/
3233-
stride += conf->raid_disks - 1;
3234-
sector_div(stride, conf->raid_disks);
3235-
3236-
conf->dev_sectors = stride << conf->chunk_shift;
3237-
3238-
if (fo)
3239-
stride = 1;
3240-
else
3241-
sector_div(stride, fc);
3242-
conf->stride = stride << conf->chunk_shift;
3243-
3250+
calc_sectors(conf, mddev->dev_sectors);
32443251

32453252
spin_lock_init(&conf->device_lock);
32463253
INIT_LIST_HEAD(&conf->retry_list);
@@ -3468,7 +3475,8 @@ static int raid10_resize(struct mddev *mddev, sector_t sectors)
34683475
mddev->recovery_cp = oldsize;
34693476
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
34703477
}
3471-
mddev->dev_sectors = sectors;
3478+
calc_sectors(conf, sectors);
3479+
mddev->dev_sectors = conf->dev_sectors;
34723480
mddev->resync_max_sectors = size;
34733481
return 0;
34743482
}

0 commit comments

Comments
 (0)