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:
parent
6ec6994107
commit
4922197a33
@ -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
|
||||
|
@ -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
62
configure
vendored
@ -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
|
||||
|
44
configure.in
44
configure.in
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
25
lib/activate/targets.h
Normal 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
|
5
lib/cache/lvmcache.h
vendored
5
lib/cache/lvmcache.h
vendored
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -380,4 +380,3 @@ int backup_list(struct cmd_context *cmd, const char *dir, const char *vgname)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
36
lib/format_text/text_export.h
Normal file
36
lib/format_text/text_export.h
Normal 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
|
25
lib/format_text/text_import.h
Normal file
25
lib/format_text/text_import.h
Normal 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
|
@ -18,6 +18,7 @@
|
||||
#include "layout.h"
|
||||
#include "label.h"
|
||||
#include "xlate.h"
|
||||
#include "lvmcache.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -13,7 +13,6 @@
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "metadata.h"
|
||||
#include "uuid.h"
|
||||
#include "config.h"
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
32
lib/metadata/segtypes.c
Normal 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
84
lib/metadata/segtypes.h
Normal 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
|
1
lib/mirror/.exported_symbols
Normal file
1
lib/mirror/.exported_symbols
Normal file
@ -0,0 +1 @@
|
||||
init_segtype
|
31
lib/mirror/Makefile.in
Normal file
31
lib/mirror/Makefile.in
Normal 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
236
lib/mirror/mirrored.c
Normal 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;
|
||||
}
|
@ -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;
|
||||
|
1
lib/snapshot/.exported_symbols
Normal file
1
lib/snapshot/.exported_symbols
Normal file
@ -0,0 +1 @@
|
||||
init_segtype
|
32
lib/snapshot/Makefile.in
Normal file
32
lib/snapshot/Makefile.in
Normal 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
145
lib/snapshot/snapshot.c
Normal 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
207
lib/striped/striped.c
Normal 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;
|
||||
}
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user