Commit 05256d98 authored by NeilBrown's avatar NeilBrown

md/raid5: strengthen check on reshape_position at run.

When reshaping, we work in units of the largest chunk size.
If changing from a larger to a smaller chunk size, that means we
reshape more than one stripe at a time.  So the required alignment
of reshape_position needs to take into account both the old
and new chunk size.

This means that both 'here_new' and 'here_old' are calculated with
respect to the same (maximum) chunk size, so testing if they are the
same when delta_disks is zero becomes pointless.
Signed-off-by: default avatarNeilBrown <neilb@suse.com>
parent 3cb5edf4
...@@ -6688,6 +6688,8 @@ static int run(struct mddev *mddev) ...@@ -6688,6 +6688,8 @@ static int run(struct mddev *mddev)
sector_t here_new, here_old; sector_t here_new, here_old;
int old_disks; int old_disks;
int max_degraded = (mddev->level == 6 ? 2 : 1); int max_degraded = (mddev->level == 6 ? 2 : 1);
int chunk_sectors;
int new_data_disks;
if (mddev->new_level != mddev->level) { if (mddev->new_level != mddev->level) {
printk(KERN_ERR "md/raid:%s: unsupported reshape " printk(KERN_ERR "md/raid:%s: unsupported reshape "
...@@ -6699,28 +6701,25 @@ static int run(struct mddev *mddev) ...@@ -6699,28 +6701,25 @@ static int run(struct mddev *mddev)
/* reshape_position must be on a new-stripe boundary, and one /* reshape_position must be on a new-stripe boundary, and one
* further up in new geometry must map after here in old * further up in new geometry must map after here in old
* geometry. * geometry.
* If the chunk sizes are different, then as we perform reshape
* in units of the largest of the two, reshape_position needs
* be a multiple of the largest chunk size times new data disks.
*/ */
here_new = mddev->reshape_position; here_new = mddev->reshape_position;
if (sector_div(here_new, mddev->new_chunk_sectors * chunk_sectors = max(mddev->chunk_sectors, mddev->new_chunk_sectors);
(mddev->raid_disks - max_degraded))) { new_data_disks = mddev->raid_disks - max_degraded;
if (sector_div(here_new, chunk_sectors * new_data_disks)) {
printk(KERN_ERR "md/raid:%s: reshape_position not " printk(KERN_ERR "md/raid:%s: reshape_position not "
"on a stripe boundary\n", mdname(mddev)); "on a stripe boundary\n", mdname(mddev));
return -EINVAL; return -EINVAL;
} }
reshape_offset = here_new * mddev->new_chunk_sectors; reshape_offset = here_new * chunk_sectors;
/* here_new is the stripe we will write to */ /* here_new is the stripe we will write to */
here_old = mddev->reshape_position; here_old = mddev->reshape_position;
sector_div(here_old, mddev->chunk_sectors * sector_div(here_old, chunk_sectors * (old_disks-max_degraded));
(old_disks-max_degraded));
/* here_old is the first stripe that we might need to read /* here_old is the first stripe that we might need to read
* from */ * from */
if (mddev->delta_disks == 0) { if (mddev->delta_disks == 0) {
if ((here_new * mddev->new_chunk_sectors !=
here_old * mddev->chunk_sectors)) {
printk(KERN_ERR "md/raid:%s: reshape position is"
" confused - aborting\n", mdname(mddev));
return -EINVAL;
}
/* We cannot be sure it is safe to start an in-place /* We cannot be sure it is safe to start an in-place
* reshape. It is only safe if user-space is monitoring * reshape. It is only safe if user-space is monitoring
* and taking constant backups. * and taking constant backups.
...@@ -6739,10 +6738,10 @@ static int run(struct mddev *mddev) ...@@ -6739,10 +6738,10 @@ static int run(struct mddev *mddev)
return -EINVAL; return -EINVAL;
} }
} else if (mddev->reshape_backwards } else if (mddev->reshape_backwards
? (here_new * mddev->new_chunk_sectors + min_offset_diff <= ? (here_new * chunk_sectors + min_offset_diff <=
here_old * mddev->chunk_sectors) here_old * chunk_sectors)
: (here_new * mddev->new_chunk_sectors >= : (here_new * chunk_sectors >=
here_old * mddev->chunk_sectors + (-min_offset_diff))) { here_old * chunk_sectors + (-min_offset_diff))) {
/* Reading from the same stripe as writing to - bad */ /* Reading from the same stripe as writing to - bad */
printk(KERN_ERR "md/raid:%s: reshape_position too early for " printk(KERN_ERR "md/raid:%s: reshape_position too early for "
"auto-recovery - aborting.\n", "auto-recovery - aborting.\n",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment