r418 - in lvm2/trunk: . daemons/clvmd dmeventd/mirror doc
lib/activate lib/cache lib/commands lib/config lib/device
lib/display lib/error lib/filters lib/format1 lib/format_pool
lib/format_text lib/label lib/locking lib/log lib/metadata
lib/mirror lib/misc lib/report lib/snapshot lib/striped
lib/zero man scripts scripts/lvm2create_initrd tools tools/fsadm
Bastian Blank
waldi at alioth.debian.org
Sat Apr 7 16:07:07 UTC 2007
Author: waldi
Date: Sat Apr 7 16:07:03 2007
New Revision: 418
Added:
lvm2/trunk/man/lvmdump.8
Modified:
lvm2/trunk/ (props changed)
lvm2/trunk/Makefile.in
lvm2/trunk/VERSION
lvm2/trunk/WHATS_NEW
lvm2/trunk/configure
lvm2/trunk/configure.in
lvm2/trunk/daemons/clvmd/Makefile.in
lvm2/trunk/daemons/clvmd/clvmd-command.c
lvm2/trunk/daemons/clvmd/clvmd-gulm.c
lvm2/trunk/daemons/clvmd/clvmd-gulm.h
lvm2/trunk/daemons/clvmd/clvmd.c
lvm2/trunk/daemons/clvmd/clvmd.h
lvm2/trunk/daemons/clvmd/lvm-functions.c
lvm2/trunk/daemons/clvmd/refresh_clvmd.c
lvm2/trunk/dmeventd/mirror/dmeventd_mirror.c
lvm2/trunk/doc/example.conf
lvm2/trunk/lib/activate/activate.c
lvm2/trunk/lib/activate/activate.h
lvm2/trunk/lib/activate/dev_manager.c
lvm2/trunk/lib/cache/lvmcache.c
lvm2/trunk/lib/commands/toolcontext.c
lvm2/trunk/lib/commands/toolcontext.h
lvm2/trunk/lib/config/config.c
lvm2/trunk/lib/config/config.h
lvm2/trunk/lib/config/defaults.h
lvm2/trunk/lib/device/dev-io.c
lvm2/trunk/lib/device/dev-md.c
lvm2/trunk/lib/device/device.c
lvm2/trunk/lib/display/display.c
lvm2/trunk/lib/error/errseg.c
lvm2/trunk/lib/filters/filter-persistent.c
lvm2/trunk/lib/filters/filter-persistent.h
lvm2/trunk/lib/filters/filter-sysfs.c
lvm2/trunk/lib/filters/filter.c
lvm2/trunk/lib/format1/disk-rep.c
lvm2/trunk/lib/format1/disk-rep.h
lvm2/trunk/lib/format1/format1.c
lvm2/trunk/lib/format1/import-export.c
lvm2/trunk/lib/format1/import-extents.c
lvm2/trunk/lib/format1/lvm1-label.c
lvm2/trunk/lib/format_pool/disk_rep.c
lvm2/trunk/lib/format_pool/disk_rep.h
lvm2/trunk/lib/format_pool/pool_label.c
lvm2/trunk/lib/format_text/archive.c
lvm2/trunk/lib/format_text/export.c
lvm2/trunk/lib/format_text/format-text.c
lvm2/trunk/lib/format_text/import.c
lvm2/trunk/lib/format_text/import_vsn1.c
lvm2/trunk/lib/format_text/text_label.c
lvm2/trunk/lib/label/label.c
lvm2/trunk/lib/label/label.h
lvm2/trunk/lib/locking/cluster_locking.c
lvm2/trunk/lib/locking/file_locking.c
lvm2/trunk/lib/locking/locking.c
lvm2/trunk/lib/locking/locking.h
lvm2/trunk/lib/locking/no_locking.c
lvm2/trunk/lib/log/log.c
lvm2/trunk/lib/log/log.h
lvm2/trunk/lib/metadata/lv_manip.c
lvm2/trunk/lib/metadata/metadata.c
lvm2/trunk/lib/metadata/metadata.h
lvm2/trunk/lib/metadata/mirror.c
lvm2/trunk/lib/metadata/pv_map.c
lvm2/trunk/lib/metadata/pv_map.h
lvm2/trunk/lib/metadata/segtype.h
lvm2/trunk/lib/mirror/mirrored.c
lvm2/trunk/lib/misc/lvm-file.c
lvm2/trunk/lib/misc/lvm-file.h
lvm2/trunk/lib/report/columns.h
lvm2/trunk/lib/report/report.c
lvm2/trunk/lib/snapshot/snapshot.c
lvm2/trunk/lib/striped/striped.c
lvm2/trunk/lib/zero/zero.c
lvm2/trunk/make.tmpl.in
lvm2/trunk/man/Makefile.in
lvm2/trunk/man/clvmd.8
lvm2/trunk/man/lvchange.8
lvm2/trunk/man/lvconvert.8
lvm2/trunk/man/lvcreate.8
lvm2/trunk/man/lvextend.8
lvm2/trunk/man/lvm.conf.5
lvm2/trunk/man/lvreduce.8
lvm2/trunk/man/lvremove.8
lvm2/trunk/man/lvresize.8
lvm2/trunk/man/lvs.8
lvm2/trunk/man/pvmove.8
lvm2/trunk/man/pvs.8
lvm2/trunk/man/vgchange.8
lvm2/trunk/man/vgcreate.8
lvm2/trunk/man/vgs.8
lvm2/trunk/scripts/clvmd_init_rhel4
lvm2/trunk/scripts/lvm2create_initrd/lvm2create_initrd
lvm2/trunk/scripts/lvm_dump.sh
lvm2/trunk/tools/Makefile.in
lvm2/trunk/tools/args.h
lvm2/trunk/tools/commands.h
lvm2/trunk/tools/dumpconfig.c
lvm2/trunk/tools/fsadm/Makefile.in
lvm2/trunk/tools/lvchange.c
lvm2/trunk/tools/lvconvert.c
lvm2/trunk/tools/lvcreate.c
lvm2/trunk/tools/lvm-static.c
lvm2/trunk/tools/lvm.c
lvm2/trunk/tools/lvm2cmdline.h
lvm2/trunk/tools/lvmcmdlib.c
lvm2/trunk/tools/lvmcmdline.c
lvm2/trunk/tools/lvremove.c
lvm2/trunk/tools/lvrename.c
lvm2/trunk/tools/pvchange.c
lvm2/trunk/tools/pvmove.c
lvm2/trunk/tools/pvremove.c
lvm2/trunk/tools/pvscan.c
lvm2/trunk/tools/reporter.c
lvm2/trunk/tools/toollib.c
lvm2/trunk/tools/toollib.h
lvm2/trunk/tools/vgcfgrestore.c
lvm2/trunk/tools/vgchange.c
lvm2/trunk/tools/vgcreate.c
lvm2/trunk/tools/vgextend.c
lvm2/trunk/tools/vgmerge.c
lvm2/trunk/tools/vgreduce.c
lvm2/trunk/tools/vgremove.c
lvm2/trunk/tools/vgrename.c
lvm2/trunk/tools/vgsplit.c
Log:
Merge /lvm2/upstream/current (2.02.24).
Modified: lvm2/trunk/Makefile.in
==============================================================================
--- lvm2/trunk/Makefile.in (original)
+++ lvm2/trunk/Makefile.in Sat Apr 7 16:07:03 2007
@@ -16,7 +16,7 @@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
-SUBDIRS = doc include man
+SUBDIRS = doc include man scripts
ifeq ("@INTL@", "yes")
SUBDIRS += po
Modified: lvm2/trunk/VERSION
==============================================================================
--- lvm2/trunk/VERSION (original)
+++ lvm2/trunk/VERSION Sat Apr 7 16:07:03 2007
@@ -1 +1 @@
-2.02.12 (2006-10-16)
+2.02.24 (2007-03-19)
Modified: lvm2/trunk/WHATS_NEW
==============================================================================
--- lvm2/trunk/WHATS_NEW (original)
+++ lvm2/trunk/WHATS_NEW Sat Apr 7 16:07:03 2007
@@ -1,3 +1,153 @@
+Version 2.02.24 - 19th March 2007
+=================================
+ Fix processing of exit status in init scripts
+ Fix vgremove to require at least one vg argument.
+ Fix reading of striped LVs in LVM1 format.
+ Flag nolocking as clustered so clvmd startup sees clustered LVs. (2.02.10)
+ Add a few missing pieces of vgname command line validation.
+ Support the /dev/mapper prefix on most command lines.
+
+Version 2.02.23 - 8th March 2007
+================================
+ Fix vgrename active LV check to ignore differing vgids.
+ Remove no-longer-used uuid_out parameter from activation info functions.
+ Fix two more segfaults if an empty config file section encountered.
+ Move .cache file into a new /etc/lvm/cache directory by default.
+ Add devices/cache_dir & devices/cache_file_prefix, deprecating devices/cache.
+ Create directory in fcntl_lock_file() if required.
+ Exclude readline support from lvm.static.
+ Fix a leak in a reporting error path (2.02.19).
+
+Version 2.02.22 - 13th February 2007
+====================================
+ Correct -b and -P on a couple of man pages.
+ Add global/units to example.conf.
+ Fix loading of segment_libraries.
+ If a PV reappears after it was removed from its VG, make it an orphan.
+ Don't update metadata automatically if VGIDs don't match.
+ Fix some vgreduce --removemissing command line validation.
+
+Version 2.02.21 - 30th January 2007
+===================================
+ Add warning to lvm2_monitoring_init_rhel4 if attempting to stop monitoring.
+ Fix vgsplit to handle mirrors.
+ Reorder fields in reporting field definitions.
+ Fix vgs to treat args as VGs even when PV fields are displayed.
+ Fix md signature check to handle both endiannesses.
+
+Version 2.02.20 - 25th January 2007
+===================================
+ dmeventd mirror sets ignore_suspended_devices and avoids scanning mirrors.
+ Add devices/ignore_suspended_devices to ignore suspended dm devices.
+ Add some missing close() and fclose() return code checks.
+ Fix exit statuses of reporting tools (2.02.19).
+ Add init script for dmeventd monitoring.
+ lvm.static no longer interacts with dmeventd unless explicitly asked to.
+ Add field definitions to report help text.
+ Remove unnecessary cmd arg from target_*monitor_events().
+ Add private variable to dmeventd shared library interface.
+ Long-lived processes write out persistent dev cache in refresh_toolcontext().
+ Fix refresh_toolcontext() always to wipe persistent device filter cache.
+ Add is_long_lived to toolcontext.
+ Add --clustered to man pages.
+ Streamline dm_report_field_* interface.
+ Change remaining dmeventd terminology 'register' to 'monitor'.
+ Update reporting man pages.
+ No longer necessary to specify alignment type for report fields.
+
+Version 2.02.19 - 17th January 2007
+===================================
+ Fix a segfault if an empty config file section encountered.
+ Move basic reporting functions into libdevmapper.
+ Fix partition table processing after sparc changes (2.02.16).
+ Fix cmdline PE range processing segfault (2.02.13).
+ Some libdevmapper-event interface changes.
+ Report dmeventd mirror monitoring status.
+ Fix dmeventd mirror status line processing.
+
+Version 2.02.18 - 11th January 2007
+===================================
+ Revised libdevmapper-event interface for dmeventd.
+ Remove dmeventd mirror status line word limit.
+ Use CFLAGS when linking so mixed sparc builds can supply -m64.
+ Prevent permission changes on active mirrors.
+ Print warning instead of error message if lvconvert cannot zero volume.
+ Add snapshot options to lvconvert man page.
+ dumpconfig accepts a list of configuration variables to display.
+ Change dumpconfig to use --file to redirect output to a file.
+ Avoid vgreduce error when mirror code removes the log LV.
+ Remove 3 redundant AC_MSG_RESULTs from configure.in.
+ Free memory in _raw_read_mda_header() error paths.
+ Fix ambiguous vgsplit error message for split LV.
+ Fix lvextend man page typo.
+ Add configure --with-dmdir to compile against a device-mapper source tree.
+ Use no flush suspending for mirrors.
+ Add dmeventd_mirror register_mutex, tidy initialisation & add memlock.
+ Fix create mirror with name longer than 22 chars.
+ Fix some activate.c prototypes when compiled without devmapper.
+ Fix dmeventd mirror to cope if monitored device disappears.
+
+Version 2.02.17 - 14th December 2006
+====================================
+ Add missing pvremove error message when device doesn't exist.
+ When lvconvert allocates a mirror log, respect parallel area constraints.
+ Use loop to iterate through the now-ordered policy list in _allocate().
+ Check for failure to allocate just the mirror log.
+ Introduce calc_area_multiple().
+ Support mirror log allocation when there is only one PV: area_count now 0.
+ Fix detection of smallest area in _alloc_parallel_area() for cling policy.
+ Add manpage entry for clvmd -T
+ Fix gulm operation of clvmd, including a hang when doing lvchange -aey
+ Fix hang in clvmd if a pre-command failed.
+
+Version 2.02.16 - 1st December 2006
+===================================
+ Fix VG clustered read locks to use PR not CR.
+ Adjust some alignments for ia64/sparc.
+ Fix mirror segment removal to use temporary error segment.
+ Always compile debug logging into clvmd.
+ Add startup timeout to RHEL4 clvmd startup script.
+ Add -T (startup timeout) switch to clvmd.
+ Improve lvm_dump.sh robustness.
+ Update lvm2create_initrd to support gentoo.
+
+Version 2.02.15 - 21st November 2006
+====================================
+ Fix clvmd_init_rhel4 line truncation (2.02.14).
+ Install lvmdump by default.
+ Fix check for snapshot module when activating snapshot.
+ Fix pvremove error path for case when PV is in use.
+ Warn if certain duplicate config file entries are seen.
+ Enhance lvm_dump.sh for sysreport integration and add man page.
+ Fix --autobackup argument which could never disable backups.
+ Fix a label_verify error path.
+
+Version 2.02.14 - 10th November 2006
+====================================
+ Fix adjusted_mirror_region_size() to handle 64-bit size.
+ Add some missing bounds checks on 32-bit extent counters.
+ Add Petabyte and Exabyte support.
+ Fix lvcreate error message when 0 extents requested.
+ lvremove man page: volumes must be cluster inactive before being removed.
+ Protect .cache manipulations with fcntl locking.
+ Change .cache timestamp comparisons to use ctime.
+ Fix mirror log LV writing to set all bits in whole LV.
+ Fix clustered VG detection and default runlevels in clvmd_init_rhel4.
+ Fix high-level free space check for partial allocations.
+
+Version 2.02.13 - 27th October 2006
+===================================
+ Add couple of missing files to tools/Makefile CLEAN_TARGETS.
+ When adding snapshot leave cow LV mapped device active after zeroing.
+ Fix a clvmd debug message.
+ Add dev_flush() to set_lv().
+ Add lvchange --resync.
+ Perform high-level free space check before each allocation attempt.
+ Don't allow a node to remove an LV that's exclusively active on anther node.
+ Cope if same PV is included more than once in cmdline PE range list.
+ Set PV size to current device size if it is found to be zero.
+ Add segment parameter to target_present functions.
+
Version 2.02.12 - 16th October 2006
===================================
Fix pvdisplay to use vg_read() for non-orphans.
Modified: lvm2/trunk/configure
==============================================================================
--- lvm2/trunk/configure (original)
+++ lvm2/trunk/configure Sat Apr 7 16:07:03 2007
@@ -310,7 +310,7 @@
#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 build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os AWK CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE RANLIB ac_ct_RANLIB CFLOW_CMD CSCOPE_CMD CPP EGREP ALLOCA LIBOBJS POW_LIB MSGFMT MODPROBE_CMD JOBS STATIC_LINK LVM1 POOL SNAPSHOTS MIRRORS OWNER GROUP COPTIMISE_FLAG CLDFLAGS CLDWHOLEARCHIVE CLDNOWHOLEARCHIVE LDDEPS LIB_SUFFIX LVM_VERSION LVM1_FALLBACK DEBUG DEVMAPPER HAVE_LIBDL HAVE_SELINUX HAVE_REALTIME CMDLIB LOCALEDIR CONFDIR STATICDIR INTL_PACKAGE INTL CLVMD CLUSTER FSADM DMEVENTD 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 build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os AWK CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE RANLIB ac_ct_RANLIB CFLOW_CMD CSCOPE_CMD CPP EGREP ALLOCA LIBOBJS POW_LIB MSGFMT MODPROBE_CMD JOBS STATIC_LINK LVM1 POOL SNAPSHOTS MIRRORS OWNER GROUP COPTIMISE_FLAG CLDFLAGS CLDWHOLEARCHIVE CLDNOWHOLEARCHIVE LDDEPS LIB_SUFFIX LVM_VERSION LVM1_FALLBACK DEBUG DEVMAPPER HAVE_LIBDL HAVE_SELINUX HAVE_REALTIME CMDLIB LOCALEDIR CONFDIR STATICDIR DMDIR INTL_PACKAGE INTL CLVMD CLUSTER FSADM DMEVENTD LTLIBOBJS'
ac_subst_files=''
# Initialize some variables set by options.
@@ -883,6 +883,7 @@
--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
+ --with-dmdir=DIR Build against device-mapper source tree in DIR
Some influential environment variables:
CC C compiler command
@@ -8267,8 +8268,6 @@
################################################################################
if test x$SELINUX = xyes; then
- echo "$as_me:$LINENO: checking for sepol_check_context function" >&5
-echo $ECHO_N "checking for sepol_check_context function... $ECHO_C" >&6
echo "$as_me:$LINENO: checking for sepol_check_context in -lsepol" >&5
echo $ECHO_N "checking for sepol_check_context in -lsepol... $ECHO_C" >&6
if test "${ac_cv_lib_sepol_sepol_check_context+set}" = set; then
@@ -8339,15 +8338,11 @@
HAVE_SEPOL=no
fi
- echo "$as_me:$LINENO: result: $HAVE_SEPOL" >&5
-echo "${ECHO_T}$HAVE_SEPOL" >&6
if test x$HAVE_SEPOL = xyes; then
LIBS="-lsepol $LIBS"
fi
- echo "$as_me:$LINENO: checking for is_selinux_enabled function" >&5
-echo $ECHO_N "checking for is_selinux_enabled function... $ECHO_C" >&6
echo "$as_me:$LINENO: checking for is_selinux_enabled in -lselinux" >&5
echo $ECHO_N "checking for is_selinux_enabled in -lselinux... $ECHO_C" >&6
if test "${ac_cv_lib_selinux_is_selinux_enabled+set}" = set; then
@@ -8418,8 +8413,6 @@
HAVE_SELINUX=no
fi
- echo "$as_me:$LINENO: result: $HAVE_SELINUX" >&5
-echo "${ECHO_T}$HAVE_SELINUX" >&6
if test x$HAVE_SELINUX = xyes; then
@@ -8436,8 +8429,6 @@
################################################################################
if test x$REALTIME = xyes; then
- echo "$as_me:$LINENO: checking for clock_gettime function" >&5
-echo $ECHO_N "checking for clock_gettime function... $ECHO_C" >&6
echo "$as_me:$LINENO: checking for clock_gettime in -lrt" >&5
echo $ECHO_N "checking for clock_gettime in -lrt... $ECHO_C" >&6
if test "${ac_cv_lib_rt_clock_gettime+set}" = set; then
@@ -8508,8 +8499,6 @@
HAVE_REALTIME=no
fi
- echo "$as_me:$LINENO: result: $HAVE_REALTIME" >&5
-echo "${ECHO_T}$HAVE_REALTIME" >&6
if test x$HAVE_REALTIME = xyes; then
@@ -8964,6 +8953,15 @@
STATICDIR='${exec_prefix}/sbin'
fi;
+
+# Check whether --with-dmdir or --without-dmdir was given.
+if test "${with_dmdir+set}" = set; then
+ withval="$with_dmdir"
+ DMDIR="$withval"
+else
+ DMDIR=
+fi;
+
################################################################################
if test x$READLINE = xyes; then
@@ -11202,8 +11200,9 @@
+
################################################################################
- ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile dmeventd/Makefile dmeventd/mirror/Makefile doc/Makefile include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/snapshot/Makefile man/Makefile po/Makefile tools/Makefile tools/version.h tools/fsadm/Makefile test/mm/Makefile test/device/Makefile test/format1/Makefile test/regex/Makefile test/filters/Makefile"
+ ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile dmeventd/Makefile dmeventd/mirror/Makefile doc/Makefile include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/snapshot/Makefile man/Makefile po/Makefile scripts/Makefile tools/Makefile tools/version.h tools/fsadm/Makefile 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
@@ -11745,6 +11744,7 @@
"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" ;;
+ "scripts/Makefile" ) CONFIG_FILES="$CONFIG_FILES scripts/Makefile" ;;
"tools/Makefile" ) CONFIG_FILES="$CONFIG_FILES tools/Makefile" ;;
"tools/version.h" ) CONFIG_FILES="$CONFIG_FILES tools/version.h" ;;
"tools/fsadm/Makefile" ) CONFIG_FILES="$CONFIG_FILES tools/fsadm/Makefile" ;;
@@ -11899,6 +11899,7 @@
s, at LOCALEDIR@,$LOCALEDIR,;t t
s, at CONFDIR@,$CONFDIR,;t t
s, at STATICDIR@,$STATICDIR,;t t
+s, at DMDIR@,$DMDIR,;t t
s, at INTL_PACKAGE@,$INTL_PACKAGE,;t t
s, at INTL@,$INTL,;t t
s, at CLVMD@,$CLVMD,;t t
Modified: lvm2/trunk/configure.in
==============================================================================
--- lvm2/trunk/configure.in (original)
+++ lvm2/trunk/configure.in Sat Apr 7 16:07:03 2007
@@ -438,17 +438,13 @@
################################################################################
dnl -- Check for selinux
if test x$SELINUX = xyes; then
- AC_MSG_CHECKING(for sepol_check_context function)
AC_CHECK_LIB(sepol, sepol_check_context, HAVE_SEPOL=yes, HAVE_SEPOL=no)
- AC_MSG_RESULT($HAVE_SEPOL)
if test x$HAVE_SEPOL = xyes; then
LIBS="-lsepol $LIBS"
fi
- AC_MSG_CHECKING(for is_selinux_enabled function)
AC_CHECK_LIB(selinux, is_selinux_enabled, HAVE_SELINUX=yes, HAVE_SELINUX=no)
- AC_MSG_RESULT($HAVE_SELINUX)
if test x$HAVE_SELINUX = xyes; then
AC_DEFINE([HAVE_SELINUX], 1, [Define to 1 to include support for selinux.])
@@ -461,9 +457,7 @@
################################################################################
dnl -- Check for realtime clock support
if test x$REALTIME = xyes; then
- AC_MSG_CHECKING(for clock_gettime function)
AC_CHECK_LIB(rt, clock_gettime, HAVE_REALTIME=yes, HAVE_REALTIME=no)
- AC_MSG_RESULT($HAVE_REALTIME)
if test x$HAVE_REALTIME = xyes; then
AC_DEFINE([HAVE_REALTIME], 1, [Define to 1 to include support for realtime clock.])
@@ -526,6 +520,11 @@
[ STATICDIR="$withval" ],
[ STATICDIR='${exec_prefix}/sbin' ])
+AC_ARG_WITH(dmdir,
+ [ --with-dmdir=DIR Build against device-mapper source tree in DIR],
+ [ DMDIR="$withval" ],
+ [ DMDIR= ])
+
################################################################################
dnl -- Ensure additional headers required
if test x$READLINE = xyes; then
@@ -608,6 +607,7 @@
AC_SUBST(LOCALEDIR)
AC_SUBST(CONFDIR)
AC_SUBST(STATICDIR)
+AC_SUBST(DMDIR)
AC_SUBST(INTL_PACKAGE)
AC_SUBST(INTL)
AC_SUBST(CLVMD)
@@ -637,6 +637,7 @@
lib/snapshot/Makefile \
man/Makefile \
po/Makefile \
+scripts/Makefile \
tools/Makefile \
tools/version.h \
tools/fsadm/Makefile \
Modified: lvm2/trunk/daemons/clvmd/Makefile.in
==============================================================================
--- lvm2/trunk/daemons/clvmd/Makefile.in (original)
+++ lvm2/trunk/daemons/clvmd/Makefile.in Sat Apr 7 16:07:03 2007
@@ -73,7 +73,8 @@
install_clvmd
clvmd: $(OBJECTS) $(top_srcdir)/lib/liblvm.a
- $(CC) -o clvmd $(OBJECTS) $(LDFLAGS) $(LVMLIBS) $(LMLIBS) $(LIBS)
+ $(CC) -o clvmd $(OBJECTS) $(CFLAGS) $(LDFLAGS) \
+ $(LVMLIBS) $(LMLIBS) $(LIBS)
.PHONY: install_clvmd
Modified: lvm2/trunk/daemons/clvmd/clvmd-command.c
==============================================================================
--- lvm2/trunk/daemons/clvmd/clvmd-command.c (original)
+++ lvm2/trunk/daemons/clvmd/clvmd-command.c Sat Apr 7 16:07:03 2007
@@ -191,12 +191,16 @@
dm_hash_remove(lock_hash, lockname);
}
else {
-
+ /* Read locks need to be PR; other modes get passed through */
+ if ((lock_cmd & LCK_TYPE_MASK) == LCK_READ) {
+ lock_cmd &= ~LCK_TYPE_MASK;
+ lock_cmd |= LCK_PREAD;
+ }
status = sync_lock(lockname, (int)lock_cmd, (lock_flags & LCK_NONBLOCK) ? LKF_NOQUEUE : 0, &lkid);
if (status)
status = errno;
else
- dm_hash_insert(lock_hash, lockname, (void *)lkid);
+ dm_hash_insert(lock_hash, lockname, (void *)(long)lkid);
}
return status;
@@ -220,7 +224,7 @@
switch (header->cmd) {
case CLVMD_CMD_TEST:
status = sync_lock("CLVMD_TEST", LKM_EXMODE, 0, &lockid);
- client->bits.localsock.private = (void *) lockid;
+ client->bits.localsock.private = (void *)(long)lockid;
break;
case CLVMD_CMD_LOCK_VG:
Modified: lvm2/trunk/daemons/clvmd/clvmd-gulm.c
==============================================================================
--- lvm2/trunk/daemons/clvmd/clvmd-gulm.c (original)
+++ lvm2/trunk/daemons/clvmd/clvmd-gulm.c Sat Apr 7 16:07:03 2007
@@ -730,7 +730,7 @@
pthread_mutex_lock(&lwait.mutex);
/* This needs to be converted from DLM/LVM2 value for GULM */
- if (flags == LCK_NONBLOCK) flags = lg_lock_flag_Try;
+ if (flags & LKF_NOQUEUE) flags = lg_lock_flag_Try;
dm_hash_insert(lock_hash, resource, &lwait);
DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
@@ -828,6 +828,7 @@
}
break;
+ case LCK_PREAD:
case LCK_READ:
status = _lock_resource(lock1, lg_lock_state_Shared, flags, lockid);
if (status)
@@ -864,6 +865,7 @@
/* The held lock mode is in the lock id */
assert(lockid == LCK_EXCL ||
lockid == LCK_READ ||
+ lockid == LCK_PREAD ||
lockid == LCK_WRITE);
status = _unlock_resource(lock1, lockid);
Modified: lvm2/trunk/daemons/clvmd/clvmd-gulm.h
==============================================================================
--- lvm2/trunk/daemons/clvmd/clvmd-gulm.h (original)
+++ lvm2/trunk/daemons/clvmd/clvmd-gulm.h Sat Apr 7 16:07:03 2007
@@ -1,5 +1,6 @@
-
+/* DLM constant that clvmd uses as a generic NONBLOCK lock flag */
+#define LKF_NOQUEUE 1
extern int get_next_node_csid(void **context, char *csid);
extern void add_down_node(char *csid);
Modified: lvm2/trunk/daemons/clvmd/clvmd.c
==============================================================================
--- lvm2/trunk/daemons/clvmd/clvmd.c (original)
+++ lvm2/trunk/daemons/clvmd/clvmd.c Sat Apr 7 16:07:03 2007
@@ -30,6 +30,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
+#include <stdarg.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
@@ -85,6 +86,7 @@
int msglen;
unsigned short xid;
};
+static int debug = 0;
static pthread_t lvm_thread;
static pthread_mutex_t lvm_thread_mutex;
static pthread_cond_t lvm_thread_cond;
@@ -99,6 +101,7 @@
#define DFAIL_LOCAL_SOCK 2
#define DFAIL_CLUSTER_IF 3
#define DFAIL_MALLOC 4
+#define DFAIL_TIMEOUT 5
#define SUCCESS 0
/* Prototypes for code further down */
@@ -122,7 +125,7 @@
static int open_local_sock(void);
static struct local_client *find_client(int clientid);
static void main_loop(int local_sock, int cmd_timeout);
-static void be_daemon(void);
+static void be_daemon(int start_timeout);
static int check_all_clvmds_running(struct local_client *client);
static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
int len, char *csid,
@@ -146,6 +149,7 @@
fprintf(file, " -d Don't fork, run in the foreground\n");
fprintf(file, " -R Tell all running clvmds in the cluster to reload their device cache\n");
fprintf(file, " -t<secs> Command timeout (default 60 seconds)\n");
+ fprintf(file, " -T<secs> Startup timeout (default none)\n");
fprintf(file, "\n");
}
@@ -161,21 +165,36 @@
}
+void debuglog(const char *fmt, ...)
+{
+ time_t P;
+ va_list ap;
+
+ if (!debug)
+ return;
+
+ va_start(ap,fmt);
+ time(&P);
+ fprintf(stderr, "CLVMD[%x]: %.15s ", (int)pthread_self(), ctime(&P)+4 );
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+
int main(int argc, char *argv[])
{
int local_sock;
struct local_client *newfd;
struct utsname nodeinfo;
signed char opt;
- int debug = 0;
int cmd_timeout = DEFAULT_CMD_TIMEOUT;
+ int start_timeout = 0;
sigset_t ss;
int using_gulm = 0;
/* Deal with command-line arguments */
opterr = 0;
optind = 0;
- while ((opt = getopt(argc, argv, "?vVhdt:R")) != EOF) {
+ while ((opt = getopt(argc, argv, "?vVhdt:RT:")) != EOF) {
switch (opt) {
case 'h':
usage(argv[0], stdout);
@@ -200,6 +219,14 @@
exit(1);
}
break;
+ case 'T':
+ start_timeout = atoi(optarg);
+ if (start_timeout <= 0) {
+ fprintf(stderr, "startup timeout is invalid\n");
+ usage(argv[0], stderr);
+ exit(1);
+ }
+ break;
case 'V':
printf("Cluster LVM daemon version: %s\n", LVM_VERSION);
@@ -214,7 +241,7 @@
/* Fork into the background (unless requested not to) */
if (!debug) {
- be_daemon();
+ be_daemon(start_timeout);
}
DEBUGLOG("CLVMD started\n");
@@ -298,7 +325,8 @@
/* This needs to be started after cluster initialisation
as it may need to take out locks */
DEBUGLOG("starting LVM thread\n");
- pthread_create(&lvm_thread, NULL, lvm_thread_fn, (void *)using_gulm);
+ pthread_create(&lvm_thread, NULL, lvm_thread_fn,
+ (void *)(long)using_gulm);
/* Tell the rest of the cluster our version number */
/* CMAN can do this immediately, gulm needs to wait until
@@ -385,16 +413,17 @@
len = read(thisfd->fd, buffer, sizeof(int));
- DEBUGLOG("read on PIPE %d: %d bytes: status: %d\n",
- thisfd->fd, len, *(int *) buffer);
-
if (len == sizeof(int)) {
- status = *(int *) buffer;
+ memcpy(&status, buffer, sizeof(int));
}
+ DEBUGLOG("read on PIPE %d: %d bytes: status: %d\n",
+ thisfd->fd, len, status);
+
/* EOF on pipe or an error, close it */
if (len <= 0) {
int jstat;
+ void *ret = &status;
close(thisfd->fd);
/* Clear out the cross-link */
@@ -404,9 +433,7 @@
/* Reap child thread */
if (thisfd->bits.pipe.threadid) {
- jstat =
- pthread_join(thisfd->bits.pipe.threadid,
- (void **) &status);
+ jstat = pthread_join(thisfd->bits.pipe.threadid, &ret);
thisfd->bits.pipe.threadid = 0;
if (thisfd->bits.pipe.client != NULL)
thisfd->bits.pipe.client->bits.localsock.
@@ -647,16 +674,66 @@
close(local_sock);
}
+static __attribute__ ((noreturn)) void wait_for_child(int c_pipe, int timeout)
+{
+ int child_status;
+ int sstat;
+ fd_set fds;
+ struct timeval tv = {timeout, 0};
+
+ FD_ZERO(&fds);
+ FD_SET(c_pipe, &fds);
+
+ sstat = select(c_pipe+1, &fds, NULL, NULL, timeout? &tv: NULL);
+ if (sstat == 0) {
+ fprintf(stderr, "clvmd startup timed out\n");
+ exit(DFAIL_TIMEOUT);
+ }
+ if (sstat == 1) {
+ if (read(c_pipe, &child_status, sizeof(child_status)) !=
+ sizeof(child_status)) {
+
+ fprintf(stderr, "clvmd failed in initialisation\n");
+ exit(DFAIL_INIT);
+ }
+ else {
+ switch (child_status) {
+ case SUCCESS:
+ break;
+ case DFAIL_INIT:
+ fprintf(stderr, "clvmd failed in initialisation\n");
+ break;
+ case DFAIL_LOCAL_SOCK:
+ fprintf(stderr, "clvmd could not create local socket\n");
+ fprintf(stderr, "Another clvmd is probably already running\n");
+ break;
+ case DFAIL_CLUSTER_IF:
+ fprintf(stderr, "clvmd could not connect to cluster manager\n");
+ fprintf(stderr, "Consult syslog for more information\n");
+ break;
+ case DFAIL_MALLOC:
+ fprintf(stderr, "clvmd failed, not enough memory\n");
+ break;
+ default:
+ fprintf(stderr, "clvmd failed, error was %d\n", child_status);
+ break;
+ }
+ exit(child_status);
+ }
+ }
+ fprintf(stderr, "clvmd startup, select failed: %s\n", strerror(errno));
+ exit(DFAIL_INIT);
+}
+
/*
* Fork into the background and detach from our parent process.
* In the interests of user-friendliness we wait for the daemon
* to complete initialisation before returning its status
* the the user.
*/
-static void be_daemon()
+static void be_daemon(int timeout)
{
pid_t pid;
- int child_status;
int devnull = open("/dev/null", O_RDWR);
if (devnull == -1) {
perror("Can't open /dev/null");
@@ -676,36 +753,7 @@
default: /* Parent */
close(child_pipe[1]);
- if (read(child_pipe[0], &child_status, sizeof(child_status)) !=
- sizeof(child_status)) {
-
- fprintf(stderr, "clvmd failed in initialisation\n");
- exit(DFAIL_INIT);
- }
- else {
- switch (child_status) {
- case SUCCESS:
- break;
- case DFAIL_INIT:
- fprintf(stderr, "clvmd failed in initialisation\n");
- break;
- case DFAIL_LOCAL_SOCK:
- fprintf(stderr, "clvmd could not create local socket\n");
- fprintf(stderr, "Another clvmd is probably already running\n");
- break;
- case DFAIL_CLUSTER_IF:
- fprintf(stderr, "clvmd could not connect to cluster manager\n");
- fprintf(stderr, "Consult syslog for more information\n");
- break;
- case DFAIL_MALLOC:
- fprintf(stderr, "clvmd failed, not enough memory\n");
- break;
- default:
- fprintf(stderr, "clvmd failed, error was %d\n", child_status);
- break;
- }
- exit(child_status);
- }
+ wait_for_child(child_pipe[0], timeout);
}
/* Detach ourself from the calling environment */
@@ -1091,8 +1139,8 @@
}
/* Process a command from a remote node and return the result */
-void process_remote_command(struct clvm_header *msg, int msglen, int fd,
- char *csid)
+static void process_remote_command(struct clvm_header *msg, int msglen, int fd,
+ char *csid)
{
char *replyargs;
char nodename[max_cluster_member_name_len];
@@ -1116,11 +1164,12 @@
(struct clvm_header *) malloc(msg->arglen +
sizeof(struct clvm_header));
if (newmsg) {
- if (system_lv_read_data
- (nodename, (char *) newmsg,
- (size_t *) &msglen) == 0) {
+ ssize_t len;
+ if (system_lv_read_data(nodename, (char *) newmsg,
+ &len) == 0) {
msg = newmsg;
msg_malloced = 1;
+ msglen = len;
} else {
struct clvm_header head;
DEBUGLOG("System LV read failed\n");
@@ -1166,8 +1215,11 @@
/* Version check is internal - don't bother exposing it in
clvmd-command.c */
if (msg->cmd == CLVMD_CMD_VERSION) {
- int *version_nums = (int *) msg->args;
+ int version_nums[3];
char node[256];
+
+ memcpy(version_nums, msg->args, sizeof(version_nums));
+
clops->name_from_csid(csid, node);
DEBUGLOG("Remote node %s is version %d.%d.%d\n",
node,
@@ -1339,7 +1391,7 @@
}
/* This is the thread that runs the PRE and post commands for a particular connection */
-static void *pre_and_post_thread(void *arg)
+static __attribute__ ((noreturn)) void *pre_and_post_thread(void *arg)
{
struct local_client *client = (struct local_client *) arg;
int status;
@@ -1374,6 +1426,8 @@
DEBUGLOG("Writing status %d down pipe %d\n", status, pipe_fd);
/* Tell the parent process we have finished this bit */
write(pipe_fd, &status, sizeof(int));
+ if (status)
+ continue; /* Wait for another PRE command */
/* We may need to wait for the condition variable before running the post command */
pthread_mutex_lock(&client->bits.localsock.mutex);
@@ -1407,7 +1461,6 @@
}
DEBUGLOG("Subthread finished\n");
pthread_exit((void *) 0);
- return 0;
}
/* Process a command on the local node and store the result */
@@ -1516,7 +1569,7 @@
if (thisreply->status)
clientreply->flags |= CLVMD_FLAG_NODEERRS;
- *(int *) ptr = thisreply->status;
+ memcpy(ptr, &thisreply->status, sizeof(int));
ptr += sizeof(int);
if (thisreply->replymsg) {
@@ -1572,19 +1625,22 @@
{
char message[sizeof(struct clvm_header) + sizeof(int) * 3];
struct clvm_header *msg = (struct clvm_header *) message;
- int *version_nums = (int *) msg->args;
+ int version_nums[3];
msg->cmd = CLVMD_CMD_VERSION;
msg->status = 0;
msg->flags = 0;
msg->clientid = 0;
- msg->arglen = sizeof(int) * 3;
+ msg->arglen = sizeof(version_nums);
version_nums[0] = htonl(CLVMD_MAJOR_VERSION);
version_nums[1] = htonl(CLVMD_MINOR_VERSION);
version_nums[2] = htonl(CLVMD_PATCH_VERSION);
+ memcpy(&msg->args, version_nums, sizeof(version_nums));
+
hton_clvm(msg);
+
clops->cluster_send_message(message, sizeof(message), NULL,
"Error Sending version number");
}
@@ -1641,11 +1697,11 @@
/*
* Routine that runs in the "LVM thread".
*/
-static void *lvm_thread_fn(void *arg)
+static __attribute__ ((noreturn)) void *lvm_thread_fn(void *arg)
{
struct list *cmdl, *tmp;
sigset_t ss;
- int using_gulm = (int)arg;
+ int using_gulm = (int)(long)arg;
/* Don't let anyone else to do work until we are started */
pthread_mutex_lock(&lvm_start_mutex);
@@ -1689,7 +1745,6 @@
}
pthread_mutex_unlock(&lvm_thread_mutex);
}
- return NULL;
}
/* Pass down some work to the LVM thread */
Modified: lvm2/trunk/daemons/clvmd/clvmd.h
==============================================================================
--- lvm2/trunk/daemons/clvmd/clvmd.h (original)
+++ lvm2/trunk/daemons/clvmd/clvmd.h Sat Apr 7 16:07:03 2007
@@ -95,11 +95,7 @@
} bits;
};
-#ifdef DEBUG
-#define DEBUGLOG(fmt, args...) {time_t P; time(&P); fprintf(stderr, "CLVMD[%x]: %.15s ", (int)pthread_self(), ctime(&P)+4 ); fprintf(stderr, fmt, ## args);}
-#else
-#define DEBUGLOG(fmt, args...)
-#endif
+#define DEBUGLOG(fmt, args...) debuglog(fmt, ## args);
#ifndef max
#define max(a,b) ((a)>(b)?(a):(b))
@@ -117,6 +113,7 @@
extern void clvmd_cluster_init_completed(void);
extern void process_message(struct local_client *client, char *buf, int len, char *csid);
+extern void debuglog(const char *fmt, ... );
int sync_lock(const char *resource, int mode, int flags, int *lockid);
int sync_unlock(const char *resource, int lockid);
Modified: lvm2/trunk/daemons/clvmd/lvm-functions.c
==============================================================================
--- lvm2/trunk/daemons/clvmd/lvm-functions.c (original)
+++ lvm2/trunk/daemons/clvmd/lvm-functions.c Sat Apr 7 16:07:03 2007
@@ -243,7 +243,7 @@
/* Is it open ? */
oldmode = get_current_lock(resource);
if (oldmode == -1) {
- DEBUGLOG("do_deactivate_lock, lock not already held\n");
+ DEBUGLOG("do_resume_lv, lock not already held\n");
return 0; /* We don't need to do anything */
}
@@ -325,8 +325,8 @@
if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
init_mirror_in_sync(1);
- if (!(lock_flags & LCK_DMEVENTD_REGISTER_MODE))
- init_dmeventd_register(0);
+ if (!(lock_flags & LCK_DMEVENTD_MONITOR_MODE))
+ init_dmeventd_monitor(0);
switch (command) {
case LCK_LV_EXCLUSIVE:
@@ -362,8 +362,8 @@
if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
init_mirror_in_sync(0);
- if (!(lock_flags & LCK_DMEVENTD_REGISTER_MODE))
- init_dmeventd_register(DEFAULT_DMEVENTD_MONITOR);
+ if (!(lock_flags & LCK_DMEVENTD_MONITOR_MODE))
+ init_dmeventd_monitor(DEFAULT_DMEVENTD_MONITOR);
/* clean the pool for another command */
dm_pool_empty(cmd->mem);
@@ -473,7 +473,8 @@
sync_unlock(vg, LCK_EXCL);
}
- fclose(vgs);
+ if (fclose(vgs))
+ DEBUGLOG("vgs fclose failed: %s\n", strerror(errno));
}
/*
@@ -523,7 +524,8 @@
}
}
}
- fclose(lvs);
+ if (fclose(lvs))
+ DEBUGLOG("lvs fclose failed: %s\n", strerror(errno));
return NULL;
}
@@ -575,7 +577,7 @@
/* Called to initialise the LVM context of the daemon */
int init_lvm(int using_gulm)
{
- if (!(cmd = create_toolcontext(NULL, 0))) {
+ if (!(cmd = create_toolcontext(NULL, 0, 1))) {
log_error("Failed to allocate command context");
return 0;
}
Modified: lvm2/trunk/daemons/clvmd/refresh_clvmd.c
==============================================================================
--- lvm2/trunk/daemons/clvmd/refresh_clvmd.c (original)
+++ lvm2/trunk/daemons/clvmd/refresh_clvmd.c Sat Apr 7 16:07:03 2007
@@ -183,7 +183,6 @@
lvm_response_t ** response, int *num)
{
char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1];
- int *outptr;
char *inptr;
char *retbuf = NULL;
int status;
@@ -223,17 +222,14 @@
* With an extra pair of INTs on the front to sanity
* check the pointer when we are given it back to free
*/
- outptr = dm_malloc(sizeof(lvm_response_t) * num_responses +
+ *response = dm_malloc(sizeof(lvm_response_t) * num_responses +
sizeof(int) * 2);
- if (!outptr) {
+ if (!*response) {
errno = ENOMEM;
status = 0;
goto out;
}
- *response = (lvm_response_t *) (outptr + 2);
- outptr[0] = LVM_SIGNATURE;
- outptr[1] = num_responses;
rarray = *response;
/* Unpack the response into an lvm_response_t array */
@@ -252,7 +248,7 @@
int j;
for (j = 0; j < i; j++)
dm_free(rarray[i].response);
- free(outptr);
+ free(*response);
errno = ENOMEM;
status = -1;
goto out;
@@ -274,25 +270,15 @@
}
/* Free reply array */
-static int _cluster_free_request(lvm_response_t * response)
+static int _cluster_free_request(lvm_response_t * response, int num)
{
- int *ptr = (int *) response - 2;
int i;
- int num;
-
- /* Check it's ours to free */
- if (response == NULL || *ptr != LVM_SIGNATURE) {
- errno = EINVAL;
- return 0;
- }
-
- num = ptr[1];
for (i = 0; i < num; i++) {
dm_free(response[i].response);
}
- dm_free(ptr);
+ dm_free(response);
return 1;
}
@@ -327,7 +313,7 @@
}
saved_errno = errno;
- _cluster_free_request(response);
+ _cluster_free_request(response, num_responses);
errno = saved_errno;
return status;
Modified: lvm2/trunk/dmeventd/mirror/dmeventd_mirror.c
==============================================================================
--- lvm2/trunk/dmeventd/mirror/dmeventd_mirror.c (original)
+++ lvm2/trunk/dmeventd/mirror/dmeventd_mirror.c Sat Apr 7 16:07:03 2007
@@ -15,7 +15,6 @@
#include "libdevmapper.h"
#include "libdevmapper-event.h"
#include "lvm2cmd.h"
-#include "lvm-string.h"
#include <errno.h>
#include <signal.h>
@@ -26,79 +25,104 @@
#include <unistd.h>
#include <syslog.h> /* FIXME Replace syslog with multilog */
+/* FIXME Missing openlog? */
#define ME_IGNORE 0
#define ME_INSYNC 1
#define ME_FAILURE 2
-static pthread_mutex_t _lock = PTHREAD_MUTEX_INITIALIZER;
+/*
+ * register_device() is called first and performs initialisation.
+ * Only one device may be registered or unregistered at a time.
+ */
+static pthread_mutex_t _register_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/*
+ * Number of active registrations.
+ */
+static int _register_count = 0;
-/* FIXME: We may need to lock around operations to these */
-static int register_count = 0;
-static struct dm_pool *mem_pool = NULL;
+static struct dm_pool *_mem_pool = NULL;
+static void *_lvm_handle = NULL;
+
+/*
+ * Currently only one event can be processed at a time.
+ */
+static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
static int _get_mirror_event(char *params)
{
- int i, rtn = ME_INSYNC;
- int max_args = 30; /* should support at least 8-way mirrors */
- char *args[max_args];
+ int i, r = ME_INSYNC;
+ char **args = NULL;
char *dev_status_str;
char *log_status_str;
char *sync_str;
- char *p;
- int log_argc, num_devs, num_failures=0;
-
- if (max_args <= dm_split_words(params, max_args, 0, args)) {
- syslog(LOG_ERR, "Unable to split mirror parameters: Arg list too long");
- return -E2BIG;
- }
+ char *p = NULL;
+ int log_argc, num_devs;
/*
- * Unused: 0 409600 mirror
- * Used : 2 253:4 253:5 400/400 1 AA 3 cluster 253:3 A
- */
- num_devs = atoi(args[0]);
- dev_status_str = args[3 + num_devs];
- log_argc = atoi(args[4 + num_devs]);
- log_status_str = args[4 + num_devs + log_argc];
- sync_str = args[1 + num_devs];
+ * dm core parms: 0 409600 mirror
+ * Mirror core parms: 2 253:4 253:5 400/400
+ * New-style failure params: 1 AA
+ * New-style log params: 3 cluster 253:3 A
+ * or 3 disk 253:3 A
+ * or 1 core
+ */
+
+ /* number of devices */
+ if (!dm_split_words(params, 1, 0, &p))
+ goto out_parse;
+
+ if (!(num_devs = atoi(p)))
+ goto out_parse;
+ p += strlen(p) + 1;
+
+ /* devices names + "400/400" + "1 AA" + 1 or 3 log parms + NULL */
+ args = dm_malloc((num_devs + 7) * sizeof(char *));
+ if (!args || dm_split_words(p, num_devs + 7, 0, args) < num_devs + 5)
+ goto out_parse;
+
+ dev_status_str = args[2 + num_devs];
+ log_argc = atoi(args[3 + num_devs]);
+ log_status_str = args[3 + num_devs + log_argc];
+ sync_str = args[num_devs];
/* Check for bad mirror devices */
- for (i = 0; i < num_devs; i++) {
+ for (i = 0; i < num_devs; i++)
if (dev_status_str[i] == 'D') {
- syslog(LOG_ERR, "Mirror device, %s, has failed.\n", args[i+1]);
- num_failures++;
+ syslog(LOG_ERR, "Mirror device, %s, has failed.\n", args[i]);
+ r = ME_FAILURE;
}
- }
- /* Check for bad log device */
- if (log_status_str[0] == 'D') {
+ /* Check for bad disk log device */
+ if (log_argc > 1 && log_status_str[0] == 'D') {
syslog(LOG_ERR, "Log device, %s, has failed.\n",
- args[3 + num_devs + log_argc]);
- num_failures++;
+ args[2 + num_devs + log_argc]);
+ r = ME_FAILURE;
}
- if (num_failures) {
- rtn = ME_FAILURE;
+ if (r == ME_FAILURE)
goto out;
- }
p = strstr(sync_str, "/");
if (p) {
p[0] = '\0';
if (strcmp(sync_str, p+1))
- rtn = ME_IGNORE;
+ r = ME_IGNORE;
p[0] = '/';
- } else {
- /*
- * How the hell did we get this?
- * Might mean all our parameters are screwed.
- */
- syslog(LOG_ERR, "Unable to parse sync string.");
- rtn = ME_IGNORE;
- }
- out:
- return rtn;
+ } else
+ goto out_parse;
+
+out:
+ if (args)
+ dm_free(args);
+ return r;
+
+out_parse:
+ if (args)
+ dm_free(args);
+ syslog(LOG_ERR, "Unable to parse mirror status string.");
+ return ME_IGNORE;
}
static void _temporary_log_fn(int level, const char *file,
@@ -113,69 +137,55 @@
static int _remove_failed_devices(const char *device)
{
int r;
- void *handle;
- int cmd_size = 256; /* FIXME Use system restriction */
- char cmd_str[cmd_size];
+#define CMD_SIZE 256 /* FIXME Use system restriction */
+ char cmd_str[CMD_SIZE];
char *vg = NULL, *lv = NULL, *layer = NULL;
- if (strlen(device) > 200)
- return -ENAMETOOLONG;
+ if (strlen(device) > 200) /* FIXME Use real restriction */
+ return -ENAMETOOLONG; /* FIXME These return code distinctions are not used so remove them! */
- if (!dm_split_lvm_name(mem_pool, device, &vg, &lv, &layer)) {
+ if (!dm_split_lvm_name(_mem_pool, device, &vg, &lv, &layer)) {
syslog(LOG_ERR, "Unable to determine VG name from %s",
device);
- return -ENOMEM;
+ return -ENOMEM; /* FIXME Replace with generic error return - reason for failure has already got logged */
}
/* FIXME Is any sanity-checking required on %s? */
- if (cmd_size <= snprintf(cmd_str, cmd_size, "vgreduce --removemissing %s", vg)) {
+ if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "vgreduce --config devices{ignore_suspended_devices=1} --removemissing %s", vg)) {
/* this error should be caught above, but doesn't hurt to check again */
syslog(LOG_ERR, "Unable to form LVM command: Device name too long");
- dm_pool_empty(mem_pool); /* FIXME: not safe with multiple threads */
- return -ENAMETOOLONG;
+ dm_pool_empty(_mem_pool); /* FIXME: not safe with multiple threads */
+ return -ENAMETOOLONG; /* FIXME Replace with generic error return - reason for failure has already got logged */
}
- lvm2_log_fn(_temporary_log_fn);
- handle = lvm2_init();
- lvm2_log_level(handle, 1);
- r = lvm2_run(handle, cmd_str);
+ r = lvm2_run(_lvm_handle, cmd_str);
- dm_pool_empty(mem_pool); /* FIXME: not safe with multiple threads */
- return (r == 1)? 0: -1;
+ dm_pool_empty(_mem_pool); /* FIXME: not safe with multiple threads */
+ return (r == 1) ? 0 : -1;
}
-void process_event(const char *device, enum dm_event_type event)
+void process_event(struct dm_task *dmt, enum dm_event_mask event,
+ void **unused __attribute((unused)))
{
- struct dm_task *dmt;
void *next = NULL;
uint64_t start, length;
char *target_type = NULL;
char *params;
+ const char *device = dm_task_get_name(dmt);
- if (pthread_mutex_trylock(&_lock)) {
+ if (pthread_mutex_trylock(&_event_mutex)) {
syslog(LOG_NOTICE, "Another thread is handling an event. Waiting...");
- pthread_mutex_lock(&_lock);
- }
- /* FIXME Move inside libdevmapper */
- if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) {
- syslog(LOG_ERR, "Unable to create dm_task.\n");
- goto fail;
- }
-
- if (!dm_task_set_name(dmt, device)) {
- syslog(LOG_ERR, "Unable to set device name.\n");
- goto fail;
+ pthread_mutex_lock(&_event_mutex);
}
-
- if (!dm_task_run(dmt)) {
- syslog(LOG_ERR, "Unable to run task.\n");
- goto fail;
- }
-
do {
next = dm_get_next_target(dmt, next, &start, &length,
&target_type, ¶ms);
+ if (!target_type) {
+ syslog(LOG_INFO, "%s mapping lost.\n", device);
+ continue;
+ }
+
if (strcmp(target_type, "mirror")) {
syslog(LOG_INFO, "%s has unmirrored portion.\n", device);
continue;
@@ -192,6 +202,7 @@
case ME_FAILURE:
syslog(LOG_ERR, "Device failure in %s\n", device);
if (_remove_failed_devices(device))
+ /* FIXME Why are all the error return codes unused? Get rid of them? */
syslog(LOG_ERR, "Failed to remove faulty devices in %s\n",
device);
/* Should check before warning user that device is now linear
@@ -203,52 +214,68 @@
case ME_IGNORE:
break;
default:
+ /* FIXME Provide value then! */
syslog(LOG_INFO, "Unknown event received.\n");
}
} while (next);
- fail:
- if (dmt)
- dm_task_destroy(dmt);
- pthread_mutex_unlock(&_lock);
+ pthread_mutex_unlock(&_event_mutex);
}
-int register_device(const char *device)
+int register_device(const char *device, const char *uuid, int major, int minor,
+ void **unused __attribute((unused)))
{
- syslog(LOG_INFO, "Monitoring mirror device, %s for events\n", device);
+ int r = 0;
+
+ pthread_mutex_lock(&_register_mutex);
+
+ syslog(LOG_INFO, "Monitoring mirror device %s for events\n", device);
/*
* Need some space for allocations. 1024 should be more
* than enough for what we need (device mapper name splitting)
*/
- if (!mem_pool)
- mem_pool = dm_pool_create("mirror_dso", 1024);
+ if (!_mem_pool && !(_mem_pool = dm_pool_create("mirror_dso", 1024)))
+ goto out;
- if (!mem_pool)
- return 0;
+ if (!_lvm_handle) {
+ lvm2_log_fn(_temporary_log_fn);
+ if (!(_lvm_handle = lvm2_init())) {
+ dm_pool_destroy(_mem_pool);
+ _mem_pool = NULL;
+ goto out;
+ }
+ lvm2_log_level(_lvm_handle, LVM2_LOG_SUPPRESS);
+ /* FIXME Temporary: move to dmeventd core */
+ lvm2_run(_lvm_handle, "_memlock_inc");
+ }
+
+ _register_count++;
+ r = 1;
- register_count++;
+out:
+ pthread_mutex_unlock(&_register_mutex);
- return 1;
+ return r;
}
-int unregister_device(const char *device)
+int unregister_device(const char *device, const char *uuid, int major, int minor,
+ void **unused __attribute((unused)))
{
- if (!(--register_count)) {
- dm_pool_destroy(mem_pool);
- mem_pool = NULL;
+ pthread_mutex_lock(&_register_mutex);
+
+ syslog(LOG_INFO, "No longer monitoring mirror device %s for events\n",
+ device);
+
+ if (!--_register_count) {
+ dm_pool_destroy(_mem_pool);
+ _mem_pool = NULL;
+ lvm2_run(_lvm_handle, "_memlock_dec");
+ lvm2_exit(_lvm_handle);
+ _lvm_handle = NULL;
}
- return 1;
-}
+ pthread_mutex_unlock(&_register_mutex);
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+ return 1;
+}
Modified: lvm2/trunk/doc/example.conf
==============================================================================
--- lvm2/trunk/doc/example.conf (original)
+++ lvm2/trunk/doc/example.conf Sat Apr 7 16:07:03 2007
@@ -56,10 +56,14 @@
# filter = [ "a|^/dev/hda8$|", "r/.*/" ]
# The results of the filtering are cached on disk to avoid
- # rescanning dud devices (which can take a very long time). By
- # default this cache file is hidden in the /etc/lvm directory.
- # It is safe to delete this file: the tools regenerate it.
- cache = "/etc/lvm/.cache"
+ # rescanning dud devices (which can take a very long time).
+ # By default this cache is stored in the /etc/lvm/cache directory
+ # in a file called '.cache'.
+ # It is safe to delete the contents: the tools regenerate it.
+ # (The old setting 'cache' is still respected if neither of
+ # these new ones is present.)
+ cache_dir = "/etc/lvm/cache"
+ cache_file_prefix = ""
# You can turn off writing this cache file by setting this to 0.
write_cache_state = 1
@@ -79,6 +83,12 @@
# software RAID (md) devices by looking for md superblocks.
# 1 enables; 0 disables.
md_component_detection = 1
+
+ # If, while scanning the system for PVs, LVM2 encounters a device-mapper
+ # device that has its I/O suspended, it waits for it to become accessible.
+ # Set this to 1 to skip such devices. This should only be needed
+ # in recovery situations.
+ ignore_suspended_devices = 0
}
# This section that allows you to configure the nature of the
@@ -182,6 +192,9 @@
# command. Defaults to off.
test = 0
+ # Default value for --units argument
+ units = "h"
+
# Whether or not to communicate with the kernel device-mapper.
# Set to 0 if you want to use the tools to manipulate LVM metadata
# without activating any logical volumes.
Modified: lvm2/trunk/lib/activate/activate.c
==============================================================================
--- lvm2/trunk/lib/activate/activate.c (original)
+++ lvm2/trunk/lib/activate/activate.c Sat Apr 7 16:07:03 2007
@@ -141,7 +141,7 @@
{
return 0;
}
-int target_present(const char *target_name)
+int target_present(const char *target_name, int use_modprobe)
{
return 0;
}
@@ -168,6 +168,10 @@
{
return 0;
}
+int lvs_in_vg_activated_by_uuid_only(struct volume_group *vg);
+{
+ return 0;
+}
int lvs_in_vg_opened(struct volume_group *vg)
{
return 0;
@@ -211,7 +215,7 @@
return 1;
}
-int pv_uses_vg(struct cmd_context *cmd, struct physical_volume *pv,
+int pv_uses_vg(struct physical_volume *pv,
struct volume_group *vg)
{
return 0;
@@ -421,21 +425,23 @@
* Returns 1 if info structure populated, else 0 on failure.
*/
static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv, int with_mknodes,
- struct lvinfo *info, int with_open_count)
+ struct lvinfo *info, int with_open_count, unsigned by_uuid_only)
{
struct dm_info dminfo;
- char *name;
+ char *name = NULL;
if (!activation())
return 0;
- if (!(name = build_dm_name(cmd->mem, lv->vg->name, lv->name, NULL)))
+ if (!by_uuid_only &&
+ !(name = build_dm_name(cmd->mem, lv->vg->name, lv->name, NULL)))
return_0;
log_debug("Getting device info for %s", name);
if (!dev_manager_info(lv->vg->cmd->mem, name, lv, with_mknodes,
with_open_count, &dminfo)) {
- dm_pool_free(cmd->mem, name);
+ if (name)
+ dm_pool_free(cmd->mem, name);
return_0;
}
@@ -448,14 +454,16 @@
info->live_table = dminfo.live_table;
info->inactive_table = dminfo.inactive_table;
- dm_pool_free(cmd->mem, name);
+ if (name)
+ dm_pool_free(cmd->mem, name);
+
return 1;
}
int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, struct lvinfo *info,
int with_open_count)
{
- return _lv_info(cmd, lv, 0, info, with_open_count);
+ return _lv_info(cmd, lv, 0, info, with_open_count, 0);
}
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
@@ -466,7 +474,7 @@
if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
return 0;
- return _lv_info(cmd, lv, 0, info, with_open_count);
+ return _lv_info(cmd, lv, 0, info, with_open_count, 0);
}
/*
@@ -519,11 +527,12 @@
return r;
}
-static int _lv_active(struct cmd_context *cmd, struct logical_volume *lv)
+static int _lv_active(struct cmd_context *cmd, struct logical_volume *lv,
+ unsigned by_uuid_only)
{
struct lvinfo info;
- if (!lv_info(cmd, lv, &info, 0)) {
+ if (!_lv_info(cmd, lv, 0, &info, 0, by_uuid_only)) {
stack;
return -1;
}
@@ -607,7 +616,7 @@
* These two functions return the number of visible LVs in the state,
* or -1 on error.
*/
-int lvs_in_vg_activated(struct volume_group *vg)
+static int _lvs_in_vg_activated(struct volume_group *vg, unsigned by_uuid_only)
{
struct lv_list *lvl;
int count = 0;
@@ -617,12 +626,22 @@
list_iterate_items(lvl, &vg->lvs) {
if (lvl->lv->status & VISIBLE_LV)
- count += (_lv_active(vg->cmd, lvl->lv) == 1);
+ count += (_lv_active(vg->cmd, lvl->lv, by_uuid_only) == 1);
}
return count;
}
+int lvs_in_vg_activated_by_uuid_only(struct volume_group *vg)
+{
+ return _lvs_in_vg_activated(vg, 1);
+}
+
+int lvs_in_vg_activated(struct volume_group *vg)
+{
+ return _lvs_in_vg_activated(vg, 0);
+}
+
int lvs_in_vg_opened(struct volume_group *vg)
{
struct lv_list *lvl;
@@ -640,50 +659,89 @@
}
/*
- * register_dev_for_events
- *
- * This function uses proper error codes (but breaks convention)
- * to return:
- * -1 on error
- * 0 if the lv's targets don't do event [un]registration
- * 0 if the lv is already [un]registered -- FIXME: not implemented
- * 1 if the lv had a segment which was [un]registered
- *
- * Returns: -1 on error
+ * Returns 0 if an attempt to (un)monitor the device failed.
+ * Returns 1 otherwise.
*/
-int register_dev_for_events(struct cmd_context *cmd,
- struct logical_volume *lv, int do_reg)
+int monitor_dev_for_events(struct cmd_context *cmd,
+ struct logical_volume *lv, int monitor)
{
#ifdef DMEVENTD
- int r = 0;
+ int i, pending = 0, monitored;
+ int r = 1;
struct list *tmp;
struct lv_segment *seg;
- int (*reg) (struct lv_segment *, int events);
+ int (*monitor_fn) (struct lv_segment *s, int e);
- if (do_reg && !dmeventd_register_mode())
+ /* skip dmeventd code altogether */
+ if (dmeventd_monitor_mode() == DMEVENTD_MONITOR_IGNORE)
+ return 1;
+
+ /*
+ * Nothing to do if dmeventd configured not to be used.
+ */
+ if (monitor && !dmeventd_monitor_mode())
return 1;
list_iterate(tmp, &lv->segments) {
seg = list_item(tmp, struct lv_segment);
- reg = NULL;
+ if (!seg_monitored(seg) || (seg->status & PVMOVE))
+ continue;
+
+ monitor_fn = NULL;
- if (do_reg) {
- if (seg->segtype->ops->target_register_events)
- reg = seg->segtype->ops->target_register_events;
- } else if (seg->segtype->ops->target_unregister_events)
- reg = seg->segtype->ops->target_unregister_events;
+ /* Check monitoring status */
+ if (seg->segtype->ops->target_monitored)
+ monitored = seg->segtype->ops->target_monitored(seg, &pending);
+ else
+ continue; /* segtype doesn't support registration */
+
+ /*
+ * FIXME: We should really try again if pending
+ */
+ monitored = (pending) ? 0 : monitored;
+
+ if (monitor) {
+ if (monitored)
+ log_verbose("%s/%s already monitored.", lv->vg->name, lv->name);
+ else if (seg->segtype->ops->target_monitor_events)
+ monitor_fn = seg->segtype->ops->target_monitor_events;
+ } else {
+ if (!monitored)
+ log_verbose("%s/%s already not monitored.", lv->vg->name, lv->name);
+ else if (seg->segtype->ops->target_unmonitor_events)
+ monitor_fn = seg->segtype->ops->target_unmonitor_events;
+ }
- if (!reg)
+ /* Do [un]monitor */
+ if (!monitor_fn)
continue;
+ log_verbose("%sonitoring %s/%s", monitor ? "M" : "Not m", lv->vg->name, lv->name);
+
/* FIXME specify events */
- if (!reg(seg, 0)) {
- stack;
- return -1;
+ if (!monitor_fn(seg, 0)) {
+ log_error("%s/%s: %s segment monitoring function failed.",
+ lv->vg->name, lv->name, seg->segtype->name);
+ return 0;
+ }
+
+ /* Check [un]monitor results */
+ /* Try a couple times if pending, but not forever... */
+ for (i = 0; i < 10; i++) {
+ pending = 0;
+ monitored = seg->segtype->ops->target_monitored(seg, &pending);
+ if (pending ||
+ (!monitored && monitor) ||
+ (monitored && !monitor))
+ log_very_verbose("%s/%s %smonitoring still pending: waiting...",
+ lv->vg->name, lv->name, monitor ? "" : "un");
+ else
+ break;
+ sleep(1);
}
- r = 1;
+ r = (monitored && monitor) || (!monitored && !monitor);
}
return r;
@@ -728,7 +786,7 @@
}
}
- if (register_dev_for_events(cmd, lv, 0) != 1)
+ if (!monitor_dev_for_events(cmd, lv, 0))
/* FIXME Consider aborting here */
stack;
@@ -786,7 +844,7 @@
memlock_dec();
fs_unlock();
- if (register_dev_for_events(cmd, lv, 1) != 1)
+ if (!monitor_dev_for_events(cmd, lv, 1))
stack;
return 1;
@@ -832,7 +890,7 @@
return 0;
}
- if (register_dev_for_events(cmd, lv, 0) != 1)
+ if (!monitor_dev_for_events(cmd, lv, 0))
stack;
memlock_inc();
@@ -905,7 +963,7 @@
memlock_dec();
fs_unlock();
- if (!register_dev_for_events(cmd, lv, 1) != 1)
+ if (!monitor_dev_for_events(cmd, lv, 1))
stack;
return r;
@@ -934,7 +992,7 @@
return r;
}
- if (!_lv_info(cmd, lv, 1, &info, 0))
+ if (!_lv_info(cmd, lv, 1, &info, 0, 0))
return_0;
if (info.exists)
Modified: lvm2/trunk/lib/activate/activate.h
==============================================================================
--- lvm2/trunk/lib/activate/activate.h (original)
+++ lvm2/trunk/lib/activate/activate.h Sat Apr 7 16:07:03 2007
@@ -83,10 +83,11 @@
* Return number of LVs in the VG that are active.
*/
int lvs_in_vg_activated(struct volume_group *vg);
+int lvs_in_vg_activated_by_uuid_only(struct volume_group *vg);
int lvs_in_vg_opened(struct volume_group *vg);
-int register_dev_for_events(struct cmd_context *cmd,
+int monitor_dev_for_events(struct cmd_context *cmd,
struct logical_volume *lv, int do_reg);
/*
@@ -95,4 +96,9 @@
int pv_uses_vg(struct physical_volume *pv,
struct volume_group *vg);
+/*
+ * Returns 1 if mapped device is not suspended.
+ */
+int device_is_usable(dev_t dev);
+
#endif
Modified: lvm2/trunk/lib/activate/dev_manager.c
==============================================================================
--- lvm2/trunk/lib/activate/dev_manager.c (original)
+++ lvm2/trunk/lib/activate/dev_manager.c Sat Apr 7 16:07:03 2007
@@ -25,6 +25,7 @@
#include "targets.h"
#include "config.h"
#include "filter.h"
+#include "activate.h"
#include <limits.h>
#include <dirent.h>
@@ -117,12 +118,10 @@
}
static int _info_run(const char *name, const char *dlid, struct dm_info *info,
- int mknodes, int with_open_count, struct dm_pool *mem,
- char **uuid_out)
+ int mknodes, int with_open_count)
{
int r = 0;
struct dm_task *dmt;
- const char *u;
int dmtask;
dmtask = mknodes ? DM_DEVICE_MKNODES : DM_DEVICE_INFO;
@@ -142,11 +141,58 @@
if (!dm_task_get_info(dmt, info))
goto_out;
- if (info->exists && uuid_out) {
- if (!(u = dm_task_get_uuid(dmt)))
- goto_out;
- *uuid_out = dm_pool_strdup(mem, u);
+ r = 1;
+
+ out:
+ dm_task_destroy(dmt);
+ return r;
+}
+
+int device_is_usable(dev_t dev)
+{
+ struct dm_task *dmt;
+ struct dm_info info;
+ const char *name;
+ uint64_t start, length;
+ char *target_type = NULL;
+ char *params;
+ void *next = NULL;
+ int r = 0;
+
+ if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) {
+ log_error("Failed to allocate dm_task struct to check dev status");
+ return 0;
}
+
+ if (!dm_task_set_major(dmt, MAJOR(dev)) || !dm_task_set_minor(dmt, MINOR(dev)))
+ goto_out;
+
+ if (!dm_task_run(dmt)) {
+ log_error("Failed to get state of mapped device");
+ goto out;
+ }
+
+ if (!dm_task_get_info(dmt, &info))
+ goto_out;
+
+ if (!info.exists || info.suspended)
+ goto out;
+
+ name = dm_task_get_name(dmt);
+
+ /* FIXME Also check for mirror block_on_error and mpath no paths */
+ /* For now, we exclude all mirrors */
+
+ do {
+ next = dm_get_next_target(dmt, next, &start, &length,
+ &target_type, ¶ms);
+ /* Skip if target type doesn't match */
+ if (!strcmp(target_type, "mirror"))
+ goto out;
+ } while (next);
+
+ /* FIXME Also check dependencies? */
+
r = 1;
out:
@@ -155,23 +201,20 @@
}
static int _info(const char *name, const char *dlid, int mknodes,
- int with_open_count, struct dm_info *info,
- struct dm_pool *mem, char **uuid_out)
+ int with_open_count, struct dm_info *info)
{
if (!mknodes && dlid && *dlid) {
- if (_info_run(NULL, dlid, info, 0, with_open_count, mem,
- uuid_out) &&
+ if (_info_run(NULL, dlid, info, 0, with_open_count) &&
info->exists)
return 1;
else if (_info_run(NULL, dlid + sizeof(UUID_PREFIX) - 1, info,
- 0, with_open_count, mem, uuid_out) &&
+ 0, with_open_count) &&
info->exists)
return 1;
}
if (name)
- return _info_run(name, NULL, info, mknodes, with_open_count,
- mem, uuid_out);
+ return _info_run(name, NULL, info, mknodes, with_open_count);
return 0;
}
@@ -187,8 +230,7 @@
return 0;
}
- return _info(name, dlid, with_mknodes, with_open_count, info,
- NULL, NULL);
+ return _info(name, dlid, with_mknodes, with_open_count, info);
}
/* FIXME Interface must cope with multiple targets */
@@ -593,7 +635,7 @@
return_0;
log_debug("Getting device info for %s [%s]", name, dlid);
- if (!_info(name, dlid, 0, 1, &info, dm->mem, NULL)) {
+ if (!_info(name, dlid, 0, 1, &info)) {
log_error("Failed to get info for %s [%s].", name, dlid);
return 0;
}
@@ -782,12 +824,19 @@
{
uint32_t s;
struct list *snh;
+ struct lv_segment *seg_present;
/* Ensure required device-mapper targets are loaded */
- if (seg->segtype->ops->target_present &&
- !seg->segtype->ops->target_present()) {
+ seg_present = find_cow(seg->lv) ? : seg;
+
+ log_debug("Checking kernel supports %s segment type for %s%s%s",
+ seg_present->segtype->name, seg->lv->name,
+ layer ? "-" : "", layer ? : "");
+
+ if (seg_present->segtype->ops->target_present &&
+ !seg_present->segtype->ops->target_present(seg_present)) {
log_error("Can't expand LV %s: %s target support missing "
- "from kernel?", seg->lv->name, seg->segtype->name);
+ "from kernel?", seg->lv->name, seg_present->segtype->name);
return 0;
}
@@ -986,6 +1035,8 @@
break;
case SUSPEND:
dm_tree_skip_lockfs(root);
+ if ((lv->status & MIRRORED) && !(lv->status & PVMOVE))
+ dm_tree_use_no_flush_suspend(root);
case SUSPEND_WITH_LOCKFS:
if (!dm_tree_suspend_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
goto_out;
@@ -1065,7 +1116,7 @@
{
struct dm_tree *dtree;
struct dm_tree_node *root;
- char dlid[sizeof(UUID_PREFIX) + sizeof(struct id) - 1];
+ char dlid[sizeof(UUID_PREFIX) + sizeof(struct id) - 1] __attribute((aligned(8)));
int r = 1;
if (!(dtree = dm_tree_create())) {
Modified: lvm2/trunk/lib/cache/lvmcache.c
==============================================================================
--- lvm2/trunk/lib/cache/lvmcache.c (original)
+++ lvm2/trunk/lib/cache/lvmcache.c Sat Apr 7 16:07:03 2007
@@ -114,7 +114,7 @@
struct list *devh, *tmp;
struct list devs;
struct device_list *devl;
- char vgid_found[ID_LEN + 1];
+ char vgid_found[ID_LEN + 1] __attribute((aligned(8)));
if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
return NULL;
@@ -151,7 +151,7 @@
struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid)
{
struct lvmcache_vginfo *vginfo;
- char id[ID_LEN + 1];
+ char id[ID_LEN + 1] __attribute((aligned(8)));
if (!_vgid_hash || !vgid)
return NULL;
@@ -186,7 +186,7 @@
struct lvmcache_info *info_from_pvid(const char *pvid)
{
struct lvmcache_info *info;
- char id[ID_LEN + 1];
+ char id[ID_LEN + 1] __attribute((aligned(8)));
if (!_pvid_hash || !pvid)
return NULL;
@@ -476,7 +476,8 @@
struct lvmcache_vginfo *primary_vginfo)
{
struct lvmcache_vginfo *last_vginfo = primary_vginfo;
- char uuid_primary[64], uuid_new[64];
+ char uuid_primary[64] __attribute((aligned(8)));
+ char uuid_new[64] __attribute((aligned(8)));
int use_new = 0;
/* Pre-existing VG takes precedence. Unexported VG takes precedence. */
@@ -709,7 +710,7 @@
{
struct pv_list *pvl;
struct lvmcache_info *info;
- char pvid_s[ID_LEN + 1];
+ char pvid_s[ID_LEN + 1] __attribute((aligned(8)));
pvid_s[sizeof(pvid_s) - 1] = '\0';
@@ -733,7 +734,7 @@
{
struct label *label;
struct lvmcache_info *existing, *info;
- char pvid_s[ID_LEN + 1];
+ char pvid_s[ID_LEN + 1] __attribute((aligned(8)));
if (!_vgname_hash && !lvmcache_init()) {
log_error("Internal cache initialisation failed");
Modified: lvm2/trunk/lib/commands/toolcontext.c
==============================================================================
--- lvm2/trunk/lib/commands/toolcontext.c (original)
+++ lvm2/trunk/lib/commands/toolcontext.c Sat Apr 7 16:07:03 2007
@@ -59,8 +59,6 @@
# include <malloc.h>
#endif
-static FILE *_log;
-
static int _get_env_vars(struct cmd_context *cmd)
{
const char *e;
@@ -330,7 +328,7 @@
return 0;
}
- if (!(cfl->cft = create_config_tree(config_file))) {
+ if (!(cfl->cft = create_config_tree(config_file, 0))) {
log_error("config_tree allocation failed");
return 0;
}
@@ -370,7 +368,7 @@
{
/* No config file if LVM_SYSTEM_DIR is empty */
if (!*cmd->sys_dir) {
- if (!(cmd->cft = create_config_tree(NULL))) {
+ if (!(cmd->cft = create_config_tree(NULL, 0))) {
log_error("Failed to create config tree");
return 0;
}
@@ -408,7 +406,7 @@
/* Replace temporary duplicate copy of lvm.conf */
if (cmd->cft->root) {
- if (!(cmd->cft = create_config_tree(NULL))) {
+ if (!(cmd->cft = create_config_tree(NULL, 0))) {
log_error("Failed to create config tree");
return 0;
}
@@ -575,9 +573,9 @@
filters[0] : composite_filter_create(nr_filt, filters);
}
-static int _init_filters(struct cmd_context *cmd)
+static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache)
{
- const char *dev_cache;
+ const char *dev_cache = NULL, *cache_dir, *cache_file_prefix;
struct dev_filter *f3, *f4;
struct stat st;
char cache_file[PATH_MAX];
@@ -587,16 +585,35 @@
if (!(f3 = _init_filter_components(cmd)))
return 0;
- if (dm_snprintf(cache_file, sizeof(cache_file),
- "%s/.cache", cmd->sys_dir) < 0) {
- log_error("Persistent cache filename too long ('%s/.cache').",
- cmd->sys_dir);
+ init_ignore_suspended_devices(find_config_tree_int(cmd,
+ "devices/ignore_suspended_devices", DEFAULT_IGNORE_SUSPENDED_DEVICES));
+
+ /*
+ * If 'cache_dir' or 'cache_file_prefix' is set, ignore 'cache'.
+ */
+ cache_dir = find_config_tree_str(cmd, "devices/cache_dir", NULL);
+ cache_file_prefix = find_config_tree_str(cmd, "devices/cache_file_prefix", NULL);
+
+ if (cache_dir || cache_file_prefix) {
+ if (dm_snprintf(cache_file, sizeof(cache_file),
+ "%s%s%s/%s.cache",
+ cache_dir ? "" : cmd->sys_dir,
+ cache_dir ? "" : "/",
+ cache_dir ? : DEFAULT_CACHE_SUBDIR,
+ cache_file_prefix ? : DEFAULT_CACHE_FILE_PREFIX) < 0) {
+ log_error("Persistent cache filename too long.");
+ return 0;
+ }
+ } else if (!(dev_cache = find_config_tree_str(cmd, "devices/cache", NULL)) &&
+ (dm_snprintf(cache_file, sizeof(cache_file),
+ "%s/%s/%s.cache",
+ cmd->sys_dir, DEFAULT_CACHE_SUBDIR,
+ DEFAULT_CACHE_FILE_PREFIX) < 0)) {
+ log_error("Persistent cache filename too long.");
return 0;
}
- dev_cache = find_config_tree_str(cmd, "devices/cache",
- cache_file);
- if (!(f4 = persistent_filter_create(f3, dev_cache))) {
+ if (!(f4 = persistent_filter_create(f3, dev_cache ? : cache_file))) {
log_error("Failed to create persistent device filter");
return 0;
}
@@ -608,9 +625,14 @@
if (!*cmd->sys_dir)
cmd->dump_filter = 0;
- if (!stat(dev_cache, &st) &&
- (st.st_mtime > config_file_timestamp(cmd->cft)) &&
- !persistent_filter_load(f4))
+ /*
+ * Only load persistent filter device cache on startup if it is newer
+ * than the config file and this is not a long-lived process.
+ */
+ if (load_persistent_cache && !cmd->is_long_lived &&
+ !stat(dev_cache, &st) &&
+ (st.st_ctime > config_file_timestamp(cmd->cft)) &&
+ !persistent_filter_load(f4, NULL))
log_verbose("Failed to load existing device cache from %s",
dev_cache);
@@ -748,7 +770,6 @@
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) {
@@ -775,18 +796,16 @@
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;
- }
-
+ list_iterate_items(segtype2, &cmd->segtypes) {
+ if ((segtype == segtype2) ||
+ strcmp(segtype2->name, segtype->name))
+ continue;
+ 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);
}
}
}
@@ -881,7 +900,8 @@
}
/* Entry point */
-struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static)
+struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static,
+ unsigned is_long_lived)
{
struct cmd_context *cmd;
@@ -905,6 +925,7 @@
memset(cmd, 0, sizeof(*cmd));
cmd->args = the_args;
cmd->is_static = is_static;
+ cmd->is_long_lived = is_long_lived;
cmd->hosttags = 0;
list_init(&cmd->formats);
list_init(&cmd->segtypes);
@@ -953,7 +974,7 @@
if (!_init_dev_cache(cmd))
goto error;
- if (!_init_filters(cmd))
+ if (!_init_filters(cmd, 1))
goto error;
if (!(cmd->mem = dm_pool_create("command", 4 * 1024))) {
@@ -1022,10 +1043,10 @@
{
log_verbose("Reloading config files");
- if (cmd->config_valid) {
- if (cmd->dump_filter)
- persistent_filter_dump(cmd->filter);
- }
+ /*
+ * Don't update the persistent filter cache as we will
+ * perform a full rescan.
+ */
activation_release();
lvmcache_destroy();
@@ -1064,7 +1085,7 @@
if (!_init_dev_cache(cmd))
return 0;
- if (!_init_filters(cmd))
+ if (!_init_filters(cmd, 0))
return 0;
if (!_init_formats(cmd))
@@ -1073,6 +1094,13 @@
if (!_init_segtypes(cmd))
return 0;
+ /*
+ * If we are a long-lived process, write out the updated persistent
+ * device cache for the benefit of short-lived processes.
+ */
+ if (cmd->is_long_lived && cmd->dump_filter)
+ persistent_filter_dump(cmd->filter);
+
cmd->config_valid = 1;
return 1;
}
@@ -1100,8 +1128,4 @@
activation_exit();
fin_log();
fin_syslog();
-
- if (_log)
- fclose(_log);
-
}
Modified: lvm2/trunk/lib/commands/toolcontext.h
==============================================================================
--- lvm2/trunk/lib/commands/toolcontext.h (original)
+++ lvm2/trunk/lib/commands/toolcontext.h Sat Apr 7 16:07:03 2007
@@ -65,6 +65,7 @@
struct arg *args;
char **argv;
unsigned is_static; /* Static binary? */
+ unsigned is_long_lived; /* Optimises persistent_filter handling */
struct dev_filter *filter;
int dump_filter; /* Dump filter when exiting? */
@@ -88,7 +89,7 @@
char proc_dir[PATH_MAX];
};
-struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static);
+struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static, unsigned is_long_lived);
void destroy_toolcontext(struct cmd_context *cmd);
int refresh_toolcontext(struct cmd_context *cmd);
int config_files_changed(struct cmd_context *cmd);
Modified: lvm2/trunk/lib/config/config.c
==============================================================================
--- lvm2/trunk/lib/config/config.c (original)
+++ lvm2/trunk/lib/config/config.c Sat Apr 7 16:07:03 2007
@@ -58,6 +58,8 @@
time_t timestamp;
char *filename;
int exists;
+ int keep_open;
+ struct device *dev;
};
static void _get_token(struct parser *p, int tok_prev);
@@ -95,7 +97,7 @@
/*
* public interface
*/
-struct config_tree *create_config_tree(const char *filename)
+struct config_tree *create_config_tree(const char *filename, int keep_open)
{
struct cs *c;
struct dm_pool *mem = dm_pool_create("config", 10 * 1024);
@@ -115,6 +117,8 @@
c->cft.root = (struct config_node *) NULL;
c->timestamp = 0;
c->exists = 0;
+ c->keep_open = keep_open;
+ c->dev = 0;
if (filename)
c->filename = dm_pool_strdup(c->mem, filename);
return &c->cft;
@@ -122,7 +126,12 @@
void destroy_config_tree(struct config_tree *cft)
{
- dm_pool_destroy(((struct cs *) cft)->mem);
+ struct cs *c = (struct cs *) cft;
+
+ if (c->dev)
+ dev_close(c->dev);
+
+ dm_pool_destroy(c->mem);
}
static int _parse_config_file(struct parser *p, struct config_tree *cft)
@@ -143,7 +152,7 @@
struct config_tree *cft;
struct parser *p;
- if (!(cft = create_config_tree(NULL)))
+ if (!(cft = create_config_tree(NULL, 0)))
return_NULL;
c = (struct cs *) cft;
@@ -250,7 +259,6 @@
{
struct cs *c = (struct cs *) cft;
struct stat info;
- struct device *dev;
int r = 1;
if (stat(c->filename, &info)) {
@@ -272,22 +280,23 @@
return 1;
}
- if (!(dev = dev_create_file(c->filename, NULL, NULL, 1))) {
- stack;
- return 0;
- }
+ if (!c->dev) {
+ if (!(c->dev = dev_create_file(c->filename, NULL, NULL, 1)))
+ return_0;
- if (!dev_open_flags(dev, O_RDONLY, 0, 0)) {
- stack;
- return 0;
+ if (!dev_open_flags(c->dev, O_RDONLY, 0, 0))
+ return_0;
}
- r = read_config_fd(cft, dev, 0, (size_t) info.st_size, 0, 0,
+ r = read_config_fd(cft, c->dev, 0, (size_t) info.st_size, 0, 0,
(checksum_fn_t) NULL, 0);
- dev_close(dev);
+ if (!c->keep_open) {
+ dev_close(c->dev);
+ c->dev = 0;
+ }
- c->timestamp = info.st_mtime;
+ c->timestamp = info.st_ctime;
return r;
}
@@ -331,7 +340,7 @@
}
/* Unchanged? */
- if (c->timestamp == info.st_mtime)
+ if (c->timestamp == info.st_ctime)
return 0;
reload:
@@ -364,7 +373,8 @@
}
}
-static int _write_config(struct config_node *n, FILE *fp, int level)
+static int _write_config(struct config_node *n, int only_one, FILE *fp,
+ int level)
{
char space[MAX_INDENT + 1];
int l = (level < MAX_INDENT) ? level : MAX_INDENT;
@@ -377,12 +387,12 @@
space[i] = '\t';
space[i] = '\0';
- while (n) {
+ do {
fprintf(fp, "%s%s", space, n->key);
if (!n->v) {
/* it's a sub section */
fprintf(fp, " {\n");
- _write_config(n->child, fp, level + 1);
+ _write_config(n->child, 0, fp, level + 1);
fprintf(fp, "%s}", space);
} else {
/* it's a value */
@@ -402,13 +412,15 @@
}
fprintf(fp, "\n");
n = n->sib;
- }
+ } while (n && !only_one);
/* FIXME: add error checking */
return 1;
}
-int write_config_file(struct config_tree *cft, const char *file)
+int write_config_file(struct config_tree *cft, const char *file,
+ int argc, char **argv)
{
+ struct config_node *cn;
int r = 1;
FILE *fp;
@@ -421,13 +433,28 @@
}
log_verbose("Dumping configuration to %s", file);
- if (!_write_config(cft->root, fp, 0)) {
- log_error("Failure while writing configuration");
- r = 0;
+ if (!argc) {
+ if (!_write_config(cft->root, 0, fp, 0)) {
+ log_error("Failure while writing to %s", file);
+ r = 0;
+ }
+ } else while (argc--) {
+ if ((cn = find_config_node(cft->root, *argv))) {
+ if (!_write_config(cn, 1, fp, 0)) {
+ log_error("Failure while writing to %s", file);
+ r = 0;
+ }
+ } else {
+ log_error("Configuration node %s not found", *argv);
+ r = 0;
+ }
+ argv++;
}
- if (fp != stdout)
- fclose(fp);
+ if ((fp != stdout) && fclose(fp)) {
+ log_sys_error("fclose", file);
+ r = 0;
+ }
return r;
}
@@ -763,6 +790,7 @@
const char *path)
{
const char *e;
+ const struct config_node *cn_found = NULL;
while (cn) {
/* trim any leading slashes */
@@ -773,22 +801,30 @@
for (e = path; *e && (*e != sep); e++) ;
/* hunt for the node */
+ cn_found = NULL;
while (cn) {
- if (_tok_match(cn->key, path, e))
- break;
+ if (_tok_match(cn->key, path, e)) {
+ /* Inefficient */
+ if (!cn_found)
+ cn_found = cn;
+ else
+ log_error("WARNING: Ignoring duplicate"
+ " config node: %s ("
+ "seeking %s)", cn->key, path);
+ }
cn = cn->sib;
}
- if (cn && *e)
- cn = cn->child;
+ if (cn_found && *e)
+ cn = cn_found->child;
else
break; /* don't move into the last node */
path = e;
}
- return (struct config_node *) cn;
+ return (struct config_node *) cn_found;
}
static struct config_node *_find_first_config_node(const struct config_node *cn1,
@@ -819,7 +855,7 @@
const struct config_node *n = _find_first_config_node(cn1, cn2, path);
/* Empty strings are ignored */
- if ((n && n->v->type == CFG_STRING) && (*n->v->v.str)) {
+ if ((n && n->v && n->v->type == CFG_STRING) && (*n->v->v.str)) {
log_very_verbose("Setting %s to %s", path, n->v->v.str);
return n->v->v.str;
}
@@ -842,7 +878,7 @@
{
const struct config_node *n = _find_first_config_node(cn1, cn2, path);
- if (n && n->v->type == CFG_INT) {
+ if (n && n->v && n->v->type == CFG_INT) {
log_very_verbose("Setting %s to %d", path, n->v->v.i);
return n->v->v.i;
}
@@ -863,7 +899,7 @@
{
const struct config_node *n = _find_first_config_node(cn1, cn2, path);
- if (n && n->v->type == CFG_FLOAT) {
+ if (n && n->v && n->v->type == CFG_FLOAT) {
log_very_verbose("Setting %s to %f", path, n->v->v.r);
return n->v->v.r;
}
Modified: lvm2/trunk/lib/config/config.h
==============================================================================
--- lvm2/trunk/lib/config/config.h (original)
+++ lvm2/trunk/lib/config/config.h Sat Apr 7 16:07:03 2007
@@ -53,7 +53,7 @@
struct config_tree *cft;
};
-struct config_tree *create_config_tree(const char *filename);
+struct config_tree *create_config_tree(const char *filename, int keep_open);
struct config_tree *create_config_tree_from_string(struct cmd_context *cmd,
const char *config_settings);
void destroy_config_tree(struct config_tree *cft);
@@ -65,7 +65,8 @@
checksum_fn_t checksum_fn, uint32_t checksum);
int read_config_file(struct config_tree *cft);
-int write_config_file(struct config_tree *cft, const char *file);
+int write_config_file(struct config_tree *cft, const char *file,
+ int argc, char **argv);
time_t config_file_timestamp(struct config_tree *cft);
int config_file_changed(struct config_tree *cft);
int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft,
Modified: lvm2/trunk/lib/config/defaults.h
==============================================================================
--- lvm2/trunk/lib/config/defaults.h (original)
+++ lvm2/trunk/lib/config/defaults.h Sat Apr 7 16:07:03 2007
@@ -21,6 +21,8 @@
#define DEFAULT_ARCHIVE_SUBDIR "archive"
#define DEFAULT_BACKUP_SUBDIR "backup"
+#define DEFAULT_CACHE_SUBDIR "cache"
+#define DEFAULT_CACHE_FILE_PREFIX ""
#define DEFAULT_ARCHIVE_DAYS 30
#define DEFAULT_ARCHIVE_NUMBER 10
@@ -30,6 +32,7 @@
#define DEFAULT_PROC_DIR "/proc"
#define DEFAULT_SYSFS_SCAN 1
#define DEFAULT_MD_COMPONENT_DETECTION 1
+#define DEFAULT_IGNORE_SUSPENDED_DEVICES 1
#define DEFAULT_LOCK_DIR "/var/lock/lvm"
#define DEFAULT_LOCKING_LIB "liblvm2clusterlock.so"
Modified: lvm2/trunk/lib/device/dev-io.c
==============================================================================
--- lvm2/trunk/lib/device/dev-io.c (original)
+++ lvm2/trunk/lib/device/dev-io.c Sat Apr 7 16:07:03 2007
@@ -292,11 +292,14 @@
if (ioctl(fd, BLKSSZGET, &s) < 0) {
log_sys_error("ioctl BLKSSZGET", name);
- close(fd);
+ if (close(fd))
+ log_sys_error("close", name);
return 0;
}
- close(fd);
+ if (close(fd))
+ log_sys_error("close", name);
+
*size = (uint32_t) s;
log_very_verbose("%s: sector size is %" PRIu32 " bytes", name, *size);
@@ -605,7 +608,7 @@
int dev_set(struct device *dev, uint64_t offset, size_t len, int value)
{
size_t s;
- char buffer[4096];
+ char buffer[4096] __attribute((aligned(8)));
if (!dev_open(dev)) {
stack;
Modified: lvm2/trunk/lib/device/dev-md.c
==============================================================================
--- lvm2/trunk/lib/device/dev-md.c (original)
+++ lvm2/trunk/lib/device/dev-md.c Sat Apr 7 16:07:03 2007
@@ -53,8 +53,10 @@
sb_offset = MD_NEW_SIZE_SECTORS(size) << SECTOR_SHIFT;
/* Check if it is an md component device. */
+ /* Version 1 is little endian; version 0.90.0 is machine endian */
if (dev_read(dev, sb_offset, sizeof(uint32_t), &md_magic) &&
- (md_magic == xlate32(MD_SB_MAGIC))) {
+ ((md_magic == xlate32(MD_SB_MAGIC)) ||
+ (md_magic == MD_SB_MAGIC))) {
if (sb)
*sb = sb_offset;
ret = 1;
Modified: lvm2/trunk/lib/device/device.c
==============================================================================
--- lvm2/trunk/lib/device/device.c (original)
+++ lvm2/trunk/lib/device/device.c Sat Apr 7 16:07:03 2007
@@ -53,7 +53,7 @@
{
int ret = 0;
unsigned p;
- uint8_t buf[SECTOR_SIZE];
+ uint16_t buf[SECTOR_SIZE/sizeof(uint16_t)];
uint16_t *part_magic;
struct partition *part;
@@ -70,9 +70,9 @@
/* FIXME Check for other types of partition table too */
/* Check for msdos partition table */
- part_magic = (uint16_t *)(buf + PART_MAGIC_OFFSET);
+ part_magic = buf + PART_MAGIC_OFFSET/sizeof(buf[0]);
if ((*part_magic == xlate16(PART_MAGIC))) {
- part = (struct partition *) (buf + PART_OFFSET);
+ part = (struct partition *) (buf + PART_OFFSET/sizeof(buf[0]));
for (p = 0; p < 4; p++, part++) {
/* Table is invalid if boot indicator not 0 or 0x80 */
if ((part->boot_ind & 0x7f)) {
Modified: lvm2/trunk/lib/display/display.c
==============================================================================
--- lvm2/trunk/lib/display/display.c (original)
+++ lvm2/trunk/lib/display/display.c Sat Apr 7 16:07:03 2007
@@ -82,6 +82,12 @@
case 't':
v *= KILO * KILO * KILO * KILO;
break;
+ case 'p':
+ v *= KILO * KILO * KILO * KILO * KILO;
+ break;
+ case 'e':
+ v *= KILO * KILO * KILO * KILO * KILO * KILO;
+ break;
#undef KILO
#define KILO UINT64_C(1000)
case 'K':
@@ -96,6 +102,12 @@
case 'T':
v *= KILO * KILO * KILO * KILO;
break;
+ case 'P':
+ v *= KILO * KILO * KILO * KILO * KILO;
+ break;
+ case 'E':
+ v *= KILO * KILO * KILO * KILO * KILO * KILO;
+ break;
#undef KILO
default:
return 0;
@@ -143,6 +155,8 @@
uint64_t units = UINT64_C(1024);
char *size_buf = NULL;
const char *size_str[][3] = {
+ {" Exabyte", " EB", "E"},
+ {" Petabyte", " PB", "P"},
{" Terabyte", " TB", "T"},
{" Gigabyte", " GB", "G"},
{" Megabyte", " MB", "M"},
@@ -161,7 +175,7 @@
suffix = cmd->current_settings.suffix;
- for (s = 0; s < 8; s++)
+ for (s = 0; s < 10; s++)
if (toupper((int) cmd->current_settings.unit_type) ==
*size_str[s][2])
break;
@@ -171,7 +185,7 @@
return size_buf;
}
- if (s < 8) {
+ if (s < 10) {
byte = cmd->current_settings.unit_factor;
size *= UINT64_C(512);
} else {
@@ -181,7 +195,7 @@
units = UINT64_C(1000);
else
units = UINT64_C(1024);
- byte = units * units * units;
+ byte = units * units * units * units * units;
s = 0;
while (size_str[s] && size < byte)
s++, byte /= units;
@@ -220,7 +234,7 @@
void pvdisplay_colons(struct physical_volume *pv)
{
- char uuid[64];
+ char uuid[64] __attribute((aligned(8)));
if (!pv)
return;
@@ -248,7 +262,7 @@
void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
void *handle __attribute((unused)))
{
- char uuid[64];
+ char uuid[64] __attribute((aligned(8)));
const char *size;
uint32_t pe_free;
@@ -310,7 +324,7 @@
struct physical_volume *pv,
void *handle __attribute((unused)))
{
- char uuid[64];
+ char uuid[64] __attribute((aligned(8)));
if (!pv)
return 0;
@@ -357,7 +371,7 @@
{
struct lvinfo info;
int inkernel, snap_active = 0;
- char uuid[64];
+ char uuid[64] __attribute((aligned(8)));
struct lv_segment *snap_seg = NULL;
float snap_percent; /* fused, fsize; */
@@ -523,7 +537,7 @@
{
uint32_t access;
uint32_t active_pvs;
- char uuid[64];
+ char uuid[64] __attribute((aligned(8)));
if (vg->status & PARTIAL_VG)
active_pvs = list_size(&vg->pvs);
@@ -602,7 +616,7 @@
{
uint32_t active_pvs;
const char *access;
- char uuid[64];
+ char uuid[64] __attribute((aligned(8)));
if (vg->status & PARTIAL_VG)
active_pvs = list_size(&vg->pvs);
Modified: lvm2/trunk/lib/error/errseg.c
==============================================================================
--- lvm2/trunk/lib/error/errseg.c (original)
+++ lvm2/trunk/lib/error/errseg.c Sat Apr 7 16:07:03 2007
@@ -50,7 +50,7 @@
return dm_tree_node_add_error_target(node, len);
}
-static int _errseg_target_present(void)
+static int _errseg_target_present(const struct lv_segment *seg __attribute((unused)))
{
static int _errseg_checked = 0;
static int _errseg_present = 0;
Modified: lvm2/trunk/lib/filters/filter-persistent.c
==============================================================================
--- lvm2/trunk/lib/filters/filter-persistent.c (original)
+++ lvm2/trunk/lib/filters/filter-persistent.c Sat Apr 7 16:07:03 2007
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -17,6 +17,7 @@
#include "config.h"
#include "dev-cache.h"
#include "filter-persistent.h"
+#include "lvm-file.h"
#include <sys/stat.h>
#include <fcntl.h>
@@ -26,11 +27,12 @@
char *file;
struct dm_hash_table *devices;
struct dev_filter *real;
+ time_t ctime;
};
/*
- * entries in the table can be in one of these
- * states.
+ * The hash table holds one of these two states
+ * against each entry.
*/
#define PF_BAD_DEVICE ((void *) 1)
#define PF_GOOD_DEVICE ((void *) 2)
@@ -93,22 +95,26 @@
return 1;
}
-int persistent_filter_load(struct dev_filter *f)
+int persistent_filter_load(struct dev_filter *f, struct config_tree **cft_out)
{
struct pfilter *pf = (struct pfilter *) f->private;
-
- int r = 0;
struct config_tree *cft;
+ struct stat info;
+ int r = 0;
- if (!(cft = create_config_tree(pf->file))) {
- stack;
- return 0;
+ if (!stat(pf->file, &info))
+ pf->ctime = info.st_ctime;
+ else {
+ log_very_verbose("%s: stat failed: %s", pf->file,
+ strerror(errno));
+ return_0;
}
- if (!read_config_file(cft)) {
- stack;
- goto out;
- }
+ if (!(cft = create_config_tree(pf->file, 1)))
+ return_0;
+
+ if (!read_config_file(cft))
+ goto_out;
_read_array(pf, cft, "persistent_filter_cache/valid_devices",
PF_GOOD_DEVICE);
@@ -126,7 +132,10 @@
log_very_verbose("Loaded persistent filter cache from %s", pf->file);
out:
- destroy_config_tree(cft);
+ if (r && cft_out)
+ *cft_out = cft;
+ else
+ destroy_config_tree(cft);
return r;
}
@@ -163,8 +172,12 @@
int persistent_filter_dump(struct dev_filter *f)
{
struct pfilter *pf = (struct pfilter *) f->private;
-
+ char *tmp_file;
+ struct stat info, info2;
+ struct config_tree *cft = NULL;
FILE *fp;
+ int lockfd;
+ int r = 0;
if (!dm_hash_get_num_entries(pf->devices)) {
log_very_verbose("Internal persistent device cache empty "
@@ -179,11 +192,43 @@
log_very_verbose("Dumping persistent device cache to %s", pf->file);
- fp = fopen(pf->file, "w");
- if (!fp) {
- if (errno != EROFS)
- log_sys_error("fopen", pf->file);
- return 0;
+ while (1) {
+ if ((lockfd = fcntl_lock_file(pf->file, F_WRLCK, 0)) < 0)
+ return_0;
+
+ /*
+ * Ensure we locked the file we expected
+ */
+ if (fstat(lockfd, &info)) {
+ log_sys_error("fstat", pf->file);
+ goto out;
+ }
+ if (stat(pf->file, &info2)) {
+ log_sys_error("stat", pf->file);
+ goto out;
+ }
+
+ if (!memcmp(&info.st_ino, &info2.st_ino, sizeof(ino_t)))
+ break;
+
+ fcntl_unlock_file(lockfd);
+ }
+
+ /*
+ * If file contents changed since we loaded it, merge new contents
+ */
+ if (info.st_ctime != pf->ctime)
+ /* Keep cft open to avoid losing lock */
+ persistent_filter_load(f, &cft);
+
+ tmp_file = alloca(strlen(pf->file) + 5);
+ sprintf(tmp_file, "%s.tmp", pf->file);
+
+ if (!(fp = fopen(tmp_file, "w"))) {
+ /* EACCES has been reported over NFS */
+ if (errno != EROFS && errno != EACCES)
+ log_sys_error("fopen", tmp_file);
+ goto out;
}
fprintf(fp, "# This file is automatically maintained by lvm.\n\n");
@@ -194,8 +239,24 @@
/* _write_array(pf, fp, "invalid_devices", PF_BAD_DEVICE); */
fprintf(fp, "}\n");
- fclose(fp);
- return 1;
+ if (fclose(fp)) {
+ log_sys_error("fclose", tmp_file);
+ goto out;
+ }
+
+ if (rename(tmp_file, pf->file))
+ log_error("%s: rename to %s failed: %s", tmp_file, pf->file,
+ strerror(errno));
+
+ r = 1;
+
+out:
+ fcntl_unlock_file(lockfd);
+
+ if (cft)
+ destroy_config_tree(cft);
+
+ return r;
}
static int _lookup_p(struct dev_filter *f, struct device *dev)
Modified: lvm2/trunk/lib/filters/filter-persistent.h
==============================================================================
--- lvm2/trunk/lib/filters/filter-persistent.h (original)
+++ lvm2/trunk/lib/filters/filter-persistent.h Sat Apr 7 16:07:03 2007
@@ -22,7 +22,7 @@
const char *file);
int persistent_filter_wipe(struct dev_filter *f);
-int persistent_filter_load(struct dev_filter *f);
+int persistent_filter_load(struct dev_filter *f, struct config_tree **cft_out);
int persistent_filter_dump(struct dev_filter *f);
#endif
Modified: lvm2/trunk/lib/filters/filter-sysfs.c
==============================================================================
--- lvm2/trunk/lib/filters/filter-sysfs.c (original)
+++ lvm2/trunk/lib/filters/filter-sysfs.c Sat Apr 7 16:07:03 2007
@@ -54,7 +54,9 @@
}
}
- fclose(fp);
+ if (fclose(fp))
+ log_sys_error("fclose", proc_mounts);
+
return r;
}
@@ -156,7 +158,9 @@
}
r = _parse_dev(file, fp, result);
- fclose(fp);
+
+ if (fclose(fp))
+ log_sys_error("fclose", file);
return r;
}
Modified: lvm2/trunk/lib/filters/filter.c
==============================================================================
--- lvm2/trunk/lib/filters/filter.c (original)
+++ lvm2/trunk/lib/filters/filter.c Sat Apr 7 16:07:03 2007
@@ -19,6 +19,7 @@
#include "lvm-string.h"
#include "config.h"
#include "metadata.h"
+#include "activate.h"
#include <dirent.h>
#include <unistd.h>
@@ -37,6 +38,7 @@
} device_info_t;
static int _md_major = -1;
+static int _device_mapper_major = -1;
int md_major(void)
{
@@ -90,6 +92,13 @@
return 0;
}
+ /* Skip suspended devices */
+ if (MAJOR(dev->dev) == _device_mapper_major &&
+ ignore_suspended_devices() && !device_is_usable(dev->dev)) {
+ log_debug("%s: Skipping: Suspended dm device", name);
+ return 0;
+ }
+
/* Check it's accessible */
if (!dev_open_flags(dev, O_RDONLY, 0, 1)) {
log_debug("%s: Skipping: open failed", name);
@@ -182,10 +191,14 @@
if (!strncmp("md", line + i, 2) && isspace(*(line + i + 2)))
_md_major = line_maj;
+ /* Look for device-mapper device */
+ /* FIXME Cope with multiple majors */
+ if (!strncmp("device-mapper", line + i, 13) && isspace(*(line + i + 13)))
+ _device_mapper_major = line_maj;
+
/* Go through the valid device names and if there is a
match store max number of partitions */
for (j = 0; device_info[j].name != NULL; j++) {
-
dev_len = strlen(device_info[j].name);
if (dev_len <= strlen(line + i) &&
!strncmp(device_info[j].name, line + i, dev_len) &&
@@ -204,7 +217,8 @@
if (cv->type != CFG_STRING) {
log_error("Expecting string in devices/types "
"in config file");
- fclose(pd);
+ if (fclose(pd))
+ log_sys_error("fclose", proc_devices);
return 0;
}
dev_len = strlen(cv->v.str);
@@ -214,14 +228,16 @@
log_error("Max partition count missing for %s "
"in devices/types in config file",
name);
- fclose(pd);
+ if (fclose(pd))
+ log_sys_error("fclose", proc_devices);
return 0;
}
if (!cv->v.i) {
log_error("Zero partition count invalid for "
"%s in devices/types in config file",
name);
- fclose(pd);
+ if (fclose(pd))
+ log_sys_error("fclose", proc_devices);
return 0;
}
if (dev_len <= strlen(line + i) &&
@@ -232,7 +248,10 @@
}
}
}
- fclose(pd);
+
+ if (fclose(pd))
+ log_sys_error("fclose", proc_devices);
+
return 1;
}
Modified: lvm2/trunk/lib/format1/disk-rep.c
==============================================================================
--- lvm2/trunk/lib/format1/disk-rep.c (original)
+++ lvm2/trunk/lib/format1/disk-rep.c Sat Apr 7 16:07:03 2007
@@ -248,7 +248,7 @@
{
unsigned num_read = 0;
struct uuid_list *ul;
- char buffer[NAME_LEN];
+ char buffer[NAME_LEN] __attribute((aligned(8)));
uint64_t pos = data->pvd.pv_uuidlist_on_disk.base;
uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size;
Modified: lvm2/trunk/lib/format1/disk-rep.h
==============================================================================
--- lvm2/trunk/lib/format1/disk-rep.h (original)
+++ lvm2/trunk/lib/format1/disk-rep.h Sat Apr 7 16:07:03 2007
@@ -148,7 +148,7 @@
struct uuid_list {
struct list list;
- char uuid[NAME_LEN];
+ char uuid[NAME_LEN] __attribute((aligned(8)));
};
struct lvd_list {
@@ -161,11 +161,11 @@
struct dm_pool *mem;
struct device *dev;
- struct pv_disk pvd;
- struct vg_disk vgd;
- struct list uuids;
- struct list lvds;
- struct pe_disk *extents;
+ struct pv_disk pvd __attribute((aligned(8)));
+ struct vg_disk vgd __attribute((aligned(8)));
+ struct list uuids __attribute((aligned(8)));
+ struct list lvds __attribute((aligned(8)));
+ struct pe_disk *extents __attribute((aligned(8)));
};
/*
@@ -203,8 +203,8 @@
* Functions to translate to between disk and in
* core structures.
*/
-int import_pv(struct dm_pool *mem, struct device *dev,
- struct volume_group *vg,
+int import_pv(const struct format_type *fmt, struct dm_pool *mem,
+ struct device *dev, struct volume_group *vg,
struct physical_volume *pv, struct pv_disk *pvd,
struct vg_disk *vgd);
int export_pv(struct cmd_context *cmd, struct dm_pool *mem,
Modified: lvm2/trunk/lib/format1/format1.c
==============================================================================
--- lvm2/trunk/lib/format1/format1.c (original)
+++ lvm2/trunk/lib/format1/format1.c Sat Apr 7 16:07:03 2007
@@ -312,7 +312,7 @@
goto out;
}
- if (!import_pv(fmt->cmd->mem, dl->dev, NULL, pv, &dl->pvd, &dl->vgd)) {
+ if (!import_pv(fmt, fmt->cmd->mem, dl->dev, NULL, pv, &dl->pvd, &dl->vgd)) {
stack;
goto out;
}
Modified: lvm2/trunk/lib/format1/import-export.c
==============================================================================
--- lvm2/trunk/lib/format1/import-export.c (original)
+++ lvm2/trunk/lib/format1/import-export.c Sat Apr 7 16:07:03 2007
@@ -24,6 +24,7 @@
#include "toolcontext.h"
#include "segtype.h"
#include "pv_alloc.h"
+#include "display.h"
#include <time.h>
@@ -47,11 +48,13 @@
return dm_pool_strdup(mem, ptr);
}
-int import_pv(struct dm_pool *mem, struct device *dev,
- struct volume_group *vg,
+int import_pv(const struct format_type *fmt, struct dm_pool *mem,
+ struct device *dev, struct volume_group *vg,
struct physical_volume *pv, struct pv_disk *pvd,
struct vg_disk *vgd)
{
+ uint64_t size;
+
memset(pv, 0, sizeof(*pv));
memcpy(&pv->id, pvd->pv_uuid, ID_LEN);
@@ -89,6 +92,25 @@
pv->pe_count = pvd->pe_total;
pv->pe_alloc_count = 0;
+ /* Fix up pv size if missing */
+ if (!pv->size) {
+ if (!dev_get_size(dev, &pv->size)) {
+ log_error("%s: Couldn't get size.", dev_name(pv->dev));
+ return 0;
+ }
+ log_verbose("Fixing up missing format1 size (%s) "
+ "for PV %s", display_size(fmt->cmd, pv->size),
+ dev_name(pv->dev));
+ if (vg) {
+ size = pv->pe_count * (uint64_t) vg->extent_size +
+ pv->pe_start;
+ if (size > pv->size)
+ log_error("WARNING: Physical Volume %s is too "
+ "large for underlying device",
+ dev_name(pv->dev));
+ }
+ }
+
list_init(&pv->tags);
list_init(&pv->segments);
@@ -427,7 +449,7 @@
return 0;
}
- if (!import_pv(mem, dl->dev, vg, pvl->pv, &dl->pvd, &dl->vgd)) {
+ if (!import_pv(fmt, mem, dl->dev, vg, pvl->pv, &dl->pvd, &dl->vgd)) {
stack;
return 0;
}
Modified: lvm2/trunk/lib/format1/import-extents.c
==============================================================================
--- lvm2/trunk/lib/format1/import-extents.c (original)
+++ lvm2/trunk/lib/format1/import-extents.c Sat Apr 7 16:07:03 2007
@@ -203,6 +203,19 @@
return 1;
}
+static uint32_t _area_length(struct lv_map *lvm, uint32_t le)
+{
+ uint32_t len = 0;
+
+ do
+ len++;
+ while ((lvm->map[le + len].pv == lvm->map[le].pv) &&
+ (lvm->map[le].pv &&
+ lvm->map[le + len].pe == lvm->map[le].pe + len));
+
+ return len;
+}
+
static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
{
uint32_t le = 0, len;
@@ -215,13 +228,7 @@
}
while (le < lvm->lv->le_count) {
- len = 0;
-
- do
- len++;
- while ((lvm->map[le + len].pv == lvm->map[le].pv) &&
- (lvm->map[le].pv &&
- lvm->map[le + len].pe == lvm->map[le].pe + len));
+ len = _area_length(lvm, le);
if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv, le,
len, 0, 0, NULL, 1, len, 0, 0, 0))) {
@@ -230,10 +237,8 @@
}
if (!set_lv_segment_area_pv(seg, 0, lvm->map[le].pv,
- lvm->map[le].pe)) {
- stack;
- return 0;
- }
+ lvm->map[le].pe))
+ return_0;
list_add(&lvm->lv->segments, &seg->list);
@@ -244,7 +249,8 @@
}
static int _check_stripe(struct lv_map *lvm, uint32_t area_count,
- uint32_t seg_len, uint32_t base_le, uint32_t len)
+ uint32_t area_len, uint32_t base_le,
+ uint32_t total_area_len)
{
uint32_t st;
@@ -252,11 +258,11 @@
* Is the next physical extent in every stripe adjacent to the last?
*/
for (st = 0; st < area_count; st++)
- if ((lvm->map[base_le + st * len + seg_len].pv !=
- lvm->map[base_le + st * len].pv) ||
- (lvm->map[base_le + st * len].pv &&
- lvm->map[base_le + st * len + seg_len].pe !=
- lvm->map[base_le + st * len].pe + seg_len))
+ if ((lvm->map[base_le + st * total_area_len + area_len].pv !=
+ lvm->map[base_le + st * total_area_len].pv) ||
+ (lvm->map[base_le + st * total_area_len].pv &&
+ lvm->map[base_le + st * total_area_len + area_len].pe !=
+ lvm->map[base_le + st * total_area_len].pe + area_len))
return 0;
return 1;
@@ -264,7 +270,7 @@
static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
{
- uint32_t st, le = 0, len;
+ uint32_t st, first_area_le = 0, total_area_len;
uint32_t area_len;
struct lv_segment *seg;
struct segment_type *segtype;
@@ -277,26 +283,25 @@
"with logical extent count (%u) for %s",
lvm->stripes, lvm->lv->le_count, lvm->lv->name);
}
- len = lvm->lv->le_count / lvm->stripes;
- if (!(segtype = get_segtype_from_string(cmd, "striped"))) {
- stack;
- return 0;
- }
+ total_area_len = lvm->lv->le_count / lvm->stripes;
+
+ if (!(segtype = get_segtype_from_string(cmd, "striped")))
+ return_0;
- while (le < len) {
+ while (first_area_le < total_area_len) {
area_len = 1;
/*
- * Find how many blocks are contiguous in all stripes
+ * Find how many extents are contiguous in all stripes
* and so can form part of this segment
*/
while (_check_stripe(lvm, lvm->stripes,
- area_len * lvm->stripes, le, len))
+ area_len, first_area_le, total_area_len))
area_len++;
if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv,
- lvm->stripes * le,
+ lvm->stripes * first_area_le,
lvm->stripes * area_len,
0, lvm->stripe_size, NULL,
lvm->stripes,
@@ -310,15 +315,13 @@
*/
for (st = 0; st < seg->area_count; st++)
if (!set_lv_segment_area_pv(seg, st,
- lvm->map[le + st * len].pv,
- lvm->map[le + st * len].pe)) {
- stack;
- return 0;
- }
+ lvm->map[first_area_le + st * total_area_len].pv,
+ lvm->map[first_area_le + st * total_area_len].pe))
+ return_0;
list_add(&lvm->lv->segments, &seg->list);
- le += seg->len;
+ first_area_le += area_len;
}
return 1;
Modified: lvm2/trunk/lib/format1/lvm1-label.c
==============================================================================
--- lvm2/trunk/lib/format1/lvm1-label.c (original)
+++ lvm2/trunk/lib/format1/lvm1-label.c Sat Apr 7 16:07:03 2007
@@ -30,7 +30,7 @@
op);
}
-static int _lvm1_can_handle(struct labeller *l, char *buf, uint64_t sector)
+static int _lvm1_can_handle(struct labeller *l, void *buf, uint64_t sector)
{
struct pv_disk *pvd = (struct pv_disk *) buf;
uint32_t version;
@@ -48,13 +48,13 @@
return 0;
}
-static int _lvm1_write(struct label *label, char *buf)
+static int _lvm1_write(struct label *label, void *buf)
{
_not_supported("write");
return 0;
}
-static int _lvm1_read(struct labeller *l, struct device *dev, char *buf,
+static int _lvm1_read(struct labeller *l, struct device *dev, void *buf,
struct label **label)
{
struct pv_disk *pvd = (struct pv_disk *) buf;
Modified: lvm2/trunk/lib/format_pool/disk_rep.c
==============================================================================
--- lvm2/trunk/lib/format_pool/disk_rep.c (original)
+++ lvm2/trunk/lib/format_pool/disk_rep.c Sat Apr 7 16:07:03 2007
@@ -36,7 +36,7 @@
struct dm_pool *mem, struct pool_list *pl,
const char *vg_name)
{
- char buf[512];
+ char buf[512] __attribute((aligned(8)));
/* FIXME: Need to check the cache here first */
if (!dev_read(dev, UINT64_C(0), 512, buf)) {
@@ -59,7 +59,7 @@
list_iterate_items(pl, head) {
if (id_equal(&data->pv_uuid, &pl->pv_uuid)) {
- char uuid[ID_LEN + 7];
+ char uuid[ID_LEN + 7] __attribute((aligned(8)));
id_write_format(&pl->pv_uuid, uuid, ID_LEN + 7);
@@ -84,7 +84,7 @@
struct lvmcache_info *info;
struct id pvid;
struct id vgid;
- char uuid[ID_LEN + 7];
+ char uuid[ID_LEN + 7] __attribute((aligned(8)));
struct pool_disk *pd = &pl->pd;
pool_label_in(pd, buf);
@@ -128,7 +128,7 @@
* 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)
+void pool_label_out(struct pool_disk *pl, void *buf)
{
struct pool_disk *bufpl = (struct pool_disk *) buf;
@@ -163,7 +163,7 @@
* correctly. Always use this function before using labels that
* were read from disk.
*/
-void pool_label_in(struct pool_disk *pl, char *buf)
+void pool_label_in(struct pool_disk *pl, void *buf)
{
struct pool_disk *bufpl = (struct pool_disk *) buf;
Modified: lvm2/trunk/lib/format_pool/disk_rep.h
==============================================================================
--- lvm2/trunk/lib/format_pool/disk_rep.h (original)
+++ lvm2/trunk/lib/format_pool/disk_rep.h Sat Apr 7 16:07:03 2007
@@ -134,8 +134,8 @@
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 pool_label_out(struct pool_disk *pl, void *buf);
+void pool_label_in(struct pool_disk *pl, void *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 dm_pool *mem, struct list *pls);
int import_pool_lvs(struct volume_group *vg, struct dm_pool *mem,
Modified: lvm2/trunk/lib/format_pool/pool_label.c
==============================================================================
--- lvm2/trunk/lib/format_pool/pool_label.c (original)
+++ lvm2/trunk/lib/format_pool/pool_label.c Sat Apr 7 16:07:03 2007
@@ -29,7 +29,7 @@
op);
}
-static int _pool_can_handle(struct labeller *l, char *buf, uint64_t sector)
+static int _pool_can_handle(struct labeller *l, void *buf, uint64_t sector)
{
struct pool_disk pd;
@@ -50,13 +50,13 @@
return 0;
}
-static int _pool_write(struct label *label, char *buf)
+static int _pool_write(struct label *label, void *buf)
{
_pool_not_supported("write");
return 0;
}
-static int _pool_read(struct labeller *l, struct device *dev, char *buf,
+static int _pool_read(struct labeller *l, struct device *dev, void *buf,
struct label **label)
{
struct pool_list pl;
Modified: lvm2/trunk/lib/format_text/archive.c
==============================================================================
--- lvm2/trunk/lib/format_text/archive.c (original)
+++ lvm2/trunk/lib/format_text/archive.c Sat Apr 7 16:07:03 2007
@@ -249,17 +249,23 @@
if (!(fp = fdopen(fd, "w"))) {
log_err("Couldn't create FILE object for archive.");
- close(fd);
+ if (close(fd))
+ log_sys_error("close", temp_file);
return 0;
}
if (!text_vg_export_file(vg, desc, fp)) {
stack;
- fclose(fp);
+ if (fclose(fp))
+ log_sys_error("fclose", temp_file);
return 0;
}
- fclose(fp);
+ if (fclose(fp)) {
+ log_sys_error("fclose", temp_file);
+ /* Leave file behind as evidence of failure */
+ return 0;
+ }
/*
* Now we want to rename this file to <vg>_index.vg.
Modified: lvm2/trunk/lib/format_text/export.c
==============================================================================
--- lvm2/trunk/lib/format_text/export.c (original)
+++ lvm2/trunk/lib/format_text/export.c Sat Apr 7 16:07:03 2007
@@ -221,6 +221,8 @@
"Megabytes",
"Gigabytes",
"Terabytes",
+ "Petabytes",
+ "Exabytes",
NULL
};
Modified: lvm2/trunk/lib/format_text/format-text.c
==============================================================================
--- lvm2/trunk/lib/format_text/format-text.c (original)
+++ lvm2/trunk/lib/format_text/format-text.c Sat Apr 7 16:07:03 2007
@@ -132,37 +132,40 @@
if (!dev_read(dev_area->dev, dev_area->start, MDA_HEADER_SIZE, mdah)) {
stack;
- dm_pool_free(fmt->cmd->mem, mdah);
- return NULL;
+ goto error;
}
if (mdah->checksum_xl != xlate32(calc_crc(INITIAL_CRC, mdah->magic,
MDA_HEADER_SIZE -
sizeof(mdah->checksum_xl)))) {
log_error("Incorrect metadata area header checksum");
- return NULL;
+ goto error;
}
_xlate_mdah(mdah);
if (strncmp((char *)mdah->magic, FMTT_MAGIC, sizeof(mdah->magic))) {
log_error("Wrong magic number in metadata area header");
- return NULL;
+ goto error;
}
if (mdah->version != FMTT_VERSION) {
log_error("Incompatible metadata area header version: %d",
mdah->version);
- return NULL;
+ goto error;
}
if (mdah->start != dev_area->start) {
log_error("Incorrect start sector in metadata area header: %"
PRIu64, mdah->start);
- return NULL;
+ goto error;
}
return mdah;
+
+error:
+ dm_pool_free(fmt->cmd->mem, mdah);
+ return NULL;
}
static int _raw_write_mda_header(const struct format_type *fmt,
@@ -193,7 +196,7 @@
int *precommitted)
{
size_t len;
- char vgnamebuf[NAME_LEN + 2];
+ char vgnamebuf[NAME_LEN + 2] __attribute((aligned(8)));
struct raw_locn *rlocn, *rlocn_precommitted;
struct lvmcache_info *info;
@@ -707,7 +710,8 @@
if (!(fp = fdopen(fd, "w"))) {
log_sys_error("fdopen", temp_file);
- close(fd);
+ if (close(fd))
+ log_sys_error("fclose", temp_file);
return 0;
}
@@ -715,13 +719,15 @@
if (!text_vg_export_file(vg, tc->desc, fp)) {
log_error("Failed to write metadata to %s.", temp_file);
- fclose(fp);
+ if (fclose(fp))
+ log_sys_error("fclose", temp_file);
return 0;
}
if (fsync(fd) && (errno != EROFS) && (errno != EINVAL)) {
log_sys_error("fsync", tc->path_edit);
- fclose(fp);
+ if (fclose(fp))
+ log_sys_error("fclose", tc->path_edit);
return 0;
}
@@ -885,8 +891,8 @@
uint32_t wrap = 0;
const char *vgname = NULL;
unsigned int len = 0;
- char buf[NAME_LEN + 1];
- char uuid[64];
+ char buf[NAME_LEN + 1] __attribute((aligned(8)));
+ char uuid[64] __attribute((aligned(8)));
if (!dev_open(dev_area->dev)) {
stack;
@@ -1131,7 +1137,7 @@
struct lvmcache_info *info;
struct mda_context *mdac;
struct metadata_area *mda;
- char buf[MDA_HEADER_SIZE];
+ char buf[MDA_HEADER_SIZE] __attribute((aligned(8)));
struct mda_header *mdah = (struct mda_header *) buf;
uint64_t adjustment;
@@ -1408,6 +1414,7 @@
uint64_t pe_end = 0;
unsigned mda_count = 0;
uint64_t mda_size2 = 0;
+ uint64_t pe_count;
/* FIXME Cope with pvchange */
/* FIXME Merge code with _text_create_text_instance */
@@ -1473,8 +1480,17 @@
pv->pe_start + mda_size2;
/* Recalculate number of extents that will fit */
- if (!pv->pe_count)
- pv->pe_count = (pv->size - pv->pe_start - mda_size2) / vg->extent_size;
+ if (!pv->pe_count) {
+ pe_count = (pv->size - pv->pe_start - mda_size2) /
+ vg->extent_size;
+ if (pe_count > UINT32_MAX) {
+ log_error("PV %s too large for extent size %s.",
+ dev_name(pv->dev),
+ display_size(vg->cmd, (uint64_t) vg->extent_size));
+ return 0;
+ }
+ pv->pe_count = (uint32_t) pe_count;
+ }
/* Unlike LVM1, we don't store this outside a VG */
/* FIXME Default from config file? vgextend cmdline flag? */
@@ -1732,7 +1748,7 @@
}
if (!(dev_area.dev = device_from_pvid(cmd, &id))) {
- char buffer[64];
+ char buffer[64] __attribute((aligned(8)));
if (!id_write_format(&id, buffer, sizeof(buffer)))
log_err("Couldn't find device.");
Modified: lvm2/trunk/lib/format_text/import.c
==============================================================================
--- lvm2/trunk/lib/format_text/import.c (original)
+++ lvm2/trunk/lib/format_text/import.c Sat Apr 7 16:07:03 2007
@@ -43,7 +43,7 @@
_text_import_initialised = 1;
}
- if (!(cft = create_config_tree(NULL)))
+ if (!(cft = create_config_tree(NULL, 0)))
return_NULL;
if ((!dev && !read_config_file(cft)) ||
@@ -94,7 +94,7 @@
*desc = NULL;
*when = 0;
- if (!(cft = create_config_tree(file)))
+ if (!(cft = create_config_tree(file, 0)))
return_NULL;
if ((!dev && !read_config_file(cft)) ||
Modified: lvm2/trunk/lib/format_text/import_vsn1.c
==============================================================================
--- lvm2/trunk/lib/format_text/import_vsn1.c (original)
+++ lvm2/trunk/lib/format_text/import_vsn1.c Sat Apr 7 16:07:03 2007
@@ -116,6 +116,7 @@
struct physical_volume *pv;
struct pv_list *pvl;
struct config_node *cn;
+ uint64_t size;
if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl))) ||
!(pvl->pv = dm_pool_zalloc(mem, sizeof(*pvl->pv)))) {
@@ -148,7 +149,7 @@
* Convert the uuid into a device.
*/
if (!(pv->dev = device_from_pvid(fid->fmt->cmd, &pv->id))) {
- char buffer[64];
+ char buffer[64] __attribute((aligned(8)));
if (!id_write_format(&pv->id, buffer, sizeof(buffer)))
log_error("Couldn't find device.");
@@ -213,6 +214,25 @@
pv->pe_alloc_count = 0;
pv->fmt = fid->fmt;
+ /* Fix up pv size if missing */
+ if (!pv->size && pv->dev) {
+ if (!dev_get_size(pv->dev, &pv->size)) {
+ log_error("%s: Couldn't get size.", dev_name(pv->dev));
+ return 0;
+ }
+ log_verbose("Fixing up missing format1 size (%s) "
+ "for PV %s", display_size(fid->fmt->cmd, pv->size),
+ dev_name(pv->dev));
+ if (vg) {
+ size = pv->pe_count * (uint64_t) vg->extent_size +
+ pv->pe_start;
+ if (size > pv->size)
+ log_error("WARNING: Physical Volume %s is too "
+ "large for underlying device",
+ dev_name(pv->dev));
+ }
+ }
+
if (!alloc_pv_segment_whole_pv(mem, pv)) {
stack;
return 0;
Modified: lvm2/trunk/lib/format_text/text_label.c
==============================================================================
--- lvm2/trunk/lib/format_text/text_label.c (original)
+++ lvm2/trunk/lib/format_text/text_label.c Sat Apr 7 16:07:03 2007
@@ -24,7 +24,7 @@
#include <fcntl.h>
static int _text_can_handle(struct labeller *l __attribute((unused)),
- char *buf,
+ void *buf,
uint64_t sector __attribute((unused)))
{
struct label_header *lh = (struct label_header *) buf;
@@ -35,7 +35,7 @@
return 0;
}
-static int _text_write(struct label *label, char *buf)
+static int _text_write(struct label *label, void *buf)
{
struct label_header *lh = (struct label_header *) buf;
struct pv_header *pvhdr;
@@ -189,7 +189,7 @@
return 1;
}
-static int _text_read(struct labeller *l, struct device *dev, char *buf,
+static int _text_read(struct labeller *l, struct device *dev, void *buf,
struct label **label)
{
struct label_header *lh = (struct label_header *) buf;
Modified: lvm2/trunk/lib/label/label.c
==============================================================================
--- lvm2/trunk/lib/label/label.c (original)
+++ lvm2/trunk/lib/label/label.c Sat Apr 7 16:07:03 2007
@@ -115,7 +115,7 @@
struct lvmcache_info *info;
uint64_t sector;
int found = 0;
- char readbuf[LABEL_SCAN_SIZE];
+ char readbuf[LABEL_SCAN_SIZE] __attribute((aligned(8)));
if (!dev_read(dev, UINT64_C(0), LABEL_SCAN_SIZE, readbuf)) {
log_debug("%s: Failed to read label area", dev_name(dev));
@@ -186,8 +186,8 @@
/* FIXME Also wipe associated metadata area headers? */
int label_remove(struct device *dev)
{
- char buf[LABEL_SIZE];
- char readbuf[LABEL_SCAN_SIZE];
+ char buf[LABEL_SIZE] __attribute((aligned(8)));
+ char readbuf[LABEL_SCAN_SIZE] __attribute((aligned(8)));
int r = 1;
uint64_t sector;
int wipe;
@@ -258,7 +258,7 @@
/* FIXME Avoid repeated re-reading if cache lock held */
int label_read(struct device *dev, struct label **result)
{
- char buf[LABEL_SIZE];
+ char buf[LABEL_SIZE] __attribute((aligned(8)));
struct labeller *l;
uint64_t sector;
struct lvmcache_info *info;
@@ -290,7 +290,7 @@
/* Caller may need to use label_get_handler to create label struct! */
int label_write(struct device *dev, struct label *label)
{
- char buf[LABEL_SIZE];
+ char buf[LABEL_SIZE] __attribute((aligned(8)));
struct label_header *lh = (struct label_header *) buf;
int r = 1;
@@ -341,19 +341,17 @@
int label_verify(struct device *dev)
{
struct labeller *l;
- char buf[LABEL_SIZE];
+ char buf[LABEL_SIZE] __attribute((aligned(8)));
uint64_t sector;
struct lvmcache_info *info;
int r = 0;
if (!dev_open(dev)) {
- stack;
-
if ((info = info_from_pvid(dev->pvid)))
lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN,
0, NULL);
- goto out;
+ return_0;
}
if (!(l = _find_labeller(dev, buf, §or)))
Modified: lvm2/trunk/lib/label/label.h
==============================================================================
--- lvm2/trunk/lib/label/label.h (original)
+++ lvm2/trunk/lib/label/label.h Sat Apr 7 16:07:03 2007
@@ -49,23 +49,23 @@
/*
* Is the device labelled with this format ?
*/
- int (*can_handle) (struct labeller * l, char *buf, uint64_t sector);
+ int (*can_handle) (struct labeller * l, void *buf, uint64_t sector);
/*
* Write a label to a volume.
*/
- int (*write) (struct label * label, char *buf);
+ int (*write) (struct label * label, void *buf);
/*
* Read a label from a volume.
*/
int (*read) (struct labeller * l, struct device * dev,
- char *buf, struct label ** label);
+ void *buf, struct label ** label);
/*
* Additional consistency checks for the paranoid.
*/
- int (*verify) (struct labeller * l, char *buf, uint64_t sector);
+ int (*verify) (struct labeller * l, void *buf, uint64_t sector);
/*
* Populate label_type etc.
Modified: lvm2/trunk/lib/locking/cluster_locking.c
==============================================================================
--- lvm2/trunk/lib/locking/cluster_locking.c (original)
+++ lvm2/trunk/lib/locking/cluster_locking.c Sat Apr 7 16:07:03 2007
@@ -94,7 +94,7 @@
/* Send a request and return the status */
static int _send_request(char *inbuf, int inlen, char **retbuf)
{
- char outbuf[PIPE_BUF];
+ char outbuf[PIPE_BUF] __attribute((aligned(8)));
struct clvm_header *outheader = (struct clvm_header *) outbuf;
int len;
int off;
@@ -195,8 +195,7 @@
static int _cluster_request(char cmd, const char *node, void *data, int len,
lvm_response_t ** response, int *num)
{
- char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1];
- int *outptr;
+ char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1] __attribute((aligned(8)));
char *inptr;
char *retbuf = NULL;
int status;
@@ -236,17 +235,13 @@
* With an extra pair of INTs on the front to sanity
* check the pointer when we are given it back to free
*/
- outptr = dm_malloc(sizeof(lvm_response_t) * num_responses +
- sizeof(int) * 2);
- if (!outptr) {
+ *response = dm_malloc(sizeof(lvm_response_t) * num_responses);
+ if (!*response) {
errno = ENOMEM;
status = 0;
goto out;
}
- *response = (lvm_response_t *) (outptr + 2);
- outptr[0] = LVM_SIGNATURE;
- outptr[1] = num_responses;
rarray = *response;
/* Unpack the response into an lvm_response_t array */
@@ -265,7 +260,7 @@
int j;
for (j = 0; j < i; j++)
dm_free(rarray[i].response);
- free(outptr);
+ free(*response);
errno = ENOMEM;
status = -1;
goto out;
@@ -287,25 +282,15 @@
}
/* Free reply array */
-static int _cluster_free_request(lvm_response_t * response)
+static int _cluster_free_request(lvm_response_t * response, int num)
{
- int *ptr = (int *) response - 2;
int i;
- int num;
-
- /* Check it's ours to free */
- if (response == NULL || *ptr != LVM_SIGNATURE) {
- errno = EINVAL;
- return 0;
- }
-
- num = ptr[1];
for (i = 0; i < num; i++) {
dm_free(response[i].response);
}
- dm_free(ptr);
+ dm_free(response);
return 1;
}
@@ -336,8 +321,8 @@
if (mirror_in_sync())
args[1] |= LCK_MIRROR_NOSYNC_MODE;
- if (dmeventd_register_mode())
- args[1] |= LCK_DMEVENTD_REGISTER_MODE;
+ if (dmeventd_monitor_mode())
+ args[1] |= LCK_DMEVENTD_MONITOR_MODE;
/*
* VG locks are just that: locks, and have no side effects
@@ -374,7 +359,7 @@
}
saved_errno = errno;
- _cluster_free_request(response);
+ _cluster_free_request(response, num_responses);
errno = saved_errno;
return status;
Modified: lvm2/trunk/lib/locking/file_locking.c
==============================================================================
--- lvm2/trunk/lib/locking/file_locking.c (original)
+++ lvm2/trunk/lib/locking/file_locking.c Sat Apr 7 16:07:03 2007
@@ -163,8 +163,8 @@
log_very_verbose("Locking %s %c%c", ll->res, state,
flags & LCK_NONBLOCK ? ' ' : 'B');
do {
- if (ll->lf > -1)
- close(ll->lf);
+ if ((ll->lf > -1) && close(ll->lf))
+ log_sys_error("close", file);
if ((ll->lf = open(file, O_CREAT | O_APPEND | O_RDWR, 0777))
< 0) {
Modified: lvm2/trunk/lib/locking/locking.c
==============================================================================
--- lvm2/trunk/lib/locking/locking.c (original)
+++ lvm2/trunk/lib/locking/locking.c Sat Apr 7 16:07:03 2007
@@ -249,7 +249,7 @@
int lock_vol(struct cmd_context *cmd, const char *vol, int flags)
{
- char resource[258];
+ char resource[258] __attribute((aligned(8)));
switch (flags & LCK_SCOPE_MASK) {
case LCK_VG:
Modified: lvm2/trunk/lib/locking/locking.h
==============================================================================
--- lvm2/trunk/lib/locking/locking.h (original)
+++ lvm2/trunk/lib/locking/locking.h Sat Apr 7 16:07:03 2007
@@ -50,7 +50,7 @@
#define LCK_NULL 0x00000000 /* LCK$_NLMODE */
#define LCK_READ 0x00000001 /* LCK$_CRMODE */
/* LCK$_CWMODE */
- /* LCK$_PRMODE */
+#define LCK_PREAD 0x00000003 /* LCK$_PRMODE */
#define LCK_WRITE 0x00000004 /* LCK$_PWMODE */
#define LCK_EXCL 0x00000005 /* LCK$_EXMODE */
#define LCK_UNLOCK 0x00000006 /* This is ours */
@@ -75,7 +75,7 @@
*/
#define LCK_PARTIAL_MODE 0x00000001 /* Running in partial mode */
#define LCK_MIRROR_NOSYNC_MODE 0x00000002 /* Mirrors don't require sync */
-#define LCK_DMEVENTD_REGISTER_MODE 0x00000004 /* Register with dmeventd */
+#define LCK_DMEVENTD_MONITOR_MODE 0x00000004 /* Register with dmeventd */
/*
Modified: lvm2/trunk/lib/locking/no_locking.c
==============================================================================
--- lvm2/trunk/lib/locking/no_locking.c (original)
+++ lvm2/trunk/lib/locking/no_locking.c Sat Apr 7 16:07:03 2007
@@ -81,7 +81,7 @@
locking->lock_resource = _no_lock_resource;
locking->reset_locking = _no_reset_locking;
locking->fin_locking = _no_fin_locking;
- locking->flags = 0;
+ locking->flags = LCK_CLUSTERED;
return 1;
}
Modified: lvm2/trunk/lib/log/log.c
==============================================================================
--- lvm2/trunk/lib/log/log.c (original)
+++ lvm2/trunk/lib/log/log.c Sat Apr 7 16:07:03 2007
@@ -48,7 +48,8 @@
static char _msg_prefix[30] = " ";
static int _already_logging = 0;
static int _mirror_in_sync = 0;
-static int _dmeventd_register = DEFAULT_DMEVENTD_MONITOR;
+static int _dmeventd_monitor = DEFAULT_DMEVENTD_MONITOR;
+static int _ignore_suspended_devices = 0;
static lvm2_log_fn_t _lvm2_log_fn = NULL;
@@ -120,7 +121,8 @@
}
if (_log_to_file) {
- fclose(_log_file);
+ if (fclose(_log_file))
+ fprintf(stderr, "fclose() on log file failed: %s", strerror(errno));
_log_to_file = 0;
}
}
@@ -189,9 +191,14 @@
_mirror_in_sync = in_sync;
}
-void init_dmeventd_register(int reg)
+void init_dmeventd_monitor(int reg)
{
- _dmeventd_register = reg;
+ _dmeventd_monitor = reg;
+}
+
+void init_ignore_suspended_devices(int ignore)
+{
+ _ignore_suspended_devices = ignore;
}
void init_cmd_name(int status)
@@ -268,9 +275,14 @@
return _mirror_in_sync;
}
-int dmeventd_register_mode(void)
+int dmeventd_monitor_mode(void)
+{
+ return _dmeventd_monitor;
+}
+
+int ignore_suspended_devices(void)
{
- return _dmeventd_register;
+ return _ignore_suspended_devices;
}
void init_debug(int level)
Modified: lvm2/trunk/lib/log/log.h
==============================================================================
--- lvm2/trunk/lib/log/log.h (original)
+++ lvm2/trunk/lib/log/log.h Sat Apr 7 16:07:03 2007
@@ -75,7 +75,8 @@
void init_lockingfailed(int level);
void init_security_level(int level);
void init_mirror_in_sync(int in_sync);
-void init_dmeventd_register(int reg);
+void init_dmeventd_monitor(int reg);
+void init_ignore_suspended_devices(int ignore);
void set_cmd_name(const char *cmd_name);
@@ -90,7 +91,10 @@
int lockingfailed(void);
int security_level(void);
int mirror_in_sync(void);
-int dmeventd_register_mode(void);
+int ignore_suspended_devices(void);
+
+#define DMEVENTD_MONITOR_IGNORE -1
+int dmeventd_monitor_mode(void);
/* Suppress messages to stdout/stderr (1) or everywhere (2) */
/* Returns previous setting */
Modified: lvm2/trunk/lib/metadata/lv_manip.c
==============================================================================
--- lvm2/trunk/lib/metadata/lv_manip.c (original)
+++ lvm2/trunk/lib/metadata/lv_manip.c Sat Apr 7 16:07:03 2007
@@ -415,6 +415,15 @@
struct list alloced_areas[0]; /* Lists of areas in each stripe */
};
+static uint32_t calc_area_multiple(const struct segment_type *segtype,
+ const uint32_t area_count)
+{
+ if (!segtype_is_striped(segtype) || !area_count)
+ return 1;
+
+ return area_count;
+}
+
/*
* Preparation for a specific allocation attempt
*/
@@ -476,7 +485,7 @@
ah->area_count = area_count;
ah->log_count = log_count;
ah->alloc = alloc;
- ah->area_multiple = segtype_is_striped(segtype) ? ah->area_count : 1;
+ ah->area_multiple = calc_area_multiple(segtype, area_count);
for (s = 0; s < ah->area_count; s++)
list_init(&ah->alloced_areas[s]);
@@ -553,7 +562,7 @@
if (mirrored_pv)
extra_areas = 1;
- area_multiple = segtype_is_striped(segtype) ? area_count : 1;
+ area_multiple = calc_area_multiple(segtype, area_count);
/* log_lv gets set up elsehere */
if (!(seg = alloc_lv_segment(lv->vg->cmd->mem, segtype, lv,
@@ -628,17 +637,17 @@
struct pv_area **areas,
uint32_t *ix, struct pv_area *log_area)
{
- uint32_t area_len, smallest, remaining;
+ uint32_t area_len, remaining;
uint32_t s;
struct alloced_area *aa;
remaining = needed - *ix;
area_len = remaining / ah->area_multiple;
- smallest = areas[ah->area_count - 1]->count;
-
- if (area_len > smallest)
- area_len = smallest;
+ /* Reduce area_len to the smallest of the areas */
+ for (s = 0; s < ah->area_count; s++)
+ if (area_len > areas[s]->count)
+ area_len = areas[s]->count;
if (!(aa = dm_pool_alloc(ah->mem, sizeof(*aa) *
(ah->area_count + (log_area ? 1 : 0))))) {
@@ -707,7 +716,7 @@
if (max_seg_len && *max_seg_len > remaining_seg_len)
*max_seg_len = remaining_seg_len;
- area_multiple = segtype_is_striped(seg->segtype) ? seg->area_count : 1;
+ area_multiple = calc_area_multiple(seg->segtype, seg->area_count);
area_len = remaining_seg_len / area_multiple ? : 1;
for (s = first_area;
@@ -890,8 +899,17 @@
uint32_t next_le;
struct seg_pvs *spvs;
struct list *parallel_pvs;
+ uint32_t free_pes;
+
+ /* Is there enough total space? */
+ free_pes = pv_maps_size(pvms);
+ if (needed - *allocated > free_pes) {
+ log_error("Insufficient free space: %" PRIu32 " extents needed,"
+ " but only %" PRIu32 " available",
+ needed - *allocated, free_pes);
+ return 0;
+ }
- /* FIXME Do calculations on free extent counts before selecting space */
/* FIXME Select log PV appropriately if there isn't one yet */
/* Are there any preceding segments we must follow on from? */
@@ -1057,6 +1075,7 @@
int r = 0;
struct list *pvms;
uint32_t areas_size;
+ alloc_policy_t alloc;
if (allocated >= new_extents && !ah->log_count) {
log_error("_allocate called with no work to do!");
@@ -1102,50 +1121,18 @@
return 0;
}
- old_allocated = allocated;
- if (!_find_parallel_space(ah, ALLOC_CONTIGUOUS, pvms, areas,
- areas_size, can_split,
- prev_lvseg, &allocated, new_extents)) {
- stack;
- goto out;
- }
-
- if ((allocated == new_extents) || (ah->alloc == ALLOC_CONTIGUOUS) ||
- (!can_split && (allocated != old_allocated)))
- goto finished;
-
- old_allocated = allocated;
- if (!_find_parallel_space(ah, ALLOC_CLING, pvms, areas,
- areas_size, can_split,
- prev_lvseg, &allocated, new_extents)) {
- stack;
- goto out;
- }
-
- if ((allocated == new_extents) || (ah->alloc == ALLOC_CLING) ||
- (!can_split && (allocated != old_allocated)))
- goto finished;
-
- old_allocated = allocated;
- if (!_find_parallel_space(ah, ALLOC_NORMAL, pvms, areas,
- areas_size, can_split,
- prev_lvseg, &allocated, new_extents)) {
- stack;
- goto out;
- }
-
- if ((allocated == new_extents) || (ah->alloc == ALLOC_NORMAL) ||
- (!can_split && (allocated != old_allocated)))
- goto finished;
-
- if (!_find_parallel_space(ah, ALLOC_ANYWHERE, pvms, areas,
- areas_size, can_split,
- prev_lvseg, &allocated, new_extents)) {
- stack;
- goto out;
+ /* Attempt each defined allocation policy in turn */
+ for (alloc = ALLOC_CONTIGUOUS; alloc < ALLOC_INHERIT; alloc++) {
+ old_allocated = allocated;
+ if (!_find_parallel_space(ah, alloc, pvms, areas,
+ areas_size, can_split,
+ prev_lvseg, &allocated, new_extents))
+ goto_out;
+ if ((allocated == new_extents) || (ah->alloc == alloc) ||
+ (!can_split && (allocated != old_allocated)))
+ break;
}
- finished:
if (allocated != new_extents) {
log_error("Insufficient suitable %sallocatable extents "
"for logical volume %s: %u more required",
@@ -1156,6 +1143,13 @@
goto out;
}
+ if (ah->log_count && !ah->log_area.len) {
+ log_error("Insufficient extents for log allocation "
+ "for logical volume %s.",
+ lv ? lv->name : "");
+ goto out;
+ }
+
r = 1;
out:
@@ -1499,7 +1493,7 @@
struct cmd_context *cmd = vg->cmd;
struct lv_list *ll = NULL;
struct logical_volume *lv;
- char dname[32];
+ char dname[NAME_LEN];
if (vg->max_lv && (vg->max_lv == vg->lv_count)) {
log_error("Maximum number of logical volumes (%u) reached "
Modified: lvm2/trunk/lib/metadata/metadata.c
==============================================================================
--- lvm2/trunk/lib/metadata/metadata.c (original)
+++ lvm2/trunk/lib/metadata/metadata.c Sat Apr 7 16:07:03 2007
@@ -23,6 +23,7 @@
#include "str_list.h"
#include "pv_alloc.h"
#include "activate.h"
+#include "display.h"
#include <sys/param.h>
@@ -122,6 +123,15 @@
pvl->pv = pv;
list_add(&vg->pvs, &pvl->list);
+ if ((uint64_t) vg->extent_count + pv->pe_count > UINT32_MAX) {
+ log_error("Unable to add %s to %s: new extent count (%"
+ PRIu64 ") exceeds limit (%" PRIu32 ").",
+ pv_name, vg->name,
+ (uint64_t) vg->extent_count + pv->pe_count,
+ UINT32_MAX);
+ return 0;
+ }
+
vg->pv_count++;
vg->extent_count += pv->pe_count;
vg->free_count += pv->pe_count;
@@ -728,7 +738,7 @@
{
struct pv_list *pvl, *pvl2;
struct lv_list *lvl, *lvl2;
- char uuid[64];
+ char uuid[64] __attribute((aligned(8)));
int r = 1;
/* FIXME Also check there's no data/metadata overlap */
@@ -953,6 +963,30 @@
return vg;
}
+static int _update_pv_list(struct list *all_pvs, struct volume_group *vg)
+{
+ struct pv_list *pvl, *pvl2;
+
+ list_iterate_items(pvl, &vg->pvs) {
+ list_iterate_items(pvl2, all_pvs) {
+ if (pvl->pv->dev == pvl2->pv->dev)
+ goto next_pv;
+ }
+ /* PV is not on list so add it. Note that we don't copy it. */
+ if (!(pvl2 = dm_pool_zalloc(vg->cmd->mem, sizeof(*pvl2)))) {
+ log_error("pv_list allocation for '%s' failed",
+ dev_name(pvl->pv->dev));
+ return 0;
+ }
+ pvl2->pv = pvl->pv;
+ list_add(all_pvs, &pvl2->list);
+ next_pv:
+ ;
+ }
+
+ return 1;
+}
+
/* Caller sets consistent to 1 if it's safe for vg_read to correct
* inconsistent metadata on disk (i.e. the VG write lock is held).
* This guarantees only consistent metadata is returned unless PARTIAL_VG.
@@ -972,9 +1006,12 @@
struct volume_group *vg, *correct_vg = NULL;
struct metadata_area *mda;
int inconsistent = 0;
+ int inconsistent_vgid = 0;
int use_precommitted = precommitted;
struct list *pvids;
- struct pv_list *pvl;
+ struct pv_list *pvl, *pvl2;
+ struct list all_pvs;
+ char uuid[64] __attribute((aligned(8)));
if (!*vgname) {
if (use_precommitted) {
@@ -1059,6 +1096,8 @@
}
}
+ list_init(&all_pvs);
+
/* Failed to find VG where we expected it - full scan and retry */
if (!correct_vg) {
inconsistent = 0;
@@ -1094,13 +1133,25 @@
}
if (!correct_vg) {
correct_vg = vg;
+ if (!_update_pv_list(&all_pvs, correct_vg))
+ return_NULL;
continue;
}
+
+ if (strncmp((char *)vg->id.uuid,
+ (char *)correct_vg->id.uuid, ID_LEN)) {
+ inconsistent = 1;
+ inconsistent_vgid = 1;
+ }
+
/* FIXME Also ensure contents same - checksums same? */
if (correct_vg->seqno != vg->seqno) {
inconsistent = 1;
- if (vg->seqno > correct_vg->seqno)
+ if (vg->seqno > correct_vg->seqno) {
+ if (!_update_pv_list(&all_pvs, vg))
+ return_NULL;
correct_vg = vg;
+ }
}
}
@@ -1133,17 +1184,42 @@
return correct_vg;
}
- log_print("Inconsistent metadata copies found - updating "
- "to use version %u", correct_vg->seqno);
+ /* Don't touch if vgids didn't match */
+ if (inconsistent_vgid) {
+ log_error("Inconsistent metadata UUIDs found for "
+ "volume group %s", vgname);
+ *consistent = 0;
+ return correct_vg;
+ }
+
+ log_print("Inconsistent metadata found for VG %s - updating "
+ "to use version %u", vgname, correct_vg->seqno);
+
if (!vg_write(correct_vg)) {
log_error("Automatic metadata correction failed");
return NULL;
}
+
if (!vg_commit(correct_vg)) {
log_error("Automatic metadata correction commit "
"failed");
return NULL;
}
+
+ list_iterate_items(pvl, &all_pvs) {
+ list_iterate_items(pvl2, &correct_vg->pvs) {
+ if (pvl->pv->dev == pvl2->pv->dev)
+ goto next_pv;
+ }
+ if (!id_write_format(&pvl->pv->id, uuid, sizeof(uuid)))
+ return_NULL;
+ log_error("Removing PV %s (%s) that no longer belongs to VG %s",
+ dev_name(pvl->pv->dev), uuid, correct_vg->name);
+ if (!pv_write_orphan(cmd, pvl->pv))
+ return_NULL;
+ next_pv:
+ ;
+ }
}
if ((correct_vg->status & PVMOVE) && !pvmove_mode()) {
@@ -1423,3 +1499,25 @@
return 1;
}
+
+int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv)
+{
+ const char *old_vg_name = pv->vg_name;
+
+ pv->vg_name = ORPHAN;
+ pv->status = ALLOCATABLE_PV;
+
+ if (!dev_get_size(pv->dev, &pv->size)) {
+ log_error("%s: Couldn't get size.", dev_name(pv->dev));
+ return 0;
+ }
+
+ if (!pv_write(cmd, pv, NULL, INT64_C(-1))) {
+ log_error("Failed to clear metadata from physical "
+ "volume \"%s\" after removal from \"%s\"",
+ dev_name(pv->dev), old_vg_name);
+ return 0;
+ }
+
+ return 1;
+}
Modified: lvm2/trunk/lib/metadata/metadata.h
==============================================================================
--- lvm2/trunk/lib/metadata/metadata.h (original)
+++ lvm2/trunk/lib/metadata/metadata.h Sat Apr 7 16:07:03 2007
@@ -78,17 +78,18 @@
#define FMT_RESIZE_PV 0x00000080U /* Supports pvresize? */
#define FMT_UNLIMITED_STRIPESIZE 0x00000100U /* Unlimited stripe size? */
+/* Ordered list - see lv_manip.c */
typedef enum {
- ALLOC_INVALID = 0,
- ALLOC_INHERIT,
+ ALLOC_INVALID,
ALLOC_CONTIGUOUS,
ALLOC_CLING,
ALLOC_NORMAL,
- ALLOC_ANYWHERE
+ ALLOC_ANYWHERE,
+ ALLOC_INHERIT
} alloc_policy_t;
typedef enum {
- AREA_UNASSIGNED = 0,
+ AREA_UNASSIGNED,
AREA_PV,
AREA_LV
} area_type_t;
@@ -285,7 +286,7 @@
int32_t major;
int32_t minor;
- uint64_t size;
+ uint64_t size; /* Sectors */
uint32_t le_count;
uint32_t origin_count;
@@ -422,6 +423,7 @@
int pv_write(struct cmd_context *cmd, struct physical_volume *pv,
struct list *mdas, int64_t label_sector);
+int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv);
/* pe_start and pe_end relate to any existing data so that new metadata
* areas can avoid overlap */
Modified: lvm2/trunk/lib/metadata/mirror.c
==============================================================================
--- lvm2/trunk/lib/metadata/mirror.c (original)
+++ lvm2/trunk/lib/metadata/mirror.c Sat Apr 7 16:07:03 2007
@@ -36,20 +36,20 @@
}
/*
- * Ensure region size is compatible with volume size.
+ * Reduce the region size if necessary to ensure
+ * the volume size is a multiple of the region size.
*/
uint32_t adjusted_mirror_region_size(uint32_t extent_size, uint32_t extents,
uint32_t region_size)
{
- uint32_t region_max;
+ uint64_t region_max;
- region_max = (1 << (ffs((int)extents) - 1)) * extent_size;
+ region_max = (1 << (ffs((int)extents) - 1)) * (uint64_t) extent_size;
- if (region_max < region_size) {
- region_size = region_max;
+ if (region_max < UINT32_MAX && region_size > region_max) {
+ region_size = (uint32_t) region_max;
log_print("Using reduced mirror region size of %" PRIu32
- " sectors", region_max);
- return region_max;
+ " sectors", region_size);
}
return region_size;
@@ -84,6 +84,7 @@
struct list *removable_pvs, int remove_log)
{
uint32_t m;
+ uint32_t extents;
uint32_t s, s1;
struct logical_volume *sub_lv;
struct logical_volume *log_lv = NULL;
@@ -95,6 +96,7 @@
struct pv_list *pvl;
uint32_t old_area_count = mirrored_seg->area_count;
uint32_t new_area_count = mirrored_seg->area_count;
+ struct segment_type *segtype;
log_very_verbose("Reducing mirror set from %" PRIu32 " to %"
PRIu32 " image(s)%s.",
@@ -156,9 +158,14 @@
/* If no more mirrors, remove mirror layer */
if (num_mirrors == 1) {
lv1 = seg_lv(mirrored_seg, 0);
+ extents = lv1->le_count;
_move_lv_segments(mirrored_seg->lv, lv1);
mirrored_seg->lv->status &= ~MIRRORED;
remove_log = 1;
+ /* Replace mirror with error segment */
+ segtype = get_segtype_from_string(mirrored_seg->lv->vg->cmd, "error");
+ if (!lv_add_virtual_segment(lv1, 0, extents, segtype))
+ return_0;
}
if (remove_log && mirrored_seg->log_lv) {
@@ -174,8 +181,6 @@
* then deactivate and remove them fully.
*/
- /* FIXME lv1 has no segments here so shouldn't be written to disk! */
-
if (!vg_write(mirrored_seg->lv->vg)) {
log_error("intermediate VG write failed.");
return 0;
@@ -562,7 +567,7 @@
}
if (activation() && segtype->ops->target_present &&
- !segtype->ops->target_present()) {
+ !segtype->ops->target_present(NULL)) {
log_error("%s: Required device-mapper target(s) not "
"detected in your kernel", segtype->name);
return 0;
Modified: lvm2/trunk/lib/metadata/pv_map.c
==============================================================================
--- lvm2/trunk/lib/metadata/pv_map.c (original)
+++ lvm2/trunk/lib/metadata/pv_map.c Sat Apr 7 16:07:03 2007
@@ -19,6 +19,8 @@
/*
* Areas are maintained in size order, largest first.
+ *
+ * FIXME Cope with overlap.
*/
static void _insert_area(struct list *head, struct pv_area *a)
{
@@ -30,6 +32,7 @@
}
list_add(&pva->list, &a->list);
+ a->map->pe_count += a->count;
}
static int _create_single_area(struct dm_pool *mem, struct pv_map *pvm,
@@ -126,22 +129,31 @@
static int _create_maps(struct dm_pool *mem, struct list *pvs, struct list *pvms)
{
- struct pv_map *pvm;
+ struct pv_map *pvm, *pvm2;
struct pv_list *pvl;
list_iterate_items(pvl, pvs) {
if (!(pvl->pv->status & ALLOCATABLE_PV))
continue;
- if (!(pvm = dm_pool_zalloc(mem, sizeof(*pvm)))) {
- stack;
- return 0;
- }
-
- pvm->pv = pvl->pv;
+ pvm = NULL;
- list_init(&pvm->areas);
- list_add(pvms, &pvm->list);
+ list_iterate_items(pvm2, pvms)
+ if (pvm2->pv->dev == pvl->pv->dev) {
+ pvm = pvm2;
+ break;
+ }
+
+ if (!pvm) {
+ if (!(pvm = dm_pool_zalloc(mem, sizeof(*pvm)))) {
+ stack;
+ return 0;
+ }
+
+ pvm->pv = pvl->pv;
+ list_init(&pvm->areas);
+ list_add(pvms, &pvm->list);
+ }
if (!_create_all_areas_for_pv(mem, pvm, pvl->pe_ranges)) {
stack;
@@ -180,6 +192,7 @@
void consume_pv_area(struct pv_area *pva, uint32_t to_go)
{
list_del(&pva->list);
+ pva->map->pe_count -= pva->count;
assert(to_go <= pva->count);
@@ -190,3 +203,14 @@
_insert_area(&pva->map->areas, pva);
}
}
+
+uint32_t pv_maps_size(struct list *pvms)
+{
+ struct pv_map *pvm;
+ uint32_t pe_count = 0;
+
+ list_iterate_items(pvm, pvms)
+ pe_count += pvm->pe_count;
+
+ return pe_count;
+}
Modified: lvm2/trunk/lib/metadata/pv_map.h
==============================================================================
--- lvm2/trunk/lib/metadata/pv_map.h (original)
+++ lvm2/trunk/lib/metadata/pv_map.h Sat Apr 7 16:07:03 2007
@@ -37,6 +37,7 @@
struct pv_map {
struct physical_volume *pv;
struct list areas; /* struct pv_areas */
+ uint32_t pe_count; /* Total number of PEs */
struct list list;
};
@@ -49,4 +50,6 @@
void consume_pv_area(struct pv_area *area, uint32_t to_go);
+uint32_t pv_maps_size(struct list *pvms);
+
#endif
Modified: lvm2/trunk/lib/metadata/segtype.h
==============================================================================
--- lvm2/trunk/lib/metadata/segtype.h (original)
+++ lvm2/trunk/lib/metadata/segtype.h Sat Apr 7 16:07:03 2007
@@ -32,6 +32,7 @@
#define SEG_FORMAT1_SUPPORT 0x00000010U
#define SEG_VIRTUAL 0x00000020U
#define SEG_CANNOT_BE_ZEROED 0x00000040U
+#define SEG_MONITORED 0x00000080U
#define seg_is_mirrored(seg) ((seg)->segtype->flags & SEG_AREAS_MIRRORED ? 1 : 0)
#define seg_is_striped(seg) ((seg)->segtype->flags & SEG_AREAS_STRIPED ? 1 : 0)
@@ -39,6 +40,7 @@
#define seg_is_virtual(seg) ((seg)->segtype->flags & SEG_VIRTUAL ? 1 : 0)
#define seg_can_split(seg) ((seg)->segtype->flags & SEG_CAN_SPLIT ? 1 : 0)
#define seg_cannot_be_zeroed(seg) ((seg)->segtype->flags & SEG_CANNOT_BE_ZEROED ? 1 : 0)
+#define seg_monitored(seg) ((seg)->segtype->flags & SEG_MONITORED ? 1 : 0)
#define segtype_is_striped(segtype) ((segtype)->flags & SEG_AREAS_STRIPED ? 1 : 0)
#define segtype_is_mirrored(segtype) ((segtype)->flags & SEG_AREAS_MIRRORED ? 1 : 0)
@@ -76,13 +78,14 @@
struct lv_segment *seg, char *params,
uint64_t *total_numerator,
uint64_t *total_denominator, float *percent);
- int (*target_present) (void);
+ int (*target_present) (const struct lv_segment *seg);
int (*modules_needed) (struct dm_pool *mem,
const struct lv_segment *seg,
struct list *modules);
void (*destroy) (const struct segment_type * segtype);
- int (*target_register_events) (struct lv_segment *seg, int events);
- int (*target_unregister_events) (struct lv_segment *seg, int events);
+ int (*target_monitored) (struct lv_segment *seg, int *pending);
+ int (*target_monitor_events) (struct lv_segment *seg, int events);
+ int (*target_unmonitor_events) (struct lv_segment *seg, int events);
};
struct segment_type *get_segtype_from_string(struct cmd_context *cmd,
Modified: lvm2/trunk/lib/mirror/mirrored.c
==============================================================================
--- lvm2/trunk/lib/mirror/mirrored.c (original)
+++ lvm2/trunk/lib/mirror/mirrored.c Sat Apr 7 16:07:03 2007
@@ -336,7 +336,7 @@
return add_areas_line(dm, seg, node, start_area, area_count);
}
-static int _mirrored_target_present(void)
+static int _mirrored_target_present(const struct lv_segment *seg __attribute((unused)))
{
static int _mirrored_checked = 0;
static int _mirrored_present = 0;
@@ -368,13 +368,12 @@
}
#ifdef DMEVENTD
-static int _setup_registration(struct dm_pool *mem, struct cmd_context *cmd,
- char **dso)
+static int _get_mirror_dso_path(struct cmd_context *cmd, char **dso)
{
char *path;
const char *libpath;
- if (!(path = dm_pool_alloc(mem, PATH_MAX))) {
+ if (!(path = dm_pool_alloc(cmd->mem, PATH_MAX))) {
log_error("Failed to allocate dmeventd library path.");
return 0;
}
@@ -389,62 +388,107 @@
return 1;
}
-/* FIXME This gets run while suspended and performs banned operations. */
-/* FIXME Merge these two functions */
-static int _target_register_events(struct lv_segment *seg,
- int events)
+static struct dm_event_handler *_create_dm_event_handler(const char *dmname,
+ const char *dso,
+ enum dm_event_mask mask)
+{
+ struct dm_event_handler *dmevh;
+
+ if (!(dmevh = dm_event_handler_create()))
+ return_0;
+
+ if (dm_event_handler_set_dso(dmevh, dso))
+ goto fail;
+
+ if (dm_event_handler_set_dev_name(dmevh, dmname))
+ goto fail;
+
+ dm_event_handler_set_event_mask(dmevh, mask);
+ return dmevh;
+
+fail:
+ dm_event_handler_destroy(dmevh);
+ return NULL;
+}
+
+static int _target_monitored(struct lv_segment *seg, int *pending)
{
char *dso, *name;
struct logical_volume *lv;
struct volume_group *vg;
+ enum dm_event_mask evmask = 0;
+ struct dm_event_handler *dmevh;
lv = seg->lv;
vg = lv->vg;
- if (!_setup_registration(vg->cmd->mem, vg->cmd, &dso)) {
- stack;
- return 0;
- }
+ *pending = 0;
+ if (!_get_mirror_dso_path(vg->cmd, &dso))
+ return_0;
if (!(name = build_dm_name(vg->cmd->mem, vg->name, lv->name, NULL)))
return_0;
- /* FIXME Save a returned handle here so we can unregister it later */
- if (!dm_event_register(dso, name, DM_EVENT_ALL_ERRORS))
+ if (!(dmevh = _create_dm_event_handler(name, dso, DM_EVENT_ALL_ERRORS)))
return_0;
- log_info("Registered %s for events", name);
+ if (dm_event_get_registered_device(dmevh, 0)) {
+ dm_event_handler_destroy(dmevh);
+ return 0;
+ }
+
+ evmask = dm_event_handler_get_event_mask(dmevh);
+ if (evmask & DM_EVENT_REGISTRATION_PENDING) {
+ *pending = 1;
+ evmask &= ~DM_EVENT_REGISTRATION_PENDING;
+ }
- return 1;
+ dm_event_handler_destroy(dmevh);
+
+ return evmask;
}
-static int _target_unregister_events(struct lv_segment *seg,
- int events)
+/* FIXME This gets run while suspended and performs banned operations. */
+static int _target_set_events(struct lv_segment *seg, int evmask, int set)
{
- char *dso;
- char *name;
+ char *dso, *name;
struct logical_volume *lv;
struct volume_group *vg;
+ struct dm_event_handler *dmevh;
+ int r;
lv = seg->lv;
vg = lv->vg;
- /* FIXME Remove this and use handle to avoid config file race */
- if (!_setup_registration(vg->cmd->mem, vg->cmd, &dso))
+ if (!_get_mirror_dso_path(vg->cmd, &dso))
return_0;
if (!(name = build_dm_name(vg->cmd->mem, vg->name, lv->name, NULL)))
return_0;
- /* FIXME Use handle returned by registration function instead of dso */
- if (!dm_event_unregister(dso, name, DM_EVENT_ALL_ERRORS))
+ if (!(dmevh = _create_dm_event_handler(name, dso, DM_EVENT_ALL_ERRORS)))
return_0;
- log_info("Unregistered %s for events", name);
+ r = set ? dm_event_register_handler(dmevh) : dm_event_unregister_handler(dmevh);
+ dm_event_handler_destroy(dmevh);
+ if (!r)
+ return_0;
+
+ log_info("%s %s for events", set ? "Monitored" : "Unmonitored", name);
return 1;
}
+static int _target_monitor_events(struct lv_segment *seg, int events)
+{
+ return _target_set_events(seg, events, 1);
+}
+
+static int _target_unmonitor_events(struct lv_segment *seg, int events)
+{
+ return _target_set_events(seg, events, 0);
+}
+
#endif /* DMEVENTD */
#endif /* DEVMAPPER_SUPPORT */
@@ -486,8 +530,9 @@
.target_percent = _mirrored_target_percent,
.target_present = _mirrored_target_present,
#ifdef DMEVENTD
- .target_register_events = _target_register_events,
- .target_unregister_events = _target_unregister_events,
+ .target_monitored = _target_monitored,
+ .target_monitor_events = _target_monitor_events,
+ .target_unmonitor_events = _target_unmonitor_events,
#endif
#endif
.modules_needed = _mirrored_modules_needed,
@@ -512,7 +557,7 @@
segtype->ops = &_mirrored_ops;
segtype->name = "mirror";
segtype->private = NULL;
- segtype->flags = SEG_AREAS_MIRRORED;
+ segtype->flags = SEG_AREAS_MIRRORED | SEG_MONITORED;
log_very_verbose("Initialised segtype: %s", segtype->name);
Modified: lvm2/trunk/lib/misc/lvm-file.c
==============================================================================
--- lvm2/trunk/lib/misc/lvm-file.c (original)
+++ lvm2/trunk/lib/misc/lvm-file.c Sat Apr 7 16:07:03 2007
@@ -66,7 +66,8 @@
if (!fcntl(*fd, F_SETLK, &lock))
return 1;
- close(*fd);
+ if (close(*fd))
+ log_sys_error("close", buffer);
}
return 0;
@@ -239,8 +240,80 @@
if (fsync(fd) && (errno != EROFS) && (errno != EINVAL))
log_sys_error("fsync", dir);
- close(fd);
+ if (close(fd))
+ log_sys_error("close", dir);
out:
dm_free(dir);
}
+
+/*
+ * Attempt to obtain fcntl lock on a file, if necessary creating file first
+ * or waiting.
+ * Returns file descriptor on success, else -1.
+ * mode is F_WRLCK or F_RDLCK
+ */
+int fcntl_lock_file(const char *file, short lock_type, int warn_if_read_only)
+{
+ int lockfd;
+ char *dir;
+ char *c;
+ struct flock lock = {
+ .l_type = lock_type,
+ .l_whence = 0,
+ .l_start = 0,
+ .l_len = 0
+ };
+
+ if (!(dir = dm_strdup(file))) {
+ log_error("fcntl_lock_file failed in strdup.");
+ return -1;
+ }
+
+ if ((c = strrchr(dir, '/')))
+ *c = '\0';
+
+ if (!create_dir(dir))
+ return -1;
+
+ log_very_verbose("Locking %s (%s, %hd)", file,
+ (lock_type == F_WRLCK) ? "F_WRLCK" : "F_RDLCK",
+ lock_type);
+ if ((lockfd = open(file, O_RDWR | O_CREAT, 0777)) < 0) {
+ /* EACCES has been reported on NFS */
+ if (warn_if_read_only || (errno != EROFS && errno != EACCES))
+ log_sys_error("open", file);
+ else
+ stack;
+
+ return -1;
+ }
+
+ if (fcntl(lockfd, F_SETLKW, &lock)) {
+ log_sys_error("fcntl", file);
+ return -1;
+ }
+
+ return lockfd;
+}
+
+void fcntl_unlock_file(int lockfd)
+{
+ struct flock lock = {
+ .l_type = F_UNLCK,
+ .l_whence = 0,
+ .l_start = 0,
+ .l_len = 0
+ };
+
+ log_very_verbose("Unlocking fd %d", lockfd);
+
+ if (fcntl(lockfd, F_SETLK, &lock) == -1)
+ log_error("fcntl unlock failed on fd %d: %s", lockfd,
+ strerror(errno));
+
+ if (close(lockfd))
+ log_error("lock file close failed on fd %d: %s", lockfd,
+ strerror(errno));
+}
+
Modified: lvm2/trunk/lib/misc/lvm-file.h
==============================================================================
--- lvm2/trunk/lib/misc/lvm-file.h (original)
+++ lvm2/trunk/lib/misc/lvm-file.h Sat Apr 7 16:07:03 2007
@@ -48,4 +48,8 @@
/* Sync directory changes */
void sync_dir(const char *file);
+/* fcntl locking wrappers */
+int fcntl_lock_file(const char *file, short lock_type, int warn_if_read_only);
+void fcntl_unlock_file(int lockfd);
+
#endif
Modified: lvm2/trunk/lib/report/columns.h
==============================================================================
--- lvm2/trunk/lib/report/columns.h (original)
+++ lvm2/trunk/lib/report/columns.h Sat Apr 7 16:07:03 2007
@@ -18,67 +18,67 @@
* Display Fn, Unique format identifier */
/* *INDENT-OFF* */
-FIELD(LVS, lv, STR, "LV UUID", lvid.id[1], 38, uuid, "lv_uuid")
-FIELD(LVS, lv, STR, "LV", lvid, 4, lvname, "lv_name")
-FIELD(LVS, lv, STR, "Attr", lvid, 4, lvstatus, "lv_attr")
-FIELD(LVS, lv, NUM, "Maj", major, 3, int32, "lv_major")
-FIELD(LVS, lv, NUM, "Min", minor, 3, int32, "lv_minor")
-FIELD(LVS, lv, STR, "KMaj", lvid, 4, lvkmaj, "lv_kernel_major")
-FIELD(LVS, lv, STR, "KMin", lvid, 4, lvkmin, "lv_kernel_minor")
-FIELD(LVS, lv, NUM, "LSize", size, 5, size64, "lv_size")
-FIELD(LVS, lv, NUM, "#Seg", lvid, 4, lvsegcount, "seg_count")
-FIELD(LVS, lv, STR, "Origin", lvid, 6, origin, "origin")
-FIELD(LVS, lv, NUM, "Snap%", lvid, 6, snpercent, "snap_percent")
-FIELD(LVS, lv, NUM, "Copy%", lvid, 6, copypercent, "copy_percent")
-FIELD(LVS, lv, STR, "Move", lvid, 4, movepv, "move_pv")
-FIELD(LVS, lv, STR, "LV Tags", tags, 7, tags, "lv_tags")
-FIELD(LVS, lv, STR, "Log", lvid, 3, loglv, "mirror_log")
-FIELD(LVS, lv, STR, "Modules", lvid, 7, modules, "modules")
+FIELD(LVS, lv, STR, "LV UUID", lvid.id[1], 38, uuid, "lv_uuid", "Unique identifier")
+FIELD(LVS, lv, STR, "LV", lvid, 4, lvname, "lv_name", "Name. LVs created for internal use are enclosed in brackets.")
+FIELD(LVS, lv, STR, "Attr", lvid, 4, lvstatus, "lv_attr", "Various attributes - see man page.")
+FIELD(LVS, lv, NUM, "Maj", major, 3, int32, "lv_major", "Persistent major number or -1 if not persistent.")
+FIELD(LVS, lv, NUM, "Min", minor, 3, int32, "lv_minor", "Persistent minor number or -1 if not persistent.")
+FIELD(LVS, lv, STR, "KMaj", lvid, 4, lvkmaj, "lv_kernel_major", "Currently assigned major number or -1 if LV is not active.")
+FIELD(LVS, lv, STR, "KMin", lvid, 4, lvkmin, "lv_kernel_minor", "Currently assigned minor number or -1 if LV is not active.")
+FIELD(LVS, lv, NUM, "LSize", size, 5, size64, "lv_size", "Size of LV in current units.")
+FIELD(LVS, lv, NUM, "#Seg", lvid, 4, lvsegcount, "seg_count", "Number of segments in LV.")
+FIELD(LVS, lv, STR, "Origin", lvid, 6, origin, "origin", "For snapshots, the origin device of this LV")
+FIELD(LVS, lv, NUM, "Snap%", lvid, 6, snpercent, "snap_percent", "For snapshots, the percentage full if LV is active.")
+FIELD(LVS, lv, NUM, "Copy%", lvid, 6, copypercent, "copy_percent", "For mirrors and pvmove, current percentage in-sync.")
+FIELD(LVS, lv, STR, "Move", lvid, 4, movepv, "move_pv", "For pvmove, Source PV of temporary LV created by pvmove")
+FIELD(LVS, lv, STR, "LV Tags", tags, 7, tags, "lv_tags", "Tags, if any.")
+FIELD(LVS, lv, STR, "Log", lvid, 3, loglv, "mirror_log", "For mirrors, the LV holding the synchronisation log.")
+FIELD(LVS, lv, STR, "Modules", lvid, 7, modules, "modules", "Kernel device-mapper modules required for this LV.")
-FIELD(PVS, pv, STR, "Fmt", id, 3, pvfmt, "pv_fmt")
-FIELD(PVS, pv, STR, "PV UUID", id, 38, uuid, "pv_uuid")
-FIELD(PVS, pv, NUM, "PSize", id, 5, pvsize, "pv_size")
-FIELD(PVS, pv, NUM, "DevSize", dev, 7, devsize, "dev_size")
-FIELD(PVS, pv, NUM, "1st PE", pe_start, 7, size64, "pe_start")
-FIELD(PVS, pv, NUM, "PFree", id, 5, pvfree, "pv_free")
-FIELD(PVS, pv, NUM, "Used", id, 4, pvused, "pv_used")
-FIELD(PVS, pv, STR, "PV", dev, 10, dev_name, "pv_name")
-FIELD(PVS, pv, STR, "Attr", status, 4, pvstatus, "pv_attr")
-FIELD(PVS, pv, NUM, "PE", pe_count, 3, uint32, "pv_pe_count")
-FIELD(PVS, pv, NUM, "Alloc", pe_alloc_count, 5, uint32, "pv_pe_alloc_count")
-FIELD(PVS, pv, STR, "PV Tags", tags, 7, tags, "pv_tags")
+FIELD(PVS, pv, STR, "Fmt", id, 3, pvfmt, "pv_fmt", "Type of metadata.")
+FIELD(PVS, pv, STR, "PV UUID", id, 38, uuid, "pv_uuid", "Unique identifier.")
+FIELD(PVS, pv, NUM, "PSize", id, 5, pvsize, "pv_size", "Size of PV in current units.")
+FIELD(PVS, pv, NUM, "DevSize", dev, 7, devsize, "dev_size", "Size of underlying device in current units.")
+FIELD(PVS, pv, NUM, "1st PE", pe_start, 7, size64, "pe_start", "Offset to the start of data on the underlying device.")
+FIELD(PVS, pv, NUM, "PFree", id, 5, pvfree, "pv_free", "Total amount of unallocated space in current units.")
+FIELD(PVS, pv, NUM, "Used", id, 4, pvused, "pv_used", "Total amount of allocated space in current units.")
+FIELD(PVS, pv, STR, "PV", dev, 10, dev_name, "pv_name", "Name.")
+FIELD(PVS, pv, STR, "Attr", status, 4, pvstatus, "pv_attr", "Various attributes - see man page.")
+FIELD(PVS, pv, NUM, "PE", pe_count, 3, uint32, "pv_pe_count", "Total number of Physical Extents.")
+FIELD(PVS, pv, NUM, "Alloc", pe_alloc_count, 5, uint32, "pv_pe_alloc_count", "Total number of allocated Physical Extents.")
+FIELD(PVS, pv, STR, "PV Tags", tags, 7, tags, "pv_tags", "Tags, if any.")
-FIELD(VGS, vg, STR, "Fmt", cmd, 3, vgfmt, "vg_fmt")
-FIELD(VGS, vg, STR, "VG UUID", id, 38, uuid, "vg_uuid")
-FIELD(VGS, vg, STR, "VG", name, 4, string, "vg_name")
-FIELD(VGS, vg, STR, "Attr", cmd, 5, vgstatus, "vg_attr")
-FIELD(VGS, vg, NUM, "VSize", cmd, 5, vgsize, "vg_size")
-FIELD(VGS, vg, NUM, "VFree", cmd, 5, vgfree, "vg_free")
-FIELD(VGS, vg, STR, "SYS ID", system_id, 6, string, "vg_sysid")
-FIELD(VGS, vg, NUM, "Ext", extent_size, 3, size32, "vg_extent_size")
-FIELD(VGS, vg, NUM, "#Ext", extent_count, 4, uint32, "vg_extent_count")
-FIELD(VGS, vg, NUM, "Free", free_count, 4, uint32, "vg_free_count")
-FIELD(VGS, vg, NUM, "MaxLV", max_lv, 5, uint32, "max_lv")
-FIELD(VGS, vg, NUM, "MaxPV", max_pv, 5, uint32, "max_pv")
-FIELD(VGS, vg, NUM, "#PV", pv_count, 3, uint32, "pv_count")
-FIELD(VGS, vg, NUM, "#LV", lv_count, 3, uint32, "lv_count")
-FIELD(VGS, vg, NUM, "#SN", snapshot_count, 3, uint32, "snap_count")
-FIELD(VGS, vg, NUM, "Seq", seqno, 3, uint32, "vg_seqno")
-FIELD(VGS, vg, STR, "VG Tags", tags, 7, tags, "vg_tags")
+FIELD(VGS, vg, STR, "Fmt", cmd, 3, vgfmt, "vg_fmt", "Type of metadata.")
+FIELD(VGS, vg, STR, "VG UUID", id, 38, uuid, "vg_uuid", "Unique identifier.")
+FIELD(VGS, vg, STR, "VG", name, 4, string, "vg_name", "Name.")
+FIELD(VGS, vg, STR, "Attr", cmd, 5, vgstatus, "vg_attr", "Various attributes - see man page.")
+FIELD(VGS, vg, NUM, "VSize", cmd, 5, vgsize, "vg_size", "Total size of VG in current units.")
+FIELD(VGS, vg, NUM, "VFree", cmd, 5, vgfree, "vg_free", "Total amount of free space in current units.")
+FIELD(VGS, vg, STR, "SYS ID", system_id, 6, string, "vg_sysid", "System ID indicating when and where it was created.")
+FIELD(VGS, vg, NUM, "Ext", extent_size, 3, size32, "vg_extent_size", "Size of Physical Extents in current units.")
+FIELD(VGS, vg, NUM, "#Ext", extent_count, 4, uint32, "vg_extent_count", "Total number of Physical Extents.")
+FIELD(VGS, vg, NUM, "Free", free_count, 4, uint32, "vg_free_count", "Total number of unallocated Physical Extents.")
+FIELD(VGS, vg, NUM, "MaxLV", max_lv, 5, uint32, "max_lv", "Maximum number of LVs allowed in VG or 0 if unlimited.")
+FIELD(VGS, vg, NUM, "MaxPV", max_pv, 5, uint32, "max_pv", "Maximum number of PVs allowed in VG or 0 if unlimited.")
+FIELD(VGS, vg, NUM, "#PV", pv_count, 3, uint32, "pv_count", "Number of PVs.")
+FIELD(VGS, vg, NUM, "#LV", lv_count, 3, uint32, "lv_count", "Number of LVs.")
+FIELD(VGS, vg, NUM, "#SN", snapshot_count, 3, uint32, "snap_count", "Number of snapshots.")
+FIELD(VGS, vg, NUM, "Seq", seqno, 3, uint32, "vg_seqno", "Revision number of internal metadata. Incremented whenever it changes.")
+FIELD(VGS, vg, STR, "VG Tags", tags, 7, tags, "vg_tags", "Tags, if any.")
-FIELD(SEGS, seg, STR, "Type", list, 4, segtype, "segtype")
-FIELD(SEGS, seg, NUM, "#Str", area_count, 4, uint32, "stripes")
-FIELD(SEGS, seg, NUM, "Stripe", stripe_size, 6, size32, "stripesize")
-FIELD(SEGS, seg, NUM, "Stripe", stripe_size, 6, size32, "stripe_size")
-FIELD(SEGS, seg, NUM, "Chunk", list, 5, chunksize, "chunksize")
-FIELD(SEGS, seg, NUM, "Chunk", list, 5, chunksize, "chunk_size")
-FIELD(SEGS, seg, NUM, "Region", region_size, 6, size32, "regionsize")
-FIELD(SEGS, seg, NUM, "Region", region_size, 6, size32, "region_size")
-FIELD(SEGS, seg, NUM, "Start", list, 5, segstart, "seg_start")
-FIELD(SEGS, seg, NUM, "SSize", list, 5, segsize, "seg_size")
-FIELD(SEGS, seg, STR, "Seg Tags", tags, 8, tags, "seg_tags")
-FIELD(SEGS, seg, STR, "Devices", list, 5, devices, "devices")
+FIELD(SEGS, seg, STR, "Type", list, 4, segtype, "segtype", "Type of LV segment")
+FIELD(SEGS, seg, NUM, "#Str", area_count, 4, uint32, "stripes", "Number of stripes or mirror legs.")
+FIELD(SEGS, seg, NUM, "Stripe", stripe_size, 6, size32, "stripesize", "For stripes, amount of data placed on one device before switching to the next.")
+FIELD(SEGS, seg, NUM, "Stripe", stripe_size, 6, size32, "stripe_size", "For stripes, amount of data placed on one device before switching to the next.")
+FIELD(SEGS, seg, NUM, "Region", region_size, 6, size32, "regionsize", "For mirrors, the unit of data copied when synchronising devices.")
+FIELD(SEGS, seg, NUM, "Region", region_size, 6, size32, "region_size", "For mirrors, the unit of data copied when synchronising devices.")
+FIELD(SEGS, seg, NUM, "Chunk", list, 5, chunksize, "chunksize", "For snapshots, the unit of data used when tracking changes.")
+FIELD(SEGS, seg, NUM, "Chunk", list, 5, chunksize, "chunk_size", "For snapshots, the unit of data used when tracking changes.")
+FIELD(SEGS, seg, NUM, "Start", list, 5, segstart, "seg_start", "Offset within the LV to the start of the segment in current units.")
+FIELD(SEGS, seg, NUM, "SSize", list, 5, segsize, "seg_size", "Size of segment in current units.")
+FIELD(SEGS, seg, STR, "Seg Tags", tags, 8, tags, "seg_tags", "Tags, if any.")
+FIELD(SEGS, seg, STR, "Devices", list, 5, devices, "devices", "Underlying devices used with starting extent numbers.")
-FIELD(PVSEGS, pvseg, NUM, "Start", pe, 5, uint32, "pvseg_start")
-FIELD(PVSEGS, pvseg, NUM, "SSize", len, 5, uint32, "pvseg_size")
+FIELD(PVSEGS, pvseg, NUM, "Start", pe, 5, uint32, "pvseg_start", "Physical Extent number of start of segment.")
+FIELD(PVSEGS, pvseg, NUM, "SSize", len, 5, uint32, "pvseg_size", "Number of extents in segment.")
/* *INDENT-ON* */
Modified: lvm2/trunk/lib/report/report.c
==============================================================================
--- lvm2/trunk/lib/report/report.c (original)
+++ lvm2/trunk/lib/report/report.c Sat Apr 7 16:07:03 2007
@@ -22,8 +22,17 @@
#include "activate.h"
#include "segtype.h"
#include "str_list.h"
+#include "lvmcache.h"
-/*
+struct lvm_report_object {
+ struct volume_group *vg;
+ struct logical_volume *lv;
+ struct physical_volume *pv;
+ struct lv_segment *seg;
+ struct pv_segment *pvseg;
+};
+
+/*
* For macro use
*/
static union {
@@ -34,71 +43,6 @@
struct pv_segment _pvseg;
} _dummy;
-/*
- * Report handle flags
- */
-#define RH_SORT_REQUIRED 0x00000001
-#define RH_HEADINGS_PRINTED 0x00000002
-#define RH_BUFFERED 0x00000004
-#define RH_ALIGNED 0x00000008
-#define RH_HEADINGS 0x00000010
-
-struct report_handle {
- struct cmd_context *cmd;
- struct dm_pool *mem;
-
- report_type_t type;
- const char *field_prefix;
- uint32_t flags;
- const char *separator;
-
- uint32_t keys_count;
-
- /* Ordered list of fields needed for this report */
- struct list field_props;
-
- /* Rows of report data */
- struct list rows;
-};
-
-/*
- * Per-field flags
- */
-#define FLD_ALIGN_LEFT 0x00000001
-#define FLD_ALIGN_RIGHT 0x00000002
-#define FLD_STRING 0x00000004
-#define FLD_NUMBER 0x00000008
-#define FLD_HIDDEN 0x00000010
-#define FLD_SORT_KEY 0x00000020
-#define FLD_ASCENDING 0x00000040
-#define FLD_DESCENDING 0x00000080
-
-struct field_properties {
- struct list list;
- uint32_t field_num;
- uint32_t sort_posn;
- int width;
- uint32_t flags;
-};
-
-/*
- * Report data
- */
-struct field {
- struct list list;
- struct field_properties *props;
-
- const char *report_string; /* Formatted ready for display */
- const void *sort_value; /* Raw value for sorting */
-};
-
-struct row {
- struct list list;
- struct report_handle *rh;
- struct list fields; /* Fields in display order */
- struct field *(*sort_fields)[]; /* Fields in sort order */
-};
-
static char _alloc_policy_char(alloc_policy_t alloc)
{
switch (alloc) {
@@ -118,31 +62,25 @@
/*
* Data-munging functions to prepare each data type for display and sorting
*/
-static int _string_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _string_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
- if (!
- (field->report_string =
- dm_pool_strdup(rh->mem, *(const char **) data))) {
- log_error("dm_pool_strdup failed");
- return 0;
- }
-
- field->sort_value = (const void *) field->report_string;
-
- return 1;
+ return dm_report_field_string(rh, field, (const char **) data);
}
-static int _dev_name_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _dev_name_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const char *name = dev_name(*(const struct device **) data);
- return _string_disp(rh, field, &name);
+ return dm_report_field_string(rh, field, &name);
}
-static int _devices_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _devices_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const struct lv_segment *seg = (const struct lv_segment *) data;
unsigned int s;
@@ -150,7 +88,7 @@
uint32_t extent = 0;
char extent_str[32];
- if (!dm_pool_begin_object(rh->mem, 256)) {
+ if (!dm_pool_begin_object(mem, 256)) {
log_error("dm_pool_begin_object failed");
return 0;
}
@@ -170,7 +108,7 @@
extent = 0;
}
- if (!dm_pool_grow_object(rh->mem, name, strlen(name))) {
+ if (!dm_pool_grow_object(mem, name, strlen(name))) {
log_error("dm_pool_grow_object failed");
return 0;
}
@@ -181,173 +119,143 @@
return 0;
}
- if (!dm_pool_grow_object(rh->mem, extent_str, strlen(extent_str))) {
+ if (!dm_pool_grow_object(mem, extent_str, strlen(extent_str))) {
log_error("dm_pool_grow_object failed");
return 0;
}
if ((s != seg->area_count - 1) &&
- !dm_pool_grow_object(rh->mem, ",", 1)) {
+ !dm_pool_grow_object(mem, ",", 1)) {
log_error("dm_pool_grow_object failed");
return 0;
}
}
- if (!dm_pool_grow_object(rh->mem, "\0", 1)) {
+ if (!dm_pool_grow_object(mem, "\0", 1)) {
log_error("dm_pool_grow_object failed");
return 0;
}
- field->report_string = dm_pool_end_object(rh->mem);
- field->sort_value = (const void *) field->report_string;
+ dm_report_field_set_value(field, dm_pool_end_object(mem), NULL);
return 1;
}
-static int _tags_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _tags_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const struct list *tags = (const struct list *) data;
struct str_list *sl;
- if (!dm_pool_begin_object(rh->mem, 256)) {
+ if (!dm_pool_begin_object(mem, 256)) {
log_error("dm_pool_begin_object failed");
return 0;
}
list_iterate_items(sl, tags) {
- if (!dm_pool_grow_object(rh->mem, sl->str, strlen(sl->str)) ||
- (sl->list.n != tags && !dm_pool_grow_object(rh->mem, ",", 1))) {
+ if (!dm_pool_grow_object(mem, sl->str, strlen(sl->str)) ||
+ (sl->list.n != tags && !dm_pool_grow_object(mem, ",", 1))) {
log_error("dm_pool_grow_object failed");
return 0;
}
}
- if (!dm_pool_grow_object(rh->mem, "\0", 1)) {
+ if (!dm_pool_grow_object(mem, "\0", 1)) {
log_error("dm_pool_grow_object failed");
return 0;
}
- field->report_string = dm_pool_end_object(rh->mem);
- field->sort_value = (const void *) field->report_string;
+ dm_report_field_set_value(field, dm_pool_end_object(mem), NULL);
return 1;
}
-static int _modules_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _modules_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
struct list *modules;
- if (!(modules = str_list_create(rh->mem))) {
+ if (!(modules = str_list_create(mem))) {
log_error("modules str_list allocation failed");
return 0;
}
- if (!list_lv_modules(rh->mem, lv, modules))
+ if (!list_lv_modules(mem, lv, modules))
return_0;
- return _tags_disp(rh, field, modules);
+ return _tags_disp(rh, mem, field, modules, private);
}
-static int _vgfmt_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _vgfmt_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const struct volume_group *vg = (const struct volume_group *) data;
if (!vg->fid) {
- field->report_string = "";
- field->sort_value = (const void *) field->report_string;
+ dm_report_field_set_value(field, "", NULL);
return 1;
}
- return _string_disp(rh, field, &vg->fid->fmt->name);
+ return _string_disp(rh, mem, field, &vg->fid->fmt->name, private);
}
-static int _pvfmt_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _pvfmt_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const struct physical_volume *pv =
(const struct physical_volume *) data;
if (!pv->fmt) {
- field->report_string = "";
- field->sort_value = (const void *) field->report_string;
+ dm_report_field_set_value(field, "", NULL);
return 1;
}
- return _string_disp(rh, field, &pv->fmt->name);
+ return _string_disp(rh, mem, field, &pv->fmt->name, private);
}
-static int _int_disp(struct report_handle *rh, struct field *field,
- const void *data)
-{
- const int value = *(const int *) data;
- uint64_t *sortval;
- char *repstr;
-
- if (!(repstr = dm_pool_zalloc(rh->mem, 13))) {
- log_error("dm_pool_alloc failed");
- return 0;
- }
-
- if (!(sortval = dm_pool_alloc(rh->mem, sizeof(int64_t)))) {
- log_error("dm_pool_alloc failed");
- return 0;
- }
-
- if (dm_snprintf(repstr, 12, "%d", value) < 0) {
- log_error("int too big: %d", value);
- return 0;
- }
-
- *sortval = (const uint64_t) value;
- field->sort_value = sortval;
- field->report_string = repstr;
-
- return 1;
-}
-
-static int _lvkmaj_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _lvkmaj_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
struct lvinfo info;
uint64_t minusone = UINT64_C(-1);
if (lv_info(lv->vg->cmd, lv, &info, 0) && info.exists)
- return _int_disp(rh, field, &info.major);
- else
- return _int_disp(rh, field, &minusone);
+ return dm_report_field_int(rh, field, &info.major);
- return 1;
+ return dm_report_field_uint64(rh, field, &minusone);
}
-static int _lvkmin_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _lvkmin_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
struct lvinfo info;
uint64_t minusone = UINT64_C(-1);
if (lv_info(lv->vg->cmd, lv, &info, 0) && info.exists)
- return _int_disp(rh, field, &info.minor);
- else
- return _int_disp(rh, field, &minusone);
+ return dm_report_field_int(rh, field, &info.minor);
- return 1;
+ return dm_report_field_uint64(rh, field, &minusone);
}
-static int _lvstatus_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _lvstatus_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
struct lvinfo info;
char *repstr;
float snap_percent;
- if (!(repstr = dm_pool_zalloc(rh->mem, 7))) {
+ if (!(repstr = dm_pool_zalloc(mem, 7))) {
log_error("dm_pool_alloc failed");
return 0;
}
@@ -419,19 +327,18 @@
repstr[5] = '-';
}
- field->report_string = repstr;
- field->sort_value = (const void *) field->report_string;
-
+ dm_report_field_set_value(field, repstr, NULL);
return 1;
}
-static int _pvstatus_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _pvstatus_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const uint32_t status = *(const uint32_t *) data;
char *repstr;
- if (!(repstr = dm_pool_zalloc(rh->mem, 4))) {
+ if (!(repstr = dm_pool_zalloc(mem, 4))) {
log_error("dm_pool_alloc failed");
return 0;
}
@@ -446,19 +353,18 @@
else
repstr[1] = '-';
- field->report_string = repstr;
- field->sort_value = (const void *) field->report_string;
-
+ dm_report_field_set_value(field, repstr, NULL);
return 1;
}
-static int _vgstatus_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _vgstatus_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const struct volume_group *vg = (const struct volume_group *) data;
char *repstr;
- if (!(repstr = dm_pool_zalloc(rh->mem, 7))) {
+ if (!(repstr = dm_pool_zalloc(mem, 7))) {
log_error("dm_pool_alloc failed");
return 0;
}
@@ -490,43 +396,43 @@
else
repstr[5] = '-';
- field->report_string = repstr;
- field->sort_value = (const void *) field->report_string;
-
+ dm_report_field_set_value(field, repstr, NULL);
return 1;
}
-static int _segtype_disp(struct report_handle *rh __attribute((unused)),
- struct field *field,
- const void *data)
+static int _segtype_disp(struct dm_report *rh __attribute((unused)),
+ struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const struct lv_segment *seg = (const struct lv_segment *) data;
- if (seg->area_count == 1)
- field->report_string = "linear";
- else
- field->report_string = seg->segtype->ops->name(seg);
- field->sort_value = (const void *) field->report_string;
+ if (seg->area_count == 1) {
+ dm_report_field_set_value(field, "linear", NULL);
+ return 1;
+ }
+ dm_report_field_set_value(field, seg->segtype->ops->name(seg), NULL);
return 1;
}
-static int _origin_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _origin_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
if (lv_is_cow(lv))
- return _string_disp(rh, field, &origin_from_cow(lv)->name);
-
- field->report_string = "";
- field->sort_value = (const void *) field->report_string;
+ return dm_report_field_string(rh, field,
+ (const char **) &origin_from_cow(lv)->name);
+ dm_report_field_set_value(field, "", NULL);
return 1;
}
-static int _loglv_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _loglv_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
struct lv_segment *seg;
@@ -534,29 +440,29 @@
list_iterate_items(seg, &lv->segments) {
if (!seg_is_mirrored(seg) || !seg->log_lv)
continue;
- return _string_disp(rh, field, &seg->log_lv->name);
+ return dm_report_field_string(rh, field,
+ (const char **) &seg->log_lv->name);
}
- field->report_string = "";
- field->sort_value = (const void *) field->report_string;
-
+ dm_report_field_set_value(field, "", NULL);
return 1;
}
-static int _lvname_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _lvname_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
- char *repstr;
+ char *repstr, *lvname;
size_t len;
if (lv_is_visible(lv)) {
repstr = lv->name;
- return _string_disp(rh, field, &repstr);
+ return dm_report_field_string(rh, field, (const char **) &repstr);
}
len = strlen(lv->name) + 3;
- if (!(repstr = dm_pool_zalloc(rh->mem, len))) {
+ if (!(repstr = dm_pool_zalloc(mem, len))) {
log_error("dm_pool_alloc failed");
return 0;
}
@@ -566,18 +472,19 @@
return 0;
}
- field->report_string = repstr;
-
- if (!(field->sort_value = dm_pool_strdup(rh->mem, lv->name))) {
+ if (!(lvname = dm_pool_strdup(mem, lv->name))) {
log_error("dm_pool_strdup failed");
return 0;
}
+ dm_report_field_set_value(field, repstr, lvname);
+
return 1;
}
-static int _movepv_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _movepv_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
const char *name;
@@ -587,106 +494,111 @@
if (!(seg->status & PVMOVE))
continue;
name = dev_name(seg_dev(seg, 0));
- return _string_disp(rh, field, &name);
+ return dm_report_field_string(rh, field, &name);
}
- field->report_string = "";
- field->sort_value = (const void *) field->report_string;
-
+ dm_report_field_set_value(field, "", NULL);
return 1;
}
-static int _size32_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _size32_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const uint32_t size = *(const uint32_t *) data;
- const char *disp;
+ const char *disp, *repstr;
uint64_t *sortval;
- if (!*(disp = display_size_units(rh->cmd, (uint64_t) size))) {
+ if (!*(disp = display_size_units(private, (uint64_t) size))) {
stack;
return 0;
}
- if (!(field->report_string = dm_pool_strdup(rh->mem, disp))) {
+ if (!(repstr = dm_pool_strdup(mem, disp))) {
log_error("dm_pool_strdup failed");
return 0;
}
- if (!(sortval = dm_pool_alloc(rh->mem, sizeof(uint64_t)))) {
+ if (!(sortval = dm_pool_alloc(mem, sizeof(uint64_t)))) {
log_error("dm_pool_alloc failed");
return 0;
}
*sortval = (const uint64_t) size;
- field->sort_value = (const void *) sortval;
+
+ dm_report_field_set_value(field, repstr, sortval);
return 1;
}
-static int _size64_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _size64_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const uint64_t size = *(const uint64_t *) data;
- const char *disp;
+ const char *disp, *repstr;
uint64_t *sortval;
- if (!*(disp = display_size_units(rh->cmd, size))) {
+ if (!*(disp = display_size_units(private, size))) {
stack;
return 0;
}
- if (!(field->report_string = dm_pool_strdup(rh->mem, disp))) {
+ if (!(repstr = dm_pool_strdup(mem, disp))) {
log_error("dm_pool_strdup failed");
return 0;
}
- if (!(sortval = dm_pool_alloc(rh->mem, sizeof(uint64_t)))) {
+ if (!(sortval = dm_pool_alloc(mem, sizeof(uint64_t)))) {
log_error("dm_pool_alloc failed");
return 0;
}
*sortval = size;
- field->sort_value = sortval;
+ dm_report_field_set_value(field, repstr, sortval);
return 1;
}
-static int _vgsize_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _vgsize_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const struct volume_group *vg = (const struct volume_group *) data;
uint64_t size;
size = (uint64_t) vg->extent_count * vg->extent_size;
- return _size64_disp(rh, field, &size);
+ return _size64_disp(rh, mem, field, &size, private);
}
-static int _segstart_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _segstart_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const struct lv_segment *seg = (const struct lv_segment *) data;
uint64_t start;
start = (uint64_t) seg->le * seg->lv->vg->extent_size;
- return _size64_disp(rh, field, &start);
+ return _size64_disp(rh, mem, field, &start, private);
}
-static int _segsize_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _segsize_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const struct lv_segment *seg = (const struct lv_segment *) data;
uint64_t size;
size = (uint64_t) seg->len * seg->lv->vg->extent_size;
- return _size64_disp(rh, field, &size);
+ return _size64_disp(rh, mem, field, &size, private);
}
-static int _chunksize_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _chunksize_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const struct lv_segment *seg = (const struct lv_segment *) data;
uint64_t size;
@@ -696,11 +608,12 @@
else
size = 0;
- return _size64_disp(rh, field, &size);
+ return _size64_disp(rh, mem, field, &size, private);
}
-static int _pvused_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _pvused_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const struct physical_volume *pv =
(const struct physical_volume *) data;
@@ -711,11 +624,12 @@
else
used = (uint64_t) pv->pe_alloc_count * pv->pe_size;
- return _size64_disp(rh, field, &used);
+ return _size64_disp(rh, mem, field, &used, private);
}
-static int _pvfree_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _pvfree_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const struct physical_volume *pv =
(const struct physical_volume *) data;
@@ -726,11 +640,12 @@
else
freespace = (uint64_t) (pv->pe_count - pv->pe_alloc_count) * pv->pe_size;
- return _size64_disp(rh, field, &freespace);
+ return _size64_disp(rh, mem, field, &freespace, private);
}
-static int _pvsize_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _pvsize_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const struct physical_volume *pv =
(const struct physical_volume *) data;
@@ -741,11 +656,12 @@
else
size = (uint64_t) pv->pe_count * pv->pe_size;
- return _size64_disp(rh, field, &size);
+ return _size64_disp(rh, mem, field, &size, private);
}
-static int _devsize_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _devsize_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const struct device *dev = *(const struct device **) data;
uint64_t size;
@@ -753,26 +669,28 @@
if (!dev_get_size(dev, &size))
size = 0;
- return _size64_disp(rh, field, &size);
+ return _size64_disp(rh, mem, field, &size, private);
}
-static int _vgfree_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _vgfree_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const struct volume_group *vg = (const struct volume_group *) data;
uint64_t freespace;
freespace = (uint64_t) vg->free_count * vg->extent_size;
- return _size64_disp(rh, field, &freespace);
+ return _size64_disp(rh, mem, field, &freespace, private);
}
-static int _uuid_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _uuid_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
char *repstr = NULL;
- if (!(repstr = dm_pool_alloc(rh->mem, 40))) {
+ if (!(repstr = dm_pool_alloc(mem, 40))) {
log_error("dm_pool_alloc failed");
return 0;
}
@@ -782,83 +700,39 @@
return 0;
}
- field->report_string = repstr;
- field->sort_value = (const void *) field->report_string;
-
+ dm_report_field_set_value(field, repstr, NULL);
return 1;
}
-static int _uint32_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _uint32_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
- const uint32_t value = *(const uint32_t *) data;
- uint64_t *sortval;
- char *repstr;
-
- if (!(repstr = dm_pool_zalloc(rh->mem, 12))) {
- log_error("dm_pool_alloc failed");
- return 0;
- }
-
- if (!(sortval = dm_pool_alloc(rh->mem, sizeof(uint64_t)))) {
- log_error("dm_pool_alloc failed");
- return 0;
- }
-
- if (dm_snprintf(repstr, 11, "%u", value) < 0) {
- log_error("uint32 too big: %u", value);
- return 0;
- }
-
- *sortval = (const uint64_t) value;
- field->sort_value = sortval;
- field->report_string = repstr;
-
- return 1;
+ return dm_report_field_uint32(rh, field, data);
}
-static int _int32_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _int32_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
- const int32_t value = *(const int32_t *) data;
- uint64_t *sortval;
- char *repstr;
-
- if (!(repstr = dm_pool_zalloc(rh->mem, 13))) {
- log_error("dm_pool_alloc failed");
- return 0;
- }
-
- if (!(sortval = dm_pool_alloc(rh->mem, sizeof(int64_t)))) {
- log_error("dm_pool_alloc failed");
- return 0;
- }
-
- if (dm_snprintf(repstr, 12, "%d", value) < 0) {
- log_error("int32 too big: %d", value);
- return 0;
- }
-
- *sortval = (const uint64_t) value;
- field->sort_value = sortval;
- field->report_string = repstr;
-
- return 1;
+ return dm_report_field_int32(rh, field, data);
}
-static int _lvsegcount_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _lvsegcount_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
uint32_t count;
count = list_size(&lv->segments);
- return _uint32_disp(rh, field, &count);
+ return _uint32_disp(rh, mem, field, &count, private);
}
-static int _snpercent_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _snpercent_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
struct lvinfo info;
@@ -866,27 +740,31 @@
uint64_t *sortval;
char *repstr;
- if (!(sortval = dm_pool_alloc(rh->mem, sizeof(uint64_t)))) {
+ /* Suppress snapshot percentage if not using driver */
+ if (!activation()) {
+ dm_report_field_set_value(field, "", NULL);
+ return 1;
+ }
+
+ if (!(sortval = dm_pool_alloc(mem, sizeof(uint64_t)))) {
log_error("dm_pool_alloc failed");
return 0;
}
if (!lv_is_cow(lv) ||
(lv_info(lv->vg->cmd, lv, &info, 0) && !info.exists)) {
- field->report_string = "";
*sortval = UINT64_C(0);
- field->sort_value = sortval;
+ dm_report_field_set_value(field, "", sortval);
return 1;
}
if (!lv_snapshot_percent(lv, &snap_percent) || snap_percent < 0) {
- field->report_string = "100.00";
*sortval = UINT64_C(100);
- field->sort_value = sortval;
+ dm_report_field_set_value(field, "100.00", sortval);
return 1;
}
- if (!(repstr = dm_pool_zalloc(rh->mem, 8))) {
+ if (!(repstr = dm_pool_zalloc(mem, 8))) {
log_error("dm_pool_alloc failed");
return 0;
}
@@ -897,36 +775,35 @@
}
*sortval = snap_percent * UINT64_C(1000);
- field->sort_value = sortval;
- field->report_string = repstr;
+ dm_report_field_set_value(field, repstr, sortval);
return 1;
}
-static int _copypercent_disp(struct report_handle *rh, struct field *field,
- const void *data)
+static int _copypercent_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
{
struct logical_volume *lv = (struct logical_volume *) data;
float percent;
uint64_t *sortval;
char *repstr;
- if (!(sortval = dm_pool_alloc(rh->mem, sizeof(uint64_t)))) {
+ if (!(sortval = dm_pool_alloc(mem, sizeof(uint64_t)))) {
log_error("dm_pool_alloc failed");
return 0;
}
if ((!(lv->status & PVMOVE) && !(lv->status & MIRRORED)) ||
!lv_mirror_percent(lv->vg->cmd, lv, 0, &percent, NULL)) {
- field->report_string = "";
*sortval = UINT64_C(0);
- field->sort_value = sortval;
+ dm_report_field_set_value(field, "", sortval);
return 1;
}
percent = copy_percent(lv);
- if (!(repstr = dm_pool_zalloc(rh->mem, 8))) {
+ if (!(repstr = dm_pool_zalloc(mem, 8))) {
log_error("dm_pool_alloc failed");
return 0;
}
@@ -937,330 +814,88 @@
}
*sortval = percent * UINT64_C(1000);
- field->sort_value = sortval;
- field->report_string = repstr;
+ dm_report_field_set_value(field, repstr, sortval);
return 1;
}
-/*
- * Import column definitions
- */
+/* Report object types */
-#define STR (FLD_STRING | FLD_ALIGN_LEFT)
-#define NUM (FLD_NUMBER | FLD_ALIGN_RIGHT)
-#define FIELD(type, strct, sorttype, head, field, width, func, id) {type, id, (off_t)((void *)&_dummy._ ## strct.field - (void *)&_dummy._ ## strct), head, width, sorttype, &_ ## func ## _disp},
-
-static struct {
- report_type_t type;
- const char id[32];
- off_t offset;
- const char heading[32];
- int width;
- uint32_t flags;
- field_report_fn report_fn;
-} _fields[] = {
-#include "columns.h"
+/* necessary for displaying something for PVs not belonging to VG */
+static struct volume_group _dummy_vg = {
+ .name = (char *) ORPHAN,
};
-#undef STR
-#undef NUM
-#undef FIELD
-
-const unsigned int _num_fields = sizeof(_fields) / sizeof(_fields[0]);
-
-static void _display_fields(void)
+static void *_obj_get_vg(void *obj)
{
- uint32_t f;
- const char *type, *last_type = "";
-
- for (f = 0; f < _num_fields; f++) {
- switch (_fields[f].type) {
- case PVS:
- type = "Physical Volume";
- break;
- case LVS:
- type = "Logical Volume";
- break;
- case VGS:
- type = "Volume Group";
- break;
- case SEGS:
- type = "Logical Volume Segment";
- break;
- case PVSEGS:
- type = "Physical Volume Segment";
- break;
- default:
- type = " ";
- }
-
- if (type != last_type) {
- if (*last_type)
- log_print(" ");
- log_print("%s Fields", type);
- }
-
- log_print("- %s", _fields[f].id);
+ struct volume_group *vg = ((struct lvm_report_object *)obj)->vg;
- last_type = type;
- }
+ return vg ? vg : &_dummy_vg;
}
-/*
- * Initialise report handle
- */
-static int _field_match(struct report_handle *rh, const char *field, size_t len)
+static void *_obj_get_lv(void *obj)
{
- uint32_t f, l;
- struct field_properties *fp;
-
- if (!len)
- return 0;
-
- for (f = 0; f < _num_fields; f++) {
- if ((!strncasecmp(_fields[f].id, field, len) &&
- strlen(_fields[f].id) == len) ||
- (l = strlen(rh->field_prefix),
- !strncasecmp(rh->field_prefix, _fields[f].id, l) &&
- !strncasecmp(_fields[f].id + l, field, len) &&
- strlen(_fields[f].id) == l + len)) {
- rh->type |= _fields[f].type;
- if (!(fp = dm_pool_zalloc(rh->mem, sizeof(*fp)))) {
- log_error("struct field_properties allocation "
- "failed");
- return 0;
- }
- fp->field_num = f;
- fp->width = _fields[f].width;
- fp->flags = _fields[f].flags;
-
- /* Suppress snapshot percentage if not using driver */
- if (!activation()
- && !strncmp(field, "snap_percent", len))
- fp->flags |= FLD_HIDDEN;
-
- list_add(&rh->field_props, &fp->list);
- return 1;
- }
- }
-
- return 0;
+ return ((struct lvm_report_object *)obj)->lv;
}
-static int _add_sort_key(struct report_handle *rh, uint32_t field_num,
- uint32_t flags)
+static void *_obj_get_pv(void *obj)
{
- struct field_properties *fp, *found = NULL;
-
- list_iterate_items(fp, &rh->field_props) {
- if (fp->field_num == field_num) {
- found = fp;
- break;
- }
- }
-
- if (!found) {
- /* Add as a non-display field */
- if (!(found = dm_pool_zalloc(rh->mem, sizeof(*found)))) {
- log_error("struct field_properties allocation failed");
- return 0;
- }
-
- rh->type |= _fields[field_num].type;
- found->field_num = field_num;
- found->width = _fields[field_num].width;
- found->flags = _fields[field_num].flags | FLD_HIDDEN;
-
- list_add(&rh->field_props, &found->list);
- }
-
- if (found->flags & FLD_SORT_KEY) {
- log_error("Ignoring duplicate sort field: %s",
- _fields[field_num].id);
- return 1;
- }
-
- found->flags |= FLD_SORT_KEY;
- found->sort_posn = rh->keys_count++;
- found->flags |= flags;
-
- return 1;
+ return ((struct lvm_report_object *)obj)->pv;
}
-static int _key_match(struct report_handle *rh, const char *key, size_t len)
+static void *_obj_get_seg(void *obj)
{
- uint32_t f, l;
- uint32_t flags = 0;
-
- if (!len)
- return 0;
-
- if (*key == '+') {
- key++;
- len--;
- flags = FLD_ASCENDING;
- } else if (*key == '-') {
- key++;
- len--;
- flags = FLD_DESCENDING;
- } else
- flags = FLD_ASCENDING;
-
- if (!len) {
- log_error("Missing sort field name");
- return 0;
- }
-
- for (f = 0; f < _num_fields; f++) {
- if ((!strncasecmp(_fields[f].id, key, len) &&
- strlen(_fields[f].id) == len) ||
- (l = strlen(rh->field_prefix),
- !strncasecmp(rh->field_prefix, _fields[f].id, l) &&
- !strncasecmp(_fields[f].id + l, key, len) &&
- strlen(_fields[f].id) == l + len)) {
- return _add_sort_key(rh, f, flags);
- }
- }
-
- return 0;
+ return ((struct lvm_report_object *)obj)->seg;
}
-static int _parse_options(struct report_handle *rh, const char *format)
+static void *_obj_get_pvseg(void *obj)
{
- const char *ws; /* Word start */
- const char *we = format; /* Word end */
+ return ((struct lvm_report_object *)obj)->pvseg;
+}
- while (*we) {
- /* Allow consecutive commas */
- while (*we && *we == ',')
- we++;
- ws = we;
- while (*we && *we != ',')
- we++;
- if (!_field_match(rh, ws, (size_t) (we - ws))) {
- _display_fields();
- log_print(" ");
- log_error("Unrecognised field: %.*s", (int) (we - ws),
- ws);
- return 0;
- }
- }
+static const struct dm_report_object_type _report_types[] = {
+ { VGS, "Volume Group", "vg_", _obj_get_vg },
+ { LVS, "Logical Volume", "lv_", _obj_get_lv },
+ { PVS, "Physical Volume", "pv_", _obj_get_pv },
+ { SEGS, "Logical Volume Segment", "seg_", _obj_get_seg },
+ { PVSEGS, "Physical Volume Segment", "pvseg_", _obj_get_pvseg },
+ { 0, "", "", NULL },
+};
- return 1;
-}
+/*
+ * Import column definitions
+ */
-static int _parse_keys(struct report_handle *rh, const char *keys)
-{
- const char *ws; /* Word start */
- const char *we = keys; /* Word end */
+#define STR DM_REPORT_FIELD_TYPE_STRING
+#define NUM DM_REPORT_FIELD_TYPE_NUMBER
+#define FIELD(type, strct, sorttype, head, field, width, func, id, desc) {type, sorttype, (off_t)((void *)&_dummy._ ## strct.field - (void *)&_dummy._ ## strct), width, id, head, &_ ## func ## _disp, desc},
- while (*we) {
- /* Allow consecutive commas */
- while (*we && *we == ',')
- we++;
- ws = we;
- while (*we && *we != ',')
- we++;
- if (!_key_match(rh, ws, (size_t) (we - ws))) {
- log_error("Unrecognised field: %.*s", (int) (we - ws),
- ws);
- return 0;
- }
- }
+static struct dm_report_field_type _fields[] = {
+#include "columns.h"
+{0, 0, 0, 0, "", "", NULL, NULL},
+};
- return 1;
-}
+#undef STR
+#undef NUM
+#undef FIELD
void *report_init(struct cmd_context *cmd, const char *format, const char *keys,
- report_type_t *report_type, const char *separator,
- int aligned, int buffered, int headings)
+ report_type_t *report_type, const char *separator,
+ int aligned, int buffered, int headings)
{
- struct report_handle *rh;
-
- if (!(rh = dm_pool_zalloc(cmd->mem, sizeof(*rh)))) {
- log_error("report_handle dm_pool_zalloc failed");
- return 0;
- }
-
- rh->cmd = cmd;
- rh->type = *report_type;
- rh->separator = separator;
+ uint32_t report_flags = 0;
if (aligned)
- rh->flags |= RH_ALIGNED;
+ report_flags |= DM_REPORT_OUTPUT_ALIGNED;
if (buffered)
- rh->flags |= RH_BUFFERED | RH_SORT_REQUIRED;
+ report_flags |= DM_REPORT_OUTPUT_BUFFERED;
if (headings)
- rh->flags |= RH_HEADINGS;
-
- list_init(&rh->field_props);
- list_init(&rh->rows);
-
- switch (rh->type) {
- case PVS:
- rh->field_prefix = "pv_";
- break;
- case LVS:
- rh->field_prefix = "lv_";
- break;
- case VGS:
- rh->field_prefix = "vg_";
- break;
- case SEGS:
- rh->field_prefix = "seg_";
- break;
- case PVSEGS:
- rh->field_prefix = "pvseg_";
- break;
- default:
- rh->field_prefix = "";
- }
-
- if (!(rh->mem = dm_pool_create("report", 10 * 1024))) {
- log_error("Allocation of memory pool for report failed");
- return NULL;
- }
-
- /* Generate list of fields for output based on format string & flags */
- if (!_parse_options(rh, format))
- return NULL;
-
- if (!_parse_keys(rh, keys))
- return NULL;
+ report_flags |= DM_REPORT_OUTPUT_HEADINGS;
- /* Ensure options selected are compatible */
- if (rh->type & SEGS)
- rh->type |= LVS;
- if (rh->type & PVSEGS)
- rh->type |= PVS;
- if ((rh->type & LVS) && (rh->type & PVS)) {
- log_error("Can't report LV and PV fields at the same time");
- return NULL;
- }
-
- /* Change report type if fields specified makes this necessary */
- if (rh->type & SEGS)
- *report_type = SEGS;
- else if (rh->type & LVS)
- *report_type = LVS;
- else if (rh->type & PVSEGS)
- *report_type = PVSEGS;
- else if (rh->type & PVS)
- *report_type = PVS;
-
- return rh;
-}
-
-void report_free(void *handle)
-{
- struct report_handle *rh = handle;
-
- dm_pool_destroy(rh->mem);
-
- return;
+ return dm_report_init(report_type, _report_types, _fields, format,
+ separator, report_flags, keys, cmd);
}
/*
@@ -1270,303 +905,13 @@
struct logical_volume *lv, struct physical_volume *pv,
struct lv_segment *seg, struct pv_segment *pvseg)
{
- struct report_handle *rh = handle;
- struct field_properties *fp;
- struct row *row;
- struct field *field;
- void *data = NULL;
- int skip;
-
- if (lv && pv) {
- log_error("report_object: One of *lv and *pv must be NULL!");
- return 0;
- }
-
- if (!(row = dm_pool_zalloc(rh->mem, sizeof(*row)))) {
- log_error("struct row allocation failed");
- return 0;
- }
-
- row->rh = rh;
-
- if ((rh->flags & RH_SORT_REQUIRED) &&
- !(row->sort_fields = dm_pool_zalloc(rh->mem, sizeof(struct field *) *
- rh->keys_count))) {
- log_error("row sort value structure allocation failed");
- return 0;
- }
-
- list_init(&row->fields);
- list_add(&rh->rows, &row->list);
-
- /* For each field to be displayed, call its report_fn */
- list_iterate_items(fp, &rh->field_props) {
- skip = 0;
-
- if (!(field = dm_pool_zalloc(rh->mem, sizeof(*field)))) {
- log_error("struct field allocation failed");
- return 0;
- }
- field->props = fp;
-
- switch (_fields[fp->field_num].type) {
- case LVS:
- data = (void *) lv + _fields[fp->field_num].offset;
- break;
- case VGS:
- if (!vg) {
- skip = 1;
- break;
- }
- data = (void *) vg + _fields[fp->field_num].offset;
- break;
- case PVS:
- data = (void *) pv + _fields[fp->field_num].offset;
- break;
- case SEGS:
- data = (void *) seg + _fields[fp->field_num].offset;
- break;
- case PVSEGS:
- data = (void *) pvseg + _fields[fp->field_num].offset;
- }
-
- if (skip) {
- field->report_string = "";
- field->sort_value = (const void *) field->report_string;
- } else if (!_fields[fp->field_num].report_fn(rh, field, data)) {
- log_error("report function failed for field %s",
- _fields[fp->field_num].id);
- return 0;
- }
-
- if ((strlen(field->report_string) > field->props->width))
- field->props->width = strlen(field->report_string);
-
- if ((rh->flags & RH_SORT_REQUIRED) &&
- (field->props->flags & FLD_SORT_KEY)) {
- (*row->sort_fields)[field->props->sort_posn] = field;
- }
- list_add(&row->fields, &field->list);
- }
-
- if (!(rh->flags & RH_BUFFERED))
- report_output(handle);
-
- return 1;
-}
-
-/*
- * Print row of headings
- */
-static int _report_headings(void *handle)
-{
- struct report_handle *rh = handle;
- struct field_properties *fp;
- const char *heading;
- char buf[1024];
-
- if (rh->flags & RH_HEADINGS_PRINTED)
- return 1;
-
- rh->flags |= RH_HEADINGS_PRINTED;
-
- if (!(rh->flags & RH_HEADINGS))
- return 1;
-
- if (!dm_pool_begin_object(rh->mem, 128)) {
- log_error("dm_pool_begin_object failed for headings");
- return 0;
- }
-
- /* First heading line */
- list_iterate_items(fp, &rh->field_props) {
- if (fp->flags & FLD_HIDDEN)
- continue;
-
- heading = _fields[fp->field_num].heading;
- if (rh->flags & RH_ALIGNED) {
- if (dm_snprintf(buf, sizeof(buf), "%-*.*s",
- fp->width, fp->width, heading) < 0) {
- log_error("snprintf heading failed");
- dm_pool_end_object(rh->mem);
- return 0;
- }
- if (!dm_pool_grow_object(rh->mem, buf, fp->width))
- goto bad;
- } else if (!dm_pool_grow_object(rh->mem, heading, strlen(heading)))
- goto bad;
-
- if (!list_end(&rh->field_props, &fp->list))
- if (!dm_pool_grow_object(rh->mem, rh->separator,
- strlen(rh->separator)))
- goto bad;
- }
- if (!dm_pool_grow_object(rh->mem, "\0", 1)) {
- log_error("dm_pool_grow_object failed");
- goto bad;
- }
- log_print("%s", (char *) dm_pool_end_object(rh->mem));
-
- return 1;
-
- bad:
- log_error("Failed to generate report headings for printing");
-
- return 0;
-}
-
-/*
- * Sort rows of data
- */
-static int _row_compare(const void *a, const void *b)
-{
- const struct row *rowa = *(const struct row **) a;
- const struct row *rowb = *(const struct row **) b;
- const struct field *sfa, *sfb;
- int32_t cnt = -1;
-
- for (cnt = 0; cnt < rowa->rh->keys_count; cnt++) {
- sfa = (*rowa->sort_fields)[cnt];
- sfb = (*rowb->sort_fields)[cnt];
- if (sfa->props->flags & FLD_NUMBER) {
- const uint64_t numa =
- *(const uint64_t *) sfa->sort_value;
- const uint64_t numb =
- *(const uint64_t *) sfb->sort_value;
-
- if (numa == numb)
- continue;
-
- if (sfa->props->flags & FLD_ASCENDING) {
- return (numa > numb) ? 1 : -1;
- } else { /* FLD_DESCENDING */
- return (numa < numb) ? 1 : -1;
- }
- } else { /* FLD_STRING */
- const char *stra = (const char *) sfa->sort_value;
- const char *strb = (const char *) sfb->sort_value;
- int cmp = strcmp(stra, strb);
-
- if (!cmp)
- continue;
-
- if (sfa->props->flags & FLD_ASCENDING) {
- return (cmp > 0) ? 1 : -1;
- } else { /* FLD_DESCENDING */
- return (cmp < 0) ? 1 : -1;
- }
- }
- }
-
- return 0; /* Identical */
-}
-
-static int _sort_rows(struct report_handle *rh)
-{
- struct row *(*rows)[];
- uint32_t count = 0;
- struct row *row;
-
- if (!(rows = dm_pool_alloc(rh->mem, sizeof(**rows) *
- list_size(&rh->rows)))) {
- log_error("sort array allocation failed");
- return 0;
- }
+ struct lvm_report_object obj;
- list_iterate_items(row, &rh->rows)
- (*rows)[count++] = row;
-
- qsort(rows, count, sizeof(**rows), _row_compare);
-
- list_init(&rh->rows);
- while (count--)
- list_add_h(&rh->rows, &(*rows)[count]->list);
-
- return 1;
-}
-
-/*
- * Produce report output
- */
-int report_output(void *handle)
-{
- struct report_handle *rh = handle;
- struct list *fh, *rowh, *ftmp, *rtmp;
- struct row *row = NULL;
- struct field *field;
- const char *repstr;
- char buf[4096];
- int width;
-
- if (list_empty(&rh->rows))
- return 1;
-
- /* Sort rows */
- if ((rh->flags & RH_SORT_REQUIRED))
- _sort_rows(rh);
-
- /* If headings not printed yet, calculate field widths and print them */
- if (!(rh->flags & RH_HEADINGS_PRINTED))
- _report_headings(rh);
-
- /* Print and clear buffer */
- list_iterate_safe(rowh, rtmp, &rh->rows) {
- if (!dm_pool_begin_object(rh->mem, 512)) {
- log_error("dm_pool_begin_object failed for row");
- return 0;
- }
- row = list_item(rowh, struct row);
- list_iterate_safe(fh, ftmp, &row->fields) {
- field = list_item(fh, struct field);
- if (field->props->flags & FLD_HIDDEN)
- continue;
-
- repstr = field->report_string;
- width = field->props->width;
- if (!(rh->flags & RH_ALIGNED)) {
- if (!dm_pool_grow_object(rh->mem, repstr,
- strlen(repstr)))
- goto bad;
- } else if (field->props->flags & FLD_ALIGN_LEFT) {
- if (dm_snprintf(buf, sizeof(buf), "%-*.*s",
- width, width, repstr) < 0) {
- log_error("snprintf repstr failed");
- dm_pool_end_object(rh->mem);
- return 0;
- }
- if (!dm_pool_grow_object(rh->mem, buf, width))
- goto bad;
- } else if (field->props->flags & FLD_ALIGN_RIGHT) {
- if (dm_snprintf(buf, sizeof(buf), "%*.*s",
- width, width, repstr) < 0) {
- log_error("snprintf repstr failed");
- dm_pool_end_object(rh->mem);
- return 0;
- }
- if (!dm_pool_grow_object(rh->mem, buf, width))
- goto bad;
- }
-
- if (!list_end(&row->fields, fh))
- if (!dm_pool_grow_object(rh->mem, rh->separator,
- strlen(rh->separator)))
- goto bad;
- list_del(&field->list);
- }
- if (!dm_pool_grow_object(rh->mem, "\0", 1)) {
- log_error("dm_pool_grow_object failed for row");
- return 0;
- }
- log_print("%s", (char *) dm_pool_end_object(rh->mem));
- list_del(&row->list);
- }
-
- if (row)
- dm_pool_free(rh->mem, row);
-
- return 1;
+ obj.vg = vg;
+ obj.lv = lv;
+ obj.pv = pv;
+ obj.seg = seg;
+ obj.pvseg = pvseg;
- bad:
- log_error("Failed to generate row for printing");
- return 0;
+ return dm_report_object(handle, &obj);
}
Modified: lvm2/trunk/lib/snapshot/snapshot.c
==============================================================================
--- lvm2/trunk/lib/snapshot/snapshot.c (original)
+++ lvm2/trunk/lib/snapshot/snapshot.c Sat Apr 7 16:07:03 2007
@@ -112,7 +112,7 @@
return 1;
}
-static int _snap_target_present(void)
+static int _snap_target_present(const struct lv_segment *seg __attribute((unused)))
{
static int _snap_checked = 0;
static int _snap_present = 0;
Modified: lvm2/trunk/lib/striped/striped.c
==============================================================================
--- lvm2/trunk/lib/striped/striped.c (original)
+++ lvm2/trunk/lib/striped/striped.c Sat Apr 7 16:07:03 2007
@@ -174,7 +174,7 @@
return add_areas_line(dm, seg, node, 0u, seg->area_count);
}
-static int _striped_target_present(void)
+static int _striped_target_present(const struct lv_segment *seg __attribute((unused)))
{
static int _striped_checked = 0;
static int _striped_present = 0;
Modified: lvm2/trunk/lib/zero/zero.c
==============================================================================
--- lvm2/trunk/lib/zero/zero.c (original)
+++ lvm2/trunk/lib/zero/zero.c Sat Apr 7 16:07:03 2007
@@ -49,7 +49,7 @@
return dm_tree_node_add_zero_target(node, len);
}
-static int _zero_target_present(void)
+static int _zero_target_present(const struct lv_segment *seg __attribute((unused)))
{
static int _zero_checked = 0;
static int _zero_present = 0;
Modified: lvm2/trunk/make.tmpl.in
==============================================================================
--- lvm2/trunk/make.tmpl.in (original)
+++ lvm2/trunk/make.tmpl.in Sat Apr 7 16:07:03 2007
@@ -73,6 +73,13 @@
DEFS += -DINTL_PACKAGE=\"@INTL_PACKAGE@\" -DLOCALEDIR=\"@LOCALEDIR@\"
endif
+ifneq ("@DMDIR@", "")
+ LDFLAGS += -L at DMDIR@/lib/ioctl
+ ifeq ("@DMEVENTD@", "yes")
+ LDFLAGS += -L at DMDIR@/dmeventd
+ endif
+endif
+
LDFLAGS += -L$(top_srcdir)/lib -L$(libdir)
#DEFS += -DDEBUG_POOL
@@ -89,6 +96,10 @@
INCLUDES += -I. -I$(top_srcdir)/include
+ifneq ("@DMDIR@", "")
+ INCLUDES += -I at DMDIR@/include
+endif
+
ifdef DESTDIR
INCLUDES += -I$(DESTDIR)/usr/include
endif
@@ -162,18 +173,19 @@
ifeq ("@LIB_SUFFIX@","so")
$(LIB_SHARED): $(OBJECTS) $(LDDEPS)
$(CC) -shared -Wl,-soname,$(notdir $@).$(LIB_VERSION) \
- $(CLDFLAGS) $(OBJECTS) $(LIBS) -o $@
+ $(CFLAGS) $(CLDFLAGS) $(OBJECTS) $(LIBS) -o $@
endif
ifeq ("@LIB_SUFFIX@","dylib")
$(LIB_SHARED): $(OBJECTS) $(LDDEPS)
$(CC) -dynamiclib -dylib_current_version,$(LIB_VERSION) \
- $(CLDFLAGS) $(OBJECTS) $(LIBS) -o $@
+ $(CFLAGS) $(CLDFLAGS) $(OBJECTS) $(LIBS) -o $@
endif
%.so: %.a
$(CC) -shared -Wl,-soname,$(notdir $@).$(LIB_VERSION) \
- $(CLDFLAGS) $(LIBS) -o $@ @CLDWHOLEARCHIVE@ $< @CLDNOWHOLEARCHIVE@
+ $(CFLAGS) $(CLDFLAGS) $(LIBS) -o $@ \
+ @CLDWHOLEARCHIVE@ $< @CLDNOWHOLEARCHIVE@
$(LIB_STATIC): $(OBJECTS)
$(RM) $@
Modified: lvm2/trunk/man/Makefile.in
==============================================================================
--- lvm2/trunk/man/Makefile.in (original)
+++ lvm2/trunk/man/Makefile.in Sat Apr 7 16:07:03 2007
@@ -18,8 +18,8 @@
MAN5=lvm.conf.5
MAN8=lvchange.8 lvconvert.8 lvcreate.8 lvdisplay.8 lvextend.8 lvm.8 \
- lvmchange.8 \
- lvmdiskscan.8 lvreduce.8 lvremove.8 lvrename.8 lvresize.8 lvs.8 \
+ lvmchange.8 lvmdiskscan.8 lvmdump.8 \
+ lvreduce.8 lvremove.8 lvrename.8 lvresize.8 lvs.8 \
lvscan.8 pvchange.8 pvcreate.8 pvdisplay.8 pvmove.8 pvremove.8 \
pvresize.8 pvs.8 pvscan.8 vgcfgbackup.8 vgcfgrestore.8 vgchange.8 \
vgck.8 vgcreate.8 vgconvert.8 vgdisplay.8 vgexport.8 vgextend.8 \
Modified: lvm2/trunk/man/clvmd.8
==============================================================================
--- lvm2/trunk/man/clvmd.8 (original)
+++ lvm2/trunk/man/clvmd.8 Sat Apr 7 16:07:03 2007
@@ -6,6 +6,7 @@
[\-d] [\-h]
[\-R]
[\-t <timeout>]
+[\-T <start timeout>]
[\-V]
.SH DESCRIPTION
clvmd is the daemon that distributes LVM metadata updates around a cluster.
@@ -23,6 +24,23 @@
may need to increase this on systems with very large disk farms.
The default is 30 seconds.
.TP
+.I \-T <start timeout>
+Specifies the timeout for clvmd daemon startup. If the daemon does not report
+that it has started up within this time then the parent command will exit with
+status of 5. This does NOT mean that clvmd has not started! What it means is
+that the startup of clvmd has been delayed for some reason; the most likely
+cause of this is an inquorate cluster though it could be due to locking
+latencies on a cluster with large numbers of logical volumes. If you get the
+return code of 5 it is usually not necessary to restart clvmd - it will start
+as soon as that blockage has cleared. This flag is to allow startup scripts
+to exit in a timely fashion even if the cluster is stalled for some reason.
+<br>
+The default is 0 (no timeout) and the value is in seconds. Don't set this too
+small or you will experience spurious errors. 10 or 20 seconds might be
+sensible.
+<br>
+This timeout will be ignored if you start clvmd with the -d switch.
+.TP
.I \-R
Tells all the running clvmd in the cluster to reload their device cache and
re-read the lvm configuration file. This command should be run whenever the
Modified: lvm2/trunk/man/lvchange.8
==============================================================================
--- lvm2/trunk/man/lvchange.8 (original)
+++ lvm2/trunk/man/lvchange.8 Sat Apr 7 16:07:03 2007
@@ -7,11 +7,12 @@
[\-A/\-\-autobackup y/n] [\-a/\-\-available y/n/ey/en/ly/ln]
[\-\-alloc AllocationPolicy]
[\-C/\-\-contiguous y/n] [\-d/\-\-debug] [\-\-deltag Tag]
+[\-\-resync]
[\-h/\-?/\-\-help]
[\-\-ignorelockingfailure]
[\-\-monitor {y|n}]
[\-M/\-\-persistent y/n] [\-\-minor minor]
-[\-P/\-\-partial y/n]
+[\-P/\-\-partial]
[\-p/\-\-permission r/w] [\-r/\-\-readahead ReadAheadSectors]
[\-\-refresh]
[\-t/\-\-test]
@@ -40,6 +41,14 @@
logical volume's allocation policy to contiguous, if all of the
allocated physical extents are already contiguous.
.TP
+.I \-\-resync
+Forces the complete resynchronization of a mirror. In normal
+circumstances you should not need this option because synchronization
+happens automatically. Data is read from the primary mirror device
+and copied to the others, so this can take a considerable amount of
+time - and during this time you are without a complete redundant copy
+of your data.
+.TP
.I \-\-minor minor
Set the minor number.
.TP
Modified: lvm2/trunk/man/lvconvert.8
==============================================================================
--- lvm2/trunk/man/lvconvert.8 (original)
+++ lvm2/trunk/man/lvconvert.8 Sat Apr 7 16:07:03 2007
@@ -1,20 +1,35 @@
.TH LVCONVERT 8 "LVM TOOLS" "Red Hat, Inc" \" -*- nroff -*-
.SH NAME
-lvconvert \- convert a logical volume between linear and mirror
+lvconvert \- convert a logical volume from linear to mirror or snapshot
.SH SYNOPSIS
.B lvconvert
-[\-m/\-\-mirrors Mirrors [\-\-corelog] [\-R/\-\-regionsize MirrorLogRegionSize]]
+\-m/\-\-mirrors Mirrors [\-\-corelog] [\-R/\-\-regionsize MirrorLogRegionSize]
[\-A/\-\-alloc AllocationPolicy]
[\-h/\-?/\-\-help]
[\-v/\-\-verbose]
[\-\-version]
+.br
LogicalVolume[Path] [PhysicalVolume[Path]...]
+.br
+
+.br
+.B lvconvert
+\-s/\-\-snapshot [\-c/\-\-chunksize ChunkSize]
+[\-h/\-?/\-\-help]
+[\-v/\-\-verbose]
+[\-Z/\-\-zero y/n]
+[\-\-version]
+.br
+OriginalLogicalVolume[Path] SnapshotLogicalVolume[Path]
.SH DESCRIPTION
lvconvert will change a linear logical volume to a mirror
-logical volume or vis versa. It is also used to add and
-remove disk logs from mirror devices.
+logical volume or to a snapshot of linear volume and vice versa.
+It is also used to add and remove disk logs from mirror devices.
.SH OPTIONS
See \fBlvm\fP for common options.
+.br
+Exactly one of \-\-mirrors or \-\-snapshot arguments required.
+.br
.TP
.I \-m, \-\-mirrors Mirrors
Specifies the degree of the mirror you wish to create.
@@ -32,6 +47,19 @@
.I \-R, \-\-regionsize MirrorLogRegionSize
A mirror is divided into regions of this size (in MB), and the mirror log
uses this granularity to track which regions are in sync.
+.br
+.TP
+.I \-s, \-\-snapshot
+Create a snapshot from existing logical volume using another
+existing logical volume as its origin.
+.TP
+.I \-c, \-\-chunksize ChunkSize
+Power of 2 chunk size for the snapshot logical volume between 4k and 512k.
+.TP
+.I \-Z, \-\-zero y/n
+Controls zeroing of the first KB of data in the snapshot.
+If the volume is read-only the snapshot will not be zeroed.
+.br
.SH Examples
"lvconvert -m1 vg00/lvol1"
.br
@@ -49,6 +77,12 @@
.br
converts a mirror logical volume to a linear logical
volume.
+.br
+
+.br
+"lvconvert -s vg00/lvol1 vg00/lvol2"
+.br
+converts logical volume "vg00/lvol2" to snapshot of original volume "vg00/lvol1"
.SH SEE ALSO
.BR lvm (8),
Modified: lvm2/trunk/man/lvcreate.8
==============================================================================
--- lvm2/trunk/man/lvcreate.8 (original)
+++ lvm2/trunk/man/lvcreate.8 Sat Apr 7 16:07:03 2007
@@ -70,10 +70,11 @@
in the Volume Group with the suffix %VG or of the remaining free space
with the suffix %FREE.
.TP
-.I \-L, \-\-size LogicalVolumeSize[kKmMgGtT]
+.I \-L, \-\-size LogicalVolumeSize[kKmMgGtTpPeE]
Gives the size to allocate for the new logical volume.
A size suffix of K for kilobytes, M for megabytes,
-G for gigabytes or T for terabytes is optional.
+G for gigabytes, T for terabytes, P for petabytes
+or E for exabytes is optional.
.br
Default unit is megabytes.
.TP
@@ -138,6 +139,10 @@
Controls zeroing of the first KB of data in the new logical volume.
.br
Default is yes.
+.br
+Volume will not be zeroed if read only flag is set.
+.br
+Snapshot volumes are zeroed always.
.br
Warning: trying to mount an unzeroed logical volume can cause the system to
Modified: lvm2/trunk/man/lvextend.8
==============================================================================
--- lvm2/trunk/man/lvextend.8 (original)
+++ lvm2/trunk/man/lvextend.8 Sat Apr 7 16:07:03 2007
@@ -30,10 +30,12 @@
size of the Logical Volume with the suffix %LV or as a percentage of the remaining
free space in the Volume Group with the suffix %FREE.
.TP
-.I \-L, \-\-size [+]LogicalVolumeSize[kKmMgGtT]
-Extend or set the logical volume size in units in units of megabytes.
-A size suffix of M for megabytes, G for gigabytes or T for terabytes is
-optional. With the + sign the value is added to the actual size
+.I \-L, \-\-size [+]LogicalVolumeSize[kKmMgGtTpPeE]
+Extend or set the logical volume size in units of megabytes.
+A size suffix of M for megabytes,
+G for gigabytes, T for terabytes, P for petabytes
+or E for exabytes is optional.
+With the + sign the value is added to the actual size
of the logical volume and without it, the value is taken as an absolute one.
.TP
.I \-i, \-\-stripes Stripes
Modified: lvm2/trunk/man/lvm.conf.5
==============================================================================
--- lvm2/trunk/man/lvm.conf.5 (original)
+++ lvm2/trunk/man/lvm.conf.5 Sat Apr 7 16:07:03 2007
@@ -95,8 +95,8 @@
As an example, to ignore /dev/cdrom you could use:
\fBdevices { filter=["r|cdrom|"] }\fP
.IP
-\fBcache\fP \(em Persistent filter cache file.
-Defaults to "/etc/lvm/.cache".
+\fBcache_dir\fP \(em Persistent filter cache file directory.
+Defaults to "/etc/lvm/cache".
.IP
\fBwrite_cache_state\fP \(em Set to 0 to disable the writing out of the
persistent filter cache file when \fBlvm\fP exits.
@@ -364,9 +364,9 @@
the tools as normal, or else vgcfgbackup, edit backup, vgcfgrestore.
.SH FILES
.I /etc/lvm/lvm.conf
-.I /etc/lvm/.cache
.I /etc/lvm/archive
.I /etc/lvm/backup
+.I /etc/lvm/cache/.cache
.I /var/lock/lvm
.SH SEE ALSO
.BR lvm (8),
Added: lvm2/trunk/man/lvmdump.8
==============================================================================
--- (empty file)
+++ lvm2/trunk/man/lvmdump.8 Sat Apr 7 16:07:03 2007
@@ -0,0 +1,50 @@
+.TH LVMDUMP "8" "" "Red Hat, Inc."
+.SH NAME
+lvmdump - create lvm2 information dumps for diagnostic purposes
+.SH SYNOPSIS
+\fBlvmdump\fP [options] [-d directory]
+.SH DESCRIPTION
+\fBlvmdump\fP is a tool to dump various information concerning LVM2. By default, it creates a tarball suitable for submission along with a problem report.
+.PP
+The content of the tarball is as follows:
+.br
+- dmsetup info
+.br
+- table of currently running processes
+.br
+- recent entries from /var/log/messages (containing system messages)
+.br
+- complete lvm configuration and cache
+.br
+- list of device nodes present under /dev
+.br
+- if enabled with -m, metadata dump will be also included
+.br
+- if enabled with -a, debug output of vgscan, pvscan and list of all available volume groups, physical volumes and logical volumes will be included
+.br
+- if enabled with -c, cluster status info
+.SH OPTIONS
+.TP
+\fB\-h\fR \(em print help message
+.TP
+\fB\-a\fR \(em advanced collection
+\fBWARNING\fR: if lvm is already hung, then this script may hang as well if \fB\-a\fR is used
+.TP
+\fB\-m\fR \(em gather LVM metadata from the PVs
+This option generates a 1:1 dump of the metadata area from all PVs visible to the system, which can cause the dump to increase in size considerably. However, the metadata dump may represent a valuable diagnostic resource.
+.TP
+\fB\-d\fR directory \(em dump into a directory instead of tarball
+By default, lvmdump will produce a single compressed tarball containing all the information. Using this option, it can be instructed to only produce the raw dump tree, rooted in \fBdirectory\fP.
+.TP
+\fB\-c\fR \(em if clvmd is running, gather cluster data as well
+.SH ENVIRONMENT VARIABLES
+.TP
+\fBLVM_BINARY\fP
+The LVM2 binary to use.
+Defaults to "lvm".
+Sometimes you might need to set this to "/sbin/lvm.static", for example.
+.TP
+\fBDMSETUP_BINARY\fP
+The dmsetup binary to use.
+Defaults to "dmsetup".
+.PP
Modified: lvm2/trunk/man/lvreduce.8
==============================================================================
--- lvm2/trunk/man/lvreduce.8 (original)
+++ lvm2/trunk/man/lvreduce.8 Sat Apr 7 16:07:03 2007
@@ -46,10 +46,11 @@
size of the Logical Volume with the suffix %LV or as a percentage of the remaining
free space in the Volume Group with the suffix %FREE.
.TP
-.I \-L, \-\-size [\-]LogicalVolumeSize[kKmMgGtT]
+.I \-L, \-\-size [\-]LogicalVolumeSize[kKmMgGtTpPeE]
Reduce or set the logical volume size in units of megabyte by default.
-A size suffix of k for kilobyte, m for megabyte, g for gigabyte or
-t for terabyte is optional.
+A size suffix of k for kilobyte, m for megabyte,
+g for gigabytes, t for terabytes, p for petabytes
+or e for exabytes is optional.
With the - sign the value will be subtracted from
the logical volume's actual size and without it it will be taken as
an absolute size.
Modified: lvm2/trunk/man/lvremove.8
==============================================================================
--- lvm2/trunk/man/lvremove.8 (original)
+++ lvm2/trunk/man/lvremove.8 Sat Apr 7 16:07:03 2007
@@ -12,6 +12,10 @@
Confirmation will be requested before deactivating any active logical
volume prior to removal. Logical volumes cannot be deactivated
or removed while they are open (e.g. if they contain a mounted filesystem).
+.sp
+If the logical volume is clustered then it must be deactivated on all
+nodes in the cluster before it can be removed. A single lvchange command
+issued from one node can do this.
.SH OPTIONS
See \fBlvm\fP(8) for common options.
.TP
@@ -28,7 +32,8 @@
\ \fBlvremove vg00\fP
.SH SEE ALSO
.BR lvcreate (8),
-.BR lvdisplay (8),
+.BR lvdisplay (8),
+.BR lvchange (8),
.BR lvm (8),
.BR lvs (8),
.BR lvscan (8),
Modified: lvm2/trunk/man/lvresize.8
==============================================================================
--- lvm2/trunk/man/lvresize.8 (original)
+++ lvm2/trunk/man/lvresize.8 Sat Apr 7 16:07:03 2007
@@ -34,10 +34,12 @@
size of the Logical Volume with the suffix %LV or as a percentage of the remaining
free space in the Volume Group with the suffix %FREE.
.TP
-.I \-L, \-\-size [+/-]LogicalVolumeSize[kKmMgGtT]
+.I \-L, \-\-size [+/-]LogicalVolumeSize[kKmMgGtTpPeE]
Change or set the logical volume size in units of megabytes.
-A size suffix of M for megabytes, G for gigabytes or T for terabytes is
-optional. With the + or - sign the value is added to or subtracted from
+A size suffix of M for megabytes,
+G for gigabytes, T for terabytes, P for petabytes
+or E for exabytes is optional.
+With the + or - sign the value is added to or subtracted from
the actual size of the logical volume and without it, the value is taken as an
absolute one.
.TP
Modified: lvm2/trunk/man/lvs.8
==============================================================================
--- lvm2/trunk/man/lvs.8 (original)
+++ lvm2/trunk/man/lvs.8 Sat Apr 7 16:07:03 2007
@@ -35,11 +35,13 @@
lv_size, seg_count, origin, snap_percent,
copy_percent, move_pv, lv_tags,
segtype, stripes,
-stripesize, chunksize, seg_start, seg_size, seg_tags, devices.
+stripesize, chunksize, seg_start, seg_size, seg_tags, devices,
+regionsize, mirror_log, modules.
.IP
With \-\-segments, any "seg_" prefixes are optional; otherwise any "lv_"
prefixes are optional. Columns mentioned in \fBvgs (8)\fP
can also be chosen.
+Use \fb-o help\fP to view the full list of fields available.
.IP
The lv_attr bits are:
.RS
Modified: lvm2/trunk/man/pvmove.8
==============================================================================
--- lvm2/trunk/man/pvmove.8 (original)
+++ lvm2/trunk/man/pvmove.8 Sat Apr 7 16:07:03 2007
@@ -5,7 +5,7 @@
.B pvmove
[\-\-abort]
[\-\-alloc AllocationPolicy]
-[\-\-background]
+[\-b/\-\-background]
[\-d/\-\-debug] [\-h/\-\-help] [\-i/\-\-interval Seconds] [\-v/\-\-verbose]
[\-n/\-\-name LogicalVolume]
[SourcePhysicalVolume[:PE[-PE]...] [DestinationPhysicalVolume[:PE[-PE]...]...]]
@@ -73,7 +73,7 @@
.I \-\-abort
Abort any moves in progress.
.TP
-.I \-\-background
+.I \-b, \-\-background
Run the daemon in the background.
.TP
.I \-i, \-\-interval Seconds
Modified: lvm2/trunk/man/pvs.8
==============================================================================
--- lvm2/trunk/man/pvs.8 (original)
+++ lvm2/trunk/man/pvs.8 Sat Apr 7 16:07:03 2007
@@ -31,9 +31,16 @@
Comma-separated ordered list of columns. Precede the list with '+' to append
to the default selection of columns. Column names are: pv_fmt, pv_uuid,
pv_size, dev_size, pv_free, pv_used, pv_name, pv_attr, pv_pe_count,
-pv_pe_alloc_count, pv_tags.
-The "pv_" prefix is optional. Columns mentioned in \fBvgs (8)\fP can also
+pv_pe_alloc_count, pv_tags, pvseg_start, pvseg_size, pe_start.
+With --segments, any "pvseg_" prefixes are optional; otherwise any
+"pv_" prefixes are optional. Columns mentioned in \fBvgs (8)\fP can also
be chosen. The pv_attr bits are: (a)llocatable and e(x)ported.
+Use \fb-o help\fP to view the full list of fields available.
+.TP
+.I \-\-segments
+Produces one line of output for each contiguous allocation of space on each
+Physical Volume, showing the start (pvseg_start) and length (pvseg_size) in
+units of physical extents.
.TP
.I \-O, \-\-sort
Comma-separated ordered list of columns to sort by. Replaces the default
Modified: lvm2/trunk/man/vgchange.8
==============================================================================
--- lvm2/trunk/man/vgchange.8 (original)
+++ lvm2/trunk/man/vgchange.8 Sat Apr 7 16:07:03 2007
@@ -10,6 +10,7 @@
.RB [ \-A | \-\-autobackup " {" y | n }]
.RB [ \-a | \-\-available " [e|l] {" y | n }]
.RB [ \-\-monitor " {" y | n }]
+.RB [ \-c | \-\-clustered " {" y | n }]
.RB [ \-d | \-\-debug]
.RB [ \-\-deltag
.IR Tag ]
@@ -44,12 +45,12 @@
.SH OPTIONS
See \fBlvm\fP for common options.
.TP
-.BR \-A ", " \-\-autobackup { y | n }
+.BR \-A ", " \-\-autobackup " " { y | n }
Controls automatic backup of metadata after the change. See
.B vgcfgbackup (8).
Default is yes.
.TP
-.BR \-a ", " \-\-available [e|l] { y | n }
+.BR \-a ", " \-\-available " " [e|l] { y | n }
Controls the availability of the logical volumes in the volume
group for input/output.
In other words, makes the logical volumes known/unknown to the kernel.
@@ -60,6 +61,14 @@
Logical volumes with single-host snapshots are always activated
exclusively because they can only be used on one node at once.
.TP
+.BR \-c ", " \-\-clustered " " { y | n }
+If clustered locking is enabled, this indicates whether this
+Volume Group is shared with other nodes in the cluster or whether
+it contains only local disks that are not visible on the other nodes.
+If the cluster infrastructure is unavailable on a particular node at a
+particular time, you may still be able to use Volume Groups that
+are not marked as clustered.
+.TP
.BR \-\-monitor " " { y | n }
Controls whether or not a mirrored logical volume is monitored by
dmeventd, if it is installed.
@@ -108,7 +117,7 @@
The 2.4 kernel has a limitation of 2TB per block device.
.TP
-.BR \-x ", " \-\-resizeable { y | n }
+.BR \-x ", " \-\-resizeable " " { y | n }
Enables or disables the extension/reduction of this volume group
with/by physical volumes.
.SH EXAMPLES
Modified: lvm2/trunk/man/vgcreate.8
==============================================================================
--- lvm2/trunk/man/vgcreate.8 (original)
+++ lvm2/trunk/man/vgcreate.8 Sat Apr 7 16:07:03 2007
@@ -8,6 +8,7 @@
.RB [ \-\-alloc
.IR AllocationPolicy ]
.RB [ \-A | \-\-autobackup " {" y | n }]
+.RB [ \-c | \-\-clustered " {" y | n }]
.RB [ \-d | \-\-debug ]
.RB [ \-h | \-\-help ]
.RB [ \-l | \-\-maxlogicalvolumes
@@ -33,6 +34,14 @@
.SH OPTIONS
See \fBlvm\fP for common options.
.TP
+.BR \-c ", " \-\-clustered " " { y | n }
+If clustered locking is enabled, this indicates whether this
+Volume Group is shared with other nodes in the cluster or whether
+it contains only local disks that are not visible on the other nodes.
+If the cluster infrastructure is unavailable on a particular node at a
+particular time, you may still be able to use Volume Groups that
+are not marked as clustered.
+.TP
.BR \-l ", " \-\-maxlogicalvolumes " " \fIMaxLogicalVolumes\fR
Sets the maximum number of logical volumes allowed in this
volume group.
Modified: lvm2/trunk/man/vgs.8
==============================================================================
--- lvm2/trunk/man/vgs.8 (original)
+++ lvm2/trunk/man/vgs.8 Sat Apr 7 16:07:03 2007
@@ -38,6 +38,7 @@
or \fBlvs (8)\fP can also be chosen, but columns cannot be taken from both
at the same time. The vg_attr bits are: (w)riteable, (r)eadonly,
resi(z)eable, e(x)ported, (p)artial and (c)lustered.
+Use \fb-o help\fP to view the full list of fields available.
.TP
.I \-O, \-\-sort
Comma-separated ordered list of columns to sort by. Replaces the default
Modified: lvm2/trunk/scripts/clvmd_init_rhel4
==============================================================================
--- lvm2/trunk/scripts/clvmd_init_rhel4 (original)
+++ lvm2/trunk/scripts/clvmd_init_rhel4 Sat Apr 7 16:07:03 2007
@@ -1,6 +1,6 @@
#!/bin/bash
#
-# chkconfig: 345 24 76
+# chkconfig: - 24 76
# description: Starts and stops clvmd
#
#
@@ -15,6 +15,7 @@
VGSCAN="/usr/sbin/vgscan"
VGDISPLAY="/usr/sbin/vgdisplay"
VGS="/usr/sbin/vgs"
+CLVMDOPTS="-T20"
[ -f /etc/sysconfig/cluster ] && . /etc/sysconfig/cluster
@@ -27,7 +28,7 @@
if ! pidof clvmd > /dev/null
then
echo -n "Starting clvmd: "
- daemon clvmd
+ daemon clvmd $CLVMDOPTS
rtrn=$?
echo
if [ $rtrn -ne 0 ]
@@ -42,16 +43,10 @@
then
for vg in $LVM_VGS
do
- if ! action "Activating VG $vg:" $VGCHANGE -ayl $vg
- then
- rtrn=$?
- fi
+ action "Activating VG $vg:" $VGCHANGE -ayl $vg || rtrn=$?
done
else
- if ! action "Activating VGs:" $VGCHANGE -ayl
- then
- rtrn=$?
- fi
+ action "Activating VGs:" $VGCHANGE -ayl || rtrn=$?
fi
done
@@ -66,19 +61,13 @@
then
for vg in $LVM_VGS
do
- if ! action "Deactivating VG $vg:" $VGCHANGE -anl $vg
- then
- rtrn=$?
- fi
+ action "Deactivating VG $vg:" $VGCHANGE -anl $vg || rtrn=$?
done
else
# Hack to only deactivate clustered volumes
- clustervgs=`$VGDISPLAY \`$VGS --noheadings -o name\` | awk 'BEGIN {RS="VG Name"} {if (/Clustered/) print $1;}'`
+ clustervgs=`$VGDISPLAY 2> /dev/null | awk 'BEGIN {RS="VG Name"} {if (/Clustered/) print $1;}'`
for vg in $clustervgs; do
- if ! action "Deactivating VG $vg:" $VGCHANGE -anl $vg
- then
- rtrn=$?
- fi
+ action "Deactivating VG $vg:" $VGCHANGE -anl $vg || rtrn=$?
done
fi
Modified: lvm2/trunk/scripts/lvm2create_initrd/lvm2create_initrd
==============================================================================
--- lvm2/trunk/scripts/lvm2create_initrd/lvm2create_initrd (original)
+++ lvm2/trunk/scripts/lvm2create_initrd/lvm2create_initrd Sat Apr 7 16:07:03 2007
@@ -29,6 +29,8 @@
# PATH entries to /sbin/init shell script so chroot works without /usr mounted. Remove
# mkdir /initrd so we don't cause problems if root filesystem is corrupted. -- Jeff Layton
# 15/05/2004 initial support for modules, create lvm.conf from lvm dumpconfig, other cleanups -- Jeff Layton
+# 14/11/2006 Update handling of ldd output to handle hardcoded library links and virtual dll linux-gate.
+# Add support for Gentoo-style MAKEDEV. Remove hardcoded BINUTILS paths -- Douglas Mayle
#
# Copyright Miguel Cabeca, Jeffrey Layton, 2004
#
@@ -46,13 +48,13 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
-# $Id: lvm2create_initrd,v 1.1 2004/06/07 16:20:05 agk Exp $
+# $Id: lvm2create_initrd,v 1.2 2006/11/21 22:41:56 agk Exp $
TMPMNT=/tmp/mnt.$$
DEVRAM=/tmp/initrd.$$
# set defaults
-BINFILES=${BINFILES:-"/lib/lvm-200/lvm /bin/bash /bin/busybox /sbin/pivot_root"}
+BINFILES=${BINFILES:-"`which lvm` `which bash` `which busybox` `which pivot_root`"}
BASICDEVICES=${BASICDEVICES:-"std consoleonly fd"}
BLOCKDEVICES=${BLOCKDEVICES:-"md hda hdb hdc hdd sda sdb sdc sdd"}
MAKEDEV=${MAKEDEV:-"debian"}
@@ -269,7 +271,27 @@
# Figure out which shared libraries we actually need in our initrd
echo "$cmd -- finding required shared libraries"
verbose "BINFILES: `echo $BINFILES`"
-LIBFILES=`ldd $BINFILES 2>/dev/null | awk '{if (/=>/) { print $3 }}' | sort -u`
+
+# We need to strip certain lines from ldd output. This is the full output of an example ldd:
+#lvmhost~ # ldd /sbin/lvm /bin/bash
+#/sbin/lvm:
+# not a dynamic executable
+#/bin/bash:
+# linux-gate.so.1 => (0xbfffe000)
+# libncurses.so.5 => /lib/libncurses.so.5 (0xb7ee3000)
+# libdl.so.2 => /lib/libdl.so.2 (0xb7edf000)
+# libc.so.6 => /lib/libc.so.6 (0xb7dc1000)
+# /lib/ld-linux.so.2 (0xb7f28000)
+#
+# 1) Lines with a ":" contain the name of the original binary we're examining, and so are unnecessary.
+# We need to strip them because they contain "/", and can be confused with links with a hardcoded path.
+# 2) The linux-gate library is a virtual dll that does not exist on disk, but is instead loaded automatically
+# into the process space, and can't be copied to the ramdisk
+#
+# After these lines have been stripped, we're interested in the lines remaining if they
+# 1) Contain "=>" because they are pathless links, and the value following the token is the path on the disk
+# 2) Contain "/" because it's a link with a hardcoded path, and so we're interested in the link itself.
+LIBFILES=`ldd $BINFILES 2>/dev/null |grep -v -E \(linux-gate\|:\) | awk '{if (/=>/) { print $3 } else if (/\//) { print $1 }}' | sort -u`
if [ $? -ne 0 ]; then
echo "$cmd -- ERROR figuring out needed shared libraries"
exit 1
@@ -356,6 +378,10 @@
(cd $TMPMNT/dev; /dev/MAKEDEV $OPT_Q -d $TMPMNT/dev -m 2)
RETCODE=$?
;;
+gentoo)
+ (cd $TMPMNT/dev; /usr/sbin/MAKEDEV $OPT_Q $BASICDEVICES $BLOCKDEVICES)
+ RETCODE=$?
+ ;;
*)
echo "$cmd -- ERROR: $MAKEDEV is not a known MAKEDEV style."
RETCODE=1
Modified: lvm2/trunk/scripts/lvm_dump.sh
==============================================================================
--- lvm2/trunk/scripts/lvm_dump.sh (original)
+++ lvm2/trunk/scripts/lvm_dump.sh Sat Apr 7 16:07:03 2007
@@ -1,8 +1,41 @@
#!/bin/bash
-#
+# we use some bash-isms (getopts?)
+
# lvm_dump: This script is used to collect pertinent information for
# the debugging of lvm issues.
-#
+
+# following external commands are used throughout the script
+# which, echo and test are internal in bash at least
+MKDIR=mkdir # need -p
+TAR=tar # need czf
+RM=rm # need -rf
+CP=cp
+TAIL=tail # we need -n
+LS=ls # need -la
+PS=ps # need alx
+SED=sed
+DD=dd
+CUT=cut
+DATE=date
+BASENAME=basename
+
+# user may override lvm and dmsetup location by setting LVM_BINARY
+# and DMSETUP_BINARY respectively
+LVM=${LVM_BINARY-lvm}
+DMSETUP=${DMSETUP_BINARY-dmsetup}
+
+die() {
+ code=$1; shift
+ echo "$@" 1>&2
+ exit $code
+}
+
+# which should error out if the binary is not executable, although i
+# am not sure we can rely on this
+which $LVM >& /dev/null || die 2 "Fatal: could not find lvm binary '$LVM'"
+test -x `which $LVM` || die 2 "Fatal: lvm binary '$LVM' not executable"
+which $DMSETUP >& /dev/null || die 2 "Fatal: could not find dmsetup binary '$DMSETUP'"
+test -x `which $DMSETUP` || die 2 "Fatal: dmsetup binary '$DMSETUP' not executable"
function usage {
echo "$0 [options]"
@@ -10,7 +43,7 @@
echo " -a advanced collection - warning: if lvm is already hung,"
echo " then this script may hang as well if -a is used"
echo " -m gather LVM metadata from the PVs"
- echo " -d dump directory to place data in (default=/tmp/lvm_dump.\$\$)"
+ echo " -d <directory> dump into a directory instead of tarball"
echo " -c if running clvmd, gather cluster data as well"
echo ""
@@ -22,9 +55,10 @@
metadata=0
while getopts :acd:hm opt; do
case $opt in
+ s) sysreport=1 ;;
a) advanced=1 ;;
c) clustered=1 ;;
- d) lvm_dir=$OPTARG ;;
+ d) userdir=$OPTARG ;;
h) usage ;;
m) metadata=1 ;;
:) echo "$0: $OPTARG requires a value:"; usage ;;
@@ -33,86 +67,119 @@
esac
done
-dir=`mktemp -d -p /tmp lvm_dump.XXXXXX` || exit 2
-lvm_dir="$dir/lvm_dump"
+NOW=`$DATE -u +%G%m%d%k%M%S | /usr/bin/tr -d ' '`
+if test -n "$userdir"; then
+ dir="$userdir"
+else
+ dirbase="lvmdump-$HOSTNAME-$NOW"
+ dir="$HOME/$dirbase"
+fi
+
+test -e $dir && die 3 "Fatal: $dir already exists"
+$MKDIR -p $dir || die 4 "Fatal: could not create $dir"
+
+log="$dir/lvmdump.log"
+
+myecho() {
+ echo "$@"
+ echo "$@" >> $log
+}
+
+log() {
+ echo "$@" >> $log
+ eval "$@"
+}
echo " "
-echo "Creating dump directory: $lvm_dir"
+myecho "Creating dump directory: $dir"
echo " "
-mkdir -p $lvm_dir || exit 3
-
if (( $advanced )); then
- echo "Gathering LVM volume info..."
+ myecho "Gathering LVM volume info..."
- echo " vgscan..."
- vgscan -vvvv > $lvm_dir/vgscan 2>&1
+ myecho " vgscan..."
+ log "$LVM vgscan -vvvv > $dir/vgscan 2>&1"
- echo " pvscan..."
- pvscan -v >> $lvm_dir/pvscan 2>/dev/null
+ myecho " pvscan..."
+ log "$LVM pvscan -v >> $dir/pvscan 2>> $log"
- echo " lvs..."
- lvs -a -o +devices >> $lvm_dir/lvs 2>/dev/null
+ myecho " lvs..."
+ log "$LVM lvs -a -o +devices >> $dir/lvs 2>> $log"
- echo " pvs..."
- pvs -a -v > $lvm_dir/pvs 2>/dev/null
+ myecho " pvs..."
+ log "$LVM pvs -a -v > $dir/pvs 2>> $log"
echo " vgs..."
- vgs -v > $lvm_dir/vgs 2>/dev/null
+ log "$LVM vgs -v > $dir/vgs 2>> $log"
fi
if (( $clustered )); then
- echo "Gathering cluster info..."
- echo "STATUS: " > $lvm_dir/cluster_info
- echo "----------------------------------" >> $lvm_dir/cluster_info
- cman_tool status >> $lvm_dir/cluster_info
- echo " " >> $lvm_dir/lvm_info
-
- echo "SERVICES: " >> $lvm_dir/cluster_info
- echo "----------------------------------" >> $lvm_dir/cluster_info
- cman_tool services >> $lvm_dir/cluster_info
- echo " " >> $lvm_dir/lvm_info
-fi
-
-echo "Gathering LVM & device-mapper version info..."
-echo "LVM VERSION:" > $lvm_dir/versions
-lvs --version >> $lvm_dir/versions
-echo "DEVICE MAPPER VERSION:" >> $lvm_dir/versions
-dmsetup --version >> $lvm_dir/versions
-
-echo "Gathering dmsetup info..."
-dmsetup info -c > $lvm_dir/dmsetup_info
-dmsetup table > $lvm_dir/dmsetup_table
-dmsetup status > $lvm_dir/dmsetup_status
-
-echo "Gathering process info..."
-ps alx > $lvm_dir/ps_info
+ myecho "Gathering cluster info..."
+ echo "STATUS: " > $dir/cluster_info
+ echo "----------------------------------" >> $dir/cluster_info
+ log "cman_tool status >> $dir/cluster_info 2>> $log"
+ echo " " >> $dir/lvm_info
+
+ echo "SERVICES: " >> $dir/cluster_info
+ echo "----------------------------------" >> $dir/cluster_info
+ log "cman_tool services >> $dir/cluster_info 2>> $log"
+ echo " " >> $dir/lvm_info
+fi
-echo "Gathering console messages..."
-tail -n 75 /var/log/messages > $lvm_dir/messages
+myecho "Gathering LVM & device-mapper version info..."
+echo "LVM VERSION:" > $dir/versions
+$LVM lvs --version >> $dir/versions 2>> $log
+echo "DEVICE MAPPER VERSION:" >> $dir/versions
+$DMSETUP --version >> $dir/versions 2>> $log
+
+myecho "Gathering dmsetup info..."
+log "$DMSETUP info -c > $dir/dmsetup_info 2>> $log"
+log "$DMSETUP table > $dir/dmsetup_table 2>> $log"
+log "$DMSETUP status > $dir/dmsetup_status 2>> $log"
+
+myecho "Gathering process info..."
+log "$PS alx > $dir/ps_info 2>> $log"
-echo "Gathering /etc/lvm info..."
-cp -a /etc/lvm $lvm_dir/lvm
+myecho "Gathering console messages..."
+log "$TAIL -n 75 /var/log/messages > $dir/messages 2>> $log"
-echo "Gathering /dev listing..."
-ls -la /dev > $lvm_dir/dev_listing
+myecho "Gathering /etc/lvm info..."
+log "$CP -a /etc/lvm $dir/lvm 2>> $log"
+
+myecho "Gathering /dev listing..."
+log "$LS -la /dev > $dir/dev_listing 2>> $log"
if (( $metadata )); then
- echo "Gathering LVM metadata from Physical Volumes..."
+ myecho "Gathering LVM metadata from Physical Volumes..."
- mkdir -p $lvm_dir/metadata
+ log "$MKDIR -p $dir/metadata"
- for pv in `pvs --noheadings -o name`
+ pvs="$($LVM pvs --separator , --noheadings --units s --nosuffix -o \
+ name,pe_start 2>> $log | $SED -e 's/^ *//')"
+ for line in "$pvs"
do
- echo " $pv"
- name=`basename $pv`
- dd if=$pv of=$lvm_dir/metadata/$name bs=512 count=`pvs --noheadings --nosuffix --units s -o pe_start $pv | tr -d \ `
- done 2>/dev/null
+ test -z "$line" && continue
+ pv="$(echo $line | $CUT -d, -f1)"
+ pe_start="$(echo $line | $CUT -d, -f2)"
+ name="$($BASENAME $pv)"
+ myecho " $pv"
+ log "$DD if=$pv of=$dir/metadata/$name bs=512 count=$pe_start 2>> $log"
+ done
+fi
+
+if test -z "$userdir"; then
+ lvm_dump="$dirbase.tgz"
+ myecho "Creating report tarball in $HOME/$lvm_dump..."
+ cd $HOME
+ $TAR czf $lvm_dump $dirbase 2>/dev/null
+ $RM -rf $dir
fi
-lvm_dump=$lvm_dir.tgz
-echo "Creating tarball $lvm_dump..."
-tar czf $lvm_dump $lvm_dir 2>/dev/null
+if test "$UID" != "0" && test "$EUID" != "0"; then
+ myecho
+ myecho "WARNING! Running as non-privileged user, dump is likely incomplete!"
+ myecho
+fi
exit 0
Modified: lvm2/trunk/tools/Makefile.in
==============================================================================
--- lvm2/trunk/tools/Makefile.in (original)
+++ lvm2/trunk/tools/Makefile.in Sat Apr 7 16:07:03 2007
@@ -82,7 +82,8 @@
CLEAN_TARGETS = liblvm2cmd.so liblvm2cmd.a liblvm2cmd-static.a lvm lvm.o \
lvm2cmd.o lvm2cmd-static.o lvm2cmdlib.o lvm.static \
- lvm.cflow lvm.xref lvm.tree lvm.rxref lvm.rtree
+ lvm.cflow lvm.xref lvm.tree lvm.rxref lvm.rtree \
+ lvmcmdlib.o lvm-static.o
ifeq ("@CMDLIB@", "yes")
TARGETS += liblvm2cmd.so
@@ -100,11 +101,12 @@
include $(top_srcdir)/make.tmpl
lvm: $(OBJECTS) lvm.o $(top_srcdir)/lib/liblvm.a
- $(CC) -o $@ $(OBJECTS) lvm.o $(LDFLAGS) $(LVMLIBS) $(LIBS) -rdynamic
+ $(CC) -o $@ $(CFLAGS) $(OBJECTS) lvm.o \
+ $(LDFLAGS) $(LVMLIBS) $(LIBS) -rdynamic
lvm.static: $(OBJECTS) lvm-static.o $(top_srcdir)/lib/liblvm.a
- $(CC) -o $@ $(OBJECTS) lvm-static.o -static $(LDFLAGS) $(LVMLIBS) \
- $(LIBS) -rdynamic
+ $(CC) -o $@ $(CFLAGS) $(OBJECTS) lvm-static.o -static \
+ $(LDFLAGS) $(LVMLIBS) $(LIBS) -rdynamic
liblvm2cmd.a: $(top_srcdir)/lib/liblvm.a $(OBJECTS) lvmcmdlib.o lvm2cmd.o
cat $(top_srcdir)/lib/liblvm.a > $@
Modified: lvm2/trunk/tools/args.h
==============================================================================
--- lvm2/trunk/tools/args.h (original)
+++ lvm2/trunk/tools/args.h Sat Apr 7 16:07:03 2007
@@ -46,6 +46,7 @@
arg(separator_ARG, '\0', "separator", string_arg)
arg(mirrorsonly_ARG, '\0', "mirrorsonly", NULL)
arg(nosync_ARG, '\0', "nosync", NULL)
+arg(resync_ARG, '\0', "resync", NULL)
arg(corelog_ARG, '\0', "corelog", NULL)
arg(monitor_ARG, '\0', "monitor", yes_no_arg)
arg(config_ARG, '\0', "config", string_arg)
Modified: lvm2/trunk/tools/commands.h
==============================================================================
--- lvm2/trunk/tools/commands.h (original)
+++ lvm2/trunk/tools/commands.h Sat Apr 7 16:07:03 2007
@@ -19,7 +19,7 @@
"e2fsadm "
"[-d|--debug] " "[-h|--help] " "[-n|--nofsck]" "\n"
"\t{[-l|--extents] [+|-]LogicalExtentsNumber |" "\n"
- "\t [-L|--size] [+|-]LogicalVolumeSize[kKmMgGtT]}" "\n"
+ "\t [-L|--size] [+|-]LogicalVolumeSize[kKmMgGtTpPeE]}" "\n"
"\t[-t|--test] " "\n"
"\t[-v|--verbose] " "\n"
"\t[--version] " "\n"
@@ -30,7 +30,10 @@
xx(dumpconfig,
"Dump active configuration",
- "dumpconfig <filename>\n")
+ "dumpconfig "
+ "\t[-f|--file filename] " "\n"
+ "[ConfigurationVariable...]\n",
+ file_ARG)
xx(formats,
"List available metadata formats",
@@ -69,15 +72,17 @@
"\t[-p|--permission r|rw]\n"
"\t[-r|--readahead ReadAheadSectors]\n"
"\t[--refresh]\n"
+ "\t[--resync]\n"
"\t[-t|--test]\n"
"\t[-v|--verbose]\n"
+ "\t[-y|--yes]\n"
"\t[--version]" "\n"
"\tLogicalVolume[Path] [LogicalVolume[Path]...]\n",
alloc_ARG, autobackup_ARG, available_ARG, contiguous_ARG, force_ARG,
ignorelockingfailure_ARG, major_ARG, minor_ARG, monitor_ARG,
- partial_ARG, permission_ARG, persistent_ARG, readahead_ARG,
- refresh_ARG, addtag_ARG, deltag_ARG, test_ARG)
+ partial_ARG, permission_ARG, persistent_ARG, readahead_ARG, resync_ARG,
+ refresh_ARG, addtag_ARG, deltag_ARG, test_ARG, yes_ARG)
xx(lvconvert,
"Change logical volume layout",
@@ -115,7 +120,7 @@
"\t[-h|-?|--help]\n"
"\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
"\t{-l|--extents LogicalExtentsNumber |\n"
- "\t -L|--size LogicalVolumeSize[kKmMgGtT]}\n"
+ "\t -L|--size LogicalVolumeSize[kKmMgGtTpPeE]}\n"
"\t[-M|--persistent {y|n}] [--major major] [--minor minor]\n"
"\t[-m|--mirrors Mirrors [--nosync] [--corelog]]\n"
"\t[-n|--name LogicalVolumeName]\n"
@@ -139,7 +144,7 @@
"\t[-h|-?|--help]\n"
"\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
"\t{-l|--extents LogicalExtentsNumber[%{VG|LV|FREE}] |\n"
- "\t -L|--size LogicalVolumeSize[kKmMgGtT]}\n"
+ "\t -L|--size LogicalVolumeSize[kKmMgGtTpPeE]}\n"
"\t[-M|--persistent {y|n}] [--major major] [--minor minor]\n"
"\t[-n|--name LogicalVolumeName]\n"
"\t[-p|--permission {r|rw}]\n"
@@ -204,7 +209,7 @@
"\t[-h|--help]\n"
"\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
"\t{-l|--extents [+]LogicalExtentsNumber[%{VG|FREE}] |\n"
- "\t -L|--size [+]LogicalVolumeSize[kKmMgGtT]}\n"
+ "\t -L|--size [+]LogicalVolumeSize[kKmMgGtTpPeE]}\n"
"\t[-m|--mirrors Mirrors]\n"
"\t[-n|--nofsck]\n"
"\t[-r|--resizefs]\n"
@@ -269,11 +274,12 @@
"\t[-f|--force]\n"
"\t[-h|--help]\n"
"\t{-l|--extents [-]LogicalExtentsNumber[%{VG|LV|FREE}] |\n"
- "\t -L|--size [-]LogicalVolumeSize[kKmMgGtT]}\n"
+ "\t -L|--size [-]LogicalVolumeSize[kKmMgGtTpPeE]}\n"
"\t[-n|--nofsck]\n"
"\t[-r|--resizefs]\n"
"\t[-t|--test]\n"
"\t[-v|--verbose]\n"
+ "\t[-y|--yes]\n"
"\t[--version]" "\n"
"\tLogicalVolume[Path]\n",
@@ -317,7 +323,7 @@
"\t[-h|--help]\n"
"\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
"\t{-l|--extents [+|-]LogicalExtentsNumber[%{VG|LV|FREE}] |\n"
- "\t -L|--size [+|-]LogicalVolumeSize[kKmMgGtT]}\n"
+ "\t -L|--size [+|-]LogicalVolumeSize[kKmMgGtTpPeE]}\n"
"\t[-n|--nofsck]\n"
"\t[-r|--resizefs]\n"
"\t[-t|--test]\n"
@@ -393,7 +399,7 @@
"pvresize " "\n"
"\t[-d|--debug]" "\n"
"\t[-h|-?|--help] " "\n"
- "\t[--setphysicalvolumesize PhysicalVolumeSize[kKmMgGtT]" "\n"
+ "\t[--setphysicalvolumesize PhysicalVolumeSize[kKmMgGtTpPeE]" "\n"
"\t[-t|--test] " "\n"
"\t[-v|--verbose] " "\n"
"\t[--version] " "\n"
@@ -411,8 +417,8 @@
"\t[--labelsector sector] " "\n"
"\t[-M|--metadatatype 1|2]" "\n"
"\t[--metadatacopies #copies]" "\n"
- "\t[--metadatasize MetadataSize[kKmMgGtT]]" "\n"
- "\t[--setphysicalvolumesize PhysicalVolumeSize[kKmMgGtT]" "\n"
+ "\t[--metadatasize MetadataSize[kKmMgGtTpPeE]]" "\n"
+ "\t[--setphysicalvolumesize PhysicalVolumeSize[kKmMgGtTpPeE]" "\n"
"\t[-t|--test] " "\n"
"\t[-u|--uuid uuid] " "\n"
"\t[-v|--verbose] " "\n"
@@ -609,7 +615,7 @@
"\t -x|--resizeable {y|n} |" "\n"
"\t -l|--logicalvolume MaxLogicalVolumes |" "\n"
"\t -p|--maxphysicalvolumes MaxPhysicalVolumes |" "\n"
- "\t -s|--physicalextentsize PhysicalExtentSize[kKmMgGtT] |" "\n"
+ "\t -s|--physicalextentsize PhysicalExtentSize[kKmMgGtTpPeE] |" "\n"
"\t --addtag Tag |\n"
"\t --deltag Tag}\n"
"\t[VolumeGroupName...]\n",
@@ -636,7 +642,7 @@
"\t[--labelsector sector] " "\n"
"\t[-M|--metadatatype 1|2]" "\n"
"\t[--metadatacopies #copies]" "\n"
- "\t[--metadatasize MetadataSize[kKmMgGtT]]" "\n"
+ "\t[--metadatasize MetadataSize[kKmMgGtTpPeE]]" "\n"
"\t[-t|--test] " "\n"
"\t[-v|--verbose] " "\n"
"\t[--version] " "\n"
@@ -651,13 +657,13 @@
"\t[-A|--autobackup {y|n}] " "\n"
"\t[--addtag Tag] " "\n"
"\t[--alloc AllocationPolicy] " "\n"
- "\t[-c|--clustered] " "\n"
+ "\t[-c|--clustered {y|n}] " "\n"
"\t[-d|--debug]" "\n"
"\t[-h|--help]" "\n"
"\t[-l|--maxlogicalvolumes MaxLogicalVolumes]" "\n"
"\t[-M|--metadatatype 1|2] " "\n"
"\t[-p|--maxphysicalvolumes MaxPhysicalVolumes] " "\n"
- "\t[-s|--physicalextentsize PhysicalExtentSize[kKmMgGtT]] " "\n"
+ "\t[-s|--physicalextentsize PhysicalExtentSize[kKmMgGtTpPeE]] " "\n"
"\t[-t|--test] " "\n"
"\t[-v|--verbose]" "\n"
"\t[--version] " "\n"
Modified: lvm2/trunk/tools/dumpconfig.c
==============================================================================
--- lvm2/trunk/tools/dumpconfig.c (original)
+++ lvm2/trunk/tools/dumpconfig.c Sat Apr 7 16:07:03 2007
@@ -19,15 +19,10 @@
{
const char *file = NULL;
- if (argc == 1)
- file = argv[0];
+ if (arg_count(cmd, file_ARG))
+ file = arg_str_value(cmd, file_ARG, "");
- if (argc > 1) {
- log_error("Please specify one file for output");
- return EINVALID_CMD_LINE;
- }
-
- if (!write_config_file(cmd->cft, file))
+ if (!write_config_file(cmd->cft, file, argc, argv))
return ECMD_FAILED;
return ECMD_PROCESSED;
Modified: lvm2/trunk/tools/fsadm/Makefile.in
==============================================================================
--- lvm2/trunk/tools/fsadm/Makefile.in (original)
+++ lvm2/trunk/tools/fsadm/Makefile.in Sat Apr 7 16:07:03 2007
@@ -23,7 +23,7 @@
include $(top_srcdir)/make.tmpl
fsadm: $(OBJECTS)
- $(CC) -o $@ $(OBJECTS) -rdynamic
+ $(CC) -o $@ $(CFLAGS) $(OBJECTS) -rdynamic
install: fsadm
$(INSTALL) -D $(OWNER) $(GROUP) $(STRIP) fsadm \
Modified: lvm2/trunk/tools/lvchange.c
==============================================================================
--- lvm2/trunk/tools/lvchange.c (original)
+++ lvm2/trunk/tools/lvchange.c Sat Apr 7 16:07:03 2007
@@ -19,6 +19,7 @@
struct logical_volume *lv)
{
uint32_t lv_access;
+ struct lvinfo info;
lv_access = arg_uint_value(cmd, permission_ARG, 0);
@@ -34,6 +35,13 @@
return 0;
}
+ if ((lv->status & MIRRORED) && (lv->vg->status & CLUSTERED) &&
+ lv_info(cmd, lv, &info, 0) && info.exists) {
+ log_error("Cannot change permissions of mirror \"%s\" "
+ "while active.", lv->name);
+ return 0;
+ }
+
if (lv_access & LVM_WRITE) {
lv->status |= LVM_WRITE;
log_verbose("Setting logical volume \"%s\" read/write",
@@ -72,10 +80,9 @@
return 1;
}
-static int lvchange_registration(struct cmd_context *cmd,
- struct logical_volume *lv)
+static int lvchange_monitoring(struct cmd_context *cmd,
+ struct logical_volume *lv)
{
- int r;
struct lvinfo info;
if (!lv_info(cmd, lv, &info, 0) || !info.exists) {
@@ -83,25 +90,15 @@
return 0;
}
- /* do not register pvmove lv's */
+ /* do not monitor pvmove lv's */
if (lv->status & PVMOVE)
return 1;
- log_verbose("%smonitoring logical volume \"%s\"",
- (dmeventd_register_mode()) ? "" : "Not ", lv->name);
- r = register_dev_for_events(cmd, lv, dmeventd_register_mode());
-
- if (r < 0) {
- log_error("Unable to %smonitor logical volume, %s",
- (dmeventd_register_mode()) ? "" : "un", lv->name);
- r = 0;
- } else if (!r) {
- log_verbose("Logical volume %s needs no monitoring.",
- lv->name);
- r = 1;
- }
+ if ((dmeventd_monitor_mode() != DMEVENTD_MONITOR_IGNORE) &&
+ !monitor_dev_for_events(cmd, lv, dmeventd_monitor_mode()))
+ stack;
- return r;
+ return 1;
}
static int lvchange_availability(struct cmd_context *cmd,
@@ -127,10 +124,10 @@
}
} else {
if (lockingfailed() && (lv->vg->status & CLUSTERED)) {
- log_verbose("Locking failed: ignoring clustered "
+ log_verbose("Locking failed: ignoring clustered "
"logical volume %s", lv->name);
- return 0;
- }
+ return 0;
+ }
if (lv_is_origin(lv) || (activate == CHANGE_AE)) {
log_verbose("Activating logical volume \"%s\" "
@@ -175,6 +172,159 @@
return 1;
}
+static int lvchange_resync(struct cmd_context *cmd,
+ struct logical_volume *lv)
+{
+ int active = 0;
+ struct lvinfo info;
+ struct logical_volume *log_lv;
+
+ if (!(lv->status & MIRRORED)) {
+ log_error("Unable to resync %s because it is not mirrored.",
+ lv->name);
+ return 1;
+ }
+
+ if (lv->status & PVMOVE) {
+ log_error("Unable to resync pvmove volume %s", lv->name);
+ return 0;
+ }
+
+ if (lv->status & LOCKED) {
+ log_error("Unable to resync locked volume %s", lv->name);
+ return 0;
+ }
+
+ if (lv_info(cmd, lv, &info, 1)) {
+ if (info.open_count) {
+ log_error("Can't resync open logical volume \"%s\"",
+ lv->name);
+ return ECMD_FAILED;
+ }
+
+ if (info.exists) {
+ if (!arg_count(cmd, yes_ARG) &&
+ yes_no_prompt("Do you really want to deactivate "
+ "logical volume %s to resync it? [y/n]: ",
+ lv->name) == 'n') {
+ log_print("Logical volume \"%s\" not resynced",
+ lv->name);
+ return ECMD_FAILED;
+ }
+
+ active = 1;
+ }
+ }
+
+ if ((lv->vg->status & CLUSTERED) && !activate_lv_excl(cmd, lv)) {
+ log_error("Can't get exclusive access to clustered volume %s",
+ lv->name);
+ return ECMD_FAILED;
+ }
+
+ if (!deactivate_lv(cmd, lv)) {
+ log_error("Unable to deactivate %s for resync", lv->name);
+ return 0;
+ }
+
+ log_lv = first_seg(lv)->log_lv;
+
+ log_very_verbose("Starting resync of %s%s%s mirror \"%s\"",
+ (active) ? "active " : "",
+ (lv->vg->status & CLUSTERED) ? "clustered " : "",
+ (log_lv) ? "disk-logged" : "core-logged",
+ lv->name);
+
+ /*
+ * If this mirror has a core log (i.e. !log_lv),
+ * then simply deactivating/activating will cause
+ * it to reset the sync status. We only need to
+ * worry about persistent logs.
+ */
+ if (!log_lv && !(lv->status & MIRROR_NOTSYNCED)) {
+ if (active && !activate_lv(cmd, lv)) {
+ log_error("Failed to reactivate %s to resynchronize "
+ "mirror", lv->name);
+ return 0;
+ }
+ return 1;
+ }
+
+ lv->status &= ~MIRROR_NOTSYNCED;
+
+ if (log_lv) {
+ /* Separate mirror log so we can clear it */
+ first_seg(lv)->log_lv = NULL;
+ log_lv->status &= ~MIRROR_LOG;
+ log_lv->status |= VISIBLE_LV;
+
+ if (!vg_write(lv->vg)) {
+ log_error("Failed to write intermediate VG metadata.");
+ if (active) {
+ first_seg(lv)->log_lv = log_lv;
+ log_lv->status |= MIRROR_LOG;
+ log_lv->status &= ~VISIBLE_LV;
+ if (!activate_lv(cmd, lv))
+ stack;
+ }
+ return 0;
+ }
+
+ backup(lv->vg);
+
+ if (!vg_commit(lv->vg)) {
+ log_error("Failed to commit intermediate VG metadata.");
+ if (active) {
+ first_seg(lv)->log_lv = log_lv;
+ log_lv->status |= MIRROR_LOG;
+ log_lv->status &= ~VISIBLE_LV;
+ if (!activate_lv(cmd, lv))
+ stack;
+ }
+ return 0;
+ }
+
+ if (!activate_lv(cmd, log_lv)) {
+ log_error("Unable to activate %s for mirror log resync",
+ log_lv->name);
+ return 0;
+ }
+
+ log_very_verbose("Clearing log device %s", log_lv->name);
+ if (!set_lv(cmd, log_lv, log_lv->size, 0)) {
+ log_error("Unable to reset sync status for %s", lv->name);
+ if (!deactivate_lv(cmd, log_lv))
+ log_error("Failed to deactivate log LV after "
+ "wiping failed");
+ return 0;
+ }
+
+ if (!deactivate_lv(cmd, log_lv)) {
+ log_error("Unable to deactivate log LV %s after wiping "
+ "for resync", log_lv->name);
+ return 0;
+ }
+
+ /* Put mirror log back in place */
+ first_seg(lv)->log_lv = log_lv;
+ log_lv->status |= MIRROR_LOG;
+ log_lv->status &= ~VISIBLE_LV;
+ }
+
+ log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
+ if (!vg_write(lv->vg) || !vg_commit(lv->vg)) {
+ log_error("Failed to update metadata on disk.");
+ return 0;
+ }
+
+ if (active && !activate_lv(cmd, lv)) {
+ log_error("Failed to reactivate %s after resync", lv->name);
+ return 0;
+ }
+
+ return 1;
+}
+
static int lvchange_alloc(struct cmd_context *cmd, struct logical_volume *lv)
{
int want_contiguous = 0;
@@ -442,7 +592,9 @@
return ECMD_FAILED;
}
- init_dmeventd_register(arg_int_value(cmd, monitor_ARG, DEFAULT_DMEVENTD_MONITOR));
+ init_dmeventd_monitor(arg_int_value(cmd, monitor_ARG,
+ cmd->is_static ?
+ DMEVENTD_MONITOR_IGNORE : DEFAULT_DMEVENTD_MONITOR));
/* access permission change */
if (arg_count(cmd, permission_ARG)) {
@@ -495,6 +647,10 @@
if (doit)
log_print("Logical volume \"%s\" changed", lv->name);
+ if (arg_count(cmd, resync_ARG))
+ if (!lvchange_resync(cmd, lv))
+ return ECMD_FAILED;
+
/* availability change */
if (arg_count(cmd, available_ARG)) {
if (!lvchange_availability(cmd, lv))
@@ -508,7 +664,7 @@
if (!arg_count(cmd, available_ARG) &&
!arg_count(cmd, refresh_ARG) &&
arg_count(cmd, monitor_ARG)) {
- if (!lvchange_registration(cmd, lv))
+ if (!lvchange_monitoring(cmd, lv))
return ECMD_FAILED;
}
@@ -522,9 +678,10 @@
&& !arg_count(cmd, minor_ARG) && !arg_count(cmd, major_ARG)
&& !arg_count(cmd, persistent_ARG) && !arg_count(cmd, addtag_ARG)
&& !arg_count(cmd, deltag_ARG) && !arg_count(cmd, refresh_ARG)
- && !arg_count(cmd, alloc_ARG) && !arg_count(cmd, monitor_ARG)) {
+ && !arg_count(cmd, alloc_ARG) && !arg_count(cmd, monitor_ARG)
+ && !arg_count(cmd, resync_ARG)) {
log_error("Need 1 or more of -a, -C, -j, -m, -M, -p, -r, "
- "--refresh, --alloc, --addtag, --deltag "
+ "--resync, --refresh, --alloc, --addtag, --deltag "
"or --monitor");
return EINVALID_CMD_LINE;
}
Modified: lvm2/trunk/tools/lvconvert.c
==============================================================================
--- lvm2/trunk/tools/lvconvert.c (original)
+++ lvm2/trunk/tools/lvconvert.c Sat Apr 7 16:07:03 2007
@@ -212,7 +212,7 @@
}
if (activation() && lp->segtype->ops->target_present &&
- !lp->segtype->ops->target_present()) {
+ !lp->segtype->ops->target_present(NULL)) {
log_error("%s: Required device-mapper target(s) not "
"detected in your kernel", lp->segtype->name);
return 0;
@@ -281,15 +281,8 @@
if (lp->mirrors == existing_mirrors) {
if (!seg->log_lv && !arg_count(cmd, corelog_ARG)) {
/* No disk log present, add one. */
- /* FIXME: Why doesn't this work? Without
- it, we will probably put the log on the
- same device as a mirror leg.
- if (!(parallel_areas = build_parallel_areas_from_lv(cmd, lv))) {
- stack;
- return 0;
- }
- */
- parallel_areas = NULL;
+ if (!(parallel_areas = build_parallel_areas_from_lv(cmd, lv)))
+ return_0;
if (!lv_mirror_percent(cmd, lv, 0, &sync_percent, NULL)) {
log_error("Unable to determine mirror sync status.");
return 0;
@@ -297,7 +290,7 @@
segtype = get_segtype_from_string(cmd, "striped");
- if (!(ah = allocate_extents(lv->vg, NULL, segtype, 1,
+ if (!(ah = allocate_extents(lv->vg, NULL, segtype, 0,
0, 1, 0,
NULL, 0, 0, lp->pvh,
lp->alloc,
@@ -453,9 +446,9 @@
return 0;
}
- if (!lp->zero)
- log_error("WARNING: \"%s\" not zeroed", lv->name);
- else if (!set_lv(cmd, lv, 0)) {
+ if (!lp->zero || !(lv->status & LVM_WRITE))
+ log_print("WARNING: \"%s\" not zeroed", lv->name);
+ else if (!set_lv(cmd, lv, 0, 0)) {
log_error("Aborting. Failed to wipe snapshot "
"exception store.");
return 0;
Modified: lvm2/trunk/tools/lvcreate.c
==============================================================================
--- lvm2/trunk/tools/lvcreate.c (original)
+++ lvm2/trunk/tools/lvcreate.c Sat Apr 7 16:07:03 2007
@@ -95,7 +95,7 @@
}
} else {
- vg_name = skip_dev_dir(cmd, argv[0]);
+ vg_name = skip_dev_dir(cmd, argv[0], NULL);
if (strrchr(vg_name, '/')) {
log_error("Volume group name expected "
"(no slash)");
@@ -386,7 +386,7 @@
}
if (activation() && lp->segtype->ops->target_present &&
- !lp->segtype->ops->target_present()) {
+ !lp->segtype->ops->target_present(NULL)) {
log_error("%s: Required device-mapper target(s) not "
"detected in your kernel", lp->segtype->name);
return 0;
@@ -434,6 +434,10 @@
else
lp->permission = LVM_READ | LVM_WRITE;
+ /* Must not zero read only volume */
+ if (!(lp->permission & LVM_WRITE))
+ lp->zero = 0;
+
lp->minor = arg_int_value(cmd, minor_ARG, -1);
lp->major = arg_int_value(cmd, major_ARG, -1);
@@ -556,7 +560,16 @@
display_size(cmd, tmp_size));
}
- lp->extents = tmp_size / vg->extent_size;
+ if (tmp_size > (uint64_t) UINT32_MAX * vg->extent_size) {
+ log_error("Volume too large (%s) for extent size %s. "
+ "Upper limit is %s.",
+ display_size(cmd, tmp_size),
+ display_size(cmd, vg->extent_size),
+ display_size(cmd, (uint64_t) UINT32_MAX *
+ vg->extent_size));
+ return 0;
+ }
+ lp->extents = (uint64_t) tmp_size / vg->extent_size;
}
switch(lp->percent) {
@@ -618,8 +631,7 @@
}
if (!lp->extents) {
- log_error("Unable to create logical volume %s with no extents",
- lp->lv_name);
+ log_error("Unable to create new logical volume with no extents");
return 0;
}
@@ -761,18 +773,19 @@
return 0;
}
- if (!activate_lv(cmd, lv)) {
- if (lp->snapshot)
- /* FIXME Remove the failed lv we just added */
+ if (lp->snapshot) {
+ if (!activate_lv_excl(cmd, lv)) {
log_error("Aborting. Failed to activate snapshot "
"exception store. Remove new LV and retry.");
- else
- log_error("Failed to activate new LV.");
+ return 0;
+ }
+ } else if (!activate_lv(cmd, lv)) {
+ log_error("Failed to activate new LV.");
return 0;
}
if ((lp->zero || lp->snapshot) && activation()) {
- if (!set_lv(cmd, lv, 0) && lp->snapshot) {
+ if (!set_lv(cmd, lv, 0, 0) && lp->snapshot) {
/* FIXME Remove the failed lv we just added */
log_error("Aborting. Failed to wipe snapshot "
"exception store. Remove new LV and retry.");
@@ -787,10 +800,8 @@
/* Reset permission after zeroing */
if (!(lp->permission & LVM_WRITE))
lv->status &= ~LVM_WRITE;
- if (!deactivate_lv(cmd, lv)) {
- log_err("Couldn't deactivate new snapshot.");
- return 0;
- }
+
+ /* cow LV remains active and becomes snapshot LV */
if (!vg_add_snapshot(vg->fid, NULL, org, lv, NULL,
org->le_count, lp->chunk_size)) {
Modified: lvm2/trunk/tools/lvm-static.c
==============================================================================
--- lvm2/trunk/tools/lvm-static.c (original)
+++ lvm2/trunk/tools/lvm-static.c Sat Apr 7 16:07:03 2007
@@ -19,3 +19,8 @@
{
return lvm2_main(argc, argv, 1);
}
+
+int lvm_shell(struct cmd_context *cmd, struct cmdline_context *cmdline)
+{
+ return 0;
+}
Modified: lvm2/trunk/tools/lvm.c
==============================================================================
--- lvm2/trunk/tools/lvm.c (original)
+++ lvm2/trunk/tools/lvm.c Sat Apr 7 16:07:03 2007
@@ -13,9 +13,233 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include "tools.h"
#include "lvm2cmdline.h"
int main(int argc, char **argv)
{
return lvm2_main(argc, argv, 0);
}
+
+#ifdef READLINE_SUPPORT
+
+# include <readline/readline.h>
+# include <readline/history.h>
+# ifndef HAVE_RL_COMPLETION_MATCHES
+# define rl_completion_matches(a, b) completion_matches((char *)a, b)
+# endif
+
+static struct cmdline_context *_cmdline;
+
+/* List matching commands */
+static char *_list_cmds(const char *text, int state)
+{
+ static int i = 0;
+ static size_t len = 0;
+
+ /* Initialise if this is a new completion attempt */
+ if (!state) {
+ i = 0;
+ len = strlen(text);
+ }
+
+ while (i < _cmdline->num_commands)
+ if (!strncmp(text, _cmdline->commands[i++].name, len))
+ return strdup(_cmdline->commands[i - 1].name);
+
+ return NULL;
+}
+
+/* List matching arguments */
+static char *_list_args(const char *text, int state)
+{
+ static int match_no = 0;
+ static size_t len = 0;
+ static struct command *com;
+
+ /* Initialise if this is a new completion attempt */
+ if (!state) {
+ char *s = rl_line_buffer;
+ int j = 0;
+
+ match_no = 0;
+ com = NULL;
+ len = strlen(text);
+
+ /* Find start of first word in line buffer */
+ while (isspace(*s))
+ s++;
+
+ /* Look for word in list of commands */
+ for (j = 0; j < _cmdline->num_commands; j++) {
+ const char *p;
+ char *q = s;
+
+ p = _cmdline->commands[j].name;
+ while (*p == *q) {
+ p++;
+ q++;
+ }
+ if ((!*p) && *q == ' ') {
+ com = _cmdline->commands + j;
+ break;
+ }
+ }
+
+ if (!com)
+ return NULL;
+ }
+
+ /* Short form arguments */
+ if (len < 3) {
+ while (match_no < com->num_args) {
+ char s[3];
+ char c;
+ if (!(c = (_cmdline->the_args +
+ com->valid_args[match_no++])->short_arg))
+ continue;
+
+ sprintf(s, "-%c", c);
+ if (!strncmp(text, s, len))
+ return strdup(s);
+ }
+ }
+
+ /* Long form arguments */
+ if (match_no < com->num_args)
+ match_no = com->num_args;
+
+ while (match_no - com->num_args < com->num_args) {
+ const char *l;
+ l = (_cmdline->the_args +
+ com->valid_args[match_no++ - com->num_args])->long_arg;
+ if (*(l + 2) && !strncmp(text, l, len))
+ return strdup(l);
+ }
+
+ return NULL;
+}
+
+/* Custom completion function */
+static char **_completion(const char *text, int start_pos, int end_pos)
+{
+ char **match_list = NULL;
+ int p = 0;
+
+ while (isspace((int) *(rl_line_buffer + p)))
+ p++;
+
+ /* First word should be one of our commands */
+ if (start_pos == p)
+ match_list = rl_completion_matches(text, _list_cmds);
+
+ else if (*text == '-')
+ match_list = rl_completion_matches(text, _list_args);
+ /* else other args */
+
+ /* No further completion */
+ rl_attempted_completion_over = 1;
+ return match_list;
+}
+
+static int _hist_file(char *buffer, size_t size)
+{
+ char *e = getenv("HOME");
+
+ if (dm_snprintf(buffer, size, "%s/.lvm_history", e) < 0) {
+ log_error("$HOME/.lvm_history: path too long");
+ return 0;
+ }
+
+ return 1;
+}
+
+static void _read_history(struct cmd_context *cmd)
+{
+ char hist_file[PATH_MAX];
+
+ if (!_hist_file(hist_file, sizeof(hist_file)))
+ return;
+
+ if (read_history(hist_file))
+ log_very_verbose("Couldn't read history from %s.", hist_file);
+
+ stifle_history(find_config_tree_int(cmd, "shell/history_size",
+ DEFAULT_MAX_HISTORY));
+
+}
+
+static void _write_history(void)
+{
+ char hist_file[PATH_MAX];
+
+ if (!_hist_file(hist_file, sizeof(hist_file)))
+ return;
+
+ if (write_history(hist_file))
+ log_very_verbose("Couldn't write history to %s.", hist_file);
+}
+
+int lvm_shell(struct cmd_context *cmd, struct cmdline_context *cmdline)
+{
+ int argc, ret;
+ char *input = NULL, *args[MAX_ARGS], **argv;
+
+ rl_readline_name = "lvm";
+ rl_attempted_completion_function = (CPPFunction *) _completion;
+
+ _read_history(cmd);
+
+ _cmdline = cmdline;
+
+ _cmdline->interactive = 1;
+ while (1) {
+ free(input);
+ input = readline("lvm> ");
+
+ /* EOF */
+ if (!input) {
+ printf("\n");
+ break;
+ }
+
+ /* empty line */
+ if (!*input)
+ continue;
+
+ add_history(input);
+
+ argv = args;
+
+ if (lvm_split(input, &argc, argv, MAX_ARGS) == MAX_ARGS) {
+ log_error("Too many arguments, sorry.");
+ continue;
+ }
+
+ if (!strcmp(argv[0], "lvm")) {
+ argv++;
+ argc--;
+ }
+
+ if (!argc)
+ continue;
+
+ if (!strcmp(argv[0], "quit") || !strcmp(argv[0], "exit")) {
+ remove_history(history_length - 1);
+ log_error("Exiting.");
+ break;
+ }
+
+ ret = lvm_run_command(cmd, argc, argv);
+ if (ret == ENO_SUCH_CMD)
+ log_error("No such command '%s'. Try 'help'.",
+ argv[0]);
+
+ _write_history();
+ }
+
+ free(input);
+ return 0;
+}
+
+#endif /* READLINE_SUPPORT */
Modified: lvm2/trunk/tools/lvm2cmdline.h
==============================================================================
--- lvm2/trunk/tools/lvm2cmdline.h (original)
+++ lvm2/trunk/tools/lvm2cmdline.h Sat Apr 7 16:07:03 2007
@@ -18,6 +18,14 @@
struct cmd_context;
+struct cmdline_context {
+ struct arg *the_args;
+ struct command *commands;
+ int num_commands;
+ int commands_size;
+ int interactive;
+};
+
int lvm2_main(int argc, char **argv, unsigned is_static);
void *cmdlib_lvm2_init(unsigned is_static);
@@ -27,5 +35,6 @@
void lvm_register_commands(void);
int lvm_split(char *str, int *argc, char **argv, int max);
int lvm_run_command(struct cmd_context *cmd, int argc, char **argv);
+int lvm_shell(struct cmd_context *cmd, struct cmdline_context *cmdline);
#endif
Modified: lvm2/trunk/tools/lvmcmdlib.c
==============================================================================
--- lvm2/trunk/tools/lvmcmdlib.c (original)
+++ lvm2/trunk/tools/lvmcmdlib.c Sat Apr 7 16:07:03 2007
@@ -16,6 +16,7 @@
#include "tools.h"
#include "lvm2cmdline.h"
#include "label.h"
+#include "memlock.h"
#include "version.h"
#include "lvm2cmd.h"
@@ -77,7 +78,13 @@
goto out;
}
- ret = lvm_run_command(cmd, argc, argv);
+ /* FIXME Temporary - move to libdevmapper */
+ if (!strcmp(cmdline, "_memlock_inc"))
+ memlock_inc();
+ if (!strcmp(cmdline, "_memlock_dec"))
+ memlock_dec();
+ else
+ ret = lvm_run_command(cmd, argc, argv);
out:
dm_free(cmdcopy);
Modified: lvm2/trunk/tools/lvmcmdline.c
==============================================================================
--- lvm2/trunk/tools/lvmcmdline.c (original)
+++ lvm2/trunk/tools/lvmcmdline.c Sat Apr 7 16:07:03 2007
@@ -41,30 +41,16 @@
# define OPTIND_INIT 1
#endif
-#ifdef READLINE_SUPPORT
-# include <readline/readline.h>
-# include <readline/history.h>
-# ifndef HAVE_RL_COMPLETION_MATCHES
-# define rl_completion_matches(a, b) completion_matches((char *)a, b)
-# endif
-#endif
-
/*
- * Exported table of valid switches
+ * Table of valid switches
*/
-struct arg the_args[ARG_COUNT + 1] = {
-
+static struct arg _the_args[ARG_COUNT + 1] = {
#define arg(a, b, c, d) {b, "", "--" c, d, 0, NULL, 0, 0, INT64_C(0), UINT64_C(0), SIGN_NONE, PERCENT_NONE, NULL},
#include "args.h"
#undef arg
-
};
-static int _array_size;
-static int _num_commands;
-static struct command *_commands;
-
-static int _interactive;
+static struct cmdline_context _cmdline;
int yes_no_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a)
{
@@ -186,7 +172,7 @@
{
char *ptr;
int i;
- static const char *suffixes = "kmgt";
+ static const char *suffixes = "kmgtpe";
char *val;
double v;
@@ -412,21 +398,21 @@
static void __alloc(int size)
{
- if (!(_commands = dm_realloc(_commands, sizeof(*_commands) * size))) {
+ if (!(_cmdline.commands = dm_realloc(_cmdline.commands, sizeof(*_cmdline.commands) * size))) {
log_fatal("Couldn't allocate memory.");
exit(ECMD_FAILED);
}
- _array_size = size;
+ _cmdline.commands_size = size;
}
static void _alloc_command(void)
{
- if (!_array_size)
+ if (!_cmdline.commands_size)
__alloc(32);
- if (_array_size <= _num_commands)
- __alloc(2 * _array_size);
+ if (_cmdline.commands_size <= _cmdline.num_commands)
+ __alloc(2 * _cmdline.commands_size);
}
static void _create_new_command(const char *name, command_fn command,
@@ -437,7 +423,7 @@
_alloc_command();
- nc = _commands + _num_commands++;
+ nc = _cmdline.commands + _cmdline.num_commands++;
nc->name = name;
nc->desc = desc;
@@ -495,17 +481,17 @@
namebase = strdup(name);
base = basename(namebase);
- for (i = 0; i < _num_commands; i++) {
- if (!strcmp(base, _commands[i].name))
+ for (i = 0; i < _cmdline.num_commands; i++) {
+ if (!strcmp(base, _cmdline.commands[i].name))
break;
}
free(namebase);
- if (i >= _num_commands)
+ if (i >= _cmdline.num_commands)
return 0;
- return _commands + i;
+ return _cmdline.commands + i;
}
static void _usage(const char *name)
@@ -527,7 +513,7 @@
*/
static void _add_getopt_arg(int arg, char **ptr, struct option **o)
{
- struct arg *a = the_args + arg;
+ struct arg *a = _cmdline.the_args + arg;
if (a->short_arg) {
*(*ptr)++ = a->short_arg;
@@ -556,12 +542,12 @@
for (i = 0; i < com->num_args; i++) {
arg = com->valid_args[i];
- a = the_args + arg;
+ a = _cmdline.the_args + arg;
/*
* opt should equal either the
* short arg, or the index into
- * 'the_args'.
+ * the_args.
*/
if ((a->short_arg && (opt == a->short_arg)) ||
(!a->short_arg && (opt == arg)))
@@ -580,7 +566,7 @@
struct arg *a;
for (i = 0; i < ARG_COUNT; i++) {
- a = the_args + i;
+ a = _cmdline.the_args + i;
/* zero the count and arg */
a->count = 0;
@@ -651,15 +637,15 @@
if (arg_count(cmd, oldarg) && arg_count(cmd, newarg)) {
log_error("%s and %s are synonyms. Please only supply one.",
- the_args[oldarg].long_arg, the_args[newarg].long_arg);
+ _cmdline.the_args[oldarg].long_arg, _cmdline.the_args[newarg].long_arg);
return 0;
}
if (!arg_count(cmd, oldarg))
return 1;
- old = the_args + oldarg;
- new = the_args + newarg;
+ old = _cmdline.the_args + oldarg;
+ new = _cmdline.the_args + newarg;
new->count = old->count;
new->value = old->value;
@@ -712,10 +698,8 @@
cmd->default_settings.activation);
}
- if (arg_count(cmd, autobackup_ARG)) {
- cmd->current_settings.archive = 1;
- cmd->current_settings.backup = 1;
- }
+ cmd->current_settings.archive = arg_int_value(cmd, autobackup_ARG, cmd->current_settings.archive);
+ cmd->current_settings.backup = arg_int_value(cmd, autobackup_ARG, cmd->current_settings.backup);
if (arg_count(cmd, partial_ARG)) {
init_partial(1);
@@ -784,8 +768,8 @@
log_error("Use 'lvm help <command>' for more information");
log_error(" ");
- for (i = 0; i < _num_commands; i++) {
- struct command *com = _commands + i;
+ for (i = 0; i < _cmdline.num_commands; i++) {
+ struct command *com = _cmdline.commands + i;
log_error("%-16.16s%s", com->name, com->desc);
}
@@ -961,7 +945,7 @@
*/
dm_pool_empty(cmd->mem);
- if (ret == EINVALID_CMD_LINE && !_interactive)
+ if (ret == EINVALID_CMD_LINE && !_cmdline.interactive)
_usage(cmd->command->name);
log_debug("Completed: %s", cmd->cmd_line);
@@ -1032,7 +1016,9 @@
{
struct cmd_context *cmd;
- if (!(cmd = create_toolcontext(&the_args[0], is_static))) {
+ _cmdline.the_args = &_the_args[0];
+
+ if (!(cmd = create_toolcontext(_cmdline.the_args, is_static, 0))) {
stack;
return NULL;
}
@@ -1048,10 +1034,10 @@
{
int i;
- for (i = 0; i < _num_commands; i++)
- dm_free(_commands[i].valid_args);
+ for (i = 0; i < _cmdline.num_commands; i++)
+ dm_free(_cmdline.commands[i].valid_args);
- dm_free(_commands);
+ dm_free(_cmdline.commands);
}
void lvm_fin(struct cmd_context *cmd)
@@ -1067,8 +1053,9 @@
char buffer[CMD_LEN];
int ret = 0;
int magic_number = 0;
+ char *script_file = argv[0];
- if ((script = fopen(argv[0], "r")) == NULL)
+ if ((script = fopen(script_file, "r")) == NULL)
return ENO_SUCH_CMD;
while (fgets(buffer, sizeof(buffer), script) != NULL) {
@@ -1101,222 +1088,12 @@
lvm_run_command(cmd, argc, argv);
}
- fclose(script);
- return ret;
-}
-
-#ifdef READLINE_SUPPORT
-/* List matching commands */
-static char *_list_cmds(const char *text, int state)
-{
- static int i = 0;
- static size_t len = 0;
-
- /* Initialise if this is a new completion attempt */
- if (!state) {
- i = 0;
- len = strlen(text);
- }
-
- while (i < _num_commands)
- if (!strncmp(text, _commands[i++].name, len))
- return strdup(_commands[i - 1].name);
-
- return NULL;
-}
-
-/* List matching arguments */
-static char *_list_args(const char *text, int state)
-{
- static int match_no = 0;
- static size_t len = 0;
- static struct command *com;
-
- /* Initialise if this is a new completion attempt */
- if (!state) {
- char *s = rl_line_buffer;
- int j = 0;
-
- match_no = 0;
- com = NULL;
- len = strlen(text);
-
- /* Find start of first word in line buffer */
- while (isspace(*s))
- s++;
-
- /* Look for word in list of commands */
- for (j = 0; j < _num_commands; j++) {
- const char *p;
- char *q = s;
-
- p = _commands[j].name;
- while (*p == *q) {
- p++;
- q++;
- }
- if ((!*p) && *q == ' ') {
- com = _commands + j;
- break;
- }
- }
-
- if (!com)
- return NULL;
- }
-
- /* Short form arguments */
- if (len < 3) {
- while (match_no < com->num_args) {
- char s[3];
- char c;
- if (!(c = (the_args +
- com->valid_args[match_no++])->short_arg))
- continue;
-
- sprintf(s, "-%c", c);
- if (!strncmp(text, s, len))
- return strdup(s);
- }
- }
-
- /* Long form arguments */
- if (match_no < com->num_args)
- match_no = com->num_args;
-
- while (match_no - com->num_args < com->num_args) {
- const char *l;
- l = (the_args +
- com->valid_args[match_no++ - com->num_args])->long_arg;
- if (*(l + 2) && !strncmp(text, l, len))
- return strdup(l);
- }
-
- return NULL;
-}
-
-/* Custom completion function */
-static char **_completion(const char *text, int start_pos, int end_pos)
-{
- char **match_list = NULL;
- int p = 0;
-
- while (isspace((int) *(rl_line_buffer + p)))
- p++;
-
- /* First word should be one of our commands */
- if (start_pos == p)
- match_list = rl_completion_matches(text, _list_cmds);
-
- else if (*text == '-')
- match_list = rl_completion_matches(text, _list_args);
- /* else other args */
-
- /* No further completion */
- rl_attempted_completion_over = 1;
- return match_list;
-}
-
-static int _hist_file(char *buffer, size_t size)
-{
- char *e = getenv("HOME");
-
- if (dm_snprintf(buffer, size, "%s/.lvm_history", e) < 0) {
- log_error("$HOME/.lvm_history: path too long");
- return 0;
- }
-
- return 1;
-}
-
-static void _read_history(struct cmd_context *cmd)
-{
- char hist_file[PATH_MAX];
-
- if (!_hist_file(hist_file, sizeof(hist_file)))
- return;
-
- if (read_history(hist_file))
- log_very_verbose("Couldn't read history from %s.", hist_file);
-
- stifle_history(find_config_tree_int(cmd, "shell/history_size",
- DEFAULT_MAX_HISTORY));
-
-}
-
-static void _write_history(void)
-{
- char hist_file[PATH_MAX];
-
- if (!_hist_file(hist_file, sizeof(hist_file)))
- return;
-
- if (write_history(hist_file))
- log_very_verbose("Couldn't write history to %s.", hist_file);
-}
-
-static int _shell(struct cmd_context *cmd)
-{
- int argc, ret;
- char *input = NULL, *args[MAX_ARGS], **argv;
-
- rl_readline_name = "lvm";
- rl_attempted_completion_function = (CPPFunction *) _completion;
-
- _read_history(cmd);
-
- _interactive = 1;
- while (1) {
- free(input);
- input = readline("lvm> ");
-
- /* EOF */
- if (!input) {
- printf("\n");
- break;
- }
+ if (fclose(script))
+ log_sys_error("fclose", script_file);
- /* empty line */
- if (!*input)
- continue;
-
- add_history(input);
-
- argv = args;
-
- if (lvm_split(input, &argc, argv, MAX_ARGS) == MAX_ARGS) {
- log_error("Too many arguments, sorry.");
- continue;
- }
-
- if (!strcmp(argv[0], "lvm")) {
- argv++;
- argc--;
- }
-
- if (!argc)
- continue;
-
- if (!strcmp(argv[0], "quit") || !strcmp(argv[0], "exit")) {
- remove_history(history_length - 1);
- log_error("Exiting.");
- break;
- }
-
- ret = lvm_run_command(cmd, argc, argv);
- if (ret == ENO_SUCH_CMD)
- log_error("No such command '%s'. Try 'help'.",
- argv[0]);
-
- _write_history();
- }
-
- free(input);
- return 0;
+ return ret;
}
-#endif
-
/*
* Determine whether we should fall back and exec the equivalent LVM1 tool
*/
@@ -1402,7 +1179,7 @@
}
#ifdef READLINE_SUPPORT
if (!alias && argc == 1) {
- ret = _shell(cmd);
+ ret = lvm_shell(cmd, &_cmdline);
goto out;
}
#endif
Modified: lvm2/trunk/tools/lvremove.c
==============================================================================
--- lvm2/trunk/tools/lvremove.c (original)
+++ lvm2/trunk/tools/lvremove.c Sat Apr 7 16:07:03 2007
@@ -75,6 +75,16 @@
if (!archive(vg))
return ECMD_FAILED;
+ /* If the VG is clustered then make sure no-one else is using the LV
+ we are about to remove */
+ if (vg->status & CLUSTERED) {
+ if (!activate_lv_excl(cmd, lv)) {
+ log_error("Can't get exclusive access to volume \"%s\"",
+ lv->name);
+ return ECMD_FAILED;
+ }
+ }
+
/* FIXME Snapshot commit out of sequence if it fails after here? */
if (!deactivate_lv(cmd, lv)) {
log_error("Unable to deactivate logical volume \"%s\"",
Modified: lvm2/trunk/tools/lvrename.c
==============================================================================
--- lvm2/trunk/tools/lvrename.c (original)
+++ lvm2/trunk/tools/lvrename.c Sat Apr 7 16:07:03 2007
@@ -29,7 +29,7 @@
struct lv_list *lvl;
if (argc == 3) {
- vg_name = skip_dev_dir(cmd, argv[0]);
+ vg_name = skip_dev_dir(cmd, argv[0], NULL);
lv_name_old = argv[1];
lv_name_new = argv[2];
if (strchr(lv_name_old, '/') &&
@@ -152,6 +152,14 @@
goto error;
}
+ if ((lv->status & MIRRORED) ||
+ (lv->status & MIRROR_LOG) ||
+ (lv->status & MIRROR_IMAGE)) {
+ log_error("Mirrored LV, \"%s\" cannot be renamed: %s",
+ lv->name, strerror(ENOSYS));
+ goto error;
+ }
+
if (!archive(lv->vg)) {
stack;
goto error;
Modified: lvm2/trunk/tools/pvchange.c
==============================================================================
--- lvm2/trunk/tools/pvchange.c (original)
+++ lvm2/trunk/tools/pvchange.c Sat Apr 7 16:07:03 2007
@@ -29,7 +29,7 @@
const char *pv_name = dev_name(pv->dev);
const char *tag = NULL;
const char *orig_vg_name;
- char uuid[64];
+ char uuid[64] __attribute((aligned(8)));
int consistent = 1;
int allocatable = 0;
Modified: lvm2/trunk/tools/pvmove.c
==============================================================================
--- lvm2/trunk/tools/pvmove.c (original)
+++ lvm2/trunk/tools/pvmove.c Sat Apr 7 16:07:03 2007
@@ -27,7 +27,7 @@
if (!strchr(arg, '/'))
return arg;
- lvname = skip_dev_dir(cmd, arg);
+ lvname = skip_dev_dir(cmd, arg, NULL);
while (*lvname == '/')
lvname++;
if (!strchr(lvname, '/')) {
Modified: lvm2/trunk/tools/pvremove.c
==============================================================================
--- lvm2/trunk/tools/pvremove.c (original)
+++ lvm2/trunk/tools/pvremove.c Sat Apr 7 16:07:03 2007
@@ -38,8 +38,8 @@
if (!(pv = pv_read(cmd, name, NULL, NULL, 1))) {
if (arg_count(cmd, force_ARG))
return 1;
- else
- return 0;
+ log_error("Physical Volume %s not found", name);
+ return 0;
}
/* orphan ? */
@@ -92,9 +92,9 @@
}
if (!dev_test_excl(dev)) {
- log_error("Can't open %s exclusively. Mounted filesystem?",
- dev_name(dev));
- return 0;
+ log_error("Can't open %s exclusively - not removing. "
+ "Mounted filesystem?", dev_name(dev));
+ goto error;
}
/* Wipe existing label(s) */
Modified: lvm2/trunk/tools/pvscan.c
==============================================================================
--- lvm2/trunk/tools/pvscan.c (original)
+++ lvm2/trunk/tools/pvscan.c Sat Apr 7 16:07:03 2007
@@ -22,7 +22,7 @@
struct physical_volume *pv,
void *handle __attribute((unused)))
{
- char uuid[64];
+ char uuid[64] __attribute((aligned(8)));
unsigned vg_name_len = 0;
char pv_tmp_name[NAME_LEN] = { 0, };
Modified: lvm2/trunk/tools/reporter.c
==============================================================================
--- lvm2/trunk/tools/reporter.c (original)
+++ lvm2/trunk/tools/reporter.c Sat Apr 7 16:07:03 2007
@@ -138,6 +138,30 @@
return ret;
}
+static int _pvs_in_vg(struct cmd_context *cmd, const char *vg_name,
+ struct volume_group *vg, int consistent,
+ void *handle)
+{
+ if (!vg) {
+ log_error("Volume group %s not found", vg_name);
+ return ECMD_FAILED;
+ }
+
+ return process_each_pv_in_vg(cmd, vg, NULL, handle, &_pvs_single);
+}
+
+static int _pvsegs_in_vg(struct cmd_context *cmd, const char *vg_name,
+ struct volume_group *vg, int consistent,
+ void *handle)
+{
+ if (!vg) {
+ log_error("Volume group %s not found", vg_name);
+ return ECMD_FAILED;
+ }
+
+ return process_each_pv_in_vg(cmd, vg, NULL, handle, &_pvsegs_single);
+}
+
static int _report(struct cmd_context *cmd, int argc, char **argv,
report_type_t report_type)
{
@@ -146,8 +170,8 @@
char *str;
const char *keys = NULL, *options = NULL, *separator;
int r = ECMD_PROCESSED;
-
int aligned, buffered, headings;
+ unsigned args_are_pvs;
aligned = find_config_tree_int(cmd, "report/aligned",
DEFAULT_REP_ALIGNED);
@@ -158,6 +182,8 @@
separator = find_config_tree_str(cmd, "report/separator",
DEFAULT_REP_SEPARATOR);
+ args_are_pvs = (report_type == PVS || report_type == PVSEGS) ? 1 : 0;
+
switch (report_type) {
case LVS:
keys = find_config_tree_str(cmd, "report/lvs_sort",
@@ -260,7 +286,28 @@
if (!(report_handle = report_init(cmd, options, keys, &report_type,
separator, aligned, buffered,
headings)))
+ return_0;
+
+ /* Ensure options selected are compatible */
+ if (report_type & SEGS)
+ report_type |= LVS;
+ if (report_type & PVSEGS)
+ report_type |= PVS;
+ if ((report_type & LVS) && (report_type & PVS)) {
+ log_error("Can't report LV and PV fields at the same time");
+ dm_report_free(report_handle);
return 0;
+ }
+
+ /* Change report type if fields specified makes this necessary */
+ if (report_type & SEGS)
+ report_type = SEGS;
+ else if (report_type & LVS)
+ report_type = LVS;
+ else if (report_type & PVSEGS)
+ report_type = PVSEGS;
+ else if (report_type & PVS)
+ report_type = PVS;
switch (report_type) {
case LVS:
@@ -272,22 +319,30 @@
report_handle, &_vgs_single);
break;
case PVS:
- r = process_each_pv(cmd, argc, argv, NULL, report_handle,
- &_pvs_single);
+ if (args_are_pvs)
+ r = process_each_pv(cmd, argc, argv, NULL,
+ report_handle, &_pvs_single);
+ else
+ r = process_each_vg(cmd, argc, argv, LCK_VG_READ, 0,
+ report_handle, &_pvs_in_vg);
break;
case SEGS:
r = process_each_lv(cmd, argc, argv, LCK_VG_READ, report_handle,
&_lvsegs_single);
break;
case PVSEGS:
- r = process_each_pv(cmd, argc, argv, NULL, report_handle,
- &_pvsegs_single);
+ if (args_are_pvs)
+ r = process_each_pv(cmd, argc, argv, NULL,
+ report_handle, &_pvsegs_single);
+ else
+ r = process_each_vg(cmd, argc, argv, LCK_VG_READ, 0,
+ report_handle, &_pvsegs_in_vg);
break;
}
- report_output(report_handle);
+ dm_report_output(report_handle);
- report_free(report_handle);
+ dm_report_free(report_handle);
return r;
}
Modified: lvm2/trunk/tools/toollib.c
==============================================================================
--- lvm2/trunk/tools/toollib.c (original)
+++ lvm2/trunk/tools/toollib.c Sat Apr 7 16:07:03 2007
@@ -88,21 +88,53 @@
/*
* Strip dev_dir if present
*/
-char *skip_dev_dir(struct cmd_context *cmd, const char *vg_name)
+char *skip_dev_dir(struct cmd_context *cmd, const char *vg_name,
+ unsigned *dev_dir_found)
{
- /* FIXME Do this properly */
+ const char *dmdir = dm_dir();
+ size_t dmdir_len = strlen(dmdir), vglv_sz;
+ char *vgname, *lvname, *layer, *vglv;
+ /* FIXME Do this properly */
if (*vg_name == '/') {
while (*vg_name == '/')
vg_name++;
vg_name--;
}
+ /* Reformat string if /dev/mapper found */
+ if (!strncmp(vg_name, dmdir, dmdir_len) && vg_name[dmdir_len] == '/') {
+ if (dev_dir_found)
+ *dev_dir_found = 1;
+ vg_name += dmdir_len;
+ while (*vg_name == '/')
+ vg_name++;
+
+ if (!dm_split_lvm_name(cmd->mem, vg_name, &vgname, &lvname, &layer) ||
+ *layer) {
+ log_error("skip_dev_dir: Couldn't split up device name %s",
+ vg_name);
+ return (char *) vg_name;
+ }
+ vglv_sz = strlen(vgname) + strlen(lvname) + 2;
+ if (!(vglv = dm_pool_alloc(cmd->mem, vglv_sz)) ||
+ dm_snprintf(vglv, vglv_sz, "%s%s%s", vgname,
+ *lvname ? "/" : "",
+ lvname) < 0) {
+ log_error("vg/lv string alloc failed");
+ return (char *) vg_name;
+ }
+ return vglv;
+ }
+
if (!strncmp(vg_name, cmd->dev_dir, strlen(cmd->dev_dir))) {
+ if (dev_dir_found)
+ *dev_dir_found = 1;
vg_name += strlen(cmd->dev_dir);
while (*vg_name == '/')
vg_name++;
- }
+ } else if (dev_dir_found)
+ *dev_dir_found = 0;
return (char *) vg_name;
}
@@ -222,7 +254,7 @@
for (; opt < argc; opt++) {
const char *lv_name = argv[opt];
char *vgname_def;
- int dev_dir_found = 0;
+ unsigned dev_dir_found = 0;
/* Do we have a tag or vgname or lvname? */
vgname = lv_name;
@@ -243,18 +275,8 @@
}
/* FIXME Jumbled parsing */
- if (*vgname == '/') {
- while (*vgname == '/')
- vgname++;
- vgname--;
- }
- if (!strncmp(vgname, cmd->dev_dir,
- strlen(cmd->dev_dir))) {
- vgname += strlen(cmd->dev_dir);
- dev_dir_found = 1;
- while (*vgname == '/')
- vgname++;
- }
+ vgname = skip_dev_dir(cmd, vgname, &dev_dir_found);
+
if (*vgname == '/') {
log_error("\"%s\": Invalid path for Logical "
"Volume", argv[opt]);
@@ -528,7 +550,7 @@
continue;
}
- vg_name = skip_dev_dir(cmd, vg_name);
+ vg_name = skip_dev_dir(cmd, vg_name, NULL);
if (strchr(vg_name, '/')) {
log_error("Invalid volume group name: %s",
vg_name);
@@ -830,7 +852,7 @@
if (!vg_path)
return 0;
- vg_path = skip_dev_dir(cmd, vg_path);
+ vg_path = skip_dev_dir(cmd, vg_path, NULL);
if (strchr(vg_path, '/')) {
log_error("Environment Volume Group in LVM_VG_NAME invalid: "
@@ -844,23 +866,24 @@
/*
* Process physical extent range specifiers
*/
-static int _add_pe_range(struct dm_pool *mem, struct list *pe_ranges,
- uint32_t start, uint32_t count)
+static int _add_pe_range(struct dm_pool *mem, const char *pvname,
+ struct list *pe_ranges, uint32_t start, uint32_t count)
{
struct pe_range *per;
- log_debug("Adding PE range: start PE %" PRIu32 " length %" PRIu32,
- start, count);
+ log_debug("Adding PE range: start PE %" PRIu32 " length %" PRIu32
+ " on %s", start, count, pvname);
/* Ensure no overlap with existing areas */
list_iterate_items(per, pe_ranges) {
if (((start < per->start) && (start + count - 1 >= per->start))
|| ((start >= per->start) &&
(per->start + per->count - 1) >= start)) {
- log_error("Overlapping PE ranges detected (%" PRIu32
- "-%" PRIu32 ", %" PRIu32 "-%" PRIu32 ")",
+ log_error("Overlapping PE ranges specified (%" PRIu32
+ "-%" PRIu32 ", %" PRIu32 "-%" PRIu32 ")"
+ " on %s",
start, start + count - 1, per->start,
- per->start + per->count - 1);
+ per->start + per->count - 1, pvname);
return 0;
}
}
@@ -878,14 +901,14 @@
}
static int _parse_pes(struct dm_pool *mem, char *c, struct list *pe_ranges,
- uint32_t size)
+ const char *pvname, uint32_t size)
{
char *endptr;
uint32_t start, end;
/* Default to whole PV */
if (!c) {
- if (!_add_pe_range(mem, pe_ranges, UINT32_C(0), size)) {
+ if (!_add_pe_range(mem, pvname, pe_ranges, UINT32_C(0), size)) {
stack;
return 0;
}
@@ -935,7 +958,7 @@
return 0;
}
- if (!_add_pe_range(mem, pe_ranges, start, end - start + 1)) {
+ if (!_add_pe_range(mem, pvname, pe_ranges, start, end - start + 1)) {
stack;
return 0;
}
@@ -949,46 +972,56 @@
return 0;
}
-static void _create_pv_entry(struct dm_pool *mem, struct pv_list *pvl,
+static int _create_pv_entry(struct dm_pool *mem, struct pv_list *pvl,
char *colon, int allocatable_only, struct list *r)
{
const char *pvname;
- struct pv_list *new_pvl;
+ struct pv_list *new_pvl = NULL, *pvl2;
struct list *pe_ranges;
pvname = dev_name(pvl->pv->dev);
if (allocatable_only && !(pvl->pv->status & ALLOCATABLE_PV)) {
log_error("Physical volume %s not allocatable", pvname);
- return;
+ return 1;
}
if (allocatable_only &&
(pvl->pv->pe_count == pvl->pv->pe_alloc_count)) {
log_err("No free extents on physical volume \"%s\"", pvname);
- return;
+ return 1;
}
- if (!(new_pvl = dm_pool_alloc(mem, sizeof(*new_pvl)))) {
- log_err("Unable to allocate physical volume list.");
- return;
- }
+ list_iterate_items(pvl2, r)
+ if (pvl->pv->dev == pvl2->pv->dev) {
+ new_pvl = pvl2;
+ break;
+ }
+
+ if (!new_pvl) {
+ if (!(new_pvl = dm_pool_alloc(mem, sizeof(*new_pvl)))) {
+ log_err("Unable to allocate physical volume list.");
+ return 0;
+ }
- memcpy(new_pvl, pvl, sizeof(*new_pvl));
+ memcpy(new_pvl, pvl, sizeof(*new_pvl));
- if (!(pe_ranges = dm_pool_alloc(mem, sizeof(*pe_ranges)))) {
- log_error("Allocation of pe_ranges list failed");
- return;
+ if (!(pe_ranges = dm_pool_alloc(mem, sizeof(*pe_ranges)))) {
+ log_error("Allocation of pe_ranges list failed");
+ return 0;
+ }
+ list_init(pe_ranges);
+ new_pvl->pe_ranges = pe_ranges;
+ list_add(r, &new_pvl->list);
}
- list_init(pe_ranges);
/* Determine selected physical extents */
- if (!_parse_pes(mem, colon, pe_ranges, pvl->pv->pe_count)) {
+ if (!_parse_pes(mem, colon, new_pvl->pe_ranges, dev_name(pvl->pv->dev),
+ pvl->pv->pe_count)) {
stack;
- return;
+ return 0;
}
- new_pvl->pe_ranges = pe_ranges;
- list_add(r, &new_pvl->list);
+ return 1;
}
struct list *create_pv_list(struct dm_pool *mem, struct volume_group *vg, int argc,
@@ -1021,8 +1054,12 @@
list_iterate_items(pvl, &vg->pvs) {
if (str_list_match_item(&pvl->pv->tags,
tagname)) {
- _create_pv_entry(mem, pvl, NULL,
- allocatable_only, r);
+ if (!_create_pv_entry(mem, pvl, NULL,
+ allocatable_only,
+ r)) {
+ stack;
+ return NULL;
+ }
}
}
continue;
@@ -1044,7 +1081,10 @@
"Volume Group \"%s\"", pvname, vg->name);
return NULL;
}
- _create_pv_entry(mem, pvl, colon, allocatable_only, r);
+ if (!_create_pv_entry(mem, pvl, colon, allocatable_only, r)) {
+ stack;
+ return NULL;
+ }
}
if (list_empty(r))
@@ -1170,7 +1210,8 @@
/*
* Initialize the LV with 'value'.
*/
-int set_lv(struct cmd_context *cmd, struct logical_volume *lv, int value)
+int set_lv(struct cmd_context *cmd, struct logical_volume *lv,
+ uint64_t sectors, int value)
{
struct device *dev;
char *name;
@@ -1203,7 +1244,10 @@
if (!dev_open_quiet(dev))
return 0;
- dev_set(dev, UINT64_C(0), (size_t) 4096, value);
+ dev_set(dev, UINT64_C(0),
+ sectors ? (size_t) sectors << SECTOR_SHIFT : (size_t) 4096,
+ value);
+ dev_flush(dev);
dev_close_immediate(dev);
return 1;
@@ -1317,7 +1361,8 @@
goto error;
}
- if (activation() && !set_lv(cmd, log_lv, in_sync)) {
+ if (activation() && !set_lv(cmd, log_lv, log_lv->size,
+ in_sync ? -1 : 0)) {
log_error("Aborting. Failed to wipe mirror log. "
"Remove new LV and retry.");
goto error;
Modified: lvm2/trunk/tools/toollib.h
==============================================================================
--- lvm2/trunk/tools/toollib.h (original)
+++ lvm2/trunk/tools/toollib.h Sat Apr 7 16:07:03 2007
@@ -76,7 +76,8 @@
char *default_vgname(struct cmd_context *cmd);
const char *extract_vgname(struct cmd_context *cmd, const char *lv_name);
-char *skip_dev_dir(struct cmd_context *cmd, const char *vg_name);
+char *skip_dev_dir(struct cmd_context *cmd, const char *vg_name,
+ unsigned *dev_dir_found);
/*
* Builds a list of pv's from the names in argv. Used in
@@ -101,6 +102,7 @@
const char *lv_name,
int in_sync);
-int set_lv(struct cmd_context *cmd, struct logical_volume *lv, int value);
+int set_lv(struct cmd_context *cmd, struct logical_volume *lv,
+ uint64_t sectors, int value);
#endif
Modified: lvm2/trunk/tools/vgcfgrestore.c
==============================================================================
--- lvm2/trunk/tools/vgcfgrestore.c (original)
+++ lvm2/trunk/tools/vgcfgrestore.c Sat Apr 7 16:07:03 2007
@@ -24,7 +24,7 @@
return ECMD_FAILED;
}
- vg_name = skip_dev_dir(cmd, argv[0]);
+ vg_name = skip_dev_dir(cmd, argv[0], NULL);
if (!validate_name(vg_name)) {
log_error("Volume group name \"%s\" is invalid", vg_name);
Modified: lvm2/trunk/tools/vgchange.c
==============================================================================
--- lvm2/trunk/tools/vgchange.c (original)
+++ lvm2/trunk/tools/vgchange.c Sat Apr 7 16:07:03 2007
@@ -15,7 +15,7 @@
#include "tools.h"
-static int _register_lvs_in_vg(struct cmd_context *cmd,
+static int _monitor_lvs_in_vg(struct cmd_context *cmd,
struct volume_group *vg, int reg)
{
struct lv_list *lvl;
@@ -23,7 +23,6 @@
struct lvinfo info;
int lv_active;
int count = 0;
- int r;
list_iterate_items(lvl, &vg->lvs) {
lv = lvl->lv;
@@ -39,22 +38,14 @@
if ((lv->status & PVMOVE) || !lv_active)
continue;
- r = register_dev_for_events(cmd, lv, reg);
-
- if (r < 0) {
- log_error("Failed to %s logical volume, %s",
- (reg) ? "register" : "unregister",
- lv->name);
+ if (!monitor_dev_for_events(cmd, lv, reg)) {
continue;
- }
-
- if (r)
+ } else
count++;
}
/*
- * returns the number of monitored devices, not the number
- * of _new_ monitored devices
+ * returns the number of _new_ monitored devices
*/
return count;
@@ -114,11 +105,12 @@
{
int active, monitored;
- if ((active = lvs_in_vg_activated(vg))) {
- monitored = _register_lvs_in_vg(cmd, vg, dmeventd_register_mode());
+ if ((active = lvs_in_vg_activated(vg)) &&
+ dmeventd_monitor_mode() != DMEVENTD_MONITOR_IGNORE) {
+ monitored = _monitor_lvs_in_vg(cmd, vg, dmeventd_monitor_mode());
log_print("%d logical volume(s) in volume group "
- "\"%s\" now %smonitored",
- monitored, vg->name, (dmeventd_register_mode()) ? "" : "un");
+ "\"%s\" %smonitored",
+ monitored, vg->name, (dmeventd_monitor_mode()) ? "" : "un");
}
return ECMD_PROCESSED;
@@ -155,11 +147,13 @@
if (activate && (active = lvs_in_vg_activated(vg))) {
log_verbose("%d logical volume(s) in volume group \"%s\" "
"already active", active, vg->name);
- monitored = _register_lvs_in_vg(cmd, vg, dmeventd_register_mode());
- log_verbose("%d existing logical volume(s) in volume "
- "group \"%s\" now %smonitored",
- monitored, vg->name,
- dmeventd_register_mode() ? "" : "un");
+ if (dmeventd_monitor_mode() != DMEVENTD_MONITOR_IGNORE) {
+ monitored = _monitor_lvs_in_vg(cmd, vg, dmeventd_monitor_mode());
+ log_verbose("%d existing logical volume(s) in volume "
+ "group \"%s\" %smonitored",
+ monitored, vg->name,
+ dmeventd_monitor_mode() ? "" : "un");
+ }
}
if (activate && _activate_lvs_in_vg(cmd, vg, available))
@@ -541,7 +535,9 @@
return ECMD_FAILED;
}
- init_dmeventd_register(arg_int_value(cmd, monitor_ARG, DEFAULT_DMEVENTD_MONITOR));
+ init_dmeventd_monitor(arg_int_value(cmd, monitor_ARG,
+ cmd->is_static ?
+ DMEVENTD_MONITOR_IGNORE : DEFAULT_DMEVENTD_MONITOR));
if (arg_count(cmd, available_ARG))
r = _vgchange_available(cmd, vg);
Modified: lvm2/trunk/tools/vgcreate.c
==============================================================================
--- lvm2/trunk/tools/vgcreate.c (original)
+++ lvm2/trunk/tools/vgcreate.c Sat Apr 7 16:07:03 2007
@@ -38,7 +38,7 @@
return EINVALID_CMD_LINE;
}
- vg_name = skip_dev_dir(cmd, argv[0]);
+ vg_name = skip_dev_dir(cmd, argv[0], NULL);
max_lv = arg_uint_value(cmd, maxlogicalvolumes_ARG, 0);
max_pv = arg_uint_value(cmd, maxphysicalvolumes_ARG, 0);
alloc = arg_uint_value(cmd, alloc_ARG, ALLOC_NORMAL);
Modified: lvm2/trunk/tools/vgextend.c
==============================================================================
--- lvm2/trunk/tools/vgextend.c (original)
+++ lvm2/trunk/tools/vgextend.c Sat Apr 7 16:07:03 2007
@@ -32,7 +32,7 @@
return EINVALID_CMD_LINE;
}
- vg_name = skip_dev_dir(cmd, argv[0]);
+ vg_name = skip_dev_dir(cmd, argv[0], NULL);
argc--;
argv++;
@@ -41,6 +41,12 @@
return ECMD_FAILED;
}
+ if (!validate_name(vg_name)) {
+ log_error("Volume group name \"%s\" is invalid",
+ vg_name);
+ return ECMD_FAILED;
+ }
+
log_verbose("Checking for volume group \"%s\"", vg_name);
if (!lock_vol(cmd, vg_name, LCK_VG_WRITE | LCK_NONBLOCK)) {
unlock_vg(cmd, ORPHAN);
Modified: lvm2/trunk/tools/vgmerge.c
==============================================================================
--- lvm2/trunk/tools/vgmerge.c (original)
+++ lvm2/trunk/tools/vgmerge.c Sat Apr 7 16:07:03 2007
@@ -176,7 +176,7 @@
/* Fix up LVIDs */
list_iterate_items(lvl1, &vg_to->lvs) {
union lvid *lvid1 = &lvl1->lv->lvid;
- char uuid[64];
+ char uuid[64] __attribute((aligned(8)));
list_iterate_items(lvl2, &vg_from->lvs) {
union lvid *lvid2 = &lvl2->lv->lvid;
@@ -253,12 +253,12 @@
return EINVALID_CMD_LINE;
}
- vg_name_to = skip_dev_dir(cmd, argv[0]);
+ vg_name_to = skip_dev_dir(cmd, argv[0], NULL);
argc--;
argv++;
for (; opt < argc; opt++) {
- vg_name_from = skip_dev_dir(cmd, argv[opt]);
+ vg_name_from = skip_dev_dir(cmd, argv[opt], NULL);
ret = _vgmerge_single(cmd, vg_name_to, vg_name_from);
if (ret > ret_max)
Modified: lvm2/trunk/tools/vgreduce.c
==============================================================================
--- lvm2/trunk/tools/vgreduce.c (original)
+++ lvm2/trunk/tools/vgreduce.c Sat Apr 7 16:07:03 2007
@@ -18,7 +18,7 @@
static int _remove_pv(struct volume_group *vg, struct pv_list *pvl)
{
- char uuid[64];
+ char uuid[64] __attribute((aligned(8)));
if (vg->pv_count == 1) {
log_error("Volume Groups must always contain at least one PV");
@@ -347,7 +347,9 @@
list_iterate_items(lvl, &lvs_changed) {
log_verbose("Removing LV %s from VG %s", lvl->lv->name,
lvl->lv->vg->name);
- if (!lv_remove(lvl->lv)) {
+ /* Skip LVs already removed by mirror code */
+ if (find_lv_in_vg(vg, lvl->lv->name) &&
+ !lv_remove(lvl->lv)) {
stack;
return 0;
}
@@ -425,13 +427,13 @@
int ret = 1;
int consistent = 1;
- if (!argc & !arg_count(cmd, removemissing_ARG)) {
+ if (!argc && !arg_count(cmd, removemissing_ARG)) {
log_error("Please give volume group name and "
"physical volume paths");
return EINVALID_CMD_LINE;
}
- if (!argc & arg_count(cmd, removemissing_ARG)) {
+ if (!argc && arg_count(cmd, removemissing_ARG)) {
log_error("Please give volume group name");
return EINVALID_CMD_LINE;
}
@@ -459,10 +461,16 @@
return EINVALID_CMD_LINE;
}
- vg_name = skip_dev_dir(cmd, argv[0]);
+ vg_name = skip_dev_dir(cmd, argv[0], NULL);
argv++;
argc--;
+ if (!validate_name(vg_name)) {
+ log_error("Volume group name \"%s\" is invalid",
+ vg_name);
+ return ECMD_FAILED;
+ }
+
log_verbose("Finding volume group \"%s\"", vg_name);
if (!lock_vol(cmd, vg_name, LCK_VG_WRITE)) {
log_error("Can't get lock for %s", vg_name);
Modified: lvm2/trunk/tools/vgremove.c
==============================================================================
--- lvm2/trunk/tools/vgremove.c (original)
+++ lvm2/trunk/tools/vgremove.c Sat Apr 7 16:07:03 2007
@@ -87,6 +87,11 @@
{
int ret;
+ if (!argc) {
+ log_error("Please enter one or more volume group paths");
+ return EINVALID_CMD_LINE;
+ }
+
if (!lock_vol(cmd, ORPHAN, LCK_VG_WRITE)) {
log_error("Can't get lock for orphan PVs");
return ECMD_FAILED;
Modified: lvm2/trunk/tools/vgrename.c
==============================================================================
--- lvm2/trunk/tools/vgrename.c (original)
+++ lvm2/trunk/tools/vgrename.c Sat Apr 7 16:07:03 2007
@@ -35,8 +35,8 @@
return EINVALID_CMD_LINE;
}
- vg_name_old = skip_dev_dir(cmd, argv[0]);
- vg_name_new = skip_dev_dir(cmd, argv[1]);
+ vg_name_old = skip_dev_dir(cmd, argv[0], NULL);
+ vg_name_new = skip_dev_dir(cmd, argv[1], NULL);
dev_dir = cmd->dev_dir;
length = strlen(dev_dir);
@@ -118,7 +118,7 @@
return ECMD_FAILED;
}
- if (lvs_in_vg_activated(vg_old)) {
+ if (lvs_in_vg_activated_by_uuid_only(vg_old)) {
unlock_vg(cmd, vg_name_old);
log_error("Volume group \"%s\" still has active LVs",
vg_name_old);
Modified: lvm2/trunk/tools/vgsplit.c
==============================================================================
--- lvm2/trunk/tools/vgsplit.c (original)
+++ lvm2/trunk/tools/vgsplit.c Sat Apr 7 16:07:03 2007
@@ -72,6 +72,9 @@
if ((lv->status & SNAPSHOT))
continue;
+ if ((lv->status & MIRRORED))
+ continue;
+
/* Ensure all the PVs used by this LV remain in the same */
/* VG as each other */
vg_with = NULL;
@@ -84,9 +87,9 @@
pv = seg_pv(seg, s);
if (vg_with) {
if (!pv_is_in_vg(vg_with, pv)) {
- log_error("Logical Volume %s "
- "split between "
- "Volume Groups",
+ log_error("Can't split Logical "
+ "Volume %s between "
+ "two Volume Groups",
lv->name);
return 0;
}
@@ -161,6 +164,48 @@
return 1;
}
+static int _move_mirrors(struct volume_group *vg_from,
+ struct volume_group *vg_to)
+{
+ struct list *lvh, *lvht;
+ struct logical_volume *lv;
+ struct lv_segment *seg;
+ int i, seg_in, log_in;
+
+ list_iterate_safe(lvh, lvht, &vg_from->lvs) {
+ lv = list_item(lvh, struct lv_list)->lv;
+
+ if (!(lv->status & MIRRORED))
+ continue;
+
+ seg = first_seg(lv);
+
+ seg_in = 0;
+ for (i = 0; i < seg->area_count; i++)
+ if (_lv_is_in_vg(vg_to, seg_lv(seg, i)))
+ seg_in++;
+
+ log_in = (!seg->log_lv || _lv_is_in_vg(vg_to, seg->log_lv));
+
+ if ((seg_in && seg_in < seg->area_count) ||
+ (seg_in && seg->log_lv && !log_in) ||
+ (!seg_in && seg->log_lv && log_in)) {
+ log_error("Mirror %s split", lv->name);
+ return 0;
+ }
+
+ if (seg_in == seg->area_count && log_in) {
+ list_del(lvh);
+ list_add(&vg_to->lvs, lvh);
+
+ vg_from->lv_count--;
+ vg_to->lv_count++;
+ }
+ }
+
+ return 1;
+}
+
int vgsplit(struct cmd_context *cmd, int argc, char **argv)
{
char *vg_name_from, *vg_name_to;
@@ -174,11 +219,17 @@
return EINVALID_CMD_LINE;
}
- vg_name_from = argv[0];
- vg_name_to = argv[1];
+ vg_name_from = skip_dev_dir(cmd, argv[0], NULL);
+ vg_name_to = skip_dev_dir(cmd, argv[1], NULL);
argc -= 2;
argv += 2;
+ if (!validate_name(vg_name_from)) {
+ log_error("Volume group name \"%s\" is invalid",
+ vg_name_from);
+ return ECMD_FAILED;
+ }
+
if (!strcmp(vg_name_to, vg_name_from)) {
log_error("Duplicate volume group name \"%s\"", vg_name_from);
return ECMD_FAILED;
@@ -275,6 +326,10 @@
if (!(_move_snapshots(vg_from, vg_to)))
goto error;
+ /* Move required mirrors across */
+ if (!(_move_mirrors(vg_from, vg_to)))
+ goto error;
+
/* FIXME Split mdas properly somehow too! */
/* Currently we cheat by sharing the format instance and relying on
* vg_write to ignore mdas outside the VG! Done this way, with text
More information about the pkg-lvm-commits
mailing list