diff options
author | Alasdair G Kergon <agk@redhat.com> | 2014-12-03 22:47:08 +0000 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2014-12-03 22:47:08 +0000 |
commit | a057f40155b415be40dac31bb138ee66761ce999 (patch) | |
tree | d65b50c9ba5f0b7078fb78282711eb833436d551 | |
parent | de53e0955dc43d5f069604553b038fa672463da9 (diff) | |
download | lvm2-a057f40155b415be40dac31bb138ee66761ce999.tar.gz |
mirror: Validate raid region size config setting.
If necessary, round down to a power of 2 the raid/mirror region size
taken from the config files.
-rw-r--r-- | lib/metadata/lv_manip.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index b00e11ba0..4483fba76 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -731,7 +731,7 @@ int get_pv_list_for_lv(struct dm_pool *mem, * * Returns: default region_size in sectors */ -int get_default_region_size(struct cmd_context *cmd) +static int _get_default_region_size(struct cmd_context *cmd) { int mrs, rrs; @@ -759,6 +759,35 @@ int get_default_region_size(struct cmd_context *cmd) return rrs; } +static int _round_down_pow2(int r) +{ + /* Set all bits to the right of the leftmost set bit */ + r |= (r >> 1); + r |= (r >> 2); + r |= (r >> 4); + r |= (r >> 8); + r |= (r >> 16); + + /* Pull out the leftmost set bit */ + return r & ~(r >> 1); +} + +int get_default_region_size(struct cmd_context *cmd) +{ + int region_size = _get_default_region_size(cmd); + + if (region_size > INT32_MAX) + region_size = INT32_MAX; + + if (region_size & (region_size - 1)) { + region_size = _round_down_pow2(region_size); + log_verbose("Reducing mirror region size to %u kiB (power of 2).", + region_size / 2); + } + + return region_size; +} + int add_seg_to_segs_using_this_lv(struct logical_volume *lv, struct lv_segment *seg) { |