]> sourceware.org Git - lvm2.git/commitdiff
Begin to separate out segment types.
authorAlasdair Kergon <agk@redhat.com>
Tue, 4 May 2004 21:25:57 +0000 (21:25 +0000)
committerAlasdair Kergon <agk@redhat.com>
Tue, 4 May 2004 21:25:57 +0000 (21:25 +0000)
50 files changed:
Makefile.in
WHATS_NEW
configure
configure.in
include/.symlinks
lib/Makefile.in
lib/activate/activate.c
lib/activate/dev_manager.c
lib/activate/dev_manager.h
lib/activate/targets.h [new file with mode: 0644]
lib/cache/lvmcache.h
lib/commands/toolcontext.c
lib/commands/toolcontext.h
lib/display/display.c
lib/display/display.h
lib/format1/disk-rep.c
lib/format1/disk-rep.h
lib/format1/format1.c
lib/format1/import-export.c
lib/format1/import-extents.c
lib/format_text/archive.c
lib/format_text/export.c
lib/format_text/flags.c
lib/format_text/format-text.c
lib/format_text/import_vsn1.c
lib/format_text/text_export.h [new file with mode: 0644]
lib/format_text/text_import.h [new file with mode: 0644]
lib/format_text/text_label.c
lib/label/label.c
lib/label/label.h
lib/locking/locking.h
lib/metadata/lv_manip.c
lib/metadata/merge.c
lib/metadata/metadata.h
lib/metadata/mirror.c
lib/metadata/segtypes.c [new file with mode: 0644]
lib/metadata/segtypes.h [new file with mode: 0644]
lib/mirror/.exported_symbols [new file with mode: 0644]
lib/mirror/Makefile.in [new file with mode: 0644]
lib/mirror/mirrored.c [new file with mode: 0644]
lib/report/report.c
lib/snapshot/.exported_symbols [new file with mode: 0644]
lib/snapshot/Makefile.in [new file with mode: 0644]
lib/snapshot/snapshot.c [new file with mode: 0644]
lib/striped/striped.c [new file with mode: 0644]
tools/lvcreate.c
tools/lvmcmdline.c
tools/lvresize.c
tools/tools.h
tools/vgchange.c

index 4d9597b3646a56e5848ae5b51a49c2cdfc7ee902..489ba3bb477750684a47a1d871becc06abd2f65c 100644 (file)
@@ -26,6 +26,8 @@ SUBDIRS += lib tools
 
 ifeq ($(MAKECMDGOALS),distclean)
   SUBDIRS += lib/format1 \
+            lib/mirror \
+            lib/snapshot \
             po \
             test/mm test/device test/format1 test/regex test/filters
 endif
index 7c864f0075b070267222778f324565d1c88eeb1d..dfc20b6363ad3d903aae950afb8f8cc2d34a371e 100644 (file)
--- 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.
index 2e931b2fea0ed038d4f4d545a275ec9020fe3328..79859784fb0cd359e68802e6a09b1485bf722605 100755 (executable)
--- 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
index c35f81a76fbd2ed0b1acb3223d677fd568ed5041..e0a16369603b97812d13f8ac1314b3e1a1647232 100644 (file)
@@ -123,6 +123,42 @@ fi
 
 AC_ARG_ENABLE(jobs, [  --enable-jobs=NUM       Number of jobs to run simultaneously], JOBS=-j$enableval, JOBS=-j2)
 
+dnl -- snapshots inclusion type
+AC_ARG_WITH(snapshots,
+  [  --with-snapshots=TYPE   Snapshot support: internal/shared/none
+                          [TYPE=internal] ],
+  [ SNAPSHOTS="$withval" ],
+  [ SNAPSHOTS="internal" ])
+
+if [[ "x$SNAPSHOTS" != xnone -a "x$SNAPSHOTS" != xinternal -a "x$SNAPSHOTS" != xshared ]];
+ then  AC_MSG_ERROR(
+--with-snapshots parameter invalid
+)
+ exit
+fi;
+
+if test x$SNAPSHOTS = xinternal; then
+       CFLAGS="$CFLAGS -DSNAPSHOT_INTERNAL"
+fi
+
+dnl -- mirrors inclusion type
+AC_ARG_WITH(mirrors,
+  [  --with-mirrors=TYPE     Mirror support: internal/shared/none
+                          [TYPE=internal] ],
+  [ MIRRORS="$withval" ],
+  [ MIRRORS="internal" ])
+
+if [[ "x$MIRRORS" != xnone -a "x$MIRRORS" != xinternal -a "x$MIRRORS" != xshared ]];
+ then  AC_MSG_ERROR(
+--with-mirrors parameter invalid
+)
+ exit
+fi;
+
+if test x$MIRRORS = xinternal; then
+       CFLAGS="$CFLAGS -DMIRRORED_INTERNAL"
+fi
+
 dnl Enables staticly-linked tools
 AC_ARG_ENABLE(static_link, [  --enable-static_link    Use this to link the tools to their libraries
                           statically.  Default is dynamic linking],  STATIC_LINK=$enableval, STATIC_LINK=no)
@@ -210,7 +246,9 @@ else
 fi
 
 dnl Check for shared/static conflicts
-if [[ "x$LVM1" = xshared -a "x$STATIC_LINK" = xyes ]];
+if [[ \( "x$LVM1" = xshared -o \
+      "x$SNAPSHOTS" = xshared -o "x$MIRRORS" = xshared \
+      \) -a "x$STATIC_LINK" = xyes ]];
  then  AC_MSG_ERROR(
 Features cannot be 'shared' when building statically
 )
@@ -287,6 +325,8 @@ fi
 AC_SUBST(JOBS)
 AC_SUBST(STATIC_LINK)
 AC_SUBST(LVM1)
+AC_SUBST(SNAPSHOTS)
+AC_SUBST(MIRRORS)
 AC_SUBST(OWNER)
 AC_SUBST(GROUP)
 AC_SUBST(CFLAGS)
@@ -320,6 +360,8 @@ doc/Makefile                                                                \
 include/Makefile                                                       \
 lib/Makefile                                                           \
 lib/format1/Makefile                                                   \
+lib/mirror/Makefile                                                    \
+lib/snapshot/Makefile                                                  \
 man/Makefile                                                           \
 po/Makefile                                                            \
 tools/Makefile                                                         \
index 955007c28c9cf89f1745f6de07947e56e7679ec3..7c350da6237a62300e73fb3390ff551a649e4c00 100644 (file)
@@ -1,4 +1,5 @@
 ../lib/activate/activate.h
+../lib/activate/targets.h
 ../lib/cache/lvmcache.h
 ../lib/commands/errors.h
 ../lib/commands/toolcontext.h
 ../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
index fa640597dd864318f09ec32cf00bcd00038580d1..7d321cc3626e7df243b060a83d8fa849629fa32a 100644 (file)
@@ -20,6 +20,14 @@ ifeq ("@LVM1@", "shared")
   SUBDIRS = format1
 endif
 
+ifeq ("@SNAPSHOTS@", "shared")
+  SUBDIRS += snapshot
+endif
+
+ifeq ("@MIRRORS@", "shared")
+  SUBDIRS += mirror
+endif
+
 SOURCES =\
        activate/activate.c \
        cache/lvmcache.c \
@@ -57,6 +65,7 @@ SOURCES =\
        metadata/metadata.c \
        metadata/mirror.c \
        metadata/pv_map.c \
+       metadata/segtypes.c \
        metadata/snapshot_manip.c \
        misc/crc.c \
        misc/lvm-file.c \
@@ -67,6 +76,7 @@ SOURCES =\
        regex/parse_rx.c \
        regex/ttree.c \
        report/report.c \
+       striped/striped.c \
        uuid/uuid.c 
 
 ifeq ("@LVM1@", "internal")
@@ -80,6 +90,14 @@ ifeq ("@LVM1@", "internal")
        format1/vg_number.c
 endif
 
+ifeq ("@SNAPSHOTS@", "internal")
+  SOURCES += snapshot/snapshot.c
+endif
+
+ifeq ("@MIRRORS@", "internal")
+  SOURCES += mirror/mirrored.c
+endif
+
 ifeq ("@DEBUG@", "yes")
   SOURCES += mm/dbg_malloc.c
 endif
index ae9fa87aee0be8a7ef4c545c9ddb841253c4a2df..e5533680efcebd260117caf5dea27cf7199b1d0f 100644 (file)
@@ -25,6 +25,7 @@
 #include "toolcontext.h"
 #include "dev_manager.h"
 #include "str_list.h"
+#include "config.h"
 
 #include <limits.h>
 #include <fcntl.h>
@@ -341,7 +342,7 @@ static int _lv_info(const struct logical_volume *lv, int mknodes,
        if (!activation())
                return 0;
 
-       if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cft))) {
+       if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
                stack;
                return 0;
        }
@@ -387,7 +388,7 @@ int lv_snapshot_percent(struct logical_volume *lv, float *percent)
        if (!activation())
                return 0;
 
-       if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cft))) {
+       if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
                stack;
                return 0;
        }
@@ -419,7 +420,7 @@ int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
        if (!info.exists)
                return 0;
 
-       if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cft))) {
+       if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
                stack;
                return 0;
        }
@@ -462,7 +463,7 @@ static int _lv_activate_lv(struct logical_volume *lv)
        int r;
        struct dev_manager *dm;
 
-       if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cft))) {
+       if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
                stack;
                return 0;
        }
@@ -479,7 +480,7 @@ static int _lv_deactivate(struct logical_volume *lv)
        int r;
        struct dev_manager *dm;
 
-       if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cft))) {
+       if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
                stack;
                return 0;
        }
@@ -496,7 +497,7 @@ static int _lv_suspend_lv(struct logical_volume *lv)
        int r;
        struct dev_manager *dm;
 
-       if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cft))) {
+       if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
                stack;
                return 0;
        }
index 7cff1407dfaf15e6e16d687f7977bd1bd69b0d67..2e61bed1813935a681b4bb8599edf5a30c34346c 100644 (file)
 #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;
                        }
index 1482d3348aba3b2094cd1dc609240ea6e2570cb6..2290679cd69be19e01cf9134bf155bd120eda0da 100644 (file)
 #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 (file)
index 0000000..06f9152
--- /dev/null
@@ -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
index cbfb3167d68e15284d3304f1002ad4ade356efec..a461cd32123a5b0d87cd0114965a1f15e5362987 100644 (file)
@@ -20,7 +20,6 @@
 #include "dev-cache.h"
 #include "uuid.h"
 #include "label.h"
-#include "metadata.h"
 
 #define ORPHAN ""
 
 /* 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 */
index 883230b1ea6f3cfcc84ee823ed090ac4d5f4d2b3..7955dcaa42308319950c1ff1c66a29828acfe95d 100644 (file)
@@ -33,6 +33,8 @@
 #include "display.h"
 #include "memlock.h"
 #include "str_list.h"
+#include "segtypes.h"
+#include "lvmcache.h"
 
 #ifdef HAVE_LIBDL
 #include "sharedlib.h"
@@ -662,6 +664,87 @@ static int _init_formats(struct cmd_context *cmd)
        return 0;
 }
 
+static int _init_segtypes(struct cmd_context *cmd)
+{
+       struct segment_type *segtype;
+
+#ifdef HAVE_LIBDL
+       const struct config_node *cn;
+#endif
+
+       if (!(segtype = init_striped_segtype(cmd)))
+               return 0;
+       segtype->library = NULL;
+       list_add(&cmd->segtypes, &segtype->list);
+
+#ifdef SNAPSHOT_INTERNAL
+       if (!(segtype = init_snapshot_segtype(cmd)))
+               return 0;
+       segtype->library = NULL;
+       list_add(&cmd->segtypes, &segtype->list);
+#endif
+
+#ifdef MIRRORED_INTERNAL
+       if (!(segtype = init_mirrored_segtype(cmd)))
+               return 0;
+       segtype->library = NULL;
+       list_add(&cmd->segtypes, &segtype->list);
+#endif
+
+#ifdef HAVE_LIBDL
+       /* Load any formats in shared libs */
+       if ((cn = find_config_node(cmd->cft->root, "global/segment_libraries"))) {
+
+               struct config_value *cv;
+               struct segment_type *(*init_segtype_fn) (struct cmd_context *);
+               void *lib;
+               struct list *sgtl, *tmp;
+               struct segment_type *segtype2;
+
+               for (cv = cn->v; cv; cv = cv->next) {
+                       if (cv->type != CFG_STRING) {
+                               log_error("Invalid string in config file: "
+                                         "global/segment_libraries");
+                               return 0;
+                       }
+                       if (!(lib = load_shared_library(cmd->cft, cv->v.str,
+                                                       "segment type"))) {
+                               stack;
+                               return 0;
+                       }
+
+                       if (!(init_segtype_fn = dlsym(lib, "init_segtype"))) {
+                               log_error("Shared library %s does not contain "
+                                         "segment type functions", cv->v.str);
+                               dlclose(lib);
+                               return 0;
+                       }
+
+                       if (!(segtype = init_segtype_fn(cmd)))
+                               return 0;
+                       segtype->library = lib;
+                       list_add(&cmd->segtypes, &segtype->list);
+
+                       list_iterate_safe(sgtl, tmp, &cmd->segtypes) {
+                               segtype2 = list_item(sgtl, struct segment_type);
+                               if (!strcmp(segtype2->name, segtype->name)) {
+                                       log_error("Duplicate segment type %s: "
+                                                 "unloading shared library %s",
+                                                 segtype->name, cv->v.str);
+                                       list_del(&segtype->list);
+                                       segtype->ops->destroy(segtype);
+                                       dlclose(lib);
+                                       break;
+                               }
+
+                       }
+               }
+       }
+#endif
+
+       return 1;
+}
+
 static int _init_hostname(struct cmd_context *cmd)
 {
        struct utsname uts;
@@ -710,6 +793,7 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
        cmd->args = the_args;
        cmd->hosttags = 0;
        list_init(&cmd->formats);
+       list_init(&cmd->segtypes);
        list_init(&cmd->tags);
        list_init(&cmd->config_files);
 
@@ -763,6 +847,9 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
        if (!_init_formats(cmd))
                goto error;
 
+       if (!_init_segtypes(cmd))
+               goto error;
+
        cmd->current_settings = cmd->default_settings;
 
        cmd->config_valid = 1;
@@ -791,6 +878,24 @@ static void _destroy_formats(struct list *formats)
        }
 }
 
+static void _destroy_segtypes(struct list *segtypes)
+{
+       struct list *sgtl, *tmp;
+       struct segment_type *segtype;
+       void *lib;
+
+       list_iterate_safe(sgtl, tmp, segtypes) {
+               segtype = list_item(sgtl, struct segment_type);
+               list_del(&segtype->list);
+               lib = segtype->library;
+               segtype->ops->destroy(segtype);
+#ifdef HAVE_LIBDL
+               if (lib)
+                       dlclose(lib);
+#endif
+       }
+}
+
 int refresh_toolcontext(struct cmd_context *cmd)
 {
        log_verbose("Reloading config files");
@@ -803,6 +908,7 @@ int refresh_toolcontext(struct cmd_context *cmd)
        activation_exit();
        lvmcache_destroy();
        label_exit();
+       _destroy_segtypes(&cmd->segtypes);
        _destroy_formats(&cmd->formats);
        if (cmd->filter) {
                cmd->filter->destroy(cmd->filter);
@@ -842,6 +948,9 @@ int refresh_toolcontext(struct cmd_context *cmd)
        if (!_init_formats(cmd))
                return 0;
 
+       if (!_init_segtypes(cmd))
+               return 0;
+
        cmd->config_valid = 1;
        return 1;
 }
@@ -854,6 +963,7 @@ void destroy_toolcontext(struct cmd_context *cmd)
        activation_exit();
        lvmcache_destroy();
        label_exit();
+       _destroy_segtypes(&cmd->segtypes);
        _destroy_formats(&cmd->formats);
        cmd->filter->destroy(cmd->filter);
        pool_destroy(cmd->mem);
index 839716d64c73cef0efafa70304dc2888a0b5b84b..34606f1f9f6d1d242ef0331835029b3fafabb9eb 100644 (file)
@@ -57,6 +57,7 @@ struct cmd_context {
        struct format_type *fmt_backup; /* Format to use for backups */
 
        struct list formats;    /* Available formats */
+       struct list segtypes;   /* Available segment types */
        const char *hostname;
        const char *kernel_vsn;
 
index 75315b57f3c634bcd2f4baf86491dcb4eb9e8fd1..4a1aa921e35c0f4c5cfb9c04d709be06883bf768 100644 (file)
@@ -18,6 +18,7 @@
 #include "display.h"
 #include "activate.h"
 #include "toolcontext.h"
+#include "segtypes.h"
 
 #define SIZE_BUF 128
 
@@ -31,18 +32,7 @@ static struct {
        ALLOC_DEFAULT, "next free (default)"}
 };
 
-static struct {
-       segment_type_t segtype;
-       const char *str;
-} _segtypes[] = {
-       {
-       SEG_STRIPED, "striped"}, {
-       SEG_MIRRORED, "mirror"}, {
-       SEG_SNAPSHOT, "snapshot"}
-};
-
 static int _num_policies = sizeof(_policies) / sizeof(*_policies);
-static int _num_segtypes = sizeof(_segtypes) / sizeof(*_segtypes);
 
 uint64_t units_to_bytes(const char *units, char *unit_type)
 {
@@ -124,17 +114,6 @@ const char *get_alloc_string(alloc_policy_t alloc)
        return NULL;
 }
 
-const char *get_segtype_string(segment_type_t segtype)
-{
-       int i;
-
-       for (i = 0; i < _num_segtypes; i++)
-               if (_segtypes[i].segtype == segtype)
-                       return _segtypes[i].str;
-
-       return "unknown";
-}
-
 alloc_policy_t get_alloc_from_string(const char *str)
 {
        int i;
@@ -147,18 +126,6 @@ alloc_policy_t get_alloc_from_string(const char *str)
        return ALLOC_DEFAULT;
 }
 
-segment_type_t get_segtype_from_string(const char *str)
-{
-       int i;
-
-       for (i = 0; i < _num_segtypes; i++)
-               if (!strcmp(_segtypes[i].str, str))
-                       return _segtypes[i].segtype;
-
-       log_error("Unrecognised segment type - using default (striped)");
-       return SEG_STRIPED;
-}
-
 const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
 {
        int s;
@@ -386,8 +353,7 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
                        snap_active = lv_snapshot_percent(snap->cow,
                                                          &snap_percent);
                        if (!snap_active || snap_percent < 0 ||
-                           snap_percent >= 100)
-                               snap_active = 0;
+                           snap_percent >= 100) snap_active = 0;
                        log_print("                       %s%s/%s [%s]",
                                  lv->vg->cmd->dev_dir, lv->vg->name,
                                  snap->cow->name,
@@ -478,7 +444,7 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
        return 0;
 }
 
-static void _display_stripe(struct lv_segment *seg, uint32_t s, const char *pre)
+void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre)
 {
        switch (seg->area[s].type) {
        case AREA_PV:
@@ -506,52 +472,18 @@ static void _display_stripe(struct lv_segment *seg, uint32_t s, const char *pre)
 
 int lvdisplay_segments(struct logical_volume *lv)
 {
-       uint32_t s;
-       struct list *segh;
        struct lv_segment *seg;
 
        log_print("--- Segments ---");
 
-       list_iterate(segh, &lv->segments) {
-               seg = list_item(segh, struct lv_segment);
-
+       list_iterate_items(seg, &lv->segments) {
                log_print("Logical extent %u to %u:",
                          seg->le, seg->le + seg->len - 1);
 
-               if (seg->type == SEG_STRIPED && seg->area_count == 1)
-                       log_print("  Type\t\tlinear");
-               else
-                       log_print("  Type\t\t%s",
-                                 get_segtype_string(seg->type));
-
-               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;
index 1292fd75fb345502c8e7d29c2d7749ccc27bd6ca..0fc3486ffa44ca060ec4e388a12ee92c8f70891f 100644 (file)
@@ -27,6 +27,7 @@ uint64_t units_to_bytes(const char *units, char *unit_type);
 /* Specify size in KB */
 const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl);
 char *display_uuid(char *uuidstr);
+void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre);
 
 void pvdisplay_colons(struct physical_volume *pv);
 void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
@@ -50,10 +51,4 @@ void vgdisplay_short(struct volume_group *vg);
 const char *get_alloc_string(alloc_policy_t alloc);
 alloc_policy_t get_alloc_from_string(const char *str);
 
-/*
- * Segment type display conversion routines.
- */
-segment_type_t get_segtype_from_string(const char *str);
-const char *get_segtype_string(segment_type_t segtype);
-
 #endif
index aa0d964cc9d4656975a41341e61dd43ca30465e6..bb96e8918366286615ce5c9ed6c848193bc2376f 100644 (file)
@@ -153,6 +153,10 @@ static int _munge_formats(struct pv_disk *pvd)
                memset(&pvd->pv_uuid[ID_LEN], 0, sizeof(pvd->pv_uuid) - ID_LEN);
         }
 
+       /* If UUID is missing, create one */
+       if (pvd->pv_uuid[0] == '\0')
+               uuid_from_num(pvd->pv_uuid, pvd->pv_number);
+
        return 1;
 }
 
@@ -193,10 +197,6 @@ int munge_pvd(struct device *dev, struct pv_disk *pvd)
                return 0;
        }
 
-       /* If UUID is missing, create one */
-       if (pvd->pv_uuid[0] == '\0')
-               uuid_from_num(pvd->pv_uuid, pvd->pv_number);
-
        /* If VG is exported, set VG name back to the real name */
        _munge_exported_vg(pvd);
 
index b6b03229e99f8234e956830dda2ebe07138e42c4..9f8167f0624754c0e5cb4538663cedc6f2267bf4 100644 (file)
@@ -216,7 +216,7 @@ int export_vg(struct vg_disk *vgd, struct volume_group *vg);
 
 int import_lv(struct pool *mem, struct logical_volume *lv, struct lv_disk *lvd);
 
-int import_extents(struct pool *mem, struct volume_group *vg,
+int import_extents(struct cmd_context *cmd, struct volume_group *vg,
                   struct list *pvds);
 int export_extents(struct disk_list *dl, uint32_t lv_num,
                   struct logical_volume *lv, struct physical_volume *pv);
index 20c965c568019636e0af55e3cad2a957dc610ad5..39e28dc3c19a52b1273f547eca54e3641ddb07a1 100644 (file)
@@ -164,7 +164,7 @@ static struct volume_group *_build_vg(struct format_instance *fid,
        if (!import_lvs(mem, vg, pvs))
                goto bad;
 
-       if (!import_extents(mem, vg, pvs))
+       if (!import_extents(fid->fmt->cmd, vg, pvs))
                goto bad;
 
        if (!import_snapshots(mem, vg, pvs))
index 33305fc4f542cd1e125478913399a5fcef90d058..297056a5f9ac3875342b2467ac6770e4969df5ad 100644 (file)
@@ -25,6 +25,7 @@
 #include "lvm-string.h"
 #include "filter.h"
 #include "toolcontext.h"
+#include "segtypes.h"
 
 #include <time.h>
 
@@ -380,9 +381,10 @@ int export_extents(struct disk_list *dl, uint32_t lv_num,
                seg = list_item(segh, struct lv_segment);
 
                for (s = 0; s < seg->area_count; s++) {
-                       if (seg->type != SEG_STRIPED) {
-                               log_error("Non-striped segment type in LV %s: "
-                                         "unsupported by format1", lv->name);
+                       if (!(seg->segtype->flags & SEG_FORMAT1_SUPPORT)) {
+                               log_error("Segment type %s in LV %s: "
+                                         "unsupported by format1",
+                                         seg->segtype->name, lv->name);
                                return 0;
                        }
                        if (seg->area[s].type != AREA_PV) {
index 82828a1b6f9c05aac51227c4dc979f19818b056e..851e7c251dd840cc79e48d0255be88d0d97094c1 100644 (file)
@@ -19,6 +19,8 @@
 #include "pool.h"
 #include "disk-rep.h"
 #include "lv_alloc.h"
+#include "display.h"
+#include "segtypes.h"
 
 /*
  * After much thought I have decided it is easier,
@@ -201,16 +203,20 @@ static int _check_maps_are_complete(struct hash_table *maps)
        return 1;
 }
 
-static int _read_linear(struct pool *mem, struct lv_map *lvm)
+static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
 {
        uint32_t le = 0;
        struct lv_segment *seg;
 
        while (le < lvm->lv->le_count) {
-               seg = alloc_lv_segment(mem, 1);
+               seg = alloc_lv_segment(cmd->mem, 1);
 
                seg->lv = lvm->lv;
-               seg->type = SEG_STRIPED;
+               if (!(seg->segtype = get_segtype_from_string(cmd, "striped"))) {
+                       stack;
+                       return 0;
+               }
+
                seg->le = le;
                seg->len = 0;
                seg->area_len = 0;
@@ -251,13 +257,12 @@ static int _check_stripe(struct lv_map *lvm, struct lv_segment *seg,
                if ((lvm->map[le + st * len].pv != seg->area[st].u.pv.pv) ||
                    (seg->area[st].u.pv.pv &&
                     lvm->map[le + st * len].pe !=
-                    seg->area[st].u.pv.pe + seg->len))
-                       return 0;
+                    seg->area[st].u.pv.pe + seg->len)) return 0;
 
        return 1;
 }
 
-static int _read_stripes(struct pool *mem, struct lv_map *lvm)
+static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
 {
        uint32_t st, le = 0, len;
        struct lv_segment *seg;
@@ -273,13 +278,16 @@ static int _read_stripes(struct pool *mem, struct lv_map *lvm)
        len = lvm->lv->le_count / lvm->stripes;
 
        while (le < len) {
-               if (!(seg = alloc_lv_segment(mem, lvm->stripes))) {
+               if (!(seg = alloc_lv_segment(cmd->mem, lvm->stripes))) {
                        stack;
                        return 0;
                }
 
                seg->lv = lvm->lv;
-               seg->type = SEG_STRIPED;
+               if (!(seg->segtype = get_segtype_from_string(cmd, "striped"))) {
+                       stack;
+                       return 0;
+               }
                seg->stripe_size = lvm->stripe_size;
                seg->area_count = lvm->stripes;
                seg->le = seg->area_count * le;
@@ -312,20 +320,20 @@ static int _read_stripes(struct pool *mem, struct lv_map *lvm)
        return 1;
 }
 
-static int _build_segments(struct pool *mem, struct lv_map *lvm)
+static int _build_segments(struct cmd_context *cmd, struct lv_map *lvm)
 {
-       return (lvm->stripes > 1 ? _read_stripes(mem, lvm) :
-               _read_linear(mem, lvm));
+       return (lvm->stripes > 1 ? _read_stripes(cmd, lvm) :
+               _read_linear(cmd, lvm));
 }
 
-static int _build_all_segments(struct pool *mem, struct hash_table *maps)
+static int _build_all_segments(struct cmd_context *cmd, struct hash_table *maps)
 {
        struct hash_node *n;
        struct lv_map *lvm;
 
        for (n = hash_get_first(maps); n; n = hash_get_next(maps, n)) {
                lvm = (struct lv_map *) hash_get_data(maps, n);
-               if (!_build_segments(mem, lvm)) {
+               if (!_build_segments(cmd, lvm)) {
                        stack;
                        return 0;
                }
@@ -334,7 +342,8 @@ static int _build_all_segments(struct pool *mem, struct hash_table *maps)
        return 1;
 }
 
-int import_extents(struct pool *mem, struct volume_group *vg, struct list *pvds)
+int import_extents(struct cmd_context *cmd, struct volume_group *vg,
+                  struct list *pvds)
 {
        int r = 0;
        struct pool *scratch = pool_create(10 * 1024);
@@ -360,7 +369,7 @@ int import_extents(struct pool *mem, struct volume_group *vg, struct list *pvds)
                goto out;
        }
 
-       if (!_build_all_segments(mem, maps)) {
+       if (!_build_all_segments(cmd, maps)) {
                log_err("Couldn't build extent segments.");
                goto out;
        }
index cdbafb7039fc09d816ee8cf611a84481b30b0745..724ffff6741e586cd2a46c6f15082f92e57f4b0a 100644 (file)
@@ -380,4 +380,3 @@ int backup_list(struct cmd_context *cmd, const char *dir, const char *vgname)
 
        return 1;
 }
-
index 69b960e82383a3eb6b9bda79123ca010edc50ba4..7ae3072c9d8d50d38ad7548c2ddffa44482af623 100644 (file)
@@ -20,6 +20,8 @@
 #include "pool.h"
 #include "display.h"
 #include "lvm-string.h"
+#include "segtypes.h"
+#include "text_export.h"
 
 #include <stdarg.h>
 #include <time.h>
@@ -74,14 +76,6 @@ static void _init(void)
 /*
  * Formatting functions.
  */
-static int _out_size(struct formatter *f, uint64_t size, const char *fmt, ...)
-    __attribute__ ((format(printf, 3, 4)));
-
-static int _out_hint(struct formatter *f, const char *fmt, ...)
-    __attribute__ ((format(printf, 2, 3)));
-
-static int _out(struct formatter *f, const char *fmt, ...)
-    __attribute__ ((format(printf, 2, 3)));
 
 #define MAX_INDENT 5
 static void _inc_indent(struct formatter *f)
@@ -206,7 +200,7 @@ static int _sectors_to_units(uint64_t sectors, char *buffer, size_t s)
  * Appends a comment giving a size in more easily
  * readable form (eg, 4M instead of 8096).
  */
-static int _out_size(struct formatter *f, uint64_t size, const char *fmt, ...)
+int out_size(struct formatter *f, uint64_t size, const char *fmt, ...)
 {
        char buffer[64];
        va_list ap;
@@ -226,7 +220,7 @@ static int _out_size(struct formatter *f, uint64_t size, const char *fmt, ...)
  * Appends a comment indicating that the line is
  * only a hint.
  */
-static int _out_hint(struct formatter *f, const char *fmt, ...)
+int out_hint(struct formatter *f, const char *fmt, ...)
 {
        va_list ap;
        int r;
@@ -241,7 +235,7 @@ static int _out_hint(struct formatter *f, const char *fmt, ...)
 /*
  * The normal output function.
  */
-static int _out(struct formatter *f, const char *fmt, ...)
+int out_text(struct formatter *f, const char *fmt, ...)
 {
        va_list ap;
        int r;
@@ -253,8 +247,6 @@ static int _out(struct formatter *f, const char *fmt, ...)
        return r;
 }
 
-#define _outf(args...) do {if (!_out(args)) {stack; return 0;}} while (0)
-
 static int _print_header(struct formatter *f,
                         struct volume_group *vg, const char *desc)
 {
@@ -262,17 +254,17 @@ static int _print_header(struct formatter *f,
 
        t = time(NULL);
 
-       _outf(f, "# Generated by LVM2: %s", ctime(&t));
-       _outf(f, CONTENTS_FIELD " = \"" CONTENTS_VALUE "\"");
-       _outf(f, FORMAT_VERSION_FIELD " = %d", FORMAT_VERSION_VALUE);
+       outf(f, "# Generated by LVM2: %s", ctime(&t));
+       outf(f, CONTENTS_FIELD " = \"" CONTENTS_VALUE "\"");
+       outf(f, FORMAT_VERSION_FIELD " = %d", FORMAT_VERSION_VALUE);
        f->nl(f);
 
-       _outf(f, "description = \"%s\"", desc);
+       outf(f, "description = \"%s\"", desc);
        f->nl(f);
-       _outf(f, "creation_host = \"%s\"\t# %s %s %s %s %s", _utsname.nodename,
-             _utsname.sysname, _utsname.nodename, _utsname.release,
-             _utsname.version, _utsname.machine);
-       _outf(f, "creation_time = %lu\t# %s", t, ctime(&t));
+       outf(f, "creation_host = \"%s\"\t# %s %s %s %s %s", _utsname.nodename,
+            _utsname.sysname, _utsname.nodename, _utsname.release,
+            _utsname.version, _utsname.machine);
+       outf(f, "creation_time = %lu\t# %s", t, ctime(&t));
 
        return 1;
 }
@@ -286,34 +278,34 @@ static int _print_vg(struct formatter *f, struct volume_group *vg)
                return 0;
        }
 
-       _outf(f, "id = \"%s\"", buffer);
+       outf(f, "id = \"%s\"", buffer);
 
-       _outf(f, "seqno = %u", vg->seqno);
+       outf(f, "seqno = %u", vg->seqno);
 
        if (!print_flags(vg->status, VG_FLAGS, buffer, sizeof(buffer))) {
                stack;
                return 0;
        }
-       _outf(f, "status = %s", buffer);
+       outf(f, "status = %s", buffer);
 
        if (!list_empty(&vg->tags)) {
                if (!print_tags(&vg->tags, buffer, sizeof(buffer))) {
                        stack;
                        return 0;
                }
-               _outf(f, "tags = %s", buffer);
+               outf(f, "tags = %s", buffer);
        }
 
        if (vg->system_id && *vg->system_id)
-               _outf(f, "system_id = \"%s\"", vg->system_id);
+               outf(f, "system_id = \"%s\"", vg->system_id);
 
-       if (!_out_size(f, (uint64_t) vg->extent_size, "extent_size = %u",
-                      vg->extent_size)) {
+       if (!out_size(f, (uint64_t) vg->extent_size, "extent_size = %u",
+                     vg->extent_size)) {
                stack;
                return 0;
        }
-       _outf(f, "max_lv = %u", vg->max_lv);
-       _outf(f, "max_pv = %u", vg->max_pv);
+       outf(f, "max_lv = %u", vg->max_lv);
+       outf(f, "max_pv = %u", vg->max_pv);
 
        return 1;
 }
@@ -336,7 +328,7 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
        char buffer[4096];
        const char *name;
 
-       _outf(f, "physical_volumes {");
+       outf(f, "physical_volumes {");
        _inc_indent(f);
 
        list_iterate(pvh, &vg->pvs) {
@@ -348,7 +340,7 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
                }
 
                f->nl(f);
-               _outf(f, "%s {", name);
+               outf(f, "%s {", name);
                _inc_indent(f);
 
                if (!id_write_format(&pv->id, buffer, sizeof(buffer))) {
@@ -356,8 +348,8 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
                        return 0;
                }
 
-               _outf(f, "id = \"%s\"", buffer);
-               if (!_out_hint(f, "device = \"%s\"", dev_name(pv->dev))) {
+               outf(f, "id = \"%s\"", buffer);
+               if (!out_hint(f, "device = \"%s\"", dev_name(pv->dev))) {
                        stack;
                        return 0;
                }
@@ -367,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
index f9d16acf0669e6e997dfda9a6132d2585dadc687..1a9bbb394c1e520c6fd6d5b0b9a905dda29785f3 100644 (file)
@@ -52,6 +52,7 @@ static struct flag _lv_flags[] = {
        {VISIBLE_LV, "VISIBLE"},
        {PVMOVE, "PVMOVE"},
        {LOCKED, "LOCKED"},
+       {MIRRORED, NULL},
        {0, NULL}
 };
 
@@ -99,7 +100,8 @@ int print_flags(uint32_t status, int type, char *buffer, size_t size)
                        } else
                                first = 0;
 
-                       if (!emit_to_buffer(&buffer, &size, "\"%s\"",
+                       if (flags[f].description &&
+                           !emit_to_buffer(&buffer, &size, "\"%s\"",
                                            flags[f].description))
                                return 0;
 
index 2995d6ab50037cce467b2db8720bc33fe4d55188..80afc042917b4afe0f46ddbadab5a3dc8a29e983 100644 (file)
@@ -30,6 +30,7 @@
 #include "xlate.h"
 #include "label.h"
 #include "memlock.h"
+#include "lvmcache.h"
 
 #include <unistd.h>
 #include <sys/file.h>
@@ -928,8 +929,7 @@ static int _mda_setup(const struct format_type *fmt,
        /* FIXME If creating new mdas, wipe them! */
        if (mda_size1) {
                if (!add_mda(fmt, fmt->cmd->mem, mdas, pv->dev, start1,
-                            mda_size1))
-                       return 0;
+                            mda_size1)) return 0;
 
                if (!dev_zero((struct device *) pv->dev, start1,
                              (size_t) (mda_size1 >
@@ -976,8 +976,7 @@ static int _mda_setup(const struct format_type *fmt,
 
        if (mda_size2) {
                if (!add_mda(fmt, fmt->cmd->mem, mdas, pv->dev, start2,
-                            mda_size2))
-                       return 0;
+                            mda_size2)) return 0;
                if (!dev_zero(pv->dev, start2,
                              (size_t) (mda_size1 >
                                        wipe_size ? wipe_size : mda_size1))) {
@@ -1066,8 +1065,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
                }
        }
        if (!add_da
-           (fmt, NULL, &info->das, pv->pe_start << SECTOR_SHIFT,
-            UINT64_C(0))) {
+           (fmt, NULL, &info->das, pv->pe_start << SECTOR_SHIFT, UINT64_C(0))) {
                stack;
                return 0;
        }
@@ -1139,8 +1137,7 @@ static int _add_raw(struct list *raw_list, struct device_area *dev_area)
                rl = list_item(rlh, struct raw_list);
                /* FIXME Check size/overlap consistency too */
                if (rl->dev_area.dev == dev_area->dev &&
-                   rl->dev_area.start == dev_area->start)
-                       return 1;
+                   rl->dev_area.start == dev_area->start) return 1;
        }
 
        if (!(rl = dbg_malloc(sizeof(struct raw_list)))) {
@@ -1334,11 +1331,10 @@ static int _pv_setup(const struct format_type *fmt,
                                            list_item(mdash,
                                                      struct metadata_area);
                                        if (mda2->ops !=
-                                           &_metadata_text_raw_ops)
-                                               continue;
+                                           &_metadata_text_raw_ops) continue;
                                        mdac2 =
-                                           (struct mda_context *) mda2->
-                                           metadata_locn;
+                                           (struct mda_context *)
+                                           mda2->metadata_locn;
                                        if (!memcmp
                                            (&mdac2->area, &mdac->area,
                                             sizeof(mdac->area))) {
@@ -1356,8 +1352,7 @@ static int _pv_setup(const struct format_type *fmt,
                                }
 
                                if (!(mdac_new = pool_alloc(fmt->cmd->mem,
-                                                           sizeof(*mdac_new))))
-                               {
+                                                           sizeof(*mdac_new)))) {
                                        stack;
                                        return 0;
                                }
@@ -1486,8 +1481,7 @@ static struct format_instance *_create_text_instance(const struct format_type
                                }
 
                                if (!(mdac_new = pool_alloc(fmt->cmd->mem,
-                                                           sizeof(*mdac_new))))
-                               {
+                                                           sizeof(*mdac_new)))) {
                                        stack;
                                        return NULL;
                                }
index 08eda5239f6f6d6cb5f54f4a59ddade2848dbd58..07f84a86ca8d845bdf96d8f3e1ea26244d9329d8 100644 (file)
@@ -22,6 +22,8 @@
 #include "toolcontext.h"
 #include "lvmcache.h"
 #include "lv_alloc.h"
+#include "segtypes.h"
+#include "text_import.h"
 
 typedef int (*section_fn) (struct format_instance * fid, struct pool * mem,
                           struct volume_group * vg, struct config_node * pvn,
@@ -234,17 +236,13 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
                         struct logical_volume *lv, struct config_node *sn,
                         struct hash_table *pv_hash)
 {
-       unsigned int s;
-       uint32_t area_count = 0;
+       uint32_t area_count = 0u;
        struct lv_segment *seg;
        struct config_node *cn;
        struct config_value *cv;
-       const char *seg_name = sn->key;
        uint32_t start_extent, extent_count;
-       uint32_t chunk_size, extents_moved = 0u, seg_status = 0u;
-       const char *org_name, *cow_name;
-       struct logical_volume *org, *cow, *lv1;
-       segment_type_t segtype;
+       struct segment_type *segtype;
+       const char *segtype_str;
 
        if (!(sn = sn->child)) {
                log_error("Empty segment section.");
@@ -263,40 +261,26 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
                return 0;
        }
 
-       segtype = SEG_STRIPED;  /* Default */
+       segtype_str = "striped";
+
        if ((cn = find_config_node(sn, "type"))) {
                cv = cn->v;
                if (!cv || !cv->v.str) {
                        log_error("Segment type must be a string.");
                        return 0;
                }
-               segtype = get_segtype_from_string(cv->v.str);
+               segtype_str = cv->v.str;
        }
 
-       if (segtype == SEG_STRIPED) {
-               if (!_read_int32(sn, "stripe_count", &area_count)) {
-                       log_error("Couldn't read 'stripe_count' for "
-                                 "segment '%s'.", sn->key);
-                       return 0;
-               }
+       if (!(segtype = get_segtype_from_string(vg->cmd, segtype_str))) {
+               stack;
+               return 0;
        }
 
-       if (segtype == SEG_MIRRORED) {
-               if (!_read_int32(sn, "mirror_count", &area_count)) {
-                       log_error("Couldn't read 'mirror_count' for "
-                                 "segment '%s'.", sn->key);
-                       return 0;
-               }
-
-               if (find_config_node(sn, "extents_moved")) {
-                       if (_read_uint32(sn, "extents_moved", &extents_moved))
-                               seg_status |= PVMOVE;
-                       else {
-                               log_error("Couldn't read 'extents_moved' for "
-                                         "segment '%s'.", sn->key);
-                               return 0;
-                       }
-               }
+       if (segtype->ops->text_import_area_count &&
+           !segtype->ops->text_import_area_count(sn, &area_count)) {
+               stack;
+               return 0;
        }
 
        if (!(seg = alloc_lv_segment(mem, area_count))) {
@@ -308,9 +292,16 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
        seg->le = start_extent;
        seg->len = extent_count;
        seg->area_len = extent_count;
-       seg->type = segtype;
-       seg->status = seg_status;
-       seg->extents_moved = extents_moved;
+       seg->status = 0u;
+       seg->segtype = segtype;
+       seg->extents_moved = 0u;
+       seg->area_count = area_count;
+
+       if (seg->segtype->ops->text_import &&
+           !seg->segtype->ops->text_import(seg, sn, pv_hash)) {
+               stack;
+               return 0;
+       }
 
        /* Optional tags */
        if ((cn = find_config_node(sn, "tags")) &&
@@ -320,145 +311,86 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
                return 0;
        }
 
-       switch (segtype) {
-       case SEG_SNAPSHOT:
-               lv->status |= SNAPSHOT;
-
-               if (!_read_uint32(sn, "chunk_size", &chunk_size)) {
-                       log_error("Couldn't read chunk size for snapshot.");
-                       return 0;
-               }
-
-               log_suppress(1);
-
-               if (!(cow_name = find_config_str(sn, "cow_store", NULL))) {
-                       log_suppress(0);
-                       log_error("Snapshot cow storage not specified.");
-                       return 0;
-               }
+       /*
+        * 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 (file)
index 0000000..fdc42c1
--- /dev/null
@@ -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 (file)
index 0000000..c6b8c71
--- /dev/null
@@ -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
index 321d41ad3fd880aa9cf693aee6fa4d21b045a567..3cecf4bdbd497aa6d5922d283133fd1be24c610d 100644 (file)
@@ -18,6 +18,7 @@
 #include "layout.h"
 #include "label.h"
 #include "xlate.h"
+#include "lvmcache.h"
 
 #include <sys/stat.h>
 #include <fcntl.h>
index 815d62ddab7e389fe8d62a83f65f5dd5dd2dd5d3..030c103e0382713597ff7be7375d60ea488f0a43 100644 (file)
@@ -19,6 +19,7 @@
 #include "crc.h"
 #include "xlate.h"
 #include "lvmcache.h"
+#include "metadata.h"
 
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -78,6 +79,8 @@ void label_exit(void)
                li->l->ops->destroy(li->l);
                _free_li(li);
        }
+
+       list_init(&_labellers);
 }
 
 int label_register_handler(const char *name, struct labeller *handler)
index 4933db5e4a041f979cb1ae39a3dd11aef8302446..99f1164db88cfcaa3c4de7c09e7b48d2ee8bd82a 100644 (file)
@@ -16,7 +16,6 @@
 #ifndef _LVM_LABEL_H
 #define _LVM_LABEL_H
 
-#include "lvmcache.h"
 #include "uuid.h"
 #include "device.h"
 
@@ -25,6 +24,8 @@
 #define LABEL_SCAN_SECTORS 4L
 #define LABEL_SCAN_SIZE (LABEL_SCAN_SECTORS << SECTOR_SHIFT)
 
+struct labeller;
+
 /* On disk - 32 bytes */
 struct label_header {
        uint8_t id[8];          /* LABELONE */
index 70ce0e8bb5bdd427851989b731056917b4a8cdab..69f0664d1d1f1fa3d9c415263f0ca59b7e1a9957 100644 (file)
@@ -13,7 +13,6 @@
  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include "metadata.h"
 #include "uuid.h"
 #include "config.h"
 
index e9982f5054482692877eaae63a99277a7da478d1..197aa8bb8827201be8bbf0df0ff16d9e22df2546 100644 (file)
@@ -20,6 +20,8 @@
 #include "lvm-string.h"
 #include "toolcontext.h"
 #include "lv_alloc.h"
+#include "display.h"
+#include "segtypes.h"
 
 /*
  * These functions adjust the pe counts in pv's
@@ -76,6 +78,7 @@ struct lv_segment *alloc_lv_segment(struct pool *mem, uint32_t num_areas)
 
 static int _alloc_parallel_area(struct logical_volume *lv, uint32_t area_count,
                                uint32_t stripe_size,
+                               struct segment_type *segtype,
                                struct pv_area **areas, uint32_t *ix)
 {
        uint32_t count, area_len, smallest;
@@ -83,7 +86,9 @@ static int _alloc_parallel_area(struct logical_volume *lv, uint32_t area_count,
        struct lv_segment *seg;
        int striped = 0;
 
-       striped = 1;
+       /* Striped or mirrored? */
+       if (segtype->flags & SEG_AREAS_STRIPED)
+               striped = 1;
 
        count = lv->le_count - *ix;
        area_len = count / (striped ? area_count : 1);
@@ -98,7 +103,7 @@ static int _alloc_parallel_area(struct logical_volume *lv, uint32_t area_count,
        }
 
        seg->lv = lv;
-       seg->type = SEG_STRIPED;
+       seg->segtype = segtype;
        seg->le = *ix;
        seg->len = area_len * (striped ? area_count : 1);
        seg->area_len = area_len;
@@ -116,6 +121,10 @@ static int _alloc_parallel_area(struct logical_volume *lv, uint32_t area_count,
 
        list_add(&lv->segments, &seg->list);
        *ix += seg->len;
+
+       if (!striped)
+               lv->status |= MIRRORED;
+
        return 1;
 }
 
@@ -135,7 +144,8 @@ static int _comp_area(const void *l, const void *r)
 
 static int _alloc_parallel(struct logical_volume *lv,
                           struct list *pvms, uint32_t allocated,
-                          uint32_t stripes, uint32_t stripe_size)
+                          uint32_t stripes, uint32_t stripe_size,
+                          uint32_t mirrors, struct segment_type *segtype)
 {
        int r = 0;
        struct list *pvmh;
@@ -145,7 +155,15 @@ static int _alloc_parallel(struct logical_volume *lv,
        size_t len;
        uint32_t area_count;
 
-       area_count = stripes;
+       if (stripes > 1 && mirrors > 1) {
+               log_error("striped mirrors are not supported yet");
+               return 0;
+       }
+
+       if (stripes > 1)
+               area_count = stripes;
+       else
+               area_count = mirrors;
 
        list_iterate(pvmh, pvms)
            pv_count++;
@@ -179,8 +197,8 @@ static int _alloc_parallel(struct logical_volume *lv,
                /* sort the areas so we allocate from the biggest */
                qsort(areas, ix, sizeof(*areas), _comp_area);
 
-               if (!_alloc_parallel_area(lv, area_count, stripe_size, areas,
-                                         &allocated)) {
+               if (!_alloc_parallel_area(lv, area_count, stripe_size, segtype,
+                                         areas, &allocated)) {
                        stack;
                        goto out;
                }
@@ -215,7 +233,11 @@ static int _alloc_linear_area(struct logical_volume *lv, uint32_t *ix,
        }
 
        seg->lv = lv;
-       seg->type = SEG_STRIPED;
+       if (!(seg->segtype = get_segtype_from_string(lv->vg->cmd, "striped"))) {
+               stack;
+               return 0;
+       }
+       seg->le = *ix;
        seg->le = *ix;
        seg->len = count;
        seg->area_len = count;
@@ -234,6 +256,7 @@ static int _alloc_linear_area(struct logical_volume *lv, uint32_t *ix,
 
 static int _alloc_mirrored_area(struct logical_volume *lv, uint32_t *ix,
                                struct pv_map *map, struct pv_area *pva,
+                               struct segment_type *segtype,
                                struct physical_volume *mirrored_pv,
                                uint32_t mirrored_pe)
 {
@@ -251,7 +274,8 @@ static int _alloc_mirrored_area(struct logical_volume *lv, uint32_t *ix,
        }
 
        seg->lv = lv;
-       seg->type = SEG_MIRRORED;
+       seg->segtype = segtype;
+       seg->le = *ix;
        seg->status = 0u;
        seg->le = *ix;
        seg->len = count;
@@ -321,6 +345,7 @@ static int _alloc_contiguous(struct logical_volume *lv,
 /* FIXME Contiguous depends on *segment* (i.e. stripe) not LV */
 static int _alloc_mirrored(struct logical_volume *lv,
                           struct list *pvms, uint32_t allocated,
+                          struct segment_type *segtype,
                           struct physical_volume *mirrored_pv,
                           uint32_t mirrored_pe)
 {
@@ -343,7 +368,7 @@ static int _alloc_mirrored(struct logical_volume *lv,
                        continue;
                }
 
-               if (!_alloc_mirrored_area(lv, &allocated, pvm, pva,
+               if (!_alloc_mirrored_area(lv, &allocated, pvm, pva, segtype,
                                          mirrored_pv, mirrored_pe)) {
                        stack;
                        return 0;
@@ -400,7 +425,8 @@ static int _alloc_next_free(struct logical_volume *lv,
  */
 static int _allocate(struct volume_group *vg, struct logical_volume *lv,
                     struct list *allocatable_pvs, uint32_t allocated,
-                    uint32_t stripes, uint32_t stripe_size,
+                    struct segment_type *segtype,
+                    uint32_t stripes, uint32_t stripe_size, uint32_t mirrors,
                     struct physical_volume *mirrored_pv, uint32_t mirrored_pe,
                     uint32_t status)
 {
@@ -420,11 +446,12 @@ static int _allocate(struct volume_group *vg, struct logical_volume *lv,
        if (!(pvms = create_pv_maps(scratch, vg, allocatable_pvs)))
                goto out;
 
-       if (stripes > 1)
-               r = _alloc_parallel(lv, pvms, allocated, stripes, stripe_size);
+       if (stripes > 1 || mirrors > 1)
+               r = _alloc_parallel(lv, pvms, allocated, stripes, stripe_size,
+                                   mirrors, segtype);
 
        else if (mirrored_pv)
-               r = _alloc_mirrored(lv, pvms, allocated, mirrored_pv,
+               r = _alloc_mirrored(lv, pvms, allocated, segtype, mirrored_pv,
                                    mirrored_pe);
        else if (lv->alloc == ALLOC_CONTIGUOUS)
                r = _alloc_contiguous(lv, pvms, allocated);
@@ -554,12 +581,51 @@ struct logical_volume *lv_create_empty(struct format_instance *fi,
        return lv;
 }
 
-struct logical_volume *lv_create(struct format_instance *fi,
+int lv_extend(struct format_instance *fid,
+                     struct logical_volume *lv,
+                     struct segment_type *segtype,
+                     uint32_t stripes, uint32_t stripe_size,
+                     uint32_t mirrors, uint32_t extents,
+                     struct physical_volume *mirrored_pv, uint32_t mirrored_pe,
+                     uint32_t status, struct list *allocatable_pvs)
+{
+       uint32_t old_le_count = lv->le_count;
+       uint64_t old_size = lv->size;
+
+       lv->le_count += extents;
+       lv->size += (uint64_t) extents *lv->vg->extent_size;
+
+       if (!_allocate(lv->vg, lv, allocatable_pvs, old_le_count, segtype,
+                      stripes, stripe_size, mirrors, mirrored_pv, mirrored_pe,
+                      status)) {
+               lv->le_count = old_le_count;
+               lv->size = old_size;
+               stack;
+               return 0;
+       }
+
+       if ((segtype->flags & SEG_CAN_SPLIT) && !lv_merge_segments(lv)) {
+               log_err("Couldn't merge segments after extending "
+                       "logical volume.");
+               return 0;
+       }
+
+       if (fid->fmt->ops->lv_setup && !fid->fmt->ops->lv_setup(fid, lv)) {
+               stack;
+               return 0;
+       }
+
+       return 1;
+}
+
+struct logical_volume *lv_create(struct format_instance *fid,
                                 const char *name,
                                 uint32_t status,
                                 alloc_policy_t alloc,
+                                struct segment_type *segtype,
                                 uint32_t stripes,
                                 uint32_t stripe_size,
+                                uint32_t mirrors,
                                 uint32_t extents,
                                 struct volume_group *vg,
                                 struct list *allocatable_pvs)
@@ -585,21 +651,13 @@ struct logical_volume *lv_create(struct format_instance *fi,
                return NULL;
        }
 
-       if (!(lv = lv_create_empty(fi, name, "lvol%d", status, alloc, vg))) {
+       if (!(lv = lv_create_empty(fid, name, "lvol%d", status, alloc, vg))) {
                stack;
                return NULL;
        }
 
-       lv->size = (uint64_t) extents *vg->extent_size;
-       lv->le_count = extents;
-
-       if (!_allocate(vg, lv, allocatable_pvs, 0u, stripes, stripe_size,
-                      NULL, 0u, 0u)) {
-               stack;
-               return NULL;
-       }
-
-       if (fi->fmt->ops->lv_setup && !fi->fmt->ops->lv_setup(fi, lv)) {
+       if (!lv_extend(fid, lv, segtype, stripes, stripe_size, mirrors,
+                      extents, NULL, 0u, 0u, allocatable_pvs)) {
                stack;
                return NULL;
        }
@@ -628,7 +686,7 @@ int lv_reduce(struct format_instance *fi,
                        /* reduce this segment */
                        _put_extents(seg);
                        seg->len -= count;
-                       striped = (seg->type == SEG_STRIPED);
+                       striped = seg->segtype->flags & SEG_AREAS_STRIPED;
                        /* Caller must ensure exact divisibility */
                        if (striped && (count % seg->area_count)) {
                                log_error("Segment extent reduction %" PRIu32
@@ -655,68 +713,6 @@ int lv_reduce(struct format_instance *fi,
        return 1;
 }
 
-int lv_extend(struct format_instance *fi,
-             struct logical_volume *lv,
-             uint32_t stripes, uint32_t stripe_size,
-             uint32_t extents, struct list *allocatable_pvs)
-{
-       uint32_t old_le_count = lv->le_count;
-       uint64_t old_size = lv->size;
-
-       lv->le_count += extents;
-       lv->size += (uint64_t) extents *lv->vg->extent_size;
-
-       if (!_allocate(lv->vg, lv, allocatable_pvs, old_le_count,
-                      stripes, stripe_size, NULL, 0u, 0u)) {
-               lv->le_count = old_le_count;
-               lv->size = old_size;
-               stack;
-               return 0;
-       }
-
-       if (!lv_merge_segments(lv)) {
-               log_err("Couldn't merge segments after extending "
-                       "logical volume.");
-               return 0;
-       }
-
-       if (fi->fmt->ops->lv_setup && !fi->fmt->ops->lv_setup(fi, lv)) {
-               stack;
-               return 0;
-       }
-
-       return 1;
-}
-
-int lv_extend_mirror(struct format_instance *fid,
-                    struct logical_volume *lv,
-                    struct physical_volume *mirrored_pv,
-                    uint32_t mirrored_pe,
-                    uint32_t extents, struct list *allocatable_pvs,
-                    uint32_t status)
-{
-       uint32_t old_le_count = lv->le_count;
-       uint64_t old_size = lv->size;
-
-       lv->le_count += extents;
-       lv->size += (uint64_t) extents *lv->vg->extent_size;
-
-       if (!_allocate(lv->vg, lv, allocatable_pvs, old_le_count,
-                      1, extents, mirrored_pv, mirrored_pe, status)) {
-               lv->le_count = old_le_count;
-               lv->size = old_size;
-               stack;
-               return 0;
-       }
-
-       if (fid->fmt->ops->lv_setup && !fid->fmt->ops->lv_setup(fid, lv)) {
-               stack;
-               return 0;
-       }
-
-       return 1;
-}
-
 int lv_remove(struct volume_group *vg, struct logical_volume *lv)
 {
        struct list *segh;
index 81cbd924df759022f12fc83c16727d8ea45d7615..decd7051eff4da17585284352a007581965ea028 100644 (file)
 #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;
 }
-
index 6bd9a2006aa25ed29403063cc15bf9f779317c05..dcefe6ebd63e2f0ad264ef14254b0c45d9969c8e 100644 (file)
@@ -53,6 +53,7 @@
 #define SNAPSHOT               0x00001000      /* LV - tmp internal use only */
 #define PVMOVE                 0x00002000      /* VG LV SEG */
 #define LOCKED                 0x00004000      /* LV */
+#define MIRRORED               0x00008000      /* LV - internal use only */
 
 #define LVM_READ               0x00000100      /* LV VG */
 #define LVM_WRITE              0x00000200      /* LV VG */
 #define FMT_UNLIMITED_VOLS     0x00000008      /* Unlimited PVs/LVs? */
 #define FMT_RESTRICTED_LVIDS   0x00000010      /* LVID <= 255 */
 #define FMT_ORPHAN_ALLOCATABLE 0x00000020      /* Orphan PV allocatable? */
-  
+
 typedef enum {
        ALLOC_DEFAULT,
        ALLOC_NEXT_FREE,
        ALLOC_CONTIGUOUS
 } alloc_policy_t;
 
-typedef enum {
-       SEG_STRIPED,
-       SEG_SNAPSHOT,
-       SEG_MIRRORED
-} segment_type_t;
-
 typedef enum {
        AREA_PV,
        AREA_LV
@@ -194,11 +189,12 @@ struct volume_group {
        struct list tags;
 };
 
+struct segment_type;
 struct lv_segment {
        struct list list;
        struct logical_volume *lv;
 
-       segment_type_t type;
+       struct segment_type *segtype;
        uint32_t le;
        uint32_t len;
 
@@ -407,8 +403,10 @@ struct logical_volume *lv_create(struct format_instance *fi,
                                 const char *name,
                                 uint32_t status,
                                 alloc_policy_t alloc,
+                                struct segment_type *segtype,
                                 uint32_t stripes,
                                 uint32_t stripe_size,
+                                uint32_t mirrors,
                                 uint32_t extents,
                                 struct volume_group *vg,
                                 struct list *allocatable_pvs);
@@ -424,18 +422,13 @@ struct logical_volume *lv_create_empty(struct format_instance *fi,
 int lv_reduce(struct format_instance *fi,
              struct logical_volume *lv, uint32_t extents);
 
-int lv_extend(struct format_instance *fi,
+int lv_extend(struct format_instance *fid,
              struct logical_volume *lv,
-             uint32_t stripes,
-             uint32_t stripe_size,
-             uint32_t extents, struct list *allocatable_pvs);
-
-int lv_extend_mirror(struct format_instance *fid,
-                    struct logical_volume *lv,
-                    struct physical_volume *mirrored_pv,
-                    uint32_t mirrored_pe,
-                    uint32_t extents, struct list *allocatable_pvs,
-                    uint32_t status);
+             struct segment_type *segtype,
+             uint32_t stripes, uint32_t stripe_size,
+             uint32_t mirrors, uint32_t extents,
+             struct physical_volume *mirrored_pv, uint32_t mirrored_pe,
+             uint32_t status, struct list *allocatable_pvs);
 
 /* lv must be part of vg->lvs */
 int lv_remove(struct volume_group *vg, struct logical_volume *lv);
index ac777d54aa63c0e4d012aa75affd210745bb1a9e..5e058c16f1257ab52dee679d56eafe7f3a669b81 100644 (file)
@@ -16,6 +16,8 @@
 #include "lib.h"
 #include "metadata.h"
 #include "toolcontext.h"
+#include "segtypes.h"
+#include "display.h"
 
 /* 
  * Replace any LV segments on given PV with temporary mirror.
@@ -33,6 +35,12 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
        struct lv_list *lvl;
        int lv_used = 0;
        uint32_t s, start_le, extent_count = 0u;
+       struct segment_type *segtype;
+
+       if (!(segtype = get_segtype_from_string(lv->vg->cmd, "mirror"))) {
+               stack;
+               return 0;
+       }
 
        list_iterate(segh, &lv->segments) {
                seg = list_item(segh, struct lv_segment);
@@ -52,11 +60,11 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
                        }
 
                        start_le = lv_mirr->le_count;
-                       if (!lv_extend_mirror(lv->vg->fid, lv_mirr,
-                                             seg->area[s].u.pv.pv,
-                                             seg->area[s].u.pv.pe,
-                                             seg->area_len, allocatable_pvs,
-                                             PVMOVE)) {
+                       if (!lv_extend(lv->vg->fid, lv_mirr, segtype, 1,
+                                      seg->area_len, 0u, seg->area_len,
+                                      seg->area[s].u.pv.pv,
+                                      seg->area[s].u.pv.pe,
+                                      PVMOVE, allocatable_pvs)) {
                                log_error("Allocation for temporary "
                                          "pvmove LV failed");
                                return 0;
@@ -98,13 +106,14 @@ int remove_pvmove_mirrors(struct volume_group *vg,
                                        continue;
 
                                if (!(mir_seg = find_seg_by_le(lv_mirr,
-                                                              seg->area[s].u.
-                                                              lv.le))) {
+                                                              seg->area[s].
+                                                              u.lv.le))) {
                                        log_error("No segment found with LE");
                                        return 0;
                                }
 
-                               if (mir_seg->type != SEG_MIRRORED ||
+                               if ((!(mir_seg->segtype->flags
+                                      & SEG_AREAS_MIRRORED)) ||
                                    !(mir_seg->status & PVMOVE) ||
                                    mir_seg->le != seg->area[s].u.lv.le ||
                                    mir_seg->area_count != 2 ||
@@ -122,7 +131,13 @@ int remove_pvmove_mirrors(struct volume_group *vg,
                                seg->area[s].u.pv.pv = mir_seg->area[c].u.pv.pv;
                                seg->area[s].u.pv.pe = mir_seg->area[c].u.pv.pe;
 
-                               mir_seg->type = SEG_STRIPED;
+                               if (!
+                                   (mir_seg->segtype =
+                                    get_segtype_from_string(vg->cmd,
+                                                            "striped"))) {
+                                       log_error("Missing striped segtype");
+                                       return 0;
+                               }
                                mir_seg->area_count = 1;
 
                                lv1->status &= ~LOCKED;
@@ -141,7 +156,7 @@ struct physical_volume *get_pvmove_pv_from_lv_mirr(struct logical_volume
 
        list_iterate(segh, &lv_mirr->segments) {
                seg = list_item(segh, struct lv_segment);
-               if (seg->type != SEG_MIRRORED)
+               if (!(seg->segtype->flags & SEG_AREAS_MIRRORED))
                        continue;
                if (seg->area[0].type != AREA_PV)
                        continue;
diff --git a/lib/metadata/segtypes.c b/lib/metadata/segtypes.c
new file mode 100644 (file)
index 0000000..0024e29
--- /dev/null
@@ -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 (file)
index 0000000..3ebb2c7
--- /dev/null
@@ -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 (file)
index 0000000..1c92c6a
--- /dev/null
@@ -0,0 +1 @@
+init_segtype
diff --git a/lib/mirror/Makefile.in b/lib/mirror/Makefile.in
new file mode 100644 (file)
index 0000000..66f33d5
--- /dev/null
@@ -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 (file)
index 0000000..846297c
--- /dev/null
@@ -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;
+}
index 00f5bbce67c93c485d7c0c9d54d097759bff3ba5..485bdd118e483c248caf29328efc7eb2e7f23495 100644 (file)
@@ -21,6 +21,7 @@
 #include "lvm-string.h"
 #include "display.h"
 #include "activate.h"
+#include "segtypes.h"
 
 /* 
  * For macro use
@@ -329,7 +330,7 @@ static int _segtype_disp(struct report_handle *rh, struct field *field,
        if (seg->area_count == 1)
                field->report_string = "linear";
        else
-               field->report_string = get_segtype_string(seg->type);
+               field->report_string = seg->segtype->ops->name(seg);
        field->sort_value = (const void *) field->report_string;
 
        return 1;
diff --git a/lib/snapshot/.exported_symbols b/lib/snapshot/.exported_symbols
new file mode 100644 (file)
index 0000000..1c92c6a
--- /dev/null
@@ -0,0 +1 @@
+init_segtype
diff --git a/lib/snapshot/Makefile.in b/lib/snapshot/Makefile.in
new file mode 100644 (file)
index 0000000..8766161
--- /dev/null
@@ -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 (file)
index 0000000..feb5faa
--- /dev/null
@@ -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 (file)
index 0000000..3b06c3d
--- /dev/null
@@ -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;
+}
index afe4f0a04d99d68c041d67c67236dd11a316c9ba..9385ea4006d0f94339d03103f376933257482472 100644 (file)
@@ -33,6 +33,10 @@ struct lvcreate_params {
        uint32_t stripe_size;
        uint32_t chunk_size;
 
+       uint32_t mirrors;
+
+       struct segment_type *segtype;
+
        /* size */
        uint32_t extents;
        uint64_t size;
@@ -188,6 +192,11 @@ static int _read_stripe_params(struct lvcreate_params *lp,
                lp->stripes = arg_uint_value(cmd, stripes_ARG, 1);
                if (lp->stripes == 1)
                        log_print("Redundant stripes argument: default is 1");
+               else if (!(lp->segtype = get_segtype_from_string(cmd,
+                                                                "striped"))) {
+                       stack;
+                       return 0;
+               }
        }
 
        if (arg_count(cmd, stripesize_ARG)) {
@@ -466,8 +475,9 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
                status |= LVM_WRITE;
        }
 
-       if (!(lv = lv_create(vg->fid, lp->lv_name, status, alloc, lp->stripes,
-                            lp->stripe_size, lp->extents, vg, pvh)))
+       if (!(lv = lv_create(vg->fid, lp->lv_name, status, alloc, lp->segtype,
+                            lp->stripes, lp->stripe_size, lp->mirrors,
+                            lp->extents, vg, pvh)))
                return 0;
 
        if (lp->read_ahead) {
index 4efef72cff58921b2ecc8b76843a22d131abd8c2..168e573852c9d576e07a9e073394f4cdc6c6b531 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.   
  * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
  * This file is part of LVM2.
  *
  * This copyrighted material is made available to anyone wishing to use,
index a4c0b19de46dcfeb96c342343b8ece33c491820e..f818c887308943d5b33611c9482e6f32a76430ed 100644 (file)
@@ -39,6 +39,7 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
        struct lv_segment *seg;
        uint32_t seg_extents;
        uint32_t sz, str;
+       struct segment_type *segtype;
 
        enum {
                LV_ANY = 0,
@@ -196,8 +197,8 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
        /* If extending, find stripes, stripesize & size of last segment */
        if (extents > lv->le_count && !(stripes == 1 || (stripes > 1 && ssize))) {
                list_iterate_items(seg, &lv->segments) {
-                       if (seg->type != SEG_STRIPED)
-                               continue;
+                       if (strcmp(seg->segtype->ops->name(seg), "striped"))
+                               continue;       /* Not striped */
 
                        sz = seg->stripe_size;
                        str = seg->area_count;
@@ -243,7 +244,7 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
                list_iterate_items(seg, &lv->segments) {
                        seg_extents = seg->len;
 
-                       if (seg->type == SEG_STRIPED) {
+                       if (seg->segtype->flags & SEG_AREAS_STRIPED) {
                                seg_stripesize = seg->stripe_size;
                                seg_stripes = seg->area_count;
                        }
@@ -354,9 +355,14 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
                          display_size(cmd, (uint64_t)
                                       extents * (vg->extent_size / 2),
                                       SIZE_SHORT));
+               if (!(segtype = get_segtype_from_string(lv->vg->cmd,
+                                                       "striped"))) {
+                       stack;
+                       return 0;
+               }
 
-               if (!lv_extend(vg->fid, lv, stripes, ssize,
-                              extents - lv->le_count, pvh))
+               if (!lv_extend(vg->fid, lv, segtype, stripes, ssize, 0u,
+                              extents - lv->le_count, NULL, 0u, 0u, pvh))
                        goto error;
        }
 
index a68d9cc6db06a8dafd18f6e51180f34418555aa1..9e447e90f9f8716b3cba181a2af7707db2fd32e7 100644 (file)
@@ -43,6 +43,7 @@
 #include "lvm-file.h"
 #include "lvm-string.h"
 #include "pool.h"
+#include "segtypes.h"
 #include "str_list.h"
 #include "toolcontext.h"
 #include "toollib.h"
index a298c64d1d9a2fe6b8387b127bd3c1c34344892c..a8f7cff0c4685a3ea9a673c7bbfca3b1945a4a5a 100644 (file)
@@ -51,8 +51,7 @@ static int _activate_lvs_in_vg(struct cmd_context *cmd,
        return count;
 }
 
-static int _vgchange_available(struct cmd_context *cmd,
-                              struct volume_group *vg)
+static int _vgchange_available(struct cmd_context *cmd, struct volume_group *vg)
 {
        int lv_open, active;
        int available = !strcmp(arg_str_value(cmd, available_ARG, "n"), "y");
This page took 0.161345 seconds and 5 git commands to generate.