summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlasdair Kergon <agk@redhat.com>2004-06-07 19:10:21 +0000
committerAlasdair Kergon <agk@redhat.com>2004-06-07 19:10:21 +0000
commitd0a7ac6b7431c2de96a19e16e5ae9b7c574fcf4f (patch)
treedbed55da1423f7eee4df53bdb8cab7e2e40e35b2
parentff9a238fbdb640ad47737103b92c4300e077856e (diff)
downloadlvm2-d0a7ac6b7431c2de96a19e16e5ae9b7c574fcf4f.tar.gz
Add read-only GFS pool support.
-rw-r--r--Makefile.in1
-rw-r--r--WHATS_NEW1
-rwxr-xr-xconfigure34
-rw-r--r--configure.in23
-rw-r--r--include/.symlinks1
-rw-r--r--lib/Makefile.in12
-rw-r--r--lib/commands/toolcontext.c11
-rw-r--r--lib/format_pool/.exported_symbols1
-rw-r--r--lib/format_pool/Makefile.in37
-rw-r--r--lib/format_pool/disk_rep.c385
-rw-r--r--lib/format_pool/disk_rep.h178
-rw-r--r--lib/format_pool/format_pool.c361
-rw-r--r--lib/format_pool/format_pool.h25
-rw-r--r--lib/format_pool/import_export.c309
-rw-r--r--lib/format_pool/pool_label.c108
-rw-r--r--lib/format_pool/pool_label.h23
16 files changed, 1506 insertions, 4 deletions
diff --git a/Makefile.in b/Makefile.in
index 489ba3bb4..f7b4d5238 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -26,6 +26,7 @@ SUBDIRS += lib tools
ifeq ($(MAKECMDGOALS),distclean)
SUBDIRS += lib/format1 \
+ lib/format_pool \
lib/mirror \
lib/snapshot \
po \
diff --git a/WHATS_NEW b/WHATS_NEW
index a2725f9c0..4d5fe2fa5 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.00.17 -
=============================
+ Add read-only GFS pool support.
Add lvm2create_initrd script from http://poochiereds.net/svn/lvm2/
Fix rounding of large diplayed sizes.
Suppress decimal point when using units of sectors/bytes.
diff --git a/configure b/configure
index 79859784f..22487fb85 100755
--- a/configure
+++ b/configure
@@ -309,7 +309,7 @@ ac_includes_default="\
#endif"
ac_default_prefix=/usr
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS AWK CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE RANLIB ac_ct_RANLIB CPP EGREP build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os MSGFMT JOBS STATIC_LINK LVM1 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_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 POOL 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,8 @@ Optional Packages:
--with-group=GROUP Set the group owner of installed files
--with-lvm1=TYPE LVM1 metadata support: internal/shared/none
TYPE=internal
+ --with-pool=TYPE GFS pool 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
@@ -3970,6 +3972,29 @@ if test x$LVM1 = xinternal; then
CFLAGS="$CFLAGS -DLVM1_INTERNAL"
fi
+
+# Check whether --with-pool or --without-pool was given.
+if test "${with_pool+set}" = set; then
+ withval="$with_pool"
+ POOL="$withval"
+else
+ POOL="internal"
+fi;
+
+if [ "x$POOL" != xnone -a "x$POOL" != xinternal -a "x$POOL" != xshared ];
+ then { { echo "$as_me:$LINENO: error: --with-pool parameter invalid
+" >&5
+echo "$as_me: error: --with-pool parameter invalid
+" >&2;}
+ { (exit 1); exit 1; }; }
+ exit
+fi;
+
+if test x$POOL = xinternal; then
+ CFLAGS="$CFLAGS -DPOOL_INTERNAL"
+fi
+
+
# Check whether --enable-jobs or --disable-jobs was given.
if test "${enable_jobs+set}" = set; then
enableval="$enable_jobs"
@@ -4662,7 +4687,7 @@ else
HAVE_LIBDL=no
fi
-if [ \( "x$LVM1" = xshared -o \
+if [ \( "x$LVM1" = xshared -o "x$POOL" = 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
@@ -5169,7 +5194,8 @@ fi
- 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"
+
+ ac_config_files="$ac_config_files Makefile make.tmpl doc/Makefile include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/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
@@ -5726,6 +5752,7 @@ 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/format_pool/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/format_pool/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" ;;
@@ -5853,6 +5880,7 @@ s,@MSGFMT@,$MSGFMT,;t t
s,@JOBS@,$JOBS,;t t
s,@STATIC_LINK@,$STATIC_LINK,;t t
s,@LVM1@,$LVM1,;t t
+s,@POOL@,$POOL,;t t
s,@SNAPSHOTS@,$SNAPSHOTS,;t t
s,@MIRRORS@,$MIRRORS,;t t
s,@OWNER@,$OWNER,;t t
diff --git a/configure.in b/configure.in
index e0a163696..2ae7629ea 100644
--- a/configure.in
+++ b/configure.in
@@ -121,6 +121,25 @@ if test x$LVM1 = xinternal; then
CFLAGS="$CFLAGS -DLVM1_INTERNAL"
fi
+dnl -- format_pool inclusion type
+AC_ARG_WITH(pool,
+ [ --with-pool=TYPE GFS pool metadata support: internal/shared/none
+ [TYPE=internal] ],
+ [ POOL="$withval" ],
+ [ POOL="internal" ])
+
+if [[ "x$POOL" != xnone -a "x$POOL" != xinternal -a "x$POOL" != xshared ]];
+ then AC_MSG_ERROR(
+--with-pool parameter invalid
+)
+ exit
+fi;
+
+if test x$POOL = xinternal; then
+ CFLAGS="$CFLAGS -DPOOL_INTERNAL"
+fi
+
+
AC_ARG_ENABLE(jobs, [ --enable-jobs=NUM Number of jobs to run simultaneously], JOBS=-j$enableval, JOBS=-j2)
dnl -- snapshots inclusion type
@@ -246,7 +265,7 @@ else
fi
dnl Check for shared/static conflicts
-if [[ \( "x$LVM1" = xshared -o \
+if [[ \( "x$LVM1" = xshared -o "x$POOL" = xshared -o \
"x$SNAPSHOTS" = xshared -o "x$MIRRORS" = xshared \
\) -a "x$STATIC_LINK" = xyes ]];
then AC_MSG_ERROR(
@@ -325,6 +344,7 @@ fi
AC_SUBST(JOBS)
AC_SUBST(STATIC_LINK)
AC_SUBST(LVM1)
+AC_SUBST(POOL)
AC_SUBST(SNAPSHOTS)
AC_SUBST(MIRRORS)
AC_SUBST(OWNER)
@@ -360,6 +380,7 @@ doc/Makefile \
include/Makefile \
lib/Makefile \
lib/format1/Makefile \
+lib/format_pool/Makefile \
lib/mirror/Makefile \
lib/snapshot/Makefile \
man/Makefile \
diff --git a/include/.symlinks b/include/.symlinks
index 7c350da62..74987de7c 100644
--- a/include/.symlinks
+++ b/include/.symlinks
@@ -21,6 +21,7 @@
../lib/filters/filter-sysfs.h
../lib/filters/filter.h
../lib/format1/format1.h
+../lib/format_pool/format_pool.h
../lib/format_text/format-text.h
../lib/format_text/text_export.h
../lib/format_text/text_import.h
diff --git a/lib/Makefile.in b/lib/Makefile.in
index c1f61f0d8..dd370ad3a 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -20,6 +20,10 @@ ifeq ("@LVM1@", "shared")
SUBDIRS = format1
endif
+ifeq ("@POOL@", "shared")
+ SUBDIRS += format_pool
+endif
+
ifeq ("@SNAPSHOTS@", "shared")
SUBDIRS += snapshot
endif
@@ -92,6 +96,14 @@ ifeq ("@LVM1@", "internal")
format1/vg_number.c
endif
+ifeq ("@POOL@", "internal")
+ SOURCES +=\
+ format_pool/disk_rep.c \
+ format_pool/format_pool.c \
+ format_pool/import_export.c \
+ format_pool/pool_label.c
+endif
+
ifeq ("@SNAPSHOTS@", "internal")
SOURCES += snapshot/snapshot.c
endif
diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index ff8a90b76..423fefea8 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -44,6 +44,10 @@
#include "format1.h"
#endif
+#ifdef POOL_INTERNAL
+#include "format_pool.h"
+#endif
+
#include <locale.h>
#include <sys/stat.h>
#include <sys/utsname.h>
@@ -606,6 +610,13 @@ static int _init_formats(struct cmd_context *cmd)
list_add(&cmd->formats, &fmt->list);
#endif
+#ifdef POOL_INTERNAL
+ if (!(fmt = init_pool_format(cmd)))
+ return 0;
+ fmt->library = NULL;
+ list_add(&cmd->formats, &fmt->list);
+#endif
+
#ifdef HAVE_LIBDL
/* Load any formats in shared libs */
if ((cn = find_config_node(cmd->cft->root, "global/format_libraries"))) {
diff --git a/lib/format_pool/.exported_symbols b/lib/format_pool/.exported_symbols
new file mode 100644
index 000000000..e9fac2e80
--- /dev/null
+++ b/lib/format_pool/.exported_symbols
@@ -0,0 +1 @@
+init_format
diff --git a/lib/format_pool/Makefile.in b/lib/format_pool/Makefile.in
new file mode 100644
index 000000000..1c703fc70
--- /dev/null
+++ b/lib/format_pool/Makefile.in
@@ -0,0 +1,37 @@
+#
+# 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 =\
+ disk_rep.c \
+ format_pool.c \
+ import_export.c \
+ pool_label.c
+
+LIB_SHARED = liblvm2formatpool.so
+
+include ../../make.tmpl
+
+.PHONY: install
+
+install: liblvm2format_pool.so
+ $(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
+ $(libdir)/liblvm2formatpool.so.$(LIB_VERSION)
+ $(LN_S) -f liblvm2formatpool.so.$(LIB_VERSION) \
+ $(libdir)/liblvm2formatpool.so
+
+
diff --git a/lib/format_pool/disk_rep.c b/lib/format_pool/disk_rep.c
new file mode 100644
index 000000000..b3a678a80
--- /dev/null
+++ b/lib/format_pool/disk_rep.c
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 1997-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 "label.h"
+#include "metadata.h"
+#include "lvmcache.h"
+#include "filter.h"
+#include "list.h"
+#include "xlate.h"
+
+#include "disk_rep.h"
+
+/* FIXME: memcpy might not be portable */
+#define CPIN_8(x, y, z) {memcpy((x), (y), (z));}
+#define CPOUT_8(x, y, z) {memcpy((y), (x), (z));}
+#define CPIN_16(x, y) {(x) = xlate16_be((y));}
+#define CPOUT_16(x, y) {(y) = xlate16_be((x));}
+#define CPIN_32(x, y) {(x) = xlate32_be((y));}
+#define CPOUT_32(x, y) {(y) = xlate32_be((x));}
+#define CPIN_64(x, y) {(x) = xlate64_be((y));}
+#define CPOUT_64(x, y) {(y) = xlate64_be((x));}
+
+static int __read_pool_disk(const struct format_type *fmt, struct device *dev,
+ struct pool *mem, struct pool_list *pl,
+ const char *vg_name)
+{
+ char buf[512];
+
+ /* FIXME: Need to check the cache here first */
+ if (!dev_read(dev, UINT64_C(0), 512, buf)) {
+ log_very_verbose("Failed to read PV data from %s",
+ dev_name(dev));
+ return 0;
+ }
+
+ if (!read_pool_label(pl, fmt->labeller, dev, buf, NULL)) {
+ stack;
+ return 0;
+ }
+
+ return 1;
+}
+
+static void _add_pl_to_list(struct list *head, struct pool_list *data)
+{
+ struct list *pvdh;
+ struct pool_list *pl;
+
+ list_iterate(pvdh, head) {
+ pl = list_item(pvdh, struct pool_list);
+
+ if (id_equal(&data->pv_uuid, &pl->pv_uuid)) {
+ char uuid[ID_LEN + 7];
+
+ id_write_format(&pl->pv_uuid, uuid, ID_LEN + 7);
+
+ if (MAJOR(data->dev->dev) != md_major()) {
+ log_very_verbose("Ignoring duplicate PV %s on "
+ "%s", uuid,
+ dev_name(data->dev));
+ return;
+ }
+ log_very_verbose("Duplicate PV %s - using md %s",
+ uuid, dev_name(data->dev));
+ list_del(pvdh);
+ break;
+ }
+ }
+ list_add(head, &data->list);
+}
+
+int read_pool_label(struct pool_list *pl, struct labeller *l,
+ struct device *dev, char *buf, struct label **label)
+{
+ struct lvmcache_info *info;
+ struct id pvid;
+ struct id vgid;
+ char uuid[ID_LEN + 7];
+ struct pool_disk *pd = &pl->pd;
+
+ pool_label_in(pd, buf);
+
+ get_pool_pv_uuid(&pvid, pd);
+ id_write_format(&pvid, uuid, ID_LEN + 7);
+ log_debug("Calculated uuid %s for %s", uuid, dev_name(dev));
+
+ get_pool_vg_uuid(&vgid, pd);
+ id_write_format(&vgid, uuid, ID_LEN + 7);
+ log_debug("Calculated uuid %s for %s", uuid, pd->pl_pool_name);
+
+ if (!(info = lvmcache_add(l, (char *) &pvid, dev, pd->pl_pool_name,
+ (char *) &vgid))) {
+ stack;
+ return 0;
+ }
+ if (label)
+ *label = info->label;
+
+ info->device_size = xlate32_be(pd->pl_blocks) << SECTOR_SHIFT;
+ list_init(&info->mdas);
+
+ info->status &= ~CACHE_INVALID;
+
+ pl->dev = dev;
+ pl->pv = NULL;
+ memcpy(&pl->pv_uuid, &pvid, sizeof(pvid));
+
+ return 1;
+}
+
+/**
+ * pool_label_out - copies a pool_label_t into a char buffer
+ * @pl: ptr to a pool_label_t struct
+ * @buf: ptr to raw space where label info will be copied
+ *
+ * This function is important because it takes care of all of
+ * the endian issues when copying to disk. This way, when
+ * machines of different architectures are used, they will
+ * be able to interpret ondisk labels correctly. Always use
+ * this function before writing to disk.
+ */
+void pool_label_out(struct pool_disk *pl, char *buf)
+{
+ struct pool_disk *bufpl = (struct pool_disk *) buf;
+
+ CPOUT_64(pl->pl_magic, bufpl->pl_magic);
+ CPOUT_64(pl->pl_pool_id, bufpl->pl_pool_id);
+ CPOUT_8(pl->pl_pool_name, bufpl->pl_pool_name, POOL_NAME_SIZE);
+ CPOUT_32(pl->pl_version, bufpl->pl_version);
+ CPOUT_32(pl->pl_subpools, bufpl->pl_subpools);
+ CPOUT_32(pl->pl_sp_id, bufpl->pl_sp_id);
+ CPOUT_32(pl->pl_sp_devs, bufpl->pl_sp_devs);
+ CPOUT_32(pl->pl_sp_devid, bufpl->pl_sp_devid);
+ CPOUT_32(pl->pl_sp_type, bufpl->pl_sp_type);
+ CPOUT_64(pl->pl_blocks, bufpl->pl_blocks);
+ CPOUT_32(pl->pl_striping, bufpl->pl_striping);
+ CPOUT_32(pl->pl_sp_dmepdevs, bufpl->pl_sp_dmepdevs);
+ CPOUT_32(pl->pl_sp_dmepid, bufpl->pl_sp_dmepid);
+ CPOUT_32(pl->pl_sp_weight, bufpl->pl_sp_weight);
+ CPOUT_32(pl->pl_minor, bufpl->pl_minor);
+ CPOUT_32(pl->pl_padding, bufpl->pl_padding);
+ CPOUT_8(pl->pl_reserve, bufpl->pl_reserve, 184);
+}
+
+/**
+ * pool_label_in - copies a char buffer into a pool_label_t
+ * @pl: ptr to a pool_label_t struct
+ * @buf: ptr to raw space where label info is copied from
+ *
+ * This function is important because it takes care of all of
+ * the endian issues when information from disk is about to be
+ * used. This way, when machines of different architectures
+ * are used, they will be able to interpret ondisk labels
+ * correctly. Always use this function before using labels that
+ * were read from disk.
+ */
+void pool_label_in(struct pool_disk *pl, char *buf)
+{
+ struct pool_disk *bufpl = (struct pool_disk *) buf;
+
+ CPIN_64(pl->pl_magic, bufpl->pl_magic);
+ CPIN_64(pl->pl_pool_id, bufpl->pl_pool_id);
+ CPIN_8(pl->pl_pool_name, bufpl->pl_pool_name, POOL_NAME_SIZE);
+ CPIN_32(pl->pl_version, bufpl->pl_version);
+ CPIN_32(pl->pl_subpools, bufpl->pl_subpools);
+ CPIN_32(pl->pl_sp_id, bufpl->pl_sp_id);
+ CPIN_32(pl->pl_sp_devs, bufpl->pl_sp_devs);
+ CPIN_32(pl->pl_sp_devid, bufpl->pl_sp_devid);
+ CPIN_32(pl->pl_sp_type, bufpl->pl_sp_type);
+ CPIN_64(pl->pl_blocks, bufpl->pl_blocks);
+ CPIN_32(pl->pl_striping, bufpl->pl_striping);
+ CPIN_32(pl->pl_sp_dmepdevs, bufpl->pl_sp_dmepdevs);
+ CPIN_32(pl->pl_sp_dmepid, bufpl->pl_sp_dmepid);
+ CPIN_32(pl->pl_sp_weight, bufpl->pl_sp_weight);
+ CPIN_32(pl->pl_minor, bufpl->pl_minor);
+ CPIN_32(pl->pl_padding, bufpl->pl_padding);
+ CPIN_8(pl->pl_reserve, bufpl->pl_reserve, 184);
+}
+
+static char _calc_char(unsigned int id)
+{
+ /*
+ * [0-9A-Za-z!#] - 64 printable chars (6-bits)
+ */
+
+ if (id < 10)
+ return id + 48;
+ if (id < 36)
+ return (id - 10) + 65;
+ if (id < 62)
+ return (id - 36) + 97;
+ if (id == 62)
+ return '!';
+ if (id == 63)
+ return '#';
+
+ return '%';
+}
+
+void get_pool_uuid(char *uuid, uint64_t poolid, uint32_t spid, uint32_t devid)
+{
+ int i;
+ unsigned shifter = 0x003F;
+
+ assert(ID_LEN == 32);
+ memset(uuid, 0, ID_LEN);
+ strcat(uuid, "POOL0000000000");
+
+ /* We grab the entire 64 bits (+2 that get shifted in) */
+ for (i = 13; i < 24; i++) {
+ uuid[i] = _calc_char(((unsigned) poolid) & shifter);
+ poolid = poolid >> 6;
+ }
+
+ /* We grab the entire 32 bits (+4 that get shifted in) */
+ for (i = 24; i < 30; i++) {
+ uuid[i] = _calc_char((unsigned) (spid & shifter));
+ spid = spid >> 6;
+ }
+
+ /*
+ * Since we can only have 128 devices, we only worry about the
+ * last 12 bits
+ */
+ for (i = 30; i < 32; i++) {
+ uuid[i] = _calc_char((unsigned) (devid & shifter));
+ devid = devid >> 6;
+ }
+
+}
+
+static int _read_vg_pds(const struct format_type *fmt, struct pool *mem,
+ struct lvmcache_vginfo *vginfo, struct list *head,
+ uint32_t *devcount)
+{
+
+ struct list *vgih = NULL;
+ struct device *dev;
+ struct pool_list *pl = NULL;
+ struct pool *tmpmem = NULL;
+
+ uint32_t sp_count = 0;
+ uint32_t *sp_devs = NULL;
+ int i;
+
+ /* FIXME: maybe should return a different error in memory
+ * allocation failure */
+ if (!(tmpmem = pool_create(512))) {
+ stack;
+ return 0;
+ }
+
+ list_iterate(vgih, &vginfo->infos) {
+ dev = list_item(vgih, struct lvmcache_info)->dev;
+ if (dev &&
+ !(pl = read_pool_disk(fmt, dev, mem, vginfo->vgname)))
+ break;
+ /*
+ * We need to keep track of the total expected number
+ * of devices per subpool
+ */
+ if (!sp_count) {
+ sp_count = pl->pd.pl_subpools;
+ if (!(sp_devs =
+ pool_zalloc(tmpmem,
+ sizeof(uint32_t) * sp_count))) {
+ log_error("Unable to allocate %d 32-bit uints",
+ sp_count);
+ pool_destroy(tmpmem);
+ return 0;
+ }
+ }
+ /*
+ * watch out for a pool label with a different subpool
+ * count than the original - give up if it does
+ */
+ if (sp_count != pl->pd.pl_subpools)
+ break;
+
+ _add_pl_to_list(head, pl);
+
+ if (sp_count > pl->pd.pl_sp_id && sp_devs[pl->pd.pl_sp_id] == 0)
+ sp_devs[pl->pd.pl_sp_id] = pl->pd.pl_sp_devs;
+ }
+
+ *devcount = 0;
+ for (i = 0; i < sp_count; i++) {
+ *devcount += sp_devs[i];
+ }
+
+ pool_destroy(tmpmem);
+
+ if (pl && *pl->pd.pl_pool_name)
+ return 1;
+
+ return 0;
+
+}
+
+int read_pool_pds(const struct format_type *fmt, const char *vg_name,
+ struct pool *mem, struct list *pdhead)
+{
+ struct lvmcache_vginfo *vginfo;
+ uint32_t totaldevs;
+ int full_scan = -1;
+
+ do {
+ /*
+ * If the cache scanning doesn't work, this will never work
+ */
+ if (vg_name && (vginfo = vginfo_from_vgname(vg_name)) &&
+ vginfo->infos.n) {
+
+ if (_read_vg_pds(fmt, mem, vginfo, pdhead, &totaldevs)) {
+ /*
+ * If we found all the devices we were
+ * expecting, return success
+ */
+ if (list_size(pdhead) == totaldevs)
+ return 1;
+
+ /*
+ * accept partial pool if we've done a full
+ * rescan of the cache
+ */
+ if (full_scan > 0)
+ return 1;
+ }
+ }
+ /* Failed */
+ list_init(pdhead);
+
+ full_scan++;
+ if (full_scan > 1) {
+ log_debug("No devices for vg %s found in cache",
+ vg_name);
+ return 0;
+ }
+ lvmcache_label_scan(fmt->cmd, full_scan);
+
+ } while (1);
+
+}
+
+struct pool_list *read_pool_disk(const struct format_type *fmt,
+ struct device *dev, struct pool *mem,
+ const char *vg_name)
+{
+ struct pool_list *pl;
+
+ if (!dev_open(dev)) {
+ stack;
+ return NULL;
+ }
+
+ if (!(pl = pool_zalloc(mem, sizeof(*pl)))) {
+ log_error("Unable to allocate pool list structure");
+ return 0;
+ }
+
+ if (!__read_pool_disk(fmt, dev, mem, pl, vg_name)) {
+ stack;
+ return NULL;
+ }
+
+ if (!dev_close(dev))
+ stack;
+
+ return pl;
+
+}
diff --git a/lib/format_pool/disk_rep.h b/lib/format_pool/disk_rep.h
new file mode 100644
index 000000000..8d09d9617
--- /dev/null
+++ b/lib/format_pool/disk_rep.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 1997-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 DISK_REP_FORMAT_POOL_H
+#define DISK_REP_FORMAT_POOL_H
+
+#include "label.h"
+#include "metadata.h"
+#include "pool.h"
+
+/* From NSP.cf */
+#define NSPMajorVersion 4
+#define NSPMinorVersion 1
+#define NSPUpdateLevel 3
+
+/* From pool_std.h */
+#define POOL_NAME_SIZE (256)
+#define POOL_MAGIC 0x011670
+#define POOL_MAJOR (121)
+#define POOL_MAX_DEVICES 128
+
+/* When checking for version matching, the first two numbers **
+** are important for metadata formats, a.k.a pool labels. **
+** All the numbers are important when checking if the user **
+** space tools match up with the kernel module............. */
+#define POOL_VERSION (NSPMajorVersion << 16 | \
+ NSPMinorVersion << 8 | \
+ NSPUpdateLevel)
+
+/* Pool label is at the head of every pool disk partition */
+#define SIZEOF_POOL_LABEL (8192)
+
+/* in sectors */
+#define POOL_PE_SIZE (SIZEOF_POOL_LABEL >> SECTOR_SHIFT)
+#define POOL_PE_START (SIZEOF_POOL_LABEL >> SECTOR_SHIFT)
+
+/* Helper fxns */
+#define get_pool_vg_uuid(id, pd) do { get_pool_uuid((char *)(id), \
+ (pd)->pl_pool_id, 0, 0); \
+ } while(0)
+#define get_pool_pv_uuid(id, pd) do { get_pool_uuid((char *)(id), \
+ (pd)->pl_pool_id, \
+ (pd)->pl_sp_id, \
+ (pd)->pl_sp_devid); \
+ } while(0)
+#define get_pool_lv_uuid(id, pd) do { get_pool_uuid((char *)&(id)[0], \
+ (pd)->pl_pool_id, 0, 0); \
+ get_pool_uuid((char*)&(id)[1], \
+ (pd)->pl_pool_id, 0, 0); \
+ } while(0)
+
+struct pool_disk;
+struct pool_list;
+struct user_subpool;
+struct user_device;
+
+/* This must be kept up to date with sistina/pool/module/pool_sptypes.h */
+
+/* Generic Labels */
+#define SPTYPE_DATA (0x00000000)
+
+/* GFS specific labels */
+#define SPTYPE_GFS_DATA (0x68011670)
+#define SPTYPE_GFS_JOURNAL (0x69011670)
+
+struct sptype_name {
+ const char *name;
+ uint32_t label;
+};
+
+static const struct sptype_name sptype_names[] = {
+ {"data", SPTYPE_DATA},
+
+ {"gfs_data", SPTYPE_GFS_DATA},
+ {"gfs_journal", SPTYPE_GFS_JOURNAL},
+
+ {"", 0x0} /* This must be the last flag. */
+};
+
+struct pool_disk {
+ uint64_t pl_magic; /* Pool magic number */
+ uint64_t pl_pool_id; /* Unique pool identifier */
+ char pl_pool_name[POOL_NAME_SIZE]; /* Name of pool */
+ uint32_t pl_version; /* Pool version */
+ uint32_t pl_subpools; /* Number of subpools in this pool */
+ uint32_t pl_sp_id; /* Subpool number within pool */
+ uint32_t pl_sp_devs; /* Number of data partitions in this subpool */
+ uint32_t pl_sp_devid; /* Partition number within subpool */
+ uint32_t pl_sp_type; /* Partition type */
+ uint64_t pl_blocks; /* Number of blocks in this partition */
+ uint32_t pl_striping; /* Striping size within subpool */
+ /*
+ * If the number of DMEP devices is zero, then the next field **
+ * ** (pl_sp_dmepid) becomes the subpool ID for redirection. In **
+ * ** other words, if this subpool does not have the capability **
+ * ** to do DMEP, then it must specify which subpool will do it **
+ * ** in it's place
+ */
+
+ /*
+ * While the next 3 field are no longer used, they must stay to keep **
+ * ** backward compatibility...........................................
+ */
+ uint32_t pl_sp_dmepdevs;/* Number of dmep devices in this subpool */
+ uint32_t pl_sp_dmepid; /* Dmep device number within subpool */
+ uint32_t pl_sp_weight; /* if dmep dev, pref to using it */
+
+ uint32_t pl_minor; /* the pool minor number */
+ uint32_t pl_padding; /* reminder - think about alignment */
+
+ /*
+ * Even though we're zeroing out 8k at the front of the disk before
+ * writing the label, putting this in
+ */
+ char pl_reserve[184]; /* bump the structure size out to 512 bytes */
+};
+
+struct pool_list {
+ struct list list;
+ struct pool_disk pd;
+ struct physical_volume *pv;
+ struct id pv_uuid;
+ struct device *dev;
+};
+
+struct user_subpool {
+ uint32_t initialized;
+ uint32_t id;
+ uint32_t striping;
+ uint32_t num_devs;
+ uint32_t type;
+ uint32_t dummy;
+ struct user_device *devs;
+};
+
+struct user_device {
+ uint32_t initialized;
+ uint32_t sp_id;
+ uint32_t devid;
+ uint32_t dummy;
+ uint64_t blocks;
+ struct physical_volume *pv;
+};
+
+int read_pool_label(struct pool_list *pl, struct labeller *l,
+ struct device *dev, char *buf, struct label **label);
+void pool_label_out(struct pool_disk *pl, char *buf);
+void pool_label_in(struct pool_disk *pl, char *buf);
+void get_pool_uuid(char *uuid, uint64_t poolid, uint32_t spid, uint32_t devid);
+int import_pool_vg(struct volume_group *vg, struct pool *mem, struct list *pls);
+int import_pool_lvs(struct volume_group *vg, struct pool *mem,
+ struct list *pls);
+int import_pool_pvs(const struct format_type *fmt, struct volume_group *vg,
+ struct list *pvs, struct pool *mem, struct list *pls);
+int import_pool_pv(const struct format_type *fmt, struct pool *mem,
+ struct volume_group *vg, struct physical_volume *pv,
+ struct pool_list *pl);
+int import_pool_segments(struct list *lvs, struct pool *mem,
+ struct user_subpool *usp, int sp_count);
+int read_pool_pds(const struct format_type *fmt, const char *vgname,
+ struct pool *mem, struct list *head);
+struct pool_list *read_pool_disk(const struct format_type *fmt,
+ struct device *dev, struct pool *mem,
+ const char *vg_name);
+
+#endif /* DISK_REP_POOL_FORMAT_H */
diff --git a/lib/format_pool/format_pool.c b/lib/format_pool/format_pool.c
new file mode 100644
index 000000000..b11d409b6
--- /dev/null
+++ b/lib/format_pool/format_pool.c
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 1997-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 "label.h"
+#include "metadata.h"
+#include "hash.h"
+#include "limits.h"
+#include "list.h"
+#include "display.h"
+#include "toolcontext.h"
+#include "lvmcache.h"
+#include "disk_rep.h"
+#include "format_pool.h"
+#include "pool_label.h"
+
+#define FMT_POOL_NAME "pool"
+
+/* Must be called after pvs are imported */
+static struct user_subpool *_build_usp(struct list *pls, struct pool *mem,
+ int *sps)
+{
+
+ struct list *plhs;
+ struct pool_list *pl;
+ struct user_subpool *usp = NULL, *cur_sp = NULL;
+ struct user_device *cur_dev = NULL;
+
+ /*
+ * FIXME: Need to do some checks here - I'm tempted to add a
+ * user_pool structure and build the entire thing to check against.
+ */
+ list_iterate(plhs, pls) {
+ pl = list_item(plhs, struct pool_list);
+
+ *sps = pl->pd.pl_subpools;
+ if (!usp && (!(usp = pool_zalloc(mem, sizeof(*usp) * (*sps))))) {
+ log_error("Unable to allocate %d subpool structures",
+ *sps);
+ return 0;
+ }
+
+ if (cur_sp != &usp[pl->pd.pl_sp_id]) {
+ cur_sp = &usp[pl->pd.pl_sp_id];
+
+ cur_sp->id = pl->pd.pl_sp_id;
+ cur_sp->striping = pl->pd.pl_striping;
+ cur_sp->num_devs = pl->pd.pl_sp_devs;
+ cur_sp->type = pl->pd.pl_sp_type;
+ cur_sp->initialized = 1;
+ }
+
+ if (!cur_sp->devs &&
+ (!(cur_sp->devs =
+ pool_zalloc(mem,
+ sizeof(*usp->devs) * pl->pd.pl_sp_devs)))) {
+
+ log_error("Unable to allocate %d pool_device "
+ "structures", pl->pd.pl_sp_devs);
+ return 0;
+ }
+ cur_dev = &cur_sp->devs[pl->pd.pl_sp_devid];
+ cur_dev->sp_id = cur_sp->id;
+ cur_dev->devid = pl->pd.pl_sp_id;
+ cur_dev->blocks = pl->pd.pl_blocks;
+ cur_dev->pv = pl->pv;
+ cur_dev->initialized = 1;
+
+ }
+
+ return usp;
+}
+
+static int _check_usp(char *vgname, struct user_subpool *usp, int sp_count)
+{
+ int i, j;
+
+ for (i = 0; i < sp_count; i++) {
+ if (!usp[i].initialized) {
+ log_error("Missing subpool %d in pool %s", i, vgname);
+ return 0;
+ }
+ for (j = 0; j < usp[i].num_devs; j++) {
+ if (!usp[i].devs[j].initialized) {
+ log_error("Missing device %d for subpool %d"
+ " in pool %s", j, i, vgname);
+ return 0;
+ }
+
+ }
+ }
+
+ return 1;
+}
+
+static struct volume_group *_build_vg_from_pds(struct format_instance
+ *fid, struct pool *mem,
+ struct list *pds)
+{
+ struct pool *smem = fid->fmt->cmd->mem;
+ struct volume_group *vg = NULL;
+ struct user_subpool *usp = NULL;
+ int sp_count;
+
+ if (!(vg = pool_zalloc(smem, sizeof(*vg)))) {
+ log_error("Unable to allocate volume group structure");
+ return NULL;
+ }
+
+ vg->cmd = fid->fmt->cmd;
+ vg->fid = fid;
+ vg->name = NULL;
+ vg->status = 0;
+ vg->extent_count = 0;
+ vg->pv_count = 0;
+ vg->lv_count = 0;
+ vg->snapshot_count = 0;
+ vg->seqno = 1;
+ vg->system_id = NULL;
+ list_init(&vg->pvs);
+ list_init(&vg->lvs);
+ list_init(&vg->snapshots);
+ list_init(&vg->tags);
+
+ if (!import_pool_vg(vg, smem, pds)) {
+ stack;
+ return NULL;
+ }
+
+ if (!import_pool_pvs(fid->fmt, vg, &vg->pvs, smem, pds)) {
+ stack;
+ return NULL;
+ }
+
+ if (!import_pool_lvs(vg, smem, pds)) {
+ stack;
+ return NULL;
+ }
+
+ /*
+ * I need an intermediate subpool structure that contains all the
+ * relevant info for this. Then i can iterate through the subpool
+ * structures for checking, and create the segments
+ */
+ if (!(usp = _build_usp(pds, mem, &sp_count))) {
+ stack;
+ return NULL;
+ }
+
+ /*
+ * check the subpool structures - we can't handle partial VGs in
+ * the pool format, so this will error out if we're missing PVs
+ */
+ if (!_check_usp(vg->name, usp, sp_count)) {
+ stack;
+ return NULL;
+ }
+
+ if (!import_pool_segments(&vg->lvs, smem, usp, sp_count)) {
+ stack;
+ return NULL;
+ }
+
+ return vg;
+}
+
+static struct volume_group *_vg_read(struct format_instance *fid,
+ const char *vg_name,
+ struct metadata_area *mda)
+{
+ struct pool *mem = pool_create(1024);
+ struct list pds;
+ struct volume_group *vg = NULL;
+
+ list_init(&pds);
+
+ /* We can safely ignore the mda passed in */
+
+ if (!mem) {
+ stack;
+ return NULL;
+ }
+
+ /* Strip dev_dir if present */
+ vg_name = strip_dir(vg_name, fid->fmt->cmd->dev_dir);
+
+ /* Read all the pvs in the vg */
+ if (!read_pool_pds(fid->fmt, vg_name, mem, &pds)) {
+ stack;
+ goto out;
+ }
+
+ /* Do the rest of the vg stuff */
+ if (!(vg = _build_vg_from_pds(fid, mem, &pds))) {
+ stack;
+ goto out;
+ }
+
+ out:
+ pool_destroy(mem);
+ return vg;
+}
+
+static int _pv_setup(const struct format_type *fmt,
+ uint64_t pe_start, uint32_t extent_count,
+ uint32_t extent_size,
+ int pvmetadatacopies,
+ uint64_t pvmetadatasize, struct list *mdas,
+ struct physical_volume *pv, struct volume_group *vg)
+{
+ return 1;
+}
+
+static int _pv_read(const struct format_type *fmt, const char *pv_name,
+ struct physical_volume *pv, struct list *mdas)
+{
+ struct pool *mem = pool_create(1024);
+ struct pool_list *pl;
+ struct device *dev;
+ int r = 0;
+
+ log_very_verbose("Reading physical volume data %s from disk", pv_name);
+
+ if (!mem) {
+ stack;
+ return 0;
+ }
+
+ if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter))) {
+ stack;
+ goto out;
+ }
+
+ /*
+ * I need to read the disk and populate a pv structure here
+ * I'll probably need to abstract some of this later for the
+ * vg_read code
+ */
+ if (!(pl = read_pool_disk(fmt, dev, mem, NULL))) {
+ stack;
+ goto out;
+ }
+
+ if (!import_pool_pv(fmt, fmt->cmd->mem, NULL, pv, pl)) {
+ stack;
+ goto out;
+ }
+
+ pv->fmt = fmt;
+
+ r = 1;
+
+ out:
+ pool_destroy(mem);
+ return r;
+}
+
+/* *INDENT-OFF* */
+static struct metadata_area_ops _metadata_format_pool_ops = {
+ vg_read:_vg_read,
+};
+/* *INDENT-ON* */
+
+static struct format_instance *_create_instance(const struct format_type *fmt,
+ const char *vgname,
+ void *private)
+{
+ struct format_instance *fid;
+ struct metadata_area *mda;
+
+ if (!(fid = pool_zalloc(fmt->cmd->mem, sizeof(*fid)))) {
+ log_error("Unable to allocate format instance structure for "
+ "pool format");
+ return NULL;
+ }
+
+ fid->fmt = fmt;
+ list_init(&fid->metadata_areas);
+
+ /* Define a NULL metadata area */
+ if (!(mda = pool_zalloc(fmt->cmd->mem, sizeof(*mda)))) {
+ log_error("Unable to allocate metadata area structure "
+ "for pool format");
+ pool_free(fmt->cmd->mem, fid);
+ return NULL;
+ }
+
+ mda->ops = &_metadata_format_pool_ops;
+ mda->metadata_locn = NULL;
+ list_add(&fid->metadata_areas, &mda->list);
+
+ return fid;
+}
+
+static void _destroy_instance(struct format_instance *fid)
+{
+ return;
+}
+
+static void _destroy(const struct format_type *fmt)
+{
+ dbg_free((void *) fmt);
+}
+
+/* *INDENT-OFF* */
+static struct format_handler _format_pool_ops = {
+ pv_read:_pv_read,
+ pv_setup:_pv_setup,
+ create_instance:_create_instance,
+ destroy_instance:_destroy_instance,
+ destroy:_destroy,
+};
+/* *INDENT-ON */
+
+#ifdef POOL_INTERNAL
+struct format_type *init_pool_format(struct cmd_context *cmd)
+#else /* Shared */
+struct format_type *init_format(struct cmd_context *cmd);
+struct format_type *init_format(struct cmd_context *cmd)
+#endif
+{
+ struct format_type *fmt = dbg_malloc(sizeof(*fmt));
+
+ if (!fmt) {
+ log_error("Unable to allocate format type structure for pool "
+ "format");
+ return NULL;
+ }
+
+ fmt->cmd = cmd;
+ fmt->ops = &_format_pool_ops;
+ fmt->name = FMT_POOL_NAME;
+ fmt->alias = NULL;
+ fmt->features = 0;
+ fmt->private = NULL;
+
+ if (!(fmt->labeller = pool_labeller_create(fmt))) {
+ log_error("Couldn't create pool label handler.");
+ return NULL;
+ }
+
+ if (!(label_register_handler(FMT_POOL_NAME, fmt->labeller))) {
+ log_error("Couldn't register pool label handler.");
+ return NULL;
+ }
+
+ return fmt;
+}
diff --git a/lib/format_pool/format_pool.h b/lib/format_pool/format_pool.h
new file mode 100644
index 000000000..61472c7ec
--- /dev/null
+++ b/lib/format_pool/format_pool.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _LVM_FORMAT_POOL_H
+#define _LVM_FORMAT_POOL_H
+
+#include "metadata.h"
+
+#ifdef POOL_INTERNAL
+struct format_type *init_pool_format(struct cmd_context *cmd);
+#endif
+
+#endif
diff --git a/lib/format_pool/import_export.c b/lib/format_pool/import_export.c
new file mode 100644
index 000000000..617521287
--- /dev/null
+++ b/lib/format_pool/import_export.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 1997-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 "label.h"
+#include "metadata.h"
+#include "lvmcache.h"
+#include "disk_rep.h"
+#include "lv_alloc.h"
+#include "str_list.h"
+#include "display.h"
+#include "segtypes.h"
+
+/* This file contains only imports at the moment... */
+
+int import_pool_vg(struct volume_group *vg, struct pool *mem, struct list *pls)
+{
+ struct list *plhs;
+ struct pool_list *pl;
+
+ list_iterate(plhs, pls) {
+ pl = list_item(plhs, struct pool_list);
+
+ vg->extent_count +=
+ ((pl->pd.pl_blocks) / POOL_PE_SIZE);
+
+ vg->pv_count++;
+
+ if (vg->name)
+ continue;
+
+ vg->name = pool_strdup(mem, pl->pd.pl_pool_name);
+ get_pool_vg_uuid(&vg->id, &pl->pd);
+ vg->extent_size = POOL_PE_SIZE;
+ vg->status |= LVM_READ | LVM_WRITE | CLUSTERED | SHARED;
+ vg->free_count = 0;
+ vg->max_lv = 1;
+ vg->max_pv = POOL_MAX_DEVICES;
+ vg->alloc = ALLOC_NORMAL;
+ vg->lv_count = 0;
+ }
+
+ return 1;
+}
+
+int import_pool_lvs(struct volume_group *vg, struct pool *mem, struct list *pls)
+{
+ struct pool_list *pl;
+ struct list *plhs;
+ struct lv_list *lvl = pool_zalloc(mem, sizeof(*lvl));
+ struct logical_volume *lv;
+
+ if (!lvl) {
+ log_error("Unable to allocate lv list structure");
+ return 0;
+ }
+
+ if (!(lvl->lv = pool_zalloc(mem, sizeof(*lvl->lv)))) {
+ log_error("Unable to allocate logical volume structure");
+ return 0;
+ }
+
+ lv = lvl->lv;
+ lv->status = 0;
+ lv->vg = vg;
+ lv->alloc = ALLOC_NORMAL;
+ lv->size = 0;
+ lv->name = NULL;
+ lv->le_count = 0;
+ lv->read_ahead = 0;
+ list_init(&lv->segments);
+ list_init(&lv->tags);
+
+ list_iterate(plhs, pls) {
+ pl = list_item(plhs, struct pool_list);
+
+ lv->size += pl->pd.pl_blocks;
+
+ if (lv->name)
+ continue;
+
+ if (!(lv->name = pool_strdup(mem, pl->pd.pl_pool_name))) {
+ stack;
+ return 0;
+ }
+
+ get_pool_lv_uuid(lv->lvid.id, &pl->pd);
+ log_debug("Calculated lv uuid for lv %s: %s", lv->name,
+ lv->lvid.s);
+
+ lv->status |= VISIBLE_LV | LVM_READ | LVM_WRITE;
+ lv->major = POOL_MAJOR;
+
+ /* for pool a minor of 0 is dynamic */
+ if (pl->pd.pl_minor) {
+ lv->status |= FIXED_MINOR;
+ lv->minor = pl->pd.pl_minor;
+ } else {
+ lv->minor = -1;
+ }
+ list_init(&lv->segments);
+ list_init(&lv->tags);
+ }
+
+ lv->le_count = lv->size / POOL_PE_SIZE;
+ lvl->lv = lv;
+ list_add(&vg->lvs, &lvl->list);
+ vg->lv_count++;
+
+ return 1;
+}
+
+int import_pool_pvs(const struct format_type *fmt, struct volume_group *vg,
+ struct list *pvs, struct pool *mem, struct list *pls)
+{
+ struct pv_list *pvl;
+ struct pool_list *pl;
+ struct list *plhs;
+
+ list_iterate(plhs, pls) {
+ pl = list_item(plhs, struct pool_list);
+
+ if (!(pvl = pool_zalloc(mem, sizeof(*pvl)))) {
+ log_error("Unable to allocate pv list structure");
+ return 0;
+ }
+ if (!(pvl->pv = pool_zalloc(mem, sizeof(*pvl->pv)))) {
+ log_error("Unable to allocate pv structure");
+ return 0;
+ }
+ if (!import_pool_pv(fmt, mem, vg, pvl->pv, pl)) {
+ return 0;
+ }
+ pl->pv = pvl->pv;
+ pvl->mdas = NULL;
+ pvl->alloc_areas = NULL;
+ list_add(pvs, &pvl->list);
+ }
+
+ return 1;
+}
+
+int import_pool_pv(const struct format_type *fmt, struct pool *mem,
+ struct volume_group *vg, struct physical_volume *pv,
+ struct pool_list *pl)
+{
+ struct pool_disk *pd = &pl->pd;
+
+ memset(pv, 0, sizeof(*pv));
+
+ get_pool_pv_uuid(&pv->id, pd);
+ pv->fmt = fmt;
+
+ pv->dev = pl->dev;
+ if (!(pv->vg_name = pool_strdup(mem, pd->pl_pool_name))) {
+ log_error("Unable to duplicate vg_name string");
+ return 0;
+ }
+ pv->status = 0;
+ pv->size = pd->pl_blocks;
+ pv->pe_size = POOL_PE_SIZE;
+ pv->pe_start = POOL_PE_START;
+ pv->pe_count = pv->size / POOL_PE_SIZE;
+ pv->pe_alloc_count = pv->pe_count;
+
+ list_init(&pv->tags);
+
+ return 1;
+}
+
+static const char *_cvt_sptype(uint32_t sptype)
+{
+ int i;
+ for (i = 0; sptype_names[i].name[0]; i++) {
+ if (sptype == sptype_names[i].label) {
+ break;
+ }
+ }
+ log_debug("Found sptype %X and converted it to %s",
+ sptype, sptype_names[i].name);
+ return sptype_names[i].name;
+}
+
+static int _add_stripe_seg(struct pool *mem,
+ struct user_subpool *usp, struct logical_volume *lv,
+ uint32_t *le_cur)
+{
+ struct lv_segment *seg;
+ int j;
+
+ if (!(seg = alloc_lv_segment(mem, usp->num_devs))) {
+ log_error("Unable to allocate striped lv_segment structure");
+ return 0;
+ }
+ if(usp->striping & (usp->striping - 1)) {
+ log_error("Stripe size must be a power of 2");
+ return 0;
+ }
+ seg->stripe_size = usp->striping;
+ seg->status |= 0;
+ seg->le += *le_cur;
+
+ /* add the subpool type to the segment tag list */
+ str_list_add(mem, &seg->tags, _cvt_sptype(usp->type));
+
+ for (j = 0; j < usp->num_devs; j++) {
+ if (!(seg->segtype = get_segtype_from_string(lv->vg->cmd,
+ "striped"))) {
+ stack;
+ return 0;
+ }
+
+ seg->area_len = (usp->devs[j].blocks) / POOL_PE_SIZE;
+ seg->len += seg->area_len;
+ *le_cur += seg->area_len;
+ seg->lv = lv;
+
+ seg->area[j].type = AREA_PV;
+ seg->area[j].u.pv.pv = usp->devs[j].pv;
+ seg->area[j].u.pv.pe = 0;
+ }
+ list_add(&lv->segments, &seg->list);
+ return 1;
+}
+
+static int _add_linear_seg(struct pool *mem,
+ struct user_subpool *usp, struct logical_volume *lv,
+ uint32_t *le_cur)
+{
+ struct lv_segment *seg;
+ int j;
+
+ for (j = 0; j < usp->num_devs; j++) {
+ /* linear segments only have 1 data area */
+ if (!(seg = alloc_lv_segment(mem, 1))) {
+ log_error("Unable to allocate linear lv_segment "
+ "structure");
+ return 0;
+ }
+ seg->stripe_size = usp->striping;
+ seg->le += *le_cur;
+ seg->chunk_size = POOL_PE_SIZE;
+ seg->status |= 0;
+ if (!(seg->segtype = get_segtype_from_string(lv->vg->cmd,
+ "striped"))) {
+ stack;
+ return 0;
+ }
+ /* add the subpool type to the segment tag list */
+ str_list_add(mem, &seg->tags, _cvt_sptype(usp->type));
+
+ seg->lv = lv;
+
+ seg->area_len = (usp->devs[j].blocks) / POOL_PE_SIZE;
+ seg->len = seg->area_len;
+ *le_cur += seg->len;
+ seg->area[0].type = AREA_PV;
+ seg->area[0].u.pv.pv = usp->devs[j].pv;
+ seg->area[0].u.pv.pe = 0;
+ list_add(&lv->segments, &seg->list);
+ }
+ return 1;
+}
+
+int import_pool_segments(struct list *lvs, struct pool *mem,
+ struct user_subpool *usp, int subpools)
+{
+
+ struct list *lvhs;
+ struct lv_list *lvl;
+ struct logical_volume *lv;
+ uint32_t le_cur = 0;
+ int i;
+
+ list_iterate(lvhs, lvs) {
+ lvl = list_item(lvhs, struct lv_list);
+
+ lv = lvl->lv;
+ for (i = 0; i < subpools; i++) {
+ if (usp[i].striping) {
+ if (!_add_stripe_seg(mem, &usp[i], lv, &le_cur)) {
+ stack;
+ return 0;
+ }
+ } else {
+ if (!_add_linear_seg(mem, &usp[i], lv, &le_cur)) {
+ stack;
+ return 0;
+ }
+ }
+ }
+ }
+
+ return 1;
+
+}
diff --git a/lib/format_pool/pool_label.c b/lib/format_pool/pool_label.c
new file mode 100644
index 000000000..adc8c4cd3
--- /dev/null
+++ b/lib/format_pool/pool_label.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 1997-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 "label.h"
+#include "metadata.h"
+#include "xlate.h"
+#include "disk_rep.h"
+#include "pool_label.h"
+
+#include <sys/stat.h>
+#include <fcntl.h>
+
+static void _not_supported(const char *op)
+{
+ log_error("The '%s' operation is not supported for the pool labeller.",
+ op);
+}
+
+static int _can_handle(struct labeller *l, char *buf, uint64_t sector)
+{
+
+ struct pool_disk pd;
+
+ /*
+ * POOL label must always be in first sector
+ */
+ if (sector)
+ return 0;
+
+ pool_label_in(&pd, buf);
+
+ /* can ignore 8 rightmost bits for ondisk format check */
+ if ((pd.pl_magic == POOL_MAGIC) &&
+ (pd.pl_version >> 8 == POOL_VERSION >> 8))
+ return 1;
+
+ return 0;
+}
+
+static int _write(struct label *label, char *buf)
+{
+ _not_supported("write");
+ return 0;
+}
+
+static int _read(struct labeller *l, struct device *dev, char *buf,
+ struct label **label)
+{
+ struct pool_list pl;
+
+ return read_pool_label(&pl, l, dev, buf, label);
+}
+
+static int _initialise_label(struct labeller *l, struct label *label)
+{
+ strcpy(label->type, "POOL");
+
+ return 1;
+}
+
+static void _destroy_label(struct labeller *l, struct label *label)
+{
+ return;
+}
+
+static void _destroy(struct labeller *l)
+{
+ dbg_free(l);
+}
+
+struct label_ops _pool_ops = {
+ can_handle:_can_handle,
+ write:_write,
+ read:_read,
+ verify:_can_handle,
+ initialise_label:_initialise_label,
+ destroy_label:_destroy_label,
+ destroy:_destroy
+};
+
+struct labeller *pool_labeller_create(struct format_type *fmt)
+{
+ struct labeller *l;
+
+ if (!(l = dbg_malloc(sizeof(*l)))) {
+ log_error("Couldn't allocate labeller object.");
+ return NULL;
+ }
+
+ l->ops = &_pool_ops;
+ l->private = (const void *) fmt;
+
+ return l;
+}
diff --git a/lib/format_pool/pool_label.h b/lib/format_pool/pool_label.h
new file mode 100644
index 000000000..3d86502b2
--- /dev/null
+++ b/lib/format_pool/pool_label.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 1997-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_POOL_LABEL_H
+#define _LVM_POOL_LABEL_H
+
+#include "metadata.h"
+
+struct labeller *pool_labeller_create(struct format_type *fmt);
+
+#endif