Commit 50c4feb9 authored by Heinz Mauelshagen's avatar Heinz Mauelshagen Committed by Mike Snitzer

dm raid: be prepared to accept arbitrary '- -' tuples

During raid set resize checks and setting up the recovery offset in case a raid
set grows, calculated rd->md.dev_sectors is compared to rs->dev[0].rdev.sectors.

Device 0 may not be defined in case userspace passes in '- -' for it
(lvm2 doesn't do that so far), thus it's device sectors can't be taken
authoritatively in this comparison and another valid device must be used
to retrieve the device size.

Use mddev->dev_sectors in checking for ongoing recovery for the same reason.
Signed-off-by: default avatarHeinz Mauelshagen <heinzm@redhat.com>
Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
parent c63ede3b
...@@ -370,7 +370,7 @@ static bool rs_is_reshapable(struct raid_set *rs) ...@@ -370,7 +370,7 @@ static bool rs_is_reshapable(struct raid_set *rs)
/* Return true, if raid set in @rs is recovering */ /* Return true, if raid set in @rs is recovering */
static bool rs_is_recovering(struct raid_set *rs) static bool rs_is_recovering(struct raid_set *rs)
{ {
return rs->md.recovery_cp < rs->dev[0].rdev.sectors; return rs->md.recovery_cp < rs->md.dev_sectors;
} }
/* Return true, if raid set in @rs is reshaping */ /* Return true, if raid set in @rs is reshaping */
...@@ -1425,6 +1425,24 @@ static unsigned int rs_data_stripes(struct raid_set *rs) ...@@ -1425,6 +1425,24 @@ static unsigned int rs_data_stripes(struct raid_set *rs)
return rs->raid_disks - rs->raid_type->parity_devs; return rs->raid_disks - rs->raid_type->parity_devs;
} }
/*
* Retrieve rdev->sectors from any valid raid device of @rs
* to allow userpace to pass in arbitray "- -" device tupples.
*/
static sector_t __rdev_sectors(struct raid_set *rs)
{
int i;
for (i = 0; i < rs->md.raid_disks; i++) {
struct md_rdev *rdev = &rs->dev[i].rdev;
if (rdev->bdev && rdev->sectors)
return rdev->sectors;
}
BUG(); /* Constructor ensures we got some. */
}
/* Calculate the sectors per device and per array used for @rs */ /* Calculate the sectors per device and per array used for @rs */
static int rs_set_dev_and_array_sectors(struct raid_set *rs, bool use_mddev) static int rs_set_dev_and_array_sectors(struct raid_set *rs, bool use_mddev)
{ {
...@@ -1510,9 +1528,9 @@ static void rs_setup_recovery(struct raid_set *rs, sector_t dev_sectors) ...@@ -1510,9 +1528,9 @@ static void rs_setup_recovery(struct raid_set *rs, sector_t dev_sectors)
else if (dev_sectors == MaxSector) else if (dev_sectors == MaxSector)
/* Prevent recovery */ /* Prevent recovery */
__rs_setup_recovery(rs, MaxSector); __rs_setup_recovery(rs, MaxSector);
else if (rs->dev[0].rdev.sectors < dev_sectors) else if (__rdev_sectors(rs) < dev_sectors)
/* Grown raid set */ /* Grown raid set */
__rs_setup_recovery(rs, rs->dev[0].rdev.sectors); __rs_setup_recovery(rs, __rdev_sectors(rs));
else else
__rs_setup_recovery(rs, MaxSector); __rs_setup_recovery(rs, MaxSector);
} }
...@@ -2828,7 +2846,7 @@ static int raid_ctr(struct dm_target *ti, unsigned int argc, char **argv) ...@@ -2828,7 +2846,7 @@ static int raid_ctr(struct dm_target *ti, unsigned int argc, char **argv)
if (r) if (r)
goto bad; goto bad;
calculated_dev_sectors = rs->dev[0].rdev.sectors; calculated_dev_sectors = rs->md.dev_sectors;
/* /*
* Backup any new raid set level, layout, ... * Backup any new raid set level, layout, ...
...@@ -2841,7 +2859,7 @@ static int raid_ctr(struct dm_target *ti, unsigned int argc, char **argv) ...@@ -2841,7 +2859,7 @@ static int raid_ctr(struct dm_target *ti, unsigned int argc, char **argv)
if (r) if (r)
goto bad; goto bad;
resize = calculated_dev_sectors != rs->dev[0].rdev.sectors; resize = calculated_dev_sectors != __rdev_sectors(rs);
INIT_WORK(&rs->md.event_work, do_table_event); INIT_WORK(&rs->md.event_work, do_table_event);
ti->private = rs; ti->private = rs;
......
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