1
0
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:
Alasdair Kergon 2004-05-11 16:01:58 +00:00
parent 1d2ebf6281
commit 1832f310ac
19 changed files with 336 additions and 72 deletions

View File

@ -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.

View File

@ -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 +=\

View File

@ -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
View 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;
}

View File

@ -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;
}

View File

@ -53,6 +53,7 @@ static struct flag _lv_flags[] = {
{PVMOVE, "PVMOVE"},
{LOCKED, "LOCKED"},
{MIRRORED, NULL},
{VIRTUAL, NULL},
{0, NULL}
};

View File

@ -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;
}

View File

@ -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;

View File

@ -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 */

View File

@ -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);

View File

@ -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))

View File

@ -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
View 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;
}

View File

@ -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)

View File

@ -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",

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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, ...);