summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlasdair G Kergon <agk@redhat.com>2014-12-03 22:47:08 +0000
committerAlasdair G Kergon <agk@redhat.com>2014-12-03 22:47:08 +0000
commita057f40155b415be40dac31bb138ee66761ce999 (patch)
treed65b50c9ba5f0b7078fb78282711eb833436d551
parentde53e0955dc43d5f069604553b038fa672463da9 (diff)
downloadlvm2-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.c31
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)
{