1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-30 17:18:21 +03:00

Begin to separate out segment types.

This commit is contained in:
Alasdair Kergon 2004-05-04 21:25:57 +00:00
parent 6ec6994107
commit 4922197a33
50 changed files with 1663 additions and 783 deletions

View File

@ -26,6 +26,8 @@ SUBDIRS += lib tools
ifeq ($(MAKECMDGOALS),distclean)
SUBDIRS += lib/format1 \
lib/mirror \
lib/snapshot \
po \
test/mm test/device test/format1 test/regex test/filters
endif

View File

@ -1,5 +1,7 @@
Version 2.00.16 -
=============================
Begin separating out segment code. There's a lot of change here.
Compress any (obsolete) long LVM1 pvids encountered.
Support for tagged config files.
Don't abort operations if selinux present but disabled.
Fix typo in configure which left HAVE_LIBDL unset.

62
configure vendored
View File

@ -309,7 +309,7 @@ ac_includes_default="\
#endif"
ac_default_prefix=/usr
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS AWK CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE RANLIB ac_ct_RANLIB CPP EGREP build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os MSGFMT JOBS STATIC_LINK LVM1 OWNER GROUP CLDFLAGS CLDWHOLEARCHIVE CLDNOWHOLEARCHIVE LD_DEPS LD_FLAGS SOFLAG LVM_VERSION LVM1_FALLBACK DEBUG DEVMAPPER HAVE_LIBDL HAVE_SELINUX CMDLIB LOCALEDIR CONFDIR STATICDIR INTL_PACKAGE INTL LIBOBJS LTLIBOBJS'
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS AWK CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE RANLIB ac_ct_RANLIB CPP EGREP build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os MSGFMT JOBS STATIC_LINK LVM1 SNAPSHOTS MIRRORS OWNER GROUP CLDFLAGS CLDWHOLEARCHIVE CLDNOWHOLEARCHIVE LD_DEPS LD_FLAGS SOFLAG LVM_VERSION LVM1_FALLBACK DEBUG DEVMAPPER HAVE_LIBDL HAVE_SELINUX CMDLIB LOCALEDIR CONFDIR STATICDIR INTL_PACKAGE INTL LIBOBJS LTLIBOBJS'
ac_subst_files=''
# Initialize some variables set by options.
@ -864,6 +864,10 @@ Optional Packages:
--with-group=GROUP Set the group owner of installed files
--with-lvm1=TYPE LVM1 metadata support: internal/shared/none
TYPE=internal
--with-snapshots=TYPE Snapshot support: internal/shared/none
TYPE=internal
--with-mirrors=TYPE Mirror support: internal/shared/none
TYPE=internal
--with-localedir=DIR Translation files in DIR PREFIX/share/locale
--with-confdir=DIR Configuration files in DIR /etc
--with-staticdir=DIR Static binary in DIR EXEC_PREFIX/sbin
@ -3974,6 +3978,50 @@ else
JOBS=-j2
fi;
# Check whether --with-snapshots or --without-snapshots was given.
if test "${with_snapshots+set}" = set; then
withval="$with_snapshots"
SNAPSHOTS="$withval"
else
SNAPSHOTS="internal"
fi;
if [ "x$SNAPSHOTS" != xnone -a "x$SNAPSHOTS" != xinternal -a "x$SNAPSHOTS" != xshared ];
then { { echo "$as_me:$LINENO: error: --with-snapshots parameter invalid
" >&5
echo "$as_me: error: --with-snapshots parameter invalid
" >&2;}
{ (exit 1); exit 1; }; }
exit
fi;
if test x$SNAPSHOTS = xinternal; then
CFLAGS="$CFLAGS -DSNAPSHOT_INTERNAL"
fi
# Check whether --with-mirrors or --without-mirrors was given.
if test "${with_mirrors+set}" = set; then
withval="$with_mirrors"
MIRRORS="$withval"
else
MIRRORS="internal"
fi;
if [ "x$MIRRORS" != xnone -a "x$MIRRORS" != xinternal -a "x$MIRRORS" != xshared ];
then { { echo "$as_me:$LINENO: error: --with-mirrors parameter invalid
" >&5
echo "$as_me: error: --with-mirrors parameter invalid
" >&2;}
{ (exit 1); exit 1; }; }
exit
fi;
if test x$MIRRORS = xinternal; then
CFLAGS="$CFLAGS -DMIRRORED_INTERNAL"
fi
# Check whether --enable-static_link or --disable-static_link was given.
if test "${enable_static_link+set}" = set; then
enableval="$enable_static_link"
@ -4614,7 +4662,9 @@ else
HAVE_LIBDL=no
fi
if [ "x$LVM1" = xshared -a "x$STATIC_LINK" = xyes ];
if [ \( "x$LVM1" = xshared -o \
"x$SNAPSHOTS" = xshared -o "x$MIRRORS" = xshared \
\) -a "x$STATIC_LINK" = xyes ];
then { { echo "$as_me:$LINENO: error: Features cannot be 'shared' when building statically
" >&5
echo "$as_me: error: Features cannot be 'shared' when building statically
@ -5117,7 +5167,9 @@ fi
ac_config_files="$ac_config_files Makefile make.tmpl doc/Makefile include/Makefile lib/Makefile lib/format1/Makefile man/Makefile po/Makefile tools/Makefile tools/version.h test/mm/Makefile test/device/Makefile test/format1/Makefile test/regex/Makefile test/filters/Makefile"
ac_config_files="$ac_config_files Makefile make.tmpl doc/Makefile include/Makefile lib/Makefile lib/format1/Makefile lib/mirror/Makefile lib/snapshot/Makefile man/Makefile po/Makefile tools/Makefile tools/version.h test/mm/Makefile test/device/Makefile test/format1/Makefile test/regex/Makefile test/filters/Makefile"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
@ -5674,6 +5726,8 @@ do
"include/Makefile" ) CONFIG_FILES="$CONFIG_FILES include/Makefile" ;;
"lib/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;;
"lib/format1/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/format1/Makefile" ;;
"lib/mirror/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/mirror/Makefile" ;;
"lib/snapshot/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/snapshot/Makefile" ;;
"man/Makefile" ) CONFIG_FILES="$CONFIG_FILES man/Makefile" ;;
"po/Makefile" ) CONFIG_FILES="$CONFIG_FILES po/Makefile" ;;
"tools/Makefile" ) CONFIG_FILES="$CONFIG_FILES tools/Makefile" ;;
@ -5799,6 +5853,8 @@ s,@MSGFMT@,$MSGFMT,;t t
s,@JOBS@,$JOBS,;t t
s,@STATIC_LINK@,$STATIC_LINK,;t t
s,@LVM1@,$LVM1,;t t
s,@SNAPSHOTS@,$SNAPSHOTS,;t t
s,@MIRRORS@,$MIRRORS,;t t
s,@OWNER@,$OWNER,;t t
s,@GROUP@,$GROUP,;t t
s,@CLDFLAGS@,$CLDFLAGS,;t t

View File

@ -123,6 +123,42 @@ fi
AC_ARG_ENABLE(jobs, [ --enable-jobs=NUM Number of jobs to run simultaneously], JOBS=-j$enableval, JOBS=-j2)
dnl -- snapshots inclusion type
AC_ARG_WITH(snapshots,
[ --with-snapshots=TYPE Snapshot support: internal/shared/none
[TYPE=internal] ],
[ SNAPSHOTS="$withval" ],
[ SNAPSHOTS="internal" ])
if [[ "x$SNAPSHOTS" != xnone -a "x$SNAPSHOTS" != xinternal -a "x$SNAPSHOTS" != xshared ]];
then AC_MSG_ERROR(
--with-snapshots parameter invalid
)
exit
fi;
if test x$SNAPSHOTS = xinternal; then
CFLAGS="$CFLAGS -DSNAPSHOT_INTERNAL"
fi
dnl -- mirrors inclusion type
AC_ARG_WITH(mirrors,
[ --with-mirrors=TYPE Mirror support: internal/shared/none
[TYPE=internal] ],
[ MIRRORS="$withval" ],
[ MIRRORS="internal" ])
if [[ "x$MIRRORS" != xnone -a "x$MIRRORS" != xinternal -a "x$MIRRORS" != xshared ]];
then AC_MSG_ERROR(
--with-mirrors parameter invalid
)
exit
fi;
if test x$MIRRORS = xinternal; then
CFLAGS="$CFLAGS -DMIRRORED_INTERNAL"
fi
dnl Enables staticly-linked tools
AC_ARG_ENABLE(static_link, [ --enable-static_link Use this to link the tools to their libraries
statically. Default is dynamic linking], STATIC_LINK=$enableval, STATIC_LINK=no)
@ -210,7 +246,9 @@ else
fi
dnl Check for shared/static conflicts
if [[ "x$LVM1" = xshared -a "x$STATIC_LINK" = xyes ]];
if [[ \( "x$LVM1" = xshared -o \
"x$SNAPSHOTS" = xshared -o "x$MIRRORS" = xshared \
\) -a "x$STATIC_LINK" = xyes ]];
then AC_MSG_ERROR(
Features cannot be 'shared' when building statically
)
@ -287,6 +325,8 @@ fi
AC_SUBST(JOBS)
AC_SUBST(STATIC_LINK)
AC_SUBST(LVM1)
AC_SUBST(SNAPSHOTS)
AC_SUBST(MIRRORS)
AC_SUBST(OWNER)
AC_SUBST(GROUP)
AC_SUBST(CFLAGS)
@ -320,6 +360,8 @@ doc/Makefile \
include/Makefile \
lib/Makefile \
lib/format1/Makefile \
lib/mirror/Makefile \
lib/snapshot/Makefile \
man/Makefile \
po/Makefile \
tools/Makefile \

View File

@ -1,4 +1,5 @@
../lib/activate/activate.h
../lib/activate/targets.h
../lib/cache/lvmcache.h
../lib/commands/errors.h
../lib/commands/toolcontext.h
@ -21,11 +22,14 @@
../lib/filters/filter.h
../lib/format1/format1.h
../lib/format_text/format-text.h
../lib/format_text/text_export.h
../lib/format_text/text_import.h
../lib/label/label.h
../lib/locking/locking.h
../lib/log/log.h
../lib/metadata/lv_alloc.h
../lib/metadata/metadata.h
../lib/metadata/segtypes.h
../lib/mm/dbg_malloc.h
../lib/mm/memlock.h
../lib/mm/pool.h

View File

@ -20,6 +20,14 @@ ifeq ("@LVM1@", "shared")
SUBDIRS = format1
endif
ifeq ("@SNAPSHOTS@", "shared")
SUBDIRS += snapshot
endif
ifeq ("@MIRRORS@", "shared")
SUBDIRS += mirror
endif
SOURCES =\
activate/activate.c \
cache/lvmcache.c \
@ -57,6 +65,7 @@ SOURCES =\
metadata/metadata.c \
metadata/mirror.c \
metadata/pv_map.c \
metadata/segtypes.c \
metadata/snapshot_manip.c \
misc/crc.c \
misc/lvm-file.c \
@ -67,6 +76,7 @@ SOURCES =\
regex/parse_rx.c \
regex/ttree.c \
report/report.c \
striped/striped.c \
uuid/uuid.c
ifeq ("@LVM1@", "internal")
@ -80,6 +90,14 @@ ifeq ("@LVM1@", "internal")
format1/vg_number.c
endif
ifeq ("@SNAPSHOTS@", "internal")
SOURCES += snapshot/snapshot.c
endif
ifeq ("@MIRRORS@", "internal")
SOURCES += mirror/mirrored.c
endif
ifeq ("@DEBUG@", "yes")
SOURCES += mm/dbg_malloc.c
endif

View File

@ -25,6 +25,7 @@
#include "toolcontext.h"
#include "dev_manager.h"
#include "str_list.h"
#include "config.h"
#include <limits.h>
#include <fcntl.h>
@ -341,7 +342,7 @@ static int _lv_info(const struct logical_volume *lv, int mknodes,
if (!activation())
return 0;
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cft))) {
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
stack;
return 0;
}
@ -387,7 +388,7 @@ int lv_snapshot_percent(struct logical_volume *lv, float *percent)
if (!activation())
return 0;
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cft))) {
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
stack;
return 0;
}
@ -419,7 +420,7 @@ int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
if (!info.exists)
return 0;
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cft))) {
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
stack;
return 0;
}
@ -462,7 +463,7 @@ static int _lv_activate_lv(struct logical_volume *lv)
int r;
struct dev_manager *dm;
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cft))) {
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
stack;
return 0;
}
@ -479,7 +480,7 @@ static int _lv_deactivate(struct logical_volume *lv)
int r;
struct dev_manager *dm;
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cft))) {
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
stack;
return 0;
}
@ -496,7 +497,7 @@ static int _lv_suspend_lv(struct logical_volume *lv)
int r;
struct dev_manager *dm;
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cft))) {
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
stack;
return 0;
}

View File

@ -21,7 +21,11 @@
#include "lvm-string.h"
#include "fs.h"
#include "defaults.h"
#include "segtypes.h"
#include "display.h"
#include "toolcontext.h"
#include "targets.h"
#include "config.h"
#include <libdevmapper.h>
#include <limits.h>
@ -65,12 +69,6 @@ enum {
REMOVE = 7
};
enum {
MIRR_DISABLED,
MIRR_RUNNING,
MIRR_COMPLETED
};
typedef enum {
ACTIVATE,
DEACTIVATE,
@ -112,14 +110,14 @@ struct dl_list {
};
static const char *stripe_filler = NULL;
static uint32_t mirror_region_size = 0;
struct dev_manager {
struct pool *mem;
struct config_tree *cft;
struct cmd_context *cmd;
const char *stripe_filler;
uint32_t mirror_region_size;
void *target_state;
uint32_t pvmove_mirror_count;
char *vg_name;
@ -336,7 +334,7 @@ static int _info_run(const char *name, const char *uuid, struct dm_info *info,
static int _info(const char *name, const char *uuid, int mknodes,
struct dm_info *info, struct pool *mem, char **uuid_out)
{
if (!mknodes && uuid && *uuid &&
if (!mknodes && uuid && *uuid &&
_info_run(NULL, uuid, info, 0, mem, uuid_out) && info->exists)
return 1;
@ -427,18 +425,16 @@ static int _percent_run(struct dev_manager *dm, const char *name,
uint64_t start, length;
char *type = NULL;
char *params = NULL;
float percent2;
struct list *segh = &lv->segments;
struct lv_segment *seg = NULL;
struct segment_type *segtype;
uint64_t numerator, denominator;
uint64_t total_numerator = 0, total_denominator = 0;
*percent = -1;
if (!(dmt = _setup_task(name, uuid, event_nr,
wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS)))
{
wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS))) {
stack;
return 0;
}
@ -471,40 +467,19 @@ static int _percent_run(struct dev_manager *dm, const char *name,
if (!type || !params || strcmp(type, target_type))
continue;
/* Mirror? */
if (!strcmp(type, "mirror")) {
log_debug("Mirror status: %s", params);
if (sscanf(params, "%*d %*x:%*x %*x:%*x %" PRIu64
"/%" PRIu64, &numerator,
&denominator) != 2) {
log_error("Failure parsing mirror status: %s",
params);
goto out;
}
total_numerator += numerator;
total_denominator += denominator;
if (seg && (seg->status & PVMOVE))
seg->extents_moved = dm->mirror_region_size *
numerator / lv->vg->extent_size;
if (!(segtype = get_segtype_from_string(dm->cmd, type)))
continue;
if (segtype->ops->target_percent &&
!segtype->ops->target_percent(&dm->target_state, dm->mem,
dm->cmd->cft, seg, params,
&total_numerator,
&total_denominator,
percent)) {
stack;
goto out;
}
if (strcmp(type, "snapshot"))
continue;
/* Snapshot */
if (index(params, '/')) {
if (sscanf(params, "%" PRIu64 "/%" PRIu64,
&numerator, &denominator) == 2) {
total_numerator += numerator;
total_denominator += denominator;
}
continue;
} else if (sscanf(params, "%f", &percent2) == 1) {
*percent += percent2;
*percent /= 2;
}
} while (next);
if (lv && (segh = list_next(&lv->segments, segh))) {
@ -515,7 +490,7 @@ static int _percent_run(struct dev_manager *dm, const char *name,
if (total_denominator)
*percent = (float) total_numerator *100 / total_denominator;
else
else if (*percent < 0)
*percent = 100;
log_debug("LV percent: %f", *percent);
@ -633,9 +608,9 @@ static int _load(struct dev_manager *dm, struct dev_layer *dl, int task)
log_error("Couldn't load device '%s'.", dl->name);
if ((dl->lv->minor >= 0 || dl->lv->major >= 0) &&
_get_flag(dl, VISIBLE))
log_error("Perhaps the persistent device number "
"%d:%d is already in use?",
dl->lv->major, dl->lv->minor);
log_error("Perhaps the persistent device number "
"%d:%d is already in use?",
dl->lv->major, dl->lv->minor);
}
if (!dm_task_get_info(dmt, &dl->info)) {
@ -759,98 +734,26 @@ static int _emit_target_line(struct dev_manager *dm, struct dm_task *dmt,
size_t paramsize)
{
uint64_t esize = seg->lv->vg->extent_size;
uint32_t s, start_area = 0u, areas = seg->area_count;
int w = 0, tw = 0;
int w = 0;
const char *target = NULL;
const char *trailing_space;
int mirror_status;
struct dev_layer *dl;
char devbuf[10];
int r;
switch (seg->type) {
case SEG_SNAPSHOT:
if (!seg->segtype->ops->compose_target_line) {
log_error("_emit_target: Internal error: Can't handle "
"SEG_SNAPSHOT");
"segment type %s", seg->segtype->name);
return 0;
/* Target formats:
* linear [device offset]+
* striped #stripes stripe_size [device offset]+
* mirror log_type #log_params [log_params]*
* #mirrors [device offset]+
*/
case SEG_STRIPED:
if (areas == 1)
target = "linear";
else if (areas > 1) {
target = "striped";
if ((tw = lvm_snprintf(params, paramsize, "%u %u ",
areas, seg->stripe_size)) < 0)
goto error;
w = tw;
} else {
log_error("_emit_target: Internal error: SEG_STRIPED "
"with no stripes");
return 0;
}
break;
case SEG_MIRRORED:
mirror_status = MIRR_RUNNING;
if (seg->status & PVMOVE) {
if (seg->extents_moved == seg->area_len) {
mirror_status = MIRR_COMPLETED;
start_area = 1;
} else if (dm->pvmove_mirror_count++) {
mirror_status = MIRR_DISABLED;
areas = 1;
}
}
if (mirror_status != MIRR_RUNNING) {
target = "linear";
break;
}
target = "mirror";
if ((tw = lvm_snprintf(params, paramsize, "core 1 %u %u ",
dm->mirror_region_size, areas)) < 0)
goto error;
w = tw;
break;
}
for (s = start_area; s < areas; s++, w += tw) {
trailing_space = (areas - s - 1) ? " " : "";
if ((seg->area[s].type == AREA_PV &&
(!seg->area[s].u.pv.pv || !seg->area[s].u.pv.pv->dev)) ||
(seg->area[s].type == AREA_LV && !seg->area[s].u.lv.lv))
tw = lvm_snprintf(params + w, paramsize - w,
"%s 0%s", dm->stripe_filler,
trailing_space);
else if (seg->area[s].type == AREA_PV)
tw = lvm_snprintf(params + w, paramsize - w,
"%s %" PRIu64 "%s",
dev_name(seg->area[s].u.pv.pv->dev),
(seg->area[s].u.pv.pv->pe_start +
(esize * seg->area[s].u.pv.pe)),
trailing_space);
else {
if (!(dl = hash_lookup(dm->layers,
seg->area[s].u.lv.lv->lvid.s))) {
log_error("device layer %s missing from hash",
seg->area[s].u.lv.lv->lvid.s);
return 0;
}
if (!dm_format_dev(devbuf, sizeof(devbuf), dl->info.major, dl->info.minor)) {
log_error("Failed to format device number as dm target (%u,%u)",
dl->info.major, dl->info.minor);
return 0;
}
tw = lvm_snprintf(params + w, paramsize - w,
"%s %" PRIu64 "%s", devbuf,
esize * seg->area[s].u.lv.le,
trailing_space);
}
if (tw < 0)
goto error;
if ((r = seg->segtype->ops->compose_target_line(dm, dm->mem,
dm->cmd->cft,
&dm->target_state, seg,
params, paramsize,
&target, &w,
&dm->
pvmove_mirror_count)) <=
0) {
stack;
return r;
}
log_debug("Adding target: %" PRIu64 " %" PRIu64 " %s %s",
@ -863,11 +766,62 @@ static int _emit_target_line(struct dev_manager *dm, struct dm_task *dmt,
}
return 1;
}
error:
log_debug("Insufficient space in params[%" PRIsize_t "] for target "
"parameters.", paramsize);
return -1;
int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
char *params, size_t paramsize, int *pos, int start_area,
int areas)
{
uint32_t s;
int tw = 0;
const char *trailing_space;
uint64_t esize = seg->lv->vg->extent_size;
struct dev_layer *dl;
char devbuf[10];
for (s = start_area; s < areas; s++, *pos += tw) {
trailing_space = (areas - s - 1) ? " " : "";
if ((seg->area[s].type == AREA_PV &&
(!seg->area[s].u.pv.pv || !seg->area[s].u.pv.pv->dev)) ||
(seg->area[s].type == AREA_LV && !seg->area[s].u.lv.lv))
tw = lvm_snprintf(params + *pos, paramsize - *pos,
"%s 0%s", dm->stripe_filler,
trailing_space);
else if (seg->area[s].type == AREA_PV)
tw = lvm_snprintf(params + *pos, paramsize - *pos,
"%s %" PRIu64 "%s",
dev_name(seg->area[s].u.pv.pv->dev),
(seg->area[s].u.pv.pv->pe_start +
(esize * seg->area[s].u.pv.pe)),
trailing_space);
else {
if (!(dl = hash_lookup(dm->layers,
seg->area[s].u.lv.lv->lvid.s))) {
log_error("device layer %s missing from hash",
seg->area[s].u.lv.lv->lvid.s);
return 0;
}
if (!dm_format_dev
(devbuf, sizeof(devbuf), dl->info.major,
dl->info.minor)) {
log_error
("Failed to format device number as dm target (%u,%u)",
dl->info.major, dl->info.minor);
return 0;
}
tw = lvm_snprintf(params + *pos, paramsize - *pos,
"%s %" PRIu64 "%s", devbuf,
esize * seg->area[s].u.lv.le,
trailing_space);
}
if (tw < 0) {
stack;
return -1;
}
}
return 1;
}
static int _emit_target(struct dev_manager *dm, struct dm_task *dmt,
@ -892,6 +846,9 @@ static int _emit_target(struct dev_manager *dm, struct dm_task *dmt,
if (ret >= 0)
return ret;
log_debug("Insufficient space in params[%" PRIsize_t
"] for target parameters.", paramsize);
paramsize *= 2;
} while (paramsize < MAX_TARGET_PARAMSIZE);
@ -1023,8 +980,8 @@ static int _populate_snapshot(struct dev_manager *dm,
/*
* dev_manager implementation.
*/
struct dev_manager *dev_manager_create(const char *vg_name,
struct config_tree *cft)
struct dev_manager *dev_manager_create(struct cmd_context *cmd,
const char *vg_name)
{
struct pool *mem;
struct dev_manager *dm;
@ -1039,22 +996,16 @@ struct dev_manager *dev_manager_create(const char *vg_name,
goto bad;
}
dm->cmd = cmd;
dm->mem = mem;
dm->cft = cft;
if (!stripe_filler) {
stripe_filler = find_config_str(cft->root,
stripe_filler = find_config_str(cmd->cft->root,
"activation/missing_stripe_filler",
DEFAULT_STRIPE_FILLER);
}
dm->stripe_filler = stripe_filler;
if (!mirror_region_size) {
mirror_region_size = 2 * find_config_int(cft->root,
"activation/mirror_region_size",
DEFAULT_MIRROR_REGION_SIZE);
}
dm->mirror_region_size = mirror_region_size;
if (!(dm->vg_name = pool_strdup(dm->mem, vg_name))) {
stack;
goto bad;
@ -1070,6 +1021,8 @@ struct dev_manager *dev_manager_create(const char *vg_name,
list_init(&dm->remove_list);
list_init(&dm->suspend_list);
dm->target_state = NULL;
return dm;
bad:
@ -1282,15 +1235,13 @@ static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv,
/* Add dependencies for any LVs that segments refer to */
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
if (seg->type != SEG_STRIPED && seg->type != SEG_MIRRORED)
continue;
for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_LV)
continue;
if (!str_list_add(dm->mem, &dl->pre_create,
_build_dlid(dm->mem,
seg->area[s].u.lv.
lv->lvid.s, NULL))) {
seg->area[s].u.lv.lv->
lvid.s, NULL))) {
stack;
return 0;
}
@ -1311,7 +1262,7 @@ static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv,
_clear_flag(dlr, VISIBLE);
_clear_flag(dlr, TOPLEVEL);
_set_flag(dlr, REMOVE);
/* add the dependency on the real device */
if (!str_list_add(dm->mem, &dl->pre_create,
pool_strdup(dm->mem, dlr->dlid))) {
@ -1688,7 +1639,6 @@ static int _create_rec(struct dev_manager *dm, struct dev_layer *dl)
return 1;
}
static int _build_all_layers(struct dev_manager *dm, struct volume_group *vg)
{
struct list *lvh;
@ -1756,8 +1706,7 @@ static int _populate_pre_suspend_lists(struct dev_manager *dm)
continue;
}
if (!str_list_add(dm->mem, &dep->pre_create,
dl->dlid)) {
if (!str_list_add(dm->mem, &dep->pre_create, dl->dlid)) {
stack;
return 0;
}
@ -1773,8 +1722,7 @@ static int _populate_pre_suspend_lists(struct dev_manager *dm)
continue;
}
if (!str_list_add(dm->mem, &dep->pre_suspend,
dl->dlid)) {
if (!str_list_add(dm->mem, &dep->pre_suspend, dl->dlid)) {
stack;
return 0;
}

View File

@ -16,17 +16,16 @@
#ifndef _LVM_DEV_MANAGER_H
#define _LVM_DEV_MANAGER_H
#include "metadata.h"
#include "config.h"
struct logical_volume;
struct cmd_context;
struct dev_manager;
struct dm_info;
/*
* Constructor and destructor.
*/
struct dev_manager *dev_manager_create(const char *vg_name,
struct config_tree *cf);
struct dev_manager *dev_manager_create(struct cmd_context *cmd,
const char *vg_name);
void dev_manager_destroy(struct dev_manager *dm);
void dev_manager_exit(void);

25
lib/activate/targets.h Normal file
View File

@ -0,0 +1,25 @@
/*
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
* 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
*/
#ifndef _LVM_TARGETS_H
#define _LVM_TARGETS_H
struct dev_manager;
struct lv_segment;
int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg, char *params, size_t paramsize, int *pos,
int start_area, int areas);
#endif

View File

@ -20,7 +20,6 @@
#include "dev-cache.h"
#include "uuid.h"
#include "label.h"
#include "metadata.h"
#define ORPHAN ""
@ -30,6 +29,10 @@
/* LVM specific per-volume info */
/* Eventual replacement for struct physical_volume perhaps? */
struct cmd_context;
struct format_type;
struct volume_group;
struct lvmcache_vginfo {
struct list list; /* Join these vginfos together */
struct list infos; /* List head for lvmcache_infos */

View File

@ -33,6 +33,8 @@
#include "display.h"
#include "memlock.h"
#include "str_list.h"
#include "segtypes.h"
#include "lvmcache.h"
#ifdef HAVE_LIBDL
#include "sharedlib.h"
@ -662,6 +664,87 @@ static int _init_formats(struct cmd_context *cmd)
return 0;
}
static int _init_segtypes(struct cmd_context *cmd)
{
struct segment_type *segtype;
#ifdef HAVE_LIBDL
const struct config_node *cn;
#endif
if (!(segtype = init_striped_segtype(cmd)))
return 0;
segtype->library = NULL;
list_add(&cmd->segtypes, &segtype->list);
#ifdef SNAPSHOT_INTERNAL
if (!(segtype = init_snapshot_segtype(cmd)))
return 0;
segtype->library = NULL;
list_add(&cmd->segtypes, &segtype->list);
#endif
#ifdef MIRRORED_INTERNAL
if (!(segtype = init_mirrored_segtype(cmd)))
return 0;
segtype->library = NULL;
list_add(&cmd->segtypes, &segtype->list);
#endif
#ifdef HAVE_LIBDL
/* Load any formats in shared libs */
if ((cn = find_config_node(cmd->cft->root, "global/segment_libraries"))) {
struct config_value *cv;
struct segment_type *(*init_segtype_fn) (struct cmd_context *);
void *lib;
struct list *sgtl, *tmp;
struct segment_type *segtype2;
for (cv = cn->v; cv; cv = cv->next) {
if (cv->type != CFG_STRING) {
log_error("Invalid string in config file: "
"global/segment_libraries");
return 0;
}
if (!(lib = load_shared_library(cmd->cft, cv->v.str,
"segment type"))) {
stack;
return 0;
}
if (!(init_segtype_fn = dlsym(lib, "init_segtype"))) {
log_error("Shared library %s does not contain "
"segment type functions", cv->v.str);
dlclose(lib);
return 0;
}
if (!(segtype = init_segtype_fn(cmd)))
return 0;
segtype->library = lib;
list_add(&cmd->segtypes, &segtype->list);
list_iterate_safe(sgtl, tmp, &cmd->segtypes) {
segtype2 = list_item(sgtl, struct segment_type);
if (!strcmp(segtype2->name, segtype->name)) {
log_error("Duplicate segment type %s: "
"unloading shared library %s",
segtype->name, cv->v.str);
list_del(&segtype->list);
segtype->ops->destroy(segtype);
dlclose(lib);
break;
}
}
}
}
#endif
return 1;
}
static int _init_hostname(struct cmd_context *cmd)
{
struct utsname uts;
@ -710,6 +793,7 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
cmd->args = the_args;
cmd->hosttags = 0;
list_init(&cmd->formats);
list_init(&cmd->segtypes);
list_init(&cmd->tags);
list_init(&cmd->config_files);
@ -763,6 +847,9 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
if (!_init_formats(cmd))
goto error;
if (!_init_segtypes(cmd))
goto error;
cmd->current_settings = cmd->default_settings;
cmd->config_valid = 1;
@ -791,6 +878,24 @@ static void _destroy_formats(struct list *formats)
}
}
static void _destroy_segtypes(struct list *segtypes)
{
struct list *sgtl, *tmp;
struct segment_type *segtype;
void *lib;
list_iterate_safe(sgtl, tmp, segtypes) {
segtype = list_item(sgtl, struct segment_type);
list_del(&segtype->list);
lib = segtype->library;
segtype->ops->destroy(segtype);
#ifdef HAVE_LIBDL
if (lib)
dlclose(lib);
#endif
}
}
int refresh_toolcontext(struct cmd_context *cmd)
{
log_verbose("Reloading config files");
@ -803,6 +908,7 @@ int refresh_toolcontext(struct cmd_context *cmd)
activation_exit();
lvmcache_destroy();
label_exit();
_destroy_segtypes(&cmd->segtypes);
_destroy_formats(&cmd->formats);
if (cmd->filter) {
cmd->filter->destroy(cmd->filter);
@ -842,6 +948,9 @@ int refresh_toolcontext(struct cmd_context *cmd)
if (!_init_formats(cmd))
return 0;
if (!_init_segtypes(cmd))
return 0;
cmd->config_valid = 1;
return 1;
}
@ -854,6 +963,7 @@ void destroy_toolcontext(struct cmd_context *cmd)
activation_exit();
lvmcache_destroy();
label_exit();
_destroy_segtypes(&cmd->segtypes);
_destroy_formats(&cmd->formats);
cmd->filter->destroy(cmd->filter);
pool_destroy(cmd->mem);

View File

@ -57,6 +57,7 @@ struct cmd_context {
struct format_type *fmt_backup; /* Format to use for backups */
struct list formats; /* Available formats */
struct list segtypes; /* Available segment types */
const char *hostname;
const char *kernel_vsn;

View File

@ -18,6 +18,7 @@
#include "display.h"
#include "activate.h"
#include "toolcontext.h"
#include "segtypes.h"
#define SIZE_BUF 128
@ -31,18 +32,7 @@ static struct {
ALLOC_DEFAULT, "next free (default)"}
};
static struct {
segment_type_t segtype;
const char *str;
} _segtypes[] = {
{
SEG_STRIPED, "striped"}, {
SEG_MIRRORED, "mirror"}, {
SEG_SNAPSHOT, "snapshot"}
};
static int _num_policies = sizeof(_policies) / sizeof(*_policies);
static int _num_segtypes = sizeof(_segtypes) / sizeof(*_segtypes);
uint64_t units_to_bytes(const char *units, char *unit_type)
{
@ -124,17 +114,6 @@ const char *get_alloc_string(alloc_policy_t alloc)
return NULL;
}
const char *get_segtype_string(segment_type_t segtype)
{
int i;
for (i = 0; i < _num_segtypes; i++)
if (_segtypes[i].segtype == segtype)
return _segtypes[i].str;
return "unknown";
}
alloc_policy_t get_alloc_from_string(const char *str)
{
int i;
@ -147,18 +126,6 @@ alloc_policy_t get_alloc_from_string(const char *str)
return ALLOC_DEFAULT;
}
segment_type_t get_segtype_from_string(const char *str)
{
int i;
for (i = 0; i < _num_segtypes; i++)
if (!strcmp(_segtypes[i].str, str))
return _segtypes[i].segtype;
log_error("Unrecognised segment type - using default (striped)");
return SEG_STRIPED;
}
const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
{
int s;
@ -386,8 +353,7 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
snap_active = lv_snapshot_percent(snap->cow,
&snap_percent);
if (!snap_active || snap_percent < 0 ||
snap_percent >= 100)
snap_active = 0;
snap_percent >= 100) snap_active = 0;
log_print(" %s%s/%s [%s]",
lv->vg->cmd->dev_dir, lv->vg->name,
snap->cow->name,
@ -478,7 +444,7 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
return 0;
}
static void _display_stripe(struct lv_segment *seg, uint32_t s, const char *pre)
void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre)
{
switch (seg->area[s].type) {
case AREA_PV:
@ -506,52 +472,18 @@ static void _display_stripe(struct lv_segment *seg, uint32_t s, const char *pre)
int lvdisplay_segments(struct logical_volume *lv)
{
uint32_t s;
struct list *segh;
struct lv_segment *seg;
log_print("--- Segments ---");
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
list_iterate_items(seg, &lv->segments) {
log_print("Logical extent %u to %u:",
seg->le, seg->le + seg->len - 1);
if (seg->type == SEG_STRIPED && seg->area_count == 1)
log_print(" Type\t\tlinear");
else
log_print(" Type\t\t%s",
get_segtype_string(seg->type));
log_print(" Type\t\t%s", seg->segtype->ops->name(seg));
switch (seg->type) {
case SEG_STRIPED:
if (seg->area_count == 1)
_display_stripe(seg, 0, " ");
else {
log_print(" Stripes\t\t%u", seg->area_count);
log_print(" Stripe size\t\t%u KB",
seg->stripe_size / 2);
for (s = 0; s < seg->area_count; s++) {
log_print(" Stripe %d:", s);
_display_stripe(seg, s, " ");
}
}
log_print(" ");
break;
case SEG_SNAPSHOT:
break;
case SEG_MIRRORED:
log_print(" Mirrors\t\t%u", seg->area_count);
log_print(" Mirror size\t\t%u", seg->area_len);
log_print(" Mirror original:");
_display_stripe(seg, 0, " ");
log_print(" Mirror destination:");
_display_stripe(seg, 1, " ");
log_print(" ");
break;
}
if (seg->segtype->ops->display)
seg->segtype->ops->display(seg);
}
log_print(" ");
@ -626,14 +558,12 @@ void vgdisplay_full(struct volume_group *vg)
log_print("Alloc PE / Size %u / %s",
vg->extent_count - vg->free_count, display_size(vg->cmd,
((uint64_t)
vg->
extent_count
vg->extent_count
-
vg->
free_count) *
(vg->
extent_size /
2),
vg->free_count)
*
(vg->extent_size
/ 2),
SIZE_SHORT));
log_print("Free PE / Size %u / %s", vg->free_count,
@ -714,8 +644,8 @@ void vgdisplay_short(struct volume_group *vg)
((uint64_t) vg->extent_count -
vg->free_count) * vg->extent_size / 2,
SIZE_SHORT), display_size(vg->cmd,
(uint64_t) vg->
free_count *
(uint64_t)
vg->free_count *
vg->extent_size / 2,
SIZE_SHORT));
return;

View File

@ -27,6 +27,7 @@ uint64_t units_to_bytes(const char *units, char *unit_type);
/* Specify size in KB */
const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl);
char *display_uuid(char *uuidstr);
void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre);
void pvdisplay_colons(struct physical_volume *pv);
void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
@ -50,10 +51,4 @@ void vgdisplay_short(struct volume_group *vg);
const char *get_alloc_string(alloc_policy_t alloc);
alloc_policy_t get_alloc_from_string(const char *str);
/*
* Segment type display conversion routines.
*/
segment_type_t get_segtype_from_string(const char *str);
const char *get_segtype_string(segment_type_t segtype);
#endif

View File

@ -153,6 +153,10 @@ static int _munge_formats(struct pv_disk *pvd)
memset(&pvd->pv_uuid[ID_LEN], 0, sizeof(pvd->pv_uuid) - ID_LEN);
}
/* If UUID is missing, create one */
if (pvd->pv_uuid[0] == '\0')
uuid_from_num(pvd->pv_uuid, pvd->pv_number);
return 1;
}
@ -193,10 +197,6 @@ int munge_pvd(struct device *dev, struct pv_disk *pvd)
return 0;
}
/* If UUID is missing, create one */
if (pvd->pv_uuid[0] == '\0')
uuid_from_num(pvd->pv_uuid, pvd->pv_number);
/* If VG is exported, set VG name back to the real name */
_munge_exported_vg(pvd);

View File

@ -216,7 +216,7 @@ int export_vg(struct vg_disk *vgd, struct volume_group *vg);
int import_lv(struct pool *mem, struct logical_volume *lv, struct lv_disk *lvd);
int import_extents(struct pool *mem, struct volume_group *vg,
int import_extents(struct cmd_context *cmd, struct volume_group *vg,
struct list *pvds);
int export_extents(struct disk_list *dl, uint32_t lv_num,
struct logical_volume *lv, struct physical_volume *pv);

View File

@ -164,7 +164,7 @@ static struct volume_group *_build_vg(struct format_instance *fid,
if (!import_lvs(mem, vg, pvs))
goto bad;
if (!import_extents(mem, vg, pvs))
if (!import_extents(fid->fmt->cmd, vg, pvs))
goto bad;
if (!import_snapshots(mem, vg, pvs))

View File

@ -25,6 +25,7 @@
#include "lvm-string.h"
#include "filter.h"
#include "toolcontext.h"
#include "segtypes.h"
#include <time.h>
@ -380,9 +381,10 @@ int export_extents(struct disk_list *dl, uint32_t lv_num,
seg = list_item(segh, struct lv_segment);
for (s = 0; s < seg->area_count; s++) {
if (seg->type != SEG_STRIPED) {
log_error("Non-striped segment type in LV %s: "
"unsupported by format1", lv->name);
if (!(seg->segtype->flags & SEG_FORMAT1_SUPPORT)) {
log_error("Segment type %s in LV %s: "
"unsupported by format1",
seg->segtype->name, lv->name);
return 0;
}
if (seg->area[s].type != AREA_PV) {

View File

@ -19,6 +19,8 @@
#include "pool.h"
#include "disk-rep.h"
#include "lv_alloc.h"
#include "display.h"
#include "segtypes.h"
/*
* After much thought I have decided it is easier,
@ -201,16 +203,20 @@ static int _check_maps_are_complete(struct hash_table *maps)
return 1;
}
static int _read_linear(struct pool *mem, struct lv_map *lvm)
static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
{
uint32_t le = 0;
struct lv_segment *seg;
while (le < lvm->lv->le_count) {
seg = alloc_lv_segment(mem, 1);
seg = alloc_lv_segment(cmd->mem, 1);
seg->lv = lvm->lv;
seg->type = SEG_STRIPED;
if (!(seg->segtype = get_segtype_from_string(cmd, "striped"))) {
stack;
return 0;
}
seg->le = le;
seg->len = 0;
seg->area_len = 0;
@ -251,13 +257,12 @@ static int _check_stripe(struct lv_map *lvm, struct lv_segment *seg,
if ((lvm->map[le + st * len].pv != seg->area[st].u.pv.pv) ||
(seg->area[st].u.pv.pv &&
lvm->map[le + st * len].pe !=
seg->area[st].u.pv.pe + seg->len))
return 0;
seg->area[st].u.pv.pe + seg->len)) return 0;
return 1;
}
static int _read_stripes(struct pool *mem, struct lv_map *lvm)
static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
{
uint32_t st, le = 0, len;
struct lv_segment *seg;
@ -273,13 +278,16 @@ static int _read_stripes(struct pool *mem, struct lv_map *lvm)
len = lvm->lv->le_count / lvm->stripes;
while (le < len) {
if (!(seg = alloc_lv_segment(mem, lvm->stripes))) {
if (!(seg = alloc_lv_segment(cmd->mem, lvm->stripes))) {
stack;
return 0;
}
seg->lv = lvm->lv;
seg->type = SEG_STRIPED;
if (!(seg->segtype = get_segtype_from_string(cmd, "striped"))) {
stack;
return 0;
}
seg->stripe_size = lvm->stripe_size;
seg->area_count = lvm->stripes;
seg->le = seg->area_count * le;
@ -312,20 +320,20 @@ static int _read_stripes(struct pool *mem, struct lv_map *lvm)
return 1;
}
static int _build_segments(struct pool *mem, struct lv_map *lvm)
static int _build_segments(struct cmd_context *cmd, struct lv_map *lvm)
{
return (lvm->stripes > 1 ? _read_stripes(mem, lvm) :
_read_linear(mem, lvm));
return (lvm->stripes > 1 ? _read_stripes(cmd, lvm) :
_read_linear(cmd, lvm));
}
static int _build_all_segments(struct pool *mem, struct hash_table *maps)
static int _build_all_segments(struct cmd_context *cmd, struct hash_table *maps)
{
struct hash_node *n;
struct lv_map *lvm;
for (n = hash_get_first(maps); n; n = hash_get_next(maps, n)) {
lvm = (struct lv_map *) hash_get_data(maps, n);
if (!_build_segments(mem, lvm)) {
if (!_build_segments(cmd, lvm)) {
stack;
return 0;
}
@ -334,7 +342,8 @@ static int _build_all_segments(struct pool *mem, struct hash_table *maps)
return 1;
}
int import_extents(struct pool *mem, struct volume_group *vg, struct list *pvds)
int import_extents(struct cmd_context *cmd, struct volume_group *vg,
struct list *pvds)
{
int r = 0;
struct pool *scratch = pool_create(10 * 1024);
@ -360,7 +369,7 @@ int import_extents(struct pool *mem, struct volume_group *vg, struct list *pvds)
goto out;
}
if (!_build_all_segments(mem, maps)) {
if (!_build_all_segments(cmd, maps)) {
log_err("Couldn't build extent segments.");
goto out;
}

View File

@ -380,4 +380,3 @@ int backup_list(struct cmd_context *cmd, const char *dir, const char *vgname)
return 1;
}

View File

@ -20,6 +20,8 @@
#include "pool.h"
#include "display.h"
#include "lvm-string.h"
#include "segtypes.h"
#include "text_export.h"
#include <stdarg.h>
#include <time.h>
@ -74,14 +76,6 @@ static void _init(void)
/*
* Formatting functions.
*/
static int _out_size(struct formatter *f, uint64_t size, const char *fmt, ...)
__attribute__ ((format(printf, 3, 4)));
static int _out_hint(struct formatter *f, const char *fmt, ...)
__attribute__ ((format(printf, 2, 3)));
static int _out(struct formatter *f, const char *fmt, ...)
__attribute__ ((format(printf, 2, 3)));
#define MAX_INDENT 5
static void _inc_indent(struct formatter *f)
@ -206,7 +200,7 @@ static int _sectors_to_units(uint64_t sectors, char *buffer, size_t s)
* Appends a comment giving a size in more easily
* readable form (eg, 4M instead of 8096).
*/
static int _out_size(struct formatter *f, uint64_t size, const char *fmt, ...)
int out_size(struct formatter *f, uint64_t size, const char *fmt, ...)
{
char buffer[64];
va_list ap;
@ -226,7 +220,7 @@ static int _out_size(struct formatter *f, uint64_t size, const char *fmt, ...)
* Appends a comment indicating that the line is
* only a hint.
*/
static int _out_hint(struct formatter *f, const char *fmt, ...)
int out_hint(struct formatter *f, const char *fmt, ...)
{
va_list ap;
int r;
@ -241,7 +235,7 @@ static int _out_hint(struct formatter *f, const char *fmt, ...)
/*
* The normal output function.
*/
static int _out(struct formatter *f, const char *fmt, ...)
int out_text(struct formatter *f, const char *fmt, ...)
{
va_list ap;
int r;
@ -253,8 +247,6 @@ static int _out(struct formatter *f, const char *fmt, ...)
return r;
}
#define _outf(args...) do {if (!_out(args)) {stack; return 0;}} while (0)
static int _print_header(struct formatter *f,
struct volume_group *vg, const char *desc)
{
@ -262,17 +254,17 @@ static int _print_header(struct formatter *f,
t = time(NULL);
_outf(f, "# Generated by LVM2: %s", ctime(&t));
_outf(f, CONTENTS_FIELD " = \"" CONTENTS_VALUE "\"");
_outf(f, FORMAT_VERSION_FIELD " = %d", FORMAT_VERSION_VALUE);
outf(f, "# Generated by LVM2: %s", ctime(&t));
outf(f, CONTENTS_FIELD " = \"" CONTENTS_VALUE "\"");
outf(f, FORMAT_VERSION_FIELD " = %d", FORMAT_VERSION_VALUE);
f->nl(f);
_outf(f, "description = \"%s\"", desc);
outf(f, "description = \"%s\"", desc);
f->nl(f);
_outf(f, "creation_host = \"%s\"\t# %s %s %s %s %s", _utsname.nodename,
_utsname.sysname, _utsname.nodename, _utsname.release,
_utsname.version, _utsname.machine);
_outf(f, "creation_time = %lu\t# %s", t, ctime(&t));
outf(f, "creation_host = \"%s\"\t# %s %s %s %s %s", _utsname.nodename,
_utsname.sysname, _utsname.nodename, _utsname.release,
_utsname.version, _utsname.machine);
outf(f, "creation_time = %lu\t# %s", t, ctime(&t));
return 1;
}
@ -286,34 +278,34 @@ static int _print_vg(struct formatter *f, struct volume_group *vg)
return 0;
}
_outf(f, "id = \"%s\"", buffer);
outf(f, "id = \"%s\"", buffer);
_outf(f, "seqno = %u", vg->seqno);
outf(f, "seqno = %u", vg->seqno);
if (!print_flags(vg->status, VG_FLAGS, buffer, sizeof(buffer))) {
stack;
return 0;
}
_outf(f, "status = %s", buffer);
outf(f, "status = %s", buffer);
if (!list_empty(&vg->tags)) {
if (!print_tags(&vg->tags, buffer, sizeof(buffer))) {
stack;
return 0;
}
_outf(f, "tags = %s", buffer);
outf(f, "tags = %s", buffer);
}
if (vg->system_id && *vg->system_id)
_outf(f, "system_id = \"%s\"", vg->system_id);
outf(f, "system_id = \"%s\"", vg->system_id);
if (!_out_size(f, (uint64_t) vg->extent_size, "extent_size = %u",
vg->extent_size)) {
if (!out_size(f, (uint64_t) vg->extent_size, "extent_size = %u",
vg->extent_size)) {
stack;
return 0;
}
_outf(f, "max_lv = %u", vg->max_lv);
_outf(f, "max_pv = %u", vg->max_pv);
outf(f, "max_lv = %u", vg->max_lv);
outf(f, "max_pv = %u", vg->max_pv);
return 1;
}
@ -336,7 +328,7 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
char buffer[4096];
const char *name;
_outf(f, "physical_volumes {");
outf(f, "physical_volumes {");
_inc_indent(f);
list_iterate(pvh, &vg->pvs) {
@ -348,7 +340,7 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
}
f->nl(f);
_outf(f, "%s {", name);
outf(f, "%s {", name);
_inc_indent(f);
if (!id_write_format(&pv->id, buffer, sizeof(buffer))) {
@ -356,8 +348,8 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
return 0;
}
_outf(f, "id = \"%s\"", buffer);
if (!_out_hint(f, "device = \"%s\"", dev_name(pv->dev))) {
outf(f, "id = \"%s\"", buffer);
if (!out_hint(f, "device = \"%s\"", dev_name(pv->dev))) {
stack;
return 0;
}
@ -367,119 +359,105 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
stack;
return 0;
}
_outf(f, "status = %s", buffer);
outf(f, "status = %s", buffer);
if (!list_empty(&pv->tags)) {
if (!print_tags(&pv->tags, buffer, sizeof(buffer))) {
stack;
return 0;
}
_outf(f, "tags = %s", buffer);
outf(f, "tags = %s", buffer);
}
_outf(f, "pe_start = %" PRIu64, pv->pe_start);
if (!_out_size(f, vg->extent_size * (uint64_t) pv->pe_count,
"pe_count = %u", pv->pe_count)) {
outf(f, "pe_start = %" PRIu64, pv->pe_start);
if (!out_size(f, vg->extent_size * (uint64_t) pv->pe_count,
"pe_count = %u", pv->pe_count)) {
stack;
return 0;
}
_dec_indent(f);
_outf(f, "}");
outf(f, "}");
}
_dec_indent(f);
_outf(f, "}");
outf(f, "}");
return 1;
}
static int _print_segment(struct formatter *f, struct volume_group *vg,
int count, struct lv_segment *seg)
{
unsigned int s;
const char *name;
const char *type;
char buffer[4096];
_outf(f, "segment%u {", count);
outf(f, "segment%u {", count);
_inc_indent(f);
_outf(f, "start_extent = %u", seg->le);
if (!_out_size(f, (uint64_t) seg->len * vg->extent_size,
"extent_count = %u", seg->len)) {
outf(f, "start_extent = %u", seg->le);
if (!out_size(f, (uint64_t) seg->len * vg->extent_size,
"extent_count = %u", seg->len)) {
stack;
return 0;
}
f->nl(f);
_outf(f, "type = \"%s\"", get_segtype_string(seg->type));
outf(f, "type = \"%s\"", seg->segtype->name);
if (!list_empty(&seg->tags)) {
if (!print_tags(&seg->tags, buffer, sizeof(buffer))) {
stack;
return 0;
}
_outf(f, "tags = %s", buffer);
outf(f, "tags = %s", buffer);
}
switch (seg->type) {
case SEG_SNAPSHOT:
_outf(f, "chunk_size = %u", seg->chunk_size);
_outf(f, "origin = \"%s\"", seg->origin->name);
_outf(f, "cow_store = \"%s\"", seg->cow->name);
break;
case SEG_MIRRORED:
case SEG_STRIPED:
type = (seg->type == SEG_MIRRORED) ? "mirror" : "stripe";
_outf(f, "%s_count = %u%s", type, seg->area_count,
(seg->area_count == 1) ? "\t# linear" : "");
if ((seg->type == SEG_MIRRORED) && (seg->status & PVMOVE))
_out_size(f, (uint64_t) seg->extents_moved,
"extents_moved = %u", seg->extents_moved);
if ((seg->type == SEG_STRIPED) && (seg->area_count > 1))
_out_size(f, (uint64_t) seg->stripe_size,
"stripe_size = %u", seg->stripe_size);
f->nl(f);
_outf(f, "%ss = [", type);
_inc_indent(f);
for (s = 0; s < seg->area_count; s++) {
switch (seg->area[s].type) {
case AREA_PV:
if (!(name = _get_pv_name(f, seg->
area[s].u.pv.pv))) {
stack;
return 0;
}
_outf(f, "\"%s\", %u%s", name,
seg->area[s].u.pv.pe,
(s == seg->area_count - 1) ? "" : ",");
break;
case AREA_LV:
_outf(f, "\"%s\", %u%s",
seg->area[s].u.lv.lv->name,
seg->area[s].u.lv.le,
(s == seg->area_count - 1) ? "" : ",");
}
}
_dec_indent(f);
_outf(f, "]");
break;
if (!seg->segtype->ops->text_export(seg, f)) {
stack;
return 0;
}
_dec_indent(f);
_outf(f, "}");
outf(f, "}");
return 1;
}
int out_areas(struct formatter *f, const struct lv_segment *seg,
const char *type)
{
const char *name;
unsigned int s;
f->nl(f);
outf(f, "%ss = [", type);
_inc_indent(f);
for (s = 0; s < seg->area_count; s++) {
switch (seg->area[s].type) {
case AREA_PV:
if (!(name = _get_pv_name(f, seg->area[s].u.pv.pv))) {
stack;
return 0;
}
outf(f, "\"%s\", %u%s", name,
seg->area[s].u.pv.pe,
(s == seg->area_count - 1) ? "" : ",");
break;
case AREA_LV:
outf(f, "\"%s\", %u%s",
seg->area[s].u.lv.lv->name,
seg->area[s].u.lv.le,
(s == seg->area_count - 1) ? "" : ",");
}
}
_dec_indent(f);
outf(f, "]");
return 1;
}
static int _count_segments(struct logical_volume *lv)
{
int r = 0;
@ -499,7 +477,7 @@ static int _print_snapshot(struct formatter *f, struct snapshot *snap,
f->nl(f);
_outf(f, "snapshot%u {", count);
outf(f, "snapshot%u {", count);
_inc_indent(f);
if (!id_write_format(&snap->id, buffer, sizeof(buffer))) {
@ -507,25 +485,39 @@ static int _print_snapshot(struct formatter *f, struct snapshot *snap,
return 0;
}
_outf(f, "id = \"%s\"", buffer);
if (!print_flags(LVM_READ | LVM_WRITE | VISIBLE_LV, LV_FLAGS,
buffer, sizeof(buffer))) {
outf(f, "id = \"%s\"", buffer);
seg.status = LVM_READ | LVM_WRITE | VISIBLE_LV;
if (!print_flags(seg.status, LV_FLAGS, buffer, sizeof(buffer))) {
stack;
return 0;
}
_outf(f, "status = %s", buffer);
_outf(f, "segment_count = 1");
outf(f, "status = %s", buffer);
outf(f, "segment_count = 1");
f->nl(f);
seg.type = SEG_SNAPSHOT;
if (!(seg.segtype = get_segtype_from_string(snap->origin->vg->cmd,
"snapshot"))) {
stack;
return 0;
}
seg.le = 0;
seg.len = snap->origin->le_count;
seg.origin = snap->origin;
seg.cow = snap->cow;
seg.chunk_size = snap->chunk_size;
/* FIXME Dummy values */
list_init(&seg.list);
seg.lv = snap->cow;
seg.stripe_size = 0;
seg.area_count = 0;
seg.area_len = 0;
seg.extents_moved = 0;
/* Can't tag a snapshot independently of its origin */
list_init(&seg.tags);
@ -535,7 +527,7 @@ static int _print_snapshot(struct formatter *f, struct snapshot *snap,
}
_dec_indent(f);
_outf(f, "}");
outf(f, "}");
return 1;
}
@ -572,14 +564,14 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
if (list_empty(&vg->lvs))
return 1;
_outf(f, "logical_volumes {");
outf(f, "logical_volumes {");
_inc_indent(f);
list_iterate(lvh, &vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv;
f->nl(f);
_outf(f, "%s {", lv->name);
outf(f, "%s {", lv->name);
_inc_indent(f);
/* FIXME: Write full lvid */
@ -588,32 +580,32 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
return 0;
}
_outf(f, "id = \"%s\"", buffer);
outf(f, "id = \"%s\"", buffer);
if (!print_flags(lv->status, LV_FLAGS, buffer, sizeof(buffer))) {
stack;
return 0;
}
_outf(f, "status = %s", buffer);
outf(f, "status = %s", buffer);
if (!list_empty(&lv->tags)) {
if (!print_tags(&lv->tags, buffer, sizeof(buffer))) {
stack;
return 0;
}
_outf(f, "tags = %s", buffer);
outf(f, "tags = %s", buffer);
}
if (lv->alloc != ALLOC_DEFAULT)
_outf(f, "allocation_policy = \"%s\"",
get_alloc_string(lv->alloc));
outf(f, "allocation_policy = \"%s\"",
get_alloc_string(lv->alloc));
if (lv->read_ahead)
_outf(f, "read_ahead = %u", lv->read_ahead);
outf(f, "read_ahead = %u", lv->read_ahead);
if (lv->major >= 0)
_outf(f, "major = %d", lv->major);
outf(f, "major = %d", lv->major);
if (lv->minor >= 0)
_outf(f, "minor = %d", lv->minor);
_outf(f, "segment_count = %u", _count_segments(lv));
outf(f, "minor = %d", lv->minor);
outf(f, "segment_count = %u", _count_segments(lv));
f->nl(f);
seg_count = 1;
@ -625,7 +617,7 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
}
_dec_indent(f);
_outf(f, "}");
outf(f, "}");
}
if (!_print_snapshots(f, vg)) {
@ -634,7 +626,7 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
}
_dec_indent(f);
_outf(f, "}");
outf(f, "}");
return 1;
}
@ -707,7 +699,7 @@ static int _text_vg_export(struct formatter *f,
if (f->header && !_print_header(f, vg, desc))
fail;
if (!_out(f, "%s {", vg->name))
if (!out_text(f, "%s {", vg->name))
fail;
_inc_indent(f);
@ -724,7 +716,7 @@ static int _text_vg_export(struct formatter *f,
fail;
_dec_indent(f);
if (!_out(f, "}"))
if (!out_text(f, "}"))
fail;
if (!f->header && !_print_header(f, vg, desc))
@ -804,4 +796,4 @@ int text_vg_export_raw(struct volume_group *vg, const char *desc, char *buf,
return r;
}
#undef _outf
#undef outf

View File

@ -52,6 +52,7 @@ static struct flag _lv_flags[] = {
{VISIBLE_LV, "VISIBLE"},
{PVMOVE, "PVMOVE"},
{LOCKED, "LOCKED"},
{MIRRORED, NULL},
{0, NULL}
};
@ -99,7 +100,8 @@ int print_flags(uint32_t status, int type, char *buffer, size_t size)
} else
first = 0;
if (!emit_to_buffer(&buffer, &size, "\"%s\"",
if (flags[f].description &&
!emit_to_buffer(&buffer, &size, "\"%s\"",
flags[f].description))
return 0;

View File

@ -30,6 +30,7 @@
#include "xlate.h"
#include "label.h"
#include "memlock.h"
#include "lvmcache.h"
#include <unistd.h>
#include <sys/file.h>
@ -928,8 +929,7 @@ static int _mda_setup(const struct format_type *fmt,
/* FIXME If creating new mdas, wipe them! */
if (mda_size1) {
if (!add_mda(fmt, fmt->cmd->mem, mdas, pv->dev, start1,
mda_size1))
return 0;
mda_size1)) return 0;
if (!dev_zero((struct device *) pv->dev, start1,
(size_t) (mda_size1 >
@ -976,8 +976,7 @@ static int _mda_setup(const struct format_type *fmt,
if (mda_size2) {
if (!add_mda(fmt, fmt->cmd->mem, mdas, pv->dev, start2,
mda_size2))
return 0;
mda_size2)) return 0;
if (!dev_zero(pv->dev, start2,
(size_t) (mda_size1 >
wipe_size ? wipe_size : mda_size1))) {
@ -1066,8 +1065,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
}
}
if (!add_da
(fmt, NULL, &info->das, pv->pe_start << SECTOR_SHIFT,
UINT64_C(0))) {
(fmt, NULL, &info->das, pv->pe_start << SECTOR_SHIFT, UINT64_C(0))) {
stack;
return 0;
}
@ -1139,8 +1137,7 @@ static int _add_raw(struct list *raw_list, struct device_area *dev_area)
rl = list_item(rlh, struct raw_list);
/* FIXME Check size/overlap consistency too */
if (rl->dev_area.dev == dev_area->dev &&
rl->dev_area.start == dev_area->start)
return 1;
rl->dev_area.start == dev_area->start) return 1;
}
if (!(rl = dbg_malloc(sizeof(struct raw_list)))) {
@ -1334,11 +1331,10 @@ static int _pv_setup(const struct format_type *fmt,
list_item(mdash,
struct metadata_area);
if (mda2->ops !=
&_metadata_text_raw_ops)
continue;
&_metadata_text_raw_ops) continue;
mdac2 =
(struct mda_context *) mda2->
metadata_locn;
(struct mda_context *)
mda2->metadata_locn;
if (!memcmp
(&mdac2->area, &mdac->area,
sizeof(mdac->area))) {
@ -1356,8 +1352,7 @@ static int _pv_setup(const struct format_type *fmt,
}
if (!(mdac_new = pool_alloc(fmt->cmd->mem,
sizeof(*mdac_new))))
{
sizeof(*mdac_new)))) {
stack;
return 0;
}
@ -1486,8 +1481,7 @@ static struct format_instance *_create_text_instance(const struct format_type
}
if (!(mdac_new = pool_alloc(fmt->cmd->mem,
sizeof(*mdac_new))))
{
sizeof(*mdac_new)))) {
stack;
return NULL;
}

View File

@ -22,6 +22,8 @@
#include "toolcontext.h"
#include "lvmcache.h"
#include "lv_alloc.h"
#include "segtypes.h"
#include "text_import.h"
typedef int (*section_fn) (struct format_instance * fid, struct pool * mem,
struct volume_group * vg, struct config_node * pvn,
@ -234,17 +236,13 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
struct logical_volume *lv, struct config_node *sn,
struct hash_table *pv_hash)
{
unsigned int s;
uint32_t area_count = 0;
uint32_t area_count = 0u;
struct lv_segment *seg;
struct config_node *cn;
struct config_value *cv;
const char *seg_name = sn->key;
uint32_t start_extent, extent_count;
uint32_t chunk_size, extents_moved = 0u, seg_status = 0u;
const char *org_name, *cow_name;
struct logical_volume *org, *cow, *lv1;
segment_type_t segtype;
struct segment_type *segtype;
const char *segtype_str;
if (!(sn = sn->child)) {
log_error("Empty segment section.");
@ -263,40 +261,26 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
return 0;
}
segtype = SEG_STRIPED; /* Default */
segtype_str = "striped";
if ((cn = find_config_node(sn, "type"))) {
cv = cn->v;
if (!cv || !cv->v.str) {
log_error("Segment type must be a string.");
return 0;
}
segtype = get_segtype_from_string(cv->v.str);
segtype_str = cv->v.str;
}
if (segtype == SEG_STRIPED) {
if (!_read_int32(sn, "stripe_count", &area_count)) {
log_error("Couldn't read 'stripe_count' for "
"segment '%s'.", sn->key);
return 0;
}
if (!(segtype = get_segtype_from_string(vg->cmd, segtype_str))) {
stack;
return 0;
}
if (segtype == SEG_MIRRORED) {
if (!_read_int32(sn, "mirror_count", &area_count)) {
log_error("Couldn't read 'mirror_count' for "
"segment '%s'.", sn->key);
return 0;
}
if (find_config_node(sn, "extents_moved")) {
if (_read_uint32(sn, "extents_moved", &extents_moved))
seg_status |= PVMOVE;
else {
log_error("Couldn't read 'extents_moved' for "
"segment '%s'.", sn->key);
return 0;
}
}
if (segtype->ops->text_import_area_count &&
!segtype->ops->text_import_area_count(sn, &area_count)) {
stack;
return 0;
}
if (!(seg = alloc_lv_segment(mem, area_count))) {
@ -308,9 +292,16 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
seg->le = start_extent;
seg->len = extent_count;
seg->area_len = extent_count;
seg->type = segtype;
seg->status = seg_status;
seg->extents_moved = extents_moved;
seg->status = 0u;
seg->segtype = segtype;
seg->extents_moved = 0u;
seg->area_count = area_count;
if (seg->segtype->ops->text_import &&
!seg->segtype->ops->text_import(seg, sn, pv_hash)) {
stack;
return 0;
}
/* Optional tags */
if ((cn = find_config_node(sn, "tags")) &&
@ -320,145 +311,86 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
return 0;
}
switch (segtype) {
case SEG_SNAPSHOT:
lv->status |= SNAPSHOT;
if (!_read_uint32(sn, "chunk_size", &chunk_size)) {
log_error("Couldn't read chunk size for snapshot.");
return 0;
}
log_suppress(1);
if (!(cow_name = find_config_str(sn, "cow_store", NULL))) {
log_suppress(0);
log_error("Snapshot cow storage not specified.");
return 0;
}
if (!(org_name = find_config_str(sn, "origin", NULL))) {
log_suppress(0);
log_error("Snapshot origin not specified.");
return 0;
}
log_suppress(0);
if (!(cow = find_lv(vg, cow_name))) {
log_error("Unknown logical volume specified for "
"snapshot cow store.");
return 0;
}
if (!(org = find_lv(vg, org_name))) {
log_error("Unknown logical volume specified for "
"snapshot origin.");
return 0;
}
if (!vg_add_snapshot(org, cow, 1, &lv->lvid.id[1], chunk_size)) {
stack;
return 0;
}
break;
case SEG_STRIPED:
if ((area_count != 1) &&
!_read_int32(sn, "stripe_size", &seg->stripe_size)) {
log_error("Couldn't read stripe_size for segment '%s'.",
sn->key);
return 0;
}
if (!(cn = find_config_node(sn, "stripes"))) {
log_error("Couldn't find stripes array for segment "
"'%s'.", sn->key);
return 0;
}
seg->area_len /= area_count;
case SEG_MIRRORED:
seg->area_count = area_count;
if (!seg->area_count) {
log_error("Zero areas not allowed for segment '%s'",
sn->key);
return 0;
}
if ((seg->type == SEG_MIRRORED) &&
!(cn = find_config_node(sn, "mirrors"))) {
log_error("Couldn't find mirrors array for segment "
"'%s'.", sn->key);
return 0;
}
for (cv = cn->v, s = 0; cv && s < seg->area_count;
s++, cv = cv->next) {
/* first we read the pv */
const char *bad = "Badly formed areas array for "
"segment '%s'.";
struct physical_volume *pv;
if (cv->type != CFG_STRING) {
log_error(bad, sn->key);
return 0;
}
if (!cv->next) {
log_error(bad, sn->key);
return 0;
}
if (cv->next->type != CFG_INT) {
log_error(bad, sn->key);
return 0;
}
/* FIXME Cope if LV not yet read in */
if ((pv = hash_lookup(pv_hash, cv->v.str))) {
seg->area[s].type = AREA_PV;
seg->area[s].u.pv.pv = pv;
seg->area[s].u.pv.pe = cv->next->v.i;
/*
* Adjust extent counts in the pv and vg.
*/
pv->pe_alloc_count += seg->area_len;
vg->free_count -= seg->area_len;
} else if ((lv1 = find_lv(vg, cv->v.str))) {
seg->area[s].type = AREA_LV;
seg->area[s].u.lv.lv = lv1;
seg->area[s].u.lv.le = cv->next->v.i;
} else {
log_error("Couldn't find volume '%s' "
"for segment '%s'.",
cv->v.str ? cv->v.str : "NULL",
seg_name);
return 0;
}
cv = cv->next;
}
/*
* Check we read the correct number of stripes.
*/
if (cv || (s < seg->area_count)) {
log_error("Incorrect number of areas in area array "
"for segment '%s'.", seg_name);
return 0;
}
}
/*
* Insert into correct part of segment list.
*/
_insert_segment(lv, seg);
if (seg->segtype->flags & SEG_AREAS_MIRRORED)
lv->status |= MIRRORED;
return 1;
}
int text_import_areas(struct lv_segment *seg, const struct config_node *sn,
const struct config_node *cn, struct hash_table *pv_hash)
{
unsigned int s;
struct config_value *cv;
struct logical_volume *lv1;
const char *seg_name = sn->key;
if (!seg->area_count) {
log_error("Zero areas not allowed for segment '%s'", sn->key);
return 0;
}
for (cv = cn->v, s = 0; cv && s < seg->area_count; s++, cv = cv->next) {
/* first we read the pv */
const char *bad = "Badly formed areas array for "
"segment '%s'.";
struct physical_volume *pv;
if (cv->type != CFG_STRING) {
log_error(bad, sn->key);
return 0;
}
if (!cv->next) {
log_error(bad, sn->key);
return 0;
}
if (cv->next->type != CFG_INT) {
log_error(bad, sn->key);
return 0;
}
/* FIXME Cope if LV not yet read in */
if ((pv = hash_lookup(pv_hash, cv->v.str))) {
seg->area[s].type = AREA_PV;
seg->area[s].u.pv.pv = pv;
seg->area[s].u.pv.pe = cv->next->v.i;
/*
* Adjust extent counts in the pv and vg.
*/
pv->pe_alloc_count += seg->area_len;
seg->lv->vg->free_count -= seg->area_len;
} else if ((lv1 = find_lv(seg->lv->vg, cv->v.str))) {
seg->area[s].type = AREA_LV;
seg->area[s].u.lv.lv = lv1;
seg->area[s].u.lv.le = cv->next->v.i;
} else {
log_error("Couldn't find volume '%s' "
"for segment '%s'.",
cv->v.str ? cv->v.str : "NULL", seg_name);
return 0;
}
cv = cv->next;
}
/*
* Check we read the correct number of stripes.
*/
if (cv || (s < seg->area_count)) {
log_error("Incorrect number of areas in area array "
"for segment '%s'.", seg_name);
return 0;
}
return 1;
}

View File

@ -0,0 +1,36 @@
/*
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
* 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
*/
#ifndef _LVM_TEXT_EXPORT_H
#define _LVM_TEXT_EXPORT_H
#define outf(args...) do {if (!out_text(args)) {stack; return 0;}} while (0)
struct formatter;
struct lv_segment;
int out_size(struct formatter *f, uint64_t size, const char *fmt, ...)
__attribute__ ((format(printf, 3, 4)));
int out_hint(struct formatter *f, const char *fmt, ...)
__attribute__ ((format(printf, 2, 3)));
int out_text(struct formatter *f, const char *fmt, ...)
__attribute__ ((format(printf, 2, 3)));
int out_areas(struct formatter *f, const struct lv_segment *seg,
const char *type);
#endif

View File

@ -0,0 +1,25 @@
/*
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
* 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
*/
#ifndef _LVM_TEXT_IMPORT_H
#define _LVM_TEXT_IMPORT_H
struct lv_segment;
struct config_node;
int text_import_areas(struct lv_segment *seg, const struct config_node *sn,
const struct config_node *cn, struct hash_table *pv_hash);
#endif

View File

@ -18,6 +18,7 @@
#include "layout.h"
#include "label.h"
#include "xlate.h"
#include "lvmcache.h"
#include <sys/stat.h>
#include <fcntl.h>

View File

@ -19,6 +19,7 @@
#include "crc.h"
#include "xlate.h"
#include "lvmcache.h"
#include "metadata.h"
#include <sys/stat.h>
#include <fcntl.h>
@ -78,6 +79,8 @@ void label_exit(void)
li->l->ops->destroy(li->l);
_free_li(li);
}
list_init(&_labellers);
}
int label_register_handler(const char *name, struct labeller *handler)

View File

@ -16,7 +16,6 @@
#ifndef _LVM_LABEL_H
#define _LVM_LABEL_H
#include "lvmcache.h"
#include "uuid.h"
#include "device.h"
@ -25,6 +24,8 @@
#define LABEL_SCAN_SECTORS 4L
#define LABEL_SCAN_SIZE (LABEL_SCAN_SECTORS << SECTOR_SHIFT)
struct labeller;
/* On disk - 32 bytes */
struct label_header {
uint8_t id[8]; /* LABELONE */

View File

@ -13,7 +13,6 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "metadata.h"
#include "uuid.h"
#include "config.h"

View File

@ -20,6 +20,8 @@
#include "lvm-string.h"
#include "toolcontext.h"
#include "lv_alloc.h"
#include "display.h"
#include "segtypes.h"
/*
* These functions adjust the pe counts in pv's
@ -76,6 +78,7 @@ struct lv_segment *alloc_lv_segment(struct pool *mem, uint32_t num_areas)
static int _alloc_parallel_area(struct logical_volume *lv, uint32_t area_count,
uint32_t stripe_size,
struct segment_type *segtype,
struct pv_area **areas, uint32_t *ix)
{
uint32_t count, area_len, smallest;
@ -83,7 +86,9 @@ static int _alloc_parallel_area(struct logical_volume *lv, uint32_t area_count,
struct lv_segment *seg;
int striped = 0;
striped = 1;
/* Striped or mirrored? */
if (segtype->flags & SEG_AREAS_STRIPED)
striped = 1;
count = lv->le_count - *ix;
area_len = count / (striped ? area_count : 1);
@ -98,7 +103,7 @@ static int _alloc_parallel_area(struct logical_volume *lv, uint32_t area_count,
}
seg->lv = lv;
seg->type = SEG_STRIPED;
seg->segtype = segtype;
seg->le = *ix;
seg->len = area_len * (striped ? area_count : 1);
seg->area_len = area_len;
@ -116,6 +121,10 @@ static int _alloc_parallel_area(struct logical_volume *lv, uint32_t area_count,
list_add(&lv->segments, &seg->list);
*ix += seg->len;
if (!striped)
lv->status |= MIRRORED;
return 1;
}
@ -135,7 +144,8 @@ static int _comp_area(const void *l, const void *r)
static int _alloc_parallel(struct logical_volume *lv,
struct list *pvms, uint32_t allocated,
uint32_t stripes, uint32_t stripe_size)
uint32_t stripes, uint32_t stripe_size,
uint32_t mirrors, struct segment_type *segtype)
{
int r = 0;
struct list *pvmh;
@ -145,7 +155,15 @@ static int _alloc_parallel(struct logical_volume *lv,
size_t len;
uint32_t area_count;
area_count = stripes;
if (stripes > 1 && mirrors > 1) {
log_error("striped mirrors are not supported yet");
return 0;
}
if (stripes > 1)
area_count = stripes;
else
area_count = mirrors;
list_iterate(pvmh, pvms)
pv_count++;
@ -179,8 +197,8 @@ static int _alloc_parallel(struct logical_volume *lv,
/* sort the areas so we allocate from the biggest */
qsort(areas, ix, sizeof(*areas), _comp_area);
if (!_alloc_parallel_area(lv, area_count, stripe_size, areas,
&allocated)) {
if (!_alloc_parallel_area(lv, area_count, stripe_size, segtype,
areas, &allocated)) {
stack;
goto out;
}
@ -215,7 +233,11 @@ static int _alloc_linear_area(struct logical_volume *lv, uint32_t *ix,
}
seg->lv = lv;
seg->type = SEG_STRIPED;
if (!(seg->segtype = get_segtype_from_string(lv->vg->cmd, "striped"))) {
stack;
return 0;
}
seg->le = *ix;
seg->le = *ix;
seg->len = count;
seg->area_len = count;
@ -234,6 +256,7 @@ static int _alloc_linear_area(struct logical_volume *lv, uint32_t *ix,
static int _alloc_mirrored_area(struct logical_volume *lv, uint32_t *ix,
struct pv_map *map, struct pv_area *pva,
struct segment_type *segtype,
struct physical_volume *mirrored_pv,
uint32_t mirrored_pe)
{
@ -251,7 +274,8 @@ static int _alloc_mirrored_area(struct logical_volume *lv, uint32_t *ix,
}
seg->lv = lv;
seg->type = SEG_MIRRORED;
seg->segtype = segtype;
seg->le = *ix;
seg->status = 0u;
seg->le = *ix;
seg->len = count;
@ -321,6 +345,7 @@ static int _alloc_contiguous(struct logical_volume *lv,
/* FIXME Contiguous depends on *segment* (i.e. stripe) not LV */
static int _alloc_mirrored(struct logical_volume *lv,
struct list *pvms, uint32_t allocated,
struct segment_type *segtype,
struct physical_volume *mirrored_pv,
uint32_t mirrored_pe)
{
@ -343,7 +368,7 @@ static int _alloc_mirrored(struct logical_volume *lv,
continue;
}
if (!_alloc_mirrored_area(lv, &allocated, pvm, pva,
if (!_alloc_mirrored_area(lv, &allocated, pvm, pva, segtype,
mirrored_pv, mirrored_pe)) {
stack;
return 0;
@ -400,7 +425,8 @@ static int _alloc_next_free(struct logical_volume *lv,
*/
static int _allocate(struct volume_group *vg, struct logical_volume *lv,
struct list *allocatable_pvs, uint32_t allocated,
uint32_t stripes, uint32_t stripe_size,
struct segment_type *segtype,
uint32_t stripes, uint32_t stripe_size, uint32_t mirrors,
struct physical_volume *mirrored_pv, uint32_t mirrored_pe,
uint32_t status)
{
@ -420,11 +446,12 @@ static int _allocate(struct volume_group *vg, struct logical_volume *lv,
if (!(pvms = create_pv_maps(scratch, vg, allocatable_pvs)))
goto out;
if (stripes > 1)
r = _alloc_parallel(lv, pvms, allocated, stripes, stripe_size);
if (stripes > 1 || mirrors > 1)
r = _alloc_parallel(lv, pvms, allocated, stripes, stripe_size,
mirrors, segtype);
else if (mirrored_pv)
r = _alloc_mirrored(lv, pvms, allocated, mirrored_pv,
r = _alloc_mirrored(lv, pvms, allocated, segtype, mirrored_pv,
mirrored_pe);
else if (lv->alloc == ALLOC_CONTIGUOUS)
r = _alloc_contiguous(lv, pvms, allocated);
@ -554,12 +581,51 @@ struct logical_volume *lv_create_empty(struct format_instance *fi,
return lv;
}
struct logical_volume *lv_create(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)
{
uint32_t old_le_count = lv->le_count;
uint64_t old_size = lv->size;
lv->le_count += extents;
lv->size += (uint64_t) extents *lv->vg->extent_size;
if (!_allocate(lv->vg, lv, allocatable_pvs, old_le_count, segtype,
stripes, stripe_size, mirrors, mirrored_pv, mirrored_pe,
status)) {
lv->le_count = old_le_count;
lv->size = old_size;
stack;
return 0;
}
if ((segtype->flags & SEG_CAN_SPLIT) && !lv_merge_segments(lv)) {
log_err("Couldn't merge segments after extending "
"logical volume.");
return 0;
}
if (fid->fmt->ops->lv_setup && !fid->fmt->ops->lv_setup(fid, lv)) {
stack;
return 0;
}
return 1;
}
struct logical_volume *lv_create(struct format_instance *fid,
const char *name,
uint32_t status,
alloc_policy_t alloc,
struct segment_type *segtype,
uint32_t stripes,
uint32_t stripe_size,
uint32_t mirrors,
uint32_t extents,
struct volume_group *vg,
struct list *allocatable_pvs)
@ -585,21 +651,13 @@ struct logical_volume *lv_create(struct format_instance *fi,
return NULL;
}
if (!(lv = lv_create_empty(fi, name, "lvol%d", status, alloc, vg))) {
if (!(lv = lv_create_empty(fid, name, "lvol%d", status, alloc, vg))) {
stack;
return NULL;
}
lv->size = (uint64_t) extents *vg->extent_size;
lv->le_count = extents;
if (!_allocate(vg, lv, allocatable_pvs, 0u, stripes, stripe_size,
NULL, 0u, 0u)) {
stack;
return NULL;
}
if (fi->fmt->ops->lv_setup && !fi->fmt->ops->lv_setup(fi, lv)) {
if (!lv_extend(fid, lv, segtype, stripes, stripe_size, mirrors,
extents, NULL, 0u, 0u, allocatable_pvs)) {
stack;
return NULL;
}
@ -628,7 +686,7 @@ int lv_reduce(struct format_instance *fi,
/* reduce this segment */
_put_extents(seg);
seg->len -= count;
striped = (seg->type == SEG_STRIPED);
striped = seg->segtype->flags & SEG_AREAS_STRIPED;
/* Caller must ensure exact divisibility */
if (striped && (count % seg->area_count)) {
log_error("Segment extent reduction %" PRIu32
@ -655,68 +713,6 @@ int lv_reduce(struct format_instance *fi,
return 1;
}
int lv_extend(struct format_instance *fi,
struct logical_volume *lv,
uint32_t stripes, uint32_t stripe_size,
uint32_t extents, struct list *allocatable_pvs)
{
uint32_t old_le_count = lv->le_count;
uint64_t old_size = lv->size;
lv->le_count += extents;
lv->size += (uint64_t) extents *lv->vg->extent_size;
if (!_allocate(lv->vg, lv, allocatable_pvs, old_le_count,
stripes, stripe_size, NULL, 0u, 0u)) {
lv->le_count = old_le_count;
lv->size = old_size;
stack;
return 0;
}
if (!lv_merge_segments(lv)) {
log_err("Couldn't merge segments after extending "
"logical volume.");
return 0;
}
if (fi->fmt->ops->lv_setup && !fi->fmt->ops->lv_setup(fi, lv)) {
stack;
return 0;
}
return 1;
}
int lv_extend_mirror(struct format_instance *fid,
struct logical_volume *lv,
struct physical_volume *mirrored_pv,
uint32_t mirrored_pe,
uint32_t extents, struct list *allocatable_pvs,
uint32_t status)
{
uint32_t old_le_count = lv->le_count;
uint64_t old_size = lv->size;
lv->le_count += extents;
lv->size += (uint64_t) extents *lv->vg->extent_size;
if (!_allocate(lv->vg, lv, allocatable_pvs, old_le_count,
1, extents, mirrored_pv, mirrored_pe, status)) {
lv->le_count = old_le_count;
lv->size = old_size;
stack;
return 0;
}
if (fid->fmt->ops->lv_setup && !fid->fmt->ops->lv_setup(fid, lv)) {
stack;
return 0;
}
return 1;
}
int lv_remove(struct volume_group *vg, struct logical_volume *lv)
{
struct list *segh;

View File

@ -18,60 +18,20 @@
#include "toolcontext.h"
#include "lv_alloc.h"
#include "str_list.h"
/*
* Test whether two segments could be merged by the current merging code
*/
static int _segments_compatible(struct lv_segment *first,
struct lv_segment *second)
{
uint32_t width;
unsigned s;
/* FIXME Relax the seg type restriction */
if (!first || !second ||
(first->type != SEG_STRIPED) || (second->type != first->type) ||
(first->area_count != second->area_count) ||
(first->stripe_size != second->stripe_size))
return 0;
for (s = 0; s < first->area_count; s++) {
/* FIXME Relax this to first area type != second area type */
/* plus the additional AREA_LV checks needed */
if ((first->area[s].type != AREA_PV) ||
(second->area[s].type != AREA_PV))
return 0;
width = first->area_len;
if ((first->area[s].u.pv.pv != second->area[s].u.pv.pv) ||
(first->area[s].u.pv.pe + width != second->area[s].u.pv.pe))
return 0;
}
if (!str_list_lists_equal(&first->tags, &second->tags))
return 0;
return 1;
}
#include "segtypes.h"
/*
* Attempt to merge two adjacent segments.
* Currently only supports SEG_STRIPED on AREA_PV.
* Currently only supports striped segments on AREA_PV.
* Returns success if successful, in which case 'first'
* gets adjusted to contain both areas.
*/
static int _merge(struct lv_segment *first, struct lv_segment *second)
{
if (!first || !second || first->segtype != second->segtype ||
!first->segtype->ops->merge_segments) return 0;
if (!_segments_compatible(first, second))
return 0;
first->len += second->len;
first->area_len += second->area_len;
return 1;
return first->segtype->ops->merge_segments(first, second);
}
int lv_merge_segments(struct logical_volume *lv)
@ -126,15 +86,14 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
uint32_t s;
uint32_t offset = le - seg->le;
if (seg->type == SEG_SNAPSHOT) {
log_error("Unable to split the snapshot segment at LE %" PRIu32
" in LV %s", le, lv->name);
if (!(seg->segtype->flags & SEG_CAN_SPLIT)) {
log_error("Unable to split the %s segment at LE %" PRIu32
" in LV %s", seg->segtype->name, le, lv->name);
return 0;
}
/* Clone the existing segment */
if (!(split_seg = alloc_lv_segment(lv->vg->cmd->mem,
seg->area_count))) {
if (!(split_seg = alloc_lv_segment(lv->vg->cmd->mem, seg->area_count))) {
log_error("Couldn't allocate new LV segment.");
return 0;
}
@ -148,7 +107,7 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
}
/* In case of a striped segment, the offset has to be / stripes */
if (seg->type == SEG_STRIPED)
if (seg->segtype->flags & SEG_AREAS_STRIPED)
offset /= seg->area_count;
/* Adjust the PV mapping */
@ -205,4 +164,3 @@ int lv_split_segment(struct logical_volume *lv, uint32_t le)
return 1;
}

View File

@ -53,6 +53,7 @@
#define SNAPSHOT 0x00001000 /* LV - tmp internal use only */
#define PVMOVE 0x00002000 /* VG LV SEG */
#define LOCKED 0x00004000 /* LV */
#define MIRRORED 0x00008000 /* LV - internal use only */
#define LVM_READ 0x00000100 /* LV VG */
#define LVM_WRITE 0x00000200 /* LV VG */
@ -66,19 +67,13 @@
#define FMT_UNLIMITED_VOLS 0x00000008 /* Unlimited PVs/LVs? */
#define FMT_RESTRICTED_LVIDS 0x00000010 /* LVID <= 255 */
#define FMT_ORPHAN_ALLOCATABLE 0x00000020 /* Orphan PV allocatable? */
typedef enum {
ALLOC_DEFAULT,
ALLOC_NEXT_FREE,
ALLOC_CONTIGUOUS
} alloc_policy_t;
typedef enum {
SEG_STRIPED,
SEG_SNAPSHOT,
SEG_MIRRORED
} segment_type_t;
typedef enum {
AREA_PV,
AREA_LV
@ -194,11 +189,12 @@ struct volume_group {
struct list tags;
};
struct segment_type;
struct lv_segment {
struct list list;
struct logical_volume *lv;
segment_type_t type;
struct segment_type *segtype;
uint32_t le;
uint32_t len;
@ -407,8 +403,10 @@ struct logical_volume *lv_create(struct format_instance *fi,
const char *name,
uint32_t status,
alloc_policy_t alloc,
struct segment_type *segtype,
uint32_t stripes,
uint32_t stripe_size,
uint32_t mirrors,
uint32_t extents,
struct volume_group *vg,
struct list *allocatable_pvs);
@ -424,18 +422,13 @@ struct logical_volume *lv_create_empty(struct format_instance *fi,
int lv_reduce(struct format_instance *fi,
struct logical_volume *lv, uint32_t extents);
int lv_extend(struct format_instance *fi,
int lv_extend(struct format_instance *fid,
struct logical_volume *lv,
uint32_t stripes,
uint32_t stripe_size,
uint32_t extents, struct list *allocatable_pvs);
int lv_extend_mirror(struct format_instance *fid,
struct logical_volume *lv,
struct physical_volume *mirrored_pv,
uint32_t mirrored_pe,
uint32_t extents, struct list *allocatable_pvs,
uint32_t status);
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);
/* lv must be part of vg->lvs */
int lv_remove(struct volume_group *vg, struct logical_volume *lv);

View File

@ -16,6 +16,8 @@
#include "lib.h"
#include "metadata.h"
#include "toolcontext.h"
#include "segtypes.h"
#include "display.h"
/*
* Replace any LV segments on given PV with temporary mirror.
@ -33,6 +35,12 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
struct lv_list *lvl;
int lv_used = 0;
uint32_t s, start_le, extent_count = 0u;
struct segment_type *segtype;
if (!(segtype = get_segtype_from_string(lv->vg->cmd, "mirror"))) {
stack;
return 0;
}
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
@ -52,11 +60,11 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
}
start_le = lv_mirr->le_count;
if (!lv_extend_mirror(lv->vg->fid, lv_mirr,
seg->area[s].u.pv.pv,
seg->area[s].u.pv.pe,
seg->area_len, allocatable_pvs,
PVMOVE)) {
if (!lv_extend(lv->vg->fid, lv_mirr, segtype, 1,
seg->area_len, 0u, seg->area_len,
seg->area[s].u.pv.pv,
seg->area[s].u.pv.pe,
PVMOVE, allocatable_pvs)) {
log_error("Allocation for temporary "
"pvmove LV failed");
return 0;
@ -98,13 +106,14 @@ int remove_pvmove_mirrors(struct volume_group *vg,
continue;
if (!(mir_seg = find_seg_by_le(lv_mirr,
seg->area[s].u.
lv.le))) {
seg->area[s].
u.lv.le))) {
log_error("No segment found with LE");
return 0;
}
if (mir_seg->type != SEG_MIRRORED ||
if ((!(mir_seg->segtype->flags
& SEG_AREAS_MIRRORED)) ||
!(mir_seg->status & PVMOVE) ||
mir_seg->le != seg->area[s].u.lv.le ||
mir_seg->area_count != 2 ||
@ -122,7 +131,13 @@ int remove_pvmove_mirrors(struct volume_group *vg,
seg->area[s].u.pv.pv = mir_seg->area[c].u.pv.pv;
seg->area[s].u.pv.pe = mir_seg->area[c].u.pv.pe;
mir_seg->type = SEG_STRIPED;
if (!
(mir_seg->segtype =
get_segtype_from_string(vg->cmd,
"striped"))) {
log_error("Missing striped segtype");
return 0;
}
mir_seg->area_count = 1;
lv1->status &= ~LOCKED;
@ -141,7 +156,7 @@ struct physical_volume *get_pvmove_pv_from_lv_mirr(struct logical_volume
list_iterate(segh, &lv_mirr->segments) {
seg = list_item(segh, struct lv_segment);
if (seg->type != SEG_MIRRORED)
if (!(seg->segtype->flags & SEG_AREAS_MIRRORED))
continue;
if (seg->area[0].type != AREA_PV)
continue;

32
lib/metadata/segtypes.c Normal file
View File

@ -0,0 +1,32 @@
/*
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
* 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 "toolcontext.h"
#include "segtypes.h"
struct segment_type *get_segtype_from_string(struct cmd_context *cmd,
const char *str)
{
struct segment_type *segtype;
list_iterate_items(segtype, &cmd->segtypes) {
if (!strcmp(segtype->name, str))
return segtype;
}
log_error("Unrecognised segment type %s", str);
return NULL;
}

84
lib/metadata/segtypes.h Normal file
View File

@ -0,0 +1,84 @@
/*
* 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.
*
* 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
*/
#ifndef _SEGTYPES_H
#define _SEGTYPES_H
struct segtype_handler;
struct cmd_context;
struct config_tree;
struct lv_segment;
struct formatter;
struct config_node;
struct hash_table;
struct dev_manager;
/* Feature flags */
#define SEG_CAN_SPLIT 0x00000001
#define SEG_AREAS_STRIPED 0x00000002
#define SEG_AREAS_MIRRORED 0x00000004
#define SEG_FORMAT1_SUPPORT 0x00000008
struct segment_type {
struct list list;
struct cmd_context *cmd;
uint32_t flags;
struct segtype_handler *ops;
const char *name;
void *library;
void *private;
};
struct segtype_handler {
const char *(*name) (const struct lv_segment * seg);
void (*display) (const struct lv_segment * seg);
int (*text_export) (const struct lv_segment * seg,
struct formatter * f);
int (*text_import_area_count) (struct config_node * sn,
uint32_t *area_count);
int (*text_import) (struct lv_segment * seg,
const struct config_node * sn,
struct hash_table * pv_hash);
int (*merge_segments) (struct lv_segment * seg1,
struct lv_segment * seg2);
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);
int (*target_percent) (void **target_state, struct pool * mem,
struct config_tree * cft,
struct lv_segment * seg, char *params,
uint64_t *total_numerator,
uint64_t *total_denominator, float *percent);
int (*target_present) (void);
void (*destroy) (const struct segment_type * segtype);
};
struct segment_type *get_segtype_from_string(struct cmd_context *cmd,
const char *str);
struct segment_type *init_striped_segtype(struct cmd_context *cmd);
#ifdef SNAPSHOT_INTERNAL
struct segment_type *init_snapshot_segtype(struct cmd_context *cmd);
#endif
#ifdef MIRRORED_INTERNAL
struct segment_type *init_mirrored_segtype(struct cmd_context *cmd);
#endif
#endif

View File

@ -0,0 +1 @@
init_segtype

31
lib/mirror/Makefile.in Normal file
View File

@ -0,0 +1,31 @@
#
# Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
#
# This file is part of the 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
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
SOURCES = mirrored.c
LIB_SHARED = liblvm2mirror.so
include ../../make.tmpl
.PHONY: install
install: liblvm2mirror.so
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
$(libdir)/liblvm2mirror.so.$(LIB_VERSION)
$(LN_S) -f liblvm2mirror.so.$(LIB_VERSION) $(libdir)/liblvm2mirror.so

236
lib/mirror/mirrored.c Normal file
View File

@ -0,0 +1,236 @@
/*
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
* 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 "metadata.h"
#include "segtypes.h"
#include "display.h"
#include "text_export.h"
#include "text_import.h"
#include "config.h"
#include "defaults.h"
#include "lvm-string.h"
#include "targets.h"
enum {
MIRR_DISABLED,
MIRR_RUNNING,
MIRR_COMPLETED
};
struct mirror_state {
uint32_t region_size;
};
static const char *_name(const struct lv_segment *seg)
{
return seg->segtype->name;
}
static void _display(const struct lv_segment *seg)
{
log_print(" Mirrors\t\t%u", seg->area_count);
log_print(" Mirror size\t\t%u", seg->area_len);
log_print(" Mirror original:");
display_stripe(seg, 0, " ");
log_print(" Mirror destination:");
display_stripe(seg, 1, " ");
log_print(" ");
}
static int _text_import_area_count(struct config_node *sn, uint32_t *area_count)
{
if (!get_config_uint32(sn, "mirror_count", area_count)) {
log_error("Couldn't read 'mirror_count' for "
"segment '%s'.", sn->key);
return 0;
}
return 1;
}
static int _text_import(struct lv_segment *seg, const struct config_node *sn,
struct hash_table *pv_hash)
{
const struct config_node *cn;
if (find_config_node(sn, "extents_moved")) {
if (get_config_uint32(sn, "extents_moved", &seg->extents_moved))
seg->status |= PVMOVE;
else {
log_error("Couldn't read 'extents_moved' for "
"segment '%s'.", sn->key);
return 0;
}
}
if (!(cn = find_config_node(sn, "mirrors"))) {
log_error("Couldn't find mirrors array for segment "
"'%s'.", sn->key);
return 0;
}
return text_import_areas(seg, sn, cn, pv_hash);
}
static int _text_export(const struct lv_segment *seg, struct formatter *f)
{
outf(f, "mirror_count = %u", seg->area_count);
if (seg->status & PVMOVE)
out_size(f, (uint64_t) seg->extents_moved,
"extents_moved = %u", seg->extents_moved);
return out_areas(f, seg, "mirror");
}
#ifdef DEVMAPPER_SUPPORT
static struct mirror_state *_init_target(struct pool *mem,
struct config_tree *cft)
{
struct mirror_state *mirr_state;
if (!(mirr_state = pool_alloc(mem, sizeof(*mirr_state)))) {
log_error("struct mirr_state allocation failed");
return NULL;
}
mirr_state->region_size = 2 *
find_config_int(cft->root,
"activation/mirror_region_size",
DEFAULT_MIRROR_REGION_SIZE);
return mirr_state;
}
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)
{
struct mirror_state *mirr_state;
int mirror_status = MIRR_RUNNING;
int areas = seg->area_count;
int start_area = 0u;
if (!*target_state)
*target_state = _init_target(mem, cft);
mirr_state = *target_state;
/* mirror log_type #log_params [log_params]*
* #mirrors [device offset]+
*/
if (seg->status & PVMOVE) {
if (seg->extents_moved == seg->area_len) {
mirror_status = MIRR_COMPLETED;
start_area = 1;
} else if (*pvmove_mirror_count++) {
mirror_status = MIRR_DISABLED;
areas = 1;
}
}
if (mirror_status != MIRR_RUNNING) {
*target = "linear";
} else {
*target = "mirror";
if ((*pos = lvm_snprintf(params, paramsize, "core 1 %u %u ",
mirr_state->region_size, areas)) < 0) {
stack;
return -1;
}
}
return compose_areas_line(dm, seg, params, paramsize, pos, start_area,
areas);
}
static int _target_percent(void **target_state, struct pool *mem,
struct config_tree *cft, struct lv_segment *seg,
char *params, uint64_t *total_numerator,
uint64_t *total_denominator, float *percent)
{
struct mirror_state *mirr_state;
uint64_t numerator, denominator;
if (!*target_state)
*target_state = _init_target(mem, cft);
mirr_state = *target_state;
log_debug("Mirror status: %s", params);
if (sscanf(params, "%*d %*x:%*x %*x:%*x %" PRIu64
"/%" PRIu64, &numerator, &denominator) != 2) {
log_error("Failure parsing mirror status: %s", params);
return 0;
}
*total_numerator += numerator;
*total_denominator += denominator;
if (seg && (seg->status & PVMOVE))
seg->extents_moved = mirr_state->region_size *
numerator / seg->lv->vg->extent_size;
return 1;
}
#endif
static void _destroy(const struct segment_type *segtype)
{
dbg_free((void *) segtype);
}
static struct segtype_handler _mirrored_ops = {
name:_name,
display:_display,
text_import_area_count:_text_import_area_count,
text_import:_text_import,
text_export:_text_export,
#ifdef DEVMAPPER_SUPPORT
compose_target_line:_compose_target_line,
target_percent:_target_percent,
#endif
destroy:_destroy,
};
#ifdef MIRRORED_INTERNAL
struct segment_type *init_mirrored_segtype(struct cmd_context *cmd)
#else /* Shared */
struct segment_type *init_segtype(struct cmd_context *cmd);
struct segment_type *init_segtype(struct cmd_context *cmd)
#endif
{
struct segment_type *segtype = dbg_malloc(sizeof(*segtype));
if (!segtype) {
stack;
return NULL;
}
segtype->cmd = cmd;
segtype->ops = &_mirrored_ops;
segtype->name = "mirror";
segtype->private = NULL;
segtype->flags = SEG_CAN_SPLIT | SEG_AREAS_MIRRORED;
return segtype;
}

View File

@ -21,6 +21,7 @@
#include "lvm-string.h"
#include "display.h"
#include "activate.h"
#include "segtypes.h"
/*
* For macro use
@ -329,7 +330,7 @@ static int _segtype_disp(struct report_handle *rh, struct field *field,
if (seg->area_count == 1)
field->report_string = "linear";
else
field->report_string = get_segtype_string(seg->type);
field->report_string = seg->segtype->ops->name(seg);
field->sort_value = (const void *) field->report_string;
return 1;

View File

@ -0,0 +1 @@
init_segtype

32
lib/snapshot/Makefile.in Normal file
View File

@ -0,0 +1,32 @@
#
# Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
#
# This file is part of the 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
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
SOURCES = snapshot.c
LIB_SHARED = liblvm2snapshot.so
include ../../make.tmpl
.PHONY: install
install: liblvm2snapshot.so
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
$(libdir)/liblvm2snapshot.so.$(LIB_VERSION)
$(LN_S) -f liblvm2snapshot.so.$(LIB_VERSION) \
$(libdir)/liblvm2snapshot.so

145
lib/snapshot/snapshot.c Normal file
View File

@ -0,0 +1,145 @@
/*
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
* 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 "metadata.h"
#include "segtypes.h"
#include "text_export.h"
#include "config.h"
static const char *_name(const struct lv_segment *seg)
{
return seg->segtype->name;
}
static int _text_import(struct lv_segment *seg, const struct config_node *sn,
struct hash_table *pv_hash)
{
uint32_t chunk_size;
const char *org_name, *cow_name;
struct logical_volume *org, *cow;
seg->lv->status |= SNAPSHOT;
if (!get_config_uint32(sn, "chunk_size", &chunk_size)) {
log_error("Couldn't read chunk size for snapshot.");
return 0;
}
log_suppress(1);
if (!(cow_name = find_config_str(sn, "cow_store", NULL))) {
log_suppress(0);
log_error("Snapshot cow storage not specified.");
return 0;
}
if (!(org_name = find_config_str(sn, "origin", NULL))) {
log_suppress(0);
log_error("Snapshot origin not specified.");
return 0;
}
log_suppress(0);
if (!(cow = find_lv(seg->lv->vg, cow_name))) {
log_error("Unknown logical volume specified for "
"snapshot cow store.");
return 0;
}
if (!(org = find_lv(seg->lv->vg, org_name))) {
log_error("Unknown logical volume specified for "
"snapshot origin.");
return 0;
}
if (!vg_add_snapshot(org, cow, 1, &seg->lv->lvid.id[1], chunk_size)) {
stack;
return 0;
}
return 1;
}
static int _text_export(const struct lv_segment *seg, struct formatter *f)
{
outf(f, "chunk_size = %u", seg->chunk_size);
outf(f, "origin = \"%s\"", seg->origin->name);
outf(f, "cow_store = \"%s\"", seg->cow->name);
return 1;
}
static int _target_percent(void **target_state, struct pool *mem,
struct config_tree *cft, struct lv_segment *seg,
char *params, uint64_t *total_numerator,
uint64_t *total_denominator, float *percent)
{
float percent2;
uint64_t numerator, denominator;
if (index(params, '/')) {
if (sscanf(params, "%" PRIu64 "/%" PRIu64,
&numerator, &denominator) == 2) {
*total_numerator += numerator;
*total_denominator += denominator;
}
} else if (sscanf(params, "%f", &percent2) == 1) {
*percent += percent2;
*percent /= 2;
}
return 1;
}
static void _destroy(const struct segment_type *segtype)
{
dbg_free((void *) segtype);
}
static struct segtype_handler _snapshot_ops = {
name:_name,
text_import:_text_import,
text_export:_text_export,
target_percent:_target_percent,
destroy:_destroy,
};
#ifdef SNAPSHOT_INTERNAL
struct segment_type *init_snapshot_segtype(struct cmd_context *cmd)
#else /* Shared */
struct segment_type *init_segtype(struct cmd_context *cmd);
struct segment_type *init_segtype(struct cmd_context *cmd)
#endif
{
struct segment_type *segtype = dbg_malloc(sizeof(*segtype));
if (!segtype) {
stack;
return NULL;
}
segtype->cmd = cmd;
segtype->ops = &_snapshot_ops;
segtype->name = "snapshot";
segtype->private = NULL;
segtype->flags = 0u;
return segtype;
}

207
lib/striped/striped.c Normal file
View File

@ -0,0 +1,207 @@
/*
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
* 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"
static const char *_name(const struct lv_segment *seg)
{
return (seg->area_count == 1) ? "linear" : seg->segtype->name;
}
static void _display(const struct lv_segment *seg)
{
uint32_t s;
if (seg->area_count == 1)
display_stripe(seg, 0, " ");
else {
log_print(" Stripes\t\t%u", seg->area_count);
log_print(" Stripe size\t\t%u KB", seg->stripe_size / 2);
for (s = 0; s < seg->area_count; s++) {
log_print(" Stripe %d:", s);
display_stripe(seg, s, " ");
}
}
log_print(" ");
}
static int _text_import_area_count(struct config_node *sn, uint32_t *area_count)
{
if (!get_config_uint32(sn, "stripe_count", area_count)) {
log_error("Couldn't read 'stripe_count' for "
"segment '%s'.", sn->key);
return 0;
}
return 1;
}
static int _text_import(struct lv_segment *seg, const struct config_node *sn,
struct hash_table *pv_hash)
{
struct config_node *cn;
if ((seg->area_count != 1) &&
!get_config_uint32(sn, "stripe_size", &seg->stripe_size)) {
log_error("Couldn't read stripe_size for segment '%s'.",
sn->key);
return 0;
}
if (!(cn = find_config_node(sn, "stripes"))) {
log_error("Couldn't find stripes array for segment "
"'%s'.", sn->key);
return 0;
}
seg->area_len /= seg->area_count;
return text_import_areas(seg, sn, cn, pv_hash);
}
static int _text_export(const struct lv_segment *seg, struct formatter *f)
{
outf(f, "stripe_count = %u%s", seg->area_count,
(seg->area_count == 1) ? "\t# linear" : "");
if (seg->area_count > 1)
out_size(f, (uint64_t) seg->stripe_size,
"stripe_size = %u", seg->stripe_size);
return out_areas(f, seg, "stripe");
}
/*
* Test whether two segments could be merged by the current merging code
*/
static int _segments_compatible(struct lv_segment *first,
struct lv_segment *second)
{
uint32_t width;
unsigned s;
if ((first->area_count != second->area_count) ||
(first->stripe_size != second->stripe_size)) return 0;
for (s = 0; s < first->area_count; s++) {
/* FIXME Relax this to first area type != second area type */
/* plus the additional AREA_LV checks needed */
if ((first->area[s].type != AREA_PV) ||
(second->area[s].type != AREA_PV)) return 0;
width = first->area_len;
if ((first->area[s].u.pv.pv != second->area[s].u.pv.pv) ||
(first->area[s].u.pv.pe + width != second->area[s].u.pv.pe))
return 0;
}
if (!str_list_lists_equal(&first->tags, &second->tags))
return 0;
return 1;
}
static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
{
if (!_segments_compatible(seg1, seg2))
return 0;
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)
{
/* linear [device offset]+
* striped #stripes stripe_size [device offset]+ */
if (seg->area_count == 1)
*target = "linear";
else if (seg->area_count > 1) {
*target = "striped";
if ((*pos = lvm_snprintf(params, paramsize, "%u %u ",
seg->area_count,
seg->stripe_size)) < 0) {
stack;
return -1;
}
} else {
log_error("Internal error: striped target with no stripes");
return 0;
}
return compose_areas_line(dm, seg, params, paramsize, pos, 0u,
seg->area_count);
}
#endif
static void _destroy(const struct segment_type *segtype)
{
dbg_free((void *) segtype);
}
static struct segtype_handler _striped_ops = {
name:_name,
display:_display,
text_import_area_count:_text_import_area_count,
text_import:_text_import,
text_export:_text_export,
merge_segments:_merge_segments,
#ifdef DEVMAPPER_SUPPORT
compose_target_line:_compose_target_line,
#endif
destroy:_destroy,
};
struct segment_type *init_striped_segtype(struct cmd_context *cmd)
{
struct segment_type *segtype = dbg_malloc(sizeof(*segtype));
if (!segtype) {
stack;
return NULL;
}
segtype->cmd = cmd;
segtype->ops = &_striped_ops;
segtype->name = "striped";
segtype->private = NULL;
segtype->flags =
SEG_CAN_SPLIT | SEG_AREAS_STRIPED | SEG_FORMAT1_SUPPORT;
return segtype;
}

View File

@ -33,6 +33,10 @@ struct lvcreate_params {
uint32_t stripe_size;
uint32_t chunk_size;
uint32_t mirrors;
struct segment_type *segtype;
/* size */
uint32_t extents;
uint64_t size;
@ -188,6 +192,11 @@ static int _read_stripe_params(struct lvcreate_params *lp,
lp->stripes = arg_uint_value(cmd, stripes_ARG, 1);
if (lp->stripes == 1)
log_print("Redundant stripes argument: default is 1");
else if (!(lp->segtype = get_segtype_from_string(cmd,
"striped"))) {
stack;
return 0;
}
}
if (arg_count(cmd, stripesize_ARG)) {
@ -466,8 +475,9 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
status |= LVM_WRITE;
}
if (!(lv = lv_create(vg->fid, lp->lv_name, status, alloc, lp->stripes,
lp->stripe_size, lp->extents, vg, pvh)))
if (!(lv = lv_create(vg->fid, lp->lv_name, status, alloc, lp->segtype,
lp->stripes, lp->stripe_size, lp->mirrors,
lp->extents, vg, pvh)))
return 0;
if (lp->read_ahead) {

View File

@ -1,6 +1,7 @@
/*
* 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.
*
* This copyrighted material is made available to anyone wishing to use,

View File

@ -39,6 +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;
enum {
LV_ANY = 0,
@ -196,8 +197,8 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
/* 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 (seg->type != SEG_STRIPED)
continue;
if (strcmp(seg->segtype->ops->name(seg), "striped"))
continue; /* Not striped */
sz = seg->stripe_size;
str = seg->area_count;
@ -243,7 +244,7 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
list_iterate_items(seg, &lv->segments) {
seg_extents = seg->len;
if (seg->type == SEG_STRIPED) {
if (seg->segtype->flags & SEG_AREAS_STRIPED) {
seg_stripesize = seg->stripe_size;
seg_stripes = seg->area_count;
}
@ -354,9 +355,14 @@ 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, stripes, ssize,
extents - lv->le_count, pvh))
if (!lv_extend(vg->fid, lv, segtype, stripes, ssize, 0u,
extents - lv->le_count, NULL, 0u, 0u, pvh))
goto error;
}

View File

@ -43,6 +43,7 @@
#include "lvm-file.h"
#include "lvm-string.h"
#include "pool.h"
#include "segtypes.h"
#include "str_list.h"
#include "toolcontext.h"
#include "toollib.h"

View File

@ -51,8 +51,7 @@ static int _activate_lvs_in_vg(struct cmd_context *cmd,
return count;
}
static int _vgchange_available(struct cmd_context *cmd,
struct volume_group *vg)
static int _vgchange_available(struct cmd_context *cmd, struct volume_group *vg)
{
int lv_open, active;
int available = !strcmp(arg_str_value(cmd, available_ARG, "n"), "y");