From: Alasdair Kergon Date: Sat, 29 Apr 2006 22:08:43 +0000 (+0000) Subject: Improve stripe size validation. X-Git-Tag: v2_02_91~4531 X-Git-Url: https://sourceware.org/git/?a=commitdiff_plain;h=12de747d3aa1e9471344586c25b31703e092a52e;p=lvm2.git Improve stripe size validation. Increase maximum stripe size limit to physical extent size for lvm2 metadata. --- diff --git a/WHATS_NEW b/WHATS_NEW index 7bd1653e0..9ff0176ab 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,7 @@ Version 2.02.06 - ================================= + Improve stripe size validation. + Increase maximum stripe size limit to physical extent size for lvm2 metadata. Fix activation code to check for pre-existing mirror logs. Tighten region size validation. Ignore empty strings in config files. diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c index cd579950a..3ca480b80 100644 --- a/lib/format_text/format-text.c +++ b/lib/format_text/format-text.c @@ -1754,7 +1754,8 @@ struct format_type *create_text_format(struct cmd_context *cmd) fmt->name = FMT_TEXT_NAME; fmt->alias = FMT_TEXT_ALIAS; fmt->features = FMT_SEGMENTS | FMT_MDAS | FMT_TAGS | FMT_PRECOMMIT | - FMT_UNLIMITED_VOLS | FMT_RESIZE_PV; + FMT_UNLIMITED_VOLS | FMT_RESIZE_PV | + FMT_UNLIMITED_STRIPESIZE; if (!(mda_lists = dm_malloc(sizeof(struct mda_lists)))) { log_error("Failed to allocate dir_list"); diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h index f9b732dfc..c3f2b0d21 100644 --- a/lib/metadata/metadata.h +++ b/lib/metadata/metadata.h @@ -31,6 +31,7 @@ #define SECTOR_SIZE ( 1L << SECTOR_SHIFT ) #define STRIPE_SIZE_MIN ( getpagesize() >> SECTOR_SHIFT) /* PAGESIZE in sectors */ #define STRIPE_SIZE_MAX ( 512L * 1024L >> SECTOR_SHIFT) /* 512 KB in sectors */ +#define STRIPE_SIZE_LIMIT ((UINT_MAX >> 2) + 1) #define PV_MIN_SIZE ( 512L * 1024L >> SECTOR_SHIFT) /* 512 KB in sectors */ #define PE_ALIGN (65536UL >> SECTOR_SHIFT) /* PE alignment */ #define MAX_RESTRICTED_LVS 255 /* Used by FMT_RESTRICTED_LVIDS */ @@ -74,6 +75,7 @@ #define FMT_ORPHAN_ALLOCATABLE 0x00000020 /* Orphan PV allocatable? */ #define FMT_PRECOMMIT 0x00000040 /* Supports pre-commit? */ #define FMT_RESIZE_PV 0x00000080 /* Supports pvresize? */ +#define FMT_UNLIMITED_STRIPESIZE 0x00000080 /* Unlimited stripe size? */ typedef enum { ALLOC_INVALID, diff --git a/man/lvcreate.8 b/man/lvcreate.8 index 881cdc4c4..a3717ab6a 100644 --- a/man/lvcreate.8 +++ b/man/lvcreate.8 @@ -58,7 +58,9 @@ the logical volume. .I \-I, \-\-stripesize StripeSize Gives the number of kilobytes for the granularity of the stripes. .br -StripeSize must be 2^n (n = 2 to 9) +StripeSize must be 2^n (n = 2 to 9) for metadata in LVM1 format. +For metadata in LVM2 format, the stripe size may be a larger +power of 2 but must not exceed the physical extent size. .TP .I \-l, \-\-extents LogicalExtentsNumber Gives the number of logical extents to allocate for the new diff --git a/tools/lvcreate.c b/tools/lvcreate.c index f19117458..7464929be 100644 --- a/tools/lvcreate.c +++ b/tools/lvcreate.c @@ -181,6 +181,10 @@ static int _read_size_params(struct lvcreate_params *lp, return 1; } +/* The stripe size is limited by the size of a uint32_t, but since the + * value given by the user is doubled, and the final result must be a + * power of 2, we must divide UINT_MAX by four and add 1 (to round it + * up to the power of 2) */ static int _read_stripe_params(struct lvcreate_params *lp, struct cmd_context *cmd, int *pargc, char ***pargv) @@ -192,6 +196,12 @@ static int _read_stripe_params(struct lvcreate_params *lp, log_error("Negative stripesize is invalid"); return 0; } + /* Check to make sure we won't overflow lp->stripe_size */ + if(arg_uint_value(cmd, stripesize_ARG, 0) > STRIPE_SIZE_LIMIT) { + log_error("Stripe size cannot be larger than %s", + display_size(cmd, STRIPE_SIZE_LIMIT, SIZE_SHORT)); + return 0; + } lp->stripe_size = 2 * arg_uint_value(cmd, stripesize_ARG, 0); } @@ -204,7 +214,8 @@ static int _read_stripe_params(struct lvcreate_params *lp, lp->stripe_size = find_config_int(cmd->cft->root, "metadata/stripesize", DEFAULT_STRIPESIZE) * 2; - log_print("Using default stripesize %dKB", lp->stripe_size / 2); + log_print("Using default stripesize %s", + display_size(cmd, lp->stripe_size, SIZE_SHORT)); } if (argc && (unsigned) argc < lp->stripes) { @@ -219,10 +230,11 @@ static int _read_stripe_params(struct lvcreate_params *lp, return 0; } + /* MAX size check is in _lvcreate */ if (lp->stripes > 1 && (lp->stripe_size < STRIPE_SIZE_MIN || - lp->stripe_size > STRIPE_SIZE_MAX || lp->stripe_size & (lp->stripe_size - 1))) { - log_error("Invalid stripe size %d", lp->stripe_size); + log_error("Invalid stripe size %s", + display_size(cmd, lp->stripe_size, SIZE_SHORT)); return 0; } @@ -505,12 +517,23 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp) pvh = &vg->pvs; if (lp->stripe_size > vg->extent_size) { - log_error("Setting stripe size %d KB to physical extent " - "size %u KB", lp->stripe_size / 2, - vg->extent_size / 2); + log_error("Reducing requested stripe size %s to maximum, " + "physical extent size %s", + display_size(cmd, lp->stripe_size, SIZE_SHORT), + display_size(cmd, vg->extent_size, SIZE_SHORT)); lp->stripe_size = vg->extent_size; } + /* Need to check the vg's format to verify this - the cmd format isn't setup properly yet */ + if (lp->stripes > 1 && + !(vg->fid->fmt->features & FMT_UNLIMITED_STRIPESIZE) && + (lp->stripe_size > STRIPE_SIZE_MAX)) { + log_error("Stripe size may not exceed %s", + display_size(cmd, STRIPE_SIZE_MAX, + SIZE_SHORT)); + return 0; + } + if (lp->size) { /* No of 512-byte sectors */ tmp_size = lp->size; diff --git a/tools/lvresize.c b/tools/lvresize.c index 094c7f5a0..f3956fa26 100644 --- a/tools/lvresize.c +++ b/tools/lvresize.c @@ -178,15 +178,35 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp) log_error("Stripesize may not be negative."); return ECMD_FAILED; } - if (vg->fid->fmt->features & FMT_SEGMENTS) + + if (arg_uint_value(cmd, stripesize_ARG, 0) > STRIPE_SIZE_LIMIT) { + log_error("Stripe size cannot be larger than %s", + display_size(cmd, STRIPE_SIZE_LIMIT, SIZE_SHORT)); + return 0; + } + + if (!(vg->fid->fmt->features & FMT_SEGMENTS)) + log_print("Varied stripesize not supported. Ignoring."); + else if (arg_uint_value(cmd, stripesize_ARG, 0) > vg->extent_size) { + log_error("Reducing stripe size %s to maximum, " + "physical extent size %s", + display_size(cmd, + arg_uint_value(cmd, stripesize_ARG, 0) * 2, + SIZE_SHORT), + display_size(cmd, vg->extent_size, SIZE_SHORT)); + lp->stripe_size = vg->extent_size; + } else lp->stripe_size = 2 * arg_uint_value(cmd, stripesize_ARG, 0); - else - log_print("Varied stripesize not supported. Ignoring."); + if (lp->mirrors) { log_error("Mirrors and striping cannot be combined yet."); return ECMD_FAILED; } + if (lp->stripe_size & (lp->stripe_size - 1)) { + log_error("Stripe size must be power of 2"); + return 0; + } } lv = lvl->lv; @@ -279,16 +299,18 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp) if (!lp->stripe_size && lp->stripes > 1) { if (seg_stripesize) { - log_print("Using stripesize of last segment " - "%dKB", seg_stripesize / 2); + log_print("Using stripesize of last segment %s", + display_size(cmd, seg_stripesize, + SIZE_SHORT)); lp->stripe_size = seg_stripesize; } else { lp->stripe_size = find_config_int(cmd->cft->root, "metadata/stripesize", DEFAULT_STRIPESIZE) * 2; - log_print("Using default stripesize %dKB", - lp->stripe_size / 2); + log_print("Using default stripesize %s", + display_size(cmd, lp->stripe_size, + SIZE_SHORT)); } } } @@ -362,6 +384,12 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp) lp->extents, lp->extents - size_rest); lp->extents = lp->extents - size_rest; } + + if (lp->stripe_size < STRIPE_SIZE_MIN) { + log_error("Invalid stripe size %s", + display_size(cmd, lp->stripe_size, SIZE_SHORT)); + return 0; + } } if (lp->extents == lv->le_count) {