1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-09-30 17:44:21 +03:00

Compare commits

...

89 Commits

Author SHA1 Message Date
Alasdair Kergon
4049c1e480 Backwards compatibility fix for version1 suspend/resume. 2003-07-05 23:20:43 +00:00
Alasdair Kergon
8449314da2 Another sync point - numerous fixes & clean ups. 2003-07-04 22:34:56 +00:00
Alasdair Kergon
63ad057028 Synchronise repository / 2.4.21 support 2003-07-04 19:38:49 +00:00
Alasdair Kergon
e720464330 Support for v4 interface 2003-07-01 21:20:58 +00:00
Alasdair Kergon
24036afef9 move functions 2003-05-06 12:22:24 +00:00
Alasdair Kergon
c78fa1a1bc remove global pvmove lock & poll for completion 2003-05-06 12:20:11 +00:00
Alasdair Kergon
faa8b9022c Check for locked LVs/pvmoves. 2003-05-06 12:14:36 +00:00
Alasdair Kergon
729bafef7a unsigned 2003-05-06 12:13:19 +00:00
Alasdair Kergon
590b028632 Prevent renaming active VGs for now. 2003-05-06 12:11:46 +00:00
Alasdair Kergon
8150d00f36 Don't process locked LVs 2003-05-06 12:10:18 +00:00
Alasdair Kergon
060065926f Store argv 2003-05-06 12:09:28 +00:00
Alasdair Kergon
70babe8a28 --abort --background 2003-05-06 12:08:58 +00:00
Alasdair Kergon
c36e09664f move fields 2003-05-06 12:06:02 +00:00
Alasdair Kergon
a9672246f3 reset_locking() 2003-05-06 12:03:13 +00:00
Alasdair Kergon
ff571884e9 Move fields. 2003-05-06 12:02:36 +00:00
Alasdair Kergon
475138bceb list_next 2003-05-06 12:01:13 +00:00
Alasdair Kergon
4a8af199c2 Add argv 2003-05-06 12:00:51 +00:00
Alasdair Kergon
bdabf5db72 Distinguish between visible & top level devices. 2003-05-06 12:00:29 +00:00
Alasdair Kergon
6a5f21b34e Missing 'make install' dependency. 2003-05-06 11:58:55 +00:00
Alasdair Kergon
d608be103c Update 2003-04-30 16:49:27 +00:00
Alasdair Kergon
374bb5d18a Don't move snapshots 2003-04-30 15:58:09 +00:00
Alasdair Kergon
031d6c25ff Add pvmove 2003-04-30 15:28:17 +00:00
Alasdair Kergon
223fb7b075 add region size & interval 2003-04-30 15:27:48 +00:00
Alasdair Kergon
a746741971 configurable region size 2003-04-30 15:26:54 +00:00
Alasdair Kergon
120faf2a58 pvmove support 2003-04-30 15:26:25 +00:00
Alasdair Kergon
990bca0dc6 use pvmove flag 2003-04-30 15:25:34 +00:00
Alasdair Kergon
3406472db7 Add mirror.c 2003-04-30 15:24:49 +00:00
Alasdair Kergon
1bd733c9f6 Outline pvmove man page 2003-04-30 15:24:08 +00:00
Alasdair Kergon
238c7f982e basic pvmove support 2003-04-30 15:23:43 +00:00
Alasdair Kergon
fcb81147cb pvmove flag 2003-04-30 15:22:52 +00:00
Alasdair Kergon
1915b73783 mirror type 2003-04-30 15:22:36 +00:00
Alasdair Kergon
ee79e621fb mirror display type 2003-04-30 15:21:43 +00:00
Alasdair Kergon
d203275a3b Add comment 2003-04-30 15:21:10 +00:00
Alasdair Kergon
9e8a996222 Up interface to major version number 4. 2003-04-30 13:48:53 +00:00
Alasdair Kergon
0126b0b3ed Up interface to major version number 4. 2003-04-29 22:52:11 +00:00
Alasdair Kergon
458928612c Display event number. 2003-04-29 11:34:40 +00:00
Alasdair Kergon
e33f88e28d Event number support. 2003-04-29 11:34:23 +00:00
Alasdair Kergon
be570bbf9e Try alternative syncs if BLKFLSBUF fails. 2003-04-28 16:20:39 +00:00
Alasdair Kergon
f59b4be110 Extra metadata-reading debug message. 2003-04-28 12:18:53 +00:00
Alasdair Kergon
37336e41be Revert to data_start 2003-04-28 11:55:58 +00:00
Alasdair Kergon
d24a1a3f0a Version 1.95.17 (new <PV>:<PE range list> allocation restriction feature). 2003-04-24 22:52:14 +00:00
Alasdair Kergon
f7258955bd Update segment area length when merging consecutive segments. 2003-04-24 22:46:47 +00:00
Alasdair Kergon
2a1eae5d6f o Metadata area struct change.
o Support physical extent restrictions on PV lists for allocations
    e.g. lvcreate -l 200 vg1 /dev/sda1:100-199:300-399
2003-04-24 22:23:24 +00:00
Alasdair Kergon
50ee0a4adb Stop more gracefully when in test mode. 2003-04-24 22:13:48 +00:00
Alasdair Kergon
955a26584e stripe filler parameter 2003-04-24 22:10:56 +00:00
Alasdair Kergon
1d3e407c8f o Rejig activation code device dependencies to make things a bit more robust
and further reduce the number of ioctl calls made.
o Metadata area struct change.
o Make config file accessible to activation functions & get stripe_filler
  from it.
o Allow kernel to return snapshot status as a fraction or a percentage.
2003-04-24 22:09:13 +00:00
Alasdair Kergon
cb809c4596 indent 2003-04-24 22:00:29 +00:00
Alasdair Kergon
53bbe2888e fix optind after last change to it 2003-04-24 21:59:42 +00:00
Alasdair Kergon
7246f476a5 Add pool_strndup 2003-04-24 21:58:34 +00:00
Alasdair Kergon
0785d1c390 DM_EXISTS_FLAG replaced by ENXIO 2003-04-24 16:08:18 +00:00
Alasdair Kergon
85d2c49d14 Some ioctl code tidying: removing duplicate internal buffers; making bounds
checks clearer (incl. variable renaming); using a flag to indicate when
output data doesn't fit into supplied buffer instead of returning an error etc.
2003-04-22 21:22:04 +00:00
Alasdair Kergon
8b77d62b7f Improve message for pvcreate of empty device. 2003-04-22 16:09:11 +00:00
Alasdair Kergon
373058a32a Improve build robustness. 2003-04-15 13:24:42 +00:00
Alasdair Kergon
e6293c2c8c Abort if any filter creation fails. 2003-04-15 13:22:43 +00:00
Alasdair Kergon
eff181c959 Cope with intentionally missing /proc. 2003-04-15 13:21:38 +00:00
Alasdair Kergon
54752c2305 Support snapshot status fraction. 2003-04-15 13:20:16 +00:00
Alasdair Kergon
b4753c044f Display read-only state. 2003-04-15 12:30:44 +00:00
Alasdair Kergon
26493424ae alignment fixes 2003-04-08 21:20:31 +00:00
Alasdair Kergon
0282fd1332 Add major arg 2003-04-04 13:22:58 +00:00
Alasdair Kergon
b9a019a08b Allow for specification of major number as well as minor. 2003-04-02 19:14:43 +00:00
Alasdair Kergon
66f6a0e687 size_t tidying 2003-04-02 19:11:23 +00:00
Alasdair Kergon
2dd1b9f97d Allow device major to be set too. 2003-04-02 19:03:00 +00:00
Alasdair Kergon
89615f3045 Reinstate lost vg_write() in lvchange --permission. 2003-04-02 13:01:04 +00:00
Alasdair Kergon
7e46192f67 Proposed changes to the ioctl interface to fix alignment issues on some
architectures and specify an explicit width for every numeric field.
2003-03-28 18:58:59 +00:00
Alasdair Kergon
e78d985cdf Avoid report segfault with non-partial inconsistent VG. 2003-03-24 18:22:48 +00:00
Alasdair Kergon
e8c4bf56fe Tidy various pre-processing incl. making libdl optional. 2003-03-24 18:08:53 +00:00
Alasdair Kergon
e6aa7d323d Fix incomplete munmap. (pjc) 2003-03-20 14:29:28 +00:00
Alasdair Kergon
fca8e25929 Fix typo. 2003-03-03 12:57:27 +00:00
Joe Thornber
8e8ac286b4 HAT_CHAR and DOLLAR_CHAR were defined to the same value ! 2003-02-20 14:53:56 +00:00
Alasdair Kergon
7d9770b9a2 Fix table output bug in last commit. 2003-02-20 13:30:03 +00:00
Andres Salomon
1996230460 Update packages. 2003-02-16 22:12:28 +00:00
Alasdair Kergon
de7897a864 LV name validation 2003-02-03 20:09:58 +00:00
Alasdair Kergon
e2884dcdb7 Identifiers may now start with digits etc. 2003-02-03 20:08:45 +00:00
Alasdair Kergon
544a53a42b Allow strings in single quotes too 2003-01-28 17:20:11 +00:00
Alasdair Kergon
2e4787bfc8 Treat 'section{' as equivalent to 'section {' 2003-01-28 16:07:04 +00:00
Alasdair Kergon
1829eeb171 merge back accidentally overwritten r1.2 change 2003-01-25 13:34:35 +00:00
Alasdair Kergon
c7488e3c4a Prepare for ioctl version number change. 2003-01-21 21:27:36 +00:00
Alasdair Kergon
3bf9606383 Allow optional verbose logging. 2003-01-21 21:25:51 +00:00
Alasdair Kergon
4f43f18f0a Allow optional verbose logging 2003-01-21 21:25:11 +00:00
Alasdair Kergon
5b7f197397 Add --enable-debug --disable-compat 2003-01-21 21:22:55 +00:00
Alasdair Kergon
018141c97f Indicate full (dropped) snapshot. 2003-01-21 18:50:50 +00:00
Alasdair Kergon
4d7813e57c vgreduce --removemissing to remove missing PVs & deps & make VG consistent 2003-01-17 21:04:26 +00:00
Alasdair Kergon
605c60208f Add success message; validate given VG name. 2003-01-17 21:02:04 +00:00
Alasdair Kergon
884fafcc30 Activation commands now return success in test mode. 2003-01-17 20:16:23 +00:00
Alasdair Kergon
56baa90320 Update 2003-01-10 22:51:18 +00:00
Alasdair Kergon
6bb20ee09e Fix (rare) cache bug on machines with large /dev directories. 2003-01-10 19:14:01 +00:00
Alasdair Kergon
541356430c Fix segfault in uuid display (substitution missed during bulk change) 2003-01-09 19:35:17 +00:00
Alasdair Kergon
2f4d91fd69 configure --disable-devmapper if you don't have libdevmapper 2003-01-08 22:44:07 +00:00
Alasdair Kergon
f58c5e6b30 o Additional device/filter-level debugging messages + duplicate alias fix
o 32/64-bit size_t fix (pjc)
2003-01-08 16:41:22 +00:00
141 changed files with 7594 additions and 2003 deletions

View File

@@ -1 +1 @@
1.95.13-cvs (2003-01-07)
2.00.00-cvs (2003-07-04)

View File

@@ -1,4 +1,13 @@
Mondy 18th November 2002
Wednesday 30th April 2003
=========================
A pvmove implementation is now available for the new metadata format.
When running a command that allocates space (e.g. lvcreate), you can now
restrict not only which disk(s) may be used but also the Physical Extents
on those disks. e.g. lvcreate -L 10 vg1 /dev/hda6:1000-2000:3000-4000
Monday 18th November 2002
========================
The new format of LVM metadata is ready for you to test!
@@ -15,7 +24,7 @@ While testing, we recommend turning logging on in the configuration file
to provide us with diagnostic information:
log {
file="/tmp/lvm2.log"
level=6
level=7
}
You should schedule regular backups of your configuration file and
@@ -65,7 +74,7 @@ changes.
What's not finished?
====================
The internal cache. If you turn on debugging output you'll see lots of
repeated disk reads, many of which will eventually get optimised out.
repeated messages, many of which will eventually get optimised out.
--test sometimes causes a command to fail (e.g. vgconvert --test) even
though the real command would work: again, fixing this is waiting for
@@ -78,9 +87,7 @@ finds something unexpected. This applies particularly to tools that
work on more than one volume group at once (e.g. vgsplit).
Display output. Some metadata information cannot yet be displayed.
Work has started on new display tools.
Recovery tools to salvage "lost" metadata directly from the disks:
but we hope the new format will mean such tools are hardly ever needed!

777
autoconf/config.guess vendored

File diff suppressed because it is too large Load Diff

373
autoconf/config.sub vendored
View File

@@ -1,6 +1,10 @@
#! /bin/sh
# Configuration validation subroutine script, version 1.1.
# Copyright (C) 1991, 92-97, 1998, 1999 Free Software Foundation, Inc.
# Configuration validation subroutine script.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
# Free Software Foundation, Inc.
timestamp='2001-09-07'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
# can handle that machine. It does not imply ALL GNU software can.
@@ -25,6 +29,8 @@
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Please send patches to <config-patches@gnu.org>.
#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
# If it is invalid, we print an error message on stderr and exit with code 1.
@@ -45,30 +51,73 @@
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# It is wrong to echo any other type of specification.
if [ x$1 = x ]
then
echo Configuration name missing. 1>&2
echo "Usage: $0 CPU-MFR-OPSYS" 1>&2
echo "or $0 ALIAS" 1>&2
echo where ALIAS is a recognized configuration type. 1>&2
exit 1
fi
me=`echo "$0" | sed -e 's,.*/,,'`
# First pass through any local machine types.
case $1 in
*local*)
echo $1
exit 0
;;
*)
;;
usage="\
Usage: $0 [OPTION] CPU-MFR-OPSYS
$0 [OPTION] ALIAS
Canonicalize a configuration name.
Operation modes:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
help="
Try \`$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
echo "$timestamp" ; exit 0 ;;
--version | -v )
echo "$version" ; exit 0 ;;
--help | --h* | -h )
echo "$usage"; exit 0 ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
break ;;
-* )
echo "$me: invalid option $1$help"
exit 1 ;;
*local*)
# First pass through any local machine types.
echo $1
exit 0;;
* )
break ;;
esac
done
case $# in
0) echo "$me: missing argument$help" >&2
exit 1;;
1) ;;
*) echo "$me: too many arguments$help" >&2
exit 1;;
esac
# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
linux-gnu*)
nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
@@ -94,7 +143,7 @@ case $os in
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-apple)
-apple | -axis)
os=
basic_machine=$1
;;
@@ -105,9 +154,17 @@ case $os in
-scout)
;;
-wrs)
os=vxworks
os=-vxworks
basic_machine=$1
;;
-chorusos*)
os=-chorusos
basic_machine=$1
;;
-chorusrdb)
os=-chorusrdb
basic_machine=$1
;;
-hiux*)
os=-hiuxwe2
;;
@@ -156,33 +213,60 @@ case $os in
-psos*)
os=-psos
;;
-mint | -mint[0-9]*)
basic_machine=m68k-atari
os=-mint
;;
esac
# Decode aliases for certain CPU-COMPANY combinations.
case $basic_machine in
# Recognize the basic CPU types without company name.
# Some are omitted here because they have special meanings below.
tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \
| arme[lb] | pyramid | mn10200 | mn10300 | tron | a29k \
| 580 | i960 | h8300 \
| hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \
| alpha | alphaev[4-7] | alphaev56 | alphapca5[67] \
| we32k | ns16k | clipper | i370 | sh | powerpc | powerpcle \
| 1750a | dsp16xx | pdp11 | mips16 | mips64 | mipsel | mips64el \
| mips64orion | mips64orionel | mipstx39 | mipstx39el \
| mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \
| mips64vr5000 | miprs64vr5000el | mcore \
| sparc | sparclet | sparclite | sparc64 | sparcv9 | v850 | c4x \
| thumb | d10v)
1750a | 580 \
| a29k \
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
| c4x | clipper \
| d10v | d30v | dsp16xx \
| fr30 \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| i370 | i860 | i960 | ia64 \
| m32r | m68000 | m68k | m88k | mcore \
| mips16 | mips64 | mips64el | mips64orion | mips64orionel \
| mips64vr4100 | mips64vr4100el | mips64vr4300 \
| mips64vr4300el | mips64vr5000 | mips64vr5000el \
| mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \
| mipsisa32 \
| mn10200 | mn10300 \
| ns16k | ns32k \
| openrisc \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
| pyramid \
| s390 | s390x \
| sh | sh[34] | sh[34]eb | shbe | shle \
| sparc | sparc64 | sparclet | sparclite | sparcv9 | sparcv9b \
| stormy16 | strongarm \
| tahoe | thumb | tic80 | tron \
| v850 \
| we32k \
| x86 | xscale \
| z8k)
basic_machine=$basic_machine-unknown
;;
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | h8500 | w65)
m6811 | m68hc11 | m6812 | m68hc12)
# Motorola 68HC11/12.
basic_machine=$basic_machine-unknown
os=-none
;;
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
;;
# We use `pc' rather than `unknown'
# because (1) that's what they normally are, and
# (2) the word "unknown" tends to confuse beginning users.
i[34567]86)
i*86 | x86_64)
basic_machine=$basic_machine-pc
;;
# Object if more than one company name word.
@@ -191,24 +275,43 @@ case $basic_machine in
exit 1
;;
# Recognize the basic CPU types with company name.
# FIXME: clean up the formatting here.
vax-* | tahoe-* | i[34567]86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \
| m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \
| mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
| power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \
| xmp-* | ymp-* \
| hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* | hppa2.0n-* \
| alpha-* | alphaev[4-7]-* | alphaev56-* | alphapca5[67]-* \
| we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \
| clipper-* | orion-* \
| sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \
| sparc64-* | sparcv9-* | sparc86x-* | mips16-* | mips64-* | mipsel-* \
| mips64el-* | mips64orion-* | mips64orionel-* \
| mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \
| mipstx39-* | mipstx39el-* | mcore-* \
| f301-* | armv*-* | t3e-* \
| m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \
| thumb-* | v850-* | d30v-* | tic30-* | c30-* )
580-* \
| a29k-* \
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
| alphapca5[67]-* | arc-* \
| arm-* | armbe-* | armle-* | armv*-* \
| bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c54x-* \
| clipper-* | cray2-* | cydra-* \
| d10v-* | d30v-* \
| elxsi-* \
| f30[01]-* | f700-* | fr30-* | fx80-* \
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| i*86-* | i860-* | i960-* | ia64-* \
| m32r-* \
| m68000-* | m680[01234]0-* | m68360-* | m683?2-* | m68k-* \
| m88110-* | m88k-* | mcore-* \
| mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \
| mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \
| mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \
| mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \
| none-* | np1-* | ns16k-* | ns32k-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
| pyramid-* \
| romp-* | rs6000-* \
| s390-* | s390x-* \
| sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* \
| sparc-* | sparc64-* | sparc86x-* | sparclite-* \
| sparcv9-* | sparcv9b-* | stormy16-* | strongarm-* | sv1-* \
| t3e-* | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \
| v850-* | vax-* \
| we32k-* \
| x86-* | x86_64-* | xmp-* | xps100-* | xscale-* \
| ymp-* \
| z8k-*)
;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
@@ -245,14 +348,14 @@ case $basic_machine in
os=-sysv
;;
amiga | amiga-*)
basic_machine=m68k-cbm
basic_machine=m68k-unknown
;;
amigaos | amigados)
basic_machine=m68k-cbm
basic_machine=m68k-unknown
os=-amigaos
;;
amigaunix | amix)
basic_machine=m68k-cbm
basic_machine=m68k-unknown
os=-sysv4
;;
apollo68)
@@ -299,13 +402,16 @@ case $basic_machine in
basic_machine=cray2-cray
os=-unicos
;;
[ctj]90-cray)
basic_machine=c90-cray
[cjt]90)
basic_machine=${basic_machine}-cray
os=-unicos
;;
crds | unos)
basic_machine=m68k-crds
;;
cris | cris-* | etrax*)
basic_machine=cris-axis
;;
da30 | da30-*)
basic_machine=m68k-da30
;;
@@ -353,6 +459,10 @@ case $basic_machine in
basic_machine=tron-gmicro
os=-sysv
;;
go32)
basic_machine=i386-pc
os=-go32
;;
h3050r* | hiux*)
basic_machine=hppa1.1-hitachi
os=-hiuxwe2
@@ -426,22 +536,21 @@ case $basic_machine in
;;
i370-ibm* | ibm*)
basic_machine=i370-ibm
os=-mvs
;;
# I'm not sure what "Sysv32" means. Should this be sysv3.2?
i[34567]86v32)
i*86v32)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv32
;;
i[34567]86v4*)
i*86v4*)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv4
;;
i[34567]86v)
i*86v)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv
;;
i[34567]86sol2)
i*86sol2)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-solaris2
;;
@@ -453,14 +562,6 @@ case $basic_machine in
basic_machine=i386-unknown
os=-vsta
;;
i386-go32 | go32)
basic_machine=i386-unknown
os=-go32
;;
i386-mingw32 | mingw32)
basic_machine=i386-unknown
os=-mingw32
;;
iris | iris4d)
basic_machine=mips-sgi
case $os in
@@ -486,10 +587,14 @@ case $basic_machine in
basic_machine=ns32k-utek
os=-sysv
;;
mingw32)
basic_machine=i386-pc
os=-mingw32
;;
miniframe)
basic_machine=m68000-convergent
;;
*mint | *MiNT)
*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
basic_machine=m68k-atari
os=-mint
;;
@@ -507,14 +612,22 @@ case $basic_machine in
mips3*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
;;
mmix*)
basic_machine=mmix-knuth
os=-mmixware
;;
monitor)
basic_machine=m68k-rom68k
os=-coff
;;
msdos)
basic_machine=i386-unknown
basic_machine=i386-pc
os=-msdos
;;
mvs)
basic_machine=i370-ibm
os=-mvs
;;
ncr3000)
basic_machine=i486-ncr
os=-sysv4
@@ -524,7 +637,7 @@ case $basic_machine in
os=-netbsd
;;
netwinder)
basic_machine=armv4l-corel
basic_machine=armv4l-rebel
os=-linux
;;
news | news700 | news800 | news900)
@@ -572,9 +685,16 @@ case $basic_machine in
basic_machine=i960-intel
os=-mon960
;;
nonstopux)
basic_machine=mips-compaq
os=-nonstopux
;;
np1)
basic_machine=np1-gould
;;
nsr-tandem)
basic_machine=nsr-tandem
;;
op50n-* | op60c-*)
basic_machine=hppa1.1-oki
os=-proelf
@@ -604,28 +724,28 @@ case $basic_machine in
pc532 | pc532-*)
basic_machine=ns32k-pc532
;;
pentium | p5 | k5 | k6 | nexen)
pentium | p5 | k5 | k6 | nexgen)
basic_machine=i586-pc
;;
pentiumpro | p6 | 6x86)
pentiumpro | p6 | 6x86 | athlon)
basic_machine=i686-pc
;;
pentiumii | pentium2)
basic_machine=i786-pc
basic_machine=i686-pc
;;
pentium-* | p5-* | k5-* | k6-* | nexen-*)
pentium-* | p5-* | k5-* | k6-* | nexgen-*)
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentiumpro-* | p6-* | 6x86-*)
pentiumpro-* | p6-* | 6x86-* | athlon-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentiumii-* | pentium2-*)
basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pn)
basic_machine=pn-gould
;;
power) basic_machine=rs6000-ibm
power) basic_machine=power-ibm
;;
ppc) basic_machine=powerpc-unknown
;;
@@ -637,9 +757,23 @@ case $basic_machine in
ppcle-* | powerpclittle-*)
basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppc64) basic_machine=powerpc64-unknown
;;
ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppc64le | powerpc64little | ppc64-le | powerpc64-little)
basic_machine=powerpc64le-unknown
;;
ppc64le-* | powerpc64little-*)
basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ps2)
basic_machine=i386-ibm
;;
pw32)
basic_machine=i586-unknown
os=-pw32
;;
rom68k)
basic_machine=m68k-rom68k
os=-coff
@@ -719,6 +853,10 @@ case $basic_machine in
sun386 | sun386i | roadrunner)
basic_machine=i386-sun
;;
sv1)
basic_machine=sv1-cray
os=-unicos
;;
symmetry)
basic_machine=i386-sequent
os=-dynix
@@ -727,6 +865,10 @@ case $basic_machine in
basic_machine=t3e-cray
os=-unicos
;;
tic54x | c54x*)
basic_machine=tic54x-unknown
os=-coff
;;
tx39)
basic_machine=mipstx39-unknown
;;
@@ -779,6 +921,10 @@ case $basic_machine in
basic_machine=hppa1.1-winbond
os=-proelf
;;
windows32)
basic_machine=i386-pc
os=-windows32-msvcrt
;;
xmp)
basic_machine=xmp-cray
os=-unicos
@@ -822,13 +968,20 @@ case $basic_machine in
vax)
basic_machine=vax-dec
;;
pdp10)
# there are many clones, so DEC is not a safe bet
basic_machine=pdp10-unknown
;;
pdp11)
basic_machine=pdp11-dec
;;
we32k)
basic_machine=we32k-att
;;
sparc | sparcv9)
sh3 | sh4 | sh3eb | sh4eb)
basic_machine=sh-unknown
;;
sparc | sparcv9 | sparcv9b)
basic_machine=sparc-sun
;;
cydra)
@@ -850,6 +1003,9 @@ case $basic_machine in
basic_machine=c4x-none
os=-coff
;;
*-unknown)
# Make sure to match an already-canonicalized machine name.
;;
*)
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
exit 1
@@ -906,14 +1062,30 @@ case $os in
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* \
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -rhapsody* | -openstep* | -oskit*)
| -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
| -os2* | -vos*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
case $basic_machine in
x86-* | i*86-*)
;;
*)
os=-nto$os
;;
esac
;;
-nto*)
os=-nto-qnx
;;
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
| -windows* | -osx | -abug | -netware* | -os9* | -beos* \
| -macos* | -mpw* | -magic* | -mon960* | -lnews*)
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
;;
-mac*)
os=`echo $os | sed -e 's|mac|macos|'`
@@ -927,6 +1099,12 @@ case $os in
-sunos6*)
os=`echo $os | sed -e 's|sunos6|solaris3|'`
;;
-opened*)
os=-openedition
;;
-wince*)
os=-wince
;;
-osfrose*)
os=-osfrose
;;
@@ -951,6 +1129,9 @@ case $os in
-ns2 )
os=-nextstep2
;;
-nsk*)
os=-nsk
;;
# Preserve the version number of sinix5.
-sinix5.*)
os=`echo $os | sed -e 's|sinix|sysv|'`
@@ -985,7 +1166,7 @@ case $os in
-xenix)
os=-xenix
;;
-*mint | -*MiNT)
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
os=-mint
;;
-none)
@@ -1013,12 +1194,15 @@ case $basic_machine in
*-acorn)
os=-riscix1.2
;;
arm*-corel)
arm*-rebel)
os=-linux
;;
arm*-semi)
os=-aout
;;
pdp10-*)
os=-tops20
;;
pdp11-*)
os=-none
;;
@@ -1127,7 +1311,7 @@ case $basic_machine in
*-masscomp)
os=-rtu
;;
f301-fujitsu)
f30[01]-fujitsu | f700-fujitsu)
os=-uxpv
;;
*-rom68k)
@@ -1187,7 +1371,7 @@ case $basic_machine in
-genix*)
vendor=ns
;;
-mvs*)
-mvs* | -opened*)
vendor=ibm
;;
-ptx*)
@@ -1205,12 +1389,23 @@ case $basic_machine in
-mpw* | -macos*)
vendor=apple
;;
-*mint | -*MiNT)
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
vendor=atari
;;
-vos*)
vendor=stratus
;;
esac
basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
;;
esac
echo $basic_machine$os
exit 0
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
# End:

401
configure vendored
View File

@@ -28,6 +28,8 @@ ac_help="$ac_help
--enable-readline Enable readline support"
ac_help="$ac_help
--enable-debug Enable debugging"
ac_help="$ac_help
--disable-devmapper Disable device-mapper interaction"
# Initialize some variables set by options.
# The variables have the same names as the options, with
@@ -564,7 +566,7 @@ do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:568: checking for $ac_word" >&5
echo "configure:570: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_AWK'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -596,7 +598,7 @@ done
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:600: checking for $ac_word" >&5
echo "configure:602: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -626,7 +628,7 @@ if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:630: checking for $ac_word" >&5
echo "configure:632: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -677,7 +679,7 @@ fi
# Extract the first word of "cl", so it can be a program name with args.
set dummy cl; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:681: checking for $ac_word" >&5
echo "configure:683: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -709,7 +711,7 @@ fi
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
echo "configure:713: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
echo "configure:715: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
@@ -720,12 +722,12 @@ cross_compiling=$ac_cv_prog_cc_cross
cat > conftest.$ac_ext << EOF
#line 724 "configure"
#line 726 "configure"
#include "confdefs.h"
main(){return(0);}
EOF
if { (eval echo configure:729: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:731: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
ac_cv_prog_cc_works=yes
# If we can't run a trivial program, we are probably using a cross compiler.
if (./conftest; exit) 2>/dev/null; then
@@ -751,12 +753,12 @@ if test $ac_cv_prog_cc_works = no; then
{ echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
echo "configure:755: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
echo "configure:757: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
cross_compiling=$ac_cv_prog_cc_cross
echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
echo "configure:760: checking whether we are using GNU C" >&5
echo "configure:762: checking whether we are using GNU C" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -765,7 +767,7 @@ else
yes;
#endif
EOF
if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:769: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:771: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
ac_cv_prog_gcc=yes
else
ac_cv_prog_gcc=no
@@ -784,7 +786,7 @@ ac_test_CFLAGS="${CFLAGS+set}"
ac_save_CFLAGS="$CFLAGS"
CFLAGS=
echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
echo "configure:788: checking whether ${CC-cc} accepts -g" >&5
echo "configure:790: checking whether ${CC-cc} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -827,7 +829,7 @@ fi
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
echo "configure:831: checking for a BSD compatible install" >&5
echo "configure:833: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -880,7 +882,7 @@ test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
echo "configure:884: checking whether ln -s works" >&5
echo "configure:886: checking whether ln -s works" >&5
if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -901,7 +903,7 @@ else
fi
echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
echo "configure:905: checking whether ${MAKE-make} sets \${MAKE}" >&5
echo "configure:907: checking whether ${MAKE-make} sets \${MAKE}" >&5
set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -930,7 +932,7 @@ fi
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:934: checking for $ac_word" >&5
echo "configure:936: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -963,12 +965,12 @@ for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6
echo "configure:967: checking for $ac_hdr that defines DIR" >&5
echo "configure:969: checking for $ac_hdr that defines DIR" >&5
if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 972 "configure"
#line 974 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <$ac_hdr>
@@ -976,7 +978,7 @@ int main() {
DIR *dirp = 0;
; return 0; }
EOF
if { (eval echo configure:980: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:982: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_header_dirent_$ac_safe=yes"
else
@@ -1001,7 +1003,7 @@ done
# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
if test $ac_header_dirent = dirent.h; then
echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6
echo "configure:1005: checking for opendir in -ldir" >&5
echo "configure:1007: checking for opendir in -ldir" >&5
ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1009,7 +1011,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-ldir $LIBS"
cat > conftest.$ac_ext <<EOF
#line 1013 "configure"
#line 1015 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -1020,7 +1022,7 @@ int main() {
opendir()
; return 0; }
EOF
if { (eval echo configure:1024: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:1026: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1042,7 +1044,7 @@ fi
else
echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6
echo "configure:1046: checking for opendir in -lx" >&5
echo "configure:1048: checking for opendir in -lx" >&5
ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1050,7 +1052,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lx $LIBS"
cat > conftest.$ac_ext <<EOF
#line 1054 "configure"
#line 1056 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -1061,7 +1063,7 @@ int main() {
opendir()
; return 0; }
EOF
if { (eval echo configure:1065: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:1067: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1084,7 +1086,7 @@ fi
fi
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
echo "configure:1088: checking how to run the C preprocessor" >&5
echo "configure:1090: checking how to run the C preprocessor" >&5
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
@@ -1099,13 +1101,13 @@ else
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp.
cat > conftest.$ac_ext <<EOF
#line 1103 "configure"
#line 1105 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1109: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:1111: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
@@ -1116,13 +1118,13 @@ else
rm -rf conftest*
CPP="${CC-cc} -E -traditional-cpp"
cat > conftest.$ac_ext <<EOF
#line 1120 "configure"
#line 1122 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1126: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:1128: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
@@ -1133,13 +1135,13 @@ else
rm -rf conftest*
CPP="${CC-cc} -nologo -E"
cat > conftest.$ac_ext <<EOF
#line 1137 "configure"
#line 1139 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1143: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:1145: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
@@ -1164,12 +1166,12 @@ fi
echo "$ac_t""$CPP" 1>&6
echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
echo "configure:1168: checking for ANSI C header files" >&5
echo "configure:1170: checking for ANSI C header files" >&5
if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1173 "configure"
#line 1175 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <stdarg.h>
@@ -1177,7 +1179,7 @@ else
#include <float.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1181: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:1183: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -1194,7 +1196,7 @@ rm -f conftest*
if test $ac_cv_header_stdc = yes; then
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
#line 1198 "configure"
#line 1200 "configure"
#include "confdefs.h"
#include <string.h>
EOF
@@ -1212,7 +1214,7 @@ fi
if test $ac_cv_header_stdc = yes; then
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
#line 1216 "configure"
#line 1218 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
@@ -1233,7 +1235,7 @@ if test "$cross_compiling" = yes; then
:
else
cat > conftest.$ac_ext <<EOF
#line 1237 "configure"
#line 1239 "configure"
#include "confdefs.h"
#include <ctype.h>
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -1244,7 +1246,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
exit (0); }
EOF
if { (eval echo configure:1248: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
if { (eval echo configure:1250: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
:
else
@@ -1271,17 +1273,17 @@ for ac_hdr in fcntl.h malloc.h sys/ioctl.h unistd.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:1275: checking for $ac_hdr" >&5
echo "configure:1277: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1280 "configure"
#line 1282 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1285: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:1287: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -1309,12 +1311,12 @@ done
echo $ac_n "checking for working const""... $ac_c" 1>&6
echo "configure:1313: checking for working const" >&5
echo "configure:1315: checking for working const" >&5
if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1318 "configure"
#line 1320 "configure"
#include "confdefs.h"
int main() {
@@ -1363,7 +1365,7 @@ ccp = (char const *const *) p;
; return 0; }
EOF
if { (eval echo configure:1367: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:1369: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_const=yes
else
@@ -1384,21 +1386,21 @@ EOF
fi
echo $ac_n "checking for inline""... $ac_c" 1>&6
echo "configure:1388: checking for inline" >&5
echo "configure:1390: checking for inline" >&5
if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_cv_c_inline=no
for ac_kw in inline __inline__ __inline; do
cat > conftest.$ac_ext <<EOF
#line 1395 "configure"
#line 1397 "configure"
#include "confdefs.h"
int main() {
} int $ac_kw foo() {
; return 0; }
EOF
if { (eval echo configure:1402: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:1404: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_inline=$ac_kw; break
else
@@ -1424,12 +1426,12 @@ EOF
esac
echo $ac_n "checking for off_t""... $ac_c" 1>&6
echo "configure:1428: checking for off_t" >&5
echo "configure:1430: checking for off_t" >&5
if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1433 "configure"
#line 1435 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
@@ -1457,12 +1459,12 @@ EOF
fi
echo $ac_n "checking for pid_t""... $ac_c" 1>&6
echo "configure:1461: checking for pid_t" >&5
echo "configure:1463: checking for pid_t" >&5
if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1466 "configure"
#line 1468 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
@@ -1490,12 +1492,12 @@ EOF
fi
echo $ac_n "checking for size_t""... $ac_c" 1>&6
echo "configure:1494: checking for size_t" >&5
echo "configure:1496: checking for size_t" >&5
if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1499 "configure"
#line 1501 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
@@ -1523,12 +1525,12 @@ EOF
fi
echo $ac_n "checking for st_rdev in struct stat""... $ac_c" 1>&6
echo "configure:1527: checking for st_rdev in struct stat" >&5
echo "configure:1529: checking for st_rdev in struct stat" >&5
if eval "test \"`echo '$''{'ac_cv_struct_st_rdev'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1532 "configure"
#line 1534 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/stat.h>
@@ -1536,7 +1538,7 @@ int main() {
struct stat s; s.st_rdev;
; return 0; }
EOF
if { (eval echo configure:1540: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:1542: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_struct_st_rdev=yes
else
@@ -1557,12 +1559,12 @@ EOF
fi
echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
echo "configure:1561: checking whether time.h and sys/time.h may both be included" >&5
echo "configure:1563: checking whether time.h and sys/time.h may both be included" >&5
if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1566 "configure"
#line 1568 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/time.h>
@@ -1571,7 +1573,7 @@ int main() {
struct tm *tp;
; return 0; }
EOF
if { (eval echo configure:1575: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:1577: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_header_time=yes
else
@@ -1593,6 +1595,101 @@ fi
# Do some error checking and defaulting for the host and target type.
# The inputs are:
# configure --host=HOST --target=TARGET --build=BUILD NONOPT
#
# The rules are:
# 1. You are not allowed to specify --host, --target, and nonopt at the
# same time.
# 2. Host defaults to nonopt.
# 3. If nonopt is not specified, then host defaults to the current host,
# as determined by config.guess.
# 4. Target and build default to nonopt.
# 5. If nonopt is not specified, then target and build default to host.
# The aliases save the names the user supplied, while $host etc.
# will get canonicalized.
case $host---$target---$nonopt in
NONE---*---* | *---NONE---* | *---*---NONE) ;;
*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
esac
# Make sure we can run config.sub.
if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
fi
echo $ac_n "checking host system type""... $ac_c" 1>&6
echo "configure:1626: checking host system type" >&5
host_alias=$host
case "$host_alias" in
NONE)
case $nonopt in
NONE)
if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
fi ;;
*) host_alias=$nonopt ;;
esac ;;
esac
host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$host" 1>&6
echo $ac_n "checking target system type""... $ac_c" 1>&6
echo "configure:1647: checking target system type" >&5
target_alias=$target
case "$target_alias" in
NONE)
case $nonopt in
NONE) target_alias=$host_alias ;;
*) target_alias=$nonopt ;;
esac ;;
esac
target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$target" 1>&6
echo $ac_n "checking build system type""... $ac_c" 1>&6
echo "configure:1665: checking build system type" >&5
build_alias=$build
case "$build_alias" in
NONE)
case $nonopt in
NONE) build_alias=$host_alias ;;
*) build_alias=$nonopt ;;
esac ;;
esac
build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$build" 1>&6
test "$host_alias" != "$target_alias" &&
test "$program_prefix$program_suffix$program_transform_name" = \
NONENONEs,x,x, &&
program_prefix=${target_alias}-
case "$host_os" in
linux*)
CFLAGS= ;;
esac
# Check whether --with-user or --without-user was given.
if test "${with_user+set}" = set; then
@@ -1627,6 +1724,10 @@ if [ "x$LVM1" != xnone -a "x$LVM1" != xinternal -a "x$LVM1" != xshared ];
exit
fi;
if test x$LVM1 = xinternal; then
CFLAGS="$CFLAGS -DLVM1_INTERNAL"
fi
# Check whether --enable-jobs or --disable-jobs was given.
if test "${enable_jobs+set}" = set; then
enableval="$enable_jobs"
@@ -1655,6 +1756,10 @@ else
fi
if test x$READLINE = xyes; then
CFLAGS="$CFLAGS -DREADLINE_SUPPORT"
fi
# Check whether --enable-debug or --disable-debug was given.
if test "${enable_debug+set}" = set; then
enableval="$enable_debug"
@@ -1665,19 +1770,33 @@ else
fi
# Check whether --enable-devmapper or --disable-devmapper was given.
if test "${enable_devmapper+set}" = set; then
enableval="$enable_devmapper"
\
DEVMAPPER=no
else
DEVMAPPER=yes
fi
if test x$DEVMAPPER = xyes; then
CFLAGS="$CFLAGS -DDEVMAPPER_SUPPORT"
fi
if [ "x$exec_prefix" = xNONE -a "x$prefix" = xNONE ];
then exec_prefix="";
fi;
if test $ac_cv_prog_gcc = yes; then
echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6
echo "configure:1675: checking whether ${CC-cc} needs -traditional" >&5
echo "configure:1794: checking whether ${CC-cc} needs -traditional" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_pattern="Autoconf.*'x'"
cat > conftest.$ac_ext <<EOF
#line 1681 "configure"
#line 1800 "configure"
#include "confdefs.h"
#include <sgtty.h>
Autoconf TIOCGETP
@@ -1695,7 +1814,7 @@ rm -f conftest*
if test $ac_cv_prog_gcc_traditional = no; then
cat > conftest.$ac_ext <<EOF
#line 1699 "configure"
#line 1818 "configure"
#include "confdefs.h"
#include <termio.h>
Autoconf TCGETA
@@ -1717,12 +1836,12 @@ echo "$ac_t""$ac_cv_prog_gcc_traditional" 1>&6
fi
echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
echo "configure:1721: checking return type of signal handlers" >&5
echo "configure:1840: checking return type of signal handlers" >&5
if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1726 "configure"
#line 1845 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <signal.h>
@@ -1739,7 +1858,7 @@ int main() {
int i;
; return 0; }
EOF
if { (eval echo configure:1743: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:1862: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_type_signal=void
else
@@ -1758,12 +1877,12 @@ EOF
echo $ac_n "checking for vprintf""... $ac_c" 1>&6
echo "configure:1762: checking for vprintf" >&5
echo "configure:1881: checking for vprintf" >&5
if eval "test \"`echo '$''{'ac_cv_func_vprintf'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1767 "configure"
#line 1886 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char vprintf(); below. */
@@ -1786,7 +1905,7 @@ vprintf();
; return 0; }
EOF
if { (eval echo configure:1790: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:1909: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_vprintf=yes"
else
@@ -1810,12 +1929,12 @@ fi
if test "$ac_cv_func_vprintf" != yes; then
echo $ac_n "checking for _doprnt""... $ac_c" 1>&6
echo "configure:1814: checking for _doprnt" >&5
echo "configure:1933: checking for _doprnt" >&5
if eval "test \"`echo '$''{'ac_cv_func__doprnt'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1819 "configure"
#line 1938 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char _doprnt(); below. */
@@ -1838,7 +1957,7 @@ _doprnt();
; return 0; }
EOF
if { (eval echo configure:1842: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:1961: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func__doprnt=yes"
else
@@ -1865,12 +1984,12 @@ fi
for ac_func in mkdir rmdir uname
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:1869: checking for $ac_func" >&5
echo "configure:1988: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1874 "configure"
#line 1993 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -1893,7 +2012,7 @@ $ac_func();
; return 0; }
EOF
if { (eval echo configure:1897: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:2016: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -1921,14 +2040,14 @@ done
if test x$READLINE = xyes; then
echo $ac_n "checking for library containing tgetent""... $ac_c" 1>&6
echo "configure:1925: checking for library containing tgetent" >&5
echo "configure:2044: checking for library containing tgetent" >&5
if eval "test \"`echo '$''{'ac_cv_search_tgetent'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_func_search_save_LIBS="$LIBS"
ac_cv_search_tgetent="no"
cat > conftest.$ac_ext <<EOF
#line 1932 "configure"
#line 2051 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -1939,7 +2058,7 @@ int main() {
tgetent()
; return 0; }
EOF
if { (eval echo configure:1943: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:2062: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_search_tgetent="none required"
else
@@ -1950,7 +2069,7 @@ rm -f conftest*
test "$ac_cv_search_tgetent" = "no" && for i in ncurses curses termcap termlib; do
LIBS="-l$i $ac_func_search_save_LIBS"
cat > conftest.$ac_ext <<EOF
#line 1954 "configure"
#line 2073 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -1961,7 +2080,7 @@ int main() {
tgetent()
; return 0; }
EOF
if { (eval echo configure:1965: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:2084: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_search_tgetent="-l$i"
break
@@ -1993,9 +2112,97 @@ Note: (n)curses also seems to work as a substitute for termcap. This was
fi
fi
echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
echo "configure:2117: checking for dlopen in -ldl" >&5
ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_save_LIBS="$LIBS"
LIBS="-ldl $LIBS"
cat > conftest.$ac_ext <<EOF
#line 2125 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
builtin and then its argument prototype would still apply. */
char dlopen();
int main() {
dlopen()
; return 0; }
EOF
if { (eval echo configure:2136: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=no"
fi
rm -f conftest*
LIBS="$ac_save_LIBS"
fi
if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
echo "$ac_t""yes" 1>&6
HAVE_LIBDL=yes
else
echo "$ac_t""no" 1>&6
HAVE_LIBDL=no
fi
if test x$HAVE_LIBDL = xyes; then
CFLAGS="$CFLAGS -DHAVE_LIBDL"
LIBS="-ldl $LIBS"
fi
for ac_hdr in getopt.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:2167: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2172 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2177: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
eval "ac_cv_header_$ac_safe=yes"
else
echo "$ac_err" >&5
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
eval "ac_cv_header_$ac_safe=no"
fi
rm -f conftest*
fi
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
echo "$ac_t""yes" 1>&6
ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
cat >> confdefs.h <<EOF
#define $ac_tr_hdr 1
EOF
CFLAGS="$CFLAGS -DHAVE_GETOPTLONG"
else
echo "$ac_t""no" 1>&6
fi
done
if test x$READLINE = xyes; then
echo $ac_n "checking for readline in -lreadline""... $ac_c" 1>&6
echo "configure:1999: checking for readline in -lreadline" >&5
echo "configure:2206: checking for readline in -lreadline" >&5
ac_lib_var=`echo readline'_'readline | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -2003,7 +2210,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lreadline $LIBS"
cat > conftest.$ac_ext <<EOF
#line 2007 "configure"
#line 2214 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -2014,7 +2221,7 @@ int main() {
readline()
; return 0; }
EOF
if { (eval echo configure:2018: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:2225: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -2051,12 +2258,12 @@ package as well (which may be called readline-devel or something similar).
fi
echo $ac_n "checking for rl_completion_matches""... $ac_c" 1>&6
echo "configure:2055: checking for rl_completion_matches" >&5
echo "configure:2262: checking for rl_completion_matches" >&5
if eval "test \"`echo '$''{'ac_cv_func_rl_completion_matches'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2060 "configure"
#line 2267 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char rl_completion_matches(); below. */
@@ -2079,7 +2286,7 @@ rl_completion_matches();
; return 0; }
EOF
if { (eval echo configure:2083: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:2290: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_rl_completion_matches=yes"
else
@@ -2093,12 +2300,12 @@ fi
if eval "test \"`echo '$ac_cv_func_'rl_completion_matches`\" = yes"; then
echo "$ac_t""yes" 1>&6
HAVE_RL_COMPLETION_MATCHES=yes
CFLAGS="$CFLAGS -DHAVE_RL_COMPLETION_MATCHES"
else
echo "$ac_t""no" 1>&6
HAVE_RL_COMPLETION_MATCHES=no
fi
fi
if test "-f VERSION"; then
@@ -2117,6 +2324,7 @@ fi
trap '' 1 2 15
cat > confcache <<\EOF
# This file is a shell script that caches the results of configure
@@ -2285,15 +2493,30 @@ s%@LN_S@%$LN_S%g
s%@SET_MAKE@%$SET_MAKE%g
s%@RANLIB@%$RANLIB%g
s%@CPP@%$CPP%g
s%@host@%$host%g
s%@host_alias@%$host_alias%g
s%@host_cpu@%$host_cpu%g
s%@host_vendor@%$host_vendor%g
s%@host_os@%$host_os%g
s%@target@%$target%g
s%@target_alias@%$target_alias%g
s%@target_cpu@%$target_cpu%g
s%@target_vendor@%$target_vendor%g
s%@target_os@%$target_os%g
s%@build@%$build%g
s%@build_alias@%$build_alias%g
s%@build_cpu@%$build_cpu%g
s%@build_vendor@%$build_vendor%g
s%@build_os@%$build_os%g
s%@JOBS@%$JOBS%g
s%@STATIC_LINK@%$STATIC_LINK%g
s%@READLINE@%$READLINE%g
s%@LVM1@%$LVM1%g
s%@HAVE_RL_COMPLETION_MATCHES@%$HAVE_RL_COMPLETION_MATCHES%g
s%@OWNER@%$OWNER%g
s%@GROUP@%$GROUP%g
s%@LVM_VERSION@%$LVM_VERSION%g
s%@DEBUG@%$DEBUG%g
s%@DEVMAPPER@%$DEVMAPPER%g
s%@HAVE_LIBDL@%$HAVE_LIBDL%g
CEOF
EOF

View File

@@ -46,6 +46,14 @@ AC_TYPE_SIZE_T
AC_STRUCT_ST_RDEV
AC_HEADER_TIME
dnl Get system type
AC_CANONICAL_SYSTEM
case "$host_os" in
linux*)
CFLAGS= ;;
esac
dnl -- prefix is /usr by default, the exec_prefix default is setup later
AC_PREFIX_DEFAULT(/usr)
@@ -75,6 +83,10 @@ if [[ "x$LVM1" != xnone -a "x$LVM1" != xinternal -a "x$LVM1" != xshared ]];
exit
fi;
if test x$LVM1 = xinternal; then
CFLAGS="$CFLAGS -DLVM1_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
@@ -85,10 +97,22 @@ dnl Enable readline
AC_ARG_ENABLE(readline, [ --enable-readline Enable readline support], \
READLINE=$enableval, READLINE=no)
if test x$READLINE = xyes; then
CFLAGS="$CFLAGS -DREADLINE_SUPPORT"
fi
dnl Enable Debugging
AC_ARG_ENABLE(debug, [ --enable-debug Enable debugging], \
DEBUG=yes, DEBUG=no)
dnl Disable devmapper
AC_ARG_ENABLE(devmapper, [ --disable-devmapper Disable device-mapper interaction], \
DEVMAPPER=no, DEVMAPPER=yes)
if test x$DEVMAPPER = xyes; then
CFLAGS="$CFLAGS -DDEVMAPPER_SUPPORT"
fi
dnl Mess with default exec_prefix
if [[ "x$exec_prefix" = xNONE -a "x$prefix" = xNONE ]];
then exec_prefix="";
@@ -117,6 +141,17 @@ Note: (n)curses also seems to work as a substitute for termcap. This was
)
fi
dnl Check for dlopen
AC_CHECK_LIB(dl, dlopen, HAVE_LIBDL=yes, HAVE_LIBDL=no)
if test x$HAVE_LIBDL = xyes; then
CFLAGS="$CFLAGS -DHAVE_LIBDL"
LIBS="-ldl $LIBS"
fi
dnl Check for getopt
AC_CHECK_HEADERS(getopt.h, CFLAGS="$CFLAGS -DHAVE_GETOPTLONG")
dnl Check for readline (Shamelessly copied from parted 1.4.17)
if test x$READLINE = xyes; then
AC_CHECK_LIB(readline, readline, ,
@@ -130,8 +165,8 @@ package as well (which may be called readline-devel or something similar).
)
exit
)
AC_CHECK_FUNC(rl_completion_matches, HAVE_RL_COMPLETION_MATCHES=yes,
HAVE_RL_COMPLETION_MATCHES=no)
AC_CHECK_FUNC(rl_completion_matches, CFLAGS="$CFLAGS -DHAVE_RL_COMPLETION_MATCHES")
fi
if test "-f VERSION"; then
@@ -142,14 +177,15 @@ fi
AC_SUBST(JOBS)
AC_SUBST(STATIC_LINK)
AC_SUBST(READLINE)
AC_SUBST(LVM1)
AC_SUBST(HAVE_RL_COMPLETION_MATCHES)
AC_SUBST(OWNER)
AC_SUBST(GROUP)
AC_SUBST(CFLAGS)
AC_SUBST(LIBS)
AC_SUBST(LVM_VERSION)
AC_SUBST(DEBUG)
AC_SUBST(DEVMAPPER)
AC_SUBST(HAVE_LIBDL)
dnl First and last lines should not contain files to generate in order to
dnl keep utility scripts running properly
AC_OUTPUT( \

10
debian/changelog vendored
View File

@@ -1,3 +1,13 @@
lvm2 (1.95.15-1) unstable; urgency=low
* New upstream release.
* Remove undocumented manpage symlinks.
* Update description to be more informative. (Closes: #173499)
* Add kernel-patch-device-mapper suggestion.
* Update standards version.
-- Andres Salomon <dilinger@mp3revolution.net> Sun, 16 Feb 2002 04:21:26 -0400
lvm2 (1.95.11-1) unstable; urgency=low
* New upstream release. (Closes: #171436)

8
debian/control vendored
View File

@@ -3,7 +3,7 @@ Section: admin
Priority: optional
Maintainer: Andres Salomon <dilinger@mp3revolution.net>
Build-Depends: debhelper (>> 3.0.0), libdevmapper-dev (>= 0.96.04), libreadline4-dev
Standards-Version: 3.5.2
Standards-Version: 3.5.8.0
Package: lvm2
Architecture: any
@@ -11,10 +11,14 @@ Depends: ${shlibs:Depends}
Conflicts: lvm10, lvm-common
Replaces: lvm10, lvm-common
Provides: lvm-binaries
Suggests: dmsetup
Suggests: dmsetup, kernel-patch-device-mapper
Description: The Linux Logical Volume Manager
This is LVM2, the rewrite of The Linux Logical Volume Manager. LVM
supports enterprise level volume management of disk and disk subsystems
by grouping arbitrary disks into volume groups. The total capacity of
volume groups can be allocated to logical volumes, which are accessed as
regular block devices.
.
LVM2 is currently stable, but has some unimplemented features (most notably,
pvmove and e2fsadm). It is not yet recommended for production use. It is
backwards-compatible with LVM1 (lvm10), and requires Linux kernel 2.4.

1
debian/rules vendored
View File

@@ -102,7 +102,6 @@ binary-arch: build install
dh_installcron
dh_installman
dh_installinfo
dh_undocumented
dh_installchangelogs
dh_strip
dh_link

13
debian/undocumented vendored
View File

@@ -1,13 +0,0 @@
e2fsadm.8
lvmdiskscan.8
lvmsadc.8
lvmsar.8
lvresize.8
pvdata.8
pvmove.8
pvresize.8
version.8
vgexport.8
vgimport.8
vgmknodes.8
vgsplit.8

View File

@@ -104,6 +104,10 @@ log {
# indent = 0
# command_names = 1
# prefix = " -- "
# Set this if you want log messages during activation.
# Don't use this in low memory situations (can deadlock).
# activation = 0
}
# Configuration of metadata backups and archiving. In LVM2 when we
@@ -193,6 +197,26 @@ global {
# library_dir = "/lib"
}
activation {
# Device used in place of missing stripes if activating incomplete volume.
# For now, you need to set this up yourself first (e.g. with 'dmsetup')
# For example, you could make it return I/O errors using the 'error'
# target or make it return zeros.
missing_stripe_filler = "/dev/ioerror"
# Size (in KB) of each copy operation when mirroring
mirror_region_size = 512
# How much stack (in KB) to reserve for use while devices suspended
reserved_stack = 256
# How much memory (in KB) to reserve for use while devices suspended
reserved_memory = 8192
# Nice value used while devices suspended
process_priority = -18
}
####################
# Advanced section #
@@ -220,7 +244,8 @@ global {
# preferably on different (non-LV) filesystems, and with no other
# on-disk metadata (pvmetadatacopies = 0). Or this can be in
# addition to on-disk metadata areas.
# The feature was originally added to simplify testing.
# The feature was originally added to simplify testing and is not
# supported under low memory situations - the machine could lock up.
#
# Never edit any files in these directories by hand unless you
# you are absolutely sure you know what you are doing! Use

View File

@@ -1,5 +1,5 @@
../lib/activate/activate.h
../lib/cache/cache.h
../lib/cache/lvmcache.h
../lib/commands/errors.h
../lib/commands/toolcontext.h
../lib/config/config.h
@@ -24,6 +24,7 @@
../lib/log/log.h
../lib/metadata/metadata.h
../lib/mm/dbg_malloc.h
../lib/mm/memlock.h
../lib/mm/pool.h
../lib/mm/xlate.h
../lib/misc/crc.h

View File

@@ -14,9 +14,7 @@ endif
SOURCES=\
activate/activate.c \
activate/dev_manager.c \
activate/fs.c \
cache/cache.c \
cache/lvmcache.c \
commands/toolcontext.c \
config/config.c \
datastruct/bitset.c \
@@ -38,7 +36,6 @@ SOURCES=\
format_text/import_vsn1.c \
format_text/text_label.c \
label/label.c \
locking/external_locking.c \
locking/file_locking.c \
locking/locking.c \
locking/no_locking.c \
@@ -46,12 +43,13 @@ SOURCES=\
metadata/lv_manip.c \
metadata/merge.c \
metadata/metadata.c \
metadata/mirror.c \
metadata/pv_map.c \
metadata/snapshot_manip.c \
misc/crc.c \
misc/lvm-file.c \
misc/lvm-string.c \
misc/sharedlib.c \
mm/memlock.c \
mm/pool.c \
regex/matcher.c \
regex/parse_rx.c \
@@ -75,6 +73,18 @@ ifeq ("@DEBUG@", "yes")
mm/dbg_malloc.c
endif
ifeq ("@DEVMAPPER@", "yes")
SOURCES+=\
activate/dev_manager.c \
activate/fs.c
endif
ifeq ("@HAVE_LIBDL@", "yes")
SOURCES+=\
locking/external_locking.c \
misc/sharedlib.c
endif
TARGETS=liblvm.a
include ../make.tmpl

View File

@@ -7,6 +7,7 @@
#include "lib.h"
#include "metadata.h"
#include "activate.h"
#include "memlock.h"
#include "display.h"
#include "fs.h"
#include "lvm-string.h"
@@ -15,11 +16,74 @@
#include "dev_manager.h"
#include <limits.h>
#include <linux/kdev_t.h>
#include <fcntl.h>
#include <unistd.h>
#define _skip(fmt, args...) log_very_verbose("Skipping: " fmt , ## args)
#ifndef DEVMAPPER_SUPPORT
void set_activation(int act)
{
if (act)
log_error("Compiled without libdevmapper support. "
"Can't enable activation.");
}
int activation(void)
{
return 0;
}
int library_version(char *version, size_t size)
{
return 0;
}
int driver_version(char *version, size_t size)
{
return 0;
}
int lv_info(const struct logical_volume *lv, struct lvinfo *info)
{
return 0;
}
int lv_snapshot_percent(struct logical_volume *lv, float *percent)
{
return 0;
}
int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
uint32_t *event_nr)
{
return 0;
}
int lvs_in_vg_activated(struct volume_group *vg)
{
return 0;
}
int lvs_in_vg_opened(struct volume_group *vg)
{
return 0;
}
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)
{
return 1;
}
int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
{
return 1;
}
int lv_activate(struct cmd_context *cmd, const char *lvid_s)
{
return 1;
}
void activation_exit(void)
{
return;
}
#else /* DEVMAPPER_SUPPORT */
static int _activation = 1;
void set_activation(int act)
@@ -82,22 +146,30 @@ int driver_version(char *version, size_t size)
/*
* Returns 1 if info structure populated, else 0 on failure.
*/
int lv_info(const struct logical_volume *lv, struct dm_info *info)
int lv_info(const struct logical_volume *lv, struct lvinfo *info)
{
int r;
struct dev_manager *dm;
struct dm_info dminfo;
if (!activation())
return 0;
if (!(dm = dev_manager_create(lv->vg->name))) {
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
stack;
return 0;
}
if (!(r = dev_manager_info(dm, lv, info)))
if (!(r = dev_manager_info(dm, lv, &dminfo)))
stack;
info->exists = dminfo.exists;
info->suspended = dminfo.suspended;
info->open_count = dminfo.open_count;
info->major = dminfo.major;
info->minor = dminfo.minor;
info->read_only = dminfo.read_only;
dev_manager_destroy(dm);
return r;
}
@@ -113,7 +185,7 @@ int lv_snapshot_percent(struct logical_volume *lv, float *percent)
if (!activation())
return 0;
if (!(dm = dev_manager_create(lv->vg->name))) {
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
stack;
return 0;
}
@@ -126,9 +198,32 @@ int lv_snapshot_percent(struct logical_volume *lv, float *percent)
return r;
}
/* FIXME Merge with snapshot_percent */
int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
uint32_t *event_nr)
{
int r;
struct dev_manager *dm;
if (!activation())
return 0;
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
stack;
return 0;
}
if (!(r = dev_manager_mirror_percent(dm, lv, wait, percent, event_nr)))
stack;
dev_manager_destroy(dm);
return r;
}
static int _lv_active(struct logical_volume *lv)
{
struct dm_info info;
struct lvinfo info;
if (!lv_info(lv, &info)) {
stack;
@@ -140,7 +235,7 @@ static int _lv_active(struct logical_volume *lv)
static int _lv_open_count(struct logical_volume *lv)
{
struct dm_info info;
struct lvinfo info;
if (!lv_info(lv, &info)) {
stack;
@@ -156,7 +251,7 @@ static int _lv_activate(struct logical_volume *lv)
int r;
struct dev_manager *dm;
if (!(dm = dev_manager_create(lv->vg->name))) {
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
stack;
return 0;
}
@@ -173,7 +268,7 @@ static int _lv_deactivate(struct logical_volume *lv)
int r;
struct dev_manager *dm;
if (!(dm = dev_manager_create(lv->vg->name))) {
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
stack;
return 0;
}
@@ -190,7 +285,7 @@ static int _lv_suspend(struct logical_volume *lv)
int r;
struct dev_manager *dm;
if (!(dm = dev_manager_create(lv->vg->name))) {
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
stack;
return 0;
}
@@ -244,7 +339,7 @@ int lvs_in_vg_opened(struct volume_group *vg)
int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
{
struct logical_volume *lv;
struct dm_info info;
struct lvinfo info;
if (!activation())
return 1;
@@ -252,12 +347,9 @@ int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
if (!(lv = lv_from_lvid(cmd, lvid_s)))
return 0;
if (!activation())
return 1;
if (test_mode()) {
_skip("Suspending '%s'.", lv->name);
return 0;
return 1;
}
if (!lv_info(lv, &info)) {
@@ -265,8 +357,15 @@ int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
return 0;
}
if (info.exists && !info.suspended)
return _lv_suspend(lv);
if (!info.exists || info.suspended)
return 1;
memlock_inc();
if (!_lv_suspend(lv)) {
memlock_dec();
fs_unlock();
return 0;
}
return 1;
}
@@ -274,7 +373,7 @@ int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
{
struct logical_volume *lv;
struct dm_info info;
struct lvinfo info;
if (!activation())
return 1;
@@ -284,7 +383,7 @@ int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
if (test_mode()) {
_skip("Resuming '%s'.", lv->name);
return 0;
return 1;
}
if (!lv_info(lv, &info)) {
@@ -292,8 +391,14 @@ int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
return 0;
}
if (info.exists && info.suspended)
return _lv_activate(lv);
if (!info.exists || !info.suspended)
return 1;
if (!_lv_activate(lv))
return 0;
memlock_dec();
fs_unlock();
return 1;
}
@@ -301,7 +406,8 @@ int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
{
struct logical_volume *lv;
struct dm_info info;
struct lvinfo info;
int r;
if (!activation())
return 1;
@@ -311,7 +417,7 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
if (test_mode()) {
_skip("Deactivating '%s'.", lv->name);
return 0;
return 1;
}
if (!lv_info(lv, &info)) {
@@ -319,16 +425,22 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
return 0;
}
if (info.exists)
return _lv_deactivate(lv);
if (!info.exists)
return 1;
return 1;
memlock_inc();
r = _lv_deactivate(lv);
memlock_dec();
fs_unlock();
return r;
}
int lv_activate(struct cmd_context *cmd, const char *lvid_s)
{
struct logical_volume *lv;
struct dm_info info;
struct lvinfo info;
int r;
if (!activation())
return 1;
@@ -338,7 +450,7 @@ int lv_activate(struct cmd_context *cmd, const char *lvid_s)
if (test_mode()) {
_skip("Activating '%s'.", lv->name);
return 0;
return 1;
}
if (!lv_info(lv, &info)) {
@@ -346,8 +458,19 @@ int lv_activate(struct cmd_context *cmd, const char *lvid_s)
return 0;
}
if (!info.exists || info.suspended)
return _lv_activate(lv);
if (info.exists && !info.suspended)
return 1;
return 1;
memlock_inc();
r = _lv_activate(lv);
memlock_dec();
fs_unlock();
return r;
}
void activation_exit(void)
{
dev_manager_exit();
}
#endif

View File

@@ -8,7 +8,19 @@
#define LVM_ACTIVATE_H
#include "metadata.h"
#include <libdevmapper.h>
#ifdef DEVMAPPER_SUPPORT
# include <libdevmapper.h>
#endif
struct lvinfo {
int exists;
int suspended;
unsigned int open_count;
int major;
int minor;
int read_only;
};
void set_activation(int activation);
int activation(void);
@@ -16,28 +28,23 @@ int activation(void);
int driver_version(char *version, size_t size);
int library_version(char *version, size_t size);
/*
* Returns 1 if info structure has been populated, else 0.
*/
int lv_info(const struct logical_volume *lv, struct dm_info *info);
/*
* Returns 1 if percent has been set, else 0.
*/
int lv_snapshot_percent(struct logical_volume *lv, float *percent);
void activation_exit(void);
/*
* These should eventually use config file
* to determine whether or not to activate
*/
int lv_suspend_if_active(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_deactivate(struct cmd_context *cmd, const char *lvid_s);
/*
* FIXME:
* I don't like the *lvs_in_vg* function names.
* Returns 1 if info structure has been populated, else 0.
*/
int lv_info(const struct logical_volume *lv, struct lvinfo *info);
/*
* Returns 1 if percent has been set, else 0.
*/
int lv_snapshot_percent(struct logical_volume *lv, float *percent);
int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
uint32_t *event_nr);
/*
* Return number of LVs in the VG that are active.

File diff suppressed because it is too large Load Diff

View File

@@ -8,16 +8,18 @@
#define _LVM_DEV_MANAGER_H
#include "metadata.h"
#include <libdevmapper.h>
#include "config.h"
struct dev_manager;
struct dm_info;
/*
* Constructor and destructor.
*/
struct dev_manager *dev_manager_create(const char *vg_name);
struct dev_manager *dev_manager_create(const char *vg_name,
struct config_tree *cf);
void dev_manager_destroy(struct dev_manager *dm);
void dev_manager_exit(void);
/*
* The device handler is responsible for creating all the layered
@@ -29,6 +31,9 @@ int dev_manager_info(struct dev_manager *dm, const struct logical_volume *lv,
struct dm_info *info);
int dev_manager_snapshot_percent(struct dev_manager *dm,
struct logical_volume *lv, float *percent);
int dev_manager_mirror_percent(struct dev_manager *dm,
struct logical_volume *lv, int wait,
float *percent, uint32_t *event_nr);
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);

View File

@@ -9,6 +9,7 @@
#include "toolcontext.h"
#include "lvm-string.h"
#include "lvm-file.h"
#include "memlock.h"
#include <sys/stat.h>
#include <fcntl.h>
@@ -17,12 +18,12 @@
#include <dirent.h>
#include <libdevmapper.h>
static int _mk_dir(struct volume_group *vg)
static int _mk_dir(const char *dev_dir, const char *vg_name)
{
char vg_path[PATH_MAX];
if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s",
vg->cmd->dev_dir, vg->name) == -1) {
dev_dir, vg_name) == -1) {
log_error("Couldn't construct name of volume "
"group directory.");
return 0;
@@ -40,12 +41,12 @@ static int _mk_dir(struct volume_group *vg)
return 1;
}
static int _rm_dir(struct volume_group *vg)
static int _rm_dir(const char *dev_dir, const char *vg_name)
{
char vg_path[PATH_MAX];
if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s",
vg->cmd->dev_dir, vg->name) == -1) {
dev_dir, vg_name) == -1) {
log_error("Couldn't construct name of volume "
"group directory.");
return 0;
@@ -93,37 +94,38 @@ static void _rm_blks(const char *dir)
}
}
static int _mk_link(struct logical_volume *lv, const char *dev)
static int _mk_link(const char *dev_dir, const char *vg_name,
const char *lv_name, const char *dev)
{
char lv_path[PATH_MAX], link_path[PATH_MAX], lvm1_group_path[PATH_MAX];
char vg_path[PATH_MAX];
struct stat buf;
if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s",
lv->vg->cmd->dev_dir, lv->vg->name) == -1) {
dev_dir, vg_name) == -1) {
log_error("Couldn't create path for volume group dir %s",
lv->vg->name);
vg_name);
return 0;
}
if (lvm_snprintf(lv_path, sizeof(lv_path), "%s/%s", vg_path,
lv->name) == -1) {
lv_name) == -1) {
log_error("Couldn't create source pathname for "
"logical volume link %s", lv->name);
"logical volume link %s", lv_name);
return 0;
}
if (lvm_snprintf(link_path, sizeof(link_path), "%s/%s",
dm_dir(), dev) == -1) {
log_error("Couldn't create destination pathname for "
"logical volume link for %s", lv->name);
"logical volume link for %s", lv_name);
return 0;
}
if (lvm_snprintf(lvm1_group_path, sizeof(lvm1_group_path), "%s/group",
vg_path) == -1) {
log_error("Couldn't create pathname for LVM1 group file for %s",
lv->vg->name);
vg_name);
return 0;
}
@@ -167,13 +169,14 @@ static int _mk_link(struct logical_volume *lv, const char *dev)
return 1;
}
static int _rm_link(struct logical_volume *lv, const char *lv_name)
static int _rm_link(const char *dev_dir, const char *vg_name,
const char *lv_name)
{
struct stat buf;
char lv_path[PATH_MAX];
if (lvm_snprintf(lv_path, sizeof(lv_path), "%s%s/%s",
lv->vg->cmd->dev_dir, lv->vg->name, lv_name) == -1) {
dev_dir, vg_name, lv_name) == -1) {
log_error("Couldn't determine link pathname.");
return 0;
}
@@ -192,35 +195,143 @@ static int _rm_link(struct logical_volume *lv, const char *lv_name)
return 1;
}
int fs_add_lv(struct logical_volume *lv, const char *dev)
typedef enum {
FS_ADD,
FS_DEL,
FS_RENAME
} fs_op_t;
static int _do_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
const char *lv_name, const char *dev,
const char *old_lv_name)
{
if (!_mk_dir(lv->vg) || !_mk_link(lv, dev)) {
stack;
return 0;
switch (type) {
case FS_ADD:
if (!_mk_dir(dev_dir, vg_name) ||
!_mk_link(dev_dir, vg_name, lv_name, dev)) {
stack;
return 0;
}
break;
case FS_DEL:
if (!_rm_link(dev_dir, vg_name, lv_name) ||
!_rm_dir(dev_dir, vg_name)) {
stack;
return 0;
}
break;
/* FIXME Use rename() */
case FS_RENAME:
if (old_lv_name && !_rm_link(dev_dir, vg_name, old_lv_name))
stack;
if (!_mk_link(dev_dir, vg_name, lv_name, dev))
stack;
}
return 1;
}
static LIST_INIT(_fs_ops);
struct fs_op_parms {
struct list list;
fs_op_t type;
char *dev_dir;
char *vg_name;
char *lv_name;
char *dev;
char *old_lv_name;
char names[0];
};
static void _store_str(char **pos, char **ptr, const char *str)
{
strcpy(*pos, str);
*ptr = *pos;
*pos += strlen(*ptr) + 1;
}
static int _stack_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
const char *lv_name, const char *dev,
const char *old_lv_name)
{
struct fs_op_parms *fsp;
size_t len = strlen(dev_dir) + strlen(vg_name) + strlen(lv_name) +
strlen(dev) + strlen(old_lv_name) + 5;
char *pos;
if (!(fsp = dbg_malloc(sizeof(*fsp) + len))) {
log_error("No space to stack fs operation");
return 0;
}
pos = fsp->names;
fsp->type = type;
_store_str(&pos, &fsp->dev_dir, dev_dir);
_store_str(&pos, &fsp->vg_name, vg_name);
_store_str(&pos, &fsp->lv_name, lv_name);
_store_str(&pos, &fsp->dev, dev);
_store_str(&pos, &fsp->old_lv_name, old_lv_name);
list_add(&_fs_ops, &fsp->list);
return 1;
}
static void _pop_fs_ops(void)
{
struct list *fsph, *fspht;
struct fs_op_parms *fsp;
list_iterate_safe(fsph, fspht, &_fs_ops) {
fsp = list_item(fsph, struct fs_op_parms);
_do_fs_op(fsp->type, fsp->dev_dir, fsp->vg_name, fsp->lv_name,
fsp->dev, fsp->old_lv_name);
list_del(&fsp->list);
dbg_free(fsp);
}
}
static int _fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
const char *lv_name, const char *dev, const char *old_lv_name)
{
if (memlock()) {
if (!_stack_fs_op(type, dev_dir, vg_name, lv_name, dev,
old_lv_name)) {
stack;
return 0;
}
return 1;
}
return _do_fs_op(type, dev_dir, vg_name, lv_name, dev, old_lv_name);
}
int fs_add_lv(struct logical_volume *lv, const char *dev)
{
return _fs_op(FS_ADD, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
dev, "");
}
int fs_del_lv(struct logical_volume *lv)
{
if (!_rm_link(lv, lv->name) || !_rm_dir(lv->vg)) {
stack;
return 0;
}
return 1;
return _fs_op(FS_DEL, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
"", "");
}
/* FIXME Use rename() */
int fs_rename_lv(struct logical_volume *lv,
const char *dev, const char *old_name)
{
if (old_name && !_rm_link(lv, old_name))
stack;
if (!_mk_link(lv, dev))
stack;
return 1;
return _fs_op(FS_RENAME, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
dev, old_name);
}
void fs_unlock(void)
{
if (!memlock()) {
dm_lib_release();
_pop_fs_ops();
}
}

View File

@@ -18,5 +18,6 @@ int fs_add_lv(struct logical_volume *lv, const char *dev);
int fs_del_lv(struct logical_volume *lv);
int fs_rename_lv(struct logical_volume *lv,
const char *dev, const char *old_name);
void fs_unlock(void);
#endif

View File

@@ -6,22 +6,23 @@
*/
#include "lib.h"
#include "cache.h"
#include "lvmcache.h"
#include "hash.h"
#include "toolcontext.h"
#include "dev-cache.h"
#include "metadata.h"
#include "filter.h"
#include <linux/kdev_t.h>
#include "memlock.h"
static struct hash_table *_pvid_hash = NULL;
static struct hash_table *_vgid_hash = NULL;
static struct hash_table *_vgname_hash = NULL;
static struct hash_table *_lock_hash = NULL;
static struct list _vginfos;
int _has_scanned = 0;
static int _has_scanned = 0;
static int _vgs_locked = 0;
int cache_init(void)
int lvmcache_init(void)
{
list_init(&_vginfos);
@@ -34,12 +35,52 @@ int cache_init(void)
if (!(_pvid_hash = hash_create(128)))
return 0;
if (!(_lock_hash = hash_create(128)))
return 0;
return 1;
}
struct cache_vginfo *vginfo_from_vgname(const char *vgname)
void lvmcache_lock_vgname(const char *vgname, int read_only)
{
struct cache_vginfo *vginfo;
if (!_lock_hash && !lvmcache_init()) {
log_error("Internal cache initialisation failed");
return;
}
if (!hash_insert(_lock_hash, vgname, (void *) 1))
log_error("Cache locking failure for %s", vgname);
_vgs_locked++;
}
static int _vgname_is_locked(const char *vgname) __attribute__ ((unused));
static int _vgname_is_locked(const char *vgname)
{
if (!_lock_hash)
return 0;
return hash_lookup(_lock_hash, vgname) ? 1 : 0;
}
void lvmcache_unlock_vgname(const char *vgname)
{
/* FIXME: Clear all CACHE_LOCKED flags in this vg */
hash_remove(_lock_hash, vgname);
/* FIXME Do this per-VG */
if (!--_vgs_locked)
dev_close_all();
}
int vgs_locked(void)
{
return _vgs_locked;
}
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname)
{
struct lvmcache_vginfo *vginfo;
if (!_vgname_hash)
return NULL;
@@ -52,7 +93,7 @@ struct cache_vginfo *vginfo_from_vgname(const char *vgname)
const struct format_type *fmt_from_vgname(const char *vgname)
{
struct cache_vginfo *vginfo;
struct lvmcache_vginfo *vginfo;
if (!(vginfo = vginfo_from_vgname(vgname)))
return NULL;
@@ -60,33 +101,42 @@ const struct format_type *fmt_from_vgname(const char *vgname)
return vginfo->fmt;
}
struct cache_vginfo *vginfo_from_vgid(const char *vgid)
struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid)
{
struct cache_vginfo *vginfo;
struct lvmcache_vginfo *vginfo;
char id[ID_LEN + 1];
if (!_vgid_hash || !vgid)
return NULL;
if (!(vginfo = hash_lookup_fixed(_vgid_hash, vgid, ID_LEN)))
/* vgid not necessarily NULL-terminated */
strncpy(&id[0], vgid, ID_LEN);
id[ID_LEN] = '\0';
if (!(vginfo = hash_lookup(_vgid_hash, id)))
return NULL;
return vginfo;
}
struct cache_info *info_from_pvid(const char *pvid)
struct lvmcache_info *info_from_pvid(const char *pvid)
{
struct cache_info *info;
struct lvmcache_info *info;
char id[ID_LEN + 1];
if (!_pvid_hash || !pvid)
return NULL;
if (!(info = hash_lookup_fixed(_pvid_hash, pvid, ID_LEN)))
strncpy(&id[0], pvid, ID_LEN);
id[ID_LEN] = '\0';
if (!(info = hash_lookup(_pvid_hash, id)))
return NULL;
return info;
}
static void _rescan_entry(struct cache_info *info)
static void _rescan_entry(struct lvmcache_info *info)
{
struct label *label;
@@ -101,7 +151,7 @@ static int _scan_invalid(void)
return 1;
}
int cache_label_scan(struct cmd_context *cmd, int full_scan)
int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
{
struct label *label;
struct dev_iter *iter;
@@ -118,7 +168,7 @@ int cache_label_scan(struct cmd_context *cmd, int full_scan)
_scanning_in_progress = 1;
if (!_vgname_hash && !cache_init()) {
if (!_vgname_hash && !lvmcache_init()) {
log_error("Internal cache initialisation failed");
goto out;
}
@@ -155,12 +205,12 @@ int cache_label_scan(struct cmd_context *cmd, int full_scan)
return r;
}
struct list *cache_get_vgnames(struct cmd_context *cmd, int full_scan)
struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
{
struct list *vgih, *vgnames;
struct str_list *sl;
cache_label_scan(cmd, full_scan);
lvmcache_label_scan(cmd, full_scan);
if (!(vgnames = pool_alloc(cmd->mem, sizeof(struct list)))) {
log_error("vgnames list allocation failed");
@@ -176,7 +226,7 @@ struct list *cache_get_vgnames(struct cmd_context *cmd, int full_scan)
}
if (!(sl->str = pool_strdup(cmd->mem,
list_item(vgih,
struct cache_vginfo)->
struct lvmcache_vginfo)->
vgname))) {
log_error("vgname allocation failed");
return NULL;
@@ -190,34 +240,37 @@ struct list *cache_get_vgnames(struct cmd_context *cmd, int full_scan)
struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
{
struct label *label;
struct cache_info *info;
struct lvmcache_info *info;
/* Already cached ? */
if ((info = info_from_pvid((char *) pvid))) {
if (label_read(info->dev, &label)) {
info = (struct cache_info *) label->info;
info = (struct lvmcache_info *) label->info;
if (id_equal(pvid, (struct id *) &info->dev->pvid))
return info->dev;
}
}
cache_label_scan(cmd, 0);
lvmcache_label_scan(cmd, 0);
/* Try again */
if ((info = info_from_pvid((char *) pvid))) {
if (label_read(info->dev, &label)) {
info = (struct cache_info *) label->info;
info = (struct lvmcache_info *) label->info;
if (id_equal(pvid, (struct id *) &info->dev->pvid))
return info->dev;
}
}
cache_label_scan(cmd, 1);
if (memlock())
return NULL;
lvmcache_label_scan(cmd, 1);
/* Try again */
if ((info = info_from_pvid((char *) pvid))) {
if (label_read(info->dev, &label)) {
info = (struct cache_info *) label->info;
info = (struct lvmcache_info *) label->info;
if (id_equal(pvid, (struct id *) &info->dev->pvid))
return info->dev;
}
@@ -226,7 +279,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
return NULL;
}
static void _drop_vginfo(struct cache_info *info)
static void _drop_vginfo(struct lvmcache_info *info)
{
if (!list_empty(&info->list)) {
list_del(&info->list);
@@ -247,7 +300,7 @@ static void _drop_vginfo(struct cache_info *info)
}
/* Unused
void cache_del(struct cache_info *info)
void lvmcache_del(struct lvmcache_info *info)
{
if (info->dev->pvid[0] && _pvid_hash)
hash_remove(_pvid_hash, info->dev->pvid);
@@ -261,7 +314,7 @@ void cache_del(struct cache_info *info)
return;
} */
static int _cache_update_pvid(struct cache_info *info, const char *pvid)
static int _lvmcache_update_pvid(struct lvmcache_info *info, const char *pvid)
{
if (!strcmp(info->dev->pvid, pvid))
return 1;
@@ -270,14 +323,14 @@ static int _cache_update_pvid(struct cache_info *info, const char *pvid)
}
strncpy(info->dev->pvid, pvid, sizeof(info->dev->pvid));
if (!hash_insert(_pvid_hash, pvid, info)) {
log_error("_cache_update: pvid insertion failed: %s", pvid);
log_error("_lvmcache_update: pvid insertion failed: %s", pvid);
return 0;
}
return 1;
}
static int _cache_update_vgid(struct cache_info *info, const char *vgid)
static int _lvmcache_update_vgid(struct lvmcache_info *info, const char *vgid)
{
if (!vgid || !info->vginfo || !strncmp(info->vginfo->vgid, vgid,
sizeof(info->vginfo->vgid)))
@@ -290,18 +343,18 @@ static int _cache_update_vgid(struct cache_info *info, const char *vgid)
strncpy(info->vginfo->vgid, vgid, sizeof(info->vginfo->vgid));
info->vginfo->vgid[sizeof(info->vginfo->vgid) - 1] = '\0';
if (!hash_insert(_vgid_hash, vgid, info->vginfo)) {
log_error("_cache_update: vgid hash insertion failed: %s",
vgid);
if (!hash_insert(_vgid_hash, info->vginfo->vgid, info->vginfo)) {
log_error("_lvmcache_update: vgid hash insertion failed: %s",
info->vginfo->vgid);
return 0;
}
return 1;
}
int cache_update_vgname(struct cache_info *info, const char *vgname)
int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
{
struct cache_vginfo *vginfo;
struct lvmcache_vginfo *vginfo;
/* If vgname is NULL and we don't already have a vgname,
* assume ORPHAN - we want every entry to have a vginfo
@@ -319,7 +372,7 @@ int cache_update_vgname(struct cache_info *info, const char *vgname)
/* Get existing vginfo or create new one */
if (!(vginfo = vginfo_from_vgname(vgname))) {
if (!(vginfo = dbg_malloc(sizeof(*vginfo)))) {
log_error("cache_update_vgname: list alloc failed");
log_error("lvmcache_update_vgname: list alloc failed");
return 0;
}
memset(vginfo, 0, sizeof(*vginfo));
@@ -352,11 +405,11 @@ int cache_update_vgname(struct cache_info *info, const char *vgname)
return 1;
}
int cache_update_vg(struct volume_group *vg)
int lvmcache_update_vg(struct volume_group *vg)
{
struct list *pvh;
struct physical_volume *pv;
struct cache_info *info;
struct lvmcache_info *info;
char pvid_s[ID_LEN + 1];
int vgid_updated = 0;
@@ -367,9 +420,9 @@ int cache_update_vg(struct volume_group *vg)
strncpy(pvid_s, (char *) &pv->id, sizeof(pvid_s) - 1);
/* FIXME Could pv->dev->pvid ever be different? */
if ((info = info_from_pvid(pvid_s))) {
cache_update_vgname(info, vg->name);
lvmcache_update_vgname(info, vg->name);
if (!vgid_updated) {
_cache_update_vgid(info, (char *) &vg->id);
_lvmcache_update_vgid(info, (char *) &vg->id);
vgid_updated = 1;
}
}
@@ -378,15 +431,15 @@ int cache_update_vg(struct volume_group *vg)
return 1;
}
struct cache_info *cache_add(struct labeller *labeller, const char *pvid,
struct device *dev,
const char *vgname, const char *vgid)
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
struct device *dev,
const char *vgname, const char *vgid)
{
struct label *label;
struct cache_info *existing, *info;
struct lvmcache_info *existing, *info;
char pvid_s[ID_LEN + 1];
if (!_vgname_hash && !cache_init()) {
if (!_vgname_hash && !lvmcache_init()) {
log_error("Internal cache initialisation failed");
return NULL;
}
@@ -401,7 +454,7 @@ struct cache_info *cache_add(struct labeller *labeller, const char *pvid,
return NULL;
}
if (!(info = dbg_malloc(sizeof(*info)))) {
log_error("cache_info allocation failed");
log_error("lvmcache_info allocation failed");
label_destroy(label);
return NULL;
}
@@ -449,7 +502,7 @@ struct cache_info *cache_add(struct labeller *labeller, const char *pvid,
info->fmt = (const struct format_type *) labeller->private;
info->status |= CACHE_INVALID;
if (!_cache_update_pvid(info, pvid_s)) {
if (!_lvmcache_update_pvid(info, pvid_s)) {
if (!existing) {
dbg_free(info);
label_destroy(label);
@@ -457,7 +510,7 @@ struct cache_info *cache_add(struct labeller *labeller, const char *pvid,
return NULL;
}
if (!cache_update_vgname(info, vgname)) {
if (!lvmcache_update_vgname(info, vgname)) {
if (!existing) {
hash_remove(_pvid_hash, pvid_s);
strcpy(info->dev->pvid, "");
@@ -467,14 +520,14 @@ struct cache_info *cache_add(struct labeller *labeller, const char *pvid,
return NULL;
}
if (!_cache_update_vgid(info, vgid))
if (!_lvmcache_update_vgid(info, vgid))
/* Non-critical */
stack;
return info;
}
static void _cache_destroy_entry(struct cache_info *info)
static void _lvmcache_destroy_entry(struct lvmcache_info *info)
{
if (!list_empty(&info->list))
list_del(&info->list);
@@ -483,14 +536,19 @@ static void _cache_destroy_entry(struct cache_info *info)
dbg_free(info);
}
static void _cache_destroy_vgnamelist(struct cache_vginfo *vginfo)
static void _lvmcache_destroy_vgnamelist(struct lvmcache_vginfo *vginfo)
{
if (vginfo->vgname)
dbg_free(vginfo->vgname);
dbg_free(vginfo);
}
void cache_destroy(void)
static void _lvmcache_destroy_lockname(int present)
{
/* Nothing to do */
}
void lvmcache_destroy(void)
{
_has_scanned = 0;
@@ -500,15 +558,23 @@ void cache_destroy(void)
}
if (_pvid_hash) {
hash_iter(_pvid_hash, (iterate_fn) _cache_destroy_entry);
hash_iter(_pvid_hash, (iterate_fn) _lvmcache_destroy_entry);
hash_destroy(_pvid_hash);
_pvid_hash = NULL;
}
if (_vgname_hash) {
hash_iter(_vgname_hash, (iterate_fn) _cache_destroy_vgnamelist);
hash_iter(_vgname_hash,
(iterate_fn) _lvmcache_destroy_vgnamelist);
hash_destroy(_vgname_hash);
_vgname_hash = NULL;
}
if (_lock_hash) {
hash_iter(_lock_hash, (iterate_fn) _lvmcache_destroy_lockname);
hash_destroy(_lock_hash);
_lock_hash = NULL;
}
list_init(&_vginfos);
}

View File

@@ -9,33 +9,31 @@
#define _LVM_CACHE_H
#include "dev-cache.h"
#include "list.h"
#include "uuid.h"
#include "label.h"
#include "metadata.h"
#include <sys/types.h>
#define ORPHAN ""
#define CACHE_INVALID 0x00000001
#define CACHE_INVALID 0x00000001
#define CACHE_LOCKED 0x00000002
/* LVM specific per-volume info */
/* Eventual replacement for struct physical_volume perhaps? */
struct cache_vginfo {
struct lvmcache_vginfo {
struct list list; /* Join these vginfos together */
struct list infos; /* List head for cache_infos */
struct list infos; /* List head for lvmcache_infos */
char *vgname; /* "" == orphan */
char vgid[ID_LEN + 1];
const struct format_type *fmt;
};
struct cache_info {
struct lvmcache_info {
struct list list; /* Join VG members together */
struct list mdas; /* list head for metadata areas */
struct list das; /* list head for data areas */
struct cache_vginfo *vginfo; /* NULL == unknown */
struct lvmcache_vginfo *vginfo; /* NULL == unknown */
struct label *label;
const struct format_type *fmt;
struct device *dev;
@@ -43,31 +41,35 @@ struct cache_info {
uint32_t status;
};
int cache_init(void);
void cache_destroy(void);
int lvmcache_init(void);
void lvmcache_destroy(void);
/* Set full_scan to 1 to reread every filtered device label */
int cache_label_scan(struct cmd_context *cmd, int full_scan);
int lvmcache_label_scan(struct cmd_context *cmd, int full_scan);
/* Add/delete a device */
struct cache_info *cache_add(struct labeller *labeller, const char *pvid,
struct device *dev,
const char *vgname, const char *vgid);
void cache_del(struct cache_info *info);
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
struct device *dev,
const char *vgname, const char *vgid);
void lvmcache_del(struct lvmcache_info *info);
/* Update things */
int cache_update_vgname(struct cache_info *info, const char *vgname);
int cache_update_vg(struct volume_group *vg);
int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname);
int lvmcache_update_vg(struct volume_group *vg);
void lvmcache_lock_vgname(const char *vgname, int read_only);
void lvmcache_unlock_vgname(const char *vgname);
/* Queries */
const struct format_type *fmt_from_vgname(const char *vgname);
struct cache_vginfo *vginfo_from_vgname(const char *vgname);
struct cache_vginfo *vginfo_from_vgid(const char *vgid);
struct cache_info *info_from_pvid(const char *pvid);
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname);
struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid);
struct lvmcache_info *info_from_pvid(const char *pvid);
struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid);
int vgs_locked(void);
/* Returns list of struct str_lists containing pool-allocated copy of vgnames */
/* Set full_scan to 1 to reread every filtered device label */
struct list *cache_get_vgnames(struct cmd_context *cmd, int full_scan);
struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan);
#endif

View File

@@ -19,8 +19,12 @@
#include "label.h"
#include "lvm-file.h"
#include "format-text.h"
#include "sharedlib.h"
#include "display.h"
#include "memlock.h"
#ifdef HAVE_LIBDL
#include "sharedlib.h"
#endif
#ifdef LVM1_INTERNAL
#include "format1.h"
@@ -29,9 +33,12 @@
#include <locale.h>
#include <sys/stat.h>
#include <syslog.h>
#include <dlfcn.h>
#include <time.h>
#ifdef linux
# include <malloc.h>
#endif
static FILE *_log;
static int _get_env_vars(struct cmd_context *cmd)
@@ -53,7 +60,7 @@ static int _get_env_vars(struct cmd_context *cmd)
static void _init_logging(struct cmd_context *cmd)
{
const char *open_mode = "a";
int append = 1;
time_t t;
const char *log_file;
@@ -98,22 +105,26 @@ static void _init_logging(struct cmd_context *cmd)
/* Settings for logging to file */
if (find_config_int(cmd->cf->root, "log/overwrite", '/',
DEFAULT_OVERWRITE))
open_mode = "w";
append = 0;
log_file = find_config_str(cmd->cf->root, "log/file", '/', 0);
if (log_file) {
/* set up the logging */
if (!(_log = fopen(log_file, open_mode)))
log_error("Couldn't open log file %s", log_file);
else
init_log(_log);
}
if (log_file)
init_log_file(log_file, append);
log_file = find_config_str(cmd->cf->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));
t = time(NULL);
log_verbose("Logging initialised at %s", ctime(&t));
/* Tell device-mapper about our logging */
#ifdef DEVMAPPER_SUPPORT
dm_log_init(print_log);
#endif
}
static int _process_config(struct cmd_context *cmd)
@@ -136,8 +147,9 @@ static int _process_config(struct cmd_context *cmd)
log_error("Device directory given in config file too long");
return 0;
}
#ifdef DEVMAPPER_SUPPORT
dm_set_dev_dir(cmd->dev_dir);
#endif
/* proc dir */
if (lvm_snprintf(cmd->proc_dir, sizeof(cmd->proc_dir), "%s",
@@ -267,12 +279,12 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
if (!(f1 = regex_filter_create(cn->v))) {
log_error("Failed to create regex device filter");
return f2;
return NULL;
}
if (!(f3 = composite_filter_create(2, f1, f2))) {
log_error("Failed to create composite device filter");
return f2;
return NULL;
}
return f3;
@@ -280,7 +292,7 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
static int _init_filters(struct cmd_context *cmd)
{
const char *lvm_cache;
const char *dev_cache;
struct dev_filter *f3, *f4;
struct stat st;
char cache_file[PATH_MAX];
@@ -297,9 +309,9 @@ static int _init_filters(struct cmd_context *cmd)
return 0;
}
lvm_cache =
dev_cache =
find_config_str(cmd->cf->root, "devices/cache", '/', cache_file);
if (!(f4 = persistent_filter_create(f3, lvm_cache))) {
if (!(f4 = persistent_filter_create(f3, dev_cache))) {
log_error("Failed to create persistent device filter");
return 0;
}
@@ -311,11 +323,11 @@ static int _init_filters(struct cmd_context *cmd)
if (!*cmd->sys_dir)
cmd->dump_filter = 0;
if (!stat(lvm_cache, &st) &&
if (!stat(dev_cache, &st) &&
(st.st_mtime > config_file_timestamp(cmd->cf)) &&
!persistent_filter_load(f4))
log_verbose("Failed to load existing device cache from %s",
lvm_cache);
dev_cache);
cmd->filter = f4;
@@ -328,12 +340,10 @@ static int _init_formats(struct cmd_context *cmd)
struct format_type *fmt;
struct list *fmth;
#ifdef HAVE_LIBDL
struct config_node *cn;
struct config_value *cv;
struct format_type *(*init_format_fn) (struct cmd_context *);
void *lib;
#endif
label_init();
@@ -344,9 +354,15 @@ static int _init_formats(struct cmd_context *cmd)
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",
'/'))) {
struct config_value *cv;
struct format_type *(*init_format_fn) (struct cmd_context *);
void *lib;
for (cv = cn->v; cv; cv = cv->next) {
if (cv->type != CFG_STRING) {
log_error("Invalid string in config file: "
@@ -372,6 +388,7 @@ static int _init_formats(struct cmd_context *cmd)
list_add(&cmd->formats, &fmt->list);
}
}
#endif
if (!(fmt = create_text_format(cmd)))
return 0;
@@ -401,6 +418,10 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
{
struct cmd_context *cmd;
#ifdef M_MMAP_MAX
mallopt(M_MMAP_MAX, 0);
#endif
if (!setlocale(LC_ALL, ""))
log_error("setlocale failed");
@@ -442,6 +463,8 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
return 0;
}
memlock_init(cmd);
if (!_init_formats(cmd))
goto error;
@@ -465,8 +488,10 @@ static void _destroy_formats(struct list *formats)
list_del(&fmt->list);
lib = fmt->library;
fmt->ops->destroy(fmt);
#ifdef HAVE_LIBDL
if (lib)
dlclose(lib);
#endif
}
}
@@ -475,7 +500,8 @@ void destroy_toolcontext(struct cmd_context *cmd)
if (cmd->dump_filter)
persistent_filter_dump(cmd->filter);
cache_destroy();
activation_exit();
lvmcache_destroy();
label_exit();
_destroy_formats(&cmd->formats);
cmd->filter->destroy(cmd->filter);
@@ -484,6 +510,7 @@ void destroy_toolcontext(struct cmd_context *cmd)
destroy_config_tree(cmd->cf);
dbg_free(cmd);
release_log_memory();
dump_memory();
fin_log();
fin_syslog();

View File

@@ -53,6 +53,7 @@ struct cmd_context {
char *cmd_line;
struct command *command;
struct arg *args;
char **argv;
struct dev_filter *filter;
int dump_filter; /* Dump filter when exiting? */

View File

@@ -15,7 +15,6 @@
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include <asm/page.h>
enum {
TOK_INT,
@@ -50,7 +49,7 @@ struct cs {
char *filename;
};
static void _get_token(struct parser *p);
static void _get_token(struct parser *p, int tok_prev);
static void _eat_space(struct parser *p);
static struct config_node *_file(struct parser *p);
static struct config_node *_section(struct parser *p);
@@ -111,14 +110,15 @@ void destroy_config_tree(struct config_tree *cf)
pool_destroy(((struct cs *) cf)->mem);
}
int read_config_fd(struct config_tree *cf, int fd, const char *file,
int read_config_fd(struct config_tree *cf, 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 parser *p;
off_t mmap_offset = 0;
int r = 0;
int use_mmap = 1;
off_t mmap_offset = 0;
if (!(p = pool_alloc(c->mem, sizeof(*p)))) {
stack;
@@ -126,47 +126,43 @@ int read_config_fd(struct config_tree *cf, int fd, const char *file,
}
p->mem = c->mem;
if (size2) {
/* FIXME Attempt adjacent mmaps MAP_FIXED into malloced space
* one PAGE_SIZE larger than required...
*/
/* Only use mmap with regular files */
if (!(dev->flags & DEV_REGULAR) || size2)
use_mmap = 0;
if (use_mmap) {
mmap_offset = offset % getpagesize();
/* memory map the file */
p->fb = mmap((caddr_t) 0, size + mmap_offset, PROT_READ,
MAP_PRIVATE, dev_fd(dev), offset - mmap_offset);
if (p->fb == (caddr_t) (-1)) {
log_sys_error("mmap", dev_name(dev));
goto out;
}
p->fb = p->fb + mmap_offset;
} else {
if (!(p->fb = dbg_malloc(size + size2))) {
stack;
return 0;
}
if (lseek(fd, offset, SEEK_SET) < 0) {
log_sys_error("lseek", file);
if (!dev_read(dev, (uint64_t) offset, size, p->fb)) {
log_error("Read from %s failed", dev_name(dev));
goto out;
}
if (raw_read(fd, p->fb, size) != size) {
log_error("Circular read from %s failed", file);
goto out;
if (size2) {
if (!dev_read(dev, (uint64_t) offset2, size2,
p->fb + size)) {
log_error("Circular read from %s failed",
dev_name(dev));
goto out;
}
}
if (lseek(fd, offset2, SEEK_SET) < 0) {
log_sys_error("lseek", file);
goto out;
}
if (raw_read(fd, p->fb + size, size2) != size2) {
log_error("Circular read from %s failed", file);
goto out;
}
} else {
mmap_offset = offset % PAGE_SIZE;
/* memory map the file */
p->fb = mmap((caddr_t) 0, size + mmap_offset, PROT_READ,
MAP_PRIVATE, fd, offset - mmap_offset);
if (p->fb == (caddr_t) (-1)) {
log_sys_error("mmap", file);
goto out;
}
p->fb = p->fb + mmap_offset;
}
if (checksum_fn && checksum !=
(checksum_fn(checksum_fn(INITIAL_CRC, p->fb, size),
p->fb + size, size2))) {
log_error("%s: Checksum error", file);
log_error("%s: Checksum error", dev_name(dev));
goto out;
}
@@ -175,7 +171,7 @@ int read_config_fd(struct config_tree *cf, int fd, const char *file,
/* parse */
p->tb = p->te = p->fb;
p->line = 1;
_get_token(p);
_get_token(p, TOK_SECTION_E);
if (!(cf->root = _file(p))) {
stack;
goto out;
@@ -184,12 +180,12 @@ int read_config_fd(struct config_tree *cf, int fd, const char *file,
r = 1;
out:
if (size2)
if (!use_mmap)
dbg_free(p->fb);
else {
/* unmap the file */
if (munmap((char *) (p->fb - mmap_offset), size)) {
log_sys_error("munmap", file);
if (munmap((char *) (p->fb - mmap_offset), size + mmap_offset)) {
log_sys_error("munmap", dev_name(dev));
r = 0;
}
}
@@ -201,7 +197,8 @@ int read_config_file(struct config_tree *cf, const char *file)
{
struct cs *c = (struct cs *) cf;
struct stat info;
int r = 1, fd;
struct device *dev;
int r = 1;
if (stat(file, &info)) {
log_sys_error("stat", file);
@@ -218,15 +215,20 @@ int read_config_file(struct config_tree *cf, const char *file)
return 1;
}
if ((fd = open(file, O_RDONLY)) < 0) {
log_sys_error("open", file);
if (!(dev = dev_create_file(file, NULL, NULL))) {
stack;
return 0;
}
r = read_config_fd(cf, fd, file, 0, (size_t) info.st_size, 0, 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);
close(fd);
dev_close(dev);
c->timestamp = info.st_mtime;
c->filename = pool_strdup(c->mem, file);
@@ -250,7 +252,8 @@ int reload_config_file(struct config_tree **cf)
struct cs *c = (struct cs *) *cf;
struct cs *new_cs;
struct stat info;
int r, fd;
struct device *dev;
int r;
if (!c->filename)
return 0;
@@ -280,19 +283,25 @@ int reload_config_file(struct config_tree **cf)
return 0;
}
if ((fd = open(c->filename, O_RDONLY)) < 0) {
log_sys_error("open", c->filename);
return 0;
}
if (!(new_cf = create_config_tree())) {
log_error("Allocation of new config_tree failed");
return 0;
}
r = read_config_fd(new_cf, fd, c->filename, 0, (size_t) info.st_size,
if (!(dev = dev_create_file(c->filename, NULL, NULL))) {
stack;
return 0;
}
if (!dev_open_flags(dev, O_RDONLY, 0, 0)) {
stack;
return 0;
}
r = read_config_fd(new_cf, dev, 0, (size_t) info.st_size,
0, 0, (checksum_fn_t) NULL, 0);
close(fd);
dev_close(dev);
if (r) {
new_cs = (struct cs *) new_cf;
@@ -536,15 +545,17 @@ static int _match_aux(struct parser *p, int t)
if (p->t != t)
return 0;
_get_token(p);
_get_token(p, t);
return 1;
}
/*
* tokeniser
*/
static void _get_token(struct parser *p)
static void _get_token(struct parser *p, int tok_prev)
{
int values_allowed = 0;
p->tb = p->te;
_eat_space(p);
if (p->tb == p->fe || !*p->tb) {
@@ -552,6 +563,11 @@ static void _get_token(struct parser *p)
return;
}
/* Should next token be interpreted as value instead of identifier? */
if (tok_prev == TOK_EQ || tok_prev == TOK_ARRAY_B ||
tok_prev == TOK_COMMA)
values_allowed = 1;
p->t = TOK_INT; /* fudge so the fall through for
floats works */
switch (*p->te) {
@@ -599,6 +615,16 @@ static void _get_token(struct parser *p)
p->te++;
break;
case '\'':
p->t = TOK_STRING;
p->te++;
while ((p->te != p->fe) && (*p->te) && (*p->te != '\''))
p->te++;
if ((p->te != p->fe) && (*p->te))
p->te++;
break;
case '.':
p->t = TOK_FLOAT;
case '0':
@@ -611,22 +637,25 @@ static void _get_token(struct parser *p)
case '7':
case '8':
case '9':
p->te++;
while ((p->te != p->fe) && (*p->te)) {
if (*p->te == '.') {
if (p->t == TOK_FLOAT)
break;
p->t = TOK_FLOAT;
} else if (!isdigit((int) *p->te))
break;
if (values_allowed) {
p->te++;
while ((p->te != p->fe) && (*p->te)) {
if (*p->te == '.') {
if (p->t == TOK_FLOAT)
break;
p->t = TOK_FLOAT;
} else if (!isdigit((int) *p->te))
break;
p->te++;
}
break;
}
break;
default:
p->t = TOK_IDENTIFIER;
while ((p->te != p->fe) && (*p->te) && !isspace(*p->te) &&
(*p->te != '#') && (*p->te != '='))
(*p->te != '#') && (*p->te != '=') && (*p->te != '{') &&
(*p->te != '}'))
p->te++;
break;
}

View File

@@ -7,8 +7,7 @@
#ifndef _LVM_CONFIG_H
#define _LVM_CONFIG_H
#include <inttypes.h>
#include <sys/types.h>
#include "device.h"
enum {
CFG_STRING,
@@ -42,7 +41,7 @@ void destroy_config_tree(struct config_tree *cf);
typedef uint32_t (*checksum_fn_t) (uint32_t initial, void *buf, uint32_t size);
int read_config_fd(struct config_tree *cf, int fd, const char *file,
int read_config_fd(struct config_tree *cf, struct device *dev,
off_t offset, size_t size, off_t offset2, size_t size2,
checksum_fn_t checksum_fn, uint32_t checksum);

View File

@@ -26,22 +26,22 @@
#define DEFAULT_UMASK 0077
#ifdef LVM1_SUPPORT
#define DEFAULT_FORMAT "lvm1"
# define DEFAULT_FORMAT "lvm1"
#else
#define DEFAULT_FORMAT "lvm2"
# define DEFAULT_FORMAT "lvm2"
#endif
#define DEFAULT_STRIPESIZE 64 /* KB */
#define DEFAULT_PVMETADATASIZE 255
#define DEFAULT_PVMETADATACOPIES 1
#define DEFAULT_LABELSECTOR __UINT64_C(1)
#define DEFAULT_LABELSECTOR UINT64_C(1)
#define DEFAULT_MSG_PREFIX " "
#define DEFAULT_CMD_NAME 0
#define DEFAULT_OVERWRITE 0
#ifndef DEFAULT_LOG_FACILITY
#define DEFAULT_LOG_FACILITY LOG_USER
# define DEFAULT_LOG_FACILITY LOG_USER
#endif
#define DEFAULT_SYSLOG 1
@@ -51,10 +51,21 @@
#define DEFAULT_UNITS "h"
#define DEFAULT_SUFFIX 1
#define DEFAULT_ACTIVATION 1
#ifdef DEVMAPPER_SUPPORT
# define DEFAULT_ACTIVATION 1
# define DEFAULT_RESERVED_MEMORY 8192
# define DEFAULT_RESERVED_STACK 256
# define DEFAULT_PROCESS_PRIORITY -18
#else
# define DEFAULT_ACTIVATION 0
#endif
#define DEFAULT_STRIPE_FILLER "/dev/ioerror"
#define DEFAULT_MIRROR_REGION_SIZE 512 /* KB */
#define DEFAULT_INTERVAL 15
#ifdef READLINE_SUPPORT
#define DEFAULT_MAX_HISTORY 100
# define DEFAULT_MAX_HISTORY 100
#endif
#define DEFAULT_REP_ALIGNED 1
@@ -62,12 +73,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"
#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent,move_pv,move_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_minor,origin,snap_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,move_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"

View File

@@ -7,7 +7,6 @@
#ifndef _LVM_BITSET_H
#define _LVM_BITSET_H
#include "lvm-types.h"
#include "pool.h"
#include <limits.h>

View File

@@ -7,7 +7,6 @@
#ifndef _LVM_BTREE_H
#define _LVM_BTREE_H
#include "lvm-types.h"
#include "pool.h"
struct btree;

View File

@@ -59,10 +59,10 @@ static struct hash_node *_create_node(const char *str)
return n;
}
static unsigned _hash(const char *str, unsigned len)
static unsigned _hash(const char *str)
{
unsigned long h = 0, g;
while (*str && len--) {
while (*str) {
h <<= 4;
h += _nums[(int) *str++];
g = h & ((unsigned long) 0xf << 16u);
@@ -125,30 +125,18 @@ void hash_destroy(struct hash_table *t)
dbg_free(t);
}
static inline struct hash_node **_find_fixed(struct hash_table *t,
const char *key, unsigned len)
static inline struct hash_node **_find(struct hash_table *t, const char *key)
{
unsigned h = _hash(key, len) & (t->num_slots - 1);
unsigned h = _hash(key) & (t->num_slots - 1);
struct hash_node **c;
for (c = &t->slots[h]; *c; c = &((*c)->next))
if (!strncmp(key, (*c)->key, len))
if (!strcmp(key, (*c)->key))
break;
return c;
}
static inline struct hash_node **_find(struct hash_table *t, const char *key)
{
return _find_fixed(t, key, strlen(key));
}
void *hash_lookup_fixed(struct hash_table *t, const char *key, unsigned len)
{
struct hash_node **c = _find_fixed(t, key, len);
return *c ? (*c)->data : 0;
}
void *hash_lookup(struct hash_table *t, const char *key)
{
struct hash_node **c = _find(t, key);
@@ -238,6 +226,6 @@ struct hash_node *hash_get_first(struct hash_table *t)
struct hash_node *hash_get_next(struct hash_table *t, struct hash_node *n)
{
unsigned h = _hash(n->key, strlen(n->key)) & (t->num_slots - 1);
unsigned h = _hash(n->key) & (t->num_slots - 1);
return n->next ? n->next : _next_slot(t, h + 1);
}

View File

@@ -7,8 +7,6 @@
#ifndef _LVM_HASH_H
#define _LVM_HASH_H
#include "lvm-types.h"
struct hash_table;
struct hash_node;

View File

@@ -7,10 +7,14 @@
#ifndef _LVM_LIST_H
#define _LVM_LIST_H
#include <assert.h>
struct list {
struct list *n, *p;
};
#define LIST_INIT(name) struct list name = { &(name), &(name) }
static inline void list_init(struct list *head)
{
head->n = head->p = head;
@@ -54,9 +58,17 @@ static inline int list_end(struct list *head, struct list *elem)
return elem->n == head;
}
static inline struct list *list_next(struct list *head, struct list *elem)
{
return (list_end(head, elem) ? NULL : elem->n);
}
#define list_iterate(v, head) \
for (v = (head)->n; v != head; v = v->n)
#define list_uniterate(v, head, start) \
for (v = (start)->p; v != head; v = v->p)
#define list_iterate_safe(v, t, head) \
for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
@@ -74,8 +86,14 @@ static inline unsigned int list_size(const struct list *head)
#define list_item(v, t) \
((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->list))
/* Given a known element in a known structure, locate the struct list */
#define list_head(v, t, e) \
(((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->e))->list)
#define list_struct_base(v, t, h) \
((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->h))
/* Given a known element in a known structure, locate another */
#define struct_field(v, t, e, f) \
(((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->e))->f)
/* Given a known element in a known structure, locate the list head */
#define list_head(v, t, e) struct_field(v, t, e, list)
#endif

View File

@@ -12,9 +12,12 @@
#include <sys/types.h>
#include <inttypes.h>
/* Define some portable printing types */
#define PRIsize_t "Zu"
struct str_list {
struct list list;
char *str;
const char *str;
};
#endif

View File

@@ -11,17 +11,11 @@
#include "list.h"
#include "lvm-types.h"
#include "btree.h"
#include "filter.h"
#include <sys/stat.h>
#include <unistd.h>
#include <sys/param.h>
#include <dirent.h>
#include <linux/kdev_t.h>
/*
* FIXME: really need to seperate names from the devices since
* multiple names can point to the same device.
*/
struct dev_iter {
struct btree_iter *current;
@@ -48,20 +42,60 @@ static struct {
static int _insert(const char *path, int rec);
static struct device *_create_dev(dev_t d)
struct device *dev_create_file(const char *filename, struct device *dev,
struct str_list *alias)
{
int allocate = !dev;
if (allocate && !(dev = dbg_malloc(sizeof(*dev)))) {
log_error("struct device allocation failed");
return NULL;
}
if (allocate && !(alias = dbg_malloc(sizeof(*alias)))) {
log_error("struct str_list allocation failed");
dbg_free(dev);
return NULL;
}
if (!(alias->str = dbg_strdup(filename))) {
log_error("filename strdup failed");
if (allocate) {
dbg_free(dev);
dbg_free(alias);
}
return NULL;
}
dev->flags = DEV_REGULAR;
if (allocate)
dev->flags |= DEV_ALLOCED;
list_init(&dev->aliases);
list_add(&dev->aliases, &alias->list);
dev->end = UINT64_C(0);
dev->dev = 0;
dev->fd = -1;
dev->open_count = 0;
memset(dev->pvid, 0, sizeof(dev->pvid));
list_init(&dev->open_list);
return dev;
}
static struct device *_dev_create(dev_t d)
{
struct device *dev;
if (!(dev = _alloc(sizeof(*dev)))) {
stack;
log_error("struct device allocation failed");
return NULL;
}
dev->flags = 0;
list_init(&dev->aliases);
dev->dev = d;
dev->fd = -1;
dev->flags = 0;
dev->open_count = 0;
dev->end = UINT64_C(0);
memset(dev->pvid, 0, sizeof(dev->pvid));
list_init(&dev->open_list);
return dev;
}
@@ -129,6 +163,7 @@ static int _compare_paths(const char *path0, const char *path1)
static int _add_alias(struct device *dev, const char *path)
{
struct str_list *sl = _alloc(sizeof(*sl));
struct list *ah;
const char *oldpath;
int prefer_old = 1;
@@ -137,6 +172,14 @@ static int _add_alias(struct device *dev, const char *path)
return 0;
}
/* Is name already there? */
list_iterate(ah, &dev->aliases) {
if (!strcmp(list_item(ah, struct str_list)->str, path)) {
stack;
return 1;
}
}
if (!(sl->str = pool_strdup(_cache.mem, path))) {
stack;
return 0;
@@ -145,7 +188,11 @@ static int _add_alias(struct device *dev, const char *path)
if (!list_empty(&dev->aliases)) {
oldpath = list_item(dev->aliases.n, struct str_list)->str;
prefer_old = _compare_paths(path, oldpath);
}
log_debug("%s: Aliased to %s in device cache%s",
path, oldpath, prefer_old ? "" : " (preferred name)");
} else
log_debug("%s: Added to device cache", path);
if (prefer_old)
list_add(&dev->aliases, &sl->list);
@@ -167,7 +214,7 @@ static int _insert_dev(const char *path, dev_t d)
if (!(dev = (struct device *) btree_lookup(_cache.devices,
(uint32_t) d))) {
/* create new device */
if (!(dev = _create_dev(d))) {
if (!(dev = _dev_create(d))) {
stack;
return 0;
}
@@ -382,8 +429,10 @@ int dev_cache_add_dir(const char *path)
return 1;
}
if (!(dl = _alloc(sizeof(*dl) + strlen(path) + 1)))
if (!(dl = _alloc(sizeof(*dl) + strlen(path) + 1))) {
log_error("dir_list allocation failed");
return 0;
}
strcpy(dl->dir, path);
list_add(&_cache.dirs, &dl->list);
@@ -392,20 +441,31 @@ int dev_cache_add_dir(const char *path)
/* Check cached device name is still valid before returning it */
/* This should be a rare occurrence */
/* set quiet if the cache is expected to be out-of-date */
/* FIXME Make rest of code pass/cache struct device instead of dev_name */
const char *dev_name_confirmed(struct device *dev)
const char *dev_name_confirmed(struct device *dev, int quiet)
{
struct stat buf;
char *name;
const char *name;
int r;
while ((r = stat(name = list_item(dev->aliases.n,
struct str_list)->str, &buf)) ||
(buf.st_rdev != dev->dev)) {
if (r < 0)
log_sys_error("stat", name);
log_error("Path %s no longer valid for device(%d,%d)",
name, (int) MAJOR(dev->dev), (int) MINOR(dev->dev));
if (r < 0) {
if (quiet)
log_sys_debug("stat", name);
else
log_sys_error("stat", name);
}
if (quiet)
log_debug("Path %s no longer valid for device(%d,%d)",
name, (int) MAJOR(dev->dev),
(int) MINOR(dev->dev));
else
log_error("Path %s no longer valid for device(%d,%d)",
name, (int) MAJOR(dev->dev),
(int) MINOR(dev->dev));
/* Remove the incorrect hash entry */
hash_remove(_cache.names, name);
@@ -451,8 +511,10 @@ struct dev_iter *dev_iter_create(struct dev_filter *f)
{
struct dev_iter *di = dbg_malloc(sizeof(*di));
if (!di)
if (!di) {
log_error("dev_iter allocation failed");
return NULL;
}
_full_scan();
di->current = btree_first(_cache.devices);

View File

@@ -7,7 +7,6 @@
#ifndef _LVM_DEV_CACHE_H
#define _LVM_DEV_CACHE_H
#include <sys/types.h>
#include "lvm-types.h"
#include "device.h"

View File

@@ -5,26 +5,205 @@
*/
#include "lib.h"
#include "device.h"
#include "lvm-types.h"
#include "device.h"
#include "metadata.h"
#include "lvmcache.h"
#include "memlock.h"
#include <limits.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/unistd.h>
#include <sys/ioctl.h>
#include <linux/fs.h> // UGH!!! for BLKSSZGET
/* FIXME 64 bit offset!!!
#ifdef linux
# define u64 uint64_t /* Missing without __KERNEL__ */
# undef WNOHANG /* Avoid redefinition */
# undef WUNTRACED /* Avoid redefinition */
# include <linux/fs.h> /* For block ioctl definitions */
# define BLKSIZE_SHIFT SECTOR_SHIFT
#else
# include <sys/disk.h>
# define BLKBSZGET DKIOCGETBLOCKSIZE
# define BLKSSZGET DKIOCGETBLOCKSIZE
# define BLKGETSIZE64 DKIOCGETBLOCKCOUNT
# define BLKFLSBUF DKIOCSYNCHRONIZECACHE
# define BLKSIZE_SHIFT 0
# ifndef O_DIRECT
# define O_DIRECT 0
# 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);
/*-----------------------------------------------------------------
* The standard io loop that keeps submitting an io until it's
* all gone.
*---------------------------------------------------------------*/
static int _io(struct device_area *where, void *buffer, int should_write)
{
int fd = dev_fd(where->dev);
ssize_t n = 0;
size_t total = 0;
if (fd < 0) {
log_error("Attempt to read an unopened device (%s).",
dev_name(where->dev));
return 0;
}
/*
* Skip all writes in test mode.
*/
if (should_write && test_mode())
return 1;
if (where->size > SSIZE_MAX) {
log_error("Read size too large: %" PRIu64, where->size);
return 0;
}
if (lseek(fd, (off_t) where->start, SEEK_SET) < 0) {
log_sys_error("lseek", dev_name(where->dev));
return 0;
}
while (total < (size_t) where->size) {
do
n = should_write ?
write(fd, buffer, (size_t) where->size - total) :
read(fd, buffer, (size_t) where->size - total);
while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
if (n <= 0)
break;
total += n;
buffer += n;
}
return (total == (size_t) where->size);
}
/*-----------------------------------------------------------------
* LVM2 uses O_DIRECT when performing metadata io, which requires
* block size aligned accesses. If any io is not aligned we have
* to perform the io via a bounce buffer, obviously this is quite
* inefficient.
*---------------------------------------------------------------*/
/*
* Get the sector size from an _open_ device.
*/
static int _get_block_size(struct device *dev, unsigned int *size)
{
int s;
if (ioctl(dev_fd(dev), BLKBSZGET, &s) < 0) {
log_sys_error("ioctl BLKBSZGET", dev_name(dev));
return 0;
}
*size = (unsigned int) s;
return 1;
}
/*
* Widens a region to be an aligned region.
*/
static void _widen_region(unsigned int block_size, struct device_area *region,
struct device_area *result)
{
uint64_t mask = block_size - 1, delta;
memcpy(result, region, sizeof(*result));
/* adjust the start */
delta = result->start & mask;
if (delta) {
result->start -= delta;
result->size += delta;
}
/* adjust the end */
delta = (result->start + result->size) & mask;
if (delta)
result->size += block_size - delta;
}
static int _aligned_io(struct device_area *where, void *buffer,
int should_write)
{
void *bounce;
unsigned int block_size = 0;
uintptr_t mask;
struct device_area widened;
if (!(where->dev->flags & DEV_REGULAR) &&
!_get_block_size(where->dev, &block_size)) {
stack;
return 0;
}
if (!block_size)
block_size = SECTOR_SIZE * 2;
_widen_region(block_size, where, &widened);
/* Do we need to use a bounce buffer? */
mask = block_size - 1;
if (!memcmp(where, &widened, sizeof(widened)) &&
!((uintptr_t) buffer & mask))
return _io(where, buffer, should_write);
/* Allocate a bounce buffer with an extra block */
if (!(bounce = alloca((size_t) widened.size + block_size))) {
log_error("Bounce buffer alloca failed");
return 0;
}
/*
* Realign start of bounce buffer (using the extra sector)
*/
if (((uintptr_t) bounce) & mask)
bounce = (void *) ((((uintptr_t) bounce) + mask) & ~mask);
/* channel the io through the bounce buffer */
if (!_io(&widened, bounce, 0)) {
if (!should_write) {
stack;
return 0;
}
/* FIXME pre-extend the file */
memset(bounce, '\n', widened.size);
}
if (should_write) {
memcpy(bounce + (where->start - widened.start), buffer,
(size_t) where->size);
/* ... then we write */
return _io(&widened, bounce, 1);
}
memcpy(buffer, bounce + (where->start - widened.start),
(size_t) where->size);
return 1;
}
/*-----------------------------------------------------------------
* Public functions
*---------------------------------------------------------------*/
int dev_get_size(struct device *dev, uint64_t *size)
{
int fd;
long s;
const char *name = dev_name(dev);
log_very_verbose("Getting size of %s", name);
@@ -33,15 +212,14 @@ int dev_get_size(struct device *dev, uint64_t *size)
return 0;
}
/* FIXME: add 64 bit ioctl */
if (ioctl(fd, BLKGETSIZE, &s) < 0) {
log_sys_error("ioctl BLKGETSIZE", name);
if (ioctl(fd, BLKGETSIZE64, size) < 0) {
log_sys_error("ioctl BLKGETSIZE64", name);
close(fd);
return 0;
}
*size >>= BLKSIZE_SHIFT; /* Convert to sectors */
close(fd);
*size = (uint64_t) s;
return 1;
}
@@ -68,48 +246,106 @@ int dev_get_sectsize(struct device *dev, uint32_t *size)
return 1;
}
static void _flush(int fd)
void dev_flush(struct device *dev)
{
ioctl(fd, BLKFLSBUF, 0);
if (!(dev->flags & DEV_REGULAR) && ioctl(dev->fd, BLKFLSBUF, 0) >= 0)
return;
if (fsync(dev->fd) >= 0)
return;
sync();
}
int dev_open(struct device *dev, int flags)
int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
{
struct stat buf;
const char *name = dev_name_confirmed(dev);
const char *name;
if (!name) {
if (dev->fd >= 0) {
dev->open_count++;
return 1;
}
if (memlock())
log_error("WARNING: dev_open(%s) called while suspended",
dev_name(dev));
if (dev->flags & DEV_REGULAR)
name = dev_name(dev);
else if (!(name = dev_name_confirmed(dev, quiet))) {
stack;
return 0;
}
if (dev->fd >= 0) {
log_error("Device '%s' has already been opened", name);
return 0;
}
if ((stat(name, &buf) < 0) || (buf.st_rdev != dev->dev)) {
if (!(dev->flags & DEV_REGULAR) &&
((stat(name, &buf) < 0) || (buf.st_rdev != dev->dev))) {
log_error("%s: stat failed: Has device name changed?", name);
return 0;
}
if ((dev->fd = open(name, flags)) < 0) {
if (direct)
flags |= O_DIRECT;
if ((dev->fd = open(name, flags, 0777)) < 0) {
log_sys_error("open", name);
return 0;
}
if ((fstat(dev->fd, &buf) < 0) || (buf.st_rdev != dev->dev)) {
dev->open_count = 1;
dev->flags &= ~DEV_ACCESSED_W;
if (!(dev->flags & DEV_REGULAR) &&
((fstat(dev->fd, &buf) < 0) || (buf.st_rdev != dev->dev))) {
log_error("%s: fstat failed: Has device name changed?", name);
dev_close(dev);
dev->fd = -1;
return 0;
}
_flush(dev->fd);
dev->flags = 0;
#if !O_DIRECT
if (!(dev->flags & DEV_REGULAR))
dev_flush(dev);
#endif
if ((flags & O_CREAT) && !(flags & O_TRUNC)) {
dev->end = lseek(dev->fd, (off_t) 0, SEEK_END);
}
list_add(&_open_devices, &dev->open_list);
log_debug("Opened %s", dev_name(dev));
return 1;
}
int dev_open_quiet(struct device *dev)
{
/* FIXME Open O_RDONLY if vg read lock? */
return dev_open_flags(dev, O_RDWR, 1, 1);
}
int dev_open(struct device *dev)
{
/* FIXME Open O_RDONLY if vg read lock? */
return dev_open_flags(dev, O_RDWR, 1, 0);
}
static void _close(struct device *dev)
{
if (close(dev->fd))
log_sys_error("close", dev_name(dev));
dev->fd = -1;
list_del(&dev->open_list);
log_debug("Closed %s", dev_name(dev));
if (dev->flags & DEV_ALLOCED) {
dbg_free((void *) list_item(dev->aliases.n, struct str_list)->
str);
dbg_free(dev->aliases.n);
dbg_free(dev);
}
}
int dev_close(struct device *dev)
{
if (dev->fd < 0) {
@@ -117,152 +353,113 @@ int dev_close(struct device *dev)
"which is not open.", dev_name(dev));
return 0;
}
#if !O_DIRECT
if (dev->flags & DEV_ACCESSED_W)
_flush(dev->fd);
dev_flush(dev);
#endif
if (close(dev->fd))
log_sys_error("close", dev_name(dev));
dev->fd = -1;
/* FIXME lookup device in cache to get vgname and see if it's locked? */
if (--dev->open_count < 1 && !vgs_locked())
_close(dev);
return 1;
}
ssize_t raw_read(int fd, void *buf, size_t count)
void dev_close_all(void)
{
ssize_t n = 0, tot = 0;
struct list *doh, *doht;
struct device *dev;
if (count > SSIZE_MAX)
return -1;
while (tot < (signed) count) {
do
n = read(fd, buf, count - tot);
while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
if (n <= 0)
return tot ? tot : n;
tot += n;
buf += n;
list_iterate_safe(doh, doht, &_open_devices) {
dev = list_struct_base(doh, struct device, open_list);
if (dev->open_count < 1)
_close(dev);
}
return tot;
}
ssize_t dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
{
const char *name = dev_name(dev);
int fd = dev->fd;
/* loff_t pos; */
struct device_area where;
if (fd < 0) {
log_err("Attempt to read an unopened device (%s).", name);
if (!dev->open_count)
return 0;
}
/* if (_llseek((unsigned) fd, (ulong) (offset >> 32), (ulong) (offset & 0xFFFFFFFF), &pos, SEEK_SET) < 0) { */
if (lseek(fd, (off_t) offset, SEEK_SET) < 0) {
log_sys_error("lseek", name);
return 0;
}
where.dev = dev;
where.start = offset;
where.size = len;
return raw_read(fd, buffer, len);
return _aligned_io(&where, buffer, 0);
}
static int _write(int fd, const void *buf, size_t count)
/* FIXME If O_DIRECT can't extend file, dev_extend first; dev_truncate after.
* But fails if concurrent processes writing
*/
/* FIXME pre-extend the file */
int dev_append(struct device *dev, size_t len, void *buffer)
{
ssize_t n = 0;
int tot = 0;
int r;
/* Skip all writes */
if (test_mode())
return count;
if (!dev->open_count)
return 0;
while (tot < count) {
do
n = write(fd, buf, count - tot);
while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
r = dev_write(dev, dev->end, len, buffer);
dev->end += (uint64_t) len;
if (n <= 0)
return tot ? tot : n;
tot += n;
buf += n;
}
return tot;
#if !O_DIRECT
dev_flush(dev);
#endif
return r;
}
int64_t dev_write(struct device * dev, uint64_t offset, size_t len,
void *buffer)
int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer)
{
const char *name = dev_name(dev);
int fd = dev->fd;
struct device_area where;
if (fd < 0) {
log_error("Attempt to write to unopened device %s", name);
if (!dev->open_count)
return 0;
}
if (lseek(fd, (off_t) offset, SEEK_SET) < 0) {
log_sys_error("lseek", name);
return 0;
}
where.dev = dev;
where.start = offset;
where.size = len;
dev->flags |= DEV_ACCESSED_W;
return _write(fd, buffer, len);
return _aligned_io(&where, buffer, 1);
}
int dev_zero(struct device *dev, uint64_t offset, size_t len)
{
int64_t r;
size_t s;
char buffer[4096];
int already_open;
already_open = dev_is_open(dev);
if (!already_open && !dev_open(dev, O_RDWR)) {
if (!dev_open(dev)) {
stack;
return 0;
}
if (lseek(dev->fd, (off_t) offset, SEEK_SET) < 0) {
log_sys_error("lseek", dev_name(dev));
if (!already_open && !dev_close(dev))
stack;
return 0;
}
if ((offset % SECTOR_SIZE) || (len % SECTOR_SIZE))
log_debug("Wiping %s at %" PRIu64 " length %u",
log_debug("Wiping %s at %" PRIu64 " length %" PRIsize_t,
dev_name(dev), offset, len);
else
log_debug("Wiping %s at sector %" PRIu64 " length %u"
log_debug("Wiping %s at sector %" PRIu64 " length %" PRIsize_t
" sectors", dev_name(dev), offset >> SECTOR_SHIFT,
len >> SECTOR_SHIFT);
memset(buffer, 0, sizeof(buffer));
while (1) {
s = len > sizeof(buffer) ? sizeof(buffer) : len;
r = _write(dev->fd, buffer, s);
if (r <= 0)
if (!dev_write(dev, offset, s, buffer))
break;
len -= r;
if (!len) {
r = 1;
len -= s;
if (!len)
break;
}
}
dev->flags |= DEV_ACCESSED_W;
if (!already_open && !dev_close(dev))
if (!dev_close(dev))
stack;
/* FIXME: Always display error */

View File

@@ -18,7 +18,6 @@
*/
#if 0
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <stdio.h>

View File

@@ -7,11 +7,12 @@
#ifndef _LVM_DEVICE_H
#define _LVM_DEVICE_H
#include "lvm-types.h"
#include "list.h"
#include "uuid.h"
#include <fcntl.h>
#define DEV_ACCESSED_W 0x00000001 /* Device written to? */
#define DEV_REGULAR 0x00000002 /* Regular file? */
#define DEV_ALLOCED 0x00000004 /* dbg_malloc used */
/*
* All devices in LVM will be represented by one of these.
@@ -23,7 +24,10 @@ struct device {
/* private */
int fd;
int open_count;
uint32_t flags;
uint64_t end;
struct list open_list;
char pvid[ID_LEN + 1];
};
@@ -45,20 +49,26 @@ struct device_area {
int dev_get_size(struct device *dev, uint64_t *size);
int dev_get_sectsize(struct device *dev, uint32_t *size);
int dev_open(struct device *dev, int flags);
/* Use quiet version if device number could change e.g. when opening LV */
int dev_open(struct device *dev);
int dev_open_quiet(struct device *dev);
int dev_open_flags(struct device *dev, int flags, int append, int quiet);
int dev_close(struct device *dev);
void dev_close_all(void);
static inline int dev_fd(struct device *dev)
{
return dev->fd;
}
ssize_t raw_read(int fd, void *buf, size_t count);
ssize_t dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer);
int64_t dev_write(struct device *dev, uint64_t offset, size_t len,
void *buffer);
int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer);
int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer);
int dev_append(struct device *dev, size_t len, void *buffer);
int dev_zero(struct device *dev, uint64_t offset, size_t len);
void dev_flush(struct device *dev);
struct device *dev_create_file(const char *filename, struct device *dev,
struct str_list *alias);
static inline const char *dev_name(const struct device *dev)
{
@@ -67,12 +77,7 @@ static inline const char *dev_name(const struct device *dev)
}
/* Return a valid device name from the alias list; NULL otherwise */
const char *dev_name_confirmed(struct device *dev);
static inline int dev_is_open(struct device *dev)
{
return dev->fd >= 0 ? 1 : 0;
}
const char *dev_name_confirmed(struct device *dev, int quiet);
/* FIXME Check partition type if appropriate */

View File

@@ -42,7 +42,7 @@ static struct {
} _segtypes[] = {
{
SEG_STRIPED, "striped"}, {
SEG_MIRROR, "mirror"}, {
SEG_MIRRORED, "mirror"}, {
SEG_SNAPSHOT, "snapshot"}
};
@@ -70,18 +70,20 @@ uint64_t units_to_bytes(const char *units, char *unit_type)
switch (*units) {
case 'h':
case 'H':
v = __UINT64_C(1);
v = UINT64_C(1);
*unit_type = *units;
break;
case 's':
v *= SECTOR_SIZE;
break;
case 'b':
case 'B':
v *= __UINT64_C(1);
v *= UINT64_C(1);
break;
#define KILO __UINT64_C(1024)
#define KILO UINT64_C(1024)
case 'k':
v *= KILO;
break;
case 'm':
v *= KILO * KILO;
break;
@@ -92,7 +94,7 @@ uint64_t units_to_bytes(const char *units, char *unit_type)
v *= KILO * KILO * KILO * KILO;
break;
#undef KILO
#define KILO __UINT64_C(1000)
#define KILO UINT64_C(1000)
case 'K':
v *= KILO;
break;
@@ -166,8 +168,8 @@ const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
{
int s;
int suffix = 1;
uint64_t byte;
uint64_t units = __UINT64_C(1024);
uint64_t byte = UINT64_C(0);
uint64_t units = UINT64_C(1024);
char *size_buf = NULL;
const char *size_str[][3] = {
{" Terabyte", " TB", "T"},
@@ -193,20 +195,20 @@ const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
*size_str[s][2])
break;
if (size == __UINT64_C(0)) {
if (size == UINT64_C(0)) {
sprintf(size_buf, "0%s", suffix ? size_str[s][sl] : "");
return size_buf;
}
if (s < 8) {
byte = cmd->current_settings.unit_factor;
size *= __UINT64_C(1024);
size *= UINT64_C(1024);
} else {
suffix = 1;
if (cmd->current_settings.unit_type == 'H')
units = __UINT64_C(1000);
units = UINT64_C(1000);
else
units = __UINT64_C(1024);
units = UINT64_C(1024);
byte = units * units * units;
s = 0;
while (size_str[s] && size < byte)
@@ -335,7 +337,7 @@ int pvdisplay_short(struct cmd_context *cmd, struct volume_group *vg,
void lvdisplay_colons(struct logical_volume *lv)
{
int inkernel;
struct dm_info info;
struct lvinfo info;
inkernel = lv_info(lv, &info) && info.exists;
log_print("%s%s/%s:%s:%d:%d:-1:%d:%" PRIu64 ":%d:-1:%d:%d:%d:%d",
@@ -355,7 +357,7 @@ void lvdisplay_colons(struct logical_volume *lv)
int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
void *handle)
{
struct dm_info info;
struct lvinfo info;
int inkernel, snap_active;
char uuid[64];
struct snapshot *snap = NULL;
@@ -461,8 +463,11 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
log_print("Allocation %s", get_alloc_string(lv->alloc));
log_print("Read ahead sectors %u", lv->read_ahead);
if (lv->status & FIXED_MINOR)
if (lv->status & FIXED_MINOR) {
if (lv->major >= 0)
log_print("Persistent major %d", lv->major);
log_print("Persistent minor %d", lv->minor);
}
if (inkernel)
log_print("Block device %d:%d", info.major,
@@ -475,14 +480,28 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
static void _display_stripe(struct lv_segment *seg, uint32_t s, const char *pre)
{
uint32_t len = seg->len / seg->stripes;
switch (seg->area[s].type) {
case AREA_PV:
log_print("%sPhysical volume\t%s", pre,
seg->area[s].u.pv.pv ?
dev_name(seg->area[s].u.pv.pv->dev) : "Missing");
log_print("%sPhysical volume\t%s", pre,
seg->area[s].pv ? dev_name(seg->area[s].pv->dev) : "Missing");
if (seg->area[s].u.pv.pv)
log_print("%sPhysical extents\t%d to %d", pre,
seg->area[s].u.pv.pe,
seg->area[s].u.pv.pe + seg->area_len - 1);
break;
case AREA_LV:
log_print("%sLogical volume\t%s", pre,
seg->area[s].u.lv.lv ?
seg->area[s].u.lv.lv->name : "Missing");
if (seg->area[s].pv)
log_print("%sPhysical extents\t%d to %d", pre,
seg->area[s].pe, seg->area[s].pe + len - 1);
if (seg->area[s].u.lv.lv)
log_print("%sLogical extents\t%d to %d", pre,
seg->area[s].u.lv.le,
seg->area[s].u.lv.le + seg->area_len - 1);
}
}
int lvdisplay_segments(struct logical_volume *lv)
@@ -499,7 +518,7 @@ int lvdisplay_segments(struct logical_volume *lv)
log_print("Logical extent %u to %u:",
seg->le, seg->le + seg->len - 1);
if (seg->type == SEG_STRIPED && seg->stripes == 1)
if (seg->type == SEG_STRIPED && seg->area_count == 1)
log_print(" Type\t\tlinear");
else
log_print(" Type\t\t%s",
@@ -507,14 +526,14 @@ int lvdisplay_segments(struct logical_volume *lv)
switch (seg->type) {
case SEG_STRIPED:
if (seg->stripes == 1)
if (seg->area_count == 1)
_display_stripe(seg, 0, " ");
else {
log_print(" Stripes\t\t%u", seg->stripes);
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->stripes; s++) {
for (s = 0; s < seg->area_count; s++) {
log_print(" Stripe %d:", s);
_display_stripe(seg, s, " ");
}
@@ -522,8 +541,16 @@ int lvdisplay_segments(struct logical_volume *lv)
log_print(" ");
break;
case SEG_SNAPSHOT:
case SEG_MIRROR:
;
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;
}
}

View File

@@ -19,6 +19,8 @@ static int _and_p(struct dev_filter *f, struct device *dev)
filters++;
}
log_debug("Using %s", dev_name(dev));
return 1;
}

View File

@@ -32,8 +32,12 @@ static int _init_hash(struct pfilter *pf)
if (pf->devices)
hash_destroy(pf->devices);
pf->devices = hash_create(128);
return pf->devices ? 1 : 0;
if (!(pf->devices = hash_create(128))) {
stack;
return 0;
}
return 1;
}
int persistent_filter_wipe(struct dev_filter *f)
@@ -201,7 +205,11 @@ static int _lookup_p(struct dev_filter *f, struct device *dev)
}
}
return l == PF_GOOD_DEVICE;
if (l == PF_BAD_DEVICE) {
log_debug("%s: Skipping (cached)", dev_name(dev));
return 0;
} else
return 1;
}
static void _destroy(struct dev_filter *f)

View File

@@ -162,6 +162,8 @@ static int _accept_p(struct dev_filter *f, struct device *dev)
if (bit(rf->accept, m)) {
if (!first) {
log_debug("%s: New preferred name",
sl->str);
list_del(&sl->list);
list_add_h(&dev->aliases, &sl->list);
}

View File

@@ -25,11 +25,10 @@
#include "config.h"
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>
#include <linux/kdev_t.h>
#include <limits.h>
#define NUMBER_OF_MAJORS 256
@@ -68,12 +67,16 @@ static int _passes_lvm_type_device_filter(struct dev_filter *f,
const char *name = dev_name(dev);
/* Is this a recognised device type? */
if (!(((int *) f->private)[MAJOR(dev->dev)]))
if (!(((int *) f->private)[MAJOR(dev->dev)])) {
log_debug("%s: Skipping: Unrecognised LVM device type %"
PRIu64, name, (uint64_t) MAJOR(dev->dev));
return 0;
}
/* Check it's accessible */
if ((fd = open(name, O_RDONLY)) < 0) {
log_debug("Unable to open %s: %s", name, strerror(errno));
log_debug("%s: Skipping: open failed: %s", name,
strerror(errno));
return 0;
}
@@ -101,6 +104,14 @@ static int *_scan_proc_dev(const char *proc, struct config_node *cn)
return NULL;
}
if (!*proc) {
log_verbose("No proc filesystem found: using all block device "
"types");
for (i = 0; i < NUMBER_OF_MAJORS; i++)
max_partitions_by_major[i] = 1;
return max_partitions_by_major;
}
if (lvm_snprintf(proc_devices, sizeof(proc_devices),
"%s/devices", proc) < 0) {
log_error("Failed to create /proc/devices string");
@@ -203,8 +214,10 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
f->passes_filter = _passes_lvm_type_device_filter;
f->destroy = lvm_type_filter_destroy;
if (!(f->private = _scan_proc_dev(proc, cn)))
if (!(f->private = _scan_proc_dev(proc, cn))) {
stack;
return NULL;
}
return f;
}

View File

@@ -23,6 +23,16 @@
#include "config.h"
#include <sys/stat.h>
#ifdef linux
# include <linux/kdev_t.h>
#else
# define MAJOR(x) major((x))
# define MINOR(x) minor((x))
# define MKDEV(x,y) makedev((x),(y))
#endif
struct dev_filter *lvm_type_filter_create(const char *proc,
struct config_node *cn);

View File

@@ -9,11 +9,9 @@
#include "pool.h"
#include "xlate.h"
#include "filter.h"
#include "cache.h"
#include "lvmcache.h"
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/kdev_t.h>
#define fail do {stack; return 0;} while(0)
#define xx16(v) disk->v = xlate16(disk->v)
@@ -132,7 +130,7 @@ static int _munge_formats(struct pv_disk *pvd)
static int _read_pvd(struct device *dev, struct pv_disk *pvd)
{
if (dev_read(dev, __UINT64_C(0), sizeof(*pvd), pvd) != sizeof(*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;
@@ -157,7 +155,7 @@ static int _read_pvd(struct device *dev, struct pv_disk *pvd)
static int _read_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
{
if (dev_read(dev, pos, sizeof(*disk), disk) != sizeof(*disk))
if (!dev_read(dev, pos, sizeof(*disk), disk))
fail;
_xlate_lvd(disk);
@@ -169,7 +167,7 @@ static int _read_vgd(struct disk_list *data)
{
struct vg_disk *vgd = &data->vgd;
uint64_t pos = data->pvd.vg_on_disk.base;
if (dev_read(data->dev, pos, sizeof(*vgd), vgd) != sizeof(*vgd))
if (!dev_read(data->dev, pos, sizeof(*vgd), vgd))
fail;
_xlate_vgd(vgd);
@@ -186,8 +184,7 @@ static int _read_uuids(struct disk_list *data)
uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size;
while (pos < end && num_read < data->vgd.pv_cur) {
if (dev_read(data->dev, pos, sizeof(buffer), buffer) !=
sizeof(buffer))
if (!dev_read(data->dev, pos, sizeof(buffer), buffer))
fail;
if (!(ul = pool_alloc(data->mem, sizeof(*ul))))
@@ -246,7 +243,7 @@ static int _read_extents(struct disk_list *data)
if (!extents)
fail;
if (dev_read(data->dev, pos, len, extents) != len)
if (!dev_read(data->dev, pos, len, extents))
fail;
_xlate_extents(extents, data->pvd.pe_total);
@@ -281,7 +278,7 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
{
struct disk_list *dl = pool_alloc(mem, sizeof(*dl));
const char *name = dev_name(dev);
struct cache_info *info;
struct lvmcache_info *info;
if (!dl) {
stack;
@@ -298,8 +295,8 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
goto bad;
}
if (!(info = cache_add(fmt->labeller, dl->pvd.pv_uuid, dev,
dl->pvd.vg_name, NULL)))
if (!(info = lvmcache_add(fmt->labeller, dl->pvd.pv_uuid, dev,
dl->pvd.vg_name, NULL)))
stack;
else {
info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT;
@@ -367,7 +364,7 @@ struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
{
struct disk_list *r;
if (!dev_open(dev, O_RDONLY)) {
if (!dev_open(dev)) {
stack;
return NULL;
}
@@ -417,13 +414,13 @@ int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
struct device *dev;
struct disk_list *data = NULL;
struct list *vgih;
struct cache_vginfo *vginfo;
struct lvmcache_vginfo *vginfo;
/* Fast path if we already saw this VG and cached the list of PVs */
if (vg_name && (vginfo = vginfo_from_vgname(vg_name)) &&
vginfo->infos.n) {
list_iterate(vgih, &vginfo->infos) {
dev = list_item(vgih, struct cache_info)->dev;
dev = list_item(vgih, struct lvmcache_info)->dev;
if (dev && !(data = read_disk(fmt, dev, mem, vg_name)))
break;
_add_pv_to_list(head, data);
@@ -465,7 +462,7 @@ static int _write_vgd(struct disk_list *data)
uint64_t pos = data->pvd.vg_on_disk.base;
_xlate_vgd(vgd);
if (dev_write(data->dev, pos, sizeof(*vgd), vgd) != sizeof(*vgd))
if (!dev_write(data->dev, pos, sizeof(*vgd), vgd))
fail;
_xlate_vgd(vgd);
@@ -488,7 +485,7 @@ static int _write_uuids(struct disk_list *data)
}
ul = list_item(uh, struct uuid_list);
if (dev_write(data->dev, pos, NAME_LEN, ul->uuid) != NAME_LEN)
if (!dev_write(data->dev, pos, NAME_LEN, ul->uuid))
fail;
pos += NAME_LEN;
@@ -500,7 +497,7 @@ static int _write_uuids(struct disk_list *data)
static int _write_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
{
_xlate_lvd(disk);
if (dev_write(dev, pos, sizeof(*disk), disk) != sizeof(*disk))
if (!dev_write(dev, pos, sizeof(*disk), disk))
fail;
_xlate_lvd(disk);
@@ -544,7 +541,7 @@ static int _write_extents(struct disk_list *data)
uint64_t pos = data->pvd.pe_on_disk.base;
_xlate_extents(extents, data->pvd.pe_total);
if (dev_write(data->dev, pos, len, extents) != len)
if (!dev_write(data->dev, pos, len, extents))
fail;
_xlate_extents(extents, data->pvd.pe_total);
@@ -576,7 +573,7 @@ static int _write_pvd(struct disk_list *data)
memcpy(buf, &data->pvd, sizeof(struct pv_disk));
_xlate_pvd((struct pv_disk *) buf);
if (dev_write(data->dev, pos, size, buf) != size) {
if (!dev_write(data->dev, pos, size, buf)) {
dbg_free(buf);
fail;
}
@@ -642,7 +639,7 @@ static int _write_all_pvd(const struct format_type *fmt, struct disk_list *data)
{
int r;
if (!dev_open(data->dev, O_WRONLY)) {
if (!dev_open(data->dev)) {
stack;
return 0;
}

View File

@@ -12,7 +12,7 @@
#include "list.h"
#include "display.h"
#include "toolcontext.h"
#include "cache.h"
#include "lvmcache.h"
#include "lvm1-label.h"
#include "format1.h"
@@ -248,7 +248,7 @@ static int _vg_write(struct format_instance *fid, struct volume_group *vg,
fid->fmt->cmd->filter) &&
write_disks(fid->fmt, &pvds));
cache_update_vg(vg);
lvmcache_update_vg(vg);
pool_destroy(mem);
return r;
}
@@ -381,10 +381,10 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
struct disk_list *dl;
struct list pvs;
struct label *label;
struct cache_info *info;
struct lvmcache_info *info;
if (!(info = cache_add(fmt->labeller, (char *) &pv->id, pv->dev,
pv->vg_name, NULL))) {
if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
pv->vg_name, NULL))) {
stack;
return 0;
}
@@ -533,6 +533,7 @@ static struct format_handler _format1_ops = {
#ifdef LVM1_INTERNAL
struct format_type *init_lvm1_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
{

View File

@@ -12,10 +12,10 @@
#include "hash.h"
#include "list.h"
#include "lvm-string.h"
#include "filter.h"
#include <time.h>
#include <sys/utsname.h>
#include <linux/kdev_t.h>
static int _check_vg_name(const char *name)
{
@@ -288,8 +288,11 @@ int import_lv(struct pool *mem, struct logical_volume *lv, struct lv_disk *lvd)
if (lvd->lv_status & LV_PERSISTENT_MINOR) {
lv->status |= FIXED_MINOR;
lv->minor = MINOR(lvd->lv_dev);
} else
lv->major = MAJOR(lvd->lv_dev);
} else {
lv->major = -1;
lv->minor = -1;
}
if (lvd->lv_access & LV_READ)
lv->status |= LVM_READ;
@@ -335,13 +338,14 @@ static void _export_lv(struct lv_disk *lvd, struct volume_group *vg,
if (lv->status & FIXED_MINOR) {
lvd->lv_status |= LV_PERSISTENT_MINOR;
lvd->lv_dev = MKDEV(0, lv->minor);
lvd->lv_dev = MKDEV(lv->major, lv->minor);
}
lvd->lv_read_ahead = lv->read_ahead;
lvd->lv_stripes = list_item(lv->segments.n, struct lv_segment)->stripes;
lvd->lv_stripesize = list_item(lv->segments.n,
struct lv_segment)->stripe_size;
lvd->lv_stripes =
list_item(lv->segments.n, struct lv_segment)->area_count;
lvd->lv_stripesize =
list_item(lv->segments.n, struct lv_segment)->stripe_size;
lvd->lv_size = lv->size;
lvd->lv_allocated_le = lv->le_count;
@@ -364,15 +368,25 @@ int export_extents(struct disk_list *dl, uint32_t lv_num,
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
for (s = 0; s < seg->stripes; s++) {
if (seg->area[s].pv != pv)
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);
return 0;
}
if (seg->area[s].type != AREA_PV) {
log_error("LV stripe found in LV %s: "
"unsupported by format1", lv->name);
return 0;
}
if (seg->area[s].u.pv.pv != pv)
continue; /* not our pv */
for (pe = 0; pe < (seg->len / seg->stripes); pe++) {
ped = &dl->extents[pe + seg->area[s].pe];
for (pe = 0; pe < (seg->len / seg->area_count); pe++) {
ped = &dl->extents[pe + seg->area[s].u.pv.pe];
ped->lv_num = lv_num;
ped->le_num = (seg->le / seg->stripes) + pe +
s * (lv->le_count / seg->stripes);
ped->le_num = (seg->le / seg->area_count) + pe +
s * (lv->le_count / seg->area_count);
}
}
}
@@ -393,7 +407,7 @@ int import_pvs(const struct format_type *fmt, struct pool *mem,
dl = list_item(pvdh, struct disk_list);
if (!(pvl = pool_alloc(mem, sizeof(*pvl))) ||
if (!(pvl = pool_zalloc(mem, sizeof(*pvl))) ||
!(pvl->pv = pool_alloc(mem, sizeof(*pvl->pv)))) {
stack;
return 0;

View File

@@ -216,19 +216,21 @@ static int _read_linear(struct pool *mem, struct lv_map *lvm)
seg->type = SEG_STRIPED;
seg->le = le;
seg->len = 0;
seg->area_len = 0;
seg->stripe_size = 0;
seg->stripes = 1;
seg->area_count = 1;
seg->area[0].pv = lvm->map[le].pv;
seg->area[0].pe = lvm->map[le].pe;
seg->area[0].type = AREA_PV;
seg->area[0].u.pv.pv = lvm->map[le].pv;
seg->area[0].u.pv.pe = lvm->map[le].pe;
do
do {
seg->len++;
while ((lvm->map[le + seg->len].pv == seg->area[0].pv) &&
(seg->area[0].pv &&
lvm->map[le + seg->len].pe == seg->area[0].pe +
seg->len));
seg->area_len++;
} while ((lvm->map[le + seg->len].pv == seg->area[0].u.pv.pv) &&
(seg->area[0].u.pv.pv &&
lvm->map[le + seg->len].pe == seg->area[0].u.pv.pe +
seg->len));
le += seg->len;
@@ -248,10 +250,11 @@ static int _check_stripe(struct lv_map *lvm, struct lv_segment *seg,
/*
* Is the next physical extent in every stripe adjacent to the last?
*/
for (st = 0; st < seg->stripes; st++)
if ((lvm->map[le + st * len].pv != seg->area[st].pv) ||
(seg->area[st].pv &&
lvm->map[le + st * len].pe != seg->area[st].pe + seg->len))
for (st = 0; st < seg->area_count; st++)
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;
return 1;
@@ -281,27 +284,30 @@ static int _read_stripes(struct pool *mem, struct lv_map *lvm)
seg->lv = lvm->lv;
seg->type = SEG_STRIPED;
seg->stripe_size = lvm->stripe_size;
seg->stripes = lvm->stripes;
seg->le = seg->stripes * le;
seg->area_count = lvm->stripes;
seg->le = seg->area_count * le;
seg->len = 1;
seg->area_len = 1;
/*
* Set up start positions of each stripe in this segment
*/
for (st = 0; st < seg->stripes; st++) {
seg->area[st].pv = lvm->map[le + st * len].pv;
seg->area[st].pe = lvm->map[le + st * len].pe;
for (st = 0; st < seg->area_count; st++) {
seg->area[st].u.pv.pv = lvm->map[le + st * len].pv;
seg->area[st].u.pv.pe = lvm->map[le + st * len].pe;
}
/*
* Find how many blocks are contiguous in all stripes
* and so can form part of this segment
*/
while (_check_stripe(lvm, seg, le, len))
while (_check_stripe(lvm, seg, le, len)) {
seg->len++;
seg->area_len++;
}
le += seg->len;
seg->len *= seg->stripes;
seg->len *= seg->area_count;
list_add(&lvm->lv->segments, &seg->list);
}

View File

@@ -10,13 +10,13 @@
/*
* Only works with powers of 2.
*/
static inline ulong _round_up(ulong n, ulong size)
static inline uint32_t _round_up(uint32_t n, uint32_t size)
{
size--;
return (n + size) & ~size;
}
static inline ulong _div_up(ulong n, ulong size)
static inline uint32_t _div_up(uint32_t n, uint32_t size)
{
return _round_up(n, size) / size;
}

View File

@@ -10,7 +10,7 @@
#include "label.h"
#include "metadata.h"
#include "xlate.h"
#include "cache.h"
#include "lvmcache.h"
#include <sys/stat.h>
#include <fcntl.h>
@@ -49,9 +49,9 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
struct label **label)
{
struct pv_disk *pvd = (struct pv_disk *) buf;
struct cache_info *info;
struct lvmcache_info *info;
if (!(info = cache_add(l, pvd->pv_uuid, dev, pvd->vg_name, NULL)))
if (!(info = lvmcache_add(l, pvd->pv_uuid, dev, pvd->vg_name, NULL)))
return 0;
*label = info->label;

View File

@@ -372,6 +372,7 @@ static int _print_segment(struct formatter *f, struct volume_group *vg,
{
unsigned int s;
const char *name;
const char *type;
_outf(f, "segment%u {", count);
_inc_indent(f);
@@ -387,40 +388,55 @@ static int _print_segment(struct formatter *f, struct volume_group *vg,
_outf(f, "type = \"%s\"", get_segtype_string(seg->type));
switch (seg->type) {
case SEG_STRIPED:
_outf(f, "stripe_count = %u%s", seg->stripes,
(seg->stripes == 1) ? "\t# linear" : "");
if (seg->stripes > 1)
_out_size(f, (uint64_t) seg->stripe_size,
"stripe_size = %u", seg->stripe_size);
f->nl(f);
_outf(f, "stripes = [");
_inc_indent(f);
for (s = 0; s < seg->stripes; s++) {
if (!(name = _get_pv_name(f, seg->area[s].pv))) {
stack;
return 0;
}
_outf(f, "\"%s\", %u%s", name, seg->area[s].pe,
(s == seg->stripes - 1) ? "" : ",");
}
_dec_indent(f);
_outf(f, "]");
break;
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_MIRROR:
/* mirrors = [ "lvol1", 10, ... ] */
;
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) ? "" : ",");
}
}
_dec_indent(f);
_outf(f, "]");
break;
}
_dec_indent(f);
@@ -547,6 +563,8 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
get_alloc_string(lv->alloc));
if (lv->read_ahead)
_outf(f, "read_ahead = %u", lv->read_ahead);
if (lv->major >= 0)
_outf(f, "major = %d", lv->major);
if (lv->minor >= 0)
_outf(f, "minor = %d", lv->minor);
_outf(f, "segment_count = %u", _count_segments(lv));
@@ -602,6 +620,7 @@ static int _build_pv_names(struct formatter *f, struct volume_group *vg)
list_iterate(pvh, &vg->pvs) {
pv = list_item(pvh, struct pv_list)->pv;
/* FIXME But skip if there's already an LV called pv%d ! */
if (lvm_snprintf(buffer, sizeof(buffer), "pv%d", count++) < 0) {
stack;
goto bad;

View File

@@ -22,6 +22,7 @@ static struct flag _vg_flags[] = {
{EXPORTED_VG, "EXPORTED"},
{RESIZEABLE_VG, "RESIZEABLE"},
{PARTIAL_VG, "PARTIAL"},
{PVMOVE, "PVMOVE"},
{LVM_READ, "READ"},
{LVM_WRITE, "WRITE"},
{CLUSTERED, "CLUSTERED"},
@@ -40,6 +41,8 @@ static struct flag _lv_flags[] = {
{LVM_WRITE, "WRITE"},
{FIXED_MINOR, "FIXED_MINOR"},
{VISIBLE_LV, "VISIBLE"},
{PVMOVE, "PVMOVE"},
{LOCKED, "LOCKED"},
{0, NULL}
};

View File

@@ -20,6 +20,7 @@
#include "crc.h"
#include "xlate.h"
#include "label.h"
#include "memlock.h"
#include <unistd.h>
#include <sys/file.h>
@@ -107,8 +108,7 @@ static struct mda_header *_raw_read_mda_header(const struct format_type *fmt,
return NULL;
}
if (dev_read(dev_area->dev, dev_area->start, MDA_HEADER_SIZE, mdah) !=
MDA_HEADER_SIZE) {
if (!dev_read(dev_area->dev, dev_area->start, MDA_HEADER_SIZE, mdah)) {
stack;
pool_free(fmt->cmd->mem, mdah);
return NULL;
@@ -156,8 +156,7 @@ static int _raw_write_mda_header(const struct format_type *fmt,
MDA_HEADER_SIZE -
sizeof(mdah->checksum_xl)));
if (dev_write(dev, start_byte, MDA_HEADER_SIZE, mdah)
!= MDA_HEADER_SIZE) {
if (!dev_write(dev, start_byte, MDA_HEADER_SIZE, mdah)) {
stack;
pool_free(fmt->cmd->mem, mdah);
return 0;
@@ -178,9 +177,8 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
/* FIXME Ignore if checksum incorrect!!! */
while (rlocn->offset) {
if (dev_read(dev_area->dev, dev_area->start + rlocn->offset,
sizeof(vgnamebuf), vgnamebuf)
!= sizeof(vgnamebuf)) {
if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
sizeof(vgnamebuf), vgnamebuf)) {
stack;
return NULL;
}
@@ -214,7 +212,7 @@ static int _raw_holds_vgname(struct format_instance *fid,
{
int r = 0;
if (!dev_open(dev_area->dev, O_RDONLY)) {
if (!dev_open(dev_area->dev)) {
stack;
return 0;
}
@@ -239,7 +237,7 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
char *desc;
uint32_t wrap = 0;
if (!dev_open(area->dev, O_RDONLY)) {
if (!dev_open(area->dev)) {
stack;
return NULL;
}
@@ -264,8 +262,7 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
}
/* FIXME 64-bit */
if (!(vg = text_vg_import_fd(fid, dev_name(area->dev),
dev_fd(area->dev),
if (!(vg = text_vg_import_fd(fid, NULL, area->dev,
(off_t) (area->start + rlocn->offset),
(uint32_t) (rlocn->size - wrap),
(off_t) (area->start + MDA_HEADER_SIZE),
@@ -274,6 +271,9 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
stack;
goto out;
}
log_debug("Read %s metadata (%u) from %s at %" PRIu64 " size %" PRIu64,
vg->name, vg->seqno, dev_name(area->dev),
area->start + rlocn->offset, rlocn->size);
out:
if (!dev_close(area->dev))
@@ -318,7 +318,7 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
if (!found)
return 1;
if (!dev_open(mdac->area.dev, O_RDWR)) {
if (!dev_open(mdac->area.dev)) {
stack;
return 0;
}
@@ -367,9 +367,8 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
mdac->rlocn.offset, mdac->rlocn.size - new_wrap);
/* Write text out, circularly */
if (dev_write(mdac->area.dev, mdac->area.start + mdac->rlocn.offset,
(size_t) (mdac->rlocn.size - new_wrap),
buf) != mdac->rlocn.size - new_wrap) {
if (!dev_write(mdac->area.dev, mdac->area.start + mdac->rlocn.offset,
(size_t) (mdac->rlocn.size - new_wrap), buf)) {
stack;
goto out;
}
@@ -379,11 +378,10 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
dev_name(mdac->area.dev), mdac->area.start +
MDA_HEADER_SIZE, new_wrap);
if (dev_write(mdac->area.dev,
mdac->area.start + MDA_HEADER_SIZE,
(size_t) new_wrap,
buf + mdac->rlocn.size - new_wrap)
!= new_wrap) {
if (!dev_write(mdac->area.dev,
mdac->area.start + MDA_HEADER_SIZE,
(size_t) new_wrap,
buf + mdac->rlocn.size - new_wrap)) {
stack;
goto out;
}
@@ -400,7 +398,7 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
r = 1;
out:
if (!dev_close(mdac->area.dev))
if (!r && !dev_close(mdac->area.dev))
stack;
return r;
@@ -429,11 +427,6 @@ static int _vg_commit_raw(struct format_instance *fid, struct volume_group *vg,
if (!found)
return 1;
if (!dev_open(mdac->area.dev, O_RDWR)) {
stack;
return 0;
}
if (!(mdah = _raw_read_mda_header(fid->fmt, &mdac->area))) {
stack;
goto out;
@@ -466,6 +459,33 @@ static int _vg_commit_raw(struct format_instance *fid, struct volume_group *vg,
return r;
}
/* Close metadata area devices */
static int _vg_revert_raw(struct format_instance *fid, struct volume_group *vg,
struct metadata_area *mda)
{
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
struct physical_volume *pv;
struct list *pvh;
int found = 0;
/* Ignore any mda on a PV outside the VG. vgsplit relies on this */
list_iterate(pvh, &vg->pvs) {
pv = list_item(pvh, struct pv_list)->pv;
if (pv->dev == mdac->area.dev) {
found = 1;
break;
}
}
if (!found)
return 1;
if (!dev_close(mdac->area.dev))
stack;
return 1;
}
static int _vg_remove_raw(struct format_instance *fid, struct volume_group *vg,
struct metadata_area *mda)
{
@@ -474,7 +494,7 @@ static int _vg_remove_raw(struct format_instance *fid, struct volume_group *vg,
struct raw_locn *rlocn;
int r = 0;
if (!dev_open(mdac->area.dev, O_RDWR)) {
if (!dev_open(mdac->area.dev)) {
stack;
return 0;
}
@@ -735,7 +755,7 @@ static int _scan_file(const struct format_type *fmt)
fid = _create_text_instance(fmt, NULL, NULL);
if ((vg = _vg_read_file_name(fid, vgname,
path)))
cache_update_vg(vg);
lvmcache_update_vg(vg);
}
if (closedir(d))
@@ -750,13 +770,10 @@ int vgname_from_mda(const struct format_type *fmt, struct device_area *dev_area,
{
struct raw_locn *rlocn;
struct mda_header *mdah;
int already_open;
unsigned int len;
int r = 0;
already_open = dev_is_open(dev_area->dev);
if (!already_open && !dev_open(dev_area->dev, O_RDONLY)) {
if (!dev_open(dev_area->dev)) {
stack;
return 0;
}
@@ -769,8 +786,8 @@ int vgname_from_mda(const struct format_type *fmt, struct device_area *dev_area,
rlocn = mdah->raw_locns;
while (rlocn->offset) {
if (dev_read(dev_area->dev, dev_area->start + rlocn->offset,
size, buf) != (signed) size) {
if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
size, buf)) {
stack;
goto out;
}
@@ -781,7 +798,7 @@ int vgname_from_mda(const struct format_type *fmt, struct device_area *dev_area,
buf[len] = '\0';
/* Ignore this entry if the characters aren't permissible */
if (!validate_vgname(buf)) {
if (!validate_name(buf)) {
stack;
goto out;
}
@@ -794,7 +811,7 @@ int vgname_from_mda(const struct format_type *fmt, struct device_area *dev_area,
}
out:
if (!already_open && dev_close(dev_area->dev))
if (!dev_close(dev_area->dev))
stack;
return r;
@@ -821,7 +838,7 @@ static int _scan_raw(const struct format_type *fmt)
sizeof(vgnamebuf))) {
if ((vg = _vg_read_raw_area(&fid, vgnamebuf,
&rl->dev_area)))
cache_update_vg(vg);
lvmcache_update_vg(vg);
}
}
@@ -957,7 +974,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
struct list *mdas, int64_t label_sector)
{
struct label *label;
struct cache_info *info;
struct lvmcache_info *info;
struct mda_context *mdac;
struct list *mdash;
struct metadata_area *mda;
@@ -967,8 +984,8 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
/* FIXME Test mode don't update cache? */
if (!(info = cache_add(fmt->labeller, (char *) &pv->id, pv->dev,
ORPHAN, NULL))) {
if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
ORPHAN, NULL))) {
stack;
return 0;
}
@@ -1027,12 +1044,12 @@ 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))) {
UINT64_C(0))) {
stack;
return 0;
}
if (!dev_open(pv->dev, O_RDWR)) {
if (!dev_open(pv->dev)) {
stack;
return 0;
}
@@ -1118,7 +1135,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
{
struct label *label;
struct device *dev;
struct cache_info *info;
struct lvmcache_info *info;
struct metadata_area *mda, *mda_new;
struct mda_context *mdac, *mdac_new;
struct list *mdah, *dah;
@@ -1134,7 +1151,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
stack;
return 0;
}
info = (struct cache_info *) label->info;
info = (struct lvmcache_info *) label->info;
/* Have we already cached vgname? */
if (info->vginfo && info->vginfo->vgname && *info->vginfo->vgname &&
@@ -1144,12 +1161,15 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
}
/* Perform full scan and try again */
cache_label_scan(fmt->cmd, 0);
if (!memlock()) {
lvmcache_label_scan(fmt->cmd, 1);
if (info->vginfo && info->vginfo->vgname && *info->vginfo->vgname &&
_get_pv_from_vg(info->fmt, info->vginfo->vgname, info->dev->pvid,
pv)) {
return 1;
if (info->vginfo && info->vginfo->vgname &&
*info->vginfo->vgname &&
_get_pv_from_vg(info->fmt, info->vginfo->vgname,
info->dev->pvid, pv)) {
return 1;
}
}
/* Orphan */
@@ -1248,7 +1268,8 @@ static struct metadata_area_ops _metadata_text_raw_ops = {
vg_read:_vg_read_raw,
vg_write:_vg_write_raw,
vg_remove:_vg_remove_raw,
vg_commit:_vg_commit_raw
vg_commit:_vg_commit_raw,
vg_revert:_vg_revert_raw
};
/* pvmetadatasize in sectors */
@@ -1262,7 +1283,7 @@ static int _pv_setup(const struct format_type *fmt,
struct metadata_area *mda, *mda_new, *mda2;
struct mda_context *mdac, *mdac_new, *mdac2;
struct list *pvmdas, *pvmdash, *mdash;
struct cache_info *info;
struct lvmcache_info *info;
int found;
uint64_t pe_end = 0;
@@ -1354,7 +1375,7 @@ static struct format_instance *_create_text_instance(const struct format_type
struct raw_list *rl;
struct list *dlh, *dir_list, *rlh, *raw_list, *mdas, *mdash, *infoh;
char path[PATH_MAX];
struct cache_vginfo *vginfo;
struct lvmcache_vginfo *vginfo;
if (!(fid = pool_alloc(fmt->cmd->mem, sizeof(*fid)))) {
log_error("Couldn't allocate format instance object.");
@@ -1422,13 +1443,13 @@ static struct format_instance *_create_text_instance(const struct format_type
}
/* Scan PVs in VG for any further MDAs */
cache_label_scan(fmt->cmd, 0);
lvmcache_label_scan(fmt->cmd, 0);
if (!(vginfo = vginfo_from_vgname(vgname))) {
stack;
goto out;
}
list_iterate(infoh, &vginfo->infos) {
mdas = &(list_item(infoh, struct cache_info)->mdas);
mdas = &(list_item(infoh, struct lvmcache_info)->mdas);
list_iterate(mdash, mdas) {
mda = list_item(mdash, struct metadata_area);
mdac =

View File

@@ -54,7 +54,7 @@ struct volume_group *text_vg_import_file(struct format_instance *fid,
time_t *when, char **desc);
struct volume_group *text_vg_import_fd(struct format_instance *fid,
const char *file,
int fd,
struct device *dev,
off_t offset, uint32_t size,
off_t offset2, uint32_t size2,
checksum_fn_t checksum_fn,

View File

@@ -11,14 +11,14 @@
#include "display.h"
#include "hash.h"
#include "toolcontext.h"
#include "cache.h"
#include "lvmcache.h"
/* FIXME Use tidier inclusion method */
static struct text_vg_version_ops *(_text_vsn_list[2]);
struct volume_group *text_vg_import_fd(struct format_instance *fid,
const char *file,
int fd,
struct device *dev,
off_t offset, uint32_t size,
off_t offset2, uint32_t size2,
checksum_fn_t checksum_fn,
@@ -45,10 +45,9 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
goto out;
}
if ((fd == -1 && !read_config_file(cf, file)) ||
(fd != -1 && !read_config_fd(cf, fd, file, offset, size,
offset2, size2, checksum_fn,
checksum))) {
if ((!dev && !read_config_file(cf, file)) ||
(dev && !read_config_fd(cf, dev, offset, size,
offset2, size2, checksum_fn, checksum))) {
log_error("Couldn't read volume group metadata.");
goto out;
}
@@ -78,6 +77,6 @@ struct volume_group *text_vg_import_file(struct format_instance *fid,
const char *file,
time_t *when, char **desc)
{
return text_vg_import_fd(fid, file, -1, 0, 0, 0, 0, NULL, 0,
return text_vg_import_fd(fid, file, NULL, 0, 0, 0, 0, NULL, 0,
when, desc);
}

View File

@@ -11,7 +11,7 @@
#include "display.h"
#include "hash.h"
#include "toolcontext.h"
#include "cache.h"
#include "lvmcache.h"
typedef int (*section_fn) (struct format_instance * fid, struct pool * mem,
struct volume_group * vg, struct config_node * pvn,
@@ -215,15 +215,15 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
struct hash_table *pv_hash)
{
unsigned int s;
uint32_t stripes = 0;
uint32_t area_count = 0;
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;
uint32_t chunk_size, extents_moved = 0u, seg_status = 0u;
const char *org_name, *cow_name;
struct logical_volume *org, *cow;
struct logical_volume *org, *cow, *lv1;
segment_type_t segtype;
if (!(sn = sn->child)) {
@@ -254,15 +254,33 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
}
if (segtype == SEG_STRIPED) {
if (!_read_int32(sn, "stripe_count", &stripes)) {
if (!_read_int32(sn, "stripe_count", &area_count)) {
log_error("Couldn't read 'stripe_count' for "
"segment '%s'.", sn->key);
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 (!(seg = pool_zalloc(mem, sizeof(*seg) +
(sizeof(seg->area[0]) * stripes)))) {
(sizeof(seg->area[0]) * area_count)))) {
stack;
return 0;
}
@@ -270,9 +288,12 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
seg->lv = lv;
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;
switch (segtype) {
case SEG_MIRROR:
case SEG_SNAPSHOT:
lv->status |= SNAPSHOT;
@@ -316,15 +337,7 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
break;
case SEG_STRIPED:
seg->stripes = stripes;
if (!seg->stripes) {
log_error("Zero stripes *not* allowed for segment '%s'",
sn->key);
return 0;
}
if ((seg->stripes != 1) &&
if ((area_count != 1) &&
!_read_int32(sn, "stripe_size", &seg->stripe_size)) {
log_error("Couldn't read stripe_size for segment '%s'.",
sn->key);
@@ -337,55 +350,78 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
return 0;
}
for (cv = cn->v, s = 0; cv && s < seg->stripes;
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;
uint32_t allocated;
if (cv->type != CFG_STRING) {
log_error(bad, sn->key);
return 0;
}
if (!(pv = hash_lookup(pv_hash, cv->v.str))) {
log_error("Couldn't find physical volume '%s' "
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;
}
seg->area[s].pv = pv;
if (!(cv = cv->next)) {
log_error(bad, sn->key);
return 0;
}
if (cv->type != CFG_INT) {
log_error(bad, sn->key);
return 0;
}
seg->area[s].pe = cv->v.i;
/*
* Adjust the extent counts in the pv and vg.
*/
allocated = seg->len / seg->stripes;
pv->pe_alloc_count += allocated;
vg->free_count -= allocated;
cv = cv->next;
}
/*
* Check we read the correct number of stripes.
*/
if (cv || (s < seg->stripes)) {
log_error("Incorrect number of stripes in 'area' array "
if (cv || (s < seg->area_count)) {
log_error("Incorrect number of areas in area array "
"for segment '%s'.", seg_name);
return 0;
}
@@ -456,9 +492,9 @@ static int _read_segments(struct pool *mem, struct volume_group *vg,
return 1;
}
static int _read_lv(struct format_instance *fid, struct pool *mem,
struct volume_group *vg, struct config_node *lvn,
struct config_node *vgn, struct hash_table *pv_hash)
static int _read_lvnames(struct format_instance *fid, struct pool *mem,
struct volume_group *vg, struct config_node *lvn,
struct config_node *vgn, struct hash_table *pv_hash)
{
struct logical_volume *lv;
struct lv_list *lvl;
@@ -482,17 +518,6 @@ static int _read_lv(struct format_instance *fid, struct pool *mem,
return 0;
}
lv->vg = vg;
/* FIXME: read full lvid */
if (!_read_id(&lv->lvid.id[1], lvn, "id")) {
log_error("Couldn't read uuid for logical volume %s.",
lv->name);
return 0;
}
memcpy(&lv->lvid.id[0], &lv->vg->id, sizeof(lv->lvid.id[0]));
if (!(cn = find_config_node(lvn, "status", '/'))) {
log_error("Couldn't find status flags for logical volume.");
return 0;
@@ -503,12 +528,6 @@ static int _read_lv(struct format_instance *fid, struct pool *mem,
return 0;
}
list_init(&lv->segments);
if (!_read_segments(mem, vg, lv, lvn, pv_hash)) {
stack;
return 0;
}
lv->alloc = ALLOC_DEFAULT;
if ((cn = find_config_node(lvn, "allocation_policy", '/'))) {
struct config_value *cv = cn->v;
@@ -524,6 +543,48 @@ static int _read_lv(struct format_instance *fid, struct pool *mem,
if (!_read_int32(lvn, "read_ahead", &lv->read_ahead))
lv->read_ahead = 0;
list_init(&lv->segments);
lv->vg = vg;
vg->lv_count++;
list_add(&vg->lvs, &lvl->list);
return 1;
}
static int _read_lvsegs(struct format_instance *fid, struct pool *mem,
struct volume_group *vg, struct config_node *lvn,
struct config_node *vgn, struct hash_table *pv_hash)
{
struct logical_volume *lv;
struct lv_list *lvl;
if (!(lvl = find_lv_in_vg(vg, lvn->key))) {
log_error("Lost logical volume reference %s", lvn->key);
return 0;
}
lv = lvl->lv;
if (!(lvn = lvn->child)) {
log_error("Empty logical volume section.");
return 0;
}
/* FIXME: read full lvid */
if (!_read_id(&lv->lvid.id[1], lvn, "id")) {
log_error("Couldn't read uuid for logical volume %s.",
lv->name);
return 0;
}
memcpy(&lv->lvid.id[0], &lv->vg->id, sizeof(lv->lvid.id[0]));
if (!_read_segments(mem, vg, lv, lvn, pv_hash)) {
stack;
return 0;
}
lv->size = (uint64_t) lv->le_count * (uint64_t) vg->extent_size;
/* Skip this for now for snapshots */
@@ -532,12 +593,18 @@ static int _read_lv(struct format_instance *fid, struct pool *mem,
if ((lv->status & FIXED_MINOR) &&
!_read_int32(lvn, "minor", &lv->minor)) {
log_error("Couldn't read minor number for logical "
"volume.");
"volume %s.", lv->name);
return 0;
}
vg->lv_count++;
list_add(&vg->lvs, &lvl->list);
lv->major = -1;
if ((lv->status & FIXED_MINOR) &&
!_read_int32(lvn, "major", &lv->major)) {
log_error("Couldn't read major number for logical "
"volume %s.", lv->name);
}
} else {
vg->lv_count--;
list_del(&lvl->list);
}
return 1;
@@ -681,13 +748,21 @@ static struct volume_group *_read_vg(struct format_instance *fid,
list_init(&vg->lvs);
list_init(&vg->snapshots);
if (!_read_sections(fid, "logical_volumes", _read_lv, mem, vg,
if (!_read_sections(fid, "logical_volumes", _read_lvnames, mem, vg,
vgn, pv_hash, 1)) {
log_error("Couldn't read all logical volumes for volume "
log_error("Couldn't read all logical volume names for volume "
"group %s.", vg->name);
goto bad;
}
if (!_read_sections(fid, "logical_volumes", _read_lvsegs, mem, vg,
vgn, pv_hash, 1)) {
log_error("Couldn't read all logical volumes for "
"volume group %s.", vg->name);
goto bad;
}
hash_destroy(pv_hash);
if (vg->status & PARTIAL_VG) {

View File

@@ -27,7 +27,7 @@ static int _write(struct label *label, char *buf)
{
struct label_header *lh = (struct label_header *) buf;
struct pv_header *pvhdr;
struct cache_info *info;
struct lvmcache_info *info;
struct disk_locn *pvh_dlocn_xl;
struct list *mdash, *dash;
struct metadata_area *mda;
@@ -40,7 +40,7 @@ static int _write(struct label *label, char *buf)
strncpy(lh->type, label->type, sizeof(label->type));
pvhdr = (struct pv_header *) ((void *) buf + xlate32(lh->offset_xl));
info = (struct cache_info *) label->info;
info = (struct lvmcache_info *) label->info;
pvhdr->device_size_xl = xlate64(info->device_size);
memcpy(pvhdr->pv_uuid, &info->dev->pvid, sizeof(struct id));
@@ -185,7 +185,7 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
{
struct label_header *lh = (struct label_header *) buf;
struct pv_header *pvhdr;
struct cache_info *info;
struct lvmcache_info *info;
struct disk_locn *dlocn_xl;
uint64_t offset;
struct list *mdah;
@@ -195,7 +195,7 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
pvhdr = (struct pv_header *) ((void *) buf + xlate32(lh->offset_xl));
if (!(info = cache_add(l, pvhdr->pv_uuid, dev, NULL, NULL)))
if (!(info = lvmcache_add(l, pvhdr->pv_uuid, dev, NULL, NULL)))
return 0;
*label = info->label;
@@ -230,7 +230,7 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
mdac = (struct mda_context *) mda->metadata_locn;
if (vgname_from_mda(info->fmt, &mdac->area, vgnamebuf,
sizeof(vgnamebuf))) {
cache_update_vgname(info, vgnamebuf);
lvmcache_update_vgname(info, vgnamebuf);
}
}
@@ -241,7 +241,7 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
static void _destroy_label(struct labeller *l, struct label *label)
{
struct cache_info *info = (struct cache_info *) label->info;
struct lvmcache_info *info = (struct lvmcache_info *) label->info;
if (info->mdas.n)
del_mdas(&info->mdas);

View File

@@ -9,7 +9,7 @@
#include "list.h"
#include "crc.h"
#include "xlate.h"
#include "cache.h"
#include "lvmcache.h"
#include <sys/stat.h>
#include <fcntl.h>
@@ -104,21 +104,17 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
struct list *lih;
struct labeller_i *li;
struct labeller *r = NULL;
int already_open;
struct label_header *lh;
uint64_t sector;
int found = 0;
char readbuf[LABEL_SCAN_SIZE];
already_open = dev_is_open(dev);
if (!already_open && !dev_open(dev, O_RDONLY)) {
if (!dev_open(dev)) {
stack;
return NULL;
}
if (dev_read(dev, __UINT64_C(0), LABEL_SCAN_SIZE, readbuf) !=
LABEL_SCAN_SIZE) {
if (!dev_read(dev, UINT64_C(0), LABEL_SCAN_SIZE, readbuf)) {
log_debug("%s: Failed to read label area", dev_name(dev));
goto out;
}
@@ -178,7 +174,7 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
log_very_verbose("%s: No label detected", dev_name(dev));
out:
if (!already_open && !dev_close(dev))
if (!dev_close(dev))
stack;
return r;
@@ -200,13 +196,18 @@ int label_remove(struct device *dev)
log_very_verbose("Scanning for labels to wipe from %s", dev_name(dev));
if (!dev_open(dev, O_RDWR)) {
if (!dev_open(dev)) {
stack;
return 0;
}
if (dev_read(dev, __UINT64_C(0), LABEL_SCAN_SIZE, readbuf) !=
LABEL_SCAN_SIZE) {
/*
* We flush the device just in case someone is stupid
* enough to be trying to import an open pv into lvm.
*/
dev_flush(dev);
if (!dev_read(dev, UINT64_C(0), LABEL_SCAN_SIZE, readbuf)) {
log_debug("%s: Failed to read label area", dev_name(dev));
goto out;
}
@@ -236,8 +237,8 @@ int label_remove(struct device *dev)
if (wipe) {
log_info("%s: Wiping label at sector %" PRIu64,
dev_name(dev), sector);
if (dev_write(dev, sector << SECTOR_SHIFT, LABEL_SIZE,
buf) != LABEL_SIZE) {
if (!dev_write(dev, sector << SECTOR_SHIFT, LABEL_SIZE,
buf)) {
log_error("Failed to remove label from %s at "
"sector %" PRIu64, dev_name(dev),
sector);
@@ -278,7 +279,6 @@ int label_write(struct device *dev, struct label *label)
char buf[LABEL_SIZE];
struct label_header *lh = (struct label_header *) buf;
int r = 1;
int already_open;
if ((LABEL_SIZE + (label->sector << SECTOR_SHIFT)) > LABEL_SCAN_SIZE) {
log_error("Label sector %" PRIu64 " beyond range (%ld)",
@@ -298,21 +298,19 @@ int label_write(struct device *dev, struct label *label)
lh->crc_xl = xlate32(calc_crc(INITIAL_CRC, &lh->offset_xl, LABEL_SIZE -
((void *) &lh->offset_xl - (void *) lh)));
already_open = dev_is_open(dev);
if (!already_open && dev_open(dev, O_RDWR)) {
if (!dev_open(dev)) {
stack;
return 0;
}
log_info("%s: Writing label to sector %" PRIu64, dev_name(dev),
label->sector);
if (dev_write(dev, label->sector << SECTOR_SHIFT, LABEL_SIZE, buf) !=
LABEL_SIZE) {
if (!dev_write(dev, label->sector << SECTOR_SHIFT, LABEL_SIZE, buf)) {
log_debug("Failed to write label to %s", dev_name(dev));
r = 0;
}
if (!already_open && dev_close(dev))
if (!dev_close(dev))
stack;
return r;

View File

@@ -7,8 +7,7 @@
#ifndef _LVM_LABEL_H
#define _LVM_LABEL_H
#include "cache.h"
#include "lvm-types.h"
#include "lvmcache.h"
#include "uuid.h"
#include "device.h"

View File

@@ -10,8 +10,6 @@
#include "defaults.h"
#include "sharedlib.h"
#include <dlfcn.h>
static void *_locking_lib = NULL;
static void (*_end_fn) (void) = NULL;
static int (*_lock_fn) (struct cmd_context * cmd, const char *resource,

View File

@@ -13,6 +13,7 @@
#include "defaults.h"
#include "lvm-file.h"
#include "lvm-string.h"
#include "lvmcache.h"
#include <limits.h>
#include <unistd.h>
@@ -34,7 +35,7 @@ static sig_t _oldhandler;
static sigset_t _fullsigset, _intsigset;
static int _handler_installed;
static int _release_lock(const char *file)
static int _release_lock(const char *file, int unlock)
{
struct lock_list *ll;
struct list *llh, *llt;
@@ -46,10 +47,11 @@ static int _release_lock(const char *file)
if (!file || !strcmp(ll->res, file)) {
list_del(llh);
log_very_verbose("Unlocking %s", ll->res);
if (flock(ll->lf, LOCK_NB | LOCK_UN))
log_sys_error("flock", ll->res);
if (unlock) {
log_very_verbose("Unlocking %s", ll->res);
if (flock(ll->lf, LOCK_NB | LOCK_UN))
log_sys_error("flock", ll->res);
}
if (!flock(ll->lf, LOCK_NB | LOCK_EX) &&
!stat(ll->res, &buf1) &&
@@ -74,7 +76,12 @@ static int _release_lock(const char *file)
static void _fin_file_locking(void)
{
_release_lock(NULL);
_release_lock(NULL, 1);
}
static void _reset_file_locking(void)
{
_release_lock(NULL, 0);
}
static void _remove_ctrl_c_handler()
@@ -127,7 +134,7 @@ static int _lock_file(const char *file, int flags)
state = 'W';
break;
case LCK_UNLOCK:
return _release_lock(file);
return _release_lock(file, 1);
default:
log_error("Unrecognised lock type: %d", flags & LCK_TYPE_MASK);
return 0;
@@ -196,24 +203,39 @@ static int _file_lock_resource(struct cmd_context *cmd, const char *resource,
else
lvm_snprintf(lockfile, sizeof(lockfile),
"%s/V_%s", _lock_dir, resource);
if (!_lock_file(lockfile, flags))
return 0;
switch (flags & LCK_TYPE_MASK) {
case LCK_UNLOCK:
lvmcache_unlock_vgname(resource);
break;
default:
lvmcache_lock_vgname(resource,
(flags & LCK_TYPE_MASK) ==
LCK_READ);
}
break;
case LCK_LV:
switch (flags & LCK_TYPE_MASK) {
case LCK_UNLOCK:
log_debug("Unlocking LV %s", resource);
if (!lv_resume_if_active(cmd, resource))
return 0;
break;
case LCK_READ:
log_debug("Locking LV %s (R)", resource);
if (!lv_activate(cmd, resource))
return 0;
break;
case LCK_WRITE:
log_debug("Locking LV %s (W)", resource);
if (!lv_suspend_if_active(cmd, resource))
return 0;
break;
case LCK_EXCL:
log_debug("Locking LV %s (EX)", resource);
if (!lv_deactivate(cmd, resource))
return 0;
break;
@@ -233,6 +255,7 @@ static int _file_lock_resource(struct cmd_context *cmd, const char *resource,
int init_file_locking(struct locking_type *locking, struct config_tree *cf)
{
locking->lock_resource = _file_lock_resource;
locking->reset_locking = _reset_file_locking;
locking->fin_locking = _fin_file_locking;
/* Get lockfile directory from config file */

View File

@@ -14,30 +14,19 @@
#include <signal.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <limits.h>
#include <unistd.h>
static struct locking_type _locking;
static sigset_t _oldset;
static int _lock_count = 0; /* Number of locks held */
static int _write_lock_held = 0;
static int _signals_blocked = 0;
static void _block_signals(int flags)
{
sigset_t set;
if (!_write_lock_held && (flags & LCK_SCOPE_MASK) == LCK_LV &&
(flags & LCK_TYPE_MASK) == LCK_WRITE) {
if (mlockall(MCL_CURRENT | MCL_FUTURE))
log_sys_error("mlockall", "");
else {
log_very_verbose("Locking memory");
_write_lock_held = 1;
}
}
if (_signals_blocked)
return;
@@ -58,15 +47,6 @@ static void _block_signals(int flags)
static void _unblock_signals(void)
{
if (!_lock_count && _write_lock_held) {
if (munlockall()) {
log_very_verbose("Unlocking memory");
log_sys_error("munlockall", "");
}
_write_lock_held = 0;
}
/* Don't unblock signals while any locks are held */
if (!_signals_blocked || _lock_count)
return;
@@ -81,6 +61,18 @@ static void _unblock_signals(void)
return;
}
void reset_locking(void)
{
int was_locked = _lock_count;
_lock_count = 0;
_locking.reset_locking();
if (was_locked)
_unblock_signals();
}
static inline void _update_lock_count(int flags)
{
if ((flags & LCK_TYPE_MASK) == LCK_UNLOCK)
@@ -107,11 +99,13 @@ int init_locking(int type, struct config_tree *cf)
log_very_verbose("File-based locking enabled.");
return 1;
#ifdef HAVE_LIBDL
case 2:
if (!init_external_locking(&_locking, cf))
break;
log_very_verbose("External locking enabled.");
return 1;
#endif
default:
log_error("Unknown locking type requested.");

View File

@@ -11,6 +11,7 @@
int init_locking(int type, struct config_tree *cf);
void fin_locking(void);
void reset_locking(void);
/*
* LCK_VG:

View File

@@ -12,10 +12,12 @@ typedef int (*lock_resource_fn) (struct cmd_context * cmd, const char *resource,
int flags);
typedef void (*fin_lock_fn) (void);
typedef void (*reset_lock_fn) (void);
struct locking_type {
lock_resource_fn lock_resource;
reset_lock_fn reset_locking;
fin_lock_fn fin_locking;
};

View File

@@ -10,6 +10,7 @@
#include "locking_types.h"
#include "lvm-string.h"
#include "activate.h"
#include "lvmcache.h"
#include <signal.h>
@@ -22,11 +23,25 @@ static void _no_fin_locking(void)
return;
}
static void _no_reset_locking(void)
{
return;
}
static int _no_lock_resource(struct cmd_context *cmd, const char *resource,
int flags)
{
switch (flags & LCK_SCOPE_MASK) {
case LCK_VG:
switch (flags & LCK_TYPE_MASK) {
case LCK_UNLOCK:
lvmcache_unlock_vgname(resource);
break;
default:
lvmcache_lock_vgname(resource,
(flags & LCK_TYPE_MASK) ==
LCK_READ);
}
break;
case LCK_LV:
switch (flags & LCK_TYPE_MASK) {
@@ -54,6 +69,7 @@ static int _no_lock_resource(struct cmd_context *cmd, const char *resource,
int init_no_locking(struct locking_type *locking, struct config_tree *cf)
{
locking->lock_resource = _no_lock_resource;
locking->reset_locking = _no_reset_locking;
locking->fin_locking = _no_fin_locking;
return 1;

View File

@@ -5,27 +5,62 @@
*/
#include "lib.h"
#include "device.h"
#include "memlock.h"
#include "lvm-string.h"
#include <stdarg.h>
#include <syslog.h>
static FILE *_log = 0;
static FILE *_log_file;
static struct device _log_dev;
static struct str_list _log_dev_alias;
static int _verbose_level = 0;
static int _test = 0;
static int _partial = 0;
static int _pvmove = 0;
static int _debug_level = 0;
static int _syslog = 0;
static int _log_to_file = 0;
static int _log_direct = 0;
static int _log_while_suspended = 0;
static int _indent = 1;
static int _log_cmd_name = 0;
static int _log_suppress = 0;
static int _ignorelockingfailure = 0;
static char _cmd_name[30] = "";
static char _msg_prefix[30] = " ";
static int _already_logging = 0;
void init_log(FILE *fp)
void init_log_file(const char *log_file, int append)
{
_log = fp;
const char *open_mode = append ? "a" : "w";
if (!(_log_file = fopen(log_file, open_mode))) {
log_sys_error("fopen", log_file);
return;
}
_log_to_file = 1;
}
void init_log_direct(const char *log_file, int append)
{
const char *filename;
int open_flags = append ? 0 : O_TRUNC;
filename = dbg_strdup(log_file);
dev_create_file(filename, &_log_dev, &_log_dev_alias);
if (!dev_open_flags(&_log_dev, O_RDWR | O_CREAT | open_flags, 1, 0))
return;
_log_direct = 1;
}
void init_log_while_suspended(int log_while_suspended)
{
_log_while_suspended = log_while_suspended;
}
void init_syslog(int facility)
@@ -39,9 +74,23 @@ void log_suppress(int suppress)
_log_suppress = suppress;
}
void fin_log()
void release_log_memory(void)
{
_log = 0;
dbg_free((char *) _log_dev_alias.str);
_log_dev_alias.str = "activate_log file";
}
void fin_log(void)
{
if (_log_direct) {
dev_close(&_log_dev);
_log_direct = 0;
}
if (_log_to_file) {
fclose(_log_file);
_log_to_file = 0;
}
}
void fin_syslog()
@@ -68,6 +117,11 @@ void init_partial(int level)
_partial = level;
}
void init_pvmove(int level)
{
_pvmove = level;
}
void init_ignorelockingfailure(int level)
{
_ignorelockingfailure = level;
@@ -107,6 +161,11 @@ int partial_mode()
return _partial;
}
int pvmove_mode()
{
return _pvmove;
}
int ignorelockingfailure()
{
return _ignorelockingfailure;
@@ -125,6 +184,8 @@ int debug_level()
void print_log(int level, const char *file, int line, const char *format, ...)
{
va_list ap;
char buf[1024];
int bufused, n;
if (!_log_suppress) {
va_start(ap, format);
@@ -183,20 +244,48 @@ void print_log(int level, const char *file, int line, const char *format, ...)
if (level > _debug_level)
return;
if (_log) {
fprintf(_log, "%s:%d %s%s", file, line, _cmd_name, _msg_prefix);
if (_log_to_file && (_log_while_suspended || !memlock())) {
fprintf(_log_file, "%s:%d %s%s", file, line, _cmd_name,
_msg_prefix);
va_start(ap, format);
vfprintf(_log, format, ap);
vfprintf(_log_file, format, ap);
va_end(ap);
fprintf(_log, "\n");
fflush(_log);
fprintf(_log_file, "\n");
fflush(_log_file);
}
if (_syslog) {
if (_syslog && (_log_while_suspended || !memlock())) {
va_start(ap, format);
vsyslog(level, format, ap);
va_end(ap);
}
/* FIXME This code is unfinished - pre-extend & condense. */
if (!_already_logging && _log_direct && memlock()) {
_already_logging = 1;
memset(&buf, ' ', sizeof(buf));
bufused = 0;
if ((n = lvm_snprintf(buf, sizeof(buf) - bufused - 1,
"%s:%d %s%s", file, line, _cmd_name,
_msg_prefix)) == -1)
goto done;
bufused += n;
va_start(ap, format);
n = vsnprintf(buf + bufused - 1, sizeof(buf) - bufused - 1,
format, ap);
va_end(ap);
bufused += n;
done:
buf[bufused - 1] = '\n';
buf[bufused] = '\n';
buf[sizeof(buf) - 1] = '\n';
/* FIXME real size bufused */
dev_append(&_log_dev, sizeof(buf), buf);
_already_logging = 0;
}
}

View File

@@ -39,8 +39,11 @@
#define _LOG_ERR 3
#define _LOG_FATAL 2
void init_log(FILE *fp);
void init_log_file(const char *log_file, int append);
void init_log_direct(const char *log_file, int append);
void init_log_while_suspended(int log_while_suspended);
void fin_log(void);
void release_log_memory(void);
void init_syslog(int facility);
void fin_syslog(void);
@@ -48,6 +51,7 @@ void fin_syslog(void);
void init_verbose(int level);
void init_test(int level);
void init_partial(int level);
void init_pvmove(int level);
void init_debug(int level);
void init_cmd_name(int status);
void init_msg_prefix(const char *prefix);
@@ -58,12 +62,16 @@ void set_cmd_name(const char *cmd_name);
int test_mode(void);
int partial_mode(void);
int pvmove_mode(void);
int debug_level(void);
int ignorelockingfailure(void);
/* Suppress messages to stdout/stderr */
void log_suppress(int suppress);
/* Suppress messages to syslog */
void syslog_suppress(int suppress);
void print_log(int level, const char *file, int line, const char *format, ...)
__attribute__ ((format(printf, 4, 5)));
@@ -78,15 +86,17 @@ void print_log(int level, const char *file, int line, const char *format, ...)
#define stack log_debug("<backtrace>") /* Backtrace on error */
#define log_error(fmt, args...) log_err(fmt , ## args)
#define log_print(fmt, args...) log_warn(fmt , ## args)
#define log_verbose(fmt, args...) log_notice(fmt , ## args)
#define log_very_verbose(fmt, args...) log_info(fmt , ## args)
#define log_error(args...) log_err(args)
#define log_print(args...) log_warn(args)
#define log_verbose(args...) log_notice(args)
#define log_very_verbose(args...) log_info(args)
/* Two System call equivalents */
#define log_sys_error(x, y) \
log_err("%s: %s failed: %s", y, x, strerror(errno))
#define log_sys_very_verbose(x, y) \
log_info("%s: %s failed: %s", y, x, strerror(errno))
#define log_sys_debug(x, y) \
log_debug("%s: %s failed: %s", y, x, strerror(errno))
#endif

View File

@@ -6,6 +6,7 @@
#include "lib.h"
#include "metadata.h"
#include "locking.h"
#include "pv_map.h"
#include "lvm-string.h"
#include "toolcontext.h"
@@ -19,9 +20,12 @@ static void _get_extents(struct lv_segment *seg)
unsigned int s, count;
struct physical_volume *pv;
for (s = 0; s < seg->stripes; s++) {
pv = seg->area[s].pv;
count = seg->len / seg->stripes;
for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_PV)
continue;
pv = seg->area[s].u.pv.pv;
count = seg->area_len;
pv->pe_alloc_count += count;
}
}
@@ -31,12 +35,17 @@ static void _put_extents(struct lv_segment *seg)
unsigned int s, count;
struct physical_volume *pv;
for (s = 0; s < seg->stripes; s++) {
pv = seg->area[s].pv;
count = seg->len / seg->stripes;
for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_PV)
continue;
assert(pv->pe_alloc_count >= count);
pv->pe_alloc_count -= count;
pv = seg->area[s].u.pv.pv;
if (pv) {
count = seg->area_len;
assert(pv->pe_alloc_count >= count);
pv->pe_alloc_count -= count;
}
}
}
@@ -58,13 +67,13 @@ static int _alloc_stripe_area(struct logical_volume *lv, uint32_t stripes,
struct pv_area **areas, uint32_t *ix)
{
uint32_t count = lv->le_count - *ix;
uint32_t per_area = count / stripes;
uint32_t area_len = count / stripes;
uint32_t smallest = areas[stripes - 1]->count;
uint32_t s;
struct lv_segment *seg;
if (smallest < per_area)
per_area = smallest;
if (smallest < area_len)
area_len = smallest;
if (!(seg = _alloc_segment(lv->vg->cmd->mem, stripes))) {
log_err("Couldn't allocate new stripe segment.");
@@ -74,15 +83,17 @@ static int _alloc_stripe_area(struct logical_volume *lv, uint32_t stripes,
seg->lv = lv;
seg->type = SEG_STRIPED;
seg->le = *ix;
seg->len = per_area * stripes;
seg->stripes = stripes;
seg->len = area_len * stripes;
seg->area_len = area_len;
seg->area_count = stripes;
seg->stripe_size = stripe_size;
for (s = 0; s < stripes; s++) {
struct pv_area *pva = areas[s];
seg->area[s].pv = pva->map->pv;
seg->area[s].pe = pva->start;
consume_pv_area(pva, per_area);
seg->area[s].type = AREA_PV;
seg->area[s].u.pv.pv = pva->map->pvl->pv;
seg->area[s].u.pv.pe = pva->start;
consume_pv_area(pva, area_len);
}
list_add(&lv->segments, &seg->list);
@@ -186,10 +197,12 @@ static int _alloc_linear_area(struct logical_volume *lv, uint32_t *ix,
seg->type = SEG_STRIPED;
seg->le = *ix;
seg->len = count;
seg->area_len = count;
seg->stripe_size = 0;
seg->stripes = 1;
seg->area[0].pv = map->pv;
seg->area[0].pe = pva->start;
seg->area_count = 1;
seg->area[0].type = AREA_PV;
seg->area[0].u.pv.pv = map->pvl->pv;
seg->area[0].u.pv.pe = pva->start;
list_add(&lv->segments, &seg->list);
@@ -198,6 +211,47 @@ static int _alloc_linear_area(struct logical_volume *lv, uint32_t *ix,
return 1;
}
static int _alloc_mirrored_area(struct logical_volume *lv, uint32_t *ix,
struct pv_map *map, struct pv_area *pva,
struct physical_volume *mirrored_pv,
uint32_t mirrored_pe)
{
uint32_t count, remaining;
struct lv_segment *seg;
count = pva->count;
remaining = lv->le_count - *ix;
if (count > remaining)
count = remaining;
if (!(seg = _alloc_segment(lv->vg->cmd->mem, 2))) {
log_err("Couldn't allocate new mirrored segment.");
return 0;
}
seg->lv = lv;
seg->type = SEG_MIRRORED;
seg->status = 0u;
seg->le = *ix;
seg->len = count;
seg->area_len = count;
seg->stripe_size = 0;
seg->area_count = 2;
seg->extents_moved = 0u;
/* FIXME Remove AREA_PV restriction here? */
seg->area[0].type = AREA_PV;
seg->area[0].u.pv.pv = mirrored_pv;
seg->area[0].u.pv.pe = mirrored_pe;
seg->area[1].type = AREA_PV;
seg->area[1].u.pv.pv = map->pvl->pv;
seg->area[1].u.pv.pe = pva->start;
list_add(&lv->segments, &seg->list);
consume_pv_area(pva, count);
*ix += count;
return 1;
}
/*
* Only one area per pv is allowed, so we search
* for the biggest area, or the first area that
@@ -222,14 +276,15 @@ static int _alloc_contiguous(struct logical_volume *lv,
/* first item in the list is the biggest */
pva = list_item(pvm->areas.n, struct pv_area);
if (pva->count < lv->le_count)
continue;
if (!_alloc_linear_area(lv, &allocated, pvm, pva)) {
stack;
return 0;
}
if (allocated == lv->le_count)
break;
break;
}
if (allocated != lv->le_count) {
@@ -242,6 +297,50 @@ static int _alloc_contiguous(struct logical_volume *lv,
return 1;
}
/* FIXME Contiguous depends on *segment* (i.e. stripe) not LV */
static int _alloc_mirrored(struct logical_volume *lv,
struct list *pvms, uint32_t allocated,
struct physical_volume *mirrored_pv,
uint32_t mirrored_pe)
{
struct list *tmp1;
struct pv_map *pvm;
struct pv_area *pva;
uint32_t max_found = 0;
/* Try each PV in turn */
list_iterate(tmp1, pvms) {
pvm = list_item(tmp1, struct pv_map);
if (list_empty(&pvm->areas))
continue;
/* first item in the list is the biggest */
pva = list_item(pvm->areas.n, struct pv_area);
if (pva->count < lv->le_count - allocated) {
max_found = pva->count;
continue;
}
if (!_alloc_mirrored_area(lv, &allocated, pvm, pva,
mirrored_pv, mirrored_pe)) {
stack;
return 0;
}
break;
}
if (allocated != lv->le_count) {
log_error("Insufficient contiguous allocatable extents (%u) "
"for logical volume %s: %u required",
allocated + max_found, lv->name, lv->le_count);
return 0;
}
return 1;
}
/*
* Areas just get allocated in order until the lv
* is full.
@@ -279,12 +378,15 @@ static int _alloc_next_free(struct logical_volume *lv,
* Chooses a correct allocation policy.
*/
static int _allocate(struct volume_group *vg, struct logical_volume *lv,
struct list *acceptable_pvs, uint32_t allocated,
uint32_t stripes, uint32_t stripe_size)
struct list *allocatable_pvs, uint32_t allocated,
uint32_t stripes, uint32_t stripe_size,
struct physical_volume *mirrored_pv, uint32_t mirrored_pe,
uint32_t status)
{
int r = 0;
struct pool *scratch;
struct list *pvms, *old_tail = lv->segments.p, *segh;
struct lv_segment *seg;
if (!(scratch = pool_create(1024))) {
stack;
@@ -294,12 +396,15 @@ static int _allocate(struct volume_group *vg, struct logical_volume *lv,
/*
* Build the sets of available areas on the pv's.
*/
if (!(pvms = create_pv_maps(scratch, vg, acceptable_pvs)))
if (!(pvms = create_pv_maps(scratch, vg, allocatable_pvs)))
goto out;
if (stripes > 1)
r = _alloc_striped(lv, pvms, allocated, stripes, stripe_size);
else if (mirrored_pv)
r = _alloc_mirrored(lv, pvms, allocated, mirrored_pv,
mirrored_pe);
else if (lv->alloc == ALLOC_CONTIGUOUS)
r = _alloc_contiguous(lv, pvms, allocated);
@@ -319,8 +424,11 @@ static int _allocate(struct volume_group *vg, struct logical_volume *lv,
* Iterate through the new segments, updating pe
* counts in pv's.
*/
for (segh = lv->segments.p; segh != old_tail; segh = segh->p)
_get_extents(list_item(segh, struct lv_segment));
for (segh = lv->segments.p; segh != old_tail; segh = segh->p) {
seg = list_item(segh, struct lv_segment);
_get_extents(seg);
seg->status = status;
}
} else {
/*
* Put the segment list back how we found it.
@@ -334,7 +442,7 @@ static int _allocate(struct volume_group *vg, struct logical_volume *lv,
return r;
}
static char *_generate_lv_name(struct volume_group *vg,
static char *_generate_lv_name(struct volume_group *vg, const char *format,
char *buffer, size_t len)
{
struct list *lvh;
@@ -344,19 +452,86 @@ static char *_generate_lv_name(struct volume_group *vg,
list_iterate(lvh, &vg->lvs) {
lv = (list_item(lvh, struct lv_list)->lv);
if (sscanf(lv->name, "lvol%d", &i) != 1)
if (sscanf(lv->name, format, &i) != 1)
continue;
if (i > high)
high = i;
}
if (lvm_snprintf(buffer, len, "lvol%d", high + 1) < 0)
if (lvm_snprintf(buffer, len, format, high + 1) < 0)
return NULL;
return buffer;
}
struct logical_volume *lv_create_empty(struct format_instance *fi,
const char *name,
const char *name_format,
uint32_t status,
alloc_policy_t alloc,
struct volume_group *vg)
{
struct cmd_context *cmd = vg->cmd;
struct lv_list *ll = NULL;
struct logical_volume *lv;
char dname[32];
if (vg->max_lv == vg->lv_count) {
log_error("Maximum number of logical volumes (%u) reached "
"in volume group %s", vg->max_lv, vg->name);
return NULL;
}
if (!name && !(name = _generate_lv_name(vg, name_format, dname,
sizeof(dname)))) {
log_error("Failed to generate unique name for the new "
"logical volume");
return NULL;
}
log_verbose("Creating logical volume %s", name);
if (!(ll = pool_zalloc(cmd->mem, sizeof(*ll))) ||
!(ll->lv = pool_zalloc(cmd->mem, sizeof(*ll->lv)))) {
log_error("lv_list allocation failed");
if (ll)
pool_free(cmd->mem, ll);
return NULL;
}
lv = ll->lv;
lv->vg = vg;
if (!(lv->name = pool_strdup(cmd->mem, name))) {
log_error("lv name strdup failed");
if (ll)
pool_free(cmd->mem, ll);
return NULL;
}
lv->status = status;
lv->alloc = alloc;
lv->read_ahead = 0;
lv->major = -1;
lv->minor = -1;
lv->size = UINT64_C(0);
lv->le_count = 0;
list_init(&lv->segments);
if (fi->fmt->ops->lv_setup && !fi->fmt->ops->lv_setup(fi, lv)) {
stack;
if (ll)
pool_free(cmd->mem, ll);
return NULL;
}
vg->lv_count++;
list_add(&vg->lvs, &ll->list);
return lv;
}
struct logical_volume *lv_create(struct format_instance *fi,
const char *name,
uint32_t status,
@@ -365,12 +540,9 @@ struct logical_volume *lv_create(struct format_instance *fi,
uint32_t stripe_size,
uint32_t extents,
struct volume_group *vg,
struct list *acceptable_pvs)
struct list *allocatable_pvs)
{
struct cmd_context *cmd = vg->cmd;
struct lv_list *ll = NULL;
struct logical_volume *lv;
char dname[32];
if (!extents) {
log_error("Unable to create logical volume %s with no extents",
@@ -384,70 +556,33 @@ struct logical_volume *lv_create(struct format_instance *fi,
return NULL;
}
if (vg->max_lv == vg->lv_count) {
log_error("Maximum number of logical volumes (%u) reached "
"in volume group %s", vg->max_lv, vg->name);
return NULL;
}
if (stripes > list_size(acceptable_pvs)) {
if (stripes > list_size(allocatable_pvs)) {
log_error("Number of stripes (%u) must not exceed "
"number of physical volumes (%d)", stripes,
list_size(acceptable_pvs));
list_size(allocatable_pvs));
return NULL;
}
if (!name && !(name = _generate_lv_name(vg, dname, sizeof(dname)))) {
log_error("Failed to generate unique name for the new "
"logical volume");
return NULL;
}
log_verbose("Creating logical volume %s", name);
if (!(ll = pool_zalloc(cmd->mem, sizeof(*ll))) ||
!(ll->lv = pool_zalloc(cmd->mem, sizeof(*ll->lv)))) {
if (!(lv = lv_create_empty(fi, name, "lvol%d", status, alloc, vg))) {
stack;
return NULL;
}
lv = ll->lv;
lv->vg = vg;
if (!(lv->name = pool_strdup(cmd->mem, name))) {
stack;
goto bad;
}
lv->status = status;
lv->alloc = alloc;
lv->read_ahead = 0;
lv->minor = -1;
lv->size = (uint64_t) extents *vg->extent_size;
lv->le_count = extents;
list_init(&lv->segments);
if (!_allocate(vg, lv, acceptable_pvs, 0u, stripes, stripe_size)) {
if (!_allocate(vg, lv, allocatable_pvs, 0u, stripes, stripe_size,
NULL, 0u, 0u)) {
stack;
goto bad;
return NULL;
}
if (fi->fmt->ops->lv_setup && !fi->fmt->ops->lv_setup(fi, lv)) {
stack;
goto bad;
return NULL;
}
vg->lv_count++;
list_add(&vg->lvs, &ll->list);
return lv;
bad:
if (ll)
pool_free(cmd->mem, ll);
return NULL;
}
int lv_reduce(struct format_instance *fi,
@@ -490,7 +625,7 @@ int lv_reduce(struct format_instance *fi,
int lv_extend(struct format_instance *fi,
struct logical_volume *lv,
uint32_t stripes, uint32_t stripe_size,
uint32_t extents, struct list *acceptable_pvs)
uint32_t extents, struct list *allocatable_pvs)
{
uint32_t old_le_count = lv->le_count;
uint64_t old_size = lv->size;
@@ -498,10 +633,11 @@ int lv_extend(struct format_instance *fi,
lv->le_count += extents;
lv->size += (uint64_t) extents *lv->vg->extent_size;
if (!_allocate(lv->vg, lv, acceptable_pvs, old_le_count,
stripes, stripe_size)) {
if (!_allocate(lv->vg, lv, allocatable_pvs, old_le_count,
stripes, stripe_size, NULL, 0u, 0u)) {
lv->le_count = old_le_count;
lv->size = old_size;
stack;
return 0;
}
@@ -519,6 +655,35 @@ int lv_extend(struct format_instance *fi,
return 1;
}
int lv_extend_mirror(struct format_instance *fid,
struct logical_volume *lv,
struct physical_volume *mirrored_pv,
uint32_t mirrored_pe,
uint32_t extents, struct list *allocatable_pvs,
uint32_t status)
{
uint32_t old_le_count = lv->le_count;
uint64_t old_size = lv->size;
lv->le_count += extents;
lv->size += (uint64_t) extents *lv->vg->extent_size;
if (!_allocate(lv->vg, lv, allocatable_pvs, old_le_count,
1, extents, mirrored_pv, mirrored_pe, status)) {
lv->le_count = old_le_count;
lv->size = old_size;
stack;
return 0;
}
if (fid->fmt->ops->lv_setup && !fid->fmt->ops->lv_setup(fid, lv)) {
stack;
return 0;
}
return 1;
}
int lv_remove(struct volume_group *vg, struct logical_volume *lv)
{
struct list *segh;
@@ -541,3 +706,36 @@ int lv_remove(struct volume_group *vg, struct logical_volume *lv)
return 1;
}
/* Unlock list of LVs */
int unlock_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;
unlock_lv(cmd, lv->lvid.s);
}
return 1;
}
/* Lock a list of LVs */
int lock_lvs(struct cmd_context *cmd, struct list *lvs, int flags)
{
struct list *lvh;
struct logical_volume *lv;
list_iterate(lvh, lvs) {
lv = list_item(lvh, struct lv_list)->lv;
if (!lock_vol(cmd, lv->lvid.s, flags)) {
log_error("Failed to lock %s", lv->name);
/* FIXME Only unlock the locked ones */
unlock_lvs(cmd, lvs);
return 0;
}
}
return 1;
}

View File

@@ -20,20 +20,26 @@ static int _merge(struct lv_segment *first, struct lv_segment *second)
if (!first ||
(first->type != SEG_STRIPED) ||
(first->type != second->type) ||
(first->stripes != second->stripes) ||
(first->area_count != second->area_count) ||
(first->stripe_size != second->stripe_size))
return 0;
for (s = 0; s < first->stripes; s++) {
width = first->len / first->stripes;
for (s = 0; s < first->area_count; s++) {
width = first->area_len;
if ((first->area[s].pv != second->area[s].pv) ||
(first->area[s].pe + width != second->area[s].pe))
/* FIXME Relax this to first type != second type ? */
if (first->area[s].type != AREA_PV ||
second->area[s].type != AREA_PV)
return 0;
if ((first->area[s].u.pv.pv != second->area[s].u.pv.pv) ||
(first->area[s].u.pv.pe + width != second->area[s].u.pv.pe))
return 0;
}
/* we should merge */
first->len += second->len;
first->area_len += second->area_len;
return 1;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2001 Sistina Software (UK) Limited.
* Copyright (C) 2001-2003 Sistina Software (UK) Limited.
*
* This file is released under the LGPL.
*/
@@ -10,7 +10,8 @@
#include "metadata.h"
#include "toolcontext.h"
#include "lvm-string.h"
#include "cache.h"
#include "lvmcache.h"
#include "memlock.h"
static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg,
const char *pv_name)
@@ -23,14 +24,14 @@ static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg,
log_verbose("Adding physical volume '%s' to volume group '%s'",
pv_name, vg->name);
if (!(pvl = pool_alloc(mem, sizeof(*pvl)))) {
if (!(pvl = pool_zalloc(mem, sizeof(*pvl)))) {
log_error("pv_list allocation for '%s' failed", pv_name);
return 0;
}
list_init(&mdas);
if (!(pv = pv_read(fid->fmt->cmd, pv_name, &mdas, NULL))) {
log_error("Failed to read existing physical volume '%s'",
log_error("%s not identified as an existing physical volume",
pv_name);
return 0;
}
@@ -68,8 +69,8 @@ static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg,
pv->pe_alloc_count = 0;
if (!fid->fmt->ops->pv_setup(fid->fmt, __UINT64_C(0), 0,
vg->extent_size, 0, __UINT64_C(0),
if (!fid->fmt->ops->pv_setup(fid->fmt, UINT64_C(0), 0,
vg->extent_size, 0, UINT64_C(0),
&fid->metadata_areas, pv, vg)) {
log_error("Format-specific setup of physical volume '%s' "
"failed.", pv_name);
@@ -157,6 +158,7 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name,
struct volume_group *vg;
struct pool *mem = cmd->mem;
int consistent = 0;
int old_partial;
if (!(vg = pool_zalloc(mem, sizeof(*vg)))) {
stack;
@@ -164,12 +166,13 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name,
}
/* is this vg name already in use ? */
old_partial = partial_mode();
init_partial(1);
if (vg_read(cmd, vg_name, &consistent)) {
log_err("A volume group called '%s' already exists.", vg_name);
goto bad;
}
init_partial(0);
init_partial(old_partial);
if (!id_create(&vg->id)) {
log_err("Couldn't create uuid for volume group '%s'.", vg_name);
@@ -318,6 +321,18 @@ struct pv_list *find_pv_in_vg(struct volume_group *vg, const char *pv_name)
return NULL;
}
int pv_is_in_vg(struct volume_group *vg, struct physical_volume *pv)
{
struct list *pvh;
list_iterate(pvh, &vg->pvs) {
if (pv == list_item(pvh, struct pv_list)->pv)
return 1;
}
return 0;
}
struct physical_volume *find_pv_in_vg_by_uuid(struct volume_group *vg,
struct id *id)
{
@@ -389,6 +404,21 @@ struct physical_volume *find_pv(struct volume_group *vg, struct device *dev)
return NULL;
}
/* Find segment at a given logical extent in an LV */
struct lv_segment *find_seg_by_le(struct logical_volume *lv, uint32_t le)
{
struct list *segh;
struct lv_segment *seg;
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
if (le >= seg->le && le < seg->le + seg->len)
return seg;
}
return NULL;
}
int vg_remove(struct volume_group *vg)
{
struct list *mdah;
@@ -408,11 +438,14 @@ int vg_remove(struct volume_group *vg)
return 1;
}
/*
* After vg_write() returns success,
* caller MUST call either vg_commit() or vg_revert()
*/
int vg_write(struct volume_group *vg)
{
struct list *mdah;
struct list *mdah, *mdah2;
struct metadata_area *mda;
int cache_updated = 0;
if (vg->status & PARTIAL_VG) {
log_error("Cannot change metadata for partial volume group %s",
@@ -432,21 +465,61 @@ int vg_write(struct volume_group *vg)
mda = list_item(mdah, struct metadata_area);
if (!mda->ops->vg_write(vg->fid, vg, mda)) {
stack;
/* Revert */
list_uniterate(mdah2, &vg->fid->metadata_areas, mdah) {
mda = list_item(mdah2, struct metadata_area);
if (mda->ops->vg_revert &&
!mda->ops->vg_revert(vg->fid, vg, mda)) {
stack;
}
}
return 0;
}
}
return 1;
}
/* Commit pending changes */
int vg_commit(struct volume_group *vg)
{
struct list *mdah;
struct metadata_area *mda;
int cache_updated = 0;
int failed = 0;
/* Commit to each copy of the metadata area */
list_iterate(mdah, &vg->fid->metadata_areas) {
mda = list_item(mdah, struct metadata_area);
if (!cache_updated) {
cache_update_vg(vg);
cache_updated = 1;
}
failed = 0;
if (mda->ops->vg_commit &&
!mda->ops->vg_commit(vg->fid, vg, mda)) {
stack;
return 0;
failed = 1;
}
/* Update cache first time we succeed */
if (!failed && !cache_updated) {
lvmcache_update_vg(vg);
cache_updated = 1;
}
}
/* If at least one mda commit succeeded, it was committed */
return cache_updated;
}
/* Don't commit any pending changes */
int vg_revert(struct volume_group *vg)
{
struct list *mdah;
struct metadata_area *mda;
list_iterate(mdah, &vg->fid->metadata_areas) {
mda = list_item(mdah, struct metadata_area);
if (mda->ops->vg_revert &&
!mda->ops->vg_revert(vg->fid, vg, mda)) {
stack;
}
}
@@ -456,7 +529,7 @@ int vg_write(struct volume_group *vg)
/* Make orphan PVs look like a VG */
static struct volume_group *_vg_read_orphans(struct cmd_context *cmd)
{
struct cache_vginfo *vginfo;
struct lvmcache_vginfo *vginfo;
struct list *ih;
struct device *dev;
struct pv_list *pvl;
@@ -482,7 +555,7 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd)
}
list_iterate(ih, &vginfo->infos) {
dev = list_item(ih, struct cache_info)->dev;
dev = list_item(ih, struct lvmcache_info)->dev;
if (!(pv = pv_read(cmd, dev_name(dev), NULL, NULL))) {
continue;
}
@@ -523,9 +596,13 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
/* Find the vgname in the cache */
/* If it's not there we must do full scan to be completely sure */
if (!(fmt = fmt_from_vgname(vgname))) {
cache_label_scan(cmd, 0);
lvmcache_label_scan(cmd, 0);
if (!(fmt = fmt_from_vgname(vgname))) {
cache_label_scan(cmd, 1);
if (memlock()) {
stack;
return NULL;
}
lvmcache_label_scan(cmd, 1);
if (!(fmt = fmt_from_vgname(vgname))) {
stack;
return NULL;
@@ -564,7 +641,7 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
return NULL;
}
cache_update_vg(correct_vg);
lvmcache_update_vg(correct_vg);
if (inconsistent) {
if (!*consistent)
@@ -587,8 +664,15 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
}
}
*consistent = 1;
if ((correct_vg->status & PVMOVE) && !pvmove_mode()) {
log_error("WARNING: Interrupted pvmove detected in "
"volume group %s", vg->name);
log_error("Please restore the metadata by running "
"vgcfgrestore.");
return NULL;
}
*consistent = 1;
return correct_vg;
}
@@ -598,10 +682,10 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
*/
struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid)
{
char *vgname;
struct list *vgnames, *slh;
// const char *vgname;
// struct list *vgnames, *slh;
struct volume_group *vg;
struct cache_vginfo *vginfo;
struct lvmcache_vginfo *vginfo;
int consistent = 0;
/* Is corresponding vgname already cached? */
@@ -618,7 +702,14 @@ struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid)
}
}
/* The slow way - full scan required to cope with vgrename */
return NULL;
/* FIXME Need a genuine read by ID here - don't vg_read by name! */
/* FIXME Disabled vgrenames while active for now because we aren't
* allowed to do a full scan here any more. */
/*** FIXME Cope with vgrename here
// The slow way - full scan required to cope with vgrename
if (!(vgnames = get_vgs(cmd, 1))) {
log_error("vg_read_by_vgid: get_vgs failed");
return NULL;
@@ -627,7 +718,7 @@ struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid)
list_iterate(slh, vgnames) {
vgname = list_item(slh, struct str_list)->str;
if (!vgname || !*vgname)
continue; /* FIXME Unnecessary? */
continue; // FIXME Unnecessary?
consistent = 0;
if ((vg = vg_read(cmd, vgname, &consistent)) &&
!strncmp(vg->id.uuid, vgid, ID_LEN)) {
@@ -641,6 +732,7 @@ struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid)
}
return NULL;
***/
}
/* Only called by activate.c */
@@ -677,7 +769,7 @@ struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
{
struct physical_volume *pv;
struct label *label;
struct cache_info *info;
struct lvmcache_info *info;
struct device *dev;
if (!(dev = dev_cache_get(pv_name, cmd->filter))) {
@@ -686,17 +778,16 @@ struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
}
if (!(label_read(dev, &label))) {
log_error("Failed to read label on physical volume %s",
pv_name);
log_error("No physical volume label read from %s", pv_name);
return 0;
}
info = (struct cache_info *) label->info;
info = (struct lvmcache_info *) label->info;
if (label_sector && *label_sector)
*label_sector = label->sector;
if (!(pv = pool_zalloc(cmd->mem, sizeof(*pv)))) {
log_error("pv_list allocation for '%s' failed", pv_name);
log_error("pv allocation for '%s' failed", pv_name);
return 0;
}
@@ -716,19 +807,21 @@ struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
/* May return empty list */
struct list *get_vgs(struct cmd_context *cmd, int full_scan)
{
return cache_get_vgnames(cmd, full_scan);
return lvmcache_get_vgnames(cmd, full_scan);
}
struct list *get_pvs(struct cmd_context *cmd)
{
struct list *results;
char *vgname;
const char *vgname;
struct list *pvh, *tmp;
struct list *vgnames, *slh;
struct volume_group *vg;
int consistent = 0;
int old_partial;
int old_pvmove;
cache_label_scan(cmd, 0);
lvmcache_label_scan(cmd, 0);
if (!(results = pool_alloc(cmd->mem, sizeof(*results)))) {
log_error("PV list allocation failed");
@@ -745,7 +838,10 @@ struct list *get_pvs(struct cmd_context *cmd)
/* Read every VG to ensure cache consistency */
/* Orphan VG is last on list */
old_partial = partial_mode();
old_pvmove = pvmove_mode();
init_partial(1);
init_pvmove(1);
list_iterate(slh, vgnames) {
vgname = list_item(slh, struct str_list)->str;
if (!vgname)
@@ -764,7 +860,8 @@ struct list *get_pvs(struct cmd_context *cmd)
list_add(results, pvh);
}
}
init_partial(0);
init_pvmove(old_pvmove);
init_partial(old_partial);
return results;
}

View File

@@ -12,17 +12,13 @@
#include "ctype.h"
#include "dev-cache.h"
#include "list.h"
#include "uuid.h"
#include <sys/types.h>
#include <asm/page.h>
#define NAME_LEN 128
#define MAX_STRIPES 128
#define SECTOR_SHIFT 9L
#define SECTOR_SIZE ( 1L << SECTOR_SHIFT )
#define STRIPE_SIZE_MIN ( PAGE_SIZE >> SECTOR_SHIFT) /* PAGESIZE in sectors */
#define STRIPE_SIZE_MIN ( getpagesize() >> SECTOR_SHIFT) /* PAGESIZE in sectors */
#define STRIPE_SIZE_MAX ( 512L * 1024L >> SECTOR_SHIFT) /* 512 KB in sectors */
#define PV_MIN_SIZE ( 512L * 1024L >> SECTOR_SHIFT) /* 512 KB in sectors */
#define PE_ALIGN (65536UL >> SECTOR_SHIFT) /* PE alignment */
@@ -42,7 +38,9 @@
#define VISIBLE_LV 0x00000040 /* LV */
#define FIXED_MINOR 0x00000080 /* LV */
/* FIXME Remove when metadata restructuring is completed */
#define SNAPSHOT 0x00001000 /* LV - temp internal use only */
#define SNAPSHOT 0x00001000 /* LV - tmp internal use only */
#define PVMOVE 0x00002000 /* VG LV SEG */
#define LOCKED 0x00004000 /* LV */
#define LVM_READ 0x00000100 /* LV VG */
#define LVM_WRITE 0x00000200 /* LV VG */
@@ -62,9 +60,14 @@ typedef enum {
typedef enum {
SEG_STRIPED,
SEG_SNAPSHOT,
SEG_MIRROR
SEG_MIRRORED
} segment_type_t;
typedef enum {
AREA_PV,
AREA_LV
} area_type_t;
struct cmd_context;
struct format_handler;
struct labeller;
@@ -123,6 +126,8 @@ struct metadata_area_ops {
struct metadata_area * mda);
int (*vg_commit) (struct format_instance * fid,
struct volume_group * vg, struct metadata_area * mda);
int (*vg_revert) (struct format_instance * fid,
struct volume_group * vg, struct metadata_area * mda);
int (*vg_remove) (struct format_instance * fi, struct volume_group * vg,
struct metadata_area * mda);
};
@@ -177,17 +182,30 @@ struct lv_segment {
uint32_t le;
uint32_t len;
uint32_t status;
/* FIXME Fields depend on segment type */
uint32_t stripe_size;
uint32_t stripes;
uint32_t area_count;
uint32_t area_len;
struct logical_volume *origin;
struct logical_volume *cow;
uint32_t chunk_size;
uint32_t extents_moved;
/* There will be one area for each stripe */
struct {
struct physical_volume *pv;
uint32_t pe;
area_type_t type;
union {
struct {
struct physical_volume *pv;
uint32_t pe;
} pv;
struct {
struct logical_volume *lv;
uint32_t le;
} lv;
} u;
} area[0];
};
@@ -200,6 +218,7 @@ struct logical_volume {
uint32_t status;
alloc_policy_t alloc;
uint32_t read_ahead;
int32_t major;
int32_t minor;
uint64_t size;
@@ -223,10 +242,17 @@ struct name_list {
char *name;
};
struct alloc_area {
struct list list;
uint32_t start; /* PEs */
uint32_t count; /* PEs */
};
struct pv_list {
struct list list;
struct physical_volume *pv;
struct list *mdas;
struct list *mdas; /* Metadata areas */
struct list *alloc_areas; /* Areas we may allocate from */
};
struct lv_list {
@@ -314,6 +340,8 @@ struct format_handler {
* Utility functions
*/
int vg_write(struct volume_group *vg);
int vg_commit(struct volume_group *vg);
int vg_revert(struct volume_group *vg);
struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name,
int *consistent);
struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid);
@@ -360,8 +388,16 @@ struct logical_volume *lv_create(struct format_instance *fi,
uint32_t stripe_size,
uint32_t extents,
struct volume_group *vg,
struct list *acceptable_pvs);
struct list *allocatable_pvs);
struct logical_volume *lv_create_empty(struct format_instance *fi,
const char *name,
const char *name_format,
uint32_t status,
alloc_policy_t alloc,
struct volume_group *vg);
/* Manipulate LVs */
int lv_reduce(struct format_instance *fi,
struct logical_volume *lv, uint32_t extents);
@@ -371,6 +407,17 @@ int lv_extend(struct format_instance *fi,
uint32_t stripe_size,
uint32_t extents, struct list *allocatable_pvs);
int lv_extend_mirror(struct format_instance *fid,
struct logical_volume *lv,
struct physical_volume *mirrored_pv,
uint32_t mirrored_pe,
uint32_t extents, struct list *allocatable_pvs,
uint32_t status);
/* Lock list of LVs */
int lock_lvs(struct cmd_context *cmd, struct list *lvs, int flags);
int unlock_lvs(struct cmd_context *cmd, struct list *lvs);
/* lv must be part of vg->lvs */
int lv_remove(struct volume_group *vg, struct logical_volume *lv);
@@ -401,6 +448,9 @@ struct logical_volume *lv_from_lvid(struct cmd_context *cmd,
struct physical_volume *find_pv(struct volume_group *vg, struct device *dev);
struct logical_volume *find_lv(struct volume_group *vg, const char *lv_name);
/* Find LV segment containing given LE */
struct lv_segment *find_seg_by_le(struct logical_volume *lv, uint32_t le);
/*
* Remove a dev_dir if present.
*/
@@ -424,6 +474,8 @@ int lv_merge_segments(struct logical_volume *lv);
int lv_is_origin(const struct logical_volume *lv);
int lv_is_cow(const struct logical_volume *lv);
int pv_is_in_vg(struct volume_group *vg, struct physical_volume *pv);
struct snapshot *find_cow(const struct logical_volume *lv);
struct snapshot *find_origin(const struct logical_volume *lv);
struct list *find_snapshots(const struct logical_volume *lv);
@@ -434,7 +486,27 @@ int vg_add_snapshot(struct logical_volume *origin,
int vg_remove_snapshot(struct volume_group *vg, struct logical_volume *cow);
static inline int validate_vgname(const char *n)
/*
* Mirroring functions
*/
int insert_pvmove_mirrors(struct cmd_context *cmd,
struct logical_volume *lv_mirr,
struct physical_volume *pv,
struct logical_volume *lv,
struct list *allocatable_pvs,
struct list *lvs_changed);
int remove_pvmove_mirrors(struct volume_group *vg,
struct logical_volume *lv_mirr);
struct logical_volume *find_pvmove_lv(struct volume_group *vg,
struct device *dev);
struct physical_volume *get_pvmove_pv_from_lv(struct logical_volume *lv);
struct physical_volume *get_pvmove_pv_from_lv_mirr(struct logical_volume
*lv_mirr);
float pvmove_percent(struct logical_volume *lv_mirr);
struct list *lvs_using_lv(struct cmd_context *cmd, struct volume_group *vg,
struct logical_volume *lv);
static inline int validate_name(const char *n)
{
register char c;
register int len = 0;

250
lib/metadata/mirror.c Normal file
View File

@@ -0,0 +1,250 @@
/*
* Copyright (C) 2003 Sistina Software (UK) Limited.
*
* This file is released under the LGPL.
*/
#include "lib.h"
#include "metadata.h"
#include "toolcontext.h"
/*
* Replace any LV segments on given PV with temporary mirror.
* Returns list of LVs changed.
*/
int insert_pvmove_mirrors(struct cmd_context *cmd,
struct logical_volume *lv_mirr,
struct physical_volume *pv,
struct logical_volume *lv,
struct list *allocatable_pvs,
struct list *lvs_changed)
{
struct list *segh;
struct lv_segment *seg;
struct lv_list *lvl;
int lv_used = 0;
uint32_t s, start_le, extent_count = 0u;
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_PV ||
seg->area[s].u.pv.pv->dev != pv->dev)
continue;
if (!lv_used) {
if (!(lvl = pool_alloc(cmd->mem, sizeof(*lvl)))) {
log_error("lv_list alloc failed");
return 0;
}
lvl->lv = lv;
list_add(lvs_changed, &lvl->list);
lv_used = 1;
}
start_le = lv_mirr->le_count;
if (!lv_extend_mirror(lv->vg->fid, lv_mirr,
seg->area[s].u.pv.pv,
seg->area[s].u.pv.pe,
seg->area_len, allocatable_pvs,
PVMOVE)) {
log_error("Allocation for temporary "
"pvmove LV failed");
return 0;
}
seg->area[s].type = AREA_LV;
seg->area[s].u.lv.lv = lv_mirr;
seg->area[s].u.lv.le = start_le;
extent_count += seg->area_len;
lv->status |= LOCKED;
}
}
log_verbose("Moving %u extents of logical volume %s/%s", extent_count,
lv->vg->name, lv->name);
return 1;
}
int remove_pvmove_mirrors(struct volume_group *vg,
struct logical_volume *lv_mirr)
{
struct list *lvh, *segh;
struct logical_volume *lv1;
struct lv_segment *seg, *mir_seg;
uint32_t s, c;
list_iterate(lvh, &vg->lvs) {
lv1 = list_item(lvh, struct lv_list)->lv;
if (lv1 == lv_mirr)
continue;
list_iterate(segh, &lv1->segments) {
seg = list_item(segh, struct lv_segment);
for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_LV ||
seg->area[s].u.lv.lv != lv_mirr)
continue;
if (!(mir_seg = find_seg_by_le(lv_mirr,
seg->area[s].u.
lv.le))) {
log_error("No segment found with LE");
return 0;
}
if (mir_seg->type != SEG_MIRRORED ||
!(mir_seg->status & PVMOVE) ||
mir_seg->le != seg->area[s].u.lv.le ||
mir_seg->area_count != 2 ||
mir_seg->area_len != seg->area_len) {
log_error("Incompatible segments");
return 0;
}
if (mir_seg->extents_moved == mir_seg->area_len)
c = 1;
else
c = 0;
seg->area[s].type = AREA_PV;
seg->area[s].u.pv.pv = mir_seg->area[c].u.pv.pv;
seg->area[s].u.pv.pe = mir_seg->area[c].u.pv.pe;
mir_seg->type = SEG_STRIPED;
mir_seg->area_count = 1;
lv1->status &= ~LOCKED;
}
}
}
return 1;
}
struct physical_volume *get_pvmove_pv_from_lv_mirr(struct logical_volume
*lv_mirr)
{
struct list *segh;
struct lv_segment *seg;
list_iterate(segh, &lv_mirr->segments) {
seg = list_item(segh, struct lv_segment);
if (seg->type != SEG_MIRRORED)
continue;
if (seg->area[0].type != AREA_PV)
continue;
return seg->area[0].u.pv.pv;
}
return NULL;
}
struct physical_volume *get_pvmove_pv_from_lv(struct logical_volume *lv)
{
struct list *segh;
struct lv_segment *seg;
uint32_t s;
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_LV)
continue;
return get_pvmove_pv_from_lv_mirr(seg->area[s].u.lv.lv);
}
}
return NULL;
}
struct logical_volume *find_pvmove_lv(struct volume_group *vg,
struct device *dev)
{
struct list *lvh, *segh;
struct logical_volume *lv;
struct lv_segment *seg;
/* Loop through all LVs */
list_iterate(lvh, &vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv;
if (!(lv->status & PVMOVE))
continue;
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
if (seg->area[0].type != AREA_PV)
continue;
if (seg->area[0].u.pv.pv->dev != dev)
continue;
return lv;
}
}
return NULL;
}
struct list *lvs_using_lv(struct cmd_context *cmd, struct volume_group *vg,
struct logical_volume *lv)
{
struct list *lvh, *segh, *lvs;
struct logical_volume *lv1;
struct lv_list *lvl;
struct lv_segment *seg;
uint32_t s;
if (!(lvs = pool_alloc(cmd->mem, sizeof(*lvs)))) {
log_error("lvs list alloc failed");
return NULL;
}
list_init(lvs);
/* Loop through all LVs except the one supplied */
list_iterate(lvh, &vg->lvs) {
lv1 = list_item(lvh, struct lv_list)->lv;
if (lv1 == lv)
continue;
list_iterate(segh, &lv1->segments) {
seg = list_item(segh, struct lv_segment);
for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_LV ||
seg->area[s].u.lv.lv != lv)
continue;
if (!(lvl = pool_alloc(cmd->mem, sizeof(*lvl)))) {
log_error("lv_list alloc failed");
return NULL;
}
lvl->lv = lv1;
list_add(lvs, &lvl->list);
goto next_lv;
}
}
next_lv:
;
}
return lvs;
}
float pvmove_percent(struct logical_volume *lv_mirr)
{
uint32_t numerator = 0u, denominator = 0u;
struct list *segh;
struct lv_segment *seg;
list_iterate(segh, &lv_mirr->segments) {
seg = list_item(segh, struct lv_segment);
if (!(seg->status & PVMOVE))
continue;
numerator += seg->extents_moved;
denominator += seg->area_len;
}
return denominator ? (float) numerator *100 / denominator : 100.0;
}

View File

@@ -11,13 +11,13 @@
static int _create_maps(struct pool *mem, struct list *pvs, struct list *maps)
{
struct list *tmp;
struct physical_volume *pv;
struct pv_map *pvm;
struct pv_list *pvl;
list_iterate(tmp, pvs) {
pv = list_item(tmp, struct pv_list)->pv;
pvl = list_item(tmp, struct pv_list);
if (!(pv->status & ALLOCATABLE_PV))
if (!(pvl->pv->status & ALLOCATABLE_PV))
continue;
if (!(pvm = pool_zalloc(mem, sizeof(*pvm)))) {
@@ -25,9 +25,9 @@ static int _create_maps(struct pool *mem, struct list *pvs, struct list *maps)
return 0;
}
pvm->pv = pv;
pvm->pvl = pvl;
if (!(pvm->allocated_extents =
bitset_create(mem, pv->pe_count))) {
bitset_create(mem, pvl->pv->pe_count))) {
stack;
return 0;
}
@@ -39,8 +39,8 @@ static int _create_maps(struct pool *mem, struct list *pvs, struct list *maps)
return 1;
}
static int _set_allocated(struct hash_table *hash,
struct physical_volume *pv, uint32_t pe)
static int _set_allocd(struct hash_table *hash,
struct physical_volume *pv, uint32_t pe)
{
struct pv_map *pvm;
@@ -82,7 +82,7 @@ static int _fill_bitsets(struct volume_group *vg, struct list *maps)
/* populate the hash table */
list_iterate(pvmh, maps) {
pvm = list_item(pvmh, struct pv_map);
if (!hash_insert(hash, dev_name(pvm->pv->dev), pvm)) {
if (!hash_insert(hash, dev_name(pvm->pvl->pv->dev), pvm)) {
stack;
goto out;
}
@@ -95,13 +95,14 @@ static int _fill_bitsets(struct volume_group *vg, struct list *maps)
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
for (s = 0; s < seg->stripes; s++) {
for (pe = 0; pe < (seg->len / seg->stripes);
pe++) {
if (!_set_allocated(hash,
seg->area[s].pv,
seg->area[s].pe
+ pe)) {
for (s = 0u; s < seg->area_count; s++) {
for (pe = 0u; pe < seg->area_len; pe++) {
if (seg->area[s].type != AREA_PV)
continue;
if (!_set_allocd(hash,
seg->area[s].u.pv.pv,
seg->area[s].u.pv.pe
+ pe)) {
stack;
goto out;
}
@@ -140,22 +141,22 @@ static void _insert_area(struct list *head, struct pv_area *a)
}
static int _create_single_area(struct pool *mem, struct pv_map *pvm,
uint32_t *extent)
uint32_t end, uint32_t *extent)
{
uint32_t e = *extent, b, count = pvm->pv->pe_count;
uint32_t e = *extent, b;
struct pv_area *pva;
while (e < count && bit(pvm->allocated_extents, e))
while (e <= end && bit(pvm->allocated_extents, e))
e++;
if (e == count) {
if (e > end) {
*extent = e;
return 1;
}
b = e++;
while (e < count && !bit(pvm->allocated_extents, e))
while (e <= end && !bit(pvm->allocated_extents, e))
e++;
if (!(pva = pool_zalloc(mem, sizeof(*pva)))) {
@@ -163,6 +164,8 @@ static int _create_single_area(struct pool *mem, struct pv_map *pvm,
return 0;
}
log_debug("Allowing allocation on %s start PE %" PRIu32 " length %"
PRIu32, dev_name(pvm->pvl->pv->dev), b, e - b);
pva->map = pvm;
pva->start = b;
pva->count = e - b;
@@ -172,12 +175,18 @@ static int _create_single_area(struct pool *mem, struct pv_map *pvm,
return 1;
}
static int _create_areas(struct pool *mem, struct pv_map *pvm)
static int _create_areas(struct pool *mem, struct pv_map *pvm, uint32_t start,
uint32_t count)
{
uint32_t pe = 0;
uint32_t pe, end;
while (pe < pvm->pv->pe_count)
if (!_create_single_area(mem, pvm, &pe)) {
end = start + count - 1;
if (end > pvm->pvl->pv->pe_count - 1)
end = pvm->pvl->pv->pe_count - 1;
pe = start;
while (pe <= end)
if (!_create_single_area(mem, pvm, end, &pe)) {
stack;
return 0;
}
@@ -185,7 +194,36 @@ static int _create_areas(struct pool *mem, struct pv_map *pvm)
return 1;
}
static int _create_all_areas(struct pool *mem, struct list *maps)
static int _create_allocatable_areas(struct pool *mem, struct pv_map *pvm)
{
struct list *alloc_areas, *aah;
struct alloc_area *aa;
alloc_areas = pvm->pvl->alloc_areas;
if (alloc_areas) {
list_iterate(aah, alloc_areas) {
aa = list_item(aah, struct alloc_area);
if (!_create_areas(mem, pvm, aa->start, aa->count)) {
stack;
return 0;
}
}
} else {
/* Use whole PV */
if (!_create_areas(mem, pvm, UINT32_C(0),
pvm->pvl->pv->pe_count)) {
stack;
return 0;
}
}
return 1;
}
static int _create_all_areas(struct pool *mem, struct list *maps,
struct list *pvs)
{
struct list *tmp;
struct pv_map *pvm;
@@ -193,7 +231,7 @@ static int _create_all_areas(struct pool *mem, struct list *maps)
list_iterate(tmp, maps) {
pvm = list_item(tmp, struct pv_map);
if (!_create_areas(mem, pvm)) {
if (!_create_allocatable_areas(mem, pvm)) {
stack;
return 0;
}
@@ -226,7 +264,7 @@ struct list *create_pv_maps(struct pool *mem, struct volume_group *vg,
goto bad;
}
if (!_create_all_areas(mem, maps)) {
if (!_create_all_areas(mem, maps, pvs)) {
log_error("Couldn't create area maps in %s", vg->name);
goto bad;
}

View File

@@ -28,7 +28,7 @@ struct pv_area {
};
struct pv_map {
struct physical_volume *pv;
struct pv_list *pvl;
bitset_t allocated_extents;
struct list areas;

View File

@@ -7,8 +7,6 @@
#ifndef _LVM_CRC_H
#define _LVM_CRC_H
#include "lvm-types.h"
#define INITIAL_CRC 0xf597a6cf
uint32_t calc_crc(uint32_t initial, void *buf, uint32_t size);

View File

@@ -11,10 +11,9 @@
#define _LVM_LIB_H
#define _REENTRANT
#define _GNU_SOURCE
#include "log.h"
#include "dbg_malloc.h"
#include <assert.h>
#endif

View File

@@ -6,6 +6,7 @@
*/
#include "config.h"
#include <dlfcn.h>
void *load_shared_library(struct config_tree *cf, const char *libname,
const char *what);

View File

@@ -7,9 +7,9 @@
#ifndef _LVM_DBG_MALLOC_H
#define _LVM_DBG_MALLOC_H
#include "lvm-types.h"
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#ifdef DEBUG_MEM
void *malloc_aux(size_t s, const char *file, int line);
@@ -18,15 +18,15 @@ void *realloc_aux(void *p, unsigned int s, const char *file, int line);
int dump_memory(void);
void bounds_check(void);
#define dbg_malloc(s) malloc_aux((s), __FILE__, __LINE__)
#define dbg_free(p) free_aux(p)
#define dbg_realloc(p, s) realloc_aux(p, s, __FILE__, __LINE__)
# define dbg_malloc(s) malloc_aux((s), __FILE__, __LINE__)
# define dbg_free(p) free_aux(p)
# define dbg_realloc(p, s) realloc_aux(p, s, __FILE__, __LINE__)
#else
#define dbg_malloc(s) malloc(s)
#define dbg_free(p) free(p)
#define dbg_realloc(p, s) realloc(p, s)
#define dump_memory()
#define bounds_check()
# define dbg_malloc(s) malloc(s)
# define dbg_free(p) free(p)
# define dbg_realloc(p, s) realloc(p, s)
# define dump_memory()
# define bounds_check()
#endif
static inline char *dbg_strdup(const char *str)

144
lib/mm/memlock.c Normal file
View File

@@ -0,0 +1,144 @@
/*
* Copyright (C) 2003 Sistina Software (UK) Limited.
*
* This file is released under the LGPL.
*/
#include "lib.h"
#include "memlock.h"
#include "pool.h"
#include "defaults.h"
#include <limits.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <sys/resource.h>
#ifndef DEVMAPPER_SUPPORT
void memlock_inc(void)
{
return;
}
void memlock_dec(void)
{
return;
}
int memlock(void)
{
return 0;
}
#else /* DEVMAPPER_SUPPORT */
static size_t _size_stack;
static size_t _size_malloc_tmp;
static size_t _size_malloc = 2000000;
static void *_malloc_mem = NULL;
static int _memlock_count = 0;
static int _priority;
static int _default_priority;
static void _touch_memory(void *mem, size_t size)
{
size_t pagesize = getpagesize();
void *pos = mem;
void *end = mem + size - sizeof(long);
while (pos < end) {
*(long *) pos = 1;
pos += pagesize;
}
}
static void _allocate_memory(void)
{
void *stack_mem, *temp_malloc_mem;
if ((stack_mem = alloca(_size_stack)))
_touch_memory(stack_mem, _size_stack);
if ((temp_malloc_mem = malloc(_size_malloc_tmp)))
_touch_memory(temp_malloc_mem, _size_malloc_tmp);
if ((_malloc_mem = malloc(_size_malloc)))
_touch_memory(_malloc_mem, _size_malloc);
free(temp_malloc_mem);
}
static void _release_memory(void)
{
free(_malloc_mem);
}
/* Stop memory getting swapped out */
static void _lock_memory(void)
{
#ifdef MCL_CURRENT
if (mlockall(MCL_CURRENT | MCL_FUTURE))
log_sys_error("mlockall", "");
else
log_very_verbose("Locking memory");
#endif
_allocate_memory();
errno = 0;
if (((_priority = getpriority(PRIO_PROCESS, 0)) == -1) && errno)
log_sys_error("getpriority", "");
else
if (setpriority(PRIO_PROCESS, 0, _default_priority))
log_error("setpriority %u failed: %s",
_default_priority, strerror(errno));
}
static void _unlock_memory(void)
{
#ifdef MCL_CURRENT
if (munlockall())
log_sys_error("munlockall", "");
else
log_very_verbose("Unlocking memory");
#endif
_release_memory();
if (setpriority(PRIO_PROCESS, 0, _priority))
log_error("setpriority %u failed: %s", _priority,
strerror(errno));
}
void memlock_inc(void)
{
if (!_memlock_count++)
_lock_memory();
log_debug("memlock_count inc to %d", _memlock_count);
}
void memlock_dec(void)
{
if (_memlock_count && (!--_memlock_count))
_unlock_memory();
log_debug("memlock_count dec to %d", _memlock_count);
}
int memlock(void)
{
return _memlock_count;
}
void memlock_init(struct cmd_context *cmd)
{
_size_stack = find_config_int(cmd->cf->root,
"activation/reserved_stack",
'/', DEFAULT_RESERVED_STACK) * 1024;
_size_malloc_tmp = find_config_int(cmd->cf->root,
"activation/reserved_memory",
'/', DEFAULT_RESERVED_MEMORY) * 1024;
_default_priority = find_config_int(cmd->cf->root,
"activation/process_priority",
'/', DEFAULT_PROCESS_PRIORITY);
}
#endif

17
lib/mm/memlock.h Normal file
View File

@@ -0,0 +1,17 @@
/*
* Copyright (C) 2001 Sistina Software (UK) Limited.
*
* This file is released under the LGPL.
*/
#ifndef LVM_MEMLOCK_H
#define LVM_MEMLOCK_H
#include "toolcontext.h"
void memlock_inc(void);
void memlock_dec(void);
int memlock(void);
void memlock_init(struct cmd_context *cmd);
#endif

View File

@@ -29,7 +29,7 @@ struct pool *pool_create(size_t chunk_hint)
struct pool *mem = dbg_malloc(sizeof(*mem));
if (!mem) {
log_error("Couldn't create memory pool (size %u)",
log_error("Couldn't create memory pool (size %" PRIsize_t ")",
sizeof(*mem));
return NULL;
}
@@ -205,3 +205,15 @@ char *pool_strdup(struct pool *p, const char *str)
return ret;
}
char *pool_strndup(struct pool *p, const char *str, size_t n)
{
char *ret = pool_alloc(p, n + 1);
if (ret) {
strncpy(ret, str, n);
ret[n] = '\0';
}
return ret;
}

View File

@@ -33,7 +33,7 @@ struct pool *pool_create(size_t chunk_hint)
struct pool *p = dbg_malloc(sizeof(*p));
if (!p) {
log_error("Couldn't create memory pool (size %" PRIuPTR ")",
log_error("Couldn't create memory pool (size %" PRIsize_t ")",
sizeof(*p));
return 0;
}
@@ -205,6 +205,18 @@ char *pool_strdup(struct pool *p, const char *str)
return ret;
}
char *pool_strndup(struct pool *p, const char *str, size_t n)
{
char *ret = pool_alloc(p, n + 1);
if (ret) {
strncpy(ret, str, n);
ret[n] = '\0';
}
return ret;
}
void _align_chunk(struct chunk *c, unsigned alignment)
{
c->begin += alignment - ((unsigned long) c->begin & (alignment - 1));
@@ -221,8 +233,8 @@ struct chunk *_new_chunk(struct pool *p, size_t s)
p->spare_chunk = 0;
} else {
if (!(c = dbg_malloc(s))) {
log_err("Out of memory. Requested %" PRIuPTR " bytes.",
s);
log_err("Out of memory. Requested %" PRIsize_t
" bytes.", s);
return NULL;
}

View File

@@ -106,6 +106,7 @@ void pool_abandon_object(struct pool *p);
/* utilities */
char *pool_strdup(struct pool *p, const char *str);
char *pool_strndup(struct pool *p, const char *str, size_t n);
static inline void *pool_zalloc(struct pool *p, size_t s)
{

View File

@@ -8,10 +8,37 @@
#ifndef _LVM_XLATE_H
#define _LVM_XLATE_H
#include <asm/byteorder.h>
#define xlate16(x) __cpu_to_le16((x))
#define xlate32(x) __cpu_to_le32((x))
#define xlate64(x) __cpu_to_le64((x))
#ifdef linux
# include <asm/byteorder.h>
# define xlate16(x) __cpu_to_le16((x))
# define xlate32(x) __cpu_to_le32((x))
# define xlate64(x) __cpu_to_le64((x))
#else
# include <machine/endian.h>
# if !defined(BYTE_ORDER) || \
(BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN)
# error "Undefined or unrecognised BYTE_ORDER";
# endif
# if BYTE_ORDER == LITTLE_ENDIAN
# define xlate16(x) (x)
# define xlate32(x) (x)
# define xlate64(x) (x)
# else
# define xlate16(x) (((x) & 0x00ffU) << 8 | \
((x) & 0xff00U) >> 8)
# define xlate32(x) (((x) & 0x000000ffU) << 24 | \
((x) & 0xff000000U) >> 24 | \
((x) & 0x0000ff00U) << 8 | \
((x) & 0x00ff0000U) >> 8)
# define xlate64(x) (((x) & 0x00000000000000ffU) << 56 | \
((x) & 0xff00000000000000U) >> 56 | \
((x) & 0x000000000000ff00U) << 40 | \
((x) & 0x00ff000000000000U) >> 40 | \
((x) & 0x0000000000ff0000U) << 24 | \
((x) & 0x0000ff0000000000U) >> 24 | \
((x) & 0x00000000ff000000U) << 8 | \
((x) & 0x000000ff00000000U) >> 8)
# endif
#endif
#endif

View File

@@ -24,7 +24,7 @@ enum {
* start and end of a string.
*/
#define HAT_CHAR 0x2
#define DOLLAR_CHAR 0x2
#define DOLLAR_CHAR 0x3
struct rx_node {
int type;

View File

@@ -7,14 +7,19 @@
/* Report type, Containing struct, Field type, Report heading,
* Data field with struct to pass to display function, Minimum display width,
* Display Fn, Unique format identifier */
/* *INDENT-OFF* */
FIELD(LVS, lv, STR, "LV UUID", lvid.id[1], 38, uuid, "lv_uuid")
FIELD(LVS, lv, STR, "LV", name, 4, string, "lv_name")
FIELD(LVS, lv, STR, "Attr", lvid, 4, lvstatus, "lv_attr")
FIELD(LVS, lv, NUM, "Maj", major, 3, int32, "lv_major")
FIELD(LVS, lv, NUM, "Min", minor, 3, int32, "lv_minor")
FIELD(LVS, lv, NUM, "LSize", size, 5, size64, "lv_size")
FIELD(LVS, lv, NUM, "#Seg", lvid, 4, lvsegcount, "seg_count")
FIELD(LVS, lv, STR, "Origin", lvid, 6, origin, "origin")
FIELD(LVS, lv, NUM, "Snap%", lvid, 6, snpercent, "snap_percent")
FIELD(LVS, lv, NUM, "Move%", lvid, 6, movepercent, "move_percent")
FIELD(LVS, lv, STR, "Move", lvid, 4, movepv, "move_pv")
FIELD(PVS, pv, STR, "Fmt", id, 3, pvfmt, "pv_fmt")
FIELD(PVS, pv, STR, "PV UUID", id, 38, uuid, "pv_uuid")
@@ -44,9 +49,9 @@ FIELD(VGS, vg, NUM, "#SN", snapshot_count, 3, uint32, "snap_count")
FIELD(VGS, vg, NUM, "Seq", seqno, 3, uint32, "vg_seqno")
FIELD(SEGS, seg, STR, "Type", list, 4, segtype, "segtype")
FIELD(SEGS, seg, NUM, "#Str", stripes, 4, uint32, "stripes")
FIELD(SEGS, seg, NUM, "#Str", area_count, 4, uint32, "stripes")
FIELD(SEGS, seg, NUM, "Stripe", stripe_size, 6, size32, "stripesize")
FIELD(SEGS, seg, NUM, "Chunk", chunk_size, 5, size32, "chunksize")
FIELD(SEGS, seg, NUM, "Start", list, 5, segstart, "seg_start")
FIELD(SEGS, seg, NUM, "SSize", list, 5, segsize, "seg_size")
/* *INDENT-ON* */

View File

@@ -27,8 +27,6 @@
#include "display.h"
#include "activate.h"
#include <sys/types.h>
/*
* For macro use
*/
@@ -163,22 +161,28 @@ static int _lvstatus_disp(struct report_handle *rh, struct field *field,
const void *data)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
struct dm_info info;
struct lvinfo info;
char *repstr;
struct snapshot *snap;
float snap_percent;
if (!(repstr = pool_zalloc(rh->mem, 7))) {
log_error("pool_alloc failed");
return 0;
}
if (lv_is_origin(lv))
if (lv->status & PVMOVE)
repstr[0] = 'p';
else if (lv_is_origin(lv))
repstr[0] = 'o';
else if (find_cow(lv))
repstr[0] = 's';
else
repstr[0] = '-';
if (lv->status & LVM_WRITE)
if (lv->status & PVMOVE)
repstr[1] = '-';
else if (lv->status & LVM_WRITE)
repstr[1] = 'w';
else
repstr[1] = 'r';
@@ -188,6 +192,9 @@ static int _lvstatus_disp(struct report_handle *rh, struct field *field,
else
repstr[2] = 'n';
if (lv->status & LOCKED)
repstr[2] = toupper(repstr[2]);
if (lv->status & FIXED_MINOR)
repstr[3] = 'm'; /* Fixed Minor */
else
@@ -202,6 +209,18 @@ static int _lvstatus_disp(struct report_handle *rh, struct field *field,
repstr[5] = 'o'; /* Open */
else
repstr[5] = '-';
/* Snapshot dropped? */
if ((snap = find_cow(lv)) &&
(!lv_snapshot_percent(snap->cow, &snap_percent) ||
snap_percent < 0 || snap_percent >= 100)) {
repstr[0] = toupper(repstr[0]);
if (info.suspended)
repstr[4] = 'S';
else
repstr[4] = 'I';
}
} else {
repstr[4] = '-';
repstr[5] = '-';
@@ -282,7 +301,7 @@ static int _segtype_disp(struct report_handle *rh, struct field *field,
{
const struct lv_segment *seg = (const struct lv_segment *) data;
if (seg->stripes == 1)
if (seg->area_count == 1)
field->report_string = "linear";
else
field->report_string = get_segtype_string(seg->type);
@@ -306,6 +325,28 @@ static int _origin_disp(struct report_handle *rh, struct field *field,
return 1;
}
static int _movepv_disp(struct report_handle *rh, struct field *field,
const void *data)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
const char *name;
struct list *segh;
struct lv_segment *seg;
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
if (!(seg->status & PVMOVE))
continue;
name = dev_name(seg->area[0].u.pv.pv->dev);
return _string_disp(rh, field, &name);
}
field->report_string = "";
field->sort_value = (const void *) field->report_string;
return 1;
}
static int _size32_disp(struct report_handle *rh, struct field *field,
const void *data)
{
@@ -456,7 +497,7 @@ static int _uuid_disp(struct report_handle *rh, struct field *field,
{
char *repstr = NULL;
if (!(field->report_string = pool_alloc(rh->mem, 40))) {
if (!(repstr = pool_alloc(rh->mem, 40))) {
log_error("pool_alloc failed");
return 0;
}
@@ -546,6 +587,7 @@ static int _snpercent_disp(struct report_handle *rh, struct field *field,
{
const struct logical_volume *lv = (const struct logical_volume *) data;
struct snapshot *snap;
struct lvinfo info;
float snap_percent;
uint64_t *sortval;
char *repstr;
@@ -555,10 +597,17 @@ static int _snpercent_disp(struct report_handle *rh, struct field *field,
return 0;
}
if (!(snap = find_cow(lv))
|| !lv_snapshot_percent(snap->cow, &snap_percent)) {
if (!(snap = find_cow(lv)) ||
(lv_info(snap->cow, &info) && !info.exists)) {
field->report_string = "";
*sortval = __UINT64_C(0);
*sortval = UINT64_C(0);
field->sort_value = sortval;
return 1;
}
if (!lv_snapshot_percent(snap->cow, &snap_percent) || snap_percent < 0) {
field->report_string = "100.00";
*sortval = UINT64_C(100);
field->sort_value = sortval;
return 1;
}
@@ -568,15 +617,54 @@ static int _snpercent_disp(struct report_handle *rh, struct field *field,
return 0;
}
if (snap_percent == -1)
snap_percent = 100;
if (lvm_snprintf(repstr, 7, "%.2f", snap_percent) < 0) {
log_error("snapshot percentage too large");
return 0;
}
*sortval = snap_percent * __UINT64_C(1000);
*sortval = snap_percent * UINT64_C(1000);
field->sort_value = sortval;
field->report_string = repstr;
return 1;
}
static int _movepercent_disp(struct report_handle *rh, struct field *field,
const void *data)
{
struct logical_volume *lv = (struct logical_volume *) data;
float move_percent;
uint64_t *sortval;
char *repstr;
if (!(sortval = pool_alloc(rh->mem, sizeof(uint64_t)))) {
log_error("pool_alloc failed");
return 0;
}
if (!(lv->status & PVMOVE)) {
field->report_string = "";
*sortval = UINT64_C(0);
field->sort_value = sortval;
return 1;
}
/* Update percentage done in lv metadata in core */
lv_mirror_percent(lv, 0, &move_percent, NULL);
move_percent = pvmove_percent(lv);
if (!(repstr = pool_zalloc(rh->mem, 8))) {
log_error("pool_alloc failed");
return 0;
}
if (lvm_snprintf(repstr, 7, "%.2f", move_percent) < 0) {
log_error("move percentage too large");
return 0;
}
*sortval = move_percent * UINT64_C(1000);
field->sort_value = sortval;
field->report_string = repstr;
@@ -744,7 +832,8 @@ static int _parse_options(struct report_handle *rh, const char *format)
while (*we && *we != ',')
we++;
if (!_field_match(rh, ws, (size_t) (we - ws))) {
log_error("Unrecognised field: %.*s", we - ws, ws);
log_error("Unrecognised field: %.*s", (int) (we - ws),
ws);
return 0;
}
}
@@ -765,7 +854,8 @@ static int _parse_keys(struct report_handle *rh, const char *keys)
while (*we && *we != ',')
we++;
if (!_key_match(rh, ws, (size_t) (we - ws))) {
log_error("Unrecognised field: %.*s", we - ws, ws);
log_error("Unrecognised field: %.*s", (int) (we - ws),
ws);
return 0;
}
}

View File

@@ -7,8 +7,6 @@
#ifndef _LVM_UUID_H
#define _LVM_UUID_H
#include "lvm-types.h"
#define ID_LEN 32
#define ID_LEN_S "32"

View File

@@ -1,6 +1,7 @@
Base {
Base {
global:
dm_log_init;
dm_log_init_verbose;
dm_task_create;
dm_task_destroy;
dm_task_set_name;
@@ -9,16 +10,22 @@ Base {
dm_task_get_driver_version;
dm_task_get_info;
dm_task_get_deps;
dm_task_get_name;
dm_task_get_names;
dm_task_get_uuid;
dm_task_set_ro;
dm_task_set_newname;
dm_task_set_event_nr;
dm_task_set_major;
dm_task_set_minor;
dm_task_add_target;
dm_get_next_target;
dm_task_run;
dm_set_dev_dir;
dm_dir;
dm_format_dev;
dm_lib_release;
dm_lib_exit;
local:
*;
};

View File

@@ -9,7 +9,7 @@ top_srcdir = @top_srcdir@
VPATH = @srcdir@
interface = @interface@
SOURCES=$(interface)/libdevmapper.c libdm-common.c
SOURCES=libdm-common.c $(interface)/libdevmapper.c
INCLUDES=-I$(interface)

View File

@@ -7,10 +7,14 @@
#ifndef _LVM_LIST_H
#define _LVM_LIST_H
#include <assert.h>
struct list {
struct list *n, *p;
};
#define LIST_INIT(name) struct list name = { &(name), &(name) }
static inline void list_init(struct list *head)
{
head->n = head->p = head;
@@ -54,9 +58,17 @@ static inline int list_end(struct list *head, struct list *elem)
return elem->n == head;
}
static inline struct list *list_next(struct list *head, struct list *elem)
{
return (list_end(head, elem) ? NULL : elem->n);
}
#define list_iterate(v, head) \
for (v = (head)->n; v != head; v = v->n)
#define list_uniterate(v, head, start) \
for (v = (start)->p; v != head; v = v->p)
#define list_iterate_safe(v, t, head) \
for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
@@ -74,8 +86,14 @@ static inline unsigned int list_size(const struct list *head)
#define list_item(v, t) \
((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->list))
/* Given a known element in a known structure, locate the struct list */
#define list_head(v, t, e) \
(((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->e))->list)
#define list_struct_base(v, t, h) \
((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->h))
/* Given a known element in a known structure, locate another */
#define struct_field(v, t, e, f) \
(((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->e))->f)
/* Given a known element in a known structure, locate the list head */
#define list_head(v, t, e) struct_field(v, t, e, list)
#endif

View File

@@ -4,60 +4,460 @@
* This file is released under the LGPL.
*/
#include "libdevmapper.h"
#include "libdm-targets.h"
#include "libdm-common.h"
#include "libdm-compat.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>
#include <linux/kdev_t.h>
#include <sys/stat.h>
#include <limits.h>
#include <linux/limits.h>
#include <sys/ioctl.h>
#include <linux/dm-ioctl.h>
#include "libdm-targets.h"
#include "libdm-common.h"
#define ALIGNMENT sizeof(int)
/*
* Ensure build compatibility. The hard-coded version here (major, minor)
* is the highest present in the _cmd_data array below.
* Ensure build compatibility.
* The hard-coded versions here are the highest present
* in the _cmd_data arrays.
*/
#if DM_VERSION_MAJOR != 1 || DM_VERSION_MINOR < 0
#error The version of dm-ioctl.h included is incompatible.
#if !((DM_VERSION_MAJOR == 1 && DM_VERSION_MINOR >= 0) || \
(DM_VERSION_MAJOR == 4 && DM_VERSION_MINOR >= 0))
#error The version of dm-ioctl.h included is incompatible.
#endif
static struct {
char *name;
int cmd;
int version[3];
} _cmd_data[] = {
{ "create", DM_DEV_CREATE, {1, 0, 0} },
{ "reload", DM_DEV_RELOAD, {1, 0, 0} },
{ "remove", DM_DEV_REMOVE, {1, 0, 0} },
{ "remove_all", DM_REMOVE_ALL, {1, 0, 0} },
{ "suspend", DM_DEV_SUSPEND, {1, 0, 0} },
{ "resume", DM_DEV_SUSPEND, {1, 0, 0} },
{ "info", DM_DEV_STATUS, {1, 0, 0} },
{ "deps", DM_DEV_DEPS, {1, 0, 0} },
{ "rename", DM_DEV_RENAME, {1, 0, 0} },
{ "version", DM_VERSION, {1, 0, 0} },
{ "status", DM_TARGET_STATUS, {1, 0, 0} },
{ "table", DM_TARGET_STATUS, {1, 0, 0} },
{ "waitevent", DM_TARGET_WAIT, {1, 0, 0} },
/* dm major version no for running kernel */
static int _dm_version = DM_VERSION_MAJOR;
static int _log_suppress = 0;
static int _control_fd = -1;
static int _version_checked = 0;
static int _version_ok = 1;
/*
* Support both old and new major numbers to ease the transition.
* Clumsy, but only temporary.
*/
#if DM_VERSION_MAJOR == 4 && defined(DM_COMPAT)
const int _dm_compat = 1;
#else
const int _dm_compat = 0;
#endif
/* *INDENT-OFF* */
static struct cmd_data _cmd_data_v4[] = {
{"create", DM_DEV_CREATE, {4, 0, 0}},
{"reload", DM_TABLE_LOAD, {4, 0, 0}},
{"remove", DM_DEV_REMOVE, {4, 0, 0}},
{"remove_all", DM_REMOVE_ALL, {4, 0, 0}},
{"suspend", DM_DEV_SUSPEND, {4, 0, 0}},
{"resume", DM_DEV_SUSPEND, {4, 0, 0}},
{"info", DM_DEV_STATUS, {4, 0, 0}},
{"deps", DM_TABLE_DEPS, {4, 0, 0}},
{"rename", DM_DEV_RENAME, {4, 0, 0}},
{"version", DM_VERSION, {4, 0, 0}},
{"status", DM_TABLE_STATUS, {4, 0, 0}},
{"table", DM_TABLE_STATUS, {4, 0, 0}},
{"waitevent", DM_DEV_WAIT, {4, 0, 0}},
{"names", DM_LIST_DEVICES, {4, 0, 0}},
{"clear", DM_TABLE_CLEAR, {4, 0, 0}},
};
/* *INDENT-ON* */
#define ALIGNMENT_V1 sizeof(int)
#define ALIGNMENT 8
/* FIXME Rejig library to record & use errno instead */
#ifndef DM_EXISTS_FLAG
# define DM_EXISTS_FLAG 0x00000004
#endif
static void *_align(void *ptr, unsigned int a)
{
register unsigned long align = --a;
register unsigned long agn = --a;
return (void *) (((unsigned long) ptr + align) & ~align);
return (void *) (((unsigned long) ptr + agn) & ~agn);
}
static int _dm_task_get_driver_version_v1(struct dm_task *dmt, char *version,
size_t size)
{
unsigned int *v;
if (!dmt->dmi.v1) {
version[0] = '\0';
return 0;
}
v = dmt->dmi.v1->version;
snprintf(version, size, "%u.%u.%u", v[0], v[1], v[2]);
return 1;
}
/* Unmarshall the target info returned from a status call */
static int _unmarshal_status_v1(struct dm_task *dmt, struct dm_ioctl_v1 *dmi)
{
char *outbuf = (char *) dmi + dmi->data_start;
char *outptr = outbuf;
int32_t i;
struct dm_target_spec_v1 *spec;
for (i = 0; i < dmi->target_count; i++) {
spec = (struct dm_target_spec_v1 *) outptr;
if (!dm_task_add_target(dmt, spec->sector_start,
(uint64_t) spec->length,
spec->target_type,
outptr + sizeof(*spec)))
return 0;
outptr = outbuf + spec->next;
}
return 1;
}
static int _dm_format_dev_v1(char *buf, int bufsize, uint32_t dev_major, uint32_t dev_minor)
{
int r;
if (bufsize < 8)
return 0;
r = snprintf(buf, bufsize, "%03x:%03x", dev_major, dev_minor);
if (r < 0 || r > bufsize - 1)
return 0;
return 1;
}
static int _dm_task_get_info_v1(struct dm_task *dmt, struct dm_info *info)
{
if (!dmt->dmi.v1)
return 0;
memset(info, 0, sizeof(*info));
info->exists = dmt->dmi.v1->flags & DM_EXISTS_FLAG ? 1 : 0;
if (!info->exists)
return 1;
info->suspended = dmt->dmi.v1->flags & DM_SUSPEND_FLAG ? 1 : 0;
info->read_only = dmt->dmi.v1->flags & DM_READONLY_FLAG ? 1 : 0;
info->target_count = dmt->dmi.v1->target_count;
info->open_count = dmt->dmi.v1->open_count;
info->event_nr = 0;
info->major = MAJOR(dmt->dmi.v1->dev);
info->minor = MINOR(dmt->dmi.v1->dev);
info->live_table = 1;
info->inactive_table = 0;
return 1;
}
static const char *_dm_task_get_name_v1(struct dm_task *dmt)
{
return (dmt->dmi.v1->name);
}
static const char *_dm_task_get_uuid_v1(struct dm_task *dmt)
{
return (dmt->dmi.v1->uuid);
}
static struct dm_deps *_dm_task_get_deps_v1(struct dm_task *dmt)
{
log_error("deps version 1 no longer supported by libdevmapper");
return NULL;
}
static struct dm_names *_dm_task_get_names_v1(struct dm_task *dmt)
{
return (struct dm_names *) (((void *) dmt->dmi.v1) +
dmt->dmi.v1->data_start);
}
static void *_add_target_v1(struct target *t, void *out, void *end)
{
void *out_sp = out;
struct dm_target_spec_v1 sp;
size_t sp_size = sizeof(struct dm_target_spec_v1);
int len;
const char no_space[] = "Ran out of memory building ioctl parameter";
out += sp_size;
if (out >= end) {
log_error(no_space);
return NULL;
}
sp.status = 0;
sp.sector_start = t->start;
sp.length = t->length;
strncpy(sp.target_type, t->type, sizeof(sp.target_type));
len = strlen(t->params);
if ((out + len + 1) >= end) {
log_error(no_space);
log_error("t->params= '%s'", t->params);
return NULL;
}
strcpy((char *) out, t->params);
out += len + 1;
/* align next block */
out = _align(out, ALIGNMENT_V1);
sp.next = out - out_sp;
memcpy(out_sp, &sp, sp_size);
return out;
}
static struct dm_ioctl_v1 *_flatten_v1(struct dm_task *dmt)
{
const size_t min_size = 16 * 1024;
const int (*version)[3];
struct dm_ioctl_v1 *dmi;
struct target *t;
size_t len = sizeof(struct dm_ioctl_v1);
void *b, *e;
int count = 0;
for (t = dmt->head; t; t = t->next) {
len += sizeof(struct dm_target_spec_v1);
len += strlen(t->params) + 1 + ALIGNMENT_V1;
count++;
}
if (count && dmt->newname) {
log_error("targets and newname are incompatible");
return NULL;
}
if (dmt->newname)
len += strlen(dmt->newname) + 1;
/*
* Give len a minimum size so that we have space to store
* dependencies or status information.
*/
if (len < min_size)
len = min_size;
if (!(dmi = malloc(len)))
return NULL;
memset(dmi, 0, len);
version = &_cmd_data_v1[dmt->type].version;
dmi->version[0] = (*version)[0];
dmi->version[1] = (*version)[1];
dmi->version[2] = (*version)[2];
dmi->data_size = len;
dmi->data_start = sizeof(struct dm_ioctl_v1);
if (dmt->dev_name)
strncpy(dmi->name, dmt->dev_name, sizeof(dmi->name));
if (dmt->type == DM_DEVICE_SUSPEND)
dmi->flags |= DM_SUSPEND_FLAG;
if (dmt->read_only)
dmi->flags |= DM_READONLY_FLAG;
if (dmt->minor >= 0) {
if (dmt->major <= 0) {
log_error("Missing major number for persistent device");
return NULL;
}
dmi->flags |= DM_PERSISTENT_DEV_FLAG;
dmi->dev = MKDEV(dmt->major, dmt->minor);
}
if (dmt->uuid)
strncpy(dmi->uuid, dmt->uuid, sizeof(dmi->uuid));
dmi->target_count = count;
b = (void *) (dmi + 1);
e = (void *) ((char *) dmi + len);
for (t = dmt->head; t; t = t->next)
if (!(b = _add_target_v1(t, b, e)))
goto bad;
if (dmt->newname)
strcpy(b, dmt->newname);
return dmi;
bad:
free(dmi);
return NULL;
}
static int _dm_names_v1(struct dm_ioctl_v1 *dmi)
{
const char *dev_dir = dm_dir();
int r = 1, len;
const char *name;
struct dirent *dirent;
DIR *d;
struct dm_names *names, *old_names = NULL;
void *end = (void *) dmi + dmi->data_size;
struct stat buf;
char path[PATH_MAX];
if (!(d = opendir(dev_dir))) {
log_error("%s: opendir failed: %s", dev_dir, strerror(errno));
return 0;
}
names = (struct dm_names *) ((void *) dmi + dmi->data_start);
names->dev = 0; /* Flags no data */
while ((dirent = readdir(d))) {
name = dirent->d_name;
if (name[0] == '.' || !strcmp(name, "control"))
continue;
if (old_names)
old_names->next = (uint32_t) ((void *) names -
(void *) old_names);
snprintf(path, sizeof(path), "%s/%s", dev_dir, name);
if (stat(path, &buf)) {
log_error("%s: stat failed: %s", path, strerror(errno));
continue;
}
if (!S_ISBLK(buf.st_mode))
continue;
names->dev = (uint64_t) buf.st_rdev;
names->next = 0;
len = strlen(name);
if (((void *) (names + 1) + len + 1) >= end) {
log_error("Insufficient buffer space for device list");
r = 0;
break;
}
strcpy(names->name, name);
old_names = names;
names = _align((void *) ++names + len + 1, ALIGNMENT);
}
if (closedir(d))
log_error("%s: closedir failed: %s", dev_dir, strerror(errno));
return r;
}
static int _open_control(void)
{
char control[PATH_MAX];
if (_control_fd != -1)
return 1;
snprintf(control, sizeof(control), "%s/control", dm_dir());
if ((_control_fd = open(control, O_RDWR)) < 0) {
log_error("%s: open failed: %s", control, strerror(errno));
log_error("Is device-mapper driver missing from kernel?");
return 0;
}
return 1;
}
static int _dm_task_run_v1(struct dm_task *dmt)
{
struct dm_ioctl_v1 *dmi;
unsigned int command;
dmi = _flatten_v1(dmt);
if (!dmi) {
log_error("Couldn't create ioctl argument");
return 0;
}
if (!_open_control())
return 0;
if ((unsigned) dmt->type >=
(sizeof(_cmd_data_v1) / sizeof(*_cmd_data_v1))) {
log_error("Internal error: unknown device-mapper task %d",
dmt->type);
goto bad;
}
command = _cmd_data_v1[dmt->type].cmd;
if (dmt->type == DM_DEVICE_TABLE)
dmi->flags |= DM_STATUS_TABLE_FLAG;
log_debug("dm %s %s %s %s", _cmd_data_v1[dmt->type].name, dmi->name,
dmi->uuid, dmt->newname ? dmt->newname : "");
if (dmt->type == DM_DEVICE_LIST) {
if (!_dm_names_v1(dmi))
goto bad;
} else if (ioctl(_control_fd, command, dmi) < 0) {
if (_log_suppress)
log_verbose("device-mapper ioctl cmd %d failed: %s",
_IOC_NR(command), strerror(errno));
else
log_error("device-mapper ioctl cmd %d failed: %s",
_IOC_NR(command), strerror(errno));
goto bad;
}
switch (dmt->type) {
case DM_DEVICE_CREATE:
add_dev_node(dmt->dev_name, MAJOR(dmi->dev), MINOR(dmi->dev));
break;
case DM_DEVICE_REMOVE:
rm_dev_node(dmt->dev_name);
break;
case DM_DEVICE_RENAME:
rename_dev_node(dmt->dev_name, dmt->newname);
break;
case DM_DEVICE_STATUS:
case DM_DEVICE_TABLE:
if (!_unmarshal_status_v1(dmt, dmi))
goto bad;
break;
case DM_DEVICE_SUSPEND:
case DM_DEVICE_RESUME:
dmt->type = DM_DEVICE_INFO;
if (!dm_task_run(dmt))
goto bad;
free(dmi); /* We'll use what info returned */
return 1;
}
dmt->dmi.v1 = dmi;
return 1;
bad:
free(dmi);
return 0;
}
void dm_task_destroy(struct dm_task *dmt)
@@ -77,8 +477,8 @@ void dm_task_destroy(struct dm_task *dmt)
if (dmt->newname)
free(dmt->newname);
if (dmt->dmi)
free(dmt->dmi);
if (dmt->dmi.v4)
free(dmt->dmi.v4);
if (dmt->uuid)
free(dmt->uuid);
@@ -90,14 +490,81 @@ int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size)
{
unsigned int *v;
if (!dmt->dmi)
return 0;
if (_dm_version == 1)
return _dm_task_get_driver_version_v1(dmt, version, size);
v = dmt->dmi->version;
if (!dmt->dmi.v4) {
version[0] = '\0';
return 0;
}
v = dmt->dmi.v4->version;
snprintf(version, size, "%u.%u.%u", v[0], v[1], v[2]);
return 1;
}
static int _check_version(char *version, size_t size, int log_suppress)
{
struct dm_task *task;
int r;
if (!(task = dm_task_create(DM_DEVICE_VERSION))) {
log_error("Failed to get device-mapper version");
version[0] = '\0';
return 0;
}
if (log_suppress)
_log_suppress = 1;
r = dm_task_run(task);
dm_task_get_driver_version(task, version, size);
dm_task_destroy(task);
_log_suppress = 0;
return r;
}
/*
* Find out device-mapper's major version number the first time
* this is called and whether or not we support it.
*/
int dm_check_version(void)
{
char libversion[64], dmversion[64];
const char *compat = "";
if (_version_checked)
return _version_ok;
_version_checked = 1;
if (_check_version(dmversion, sizeof(dmversion), _dm_compat))
return 1;
if (!_dm_compat)
goto bad;
log_verbose("device-mapper ioctl protocol version %d failed. "
"Trying protocol version 1.", _dm_version);
_dm_version = 1;
if (_check_version(dmversion, sizeof(dmversion), 0)) {
log_verbose("Using device-mapper ioctl protocol version 1");
return 1;
}
compat = "(compat)";
dm_get_library_version(libversion, sizeof(libversion));
log_error("Incompatible libdevmapper %s%s and kernel driver %s",
libversion, compat, dmversion);
bad:
_version_ok = 0;
return 0;
}
void *dm_get_next_target(struct dm_task *dmt, void *next,
uint64_t *start, uint64_t *length,
char **target_type, char **params)
@@ -121,55 +588,102 @@ void *dm_get_next_target(struct dm_task *dmt, void *next,
/* Unmarshall the target info returned from a status call */
static int _unmarshal_status(struct dm_task *dmt, struct dm_ioctl *dmi)
{
char *outbuf = (char *) dmi + sizeof(struct dm_ioctl);
char *outbuf = (char *) dmi + dmi->data_start;
char *outptr = outbuf;
int i;
uint32_t i;
struct dm_target_spec *spec;
for (i = 0; i < dmi->target_count; i++) {
struct dm_target_spec *spec = (struct dm_target_spec *) outptr;
if (!dm_task_add_target(dmt, spec->sector_start, spec->length,
spec = (struct dm_target_spec *) outptr;
if (!dm_task_add_target(dmt, spec->sector_start,
spec->length,
spec->target_type,
outptr + sizeof(*spec)))
return 0;
outptr += sizeof(struct dm_target_spec);
outptr += strlen(outptr) + 1;
_align(outptr, ALIGNMENT);
outptr = outbuf + spec->next;
}
return 1;
}
int dm_format_dev(char *buf, int bufsize, uint32_t dev_major, uint32_t dev_minor)
{
int r;
if (_dm_version == 1)
return _dm_format_dev_v1(buf, bufsize, dev_major, dev_minor);
if (bufsize < 8)
return 0;
r = snprintf(buf, bufsize, "%03u:%03u", dev_major, dev_minor);
if (r < 0 || r > bufsize - 1)
return 0;
return 1;
}
int dm_task_get_info(struct dm_task *dmt, struct dm_info *info)
{
if (!dmt->dmi)
if (_dm_version == 1)
return _dm_task_get_info_v1(dmt, info);
if (!dmt->dmi.v4)
return 0;
memset(info, 0, sizeof(*info));
info->exists = dmt->dmi->flags & DM_EXISTS_FLAG ? 1 : 0;
info->exists = dmt->dmi.v4->flags & DM_EXISTS_FLAG ? 1 : 0;
if (!info->exists)
return 1;
info->suspended = dmt->dmi->flags & DM_SUSPEND_FLAG ? 1 : 0;
info->read_only = dmt->dmi->flags & DM_READONLY_FLAG ? 1 : 0;
info->target_count = dmt->dmi->target_count;
info->open_count = dmt->dmi->open_count;
info->major = MAJOR(dmt->dmi->dev);
info->minor = MINOR(dmt->dmi->dev);
info->suspended = dmt->dmi.v4->flags & DM_SUSPEND_FLAG ? 1 : 0;
info->read_only = dmt->dmi.v4->flags & DM_READONLY_FLAG ? 1 : 0;
info->live_table = dmt->dmi.v4->flags & DM_ACTIVE_PRESENT_FLAG ? 1 : 0;
info->inactive_table = dmt->dmi.v4->flags & DM_INACTIVE_PRESENT_FLAG ?
1 : 0;
info->target_count = dmt->dmi.v4->target_count;
info->open_count = dmt->dmi.v4->open_count;
info->event_nr = dmt->dmi.v4->event_nr;
info->major = MAJOR(dmt->dmi.v4->dev);
info->minor = MINOR(dmt->dmi.v4->dev);
return 1;
}
const char *dm_task_get_name(struct dm_task *dmt)
{
if (_dm_version == 1)
return _dm_task_get_name_v1(dmt);
return (dmt->dmi.v4->name);
}
const char *dm_task_get_uuid(struct dm_task *dmt)
{
return (dmt->dmi->uuid);
if (_dm_version == 1)
return _dm_task_get_uuid_v1(dmt);
return (dmt->dmi.v4->uuid);
}
struct dm_deps *dm_task_get_deps(struct dm_task *dmt)
{
return (struct dm_deps *) (((void *) dmt->dmi) + dmt->dmi->data_start);
if (_dm_version == 1)
return _dm_task_get_deps_v1(dmt);
return (struct dm_deps *) (((void *) dmt->dmi.v4) +
dmt->dmi.v4->data_start);
}
struct dm_names *dm_task_get_names(struct dm_task *dmt)
{
if (_dm_version == 1)
return _dm_task_get_names_v1(dmt);
return (struct dm_names *) (((void *) dmt->dmi.v4) +
dmt->dmi.v4->data_start);
}
int dm_task_set_ro(struct dm_task *dmt)
@@ -188,6 +702,13 @@ int dm_task_set_newname(struct dm_task *dmt, const char *newname)
return 1;
}
int dm_task_set_event_nr(struct dm_task *dmt, uint32_t event_nr)
{
dmt->event_nr = event_nr;
return 1;
}
struct target *create_target(uint64_t start, uint64_t len, const char *type,
const char *params)
{
@@ -225,10 +746,11 @@ static void *_add_target(struct target *t, void *out, void *end)
{
void *out_sp = out;
struct dm_target_spec sp;
size_t sp_size = sizeof(struct dm_target_spec);
int len;
const char no_space[] = "Ran out of memory building ioctl parameter";
out += sizeof(struct dm_target_spec);
out += sp_size;
if (out >= end) {
log_error(no_space);
return NULL;
@@ -254,7 +776,7 @@ static void *_add_target(struct target *t, void *out, void *end)
out = _align(out, ALIGNMENT);
sp.next = out - out_sp;
memcpy(out_sp, &sp, sizeof(sp));
memcpy(out_sp, &sp, sp_size);
return out;
}
@@ -262,6 +784,7 @@ static void *_add_target(struct target *t, void *out, void *end)
static struct dm_ioctl *_flatten(struct dm_task *dmt)
{
const size_t min_size = 16 * 1024;
const int (*version)[3];
struct dm_ioctl *dmi;
struct target *t;
@@ -295,9 +818,12 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt)
memset(dmi, 0, len);
dmi->version[0] = _cmd_data[dmt->type].version[0];
dmi->version[1] = _cmd_data[dmt->type].version[1];
dmi->version[2] = _cmd_data[dmt->type].version[2];
version = &_cmd_data_v4[dmt->type].version;
dmi->version[0] = (*version)[0];
dmi->version[1] = (*version)[1];
dmi->version[2] = (*version)[2];
dmi->data_size = len;
dmi->data_start = sizeof(struct dm_ioctl);
@@ -310,14 +836,19 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt)
dmi->flags |= DM_READONLY_FLAG;
if (dmt->minor >= 0) {
if (dmt->major <= 0) {
log_error("Missing major number for persistent device");
return NULL;
}
dmi->flags |= DM_PERSISTENT_DEV_FLAG;
dmi->dev = MKDEV(0, dmt->minor);
dmi->dev = MKDEV(dmt->major, dmt->minor);
}
if (dmt->uuid)
strncpy(dmi->uuid, dmt->uuid, sizeof(dmi->uuid));
dmi->target_count = count;
dmi->event_nr = dmt->event_nr;
b = (void *) (dmi + 1);
e = (void *) ((char *) dmi + len);
@@ -336,49 +867,124 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt)
return NULL;
}
int dm_task_run(struct dm_task *dmt)
static int _create_and_load_v4(struct dm_task *dmt)
{
int fd = -1;
struct dm_ioctl *dmi = _flatten(dmt);
unsigned int command;
char control[PATH_MAX];
struct dm_task *task;
int r;
if (!dmi) {
log_error("Couldn't create ioctl argument");
/* Use new task struct to create the device */
if (!(task = dm_task_create(DM_DEVICE_CREATE))) {
log_error("Failed to create device-mapper task struct");
return 0;
}
snprintf(control, sizeof(control), "%s/control", dm_dir());
if ((fd = open(control, O_RDWR)) < 0) {
log_error("%s: open failed: %s", control, strerror(errno));
log_error("Is device-mapper driver missing from kernel?");
goto bad;
/* Copy across relevant fields */
if (dmt->dev_name && !dm_task_set_name(task, dmt->dev_name)) {
dm_task_destroy(task);
return 0;
}
if (dmt->type >= (sizeof(_cmd_data) / sizeof(*_cmd_data))) {
if (dmt->uuid && !dm_task_set_uuid(task, dmt->uuid)) {
dm_task_destroy(task);
return 0;
}
task->major = dmt->major;
task->minor = dmt->minor;
r = dm_task_run(task);
dm_task_destroy(task);
if (!r)
return r;
/* Next load the table */
if (!(task = dm_task_create(DM_DEVICE_RELOAD))) {
log_error("Failed to create device-mapper task struct");
return 0;
}
/* Copy across relevant fields */
if (dmt->dev_name && !dm_task_set_name(task, dmt->dev_name)) {
dm_task_destroy(task);
return 0;
}
task->read_only = dmt->read_only;
task->head = dmt->head;
task->tail = dmt->tail;
r = dm_task_run(task);
task->head = NULL;
task->tail = NULL;
dm_task_destroy(task);
if (!r)
return r;
/* Use the original structure last so the info will be correct */
dmt->type = DM_DEVICE_RESUME;
dmt->uuid = NULL;
free(dmt->uuid);
r = dm_task_run(dmt);
return r;
}
int dm_task_run(struct dm_task *dmt)
{
struct dm_ioctl *dmi;
unsigned int command;
if (_dm_version == 1)
return _dm_task_run_v1(dmt);
if ((unsigned) dmt->type >=
(sizeof(_cmd_data_v4) / sizeof(*_cmd_data_v4))) {
log_error("Internal error: unknown device-mapper task %d",
dmt->type);
goto bad;
}
command = _cmd_data[dmt->type].cmd;
command = _cmd_data_v4[dmt->type].cmd;
/* Old-style creation had a table supplied */
if (dmt->type == DM_DEVICE_CREATE && dmt->head)
return _create_and_load_v4(dmt);
if (!_open_control())
return 0;
dmi = _flatten(dmt);
if (!dmi) {
log_error("Couldn't create ioctl argument");
return 0;
}
if (dmt->type == DM_DEVICE_TABLE)
dmi->flags |= DM_STATUS_TABLE_FLAG;
log_debug("dm %s %s %s %s", _cmd_data[dmt->type].name, dmi->name,
dmi->flags |= DM_EXISTS_FLAG; /* FIXME */
log_debug("dm %s %s %s %s", _cmd_data_v4[dmt->type].name, dmi->name,
dmi->uuid, dmt->newname ? dmt->newname : "");
if (ioctl(fd, command, dmi) < 0) {
log_error("device-mapper ioctl cmd %d failed: %s",
_IOC_NR(command), strerror(errno));
if (ioctl(_control_fd, command, dmi) < 0) {
if (errno == ENXIO && dmt->type == DM_DEVICE_INFO) {
dmi->flags &= ~DM_EXISTS_FLAG; /* FIXME */
goto ignore_error;
}
if (_log_suppress)
log_verbose("device-mapper ioctl cmd %d failed: %s",
_IOC_NR(command), strerror(errno));
else
log_error("device-mapper ioctl cmd %d failed: %s",
_IOC_NR(command), strerror(errno));
goto bad;
}
ignore_error:
switch (dmt->type) {
case DM_DEVICE_CREATE:
add_dev_node(dmt->dev_name, dmi->dev);
add_dev_node(dmt->dev_name, MAJOR(dmi->dev), MINOR(dmi->dev));
break;
case DM_DEVICE_REMOVE:
@@ -391,18 +997,35 @@ int dm_task_run(struct dm_task *dmt)
case DM_DEVICE_STATUS:
case DM_DEVICE_TABLE:
case DM_DEVICE_WAITEVENT:
if (!_unmarshal_status(dmt, dmi))
goto bad;
break;
}
dmt->dmi = dmi;
close(fd);
dmt->dmi.v4 = dmi;
return 1;
bad:
free(dmi);
if (fd >= 0)
close(fd);
return 0;
}
void dm_lib_release(void)
{
if (_control_fd != -1) {
close(_control_fd);
_control_fd = -1;
}
update_devs();
}
void dm_lib_exit(void)
{
if (_control_fd != -1) {
close(_control_fd);
_control_fd = -1;
}
_version_ok = 1;
_version_checked = 0;
}

109
libdm/ioctl/libdm-compat.h Normal file
View File

@@ -0,0 +1,109 @@
/*
* Copyright (C) 2001 Sistina Software (UK) Limited.
*
* This file is released under the LGPL.
*/
#ifndef _LINUX_LIBDM_COMPAT_H
#define _LINUX_LIBDM_COMPAT_H
#include <inttypes.h>
#include <linux/dm-ioctl.h>
#include <linux/kdev_t.h>
#include <sys/ioctl.h>
struct dm_task;
struct dm_info;
/*
* Old versions of structures for backwards compatibility.
*/
struct dm_ioctl_v1 {
uint32_t version[3]; /* in/out */
uint32_t data_size; /* total size of data passed in
* including this struct */
uint32_t data_start; /* offset to start of data
* relative to start of this struct */
int32_t target_count; /* in/out */
int32_t open_count; /* out */
uint32_t flags; /* in/out */
__kernel_dev_t dev; /* in/out */
char name[DM_NAME_LEN]; /* device name */
char uuid[DM_UUID_LEN]; /* unique identifier for
* the block device */
};
struct dm_target_spec_v1 {
int32_t status; /* used when reading from kernel only */
uint64_t sector_start;
uint32_t length;
uint32_t next;
char target_type[DM_MAX_TYPE_NAME];
};
struct dm_target_deps_v1 {
uint32_t count;
__kernel_dev_t dev[0]; /* out */
};
enum {
/* Top level cmds */
DM_VERSION_CMD_V1 = 0,
DM_REMOVE_ALL_CMD_V1,
/* device level cmds */
DM_DEV_CREATE_CMD_V1,
DM_DEV_REMOVE_CMD_V1,
DM_DEV_RELOAD_CMD_V1,
DM_DEV_RENAME_CMD_V1,
DM_DEV_SUSPEND_CMD_V1,
DM_DEV_DEPS_CMD_V1,
DM_DEV_STATUS_CMD_V1,
/* target level cmds */
DM_TARGET_STATUS_CMD_V1,
DM_TARGET_WAIT_CMD_V1,
};
#define DM_VERSION_V1 _IOWR(DM_IOCTL, DM_VERSION_CMD_V1, struct dm_ioctl)
#define DM_REMOVE_ALL_V1 _IOWR(DM_IOCTL, DM_REMOVE_ALL_CMD_V1, struct dm_ioctl)
#define DM_DEV_CREATE_V1 _IOWR(DM_IOCTL, DM_DEV_CREATE_CMD_V1, struct dm_ioctl)
#define DM_DEV_REMOVE_V1 _IOWR(DM_IOCTL, DM_DEV_REMOVE_CMD_V1, struct dm_ioctl)
#define DM_DEV_RELOAD_V1 _IOWR(DM_IOCTL, DM_DEV_RELOAD_CMD_V1, struct dm_ioctl)
#define DM_DEV_SUSPEND_V1 _IOWR(DM_IOCTL, DM_DEV_SUSPEND_CMD_V1, struct dm_ioctl)
#define DM_DEV_RENAME_V1 _IOWR(DM_IOCTL, DM_DEV_RENAME_CMD_V1, struct dm_ioctl)
#define DM_DEV_DEPS_V1 _IOWR(DM_IOCTL, DM_DEV_DEPS_CMD_V1, struct dm_ioctl)
#define DM_DEV_STATUS_V1 _IOWR(DM_IOCTL, DM_DEV_STATUS_CMD_V1, struct dm_ioctl)
#define DM_TARGET_STATUS_V1 _IOWR(DM_IOCTL, DM_TARGET_STATUS_CMD_V1, struct dm_ioctl)
#define DM_TARGET_WAIT_V1 _IOWR(DM_IOCTL, DM_TARGET_WAIT_CMD_V1, struct dm_ioctl)
/* *INDENT-OFF* */
static struct cmd_data _cmd_data_v1[] = {
{ "create", DM_DEV_CREATE_V1, {1, 0, 0} },
{ "reload", DM_DEV_RELOAD_V1, {1, 0, 0} },
{ "remove", DM_DEV_REMOVE_V1, {1, 0, 0} },
{ "remove_all", DM_REMOVE_ALL_V1, {1, 0, 0} },
{ "suspend", DM_DEV_SUSPEND_V1, {1, 0, 0} },
{ "resume", DM_DEV_SUSPEND_V1, {1, 0, 0} },
{ "info", DM_DEV_STATUS_V1, {1, 0, 0} },
{ "deps", DM_DEV_DEPS_V1, {1, 0, 0} },
{ "rename", DM_DEV_RENAME_V1, {1, 0, 0} },
{ "version", DM_VERSION_V1, {1, 0, 0} },
{ "status", DM_TARGET_STATUS_V1, {1, 0, 0} },
{ "table", DM_TARGET_STATUS_V1, {1, 0, 0} },
{ "waitevent", DM_TARGET_WAIT_V1, {1, 0, 0} },
{ "names", 0, {4, 0, 0} }
};
/* *INDENT-ON* */
#endif

View File

@@ -7,7 +7,10 @@
#ifndef LIB_DMTARGETS_H
#define LIB_DMTARGETS_H
#include "libdevmapper.h"
#include <inttypes.h>
struct dm_ioctl;
struct dm_ioctl_v1;
struct target {
uint64_t start;
@@ -25,12 +28,24 @@ struct dm_task {
struct target *head, *tail;
int read_only;
uint32_t event_nr;
int major;
int minor;
struct dm_ioctl *dmi;
union {
struct dm_ioctl *v4;
struct dm_ioctl_v1 *v1;
} dmi;
char *newname;
char *uuid;
};
#endif
struct cmd_data {
const char *name;
const int cmd;
const int version[3];
};
int dm_check_version(void);
#endif

View File

@@ -29,6 +29,7 @@ typedef void (*dm_log_fn) (int level, const char *file, int line,
* stderr.
*/
void dm_log_init(dm_log_fn fn);
void dm_log_init_verbose(int level);
enum {
DM_DEVICE_CREATE,
@@ -47,7 +48,11 @@ enum {
DM_DEVICE_STATUS,
DM_DEVICE_TABLE,
DM_DEVICE_WAITEVENT
DM_DEVICE_WAITEVENT,
DM_DEVICE_LIST,
DM_DEVICE_CLEAR
};
struct dm_task;
@@ -64,29 +69,43 @@ int dm_task_set_uuid(struct dm_task *dmt, const char *uuid);
struct dm_info {
int exists;
int suspended;
unsigned int open_count;
int major;
int minor; /* minor device number */
int live_table;
int inactive_table;
int32_t open_count;
uint32_t event_nr;
uint32_t major;
uint32_t minor; /* minor device number */
int read_only; /* 0:read-write; 1:read-only */
unsigned int target_count;
int32_t target_count;
};
struct dm_deps {
unsigned int count;
__kernel_dev_t device[0];
uint32_t count;
uint32_t filler;
uint64_t device[0];
};
struct dm_names {
uint64_t dev;
uint32_t next; /* Offset to next struct from start of this struct */
char name[0];
};
int dm_get_library_version(char *version, size_t size);
int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size);
int dm_task_get_info(struct dm_task *dmt, struct dm_info *dmi);
const char *dm_task_get_name(struct dm_task *dmt);
const char *dm_task_get_uuid(struct dm_task *dmt);
struct dm_deps *dm_task_get_deps(struct dm_task *dmt);
struct dm_names *dm_task_get_names(struct dm_task *dmt);
int dm_task_set_ro(struct dm_task *dmt);
int dm_task_set_newname(struct dm_task *dmt, const char *newname);
int dm_task_set_minor(struct dm_task *dmt, int minor);
int dm_task_set_major(struct dm_task *dmt, int major);
int dm_task_set_event_nr(struct dm_task *dmt, uint32_t event_nr);
/*
* Use these to prepare for a create or reload.
@@ -95,6 +114,11 @@ int dm_task_add_target(struct dm_task *dmt,
uint64_t start,
uint64_t size, const char *ttype, const char *params);
/*
* Format major/minor numbers correctly for input to driver
*/
int dm_format_dev(char *buf, int bufsize, uint32_t dev_major, uint32_t dev_minor);
/* Use this to retrive target information returned from a STATUS call */
void *dm_get_next_target(struct dm_task *dmt,
void *next, uint64_t *start, uint64_t *length,
@@ -111,4 +135,8 @@ int dm_task_run(struct dm_task *dmt);
int dm_set_dev_dir(const char *dir);
const char *dm_dir(void);
/* Release library resources */
void dm_lib_release(void);
void dm_lib_exit(void);
#endif /* LIB_DEVICE_MAPPER_H */

View File

@@ -6,25 +6,25 @@
#include "libdm-targets.h"
#include "libdm-common.h"
#include "libdevmapper.h"
#include "list.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <linux/kdev_t.h>
#include <linux/dm-ioctl.h>
#include <linux/kdev_t.h>
#define DEV_DIR "/dev/"
static char _dm_dir[PATH_MAX] = DEV_DIR DM_DIR;
static int _verbose = 0;
/*
* Library users can provide their own logging
* function.
@@ -34,19 +34,22 @@ static void _default_log(int level, const char *file, int line,
{
va_list ap;
if (level > _LOG_WARN)
if (level > _LOG_WARN && !_verbose)
return;
va_start(ap, f);
if (level == _LOG_WARN)
vprintf(f, ap);
else
if (level < _LOG_WARN)
vfprintf(stderr, f, ap);
else
vprintf(f, ap);
va_end(ap);
fprintf(stderr, "\n");
if (level < _LOG_WARN)
fprintf(stderr, "\n");
else
printf("\n");
}
dm_log_fn _log = _default_log;
@@ -56,6 +59,11 @@ void dm_log_init(dm_log_fn fn)
_log = fn;
}
void dm_log_init_verbose(int level)
{
_verbose = level;
}
static void _build_dev_path(char *buffer, size_t len, const char *dev_name)
{
/* If there's a /, assume caller knows what they're doing */
@@ -75,6 +83,9 @@ struct dm_task *dm_task_create(int type)
{
struct dm_task *dmt = malloc(sizeof(*dmt));
if (!dm_check_version())
return NULL;
if (!dmt) {
log_error("dm_task_create: malloc(%d) failed", sizeof(*dmt));
return NULL;
@@ -84,6 +95,8 @@ struct dm_task *dm_task_create(int type)
dmt->type = type;
dmt->minor = -1;
dmt->major = -1;
return dmt;
}
@@ -137,6 +150,14 @@ int dm_task_set_uuid(struct dm_task *dmt, const char *uuid)
return 1;
}
int dm_task_set_major(struct dm_task *dmt, int major)
{
dmt->major = major;
log_debug("Setting major: %d", dmt->major);
return 1;
}
int dm_task_set_minor(struct dm_task *dmt, int minor)
{
dmt->minor = minor;
@@ -163,10 +184,11 @@ int dm_task_add_target(struct dm_task *dmt, uint64_t start, uint64_t size,
return 1;
}
int add_dev_node(const char *dev_name, dev_t dev)
static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor)
{
char path[PATH_MAX];
struct stat info;
dev_t dev = MKDEV(major, minor);
_build_dev_path(path, sizeof(path), dev_name);
@@ -195,7 +217,7 @@ int add_dev_node(const char *dev_name, dev_t dev)
return 1;
}
int rename_dev_node(const char *old_name, const char *new_name)
static int _rename_dev_node(const char *old_name, const char *new_name)
{
char oldpath[PATH_MAX];
char newpath[PATH_MAX];
@@ -212,7 +234,7 @@ int rename_dev_node(const char *old_name, const char *new_name)
}
if (unlink(newpath) < 0) {
if (errno == EPERM) {
if (errno == EPERM) {
/* devfs, entry has already been renamed */
return 1;
}
@@ -231,7 +253,7 @@ int rename_dev_node(const char *old_name, const char *new_name)
return 1;
}
int rm_dev_node(const char *dev_name)
static int _rm_dev_node(const char *dev_name)
{
char path[PATH_MAX];
struct stat info;
@@ -249,6 +271,105 @@ int rm_dev_node(const char *dev_name)
return 1;
}
typedef enum {
NODE_ADD,
NODE_DEL,
NODE_RENAME
} node_op_t;
static int _do_node_op(node_op_t type, const char *dev_name, uint32_t major,
uint32_t minor, const char *old_name)
{
switch (type) {
case NODE_ADD:
return _add_dev_node(dev_name, major, minor);
case NODE_DEL:
return _rm_dev_node(dev_name);
case NODE_RENAME:
return _rename_dev_node(old_name, dev_name);
}
return 1;
}
static LIST_INIT(_node_ops);
struct node_op_parms {
struct list list;
node_op_t type;
char *dev_name;
uint32_t major;
uint32_t minor;
char *old_name;
char names[0];
};
static void _store_str(char **pos, char **ptr, const char *str)
{
strcpy(*pos, str);
*ptr = *pos;
*pos += strlen(*ptr) + 1;
}
static int _stack_node_op(node_op_t type, const char *dev_name, uint32_t major,
uint32_t minor, const char *old_name)
{
struct node_op_parms *nop;
size_t len = strlen(dev_name) + strlen(old_name) + 2;
char *pos;
if (!(nop = malloc(sizeof(*nop) + len))) {
log_error("Insufficient memory to stack mknod operation");
return 0;
}
pos = nop->names;
nop->type = type;
nop->major = major;
nop->minor = minor;
_store_str(&pos, &nop->dev_name, dev_name);
_store_str(&pos, &nop->old_name, old_name);
list_add(&_node_ops, &nop->list);
return 1;
}
static void _pop_node_ops(void)
{
struct list *noph, *nopht;
struct node_op_parms *nop;
list_iterate_safe(noph, nopht, &_node_ops) {
nop = list_item(noph, struct node_op_parms);
_do_node_op(nop->type, nop->dev_name, nop->major, nop->minor,
nop->old_name);
list_del(&nop->list);
free(nop);
}
}
int add_dev_node(const char *dev_name, uint32_t major, uint32_t minor)
{
return _stack_node_op(NODE_ADD, dev_name, major, minor, "");
}
int rename_dev_node(const char *old_name, const char *new_name)
{
return _stack_node_op(NODE_RENAME, new_name, 0, 0, old_name);
}
int rm_dev_node(const char *dev_name)
{
return _stack_node_op(NODE_DEL, dev_name, 0, 0, "");
}
void update_devs(void)
{
_pop_node_ops();
}
int dm_set_dev_dir(const char *dir)
{
snprintf(_dm_dir, sizeof(_dm_dir), "%s%s", dir, DM_DIR);

View File

@@ -7,6 +7,8 @@
#ifndef LIB_DMCOMMON_H
#define LIB_DMCOMMON_H
#include "libdevmapper.h"
#define _LOG_DEBUG 7
#define _LOG_INFO 6
#define _LOG_NOTICE 5
@@ -14,7 +16,7 @@
#define _LOG_ERR 3
#define _LOG_FATAL 2
dm_log_fn _log;
extern dm_log_fn _log;
#define log_error(msg, x...) _log(_LOG_ERR, __FILE__, __LINE__, msg, ## x)
#define log_print(msg, x...) _log(_LOG_WARN, __FILE__, __LINE__, msg, ## x)
@@ -23,12 +25,13 @@ dm_log_fn _log;
#define log_debug(msg, x...) _log(_LOG_DEBUG, __FILE__, __LINE__, msg, ## x)
struct target *create_target(uint64_t start,
uint64_t len,
const char *type, const char *params);
uint64_t len,
const char *type, const char *params);
int add_dev_node(const char *dev_name, dev_t dev);
int add_dev_node(const char *dev_name, uint32_t minor, uint32_t major);
int rm_dev_node(const char *dev_name);
int rename_dev_node(const char *old_name, const char *new_name);
void update_devs(void);
#define DM_LIB_VERSION @DM_LIB_VERSION@

View File

@@ -27,6 +27,7 @@ SHELL = /bin/sh
INSTALL = @INSTALL@
LN_S = @LN_S@
LIBS = @LIBS@
CFLAGS = @CFLAGS@
# Setup directory variables
prefix = $(DESTDIR)@prefix@
@@ -81,18 +82,6 @@ STRIP=
DEPS=$(top_srcdir)/make.tmpl Makefile $(INC_LNS)
ifeq ("@READLINE@", "yes")
CFLAGS += -DREADLINE_SUPPORT
endif
ifeq ("@HAVE_RL_COMPLETION_MATCHES@", "yes")
CFLAGS += -DHAVE_RL_COMPLETION_MATCHES
endif
ifeq ("@LVM1@", "internal")
CFLAGS += -DLVM1_INTERNAL
endif
OBJECTS=$(SOURCES:%.c=%.o)
SUBDIRS.install := $(SUBDIRS:=.install)
@@ -109,7 +98,7 @@ install: all $(SUBDIRS.install)
$(SUBDIRS):
$(MAKE) -C $@
$(SUBDIRS.install):
$(SUBDIRS.install): $(SUBDIRS)
$(MAKE) -C $(@:.install=) install
$(SUBDIRS.clean):

View File

@@ -23,8 +23,8 @@ VPATH = @srcdir@
MAN5=lvm.conf.5
MAN8=lvchange.8 lvcreate.8 lvdisplay.8 lvextend.8 lvm.8 lvmchange.8 \
lvreduce.8 lvremove.8 lvrename.8 lvs.8 lvscan.8 pvchange.8 \
pvcreate.8 pvdisplay.8 pvremove.8 pvs.8 pvscan.8 vgcfgbackup.8 \
vgcfgrestore.8 vgchange.8 vgck.8 vgcreate.8 \
pvcreate.8 pvdisplay.8 pvmove.8 pvremove.8 pvs.8 pvscan.8 \
vgcfgbackup.8 vgcfgrestore.8 vgchange.8 vgck.8 vgcreate.8 \
vgconvert.8 vgdisplay.8 vgextend.8 vgmerge.8 vgreduce.8 vgremove.8 \
vgrename.8 vgs.8 vgscan.8
MAN5DIR=${mandir}/man5

View File

@@ -31,7 +31,7 @@ the volume group can be extended ( see
.B vgextend(8)
) with other physical volumes or by reducing existing logical volumes
of this volume group in size ( see
.B lvreduce(8), e2fsadm(8)
.B lvreduce(8)
).
.br
The second form supports the creation of snapshot logical volumes which

View File

@@ -17,9 +17,6 @@ You should therefore ensure that the (eg) filesystem on the volume is
resized
.i before
running lvreduce so that the extents that are to be removed are not in use.
If the filesystem is ext2 then you can use the
.B e2fsadm(8)
command to both resize the filesystem and the logical volume together.
.br.
Shrinking snapshot logical volumes (see
.B lvcreate(8)

Some files were not shown because too many files have changed in this diff Show More