summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlasdair Kergon <agk@redhat.com>2004-05-04 21:25:57 +0000
committerAlasdair Kergon <agk@redhat.com>2004-05-04 21:25:57 +0000
commit4922197a3394d5482387efdf34aa89843da516c4 (patch)
tree291208c3ad46d660f99555db537336c0a5c1b961
parent6ec69941076b37d6528984ee2f42628cfa7b42ef (diff)
downloadlvm2-4922197a3394d5482387efdf34aa89843da516c4.tar.gz
lvm2-4922197a3394d5482387efdf34aa89843da516c4.tar.xz
lvm2-4922197a3394d5482387efdf34aa89843da516c4.zip
Begin to separate out segment types.
-rw-r--r--Makefile.in2
-rw-r--r--WHATS_NEW2
-rwxr-xr-xconfigure62
-rw-r--r--configure.in44
-rw-r--r--include/.symlinks4
-rw-r--r--lib/Makefile.in18
-rw-r--r--lib/activate/activate.c13
-rw-r--r--lib/activate/dev_manager.c236
-rw-r--r--lib/activate/dev_manager.h9
-rw-r--r--lib/activate/targets.h25
-rw-r--r--lib/cache/lvmcache.h5
-rw-r--r--lib/commands/toolcontext.c110
-rw-r--r--lib/commands/toolcontext.h1
-rw-r--r--lib/display/display.c100
-rw-r--r--lib/display/display.h7
-rw-r--r--lib/format1/disk-rep.c8
-rw-r--r--lib/format1/disk-rep.h2
-rw-r--r--lib/format1/format1.c2
-rw-r--r--lib/format1/import-export.c8
-rw-r--r--lib/format1/import-extents.c39
-rw-r--r--lib/format_text/archive.c1
-rw-r--r--lib/format_text/export.c228
-rw-r--r--lib/format_text/flags.c4
-rw-r--r--lib/format_text/format-text.c26
-rw-r--r--lib/format_text/import_vsn1.c232
-rw-r--r--lib/format_text/text_export.h36
-rw-r--r--lib/format_text/text_import.h25
-rw-r--r--lib/format_text/text_label.c1
-rw-r--r--lib/label/label.c3
-rw-r--r--lib/label/label.h3
-rw-r--r--lib/locking/locking.h1
-rw-r--r--lib/metadata/lv_manip.c172
-rw-r--r--lib/metadata/merge.c62
-rw-r--r--lib/metadata/metadata.h31
-rw-r--r--lib/metadata/mirror.c35
-rw-r--r--lib/metadata/segtypes.c32
-rw-r--r--lib/metadata/segtypes.h84
-rw-r--r--lib/mirror/.exported_symbols1
-rw-r--r--lib/mirror/Makefile.in31
-rw-r--r--lib/mirror/mirrored.c236
-rw-r--r--lib/report/report.c3
-rw-r--r--lib/snapshot/.exported_symbols1
-rw-r--r--lib/snapshot/Makefile.in32
-rw-r--r--lib/snapshot/snapshot.c145
-rw-r--r--lib/striped/striped.c207
-rw-r--r--tools/lvcreate.c14
-rw-r--r--tools/lvmcmdline.c1
-rw-r--r--tools/lvresize.c16
-rw-r--r--tools/tools.h1
-rw-r--r--tools/vgchange.c3
50 files changed, 1622 insertions, 742 deletions
diff --git a/Makefile.in b/Makefile.in
index 4d9597b3..489ba3bb 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -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
diff --git a/WHATS_NEW b/WHATS_NEW
index 7c864f00..dfc20b63 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -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.
diff --git a/configure b/configure
index 2e931b2f..79859784 100755
--- a/configure
+++ b/configure
@@ -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
diff --git a/configure.in b/configure.in
index c35f81a7..e0a16369 100644
--- a/configure.in
+++ b/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 \
diff --git a/include/.symlinks b/include/.symlinks
index 955007c2..7c350da6 100644
--- a/include/.symlinks
+++ b/include/.symlinks
@@ -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
diff --git a/lib/Makefile.in b/lib/Makefile.in
index fa640597..7d321cc3 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -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
diff --git a/lib/activate/activate.c b/lib/activate/activate.c
index ae9fa87a..e5533680 100644
--- a/lib/activate/activate.c
+++ b/lib/activate/activate.c
@@ -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;
}
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index 7cff1407..2e61bed1 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -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 (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;
+ 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;
}
+
} 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,73 +734,61 @@ 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;
+ }
+
+ 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",
+ esize * seg->le, esize * seg->len, target, params);
+
+ if (!dm_task_add_target(dmt, esize * seg->le, esize * seg->len,
+ target, params)) {
+ stack;
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) {
+ 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 + w, paramsize - w,
+ 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 + w, paramsize - w,
+ 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 +
@@ -838,36 +801,27 @@ static int _emit_target_line(struct dev_manager *dm, struct dm_task *dmt,
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);
+ 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,
+ tw = lvm_snprintf(params + *pos, paramsize - *pos,
"%s %" PRIu64 "%s", devbuf,
esize * seg->area[s].u.lv.le,
trailing_space);
}
- if (tw < 0)
- goto error;
- }
-
- log_debug("Adding target: %" PRIu64 " %" PRIu64 " %s %s",
- esize * seg->le, esize * seg->len, target, params);
-
- if (!dm_task_add_target(dmt, esize * seg->le, esize * seg->len,
- target, params)) {
- stack;
- return 0;
+ if (tw < 0) {
+ stack;
+ return -1;
+ }
}
return 1;
-
- error:
- log_debug("Insufficient space in params[%" PRIsize_t "] for target "
- "parameters.", paramsize);
- 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;
}
diff --git a/lib/activate/dev_manager.h b/lib/activate/dev_manager.h
index 1482d334..2290679c 100644
--- a/lib/activate/dev_manager.h
+++ b/lib/activate/dev_manager.h
@@ -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);
diff --git a/lib/activate/targets.h b/lib/activate/targets.h
new file mode 100644
index 00000000..06f91523
--- /dev/null
+++ b/lib/activate/targets.h
@@ -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
diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h
index cbfb3167..a461cd32 100644
--- a/lib/cache/lvmcache.h
+++ b/lib/cache/lvmcache.h
@@ -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 */
diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index 883230b1..7955dcaa 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -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);
diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
index 839716d6..34606f1f 100644
--- a/lib/commands/toolcontext.h
+++ b/lib/commands/toolcontext.h
@@ -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;
diff --git a/lib/display/display.c b/lib/display/display.c
index 75315b57..4a1aa921 100644
--- a/lib/display/display.c
+++ b/lib/display/display.c
@@ -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));
-
- 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;
- }
+ log_print(" Type\t\t%s", seg->segtype->ops->name(seg));
+
+ 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;
diff --git a/lib/display/display.h b/lib/display/display.h
index 1292fd75..0fc3486f 100644
--- a/lib/display/display.h
+++ b/lib/display/display.h
@@ -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
diff --git a/lib/format1/disk-rep.c b/lib/format1/disk-rep.c
index aa0d964c..bb96e891 100644
--- a/lib/format1/disk-rep.c
+++ b/lib/format1/disk-rep.c
@@ -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);
diff --git a/lib/format1/disk-rep.h b/lib/format1/disk-rep.h
index b6b03229..9f8167f0 100644
--- a/lib/format1/disk-rep.h
+++ b/lib/format1/disk-rep.h
@@ -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);
diff --git a/lib/format1/format1.c b/lib/format1/format1.c
index 20c965c5..39e28dc3 100644
--- a/lib/format1/format1.c
+++ b/lib/format1/format1.c
@@ -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))
diff --git a/lib/format1/import-export.c b/lib/format1/import-export.c
index 33305fc4..297056a5 100644
--- a/lib/format1/import-export.c
+++ b/lib/format1/import-export.c
@@ -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) {
diff --git a/lib/format1/import-extents.c b/lib/format1/import-extents.c
index 82828a1b..851e7c25 100644
--- a/lib/format1/import-extents.c
+++ b/lib/format1/import-extents.c
@@ -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;
}
diff --git a/lib/format_text/archive.c b/lib/format_text/archive.c
index cdbafb70..724ffff6 100644
--- a/lib/format_text/archive.c
+++ b/lib/format_text/archive.c
@@ -380,4 +380,3 @@ int backup_list(struct cmd_context *cmd, const char *dir, const char *vgname)
return 1;
}
-
diff --git a/lib/format_text/export.c b/lib/format_text/export.c
index 69b960e8..7ae3072c 100644
--- a/lib/format_text/export.c
+++ b/lib/format_text/export.c
@@ -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,116 +359,102 @@ 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;
+ if (!seg->segtype->ops->text_export(seg, f)) {
+ stack;
+ return 0;
+ }
- 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" : "");
+ _dec_indent(f);
+ outf(f, "}");
- if ((seg->type == SEG_MIRRORED) && (seg->status & PVMOVE))
- _out_size(f, (uint64_t) seg->extents_moved,
- "extents_moved = %u", seg->extents_moved);
+ return 1;
+}
- if ((seg->type == SEG_STRIPED) && (seg->area_count > 1))
- _out_size(f, (uint64_t) seg->stripe_size,
- "stripe_size = %u", seg->stripe_size);
+int out_areas(struct formatter *f, const struct lv_segment *seg,
+ const char *type)
+{
+ const char *name;
+ unsigned int s;
- f->nl(f);
+ f->nl(f);
- _outf(f, "%ss = [", type);
- _inc_indent(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) ? "" : ",");
+ 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;
}
- }
- _dec_indent(f);
- _outf(f, "]");
- break;
+ 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, "}");
-
+ outf(f, "]");
return 1;
}
@@ -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
diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c
index f9d16acf..1a9bbb39 100644
--- a/lib/format_text/flags.c
+++ b/lib/format_text/flags.c
@@ -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;
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index 2995d6ab..80afc042 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -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;
}
diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c
index 08eda523..07f84a86 100644
--- a/lib/format_text/import_vsn1.c
+++ b/lib/format_text/import_vsn1.c
@@ -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;
- }
+ /*
+ * Insert into correct part of segment list.
+ */
+ _insert_segment(lv, seg);
- if (!(org_name = find_config_str(sn, "origin", NULL))) {
- log_suppress(0);
- log_error("Snapshot origin not specified.");
- return 0;
- }
+ if (seg->segtype->flags & SEG_AREAS_MIRRORED)
+ lv->status |= MIRRORED;
- log_suppress(0);
+ return 1;
+}
- if (!(cow = find_lv(vg, cow_name))) {
- log_error("Unknown logical volume specified for "
- "snapshot cow store.");
- return 0;
- }
+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 (!(org = find_lv(vg, org_name))) {
- log_error("Unknown logical volume specified for "
- "snapshot origin.");
- return 0;
- }
+ if (!seg->area_count) {
+ log_error("Zero areas not allowed for segment '%s'", sn->key);
+ return 0;
+ }
- if (!vg_add_snapshot(org, cow, 1, &lv->lvid.id[1], chunk_size)) {
- stack;
- return 0;
- }
- break;
+ for (cv = cn->v, s = 0; cv && s < seg->area_count; s++, cv = cv->next) {
- 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;
- }
+ /* first we read the pv */
+ const char *bad = "Badly formed areas array for "
+ "segment '%s'.";
+ struct physical_volume *pv;
- if (!(cn = find_config_node(sn, "stripes"))) {
- log_error("Couldn't find stripes array for segment "
- "'%s'.", sn->key);
+ if (cv->type != CFG_STRING) {
+ log_error(bad, 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);
+ if (!cv->next) {
+ log_error(bad, 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);
+ if (cv->next->type != CFG_INT) {
+ log_error(bad, 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);
+ /* 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;
}
/*
- * Insert into correct part of segment list.
+ * Check we read the correct number of stripes.
*/
- _insert_segment(lv, seg);
+ if (cv || (s < seg->area_count)) {
+ log_error("Incorrect number of areas in area array "
+ "for segment '%s'.", seg_name);
+ return 0;
+ }
+
return 1;
}
diff --git a/lib/format_text/text_export.h b/lib/format_text/text_export.h
new file mode 100644
index 00000000..fdc42c1c
--- /dev/null
+++ b/lib/format_text/text_export.h
@@ -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
diff --git a/lib/format_text/text_import.h b/lib/format_text/text_import.h
new file mode 100644
index 00000000..c6b8c717
--- /dev/null
+++ b/lib/format_text/text_import.h
@@ -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
diff --git a/lib/format_text/text_label.c b/lib/format_text/text_label.c
index 321d41ad..3cecf4bd 100644
--- a/lib/format_text/text_label.c
+++ b/lib/format_text/text_label.c
@@ -18,6 +18,7 @@
#include "layout.h"
#include "label.h"
#include "xlate.h"
+#include "lvmcache.h"
#include <sys/stat.h>
#include <fcntl.h>
diff --git a/lib/label/label.c b/lib/label/label.c
index 815d62dd..030c103e 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -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)
diff --git a/lib/label/label.h b/lib/label/label.h
index 4933db5e..99f1164d 100644
--- a/lib/label/label.h
+++ b/lib/label/label.h
@@ -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 */
diff --git a/lib/locking/locking.h b/lib/locking/locking.h
index 70ce0e8b..69f0664d 100644
--- a/lib/locking/locking.h
+++ b/lib/locking/locking.h
@@ -13,7 +13,6 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "metadata.h"
#include "uuid.h"
#include "config.h"
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index e9982f50..197aa8bb 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -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;
diff --git a/lib/metadata/merge.c b/lib/metadata/merge.c
index 81cbd924..decd7051 100644
--- a/lib/metadata/merge.c
+++ b/lib/metadata/merge.c
@@ -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;
}
-
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index 6bd9a200..dcefe6eb 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -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,7 +67,7 @@
#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,
@@ -74,12 +75,6 @@ typedef enum {
} alloc_policy_t;
typedef enum {
- SEG_STRIPED,
- SEG_SNAPSHOT,
- SEG_MIRRORED
-} segment_type_t;
-
-typedef enum {
AREA_PV,
AREA_LV
} area_type_t;
@@ -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);
diff --git a/lib/metadata/mirror.c b/lib/metadata/mirror.c
index ac777d54..5e058c16 100644
--- a/lib/metadata/mirror.c
+++ b/lib/metadata/mirror.c
@@ -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;
diff --git a/lib/metadata/segtypes.c b/lib/metadata/segtypes.c
new file mode 100644
index 00000000..0024e29c
--- /dev/null
+++ b/lib/metadata/segtypes.c
@@ -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;
+}
diff --git a/lib/metadata/segtypes.h b/lib/metadata/segtypes.h
new file mode 100644
index 00000000..3ebb2c73
--- /dev/null
+++ b/lib/metadata/segtypes.h
@@ -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
diff --git a/lib/mirror/.exported_symbols b/lib/mirror/.exported_symbols
new file mode 100644
index 00000000..1c92c6a3
--- /dev/null
+++ b/lib/mirror/.exported_symbols
@@ -0,0 +1 @@
+init_segtype
diff --git a/lib/mirror/Makefile.in b/lib/mirror/Makefile.in
new file mode 100644
index 00000000..66f33d50
--- /dev/null
+++ b/lib/mirror/Makefile.in
@@ -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
+
diff --git a/lib/mirror/mirrored.c b/lib/mirror/mirrored.c
new file mode 100644
index 00000000..846297c4
--- /dev/null
+++ b/lib/mirror/mirrored.c
@@ -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;
+}
diff --git a/lib/report/report.c b/lib/report/report.c
index 00f5bbce..485bdd11 100644
--- a/lib/report/report.c
+++ b/lib/report/report.c
@@ -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;
diff --git a/lib/snapshot/.exported_symbols b/lib/snapshot/.exported_symbols
new file mode 100644
index 00000000..1c92c6a3
--- /dev/null
+++ b/lib/snapshot/.exported_symbols
@@ -0,0 +1 @@
+init_segtype
diff --git a/lib/snapshot/Makefile.in b/lib/snapshot/Makefile.in
new file mode 100644
index 00000000..87661613
--- /dev/null
+++ b/lib/snapshot/Makefile.in
@@ -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
+
diff --git a/lib/snapshot/snapshot.c b/lib/snapshot/snapshot.c
new file mode 100644
index 00000000..feb5faa9
--- /dev/null
+++ b/lib/snapshot/snapshot.c
@@ -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;
+}
diff --git a/lib/striped/striped.c b/lib/striped/striped.c
new file mode 100644
index 00000000..3b06c3df
--- /dev/null
+++ b/lib/striped/striped.c
@@ -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;
+}
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index afe4f0a0..9385ea40 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -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) {
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
index 4efef72c..168e5738 100644
--- a/tools/lvmcmdline.c
+++ b/tools/lvmcmdline.c
@@ -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,
diff --git a/tools/lvresize.c b/tools/lvresize.c
index a4c0b19d..f818c887 100644
--- a/tools/lvresize.c
+++ b/tools/lvresize.c
@@ -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;
}
diff --git a/tools/tools.h b/tools/tools.h
index a68d9cc6..9e447e90 100644
--- a/tools/tools.h
+++ b/tools/tools.h
@@ -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"
diff --git a/tools/vgchange.c b/tools/vgchange.c
index a298c64d..a8f7cff0 100644
--- a/tools/vgchange.c
+++ b/tools/vgchange.c
@@ -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");