summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--WHATS_NEW1
-rw-r--r--lib/metadata/metadata-exported.h3
-rw-r--r--lib/metadata/pv_manip.c40
-rw-r--r--lib/misc/util.h10
-rw-r--r--man/lvcreate.810
-rw-r--r--man/lvextend.816
-rw-r--r--man/lvresize.812
-rw-r--r--tools/commands.h6
-rw-r--r--tools/lvcreate.c13
-rw-r--r--tools/lvmcmdline.c3
-rw-r--r--tools/lvresize.c31
-rw-r--r--tools/tools.h3
12 files changed, 123 insertions, 25 deletions
diff --git a/WHATS_NEW b/WHATS_NEW
index d41353eb..856eb59b 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.29 -
==================================
+ Add %PVS extents option to lvresize, lvextend, and lvcreate.
Moved the obsolete test subdirectory to old-tests.
Remove no-longer-correct restrictions on PV arg count with stripes/mirrors.
Fix strdup memory leak in str_list_dup().
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 7b468897..d4b3ec4a 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -329,6 +329,9 @@ int pv_resize_single(struct cmd_context *cmd,
int pv_analyze(struct cmd_context *cmd, const char *pv_name,
uint64_t label_sector);
+/* FIXME: move internal to library */
+uint32_t pv_list_extents_free(struct list *pvh);
+
struct volume_group *vg_create(struct cmd_context *cmd, const char *name,
uint32_t extent_size, uint32_t max_pv,
uint32_t max_lv, alloc_policy_t alloc,
diff --git a/lib/metadata/pv_manip.c b/lib/metadata/pv_manip.c
index 740dc5ae..dcef00e2 100644
--- a/lib/metadata/pv_manip.c
+++ b/lib/metadata/pv_manip.c
@@ -215,6 +215,46 @@ void merge_pv_segments(struct pv_segment *peg1, struct pv_segment *peg2)
}
/*
+ * Calculate the overlap, in extents, between a struct pv_segment and
+ * a struct pe_range.
+ */
+static uint32_t _overlap_pe(struct pv_segment *pvseg,
+ struct pe_range *per)
+{
+ uint32_t start;
+ uint32_t end;
+
+ start = max(pvseg->pe, per->start);
+ end = min(pvseg->pe + pvseg->len, per->start + per->count);
+ if (end < start)
+ return 0;
+ else
+ return end - start;
+}
+
+/*
+ * Returns: number of free PEs in a struct pv_list
+ */
+uint32_t pv_list_extents_free(struct list *pvh)
+{
+ struct pv_list *pvl;
+ struct pe_range *per;
+ uint32_t extents = 0;
+ struct pv_segment *pvseg;
+
+ list_iterate_items(pvl, pvh) {
+ list_iterate_items(per, pvl->pe_ranges) {
+ list_iterate_items(pvseg, &pvl->pv->segments) {
+ if (!pvseg->lvseg) /* free space */
+ extents += _overlap_pe(pvseg, per);
+ }
+ }
+ }
+
+ return extents;
+}
+
+/*
* Check all pv_segments in VG for consistency
*/
int check_pv_segments(struct volume_group *vg)
diff --git a/lib/misc/util.h b/lib/misc/util.h
index a178e036..694864cb 100644
--- a/lib/misc/util.h
+++ b/lib/misc/util.h
@@ -15,6 +15,16 @@
#ifndef _LVM_UTIL_H
#define _LVM_UTIL_H
+#define min(a, b) ({ typeof(a) _a = (a); \
+ typeof(b) _b = (b); \
+ (void) (&_a == &_b); \
+ _a < _b ? _a : _b; })
+
+#define max(a, b) ({ typeof(a) _a = (a); \
+ typeof(b) _b = (b); \
+ (void) (&_a == &_b); \
+ _a > _b ? _a : _b; })
+
char *last_path_component(char const *name);
#endif
diff --git a/man/lvcreate.8 b/man/lvcreate.8
index 56ff8216..f99d6297 100644
--- a/man/lvcreate.8
+++ b/man/lvcreate.8
@@ -8,7 +8,7 @@ lvcreate \- create a logical volume in an existing volume group
[\-A/\-\-autobackup y/n] [\-C/\-\-contiguous y/n] [\-d/\-\-debug]
[\-h/\-?/\-\-help]
[\-i/\-\-stripes Stripes [\-I/\-\-stripesize StripeSize]]
-{\-l/\-\-extents LogicalExtentsNumber[%{VG|FREE}] |
+{\-l/\-\-extents LogicalExtentsNumber[%{VG|PVS|FREE}] |
\-L/\-\-size LogicalVolumeSize[kKmMgGtT]}
[\-M/\-\-persistent y/n] [\-\-minor minor]
[\-m/\-\-mirrors Mirrors [\-\-nosync] [\-\-mirrorlog {disk|log}] [\-\-corelog]
@@ -63,12 +63,14 @@ 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[%{VG|FREE}]
+.I \-l, \-\-extents LogicalExtentsNumber[%{VG|PVS|FREE}]
Gives the number of logical extents to allocate for the new
logical volume.
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.
+in the Volume Group with the suffix %VG, of the remaining
+free space in the Volume Group with the suffix %FREE, or
+of the remaining free space for the specified PhysicalVolume(s)
+with the suffix %PVS,
.TP
.I \-L, \-\-size LogicalVolumeSize[kKmMgGtTpPeE]
Gives the size to allocate for the new logical volume.
diff --git a/man/lvextend.8 b/man/lvextend.8
index 888e0112..7a3836c4 100644
--- a/man/lvextend.8
+++ b/man/lvextend.8
@@ -6,7 +6,7 @@ lvextend \- extend the size of a logical volume
[\-\-alloc AllocationPolicy]
[\-A/\-\-autobackup y/n] [\-d/\-\-debug] [\-h/\-?/\-\-help]
[\-i/\-\-stripes Stripes [\-I/\-\-stripesize StripeSize]]
-{\-l/\-\-extents [+]LogicalExtentsNumber[%{VG|LV|FREE}] |
+{\-l/\-\-extents [+]LogicalExtentsNumber[%{VG|LV|PVS|FREE}] |
\-L/\-\-size [+]LogicalVolumeSize[kKmMgGtT]}
[\-t/\-\-test]
[\-v/\-\-verbose] LogicalVolumePath [PhysicalVolumePath...]
@@ -21,14 +21,16 @@ volume use
.SH OPTIONS
See \fBlvm\fP for common options.
.TP
-.I \-l, \-\-extents [+]LogicalExtentsNumber[%{VG|LV|FREE}]
+.I \-l, \-\-extents [+]LogicalExtentsNumber[%{VG|LV|PVS|FREE}]
Extend or set the logical volume size in units of logical extents.
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.
The number can also be expressed as a percentage of the total space
-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.
+in the Volume Group with the suffix %VG, relative to the existing
+size of the Logical Volume with the suffix %LV, of the remaining
+free space for the specified PhysicalVolume(s) with the suffix %PVS,
+or as a percentage of the remaining free space in the Volume Group
+with the suffix %FREE.
.TP
.I \-L, \-\-size [+]LogicalVolumeSize[kKmMgGtTpPeE]
Extend or set the logical volume size in units of megabytes.
@@ -54,6 +56,10 @@ StripeSize must be 2^n (n = 2 to 9)
that logical volume by 54MB on physical volume /dev/sdk3.
This is only possible if /dev/sdk3 is a member of volume group vg01 and
there are enough free physical extents in it.
+
+"lvextend /dev/vg01/lvol01 /dev/sdk3" tries to extend the size of that
+logical volume by the amount of free space on physical volume /dev/sdk3.
+This is equivalent to specifying "-l +100%PVS" on the command line.
.SH SEE ALSO
.BR lvm (8),
.BR lvcreate (8),
diff --git a/man/lvresize.8 b/man/lvresize.8
index 2b63cd99..6666fa87 100644
--- a/man/lvresize.8
+++ b/man/lvresize.8
@@ -6,7 +6,7 @@ lvresize \- resize a logical volume
[\-\-alloc AllocationPolicy]
[\-A/\-\-autobackup y/n] [\-d/\-\-debug] [\-h/\-?/\-\-help]
[\-i/\-\-stripes Stripes [\-I/\-\-stripesize StripeSize]]
-{\-l/\-\-extents [+]LogicalExtentsNumber[%{VG|LV|FREE}] |
+{\-l/\-\-extents [+]LogicalExtentsNumber[%{VG|LV|PVS|FREE}] |
\-L/\-\-size [+]LogicalVolumeSize[kKmMgGtT]}
[\-t/\-\-test]
[\-v/\-\-verbose] LogicalVolumePath [PhysicalVolumePath...]
@@ -25,14 +25,16 @@ volume use
.SH OPTIONS
See \fBlvm\fP for common options.
.TP
-.I \-l, \-\-extents [+/-]LogicalExtentsNumber[%{VG|LV|FREE}]
+.I \-l, \-\-extents [+/-]LogicalExtentsNumber[%{VG|LV|PVS|FREE}]
Change or set the logical volume size in units of logical extents.
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.
The number can also be expressed as a percentage of the total space
-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.
+in the Volume Group with the suffix %VG, relative to the existing
+size of the Logical Volume with the suffix %LV, as a percentage of
+the remaining free space of the PhysicalVolumes on the command line with the
+suffix %PVS, or as a percentage of the remaining free space in the
+Volume Group with the suffix %FREE.
.TP
.I \-L, \-\-size [+/-]LogicalVolumeSize[kKmMgGtTpPeE]
Change or set the logical volume size in units of megabytes.
diff --git a/tools/commands.h b/tools/commands.h
index 1ab5e380..cebb3060 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -144,7 +144,7 @@ xx(lvcreate,
"\t[-d|--debug]\n"
"\t[-h|-?|--help]\n"
"\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
- "\t{-l|--extents LogicalExtentsNumber[%{VG|LV|FREE}] |\n"
+ "\t{-l|--extents LogicalExtentsNumber[%{VG|LV|PVS|FREE}] |\n"
"\t -L|--size LogicalVolumeSize[kKmMgGtTpPeE]}\n"
"\t[-M|--persistent {y|n}] [--major major] [--minor minor]\n"
"\t[-n|--name LogicalVolumeName]\n"
@@ -209,7 +209,7 @@ xx(lvextend,
"\t[-d|--debug]\n"
"\t[-h|--help]\n"
"\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
- "\t{-l|--extents [+]LogicalExtentsNumber[%{VG|FREE}] |\n"
+ "\t{-l|--extents [+]LogicalExtentsNumber[%{VG|PVS|FREE}] |\n"
"\t -L|--size [+]LogicalVolumeSize[kKmMgGtTpPeE]}\n"
"\t[-m|--mirrors Mirrors]\n"
"\t[-n|--nofsck]\n"
@@ -323,7 +323,7 @@ xx(lvresize,
"\t[-d|--debug]\n"
"\t[-h|--help]\n"
"\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
- "\t{-l|--extents [+|-]LogicalExtentsNumber[%{VG|LV|FREE}] |\n"
+ "\t{-l|--extents [+|-]LogicalExtentsNumber[%{VG|LV|PVS|FREE}] |\n"
"\t -L|--size [+|-]LogicalVolumeSize[kKmMgGtTpPeE]}\n"
"\t[-n|--nofsck]\n"
"\t[-r|--resizefs]\n"
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index bf990722..9986be22 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -490,6 +490,7 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
char lv_name_buf[128];
const char *lv_name;
struct lvinfo info;
+ uint32_t pv_extent_count;
status |= lp->permission | VISIBLE_LV;
@@ -574,8 +575,18 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
case PERCENT_FREE:
lp->extents = lp->extents * vg->free_count / 100;
break;
+ case PERCENT_PVS:
+ if (!lp->pv_count) {
+ log_error("Please specify physical volume(s) "
+ "with %%PVS");
+ return 0;
+ }
+ pv_extent_count = pv_list_extents_free(pvh);
+ lp->extents = lp->extents * pv_extent_count / 100;
+ break;
case PERCENT_LV:
- log_error("Please express size as %%VG or %%FREE.");
+ log_error("Please express size as %%VG, %%PVS, or "
+ "%%FREE.");
return 0;
case PERCENT_NONE:
break;
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
index b5e2e444..0f5cc085 100644
--- a/tools/lvmcmdline.c
+++ b/tools/lvmcmdline.c
@@ -269,6 +269,9 @@ int int_arg_with_sign_and_percent(struct cmd_context *cmd __attribute((unused)),
a->percent = PERCENT_VG;
else if (!strcasecmp(ptr, "L") || !strcasecmp(ptr, "LV"))
a->percent = PERCENT_LV;
+ else if (!strcasecmp(ptr, "P") || !strcasecmp(ptr, "PV") ||
+ !strcasecmp(ptr, "PVS"))
+ a->percent = PERCENT_PVS;
else if (!strcasecmp(ptr, "F") || !strcasecmp(ptr, "FR") ||
!strcasecmp(ptr, "FREE"))
a->percent = PERCENT_FREE;
diff --git a/tools/lvresize.c b/tools/lvresize.c
index 7c17b392..e69c8dd4 100644
--- a/tools/lvresize.c
+++ b/tools/lvresize.c
@@ -182,8 +182,20 @@ static int _lvresize_params(struct cmd_context *cmd, int argc, char **argv,
if (!strcmp(cmd_name, "lvextend"))
lp->resize = LV_EXTEND;
- if (arg_count(cmd, extents_ARG) + arg_count(cmd, size_ARG) != 1) {
- log_error("Please specify either size or extents (not both)");
+ /*
+ * Allow omission of extents and size if the user has given us
+ * one or more PVs. Most likely, the intent was "resize this
+ * LV the best you can with these PVs"
+ */
+ if ((arg_count(cmd, extents_ARG) + arg_count(cmd, size_ARG) == 0) &&
+ (argc >= 2)) {
+ lp->extents = 100;
+ lp->percent = PERCENT_PVS;
+ lp->sign = SIGN_PLUS;
+ } else if ((arg_count(cmd, extents_ARG) +
+ arg_count(cmd, size_ARG) != 1)) {
+ log_error("Please specify either size or extents but not "
+ "both.");
return 0;
}
@@ -246,6 +258,7 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp)
uint32_t seg_mirrors = 0;
uint32_t extents_used = 0;
uint32_t size_rest;
+ uint32_t pv_extent_count = 0;
alloc_policy_t alloc;
struct logical_volume *lock_lv;
struct lv_list *lvl;
@@ -319,6 +332,12 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp)
lp->extents = lp->size / vg->extent_size;
}
+ if (!(pvh = lp->argc ? create_pv_list(cmd->mem, vg, lp->argc,
+ lp->argv, 1) : &vg->pvs)) {
+ stack;
+ return ECMD_FAILED;
+ }
+
switch(lp->percent) {
case PERCENT_VG:
lp->extents = lp->extents * vg->extent_count / 100;
@@ -329,6 +348,10 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp)
case PERCENT_LV:
lp->extents = lp->extents * lv->le_count / 100;
break;
+ case PERCENT_PVS:
+ pv_extent_count = pv_list_extents_free(pvh);
+ lp->extents = lp->extents * pv_extent_count / 100;
+ break;
case PERCENT_NONE:
break;
}
@@ -539,10 +562,6 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp)
if (lp->resize == LV_REDUCE) {
if (lp->argc)
log_warn("Ignoring PVs on command line when reducing");
- } else if (!(pvh = lp->argc ? create_pv_list(cmd->mem, vg, lp->argc,
- lp->argv, 1) : &vg->pvs)) {
- stack;
- return ECMD_FAILED;
}
if (lp->resize == LV_REDUCE || lp->resizefs) {
diff --git a/tools/tools.h b/tools/tools.h
index d0d3d300..436cc9c5 100644
--- a/tools/tools.h
+++ b/tools/tools.h
@@ -83,7 +83,8 @@ typedef enum {
PERCENT_NONE = 0,
PERCENT_VG,
PERCENT_FREE,
- PERCENT_LV
+ PERCENT_LV,
+ PERCENT_PVS
} percent_t;
enum {