From a89d60146342a350784615acd56b3087a4696c45 Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Fri, 10 Nov 2006 18:24:11 +0000 Subject: [PATCH] Add some missing bounds checks on 32 bit extent counters. Add Petabyte and Exabyte support. Fix lvcreate error message when 0 extents requested. --- WHATS_NEW | 3 +++ lib/display/display.c | 20 +++++++++++++++++--- lib/format_text/export.c | 2 ++ lib/format_text/format-text.c | 14 ++++++++++++-- lib/metadata/metadata.c | 10 ++++++++++ man/lvcreate.8 | 5 +++-- man/lvextend.8 | 8 +++++--- man/lvreduce.8 | 7 ++++--- man/lvresize.8 | 8 +++++--- tools/commands.h | 24 ++++++++++++------------ tools/lvcreate.c | 14 +++++++++++--- tools/lvmcmdline.c | 2 +- 12 files changed, 85 insertions(+), 32 deletions(-) diff --git a/WHATS_NEW b/WHATS_NEW index 11ebd0ccb..a8c0f9d10 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,8 @@ Version 2.02.14 - =================================== + Add some missing bounds checks on 32 bit extent counters. + Add Petabyte and Exabyte support. + Fix lvcreate error message when 0 extents requested. lvremove man page: volumes must be cluster inactive before being removed. Protect .cache manipulations with fcntl locking. Change .cache timestamp comparisons to use ctime. diff --git a/lib/display/display.c b/lib/display/display.c index 5b9cd640d..ef4fa4f84 100644 --- a/lib/display/display.c +++ b/lib/display/display.c @@ -82,6 +82,12 @@ uint64_t units_to_bytes(const char *units, char *unit_type) case 't': v *= KILO * KILO * KILO * KILO; break; + case 'p': + v *= KILO * KILO * KILO * KILO * KILO; + break; + case 'e': + v *= KILO * KILO * KILO * KILO * KILO * KILO; + break; #undef KILO #define KILO UINT64_C(1000) case 'K': @@ -96,6 +102,12 @@ uint64_t units_to_bytes(const char *units, char *unit_type) case 'T': v *= KILO * KILO * KILO * KILO; break; + case 'P': + v *= KILO * KILO * KILO * KILO * KILO; + break; + case 'E': + v *= KILO * KILO * KILO * KILO * KILO * KILO; + break; #undef KILO default: return 0; @@ -143,6 +155,8 @@ static const char *_display_size(struct cmd_context *cmd, uint64_t size, size_le uint64_t units = UINT64_C(1024); char *size_buf = NULL; const char *size_str[][3] = { + {" Exabyte", " EB", "E"}, + {" Petabyte", " PB", "P"}, {" Terabyte", " TB", "T"}, {" Gigabyte", " GB", "G"}, {" Megabyte", " MB", "M"}, @@ -161,7 +175,7 @@ static const char *_display_size(struct cmd_context *cmd, uint64_t size, size_le suffix = cmd->current_settings.suffix; - for (s = 0; s < 8; s++) + for (s = 0; s < 10; s++) if (toupper((int) cmd->current_settings.unit_type) == *size_str[s][2]) break; @@ -171,7 +185,7 @@ static const char *_display_size(struct cmd_context *cmd, uint64_t size, size_le return size_buf; } - if (s < 8) { + if (s < 10) { byte = cmd->current_settings.unit_factor; size *= UINT64_C(512); } else { @@ -181,7 +195,7 @@ static const char *_display_size(struct cmd_context *cmd, uint64_t size, size_le units = UINT64_C(1000); else units = UINT64_C(1024); - byte = units * units * units; + byte = units * units * units * units * units; s = 0; while (size_str[s] && size < byte) s++, byte /= units; diff --git a/lib/format_text/export.c b/lib/format_text/export.c index aaf4b9113..d8127e6d9 100644 --- a/lib/format_text/export.c +++ b/lib/format_text/export.c @@ -221,6 +221,8 @@ static int _sectors_to_units(uint64_t sectors, char *buffer, size_t s) "Megabytes", "Gigabytes", "Terabytes", + "Petabytes", + "Exabytes", NULL }; diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c index 394ed6c91..bd0e1be68 100644 --- a/lib/format_text/format-text.c +++ b/lib/format_text/format-text.c @@ -1408,6 +1408,7 @@ static int _text_pv_setup(const struct format_type *fmt, uint64_t pe_end = 0; unsigned mda_count = 0; uint64_t mda_size2 = 0; + uint64_t pe_count; /* FIXME Cope with pvchange */ /* FIXME Merge code with _text_create_text_instance */ @@ -1473,8 +1474,17 @@ static int _text_pv_setup(const struct format_type *fmt, pv->pe_start + mda_size2; /* Recalculate number of extents that will fit */ - if (!pv->pe_count) - pv->pe_count = (pv->size - pv->pe_start - mda_size2) / vg->extent_size; + if (!pv->pe_count) { + pe_count = (pv->size - pv->pe_start - mda_size2) / + vg->extent_size; + if (pe_count > UINT32_MAX) { + log_error("PV %s too large for extent size %s.", + dev_name(pv->dev), + display_size(vg->cmd, (uint64_t) vg->extent_size)); + return 0; + } + pv->pe_count = (uint32_t) pe_count; + } /* Unlike LVM1, we don't store this outside a VG */ /* FIXME Default from config file? vgextend cmdline flag? */ diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c index 0f153a659..1a28b83ba 100644 --- a/lib/metadata/metadata.c +++ b/lib/metadata/metadata.c @@ -23,6 +23,7 @@ #include "str_list.h" #include "pv_alloc.h" #include "activate.h" +#include "display.h" #include @@ -122,6 +123,15 @@ static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg, pvl->pv = pv; list_add(&vg->pvs, &pvl->list); + if ((uint64_t) vg->extent_count + pv->pe_count > UINT32_MAX) { + log_error("Unable to add %s to %s: new extent count (%" + PRIu64 ") exceeds limit (%" PRIu32 ").", + pv_name, vg->name, + (uint64_t) vg->extent_count + pv->pe_count, + UINT32_MAX); + return 0; + } + vg->pv_count++; vg->extent_count += pv->pe_count; vg->free_count += pv->pe_count; diff --git a/man/lvcreate.8 b/man/lvcreate.8 index c0e8959fd..3cafb5c1f 100644 --- a/man/lvcreate.8 +++ b/man/lvcreate.8 @@ -70,10 +70,11 @@ This can also be expressed as a percentage of the total space in the Volume Group with the suffix %VG or of the remaining free space with the suffix %FREE. .TP -.I \-L, \-\-size LogicalVolumeSize[kKmMgGtT] +.I \-L, \-\-size LogicalVolumeSize[kKmMgGtTpPeE] Gives the size to allocate for the new logical volume. A size suffix of K for kilobytes, M for megabytes, -G for gigabytes or T for terabytes is optional. +G for gigabytes, T for terabytes, P for petabytes +or E for exabytes is optional. .br Default unit is megabytes. .TP diff --git a/man/lvextend.8 b/man/lvextend.8 index 255aa21dd..ba48ba374 100644 --- a/man/lvextend.8 +++ b/man/lvextend.8 @@ -30,10 +30,12 @@ in the Volume Group with the suffix %VG or relative to the existing size of the Logical Volume with the suffix %LV or as a percentage of the remaining free space in the Volume Group with the suffix %FREE. .TP -.I \-L, \-\-size [+]LogicalVolumeSize[kKmMgGtT] +.I \-L, \-\-size [+]LogicalVolumeSize[kKmMgGtTpPeE] Extend or set the logical volume size in units in units of megabytes. -A size suffix of M for megabytes, G for gigabytes or T for terabytes is -optional. With the + sign the value is added to the actual size +A size suffix of M for megabytes, +G for gigabytes, T for terabytes, P for petabytes +or E for exabytes is optional. +With the + sign the value is added to the actual size of the logical volume and without it, the value is taken as an absolute one. .TP .I \-i, \-\-stripes Stripes diff --git a/man/lvreduce.8 b/man/lvreduce.8 index 3a0823145..e7180cb87 100644 --- a/man/lvreduce.8 +++ b/man/lvreduce.8 @@ -46,10 +46,11 @@ in the Volume Group with the suffix %VG or relative to the existing size of the Logical Volume with the suffix %LV or as a percentage of the remaining free space in the Volume Group with the suffix %FREE. .TP -.I \-L, \-\-size [\-]LogicalVolumeSize[kKmMgGtT] +.I \-L, \-\-size [\-]LogicalVolumeSize[kKmMgGtTpPeE] Reduce or set the logical volume size in units of megabyte by default. -A size suffix of k for kilobyte, m for megabyte, g for gigabyte or -t for terabyte is optional. +A size suffix of k for kilobyte, m for megabyte, +g for gigabytes, t for terabytes, p for petabytes +or e for exabytes is optional. With the - sign the value will be subtracted from the logical volume's actual size and without it it will be taken as an absolute size. diff --git a/man/lvresize.8 b/man/lvresize.8 index 2a3f50c3f..2b63cd994 100644 --- a/man/lvresize.8 +++ b/man/lvresize.8 @@ -34,10 +34,12 @@ in the Volume Group with the suffix %VG or relative to the existing size of the Logical Volume with the suffix %LV or as a percentage of the remaining free space in the Volume Group with the suffix %FREE. .TP -.I \-L, \-\-size [+/-]LogicalVolumeSize[kKmMgGtT] +.I \-L, \-\-size [+/-]LogicalVolumeSize[kKmMgGtTpPeE] Change or set the logical volume size in units of megabytes. -A size suffix of M for megabytes, G for gigabytes or T for terabytes is -optional. With the + or - sign the value is added to or subtracted from +A size suffix of M for megabytes, +G for gigabytes, T for terabytes, P for petabytes +or E for exabytes is optional. +With the + or - sign the value is added to or subtracted from the actual size of the logical volume and without it, the value is taken as an absolute one. .TP diff --git a/tools/commands.h b/tools/commands.h index 928fa676e..0daa19f4c 100644 --- a/tools/commands.h +++ b/tools/commands.h @@ -19,7 +19,7 @@ xx(e2fsadm, "e2fsadm " "[-d|--debug] " "[-h|--help] " "[-n|--nofsck]" "\n" "\t{[-l|--extents] [+|-]LogicalExtentsNumber |" "\n" - "\t [-L|--size] [+|-]LogicalVolumeSize[kKmMgGtT]}" "\n" + "\t [-L|--size] [+|-]LogicalVolumeSize[kKmMgGtTpPeE]}" "\n" "\t[-t|--test] " "\n" "\t[-v|--verbose] " "\n" "\t[--version] " "\n" @@ -117,7 +117,7 @@ xx(lvcreate, "\t[-h|-?|--help]\n" "\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n" "\t{-l|--extents LogicalExtentsNumber |\n" - "\t -L|--size LogicalVolumeSize[kKmMgGtT]}\n" + "\t -L|--size LogicalVolumeSize[kKmMgGtTpPeE]}\n" "\t[-M|--persistent {y|n}] [--major major] [--minor minor]\n" "\t[-m|--mirrors Mirrors [--nosync] [--corelog]]\n" "\t[-n|--name LogicalVolumeName]\n" @@ -141,7 +141,7 @@ xx(lvcreate, "\t[-h|-?|--help]\n" "\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n" "\t{-l|--extents LogicalExtentsNumber[%{VG|LV|FREE}] |\n" - "\t -L|--size LogicalVolumeSize[kKmMgGtT]}\n" + "\t -L|--size LogicalVolumeSize[kKmMgGtTpPeE]}\n" "\t[-M|--persistent {y|n}] [--major major] [--minor minor]\n" "\t[-n|--name LogicalVolumeName]\n" "\t[-p|--permission {r|rw}]\n" @@ -206,7 +206,7 @@ xx(lvextend, "\t[-h|--help]\n" "\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n" "\t{-l|--extents [+]LogicalExtentsNumber[%{VG|FREE}] |\n" - "\t -L|--size [+]LogicalVolumeSize[kKmMgGtT]}\n" + "\t -L|--size [+]LogicalVolumeSize[kKmMgGtTpPeE]}\n" "\t[-m|--mirrors Mirrors]\n" "\t[-n|--nofsck]\n" "\t[-r|--resizefs]\n" @@ -271,7 +271,7 @@ xx(lvreduce, "\t[-f|--force]\n" "\t[-h|--help]\n" "\t{-l|--extents [-]LogicalExtentsNumber[%{VG|LV|FREE}] |\n" - "\t -L|--size [-]LogicalVolumeSize[kKmMgGtT]}\n" + "\t -L|--size [-]LogicalVolumeSize[kKmMgGtTpPeE]}\n" "\t[-n|--nofsck]\n" "\t[-r|--resizefs]\n" "\t[-t|--test]\n" @@ -320,7 +320,7 @@ xx(lvresize, "\t[-h|--help]\n" "\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n" "\t{-l|--extents [+|-]LogicalExtentsNumber[%{VG|LV|FREE}] |\n" - "\t -L|--size [+|-]LogicalVolumeSize[kKmMgGtT]}\n" + "\t -L|--size [+|-]LogicalVolumeSize[kKmMgGtTpPeE]}\n" "\t[-n|--nofsck]\n" "\t[-r|--resizefs]\n" "\t[-t|--test]\n" @@ -396,7 +396,7 @@ xx(pvresize, "pvresize " "\n" "\t[-d|--debug]" "\n" "\t[-h|-?|--help] " "\n" - "\t[--setphysicalvolumesize PhysicalVolumeSize[kKmMgGtT]" "\n" + "\t[--setphysicalvolumesize PhysicalVolumeSize[kKmMgGtTpPeE]" "\n" "\t[-t|--test] " "\n" "\t[-v|--verbose] " "\n" "\t[--version] " "\n" @@ -414,8 +414,8 @@ xx(pvcreate, "\t[--labelsector sector] " "\n" "\t[-M|--metadatatype 1|2]" "\n" "\t[--metadatacopies #copies]" "\n" - "\t[--metadatasize MetadataSize[kKmMgGtT]]" "\n" - "\t[--setphysicalvolumesize PhysicalVolumeSize[kKmMgGtT]" "\n" + "\t[--metadatasize MetadataSize[kKmMgGtTpPeE]]" "\n" + "\t[--setphysicalvolumesize PhysicalVolumeSize[kKmMgGtTpPeE]" "\n" "\t[-t|--test] " "\n" "\t[-u|--uuid uuid] " "\n" "\t[-v|--verbose] " "\n" @@ -612,7 +612,7 @@ xx(vgchange, "\t -x|--resizeable {y|n} |" "\n" "\t -l|--logicalvolume MaxLogicalVolumes |" "\n" "\t -p|--maxphysicalvolumes MaxPhysicalVolumes |" "\n" - "\t -s|--physicalextentsize PhysicalExtentSize[kKmMgGtT] |" "\n" + "\t -s|--physicalextentsize PhysicalExtentSize[kKmMgGtTpPeE] |" "\n" "\t --addtag Tag |\n" "\t --deltag Tag}\n" "\t[VolumeGroupName...]\n", @@ -639,7 +639,7 @@ xx(vgconvert, "\t[--labelsector sector] " "\n" "\t[-M|--metadatatype 1|2]" "\n" "\t[--metadatacopies #copies]" "\n" - "\t[--metadatasize MetadataSize[kKmMgGtT]]" "\n" + "\t[--metadatasize MetadataSize[kKmMgGtTpPeE]]" "\n" "\t[-t|--test] " "\n" "\t[-v|--verbose] " "\n" "\t[--version] " "\n" @@ -660,7 +660,7 @@ xx(vgcreate, "\t[-l|--maxlogicalvolumes MaxLogicalVolumes]" "\n" "\t[-M|--metadatatype 1|2] " "\n" "\t[-p|--maxphysicalvolumes MaxPhysicalVolumes] " "\n" - "\t[-s|--physicalextentsize PhysicalExtentSize[kKmMgGtT]] " "\n" + "\t[-s|--physicalextentsize PhysicalExtentSize[kKmMgGtTpPeE]] " "\n" "\t[-t|--test] " "\n" "\t[-v|--verbose]" "\n" "\t[--version] " "\n" diff --git a/tools/lvcreate.c b/tools/lvcreate.c index 285ceca54..d2de870a6 100644 --- a/tools/lvcreate.c +++ b/tools/lvcreate.c @@ -556,7 +556,16 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp) display_size(cmd, tmp_size)); } - lp->extents = tmp_size / vg->extent_size; + if (tmp_size > (uint64_t) UINT32_MAX * vg->extent_size) { + log_error("Volume too large (%s) for extent size %s. " + "Upper limit is %s.", + display_size(cmd, tmp_size), + display_size(cmd, vg->extent_size), + display_size(cmd, (uint64_t) UINT32_MAX * + vg->extent_size)); + return 0; + } + lp->extents = (uint64_t) tmp_size / vg->extent_size; } switch(lp->percent) { @@ -618,8 +627,7 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp) } if (!lp->extents) { - log_error("Unable to create logical volume %s with no extents", - lp->lv_name); + log_error("Unable to create new logical volume with no extents"); return 0; } diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c index b46e339e3..c383b35e7 100644 --- a/tools/lvmcmdline.c +++ b/tools/lvmcmdline.c @@ -186,7 +186,7 @@ static int _size_arg(struct cmd_context *cmd __attribute((unused)), struct arg * { char *ptr; int i; - static const char *suffixes = "kmgt"; + static const char *suffixes = "kmgtpe"; char *val; double v; -- 2.43.5