mirror of
				git://sourceware.org/git/lvm2.git
				synced 2025-11-03 08:23:48 +03:00 
			
		
		
		
	Compare commits
	
		
			87 Commits
		
	
	
		
			old-beta6_
			...
			beta8_2
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					4049c1e480 | ||
| 
						 | 
					8449314da2 | ||
| 
						 | 
					63ad057028 | ||
| 
						 | 
					e720464330 | ||
| 
						 | 
					24036afef9 | ||
| 
						 | 
					c78fa1a1bc | ||
| 
						 | 
					faa8b9022c | ||
| 
						 | 
					729bafef7a | ||
| 
						 | 
					590b028632 | ||
| 
						 | 
					8150d00f36 | ||
| 
						 | 
					060065926f | ||
| 
						 | 
					70babe8a28 | ||
| 
						 | 
					c36e09664f | ||
| 
						 | 
					a9672246f3 | ||
| 
						 | 
					ff571884e9 | ||
| 
						 | 
					475138bceb | ||
| 
						 | 
					4a8af199c2 | ||
| 
						 | 
					bdabf5db72 | ||
| 
						 | 
					6a5f21b34e | ||
| 
						 | 
					d608be103c | ||
| 
						 | 
					374bb5d18a | ||
| 
						 | 
					031d6c25ff | ||
| 
						 | 
					223fb7b075 | ||
| 
						 | 
					a746741971 | ||
| 
						 | 
					120faf2a58 | ||
| 
						 | 
					990bca0dc6 | ||
| 
						 | 
					3406472db7 | ||
| 
						 | 
					1bd733c9f6 | ||
| 
						 | 
					238c7f982e | ||
| 
						 | 
					fcb81147cb | ||
| 
						 | 
					1915b73783 | ||
| 
						 | 
					ee79e621fb | ||
| 
						 | 
					d203275a3b | ||
| 
						 | 
					9e8a996222 | ||
| 
						 | 
					0126b0b3ed | ||
| 
						 | 
					458928612c | ||
| 
						 | 
					e33f88e28d | ||
| 
						 | 
					be570bbf9e | ||
| 
						 | 
					f59b4be110 | ||
| 
						 | 
					37336e41be | ||
| 
						 | 
					d24a1a3f0a | ||
| 
						 | 
					f7258955bd | ||
| 
						 | 
					2a1eae5d6f | ||
| 
						 | 
					50ee0a4adb | ||
| 
						 | 
					955a26584e | ||
| 
						 | 
					1d3e407c8f | ||
| 
						 | 
					cb809c4596 | ||
| 
						 | 
					53bbe2888e | ||
| 
						 | 
					7246f476a5 | ||
| 
						 | 
					0785d1c390 | ||
| 
						 | 
					85d2c49d14 | ||
| 
						 | 
					8b77d62b7f | ||
| 
						 | 
					373058a32a | ||
| 
						 | 
					e6293c2c8c | ||
| 
						 | 
					eff181c959 | ||
| 
						 | 
					54752c2305 | ||
| 
						 | 
					b4753c044f | ||
| 
						 | 
					26493424ae | ||
| 
						 | 
					0282fd1332 | ||
| 
						 | 
					b9a019a08b | ||
| 
						 | 
					66f6a0e687 | ||
| 
						 | 
					2dd1b9f97d | ||
| 
						 | 
					89615f3045 | ||
| 
						 | 
					7e46192f67 | ||
| 
						 | 
					e78d985cdf | ||
| 
						 | 
					e8c4bf56fe | ||
| 
						 | 
					e6aa7d323d | ||
| 
						 | 
					fca8e25929 | ||
| 
						 | 
					8e8ac286b4 | ||
| 
						 | 
					7d9770b9a2 | ||
| 
						 | 
					1996230460 | ||
| 
						 | 
					de7897a864 | ||
| 
						 | 
					e2884dcdb7 | ||
| 
						 | 
					544a53a42b | ||
| 
						 | 
					2e4787bfc8 | ||
| 
						 | 
					1829eeb171 | ||
| 
						 | 
					c7488e3c4a | ||
| 
						 | 
					3bf9606383 | ||
| 
						 | 
					4f43f18f0a | ||
| 
						 | 
					5b7f197397 | ||
| 
						 | 
					018141c97f | ||
| 
						 | 
					4d7813e57c | ||
| 
						 | 
					605c60208f | ||
| 
						 | 
					884fafcc30 | ||
| 
						 | 
					56baa90320 | ||
| 
						 | 
					6bb20ee09e | ||
| 
						 | 
					541356430c | 
							
								
								
									
										17
									
								
								WHATS_NEW
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								WHATS_NEW
									
									
									
									
									
								
							@@ -1,4 +1,13 @@
 | 
			
		||||
Mondy 18th November 2002
 | 
			
		||||
Wednesday 30th April 2003
 | 
			
		||||
=========================
 | 
			
		||||
A pvmove implementation is now available for the new metadata format.
 | 
			
		||||
 | 
			
		||||
When running a command that allocates space (e.g. lvcreate), you can now
 | 
			
		||||
restrict not only which disk(s) may be used but also the Physical Extents 
 | 
			
		||||
on those disks.  e.g. lvcreate -L 10 vg1 /dev/hda6:1000-2000:3000-4000
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Monday 18th November 2002
 | 
			
		||||
========================
 | 
			
		||||
 | 
			
		||||
The new format of LVM metadata is ready for you to test!
 | 
			
		||||
@@ -15,7 +24,7 @@ While testing, we recommend turning logging on in the configuration file
 | 
			
		||||
to provide us with diagnostic information:
 | 
			
		||||
  log {
 | 
			
		||||
        file="/tmp/lvm2.log"
 | 
			
		||||
	level=6
 | 
			
		||||
	level=7
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
You should schedule regular backups of your configuration file and
 | 
			
		||||
@@ -65,7 +74,7 @@ changes.
 | 
			
		||||
What's not finished?
 | 
			
		||||
====================
 | 
			
		||||
The internal cache.  If you turn on debugging output you'll see lots of
 | 
			
		||||
repeated disk reads, many of which will eventually get optimised out.
 | 
			
		||||
repeated messages, many of which will eventually get optimised out.
 | 
			
		||||
 | 
			
		||||
--test sometimes causes a command to fail (e.g. vgconvert --test) even 
 | 
			
		||||
though the real command would work: again, fixing this is waiting for 
 | 
			
		||||
@@ -78,9 +87,7 @@ finds something unexpected.  This applies particularly to tools that
 | 
			
		||||
work on more than one volume group at once (e.g. vgsplit).
 | 
			
		||||
 | 
			
		||||
Display output.  Some metadata information cannot yet be displayed.
 | 
			
		||||
Work has started on new display tools.
 | 
			
		||||
 | 
			
		||||
Recovery tools to salvage "lost" metadata directly from the disks:
 | 
			
		||||
but we hope the new format will mean such tools are hardly ever needed!
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										777
									
								
								autoconf/config.guess
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										777
									
								
								autoconf/config.guess
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										373
									
								
								autoconf/config.sub
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										373
									
								
								autoconf/config.sub
									
									
									
									
										vendored
									
									
								
							@@ -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:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										269
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										269
									
								
								configure
									
									
									
									
										vendored
									
									
								
							@@ -1595,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
 | 
			
		||||
@@ -1629,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"
 | 
			
		||||
@@ -1657,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"
 | 
			
		||||
@@ -1677,19 +1780,23 @@ else
 | 
			
		||||
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:1687: 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 1693 "configure"
 | 
			
		||||
#line 1800 "configure"
 | 
			
		||||
#include "confdefs.h"
 | 
			
		||||
#include <sgtty.h>
 | 
			
		||||
Autoconf TIOCGETP
 | 
			
		||||
@@ -1707,7 +1814,7 @@ rm -f conftest*
 | 
			
		||||
 | 
			
		||||
  if test $ac_cv_prog_gcc_traditional = no; then
 | 
			
		||||
    cat > conftest.$ac_ext <<EOF
 | 
			
		||||
#line 1711 "configure"
 | 
			
		||||
#line 1818 "configure"
 | 
			
		||||
#include "confdefs.h"
 | 
			
		||||
#include <termio.h>
 | 
			
		||||
Autoconf TCGETA
 | 
			
		||||
@@ -1729,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:1733: 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 1738 "configure"
 | 
			
		||||
#line 1845 "configure"
 | 
			
		||||
#include "confdefs.h"
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
@@ -1751,7 +1858,7 @@ int main() {
 | 
			
		||||
int i;
 | 
			
		||||
; return 0; }
 | 
			
		||||
EOF
 | 
			
		||||
if { (eval echo configure:1755: \"$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
 | 
			
		||||
@@ -1770,12 +1877,12 @@ EOF
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
echo $ac_n "checking for vprintf""... $ac_c" 1>&6
 | 
			
		||||
echo "configure:1774: 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 1779 "configure"
 | 
			
		||||
#line 1886 "configure"
 | 
			
		||||
#include "confdefs.h"
 | 
			
		||||
/* System header to define __stub macros and hopefully few prototypes,
 | 
			
		||||
    which can conflict with char vprintf(); below.  */
 | 
			
		||||
@@ -1798,7 +1905,7 @@ vprintf();
 | 
			
		||||
 | 
			
		||||
; return 0; }
 | 
			
		||||
EOF
 | 
			
		||||
if { (eval echo configure:1802: \"$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
 | 
			
		||||
@@ -1822,12 +1929,12 @@ fi
 | 
			
		||||
 | 
			
		||||
if test "$ac_cv_func_vprintf" != yes; then
 | 
			
		||||
echo $ac_n "checking for _doprnt""... $ac_c" 1>&6
 | 
			
		||||
echo "configure:1826: 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 1831 "configure"
 | 
			
		||||
#line 1938 "configure"
 | 
			
		||||
#include "confdefs.h"
 | 
			
		||||
/* System header to define __stub macros and hopefully few prototypes,
 | 
			
		||||
    which can conflict with char _doprnt(); below.  */
 | 
			
		||||
@@ -1850,7 +1957,7 @@ _doprnt();
 | 
			
		||||
 | 
			
		||||
; return 0; }
 | 
			
		||||
EOF
 | 
			
		||||
if { (eval echo configure:1854: \"$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
 | 
			
		||||
@@ -1877,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:1881: 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 1886 "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.  */
 | 
			
		||||
@@ -1905,7 +2012,7 @@ $ac_func();
 | 
			
		||||
 | 
			
		||||
; return 0; }
 | 
			
		||||
EOF
 | 
			
		||||
if { (eval echo configure:1909: \"$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
 | 
			
		||||
@@ -1933,14 +2040,14 @@ done
 | 
			
		||||
if test x$READLINE = xyes; then
 | 
			
		||||
	
 | 
			
		||||
echo $ac_n "checking for library containing tgetent""... $ac_c" 1>&6
 | 
			
		||||
echo "configure:1937: 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 1944 "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
 | 
			
		||||
@@ -1951,7 +2058,7 @@ int main() {
 | 
			
		||||
tgetent()
 | 
			
		||||
; return 0; }
 | 
			
		||||
EOF
 | 
			
		||||
if { (eval echo configure:1955: \"$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
 | 
			
		||||
@@ -1962,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 1966 "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
 | 
			
		||||
@@ -1973,7 +2080,7 @@ int main() {
 | 
			
		||||
tgetent()
 | 
			
		||||
; return 0; }
 | 
			
		||||
EOF
 | 
			
		||||
if { (eval echo configure:1977: \"$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
 | 
			
		||||
@@ -2005,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:2011: 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
 | 
			
		||||
@@ -2015,7 +2210,7 @@ else
 | 
			
		||||
  ac_save_LIBS="$LIBS"
 | 
			
		||||
LIBS="-lreadline  $LIBS"
 | 
			
		||||
cat > conftest.$ac_ext <<EOF
 | 
			
		||||
#line 2019 "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
 | 
			
		||||
@@ -2026,7 +2221,7 @@ int main() {
 | 
			
		||||
readline()
 | 
			
		||||
; return 0; }
 | 
			
		||||
EOF
 | 
			
		||||
if { (eval echo configure:2030: \"$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
 | 
			
		||||
@@ -2063,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:2067: 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 2072 "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.  */
 | 
			
		||||
@@ -2091,7 +2286,7 @@ rl_completion_matches();
 | 
			
		||||
 | 
			
		||||
; return 0; }
 | 
			
		||||
EOF
 | 
			
		||||
if { (eval echo configure:2095: \"$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
 | 
			
		||||
@@ -2105,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
 | 
			
		||||
@@ -2298,16 +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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										39
									
								
								configure.in
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								configure.in
									
									
									
									
									
								
							@@ -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,6 +97,10 @@ 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)
 | 
			
		||||
@@ -93,6 +109,10 @@ 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="";
 | 
			
		||||
@@ -121,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, ,
 | 
			
		||||
@@ -134,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
 | 
			
		||||
@@ -146,15 +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
									
									
								
							
							
						
						
									
										10
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							@@ -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
									
									
								
							
							
						
						
									
										8
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							@@ -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
									
									
								
							
							
						
						
									
										1
									
								
								debian/rules
									
									
									
									
										vendored
									
									
								
							@@ -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
									
									
								
							
							
						
						
									
										13
									
								
								debian/undocumented
									
									
									
									
										vendored
									
									
								
							@@ -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
 | 
			
		||||
@@ -104,6 +104,10 @@ log {
 | 
			
		||||
    #   indent = 0
 | 
			
		||||
    #   command_names = 1
 | 
			
		||||
    #   prefix = " -- "
 | 
			
		||||
 | 
			
		||||
    # Set this if you want log messages during activation.
 | 
			
		||||
    # Don't use this in low memory situations (can deadlock).
 | 
			
		||||
    # activation = 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Configuration of metadata backups and archiving.  In LVM2 when we
 | 
			
		||||
@@ -193,6 +197,26 @@ global {
 | 
			
		||||
    #   library_dir = "/lib"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
activation {
 | 
			
		||||
    # Device used in place of missing stripes if activating incomplete volume.
 | 
			
		||||
    # For now, you need to set this up yourself first (e.g. with 'dmsetup')
 | 
			
		||||
    # For example, you could make it return I/O errors using the 'error' 
 | 
			
		||||
    # target or make it return zeros.
 | 
			
		||||
    missing_stripe_filler = "/dev/ioerror"
 | 
			
		||||
 | 
			
		||||
    # Size (in KB) of each copy operation when mirroring
 | 
			
		||||
    mirror_region_size = 512
 | 
			
		||||
 | 
			
		||||
    # How much stack (in KB) to reserve for use while devices suspended
 | 
			
		||||
    reserved_stack = 256
 | 
			
		||||
 | 
			
		||||
    # How much memory (in KB) to reserve for use while devices suspended
 | 
			
		||||
    reserved_memory = 8192
 | 
			
		||||
 | 
			
		||||
    # Nice value used while devices suspended
 | 
			
		||||
    process_priority = -18
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
####################
 | 
			
		||||
# Advanced section #
 | 
			
		||||
@@ -220,7 +244,8 @@ global {
 | 
			
		||||
    # preferably on different (non-LV) filesystems, and with no other 
 | 
			
		||||
    # on-disk metadata (pvmetadatacopies = 0). Or this can be in
 | 
			
		||||
    # addition to on-disk metadata areas.
 | 
			
		||||
    # The feature was originally added to simplify testing.
 | 
			
		||||
    # The feature was originally added to simplify testing and is not
 | 
			
		||||
    # supported under low memory situations - the machine could lock up.
 | 
			
		||||
    #
 | 
			
		||||
    # Never edit any files in these directories by hand unless you
 | 
			
		||||
    # you are absolutely sure you know what you are doing! Use
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
../lib/activate/activate.h
 | 
			
		||||
../lib/cache/cache.h
 | 
			
		||||
../lib/cache/lvmcache.h
 | 
			
		||||
../lib/commands/errors.h
 | 
			
		||||
../lib/commands/toolcontext.h
 | 
			
		||||
../lib/config/config.h
 | 
			
		||||
@@ -24,6 +24,7 @@
 | 
			
		||||
../lib/log/log.h
 | 
			
		||||
../lib/metadata/metadata.h
 | 
			
		||||
../lib/mm/dbg_malloc.h
 | 
			
		||||
../lib/mm/memlock.h
 | 
			
		||||
../lib/mm/pool.h
 | 
			
		||||
../lib/mm/xlate.h
 | 
			
		||||
../lib/misc/crc.h
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ endif
 | 
			
		||||
 | 
			
		||||
SOURCES=\
 | 
			
		||||
	activate/activate.c \
 | 
			
		||||
	cache/cache.c \
 | 
			
		||||
	cache/lvmcache.c \
 | 
			
		||||
	commands/toolcontext.c \
 | 
			
		||||
	config/config.c \
 | 
			
		||||
	datastruct/bitset.c \
 | 
			
		||||
@@ -36,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 \
 | 
			
		||||
@@ -44,12 +43,13 @@ SOURCES=\
 | 
			
		||||
	metadata/lv_manip.c \
 | 
			
		||||
	metadata/merge.c \
 | 
			
		||||
	metadata/metadata.c \
 | 
			
		||||
	metadata/mirror.c \
 | 
			
		||||
	metadata/pv_map.c \
 | 
			
		||||
	metadata/snapshot_manip.c \
 | 
			
		||||
	misc/crc.c \
 | 
			
		||||
	misc/lvm-file.c \
 | 
			
		||||
	misc/lvm-string.c \
 | 
			
		||||
	misc/sharedlib.c \
 | 
			
		||||
	mm/memlock.c \
 | 
			
		||||
	mm/pool.c \
 | 
			
		||||
	regex/matcher.c \
 | 
			
		||||
	regex/parse_rx.c \
 | 
			
		||||
@@ -79,6 +79,12 @@ ifeq ("@DEVMAPPER@", "yes")
 | 
			
		||||
	activate/fs.c
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@HAVE_LIBDL@", "yes")
 | 
			
		||||
  SOURCES+=\
 | 
			
		||||
	locking/external_locking.c \
 | 
			
		||||
	misc/sharedlib.c
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
TARGETS=liblvm.a
 | 
			
		||||
 | 
			
		||||
include ../make.tmpl
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@
 | 
			
		||||
#include "lib.h"
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
#include "activate.h"
 | 
			
		||||
#include "memlock.h"
 | 
			
		||||
#include "display.h"
 | 
			
		||||
#include "fs.h"
 | 
			
		||||
#include "lvm-string.h"
 | 
			
		||||
@@ -15,8 +16,8 @@
 | 
			
		||||
#include "dev_manager.h"
 | 
			
		||||
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <linux/kdev_t.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#define _skip(fmt, args...) log_very_verbose("Skipping: " fmt , ## args)
 | 
			
		||||
 | 
			
		||||
@@ -47,6 +48,11 @@ int lv_snapshot_percent(struct logical_volume *lv, float *percent)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
 | 
			
		||||
		      uint32_t *event_nr)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int lvs_in_vg_activated(struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
@@ -71,6 +77,10 @@ int lv_activate(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
{
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
void activation_exit(void)
 | 
			
		||||
{
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else				/* DEVMAPPER_SUPPORT */
 | 
			
		||||
 | 
			
		||||
@@ -145,7 +155,7 @@ int lv_info(const struct logical_volume *lv, struct lvinfo *info)
 | 
			
		||||
	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;
 | 
			
		||||
	}
 | 
			
		||||
@@ -175,7 +185,7 @@ int lv_snapshot_percent(struct logical_volume *lv, float *percent)
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->name))) {
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -188,6 +198,29 @@ 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 lvinfo info;
 | 
			
		||||
@@ -218,7 +251,7 @@ static int _lv_activate(struct logical_volume *lv)
 | 
			
		||||
	int r;
 | 
			
		||||
	struct dev_manager *dm;
 | 
			
		||||
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->name))) {
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -235,7 +268,7 @@ static int _lv_deactivate(struct logical_volume *lv)
 | 
			
		||||
	int r;
 | 
			
		||||
	struct dev_manager *dm;
 | 
			
		||||
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->name))) {
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -252,7 +285,7 @@ static int _lv_suspend(struct logical_volume *lv)
 | 
			
		||||
	int r;
 | 
			
		||||
	struct dev_manager *dm;
 | 
			
		||||
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->name))) {
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -314,12 +347,9 @@ int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
	if (!(lv = lv_from_lvid(cmd, lvid_s)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (test_mode()) {
 | 
			
		||||
		_skip("Suspending '%s'.", lv->name);
 | 
			
		||||
		return 0;
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!lv_info(lv, &info)) {
 | 
			
		||||
@@ -327,8 +357,15 @@ int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (info.exists && !info.suspended)
 | 
			
		||||
		return _lv_suspend(lv);
 | 
			
		||||
	if (!info.exists || info.suspended)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	memlock_inc();
 | 
			
		||||
	if (!_lv_suspend(lv)) {
 | 
			
		||||
		memlock_dec();
 | 
			
		||||
		fs_unlock();
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
@@ -346,7 +383,7 @@ int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
 | 
			
		||||
	if (test_mode()) {
 | 
			
		||||
		_skip("Resuming '%s'.", lv->name);
 | 
			
		||||
		return 0;
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!lv_info(lv, &info)) {
 | 
			
		||||
@@ -354,8 +391,14 @@ int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (info.exists && info.suspended)
 | 
			
		||||
		return _lv_activate(lv);
 | 
			
		||||
	if (!info.exists || !info.suspended)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (!_lv_activate(lv))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	memlock_dec();
 | 
			
		||||
	fs_unlock();
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
@@ -364,6 +407,7 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
{
 | 
			
		||||
	struct logical_volume *lv;
 | 
			
		||||
	struct lvinfo info;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		return 1;
 | 
			
		||||
@@ -373,7 +417,7 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
 | 
			
		||||
	if (test_mode()) {
 | 
			
		||||
		_skip("Deactivating '%s'.", lv->name);
 | 
			
		||||
		return 0;
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!lv_info(lv, &info)) {
 | 
			
		||||
@@ -381,16 +425,22 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (info.exists)
 | 
			
		||||
		return _lv_deactivate(lv);
 | 
			
		||||
	if (!info.exists)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
	memlock_inc();
 | 
			
		||||
	r = _lv_deactivate(lv);
 | 
			
		||||
	memlock_dec();
 | 
			
		||||
	fs_unlock();
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
{
 | 
			
		||||
	struct logical_volume *lv;
 | 
			
		||||
	struct lvinfo info;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		return 1;
 | 
			
		||||
@@ -400,7 +450,7 @@ int lv_activate(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
 | 
			
		||||
	if (test_mode()) {
 | 
			
		||||
		_skip("Activating '%s'.", lv->name);
 | 
			
		||||
		return 0;
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!lv_info(lv, &info)) {
 | 
			
		||||
@@ -408,10 +458,19 @@ int lv_activate(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!info.exists || info.suspended)
 | 
			
		||||
		return _lv_activate(lv);
 | 
			
		||||
	if (info.exists && !info.suspended)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
	memlock_inc();
 | 
			
		||||
	r = _lv_activate(lv);
 | 
			
		||||
	memlock_dec();
 | 
			
		||||
	fs_unlock();
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void activation_exit(void)
 | 
			
		||||
{
 | 
			
		||||
	dev_manager_exit();
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
 | 
			
		||||
#ifdef DEVMAPPER_SUPPORT
 | 
			
		||||
#include <libdevmapper.h>
 | 
			
		||||
#  include <libdevmapper.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct lvinfo {
 | 
			
		||||
@@ -28,6 +28,13 @@ int activation(void);
 | 
			
		||||
int driver_version(char *version, size_t size);
 | 
			
		||||
int library_version(char *version, size_t size);
 | 
			
		||||
 | 
			
		||||
void activation_exit(void);
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns 1 if info structure has been populated, else 0.
 | 
			
		||||
 */
 | 
			
		||||
@@ -36,20 +43,8 @@ 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);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
 | 
			
		||||
		      uint32_t *event_nr);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return number of LVs in the VG that are active.
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -8,16 +8,18 @@
 | 
			
		||||
#define _LVM_DEV_MANAGER_H
 | 
			
		||||
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
 | 
			
		||||
#include <libdevmapper.h>
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
struct dev_manager;
 | 
			
		||||
struct dm_info;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Constructor and destructor.
 | 
			
		||||
 */
 | 
			
		||||
struct dev_manager *dev_manager_create(const char *vg_name);
 | 
			
		||||
struct dev_manager *dev_manager_create(const char *vg_name,
 | 
			
		||||
				       struct config_tree *cf);
 | 
			
		||||
void dev_manager_destroy(struct dev_manager *dm);
 | 
			
		||||
void dev_manager_exit(void);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The device handler is responsible for creating all the layered
 | 
			
		||||
@@ -29,6 +31,9 @@ int dev_manager_info(struct dev_manager *dm, const struct logical_volume *lv,
 | 
			
		||||
		     struct dm_info *info);
 | 
			
		||||
int dev_manager_snapshot_percent(struct dev_manager *dm,
 | 
			
		||||
				 struct logical_volume *lv, float *percent);
 | 
			
		||||
int dev_manager_mirror_percent(struct dev_manager *dm,
 | 
			
		||||
			       struct logical_volume *lv, int wait,
 | 
			
		||||
			       float *percent, uint32_t *event_nr);
 | 
			
		||||
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv);
 | 
			
		||||
int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv);
 | 
			
		||||
int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv);
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,7 @@
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
#include "lvm-string.h"
 | 
			
		||||
#include "lvm-file.h"
 | 
			
		||||
#include "memlock.h"
 | 
			
		||||
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
@@ -17,12 +18,12 @@
 | 
			
		||||
#include <dirent.h>
 | 
			
		||||
#include <libdevmapper.h>
 | 
			
		||||
 | 
			
		||||
static int _mk_dir(struct volume_group *vg)
 | 
			
		||||
static int _mk_dir(const char *dev_dir, const char *vg_name)
 | 
			
		||||
{
 | 
			
		||||
	char vg_path[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s",
 | 
			
		||||
			 vg->cmd->dev_dir, vg->name) == -1) {
 | 
			
		||||
			 dev_dir, vg_name) == -1) {
 | 
			
		||||
		log_error("Couldn't construct name of volume "
 | 
			
		||||
			  "group directory.");
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -40,12 +41,12 @@ static int _mk_dir(struct volume_group *vg)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _rm_dir(struct volume_group *vg)
 | 
			
		||||
static int _rm_dir(const char *dev_dir, const char *vg_name)
 | 
			
		||||
{
 | 
			
		||||
	char vg_path[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s",
 | 
			
		||||
			 vg->cmd->dev_dir, vg->name) == -1) {
 | 
			
		||||
			 dev_dir, vg_name) == -1) {
 | 
			
		||||
		log_error("Couldn't construct name of volume "
 | 
			
		||||
			  "group directory.");
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -93,37 +94,38 @@ static void _rm_blks(const char *dir)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _mk_link(struct logical_volume *lv, const char *dev)
 | 
			
		||||
static int _mk_link(const char *dev_dir, const char *vg_name,
 | 
			
		||||
		    const char *lv_name, const char *dev)
 | 
			
		||||
{
 | 
			
		||||
	char lv_path[PATH_MAX], link_path[PATH_MAX], lvm1_group_path[PATH_MAX];
 | 
			
		||||
	char vg_path[PATH_MAX];
 | 
			
		||||
	struct stat buf;
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s",
 | 
			
		||||
			 lv->vg->cmd->dev_dir, lv->vg->name) == -1) {
 | 
			
		||||
			 dev_dir, vg_name) == -1) {
 | 
			
		||||
		log_error("Couldn't create path for volume group dir %s",
 | 
			
		||||
			  lv->vg->name);
 | 
			
		||||
			  vg_name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(lv_path, sizeof(lv_path), "%s/%s", vg_path,
 | 
			
		||||
			 lv->name) == -1) {
 | 
			
		||||
			 lv_name) == -1) {
 | 
			
		||||
		log_error("Couldn't create source pathname for "
 | 
			
		||||
			  "logical volume link %s", lv->name);
 | 
			
		||||
			  "logical volume link %s", lv_name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(link_path, sizeof(link_path), "%s/%s",
 | 
			
		||||
			 dm_dir(), dev) == -1) {
 | 
			
		||||
		log_error("Couldn't create destination pathname for "
 | 
			
		||||
			  "logical volume link for %s", lv->name);
 | 
			
		||||
			  "logical volume link for %s", lv_name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(lvm1_group_path, sizeof(lvm1_group_path), "%s/group",
 | 
			
		||||
			 vg_path) == -1) {
 | 
			
		||||
		log_error("Couldn't create pathname for LVM1 group file for %s",
 | 
			
		||||
			  lv->vg->name);
 | 
			
		||||
			  vg_name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -167,13 +169,14 @@ static int _mk_link(struct logical_volume *lv, const char *dev)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _rm_link(struct logical_volume *lv, const char *lv_name)
 | 
			
		||||
static int _rm_link(const char *dev_dir, const char *vg_name,
 | 
			
		||||
		    const char *lv_name)
 | 
			
		||||
{
 | 
			
		||||
	struct stat buf;
 | 
			
		||||
	char lv_path[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(lv_path, sizeof(lv_path), "%s%s/%s",
 | 
			
		||||
			 lv->vg->cmd->dev_dir, lv->vg->name, lv_name) == -1) {
 | 
			
		||||
			 dev_dir, vg_name, lv_name) == -1) {
 | 
			
		||||
		log_error("Couldn't determine link pathname.");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -192,35 +195,143 @@ static int _rm_link(struct logical_volume *lv, const char *lv_name)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fs_add_lv(struct logical_volume *lv, const char *dev)
 | 
			
		||||
typedef enum {
 | 
			
		||||
	FS_ADD,
 | 
			
		||||
	FS_DEL,
 | 
			
		||||
	FS_RENAME
 | 
			
		||||
} fs_op_t;
 | 
			
		||||
 | 
			
		||||
static int _do_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
 | 
			
		||||
		     const char *lv_name, const char *dev,
 | 
			
		||||
		     const char *old_lv_name)
 | 
			
		||||
{
 | 
			
		||||
	if (!_mk_dir(lv->vg) || !_mk_link(lv, dev)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	switch (type) {
 | 
			
		||||
	case FS_ADD:
 | 
			
		||||
		if (!_mk_dir(dev_dir, vg_name) ||
 | 
			
		||||
		    !_mk_link(dev_dir, vg_name, lv_name, dev)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case FS_DEL:
 | 
			
		||||
		if (!_rm_link(dev_dir, vg_name, lv_name) ||
 | 
			
		||||
		    !_rm_dir(dev_dir, vg_name)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
		/* FIXME Use rename() */
 | 
			
		||||
	case FS_RENAME:
 | 
			
		||||
		if (old_lv_name && !_rm_link(dev_dir, vg_name, old_lv_name))
 | 
			
		||||
			stack;
 | 
			
		||||
 | 
			
		||||
		if (!_mk_link(dev_dir, vg_name, lv_name, dev))
 | 
			
		||||
			stack;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static LIST_INIT(_fs_ops);
 | 
			
		||||
 | 
			
		||||
struct fs_op_parms {
 | 
			
		||||
	struct list list;
 | 
			
		||||
	fs_op_t type;
 | 
			
		||||
	char *dev_dir;
 | 
			
		||||
	char *vg_name;
 | 
			
		||||
	char *lv_name;
 | 
			
		||||
	char *dev;
 | 
			
		||||
	char *old_lv_name;
 | 
			
		||||
	char names[0];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void _store_str(char **pos, char **ptr, const char *str)
 | 
			
		||||
{
 | 
			
		||||
	strcpy(*pos, str);
 | 
			
		||||
	*ptr = *pos;
 | 
			
		||||
	*pos += strlen(*ptr) + 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _stack_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
 | 
			
		||||
			const char *lv_name, const char *dev,
 | 
			
		||||
			const char *old_lv_name)
 | 
			
		||||
{
 | 
			
		||||
	struct fs_op_parms *fsp;
 | 
			
		||||
	size_t len = strlen(dev_dir) + strlen(vg_name) + strlen(lv_name) +
 | 
			
		||||
	    strlen(dev) + strlen(old_lv_name) + 5;
 | 
			
		||||
	char *pos;
 | 
			
		||||
 | 
			
		||||
	if (!(fsp = dbg_malloc(sizeof(*fsp) + len))) {
 | 
			
		||||
		log_error("No space to stack fs operation");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pos = fsp->names;
 | 
			
		||||
	fsp->type = type;
 | 
			
		||||
 | 
			
		||||
	_store_str(&pos, &fsp->dev_dir, dev_dir);
 | 
			
		||||
	_store_str(&pos, &fsp->vg_name, vg_name);
 | 
			
		||||
	_store_str(&pos, &fsp->lv_name, lv_name);
 | 
			
		||||
	_store_str(&pos, &fsp->dev, dev);
 | 
			
		||||
	_store_str(&pos, &fsp->old_lv_name, old_lv_name);
 | 
			
		||||
 | 
			
		||||
	list_add(&_fs_ops, &fsp->list);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _pop_fs_ops(void)
 | 
			
		||||
{
 | 
			
		||||
	struct list *fsph, *fspht;
 | 
			
		||||
	struct fs_op_parms *fsp;
 | 
			
		||||
 | 
			
		||||
	list_iterate_safe(fsph, fspht, &_fs_ops) {
 | 
			
		||||
		fsp = list_item(fsph, struct fs_op_parms);
 | 
			
		||||
		_do_fs_op(fsp->type, fsp->dev_dir, fsp->vg_name, fsp->lv_name,
 | 
			
		||||
			  fsp->dev, fsp->old_lv_name);
 | 
			
		||||
		list_del(&fsp->list);
 | 
			
		||||
		dbg_free(fsp);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
 | 
			
		||||
		  const char *lv_name, const char *dev, const char *old_lv_name)
 | 
			
		||||
{
 | 
			
		||||
	if (memlock()) {
 | 
			
		||||
		if (!_stack_fs_op(type, dev_dir, vg_name, lv_name, dev,
 | 
			
		||||
				  old_lv_name)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return _do_fs_op(type, dev_dir, vg_name, lv_name, dev, old_lv_name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fs_add_lv(struct logical_volume *lv, const char *dev)
 | 
			
		||||
{
 | 
			
		||||
	return _fs_op(FS_ADD, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
 | 
			
		||||
		      dev, "");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fs_del_lv(struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
	if (!_rm_link(lv, lv->name) || !_rm_dir(lv->vg)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
	return _fs_op(FS_DEL, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
 | 
			
		||||
		      "", "");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* FIXME Use rename() */
 | 
			
		||||
int fs_rename_lv(struct logical_volume *lv,
 | 
			
		||||
		 const char *dev, const char *old_name)
 | 
			
		||||
{
 | 
			
		||||
	if (old_name && !_rm_link(lv, old_name))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	if (!_mk_link(lv, dev))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
	return _fs_op(FS_RENAME, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
 | 
			
		||||
		      dev, old_name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fs_unlock(void)
 | 
			
		||||
{
 | 
			
		||||
	if (!memlock()) {
 | 
			
		||||
		dm_lib_release();
 | 
			
		||||
		_pop_fs_ops();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -18,5 +18,6 @@ int fs_add_lv(struct logical_volume *lv, const char *dev);
 | 
			
		||||
int fs_del_lv(struct logical_volume *lv);
 | 
			
		||||
int fs_rename_lv(struct logical_volume *lv,
 | 
			
		||||
		 const char *dev, const char *old_name);
 | 
			
		||||
void fs_unlock(void);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										176
									
								
								lib/cache/cache.c → lib/cache/lvmcache.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										176
									
								
								lib/cache/cache.c → lib/cache/lvmcache.c
									
									
									
									
										vendored
									
									
								
							@@ -6,22 +6,23 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "lib.h"
 | 
			
		||||
#include "cache.h"
 | 
			
		||||
#include "lvmcache.h"
 | 
			
		||||
#include "hash.h"
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
#include "dev-cache.h"
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
#include "filter.h"
 | 
			
		||||
 | 
			
		||||
#include <linux/kdev_t.h>
 | 
			
		||||
#include "memlock.h"
 | 
			
		||||
 | 
			
		||||
static struct hash_table *_pvid_hash = NULL;
 | 
			
		||||
static struct hash_table *_vgid_hash = NULL;
 | 
			
		||||
static struct hash_table *_vgname_hash = NULL;
 | 
			
		||||
static struct hash_table *_lock_hash = NULL;
 | 
			
		||||
static struct list _vginfos;
 | 
			
		||||
int _has_scanned = 0;
 | 
			
		||||
static int _has_scanned = 0;
 | 
			
		||||
static int _vgs_locked = 0;
 | 
			
		||||
 | 
			
		||||
int cache_init(void)
 | 
			
		||||
int lvmcache_init(void)
 | 
			
		||||
{
 | 
			
		||||
	list_init(&_vginfos);
 | 
			
		||||
 | 
			
		||||
@@ -34,12 +35,52 @@ int cache_init(void)
 | 
			
		||||
	if (!(_pvid_hash = hash_create(128)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!(_lock_hash = hash_create(128)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct cache_vginfo *vginfo_from_vgname(const char *vgname)
 | 
			
		||||
void lvmcache_lock_vgname(const char *vgname, int read_only)
 | 
			
		||||
{
 | 
			
		||||
	struct cache_vginfo *vginfo;
 | 
			
		||||
	if (!_lock_hash && !lvmcache_init()) {
 | 
			
		||||
		log_error("Internal cache initialisation failed");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!hash_insert(_lock_hash, vgname, (void *) 1))
 | 
			
		||||
		log_error("Cache locking failure for %s", vgname);
 | 
			
		||||
 | 
			
		||||
	_vgs_locked++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _vgname_is_locked(const char *vgname) __attribute__ ((unused));
 | 
			
		||||
static int _vgname_is_locked(const char *vgname)
 | 
			
		||||
{
 | 
			
		||||
	if (!_lock_hash)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	return hash_lookup(_lock_hash, vgname) ? 1 : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void lvmcache_unlock_vgname(const char *vgname)
 | 
			
		||||
{
 | 
			
		||||
	/* FIXME: Clear all CACHE_LOCKED flags in this vg */
 | 
			
		||||
	hash_remove(_lock_hash, vgname);
 | 
			
		||||
 | 
			
		||||
	/* FIXME Do this per-VG */
 | 
			
		||||
	if (!--_vgs_locked)
 | 
			
		||||
		dev_close_all();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int vgs_locked(void)
 | 
			
		||||
{
 | 
			
		||||
	return _vgs_locked;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
 | 
			
		||||
	if (!_vgname_hash)
 | 
			
		||||
		return NULL;
 | 
			
		||||
@@ -52,7 +93,7 @@ struct cache_vginfo *vginfo_from_vgname(const char *vgname)
 | 
			
		||||
 | 
			
		||||
const struct format_type *fmt_from_vgname(const char *vgname)
 | 
			
		||||
{
 | 
			
		||||
	struct cache_vginfo *vginfo;
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
 | 
			
		||||
	if (!(vginfo = vginfo_from_vgname(vgname)))
 | 
			
		||||
		return NULL;
 | 
			
		||||
@@ -60,33 +101,42 @@ const struct format_type *fmt_from_vgname(const char *vgname)
 | 
			
		||||
	return vginfo->fmt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct cache_vginfo *vginfo_from_vgid(const char *vgid)
 | 
			
		||||
struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid)
 | 
			
		||||
{
 | 
			
		||||
	struct cache_vginfo *vginfo;
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
	char id[ID_LEN + 1];
 | 
			
		||||
 | 
			
		||||
	if (!_vgid_hash || !vgid)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	if (!(vginfo = hash_lookup_fixed(_vgid_hash, vgid, ID_LEN)))
 | 
			
		||||
	/* vgid not necessarily NULL-terminated */
 | 
			
		||||
	strncpy(&id[0], vgid, ID_LEN);
 | 
			
		||||
	id[ID_LEN] = '\0';
 | 
			
		||||
 | 
			
		||||
	if (!(vginfo = hash_lookup(_vgid_hash, id)))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	return vginfo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct cache_info *info_from_pvid(const char *pvid)
 | 
			
		||||
struct lvmcache_info *info_from_pvid(const char *pvid)
 | 
			
		||||
{
 | 
			
		||||
	struct cache_info *info;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
	char id[ID_LEN + 1];
 | 
			
		||||
 | 
			
		||||
	if (!_pvid_hash || !pvid)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	if (!(info = hash_lookup_fixed(_pvid_hash, pvid, ID_LEN)))
 | 
			
		||||
	strncpy(&id[0], pvid, ID_LEN);
 | 
			
		||||
	id[ID_LEN] = '\0';
 | 
			
		||||
 | 
			
		||||
	if (!(info = hash_lookup(_pvid_hash, id)))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	return info;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _rescan_entry(struct cache_info *info)
 | 
			
		||||
static void _rescan_entry(struct lvmcache_info *info)
 | 
			
		||||
{
 | 
			
		||||
	struct label *label;
 | 
			
		||||
 | 
			
		||||
@@ -101,7 +151,7 @@ static int _scan_invalid(void)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int cache_label_scan(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
{
 | 
			
		||||
	struct label *label;
 | 
			
		||||
	struct dev_iter *iter;
 | 
			
		||||
@@ -118,7 +168,7 @@ int cache_label_scan(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
 | 
			
		||||
	_scanning_in_progress = 1;
 | 
			
		||||
 | 
			
		||||
	if (!_vgname_hash && !cache_init()) {
 | 
			
		||||
	if (!_vgname_hash && !lvmcache_init()) {
 | 
			
		||||
		log_error("Internal cache initialisation failed");
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
@@ -155,12 +205,12 @@ int cache_label_scan(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct list *cache_get_vgnames(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
{
 | 
			
		||||
	struct list *vgih, *vgnames;
 | 
			
		||||
	struct str_list *sl;
 | 
			
		||||
 | 
			
		||||
	cache_label_scan(cmd, full_scan);
 | 
			
		||||
	lvmcache_label_scan(cmd, full_scan);
 | 
			
		||||
 | 
			
		||||
	if (!(vgnames = pool_alloc(cmd->mem, sizeof(struct list)))) {
 | 
			
		||||
		log_error("vgnames list allocation failed");
 | 
			
		||||
@@ -176,7 +226,7 @@ struct list *cache_get_vgnames(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
		}
 | 
			
		||||
		if (!(sl->str = pool_strdup(cmd->mem,
 | 
			
		||||
					    list_item(vgih,
 | 
			
		||||
						      struct cache_vginfo)->
 | 
			
		||||
						      struct lvmcache_vginfo)->
 | 
			
		||||
					    vgname))) {
 | 
			
		||||
			log_error("vgname allocation failed");
 | 
			
		||||
			return NULL;
 | 
			
		||||
@@ -190,34 +240,37 @@ struct list *cache_get_vgnames(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
 | 
			
		||||
{
 | 
			
		||||
	struct label *label;
 | 
			
		||||
	struct cache_info *info;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
 | 
			
		||||
	/* Already cached ? */
 | 
			
		||||
	if ((info = info_from_pvid((char *) pvid))) {
 | 
			
		||||
		if (label_read(info->dev, &label)) {
 | 
			
		||||
			info = (struct cache_info *) label->info;
 | 
			
		||||
			info = (struct lvmcache_info *) label->info;
 | 
			
		||||
			if (id_equal(pvid, (struct id *) &info->dev->pvid))
 | 
			
		||||
				return info->dev;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cache_label_scan(cmd, 0);
 | 
			
		||||
	lvmcache_label_scan(cmd, 0);
 | 
			
		||||
 | 
			
		||||
	/* Try again */
 | 
			
		||||
	if ((info = info_from_pvid((char *) pvid))) {
 | 
			
		||||
		if (label_read(info->dev, &label)) {
 | 
			
		||||
			info = (struct cache_info *) label->info;
 | 
			
		||||
			info = (struct lvmcache_info *) label->info;
 | 
			
		||||
			if (id_equal(pvid, (struct id *) &info->dev->pvid))
 | 
			
		||||
				return info->dev;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cache_label_scan(cmd, 1);
 | 
			
		||||
	if (memlock())
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	lvmcache_label_scan(cmd, 1);
 | 
			
		||||
 | 
			
		||||
	/* Try again */
 | 
			
		||||
	if ((info = info_from_pvid((char *) pvid))) {
 | 
			
		||||
		if (label_read(info->dev, &label)) {
 | 
			
		||||
			info = (struct cache_info *) label->info;
 | 
			
		||||
			info = (struct lvmcache_info *) label->info;
 | 
			
		||||
			if (id_equal(pvid, (struct id *) &info->dev->pvid))
 | 
			
		||||
				return info->dev;
 | 
			
		||||
		}
 | 
			
		||||
@@ -226,7 +279,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _drop_vginfo(struct cache_info *info)
 | 
			
		||||
static void _drop_vginfo(struct lvmcache_info *info)
 | 
			
		||||
{
 | 
			
		||||
	if (!list_empty(&info->list)) {
 | 
			
		||||
		list_del(&info->list);
 | 
			
		||||
@@ -247,7 +300,7 @@ static void _drop_vginfo(struct cache_info *info)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Unused
 | 
			
		||||
void cache_del(struct cache_info *info)
 | 
			
		||||
void lvmcache_del(struct lvmcache_info *info)
 | 
			
		||||
{
 | 
			
		||||
	if (info->dev->pvid[0] && _pvid_hash)
 | 
			
		||||
		hash_remove(_pvid_hash, info->dev->pvid);
 | 
			
		||||
@@ -261,7 +314,7 @@ void cache_del(struct cache_info *info)
 | 
			
		||||
	return;
 | 
			
		||||
} */
 | 
			
		||||
 | 
			
		||||
static int _cache_update_pvid(struct cache_info *info, const char *pvid)
 | 
			
		||||
static int _lvmcache_update_pvid(struct lvmcache_info *info, const char *pvid)
 | 
			
		||||
{
 | 
			
		||||
	if (!strcmp(info->dev->pvid, pvid))
 | 
			
		||||
		return 1;
 | 
			
		||||
@@ -270,14 +323,14 @@ static int _cache_update_pvid(struct cache_info *info, const char *pvid)
 | 
			
		||||
	}
 | 
			
		||||
	strncpy(info->dev->pvid, pvid, sizeof(info->dev->pvid));
 | 
			
		||||
	if (!hash_insert(_pvid_hash, pvid, info)) {
 | 
			
		||||
		log_error("_cache_update: pvid insertion failed: %s", pvid);
 | 
			
		||||
		log_error("_lvmcache_update: pvid insertion failed: %s", pvid);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _cache_update_vgid(struct cache_info *info, const char *vgid)
 | 
			
		||||
static int _lvmcache_update_vgid(struct lvmcache_info *info, const char *vgid)
 | 
			
		||||
{
 | 
			
		||||
	if (!vgid || !info->vginfo || !strncmp(info->vginfo->vgid, vgid,
 | 
			
		||||
					       sizeof(info->vginfo->vgid)))
 | 
			
		||||
@@ -290,18 +343,18 @@ static int _cache_update_vgid(struct cache_info *info, const char *vgid)
 | 
			
		||||
 | 
			
		||||
	strncpy(info->vginfo->vgid, vgid, sizeof(info->vginfo->vgid));
 | 
			
		||||
	info->vginfo->vgid[sizeof(info->vginfo->vgid) - 1] = '\0';
 | 
			
		||||
	if (!hash_insert(_vgid_hash, vgid, info->vginfo)) {
 | 
			
		||||
		log_error("_cache_update: vgid hash insertion failed: %s",
 | 
			
		||||
			  vgid);
 | 
			
		||||
	if (!hash_insert(_vgid_hash, info->vginfo->vgid, info->vginfo)) {
 | 
			
		||||
		log_error("_lvmcache_update: vgid hash insertion failed: %s",
 | 
			
		||||
			  info->vginfo->vgid);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int cache_update_vgname(struct cache_info *info, const char *vgname)
 | 
			
		||||
int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
 | 
			
		||||
{
 | 
			
		||||
	struct cache_vginfo *vginfo;
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
 | 
			
		||||
	/* If vgname is NULL and we don't already have a vgname, 
 | 
			
		||||
	 * assume ORPHAN - we want every entry to have a vginfo
 | 
			
		||||
@@ -319,7 +372,7 @@ int cache_update_vgname(struct cache_info *info, const char *vgname)
 | 
			
		||||
	/* Get existing vginfo or create new one */
 | 
			
		||||
	if (!(vginfo = vginfo_from_vgname(vgname))) {
 | 
			
		||||
		if (!(vginfo = dbg_malloc(sizeof(*vginfo)))) {
 | 
			
		||||
			log_error("cache_update_vgname: list alloc failed");
 | 
			
		||||
			log_error("lvmcache_update_vgname: list alloc failed");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		memset(vginfo, 0, sizeof(*vginfo));
 | 
			
		||||
@@ -352,11 +405,11 @@ int cache_update_vgname(struct cache_info *info, const char *vgname)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int cache_update_vg(struct volume_group *vg)
 | 
			
		||||
int lvmcache_update_vg(struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	struct list *pvh;
 | 
			
		||||
	struct physical_volume *pv;
 | 
			
		||||
	struct cache_info *info;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
	char pvid_s[ID_LEN + 1];
 | 
			
		||||
	int vgid_updated = 0;
 | 
			
		||||
 | 
			
		||||
@@ -367,9 +420,9 @@ int cache_update_vg(struct volume_group *vg)
 | 
			
		||||
		strncpy(pvid_s, (char *) &pv->id, sizeof(pvid_s) - 1);
 | 
			
		||||
		/* FIXME Could pv->dev->pvid ever be different? */
 | 
			
		||||
		if ((info = info_from_pvid(pvid_s))) {
 | 
			
		||||
			cache_update_vgname(info, vg->name);
 | 
			
		||||
			lvmcache_update_vgname(info, vg->name);
 | 
			
		||||
			if (!vgid_updated) {
 | 
			
		||||
				_cache_update_vgid(info, (char *) &vg->id);
 | 
			
		||||
				_lvmcache_update_vgid(info, (char *) &vg->id);
 | 
			
		||||
				vgid_updated = 1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
@@ -378,15 +431,15 @@ int cache_update_vg(struct volume_group *vg)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct cache_info *cache_add(struct labeller *labeller, const char *pvid,
 | 
			
		||||
			     struct device *dev,
 | 
			
		||||
			     const char *vgname, const char *vgid)
 | 
			
		||||
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
 | 
			
		||||
				   struct device *dev,
 | 
			
		||||
				   const char *vgname, const char *vgid)
 | 
			
		||||
{
 | 
			
		||||
	struct label *label;
 | 
			
		||||
	struct cache_info *existing, *info;
 | 
			
		||||
	struct lvmcache_info *existing, *info;
 | 
			
		||||
	char pvid_s[ID_LEN + 1];
 | 
			
		||||
 | 
			
		||||
	if (!_vgname_hash && !cache_init()) {
 | 
			
		||||
	if (!_vgname_hash && !lvmcache_init()) {
 | 
			
		||||
		log_error("Internal cache initialisation failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
@@ -401,7 +454,7 @@ struct cache_info *cache_add(struct labeller *labeller, const char *pvid,
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		if (!(info = dbg_malloc(sizeof(*info)))) {
 | 
			
		||||
			log_error("cache_info allocation failed");
 | 
			
		||||
			log_error("lvmcache_info allocation failed");
 | 
			
		||||
			label_destroy(label);
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
@@ -449,7 +502,7 @@ struct cache_info *cache_add(struct labeller *labeller, const char *pvid,
 | 
			
		||||
	info->fmt = (const struct format_type *) labeller->private;
 | 
			
		||||
	info->status |= CACHE_INVALID;
 | 
			
		||||
 | 
			
		||||
	if (!_cache_update_pvid(info, pvid_s)) {
 | 
			
		||||
	if (!_lvmcache_update_pvid(info, pvid_s)) {
 | 
			
		||||
		if (!existing) {
 | 
			
		||||
			dbg_free(info);
 | 
			
		||||
			label_destroy(label);
 | 
			
		||||
@@ -457,7 +510,7 @@ struct cache_info *cache_add(struct labeller *labeller, const char *pvid,
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!cache_update_vgname(info, vgname)) {
 | 
			
		||||
	if (!lvmcache_update_vgname(info, vgname)) {
 | 
			
		||||
		if (!existing) {
 | 
			
		||||
			hash_remove(_pvid_hash, pvid_s);
 | 
			
		||||
			strcpy(info->dev->pvid, "");
 | 
			
		||||
@@ -467,14 +520,14 @@ struct cache_info *cache_add(struct labeller *labeller, const char *pvid,
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_cache_update_vgid(info, vgid))
 | 
			
		||||
	if (!_lvmcache_update_vgid(info, vgid))
 | 
			
		||||
		/* Non-critical */
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	return info;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _cache_destroy_entry(struct cache_info *info)
 | 
			
		||||
static void _lvmcache_destroy_entry(struct lvmcache_info *info)
 | 
			
		||||
{
 | 
			
		||||
	if (!list_empty(&info->list))
 | 
			
		||||
		list_del(&info->list);
 | 
			
		||||
@@ -483,14 +536,19 @@ static void _cache_destroy_entry(struct cache_info *info)
 | 
			
		||||
	dbg_free(info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _cache_destroy_vgnamelist(struct cache_vginfo *vginfo)
 | 
			
		||||
static void _lvmcache_destroy_vgnamelist(struct lvmcache_vginfo *vginfo)
 | 
			
		||||
{
 | 
			
		||||
	if (vginfo->vgname)
 | 
			
		||||
		dbg_free(vginfo->vgname);
 | 
			
		||||
	dbg_free(vginfo);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cache_destroy(void)
 | 
			
		||||
static void _lvmcache_destroy_lockname(int present)
 | 
			
		||||
{
 | 
			
		||||
	/* Nothing to do */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void lvmcache_destroy(void)
 | 
			
		||||
{
 | 
			
		||||
	_has_scanned = 0;
 | 
			
		||||
 | 
			
		||||
@@ -500,15 +558,23 @@ void cache_destroy(void)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (_pvid_hash) {
 | 
			
		||||
		hash_iter(_pvid_hash, (iterate_fn) _cache_destroy_entry);
 | 
			
		||||
		hash_iter(_pvid_hash, (iterate_fn) _lvmcache_destroy_entry);
 | 
			
		||||
		hash_destroy(_pvid_hash);
 | 
			
		||||
		_pvid_hash = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (_vgname_hash) {
 | 
			
		||||
		hash_iter(_vgname_hash, (iterate_fn) _cache_destroy_vgnamelist);
 | 
			
		||||
		hash_iter(_vgname_hash,
 | 
			
		||||
			  (iterate_fn) _lvmcache_destroy_vgnamelist);
 | 
			
		||||
		hash_destroy(_vgname_hash);
 | 
			
		||||
		_vgname_hash = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (_lock_hash) {
 | 
			
		||||
		hash_iter(_lock_hash, (iterate_fn) _lvmcache_destroy_lockname);
 | 
			
		||||
		hash_destroy(_lock_hash);
 | 
			
		||||
		_lock_hash = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	list_init(&_vginfos);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										44
									
								
								lib/cache/cache.h → lib/cache/lvmcache.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										44
									
								
								lib/cache/cache.h → lib/cache/lvmcache.h
									
									
									
									
										vendored
									
									
								
							@@ -9,33 +9,31 @@
 | 
			
		||||
#define _LVM_CACHE_H
 | 
			
		||||
 | 
			
		||||
#include "dev-cache.h"
 | 
			
		||||
#include "list.h"
 | 
			
		||||
#include "uuid.h"
 | 
			
		||||
#include "label.h"
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#define ORPHAN ""
 | 
			
		||||
 | 
			
		||||
#define CACHE_INVALID 0x00000001
 | 
			
		||||
#define CACHE_INVALID	0x00000001
 | 
			
		||||
#define CACHE_LOCKED	0x00000002
 | 
			
		||||
 | 
			
		||||
/* LVM specific per-volume info */
 | 
			
		||||
/* Eventual replacement for struct physical_volume perhaps? */
 | 
			
		||||
 | 
			
		||||
struct cache_vginfo {
 | 
			
		||||
struct lvmcache_vginfo {
 | 
			
		||||
	struct list list;	/* Join these vginfos together */
 | 
			
		||||
	struct list infos;	/* List head for cache_infos */
 | 
			
		||||
	struct list infos;	/* List head for lvmcache_infos */
 | 
			
		||||
	char *vgname;		/* "" == orphan */
 | 
			
		||||
	char vgid[ID_LEN + 1];
 | 
			
		||||
	const struct format_type *fmt;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct cache_info {
 | 
			
		||||
struct lvmcache_info {
 | 
			
		||||
	struct list list;	/* Join VG members together */
 | 
			
		||||
	struct list mdas;	/* list head for metadata areas */
 | 
			
		||||
	struct list das;	/* list head for data areas */
 | 
			
		||||
	struct cache_vginfo *vginfo;	/* NULL == unknown */
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;	/* NULL == unknown */
 | 
			
		||||
	struct label *label;
 | 
			
		||||
	const struct format_type *fmt;
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
@@ -43,31 +41,35 @@ struct cache_info {
 | 
			
		||||
	uint32_t status;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int cache_init(void);
 | 
			
		||||
void cache_destroy(void);
 | 
			
		||||
int lvmcache_init(void);
 | 
			
		||||
void lvmcache_destroy(void);
 | 
			
		||||
 | 
			
		||||
/* Set full_scan to 1 to reread every filtered device label */
 | 
			
		||||
int cache_label_scan(struct cmd_context *cmd, int full_scan);
 | 
			
		||||
int lvmcache_label_scan(struct cmd_context *cmd, int full_scan);
 | 
			
		||||
 | 
			
		||||
/* Add/delete a device */
 | 
			
		||||
struct cache_info *cache_add(struct labeller *labeller, const char *pvid,
 | 
			
		||||
			     struct device *dev,
 | 
			
		||||
			     const char *vgname, const char *vgid);
 | 
			
		||||
void cache_del(struct cache_info *info);
 | 
			
		||||
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
 | 
			
		||||
				   struct device *dev,
 | 
			
		||||
				   const char *vgname, const char *vgid);
 | 
			
		||||
void lvmcache_del(struct lvmcache_info *info);
 | 
			
		||||
 | 
			
		||||
/* Update things */
 | 
			
		||||
int cache_update_vgname(struct cache_info *info, const char *vgname);
 | 
			
		||||
int cache_update_vg(struct volume_group *vg);
 | 
			
		||||
int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname);
 | 
			
		||||
int lvmcache_update_vg(struct volume_group *vg);
 | 
			
		||||
 | 
			
		||||
void lvmcache_lock_vgname(const char *vgname, int read_only);
 | 
			
		||||
void lvmcache_unlock_vgname(const char *vgname);
 | 
			
		||||
 | 
			
		||||
/* Queries */
 | 
			
		||||
const struct format_type *fmt_from_vgname(const char *vgname);
 | 
			
		||||
struct cache_vginfo *vginfo_from_vgname(const char *vgname);
 | 
			
		||||
struct cache_vginfo *vginfo_from_vgid(const char *vgid);
 | 
			
		||||
struct cache_info *info_from_pvid(const char *pvid);
 | 
			
		||||
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname);
 | 
			
		||||
struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid);
 | 
			
		||||
struct lvmcache_info *info_from_pvid(const char *pvid);
 | 
			
		||||
struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid);
 | 
			
		||||
int vgs_locked(void);
 | 
			
		||||
 | 
			
		||||
/* Returns list of struct str_lists containing pool-allocated copy of vgnames */
 | 
			
		||||
/* Set full_scan to 1 to reread every filtered device label */
 | 
			
		||||
struct list *cache_get_vgnames(struct cmd_context *cmd, int full_scan);
 | 
			
		||||
struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -19,8 +19,12 @@
 | 
			
		||||
#include "label.h"
 | 
			
		||||
#include "lvm-file.h"
 | 
			
		||||
#include "format-text.h"
 | 
			
		||||
#include "sharedlib.h"
 | 
			
		||||
#include "display.h"
 | 
			
		||||
#include "memlock.h"
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_LIBDL
 | 
			
		||||
#include "sharedlib.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef LVM1_INTERNAL
 | 
			
		||||
#include "format1.h"
 | 
			
		||||
@@ -29,9 +33,12 @@
 | 
			
		||||
#include <locale.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <syslog.h>
 | 
			
		||||
#include <dlfcn.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
 | 
			
		||||
#ifdef linux
 | 
			
		||||
#  include <malloc.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static FILE *_log;
 | 
			
		||||
 | 
			
		||||
static int _get_env_vars(struct cmd_context *cmd)
 | 
			
		||||
@@ -53,7 +60,7 @@ static int _get_env_vars(struct cmd_context *cmd)
 | 
			
		||||
 | 
			
		||||
static void _init_logging(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	const char *open_mode = "a";
 | 
			
		||||
	int append = 1;
 | 
			
		||||
	time_t t;
 | 
			
		||||
 | 
			
		||||
	const char *log_file;
 | 
			
		||||
@@ -98,16 +105,18 @@ static void _init_logging(struct cmd_context *cmd)
 | 
			
		||||
	/* Settings for logging to file */
 | 
			
		||||
	if (find_config_int(cmd->cf->root, "log/overwrite", '/',
 | 
			
		||||
			    DEFAULT_OVERWRITE))
 | 
			
		||||
		open_mode = "w";
 | 
			
		||||
		append = 0;
 | 
			
		||||
 | 
			
		||||
	log_file = find_config_str(cmd->cf->root, "log/file", '/', 0);
 | 
			
		||||
	if (log_file) {
 | 
			
		||||
		/* set up the logging */
 | 
			
		||||
		if (!(_log = fopen(log_file, open_mode)))
 | 
			
		||||
			log_error("Couldn't open log file %s", log_file);
 | 
			
		||||
		else
 | 
			
		||||
			init_log(_log);
 | 
			
		||||
	}
 | 
			
		||||
	if (log_file)
 | 
			
		||||
		init_log_file(log_file, append);
 | 
			
		||||
 | 
			
		||||
	log_file = find_config_str(cmd->cf->root, "log/activate_file", '/', 0);
 | 
			
		||||
	if (log_file)
 | 
			
		||||
		init_log_direct(log_file, append);
 | 
			
		||||
 | 
			
		||||
	init_log_while_suspended(find_config_int(cmd->cf->root,
 | 
			
		||||
						 "log/activation", '/', 0));
 | 
			
		||||
 | 
			
		||||
	t = time(NULL);
 | 
			
		||||
	log_verbose("Logging initialised at %s", ctime(&t));
 | 
			
		||||
@@ -138,7 +147,6 @@ 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
 | 
			
		||||
@@ -271,12 +279,12 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
 | 
			
		||||
 | 
			
		||||
	if (!(f1 = regex_filter_create(cn->v))) {
 | 
			
		||||
		log_error("Failed to create regex device filter");
 | 
			
		||||
		return f2;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(f3 = composite_filter_create(2, f1, f2))) {
 | 
			
		||||
		log_error("Failed to create composite device filter");
 | 
			
		||||
		return f2;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return f3;
 | 
			
		||||
@@ -284,7 +292,7 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
 | 
			
		||||
 | 
			
		||||
static int _init_filters(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	const char *lvm_cache;
 | 
			
		||||
	const char *dev_cache;
 | 
			
		||||
	struct dev_filter *f3, *f4;
 | 
			
		||||
	struct stat st;
 | 
			
		||||
	char cache_file[PATH_MAX];
 | 
			
		||||
@@ -301,9 +309,9 @@ static int _init_filters(struct cmd_context *cmd)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	lvm_cache =
 | 
			
		||||
	dev_cache =
 | 
			
		||||
	    find_config_str(cmd->cf->root, "devices/cache", '/', cache_file);
 | 
			
		||||
	if (!(f4 = persistent_filter_create(f3, lvm_cache))) {
 | 
			
		||||
	if (!(f4 = persistent_filter_create(f3, dev_cache))) {
 | 
			
		||||
		log_error("Failed to create persistent device filter");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -315,11 +323,11 @@ static int _init_filters(struct cmd_context *cmd)
 | 
			
		||||
	if (!*cmd->sys_dir)
 | 
			
		||||
		cmd->dump_filter = 0;
 | 
			
		||||
 | 
			
		||||
	if (!stat(lvm_cache, &st) &&
 | 
			
		||||
	if (!stat(dev_cache, &st) &&
 | 
			
		||||
	    (st.st_mtime > config_file_timestamp(cmd->cf)) &&
 | 
			
		||||
	    !persistent_filter_load(f4))
 | 
			
		||||
		log_verbose("Failed to load existing device cache from %s",
 | 
			
		||||
			    lvm_cache);
 | 
			
		||||
			    dev_cache);
 | 
			
		||||
 | 
			
		||||
	cmd->filter = f4;
 | 
			
		||||
 | 
			
		||||
@@ -332,12 +340,10 @@ static int _init_formats(struct cmd_context *cmd)
 | 
			
		||||
 | 
			
		||||
	struct format_type *fmt;
 | 
			
		||||
	struct list *fmth;
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_LIBDL
 | 
			
		||||
	struct config_node *cn;
 | 
			
		||||
	struct config_value *cv;
 | 
			
		||||
 | 
			
		||||
	struct format_type *(*init_format_fn) (struct cmd_context *);
 | 
			
		||||
 | 
			
		||||
	void *lib;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	label_init();
 | 
			
		||||
 | 
			
		||||
@@ -348,9 +354,15 @@ static int _init_formats(struct cmd_context *cmd)
 | 
			
		||||
	list_add(&cmd->formats, &fmt->list);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_LIBDL
 | 
			
		||||
	/* Load any formats in shared libs */
 | 
			
		||||
	if ((cn = find_config_node(cmd->cf->root, "global/format_libraries",
 | 
			
		||||
				   '/'))) {
 | 
			
		||||
 | 
			
		||||
		struct config_value *cv;
 | 
			
		||||
		struct format_type *(*init_format_fn) (struct cmd_context *);
 | 
			
		||||
		void *lib;
 | 
			
		||||
 | 
			
		||||
		for (cv = cn->v; cv; cv = cv->next) {
 | 
			
		||||
			if (cv->type != CFG_STRING) {
 | 
			
		||||
				log_error("Invalid string in config file: "
 | 
			
		||||
@@ -376,6 +388,7 @@ static int _init_formats(struct cmd_context *cmd)
 | 
			
		||||
			list_add(&cmd->formats, &fmt->list);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (!(fmt = create_text_format(cmd)))
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -405,6 +418,10 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
 | 
			
		||||
{
 | 
			
		||||
	struct cmd_context *cmd;
 | 
			
		||||
 | 
			
		||||
#ifdef M_MMAP_MAX
 | 
			
		||||
	mallopt(M_MMAP_MAX, 0);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (!setlocale(LC_ALL, ""))
 | 
			
		||||
		log_error("setlocale failed");
 | 
			
		||||
 | 
			
		||||
@@ -446,6 +463,8 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memlock_init(cmd);
 | 
			
		||||
 | 
			
		||||
	if (!_init_formats(cmd))
 | 
			
		||||
		goto error;
 | 
			
		||||
 | 
			
		||||
@@ -469,8 +488,10 @@ static void _destroy_formats(struct list *formats)
 | 
			
		||||
		list_del(&fmt->list);
 | 
			
		||||
		lib = fmt->library;
 | 
			
		||||
		fmt->ops->destroy(fmt);
 | 
			
		||||
#ifdef HAVE_LIBDL
 | 
			
		||||
		if (lib)
 | 
			
		||||
			dlclose(lib);
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -479,7 +500,8 @@ void destroy_toolcontext(struct cmd_context *cmd)
 | 
			
		||||
	if (cmd->dump_filter)
 | 
			
		||||
		persistent_filter_dump(cmd->filter);
 | 
			
		||||
 | 
			
		||||
	cache_destroy();
 | 
			
		||||
	activation_exit();
 | 
			
		||||
	lvmcache_destroy();
 | 
			
		||||
	label_exit();
 | 
			
		||||
	_destroy_formats(&cmd->formats);
 | 
			
		||||
	cmd->filter->destroy(cmd->filter);
 | 
			
		||||
@@ -488,6 +510,7 @@ void destroy_toolcontext(struct cmd_context *cmd)
 | 
			
		||||
	destroy_config_tree(cmd->cf);
 | 
			
		||||
	dbg_free(cmd);
 | 
			
		||||
 | 
			
		||||
	release_log_memory();
 | 
			
		||||
	dump_memory();
 | 
			
		||||
	fin_log();
 | 
			
		||||
	fin_syslog();
 | 
			
		||||
 
 | 
			
		||||
@@ -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? */
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,6 @@
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include <asm/page.h>
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	TOK_INT,
 | 
			
		||||
@@ -50,7 +49,7 @@ struct cs {
 | 
			
		||||
	char *filename;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void _get_token(struct parser *p);
 | 
			
		||||
static void _get_token(struct parser *p, int tok_prev);
 | 
			
		||||
static void _eat_space(struct parser *p);
 | 
			
		||||
static struct config_node *_file(struct parser *p);
 | 
			
		||||
static struct config_node *_section(struct parser *p);
 | 
			
		||||
@@ -111,14 +110,15 @@ void destroy_config_tree(struct config_tree *cf)
 | 
			
		||||
	pool_destroy(((struct cs *) cf)->mem);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int read_config_fd(struct config_tree *cf, int fd, const char *file,
 | 
			
		||||
int read_config_fd(struct config_tree *cf, struct device *dev,
 | 
			
		||||
		   off_t offset, size_t size, off_t offset2, size_t size2,
 | 
			
		||||
		   checksum_fn_t checksum_fn, uint32_t checksum)
 | 
			
		||||
{
 | 
			
		||||
	struct cs *c = (struct cs *) cf;
 | 
			
		||||
	struct parser *p;
 | 
			
		||||
	off_t mmap_offset = 0;
 | 
			
		||||
	int r = 0;
 | 
			
		||||
	int use_mmap = 1;
 | 
			
		||||
	off_t mmap_offset = 0;
 | 
			
		||||
 | 
			
		||||
	if (!(p = pool_alloc(c->mem, sizeof(*p)))) {
 | 
			
		||||
		stack;
 | 
			
		||||
@@ -126,47 +126,43 @@ int read_config_fd(struct config_tree *cf, int fd, const char *file,
 | 
			
		||||
	}
 | 
			
		||||
	p->mem = c->mem;
 | 
			
		||||
 | 
			
		||||
	if (size2) {
 | 
			
		||||
		/* FIXME Attempt adjacent mmaps MAP_FIXED into malloced space 
 | 
			
		||||
		 * one PAGE_SIZE larger than required...
 | 
			
		||||
		 */
 | 
			
		||||
	/* Only use mmap with regular files */
 | 
			
		||||
	if (!(dev->flags & DEV_REGULAR) || size2)
 | 
			
		||||
		use_mmap = 0;
 | 
			
		||||
 | 
			
		||||
	if (use_mmap) {
 | 
			
		||||
		mmap_offset = offset % getpagesize();
 | 
			
		||||
		/* memory map the file */
 | 
			
		||||
		p->fb = mmap((caddr_t) 0, size + mmap_offset, PROT_READ,
 | 
			
		||||
			     MAP_PRIVATE, dev_fd(dev), offset - mmap_offset);
 | 
			
		||||
		if (p->fb == (caddr_t) (-1)) {
 | 
			
		||||
			log_sys_error("mmap", dev_name(dev));
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		p->fb = p->fb + mmap_offset;
 | 
			
		||||
	} else {
 | 
			
		||||
		if (!(p->fb = dbg_malloc(size + size2))) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		if (lseek(fd, offset, SEEK_SET) < 0) {
 | 
			
		||||
			log_sys_error("lseek", file);
 | 
			
		||||
		if (!dev_read(dev, (uint64_t) offset, size, p->fb)) {
 | 
			
		||||
			log_error("Read from %s failed", dev_name(dev));
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		if (raw_read(fd, p->fb, size) != size) {
 | 
			
		||||
			log_error("Circular read from %s failed", file);
 | 
			
		||||
			goto out;
 | 
			
		||||
		if (size2) {
 | 
			
		||||
			if (!dev_read(dev, (uint64_t) offset2, size2,
 | 
			
		||||
				      p->fb + size)) {
 | 
			
		||||
				log_error("Circular read from %s failed",
 | 
			
		||||
					  dev_name(dev));
 | 
			
		||||
				goto out;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (lseek(fd, offset2, SEEK_SET) < 0) {
 | 
			
		||||
			log_sys_error("lseek", file);
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		if (raw_read(fd, p->fb + size, size2) != size2) {
 | 
			
		||||
			log_error("Circular read from %s failed", file);
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		mmap_offset = offset % PAGE_SIZE;
 | 
			
		||||
		/* memory map the file */
 | 
			
		||||
		p->fb = mmap((caddr_t) 0, size + mmap_offset, PROT_READ,
 | 
			
		||||
			     MAP_PRIVATE, fd, offset - mmap_offset);
 | 
			
		||||
		if (p->fb == (caddr_t) (-1)) {
 | 
			
		||||
			log_sys_error("mmap", file);
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		p->fb = p->fb + mmap_offset;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (checksum_fn && checksum !=
 | 
			
		||||
	    (checksum_fn(checksum_fn(INITIAL_CRC, p->fb, size),
 | 
			
		||||
			 p->fb + size, size2))) {
 | 
			
		||||
		log_error("%s: Checksum error", file);
 | 
			
		||||
		log_error("%s: Checksum error", dev_name(dev));
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -175,7 +171,7 @@ int read_config_fd(struct config_tree *cf, int fd, const char *file,
 | 
			
		||||
	/* parse */
 | 
			
		||||
	p->tb = p->te = p->fb;
 | 
			
		||||
	p->line = 1;
 | 
			
		||||
	_get_token(p);
 | 
			
		||||
	_get_token(p, TOK_SECTION_E);
 | 
			
		||||
	if (!(cf->root = _file(p))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto out;
 | 
			
		||||
@@ -184,12 +180,12 @@ int read_config_fd(struct config_tree *cf, int fd, const char *file,
 | 
			
		||||
	r = 1;
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	if (size2)
 | 
			
		||||
	if (!use_mmap)
 | 
			
		||||
		dbg_free(p->fb);
 | 
			
		||||
	else {
 | 
			
		||||
		/* unmap the file */
 | 
			
		||||
		if (munmap((char *) (p->fb - mmap_offset), size)) {
 | 
			
		||||
			log_sys_error("munmap", file);
 | 
			
		||||
		if (munmap((char *) (p->fb - mmap_offset), size + mmap_offset)) {
 | 
			
		||||
			log_sys_error("munmap", dev_name(dev));
 | 
			
		||||
			r = 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -201,7 +197,8 @@ int read_config_file(struct config_tree *cf, const char *file)
 | 
			
		||||
{
 | 
			
		||||
	struct cs *c = (struct cs *) cf;
 | 
			
		||||
	struct stat info;
 | 
			
		||||
	int r = 1, fd;
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
	int r = 1;
 | 
			
		||||
 | 
			
		||||
	if (stat(file, &info)) {
 | 
			
		||||
		log_sys_error("stat", file);
 | 
			
		||||
@@ -218,15 +215,20 @@ int read_config_file(struct config_tree *cf, const char *file)
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((fd = open(file, O_RDONLY)) < 0) {
 | 
			
		||||
		log_sys_error("open", file);
 | 
			
		||||
	if (!(dev = dev_create_file(file, NULL, NULL))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r = read_config_fd(cf, fd, file, 0, (size_t) info.st_size, 0, 0,
 | 
			
		||||
	if (!dev_open_flags(dev, O_RDONLY, 0, 0)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r = read_config_fd(cf, dev, 0, (size_t) info.st_size, 0, 0,
 | 
			
		||||
			   (checksum_fn_t) NULL, 0);
 | 
			
		||||
 | 
			
		||||
	close(fd);
 | 
			
		||||
	dev_close(dev);
 | 
			
		||||
 | 
			
		||||
	c->timestamp = info.st_mtime;
 | 
			
		||||
	c->filename = pool_strdup(c->mem, file);
 | 
			
		||||
@@ -250,7 +252,8 @@ int reload_config_file(struct config_tree **cf)
 | 
			
		||||
	struct cs *c = (struct cs *) *cf;
 | 
			
		||||
	struct cs *new_cs;
 | 
			
		||||
	struct stat info;
 | 
			
		||||
	int r, fd;
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	if (!c->filename)
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -280,19 +283,25 @@ int reload_config_file(struct config_tree **cf)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((fd = open(c->filename, O_RDONLY)) < 0) {
 | 
			
		||||
		log_sys_error("open", c->filename);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(new_cf = create_config_tree())) {
 | 
			
		||||
		log_error("Allocation of new config_tree failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r = read_config_fd(new_cf, fd, c->filename, 0, (size_t) info.st_size,
 | 
			
		||||
	if (!(dev = dev_create_file(c->filename, NULL, NULL))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dev_open_flags(dev, O_RDONLY, 0, 0)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r = read_config_fd(new_cf, dev, 0, (size_t) info.st_size,
 | 
			
		||||
			   0, 0, (checksum_fn_t) NULL, 0);
 | 
			
		||||
	close(fd);
 | 
			
		||||
 | 
			
		||||
	dev_close(dev);
 | 
			
		||||
 | 
			
		||||
	if (r) {
 | 
			
		||||
		new_cs = (struct cs *) new_cf;
 | 
			
		||||
@@ -536,15 +545,17 @@ static int _match_aux(struct parser *p, int t)
 | 
			
		||||
	if (p->t != t)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	_get_token(p);
 | 
			
		||||
	_get_token(p, t);
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * tokeniser
 | 
			
		||||
 */
 | 
			
		||||
static void _get_token(struct parser *p)
 | 
			
		||||
static void _get_token(struct parser *p, int tok_prev)
 | 
			
		||||
{
 | 
			
		||||
	int values_allowed = 0;
 | 
			
		||||
 | 
			
		||||
	p->tb = p->te;
 | 
			
		||||
	_eat_space(p);
 | 
			
		||||
	if (p->tb == p->fe || !*p->tb) {
 | 
			
		||||
@@ -552,6 +563,11 @@ static void _get_token(struct parser *p)
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Should next token be interpreted as value instead of identifier? */
 | 
			
		||||
	if (tok_prev == TOK_EQ || tok_prev == TOK_ARRAY_B ||
 | 
			
		||||
	    tok_prev == TOK_COMMA)
 | 
			
		||||
		values_allowed = 1;
 | 
			
		||||
 | 
			
		||||
	p->t = TOK_INT;		/* fudge so the fall through for
 | 
			
		||||
				   floats works */
 | 
			
		||||
	switch (*p->te) {
 | 
			
		||||
@@ -599,6 +615,16 @@ static void _get_token(struct parser *p)
 | 
			
		||||
			p->te++;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case '\'':
 | 
			
		||||
		p->t = TOK_STRING;
 | 
			
		||||
		p->te++;
 | 
			
		||||
		while ((p->te != p->fe) && (*p->te) && (*p->te != '\''))
 | 
			
		||||
			p->te++;
 | 
			
		||||
 | 
			
		||||
		if ((p->te != p->fe) && (*p->te))
 | 
			
		||||
			p->te++;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case '.':
 | 
			
		||||
		p->t = TOK_FLOAT;
 | 
			
		||||
	case '0':
 | 
			
		||||
@@ -611,22 +637,25 @@ static void _get_token(struct parser *p)
 | 
			
		||||
	case '7':
 | 
			
		||||
	case '8':
 | 
			
		||||
	case '9':
 | 
			
		||||
		p->te++;
 | 
			
		||||
		while ((p->te != p->fe) && (*p->te)) {
 | 
			
		||||
			if (*p->te == '.') {
 | 
			
		||||
				if (p->t == TOK_FLOAT)
 | 
			
		||||
					break;
 | 
			
		||||
				p->t = TOK_FLOAT;
 | 
			
		||||
			} else if (!isdigit((int) *p->te))
 | 
			
		||||
				break;
 | 
			
		||||
		if (values_allowed) {
 | 
			
		||||
			p->te++;
 | 
			
		||||
			while ((p->te != p->fe) && (*p->te)) {
 | 
			
		||||
				if (*p->te == '.') {
 | 
			
		||||
					if (p->t == TOK_FLOAT)
 | 
			
		||||
						break;
 | 
			
		||||
					p->t = TOK_FLOAT;
 | 
			
		||||
				} else if (!isdigit((int) *p->te))
 | 
			
		||||
					break;
 | 
			
		||||
				p->te++;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		p->t = TOK_IDENTIFIER;
 | 
			
		||||
		while ((p->te != p->fe) && (*p->te) && !isspace(*p->te) &&
 | 
			
		||||
		       (*p->te != '#') && (*p->te != '='))
 | 
			
		||||
		       (*p->te != '#') && (*p->te != '=') && (*p->te != '{') &&
 | 
			
		||||
		       (*p->te != '}'))
 | 
			
		||||
			p->te++;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,8 +7,7 @@
 | 
			
		||||
#ifndef _LVM_CONFIG_H
 | 
			
		||||
#define _LVM_CONFIG_H
 | 
			
		||||
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include "device.h"
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	CFG_STRING,
 | 
			
		||||
@@ -42,7 +41,7 @@ void destroy_config_tree(struct config_tree *cf);
 | 
			
		||||
 | 
			
		||||
typedef uint32_t (*checksum_fn_t) (uint32_t initial, void *buf, uint32_t size);
 | 
			
		||||
 | 
			
		||||
int read_config_fd(struct config_tree *cf, int fd, const char *file,
 | 
			
		||||
int read_config_fd(struct config_tree *cf, struct device *dev,
 | 
			
		||||
		   off_t offset, size_t size, off_t offset2, size_t size2,
 | 
			
		||||
		   checksum_fn_t checksum_fn, uint32_t checksum);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -52,13 +52,20 @@
 | 
			
		||||
#define DEFAULT_SUFFIX 1
 | 
			
		||||
 | 
			
		||||
#ifdef DEVMAPPER_SUPPORT
 | 
			
		||||
  #define DEFAULT_ACTIVATION 1
 | 
			
		||||
#  define DEFAULT_ACTIVATION 1
 | 
			
		||||
#  define DEFAULT_RESERVED_MEMORY 8192
 | 
			
		||||
#  define DEFAULT_RESERVED_STACK 256
 | 
			
		||||
#  define DEFAULT_PROCESS_PRIORITY -18
 | 
			
		||||
#else
 | 
			
		||||
  #define DEFAULT_ACTIVATION 0
 | 
			
		||||
#  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
 | 
			
		||||
@@ -66,12 +73,12 @@
 | 
			
		||||
#define DEFAULT_REP_HEADINGS 1
 | 
			
		||||
#define DEFAULT_REP_SEPARATOR " "
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent"
 | 
			
		||||
#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent,move_pv,move_percent"
 | 
			
		||||
#define DEFAULT_VGS_COLS "vg_name,pv_count,lv_count,snap_count,vg_attr,vg_size,vg_free"
 | 
			
		||||
#define DEFAULT_PVS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free"
 | 
			
		||||
#define DEFAULT_SEGS_COLS "lv_name,vg_name,lv_attr,stripes,segtype,seg_size"
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_minor,origin,snap_percent,lv_uuid"
 | 
			
		||||
#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,origin,snap_percent,move_pv,move_percent,lv_uuid"
 | 
			
		||||
#define DEFAULT_VGS_COLS_VERB "vg_name,vg_attr,vg_extent_size,pv_count,lv_count,snap_count,vg_size,vg_free,vg_uuid"
 | 
			
		||||
#define DEFAULT_PVS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pv_uuid"
 | 
			
		||||
#define DEFAULT_SEGS_COLS_VERB "lv_name,vg_name,lv_attr,seg_start,seg_size,stripes,segtype,stripesize,chunksize"
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,6 @@
 | 
			
		||||
#ifndef _LVM_BITSET_H
 | 
			
		||||
#define _LVM_BITSET_H
 | 
			
		||||
 | 
			
		||||
#include "lvm-types.h"
 | 
			
		||||
#include "pool.h"
 | 
			
		||||
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,6 @@
 | 
			
		||||
#ifndef _LVM_BTREE_H
 | 
			
		||||
#define _LVM_BTREE_H
 | 
			
		||||
 | 
			
		||||
#include "lvm-types.h"
 | 
			
		||||
#include "pool.h"
 | 
			
		||||
 | 
			
		||||
struct btree;
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,8 +7,6 @@
 | 
			
		||||
#ifndef _LVM_HASH_H
 | 
			
		||||
#define _LVM_HASH_H
 | 
			
		||||
 | 
			
		||||
#include "lvm-types.h"
 | 
			
		||||
 | 
			
		||||
struct hash_table;
 | 
			
		||||
struct hash_node;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,10 +7,14 @@
 | 
			
		||||
#ifndef _LVM_LIST_H
 | 
			
		||||
#define _LVM_LIST_H
 | 
			
		||||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
 | 
			
		||||
struct list {
 | 
			
		||||
	struct list *n, *p;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define LIST_INIT(name)	struct list name = { &(name), &(name) }
 | 
			
		||||
 | 
			
		||||
static inline void list_init(struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	head->n = head->p = head;
 | 
			
		||||
@@ -54,9 +58,17 @@ static inline int list_end(struct list *head, struct list *elem)
 | 
			
		||||
	return elem->n == head;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline struct list *list_next(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	return (list_end(head, elem) ? NULL : elem->n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define list_iterate(v, head) \
 | 
			
		||||
	for (v = (head)->n; v != head; v = v->n)
 | 
			
		||||
 | 
			
		||||
#define list_uniterate(v, head, start) \
 | 
			
		||||
	for (v = (start)->p; v != head; v = v->p)
 | 
			
		||||
 | 
			
		||||
#define list_iterate_safe(v, t, head) \
 | 
			
		||||
	for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
 | 
			
		||||
 | 
			
		||||
@@ -74,8 +86,14 @@ static inline unsigned int list_size(const struct list *head)
 | 
			
		||||
#define list_item(v, t) \
 | 
			
		||||
    ((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->list))
 | 
			
		||||
 | 
			
		||||
/* Given a known element in a known structure, locate the struct list */
 | 
			
		||||
#define list_head(v, t, e) \
 | 
			
		||||
    (((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->e))->list)
 | 
			
		||||
#define list_struct_base(v, t, h) \
 | 
			
		||||
    ((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->h))
 | 
			
		||||
 | 
			
		||||
/* Given a known element in a known structure, locate another */
 | 
			
		||||
#define struct_field(v, t, e, f) \
 | 
			
		||||
    (((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->e))->f)
 | 
			
		||||
 | 
			
		||||
/* Given a known element in a known structure, locate the list head */
 | 
			
		||||
#define list_head(v, t, e) struct_field(v, t, e, list)
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -13,15 +13,11 @@
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
 | 
			
		||||
/* Define some portable printing types */
 | 
			
		||||
#if __WORDSIZE == 64
 | 
			
		||||
#define PRIsize_t "lu"
 | 
			
		||||
#else
 | 
			
		||||
#define PRIsize_t "u"
 | 
			
		||||
#endif
 | 
			
		||||
#define PRIsize_t "Zu"
 | 
			
		||||
 | 
			
		||||
struct str_list {
 | 
			
		||||
	struct list list;
 | 
			
		||||
	char *str;
 | 
			
		||||
	const char *str;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -11,12 +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>
 | 
			
		||||
 | 
			
		||||
struct dev_iter {
 | 
			
		||||
	struct btree_iter *current;
 | 
			
		||||
@@ -43,7 +42,44 @@ static struct {
 | 
			
		||||
 | 
			
		||||
static int _insert(const char *path, int rec);
 | 
			
		||||
 | 
			
		||||
static struct device *_create_dev(dev_t d)
 | 
			
		||||
struct device *dev_create_file(const char *filename, struct device *dev,
 | 
			
		||||
			       struct str_list *alias)
 | 
			
		||||
{
 | 
			
		||||
	int allocate = !dev;
 | 
			
		||||
 | 
			
		||||
	if (allocate && !(dev = dbg_malloc(sizeof(*dev)))) {
 | 
			
		||||
		log_error("struct device allocation failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	if (allocate && !(alias = dbg_malloc(sizeof(*alias)))) {
 | 
			
		||||
		log_error("struct str_list allocation failed");
 | 
			
		||||
		dbg_free(dev);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(alias->str = dbg_strdup(filename))) {
 | 
			
		||||
		log_error("filename strdup failed");
 | 
			
		||||
		if (allocate) {
 | 
			
		||||
			dbg_free(dev);
 | 
			
		||||
			dbg_free(alias);
 | 
			
		||||
		}
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	dev->flags = DEV_REGULAR;
 | 
			
		||||
	if (allocate)
 | 
			
		||||
		dev->flags |= DEV_ALLOCED;
 | 
			
		||||
	list_init(&dev->aliases);
 | 
			
		||||
	list_add(&dev->aliases, &alias->list);
 | 
			
		||||
	dev->end = UINT64_C(0);
 | 
			
		||||
	dev->dev = 0;
 | 
			
		||||
	dev->fd = -1;
 | 
			
		||||
	dev->open_count = 0;
 | 
			
		||||
	memset(dev->pvid, 0, sizeof(dev->pvid));
 | 
			
		||||
	list_init(&dev->open_list);
 | 
			
		||||
 | 
			
		||||
	return dev;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct device *_dev_create(dev_t d)
 | 
			
		||||
{
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
 | 
			
		||||
@@ -51,12 +87,14 @@ static struct device *_create_dev(dev_t d)
 | 
			
		||||
		log_error("struct device allocation failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dev->flags = 0;
 | 
			
		||||
	list_init(&dev->aliases);
 | 
			
		||||
	dev->dev = d;
 | 
			
		||||
	dev->fd = -1;
 | 
			
		||||
	dev->flags = 0;
 | 
			
		||||
	dev->open_count = 0;
 | 
			
		||||
	dev->end = UINT64_C(0);
 | 
			
		||||
	memset(dev->pvid, 0, sizeof(dev->pvid));
 | 
			
		||||
	list_init(&dev->open_list);
 | 
			
		||||
 | 
			
		||||
	return dev;
 | 
			
		||||
}
 | 
			
		||||
@@ -176,7 +214,7 @@ static int _insert_dev(const char *path, dev_t d)
 | 
			
		||||
	if (!(dev = (struct device *) btree_lookup(_cache.devices,
 | 
			
		||||
						   (uint32_t) d))) {
 | 
			
		||||
		/* create new device */
 | 
			
		||||
		if (!(dev = _create_dev(d))) {
 | 
			
		||||
		if (!(dev = _dev_create(d))) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
@@ -403,20 +441,31 @@ int dev_cache_add_dir(const char *path)
 | 
			
		||||
 | 
			
		||||
/* Check cached device name is still valid before returning it */
 | 
			
		||||
/* This should be a rare occurrence */
 | 
			
		||||
/* set quiet if the cache is expected to be out-of-date */
 | 
			
		||||
/* FIXME Make rest of code pass/cache struct device instead of dev_name */
 | 
			
		||||
const char *dev_name_confirmed(struct device *dev)
 | 
			
		||||
const char *dev_name_confirmed(struct device *dev, int quiet)
 | 
			
		||||
{
 | 
			
		||||
	struct stat buf;
 | 
			
		||||
	char *name;
 | 
			
		||||
	const char *name;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	while ((r = stat(name = list_item(dev->aliases.n,
 | 
			
		||||
					  struct str_list)->str, &buf)) ||
 | 
			
		||||
	       (buf.st_rdev != dev->dev)) {
 | 
			
		||||
		if (r < 0)
 | 
			
		||||
			log_sys_error("stat", name);
 | 
			
		||||
		log_error("Path %s no longer valid for device(%d,%d)",
 | 
			
		||||
			  name, (int) MAJOR(dev->dev), (int) MINOR(dev->dev));
 | 
			
		||||
		if (r < 0) {
 | 
			
		||||
			if (quiet)
 | 
			
		||||
				log_sys_debug("stat", name);
 | 
			
		||||
			else
 | 
			
		||||
				log_sys_error("stat", name);
 | 
			
		||||
		}
 | 
			
		||||
		if (quiet)
 | 
			
		||||
			log_debug("Path %s no longer valid for device(%d,%d)",
 | 
			
		||||
			  	  name, (int) MAJOR(dev->dev),
 | 
			
		||||
				  (int) MINOR(dev->dev));
 | 
			
		||||
		else
 | 
			
		||||
			log_error("Path %s no longer valid for device(%d,%d)",
 | 
			
		||||
				  name, (int) MAJOR(dev->dev),
 | 
			
		||||
				  (int) MINOR(dev->dev));
 | 
			
		||||
 | 
			
		||||
		/* Remove the incorrect hash entry */
 | 
			
		||||
		hash_remove(_cache.names, name);
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,26 +5,205 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "lib.h"
 | 
			
		||||
#include "device.h"
 | 
			
		||||
#include "lvm-types.h"
 | 
			
		||||
#include "device.h"
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
#include "lvmcache.h"
 | 
			
		||||
#include "memlock.h"
 | 
			
		||||
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <linux/unistd.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <linux/fs.h>		// UGH!!! for BLKSSZGET
 | 
			
		||||
 | 
			
		||||
/* FIXME 64 bit offset!!!
 | 
			
		||||
#ifdef linux
 | 
			
		||||
#  define u64 uint64_t		/* Missing without __KERNEL__ */
 | 
			
		||||
#  undef WNOHANG		/* Avoid redefinition */
 | 
			
		||||
#  undef WUNTRACED		/* Avoid redefinition */
 | 
			
		||||
#  include <linux/fs.h>		/* For block ioctl definitions */
 | 
			
		||||
#  define BLKSIZE_SHIFT SECTOR_SHIFT
 | 
			
		||||
#else
 | 
			
		||||
#  include <sys/disk.h>
 | 
			
		||||
#  define BLKBSZGET DKIOCGETBLOCKSIZE
 | 
			
		||||
#  define BLKSSZGET DKIOCGETBLOCKSIZE
 | 
			
		||||
#  define BLKGETSIZE64 DKIOCGETBLOCKCOUNT
 | 
			
		||||
#  define BLKFLSBUF DKIOCSYNCHRONIZECACHE
 | 
			
		||||
#  define BLKSIZE_SHIFT 0
 | 
			
		||||
#  ifndef O_DIRECT
 | 
			
		||||
#    define O_DIRECT	0
 | 
			
		||||
#  endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* FIXME Use _llseek for 64-bit
 | 
			
		||||
_syscall5(int,  _llseek,  uint,  fd, ulong, hi, ulong, lo, loff_t *, res, uint, wh);
 | 
			
		||||
 if (_llseek((unsigned) fd, (ulong) (offset >> 32), (ulong) (offset & 0xFFFFFFFF), &pos, SEEK_SET) < 0) { 
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
static LIST_INIT(_open_devices);
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------------
 | 
			
		||||
 * The standard io loop that keeps submitting an io until it's
 | 
			
		||||
 * all gone.
 | 
			
		||||
 *---------------------------------------------------------------*/
 | 
			
		||||
static int _io(struct device_area *where, void *buffer, int should_write)
 | 
			
		||||
{
 | 
			
		||||
	int fd = dev_fd(where->dev);
 | 
			
		||||
	ssize_t n = 0;
 | 
			
		||||
	size_t total = 0;
 | 
			
		||||
 | 
			
		||||
	if (fd < 0) {
 | 
			
		||||
		log_error("Attempt to read an unopened device (%s).",
 | 
			
		||||
			  dev_name(where->dev));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Skip all writes in test mode.
 | 
			
		||||
	 */
 | 
			
		||||
	if (should_write && test_mode())
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (where->size > SSIZE_MAX) {
 | 
			
		||||
		log_error("Read size too large: %" PRIu64, where->size);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lseek(fd, (off_t) where->start, SEEK_SET) < 0) {
 | 
			
		||||
		log_sys_error("lseek", dev_name(where->dev));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while (total < (size_t) where->size) {
 | 
			
		||||
		do
 | 
			
		||||
			n = should_write ?
 | 
			
		||||
			    write(fd, buffer, (size_t) where->size - total) :
 | 
			
		||||
			    read(fd, buffer, (size_t) where->size - total);
 | 
			
		||||
		while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
 | 
			
		||||
 | 
			
		||||
		if (n <= 0)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		total += n;
 | 
			
		||||
		buffer += n;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return (total == (size_t) where->size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------------
 | 
			
		||||
 * LVM2 uses O_DIRECT when performing metadata io, which requires
 | 
			
		||||
 * block size aligned accesses.  If any io is not aligned we have
 | 
			
		||||
 * to perform the io via a bounce buffer, obviously this is quite
 | 
			
		||||
 * inefficient.
 | 
			
		||||
 *---------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Get the sector size from an _open_ device.
 | 
			
		||||
 */
 | 
			
		||||
static int _get_block_size(struct device *dev, unsigned int *size)
 | 
			
		||||
{
 | 
			
		||||
	int s;
 | 
			
		||||
 | 
			
		||||
	if (ioctl(dev_fd(dev), BLKBSZGET, &s) < 0) {
 | 
			
		||||
		log_sys_error("ioctl BLKBSZGET", dev_name(dev));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*size = (unsigned int) s;
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Widens a region to be an aligned region.
 | 
			
		||||
 */
 | 
			
		||||
static void _widen_region(unsigned int block_size, struct device_area *region,
 | 
			
		||||
			  struct device_area *result)
 | 
			
		||||
{
 | 
			
		||||
	uint64_t mask = block_size - 1, delta;
 | 
			
		||||
	memcpy(result, region, sizeof(*result));
 | 
			
		||||
 | 
			
		||||
	/* adjust the start */
 | 
			
		||||
	delta = result->start & mask;
 | 
			
		||||
	if (delta) {
 | 
			
		||||
		result->start -= delta;
 | 
			
		||||
		result->size += delta;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* adjust the end */
 | 
			
		||||
	delta = (result->start + result->size) & mask;
 | 
			
		||||
	if (delta)
 | 
			
		||||
		result->size += block_size - delta;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _aligned_io(struct device_area *where, void *buffer,
 | 
			
		||||
		       int should_write)
 | 
			
		||||
{
 | 
			
		||||
	void *bounce;
 | 
			
		||||
	unsigned int block_size = 0;
 | 
			
		||||
	uintptr_t mask;
 | 
			
		||||
	struct device_area widened;
 | 
			
		||||
 | 
			
		||||
	if (!(where->dev->flags & DEV_REGULAR) &&
 | 
			
		||||
	    !_get_block_size(where->dev, &block_size)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!block_size)
 | 
			
		||||
		block_size = SECTOR_SIZE * 2;
 | 
			
		||||
 | 
			
		||||
	_widen_region(block_size, where, &widened);
 | 
			
		||||
 | 
			
		||||
	/* Do we need to use a bounce buffer? */
 | 
			
		||||
	mask = block_size - 1;
 | 
			
		||||
	if (!memcmp(where, &widened, sizeof(widened)) &&
 | 
			
		||||
	    !((uintptr_t) buffer & mask))
 | 
			
		||||
		return _io(where, buffer, should_write);
 | 
			
		||||
 | 
			
		||||
	/* Allocate a bounce buffer with an extra block */
 | 
			
		||||
	if (!(bounce = alloca((size_t) widened.size + block_size))) {
 | 
			
		||||
		log_error("Bounce buffer alloca failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Realign start of bounce buffer (using the extra sector)
 | 
			
		||||
	 */
 | 
			
		||||
	if (((uintptr_t) bounce) & mask)
 | 
			
		||||
		bounce = (void *) ((((uintptr_t) bounce) + mask) & ~mask);
 | 
			
		||||
 | 
			
		||||
	/* channel the io through the bounce buffer */
 | 
			
		||||
	if (!_io(&widened, bounce, 0)) {
 | 
			
		||||
		if (!should_write) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		/* FIXME pre-extend the file */
 | 
			
		||||
		memset(bounce, '\n', widened.size);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (should_write) {
 | 
			
		||||
		memcpy(bounce + (where->start - widened.start), buffer,
 | 
			
		||||
		       (size_t) where->size);
 | 
			
		||||
 | 
			
		||||
		/* ... then we write */
 | 
			
		||||
		return _io(&widened, bounce, 1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memcpy(buffer, bounce + (where->start - widened.start),
 | 
			
		||||
	       (size_t) where->size);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------------
 | 
			
		||||
 * Public functions
 | 
			
		||||
 *---------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
int dev_get_size(struct device *dev, uint64_t *size)
 | 
			
		||||
{
 | 
			
		||||
	int fd;
 | 
			
		||||
	long s;
 | 
			
		||||
	const char *name = dev_name(dev);
 | 
			
		||||
 | 
			
		||||
	log_very_verbose("Getting size of %s", name);
 | 
			
		||||
@@ -33,15 +212,14 @@ int dev_get_size(struct device *dev, uint64_t *size)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* FIXME: add 64 bit ioctl */
 | 
			
		||||
	if (ioctl(fd, BLKGETSIZE, &s) < 0) {
 | 
			
		||||
		log_sys_error("ioctl BLKGETSIZE", name);
 | 
			
		||||
	if (ioctl(fd, BLKGETSIZE64, size) < 0) {
 | 
			
		||||
		log_sys_error("ioctl BLKGETSIZE64", name);
 | 
			
		||||
		close(fd);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*size >>= BLKSIZE_SHIFT;	/* Convert to sectors */
 | 
			
		||||
	close(fd);
 | 
			
		||||
	*size = (uint64_t) s;
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -68,48 +246,106 @@ int dev_get_sectsize(struct device *dev, uint32_t *size)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _flush(int fd)
 | 
			
		||||
void dev_flush(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	ioctl(fd, BLKFLSBUF, 0);
 | 
			
		||||
	if (!(dev->flags & DEV_REGULAR) && ioctl(dev->fd, BLKFLSBUF, 0) >= 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (fsync(dev->fd) >= 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	sync();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_open(struct device *dev, int flags)
 | 
			
		||||
int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
 | 
			
		||||
{
 | 
			
		||||
	struct stat buf;
 | 
			
		||||
	const char *name = dev_name_confirmed(dev);
 | 
			
		||||
	const char *name;
 | 
			
		||||
 | 
			
		||||
	if (!name) {
 | 
			
		||||
	if (dev->fd >= 0) {
 | 
			
		||||
		dev->open_count++;
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (memlock())
 | 
			
		||||
		log_error("WARNING: dev_open(%s) called while suspended",
 | 
			
		||||
			  dev_name(dev));
 | 
			
		||||
 | 
			
		||||
	if (dev->flags & DEV_REGULAR)
 | 
			
		||||
		name = dev_name(dev);
 | 
			
		||||
	else if (!(name = dev_name_confirmed(dev, quiet))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (dev->fd >= 0) {
 | 
			
		||||
		log_error("Device '%s' has already been opened", name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((stat(name, &buf) < 0) || (buf.st_rdev != dev->dev)) {
 | 
			
		||||
	if (!(dev->flags & DEV_REGULAR) &&
 | 
			
		||||
	    ((stat(name, &buf) < 0) || (buf.st_rdev != dev->dev))) {
 | 
			
		||||
		log_error("%s: stat failed: Has device name changed?", name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((dev->fd = open(name, flags)) < 0) {
 | 
			
		||||
	if (direct)
 | 
			
		||||
		flags |= O_DIRECT;
 | 
			
		||||
 | 
			
		||||
	if ((dev->fd = open(name, flags, 0777)) < 0) {
 | 
			
		||||
		log_sys_error("open", name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((fstat(dev->fd, &buf) < 0) || (buf.st_rdev != dev->dev)) {
 | 
			
		||||
	dev->open_count = 1;
 | 
			
		||||
	dev->flags &= ~DEV_ACCESSED_W;
 | 
			
		||||
 | 
			
		||||
	if (!(dev->flags & DEV_REGULAR) &&
 | 
			
		||||
	    ((fstat(dev->fd, &buf) < 0) || (buf.st_rdev != dev->dev))) {
 | 
			
		||||
		log_error("%s: fstat failed: Has device name changed?", name);
 | 
			
		||||
		dev_close(dev);
 | 
			
		||||
		dev->fd = -1;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	_flush(dev->fd);
 | 
			
		||||
	dev->flags = 0;
 | 
			
		||||
#if !O_DIRECT
 | 
			
		||||
	if (!(dev->flags & DEV_REGULAR))
 | 
			
		||||
		dev_flush(dev);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if ((flags & O_CREAT) && !(flags & O_TRUNC)) {
 | 
			
		||||
		dev->end = lseek(dev->fd, (off_t) 0, SEEK_END);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	list_add(&_open_devices, &dev->open_list);
 | 
			
		||||
	log_debug("Opened %s", dev_name(dev));
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_open_quiet(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	/* FIXME Open O_RDONLY if vg read lock? */
 | 
			
		||||
	return dev_open_flags(dev, O_RDWR, 1, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_open(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	/* FIXME Open O_RDONLY if vg read lock? */
 | 
			
		||||
	return dev_open_flags(dev, O_RDWR, 1, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _close(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	if (close(dev->fd))
 | 
			
		||||
		log_sys_error("close", dev_name(dev));
 | 
			
		||||
	dev->fd = -1;
 | 
			
		||||
	list_del(&dev->open_list);
 | 
			
		||||
 | 
			
		||||
	log_debug("Closed %s", dev_name(dev));
 | 
			
		||||
 | 
			
		||||
	if (dev->flags & DEV_ALLOCED) {
 | 
			
		||||
		dbg_free((void *) list_item(dev->aliases.n, struct str_list)->
 | 
			
		||||
			 str);
 | 
			
		||||
		dbg_free(dev->aliases.n);
 | 
			
		||||
		dbg_free(dev);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_close(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	if (dev->fd < 0) {
 | 
			
		||||
@@ -117,126 +353,91 @@ int dev_close(struct device *dev)
 | 
			
		||||
			  "which is not open.", dev_name(dev));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#if !O_DIRECT
 | 
			
		||||
	if (dev->flags & DEV_ACCESSED_W)
 | 
			
		||||
		_flush(dev->fd);
 | 
			
		||||
		dev_flush(dev);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (close(dev->fd))
 | 
			
		||||
		log_sys_error("close", dev_name(dev));
 | 
			
		||||
 | 
			
		||||
	dev->fd = -1;
 | 
			
		||||
	/* FIXME lookup device in cache to get vgname and see if it's locked? */
 | 
			
		||||
	if (--dev->open_count < 1 && !vgs_locked())
 | 
			
		||||
		_close(dev);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ssize_t raw_read(int fd, void *buf, size_t count)
 | 
			
		||||
void dev_close_all(void)
 | 
			
		||||
{
 | 
			
		||||
	ssize_t n = 0, tot = 0;
 | 
			
		||||
	struct list *doh, *doht;
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
 | 
			
		||||
	if (count > SSIZE_MAX)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	while (tot < (signed) count) {
 | 
			
		||||
		do
 | 
			
		||||
			n = read(fd, buf, count - tot);
 | 
			
		||||
		while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
 | 
			
		||||
 | 
			
		||||
		if (n <= 0)
 | 
			
		||||
			return tot ? tot : n;
 | 
			
		||||
 | 
			
		||||
		tot += n;
 | 
			
		||||
		buf += n;
 | 
			
		||||
	list_iterate_safe(doh, doht, &_open_devices) {
 | 
			
		||||
		dev = list_struct_base(doh, struct device, open_list);
 | 
			
		||||
		if (dev->open_count < 1)
 | 
			
		||||
			_close(dev);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return tot;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ssize_t dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
 | 
			
		||||
int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
 | 
			
		||||
{
 | 
			
		||||
	const char *name = dev_name(dev);
 | 
			
		||||
	int fd = dev->fd;
 | 
			
		||||
	/* loff_t pos; */
 | 
			
		||||
	struct device_area where;
 | 
			
		||||
 | 
			
		||||
	if (fd < 0) {
 | 
			
		||||
		log_err("Attempt to read an unopened device (%s).", name);
 | 
			
		||||
	if (!dev->open_count)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* if (_llseek((unsigned) fd, (ulong) (offset >> 32), (ulong) (offset & 0xFFFFFFFF), &pos, SEEK_SET) < 0) { */
 | 
			
		||||
	if (lseek(fd, (off_t) offset, SEEK_SET) < 0) {
 | 
			
		||||
		log_sys_error("lseek", name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	where.dev = dev;
 | 
			
		||||
	where.start = offset;
 | 
			
		||||
	where.size = len;
 | 
			
		||||
 | 
			
		||||
	return raw_read(fd, buffer, len);
 | 
			
		||||
	return _aligned_io(&where, buffer, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _write(int fd, const void *buf, size_t count)
 | 
			
		||||
/* FIXME If O_DIRECT can't extend file, dev_extend first; dev_truncate after.
 | 
			
		||||
 *       But fails if concurrent processes writing
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* FIXME pre-extend the file */
 | 
			
		||||
int dev_append(struct device *dev, size_t len, void *buffer)
 | 
			
		||||
{
 | 
			
		||||
	ssize_t n = 0;
 | 
			
		||||
	int tot = 0;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	/* Skip all writes */
 | 
			
		||||
	if (test_mode())
 | 
			
		||||
		return count;
 | 
			
		||||
	if (!dev->open_count)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	while (tot < count) {
 | 
			
		||||
		do
 | 
			
		||||
			n = write(fd, buf, count - tot);
 | 
			
		||||
		while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
 | 
			
		||||
	r = dev_write(dev, dev->end, len, buffer);
 | 
			
		||||
	dev->end += (uint64_t) len;
 | 
			
		||||
 | 
			
		||||
		if (n <= 0)
 | 
			
		||||
			return tot ? tot : n;
 | 
			
		||||
 | 
			
		||||
		tot += n;
 | 
			
		||||
		buf += n;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return tot;
 | 
			
		||||
#if !O_DIRECT
 | 
			
		||||
	dev_flush(dev);
 | 
			
		||||
#endif
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int64_t dev_write(struct device * dev, uint64_t offset, size_t len,
 | 
			
		||||
		  void *buffer)
 | 
			
		||||
int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer)
 | 
			
		||||
{
 | 
			
		||||
	const char *name = dev_name(dev);
 | 
			
		||||
	int fd = dev->fd;
 | 
			
		||||
	struct device_area where;
 | 
			
		||||
 | 
			
		||||
	if (fd < 0) {
 | 
			
		||||
		log_error("Attempt to write to unopened device %s", name);
 | 
			
		||||
	if (!dev->open_count)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lseek(fd, (off_t) offset, SEEK_SET) < 0) {
 | 
			
		||||
		log_sys_error("lseek", name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	where.dev = dev;
 | 
			
		||||
	where.start = offset;
 | 
			
		||||
	where.size = len;
 | 
			
		||||
 | 
			
		||||
	dev->flags |= DEV_ACCESSED_W;
 | 
			
		||||
 | 
			
		||||
	return _write(fd, buffer, len);
 | 
			
		||||
	return _aligned_io(&where, buffer, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_zero(struct device *dev, uint64_t offset, size_t len)
 | 
			
		||||
{
 | 
			
		||||
	int64_t r;
 | 
			
		||||
	size_t s;
 | 
			
		||||
	char buffer[4096];
 | 
			
		||||
	int already_open;
 | 
			
		||||
 | 
			
		||||
	already_open = dev_is_open(dev);
 | 
			
		||||
 | 
			
		||||
	if (!already_open && !dev_open(dev, O_RDWR)) {
 | 
			
		||||
	if (!dev_open(dev)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lseek(dev->fd, (off_t) offset, SEEK_SET) < 0) {
 | 
			
		||||
		log_sys_error("lseek", dev_name(dev));
 | 
			
		||||
		if (!already_open && !dev_close(dev))
 | 
			
		||||
			stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((offset % SECTOR_SIZE) || (len % SECTOR_SIZE))
 | 
			
		||||
		log_debug("Wiping %s at %" PRIu64 " length %" PRIsize_t,
 | 
			
		||||
			  dev_name(dev), offset, len);
 | 
			
		||||
@@ -248,21 +449,17 @@ int dev_zero(struct device *dev, uint64_t offset, size_t len)
 | 
			
		||||
	memset(buffer, 0, sizeof(buffer));
 | 
			
		||||
	while (1) {
 | 
			
		||||
		s = len > sizeof(buffer) ? sizeof(buffer) : len;
 | 
			
		||||
		r = _write(dev->fd, buffer, s);
 | 
			
		||||
 | 
			
		||||
		if (r <= 0)
 | 
			
		||||
		if (!dev_write(dev, offset, s, buffer))
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		len -= r;
 | 
			
		||||
		if (!len) {
 | 
			
		||||
			r = 1;
 | 
			
		||||
		len -= s;
 | 
			
		||||
		if (!len)
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dev->flags |= DEV_ACCESSED_W;
 | 
			
		||||
 | 
			
		||||
	if (!already_open && !dev_close(dev))
 | 
			
		||||
	if (!dev_close(dev))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	/* FIXME: Always display error */
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,6 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,11 +7,12 @@
 | 
			
		||||
#ifndef _LVM_DEVICE_H
 | 
			
		||||
#define _LVM_DEVICE_H
 | 
			
		||||
 | 
			
		||||
#include "lvm-types.h"
 | 
			
		||||
#include "list.h"
 | 
			
		||||
#include "uuid.h"
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
 | 
			
		||||
#define DEV_ACCESSED_W		0x00000001	/* Device written to? */
 | 
			
		||||
#define DEV_REGULAR		0x00000002	/* Regular file? */
 | 
			
		||||
#define DEV_ALLOCED		0x00000004	/* dbg_malloc used */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * All devices in LVM will be represented by one of these.
 | 
			
		||||
@@ -23,7 +24,10 @@ struct device {
 | 
			
		||||
 | 
			
		||||
	/* private */
 | 
			
		||||
	int fd;
 | 
			
		||||
	int open_count;
 | 
			
		||||
	uint32_t flags;
 | 
			
		||||
	uint64_t end;
 | 
			
		||||
	struct list open_list;
 | 
			
		||||
 | 
			
		||||
	char pvid[ID_LEN + 1];
 | 
			
		||||
};
 | 
			
		||||
@@ -45,20 +49,26 @@ struct device_area {
 | 
			
		||||
int dev_get_size(struct device *dev, uint64_t *size);
 | 
			
		||||
int dev_get_sectsize(struct device *dev, uint32_t *size);
 | 
			
		||||
 | 
			
		||||
int dev_open(struct device *dev, int flags);
 | 
			
		||||
/* Use quiet version if device number could change e.g. when opening LV */
 | 
			
		||||
int dev_open(struct device *dev);
 | 
			
		||||
int dev_open_quiet(struct device *dev);
 | 
			
		||||
int dev_open_flags(struct device *dev, int flags, int append, int quiet);
 | 
			
		||||
int dev_close(struct device *dev);
 | 
			
		||||
void dev_close_all(void);
 | 
			
		||||
 | 
			
		||||
static inline int dev_fd(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return dev->fd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ssize_t raw_read(int fd, void *buf, size_t count);
 | 
			
		||||
 | 
			
		||||
ssize_t dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer);
 | 
			
		||||
int64_t dev_write(struct device *dev, uint64_t offset, size_t len,
 | 
			
		||||
		  void *buffer);
 | 
			
		||||
int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer);
 | 
			
		||||
int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer);
 | 
			
		||||
int dev_append(struct device *dev, size_t len, void *buffer);
 | 
			
		||||
int dev_zero(struct device *dev, uint64_t offset, size_t len);
 | 
			
		||||
void dev_flush(struct device *dev);
 | 
			
		||||
 | 
			
		||||
struct device *dev_create_file(const char *filename, struct device *dev,
 | 
			
		||||
			       struct str_list *alias);
 | 
			
		||||
 | 
			
		||||
static inline const char *dev_name(const struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
@@ -67,12 +77,7 @@ static inline const char *dev_name(const struct device *dev)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Return a valid device name from the alias list; NULL otherwise */
 | 
			
		||||
const char *dev_name_confirmed(struct device *dev);
 | 
			
		||||
 | 
			
		||||
static inline int dev_is_open(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return dev->fd >= 0 ? 1 : 0;
 | 
			
		||||
}
 | 
			
		||||
const char *dev_name_confirmed(struct device *dev, int quiet);
 | 
			
		||||
 | 
			
		||||
/* FIXME Check partition type if appropriate */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -42,7 +42,7 @@ static struct {
 | 
			
		||||
} _segtypes[] = {
 | 
			
		||||
	{
 | 
			
		||||
	SEG_STRIPED, "striped"}, {
 | 
			
		||||
	SEG_MIRROR, "mirror"}, {
 | 
			
		||||
	SEG_MIRRORED, "mirror"}, {
 | 
			
		||||
	SEG_SNAPSHOT, "snapshot"}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -70,18 +70,20 @@ uint64_t units_to_bytes(const char *units, char *unit_type)
 | 
			
		||||
	switch (*units) {
 | 
			
		||||
	case 'h':
 | 
			
		||||
	case 'H':
 | 
			
		||||
		v = __UINT64_C(1);
 | 
			
		||||
		v = UINT64_C(1);
 | 
			
		||||
		*unit_type = *units;
 | 
			
		||||
		break;
 | 
			
		||||
	case 's':
 | 
			
		||||
		v *= SECTOR_SIZE;
 | 
			
		||||
		break;
 | 
			
		||||
	case 'b':
 | 
			
		||||
	case 'B':
 | 
			
		||||
		v *= __UINT64_C(1);
 | 
			
		||||
		v *= UINT64_C(1);
 | 
			
		||||
		break;
 | 
			
		||||
#define KILO __UINT64_C(1024)
 | 
			
		||||
#define KILO UINT64_C(1024)
 | 
			
		||||
	case 'k':
 | 
			
		||||
		v *= KILO;
 | 
			
		||||
		break;
 | 
			
		||||
	case 'm':
 | 
			
		||||
		v *= KILO * KILO;
 | 
			
		||||
		break;
 | 
			
		||||
@@ -92,7 +94,7 @@ uint64_t units_to_bytes(const char *units, char *unit_type)
 | 
			
		||||
		v *= KILO * KILO * KILO * KILO;
 | 
			
		||||
		break;
 | 
			
		||||
#undef KILO
 | 
			
		||||
#define KILO __UINT64_C(1000)
 | 
			
		||||
#define KILO UINT64_C(1000)
 | 
			
		||||
	case 'K':
 | 
			
		||||
		v *= KILO;
 | 
			
		||||
		break;
 | 
			
		||||
@@ -166,8 +168,8 @@ const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
 | 
			
		||||
{
 | 
			
		||||
	int s;
 | 
			
		||||
	int suffix = 1;
 | 
			
		||||
	uint64_t byte;
 | 
			
		||||
	uint64_t units = __UINT64_C(1024);
 | 
			
		||||
	uint64_t byte = UINT64_C(0);
 | 
			
		||||
	uint64_t units = UINT64_C(1024);
 | 
			
		||||
	char *size_buf = NULL;
 | 
			
		||||
	const char *size_str[][3] = {
 | 
			
		||||
		{" Terabyte", " TB", "T"},
 | 
			
		||||
@@ -193,20 +195,20 @@ const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
 | 
			
		||||
		    *size_str[s][2])
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
	if (size == __UINT64_C(0)) {
 | 
			
		||||
	if (size == UINT64_C(0)) {
 | 
			
		||||
		sprintf(size_buf, "0%s", suffix ? size_str[s][sl] : "");
 | 
			
		||||
		return size_buf;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (s < 8) {
 | 
			
		||||
		byte = cmd->current_settings.unit_factor;
 | 
			
		||||
		size *= __UINT64_C(1024);
 | 
			
		||||
		size *= UINT64_C(1024);
 | 
			
		||||
	} else {
 | 
			
		||||
		suffix = 1;
 | 
			
		||||
		if (cmd->current_settings.unit_type == 'H')
 | 
			
		||||
			units = __UINT64_C(1000);
 | 
			
		||||
			units = UINT64_C(1000);
 | 
			
		||||
		else
 | 
			
		||||
			units = __UINT64_C(1024);
 | 
			
		||||
			units = UINT64_C(1024);
 | 
			
		||||
		byte = units * units * units;
 | 
			
		||||
		s = 0;
 | 
			
		||||
		while (size_str[s] && size < byte)
 | 
			
		||||
@@ -461,8 +463,11 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
	log_print("Allocation             %s", get_alloc_string(lv->alloc));
 | 
			
		||||
	log_print("Read ahead sectors     %u", lv->read_ahead);
 | 
			
		||||
 | 
			
		||||
	if (lv->status & FIXED_MINOR)
 | 
			
		||||
	if (lv->status & FIXED_MINOR) {
 | 
			
		||||
		if (lv->major >= 0)
 | 
			
		||||
			log_print("Persistent major       %d", lv->major);
 | 
			
		||||
		log_print("Persistent minor       %d", lv->minor);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (inkernel)
 | 
			
		||||
		log_print("Block device           %d:%d", info.major,
 | 
			
		||||
@@ -475,14 +480,28 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
 | 
			
		||||
static void _display_stripe(struct lv_segment *seg, uint32_t s, const char *pre)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t len = seg->len / seg->stripes;
 | 
			
		||||
	switch (seg->area[s].type) {
 | 
			
		||||
	case AREA_PV:
 | 
			
		||||
		log_print("%sPhysical volume\t%s", pre,
 | 
			
		||||
			  seg->area[s].u.pv.pv ?
 | 
			
		||||
			  dev_name(seg->area[s].u.pv.pv->dev) : "Missing");
 | 
			
		||||
 | 
			
		||||
	log_print("%sPhysical volume\t%s", pre,
 | 
			
		||||
		  seg->area[s].pv ? dev_name(seg->area[s].pv->dev) : "Missing");
 | 
			
		||||
		if (seg->area[s].u.pv.pv)
 | 
			
		||||
			log_print("%sPhysical extents\t%d to %d", pre,
 | 
			
		||||
				  seg->area[s].u.pv.pe,
 | 
			
		||||
				  seg->area[s].u.pv.pe + seg->area_len - 1);
 | 
			
		||||
		break;
 | 
			
		||||
	case AREA_LV:
 | 
			
		||||
		log_print("%sLogical volume\t%s", pre,
 | 
			
		||||
			  seg->area[s].u.lv.lv ?
 | 
			
		||||
			  seg->area[s].u.lv.lv->name : "Missing");
 | 
			
		||||
 | 
			
		||||
	if (seg->area[s].pv)
 | 
			
		||||
		log_print("%sPhysical extents\t%d to %d", pre,
 | 
			
		||||
			  seg->area[s].pe, seg->area[s].pe + len - 1);
 | 
			
		||||
		if (seg->area[s].u.lv.lv)
 | 
			
		||||
			log_print("%sLogical extents\t%d to %d", pre,
 | 
			
		||||
				  seg->area[s].u.lv.le,
 | 
			
		||||
				  seg->area[s].u.lv.le + seg->area_len - 1);
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lvdisplay_segments(struct logical_volume *lv)
 | 
			
		||||
@@ -499,7 +518,7 @@ int lvdisplay_segments(struct logical_volume *lv)
 | 
			
		||||
		log_print("Logical extent %u to %u:",
 | 
			
		||||
			  seg->le, seg->le + seg->len - 1);
 | 
			
		||||
 | 
			
		||||
		if (seg->type == SEG_STRIPED && seg->stripes == 1)
 | 
			
		||||
		if (seg->type == SEG_STRIPED && seg->area_count == 1)
 | 
			
		||||
			log_print("  Type\t\tlinear");
 | 
			
		||||
		else
 | 
			
		||||
			log_print("  Type\t\t%s",
 | 
			
		||||
@@ -507,14 +526,14 @@ int lvdisplay_segments(struct logical_volume *lv)
 | 
			
		||||
 | 
			
		||||
		switch (seg->type) {
 | 
			
		||||
		case SEG_STRIPED:
 | 
			
		||||
			if (seg->stripes == 1)
 | 
			
		||||
			if (seg->area_count == 1)
 | 
			
		||||
				_display_stripe(seg, 0, "  ");
 | 
			
		||||
			else {
 | 
			
		||||
				log_print("  Stripes\t\t%u", seg->stripes);
 | 
			
		||||
				log_print("  Stripes\t\t%u", seg->area_count);
 | 
			
		||||
				log_print("  Stripe size\t\t%u KB",
 | 
			
		||||
					  seg->stripe_size / 2);
 | 
			
		||||
 | 
			
		||||
				for (s = 0; s < seg->stripes; s++) {
 | 
			
		||||
				for (s = 0; s < seg->area_count; s++) {
 | 
			
		||||
					log_print("  Stripe %d:", s);
 | 
			
		||||
					_display_stripe(seg, s, "    ");
 | 
			
		||||
				}
 | 
			
		||||
@@ -522,8 +541,16 @@ int lvdisplay_segments(struct logical_volume *lv)
 | 
			
		||||
			log_print(" ");
 | 
			
		||||
			break;
 | 
			
		||||
		case SEG_SNAPSHOT:
 | 
			
		||||
		case SEG_MIRROR:
 | 
			
		||||
			;
 | 
			
		||||
			break;
 | 
			
		||||
		case SEG_MIRRORED:
 | 
			
		||||
			log_print("  Mirrors\t\t%u", seg->area_count);
 | 
			
		||||
			log_print("  Mirror size\t\t%u", seg->area_len);
 | 
			
		||||
			log_print("  Mirror original:");
 | 
			
		||||
			_display_stripe(seg, 0, "    ");
 | 
			
		||||
			log_print("  Mirror destination:");
 | 
			
		||||
			_display_stripe(seg, 1, "    ");
 | 
			
		||||
			log_print(" ");
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
@@ -105,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");
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -9,11 +9,9 @@
 | 
			
		||||
#include "pool.h"
 | 
			
		||||
#include "xlate.h"
 | 
			
		||||
#include "filter.h"
 | 
			
		||||
#include "cache.h"
 | 
			
		||||
#include "lvmcache.h"
 | 
			
		||||
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <linux/kdev_t.h>
 | 
			
		||||
 | 
			
		||||
#define fail do {stack; return 0;} while(0)
 | 
			
		||||
#define xx16(v) disk->v = xlate16(disk->v)
 | 
			
		||||
@@ -132,7 +130,7 @@ static int _munge_formats(struct pv_disk *pvd)
 | 
			
		||||
 | 
			
		||||
static int _read_pvd(struct device *dev, struct pv_disk *pvd)
 | 
			
		||||
{
 | 
			
		||||
	if (dev_read(dev, __UINT64_C(0), sizeof(*pvd), pvd) != sizeof(*pvd)) {
 | 
			
		||||
	if (!dev_read(dev, UINT64_C(0), sizeof(*pvd), pvd)) {
 | 
			
		||||
		log_very_verbose("Failed to read PV data from %s",
 | 
			
		||||
				 dev_name(dev));
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -157,7 +155,7 @@ static int _read_pvd(struct device *dev, struct pv_disk *pvd)
 | 
			
		||||
 | 
			
		||||
static int _read_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
 | 
			
		||||
{
 | 
			
		||||
	if (dev_read(dev, pos, sizeof(*disk), disk) != sizeof(*disk))
 | 
			
		||||
	if (!dev_read(dev, pos, sizeof(*disk), disk))
 | 
			
		||||
		fail;
 | 
			
		||||
 | 
			
		||||
	_xlate_lvd(disk);
 | 
			
		||||
@@ -169,7 +167,7 @@ static int _read_vgd(struct disk_list *data)
 | 
			
		||||
{
 | 
			
		||||
	struct vg_disk *vgd = &data->vgd;
 | 
			
		||||
	uint64_t pos = data->pvd.vg_on_disk.base;
 | 
			
		||||
	if (dev_read(data->dev, pos, sizeof(*vgd), vgd) != sizeof(*vgd))
 | 
			
		||||
	if (!dev_read(data->dev, pos, sizeof(*vgd), vgd))
 | 
			
		||||
		fail;
 | 
			
		||||
 | 
			
		||||
	_xlate_vgd(vgd);
 | 
			
		||||
@@ -186,8 +184,7 @@ static int _read_uuids(struct disk_list *data)
 | 
			
		||||
	uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size;
 | 
			
		||||
 | 
			
		||||
	while (pos < end && num_read < data->vgd.pv_cur) {
 | 
			
		||||
		if (dev_read(data->dev, pos, sizeof(buffer), buffer) !=
 | 
			
		||||
		    sizeof(buffer))
 | 
			
		||||
		if (!dev_read(data->dev, pos, sizeof(buffer), buffer))
 | 
			
		||||
			fail;
 | 
			
		||||
 | 
			
		||||
		if (!(ul = pool_alloc(data->mem, sizeof(*ul))))
 | 
			
		||||
@@ -246,7 +243,7 @@ static int _read_extents(struct disk_list *data)
 | 
			
		||||
	if (!extents)
 | 
			
		||||
		fail;
 | 
			
		||||
 | 
			
		||||
	if (dev_read(data->dev, pos, len, extents) != len)
 | 
			
		||||
	if (!dev_read(data->dev, pos, len, extents))
 | 
			
		||||
		fail;
 | 
			
		||||
 | 
			
		||||
	_xlate_extents(extents, data->pvd.pe_total);
 | 
			
		||||
@@ -281,7 +278,7 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
 | 
			
		||||
{
 | 
			
		||||
	struct disk_list *dl = pool_alloc(mem, sizeof(*dl));
 | 
			
		||||
	const char *name = dev_name(dev);
 | 
			
		||||
	struct cache_info *info;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
 | 
			
		||||
	if (!dl) {
 | 
			
		||||
		stack;
 | 
			
		||||
@@ -298,8 +295,8 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(info = cache_add(fmt->labeller, dl->pvd.pv_uuid, dev,
 | 
			
		||||
			       dl->pvd.vg_name, NULL)))
 | 
			
		||||
	if (!(info = lvmcache_add(fmt->labeller, dl->pvd.pv_uuid, dev,
 | 
			
		||||
				  dl->pvd.vg_name, NULL)))
 | 
			
		||||
		stack;
 | 
			
		||||
	else {
 | 
			
		||||
		info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT;
 | 
			
		||||
@@ -367,7 +364,7 @@ struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
 | 
			
		||||
{
 | 
			
		||||
	struct disk_list *r;
 | 
			
		||||
 | 
			
		||||
	if (!dev_open(dev, O_RDONLY)) {
 | 
			
		||||
	if (!dev_open(dev)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
@@ -417,13 +414,13 @@ int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
	struct disk_list *data = NULL;
 | 
			
		||||
	struct list *vgih;
 | 
			
		||||
	struct cache_vginfo *vginfo;
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
 | 
			
		||||
	/* Fast path if we already saw this VG and cached the list of PVs */
 | 
			
		||||
	if (vg_name && (vginfo = vginfo_from_vgname(vg_name)) &&
 | 
			
		||||
	    vginfo->infos.n) {
 | 
			
		||||
		list_iterate(vgih, &vginfo->infos) {
 | 
			
		||||
			dev = list_item(vgih, struct cache_info)->dev;
 | 
			
		||||
			dev = list_item(vgih, struct lvmcache_info)->dev;
 | 
			
		||||
			if (dev && !(data = read_disk(fmt, dev, mem, vg_name)))
 | 
			
		||||
				break;
 | 
			
		||||
			_add_pv_to_list(head, data);
 | 
			
		||||
@@ -465,7 +462,7 @@ static int _write_vgd(struct disk_list *data)
 | 
			
		||||
	uint64_t pos = data->pvd.vg_on_disk.base;
 | 
			
		||||
 | 
			
		||||
	_xlate_vgd(vgd);
 | 
			
		||||
	if (dev_write(data->dev, pos, sizeof(*vgd), vgd) != sizeof(*vgd))
 | 
			
		||||
	if (!dev_write(data->dev, pos, sizeof(*vgd), vgd))
 | 
			
		||||
		fail;
 | 
			
		||||
 | 
			
		||||
	_xlate_vgd(vgd);
 | 
			
		||||
@@ -488,7 +485,7 @@ static int _write_uuids(struct disk_list *data)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ul = list_item(uh, struct uuid_list);
 | 
			
		||||
		if (dev_write(data->dev, pos, NAME_LEN, ul->uuid) != NAME_LEN)
 | 
			
		||||
		if (!dev_write(data->dev, pos, NAME_LEN, ul->uuid))
 | 
			
		||||
			fail;
 | 
			
		||||
 | 
			
		||||
		pos += NAME_LEN;
 | 
			
		||||
@@ -500,7 +497,7 @@ static int _write_uuids(struct disk_list *data)
 | 
			
		||||
static int _write_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
 | 
			
		||||
{
 | 
			
		||||
	_xlate_lvd(disk);
 | 
			
		||||
	if (dev_write(dev, pos, sizeof(*disk), disk) != sizeof(*disk))
 | 
			
		||||
	if (!dev_write(dev, pos, sizeof(*disk), disk))
 | 
			
		||||
		fail;
 | 
			
		||||
 | 
			
		||||
	_xlate_lvd(disk);
 | 
			
		||||
@@ -544,7 +541,7 @@ static int _write_extents(struct disk_list *data)
 | 
			
		||||
	uint64_t pos = data->pvd.pe_on_disk.base;
 | 
			
		||||
 | 
			
		||||
	_xlate_extents(extents, data->pvd.pe_total);
 | 
			
		||||
	if (dev_write(data->dev, pos, len, extents) != len)
 | 
			
		||||
	if (!dev_write(data->dev, pos, len, extents))
 | 
			
		||||
		fail;
 | 
			
		||||
 | 
			
		||||
	_xlate_extents(extents, data->pvd.pe_total);
 | 
			
		||||
@@ -576,7 +573,7 @@ static int _write_pvd(struct disk_list *data)
 | 
			
		||||
	memcpy(buf, &data->pvd, sizeof(struct pv_disk));
 | 
			
		||||
 | 
			
		||||
	_xlate_pvd((struct pv_disk *) buf);
 | 
			
		||||
	if (dev_write(data->dev, pos, size, buf) != size) {
 | 
			
		||||
	if (!dev_write(data->dev, pos, size, buf)) {
 | 
			
		||||
		dbg_free(buf);
 | 
			
		||||
		fail;
 | 
			
		||||
	}
 | 
			
		||||
@@ -642,7 +639,7 @@ static int _write_all_pvd(const struct format_type *fmt, struct disk_list *data)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	if (!dev_open(data->dev, O_WRONLY)) {
 | 
			
		||||
	if (!dev_open(data->dev)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
#include "list.h"
 | 
			
		||||
#include "display.h"
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
#include "cache.h"
 | 
			
		||||
#include "lvmcache.h"
 | 
			
		||||
#include "lvm1-label.h"
 | 
			
		||||
#include "format1.h"
 | 
			
		||||
 | 
			
		||||
@@ -248,7 +248,7 @@ static int _vg_write(struct format_instance *fid, struct volume_group *vg,
 | 
			
		||||
			 fid->fmt->cmd->filter) &&
 | 
			
		||||
	     write_disks(fid->fmt, &pvds));
 | 
			
		||||
 | 
			
		||||
	cache_update_vg(vg);
 | 
			
		||||
	lvmcache_update_vg(vg);
 | 
			
		||||
	pool_destroy(mem);
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
@@ -381,10 +381,10 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
 | 
			
		||||
	struct disk_list *dl;
 | 
			
		||||
	struct list pvs;
 | 
			
		||||
	struct label *label;
 | 
			
		||||
	struct cache_info *info;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
 | 
			
		||||
	if (!(info = cache_add(fmt->labeller, (char *) &pv->id, pv->dev,
 | 
			
		||||
			       pv->vg_name, NULL))) {
 | 
			
		||||
	if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
 | 
			
		||||
				  pv->vg_name, NULL))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -533,6 +533,7 @@ static struct format_handler _format1_ops = {
 | 
			
		||||
#ifdef LVM1_INTERNAL
 | 
			
		||||
struct format_type *init_lvm1_format(struct cmd_context *cmd)
 | 
			
		||||
#else				/* Shared */
 | 
			
		||||
struct format_type *init_format(struct cmd_context *cmd);
 | 
			
		||||
struct format_type *init_format(struct cmd_context *cmd)
 | 
			
		||||
#endif
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@
 | 
			
		||||
#include "label.h"
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
#include "xlate.h"
 | 
			
		||||
#include "cache.h"
 | 
			
		||||
#include "lvmcache.h"
 | 
			
		||||
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
@@ -49,9 +49,9 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
 | 
			
		||||
		 struct label **label)
 | 
			
		||||
{
 | 
			
		||||
	struct pv_disk *pvd = (struct pv_disk *) buf;
 | 
			
		||||
	struct cache_info *info;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
 | 
			
		||||
	if (!(info = cache_add(l, pvd->pv_uuid, dev, pvd->vg_name, NULL)))
 | 
			
		||||
	if (!(info = lvmcache_add(l, pvd->pv_uuid, dev, pvd->vg_name, NULL)))
 | 
			
		||||
		return 0;
 | 
			
		||||
	*label = info->label;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@
 | 
			
		||||
#include "crc.h"
 | 
			
		||||
#include "xlate.h"
 | 
			
		||||
#include "label.h"
 | 
			
		||||
#include "memlock.h"
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <sys/file.h>
 | 
			
		||||
@@ -107,8 +108,7 @@ static struct mda_header *_raw_read_mda_header(const struct format_type *fmt,
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (dev_read(dev_area->dev, dev_area->start, MDA_HEADER_SIZE, mdah) !=
 | 
			
		||||
	    MDA_HEADER_SIZE) {
 | 
			
		||||
	if (!dev_read(dev_area->dev, dev_area->start, MDA_HEADER_SIZE, mdah)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		pool_free(fmt->cmd->mem, mdah);
 | 
			
		||||
		return NULL;
 | 
			
		||||
@@ -156,8 +156,7 @@ static int _raw_write_mda_header(const struct format_type *fmt,
 | 
			
		||||
					     MDA_HEADER_SIZE -
 | 
			
		||||
					     sizeof(mdah->checksum_xl)));
 | 
			
		||||
 | 
			
		||||
	if (dev_write(dev, start_byte, MDA_HEADER_SIZE, mdah)
 | 
			
		||||
	    != MDA_HEADER_SIZE) {
 | 
			
		||||
	if (!dev_write(dev, start_byte, MDA_HEADER_SIZE, mdah)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		pool_free(fmt->cmd->mem, mdah);
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -178,9 +177,8 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
 | 
			
		||||
 | 
			
		||||
	/* FIXME Ignore if checksum incorrect!!! */
 | 
			
		||||
	while (rlocn->offset) {
 | 
			
		||||
		if (dev_read(dev_area->dev, dev_area->start + rlocn->offset,
 | 
			
		||||
			     sizeof(vgnamebuf), vgnamebuf)
 | 
			
		||||
		    != sizeof(vgnamebuf)) {
 | 
			
		||||
		if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
 | 
			
		||||
			      sizeof(vgnamebuf), vgnamebuf)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
@@ -214,7 +212,7 @@ static int _raw_holds_vgname(struct format_instance *fid,
 | 
			
		||||
{
 | 
			
		||||
	int r = 0;
 | 
			
		||||
 | 
			
		||||
	if (!dev_open(dev_area->dev, O_RDONLY)) {
 | 
			
		||||
	if (!dev_open(dev_area->dev)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -239,7 +237,7 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
 | 
			
		||||
	char *desc;
 | 
			
		||||
	uint32_t wrap = 0;
 | 
			
		||||
 | 
			
		||||
	if (!dev_open(area->dev, O_RDONLY)) {
 | 
			
		||||
	if (!dev_open(area->dev)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
@@ -264,8 +262,7 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* FIXME 64-bit */
 | 
			
		||||
	if (!(vg = text_vg_import_fd(fid, dev_name(area->dev),
 | 
			
		||||
				     dev_fd(area->dev),
 | 
			
		||||
	if (!(vg = text_vg_import_fd(fid, NULL, area->dev,
 | 
			
		||||
				     (off_t) (area->start + rlocn->offset),
 | 
			
		||||
				     (uint32_t) (rlocn->size - wrap),
 | 
			
		||||
				     (off_t) (area->start + MDA_HEADER_SIZE),
 | 
			
		||||
@@ -274,6 +271,9 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
 | 
			
		||||
		stack;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
	log_debug("Read %s metadata (%u) from %s at %" PRIu64 " size %" PRIu64,
 | 
			
		||||
		  vg->name, vg->seqno, dev_name(area->dev),
 | 
			
		||||
		  area->start + rlocn->offset, rlocn->size);
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	if (!dev_close(area->dev))
 | 
			
		||||
@@ -318,7 +318,7 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
 | 
			
		||||
	if (!found)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (!dev_open(mdac->area.dev, O_RDWR)) {
 | 
			
		||||
	if (!dev_open(mdac->area.dev)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -367,9 +367,8 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
 | 
			
		||||
		  mdac->rlocn.offset, mdac->rlocn.size - new_wrap);
 | 
			
		||||
 | 
			
		||||
	/* Write text out, circularly */
 | 
			
		||||
	if (dev_write(mdac->area.dev, mdac->area.start + mdac->rlocn.offset,
 | 
			
		||||
		      (size_t) (mdac->rlocn.size - new_wrap),
 | 
			
		||||
		      buf) != mdac->rlocn.size - new_wrap) {
 | 
			
		||||
	if (!dev_write(mdac->area.dev, mdac->area.start + mdac->rlocn.offset,
 | 
			
		||||
		       (size_t) (mdac->rlocn.size - new_wrap), buf)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
@@ -379,11 +378,10 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
 | 
			
		||||
			  dev_name(mdac->area.dev), mdac->area.start +
 | 
			
		||||
			  MDA_HEADER_SIZE, new_wrap);
 | 
			
		||||
 | 
			
		||||
		if (dev_write(mdac->area.dev,
 | 
			
		||||
			      mdac->area.start + MDA_HEADER_SIZE,
 | 
			
		||||
			      (size_t) new_wrap,
 | 
			
		||||
			      buf + mdac->rlocn.size - new_wrap)
 | 
			
		||||
		    != new_wrap) {
 | 
			
		||||
		if (!dev_write(mdac->area.dev,
 | 
			
		||||
			       mdac->area.start + MDA_HEADER_SIZE,
 | 
			
		||||
			       (size_t) new_wrap,
 | 
			
		||||
			       buf + mdac->rlocn.size - new_wrap)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
@@ -400,7 +398,7 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
 | 
			
		||||
	r = 1;
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	if (!dev_close(mdac->area.dev))
 | 
			
		||||
	if (!r && !dev_close(mdac->area.dev))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
@@ -429,11 +427,6 @@ static int _vg_commit_raw(struct format_instance *fid, struct volume_group *vg,
 | 
			
		||||
	if (!found)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (!dev_open(mdac->area.dev, O_RDWR)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(mdah = _raw_read_mda_header(fid->fmt, &mdac->area))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto out;
 | 
			
		||||
@@ -466,6 +459,33 @@ static int _vg_commit_raw(struct format_instance *fid, struct volume_group *vg,
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Close metadata area devices */
 | 
			
		||||
static int _vg_revert_raw(struct format_instance *fid, struct volume_group *vg,
 | 
			
		||||
			  struct metadata_area *mda)
 | 
			
		||||
{
 | 
			
		||||
	struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
 | 
			
		||||
	struct physical_volume *pv;
 | 
			
		||||
	struct list *pvh;
 | 
			
		||||
	int found = 0;
 | 
			
		||||
 | 
			
		||||
	/* Ignore any mda on a PV outside the VG. vgsplit relies on this */
 | 
			
		||||
	list_iterate(pvh, &vg->pvs) {
 | 
			
		||||
		pv = list_item(pvh, struct pv_list)->pv;
 | 
			
		||||
		if (pv->dev == mdac->area.dev) {
 | 
			
		||||
			found = 1;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!found)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (!dev_close(mdac->area.dev))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _vg_remove_raw(struct format_instance *fid, struct volume_group *vg,
 | 
			
		||||
			  struct metadata_area *mda)
 | 
			
		||||
{
 | 
			
		||||
@@ -474,7 +494,7 @@ static int _vg_remove_raw(struct format_instance *fid, struct volume_group *vg,
 | 
			
		||||
	struct raw_locn *rlocn;
 | 
			
		||||
	int r = 0;
 | 
			
		||||
 | 
			
		||||
	if (!dev_open(mdac->area.dev, O_RDWR)) {
 | 
			
		||||
	if (!dev_open(mdac->area.dev)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -735,7 +755,7 @@ static int _scan_file(const struct format_type *fmt)
 | 
			
		||||
				fid = _create_text_instance(fmt, NULL, NULL);
 | 
			
		||||
				if ((vg = _vg_read_file_name(fid, vgname,
 | 
			
		||||
							     path)))
 | 
			
		||||
					cache_update_vg(vg);
 | 
			
		||||
					lvmcache_update_vg(vg);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		if (closedir(d))
 | 
			
		||||
@@ -750,13 +770,10 @@ int vgname_from_mda(const struct format_type *fmt, struct device_area *dev_area,
 | 
			
		||||
{
 | 
			
		||||
	struct raw_locn *rlocn;
 | 
			
		||||
	struct mda_header *mdah;
 | 
			
		||||
	int already_open;
 | 
			
		||||
	unsigned int len;
 | 
			
		||||
	int r = 0;
 | 
			
		||||
 | 
			
		||||
	already_open = dev_is_open(dev_area->dev);
 | 
			
		||||
 | 
			
		||||
	if (!already_open && !dev_open(dev_area->dev, O_RDONLY)) {
 | 
			
		||||
	if (!dev_open(dev_area->dev)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -769,8 +786,8 @@ int vgname_from_mda(const struct format_type *fmt, struct device_area *dev_area,
 | 
			
		||||
	rlocn = mdah->raw_locns;
 | 
			
		||||
 | 
			
		||||
	while (rlocn->offset) {
 | 
			
		||||
		if (dev_read(dev_area->dev, dev_area->start + rlocn->offset,
 | 
			
		||||
			     size, buf) != (signed) size) {
 | 
			
		||||
		if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
 | 
			
		||||
			      size, buf)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
@@ -781,7 +798,7 @@ int vgname_from_mda(const struct format_type *fmt, struct device_area *dev_area,
 | 
			
		||||
		buf[len] = '\0';
 | 
			
		||||
 | 
			
		||||
		/* Ignore this entry if the characters aren't permissible */
 | 
			
		||||
		if (!validate_vgname(buf)) {
 | 
			
		||||
		if (!validate_name(buf)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
@@ -794,7 +811,7 @@ int vgname_from_mda(const struct format_type *fmt, struct device_area *dev_area,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	if (!already_open && dev_close(dev_area->dev))
 | 
			
		||||
	if (!dev_close(dev_area->dev))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
@@ -821,7 +838,7 @@ static int _scan_raw(const struct format_type *fmt)
 | 
			
		||||
				    sizeof(vgnamebuf))) {
 | 
			
		||||
			if ((vg = _vg_read_raw_area(&fid, vgnamebuf,
 | 
			
		||||
						    &rl->dev_area)))
 | 
			
		||||
				cache_update_vg(vg);
 | 
			
		||||
				lvmcache_update_vg(vg);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -957,7 +974,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
 | 
			
		||||
		     struct list *mdas, int64_t label_sector)
 | 
			
		||||
{
 | 
			
		||||
	struct label *label;
 | 
			
		||||
	struct cache_info *info;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
	struct mda_context *mdac;
 | 
			
		||||
	struct list *mdash;
 | 
			
		||||
	struct metadata_area *mda;
 | 
			
		||||
@@ -967,8 +984,8 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
 | 
			
		||||
 | 
			
		||||
	/* FIXME Test mode don't update cache? */
 | 
			
		||||
 | 
			
		||||
	if (!(info = cache_add(fmt->labeller, (char *) &pv->id, pv->dev,
 | 
			
		||||
			       ORPHAN, NULL))) {
 | 
			
		||||
	if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
 | 
			
		||||
				  ORPHAN, NULL))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -1027,12 +1044,12 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
 | 
			
		||||
	}
 | 
			
		||||
	if (!add_da
 | 
			
		||||
	    (fmt, NULL, &info->das, pv->pe_start << SECTOR_SHIFT,
 | 
			
		||||
	     __UINT64_C(0))) {
 | 
			
		||||
	     UINT64_C(0))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dev_open(pv->dev, O_RDWR)) {
 | 
			
		||||
	if (!dev_open(pv->dev)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -1118,7 +1135,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
 | 
			
		||||
{
 | 
			
		||||
	struct label *label;
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
	struct cache_info *info;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
	struct metadata_area *mda, *mda_new;
 | 
			
		||||
	struct mda_context *mdac, *mdac_new;
 | 
			
		||||
	struct list *mdah, *dah;
 | 
			
		||||
@@ -1134,7 +1151,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	info = (struct cache_info *) label->info;
 | 
			
		||||
	info = (struct lvmcache_info *) label->info;
 | 
			
		||||
 | 
			
		||||
	/* Have we already cached vgname? */
 | 
			
		||||
	if (info->vginfo && info->vginfo->vgname && *info->vginfo->vgname &&
 | 
			
		||||
@@ -1144,12 +1161,15 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Perform full scan and try again */
 | 
			
		||||
	cache_label_scan(fmt->cmd, 0);
 | 
			
		||||
	if (!memlock()) {
 | 
			
		||||
		lvmcache_label_scan(fmt->cmd, 1);
 | 
			
		||||
 | 
			
		||||
	if (info->vginfo && info->vginfo->vgname && *info->vginfo->vgname &&
 | 
			
		||||
	    _get_pv_from_vg(info->fmt, info->vginfo->vgname, info->dev->pvid,
 | 
			
		||||
			    pv)) {
 | 
			
		||||
		return 1;
 | 
			
		||||
		if (info->vginfo && info->vginfo->vgname &&
 | 
			
		||||
		    *info->vginfo->vgname &&
 | 
			
		||||
		    _get_pv_from_vg(info->fmt, info->vginfo->vgname,
 | 
			
		||||
				    info->dev->pvid, pv)) {
 | 
			
		||||
			return 1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Orphan */
 | 
			
		||||
@@ -1248,7 +1268,8 @@ static struct metadata_area_ops _metadata_text_raw_ops = {
 | 
			
		||||
	vg_read:_vg_read_raw,
 | 
			
		||||
	vg_write:_vg_write_raw,
 | 
			
		||||
	vg_remove:_vg_remove_raw,
 | 
			
		||||
	vg_commit:_vg_commit_raw
 | 
			
		||||
	vg_commit:_vg_commit_raw,
 | 
			
		||||
	vg_revert:_vg_revert_raw
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* pvmetadatasize in sectors */
 | 
			
		||||
@@ -1262,7 +1283,7 @@ static int _pv_setup(const struct format_type *fmt,
 | 
			
		||||
	struct metadata_area *mda, *mda_new, *mda2;
 | 
			
		||||
	struct mda_context *mdac, *mdac_new, *mdac2;
 | 
			
		||||
	struct list *pvmdas, *pvmdash, *mdash;
 | 
			
		||||
	struct cache_info *info;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
	int found;
 | 
			
		||||
	uint64_t pe_end = 0;
 | 
			
		||||
 | 
			
		||||
@@ -1354,7 +1375,7 @@ static struct format_instance *_create_text_instance(const struct format_type
 | 
			
		||||
	struct raw_list *rl;
 | 
			
		||||
	struct list *dlh, *dir_list, *rlh, *raw_list, *mdas, *mdash, *infoh;
 | 
			
		||||
	char path[PATH_MAX];
 | 
			
		||||
	struct cache_vginfo *vginfo;
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
 | 
			
		||||
	if (!(fid = pool_alloc(fmt->cmd->mem, sizeof(*fid)))) {
 | 
			
		||||
		log_error("Couldn't allocate format instance object.");
 | 
			
		||||
@@ -1422,13 +1443,13 @@ static struct format_instance *_create_text_instance(const struct format_type
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Scan PVs in VG for any further MDAs */
 | 
			
		||||
		cache_label_scan(fmt->cmd, 0);
 | 
			
		||||
		lvmcache_label_scan(fmt->cmd, 0);
 | 
			
		||||
		if (!(vginfo = vginfo_from_vgname(vgname))) {
 | 
			
		||||
			stack;
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		list_iterate(infoh, &vginfo->infos) {
 | 
			
		||||
			mdas = &(list_item(infoh, struct cache_info)->mdas);
 | 
			
		||||
			mdas = &(list_item(infoh, struct lvmcache_info)->mdas);
 | 
			
		||||
			list_iterate(mdash, mdas) {
 | 
			
		||||
				mda = list_item(mdash, struct metadata_area);
 | 
			
		||||
				mdac =
 | 
			
		||||
 
 | 
			
		||||
@@ -54,7 +54,7 @@ struct volume_group *text_vg_import_file(struct format_instance *fid,
 | 
			
		||||
					 time_t *when, char **desc);
 | 
			
		||||
struct volume_group *text_vg_import_fd(struct format_instance *fid,
 | 
			
		||||
				       const char *file,
 | 
			
		||||
				       int fd,
 | 
			
		||||
				       struct device *dev,
 | 
			
		||||
				       off_t offset, uint32_t size,
 | 
			
		||||
				       off_t offset2, uint32_t size2,
 | 
			
		||||
				       checksum_fn_t checksum_fn,
 | 
			
		||||
 
 | 
			
		||||
@@ -11,14 +11,14 @@
 | 
			
		||||
#include "display.h"
 | 
			
		||||
#include "hash.h"
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
#include "cache.h"
 | 
			
		||||
#include "lvmcache.h"
 | 
			
		||||
 | 
			
		||||
/* FIXME Use tidier inclusion method */
 | 
			
		||||
static struct text_vg_version_ops *(_text_vsn_list[2]);
 | 
			
		||||
 | 
			
		||||
struct volume_group *text_vg_import_fd(struct format_instance *fid,
 | 
			
		||||
				       const char *file,
 | 
			
		||||
				       int fd,
 | 
			
		||||
				       struct device *dev,
 | 
			
		||||
				       off_t offset, uint32_t size,
 | 
			
		||||
				       off_t offset2, uint32_t size2,
 | 
			
		||||
				       checksum_fn_t checksum_fn,
 | 
			
		||||
@@ -45,10 +45,9 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((fd == -1 && !read_config_file(cf, file)) ||
 | 
			
		||||
	    (fd != -1 && !read_config_fd(cf, fd, file, offset, size,
 | 
			
		||||
					 offset2, size2, checksum_fn,
 | 
			
		||||
					 checksum))) {
 | 
			
		||||
	if ((!dev && !read_config_file(cf, file)) ||
 | 
			
		||||
	    (dev && !read_config_fd(cf, dev, offset, size,
 | 
			
		||||
				    offset2, size2, checksum_fn, checksum))) {
 | 
			
		||||
		log_error("Couldn't read volume group metadata.");
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
@@ -78,6 +77,6 @@ struct volume_group *text_vg_import_file(struct format_instance *fid,
 | 
			
		||||
					 const char *file,
 | 
			
		||||
					 time_t *when, char **desc)
 | 
			
		||||
{
 | 
			
		||||
	return text_vg_import_fd(fid, file, -1, 0, 0, 0, 0, NULL, 0,
 | 
			
		||||
	return text_vg_import_fd(fid, file, NULL, 0, 0, 0, 0, NULL, 0,
 | 
			
		||||
				 when, desc);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
#include "display.h"
 | 
			
		||||
#include "hash.h"
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
#include "cache.h"
 | 
			
		||||
#include "lvmcache.h"
 | 
			
		||||
 | 
			
		||||
typedef int (*section_fn) (struct format_instance * fid, struct pool * mem,
 | 
			
		||||
			   struct volume_group * vg, struct config_node * pvn,
 | 
			
		||||
@@ -215,15 +215,15 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
 | 
			
		||||
			 struct hash_table *pv_hash)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int s;
 | 
			
		||||
	uint32_t stripes = 0;
 | 
			
		||||
	uint32_t area_count = 0;
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
	struct config_node *cn;
 | 
			
		||||
	struct config_value *cv;
 | 
			
		||||
	const char *seg_name = sn->key;
 | 
			
		||||
	uint32_t start_extent, extent_count;
 | 
			
		||||
	uint32_t chunk_size;
 | 
			
		||||
	uint32_t chunk_size, extents_moved = 0u, seg_status = 0u;
 | 
			
		||||
	const char *org_name, *cow_name;
 | 
			
		||||
	struct logical_volume *org, *cow;
 | 
			
		||||
	struct logical_volume *org, *cow, *lv1;
 | 
			
		||||
	segment_type_t segtype;
 | 
			
		||||
 | 
			
		||||
	if (!(sn = sn->child)) {
 | 
			
		||||
@@ -254,15 +254,33 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (segtype == SEG_STRIPED) {
 | 
			
		||||
		if (!_read_int32(sn, "stripe_count", &stripes)) {
 | 
			
		||||
		if (!_read_int32(sn, "stripe_count", &area_count)) {
 | 
			
		||||
			log_error("Couldn't read 'stripe_count' for "
 | 
			
		||||
				  "segment '%s'.", sn->key);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (segtype == SEG_MIRRORED) {
 | 
			
		||||
		if (!_read_int32(sn, "mirror_count", &area_count)) {
 | 
			
		||||
			log_error("Couldn't read 'mirror_count' for "
 | 
			
		||||
				  "segment '%s'.", sn->key);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (find_config_node(sn, "extents_moved", '/')) {
 | 
			
		||||
			if (_read_uint32(sn, "extents_moved", &extents_moved))
 | 
			
		||||
				seg_status |= PVMOVE;
 | 
			
		||||
			else {
 | 
			
		||||
				log_error("Couldn't read 'extents_moved' for "
 | 
			
		||||
					  "segment '%s'.", sn->key);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(seg = pool_zalloc(mem, sizeof(*seg) +
 | 
			
		||||
				(sizeof(seg->area[0]) * stripes)))) {
 | 
			
		||||
				(sizeof(seg->area[0]) * area_count)))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -270,9 +288,12 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
 | 
			
		||||
	seg->lv = lv;
 | 
			
		||||
	seg->le = start_extent;
 | 
			
		||||
	seg->len = extent_count;
 | 
			
		||||
	seg->area_len = extent_count;
 | 
			
		||||
	seg->type = segtype;
 | 
			
		||||
	seg->status = seg_status;
 | 
			
		||||
	seg->extents_moved = extents_moved;
 | 
			
		||||
 | 
			
		||||
	switch (segtype) {
 | 
			
		||||
	case SEG_MIRROR:
 | 
			
		||||
	case SEG_SNAPSHOT:
 | 
			
		||||
		lv->status |= SNAPSHOT;
 | 
			
		||||
 | 
			
		||||
@@ -316,15 +337,7 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case SEG_STRIPED:
 | 
			
		||||
		seg->stripes = stripes;
 | 
			
		||||
 | 
			
		||||
		if (!seg->stripes) {
 | 
			
		||||
			log_error("Zero stripes *not* allowed for segment '%s'",
 | 
			
		||||
				  sn->key);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if ((seg->stripes != 1) &&
 | 
			
		||||
		if ((area_count != 1) &&
 | 
			
		||||
		    !_read_int32(sn, "stripe_size", &seg->stripe_size)) {
 | 
			
		||||
			log_error("Couldn't read stripe_size for segment '%s'.",
 | 
			
		||||
				  sn->key);
 | 
			
		||||
@@ -337,55 +350,78 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for (cv = cn->v, s = 0; cv && s < seg->stripes;
 | 
			
		||||
		seg->area_len /= area_count;
 | 
			
		||||
 | 
			
		||||
	case SEG_MIRRORED:
 | 
			
		||||
		seg->area_count = area_count;
 | 
			
		||||
 | 
			
		||||
		if (!seg->area_count) {
 | 
			
		||||
			log_error("Zero areas not allowed for segment '%s'",
 | 
			
		||||
				  sn->key);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if ((seg->type == SEG_MIRRORED) &&
 | 
			
		||||
		    !(cn = find_config_node(sn, "mirrors", '/'))) {
 | 
			
		||||
			log_error("Couldn't find mirrors array for segment "
 | 
			
		||||
				  "'%s'.", sn->key);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for (cv = cn->v, s = 0; cv && s < seg->area_count;
 | 
			
		||||
		     s++, cv = cv->next) {
 | 
			
		||||
 | 
			
		||||
			/* first we read the pv */
 | 
			
		||||
			const char *bad = "Badly formed areas array for "
 | 
			
		||||
			    "segment '%s'.";
 | 
			
		||||
			struct physical_volume *pv;
 | 
			
		||||
			uint32_t allocated;
 | 
			
		||||
 | 
			
		||||
			if (cv->type != CFG_STRING) {
 | 
			
		||||
				log_error(bad, sn->key);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (!(pv = hash_lookup(pv_hash, cv->v.str))) {
 | 
			
		||||
				log_error("Couldn't find physical volume '%s' "
 | 
			
		||||
			if (!cv->next) {
 | 
			
		||||
				log_error(bad, sn->key);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (cv->next->type != CFG_INT) {
 | 
			
		||||
				log_error(bad, sn->key);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			/* FIXME Cope if LV not yet read in */
 | 
			
		||||
			if ((pv = hash_lookup(pv_hash, cv->v.str))) {
 | 
			
		||||
				seg->area[s].type = AREA_PV;
 | 
			
		||||
				seg->area[s].u.pv.pv = pv;
 | 
			
		||||
				seg->area[s].u.pv.pe = cv->next->v.i;
 | 
			
		||||
				/*
 | 
			
		||||
				 * Adjust extent counts in the pv and vg.
 | 
			
		||||
				 */
 | 
			
		||||
				pv->pe_alloc_count += seg->area_len;
 | 
			
		||||
				vg->free_count -= seg->area_len;
 | 
			
		||||
 | 
			
		||||
			} else if ((lv1 = find_lv(vg, cv->v.str))) {
 | 
			
		||||
				seg->area[s].type = AREA_LV;
 | 
			
		||||
				seg->area[s].u.lv.lv = lv1;
 | 
			
		||||
				seg->area[s].u.lv.le = cv->next->v.i;
 | 
			
		||||
			} else {
 | 
			
		||||
				log_error("Couldn't find volume '%s' "
 | 
			
		||||
					  "for segment '%s'.",
 | 
			
		||||
					  cv->v.str ? cv->v.str : "NULL",
 | 
			
		||||
					  seg_name);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			seg->area[s].pv = pv;
 | 
			
		||||
 | 
			
		||||
			if (!(cv = cv->next)) {
 | 
			
		||||
				log_error(bad, sn->key);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (cv->type != CFG_INT) {
 | 
			
		||||
				log_error(bad, sn->key);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			seg->area[s].pe = cv->v.i;
 | 
			
		||||
 | 
			
		||||
			/*
 | 
			
		||||
			   * Adjust the extent counts in the pv and vg.
 | 
			
		||||
			 */
 | 
			
		||||
			allocated = seg->len / seg->stripes;
 | 
			
		||||
			pv->pe_alloc_count += allocated;
 | 
			
		||||
			vg->free_count -= allocated;
 | 
			
		||||
			cv = cv->next;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * Check we read the correct number of stripes.
 | 
			
		||||
		 */
 | 
			
		||||
		if (cv || (s < seg->stripes)) {
 | 
			
		||||
			log_error("Incorrect number of stripes in 'area' array "
 | 
			
		||||
		if (cv || (s < seg->area_count)) {
 | 
			
		||||
			log_error("Incorrect number of areas in area array "
 | 
			
		||||
				  "for segment '%s'.", seg_name);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
@@ -456,9 +492,9 @@ static int _read_segments(struct pool *mem, struct volume_group *vg,
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _read_lv(struct format_instance *fid, struct pool *mem,
 | 
			
		||||
		    struct volume_group *vg, struct config_node *lvn,
 | 
			
		||||
		    struct config_node *vgn, struct hash_table *pv_hash)
 | 
			
		||||
static int _read_lvnames(struct format_instance *fid, struct pool *mem,
 | 
			
		||||
			 struct volume_group *vg, struct config_node *lvn,
 | 
			
		||||
			 struct config_node *vgn, struct hash_table *pv_hash)
 | 
			
		||||
{
 | 
			
		||||
	struct logical_volume *lv;
 | 
			
		||||
	struct lv_list *lvl;
 | 
			
		||||
@@ -482,17 +518,6 @@ static int _read_lv(struct format_instance *fid, struct pool *mem,
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	lv->vg = vg;
 | 
			
		||||
 | 
			
		||||
	/* FIXME: read full lvid */
 | 
			
		||||
	if (!_read_id(&lv->lvid.id[1], lvn, "id")) {
 | 
			
		||||
		log_error("Couldn't read uuid for logical volume %s.",
 | 
			
		||||
			  lv->name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memcpy(&lv->lvid.id[0], &lv->vg->id, sizeof(lv->lvid.id[0]));
 | 
			
		||||
 | 
			
		||||
	if (!(cn = find_config_node(lvn, "status", '/'))) {
 | 
			
		||||
		log_error("Couldn't find status flags for logical volume.");
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -503,12 +528,6 @@ static int _read_lv(struct format_instance *fid, struct pool *mem,
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	list_init(&lv->segments);
 | 
			
		||||
	if (!_read_segments(mem, vg, lv, lvn, pv_hash)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	lv->alloc = ALLOC_DEFAULT;
 | 
			
		||||
	if ((cn = find_config_node(lvn, "allocation_policy", '/'))) {
 | 
			
		||||
		struct config_value *cv = cn->v;
 | 
			
		||||
@@ -524,6 +543,48 @@ static int _read_lv(struct format_instance *fid, struct pool *mem,
 | 
			
		||||
	if (!_read_int32(lvn, "read_ahead", &lv->read_ahead))
 | 
			
		||||
		lv->read_ahead = 0;
 | 
			
		||||
 | 
			
		||||
	list_init(&lv->segments);
 | 
			
		||||
 | 
			
		||||
	lv->vg = vg;
 | 
			
		||||
	vg->lv_count++;
 | 
			
		||||
	list_add(&vg->lvs, &lvl->list);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _read_lvsegs(struct format_instance *fid, struct pool *mem,
 | 
			
		||||
			struct volume_group *vg, struct config_node *lvn,
 | 
			
		||||
			struct config_node *vgn, struct hash_table *pv_hash)
 | 
			
		||||
{
 | 
			
		||||
	struct logical_volume *lv;
 | 
			
		||||
	struct lv_list *lvl;
 | 
			
		||||
 | 
			
		||||
	if (!(lvl = find_lv_in_vg(vg, lvn->key))) {
 | 
			
		||||
		log_error("Lost logical volume reference %s", lvn->key);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	lv = lvl->lv;
 | 
			
		||||
 | 
			
		||||
	if (!(lvn = lvn->child)) {
 | 
			
		||||
		log_error("Empty logical volume section.");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* FIXME: read full lvid */
 | 
			
		||||
	if (!_read_id(&lv->lvid.id[1], lvn, "id")) {
 | 
			
		||||
		log_error("Couldn't read uuid for logical volume %s.",
 | 
			
		||||
			  lv->name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memcpy(&lv->lvid.id[0], &lv->vg->id, sizeof(lv->lvid.id[0]));
 | 
			
		||||
 | 
			
		||||
	if (!_read_segments(mem, vg, lv, lvn, pv_hash)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	lv->size = (uint64_t) lv->le_count * (uint64_t) vg->extent_size;
 | 
			
		||||
 | 
			
		||||
	/* Skip this for now for snapshots */
 | 
			
		||||
@@ -532,12 +593,18 @@ static int _read_lv(struct format_instance *fid, struct pool *mem,
 | 
			
		||||
		if ((lv->status & FIXED_MINOR) &&
 | 
			
		||||
		    !_read_int32(lvn, "minor", &lv->minor)) {
 | 
			
		||||
			log_error("Couldn't read minor number for logical "
 | 
			
		||||
				  "volume.");
 | 
			
		||||
				  "volume %s.", lv->name);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		vg->lv_count++;
 | 
			
		||||
		list_add(&vg->lvs, &lvl->list);
 | 
			
		||||
		lv->major = -1;
 | 
			
		||||
		if ((lv->status & FIXED_MINOR) &&
 | 
			
		||||
		    !_read_int32(lvn, "major", &lv->major)) {
 | 
			
		||||
			log_error("Couldn't read major number for logical "
 | 
			
		||||
				  "volume %s.", lv->name);
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		vg->lv_count--;
 | 
			
		||||
		list_del(&lvl->list);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
@@ -681,13 +748,21 @@ static struct volume_group *_read_vg(struct format_instance *fid,
 | 
			
		||||
 | 
			
		||||
	list_init(&vg->lvs);
 | 
			
		||||
	list_init(&vg->snapshots);
 | 
			
		||||
	if (!_read_sections(fid, "logical_volumes", _read_lv, mem, vg,
 | 
			
		||||
 | 
			
		||||
	if (!_read_sections(fid, "logical_volumes", _read_lvnames, mem, vg,
 | 
			
		||||
			    vgn, pv_hash, 1)) {
 | 
			
		||||
		log_error("Couldn't read all logical volumes for volume "
 | 
			
		||||
		log_error("Couldn't read all logical volume names for volume "
 | 
			
		||||
			  "group %s.", vg->name);
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_read_sections(fid, "logical_volumes", _read_lvsegs, mem, vg,
 | 
			
		||||
			    vgn, pv_hash, 1)) {
 | 
			
		||||
		log_error("Couldn't read all logical volumes for "
 | 
			
		||||
			  "volume group %s.", vg->name);
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	hash_destroy(pv_hash);
 | 
			
		||||
 | 
			
		||||
	if (vg->status & PARTIAL_VG) {
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,7 @@ static int _write(struct label *label, char *buf)
 | 
			
		||||
{
 | 
			
		||||
	struct label_header *lh = (struct label_header *) buf;
 | 
			
		||||
	struct pv_header *pvhdr;
 | 
			
		||||
	struct cache_info *info;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
	struct disk_locn *pvh_dlocn_xl;
 | 
			
		||||
	struct list *mdash, *dash;
 | 
			
		||||
	struct metadata_area *mda;
 | 
			
		||||
@@ -40,7 +40,7 @@ static int _write(struct label *label, char *buf)
 | 
			
		||||
	strncpy(lh->type, label->type, sizeof(label->type));
 | 
			
		||||
 | 
			
		||||
	pvhdr = (struct pv_header *) ((void *) buf + xlate32(lh->offset_xl));
 | 
			
		||||
	info = (struct cache_info *) label->info;
 | 
			
		||||
	info = (struct lvmcache_info *) label->info;
 | 
			
		||||
	pvhdr->device_size_xl = xlate64(info->device_size);
 | 
			
		||||
	memcpy(pvhdr->pv_uuid, &info->dev->pvid, sizeof(struct id));
 | 
			
		||||
 | 
			
		||||
@@ -185,7 +185,7 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
 | 
			
		||||
{
 | 
			
		||||
	struct label_header *lh = (struct label_header *) buf;
 | 
			
		||||
	struct pv_header *pvhdr;
 | 
			
		||||
	struct cache_info *info;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
	struct disk_locn *dlocn_xl;
 | 
			
		||||
	uint64_t offset;
 | 
			
		||||
	struct list *mdah;
 | 
			
		||||
@@ -195,7 +195,7 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
 | 
			
		||||
 | 
			
		||||
	pvhdr = (struct pv_header *) ((void *) buf + xlate32(lh->offset_xl));
 | 
			
		||||
 | 
			
		||||
	if (!(info = cache_add(l, pvhdr->pv_uuid, dev, NULL, NULL)))
 | 
			
		||||
	if (!(info = lvmcache_add(l, pvhdr->pv_uuid, dev, NULL, NULL)))
 | 
			
		||||
		return 0;
 | 
			
		||||
	*label = info->label;
 | 
			
		||||
 | 
			
		||||
@@ -230,7 +230,7 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
 | 
			
		||||
		mdac = (struct mda_context *) mda->metadata_locn;
 | 
			
		||||
		if (vgname_from_mda(info->fmt, &mdac->area, vgnamebuf,
 | 
			
		||||
				    sizeof(vgnamebuf))) {
 | 
			
		||||
			cache_update_vgname(info, vgnamebuf);
 | 
			
		||||
			lvmcache_update_vgname(info, vgnamebuf);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -241,7 +241,7 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
 | 
			
		||||
 | 
			
		||||
static void _destroy_label(struct labeller *l, struct label *label)
 | 
			
		||||
{
 | 
			
		||||
	struct cache_info *info = (struct cache_info *) label->info;
 | 
			
		||||
	struct lvmcache_info *info = (struct lvmcache_info *) label->info;
 | 
			
		||||
 | 
			
		||||
	if (info->mdas.n)
 | 
			
		||||
		del_mdas(&info->mdas);
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
#include "list.h"
 | 
			
		||||
#include "crc.h"
 | 
			
		||||
#include "xlate.h"
 | 
			
		||||
#include "cache.h"
 | 
			
		||||
#include "lvmcache.h"
 | 
			
		||||
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
@@ -104,21 +104,17 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
 | 
			
		||||
	struct list *lih;
 | 
			
		||||
	struct labeller_i *li;
 | 
			
		||||
	struct labeller *r = NULL;
 | 
			
		||||
	int already_open;
 | 
			
		||||
	struct label_header *lh;
 | 
			
		||||
	uint64_t sector;
 | 
			
		||||
	int found = 0;
 | 
			
		||||
	char readbuf[LABEL_SCAN_SIZE];
 | 
			
		||||
 | 
			
		||||
	already_open = dev_is_open(dev);
 | 
			
		||||
 | 
			
		||||
	if (!already_open && !dev_open(dev, O_RDONLY)) {
 | 
			
		||||
	if (!dev_open(dev)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (dev_read(dev, __UINT64_C(0), LABEL_SCAN_SIZE, readbuf) !=
 | 
			
		||||
	    LABEL_SCAN_SIZE) {
 | 
			
		||||
	if (!dev_read(dev, UINT64_C(0), LABEL_SCAN_SIZE, readbuf)) {
 | 
			
		||||
		log_debug("%s: Failed to read label area", dev_name(dev));
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
@@ -178,7 +174,7 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
 | 
			
		||||
		log_very_verbose("%s: No label detected", dev_name(dev));
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	if (!already_open && !dev_close(dev))
 | 
			
		||||
	if (!dev_close(dev))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
@@ -200,13 +196,18 @@ int label_remove(struct device *dev)
 | 
			
		||||
 | 
			
		||||
	log_very_verbose("Scanning for labels to wipe from %s", dev_name(dev));
 | 
			
		||||
 | 
			
		||||
	if (!dev_open(dev, O_RDWR)) {
 | 
			
		||||
	if (!dev_open(dev)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (dev_read(dev, __UINT64_C(0), LABEL_SCAN_SIZE, readbuf) !=
 | 
			
		||||
	    LABEL_SCAN_SIZE) {
 | 
			
		||||
	/*
 | 
			
		||||
	 * We flush the device just in case someone is stupid
 | 
			
		||||
	 * enough to be trying to import an open pv into lvm.
 | 
			
		||||
	 */
 | 
			
		||||
	dev_flush(dev);
 | 
			
		||||
 | 
			
		||||
	if (!dev_read(dev, UINT64_C(0), LABEL_SCAN_SIZE, readbuf)) {
 | 
			
		||||
		log_debug("%s: Failed to read label area", dev_name(dev));
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
@@ -236,8 +237,8 @@ int label_remove(struct device *dev)
 | 
			
		||||
		if (wipe) {
 | 
			
		||||
			log_info("%s: Wiping label at sector %" PRIu64,
 | 
			
		||||
				 dev_name(dev), sector);
 | 
			
		||||
			if (dev_write(dev, sector << SECTOR_SHIFT, LABEL_SIZE,
 | 
			
		||||
				      buf) != LABEL_SIZE) {
 | 
			
		||||
			if (!dev_write(dev, sector << SECTOR_SHIFT, LABEL_SIZE,
 | 
			
		||||
				       buf)) {
 | 
			
		||||
				log_error("Failed to remove label from %s at "
 | 
			
		||||
					  "sector %" PRIu64, dev_name(dev),
 | 
			
		||||
					  sector);
 | 
			
		||||
@@ -278,7 +279,6 @@ int label_write(struct device *dev, struct label *label)
 | 
			
		||||
	char buf[LABEL_SIZE];
 | 
			
		||||
	struct label_header *lh = (struct label_header *) buf;
 | 
			
		||||
	int r = 1;
 | 
			
		||||
	int already_open;
 | 
			
		||||
 | 
			
		||||
	if ((LABEL_SIZE + (label->sector << SECTOR_SHIFT)) > LABEL_SCAN_SIZE) {
 | 
			
		||||
		log_error("Label sector %" PRIu64 " beyond range (%ld)",
 | 
			
		||||
@@ -298,21 +298,19 @@ int label_write(struct device *dev, struct label *label)
 | 
			
		||||
	lh->crc_xl = xlate32(calc_crc(INITIAL_CRC, &lh->offset_xl, LABEL_SIZE -
 | 
			
		||||
				      ((void *) &lh->offset_xl - (void *) lh)));
 | 
			
		||||
 | 
			
		||||
	already_open = dev_is_open(dev);
 | 
			
		||||
	if (!already_open && dev_open(dev, O_RDWR)) {
 | 
			
		||||
	if (!dev_open(dev)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_info("%s: Writing label to sector %" PRIu64, dev_name(dev),
 | 
			
		||||
		 label->sector);
 | 
			
		||||
	if (dev_write(dev, label->sector << SECTOR_SHIFT, LABEL_SIZE, buf) !=
 | 
			
		||||
	    LABEL_SIZE) {
 | 
			
		||||
	if (!dev_write(dev, label->sector << SECTOR_SHIFT, LABEL_SIZE, buf)) {
 | 
			
		||||
		log_debug("Failed to write label to %s", dev_name(dev));
 | 
			
		||||
		r = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!already_open && dev_close(dev))
 | 
			
		||||
	if (!dev_close(dev))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
 
 | 
			
		||||
@@ -7,8 +7,7 @@
 | 
			
		||||
#ifndef _LVM_LABEL_H
 | 
			
		||||
#define _LVM_LABEL_H
 | 
			
		||||
 | 
			
		||||
#include "cache.h"
 | 
			
		||||
#include "lvm-types.h"
 | 
			
		||||
#include "lvmcache.h"
 | 
			
		||||
#include "uuid.h"
 | 
			
		||||
#include "device.h"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@
 | 
			
		||||
#include "defaults.h"
 | 
			
		||||
#include "lvm-file.h"
 | 
			
		||||
#include "lvm-string.h"
 | 
			
		||||
#include "lvmcache.h"
 | 
			
		||||
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
@@ -34,7 +35,7 @@ static sig_t _oldhandler;
 | 
			
		||||
static sigset_t _fullsigset, _intsigset;
 | 
			
		||||
static int _handler_installed;
 | 
			
		||||
 | 
			
		||||
static int _release_lock(const char *file)
 | 
			
		||||
static int _release_lock(const char *file, int unlock)
 | 
			
		||||
{
 | 
			
		||||
	struct lock_list *ll;
 | 
			
		||||
	struct list *llh, *llt;
 | 
			
		||||
@@ -46,10 +47,11 @@ static int _release_lock(const char *file)
 | 
			
		||||
 | 
			
		||||
		if (!file || !strcmp(ll->res, file)) {
 | 
			
		||||
			list_del(llh);
 | 
			
		||||
			log_very_verbose("Unlocking %s", ll->res);
 | 
			
		||||
 | 
			
		||||
			if (flock(ll->lf, LOCK_NB | LOCK_UN))
 | 
			
		||||
				log_sys_error("flock", ll->res);
 | 
			
		||||
			if (unlock) {
 | 
			
		||||
				log_very_verbose("Unlocking %s", ll->res);
 | 
			
		||||
				if (flock(ll->lf, LOCK_NB | LOCK_UN))
 | 
			
		||||
					log_sys_error("flock", ll->res);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (!flock(ll->lf, LOCK_NB | LOCK_EX) &&
 | 
			
		||||
			    !stat(ll->res, &buf1) &&
 | 
			
		||||
@@ -74,7 +76,12 @@ static int _release_lock(const char *file)
 | 
			
		||||
 | 
			
		||||
static void _fin_file_locking(void)
 | 
			
		||||
{
 | 
			
		||||
	_release_lock(NULL);
 | 
			
		||||
	_release_lock(NULL, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _reset_file_locking(void)
 | 
			
		||||
{
 | 
			
		||||
	_release_lock(NULL, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _remove_ctrl_c_handler()
 | 
			
		||||
@@ -127,7 +134,7 @@ static int _lock_file(const char *file, int flags)
 | 
			
		||||
		state = 'W';
 | 
			
		||||
		break;
 | 
			
		||||
	case LCK_UNLOCK:
 | 
			
		||||
		return _release_lock(file);
 | 
			
		||||
		return _release_lock(file, 1);
 | 
			
		||||
	default:
 | 
			
		||||
		log_error("Unrecognised lock type: %d", flags & LCK_TYPE_MASK);
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -196,24 +203,39 @@ static int _file_lock_resource(struct cmd_context *cmd, const char *resource,
 | 
			
		||||
		else
 | 
			
		||||
			lvm_snprintf(lockfile, sizeof(lockfile),
 | 
			
		||||
				     "%s/V_%s", _lock_dir, resource);
 | 
			
		||||
 | 
			
		||||
		if (!_lock_file(lockfile, flags))
 | 
			
		||||
			return 0;
 | 
			
		||||
 | 
			
		||||
		switch (flags & LCK_TYPE_MASK) {
 | 
			
		||||
		case LCK_UNLOCK:
 | 
			
		||||
			lvmcache_unlock_vgname(resource);
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			lvmcache_lock_vgname(resource,
 | 
			
		||||
					     (flags & LCK_TYPE_MASK) ==
 | 
			
		||||
					     LCK_READ);
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case LCK_LV:
 | 
			
		||||
		switch (flags & LCK_TYPE_MASK) {
 | 
			
		||||
		case LCK_UNLOCK:
 | 
			
		||||
			log_debug("Unlocking LV %s", resource);
 | 
			
		||||
			if (!lv_resume_if_active(cmd, resource))
 | 
			
		||||
				return 0;
 | 
			
		||||
			break;
 | 
			
		||||
		case LCK_READ:
 | 
			
		||||
			log_debug("Locking LV %s (R)", resource);
 | 
			
		||||
			if (!lv_activate(cmd, resource))
 | 
			
		||||
				return 0;
 | 
			
		||||
			break;
 | 
			
		||||
		case LCK_WRITE:
 | 
			
		||||
			log_debug("Locking LV %s (W)", resource);
 | 
			
		||||
			if (!lv_suspend_if_active(cmd, resource))
 | 
			
		||||
				return 0;
 | 
			
		||||
			break;
 | 
			
		||||
		case LCK_EXCL:
 | 
			
		||||
			log_debug("Locking LV %s (EX)", resource);
 | 
			
		||||
			if (!lv_deactivate(cmd, resource))
 | 
			
		||||
				return 0;
 | 
			
		||||
			break;
 | 
			
		||||
@@ -233,6 +255,7 @@ static int _file_lock_resource(struct cmd_context *cmd, const char *resource,
 | 
			
		||||
int init_file_locking(struct locking_type *locking, struct config_tree *cf)
 | 
			
		||||
{
 | 
			
		||||
	locking->lock_resource = _file_lock_resource;
 | 
			
		||||
	locking->reset_locking = _reset_file_locking;
 | 
			
		||||
	locking->fin_locking = _fin_file_locking;
 | 
			
		||||
 | 
			
		||||
	/* Get lockfile directory from config file */
 | 
			
		||||
 
 | 
			
		||||
@@ -14,30 +14,19 @@
 | 
			
		||||
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
static struct locking_type _locking;
 | 
			
		||||
static sigset_t _oldset;
 | 
			
		||||
 | 
			
		||||
static int _lock_count = 0;	/* Number of locks held */
 | 
			
		||||
static int _write_lock_held = 0;
 | 
			
		||||
static int _signals_blocked = 0;
 | 
			
		||||
 | 
			
		||||
static void _block_signals(int flags)
 | 
			
		||||
{
 | 
			
		||||
	sigset_t set;
 | 
			
		||||
 | 
			
		||||
	if (!_write_lock_held && (flags & LCK_SCOPE_MASK) == LCK_LV &&
 | 
			
		||||
	    (flags & LCK_TYPE_MASK) == LCK_WRITE) {
 | 
			
		||||
		if (mlockall(MCL_CURRENT | MCL_FUTURE))
 | 
			
		||||
			log_sys_error("mlockall", "");
 | 
			
		||||
		else {
 | 
			
		||||
			log_very_verbose("Locking memory");
 | 
			
		||||
			_write_lock_held = 1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (_signals_blocked)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
@@ -58,15 +47,6 @@ static void _block_signals(int flags)
 | 
			
		||||
 | 
			
		||||
static void _unblock_signals(void)
 | 
			
		||||
{
 | 
			
		||||
	if (!_lock_count && _write_lock_held) {
 | 
			
		||||
		if (munlockall()) {
 | 
			
		||||
			log_very_verbose("Unlocking memory");
 | 
			
		||||
			log_sys_error("munlockall", "");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		_write_lock_held = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Don't unblock signals while any locks are held */
 | 
			
		||||
	if (!_signals_blocked || _lock_count)
 | 
			
		||||
		return;
 | 
			
		||||
@@ -81,6 +61,18 @@ static void _unblock_signals(void)
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void reset_locking(void)
 | 
			
		||||
{
 | 
			
		||||
	int was_locked = _lock_count;
 | 
			
		||||
 | 
			
		||||
	_lock_count = 0;
 | 
			
		||||
 | 
			
		||||
	_locking.reset_locking();
 | 
			
		||||
 | 
			
		||||
	if (was_locked)
 | 
			
		||||
		_unblock_signals();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void _update_lock_count(int flags)
 | 
			
		||||
{
 | 
			
		||||
	if ((flags & LCK_TYPE_MASK) == LCK_UNLOCK)
 | 
			
		||||
@@ -107,11 +99,13 @@ int init_locking(int type, struct config_tree *cf)
 | 
			
		||||
		log_very_verbose("File-based locking enabled.");
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_LIBDL
 | 
			
		||||
	case 2:
 | 
			
		||||
		if (!init_external_locking(&_locking, cf))
 | 
			
		||||
			break;
 | 
			
		||||
		log_very_verbose("External locking enabled.");
 | 
			
		||||
		return 1;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		log_error("Unknown locking type requested.");
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@
 | 
			
		||||
 | 
			
		||||
int init_locking(int type, struct config_tree *cf);
 | 
			
		||||
void fin_locking(void);
 | 
			
		||||
void reset_locking(void);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * LCK_VG:
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@
 | 
			
		||||
#include "locking_types.h"
 | 
			
		||||
#include "lvm-string.h"
 | 
			
		||||
#include "activate.h"
 | 
			
		||||
#include "lvmcache.h"
 | 
			
		||||
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
 | 
			
		||||
@@ -22,11 +23,25 @@ static void _no_fin_locking(void)
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _no_reset_locking(void)
 | 
			
		||||
{
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _no_lock_resource(struct cmd_context *cmd, const char *resource,
 | 
			
		||||
			     int flags)
 | 
			
		||||
{
 | 
			
		||||
	switch (flags & LCK_SCOPE_MASK) {
 | 
			
		||||
	case LCK_VG:
 | 
			
		||||
		switch (flags & LCK_TYPE_MASK) {
 | 
			
		||||
		case LCK_UNLOCK:
 | 
			
		||||
			lvmcache_unlock_vgname(resource);
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			lvmcache_lock_vgname(resource,
 | 
			
		||||
					     (flags & LCK_TYPE_MASK) ==
 | 
			
		||||
					     LCK_READ);
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case LCK_LV:
 | 
			
		||||
		switch (flags & LCK_TYPE_MASK) {
 | 
			
		||||
@@ -54,6 +69,7 @@ static int _no_lock_resource(struct cmd_context *cmd, const char *resource,
 | 
			
		||||
int init_no_locking(struct locking_type *locking, struct config_tree *cf)
 | 
			
		||||
{
 | 
			
		||||
	locking->lock_resource = _no_lock_resource;
 | 
			
		||||
	locking->reset_locking = _no_reset_locking;
 | 
			
		||||
	locking->fin_locking = _no_fin_locking;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										111
									
								
								lib/log/log.c
									
									
									
									
									
								
							
							
						
						
									
										111
									
								
								lib/log/log.c
									
									
									
									
									
								
							@@ -5,27 +5,62 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "lib.h"
 | 
			
		||||
#include "device.h"
 | 
			
		||||
#include "memlock.h"
 | 
			
		||||
#include "lvm-string.h"
 | 
			
		||||
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <syslog.h>
 | 
			
		||||
 | 
			
		||||
static FILE *_log = 0;
 | 
			
		||||
static FILE *_log_file;
 | 
			
		||||
static struct device _log_dev;
 | 
			
		||||
static struct str_list _log_dev_alias;
 | 
			
		||||
 | 
			
		||||
static int _verbose_level = 0;
 | 
			
		||||
static int _test = 0;
 | 
			
		||||
static int _partial = 0;
 | 
			
		||||
static int _pvmove = 0;
 | 
			
		||||
static int _debug_level = 0;
 | 
			
		||||
static int _syslog = 0;
 | 
			
		||||
static int _log_to_file = 0;
 | 
			
		||||
static int _log_direct = 0;
 | 
			
		||||
static int _log_while_suspended = 0;
 | 
			
		||||
static int _indent = 1;
 | 
			
		||||
static int _log_cmd_name = 0;
 | 
			
		||||
static int _log_suppress = 0;
 | 
			
		||||
static int _ignorelockingfailure = 0;
 | 
			
		||||
static char _cmd_name[30] = "";
 | 
			
		||||
static char _msg_prefix[30] = "  ";
 | 
			
		||||
static int _already_logging = 0;
 | 
			
		||||
 | 
			
		||||
void init_log(FILE *fp)
 | 
			
		||||
void init_log_file(const char *log_file, int append)
 | 
			
		||||
{
 | 
			
		||||
	_log = fp;
 | 
			
		||||
	const char *open_mode = append ? "a" : "w";
 | 
			
		||||
 | 
			
		||||
	if (!(_log_file = fopen(log_file, open_mode))) {
 | 
			
		||||
		log_sys_error("fopen", log_file);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_log_to_file = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void init_log_direct(const char *log_file, int append)
 | 
			
		||||
{
 | 
			
		||||
	const char *filename;
 | 
			
		||||
	int open_flags = append ? 0 : O_TRUNC;
 | 
			
		||||
 | 
			
		||||
	filename = dbg_strdup(log_file);
 | 
			
		||||
	dev_create_file(filename, &_log_dev, &_log_dev_alias);
 | 
			
		||||
	if (!dev_open_flags(&_log_dev, O_RDWR | O_CREAT | open_flags, 1, 0))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	_log_direct = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void init_log_while_suspended(int log_while_suspended)
 | 
			
		||||
{
 | 
			
		||||
	_log_while_suspended = log_while_suspended;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void init_syslog(int facility)
 | 
			
		||||
@@ -39,9 +74,23 @@ void log_suppress(int suppress)
 | 
			
		||||
	_log_suppress = suppress;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fin_log()
 | 
			
		||||
void release_log_memory(void)
 | 
			
		||||
{
 | 
			
		||||
	_log = 0;
 | 
			
		||||
	dbg_free((char *) _log_dev_alias.str);
 | 
			
		||||
	_log_dev_alias.str = "activate_log file";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fin_log(void)
 | 
			
		||||
{
 | 
			
		||||
	if (_log_direct) {
 | 
			
		||||
		dev_close(&_log_dev);
 | 
			
		||||
		_log_direct = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (_log_to_file) {
 | 
			
		||||
		fclose(_log_file);
 | 
			
		||||
		_log_to_file = 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fin_syslog()
 | 
			
		||||
@@ -68,6 +117,11 @@ void init_partial(int level)
 | 
			
		||||
	_partial = level;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void init_pvmove(int level)
 | 
			
		||||
{
 | 
			
		||||
	_pvmove = level;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void init_ignorelockingfailure(int level)
 | 
			
		||||
{
 | 
			
		||||
	_ignorelockingfailure = level;
 | 
			
		||||
@@ -107,6 +161,11 @@ int partial_mode()
 | 
			
		||||
	return _partial;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int pvmove_mode()
 | 
			
		||||
{
 | 
			
		||||
	return _pvmove;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ignorelockingfailure()
 | 
			
		||||
{
 | 
			
		||||
	return _ignorelockingfailure;
 | 
			
		||||
@@ -125,6 +184,8 @@ int debug_level()
 | 
			
		||||
void print_log(int level, const char *file, int line, const char *format, ...)
 | 
			
		||||
{
 | 
			
		||||
	va_list ap;
 | 
			
		||||
	char buf[1024];
 | 
			
		||||
	int bufused, n;
 | 
			
		||||
 | 
			
		||||
	if (!_log_suppress) {
 | 
			
		||||
		va_start(ap, format);
 | 
			
		||||
@@ -183,20 +244,48 @@ void print_log(int level, const char *file, int line, const char *format, ...)
 | 
			
		||||
	if (level > _debug_level)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (_log) {
 | 
			
		||||
		fprintf(_log, "%s:%d %s%s", file, line, _cmd_name, _msg_prefix);
 | 
			
		||||
	if (_log_to_file && (_log_while_suspended || !memlock())) {
 | 
			
		||||
		fprintf(_log_file, "%s:%d %s%s", file, line, _cmd_name,
 | 
			
		||||
			_msg_prefix);
 | 
			
		||||
 | 
			
		||||
		va_start(ap, format);
 | 
			
		||||
		vfprintf(_log, format, ap);
 | 
			
		||||
		vfprintf(_log_file, format, ap);
 | 
			
		||||
		va_end(ap);
 | 
			
		||||
 | 
			
		||||
		fprintf(_log, "\n");
 | 
			
		||||
		fflush(_log);
 | 
			
		||||
		fprintf(_log_file, "\n");
 | 
			
		||||
		fflush(_log_file);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (_syslog) {
 | 
			
		||||
	if (_syslog && (_log_while_suspended || !memlock())) {
 | 
			
		||||
		va_start(ap, format);
 | 
			
		||||
		vsyslog(level, format, ap);
 | 
			
		||||
		va_end(ap);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* FIXME This code is unfinished - pre-extend & condense. */
 | 
			
		||||
	if (!_already_logging && _log_direct && memlock()) {
 | 
			
		||||
		_already_logging = 1;
 | 
			
		||||
		memset(&buf, ' ', sizeof(buf));
 | 
			
		||||
		bufused = 0;
 | 
			
		||||
		if ((n = lvm_snprintf(buf, sizeof(buf) - bufused - 1,
 | 
			
		||||
				      "%s:%d %s%s", file, line, _cmd_name,
 | 
			
		||||
				      _msg_prefix)) == -1)
 | 
			
		||||
			goto done;
 | 
			
		||||
 | 
			
		||||
		bufused += n;
 | 
			
		||||
 | 
			
		||||
		va_start(ap, format);
 | 
			
		||||
		n = vsnprintf(buf + bufused - 1, sizeof(buf) - bufused - 1,
 | 
			
		||||
			      format, ap);
 | 
			
		||||
		va_end(ap);
 | 
			
		||||
		bufused += n;
 | 
			
		||||
 | 
			
		||||
	      done:
 | 
			
		||||
		buf[bufused - 1] = '\n';
 | 
			
		||||
		buf[bufused] = '\n';
 | 
			
		||||
		buf[sizeof(buf) - 1] = '\n';
 | 
			
		||||
		/* FIXME real size bufused */
 | 
			
		||||
		dev_append(&_log_dev, sizeof(buf), buf);
 | 
			
		||||
		_already_logging = 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -39,8 +39,11 @@
 | 
			
		||||
#define _LOG_ERR 3
 | 
			
		||||
#define _LOG_FATAL 2
 | 
			
		||||
 | 
			
		||||
void init_log(FILE *fp);
 | 
			
		||||
void init_log_file(const char *log_file, int append);
 | 
			
		||||
void init_log_direct(const char *log_file, int append);
 | 
			
		||||
void init_log_while_suspended(int log_while_suspended);
 | 
			
		||||
void fin_log(void);
 | 
			
		||||
void release_log_memory(void);
 | 
			
		||||
 | 
			
		||||
void init_syslog(int facility);
 | 
			
		||||
void fin_syslog(void);
 | 
			
		||||
@@ -48,6 +51,7 @@ void fin_syslog(void);
 | 
			
		||||
void init_verbose(int level);
 | 
			
		||||
void init_test(int level);
 | 
			
		||||
void init_partial(int level);
 | 
			
		||||
void init_pvmove(int level);
 | 
			
		||||
void init_debug(int level);
 | 
			
		||||
void init_cmd_name(int status);
 | 
			
		||||
void init_msg_prefix(const char *prefix);
 | 
			
		||||
@@ -58,12 +62,16 @@ void set_cmd_name(const char *cmd_name);
 | 
			
		||||
 | 
			
		||||
int test_mode(void);
 | 
			
		||||
int partial_mode(void);
 | 
			
		||||
int pvmove_mode(void);
 | 
			
		||||
int debug_level(void);
 | 
			
		||||
int ignorelockingfailure(void);
 | 
			
		||||
 | 
			
		||||
/* Suppress messages to stdout/stderr */
 | 
			
		||||
void log_suppress(int suppress);
 | 
			
		||||
 | 
			
		||||
/* Suppress messages to syslog */
 | 
			
		||||
void syslog_suppress(int suppress);
 | 
			
		||||
 | 
			
		||||
void print_log(int level, const char *file, int line, const char *format, ...)
 | 
			
		||||
    __attribute__ ((format(printf, 4, 5)));
 | 
			
		||||
 | 
			
		||||
@@ -78,15 +86,17 @@ void print_log(int level, const char *file, int line, const char *format, ...)
 | 
			
		||||
 | 
			
		||||
#define stack log_debug("<backtrace>")	/* Backtrace on error */
 | 
			
		||||
 | 
			
		||||
#define log_error(fmt, args...) log_err(fmt , ## args)
 | 
			
		||||
#define log_print(fmt, args...) log_warn(fmt , ## args)
 | 
			
		||||
#define log_verbose(fmt, args...) log_notice(fmt , ## args)
 | 
			
		||||
#define log_very_verbose(fmt, args...) log_info(fmt , ## args)
 | 
			
		||||
#define log_error(args...) log_err(args)
 | 
			
		||||
#define log_print(args...) log_warn(args)
 | 
			
		||||
#define log_verbose(args...) log_notice(args)
 | 
			
		||||
#define log_very_verbose(args...) log_info(args)
 | 
			
		||||
 | 
			
		||||
/* Two System call equivalents */
 | 
			
		||||
#define log_sys_error(x, y) \
 | 
			
		||||
		log_err("%s: %s failed: %s", y, x, strerror(errno))
 | 
			
		||||
#define log_sys_very_verbose(x, y) \
 | 
			
		||||
		log_info("%s: %s failed: %s", y, x, strerror(errno))
 | 
			
		||||
#define log_sys_debug(x, y) \
 | 
			
		||||
		log_debug("%s: %s failed: %s", y, x, strerror(errno))
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2003 Sistina Software (UK) Limited.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 */
 | 
			
		||||
@@ -10,7 +10,8 @@
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
#include "lvm-string.h"
 | 
			
		||||
#include "cache.h"
 | 
			
		||||
#include "lvmcache.h"
 | 
			
		||||
#include "memlock.h"
 | 
			
		||||
 | 
			
		||||
static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg,
 | 
			
		||||
			 const char *pv_name)
 | 
			
		||||
@@ -23,14 +24,14 @@ static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg,
 | 
			
		||||
	log_verbose("Adding physical volume '%s' to volume group '%s'",
 | 
			
		||||
		    pv_name, vg->name);
 | 
			
		||||
 | 
			
		||||
	if (!(pvl = pool_alloc(mem, sizeof(*pvl)))) {
 | 
			
		||||
	if (!(pvl = pool_zalloc(mem, sizeof(*pvl)))) {
 | 
			
		||||
		log_error("pv_list allocation for '%s' failed", pv_name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	list_init(&mdas);
 | 
			
		||||
	if (!(pv = pv_read(fid->fmt->cmd, pv_name, &mdas, NULL))) {
 | 
			
		||||
		log_error("Failed to read existing physical volume '%s'",
 | 
			
		||||
		log_error("%s not identified as an existing physical volume",
 | 
			
		||||
			  pv_name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -68,8 +69,8 @@ static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg,
 | 
			
		||||
 | 
			
		||||
	pv->pe_alloc_count = 0;
 | 
			
		||||
 | 
			
		||||
	if (!fid->fmt->ops->pv_setup(fid->fmt, __UINT64_C(0), 0,
 | 
			
		||||
				     vg->extent_size, 0, __UINT64_C(0),
 | 
			
		||||
	if (!fid->fmt->ops->pv_setup(fid->fmt, UINT64_C(0), 0,
 | 
			
		||||
				     vg->extent_size, 0, UINT64_C(0),
 | 
			
		||||
				     &fid->metadata_areas, pv, vg)) {
 | 
			
		||||
		log_error("Format-specific setup of physical volume '%s' "
 | 
			
		||||
			  "failed.", pv_name);
 | 
			
		||||
@@ -157,6 +158,7 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name,
 | 
			
		||||
	struct volume_group *vg;
 | 
			
		||||
	struct pool *mem = cmd->mem;
 | 
			
		||||
	int consistent = 0;
 | 
			
		||||
	int old_partial;
 | 
			
		||||
 | 
			
		||||
	if (!(vg = pool_zalloc(mem, sizeof(*vg)))) {
 | 
			
		||||
		stack;
 | 
			
		||||
@@ -164,12 +166,13 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* is this vg name already in use ? */
 | 
			
		||||
	old_partial = partial_mode();
 | 
			
		||||
	init_partial(1);
 | 
			
		||||
	if (vg_read(cmd, vg_name, &consistent)) {
 | 
			
		||||
		log_err("A volume group called '%s' already exists.", vg_name);
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
	init_partial(0);
 | 
			
		||||
	init_partial(old_partial);
 | 
			
		||||
 | 
			
		||||
	if (!id_create(&vg->id)) {
 | 
			
		||||
		log_err("Couldn't create uuid for volume group '%s'.", vg_name);
 | 
			
		||||
@@ -318,6 +321,18 @@ struct pv_list *find_pv_in_vg(struct volume_group *vg, const char *pv_name)
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int pv_is_in_vg(struct volume_group *vg, struct physical_volume *pv)
 | 
			
		||||
{
 | 
			
		||||
	struct list *pvh;
 | 
			
		||||
 | 
			
		||||
	list_iterate(pvh, &vg->pvs) {
 | 
			
		||||
		if (pv == list_item(pvh, struct pv_list)->pv)
 | 
			
		||||
			 return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct physical_volume *find_pv_in_vg_by_uuid(struct volume_group *vg,
 | 
			
		||||
					      struct id *id)
 | 
			
		||||
{
 | 
			
		||||
@@ -389,6 +404,21 @@ struct physical_volume *find_pv(struct volume_group *vg, struct device *dev)
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Find segment at a given logical extent in an LV */
 | 
			
		||||
struct lv_segment *find_seg_by_le(struct logical_volume *lv, uint32_t le)
 | 
			
		||||
{
 | 
			
		||||
	struct list *segh;
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
 | 
			
		||||
	list_iterate(segh, &lv->segments) {
 | 
			
		||||
		seg = list_item(segh, struct lv_segment);
 | 
			
		||||
		if (le >= seg->le && le < seg->le + seg->len)
 | 
			
		||||
			return seg;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int vg_remove(struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	struct list *mdah;
 | 
			
		||||
@@ -408,11 +438,14 @@ int vg_remove(struct volume_group *vg)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * After vg_write() returns success,
 | 
			
		||||
 * caller MUST call either vg_commit() or vg_revert()
 | 
			
		||||
 */
 | 
			
		||||
int vg_write(struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	struct list *mdah;
 | 
			
		||||
	struct list *mdah, *mdah2;
 | 
			
		||||
	struct metadata_area *mda;
 | 
			
		||||
	int cache_updated = 0;
 | 
			
		||||
 | 
			
		||||
	if (vg->status & PARTIAL_VG) {
 | 
			
		||||
		log_error("Cannot change metadata for partial volume group %s",
 | 
			
		||||
@@ -432,21 +465,61 @@ int vg_write(struct volume_group *vg)
 | 
			
		||||
		mda = list_item(mdah, struct metadata_area);
 | 
			
		||||
		if (!mda->ops->vg_write(vg->fid, vg, mda)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			/* Revert */
 | 
			
		||||
			list_uniterate(mdah2, &vg->fid->metadata_areas, mdah) {
 | 
			
		||||
				mda = list_item(mdah2, struct metadata_area);
 | 
			
		||||
				if (mda->ops->vg_revert &&
 | 
			
		||||
				    !mda->ops->vg_revert(vg->fid, vg, mda)) {
 | 
			
		||||
					stack;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Commit pending changes */
 | 
			
		||||
int vg_commit(struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	struct list *mdah;
 | 
			
		||||
	struct metadata_area *mda;
 | 
			
		||||
	int cache_updated = 0;
 | 
			
		||||
	int failed = 0;
 | 
			
		||||
 | 
			
		||||
	/* Commit to each copy of the metadata area */
 | 
			
		||||
	list_iterate(mdah, &vg->fid->metadata_areas) {
 | 
			
		||||
		mda = list_item(mdah, struct metadata_area);
 | 
			
		||||
		if (!cache_updated) {
 | 
			
		||||
			cache_update_vg(vg);
 | 
			
		||||
			cache_updated = 1;
 | 
			
		||||
		}
 | 
			
		||||
		failed = 0;
 | 
			
		||||
		if (mda->ops->vg_commit &&
 | 
			
		||||
		    !mda->ops->vg_commit(vg->fid, vg, mda)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
			failed = 1;
 | 
			
		||||
		}
 | 
			
		||||
		/* Update cache first time we succeed */
 | 
			
		||||
		if (!failed && !cache_updated) {
 | 
			
		||||
			lvmcache_update_vg(vg);
 | 
			
		||||
			cache_updated = 1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* If at least one mda commit succeeded, it was committed */
 | 
			
		||||
	return cache_updated;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Don't commit any pending changes */
 | 
			
		||||
int vg_revert(struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	struct list *mdah;
 | 
			
		||||
	struct metadata_area *mda;
 | 
			
		||||
 | 
			
		||||
	list_iterate(mdah, &vg->fid->metadata_areas) {
 | 
			
		||||
		mda = list_item(mdah, struct metadata_area);
 | 
			
		||||
		if (mda->ops->vg_revert &&
 | 
			
		||||
		    !mda->ops->vg_revert(vg->fid, vg, mda)) {
 | 
			
		||||
			stack;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -456,7 +529,7 @@ int vg_write(struct volume_group *vg)
 | 
			
		||||
/* Make orphan PVs look like a VG */
 | 
			
		||||
static struct volume_group *_vg_read_orphans(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	struct cache_vginfo *vginfo;
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
	struct list *ih;
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
	struct pv_list *pvl;
 | 
			
		||||
@@ -482,7 +555,7 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	list_iterate(ih, &vginfo->infos) {
 | 
			
		||||
		dev = list_item(ih, struct cache_info)->dev;
 | 
			
		||||
		dev = list_item(ih, struct lvmcache_info)->dev;
 | 
			
		||||
		if (!(pv = pv_read(cmd, dev_name(dev), NULL, NULL))) {
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
@@ -523,9 +596,13 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
 | 
			
		||||
	/* Find the vgname in the cache */
 | 
			
		||||
	/* If it's not there we must do full scan to be completely sure */
 | 
			
		||||
	if (!(fmt = fmt_from_vgname(vgname))) {
 | 
			
		||||
		cache_label_scan(cmd, 0);
 | 
			
		||||
		lvmcache_label_scan(cmd, 0);
 | 
			
		||||
		if (!(fmt = fmt_from_vgname(vgname))) {
 | 
			
		||||
			cache_label_scan(cmd, 1);
 | 
			
		||||
			if (memlock()) {
 | 
			
		||||
				stack;
 | 
			
		||||
				return NULL;
 | 
			
		||||
			}
 | 
			
		||||
			lvmcache_label_scan(cmd, 1);
 | 
			
		||||
			if (!(fmt = fmt_from_vgname(vgname))) {
 | 
			
		||||
				stack;
 | 
			
		||||
				return NULL;
 | 
			
		||||
@@ -564,7 +641,7 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cache_update_vg(correct_vg);
 | 
			
		||||
	lvmcache_update_vg(correct_vg);
 | 
			
		||||
 | 
			
		||||
	if (inconsistent) {
 | 
			
		||||
		if (!*consistent)
 | 
			
		||||
@@ -587,8 +664,15 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*consistent = 1;
 | 
			
		||||
	if ((correct_vg->status & PVMOVE) && !pvmove_mode()) {
 | 
			
		||||
		log_error("WARNING: Interrupted pvmove detected in "
 | 
			
		||||
			  "volume group %s", vg->name);
 | 
			
		||||
		log_error("Please restore the metadata by running "
 | 
			
		||||
			  "vgcfgrestore.");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*consistent = 1;
 | 
			
		||||
	return correct_vg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -598,10 +682,10 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
 | 
			
		||||
 */
 | 
			
		||||
struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid)
 | 
			
		||||
{
 | 
			
		||||
	char *vgname;
 | 
			
		||||
	struct list *vgnames, *slh;
 | 
			
		||||
	// const char *vgname;
 | 
			
		||||
	// struct list *vgnames, *slh;
 | 
			
		||||
	struct volume_group *vg;
 | 
			
		||||
	struct cache_vginfo *vginfo;
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
	int consistent = 0;
 | 
			
		||||
 | 
			
		||||
	/* Is corresponding vgname already cached? */
 | 
			
		||||
@@ -618,7 +702,14 @@ struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* The slow way - full scan required to cope with vgrename */
 | 
			
		||||
	return NULL;
 | 
			
		||||
 | 
			
		||||
	/* FIXME Need a genuine read by ID here - don't vg_read by name! */
 | 
			
		||||
	/* FIXME Disabled vgrenames while active for now because we aren't
 | 
			
		||||
	 *       allowed to do a full scan here any more. */
 | 
			
		||||
 | 
			
		||||
/*** FIXME Cope with vgrename here
 | 
			
		||||
	// The slow way - full scan required to cope with vgrename 
 | 
			
		||||
	if (!(vgnames = get_vgs(cmd, 1))) {
 | 
			
		||||
		log_error("vg_read_by_vgid: get_vgs failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
@@ -627,7 +718,7 @@ struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid)
 | 
			
		||||
	list_iterate(slh, vgnames) {
 | 
			
		||||
		vgname = list_item(slh, struct str_list)->str;
 | 
			
		||||
		if (!vgname || !*vgname)
 | 
			
		||||
			continue;	/* FIXME Unnecessary? */
 | 
			
		||||
			continue;	// FIXME Unnecessary? 
 | 
			
		||||
		consistent = 0;
 | 
			
		||||
		if ((vg = vg_read(cmd, vgname, &consistent)) &&
 | 
			
		||||
		    !strncmp(vg->id.uuid, vgid, ID_LEN)) {
 | 
			
		||||
@@ -641,6 +732,7 @@ struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return NULL;
 | 
			
		||||
***/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Only called by activate.c */
 | 
			
		||||
@@ -677,7 +769,7 @@ struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
 | 
			
		||||
{
 | 
			
		||||
	struct physical_volume *pv;
 | 
			
		||||
	struct label *label;
 | 
			
		||||
	struct cache_info *info;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
 | 
			
		||||
	if (!(dev = dev_cache_get(pv_name, cmd->filter))) {
 | 
			
		||||
@@ -686,17 +778,16 @@ struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(label_read(dev, &label))) {
 | 
			
		||||
		log_error("Failed to read label on physical volume %s",
 | 
			
		||||
			  pv_name);
 | 
			
		||||
		log_error("No physical volume label read from %s", pv_name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	info = (struct cache_info *) label->info;
 | 
			
		||||
	info = (struct lvmcache_info *) label->info;
 | 
			
		||||
	if (label_sector && *label_sector)
 | 
			
		||||
		*label_sector = label->sector;
 | 
			
		||||
 | 
			
		||||
	if (!(pv = pool_zalloc(cmd->mem, sizeof(*pv)))) {
 | 
			
		||||
		log_error("pv_list allocation for '%s' failed", pv_name);
 | 
			
		||||
		log_error("pv allocation for '%s' failed", pv_name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -716,19 +807,21 @@ struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
 | 
			
		||||
/* May return empty list */
 | 
			
		||||
struct list *get_vgs(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
{
 | 
			
		||||
	return cache_get_vgnames(cmd, full_scan);
 | 
			
		||||
	return lvmcache_get_vgnames(cmd, full_scan);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct list *get_pvs(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	struct list *results;
 | 
			
		||||
	char *vgname;
 | 
			
		||||
	const char *vgname;
 | 
			
		||||
	struct list *pvh, *tmp;
 | 
			
		||||
	struct list *vgnames, *slh;
 | 
			
		||||
	struct volume_group *vg;
 | 
			
		||||
	int consistent = 0;
 | 
			
		||||
	int old_partial;
 | 
			
		||||
	int old_pvmove;
 | 
			
		||||
 | 
			
		||||
	cache_label_scan(cmd, 0);
 | 
			
		||||
	lvmcache_label_scan(cmd, 0);
 | 
			
		||||
 | 
			
		||||
	if (!(results = pool_alloc(cmd->mem, sizeof(*results)))) {
 | 
			
		||||
		log_error("PV list allocation failed");
 | 
			
		||||
@@ -745,7 +838,10 @@ struct list *get_pvs(struct cmd_context *cmd)
 | 
			
		||||
 | 
			
		||||
	/* Read every VG to ensure cache consistency */
 | 
			
		||||
	/* Orphan VG is last on list */
 | 
			
		||||
	old_partial = partial_mode();
 | 
			
		||||
	old_pvmove = pvmove_mode();
 | 
			
		||||
	init_partial(1);
 | 
			
		||||
	init_pvmove(1);
 | 
			
		||||
	list_iterate(slh, vgnames) {
 | 
			
		||||
		vgname = list_item(slh, struct str_list)->str;
 | 
			
		||||
		if (!vgname)
 | 
			
		||||
@@ -764,7 +860,8 @@ struct list *get_pvs(struct cmd_context *cmd)
 | 
			
		||||
			list_add(results, pvh);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	init_partial(0);
 | 
			
		||||
	init_pvmove(old_pvmove);
 | 
			
		||||
	init_partial(old_partial);
 | 
			
		||||
 | 
			
		||||
	return results;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -12,17 +12,13 @@
 | 
			
		||||
 | 
			
		||||
#include "ctype.h"
 | 
			
		||||
#include "dev-cache.h"
 | 
			
		||||
#include "list.h"
 | 
			
		||||
#include "uuid.h"
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <asm/page.h>
 | 
			
		||||
 | 
			
		||||
#define NAME_LEN 128
 | 
			
		||||
#define MAX_STRIPES 128
 | 
			
		||||
#define SECTOR_SHIFT 9L
 | 
			
		||||
#define SECTOR_SIZE ( 1L << SECTOR_SHIFT )
 | 
			
		||||
#define STRIPE_SIZE_MIN ( PAGE_SIZE >> SECTOR_SHIFT)	/* PAGESIZE in sectors */
 | 
			
		||||
#define STRIPE_SIZE_MIN ( getpagesize() >> SECTOR_SHIFT)	/* PAGESIZE in sectors */
 | 
			
		||||
#define STRIPE_SIZE_MAX ( 512L * 1024L >> SECTOR_SHIFT)	/* 512 KB in sectors */
 | 
			
		||||
#define PV_MIN_SIZE ( 512L * 1024L >> SECTOR_SHIFT)	/* 512 KB in sectors */
 | 
			
		||||
#define PE_ALIGN (65536UL >> SECTOR_SHIFT)	/* PE alignment */
 | 
			
		||||
@@ -42,7 +38,9 @@
 | 
			
		||||
#define VISIBLE_LV		0x00000040	/* LV */
 | 
			
		||||
#define FIXED_MINOR		0x00000080	/* LV */
 | 
			
		||||
/* FIXME Remove when metadata restructuring is completed */
 | 
			
		||||
#define SNAPSHOT		0x00001000	/* LV - temp internal use only */
 | 
			
		||||
#define SNAPSHOT		0x00001000	/* LV - tmp internal use only */
 | 
			
		||||
#define PVMOVE			0x00002000	/* VG LV SEG */
 | 
			
		||||
#define LOCKED			0x00004000	/* LV */
 | 
			
		||||
 | 
			
		||||
#define LVM_READ              	0x00000100	/* LV VG */
 | 
			
		||||
#define LVM_WRITE             	0x00000200	/* LV VG */
 | 
			
		||||
@@ -62,9 +60,14 @@ typedef enum {
 | 
			
		||||
typedef enum {
 | 
			
		||||
	SEG_STRIPED,
 | 
			
		||||
	SEG_SNAPSHOT,
 | 
			
		||||
	SEG_MIRROR
 | 
			
		||||
	SEG_MIRRORED
 | 
			
		||||
} segment_type_t;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
	AREA_PV,
 | 
			
		||||
	AREA_LV
 | 
			
		||||
} area_type_t;
 | 
			
		||||
 | 
			
		||||
struct cmd_context;
 | 
			
		||||
struct format_handler;
 | 
			
		||||
struct labeller;
 | 
			
		||||
@@ -123,6 +126,8 @@ struct metadata_area_ops {
 | 
			
		||||
			 struct metadata_area * mda);
 | 
			
		||||
	int (*vg_commit) (struct format_instance * fid,
 | 
			
		||||
			  struct volume_group * vg, struct metadata_area * mda);
 | 
			
		||||
	int (*vg_revert) (struct format_instance * fid,
 | 
			
		||||
			  struct volume_group * vg, struct metadata_area * mda);
 | 
			
		||||
	int (*vg_remove) (struct format_instance * fi, struct volume_group * vg,
 | 
			
		||||
			  struct metadata_area * mda);
 | 
			
		||||
};
 | 
			
		||||
@@ -177,17 +182,30 @@ struct lv_segment {
 | 
			
		||||
	uint32_t le;
 | 
			
		||||
	uint32_t len;
 | 
			
		||||
 | 
			
		||||
	uint32_t status;
 | 
			
		||||
 | 
			
		||||
	/* FIXME Fields depend on segment type */
 | 
			
		||||
	uint32_t stripe_size;
 | 
			
		||||
	uint32_t stripes;
 | 
			
		||||
	uint32_t area_count;
 | 
			
		||||
	uint32_t area_len;
 | 
			
		||||
	struct logical_volume *origin;
 | 
			
		||||
	struct logical_volume *cow;
 | 
			
		||||
	uint32_t chunk_size;
 | 
			
		||||
	uint32_t extents_moved;
 | 
			
		||||
 | 
			
		||||
	/* There will be one area for each stripe */
 | 
			
		||||
	struct {
 | 
			
		||||
		struct physical_volume *pv;
 | 
			
		||||
		uint32_t pe;
 | 
			
		||||
		area_type_t type;
 | 
			
		||||
		union {
 | 
			
		||||
			struct {
 | 
			
		||||
				struct physical_volume *pv;
 | 
			
		||||
				uint32_t pe;
 | 
			
		||||
			} pv;
 | 
			
		||||
			struct {
 | 
			
		||||
				struct logical_volume *lv;
 | 
			
		||||
				uint32_t le;
 | 
			
		||||
			} lv;
 | 
			
		||||
		} u;
 | 
			
		||||
	} area[0];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -200,6 +218,7 @@ struct logical_volume {
 | 
			
		||||
	uint32_t status;
 | 
			
		||||
	alloc_policy_t alloc;
 | 
			
		||||
	uint32_t read_ahead;
 | 
			
		||||
	int32_t major;
 | 
			
		||||
	int32_t minor;
 | 
			
		||||
 | 
			
		||||
	uint64_t size;
 | 
			
		||||
@@ -223,10 +242,17 @@ struct name_list {
 | 
			
		||||
	char *name;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct alloc_area {
 | 
			
		||||
	struct list list;
 | 
			
		||||
	uint32_t start;		/* PEs */
 | 
			
		||||
	uint32_t count;		/* PEs */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct pv_list {
 | 
			
		||||
	struct list list;
 | 
			
		||||
	struct physical_volume *pv;
 | 
			
		||||
	struct list *mdas;
 | 
			
		||||
	struct list *mdas;	/* Metadata areas */
 | 
			
		||||
	struct list *alloc_areas;	/* Areas we may allocate from */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct lv_list {
 | 
			
		||||
@@ -314,6 +340,8 @@ struct format_handler {
 | 
			
		||||
 * Utility functions
 | 
			
		||||
 */
 | 
			
		||||
int vg_write(struct volume_group *vg);
 | 
			
		||||
int vg_commit(struct volume_group *vg);
 | 
			
		||||
int vg_revert(struct volume_group *vg);
 | 
			
		||||
struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name,
 | 
			
		||||
			     int *consistent);
 | 
			
		||||
struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid);
 | 
			
		||||
@@ -360,8 +388,16 @@ struct logical_volume *lv_create(struct format_instance *fi,
 | 
			
		||||
				 uint32_t stripe_size,
 | 
			
		||||
				 uint32_t extents,
 | 
			
		||||
				 struct volume_group *vg,
 | 
			
		||||
				 struct list *acceptable_pvs);
 | 
			
		||||
				 struct list *allocatable_pvs);
 | 
			
		||||
 | 
			
		||||
struct logical_volume *lv_create_empty(struct format_instance *fi,
 | 
			
		||||
				       const char *name,
 | 
			
		||||
				       const char *name_format,
 | 
			
		||||
				       uint32_t status,
 | 
			
		||||
				       alloc_policy_t alloc,
 | 
			
		||||
				       struct volume_group *vg);
 | 
			
		||||
 | 
			
		||||
/* Manipulate LVs */
 | 
			
		||||
int lv_reduce(struct format_instance *fi,
 | 
			
		||||
	      struct logical_volume *lv, uint32_t extents);
 | 
			
		||||
 | 
			
		||||
@@ -371,6 +407,17 @@ int lv_extend(struct format_instance *fi,
 | 
			
		||||
	      uint32_t stripe_size,
 | 
			
		||||
	      uint32_t extents, struct list *allocatable_pvs);
 | 
			
		||||
 | 
			
		||||
int lv_extend_mirror(struct format_instance *fid,
 | 
			
		||||
		     struct logical_volume *lv,
 | 
			
		||||
		     struct physical_volume *mirrored_pv,
 | 
			
		||||
		     uint32_t mirrored_pe,
 | 
			
		||||
		     uint32_t extents, struct list *allocatable_pvs,
 | 
			
		||||
		     uint32_t status);
 | 
			
		||||
 | 
			
		||||
/* Lock list of LVs */
 | 
			
		||||
int lock_lvs(struct cmd_context *cmd, struct list *lvs, int flags);
 | 
			
		||||
int unlock_lvs(struct cmd_context *cmd, struct list *lvs);
 | 
			
		||||
 | 
			
		||||
/* lv must be part of vg->lvs */
 | 
			
		||||
int lv_remove(struct volume_group *vg, struct logical_volume *lv);
 | 
			
		||||
 | 
			
		||||
@@ -401,6 +448,9 @@ struct logical_volume *lv_from_lvid(struct cmd_context *cmd,
 | 
			
		||||
struct physical_volume *find_pv(struct volume_group *vg, struct device *dev);
 | 
			
		||||
struct logical_volume *find_lv(struct volume_group *vg, const char *lv_name);
 | 
			
		||||
 | 
			
		||||
/* Find LV segment containing given LE */
 | 
			
		||||
struct lv_segment *find_seg_by_le(struct logical_volume *lv, uint32_t le);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Remove a dev_dir if present.
 | 
			
		||||
 */
 | 
			
		||||
@@ -424,6 +474,8 @@ int lv_merge_segments(struct logical_volume *lv);
 | 
			
		||||
int lv_is_origin(const struct logical_volume *lv);
 | 
			
		||||
int lv_is_cow(const struct logical_volume *lv);
 | 
			
		||||
 | 
			
		||||
int pv_is_in_vg(struct volume_group *vg, struct physical_volume *pv);
 | 
			
		||||
 | 
			
		||||
struct snapshot *find_cow(const struct logical_volume *lv);
 | 
			
		||||
struct snapshot *find_origin(const struct logical_volume *lv);
 | 
			
		||||
struct list *find_snapshots(const struct logical_volume *lv);
 | 
			
		||||
@@ -434,7 +486,27 @@ int vg_add_snapshot(struct logical_volume *origin,
 | 
			
		||||
 | 
			
		||||
int vg_remove_snapshot(struct volume_group *vg, struct logical_volume *cow);
 | 
			
		||||
 | 
			
		||||
static inline int validate_vgname(const char *n)
 | 
			
		||||
/*
 | 
			
		||||
 * Mirroring functions
 | 
			
		||||
 */
 | 
			
		||||
int insert_pvmove_mirrors(struct cmd_context *cmd,
 | 
			
		||||
			  struct logical_volume *lv_mirr,
 | 
			
		||||
			  struct physical_volume *pv,
 | 
			
		||||
			  struct logical_volume *lv,
 | 
			
		||||
			  struct list *allocatable_pvs,
 | 
			
		||||
			  struct list *lvs_changed);
 | 
			
		||||
int remove_pvmove_mirrors(struct volume_group *vg,
 | 
			
		||||
			  struct logical_volume *lv_mirr);
 | 
			
		||||
struct logical_volume *find_pvmove_lv(struct volume_group *vg,
 | 
			
		||||
				      struct device *dev);
 | 
			
		||||
struct physical_volume *get_pvmove_pv_from_lv(struct logical_volume *lv);
 | 
			
		||||
struct physical_volume *get_pvmove_pv_from_lv_mirr(struct logical_volume
 | 
			
		||||
						   *lv_mirr);
 | 
			
		||||
float pvmove_percent(struct logical_volume *lv_mirr);
 | 
			
		||||
struct list *lvs_using_lv(struct cmd_context *cmd, struct volume_group *vg,
 | 
			
		||||
			  struct logical_volume *lv);
 | 
			
		||||
 | 
			
		||||
static inline int validate_name(const char *n)
 | 
			
		||||
{
 | 
			
		||||
	register char c;
 | 
			
		||||
	register int len = 0;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										250
									
								
								lib/metadata/mirror.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										250
									
								
								lib/metadata/mirror.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,250 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2003  Sistina Software (UK) Limited.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "lib.h"
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
 | 
			
		||||
/* 
 | 
			
		||||
 * Replace any LV segments on given PV with temporary mirror.
 | 
			
		||||
 * Returns list of LVs changed.
 | 
			
		||||
 */
 | 
			
		||||
int insert_pvmove_mirrors(struct cmd_context *cmd,
 | 
			
		||||
			  struct logical_volume *lv_mirr,
 | 
			
		||||
			  struct physical_volume *pv,
 | 
			
		||||
			  struct logical_volume *lv,
 | 
			
		||||
			  struct list *allocatable_pvs,
 | 
			
		||||
			  struct list *lvs_changed)
 | 
			
		||||
{
 | 
			
		||||
	struct list *segh;
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
	struct lv_list *lvl;
 | 
			
		||||
	int lv_used = 0;
 | 
			
		||||
	uint32_t s, start_le, extent_count = 0u;
 | 
			
		||||
 | 
			
		||||
	list_iterate(segh, &lv->segments) {
 | 
			
		||||
		seg = list_item(segh, struct lv_segment);
 | 
			
		||||
		for (s = 0; s < seg->area_count; s++) {
 | 
			
		||||
			if (seg->area[s].type != AREA_PV ||
 | 
			
		||||
			    seg->area[s].u.pv.pv->dev != pv->dev)
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			if (!lv_used) {
 | 
			
		||||
				if (!(lvl = pool_alloc(cmd->mem, sizeof(*lvl)))) {
 | 
			
		||||
					log_error("lv_list alloc failed");
 | 
			
		||||
					return 0;
 | 
			
		||||
				}
 | 
			
		||||
				lvl->lv = lv;
 | 
			
		||||
				list_add(lvs_changed, &lvl->list);
 | 
			
		||||
				lv_used = 1;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			start_le = lv_mirr->le_count;
 | 
			
		||||
			if (!lv_extend_mirror(lv->vg->fid, lv_mirr,
 | 
			
		||||
					      seg->area[s].u.pv.pv,
 | 
			
		||||
					      seg->area[s].u.pv.pe,
 | 
			
		||||
					      seg->area_len, allocatable_pvs,
 | 
			
		||||
					      PVMOVE)) {
 | 
			
		||||
				log_error("Allocation for temporary "
 | 
			
		||||
					  "pvmove LV failed");
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			seg->area[s].type = AREA_LV;
 | 
			
		||||
			seg->area[s].u.lv.lv = lv_mirr;
 | 
			
		||||
			seg->area[s].u.lv.le = start_le;
 | 
			
		||||
 | 
			
		||||
			extent_count += seg->area_len;
 | 
			
		||||
 | 
			
		||||
			lv->status |= LOCKED;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_verbose("Moving %u extents of logical volume %s/%s", extent_count,
 | 
			
		||||
		    lv->vg->name, lv->name);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int remove_pvmove_mirrors(struct volume_group *vg,
 | 
			
		||||
			  struct logical_volume *lv_mirr)
 | 
			
		||||
{
 | 
			
		||||
	struct list *lvh, *segh;
 | 
			
		||||
	struct logical_volume *lv1;
 | 
			
		||||
	struct lv_segment *seg, *mir_seg;
 | 
			
		||||
	uint32_t s, c;
 | 
			
		||||
 | 
			
		||||
	list_iterate(lvh, &vg->lvs) {
 | 
			
		||||
		lv1 = list_item(lvh, struct lv_list)->lv;
 | 
			
		||||
		if (lv1 == lv_mirr)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		list_iterate(segh, &lv1->segments) {
 | 
			
		||||
			seg = list_item(segh, struct lv_segment);
 | 
			
		||||
			for (s = 0; s < seg->area_count; s++) {
 | 
			
		||||
				if (seg->area[s].type != AREA_LV ||
 | 
			
		||||
				    seg->area[s].u.lv.lv != lv_mirr)
 | 
			
		||||
					continue;
 | 
			
		||||
 | 
			
		||||
				if (!(mir_seg = find_seg_by_le(lv_mirr,
 | 
			
		||||
							       seg->area[s].u.
 | 
			
		||||
							       lv.le))) {
 | 
			
		||||
					log_error("No segment found with LE");
 | 
			
		||||
					return 0;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (mir_seg->type != SEG_MIRRORED ||
 | 
			
		||||
				    !(mir_seg->status & PVMOVE) ||
 | 
			
		||||
				    mir_seg->le != seg->area[s].u.lv.le ||
 | 
			
		||||
				    mir_seg->area_count != 2 ||
 | 
			
		||||
				    mir_seg->area_len != seg->area_len) {
 | 
			
		||||
					log_error("Incompatible segments");
 | 
			
		||||
					return 0;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (mir_seg->extents_moved == mir_seg->area_len)
 | 
			
		||||
					c = 1;
 | 
			
		||||
				else
 | 
			
		||||
					c = 0;
 | 
			
		||||
 | 
			
		||||
				seg->area[s].type = AREA_PV;
 | 
			
		||||
				seg->area[s].u.pv.pv = mir_seg->area[c].u.pv.pv;
 | 
			
		||||
				seg->area[s].u.pv.pe = mir_seg->area[c].u.pv.pe;
 | 
			
		||||
 | 
			
		||||
				mir_seg->type = SEG_STRIPED;
 | 
			
		||||
				mir_seg->area_count = 1;
 | 
			
		||||
 | 
			
		||||
				lv1->status &= ~LOCKED;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct physical_volume *get_pvmove_pv_from_lv_mirr(struct logical_volume
 | 
			
		||||
						   *lv_mirr)
 | 
			
		||||
{
 | 
			
		||||
	struct list *segh;
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
 | 
			
		||||
	list_iterate(segh, &lv_mirr->segments) {
 | 
			
		||||
		seg = list_item(segh, struct lv_segment);
 | 
			
		||||
		if (seg->type != SEG_MIRRORED)
 | 
			
		||||
			continue;
 | 
			
		||||
		if (seg->area[0].type != AREA_PV)
 | 
			
		||||
			continue;
 | 
			
		||||
		return seg->area[0].u.pv.pv;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct physical_volume *get_pvmove_pv_from_lv(struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
	struct list *segh;
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
	uint32_t s;
 | 
			
		||||
 | 
			
		||||
	list_iterate(segh, &lv->segments) {
 | 
			
		||||
		seg = list_item(segh, struct lv_segment);
 | 
			
		||||
		for (s = 0; s < seg->area_count; s++) {
 | 
			
		||||
			if (seg->area[s].type != AREA_LV)
 | 
			
		||||
				continue;
 | 
			
		||||
			return get_pvmove_pv_from_lv_mirr(seg->area[s].u.lv.lv);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct logical_volume *find_pvmove_lv(struct volume_group *vg,
 | 
			
		||||
				      struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct list *lvh, *segh;
 | 
			
		||||
	struct logical_volume *lv;
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
 | 
			
		||||
	/* Loop through all LVs */
 | 
			
		||||
	list_iterate(lvh, &vg->lvs) {
 | 
			
		||||
		lv = list_item(lvh, struct lv_list)->lv;
 | 
			
		||||
 | 
			
		||||
		if (!(lv->status & PVMOVE))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		list_iterate(segh, &lv->segments) {
 | 
			
		||||
			seg = list_item(segh, struct lv_segment);
 | 
			
		||||
			if (seg->area[0].type != AREA_PV)
 | 
			
		||||
				continue;
 | 
			
		||||
			if (seg->area[0].u.pv.pv->dev != dev)
 | 
			
		||||
				continue;
 | 
			
		||||
			return lv;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct list *lvs_using_lv(struct cmd_context *cmd, struct volume_group *vg,
 | 
			
		||||
			  struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
	struct list *lvh, *segh, *lvs;
 | 
			
		||||
	struct logical_volume *lv1;
 | 
			
		||||
	struct lv_list *lvl;
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
	uint32_t s;
 | 
			
		||||
 | 
			
		||||
	if (!(lvs = pool_alloc(cmd->mem, sizeof(*lvs)))) {
 | 
			
		||||
		log_error("lvs list alloc failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	list_init(lvs);
 | 
			
		||||
 | 
			
		||||
	/* Loop through all LVs except the one supplied */
 | 
			
		||||
	list_iterate(lvh, &vg->lvs) {
 | 
			
		||||
		lv1 = list_item(lvh, struct lv_list)->lv;
 | 
			
		||||
		if (lv1 == lv)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		list_iterate(segh, &lv1->segments) {
 | 
			
		||||
			seg = list_item(segh, struct lv_segment);
 | 
			
		||||
			for (s = 0; s < seg->area_count; s++) {
 | 
			
		||||
				if (seg->area[s].type != AREA_LV ||
 | 
			
		||||
				    seg->area[s].u.lv.lv != lv)
 | 
			
		||||
					continue;
 | 
			
		||||
				if (!(lvl = pool_alloc(cmd->mem, sizeof(*lvl)))) {
 | 
			
		||||
					log_error("lv_list alloc failed");
 | 
			
		||||
					return NULL;
 | 
			
		||||
				}
 | 
			
		||||
				lvl->lv = lv1;
 | 
			
		||||
				list_add(lvs, &lvl->list);
 | 
			
		||||
				goto next_lv;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	      next_lv:
 | 
			
		||||
		;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return lvs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float pvmove_percent(struct logical_volume *lv_mirr)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t numerator = 0u, denominator = 0u;
 | 
			
		||||
	struct list *segh;
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
 | 
			
		||||
	list_iterate(segh, &lv_mirr->segments) {
 | 
			
		||||
		seg = list_item(segh, struct lv_segment);
 | 
			
		||||
		if (!(seg->status & PVMOVE))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		numerator += seg->extents_moved;
 | 
			
		||||
		denominator += seg->area_len;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return denominator ? (float) numerator *100 / denominator : 100.0;
 | 
			
		||||
}
 | 
			
		||||
@@ -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;
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -11,10 +11,9 @@
 | 
			
		||||
#define _LVM_LIB_H
 | 
			
		||||
 | 
			
		||||
#define _REENTRANT
 | 
			
		||||
#define _GNU_SOURCE
 | 
			
		||||
 | 
			
		||||
#include "log.h"
 | 
			
		||||
#include "dbg_malloc.h"
 | 
			
		||||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include <dlfcn.h>
 | 
			
		||||
 | 
			
		||||
void *load_shared_library(struct config_tree *cf, const char *libname,
 | 
			
		||||
			  const char *what);
 | 
			
		||||
 
 | 
			
		||||
@@ -7,9 +7,9 @@
 | 
			
		||||
#ifndef _LVM_DBG_MALLOC_H
 | 
			
		||||
#define _LVM_DBG_MALLOC_H
 | 
			
		||||
 | 
			
		||||
#include "lvm-types.h"
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_MEM
 | 
			
		||||
void *malloc_aux(size_t s, const char *file, int line);
 | 
			
		||||
@@ -18,15 +18,15 @@ void *realloc_aux(void *p, unsigned int s, const char *file, int line);
 | 
			
		||||
int dump_memory(void);
 | 
			
		||||
void bounds_check(void);
 | 
			
		||||
 | 
			
		||||
#define dbg_malloc(s) malloc_aux((s), __FILE__, __LINE__)
 | 
			
		||||
#define dbg_free(p) free_aux(p)
 | 
			
		||||
#define dbg_realloc(p, s) realloc_aux(p, s, __FILE__, __LINE__)
 | 
			
		||||
#  define dbg_malloc(s) malloc_aux((s), __FILE__, __LINE__)
 | 
			
		||||
#  define dbg_free(p) free_aux(p)
 | 
			
		||||
#  define dbg_realloc(p, s) realloc_aux(p, s, __FILE__, __LINE__)
 | 
			
		||||
#else
 | 
			
		||||
#define dbg_malloc(s) malloc(s)
 | 
			
		||||
#define dbg_free(p) free(p)
 | 
			
		||||
#define dbg_realloc(p, s) realloc(p, s)
 | 
			
		||||
#define dump_memory()
 | 
			
		||||
#define bounds_check()
 | 
			
		||||
#  define dbg_malloc(s) malloc(s)
 | 
			
		||||
#  define dbg_free(p) free(p)
 | 
			
		||||
#  define dbg_realloc(p, s) realloc(p, s)
 | 
			
		||||
#  define dump_memory()
 | 
			
		||||
#  define bounds_check()
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static inline char *dbg_strdup(const char *str)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										144
									
								
								lib/mm/memlock.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								lib/mm/memlock.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,144 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2003 Sistina Software (UK) Limited.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "lib.h"
 | 
			
		||||
#include "memlock.h"
 | 
			
		||||
#include "pool.h"
 | 
			
		||||
#include "defaults.h"
 | 
			
		||||
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <sys/time.h>
 | 
			
		||||
#include <sys/resource.h>
 | 
			
		||||
 | 
			
		||||
#ifndef DEVMAPPER_SUPPORT
 | 
			
		||||
 | 
			
		||||
void memlock_inc(void)
 | 
			
		||||
{
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
void memlock_dec(void)
 | 
			
		||||
{
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
int memlock(void)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else				/* DEVMAPPER_SUPPORT */
 | 
			
		||||
 | 
			
		||||
static size_t _size_stack;
 | 
			
		||||
static size_t _size_malloc_tmp;
 | 
			
		||||
static size_t _size_malloc = 2000000;
 | 
			
		||||
 | 
			
		||||
static void *_malloc_mem = NULL;
 | 
			
		||||
static int _memlock_count = 0;
 | 
			
		||||
static int _priority;
 | 
			
		||||
static int _default_priority;
 | 
			
		||||
 | 
			
		||||
static void _touch_memory(void *mem, size_t size)
 | 
			
		||||
{
 | 
			
		||||
	size_t pagesize = getpagesize();
 | 
			
		||||
	void *pos = mem;
 | 
			
		||||
	void *end = mem + size - sizeof(long);
 | 
			
		||||
 | 
			
		||||
	while (pos < end) {
 | 
			
		||||
		*(long *) pos = 1;
 | 
			
		||||
		pos += pagesize;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _allocate_memory(void)
 | 
			
		||||
{
 | 
			
		||||
	void *stack_mem, *temp_malloc_mem;
 | 
			
		||||
 | 
			
		||||
	if ((stack_mem = alloca(_size_stack)))
 | 
			
		||||
		_touch_memory(stack_mem, _size_stack);
 | 
			
		||||
 | 
			
		||||
	if ((temp_malloc_mem = malloc(_size_malloc_tmp)))
 | 
			
		||||
		_touch_memory(temp_malloc_mem, _size_malloc_tmp);
 | 
			
		||||
 | 
			
		||||
	if ((_malloc_mem = malloc(_size_malloc)))
 | 
			
		||||
		_touch_memory(_malloc_mem, _size_malloc);
 | 
			
		||||
 | 
			
		||||
	free(temp_malloc_mem);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _release_memory(void)
 | 
			
		||||
{
 | 
			
		||||
	free(_malloc_mem);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Stop memory getting swapped out */
 | 
			
		||||
static void _lock_memory(void)
 | 
			
		||||
{
 | 
			
		||||
#ifdef MCL_CURRENT
 | 
			
		||||
	if (mlockall(MCL_CURRENT | MCL_FUTURE))
 | 
			
		||||
		log_sys_error("mlockall", "");
 | 
			
		||||
	else
 | 
			
		||||
		log_very_verbose("Locking memory");
 | 
			
		||||
#endif
 | 
			
		||||
	_allocate_memory();
 | 
			
		||||
 | 
			
		||||
	errno = 0;
 | 
			
		||||
	if (((_priority = getpriority(PRIO_PROCESS, 0)) == -1) && errno)
 | 
			
		||||
		log_sys_error("getpriority", "");
 | 
			
		||||
	else
 | 
			
		||||
		if (setpriority(PRIO_PROCESS, 0, _default_priority))
 | 
			
		||||
			log_error("setpriority %u failed: %s",
 | 
			
		||||
				  _default_priority, strerror(errno));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _unlock_memory(void)
 | 
			
		||||
{
 | 
			
		||||
#ifdef MCL_CURRENT
 | 
			
		||||
	if (munlockall())
 | 
			
		||||
		log_sys_error("munlockall", "");
 | 
			
		||||
	else
 | 
			
		||||
		log_very_verbose("Unlocking memory");
 | 
			
		||||
#endif
 | 
			
		||||
	_release_memory();
 | 
			
		||||
	if (setpriority(PRIO_PROCESS, 0, _priority))
 | 
			
		||||
		log_error("setpriority %u failed: %s", _priority,
 | 
			
		||||
			  strerror(errno));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void memlock_inc(void)
 | 
			
		||||
{
 | 
			
		||||
	if (!_memlock_count++)
 | 
			
		||||
		_lock_memory();
 | 
			
		||||
	log_debug("memlock_count inc to %d", _memlock_count);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void memlock_dec(void)
 | 
			
		||||
{
 | 
			
		||||
	if (_memlock_count && (!--_memlock_count))
 | 
			
		||||
		_unlock_memory();
 | 
			
		||||
	log_debug("memlock_count dec to %d", _memlock_count);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int memlock(void)
 | 
			
		||||
{
 | 
			
		||||
	return _memlock_count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void memlock_init(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	_size_stack = find_config_int(cmd->cf->root,
 | 
			
		||||
				      "activation/reserved_stack",
 | 
			
		||||
				      '/', DEFAULT_RESERVED_STACK) * 1024;
 | 
			
		||||
	_size_malloc_tmp = find_config_int(cmd->cf->root,
 | 
			
		||||
					   "activation/reserved_memory",
 | 
			
		||||
					   '/', DEFAULT_RESERVED_MEMORY) * 1024;
 | 
			
		||||
	_default_priority = find_config_int(cmd->cf->root,
 | 
			
		||||
				            "activation/process_priority",
 | 
			
		||||
				            '/', DEFAULT_PROCESS_PRIORITY);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										17
									
								
								lib/mm/memlock.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								lib/mm/memlock.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef LVM_MEMLOCK_H
 | 
			
		||||
#define LVM_MEMLOCK_H
 | 
			
		||||
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
 | 
			
		||||
void memlock_inc(void);
 | 
			
		||||
void memlock_dec(void);
 | 
			
		||||
int memlock(void);
 | 
			
		||||
void memlock_init(struct cmd_context *cmd);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -8,10 +8,37 @@
 | 
			
		||||
#ifndef _LVM_XLATE_H
 | 
			
		||||
#define _LVM_XLATE_H
 | 
			
		||||
 | 
			
		||||
#include <asm/byteorder.h>
 | 
			
		||||
 | 
			
		||||
#define xlate16(x) __cpu_to_le16((x))
 | 
			
		||||
#define xlate32(x) __cpu_to_le32((x))
 | 
			
		||||
#define xlate64(x) __cpu_to_le64((x))
 | 
			
		||||
#ifdef linux
 | 
			
		||||
#  include <asm/byteorder.h>
 | 
			
		||||
#  define xlate16(x) __cpu_to_le16((x))
 | 
			
		||||
#  define xlate32(x) __cpu_to_le32((x))
 | 
			
		||||
#  define xlate64(x) __cpu_to_le64((x))
 | 
			
		||||
#else
 | 
			
		||||
#  include <machine/endian.h>
 | 
			
		||||
#  if !defined(BYTE_ORDER) || \
 | 
			
		||||
      (BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN)
 | 
			
		||||
#    error "Undefined or unrecognised BYTE_ORDER";
 | 
			
		||||
#  endif
 | 
			
		||||
#  if BYTE_ORDER == LITTLE_ENDIAN
 | 
			
		||||
#    define xlate16(x) (x)
 | 
			
		||||
#    define xlate32(x) (x)
 | 
			
		||||
#    define xlate64(x) (x)
 | 
			
		||||
#  else
 | 
			
		||||
#    define xlate16(x) (((x) & 0x00ffU) << 8 | \
 | 
			
		||||
		        ((x) & 0xff00U) >> 8)
 | 
			
		||||
#    define xlate32(x) (((x) & 0x000000ffU) << 24 | \
 | 
			
		||||
		        ((x) & 0xff000000U) >> 24 | \
 | 
			
		||||
		        ((x) & 0x0000ff00U) << 8  | \
 | 
			
		||||
		        ((x) & 0x00ff0000U) >> 8)
 | 
			
		||||
#    define xlate64(x) (((x) & 0x00000000000000ffU) << 56 | \
 | 
			
		||||
                        ((x) & 0xff00000000000000U) >> 56 | \
 | 
			
		||||
                        ((x) & 0x000000000000ff00U) << 40 | \
 | 
			
		||||
                        ((x) & 0x00ff000000000000U) >> 40 | \
 | 
			
		||||
                        ((x) & 0x0000000000ff0000U) << 24 | \
 | 
			
		||||
                        ((x) & 0x0000ff0000000000U) >> 24 | \
 | 
			
		||||
                        ((x) & 0x00000000ff000000U) << 8 | \
 | 
			
		||||
                        ((x) & 0x000000ff00000000U) >> 8)
 | 
			
		||||
#  endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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* */
 | 
			
		||||
 
 | 
			
		||||
@@ -27,8 +27,6 @@
 | 
			
		||||
#include "display.h"
 | 
			
		||||
#include "activate.h"
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
/* 
 | 
			
		||||
 * For macro use
 | 
			
		||||
 */
 | 
			
		||||
@@ -165,20 +163,26 @@ static int _lvstatus_disp(struct report_handle *rh, struct field *field,
 | 
			
		||||
	const struct logical_volume *lv = (const struct logical_volume *) data;
 | 
			
		||||
	struct lvinfo info;
 | 
			
		||||
	char *repstr;
 | 
			
		||||
	struct snapshot *snap;
 | 
			
		||||
	float snap_percent;
 | 
			
		||||
 | 
			
		||||
	if (!(repstr = pool_zalloc(rh->mem, 7))) {
 | 
			
		||||
		log_error("pool_alloc failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lv_is_origin(lv))
 | 
			
		||||
	if (lv->status & PVMOVE)
 | 
			
		||||
		repstr[0] = 'p';
 | 
			
		||||
	else if (lv_is_origin(lv))
 | 
			
		||||
		repstr[0] = 'o';
 | 
			
		||||
	else if (find_cow(lv))
 | 
			
		||||
		repstr[0] = 's';
 | 
			
		||||
	else
 | 
			
		||||
		repstr[0] = '-';
 | 
			
		||||
 | 
			
		||||
	if (lv->status & LVM_WRITE)
 | 
			
		||||
	if (lv->status & PVMOVE)
 | 
			
		||||
		repstr[1] = '-';
 | 
			
		||||
	else if (lv->status & LVM_WRITE)
 | 
			
		||||
		repstr[1] = 'w';
 | 
			
		||||
	else
 | 
			
		||||
		repstr[1] = 'r';
 | 
			
		||||
@@ -188,6 +192,9 @@ static int _lvstatus_disp(struct report_handle *rh, struct field *field,
 | 
			
		||||
	else
 | 
			
		||||
		repstr[2] = 'n';
 | 
			
		||||
 | 
			
		||||
	if (lv->status & LOCKED)
 | 
			
		||||
		repstr[2] = toupper(repstr[2]);
 | 
			
		||||
 | 
			
		||||
	if (lv->status & FIXED_MINOR)
 | 
			
		||||
		repstr[3] = 'm';	/* Fixed Minor */
 | 
			
		||||
	else
 | 
			
		||||
@@ -202,6 +209,18 @@ static int _lvstatus_disp(struct report_handle *rh, struct field *field,
 | 
			
		||||
			repstr[5] = 'o';	/* Open */
 | 
			
		||||
		else
 | 
			
		||||
			repstr[5] = '-';
 | 
			
		||||
 | 
			
		||||
		/* Snapshot dropped? */
 | 
			
		||||
		if ((snap = find_cow(lv)) &&
 | 
			
		||||
		    (!lv_snapshot_percent(snap->cow, &snap_percent) ||
 | 
			
		||||
		     snap_percent < 0 || snap_percent >= 100)) {
 | 
			
		||||
			repstr[0] = toupper(repstr[0]);
 | 
			
		||||
			if (info.suspended)
 | 
			
		||||
				repstr[4] = 'S';
 | 
			
		||||
			else
 | 
			
		||||
				repstr[4] = 'I';
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	} else {
 | 
			
		||||
		repstr[4] = '-';
 | 
			
		||||
		repstr[5] = '-';
 | 
			
		||||
@@ -282,7 +301,7 @@ static int _segtype_disp(struct report_handle *rh, struct field *field,
 | 
			
		||||
{
 | 
			
		||||
	const struct lv_segment *seg = (const struct lv_segment *) data;
 | 
			
		||||
 | 
			
		||||
	if (seg->stripes == 1)
 | 
			
		||||
	if (seg->area_count == 1)
 | 
			
		||||
		field->report_string = "linear";
 | 
			
		||||
	else
 | 
			
		||||
		field->report_string = get_segtype_string(seg->type);
 | 
			
		||||
@@ -306,6 +325,28 @@ static int _origin_disp(struct report_handle *rh, struct field *field,
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _movepv_disp(struct report_handle *rh, struct field *field,
 | 
			
		||||
			const void *data)
 | 
			
		||||
{
 | 
			
		||||
	const struct logical_volume *lv = (const struct logical_volume *) data;
 | 
			
		||||
	const char *name;
 | 
			
		||||
	struct list *segh;
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
 | 
			
		||||
	list_iterate(segh, &lv->segments) {
 | 
			
		||||
		seg = list_item(segh, struct lv_segment);
 | 
			
		||||
		if (!(seg->status & PVMOVE))
 | 
			
		||||
			continue;
 | 
			
		||||
		name = dev_name(seg->area[0].u.pv.pv->dev);
 | 
			
		||||
		return _string_disp(rh, field, &name);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	field->report_string = "";
 | 
			
		||||
	field->sort_value = (const void *) field->report_string;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _size32_disp(struct report_handle *rh, struct field *field,
 | 
			
		||||
			const void *data)
 | 
			
		||||
{
 | 
			
		||||
@@ -456,7 +497,7 @@ static int _uuid_disp(struct report_handle *rh, struct field *field,
 | 
			
		||||
{
 | 
			
		||||
	char *repstr = NULL;
 | 
			
		||||
 | 
			
		||||
	if (!(field->report_string = pool_alloc(rh->mem, 40))) {
 | 
			
		||||
	if (!(repstr = pool_alloc(rh->mem, 40))) {
 | 
			
		||||
		log_error("pool_alloc failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -546,6 +587,7 @@ static int _snpercent_disp(struct report_handle *rh, struct field *field,
 | 
			
		||||
{
 | 
			
		||||
	const struct logical_volume *lv = (const struct logical_volume *) data;
 | 
			
		||||
	struct snapshot *snap;
 | 
			
		||||
	struct lvinfo info;
 | 
			
		||||
	float snap_percent;
 | 
			
		||||
	uint64_t *sortval;
 | 
			
		||||
	char *repstr;
 | 
			
		||||
@@ -555,10 +597,17 @@ static int _snpercent_disp(struct report_handle *rh, struct field *field,
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(snap = find_cow(lv))
 | 
			
		||||
	    || !lv_snapshot_percent(snap->cow, &snap_percent)) {
 | 
			
		||||
	if (!(snap = find_cow(lv)) ||
 | 
			
		||||
	    (lv_info(snap->cow, &info) && !info.exists)) {
 | 
			
		||||
		field->report_string = "";
 | 
			
		||||
		*sortval = __UINT64_C(0);
 | 
			
		||||
		*sortval = UINT64_C(0);
 | 
			
		||||
		field->sort_value = sortval;
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!lv_snapshot_percent(snap->cow, &snap_percent) || snap_percent < 0) {
 | 
			
		||||
		field->report_string = "100.00";
 | 
			
		||||
		*sortval = UINT64_C(100);
 | 
			
		||||
		field->sort_value = sortval;
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
@@ -568,15 +617,54 @@ static int _snpercent_disp(struct report_handle *rh, struct field *field,
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (snap_percent == -1)
 | 
			
		||||
		snap_percent = 100;
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(repstr, 7, "%.2f", snap_percent) < 0) {
 | 
			
		||||
		log_error("snapshot percentage too large");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*sortval = snap_percent * __UINT64_C(1000);
 | 
			
		||||
	*sortval = snap_percent * UINT64_C(1000);
 | 
			
		||||
	field->sort_value = sortval;
 | 
			
		||||
	field->report_string = repstr;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _movepercent_disp(struct report_handle *rh, struct field *field,
 | 
			
		||||
			     const void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct logical_volume *lv = (struct logical_volume *) data;
 | 
			
		||||
	float move_percent;
 | 
			
		||||
	uint64_t *sortval;
 | 
			
		||||
	char *repstr;
 | 
			
		||||
 | 
			
		||||
	if (!(sortval = pool_alloc(rh->mem, sizeof(uint64_t)))) {
 | 
			
		||||
		log_error("pool_alloc failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(lv->status & PVMOVE)) {
 | 
			
		||||
		field->report_string = "";
 | 
			
		||||
		*sortval = UINT64_C(0);
 | 
			
		||||
		field->sort_value = sortval;
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Update percentage done in lv metadata in core */
 | 
			
		||||
	lv_mirror_percent(lv, 0, &move_percent, NULL);
 | 
			
		||||
 | 
			
		||||
	move_percent = pvmove_percent(lv);
 | 
			
		||||
 | 
			
		||||
	if (!(repstr = pool_zalloc(rh->mem, 8))) {
 | 
			
		||||
		log_error("pool_alloc failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(repstr, 7, "%.2f", move_percent) < 0) {
 | 
			
		||||
		log_error("move percentage too large");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*sortval = move_percent * UINT64_C(1000);
 | 
			
		||||
	field->sort_value = sortval;
 | 
			
		||||
	field->report_string = repstr;
 | 
			
		||||
 | 
			
		||||
@@ -744,7 +832,8 @@ static int _parse_options(struct report_handle *rh, const char *format)
 | 
			
		||||
		while (*we && *we != ',')
 | 
			
		||||
			we++;
 | 
			
		||||
		if (!_field_match(rh, ws, (size_t) (we - ws))) {
 | 
			
		||||
			log_error("Unrecognised field: %.*s", (int) (we - ws), ws);
 | 
			
		||||
			log_error("Unrecognised field: %.*s", (int) (we - ws),
 | 
			
		||||
				  ws);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -765,7 +854,8 @@ static int _parse_keys(struct report_handle *rh, const char *keys)
 | 
			
		||||
		while (*we && *we != ',')
 | 
			
		||||
			we++;
 | 
			
		||||
		if (!_key_match(rh, ws, (size_t) (we - ws))) {
 | 
			
		||||
			log_error("Unrecognised field: %.*s", (int) (we - ws), ws);
 | 
			
		||||
			log_error("Unrecognised field: %.*s", (int) (we - ws),
 | 
			
		||||
				  ws);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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:
 | 
			
		||||
		*;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,10 +7,14 @@
 | 
			
		||||
#ifndef _LVM_LIST_H
 | 
			
		||||
#define _LVM_LIST_H
 | 
			
		||||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
 | 
			
		||||
struct list {
 | 
			
		||||
	struct list *n, *p;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define LIST_INIT(name)	struct list name = { &(name), &(name) }
 | 
			
		||||
 | 
			
		||||
static inline void list_init(struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	head->n = head->p = head;
 | 
			
		||||
@@ -54,9 +58,17 @@ static inline int list_end(struct list *head, struct list *elem)
 | 
			
		||||
	return elem->n == head;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline struct list *list_next(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	return (list_end(head, elem) ? NULL : elem->n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define list_iterate(v, head) \
 | 
			
		||||
	for (v = (head)->n; v != head; v = v->n)
 | 
			
		||||
 | 
			
		||||
#define list_uniterate(v, head, start) \
 | 
			
		||||
	for (v = (start)->p; v != head; v = v->p)
 | 
			
		||||
 | 
			
		||||
#define list_iterate_safe(v, t, head) \
 | 
			
		||||
	for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
 | 
			
		||||
 | 
			
		||||
@@ -74,8 +86,14 @@ static inline unsigned int list_size(const struct list *head)
 | 
			
		||||
#define list_item(v, t) \
 | 
			
		||||
    ((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->list))
 | 
			
		||||
 | 
			
		||||
/* Given a known element in a known structure, locate the struct list */
 | 
			
		||||
#define list_head(v, t, e) \
 | 
			
		||||
    (((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->e))->list)
 | 
			
		||||
#define list_struct_base(v, t, h) \
 | 
			
		||||
    ((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->h))
 | 
			
		||||
 | 
			
		||||
/* Given a known element in a known structure, locate another */
 | 
			
		||||
#define struct_field(v, t, e, f) \
 | 
			
		||||
    (((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->e))->f)
 | 
			
		||||
 | 
			
		||||
/* Given a known element in a known structure, locate the list head */
 | 
			
		||||
#define list_head(v, t, e) struct_field(v, t, e, list)
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -4,60 +4,460 @@
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "libdevmapper.h"
 | 
			
		||||
#include "libdm-targets.h"
 | 
			
		||||
#include "libdm-common.h"
 | 
			
		||||
#include "libdm-compat.h"
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <dirent.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <linux/kdev_t.h>
 | 
			
		||||
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <linux/limits.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <linux/dm-ioctl.h>
 | 
			
		||||
 | 
			
		||||
#include "libdm-targets.h"
 | 
			
		||||
#include "libdm-common.h"
 | 
			
		||||
 | 
			
		||||
#define ALIGNMENT sizeof(int)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Ensure build compatibility.  The hard-coded version here (major, minor)
 | 
			
		||||
 * is the highest present in the _cmd_data array below.
 | 
			
		||||
 * Ensure build compatibility.  
 | 
			
		||||
 * The hard-coded versions here are the highest present 
 | 
			
		||||
 * in the _cmd_data arrays.
 | 
			
		||||
 */
 | 
			
		||||
#if DM_VERSION_MAJOR != 1 || DM_VERSION_MINOR < 0
 | 
			
		||||
	#error The version of dm-ioctl.h included is incompatible.
 | 
			
		||||
 | 
			
		||||
#if !((DM_VERSION_MAJOR == 1 && DM_VERSION_MINOR >= 0) || \
 | 
			
		||||
      (DM_VERSION_MAJOR == 4 && DM_VERSION_MINOR >= 0))
 | 
			
		||||
#error The version of dm-ioctl.h included is incompatible.
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static struct {
 | 
			
		||||
	char *name;
 | 
			
		||||
	int cmd;
 | 
			
		||||
	int version[3];
 | 
			
		||||
} _cmd_data[] = {
 | 
			
		||||
	{ "create",	DM_DEV_CREATE,    {1, 0, 0} },
 | 
			
		||||
	{ "reload",	DM_DEV_RELOAD,    {1, 0, 0} },
 | 
			
		||||
	{ "remove",	DM_DEV_REMOVE,    {1, 0, 0} },
 | 
			
		||||
	{ "remove_all",	DM_REMOVE_ALL,    {1, 0, 0} },
 | 
			
		||||
	{ "suspend",	DM_DEV_SUSPEND,   {1, 0, 0} },
 | 
			
		||||
	{ "resume",	DM_DEV_SUSPEND,   {1, 0, 0} },
 | 
			
		||||
	{ "info",	DM_DEV_STATUS,    {1, 0, 0} },
 | 
			
		||||
	{ "deps",	DM_DEV_DEPS,      {1, 0, 0} },
 | 
			
		||||
	{ "rename",	DM_DEV_RENAME,    {1, 0, 0} },
 | 
			
		||||
	{ "version",	DM_VERSION,       {1, 0, 0} },
 | 
			
		||||
	{ "status",	DM_TARGET_STATUS, {1, 0, 0} },
 | 
			
		||||
	{ "table",	DM_TARGET_STATUS, {1, 0, 0} },
 | 
			
		||||
	{ "waitevent",	DM_TARGET_WAIT,   {1, 0, 0} },
 | 
			
		||||
/* dm major version no for running kernel */
 | 
			
		||||
static int _dm_version = DM_VERSION_MAJOR;
 | 
			
		||||
static int _log_suppress = 0;
 | 
			
		||||
 | 
			
		||||
static int _control_fd = -1;
 | 
			
		||||
static int _version_checked = 0;
 | 
			
		||||
static int _version_ok = 1;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Support both old and new major numbers to ease the transition.
 | 
			
		||||
 * Clumsy, but only temporary.
 | 
			
		||||
 */
 | 
			
		||||
#if DM_VERSION_MAJOR == 4 && defined(DM_COMPAT)
 | 
			
		||||
const int _dm_compat = 1;
 | 
			
		||||
#else
 | 
			
		||||
const int _dm_compat = 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* *INDENT-OFF* */
 | 
			
		||||
static struct cmd_data _cmd_data_v4[] = {
 | 
			
		||||
	{"create",	DM_DEV_CREATE,		{4, 0, 0}},
 | 
			
		||||
	{"reload",	DM_TABLE_LOAD,		{4, 0, 0}},
 | 
			
		||||
	{"remove",	DM_DEV_REMOVE,		{4, 0, 0}},
 | 
			
		||||
	{"remove_all",	DM_REMOVE_ALL,		{4, 0, 0}},
 | 
			
		||||
	{"suspend",	DM_DEV_SUSPEND,		{4, 0, 0}},
 | 
			
		||||
	{"resume",	DM_DEV_SUSPEND,		{4, 0, 0}},
 | 
			
		||||
	{"info",	DM_DEV_STATUS,		{4, 0, 0}},
 | 
			
		||||
	{"deps",	DM_TABLE_DEPS,		{4, 0, 0}},
 | 
			
		||||
	{"rename",	DM_DEV_RENAME,		{4, 0, 0}},
 | 
			
		||||
	{"version",	DM_VERSION,		{4, 0, 0}},
 | 
			
		||||
	{"status",	DM_TABLE_STATUS,	{4, 0, 0}},
 | 
			
		||||
	{"table",	DM_TABLE_STATUS,	{4, 0, 0}},
 | 
			
		||||
	{"waitevent",	DM_DEV_WAIT,		{4, 0, 0}},
 | 
			
		||||
	{"names",	DM_LIST_DEVICES,	{4, 0, 0}},
 | 
			
		||||
	{"clear",	DM_TABLE_CLEAR,		{4, 0, 0}},
 | 
			
		||||
};
 | 
			
		||||
/* *INDENT-ON* */
 | 
			
		||||
 | 
			
		||||
#define ALIGNMENT_V1 sizeof(int)
 | 
			
		||||
#define ALIGNMENT 8
 | 
			
		||||
 | 
			
		||||
/* FIXME Rejig library to record & use errno instead */
 | 
			
		||||
#ifndef DM_EXISTS_FLAG
 | 
			
		||||
#  define DM_EXISTS_FLAG 0x00000004
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void *_align(void *ptr, unsigned int a)
 | 
			
		||||
{
 | 
			
		||||
	register unsigned long align = --a;
 | 
			
		||||
	register unsigned long agn = --a;
 | 
			
		||||
 | 
			
		||||
	return (void *) (((unsigned long) ptr + align) & ~align);
 | 
			
		||||
	return (void *) (((unsigned long) ptr + agn) & ~agn);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _dm_task_get_driver_version_v1(struct dm_task *dmt, char *version,
 | 
			
		||||
					  size_t size)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int *v;
 | 
			
		||||
 | 
			
		||||
	if (!dmt->dmi.v1) {
 | 
			
		||||
		version[0] = '\0';
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	v = dmt->dmi.v1->version;
 | 
			
		||||
	snprintf(version, size, "%u.%u.%u", v[0], v[1], v[2]);
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Unmarshall the target info returned from a status call */
 | 
			
		||||
static int _unmarshal_status_v1(struct dm_task *dmt, struct dm_ioctl_v1 *dmi)
 | 
			
		||||
{
 | 
			
		||||
	char *outbuf = (char *) dmi + dmi->data_start;
 | 
			
		||||
	char *outptr = outbuf;
 | 
			
		||||
	int32_t i;
 | 
			
		||||
	struct dm_target_spec_v1 *spec;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < dmi->target_count; i++) {
 | 
			
		||||
		spec = (struct dm_target_spec_v1 *) outptr;
 | 
			
		||||
 | 
			
		||||
		if (!dm_task_add_target(dmt, spec->sector_start,
 | 
			
		||||
					(uint64_t) spec->length,
 | 
			
		||||
					spec->target_type,
 | 
			
		||||
					outptr + sizeof(*spec)))
 | 
			
		||||
			return 0;
 | 
			
		||||
 | 
			
		||||
		outptr = outbuf + spec->next;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _dm_format_dev_v1(char *buf, int bufsize, uint32_t dev_major, uint32_t dev_minor)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	if (bufsize < 8)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	r = snprintf(buf, bufsize, "%03x:%03x", dev_major, dev_minor);
 | 
			
		||||
	if (r < 0 || r > bufsize - 1)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _dm_task_get_info_v1(struct dm_task *dmt, struct dm_info *info)
 | 
			
		||||
{
 | 
			
		||||
	if (!dmt->dmi.v1)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	memset(info, 0, sizeof(*info));
 | 
			
		||||
 | 
			
		||||
	info->exists = dmt->dmi.v1->flags & DM_EXISTS_FLAG ? 1 : 0;
 | 
			
		||||
	if (!info->exists)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	info->suspended = dmt->dmi.v1->flags & DM_SUSPEND_FLAG ? 1 : 0;
 | 
			
		||||
	info->read_only = dmt->dmi.v1->flags & DM_READONLY_FLAG ? 1 : 0;
 | 
			
		||||
	info->target_count = dmt->dmi.v1->target_count;
 | 
			
		||||
	info->open_count = dmt->dmi.v1->open_count;
 | 
			
		||||
	info->event_nr = 0;
 | 
			
		||||
	info->major = MAJOR(dmt->dmi.v1->dev);
 | 
			
		||||
	info->minor = MINOR(dmt->dmi.v1->dev);
 | 
			
		||||
	info->live_table = 1;
 | 
			
		||||
	info->inactive_table = 0;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char *_dm_task_get_name_v1(struct dm_task *dmt)
 | 
			
		||||
{
 | 
			
		||||
	return (dmt->dmi.v1->name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char *_dm_task_get_uuid_v1(struct dm_task *dmt)
 | 
			
		||||
{
 | 
			
		||||
	return (dmt->dmi.v1->uuid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct dm_deps *_dm_task_get_deps_v1(struct dm_task *dmt)
 | 
			
		||||
{
 | 
			
		||||
	log_error("deps version 1 no longer supported by libdevmapper");
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct dm_names *_dm_task_get_names_v1(struct dm_task *dmt)
 | 
			
		||||
{
 | 
			
		||||
	return (struct dm_names *) (((void *) dmt->dmi.v1) +
 | 
			
		||||
				    dmt->dmi.v1->data_start);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void *_add_target_v1(struct target *t, void *out, void *end)
 | 
			
		||||
{
 | 
			
		||||
	void *out_sp = out;
 | 
			
		||||
	struct dm_target_spec_v1 sp;
 | 
			
		||||
	size_t sp_size = sizeof(struct dm_target_spec_v1);
 | 
			
		||||
	int len;
 | 
			
		||||
	const char no_space[] = "Ran out of memory building ioctl parameter";
 | 
			
		||||
 | 
			
		||||
	out += sp_size;
 | 
			
		||||
	if (out >= end) {
 | 
			
		||||
		log_error(no_space);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sp.status = 0;
 | 
			
		||||
	sp.sector_start = t->start;
 | 
			
		||||
	sp.length = t->length;
 | 
			
		||||
	strncpy(sp.target_type, t->type, sizeof(sp.target_type));
 | 
			
		||||
 | 
			
		||||
	len = strlen(t->params);
 | 
			
		||||
 | 
			
		||||
	if ((out + len + 1) >= end) {
 | 
			
		||||
		log_error(no_space);
 | 
			
		||||
 | 
			
		||||
		log_error("t->params= '%s'", t->params);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	strcpy((char *) out, t->params);
 | 
			
		||||
	out += len + 1;
 | 
			
		||||
 | 
			
		||||
	/* align next block */
 | 
			
		||||
	out = _align(out, ALIGNMENT_V1);
 | 
			
		||||
 | 
			
		||||
	sp.next = out - out_sp;
 | 
			
		||||
 | 
			
		||||
	memcpy(out_sp, &sp, sp_size);
 | 
			
		||||
 | 
			
		||||
	return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct dm_ioctl_v1 *_flatten_v1(struct dm_task *dmt)
 | 
			
		||||
{
 | 
			
		||||
	const size_t min_size = 16 * 1024;
 | 
			
		||||
	const int (*version)[3];
 | 
			
		||||
 | 
			
		||||
	struct dm_ioctl_v1 *dmi;
 | 
			
		||||
	struct target *t;
 | 
			
		||||
	size_t len = sizeof(struct dm_ioctl_v1);
 | 
			
		||||
	void *b, *e;
 | 
			
		||||
	int count = 0;
 | 
			
		||||
 | 
			
		||||
	for (t = dmt->head; t; t = t->next) {
 | 
			
		||||
		len += sizeof(struct dm_target_spec_v1);
 | 
			
		||||
		len += strlen(t->params) + 1 + ALIGNMENT_V1;
 | 
			
		||||
		count++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (count && dmt->newname) {
 | 
			
		||||
		log_error("targets and newname are incompatible");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (dmt->newname)
 | 
			
		||||
		len += strlen(dmt->newname) + 1;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Give len a minimum size so that we have space to store
 | 
			
		||||
	 * dependencies or status information.
 | 
			
		||||
	 */
 | 
			
		||||
	if (len < min_size)
 | 
			
		||||
		len = min_size;
 | 
			
		||||
 | 
			
		||||
	if (!(dmi = malloc(len)))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	memset(dmi, 0, len);
 | 
			
		||||
 | 
			
		||||
	version = &_cmd_data_v1[dmt->type].version;
 | 
			
		||||
 | 
			
		||||
	dmi->version[0] = (*version)[0];
 | 
			
		||||
	dmi->version[1] = (*version)[1];
 | 
			
		||||
	dmi->version[2] = (*version)[2];
 | 
			
		||||
 | 
			
		||||
	dmi->data_size = len;
 | 
			
		||||
	dmi->data_start = sizeof(struct dm_ioctl_v1);
 | 
			
		||||
 | 
			
		||||
	if (dmt->dev_name)
 | 
			
		||||
		strncpy(dmi->name, dmt->dev_name, sizeof(dmi->name));
 | 
			
		||||
 | 
			
		||||
	if (dmt->type == DM_DEVICE_SUSPEND)
 | 
			
		||||
		dmi->flags |= DM_SUSPEND_FLAG;
 | 
			
		||||
	if (dmt->read_only)
 | 
			
		||||
		dmi->flags |= DM_READONLY_FLAG;
 | 
			
		||||
 | 
			
		||||
	if (dmt->minor >= 0) {
 | 
			
		||||
		if (dmt->major <= 0) {
 | 
			
		||||
			log_error("Missing major number for persistent device");
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		dmi->flags |= DM_PERSISTENT_DEV_FLAG;
 | 
			
		||||
		dmi->dev = MKDEV(dmt->major, dmt->minor);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (dmt->uuid)
 | 
			
		||||
		strncpy(dmi->uuid, dmt->uuid, sizeof(dmi->uuid));
 | 
			
		||||
 | 
			
		||||
	dmi->target_count = count;
 | 
			
		||||
 | 
			
		||||
	b = (void *) (dmi + 1);
 | 
			
		||||
	e = (void *) ((char *) dmi + len);
 | 
			
		||||
 | 
			
		||||
	for (t = dmt->head; t; t = t->next)
 | 
			
		||||
		if (!(b = _add_target_v1(t, b, e)))
 | 
			
		||||
			goto bad;
 | 
			
		||||
 | 
			
		||||
	if (dmt->newname)
 | 
			
		||||
		strcpy(b, dmt->newname);
 | 
			
		||||
 | 
			
		||||
	return dmi;
 | 
			
		||||
 | 
			
		||||
      bad:
 | 
			
		||||
	free(dmi);
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _dm_names_v1(struct dm_ioctl_v1 *dmi)
 | 
			
		||||
{
 | 
			
		||||
	const char *dev_dir = dm_dir();
 | 
			
		||||
	int r = 1, len;
 | 
			
		||||
	const char *name;
 | 
			
		||||
	struct dirent *dirent;
 | 
			
		||||
	DIR *d;
 | 
			
		||||
	struct dm_names *names, *old_names = NULL;
 | 
			
		||||
	void *end = (void *) dmi + dmi->data_size;
 | 
			
		||||
	struct stat buf;
 | 
			
		||||
	char path[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	if (!(d = opendir(dev_dir))) {
 | 
			
		||||
		log_error("%s: opendir failed: %s", dev_dir, strerror(errno));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	names = (struct dm_names *) ((void *) dmi + dmi->data_start);
 | 
			
		||||
 | 
			
		||||
	names->dev = 0;		/* Flags no data */
 | 
			
		||||
 | 
			
		||||
	while ((dirent = readdir(d))) {
 | 
			
		||||
		name = dirent->d_name;
 | 
			
		||||
 | 
			
		||||
		if (name[0] == '.' || !strcmp(name, "control"))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		if (old_names)
 | 
			
		||||
			old_names->next = (uint32_t) ((void *) names -
 | 
			
		||||
						      (void *) old_names);
 | 
			
		||||
		snprintf(path, sizeof(path), "%s/%s", dev_dir, name);
 | 
			
		||||
		if (stat(path, &buf)) {
 | 
			
		||||
			log_error("%s: stat failed: %s", path, strerror(errno));
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		if (!S_ISBLK(buf.st_mode))
 | 
			
		||||
			continue;
 | 
			
		||||
		names->dev = (uint64_t) buf.st_rdev;
 | 
			
		||||
		names->next = 0;
 | 
			
		||||
		len = strlen(name);
 | 
			
		||||
		if (((void *) (names + 1) + len + 1) >= end) {
 | 
			
		||||
			log_error("Insufficient buffer space for device list");
 | 
			
		||||
			r = 0;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		strcpy(names->name, name);
 | 
			
		||||
 | 
			
		||||
		old_names = names;
 | 
			
		||||
		names = _align((void *) ++names + len + 1, ALIGNMENT);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (closedir(d))
 | 
			
		||||
		log_error("%s: closedir failed: %s", dev_dir, strerror(errno));
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _open_control(void)
 | 
			
		||||
{
 | 
			
		||||
	char control[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	if (_control_fd != -1)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	snprintf(control, sizeof(control), "%s/control", dm_dir());
 | 
			
		||||
 | 
			
		||||
	if ((_control_fd = open(control, O_RDWR)) < 0) {
 | 
			
		||||
		log_error("%s: open failed: %s", control, strerror(errno));
 | 
			
		||||
		log_error("Is device-mapper driver missing from kernel?");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _dm_task_run_v1(struct dm_task *dmt)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_ioctl_v1 *dmi;
 | 
			
		||||
	unsigned int command;
 | 
			
		||||
 | 
			
		||||
	dmi = _flatten_v1(dmt);
 | 
			
		||||
	if (!dmi) {
 | 
			
		||||
		log_error("Couldn't create ioctl argument");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_open_control())
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if ((unsigned) dmt->type >=
 | 
			
		||||
	    (sizeof(_cmd_data_v1) / sizeof(*_cmd_data_v1))) {
 | 
			
		||||
		log_error("Internal error: unknown device-mapper task %d",
 | 
			
		||||
			  dmt->type);
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	command = _cmd_data_v1[dmt->type].cmd;
 | 
			
		||||
 | 
			
		||||
	if (dmt->type == DM_DEVICE_TABLE)
 | 
			
		||||
		dmi->flags |= DM_STATUS_TABLE_FLAG;
 | 
			
		||||
 | 
			
		||||
	log_debug("dm %s %s %s %s", _cmd_data_v1[dmt->type].name, dmi->name,
 | 
			
		||||
		  dmi->uuid, dmt->newname ? dmt->newname : "");
 | 
			
		||||
	if (dmt->type == DM_DEVICE_LIST) {
 | 
			
		||||
		if (!_dm_names_v1(dmi))
 | 
			
		||||
			goto bad;
 | 
			
		||||
	} else if (ioctl(_control_fd, command, dmi) < 0) {
 | 
			
		||||
		if (_log_suppress)
 | 
			
		||||
			log_verbose("device-mapper ioctl cmd %d failed: %s",
 | 
			
		||||
				    _IOC_NR(command), strerror(errno));
 | 
			
		||||
		else
 | 
			
		||||
			log_error("device-mapper ioctl cmd %d failed: %s",
 | 
			
		||||
				  _IOC_NR(command), strerror(errno));
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (dmt->type) {
 | 
			
		||||
	case DM_DEVICE_CREATE:
 | 
			
		||||
		add_dev_node(dmt->dev_name, MAJOR(dmi->dev), MINOR(dmi->dev));
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case DM_DEVICE_REMOVE:
 | 
			
		||||
		rm_dev_node(dmt->dev_name);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case DM_DEVICE_RENAME:
 | 
			
		||||
		rename_dev_node(dmt->dev_name, dmt->newname);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case DM_DEVICE_STATUS:
 | 
			
		||||
	case DM_DEVICE_TABLE:
 | 
			
		||||
		if (!_unmarshal_status_v1(dmt, dmi))
 | 
			
		||||
			goto bad;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case DM_DEVICE_SUSPEND:
 | 
			
		||||
	case DM_DEVICE_RESUME:
 | 
			
		||||
		dmt->type = DM_DEVICE_INFO;
 | 
			
		||||
		if (!dm_task_run(dmt))
 | 
			
		||||
			goto bad;
 | 
			
		||||
		free(dmi);	/* We'll use what info returned */
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dmt->dmi.v1 = dmi;
 | 
			
		||||
	return 1;
 | 
			
		||||
 | 
			
		||||
      bad:
 | 
			
		||||
	free(dmi);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dm_task_destroy(struct dm_task *dmt)
 | 
			
		||||
@@ -77,8 +477,8 @@ void dm_task_destroy(struct dm_task *dmt)
 | 
			
		||||
	if (dmt->newname)
 | 
			
		||||
		free(dmt->newname);
 | 
			
		||||
 | 
			
		||||
	if (dmt->dmi)
 | 
			
		||||
		free(dmt->dmi);
 | 
			
		||||
	if (dmt->dmi.v4)
 | 
			
		||||
		free(dmt->dmi.v4);
 | 
			
		||||
 | 
			
		||||
	if (dmt->uuid)
 | 
			
		||||
		free(dmt->uuid);
 | 
			
		||||
@@ -90,14 +490,81 @@ int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int *v;
 | 
			
		||||
 | 
			
		||||
	if (!dmt->dmi)
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (_dm_version == 1)
 | 
			
		||||
		return _dm_task_get_driver_version_v1(dmt, version, size);
 | 
			
		||||
 | 
			
		||||
	v = dmt->dmi->version;
 | 
			
		||||
	if (!dmt->dmi.v4) {
 | 
			
		||||
		version[0] = '\0';
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	v = dmt->dmi.v4->version;
 | 
			
		||||
	snprintf(version, size, "%u.%u.%u", v[0], v[1], v[2]);
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _check_version(char *version, size_t size, int log_suppress)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_task *task;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	if (!(task = dm_task_create(DM_DEVICE_VERSION))) {
 | 
			
		||||
		log_error("Failed to get device-mapper version");
 | 
			
		||||
		version[0] = '\0';
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (log_suppress)
 | 
			
		||||
		_log_suppress = 1;
 | 
			
		||||
 | 
			
		||||
	r = dm_task_run(task);
 | 
			
		||||
	dm_task_get_driver_version(task, version, size);
 | 
			
		||||
	dm_task_destroy(task);
 | 
			
		||||
	_log_suppress = 0;
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Find out device-mapper's major version number the first time 
 | 
			
		||||
 * this is called and whether or not we support it.
 | 
			
		||||
 */
 | 
			
		||||
int dm_check_version(void)
 | 
			
		||||
{
 | 
			
		||||
	char libversion[64], dmversion[64];
 | 
			
		||||
	const char *compat = "";
 | 
			
		||||
 | 
			
		||||
	if (_version_checked)
 | 
			
		||||
		return _version_ok;
 | 
			
		||||
 | 
			
		||||
	_version_checked = 1;
 | 
			
		||||
 | 
			
		||||
	if (_check_version(dmversion, sizeof(dmversion), _dm_compat))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (!_dm_compat)
 | 
			
		||||
		goto bad;
 | 
			
		||||
 | 
			
		||||
	log_verbose("device-mapper ioctl protocol version %d failed. "
 | 
			
		||||
		    "Trying protocol version 1.", _dm_version);
 | 
			
		||||
	_dm_version = 1;
 | 
			
		||||
	if (_check_version(dmversion, sizeof(dmversion), 0)) {
 | 
			
		||||
		log_verbose("Using device-mapper ioctl protocol version 1");
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	compat = "(compat)";
 | 
			
		||||
 | 
			
		||||
	dm_get_library_version(libversion, sizeof(libversion));
 | 
			
		||||
 | 
			
		||||
	log_error("Incompatible libdevmapper %s%s and kernel driver %s",
 | 
			
		||||
		  libversion, compat, dmversion);
 | 
			
		||||
 | 
			
		||||
      bad:
 | 
			
		||||
	_version_ok = 0;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *dm_get_next_target(struct dm_task *dmt, void *next,
 | 
			
		||||
			 uint64_t *start, uint64_t *length,
 | 
			
		||||
			 char **target_type, char **params)
 | 
			
		||||
@@ -121,55 +588,102 @@ void *dm_get_next_target(struct dm_task *dmt, void *next,
 | 
			
		||||
/* Unmarshall the target info returned from a status call */
 | 
			
		||||
static int _unmarshal_status(struct dm_task *dmt, struct dm_ioctl *dmi)
 | 
			
		||||
{
 | 
			
		||||
	char *outbuf = (char *) dmi + sizeof(struct dm_ioctl);
 | 
			
		||||
	char *outbuf = (char *) dmi + dmi->data_start;
 | 
			
		||||
	char *outptr = outbuf;
 | 
			
		||||
	int i;
 | 
			
		||||
	uint32_t i;
 | 
			
		||||
	struct dm_target_spec *spec;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < dmi->target_count; i++) {
 | 
			
		||||
		struct dm_target_spec *spec = (struct dm_target_spec *) outptr;
 | 
			
		||||
 | 
			
		||||
		if (!dm_task_add_target(dmt, spec->sector_start, spec->length,
 | 
			
		||||
		spec = (struct dm_target_spec *) outptr;
 | 
			
		||||
		if (!dm_task_add_target(dmt, spec->sector_start,
 | 
			
		||||
					spec->length,
 | 
			
		||||
					spec->target_type,
 | 
			
		||||
					outptr + sizeof(*spec)))
 | 
			
		||||
			return 0;
 | 
			
		||||
 | 
			
		||||
		outptr += sizeof(struct dm_target_spec);
 | 
			
		||||
		outptr += strlen(outptr) + 1;
 | 
			
		||||
		_align(outptr, ALIGNMENT);
 | 
			
		||||
		outptr = outbuf + spec->next;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dm_format_dev(char *buf, int bufsize, uint32_t dev_major, uint32_t dev_minor)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	if (_dm_version == 1)
 | 
			
		||||
		return _dm_format_dev_v1(buf, bufsize, dev_major, dev_minor);
 | 
			
		||||
 | 
			
		||||
	if (bufsize < 8)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	r = snprintf(buf, bufsize, "%03u:%03u", dev_major, dev_minor);
 | 
			
		||||
	if (r < 0 || r > bufsize - 1)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dm_task_get_info(struct dm_task *dmt, struct dm_info *info)
 | 
			
		||||
{
 | 
			
		||||
	if (!dmt->dmi)
 | 
			
		||||
	if (_dm_version == 1)
 | 
			
		||||
		return _dm_task_get_info_v1(dmt, info);
 | 
			
		||||
 | 
			
		||||
	if (!dmt->dmi.v4)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	memset(info, 0, sizeof(*info));
 | 
			
		||||
 | 
			
		||||
	info->exists = dmt->dmi->flags & DM_EXISTS_FLAG ? 1 : 0;
 | 
			
		||||
	info->exists = dmt->dmi.v4->flags & DM_EXISTS_FLAG ? 1 : 0;
 | 
			
		||||
	if (!info->exists)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	info->suspended = dmt->dmi->flags & DM_SUSPEND_FLAG ? 1 : 0;
 | 
			
		||||
	info->read_only = dmt->dmi->flags & DM_READONLY_FLAG ? 1 : 0;
 | 
			
		||||
	info->target_count = dmt->dmi->target_count;
 | 
			
		||||
	info->open_count = dmt->dmi->open_count;
 | 
			
		||||
	info->major = MAJOR(dmt->dmi->dev);
 | 
			
		||||
	info->minor = MINOR(dmt->dmi->dev);
 | 
			
		||||
	info->suspended = dmt->dmi.v4->flags & DM_SUSPEND_FLAG ? 1 : 0;
 | 
			
		||||
	info->read_only = dmt->dmi.v4->flags & DM_READONLY_FLAG ? 1 : 0;
 | 
			
		||||
	info->live_table = dmt->dmi.v4->flags & DM_ACTIVE_PRESENT_FLAG ? 1 : 0;
 | 
			
		||||
	info->inactive_table = dmt->dmi.v4->flags & DM_INACTIVE_PRESENT_FLAG ?
 | 
			
		||||
	    1 : 0;
 | 
			
		||||
	info->target_count = dmt->dmi.v4->target_count;
 | 
			
		||||
	info->open_count = dmt->dmi.v4->open_count;
 | 
			
		||||
	info->event_nr = dmt->dmi.v4->event_nr;
 | 
			
		||||
	info->major = MAJOR(dmt->dmi.v4->dev);
 | 
			
		||||
	info->minor = MINOR(dmt->dmi.v4->dev);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *dm_task_get_name(struct dm_task *dmt)
 | 
			
		||||
{
 | 
			
		||||
	if (_dm_version == 1)
 | 
			
		||||
		return _dm_task_get_name_v1(dmt);
 | 
			
		||||
 | 
			
		||||
	return (dmt->dmi.v4->name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *dm_task_get_uuid(struct dm_task *dmt)
 | 
			
		||||
{
 | 
			
		||||
	return (dmt->dmi->uuid);
 | 
			
		||||
	if (_dm_version == 1)
 | 
			
		||||
		return _dm_task_get_uuid_v1(dmt);
 | 
			
		||||
 | 
			
		||||
	return (dmt->dmi.v4->uuid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct dm_deps *dm_task_get_deps(struct dm_task *dmt)
 | 
			
		||||
{
 | 
			
		||||
	return (struct dm_deps *) (((void *) dmt->dmi) + dmt->dmi->data_start);
 | 
			
		||||
	if (_dm_version == 1)
 | 
			
		||||
		return _dm_task_get_deps_v1(dmt);
 | 
			
		||||
 | 
			
		||||
	return (struct dm_deps *) (((void *) dmt->dmi.v4) +
 | 
			
		||||
				   dmt->dmi.v4->data_start);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct dm_names *dm_task_get_names(struct dm_task *dmt)
 | 
			
		||||
{
 | 
			
		||||
	if (_dm_version == 1)
 | 
			
		||||
		return _dm_task_get_names_v1(dmt);
 | 
			
		||||
 | 
			
		||||
	return (struct dm_names *) (((void *) dmt->dmi.v4) +
 | 
			
		||||
				    dmt->dmi.v4->data_start);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dm_task_set_ro(struct dm_task *dmt)
 | 
			
		||||
@@ -188,6 +702,13 @@ int dm_task_set_newname(struct dm_task *dmt, const char *newname)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dm_task_set_event_nr(struct dm_task *dmt, uint32_t event_nr)
 | 
			
		||||
{
 | 
			
		||||
	dmt->event_nr = event_nr;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct target *create_target(uint64_t start, uint64_t len, const char *type,
 | 
			
		||||
			     const char *params)
 | 
			
		||||
{
 | 
			
		||||
@@ -225,10 +746,11 @@ static void *_add_target(struct target *t, void *out, void *end)
 | 
			
		||||
{
 | 
			
		||||
	void *out_sp = out;
 | 
			
		||||
	struct dm_target_spec sp;
 | 
			
		||||
	size_t sp_size = sizeof(struct dm_target_spec);
 | 
			
		||||
	int len;
 | 
			
		||||
	const char no_space[] = "Ran out of memory building ioctl parameter";
 | 
			
		||||
 | 
			
		||||
	out += sizeof(struct dm_target_spec);
 | 
			
		||||
	out += sp_size;
 | 
			
		||||
	if (out >= end) {
 | 
			
		||||
		log_error(no_space);
 | 
			
		||||
		return NULL;
 | 
			
		||||
@@ -254,7 +776,7 @@ static void *_add_target(struct target *t, void *out, void *end)
 | 
			
		||||
	out = _align(out, ALIGNMENT);
 | 
			
		||||
 | 
			
		||||
	sp.next = out - out_sp;
 | 
			
		||||
	memcpy(out_sp, &sp, sizeof(sp));
 | 
			
		||||
	memcpy(out_sp, &sp, sp_size);
 | 
			
		||||
 | 
			
		||||
	return out;
 | 
			
		||||
}
 | 
			
		||||
@@ -262,6 +784,7 @@ static void *_add_target(struct target *t, void *out, void *end)
 | 
			
		||||
static struct dm_ioctl *_flatten(struct dm_task *dmt)
 | 
			
		||||
{
 | 
			
		||||
	const size_t min_size = 16 * 1024;
 | 
			
		||||
	const int (*version)[3];
 | 
			
		||||
 | 
			
		||||
	struct dm_ioctl *dmi;
 | 
			
		||||
	struct target *t;
 | 
			
		||||
@@ -295,9 +818,12 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt)
 | 
			
		||||
 | 
			
		||||
	memset(dmi, 0, len);
 | 
			
		||||
 | 
			
		||||
	dmi->version[0] = _cmd_data[dmt->type].version[0];
 | 
			
		||||
	dmi->version[1] = _cmd_data[dmt->type].version[1];
 | 
			
		||||
	dmi->version[2] = _cmd_data[dmt->type].version[2];
 | 
			
		||||
	version = &_cmd_data_v4[dmt->type].version;
 | 
			
		||||
 | 
			
		||||
	dmi->version[0] = (*version)[0];
 | 
			
		||||
	dmi->version[1] = (*version)[1];
 | 
			
		||||
	dmi->version[2] = (*version)[2];
 | 
			
		||||
 | 
			
		||||
	dmi->data_size = len;
 | 
			
		||||
	dmi->data_start = sizeof(struct dm_ioctl);
 | 
			
		||||
 | 
			
		||||
@@ -310,14 +836,19 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt)
 | 
			
		||||
		dmi->flags |= DM_READONLY_FLAG;
 | 
			
		||||
 | 
			
		||||
	if (dmt->minor >= 0) {
 | 
			
		||||
		if (dmt->major <= 0) {
 | 
			
		||||
			log_error("Missing major number for persistent device");
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		dmi->flags |= DM_PERSISTENT_DEV_FLAG;
 | 
			
		||||
		dmi->dev = MKDEV(0, dmt->minor);
 | 
			
		||||
		dmi->dev = MKDEV(dmt->major, dmt->minor);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (dmt->uuid)
 | 
			
		||||
		strncpy(dmi->uuid, dmt->uuid, sizeof(dmi->uuid));
 | 
			
		||||
 | 
			
		||||
	dmi->target_count = count;
 | 
			
		||||
	dmi->event_nr = dmt->event_nr;
 | 
			
		||||
 | 
			
		||||
	b = (void *) (dmi + 1);
 | 
			
		||||
	e = (void *) ((char *) dmi + len);
 | 
			
		||||
@@ -336,49 +867,124 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt)
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dm_task_run(struct dm_task *dmt)
 | 
			
		||||
static int _create_and_load_v4(struct dm_task *dmt)
 | 
			
		||||
{
 | 
			
		||||
	int fd = -1;
 | 
			
		||||
	struct dm_ioctl *dmi = _flatten(dmt);
 | 
			
		||||
	unsigned int command;
 | 
			
		||||
	char control[PATH_MAX];
 | 
			
		||||
	struct dm_task *task;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	if (!dmi) {
 | 
			
		||||
		log_error("Couldn't create ioctl argument");
 | 
			
		||||
	/* Use new task struct to create the device */
 | 
			
		||||
	if (!(task = dm_task_create(DM_DEVICE_CREATE))) {
 | 
			
		||||
		log_error("Failed to create device-mapper task struct");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	snprintf(control, sizeof(control), "%s/control", dm_dir());
 | 
			
		||||
 | 
			
		||||
	if ((fd = open(control, O_RDWR)) < 0) {
 | 
			
		||||
		log_error("%s: open failed: %s", control, strerror(errno));
 | 
			
		||||
		log_error("Is device-mapper driver missing from kernel?");
 | 
			
		||||
		goto bad;
 | 
			
		||||
	/* Copy across relevant fields */
 | 
			
		||||
	if (dmt->dev_name && !dm_task_set_name(task, dmt->dev_name)) {
 | 
			
		||||
		dm_task_destroy(task);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (dmt->type >= (sizeof(_cmd_data) / sizeof(*_cmd_data))) {
 | 
			
		||||
	if (dmt->uuid && !dm_task_set_uuid(task, dmt->uuid)) {
 | 
			
		||||
		dm_task_destroy(task);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	task->major = dmt->major;
 | 
			
		||||
	task->minor = dmt->minor;
 | 
			
		||||
 | 
			
		||||
	r = dm_task_run(task);
 | 
			
		||||
	dm_task_destroy(task);
 | 
			
		||||
	if (!r)
 | 
			
		||||
		return r;
 | 
			
		||||
 | 
			
		||||
	/* Next load the table */
 | 
			
		||||
	if (!(task = dm_task_create(DM_DEVICE_RELOAD))) {
 | 
			
		||||
		log_error("Failed to create device-mapper task struct");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Copy across relevant fields */
 | 
			
		||||
	if (dmt->dev_name && !dm_task_set_name(task, dmt->dev_name)) {
 | 
			
		||||
		dm_task_destroy(task);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	task->read_only = dmt->read_only;
 | 
			
		||||
	task->head = dmt->head;
 | 
			
		||||
	task->tail = dmt->tail;
 | 
			
		||||
 | 
			
		||||
	r = dm_task_run(task);
 | 
			
		||||
 | 
			
		||||
	task->head = NULL;
 | 
			
		||||
	task->tail = NULL;
 | 
			
		||||
	dm_task_destroy(task);
 | 
			
		||||
	if (!r)
 | 
			
		||||
		return r;
 | 
			
		||||
 | 
			
		||||
	/* Use the original structure last so the info will be correct */
 | 
			
		||||
	dmt->type = DM_DEVICE_RESUME;
 | 
			
		||||
	dmt->uuid = NULL;
 | 
			
		||||
	free(dmt->uuid);
 | 
			
		||||
 | 
			
		||||
	r = dm_task_run(dmt);
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dm_task_run(struct dm_task *dmt)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_ioctl *dmi;
 | 
			
		||||
	unsigned int command;
 | 
			
		||||
 | 
			
		||||
	if (_dm_version == 1)
 | 
			
		||||
		return _dm_task_run_v1(dmt);
 | 
			
		||||
 | 
			
		||||
	if ((unsigned) dmt->type >=
 | 
			
		||||
	    (sizeof(_cmd_data_v4) / sizeof(*_cmd_data_v4))) {
 | 
			
		||||
		log_error("Internal error: unknown device-mapper task %d",
 | 
			
		||||
			  dmt->type);
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	command = _cmd_data[dmt->type].cmd;
 | 
			
		||||
	command = _cmd_data_v4[dmt->type].cmd;
 | 
			
		||||
 | 
			
		||||
	/* Old-style creation had a table supplied */
 | 
			
		||||
	if (dmt->type == DM_DEVICE_CREATE && dmt->head)
 | 
			
		||||
		return _create_and_load_v4(dmt);
 | 
			
		||||
 | 
			
		||||
	if (!_open_control())
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	dmi = _flatten(dmt);
 | 
			
		||||
	if (!dmi) {
 | 
			
		||||
		log_error("Couldn't create ioctl argument");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (dmt->type == DM_DEVICE_TABLE)
 | 
			
		||||
		dmi->flags |= DM_STATUS_TABLE_FLAG;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	log_debug("dm %s %s %s %s", _cmd_data[dmt->type].name, dmi->name,
 | 
			
		||||
	dmi->flags |= DM_EXISTS_FLAG;	/* FIXME */
 | 
			
		||||
	log_debug("dm %s %s %s %s", _cmd_data_v4[dmt->type].name, dmi->name,
 | 
			
		||||
		  dmi->uuid, dmt->newname ? dmt->newname : "");
 | 
			
		||||
	if (ioctl(fd, command, dmi) < 0) {
 | 
			
		||||
		log_error("device-mapper ioctl cmd %d failed: %s",
 | 
			
		||||
			  _IOC_NR(command), strerror(errno));
 | 
			
		||||
	if (ioctl(_control_fd, command, dmi) < 0) {
 | 
			
		||||
		if (errno == ENXIO && dmt->type == DM_DEVICE_INFO) {
 | 
			
		||||
			dmi->flags &= ~DM_EXISTS_FLAG;	/* FIXME */
 | 
			
		||||
			goto ignore_error;
 | 
			
		||||
		}
 | 
			
		||||
		if (_log_suppress)
 | 
			
		||||
			log_verbose("device-mapper ioctl cmd %d failed: %s",
 | 
			
		||||
				    _IOC_NR(command), strerror(errno));
 | 
			
		||||
		else
 | 
			
		||||
			log_error("device-mapper ioctl cmd %d failed: %s",
 | 
			
		||||
				  _IOC_NR(command), strerror(errno));
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
      ignore_error:
 | 
			
		||||
	switch (dmt->type) {
 | 
			
		||||
	case DM_DEVICE_CREATE:
 | 
			
		||||
		add_dev_node(dmt->dev_name, dmi->dev);
 | 
			
		||||
		add_dev_node(dmt->dev_name, MAJOR(dmi->dev), MINOR(dmi->dev));
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case DM_DEVICE_REMOVE:
 | 
			
		||||
@@ -391,18 +997,35 @@ int dm_task_run(struct dm_task *dmt)
 | 
			
		||||
 | 
			
		||||
	case DM_DEVICE_STATUS:
 | 
			
		||||
	case DM_DEVICE_TABLE:
 | 
			
		||||
	case DM_DEVICE_WAITEVENT:
 | 
			
		||||
		if (!_unmarshal_status(dmt, dmi))
 | 
			
		||||
			goto bad;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dmt->dmi = dmi;
 | 
			
		||||
	close(fd);
 | 
			
		||||
	dmt->dmi.v4 = dmi;
 | 
			
		||||
	return 1;
 | 
			
		||||
 | 
			
		||||
      bad:
 | 
			
		||||
	free(dmi);
 | 
			
		||||
	if (fd >= 0)
 | 
			
		||||
		close(fd);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dm_lib_release(void)
 | 
			
		||||
{
 | 
			
		||||
	if (_control_fd != -1) {
 | 
			
		||||
		close(_control_fd);
 | 
			
		||||
		_control_fd = -1;
 | 
			
		||||
	}
 | 
			
		||||
	update_devs();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dm_lib_exit(void)
 | 
			
		||||
{
 | 
			
		||||
	if (_control_fd != -1) {
 | 
			
		||||
		close(_control_fd);
 | 
			
		||||
		_control_fd = -1;
 | 
			
		||||
	}
 | 
			
		||||
	_version_ok = 1;
 | 
			
		||||
	_version_checked = 0;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										109
									
								
								libdm/ioctl/libdm-compat.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								libdm/ioctl/libdm-compat.h
									
									
									
									
									
										Normal 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
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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 */
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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@
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								make.tmpl.in
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								make.tmpl.in
									
									
									
									
									
								
							@@ -27,6 +27,7 @@ SHELL = /bin/sh
 | 
			
		||||
INSTALL = @INSTALL@
 | 
			
		||||
LN_S = @LN_S@
 | 
			
		||||
LIBS = @LIBS@
 | 
			
		||||
CFLAGS = @CFLAGS@
 | 
			
		||||
 | 
			
		||||
# Setup directory variables
 | 
			
		||||
prefix = $(DESTDIR)@prefix@
 | 
			
		||||
@@ -81,22 +82,6 @@ STRIP=
 | 
			
		||||
 | 
			
		||||
DEPS=$(top_srcdir)/make.tmpl Makefile $(INC_LNS)
 | 
			
		||||
 | 
			
		||||
ifeq ("@READLINE@", "yes")
 | 
			
		||||
  CFLAGS += -DREADLINE_SUPPORT
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@DEVMAPPER@", "yes")
 | 
			
		||||
  CFLAGS += -DDEVMAPPER_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)
 | 
			
		||||
@@ -113,7 +98,7 @@ install: all $(SUBDIRS.install)
 | 
			
		||||
$(SUBDIRS):
 | 
			
		||||
	$(MAKE) -C $@
 | 
			
		||||
 | 
			
		||||
$(SUBDIRS.install): 
 | 
			
		||||
$(SUBDIRS.install): $(SUBDIRS)
 | 
			
		||||
	$(MAKE) -C $(@:.install=) install
 | 
			
		||||
 | 
			
		||||
$(SUBDIRS.clean):
 | 
			
		||||
 
 | 
			
		||||
@@ -23,8 +23,8 @@ VPATH = @srcdir@
 | 
			
		||||
MAN5=lvm.conf.5
 | 
			
		||||
MAN8=lvchange.8 lvcreate.8 lvdisplay.8 lvextend.8 lvm.8 lvmchange.8 \
 | 
			
		||||
	lvreduce.8 lvremove.8 lvrename.8 lvs.8 lvscan.8 pvchange.8 \
 | 
			
		||||
	pvcreate.8 pvdisplay.8 pvremove.8 pvs.8 pvscan.8 vgcfgbackup.8 \
 | 
			
		||||
	vgcfgrestore.8 vgchange.8 vgck.8 vgcreate.8 \
 | 
			
		||||
	pvcreate.8 pvdisplay.8 pvmove.8 pvremove.8 pvs.8 pvscan.8 \
 | 
			
		||||
	vgcfgbackup.8 vgcfgrestore.8 vgchange.8 vgck.8 vgcreate.8 \
 | 
			
		||||
	vgconvert.8 vgdisplay.8 vgextend.8 vgmerge.8 vgreduce.8 vgremove.8 \
 | 
			
		||||
	vgrename.8 vgs.8 vgscan.8
 | 
			
		||||
MAN5DIR=${mandir}/man5
 | 
			
		||||
 
 | 
			
		||||
@@ -31,7 +31,7 @@ the volume group can be extended ( see
 | 
			
		||||
.B vgextend(8)
 | 
			
		||||
) with other physical volumes or by reducing existing logical volumes
 | 
			
		||||
of this volume group in size ( see
 | 
			
		||||
.B lvreduce(8), e2fsadm(8)
 | 
			
		||||
.B lvreduce(8)
 | 
			
		||||
).
 | 
			
		||||
.br
 | 
			
		||||
The second form supports the creation of snapshot logical volumes which 
 | 
			
		||||
 
 | 
			
		||||
@@ -17,9 +17,6 @@ You should therefore ensure that the (eg) filesystem on the volume is
 | 
			
		||||
resized
 | 
			
		||||
.i before
 | 
			
		||||
running lvreduce so that the extents that are to be removed are not in use.
 | 
			
		||||
If the filesystem is ext2 then you can use the 
 | 
			
		||||
.B e2fsadm(8)
 | 
			
		||||
command to both resize the filesystem and the logical volume together.
 | 
			
		||||
.br.
 | 
			
		||||
Shrinking snapshot logical volumes (see
 | 
			
		||||
.B lvcreate(8)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										51
									
								
								man/pvmove.8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								man/pvmove.8
									
									
									
									
									
										Normal 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)
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user