mirror of
git://sourceware.org/git/lvm2.git
synced 2025-09-26 01:44:19 +03:00
Compare commits
133 Commits
old-v1_00_
...
v1_00_18
Author | SHA1 | Date | |
---|---|---|---|
|
9812657777 | ||
|
0b09312fc6 | ||
|
d0a7ac6b74 | ||
|
ff9a238fbd | ||
|
359fffa5f1 | ||
|
5bf92ced1a | ||
|
340bcc7b45 | ||
|
ef03742bd4 | ||
|
20431ec16d | ||
|
becba8157b | ||
|
51fd3bb0eb | ||
|
4bbd3acb4e | ||
|
3bc930ea7b | ||
|
d1b26f8e86 | ||
|
fdf15caaff | ||
|
c7b4a53c0b | ||
|
af78dc0308 | ||
|
5ad39493c4 | ||
|
61f597b408 | ||
|
2162825240 | ||
|
2b780e70d1 | ||
|
a3823f818e | ||
|
1f7c47bcaf | ||
|
ec53c365a2 | ||
|
793ad1f2d4 | ||
|
9bc733b76c | ||
|
21b28f0217 | ||
|
d3e23caa52 | ||
|
9e7518de67 | ||
|
679f0047aa | ||
|
d77d5ce14b | ||
|
33ec22a2af | ||
|
353053225f | ||
|
b7f3d6f7f7 | ||
|
e34577499d | ||
|
4cf8960c0c | ||
|
1f93ea0675 | ||
|
25b705c3a8 | ||
|
0725588731 | ||
|
fc5c61cc8b | ||
|
ac282e63c6 | ||
|
c3941941ce | ||
|
46cdd53323 | ||
|
3ff3e302c3 | ||
|
f2ceecf95c | ||
|
9314c7c881 | ||
|
54abb2c572 | ||
|
8fa3bdd025 | ||
|
5e7a308528 | ||
|
7952177786 | ||
|
9afbe49c84 | ||
|
9f06ba2db3 | ||
|
fe55bfddcf | ||
|
c0842e6444 | ||
|
3fed20d06a | ||
|
5e8f2e2c04 | ||
|
e4df99ea84 | ||
|
b3276f5f11 | ||
|
32667ca256 | ||
|
bed122a170 | ||
|
14adc9b875 | ||
|
a8778bbc5a | ||
|
a54e641f44 | ||
|
5c99efe87a | ||
|
7da1d731ff | ||
|
af9828e819 | ||
|
7a27136142 | ||
|
012ad2d423 | ||
|
ef3bdbf4da | ||
|
b3bb698f7b | ||
|
1ed5d1e4c1 | ||
|
bdee01a03d | ||
|
458f7376d7 | ||
|
cb3a00e027 | ||
|
482eb1f3fb | ||
|
6e0f638f5e | ||
|
bab349047d | ||
|
28ea6b8de8 | ||
|
9d51bbdae8 | ||
|
d622f79533 | ||
|
04c8515ad1 | ||
|
53bc4251d1 | ||
|
a5a751f02f | ||
|
66ed5f82c4 | ||
|
c802a9e6aa | ||
|
880f210946 | ||
|
4f9f7eb6a6 | ||
|
f910c4a8e7 | ||
|
529686d965 | ||
|
84dfd1536f | ||
|
85dedc324c | ||
|
d639237411 | ||
|
449aaf75f1 | ||
|
b1fda66caa | ||
|
66a8e90fd9 | ||
|
37b487d191 | ||
|
6c59fe3577 | ||
|
1cbb70c992 | ||
|
e06b39f882 | ||
|
2602b1493e | ||
|
989d14502d | ||
|
f78a550282 | ||
|
54a1abb284 | ||
|
97b492a8e2 | ||
|
0873bd14a9 | ||
|
eff6ba429a | ||
|
8c18064be4 | ||
|
44a1ac0cf3 | ||
|
28dc8d88dd | ||
|
2c0c2b64ba | ||
|
bd3e0f5248 | ||
|
cd52d98938 | ||
|
894c70e7f8 | ||
|
51d70c2edd | ||
|
7d4b355240 | ||
|
3b56193b98 | ||
|
b16045b57d | ||
|
9e8b0fca5b | ||
|
35cf1b3b5b | ||
|
83f788af57 | ||
|
2ffe378d3f | ||
|
38b33a4a5e | ||
|
60bf9ed0a0 | ||
|
16adf4de1b | ||
|
80de983023 | ||
|
8703ca623f | ||
|
286253a73f | ||
|
bd806a41df | ||
|
b89c4e9002 | ||
|
6dbf31c0c3 | ||
|
060c45d8a1 | ||
|
33d3e82e4d | ||
|
4bb074514d |
27
Makefile.in
27
Makefile.in
@@ -1,26 +1,22 @@
|
||||
#
|
||||
# Copyright (C) 2001 Sistina Software
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This LVM library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Library General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2 of the License, or (at your option) any later version.
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This LVM library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Library General Public License for more details.
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU Library General Public
|
||||
# License along with this LVM library; if not, write to the Free
|
||||
# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
# MA 02111-1307, USA
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
SUBDIRS = include man
|
||||
SUBDIRS = doc include man
|
||||
|
||||
ifeq ("@INTL@", "yes")
|
||||
SUBDIRS += po
|
||||
@@ -30,6 +26,9 @@ SUBDIRS += lib tools
|
||||
|
||||
ifeq ($(MAKECMDGOALS),distclean)
|
||||
SUBDIRS += lib/format1 \
|
||||
lib/format_pool \
|
||||
lib/mirror \
|
||||
lib/snapshot \
|
||||
po \
|
||||
test/mm test/device test/format1 test/regex test/filters
|
||||
endif
|
||||
|
109
WHATS_NEW
109
WHATS_NEW
@@ -1,3 +1,112 @@
|
||||
Version 2.00.17 -
|
||||
=============================
|
||||
Add read-only GFS pool support.
|
||||
Add lvm2create_initrd script from http://poochiereds.net/svn/lvm2/
|
||||
Fix rounding of large diplayed sizes.
|
||||
Suppress decimal point when using units of sectors/bytes.
|
||||
Additional kernel target checks before pvmove & snapshot creation.
|
||||
Add i2o_block.
|
||||
|
||||
Version 2.00.16 - 24 May 2004
|
||||
=============================
|
||||
Set area_count within alloc_lv_segment.
|
||||
Remove error labels from lvresize.
|
||||
Fix a pvs error path.
|
||||
xxchange -ae for exclusive activation.
|
||||
Don't return non-zero status if there aren't any volume groups.
|
||||
Add --alloc argument to tools.
|
||||
Rename allocation policies to contiguous, normal, anywhere, inherit.
|
||||
nextfree becomes normal; anywhere isn't implemented yet.
|
||||
LV inherits allocation policy from VG. Defaults: LV - inherit; VG - normal
|
||||
Additional status character added to vgs to indicate allocation policy.
|
||||
Add reset_fn to external_locking.
|
||||
Ensure presence of virtual targets before attempting activating.
|
||||
Attempt to fix resizing of snapshot origins.
|
||||
Restructure lvresize, bringing it closer to lvcreate.
|
||||
A quick sanity check on vg_disk struct when read in. More checks needed.
|
||||
Only include visible LVs in active/open counts.
|
||||
Add virtual segment types, zero and error. A large sparse device can be
|
||||
constructed as a writeable snapshot of a large zero segment.
|
||||
Add --type to lvcreate/resize.
|
||||
Push lv_create & alloc policy up to tool level.
|
||||
Fix pvdisplay return code.
|
||||
Detect invalid LV names in arg lists.
|
||||
Reporting uses line-at-a-time output.
|
||||
lvm2 format sets unlimited_vols format flag.
|
||||
Internal-only metadata flag support.
|
||||
Basic checking for presence of device-mapper targets.
|
||||
Separate out polldaemon.
|
||||
Revise internal locking semantics.
|
||||
Move find_pv_by_name to library.
|
||||
Rename move->copy.
|
||||
Add devices to segments report.
|
||||
Begin separating out segment code. There's a lot of change here.
|
||||
Compress any (obsolete) long LVM1 pvids encountered.
|
||||
Support for tagged config files.
|
||||
Don't abort operations if selinux present but disabled.
|
||||
Fix typo in configure which left HAVE_LIBDL unset.
|
||||
|
||||
Version 2.00.15 - 19 Apr 2004
|
||||
=============================
|
||||
configure --with-owner= --with-group= to avoid -o and -g args to 'install'
|
||||
|
||||
Version 2.00.14 - 16 Apr 2004
|
||||
=============================
|
||||
Use 64-bit file functions by default.
|
||||
|
||||
Version 2.00.13 - 16 Apr 2004
|
||||
=============================
|
||||
Set devices/md_component_detection = 1 to ignore devices containing md
|
||||
superblocks. [Luca Berra]
|
||||
Ignore error setting selinux file context if fs doesn't support it.
|
||||
|
||||
Version 2.00.12 - 14 Apr 2004
|
||||
=============================
|
||||
Install a default lvm.conf into /etc/lvm if there isn't one already.
|
||||
Allow different installation dir for lvm.static (configure --staticdir=)
|
||||
Fix inverted selinux error check.
|
||||
Recognise power2 in /proc/devices.
|
||||
Fix counting in lvs_in_vg_opened. [It ignored devices open more than once.]
|
||||
|
||||
Version 2.00.11 - 8 Apr 2004
|
||||
============================
|
||||
Set fallback_to_lvm1 in lvm.conf (or configure --enable-lvm1_fallback)
|
||||
to run lvm1 binaries if running a 2.4 kernel without device-mapper.
|
||||
|
||||
Version 2.00.10 - 7 Apr 2004
|
||||
============================
|
||||
More fixes for static build.
|
||||
Add basic selinux support.
|
||||
Fix sysfs detection.
|
||||
|
||||
Version 2.00.09 - 31 Mar 2004
|
||||
=============================
|
||||
Update copyright notices for Red Hat.
|
||||
Fix vgmknodes to remove dud /dev/mapper entries. (libdevmapper update reqd).
|
||||
Add LVM1-style colon output to vgdisplay.
|
||||
lvchange --refresh to reload active LVs.
|
||||
Add string display to memory leak dump.
|
||||
Add locking flags & memlock option.
|
||||
Add list_versions to library.
|
||||
Ignore open hidden LVs when checking if deactivation is OK.
|
||||
Suppress move percentage when device inactive.
|
||||
Add lv_info_by_lvid.
|
||||
Various tidy-ups to the build process.
|
||||
Rebaseline internal verbose level.
|
||||
Add --nolocking option for read operations if locking is failing.
|
||||
Add option to compile into a library.
|
||||
When compiled without libdevmapper, only print warning message once.
|
||||
Fix lvreduce PV extent calculations.
|
||||
Fix DESTDIR to work with configure path overrides.
|
||||
Always use / as config file separator & rename internal config file variables.
|
||||
Add support for tagging PV/VG/LVs and hosts.
|
||||
Fix rare bug in recognition of long cmdline argument forms.
|
||||
Add basic internationalisation infrastructure.
|
||||
Don't recurse symlinked dirs such as /dev/fd on 2.6 kernels.
|
||||
Update autoconf files.
|
||||
Add sysfs block device filtering for 2.6 kernels.
|
||||
Update refs for move to sources.redhat.com.
|
||||
|
||||
Friday 14th November 2003
|
||||
=========================
|
||||
Some bug fixes & minor enhancements, including:
|
||||
|
63
WHATS_NEW_DM
Normal file
63
WHATS_NEW_DM
Normal file
@@ -0,0 +1,63 @@
|
||||
Version 1.00.18
|
||||
=============================
|
||||
Add target message-passing ioctl.
|
||||
|
||||
Version 1.00.17 - 17 Apr 2004
|
||||
=============================
|
||||
configure --with-owner= --with-group= to avoid -o and -g args to 'install'
|
||||
Fix library selinux linking.
|
||||
|
||||
Version 1.00.16 - 16 Apr 2004
|
||||
=============================
|
||||
Ignore error setting selinux file context if fs doesn't support it.
|
||||
|
||||
Version 1.00.15 - 7 Apr 2004
|
||||
============================
|
||||
Fix status overflow check in kernel patches.
|
||||
|
||||
Version 1.00.14 - 6 Apr 2004
|
||||
============================
|
||||
Fix static selinux build.
|
||||
|
||||
Version 1.00.13 - 6 Apr 2004
|
||||
============================
|
||||
Add some basic selinux support.
|
||||
|
||||
Version 1.00.12 - 6 Apr 2004
|
||||
============================
|
||||
Fix dmsetup.static install.
|
||||
|
||||
Version 1.00.11 - 5 Apr 2004
|
||||
============================
|
||||
configure --enable-static_link does static build in addition to dynamic.
|
||||
Moved Makefile library targets definition into template.
|
||||
|
||||
Version 1.00.10 - 2 Apr 2004
|
||||
============================
|
||||
Fix DESTDIR handling.
|
||||
Static build installs to dmsetup.static.
|
||||
Basic support for internationalisation.
|
||||
Minor Makefile tidy-ups/fixes.
|
||||
|
||||
Version 1.00.09 - 31 Mar 2004
|
||||
=============================
|
||||
Update copyright notices to Red Hat.
|
||||
Move full mknodes functionality from dmsetup into libdevmapper.
|
||||
Avoid sscanf %as for uClibc compatibility.
|
||||
Cope if DM_LIST_VERSIONS is not defined.
|
||||
Add DM_LIST_VERSIONS functionality to kernel patches.
|
||||
Generate new kernel patches for 2.4.26-rc1.
|
||||
|
||||
Version 1.00.08 - 27 Feb 2004
|
||||
=============================
|
||||
Added 'dmsetup targets'.
|
||||
Added event_nr support to 'dmsetup wait'.
|
||||
Updated dmsetup man page.
|
||||
Allow logging function to be reset to use internal one.
|
||||
Bring log macros in line with LVM2 ones.
|
||||
Added 'make install_static_lib' which installs libdevmapper.a.
|
||||
Made configure/makefiles closer to LVM2 versions.
|
||||
Fixed DESTDIR for make install/install_static_lib.
|
||||
Updated README/INSTALL to reflect move to sources.redhat.com.
|
||||
Updated autoconf files to 2003-06-17.
|
||||
|
171
configure.in
171
configure.in
@@ -1,4 +1,3 @@
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 1999-2000 Sistina Software, Inc.
|
||||
##
|
||||
@@ -51,23 +50,58 @@ AC_CANONICAL_SYSTEM
|
||||
|
||||
case "$host_os" in
|
||||
linux*)
|
||||
CFLAGS= ;;
|
||||
CFLAGS=
|
||||
CLDFLAGS="-Wl,--version-script,.export.sym"
|
||||
CLDWHOLEARCHIVE="-Wl,-whole-archive"
|
||||
CLDNOWHOLEARCHIVE="-Wl,-no-whole-archive"
|
||||
LD_DEPS=".export.sym"
|
||||
LD_FLAGS="-Wl,--export-dynamic"
|
||||
SOFLAG="-shared"
|
||||
DEVMAPPER=yes
|
||||
ODIRECT=yes ;;
|
||||
darwin*)
|
||||
CFLAGS="-no-cpp-precomp -fno-common"
|
||||
CLDFLAGS=
|
||||
CLDWHOLEARCHIVE="-all_load"
|
||||
CLDNOWHOLEARCHIVE=
|
||||
LD_DEPS=
|
||||
LD_FLAGS=
|
||||
SOFLAG="-dynamiclib"
|
||||
DEVMAPPER=no
|
||||
ODIRECT=no ;;
|
||||
esac
|
||||
|
||||
dnl -- prefix is /usr by default, the exec_prefix default is setup later
|
||||
AC_PREFIX_DEFAULT(/usr)
|
||||
|
||||
OWNER="root"
|
||||
GROUP="root"
|
||||
|
||||
dnl -- setup the ownership of the files
|
||||
AC_ARG_WITH(user,
|
||||
[ --with-user=USER Set the owner of installed files ],
|
||||
[ OWNER="$withval" ],
|
||||
[ OWNER="root" ])
|
||||
[ OWNER="$withval" ])
|
||||
|
||||
if test x$OWNER != x; then
|
||||
OWNER="-o $OWNER"
|
||||
fi
|
||||
|
||||
dnl -- setup the group ownership of the files
|
||||
AC_ARG_WITH(group,
|
||||
[ --with-group=GROUP Set the group owner of installed files ],
|
||||
[ GROUP="$withval" ],
|
||||
[ GROUP="root" ])
|
||||
[ GROUP="$withval" ])
|
||||
|
||||
if test x$GROUP != x; then
|
||||
GROUP="-g $GROUP"
|
||||
fi
|
||||
|
||||
dnl -- LVM1 tool fallback option
|
||||
AC_ARG_ENABLE(lvm1_fallback, [ --enable-lvm1_fallback Use this to fall back and use LVM1 binaries if
|
||||
device-mapper is missing from the kernel], LVM1_FALLBACK=$enableval, LVM1_FALLBACK=no)
|
||||
|
||||
if test x$LVM1_FALLBACK = xyes; then
|
||||
CFLAGS="$CFLAGS -DLVM1_FALLBACK"
|
||||
fi
|
||||
|
||||
dnl -- format1 inclusion type
|
||||
AC_ARG_WITH(lvm1,
|
||||
@@ -87,10 +121,65 @@ if test x$LVM1 = xinternal; then
|
||||
CFLAGS="$CFLAGS -DLVM1_INTERNAL"
|
||||
fi
|
||||
|
||||
dnl -- format_pool inclusion type
|
||||
AC_ARG_WITH(pool,
|
||||
[ --with-pool=TYPE GFS pool read-only support: internal/shared/none
|
||||
[TYPE=internal] ],
|
||||
[ POOL="$withval" ],
|
||||
[ POOL="internal" ])
|
||||
|
||||
if [[ "x$POOL" != xnone -a "x$POOL" != xinternal -a "x$POOL" != xshared ]];
|
||||
then AC_MSG_ERROR(
|
||||
--with-pool parameter invalid
|
||||
)
|
||||
exit
|
||||
fi;
|
||||
|
||||
if test x$POOL = xinternal; then
|
||||
CFLAGS="$CFLAGS -DPOOL_INTERNAL"
|
||||
fi
|
||||
|
||||
|
||||
AC_ARG_ENABLE(jobs, [ --enable-jobs=NUM Number of jobs to run simultaneously], JOBS=-j$enableval, JOBS=-j2)
|
||||
|
||||
dnl Enables staticly linked tools
|
||||
AC_ARG_ENABLE(static_link, [ --enable-static_link Use this to link the tools to the liblvm library
|
||||
dnl -- snapshots inclusion type
|
||||
AC_ARG_WITH(snapshots,
|
||||
[ --with-snapshots=TYPE Snapshot support: internal/shared/none
|
||||
[TYPE=internal] ],
|
||||
[ SNAPSHOTS="$withval" ],
|
||||
[ SNAPSHOTS="internal" ])
|
||||
|
||||
if [[ "x$SNAPSHOTS" != xnone -a "x$SNAPSHOTS" != xinternal -a "x$SNAPSHOTS" != xshared ]];
|
||||
then AC_MSG_ERROR(
|
||||
--with-snapshots parameter invalid
|
||||
)
|
||||
exit
|
||||
fi;
|
||||
|
||||
if test x$SNAPSHOTS = xinternal; then
|
||||
CFLAGS="$CFLAGS -DSNAPSHOT_INTERNAL"
|
||||
fi
|
||||
|
||||
dnl -- mirrors inclusion type
|
||||
AC_ARG_WITH(mirrors,
|
||||
[ --with-mirrors=TYPE Mirror support: internal/shared/none
|
||||
[TYPE=internal] ],
|
||||
[ MIRRORS="$withval" ],
|
||||
[ MIRRORS="internal" ])
|
||||
|
||||
if [[ "x$MIRRORS" != xnone -a "x$MIRRORS" != xinternal -a "x$MIRRORS" != xshared ]];
|
||||
then AC_MSG_ERROR(
|
||||
--with-mirrors parameter invalid
|
||||
)
|
||||
exit
|
||||
fi;
|
||||
|
||||
if test x$MIRRORS = xinternal; then
|
||||
CFLAGS="$CFLAGS -DMIRRORED_INTERNAL"
|
||||
fi
|
||||
|
||||
dnl Enables staticly-linked tools
|
||||
AC_ARG_ENABLE(static_link, [ --enable-static_link Use this to link the tools to their libraries
|
||||
statically. Default is dynamic linking], STATIC_LINK=$enableval, STATIC_LINK=no)
|
||||
|
||||
dnl Enable readline
|
||||
@@ -110,7 +199,7 @@ echo "$ac_t""$DEBUG" 1>&6
|
||||
echo $ac_n "checking whether to enable device-mapper""... $ac_c" 1>&6
|
||||
dnl Disable devmapper
|
||||
AC_ARG_ENABLE(devmapper, [ --disable-devmapper Disable device-mapper interaction], \
|
||||
DEVMAPPER=no, DEVMAPPER=yes)
|
||||
DEVMAPPER=no)
|
||||
echo "$ac_t""$DEVMAPPER" 1>&6
|
||||
|
||||
if test x$DEVMAPPER = xyes; then
|
||||
@@ -120,13 +209,23 @@ fi
|
||||
echo $ac_n "checking whether to enable O_DIRECT""... $ac_c" 1>&6
|
||||
dnl Disable O_DIRECT
|
||||
AC_ARG_ENABLE(o_direct, [ --disable-o_direct Disable O_DIRECT], \
|
||||
ODIRECT=no, ODIRECT=yes)
|
||||
ODIRECT=no)
|
||||
echo "$ac_t""$ODIRECT" 1>&6
|
||||
|
||||
if test x$ODIRECT = xyes; then
|
||||
CFLAGS="$CFLAGS -DO_DIRECT_SUPPORT"
|
||||
fi
|
||||
|
||||
echo $ac_n "checking whether to compile liblvm2cmd.so""... $ac_c" 1>&6
|
||||
dnl Enable cmdlib
|
||||
AC_ARG_ENABLE(cmdlib, [ --enable-cmdlib Build shared command library], \
|
||||
CMDLIB=yes, CMDLIB=no)
|
||||
echo "$ac_t""$CMDLIB" 1>&6
|
||||
|
||||
if test x$CMDLIB = xyes; then
|
||||
CFLAGS="$CFLAGS -DCMDLIB"
|
||||
fi
|
||||
|
||||
dnl Mess with default exec_prefix
|
||||
if [[ "x$exec_prefix" = xNONE -a "x$prefix" = xNONE ]];
|
||||
then exec_prefix="";
|
||||
@@ -158,9 +257,29 @@ fi
|
||||
dnl Check for dlopen
|
||||
AC_CHECK_LIB(dl, dlopen, HAVE_LIBDL=yes, HAVE_LIBDL=no)
|
||||
|
||||
if test x$HAVE_LIBDL = xyes; then
|
||||
if [[ "x$HAVE_LIBDL" = xyes -a "x$STATIC_LINK" = xno ]]; then
|
||||
CFLAGS="$CFLAGS -DHAVE_LIBDL"
|
||||
LIBS="-ldl $LIBS"
|
||||
else
|
||||
HAVE_LIBDL=no
|
||||
fi
|
||||
|
||||
dnl Check for shared/static conflicts
|
||||
if [[ \( "x$LVM1" = xshared -o "x$POOL" = xshared -o \
|
||||
"x$SNAPSHOTS" = xshared -o "x$MIRRORS" = xshared \
|
||||
\) -a "x$STATIC_LINK" = xyes ]];
|
||||
then AC_MSG_ERROR(
|
||||
Features cannot be 'shared' when building statically
|
||||
)
|
||||
exit
|
||||
fi
|
||||
|
||||
dnl Check for is_selinux_enabled
|
||||
AC_CHECK_LIB(selinux, is_selinux_enabled, HAVE_SELINUX=yes, HAVE_SELINUX=no)
|
||||
|
||||
if test x$HAVE_SELINUX = xyes; then
|
||||
CFLAGS="$CFLAGS -DHAVE_SELINUX"
|
||||
LIBS="-lselinux $LIBS"
|
||||
fi
|
||||
|
||||
dnl Check for getopt
|
||||
@@ -205,6 +324,17 @@ if test x$INTL = xyes; then
|
||||
[ LOCALEDIR='${prefix}/share/locale' ])
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(confdir,
|
||||
[ --with-confdir=DIR Configuration files in DIR [/etc]],
|
||||
[ CONFDIR="$withval" ],
|
||||
[ CONFDIR='/etc' ])
|
||||
|
||||
AC_ARG_WITH(staticdir,
|
||||
[ --with-staticdir=DIR Static binary in DIR [EXEC_PREFIX/sbin]],
|
||||
[ STATICDIR="$withval" ],
|
||||
[ STATICDIR='${exec_prefix}/sbin' ])
|
||||
|
||||
|
||||
if test "-f VERSION"; then
|
||||
LVM_VERSION="\"`cat VERSION`\""
|
||||
else
|
||||
@@ -214,26 +344,45 @@ fi
|
||||
AC_SUBST(JOBS)
|
||||
AC_SUBST(STATIC_LINK)
|
||||
AC_SUBST(LVM1)
|
||||
AC_SUBST(POOL)
|
||||
AC_SUBST(SNAPSHOTS)
|
||||
AC_SUBST(MIRRORS)
|
||||
AC_SUBST(OWNER)
|
||||
AC_SUBST(GROUP)
|
||||
AC_SUBST(CFLAGS)
|
||||
AC_SUBST(CLDFLAGS)
|
||||
AC_SUBST(CLDWHOLEARCHIVE)
|
||||
AC_SUBST(CLDNOWHOLEARCHIVE)
|
||||
AC_SUBST(LD_DEPS)
|
||||
AC_SUBST(LD_FLAGS)
|
||||
AC_SUBST(SOFLAG)
|
||||
AC_SUBST(LIBS)
|
||||
AC_SUBST(LVM_VERSION)
|
||||
AC_SUBST(LVM1_FALLBACK)
|
||||
AC_SUBST(DEBUG)
|
||||
AC_SUBST(DEVMAPPER)
|
||||
AC_SUBST(HAVE_LIBDL)
|
||||
AC_SUBST(HAVE_SELINUX)
|
||||
AC_SUBST(CMDLIB)
|
||||
AC_SUBST(MSGFMT)
|
||||
AC_SUBST(LOCALEDIR)
|
||||
AC_SUBST(CONFDIR)
|
||||
AC_SUBST(STATICDIR)
|
||||
AC_SUBST(INTL_PACKAGE)
|
||||
AC_SUBST(INTL)
|
||||
|
||||
dnl First and last lines should not contain files to generate in order to
|
||||
dnl keep utility scripts running properly
|
||||
AC_OUTPUT( \
|
||||
Makefile \
|
||||
make.tmpl \
|
||||
doc/Makefile \
|
||||
include/Makefile \
|
||||
lib/Makefile \
|
||||
lib/format1/Makefile \
|
||||
lib/format_pool/Makefile \
|
||||
lib/mirror/Makefile \
|
||||
lib/snapshot/Makefile \
|
||||
man/Makefile \
|
||||
po/Makefile \
|
||||
tools/Makefile \
|
||||
|
29
doc/Makefile.in
Normal file
29
doc/Makefile.in
Normal file
@@ -0,0 +1,29 @@
|
||||
#
|
||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
CONFSRC=example.conf
|
||||
CONFDEST=lvm.conf
|
||||
|
||||
include ../make.tmpl
|
||||
|
||||
install:
|
||||
@if [ ! -e $(confdir)/$(CONFDEST) ]; then \
|
||||
echo "Installing $(CONFSRC) as $(confdir)/$(CONFDEST)"; \
|
||||
@INSTALL@ -D $(OWNER) $(GROUP) -m 644 $(CONFSRC) \
|
||||
$(confdir)/$(CONFDEST); \
|
||||
fi
|
||||
|
@@ -27,9 +27,6 @@ devices {
|
||||
# the device will be accepted or rejected (ignored). Devices that
|
||||
# don't match any patterns are accepted.
|
||||
|
||||
# If using RAID md devices as physical volumes, you should
|
||||
# set up a filter here to reject the constituent devices.
|
||||
|
||||
# Remember to run vgscan after you change this parameter to ensure
|
||||
# that the cache file gets regenerated (see below).
|
||||
|
||||
@@ -57,14 +54,21 @@ devices {
|
||||
# You can turn off writing this cache file by setting this to 0.
|
||||
write_cache_state = 1
|
||||
|
||||
# An advanced setting.
|
||||
# Advanced settings.
|
||||
|
||||
# List of pairs of additional acceptable block device types found
|
||||
# in /proc/devices with maximum (non-zero) number of partitions.
|
||||
# types = [ "fd", 16 ]
|
||||
|
||||
# If sysfs is mounted (2.6 kernels) restrict device scanning to
|
||||
# the block devices it believes are valid.
|
||||
# 1 enables; 0 disables.
|
||||
sysfs_scan = 1
|
||||
|
||||
# By default, LVM2 will ignore devices used as components of
|
||||
# software RAID (md) devices by looking for md superblocks.
|
||||
# 1 enables; 0 disables.
|
||||
md_component_detection = 1
|
||||
}
|
||||
|
||||
# This section that allows you to configure the nature of the
|
||||
@@ -175,6 +179,16 @@ global {
|
||||
# setting this to 0 should suppress the error messages.
|
||||
activation = 1
|
||||
|
||||
# If we can't communicate with device-mapper, should we try running
|
||||
# the LVM1 tools?
|
||||
# This option only applies to 2.4 kernels and is provided to help you
|
||||
# switch between device-mapper kernels and LVM1 kernels.
|
||||
# The LVM1 tools need to be installed with .lvm1 suffices
|
||||
# e.g. vgscan.lvm1 and they will stop working after you start using
|
||||
# the new lvm2 on-disk metadata format.
|
||||
# The default value is set when the tools are built.
|
||||
# fallback_to_lvm1 = 0
|
||||
|
||||
# The default metadata format that commands should use - "lvm1" or "lvm2".
|
||||
# The command line override is -M1 or -M2.
|
||||
# Defaults to "lvm1" if compiled in, else "lvm2".
|
||||
@@ -219,6 +233,14 @@ activation {
|
||||
|
||||
# Nice value used while devices suspended
|
||||
process_priority = -18
|
||||
|
||||
# If volume_list is defined, each LV is only activated if there is a
|
||||
# match against the list.
|
||||
# "vgname" and "vgname/lvname" are matched exactly.
|
||||
# "@tag" matches any tag set in the LV or VG.
|
||||
# "@*" matches if any tag defined on the host is also set in the LV or VG
|
||||
#
|
||||
# volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ]
|
||||
}
|
||||
|
||||
|
||||
|
47
doc/example_cmdlib.c
Normal file
47
doc/example_cmdlib.c
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lvm2cmd.h"
|
||||
|
||||
/* All output gets passed to this function line-by-line */
|
||||
void test_log_fn(int level, const char *file, int line, const char *format)
|
||||
{
|
||||
/* Extract and process output here rather than printing it */
|
||||
|
||||
if (level != 4)
|
||||
return;
|
||||
|
||||
printf("%s\n", format);
|
||||
return;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *handle;
|
||||
int r;
|
||||
|
||||
lvm2_log_fn(test_log_fn);
|
||||
|
||||
handle = lvm2_init();
|
||||
|
||||
lvm2_log_level(handle, 1);
|
||||
r = lvm2_run(handle, "vgs --noheadings vg1");
|
||||
|
||||
/* More commands here */
|
||||
|
||||
lvm2_exit(handle);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
../lib/activate/activate.h
|
||||
../lib/activate/targets.h
|
||||
../lib/cache/lvmcache.h
|
||||
../lib/commands/errors.h
|
||||
../lib/commands/toolcontext.h
|
||||
@@ -14,17 +15,22 @@
|
||||
../lib/device/device.h
|
||||
../lib/display/display.h
|
||||
../lib/filters/filter-composite.h
|
||||
../lib/filters/filter-md.h
|
||||
../lib/filters/filter-persistent.h
|
||||
../lib/filters/filter-regex.h
|
||||
../lib/filters/filter-sysfs.h
|
||||
../lib/filters/filter.h
|
||||
../lib/format1/format1.h
|
||||
../lib/format_pool/format_pool.h
|
||||
../lib/format_text/format-text.h
|
||||
../lib/format_text/text_export.h
|
||||
../lib/format_text/text_import.h
|
||||
../lib/label/label.h
|
||||
../lib/locking/locking.h
|
||||
../lib/log/log.h
|
||||
../lib/metadata/lv_alloc.h
|
||||
../lib/metadata/metadata.h
|
||||
../lib/metadata/segtypes.h
|
||||
../lib/mm/dbg_malloc.h
|
||||
../lib/mm/memlock.h
|
||||
../lib/mm/pool.h
|
||||
@@ -34,6 +40,7 @@
|
||||
../lib/misc/lib.h
|
||||
../lib/misc/lvm-file.h
|
||||
../lib/misc/lvm-string.h
|
||||
../lib/misc/selinux.h
|
||||
../lib/misc/sharedlib.h
|
||||
../lib/regex/matcher.h
|
||||
../lib/report/report.h
|
||||
|
@@ -1,20 +1,16 @@
|
||||
#
|
||||
# Copyright (C) 2001 Sistina Software
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This LVM library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Library General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2 of the License, or (at your option) any later version.
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This LVM library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Library General Public License for more details.
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU Library General Public
|
||||
# License along with this LVM library; if not, write to the Free
|
||||
# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
# MA 02111-1307, USA
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
SHELL = /bin/sh
|
||||
|
||||
|
@@ -1,8 +1,16 @@
|
||||
#
|
||||
# Copyright (C) 2001 Sistina Software (UK) Limited
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is released under the GPL.
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
@@ -12,7 +20,19 @@ ifeq ("@LVM1@", "shared")
|
||||
SUBDIRS = format1
|
||||
endif
|
||||
|
||||
SOURCES=\
|
||||
ifeq ("@POOL@", "shared")
|
||||
SUBDIRS += format_pool
|
||||
endif
|
||||
|
||||
ifeq ("@SNAPSHOTS@", "shared")
|
||||
SUBDIRS += snapshot
|
||||
endif
|
||||
|
||||
ifeq ("@MIRRORS@", "shared")
|
||||
SUBDIRS += mirror
|
||||
endif
|
||||
|
||||
SOURCES =\
|
||||
activate/activate.c \
|
||||
cache/lvmcache.c \
|
||||
commands/toolcontext.c \
|
||||
@@ -25,10 +45,12 @@ SOURCES=\
|
||||
device/dev-io.c \
|
||||
device/device.c \
|
||||
display/display.c \
|
||||
error/errseg.c \
|
||||
filters/filter-composite.c \
|
||||
filters/filter-persistent.c \
|
||||
filters/filter-regex.c \
|
||||
filters/filter-sysfs.c \
|
||||
filters/filter-md.c \
|
||||
filters/filter.c \
|
||||
format_text/archive.c \
|
||||
format_text/export.c \
|
||||
@@ -36,6 +58,7 @@ SOURCES=\
|
||||
format_text/format-text.c \
|
||||
format_text/import.c \
|
||||
format_text/import_vsn1.c \
|
||||
format_text/tags.c \
|
||||
format_text/text_label.c \
|
||||
label/label.c \
|
||||
locking/file_locking.c \
|
||||
@@ -47,6 +70,7 @@ SOURCES=\
|
||||
metadata/metadata.c \
|
||||
metadata/mirror.c \
|
||||
metadata/pv_map.c \
|
||||
metadata/segtypes.c \
|
||||
metadata/snapshot_manip.c \
|
||||
misc/crc.c \
|
||||
misc/lvm-file.c \
|
||||
@@ -57,10 +81,12 @@ SOURCES=\
|
||||
regex/parse_rx.c \
|
||||
regex/ttree.c \
|
||||
report/report.c \
|
||||
uuid/uuid.c
|
||||
striped/striped.c \
|
||||
uuid/uuid.c \
|
||||
zero/zero.c
|
||||
|
||||
ifeq ("@LVM1@", "internal")
|
||||
SOURCES+=\
|
||||
SOURCES +=\
|
||||
format1/disk-rep.c \
|
||||
format1/format1.c \
|
||||
format1/import-export.c \
|
||||
@@ -70,29 +96,45 @@ ifeq ("@LVM1@", "internal")
|
||||
format1/vg_number.c
|
||||
endif
|
||||
|
||||
ifeq ("@POOL@", "internal")
|
||||
SOURCES +=\
|
||||
format_pool/disk_rep.c \
|
||||
format_pool/format_pool.c \
|
||||
format_pool/import_export.c \
|
||||
format_pool/pool_label.c
|
||||
endif
|
||||
|
||||
ifeq ("@SNAPSHOTS@", "internal")
|
||||
SOURCES += snapshot/snapshot.c
|
||||
endif
|
||||
|
||||
ifeq ("@MIRRORS@", "internal")
|
||||
SOURCES += mirror/mirrored.c
|
||||
endif
|
||||
|
||||
ifeq ("@DEBUG@", "yes")
|
||||
SOURCES+=\
|
||||
mm/dbg_malloc.c
|
||||
SOURCES += mm/dbg_malloc.c
|
||||
endif
|
||||
|
||||
ifeq ("@DEVMAPPER@", "yes")
|
||||
SOURCES+=\
|
||||
SOURCES +=\
|
||||
activate/dev_manager.c \
|
||||
activate/fs.c
|
||||
endif
|
||||
|
||||
ifeq ("@HAVE_LIBDL@", "yes")
|
||||
SOURCES+=\
|
||||
SOURCES +=\
|
||||
locking/external_locking.c \
|
||||
misc/sharedlib.c
|
||||
endif
|
||||
|
||||
TARGETS=liblvm.a
|
||||
ifeq ("@HAVE_SELINUX@", "yes")
|
||||
SOURCES += misc/selinux.c
|
||||
endif
|
||||
|
||||
LIB_STATIC = liblvm.a
|
||||
|
||||
$(SUBDIRS): $(LIB_STATIC)
|
||||
|
||||
include ../make.tmpl
|
||||
|
||||
liblvm.a: $(OBJECTS)
|
||||
$(RM) $@
|
||||
$(AR) r $@ $(OBJECTS)
|
||||
$(RANLIB) $@
|
||||
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -10,10 +19,13 @@
|
||||
#include "memlock.h"
|
||||
#include "display.h"
|
||||
#include "fs.h"
|
||||
#include "lvm-file.h"
|
||||
#include "lvm-string.h"
|
||||
#include "pool.h"
|
||||
#include "toolcontext.h"
|
||||
#include "dev_manager.h"
|
||||
#include "str_list.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <fcntl.h>
|
||||
@@ -21,12 +33,34 @@
|
||||
|
||||
#define _skip(fmt, args...) log_very_verbose("Skipping: " fmt , ## args)
|
||||
|
||||
int lvm1_present(struct cmd_context *cmd)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
|
||||
if (lvm_snprintf(path, sizeof(path), "%s/lvm/global", cmd->proc_dir)
|
||||
< 0) {
|
||||
log_error("LVM1 proc global snprintf failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (path_exists(path))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef DEVMAPPER_SUPPORT
|
||||
void set_activation(int act)
|
||||
{
|
||||
if (act)
|
||||
log_error("Compiled without libdevmapper support. "
|
||||
"Can't enable activation.");
|
||||
static int warned = 0;
|
||||
|
||||
if (warned || !act)
|
||||
return;
|
||||
|
||||
log_error("Compiled without libdevmapper support. "
|
||||
"Can't enable activation.");
|
||||
|
||||
warned = 1;
|
||||
}
|
||||
int activation(void)
|
||||
{
|
||||
@@ -40,10 +74,19 @@ int driver_version(char *version, size_t size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int target_present(const char *target_name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_info(const struct logical_volume *lv, struct lvinfo *info)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
|
||||
struct lvinfo *info)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_snapshot_percent(struct logical_volume *lv, float *percent)
|
||||
{
|
||||
return 0;
|
||||
@@ -61,10 +104,18 @@ int lvs_in_vg_opened(struct volume_group *vg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_suspend(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
int lv_resume(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return 1;
|
||||
@@ -73,10 +124,19 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
|
||||
int *activate_lv)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
|
||||
{
|
||||
@@ -111,6 +171,86 @@ int activation(void)
|
||||
return _activation;
|
||||
}
|
||||
|
||||
static int _passes_activation_filter(struct cmd_context *cmd,
|
||||
struct logical_volume *lv)
|
||||
{
|
||||
const struct config_node *cn;
|
||||
struct config_value *cv;
|
||||
char *str;
|
||||
char path[PATH_MAX];
|
||||
|
||||
if (!(cn = find_config_node(cmd->cft->root, "activation/volume_list"))) {
|
||||
/* If no host tags defined, activate */
|
||||
if (list_empty(&cmd->tags))
|
||||
return 1;
|
||||
|
||||
/* If any host tag matches any LV or VG tag, activate */
|
||||
if (str_list_match_list(&cmd->tags, &lv->tags) ||
|
||||
str_list_match_list(&cmd->tags, &lv->vg->tags))
|
||||
return 1;
|
||||
|
||||
/* Don't activate */
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (cv = cn->v; cv; cv = cv->next) {
|
||||
if (cv->type != CFG_STRING) {
|
||||
log_error("Ignoring invalid string in config file "
|
||||
"activation/volume_list");
|
||||
continue;
|
||||
}
|
||||
str = cv->v.str;
|
||||
if (!*str) {
|
||||
log_error("Ignoring empty string in config file "
|
||||
"activation/volume_list");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Tag? */
|
||||
if (*str == '@') {
|
||||
str++;
|
||||
if (!*str) {
|
||||
log_error("Ignoring empty tag in config file "
|
||||
"activation/volume_list");
|
||||
continue;
|
||||
}
|
||||
/* If any host tag matches any LV or VG tag, activate */
|
||||
if (!strcmp(str, "*")) {
|
||||
if (str_list_match_list(&cmd->tags, &lv->tags)
|
||||
|| str_list_match_list(&cmd->tags,
|
||||
&lv->vg->tags))
|
||||
return 1;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
/* If supplied tag matches LV or VG tag, activate */
|
||||
if (str_list_match_item(&lv->tags, str) ||
|
||||
str_list_match_item(&lv->vg->tags, str))
|
||||
return 1;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
if (!index(str, '/')) {
|
||||
/* vgname supplied */
|
||||
if (!strcmp(str, lv->vg->name))
|
||||
return 1;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
/* vgname/lvname */
|
||||
if (lvm_snprintf(path, sizeof(path), "%s/%s", lv->vg->name,
|
||||
lv->name) < 0) {
|
||||
log_error("lvm_snprintf error from %s/%s", lv->vg->name,
|
||||
lv->name);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(path, str))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int library_version(char *version, size_t size)
|
||||
{
|
||||
if (!activation())
|
||||
@@ -149,6 +289,46 @@ int driver_version(char *version, size_t size)
|
||||
return r;
|
||||
}
|
||||
|
||||
int target_present(const char *target_name)
|
||||
{
|
||||
int r = 0;
|
||||
struct dm_task *dmt;
|
||||
struct dm_versions *target, *last_target;
|
||||
|
||||
if (!activation())
|
||||
return 0;
|
||||
|
||||
log_very_verbose("Getting target version for %s", target_name);
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dm_task_run(dmt)) {
|
||||
log_debug("Failed to get %s target version", target_name);
|
||||
/* Assume this was because LIST_VERSIONS isn't supported */
|
||||
return 1;
|
||||
}
|
||||
|
||||
target = dm_task_get_versions(dmt);
|
||||
|
||||
do {
|
||||
last_target = target;
|
||||
|
||||
if (!strcmp(target_name, target->name)) {
|
||||
r = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
target = (void *) target + target->next;
|
||||
} while (last_target != target);
|
||||
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 1 if info structure populated, else 0 on failure.
|
||||
*/
|
||||
@@ -162,7 +342,7 @@ static int _lv_info(const struct logical_volume *lv, int mknodes,
|
||||
if (!activation())
|
||||
return 0;
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -186,6 +366,17 @@ int lv_info(const struct logical_volume *lv, struct lvinfo *info)
|
||||
return _lv_info(lv, 0, info);
|
||||
}
|
||||
|
||||
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
|
||||
struct lvinfo *info)
|
||||
{
|
||||
struct logical_volume *lv;
|
||||
|
||||
if (!(lv = lv_from_lvid(cmd, lvid_s)))
|
||||
return 0;
|
||||
|
||||
return _lv_info(lv, 0, info);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 1 if percent set, else 0 on failure.
|
||||
*/
|
||||
@@ -197,7 +388,7 @@ int lv_snapshot_percent(struct logical_volume *lv, float *percent)
|
||||
if (!activation())
|
||||
return 0;
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -216,11 +407,20 @@ int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
|
||||
{
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
struct lvinfo info;
|
||||
|
||||
if (!activation())
|
||||
return 0;
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
|
||||
if (!lv_info(lv, &info)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!info.exists)
|
||||
return 0;
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -258,12 +458,12 @@ static int _lv_open_count(struct logical_volume *lv)
|
||||
}
|
||||
|
||||
/* FIXME Need to detect and handle an lv rename */
|
||||
static int _lv_activate(struct logical_volume *lv)
|
||||
static int _lv_activate_lv(struct logical_volume *lv)
|
||||
{
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -280,7 +480,7 @@ static int _lv_deactivate(struct logical_volume *lv)
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -292,12 +492,12 @@ static int _lv_deactivate(struct logical_volume *lv)
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _lv_suspend(struct logical_volume *lv)
|
||||
static int _lv_suspend_lv(struct logical_volume *lv)
|
||||
{
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -310,7 +510,7 @@ static int _lv_suspend(struct logical_volume *lv)
|
||||
}
|
||||
|
||||
/*
|
||||
* These two functions return the number of LVs in the state,
|
||||
* 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)
|
||||
@@ -324,7 +524,8 @@ int lvs_in_vg_activated(struct volume_group *vg)
|
||||
|
||||
list_iterate(lvh, &vg->lvs) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
count += (_lv_active(lv) == 1);
|
||||
if (lv->status & VISIBLE_LV)
|
||||
count += (_lv_active(lv) == 1);
|
||||
}
|
||||
|
||||
return count;
|
||||
@@ -341,14 +542,15 @@ int lvs_in_vg_opened(struct volume_group *vg)
|
||||
|
||||
list_iterate(lvh, &vg->lvs) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
count += (_lv_open_count(lv) == 1);
|
||||
if (lv->status & VISIBLE_LV)
|
||||
count += (_lv_open_count(lv) > 0);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* These return success if the device is not active */
|
||||
int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
|
||||
static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
|
||||
int error_if_not_suspended)
|
||||
{
|
||||
struct logical_volume *lv;
|
||||
struct lvinfo info;
|
||||
@@ -370,10 +572,10 @@ int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
|
||||
}
|
||||
|
||||
if (!info.exists || info.suspended)
|
||||
return 1;
|
||||
return error_if_not_suspended ? 0 : 1;
|
||||
|
||||
memlock_inc();
|
||||
if (!_lv_suspend(lv)) {
|
||||
if (!_lv_suspend_lv(lv)) {
|
||||
memlock_dec();
|
||||
fs_unlock();
|
||||
return 0;
|
||||
@@ -382,7 +584,19 @@ int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
|
||||
/* Returns success if the device is not active */
|
||||
int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return _lv_suspend(cmd, lvid_s, 0);
|
||||
}
|
||||
|
||||
int lv_suspend(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return _lv_suspend(cmd, lvid_s, 1);
|
||||
}
|
||||
|
||||
static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
|
||||
int error_if_not_active)
|
||||
{
|
||||
struct logical_volume *lv;
|
||||
struct lvinfo info;
|
||||
@@ -404,9 +618,9 @@ int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
|
||||
}
|
||||
|
||||
if (!info.exists || !info.suspended)
|
||||
return 1;
|
||||
return error_if_not_active ? 0 : 1;
|
||||
|
||||
if (!_lv_activate(lv))
|
||||
if (!_lv_activate_lv(lv))
|
||||
return 0;
|
||||
|
||||
memlock_dec();
|
||||
@@ -415,6 +629,17 @@ int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Returns success if the device is not active */
|
||||
int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return _lv_resume(cmd, lvid_s, 0);
|
||||
}
|
||||
|
||||
int lv_resume(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return _lv_resume(cmd, lvid_s, 1);
|
||||
}
|
||||
|
||||
int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
struct logical_volume *lv;
|
||||
@@ -440,7 +665,7 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
|
||||
if (!info.exists)
|
||||
return 1;
|
||||
|
||||
if (info.open_count) {
|
||||
if (info.open_count && (lv->status & VISIBLE_LV)) {
|
||||
log_error("LV %s/%s in use: not removing", lv->vg->name,
|
||||
lv->name);
|
||||
return 0;
|
||||
@@ -454,7 +679,31 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
|
||||
return r;
|
||||
}
|
||||
|
||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s)
|
||||
/* Test if LV passes filter */
|
||||
int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
|
||||
int *activate_lv)
|
||||
{
|
||||
struct logical_volume *lv;
|
||||
|
||||
if (!activation())
|
||||
goto activate;
|
||||
|
||||
if (!(lv = lv_from_lvid(cmd, lvid_s)))
|
||||
return 0;
|
||||
|
||||
if (!_passes_activation_filter(cmd, lv)) {
|
||||
log_verbose("Not activating %s/%s due to config file settings",
|
||||
lv->vg->name, lv->name);
|
||||
*activate_lv = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
activate:
|
||||
*activate_lv = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _lv_activate(struct cmd_context *cmd, const char *lvid_s, int filter)
|
||||
{
|
||||
struct logical_volume *lv;
|
||||
struct lvinfo info;
|
||||
@@ -466,6 +715,12 @@ int lv_activate(struct cmd_context *cmd, const char *lvid_s)
|
||||
if (!(lv = lv_from_lvid(cmd, lvid_s)))
|
||||
return 0;
|
||||
|
||||
if (filter && !_passes_activation_filter(cmd, lv)) {
|
||||
log_verbose("Not activating %s/%s due to config file settings",
|
||||
lv->vg->name, lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (test_mode()) {
|
||||
_skip("Activating '%s'.", lv->name);
|
||||
return 1;
|
||||
@@ -480,27 +735,45 @@ int lv_activate(struct cmd_context *cmd, const char *lvid_s)
|
||||
return 1;
|
||||
|
||||
memlock_inc();
|
||||
r = _lv_activate(lv);
|
||||
r = _lv_activate_lv(lv);
|
||||
memlock_dec();
|
||||
fs_unlock();
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Activate LV */
|
||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return _lv_activate(cmd, lvid_s, 0);
|
||||
}
|
||||
|
||||
/* Activate LV only if it passes filter */
|
||||
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return _lv_activate(cmd, lvid_s, 1);
|
||||
}
|
||||
|
||||
int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
|
||||
{
|
||||
struct lvinfo info;
|
||||
int r = 1;
|
||||
|
||||
if (!lv) {
|
||||
r = dev_manager_mknodes();
|
||||
fs_unlock();
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!_lv_info(lv, 1, &info)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (info.exists)
|
||||
r = dev_manager_mknodes(lv);
|
||||
r = dev_manager_lv_mknodes(lv);
|
||||
else
|
||||
r = dev_manager_rmnodes(lv);
|
||||
r = dev_manager_lv_rmnodes(lv);
|
||||
|
||||
fs_unlock();
|
||||
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef LVM_ACTIVATE_H
|
||||
@@ -27,12 +36,18 @@ int activation(void);
|
||||
|
||||
int driver_version(char *version, size_t size);
|
||||
int library_version(char *version, size_t size);
|
||||
int lvm1_present(struct cmd_context *cmd);
|
||||
|
||||
int target_present(const char *target_name);
|
||||
|
||||
void activation_exit(void);
|
||||
|
||||
int lv_suspend(struct cmd_context *cmd, const char *lvid_s);
|
||||
int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s);
|
||||
int lv_resume(struct cmd_context *cmd, const char *lvid_s);
|
||||
int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s);
|
||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s);
|
||||
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s);
|
||||
int lv_deactivate(struct cmd_context *cmd, const char *lvid_s);
|
||||
|
||||
int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv);
|
||||
@@ -41,6 +56,15 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv);
|
||||
* Returns 1 if info structure has been populated, else 0.
|
||||
*/
|
||||
int lv_info(const struct logical_volume *lv, struct lvinfo *info);
|
||||
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
|
||||
struct lvinfo *info);
|
||||
|
||||
/*
|
||||
* Returns 1 if activate_lv has been set: 1 = activate; 0 = don't.
|
||||
*/
|
||||
int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
|
||||
int *activate_lv);
|
||||
|
||||
/*
|
||||
* Returns 1 if percent has been set, else 0.
|
||||
*/
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -12,7 +21,11 @@
|
||||
#include "lvm-string.h"
|
||||
#include "fs.h"
|
||||
#include "defaults.h"
|
||||
#include "segtypes.h"
|
||||
#include "display.h"
|
||||
#include "toolcontext.h"
|
||||
#include "targets.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <libdevmapper.h>
|
||||
#include <limits.h>
|
||||
@@ -53,13 +66,8 @@ enum {
|
||||
SUSPENDED = 4,
|
||||
NOPROPAGATE = 5,
|
||||
TOPLEVEL = 6,
|
||||
REMOVE = 7
|
||||
};
|
||||
|
||||
enum {
|
||||
MIRR_DISABLED,
|
||||
MIRR_RUNNING,
|
||||
MIRR_COMPLETED
|
||||
REMOVE = 7,
|
||||
RESUME_IMMEDIATE = 8
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
@@ -103,14 +111,14 @@ struct dl_list {
|
||||
};
|
||||
|
||||
static const char *stripe_filler = NULL;
|
||||
static uint32_t mirror_region_size = 0;
|
||||
|
||||
struct dev_manager {
|
||||
struct pool *mem;
|
||||
|
||||
struct config_tree *cf;
|
||||
struct cmd_context *cmd;
|
||||
|
||||
const char *stripe_filler;
|
||||
uint32_t mirror_region_size;
|
||||
void *target_state;
|
||||
uint32_t pvmove_mirror_count;
|
||||
|
||||
char *vg_name;
|
||||
@@ -327,7 +335,7 @@ static int _info_run(const char *name, const char *uuid, struct dm_info *info,
|
||||
static int _info(const char *name, const char *uuid, int mknodes,
|
||||
struct dm_info *info, struct pool *mem, char **uuid_out)
|
||||
{
|
||||
if (!mknodes && uuid && *uuid &&
|
||||
if (!mknodes && uuid && *uuid &&
|
||||
_info_run(NULL, uuid, info, 0, mem, uuid_out) && info->exists)
|
||||
return 1;
|
||||
|
||||
@@ -418,18 +426,16 @@ static int _percent_run(struct dev_manager *dm, const char *name,
|
||||
uint64_t start, length;
|
||||
char *type = NULL;
|
||||
char *params = NULL;
|
||||
float percent2;
|
||||
struct list *segh = &lv->segments;
|
||||
struct lv_segment *seg = NULL;
|
||||
struct segment_type *segtype;
|
||||
|
||||
uint64_t numerator, denominator;
|
||||
uint64_t total_numerator = 0, total_denominator = 0;
|
||||
|
||||
*percent = -1;
|
||||
|
||||
if (!(dmt = _setup_task(name, uuid, event_nr,
|
||||
wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS)))
|
||||
{
|
||||
wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -462,40 +468,19 @@ static int _percent_run(struct dev_manager *dm, const char *name,
|
||||
if (!type || !params || strcmp(type, target_type))
|
||||
continue;
|
||||
|
||||
/* Mirror? */
|
||||
if (!strcmp(type, "mirror")) {
|
||||
log_debug("Mirror status: %s", params);
|
||||
if (sscanf(params, "%*d %*x:%*x %*x:%*x %" PRIu64
|
||||
"/%" PRIu64, &numerator,
|
||||
&denominator) != 2) {
|
||||
log_error("Failure parsing mirror status: %s",
|
||||
params);
|
||||
goto out;
|
||||
}
|
||||
total_numerator += numerator;
|
||||
total_denominator += denominator;
|
||||
|
||||
if (seg && (seg->status & PVMOVE))
|
||||
seg->extents_moved = dm->mirror_region_size *
|
||||
numerator / lv->vg->extent_size;
|
||||
if (!(segtype = get_segtype_from_string(dm->cmd, type)))
|
||||
continue;
|
||||
|
||||
if (segtype->ops->target_percent &&
|
||||
!segtype->ops->target_percent(&dm->target_state, dm->mem,
|
||||
dm->cmd->cft, seg, params,
|
||||
&total_numerator,
|
||||
&total_denominator,
|
||||
percent)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (strcmp(type, "snapshot"))
|
||||
continue;
|
||||
|
||||
/* Snapshot */
|
||||
if (index(params, '/')) {
|
||||
if (sscanf(params, "%" PRIu64 "/%" PRIu64,
|
||||
&numerator, &denominator) == 2) {
|
||||
total_numerator += numerator;
|
||||
total_denominator += denominator;
|
||||
}
|
||||
continue;
|
||||
} else if (sscanf(params, "%f", &percent2) == 1) {
|
||||
*percent += percent2;
|
||||
*percent /= 2;
|
||||
}
|
||||
} while (next);
|
||||
|
||||
if (lv && (segh = list_next(&lv->segments, segh))) {
|
||||
@@ -506,7 +491,7 @@ static int _percent_run(struct dev_manager *dm, const char *name,
|
||||
|
||||
if (total_denominator)
|
||||
*percent = (float) total_numerator *100 / total_denominator;
|
||||
else
|
||||
else if (*percent < 0)
|
||||
*percent = 100;
|
||||
|
||||
log_debug("LV percent: %f", *percent);
|
||||
@@ -565,6 +550,55 @@ static int _rename(struct dev_layer *dl, char *newname)
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _suspend_or_resume(const char *name, action_t suspend)
|
||||
{
|
||||
int r;
|
||||
struct dm_task *dmt;
|
||||
int sus = (suspend == SUSPEND) ? 1 : 0;
|
||||
int task = sus ? DM_DEVICE_SUSPEND : DM_DEVICE_RESUME;
|
||||
|
||||
log_very_verbose("%s %s", sus ? "Suspending" : "Resuming", name);
|
||||
if (!(dmt = _setup_task(name, NULL, 0, task))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(r = dm_task_run(dmt)))
|
||||
log_error("Couldn't %s device '%s'", sus ? "suspend" : "resume",
|
||||
name);
|
||||
|
||||
dm_task_destroy(dmt);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _suspend(struct dev_layer *dl)
|
||||
{
|
||||
if (!dl->info.exists || dl->info.suspended)
|
||||
return 1;
|
||||
|
||||
if (!_suspend_or_resume(dl->name, SUSPEND)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dl->info.suspended = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _resume(struct dev_layer *dl)
|
||||
{
|
||||
if (!dl->info.exists || !dl->info.suspended)
|
||||
return 1;
|
||||
|
||||
if (!_suspend_or_resume(dl->name, RESUME)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dl->info.suspended = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _load(struct dev_manager *dm, struct dev_layer *dl, int task)
|
||||
{
|
||||
int r = 1;
|
||||
@@ -624,9 +658,9 @@ static int _load(struct dev_manager *dm, struct dev_layer *dl, int task)
|
||||
log_error("Couldn't load device '%s'.", dl->name);
|
||||
if ((dl->lv->minor >= 0 || dl->lv->major >= 0) &&
|
||||
_get_flag(dl, VISIBLE))
|
||||
log_error("Perhaps the persistent device number "
|
||||
"%d:%d is already in use?",
|
||||
dl->lv->major, dl->lv->minor);
|
||||
log_error("Perhaps the persistent device number "
|
||||
"%d:%d is already in use?",
|
||||
dl->lv->major, dl->lv->minor);
|
||||
}
|
||||
|
||||
if (!dm_task_get_info(dmt, &dl->info)) {
|
||||
@@ -641,6 +675,13 @@ static int _load(struct dev_manager *dm, struct dev_layer *dl, int task)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (_get_flag(dl, RESUME_IMMEDIATE) && dl->info.suspended &&
|
||||
!_resume(dl)) {
|
||||
stack;
|
||||
r = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
log_very_verbose("Activated %s %s %03u:%03u", dl->name,
|
||||
dl->dlid, dl->info.major, dl->info.minor);
|
||||
|
||||
@@ -687,55 +728,6 @@ static int _remove(struct dev_layer *dl)
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _suspend_or_resume(const char *name, action_t suspend)
|
||||
{
|
||||
int r;
|
||||
struct dm_task *dmt;
|
||||
int sus = (suspend == SUSPEND) ? 1 : 0;
|
||||
int task = sus ? DM_DEVICE_SUSPEND : DM_DEVICE_RESUME;
|
||||
|
||||
log_very_verbose("%s %s", sus ? "Suspending" : "Resuming", name);
|
||||
if (!(dmt = _setup_task(name, NULL, 0, task))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(r = dm_task_run(dmt)))
|
||||
log_error("Couldn't %s device '%s'", sus ? "suspend" : "resume",
|
||||
name);
|
||||
|
||||
dm_task_destroy(dmt);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _suspend(struct dev_layer *dl)
|
||||
{
|
||||
if (!dl->info.exists || dl->info.suspended)
|
||||
return 1;
|
||||
|
||||
if (!_suspend_or_resume(dl->name, SUSPEND)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dl->info.suspended = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _resume(struct dev_layer *dl)
|
||||
{
|
||||
if (!dl->info.exists || !dl->info.suspended)
|
||||
return 1;
|
||||
|
||||
if (!_suspend_or_resume(dl->name, RESUME)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dl->info.suspended = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The functions that populate the table in a dm_task as part of
|
||||
* a create/reload.
|
||||
@@ -750,98 +742,26 @@ static int _emit_target_line(struct dev_manager *dm, struct dm_task *dmt,
|
||||
size_t paramsize)
|
||||
{
|
||||
uint64_t esize = seg->lv->vg->extent_size;
|
||||
uint32_t s, start_area = 0u, areas = seg->area_count;
|
||||
int w = 0, tw = 0;
|
||||
int w = 0;
|
||||
const char *target = NULL;
|
||||
const char *trailing_space;
|
||||
int mirror_status;
|
||||
struct dev_layer *dl;
|
||||
char devbuf[10];
|
||||
int r;
|
||||
|
||||
switch (seg->type) {
|
||||
case SEG_SNAPSHOT:
|
||||
if (!seg->segtype->ops->compose_target_line) {
|
||||
log_error("_emit_target: Internal error: Can't handle "
|
||||
"SEG_SNAPSHOT");
|
||||
"segment type %s", seg->segtype->name);
|
||||
return 0;
|
||||
/* Target formats:
|
||||
* linear [device offset]+
|
||||
* striped #stripes stripe_size [device offset]+
|
||||
* mirror log_type #log_params [log_params]*
|
||||
* #mirrors [device offset]+
|
||||
*/
|
||||
case SEG_STRIPED:
|
||||
if (areas == 1)
|
||||
target = "linear";
|
||||
else if (areas > 1) {
|
||||
target = "striped";
|
||||
if ((tw = lvm_snprintf(params, paramsize, "%u %u ",
|
||||
areas, seg->stripe_size)) < 0)
|
||||
goto error;
|
||||
w = tw;
|
||||
} else {
|
||||
log_error("_emit_target: Internal error: SEG_STRIPED "
|
||||
"with no stripes");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case SEG_MIRRORED:
|
||||
mirror_status = MIRR_RUNNING;
|
||||
if (seg->status & PVMOVE) {
|
||||
if (seg->extents_moved == seg->area_len) {
|
||||
mirror_status = MIRR_COMPLETED;
|
||||
start_area = 1;
|
||||
} else if (dm->pvmove_mirror_count++) {
|
||||
mirror_status = MIRR_DISABLED;
|
||||
areas = 1;
|
||||
}
|
||||
}
|
||||
if (mirror_status != MIRR_RUNNING) {
|
||||
target = "linear";
|
||||
break;
|
||||
}
|
||||
target = "mirror";
|
||||
if ((tw = lvm_snprintf(params, paramsize, "core 1 %u %u ",
|
||||
dm->mirror_region_size, areas)) < 0)
|
||||
goto error;
|
||||
w = tw;
|
||||
break;
|
||||
}
|
||||
|
||||
for (s = start_area; s < areas; s++, w += tw) {
|
||||
trailing_space = (areas - s - 1) ? " " : "";
|
||||
if ((seg->area[s].type == AREA_PV &&
|
||||
(!seg->area[s].u.pv.pv || !seg->area[s].u.pv.pv->dev)) ||
|
||||
(seg->area[s].type == AREA_LV && !seg->area[s].u.lv.lv))
|
||||
tw = lvm_snprintf(params + w, paramsize - w,
|
||||
"%s 0%s", dm->stripe_filler,
|
||||
trailing_space);
|
||||
else if (seg->area[s].type == AREA_PV)
|
||||
tw = lvm_snprintf(params + w, paramsize - w,
|
||||
"%s %" PRIu64 "%s",
|
||||
dev_name(seg->area[s].u.pv.pv->dev),
|
||||
(seg->area[s].u.pv.pv->pe_start +
|
||||
(esize * seg->area[s].u.pv.pe)),
|
||||
trailing_space);
|
||||
else {
|
||||
if (!(dl = hash_lookup(dm->layers,
|
||||
seg->area[s].u.lv.lv->lvid.s))) {
|
||||
log_error("device layer %s missing from hash",
|
||||
seg->area[s].u.lv.lv->lvid.s);
|
||||
return 0;
|
||||
}
|
||||
if (!dm_format_dev(devbuf, sizeof(devbuf), dl->info.major, dl->info.minor)) {
|
||||
log_error("Failed to format device number as dm target (%u,%u)",
|
||||
dl->info.major, dl->info.minor);
|
||||
return 0;
|
||||
}
|
||||
tw = lvm_snprintf(params + w, paramsize - w,
|
||||
"%s %" PRIu64 "%s", devbuf,
|
||||
esize * seg->area[s].u.lv.le,
|
||||
trailing_space);
|
||||
}
|
||||
|
||||
if (tw < 0)
|
||||
goto error;
|
||||
if ((r = seg->segtype->ops->compose_target_line(dm, dm->mem,
|
||||
dm->cmd->cft,
|
||||
&dm->target_state, seg,
|
||||
params, paramsize,
|
||||
&target, &w,
|
||||
&dm->
|
||||
pvmove_mirror_count)) <=
|
||||
0) {
|
||||
stack;
|
||||
return r;
|
||||
}
|
||||
|
||||
log_debug("Adding target: %" PRIu64 " %" PRIu64 " %s %s",
|
||||
@@ -854,11 +774,62 @@ static int _emit_target_line(struct dev_manager *dm, struct dm_task *dmt,
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
error:
|
||||
log_debug("Insufficient space in params[%" PRIsize_t "] for target "
|
||||
"parameters.", paramsize);
|
||||
return -1;
|
||||
int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||
char *params, size_t paramsize, int *pos, int start_area,
|
||||
int areas)
|
||||
{
|
||||
uint32_t s;
|
||||
int tw = 0;
|
||||
const char *trailing_space;
|
||||
uint64_t esize = seg->lv->vg->extent_size;
|
||||
struct dev_layer *dl;
|
||||
char devbuf[10];
|
||||
|
||||
for (s = start_area; s < areas; s++, *pos += tw) {
|
||||
trailing_space = (areas - s - 1) ? " " : "";
|
||||
if ((seg->area[s].type == AREA_PV &&
|
||||
(!seg->area[s].u.pv.pv || !seg->area[s].u.pv.pv->dev)) ||
|
||||
(seg->area[s].type == AREA_LV && !seg->area[s].u.lv.lv))
|
||||
tw = lvm_snprintf(params + *pos, paramsize - *pos,
|
||||
"%s 0%s", dm->stripe_filler,
|
||||
trailing_space);
|
||||
else if (seg->area[s].type == AREA_PV)
|
||||
tw = lvm_snprintf(params + *pos, paramsize - *pos,
|
||||
"%s %" PRIu64 "%s",
|
||||
dev_name(seg->area[s].u.pv.pv->dev),
|
||||
(seg->area[s].u.pv.pv->pe_start +
|
||||
(esize * seg->area[s].u.pv.pe)),
|
||||
trailing_space);
|
||||
else {
|
||||
if (!(dl = hash_lookup(dm->layers,
|
||||
seg->area[s].u.lv.lv->lvid.s))) {
|
||||
log_error("device layer %s missing from hash",
|
||||
seg->area[s].u.lv.lv->lvid.s);
|
||||
return 0;
|
||||
}
|
||||
if (!dm_format_dev
|
||||
(devbuf, sizeof(devbuf), dl->info.major,
|
||||
dl->info.minor)) {
|
||||
log_error
|
||||
("Failed to format device number as dm target (%u,%u)",
|
||||
dl->info.major, dl->info.minor);
|
||||
return 0;
|
||||
}
|
||||
tw = lvm_snprintf(params + *pos, paramsize - *pos,
|
||||
"%s %" PRIu64 "%s", devbuf,
|
||||
esize * seg->area[s].u.lv.le,
|
||||
trailing_space);
|
||||
}
|
||||
|
||||
if (tw < 0) {
|
||||
stack;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _emit_target(struct dev_manager *dm, struct dm_task *dmt,
|
||||
@@ -883,6 +854,9 @@ static int _emit_target(struct dev_manager *dm, struct dm_task *dmt,
|
||||
if (ret >= 0)
|
||||
return ret;
|
||||
|
||||
log_debug("Insufficient space in params[%" PRIsize_t
|
||||
"] for target parameters.", paramsize);
|
||||
|
||||
paramsize *= 2;
|
||||
} while (paramsize < MAX_TARGET_PARAMSIZE);
|
||||
|
||||
@@ -1014,8 +988,8 @@ static int _populate_snapshot(struct dev_manager *dm,
|
||||
/*
|
||||
* dev_manager implementation.
|
||||
*/
|
||||
struct dev_manager *dev_manager_create(const char *vg_name,
|
||||
struct config_tree *cf)
|
||||
struct dev_manager *dev_manager_create(struct cmd_context *cmd,
|
||||
const char *vg_name)
|
||||
{
|
||||
struct pool *mem;
|
||||
struct dev_manager *dm;
|
||||
@@ -1030,23 +1004,16 @@ struct dev_manager *dev_manager_create(const char *vg_name,
|
||||
goto bad;
|
||||
}
|
||||
|
||||
dm->cmd = cmd;
|
||||
dm->mem = mem;
|
||||
dm->cf = cf;
|
||||
|
||||
if (!stripe_filler) {
|
||||
stripe_filler = find_config_str(cf->root,
|
||||
stripe_filler = find_config_str(cmd->cft->root,
|
||||
"activation/missing_stripe_filler",
|
||||
'/', DEFAULT_STRIPE_FILLER);
|
||||
DEFAULT_STRIPE_FILLER);
|
||||
}
|
||||
dm->stripe_filler = stripe_filler;
|
||||
|
||||
if (!mirror_region_size) {
|
||||
mirror_region_size = 2 * find_config_int(cf->root,
|
||||
"activation/mirror_region_size",
|
||||
'/',
|
||||
DEFAULT_MIRROR_REGION_SIZE);
|
||||
}
|
||||
dm->mirror_region_size = mirror_region_size;
|
||||
|
||||
if (!(dm->vg_name = pool_strdup(dm->mem, vg_name))) {
|
||||
stack;
|
||||
goto bad;
|
||||
@@ -1062,6 +1029,8 @@ struct dev_manager *dev_manager_create(const char *vg_name,
|
||||
list_init(&dm->remove_list);
|
||||
list_init(&dm->suspend_list);
|
||||
|
||||
dm->target_state = NULL;
|
||||
|
||||
return dm;
|
||||
|
||||
bad:
|
||||
@@ -1274,15 +1243,13 @@ static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv,
|
||||
/* Add dependencies for any LVs that segments refer to */
|
||||
list_iterate(segh, &lv->segments) {
|
||||
seg = list_item(segh, struct lv_segment);
|
||||
if (seg->type != SEG_STRIPED && seg->type != SEG_MIRRORED)
|
||||
continue;
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
if (seg->area[s].type != AREA_LV)
|
||||
continue;
|
||||
if (!str_list_add(dm->mem, &dl->pre_create,
|
||||
_build_dlid(dm->mem,
|
||||
seg->area[s].u.lv.
|
||||
lv->lvid.s, NULL))) {
|
||||
seg->area[s].u.lv.lv->
|
||||
lvid.s, NULL))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -1303,7 +1270,7 @@ static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv,
|
||||
_clear_flag(dlr, VISIBLE);
|
||||
_clear_flag(dlr, TOPLEVEL);
|
||||
_set_flag(dlr, REMOVE);
|
||||
|
||||
|
||||
/* add the dependency on the real device */
|
||||
if (!str_list_add(dm->mem, &dl->pre_create,
|
||||
pool_strdup(dm->mem, dlr->dlid))) {
|
||||
@@ -1328,6 +1295,9 @@ static int _expand_origin_real(struct dev_manager *dm,
|
||||
_clear_flag(dl, VISIBLE);
|
||||
_clear_flag(dl, TOPLEVEL);
|
||||
|
||||
/* Size changes must take effect before tables using it are reloaded */
|
||||
_set_flag(dl, RESUME_IMMEDIATE);
|
||||
|
||||
real_dlid = dl->dlid;
|
||||
|
||||
if (!(dl = _create_layer(dm, NULL, lv))) {
|
||||
@@ -1680,7 +1650,6 @@ static int _create_rec(struct dev_manager *dm, struct dev_layer *dl)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int _build_all_layers(struct dev_manager *dm, struct volume_group *vg)
|
||||
{
|
||||
struct list *lvh;
|
||||
@@ -1748,8 +1717,7 @@ static int _populate_pre_suspend_lists(struct dev_manager *dm)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!str_list_add(dm->mem, &dep->pre_create,
|
||||
dl->dlid)) {
|
||||
if (!str_list_add(dm->mem, &dep->pre_create, dl->dlid)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -1765,8 +1733,7 @@ static int _populate_pre_suspend_lists(struct dev_manager *dm)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!str_list_add(dm->mem, &dep->pre_suspend,
|
||||
dl->dlid)) {
|
||||
if (!str_list_add(dm->mem, &dep->pre_suspend, dl->dlid)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -1940,7 +1907,6 @@ static int _add_existing_layer(struct dev_manager *dm, const char *name)
|
||||
|
||||
static int _scan_existing_devices(struct dev_manager *dm)
|
||||
{
|
||||
|
||||
int r = 0;
|
||||
struct dm_names *names;
|
||||
unsigned next = 0;
|
||||
@@ -2079,6 +2045,73 @@ static int _remove_suspended_lvs(struct dev_manager *dm,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _targets_present(struct dev_manager *dm, struct list *lvs)
|
||||
{
|
||||
struct logical_volume *lv;
|
||||
struct list *lvh, *segh;
|
||||
struct segment_type *segtype;
|
||||
struct lv_segment *seg;
|
||||
int snapshots = 0, mirrors = 0;
|
||||
|
||||
list_iterate(lvh, lvs) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
|
||||
if (!snapshots)
|
||||
if (lv_is_cow(lv) || lv_is_origin(lv))
|
||||
snapshots = 1;
|
||||
|
||||
if (!mirrors)
|
||||
if (lv->status & PVMOVE)
|
||||
mirrors = 1;
|
||||
|
||||
if (lv->status & VIRTUAL) {
|
||||
list_iterate(segh, &lv->segments) {
|
||||
seg = list_item(segh, struct lv_segment);
|
||||
if (seg->segtype->ops->target_present &&
|
||||
!seg->segtype->ops->target_present()) {
|
||||
log_error("Can't expand LV: %s target "
|
||||
"support missing "
|
||||
"from kernel?",
|
||||
seg->segtype->name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mirrors) {
|
||||
if (!(segtype = get_segtype_from_string(dm->cmd, "mirror"))) {
|
||||
log_error("Can't expand LV: Mirror support "
|
||||
"missing from tools?");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!segtype->ops->target_present ||
|
||||
!segtype->ops->target_present()) {
|
||||
log_error("Can't expand LV: Mirror support missing "
|
||||
"from kernel?");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (snapshots) {
|
||||
if (!(segtype = get_segtype_from_string(dm->cmd, "snapshot"))) {
|
||||
log_error("Can't expand LV: Snapshot support "
|
||||
"missing from tools?");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!segtype->ops->target_present ||
|
||||
!segtype->ops->target_present()) {
|
||||
log_error("Can't expand LV: Snapshot support missing "
|
||||
"from kernel?");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _fill_in_active_list(struct dev_manager *dm, struct volume_group *vg)
|
||||
{
|
||||
char *dlid;
|
||||
@@ -2161,6 +2194,12 @@ static int _action(struct dev_manager *dm, struct logical_volume *lv,
|
||||
}
|
||||
}
|
||||
|
||||
if (!_targets_present(dm, &dm->active_list) ||
|
||||
!_targets_present(dm, &dm->reload_list)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_execute(dm, lv->vg)) {
|
||||
stack;
|
||||
return 0;
|
||||
@@ -2184,7 +2223,7 @@ int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv)
|
||||
return _action(dm, lv, SUSPEND);
|
||||
}
|
||||
|
||||
int dev_manager_mknodes(const struct logical_volume *lv)
|
||||
int dev_manager_lv_mknodes(const struct logical_volume *lv)
|
||||
{
|
||||
char *name;
|
||||
|
||||
@@ -2197,11 +2236,25 @@ int dev_manager_mknodes(const struct logical_volume *lv)
|
||||
return fs_add_lv(lv, name);
|
||||
}
|
||||
|
||||
int dev_manager_rmnodes(const struct logical_volume *lv)
|
||||
int dev_manager_lv_rmnodes(const struct logical_volume *lv)
|
||||
{
|
||||
return fs_del_lv(lv);
|
||||
}
|
||||
|
||||
int dev_manager_mknodes(void)
|
||||
{
|
||||
struct dm_task *dmt;
|
||||
int r;
|
||||
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_MKNODES)))
|
||||
return 0;
|
||||
|
||||
r = dm_task_run(dmt);
|
||||
|
||||
dm_task_destroy(dmt);
|
||||
return r;
|
||||
}
|
||||
|
||||
void dev_manager_exit(void)
|
||||
{
|
||||
dm_lib_exit();
|
||||
|
@@ -1,23 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_DEV_MANAGER_H
|
||||
#define _LVM_DEV_MANAGER_H
|
||||
|
||||
#include "metadata.h"
|
||||
#include "config.h"
|
||||
|
||||
struct logical_volume;
|
||||
struct cmd_context;
|
||||
struct dev_manager;
|
||||
struct dm_info;
|
||||
|
||||
/*
|
||||
* Constructor and destructor.
|
||||
*/
|
||||
struct dev_manager *dev_manager_create(const char *vg_name,
|
||||
struct config_tree *cf);
|
||||
struct dev_manager *dev_manager_create(struct cmd_context *cmd,
|
||||
const char *vg_name);
|
||||
void dev_manager_destroy(struct dev_manager *dm);
|
||||
void dev_manager_exit(void);
|
||||
|
||||
@@ -38,8 +46,9 @@ int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv);
|
||||
int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv);
|
||||
int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv);
|
||||
|
||||
int dev_manager_mknodes(const struct logical_volume *lv);
|
||||
int dev_manager_rmnodes(const struct logical_volume *lv);
|
||||
int dev_manager_lv_mknodes(const struct logical_volume *lv);
|
||||
int dev_manager_lv_rmnodes(const struct logical_volume *lv);
|
||||
int dev_manager_mknodes(void);
|
||||
|
||||
/*
|
||||
* Put the desired changes into effect.
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -11,6 +20,10 @@
|
||||
#include "lvm-file.h"
|
||||
#include "memlock.h"
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
# include "selinux.h"
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
@@ -166,6 +179,13 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
if (!set_selinux_context(lv_path)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_FS_H
|
||||
|
25
lib/activate/targets.h
Normal file
25
lib/activate/targets.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_TARGETS_H
|
||||
#define _LVM_TARGETS_H
|
||||
|
||||
struct dev_manager;
|
||||
struct lv_segment;
|
||||
|
||||
int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg, char *params, size_t paramsize, int *pos,
|
||||
int start_area, int areas);
|
||||
|
||||
#endif
|
13
lib/cache/lvmcache.c
vendored
13
lib/cache/lvmcache.c
vendored
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
|
18
lib/cache/lvmcache.h
vendored
18
lib/cache/lvmcache.h
vendored
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -11,7 +20,6 @@
|
||||
#include "dev-cache.h"
|
||||
#include "uuid.h"
|
||||
#include "label.h"
|
||||
#include "metadata.h"
|
||||
|
||||
#define ORPHAN ""
|
||||
|
||||
@@ -21,6 +29,10 @@
|
||||
/* LVM specific per-volume info */
|
||||
/* Eventual replacement for struct physical_volume perhaps? */
|
||||
|
||||
struct cmd_context;
|
||||
struct format_type;
|
||||
struct volume_group;
|
||||
|
||||
struct lvmcache_vginfo {
|
||||
struct list list; /* Join these vginfos together */
|
||||
struct list infos; /* List head for lvmcache_infos */
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_ERRORS_H
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -14,6 +23,7 @@
|
||||
#include "activate.h"
|
||||
#include "filter.h"
|
||||
#include "filter-composite.h"
|
||||
#include "filter-md.h"
|
||||
#include "filter-persistent.h"
|
||||
#include "filter-regex.h"
|
||||
#include "filter-sysfs.h"
|
||||
@@ -22,6 +32,9 @@
|
||||
#include "format-text.h"
|
||||
#include "display.h"
|
||||
#include "memlock.h"
|
||||
#include "str_list.h"
|
||||
#include "segtypes.h"
|
||||
#include "lvmcache.h"
|
||||
|
||||
#ifdef HAVE_LIBDL
|
||||
#include "sharedlib.h"
|
||||
@@ -31,8 +44,13 @@
|
||||
#include "format1.h"
|
||||
#endif
|
||||
|
||||
#ifdef POOL_INTERNAL
|
||||
#include "format_pool.h"
|
||||
#endif
|
||||
|
||||
#include <locale.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
|
||||
@@ -68,7 +86,7 @@ static void _init_logging(struct cmd_context *cmd)
|
||||
|
||||
/* Syslog */
|
||||
cmd->default_settings.syslog =
|
||||
find_config_int(cmd->cf->root, "log/syslog", '/', DEFAULT_SYSLOG);
|
||||
find_config_int(cmd->cft->root, "log/syslog", DEFAULT_SYSLOG);
|
||||
if (cmd->default_settings.syslog != 1)
|
||||
fin_syslog();
|
||||
|
||||
@@ -77,47 +95,50 @@ static void _init_logging(struct cmd_context *cmd)
|
||||
|
||||
/* Debug level for log file output */
|
||||
cmd->default_settings.debug =
|
||||
find_config_int(cmd->cf->root, "log/level", '/', DEFAULT_LOGLEVEL);
|
||||
find_config_int(cmd->cft->root, "log/level", DEFAULT_LOGLEVEL);
|
||||
init_debug(cmd->default_settings.debug);
|
||||
|
||||
/* Verbose level for tty output */
|
||||
cmd->default_settings.verbose =
|
||||
find_config_int(cmd->cf->root, "log/verbose", '/', DEFAULT_VERBOSE);
|
||||
init_verbose(cmd->default_settings.verbose);
|
||||
find_config_int(cmd->cft->root, "log/verbose", DEFAULT_VERBOSE);
|
||||
init_verbose(cmd->default_settings.verbose + VERBOSE_BASE_LEVEL);
|
||||
|
||||
/* Log message formatting */
|
||||
init_indent(find_config_int(cmd->cf->root, "log/indent", '/',
|
||||
init_indent(find_config_int(cmd->cft->root, "log/indent",
|
||||
DEFAULT_INDENT));
|
||||
|
||||
cmd->default_settings.msg_prefix = find_config_str(cmd->cf->root,
|
||||
"log/prefix", '/',
|
||||
cmd->default_settings.msg_prefix = find_config_str(cmd->cft->root,
|
||||
"log/prefix",
|
||||
DEFAULT_MSG_PREFIX);
|
||||
init_msg_prefix(cmd->default_settings.msg_prefix);
|
||||
|
||||
cmd->default_settings.cmd_name = find_config_int(cmd->cf->root,
|
||||
cmd->default_settings.cmd_name = find_config_int(cmd->cft->root,
|
||||
"log/command_names",
|
||||
'/', DEFAULT_CMD_NAME);
|
||||
DEFAULT_CMD_NAME);
|
||||
init_cmd_name(cmd->default_settings.cmd_name);
|
||||
|
||||
/* Test mode */
|
||||
cmd->default_settings.test =
|
||||
find_config_int(cmd->cf->root, "global/test", '/', 0);
|
||||
find_config_int(cmd->cft->root, "global/test", 0);
|
||||
|
||||
/* Settings for logging to file */
|
||||
if (find_config_int(cmd->cf->root, "log/overwrite", '/',
|
||||
DEFAULT_OVERWRITE))
|
||||
if (find_config_int(cmd->cft->root, "log/overwrite", DEFAULT_OVERWRITE))
|
||||
append = 0;
|
||||
|
||||
log_file = find_config_str(cmd->cf->root, "log/file", '/', 0);
|
||||
if (log_file)
|
||||
init_log_file(log_file, append);
|
||||
log_file = find_config_str(cmd->cft->root, "log/file", 0);
|
||||
|
||||
log_file = find_config_str(cmd->cf->root, "log/activate_file", '/', 0);
|
||||
if (log_file) {
|
||||
release_log_memory();
|
||||
fin_log();
|
||||
init_log_file(log_file, append);
|
||||
}
|
||||
|
||||
log_file = find_config_str(cmd->cft->root, "log/activate_file", 0);
|
||||
if (log_file)
|
||||
init_log_direct(log_file, append);
|
||||
|
||||
init_log_while_suspended(find_config_int(cmd->cf->root,
|
||||
"log/activation", '/', 0));
|
||||
init_log_while_suspended(find_config_int(cmd->cft->root,
|
||||
"log/activation", 0));
|
||||
|
||||
t = time(NULL);
|
||||
log_verbose("Logging initialised at %s", ctime(&t));
|
||||
@@ -133,8 +154,8 @@ static int _process_config(struct cmd_context *cmd)
|
||||
mode_t old_umask;
|
||||
|
||||
/* umask */
|
||||
cmd->default_settings.umask = find_config_int(cmd->cf->root,
|
||||
"global/umask", '/',
|
||||
cmd->default_settings.umask = find_config_int(cmd->cft->root,
|
||||
"global/umask",
|
||||
DEFAULT_UMASK);
|
||||
|
||||
if ((old_umask = umask((mode_t) cmd->default_settings.umask)) !=
|
||||
@@ -143,8 +164,8 @@ static int _process_config(struct cmd_context *cmd)
|
||||
|
||||
/* dev dir */
|
||||
if (lvm_snprintf(cmd->dev_dir, sizeof(cmd->dev_dir), "%s/",
|
||||
find_config_str(cmd->cf->root, "devices/dir",
|
||||
'/', DEFAULT_DEV_DIR)) < 0) {
|
||||
find_config_str(cmd->cft->root, "devices/dir",
|
||||
DEFAULT_DEV_DIR)) < 0) {
|
||||
log_error("Device directory given in config file too long");
|
||||
return 0;
|
||||
}
|
||||
@@ -154,27 +175,25 @@ static int _process_config(struct cmd_context *cmd)
|
||||
|
||||
/* proc dir */
|
||||
if (lvm_snprintf(cmd->proc_dir, sizeof(cmd->proc_dir), "%s",
|
||||
find_config_str(cmd->cf->root, "global/proc",
|
||||
'/', DEFAULT_PROC_DIR)) < 0) {
|
||||
find_config_str(cmd->cft->root, "global/proc",
|
||||
DEFAULT_PROC_DIR)) < 0) {
|
||||
log_error("Device directory given in config file too long");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* activation? */
|
||||
cmd->default_settings.activation = find_config_int(cmd->cf->root,
|
||||
cmd->default_settings.activation = find_config_int(cmd->cft->root,
|
||||
"global/activation",
|
||||
'/',
|
||||
DEFAULT_ACTIVATION);
|
||||
set_activation(cmd->default_settings.activation);
|
||||
|
||||
cmd->default_settings.suffix = find_config_int(cmd->cf->root,
|
||||
cmd->default_settings.suffix = find_config_int(cmd->cft->root,
|
||||
"global/suffix",
|
||||
'/', DEFAULT_SUFFIX);
|
||||
DEFAULT_SUFFIX);
|
||||
|
||||
if (!(cmd->default_settings.unit_factor =
|
||||
units_to_bytes(find_config_str(cmd->cf->root,
|
||||
units_to_bytes(find_config_str(cmd->cft->root,
|
||||
"global/units",
|
||||
'/',
|
||||
DEFAULT_UNITS),
|
||||
&cmd->default_settings.unit_type))) {
|
||||
log_error("Invalid units specification");
|
||||
@@ -184,57 +203,266 @@ static int _process_config(struct cmd_context *cmd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Find and read config file */
|
||||
static int _init_config(struct cmd_context *cmd)
|
||||
static int _set_tag(struct cmd_context *cmd, const char *tag)
|
||||
{
|
||||
struct stat info;
|
||||
char config_file[PATH_MAX] = "";
|
||||
log_very_verbose("Setting host tag: %s", pool_strdup(cmd->libmem, tag));
|
||||
|
||||
if (!(cmd->cf = create_config_tree())) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* No config file if LVM_SYSTEM_DIR is empty */
|
||||
if (!*cmd->sys_dir)
|
||||
return 1;
|
||||
|
||||
if (lvm_snprintf(config_file, sizeof(config_file),
|
||||
"%s/lvm.conf", cmd->sys_dir) < 0) {
|
||||
log_error("LVM_SYSTEM_DIR was too long");
|
||||
destroy_config_tree(cmd->cf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Is there a config file? */
|
||||
if (stat(config_file, &info) == -1) {
|
||||
if (errno == ENOENT)
|
||||
return 1;
|
||||
log_sys_error("stat", config_file);
|
||||
destroy_config_tree(cmd->cf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!read_config_file(cmd->cf, config_file)) {
|
||||
log_error("Failed to load config file %s", config_file);
|
||||
destroy_config_tree(cmd->cf);
|
||||
if (!str_list_add(cmd->libmem, &cmd->tags, tag)) {
|
||||
log_error("_set_tag: str_list_add %s failed", tag);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _init_dev_cache(struct cmd_context *cmd)
|
||||
static int _check_host_filters(struct cmd_context *cmd, struct config_node *hn,
|
||||
int *passes)
|
||||
{
|
||||
struct config_node *cn;
|
||||
struct config_value *cv;
|
||||
|
||||
*passes = 1;
|
||||
|
||||
for (cn = hn; cn; cn = cn->sib) {
|
||||
if (!cn->v)
|
||||
continue;
|
||||
if (!strcmp(cn->key, "host_list")) {
|
||||
*passes = 0;
|
||||
if (cn->v->type == CFG_EMPTY_ARRAY)
|
||||
continue;
|
||||
for (cv = cn->v; cv; cv = cv->next) {
|
||||
if (cv->type != CFG_STRING) {
|
||||
log_error("Invalid hostname string "
|
||||
"for tag %s", cn->key);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(cv->v.str, cmd->hostname)) {
|
||||
*passes = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!strcmp(cn->key, "host_filter")) {
|
||||
log_error("host_filter not supported yet");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _init_tags(struct cmd_context *cmd, struct config_tree *cft)
|
||||
{
|
||||
const struct config_node *tn, *cn;
|
||||
const char *tag;
|
||||
int passes;
|
||||
|
||||
if (!(tn = find_config_node(cft->root, "tags")) || !tn->child)
|
||||
return 1;
|
||||
|
||||
/* NB hosttags 0 when already 1 intentionally does not delete the tag */
|
||||
if (!cmd->hosttags && find_config_int(cft->root, "tags/hosttags",
|
||||
DEFAULT_HOSTTAGS)) {
|
||||
/* FIXME Strip out invalid chars: only A-Za-z0-9_+.- */
|
||||
if (!_set_tag(cmd, cmd->hostname)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
cmd->hosttags = 1;
|
||||
}
|
||||
|
||||
for (cn = tn->child; cn; cn = cn->sib) {
|
||||
if (cn->v)
|
||||
continue;
|
||||
tag = cn->key;
|
||||
if (*tag == '@')
|
||||
tag++;
|
||||
if (!validate_name(tag)) {
|
||||
log_error("Invalid tag in config file: %s", cn->key);
|
||||
return 0;
|
||||
}
|
||||
if (cn->child) {
|
||||
passes = 0;
|
||||
if (!_check_host_filters(cmd, cn->child, &passes)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!passes)
|
||||
continue;
|
||||
}
|
||||
if (!_set_tag(cmd, tag)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _load_config_file(struct cmd_context *cmd, const char *tag)
|
||||
{
|
||||
char config_file[PATH_MAX] = "";
|
||||
const char *filler = "";
|
||||
struct stat info;
|
||||
struct config_tree_list *cfl;
|
||||
|
||||
if (*tag)
|
||||
filler = "_";
|
||||
|
||||
if (lvm_snprintf(config_file, sizeof(config_file), "%s/lvm%s%s.conf",
|
||||
cmd->sys_dir, filler, tag) < 0) {
|
||||
log_error("LVM_SYSTEM_DIR or tag was too long");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(cfl = pool_alloc(cmd->libmem, sizeof(*cfl)))) {
|
||||
log_error("config_tree_list allocation failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(cfl->cft = create_config_tree(config_file))) {
|
||||
log_error("config_tree allocation failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Is there a config file? */
|
||||
if (stat(config_file, &info) == -1) {
|
||||
if (errno == ENOENT) {
|
||||
list_add(&cmd->config_files, &cfl->list);
|
||||
goto out;
|
||||
}
|
||||
log_sys_error("stat", config_file);
|
||||
destroy_config_tree(cfl->cft);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_very_verbose("Loading config file: %s", config_file);
|
||||
if (!read_config_file(cfl->cft)) {
|
||||
log_error("Failed to load config file %s", config_file);
|
||||
destroy_config_tree(cfl->cft);
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_add(&cmd->config_files, &cfl->list);
|
||||
|
||||
out:
|
||||
if (*tag)
|
||||
_init_tags(cmd, cfl->cft);
|
||||
else
|
||||
/* Use temporary copy of lvm.conf while loading other files */
|
||||
cmd->cft = cfl->cft;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Find and read first config file */
|
||||
static int _init_lvm_conf(struct cmd_context *cmd)
|
||||
{
|
||||
/* No config file if LVM_SYSTEM_DIR is empty */
|
||||
if (!*cmd->sys_dir) {
|
||||
if (!(cmd->cft = create_config_tree(NULL))) {
|
||||
log_error("Failed to create config tree");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!_load_config_file(cmd, "")) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Read any additional config files */
|
||||
static int _init_tag_configs(struct cmd_context *cmd)
|
||||
{
|
||||
struct str_list *sl;
|
||||
|
||||
/* Tag list may grow while inside this loop */
|
||||
list_iterate_items(sl, &cmd->tags) {
|
||||
if (!_load_config_file(cmd, sl->str)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _merge_config_files(struct cmd_context *cmd)
|
||||
{
|
||||
struct config_tree_list *cfl;
|
||||
|
||||
/* Replace temporary duplicate copy of lvm.conf */
|
||||
if (cmd->cft->root) {
|
||||
if (!(cmd->cft = create_config_tree(NULL))) {
|
||||
log_error("Failed to create config tree");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
list_iterate_items(cfl, &cmd->config_files) {
|
||||
/* Merge all config trees into cmd->cft using merge/tag rules */
|
||||
if (!merge_config_tree(cmd, cmd->cft, cfl->cft)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _destroy_tags(struct cmd_context *cmd)
|
||||
{
|
||||
struct list *slh, *slht;
|
||||
|
||||
list_iterate_safe(slh, slht, &cmd->tags) {
|
||||
list_del(slh);
|
||||
}
|
||||
}
|
||||
|
||||
int config_files_changed(struct cmd_context *cmd)
|
||||
{
|
||||
struct config_tree_list *cfl;
|
||||
|
||||
list_iterate_items(cfl, &cmd->config_files) {
|
||||
if (config_file_changed(cfl->cft))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _destroy_tag_configs(struct cmd_context *cmd)
|
||||
{
|
||||
struct config_tree_list *cfl;
|
||||
|
||||
if (cmd->cft && cmd->cft->root) {
|
||||
destroy_config_tree(cmd->cft);
|
||||
cmd->cft = NULL;
|
||||
}
|
||||
|
||||
list_iterate_items(cfl, &cmd->config_files) {
|
||||
destroy_config_tree(cfl->cft);
|
||||
}
|
||||
|
||||
list_init(&cmd->config_files);
|
||||
}
|
||||
|
||||
static int _init_dev_cache(struct cmd_context *cmd)
|
||||
{
|
||||
const struct config_node *cn;
|
||||
struct config_value *cv;
|
||||
|
||||
if (!dev_cache_init()) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(cn = find_config_node(cmd->cf->root, "devices/scan", '/'))) {
|
||||
if (!(cn = find_config_node(cmd->cft->root, "devices/scan"))) {
|
||||
if (!dev_cache_add_dir("/dev")) {
|
||||
log_error("Failed to add /dev to internal "
|
||||
"device cache");
|
||||
@@ -262,25 +490,35 @@ static int _init_dev_cache(struct cmd_context *cmd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define MAX_FILTERS 3
|
||||
#define MAX_FILTERS 4
|
||||
|
||||
static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
|
||||
{
|
||||
unsigned nr_filt = 0;
|
||||
struct config_node *cn;
|
||||
const struct config_node *cn;
|
||||
struct dev_filter *filters[MAX_FILTERS];
|
||||
|
||||
memset(filters, 0, sizeof(filters));
|
||||
|
||||
/* sysfs filter */
|
||||
if (find_config_bool(cmd->cf->root, "devices/sysfs_scan", '/',
|
||||
/*
|
||||
* Filters listed in order: top one gets applied first.
|
||||
* Failure to initialise some filters is not fatal.
|
||||
* Update MAX_FILTERS definition above when adding new filters.
|
||||
*/
|
||||
|
||||
/*
|
||||
* sysfs filter. Only available on 2.6 kernels. Non-critical.
|
||||
* Listed first because it's very efficient at eliminating
|
||||
* unavailable devices.
|
||||
*/
|
||||
if (find_config_bool(cmd->cft->root, "devices/sysfs_scan",
|
||||
DEFAULT_SYSFS_SCAN)) {
|
||||
if ((filters[nr_filt] = sysfs_filter_create(cmd->proc_dir)))
|
||||
nr_filt++;
|
||||
}
|
||||
|
||||
/* regex filter */
|
||||
if (!(cn = find_config_node(cmd->cf->root, "devices/filter", '/')))
|
||||
/* regex filter. Optional. */
|
||||
if (!(cn = find_config_node(cmd->cft->root, "devices/filter")))
|
||||
log_debug("devices/filter not found in config file: no regex "
|
||||
"filter installed");
|
||||
|
||||
@@ -289,14 +527,21 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* device type filter */
|
||||
cn = find_config_node(cmd->cf->root, "devices/types", '/');
|
||||
/* device type filter. Required. */
|
||||
cn = find_config_node(cmd->cft->root, "devices/types");
|
||||
if (!(filters[nr_filt++] = lvm_type_filter_create(cmd->proc_dir, cn))) {
|
||||
log_error("Failed to create lvm type filter");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* only build a composite filter if we really need it */
|
||||
/* md component filter. Optional, non-critical. */
|
||||
if (find_config_bool(cmd->cft->root, "devices/md_component_detection",
|
||||
DEFAULT_MD_COMPONENT_DETECTION)) {
|
||||
if ((filters[nr_filt] = md_filter_create()))
|
||||
nr_filt++;
|
||||
}
|
||||
|
||||
/* Only build a composite filter if we really need it. */
|
||||
return (nr_filt == 1) ?
|
||||
filters[0] : composite_filter_create(nr_filt, filters);
|
||||
}
|
||||
@@ -320,22 +565,22 @@ static int _init_filters(struct cmd_context *cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_cache =
|
||||
find_config_str(cmd->cf->root, "devices/cache", '/', cache_file);
|
||||
dev_cache = find_config_str(cmd->cft->root, "devices/cache",
|
||||
cache_file);
|
||||
if (!(f4 = persistent_filter_create(f3, dev_cache))) {
|
||||
log_error("Failed to create persistent device filter");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Should we ever dump persistent filter state? */
|
||||
if (find_config_int(cmd->cf->root, "devices/write_cache_state", '/', 1))
|
||||
if (find_config_int(cmd->cft->root, "devices/write_cache_state", 1))
|
||||
cmd->dump_filter = 1;
|
||||
|
||||
if (!*cmd->sys_dir)
|
||||
cmd->dump_filter = 0;
|
||||
|
||||
if (!stat(dev_cache, &st) &&
|
||||
(st.st_mtime > config_file_timestamp(cmd->cf)) &&
|
||||
(st.st_mtime > config_file_timestamp(cmd->cft)) &&
|
||||
!persistent_filter_load(f4))
|
||||
log_verbose("Failed to load existing device cache from %s",
|
||||
dev_cache);
|
||||
@@ -353,7 +598,7 @@ static int _init_formats(struct cmd_context *cmd)
|
||||
struct list *fmth;
|
||||
|
||||
#ifdef HAVE_LIBDL
|
||||
struct config_node *cn;
|
||||
const struct config_node *cn;
|
||||
#endif
|
||||
|
||||
label_init();
|
||||
@@ -365,10 +610,16 @@ static int _init_formats(struct cmd_context *cmd)
|
||||
list_add(&cmd->formats, &fmt->list);
|
||||
#endif
|
||||
|
||||
#ifdef POOL_INTERNAL
|
||||
if (!(fmt = init_pool_format(cmd)))
|
||||
return 0;
|
||||
fmt->library = NULL;
|
||||
list_add(&cmd->formats, &fmt->list);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBDL
|
||||
/* Load any formats in shared libs */
|
||||
if ((cn = find_config_node(cmd->cf->root, "global/format_libraries",
|
||||
'/'))) {
|
||||
if ((cn = find_config_node(cmd->cft->root, "global/format_libraries"))) {
|
||||
|
||||
struct config_value *cv;
|
||||
struct format_type *(*init_format_fn) (struct cmd_context *);
|
||||
@@ -380,7 +631,7 @@ static int _init_formats(struct cmd_context *cmd)
|
||||
"global/format_libraries");
|
||||
return 0;
|
||||
}
|
||||
if (!(lib = load_shared_library(cmd->cf, cv->v.str,
|
||||
if (!(lib = load_shared_library(cmd->cft, cv->v.str,
|
||||
"format"))) {
|
||||
stack;
|
||||
return 0;
|
||||
@@ -408,7 +659,7 @@ static int _init_formats(struct cmd_context *cmd)
|
||||
|
||||
cmd->fmt_backup = fmt;
|
||||
|
||||
format = find_config_str(cmd->cf->root, "global/format", '/',
|
||||
format = find_config_str(cmd->cft->root, "global/format",
|
||||
DEFAULT_FORMAT);
|
||||
|
||||
list_iterate(fmth, &cmd->formats) {
|
||||
@@ -424,6 +675,119 @@ static int _init_formats(struct cmd_context *cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _init_segtypes(struct cmd_context *cmd)
|
||||
{
|
||||
struct segment_type *segtype;
|
||||
|
||||
#ifdef HAVE_LIBDL
|
||||
const struct config_node *cn;
|
||||
#endif
|
||||
|
||||
if (!(segtype = init_striped_segtype(cmd)))
|
||||
return 0;
|
||||
segtype->library = NULL;
|
||||
list_add(&cmd->segtypes, &segtype->list);
|
||||
|
||||
if (!(segtype = init_zero_segtype(cmd)))
|
||||
return 0;
|
||||
segtype->library = NULL;
|
||||
list_add(&cmd->segtypes, &segtype->list);
|
||||
|
||||
if (!(segtype = init_error_segtype(cmd)))
|
||||
return 0;
|
||||
segtype->library = NULL;
|
||||
list_add(&cmd->segtypes, &segtype->list);
|
||||
|
||||
#ifdef SNAPSHOT_INTERNAL
|
||||
if (!(segtype = init_snapshot_segtype(cmd)))
|
||||
return 0;
|
||||
segtype->library = NULL;
|
||||
list_add(&cmd->segtypes, &segtype->list);
|
||||
#endif
|
||||
|
||||
#ifdef MIRRORED_INTERNAL
|
||||
if (!(segtype = init_mirrored_segtype(cmd)))
|
||||
return 0;
|
||||
segtype->library = NULL;
|
||||
list_add(&cmd->segtypes, &segtype->list);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBDL
|
||||
/* Load any formats in shared libs */
|
||||
if ((cn = find_config_node(cmd->cft->root, "global/segment_libraries"))) {
|
||||
|
||||
struct config_value *cv;
|
||||
struct segment_type *(*init_segtype_fn) (struct cmd_context *);
|
||||
void *lib;
|
||||
struct list *sgtl, *tmp;
|
||||
struct segment_type *segtype2;
|
||||
|
||||
for (cv = cn->v; cv; cv = cv->next) {
|
||||
if (cv->type != CFG_STRING) {
|
||||
log_error("Invalid string in config file: "
|
||||
"global/segment_libraries");
|
||||
return 0;
|
||||
}
|
||||
if (!(lib = load_shared_library(cmd->cft, cv->v.str,
|
||||
"segment type"))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(init_segtype_fn = dlsym(lib, "init_segtype"))) {
|
||||
log_error("Shared library %s does not contain "
|
||||
"segment type functions", cv->v.str);
|
||||
dlclose(lib);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(segtype = init_segtype_fn(cmd)))
|
||||
return 0;
|
||||
segtype->library = lib;
|
||||
list_add(&cmd->segtypes, &segtype->list);
|
||||
|
||||
list_iterate_safe(sgtl, tmp, &cmd->segtypes) {
|
||||
segtype2 = list_item(sgtl, struct segment_type);
|
||||
if (!strcmp(segtype2->name, segtype->name)) {
|
||||
log_error("Duplicate segment type %s: "
|
||||
"unloading shared library %s",
|
||||
segtype->name, cv->v.str);
|
||||
list_del(&segtype->list);
|
||||
segtype->ops->destroy(segtype);
|
||||
dlclose(lib);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _init_hostname(struct cmd_context *cmd)
|
||||
{
|
||||
struct utsname uts;
|
||||
|
||||
if (uname(&uts)) {
|
||||
log_sys_error("uname", "_init_hostname");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(cmd->hostname = pool_strdup(cmd->libmem, uts.nodename))) {
|
||||
log_error("_init_hostname: pool_strdup failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(cmd->kernel_vsn = pool_strdup(cmd->libmem, uts.release))) {
|
||||
log_error("_init_hostname: pool_strdup kernel_vsn failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Entry point */
|
||||
struct cmd_context *create_toolcontext(struct arg *the_args)
|
||||
{
|
||||
@@ -448,7 +812,11 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
|
||||
}
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
cmd->args = the_args;
|
||||
cmd->hosttags = 0;
|
||||
list_init(&cmd->formats);
|
||||
list_init(&cmd->segtypes);
|
||||
list_init(&cmd->tags);
|
||||
list_init(&cmd->config_files);
|
||||
|
||||
strcpy(cmd->sys_dir, DEFAULT_SYS_DIR);
|
||||
|
||||
@@ -459,11 +827,28 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
|
||||
if (*cmd->sys_dir && !create_dir(cmd->sys_dir))
|
||||
goto error;
|
||||
|
||||
if (!_init_config(cmd))
|
||||
if (!(cmd->libmem = pool_create(4 * 1024))) {
|
||||
log_error("Library memory pool creation failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_init_lvm_conf(cmd))
|
||||
goto error;
|
||||
|
||||
_init_logging(cmd);
|
||||
|
||||
if (!_init_hostname(cmd))
|
||||
goto error;
|
||||
|
||||
if (!_init_tags(cmd, cmd->cft))
|
||||
goto error;
|
||||
|
||||
if (!_init_tag_configs(cmd))
|
||||
goto error;
|
||||
|
||||
if (!_merge_config_files(cmd))
|
||||
goto error;
|
||||
|
||||
if (!_process_config(cmd))
|
||||
goto error;
|
||||
|
||||
@@ -483,8 +868,12 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
|
||||
if (!_init_formats(cmd))
|
||||
goto error;
|
||||
|
||||
if (!_init_segtypes(cmd))
|
||||
goto error;
|
||||
|
||||
cmd->current_settings = cmd->default_settings;
|
||||
|
||||
cmd->config_valid = 1;
|
||||
return cmd;
|
||||
|
||||
error:
|
||||
@@ -510,6 +899,83 @@ static void _destroy_formats(struct list *formats)
|
||||
}
|
||||
}
|
||||
|
||||
static void _destroy_segtypes(struct list *segtypes)
|
||||
{
|
||||
struct list *sgtl, *tmp;
|
||||
struct segment_type *segtype;
|
||||
void *lib;
|
||||
|
||||
list_iterate_safe(sgtl, tmp, segtypes) {
|
||||
segtype = list_item(sgtl, struct segment_type);
|
||||
list_del(&segtype->list);
|
||||
lib = segtype->library;
|
||||
segtype->ops->destroy(segtype);
|
||||
#ifdef HAVE_LIBDL
|
||||
if (lib)
|
||||
dlclose(lib);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int refresh_toolcontext(struct cmd_context *cmd)
|
||||
{
|
||||
log_verbose("Reloading config files");
|
||||
|
||||
if (cmd->config_valid) {
|
||||
if (cmd->dump_filter)
|
||||
persistent_filter_dump(cmd->filter);
|
||||
}
|
||||
|
||||
activation_exit();
|
||||
lvmcache_destroy();
|
||||
label_exit();
|
||||
_destroy_segtypes(&cmd->segtypes);
|
||||
_destroy_formats(&cmd->formats);
|
||||
if (cmd->filter) {
|
||||
cmd->filter->destroy(cmd->filter);
|
||||
cmd->filter = NULL;
|
||||
}
|
||||
dev_cache_exit();
|
||||
_destroy_tags(cmd);
|
||||
_destroy_tag_configs(cmd);
|
||||
|
||||
cmd->config_valid = 0;
|
||||
|
||||
cmd->hosttags = 0;
|
||||
|
||||
if (!_init_lvm_conf(cmd))
|
||||
return 0;
|
||||
|
||||
_init_logging(cmd);
|
||||
|
||||
if (!_init_tags(cmd, cmd->cft))
|
||||
return 0;
|
||||
|
||||
if (!_init_tag_configs(cmd))
|
||||
return 0;
|
||||
|
||||
if (!_merge_config_files(cmd))
|
||||
return 0;
|
||||
|
||||
if (!_process_config(cmd))
|
||||
return 0;
|
||||
|
||||
if (!_init_dev_cache(cmd))
|
||||
return 0;
|
||||
|
||||
if (!_init_filters(cmd))
|
||||
return 0;
|
||||
|
||||
if (!_init_formats(cmd))
|
||||
return 0;
|
||||
|
||||
if (!_init_segtypes(cmd))
|
||||
return 0;
|
||||
|
||||
cmd->config_valid = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void destroy_toolcontext(struct cmd_context *cmd)
|
||||
{
|
||||
if (cmd->dump_filter)
|
||||
@@ -518,11 +984,14 @@ void destroy_toolcontext(struct cmd_context *cmd)
|
||||
activation_exit();
|
||||
lvmcache_destroy();
|
||||
label_exit();
|
||||
_destroy_segtypes(&cmd->segtypes);
|
||||
_destroy_formats(&cmd->formats);
|
||||
cmd->filter->destroy(cmd->filter);
|
||||
pool_destroy(cmd->mem);
|
||||
dev_cache_exit();
|
||||
destroy_config_tree(cmd->cf);
|
||||
_destroy_tags(cmd);
|
||||
_destroy_tag_configs(cmd);
|
||||
pool_destroy(cmd->libmem);
|
||||
dbg_free(cmd);
|
||||
|
||||
release_log_memory();
|
||||
|
@@ -1,17 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_TOOLCONTEXT_H
|
||||
#define _LVM_TOOLCONTEXT_H
|
||||
|
||||
#include "dev-cache.h"
|
||||
#include "config.h"
|
||||
#include "pool.h"
|
||||
#include "metadata.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
@@ -39,16 +45,21 @@ struct config_info {
|
||||
mode_t umask;
|
||||
};
|
||||
|
||||
struct config_tree;
|
||||
|
||||
/* FIXME Split into tool & library contexts */
|
||||
/* command-instance-related variables needed by library */
|
||||
struct cmd_context {
|
||||
/* format handler allocates all objects from here */
|
||||
struct pool *mem;
|
||||
struct pool *libmem; /* For permanent config data */
|
||||
struct pool *mem; /* Transient: Cleared between each command */
|
||||
|
||||
const struct format_type *fmt; /* Current format to use by default */
|
||||
struct format_type *fmt_backup; /* Format to use for backups */
|
||||
|
||||
struct list formats; /* Available formats */
|
||||
struct list segtypes; /* Available segment types */
|
||||
const char *hostname;
|
||||
const char *kernel_vsn;
|
||||
|
||||
char *cmd_line;
|
||||
struct command *command;
|
||||
@@ -58,10 +69,16 @@ struct cmd_context {
|
||||
struct dev_filter *filter;
|
||||
int dump_filter; /* Dump filter when exiting? */
|
||||
|
||||
struct config_tree *cf;
|
||||
struct list config_files;
|
||||
int config_valid;
|
||||
struct config_tree *cft;
|
||||
struct config_info default_settings;
|
||||
struct config_info current_settings;
|
||||
|
||||
/* List of defined tags */
|
||||
struct list tags;
|
||||
int hosttags;
|
||||
|
||||
char sys_dir[PATH_MAX];
|
||||
char dev_dir[PATH_MAX];
|
||||
char proc_dir[PATH_MAX];
|
||||
@@ -69,5 +86,7 @@ struct cmd_context {
|
||||
|
||||
struct cmd_context *create_toolcontext(struct arg *the_args);
|
||||
void destroy_toolcontext(struct cmd_context *cmd);
|
||||
int refresh_toolcontext(struct cmd_context *cmd);
|
||||
int config_files_changed(struct cmd_context *cmd);
|
||||
|
||||
#endif
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -9,6 +18,8 @@
|
||||
#include "crc.h"
|
||||
#include "pool.h"
|
||||
#include "device.h"
|
||||
#include "str_list.h"
|
||||
#include "toolcontext.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
@@ -43,10 +54,11 @@ struct parser {
|
||||
};
|
||||
|
||||
struct cs {
|
||||
struct config_tree cf;
|
||||
struct config_tree cft;
|
||||
struct pool *mem;
|
||||
time_t timestamp;
|
||||
char *filename;
|
||||
int exists;
|
||||
};
|
||||
|
||||
static void _get_token(struct parser *p, int tok_prev);
|
||||
@@ -60,6 +72,8 @@ static struct config_value *_create_value(struct parser *p);
|
||||
static struct config_node *_create_node(struct parser *p);
|
||||
static char *_dup_tok(struct parser *p);
|
||||
|
||||
static const int sep = '/';
|
||||
|
||||
#define MAX_INDENT 32
|
||||
|
||||
#define match(t) do {\
|
||||
@@ -82,7 +96,7 @@ static int _tok_match(const char *str, const char *b, const char *e)
|
||||
/*
|
||||
* public interface
|
||||
*/
|
||||
struct config_tree *create_config_tree(void)
|
||||
struct config_tree *create_config_tree(const char *filename)
|
||||
{
|
||||
struct cs *c;
|
||||
struct pool *mem = pool_create(10 * 1024);
|
||||
@@ -92,29 +106,31 @@ struct config_tree *create_config_tree(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(c = pool_alloc(mem, sizeof(*c)))) {
|
||||
if (!(c = pool_zalloc(mem, sizeof(*c)))) {
|
||||
stack;
|
||||
pool_destroy(mem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
c->mem = mem;
|
||||
c->cf.root = (struct config_node *) NULL;
|
||||
c->cft.root = (struct config_node *) NULL;
|
||||
c->timestamp = 0;
|
||||
c->filename = NULL;
|
||||
return &c->cf;
|
||||
c->exists = 0;
|
||||
if (filename)
|
||||
c->filename = pool_strdup(c->mem, filename);
|
||||
return &c->cft;
|
||||
}
|
||||
|
||||
void destroy_config_tree(struct config_tree *cf)
|
||||
void destroy_config_tree(struct config_tree *cft)
|
||||
{
|
||||
pool_destroy(((struct cs *) cf)->mem);
|
||||
pool_destroy(((struct cs *) cft)->mem);
|
||||
}
|
||||
|
||||
int read_config_fd(struct config_tree *cf, struct device *dev,
|
||||
int read_config_fd(struct config_tree *cft, struct device *dev,
|
||||
off_t offset, size_t size, off_t offset2, size_t size2,
|
||||
checksum_fn_t checksum_fn, uint32_t checksum)
|
||||
{
|
||||
struct cs *c = (struct cs *) cf;
|
||||
struct cs *c = (struct cs *) cft;
|
||||
struct parser *p;
|
||||
int r = 0;
|
||||
int use_mmap = 1;
|
||||
@@ -172,7 +188,7 @@ int read_config_fd(struct config_tree *cf, struct device *dev,
|
||||
p->tb = p->te = p->fb;
|
||||
p->line = 1;
|
||||
_get_token(p, TOK_SECTION_E);
|
||||
if (!(cf->root = _file(p))) {
|
||||
if (!(cft->root = _file(p))) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
@@ -193,99 +209,30 @@ int read_config_fd(struct config_tree *cf, struct device *dev,
|
||||
return r;
|
||||
}
|
||||
|
||||
int read_config_file(struct config_tree *cf, const char *file)
|
||||
int read_config_file(struct config_tree *cft)
|
||||
{
|
||||
struct cs *c = (struct cs *) cf;
|
||||
struct cs *c = (struct cs *) cft;
|
||||
struct stat info;
|
||||
struct device *dev;
|
||||
int r = 1;
|
||||
|
||||
if (stat(file, &info)) {
|
||||
log_sys_error("stat", file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!S_ISREG(info.st_mode)) {
|
||||
log_error("%s is not a regular file", file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (info.st_size == 0) {
|
||||
log_verbose("%s is empty", file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(dev = dev_create_file(file, NULL, NULL))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dev_open_flags(dev, O_RDONLY, 0, 0)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = read_config_fd(cf, dev, 0, (size_t) info.st_size, 0, 0,
|
||||
(checksum_fn_t) NULL, 0);
|
||||
|
||||
dev_close(dev);
|
||||
|
||||
c->timestamp = info.st_mtime;
|
||||
c->filename = pool_strdup(c->mem, file);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
time_t config_file_timestamp(struct config_tree *cf)
|
||||
{
|
||||
struct cs *c = (struct cs *) cf;
|
||||
|
||||
return c->timestamp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 1 if config file reloaded
|
||||
*/
|
||||
int reload_config_file(struct config_tree **cf)
|
||||
{
|
||||
struct config_tree *new_cf;
|
||||
struct cs *c = (struct cs *) *cf;
|
||||
struct cs *new_cs;
|
||||
struct stat info;
|
||||
struct device *dev;
|
||||
int r;
|
||||
|
||||
if (!c->filename)
|
||||
return 0;
|
||||
|
||||
if (stat(c->filename, &info) == -1) {
|
||||
if (errno == ENOENT)
|
||||
return 1;
|
||||
if (stat(c->filename, &info)) {
|
||||
log_sys_error("stat", c->filename);
|
||||
log_error("Failed to reload configuration file");
|
||||
c->exists = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!S_ISREG(info.st_mode)) {
|
||||
log_error("Configuration file %s is not a regular file",
|
||||
c->filename);
|
||||
log_error("%s is not a regular file", c->filename);
|
||||
c->exists = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unchanged? */
|
||||
if (c->timestamp == info.st_mtime)
|
||||
return 0;
|
||||
|
||||
log_verbose("Detected config file change: Reloading %s", c->filename);
|
||||
c->exists = 1;
|
||||
|
||||
if (info.st_size == 0) {
|
||||
log_verbose("Config file reload: %s is empty", c->filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(new_cf = create_config_tree())) {
|
||||
log_error("Allocation of new config_tree failed");
|
||||
return 0;
|
||||
log_verbose("%s is empty", c->filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(dev = dev_create_file(c->filename, NULL, NULL))) {
|
||||
@@ -298,22 +245,63 @@ int reload_config_file(struct config_tree **cf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = read_config_fd(new_cf, dev, 0, (size_t) info.st_size,
|
||||
0, 0, (checksum_fn_t) NULL, 0);
|
||||
r = read_config_fd(cft, dev, 0, (size_t) info.st_size, 0, 0,
|
||||
(checksum_fn_t) NULL, 0);
|
||||
|
||||
dev_close(dev);
|
||||
|
||||
if (r) {
|
||||
new_cs = (struct cs *) new_cf;
|
||||
new_cs->filename = pool_strdup(new_cs->mem, c->filename);
|
||||
new_cs->timestamp = info.st_mtime;
|
||||
destroy_config_tree(*cf);
|
||||
*cf = new_cf;
|
||||
}
|
||||
c->timestamp = info.st_mtime;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
time_t config_file_timestamp(struct config_tree *cft)
|
||||
{
|
||||
struct cs *c = (struct cs *) cft;
|
||||
|
||||
return c->timestamp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 1 if config files ought to be reloaded
|
||||
*/
|
||||
int config_file_changed(struct config_tree *cft)
|
||||
{
|
||||
struct cs *c = (struct cs *) cft;
|
||||
struct stat info;
|
||||
|
||||
if (!c->filename)
|
||||
return 0;
|
||||
|
||||
if (stat(c->filename, &info) == -1) {
|
||||
/* Ignore a deleted config file: still use original data */
|
||||
if (errno == ENOENT) {
|
||||
if (!c->exists)
|
||||
return 0;
|
||||
log_very_verbose("Config file %s has disappeared!",
|
||||
c->filename);
|
||||
goto reload;
|
||||
}
|
||||
log_sys_error("stat", c->filename);
|
||||
log_error("Failed to reload configuration files");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!S_ISREG(info.st_mode)) {
|
||||
log_error("Configuration file %s is not a regular file",
|
||||
c->filename);
|
||||
goto reload;
|
||||
}
|
||||
|
||||
/* Unchanged? */
|
||||
if (c->timestamp == info.st_mtime)
|
||||
return 0;
|
||||
|
||||
reload:
|
||||
log_verbose("Detected config file change to %s", c->filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _write_value(FILE *fp, struct config_value *v)
|
||||
{
|
||||
switch (v->type) {
|
||||
@@ -382,7 +370,7 @@ static int _write_config(struct config_node *n, FILE *fp, int level)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int write_config_file(struct config_tree *cf, const char *file)
|
||||
int write_config_file(struct config_tree *cft, const char *file)
|
||||
{
|
||||
int r = 1;
|
||||
FILE *fp;
|
||||
@@ -396,7 +384,7 @@ int write_config_file(struct config_tree *cf, const char *file)
|
||||
}
|
||||
|
||||
log_verbose("Dumping configuration to %s", file);
|
||||
if (!_write_config(cf->root, fp, 0)) {
|
||||
if (!_write_config(cft->root, fp, 0)) {
|
||||
log_error("Failure while writing configuration");
|
||||
r = 0;
|
||||
}
|
||||
@@ -728,8 +716,8 @@ static char *_dup_tok(struct parser *p)
|
||||
/*
|
||||
* utility functions
|
||||
*/
|
||||
struct config_node *find_config_node(struct config_node *cn,
|
||||
const char *path, const int sep)
|
||||
struct config_node *find_config_node(const struct config_node *cn,
|
||||
const char *path)
|
||||
{
|
||||
const char *e;
|
||||
|
||||
@@ -757,13 +745,13 @@ struct config_node *find_config_node(struct config_node *cn,
|
||||
path = e;
|
||||
}
|
||||
|
||||
return cn;
|
||||
return (struct config_node *) cn;
|
||||
}
|
||||
|
||||
const char *find_config_str(struct config_node *cn,
|
||||
const char *path, const int sep, const char *fail)
|
||||
const char *find_config_str(const struct config_node *cn,
|
||||
const char *path, const char *fail)
|
||||
{
|
||||
struct config_node *n = find_config_node(cn, path, sep);
|
||||
const struct config_node *n = find_config_node(cn, path);
|
||||
|
||||
if (n && n->v->type == CFG_STRING) {
|
||||
if (*n->v->v.str)
|
||||
@@ -777,10 +765,9 @@ const char *find_config_str(struct config_node *cn,
|
||||
return fail;
|
||||
}
|
||||
|
||||
int find_config_int(struct config_node *cn, const char *path,
|
||||
const int sep, int fail)
|
||||
int find_config_int(const struct config_node *cn, const char *path, int fail)
|
||||
{
|
||||
struct config_node *n = find_config_node(cn, path, sep);
|
||||
const struct config_node *n = find_config_node(cn, path);
|
||||
|
||||
if (n && n->v->type == CFG_INT) {
|
||||
log_very_verbose("Setting %s to %d", path, n->v->v.i);
|
||||
@@ -792,10 +779,10 @@ int find_config_int(struct config_node *cn, const char *path,
|
||||
return fail;
|
||||
}
|
||||
|
||||
float find_config_float(struct config_node *cn, const char *path,
|
||||
const int sep, float fail)
|
||||
float find_config_float(const struct config_node *cn, const char *path,
|
||||
float fail)
|
||||
{
|
||||
struct config_node *n = find_config_node(cn, path, sep);
|
||||
const struct config_node *n = find_config_node(cn, path);
|
||||
|
||||
if (n && n->v->type == CFG_FLOAT) {
|
||||
log_very_verbose("Setting %s to %f", path, n->v->v.r);
|
||||
@@ -835,10 +822,9 @@ static int _str_to_bool(const char *str, int fail)
|
||||
return fail;
|
||||
}
|
||||
|
||||
int find_config_bool(struct config_node *cn, const char *path,
|
||||
const int sep, int fail)
|
||||
int find_config_bool(const struct config_node *cn, const char *path, int fail)
|
||||
{
|
||||
struct config_node *n = find_config_node(cn, path, sep);
|
||||
const struct config_node *n = find_config_node(cn, path);
|
||||
struct config_value *v;
|
||||
|
||||
if (!n)
|
||||
@@ -857,12 +843,12 @@ int find_config_bool(struct config_node *cn, const char *path,
|
||||
return fail;
|
||||
}
|
||||
|
||||
int get_config_uint32(struct config_node *cn, const char *path,
|
||||
const int sep, uint32_t *result)
|
||||
int get_config_uint32(const struct config_node *cn, const char *path,
|
||||
uint32_t *result)
|
||||
{
|
||||
struct config_node *n;
|
||||
const struct config_node *n;
|
||||
|
||||
n = find_config_node(cn, path, sep);
|
||||
n = find_config_node(cn, path);
|
||||
|
||||
if (!n || !n->v || n->v->type != CFG_INT)
|
||||
return 0;
|
||||
@@ -871,12 +857,12 @@ int get_config_uint32(struct config_node *cn, const char *path,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int get_config_uint64(struct config_node *cn, const char *path,
|
||||
const int sep, uint64_t *result)
|
||||
int get_config_uint64(const struct config_node *cn, const char *path,
|
||||
uint64_t *result)
|
||||
{
|
||||
struct config_node *n;
|
||||
const struct config_node *n;
|
||||
|
||||
n = find_config_node(cn, path, sep);
|
||||
n = find_config_node(cn, path);
|
||||
|
||||
if (!n || !n->v || n->v->type != CFG_INT)
|
||||
return 0;
|
||||
@@ -886,12 +872,12 @@ int get_config_uint64(struct config_node *cn, const char *path,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int get_config_str(struct config_node *cn, const char *path,
|
||||
const int sep, char **result)
|
||||
int get_config_str(const struct config_node *cn, const char *path,
|
||||
char **result)
|
||||
{
|
||||
struct config_node *n;
|
||||
const struct config_node *n;
|
||||
|
||||
n = find_config_node(cn, path, sep);
|
||||
n = find_config_node(cn, path);
|
||||
|
||||
if (!n || !n->v || n->v->type != CFG_STRING)
|
||||
return 0;
|
||||
@@ -899,3 +885,115 @@ int get_config_str(struct config_node *cn, const char *path,
|
||||
*result = n->v->v.str;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Insert cn2 after cn1 */
|
||||
static void _insert_config_node(struct config_node **cn1,
|
||||
struct config_node *cn2)
|
||||
{
|
||||
if (!*cn1) {
|
||||
*cn1 = cn2;
|
||||
cn2->sib = NULL;
|
||||
} else {
|
||||
cn2->sib = (*cn1)->sib;
|
||||
(*cn1)->sib = cn2;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Merge section cn2 into section cn1 (which has the same name)
|
||||
* overwriting any existing cn1 nodes with matching names.
|
||||
*/
|
||||
static void _merge_section(struct config_node *cn1, struct config_node *cn2)
|
||||
{
|
||||
struct config_node *cn, *nextn, *oldn;
|
||||
struct config_value *cv;
|
||||
|
||||
for (cn = cn2->child; cn; cn = nextn) {
|
||||
nextn = cn->sib;
|
||||
|
||||
/* Skip "tags" */
|
||||
if (!strcmp(cn->key, "tags"))
|
||||
continue;
|
||||
|
||||
/* Subsection? */
|
||||
if (!cn->v)
|
||||
/* Ignore - we don't have any of these yet */
|
||||
continue;
|
||||
/* Not already present? */
|
||||
if (!(oldn = find_config_node(cn1->child, cn->key))) {
|
||||
_insert_config_node(&cn1->child, cn);
|
||||
continue;
|
||||
}
|
||||
/* Merge certain value lists */
|
||||
if ((!strcmp(cn1->key, "activation") &&
|
||||
!strcmp(cn->key, "volume_list")) ||
|
||||
(!strcmp(cn1->key, "devices") &&
|
||||
(!strcmp(cn->key, "filter") || !strcmp(cn->key, "types")))) {
|
||||
cv = cn->v;
|
||||
while (cv->next)
|
||||
cv = cv->next;
|
||||
cv->next = oldn->v;
|
||||
}
|
||||
|
||||
/* Replace values */
|
||||
oldn->v = cn->v;
|
||||
}
|
||||
}
|
||||
|
||||
static int _match_host_tags(struct list *tags, struct config_node *tn)
|
||||
{
|
||||
struct config_value *tv;
|
||||
const char *str;
|
||||
|
||||
for (tv = tn->v; tv; tv = tv->next) {
|
||||
if (tv->type != CFG_STRING)
|
||||
continue;
|
||||
str = tv->v.str;
|
||||
if (*str == '@')
|
||||
str++;
|
||||
if (!*str)
|
||||
continue;
|
||||
if (str_list_match_item(tags, str))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Destructively merge a new config tree into an existing one */
|
||||
int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft,
|
||||
struct config_tree *newdata)
|
||||
{
|
||||
struct config_node *root = cft->root;
|
||||
struct config_node *cn, *nextn, *oldn, *tn, *cn2;
|
||||
|
||||
for (cn = newdata->root; cn; cn = nextn) {
|
||||
nextn = cn->sib;
|
||||
/* Ignore tags section */
|
||||
if (!strcmp(cn->key, "tags"))
|
||||
continue;
|
||||
/* If there's a tags node, skip if host tags don't match */
|
||||
if ((tn = find_config_node(cn->child, "tags"))) {
|
||||
if (!_match_host_tags(&cmd->tags, tn))
|
||||
continue;
|
||||
}
|
||||
if (!(oldn = find_config_node(root, cn->key))) {
|
||||
_insert_config_node(&cft->root, cn);
|
||||
/* Remove any "tags" nodes */
|
||||
for (cn2 = cn->child; cn2; cn2 = cn2->sib) {
|
||||
if (!strcmp(cn2->key, "tags")) {
|
||||
cn->child = cn2->sib;
|
||||
continue;
|
||||
}
|
||||
if (cn2->sib && !strcmp(cn2->sib->key, "tags")) {
|
||||
cn2->sib = cn2->sib->sib;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
_merge_section(oldn, cn);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@@ -1,13 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_CONFIG_H
|
||||
#define _LVM_CONFIG_H
|
||||
|
||||
#include "device.h"
|
||||
struct device;
|
||||
struct cmd_context;
|
||||
|
||||
enum {
|
||||
CFG_STRING,
|
||||
@@ -36,46 +46,51 @@ struct config_tree {
|
||||
struct config_node *root;
|
||||
};
|
||||
|
||||
struct config_tree *create_config_tree(void);
|
||||
void destroy_config_tree(struct config_tree *cf);
|
||||
struct config_tree_list {
|
||||
struct list list;
|
||||
struct config_tree *cft;
|
||||
};
|
||||
|
||||
struct config_tree *create_config_tree(const char *filename);
|
||||
void destroy_config_tree(struct config_tree *cft);
|
||||
|
||||
typedef uint32_t (*checksum_fn_t) (uint32_t initial, void *buf, uint32_t size);
|
||||
|
||||
int read_config_fd(struct config_tree *cf, struct device *dev,
|
||||
int read_config_fd(struct config_tree *cft, struct device *dev,
|
||||
off_t offset, size_t size, off_t offset2, size_t size2,
|
||||
checksum_fn_t checksum_fn, uint32_t checksum);
|
||||
|
||||
int read_config_file(struct config_tree *cf, const char *file);
|
||||
int write_config_file(struct config_tree *cf, const char *file);
|
||||
int reload_config_file(struct config_tree **cf);
|
||||
time_t config_file_timestamp(struct config_tree *cf);
|
||||
int read_config_file(struct config_tree *cft);
|
||||
int write_config_file(struct config_tree *cft, const char *file);
|
||||
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,
|
||||
struct config_tree *newdata);
|
||||
|
||||
struct config_node *find_config_node(struct config_node *cn,
|
||||
const char *path, const int separator);
|
||||
struct config_node *find_config_node(const struct config_node *cn,
|
||||
const char *path);
|
||||
|
||||
const char *find_config_str(struct config_node *cn,
|
||||
const char *path, const int sep, const char *fail);
|
||||
const char *find_config_str(const struct config_node *cn, const char *path,
|
||||
const char *fail);
|
||||
|
||||
int find_config_int(struct config_node *cn, const char *path,
|
||||
const int sep, int fail);
|
||||
int find_config_int(const struct config_node *cn, const char *path, int fail);
|
||||
|
||||
float find_config_float(struct config_node *cn, const char *path,
|
||||
const int sep, float fail);
|
||||
float find_config_float(const struct config_node *cn, const char *path,
|
||||
float fail);
|
||||
|
||||
/*
|
||||
* Understands (0, ~0), (y, n), (yes, no), (on,
|
||||
* off), (true, false).
|
||||
*/
|
||||
int find_config_bool(struct config_node *cn, const char *path,
|
||||
const int sep, int fail);
|
||||
int find_config_bool(const struct config_node *cn, const char *path, int fail);
|
||||
|
||||
int get_config_uint32(struct config_node *cn, const char *path,
|
||||
const int sep, uint32_t *result);
|
||||
int get_config_uint32(const struct config_node *cn, const char *path,
|
||||
uint32_t *result);
|
||||
|
||||
int get_config_uint64(struct config_node *cn, const char *path,
|
||||
const int sep, uint64_t *result);
|
||||
int get_config_uint64(const struct config_node *cn, const char *path,
|
||||
uint64_t *result);
|
||||
|
||||
int get_config_str(struct config_node *cn, const char *path,
|
||||
const int sep, char **result);
|
||||
int get_config_str(const struct config_node *cn, const char *path,
|
||||
char **result);
|
||||
|
||||
#endif
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_DEFAULTS_H
|
||||
@@ -20,12 +29,19 @@
|
||||
#define DEFAULT_DEV_DIR "/dev"
|
||||
#define DEFAULT_PROC_DIR "/proc"
|
||||
#define DEFAULT_SYSFS_SCAN 1
|
||||
#define DEFAULT_MD_COMPONENT_DETECTION 1
|
||||
|
||||
#define DEFAULT_LOCK_DIR "/var/lock/lvm"
|
||||
#define DEFAULT_LOCKING_LIB "lvm2_locking.so"
|
||||
|
||||
#define DEFAULT_UMASK 0077
|
||||
|
||||
#ifdef LVM1_FALLBACK
|
||||
# define DEFAULT_FALLBACK_TO_LVM1 1
|
||||
#else
|
||||
# define DEFAULT_FALLBACK_TO_LVM1 0
|
||||
#endif
|
||||
|
||||
#ifdef LVM1_SUPPORT
|
||||
# define DEFAULT_FORMAT "lvm1"
|
||||
#else
|
||||
@@ -51,6 +67,7 @@
|
||||
#define DEFAULT_INDENT 1
|
||||
#define DEFAULT_UNITS "h"
|
||||
#define DEFAULT_SUFFIX 1
|
||||
#define DEFAULT_HOSTTAGS 0
|
||||
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
# define DEFAULT_ACTIVATION 1
|
||||
@@ -74,12 +91,12 @@
|
||||
#define DEFAULT_REP_HEADINGS 1
|
||||
#define DEFAULT_REP_SEPARATOR " "
|
||||
|
||||
#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent,move_pv,move_percent"
|
||||
#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent,move_pv,copy_percent"
|
||||
#define DEFAULT_VGS_COLS "vg_name,pv_count,lv_count,snap_count,vg_attr,vg_size,vg_free"
|
||||
#define DEFAULT_PVS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free"
|
||||
#define DEFAULT_SEGS_COLS "lv_name,vg_name,lv_attr,stripes,segtype,seg_size"
|
||||
|
||||
#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,origin,snap_percent,move_pv,move_percent,lv_uuid"
|
||||
#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,origin,snap_percent,move_pv,copy_percent,lv_uuid"
|
||||
#define DEFAULT_VGS_COLS_VERB "vg_name,vg_attr,vg_extent_size,pv_count,lv_count,snap_count,vg_size,vg_free,vg_uuid"
|
||||
#define DEFAULT_PVS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pv_uuid"
|
||||
#define DEFAULT_SEGS_COLS_VERB "lv_name,vg_name,lv_attr,seg_start,seg_size,stripes,segtype,stripesize,chunksize"
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_BITSET_H
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_BTREE_H
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_HASH_H
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_LIST_H
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_TYPES_H
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2003 Sistina Software
|
||||
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -57,6 +66,25 @@ int str_list_del(struct list *sll, const char *str)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int str_list_dup(struct pool *mem, struct list *sllnew, struct list *sllold)
|
||||
{
|
||||
struct str_list *sl;
|
||||
|
||||
list_init(sllnew);
|
||||
|
||||
list_iterate_items(sl, sllold) {
|
||||
if (!str_list_add(mem, sllnew, strdup(sl->str))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is item on list?
|
||||
*/
|
||||
int str_list_match_item(struct list *sll, const char *str)
|
||||
{
|
||||
struct str_list *sl;
|
||||
@@ -68,6 +96,9 @@ int str_list_match_item(struct list *sll, const char *str)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is at least one item on both lists?
|
||||
*/
|
||||
int str_list_match_list(struct list *sll, struct list *sll2)
|
||||
{
|
||||
struct str_list *sl;
|
||||
@@ -78,3 +109,20 @@ int str_list_match_list(struct list *sll, struct list *sll2)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do both lists contain the same set of items?
|
||||
*/
|
||||
int str_list_lists_equal(struct list *sll, struct list *sll2)
|
||||
{
|
||||
struct str_list *sl;
|
||||
|
||||
if (list_size(sll) != list_size(sll2))
|
||||
return 0;
|
||||
|
||||
list_iterate_items(sl, sll)
|
||||
if (!str_list_match_item(sll2, sl->str))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2003 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_STR_LIST_H
|
||||
@@ -14,5 +23,7 @@ int str_list_add(struct pool *mem, struct list *sll, const char *str);
|
||||
int str_list_del(struct list *sll, const char *str);
|
||||
int str_list_match_item(struct list *sll, const char *str);
|
||||
int str_list_match_list(struct list *sll, struct list *sll2);
|
||||
int str_list_lists_equal(struct list *sll, struct list *sll2);
|
||||
int str_list_dup(struct pool *mem, struct list *sllnew, struct list *sllold);
|
||||
|
||||
#endif
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_DEV_CACHE_H
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -42,12 +51,6 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* FIXME Use _llseek for 64-bit
|
||||
_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, loff_t *, res, uint, wh);
|
||||
if (_llseek((unsigned) fd, (ulong) (offset >> 32), (ulong) (offset & 0xFFFFFFFF), &pos, SEEK_SET) < 0) {
|
||||
*/
|
||||
|
||||
static LIST_INIT(_open_devices);
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
|
@@ -1,20 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This LVM library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This LVM library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this LVM library; if not, write to the Free
|
||||
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if 0
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_DEVICE_H
|
||||
|
@@ -1,21 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This LVM library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This LVM library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this LVM library; if not, write to the Free
|
||||
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -23,6 +18,7 @@
|
||||
#include "display.h"
|
||||
#include "activate.h"
|
||||
#include "toolcontext.h"
|
||||
#include "segtypes.h"
|
||||
|
||||
#define SIZE_BUF 128
|
||||
|
||||
@@ -31,23 +27,13 @@ static struct {
|
||||
const char *str;
|
||||
} _policies[] = {
|
||||
{
|
||||
ALLOC_NEXT_FREE, "next free"}, {
|
||||
ALLOC_CONTIGUOUS, "contiguous"}, {
|
||||
ALLOC_DEFAULT, "next free (default)"}
|
||||
};
|
||||
|
||||
static struct {
|
||||
segment_type_t segtype;
|
||||
const char *str;
|
||||
} _segtypes[] = {
|
||||
{
|
||||
SEG_STRIPED, "striped"}, {
|
||||
SEG_MIRRORED, "mirror"}, {
|
||||
SEG_SNAPSHOT, "snapshot"}
|
||||
ALLOC_NORMAL, "normal"}, {
|
||||
ALLOC_ANYWHERE, "anywhere"}, {
|
||||
ALLOC_INHERIT, "inherit"}
|
||||
};
|
||||
|
||||
static int _num_policies = sizeof(_policies) / sizeof(*_policies);
|
||||
static int _num_segtypes = sizeof(_segtypes) / sizeof(*_segtypes);
|
||||
|
||||
uint64_t units_to_bytes(const char *units, char *unit_type)
|
||||
{
|
||||
@@ -129,17 +115,6 @@ const char *get_alloc_string(alloc_policy_t alloc)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *get_segtype_string(segment_type_t segtype)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < _num_segtypes; i++)
|
||||
if (_segtypes[i].segtype == segtype)
|
||||
return _segtypes[i].str;
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
alloc_policy_t get_alloc_from_string(const char *str)
|
||||
{
|
||||
int i;
|
||||
@@ -148,26 +123,19 @@ alloc_policy_t get_alloc_from_string(const char *str)
|
||||
if (!strcmp(_policies[i].str, str))
|
||||
return _policies[i].alloc;
|
||||
|
||||
log_error("Unrecognised allocation policy - using default");
|
||||
return ALLOC_DEFAULT;
|
||||
}
|
||||
|
||||
segment_type_t get_segtype_from_string(const char *str)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < _num_segtypes; i++)
|
||||
if (!strcmp(_segtypes[i].str, str))
|
||||
return _segtypes[i].segtype;
|
||||
|
||||
log_error("Unrecognised segment type - using default (striped)");
|
||||
return SEG_STRIPED;
|
||||
/* Special case for old metadata */
|
||||
if(!strcmp("next free", str))
|
||||
return ALLOC_NORMAL;
|
||||
|
||||
log_error("Unrecognised allocation policy %s", str);
|
||||
return ALLOC_INVALID;
|
||||
}
|
||||
|
||||
/* Size supplied in sectors */
|
||||
const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
|
||||
{
|
||||
int s;
|
||||
int suffix = 1;
|
||||
int suffix = 1, precision;
|
||||
uint64_t byte = UINT64_C(0);
|
||||
uint64_t units = UINT64_C(1024);
|
||||
char *size_buf = NULL;
|
||||
@@ -202,8 +170,9 @@ const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
|
||||
|
||||
if (s < 8) {
|
||||
byte = cmd->current_settings.unit_factor;
|
||||
size *= UINT64_C(1024);
|
||||
size *= UINT64_C(512);
|
||||
} else {
|
||||
size /= 2;
|
||||
suffix = 1;
|
||||
if (cmd->current_settings.unit_type == 'H')
|
||||
units = UINT64_C(1000);
|
||||
@@ -215,8 +184,18 @@ const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
|
||||
s++, byte /= units;
|
||||
}
|
||||
|
||||
snprintf(size_buf, SIZE_BUF - 1, "%.2f%s", (float) size / byte,
|
||||
suffix ? size_str[s][sl] : "");
|
||||
/* FIXME Make precision configurable */
|
||||
switch(toupper((int) cmd->current_settings.unit_type)) {
|
||||
case 'B':
|
||||
case 'S':
|
||||
precision = 0;
|
||||
break;
|
||||
default:
|
||||
precision = 2;
|
||||
}
|
||||
|
||||
snprintf(size_buf, SIZE_BUF - 1, "%.*f%s", precision,
|
||||
(double) size / byte, suffix ? size_str[s][sl] : "");
|
||||
|
||||
return size_buf;
|
||||
}
|
||||
@@ -269,18 +248,18 @@ void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
|
||||
log_print("VG Name %s%s", pv->vg_name,
|
||||
pv->status & EXPORTED_VG ? " (exported)" : "");
|
||||
|
||||
size = display_size(cmd, (uint64_t) pv->size / 2, SIZE_SHORT);
|
||||
size = display_size(cmd, (uint64_t) pv->size, SIZE_SHORT);
|
||||
if (pv->pe_size && pv->pe_count) {
|
||||
|
||||
/******** FIXME display LVM on-disk data size
|
||||
size2 = display_size(pv->size / 2, SIZE_SHORT);
|
||||
size2 = display_size(pv->size, SIZE_SHORT);
|
||||
********/
|
||||
|
||||
log_print("PV Size %s" " / not usable %s", /* [LVM: %s]", */
|
||||
size, display_size(cmd,
|
||||
(pv->size -
|
||||
pv->pe_count * pv->pe_size) / 2,
|
||||
SIZE_SHORT));
|
||||
size,
|
||||
display_size(cmd, (pv->size -
|
||||
pv->pe_count * pv->pe_size),
|
||||
SIZE_SHORT));
|
||||
|
||||
} else
|
||||
log_print("PV Size %s", size);
|
||||
@@ -391,8 +370,7 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
snap_active = lv_snapshot_percent(snap->cow,
|
||||
&snap_percent);
|
||||
if (!snap_active || snap_percent < 0 ||
|
||||
snap_percent >= 100)
|
||||
snap_active = 0;
|
||||
snap_percent >= 100) snap_active = 0;
|
||||
log_print(" %s%s/%s [%s]",
|
||||
lv->vg->cmd->dev_dir, lv->vg->name,
|
||||
snap->cow->name,
|
||||
@@ -424,7 +402,7 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
|
||||
log_print("LV Size %s",
|
||||
display_size(cmd,
|
||||
snap ? snap->origin->size / 2 : lv->size / 2,
|
||||
snap ? snap->origin->size : lv->size,
|
||||
SIZE_SHORT));
|
||||
|
||||
log_print("Current LE %u",
|
||||
@@ -445,11 +423,11 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
snap_percent = 100;
|
||||
|
||||
log_print("Snapshot chunk size %s",
|
||||
display_size(cmd, (uint64_t) snap->chunk_size / 2,
|
||||
display_size(cmd, (uint64_t) snap->chunk_size,
|
||||
SIZE_SHORT));
|
||||
|
||||
/*
|
||||
size = display_size(lv->size / 2, SIZE_SHORT);
|
||||
size = display_size(lv->size, SIZE_SHORT);
|
||||
sscanf(size, "%f", &fsize);
|
||||
fused = fsize * snap_percent / 100;
|
||||
*/
|
||||
@@ -483,7 +461,7 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _display_stripe(struct lv_segment *seg, uint32_t s, const char *pre)
|
||||
void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre)
|
||||
{
|
||||
switch (seg->area[s].type) {
|
||||
case AREA_PV:
|
||||
@@ -511,52 +489,18 @@ static void _display_stripe(struct lv_segment *seg, uint32_t s, const char *pre)
|
||||
|
||||
int lvdisplay_segments(struct logical_volume *lv)
|
||||
{
|
||||
uint32_t s;
|
||||
struct list *segh;
|
||||
struct lv_segment *seg;
|
||||
|
||||
log_print("--- Segments ---");
|
||||
|
||||
list_iterate(segh, &lv->segments) {
|
||||
seg = list_item(segh, struct lv_segment);
|
||||
|
||||
list_iterate_items(seg, &lv->segments) {
|
||||
log_print("Logical extent %u to %u:",
|
||||
seg->le, seg->le + seg->len - 1);
|
||||
|
||||
if (seg->type == SEG_STRIPED && seg->area_count == 1)
|
||||
log_print(" Type\t\tlinear");
|
||||
else
|
||||
log_print(" Type\t\t%s",
|
||||
get_segtype_string(seg->type));
|
||||
log_print(" Type\t\t%s", seg->segtype->ops->name(seg));
|
||||
|
||||
switch (seg->type) {
|
||||
case SEG_STRIPED:
|
||||
if (seg->area_count == 1)
|
||||
_display_stripe(seg, 0, " ");
|
||||
else {
|
||||
log_print(" Stripes\t\t%u", seg->area_count);
|
||||
log_print(" Stripe size\t\t%u KB",
|
||||
seg->stripe_size / 2);
|
||||
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
log_print(" Stripe %d:", s);
|
||||
_display_stripe(seg, s, " ");
|
||||
}
|
||||
}
|
||||
log_print(" ");
|
||||
break;
|
||||
case SEG_SNAPSHOT:
|
||||
break;
|
||||
case SEG_MIRRORED:
|
||||
log_print(" Mirrors\t\t%u", seg->area_count);
|
||||
log_print(" Mirror size\t\t%u", seg->area_len);
|
||||
log_print(" Mirror original:");
|
||||
_display_stripe(seg, 0, " ");
|
||||
log_print(" Mirror destination:");
|
||||
_display_stripe(seg, 1, " ");
|
||||
log_print(" ");
|
||||
break;
|
||||
}
|
||||
if (seg->segtype->ops->display)
|
||||
seg->segtype->ops->display(seg);
|
||||
}
|
||||
|
||||
log_print(" ");
|
||||
@@ -610,7 +554,7 @@ void vgdisplay_full(struct volume_group *vg)
|
||||
log_print("Open LV %u", lvs_in_vg_opened(vg));
|
||||
/****** FIXME Max LV Size
|
||||
log_print ( "MAX LV Size %s",
|
||||
( s1 = display_size ( LVM_LV_SIZE_MAX(vg) / 2, SIZE_SHORT)));
|
||||
( s1 = display_size ( LVM_LV_SIZE_MAX(vg), SIZE_SHORT)));
|
||||
free ( s1);
|
||||
*********/
|
||||
log_print("Max PV %u", vg->max_pv);
|
||||
@@ -619,32 +563,25 @@ void vgdisplay_full(struct volume_group *vg)
|
||||
|
||||
log_print("VG Size %s",
|
||||
display_size(vg->cmd,
|
||||
(uint64_t) vg->extent_count * (vg->extent_size /
|
||||
2), SIZE_SHORT));
|
||||
(uint64_t) vg->extent_count * vg->extent_size,
|
||||
SIZE_SHORT));
|
||||
|
||||
log_print("PE Size %s",
|
||||
display_size(vg->cmd, (uint64_t) vg->extent_size / 2,
|
||||
display_size(vg->cmd, (uint64_t) vg->extent_size,
|
||||
SIZE_SHORT));
|
||||
|
||||
log_print("Total PE %u", vg->extent_count);
|
||||
|
||||
log_print("Alloc PE / Size %u / %s",
|
||||
vg->extent_count - vg->free_count, display_size(vg->cmd,
|
||||
((uint64_t)
|
||||
vg->
|
||||
extent_count
|
||||
-
|
||||
vg->
|
||||
free_count) *
|
||||
(vg->
|
||||
extent_size /
|
||||
2),
|
||||
SIZE_SHORT));
|
||||
vg->extent_count - vg->free_count,
|
||||
display_size(vg->cmd,
|
||||
((uint64_t) vg->extent_count - vg->free_count) *
|
||||
vg->extent_size, SIZE_SHORT));
|
||||
|
||||
log_print("Free PE / Size %u / %s", vg->free_count,
|
||||
display_size(vg->cmd,
|
||||
(uint64_t) vg->free_count * (vg->extent_size /
|
||||
2), SIZE_SHORT));
|
||||
(uint64_t) vg->free_count * vg->extent_size,
|
||||
SIZE_SHORT));
|
||||
|
||||
if (!id_write_format(&vg->id, uuid, sizeof(uuid))) {
|
||||
stack;
|
||||
@@ -659,6 +596,53 @@ void vgdisplay_full(struct volume_group *vg)
|
||||
|
||||
void vgdisplay_colons(struct volume_group *vg)
|
||||
{
|
||||
uint32_t active_pvs;
|
||||
const char *access;
|
||||
char uuid[64];
|
||||
|
||||
if (vg->status & PARTIAL_VG)
|
||||
active_pvs = list_size(&vg->pvs);
|
||||
else
|
||||
active_pvs = vg->pv_count;
|
||||
|
||||
switch (vg->status & (LVM_READ | LVM_WRITE)) {
|
||||
case LVM_READ | LVM_WRITE:
|
||||
access = "r/w";
|
||||
break;
|
||||
case LVM_READ:
|
||||
access = "r";
|
||||
break;
|
||||
case LVM_WRITE:
|
||||
access = "w";
|
||||
break;
|
||||
default:
|
||||
access = "";
|
||||
}
|
||||
|
||||
if (!id_write_format(&vg->id, uuid, sizeof(uuid))) {
|
||||
stack;
|
||||
return;
|
||||
}
|
||||
|
||||
log_print("%s:%s:%d:-1:%u:%u:%u:-1:%u:%u:%u:%" PRIu64 ":%" PRIu32
|
||||
":%u:%u:%u:%s",
|
||||
vg->name,
|
||||
access,
|
||||
vg->status,
|
||||
/* internal volume group number; obsolete */
|
||||
vg->max_lv,
|
||||
vg->lv_count,
|
||||
lvs_in_vg_opened(vg),
|
||||
/* FIXME: maximum logical volume size */
|
||||
vg->max_pv,
|
||||
vg->pv_count,
|
||||
active_pvs,
|
||||
(uint64_t) vg->extent_count * (vg->extent_size / 2),
|
||||
vg->extent_size / 2,
|
||||
vg->extent_count,
|
||||
vg->extent_count - vg->free_count,
|
||||
vg->free_count,
|
||||
uuid[0] ? uuid : "none");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -666,15 +650,15 @@ void vgdisplay_short(struct volume_group *vg)
|
||||
{
|
||||
log_print("\"%s\" %-9s [%-9s used / %s free]", vg->name,
|
||||
/********* FIXME if "open" print "/used" else print "/idle"??? ******/
|
||||
display_size(vg->cmd, (uint64_t) vg->extent_count *
|
||||
vg->extent_size / 2, SIZE_SHORT),
|
||||
display_size(vg->cmd,
|
||||
(uint64_t) vg->extent_count * vg->extent_size,
|
||||
SIZE_SHORT),
|
||||
display_size(vg->cmd,
|
||||
((uint64_t) vg->extent_count -
|
||||
vg->free_count) * vg->extent_size / 2,
|
||||
SIZE_SHORT), display_size(vg->cmd,
|
||||
(uint64_t) vg->
|
||||
free_count *
|
||||
vg->extent_size / 2,
|
||||
SIZE_SHORT));
|
||||
vg->free_count) * vg->extent_size,
|
||||
SIZE_SHORT),
|
||||
display_size(vg->cmd,
|
||||
(uint64_t) vg->free_count * vg->extent_size,
|
||||
SIZE_SHORT));
|
||||
return;
|
||||
}
|
||||
|
@@ -1,21 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This LVM library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This LVM library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this LVM library; if not, write to the Free
|
||||
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_DISPLAY_H
|
||||
@@ -32,6 +27,7 @@ uint64_t units_to_bytes(const char *units, char *unit_type);
|
||||
/* Specify size in KB */
|
||||
const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl);
|
||||
char *display_uuid(char *uuidstr);
|
||||
void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre);
|
||||
|
||||
void pvdisplay_colons(struct physical_volume *pv);
|
||||
void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
|
||||
@@ -55,10 +51,4 @@ void vgdisplay_short(struct volume_group *vg);
|
||||
const char *get_alloc_string(alloc_policy_t alloc);
|
||||
alloc_policy_t get_alloc_from_string(const char *str);
|
||||
|
||||
/*
|
||||
* Segment type display conversion routines.
|
||||
*/
|
||||
segment_type_t get_segtype_from_string(const char *str);
|
||||
const char *get_segtype_string(segment_type_t segtype);
|
||||
|
||||
#endif
|
||||
|
101
lib/error/errseg.c
Normal file
101
lib/error/errseg.c
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include "pool.h"
|
||||
#include "list.h"
|
||||
#include "toolcontext.h"
|
||||
#include "segtypes.h"
|
||||
#include "display.h"
|
||||
#include "text_export.h"
|
||||
#include "text_import.h"
|
||||
#include "config.h"
|
||||
#include "str_list.h"
|
||||
#include "targets.h"
|
||||
#include "lvm-string.h"
|
||||
#include "activate.h"
|
||||
|
||||
static const char *_name(const struct lv_segment *seg)
|
||||
{
|
||||
return seg->segtype->name;
|
||||
}
|
||||
|
||||
static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
|
||||
{
|
||||
seg1->len += seg2->len;
|
||||
seg1->area_len += seg2->area_len;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
static int _compose_target_line(struct dev_manager *dm, struct pool *mem,
|
||||
struct config_tree *cft, void **target_state,
|
||||
struct lv_segment *seg, char *params,
|
||||
size_t paramsize, const char **target, int *pos,
|
||||
uint32_t *pvmove_mirror_count)
|
||||
{
|
||||
/* error */
|
||||
|
||||
*target = "error";
|
||||
*params = '\0';
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _target_present(void)
|
||||
{
|
||||
static int checked = 0;
|
||||
static int present = 0;
|
||||
|
||||
if (!checked)
|
||||
present = target_present("error");
|
||||
|
||||
checked = 1;
|
||||
return present;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void _destroy(const struct segment_type *segtype)
|
||||
{
|
||||
dbg_free((void *) segtype);
|
||||
}
|
||||
|
||||
static struct segtype_handler _error_ops = {
|
||||
name:_name,
|
||||
merge_segments:_merge_segments,
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
compose_target_line:_compose_target_line,
|
||||
target_present:_target_present,
|
||||
#endif
|
||||
destroy:_destroy,
|
||||
};
|
||||
|
||||
struct segment_type *init_error_segtype(struct cmd_context *cmd)
|
||||
{
|
||||
struct segment_type *segtype = dbg_malloc(sizeof(*segtype));
|
||||
|
||||
if (!segtype) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
segtype->cmd = cmd;
|
||||
segtype->ops = &_error_ops;
|
||||
segtype->name = "error";
|
||||
segtype->private = NULL;
|
||||
segtype->flags = SEG_CAN_SPLIT | SEG_VIRTUAL;
|
||||
|
||||
return segtype;
|
||||
}
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -39,7 +48,7 @@ static void _destroy(struct dev_filter *f)
|
||||
|
||||
struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
|
||||
{
|
||||
struct dev_filter **filters_copy, *cf;
|
||||
struct dev_filter **filters_copy, *cft;
|
||||
|
||||
if (!filters) {
|
||||
stack;
|
||||
@@ -54,15 +63,15 @@ struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
|
||||
memcpy(filters_copy, filters, sizeof(*filters) * n);
|
||||
filters_copy[n] = NULL;
|
||||
|
||||
if (!(cf = dbg_malloc(sizeof(*cf)))) {
|
||||
if (!(cft = dbg_malloc(sizeof(*cft)))) {
|
||||
log_error("compsoite filters allocation failed");
|
||||
dbg_free(filters_copy);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cf->passes_filter = _and_p;
|
||||
cf->destroy = _destroy;
|
||||
cf->private = filters_copy;
|
||||
cft->passes_filter = _and_p;
|
||||
cft->destroy = _destroy;
|
||||
cft->private = filters_copy;
|
||||
|
||||
return cf;
|
||||
return cft;
|
||||
}
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_FILTER_COMPOSITE_H
|
||||
|
98
lib/filters/filter-md.c
Normal file
98
lib/filters/filter-md.c
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Luca Berra
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include "filter-md.h"
|
||||
#include "metadata.h"
|
||||
|
||||
#ifdef linux
|
||||
|
||||
/* Lifted from <linux/raid/md_p.h> because of difficulty including it */
|
||||
|
||||
#define MD_SB_MAGIC 0xa92b4efc
|
||||
#define MD_RESERVED_BYTES (64 * 1024)
|
||||
#define MD_RESERVED_SECTORS (MD_RESERVED_BYTES / 512)
|
||||
#define MD_NEW_SIZE_SECTORS(x) ((x & ~(MD_RESERVED_SECTORS - 1)) \
|
||||
- MD_RESERVED_SECTORS)
|
||||
|
||||
static int _ignore_md(struct dev_filter *f, struct device *dev)
|
||||
{
|
||||
uint64_t size, sector;
|
||||
uint32_t md_magic;
|
||||
|
||||
if (!dev_get_size(dev, &size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (size < MD_RESERVED_SECTORS * 2)
|
||||
/*
|
||||
* We could ignore it since it is obviously too
|
||||
* small, but that's not our job.
|
||||
*/
|
||||
return 1;
|
||||
|
||||
if (!dev_open(dev)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sector = MD_NEW_SIZE_SECTORS(size);
|
||||
|
||||
/* Check if it is an md component device. */
|
||||
if (dev_read(dev, sector << SECTOR_SHIFT, sizeof(uint32_t), &md_magic)) {
|
||||
if (md_magic == MD_SB_MAGIC) {
|
||||
log_debug("%s: Skipping md component device",
|
||||
dev_name(dev));
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _destroy(struct dev_filter *f)
|
||||
{
|
||||
dbg_free(f);
|
||||
}
|
||||
|
||||
struct dev_filter *md_filter_create(void)
|
||||
{
|
||||
struct dev_filter *f;
|
||||
|
||||
if (!(f = dbg_malloc(sizeof(*f)))) {
|
||||
log_error("md filter allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f->passes_filter = _ignore_md;
|
||||
f->destroy = _destroy;
|
||||
f->private = NULL;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
struct dev_filter *md_filter_create(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
23
lib/filters/filter-md.h
Normal file
23
lib/filters/filter-md.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Luca Berra
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_FILTER_MD_H
|
||||
#define _LVM_FILTER_MD_H
|
||||
|
||||
#include "dev-cache.h"
|
||||
|
||||
struct dev_filter *md_filter_create(void);
|
||||
|
||||
#endif
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -51,13 +60,13 @@ int persistent_filter_wipe(struct dev_filter *f)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _read_array(struct pfilter *pf, struct config_tree *cf,
|
||||
static int _read_array(struct pfilter *pf, struct config_tree *cft,
|
||||
const char *path, void *data)
|
||||
{
|
||||
struct config_node *cn;
|
||||
const struct config_node *cn;
|
||||
struct config_value *cv;
|
||||
|
||||
if (!(cn = find_config_node(cf->root, path, '/'))) {
|
||||
if (!(cn = find_config_node(cft->root, path))) {
|
||||
log_very_verbose("Couldn't find %s array in '%s'",
|
||||
path, pf->file);
|
||||
return 0;
|
||||
@@ -88,22 +97,22 @@ int persistent_filter_load(struct dev_filter *f)
|
||||
struct pfilter *pf = (struct pfilter *) f->private;
|
||||
|
||||
int r = 0;
|
||||
struct config_tree *cf;
|
||||
struct config_tree *cft;
|
||||
|
||||
if (!(cf = create_config_tree())) {
|
||||
if (!(cft = create_config_tree(pf->file))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!read_config_file(cf, pf->file)) {
|
||||
if (!read_config_file(cft)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
|
||||
_read_array(pf, cf, "persistent_filter_cache/valid_devices",
|
||||
_read_array(pf, cft, "persistent_filter_cache/valid_devices",
|
||||
PF_GOOD_DEVICE);
|
||||
/* We don't gain anything by holding invalid devices */
|
||||
/* _read_array(pf, cf, "persistent_filter_cache/invalid_devices",
|
||||
/* _read_array(pf, cft, "persistent_filter_cache/invalid_devices",
|
||||
PF_BAD_DEVICE); */
|
||||
|
||||
/* Did we find anything? */
|
||||
@@ -116,7 +125,7 @@ int persistent_filter_load(struct dev_filter *f)
|
||||
log_very_verbose("Loaded persistent filter cache from %s", pf->file);
|
||||
|
||||
out:
|
||||
destroy_config_tree(cf);
|
||||
destroy_config_tree(cft);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_FILTER_PERSISTENT_H
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -42,7 +51,7 @@ static int _extract_pattern(struct pool *mem, const char *pat,
|
||||
pat++;
|
||||
|
||||
/*
|
||||
* get the seperator
|
||||
* get the separator
|
||||
*/
|
||||
switch (*pat) {
|
||||
case '(':
|
||||
@@ -75,7 +84,7 @@ static int _extract_pattern(struct pool *mem, const char *pat,
|
||||
*/
|
||||
ptr = r + strlen(r) - 1;
|
||||
if (*ptr != sep) {
|
||||
log_info("invalid seperator at end of regex");
|
||||
log_info("invalid separator at end of regex");
|
||||
return 0;
|
||||
}
|
||||
*ptr = '\0';
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_FILTER_REGEX_H
|
||||
|
@@ -1,7 +1,15 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Red Hat Inc
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -9,9 +17,8 @@
|
||||
#include "lvm-string.h"
|
||||
#include "pool.h"
|
||||
|
||||
#include <sys/sysmacros.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef linux
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
static int _locate_sysfs_blocks(const char *proc, char *path, size_t len)
|
||||
@@ -19,7 +26,7 @@ static int _locate_sysfs_blocks(const char *proc, char *path, size_t len)
|
||||
char proc_mounts[PATH_MAX];
|
||||
int r = 0;
|
||||
FILE *fp;
|
||||
char *split[2], buffer[PATH_MAX + 16];
|
||||
char *split[4], buffer[PATH_MAX + 16];
|
||||
|
||||
if (!*proc) {
|
||||
log_verbose("No proc filesystem found: skipping sysfs filter");
|
||||
@@ -38,8 +45,8 @@ static int _locate_sysfs_blocks(const char *proc, char *path, size_t len)
|
||||
}
|
||||
|
||||
while (fgets(buffer, sizeof(buffer), fp)) {
|
||||
if (split_words(buffer, 2, split) == 2 &&
|
||||
!strcmp(split[0], "sysfs")) {
|
||||
if (split_words(buffer, 4, split) == 4 &&
|
||||
!strcmp(split[2], "sysfs")) {
|
||||
if (lvm_snprintf(path, len, "%s/%s", split[1],
|
||||
"block") >= 0) {
|
||||
r = 1;
|
||||
@@ -271,3 +278,11 @@ struct dev_filter *sysfs_filter_create(const char *proc)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
struct dev_filter *sysfs_filter_create(const char *proc)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -1,7 +1,15 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Red Hat Inc
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_FILTER_SYSFS_H
|
||||
|
@@ -1,21 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* lvm is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* lvm is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU CC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -58,6 +53,8 @@ static const device_info_t device_info[] = {
|
||||
{"ubd", 16}, /* User-mode virtual block device */
|
||||
{"ataraid", 16}, /* ATA Raid */
|
||||
{"drbd", 16}, /* Distributed Replicated Block Device */
|
||||
{"power2", 16}, /* EMC Powerpath */
|
||||
{"i2o_block", 16}, /* i2o Block Disk */
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
@@ -86,7 +83,7 @@ static int _passes_lvm_type_device_filter(struct dev_filter *f,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int *_scan_proc_dev(const char *proc, struct config_node *cn)
|
||||
static int *_scan_proc_dev(const char *proc, const struct config_node *cn)
|
||||
{
|
||||
char line[80];
|
||||
char proc_devices[PATH_MAX];
|
||||
@@ -203,7 +200,7 @@ static int *_scan_proc_dev(const char *proc, struct config_node *cn)
|
||||
}
|
||||
|
||||
struct dev_filter *lvm_type_filter_create(const char *proc,
|
||||
struct config_node *cn)
|
||||
const struct config_node *cn)
|
||||
{
|
||||
struct dev_filter *f;
|
||||
|
||||
|
@@ -1,21 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* lvm is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* lvm is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU CC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_FILTER_H
|
||||
@@ -34,7 +29,7 @@
|
||||
#endif
|
||||
|
||||
struct dev_filter *lvm_type_filter_create(const char *proc,
|
||||
struct config_node *cn);
|
||||
const struct config_node *cn);
|
||||
|
||||
void lvm_type_filter_destroy(struct dev_filter *f);
|
||||
|
||||
|
@@ -1,7 +0,0 @@
|
||||
Base {
|
||||
global:
|
||||
init_format;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
|
1
lib/format1/.exported_symbols
Normal file
1
lib/format1/.exported_symbols
Normal file
@@ -0,0 +1 @@
|
||||
init_format
|
@@ -1,14 +1,22 @@
|
||||
#
|
||||
# Copyright (C) 2002 Sistina Software (UK) Limited.
|
||||
# Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is released under the LGPL.
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
SOURCES=\
|
||||
SOURCES =\
|
||||
disk-rep.c \
|
||||
format1.c \
|
||||
import-export.c \
|
||||
@@ -17,15 +25,14 @@ SOURCES=\
|
||||
lvm1-label.c \
|
||||
vg_number.c
|
||||
|
||||
TARGETS=liblvm2format1.so
|
||||
LIB_SHARED = liblvm2format1.so
|
||||
|
||||
include ../../make.tmpl
|
||||
|
||||
.PHONY: install
|
||||
|
||||
install: liblvm2format1.so
|
||||
$(INSTALL) -D -o $(OWNER) -g $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/liblvm2format1.so.$(LIB_VERSION)
|
||||
$(LN_S) -f liblvm2format1.so.$(LIB_VERSION) $(libdir)/liblvm2format1.so
|
||||
|
||||
.PHONY: install
|
||||
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -108,6 +117,7 @@ static void _xlate_extents(struct pe_disk *extents, uint32_t count)
|
||||
static int _munge_formats(struct pv_disk *pvd)
|
||||
{
|
||||
uint32_t pe_start;
|
||||
int b, e;
|
||||
|
||||
switch (pvd->version) {
|
||||
case 1:
|
||||
@@ -125,17 +135,54 @@ static int _munge_formats(struct pv_disk *pvd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* UUID too long? */
|
||||
if (pvd->pv_uuid[ID_LEN]) {
|
||||
/* Retain ID_LEN chars from end */
|
||||
for (e = ID_LEN; e < sizeof(pvd->pv_uuid); e++) {
|
||||
if (!pvd->pv_uuid[e]) {
|
||||
e--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (b = 0; b < ID_LEN; b++) {
|
||||
pvd->pv_uuid[b] = pvd->pv_uuid[++e - ID_LEN];
|
||||
/* FIXME Remove all invalid chars */
|
||||
if (pvd->pv_uuid[b] == '/')
|
||||
pvd->pv_uuid[b] = '#';
|
||||
}
|
||||
memset(&pvd->pv_uuid[ID_LEN], 0, sizeof(pvd->pv_uuid) - ID_LEN);
|
||||
}
|
||||
|
||||
/* If UUID is missing, create one */
|
||||
if (pvd->pv_uuid[0] == '\0')
|
||||
uuid_from_num(pvd->pv_uuid, pvd->pv_number);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _read_pvd(struct device *dev, struct pv_disk *pvd)
|
||||
/*
|
||||
* If exported, remove "PV_EXP" from end of VG name
|
||||
*/
|
||||
static void _munge_exported_vg(struct pv_disk *pvd)
|
||||
{
|
||||
if (!dev_read(dev, UINT64_C(0), sizeof(*pvd), pvd)) {
|
||||
log_very_verbose("Failed to read PV data from %s",
|
||||
dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
int l;
|
||||
size_t s;
|
||||
|
||||
/* Return if PV not in a VG */
|
||||
if ((!*pvd->vg_name))
|
||||
return;
|
||||
/* FIXME also check vgd->status & VG_EXPORTED? */
|
||||
|
||||
l = strlen(pvd->vg_name);
|
||||
s = sizeof(EXPORTED_TAG);
|
||||
if (!strncmp(pvd->vg_name + l - s + 1, EXPORTED_TAG, s)) {
|
||||
pvd->vg_name[l - s + 1] = '\0';
|
||||
pvd->pv_status |= VG_EXPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
int munge_pvd(struct device *dev, struct pv_disk *pvd)
|
||||
{
|
||||
_xlate_pvd(pvd);
|
||||
|
||||
if (pvd->id[0] != 'H' || pvd->id[1] != 'M') {
|
||||
@@ -150,13 +197,23 @@ static int _read_pvd(struct device *dev, struct pv_disk *pvd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If UUID is missing, create one */
|
||||
if (pvd->pv_uuid[0] == '\0')
|
||||
uuid_from_num(pvd->pv_uuid, pvd->pv_number);
|
||||
/* If VG is exported, set VG name back to the real name */
|
||||
_munge_exported_vg(pvd);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _read_pvd(struct device *dev, struct pv_disk *pvd)
|
||||
{
|
||||
if (!dev_read(dev, UINT64_C(0), sizeof(*pvd), pvd)) {
|
||||
log_very_verbose("Failed to read PV data from %s",
|
||||
dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return munge_pvd(dev, pvd);
|
||||
}
|
||||
|
||||
static int _read_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
|
||||
{
|
||||
if (!dev_read(dev, pos, sizeof(*disk), disk))
|
||||
@@ -176,6 +233,9 @@ static int _read_vgd(struct disk_list *data)
|
||||
|
||||
_xlate_vgd(vgd);
|
||||
|
||||
if ((vgd->lv_max > MAX_LV) || (vgd->pv_max > MAX_PV))
|
||||
fail;
|
||||
|
||||
/* If UUID is missing, create one */
|
||||
if (vgd->vg_uuid[0] == '\0')
|
||||
uuid_from_num(vgd->vg_uuid, vgd->vg_number);
|
||||
@@ -260,26 +320,6 @@ static int _read_extents(struct disk_list *data)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If exported, remove "PV_EXP" from end of VG name
|
||||
*/
|
||||
void munge_exported_vg(struct pv_disk *pvd)
|
||||
{
|
||||
int l;
|
||||
size_t s;
|
||||
|
||||
/* Return if PV not in a VG */
|
||||
if ((!*pvd->vg_name))
|
||||
return;
|
||||
|
||||
l = strlen(pvd->vg_name);
|
||||
s = sizeof(EXPORTED_TAG);
|
||||
if (!strncmp(pvd->vg_name + l - s + 1, EXPORTED_TAG, s)) {
|
||||
pvd->vg_name[l - s + 1] = '\0';
|
||||
pvd->pv_status |= VG_EXPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
static struct disk_list *__read_disk(const struct format_type *fmt,
|
||||
struct device *dev, struct pool *mem,
|
||||
const char *vg_name)
|
||||
@@ -303,9 +343,6 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* If VG is exported, set VG name back to the real name */
|
||||
munge_exported_vg(&dl->pvd);
|
||||
|
||||
if (!(info = lvmcache_add(fmt->labeller, dl->pvd.pv_uuid, dev,
|
||||
dl->pvd.vg_name, NULL)))
|
||||
stack;
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef DISK_REP_FORMAT1_H
|
||||
@@ -10,6 +19,7 @@
|
||||
#include "lvm-types.h"
|
||||
#include "metadata.h"
|
||||
#include "pool.h"
|
||||
#include "toolcontext.h"
|
||||
|
||||
#define MAX_PV 256
|
||||
#define MAX_LV 256
|
||||
@@ -196,7 +206,8 @@ int write_disks(const struct format_type *fmt, struct list *pvds);
|
||||
int import_pv(struct pool *mem, struct device *dev,
|
||||
struct volume_group *vg,
|
||||
struct physical_volume *pv, struct pv_disk *pvd);
|
||||
int export_pv(struct pool *mem, struct volume_group *vg,
|
||||
int export_pv(struct cmd_context *cmd, struct pool *mem,
|
||||
struct volume_group *vg,
|
||||
struct pv_disk *pvd, struct physical_volume *pv);
|
||||
|
||||
int import_vg(struct pool *mem,
|
||||
@@ -205,7 +216,7 @@ int export_vg(struct vg_disk *vgd, struct volume_group *vg);
|
||||
|
||||
int import_lv(struct pool *mem, struct logical_volume *lv, struct lv_disk *lvd);
|
||||
|
||||
int import_extents(struct pool *mem, struct volume_group *vg,
|
||||
int import_extents(struct cmd_context *cmd, struct volume_group *vg,
|
||||
struct list *pvds);
|
||||
int export_extents(struct disk_list *dl, uint32_t lv_num,
|
||||
struct logical_volume *lv, struct physical_volume *pv);
|
||||
@@ -226,7 +237,7 @@ int export_uuids(struct disk_list *dl, struct volume_group *vg);
|
||||
void export_numbers(struct list *pvds, struct volume_group *vg);
|
||||
|
||||
void export_pv_act(struct list *pvds);
|
||||
void munge_exported_vg(struct pv_disk *pvd);
|
||||
int munge_pvd(struct device *dev, struct pv_disk *pvd);
|
||||
|
||||
/* blech */
|
||||
int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -139,6 +148,7 @@ static struct volume_group *_build_vg(struct format_instance *fid,
|
||||
list_init(&vg->pvs);
|
||||
list_init(&vg->lvs);
|
||||
list_init(&vg->snapshots);
|
||||
list_init(&vg->tags);
|
||||
|
||||
if (!_check_vgs(pvs, &partial))
|
||||
goto bad;
|
||||
@@ -154,7 +164,7 @@ static struct volume_group *_build_vg(struct format_instance *fid,
|
||||
if (!import_lvs(mem, vg, pvs))
|
||||
goto bad;
|
||||
|
||||
if (!import_extents(mem, vg, pvs))
|
||||
if (!import_extents(fid->fmt->cmd, vg, pvs))
|
||||
goto bad;
|
||||
|
||||
if (!import_snapshots(mem, vg, pvs))
|
||||
@@ -201,7 +211,8 @@ static struct volume_group *_vg_read(struct format_instance *fid,
|
||||
return vg;
|
||||
}
|
||||
|
||||
static struct disk_list *_flatten_pv(struct pool *mem, struct volume_group *vg,
|
||||
static struct disk_list *_flatten_pv(struct format_instance *fid,
|
||||
struct pool *mem, struct volume_group *vg,
|
||||
struct physical_volume *pv,
|
||||
const char *dev_dir)
|
||||
{
|
||||
@@ -218,7 +229,7 @@ static struct disk_list *_flatten_pv(struct pool *mem, struct volume_group *vg,
|
||||
list_init(&dl->uuids);
|
||||
list_init(&dl->lvds);
|
||||
|
||||
if (!export_pv(mem, vg, &dl->pvd, pv) ||
|
||||
if (!export_pv(fid->fmt->cmd, mem, vg, &dl->pvd, pv) ||
|
||||
!export_vg(&dl->vgd, vg) ||
|
||||
!export_uuids(dl, vg) ||
|
||||
!export_lvs(dl, vg, pv, dev_dir) || !calculate_layout(dl)) {
|
||||
@@ -242,7 +253,7 @@ static int _flatten_vg(struct format_instance *fid, struct pool *mem,
|
||||
list_iterate(pvh, &vg->pvs) {
|
||||
pvl = list_item(pvh, struct pv_list);
|
||||
|
||||
if (!(data = _flatten_pv(mem, vg, pvl->pv, dev_dir))) {
|
||||
if (!(data = _flatten_pv(fid, mem, vg, pvl->pv, dev_dir))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -334,7 +345,7 @@ static int _pv_setup(const struct format_type *fmt,
|
||||
pv->size--;
|
||||
if (pv->size > MAX_PV_SIZE) {
|
||||
log_error("Physical volumes cannot be bigger than %s",
|
||||
display_size(fmt->cmd, (uint64_t) MAX_PV_SIZE / 2,
|
||||
display_size(fmt->cmd, (uint64_t) MAX_PV_SIZE,
|
||||
SIZE_SHORT));
|
||||
return 0;
|
||||
}
|
||||
@@ -375,7 +386,7 @@ static int _lv_setup(struct format_instance *fid, struct logical_volume *lv)
|
||||
}
|
||||
if (lv->size > max_size) {
|
||||
log_error("logical volumes cannot be larger than %s",
|
||||
display_size(fid->fmt->cmd, max_size / 2,
|
||||
display_size(fid->fmt->cmd, max_size,
|
||||
SIZE_SHORT));
|
||||
return 0;
|
||||
}
|
||||
@@ -421,7 +432,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
|
||||
dl->mem = mem;
|
||||
dl->dev = pv->dev;
|
||||
|
||||
if (!export_pv(mem, NULL, &dl->pvd, pv)) {
|
||||
if (!export_pv(fmt->cmd, mem, NULL, &dl->pvd, pv)) {
|
||||
stack;
|
||||
goto bad;
|
||||
}
|
||||
@@ -457,21 +468,18 @@ static int _vg_setup(struct format_instance *fid, struct volume_group *vg)
|
||||
|
||||
if (vg->extent_size > MAX_PE_SIZE || vg->extent_size < MIN_PE_SIZE) {
|
||||
log_error("Extent size must be between %s and %s",
|
||||
display_size(fid->fmt->cmd, (uint64_t) MIN_PE_SIZE
|
||||
/ 2,
|
||||
SIZE_SHORT), display_size(fid->fmt->cmd,
|
||||
(uint64_t)
|
||||
MAX_PE_SIZE
|
||||
/ 2,
|
||||
SIZE_SHORT));
|
||||
display_size(fid->fmt->cmd, (uint64_t) MIN_PE_SIZE,
|
||||
SIZE_SHORT),
|
||||
display_size(fid->fmt->cmd, (uint64_t) MAX_PE_SIZE,
|
||||
SIZE_SHORT));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vg->extent_size % MIN_PE_SIZE) {
|
||||
log_error("Extent size must be multiple of %s",
|
||||
display_size(fid->fmt->cmd,
|
||||
(uint64_t) MIN_PE_SIZE / 2, SIZE_SHORT));
|
||||
display_size(fid->fmt->cmd, (uint64_t) MIN_PE_SIZE,
|
||||
SIZE_SHORT));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_FORMAT1_H
|
||||
|
@@ -1,9 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Translates between disk and in-core formats.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -13,9 +24,10 @@
|
||||
#include "list.h"
|
||||
#include "lvm-string.h"
|
||||
#include "filter.h"
|
||||
#include "toolcontext.h"
|
||||
#include "segtypes.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
static int _check_vg_name(const char *name)
|
||||
{
|
||||
@@ -56,9 +68,9 @@ int import_pv(struct pool *mem, struct device *dev,
|
||||
|
||||
if (vg &&
|
||||
strncmp(vg->system_id, pvd->system_id, sizeof(pvd->system_id)))
|
||||
log_very_verbose("System ID %s on %s differs from %s for "
|
||||
"volume group", pvd->system_id,
|
||||
dev_name(pv->dev), vg->system_id);
|
||||
log_very_verbose("System ID %s on %s differs from %s for "
|
||||
"volume group", pvd->system_id,
|
||||
dev_name(pv->dev), vg->system_id);
|
||||
|
||||
/*
|
||||
* If exported, we still need to flag in pv->status too because
|
||||
@@ -76,20 +88,16 @@ int import_pv(struct pool *mem, struct device *dev,
|
||||
pv->pe_count = pvd->pe_total;
|
||||
pv->pe_alloc_count = pvd->pe_allocated;
|
||||
|
||||
list_init(&pv->tags);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _system_id(char *s, const char *prefix)
|
||||
static int _system_id(struct cmd_context *cmd, char *s, const char *prefix)
|
||||
{
|
||||
struct utsname uts;
|
||||
|
||||
if (uname(&uts) != 0) {
|
||||
log_sys_error("uname", "_system_id");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lvm_snprintf(s, NAME_LEN, "%s%s%lu",
|
||||
prefix, uts.nodename, time(NULL)) < 0) {
|
||||
prefix, cmd->hostname, time(NULL)) < 0) {
|
||||
log_error("Generated system_id too long");
|
||||
return 0;
|
||||
}
|
||||
@@ -97,7 +105,8 @@ static int _system_id(char *s, const char *prefix)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int export_pv(struct pool *mem, struct volume_group *vg,
|
||||
int export_pv(struct cmd_context *cmd, struct pool *mem,
|
||||
struct volume_group *vg,
|
||||
struct pv_disk *pvd, struct physical_volume *pv)
|
||||
{
|
||||
memset(pvd, 0, sizeof(*pvd));
|
||||
@@ -128,7 +137,7 @@ int export_pv(struct pool *mem, struct volume_group *vg,
|
||||
if (!*vg->system_id ||
|
||||
strncmp(vg->system_id, EXPORTED_TAG,
|
||||
sizeof(EXPORTED_TAG) - 1)) {
|
||||
if (!_system_id(pvd->system_id, EXPORTED_TAG)) {
|
||||
if (!_system_id(cmd, pvd->system_id, EXPORTED_TAG)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -145,7 +154,7 @@ int export_pv(struct pool *mem, struct volume_group *vg,
|
||||
/* Is VG being imported? */
|
||||
if (vg && !(vg->status & EXPORTED_VG) && *vg->system_id &&
|
||||
!strncmp(vg->system_id, EXPORTED_TAG, sizeof(EXPORTED_TAG) - 1)) {
|
||||
if (!_system_id(pvd->system_id, IMPORTED_TAG)) {
|
||||
if (!_system_id(cmd, pvd->system_id, IMPORTED_TAG)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -153,7 +162,7 @@ int export_pv(struct pool *mem, struct volume_group *vg,
|
||||
|
||||
/* Generate system_id if PV is in VG */
|
||||
if (!pvd->system_id || !*pvd->system_id)
|
||||
if (!_system_id(pvd->system_id, "")) {
|
||||
if (!_system_id(cmd, pvd->system_id, "")) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -162,7 +171,7 @@ int export_pv(struct pool *mem, struct volume_group *vg,
|
||||
if (vg &&
|
||||
(!*vg->system_id ||
|
||||
strncmp(vg->system_id, pvd->system_id, sizeof(pvd->system_id))))
|
||||
strncpy(vg->system_id, pvd->system_id, NAME_LEN);
|
||||
strncpy(vg->system_id, pvd->system_id, NAME_LEN);
|
||||
|
||||
//pvd->pv_major = MAJOR(pv->dev);
|
||||
|
||||
@@ -228,6 +237,7 @@ int import_vg(struct pool *mem,
|
||||
vg->free_count = vgd->pe_total - vgd->pe_allocated;
|
||||
vg->max_lv = vgd->lv_max;
|
||||
vg->max_pv = vgd->pv_max;
|
||||
vg->alloc = ALLOC_NORMAL;
|
||||
|
||||
if (partial)
|
||||
vg->status |= PARTIAL_VG;
|
||||
@@ -307,13 +317,14 @@ int import_lv(struct pool *mem, struct logical_volume *lv, struct lv_disk *lvd)
|
||||
if (lvd->lv_allocation & LV_CONTIGUOUS)
|
||||
lv->alloc = ALLOC_CONTIGUOUS;
|
||||
else
|
||||
lv->alloc = ALLOC_NEXT_FREE;
|
||||
lv->alloc = ALLOC_NORMAL;
|
||||
|
||||
lv->read_ahead = lvd->lv_read_ahead;
|
||||
lv->size = lvd->lv_size;
|
||||
lv->le_count = lvd->lv_allocated_le;
|
||||
|
||||
list_init(&lv->segments);
|
||||
list_init(&lv->tags);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -371,9 +382,10 @@ int export_extents(struct disk_list *dl, uint32_t lv_num,
|
||||
seg = list_item(segh, struct lv_segment);
|
||||
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
if (seg->type != SEG_STRIPED) {
|
||||
log_error("Non-striped segment type in LV %s: "
|
||||
"unsupported by format1", lv->name);
|
||||
if (!(seg->segtype->flags & SEG_FORMAT1_SUPPORT)) {
|
||||
log_error("Segment type %s in LV %s: "
|
||||
"unsupported by format1",
|
||||
seg->segtype->name, lv->name);
|
||||
return 0;
|
||||
}
|
||||
if (seg->area[s].type != AREA_PV) {
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -10,6 +19,8 @@
|
||||
#include "pool.h"
|
||||
#include "disk-rep.h"
|
||||
#include "lv_alloc.h"
|
||||
#include "display.h"
|
||||
#include "segtypes.h"
|
||||
|
||||
/*
|
||||
* After much thought I have decided it is easier,
|
||||
@@ -192,21 +203,24 @@ static int _check_maps_are_complete(struct hash_table *maps)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _read_linear(struct pool *mem, struct lv_map *lvm)
|
||||
static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
|
||||
{
|
||||
uint32_t le = 0;
|
||||
struct lv_segment *seg;
|
||||
|
||||
while (le < lvm->lv->le_count) {
|
||||
seg = alloc_lv_segment(mem, 1);
|
||||
seg = alloc_lv_segment(cmd->mem, 1);
|
||||
|
||||
seg->lv = lvm->lv;
|
||||
seg->type = SEG_STRIPED;
|
||||
if (!(seg->segtype = get_segtype_from_string(cmd, "striped"))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
seg->le = le;
|
||||
seg->len = 0;
|
||||
seg->area_len = 0;
|
||||
seg->stripe_size = 0;
|
||||
seg->area_count = 1;
|
||||
|
||||
seg->area[0].type = AREA_PV;
|
||||
seg->area[0].u.pv.pv = lvm->map[le].pv;
|
||||
@@ -242,13 +256,12 @@ static int _check_stripe(struct lv_map *lvm, struct lv_segment *seg,
|
||||
if ((lvm->map[le + st * len].pv != seg->area[st].u.pv.pv) ||
|
||||
(seg->area[st].u.pv.pv &&
|
||||
lvm->map[le + st * len].pe !=
|
||||
seg->area[st].u.pv.pe + seg->len))
|
||||
return 0;
|
||||
seg->area[st].u.pv.pe + seg->len)) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _read_stripes(struct pool *mem, struct lv_map *lvm)
|
||||
static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
|
||||
{
|
||||
uint32_t st, le = 0, len;
|
||||
struct lv_segment *seg;
|
||||
@@ -264,15 +277,17 @@ static int _read_stripes(struct pool *mem, struct lv_map *lvm)
|
||||
len = lvm->lv->le_count / lvm->stripes;
|
||||
|
||||
while (le < len) {
|
||||
if (!(seg = alloc_lv_segment(mem, lvm->stripes))) {
|
||||
if (!(seg = alloc_lv_segment(cmd->mem, lvm->stripes))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
seg->lv = lvm->lv;
|
||||
seg->type = SEG_STRIPED;
|
||||
if (!(seg->segtype = get_segtype_from_string(cmd, "striped"))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
seg->stripe_size = lvm->stripe_size;
|
||||
seg->area_count = lvm->stripes;
|
||||
seg->le = seg->area_count * le;
|
||||
seg->len = 1;
|
||||
seg->area_len = 1;
|
||||
@@ -303,20 +318,20 @@ static int _read_stripes(struct pool *mem, struct lv_map *lvm)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _build_segments(struct pool *mem, struct lv_map *lvm)
|
||||
static int _build_segments(struct cmd_context *cmd, struct lv_map *lvm)
|
||||
{
|
||||
return (lvm->stripes > 1 ? _read_stripes(mem, lvm) :
|
||||
_read_linear(mem, lvm));
|
||||
return (lvm->stripes > 1 ? _read_stripes(cmd, lvm) :
|
||||
_read_linear(cmd, lvm));
|
||||
}
|
||||
|
||||
static int _build_all_segments(struct pool *mem, struct hash_table *maps)
|
||||
static int _build_all_segments(struct cmd_context *cmd, struct hash_table *maps)
|
||||
{
|
||||
struct hash_node *n;
|
||||
struct lv_map *lvm;
|
||||
|
||||
for (n = hash_get_first(maps); n; n = hash_get_next(maps, n)) {
|
||||
lvm = (struct lv_map *) hash_get_data(maps, n);
|
||||
if (!_build_segments(mem, lvm)) {
|
||||
if (!_build_segments(cmd, lvm)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -325,7 +340,8 @@ static int _build_all_segments(struct pool *mem, struct hash_table *maps)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int import_extents(struct pool *mem, struct volume_group *vg, struct list *pvds)
|
||||
int import_extents(struct cmd_context *cmd, struct volume_group *vg,
|
||||
struct list *pvds)
|
||||
{
|
||||
int r = 0;
|
||||
struct pool *scratch = pool_create(10 * 1024);
|
||||
@@ -351,7 +367,7 @@ int import_extents(struct pool *mem, struct volume_group *vg, struct list *pvds)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!_build_all_segments(mem, maps)) {
|
||||
if (!_build_all_segments(cmd, maps)) {
|
||||
log_err("Couldn't build extent segments.");
|
||||
goto out;
|
||||
}
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -51,7 +60,8 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
|
||||
struct pv_disk *pvd = (struct pv_disk *) buf;
|
||||
struct lvmcache_info *info;
|
||||
|
||||
munge_exported_vg(pvd);
|
||||
munge_pvd(dev, pvd);
|
||||
|
||||
if (!(info = lvmcache_add(l, pvd->pv_uuid, dev, pvd->vg_name, NULL))) {
|
||||
stack;
|
||||
return 0;
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_LVM1_LABEL_H
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
|
1
lib/format_pool/.exported_symbols
Normal file
1
lib/format_pool/.exported_symbols
Normal file
@@ -0,0 +1 @@
|
||||
init_format
|
37
lib/format_pool/Makefile.in
Normal file
37
lib/format_pool/Makefile.in
Normal file
@@ -0,0 +1,37 @@
|
||||
#
|
||||
# Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
SOURCES =\
|
||||
disk_rep.c \
|
||||
format_pool.c \
|
||||
import_export.c \
|
||||
pool_label.c
|
||||
|
||||
LIB_SHARED = liblvm2formatpool.so
|
||||
|
||||
include ../../make.tmpl
|
||||
|
||||
.PHONY: install
|
||||
|
||||
install: liblvm2formatpool.so
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/liblvm2formatpool.so.$(LIB_VERSION)
|
||||
$(LN_S) -f liblvm2formatpool.so.$(LIB_VERSION) \
|
||||
$(libdir)/liblvm2formatpool.so
|
||||
|
||||
|
385
lib/format_pool/disk_rep.c
Normal file
385
lib/format_pool/disk_rep.c
Normal file
@@ -0,0 +1,385 @@
|
||||
/*
|
||||
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include "pool.h"
|
||||
#include "label.h"
|
||||
#include "metadata.h"
|
||||
#include "lvmcache.h"
|
||||
#include "filter.h"
|
||||
#include "list.h"
|
||||
#include "xlate.h"
|
||||
|
||||
#include "disk_rep.h"
|
||||
|
||||
/* FIXME: memcpy might not be portable */
|
||||
#define CPIN_8(x, y, z) {memcpy((x), (y), (z));}
|
||||
#define CPOUT_8(x, y, z) {memcpy((y), (x), (z));}
|
||||
#define CPIN_16(x, y) {(x) = xlate16_be((y));}
|
||||
#define CPOUT_16(x, y) {(y) = xlate16_be((x));}
|
||||
#define CPIN_32(x, y) {(x) = xlate32_be((y));}
|
||||
#define CPOUT_32(x, y) {(y) = xlate32_be((x));}
|
||||
#define CPIN_64(x, y) {(x) = xlate64_be((y));}
|
||||
#define CPOUT_64(x, y) {(y) = xlate64_be((x));}
|
||||
|
||||
static int __read_pool_disk(const struct format_type *fmt, struct device *dev,
|
||||
struct pool *mem, struct pool_list *pl,
|
||||
const char *vg_name)
|
||||
{
|
||||
char buf[512];
|
||||
|
||||
/* FIXME: Need to check the cache here first */
|
||||
if (!dev_read(dev, UINT64_C(0), 512, buf)) {
|
||||
log_very_verbose("Failed to read PV data from %s",
|
||||
dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!read_pool_label(pl, fmt->labeller, dev, buf, NULL)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _add_pl_to_list(struct list *head, struct pool_list *data)
|
||||
{
|
||||
struct list *pvdh;
|
||||
struct pool_list *pl;
|
||||
|
||||
list_iterate(pvdh, head) {
|
||||
pl = list_item(pvdh, struct pool_list);
|
||||
|
||||
if (id_equal(&data->pv_uuid, &pl->pv_uuid)) {
|
||||
char uuid[ID_LEN + 7];
|
||||
|
||||
id_write_format(&pl->pv_uuid, uuid, ID_LEN + 7);
|
||||
|
||||
if (MAJOR(data->dev->dev) != md_major()) {
|
||||
log_very_verbose("Ignoring duplicate PV %s on "
|
||||
"%s", uuid,
|
||||
dev_name(data->dev));
|
||||
return;
|
||||
}
|
||||
log_very_verbose("Duplicate PV %s - using md %s",
|
||||
uuid, dev_name(data->dev));
|
||||
list_del(pvdh);
|
||||
break;
|
||||
}
|
||||
}
|
||||
list_add(head, &data->list);
|
||||
}
|
||||
|
||||
int read_pool_label(struct pool_list *pl, struct labeller *l,
|
||||
struct device *dev, char *buf, struct label **label)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
struct id pvid;
|
||||
struct id vgid;
|
||||
char uuid[ID_LEN + 7];
|
||||
struct pool_disk *pd = &pl->pd;
|
||||
|
||||
pool_label_in(pd, buf);
|
||||
|
||||
get_pool_pv_uuid(&pvid, pd);
|
||||
id_write_format(&pvid, uuid, ID_LEN + 7);
|
||||
log_debug("Calculated uuid %s for %s", uuid, dev_name(dev));
|
||||
|
||||
get_pool_vg_uuid(&vgid, pd);
|
||||
id_write_format(&vgid, uuid, ID_LEN + 7);
|
||||
log_debug("Calculated uuid %s for %s", uuid, pd->pl_pool_name);
|
||||
|
||||
if (!(info = lvmcache_add(l, (char *) &pvid, dev, pd->pl_pool_name,
|
||||
(char *) &vgid))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (label)
|
||||
*label = info->label;
|
||||
|
||||
info->device_size = xlate32_be(pd->pl_blocks) << SECTOR_SHIFT;
|
||||
list_init(&info->mdas);
|
||||
|
||||
info->status &= ~CACHE_INVALID;
|
||||
|
||||
pl->dev = dev;
|
||||
pl->pv = NULL;
|
||||
memcpy(&pl->pv_uuid, &pvid, sizeof(pvid));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* pool_label_out - copies a pool_label_t into a char buffer
|
||||
* @pl: ptr to a pool_label_t struct
|
||||
* @buf: ptr to raw space where label info will be copied
|
||||
*
|
||||
* This function is important because it takes care of all of
|
||||
* the endian issues when copying to disk. This way, when
|
||||
* machines of different architectures are used, they will
|
||||
* be able to interpret ondisk labels correctly. Always use
|
||||
* this function before writing to disk.
|
||||
*/
|
||||
void pool_label_out(struct pool_disk *pl, char *buf)
|
||||
{
|
||||
struct pool_disk *bufpl = (struct pool_disk *) buf;
|
||||
|
||||
CPOUT_64(pl->pl_magic, bufpl->pl_magic);
|
||||
CPOUT_64(pl->pl_pool_id, bufpl->pl_pool_id);
|
||||
CPOUT_8(pl->pl_pool_name, bufpl->pl_pool_name, POOL_NAME_SIZE);
|
||||
CPOUT_32(pl->pl_version, bufpl->pl_version);
|
||||
CPOUT_32(pl->pl_subpools, bufpl->pl_subpools);
|
||||
CPOUT_32(pl->pl_sp_id, bufpl->pl_sp_id);
|
||||
CPOUT_32(pl->pl_sp_devs, bufpl->pl_sp_devs);
|
||||
CPOUT_32(pl->pl_sp_devid, bufpl->pl_sp_devid);
|
||||
CPOUT_32(pl->pl_sp_type, bufpl->pl_sp_type);
|
||||
CPOUT_64(pl->pl_blocks, bufpl->pl_blocks);
|
||||
CPOUT_32(pl->pl_striping, bufpl->pl_striping);
|
||||
CPOUT_32(pl->pl_sp_dmepdevs, bufpl->pl_sp_dmepdevs);
|
||||
CPOUT_32(pl->pl_sp_dmepid, bufpl->pl_sp_dmepid);
|
||||
CPOUT_32(pl->pl_sp_weight, bufpl->pl_sp_weight);
|
||||
CPOUT_32(pl->pl_minor, bufpl->pl_minor);
|
||||
CPOUT_32(pl->pl_padding, bufpl->pl_padding);
|
||||
CPOUT_8(pl->pl_reserve, bufpl->pl_reserve, 184);
|
||||
}
|
||||
|
||||
/**
|
||||
* pool_label_in - copies a char buffer into a pool_label_t
|
||||
* @pl: ptr to a pool_label_t struct
|
||||
* @buf: ptr to raw space where label info is copied from
|
||||
*
|
||||
* This function is important because it takes care of all of
|
||||
* the endian issues when information from disk is about to be
|
||||
* used. This way, when machines of different architectures
|
||||
* are used, they will be able to interpret ondisk labels
|
||||
* correctly. Always use this function before using labels that
|
||||
* were read from disk.
|
||||
*/
|
||||
void pool_label_in(struct pool_disk *pl, char *buf)
|
||||
{
|
||||
struct pool_disk *bufpl = (struct pool_disk *) buf;
|
||||
|
||||
CPIN_64(pl->pl_magic, bufpl->pl_magic);
|
||||
CPIN_64(pl->pl_pool_id, bufpl->pl_pool_id);
|
||||
CPIN_8(pl->pl_pool_name, bufpl->pl_pool_name, POOL_NAME_SIZE);
|
||||
CPIN_32(pl->pl_version, bufpl->pl_version);
|
||||
CPIN_32(pl->pl_subpools, bufpl->pl_subpools);
|
||||
CPIN_32(pl->pl_sp_id, bufpl->pl_sp_id);
|
||||
CPIN_32(pl->pl_sp_devs, bufpl->pl_sp_devs);
|
||||
CPIN_32(pl->pl_sp_devid, bufpl->pl_sp_devid);
|
||||
CPIN_32(pl->pl_sp_type, bufpl->pl_sp_type);
|
||||
CPIN_64(pl->pl_blocks, bufpl->pl_blocks);
|
||||
CPIN_32(pl->pl_striping, bufpl->pl_striping);
|
||||
CPIN_32(pl->pl_sp_dmepdevs, bufpl->pl_sp_dmepdevs);
|
||||
CPIN_32(pl->pl_sp_dmepid, bufpl->pl_sp_dmepid);
|
||||
CPIN_32(pl->pl_sp_weight, bufpl->pl_sp_weight);
|
||||
CPIN_32(pl->pl_minor, bufpl->pl_minor);
|
||||
CPIN_32(pl->pl_padding, bufpl->pl_padding);
|
||||
CPIN_8(pl->pl_reserve, bufpl->pl_reserve, 184);
|
||||
}
|
||||
|
||||
static char _calc_char(unsigned int id)
|
||||
{
|
||||
/*
|
||||
* [0-9A-Za-z!#] - 64 printable chars (6-bits)
|
||||
*/
|
||||
|
||||
if (id < 10)
|
||||
return id + 48;
|
||||
if (id < 36)
|
||||
return (id - 10) + 65;
|
||||
if (id < 62)
|
||||
return (id - 36) + 97;
|
||||
if (id == 62)
|
||||
return '!';
|
||||
if (id == 63)
|
||||
return '#';
|
||||
|
||||
return '%';
|
||||
}
|
||||
|
||||
void get_pool_uuid(char *uuid, uint64_t poolid, uint32_t spid, uint32_t devid)
|
||||
{
|
||||
int i;
|
||||
unsigned shifter = 0x003F;
|
||||
|
||||
assert(ID_LEN == 32);
|
||||
memset(uuid, 0, ID_LEN);
|
||||
strcat(uuid, "POOL0000000000");
|
||||
|
||||
/* We grab the entire 64 bits (+2 that get shifted in) */
|
||||
for (i = 13; i < 24; i++) {
|
||||
uuid[i] = _calc_char(((unsigned) poolid) & shifter);
|
||||
poolid = poolid >> 6;
|
||||
}
|
||||
|
||||
/* We grab the entire 32 bits (+4 that get shifted in) */
|
||||
for (i = 24; i < 30; i++) {
|
||||
uuid[i] = _calc_char((unsigned) (spid & shifter));
|
||||
spid = spid >> 6;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since we can only have 128 devices, we only worry about the
|
||||
* last 12 bits
|
||||
*/
|
||||
for (i = 30; i < 32; i++) {
|
||||
uuid[i] = _calc_char((unsigned) (devid & shifter));
|
||||
devid = devid >> 6;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int _read_vg_pds(const struct format_type *fmt, struct pool *mem,
|
||||
struct lvmcache_vginfo *vginfo, struct list *head,
|
||||
uint32_t *devcount)
|
||||
{
|
||||
|
||||
struct list *vgih = NULL;
|
||||
struct device *dev;
|
||||
struct pool_list *pl = NULL;
|
||||
struct pool *tmpmem = NULL;
|
||||
|
||||
uint32_t sp_count = 0;
|
||||
uint32_t *sp_devs = NULL;
|
||||
int i;
|
||||
|
||||
/* FIXME: maybe should return a different error in memory
|
||||
* allocation failure */
|
||||
if (!(tmpmem = pool_create(512))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_iterate(vgih, &vginfo->infos) {
|
||||
dev = list_item(vgih, struct lvmcache_info)->dev;
|
||||
if (dev &&
|
||||
!(pl = read_pool_disk(fmt, dev, mem, vginfo->vgname)))
|
||||
break;
|
||||
/*
|
||||
* We need to keep track of the total expected number
|
||||
* of devices per subpool
|
||||
*/
|
||||
if (!sp_count) {
|
||||
sp_count = pl->pd.pl_subpools;
|
||||
if (!(sp_devs =
|
||||
pool_zalloc(tmpmem,
|
||||
sizeof(uint32_t) * sp_count))) {
|
||||
log_error("Unable to allocate %d 32-bit uints",
|
||||
sp_count);
|
||||
pool_destroy(tmpmem);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* watch out for a pool label with a different subpool
|
||||
* count than the original - give up if it does
|
||||
*/
|
||||
if (sp_count != pl->pd.pl_subpools)
|
||||
break;
|
||||
|
||||
_add_pl_to_list(head, pl);
|
||||
|
||||
if (sp_count > pl->pd.pl_sp_id && sp_devs[pl->pd.pl_sp_id] == 0)
|
||||
sp_devs[pl->pd.pl_sp_id] = pl->pd.pl_sp_devs;
|
||||
}
|
||||
|
||||
*devcount = 0;
|
||||
for (i = 0; i < sp_count; i++) {
|
||||
*devcount += sp_devs[i];
|
||||
}
|
||||
|
||||
pool_destroy(tmpmem);
|
||||
|
||||
if (pl && *pl->pd.pl_pool_name)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int read_pool_pds(const struct format_type *fmt, const char *vg_name,
|
||||
struct pool *mem, struct list *pdhead)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
uint32_t totaldevs;
|
||||
int full_scan = -1;
|
||||
|
||||
do {
|
||||
/*
|
||||
* If the cache scanning doesn't work, this will never work
|
||||
*/
|
||||
if (vg_name && (vginfo = vginfo_from_vgname(vg_name)) &&
|
||||
vginfo->infos.n) {
|
||||
|
||||
if (_read_vg_pds(fmt, mem, vginfo, pdhead, &totaldevs)) {
|
||||
/*
|
||||
* If we found all the devices we were
|
||||
* expecting, return success
|
||||
*/
|
||||
if (list_size(pdhead) == totaldevs)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* accept partial pool if we've done a full
|
||||
* rescan of the cache
|
||||
*/
|
||||
if (full_scan > 0)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/* Failed */
|
||||
list_init(pdhead);
|
||||
|
||||
full_scan++;
|
||||
if (full_scan > 1) {
|
||||
log_debug("No devices for vg %s found in cache",
|
||||
vg_name);
|
||||
return 0;
|
||||
}
|
||||
lvmcache_label_scan(fmt->cmd, full_scan);
|
||||
|
||||
} while (1);
|
||||
|
||||
}
|
||||
|
||||
struct pool_list *read_pool_disk(const struct format_type *fmt,
|
||||
struct device *dev, struct pool *mem,
|
||||
const char *vg_name)
|
||||
{
|
||||
struct pool_list *pl;
|
||||
|
||||
if (!dev_open(dev)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(pl = pool_zalloc(mem, sizeof(*pl)))) {
|
||||
log_error("Unable to allocate pool list structure");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!__read_pool_disk(fmt, dev, mem, pl, vg_name)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
return pl;
|
||||
|
||||
}
|
178
lib/format_pool/disk_rep.h
Normal file
178
lib/format_pool/disk_rep.h
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef DISK_REP_FORMAT_POOL_H
|
||||
#define DISK_REP_FORMAT_POOL_H
|
||||
|
||||
#include "label.h"
|
||||
#include "metadata.h"
|
||||
#include "pool.h"
|
||||
|
||||
/* From NSP.cf */
|
||||
#define NSPMajorVersion 4
|
||||
#define NSPMinorVersion 1
|
||||
#define NSPUpdateLevel 3
|
||||
|
||||
/* From pool_std.h */
|
||||
#define POOL_NAME_SIZE (256)
|
||||
#define POOL_MAGIC 0x011670
|
||||
#define POOL_MAJOR (121)
|
||||
#define POOL_MAX_DEVICES 128
|
||||
|
||||
/* When checking for version matching, the first two numbers **
|
||||
** are important for metadata formats, a.k.a pool labels. **
|
||||
** All the numbers are important when checking if the user **
|
||||
** space tools match up with the kernel module............. */
|
||||
#define POOL_VERSION (NSPMajorVersion << 16 | \
|
||||
NSPMinorVersion << 8 | \
|
||||
NSPUpdateLevel)
|
||||
|
||||
/* Pool label is at the head of every pool disk partition */
|
||||
#define SIZEOF_POOL_LABEL (8192)
|
||||
|
||||
/* in sectors */
|
||||
#define POOL_PE_SIZE (SIZEOF_POOL_LABEL >> SECTOR_SHIFT)
|
||||
#define POOL_PE_START (SIZEOF_POOL_LABEL >> SECTOR_SHIFT)
|
||||
|
||||
/* Helper fxns */
|
||||
#define get_pool_vg_uuid(id, pd) do { get_pool_uuid((char *)(id), \
|
||||
(pd)->pl_pool_id, 0, 0); \
|
||||
} while(0)
|
||||
#define get_pool_pv_uuid(id, pd) do { get_pool_uuid((char *)(id), \
|
||||
(pd)->pl_pool_id, \
|
||||
(pd)->pl_sp_id, \
|
||||
(pd)->pl_sp_devid); \
|
||||
} while(0)
|
||||
#define get_pool_lv_uuid(id, pd) do { get_pool_uuid((char *)&(id)[0], \
|
||||
(pd)->pl_pool_id, 0, 0); \
|
||||
get_pool_uuid((char*)&(id)[1], \
|
||||
(pd)->pl_pool_id, 0, 0); \
|
||||
} while(0)
|
||||
|
||||
struct pool_disk;
|
||||
struct pool_list;
|
||||
struct user_subpool;
|
||||
struct user_device;
|
||||
|
||||
/* This must be kept up to date with sistina/pool/module/pool_sptypes.h */
|
||||
|
||||
/* Generic Labels */
|
||||
#define SPTYPE_DATA (0x00000000)
|
||||
|
||||
/* GFS specific labels */
|
||||
#define SPTYPE_GFS_DATA (0x68011670)
|
||||
#define SPTYPE_GFS_JOURNAL (0x69011670)
|
||||
|
||||
struct sptype_name {
|
||||
const char *name;
|
||||
uint32_t label;
|
||||
};
|
||||
|
||||
static const struct sptype_name sptype_names[] = {
|
||||
{"data", SPTYPE_DATA},
|
||||
|
||||
{"gfs_data", SPTYPE_GFS_DATA},
|
||||
{"gfs_journal", SPTYPE_GFS_JOURNAL},
|
||||
|
||||
{"", 0x0} /* This must be the last flag. */
|
||||
};
|
||||
|
||||
struct pool_disk {
|
||||
uint64_t pl_magic; /* Pool magic number */
|
||||
uint64_t pl_pool_id; /* Unique pool identifier */
|
||||
char pl_pool_name[POOL_NAME_SIZE]; /* Name of pool */
|
||||
uint32_t pl_version; /* Pool version */
|
||||
uint32_t pl_subpools; /* Number of subpools in this pool */
|
||||
uint32_t pl_sp_id; /* Subpool number within pool */
|
||||
uint32_t pl_sp_devs; /* Number of data partitions in this subpool */
|
||||
uint32_t pl_sp_devid; /* Partition number within subpool */
|
||||
uint32_t pl_sp_type; /* Partition type */
|
||||
uint64_t pl_blocks; /* Number of blocks in this partition */
|
||||
uint32_t pl_striping; /* Striping size within subpool */
|
||||
/*
|
||||
* If the number of DMEP devices is zero, then the next field **
|
||||
* ** (pl_sp_dmepid) becomes the subpool ID for redirection. In **
|
||||
* ** other words, if this subpool does not have the capability **
|
||||
* ** to do DMEP, then it must specify which subpool will do it **
|
||||
* ** in it's place
|
||||
*/
|
||||
|
||||
/*
|
||||
* While the next 3 field are no longer used, they must stay to keep **
|
||||
* ** backward compatibility...........................................
|
||||
*/
|
||||
uint32_t pl_sp_dmepdevs;/* Number of dmep devices in this subpool */
|
||||
uint32_t pl_sp_dmepid; /* Dmep device number within subpool */
|
||||
uint32_t pl_sp_weight; /* if dmep dev, pref to using it */
|
||||
|
||||
uint32_t pl_minor; /* the pool minor number */
|
||||
uint32_t pl_padding; /* reminder - think about alignment */
|
||||
|
||||
/*
|
||||
* Even though we're zeroing out 8k at the front of the disk before
|
||||
* writing the label, putting this in
|
||||
*/
|
||||
char pl_reserve[184]; /* bump the structure size out to 512 bytes */
|
||||
};
|
||||
|
||||
struct pool_list {
|
||||
struct list list;
|
||||
struct pool_disk pd;
|
||||
struct physical_volume *pv;
|
||||
struct id pv_uuid;
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
struct user_subpool {
|
||||
uint32_t initialized;
|
||||
uint32_t id;
|
||||
uint32_t striping;
|
||||
uint32_t num_devs;
|
||||
uint32_t type;
|
||||
uint32_t dummy;
|
||||
struct user_device *devs;
|
||||
};
|
||||
|
||||
struct user_device {
|
||||
uint32_t initialized;
|
||||
uint32_t sp_id;
|
||||
uint32_t devid;
|
||||
uint32_t dummy;
|
||||
uint64_t blocks;
|
||||
struct physical_volume *pv;
|
||||
};
|
||||
|
||||
int read_pool_label(struct pool_list *pl, struct labeller *l,
|
||||
struct device *dev, char *buf, struct label **label);
|
||||
void pool_label_out(struct pool_disk *pl, char *buf);
|
||||
void pool_label_in(struct pool_disk *pl, char *buf);
|
||||
void get_pool_uuid(char *uuid, uint64_t poolid, uint32_t spid, uint32_t devid);
|
||||
int import_pool_vg(struct volume_group *vg, struct pool *mem, struct list *pls);
|
||||
int import_pool_lvs(struct volume_group *vg, struct pool *mem,
|
||||
struct list *pls);
|
||||
int import_pool_pvs(const struct format_type *fmt, struct volume_group *vg,
|
||||
struct list *pvs, struct pool *mem, struct list *pls);
|
||||
int import_pool_pv(const struct format_type *fmt, struct pool *mem,
|
||||
struct volume_group *vg, struct physical_volume *pv,
|
||||
struct pool_list *pl);
|
||||
int import_pool_segments(struct list *lvs, struct pool *mem,
|
||||
struct user_subpool *usp, int sp_count);
|
||||
int read_pool_pds(const struct format_type *fmt, const char *vgname,
|
||||
struct pool *mem, struct list *head);
|
||||
struct pool_list *read_pool_disk(const struct format_type *fmt,
|
||||
struct device *dev, struct pool *mem,
|
||||
const char *vg_name);
|
||||
|
||||
#endif /* DISK_REP_POOL_FORMAT_H */
|
361
lib/format_pool/format_pool.c
Normal file
361
lib/format_pool/format_pool.c
Normal file
@@ -0,0 +1,361 @@
|
||||
/*
|
||||
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include "pool.h"
|
||||
#include "label.h"
|
||||
#include "metadata.h"
|
||||
#include "hash.h"
|
||||
#include "limits.h"
|
||||
#include "list.h"
|
||||
#include "display.h"
|
||||
#include "toolcontext.h"
|
||||
#include "lvmcache.h"
|
||||
#include "disk_rep.h"
|
||||
#include "format_pool.h"
|
||||
#include "pool_label.h"
|
||||
|
||||
#define FMT_POOL_NAME "pool"
|
||||
|
||||
/* Must be called after pvs are imported */
|
||||
static struct user_subpool *_build_usp(struct list *pls, struct pool *mem,
|
||||
int *sps)
|
||||
{
|
||||
|
||||
struct list *plhs;
|
||||
struct pool_list *pl;
|
||||
struct user_subpool *usp = NULL, *cur_sp = NULL;
|
||||
struct user_device *cur_dev = NULL;
|
||||
|
||||
/*
|
||||
* FIXME: Need to do some checks here - I'm tempted to add a
|
||||
* user_pool structure and build the entire thing to check against.
|
||||
*/
|
||||
list_iterate(plhs, pls) {
|
||||
pl = list_item(plhs, struct pool_list);
|
||||
|
||||
*sps = pl->pd.pl_subpools;
|
||||
if (!usp && (!(usp = pool_zalloc(mem, sizeof(*usp) * (*sps))))) {
|
||||
log_error("Unable to allocate %d subpool structures",
|
||||
*sps);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cur_sp != &usp[pl->pd.pl_sp_id]) {
|
||||
cur_sp = &usp[pl->pd.pl_sp_id];
|
||||
|
||||
cur_sp->id = pl->pd.pl_sp_id;
|
||||
cur_sp->striping = pl->pd.pl_striping;
|
||||
cur_sp->num_devs = pl->pd.pl_sp_devs;
|
||||
cur_sp->type = pl->pd.pl_sp_type;
|
||||
cur_sp->initialized = 1;
|
||||
}
|
||||
|
||||
if (!cur_sp->devs &&
|
||||
(!(cur_sp->devs =
|
||||
pool_zalloc(mem,
|
||||
sizeof(*usp->devs) * pl->pd.pl_sp_devs)))) {
|
||||
|
||||
log_error("Unable to allocate %d pool_device "
|
||||
"structures", pl->pd.pl_sp_devs);
|
||||
return 0;
|
||||
}
|
||||
cur_dev = &cur_sp->devs[pl->pd.pl_sp_devid];
|
||||
cur_dev->sp_id = cur_sp->id;
|
||||
cur_dev->devid = pl->pd.pl_sp_id;
|
||||
cur_dev->blocks = pl->pd.pl_blocks;
|
||||
cur_dev->pv = pl->pv;
|
||||
cur_dev->initialized = 1;
|
||||
|
||||
}
|
||||
|
||||
return usp;
|
||||
}
|
||||
|
||||
static int _check_usp(char *vgname, struct user_subpool *usp, int sp_count)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < sp_count; i++) {
|
||||
if (!usp[i].initialized) {
|
||||
log_error("Missing subpool %d in pool %s", i, vgname);
|
||||
return 0;
|
||||
}
|
||||
for (j = 0; j < usp[i].num_devs; j++) {
|
||||
if (!usp[i].devs[j].initialized) {
|
||||
log_error("Missing device %d for subpool %d"
|
||||
" in pool %s", j, i, vgname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct volume_group *_build_vg_from_pds(struct format_instance
|
||||
*fid, struct pool *mem,
|
||||
struct list *pds)
|
||||
{
|
||||
struct pool *smem = fid->fmt->cmd->mem;
|
||||
struct volume_group *vg = NULL;
|
||||
struct user_subpool *usp = NULL;
|
||||
int sp_count;
|
||||
|
||||
if (!(vg = pool_zalloc(smem, sizeof(*vg)))) {
|
||||
log_error("Unable to allocate volume group structure");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vg->cmd = fid->fmt->cmd;
|
||||
vg->fid = fid;
|
||||
vg->name = NULL;
|
||||
vg->status = 0;
|
||||
vg->extent_count = 0;
|
||||
vg->pv_count = 0;
|
||||
vg->lv_count = 0;
|
||||
vg->snapshot_count = 0;
|
||||
vg->seqno = 1;
|
||||
vg->system_id = NULL;
|
||||
list_init(&vg->pvs);
|
||||
list_init(&vg->lvs);
|
||||
list_init(&vg->snapshots);
|
||||
list_init(&vg->tags);
|
||||
|
||||
if (!import_pool_vg(vg, smem, pds)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!import_pool_pvs(fid->fmt, vg, &vg->pvs, smem, pds)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!import_pool_lvs(vg, smem, pds)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* I need an intermediate subpool structure that contains all the
|
||||
* relevant info for this. Then i can iterate through the subpool
|
||||
* structures for checking, and create the segments
|
||||
*/
|
||||
if (!(usp = _build_usp(pds, mem, &sp_count))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* check the subpool structures - we can't handle partial VGs in
|
||||
* the pool format, so this will error out if we're missing PVs
|
||||
*/
|
||||
if (!_check_usp(vg->name, usp, sp_count)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!import_pool_segments(&vg->lvs, smem, usp, sp_count)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return vg;
|
||||
}
|
||||
|
||||
static struct volume_group *_vg_read(struct format_instance *fid,
|
||||
const char *vg_name,
|
||||
struct metadata_area *mda)
|
||||
{
|
||||
struct pool *mem = pool_create(1024);
|
||||
struct list pds;
|
||||
struct volume_group *vg = NULL;
|
||||
|
||||
list_init(&pds);
|
||||
|
||||
/* We can safely ignore the mda passed in */
|
||||
|
||||
if (!mem) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Strip dev_dir if present */
|
||||
vg_name = strip_dir(vg_name, fid->fmt->cmd->dev_dir);
|
||||
|
||||
/* Read all the pvs in the vg */
|
||||
if (!read_pool_pds(fid->fmt, vg_name, mem, &pds)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Do the rest of the vg stuff */
|
||||
if (!(vg = _build_vg_from_pds(fid, mem, &pds))) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
pool_destroy(mem);
|
||||
return vg;
|
||||
}
|
||||
|
||||
static int _pv_setup(const struct format_type *fmt,
|
||||
uint64_t pe_start, uint32_t extent_count,
|
||||
uint32_t extent_size,
|
||||
int pvmetadatacopies,
|
||||
uint64_t pvmetadatasize, struct list *mdas,
|
||||
struct physical_volume *pv, struct volume_group *vg)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
struct physical_volume *pv, struct list *mdas)
|
||||
{
|
||||
struct pool *mem = pool_create(1024);
|
||||
struct pool_list *pl;
|
||||
struct device *dev;
|
||||
int r = 0;
|
||||
|
||||
log_very_verbose("Reading physical volume data %s from disk", pv_name);
|
||||
|
||||
if (!mem) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter))) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* I need to read the disk and populate a pv structure here
|
||||
* I'll probably need to abstract some of this later for the
|
||||
* vg_read code
|
||||
*/
|
||||
if (!(pl = read_pool_disk(fmt, dev, mem, NULL))) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!import_pool_pv(fmt, fmt->cmd->mem, NULL, pv, pl)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pv->fmt = fmt;
|
||||
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
pool_destroy(mem);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
static struct metadata_area_ops _metadata_format_pool_ops = {
|
||||
vg_read:_vg_read,
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
static struct format_instance *_create_instance(const struct format_type *fmt,
|
||||
const char *vgname,
|
||||
void *private)
|
||||
{
|
||||
struct format_instance *fid;
|
||||
struct metadata_area *mda;
|
||||
|
||||
if (!(fid = pool_zalloc(fmt->cmd->mem, sizeof(*fid)))) {
|
||||
log_error("Unable to allocate format instance structure for "
|
||||
"pool format");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fid->fmt = fmt;
|
||||
list_init(&fid->metadata_areas);
|
||||
|
||||
/* Define a NULL metadata area */
|
||||
if (!(mda = pool_zalloc(fmt->cmd->mem, sizeof(*mda)))) {
|
||||
log_error("Unable to allocate metadata area structure "
|
||||
"for pool format");
|
||||
pool_free(fmt->cmd->mem, fid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mda->ops = &_metadata_format_pool_ops;
|
||||
mda->metadata_locn = NULL;
|
||||
list_add(&fid->metadata_areas, &mda->list);
|
||||
|
||||
return fid;
|
||||
}
|
||||
|
||||
static void _destroy_instance(struct format_instance *fid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void _destroy(const struct format_type *fmt)
|
||||
{
|
||||
dbg_free((void *) fmt);
|
||||
}
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
static struct format_handler _format_pool_ops = {
|
||||
pv_read:_pv_read,
|
||||
pv_setup:_pv_setup,
|
||||
create_instance:_create_instance,
|
||||
destroy_instance:_destroy_instance,
|
||||
destroy:_destroy,
|
||||
};
|
||||
/* *INDENT-ON */
|
||||
|
||||
#ifdef POOL_INTERNAL
|
||||
struct format_type *init_pool_format(struct cmd_context *cmd)
|
||||
#else /* Shared */
|
||||
struct format_type *init_format(struct cmd_context *cmd);
|
||||
struct format_type *init_format(struct cmd_context *cmd)
|
||||
#endif
|
||||
{
|
||||
struct format_type *fmt = dbg_malloc(sizeof(*fmt));
|
||||
|
||||
if (!fmt) {
|
||||
log_error("Unable to allocate format type structure for pool "
|
||||
"format");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fmt->cmd = cmd;
|
||||
fmt->ops = &_format_pool_ops;
|
||||
fmt->name = FMT_POOL_NAME;
|
||||
fmt->alias = NULL;
|
||||
fmt->features = 0;
|
||||
fmt->private = NULL;
|
||||
|
||||
if (!(fmt->labeller = pool_labeller_create(fmt))) {
|
||||
log_error("Couldn't create pool label handler.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(label_register_handler(FMT_POOL_NAME, fmt->labeller))) {
|
||||
log_error("Couldn't register pool label handler.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return fmt;
|
||||
}
|
25
lib/format_pool/format_pool.h
Normal file
25
lib/format_pool/format_pool.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_FORMAT_POOL_H
|
||||
#define _LVM_FORMAT_POOL_H
|
||||
|
||||
#include "metadata.h"
|
||||
|
||||
#ifdef POOL_INTERNAL
|
||||
struct format_type *init_pool_format(struct cmd_context *cmd);
|
||||
#endif
|
||||
|
||||
#endif
|
309
lib/format_pool/import_export.c
Normal file
309
lib/format_pool/import_export.c
Normal file
@@ -0,0 +1,309 @@
|
||||
/*
|
||||
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include "pool.h"
|
||||
#include "label.h"
|
||||
#include "metadata.h"
|
||||
#include "lvmcache.h"
|
||||
#include "disk_rep.h"
|
||||
#include "lv_alloc.h"
|
||||
#include "str_list.h"
|
||||
#include "display.h"
|
||||
#include "segtypes.h"
|
||||
|
||||
/* This file contains only imports at the moment... */
|
||||
|
||||
int import_pool_vg(struct volume_group *vg, struct pool *mem, struct list *pls)
|
||||
{
|
||||
struct list *plhs;
|
||||
struct pool_list *pl;
|
||||
|
||||
list_iterate(plhs, pls) {
|
||||
pl = list_item(plhs, struct pool_list);
|
||||
|
||||
vg->extent_count +=
|
||||
((pl->pd.pl_blocks) / POOL_PE_SIZE);
|
||||
|
||||
vg->pv_count++;
|
||||
|
||||
if (vg->name)
|
||||
continue;
|
||||
|
||||
vg->name = pool_strdup(mem, pl->pd.pl_pool_name);
|
||||
get_pool_vg_uuid(&vg->id, &pl->pd);
|
||||
vg->extent_size = POOL_PE_SIZE;
|
||||
vg->status |= LVM_READ | LVM_WRITE | CLUSTERED | SHARED;
|
||||
vg->free_count = 0;
|
||||
vg->max_lv = 1;
|
||||
vg->max_pv = POOL_MAX_DEVICES;
|
||||
vg->alloc = ALLOC_NORMAL;
|
||||
vg->lv_count = 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int import_pool_lvs(struct volume_group *vg, struct pool *mem, struct list *pls)
|
||||
{
|
||||
struct pool_list *pl;
|
||||
struct list *plhs;
|
||||
struct lv_list *lvl = pool_zalloc(mem, sizeof(*lvl));
|
||||
struct logical_volume *lv;
|
||||
|
||||
if (!lvl) {
|
||||
log_error("Unable to allocate lv list structure");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(lvl->lv = pool_zalloc(mem, sizeof(*lvl->lv)))) {
|
||||
log_error("Unable to allocate logical volume structure");
|
||||
return 0;
|
||||
}
|
||||
|
||||
lv = lvl->lv;
|
||||
lv->status = 0;
|
||||
lv->vg = vg;
|
||||
lv->alloc = ALLOC_NORMAL;
|
||||
lv->size = 0;
|
||||
lv->name = NULL;
|
||||
lv->le_count = 0;
|
||||
lv->read_ahead = 0;
|
||||
list_init(&lv->segments);
|
||||
list_init(&lv->tags);
|
||||
|
||||
list_iterate(plhs, pls) {
|
||||
pl = list_item(plhs, struct pool_list);
|
||||
|
||||
lv->size += pl->pd.pl_blocks;
|
||||
|
||||
if (lv->name)
|
||||
continue;
|
||||
|
||||
if (!(lv->name = pool_strdup(mem, pl->pd.pl_pool_name))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
get_pool_lv_uuid(lv->lvid.id, &pl->pd);
|
||||
log_debug("Calculated lv uuid for lv %s: %s", lv->name,
|
||||
lv->lvid.s);
|
||||
|
||||
lv->status |= VISIBLE_LV | LVM_READ | LVM_WRITE;
|
||||
lv->major = POOL_MAJOR;
|
||||
|
||||
/* for pool a minor of 0 is dynamic */
|
||||
if (pl->pd.pl_minor) {
|
||||
lv->status |= FIXED_MINOR;
|
||||
lv->minor = pl->pd.pl_minor;
|
||||
} else {
|
||||
lv->minor = -1;
|
||||
}
|
||||
list_init(&lv->segments);
|
||||
list_init(&lv->tags);
|
||||
}
|
||||
|
||||
lv->le_count = lv->size / POOL_PE_SIZE;
|
||||
lvl->lv = lv;
|
||||
list_add(&vg->lvs, &lvl->list);
|
||||
vg->lv_count++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int import_pool_pvs(const struct format_type *fmt, struct volume_group *vg,
|
||||
struct list *pvs, struct pool *mem, struct list *pls)
|
||||
{
|
||||
struct pv_list *pvl;
|
||||
struct pool_list *pl;
|
||||
struct list *plhs;
|
||||
|
||||
list_iterate(plhs, pls) {
|
||||
pl = list_item(plhs, struct pool_list);
|
||||
|
||||
if (!(pvl = pool_zalloc(mem, sizeof(*pvl)))) {
|
||||
log_error("Unable to allocate pv list structure");
|
||||
return 0;
|
||||
}
|
||||
if (!(pvl->pv = pool_zalloc(mem, sizeof(*pvl->pv)))) {
|
||||
log_error("Unable to allocate pv structure");
|
||||
return 0;
|
||||
}
|
||||
if (!import_pool_pv(fmt, mem, vg, pvl->pv, pl)) {
|
||||
return 0;
|
||||
}
|
||||
pl->pv = pvl->pv;
|
||||
pvl->mdas = NULL;
|
||||
pvl->alloc_areas = NULL;
|
||||
list_add(pvs, &pvl->list);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int import_pool_pv(const struct format_type *fmt, struct pool *mem,
|
||||
struct volume_group *vg, struct physical_volume *pv,
|
||||
struct pool_list *pl)
|
||||
{
|
||||
struct pool_disk *pd = &pl->pd;
|
||||
|
||||
memset(pv, 0, sizeof(*pv));
|
||||
|
||||
get_pool_pv_uuid(&pv->id, pd);
|
||||
pv->fmt = fmt;
|
||||
|
||||
pv->dev = pl->dev;
|
||||
if (!(pv->vg_name = pool_strdup(mem, pd->pl_pool_name))) {
|
||||
log_error("Unable to duplicate vg_name string");
|
||||
return 0;
|
||||
}
|
||||
pv->status = 0;
|
||||
pv->size = pd->pl_blocks;
|
||||
pv->pe_size = POOL_PE_SIZE;
|
||||
pv->pe_start = POOL_PE_START;
|
||||
pv->pe_count = pv->size / POOL_PE_SIZE;
|
||||
pv->pe_alloc_count = pv->pe_count;
|
||||
|
||||
list_init(&pv->tags);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const char *_cvt_sptype(uint32_t sptype)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; sptype_names[i].name[0]; i++) {
|
||||
if (sptype == sptype_names[i].label) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
log_debug("Found sptype %X and converted it to %s",
|
||||
sptype, sptype_names[i].name);
|
||||
return sptype_names[i].name;
|
||||
}
|
||||
|
||||
static int _add_stripe_seg(struct pool *mem,
|
||||
struct user_subpool *usp, struct logical_volume *lv,
|
||||
uint32_t *le_cur)
|
||||
{
|
||||
struct lv_segment *seg;
|
||||
int j;
|
||||
|
||||
if (!(seg = alloc_lv_segment(mem, usp->num_devs))) {
|
||||
log_error("Unable to allocate striped lv_segment structure");
|
||||
return 0;
|
||||
}
|
||||
if(usp->striping & (usp->striping - 1)) {
|
||||
log_error("Stripe size must be a power of 2");
|
||||
return 0;
|
||||
}
|
||||
seg->stripe_size = usp->striping;
|
||||
seg->status |= 0;
|
||||
seg->le += *le_cur;
|
||||
|
||||
/* add the subpool type to the segment tag list */
|
||||
str_list_add(mem, &seg->tags, _cvt_sptype(usp->type));
|
||||
|
||||
for (j = 0; j < usp->num_devs; j++) {
|
||||
if (!(seg->segtype = get_segtype_from_string(lv->vg->cmd,
|
||||
"striped"))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
seg->area_len = (usp->devs[j].blocks) / POOL_PE_SIZE;
|
||||
seg->len += seg->area_len;
|
||||
*le_cur += seg->area_len;
|
||||
seg->lv = lv;
|
||||
|
||||
seg->area[j].type = AREA_PV;
|
||||
seg->area[j].u.pv.pv = usp->devs[j].pv;
|
||||
seg->area[j].u.pv.pe = 0;
|
||||
}
|
||||
list_add(&lv->segments, &seg->list);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _add_linear_seg(struct pool *mem,
|
||||
struct user_subpool *usp, struct logical_volume *lv,
|
||||
uint32_t *le_cur)
|
||||
{
|
||||
struct lv_segment *seg;
|
||||
int j;
|
||||
|
||||
for (j = 0; j < usp->num_devs; j++) {
|
||||
/* linear segments only have 1 data area */
|
||||
if (!(seg = alloc_lv_segment(mem, 1))) {
|
||||
log_error("Unable to allocate linear lv_segment "
|
||||
"structure");
|
||||
return 0;
|
||||
}
|
||||
seg->stripe_size = usp->striping;
|
||||
seg->le += *le_cur;
|
||||
seg->chunk_size = POOL_PE_SIZE;
|
||||
seg->status |= 0;
|
||||
if (!(seg->segtype = get_segtype_from_string(lv->vg->cmd,
|
||||
"striped"))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
/* add the subpool type to the segment tag list */
|
||||
str_list_add(mem, &seg->tags, _cvt_sptype(usp->type));
|
||||
|
||||
seg->lv = lv;
|
||||
|
||||
seg->area_len = (usp->devs[j].blocks) / POOL_PE_SIZE;
|
||||
seg->len = seg->area_len;
|
||||
*le_cur += seg->len;
|
||||
seg->area[0].type = AREA_PV;
|
||||
seg->area[0].u.pv.pv = usp->devs[j].pv;
|
||||
seg->area[0].u.pv.pe = 0;
|
||||
list_add(&lv->segments, &seg->list);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int import_pool_segments(struct list *lvs, struct pool *mem,
|
||||
struct user_subpool *usp, int subpools)
|
||||
{
|
||||
|
||||
struct list *lvhs;
|
||||
struct lv_list *lvl;
|
||||
struct logical_volume *lv;
|
||||
uint32_t le_cur = 0;
|
||||
int i;
|
||||
|
||||
list_iterate(lvhs, lvs) {
|
||||
lvl = list_item(lvhs, struct lv_list);
|
||||
|
||||
lv = lvl->lv;
|
||||
for (i = 0; i < subpools; i++) {
|
||||
if (usp[i].striping) {
|
||||
if (!_add_stripe_seg(mem, &usp[i], lv, &le_cur)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (!_add_linear_seg(mem, &usp[i], lv, &le_cur)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
108
lib/format_pool/pool_label.c
Normal file
108
lib/format_pool/pool_label.c
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include "pool.h"
|
||||
#include "label.h"
|
||||
#include "metadata.h"
|
||||
#include "xlate.h"
|
||||
#include "disk_rep.h"
|
||||
#include "pool_label.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
static void _not_supported(const char *op)
|
||||
{
|
||||
log_error("The '%s' operation is not supported for the pool labeller.",
|
||||
op);
|
||||
}
|
||||
|
||||
static int _can_handle(struct labeller *l, char *buf, uint64_t sector)
|
||||
{
|
||||
|
||||
struct pool_disk pd;
|
||||
|
||||
/*
|
||||
* POOL label must always be in first sector
|
||||
*/
|
||||
if (sector)
|
||||
return 0;
|
||||
|
||||
pool_label_in(&pd, buf);
|
||||
|
||||
/* can ignore 8 rightmost bits for ondisk format check */
|
||||
if ((pd.pl_magic == POOL_MAGIC) &&
|
||||
(pd.pl_version >> 8 == POOL_VERSION >> 8))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _write(struct label *label, char *buf)
|
||||
{
|
||||
_not_supported("write");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _read(struct labeller *l, struct device *dev, char *buf,
|
||||
struct label **label)
|
||||
{
|
||||
struct pool_list pl;
|
||||
|
||||
return read_pool_label(&pl, l, dev, buf, label);
|
||||
}
|
||||
|
||||
static int _initialise_label(struct labeller *l, struct label *label)
|
||||
{
|
||||
strcpy(label->type, "POOL");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _destroy_label(struct labeller *l, struct label *label)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void _destroy(struct labeller *l)
|
||||
{
|
||||
dbg_free(l);
|
||||
}
|
||||
|
||||
struct label_ops _pool_ops = {
|
||||
can_handle:_can_handle,
|
||||
write:_write,
|
||||
read:_read,
|
||||
verify:_can_handle,
|
||||
initialise_label:_initialise_label,
|
||||
destroy_label:_destroy_label,
|
||||
destroy:_destroy
|
||||
};
|
||||
|
||||
struct labeller *pool_labeller_create(struct format_type *fmt)
|
||||
{
|
||||
struct labeller *l;
|
||||
|
||||
if (!(l = dbg_malloc(sizeof(*l)))) {
|
||||
log_error("Couldn't allocate labeller object.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
l->ops = &_pool_ops;
|
||||
l->private = (const void *) fmt;
|
||||
|
||||
return l;
|
||||
}
|
23
lib/format_pool/pool_label.h
Normal file
23
lib/format_pool/pool_label.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_POOL_LABEL_H
|
||||
#define _LVM_POOL_LABEL_H
|
||||
|
||||
#include "metadata.h"
|
||||
|
||||
struct labeller *pool_labeller_create(struct format_type *fmt);
|
||||
|
||||
#endif
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -371,4 +380,3 @@ int backup_list(struct cmd_context *cmd, const char *dir, const char *vgname)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -11,6 +20,8 @@
|
||||
#include "pool.h"
|
||||
#include "display.h"
|
||||
#include "lvm-string.h"
|
||||
#include "segtypes.h"
|
||||
#include "text_export.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
@@ -65,14 +76,6 @@ static void _init(void)
|
||||
/*
|
||||
* Formatting functions.
|
||||
*/
|
||||
static int _out_size(struct formatter *f, uint64_t size, const char *fmt, ...)
|
||||
__attribute__ ((format(printf, 3, 4)));
|
||||
|
||||
static int _out_hint(struct formatter *f, const char *fmt, ...)
|
||||
__attribute__ ((format(printf, 2, 3)));
|
||||
|
||||
static int _out(struct formatter *f, const char *fmt, ...)
|
||||
__attribute__ ((format(printf, 2, 3)));
|
||||
|
||||
#define MAX_INDENT 5
|
||||
static void _inc_indent(struct formatter *f)
|
||||
@@ -197,7 +200,7 @@ static int _sectors_to_units(uint64_t sectors, char *buffer, size_t s)
|
||||
* Appends a comment giving a size in more easily
|
||||
* readable form (eg, 4M instead of 8096).
|
||||
*/
|
||||
static int _out_size(struct formatter *f, uint64_t size, const char *fmt, ...)
|
||||
int out_size(struct formatter *f, uint64_t size, const char *fmt, ...)
|
||||
{
|
||||
char buffer[64];
|
||||
va_list ap;
|
||||
@@ -217,7 +220,7 @@ static int _out_size(struct formatter *f, uint64_t size, const char *fmt, ...)
|
||||
* Appends a comment indicating that the line is
|
||||
* only a hint.
|
||||
*/
|
||||
static int _out_hint(struct formatter *f, const char *fmt, ...)
|
||||
int out_hint(struct formatter *f, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int r;
|
||||
@@ -232,7 +235,7 @@ static int _out_hint(struct formatter *f, const char *fmt, ...)
|
||||
/*
|
||||
* The normal output function.
|
||||
*/
|
||||
static int _out(struct formatter *f, const char *fmt, ...)
|
||||
int out_text(struct formatter *f, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int r;
|
||||
@@ -244,8 +247,6 @@ static int _out(struct formatter *f, const char *fmt, ...)
|
||||
return r;
|
||||
}
|
||||
|
||||
#define _outf(args...) do {if (!_out(args)) {stack; return 0;}} while (0)
|
||||
|
||||
static int _print_header(struct formatter *f,
|
||||
struct volume_group *vg, const char *desc)
|
||||
{
|
||||
@@ -253,48 +254,65 @@ static int _print_header(struct formatter *f,
|
||||
|
||||
t = time(NULL);
|
||||
|
||||
_outf(f, "# Generated by LVM2: %s", ctime(&t));
|
||||
_outf(f, CONTENTS_FIELD " = \"" CONTENTS_VALUE "\"");
|
||||
_outf(f, FORMAT_VERSION_FIELD " = %d", FORMAT_VERSION_VALUE);
|
||||
outf(f, "# Generated by LVM2: %s", ctime(&t));
|
||||
outf(f, CONTENTS_FIELD " = \"" CONTENTS_VALUE "\"");
|
||||
outf(f, FORMAT_VERSION_FIELD " = %d", FORMAT_VERSION_VALUE);
|
||||
f->nl(f);
|
||||
|
||||
_outf(f, "description = \"%s\"", desc);
|
||||
outf(f, "description = \"%s\"", desc);
|
||||
f->nl(f);
|
||||
_outf(f, "creation_host = \"%s\"\t# %s %s %s %s %s", _utsname.nodename,
|
||||
_utsname.sysname, _utsname.nodename, _utsname.release,
|
||||
_utsname.version, _utsname.machine);
|
||||
_outf(f, "creation_time = %lu\t# %s", t, ctime(&t));
|
||||
outf(f, "creation_host = \"%s\"\t# %s %s %s %s %s", _utsname.nodename,
|
||||
_utsname.sysname, _utsname.nodename, _utsname.release,
|
||||
_utsname.version, _utsname.machine);
|
||||
outf(f, "creation_time = %lu\t# %s", t, ctime(&t));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _print_vg(struct formatter *f, struct volume_group *vg)
|
||||
{
|
||||
char buffer[256];
|
||||
char buffer[4096];
|
||||
|
||||
if (!id_write_format(&vg->id, buffer, sizeof(buffer))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_outf(f, "id = \"%s\"", buffer);
|
||||
outf(f, "id = \"%s\"", buffer);
|
||||
|
||||
outf(f, "seqno = %u", vg->seqno);
|
||||
|
||||
_outf(f, "seqno = %u", vg->seqno);
|
||||
if (!print_flags(vg->status, VG_FLAGS, buffer, sizeof(buffer))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
outf(f, "status = %s", buffer);
|
||||
|
||||
if (!list_empty(&vg->tags)) {
|
||||
if (!print_tags(&vg->tags, buffer, sizeof(buffer))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
outf(f, "tags = %s", buffer);
|
||||
}
|
||||
|
||||
_outf(f, "status = %s", buffer);
|
||||
if (vg->system_id && *vg->system_id)
|
||||
_outf(f, "system_id = \"%s\"", vg->system_id);
|
||||
if (!_out_size(f, (uint64_t) vg->extent_size, "extent_size = %u",
|
||||
vg->extent_size)) {
|
||||
outf(f, "system_id = \"%s\"", vg->system_id);
|
||||
|
||||
if (!out_size(f, (uint64_t) vg->extent_size, "extent_size = %u",
|
||||
vg->extent_size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
_outf(f, "max_lv = %u", vg->max_lv);
|
||||
_outf(f, "max_pv = %u", vg->max_pv);
|
||||
outf(f, "max_lv = %u", vg->max_lv);
|
||||
outf(f, "max_pv = %u", vg->max_pv);
|
||||
|
||||
/* Default policy is NORMAL; INHERIT is meaningless */
|
||||
if (vg->alloc != ALLOC_NORMAL && vg->alloc != ALLOC_INHERIT) {
|
||||
f->nl(f);
|
||||
outf(f, "allocation_policy = \"%s\"",
|
||||
get_alloc_string(vg->alloc));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -314,10 +332,10 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
|
||||
{
|
||||
struct list *pvh;
|
||||
struct physical_volume *pv;
|
||||
char buffer[256];
|
||||
char buffer[4096];
|
||||
const char *name;
|
||||
|
||||
_outf(f, "physical_volumes {");
|
||||
outf(f, "physical_volumes {");
|
||||
_inc_indent(f);
|
||||
|
||||
list_iterate(pvh, &vg->pvs) {
|
||||
@@ -329,7 +347,7 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
|
||||
}
|
||||
|
||||
f->nl(f);
|
||||
_outf(f, "%s {", name);
|
||||
outf(f, "%s {", name);
|
||||
_inc_indent(f);
|
||||
|
||||
if (!id_write_format(&pv->id, buffer, sizeof(buffer))) {
|
||||
@@ -337,8 +355,8 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
_outf(f, "id = \"%s\"", buffer);
|
||||
if (!_out_hint(f, "device = \"%s\"", dev_name(pv->dev))) {
|
||||
outf(f, "id = \"%s\"", buffer);
|
||||
if (!out_hint(f, "device = \"%s\"", dev_name(pv->dev))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -348,102 +366,106 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
outf(f, "status = %s", buffer);
|
||||
|
||||
_outf(f, "status = %s", buffer);
|
||||
_outf(f, "pe_start = %" PRIu64, pv->pe_start);
|
||||
if (!_out_size(f, vg->extent_size * (uint64_t) pv->pe_count,
|
||||
"pe_count = %u", pv->pe_count)) {
|
||||
if (!list_empty(&pv->tags)) {
|
||||
if (!print_tags(&pv->tags, buffer, sizeof(buffer))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
outf(f, "tags = %s", buffer);
|
||||
}
|
||||
|
||||
outf(f, "pe_start = %" PRIu64, pv->pe_start);
|
||||
if (!out_size(f, vg->extent_size * (uint64_t) pv->pe_count,
|
||||
"pe_count = %u", pv->pe_count)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_dec_indent(f);
|
||||
_outf(f, "}");
|
||||
outf(f, "}");
|
||||
}
|
||||
|
||||
_dec_indent(f);
|
||||
_outf(f, "}");
|
||||
outf(f, "}");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _print_segment(struct formatter *f, struct volume_group *vg,
|
||||
int count, struct lv_segment *seg)
|
||||
{
|
||||
unsigned int s;
|
||||
const char *name;
|
||||
const char *type;
|
||||
char buffer[4096];
|
||||
|
||||
_outf(f, "segment%u {", count);
|
||||
outf(f, "segment%u {", count);
|
||||
_inc_indent(f);
|
||||
|
||||
_outf(f, "start_extent = %u", seg->le);
|
||||
if (!_out_size(f, (uint64_t) seg->len * vg->extent_size,
|
||||
"extent_count = %u", seg->len)) {
|
||||
outf(f, "start_extent = %u", seg->le);
|
||||
if (!out_size(f, (uint64_t) seg->len * vg->extent_size,
|
||||
"extent_count = %u", seg->len)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
f->nl(f);
|
||||
_outf(f, "type = \"%s\"", get_segtype_string(seg->type));
|
||||
outf(f, "type = \"%s\"", seg->segtype->name);
|
||||
|
||||
switch (seg->type) {
|
||||
case SEG_SNAPSHOT:
|
||||
_outf(f, "chunk_size = %u", seg->chunk_size);
|
||||
_outf(f, "origin = \"%s\"", seg->origin->name);
|
||||
_outf(f, "cow_store = \"%s\"", seg->cow->name);
|
||||
break;
|
||||
|
||||
case SEG_MIRRORED:
|
||||
case SEG_STRIPED:
|
||||
type = (seg->type == SEG_MIRRORED) ? "mirror" : "stripe";
|
||||
_outf(f, "%s_count = %u%s", type, seg->area_count,
|
||||
(seg->area_count == 1) ? "\t# linear" : "");
|
||||
|
||||
if ((seg->type == SEG_MIRRORED) && (seg->status & PVMOVE))
|
||||
_out_size(f, (uint64_t) seg->extents_moved,
|
||||
"extents_moved = %u", seg->extents_moved);
|
||||
|
||||
if ((seg->type == SEG_STRIPED) && (seg->area_count > 1))
|
||||
_out_size(f, (uint64_t) seg->stripe_size,
|
||||
"stripe_size = %u", seg->stripe_size);
|
||||
|
||||
f->nl(f);
|
||||
|
||||
_outf(f, "%ss = [", type);
|
||||
_inc_indent(f);
|
||||
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
switch (seg->area[s].type) {
|
||||
case AREA_PV:
|
||||
if (!(name = _get_pv_name(f, seg->
|
||||
area[s].u.pv.pv))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_outf(f, "\"%s\", %u%s", name,
|
||||
seg->area[s].u.pv.pe,
|
||||
(s == seg->area_count - 1) ? "" : ",");
|
||||
break;
|
||||
case AREA_LV:
|
||||
_outf(f, "\"%s\", %u%s",
|
||||
seg->area[s].u.lv.lv->name,
|
||||
seg->area[s].u.lv.le,
|
||||
(s == seg->area_count - 1) ? "" : ",");
|
||||
}
|
||||
if (!list_empty(&seg->tags)) {
|
||||
if (!print_tags(&seg->tags, buffer, sizeof(buffer))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
outf(f, "tags = %s", buffer);
|
||||
}
|
||||
|
||||
_dec_indent(f);
|
||||
_outf(f, "]");
|
||||
break;
|
||||
if (seg->segtype->ops->text_export &&
|
||||
!seg->segtype->ops->text_export(seg, f)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_dec_indent(f);
|
||||
_outf(f, "}");
|
||||
outf(f, "}");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int out_areas(struct formatter *f, const struct lv_segment *seg,
|
||||
const char *type)
|
||||
{
|
||||
const char *name;
|
||||
unsigned int s;
|
||||
|
||||
f->nl(f);
|
||||
|
||||
outf(f, "%ss = [", type);
|
||||
_inc_indent(f);
|
||||
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
switch (seg->area[s].type) {
|
||||
case AREA_PV:
|
||||
if (!(name = _get_pv_name(f, seg->area[s].u.pv.pv))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
outf(f, "\"%s\", %u%s", name,
|
||||
seg->area[s].u.pv.pe,
|
||||
(s == seg->area_count - 1) ? "" : ",");
|
||||
break;
|
||||
case AREA_LV:
|
||||
outf(f, "\"%s\", %u%s",
|
||||
seg->area[s].u.lv.lv->name,
|
||||
seg->area[s].u.lv.le,
|
||||
(s == seg->area_count - 1) ? "" : ",");
|
||||
}
|
||||
}
|
||||
|
||||
_dec_indent(f);
|
||||
outf(f, "]");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _count_segments(struct logical_volume *lv)
|
||||
{
|
||||
int r = 0;
|
||||
@@ -463,7 +485,7 @@ static int _print_snapshot(struct formatter *f, struct snapshot *snap,
|
||||
|
||||
f->nl(f);
|
||||
|
||||
_outf(f, "snapshot%u {", count);
|
||||
outf(f, "snapshot%u {", count);
|
||||
_inc_indent(f);
|
||||
|
||||
if (!id_write_format(&snap->id, buffer, sizeof(buffer))) {
|
||||
@@ -471,32 +493,49 @@ static int _print_snapshot(struct formatter *f, struct snapshot *snap,
|
||||
return 0;
|
||||
}
|
||||
|
||||
_outf(f, "id = \"%s\"", buffer);
|
||||
if (!print_flags(LVM_READ | LVM_WRITE | VISIBLE_LV, LV_FLAGS,
|
||||
buffer, sizeof(buffer))) {
|
||||
outf(f, "id = \"%s\"", buffer);
|
||||
|
||||
seg.status = LVM_READ | LVM_WRITE | VISIBLE_LV;
|
||||
if (!print_flags(seg.status, LV_FLAGS, buffer, sizeof(buffer))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_outf(f, "status = %s", buffer);
|
||||
_outf(f, "segment_count = 1");
|
||||
outf(f, "status = %s", buffer);
|
||||
outf(f, "segment_count = 1");
|
||||
|
||||
f->nl(f);
|
||||
|
||||
seg.type = SEG_SNAPSHOT;
|
||||
if (!(seg.segtype = get_segtype_from_string(snap->origin->vg->cmd,
|
||||
"snapshot"))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
seg.le = 0;
|
||||
seg.len = snap->origin->le_count;
|
||||
seg.origin = snap->origin;
|
||||
seg.cow = snap->cow;
|
||||
seg.chunk_size = snap->chunk_size;
|
||||
|
||||
/* FIXME Dummy values */
|
||||
list_init(&seg.list);
|
||||
seg.lv = snap->cow;
|
||||
seg.stripe_size = 0;
|
||||
seg.area_count = 0;
|
||||
seg.area_len = 0;
|
||||
seg.extents_copied = 0;
|
||||
|
||||
/* Can't tag a snapshot independently of its origin */
|
||||
list_init(&seg.tags);
|
||||
|
||||
if (!_print_segment(f, snap->origin->vg, 1, &seg)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_dec_indent(f);
|
||||
_outf(f, "}");
|
||||
outf(f, "}");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -524,7 +563,7 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
|
||||
struct list *lvh;
|
||||
struct logical_volume *lv;
|
||||
struct lv_segment *seg;
|
||||
char buffer[256];
|
||||
char buffer[4096];
|
||||
int seg_count;
|
||||
|
||||
/*
|
||||
@@ -533,14 +572,14 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
|
||||
if (list_empty(&vg->lvs))
|
||||
return 1;
|
||||
|
||||
_outf(f, "logical_volumes {");
|
||||
outf(f, "logical_volumes {");
|
||||
_inc_indent(f);
|
||||
|
||||
list_iterate(lvh, &vg->lvs) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
|
||||
f->nl(f);
|
||||
_outf(f, "%s {", lv->name);
|
||||
outf(f, "%s {", lv->name);
|
||||
_inc_indent(f);
|
||||
|
||||
/* FIXME: Write full lvid */
|
||||
@@ -549,24 +588,33 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
_outf(f, "id = \"%s\"", buffer);
|
||||
outf(f, "id = \"%s\"", buffer);
|
||||
|
||||
if (!print_flags(lv->status, LV_FLAGS, buffer, sizeof(buffer))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
outf(f, "status = %s", buffer);
|
||||
|
||||
if (!list_empty(&lv->tags)) {
|
||||
if (!print_tags(&lv->tags, buffer, sizeof(buffer))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
outf(f, "tags = %s", buffer);
|
||||
}
|
||||
|
||||
if (lv->alloc != ALLOC_INHERIT)
|
||||
outf(f, "allocation_policy = \"%s\"",
|
||||
get_alloc_string(lv->alloc));
|
||||
|
||||
_outf(f, "status = %s", buffer);
|
||||
if (lv->alloc != ALLOC_DEFAULT)
|
||||
_outf(f, "allocation_policy = \"%s\"",
|
||||
get_alloc_string(lv->alloc));
|
||||
if (lv->read_ahead)
|
||||
_outf(f, "read_ahead = %u", lv->read_ahead);
|
||||
outf(f, "read_ahead = %u", lv->read_ahead);
|
||||
if (lv->major >= 0)
|
||||
_outf(f, "major = %d", lv->major);
|
||||
outf(f, "major = %d", lv->major);
|
||||
if (lv->minor >= 0)
|
||||
_outf(f, "minor = %d", lv->minor);
|
||||
_outf(f, "segment_count = %u", _count_segments(lv));
|
||||
outf(f, "minor = %d", lv->minor);
|
||||
outf(f, "segment_count = %u", _count_segments(lv));
|
||||
f->nl(f);
|
||||
|
||||
seg_count = 1;
|
||||
@@ -578,7 +626,7 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
|
||||
}
|
||||
|
||||
_dec_indent(f);
|
||||
_outf(f, "}");
|
||||
outf(f, "}");
|
||||
}
|
||||
|
||||
if (!_print_snapshots(f, vg)) {
|
||||
@@ -587,7 +635,7 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
|
||||
}
|
||||
|
||||
_dec_indent(f);
|
||||
_outf(f, "}");
|
||||
outf(f, "}");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -660,7 +708,7 @@ static int _text_vg_export(struct formatter *f,
|
||||
if (f->header && !_print_header(f, vg, desc))
|
||||
fail;
|
||||
|
||||
if (!_out(f, "%s {", vg->name))
|
||||
if (!out_text(f, "%s {", vg->name))
|
||||
fail;
|
||||
|
||||
_inc_indent(f);
|
||||
@@ -677,7 +725,7 @@ static int _text_vg_export(struct formatter *f,
|
||||
fail;
|
||||
|
||||
_dec_indent(f);
|
||||
if (!_out(f, "}"))
|
||||
if (!out_text(f, "}"))
|
||||
fail;
|
||||
|
||||
if (!f->header && !_print_header(f, vg, desc))
|
||||
@@ -757,4 +805,4 @@ int text_vg_export_raw(struct volume_group *vg, const char *desc, char *buf,
|
||||
return r;
|
||||
}
|
||||
|
||||
#undef _outf
|
||||
#undef outf
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -43,6 +52,8 @@ static struct flag _lv_flags[] = {
|
||||
{VISIBLE_LV, "VISIBLE"},
|
||||
{PVMOVE, "PVMOVE"},
|
||||
{LOCKED, "LOCKED"},
|
||||
{MIRRORED, NULL},
|
||||
{VIRTUAL, NULL},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
@@ -83,18 +94,21 @@ int print_flags(uint32_t status, int type, char *buffer, size_t size)
|
||||
|
||||
for (f = 0; flags[f].mask; f++) {
|
||||
if (status & flags[f].mask) {
|
||||
status &= ~flags[f].mask;
|
||||
|
||||
/* Internal-only flag? */
|
||||
if (!flags[f].description)
|
||||
continue;
|
||||
|
||||
if (!first) {
|
||||
if (!emit_to_buffer(&buffer, &size, ", "))
|
||||
return 0;
|
||||
|
||||
} else
|
||||
first = 0;
|
||||
|
||||
|
||||
if (!emit_to_buffer(&buffer, &size, "\"%s\"",
|
||||
flags[f].description))
|
||||
flags[f].description))
|
||||
return 0;
|
||||
|
||||
status &= ~flags[f].mask;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2002 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -21,6 +30,7 @@
|
||||
#include "xlate.h"
|
||||
#include "label.h"
|
||||
#include "memlock.h"
|
||||
#include "lvmcache.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/file.h>
|
||||
@@ -71,7 +81,7 @@ static int _lv_setup(struct format_instance *fid, struct logical_volume *lv)
|
||||
uint64_t max_size = UINT_MAX;
|
||||
|
||||
if (lv->size > max_size) {
|
||||
char *dummy = display_size(max_size / 2, SIZE_SHORT);
|
||||
char *dummy = display_size(max_size, SIZE_SHORT);
|
||||
log_error("logical volumes cannot be larger than %s", dummy);
|
||||
dbg_free(dummy);
|
||||
return 0;
|
||||
@@ -919,8 +929,7 @@ static int _mda_setup(const struct format_type *fmt,
|
||||
/* FIXME If creating new mdas, wipe them! */
|
||||
if (mda_size1) {
|
||||
if (!add_mda(fmt, fmt->cmd->mem, mdas, pv->dev, start1,
|
||||
mda_size1))
|
||||
return 0;
|
||||
mda_size1)) return 0;
|
||||
|
||||
if (!dev_zero((struct device *) pv->dev, start1,
|
||||
(size_t) (mda_size1 >
|
||||
@@ -967,8 +976,7 @@ static int _mda_setup(const struct format_type *fmt,
|
||||
|
||||
if (mda_size2) {
|
||||
if (!add_mda(fmt, fmt->cmd->mem, mdas, pv->dev, start2,
|
||||
mda_size2))
|
||||
return 0;
|
||||
mda_size2)) return 0;
|
||||
if (!dev_zero(pv->dev, start2,
|
||||
(size_t) (mda_size1 >
|
||||
wipe_size ? wipe_size : mda_size1))) {
|
||||
@@ -1057,8 +1065,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
|
||||
}
|
||||
}
|
||||
if (!add_da
|
||||
(fmt, NULL, &info->das, pv->pe_start << SECTOR_SHIFT,
|
||||
UINT64_C(0))) {
|
||||
(fmt, NULL, &info->das, pv->pe_start << SECTOR_SHIFT, UINT64_C(0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -1130,8 +1137,7 @@ static int _add_raw(struct list *raw_list, struct device_area *dev_area)
|
||||
rl = list_item(rlh, struct raw_list);
|
||||
/* FIXME Check size/overlap consistency too */
|
||||
if (rl->dev_area.dev == dev_area->dev &&
|
||||
rl->dev_area.start == dev_area->start)
|
||||
return 1;
|
||||
rl->dev_area.start == dev_area->start) return 1;
|
||||
}
|
||||
|
||||
if (!(rl = dbg_malloc(sizeof(struct raw_list)))) {
|
||||
@@ -1325,11 +1331,10 @@ static int _pv_setup(const struct format_type *fmt,
|
||||
list_item(mdash,
|
||||
struct metadata_area);
|
||||
if (mda2->ops !=
|
||||
&_metadata_text_raw_ops)
|
||||
continue;
|
||||
&_metadata_text_raw_ops) continue;
|
||||
mdac2 =
|
||||
(struct mda_context *) mda2->
|
||||
metadata_locn;
|
||||
(struct mda_context *)
|
||||
mda2->metadata_locn;
|
||||
if (!memcmp
|
||||
(&mdac2->area, &mdac->area,
|
||||
sizeof(mdac->area))) {
|
||||
@@ -1347,8 +1352,7 @@ static int _pv_setup(const struct format_type *fmt,
|
||||
}
|
||||
|
||||
if (!(mdac_new = pool_alloc(fmt->cmd->mem,
|
||||
sizeof(*mdac_new))))
|
||||
{
|
||||
sizeof(*mdac_new)))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -1477,8 +1481,7 @@ static struct format_instance *_create_text_instance(const struct format_type
|
||||
}
|
||||
|
||||
if (!(mdac_new = pool_alloc(fmt->cmd->mem,
|
||||
sizeof(*mdac_new))))
|
||||
{
|
||||
sizeof(*mdac_new)))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
@@ -1584,21 +1587,21 @@ static int _get_config_disk_area(struct cmd_context *cmd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!get_config_uint64(cn, "start_sector", '/', &dev_area.start)) {
|
||||
if (!get_config_uint64(cn, "start_sector", &dev_area.start)) {
|
||||
log_error("Missing start_sector in metadata disk_area section "
|
||||
"of config file");
|
||||
return 0;
|
||||
}
|
||||
dev_area.start <<= SECTOR_SHIFT;
|
||||
|
||||
if (!get_config_uint64(cn, "size", '/', &dev_area.size)) {
|
||||
if (!get_config_uint64(cn, "size", &dev_area.size)) {
|
||||
log_error("Missing size in metadata disk_area section "
|
||||
"of config file");
|
||||
return 0;
|
||||
}
|
||||
dev_area.size <<= SECTOR_SHIFT;
|
||||
|
||||
if (!get_config_str(cn, "id", '/', &id_str)) {
|
||||
if (!get_config_str(cn, "id", &id_str)) {
|
||||
log_error("Missing uuid in metadata disk_area section "
|
||||
"of config file");
|
||||
return 0;
|
||||
@@ -1640,7 +1643,7 @@ struct format_type *create_text_format(struct cmd_context *cmd)
|
||||
fmt->ops = &_text_handler;
|
||||
fmt->name = FMT_TEXT_NAME;
|
||||
fmt->alias = FMT_TEXT_ALIAS;
|
||||
fmt->features = FMT_SEGMENTS | FMT_MDAS;
|
||||
fmt->features = FMT_SEGMENTS | FMT_MDAS | FMT_TAGS | FMT_UNLIMITED_VOLS;
|
||||
|
||||
if (!(mda_lists = dbg_malloc(sizeof(struct mda_lists)))) {
|
||||
log_error("Failed to allocate dir_list");
|
||||
@@ -1663,7 +1666,7 @@ struct format_type *create_text_format(struct cmd_context *cmd)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((cn = find_config_node(cmd->cf->root, "metadata/dirs", '/'))) {
|
||||
if ((cn = find_config_node(cmd->cft->root, "metadata/dirs"))) {
|
||||
for (cv = cn->v; cv; cv = cv->next) {
|
||||
if (cv->type != CFG_STRING) {
|
||||
log_error("Invalid string in config file: "
|
||||
@@ -1679,7 +1682,7 @@ struct format_type *create_text_format(struct cmd_context *cmd)
|
||||
}
|
||||
}
|
||||
|
||||
if (!(cn = find_config_node(cmd->cf->root, "metadata/disk_areas", '/')))
|
||||
if (!(cn = find_config_node(cmd->cft->root, "metadata/disk_areas")))
|
||||
return fmt;
|
||||
|
||||
for (cn = cn->child; cn; cn = cn->sib) {
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_FORMAT_TEXT_H
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_TEXT_IMPORT_EXPORT_H
|
||||
@@ -46,6 +55,9 @@ struct text_vg_version_ops *text_vg_vsn1_init(void);
|
||||
int print_flags(uint32_t status, int type, char *buffer, size_t size);
|
||||
int read_flags(uint32_t *status, int type, struct config_value *cv);
|
||||
|
||||
int print_tags(struct list *tags, char *buffer, size_t size);
|
||||
int read_tags(struct pool *mem, struct list *tags, struct config_value *cv);
|
||||
|
||||
int text_vg_export_file(struct volume_group *vg, const char *desc, FILE *fp);
|
||||
int text_vg_export_raw(struct volume_group *vg, const char *desc, char *buf,
|
||||
uint32_t size);
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -26,7 +35,7 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
|
||||
time_t *when, char **desc)
|
||||
{
|
||||
struct volume_group *vg = NULL;
|
||||
struct config_tree *cf;
|
||||
struct config_tree *cft;
|
||||
struct text_vg_version_ops **vsn;
|
||||
|
||||
static int _initialised = 0;
|
||||
@@ -40,13 +49,13 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
|
||||
*desc = NULL;
|
||||
*when = 0;
|
||||
|
||||
if (!(cf = create_config_tree())) {
|
||||
if (!(cft = create_config_tree(file))) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((!dev && !read_config_file(cf, file)) ||
|
||||
(dev && !read_config_fd(cf, dev, offset, size,
|
||||
if ((!dev && !read_config_file(cft)) ||
|
||||
(dev && !read_config_fd(cft, dev, offset, size,
|
||||
offset2, size2, checksum_fn, checksum))) {
|
||||
log_error("Couldn't read volume group metadata.");
|
||||
goto out;
|
||||
@@ -56,20 +65,20 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
|
||||
* Find a set of version functions that can read this file
|
||||
*/
|
||||
for (vsn = &_text_vsn_list[0]; *vsn; vsn++) {
|
||||
if (!(*vsn)->check_version(cf))
|
||||
if (!(*vsn)->check_version(cft))
|
||||
continue;
|
||||
|
||||
if (!(vg = (*vsn)->read_vg(fid, cf))) {
|
||||
if (!(vg = (*vsn)->read_vg(fid, cft))) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
|
||||
(*vsn)->read_desc(fid->fmt->cmd->mem, cf, when, desc);
|
||||
(*vsn)->read_desc(fid->fmt->cmd->mem, cft, when, desc);
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
destroy_config_tree(cf);
|
||||
destroy_config_tree(cft);
|
||||
return vg;
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -13,6 +22,8 @@
|
||||
#include "toolcontext.h"
|
||||
#include "lvmcache.h"
|
||||
#include "lv_alloc.h"
|
||||
#include "segtypes.h"
|
||||
#include "text_import.h"
|
||||
|
||||
typedef int (*section_fn) (struct format_instance * fid, struct pool * mem,
|
||||
struct volume_group * vg, struct config_node * pvn,
|
||||
@@ -20,13 +31,13 @@ typedef int (*section_fn) (struct format_instance * fid, struct pool * mem,
|
||||
struct hash_table * pv_hash);
|
||||
|
||||
#define _read_int32(root, path, result) \
|
||||
get_config_uint32(root, path, '/', result)
|
||||
get_config_uint32(root, path, result)
|
||||
|
||||
#define _read_uint32(root, path, result) \
|
||||
get_config_uint32(root, path, '/', result)
|
||||
get_config_uint32(root, path, result)
|
||||
|
||||
#define _read_int64(root, path, result) \
|
||||
get_config_uint64(root, path, '/', result)
|
||||
get_config_uint64(root, path, result)
|
||||
|
||||
/*
|
||||
* Logs an attempt to read an invalid format file.
|
||||
@@ -40,7 +51,7 @@ static void _invalid_format(const char *str)
|
||||
* Checks that the config file contains vg metadata, and that it
|
||||
* we recognise the version number,
|
||||
*/
|
||||
static int _check_version(struct config_tree *cf)
|
||||
static int _check_version(struct config_tree *cft)
|
||||
{
|
||||
struct config_node *cn;
|
||||
struct config_value *cv;
|
||||
@@ -48,7 +59,7 @@ static int _check_version(struct config_tree *cf)
|
||||
/*
|
||||
* Check the contents field.
|
||||
*/
|
||||
if (!(cn = find_config_node(cf->root, CONTENTS_FIELD, '/'))) {
|
||||
if (!(cn = find_config_node(cft->root, CONTENTS_FIELD))) {
|
||||
_invalid_format("missing contents field");
|
||||
return 0;
|
||||
}
|
||||
@@ -62,7 +73,7 @@ static int _check_version(struct config_tree *cf)
|
||||
/*
|
||||
* Check the version number.
|
||||
*/
|
||||
if (!(cn = find_config_node(cf->root, FORMAT_VERSION_FIELD, '/'))) {
|
||||
if (!(cn = find_config_node(cft->root, FORMAT_VERSION_FIELD))) {
|
||||
_invalid_format("missing version number");
|
||||
return 0;
|
||||
}
|
||||
@@ -80,7 +91,7 @@ static int _read_id(struct id *id, struct config_node *cn, const char *path)
|
||||
{
|
||||
struct config_value *cv;
|
||||
|
||||
if (!(cn = find_config_node(cn, path, '/'))) {
|
||||
if (!(cn = find_config_node(cn, path))) {
|
||||
log_error("Couldn't find uuid.");
|
||||
return 0;
|
||||
}
|
||||
@@ -157,7 +168,7 @@ static int _read_pv(struct format_instance *fid, struct pool *mem,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(cn = find_config_node(pvn, "status", '/'))) {
|
||||
if (!(cn = find_config_node(pvn, "status"))) {
|
||||
log_error("Couldn't find status flags for physical volume.");
|
||||
return 0;
|
||||
}
|
||||
@@ -178,6 +189,16 @@ static int _read_pv(struct format_instance *fid, struct pool *mem,
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_init(&pv->tags);
|
||||
|
||||
/* Optional tags */
|
||||
if ((cn = find_config_node(pvn, "tags")) &&
|
||||
!(read_tags(mem, &pv->tags, cn->v))) {
|
||||
log_error("Couldn't read tags for physical volume %s in %s.",
|
||||
dev_name(pv->dev), vg->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* adjust the volume group. */
|
||||
vg->extent_count += pv->pe_count;
|
||||
vg->free_count += pv->pe_count;
|
||||
@@ -215,17 +236,13 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
|
||||
struct logical_volume *lv, struct config_node *sn,
|
||||
struct hash_table *pv_hash)
|
||||
{
|
||||
unsigned int s;
|
||||
uint32_t area_count = 0;
|
||||
uint32_t area_count = 0u;
|
||||
struct lv_segment *seg;
|
||||
struct config_node *cn;
|
||||
struct config_value *cv;
|
||||
const char *seg_name = sn->key;
|
||||
uint32_t start_extent, extent_count;
|
||||
uint32_t chunk_size, extents_moved = 0u, seg_status = 0u;
|
||||
const char *org_name, *cow_name;
|
||||
struct logical_volume *org, *cow, *lv1;
|
||||
segment_type_t segtype;
|
||||
struct segment_type *segtype;
|
||||
const char *segtype_str;
|
||||
|
||||
if (!(sn = sn->child)) {
|
||||
log_error("Empty segment section.");
|
||||
@@ -244,40 +261,26 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
segtype = SEG_STRIPED; /* Default */
|
||||
if ((cn = find_config_node(sn, "type", '/'))) {
|
||||
segtype_str = "striped";
|
||||
|
||||
if ((cn = find_config_node(sn, "type"))) {
|
||||
cv = cn->v;
|
||||
if (!cv || !cv->v.str) {
|
||||
log_error("Segment type must be a string.");
|
||||
return 0;
|
||||
}
|
||||
segtype = get_segtype_from_string(cv->v.str);
|
||||
segtype_str = cv->v.str;
|
||||
}
|
||||
|
||||
if (segtype == SEG_STRIPED) {
|
||||
if (!_read_int32(sn, "stripe_count", &area_count)) {
|
||||
log_error("Couldn't read 'stripe_count' for "
|
||||
"segment '%s'.", sn->key);
|
||||
return 0;
|
||||
}
|
||||
if (!(segtype = get_segtype_from_string(vg->cmd, segtype_str))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (segtype == SEG_MIRRORED) {
|
||||
if (!_read_int32(sn, "mirror_count", &area_count)) {
|
||||
log_error("Couldn't read 'mirror_count' for "
|
||||
"segment '%s'.", sn->key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (find_config_node(sn, "extents_moved", '/')) {
|
||||
if (_read_uint32(sn, "extents_moved", &extents_moved))
|
||||
seg_status |= PVMOVE;
|
||||
else {
|
||||
log_error("Couldn't read 'extents_moved' for "
|
||||
"segment '%s'.", sn->key);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (segtype->ops->text_import_area_count &&
|
||||
!segtype->ops->text_import_area_count(sn, &area_count)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(seg = alloc_lv_segment(mem, area_count))) {
|
||||
@@ -289,149 +292,107 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
|
||||
seg->le = start_extent;
|
||||
seg->len = extent_count;
|
||||
seg->area_len = extent_count;
|
||||
seg->type = segtype;
|
||||
seg->status = seg_status;
|
||||
seg->extents_moved = extents_moved;
|
||||
seg->status = 0u;
|
||||
seg->segtype = segtype;
|
||||
seg->extents_copied = 0u;
|
||||
|
||||
switch (segtype) {
|
||||
case SEG_SNAPSHOT:
|
||||
lv->status |= SNAPSHOT;
|
||||
|
||||
if (!_read_uint32(sn, "chunk_size", &chunk_size)) {
|
||||
log_error("Couldn't read chunk size for snapshot.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_suppress(1);
|
||||
|
||||
if (!(cow_name = find_config_str(sn, "cow_store", '/', NULL))) {
|
||||
log_suppress(0);
|
||||
log_error("Snapshot cow storage not specified.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(org_name = find_config_str(sn, "origin", '/', NULL))) {
|
||||
log_suppress(0);
|
||||
log_error("Snapshot origin not specified.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_suppress(0);
|
||||
|
||||
if (!(cow = find_lv(vg, cow_name))) {
|
||||
log_error("Unknown logical volume specified for "
|
||||
"snapshot cow store.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(org = find_lv(vg, org_name))) {
|
||||
log_error("Unknown logical volume specified for "
|
||||
"snapshot origin.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!vg_add_snapshot(org, cow, 1, &lv->lvid.id[1], chunk_size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case SEG_STRIPED:
|
||||
if ((area_count != 1) &&
|
||||
!_read_int32(sn, "stripe_size", &seg->stripe_size)) {
|
||||
log_error("Couldn't read stripe_size for segment '%s'.",
|
||||
sn->key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(cn = find_config_node(sn, "stripes", '/'))) {
|
||||
log_error("Couldn't find stripes array for segment "
|
||||
"'%s'.", sn->key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
seg->area_len /= area_count;
|
||||
|
||||
case SEG_MIRRORED:
|
||||
seg->area_count = area_count;
|
||||
|
||||
if (!seg->area_count) {
|
||||
log_error("Zero areas not allowed for segment '%s'",
|
||||
sn->key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((seg->type == SEG_MIRRORED) &&
|
||||
!(cn = find_config_node(sn, "mirrors", '/'))) {
|
||||
log_error("Couldn't find mirrors array for segment "
|
||||
"'%s'.", sn->key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (cv = cn->v, s = 0; cv && s < seg->area_count;
|
||||
s++, cv = cv->next) {
|
||||
|
||||
/* first we read the pv */
|
||||
const char *bad = "Badly formed areas array for "
|
||||
"segment '%s'.";
|
||||
struct physical_volume *pv;
|
||||
|
||||
if (cv->type != CFG_STRING) {
|
||||
log_error(bad, sn->key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!cv->next) {
|
||||
log_error(bad, sn->key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cv->next->type != CFG_INT) {
|
||||
log_error(bad, sn->key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME Cope if LV not yet read in */
|
||||
if ((pv = hash_lookup(pv_hash, cv->v.str))) {
|
||||
seg->area[s].type = AREA_PV;
|
||||
seg->area[s].u.pv.pv = pv;
|
||||
seg->area[s].u.pv.pe = cv->next->v.i;
|
||||
/*
|
||||
* Adjust extent counts in the pv and vg.
|
||||
*/
|
||||
pv->pe_alloc_count += seg->area_len;
|
||||
vg->free_count -= seg->area_len;
|
||||
|
||||
} else if ((lv1 = find_lv(vg, cv->v.str))) {
|
||||
seg->area[s].type = AREA_LV;
|
||||
seg->area[s].u.lv.lv = lv1;
|
||||
seg->area[s].u.lv.le = cv->next->v.i;
|
||||
} else {
|
||||
log_error("Couldn't find volume '%s' "
|
||||
"for segment '%s'.",
|
||||
cv->v.str ? cv->v.str : "NULL",
|
||||
seg_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cv = cv->next;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check we read the correct number of stripes.
|
||||
*/
|
||||
if (cv || (s < seg->area_count)) {
|
||||
log_error("Incorrect number of areas in area array "
|
||||
"for segment '%s'.", seg_name);
|
||||
return 0;
|
||||
}
|
||||
if (seg->segtype->ops->text_import &&
|
||||
!seg->segtype->ops->text_import(seg, sn, pv_hash)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Optional tags */
|
||||
if ((cn = find_config_node(sn, "tags")) &&
|
||||
!(read_tags(mem, &seg->tags, cn->v))) {
|
||||
log_error("Couldn't read tags for a segment of %s/%s.",
|
||||
vg->name, lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert into correct part of segment list.
|
||||
*/
|
||||
_insert_segment(lv, seg);
|
||||
|
||||
if (seg->segtype->flags & SEG_AREAS_MIRRORED)
|
||||
lv->status |= MIRRORED;
|
||||
|
||||
if (seg->segtype->flags & SEG_VIRTUAL)
|
||||
lv->status |= VIRTUAL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int text_import_areas(struct lv_segment *seg, const struct config_node *sn,
|
||||
const struct config_node *cn, struct hash_table *pv_hash)
|
||||
{
|
||||
unsigned int s;
|
||||
struct config_value *cv;
|
||||
struct logical_volume *lv1;
|
||||
const char *seg_name = sn->key;
|
||||
|
||||
if (!seg->area_count) {
|
||||
log_error("Zero areas not allowed for segment '%s'", sn->key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (cv = cn->v, s = 0; cv && s < seg->area_count; s++, cv = cv->next) {
|
||||
|
||||
/* first we read the pv */
|
||||
const char *bad = "Badly formed areas array for "
|
||||
"segment '%s'.";
|
||||
struct physical_volume *pv;
|
||||
|
||||
if (cv->type != CFG_STRING) {
|
||||
log_error(bad, sn->key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!cv->next) {
|
||||
log_error(bad, sn->key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cv->next->type != CFG_INT) {
|
||||
log_error(bad, sn->key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME Cope if LV not yet read in */
|
||||
if ((pv = hash_lookup(pv_hash, cv->v.str))) {
|
||||
seg->area[s].type = AREA_PV;
|
||||
seg->area[s].u.pv.pv = pv;
|
||||
seg->area[s].u.pv.pe = cv->next->v.i;
|
||||
/*
|
||||
* Adjust extent counts in the pv and vg.
|
||||
*/
|
||||
pv->pe_alloc_count += seg->area_len;
|
||||
seg->lv->vg->free_count -= seg->area_len;
|
||||
|
||||
} else if ((lv1 = find_lv(seg->lv->vg, cv->v.str))) {
|
||||
seg->area[s].type = AREA_LV;
|
||||
seg->area[s].u.lv.lv = lv1;
|
||||
seg->area[s].u.lv.le = cv->next->v.i;
|
||||
} else {
|
||||
log_error("Couldn't find volume '%s' "
|
||||
"for segment '%s'.",
|
||||
cv->v.str ? cv->v.str : "NULL", seg_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cv = cv->next;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check we read the correct number of stripes.
|
||||
*/
|
||||
if (cv || (s < seg->area_count)) {
|
||||
log_error("Incorrect number of areas in area array "
|
||||
"for segment '%s'.", seg_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -518,7 +479,7 @@ static int _read_lvnames(struct format_instance *fid, struct pool *mem,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(cn = find_config_node(lvn, "status", '/'))) {
|
||||
if (!(cn = find_config_node(lvn, "status"))) {
|
||||
log_error("Couldn't find status flags for logical volume.");
|
||||
return 0;
|
||||
}
|
||||
@@ -528,8 +489,8 @@ static int _read_lvnames(struct format_instance *fid, struct pool *mem,
|
||||
return 0;
|
||||
}
|
||||
|
||||
lv->alloc = ALLOC_DEFAULT;
|
||||
if ((cn = find_config_node(lvn, "allocation_policy", '/'))) {
|
||||
lv->alloc = ALLOC_INHERIT;
|
||||
if ((cn = find_config_node(lvn, "allocation_policy"))) {
|
||||
struct config_value *cv = cn->v;
|
||||
if (!cv || !cv->v.str) {
|
||||
log_error("allocation_policy must be a string.");
|
||||
@@ -537,6 +498,10 @@ static int _read_lvnames(struct format_instance *fid, struct pool *mem,
|
||||
}
|
||||
|
||||
lv->alloc = get_alloc_from_string(cv->v.str);
|
||||
if (lv->alloc == ALLOC_INVALID) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* read_ahead defaults to 0 */
|
||||
@@ -544,6 +509,15 @@ static int _read_lvnames(struct format_instance *fid, struct pool *mem,
|
||||
lv->read_ahead = 0;
|
||||
|
||||
list_init(&lv->segments);
|
||||
list_init(&lv->tags);
|
||||
|
||||
/* Optional tags */
|
||||
if ((cn = find_config_node(lvn, "tags")) &&
|
||||
!(read_tags(mem, &lv->tags, cn->v))) {
|
||||
log_error("Couldn't read tags for logical volume %s/%s.",
|
||||
vg->name, lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lv->vg = vg;
|
||||
vg->lv_count++;
|
||||
@@ -618,7 +592,7 @@ static int _read_sections(struct format_instance *fid,
|
||||
{
|
||||
struct config_node *n;
|
||||
|
||||
if (!(n = find_config_node(vgn, section, '/'))) {
|
||||
if (!(n = find_config_node(vgn, section))) {
|
||||
if (!optional) {
|
||||
log_error("Couldn't find section '%s'.", section);
|
||||
return 0;
|
||||
@@ -638,7 +612,7 @@ static int _read_sections(struct format_instance *fid,
|
||||
}
|
||||
|
||||
static struct volume_group *_read_vg(struct format_instance *fid,
|
||||
struct config_tree *cf)
|
||||
struct config_tree *cft)
|
||||
{
|
||||
struct config_node *vgn, *cn;
|
||||
struct volume_group *vg;
|
||||
@@ -646,7 +620,7 @@ static struct volume_group *_read_vg(struct format_instance *fid,
|
||||
struct pool *mem = fid->fmt->cmd->mem;
|
||||
|
||||
/* skip any top-level values */
|
||||
for (vgn = cf->root; (vgn && vgn->v); vgn = vgn->sib) ;
|
||||
for (vgn = cft->root; (vgn && vgn->v); vgn = vgn->sib) ;
|
||||
|
||||
if (!vgn) {
|
||||
log_error("Couldn't find volume group in file.");
|
||||
@@ -675,7 +649,7 @@ static struct volume_group *_read_vg(struct format_instance *fid,
|
||||
|
||||
vgn = vgn->child;
|
||||
|
||||
if ((cn = find_config_node(vgn, "system_id", '/')) && cn->v) {
|
||||
if ((cn = find_config_node(vgn, "system_id")) && cn->v) {
|
||||
if (!cn->v->v.str) {
|
||||
log_error("system_id must be a string");
|
||||
goto bad;
|
||||
@@ -694,7 +668,7 @@ static struct volume_group *_read_vg(struct format_instance *fid,
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!(cn = find_config_node(vgn, "status", '/'))) {
|
||||
if (!(cn = find_config_node(vgn, "status"))) {
|
||||
log_error("Couldn't find status flags for volume group %s.",
|
||||
vg->name);
|
||||
goto bad;
|
||||
@@ -729,6 +703,21 @@ static struct volume_group *_read_vg(struct format_instance *fid,
|
||||
goto bad;
|
||||
}
|
||||
|
||||
vg->alloc = ALLOC_NORMAL;
|
||||
if ((cn = find_config_node(vgn, "allocation_policy"))) {
|
||||
struct config_value *cv = cn->v;
|
||||
if (!cv || !cv->v.str) {
|
||||
log_error("allocation_policy must be a string.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
vg->alloc = get_alloc_from_string(cv->v.str);
|
||||
if (vg->alloc == ALLOC_INVALID) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The pv hash memoises the pv section names -> pv
|
||||
* structures.
|
||||
@@ -748,6 +737,14 @@ static struct volume_group *_read_vg(struct format_instance *fid,
|
||||
|
||||
list_init(&vg->lvs);
|
||||
list_init(&vg->snapshots);
|
||||
list_init(&vg->tags);
|
||||
|
||||
/* Optional tags */
|
||||
if ((cn = find_config_node(vgn, "tags")) &&
|
||||
!(read_tags(mem, &vg->tags, cn->v))) {
|
||||
log_error("Couldn't read tags for volume group %s.", vg->name);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!_read_sections(fid, "logical_volumes", _read_lvnames, mem, vg,
|
||||
vgn, pv_hash, 1)) {
|
||||
@@ -784,17 +781,17 @@ static struct volume_group *_read_vg(struct format_instance *fid,
|
||||
}
|
||||
|
||||
static void _read_desc(struct pool *mem,
|
||||
struct config_tree *cf, time_t *when, char **desc)
|
||||
struct config_tree *cft, time_t *when, char **desc)
|
||||
{
|
||||
const char *d;
|
||||
unsigned int u = 0u;
|
||||
|
||||
log_suppress(1);
|
||||
d = find_config_str(cf->root, "description", '/', "");
|
||||
d = find_config_str(cft->root, "description", "");
|
||||
log_suppress(0);
|
||||
*desc = pool_strdup(mem, d);
|
||||
|
||||
get_config_uint32(cf->root, "creation_time", '/', &u);
|
||||
get_config_uint32(cft->root, "creation_time", &u);
|
||||
*when = u;
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_TEXT_LAYOUT_H
|
||||
|
76
lib/format_text/tags.c
Normal file
76
lib/format_text/tags.c
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include "metadata.h"
|
||||
#include "import-export.h"
|
||||
#include "pool.h"
|
||||
#include "str_list.h"
|
||||
#include "lvm-string.h"
|
||||
|
||||
int print_tags(struct list *tags, char *buffer, size_t size)
|
||||
{
|
||||
struct str_list *sl;
|
||||
int first = 1;
|
||||
|
||||
if (!emit_to_buffer(&buffer, &size, "[")) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_iterate_items(sl, tags) {
|
||||
if (!first) {
|
||||
if (!emit_to_buffer(&buffer, &size, ", ")) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
first = 0;
|
||||
|
||||
if (!emit_to_buffer(&buffer, &size, "\"%s\"", sl->str)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!emit_to_buffer(&buffer, &size, "]")) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int read_tags(struct pool *mem, struct list *tags, struct config_value *cv)
|
||||
{
|
||||
if (cv->type == CFG_EMPTY_ARRAY)
|
||||
return 1;
|
||||
|
||||
while (cv) {
|
||||
if (cv->type != CFG_STRING) {
|
||||
log_error("Found a tag that is not a string");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!str_list_add(mem, tags, pool_strdup(mem, cv->v.str))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
cv = cv->next;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
36
lib/format_text/text_export.h
Normal file
36
lib/format_text/text_export.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_TEXT_EXPORT_H
|
||||
#define _LVM_TEXT_EXPORT_H
|
||||
|
||||
#define outf(args...) do {if (!out_text(args)) {stack; return 0;}} while (0)
|
||||
|
||||
struct formatter;
|
||||
struct lv_segment;
|
||||
|
||||
int out_size(struct formatter *f, uint64_t size, const char *fmt, ...)
|
||||
__attribute__ ((format(printf, 3, 4)));
|
||||
|
||||
int out_hint(struct formatter *f, const char *fmt, ...)
|
||||
__attribute__ ((format(printf, 2, 3)));
|
||||
|
||||
int out_text(struct formatter *f, const char *fmt, ...)
|
||||
__attribute__ ((format(printf, 2, 3)));
|
||||
|
||||
int out_areas(struct formatter *f, const struct lv_segment *seg,
|
||||
const char *type);
|
||||
|
||||
#endif
|
25
lib/format_text/text_import.h
Normal file
25
lib/format_text/text_import.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_TEXT_IMPORT_H
|
||||
#define _LVM_TEXT_IMPORT_H
|
||||
|
||||
struct lv_segment;
|
||||
struct config_node;
|
||||
|
||||
int text_import_areas(struct lv_segment *seg, const struct config_node *sn,
|
||||
const struct config_node *cn, struct hash_table *pv_hash);
|
||||
|
||||
#endif
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -9,6 +18,7 @@
|
||||
#include "layout.h"
|
||||
#include "label.h"
|
||||
#include "xlate.h"
|
||||
#include "lvmcache.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Sistina Software
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -10,6 +19,7 @@
|
||||
#include "crc.h"
|
||||
#include "xlate.h"
|
||||
#include "lvmcache.h"
|
||||
#include "metadata.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
@@ -69,6 +79,8 @@ void label_exit(void)
|
||||
li->l->ops->destroy(li->l);
|
||||
_free_li(li);
|
||||
}
|
||||
|
||||
list_init(&_labellers);
|
||||
}
|
||||
|
||||
int label_register_handler(const char *name, struct labeller *handler)
|
||||
|
@@ -1,13 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_LABEL_H
|
||||
#define _LVM_LABEL_H
|
||||
|
||||
#include "lvmcache.h"
|
||||
#include "uuid.h"
|
||||
#include "device.h"
|
||||
|
||||
@@ -16,6 +24,8 @@
|
||||
#define LABEL_SCAN_SECTORS 4L
|
||||
#define LABEL_SCAN_SIZE (LABEL_SCAN_SECTORS << SECTOR_SHIFT)
|
||||
|
||||
struct labeller;
|
||||
|
||||
/* On disk - 32 bytes */
|
||||
struct label_header {
|
||||
uint8_t id[8]; /* LABELONE */
|
||||
|
@@ -1,8 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -11,10 +19,12 @@
|
||||
#include "sharedlib.h"
|
||||
|
||||
static void *_locking_lib = NULL;
|
||||
static void (*_reset_fn) (void) = NULL;
|
||||
static void (*_end_fn) (void) = NULL;
|
||||
static int (*_lock_fn) (struct cmd_context * cmd, const char *resource,
|
||||
int flags) = NULL;
|
||||
static int (*_init_fn) (int type, struct config_tree * cf) = NULL;
|
||||
static int (*_init_fn) (int type, struct config_tree * cft,
|
||||
uint32_t *flags) = NULL;
|
||||
|
||||
static int _lock_resource(struct cmd_context *cmd, const char *resource,
|
||||
int flags)
|
||||
@@ -36,9 +46,16 @@ static void _fin_external_locking(void)
|
||||
_init_fn = NULL;
|
||||
_end_fn = NULL;
|
||||
_lock_fn = NULL;
|
||||
_reset_fn = NULL;
|
||||
}
|
||||
|
||||
int init_external_locking(struct locking_type *locking, struct config_tree *cf)
|
||||
static void _reset_external_locking(void)
|
||||
{
|
||||
if (_reset_fn)
|
||||
_reset_fn();
|
||||
}
|
||||
|
||||
int init_external_locking(struct locking_type *locking, struct config_tree *cft)
|
||||
{
|
||||
const char *libname;
|
||||
|
||||
@@ -49,19 +66,22 @@ int init_external_locking(struct locking_type *locking, struct config_tree *cf)
|
||||
|
||||
locking->lock_resource = _lock_resource;
|
||||
locking->fin_locking = _fin_external_locking;
|
||||
locking->reset_locking = _reset_external_locking;
|
||||
locking->flags = 0;
|
||||
|
||||
libname = find_config_str(cf->root, "global/locking_library", '/',
|
||||
libname = find_config_str(cft->root, "global/locking_library",
|
||||
DEFAULT_LOCKING_LIB);
|
||||
|
||||
if (!(_locking_lib = load_shared_library(cf, libname, "locking"))) {
|
||||
if (!(_locking_lib = load_shared_library(cft, libname, "locking"))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the functions we need */
|
||||
if (!(_init_fn = dlsym(_locking_lib, "init_locking")) ||
|
||||
if (!(_init_fn = dlsym(_locking_lib, "locking_init")) ||
|
||||
!(_lock_fn = dlsym(_locking_lib, "lock_resource")) ||
|
||||
!(_end_fn = dlsym(_locking_lib, "end_locking"))) {
|
||||
!(_reset_fn = dlsym(_locking_lib, "reset_locking")) ||
|
||||
!(_end_fn = dlsym(_locking_lib, "locking_end"))) {
|
||||
log_error("Shared library %s does not contain locking "
|
||||
"functions", libname);
|
||||
dlclose(_locking_lib);
|
||||
@@ -70,5 +90,5 @@ int init_external_locking(struct locking_type *locking, struct config_tree *cf)
|
||||
}
|
||||
|
||||
log_verbose("Loaded external locking library %s", libname);
|
||||
return _init_fn(2, cf);
|
||||
return _init_fn(2, cft, &locking->flags);
|
||||
}
|
||||
|
@@ -1,8 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -224,9 +232,14 @@ static int _file_lock_resource(struct cmd_context *cmd, const char *resource,
|
||||
if (!lv_resume_if_active(cmd, resource))
|
||||
return 0;
|
||||
break;
|
||||
case LCK_NULL:
|
||||
log_debug("Locking LV %s (NL)", resource);
|
||||
if (!lv_deactivate(cmd, resource))
|
||||
return 0;
|
||||
break;
|
||||
case LCK_READ:
|
||||
log_debug("Locking LV %s (R)", resource);
|
||||
if (!lv_activate(cmd, resource))
|
||||
if (!lv_activate_with_filter(cmd, resource))
|
||||
return 0;
|
||||
break;
|
||||
case LCK_WRITE:
|
||||
@@ -236,7 +249,7 @@ static int _file_lock_resource(struct cmd_context *cmd, const char *resource,
|
||||
break;
|
||||
case LCK_EXCL:
|
||||
log_debug("Locking LV %s (EX)", resource);
|
||||
if (!lv_deactivate(cmd, resource))
|
||||
if (!lv_activate_with_filter(cmd, resource))
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
@@ -252,15 +265,16 @@ static int _file_lock_resource(struct cmd_context *cmd, const char *resource,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int init_file_locking(struct locking_type *locking, struct config_tree *cf)
|
||||
int init_file_locking(struct locking_type *locking, struct config_tree *cft)
|
||||
{
|
||||
locking->lock_resource = _file_lock_resource;
|
||||
locking->reset_locking = _reset_file_locking;
|
||||
locking->fin_locking = _fin_file_locking;
|
||||
locking->flags = 0;
|
||||
|
||||
/* Get lockfile directory from config file */
|
||||
strncpy(_lock_dir, find_config_str(cf->root, "global/locking_dir",
|
||||
'/', DEFAULT_LOCK_DIR),
|
||||
strncpy(_lock_dir, find_config_str(cft->root, "global/locking_dir",
|
||||
DEFAULT_LOCK_DIR),
|
||||
sizeof(_lock_dir));
|
||||
|
||||
if (!create_dir(_lock_dir))
|
||||
|
@@ -1,8 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -11,6 +19,7 @@
|
||||
#include "lvm-string.h"
|
||||
#include "activate.h"
|
||||
#include "toolcontext.h"
|
||||
#include "memlock.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -62,6 +71,24 @@ static void _unblock_signals(void)
|
||||
return;
|
||||
}
|
||||
|
||||
static void _lock_memory(int flags)
|
||||
{
|
||||
if (!(_locking.flags & LCK_PRE_MEMLOCK))
|
||||
return;
|
||||
|
||||
if ((flags & (LCK_SCOPE_MASK | LCK_TYPE_MASK)) == LCK_LV_SUSPEND)
|
||||
memlock_inc();
|
||||
}
|
||||
|
||||
static void _unlock_memory(int flags)
|
||||
{
|
||||
if (!(_locking.flags & LCK_PRE_MEMLOCK))
|
||||
return;
|
||||
|
||||
if ((flags & (LCK_SCOPE_MASK | LCK_TYPE_MASK)) == LCK_LV_RESUME)
|
||||
memlock_dec();
|
||||
}
|
||||
|
||||
void reset_locking(void)
|
||||
{
|
||||
int was_locked = _vg_lock_count;
|
||||
@@ -95,24 +122,24 @@ static inline void _update_vg_lock_count(int flags)
|
||||
/*
|
||||
* Select a locking type
|
||||
*/
|
||||
int init_locking(int type, struct config_tree *cf)
|
||||
int init_locking(int type, struct config_tree *cft)
|
||||
{
|
||||
switch (type) {
|
||||
case 0:
|
||||
init_no_locking(&_locking, cf);
|
||||
init_no_locking(&_locking, cft);
|
||||
log_print("WARNING: Locking disabled. Be careful! "
|
||||
"This could corrupt your metadata.");
|
||||
return 1;
|
||||
|
||||
case 1:
|
||||
if (!init_file_locking(&_locking, cf))
|
||||
if (!init_file_locking(&_locking, cft))
|
||||
break;
|
||||
log_very_verbose("File-based locking enabled.");
|
||||
return 1;
|
||||
|
||||
#ifdef HAVE_LIBDL
|
||||
case 2:
|
||||
if (!init_external_locking(&_locking, cf))
|
||||
if (!init_external_locking(&_locking, cft))
|
||||
break;
|
||||
log_very_verbose("External locking enabled.");
|
||||
return 1;
|
||||
@@ -129,7 +156,7 @@ int init_locking(int type, struct config_tree *cf)
|
||||
/* FIXME Ensure only read ops are permitted */
|
||||
log_verbose("Locking disabled - only read operations permitted.");
|
||||
|
||||
init_no_locking(&_locking, cf);
|
||||
init_no_locking(&_locking, cft);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -176,13 +203,16 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname)
|
||||
static int _lock_vol(struct cmd_context *cmd, const char *resource, int flags)
|
||||
{
|
||||
_block_signals(flags);
|
||||
_lock_memory(flags);
|
||||
|
||||
if (!(_locking.lock_resource(cmd, resource, flags))) {
|
||||
_unlock_memory(flags);
|
||||
_unblock_signals();
|
||||
return 0;
|
||||
}
|
||||
|
||||
_update_vg_lock_count(flags);
|
||||
_unlock_memory(flags);
|
||||
_unblock_signals();
|
||||
|
||||
return 1;
|
||||
@@ -221,6 +251,64 @@ int lock_vol(struct cmd_context *cmd, const char *vol, int flags)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Unlock list of LVs */
|
||||
int resume_lvs(struct cmd_context *cmd, struct list *lvs)
|
||||
{
|
||||
struct list *lvh;
|
||||
struct logical_volume *lv;
|
||||
|
||||
list_iterate(lvh, lvs) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
resume_lv(cmd, lv->lvid.s);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Lock a list of LVs */
|
||||
int suspend_lvs(struct cmd_context *cmd, struct list *lvs)
|
||||
{
|
||||
struct list *lvh;
|
||||
struct logical_volume *lv;
|
||||
|
||||
list_iterate(lvh, lvs) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
if (!suspend_lv(cmd, lv->lvid.s)) {
|
||||
log_error("Failed to suspend %s", lv->name);
|
||||
list_uniterate(lvh, lvs, lvh) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
resume_lv(cmd, lv->lvid.s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Lock a list of LVs */
|
||||
int activate_lvs_excl(struct cmd_context *cmd, struct list *lvs)
|
||||
{
|
||||
struct list *lvh;
|
||||
struct logical_volume *lv;
|
||||
|
||||
list_iterate(lvh, lvs) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
if (!activate_lv_excl(cmd, lv->lvid.s)) {
|
||||
log_error("Failed to activate %s", lv->name);
|
||||
list_uniterate(lvh, lvs, lvh) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
activate_lv(cmd, lv->lvid.s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int vg_write_lock_held(void)
|
||||
{
|
||||
return _vg_write_lock_held;
|
||||
|
@@ -1,11 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "metadata.h"
|
||||
#include "uuid.h"
|
||||
#include "config.h"
|
||||
|
||||
@@ -64,10 +71,23 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname);
|
||||
#define LCK_VG_WRITE (LCK_VG | LCK_WRITE | LCK_HOLD)
|
||||
#define LCK_VG_UNLOCK (LCK_VG | LCK_UNLOCK)
|
||||
|
||||
#define LCK_LV_DEACTIVATE (LCK_LV | LCK_EXCL)
|
||||
#define LCK_LV_SUSPEND (LCK_LV | LCK_WRITE)
|
||||
#define LCK_LV_ACTIVATE (LCK_LV | LCK_READ)
|
||||
#define LCK_LV_UNLOCK (LCK_LV | LCK_UNLOCK)
|
||||
#define LCK_LV_EXCLUSIVE (LCK_LV | LCK_EXCL | LCK_NONBLOCK)
|
||||
#define LCK_LV_SUSPEND (LCK_LV | LCK_WRITE | LCK_NONBLOCK)
|
||||
#define LCK_LV_RESUME (LCK_LV | LCK_UNLOCK | LCK_NONBLOCK)
|
||||
#define LCK_LV_ACTIVATE (LCK_LV | LCK_READ | LCK_NONBLOCK)
|
||||
#define LCK_LV_DEACTIVATE (LCK_LV | LCK_NULL | LCK_NONBLOCK)
|
||||
|
||||
#define unlock_lv(cmd, vol) lock_vol(cmd, vol, LCK_LV_UNLOCK)
|
||||
#define unlock_vg(cmd, vol) lock_vol(cmd, vol, LCK_VG_UNLOCK)
|
||||
|
||||
#define resume_lv(cmd, vol) lock_vol(cmd, vol, LCK_LV_RESUME)
|
||||
#define suspend_lv(cmd, vol) lock_vol(cmd, vol, LCK_LV_SUSPEND | LCK_HOLD)
|
||||
#define deactivate_lv(cmd, vol) lock_vol(cmd, vol, LCK_LV_DEACTIVATE)
|
||||
#define activate_lv(cmd, vol) lock_vol(cmd, vol, LCK_LV_ACTIVATE | LCK_HOLD)
|
||||
#define activate_lv_excl(cmd, vol) \
|
||||
lock_vol(cmd, vol, LCK_LV_EXCLUSIVE | LCK_HOLD)
|
||||
|
||||
/* Process list of LVs */
|
||||
int suspend_lvs(struct cmd_context *cmd, struct list *lvs);
|
||||
int resume_lvs(struct cmd_context *cmd, struct list *lvs);
|
||||
int activate_lvs_excl(struct cmd_context *cmd, struct list *lvs);
|
||||
|
||||
|
@@ -1,8 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "metadata.h"
|
||||
@@ -14,7 +22,10 @@ typedef int (*lock_resource_fn) (struct cmd_context * cmd, const char *resource,
|
||||
typedef void (*fin_lock_fn) (void);
|
||||
typedef void (*reset_lock_fn) (void);
|
||||
|
||||
#define LCK_PRE_MEMLOCK 0x00000001 /* Is memlock() needed before calls? */
|
||||
|
||||
struct locking_type {
|
||||
uint32_t flags;
|
||||
lock_resource_fn lock_resource;
|
||||
|
||||
reset_lock_fn reset_locking;
|
||||
|
@@ -1,8 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -45,14 +53,16 @@ static int _no_lock_resource(struct cmd_context *cmd, const char *resource,
|
||||
break;
|
||||
case LCK_LV:
|
||||
switch (flags & LCK_TYPE_MASK) {
|
||||
case LCK_NULL:
|
||||
return lv_deactivate(cmd, resource);
|
||||
case LCK_UNLOCK:
|
||||
return lv_resume_if_active(cmd, resource);
|
||||
case LCK_READ:
|
||||
return lv_activate(cmd, resource);
|
||||
return lv_activate_with_filter(cmd, resource);
|
||||
case LCK_WRITE:
|
||||
return lv_suspend_if_active(cmd, resource);
|
||||
case LCK_EXCL:
|
||||
return lv_deactivate(cmd, resource);
|
||||
return lv_activate_with_filter(cmd, resource);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -66,11 +76,12 @@ static int _no_lock_resource(struct cmd_context *cmd, const char *resource,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int init_no_locking(struct locking_type *locking, struct config_tree *cf)
|
||||
int init_no_locking(struct locking_type *locking, struct config_tree *cft)
|
||||
{
|
||||
locking->lock_resource = _no_lock_resource;
|
||||
locking->reset_locking = _no_reset_locking;
|
||||
locking->fin_locking = _no_fin_locking;
|
||||
locking->flags = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user