mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +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 -
|
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.
|
Push lv_create & alloc policy up to tool level.
|
||||||
Fix pvdisplay return code.
|
Fix pvdisplay return code.
|
||||||
Detect invalid LV names in arg lists.
|
Detect invalid LV names in arg lists.
|
||||||
|
@ -41,6 +41,7 @@ SOURCES =\
|
|||||||
device/dev-io.c \
|
device/dev-io.c \
|
||||||
device/device.c \
|
device/device.c \
|
||||||
display/display.c \
|
display/display.c \
|
||||||
|
error/errseg.c \
|
||||||
filters/filter-composite.c \
|
filters/filter-composite.c \
|
||||||
filters/filter-persistent.c \
|
filters/filter-persistent.c \
|
||||||
filters/filter-regex.c \
|
filters/filter-regex.c \
|
||||||
@ -77,7 +78,8 @@ SOURCES =\
|
|||||||
regex/ttree.c \
|
regex/ttree.c \
|
||||||
report/report.c \
|
report/report.c \
|
||||||
striped/striped.c \
|
striped/striped.c \
|
||||||
uuid/uuid.c
|
uuid/uuid.c \
|
||||||
|
zero/zero.c
|
||||||
|
|
||||||
ifeq ("@LVM1@", "internal")
|
ifeq ("@LVM1@", "internal")
|
||||||
SOURCES +=\
|
SOURCES +=\
|
||||||
|
@ -677,6 +677,16 @@ static int _init_segtypes(struct cmd_context *cmd)
|
|||||||
segtype->library = NULL;
|
segtype->library = NULL;
|
||||||
list_add(&cmd->segtypes, &segtype->list);
|
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
|
#ifdef SNAPSHOT_INTERNAL
|
||||||
if (!(segtype = init_snapshot_segtype(cmd)))
|
if (!(segtype = init_snapshot_segtype(cmd)))
|
||||||
return 0;
|
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);
|
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;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,7 @@ static struct flag _lv_flags[] = {
|
|||||||
{PVMOVE, "PVMOVE"},
|
{PVMOVE, "PVMOVE"},
|
||||||
{LOCKED, "LOCKED"},
|
{LOCKED, "LOCKED"},
|
||||||
{MIRRORED, NULL},
|
{MIRRORED, NULL},
|
||||||
|
{VIRTUAL, NULL},
|
||||||
{0, 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)
|
if (seg->segtype->flags & SEG_AREAS_MIRRORED)
|
||||||
lv->status |= MIRRORED;
|
lv->status |= MIRRORED;
|
||||||
|
|
||||||
|
if (seg->segtype->flags & SEG_VIRTUAL)
|
||||||
|
lv->status |= VIRTUAL;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,7 +238,6 @@ static int _alloc_linear_area(struct logical_volume *lv, uint32_t *ix,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
seg->le = *ix;
|
seg->le = *ix;
|
||||||
seg->le = *ix;
|
|
||||||
seg->len = count;
|
seg->len = count;
|
||||||
seg->area_len = count;
|
seg->area_len = count;
|
||||||
seg->stripe_size = 0;
|
seg->stripe_size = 0;
|
||||||
@ -277,7 +276,6 @@ static int _alloc_mirrored_area(struct logical_volume *lv, uint32_t *ix,
|
|||||||
seg->segtype = segtype;
|
seg->segtype = segtype;
|
||||||
seg->le = *ix;
|
seg->le = *ix;
|
||||||
seg->status = 0u;
|
seg->status = 0u;
|
||||||
seg->le = *ix;
|
|
||||||
seg->len = count;
|
seg->len = count;
|
||||||
seg->area_len = count;
|
seg->area_len = count;
|
||||||
seg->stripe_size = 0;
|
seg->stripe_size = 0;
|
||||||
@ -420,6 +418,31 @@ static int _alloc_next_free(struct logical_volume *lv,
|
|||||||
return 1;
|
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.
|
* 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 list *pvms, *old_tail = lv->segments.p, *segh;
|
||||||
struct lv_segment *seg;
|
struct lv_segment *seg;
|
||||||
|
|
||||||
|
if (segtype->flags & SEG_VIRTUAL)
|
||||||
|
return _alloc_virtual(lv, allocated, segtype);
|
||||||
|
|
||||||
if (!(scratch = pool_create(1024))) {
|
if (!(scratch = pool_create(1024))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
#define PVMOVE 0x00002000 /* VG LV SEG */
|
#define PVMOVE 0x00002000 /* VG LV SEG */
|
||||||
#define LOCKED 0x00004000 /* LV */
|
#define LOCKED 0x00004000 /* LV */
|
||||||
#define MIRRORED 0x00008000 /* LV - internal use only */
|
#define MIRRORED 0x00008000 /* LV - internal use only */
|
||||||
|
#define VIRTUAL 0x00010000 /* LV - internal use only */
|
||||||
|
|
||||||
#define LVM_READ 0x00000100 /* LV VG */
|
#define LVM_READ 0x00000100 /* LV VG */
|
||||||
#define LVM_WRITE 0x00000200 /* LV VG */
|
#define LVM_WRITE 0x00000200 /* LV VG */
|
||||||
|
@ -29,7 +29,9 @@ struct dev_manager;
|
|||||||
#define SEG_CAN_SPLIT 0x00000001
|
#define SEG_CAN_SPLIT 0x00000001
|
||||||
#define SEG_AREAS_STRIPED 0x00000002
|
#define SEG_AREAS_STRIPED 0x00000002
|
||||||
#define SEG_AREAS_MIRRORED 0x00000004
|
#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 segment_type {
|
||||||
struct list list;
|
struct list list;
|
||||||
@ -72,6 +74,8 @@ struct segment_type *get_segtype_from_string(struct cmd_context *cmd,
|
|||||||
const char *str);
|
const char *str);
|
||||||
|
|
||||||
struct segment_type *init_striped_segtype(struct cmd_context *cmd);
|
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
|
#ifdef SNAPSHOT_INTERNAL
|
||||||
struct segment_type *init_snapshot_segtype(struct cmd_context *cmd);
|
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';
|
repstr[0] = 'p';
|
||||||
else if (lv->status & MIRRORED)
|
else if (lv->status & MIRRORED)
|
||||||
repstr[0] = 'm';
|
repstr[0] = 'm';
|
||||||
|
else if (lv->status & VIRTUAL)
|
||||||
|
repstr[0] = 'v';
|
||||||
else if (lv_is_origin(lv))
|
else if (lv_is_origin(lv))
|
||||||
repstr[0] = 'o';
|
repstr[0] = 'o';
|
||||||
else if (find_cow(lv))
|
else if (find_cow(lv))
|
||||||
|
@ -159,7 +159,7 @@ struct segment_type *init_segtype(struct cmd_context *cmd)
|
|||||||
segtype->ops = &_snapshot_ops;
|
segtype->ops = &_snapshot_ops;
|
||||||
segtype->name = "snapshot";
|
segtype->name = "snapshot";
|
||||||
segtype->private = NULL;
|
segtype->private = NULL;
|
||||||
segtype->flags = 0u;
|
segtype->flags = SEG_SNAPSHOT;
|
||||||
|
|
||||||
return segtype;
|
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(refresh_ARG, '\0', "refresh", NULL)
|
||||||
arg(mknodes_ARG, '\0', "mknodes", NULL)
|
arg(mknodes_ARG, '\0', "mknodes", NULL)
|
||||||
arg(minor_ARG, '\0', "minor", minor_arg)
|
arg(minor_ARG, '\0', "minor", minor_arg)
|
||||||
|
arg(type_ARG, '\0', "type", segtype_arg)
|
||||||
|
|
||||||
/* Allow some variations */
|
/* Allow some variations */
|
||||||
arg(resizable_ARG, '\0', "resizable", yes_no_arg)
|
arg(resizable_ARG, '\0', "resizable", yes_no_arg)
|
||||||
|
@ -89,6 +89,7 @@ xx(lvcreate,
|
|||||||
"\t[-p|--permission {r|rw}]\n"
|
"\t[-p|--permission {r|rw}]\n"
|
||||||
"\t[-r|--readahead ReadAheadSectors]\n"
|
"\t[-r|--readahead ReadAheadSectors]\n"
|
||||||
"\t[-t|--test]\n"
|
"\t[-t|--test]\n"
|
||||||
|
"\t[--type VolumeType]\n"
|
||||||
"\t[-v|--verbose]\n"
|
"\t[-v|--verbose]\n"
|
||||||
"\t[-Z|--zero {y|n}]\n"
|
"\t[-Z|--zero {y|n}]\n"
|
||||||
"\t[--version]\n"
|
"\t[--version]\n"
|
||||||
@ -115,7 +116,7 @@ xx(lvcreate,
|
|||||||
|
|
||||||
autobackup_ARG, chunksize_ARG, contiguous_ARG, extents_ARG, major_ARG,
|
autobackup_ARG, chunksize_ARG, contiguous_ARG, extents_ARG, major_ARG,
|
||||||
minor_ARG, name_ARG, permission_ARG, persistent_ARG, readahead_ARG, size_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)
|
zero_ARG)
|
||||||
|
|
||||||
xx(lvdisplay,
|
xx(lvdisplay,
|
||||||
@ -165,12 +166,13 @@ xx(lvextend,
|
|||||||
"\t{-l|--extents [+]LogicalExtentsNumber |\n"
|
"\t{-l|--extents [+]LogicalExtentsNumber |\n"
|
||||||
"\t -L|--size [+]LogicalVolumeSize[kKmMgGtT]}\n"
|
"\t -L|--size [+]LogicalVolumeSize[kKmMgGtT]}\n"
|
||||||
"\t[-t|--test]\n"
|
"\t[-t|--test]\n"
|
||||||
|
"\t[--type VolumeType]\n"
|
||||||
"\t[-v|--verbose]\n"
|
"\t[-v|--verbose]\n"
|
||||||
"\t[--version]" "\n"
|
"\t[--version]" "\n"
|
||||||
"\tLogicalVolume[Path] [ PhysicalVolumePath... ]\n",
|
"\tLogicalVolume[Path] [ PhysicalVolumePath... ]\n",
|
||||||
|
|
||||||
autobackup_ARG, extents_ARG, size_ARG, stripes_ARG,
|
autobackup_ARG, extents_ARG, size_ARG, stripes_ARG,
|
||||||
stripesize_ARG, test_ARG)
|
stripesize_ARG, test_ARG, type_ARG)
|
||||||
|
|
||||||
xx(lvmchange,
|
xx(lvmchange,
|
||||||
"With the device mapper, this is obsolete and does nothing.",
|
"With the device mapper, this is obsolete and does nothing.",
|
||||||
@ -270,12 +272,13 @@ xx(lvresize,
|
|||||||
"\t{-l|--extents [+|-]LogicalExtentsNumber |\n"
|
"\t{-l|--extents [+|-]LogicalExtentsNumber |\n"
|
||||||
"\t -L|--size [+|-]LogicalVolumeSize[kKmMgGtT]}\n"
|
"\t -L|--size [+|-]LogicalVolumeSize[kKmMgGtT]}\n"
|
||||||
"\t[-t|--test]\n"
|
"\t[-t|--test]\n"
|
||||||
|
"\t[--type VolumeType]\n"
|
||||||
"\t[-v|--verbose]\n"
|
"\t[-v|--verbose]\n"
|
||||||
"\t[--version]" "\n"
|
"\t[--version]" "\n"
|
||||||
"\tLogicalVolume[Path] [ PhysicalVolumePath... ]\n",
|
"\tLogicalVolume[Path] [ PhysicalVolumePath... ]\n",
|
||||||
|
|
||||||
autobackup_ARG, extents_ARG, size_ARG, stripes_ARG, stripesize_ARG,
|
autobackup_ARG, extents_ARG, size_ARG, stripes_ARG, stripesize_ARG,
|
||||||
test_ARG)
|
test_ARG, type_ARG)
|
||||||
|
|
||||||
xx(lvs,
|
xx(lvs,
|
||||||
"Display information about logical volumes",
|
"Display information about logical volumes",
|
||||||
|
@ -57,9 +57,7 @@ static int _read_name_params(struct lvcreate_params *lp,
|
|||||||
if (arg_count(cmd, name_ARG))
|
if (arg_count(cmd, name_ARG))
|
||||||
lp->lv_name = arg_value(cmd, name_ARG);
|
lp->lv_name = arg_value(cmd, name_ARG);
|
||||||
|
|
||||||
if (arg_count(cmd, snapshot_ARG)) {
|
if (lp->snapshot) {
|
||||||
lp->snapshot = 1;
|
|
||||||
|
|
||||||
if (!argc) {
|
if (!argc) {
|
||||||
log_err("Please specify a logical volume to act as "
|
log_err("Please specify a logical volume to act as "
|
||||||
"the snapshot origin.");
|
"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,
|
static int _read_size_params(struct lvcreate_params *lp,
|
||||||
struct cmd_context *cmd, int *pargc, char ***pargv)
|
struct cmd_context *cmd, int *pargc, char ***pargv)
|
||||||
{
|
{
|
||||||
/*
|
if (arg_count(cmd, extents_ARG) + arg_count(cmd, size_ARG) != 1) {
|
||||||
* There are two mutually exclusive ways of specifying
|
log_error("Please specify either size or extents (not both)");
|
||||||
* 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");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,20 +172,6 @@ static int _read_stripe_params(struct lvcreate_params *lp,
|
|||||||
{
|
{
|
||||||
int argc = *pargc;
|
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_count(cmd, stripesize_ARG)) {
|
||||||
if (arg_sign_value(cmd, stripesize_ARG, 0) == SIGN_MINUS) {
|
if (arg_sign_value(cmd, stripesize_ARG, 0) == SIGN_MINUS) {
|
||||||
log_error("Negative stripesize is invalid");
|
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));
|
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)) {
|
if (arg_count(cmd, zero_ARG)) {
|
||||||
log_error("-s and -Z are incompatible");
|
log_error("-Z is incompatible with snapshots");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (arg_sign_value(cmd, chunksize_ARG, 0) == SIGN_MINUS) {
|
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);
|
log_verbose("Setting chunksize to %d sectors.", lp->chunk_size);
|
||||||
} else {
|
} else {
|
||||||
if (arg_count(cmd, chunksize_ARG)) {
|
if (arg_count(cmd, chunksize_ARG)) {
|
||||||
log_error("-c is only available with -s");
|
log_error("-c is only available with snapshots");
|
||||||
return 0;
|
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) ||
|
if (!_read_name_params(lp, cmd, &argc, &argv) ||
|
||||||
!_read_size_params(lp, cmd, &argc, &argv) ||
|
!_read_size_params(lp, cmd, &argc, &argv) ||
|
||||||
!_read_stripe_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;
|
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: "
|
log_error("Insufficient free extents (%u) in volume group %s: "
|
||||||
"%u required", vg->free_count, vg->name, lp->extents);
|
"%u required", vg->free_count, vg->name, lp->extents);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -287,6 +287,14 @@ int permission_arg(struct cmd_context *cmd, struct arg *a)
|
|||||||
return 1;
|
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, ...)
|
char yes_no_prompt(const char *prompt, ...)
|
||||||
{
|
{
|
||||||
int c = 0;
|
int c = 0;
|
||||||
|
@ -22,7 +22,7 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
|
|||||||
struct snapshot *snap;
|
struct snapshot *snap;
|
||||||
struct lvinfo info;
|
struct lvinfo info;
|
||||||
uint32_t extents = 0;
|
uint32_t extents = 0;
|
||||||
uint32_t size = 0;
|
uint64_t size = 0;
|
||||||
uint32_t stripes = 0, ssize = 0, stripesize_extents = 0;
|
uint32_t stripes = 0, ssize = 0, stripesize_extents = 0;
|
||||||
uint32_t seg_stripes = 0, seg_stripesize = 0, seg_size = 0;
|
uint32_t seg_stripes = 0, seg_stripesize = 0, seg_size = 0;
|
||||||
uint32_t extents_used = 0;
|
uint32_t extents_used = 0;
|
||||||
@ -39,7 +39,7 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
|
|||||||
struct lv_segment *seg;
|
struct lv_segment *seg;
|
||||||
uint32_t seg_extents;
|
uint32_t seg_extents;
|
||||||
uint32_t sz, str;
|
uint32_t sz, str;
|
||||||
struct segment_type *segtype;
|
struct segment_type *segtype = NULL;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
LV_ANY = 0,
|
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);
|
sign = arg_sign_value(cmd, extents_ARG, SIGN_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Size returned in kilobyte units; held in sectors */
|
||||||
if (arg_count(cmd, size_ARG)) {
|
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);
|
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) {
|
if (size) {
|
||||||
/* No of 512-byte sectors */
|
if (size % vg->extent_size) {
|
||||||
extents = size * 2;
|
|
||||||
|
|
||||||
if (extents % vg->extent_size) {
|
|
||||||
if (sign == SIGN_MINUS)
|
if (sign == SIGN_MINUS)
|
||||||
extents -= extents % vg->extent_size;
|
size -= size % vg->extent_size;
|
||||||
else
|
else
|
||||||
extents += vg->extent_size -
|
size += vg->extent_size -
|
||||||
(extents % vg->extent_size);
|
(size % vg->extent_size);
|
||||||
|
|
||||||
log_print("Rounding up size to full physical extent %s",
|
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));
|
SIZE_SHORT));
|
||||||
}
|
}
|
||||||
|
|
||||||
extents /= vg->extent_size;
|
extents = size / vg->extent_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sign == SIGN_PLUS)
|
if (sign == SIGN_PLUS)
|
||||||
@ -194,11 +192,23 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
|
|||||||
|
|
||||||
seg_size = extents - lv->le_count;
|
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 extending, find stripes, stripesize & size of last segment */
|
||||||
if (extents > lv->le_count && !(stripes == 1 || (stripes > 1 && ssize))) {
|
if (extents > lv->le_count && !(stripes == 1 || (stripes > 1 && ssize))) {
|
||||||
list_iterate_items(seg, &lv->segments) {
|
list_iterate_items(seg, &lv->segments) {
|
||||||
if (strcmp(seg->segtype->ops->name(seg), "striped"))
|
if (!(seg->segtype->flags & SEG_AREAS_STRIPED))
|
||||||
continue; /* Not striped */
|
continue;
|
||||||
|
|
||||||
sz = seg->stripe_size;
|
sz = seg->stripe_size;
|
||||||
str = seg->area_count;
|
str = seg->area_count;
|
||||||
@ -355,11 +365,6 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
|
|||||||
display_size(cmd, (uint64_t)
|
display_size(cmd, (uint64_t)
|
||||||
extents * (vg->extent_size / 2),
|
extents * (vg->extent_size / 2),
|
||||||
SIZE_SHORT));
|
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,
|
if (!lv_extend(vg->fid, lv, segtype, stripes, ssize, 0u,
|
||||||
extents - lv->le_count, NULL, 0u, 0u, pvh,
|
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 permission_arg(struct cmd_context *cmd, struct arg *a);
|
||||||
int metadatatype_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 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, ...);
|
char yes_no_prompt(const char *prompt, ...);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user