mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-30 17:18:21 +03:00
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.
This commit is contained in:
parent
1d2ebf6281
commit
1832f310ac
@ -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.
|
||||
|
@ -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 +=\
|
||||
|
@ -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;
|
||||
|
101
lib/error/errseg.c
Normal file
101
lib/error/errseg.c
Normal file
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ static struct flag _lv_flags[] = {
|
||||
{PVMOVE, "PVMOVE"},
|
||||
{LOCKED, "LOCKED"},
|
||||
{MIRRORED, NULL},
|
||||
{VIRTUAL, NULL},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
}
|
||||
|
101
lib/zero/zero.c
Normal file
101
lib/zero/zero.c
Normal file
@ -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;
|
||||
}
|
@ -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)
|
||||
|
@ -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",
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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, ...);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user