1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-10-01 21:44:22 +03:00

Compare commits

...

87 Commits

Author SHA1 Message Date
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
119 changed files with 5752 additions and 1378 deletions

View File

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

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
@@ -78,9 +87,10 @@ 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!
pvmove will be enhanced to remove the volume group lock so that you can
run other commands alongside.

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

@@ -193,6 +193,17 @@ 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
}
####################
# Advanced section #

View File

@@ -14,8 +14,6 @@ endif
SOURCES=\
activate/activate.c \
activate/dev_manager.c \
activate/fs.c \
cache/cache.c \
commands/toolcontext.c \
config/config.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,12 @@ 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/pool.c \
regex/matcher.c \
regex/parse_rx.c \
@@ -75,6 +72,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

@@ -15,11 +15,68 @@
#include "dev_manager.h"
#include <limits.h>
#include <linux/kdev_t.h>
#include <fcntl.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, float *percent, int wait)
{
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;
}
#else /* DEVMAPPER_SUPPORT */
static int _activation = 1;
void set_activation(int act)
@@ -82,22 +139,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 +178,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 +191,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 +228,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 +244,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 +261,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 +278,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 +332,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;
@@ -257,7 +345,7 @@ int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
if (test_mode()) {
_skip("Suspending '%s'.", lv->name);
return 0;
return 1;
}
if (!lv_info(lv, &info)) {
@@ -274,7 +362,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 +372,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)) {
@@ -301,7 +389,7 @@ 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;
if (!activation())
return 1;
@@ -311,7 +399,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)) {
@@ -328,7 +416,7 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
int lv_activate(struct cmd_context *cmd, const char *lvid_s)
{
struct logical_volume *lv;
struct dm_info info;
struct lvinfo info;
if (!activation())
return 1;
@@ -338,7 +426,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)) {
@@ -351,3 +439,5 @@ int lv_activate(struct cmd_context *cmd, const char *lvid_s)
return 1;
}
#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,21 @@ 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);
/*
* 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.

View File

@@ -10,6 +10,7 @@
#include "hash.h"
#include "lvm-string.h"
#include "fs.h"
#include "defaults.h"
#include <libdevmapper.h>
#include <limits.h>
@@ -45,7 +46,15 @@ enum {
RELOAD = 1,
VISIBLE = 2,
READWRITE = 3,
SUSPENDED = 4
SUSPENDED = 4,
NOPROPAGATE = 5,
TOPLEVEL = 6
};
enum {
MIRR_DISABLED,
MIRR_RUNNING,
MIRR_COMPLETED
};
typedef enum {
@@ -73,8 +82,8 @@ struct dev_layer {
struct logical_volume *lv;
/*
* Devices that must be created before this one can be
* created. Holds str_lists.
* Devices that must be created before this one can be created.
* Reloads get propagated to this list. Holds str_lists.
*/
struct list pre_create;
@@ -85,9 +94,17 @@ struct dl_list {
struct dev_layer *dl;
};
static const char *stripe_filler = NULL;
static uint32_t mirror_region_size = 0;
struct dev_manager {
struct pool *mem;
struct config_tree *cf;
const char *stripe_filler;
uint32_t mirror_region_size;
uint32_t pvmove_mirror_count;
char *vg_name;
/*
@@ -262,7 +279,8 @@ static char *_build_dlid(struct pool *mem, const char *lvid, const char *layer)
/*
* Low level device-layer operations.
*/
static struct dm_task *_setup_task(const char *name, const char *uuid, int task)
static struct dm_task *_setup_task(const char *name, const char *uuid,
uint32_t *event_nr, int task)
{
struct dm_task *dmt;
@@ -277,6 +295,9 @@ static struct dm_task *_setup_task(const char *name, const char *uuid, int task)
if (uuid && *uuid)
dm_task_set_uuid(dmt, uuid);
if (event_nr)
dm_task_set_event_nr(dmt, *event_nr);
return dmt;
}
@@ -287,7 +308,7 @@ static int _info_run(const char *name, const char *uuid, struct dm_info *info,
struct dm_task *dmt;
const char *u;
if (!(dmt = _setup_task(name, uuid, DM_DEVICE_INFO))) {
if (!(dmt = _setup_task(name, uuid, 0, DM_DEVICE_INFO))) {
stack;
return 0;
}
@@ -341,7 +362,7 @@ static int _status_run(const char *name, const char *uuid,
char *type = NULL;
char *params = NULL;
if (!(dmt = _setup_task(name, uuid, DM_DEVICE_STATUS))) {
if (!(dmt = _setup_task(name, uuid, 0, DM_DEVICE_STATUS))) {
stack;
return 0;
}
@@ -375,6 +396,11 @@ static int _status_run(const char *name, const char *uuid,
return r;
}
static int _status(const char *name, const char *uuid,
unsigned long long *start, unsigned long long *length,
char **type, uint32_t type_size, char **params,
uint32_t param_size) __attribute__ ((unused));
static int _status(const char *name, const char *uuid,
unsigned long long *start, unsigned long long *length,
char **type, uint32_t type_size, char **params,
@@ -392,6 +418,135 @@ static int _status(const char *name, const char *uuid,
return 0;
}
static int _percent_run(struct dev_manager *dm, const char *name,
const char *uuid,
const char *target_type, int wait,
struct logical_volume *lv, float *percent,
uint32_t *event_nr)
{
int r = 0;
struct dm_task *dmt;
struct dm_info info;
void *next = NULL;
uint64_t start, length;
char *type = NULL;
char *params = NULL;
float percent2;
struct list *segh = &lv->segments;
struct lv_segment *seg = NULL;
uint64_t numerator, denominator;
uint64_t total_numerator = 0, total_denominator = 0;
*percent = -1;
if (!(dmt = _setup_task(name, uuid, event_nr,
wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS)))
{
stack;
return 0;
}
if (!dm_task_run(dmt)) {
stack;
goto out;
}
if (!dm_task_get_info(dmt, &info) || !info.exists) {
stack;
goto out;
}
if (event_nr)
*event_nr = info.event_nr;
do {
next = dm_get_next_target(dmt, next, &start, &length, &type,
&params);
if (lv) {
if (!(segh = list_next(&lv->segments, segh))) {
log_error("Number of segments in active LV %s "
"does not match metadata", lv->name);
goto out;
}
seg = list_item(segh, struct lv_segment);
}
if (!type || !params || strcmp(type, target_type))
continue;
/* Mirror? */
if (!strcmp(type, "mirror")) {
log_debug("Mirror status: %s", params);
if (sscanf(params, "%*d %*x:%*x %*x:%*x %" PRIu64
"/%" PRIu64, &numerator,
&denominator) != 2) {
log_error("Failure parsing mirror status: %s",
params);
goto out;
}
total_numerator += numerator;
total_denominator += denominator;
if (seg && (seg->status & PVMOVE))
seg->extents_moved = dm->mirror_region_size *
numerator / lv->vg->extent_size;
continue;
}
if (strcmp(type, "snapshot"))
continue;
/* Snapshot */
if (index(params, '/')) {
if (sscanf(params, "%" PRIu64 "/%" PRIu64,
&numerator, &denominator) == 2) {
total_numerator += numerator;
total_denominator += denominator;
}
continue;
} else if (sscanf(params, "%f", &percent2) == 1) {
*percent += percent2;
*percent /= 2;
}
} while (next);
if (lv && (segh = list_next(&lv->segments, segh))) {
log_error("Number of segments in active LV %s does not "
"match metadata", lv->name);
goto out;
}
if (total_denominator)
*percent = (float) total_numerator *100 / total_denominator;
else
*percent = 100;
log_debug("Mirror percent: %f", *percent);
r = 1;
out:
dm_task_destroy(dmt);
return r;
}
static int _percent(struct dev_manager *dm, const char *name, const char *uuid,
const char *target_type, int wait,
struct logical_volume *lv, float *percent,
uint32_t *event_nr)
{
if (uuid && *uuid
&& _percent_run(dm, NULL, uuid, target_type, wait, lv, percent,
event_nr))
return 1;
if (name && _percent_run(dm, name, NULL, target_type, wait, lv, percent,
event_nr))
return 1;
return 0;
}
static int _rename(struct dev_layer *dl, char *newname)
{
int r = 1;
@@ -399,7 +554,7 @@ static int _rename(struct dev_layer *dl, char *newname)
log_verbose("Renaming %s to %s", dl->name, newname);
if (!(dmt = _setup_task(dl->name, NULL, DM_DEVICE_RENAME))) {
if (!(dmt = _setup_task(dl->name, NULL, 0, DM_DEVICE_RENAME))) {
stack;
return 0;
}
@@ -430,7 +585,7 @@ static int _load(struct dev_manager *dm, struct dev_layer *dl, int task)
log_verbose("Loading %s", dl->name);
if (!(dmt = _setup_task(task == DM_DEVICE_CREATE ? dl->name : NULL,
dl->dlid, task))) {
dl->dlid, 0, task))) {
stack;
return 0;
}
@@ -445,8 +600,19 @@ static int _load(struct dev_manager *dm, struct dev_layer *dl, int task)
}
/*
* Do we want a specific minor number ?
* Do we want a specific device number ?
*/
if (dl->lv->major >= 0 && _get_flag(dl, VISIBLE)) {
if (!dm_task_set_major(dmt, dl->lv->major)) {
log_error("Failed to set major number for %s to %d "
"during activation.", dl->name,
dl->lv->major);
goto out;
} else
log_very_verbose("Set major number for %s to %d.",
dl->name, dl->lv->major);
}
if (dl->lv->minor >= 0 && _get_flag(dl, VISIBLE)) {
if (!dm_task_set_minor(dmt, dl->lv->minor)) {
log_error("Failed to set minor number for %s to %d "
@@ -496,7 +662,7 @@ static int _remove(struct dev_layer *dl)
else
log_very_verbose("Removing %s", dl->name);
if (!(dmt = _setup_task(dl->name, NULL, DM_DEVICE_REMOVE))) {
if (!(dmt = _setup_task(dl->name, NULL, 0, DM_DEVICE_REMOVE))) {
stack;
return 0;
}
@@ -527,7 +693,7 @@ static int _suspend_or_resume(const char *name, action_t suspend)
int task = sus ? DM_DEVICE_SUSPEND : DM_DEVICE_RESUME;
log_very_verbose("%s %s", sus ? "Suspending" : "Resuming", name);
if (!(dmt = _setup_task(name, NULL, task))) {
if (!(dmt = _setup_task(name, NULL, 0, task))) {
stack;
return 0;
}
@@ -542,7 +708,7 @@ static int _suspend_or_resume(const char *name, action_t suspend)
static int _suspend(struct dev_layer *dl)
{
if (dl->info.suspended)
if (!dl->info.exists || dl->info.suspended)
return 1;
if (!_suspend_or_resume(dl->name, SUSPEND)) {
@@ -556,7 +722,7 @@ static int _suspend(struct dev_layer *dl)
static int _resume(struct dev_layer *dl)
{
if (!dl->info.suspended)
if (!dl->info.exists || !dl->info.suspended)
return 1;
if (!_suspend_or_resume(dl->name, RESUME)) {
@@ -577,47 +743,96 @@ static int _resume(struct dev_layer *dl)
* Emit a target for a given segment.
* FIXME: tidy this function.
*/
static int _emit_target(struct dm_task *dmt, struct lv_segment *seg)
static int _emit_target(struct dev_manager *dm, struct dm_task *dmt,
struct lv_segment *seg)
{
char params[1024];
uint64_t esize = seg->lv->vg->extent_size;
uint32_t s, stripes = seg->stripes;
uint32_t s, start_area = 0u, areas = seg->area_count;
int w = 0, tw = 0;
const char *filler = "/dev/ioerror";
const char *target = NULL;
const char *trailing_space;
int mirror_status;
if (stripes == 1) {
if (!seg->area[0].pv) {
target = "error";
goto add_target;
} else
switch (seg->type) {
case SEG_SNAPSHOT:
log_error("_emit_target: Internal error: Can't handle "
"SEG_SNAPSHOT");
return 0;
/* Target formats:
* linear [device offset]+
* striped #stripes stripe_size [device offset]+
* mirror log_type #log_params [log_params]*
* #mirrors [device offset]+
*/
case SEG_STRIPED:
if (areas == 1)
target = "linear";
} else if (stripes > 1) {
target = "striped";
if ((tw = lvm_snprintf(params, sizeof(params), "%u %u ",
stripes, seg->stripe_size)) < 0)
else if (areas > 1) {
target = "striped";
if ((tw = lvm_snprintf(params, sizeof(params), "%u %u ",
areas, seg->stripe_size)) < 0)
goto error;
w = tw;
} else {
log_error("_emit_target: Internal error: SEG_STRIPED "
"with no stripes");
return 0;
}
break;
case SEG_MIRRORED:
mirror_status = MIRR_RUNNING;
if (seg->status & PVMOVE) {
if (seg->extents_moved == seg->area_len) {
mirror_status = MIRR_COMPLETED;
start_area = 1;
} else if (dm->pvmove_mirror_count++) {
mirror_status = MIRR_DISABLED;
areas = 1;
}
}
if (mirror_status != MIRR_RUNNING) {
target = "linear";
break;
}
target = "mirror";
if ((tw = lvm_snprintf(params, sizeof(params),
"core 1 %u %u ",
dm->mirror_region_size, areas)) < 0)
goto error;
w = tw;
break;
}
for (s = 0; s < stripes; s++, w += tw) {
if (!seg->area[s].pv || !seg->area[s].pv->dev)
for (s = start_area; s < areas; s++, w += tw) {
trailing_space = (areas - s - 1) ? " " : "";
if ((seg->area[s].type == AREA_PV &&
(!seg->area[s].u.pv.pv || !seg->area[s].u.pv.pv->dev)) ||
(seg->area[s].type == AREA_LV && !seg->area[s].u.lv.lv))
tw = lvm_snprintf(params + w, sizeof(params) - w,
"%s 0%s", filler,
s == (stripes - 1) ? "" : " ");
else
"%s 0%s", dm->stripe_filler,
trailing_space);
else if (seg->area[s].type == AREA_PV)
tw = lvm_snprintf(params + w, sizeof(params) - w,
"%s %" PRIu64 "%s",
dev_name(seg->area[s].pv->dev),
(seg->area[s].pv->pe_start +
(esize * seg->area[s].pe)),
s == (stripes - 1) ? "" : " ");
dev_name(seg->area[s].u.pv.pv->dev),
(seg->area[s].u.pv.pv->pe_start +
(esize * seg->area[s].u.pv.pe)),
trailing_space);
else
tw = lvm_snprintf(params + w, sizeof(params) - w,
"%s/%s %" PRIu64 "%s", dm_dir(),
_build_name(dm->mem,
seg->lv->vg->name,
seg->area[s].u.lv.lv->
name, NULL),
esize * seg->area[s].u.lv.le,
trailing_space);
if (tw < 0)
goto error;
}
add_target:
log_debug("Adding target: %" PRIu64 " %" PRIu64 " %s %s",
esize * seg->le, esize * seg->len, target, params);
@@ -630,7 +845,7 @@ static int _emit_target(struct dm_task *dmt, struct lv_segment *seg)
return 1;
error:
log_error("Insufficient space to write target parameters.");
log_error("Insufficient space in params[] to write target parameters.");
return 0;
}
@@ -641,9 +856,11 @@ static int _populate_vanilla(struct dev_manager *dm,
struct lv_segment *seg;
struct logical_volume *lv = dl->lv;
dm->pvmove_mirror_count = 0u;
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
if (!_emit_target(dmt, seg)) {
if (!_emit_target(dm, dmt, seg)) {
log_error("Unable to build table for '%s'", lv->name);
return 0;
}
@@ -671,7 +888,7 @@ static int _populate_origin(struct dev_manager *dm,
log_debug("Adding target: 0 %" PRIu64 " snapshot-origin %s",
dl->lv->size, params);
if (!dm_task_add_target(dmt, __UINT64_C(0), dl->lv->size,
if (!dm_task_add_target(dmt, UINT64_C(0), dl->lv->size,
"snapshot-origin", params)) {
stack;
return 0;
@@ -712,7 +929,7 @@ static int _populate_snapshot(struct dev_manager *dm,
log_debug("Adding target: 0 %" PRIu64 " snapshot %s",
s->origin->size, params);
if (!dm_task_add_target
(dmt, __UINT64_C(0), s->origin->size, "snapshot", params)) {
(dmt, UINT64_C(0), s->origin->size, "snapshot", params)) {
stack;
return 0;
}
@@ -723,7 +940,8 @@ static int _populate_snapshot(struct dev_manager *dm,
/*
* dev_manager implementation.
*/
struct dev_manager *dev_manager_create(const char *vg_name)
struct dev_manager *dev_manager_create(const char *vg_name,
struct config_tree *cf)
{
struct pool *mem;
struct dev_manager *dm;
@@ -739,6 +957,21 @@ struct dev_manager *dev_manager_create(const char *vg_name)
}
dm->mem = mem;
dm->cf = cf;
if (!stripe_filler) {
stripe_filler = find_config_str(cf->root,
"activation/missing_stripe_filler",
'/', DEFAULT_STRIPE_FILLER);
}
dm->stripe_filler = stripe_filler;
if (!mirror_region_size) {
mirror_region_size = 2 * find_config_int(cf->root,
"activation/mirror_region_size",
'/',
DEFAULT_MIRROR_REGION_SIZE);
}
dm->mirror_region_size = mirror_region_size;
if (!(dm->vg_name = pool_strdup(dm->mem, vg_name))) {
stack;
@@ -796,22 +1029,7 @@ int dev_manager_info(struct dev_manager *dm, const struct logical_volume *lv,
int dev_manager_snapshot_percent(struct dev_manager *dm,
struct logical_volume *lv, float *percent)
{
char *name, *type, *params;
unsigned long long start, length;
/* FIXME: Use #defines - & move allocations into _status_run ? */
uint32_t type_size = 32;
uint32_t param_size = 32;
if (!(type = pool_alloc(dm->mem, sizeof(*type) * type_size))) {
stack;
return 0;
}
if (!(params = pool_alloc(dm->mem, sizeof(*params) * param_size))) {
stack;
return 0;
}
char *name;
/*
* Build a name for the top layer.
@@ -824,23 +1042,45 @@ int dev_manager_snapshot_percent(struct dev_manager *dm,
/*
* Try and get some info on this device.
*/
log_debug("Getting device status for %s", name);
if (!(_status(name, lv->lvid.s, &start, &length, &type, type_size,
&params, param_size))) {
log_debug("Getting device status percentage for %s", name);
if (!(_percent(dm, name, lv->lvid.s, "snapshot", 0, NULL, percent,
NULL))) {
stack;
return 0;
}
/* FIXME Ensure this is a *snapshot* target with percentage! */
/* FIXME pool_free ? */
/* If the snapshot isn't available, percent will be -1 */
*percent = -1;
return 1;
}
if (!params)
/* FIXME Merge with snapshot_percent, auto-detecting target type */
/* FIXME Cope with more than one target */
int dev_manager_mirror_percent(struct dev_manager *dm,
struct logical_volume *lv, int wait,
float *percent, uint32_t *event_nr)
{
char *name;
/*
* Build a name for the top layer.
*/
if (!(name = _build_name(dm->mem, lv->vg->name, lv->name, NULL))) {
stack;
return 0;
}
return sscanf(params, "%f", percent);
/* FIXME pool_free ? */
log_debug("Getting device mirror status percentage for %s", name);
if (!(_percent(dm, name, lv->lvid.s, "mirror", wait, lv, percent,
event_nr))) {
stack;
return 0;
}
return 1;
}
static struct dev_layer *_create_dev(struct dev_manager *dm, char *name,
@@ -938,13 +1178,41 @@ static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv)
* only one layer.
*/
struct dev_layer *dl;
struct list *segh;
struct lv_segment *seg;
uint32_t s;
if (!(dl = _create_layer(dm, NULL, lv))) {
stack;
return 0;
}
dl->populate = _populate_vanilla;
_set_flag(dl, VISIBLE);
if (lv->status & VISIBLE_LV) {
_set_flag(dl, VISIBLE);
_set_flag(dl, TOPLEVEL);
}
if (lv->status & PVMOVE)
_set_flag(dl, TOPLEVEL);
/* Add dependencies for any LVs that segments refer to */
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
if (seg->type != SEG_STRIPED && seg->type != SEG_MIRRORED)
continue;
for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_LV)
continue;
if (!_pre_list_add(dm->mem, &dl->pre_create,
_build_dlid(dm->mem,
seg->area[s].u.lv.lv->
lvid.s, NULL))) {
stack;
return 0;
}
_set_flag(dl, NOPROPAGATE);
}
}
return 1;
}
@@ -961,6 +1229,7 @@ static int _expand_origin_real(struct dev_manager *dm,
}
dl->populate = _populate_vanilla;
_clear_flag(dl, VISIBLE);
_clear_flag(dl, TOPLEVEL);
real_dlid = dl->dlid;
@@ -970,6 +1239,7 @@ static int _expand_origin_real(struct dev_manager *dm,
}
dl->populate = _populate_origin;
_set_flag(dl, VISIBLE);
_set_flag(dl, TOPLEVEL);
/* add the dependency on the real device */
if (!_pre_list_add(dm->mem, &dl->pre_create,
@@ -1016,6 +1286,7 @@ static int _expand_snapshot(struct dev_manager *dm, struct logical_volume *lv,
}
dl->populate = _populate_vanilla;
_clear_flag(dl, VISIBLE);
_clear_flag(dl, TOPLEVEL);
cow_dlid = dl->dlid;
@@ -1025,6 +1296,7 @@ static int _expand_snapshot(struct dev_manager *dm, struct logical_volume *lv,
}
dl->populate = _populate_snapshot;
_set_flag(dl, VISIBLE);
_set_flag(dl, TOPLEVEL);
/* add the dependency on the real device */
if (!_pre_list_add(dm->mem, &dl->pre_create,
@@ -1097,6 +1369,10 @@ static int _trace_layer_marks(struct dev_manager *dm, struct dev_layer *dl,
if (_get_flag(dep, flag))
continue;
/* FIXME Only propagate LV ACTIVE dependencies for now */
if ((flag != ACTIVE) && _get_flag(dl, NOPROPAGATE))
continue;
_set_flag(dep, flag);
if (!_trace_layer_marks(dm, dep, flag)) {
@@ -1379,7 +1655,7 @@ static int _execute(struct dev_manager *dm, struct volume_group *vg)
hash_iterate(hn, dm->layers) {
dl = hash_get_data(dm->layers, hn);
if (_get_flag(dl, ACTIVE) && _get_flag(dl, VISIBLE))
if (_get_flag(dl, ACTIVE) && _get_flag(dl, TOPLEVEL))
_create_rec(dm, dl, NULL);
}
@@ -1432,6 +1708,7 @@ static int _add_existing_layer(struct dev_manager *dm, const char *name)
return 1;
}
/* FIXME Get this info directly from the driver not the unreliable fs */
static int _scan_existing_devices(struct dev_manager *dm)
{
const char *dev_dir = dm_dir();
@@ -1550,12 +1827,34 @@ static int _remove_lvs(struct dev_manager *dm, struct logical_volume *lv)
return _add_lvs(dm->mem, &dm->reload_list, old_origin);
}
static int _remove_suspended_lvs(struct dev_manager *dm,
struct logical_volume *lv)
{
struct logical_volume *suspended;
struct snapshot *s;
struct list *sh, *suspend_head;
suspend_head = &dm->suspend_list;
/* Remove from list any snapshots with given origin */
list_iterate(sh, suspend_head) {
suspended = list_item(sh, struct lv_list)->lv;
if ((s = find_cow(suspended)) && s->origin == lv) {
_remove_lv(suspend_head, suspended);
}
}
_remove_lv(suspend_head, lv);
return 1;
}
static int _fill_in_active_list(struct dev_manager *dm, struct volume_group *vg)
{
int found;
char *dlid;
struct list *lvh;
struct logical_volume *lv;
struct dev_layer *dl;
list_iterate(lvh, &vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv;
@@ -1565,16 +1864,24 @@ static int _fill_in_active_list(struct dev_manager *dm, struct volume_group *vg)
return 0;
}
found = hash_lookup(dm->layers, dlid) ? 1 : 0;
dl = hash_lookup(dm->layers, dlid);
pool_free(dm->mem, dlid);
if (found) {
log_debug("Found active lv %s", lv->name);
if (dl) {
log_debug("Found active lv %s%s", lv->name,
dl->info.suspended ? " (suspended)" : "");
if (!_add_lv(dm->mem, &dm->active_list, lv)) {
stack;
return 0;
}
if (dl->info.suspended) {
if (!_add_lv(dm->mem, &dm->suspend_list, lv)) {
stack;
return 0;
}
}
}
}
@@ -1610,6 +1917,13 @@ static int _action(struct dev_manager *dm, struct logical_volume *lv,
}
}
if (action == SUSPEND || action == RESUME || action == ACTIVATE)
/* Get into known state - remove from suspend list if present */
if (!_remove_suspended_lvs(dm, lv)) {
stack;
return 0;
}
if (action == SUSPEND) {
if (!_add_lvs(dm->mem, &dm->suspend_list, lv)) {
stack;

View File

@@ -8,15 +8,16 @@
#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);
/*
@@ -29,6 +30,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);

15
lib/cache/cache.c vendored
View File

@@ -13,8 +13,6 @@
#include "metadata.h"
#include "filter.h"
#include <linux/kdev_t.h>
static struct hash_table *_pvid_hash = NULL;
static struct hash_table *_vgid_hash = NULL;
static struct hash_table *_vgname_hash = NULL;
@@ -63,11 +61,16 @@ const struct format_type *fmt_from_vgname(const char *vgname)
struct cache_vginfo *vginfo_from_vgid(const char *vgid)
{
struct cache_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;
@@ -76,11 +79,15 @@ struct cache_vginfo *vginfo_from_vgid(const char *vgid)
struct cache_info *info_from_pvid(const char *pvid)
{
struct cache_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;

3
lib/cache/cache.h vendored
View File

@@ -9,13 +9,10 @@
#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

View File

@@ -19,9 +19,12 @@
#include "label.h"
#include "lvm-file.h"
#include "format-text.h"
#include "sharedlib.h"
#include "display.h"
#ifdef HAVE_LIBDL
#include "sharedlib.h"
#endif
#ifdef LVM1_INTERNAL
#include "format1.h"
#endif
@@ -29,7 +32,6 @@
#include <locale.h>
#include <sys/stat.h>
#include <syslog.h>
#include <dlfcn.h>
#include <time.h>
static FILE *_log;
@@ -113,7 +115,9 @@ static void _init_logging(struct cmd_context *cmd)
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 +140,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 +272,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;
@@ -328,12 +333,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 +347,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 +381,7 @@ static int _init_formats(struct cmd_context *cmd)
list_add(&cmd->formats, &fmt->list);
}
}
#endif
if (!(fmt = create_text_format(cmd)))
return 0;
@@ -465,8 +475,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
}
}

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);
@@ -128,7 +127,7 @@ int read_config_fd(struct config_tree *cf, int fd, const char *file,
if (size2) {
/* FIXME Attempt adjacent mmaps MAP_FIXED into malloced space
* one PAGE_SIZE larger than required...
* one page size larger than required...
*/
if (!(p->fb = dbg_malloc(size + size2))) {
stack;
@@ -151,7 +150,7 @@ int read_config_fd(struct config_tree *cf, int fd, const char *file,
goto out;
}
} else {
mmap_offset = offset % PAGE_SIZE;
mmap_offset = offset % getpagesize();
/* memory map the file */
p->fb = mmap((caddr_t) 0, size + mmap_offset, PROT_READ,
MAP_PRIVATE, fd, offset - mmap_offset);
@@ -175,7 +174,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;
@@ -188,7 +187,7 @@ int read_config_fd(struct config_tree *cf, int fd, const char *file,
dbg_free(p->fb);
else {
/* unmap the file */
if (munmap((char *) (p->fb - mmap_offset), size)) {
if (munmap((char *) (p->fb - mmap_offset), size + mmap_offset)) {
log_sys_error("munmap", file);
r = 0;
}
@@ -536,15 +535,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 +553,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 +605,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 +627,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,9 +7,6 @@
#ifndef _LVM_CONFIG_H
#define _LVM_CONFIG_H
#include <inttypes.h>
#include <sys/types.h>
enum {
CFG_STRING,
CFG_FLOAT,

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,18 @@
#define DEFAULT_UNITS "h"
#define DEFAULT_SUFFIX 1
#define DEFAULT_ACTIVATION 1
#ifdef DEVMAPPER_SUPPORT
# define DEFAULT_ACTIVATION 1
#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 +70,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,6 +7,8 @@
#ifndef _LVM_LIST_H
#define _LVM_LIST_H
#include <assert.h>
struct list {
struct list *n, *p;
};
@@ -54,6 +56,11 @@ 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)
@@ -74,8 +81,11 @@ 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)
/* 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,6 +12,9 @@
#include <sys/types.h>
#include <inttypes.h>
/* Define some portable printing types */
#define PRIsize_t "Zu"
struct str_list {
struct list list;
char *str;

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;
@@ -53,7 +47,7 @@ static struct device *_create_dev(dev_t d)
struct device *dev;
if (!(dev = _alloc(sizeof(*dev)))) {
stack;
log_error("struct device allocation failed");
return NULL;
}
@@ -62,6 +56,7 @@ static struct device *_create_dev(dev_t d)
dev->fd = -1;
dev->flags = 0;
memset(dev->pvid, 0, sizeof(dev->pvid));
return dev;
}
@@ -129,6 +124,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 +133,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 +149,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);
@@ -382,8 +390,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);
@@ -451,8 +461,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,17 +5,21 @@
*/
#include "lib.h"
#include "device.h"
#include "lvm-types.h"
#include "device.h"
#include "metadata.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
#ifdef linux
# define u64 uint64_t /* Missing without __KERNEL__ */
# include <linux/fs.h> /* For block ioctl definitions */
# define BLKSIZE_SHIFT SECTOR_SHIFT
#endif
/* FIXME 64 bit offset!!!
_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, loff_t *, res, uint, wh);
@@ -24,7 +28,6 @@ _syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, loff_t *, res, uint,
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 +36,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;
}
@@ -70,7 +72,13 @@ int dev_get_sectsize(struct device *dev, uint32_t *size)
static void _flush(int fd)
{
ioctl(fd, BLKFLSBUF, 0);
if (ioctl(fd, BLKFLSBUF, 0) >= 0)
return;
if (fsync(fd) >= 0)
return;
sync();
}
int dev_open(struct device *dev, int flags)
@@ -238,10 +246,10 @@ int dev_zero(struct device *dev, uint64_t offset, size_t len)
}
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);

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,8 +7,6 @@
#ifndef _LVM_DEVICE_H
#define _LVM_DEVICE_H
#include "lvm-types.h"
#include "list.h"
#include "uuid.h"
#define DEV_ACCESSED_W 0x00000001 /* Device written to? */

View File

@@ -42,7 +42,7 @@ static struct {
} _segtypes[] = {
{
SEG_STRIPED, "striped"}, {
SEG_MIRROR, "mirror"}, {
SEG_MIRRORED, "mirror"}, {
SEG_SNAPSHOT, "snapshot"}
};
@@ -70,16 +70,16 @@ 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;
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;
case 'm':
@@ -92,7 +92,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 +166,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 +193,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 +335,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 +355,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 +461,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 +478,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 +516,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 +524,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 +539,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

@@ -11,9 +11,7 @@
#include "filter.h"
#include "cache.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) != sizeof(*pvd)) {
log_very_verbose("Failed to read PV data from %s",
dev_name(dev));
return 0;

View File

@@ -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

@@ -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

@@ -274,6 +274,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))
@@ -781,7 +784,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;
}
@@ -1027,7 +1030,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
}
if (!add_da
(fmt, NULL, &info->das, pv->pe_start << SECTOR_SHIFT,
__UINT64_C(0))) {
UINT64_C(0))) {
stack;
return 0;
}
@@ -1144,7 +1147,7 @@ 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);
cache_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,

View File

@@ -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

@@ -117,7 +117,7 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
return NULL;
}
if (dev_read(dev, __UINT64_C(0), LABEL_SCAN_SIZE, readbuf) !=
if (dev_read(dev, UINT64_C(0), LABEL_SCAN_SIZE, readbuf) !=
LABEL_SCAN_SIZE) {
log_debug("%s: Failed to read label area", dev_name(dev));
goto out;
@@ -205,7 +205,7 @@ int label_remove(struct device *dev)
return 0;
}
if (dev_read(dev, __UINT64_C(0), LABEL_SCAN_SIZE, readbuf) !=
if (dev_read(dev, UINT64_C(0), LABEL_SCAN_SIZE, readbuf) !=
LABEL_SCAN_SIZE) {
log_debug("%s: Failed to read label area", dev_name(dev));
goto out;

View File

@@ -8,7 +8,6 @@
#define _LVM_LABEL_H
#include "cache.h"
#include "lvm-types.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

@@ -34,7 +34,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 +46,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 +75,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 +133,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;
@@ -233,6 +239,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

@@ -28,6 +28,8 @@ static void _block_signals(int flags)
{
sigset_t set;
/* Stop process memory getting swapped out */
#ifdef MCL_CURRENT
if (!_write_lock_held && (flags & LCK_SCOPE_MASK) == LCK_LV &&
(flags & LCK_TYPE_MASK) == LCK_WRITE) {
if (mlockall(MCL_CURRENT | MCL_FUTURE))
@@ -37,6 +39,7 @@ static void _block_signals(int flags)
_write_lock_held = 1;
}
}
#endif
if (_signals_blocked)
return;
@@ -58,6 +61,7 @@ static void _block_signals(int flags)
static void _unblock_signals(void)
{
#ifdef MCL_CURRENT
if (!_lock_count && _write_lock_held) {
if (munlockall()) {
log_very_verbose("Unlocking memory");
@@ -66,6 +70,7 @@ static void _unblock_signals(void)
_write_lock_held = 0;
}
#endif
/* Don't unblock signals while any locks are held */
if (!_signals_blocked || _lock_count)
@@ -81,6 +86,19 @@ static void _unblock_signals(void)
return;
}
void reset_locking(void)
{
int was_locked = _lock_count;
_lock_count = 0;
_write_lock_held = 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 +125,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

@@ -22,6 +22,11 @@ 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)
{
@@ -54,6 +59,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

@@ -14,6 +14,7 @@ static FILE *_log = 0;
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 _indent = 1;
@@ -68,6 +69,11 @@ void init_partial(int level)
_partial = level;
}
void init_pvmove(int level)
{
_pvmove = level;
}
void init_ignorelockingfailure(int level)
{
_ignorelockingfailure = level;
@@ -107,6 +113,11 @@ int partial_mode()
return _partial;
}
int pvmove_mode()
{
return _pvmove;
}
int ignorelockingfailure()
{
return _ignorelockingfailure;

View File

@@ -48,6 +48,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,6 +59,7 @@ 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);
@@ -78,10 +80,10 @@ 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) \

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

@@ -23,14 +23,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 +68,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 +157,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 +165,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 +320,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 +403,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;
@@ -587,8 +616,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;
}
@@ -686,8 +722,7 @@ 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;
}
@@ -696,7 +731,7 @@ struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
*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;
}
@@ -727,6 +762,8 @@ struct list *get_pvs(struct cmd_context *cmd)
struct list *vgnames, *slh;
struct volume_group *vg;
int consistent = 0;
int old_partial;
int old_pvmove;
cache_label_scan(cmd, 0);
@@ -745,7 +782,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 +804,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;
@@ -177,17 +180,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 +216,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 +240,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 {
@@ -360,8 +384,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 +403,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 +444,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 +470,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 +482,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;
}
/* Remove a temporary mirror */
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

@@ -15,6 +15,4 @@
#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)

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

@@ -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,13 @@ 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))
repstr[0] = toupper(repstr[0]);
} else {
repstr[4] = '-';
repstr[5] = '-';
@@ -282,7 +296,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 +320,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 +492,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;
}
@@ -555,10 +591,16 @@ 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))) {
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 +610,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 +825,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 +847,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,6 +7,8 @@
#ifndef _LVM_LIST_H
#define _LVM_LIST_H
#include <assert.h>
struct list {
struct list *n, *p;
};
@@ -54,6 +56,11 @@ 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)
@@ -74,8 +81,11 @@ 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)
/* 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,452 @@
* 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;
}
dmt->dmi.v1 = dmi;
return 1;
bad:
free(dmi);
return 0;
}
void dm_task_destroy(struct dm_task *dmt)
@@ -77,8 +469,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 +482,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 +580,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 +694,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 +738,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 +768,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 +776,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 +810,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 +828,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 +859,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 +989,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):

51
man/pvmove.8 Normal file
View File

@@ -0,0 +1,51 @@
.TH PVMOVE 8 "LVM TOOLS" "Sistina Software UK" \" -*- nroff -*-
.SH NAME
pvmove \- move physical extents
.SH SYNOPSIS
.B pvmove
[\-d/\-\-debug] [\-h/\-\-help] [\-i/\-\-interval Seconds] [\-v/\-\-verbose]
[\-n/\-\-name LogicalVolume] SourcePhysicalVolume
[DestinationPhysicalVolume[:PE[-PE]...]...]
.SH DESCRIPTION
.B pvmove
allows you to move the allocated physical extents (PEs) on
.I SourcePhysicalVolume
to one or more other physical volumes (PVs).
You can optionally specify a source
.I LogicalVolume
in which case only extents used by that LV will be moved to
free (or specified) extents on
.IR DestinationPhysicalVolume (s).
If no
.I DestinationPhysicalVolume
is specifed, the normal allocation rules for the volume group are used.
If \fBpvmove\fP gets interrupted for any reason, it will probably be
necessary to run \fBvgcfgrestore\fP to restore the volume group's metadata to
the state it was before the \fBpvmove\fP began.
\fBpvmove\fP locks the volume group and other LVM2 commands can't access
the volume group metadata until \fBpvmove\fP has completed.
.SH OPTIONS
.TP
.I \-i, \-\-interval Seconds
Report progress as a percentage at regular intervals.
.TP
.I \-n, \-\-name " \fILogicalVolume\fR"
Move only the extents belonging to
.I LogicalVolume
from
.I SourcePhysicalVolume
instead of all allocated extents to the destination physical volume(s).
.SH EXAMPLES
To move all logical extents of any logical volumes on
.B /dev/hda4
to free physical extents elsewhere in the volume group, giving verbose
runtime information, use:
.sp
\ pvmove -v /dev/hda4
.SH SEE ALSO
.BR lvm (8)

View File

@@ -14,7 +14,7 @@ vgcfgbackup \- backup volume group descriptor area
.B vgcfgbackup
allows you to backup the metadata
of your volume groups.
If you don't name any volume groups pn the command line, all of them
If you don't name any volume groups on the command line, all of them
will be backed up. This DOESN'T backup user/system data in logical
volume(s)! Backup /etc/lvm regularly too.
.SH OPTIONS

View File

@@ -4,6 +4,7 @@ vgreduce \- reduce a volume group
.SH SYNOPSIS
.B vgreduce
[\-a/\-\-all] [\-A/\-\-autobackup y/n] [\-d/\-\-debug] [\-h/\-?/\-\-help]
[\-\-removemissing]
[\-t/\-\-test]
[\-v/\-\-verbose] VolumeGroupName
[PhysicalVolumePath...]
@@ -15,6 +16,22 @@ See \fBlvm\fP for common options.
.TP
.I \-a, \-\-all
Removes all empty physical volumes if none are given on command line.
.TP
.I \-\-removemissing
Removes all missing physical volumes from the volume group and makes
the volume group consistent again.
It's a good idea to run this option with --test first to find out what it
would remove before running it for real.
Any logical volumes and dependent snapshots that were partly on the
missing disks get removed completely. This includes those parts
that lie on disks that are still present.
If your logical volumes spanned several disks including the ones that are
lost, you might want to try to salvage data first by activating your
logical volumes with --partial as described in \fBlvm (8)\fP.
.SH SEE ALSO
.BR lvm (8),
.BR vgextend (8)

View File

@@ -37,6 +37,7 @@ SOURCES=\
pvchange.c \
pvcreate.c \
pvdisplay.c \
pvmove.c \
pvremove.c \
pvscan.c \
report.c \
@@ -62,14 +63,25 @@ TARGETS=\
.commands \
lvm
LVMLIBS=-llvm
ifeq ("@DEVMAPPER@", "yes")
LVMLIBS += -ldevmapper
endif
include ../make.tmpl
ifeq ("@STATIC_LINK@", "no")
LVMLIBS += -rdynamic
endif
lvm: $(OBJECTS) $(top_srcdir)/lib/liblvm.a
$(CC) -o lvm $(OBJECTS) $(LD_FLAGS) -L$(top_srcdir)/lib \
-L$(DESTDIR)/lib -llvm -ldevmapper $(LIBS) -ldl -rdynamic
-L$(DESTDIR)/lib $(LVMLIBS) $(LIBS)
.commands: commands.h cmdnames.h Makefile
$(CC) -E -P cmdnames.h | egrep -v '(help|version)' > .commands
$(CC) -E -P cmdnames.h 2> /dev/null | \
egrep -v '^ *(|#.*|help|version) *$$' > .commands
install: $(TARGETS)
$(INSTALL) -D -o $(OWNER) -g $(GROUP) -m 555 $(STRIP) lvm \

View File

@@ -262,8 +262,8 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg)
return 0;
}
if (!vg->fid->fmt->ops->
pv_setup(vg->fid->fmt, __UINT64_C(0), 0, 0, 0,
__UINT64_C(0), &vg->fid->metadata_areas, pv, vg)) {
pv_setup(vg->fid->fmt, UINT64_C(0), 0, 0, 0,
UINT64_C(0), &vg->fid->metadata_areas, pv, vg)) {
log_error("Format-specific setup for %s failed",
dev_name(pv->dev));
return 0;

View File

@@ -8,6 +8,7 @@
* Put all long args that don't have a
* corresponding short option first ...
*/
/* *INDENT-OFF* */
arg(version_ARG, '\0', "version", NULL)
arg(quiet_ARG, '\0', "quiet", NULL)
arg(physicalvolumesize_ARG, '\0', "setphysicalvolumesize", size_mb_arg)
@@ -23,6 +24,8 @@ arg(noheadings_ARG, '\0', "noheadings", NULL)
arg(segments_ARG, '\0', "segments", NULL)
arg(units_ARG, '\0', "units", string_arg)
arg(nosuffix_ARG, '\0', "nosuffix", NULL)
arg(removemissing_ARG, '\0', "removemissing", NULL)
arg(abort_ARG, '\0', "abort", NULL)
/* Allow some variations */
arg(resizable_ARG, '\0', "resizable", yes_no_arg)
@@ -35,6 +38,7 @@ arg(available_ARG, 'a', "available", yes_no_arg)
arg(all_ARG, 'a', "all", NULL)
arg(autobackup_ARG, 'A', "autobackup", yes_no_arg)
arg(activevolumegroups_ARG, 'A', "activevolumegroups", NULL)
arg(background_ARG, 'b', "background", NULL)
arg(blockdevice_ARG, 'b', "blockdevice", NULL)
arg(chunksize_ARG, 'c', "chunksize", size_kb_arg)
arg(colon_ARG, 'c', "colon", NULL)
@@ -51,6 +55,7 @@ arg(help_ARG, 'h', "help", NULL)
arg(help2_ARG, '?', "", NULL)
arg(stripesize_ARG, 'I', "stripesize", size_kb_arg)
arg(stripes_ARG, 'i', "stripes", int_arg)
arg(interval_ARG, 'i', "interval", int_arg)
arg(iop_version_ARG, 'i', "iop_version", NULL)
arg(logicalvolume_ARG, 'l', "logicalvolume", int_arg)
arg(maxlogicalvolumes_ARG, 'l', "maxlogicalvolumes", int_arg)
@@ -60,6 +65,7 @@ arg(list_ARG, 'l', "list", NULL)
arg(size_ARG, 'L', "size", size_mb_arg)
arg(logicalextent_ARG, 'L', "logicalextent", int_arg_with_sign)
arg(persistent_ARG, 'M', "persistent", yes_no_arg)
arg(major_ARG, 'j', "major", major_arg)
arg(metadatatype_ARG, 'M', "metadatatype", metadatatype_arg)
arg(minor_ARG, 'm', "minor", minor_arg)
arg(maps_ARG, 'm', "maps", NULL)
@@ -93,3 +99,4 @@ arg(zero_ARG, 'Z', "zero", yes_no_arg)
/* this should always be last */
arg(ARG_COUNT, '-', "", NULL)
/* *INDENT-ON* */

View File

@@ -56,7 +56,7 @@ xx(lvchange,
"\t[-d|--debug]\n"
"\t[-h|--help]\n"
"\t[--ignorelockingfailure]\n"
"\t[-M|--persistent y|n] [--minor minor]\n"
"\t[-M|--persistent y|n] [--major major] [--minor minor]\n"
"\t[-P|--partial] " "\n"
"\t[-p|--permission r|rw]\n"
"\t[-r|--readahead ReadAheadSectors]\n"
@@ -66,7 +66,7 @@ xx(lvchange,
"\tLogicalVolume[Path] [LogicalVolume[Path]...]\n",
autobackup_ARG, available_ARG, contiguous_ARG,
ignorelockingfailure_ARG, minor_ARG, partial_ARG, permission_ARG,
ignorelockingfailure_ARG, major_ARG, minor_ARG, partial_ARG, permission_ARG,
persistent_ARG, readahead_ARG, test_ARG)
xx(lvcreate,
@@ -79,7 +79,7 @@ xx(lvcreate,
"\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
"\t{-l|--extents LogicalExtentsNumber |\n"
"\t -L|--size LogicalVolumeSize[kKmMgGtT]}\n"
"\t[-M|--persistent {y|n}] [--minor minor]\n"
"\t[-M|--persistent {y|n}] [--major major] [--minor minor]\n"
"\t[-n|--name LogicalVolumeName]\n"
"\t[-p|--permission {r|rw}]\n"
"\t[-r|--readahead ReadAheadSectors]\n"
@@ -98,7 +98,7 @@ xx(lvcreate,
"\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
"\t{-l|--extents LogicalExtentsNumber |\n"
"\t -L|--size LogicalVolumeSize[kKmMgGtT]}\n"
"\t[-M|--persistent {y|n}] [--minor minor]\n"
"\t[-M|--persistent {y|n}] [--major major] [--minor minor]\n"
"\t[-n|--name LogicalVolumeName]\n"
"\t[-p|--permission {r|rw}]\n"
"\t[-r|--readahead ReadAheadSectors]\n"
@@ -107,7 +107,7 @@ xx(lvcreate,
"\t[--version]\n"
"\tOriginalLogicalVolume[Path] [PhysicalVolumePath...]\n\n",
autobackup_ARG, chunksize_ARG, contiguous_ARG, extents_ARG, minor_ARG,
autobackup_ARG, chunksize_ARG, contiguous_ARG, extents_ARG, major_ARG, minor_ARG,
name_ARG, permission_ARG, persistent_ARG, readahead_ARG, size_ARG,
snapshot_ARG, stripes_ARG, stripesize_ARG, test_ARG, zero_ARG)
@@ -400,19 +400,25 @@ xx(pvdisplay,
xx(pvmove,
"Move extents from one physical volume to another",
"pvmove "
"[-A|--autobackup {y|n}] "
"[-d|--debug] "
"[-f|--force]"
"[-h|-?|--help]\n\t"
"[-t|--test] "
"[-v|--verbose] "
"[--version]\n\t"
"[{-n|--name} LogicalVolume[:LogicalExtent[-LogicalExtent]...]]\n\t"
"SourcePhysicalVolume[:PhysicalExtent[-PhysicalExtent]...]}\n\t"
"[DestinationPhysicalVolume[:PhysicalExtent[-PhysicalExtent]...]...]\n",
"pvmove " "\n"
"\t[--abort]\n"
"\t[-A|--autobackup {y|n}]\n"
"\t[-b|--background]\n"
"\t[-d|--debug]\n "
"\t[-f|--force]\n"
"\t[-h|-?|--help]\n"
"\t[-i|--interval seconds]\n"
"\t[-t|--test]\n "
"\t[-v|--verbose]\n "
"\t[--version]\n"
"\t[{-n|--name} LogicalVolume\n"
/* "\t[{-n|--name} LogicalVolume[:LogicalExtent[-LogicalExtent]...]]\n" */
"\tSourcePhysicalVolume\n"
/* "\tSourcePhysicalVolume[:PhysicalExtent[-PhysicalExtent]...]}\n" */
"\t[DestinationPhysicalVolume[:PhysicalExtent[-PhysicalExtent]...]...]\n",
autobackup_ARG, force_ARG, name_ARG, test_ARG)
abort_ARG, autobackup_ARG, background_ARG, force_ARG, interval_ARG, name_ARG,
test_ARG)
xx(pvremove,
"Remove LVM label(s) from physical volume(s)",
@@ -536,7 +542,7 @@ xx(vgck,
"\t[-d|--debug]\n"
"\t[-h|--help]\n"
"\t[-v|--verbose]\n"
"\t[--version]" "\n",
"\t[--version]" "\n"
"\t[VolumeGroupName...]\n" )
xx(vgconvert,
@@ -678,13 +684,14 @@ xx(vgreduce,
"\t[-A|--autobackup y|n]\n"
"\t[-d|--debug]\n"
"\t[-h|--help]\n"
"\t[--removemissing]\n"
"\t[-t|--test]\n"
"\t[-v|--verbose]\n"
"\t[--version]" "\n"
"\tVolumeGroupName\n"
"\t[PhysicalVolumePath...]\n",
all_ARG, autobackup_ARG, test_ARG)
all_ARG, autobackup_ARG, removemissing_ARG, test_ARG)
xx(vgremove,
"Remove volume group(s)",

View File

@@ -8,15 +8,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#include <getopt.h>
#include <linux/kdev_t.h>
@@ -29,7 +22,10 @@
*/
enum {
READ_ONLY = 0,
MAJOR_ARG,
MINOR_ARG,
VERBOSE_ARG,
VERSION_ARG,
NUM_SWITCHES
};
@@ -89,6 +85,48 @@ static int _parse_file(struct dm_task *dmt, const char *file)
return r;
}
static void _display_info(struct dm_task *dmt)
{
struct dm_info info;
const char *uuid;
if (!dm_task_get_info(dmt, &info))
return;
if (!info.exists) {
printf("Device does not exist.\n");
return;
}
printf("Name: %s\n", dm_task_get_name(dmt));
printf("State: %s%s\n",
info.suspended ? "SUSPENDED" : "ACTIVE",
info.read_only ? " (READ-ONLY)" : "");
if (!info.live_table && !info.inactive_table)
printf("Tables present: None\n");
else
printf("Tables present: %s%s%s\n",
info.live_table ? "LIVE" : "",
info.live_table && info.inactive_table ? " & " : "",
info.inactive_table ? "INACTIVE" : "");
if (info.open_count != -1)
printf("Open count: %d\n", info.open_count);
printf("Event number: %" PRIu32 "\n", info.event_nr);
printf("Major, minor: %d, %d\n", info.major, info.minor);
if (info.target_count != -1)
printf("Number of targets: %d\n", info.target_count);
if ((uuid = dm_task_get_uuid(dmt)) && *uuid)
printf("UUID: %s\n", uuid);
printf("\n");
}
static int _load(int task, const char *name, const char *file, const char *uuid)
{
int r = 0;
@@ -103,12 +141,15 @@ static int _load(int task, const char *name, const char *file, const char *uuid)
if (uuid && !dm_task_set_uuid(dmt, uuid))
goto out;
if (!_parse_file(dmt, file))
if (file && !_parse_file(dmt, file))
goto out;
if (_switches[READ_ONLY] && !dm_task_set_ro(dmt))
goto out;
if (_switches[MAJOR_ARG] && !dm_task_set_major(dmt, _values[MAJOR_ARG]))
goto out;
if (_switches[MINOR_ARG] && !dm_task_set_minor(dmt, _values[MINOR_ARG]))
goto out;
@@ -117,6 +158,9 @@ static int _load(int task, const char *name, const char *file, const char *uuid)
r = 1;
if (_switches[VERBOSE_ARG])
_display_info(dmt);
out:
dm_task_destroy(dmt);
@@ -125,7 +169,11 @@ static int _load(int task, const char *name, const char *file, const char *uuid)
static int _create(int argc, char **argv)
{
return _load(DM_DEVICE_CREATE, argv[1], argv[2], argv[3]);
if (argc == 1)
return _load(DM_DEVICE_CREATE, argv[1], NULL, NULL);
return _load(DM_DEVICE_CREATE, argv[1], argv[2],
(argc == 3) ? argv[3] : NULL);
}
static int _reload(int argc, char **argv)
@@ -187,7 +235,7 @@ static int _version(int argc, char **argv)
return r;
}
static int _simple(int task, const char *name)
static int _simple(int task, const char *name, int display)
{
int r = 0;
@@ -202,6 +250,9 @@ static int _simple(int task, const char *name)
r = dm_task_run(dmt);
if (r && display && _switches[VERBOSE_ARG])
_display_info(dmt);
out:
dm_task_destroy(dmt);
return r;
@@ -209,27 +260,32 @@ static int _simple(int task, const char *name)
static int _remove_all(int argc, char **argv)
{
return _simple(DM_DEVICE_REMOVE_ALL, "");
return _simple(DM_DEVICE_REMOVE_ALL, "", 0);
}
static int _remove(int argc, char **argv)
{
return _simple(DM_DEVICE_REMOVE, argv[1]);
return _simple(DM_DEVICE_REMOVE, argv[1], 0);
}
static int _suspend(int argc, char **argv)
{
return _simple(DM_DEVICE_SUSPEND, argv[1]);
return _simple(DM_DEVICE_SUSPEND, argv[1], 1);
}
static int _resume(int argc, char **argv)
{
return _simple(DM_DEVICE_RESUME, argv[1]);
return _simple(DM_DEVICE_RESUME, argv[1], 1);
}
static int _clear(int argc, char **argv)
{
return _simple(DM_DEVICE_CLEAR, argv[1], 1);
}
static int _wait(int argc, char **argv)
{
return _simple(DM_DEVICE_WAITEVENT, argv[1]);
return _simple(DM_DEVICE_WAITEVENT, argv[1], 2);
}
static int _status(int argc, char **argv)
@@ -256,12 +312,15 @@ static int _status(int argc, char **argv)
if (!dm_task_run(dmt))
goto out;
if (_switches[VERBOSE_ARG])
_display_info(dmt);
/* Fetch targets and print 'em */
do {
next = dm_get_next_target(dmt, next, &start, &length,
&target_type, &params);
if (target_type) {
printf("%"PRIu64" %"PRIu64" %s %s\n",
printf("%" PRIu64 " %" PRIu64 " %s %s\n",
start, length, target_type, params);
}
} while (next);
@@ -277,11 +336,9 @@ static int _status(int argc, char **argv)
static int _info(int argc, char **argv)
{
int r = 0;
const char *uuid;
/* remove <dev_name> */
struct dm_task *dmt;
struct dm_info info;
if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
return 0;
@@ -292,31 +349,7 @@ static int _info(int argc, char **argv)
if (!dm_task_run(dmt))
goto out;
if (!dm_task_get_info(dmt, &info))
goto out;
if (!info.exists) {
printf("Device does not exist.\n");
r = 1;
goto out;
}
printf("Name: %s\n", argv[1]);
printf("State: %s\n",
info.suspended ? "SUSPENDED" : "ACTIVE");
if (info.open_count != -1)
printf("Open count: %d\n", info.open_count);
printf("Major, minor: %d, %d\n", info.major, info.minor);
if (info.target_count != -1)
printf("Number of targets: %d\n", info.target_count);
if ((uuid = dm_task_get_uuid(dmt)) && *uuid)
printf("UUID: %s\n", uuid);
_display_info(dmt);
r = 1;
out:
@@ -326,7 +359,8 @@ static int _info(int argc, char **argv)
static int _deps(int argc, char **argv)
{
int r = 0, i;
int r = 0;
uint32_t i;
struct dm_deps *deps;
/* remove <dev_name> */
@@ -354,6 +388,9 @@ static int _deps(int argc, char **argv)
goto out;
}
if (_switches[VERBOSE_ARG])
_display_info(dmt);
printf("%d dependencies\t:", deps->count);
for (i = 0; i < deps->count; i++)
@@ -369,29 +406,67 @@ static int _deps(int argc, char **argv)
return r;
}
static int _ls(int argc, char **argv)
{
int r = 0;
struct dm_names *names;
unsigned next = 0;
struct dm_task *dmt;
if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
return 0;
if (!dm_task_run(dmt))
goto out;
if (!(names = dm_task_get_names(dmt)))
goto out;
r = 1;
if (!names->dev) {
printf("No devices found\n");
goto out;
}
do {
names = (void *) names + next;
printf("%s\t(%d, %d)\n", names->name,
(int) MAJOR(names->dev), (int) MINOR(names->dev));
next = names->next;
} while (next);
out:
dm_task_destroy(dmt);
return r;
}
/*
* dispatch table
*/
typedef int (*command_fn) (int argc, char **argv);
struct command {
char *name;
char *help;
const char *name;
const char *help;
int min_args;
int max_args;
command_fn fn;
};
static struct command _commands[] = {
{"create", "<dev_name> <table_file> [<uuid>]", 2, 3, _create},
{"create", "<dev_name> <table_file> [<uuid>]", 1, 3, _create},
{"remove", "<dev_name>", 1, 1, _remove},
{"remove_all", "", 0, 0, _remove_all},
{"suspend", "<dev_name>", 1, 1, _suspend},
{"resume", "<dev_name>", 1, 1, _resume},
{"load", "<dev_name> <table_file>", 2, 2, _reload},
{"clear", "<dev_name>", 1, 1, _clear},
{"reload", "<dev_name> <table_file>", 2, 2, _reload},
{"rename", "<dev_name> <new_name>", 2, 2, _rename},
{"ls", "", 0, 0, _ls},
{"info", "<dev_name>", 1, 1, _info},
{"deps", "<dev_name>", 1, 1, _deps},
{"rename", "<dev_name> <new_name>", 2, 2, _rename},
{"status", "<dev_name>", 1, 1, _status},
{"table", "<dev_name>", 1, 1, _status},
{"wait", "<dev_name>", 1, 1, _wait},
@@ -399,11 +474,13 @@ static struct command _commands[] = {
{NULL, NULL, 0, 0, NULL}
};
static void _usage(FILE * out)
static void _usage(FILE *out)
{
int i;
fprintf(out, "usage:\n");
fprintf(out, "Usage:\n\n");
fprintf(out, "dmsetup [--version] [-v|--verbose [-v|--verbose ...]]\n"
" [-r|--readonly] [-j|--major <major>] [-m|--minor <minor>]\n\n");
for (i = 0; _commands[i].name; i++)
fprintf(out, "\t%s %s\n", _commands[i].name, _commands[i].help);
return;
@@ -422,12 +499,15 @@ static struct command *_find_command(const char *name)
static int _process_switches(int *argc, char ***argv)
{
int index;
int ind;
int c;
static struct option long_options[] = {
{"read-only", 0, NULL, READ_ONLY},
{"readonly", 0, NULL, READ_ONLY},
{"major", 1, NULL, MAJOR_ARG},
{"minor", 1, NULL, MINOR_ARG},
{"verbose", 1, NULL, VERBOSE_ARG},
{"version", 0, NULL, VERSION_ARG},
{"", 0, NULL, 0}
};
@@ -437,16 +517,27 @@ static int _process_switches(int *argc, char ***argv)
memset(&_switches, 0, sizeof(_switches));
memset(&_values, 0, sizeof(_values));
while ((c = getopt_long(*argc, *argv, "m:r",
long_options, &index)) != -1) {
if (c == 'r' || index == READ_ONLY)
while ((c = getopt_long(*argc, *argv, "j:m:rv",
long_options, &ind)) != -1) {
if (c == 'r' || ind == READ_ONLY)
_switches[READ_ONLY]++;
if (c == 'm' || index == MINOR_ARG) {
if (c == 'j' || ind == MAJOR_ARG) {
_switches[MAJOR_ARG]++;
_values[MAJOR_ARG] = atoi(optarg);
}
if (c == 'm' || ind == MINOR_ARG) {
_switches[MINOR_ARG]++;
_values[MINOR_ARG] = atoi(optarg);
}
if (c == 'v' || ind == VERBOSE_ARG)
_switches[VERBOSE_ARG]++;
if ((ind == VERSION_ARG))
_switches[VERSION_ARG]++;
}
if (_switches[VERBOSE_ARG] > 1)
dm_log_init_verbose(_switches[VERBOSE_ARG] - 1);
*argv += optind;
*argc -= optind;
return 1;
@@ -461,6 +552,11 @@ int main(int argc, char **argv)
exit(1);
}
if (_switches[VERSION_ARG]) {
c = _find_command("version");
goto doit;
}
if (argc == 0) {
_usage(stderr);
exit(1);
@@ -478,10 +574,14 @@ int main(int argc, char **argv)
exit(1);
}
doit:
if (!c->fn(argc, argv)) {
fprintf(stderr, "Command failed\n");
exit(1);
}
dm_lib_release();
dm_lib_exit();
return 0;
}

View File

@@ -55,7 +55,7 @@ static int lvchange_permission(struct cmd_context *cmd,
}
log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
if (!(lv->vg)) {
if (!vg_write(lv->vg)) {
/* FIXME: Attempt reversion? */
unlock_lv(cmd, lv->lvid.s);
return 0;
@@ -76,19 +76,21 @@ static int lvchange_availability(struct cmd_context *cmd,
struct logical_volume *lv)
{
int activate = 0;
struct physical_volume *pv;
if (strcmp(arg_str_value(cmd, available_ARG, "n"), "n"))
activate = 1;
if (arg_count(cmd, minor_ARG)) {
lv->minor = arg_int_value(cmd, minor_ARG, -1);
}
if (activate) {
/* FIXME Tighter locking if lv_is_origin() */
log_verbose("Activating logical volume \"%s\"", lv->name);
if (!lock_vol(cmd, lv->lvid.s, LCK_LV_ACTIVATE))
return 0;
if ((lv->status & LOCKED) && (pv = get_pvmove_pv_from_lv(lv))) {
log_verbose("Spawning background pvmove process for %s",
dev_name(pv->dev));
pvmove_poll(cmd, dev_name(pv->dev), 1);
}
} else {
log_verbose("Deactivating logical volume \"%s\"", lv->name);
if (!lock_vol(cmd, lv->lvid.s, LCK_LV_DEACTIVATE))
@@ -218,12 +220,18 @@ static int lvchange_persistent(struct cmd_context *cmd,
}
lv->status &= ~FIXED_MINOR;
lv->minor = -1;
log_verbose("Disabling persistent minor for \"%s\"", lv->name);
lv->major = -1;
log_verbose("Disabling persistent device number for \"%s\"",
lv->name);
} else {
if (!arg_count(cmd, minor_ARG)) {
if (!arg_count(cmd, minor_ARG) && lv->minor < 0) {
log_error("Minor number must be specified with -My");
return 0;
}
if (!arg_count(cmd, major_ARG) && lv->major < 0) {
log_error("Major number must be specified with -My");
return 0;
}
log_verbose("Ensuring %s is inactive. Reactivate with -ay.",
lv->name);
if (!lock_vol(cmd, lv->lvid.s, LCK_LV_DEACTIVATE)) {
@@ -231,9 +239,10 @@ static int lvchange_persistent(struct cmd_context *cmd,
return 0;
}
lv->status |= FIXED_MINOR;
lv->minor = arg_int_value(cmd, minor_ARG, -1);
log_verbose("Setting persistent minor number to %d for \"%s\"",
lv->minor, lv->name);
lv->minor = arg_int_value(cmd, minor_ARG, lv->minor);
lv->major = arg_int_value(cmd, major_ARG, lv->major);
log_verbose("Setting persistent device number to (%d, %d) "
"for \"%s\"", lv->major, lv->minor, lv->name);
}
if (!lock_vol(cmd, lv->lvid.s, LCK_LV_SUSPEND | LCK_HOLD)) {
@@ -286,6 +295,13 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
return ECMD_FAILED;
}
if (lv->status & PVMOVE) {
log_error("Unable to change pvmove LV %s", lv->name);
if (arg_count(cmd, available_ARG))
log_error("Use 'pvmove --abort' to abandon a pvmove");
return ECMD_FAILED;
}
/* access permission change */
if (arg_count(cmd, permission_ARG)) {
if (!archive(lv->vg))
@@ -333,8 +349,10 @@ int lvchange(struct cmd_context *cmd, int argc, char **argv)
{
if (!arg_count(cmd, available_ARG) && !arg_count(cmd, contiguous_ARG)
&& !arg_count(cmd, permission_ARG) && !arg_count(cmd, readahead_ARG)
&& !arg_count(cmd, minor_ARG) && !arg_count(cmd, persistent_ARG)) {
log_error("One or more of -a, -C, -m, -M, -p or -r required");
&& !arg_count(cmd, minor_ARG) && !arg_count(cmd, major_ARG)
&& !arg_count(cmd, persistent_ARG)) {
log_error("One or more of -a, -C, -j, -m, -M, -p or -r "
"required");
return EINVALID_CMD_LINE;
}
@@ -350,6 +368,12 @@ int lvchange(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
if ((arg_count(cmd, minor_ARG) || arg_count(cmd, major_ARG)) &&
!arg_count(cmd, persistent_ARG)) {
log_error("--major and --minor require -My");
return EINVALID_CMD_LINE;
}
if (arg_count(cmd, minor_ARG) && argc != 1) {
log_error("Only give one logical volume when specifying minor");
return EINVALID_CMD_LINE;

View File

@@ -14,6 +14,7 @@ struct lvcreate_params {
int snapshot;
int zero;
int contiguous;
int major;
int minor;
char *origin;
@@ -106,14 +107,22 @@ static int _read_name_params(struct lvcreate_params *lp,
}
}
if (lp->lv_name && (ptr = strrchr(lp->lv_name, '/')))
lp->lv_name = ptr + 1;
if (lp->lv_name) {
if ((ptr = strrchr(lp->lv_name, '/')))
lp->lv_name = ptr + 1;
/* FIXME Remove this restriction eventually */
if (lp->lv_name && !strncmp(lp->lv_name, "snapshot", 8)) {
log_error("Names starting \"snapshot\" are reserved. "
"Please choose a different LV name.");
return 0;
/* FIXME Remove this restriction eventually */
if (!strncmp(lp->lv_name, "snapshot", 8)) {
log_error("Names starting \"snapshot\" are reserved. "
"Please choose a different LV name.");
return 0;
}
if (!validate_name(lp->lv_name)) {
log_error("Logical volume name \"%s\" has invalid "
"characters", lp->lv_name);
return 0;
}
}
return 1;
@@ -144,7 +153,7 @@ static int _read_size_params(struct lvcreate_params *lp,
/* Size returned in kilobyte units; held in sectors */
if (arg_count(cmd, size_ARG))
lp->size = arg_uint64_value(cmd, size_ARG, __UINT64_C(0)) * 2;
lp->size = arg_uint64_value(cmd, size_ARG, UINT64_C(0)) * 2;
return 1;
}
@@ -252,6 +261,7 @@ static int _read_params(struct lvcreate_params *lp, struct cmd_context *cmd,
lp->permission = LVM_READ | LVM_WRITE;
lp->minor = arg_int_value(cmd, minor_ARG, -1);
lp->major = arg_int_value(cmd, major_ARG, -1);
/* Persistent minor */
if (arg_count(cmd, persistent_ARG)) {
@@ -261,9 +271,15 @@ static int _read_params(struct lvcreate_params *lp, struct cmd_context *cmd,
"--minor when using -My");
return 0;
}
if (lp->major == -1) {
log_error("Please specify major number with "
"--major when using -My");
return 0;
}
} else {
if (lp->minor != -1) {
log_error("--minor not possible with -Mn");
if ((lp->minor != -1) || (lp->major != -1)) {
log_error("--major and --minor incompatible "
"with -Mn");
return 0;
}
}
@@ -311,7 +327,7 @@ static int _zero_lv(struct cmd_context *cmd, struct logical_volume *lv)
if (!(dev_open(dev, O_WRONLY)))
return 0;
dev_zero(dev, __UINT64_C(0), (size_t) 4096);
dev_zero(dev, UINT64_C(0), (size_t) 4096);
dev_close(dev);
return 1;
@@ -413,6 +429,11 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
"yet.");
return 0;
}
if (org->status & LOCKED) {
log_error("Snapshots of locked devices are not "
"supported yet");
return 0;
}
}
if (!(lv = lv_create(vg->fid, lp->lv_name, status, alloc,
@@ -426,9 +447,11 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
}
if (lp->minor >= 0) {
lv->major = lp->major;
lv->minor = lp->minor;
lv->status |= FIXED_MINOR;
log_verbose("Setting minor number to %d", lv->minor);
log_verbose("Setting device number to (%d, %d)", lv->major,
lv->minor);
}
if (!archive(vg))

View File

@@ -10,19 +10,31 @@
#include "stub.h"
#include <getopt.h>
#include <signal.h>
#include <syslog.h>
#include <libgen.h>
#include <sys/stat.h>
#include <time.h>
#ifdef READLINE_SUPPORT
#include <readline/readline.h>
#include <readline/history.h>
#ifndef HAVE_RL_COMPLETION_MATCHES
#define rl_completion_matches(a, b) completion_matches((char *)a, b)
#ifdef HAVE_GETOPTLONG
# include <getopt.h>
# define GETOPTLONG_FN(a, b, c, d, e) getopt_long((a), (b), (c), (d), (e))
# define OPTIND_INIT 0
#else
struct option {
};
extern int optind;
extern char *optarg;
# define GETOPTLONG_FN(a, b, c, d, e) getopt((a), (b), (c))
# define OPTIND_INIT 1
#endif
#ifdef READLINE_SUPPORT
# include <readline/readline.h>
# include <readline/history.h>
# ifndef HAVE_RL_COMPLETION_MATCHES
# define rl_completion_matches(a, b) completion_matches((char *)a, b)
# endif
#endif
/*
@@ -30,7 +42,7 @@
*/
struct arg the_args[ARG_COUNT + 1] = {
#define arg(a, b, c, d) {b, "--" c, d, 0, NULL, 0, 0, __INT64_C(0), __UINT64_C(0), 0, NULL},
#define arg(a, b, c, d) {b, "--" c, d, 0, NULL, 0, 0, INT64_C(0), UINT64_C(0), 0, NULL},
#include "args.h"
#undef arg
@@ -213,6 +225,23 @@ int minor_arg(struct cmd_context *cmd, struct arg *a)
return 1;
}
int major_arg(struct cmd_context *cmd, struct arg *a)
{
char *ptr;
if (!_get_int_arg(a, &ptr) || (*ptr) || (a->sign == SIGN_MINUS))
return 0;
if (a->i_value > 255) {
log_error("Major number outside range 0-255");
return 0;
}
/* FIXME Also Check against /proc/devices */
return 1;
}
int string_arg(struct cmd_context *cmd, struct arg *a)
{
return 1;
@@ -378,7 +407,7 @@ static void _add_getopt_arg(int arg, char **ptr, struct option **o)
if (a->fn)
*(*ptr)++ = ':';
}
#ifdef HAVE_GETOPTLONG
if (*(a->long_arg + 2)) {
(*o)->name = a->long_arg + 2;
(*o)->has_arg = a->fn ? 1 : 0;
@@ -389,6 +418,7 @@ static void _add_getopt_arg(int arg, char **ptr, struct option **o)
(*o)->val = arg;
(*o)++;
}
#endif
}
static struct arg *_find_arg(struct command *com, int opt)
@@ -441,8 +471,8 @@ static int _process_command_line(struct cmd_context *cmd, int *argc,
/* initialise getopt_long & scan for command line switches */
optarg = 0;
optind = 0;
while ((opt = getopt_long(*argc, *argv, str, opts, NULL)) >= 0) {
optind = OPTIND_INIT;
while ((opt = GETOPTLONG_FN(*argc, *argv, str, opts, NULL)) >= 0) {
if (opt == '?')
return 0;
@@ -1138,6 +1168,7 @@ int main(int argc, char **argv)
if (!(cmd = _init()))
return -1;
cmd->argv = argv;
namebase = strdup(argv[0]);
base = basename(namebase);
while (*base == '/')

View File

@@ -67,7 +67,7 @@ static int _check_device(struct cmd_context *cmd, struct device *dev)
if (!dev_open(dev, 0)) {
return 0;
}
if (dev_read(dev, __UINT64_C(0), (size_t) 1, &buffer) != 1) {
if (dev_read(dev, UINT64_C(0), (size_t) 1, &buffer) != 1) {
dev_close(dev);
return 0;
}

View File

@@ -24,7 +24,7 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
void *handle)
{
struct volume_group *vg;
struct dm_info info;
struct lvinfo info;
vg = lv->vg;
@@ -39,6 +39,13 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
return ECMD_FAILED;
}
if (lv->status & LOCKED) {
log_error("Can't remove locked LV %s", lv->name);
return ECMD_FAILED;
}
/* FIXME Ensure not referred to by another existing LVs */
if (lv_info(lv, &info)) {
if (info.open_count) {
log_error("Can't remove open logical volume \"%s\"",

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