From 1832f310ace893d2ffa3327a0d20c34fc9c69600 Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Tue, 11 May 2004 16:01:58 +0000 Subject: [PATCH] Add --type to lvcreate/resize. Add virtual segment types, zero and error. A large sparse device can be constructed as a writeable snapshot of a large zero device. --- WHATS_NEW | 3 + lib/Makefile.in | 4 +- lib/commands/toolcontext.c | 10 ++++ lib/error/errseg.c | 101 ++++++++++++++++++++++++++++++++++ lib/format_text/export.c | 3 +- lib/format_text/flags.c | 1 + lib/format_text/import_vsn1.c | 3 + lib/metadata/lv_manip.c | 44 ++++++++++++--- lib/metadata/metadata.h | 1 + lib/metadata/segtypes.h | 6 +- lib/report/report.c | 2 + lib/snapshot/snapshot.c | 2 +- lib/zero/zero.c | 101 ++++++++++++++++++++++++++++++++++ tools/args.h | 1 + tools/commands.h | 9 ++- tools/lvcreate.c | 63 +++++++++------------ tools/lvmcmdline.c | 8 +++ tools/lvresize.c | 45 ++++++++------- tools/tools.h | 1 + 19 files changed, 336 insertions(+), 72 deletions(-) create mode 100644 lib/error/errseg.c create mode 100644 lib/zero/zero.c diff --git a/WHATS_NEW b/WHATS_NEW index 9daf0f035..7abfb30ec 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,8 @@ Version 2.00.16 - ============================= + Add virtual segment types, zero and error. A large sparse device can be +constructed as a writeable snapshot of a large zero segment. + Add --type to lvcreate/resize. Push lv_create & alloc policy up to tool level. Fix pvdisplay return code. Detect invalid LV names in arg lists. diff --git a/lib/Makefile.in b/lib/Makefile.in index 7d321cc36..c1f61f0d8 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -41,6 +41,7 @@ SOURCES =\ device/dev-io.c \ device/device.c \ display/display.c \ + error/errseg.c \ filters/filter-composite.c \ filters/filter-persistent.c \ filters/filter-regex.c \ @@ -77,7 +78,8 @@ SOURCES =\ regex/ttree.c \ report/report.c \ striped/striped.c \ - uuid/uuid.c + uuid/uuid.c \ + zero/zero.c ifeq ("@LVM1@", "internal") SOURCES +=\ diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c index 7955dcaa4..ff8a90b76 100644 --- a/lib/commands/toolcontext.c +++ b/lib/commands/toolcontext.c @@ -677,6 +677,16 @@ static int _init_segtypes(struct cmd_context *cmd) segtype->library = NULL; list_add(&cmd->segtypes, &segtype->list); + if (!(segtype = init_zero_segtype(cmd))) + return 0; + segtype->library = NULL; + list_add(&cmd->segtypes, &segtype->list); + + if (!(segtype = init_error_segtype(cmd))) + return 0; + segtype->library = NULL; + list_add(&cmd->segtypes, &segtype->list); + #ifdef SNAPSHOT_INTERNAL if (!(segtype = init_snapshot_segtype(cmd))) return 0; diff --git a/lib/error/errseg.c b/lib/error/errseg.c new file mode 100644 index 000000000..e0310e56c --- /dev/null +++ b/lib/error/errseg.c @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2004 Red Hat, Inc. All rights reserved. + * + * This file is part of LVM2. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License v.2. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "lib.h" +#include "pool.h" +#include "list.h" +#include "toolcontext.h" +#include "segtypes.h" +#include "display.h" +#include "text_export.h" +#include "text_import.h" +#include "config.h" +#include "str_list.h" +#include "targets.h" +#include "lvm-string.h" +#include "activate.h" + +static const char *_name(const struct lv_segment *seg) +{ + return seg->segtype->name; +} + +static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2) +{ + seg1->len += seg2->len; + seg1->area_len += seg2->area_len; + + return 1; +} + +#ifdef DEVMAPPER_SUPPORT +static int _compose_target_line(struct dev_manager *dm, struct pool *mem, + struct config_tree *cft, void **target_state, + struct lv_segment *seg, char *params, + size_t paramsize, const char **target, int *pos, + uint32_t *pvmove_mirror_count) +{ + /* error */ + + *target = "error"; + *params = '\0'; + + return 1; +} + +static int _target_present(void) +{ + static int checked = 0; + static int present = 0; + + if (!checked) + present = target_present("error"); + + checked = 1; + return present; +} +#endif + +static void _destroy(const struct segment_type *segtype) +{ + dbg_free((void *) segtype); +} + +static struct segtype_handler _error_ops = { + name:_name, + merge_segments:_merge_segments, +#ifdef DEVMAPPER_SUPPORT + compose_target_line:_compose_target_line, + target_present:_target_present, +#endif + destroy:_destroy, +}; + +struct segment_type *init_error_segtype(struct cmd_context *cmd) +{ + struct segment_type *segtype = dbg_malloc(sizeof(*segtype)); + + if (!segtype) { + stack; + return NULL; + } + + segtype->cmd = cmd; + segtype->ops = &_error_ops; + segtype->name = "error"; + segtype->private = NULL; + segtype->flags = SEG_CAN_SPLIT | SEG_VIRTUAL; + + return segtype; +} diff --git a/lib/format_text/export.c b/lib/format_text/export.c index d5ecb21bd..283fee29d 100644 --- a/lib/format_text/export.c +++ b/lib/format_text/export.c @@ -411,7 +411,8 @@ static int _print_segment(struct formatter *f, struct volume_group *vg, outf(f, "tags = %s", buffer); } - if (!seg->segtype->ops->text_export(seg, f)) { + if (seg->segtype->ops->text_export && + !seg->segtype->ops->text_export(seg, f)) { stack; return 0; } diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c index 16d413c33..282f0c55f 100644 --- a/lib/format_text/flags.c +++ b/lib/format_text/flags.c @@ -53,6 +53,7 @@ static struct flag _lv_flags[] = { {PVMOVE, "PVMOVE"}, {LOCKED, "LOCKED"}, {MIRRORED, NULL}, + {VIRTUAL, NULL}, {0, NULL} }; diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c index fc798f56c..f18d2eba8 100644 --- a/lib/format_text/import_vsn1.c +++ b/lib/format_text/import_vsn1.c @@ -319,6 +319,9 @@ static int _read_segment(struct pool *mem, struct volume_group *vg, if (seg->segtype->flags & SEG_AREAS_MIRRORED) lv->status |= MIRRORED; + if (seg->segtype->flags & SEG_VIRTUAL) + lv->status |= VIRTUAL; + return 1; } diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index b182f2c33..0dcf27ff1 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -238,7 +238,6 @@ static int _alloc_linear_area(struct logical_volume *lv, uint32_t *ix, return 0; } seg->le = *ix; - seg->le = *ix; seg->len = count; seg->area_len = count; seg->stripe_size = 0; @@ -277,7 +276,6 @@ static int _alloc_mirrored_area(struct logical_volume *lv, uint32_t *ix, seg->segtype = segtype; seg->le = *ix; seg->status = 0u; - seg->le = *ix; seg->len = count; seg->area_len = count; seg->stripe_size = 0; @@ -420,6 +418,31 @@ static int _alloc_next_free(struct logical_volume *lv, return 1; } +static int _alloc_virtual(struct logical_volume *lv, + uint32_t allocated, struct segment_type *segtype) +{ + struct lv_segment *seg; + + if (!(seg = alloc_lv_segment(lv->vg->cmd->mem, 0))) { + log_err("Couldn't allocate new zero segment."); + return 0; + } + + seg->lv = lv; + seg->segtype = segtype; + seg->status = 0u; + seg->le = allocated; + seg->len = lv->le_count - allocated; + seg->area_len = seg->len; + seg->stripe_size = 0; + seg->area_count = 0; + seg->extents_copied = 0u; + list_add(&lv->segments, &seg->list); + lv->status |= VIRTUAL; + + return 1; +} + /* * Chooses a correct allocation policy. */ @@ -435,6 +458,9 @@ static int _allocate(struct volume_group *vg, struct logical_volume *lv, struct list *pvms, *old_tail = lv->segments.p, *segh; struct lv_segment *seg; + if (segtype->flags & SEG_VIRTUAL) + return _alloc_virtual(lv, allocated, segtype); + if (!(scratch = pool_create(1024))) { stack; return 0; @@ -582,13 +608,13 @@ struct logical_volume *lv_create_empty(struct format_instance *fi, } int lv_extend(struct format_instance *fid, - struct logical_volume *lv, - struct segment_type *segtype, - uint32_t stripes, uint32_t stripe_size, - uint32_t mirrors, uint32_t extents, - struct physical_volume *mirrored_pv, uint32_t mirrored_pe, - uint32_t status, struct list *allocatable_pvs, - alloc_policy_t alloc) + struct logical_volume *lv, + struct segment_type *segtype, + uint32_t stripes, uint32_t stripe_size, + uint32_t mirrors, uint32_t extents, + struct physical_volume *mirrored_pv, uint32_t mirrored_pe, + uint32_t status, struct list *allocatable_pvs, + alloc_policy_t alloc) { uint32_t old_le_count = lv->le_count; uint64_t old_size = lv->size; diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h index b22fd164a..e9380da02 100644 --- a/lib/metadata/metadata.h +++ b/lib/metadata/metadata.h @@ -54,6 +54,7 @@ #define PVMOVE 0x00002000 /* VG LV SEG */ #define LOCKED 0x00004000 /* LV */ #define MIRRORED 0x00008000 /* LV - internal use only */ +#define VIRTUAL 0x00010000 /* LV - internal use only */ #define LVM_READ 0x00000100 /* LV VG */ #define LVM_WRITE 0x00000200 /* LV VG */ diff --git a/lib/metadata/segtypes.h b/lib/metadata/segtypes.h index 3ebb2c730..ef606e52e 100644 --- a/lib/metadata/segtypes.h +++ b/lib/metadata/segtypes.h @@ -29,7 +29,9 @@ struct dev_manager; #define SEG_CAN_SPLIT 0x00000001 #define SEG_AREAS_STRIPED 0x00000002 #define SEG_AREAS_MIRRORED 0x00000004 -#define SEG_FORMAT1_SUPPORT 0x00000008 +#define SEG_SNAPSHOT 0x00000008 +#define SEG_FORMAT1_SUPPORT 0x00000010 +#define SEG_VIRTUAL 0x00000020 struct segment_type { struct list list; @@ -72,6 +74,8 @@ struct segment_type *get_segtype_from_string(struct cmd_context *cmd, const char *str); struct segment_type *init_striped_segtype(struct cmd_context *cmd); +struct segment_type *init_zero_segtype(struct cmd_context *cmd); +struct segment_type *init_error_segtype(struct cmd_context *cmd); #ifdef SNAPSHOT_INTERNAL struct segment_type *init_snapshot_segtype(struct cmd_context *cmd); diff --git a/lib/report/report.c b/lib/report/report.c index 48dc72ced..955366fd9 100644 --- a/lib/report/report.c +++ b/lib/report/report.c @@ -263,6 +263,8 @@ static int _lvstatus_disp(struct report_handle *rh, struct field *field, repstr[0] = 'p'; else if (lv->status & MIRRORED) repstr[0] = 'm'; + else if (lv->status & VIRTUAL) + repstr[0] = 'v'; else if (lv_is_origin(lv)) repstr[0] = 'o'; else if (find_cow(lv)) diff --git a/lib/snapshot/snapshot.c b/lib/snapshot/snapshot.c index 58b68a50f..aad048ef4 100644 --- a/lib/snapshot/snapshot.c +++ b/lib/snapshot/snapshot.c @@ -159,7 +159,7 @@ struct segment_type *init_segtype(struct cmd_context *cmd) segtype->ops = &_snapshot_ops; segtype->name = "snapshot"; segtype->private = NULL; - segtype->flags = 0u; + segtype->flags = SEG_SNAPSHOT; return segtype; } diff --git a/lib/zero/zero.c b/lib/zero/zero.c new file mode 100644 index 000000000..b344fee4b --- /dev/null +++ b/lib/zero/zero.c @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2004 Red Hat, Inc. All rights reserved. + * + * This file is part of LVM2. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License v.2. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "lib.h" +#include "pool.h" +#include "list.h" +#include "toolcontext.h" +#include "segtypes.h" +#include "display.h" +#include "text_export.h" +#include "text_import.h" +#include "config.h" +#include "str_list.h" +#include "targets.h" +#include "lvm-string.h" +#include "activate.h" + +static const char *_name(const struct lv_segment *seg) +{ + return seg->segtype->name; +} + +static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2) +{ + seg1->len += seg2->len; + seg1->area_len += seg2->area_len; + + return 1; +} + +#ifdef DEVMAPPER_SUPPORT +static int _compose_target_line(struct dev_manager *dm, struct pool *mem, + struct config_tree *cft, void **target_state, + struct lv_segment *seg, char *params, + size_t paramsize, const char **target, int *pos, + uint32_t *pvmove_mirror_count) +{ + /* zero */ + + *target = "zero"; + *params = '\0'; + + return 1; +} + +static int _target_present(void) +{ + static int checked = 0; + static int present = 0; + + if (!checked) + present = target_present("zero"); + + checked = 1; + return present; +} +#endif + +static void _destroy(const struct segment_type *segtype) +{ + dbg_free((void *) segtype); +} + +static struct segtype_handler _zero_ops = { + name:_name, + merge_segments:_merge_segments, +#ifdef DEVMAPPER_SUPPORT + compose_target_line:_compose_target_line, + target_present:_target_present, +#endif + destroy:_destroy, +}; + +struct segment_type *init_zero_segtype(struct cmd_context *cmd) +{ + struct segment_type *segtype = dbg_malloc(sizeof(*segtype)); + + if (!segtype) { + stack; + return NULL; + } + + segtype->cmd = cmd; + segtype->ops = &_zero_ops; + segtype->name = "zero"; + segtype->private = NULL; + segtype->flags = SEG_CAN_SPLIT | SEG_VIRTUAL; + + return segtype; +} diff --git a/tools/args.h b/tools/args.h index cee939491..ee0439bc9 100644 --- a/tools/args.h +++ b/tools/args.h @@ -41,6 +41,7 @@ arg(deltag_ARG, '\0', "deltag", tag_arg) arg(refresh_ARG, '\0', "refresh", NULL) arg(mknodes_ARG, '\0', "mknodes", NULL) arg(minor_ARG, '\0', "minor", minor_arg) +arg(type_ARG, '\0', "type", segtype_arg) /* Allow some variations */ arg(resizable_ARG, '\0', "resizable", yes_no_arg) diff --git a/tools/commands.h b/tools/commands.h index 5fe4e8d7b..2afccc67f 100644 --- a/tools/commands.h +++ b/tools/commands.h @@ -89,6 +89,7 @@ xx(lvcreate, "\t[-p|--permission {r|rw}]\n" "\t[-r|--readahead ReadAheadSectors]\n" "\t[-t|--test]\n" + "\t[--type VolumeType]\n" "\t[-v|--verbose]\n" "\t[-Z|--zero {y|n}]\n" "\t[--version]\n" @@ -115,7 +116,7 @@ xx(lvcreate, autobackup_ARG, chunksize_ARG, contiguous_ARG, extents_ARG, major_ARG, minor_ARG, name_ARG, permission_ARG, persistent_ARG, readahead_ARG, size_ARG, - snapshot_ARG, stripes_ARG, stripesize_ARG, addtag_ARG, test_ARG, + snapshot_ARG, stripes_ARG, stripesize_ARG, addtag_ARG, test_ARG, type_ARG, zero_ARG) xx(lvdisplay, @@ -165,12 +166,13 @@ xx(lvextend, "\t{-l|--extents [+]LogicalExtentsNumber |\n" "\t -L|--size [+]LogicalVolumeSize[kKmMgGtT]}\n" "\t[-t|--test]\n" + "\t[--type VolumeType]\n" "\t[-v|--verbose]\n" "\t[--version]" "\n" "\tLogicalVolume[Path] [ PhysicalVolumePath... ]\n", autobackup_ARG, extents_ARG, size_ARG, stripes_ARG, - stripesize_ARG, test_ARG) + stripesize_ARG, test_ARG, type_ARG) xx(lvmchange, "With the device mapper, this is obsolete and does nothing.", @@ -270,12 +272,13 @@ xx(lvresize, "\t{-l|--extents [+|-]LogicalExtentsNumber |\n" "\t -L|--size [+|-]LogicalVolumeSize[kKmMgGtT]}\n" "\t[-t|--test]\n" + "\t[--type VolumeType]\n" "\t[-v|--verbose]\n" "\t[--version]" "\n" "\tLogicalVolume[Path] [ PhysicalVolumePath... ]\n", autobackup_ARG, extents_ARG, size_ARG, stripes_ARG, stripesize_ARG, - test_ARG) + test_ARG, type_ARG) xx(lvs, "Display information about logical volumes", diff --git a/tools/lvcreate.c b/tools/lvcreate.c index 8a18f72e2..3e00509dc 100644 --- a/tools/lvcreate.c +++ b/tools/lvcreate.c @@ -57,9 +57,7 @@ static int _read_name_params(struct lvcreate_params *lp, if (arg_count(cmd, name_ARG)) lp->lv_name = arg_value(cmd, name_ARG); - if (arg_count(cmd, snapshot_ARG)) { - lp->snapshot = 1; - + if (lp->snapshot) { if (!argc) { log_err("Please specify a logical volume to act as " "the snapshot origin."); @@ -143,20 +141,8 @@ static int _read_name_params(struct lvcreate_params *lp, static int _read_size_params(struct lvcreate_params *lp, struct cmd_context *cmd, int *pargc, char ***pargv) { - /* - * There are two mutually exclusive ways of specifying - * the size ... - */ - if (arg_count(cmd, extents_ARG) && arg_count(cmd, size_ARG)) { - log_error("Invalid combination of arguments"); - return 0; - } - - /* - * ... you must use one of them. - */ - if (arg_count(cmd, size_ARG) + arg_count(cmd, extents_ARG) == 0) { - log_error("Please indicate size using option -l or -L"); + if (arg_count(cmd, extents_ARG) + arg_count(cmd, size_ARG) != 1) { + log_error("Please specify either size or extents (not both)"); return 0; } @@ -186,20 +172,6 @@ static int _read_stripe_params(struct lvcreate_params *lp, { int argc = *pargc; - lp->stripes = 1; - - /* Default is striped */ - if (!(lp->segtype = get_segtype_from_string(cmd, "striped"))) { - stack; - return 0; - } - - if (arg_count(cmd, stripes_ARG)) { - lp->stripes = arg_uint_value(cmd, stripes_ARG, 1); - if (lp->stripes == 1) - log_print("Redundant stripes argument: default is 1"); - } - if (arg_count(cmd, stripesize_ARG)) { if (arg_sign_value(cmd, stripesize_ARG, 0) == SIGN_MINUS) { log_error("Negative stripesize is invalid"); @@ -248,11 +220,22 @@ static int _read_params(struct lvcreate_params *lp, struct cmd_context *cmd, memset(lp, 0, sizeof(*lp)); /* - * Check selected options are compatible and set defaults + * Check selected options are compatible and determine segtype */ - if (arg_count(cmd, snapshot_ARG)) { + lp->segtype = (struct segment_type *) + arg_ptr_value(cmd, type_ARG, + get_segtype_from_string(cmd, "striped")); + + lp->stripes = arg_uint_value(cmd, stripes_ARG, 1); + if (arg_count(cmd, stripes_ARG) && lp->stripes == 1) + log_print("Redundant stripes argument: default is 1"); + + if (arg_count(cmd, snapshot_ARG) || (lp->segtype->flags & SEG_SNAPSHOT)) + lp->snapshot = 1; + + if (lp->snapshot) { if (arg_count(cmd, zero_ARG)) { - log_error("-s and -Z are incompatible"); + log_error("-Z is incompatible with snapshots"); return 0; } if (arg_sign_value(cmd, chunksize_ARG, 0) == SIGN_MINUS) { @@ -263,11 +246,18 @@ static int _read_params(struct lvcreate_params *lp, struct cmd_context *cmd, log_verbose("Setting chunksize to %d sectors.", lp->chunk_size); } else { if (arg_count(cmd, chunksize_ARG)) { - log_error("-c is only available with -s"); + log_error("-c is only available with snapshots"); return 0; } } + if (activation() && lp->segtype->ops->target_present && + !lp->segtype->ops->target_present()) { + log_error("%s: Required device-mapper target(s) not " + "detected in your kernel", lp->segtype->name); + return 0; + } + if (!_read_name_params(lp, cmd, &argc, &argv) || !_read_size_params(lp, cmd, &argc, &argv) || !_read_stripe_params(lp, cmd, &argc, &argv)) @@ -482,7 +472,8 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp) return 0; } - if (vg->free_count < lp->extents) { + if (!(lp->segtype->flags & SEG_VIRTUAL) && + vg->free_count < lp->extents) { log_error("Insufficient free extents (%u) in volume group %s: " "%u required", vg->free_count, vg->name, lp->extents); return 0; diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c index 168e57385..d7848762e 100644 --- a/tools/lvmcmdline.c +++ b/tools/lvmcmdline.c @@ -287,6 +287,14 @@ int permission_arg(struct cmd_context *cmd, struct arg *a) return 1; } +int segtype_arg(struct cmd_context *cmd, struct arg *a) +{ + if (!(a->ptr = (void *) get_segtype_from_string(cmd, a->value))) + return 0; + + return 1; +} + char yes_no_prompt(const char *prompt, ...) { int c = 0; diff --git a/tools/lvresize.c b/tools/lvresize.c index e39f9b3f2..038d98a65 100644 --- a/tools/lvresize.c +++ b/tools/lvresize.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. + * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. * Copyright (C) 2004 Red Hat, Inc. All rights reserved. * * This file is part of LVM2. @@ -22,7 +22,7 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv) struct snapshot *snap; struct lvinfo info; uint32_t extents = 0; - uint32_t size = 0; + uint64_t size = 0; uint32_t stripes = 0, ssize = 0, stripesize_extents = 0; uint32_t seg_stripes = 0, seg_stripesize = 0, seg_size = 0; uint32_t extents_used = 0; @@ -39,7 +39,7 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv) struct lv_segment *seg; uint32_t seg_extents; uint32_t sz, str; - struct segment_type *segtype; + struct segment_type *segtype = NULL; enum { LV_ANY = 0, @@ -63,8 +63,9 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv) sign = arg_sign_value(cmd, extents_ARG, SIGN_NONE); } + /* Size returned in kilobyte units; held in sectors */ if (arg_count(cmd, size_ARG)) { - size = arg_uint_value(cmd, size_ARG, 0); + size = arg_uint64_value(cmd, size_ARG, UINT64_C(0)) * 2; sign = arg_sign_value(cmd, size_ARG, SIGN_NONE); } @@ -150,22 +151,19 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv) } if (size) { - /* No of 512-byte sectors */ - extents = size * 2; - - if (extents % vg->extent_size) { + if (size % vg->extent_size) { if (sign == SIGN_MINUS) - extents -= extents % vg->extent_size; + size -= size % vg->extent_size; else - extents += vg->extent_size - - (extents % vg->extent_size); + size += vg->extent_size - + (size % vg->extent_size); log_print("Rounding up size to full physical extent %s", - display_size(cmd, (uint64_t) extents / 2, + display_size(cmd, (uint64_t) size / 2, SIZE_SHORT)); } - extents /= vg->extent_size; + extents = size / vg->extent_size; } if (sign == SIGN_PLUS) @@ -194,11 +192,23 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv) seg_size = extents - lv->le_count; + /* Use segment type of last segment */ + list_iterate_items(seg, &lv->segments) { + segtype = seg->segtype; + } + + /* FIXME Support LVs with mixed segment types */ + if (segtype != (struct segment_type *) arg_ptr_value(cmd, type_ARG, + segtype)) { + log_error("VolumeType does not match (%s)", segtype->name); + goto error_cmdline; + } + /* If extending, find stripes, stripesize & size of last segment */ if (extents > lv->le_count && !(stripes == 1 || (stripes > 1 && ssize))) { list_iterate_items(seg, &lv->segments) { - if (strcmp(seg->segtype->ops->name(seg), "striped")) - continue; /* Not striped */ + if (!(seg->segtype->flags & SEG_AREAS_STRIPED)) + continue; sz = seg->stripe_size; str = seg->area_count; @@ -355,11 +365,6 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv) display_size(cmd, (uint64_t) extents * (vg->extent_size / 2), SIZE_SHORT)); - if (!(segtype = get_segtype_from_string(lv->vg->cmd, - "striped"))) { - stack; - return 0; - } if (!lv_extend(vg->fid, lv, segtype, stripes, ssize, 0u, extents - lv->le_count, NULL, 0u, 0u, pvh, diff --git a/tools/tools.h b/tools/tools.h index 9e447e90f..0cd9b244d 100644 --- a/tools/tools.h +++ b/tools/tools.h @@ -120,6 +120,7 @@ int tag_arg(struct cmd_context *cmd, struct arg *a); int permission_arg(struct cmd_context *cmd, struct arg *a); int metadatatype_arg(struct cmd_context *cmd, struct arg *a); int units_arg(struct cmd_context *cmd, struct arg *a); +int segtype_arg(struct cmd_context *cmd, struct arg *a); char yes_no_prompt(const char *prompt, ...);