Index: src/external/gpl2/Makefile
===================================================================
RCS file: src/external/gpl2/Makefile
diff -N src/external/gpl2/Makefile
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/Makefile	16 Dec 2008 01:26:58 -0000	1.1.2.3
@@ -0,0 +1,7 @@
+.include <bsd.own.mk>
+
+.if (${MKLVM} != "no")
+SUBDIR+= lvm2tools
+.endif
+
+.include <bsd.subdir.mk>
Index: src/external/gpl2/lvm2tools/Makefile
===================================================================
RCS file: src/external/gpl2/lvm2tools/Makefile
diff -N src/external/gpl2/lvm2tools/Makefile
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/Makefile	23 Jul 2008 13:44:02 -0000	1.1.2.2
@@ -0,0 +1,9 @@
+#	$NetBSD: Makefile,v 1.1.2.2 2008/07/23 13:44:02 lukem Exp $
+
+.include "lvm2tools.mk"
+
+SUBDIR+=	lib .WAIT
+
+SUBDIR+=	sbin
+
+.include <bsd.subdir.mk>
Index: src/external/gpl2/lvm2tools/lvm2tools.mk
===================================================================
RCS file: src/external/gpl2/lvm2tools/lvm2tools.mk
diff -N src/external/gpl2/lvm2tools/lvm2tools.mk
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/lvm2tools.mk	16 Dec 2008 00:43:53 -0000	1.1.2.3
@@ -0,0 +1,21 @@
+#	$NetBSD: lvm2tools.mk,v 1.1.2.3 2008/12/16 00:43:53 haad Exp $
+
+.include <bsd.own.mk>
+
+LVM2TOOLS_SRCDIR=	${NETBSDSRCDIR}/external/gpl2/lvm2tools
+LVM2TOOLS_DISTDIR=	${NETBSDSRCDIR}/external/gpl2/lvm2tools/dist
+
+LVM2TOOLS_PREFIX=	/
+
+LIBDM_SRCDIR=		${NETBSDSRCDIR}/external/gpl2/lvm2tools/dist/libdm
+LIBDM_INCLUDE=		${NETBSDSRCDIR}/external/gpl2/lvm2tools/dist/include
+
+#
+#LIBDM_OBJDIR.libdevmapper=${LIBDM_SRCDIR}/lib/libdevmapper/
+#
+#.if !defined(LVM2TOOLSOBJDIR.liblvm)
+#LVM2TOOLSOBJDIR.liblvm!=	cd ${LVM2TOOLS_SRCDIR}/lib/liblvm && ${PRINTOBJDIR}
+#.MAKEOVERRIDES+=	LVM2TOOLSOBJDIR.liblvm 
+#.endif
+#
+#LVM2TOOLS.liblvm=	${LVM2TOOLSOBJDIR.liblvm}/liblvm.a
Index: src/external/gpl2/lvm2tools/dist/COPYING
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/COPYING
diff -N src/external/gpl2/lvm2tools/dist/COPYING
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/COPYING	15 Jul 2008 13:48:52 -0000	1.1.1.1
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: src/external/gpl2/lvm2tools/dist/COPYING.LIB
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/COPYING.LIB
diff -N src/external/gpl2/lvm2tools/dist/COPYING.LIB
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/COPYING.LIB	15 Jul 2008 13:48:52 -0000	1.1.1.1
@@ -0,0 +1,504 @@
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
Index: src/external/gpl2/lvm2tools/dist/INSTALL
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/INSTALL
diff -N src/external/gpl2/lvm2tools/dist/INSTALL
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/INSTALL	12 Dec 2008 16:32:57 -0000	1.1.1.1.2.1
@@ -0,0 +1,31 @@
+Installation
+============
+
+1) Generate custom makefiles.
+
+   Run the 'configure' script from the top directory.
+
+   If you don't want to include the LVM1 backwards-compatibility code use:
+     ./configure --with-lvm1=none 
+
+   To separate the LVM1 support into a shared library loaded by lvm.conf use:
+     ./configure --with-lvm1=shared
+
+   Use ./configure --help to see other options.
+
+2) Build and install.
+
+   Run 'make' from the top directory to build everything you configured.
+   Run 'make install' to build and install everything you configured.
+
+   If you only want the device-mapper libraries and tools use
+   'make device-mapper' or 'make install_device-mapper'.
+
+3) If using LVM2, create a configuration file.
+
+   The tools will work fine without a configuration file being
+   present, but you ought to review the example file in doc/example.conf.
+
+Please also refer to the WHATS_NEW file and the manual pages for the 
+individual commands.
+
Index: src/external/gpl2/lvm2tools/dist/Makefile.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/Makefile.in
diff -N src/external/gpl2/lvm2tools/dist/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/Makefile.in	12 Dec 2008 16:32:57 -0000	1.1.1.1.2.1
@@ -0,0 +1,110 @@
+#
+# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+# Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+SUBDIRS = doc include man scripts
+
+ifeq ("@INTL@", "yes")
+  SUBDIRS += po
+endif
+
+SUBDIRS += lib tools daemons libdm
+
+ifeq ($(MAKECMDGOALS),distclean)
+  SUBDIRS += daemons/clvmd \
+	     daemons/dmeventd/plugins \
+	     lib/format1 \
+	     lib/format_pool \
+	     lib/locking \
+	     lib/mirror \
+	     lib/snapshot \
+	     test \
+	     po
+  DISTCLEAN_TARGETS += lib/misc/configure.h
+  DISTCLEAN_DIRS += lcov_reports*
+endif
+
+include make.tmpl
+
+libdm: include
+lib: libdm
+daemons: lib
+tools: lib device-mapper
+po: tools daemons
+
+libdm.device-mapper: include.device-mapper
+daemons.device-mapper: libdm.device-mapper
+tools.device-mapper: libdm.device-mapper
+device-mapper: tools.device-mapper daemons.device-mapper man.device-mapper
+
+ifeq ("@INTL@", "yes")
+lib.pofile: include.pofile
+tools.pofile: lib.pofile
+daemons.pofile: lib.pofile
+po.pofile: tools.pofile daemons.pofile
+pofile: po.pofile
+endif
+
+ifneq ("@CFLOW_CMD@", "")
+tools.cflow: lib.cflow
+cflow: tools.cflow
+endif
+
+ifneq ("@CSCOPE_CMD@", "")
+cscope.out: tools
+	@CSCOPE_CMD@ -b -R
+all: cscope.out
+endif
+
+check: all
+	$(MAKE) -C test all
+
+ifneq ("@LCOV@", "")
+.PHONY: lcov-reset lcov lcov-dated
+
+ifeq ($(MAKECMDGOALS),lcov-dated)
+LCOV_REPORTS_DIR=$(top_srcdir)/lcov_reports-$(shell date +%Y%m%d%k%M%S)
+else
+LCOV_REPORTS_DIR=$(top_srcdir)/lcov_reports
+endif
+
+lcov-reset:
+	$(LCOV) -d $(top_srcdir)/dmeventd --zerocounters
+	$(LCOV) -d $(top_srcdir)/libdm --zerocounters
+	$(LCOV) -d $(top_srcdir)/lib --zerocounters
+	$(LCOV) -d $(top_srcdir)/tools --zerocounters
+
+lcov: all
+	$(RM) -rf $(LCOV_REPORTS_DIR)
+	$(MKDIR_P) $(LCOV_REPORTS_DIR)
+	$(LCOV) -b ${top_srcdir}/libdm -d $(top_srcdir)/libdm -c -o $(LCOV_REPORTS_DIR)/libdm.info
+	$(LCOV) -b $(top_srcdir)/lib -d $(top_srcdir)/lib -c -o $(LCOV_REPORTS_DIR)/lib.info
+	$(LCOV) -b $(top_srcdir)/tools -d $(top_srcdir)/tools -c -o $(LCOV_REPORTS_DIR)/tools.info
+	DMEVENTD_INFO="$(LCOV_REPORTS_DIR)/dmeventd.info" ;\
+	DMEVENTD_INFO_A="-a $$DMEVENTDINFO" ;\
+	$(LCOV) -b $(top_srcdir)/dmeventd -d $(top_srcdir)/dmeventd -c -o $$DMEVENTD_INFO || DMEVENTD_INFO_A="" ;\
+	$(LCOV) $$DMEVENTD_INFO_A -a $(LCOV_REPORTS_DIR)/lib.info \
+		-a $(LCOV_REPORTS_DIR)/libdm.info \
+		-a $(LCOV_REPORTS_DIR)/tools.info \
+		-o $(LCOV_REPORTS_DIR)/lvm.info
+ifneq ("@GENHTML@", "")
+	$(GENHTML) -o $(LCOV_REPORTS_DIR) -p $(top_srcdir) $(LCOV_REPORTS_DIR)/lvm.info
+endif
+
+lcov-dated: lcov
+
+endif
Index: src/external/gpl2/lvm2tools/dist/README
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/README
diff -N src/external/gpl2/lvm2tools/dist/README
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/README	12 Dec 2008 16:32:57 -0000	1.1.1.1.2.1
@@ -0,0 +1,27 @@
+This tree contains the LVM2 and device-mapper tools and libraries.
+
+For more information about LVM2 read the changelog in the WHATS_NEW file.
+Installation instructions are in INSTALL.
+
+There is no warranty - see COPYING and COPYING.LIB.
+
+Tarballs are available from:
+  ftp://sources.redhat.com/pub/lvm2/
+
+To access the CVS tree use:
+  cvs -d :pserver:cvs@sources.redhat.com:/cvs/lvm2 login
+  CVS password: cvs
+  cvs -d :pserver:cvs@sources.redhat.com:/cvs/lvm2 co LVM2
+
+Mailing list for general discussion related to LVM2:
+  linux-lvm@redhat.com
+  Subscribe from https://www.redhat.com/mailman/listinfo/linux-lvm
+
+Mailing list for LVM2 development, patches and commits:
+  lvm-devel@redhat.com
+  Subscribe from https://www.redhat.com/mailman/listinfo/linux-lvm
+
+Mailing list for device-mapper development, including kernel patches
+and multipath-tools:
+  dm-devel@redhat.com
+  Subscribe from https://www.redhat.com/mailman/listinfo/dm-devel
Index: src/external/gpl2/lvm2tools/dist/VERSION
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/VERSION
diff -N src/external/gpl2/lvm2tools/dist/VERSION
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/VERSION	12 Dec 2008 16:32:57 -0000	1.1.1.1.2.1
@@ -0,0 +1 @@
+2.02.43 (2008-11-10)
Index: src/external/gpl2/lvm2tools/dist/VERSION_DM
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/VERSION_DM
diff -N src/external/gpl2/lvm2tools/dist/VERSION_DM
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/VERSION_DM	12 Dec 2008 16:32:57 -0000	1.1.1.1.2.2
@@ -0,0 +1 @@
+1.02.29 (2008-11-10)
Index: src/external/gpl2/lvm2tools/dist/WHATS_NEW
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/WHATS_NEW
diff -N src/external/gpl2/lvm2tools/dist/WHATS_NEW
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/WHATS_NEW	12 Dec 2008 16:32:57 -0000	1.1.1.1.2.1
@@ -0,0 +1,1403 @@
+Version 2.02.43 - 10th November 2008
+====================================
+  Merge device-mapper into the lvm2 tree.
+  Correct prototype for --permission on lvchange and lvcreate man pages.
+  Exit with non-zero status from vgdisplay if couldn't show any requested VG.
+  Move list.c into libdevmapper and rename functions.
+  Rename a couple of variables that matched function names.
+  Use simplified x.y.z version number in libdevmapper.pc.
+  Remove ancient debian directory.
+  Split out lvm-logging.h from log.h and lvm-globals.[ch] from log.[ch].
+
+Version 2.02.42 - 26th October 2008
+===================================
+  Accept locking fallback_to_* options in the global section as documented.
+  Fix temp table activation in mirror conversions not to happen in other cmds.
+  Fix temp table in mirror conversions to use always-present error not zero.
+
+Version 2.02.41 - 17th October 2008
+===================================
+  Use temp table to set device size when converting mirrors.
+  In resume_mirror_images replace activate_lv with resume_lv as workaround.
+  Avoid overwriting in-use on-disk text metadata by forgetting MDA_HEADER_SIZE.
+  Fix snapshot monitoring library to not cancel monitoring invalid snapshot.
+  Generate man pages from templates and include version.
+  Add usrlibdir and usrsbindir to configure.
+  Fix conversion of md chunk size into sectors.
+  Free text metadata buffer after a failure writing it.
+  Fix misleading error message when there are no allocatable extents in VG.
+  Fix handling of PVs which reappeared with old metadata version.
+  Fix mirror DSO to call vgreduce with proper parameters.
+  Fix validation of --minor and --major in lvcreate to require -My always.
+  Fix release: clvmd build, vgreduce consolidate & tests, /dev/ioerror warning.
+
+Version 2.02.40 - 19th September 2008
+=====================================
+  Allow lvremove to remove LVs from VGs with missing PVs.
+  In VG with PVs missing, by default allow activation of LVs that are complete.
+  Track PARTIAL_LV and MISSING_PV flags internally.
+  Require --force with --removemissing in vgreduce to remove partial LVs.
+  No longer write out PARTIAL flag into metadata backups.
+  Treat new default activation/missing_stripe_filler "error" as an error target.
+  Remove internal partial_mode.
+  Add devices/md_chunk_alignment to lvm.conf.
+  Pass struct physical_volume to pe_align and adjust for md chunk size.
+  Store sysfs location in struct cmd_context.
+  Avoid shuffling remaining mirror images when removing one, retaining primary.
+  Add missing LV error target activation in _remove_mirror_images.
+  Prevent resizing an LV while lvconvert is using it.
+  Avoid repeatedly wiping cache while VG_GLOBAL is held in vgscan & pvscan.
+  Fix pvresize to not allow resize if PV has two metadata areas.
+  Fix setting of volume limit count if converting to lvm1 format.
+  Fix vgconvert logical volume id metadata validation.
+  Fix lvmdump metadata gather option (-m) to work correctly.
+  Fix allocation bug in text metadata format write error path.
+  Fix vgcfgbackup to properly check filename if template is used.
+  configure aborts if lcov or genhtml are missing with --enable-profiling
+  vgremove tries to remove lv snapshot first.
+  Added function lv_remove_with_dependencies().
+  Improve file descriptor leak detection to display likely culprit and filename.
+  Change clustered mirror kernel module name from cmirror to dm-log-clustered.
+  Avoid looping forever in _pv_analyze_mda_raw used by pvck.
+  Change lvchange exit status to indicate if any part of the operation failed.
+  Fix pvchange and pvremove to handle PVs without mdas.
+  Refactor _text_pv_read and always return mda list if requested.
+  Fix configure to work w/o readline unless --enable-readline used. (2.02.39)
+  Remove is_lvm_partition template which has not yet been coded.
+  Refactor pvcreate to separate parameter parsing from validation logic.
+  Check for label_write() failure in _text_pv_write().
+  Add pvcreate tests and update vgsplit tests to handle lvm1 and lvm2 metadata.
+  Fix pvchange -M1 -u to preserve existing extent locations when there's a VG.
+  Cease recognising snapshot-in-use percentages returned by early devt kernels.
+  Add backward-compatible flags field to on-disk format_text metadata.
+  Fix dmeventd monitoring libraries to link against liblvm2cmd again. (2.02.39)
+
+Version 2.02.39 - 27th June 2008
+================================
+  Enable readline by default if available.
+  Update autoconf to 2008-01-16.
+  Add $DISTCLEAN_DIRS to make.tmpl.in.
+  Create coverage reports with --enable-profiling and make lcov or lcov-dated.
+  Fix up cache for PVs without mdas after consistent VG metadata is processed.
+  Update validation of safe mirror log type conversions in lvconvert.
+  Fix lvconvert to disallow snapshot and mirror combinations.
+  Fix reporting of LV fields alongside unallocated PV segments.
+  Add --unquoted and --rows to reporting tools.
+  Add and use uninitialized_var() macro to suppress invalid compiler warnings.
+  Introduce enum for md minor sb version to suppress compiler warning.
+  Avoid undefined return value after _memlock manipulation in lvm2_run.
+  Avoid link failure if configured without --enable-cmdlib or --enable-readline.
+  Make clvmd return at once if other nodes down in a gulm or openais cluster.
+  Fix and improve readahead 'auto' calculation for stripe_size.
+  Fix lvchange output for -r auto setting if auto is already set.
+  Add test case for readahead.
+  Avoid ambiguous use of identifier error_message_produced.
+  Begin syncing configure.in for merge/unification with device-mapper.
+  Fix add_mirror_images not to dereference uninitialized log_lv upon failure.
+  Don't call openlog for every debug line output by clvmd.
+  Add --force to lvextend and lvresize.
+  Fix vgchange not to activate component mirror volumes directly.
+  Fix test directory clean up in make distclean.
+
+Version 2.02.38 - 11th June 2008
+================================
+  Fix tracking of validity of PVs with no mdas in lvmcache.
+  Fix return values for reporting commands when run with no PVs, LVs, or VGs.
+  Add omitted unlock_vg() call when sigint_caught() during vg processing.
+  Fix free_count when reading pool metadata.
+  Fix segfault when using pvcreate on a device containing pool metadata.
+  Fix segfault after _free_vginfo by remembering to remove vginfo from list.
+  Tweak detection of invalid fid after changes to PVs in VG in _vg_read.
+  Revert assuming precommitted metadata is live when activating (unnecessary).
+  Drop cached metadata for disappearing VG in vgmerge.
+  In script-processing mode, stop if any command fails.
+  Warn if command exits with non-zero status code without a prior log_error.
+  Check lv_count in vg_validate.
+  Add --nameprefixes to reporting tools for field name prefix output format.
+
+Version 2.02.37 - 6th June 2008
+===============================
+  Make clvmd-cman use a hash rather than an array for node updown info.
+  Correct config file line numbers in messages when parsing comments.
+  Drop cached metadata when renaming a VG.
+  Allow for vginfo changing during _vg_read.
+  Decode numbers in clvmd debugging output.
+  Add missing deactivation after activation failure in lvcreate -Zy.
+  When activating, if precommitted metadata is still cached, assume it's live.
+  When removing LV symlinks, skip any where the VG name is not determined.
+  Drop metadata cache if update fails in vg_revert or vg_commit.
+  Avoid spurious duplicate VG messages referring to VGs that are gone.
+  Drop dev_name_confirmed error message to debug level.
+  Fix setpriority error message to signed int.
+  Temporarily disable dmeventd mirror monitoring during lvchange --resync.
+  Refactor some vginfo manipulation code.
+  Add assertions to trap deprecated P_ and V_ lock usage.
+  Add missing mutex around clvmd lvmcache_drop_metadata library call.
+  Fix uninitialised mutex in clvmd if all daemons are not running at startup.
+  Avoid using DLM locks with LCK_CACHE type P_ lock requests.
+  When asked to drop cached committed VG metadata, invalidate cached PV labels.
+  Drop metadata cache before writing precommitted metadata instead of after.
+  Don't touch /dev in vgrename if activation is disabled.
+
+Version 2.02.36 - 29th April 2008
+=================================
+  Fix fsadm.sh to work with older blockdev, blkid & readlink binaries.
+  Fix lvresize to pass new size to fsadm when extending device.
+  Remove unused struct in clvmd-openais, and use correct node count.
+  Fix nodes list in clvmd-openais, and allow for broadcast messages.
+  Exclude VG_GLOBAL from internal concurrent VG lock counter.
+  Fix vgsplit internal counting of snapshot LVs.
+  Fix vgmerge snapshot_count when source VG contains snapshots.
+  Simplify clvmd-openais by using non-async saLckResourceLock.
+  Fix internal LV counter when a snapshot is removed.
+  Fix metadata corruption writing lvm1-formatted metadata with snapshots.
+  Fix lvconvert -m0 allocatable space check.
+
+Version 2.02.35 - 15th April 2008
+=================================
+  Drop cached VG metadata before and after committing changes to it.
+  Rename P_global to P_#global.
+  Don't attempt remote metadata backups of non-clustered VGs. (2.02.29)
+  Don't store fid in VG metadata cache to avoid clvmd segfault. (2.02.34)
+  Update vgsplit tests to verify loosening of active LV restriction.
+  Update vgsplit to only restrict split with active LVs involved in split.
+  Add lv_is_active() to determine whether an lv is active.
+
+Version 2.02.34 - 10th April 2008
+=================================
+  Improve preferred_names lvm.conf example.
+  Fix vgdisplay 'Cur LV' field to match lvdisplay output.
+  Fix lv_count report field to exclude hidden LVs.
+  Add vg_is_clustered() helper function.
+  Fix vgsplit to only move hidden 'snapshotN' LVs when necessary.
+  Update vgsplit tests for lvnames on the cmdline.
+  Update vgsplit man page to reflect lvnames on the cmdline.
+  Update vgsplit to take "-n LogicalVolumeName" on the cmdline.
+  Use clustered mirror log with pvmove in clustered VGs, if available.
+  Fix some pvmove error status codes.
+  Fix vgsplit error paths to release vg_to lock.
+  Indicate whether or not VG is clustered in vgcreate log message.
+  Mention default --clustered setting in vgcreate man page.
+  Add config file overrides to clvmd when it reads the active LVs list.
+  Fix vgreduce to use vg_split_mdas to check sufficient mdas remain.
+  Add (empty) orphan VGs to lvmcache during initialisation.
+  Fix orphan VG name used for format_pool.
+  Create a fid for internal orphan VGs.
+  Update lvmcache VG lock state for all locking types now.
+  Fix output if overriding command_names on cmdline.
+  Add detection of clustered mirror log capability.
+  Add check to vg_commit() ensuring VG lock held before writing new VG metadata.
+  Add validation of LV name to pvmove -n.
+  Make clvmd refresh the context correctly when lvm.conf is updated.
+  Add some basic internal VG lock validation.
+  Add per-command flags to control which commands use the VG metadata cache.
+  Fix vgsplit locking of new VG (2.02.30).
+  Avoid erroneous vgsplit error message for new VG. (2.02.29)
+  Suppress duplicate message when lvresize fails because of invalid vgname.
+  Cache VG metadata internally while VG lock is held.
+  Fix redundant lvresize message if vg doesn't exist.
+  Fix another allocation bug with clvmd and large node IDs.
+  Add find_lv_in_lv_list() and find_pv_in_pv_list().
+  Fix uninitialised variable in clvmd that could cause odd hangs.
+  Add vgmerge tests.
+  Add pvseg_is_allocated() for identifying a PV segment allocated to a LV.
+  Add list_move() for moving elements from one list to another.
+  Add 'is_reserved_lvname()' for identifying hidden LVs.
+  Correct command name in lvmdiskscan man page.
+  clvmd no longer crashes if it sees nodeids over 50.
+  Fix potential deadlock in clvmd thread handling.
+  Refactor text format initialisation into _init_text_import.
+  Escape double quotes and backslashes in external metadata and config data.
+  Add functions for escaping double quotes in strings.
+  Rename count_chars_len to count_chars.
+  Use return_0 in a couple more places.
+  Correct a function name typo in _line_append error message.
+  Include limits.h in clvmd so it compiles with newer headers.
+  Add VirtIO disks (virtblk) to filters.
+  Fix resetting of MIRROR_IMAGE and VISIBLE_LV after removal of LV. (2.02.30)
+  Fix remove_layer_from_lv to empty the LV before removing it. (2.02.30)
+  Add missing no-longer-used segs_using_this_lv test to check_lv_segments.
+  Remove redundant non-NULL tests before calling free in clvmd.c.
+  Avoid a compiler warning: make is_orphan's parameter const.
+  Fix lvconvert detection of mirror conversion in progress. (2.02.30)
+  Avoid automatic lvconvert polldaemon invocation when -R specified. (2.02.30)
+  Fix 'pvs -a' to detect VGs of PVs without metadata areas.
+  Divide up internal orphan volume group by format type.
+  Update usage message for clvmd.
+  Fix clvmd man page not to print <br> and clarified debug options.
+  Fix lvresize to support /dev/mapper prefix in the LV name.
+  Fix unfilled parameter passed to fsadm from lvresize.
+  Update fsadm to call lvresize if the partition size differs (with option -l).
+  Fix fsadm to support VG/LV names.
+
+Version 2.02.33 - 31st January 2008
+===================================
+  Fix mirror log name construction during lvconvert. (2.02.30)
+  Make monitor_dev_for_events recurse through the stack of LVs.
+  Clean up some more compiler warnings.
+  Some whitespace tidy-ups.
+  Use stack return macros throughout.
+  Rely upon internally-cached PV labels while corresponding VG lock is held.
+
+Version 2.02.32 - 29th January 2008
+===================================
+  Fix two check_lv_segments error messages to show whole segment.
+  Refactor mirror log attachment code.
+  Fix internal metadata corruption in lvchange --resync. (2.02.30)
+  Fix new parameter validation in vgsplit and test mode. (2.02.30)
+  Remove redundant cnxman-socket.h file from clvmd directory.
+  Fix pvs, vgs, lvs error exit status on some error paths.
+
+Version 2.02.31 - 19th January 2008
+===================================
+  Fix lvcreate --nosync not to wait for non-happening sync. (2.02.30)
+  Add very_verbose lvconvert messages.
+  Avoid readahead error message with default setting of lvcreate -M1. (2.02.29)
+
+Version 2.02.30 - 17th January 2008
+===================================
+  Set default readahead to twice maximium stripe size.
+  Reinstate VG extent size and stripe size defaults (halved). (2.02.29)
+  Add lists of stacked LV segments using each LV to the internal metadata.
+  Change vgsplit -l (for unimplemented --list) into --maxlogicalvolumes.
+  Fix process_all_pvs to detect non-orphans with no MDAs correctly.
+  Don't use block_on_error with mirror targets version 1.12 and above.
+  Update vgsplit to accept vgcreate options when new VG is destination.
+  Update vgsplit to accept existing VG as destination.
+  lvconvert waits for completion of initial sync by default.
+  Refactor vgcreate for parameter validation and add tests.
+  Add new convert_lv field to lvs output.
+  Print warning when lvm tools are running as non-root.
+  Add snapshot dmeventd library (enables dmeventd snapshot monitoring).
+  Prevent pvcreate from overwriting MDA-less PVs belonging to active VGs.
+  Fix a segfault if using pvs with --all argument. (2.02.29)
+  Update --uuid argument description in man pages.
+  Fix vgreduce PV list processing not to process every PV in the VG. (2.02.29)
+  Extend lvconvert to use polldaemon.
+  Add support for stacked mirrors.
+  Major restructuring of pvmove and lvconvert layer manipulation code.
+  Replace tools/fsadm with scripts/fsadm.sh.
+  Append fields to report/pvsegs_cols_verbose.
+  Permit LV segment fields with PV segment reports.
+  Add seg_start_pe and seg_pe_ranges to reports.
+
+Version 2.02.29 - 5th December 2007
+===================================
+  Make clvmd backup vg metadata on remote nodes.
+  Refactor pvmove allocation code.
+  Decode cluster locking state in log message.
+  Change file locking state messages from debug to very verbose.
+  Fix --addtag to drop @ prefix from name.
+  Stop clvmd going haywire if a pre_function fails.
+  Convert some vg_reads into vg_lock_and_reads.
+  Avoid nested vg_reads when processing PVs in VGs and fix associated locking.
+  Accept sizes with --readahead argument.
+  Store size arguments as sectors internally.
+  Attempt to remove incomplete LVs with lvcreate zeroing/activation problems.
+  Add read_ahead activation code.
+  Add activation/readahead configuration option and FMT_RESTRICTED_READAHEAD.
+  Extend readahead arg to accept "auto" and "none".
+  Add lv_read_ahead and lv_kernel_read_ahead fields to reports and lvdisplay.
+  Prevent lvconvert -s from using same LV as origin and snapshot.
+  Fix human-readable output of odd numbers of sectors.
+  Add pv_mda_free and vg_mda_free fields to reports for raw text format.
+  Add LVM2 version to 'Generated by' comment in metadata.
+  Show 'not usable' space when PV is too large for device in pvdisplay.
+  Ignore and fix up any excessive device size found in metadata.
+  Fix error message when fixing up PV size in lvm2 metadata (2.02.11).
+  Fix orphan-related locking in pvdisplay and pvs.
+  Fix missing VG unlocks in some pvchange error paths.
+  Add some missing validation of VG names.
+  Rename validate_vg_name() to validate_new_vg_name().
+  Change orphan lock to VG_ORPHANS.
+  Change format1 to use ORPHAN as orphan VG name.
+  Convert pvchange, pvdisplay, pvscan to use is_orphan()
+  Add is_orphan_vg() and change all hard-coded checks to use it.
+  Detect md superblocks version 1.0, 1.1 and 1.2.
+  Add _alloc_pv() and _free_pv() from _pv_create() code and fix error paths.
+  Add pv_dev_name() to access PV device name.
+  Add const attributes to pv accessor functions.
+  Refactor vg_add_snapshot() and lv_create_empty().
+  Handle new sysfs subsystem/block/devices directory structure.
+  Run test with LVM_SYSTEM_DIR pointing to private root and /dev dirs.
+  Fix a bug in lvm_dump.sh checks for lvm/dmsetup binaries.
+  Fix underquotations in lvm_dump.sh.
+  Refactor lvcreate stripe and mirror parameter validation.
+  Print --help output to stdout, not stderr.
+  After a cmdline processing error, don't print help text but suggest --help.
+  Add %PVS extents option to lvresize, lvextend, and lvcreate.
+  Add 'make check' to run tests in new subdirectory 'test'.
+  Moved the obsolete test subdirectory to old-tests.
+  Cope with relative paths in configure --with-dmdir.
+  Remove no-longer-correct restrictions on PV arg count with stripes/mirrors.
+  Fix strdup memory leak in str_list_dup().
+  Link with -lpthread when static SELinux libraries require that.
+  Detect command line PE values that exceed their 32-bit range.
+  Include strerror string in dev_open_flags' stat failure message.
+  Move guts of pvresize into library.
+  Avoid error when --corelog is provided without --mirrorlog. (2.02.28)
+  Correct --mirrorlog argument name in man pages (not --log).
+  Clear MIRROR_NOTSYNCED LV flag when converting from mirror to linear.
+  Modify lvremove to prompt for removal if LV active on other cluster nodes.
+  Add '-f' to vgremove to force removal of VG even if LVs exist.
+
+Version 2.02.28 - 24th August 2007
+==================================
+  Fix clvmd logging so you can get lvm-level debugging out of it.
+  Introduce VG_GLOBAL lock type for vgscan/pvscan to trigger clvmd -R.
+  Change locking_flags from int to uint32_t.
+  Fix clvmd -R, so it fully refreshes the caches.
+  Change lvconvert_mirrors to use mirror segtype not striped.
+  Fix lvconvert_mirrors detection of number of existing mirrors.
+  Clean up numerous compiler warnings that appeared in recent releases.
+  Remove several unused parameters from _allocate().
+  Only permit --force, --verbose and --debug arguments to be repeated.
+  Fix inconsistent licence notices: executables are GPLv2; libraries LGPLv2.1.
+  Move guts of vgremove and lvremove into library, including yes_no_prompt.
+  Allow clvmd debug to be turned on in a running daemon using clvmd -d [-C].
+  Update to use autoconf 2.61, while still supporting 2.57.
+  Add more cluster info to lvmdump.
+  Add further const attributes throughout.
+  Add support for renaming mirrored LVs.
+  Factor out core of lvrename() to library function.
+  Add --mirrorlog argument to specify log type for mirrors.
+  Don't attempt to monitor devices if their creation failed in _lv_activate.
+  Don't leak a file descriptor in fcntl_lock_file() when fcntl fails.
+  Replace create_dir with dm_create_dir.
+  Detect stream write failure reliably with lvm_fclose using dm_fclose.
+  Fix clvmd if compiled with gulm support. (2.02.26)
+  Fix lvdisplay man page to say LV size is reported in sectors, not KB.
+  Add vg_lock_and_read() external library function.
+  Fix loading of persistent cache if cache_dir is used. (2.02.23)
+  Reduce _compare_paths lstat error message from log_error to log_very_verbose.
+  Create util.h with last_path_component replacing strdup + basename.
+  Use gcc's printf attribute wherever possible.
+  In _line_append, use "sizeof buf - 1" rather than equivalent "4095".
+  Introduce is_same_inode macro, now including a comparison of st_dev.
+  Don't leak a file descriptor in _lock_file() when flock fails.
+  Add SUN's LDOM virtual block device (vdisk) and ps3disk to filters.
+  Split metadata-external.h out from metadata.h for the tools to use.
+
+Version 2.02.27 - 17th July 2007
+================================
+  Fix snapshot cow area deactivation if origin is not active. (2.02.13)
+  Fix configure libdevmapper.h check when --with-dmdir is used.
+  Turn _add_pv_to_vg() into external library function add_pv_to_vg().
+  Add pv_by_path() external library function.
+  Tidy clvmd-openais of redundant bits, and improve an error report.
+  Cope with find_seg_by_le() failure in check_lv_segments().
+  Call dev_iter_destroy() if _process_all_devs() is interrupted by sigint.
+  Add vg_mda_count and pv_mda_count columns to reports.
+  Fix dumpconfig to use log_print instead of stdout directly.
+  Remove unused parameter 'fid' from _add_pv_to_vg.
+  Add kernel and device-mapper targets versions to lvmdump.
+  Replace BSD (r)index with C89 str(r)chr.
+  Handle vgsplit of an entire VG as a vgrename.
+  Reinitialise internal lvmdiskscan variables when called repeatedly.
+  Fix missing lvm_shell symbol in lvm2cmd library. (2.02.23)
+  Add vg_status function and clean up vg->status in tools directory.
+  Add --ignoremonitoring to disable all dmeventd interaction.
+  Remove get_ prefix from get_pv_* functions.
+  clvmd-openais now uses cpg_local_get() to get nodeid, rather than Clm.
+  Print warnings to stderr instead of stdout.
+
+Version 2.02.26 - 15th June 2007
+================================
+  Update vgcfgrestore man page.
+  Allow keyboard interrupt during user prompts when appropriate.
+  Remove unused clvmd system-lv code.
+  Replace many physical_volume struct dereferences with new get_pv_* functions.
+  Suppress a benign compile-time warning.
+  Convert find_pv_in_vg_by_uuid and pv_create to use PV handles.
+  Add wrappers to some functions in preparation for external LVM library.
+  Add -f to vgcfgrestore to list metadata backup files.
+  Add vg_check_status to consolidate vg status checks and error messages.
+  Add pvdisplay --maps implementation.
+  Remove unsupported LVM1 options from vgcfgrestore man page.
+  Update vgcfgrestore man page to show mandatory VG name.
+  Update vgrename man page to include UUID and be consistent with lvrename.
+  Add (experimental) OpenAIS support to clvmd.
+  Fix deactivation code to follow dependencies and remove symlinks.
+  Fix and clarify vgsplit error messages.
+  Fix a segfault in device_is_usable() if a device has no table.
+  Add some more debug messages to clvmd startup.
+  Misc clvmd cleanups.
+
+Version 2.02.25 - 27th April 2007
+=================================
+  Fix get_config_uint64() to read a 64-bit value not a 32-bit one.
+  Add -Wformat-security and change one fprintf() to fputs().
+  Move regex functions into libdevmapper.
+  Change some #include lines to search only standard system directories.
+  Add devices/preferred_names config regex list for displayed device names.
+  Free a temporary dir string in fcntl_lock_file() after use.
+  Fix a dm_pool_destroy() in matcher_create().
+  Introduce goto_bad macro.
+  Fix warnings on x86_64 involving ptrdiff_t in log_error messages.
+  Update pvck to include text metadata area and record detection.
+  Add support functions for token counting in config file extracts.
+  Update pvck to read labels on disk, with --labelsector parameter.
+  Add count_chars and count_chars_len functions.
+  Add /sys/block listings to lvm_dump.sh.
+  Make lvm_dump.sh list /dev recursively.
+  Fix thread race in clvmd.
+  Add scan_sector param to label_read and _find_labeller.
+  Make clvmd cope with quorum devices.
+  Add extra internal error checking to clvmd.
+  Add dev_read_circular.
+  Add pvck command stub.
+  Update lists of attribute characters in man pages.
+  Change cling alloc policy attribute character from 'C' to l'.
+  Fix creation and conversion of mirrors with tags.
+  Fix vgsplit for lvm1 format (set and validate VG name in PVs metadata).
+  Split metadata areas in vgsplit properly.
+
+Version 2.02.24 - 19th March 2007
+=================================
+  Fix processing of exit status in init scripts
+  Fix vgremove to require at least one vg argument.
+  Fix reading of striped LVs in LVM1 format.
+  Flag nolocking as clustered so clvmd startup sees clustered LVs. (2.02.10)
+  Add a few missing pieces of vgname command line validation.
+  Support the /dev/mapper prefix on most command lines.
+
+Version 2.02.23 - 8th March 2007
+================================
+  Fix vgrename active LV check to ignore differing vgids.
+  Remove no-longer-used uuid_out parameter from activation info functions.
+  Fix two more segfaults if an empty config file section encountered.
+  Move .cache file into a new /etc/lvm/cache directory by default.
+  Add devices/cache_dir & devices/cache_file_prefix, deprecating devices/cache.
+  Create directory in fcntl_lock_file() if required.
+  Exclude readline support from lvm.static.
+  Fix a leak in a reporting error path (2.02.19).
+
+Version 2.02.22 - 13th February 2007
+====================================
+  Correct -b and -P on a couple of man pages.
+  Add global/units to example.conf.
+  Fix loading of segment_libraries.
+  If a PV reappears after it was removed from its VG, make it an orphan.
+  Don't update metadata automatically if VGIDs don't match.
+  Fix some vgreduce --removemissing command line validation.
+
+Version 2.02.21 - 30th January 2007
+===================================
+  Add warning to lvm2_monitoring_init_rhel4 if attempting to stop monitoring.
+  Fix vgsplit to handle mirrors.
+  Reorder fields in reporting field definitions.
+  Fix vgs to treat args as VGs even when PV fields are displayed.
+  Fix md signature check to handle both endiannesses.
+
+Version 2.02.20 - 25th January 2007
+===================================
+  dmeventd mirror sets ignore_suspended_devices and avoids scanning mirrors.
+  Add devices/ignore_suspended_devices to ignore suspended dm devices.
+  Add some missing close() and fclose() return code checks.
+  Fix exit statuses of reporting tools (2.02.19).
+  Add init script for dmeventd monitoring.
+  lvm.static no longer interacts with dmeventd unless explicitly asked to.
+  Add field definitions to report help text.
+  Remove unnecessary cmd arg from target_*monitor_events().
+  Add private variable to dmeventd shared library interface.
+  Long-lived processes write out persistent dev cache in refresh_toolcontext().
+  Fix refresh_toolcontext() always to wipe persistent device filter cache.
+  Add is_long_lived to toolcontext.
+  Add --clustered to man pages.
+  Streamline dm_report_field_* interface.
+  Change remaining dmeventd terminology 'register' to 'monitor'.
+  Update reporting man pages.
+  No longer necessary to specify alignment type for report fields.
+
+Version 2.02.19 - 17th January 2007
+===================================
+  Fix a segfault if an empty config file section encountered.
+  Move basic reporting functions into libdevmapper.
+  Fix partition table processing after sparc changes (2.02.16).
+  Fix cmdline PE range processing segfault (2.02.13).
+  Some libdevmapper-event interface changes.
+  Report dmeventd mirror monitoring status.
+  Fix dmeventd mirror status line processing.
+
+Version 2.02.18 - 11th January 2007
+===================================
+  Revised libdevmapper-event interface for dmeventd.
+  Remove dmeventd mirror status line word limit.
+  Use CFLAGS when linking so mixed sparc builds can supply -m64.
+  Prevent permission changes on active mirrors.
+  Print warning instead of error message if lvconvert cannot zero volume.
+  Add snapshot options to lvconvert man page.
+  dumpconfig accepts a list of configuration variables to display.
+  Change dumpconfig to use --file to redirect output to a file.
+  Avoid vgreduce error when mirror code removes the log LV.
+  Remove 3 redundant AC_MSG_RESULTs from configure.in.
+  Free memory in _raw_read_mda_header() error paths.
+  Fix ambiguous vgsplit error message for split LV.
+  Fix lvextend man page typo.
+  Add configure --with-dmdir to compile against a device-mapper source tree.
+  Use no flush suspending for mirrors.
+  Add dmeventd_mirror register_mutex, tidy initialisation & add memlock.
+  Fix create mirror with name longer than 22 chars.
+  Fix some activate.c prototypes when compiled without devmapper.
+  Fix dmeventd mirror to cope if monitored device disappears.
+
+Version 2.02.17 - 14th December 2006
+====================================
+  Add missing pvremove error message when device doesn't exist.
+  When lvconvert allocates a mirror log, respect parallel area constraints.
+  Use loop to iterate through the now-ordered policy list in _allocate().
+  Check for failure to allocate just the mirror log.
+  Introduce calc_area_multiple().
+  Support mirror log allocation when there is only one PV: area_count now 0.
+  Fix detection of smallest area in _alloc_parallel_area() for cling policy.
+  Add manpage entry for clvmd -T
+  Fix gulm operation of clvmd, including a hang when doing lvchange -aey
+  Fix hang in clvmd if a pre-command failed.
+
+Version 2.02.16 - 1st December 2006
+===================================
+  Fix VG clustered read locks to use PR not CR.
+  Adjust some alignments for ia64/sparc.
+  Fix mirror segment removal to use temporary error segment.
+  Always compile debug logging into clvmd.
+  Add startup timeout to RHEL4 clvmd startup script.
+  Add -T (startup timeout) switch to clvmd.
+  Improve lvm_dump.sh robustness.
+  Update lvm2create_initrd to support gentoo.
+
+Version 2.02.15 - 21st November 2006
+====================================
+  Fix clvmd_init_rhel4 line truncation (2.02.14).
+  Install lvmdump by default.
+  Fix check for snapshot module when activating snapshot.
+  Fix pvremove error path for case when PV is in use.
+  Warn if certain duplicate config file entries are seen.
+  Enhance lvm_dump.sh for sysreport integration and add man page.
+  Fix --autobackup argument which could never disable backups.
+  Fix a label_verify error path.
+
+Version 2.02.14 - 10th November 2006
+====================================
+  Fix adjusted_mirror_region_size() to handle 64-bit size.
+  Add some missing bounds checks on 32-bit extent counters.
+  Add Petabyte and Exabyte support.
+  Fix lvcreate error message when 0 extents requested.
+  lvremove man page: volumes must be cluster inactive before being removed.
+  Protect .cache manipulations with fcntl locking.
+  Change .cache timestamp comparisons to use ctime.
+  Fix mirror log LV writing to set all bits in whole LV.
+  Fix clustered VG detection and default runlevels in clvmd_init_rhel4.
+  Fix high-level free space check for partial allocations.
+
+Version 2.02.13 - 27th October 2006
+===================================
+  Add couple of missing files to tools/Makefile CLEAN_TARGETS.
+  When adding snapshot leave cow LV mapped device active after zeroing.
+  Fix a clvmd debug message.
+  Add dev_flush() to set_lv().
+  Add lvchange --resync.
+  Perform high-level free space check before each allocation attempt.
+  Don't allow a node to remove an LV that's exclusively active on anther node.
+  Cope if same PV is included more than once in cmdline PE range list.
+  Set PV size to current device size if it is found to be zero.
+  Add segment parameter to target_present functions.
+
+Version 2.02.12 - 16th October 2006
+===================================
+  Fix pvdisplay to use vg_read() for non-orphans.
+  Fall back to internal locking if external locking lib is missing or fails.
+  Retain activation state after changing LV minor number with --force.
+  Propagate clustered flag in vgsplit and require resizeable flag.
+
+Version 2.02.11 - 12th October 2006
+===================================
+  Add clvmd function to return the cluster name. not used by LVM yet.
+  Add cling allocation policy.
+  Change _check_contiguous() to use _for_each_pv().
+  Extend _for_each_pv() to allow termination without error.
+  Abstract _is_contiguous().
+  Remove duplicated pv arg from _check_contiguous().
+  Accept regionsize with lvconvert.
+  Add report columns with underscore before field names ending 'size'.
+  Correct regionsize default on lvcreate man page (MB).
+  Fix clvmd bug that could cause it to die when a node with a long name crashed.
+  Add device size to text metadata.
+  Fix format_text mda_setup pv->size and pv_setup pe_count calculations.
+  Fix _for_each_pv() for mirror with core log.
+  Add lvm_dump.sh script to create a tarball of debugging info from a system.
+  Capture error messages in clvmd and pass them back to the user.
+  Remove unused #defines from filter-md.c.
+  Make clvmd restart init script wait until clvmd has died before starting it.
+  Add -R to clvmd which tells running clvmds to reload their device cache.
+  Add LV column to reports listing kernel modules needed for activation.
+  Show available fields if report given invalid field. (e.g. lvs -o list)
+  Add timestamp functions with --disable-realtime configure option.
+  Add %VG, %LV and %FREE suffices to lvcreate/lvresize --extents arg.
+  Fix two potential NULL pointer derefs in error cases in vg_read().
+  Separate --enable-cluster from locking lib options in lvmconf.sh.
+  Add a missing comma in lvcreate man page.
+
+Version 2.02.10 - 19th September 2006
+=====================================
+  Fix lvconvert mirror change case detection logic.
+  Fix mirror log detachment so it correctly becomes a standalone LV.
+  Extend _check_contiguous() to detect single-area LVs.
+  Include mirror log (untested) in _for_each_pv() processing.
+  Use MIRROR_LOG_SIZE constant.
+  Remove struct seg_pvs from _for_each_pv() to generalise.
+  Avoid adding duplicates to list of parallel PVs to avoid.
+  Fix several incorrect comparisons in parallel area avoidance code.
+  Fix segment lengths when flattening existing parallel areas.
+  Log existing parallel areas prior to allocation.
+  Fix mirror log creation when activation disabled.
+  Don't attempt automatic recovery without proper locking.
+  When using local file locking, skip clustered VGs.
+  Add fallback_to_clustered_locking and fallback_to_local_locking parameters.
+  lvm.static uses built-in cluster locking instead of external locking.
+  Don't attempt to load shared libraries if built statically.
+  Change default locking_lib to liblvm2clusterlock.so.
+  Add skip_dev_dir() to process command line VGs.
+  Stop clvmd complaining about nodes that have left the cluster.
+  Move lvm_snprintf(), split_words() and split_dm_name() into libdevmapper.
+  Add lvconvert man page.
+  Add mirror options to man pages.
+  Prevent mirror renames.
+  Move CMDLIB code into separate file and record whether static build.
+
+Version 2.02.09 - 17th August 2006
+==================================
+  Fix PE_ALIGN for pagesize over 32KB.
+  Separate out LVM1_PE_ALIGN and pe_align().
+  Add lvm_getpagesize wrapper.
+  Add --maxphysicalvolumes to vgchange.
+
+Version 2.02.08 - 15th August 2006
+==================================
+  Add checks for duplicate LV name, lvid and PV id before writing metadata.
+  Report all sanity check failures, not just the first.
+  Fix missing lockfs on first snapshot creation.
+  Add unreliable --trustcache option to reporting commands.
+  Fix locking for mimage removal.
+  Fix clvmd_init_rhel4 'status' exit code.
+
+Version 2.02.07 - 17th July 2006
+================================
+  Fix activation logic in lvchange --persistent.
+  Don't ignore persistent minor numbers when activating.
+  Use RTLD_GLOBAL when loading shared libraries.
+  Add some forgotten memlock checks to _vg_read to protect against full scans.
+  Add mutex to dmeventd_mirror to avoid concurrent execution.
+  Fix vgreduce --removemissing to return success if VG is already consistent.
+  Fix return code if VG specified on command line is not found.
+  Fix PV tools to include orphaned PVs in default output again.
+  Fixed unaligned access when using clvm.
+  Fix an extra dev_close in a label_read error path.
+  Append patches to commit emails.
+  Fix target_register_events args.
+  Prevent snapshots of mirrors.
+  Add DISTCLEAN_TARGETS to make template for configure.h.
+  More fixes to error paths.
+  Fix lvcreate corelog validation.
+  Add --config for overriding most config file settings from cmdline.
+  Quote arguments when printing command line.
+  Remove linefeed from 'initialising logging' message.
+  Add 'Completed' debug message.
+  Don't attempt library exit after reloading config files.
+  Always compile with libdevmapper, even if device-mapper is disabled.
+
+Version 2.02.06 - 12th May 2006
+===============================
+  Propagate --monitor around cluster.
+  Add --monitor to vgcreate and lvcreate to control dmeventd registration.
+  Filter LCK_NONBLOCK in clvmd lock_vg.
+  Add --nosync to lvcreate with LV flag NOTSYNCED.
+  Use mirror's uuid for a core log.
+  Add mirror log fault-handling policy.
+  Improve mirror warning messages and tidy dmeventd syslog output.
+  Propagate nosync flag around cluster.
+  Allow vgreduce to handle mirror log failures.
+  Add --corelog to lvcreate and lvconvert.
+  Create a log header for replacement in-sync mirror log.
+  Use set_lv() and dev_set() to wipe sections of devices.
+  Add mirror_in_sync() flag to avoid unnecessary resync on activation.
+  Add mirror_library description to example.conf.
+  Fix uuid_from_num() buffer overrun.
+  Make SIZE_SHORT the default for display_size().
+  Fix some memory leaks in error paths found by coverity.
+  Use C99 struct initialisers.
+  Move DEFS into configure.h.
+  Clean-ups to remove miscellaneous compiler warnings.
+  Improve stripe size validation.
+  Increase maximum stripe size limit to physical extent size for lvm2 metadata.
+  Fix activation code to check for pre-existing mirror logs.
+  Tighten region size validation.
+  Ignore empty strings in config files.
+  Require non-zero regionsize and document parameter on lvcreate man page.
+  Invalidate cache if composition of VG changed externally.
+
+Version 2.02.05 - 21st April 2006
+=================================
+  Fix vgid string termination in recent cache code.
+
+Version 2.02.04 - 19th April 2006
+=================================
+  Check for libsepol.
+  Add some cflow & scope support.
+  Separate out DEFS from CFLAGS.
+  Remove inlines and use unique function names.
+
+Version 2.02.03 - 14th April 2006
+=================================
+  vgrename accepts vgid and exported VG.
+  Add --partial to pvs.
+  When choosing between identically-named VGs, also consider creation_host.
+  Provide total log suppression with 2.
+  Fix vgexport/vgimport to set/reset PV exported flag so pv_attr is correct.
+  Add vgid to struct physical_volume and pass with vg_name to some functions.
+  If two or more VGs are found with the same name, use one that is not exported.
+  Whenever vgname is captured, also capture vgid and whether exported.
+  Remove an incorrect unlock_vg() from process_each_lv().
+  Update extent size information in vgchange and vgcreate man pages.
+  Introduce origin_from_cow() and lv_is_visible().
+  pvremove without -f now fails if there's no PV label.
+  Support lvconvert -s.
+  Suppress locking library load failure message if --ignorelockingfailure.
+  Propagate partial mode around cluster.
+  Fix archive file expiration.
+  Fix dmeventd build.
+  clvmd now uses libcman rather than cman ioctls.
+  clvmd will allow new cman to shutdown on request.
+
+Version 2.02.02 - 7th February 2006
+===================================
+  Add %.so: %.a make template rule.
+  Switchover library building to use LIB_SUFFIX.
+  Only do lockfs filesystem sync when suspending snapshots.
+  Always print warning if activation is disabled.
+  vgreduce removes mirror images.
+  Add --mirrorsonly to vgreduce.
+  vgreduce replaces active LVs with error segment before removing them.
+  Set block_on_error parameter if available.
+  Add target_version.
+  Add details to format1 'Invalid LV in extent map' error message.
+  Fix lvscan snapshot full display.
+  Bring lvdisplay man page example into line.
+  Add mirror dmeventd library.
+  Add some activation logic to remove_mirror_images().
+  lvconvert can remove specified PVs from a mirror.
+  lvconvert turns an existing LV into a mirror.
+  Allow signed mirrors arguments.
+  Move create_mirror_log() into toollib.
+  Determine parallel PVs to avoid with ALLOC_NORMAL allocation.
+  Fix lv_empty.
+
+Version 2.02.01 - 23rd November 2005
+====================================
+  Fix lvdisplay cmdline to accept snapshots.
+  Fix open RO->RW promotion.
+  Fix missing vg_revert in lvcreate error path.
+
+Version 2.02.00 - 10th November 2005
+====================================
+  Extend allocation areas to avoid overflow with contiguous with other PVs.
+  Stop lvcreate attempting to wipe zero or error segments.
+  Added new lvs table attributes.
+  Separated out activation preload.
+  Moved activation functions into libdevmapper.
+  Fixed build_dm_name.
+  Add return macros.
+  Added xen xvd devices.
+  Clear up precommitted metadata better.
+  A pvresize implementation.
+  Fix contiguous allocation when there are no preceding segments.
+  Add mirror_seg pointer to lv_segment struct.
+  Only keep a device open if it's known to belong to a locked VG.
+  Fix lvdisplay to show all mirror destinations.
+  Replacement suspend code using libdevmapper dependency tree.
+  Add DEFS to make.tmpl.
+  Use dm_is_dm_major instead of local copy.
+  Allow mapped devices to be used as PVs.
+  Move set_selinux_context into libdevmapper.
+  Fix automatic text metadata buffer expansion (using macro).
+  Cache formatted text metadata buffer between metadata area writes.
+  Add pe_start field to pvs.
+  Add 'LVM-' prefix to uuids.
+  Split lv_segment_area from lv_segment to permit extension.
+  Replacement deactivation code using libdevmapper dependency tree.
+  Simplify dev_manager_info().
+  Attempt to load missing targets using modprobe.
+  Add -a to lvscan.
+  Move mknodes into libdevmapper.
+  Move bitset, hash, pool and dbg_malloc into libdevmapper.
+
+Version 2.01.15 - 16th October 2005
+===================================
+  Refuse to run pvcreate/pvremove on devices we can't open exclusively.
+  Use ORPHAN lock definition throughout.
+  Validate chunksize in lvcreate.
+  Reduce chunksize limit to 512k.
+  Fix chunksize field in reports.
+  Don't hide snapshots from default 'lvs' output.
+  Add is_dm_major() for use in duplicate device detection in lvmcache_add().
+  Really switch device number in lvmcache when it says it is doing so.
+  Option for bitset memory allocation using malloc as well as pool.
+  Don't assume exactly two mirrors when parsing mirror status.
+  Suppress fsync() error message on filesystems that don't support it.
+  Fix yes_no_prompt() error handling.
+  Add lvm.conf comment warning against multiple filter lines.
+  Tidy lvmconf.sh.
+  Add format1 dev_write debug messages.
+  Add clustered VG attribute to report.
+  Move lvconvert parameters into struct lvconvert_params.
+  Add clustered VG flag to LV lock requests.
+  Change LV locking macros to take lv instead of lvid.
+  Prepend 'cluster' activation parameter to mirror log when appropriate.
+  Pass exclusive flag to lv_activate and on to target activation code.
+  Prevent snapshot creation in a clustered VG for now.
+  Factor out adjusted_mirror_region_size() and generate_log_name_format().
+  Move compose_log_line() into mirror directory.
+  Factor out _get_library_path().
+  Don't kill idling clvmd threads.
+  clvmd no longer takes out locks for non-clustered LVs.
+  Recognise ATA over Ethernet (aoe) devices.
+
+Version 2.01.14 - 4th August 2005
+=================================
+  Fix lvconvert PV parameter in help string.
+  Prevent snapshots getting activated in a clustered VG.
+  Separate out _build_dev_string.
+  Move zero_lv to toollib.
+  Fix pool format handler to work with pv segment code.
+
+Version 2.01.13 - 13th July 2005
+================================
+  Fix pvmove segment splitting.
+  Abstract vg_validate.
+  Only make one attempt at contiguous allocation.
+  Fix lvm1 format metadata read.
+  Fix lvm1 format non-mirror lvcreate.
+
+Version 2.01.12 - 14th June 2005
+================================
+  Various allocation-related pvmove fixes.
+  Log an error if clvmd can't resolve a host name got from CCS.
+  Fix potential spin loop in clvmd.
+
+Version 2.01.11 - 13th June 2005
+================================
+  Added lvmconf.sh.
+  Use matchpathcon mode parameter.
+  Don't defer closing dead FDs in clvmd.
+  Remove hard-coded 64k text metadata writing restriction.
+  Make VG name restrictions consistent.
+  Introduce lvconvert.  So far only removes mirror images.
+  Allow mirror images to be resized.
+  Allow mirror images to have more than one segment.
+  Centralise restrictions on LV names.
+  Always insert an intermediate layer for mirrors.
+  Suppress hidden LVs from reports unless --all is given.
+  Use square brackets for hidden LVs in reports.
+  Allow the creation of mirrors with contiguous extents.
+  Always perform sanity checks against metadata before committing it to disk.
+  Split lv_extend into two steps: choosing extents + allocation to LV(s).
+  Add mirror log region size to metadata.
+  Use list_iterate_items throughout and add list*back macros.
+  Introduce seg_ macros to access areas.
+  Add segtype_is_ macros.
+  Support tiny metadata areas for pool conversions.
+  Mirror activation handles disk log as well as core.
+  Activation code recognises mirror log dependency.
+  Add mirror_log and regionsize fields to report.
+  Fix non-orphan pvchange -u.
+  Fix vgmerge to handle duplicate LVIDs.
+  Move archiver code from tools into library.
+  vgscan/change/display/vgs automatically create metadata backups if needed.
+  Merge cloned allocation functions.
+  Fix contiguous allocation policy with linear.
+  Cope with missing format1 PVs again.
+  Remove lists of free PV segments.
+  Simplify pv_maps code and remove slow bitset algorithm.
+  Red-Hat-ify the clvmd rhel4 initscript.
+  %Zu->%zu
+  Fix loopfiles alias alloc & mem debugging.
+  Un-inline dbg_strdup.
+  lv_reduce tidying.
+  Remove some unnecessary parameters.
+  Introduce seg_is macros.
+
+Version 2.01.10 - 3rd May 2005
+==============================
+  Don't create backup and archive dirs till needed.
+  Reinstate full PV size when removing from VG.
+  Support loopfiles for testing.
+  Tidy lv_segment interface.
+  pv_segment support.
+  vgchange --physicalextentsize
+  Internal snapshot restructuring.
+  Remove unused internal non-persistent snapshot option.
+  Allow offline extension of snapshot volumes.
+  Move from 2-step to 3-step on-disk metadata commit.
+  Scan ramdisks too and allow non-O_DIRECT fallback.
+  Annotate, tidy and extend list.h.
+  Alignment tidying.
+  Make clvmd work around some "bugs" in gulm's node state notifications.
+  Tidy clvmd's SIGHUP handler
+
+Version 2.01.09 - 4th April 2005
+================================
+  Add --ignorelockingfailure to vgmknodes.
+  clvmd: Don't allow user operations to start until the lvm thread is fully up.
+  clvmd-gulm: set KEEPALIVE on sockets.
+
+Version 2.01.08 - 22nd March 2005
+=================================
+  Add clustered attribute so vgchange can identify clustered VGs w/o locking.
+  Improve detection of external changes affecting internal cache.
+  Add 'already in device cache' debug message.
+  Add -a to pvdisplay -C.
+  Avoid rmdir opendir error messsages when dir was already removed.
+  Tighten signal handlers.
+  Avoid some compiler warnings.
+  Additional rename failure error message.
+  read/write may be macros.
+  clvmd: don't take out lvm thread lock at startup, it only protects jobs list.
+
+Version 2.01.07 - 8th March 2005
+================================
+  Cope with new devices appearing by rescanning /dev if a uuid can't be found.
+  Remove DESTDIR from LVM_SHARED_PATH.
+  clvmd fixes: make FDs close-on-exec
+               gulm unlocks VG & orphan locks at startup in case they are stale
+               gulm now unlocks VG & orphan locks if client dies.
+
+Version 2.01.06 - 1st March 2005
+================================
+  Suppress 'open failed' error messages during scanning.
+  Option to suppress warnings of file descriptors left open.
+  Fix default value of metadatacopies in documentation (2->1).
+  Fix clvmd-gulm locking.
+  ./configure --enable-debug now enables debugging code in clvmd.
+  Fix clvmd-gulm node up/down code so it actually works.
+  clvmd-gulm now releases locks when shut down.
+
+Version 2.01.05 - 18th February 2005
+====================================
+  Static binary invokes dynamic binary if appropriate.
+  Make clvmd config check a little more tolerant.
+  gulm clvmd can now cope with >1 message arriving in a TCP message.
+
+Version 2.01.04 - 9th February 2005
+===================================
+  Add fixed offset to imported pool minor numbers.
+  Update binary pathnames in clvmd_init_rhel4.
+  lvm2cmd.so should skip the check for open fds.
+  Remove unused -f from pvmove.
+  Gulm clvmd doesn't report "connection refused" errors.
+  clvmd does a basic config file sanity check at startup.
+  Fix potential thread shutdown race in clvmd.
+
+Version 2.01.03 - 1st February 2005
+===================================
+  More 64-bit display/report fixes.
+  More informative startup mesg if can't create /etc/lvm.
+  Fix snapshot device size bug (since 2.01.01).
+  clvmd announces startup and cluster connection in syslog.
+  Gulm clvmd doesn't hang trying to talk to a rebooted node.
+  Gulm clvmd doesn't print cman error on startup.
+
+Version 2.01.02 - 21st January 2005
+===================================
+  Update clvmd_init_rhel4: use lvm.static and don't load dlm.
+  Fix some size_t printing.
+  Fix 64 bit xlate consts.
+  Split out pool sptype_names to avoid unused const.
+  Always fail if random id generation fails.
+  Recognise gnbd devices.
+  Fix clvmd startup bug introduced in cman/gulm amalgamation.
+  Improve reporting of node-specific locking errors.
+
+Version 2.01.01 - 19th January 2005
+===================================
+  Fix clvmd lv_info_by_lvid open_count.
+  Store snapshot and origin sizes separately.
+  Update vgcreate man page.
+
+Version 2.01.00 - 17th January 2005
+===================================
+  Fix vgscan metadata auto-correction.
+  Only ask libdevmapper for open_count when we need it.
+  Adjust RHEL4 clvmd init script priority.
+  Enable building of CMAN & GULM versions of clvmd into a single binary
+
+Version 2.00.33 - 7th January 2005
+==================================
+  pvcreate wipes first 4 sectors unless given --zero n.
+  gulm clvmd now uses new ccsd key names.
+  gulm clvmd now doesn't ignore the first node in cluster.conf
+  Improve clvmd failure message if it's already running.
+  Allow user to kill clvmd during initialisation.
+  Fix off-by-one error in cluster_locking that could cause read hangs.
+
+Version 2.00.32 - 22nd December 2004
+====================================
+  Drop static/dl restriction for now.
+  Fix an error fprintf.
+  Fix vgdisplay -s. Breaks (undocumented) lvs/pvs/vgs -s instead for now.
+  Fix device reference counting on re-opens.
+  Ignore sysfs symlinks when DT_UNKNOWN.
+  Add clvmd init script for RHEL4.
+  Skip devices that are too small to be PVs.
+  Fix pvchange -x segfault with lvm2-format orphan.
+  Cope with empty msdos partition tables.
+  Add CONTRIBUTORS file.
+
+Version 2.00.31 - 12th December 2004
+====================================
+  Reopen RO file descriptors RW if necessary.
+
+Version 2.00.30 - 10th December 2004
+====================================
+  Additional device-handling debug messages.
+  Additional verbosity level -vvvv includes line numbers and backtraces.
+  Verbose messages now go to stderr not stdout.
+  Close any stray file descriptors before starting.
+  Refine partitionable checks for certain device types.
+  Allow devices/types to override built-ins.
+  Fix lvreduce man page .i->.I
+  Fix vgsplit man page title.
+  Fix clvmd man makefile.
+  Extend dev_open logging.
+  Make clvmd_fix_conf.sh UNDOable.
+
+Version 2.00.29 - 27th November 2004
+====================================
+  xlate compilation fix.
+
+Version 2.00.28 - 27th November 2004
+====================================
+  Fix partition table & md signature detection.
+  Minor configure/makefile tidy.
+  Export version.h from tools for clvmd.
+
+Version 2.00.27 - 24th November 2004
+====================================
+  Trap large memory allocation requests.
+  Fix to partition table detection code.
+  Improve filter debug mesgs.
+  Make clvmd_fix_conf.sh UNDOable
+
+Version 2.00.26 - 23rd November 2004
+====================================
+  Improve pool debugging stats.
+  Detect partition table signature.
+  pvcreate wipes md superblocks. (With --uuid or --restorefile it prompts.)
+  Separate out md superblock detection code.
+  Prevent snapshot origin resizing.
+  Improve a vgremove error message.
+  Update some man pages.
+  Allow y/n with -ae args (exclusive activation).
+  Fixes to lvcreate vgname parsing.
+  Fix dm_name string size calculation.
+  Improve clvmd error reporting during startup.
+  Make clvmd cope with large gaps in node numbers IDs.
+  Make clvmd initialisation cope better with debugging output.
+  Tidy clvmd socket callbacks so all work happens outside main loop.
+  clvmd -V now displays lvm version too.
+  Add optional gulm build for clvmd
+
+Version 2.00.25 - 29th September 2004
+=====================================
+  Fix return code from rm_link for vgmknodes.
+  Make clvmd LV hash table thread-safe.
+  Fix clvmd locking so it will lock out multiple users on the same node.
+  Fix clvmd VG locking to it can cope with multiple VG locks.
+  Remove spurious trailing dot in lvreduce man page.
+  Fix vgremove locking.
+
+Version 2.00.24 - 16th September 2004
+=====================================
+  Fix pool_empty so it really does empty the memory pool.
+  Rename old segtypes files to segtype.
+  Some fixes to memory debugging code.
+  Exclude internal commands formats & segtypes from install.
+
+Version 2.00.23 - 15th September 2004
+=====================================
+  Export dm name build & split functions.
+  Use O_NOATIME on devices if available.
+  Write log message when each segtype/format gets initialised.
+  New commands 'segtypes' and 'formats'.
+  Suppress pvmove abort message in test mode.
+  Improve pvcreate/remove device not found error message.
+  Allow pvmove to move data within the same PV.
+  Describe how pvmove works on man page.
+  Test for incompatible format/segtype combinations in lv_extend.
+  Fix lvchange example on man page.
+
+Version 2.00.22 - 3rd September 2004
+====================================
+  Fix /dev/vgname perms.
+  Restructure xlate.h.
+  Add clvmd man page.
+
+Version 2.00.21 - 19th August 2004
+==================================
+  Update cnxman-socket.h from cman.
+  Recognise iseries/vd devices.
+  Use 'make install_cluster' to install cluster extensions only.
+  Cope with DT_UNKNOWN in sysfs.
+  Fix extents_moved metadata size comment.
+  Remove duplicate line in pvremove help text.
+  Support variable mirror region size.
+  Support PE ranges in pvmove source PV.
+  Fixes to as-yet-unused LV segment splitting code.
+  Change alloc_areas to pe_ranges and allow suppression of availability checks.
+  Add dev_size column to pvs.
+  Add report columns for in-kernel device number.
+
+Version 2.00.20 - 3 July 2004
+=============================
+  More autoconf fixes.
+  Fix device number handling for 2.6 kernels.
+
+Version 2.00.19 - 29 June 2004
+==============================
+  Reduce severity of setlocale failure message.
+  Recognise argv[0] "initrd-lvm" (pld-linux).
+  Make -O2 configurable.
+  Added --disable-selinux to configure script.
+  LD_FLAGS->LDFLAGS & LD_DEPS->LDDEPS in configure script.
+  Add init_debug to clvmd.
+
+Version 2.00.18 - 24 June 2004
+==============================
+  Fix vgchange activation.
+  Add cluster support.
+
+Version 2.00.17 - 20 June 2004
+==============================
+  configure --enable-fsadm to try out fsadm.  fsadm is not tested yet.
+  Display all filtered devices, not just PVs, with pvs -a.
+  Fix sync_dir() when no / in filename
+  vgcfgbackup -f accepts template with %s for VG name.
+  Extend hash functions to handle non-null-terminated data.
+  Add local activation support.
+  Tidy relative paths in makefile includes.
+  fsadm support for fsck and resizing - needs testing.
+  Add read-only GFS pool support.
+  Add lvm2create_initrd script from http://poochiereds.net/svn/lvm2/
+  Fix rounding of large diplayed sizes.
+  Suppress decimal point when using units of sectors/bytes.
+  Additional kernel target checks before pvmove & snapshot creation.
+  Add i2o_block.
+
+Version 2.00.16 - 24 May 2004
+=============================
+  Set area_count within alloc_lv_segment.
+  Remove error labels from lvresize.
+  Fix a pvs error path.
+  xxchange -ae for exclusive activation.
+  Don't return non-zero status if there aren't any volume groups.
+  Add --alloc argument to tools.
+  Rename allocation policies to contiguous, normal, anywhere, inherit.
+  nextfree becomes normal; anywhere isn't implemented yet.
+  LV inherits allocation policy from VG. Defaults: LV - inherit; VG - normal
+  Additional status character added to vgs to indicate allocation policy.
+  Add reset_fn to external_locking.
+  Ensure presence of virtual targets before attempting activating.
+  Attempt to fix resizing of snapshot origins.
+  Restructure lvresize, bringing it closer to lvcreate.
+  A quick sanity check on vg_disk struct when read in.  More checks needed.
+  Only include visible LVs in active/open counts.
+  Add virtual segment types, zero and error.  A large sparse device can be
+constructed as a writeable snapshot of a large zero segment.
+  Add --type to lvcreate/resize.
+  Push lv_create & alloc policy up to tool level.
+  Fix pvdisplay return code.
+  Detect invalid LV names in arg lists.
+  Reporting uses line-at-a-time output.
+  lvm2 format sets unlimited_vols format flag.
+  Internal-only metadata flag support.
+  Basic checking for presence of device-mapper targets.
+  Separate out polldaemon.
+  Revise internal locking semantics.
+  Move find_pv_by_name to library.
+  Rename move->copy.
+  Add devices to segments report.
+  Begin separating out segment code. There's a lot of change here.
+  Compress any (obsolete) long LVM1 pvids encountered.
+  Support for tagged config files.
+  Don't abort operations if selinux present but disabled.
+  Fix typo in configure which left HAVE_LIBDL unset.
+
+Version 2.00.15 - 19 Apr 2004
+=============================
+  configure --with-owner= --with-group= to avoid -o and -g args to 'install'
+
+Version 2.00.14 - 16 Apr 2004
+=============================
+  Use 64-bit file functions by default.
+
+Version 2.00.13 - 16 Apr 2004
+=============================
+  Set devices/md_component_detection = 1 to ignore devices containing md
+  superblocks. [Luca Berra]
+  Ignore error setting selinux file context if fs doesn't support it.
+
+Version 2.00.12 - 14 Apr 2004
+=============================
+  Install a default lvm.conf into /etc/lvm if there isn't one already.
+  Allow different installation dir for lvm.static (configure --staticdir=)
+  Fix inverted selinux error check.
+  Recognise power2 in /proc/devices.
+  Fix counting in lvs_in_vg_opened. [It ignored devices open more than once.]
+
+Version 2.00.11 - 8 Apr 2004
+============================
+  Set fallback_to_lvm1 in lvm.conf (or configure --enable-lvm1_fallback)
+  to run lvm1 binaries if running a 2.4 kernel without device-mapper.
+
+Version 2.00.10 - 7 Apr 2004
+============================
+  More fixes for static build.
+  Add basic selinux support.
+  Fix sysfs detection.
+
+Version 2.00.09 - 31 Mar 2004
+=============================
+  Update copyright notices for Red Hat.
+  Fix vgmknodes to remove dud /dev/mapper entries. (libdevmapper update reqd).
+  Add LVM1-style colon output to vgdisplay.
+  lvchange --refresh to reload active LVs.
+  Add string display to memory leak dump.
+  Add locking flags & memlock option.
+  Add list_versions to library.
+  Ignore open hidden LVs when checking if deactivation is OK.
+  Suppress move percentage when device inactive.
+  Add lv_info_by_lvid.
+  Various tidy-ups to the build process.
+  Rebaseline internal verbose level.
+  Add --nolocking option for read operations if locking is failing.
+  Add option to compile into a library.
+  When compiled without libdevmapper, only print warning message once.
+  Fix lvreduce PV extent calculations.
+  Fix DESTDIR to work with configure path overrides.
+  Always use / as config file separator & rename internal config file variables.
+  Add support for tagging PV/VG/LVs and hosts.
+  Fix rare bug in recognition of long cmdline argument forms.
+  Add basic internationalisation infrastructure.
+  Don't recurse symlinked dirs such as /dev/fd on 2.6 kernels.
+  Update autoconf files.
+  Add sysfs block device filtering for 2.6 kernels.
+  Update refs for move to sources.redhat.com.
+
+Friday 14th November 2003
+=========================
+Some bug fixes & minor enhancements, including:
+  Backwards compatibility with LVM1 metadata improved.
+  Missing man pages written.
+  Tool error codes made more consistent.
+  vgmknodes written.
+  O_DIRECT can be turned off if it doesn't work in your kernel.
+  dumpconfig to display the active configuration file
+
+You need to update libdevmapper before using 'vgmknodes' or 'vgscan --mknodes'.
+If your root filesystem is on an LV, you should run one of those two
+commands to fix up the special files in /dev in your real root filesystem
+after finishing with your initrd.  Also, remember you can use
+'vgchange --ignorelockingfailure' on your initrd if the tool fails because
+it can't write a lock file to a read-only filesystem.
+
+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!
+  We expect it to be more efficient and more robust than the original format.
+  It's more compact and supports transactional changes and replication.
+  Should things go wrong on a system, it's human-readable (and editable).
+
+Please report any problems you find to the mailing list,
+linux-lvm@sistina.com.  The software has NOT yet been thoroughly
+tested and so quite possibly there'll still be some bugs in it.
+Be aware of the disclaimer in the COPYING file.
+
+While testing, we recommend turning logging on in the configuration file
+to provide us with diagnostic information:
+  log {
+        file="/tmp/lvm2.log"
+	level=7
+	activation=1
+  }
+
+You should schedule regular backups of your configuration file and
+metadata backups and archives (normally kept under /etc/lvm).
+
+Please read docs/example.conf and "man lvm.conf" to find out more about
+the configuration file.
+
+To convert an existing volume group called vg1 to the new format using
+the default settings, use "vgconvert -M2 vg1".  See "man vgconvert".
+
+-M (or --metadatatype in its long form) is a new flag to indicate which
+format of metadata the command should use for anything it creates.
+Currently, the valid types are "lvm1" and "lvm2" and they can be
+abbreviated to "1" and "2" respectively.  The default value for this
+flag can be changed in the global section in the config file.
+
+Backwards-compatible support for the original LVM1 metadata format is
+maintained, but it can be moved into a shared library or removed
+completely with configure's --with-lvm1 option.
+
+Under LVM2, the basic unit of metadata is the volume group.  Different
+volume groups can use different formats of metadata - vg1 could use
+the original LVM1 format while vg2 used the new format - but you can't
+mix formats within a volume group.  So to add a PV to an LVM2-format
+volume group you must run "pvcreate -M2" on it, followed by "vgextend".
+
+With LVM2-format metadata, lvextend will let you specify striping
+parameters.  So an LV could consist of two or more "segments" - the
+first segment could have 3 stripes while the second segment has just 2.
+
+LVM2 maintains a backup of the current metadata for each volume group
+in /etc/lvm/backup, and puts copies of previous versions in
+/etc/lvm/archive.  "vgcfgbackup" and "vgcfgrestore" can be used to
+create and restore from these files.  If you fully understand what
+you're doing, metadata can be changed by editing a copy of a current
+backup file and using vgcfgrestore to reload it.
+
+Please read the pvcreate man page for more information on the new
+format for metadata.
+
+All tools that can change things have a --test flag which can be used
+to check the effect  of a set of cmdline args without really making the
+changes.
+
+
+What's not finished?
+====================
+The internal cache.  If you turn on debugging output you'll see lots of
+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
+the work on the cache.
+
+Several of the tools do not yet contain the logic to handle full
+recovery: combinations of pvcreate and vgcfgrestore may sometimes be
+needed to restore metadata if a tool gets interrupted or crashes or
+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.
+
+Recovery tools to salvage "lost" metadata directly from the disks:
+but we hope the new format will mean such tools are hardly ever needed!
Index: src/external/gpl2/lvm2tools/dist/WHATS_NEW_DM
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/WHATS_NEW_DM
diff -N src/external/gpl2/lvm2tools/dist/WHATS_NEW_DM
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/WHATS_NEW_DM	12 Dec 2008 16:32:57 -0000	1.1.1.1.2.2
@@ -0,0 +1,360 @@
+Version 1.02.29 - 10th November 2008
+====================================
+  Merge device-mapper into the LVM2 tree.
+  Split out dm-logging.h from log.h.
+  Use lvm-types.h.
+  Add usrsbindir to configure.
+
+Version 1.02.28 - 18th September 2008
+=====================================
+  Only resume devices in dm_tree_preload_children if size changes.
+  Extend deptree buffers so the largest possible device numbers fit.
+  Generate versioned libdevmapper-event.so.
+  Underline longer report help text headings.
+
+Version 1.02.27 - 25th June 2008
+================================
+  Align struct memblock in dbg_malloc for sparc.
+  Add --unquoted and --rows to dmsetup.
+  Avoid compiler warning about cast in dmsetup.c's OFFSET_OF macro.
+  Fix inverted no_flush debug message.
+  Remove --enable-jobs from configure. (Set at runtime instead.)
+  Bring configure.in and list.h into line with the lvm2 versions.
+
+Version 1.02.26 - 6th June 2008
+===============================
+  Initialise params buffer to empty string in _emit_segment.
+  Skip add_dev_node when ioctls disabled.
+  Make dm_hash_iter safe against deletion.
+  Accept a NULL pointer to dm_free silently.
+  Add tables_loaded, readonly and suspended columns to reports.
+  Add --nameprefixes to dmsetup.
+  Add field name prefix option to reporting functions.
+  Calculate string size within dm_pool_grow_object.
+
+Version 1.02.25 - 10th April 2008
+=================================
+  Remove redundant if-before-free tests.
+  Use log_warn for reporting field help text instead of log_print.
+  Change cluster mirror log type name (s/clustered_/clustered-/)
+
+Version 1.02.24 - 20th December 2007
+====================================
+  Fix deptree to pass new name to _resume_node after a rename.
+  Suppress other node operations if node is deleted.
+  Add node operation stack debug messages.
+  Report error when empty device name passed to readahead functions.
+  Fix minimum readahead debug message.
+
+Version 1.02.23 - 5th December 2007
+===================================
+  Update dm-ioctl.h after removal of compat code.
+  Add readahead support to libdevmapper and dmsetup.
+  Fix double free in a libdevmapper-event error path.
+  Fix configure --with-dmeventd-path substitution.
+  Allow a DM_DEV_DIR environment variable to override /dev in dmsetup.
+  Create a libdevmapper.so.$LIB_VERSION symlink within the build tree.
+  Avoid static link failure with some SELinux libraries that require libpthread.
+  Remove obsolete dmfs code from tree and update INSTALL.
+
+Version 1.02.22 - 21st August 2007
+==================================
+  Fix inconsistent licence notices: executables are GPLv2; libraries LGPLv2.1.
+  Update to use autoconf 2.61, while still supporting 2.57.
+  Avoid repeated dm_task free on some dm_event_get_registered_device errors.
+  Introduce log_sys_* macros from LVM2.
+  Export dm_fclose and dm_create_dir; remove libdm-file.h.
+  Don't log EROFS mkdir failures in _create_dir_recursive (for LVM2).
+  Add fclose wrapper dm_fclose that catches write failures (using ferror).
+
+Version 1.02.21 - 13th July 2007
+================================
+  Introduce _LOG_STDERR to send log_warn() messages to stderr not stdout.
+  Fix dmsetup -o devno string termination. (1.02.20)
+
+Version 1.02.20 - 15th June 2007
+================================
+  Fix default dmsetup report buffering and add --unbuffered.
+  Add tree-based and dependency fields to dmsetup reports.
+
+Version 1.02.19 - 27th April 2007
+=================================
+  Standardise protective include file #defines.
+  Add regex functions to library.
+  Avoid trailing separator in reports when there are hidden sort fields.
+  Fix segfault in 'dmsetup status' without --showkeys against crypt target.
+  Deal with some more compiler warnings.
+  Introduce _add_field() and _is_same_field() to libdm-report.c.
+  Fix some libdevmapper-event and dmeventd memory leaks.
+  Remove unnecessary memset() return value checks.
+  Fix a few leaks in reporting error paths. [1.02.15+]
+
+Version 1.02.18 - 13th February 2007
+====================================
+  Improve dmeventd messaging protocol: drain pipe and tag messages.
+
+Version 1.02.17 - 29th January 2007
+===================================
+  Add recent reporting options to dmsetup man page.
+  Revise some report fields names.
+  Add dmsetup 'help' command and update usage text.
+  Use fixed-size fields in report interface and reorder.
+
+Version 1.02.16 - 25th January 2007
+===================================
+  Add some missing close() and fclose() return value checks.
+  Migrate dmsetup column-based output over to new libdevmapper report framework.
+  Add descriptions to reporting field definitions.
+  Add a dso-private variable to dmeventd dso interface.
+  Add dm_event_handler_[gs]et_timeout functions.
+  Streamline dm_report_field_* interface.
+  Add cmdline debug & version options to dmeventd.
+  Add DM_LIB_VERSION definition to configure.h.
+  Suppress 'Unrecognised field' error if report field is 'help'.
+  Add --separator and --sort to dmsetup (unused).
+  Make alignment flag optional when specifying report fields.
+
+Version 1.02.15 - 17th January 2007
+===================================
+  Add basic reporting functions to libdevmapper.
+  Fix a malloc error path in dmsetup message.
+  More libdevmapper-event interface changes and fixes.
+  Rename dm_saprintf() to dm_asprintf().
+  Report error if NULL pointer is supplied to dm_strdup_aux().
+  Reinstate dm_event_get_registered_device.
+
+Version 1.02.14 - 11th January 2007
+===================================
+  Add dm_saprintf().
+  Use CFLAGS when linking so mixed sparc builds can supply -m64.
+  Add dm_tree_use_no_flush_suspend().
+  Lots of dmevent changes including revised interface.
+  Export dm_basename().
+  Cope with a trailing space when comparing tables prior to possible reload.
+  Fix dmeventd to cope if monitored device disappears.
+
+Version 1.02.13 - 28 Nov 2006
+=============================
+  Update dmsetup man page (setgeometry & message).
+  Fix dmsetup free after getline with debug.
+  Suppress encryption key in 'dmsetup table' output unless --showkeys supplied.
+
+Version 1.02.12 - 13 Oct 2006
+=============================
+  Avoid deptree attempting to suspend a device that's already suspended.
+
+Version 1.02.11 -  12 Oct 2006
+==============================
+  Add suspend noflush support.
+  Add basic dmsetup loop support.
+  Switch dmsetup to use dm_malloc and dm_free.
+
+Version 1.02.10 - 19 Sep 2006
+=============================
+  Add dm_snprintf(), dm_split_words() and dm_split_lvm_name() to libdevmapper.
+  Reorder mm bounds_check code to reduce window for a dmeventd race.
+
+Version 1.02.09 - 15 Aug 2006
+=============================
+  Add --table argument to dmsetup for a one-line table.
+  Abort if errors are found during cmdline option processing.
+  Add lockfs indicator to debug output.
+
+Version 1.02.08 - 17 July 2006
+==============================
+  Append full patch to check in emails.
+  Avoid duplicate dmeventd subdir with 'make distclean'.
+  Update dmsetup man page.
+  Add --force to dmsetup remove* to load error target.
+  dmsetup remove_all also performs mknodes.
+  Don't suppress identical table reloads if permission changes.
+  Fix corelog segment line.
+  Suppress some compiler warnings.
+
+Version 1.02.07 - 11 May 2006
+=============================
+  Add DM_CORELOG flag to dm_tree_node_add_mirror_target().
+  Avoid a dmeventd compiler warning.
+
+Version 1.02.06 - 10 May 2006
+=============================
+  Move DEFS into configure.h.
+  Fix leaks in error paths found by coverity.
+  Remove dmsetup line buffer limitation.
+
+Version 1.02.05 - 19 Apr 2006
+=============================
+  Separate install_include target in makefiles.
+  Separate out DEFS from CFLAGS.
+  Support pkg-config.
+  Check for libsepol.
+
+Version 1.02.04 - 14 Apr 2006
+=============================
+  Bring dmsetup man page up-to-date.
+  Use name-based device refs if kernel doesn't support device number refs.
+  Fix memory leak (struct dm_ioctl) when struct dm_task is reused.
+  If _create_and_load_v4 fails part way through, revert the creation.
+  dmeventd thread/fifo fixes.
+  Add file & line to dm_strdup_aux().
+  Add setgeometry.
+
+Version 1.02.03 - 7 Feb 2006
+============================
+  Add exported functions to set uid, gid and mode.
+  Rename _log to dm_log and export.
+  Add dm_tree_skip_lockfs.
+  Fix dm_strdup debug definition.
+  Fix hash function to avoid using a negative array offset.
+  Don't inline _find in hash.c and tidy signed/unsigned etc.
+  Fix libdevmapper.h #endif.
+  Fix dmsetup version driver version.
+  Add sync, nosync and block_on_error mirror log parameters.
+  Add hweight32.
+  Fix dmeventd build.
+
+Version 1.02.02 - 2 Dec 2005
+============================
+  dmeventd added.
+  Export dm_task_update_nodes.
+  Use names instead of numbers in messages when ioctls fail.
+
+Version 1.02.01 - 23 Nov 2005
+=============================
+  Resume snapshot-origins last.
+  Drop leading zeros from dm_format_dev.
+  Suppress attempt to reload identical table.
+  Additional LVM- prefix matching for transitional period.
+
+Version 1.02.00 - 10 Nov 2005
+=============================
+  Added activation functions to library.
+  Added return macros.
+  Also suppress error if device doesn't exist with DM_DEVICE_STATUS.
+  Export dm_set_selinux_context().
+  Add dm_driver_version().
+  Added dependency tree functions to library.
+  Added hash, bitset, pool, dbg_malloc to library.
+  Added ls --tree to dmsetup.
+  Added dmsetup --nolockfs support for suspend/reload.
+
+Version 1.01.05 - 26 Sep 2005
+=============================
+  Resync list.h with LVM2.
+  Remember increased buffer size and use for subsequent calls.
+  On 'buffer full' condition, double buffer size and repeat ioctl.
+  Fix termination of getopt_long() option array.
+  Report 'buffer full' condition with v4 ioctl as well as with v1.
+
+Version 1.01.04 - 2 Aug 2005
+============================
+  Fix dmsetup ls -j and status --target with empty table.
+
+Version 1.01.03 - 13 Jun 2005
+=============================
+  Use matchpathcon mode parameter.
+  Fix configure script to re-enable selinux.
+
+Version 1.01.02 - 17 May 2005
+=============================
+  Call dm_lib_exit() and dm_lib_release() automatically now.
+  Add --target <target_type> filter to dmsetup table/status/ls.
+  Add --exec <command> to dmsetup ls.
+  Fix dmsetup getopt_long usage.
+
+Version 1.01.01 - 29 Mar 2005
+=============================
+  Update dmsetup man page.
+  Drop-in devmap_name replacement.
+  Add option to compile without ioctl for testing.
+  Fix DM_LIB_VERSION sed.
+
+Version 1.01.00 - 17 Jan 2005
+=============================
+  Add dm_task_no_open_count() to skip getting open_count.
+
+Version 1.00.21 - 7 Jan 2005
+============================
+  Fix /proc/devices parsing.
+
+Version 1.00.20 - 6 Jan 2005
+============================
+  Attempt to fix /dev/mapper/control transparently if it's wrong.
+  Configuration-time option for setting uid/gid/mode for /dev/mapper nodes.
+  Update kernel patches for 2.4.27/2.4.28-pre-4 (includes minor fixes).
+  Add --noheadings columns option for colon-separated dmsetup output.
+  Support device referencing by uuid or major/minor.
+  Warn if kernel data didn't fit in buffer.
+  Fix a printf.
+
+Version 1.00.19 - 3 July 2004
+=============================
+  More autoconf fixes.
+  Fix a dmsetup newline.
+  Fix device number handling for 2.6 kernels.
+
+Version 1.00.18 - 20 Jun 2004
+=============================
+  Fix a uuid free in libdm-iface.
+  Fix a targets string size calc in driver.
+  Add -c to dmsetup for column-based output.
+  Add target message-passing ioctl.
+
+Version 1.00.17 - 17 Apr 2004
+=============================
+  configure --with-owner= --with-group= to avoid -o and -g args to 'install'
+  Fix library selinux linking.
+
+Version 1.00.16 - 16 Apr 2004
+=============================
+  Ignore error setting selinux file context if fs doesn't support it.
+
+Version 1.00.15 - 7 Apr 2004
+============================
+  Fix status overflow check in kernel patches.
+
+Version 1.00.14 - 6 Apr 2004
+============================
+  Fix static selinux build.
+
+Version 1.00.13 - 6 Apr 2004
+============================
+  Add some basic selinux support.
+
+Version 1.00.12 - 6 Apr 2004
+============================
+  Fix dmsetup.static install.
+
+Version 1.00.11 - 5 Apr 2004
+============================
+  configure --enable-static_link does static build in addition to dynamic.
+  Moved Makefile library targets definition into template.
+
+Version 1.00.10 - 2 Apr 2004
+============================
+  Fix DESTDIR handling.
+  Static build installs to dmsetup.static.
+  Basic support for internationalisation.
+  Minor Makefile tidy-ups/fixes.
+
+Version 1.00.09 - 31 Mar 2004
+=============================
+  Update copyright notices to Red Hat.
+  Move full mknodes functionality from dmsetup into libdevmapper.
+  Avoid sscanf %as for uClibc compatibility.
+  Cope if DM_LIST_VERSIONS is not defined.
+  Add DM_LIST_VERSIONS functionality to kernel patches.
+  Generate new kernel patches for 2.4.26-rc1.
+
+Version 1.00.08 - 27 Feb 2004
+=============================
+  Added 'dmsetup targets'.
+  Added event_nr support to 'dmsetup wait'.
+  Updated dmsetup man page.
+  Allow logging function to be reset to use internal one.
+  Bring log macros in line with LVM2 ones.
+  Added 'make install_static_lib' which installs libdevmapper.a.
+  Made configure/makefiles closer to LVM2 versions.
+  Fixed DESTDIR for make install/install_static_lib.
+  Updated README/INSTALL to reflect move to sources.redhat.com.
+  Updated autoconf files to 2003-06-17.
Index: src/external/gpl2/lvm2tools/dist/configure
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/configure
diff -N src/external/gpl2/lvm2tools/dist/configure
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/configure	12 Dec 2008 16:32:57 -0000	1.1.1.1.2.1
@@ -0,0 +1,12974 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.61.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+  if (eval ":") 2>/dev/null; then
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+
+  if test $as_have_required = yes && 	 (eval ":
+(as_func_return () {
+  (exit \$1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+  as_lineno_1=\$LINENO
+  as_lineno_2=\$LINENO
+  test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+  test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+  :
+else
+  as_candidate_shells=
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  case $as_dir in
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+	   done;;
+       esac
+done
+IFS=$as_save_IFS
+
+
+      for as_shell in $as_candidate_shells $SHELL; do
+	 # Try only shells that exist, to save several forks.
+	 if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		{ ("$as_shell") 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+_ASEOF
+}; then
+  CONFIG_SHELL=$as_shell
+	       as_have_required=yes
+	       if { "$as_shell" 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+(as_func_return () {
+  (exit $1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+  break
+fi
+
+fi
+
+      done
+
+      if test "x$CONFIG_SHELL" != x; then
+  for as_var in BASH_ENV ENV
+        do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+        done
+        export CONFIG_SHELL
+        exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+    if test $as_have_required = no; then
+  echo This script requires a shell more modern than all the
+      echo shells that I found on your system.  Please install a
+      echo modern shell, or manually run the script under such a
+      echo shell if you do have one.
+      { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+  (exit \$1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+  echo No shell found that supports shell functions.
+  echo Please tell autoconf@gnu.org about your system,
+  echo including any error possibly output before this
+  echo message
+}
+
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line after each line using $LINENO; the second 'sed'
+  # does the real work.  The second script uses 'N' to pair each
+  # line-number line with the line containing $LINENO, and appends
+  # trailing '-' during substitution so that $LINENO is not a special
+  # case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # scripts with optimization help from Paolo Bonzini.  Blame Lee
+  # E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+  case `echo 'x\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  *)   ECHO_C='\c';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s='ln -s'
+  # ... but there are two gotchas:
+  # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+  # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+  # In both cases, we have to default to `cp -p'.
+  ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+    as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+        test -d "$1/.";
+      else
+	case $1 in
+        -*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="lib/device/dev-cache.h"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_default_prefix=/usr
+ac_subst_vars='SHELL
+PATH_SEPARATOR
+PACKAGE_NAME
+PACKAGE_TARNAME
+PACKAGE_VERSION
+PACKAGE_STRING
+PACKAGE_BUGREPORT
+exec_prefix
+prefix
+program_transform_name
+bindir
+sbindir
+libexecdir
+datarootdir
+datadir
+sysconfdir
+sharedstatedir
+localstatedir
+includedir
+oldincludedir
+docdir
+infodir
+htmldir
+dvidir
+pdfdir
+psdir
+libdir
+localedir
+mandir
+DEFS
+ECHO_C
+ECHO_N
+ECHO_T
+LIBS
+build_alias
+host_alias
+target_alias
+build
+build_cpu
+build_vendor
+build_os
+host
+host_cpu
+host_vendor
+host_os
+target
+target_cpu
+target_vendor
+target_os
+SED
+AWK
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+ac_ct_CC
+EXEEXT
+OBJEXT
+CPP
+GREP
+EGREP
+INSTALL_PROGRAM
+INSTALL_SCRIPT
+INSTALL_DATA
+LN_S
+SET_MAKE
+RANLIB
+CFLOW_CMD
+CSCOPE_CMD
+ALLOCA
+LIBOBJS
+POW_LIB
+LCOV
+GENHTML
+LVM2CMD_LIB
+MSGFMT
+MODPROBE_CMD
+BUILD_DMEVENTD
+CLDFLAGS
+CLDNOWHOLEARCHIVE
+CLDWHOLEARCHIVE
+CLUSTER
+CLVMD
+CMDLIB
+COPTIMISE_FLAG
+DEBUG
+DEVMAPPER
+DMEVENTD
+DM_COMPAT
+DM_DEVICE_GID
+DM_DEVICE_MODE
+DM_DEVICE_UID
+DM_IOCTLS
+DM_LIB_VERSION
+DM_LIB_PATCHLEVEL
+FSADM
+GROUP
+HAVE_LIBDL
+HAVE_REALTIME
+HAVE_SELINUX
+INTL
+INTL_PACKAGE
+JOBS
+LDDEPS
+LIB_SUFFIX
+LOCALEDIR
+LVM1
+LVM1_FALLBACK
+CONFDIR
+LVM_VERSION
+MIRRORS
+OWNER
+PKGCONFIG
+POOL
+SNAPSHOTS
+STATICDIR
+STATIC_LINK
+LIB_PTHREAD
+interface
+kerneldir
+missingkernel
+kernelvsn
+tmpdir
+usrlibdir
+usrsbindir
+LTLIBOBJS'
+ac_subst_files=''
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=*)	ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *)	ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+    eval enable_$ac_feature=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+    eval enable_$ac_feature=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+    eval with_$ac_package=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+    eval with_$ac_package=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute directory names.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; }
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  { echo "$as_me: error: Working directory cannot be determined" >&2
+   { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  { echo "$as_me: error: pwd does not report name of working directory" >&2
+   { (exit 1); exit 1; }; }
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$0" ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$0" : 'X\(//\)[^/]' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$0" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
+   { (exit 1); exit 1; }; }
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+			  [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+			  [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR           user executables [EPREFIX/bin]
+  --sbindir=DIR          system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR       program executables [EPREFIX/libexec]
+  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
+  --libdir=DIR           object code libraries [EPREFIX/lib]
+  --includedir=DIR       C header files [PREFIX/include]
+  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
+  --datarootdir=DIR      read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR          read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR          info documentation [DATAROOTDIR/info]
+  --localedir=DIR        locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR           man documentation [DATAROOTDIR/man]
+  --docdir=DIR           documentation root [DATAROOTDIR/doc/PACKAGE]
+  --htmldir=DIR          html documentation [DOCDIR]
+  --dvidir=DIR           dvi documentation [DOCDIR]
+  --pdfdir=DIR           pdf documentation [DOCDIR]
+  --psdir=DIR            ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+  --target=TARGET   configure for building compilers for TARGET [HOST]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-lvm1_fallback  Use this to fall back and use LVM1 binaries if
+                          device-mapper is missing from the kernel
+  --disable-readline      Disable readline support
+  --disable-realtime      Disable realtime clock support
+  --enable-debug          Enable debugging
+  --enable-profiling      Gather gcov profiling data
+  --disable-devmapper     Disable LVM2 device-mapper interaction
+  --enable-compat         Enable support for old device-mapper versions
+  --disable-driver        Disable calls to device-mapper in the kernel
+  --disable-o_direct      Disable O_DIRECT
+  --enable-cmdlib         Build shared command library
+  --enable-pkgconfig      Install pkgconfig support
+  --enable-fsadm          Enable fsadm
+  --enable-dmeventd       Enable the device-mapper event daemon
+  --enable-static_link    Use this to link the tools to their libraries
+                          statically.  Default is dynamic linking
+  --disable-selinux       Disable selinux support
+  --enable-nls            Enable Native Language Support
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-user=USER        Set the owner of installed files [USER=root]
+  --with-group=GROUP      Set the group owner of installed files [GROUP=root]
+  --with-device-uid=UID   Set the owner used for new device nodes [UID=0]
+  --with-device-gid=UID   Set the group used for new device nodes [GID=0]
+  --with-device-mode=MODE Set the mode used for new device nodes [MODE=0600]
+  --with-lvm1=TYPE        LVM1 metadata support: internal/shared/none
+                          TYPE=internal
+  --with-pool=TYPE        GFS pool read-only support: internal/shared/none
+                          TYPE=internal
+  --with-cluster=TYPE     Cluster LVM locking support: internal/shared/none
+                          TYPE=internal
+  --with-snapshots=TYPE   Snapshot support: internal/shared/none
+                          TYPE=internal
+  --with-mirrors=TYPE     Mirror support: internal/shared/none
+                          TYPE=internal
+  --with-clvmd=TYPE       Build cluster LVM Daemon: cman/gulm/none/all
+                          TYPE=none
+  --with-optimisation=OPT C optimisation flag [OPT=-O2]
+  --with-localedir=DIR    Translation files in DIR [PREFIX/share/locale]
+  --with-confdir=DIR      Configuration files in DIR /etc
+  --with-staticdir=DIR    Static binary in DIR EXEC_PREFIX/sbin
+  --with-usrlibdir=DIR
+  --with-usrsbindir=DIR
+  --with-dmeventd-pidfile=PATH    dmeventd pidfile [/var/run/dmeventd.pid]
+  --with-dmeventd-path=PATH       dmeventd path [${exec_prefix}/sbin/dmeventd]
+  --with-interface=IFACE  Choose kernel interface (ioctl) [ioctl]
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" || continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.61
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.61.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  echo "PATH: $as_dir"
+done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    2)
+      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      ac_configure_args="$ac_configure_args '$ac_arg'"
+      ;;
+    esac
+  done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      *) $as_unset $ac_var ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      echo "$as_me: caught signal $ac_signal"
+    echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -n "$CONFIG_SITE"; then
+  set x "$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+  set x "$prefix/share/config.site" "$prefix/etc/config.site"
+else
+  set x "$ac_default_prefix/share/config.site" \
+	"$ac_default_prefix/etc/config.site"
+fi
+shift
+for ac_site_file
+do
+  if test -r "$ac_site_file"; then
+    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	{ echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	{ echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
+echo "$as_me:   former value:  $ac_old_val" >&2;}
+	{ echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
+echo "$as_me:   current value: $ac_new_val" >&2;}
+	ac_cache_corrupted=:
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+ac_config_headers="$ac_config_headers lib/misc/configure.h"
+
+
+################################################################################
+ac_aux_dir=
+for ac_dir in autoconf "$srcdir"/autoconf; do
+  if test -f "$ac_dir/install-sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f "$ac_dir/install.sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f "$ac_dir/shtool"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in autoconf \"$srcdir\"/autoconf" >&5
+echo "$as_me: error: cannot find install-sh or install.sh in autoconf \"$srcdir\"/autoconf" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+
+################################################################################
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5
+echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;}
+   { (exit 1); exit 1; }; }
+
+{ echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6; }
+if test "${ac_cv_build+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+   { (exit 1); exit 1; }; }
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5
+echo "$as_me: error: invalid value of canonical build" >&2;}
+   { (exit 1); exit 1; }; };;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6; }
+if test "${ac_cv_host+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5
+echo "$as_me: error: invalid value of canonical host" >&2;}
+   { (exit 1); exit 1; }; };;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+{ echo "$as_me:$LINENO: checking target system type" >&5
+echo $ECHO_N "checking target system type... $ECHO_C" >&6; }
+if test "${ac_cv_target+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "x$target_alias" = x; then
+  ac_cv_target=$ac_cv_host
+else
+  ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
+    { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_target" >&5
+echo "${ECHO_T}$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical target" >&5
+echo "$as_me: error: invalid value of canonical target" >&2;}
+   { (exit 1); exit 1; }; };;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+  test "$program_prefix$program_suffix$program_transform_name" = \
+    NONENONEs,x,x, &&
+  program_prefix=${target_alias}-
+
+case "$host_os" in
+	linux*)
+		COPTIMISE_FLAG="-O2"
+		CLDFLAGS="$CLDFLAGS -Wl,--version-script,.export.sym"
+		CLDWHOLEARCHIVE="-Wl,-whole-archive"
+		CLDNOWHOLEARCHIVE="-Wl,-no-whole-archive"
+		LDDEPS="$LDDEPS .export.sym"
+		LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
+		LIB_SUFFIX=so
+		DEVMAPPER=yes
+		ODIRECT=yes
+		DM_IOCTLS=yes
+		SELINUX=yes
+		REALTIME=yes
+		CLUSTER=internal
+		FSADM=yes
+		;;
+	darwin*)
+		CFLAGS="$CFLAGS -no-cpp-precomp -fno-common"
+		COPTIMISE_FLAG="-O2"
+		CLDFLAGS="$CLDFLAGS"
+		CLDWHOLEARCHIVE="-all_load"
+		CLDNOWHOLEARCHIVE=
+		LIB_SUFFIX=dylib
+		DEVMAPPER=yes
+		ODIRECT=no
+		DM_IOCTLS=no
+		SELINUX=no
+		REALTIME=no
+		CLUSTER=none
+		FSADM=no
+		;;
+esac
+
+################################################################################
+{ echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5
+echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6; }
+if test "${ac_cv_path_SED+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+            ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+     for ac_i in 1 2 3 4 5 6 7; do
+       ac_script="$ac_script$as_nl$ac_script"
+     done
+     echo "$ac_script" | sed 99q >conftest.sed
+     $as_unset ac_script || ac_script=
+     # Extract the first word of "sed gsed" to use in msg output
+if test -z "$SED"; then
+set dummy sed gsed; ac_prog_name=$2
+if test "${ac_cv_path_SED+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_path_SED_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in sed gsed; do
+  for ac_exec_ext in '' $ac_executable_extensions; do
+    ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
+    { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue
+    # Check for GNU ac_path_SED and select it if it is found.
+  # Check for GNU $ac_path_SED
+case `"$ac_path_SED" --version 2>&1` in
+*GNU*)
+  ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
+*)
+  ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    echo '' >> "conftest.nl"
+    "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_SED_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_SED="$ac_path_SED"
+      ac_path_SED_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+    $ac_path_SED_found && break 3
+  done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+SED="$ac_cv_path_SED"
+if test -z "$SED"; then
+  { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in \$PATH" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in \$PATH" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+else
+  ac_cv_path_SED=$SED
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_SED" >&5
+echo "${ECHO_T}$ac_cv_path_SED" >&6; }
+ SED="$ac_cv_path_SED"
+  rm -f conftest.sed
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_AWK+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AWK="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  { echo "$as_me:$LINENO: result: $AWK" >&5
+echo "${ECHO_T}$AWK" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$AWK" && break
+done
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler --version >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -v >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -V >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; }
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+#
+# List of possible output files, starting from the most likely.
+# The algorithm is not robust to junk in `.', hence go to wildcards (a.*)
+# only as a last resort.  b.out is created by i960 compilers.
+ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out'
+#
+# The IRIX 6 linker writes into existing files which may not be
+# executable, retaining their permissions.  Remove them first so a
+# subsequent execution test works.
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { (ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj )
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+        if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	then :; else
+	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	fi
+	# We set ac_cv_exeext here because the later test for it is not
+	# safe: cross compilers may not add the suffix if given an `-o'
+	# argument, so we may need to know it at that point already.
+	# Even if this section looks crufty: it has the advantage of
+	# actually working.
+	break;;
+    * )
+	break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+
+{ echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6; }
+if test -z "$ac_file"; then
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; }
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  fi
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6; }
+
+{ echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; }
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; }
+if test "${ac_cv_objext+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	CFLAGS=""
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_c89=$ac_arg
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+  xno)
+    { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
+echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # Extract the first word of "grep ggrep" to use in msg output
+if test -z "$GREP"; then
+set dummy grep ggrep; ac_prog_name=$2
+if test "${ac_cv_path_GREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_path_GREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in grep ggrep; do
+  for ac_exec_ext in '' $ac_executable_extensions; do
+    ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+    { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+    # Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+    $ac_path_GREP_found && break 3
+  done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+GREP="$ac_cv_path_GREP"
+if test -z "$GREP"; then
+  { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
+echo "${ECHO_T}$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     # Extract the first word of "egrep" to use in msg output
+if test -z "$EGREP"; then
+set dummy egrep; ac_prog_name=$2
+if test "${ac_cv_path_EGREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_path_EGREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in egrep; do
+  for ac_exec_ext in '' $ac_executable_extensions; do
+    ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+    { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+    # Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+    $ac_path_EGREP_found && break 3
+  done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+EGREP="$ac_cv_path_EGREP"
+if test -z "$EGREP"; then
+  { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+
+   fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
+echo "${ECHO_T}$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+if test $ac_cv_c_compiler_gnu = yes; then
+    { echo "$as_me:$LINENO: checking whether $CC needs -traditional" >&5
+echo $ECHO_N "checking whether $CC needs -traditional... $ECHO_C" >&6; }
+if test "${ac_cv_prog_gcc_traditional+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+    ac_pattern="Autoconf.*'x'"
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sgtty.h>
+Autoconf TIOCGETP
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "$ac_pattern" >/dev/null 2>&1; then
+  ac_cv_prog_gcc_traditional=yes
+else
+  ac_cv_prog_gcc_traditional=no
+fi
+rm -f conftest*
+
+
+  if test $ac_cv_prog_gcc_traditional = no; then
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <termio.h>
+Autoconf TCGETA
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "$ac_pattern" >/dev/null 2>&1; then
+  ac_cv_prog_gcc_traditional=yes
+fi
+rm -f conftest*
+
+  fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_gcc_traditional" >&5
+echo "${ECHO_T}$ac_cv_prog_gcc_traditional" >&6; }
+  if test $ac_cv_prog_gcc_traditional = yes; then
+    CC="$CC -traditional"
+  fi
+fi
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+	if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+	  if test $ac_prog = install &&
+	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+	    break 3
+	  fi
+	fi
+      done
+    done
+    ;;
+esac
+done
+IFS=$as_save_IFS
+
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ echo "$as_me:$LINENO: checking whether ln -s works" >&5
+echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no, using $LN_S" >&5
+echo "${ECHO_T}no, using $LN_S" >&6; }
+fi
+
+{ echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; }
+set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+	@echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+  SET_MAKE=
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+{ echo "$as_me:$LINENO: checking for a thread-safe mkdir -p" >&5
+echo $ECHO_N "checking for a thread-safe mkdir -p... $ECHO_C" >&6; }
+if test -z "$MKDIR_P"; then
+  if test "${ac_cv_path_mkdir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in mkdir gmkdir; do
+	 for ac_exec_ext in '' $ac_executable_extensions; do
+	   { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
+	   case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+	     'mkdir (GNU coreutils) '* | \
+	     'mkdir (coreutils) '* | \
+	     'mkdir (fileutils) '4.1*)
+	       ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+	       break 3;;
+	   esac
+	 done
+       done
+done
+IFS=$as_save_IFS
+
+fi
+
+  if test "${ac_cv_path_mkdir+set}" = set; then
+    MKDIR_P="$ac_cv_path_mkdir -p"
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for MKDIR_P within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    test -d ./--version && rmdir ./--version
+    MKDIR_P="$ac_install_sh -d"
+  fi
+fi
+{ echo "$as_me:$LINENO: result: $MKDIR_P" >&5
+echo "${ECHO_T}$MKDIR_P" >&6; }
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+# Extract the first word of "cflow", so it can be a program name with args.
+set dummy cflow; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_CFLOW_CMD+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $CFLOW_CMD in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_CFLOW_CMD="$CFLOW_CMD" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_CFLOW_CMD="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+CFLOW_CMD=$ac_cv_path_CFLOW_CMD
+if test -n "$CFLOW_CMD"; then
+  { echo "$as_me:$LINENO: result: $CFLOW_CMD" >&5
+echo "${ECHO_T}$CFLOW_CMD" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+# Extract the first word of "cscope", so it can be a program name with args.
+set dummy cscope; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_CSCOPE_CMD+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $CSCOPE_CMD in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_CSCOPE_CMD="$CSCOPE_CMD" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_CSCOPE_CMD="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+CSCOPE_CMD=$ac_cv_path_CSCOPE_CMD
+if test -n "$CSCOPE_CMD"; then
+  { echo "$as_me:$LINENO: result: $CSCOPE_CMD" >&5
+echo "${ECHO_T}$CSCOPE_CMD" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+
+################################################################################
+
+
+
+
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do
+  as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5
+echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <$ac_hdr>
+
+int
+main ()
+{
+if ((DIR *) 0)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1
+_ACEOF
+
+ac_header_dirent=$ac_hdr; break
+fi
+
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+  { echo "$as_me:$LINENO: checking for library containing opendir" >&5
+echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; }
+if test "${ac_cv_search_opendir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char opendir ();
+int
+main ()
+{
+return opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' dir; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_search_opendir=$ac_res
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext
+  if test "${ac_cv_search_opendir+set}" = set; then
+  break
+fi
+done
+if test "${ac_cv_search_opendir+set}" = set; then
+  :
+else
+  ac_cv_search_opendir=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
+echo "${ECHO_T}$ac_cv_search_opendir" >&6; }
+ac_res=$ac_cv_search_opendir
+if test "$ac_res" != no; then
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+else
+  { echo "$as_me:$LINENO: checking for library containing opendir" >&5
+echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; }
+if test "${ac_cv_search_opendir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char opendir ();
+int
+main ()
+{
+return opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' x; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_search_opendir=$ac_res
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext
+  if test "${ac_cv_search_opendir+set}" = set; then
+  break
+fi
+done
+if test "${ac_cv_search_opendir+set}" = set; then
+  :
+else
+  ac_cv_search_opendir=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
+echo "${ECHO_T}$ac_cv_search_opendir" >&6; }
+ac_res=$ac_cv_search_opendir
+if test "$ac_res" != no; then
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+fi
+
+{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_header_stdc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for sys/wait.h that is POSIX.1 compatible" >&5
+echo $ECHO_N "checking for sys/wait.h that is POSIX.1 compatible... $ECHO_C" >&6; }
+if test "${ac_cv_header_sys_wait_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/wait.h>
+#ifndef WEXITSTATUS
+# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
+
+int
+main ()
+{
+  int s;
+  wait (&s);
+  s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_header_sys_wait_h=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_header_sys_wait_h=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5
+echo "${ECHO_T}$ac_cv_header_sys_wait_h" >&6; }
+if test $ac_cv_header_sys_wait_h = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_SYS_WAIT_H 1
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5
+echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6; }
+if test "${ac_cv_header_time+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+
+int
+main ()
+{
+if ((struct tm *) 0)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_header_time=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_header_time=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5
+echo "${ECHO_T}$ac_cv_header_time" >&6; }
+if test $ac_cv_header_time = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TIME_WITH_SYS_TIME 1
+_ACEOF
+
+fi
+
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+		  inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_header in locale.h stddef.h syslog.h sys/file.h sys/time.h assert.h \
+  libgen.h signal.h sys/mman.h sys/resource.h sys/utsname.h sys/wait.h time.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  { { echo "$as_me:$LINENO: error: bailing out" >&5
+echo "$as_me: error: bailing out" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+done
+
+
+case "$host_os" in
+	linux*)
+
+
+
+for ac_header in asm/byteorder.h linux/fs.h malloc.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  { { echo "$as_me:$LINENO: error: bailing out" >&5
+echo "$as_me: error: bailing out" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+done
+ ;;
+	darwin*)
+
+
+for ac_header in machine/endian.h sys/disk.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  { { echo "$as_me:$LINENO: error: bailing out" >&5
+echo "$as_me: error: bailing out" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+done
+ ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_header in ctype.h dirent.h errno.h fcntl.h getopt.h inttypes.h limits.h \
+  stdarg.h stdio.h stdlib.h string.h sys/ioctl.h sys/param.h sys/stat.h \
+  sys/types.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  { { echo "$as_me:$LINENO: error: bailing out" >&5
+echo "$as_me: error: bailing out" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+done
+
+
+
+for ac_header in termios.h sys/statvfs.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+################################################################################
+{ echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
+echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6; }
+if test "${ac_cv_c_const+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+  /* Ultrix mips cc rejects this.  */
+  typedef int charset[2];
+  const charset cs;
+  /* SunOS 4.1.1 cc rejects this.  */
+  char const *const *pcpcc;
+  char **ppc;
+  /* NEC SVR4.0.2 mips cc rejects this.  */
+  struct point {int x, y;};
+  static struct point const zero = {0,0};
+  /* AIX XL C 1.02.0.0 rejects this.
+     It does not let you subtract one const X* pointer from another in
+     an arm of an if-expression whose if-part is not a constant
+     expression */
+  const char *g = "string";
+  pcpcc = &g + (g ? g-g : 0);
+  /* HPUX 7.0 cc rejects these. */
+  ++pcpcc;
+  ppc = (char**) pcpcc;
+  pcpcc = (char const *const *) ppc;
+  { /* SCO 3.2v4 cc rejects this.  */
+    char *t;
+    char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+    *t++ = 0;
+    if (s) return 0;
+  }
+  { /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
+    int x[] = {25, 17};
+    const int *foo = &x[0];
+    ++foo;
+  }
+  { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+    typedef const int *iptr;
+    iptr p = 0;
+    ++p;
+  }
+  { /* AIX XL C 1.02.0.0 rejects this saying
+       "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+    struct s { int j; const int *ap[3]; };
+    struct s *b; b->j = 5;
+  }
+  { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+    const int foo = 10;
+    if (!foo) return 0;
+  }
+  return !cs[0] && !zero.x;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_c_const=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_c_const=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+echo "${ECHO_T}$ac_cv_c_const" >&6; }
+if test $ac_cv_c_const = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define const
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for inline" >&5
+echo $ECHO_N "checking for inline... $ECHO_C" >&6; }
+if test "${ac_cv_c_inline+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_c_inline=$ac_kw
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  test "$ac_cv_c_inline" != no && break
+done
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5
+echo "${ECHO_T}$ac_cv_c_inline" >&6; }
+
+
+case $ac_cv_c_inline in
+  inline | yes) ;;
+  *)
+    case $ac_cv_c_inline in
+      no) ac_val=;;
+      *) ac_val=$ac_cv_c_inline;;
+    esac
+    cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+    ;;
+esac
+
+{ echo "$as_me:$LINENO: checking for struct stat.st_rdev" >&5
+echo $ECHO_N "checking for struct stat.st_rdev... $ECHO_C" >&6; }
+if test "${ac_cv_member_struct_stat_st_rdev+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static struct stat ac_aggr;
+if (ac_aggr.st_rdev)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_member_struct_stat_st_rdev=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static struct stat ac_aggr;
+if (sizeof ac_aggr.st_rdev)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_member_struct_stat_st_rdev=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_member_struct_stat_st_rdev=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_member_struct_stat_st_rdev" >&5
+echo "${ECHO_T}$ac_cv_member_struct_stat_st_rdev" >&6; }
+if test $ac_cv_member_struct_stat_st_rdev = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STAT_ST_RDEV 1
+_ACEOF
+
+
+fi
+
+{ echo "$as_me:$LINENO: checking for off_t" >&5
+echo $ECHO_N "checking for off_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_off_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef off_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_type_off_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_type_off_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_off_t" >&5
+echo "${ECHO_T}$ac_cv_type_off_t" >&6; }
+if test $ac_cv_type_off_t = yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define off_t long int
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for pid_t" >&5
+echo $ECHO_N "checking for pid_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_pid_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef pid_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_type_pid_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_type_pid_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_pid_t" >&5
+echo "${ECHO_T}$ac_cv_type_pid_t" >&6; }
+if test $ac_cv_type_pid_t = yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define pid_t int
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking return type of signal handlers" >&5
+echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6; }
+if test "${ac_cv_type_signal+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <signal.h>
+
+int
+main ()
+{
+return *(signal (0, 0)) (0) == 1;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_type_signal=int
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_type_signal=void
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_signal" >&5
+echo "${ECHO_T}$ac_cv_type_signal" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define RETSIGTYPE $ac_cv_type_signal
+_ACEOF
+
+
+{ echo "$as_me:$LINENO: checking for size_t" >&5
+echo $ECHO_N "checking for size_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_size_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef size_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_type_size_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_type_size_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5
+echo "${ECHO_T}$ac_cv_type_size_t" >&6; }
+if test $ac_cv_type_size_t = yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned int
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for mode_t" >&5
+echo $ECHO_N "checking for mode_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_mode_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef mode_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_type_mode_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_type_mode_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_mode_t" >&5
+echo "${ECHO_T}$ac_cv_type_mode_t" >&6; }
+if test $ac_cv_type_mode_t = yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define mode_t int
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for struct stat.st_rdev" >&5
+echo $ECHO_N "checking for struct stat.st_rdev... $ECHO_C" >&6; }
+if test "${ac_cv_member_struct_stat_st_rdev+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static struct stat ac_aggr;
+if (ac_aggr.st_rdev)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_member_struct_stat_st_rdev=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static struct stat ac_aggr;
+if (sizeof ac_aggr.st_rdev)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_member_struct_stat_st_rdev=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_member_struct_stat_st_rdev=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_member_struct_stat_st_rdev" >&5
+echo "${ECHO_T}$ac_cv_member_struct_stat_st_rdev" >&6; }
+if test $ac_cv_member_struct_stat_st_rdev = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STAT_ST_RDEV 1
+_ACEOF
+
+
+fi
+
+{ echo "$as_me:$LINENO: checking whether struct tm is in sys/time.h or time.h" >&5
+echo $ECHO_N "checking whether struct tm is in sys/time.h or time.h... $ECHO_C" >&6; }
+if test "${ac_cv_struct_tm+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <time.h>
+
+int
+main ()
+{
+struct tm tm;
+				     int *p = &tm.tm_sec;
+ 				     return !p;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_struct_tm=time.h
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_struct_tm=sys/time.h
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_struct_tm" >&5
+echo "${ECHO_T}$ac_cv_struct_tm" >&6; }
+if test $ac_cv_struct_tm = sys/time.h; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TM_IN_SYS_TIME 1
+_ACEOF
+
+fi
+
+
+################################################################################
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_func in gethostname getpagesize memset mkdir rmdir munmap setlocale \
+  strcasecmp strchr strdup strncasecmp strerror strrchr strstr strtol strtoul \
+  uname
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  { { echo "$as_me:$LINENO: error: bailing out" >&5
+echo "$as_me: error: bailing out" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+done
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments.  Useless!
+{ echo "$as_me:$LINENO: checking for working alloca.h" >&5
+echo $ECHO_N "checking for working alloca.h... $ECHO_C" >&6; }
+if test "${ac_cv_working_alloca_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <alloca.h>
+int
+main ()
+{
+char *p = (char *) alloca (2 * sizeof (int));
+			  if (p) return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_working_alloca_h=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_working_alloca_h=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_working_alloca_h" >&5
+echo "${ECHO_T}$ac_cv_working_alloca_h" >&6; }
+if test $ac_cv_working_alloca_h = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ALLOCA_H 1
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for alloca" >&5
+echo $ECHO_N "checking for alloca... $ECHO_C" >&6; }
+if test "${ac_cv_func_alloca_works+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+#  include <malloc.h>
+#  define alloca _alloca
+# else
+#  ifdef HAVE_ALLOCA_H
+#   include <alloca.h>
+#  else
+#   ifdef _AIX
+ #pragma alloca
+#   else
+#    ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+#    endif
+#   endif
+#  endif
+# endif
+#endif
+
+int
+main ()
+{
+char *p = (char *) alloca (1);
+				    if (p) return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_func_alloca_works=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_func_alloca_works=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_alloca_works" >&5
+echo "${ECHO_T}$ac_cv_func_alloca_works" >&6; }
+
+if test $ac_cv_func_alloca_works = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ALLOCA 1
+_ACEOF
+
+else
+  # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+# that cause trouble.  Some versions do not even contain alloca or
+# contain a buggy version.  If you still want to use their alloca,
+# use ar to extract alloca.o from them instead of compiling alloca.c.
+
+ALLOCA=\${LIBOBJDIR}alloca.$ac_objext
+
+cat >>confdefs.h <<\_ACEOF
+#define C_ALLOCA 1
+_ACEOF
+
+
+{ echo "$as_me:$LINENO: checking whether \`alloca.c' needs Cray hooks" >&5
+echo $ECHO_N "checking whether \`alloca.c' needs Cray hooks... $ECHO_C" >&6; }
+if test "${ac_cv_os_cray+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#if defined CRAY && ! defined CRAY2
+webecray
+#else
+wenotbecray
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "webecray" >/dev/null 2>&1; then
+  ac_cv_os_cray=yes
+else
+  ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_os_cray" >&5
+echo "${ECHO_T}$ac_cv_os_cray" >&6; }
+if test $ac_cv_os_cray = yes; then
+  for ac_func in _getb67 GETB67 getb67; do
+    as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define CRAY_STACKSEG_END $ac_func
+_ACEOF
+
+    break
+fi
+
+  done
+fi
+
+{ echo "$as_me:$LINENO: checking stack direction for C alloca" >&5
+echo $ECHO_N "checking stack direction for C alloca... $ECHO_C" >&6; }
+if test "${ac_cv_c_stack_direction+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_c_stack_direction=0
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+find_stack_direction ()
+{
+  static char *addr = 0;
+  auto char dummy;
+  if (addr == 0)
+    {
+      addr = &dummy;
+      return find_stack_direction ();
+    }
+  else
+    return (&dummy > addr) ? 1 : -1;
+}
+
+int
+main ()
+{
+  return find_stack_direction () < 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_stack_direction=1
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_c_stack_direction=-1
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_stack_direction" >&5
+echo "${ECHO_T}$ac_cv_c_stack_direction" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+_ACEOF
+
+
+fi
+
+{ echo "$as_me:$LINENO: checking whether closedir returns void" >&5
+echo $ECHO_N "checking whether closedir returns void... $ECHO_C" >&6; }
+if test "${ac_cv_func_closedir_void+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_closedir_void=yes
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header_dirent>
+#ifndef __cplusplus
+int closedir ();
+#endif
+
+int
+main ()
+{
+return closedir (opendir (".")) != 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_closedir_void=no
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_closedir_void=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_closedir_void" >&5
+echo "${ECHO_T}$ac_cv_func_closedir_void" >&6; }
+if test $ac_cv_func_closedir_void = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define CLOSEDIR_VOID 1
+_ACEOF
+
+fi
+
+
+for ac_header in vfork.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+for ac_func in fork vfork
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+if test "x$ac_cv_func_fork" = xyes; then
+  { echo "$as_me:$LINENO: checking for working fork" >&5
+echo $ECHO_N "checking for working fork... $ECHO_C" >&6; }
+if test "${ac_cv_func_fork_works+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_fork_works=cross
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+
+	  /* By Ruediger Kuhlmann. */
+	  return fork () < 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_fork_works=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_fork_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_fork_works" >&5
+echo "${ECHO_T}$ac_cv_func_fork_works" >&6; }
+
+else
+  ac_cv_func_fork_works=$ac_cv_func_fork
+fi
+if test "x$ac_cv_func_fork_works" = xcross; then
+  case $host in
+    *-*-amigaos* | *-*-msdosdjgpp*)
+      # Override, as these systems have only a dummy fork() stub
+      ac_cv_func_fork_works=no
+      ;;
+    *)
+      ac_cv_func_fork_works=yes
+      ;;
+  esac
+  { echo "$as_me:$LINENO: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5
+echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;}
+fi
+ac_cv_func_vfork_works=$ac_cv_func_vfork
+if test "x$ac_cv_func_vfork" = xyes; then
+  { echo "$as_me:$LINENO: checking for working vfork" >&5
+echo $ECHO_N "checking for working vfork... $ECHO_C" >&6; }
+if test "${ac_cv_func_vfork_works+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_vfork_works=cross
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Thanks to Paul Eggert for this test.  */
+$ac_includes_default
+#include <sys/wait.h>
+#ifdef HAVE_VFORK_H
+# include <vfork.h>
+#endif
+/* On some sparc systems, changes by the child to local and incoming
+   argument registers are propagated back to the parent.  The compiler
+   is told about this with #include <vfork.h>, but some compilers
+   (e.g. gcc -O) don't grok <vfork.h>.  Test for this by using a
+   static variable whose address is put into a register that is
+   clobbered by the vfork.  */
+static void
+#ifdef __cplusplus
+sparc_address_test (int arg)
+# else
+sparc_address_test (arg) int arg;
+#endif
+{
+  static pid_t child;
+  if (!child) {
+    child = vfork ();
+    if (child < 0) {
+      perror ("vfork");
+      _exit(2);
+    }
+    if (!child) {
+      arg = getpid();
+      write(-1, "", 0);
+      _exit (arg);
+    }
+  }
+}
+
+int
+main ()
+{
+  pid_t parent = getpid ();
+  pid_t child;
+
+  sparc_address_test (0);
+
+  child = vfork ();
+
+  if (child == 0) {
+    /* Here is another test for sparc vfork register problems.  This
+       test uses lots of local variables, at least as many local
+       variables as main has allocated so far including compiler
+       temporaries.  4 locals are enough for gcc 1.40.3 on a Solaris
+       4.1.3 sparc, but we use 8 to be safe.  A buggy compiler should
+       reuse the register of parent for one of the local variables,
+       since it will think that parent can't possibly be used any more
+       in this routine.  Assigning to the local variable will thus
+       munge parent in the parent process.  */
+    pid_t
+      p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(),
+      p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid();
+    /* Convince the compiler that p..p7 are live; otherwise, it might
+       use the same hardware register for all 8 local variables.  */
+    if (p != p1 || p != p2 || p != p3 || p != p4
+	|| p != p5 || p != p6 || p != p7)
+      _exit(1);
+
+    /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent
+       from child file descriptors.  If the child closes a descriptor
+       before it execs or exits, this munges the parent's descriptor
+       as well.  Test for this by closing stdout in the child.  */
+    _exit(close(fileno(stdout)) != 0);
+  } else {
+    int status;
+    struct stat st;
+
+    while (wait(&status) != child)
+      ;
+    return (
+	 /* Was there some problem with vforking?  */
+	 child < 0
+
+	 /* Did the child fail?  (This shouldn't happen.)  */
+	 || status
+
+	 /* Did the vfork/compiler bug occur?  */
+	 || parent != getpid()
+
+	 /* Did the file descriptor bug occur?  */
+	 || fstat(fileno(stdout), &st) != 0
+	 );
+  }
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_vfork_works=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_vfork_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_vfork_works" >&5
+echo "${ECHO_T}$ac_cv_func_vfork_works" >&6; }
+
+fi;
+if test "x$ac_cv_func_fork_works" = xcross; then
+  ac_cv_func_vfork_works=$ac_cv_func_vfork
+  { echo "$as_me:$LINENO: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5
+echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;}
+fi
+
+if test "x$ac_cv_func_vfork_works" = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_WORKING_VFORK 1
+_ACEOF
+
+else
+
+cat >>confdefs.h <<\_ACEOF
+#define vfork fork
+_ACEOF
+
+fi
+if test "x$ac_cv_func_fork_works" = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_WORKING_FORK 1
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking whether lstat dereferences a symlink specified with a trailing slash" >&5
+echo $ECHO_N "checking whether lstat dereferences a symlink specified with a trailing slash... $ECHO_C" >&6; }
+if test "${ac_cv_func_lstat_dereferences_slashed_symlink+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  rm -f conftest.sym conftest.file
+echo >conftest.file
+if test "$as_ln_s" = "ln -s" && ln -s conftest.file conftest.sym; then
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_lstat_dereferences_slashed_symlink=no
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+struct stat sbuf;
+     /* Linux will dereference the symlink and fail.
+	That is better in the sense that it means we will not
+	have to compile and use the lstat wrapper.  */
+     return lstat ("conftest.sym/", &sbuf) == 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_lstat_dereferences_slashed_symlink=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_lstat_dereferences_slashed_symlink=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+else
+  # If the `ln -s' command failed, then we probably don't even
+  # have an lstat function.
+  ac_cv_func_lstat_dereferences_slashed_symlink=no
+fi
+rm -f conftest.sym conftest.file
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_lstat_dereferences_slashed_symlink" >&5
+echo "${ECHO_T}$ac_cv_func_lstat_dereferences_slashed_symlink" >&6; }
+
+test $ac_cv_func_lstat_dereferences_slashed_symlink = yes &&
+
+cat >>confdefs.h <<_ACEOF
+#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1
+_ACEOF
+
+
+if test $ac_cv_func_lstat_dereferences_slashed_symlink = no; then
+  case " $LIBOBJS " in
+  *" lstat.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS lstat.$ac_objext"
+ ;;
+esac
+
+fi
+
+{ echo "$as_me:$LINENO: checking whether lstat accepts an empty string" >&5
+echo $ECHO_N "checking whether lstat accepts an empty string... $ECHO_C" >&6; }
+if test "${ac_cv_func_lstat_empty_string_bug+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_lstat_empty_string_bug=yes
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+struct stat sbuf;
+  return lstat ("", &sbuf) == 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_lstat_empty_string_bug=no
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_lstat_empty_string_bug=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_lstat_empty_string_bug" >&5
+echo "${ECHO_T}$ac_cv_func_lstat_empty_string_bug" >&6; }
+if test $ac_cv_func_lstat_empty_string_bug = yes; then
+  case " $LIBOBJS " in
+  *" lstat.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS lstat.$ac_objext"
+ ;;
+esac
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_LSTAT_EMPTY_STRING_BUG 1
+_ACEOF
+
+fi
+
+
+for ac_header in stdlib.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+{ echo "$as_me:$LINENO: checking for GNU libc compatible malloc" >&5
+echo $ECHO_N "checking for GNU libc compatible malloc... $ECHO_C" >&6; }
+if test "${ac_cv_func_malloc_0_nonnull+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_malloc_0_nonnull=no
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#if defined STDC_HEADERS || defined HAVE_STDLIB_H
+# include <stdlib.h>
+#else
+char *malloc ();
+#endif
+
+int
+main ()
+{
+return ! malloc (0);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_malloc_0_nonnull=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_malloc_0_nonnull=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_malloc_0_nonnull" >&5
+echo "${ECHO_T}$ac_cv_func_malloc_0_nonnull" >&6; }
+if test $ac_cv_func_malloc_0_nonnull = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_MALLOC 1
+_ACEOF
+
+else
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_MALLOC 0
+_ACEOF
+
+   case " $LIBOBJS " in
+  *" malloc.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS malloc.$ac_objext"
+ ;;
+esac
+
+
+cat >>confdefs.h <<\_ACEOF
+#define malloc rpl_malloc
+_ACEOF
+
+fi
+
+
+
+{ echo "$as_me:$LINENO: checking for working memcmp" >&5
+echo $ECHO_N "checking for working memcmp... $ECHO_C" >&6; }
+if test "${ac_cv_func_memcmp_working+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_memcmp_working=no
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+
+  /* Some versions of memcmp are not 8-bit clean.  */
+  char c0 = '\100', c1 = '\200', c2 = '\201';
+  if (memcmp(&c0, &c2, 1) >= 0 || memcmp(&c1, &c2, 1) >= 0)
+    return 1;
+
+  /* The Next x86 OpenStep bug shows up only when comparing 16 bytes
+     or more and with at least one buffer not starting on a 4-byte boundary.
+     William Lewis provided this test program.   */
+  {
+    char foo[21];
+    char bar[21];
+    int i;
+    for (i = 0; i < 4; i++)
+      {
+	char *a = foo + i;
+	char *b = bar + i;
+	strcpy (a, "--------01111111");
+	strcpy (b, "--------10000000");
+	if (memcmp (a, b, 16) >= 0)
+	  return 1;
+      }
+    return 0;
+  }
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_memcmp_working=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_memcmp_working=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_memcmp_working" >&5
+echo "${ECHO_T}$ac_cv_func_memcmp_working" >&6; }
+test $ac_cv_func_memcmp_working = no && case " $LIBOBJS " in
+  *" memcmp.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS memcmp.$ac_objext"
+ ;;
+esac
+
+
+
+
+for ac_header in stdlib.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_func in getpagesize
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+{ echo "$as_me:$LINENO: checking for working mmap" >&5
+echo $ECHO_N "checking for working mmap... $ECHO_C" >&6; }
+if test "${ac_cv_func_mmap_fixed_mapped+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_mmap_fixed_mapped=no
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+/* malloc might have been renamed as rpl_malloc. */
+#undef malloc
+
+/* Thanks to Mike Haertel and Jim Avera for this test.
+   Here is a matrix of mmap possibilities:
+	mmap private not fixed
+	mmap private fixed at somewhere currently unmapped
+	mmap private fixed at somewhere already mapped
+	mmap shared not fixed
+	mmap shared fixed at somewhere currently unmapped
+	mmap shared fixed at somewhere already mapped
+   For private mappings, we should verify that changes cannot be read()
+   back from the file, nor mmap's back from the file at a different
+   address.  (There have been systems where private was not correctly
+   implemented like the infamous i386 svr4.0, and systems where the
+   VM page cache was not coherent with the file system buffer cache
+   like early versions of FreeBSD and possibly contemporary NetBSD.)
+   For shared mappings, we should conversely verify that changes get
+   propagated back to all the places they're supposed to be.
+
+   Grep wants private fixed already mapped.
+   The main things grep needs to know about mmap are:
+   * does it exist and is it safe to write into the mmap'd area
+   * how to use it (BSD variants)  */
+
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#if !defined STDC_HEADERS && !defined HAVE_STDLIB_H
+char *malloc ();
+#endif
+
+/* This mess was copied from the GNU getpagesize.h.  */
+#ifndef HAVE_GETPAGESIZE
+/* Assume that all systems that can run configure have sys/param.h.  */
+# ifndef HAVE_SYS_PARAM_H
+#  define HAVE_SYS_PARAM_H 1
+# endif
+
+# ifdef _SC_PAGESIZE
+#  define getpagesize() sysconf(_SC_PAGESIZE)
+# else /* no _SC_PAGESIZE */
+#  ifdef HAVE_SYS_PARAM_H
+#   include <sys/param.h>
+#   ifdef EXEC_PAGESIZE
+#    define getpagesize() EXEC_PAGESIZE
+#   else /* no EXEC_PAGESIZE */
+#    ifdef NBPG
+#     define getpagesize() NBPG * CLSIZE
+#     ifndef CLSIZE
+#      define CLSIZE 1
+#     endif /* no CLSIZE */
+#    else /* no NBPG */
+#     ifdef NBPC
+#      define getpagesize() NBPC
+#     else /* no NBPC */
+#      ifdef PAGESIZE
+#       define getpagesize() PAGESIZE
+#      endif /* PAGESIZE */
+#     endif /* no NBPC */
+#    endif /* no NBPG */
+#   endif /* no EXEC_PAGESIZE */
+#  else /* no HAVE_SYS_PARAM_H */
+#   define getpagesize() 8192	/* punt totally */
+#  endif /* no HAVE_SYS_PARAM_H */
+# endif /* no _SC_PAGESIZE */
+
+#endif /* no HAVE_GETPAGESIZE */
+
+int
+main ()
+{
+  char *data, *data2, *data3;
+  int i, pagesize;
+  int fd;
+
+  pagesize = getpagesize ();
+
+  /* First, make a file with some known garbage in it. */
+  data = (char *) malloc (pagesize);
+  if (!data)
+    return 1;
+  for (i = 0; i < pagesize; ++i)
+    *(data + i) = rand ();
+  umask (0);
+  fd = creat ("conftest.mmap", 0600);
+  if (fd < 0)
+    return 1;
+  if (write (fd, data, pagesize) != pagesize)
+    return 1;
+  close (fd);
+
+  /* Next, try to mmap the file at a fixed address which already has
+     something else allocated at it.  If we can, also make sure that
+     we see the same garbage.  */
+  fd = open ("conftest.mmap", O_RDWR);
+  if (fd < 0)
+    return 1;
+  data2 = (char *) malloc (2 * pagesize);
+  if (!data2)
+    return 1;
+  data2 += (pagesize - ((long int) data2 & (pagesize - 1))) & (pagesize - 1);
+  if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE,
+		     MAP_PRIVATE | MAP_FIXED, fd, 0L))
+    return 1;
+  for (i = 0; i < pagesize; ++i)
+    if (*(data + i) != *(data2 + i))
+      return 1;
+
+  /* Finally, make sure that changes to the mapped area do not
+     percolate back to the file as seen by read().  (This is a bug on
+     some variants of i386 svr4.0.)  */
+  for (i = 0; i < pagesize; ++i)
+    *(data2 + i) = *(data2 + i) + 1;
+  data3 = (char *) malloc (pagesize);
+  if (!data3)
+    return 1;
+  if (read (fd, data3, pagesize) != pagesize)
+    return 1;
+  for (i = 0; i < pagesize; ++i)
+    if (*(data + i) != *(data3 + i))
+      return 1;
+  close (fd);
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_mmap_fixed_mapped=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_mmap_fixed_mapped=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_mmap_fixed_mapped" >&5
+echo "${ECHO_T}$ac_cv_func_mmap_fixed_mapped" >&6; }
+if test $ac_cv_func_mmap_fixed_mapped = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_MMAP 1
+_ACEOF
+
+fi
+rm -f conftest.mmap
+
+{ echo "$as_me:$LINENO: checking whether stat accepts an empty string" >&5
+echo $ECHO_N "checking whether stat accepts an empty string... $ECHO_C" >&6; }
+if test "${ac_cv_func_stat_empty_string_bug+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_stat_empty_string_bug=yes
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+struct stat sbuf;
+  return stat ("", &sbuf) == 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_stat_empty_string_bug=no
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_stat_empty_string_bug=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_stat_empty_string_bug" >&5
+echo "${ECHO_T}$ac_cv_func_stat_empty_string_bug" >&6; }
+if test $ac_cv_func_stat_empty_string_bug = yes; then
+  case " $LIBOBJS " in
+  *" stat.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS stat.$ac_objext"
+ ;;
+esac
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STAT_EMPTY_STRING_BUG 1
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for working strtod" >&5
+echo $ECHO_N "checking for working strtod... $ECHO_C" >&6; }
+if test "${ac_cv_func_strtod+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_strtod=no
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+$ac_includes_default
+#ifndef strtod
+double strtod ();
+#endif
+int
+main()
+{
+  {
+    /* Some versions of Linux strtod mis-parse strings with leading '+'.  */
+    char *string = " +69";
+    char *term;
+    double value;
+    value = strtod (string, &term);
+    if (value != 69 || term != (string + 4))
+      return 1;
+  }
+
+  {
+    /* Under Solaris 2.4, strtod returns the wrong value for the
+       terminating character under some conditions.  */
+    char *string = "NaN";
+    char *term;
+    strtod (string, &term);
+    if (term != string && *(term - 1) == 0)
+      return 1;
+  }
+  return 0;
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_strtod=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_strtod=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_strtod" >&5
+echo "${ECHO_T}$ac_cv_func_strtod" >&6; }
+if test $ac_cv_func_strtod = no; then
+  case " $LIBOBJS " in
+  *" strtod.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS strtod.$ac_objext"
+ ;;
+esac
+
+{ echo "$as_me:$LINENO: checking for pow" >&5
+echo $ECHO_N "checking for pow... $ECHO_C" >&6; }
+if test "${ac_cv_func_pow+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define pow to an innocuous variant, in case <limits.h> declares pow.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define pow innocuous_pow
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char pow (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef pow
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pow ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_pow || defined __stub___pow
+choke me
+#endif
+
+int
+main ()
+{
+return pow ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_func_pow=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_func_pow=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_pow" >&5
+echo "${ECHO_T}$ac_cv_func_pow" >&6; }
+
+if test $ac_cv_func_pow = no; then
+  { echo "$as_me:$LINENO: checking for pow in -lm" >&5
+echo $ECHO_N "checking for pow in -lm... $ECHO_C" >&6; }
+if test "${ac_cv_lib_m_pow+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pow ();
+int
+main ()
+{
+return pow ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_m_pow=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_m_pow=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_m_pow" >&5
+echo "${ECHO_T}$ac_cv_lib_m_pow" >&6; }
+if test $ac_cv_lib_m_pow = yes; then
+  POW_LIB=-lm
+else
+  { echo "$as_me:$LINENO: WARNING: cannot find library containing definition of pow" >&5
+echo "$as_me: WARNING: cannot find library containing definition of pow" >&2;}
+fi
+
+fi
+
+fi
+
+
+for ac_func in vprintf
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+{ echo "$as_me:$LINENO: checking for _doprnt" >&5
+echo $ECHO_N "checking for _doprnt... $ECHO_C" >&6; }
+if test "${ac_cv_func__doprnt+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define _doprnt to an innocuous variant, in case <limits.h> declares _doprnt.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define _doprnt innocuous__doprnt
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char _doprnt (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef _doprnt
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char _doprnt ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub__doprnt || defined __stub____doprnt
+choke me
+#endif
+
+int
+main ()
+{
+return _doprnt ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_func__doprnt=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_func__doprnt=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func__doprnt" >&5
+echo "${ECHO_T}$ac_cv_func__doprnt" >&6; }
+if test $ac_cv_func__doprnt = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_DOPRNT 1
+_ACEOF
+
+fi
+
+fi
+done
+
+
+
+################################################################################
+
+
+################################################################################
+{ echo "$as_me:$LINENO: checking file owner" >&5
+echo $ECHO_N "checking file owner... $ECHO_C" >&6; }
+OWNER="root"
+
+
+# Check whether --with-user was given.
+if test "${with_user+set}" = set; then
+  withval=$with_user;  OWNER="$withval"
+fi
+
+{ echo "$as_me:$LINENO: result: $OWNER" >&5
+echo "${ECHO_T}$OWNER" >&6; }
+
+if test x$OWNER != x; then
+	OWNER="-o $OWNER"
+fi
+
+################################################################################
+{ echo "$as_me:$LINENO: checking group owner" >&5
+echo $ECHO_N "checking group owner... $ECHO_C" >&6; }
+GROUP="root"
+
+# Check whether --with-group was given.
+if test "${with_group+set}" = set; then
+  withval=$with_group;  GROUP="$withval"
+fi
+
+{ echo "$as_me:$LINENO: result: $GROUP" >&5
+echo "${ECHO_T}$GROUP" >&6; }
+
+if test x$GROUP != x; then
+	GROUP="-g $GROUP"
+fi
+
+################################################################################
+{ echo "$as_me:$LINENO: checking device node uid" >&5
+echo $ECHO_N "checking device node uid... $ECHO_C" >&6; }
+
+
+# Check whether --with-device-uid was given.
+if test "${with_device_uid+set}" = set; then
+  withval=$with_device_uid;  DM_DEVICE_UID="$withval"
+else
+   DM_DEVICE_UID="0"
+fi
+
+{ echo "$as_me:$LINENO: result: $DM_DEVICE_UID" >&5
+echo "${ECHO_T}$DM_DEVICE_UID" >&6; }
+
+################################################################################
+{ echo "$as_me:$LINENO: checking device node gid" >&5
+echo $ECHO_N "checking device node gid... $ECHO_C" >&6; }
+
+
+# Check whether --with-device-gid was given.
+if test "${with_device_gid+set}" = set; then
+  withval=$with_device_gid;  DM_DEVICE_GID="$withval"
+else
+   DM_DEVICE_GID="0"
+fi
+
+{ echo "$as_me:$LINENO: result: $DM_DEVICE_GID" >&5
+echo "${ECHO_T}$DM_DEVICE_GID" >&6; }
+
+################################################################################
+{ echo "$as_me:$LINENO: checking device node mode" >&5
+echo $ECHO_N "checking device node mode... $ECHO_C" >&6; }
+
+
+# Check whether --with-device-mode was given.
+if test "${with_device_mode+set}" = set; then
+  withval=$with_device_mode;  DM_DEVICE_MODE="$withval"
+else
+   DM_DEVICE_MODE="0600"
+fi
+
+{ echo "$as_me:$LINENO: result: $DM_DEVICE_MODE" >&5
+echo "${ECHO_T}$DM_DEVICE_MODE" >&6; }
+
+################################################################################
+{ echo "$as_me:$LINENO: checking whether to enable lvm1 fallback" >&5
+echo $ECHO_N "checking whether to enable lvm1 fallback... $ECHO_C" >&6; }
+# Check whether --enable-lvm1_fallback was given.
+if test "${enable_lvm1_fallback+set}" = set; then
+  enableval=$enable_lvm1_fallback; LVM1_FALLBACK=$enableval
+else
+  LVM1_FALLBACK=no
+fi
+
+{ echo "$as_me:$LINENO: result: $LVM1_FALLBACK" >&5
+echo "${ECHO_T}$LVM1_FALLBACK" >&6; }
+
+if test x$LVM1_FALLBACK = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define LVM1_FALLBACK 1
+_ACEOF
+
+fi
+
+################################################################################
+{ echo "$as_me:$LINENO: checking whether to include support for lvm1 metadata" >&5
+echo $ECHO_N "checking whether to include support for lvm1 metadata... $ECHO_C" >&6; }
+
+# Check whether --with-lvm1 was given.
+if test "${with_lvm1+set}" = set; then
+  withval=$with_lvm1;  LVM1="$withval"
+else
+   LVM1="internal"
+fi
+
+{ echo "$as_me:$LINENO: result: $LVM1" >&5
+echo "${ECHO_T}$LVM1" >&6; }
+
+if [ "x$LVM1" != xnone -a "x$LVM1" != xinternal -a "x$LVM1" != xshared ];
+ then  { { echo "$as_me:$LINENO: error: --with-lvm1 parameter invalid
+" >&5
+echo "$as_me: error: --with-lvm1 parameter invalid
+" >&2;}
+   { (exit 1); exit 1; }; }
+fi;
+
+if test x$LVM1 = xinternal; then
+
+cat >>confdefs.h <<\_ACEOF
+#define LVM1_INTERNAL 1
+_ACEOF
+
+fi
+
+################################################################################
+{ echo "$as_me:$LINENO: checking whether to include support for GFS pool metadata" >&5
+echo $ECHO_N "checking whether to include support for GFS pool metadata... $ECHO_C" >&6; }
+
+# Check whether --with-pool was given.
+if test "${with_pool+set}" = set; then
+  withval=$with_pool;  POOL="$withval"
+else
+   POOL="internal"
+fi
+
+{ echo "$as_me:$LINENO: result: $POOL" >&5
+echo "${ECHO_T}$POOL" >&6; }
+
+if [ "x$POOL" != xnone -a "x$POOL" != xinternal -a "x$POOL" != xshared ];
+ then  { { echo "$as_me:$LINENO: error: --with-pool parameter invalid
+" >&5
+echo "$as_me: error: --with-pool parameter invalid
+" >&2;}
+   { (exit 1); exit 1; }; }
+fi;
+
+if test x$POOL = xinternal; then
+
+cat >>confdefs.h <<\_ACEOF
+#define POOL_INTERNAL 1
+_ACEOF
+
+fi
+
+################################################################################
+{ echo "$as_me:$LINENO: checking whether to include support for cluster locking" >&5
+echo $ECHO_N "checking whether to include support for cluster locking... $ECHO_C" >&6; }
+
+# Check whether --with-cluster was given.
+if test "${with_cluster+set}" = set; then
+  withval=$with_cluster;  CLUSTER="$withval"
+fi
+
+{ echo "$as_me:$LINENO: result: $CLUSTER" >&5
+echo "${ECHO_T}$CLUSTER" >&6; }
+
+if [ "x$CLUSTER" != xnone -a "x$CLUSTER" != xinternal -a "x$CLUSTER" != xshared ];
+ then  { { echo "$as_me:$LINENO: error: --with-cluster parameter invalid
+" >&5
+echo "$as_me: error: --with-cluster parameter invalid
+" >&2;}
+   { (exit 1); exit 1; }; }
+fi;
+
+if test x$CLUSTER = xinternal; then
+
+cat >>confdefs.h <<\_ACEOF
+#define CLUSTER_LOCKING_INTERNAL 1
+_ACEOF
+
+fi
+
+################################################################################
+{ echo "$as_me:$LINENO: checking whether to include snapshots" >&5
+echo $ECHO_N "checking whether to include snapshots... $ECHO_C" >&6; }
+
+# Check whether --with-snapshots was given.
+if test "${with_snapshots+set}" = set; then
+  withval=$with_snapshots;  SNAPSHOTS="$withval"
+else
+   SNAPSHOTS="internal"
+fi
+
+{ echo "$as_me:$LINENO: result: $SNAPSHOTS" >&5
+echo "${ECHO_T}$SNAPSHOTS" >&6; }
+
+if [ "x$SNAPSHOTS" != xnone -a "x$SNAPSHOTS" != xinternal -a "x$SNAPSHOTS" != xshared ];
+ then  { { echo "$as_me:$LINENO: error: --with-snapshots parameter invalid
+" >&5
+echo "$as_me: error: --with-snapshots parameter invalid
+" >&2;}
+   { (exit 1); exit 1; }; }
+fi;
+
+if test x$SNAPSHOTS = xinternal; then
+
+cat >>confdefs.h <<\_ACEOF
+#define SNAPSHOT_INTERNAL 1
+_ACEOF
+
+fi
+
+################################################################################
+{ echo "$as_me:$LINENO: checking whether to include mirrors" >&5
+echo $ECHO_N "checking whether to include mirrors... $ECHO_C" >&6; }
+
+# Check whether --with-mirrors was given.
+if test "${with_mirrors+set}" = set; then
+  withval=$with_mirrors;  MIRRORS="$withval"
+else
+   MIRRORS="internal"
+fi
+
+{ echo "$as_me:$LINENO: result: $MIRRORS" >&5
+echo "${ECHO_T}$MIRRORS" >&6; }
+
+if [ "x$MIRRORS" != xnone -a "x$MIRRORS" != xinternal -a "x$MIRRORS" != xshared ];
+ then  { { echo "$as_me:$LINENO: error: --with-mirrors parameter invalid
+" >&5
+echo "$as_me: error: --with-mirrors parameter invalid
+" >&2;}
+   { (exit 1); exit 1; }; }
+fi;
+
+if test x$MIRRORS = xinternal; then
+
+cat >>confdefs.h <<\_ACEOF
+#define MIRRORED_INTERNAL 1
+_ACEOF
+
+fi
+
+################################################################################
+{ echo "$as_me:$LINENO: checking whether to enable readline" >&5
+echo $ECHO_N "checking whether to enable readline... $ECHO_C" >&6; }
+# Check whether --enable-readline was given.
+if test "${enable_readline+set}" = set; then
+  enableval=$enable_readline; READLINE=$enableval
+else
+  READLINE=maybe
+fi
+
+{ echo "$as_me:$LINENO: result: $READLINE" >&5
+echo "${ECHO_T}$READLINE" >&6; }
+
+################################################################################
+{ echo "$as_me:$LINENO: checking whether to enable realtime support" >&5
+echo $ECHO_N "checking whether to enable realtime support... $ECHO_C" >&6; }
+# Check whether --enable-realtime was given.
+if test "${enable_realtime+set}" = set; then
+  enableval=$enable_realtime; REALTIME=$enableval
+fi
+
+{ echo "$as_me:$LINENO: result: $REALTIME" >&5
+echo "${ECHO_T}$REALTIME" >&6; }
+
+################################################################################
+{ echo "$as_me:$LINENO: checking whether to build cluster LVM daemon" >&5
+echo $ECHO_N "checking whether to build cluster LVM daemon... $ECHO_C" >&6; }
+
+# Check whether --with-clvmd was given.
+if test "${with_clvmd+set}" = set; then
+  withval=$with_clvmd;  CLVMD="$withval"
+else
+   CLVMD="none"
+fi
+
+if test x$CLVMD = xyes; then
+	CLVMD=all
+fi
+{ echo "$as_me:$LINENO: result: $CLVMD" >&5
+echo "${ECHO_T}$CLVMD" >&6; }
+
+if  test x$CLVMD != xnone && test x$CLUSTER = xnone; then
+	CLUSTER=internal
+fi
+
+################################################################################
+{ echo "$as_me:$LINENO: checking whether to enable debugging" >&5
+echo $ECHO_N "checking whether to enable debugging... $ECHO_C" >&6; }
+# Check whether --enable-debug was given.
+if test "${enable_debug+set}" = set; then
+  enableval=$enable_debug; DEBUG=$enableval
+else
+  DEBUG=no
+fi
+
+{ echo "$as_me:$LINENO: result: $DEBUG" >&5
+echo "${ECHO_T}$DEBUG" >&6; }
+
+if test x$DEBUG = xyes; then
+	COPTIMISE_FLAG=
+else
+	CSCOPE_CMD=
+fi
+
+################################################################################
+{ echo "$as_me:$LINENO: checking for C optimisation flag" >&5
+echo $ECHO_N "checking for C optimisation flag... $ECHO_C" >&6; }
+
+# Check whether --with-optimisation was given.
+if test "${with_optimisation+set}" = set; then
+  withval=$with_optimisation;  COPTIMISE_FLAG="$withval"
+fi
+
+{ echo "$as_me:$LINENO: result: $COPTIMISE_FLAG" >&5
+echo "${ECHO_T}$COPTIMISE_FLAG" >&6; }
+
+################################################################################
+{ echo "$as_me:$LINENO: checking whether to gather gcov profiling data" >&5
+echo $ECHO_N "checking whether to gather gcov profiling data... $ECHO_C" >&6; }
+# Check whether --enable-profiling was given.
+if test "${enable_profiling+set}" = set; then
+  enableval=$enable_profiling; PROFILING=$enableval
+else
+  PROFILING=no
+fi
+
+{ echo "$as_me:$LINENO: result: $PROFILING" >&5
+echo "${ECHO_T}$PROFILING" >&6; }
+
+if test "x$PROFILING" = xyes; then
+  COPTIMISE_FLAG="$COPTIMISE_FLAG -fprofile-arcs -ftest-coverage"
+  # Extract the first word of "lcov", so it can be a program name with args.
+set dummy lcov; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_LCOV+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $LCOV in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_LCOV="$LCOV" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_LCOV="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_LCOV" && ac_cv_path_LCOV="no"
+  ;;
+esac
+fi
+LCOV=$ac_cv_path_LCOV
+if test -n "$LCOV"; then
+  { echo "$as_me:$LINENO: result: $LCOV" >&5
+echo "${ECHO_T}$LCOV" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  # Extract the first word of "genhtml", so it can be a program name with args.
+set dummy genhtml; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_GENHTML+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $GENHTML in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_GENHTML="$GENHTML" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_GENHTML="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_GENHTML" && ac_cv_path_GENHTML="no"
+  ;;
+esac
+fi
+GENHTML=$ac_cv_path_GENHTML
+if test -n "$GENHTML"; then
+  { echo "$as_me:$LINENO: result: $GENHTML" >&5
+echo "${ECHO_T}$GENHTML" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  if test "$LCOV" = no -o "$GENHTML" = no ; then
+    { { echo "$as_me:$LINENO: error: lcov and genhtml are required for profiling" >&5
+echo "$as_me: error: lcov and genhtml are required for profiling" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+fi
+
+################################################################################
+{ echo "$as_me:$LINENO: checking whether to use device-mapper" >&5
+echo $ECHO_N "checking whether to use device-mapper... $ECHO_C" >&6; }
+# Check whether --enable-devmapper was given.
+if test "${enable_devmapper+set}" = set; then
+  enableval=$enable_devmapper; DEVMAPPER=$enableval
+fi
+
+{ echo "$as_me:$LINENO: result: $DEVMAPPER" >&5
+echo "${ECHO_T}$DEVMAPPER" >&6; }
+
+if test x$DEVMAPPER = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define DEVMAPPER_SUPPORT 1
+_ACEOF
+
+fi
+
+################################################################################
+# Check whether --enable-compat was given.
+if test "${enable_compat+set}" = set; then
+  enableval=$enable_compat; DM_COMPAT=$enableval
+else
+  DM_COMPAT=no
+fi
+
+
+################################################################################
+# Check whether --enable-ioctl was given.
+if test "${enable_ioctl+set}" = set; then
+  enableval=$enable_ioctl; DM_IOCTLS=$enableval
+fi
+
+
+################################################################################
+{ echo "$as_me:$LINENO: checking whether to enable O_DIRECT" >&5
+echo $ECHO_N "checking whether to enable O_DIRECT... $ECHO_C" >&6; }
+# Check whether --enable-o_direct was given.
+if test "${enable_o_direct+set}" = set; then
+  enableval=$enable_o_direct; ODIRECT=$enableval
+fi
+
+{ echo "$as_me:$LINENO: result: $ODIRECT" >&5
+echo "${ECHO_T}$ODIRECT" >&6; }
+
+if test x$ODIRECT = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define O_DIRECT_SUPPORT 1
+_ACEOF
+
+fi
+
+################################################################################
+{ echo "$as_me:$LINENO: checking whether to compile liblvm2cmd.so" >&5
+echo $ECHO_N "checking whether to compile liblvm2cmd.so... $ECHO_C" >&6; }
+# Check whether --enable-cmdlib was given.
+if test "${enable_cmdlib+set}" = set; then
+  enableval=$enable_cmdlib; CMDLIB=$enableval
+else
+  CMDLIB=no
+fi
+
+{ echo "$as_me:$LINENO: result: $CMDLIB" >&5
+echo "${ECHO_T}$CMDLIB" >&6; }
+
+test x$CMDLIB = xyes \
+  && LVM2CMD_LIB=-llvm2cmd \
+  || LVM2CMD_LIB=
+
+################################################################################
+# Check whether --enable-pkgconfig was given.
+if test "${enable_pkgconfig+set}" = set; then
+  enableval=$enable_pkgconfig; PKGCONFIG=$enableval
+else
+  PKGCONFIG=no
+fi
+
+
+################################################################################
+{ echo "$as_me:$LINENO: checking whether to install fsadm" >&5
+echo $ECHO_N "checking whether to install fsadm... $ECHO_C" >&6; }
+# Check whether --enable-fsadm was given.
+if test "${enable_fsadm+set}" = set; then
+  enableval=$enable_fsadm; FSADM=$enableval
+fi
+
+{ echo "$as_me:$LINENO: result: $FSADM" >&5
+echo "${ECHO_T}$FSADM" >&6; }
+
+################################################################################
+{ echo "$as_me:$LINENO: checking whether to use dmeventd" >&5
+echo $ECHO_N "checking whether to use dmeventd... $ECHO_C" >&6; }
+# Check whether --enable-dmeventd was given.
+if test "${enable_dmeventd+set}" = set; then
+  enableval=$enable_dmeventd; DMEVENTD=$enableval
+fi
+
+{ echo "$as_me:$LINENO: result: $DMEVENTD" >&5
+echo "${ECHO_T}$DMEVENTD" >&6; }
+
+BUILD_DMEVENTD=$DMEVENTD
+
+if test x$DMEVENTD = xyes; then
+   if test x$MIRRORS != xinternal; then
+      { { echo "$as_me:$LINENO: error: --enable-dmeventd currently requires --with-mirrors=internal
+      " >&5
+echo "$as_me: error: --enable-dmeventd currently requires --with-mirrors=internal
+      " >&2;}
+   { (exit 1); exit 1; }; }
+   fi
+   if test x$CMDLIB = xno; then
+      { { echo "$as_me:$LINENO: error: --enable-dmeventd requires --enable-cmdlib to be used as well
+      " >&5
+echo "$as_me: error: --enable-dmeventd requires --enable-cmdlib to be used as well
+      " >&2;}
+   { (exit 1); exit 1; }; }
+   fi
+fi
+
+if test x$DMEVENTD = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define DMEVENTD 1
+_ACEOF
+
+fi
+
+################################################################################
+
+{ echo "$as_me:$LINENO: checking for getline in -lc" >&5
+echo $ECHO_N "checking for getline in -lc... $ECHO_C" >&6; }
+if test "${ac_cv_lib_c_getline+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getline ();
+int
+main ()
+{
+return getline ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_c_getline=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_c_getline=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_c_getline" >&5
+echo "${ECHO_T}$ac_cv_lib_c_getline" >&6; }
+if test $ac_cv_lib_c_getline = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_GETLINE 1
+_ACEOF
+
+fi
+
+
+################################################################################
+
+{ echo "$as_me:$LINENO: checking for canonicalize_file_name in -lc" >&5
+echo $ECHO_N "checking for canonicalize_file_name in -lc... $ECHO_C" >&6; }
+if test "${ac_cv_lib_c_canonicalize_file_name+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char canonicalize_file_name ();
+int
+main ()
+{
+return canonicalize_file_name ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_c_canonicalize_file_name=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_c_canonicalize_file_name=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_c_canonicalize_file_name" >&5
+echo "${ECHO_T}$ac_cv_lib_c_canonicalize_file_name" >&6; }
+if test $ac_cv_lib_c_canonicalize_file_name = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_CANONICALIZE_FILE_NAME 1
+_ACEOF
+
+fi
+
+
+################################################################################
+if [ "x$exec_prefix" = xNONE -a "x$prefix" = xNONE ];
+ then  exec_prefix="";
+fi;
+
+################################################################################
+if test x$READLINE != xno; then
+	{ echo "$as_me:$LINENO: checking for library containing tgetent" >&5
+echo $ECHO_N "checking for library containing tgetent... $ECHO_C" >&6; }
+if test "${ac_cv_search_tgetent+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char tgetent ();
+int
+main ()
+{
+return tgetent ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' ncurses curses termcap termlib; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_search_tgetent=$ac_res
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext
+  if test "${ac_cv_search_tgetent+set}" = set; then
+  break
+fi
+done
+if test "${ac_cv_search_tgetent+set}" = set; then
+  :
+else
+  ac_cv_search_tgetent=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search_tgetent" >&5
+echo "${ECHO_T}$ac_cv_search_tgetent" >&6; }
+ac_res=$ac_cv_search_tgetent
+if test "$ac_res" != no; then
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+  tg_found=yes
+else
+  tg_found=no
+fi
+
+	test x$READLINE:$tg_found = xyes:no &&
+	  { { echo "$as_me:$LINENO: error: termcap could not be found which is required for the
+--enable-readline option (which is enabled by default).  Either disable readline
+support with --disable-readline or download and install termcap from:
+	ftp.gnu.org/gnu/termcap
+Note: if you are using precompiled packages you will also need the development
+  package as well (which may be called termcap-devel or something similar).
+Note: (n)curses also seems to work as a substitute for termcap.  This was
+  not found either - but you could try installing that as well.
+" >&5
+echo "$as_me: error: termcap could not be found which is required for the
+--enable-readline option (which is enabled by default).  Either disable readline
+support with --disable-readline or download and install termcap from:
+	ftp.gnu.org/gnu/termcap
+Note: if you are using precompiled packages you will also need the development
+  package as well (which may be called termcap-devel or something similar).
+Note: (n)curses also seems to work as a substitute for termcap.  This was
+  not found either - but you could try installing that as well.
+" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+################################################################################
+{ echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_dl_dlopen=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_dl_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; }
+if test $ac_cv_lib_dl_dlopen = yes; then
+  HAVE_LIBDL=yes
+else
+  HAVE_LIBDL=no
+fi
+
+
+if [ "x$HAVE_LIBDL" = xyes ]; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBDL 1
+_ACEOF
+
+	LIBS="-ldl $LIBS"
+else
+	HAVE_LIBDL=no
+fi
+
+################################################################################
+if [ \( "x$LVM1" = xshared -o "x$POOL" = xshared -o "x$CLUSTER" = xshared \
+      -o "x$SNAPSHOTS" = xshared -o "x$MIRRORS" = xshared \
+      \) -a "x$STATIC_LINK" = xyes ];
+ then  { { echo "$as_me:$LINENO: error: Features cannot be 'shared' when building statically
+" >&5
+echo "$as_me: error: Features cannot be 'shared' when building statically
+" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+################################################################################
+{ echo "$as_me:$LINENO: checking whether to use static linking" >&5
+echo $ECHO_N "checking whether to use static linking... $ECHO_C" >&6; }
+# Check whether --enable-static_link was given.
+if test "${enable_static_link+set}" = set; then
+  enableval=$enable_static_link; STATIC_LINK=$enableval
+else
+  STATIC_LINK=no
+fi
+
+{ echo "$as_me:$LINENO: result: $STATIC_LINK" >&5
+echo "${ECHO_T}$STATIC_LINK" >&6; }
+
+################################################################################
+{ echo "$as_me:$LINENO: checking whether to enable selinux support" >&5
+echo $ECHO_N "checking whether to enable selinux support... $ECHO_C" >&6; }
+# Check whether --enable-selinux was given.
+if test "${enable_selinux+set}" = set; then
+  enableval=$enable_selinux; SELINUX=$enableval
+fi
+
+{ echo "$as_me:$LINENO: result: $SELINUX" >&5
+echo "${ECHO_T}$SELINUX" >&6; }
+
+################################################################################
+if test x$SELINUX = xyes; then
+	{ echo "$as_me:$LINENO: checking for sepol_check_context in -lsepol" >&5
+echo $ECHO_N "checking for sepol_check_context in -lsepol... $ECHO_C" >&6; }
+if test "${ac_cv_lib_sepol_sepol_check_context+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsepol  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char sepol_check_context ();
+int
+main ()
+{
+return sepol_check_context ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_sepol_sepol_check_context=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_sepol_sepol_check_context=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_sepol_sepol_check_context" >&5
+echo "${ECHO_T}$ac_cv_lib_sepol_sepol_check_context" >&6; }
+if test $ac_cv_lib_sepol_sepol_check_context = yes; then
+  HAVE_SEPOL=yes
+else
+  HAVE_SEPOL=no
+fi
+
+
+	if test x$HAVE_SEPOL = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_SEPOL 1
+_ACEOF
+
+		LIBS="-lsepol $LIBS"
+	fi
+
+	{ echo "$as_me:$LINENO: checking for is_selinux_enabled in -lselinux" >&5
+echo $ECHO_N "checking for is_selinux_enabled in -lselinux... $ECHO_C" >&6; }
+if test "${ac_cv_lib_selinux_is_selinux_enabled+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lselinux  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char is_selinux_enabled ();
+int
+main ()
+{
+return is_selinux_enabled ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_selinux_is_selinux_enabled=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_selinux_is_selinux_enabled=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_selinux_is_selinux_enabled" >&5
+echo "${ECHO_T}$ac_cv_lib_selinux_is_selinux_enabled" >&6; }
+if test $ac_cv_lib_selinux_is_selinux_enabled = yes; then
+  HAVE_SELINUX=yes
+else
+  HAVE_SELINUX=no
+fi
+
+
+	if test x$HAVE_SELINUX = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_SELINUX 1
+_ACEOF
+
+		LIBS="-lselinux $LIBS"
+	else
+		{ echo "$as_me:$LINENO: WARNING: Disabling selinux" >&5
+echo "$as_me: WARNING: Disabling selinux" >&2;}
+	fi
+
+	# With --enable-static_link and selinux enabled, linking
+	# fails on at least Debian unstable due to unsatisfied references
+	# to pthread_mutex_lock and _unlock.  See if we need -lpthread.
+	if test "$STATIC_LINK-$HAVE_SELINUX" = yes-yes; then
+		lvm_saved_libs=$LIBS
+		LIBS="$LIBS -static"
+		{ echo "$as_me:$LINENO: checking for library containing pthread_mutex_lock" >&5
+echo $ECHO_N "checking for library containing pthread_mutex_lock... $ECHO_C" >&6; }
+if test "${ac_cv_search_pthread_mutex_lock+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_mutex_lock ();
+int
+main ()
+{
+return pthread_mutex_lock ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' pthread; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_search_pthread_mutex_lock=$ac_res
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext
+  if test "${ac_cv_search_pthread_mutex_lock+set}" = set; then
+  break
+fi
+done
+if test "${ac_cv_search_pthread_mutex_lock+set}" = set; then
+  :
+else
+  ac_cv_search_pthread_mutex_lock=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search_pthread_mutex_lock" >&5
+echo "${ECHO_T}$ac_cv_search_pthread_mutex_lock" >&6; }
+ac_res=$ac_cv_search_pthread_mutex_lock
+if test "$ac_res" != no; then
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+  test "$ac_cv_search_pthread_mutex_lock" = "none required" ||
+				LIB_PTHREAD=-lpthread
+fi
+
+		LIBS=$lvm_saved_libs
+	fi
+fi
+
+################################################################################
+if test x$REALTIME = xyes; then
+	{ echo "$as_me:$LINENO: checking for clock_gettime in -lrt" >&5
+echo $ECHO_N "checking for clock_gettime in -lrt... $ECHO_C" >&6; }
+if test "${ac_cv_lib_rt_clock_gettime+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrt  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char clock_gettime ();
+int
+main ()
+{
+return clock_gettime ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_rt_clock_gettime=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_rt_clock_gettime=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_rt_clock_gettime" >&5
+echo "${ECHO_T}$ac_cv_lib_rt_clock_gettime" >&6; }
+if test $ac_cv_lib_rt_clock_gettime = yes; then
+  HAVE_REALTIME=yes
+else
+  HAVE_REALTIME=no
+fi
+
+
+	if test x$HAVE_REALTIME = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_REALTIME 1
+_ACEOF
+
+		LIBS="-lrt $LIBS"
+	else
+		{ echo "$as_me:$LINENO: WARNING: Disabling realtime clock" >&5
+echo "$as_me: WARNING: Disabling realtime clock" >&2;}
+	fi
+fi
+
+################################################################################
+
+for ac_header in getopt.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_GETOPTLONG 1
+_ACEOF
+
+fi
+
+done
+
+
+################################################################################
+if test x$READLINE != xno; then
+	rl_found=yes
+
+{ echo "$as_me:$LINENO: checking for readline in -lreadline" >&5
+echo $ECHO_N "checking for readline in -lreadline... $ECHO_C" >&6; }
+if test "${ac_cv_lib_readline_readline+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lreadline  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char readline ();
+int
+main ()
+{
+return readline ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_readline_readline=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_readline_readline=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_readline_readline" >&5
+echo "${ECHO_T}$ac_cv_lib_readline_readline" >&6; }
+if test $ac_cv_lib_readline_readline = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBREADLINE 1
+_ACEOF
+
+  LIBS="-lreadline $LIBS"
+
+else
+  rl_found=no
+fi
+
+	test x$READLINE:$rl_found = xyes:no &&
+	  { { echo "$as_me:$LINENO: error: GNU Readline could not be found which is required for the
+--enable-readline option (which is enabled by default).  Either disable readline
+support with --disable-readline or download and install readline from:
+	ftp.gnu.org/gnu/readline
+Note: if you are using precompiled packages you will also need the development
+package as well (which may be called readline-devel or something similar).
+" >&5
+echo "$as_me: error: GNU Readline could not be found which is required for the
+--enable-readline option (which is enabled by default).  Either disable readline
+support with --disable-readline or download and install readline from:
+	ftp.gnu.org/gnu/readline
+Note: if you are using precompiled packages you will also need the development
+package as well (which may be called readline-devel or something similar).
+" >&2;}
+   { (exit 1); exit 1; }; }
+	if test $rl_found = yes; then
+
+for ac_func in rl_completion_matches
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+cat >>confdefs.h <<\_ACEOF
+#define READLINE_SUPPORT 1
+_ACEOF
+
+	fi
+fi
+
+################################################################################
+{ echo "$as_me:$LINENO: checking whether to enable internationalisation" >&5
+echo $ECHO_N "checking whether to enable internationalisation... $ECHO_C" >&6; }
+# Check whether --enable-nls was given.
+if test "${enable_nls+set}" = set; then
+  enableval=$enable_nls; INTL=$enableval
+else
+  INTL=no
+fi
+
+{ echo "$as_me:$LINENO: result: $INTL" >&5
+echo "${ECHO_T}$INTL" >&6; }
+
+if test x$INTL = xyes; then
+# FIXME - Move this - can be device-mapper too
+	INTL_PACKAGE="lvm2"
+	# Extract the first word of "msgfmt", so it can be a program name with args.
+set dummy msgfmt; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_MSGFMT+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $MSGFMT in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_MSGFMT="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+MSGFMT=$ac_cv_path_MSGFMT
+if test -n "$MSGFMT"; then
+  { echo "$as_me:$LINENO: result: $MSGFMT" >&5
+echo "${ECHO_T}$MSGFMT" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+	if [ "x$MSGFMT" == x ];
+		then  { { echo "$as_me:$LINENO: error: msgfmt not found in path $PATH
+		" >&5
+echo "$as_me: error: msgfmt not found in path $PATH
+		" >&2;}
+   { (exit 1); exit 1; }; }
+	fi;
+
+
+# Check whether --with-localedir was given.
+if test "${with_localedir+set}" = set; then
+  withval=$with_localedir;  LOCALEDIR="$withval"
+else
+   LOCALEDIR='${prefix}/share/locale'
+fi
+
+fi
+
+################################################################################
+
+# Check whether --with-confdir was given.
+if test "${with_confdir+set}" = set; then
+  withval=$with_confdir;  CONFDIR="$withval"
+else
+   CONFDIR='/etc'
+fi
+
+
+
+# Check whether --with-staticdir was given.
+if test "${with_staticdir+set}" = set; then
+  withval=$with_staticdir;  STATICDIR="$withval"
+else
+   STATICDIR='${exec_prefix}/sbin'
+fi
+
+
+
+# Check whether --with-usrlibdir was given.
+if test "${with_usrlibdir+set}" = set; then
+  withval=$with_usrlibdir;  usrlibdir="$withval"
+else
+   usrlibdir='${prefix}/lib'
+fi
+
+
+
+# Check whether --with-usrsbindir was given.
+if test "${with_usrsbindir+set}" = set; then
+  withval=$with_usrsbindir;  usrsbindir="$withval"
+else
+   usrsbindir='${prefix}/sbin'
+fi
+
+
+################################################################################
+if test x$READLINE = xyes; then
+
+
+for ac_header in readline/readline.h readline/history.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  { { echo "$as_me:$LINENO: error: bailing out" >&5
+echo "$as_me: error: bailing out" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+done
+
+fi
+
+if test x$CLVMD != xnone; then
+
+
+
+
+
+
+
+
+
+
+for ac_header in mntent.h netdb.h netinet/in.h pthread.h search.h sys/mount.h sys/socket.h sys/uio.h sys/un.h utmpx.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  { { echo "$as_me:$LINENO: error: bailing out" >&5
+echo "$as_me: error: bailing out" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+done
+
+
+
+
+
+
+for ac_func in dup2 getmntent memmove select socket
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  { { echo "$as_me:$LINENO: error: bailing out" >&5
+echo "$as_me: error: bailing out" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+done
+
+	# getmntent is in the standard C library on UNICOS, in -lsun on Irix 4,
+# -lseq on Dynix/PTX, -lgen on Unixware.
+{ echo "$as_me:$LINENO: checking for library containing getmntent" >&5
+echo $ECHO_N "checking for library containing getmntent... $ECHO_C" >&6; }
+if test "${ac_cv_search_getmntent+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getmntent ();
+int
+main ()
+{
+return getmntent ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' sun seq gen; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_search_getmntent=$ac_res
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext
+  if test "${ac_cv_search_getmntent+set}" = set; then
+  break
+fi
+done
+if test "${ac_cv_search_getmntent+set}" = set; then
+  :
+else
+  ac_cv_search_getmntent=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search_getmntent" >&5
+echo "${ECHO_T}$ac_cv_search_getmntent" >&6; }
+ac_res=$ac_cv_search_getmntent
+if test "$ac_res" != no; then
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+  ac_cv_func_getmntent=yes
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_GETMNTENT
+_ACEOF
+
+else
+  ac_cv_func_getmntent=no
+fi
+
+
+#	AC_FUNC_REALLOC
+
+
+for ac_header in sys/select.h sys/socket.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+{ echo "$as_me:$LINENO: checking types of arguments for select" >&5
+echo $ECHO_N "checking types of arguments for select... $ECHO_C" >&6; }
+if test "${ac_cv_func_select_args+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  for ac_arg234 in 'fd_set *' 'int *' 'void *'; do
+ for ac_arg1 in 'int' 'size_t' 'unsigned long int' 'unsigned int'; do
+  for ac_arg5 in 'struct timeval *' 'const struct timeval *'; do
+   cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+
+int
+main ()
+{
+extern int select ($ac_arg1,
+					    $ac_arg234, $ac_arg234, $ac_arg234,
+					    $ac_arg5);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_func_select_args="$ac_arg1,$ac_arg234,$ac_arg5"; break 3
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+ done
+done
+# Provide a safe default value.
+: ${ac_cv_func_select_args='int,int *,struct timeval *'}
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_select_args" >&5
+echo "${ECHO_T}$ac_cv_func_select_args" >&6; }
+ac_save_IFS=$IFS; IFS=','
+set dummy `echo "$ac_cv_func_select_args" | sed 's/\*/\*/g'`
+IFS=$ac_save_IFS
+shift
+
+cat >>confdefs.h <<_ACEOF
+#define SELECT_TYPE_ARG1 $1
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define SELECT_TYPE_ARG234 ($2)
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define SELECT_TYPE_ARG5 ($3)
+_ACEOF
+
+rm -f conftest*
+
+fi
+
+if test x$CLUSTER != xnone; then
+
+
+for ac_header in sys/socket.h sys/un.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  { { echo "$as_me:$LINENO: error: bailing out" >&5
+echo "$as_me: error: bailing out" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+done
+
+
+for ac_func in socket
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  { { echo "$as_me:$LINENO: error: bailing out" >&5
+echo "$as_me: error: bailing out" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+done
+
+fi
+
+if test x$HAVE_LIBDL = xyes; then
+
+for ac_header in dlfcn.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  { { echo "$as_me:$LINENO: error: bailing out" >&5
+echo "$as_me: error: bailing out" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+done
+
+fi
+
+if test x$INTL = xyes; then
+
+for ac_header in libintl.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  { { echo "$as_me:$LINENO: error: bailing out" >&5
+echo "$as_me: error: bailing out" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+done
+
+fi
+
+if test x$HAVE_SELINUX = xyes; then
+
+for ac_header in selinux/selinux.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  { { echo "$as_me:$LINENO: error: bailing out" >&5
+echo "$as_me: error: bailing out" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+done
+
+fi
+
+################################################################################
+# Extract the first word of "modprobe", so it can be a program name with args.
+set dummy modprobe; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_MODPROBE_CMD+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $MODPROBE_CMD in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_MODPROBE_CMD="$MODPROBE_CMD" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_MODPROBE_CMD="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+MODPROBE_CMD=$ac_cv_path_MODPROBE_CMD
+if test -n "$MODPROBE_CMD"; then
+  { echo "$as_me:$LINENO: result: $MODPROBE_CMD" >&5
+echo "${ECHO_T}$MODPROBE_CMD" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+
+if test x$MODPROBE_CMD != x; then
+
+cat >>confdefs.h <<_ACEOF
+#define MODPROBE_CMD "$MODPROBE_CMD"
+_ACEOF
+
+fi
+
+################################################################################
+
+
+if test "$BUILD_DMEVENTD" = yes; then
+
+# Check whether --with-dmeventd-pidfile was given.
+if test "${with_dmeventd_pidfile+set}" = set; then
+  withval=$with_dmeventd_pidfile;  cat >>confdefs.h <<_ACEOF
+#define DMEVENTD_PIDFILE "$withval"
+_ACEOF
+
+else
+   cat >>confdefs.h <<_ACEOF
+#define DMEVENTD_PIDFILE "/var/run/dmeventd.pid"
+_ACEOF
+
+fi
+
+fi
+
+
+
+if test "$BUILD_DMEVENTD" = yes; then
+        dmeventd_prefix="$exec_prefix"
+        if test "x$dmeventd_prefix" = "xNONE"; then
+                dmeventd_prefix="$prefix"
+        fi
+        if test "x$dmeventd_prefix" = "xNONE"; then
+                dmeventd_prefix=""
+        fi
+
+# Check whether --with-dmeventd-path was given.
+if test "${with_dmeventd_path+set}" = set; then
+  withval=$with_dmeventd_path;  cat >>confdefs.h <<_ACEOF
+#define DMEVENTD_PATH "$withval"
+_ACEOF
+
+else
+   cat >>confdefs.h <<_ACEOF
+#define DMEVENTD_PATH "$dmeventd_prefix/sbin/dmeventd"
+_ACEOF
+
+fi
+
+fi
+
+################################################################################
+{ echo "$as_me:$LINENO: checking for kernel interface choice" >&5
+echo $ECHO_N "checking for kernel interface choice... $ECHO_C" >&6; }
+
+# Check whether --with-interface was given.
+if test "${with_interface+set}" = set; then
+  withval=$with_interface;  interface="$withval"
+else
+   interface=ioctl
+fi
+
+if [ "x$interface" != xioctl ];
+then
+  { { echo "$as_me:$LINENO: error: --with-interface=ioctl required. fs no longer supported." >&5
+echo "$as_me: error: --with-interface=ioctl required. fs no longer supported." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+{ echo "$as_me:$LINENO: result: $interface" >&5
+echo "${ECHO_T}$interface" >&6; }
+
+################################################################################
+DM_LIB_VERSION="\"`cat VERSION_DM 2>/dev/null || echo Unknown`\""
+
+cat >>confdefs.h <<_ACEOF
+#define DM_LIB_VERSION $DM_LIB_VERSION
+_ACEOF
+
+
+DM_LIB_PATCHLEVEL=`cat VERSION_DM | awk -F '[-. ]' '{printf "%s.%s.%s",$1,$2,$3}'`
+
+LVM_VERSION="\"`cat VERSION 2>/dev/null || echo Unknown`\""
+
+################################################################################
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+################################################################################
+ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile doc/Makefile include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/snapshot/Makefile libdm/Makefile libdm/libdevmapper.pc man/Makefile po/Makefile scripts/Makefile test/Makefile tools/Makefile tools/version.h"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      *) $as_unset $ac_var ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    test "x$cache_file" != "x/dev/null" &&
+      { echo "$as_me:$LINENO: updating cache $cache_file" >&5
+echo "$as_me: updating cache $cache_file" >&6;}
+    cat confcache >$cache_file
+  else
+    { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line after each line using $LINENO; the second 'sed'
+  # does the real work.  The second script uses 'N' to pair each
+  # line-number line with the line containing $LINENO, and appends
+  # trailing '-' during substitution so that $LINENO is not a special
+  # case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # scripts with optimization help from Paolo Bonzini.  Blame Lee
+  # E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+  case `echo 'x\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  *)   ECHO_C='\c';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s='ln -s'
+  # ... but there are two gotchas:
+  # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+  # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+  # In both cases, we have to default to `cp -p'.
+  ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+    as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+        test -d "$1/.";
+      else
+	case $1 in
+        -*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+
+# Save the log message, to keep $[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.61.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+  -q, --quiet      do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+  --file=FILE[:TEMPLATE]
+		   instantiate the configuration file FILE
+  --header=FILE[:TEMPLATE]
+		   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to <bug-autoconf@gnu.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.61,
+  with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2006 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value.  By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    echo "$ac_cs_version"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    { echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) { echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+  echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+  CONFIG_SHELL=$SHELL
+  export CONFIG_SHELL
+  exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "lib/misc/configure.h") CONFIG_HEADERS="$CONFIG_HEADERS lib/misc/configure.h" ;;
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "make.tmpl") CONFIG_FILES="$CONFIG_FILES make.tmpl" ;;
+    "daemons/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/Makefile" ;;
+    "daemons/clvmd/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/clvmd/Makefile" ;;
+    "daemons/dmeventd/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/Makefile" ;;
+    "daemons/dmeventd/libdevmapper-event.pc") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/libdevmapper-event.pc" ;;
+    "daemons/dmeventd/plugins/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/Makefile" ;;
+    "daemons/dmeventd/plugins/mirror/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/mirror/Makefile" ;;
+    "daemons/dmeventd/plugins/snapshot/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/snapshot/Makefile" ;;
+    "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
+    "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;;
+    "lib/Makefile") CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;;
+    "lib/format1/Makefile") CONFIG_FILES="$CONFIG_FILES lib/format1/Makefile" ;;
+    "lib/format_pool/Makefile") CONFIG_FILES="$CONFIG_FILES lib/format_pool/Makefile" ;;
+    "lib/locking/Makefile") CONFIG_FILES="$CONFIG_FILES lib/locking/Makefile" ;;
+    "lib/mirror/Makefile") CONFIG_FILES="$CONFIG_FILES lib/mirror/Makefile" ;;
+    "lib/snapshot/Makefile") CONFIG_FILES="$CONFIG_FILES lib/snapshot/Makefile" ;;
+    "libdm/Makefile") CONFIG_FILES="$CONFIG_FILES libdm/Makefile" ;;
+    "libdm/libdevmapper.pc") CONFIG_FILES="$CONFIG_FILES libdm/libdevmapper.pc" ;;
+    "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;;
+    "po/Makefile") CONFIG_FILES="$CONFIG_FILES po/Makefile" ;;
+    "scripts/Makefile") CONFIG_FILES="$CONFIG_FILES scripts/Makefile" ;;
+    "test/Makefile") CONFIG_FILES="$CONFIG_FILES test/Makefile" ;;
+    "tools/Makefile") CONFIG_FILES="$CONFIG_FILES tools/Makefile" ;;
+    "tools/version.h") CONFIG_FILES="$CONFIG_FILES tools/version.h" ;;
+
+  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp=
+  trap 'exit_status=$?
+  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} ||
+{
+   echo "$me: cannot create a temporary directory in ." >&2
+   { (exit 1); exit 1; }
+}
+
+#
+# Set up the sed scripts for CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "$CONFIG_FILES"; then
+
+_ACEOF
+
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  cat >conf$$subs.sed <<_ACEOF
+SHELL!$SHELL$ac_delim
+PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim
+PACKAGE_NAME!$PACKAGE_NAME$ac_delim
+PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim
+PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim
+PACKAGE_STRING!$PACKAGE_STRING$ac_delim
+PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim
+exec_prefix!$exec_prefix$ac_delim
+prefix!$prefix$ac_delim
+program_transform_name!$program_transform_name$ac_delim
+bindir!$bindir$ac_delim
+sbindir!$sbindir$ac_delim
+libexecdir!$libexecdir$ac_delim
+datarootdir!$datarootdir$ac_delim
+datadir!$datadir$ac_delim
+sysconfdir!$sysconfdir$ac_delim
+sharedstatedir!$sharedstatedir$ac_delim
+localstatedir!$localstatedir$ac_delim
+includedir!$includedir$ac_delim
+oldincludedir!$oldincludedir$ac_delim
+docdir!$docdir$ac_delim
+infodir!$infodir$ac_delim
+htmldir!$htmldir$ac_delim
+dvidir!$dvidir$ac_delim
+pdfdir!$pdfdir$ac_delim
+psdir!$psdir$ac_delim
+libdir!$libdir$ac_delim
+localedir!$localedir$ac_delim
+mandir!$mandir$ac_delim
+DEFS!$DEFS$ac_delim
+ECHO_C!$ECHO_C$ac_delim
+ECHO_N!$ECHO_N$ac_delim
+ECHO_T!$ECHO_T$ac_delim
+LIBS!$LIBS$ac_delim
+build_alias!$build_alias$ac_delim
+host_alias!$host_alias$ac_delim
+target_alias!$target_alias$ac_delim
+build!$build$ac_delim
+build_cpu!$build_cpu$ac_delim
+build_vendor!$build_vendor$ac_delim
+build_os!$build_os$ac_delim
+host!$host$ac_delim
+host_cpu!$host_cpu$ac_delim
+host_vendor!$host_vendor$ac_delim
+host_os!$host_os$ac_delim
+target!$target$ac_delim
+target_cpu!$target_cpu$ac_delim
+target_vendor!$target_vendor$ac_delim
+target_os!$target_os$ac_delim
+SED!$SED$ac_delim
+AWK!$AWK$ac_delim
+CC!$CC$ac_delim
+CFLAGS!$CFLAGS$ac_delim
+LDFLAGS!$LDFLAGS$ac_delim
+CPPFLAGS!$CPPFLAGS$ac_delim
+ac_ct_CC!$ac_ct_CC$ac_delim
+EXEEXT!$EXEEXT$ac_delim
+OBJEXT!$OBJEXT$ac_delim
+CPP!$CPP$ac_delim
+GREP!$GREP$ac_delim
+EGREP!$EGREP$ac_delim
+INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim
+INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim
+INSTALL_DATA!$INSTALL_DATA$ac_delim
+LN_S!$LN_S$ac_delim
+SET_MAKE!$SET_MAKE$ac_delim
+RANLIB!$RANLIB$ac_delim
+CFLOW_CMD!$CFLOW_CMD$ac_delim
+CSCOPE_CMD!$CSCOPE_CMD$ac_delim
+ALLOCA!$ALLOCA$ac_delim
+LIBOBJS!$LIBOBJS$ac_delim
+POW_LIB!$POW_LIB$ac_delim
+LCOV!$LCOV$ac_delim
+GENHTML!$GENHTML$ac_delim
+LVM2CMD_LIB!$LVM2CMD_LIB$ac_delim
+MSGFMT!$MSGFMT$ac_delim
+MODPROBE_CMD!$MODPROBE_CMD$ac_delim
+BUILD_DMEVENTD!$BUILD_DMEVENTD$ac_delim
+CLDFLAGS!$CLDFLAGS$ac_delim
+CLDNOWHOLEARCHIVE!$CLDNOWHOLEARCHIVE$ac_delim
+CLDWHOLEARCHIVE!$CLDWHOLEARCHIVE$ac_delim
+CLUSTER!$CLUSTER$ac_delim
+CLVMD!$CLVMD$ac_delim
+CMDLIB!$CMDLIB$ac_delim
+COPTIMISE_FLAG!$COPTIMISE_FLAG$ac_delim
+DEBUG!$DEBUG$ac_delim
+DEVMAPPER!$DEVMAPPER$ac_delim
+DMEVENTD!$DMEVENTD$ac_delim
+DM_COMPAT!$DM_COMPAT$ac_delim
+DM_DEVICE_GID!$DM_DEVICE_GID$ac_delim
+DM_DEVICE_MODE!$DM_DEVICE_MODE$ac_delim
+DM_DEVICE_UID!$DM_DEVICE_UID$ac_delim
+DM_IOCTLS!$DM_IOCTLS$ac_delim
+DM_LIB_VERSION!$DM_LIB_VERSION$ac_delim
+DM_LIB_PATCHLEVEL!$DM_LIB_PATCHLEVEL$ac_delim
+FSADM!$FSADM$ac_delim
+GROUP!$GROUP$ac_delim
+_ACEOF
+
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
+    break
+  elif $ac_last_try; then
+    { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+  ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+  ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+CEOF$ac_eof
+_ACEOF
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  cat >conf$$subs.sed <<_ACEOF
+HAVE_LIBDL!$HAVE_LIBDL$ac_delim
+HAVE_REALTIME!$HAVE_REALTIME$ac_delim
+HAVE_SELINUX!$HAVE_SELINUX$ac_delim
+INTL!$INTL$ac_delim
+INTL_PACKAGE!$INTL_PACKAGE$ac_delim
+JOBS!$JOBS$ac_delim
+LDDEPS!$LDDEPS$ac_delim
+LIB_SUFFIX!$LIB_SUFFIX$ac_delim
+LOCALEDIR!$LOCALEDIR$ac_delim
+LVM1!$LVM1$ac_delim
+LVM1_FALLBACK!$LVM1_FALLBACK$ac_delim
+CONFDIR!$CONFDIR$ac_delim
+LVM_VERSION!$LVM_VERSION$ac_delim
+MIRRORS!$MIRRORS$ac_delim
+OWNER!$OWNER$ac_delim
+PKGCONFIG!$PKGCONFIG$ac_delim
+POOL!$POOL$ac_delim
+SNAPSHOTS!$SNAPSHOTS$ac_delim
+STATICDIR!$STATICDIR$ac_delim
+STATIC_LINK!$STATIC_LINK$ac_delim
+LIB_PTHREAD!$LIB_PTHREAD$ac_delim
+interface!$interface$ac_delim
+kerneldir!$kerneldir$ac_delim
+missingkernel!$missingkernel$ac_delim
+kernelvsn!$kernelvsn$ac_delim
+tmpdir!$tmpdir$ac_delim
+usrlibdir!$usrlibdir$ac_delim
+usrsbindir!$usrsbindir$ac_delim
+LTLIBOBJS!$LTLIBOBJS$ac_delim
+_ACEOF
+
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 29; then
+    break
+  elif $ac_last_try; then
+    { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+  ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+  ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-2.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+:end
+s/|#_!!_#|//g
+CEOF$ac_eof
+_ACEOF
+
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[	 ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+fi # test -n "$CONFIG_FILES"
+
+
+for ac_tag in  :F $CONFIG_FILES  :H $CONFIG_HEADERS
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
+echo "$as_me: error: Invalid tag $ac_tag." >&2;}
+   { (exit 1); exit 1; }; };;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+   { (exit 1); exit 1; }; };;
+      esac
+      ac_file_inputs="$ac_file_inputs $ac_f"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input="Generated from "`IFS=:
+	  echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    fi
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$tmp/stdin";;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  { as_dir="$ac_dir"
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+   { (exit 1); exit 1; }; }; }
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+  ac_MKDIR_P=$MKDIR_P
+  case $MKDIR_P in
+  [\\/$]* | ?:[\\/]* ) ;;
+  */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+case `sed -n '/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+' $ac_file_inputs` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+    s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF
+  sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s&@configure_input@&$configure_input&;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" >$tmp/out
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+  { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&5
+echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&2;}
+
+  rm -f "$tmp/stdin"
+  case $ac_file in
+  -) cat "$tmp/out"; rm -f "$tmp/out";;
+  *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
+  esac
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+_ACEOF
+
+# Transform confdefs.h into a sed script `conftest.defines', that
+# substitutes the proper values into config.h.in to produce config.h.
+rm -f conftest.defines conftest.tail
+# First, append a space to every undef/define line, to ease matching.
+echo 's/$/ /' >conftest.defines
+# Then, protect against being on the right side of a sed subst, or in
+# an unquoted here document, in config.status.  If some macros were
+# called several times there might be several #defines for the same
+# symbol, which is useless.  But do not sort them, since the last
+# AC_DEFINE must be honored.
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where
+# NAME is the cpp macro being defined, VALUE is the value it is being given.
+# PARAMS is the parameter list in the macro definition--in most cases, it's
+# just an empty string.
+ac_dA='s,^\\([	 #]*\\)[^	 ]*\\([	 ]*'
+ac_dB='\\)[	 (].*,\\1define\\2'
+ac_dC=' '
+ac_dD=' ,'
+
+uniq confdefs.h |
+  sed -n '
+	t rset
+	:rset
+	s/^[	 ]*#[	 ]*define[	 ][	 ]*//
+	t ok
+	d
+	:ok
+	s/[\\&,]/\\&/g
+	s/^\('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p
+	s/^\('"$ac_word_re"'\)[	 ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p
+  ' >>conftest.defines
+
+# Remove the space that was appended to ease matching.
+# Then replace #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+# (The regexp can be short, since the line contains either #define or #undef.)
+echo 's/ $//
+s,^[	 #]*u.*,/* & */,' >>conftest.defines
+
+# Break up conftest.defines:
+ac_max_sed_lines=50
+
+# First sed command is:	 sed -f defines.sed $ac_file_inputs >"$tmp/out1"
+# Second one is:	 sed -f defines.sed "$tmp/out1" >"$tmp/out2"
+# Third one will be:	 sed -f defines.sed "$tmp/out2" >"$tmp/out1"
+# et cetera.
+ac_in='$ac_file_inputs'
+ac_out='"$tmp/out1"'
+ac_nxt='"$tmp/out2"'
+
+while :
+do
+  # Write a here document:
+    cat >>$CONFIG_STATUS <<_ACEOF
+    # First, check the format of the line:
+    cat >"\$tmp/defines.sed" <<\\CEOF
+/^[	 ]*#[	 ]*undef[	 ][	 ]*$ac_word_re[	 ]*\$/b def
+/^[	 ]*#[	 ]*define[	 ][	 ]*$ac_word_re[(	 ]/b def
+b
+:def
+_ACEOF
+  sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS
+  echo 'CEOF
+    sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS
+  ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in
+  sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail
+  grep . conftest.tail >/dev/null || break
+  rm -f conftest.defines
+  mv conftest.tail conftest.defines
+done
+rm -f conftest.defines conftest.tail
+
+echo "ac_result=$ac_in" >>$CONFIG_STATUS
+cat >>$CONFIG_STATUS <<\_ACEOF
+  if test x"$ac_file" != x-; then
+    echo "/* $configure_input  */" >"$tmp/config.h"
+    cat "$ac_result" >>"$tmp/config.h"
+    if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then
+      { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f $ac_file
+      mv "$tmp/config.h" $ac_file
+    fi
+  else
+    echo "/* $configure_input  */"
+    cat "$ac_result"
+  fi
+  rm -f "$tmp/out12"
+ ;;
+
+
+  esac
+
+done # for ac_tag
+
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
+
+
+if test x$ODIRECT != xyes; then
+  { echo "$as_me:$LINENO: WARNING: Warning: O_DIRECT disabled: low-memory pvmove may lock up" >&5
+echo "$as_me: WARNING: Warning: O_DIRECT disabled: low-memory pvmove may lock up" >&2;}
+fi
Index: src/external/gpl2/lvm2tools/dist/configure.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/configure.in
diff -N src/external/gpl2/lvm2tools/dist/configure.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/configure.in	12 Dec 2008 16:32:57 -0000	1.1.1.1.2.1
@@ -0,0 +1,815 @@
+###############################################################################
+## Copyright (C) 2000-2004 Sistina Software, Inc. All rights reserved.
+## Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+##
+## This copyrighted material is made available to anyone wishing to use,
+## modify, copy, or redistribute it subject to the terms and conditions
+## of the GNU General Public License v.2.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software Foundation,
+## Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+################################################################################
+
+AC_PREREQ(2.57)
+################################################################################
+dnl -- Process this file with autoconf to produce a configure script.
+AC_INIT
+AC_CONFIG_SRCDIR([lib/device/dev-cache.h])
+AC_CONFIG_HEADERS([lib/misc/configure.h])
+
+################################################################################
+dnl -- Setup the directory where autoconf has auxilary files
+AC_CONFIG_AUX_DIR(autoconf)
+
+################################################################################
+dnl -- Get system type
+AC_CANONICAL_TARGET([])
+
+case "$host_os" in
+	linux*)
+		COPTIMISE_FLAG="-O2"
+		CLDFLAGS="$CLDFLAGS -Wl,--version-script,.export.sym"
+		CLDWHOLEARCHIVE="-Wl,-whole-archive"
+		CLDNOWHOLEARCHIVE="-Wl,-no-whole-archive"
+		LDDEPS="$LDDEPS .export.sym"
+		LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
+		LIB_SUFFIX=so
+		DEVMAPPER=yes
+		ODIRECT=yes
+		DM_IOCTLS=yes
+		SELINUX=yes
+		REALTIME=yes
+		CLUSTER=internal
+		FSADM=yes
+		;;
+	darwin*)
+		CFLAGS="$CFLAGS -no-cpp-precomp -fno-common"
+		COPTIMISE_FLAG="-O2"
+		CLDFLAGS="$CLDFLAGS"
+		CLDWHOLEARCHIVE="-all_load"
+		CLDNOWHOLEARCHIVE=
+		LIB_SUFFIX=dylib
+		DEVMAPPER=yes
+		ODIRECT=no
+		DM_IOCTLS=no
+		SELINUX=no
+		REALTIME=no
+		CLUSTER=none
+		FSADM=no
+		;;
+esac
+
+################################################################################
+dnl -- Checks for programs.
+AC_PROG_SED
+AC_PROG_AWK
+AC_PROG_CC
+
+dnl probably no longer needed in 2008, but...
+AC_PROG_GCC_TRADITIONAL
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+AC_PROG_MKDIR_P
+AC_PROG_RANLIB
+AC_PATH_PROG(CFLOW_CMD, cflow)
+AC_PATH_PROG(CSCOPE_CMD, cscope)
+
+################################################################################
+dnl -- Check for header files.
+AC_HEADER_DIRENT
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_HEADER_TIME
+
+AC_CHECK_HEADERS([locale.h stddef.h syslog.h sys/file.h sys/time.h assert.h \
+  libgen.h signal.h sys/mman.h sys/resource.h sys/utsname.h sys/wait.h time.h], ,
+  [AC_MSG_ERROR(bailing out)])
+
+case "$host_os" in
+	linux*)
+		AC_CHECK_HEADERS(asm/byteorder.h linux/fs.h malloc.h,,AC_MSG_ERROR(bailing out)) ;;
+	darwin*)
+		AC_CHECK_HEADERS(machine/endian.h sys/disk.h,,AC_MSG_ERROR(bailing out)) ;;
+esac
+
+AC_CHECK_HEADERS([ctype.h dirent.h errno.h fcntl.h getopt.h inttypes.h limits.h \
+  stdarg.h stdio.h stdlib.h string.h sys/ioctl.h sys/param.h sys/stat.h \
+  sys/types.h unistd.h], , [AC_MSG_ERROR(bailing out)])
+AC_CHECK_HEADERS(termios.h sys/statvfs.h)
+
+################################################################################
+dnl -- Check for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_C_INLINE
+AC_CHECK_MEMBERS([struct stat.st_rdev])
+AC_TYPE_OFF_T
+AC_TYPE_PID_T
+AC_TYPE_SIGNAL
+AC_TYPE_SIZE_T
+AC_TYPE_MODE_T
+AC_CHECK_MEMBERS([struct stat.st_rdev])
+AC_STRUCT_TM
+
+################################################################################
+dnl -- Check for functions
+AC_CHECK_FUNCS([gethostname getpagesize memset mkdir rmdir munmap setlocale \
+  strcasecmp strchr strdup strncasecmp strerror strrchr strstr strtol strtoul \
+  uname], , [AC_MSG_ERROR(bailing out)])
+AC_FUNC_ALLOCA
+AC_FUNC_CLOSEDIR_VOID
+AC_FUNC_FORK
+AC_FUNC_LSTAT
+AC_FUNC_MALLOC
+AC_FUNC_MEMCMP
+AC_FUNC_MMAP
+AC_FUNC_STAT
+AC_FUNC_STRTOD
+AC_FUNC_VPRINTF
+
+################################################################################
+dnl -- Prefix is /usr by default, the exec_prefix default is setup later
+AC_PREFIX_DEFAULT(/usr)
+
+################################################################################
+dnl -- Setup the ownership of the files
+AC_MSG_CHECKING(file owner)
+OWNER="root"
+
+AC_ARG_WITH(user,
+  [  --with-user=USER        Set the owner of installed files [[USER=root]] ],
+  [ OWNER="$withval" ])
+AC_MSG_RESULT($OWNER)
+
+if test x$OWNER != x; then
+	OWNER="-o $OWNER"
+fi
+
+################################################################################
+dnl -- Setup the group ownership of the files
+AC_MSG_CHECKING(group owner)
+GROUP="root"
+AC_ARG_WITH(group,
+  [  --with-group=GROUP      Set the group owner of installed files [[GROUP=root]] ],
+  [ GROUP="$withval" ])
+AC_MSG_RESULT($GROUP)
+
+if test x$GROUP != x; then
+	GROUP="-g $GROUP"
+fi
+
+################################################################################
+dnl -- Setup device node ownership
+AC_MSG_CHECKING(device node uid)
+
+AC_ARG_WITH(device-uid,
+  [  --with-device-uid=UID   Set the owner used for new device nodes [[UID=0]] ],
+  [ DM_DEVICE_UID="$withval" ], [ DM_DEVICE_UID="0" ] )
+AC_MSG_RESULT($DM_DEVICE_UID)
+
+################################################################################
+dnl -- Setup device group ownership
+AC_MSG_CHECKING(device node gid)
+
+AC_ARG_WITH(device-gid,
+  [  --with-device-gid=UID   Set the group used for new device nodes [[GID=0]] ],
+  [ DM_DEVICE_GID="$withval" ], [ DM_DEVICE_GID="0" ] )
+AC_MSG_RESULT($DM_DEVICE_GID)
+
+################################################################################
+dnl -- Setup device mode
+AC_MSG_CHECKING(device node mode)
+
+AC_ARG_WITH(device-mode,
+  [  --with-device-mode=MODE Set the mode used for new device nodes [[MODE=0600]] ],
+  [ DM_DEVICE_MODE="$withval" ], [ DM_DEVICE_MODE="0600" ] )
+AC_MSG_RESULT($DM_DEVICE_MODE)
+
+################################################################################
+dnl -- LVM1 tool fallback option
+AC_MSG_CHECKING(whether to enable lvm1 fallback)
+AC_ARG_ENABLE(lvm1_fallback, [  --enable-lvm1_fallback  Use this to fall back and use LVM1 binaries if
+                          device-mapper is missing from the kernel],  LVM1_FALLBACK=$enableval, LVM1_FALLBACK=no)
+AC_MSG_RESULT($LVM1_FALLBACK)
+
+if test x$LVM1_FALLBACK = xyes; then
+	AC_DEFINE([LVM1_FALLBACK], 1, [Define to 1 if 'lvm' should fall back to using LVM1 binaries if device-mapper is missing from the kernel])
+fi
+
+################################################################################
+dnl -- format1 inclusion type
+AC_MSG_CHECKING(whether to include support for lvm1 metadata)
+AC_ARG_WITH(lvm1,
+  [  --with-lvm1=TYPE        LVM1 metadata support: internal/shared/none
+                          [TYPE=internal] ],
+  [ LVM1="$withval" ],
+  [ LVM1="internal" ])
+AC_MSG_RESULT($LVM1)
+
+if [[ "x$LVM1" != xnone -a "x$LVM1" != xinternal -a "x$LVM1" != xshared ]];
+ then  AC_MSG_ERROR(
+--with-lvm1 parameter invalid
+)
+fi;
+
+if test x$LVM1 = xinternal; then
+	AC_DEFINE([LVM1_INTERNAL], 1, [Define to 1 to include built-in support for LVM1 metadata.])
+fi
+
+################################################################################
+dnl -- format_pool inclusion type
+AC_MSG_CHECKING(whether to include support for GFS pool metadata)
+AC_ARG_WITH(pool,
+  [  --with-pool=TYPE        GFS pool read-only support: internal/shared/none
+                          [TYPE=internal] ],
+  [ POOL="$withval" ],
+  [ POOL="internal" ])
+AC_MSG_RESULT($POOL)
+
+if [[ "x$POOL" != xnone -a "x$POOL" != xinternal -a "x$POOL" != xshared ]];
+ then  AC_MSG_ERROR(
+--with-pool parameter invalid
+)
+fi;
+
+if test x$POOL = xinternal; then
+	AC_DEFINE([POOL_INTERNAL], 1, [Define to 1 to include built-in support for GFS pool metadata.])
+fi
+
+################################################################################
+dnl -- cluster_locking inclusion type
+AC_MSG_CHECKING(whether to include support for cluster locking)
+AC_ARG_WITH(cluster,
+  [  --with-cluster=TYPE     Cluster LVM locking support: internal/shared/none
+                          [TYPE=internal] ],
+  [ CLUSTER="$withval" ])
+AC_MSG_RESULT($CLUSTER)
+
+if [[ "x$CLUSTER" != xnone -a "x$CLUSTER" != xinternal -a "x$CLUSTER" != xshared ]];
+ then  AC_MSG_ERROR(
+--with-cluster parameter invalid
+)
+fi;
+
+if test x$CLUSTER = xinternal; then
+	AC_DEFINE([CLUSTER_LOCKING_INTERNAL], 1, [Define to 1 to include built-in support for clustered LVM locking.])
+fi
+
+################################################################################
+dnl -- snapshots inclusion type
+AC_MSG_CHECKING(whether to include snapshots)
+AC_ARG_WITH(snapshots,
+  [  --with-snapshots=TYPE   Snapshot support: internal/shared/none
+                          [TYPE=internal] ],
+  [ SNAPSHOTS="$withval" ],
+  [ SNAPSHOTS="internal" ])
+AC_MSG_RESULT($SNAPSHOTS)
+
+if [[ "x$SNAPSHOTS" != xnone -a "x$SNAPSHOTS" != xinternal -a "x$SNAPSHOTS" != xshared ]];
+ then  AC_MSG_ERROR(
+--with-snapshots parameter invalid
+)
+fi;
+
+if test x$SNAPSHOTS = xinternal; then
+	AC_DEFINE([SNAPSHOT_INTERNAL], 1, [Define to 1 to include built-in support for snapshots.])
+fi
+
+################################################################################
+dnl -- mirrors inclusion type
+AC_MSG_CHECKING(whether to include mirrors)
+AC_ARG_WITH(mirrors,
+  [  --with-mirrors=TYPE     Mirror support: internal/shared/none
+                          [TYPE=internal] ],
+  [ MIRRORS="$withval" ],
+  [ MIRRORS="internal" ])
+AC_MSG_RESULT($MIRRORS)
+
+if [[ "x$MIRRORS" != xnone -a "x$MIRRORS" != xinternal -a "x$MIRRORS" != xshared ]];
+ then  AC_MSG_ERROR(
+--with-mirrors parameter invalid
+)
+fi;
+
+if test x$MIRRORS = xinternal; then
+	AC_DEFINE([MIRRORED_INTERNAL], 1, [Define to 1 to include built-in support for mirrors.])
+fi
+
+################################################################################
+dnl -- Disable readline
+AC_MSG_CHECKING(whether to enable readline)
+AC_ARG_ENABLE([readline],
+  [  --disable-readline      Disable readline support],
+  [READLINE=$enableval], [READLINE=maybe])
+AC_MSG_RESULT($READLINE)
+
+################################################################################
+dnl -- Disable realtime clock support
+AC_MSG_CHECKING(whether to enable realtime support)
+AC_ARG_ENABLE(realtime, [  --disable-realtime      Disable realtime clock support],
+REALTIME=$enableval)
+AC_MSG_RESULT($REALTIME)
+
+################################################################################
+dnl -- Build cluster LVM daemon
+AC_MSG_CHECKING(whether to build cluster LVM daemon)
+AC_ARG_WITH(clvmd,
+  [  --with-clvmd=TYPE       Build cluster LVM Daemon: cman/gulm/none/all
+                          [TYPE=none] ],
+  [ CLVMD="$withval" ],
+  [ CLVMD="none" ])
+if test x$CLVMD = xyes; then
+	CLVMD=all
+fi
+AC_MSG_RESULT($CLVMD)
+
+dnl -- If clvmd enabled without cluster locking, automagically include it
+if  test x$CLVMD != xnone && test x$CLUSTER = xnone; then
+	CLUSTER=internal
+fi
+
+################################################################################
+dnl -- Enable debugging
+AC_MSG_CHECKING(whether to enable debugging)
+AC_ARG_ENABLE(debug,    [  --enable-debug          Enable debugging],
+  DEBUG=$enableval, DEBUG=no)
+AC_MSG_RESULT($DEBUG)
+
+dnl -- Normally turn off optimisation for debug builds
+if test x$DEBUG = xyes; then
+	COPTIMISE_FLAG=
+else
+	CSCOPE_CMD=
+fi
+
+################################################################################
+dnl -- Override optimisation
+AC_MSG_CHECKING(for C optimisation flag)
+AC_ARG_WITH(optimisation,
+  [  --with-optimisation=OPT C optimisation flag [[OPT=-O2]] ],
+  [ COPTIMISE_FLAG="$withval" ])
+AC_MSG_RESULT($COPTIMISE_FLAG)
+
+################################################################################
+dnl -- Enable profiling
+AC_MSG_CHECKING(whether to gather gcov profiling data)
+AC_ARG_ENABLE(profiling,
+  AC_HELP_STRING(--enable-profiling, [Gather gcov profiling data]),
+  PROFILING=$enableval, PROFILING=no)
+AC_MSG_RESULT($PROFILING)
+
+if test "x$PROFILING" = xyes; then
+  COPTIMISE_FLAG="$COPTIMISE_FLAG -fprofile-arcs -ftest-coverage"
+  AC_PATH_PROG(LCOV, lcov, no)
+  AC_PATH_PROG(GENHTML, genhtml, no)
+  if test "$LCOV" = no -o "$GENHTML" = no ; then
+    AC_MSG_ERROR([lcov and genhtml are required for profiling])
+  fi
+fi
+
+################################################################################
+dnl -- Disable devmapper
+AC_MSG_CHECKING(whether to use device-mapper)
+AC_ARG_ENABLE(devmapper, [  --disable-devmapper     Disable LVM2 device-mapper interaction],
+DEVMAPPER=$enableval)
+AC_MSG_RESULT($DEVMAPPER)
+
+if test x$DEVMAPPER = xyes; then
+	AC_DEFINE([DEVMAPPER_SUPPORT], 1, [Define to 1 to enable LVM2 device-mapper interaction.])
+fi
+
+################################################################################
+dnl -- Compatibility mode
+AC_ARG_ENABLE(compat,   [  --enable-compat         Enable support for old device-mapper versions],
+  DM_COMPAT=$enableval, DM_COMPAT=no)
+
+################################################################################
+dnl -- Disable ioctl
+AC_ARG_ENABLE(ioctl,   [  --disable-driver        Disable calls to device-mapper in the kernel],
+  DM_IOCTLS=$enableval)
+
+################################################################################
+dnl -- Disable O_DIRECT
+AC_MSG_CHECKING(whether to enable O_DIRECT)
+AC_ARG_ENABLE(o_direct, [  --disable-o_direct      Disable O_DIRECT],
+ODIRECT=$enableval)
+AC_MSG_RESULT($ODIRECT)
+
+if test x$ODIRECT = xyes; then
+	AC_DEFINE([O_DIRECT_SUPPORT], 1, [Define to 1 to enable O_DIRECT support.])
+fi
+
+################################################################################
+dnl -- Enable cmdlib
+AC_MSG_CHECKING(whether to compile liblvm2cmd.so)
+AC_ARG_ENABLE(cmdlib, [  --enable-cmdlib         Build shared command library],
+CMDLIB=$enableval, CMDLIB=no)
+AC_MSG_RESULT($CMDLIB)
+AC_SUBST([LVM2CMD_LIB])
+test x$CMDLIB = xyes \
+  && LVM2CMD_LIB=-llvm2cmd \
+  || LVM2CMD_LIB=
+
+################################################################################
+dnl -- Enable pkg-config
+AC_ARG_ENABLE(pkgconfig,   [  --enable-pkgconfig      Install pkgconfig support],
+  PKGCONFIG=$enableval, PKGCONFIG=no)
+
+################################################################################
+dnl -- Enable fsadm
+AC_MSG_CHECKING(whether to install fsadm)
+AC_ARG_ENABLE(fsadm, [  --enable-fsadm          Enable fsadm],
+FSADM=$enableval)
+AC_MSG_RESULT($FSADM)
+
+################################################################################
+dnl -- enable dmeventd handling
+AC_MSG_CHECKING(whether to use dmeventd)
+AC_ARG_ENABLE(dmeventd, [  --enable-dmeventd       Enable the device-mapper event daemon],
+DMEVENTD=$enableval)
+AC_MSG_RESULT($DMEVENTD)
+
+BUILD_DMEVENTD=$DMEVENTD
+
+dnl -- dmeventd currently requires internal mirror support
+if test x$DMEVENTD = xyes; then
+   if test x$MIRRORS != xinternal; then
+      AC_MSG_ERROR(
+	--enable-dmeventd currently requires --with-mirrors=internal
+      )
+   fi
+   if test x$CMDLIB = xno; then
+      AC_MSG_ERROR(
+        --enable-dmeventd requires --enable-cmdlib to be used as well
+      )
+   fi
+fi
+
+if test x$DMEVENTD = xyes; then
+	AC_DEFINE([DMEVENTD], 1, [Define to 1 to enable the device-mapper event daemon.])
+fi
+
+################################################################################
+dnl -- getline included in recent libc
+
+AC_CHECK_LIB(c, getline, AC_DEFINE([HAVE_GETLINE], 1,
+  [Define to 1 if getline is available.]))
+
+################################################################################
+dnl -- canonicalize_file_name included in recent libc
+
+AC_CHECK_LIB(c, canonicalize_file_name,
+  AC_DEFINE([HAVE_CANONICALIZE_FILE_NAME], 1,
+    [Define to 1 if canonicalize_file_name is available.]))
+
+################################################################################
+dnl -- Clear default exec_prefix - install into /sbin rather than /usr/sbin
+if [[ "x$exec_prefix" = xNONE -a "x$prefix" = xNONE ]];
+ then  exec_prefix="";
+fi;
+
+################################################################################
+dnl -- Check for termcap (Shamelessly copied from parted 1.4.17)
+if test x$READLINE != xno; then
+	AC_SEARCH_LIBS([tgetent], [ncurses curses termcap termlib],
+	  [tg_found=yes], [tg_found=no])
+	test x$READLINE:$tg_found = xyes:no &&
+	  AC_MSG_ERROR(
+termcap could not be found which is required for the
+--enable-readline option (which is enabled by default).  Either disable readline
+support with --disable-readline or download and install termcap from:
+	ftp.gnu.org/gnu/termcap
+Note: if you are using precompiled packages you will also need the development
+  package as well (which may be called termcap-devel or something similar).
+Note: (n)curses also seems to work as a substitute for termcap.  This was
+  not found either - but you could try installing that as well.
+)
+fi
+
+################################################################################
+dnl -- Check for dlopen
+AC_CHECK_LIB(dl, dlopen, HAVE_LIBDL=yes, HAVE_LIBDL=no)
+
+if [[ "x$HAVE_LIBDL" = xyes ]]; then
+	AC_DEFINE([HAVE_LIBDL], 1, [Define to 1 if dynamic libraries are available.])
+	LIBS="-ldl $LIBS"
+else
+	HAVE_LIBDL=no
+fi
+
+################################################################################
+dnl -- Check for shared/static conflicts
+if [[ \( "x$LVM1" = xshared -o "x$POOL" = xshared -o "x$CLUSTER" = xshared \
+      -o "x$SNAPSHOTS" = xshared -o "x$MIRRORS" = xshared \
+      \) -a "x$STATIC_LINK" = xyes ]];
+ then  AC_MSG_ERROR(
+Features cannot be 'shared' when building statically
+)
+fi
+
+################################################################################
+dnl -- Enables statically-linked tools
+AC_MSG_CHECKING(whether to use static linking)
+AC_ARG_ENABLE(static_link,
+  [  --enable-static_link    Use this to link the tools to their libraries
+                          statically.  Default is dynamic linking],
+  STATIC_LINK=$enableval, STATIC_LINK=no)
+AC_MSG_RESULT($STATIC_LINK)
+
+################################################################################
+dnl -- Disable selinux
+AC_MSG_CHECKING(whether to enable selinux support)
+AC_ARG_ENABLE(selinux, [  --disable-selinux       Disable selinux support],
+  SELINUX=$enableval)
+AC_MSG_RESULT($SELINUX)
+
+################################################################################
+dnl -- Check for selinux
+if test x$SELINUX = xyes; then
+	AC_CHECK_LIB(sepol, sepol_check_context, HAVE_SEPOL=yes, HAVE_SEPOL=no)
+
+	if test x$HAVE_SEPOL = xyes; then
+		AC_DEFINE([HAVE_SEPOL], 1,
+		  [Define to 1 if sepol_check_context is available.])
+		LIBS="-lsepol $LIBS"
+	fi
+
+	AC_CHECK_LIB(selinux, is_selinux_enabled, HAVE_SELINUX=yes, HAVE_SELINUX=no)
+
+	if test x$HAVE_SELINUX = xyes; then
+		AC_DEFINE([HAVE_SELINUX], 1, [Define to 1 to include support for selinux.])
+		LIBS="-lselinux $LIBS"
+	else
+		AC_MSG_WARN(Disabling selinux)
+	fi
+
+	# With --enable-static_link and selinux enabled, linking
+	# fails on at least Debian unstable due to unsatisfied references
+	# to pthread_mutex_lock and _unlock.  See if we need -lpthread.
+	if test "$STATIC_LINK-$HAVE_SELINUX" = yes-yes; then
+		lvm_saved_libs=$LIBS
+		LIBS="$LIBS -static"
+		AC_SEARCH_LIBS([pthread_mutex_lock], [pthread],
+		  [test "$ac_cv_search_pthread_mutex_lock" = "none required" ||
+				LIB_PTHREAD=-lpthread])
+		LIBS=$lvm_saved_libs
+	fi
+fi
+
+################################################################################
+dnl -- Check for realtime clock support
+if test x$REALTIME = xyes; then
+	AC_CHECK_LIB(rt, clock_gettime, HAVE_REALTIME=yes, HAVE_REALTIME=no)
+
+	if test x$HAVE_REALTIME = xyes; then
+		AC_DEFINE([HAVE_REALTIME], 1, [Define to 1 to include support for realtime clock.])
+		LIBS="-lrt $LIBS"
+	else
+		AC_MSG_WARN(Disabling realtime clock)
+	fi
+fi
+
+################################################################################
+dnl -- Check for getopt
+AC_CHECK_HEADERS(getopt.h, AC_DEFINE([HAVE_GETOPTLONG], 1, [Define to 1 if getopt_long is available.]))
+
+################################################################################
+dnl -- Check for readline (Shamelessly copied from parted 1.4.17)
+if test x$READLINE != xno; then
+	rl_found=yes
+	AC_CHECK_LIB([readline], [readline], , [rl_found=no])
+	test x$READLINE:$rl_found = xyes:no &&
+	  AC_MSG_ERROR(
+GNU Readline could not be found which is required for the
+--enable-readline option (which is enabled by default).  Either disable readline
+support with --disable-readline or download and install readline from:
+	ftp.gnu.org/gnu/readline
+Note: if you are using precompiled packages you will also need the development
+package as well (which may be called readline-devel or something similar).
+)
+	if test $rl_found = yes; then
+		AC_CHECK_FUNCS([rl_completion_matches])
+		AC_DEFINE([READLINE_SUPPORT], 1,
+		  [Define to 1 to include the LVM readline shell.])
+	fi
+fi
+
+################################################################################
+dnl -- Internationalisation stuff
+AC_MSG_CHECKING(whether to enable internationalisation)
+AC_ARG_ENABLE(nls, [  --enable-nls            Enable Native Language Support],
+		INTL=$enableval, INTL=no)
+AC_MSG_RESULT($INTL)
+
+if test x$INTL = xyes; then
+# FIXME - Move this - can be device-mapper too
+	INTL_PACKAGE="lvm2"
+	AC_PATH_PROG(MSGFMT, msgfmt)
+	if [[ "x$MSGFMT" == x ]];
+		then  AC_MSG_ERROR(
+		msgfmt not found in path $PATH
+		)
+	fi;
+
+	AC_ARG_WITH(localedir,
+		    [  --with-localedir=DIR    Translation files in DIR [[PREFIX/share/locale]] ],
+		    [ LOCALEDIR="$withval" ],
+		    [ LOCALEDIR='${prefix}/share/locale' ])
+fi
+
+################################################################################
+AC_ARG_WITH(confdir,
+	    [  --with-confdir=DIR      Configuration files in DIR [/etc]],
+	    [ CONFDIR="$withval" ],
+	    [ CONFDIR='/etc' ])
+
+AC_ARG_WITH(staticdir,
+	    [  --with-staticdir=DIR    Static binary in DIR [EXEC_PREFIX/sbin]],
+	    [ STATICDIR="$withval" ],
+	    [ STATICDIR='${exec_prefix}/sbin' ])
+
+AC_ARG_WITH(usrlibdir,
+	    [  --with-usrlibdir=DIR],
+	    [ usrlibdir="$withval"],
+	    [ usrlibdir='${prefix}/lib' ])
+
+AC_ARG_WITH(usrsbindir,
+	    [  --with-usrsbindir=DIR],
+	    [ usrsbindir="$withval"],
+	    [ usrsbindir='${prefix}/sbin' ])
+
+################################################################################
+dnl -- Ensure additional headers required
+if test x$READLINE = xyes; then
+	AC_CHECK_HEADERS(readline/readline.h readline/history.h,,AC_MSG_ERROR(bailing out))
+fi
+
+if test x$CLVMD != xnone; then
+	AC_CHECK_HEADERS(mntent.h netdb.h netinet/in.h pthread.h search.h sys/mount.h sys/socket.h sys/uio.h sys/un.h utmpx.h,,AC_MSG_ERROR(bailing out))
+	AC_CHECK_FUNCS(dup2 getmntent memmove select socket,,AC_MSG_ERROR(bailing out))
+	AC_FUNC_GETMNTENT
+#	AC_FUNC_REALLOC
+	AC_FUNC_SELECT_ARGTYPES
+fi
+
+if test x$CLUSTER != xnone; then
+	AC_CHECK_HEADERS(sys/socket.h sys/un.h,,AC_MSG_ERROR(bailing out))
+	AC_CHECK_FUNCS(socket,,AC_MSG_ERROR(bailing out))
+fi
+
+if test x$HAVE_LIBDL = xyes; then
+	AC_CHECK_HEADERS(dlfcn.h,,AC_MSG_ERROR(bailing out))
+fi
+
+if test x$INTL = xyes; then
+	AC_CHECK_HEADERS(libintl.h,,AC_MSG_ERROR(bailing out))
+fi
+
+if test x$HAVE_SELINUX = xyes; then
+	AC_CHECK_HEADERS(selinux/selinux.h,,AC_MSG_ERROR(bailing out))
+fi
+
+################################################################################
+AC_PATH_PROG(MODPROBE_CMD, modprobe)
+
+if test x$MODPROBE_CMD != x; then
+	AC_DEFINE_UNQUOTED([MODPROBE_CMD], ["$MODPROBE_CMD"], [The path to 'modprobe', if available.])
+fi
+
+################################################################################
+dnl -- dmeventd pidfile and executable path
+AH_TEMPLATE(DMEVENTD_PIDFILE, [Path to dmeventd pidfile.])
+if test "$BUILD_DMEVENTD" = yes; then
+	AC_ARG_WITH(dmeventd-pidfile,
+		    [  --with-dmeventd-pidfile=PATH    dmeventd pidfile [[/var/run/dmeventd.pid]] ],
+		    [ AC_DEFINE_UNQUOTED(DMEVENTD_PIDFILE,"$withval") ],
+		    [ AC_DEFINE_UNQUOTED(DMEVENTD_PIDFILE,"/var/run/dmeventd.pid") ])
+fi
+
+AH_TEMPLATE(DMEVENTD_PATH, [Path to dmeventd binary.])
+if test "$BUILD_DMEVENTD" = yes; then
+        dmeventd_prefix="$exec_prefix"
+        if test "x$dmeventd_prefix" = "xNONE"; then
+                dmeventd_prefix="$prefix"
+        fi
+        if test "x$dmeventd_prefix" = "xNONE"; then
+                dmeventd_prefix=""
+        fi
+	AC_ARG_WITH(dmeventd-path,
+		    [  --with-dmeventd-path=PATH       dmeventd path [[${exec_prefix}/sbin/dmeventd]] ],
+		    [ AC_DEFINE_UNQUOTED(DMEVENTD_PATH,"$withval") ],
+		    [ AC_DEFINE_UNQUOTED(DMEVENTD_PATH,"$dmeventd_prefix/sbin/dmeventd") ])
+fi
+
+################################################################################
+dnl -- which kernel interface to use (ioctl only)
+AC_MSG_CHECKING(for kernel interface choice)
+AC_ARG_WITH(interface,
+  [  --with-interface=IFACE  Choose kernel interface (ioctl) [[ioctl]] ],
+  [ interface="$withval" ],
+  [ interface=ioctl ])
+if [[ "x$interface" != xioctl ]];
+then
+  AC_MSG_ERROR(--with-interface=ioctl required. fs no longer supported.)
+fi
+AC_MSG_RESULT($interface)
+
+################################################################################
+DM_LIB_VERSION="\"`cat VERSION_DM 2>/dev/null || echo Unknown`\""
+AC_DEFINE_UNQUOTED(DM_LIB_VERSION, $DM_LIB_VERSION, [Library version])
+
+DM_LIB_PATCHLEVEL=`cat VERSION_DM | awk -F '[[-. ]]' '{printf "%s.%s.%s",$1,$2,$3}'`
+
+LVM_VERSION="\"`cat VERSION 2>/dev/null || echo Unknown`\""
+
+################################################################################
+AC_SUBST(BUILD_DMEVENTD)
+AC_SUBST(CFLAGS)
+AC_SUBST(CFLOW_CMD)
+AC_SUBST(CLDFLAGS)
+AC_SUBST(CLDNOWHOLEARCHIVE)
+AC_SUBST(CLDWHOLEARCHIVE)
+AC_SUBST(CLUSTER)
+AC_SUBST(CLVMD)
+AC_SUBST(CMDLIB)
+AC_SUBST(COPTIMISE_FLAG)
+AC_SUBST(CSCOPE_CMD)
+AC_SUBST(DEBUG)
+AC_SUBST(DEVMAPPER)
+AC_SUBST(DMEVENTD)
+AC_SUBST(DM_COMPAT)
+AC_SUBST(DM_DEVICE_GID)
+AC_SUBST(DM_DEVICE_MODE)
+AC_SUBST(DM_DEVICE_UID)
+AC_SUBST(DM_IOCTLS)
+AC_SUBST(DM_LIB_VERSION)
+AC_SUBST(DM_LIB_PATCHLEVEL)
+AC_SUBST(FSADM)
+AC_SUBST(GROUP)
+AC_SUBST(HAVE_LIBDL)
+AC_SUBST(HAVE_REALTIME)
+AC_SUBST(HAVE_SELINUX)
+AC_SUBST(INTL)
+AC_SUBST(INTL_PACKAGE)
+AC_SUBST(JOBS)
+AC_SUBST(LDDEPS)
+AC_SUBST(LIBS)
+AC_SUBST(LIB_SUFFIX)
+AC_SUBST(LOCALEDIR)
+AC_SUBST(LVM1)
+AC_SUBST(LVM1_FALLBACK)
+AC_SUBST(CONFDIR)
+AC_SUBST(LVM_VERSION)
+AC_SUBST(MIRRORS)
+AC_SUBST(MSGFMT)
+AC_SUBST(OWNER)
+AC_SUBST(PKGCONFIG)
+AC_SUBST(POOL)
+AC_SUBST(SNAPSHOTS)
+AC_SUBST(STATICDIR)
+AC_SUBST(STATIC_LINK)
+AC_SUBST([LIB_PTHREAD])
+AC_SUBST(interface)
+AC_SUBST(kerneldir)
+AC_SUBST(missingkernel)
+AC_SUBST(kernelvsn)
+AC_SUBST(tmpdir)
+AC_SUBST(usrlibdir)
+AC_SUBST(usrsbindir)
+
+################################################################################
+dnl -- First and last lines should not contain files to generate in order to
+dnl -- keep utility scripts running properly
+AC_CONFIG_FILES([
+Makefile
+make.tmpl
+daemons/Makefile
+daemons/clvmd/Makefile
+daemons/dmeventd/Makefile
+daemons/dmeventd/libdevmapper-event.pc
+daemons/dmeventd/plugins/Makefile
+daemons/dmeventd/plugins/mirror/Makefile
+daemons/dmeventd/plugins/snapshot/Makefile
+doc/Makefile
+include/Makefile
+lib/Makefile
+lib/format1/Makefile
+lib/format_pool/Makefile
+lib/locking/Makefile
+lib/mirror/Makefile
+lib/snapshot/Makefile
+libdm/Makefile
+libdm/libdevmapper.pc
+man/Makefile
+po/Makefile
+scripts/Makefile
+test/Makefile
+tools/Makefile
+tools/version.h
+])
+AC_OUTPUT
+
+if test x$ODIRECT != xyes; then
+  AC_MSG_WARN(Warning: O_DIRECT disabled: low-memory pvmove may lock up)
+fi
Index: src/external/gpl2/lvm2tools/dist/lvm2netbsd
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lvm2netbsd
diff -N src/external/gpl2/lvm2tools/dist/lvm2netbsd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lvm2netbsd	12 Dec 2008 16:32:57 -0000	1.1.1.1.2.2
@@ -0,0 +1,116 @@
+#! /bin/sh
+#
+#	$NetBSD		$
+#
+# Copyright (c) 2003 The NetBSD Foundation, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# lvm2netbsd:  convert a file source tree into a
+# format suitable for import.  Works on current dir.
+# You can run this only once if you want it to work.
+#
+# configure.h file in lvm2tools/lib/ was generated with this command
+#
+# ./configure --with-cluster=none --with-snapshots=internal --with-clvmd=none 
+#   --with-lvm1=none --with-cluster=none --disable-readline --enable-o_direct 
+#   --enable-devmapper
+#
+# based on texinfo2netbsd
+#
+
+# edit this
+lvm2_vers='2.2.02.43'
+
+import_date=`date '+%m-%d-%y'`;
+#
+# (usually) NO NEED TO EDIT BELOW THIS LINE
+#
+
+### Wipe out stuff we don't want
+rm -f .cvsignore
+
+echo "Installing header files."
+(
+    cd include/
+    cp `cat .symlinks | xargs` .;
+
+    cat > version.h <<EOF
+#ifndef _LVM_VERSION_H
+#define LVM_VERSION "$lvm2_vers-cvs ($import_date)"
+#endif
+EOF
+    cd ../
+)
+echo done
+
+echo "Adding NetBSD RCS ID tags to lvm2 sources"
+
+### Add NetBSD RCS Id
+find . -type f -name '*.[chly]' -print | while read c; do
+	sed -e '1{/$NetBSD/!{i\
+/*	\$NetBSD\$	*/\
+
+};}
+/#ifndef[ 	]lint/{N;/FILE_RCSID/s/\n/\
+#if 0\
+/
+a\
+#else\
+__RCSID("\$NetBSD\$");\
+#endif
+}' $c > /tmp/file3$$
+mv /tmp/file3$$ $c && echo did source mods for $c
+done
+
+echo "Adding NetBSD RCS ID tags to manual pages"
+#### Add RCS tags to man pages
+find . -type f -name '*.[0-9].in' -print | while read m; do
+        base=`basename $m .in`
+	sed -e '1{/$NetBSD/!i\
+.\\"	\$NetBSD\$\
+.\\"
+
+}'	    -e 's/__CSECTION__/1/g' \
+	    -e 's/__FSECTION__/5/g' \
+	    -e 's/__VERSION__/'"${file_vers}/g" \
+	    -e 's,__MAGIC__,/usr/share/misc/magic,g' \
+            -e "s/#VERSION#/$lvm2_vers-cvs ($import_date)/" \
+	    $m > `dirname $m`/$base && echo did manpage mods for $base
+done
+
+echo done
+
+### Clean up any CVS directories that might be around.
+echo "cleaning up CVS residue."
+(
+        find . -type d -name "CVS" -print | xargs rm -r
+)
+echo done
+
+
+ver=`echo ${lvm2_vers} | sed -e 's/\./-/g'`
+echo You can import now.  Use the following command:
+echo cvs import src/external/gpl2/lvm2tools/dist FSF lvm2tools-${ver}
+
+exit 0
Index: src/external/gpl2/lvm2tools/dist/make.tmpl.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/make.tmpl.in
diff -N src/external/gpl2/lvm2tools/dist/make.tmpl.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/make.tmpl.in	12 Dec 2008 16:32:57 -0000	1.1.1.1.2.1
@@ -0,0 +1,261 @@
+# @configure_input@
+#
+# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+# Copyright (C) 2004, 2008 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+SHELL = /bin/sh
+
+@SET_MAKE@
+
+CC = @CC@
+RANLIB = @RANLIB@
+SHELL = /bin/sh
+INSTALL = @INSTALL@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+LCOV = @LCOV@
+GENHTML = @GENHTML@
+LN_S = @LN_S@
+SED = @SED@
+
+LIBS = @LIBS@
+DEFS += @DEFS@
+CFLAGS += @CFLAGS@
+CLDFLAGS += @CLDFLAGS@
+LDDEPS += @LDDEPS@
+LDFLAGS += @LDFLAGS@
+LIB_SUFFIX = @LIB_SUFFIX@
+
+# Setup directory variables
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = $(DESTDIR)@bindir@
+confdir = $(DESTDIR)@CONFDIR@/lvm
+includedir = $(DESTDIR)@includedir@
+libdir = $(DESTDIR)@libdir@
+usrlibdir = $(DESTDIR)@usrlibdir@
+sbindir = $(DESTDIR)@sbindir@
+usrsbindir = $(DESTDIR)@usrsbindir@
+infodir = $(DESTDIR)@infodir@
+mandir = $(DESTDIR)@mandir@
+localedir = $(DESTDIR)@LOCALEDIR@
+staticdir = $(DESTDIR)@STATICDIR@
+
+interface = @interface@
+interfacedir = $(top_srcdir)/libdm/$(interface)
+
+# setup misc variables
+# define the ownership variables for the binaries and man pages
+OWNER = @OWNER@
+GROUP = @GROUP@
+
+# The number of jobs to run, if blank, defaults to the make standard
+ifndef MAKEFLAGS
+MAKEFLAGS = @JOBS@
+endif
+
+.SUFFIXES: .c .d .o .so .a .po .pot .mo .dylib
+
+CFLAGS += -fPIC -Wall -Wundef -Wshadow -Wcast-align -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline -Wmissing-noreturn -Wformat-security
+
+#CFLAGS += -W -Wconversion -Wpointer-arith -Wredundant-decls -Wbad-function-cast -Wcast-qual
+#CFLAGS += -pedantic -std=gnu99
+
+CFLAGS += @COPTIMISE_FLAG@
+
+ifeq ("@DEBUG@", "yes")
+  CFLAGS += -g -fno-omit-frame-pointer
+  DEFS += -DDEBUG
+  DEFS += -DDEBUG_MEM
+endif
+
+ifeq ("@INTL@", "yes")
+  DEFS += -DINTL_PACKAGE=\"@INTL_PACKAGE@\" -DLOCALEDIR=\"@LOCALEDIR@\"
+endif
+
+LDFLAGS += -L$(top_srcdir)/libdm -L$(top_srcdir)/lib
+CLDFLAGS += -L$(top_srcdir)/libdm -L$(top_srcdir)/lib
+
+ifeq ("@DMEVENTD@", "yes")
+  LDFLAGS += -L$(top_srcdir)/daemons/dmeventd
+  CLDFLAGS += -L$(top_srcdir)/daemons/dmeventd
+endif
+
+ifeq ("@DM_COMPAT@", "yes")
+  DEFS += -DDM_COMPAT
+endif
+
+ifeq ("@DM_IOCTLS@", "yes")
+  DEFS += -DDM_IOCTLS
+endif
+
+#DEFS += -DDEBUG_POOL
+#DEFS += -DBOUNDS_CHECK
+
+#CFLAGS += -pg
+#LDFLAGS += -pg
+
+STRIP=
+#STRIP = -s
+
+LVM_VERSION := $(shell cat $(top_srcdir)/VERSION)
+
+LIB_VERSION_LVM := $(shell cat $(top_srcdir)/VERSION | \
+		     awk -F '.' '{printf "%s.%s",$$1,$$2}')
+
+LIB_VERSION_DM := $(shell cat $(top_srcdir)/VERSION_DM | \
+		    awk -F '.' '{printf "%s.%s",$$1,$$2}')
+
+INCLUDES += -I. -I$(top_srcdir)/include
+
+ifdef DESTDIR
+  INCLUDES += -I$(DESTDIR)/usr/include
+endif
+
+INC_LNS = $(top_srcdir)/include/.symlinks_created
+
+DEPS = $(top_srcdir)/make.tmpl $(top_srcdir)/VERSION Makefile $(INC_LNS)
+
+OBJECTS = $(SOURCES:%.c=%.o)
+POTFILES = $(SOURCES:%.c=%.pot)
+
+.PHONY: all install install_cluster pofile distclean clean cflow device-mapper 
+.PHONY: install_device-mapper
+.PHONY: $(SUBDIRS) $(SUBDIRS.install) $(SUBDIRS.clean) $(SUBDIRS.distclean)
+.PHONY: $(SUBDIRS.pofile) $(SUBDIRS.install_cluster) $(SUBDIRS.cflow)
+.PHONY: $(SUBDIRS.device-mapper) $(SUBDIRS.install-device-mapper)
+
+SUBDIRS.device-mapper := $(SUBDIRS:=.device-mapper)
+SUBDIRS.install := $(SUBDIRS:=.install)
+SUBDIRS.install_cluster := $(SUBDIRS:=.install_cluster)
+SUBDIRS.install_device-mapper := $(SUBDIRS:=.install_device-mapper)
+SUBDIRS.pofile := $(SUBDIRS:=.pofile)
+SUBDIRS.cflow := $(SUBDIRS:=.cflow)
+SUBDIRS.clean := $(SUBDIRS:=.clean)
+SUBDIRS.distclean := $(SUBDIRS:=.distclean)
+
+TARGETS += $(LIB_SHARED) $(LIB_STATIC) $(VERSIONED_SHLIB)
+
+all: $(SUBDIRS) $(TARGETS)
+
+install: all $(SUBDIRS.install)
+install_cluster: all $(SUBDIRS.install_cluster)
+install_device-mapper: $(SUBDIRS.install_device-mapper)
+
+$(SUBDIRS):
+	$(MAKE) -C $@
+
+$(SUBDIRS.device-mapper):
+	$(MAKE) -C $(@:.device-mapper=) device-mapper
+
+$(SUBDIRS.install): $(SUBDIRS)
+	$(MAKE) -C $(@:.install=) install
+
+$(SUBDIRS.install_cluster): $(SUBDIRS)
+	$(MAKE) -C $(@:.install_cluster=) install_cluster
+
+$(SUBDIRS.install_device-mapper): device-mapper
+	$(MAKE) -C $(@:.install_device-mapper=) install_device-mapper
+
+$(SUBDIRS.clean):
+	-$(MAKE) -C $(@:.clean=) clean
+
+$(SUBDIRS.distclean):
+	-$(MAKE) -C $(@:.distclean=) distclean
+
+ifeq ("@INTL@", "yes")
+pofile: $(SUBDIRS.pofile) $(POTFILES)
+
+$(SUBDIRS.pofile):
+	$(MAKE) -C $(@:.pofile=) pofile
+endif
+
+ifneq ("@CFLOW_CMD@", "")
+cflow: $(SUBDIRS.cflow)
+
+$(SUBDIRS.cflow):
+	$(MAKE) -C $(@:.cflow=) cflow
+endif
+
+$(TARGETS): $(OBJECTS)
+
+%.o: %.c
+	$(CC) -c $(INCLUDES) $(DEFS) $(CFLAGS) $< -o $@
+
+%.pot: %.c Makefile
+	$(CC) -E $(INCLUDES) -include $(top_srcdir)/include/pogen.h \
+		$(DEFS) $(CFLAGS) $< > $@
+
+%.so: %.o
+	$(CC) -c $(INCLUDES) $(DEFS) $(CFLAGS) $< -o $@
+
+ifeq ("@LIB_SUFFIX@","so")
+$(LIB_SHARED): $(OBJECTS) $(LDDEPS)
+	$(CC) -shared -Wl,-soname,$(notdir $@).$(LIB_VERSION) \
+	$(CFLAGS) $(CLDFLAGS) $(OBJECTS) $(LIBS) -o $@
+endif
+
+ifeq ("@LIB_SUFFIX@","dylib")
+$(LIB_SHARED): $(OBJECTS) $(LDDEPS)
+	$(CC) -dynamiclib -dylib_current_version,$(LIB_VERSION) \
+	$(CFLAGS) $(CLDFLAGS) $(OBJECTS) $(LIBS) -o $@
+endif
+
+%.so: %.a
+	$(CC) -shared -Wl,-soname,$(notdir $@).$(LIB_VERSION) \
+	$(CFLAGS) $(CLDFLAGS) $(LIBS) -o $@ \
+	@CLDWHOLEARCHIVE@ $< @CLDNOWHOLEARCHIVE@
+
+$(LIB_STATIC): $(OBJECTS)
+	$(RM) $@
+	$(AR) rs $@ $(OBJECTS)
+
+%.d: %.c
+	set -e; \
+	FILE=`echo $@ | sed 's/\\//\\\\\\//g;s/\\.d//g'`; \
+	DEPS=`echo $(DEPS) | sed -e 's/\\//\\\\\\//g'`; \
+	$(CC) -MM $(INCLUDES) $(DEFS) $(CFLAGS) $< | \
+	sed "s/\(.*\)\.o[ :]*/$$FILE.o $$FILE.d $$FILE.pot: $$DEPS /g" > $@; \
+	[ -s $@ ] || $(RM) $@
+
+%.mo: %.po
+	$(MSGFMT) -o $@ $<
+
+clean: $(SUBDIRS.clean)
+	$(RM) $(OBJECTS) $(TARGETS) $(CLEAN_TARGETS) $(SOURCES:%.c=%.d) \
+	      $(SOURCES:%.c=%.pot) $(SOURCES:%.c=%.gcno) \
+	      $(SOURCES:%.c=%.gcda) $(LDDEPS)
+
+distclean: $(SUBDIRS.distclean)
+	$(RM) -rf $(DISTCLEAN_DIRS)
+	$(RM) $(DISTCLEAN_TARGETS) \
+	      $(OBJECTS) $(TARGETS) $(CLEAN_TARGETS) $(SOURCES:%.c=%.d) \
+	      $(SOURCES:%.c=%.pot) $(SOURCES:%.c=%.gcno) \
+	      $(SOURCES:%.c=%.gcda) $(LDDEPS) \
+	      config.cache config.log config.status \
+	      Makefile make.tmpl core \
+	      version.h lvm2.po
+
+.export.sym: .exported_symbols
+	set -e; (echo "Base {"; echo "	global:"; \
+		 sed "s/^/		/;s/$$/;/" < $<; \
+		 echo "	local:"; echo "		*;"; echo "};") > $@
+
+ifneq ($(MAKECMDGOALS),clean)
+  ifneq ($(MAKECMDGOALS),distclean)
+    ifdef SOURCES
+       -include $(SOURCES:.c=.d)
+    endif
+  endif
+endif
+
Index: src/external/gpl2/lvm2tools/dist/autoconf/config.guess
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/autoconf/config.guess
diff -N src/external/gpl2/lvm2tools/dist/autoconf/config.guess
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/autoconf/config.guess	15 Jul 2008 13:49:12 -0000	1.1.1.1
@@ -0,0 +1,1526 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+#   Free Software Foundation, Inc.
+
+timestamp='2008-01-23'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+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.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 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 ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+	for c in cc gcc c89 c99 ; do
+	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+	     CC_FOR_BUILD="$c"; break ;
+	  fi ;
+	done ;
+	if test x"$CC_FOR_BUILD" = x ; then
+	  CC_FOR_BUILD=no_compiler_found ;
+	fi
+	;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+	# NetBSD (nbsd) targets should (where applicable) match one or
+	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	#
+	# Note: NetBSD doesn't particularly care about the vendor
+	# portion of the name.  We always set it to "unknown".
+	sysctl="sysctl -n hw.machine_arch"
+	UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+	    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+	case "${UNAME_MACHINE_ARCH}" in
+	    armeb) machine=armeb-unknown ;;
+	    arm*) machine=arm-unknown ;;
+	    sh3el) machine=shl-unknown ;;
+	    sh3eb) machine=sh-unknown ;;
+	    sh5el) machine=sh5le-unknown ;;
+	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently, or will in the future.
+	case "${UNAME_MACHINE_ARCH}" in
+	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+		eval $set_cc_for_build
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep __ELF__ >/dev/null
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+	        os=netbsd
+		;;
+	esac
+	# The OS release
+	# Debian GNU/NetBSD machines have a different userland, and
+	# thus, need a distinct triplet. However, they do not need
+	# kernel version information, so it can be replaced with a
+	# suitable tag, in the style of linux-gnu.
+	case "${UNAME_VERSION}" in
+	    Debian*)
+		release='-gnu'
+		;;
+	    *)
+		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+		;;
+	esac
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	echo "${machine}-${os}${release}"
+	exit ;;
+    *:OpenBSD:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+	exit ;;
+    *:ekkoBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+	exit ;;
+    *:SolidBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+	exit ;;
+    macppc:MirBSD:*:*)
+	echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    *:MirBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    alpha:OSF1:*:*)
+	case $UNAME_RELEASE in
+	*4.0)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+		;;
+	*5.*)
+	        UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		;;
+	esac
+	# According to Compaq, /usr/sbin/psrinfo has been available on
+	# OSF/1 and Tru64 systems produced since 1995.  I hope that
+	# covers most systems running today.  This code pipes the CPU
+	# types through head -n 1, so we only detect the type of CPU 0.
+	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+	case "$ALPHA_CPU_TYPE" in
+	    "EV4 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV4.5 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "LCA4 (21066/21068)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV5 (21164)")
+		UNAME_MACHINE="alphaev5" ;;
+	    "EV5.6 (21164A)")
+		UNAME_MACHINE="alphaev56" ;;
+	    "EV5.6 (21164PC)")
+		UNAME_MACHINE="alphapca56" ;;
+	    "EV5.7 (21164PC)")
+		UNAME_MACHINE="alphapca57" ;;
+	    "EV6 (21264)")
+		UNAME_MACHINE="alphaev6" ;;
+	    "EV6.7 (21264A)")
+		UNAME_MACHINE="alphaev67" ;;
+	    "EV6.8CB (21264C)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8AL (21264B)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8CX (21264D)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.9A (21264/EV69A)")
+		UNAME_MACHINE="alphaev69" ;;
+	    "EV7 (21364)")
+		UNAME_MACHINE="alphaev7" ;;
+	    "EV7.9 (21364A)")
+		UNAME_MACHINE="alphaev79" ;;
+	esac
+	# A Pn.n version is a patched version.
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	exit ;;
+    Alpha\ *:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# Should we change UNAME_MACHINE based on the output of uname instead
+	# of the specific Alpha model?
+	echo alpha-pc-interix
+	exit ;;
+    21064:Windows_NT:50:3)
+	echo alpha-dec-winnt3.5
+	exit ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-morphos
+	exit ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit ;;
+    *:z/VM:*:*)
+	echo s390-ibm-zvmoe
+	exit ;;
+    *:OS400:*:*)
+        echo powerpc-ibm-os400
+	exit ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit ;;
+    arm:riscos:*:*|arm:RISCOS:*:*)
+	echo arm-unknown-riscos
+	exit ;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit ;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit ;;
+    DRS?6000:unix:4.0:6*)
+	echo sparc-icl-nx6
+	exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+	case `/usr/bin/uname -p` in
+	    sparc) echo sparc-icl-nx7; exit ;;
+	esac ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+	echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:*:*)
+	case "`/usr/bin/arch -k`" in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+	exit ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos${UNAME_RELEASE}
+	exit ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+        exit ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit ;;
+    m68k:machten:*:*)
+	echo m68k-apple-machten${UNAME_RELEASE}
+	exit ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten${UNAME_RELEASE}
+	exit ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c &&
+	  dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+	  SYSTEM_NAME=`$dummy $dummyarg` &&
+	    { echo "$SYSTEM_NAME"; exit; }
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit ;;
+    Motorola:*:4.3:PL8-*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+	then
+	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+	       [ ${TARGET_BINARY_INTERFACE}x = x ]
+	    then
+		echo m88k-dg-dgux${UNAME_RELEASE}
+	    else
+		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+	    fi
+	else
+	    echo i586-dg-dgux${UNAME_RELEASE}
+	fi
+ 	exit ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+	exit ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+	exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit ;;
+    ia64:AIX:*:*)
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		eval $set_cc_for_build
+		sed 's/^		//' << EOF >$dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+		then
+			echo "$SYSTEM_NAME"
+		else
+			echo rs6000-ibm-aix3.2.5
+		fi
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit ;;
+    *:AIX:*:[456])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+	echo romp-ibm-bsd4.4
+	exit ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+	exit ;;                             # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	case "${UNAME_MACHINE}" in
+	    9000/31? )            HP_ARCH=m68000 ;;
+	    9000/[34]?? )         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+		if [ -x /usr/bin/getconf ]; then
+		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                        esac ;;
+                    esac
+		fi
+		if [ "${HP_ARCH}" = "" ]; then
+		    eval $set_cc_for_build
+		    sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+              	{
+              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+              	case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+              	    switch (bits)
+              		{
+              		case 64: puts ("hppa2.0w"); break;
+              		case 32: puts ("hppa2.0n"); break;
+              		default: puts ("hppa2.0"); break;
+              		} break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+              	    puts ("hppa2.0"); break;
+              #endif
+              	default: puts ("hppa1.0"); break;
+              	}
+                  exit (0);
+              }
+EOF
+		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+		    test -z "$HP_ARCH" && HP_ARCH=hppa
+		fi ;;
+	esac
+	if [ ${HP_ARCH} = "hppa2.0w" ]
+	then
+	    eval $set_cc_for_build
+
+	    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+	    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+	    # generating 64-bit code.  GNU and HP use different nomenclature:
+	    #
+	    # $ CC_FOR_BUILD=cc ./config.guess
+	    # => hppa2.0w-hp-hpux11.23
+	    # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+	    # => hppa64-hp-hpux11.23
+
+	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+		grep __LP64__ >/dev/null
+	    then
+		HP_ARCH="hppa2.0w"
+	    else
+		HP_ARCH="hppa64"
+	    fi
+	fi
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux${HPUX_REV}
+	exit ;;
+    3050*:HI-UX:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+		{ echo "$SYSTEM_NAME"; exit; }
+	echo unknown-hitachi-hiuxwe2
+	exit ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+	echo hppa1.1-hp-bsd
+	exit ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+	echo hppa1.1-hp-osf
+	exit ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo ${UNAME_MACHINE}-unknown-osf1mk
+	else
+	    echo ${UNAME_MACHINE}-unknown-osf1
+	fi
+	exit ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+        exit ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+        exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+        exit ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+        exit ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+        exit ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*[A-Z]90:*:*:*)
+	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+	      -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    *:UNICOS/mp:*:*)
+	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit ;;
+    5000:UNIX_System_V:4.*:*)
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+	exit ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:BSD/OS:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:FreeBSD:*:*)
+	case ${UNAME_MACHINE} in
+	    pc98)
+		echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	    amd64)
+		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	    *)
+		echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	esac
+	exit ;;
+    i*:CYGWIN*:*)
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit ;;
+    *:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
+	exit ;;
+    i*:windows32*:*)
+    	# uname -m includes "-pc" on this system.
+    	echo ${UNAME_MACHINE}-mingw32
+	exit ;;
+    i*:PW*:*)
+	echo ${UNAME_MACHINE}-pc-pw32
+	exit ;;
+    *:Interix*:[3456]*)
+    	case ${UNAME_MACHINE} in
+	    x86)
+		echo i586-pc-interix${UNAME_RELEASE}
+		exit ;;
+	    EM64T | authenticamd)
+		echo x86_64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	    IA64)
+		echo ia64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	esac ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+	echo i${UNAME_MACHINE}-pc-mks
+	exit ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+	# UNAME_MACHINE based on the output of uname instead of i386?
+	echo i586-pc-interix
+	exit ;;
+    i*:UWIN*:*)
+	echo ${UNAME_MACHINE}-pc-uwin
+	exit ;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+	echo x86_64-unknown-cygwin
+	exit ;;
+    p*:CYGWIN*:*)
+	echo powerpcle-unknown-cygwin
+	exit ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    *:GNU:*:*)
+	# the GNU system
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit ;;
+    *:GNU/*:*:*)
+	# other systems with GNU libc and userland
+	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+	exit ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit ;;
+    arm*:Linux:*:*)
+	eval $set_cc_for_build
+	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+	    | grep -q __ARM_EABI__
+	then
+	    echo ${UNAME_MACHINE}-unknown-linux-gnu
+	else
+	    echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+	fi
+	exit ;;
+    avr32*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    cris:Linux:*:*)
+	echo cris-axis-linux-gnu
+	exit ;;
+    crisv32:Linux:*:*)
+	echo crisv32-axis-linux-gnu
+	exit ;;
+    frv:Linux:*:*)
+    	echo frv-unknown-linux-gnu
+	exit ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    m32r*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    mips:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef mips
+	#undef mipsel
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=mipsel
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=mips
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+	    /^CPU/{
+		s: ::g
+		p
+	    }'`"
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+	;;
+    mips64:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef mips64
+	#undef mips64el
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=mips64el
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=mips64
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+	    /^CPU/{
+		s: ::g
+		p
+	    }'`"
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+	;;
+    or32:Linux:*:*)
+	echo or32-unknown-linux-gnu
+	exit ;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-gnu
+	exit ;;
+    ppc64:Linux:*:*)
+	echo powerpc64-unknown-linux-gnu
+	exit ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev68 ;;
+        esac
+	objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+	if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+	exit ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) echo hppa1.1-unknown-linux-gnu ;;
+	  PA8*) echo hppa2.0-unknown-linux-gnu ;;
+	  *)    echo hppa-unknown-linux-gnu ;;
+	esac
+	exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-gnu
+	exit ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo ${UNAME_MACHINE}-ibm-linux
+	exit ;;
+    sh64*:Linux:*:*)
+    	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    sh*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    vax:Linux:*:*)
+	echo ${UNAME_MACHINE}-dec-linux-gnu
+	exit ;;
+    x86_64:Linux:*:*)
+	echo x86_64-unknown-linux-gnu
+	exit ;;
+    xtensa*:Linux:*:*)
+    	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    i*86:Linux:*:*)
+	# The BFD linker knows what the default object file format is, so
+	# first see if it will tell us. cd to the root directory to prevent
+	# problems with other programs or directories called `ld' in the path.
+	# Set LC_ALL=C to ensure ld outputs messages in English.
+	ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+			 | sed -ne '/supported targets:/!d
+				    s/[ 	][ 	]*/ /g
+				    s/.*supported targets: *//
+				    s/ .*//
+				    p'`
+        case "$ld_supported_targets" in
+	  elf32-i386)
+		TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+		;;
+	  a.out-i386-linux)
+		echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+		exit ;;
+	  coff-i386)
+		echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+		exit ;;
+	  "")
+		# Either a pre-BFD a.out linker (linux-gnuoldld) or
+		# one that does not give us useful --help.
+		echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+		exit ;;
+	esac
+	# Determine whether the default compiler is a.out or elf
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <features.h>
+	#ifdef __ELF__
+	# ifdef __GLIBC__
+	#  if __GLIBC__ >= 2
+	LIBC=gnu
+	#  else
+	LIBC=gnulibc1
+	#  endif
+	# else
+	LIBC=gnulibc1
+	# endif
+	#else
+	#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+	LIBC=gnu
+	#else
+	LIBC=gnuaout
+	#endif
+	#endif
+	#ifdef __dietlibc__
+	LIBC=dietlibc
+	#endif
+EOF
+	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+	    /^LIBC/{
+		s: ::g
+		p
+	    }'`"
+	test x"${LIBC}" != x && {
+		echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+		exit
+	}
+	test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+	;;
+    i*86:DYNIX/ptx:4*:*)
+	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+	# earlier versions are messed up and put the nodename in both
+	# sysname and nodename.
+	echo i386-sequent-sysv4
+	exit ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+	exit ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit ;;
+    i*86:XTS-300:*:STOP)
+	echo ${UNAME_MACHINE}-unknown-stop
+	exit ;;
+    i*86:atheos:*:*)
+	echo ${UNAME_MACHINE}-unknown-atheos
+	exit ;;
+    i*86:syllable:*:*)
+	echo ${UNAME_MACHINE}-pc-syllable
+	exit ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+	else
+		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+	fi
+	exit ;;
+    i*86:*:5:[678]*)
+    	# UnixWare 7.x, OpenUNIX and OpenServer 6.
+	case `/bin/uname -X | grep "^Machine"` in
+	    *486*)	     UNAME_MACHINE=i486 ;;
+	    *Pentium)	     UNAME_MACHINE=i586 ;;
+	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+	esac
+	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+	exit ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	exit ;;
+    pc:*:*:*)
+	# Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i386.
+	echo i386-pc-msdosdjgpp
+        exit ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+	fi
+	exit ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+	echo m68k-convergent-sysv
+	exit ;;
+    M680?0:D-NIX:5.3:*)
+	echo m68k-diab-dnix
+	exit ;;
+    M68*:*:R3V[5678]*:*)
+	test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && { echo i486-ncr-sysv4; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv${UNAME_RELEASE}
+	exit ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo ${UNAME_MACHINE}-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit ;;
+    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                      # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes@openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit ;;
+    *:*:*:FTX*)
+	# From seanf@swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit ;;
+    i*86:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo ${UNAME_MACHINE}-stratus-vos
+	exit ;;
+    *:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo hppa1.1-stratus-vos
+	exit ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux${UNAME_RELEASE}
+	exit ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if [ -d /usr/nec ]; then
+	        echo mips-nec-sysv${UNAME_RELEASE}
+	else
+	        echo mips-unknown-sysv${UNAME_RELEASE}
+	fi
+        exit ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-6:SUPER-UX:*:*)
+	echo sx6-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-7:SUPER-UX:*:*)
+	echo sx7-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8:SUPER-UX:*:*)
+	echo sx8-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8R:SUPER-UX:*:*)
+	echo sx8r-nec-superux${UNAME_RELEASE}
+	exit ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Rhapsody:*:*)
+	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Darwin:*:*)
+	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+	case $UNAME_PROCESSOR in
+	    unknown) UNAME_PROCESSOR=powerpc ;;
+	esac
+	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+	exit ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	UNAME_PROCESSOR=`uname -p`
+	if test "$UNAME_PROCESSOR" = "x86"; then
+		UNAME_PROCESSOR=i386
+		UNAME_MACHINE=pc
+	fi
+	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+	exit ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit ;;
+    NSE-?:NONSTOP_KERNEL:*:*)
+	echo nse-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit ;;
+    DS/*:UNIX_System_V:*:*)
+	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+	exit ;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "$cputype" = "386"; then
+	    UNAME_MACHINE=i386
+	else
+	    UNAME_MACHINE="$cputype"
+	fi
+	echo ${UNAME_MACHINE}-unknown-plan9
+	exit ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit ;;
+    SEI:*:*:SEIUX)
+        echo mips-sei-seiux${UNAME_RELEASE}
+	exit ;;
+    *:DragonFly:*:*)
+	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	exit ;;
+    *:*VMS:*:*)
+    	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	case "${UNAME_MACHINE}" in
+	    A*) echo alpha-dec-vms ; exit ;;
+	    I*) echo ia64-dec-vms ; exit ;;
+	    V*) echo vax-dec-vms ; exit ;;
+	esac ;;
+    *:XENIX:*:SysV)
+	echo i386-pc-xenix
+	exit ;;
+    i*86:skyos:*:*)
+	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+	exit ;;
+    i*86:rdos:*:*)
+	echo ${UNAME_MACHINE}-pc-rdos
+	exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+	  ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+	printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+	printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+	{ echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+	echo c1-convex-bsd
+	exit ;;
+    c2*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit ;;
+    c34*)
+	echo c34-convex-bsd
+	exit ;;
+    c38*)
+	echo c38-convex-bsd
+	exit ;;
+    c4*)
+	echo c4-convex-bsd
+	exit ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
Index: src/external/gpl2/lvm2tools/dist/autoconf/config.sub
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/autoconf/config.sub
diff -N src/external/gpl2/lvm2tools/dist/autoconf/config.sub
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/autoconf/config.sub	15 Jul 2008 13:49:13 -0000	1.1.1.1
@@ -0,0 +1,1658 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+#   Free Software Foundation, Inc.
+
+timestamp='2008-01-16'
+
+# 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.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# 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>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# 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.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+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,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 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 ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # 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 ;;
+
+    * )
+       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
+  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+  uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+	-sun*os*)
+		# Prevent following clause from handling this invalid input.
+		;;
+	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+	-apple | -axis | -knuth | -cray)
+		os=
+		basic_machine=$1
+		;;
+	-sim | -cisco | -oki | -wec | -winbond)
+		os=
+		basic_machine=$1
+		;;
+	-scout)
+		;;
+	-wrs)
+		os=-vxworks
+		basic_machine=$1
+		;;
+	-chorusos*)
+		os=-chorusos
+		basic_machine=$1
+		;;
+ 	-chorusrdb)
+ 		os=-chorusrdb
+		basic_machine=$1
+ 		;;
+	-hiux*)
+		os=-hiuxwe2
+		;;
+	-sco6)
+		os=-sco5v6
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5)
+		os=-sco3.2v5
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco4)
+		os=-sco3.2v4
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2.[4-9]*)
+		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2v[4-9]*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5v6*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco*)
+		os=-sco3.2v2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-udk*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-isc)
+		os=-isc2.2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-clix*)
+		basic_machine=clipper-intergraph
+		;;
+	-isc*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-lynx*)
+		os=-lynxos
+		;;
+	-ptx*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+		;;
+	-windowsnt*)
+		os=`echo $os | sed -e 's/windowsnt/winnt/'`
+		;;
+	-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.
+	1750a | 580 \
+	| a29k \
+	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+	| am33_2.0 \
+	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+	| bfin \
+	| c4x | clipper \
+	| d10v | d30v | dlx | dsp16xx \
+	| fido | fr30 | frv \
+	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| i370 | i860 | i960 | ia64 \
+	| ip2k | iq2000 \
+	| m32c | m32r | m32rle | m68000 | m68k | m88k \
+	| maxq | mb | microblaze | mcore | mep \
+	| mips | mipsbe | mipseb | mipsel | mipsle \
+	| mips16 \
+	| mips64 | mips64el \
+	| mips64vr | mips64vrel \
+	| mips64orion | mips64orionel \
+	| mips64vr4100 | mips64vr4100el \
+	| mips64vr4300 | mips64vr4300el \
+	| mips64vr5000 | mips64vr5000el \
+	| mips64vr5900 | mips64vr5900el \
+	| mipsisa32 | mipsisa32el \
+	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa64 | mipsisa64el \
+	| mipsisa64r2 | mipsisa64r2el \
+	| mipsisa64sb1 | mipsisa64sb1el \
+	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipstx39 | mipstx39el \
+	| mn10200 | mn10300 \
+	| mt \
+	| msp430 \
+	| nios | nios2 \
+	| ns16k | ns32k \
+	| or32 \
+	| pdp10 | pdp11 | pj | pjl \
+	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+	| pyramid \
+	| score \
+	| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+	| sh64 | sh64le \
+	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+	| spu | strongarm \
+	| tahoe | thumb | tic4x | tic80 | tron \
+	| v850 | v850e \
+	| we32k \
+	| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+	| z8k)
+		basic_machine=$basic_machine-unknown
+		;;
+	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)
+		;;
+	ms1)
+		basic_machine=mt-unknown
+		;;
+
+	# 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*86 | x86_64)
+	  basic_machine=$basic_machine-pc
+	  ;;
+	# Object if more than one company name word.
+	*-*-*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+	# Recognize the basic CPU types with company name.
+	580-* \
+	| a29k-* \
+	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+	| avr-* | avr32-* \
+	| bfin-* | bs2000-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+	| clipper-* | craynv-* | cydra-* \
+	| d10v-* | d30v-* | dlx-* \
+	| elxsi-* \
+	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+	| h8300-* | h8500-* \
+	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| i*86-* | i860-* | i960-* | ia64-* \
+	| ip2k-* | iq2000-* \
+	| m32c-* | m32r-* | m32rle-* \
+	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+	| m88110-* | m88k-* | maxq-* | mcore-* \
+	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+	| mips16-* \
+	| mips64-* | mips64el-* \
+	| mips64vr-* | mips64vrel-* \
+	| mips64orion-* | mips64orionel-* \
+	| mips64vr4100-* | mips64vr4100el-* \
+	| mips64vr4300-* | mips64vr4300el-* \
+	| mips64vr5000-* | mips64vr5000el-* \
+	| mips64vr5900-* | mips64vr5900el-* \
+	| mipsisa32-* | mipsisa32el-* \
+	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa64-* | mipsisa64el-* \
+	| mipsisa64r2-* | mipsisa64r2el-* \
+	| mipsisa64sb1-* | mipsisa64sb1el-* \
+	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipstx39-* | mipstx39el-* \
+	| mmix-* \
+	| mt-* \
+	| msp430-* \
+	| nios-* | nios2-* \
+	| none-* | np1-* | ns16k-* | ns32k-* \
+	| orion-* \
+	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+	| pyramid-* \
+	| romp-* | rs6000-* \
+	| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+	| sparclite-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+	| tahoe-* | thumb-* \
+	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+	| tron-* \
+	| v850-* | v850e-* | vax-* \
+	| we32k-* \
+	| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+	| xstormy16-* | xtensa*-* \
+	| ymp-* \
+	| z8k-*)
+		;;
+	# Recognize the basic CPU types without company name, with glob match.
+	xtensa*)
+		basic_machine=$basic_machine-unknown
+		;;
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	386bsd)
+		basic_machine=i386-unknown
+		os=-bsd
+		;;
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		basic_machine=m68000-att
+		;;
+	3b*)
+		basic_machine=we32k-att
+		;;
+	a29khif)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+    	abacus)
+		basic_machine=abacus-unknown
+		;;
+	adobe68k)
+		basic_machine=m68010-adobe
+		os=-scout
+		;;
+	alliant | fx80)
+		basic_machine=fx80-alliant
+		;;
+	altos | altos3068)
+		basic_machine=m68k-altos
+		;;
+	am29k)
+		basic_machine=a29k-none
+		os=-bsd
+		;;
+	amd64)
+		basic_machine=x86_64-pc
+		;;
+	amd64-*)
+		basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	amdahl)
+		basic_machine=580-amdahl
+		os=-sysv
+		;;
+	amiga | amiga-*)
+		basic_machine=m68k-unknown
+		;;
+	amigaos | amigados)
+		basic_machine=m68k-unknown
+		os=-amigaos
+		;;
+	amigaunix | amix)
+		basic_machine=m68k-unknown
+		os=-sysv4
+		;;
+	apollo68)
+		basic_machine=m68k-apollo
+		os=-sysv
+		;;
+	apollo68bsd)
+		basic_machine=m68k-apollo
+		os=-bsd
+		;;
+	aux)
+		basic_machine=m68k-apple
+		os=-aux
+		;;
+	balance)
+		basic_machine=ns32k-sequent
+		os=-dynix
+		;;
+	blackfin)
+		basic_machine=bfin-unknown
+		os=-linux
+		;;
+	blackfin-*)
+		basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	c90)
+		basic_machine=c90-cray
+		os=-unicos
+		;;
+	convex-c1)
+		basic_machine=c1-convex
+		os=-bsd
+		;;
+	convex-c2)
+		basic_machine=c2-convex
+		os=-bsd
+		;;
+	convex-c32)
+		basic_machine=c32-convex
+		os=-bsd
+		;;
+	convex-c34)
+		basic_machine=c34-convex
+		os=-bsd
+		;;
+	convex-c38)
+		basic_machine=c38-convex
+		os=-bsd
+		;;
+	cray | j90)
+		basic_machine=j90-cray
+		os=-unicos
+		;;
+	craynv)
+		basic_machine=craynv-cray
+		os=-unicosmp
+		;;
+	cr16)
+		basic_machine=cr16-unknown
+		os=-elf
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	crisv32 | crisv32-* | etraxfs*)
+		basic_machine=crisv32-axis
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	crx)
+		basic_machine=crx-unknown
+		os=-elf
+		;;
+	da30 | da30-*)
+		basic_machine=m68k-da30
+		;;
+	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+		basic_machine=mips-dec
+		;;
+	decsystem10* | dec10*)
+		basic_machine=pdp10-dec
+		os=-tops10
+		;;
+	decsystem20* | dec20*)
+		basic_machine=pdp10-dec
+		os=-tops20
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		basic_machine=m68k-motorola
+		;;
+	delta88)
+		basic_machine=m88k-motorola
+		os=-sysv3
+		;;
+	djgpp)
+		basic_machine=i586-pc
+		os=-msdosdjgpp
+		;;
+	dpx20 | dpx20-*)
+		basic_machine=rs6000-bull
+		os=-bosx
+		;;
+	dpx2* | dpx2*-bull)
+		basic_machine=m68k-bull
+		os=-sysv3
+		;;
+	ebmon29k)
+		basic_machine=a29k-amd
+		os=-ebmon
+		;;
+	elxsi)
+		basic_machine=elxsi-elxsi
+		os=-bsd
+		;;
+	encore | umax | mmax)
+		basic_machine=ns32k-encore
+		;;
+	es1800 | OSE68k | ose68k | ose | OSE)
+		basic_machine=m68k-ericsson
+		os=-ose
+		;;
+	fx2800)
+		basic_machine=i860-alliant
+		;;
+	genix)
+		basic_machine=ns32k-ns
+		;;
+	gmicro)
+		basic_machine=tron-gmicro
+		os=-sysv
+		;;
+	go32)
+		basic_machine=i386-pc
+		os=-go32
+		;;
+	h3050r* | hiux*)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	h8300hms)
+		basic_machine=h8300-hitachi
+		os=-hms
+		;;
+	h8300xray)
+		basic_machine=h8300-hitachi
+		os=-xray
+		;;
+	h8500hms)
+		basic_machine=h8500-hitachi
+		os=-hms
+		;;
+	harris)
+		basic_machine=m88k-harris
+		os=-sysv3
+		;;
+	hp300-*)
+		basic_machine=m68k-hp
+		;;
+	hp300bsd)
+		basic_machine=m68k-hp
+		os=-bsd
+		;;
+	hp300hpux)
+		basic_machine=m68k-hp
+		os=-hpux
+		;;
+	hp3k9[0-9][0-9] | hp9[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		basic_machine=m68000-hp
+		;;
+	hp9k3[2-9][0-9])
+		basic_machine=m68k-hp
+		;;
+	hp9k6[0-9][0-9] | hp6[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k7[0-79][0-9] | hp7[0-79][0-9])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k78[0-9] | hp78[0-9])
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][13679] | hp8[0-9][13679])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hppa-next)
+		os=-nextstep3
+		;;
+	hppaosf)
+		basic_machine=hppa1.1-hp
+		os=-osf
+		;;
+	hppro)
+		basic_machine=hppa1.1-hp
+		os=-proelf
+		;;
+	i370-ibm* | ibm*)
+		basic_machine=i370-ibm
+		;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+	i*86v32)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv32
+		;;
+	i*86v4*)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv4
+		;;
+	i*86v)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv
+		;;
+	i*86sol2)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-solaris2
+		;;
+	i386mach)
+		basic_machine=i386-mach
+		os=-mach
+		;;
+	i386-vsta | vsta)
+		basic_machine=i386-unknown
+		os=-vsta
+		;;
+	iris | iris4d)
+		basic_machine=mips-sgi
+		case $os in
+		    -irix*)
+			;;
+		    *)
+			os=-irix4
+			;;
+		esac
+		;;
+	isi68 | isi)
+		basic_machine=m68k-isi
+		os=-sysv
+		;;
+	m68knommu)
+		basic_machine=m68k-unknown
+		os=-linux
+		;;
+	m68knommu-*)
+		basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	m88k-omron*)
+		basic_machine=m88k-omron
+		;;
+	magnum | m3230)
+		basic_machine=mips-mips
+		os=-sysv
+		;;
+	merlin)
+		basic_machine=ns32k-utek
+		os=-sysv
+		;;
+	mingw32)
+		basic_machine=i386-pc
+		os=-mingw32
+		;;
+	mingw32ce)
+		basic_machine=arm-unknown
+		os=-mingw32ce
+		;;
+	miniframe)
+		basic_machine=m68000-convergent
+		;;
+	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+	mips3*-*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+		;;
+	mips3*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+		;;
+	monitor)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	morphos)
+		basic_machine=powerpc-unknown
+		os=-morphos
+		;;
+	msdos)
+		basic_machine=i386-pc
+		os=-msdos
+		;;
+	ms1-*)
+		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+		;;
+	mvs)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+	ncr3000)
+		basic_machine=i486-ncr
+		os=-sysv4
+		;;
+	netbsd386)
+		basic_machine=i386-unknown
+		os=-netbsd
+		;;
+	netwinder)
+		basic_machine=armv4l-rebel
+		os=-linux
+		;;
+	news | news700 | news800 | news900)
+		basic_machine=m68k-sony
+		os=-newsos
+		;;
+	news1000)
+		basic_machine=m68030-sony
+		os=-newsos
+		;;
+	news-3600 | risc-news)
+		basic_machine=mips-sony
+		os=-newsos
+		;;
+	necv70)
+		basic_machine=v70-nec
+		os=-sysv
+		;;
+	next | m*-next )
+		basic_machine=m68k-next
+		case $os in
+		    -nextstep* )
+			;;
+		    -ns2*)
+		      os=-nextstep2
+			;;
+		    *)
+		      os=-nextstep3
+			;;
+		esac
+		;;
+	nh3000)
+		basic_machine=m68k-harris
+		os=-cxux
+		;;
+	nh[45]000)
+		basic_machine=m88k-harris
+		os=-cxux
+		;;
+	nindy960)
+		basic_machine=i960-intel
+		os=-nindy
+		;;
+	mon960)
+		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
+		;;
+	openrisc | openrisc-*)
+		basic_machine=or32-unknown
+		;;
+	os400)
+		basic_machine=powerpc-ibm
+		os=-os400
+		;;
+	OSE68000 | ose68000)
+		basic_machine=m68000-ericsson
+		os=-ose
+		;;
+	os68k)
+		basic_machine=m68k-none
+		os=-os68k
+		;;
+	pa-hitachi)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	paragon)
+		basic_machine=i860-intel
+		os=-osf
+		;;
+	parisc)
+		basic_machine=hppa-unknown
+		os=-linux
+		;;
+	parisc-*)
+		basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+	pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	pc98)
+		basic_machine=i386-pc
+		;;
+	pc98-*)
+		basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium | p5 | k5 | k6 | nexgen | viac3)
+		basic_machine=i586-pc
+		;;
+	pentiumpro | p6 | 6x86 | athlon | athlon_*)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2 | pentiumiii | pentium3)
+		basic_machine=i686-pc
+		;;
+	pentium4)
+		basic_machine=i786-pc
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium4-*)
+		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pn)
+		basic_machine=pn-gould
+		;;
+	power)	basic_machine=power-ibm
+		;;
+	ppc)	basic_machine=powerpc-unknown
+		;;
+	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppcle | powerpclittle | ppc-le | powerpc-little)
+		basic_machine=powerpcle-unknown
+		;;
+	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
+		;;
+	rdos)
+		basic_machine=i386-pc
+		os=-rdos
+		;;
+	rom68k)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	rm[46]00)
+		basic_machine=mips-siemens
+		;;
+	rtpc | rtpc-*)
+		basic_machine=romp-ibm
+		;;
+	s390 | s390-*)
+		basic_machine=s390-ibm
+		;;
+	s390x | s390x-*)
+		basic_machine=s390x-ibm
+		;;
+	sa29200)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	sb1)
+		basic_machine=mipsisa64sb1-unknown
+		;;
+	sb1el)
+		basic_machine=mipsisa64sb1el-unknown
+		;;
+	sde)
+		basic_machine=mipsisa32-sde
+		os=-elf
+		;;
+	sei)
+		basic_machine=mips-sei
+		os=-seiux
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	sh5el)
+		basic_machine=sh5le-unknown
+		;;
+	sh64)
+		basic_machine=sh64-unknown
+		;;
+	sparclite-wrs | simso-wrs)
+		basic_machine=sparclite-wrs
+		os=-vxworks
+		;;
+	sps7)
+		basic_machine=m68k-bull
+		os=-sysv2
+		;;
+	spur)
+		basic_machine=spur-unknown
+		;;
+	st2000)
+		basic_machine=m68k-tandem
+		;;
+	stratus)
+		basic_machine=i860-stratus
+		os=-sysv4
+		;;
+	sun2)
+		basic_machine=m68000-sun
+		;;
+	sun2os3)
+		basic_machine=m68000-sun
+		os=-sunos3
+		;;
+	sun2os4)
+		basic_machine=m68000-sun
+		os=-sunos4
+		;;
+	sun3os3)
+		basic_machine=m68k-sun
+		os=-sunos3
+		;;
+	sun3os4)
+		basic_machine=m68k-sun
+		os=-sunos4
+		;;
+	sun4os3)
+		basic_machine=sparc-sun
+		os=-sunos3
+		;;
+	sun4os4)
+		basic_machine=sparc-sun
+		os=-sunos4
+		;;
+	sun4sol2)
+		basic_machine=sparc-sun
+		os=-solaris2
+		;;
+	sun3 | sun3-*)
+		basic_machine=m68k-sun
+		;;
+	sun4)
+		basic_machine=sparc-sun
+		;;
+	sun386 | sun386i | roadrunner)
+		basic_machine=i386-sun
+		;;
+	sv1)
+		basic_machine=sv1-cray
+		os=-unicos
+		;;
+	symmetry)
+		basic_machine=i386-sequent
+		os=-dynix
+		;;
+	t3e)
+		basic_machine=alphaev5-cray
+		os=-unicos
+		;;
+	t90)
+		basic_machine=t90-cray
+		os=-unicos
+		;;
+	tic54x | c54x*)
+		basic_machine=tic54x-unknown
+		os=-coff
+		;;
+	tic55x | c55x*)
+		basic_machine=tic55x-unknown
+		os=-coff
+		;;
+	tic6x | c6x*)
+		basic_machine=tic6x-unknown
+		os=-coff
+		;;
+	tile*)
+		basic_machine=tile-unknown
+		os=-linux-gnu
+		;;
+	tx39)
+		basic_machine=mipstx39-unknown
+		;;
+	tx39el)
+		basic_machine=mipstx39el-unknown
+		;;
+	toad1)
+		basic_machine=pdp10-xkl
+		os=-tops20
+		;;
+	tower | tower-32)
+		basic_machine=m68k-ncr
+		;;
+	tpf)
+		basic_machine=s390x-ibm
+		os=-tpf
+		;;
+	udi29k)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	ultra3)
+		basic_machine=a29k-nyu
+		os=-sym1
+		;;
+	v810 | necv810)
+		basic_machine=v810-nec
+		os=-none
+		;;
+	vaxv)
+		basic_machine=vax-dec
+		os=-sysv
+		;;
+	vms)
+		basic_machine=vax-dec
+		os=-vms
+		;;
+	vpp*|vx|vx-*)
+		basic_machine=f301-fujitsu
+		;;
+	vxworks960)
+		basic_machine=i960-wrs
+		os=-vxworks
+		;;
+	vxworks68)
+		basic_machine=m68k-wrs
+		os=-vxworks
+		;;
+	vxworks29k)
+		basic_machine=a29k-wrs
+		os=-vxworks
+		;;
+	w65*)
+		basic_machine=w65-wdc
+		os=-none
+		;;
+	w89k-*)
+		basic_machine=hppa1.1-winbond
+		os=-proelf
+		;;
+	xbox)
+		basic_machine=i686-pc
+		os=-mingw32
+		;;
+	xps | xps100)
+		basic_machine=xps100-honeywell
+		;;
+	ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
+	z8k-*-coff)
+		basic_machine=z8k-unknown
+		os=-sim
+		;;
+	none)
+		basic_machine=none-none
+		os=-none
+		;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		basic_machine=hppa1.1-winbond
+		;;
+	op50n)
+		basic_machine=hppa1.1-oki
+		;;
+	op60c)
+		basic_machine=hppa1.1-oki
+		;;
+	romp)
+		basic_machine=romp-ibm
+		;;
+	mmix)
+		basic_machine=mmix-knuth
+		;;
+	rs6000)
+		basic_machine=rs6000-ibm
+		;;
+	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
+		;;
+	sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+		basic_machine=sh-unknown
+		;;
+	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+		basic_machine=sparc-sun
+		;;
+	cydra)
+		basic_machine=cydra-cydrome
+		;;
+	orion)
+		basic_machine=orion-highlevel
+		;;
+	orion105)
+		basic_machine=clipper-highlevel
+		;;
+	mac | mpw | mac-mpw)
+		basic_machine=m68k-apple
+		;;
+	pmac | pmac-mpw)
+		basic_machine=powerpc-apple
+		;;
+	*-unknown)
+		# Make sure to match an already-canonicalized machine name.
+		;;
+	*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+	*-digital*)
+		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+		;;
+	*-commodore*)
+		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+	# -solaris* is a basic system type, with this one exception.
+	-solaris1 | -solaris1.*)
+		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		;;
+	-solaris)
+		os=-solaris2
+		;;
+	-svr4*)
+		os=-sysv4
+		;;
+	-unixware*)
+		os=-sysv4.2uw
+		;;
+	-gnu/linux*)
+		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+		;;
+	# First accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST END IN A *, to match a version number.
+	# -sysv* is not here because it comes later, after sysvr4.
+	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+	      | -aos* \
+	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+	      | -openbsd* | -solidbsd* \
+	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -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* | -linux-newlib* | -linux-uclibc* \
+	      | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
+	# Remember, each alternative MUST END IN *, to match a version number.
+		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto-qnx*)
+		;;
+	-nto*)
+		os=`echo $os | sed -e 's|nto|nto-qnx|'`
+		;;
+	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+		;;
+	-mac*)
+		os=`echo $os | sed -e 's|mac|macos|'`
+		;;
+	-linux-dietlibc)
+		os=-linux-dietlibc
+		;;
+	-linux*)
+		os=`echo $os | sed -e 's|linux|linux-gnu|'`
+		;;
+	-sunos5*)
+		os=`echo $os | sed -e 's|sunos5|solaris2|'`
+		;;
+	-sunos6*)
+		os=`echo $os | sed -e 's|sunos6|solaris3|'`
+		;;
+	-opened*)
+		os=-openedition
+		;;
+        -os400*)
+		os=-os400
+		;;
+	-wince*)
+		os=-wince
+		;;
+	-osfrose*)
+		os=-osfrose
+		;;
+	-osf*)
+		os=-osf
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-atheos*)
+		os=-atheos
+		;;
+	-syllable*)
+		os=-syllable
+		;;
+	-386bsd)
+		os=-bsd
+		;;
+	-ctix* | -uts*)
+		os=-sysv
+		;;
+	-nova*)
+		os=-rtmk-nova
+		;;
+	-ns2 )
+		os=-nextstep2
+		;;
+	-nsk*)
+		os=-nsk
+		;;
+	# Preserve the version number of sinix5.
+	-sinix5.*)
+		os=`echo $os | sed -e 's|sinix|sysv|'`
+		;;
+	-sinix*)
+		os=-sysv4
+		;;
+        -tpf*)
+		os=-tpf
+		;;
+	-triton*)
+		os=-sysv3
+		;;
+	-oss*)
+		os=-sysv3
+		;;
+	-svr4)
+		os=-sysv4
+		;;
+	-svr3)
+		os=-sysv3
+		;;
+	-sysvr4)
+		os=-sysv4
+		;;
+	# This must come after -sysvr4.
+	-sysv*)
+		;;
+	-ose*)
+		os=-ose
+		;;
+	-es1800*)
+		os=-ose
+		;;
+	-xenix)
+		os=-xenix
+		;;
+	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+		os=-mint
+		;;
+	-aros*)
+		os=-aros
+		;;
+	-kaos*)
+		os=-kaos
+		;;
+	-zvmoe)
+		os=-zvmoe
+		;;
+	-none)
+		;;
+	*)
+		# Get rid of the `-' at the beginning of $os.
+		os=`echo $os | sed 's/[^-]*-//'`
+		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+		exit 1
+		;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+        score-*)
+		os=-elf
+		;;
+        spu-*)
+		os=-elf
+		;;
+	*-acorn)
+		os=-riscix1.2
+		;;
+	arm*-rebel)
+		os=-linux
+		;;
+	arm*-semi)
+		os=-aout
+		;;
+        c4x-* | tic4x-*)
+        	os=-coff
+		;;
+	# This must come before the *-dec entry.
+	pdp10-*)
+		os=-tops20
+		;;
+	pdp11-*)
+		os=-none
+		;;
+	*-dec | vax-*)
+		os=-ultrix4.2
+		;;
+	m68*-apollo)
+		os=-domain
+		;;
+	i386-sun)
+		os=-sunos4.0.2
+		;;
+	m68000-sun)
+		os=-sunos3
+		# This also exists in the configure program, but was not the
+		# default.
+		# os=-sunos4
+		;;
+	m68*-cisco)
+		os=-aout
+		;;
+        mep-*)
+		os=-elf
+		;;
+	mips*-cisco)
+		os=-elf
+		;;
+	mips*-*)
+		os=-elf
+		;;
+	or32-*)
+		os=-coff
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=-sysv3
+		;;
+	sparc-* | *-sun)
+		os=-sunos4.1.1
+		;;
+	*-be)
+		os=-beos
+		;;
+	*-haiku)
+		os=-haiku
+		;;
+	*-ibm)
+		os=-aix
+		;;
+    	*-knuth)
+		os=-mmixware
+		;;
+	*-wec)
+		os=-proelf
+		;;
+	*-winbond)
+		os=-proelf
+		;;
+	*-oki)
+		os=-proelf
+		;;
+	*-hp)
+		os=-hpux
+		;;
+	*-hitachi)
+		os=-hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=-sysv
+		;;
+	*-cbm)
+		os=-amigaos
+		;;
+	*-dg)
+		os=-dgux
+		;;
+	*-dolphin)
+		os=-sysv3
+		;;
+	m68k-ccur)
+		os=-rtu
+		;;
+	m88k-omron*)
+		os=-luna
+		;;
+	*-next )
+		os=-nextstep
+		;;
+	*-sequent)
+		os=-ptx
+		;;
+	*-crds)
+		os=-unos
+		;;
+	*-ns)
+		os=-genix
+		;;
+	i370-*)
+		os=-mvs
+		;;
+	*-next)
+		os=-nextstep3
+		;;
+	*-gould)
+		os=-sysv
+		;;
+	*-highlevel)
+		os=-bsd
+		;;
+	*-encore)
+		os=-bsd
+		;;
+	*-sgi)
+		os=-irix
+		;;
+	*-siemens)
+		os=-sysv4
+		;;
+	*-masscomp)
+		os=-rtu
+		;;
+	f30[01]-fujitsu | f700-fujitsu)
+		os=-uxpv
+		;;
+	*-rom68k)
+		os=-coff
+		;;
+	*-*bug)
+		os=-coff
+		;;
+	*-apple)
+		os=-macos
+		;;
+	*-atari*)
+		os=-mint
+		;;
+	*)
+		os=-none
+		;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+	*-unknown)
+		case $os in
+			-riscix*)
+				vendor=acorn
+				;;
+			-sunos*)
+				vendor=sun
+				;;
+			-aix*)
+				vendor=ibm
+				;;
+			-beos*)
+				vendor=be
+				;;
+			-hpux*)
+				vendor=hp
+				;;
+			-mpeix*)
+				vendor=hp
+				;;
+			-hiux*)
+				vendor=hitachi
+				;;
+			-unos*)
+				vendor=crds
+				;;
+			-dgux*)
+				vendor=dg
+				;;
+			-luna*)
+				vendor=omron
+				;;
+			-genix*)
+				vendor=ns
+				;;
+			-mvs* | -opened*)
+				vendor=ibm
+				;;
+			-os400*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+			-tpf*)
+				vendor=ibm
+				;;
+			-vxsim* | -vxworks* | -windiss*)
+				vendor=wrs
+				;;
+			-aux*)
+				vendor=apple
+				;;
+			-hms*)
+				vendor=hitachi
+				;;
+			-mpw* | -macos*)
+				vendor=apple
+				;;
+			-*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
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
Index: src/external/gpl2/lvm2tools/dist/autoconf/install-sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/autoconf/install-sh
diff -N src/external/gpl2/lvm2tools/dist/autoconf/install-sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/autoconf/install-sh	15 Jul 2008 13:49:13 -0000	1.1.1.1
@@ -0,0 +1,507 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2006-10-14.15
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" ""	$nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+if test -z "$doit"; then
+  doit_exec=exec
+else
+  doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+posix_glob=
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chmodcmd=$chmodprog
+chowncmd=
+chgrpcmd=
+stripcmd=
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=
+dst=
+dir_arg=
+dstarg=
+no_target_directory=
+
+usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+   or: $0 [OPTION]... SRCFILES... DIRECTORY
+   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+   or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+-c         (ignored)
+-d         create directories instead of installing files.
+-g GROUP   $chgrpprog installed files to GROUP.
+-m MODE    $chmodprog installed files to MODE.
+-o USER    $chownprog installed files to USER.
+-s         $stripprog installed files.
+-t DIRECTORY  install into DIRECTORY.
+-T         report an error if DSTFILE is a directory.
+--help     display this help and exit.
+--version  display version info and exit.
+
+Environment variables override the default commands:
+  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+  case $1 in
+    -c) shift
+        continue;;
+
+    -d) dir_arg=true
+        shift
+        continue;;
+
+    -g) chgrpcmd="$chgrpprog $2"
+        shift
+        shift
+        continue;;
+
+    --help) echo "$usage"; exit $?;;
+
+    -m) mode=$2
+        shift
+        shift
+	case $mode in
+	  *' '* | *'	'* | *'
+'*	  | *'*'* | *'?'* | *'['*)
+	    echo "$0: invalid mode: $mode" >&2
+	    exit 1;;
+	esac
+        continue;;
+
+    -o) chowncmd="$chownprog $2"
+        shift
+        shift
+        continue;;
+
+    -s) stripcmd=$stripprog
+        shift
+        continue;;
+
+    -t) dstarg=$2
+	shift
+	shift
+	continue;;
+
+    -T) no_target_directory=true
+	shift
+	continue;;
+
+    --version) echo "$0 $scriptversion"; exit $?;;
+
+    --)	shift
+	break;;
+
+    -*)	echo "$0: invalid option: $1" >&2
+	exit 1;;
+
+    *)  break;;
+  esac
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dstarg"; then
+  # When -d is used, all remaining arguments are directories to create.
+  # When -t is used, the destination is already specified.
+  # Otherwise, the last argument is the destination.  Remove it from $@.
+  for arg
+  do
+    if test -n "$dstarg"; then
+      # $@ is not empty: it contains at least $arg.
+      set fnord "$@" "$dstarg"
+      shift # fnord
+    fi
+    shift # arg
+    dstarg=$arg
+  done
+fi
+
+if test $# -eq 0; then
+  if test -z "$dir_arg"; then
+    echo "$0: no input file specified." >&2
+    exit 1
+  fi
+  # It's OK to call `install-sh -d' without argument.
+  # This can happen when creating conditional directories.
+  exit 0
+fi
+
+if test -z "$dir_arg"; then
+  trap '(exit $?); exit' 1 2 13 15
+
+  # Set umask so as not to create temps with too-generous modes.
+  # However, 'strip' requires both read and write access to temps.
+  case $mode in
+    # Optimize common cases.
+    *644) cp_umask=133;;
+    *755) cp_umask=22;;
+
+    *[0-7])
+      if test -z "$stripcmd"; then
+	u_plus_rw=
+      else
+	u_plus_rw='% 200'
+      fi
+      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+    *)
+      if test -z "$stripcmd"; then
+	u_plus_rw=
+      else
+	u_plus_rw=,u+rw
+      fi
+      cp_umask=$mode$u_plus_rw;;
+  esac
+fi
+
+for src
+do
+  # Protect names starting with `-'.
+  case $src in
+    -*) src=./$src ;;
+  esac
+
+  if test -n "$dir_arg"; then
+    dst=$src
+    dstdir=$dst
+    test -d "$dstdir"
+    dstdir_status=$?
+  else
+
+    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+    # might cause directories to be created, which would be especially bad
+    # if $src (and thus $dsttmp) contains '*'.
+    if test ! -f "$src" && test ! -d "$src"; then
+      echo "$0: $src does not exist." >&2
+      exit 1
+    fi
+
+    if test -z "$dstarg"; then
+      echo "$0: no destination specified." >&2
+      exit 1
+    fi
+
+    dst=$dstarg
+    # Protect names starting with `-'.
+    case $dst in
+      -*) dst=./$dst ;;
+    esac
+
+    # If destination is a directory, append the input filename; won't work
+    # if double slashes aren't ignored.
+    if test -d "$dst"; then
+      if test -n "$no_target_directory"; then
+	echo "$0: $dstarg: Is a directory" >&2
+	exit 1
+      fi
+      dstdir=$dst
+      dst=$dstdir/`basename "$src"`
+      dstdir_status=0
+    else
+      # Prefer dirname, but fall back on a substitute if dirname fails.
+      dstdir=`
+	(dirname "$dst") 2>/dev/null ||
+	expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	     X"$dst" : 'X\(//\)[^/]' \| \
+	     X"$dst" : 'X\(//\)$' \| \
+	     X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+	echo X"$dst" |
+	    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\/\)[^/].*/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\/\)$/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\).*/{
+		   s//\1/
+		   q
+		 }
+		 s/.*/./; q'
+      `
+
+      test -d "$dstdir"
+      dstdir_status=$?
+    fi
+  fi
+
+  obsolete_mkdir_used=false
+
+  if test $dstdir_status != 0; then
+    case $posix_mkdir in
+      '')
+	# Create intermediate dirs using mode 755 as modified by the umask.
+	# This is like FreeBSD 'install' as of 1997-10-28.
+	umask=`umask`
+	case $stripcmd.$umask in
+	  # Optimize common cases.
+	  *[2367][2367]) mkdir_umask=$umask;;
+	  .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+	  *[0-7])
+	    mkdir_umask=`expr $umask + 22 \
+	      - $umask % 100 % 40 + $umask % 20 \
+	      - $umask % 10 % 4 + $umask % 2
+	    `;;
+	  *) mkdir_umask=$umask,go-w;;
+	esac
+
+	# With -d, create the new directory with the user-specified mode.
+	# Otherwise, rely on $mkdir_umask.
+	if test -n "$dir_arg"; then
+	  mkdir_mode=-m$mode
+	else
+	  mkdir_mode=
+	fi
+
+	posix_mkdir=false
+	case $umask in
+	  *[123567][0-7][0-7])
+	    # POSIX mkdir -p sets u+wx bits regardless of umask, which
+	    # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+	    ;;
+	  *)
+	    tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+	    trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+	    if (umask $mkdir_umask &&
+		exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+	    then
+	      if test -z "$dir_arg" || {
+		   # Check for POSIX incompatibilities with -m.
+		   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+		   # other-writeable bit of parent directory when it shouldn't.
+		   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+		   ls_ld_tmpdir=`ls -ld "$tmpdir"`
+		   case $ls_ld_tmpdir in
+		     d????-?r-*) different_mode=700;;
+		     d????-?--*) different_mode=755;;
+		     *) false;;
+		   esac &&
+		   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+		     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+		     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+		   }
+		 }
+	      then posix_mkdir=:
+	      fi
+	      rmdir "$tmpdir/d" "$tmpdir"
+	    else
+	      # Remove any dirs left behind by ancient mkdir implementations.
+	      rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+	    fi
+	    trap '' 0;;
+	esac;;
+    esac
+
+    if
+      $posix_mkdir && (
+	umask $mkdir_umask &&
+	$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+      )
+    then :
+    else
+
+      # The umask is ridiculous, or mkdir does not conform to POSIX,
+      # or it failed possibly due to a race condition.  Create the
+      # directory the slow way, step by step, checking for races as we go.
+
+      case $dstdir in
+	/*) prefix=/ ;;
+	-*) prefix=./ ;;
+	*)  prefix= ;;
+      esac
+
+      case $posix_glob in
+        '')
+	  if (set -f) 2>/dev/null; then
+	    posix_glob=true
+	  else
+	    posix_glob=false
+	  fi ;;
+      esac
+
+      oIFS=$IFS
+      IFS=/
+      $posix_glob && set -f
+      set fnord $dstdir
+      shift
+      $posix_glob && set +f
+      IFS=$oIFS
+
+      prefixes=
+
+      for d
+      do
+	test -z "$d" && continue
+
+	prefix=$prefix$d
+	if test -d "$prefix"; then
+	  prefixes=
+	else
+	  if $posix_mkdir; then
+	    (umask=$mkdir_umask &&
+	     $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+	    # Don't fail if two instances are running concurrently.
+	    test -d "$prefix" || exit 1
+	  else
+	    case $prefix in
+	      *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+	      *) qprefix=$prefix;;
+	    esac
+	    prefixes="$prefixes '$qprefix'"
+	  fi
+	fi
+	prefix=$prefix/
+      done
+
+      if test -n "$prefixes"; then
+	# Don't fail if two instances are running concurrently.
+	(umask $mkdir_umask &&
+	 eval "\$doit_exec \$mkdirprog $prefixes") ||
+	  test -d "$dstdir" || exit 1
+	obsolete_mkdir_used=true
+      fi
+    fi
+  fi
+
+  if test -n "$dir_arg"; then
+    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+  else
+
+    # Make a couple of temp file names in the proper directory.
+    dsttmp=$dstdir/_inst.$$_
+    rmtmp=$dstdir/_rm.$$_
+
+    # Trap to clean up those temp files at exit.
+    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+    # Copy the file name to the temp name.
+    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+    # and set any options; do chmod last to preserve setuid bits.
+    #
+    # If any of these fail, we abort the whole thing.  If we want to
+    # ignore errors from any of these, just make sure not to ignore
+    # errors from the above "$doit $cpprog $src $dsttmp" command.
+    #
+    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
+      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
+      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
+      && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+    # Now rename the file to the real destination.
+    { $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null \
+      || {
+	   # The rename failed, perhaps because mv can't rename something else
+	   # to itself, or perhaps because mv is so ancient that it does not
+	   # support -f.
+
+	   # Now remove or move aside any old file at destination location.
+	   # We try this two ways since rm can't unlink itself on some
+	   # systems and the destination file might be busy for other
+	   # reasons.  In this case, the final cleanup might fail but the new
+	   # file should still install successfully.
+	   {
+	     if test -f "$dst"; then
+	       $doit $rmcmd -f "$dst" 2>/dev/null \
+	       || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null \
+		     && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }; }\
+	       || {
+		 echo "$0: cannot unlink or rename $dst" >&2
+		 (exit 1); exit 1
+	       }
+	     else
+	       :
+	     fi
+	   } &&
+
+	   # Now rename the file to the real destination.
+	   $doit $mvcmd "$dsttmp" "$dst"
+	 }
+    } || exit 1
+
+    trap '' 0
+  fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
Index: src/external/gpl2/lvm2tools/dist/daemons/Makefile.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/Makefile.in
diff -N src/external/gpl2/lvm2tools/dist/daemons/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/Makefile.in	12 Dec 2008 16:32:57 -0000	1.1.1.1.2.1
@@ -0,0 +1,32 @@
+#
+# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+.PHONY: dmeventd clvmd
+
+ifneq ("@CLVMD@", "none")
+  SUBDIRS = clvmd
+endif
+
+ifeq ("@DMEVENTD@", "yes")
+  SUBDIRS += dmeventd
+endif
+
+include $(top_srcdir)/make.tmpl
+
+ifeq ("@DMEVENTD@", "yes")
+device-mapper: dmeventd.device-mapper
+endif
Index: src/external/gpl2/lvm2tools/dist/daemons/clvmd/Makefile.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/clvmd/Makefile.in
diff -N src/external/gpl2/lvm2tools/dist/daemons/clvmd/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/clvmd/Makefile.in	12 Dec 2008 16:32:57 -0000	1.1.1.1.2.1
@@ -0,0 +1,98 @@
+#
+# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+SOURCES = \
+	clvmd-command.c  \
+	clvmd.c          \
+	lvm-functions.c  \
+	refresh_clvmd.c
+
+ifeq ("@CLVMD@", "gulm")
+	GULM = yes
+endif
+
+ifeq ("@CLVMD@", "cman")
+	CMAN = yes
+endif
+
+ifeq ("@CLVMD@", "openais")
+	OPENAIS = yes
+	GULM = no
+	CMAN = no
+endif
+
+ifeq ("@CLVMD@", "all")
+	GULM = yes
+	CMAN = yes
+	OPENAIS = no
+endif
+
+ifeq ("@DEBUG@", "yes")
+	DEFS += -DDEBUG
+endif
+
+ifeq ("$(GULM)", "yes")
+	SOURCES += clvmd-gulm.c tcp-comms.c
+	LMLIBS += -lccs -lgulm
+	DEFS += -DUSE_GULM
+endif
+
+ifeq ("$(CMAN)", "yes")
+	SOURCES += clvmd-cman.c
+	LMLIBS += -ldlm -lcman
+	DEFS += -DUSE_CMAN
+endif
+
+ifeq ("$(OPENAIS)", "yes")
+	SOURCES += clvmd-openais.c
+	LMLIBS += -lSaLck -lcpg
+	DEFS += -DUSE_OPENAIS
+endif
+
+TARGETS = \
+	clvmd
+
+LVMLIBS = -llvm -lpthread
+
+ifeq ("@DMEVENTD@", "yes")
+	LVMLIBS += -ldevmapper-event
+endif
+ 
+LVMLIBS += -ldevmapper
+
+DEFS += -D_REENTRANT
+CFLAGS += -fno-strict-aliasing
+
+include $(top_srcdir)/make.tmpl
+
+INSTALL_TARGETS = \
+	install_clvmd
+
+clvmd: $(OBJECTS) $(top_srcdir)/lib/liblvm.a
+	$(CC) -o clvmd $(OBJECTS) $(CFLAGS) $(LDFLAGS) \
+		$(LVMLIBS) $(LMLIBS) $(LIBS)
+
+.PHONY: install_clvmd
+
+install_clvmd: $(TARGETS)
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) clvmd \
+		$(usrsbindir)/clvmd
+
+install: $(INSTALL_TARGETS)
+
+install_cluster: $(INSTALL_TARGETS)
+
Index: src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvm.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvm.h
diff -N src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvm.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvm.h	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,73 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* Definitions for CLVMD server and clients */
+
+/*
+ * The protocol spoken over the cluster and across the local socket.
+ */
+
+#ifndef _CLVM_H
+#define _CLVM_H
+
+struct clvm_header {
+	uint8_t  cmd;	        /* See below */
+	uint8_t  flags;	        /* See below */
+	uint16_t xid;	        /* Transaction ID */
+	uint32_t clientid;	/* Only used in Daemon->Daemon comms */
+	int32_t  status;	/* For replies, whether request succeeded */
+	uint32_t arglen;	/* Length of argument below. 
+				   If >1500 then it will be passed 
+				   around the cluster in the system LV */
+	char node[1];		/* Actually a NUL-terminated string, node name.
+				   If this is empty then the command is 
+				   forwarded to all cluster nodes unless 
+				   FLAG_LOCAL is also set. */
+	char args[1];		/* Arguments for the command follow the 
+				   node name, This member is only
+				   valid if the node name is empty */
+} __attribute__ ((packed));
+
+/* Flags */
+#define CLVMD_FLAG_LOCAL        1	/* Only do this on the local node */
+#define CLVMD_FLAG_SYSTEMLV     2	/* Data in system LV under my node name */
+#define CLVMD_FLAG_NODEERRS     4       /* Reply has errors in node-specific portion */
+
+/* Name of the local socket to communicate between libclvm and clvmd */
+//static const char CLVMD_SOCKNAME[]="/var/run/clvmd";
+static const char CLVMD_SOCKNAME[] = "\0clvmd";
+
+/* Internal commands & replies */
+#define CLVMD_CMD_REPLY    1
+#define CLVMD_CMD_VERSION  2	/* Send version around cluster when we start */
+#define CLVMD_CMD_GOAWAY   3	/* Die if received this - we are running 
+				   an incompatible version */
+#define CLVMD_CMD_TEST     4	/* Just for mucking about */
+
+#define CLVMD_CMD_LOCK              30
+#define CLVMD_CMD_UNLOCK            31
+
+/* Lock/Unlock commands */
+#define CLVMD_CMD_LOCK_LV           50
+#define CLVMD_CMD_LOCK_VG           51
+
+/* Misc functions */
+#define CLVMD_CMD_REFRESH	    40
+#define CLVMD_CMD_GET_CLUSTERNAME   41
+#define CLVMD_CMD_SET_DEBUG	    42
+#define CLVMD_CMD_VG_BACKUP	    43
+#endif
Index: src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd-cman.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd-cman.c
diff -N src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd-cman.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd-cman.c	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,520 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * CMAN communication layer for clvmd.
+ */
+
+#define _GNU_SOURCE
+#define _FILE_OFFSET_BITS 64
+
+#include <configure.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <sys/un.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/utsname.h>
+#include <syslog.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <signal.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <errno.h>
+#include <libdevmapper.h>
+#include <libdlm.h>
+
+#include "clvmd-comms.h"
+#include "clvm.h"
+#include "lvm-logging.h"
+#include "clvmd.h"
+#include "lvm-functions.h"
+
+#define LOCKSPACE_NAME "clvmd"
+
+struct clvmd_node
+{
+	struct cman_node *node;
+	int clvmd_up;
+};
+
+static int num_nodes;
+static struct cman_node *nodes = NULL;
+static struct cman_node this_node;
+static int count_nodes; /* size of allocated nodes array */
+static struct dm_hash_table *node_updown_hash;
+static dlm_lshandle_t *lockspace;
+static cman_handle_t c_handle;
+
+static void count_clvmds_running(void);
+static void get_members(void);
+static int nodeid_from_csid(const char *csid);
+static int name_from_nodeid(int nodeid, char *name);
+static void event_callback(cman_handle_t handle, void *private, int reason, int arg);
+static void data_callback(cman_handle_t handle, void *private,
+			  char *buf, int len, uint8_t port, int nodeid);
+
+struct lock_wait {
+	pthread_cond_t cond;
+	pthread_mutex_t mutex;
+	struct dlm_lksb lksb;
+};
+
+static int _init_cluster(void)
+{
+	node_updown_hash = dm_hash_create(100);
+
+	/* Open the cluster communication socket */
+	c_handle = cman_init(NULL);
+	if (!c_handle) {
+		syslog(LOG_ERR, "Can't open cluster manager socket: %m");
+		return -1;
+	}
+	DEBUGLOG("Connected to CMAN\n");
+
+	if (cman_start_recv_data(c_handle, data_callback, CLUSTER_PORT_CLVMD)) {
+		syslog(LOG_ERR, "Can't bind cluster socket: %m");
+		return -1;
+	}
+
+	if (cman_start_notification(c_handle, event_callback)) {
+		syslog(LOG_ERR, "Can't start cluster event listening");
+		return -1;
+	}
+
+	/* Get the cluster members list */
+	get_members();
+	count_clvmds_running();
+
+	DEBUGLOG("CMAN initialisation complete\n");
+
+	/* Create a lockspace for LV & VG locks to live in */
+	lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600);
+	if (!lockspace) {
+		syslog(LOG_ERR, "Unable to create lockspace for CLVM: %m");
+		return -1;
+	}
+	dlm_ls_pthread_init(lockspace);
+	DEBUGLOG("DLM initialisation complete\n");
+	return 0;
+}
+
+static void _cluster_init_completed(void)
+{
+	clvmd_cluster_init_completed();
+}
+
+static int _get_main_cluster_fd()
+{
+	return cman_get_fd(c_handle);
+}
+
+static int _get_num_nodes()
+{
+	int i;
+	int nnodes = 0;
+
+	/* return number of ACTIVE nodes */
+	for (i=0; i<num_nodes; i++) {
+		if (nodes[i].cn_member && nodes[i].cn_nodeid)
+			nnodes++;
+	}
+	return nnodes;
+}
+
+/* send_message with the fd check removed */
+static int _cluster_send_message(const void *buf, int msglen, const char *csid,
+				 const char *errtext)
+{
+	int nodeid = 0;
+
+	if (csid)
+		memcpy(&nodeid, csid, CMAN_MAX_CSID_LEN);
+
+	if (cman_send_data(c_handle, buf, msglen, 0, CLUSTER_PORT_CLVMD, nodeid) <= 0)
+	{
+		log_error("%s", errtext);
+	}
+	return msglen;
+}
+
+static void _get_our_csid(char *csid)
+{
+	if (this_node.cn_nodeid == 0) {
+		cman_get_node(c_handle, 0, &this_node);
+	}
+	memcpy(csid, &this_node.cn_nodeid, CMAN_MAX_CSID_LEN);
+}
+
+/* Call a callback routine for each node is that known (down means not running a clvmd) */
+static int _cluster_do_node_callback(struct local_client *client,
+				     void (*callback) (struct local_client *,
+						       const char *,
+						       int))
+{
+	int i;
+	int somedown = 0;
+
+	for (i = 0; i < _get_num_nodes(); i++) {
+		if (nodes[i].cn_member && nodes[i].cn_nodeid) {
+			int up = (int)(long)dm_hash_lookup_binary(node_updown_hash, (char *)&nodes[i].cn_nodeid, sizeof(int));
+
+			callback(client, (char *)&nodes[i].cn_nodeid, up);
+			if (!up)
+				somedown = -1;
+		}
+	}
+	return somedown;
+}
+
+/* Process OOB messages from the cluster socket */
+static void event_callback(cman_handle_t handle, void *private, int reason, int arg)
+{
+	char namebuf[MAX_CLUSTER_MEMBER_NAME_LEN];
+
+	switch (reason) {
+        case CMAN_REASON_PORTCLOSED:
+		name_from_nodeid(arg, namebuf);
+		log_notice("clvmd on node %s has died\n", namebuf);
+		DEBUGLOG("Got port closed message, removing node %s\n", namebuf);
+
+		dm_hash_insert_binary(node_updown_hash, (char *)&arg, sizeof(int), (void *)0);
+		break;
+
+	case CMAN_REASON_STATECHANGE:
+		DEBUGLOG("Got state change message, re-reading members list\n");
+		get_members();
+		break;
+
+#if defined(LIBCMAN_VERSION) && LIBCMAN_VERSION >= 2
+	case CMAN_REASON_PORTOPENED:
+		/* Ignore this, wait for startup message from clvmd itself */
+		break;
+
+	case CMAN_REASON_TRY_SHUTDOWN:
+		DEBUGLOG("Got try shutdown, sending OK\n");
+		cman_replyto_shutdown(c_handle, 1);
+		break;
+#endif
+	default:
+		/* ERROR */
+		DEBUGLOG("Got unknown event callback message: %d\n", reason);
+		break;
+	}
+}
+
+static struct local_client *cman_client;
+static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
+				const char *csid,
+				struct local_client **new_client)
+{
+
+	/* Save this for data_callback */
+	cman_client = fd;
+
+	/* We never return a new client */
+	*new_client = NULL;
+
+	return cman_dispatch(c_handle, 0);
+}
+
+
+static void data_callback(cman_handle_t handle, void *private,
+			  char *buf, int len, uint8_t port, int nodeid)
+{
+	/* Ignore looped back messages */
+	if (nodeid == this_node.cn_nodeid)
+		return;
+	process_message(cman_client, buf, len, (char *)&nodeid);
+}
+
+static void _add_up_node(const char *csid)
+{
+	/* It's up ! */
+	int nodeid = nodeid_from_csid(csid);
+
+	dm_hash_insert_binary(node_updown_hash, (char *)&nodeid, sizeof(int), (void *)1);
+	DEBUGLOG("Added new node %d to updown list\n", nodeid);
+}
+
+static void _cluster_closedown()
+{
+	unlock_all();
+	dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
+	cman_finish(c_handle);
+}
+
+static int is_listening(int nodeid)
+{
+	int status;
+
+	do {
+		status = cman_is_listening(c_handle, nodeid, CLUSTER_PORT_CLVMD);
+		if (status < 0 && errno == EBUSY) {	/* Don't busywait */
+			sleep(1);
+			errno = EBUSY;	/* In case sleep trashes it */
+		}
+	}
+	while (status < 0 && errno == EBUSY);
+
+	return status;
+}
+
+/* Populate the list of CLVMDs running.
+   called only at startup time */
+static void count_clvmds_running(void)
+{
+	int i;
+
+	for (i = 0; i < num_nodes; i++) {
+		int nodeid = nodes[i].cn_nodeid;
+
+		if (is_listening(nodeid) == 1)
+			dm_hash_insert_binary(node_updown_hash, (void *)&nodeid, sizeof(int), (void*)1);
+		else
+			dm_hash_insert_binary(node_updown_hash, (void *)&nodeid, sizeof(int), (void*)0);
+	}
+}
+
+/* Get a list of active cluster members */
+static void get_members()
+{
+	int retnodes;
+	int status;
+	int i;
+	int high_nodeid = 0;
+
+	num_nodes = cman_get_node_count(c_handle);
+	if (num_nodes == -1) {
+		log_error("Unable to get node count");
+		return;
+	}
+
+	/* Not enough room for new nodes list ? */
+	if (num_nodes > count_nodes && nodes) {
+		free(nodes);
+		nodes = NULL;
+	}
+
+	if (nodes == NULL) {
+		count_nodes = num_nodes + 10; /* Overallocate a little */
+		nodes = malloc(count_nodes * sizeof(struct cman_node));
+		if (!nodes) {
+			log_error("Unable to allocate nodes array\n");
+			exit(5);
+		}
+	}
+
+	status = cman_get_nodes(c_handle, count_nodes, &retnodes, nodes);
+	if (status < 0) {
+		log_error("Unable to get node details");
+		exit(6);
+	}
+
+	/* Get the highest nodeid */
+	for (i=0; i<retnodes; i++) {
+		if (nodes[i].cn_nodeid > high_nodeid)
+			high_nodeid = nodes[i].cn_nodeid;
+	}
+}
+
+
+/* Convert a node name to a CSID */
+static int _csid_from_name(char *csid, const char *name)
+{
+	int i;
+
+	for (i = 0; i < num_nodes; i++) {
+		if (strcmp(name, nodes[i].cn_name) == 0) {
+			memcpy(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN);
+			return 0;
+		}
+	}
+	return -1;
+}
+
+/* Convert a CSID to a node name */
+static int _name_from_csid(const char *csid, char *name)
+{
+	int i;
+
+	for (i = 0; i < num_nodes; i++) {
+		if (memcmp(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN) == 0) {
+			strcpy(name, nodes[i].cn_name);
+			return 0;
+		}
+	}
+	/* Who?? */
+	strcpy(name, "Unknown");
+	return -1;
+}
+
+/* Convert a node ID to a node name */
+static int name_from_nodeid(int nodeid, char *name)
+{
+	int i;
+
+	for (i = 0; i < num_nodes; i++) {
+		if (nodeid == nodes[i].cn_nodeid) {
+			strcpy(name, nodes[i].cn_name);
+			return 0;
+		}
+	}
+	/* Who?? */
+	strcpy(name, "Unknown");
+	return -1;
+}
+
+/* Convert a CSID to a node ID */
+static int nodeid_from_csid(const char *csid)
+{
+        int nodeid;
+
+	memcpy(&nodeid, csid, CMAN_MAX_CSID_LEN);
+
+	return nodeid;
+}
+
+static int _is_quorate()
+{
+	return cman_is_quorate(c_handle);
+}
+
+static void sync_ast_routine(void *arg)
+{
+	struct lock_wait *lwait = arg;
+
+	pthread_mutex_lock(&lwait->mutex);
+	pthread_cond_signal(&lwait->cond);
+	pthread_mutex_unlock(&lwait->mutex);
+}
+
+static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
+{
+	int status;
+	struct lock_wait lwait;
+
+	if (!lockid) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	DEBUGLOG("sync_lock: '%s' mode:%d flags=%d\n", resource,mode,flags);
+	/* Conversions need the lockid in the LKSB */
+	if (flags & LKF_CONVERT)
+		lwait.lksb.sb_lkid = *lockid;
+
+	pthread_cond_init(&lwait.cond, NULL);
+	pthread_mutex_init(&lwait.mutex, NULL);
+	pthread_mutex_lock(&lwait.mutex);
+
+	status = dlm_ls_lock(lockspace,
+			     mode,
+			     &lwait.lksb,
+			     flags,
+			     resource,
+			     strlen(resource),
+			     0, sync_ast_routine, &lwait, NULL, NULL);
+	if (status)
+		return status;
+
+	/* Wait for it to complete */
+	pthread_cond_wait(&lwait.cond, &lwait.mutex);
+	pthread_mutex_unlock(&lwait.mutex);
+
+	*lockid = lwait.lksb.sb_lkid;
+
+	errno = lwait.lksb.sb_status;
+	DEBUGLOG("sync_lock: returning lkid %x\n", *lockid);
+	if (lwait.lksb.sb_status)
+		return -1;
+	else
+		return 0;
+}
+
+static int _sync_unlock(const char *resource /* UNUSED */, int lockid)
+{
+	int status;
+	struct lock_wait lwait;
+
+	DEBUGLOG("sync_unlock: '%s' lkid:%x\n", resource, lockid);
+
+	pthread_cond_init(&lwait.cond, NULL);
+	pthread_mutex_init(&lwait.mutex, NULL);
+	pthread_mutex_lock(&lwait.mutex);
+
+	status = dlm_ls_unlock(lockspace, lockid, 0, &lwait.lksb, &lwait);
+
+	if (status)
+		return status;
+
+	/* Wait for it to complete */
+	pthread_cond_wait(&lwait.cond, &lwait.mutex);
+	pthread_mutex_unlock(&lwait.mutex);
+
+	errno = lwait.lksb.sb_status;
+	if (lwait.lksb.sb_status != EUNLOCK)
+		return -1;
+	else
+		return 0;
+
+}
+
+static int _get_cluster_name(char *buf, int buflen)
+{
+	cman_cluster_t cluster_info;
+	int status;
+
+	status = cman_get_cluster(c_handle, &cluster_info);
+	if (!status) {
+		strncpy(buf, cluster_info.ci_name, buflen);
+	}
+	return status;
+}
+
+static struct cluster_ops _cluster_cman_ops = {
+	.cluster_init_completed   = _cluster_init_completed,
+	.cluster_send_message     = _cluster_send_message,
+	.name_from_csid           = _name_from_csid,
+	.csid_from_name           = _csid_from_name,
+	.get_num_nodes            = _get_num_nodes,
+	.cluster_fd_callback      = _cluster_fd_callback,
+	.get_main_cluster_fd      = _get_main_cluster_fd,
+	.cluster_do_node_callback = _cluster_do_node_callback,
+	.is_quorate               = _is_quorate,
+	.get_our_csid             = _get_our_csid,
+	.add_up_node              = _add_up_node,
+	.cluster_closedown        = _cluster_closedown,
+	.get_cluster_name         = _get_cluster_name,
+	.sync_lock                = _sync_lock,
+	.sync_unlock              = _sync_unlock,
+};
+
+struct cluster_ops *init_cman_cluster(void)
+{
+	if (!_init_cluster())
+		return &_cluster_cman_ops;
+	else
+		return NULL;
+}
Index: src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd-command.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd-command.c
diff -N src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd-command.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd-command.c	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,343 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+
+  CLVMD Cluster LVM daemon command processor.
+
+  To add commands to the daemon simply add a processor in do_command and return
+  and messages back in buf and the length in *retlen. The initial value of
+  buflen is the maximum size of the buffer. if buf is not large enough then it
+  may be reallocated by the functions in here to a suitable size bearing in
+  mind that anything larger than the passed-in size will have to be returned
+  using the system LV and so performance will suffer.
+
+  The status return will be negated and passed back to the originating node.
+
+  pre- and post- command routines are called only on the local node. The
+  purpose is primarily to get and release locks, though the pre- routine should
+  also do any other local setups required by the command (if any) and can
+  return a failure code that prevents the command from being distributed around
+  the cluster
+
+  The pre- and post- routines are run in their own thread so can block as long
+  they like, do_command is run in the main clvmd thread so should not block for
+  too long. If the pre-command returns an error code (!=0) then the command
+  will not be propogated around the cluster but the post-command WILL be called
+
+  Also note that the pre and post routine are *always* called on the local
+  node, even if the command to be executed was only requested to run on a
+  remote node. It may peek inside the client structure to check the status of
+  the command.
+
+  The clients of the daemon must, naturally, understand the return messages and
+  codes.
+
+  Routines in here may only READ the values in the client structure passed in
+  apart from client->private which they are free to do what they like with.
+
+*/
+
+#define _GNU_SOURCE
+#define _FILE_OFFSET_BITS 64
+
+#include <configure.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <errno.h>
+#include <libdevmapper.h>
+#include <libdlm.h>
+
+#include "locking.h"
+#include "lvm-logging.h"
+#include "lvm-functions.h"
+#include "clvmd-comms.h"
+#include "clvm.h"
+#include "clvmd.h"
+
+extern debug_t debug;
+extern struct cluster_ops *clops;
+
+/* This is where all the real work happens:
+   NOTE: client will be NULL when this is executed on a remote node */
+int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
+	       char **buf, int buflen, int *retlen)
+{
+	char *args = msg->node + strlen(msg->node) + 1;
+	int arglen = msglen - sizeof(struct clvm_header) - strlen(msg->node);
+	int status = 0;
+	char *lockname;
+	struct utsname nodeinfo;
+	unsigned char lock_cmd;
+	unsigned char lock_flags;
+
+	/* Do the command */
+	switch (msg->cmd) {
+		/* Just a test message */
+	case CLVMD_CMD_TEST:
+		if (arglen > buflen) {
+			char *new_buf;
+			buflen = arglen + 200;
+			new_buf = realloc(*buf, buflen);
+			if (new_buf == NULL) {
+				status = errno;
+				free (*buf);
+			}
+			*buf = new_buf;
+		}
+		if (*buf) {
+			uname(&nodeinfo);
+			*retlen = 1 + snprintf(*buf, buflen,
+					       "TEST from %s: %s v%s",
+					       nodeinfo.nodename, args,
+					       nodeinfo.release);
+		}
+		break;
+
+	case CLVMD_CMD_LOCK_VG:
+		lockname = &args[2];
+		/* Check to see if the VG is in use by LVM1 */
+		status = do_check_lvm1(lockname);
+		/* P_#global causes a full cache refresh */
+		if (!strcmp(lockname, "P_" VG_GLOBAL))
+			do_refresh_cache();
+		else
+			drop_metadata(lockname + 2);
+
+		break;
+
+	case CLVMD_CMD_LOCK_LV:
+		/* This is the biggie */
+		lock_cmd = args[0] & 0x3F;
+		lock_flags = args[1];
+		lockname = &args[2];
+		status = do_lock_lv(lock_cmd, lock_flags, lockname);
+		/* Replace EIO with something less scary */
+		if (status == EIO) {
+			*retlen =
+			    1 + snprintf(*buf, buflen, "%s",
+					 get_last_lvm_error());
+			return EIO;
+		}
+		break;
+
+	case CLVMD_CMD_REFRESH:
+		do_refresh_cache();
+		break;
+
+	case CLVMD_CMD_SET_DEBUG:
+		debug = args[0];
+		break;
+
+	case CLVMD_CMD_GET_CLUSTERNAME:
+		status = clops->get_cluster_name(*buf, buflen);
+		if (!status)
+			*retlen = strlen(*buf)+1;
+		break;
+
+	case CLVMD_CMD_VG_BACKUP:
+		lvm_do_backup(&args[2]);
+		break;
+
+	default:
+		/* Won't get here because command is validated in pre_command */
+		break;
+	}
+
+	/* Check the status of the command and return the error text */
+	if (status) {
+		*retlen = 1 + snprintf(*buf, buflen, "%s", strerror(status));
+	}
+
+	return status;
+
+}
+
+static int lock_vg(struct local_client *client)
+{
+    struct dm_hash_table *lock_hash;
+    struct clvm_header *header =
+	(struct clvm_header *) client->bits.localsock.cmd;
+    unsigned char lock_cmd;
+    unsigned char lock_flags;
+    char *args = header->node + strlen(header->node) + 1;
+    int lkid;
+    int status = 0;
+    char *lockname;
+
+    /* Keep a track of VG locks in our own hash table. In current
+       practice there should only ever be more than two VGs locked
+       if a user tries to merge lots of them at once */
+    if (client->bits.localsock.private) {
+	lock_hash = (struct dm_hash_table *)client->bits.localsock.private;
+    }
+    else {
+	lock_hash = dm_hash_create(3);
+	if (!lock_hash)
+	    return ENOMEM;
+	client->bits.localsock.private = (void *)lock_hash;
+    }
+
+    lock_cmd = args[0] & 0x3F;
+    lock_flags = args[1];
+    lockname = &args[2];
+    DEBUGLOG("doing PRE command LOCK_VG '%s' at %x (client=%p)\n", lockname, lock_cmd, client);
+
+    if (lock_cmd == LCK_UNLOCK) {
+
+	lkid = (int)(long)dm_hash_lookup(lock_hash, lockname);
+	if (lkid == 0)
+	    return EINVAL;
+
+	status = sync_unlock(lockname, lkid);
+	if (status)
+	    status = errno;
+	else
+	    dm_hash_remove(lock_hash, lockname);
+    }
+    else {
+	/* Read locks need to be PR; other modes get passed through */
+	if ((lock_cmd & LCK_TYPE_MASK) == LCK_READ) {
+	    lock_cmd &= ~LCK_TYPE_MASK;
+	    lock_cmd |= LCK_PREAD;
+	}
+	status = sync_lock(lockname, (int)lock_cmd, (lock_flags & LCK_NONBLOCK) ? LKF_NOQUEUE : 0, &lkid);
+	if (status)
+	    status = errno;
+	else
+	    dm_hash_insert(lock_hash, lockname, (void *)(long)lkid);
+    }
+
+    return status;
+}
+
+
+/* Pre-command is a good place to get locks that are needed only for the duration
+   of the commands around the cluster (don't forget to free them in post-command),
+   and to sanity check the command arguments */
+int do_pre_command(struct local_client *client)
+{
+	struct clvm_header *header =
+	    (struct clvm_header *) client->bits.localsock.cmd;
+	unsigned char lock_cmd;
+	unsigned char lock_flags;
+	char *args = header->node + strlen(header->node) + 1;
+	int lockid;
+	int status = 0;
+	char *lockname;
+
+	switch (header->cmd) {
+	case CLVMD_CMD_TEST:
+		status = sync_lock("CLVMD_TEST", LKM_EXMODE, 0, &lockid);
+		client->bits.localsock.private = (void *)(long)lockid;
+		break;
+
+	case CLVMD_CMD_LOCK_VG:
+		lockname = &args[2];
+		/* We take out a real lock unless LCK_CACHE was set */
+		if (!strncmp(lockname, "V_", 2) ||
+		    !strncmp(lockname, "P_#", 3))
+			status = lock_vg(client);
+		break;
+
+	case CLVMD_CMD_LOCK_LV:
+		lock_cmd = args[0];
+		lock_flags = args[1];
+		lockname = &args[2];
+		status = pre_lock_lv(lock_cmd, lock_flags, lockname);
+		break;
+
+	case CLVMD_CMD_REFRESH:
+	case CLVMD_CMD_GET_CLUSTERNAME:
+	case CLVMD_CMD_SET_DEBUG:
+	case CLVMD_CMD_VG_BACKUP:
+		break;
+
+	default:
+		log_error("Unknown command %d received\n", header->cmd);
+		status = EINVAL;
+	}
+	return status;
+}
+
+/* Note that the post-command routine is called even if the pre-command or the real command
+   failed */
+int do_post_command(struct local_client *client)
+{
+	struct clvm_header *header =
+	    (struct clvm_header *) client->bits.localsock.cmd;
+	int status = 0;
+	unsigned char lock_cmd;
+	unsigned char lock_flags;
+	char *args = header->node + strlen(header->node) + 1;
+	char *lockname;
+
+	switch (header->cmd) {
+	case CLVMD_CMD_TEST:
+		status =
+		    sync_unlock("CLVMD_TEST", (int) (long) client->bits.localsock.private);
+		client->bits.localsock.private = 0;
+		break;
+
+	case CLVMD_CMD_LOCK_VG:
+	case CLVMD_CMD_VG_BACKUP:
+		/* Nothing to do here */
+		break;
+
+	case CLVMD_CMD_LOCK_LV:
+		lock_cmd = args[0];
+		lock_flags = args[1];
+		lockname = &args[2];
+		status = post_lock_lv(lock_cmd, lock_flags, lockname);
+		break;
+	}
+	return status;
+}
+
+
+/* Called when the client is about to be deleted */
+void cmd_client_cleanup(struct local_client *client)
+{
+    if (client->bits.localsock.private) {
+
+	struct dm_hash_node *v;
+	struct dm_hash_table *lock_hash =
+	    (struct dm_hash_table *)client->bits.localsock.private;
+
+	dm_hash_iterate(v, lock_hash) {
+		int lkid = (int)(long)dm_hash_get_data(lock_hash, v);
+		char *lockname = dm_hash_get_key(lock_hash, v);
+
+		DEBUGLOG("cleanup: Unlocking lock %s %x\n", lockname, lkid);
+		sync_unlock(lockname, lkid);
+	}
+
+	dm_hash_destroy(lock_hash);
+	client->bits.localsock.private = 0;
+    }
+}
Index: src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd-comms.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd-comms.h
diff -N src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd-comms.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd-comms.h	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,99 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Abstraction layer for clvmd cluster communications
+ */
+
+#ifndef _CLVMD_COMMS_H
+#define _CLVMD_COMMS_H
+
+struct local_client;
+
+struct cluster_ops {
+	void (*cluster_init_completed) (void);
+
+	int (*cluster_send_message) (const void *buf, int msglen,
+				     const char *csid,
+				     const char *errtext);
+	int (*name_from_csid) (const char *csid, char *name);
+	int (*csid_from_name) (char *csid, const char *name);
+	int (*get_num_nodes) (void);
+	int (*cluster_fd_callback) (struct local_client *fd, char *buf, int len,
+				    const char *csid,
+				    struct local_client **new_client);
+	int (*get_main_cluster_fd) (void);	/* gets accept FD or cman cluster socket */
+	int (*cluster_do_node_callback) (struct local_client *client,
+					 void (*callback) (struct local_client *,
+							   const char *csid,
+							   int node_up));
+	int (*is_quorate) (void);
+
+	void (*get_our_csid) (char *csid);
+	void (*add_up_node) (const char *csid);
+	void (*reread_config) (void);
+	void (*cluster_closedown) (void);
+
+	int (*get_cluster_name)(char *buf, int buflen);
+
+	int (*sync_lock) (const char *resource, int mode,
+			  int flags, int *lockid);
+	int (*sync_unlock) (const char *resource, int lockid);
+
+};
+
+#ifdef USE_GULM
+#  include "tcp-comms.h"
+struct cluster_ops *init_gulm_cluster(void);
+#define MAX_CSID_LEN 			GULM_MAX_CSID_LEN
+#define MAX_CLUSTER_MEMBER_NAME_LEN	GULM_MAX_CLUSTER_MEMBER_NAME_LEN
+#endif
+
+#ifdef USE_CMAN
+#  include <netinet/in.h>
+#  include "libcman.h"
+#  define CMAN_MAX_CSID_LEN 4
+#  ifndef MAX_CSID_LEN
+#    define MAX_CSID_LEN CMAN_MAX_CSID_LEN
+#  endif
+#  undef MAX_CLUSTER_MEMBER_NAME_LEN
+#  define MAX_CLUSTER_MEMBER_NAME_LEN   CMAN_MAX_NODENAME_LEN
+#  define CMAN_MAX_CLUSTER_MESSAGE 1500
+#  define CLUSTER_PORT_CLVMD 11
+struct cluster_ops *init_cman_cluster(void);
+#endif
+
+#ifdef USE_OPENAIS
+#  include <openais/saAis.h>
+#  include <openais/totem/totem.h>
+#  define OPENAIS_CSID_LEN (sizeof(int))
+#  define OPENAIS_MAX_CLUSTER_MESSAGE         MESSAGE_SIZE_MAX
+#  define OPENAIS_MAX_CLUSTER_MEMBER_NAME_LEN SA_MAX_NAME_LENGTH
+#  ifndef MAX_CLUSTER_MEMBER_NAME_LEN
+#    define MAX_CLUSTER_MEMBER_NAME_LEN       SA_MAX_NAME_LENGTH
+#  endif
+#  ifndef CMAN_MAX_CLUSTER_MESSAGE
+#    define CMAN_MAX_CLUSTER_MESSAGE          MESSAGE_SIZE_MAX
+#  endif
+#  ifndef MAX_CSID_LEN
+#    define MAX_CSID_LEN sizeof(int)
+#  endif
+struct cluster_ops *init_openais_cluster(void);
+#endif
+
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd-gulm.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd-gulm.c
diff -N src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd-gulm.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd-gulm.c	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,1013 @@
+/*	$NetBSD$	*/
+
+/******************************************************************************
+*******************************************************************************
+**
+**  Copyright (C) Sistina Software, Inc.  2002-2003  All rights reserved.
+**  Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+**
+*******************************************************************************
+******************************************************************************/
+
+/* This provides the interface between clvmd and gulm as the cluster
+ * and lock manager.
+ *
+ * It also provides the "liblm" functions too as it's hard (and pointless)
+ * to seperate them out when using gulm.
+ *
+ * What it does /not/ provide is the communications between clvmd daemons
+ * on the cluster nodes. That is done in tcp-comms.c
+ */
+
+
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+#include <utmpx.h>
+#include <syslog.h>
+#include <assert.h>
+#include <libdevmapper.h>
+#include <ccs.h>
+#include <libgulm.h>
+
+#include "locking.h"
+#include "lvm-logging.h"
+#include "clvm.h"
+#include "clvmd-comms.h"
+#include "lvm-functions.h"
+#include "clvmd.h"
+#include "clvmd-gulm.h"
+
+/* Hash list of nodes in the cluster */
+static struct dm_hash_table *node_hash;
+
+/* hash list of outstanding lock requests */
+static struct dm_hash_table *lock_hash;
+
+/* Copy of the current quorate state */
+static uint8_t gulm_quorate = 0;
+static enum {INIT_NOTDONE, INIT_DONE, INIT_WAITQUORATE} init_state = INIT_NOTDONE;
+
+/* Number of active nodes */
+static int num_nodes;
+
+static char *cluster_name;
+static int in_shutdown = 0;
+
+static pthread_mutex_t lock_start_mutex;
+static volatile int lock_start_flag;
+
+struct node_info
+{
+    enum {NODE_UNKNOWN, NODE_DOWN, NODE_UP, NODE_CLVMD} state;
+    char name[GULM_MAX_CLUSTER_MEMBER_NAME_LEN];
+};
+
+struct lock_wait
+{
+    pthread_cond_t cond;
+    pthread_mutex_t mutex;
+    int status;
+};
+
+/* Forward */
+static int read_from_core_sock(struct local_client *client, char *buf, int len, const char *csid,
+			       struct local_client **new_client);
+static int read_from_lock_sock(struct local_client *client, char *buf, int len, const char *csid,
+			       struct local_client **new_client);
+static int get_all_cluster_nodes(void);
+static int _csid_from_name(char *csid, const char *name);
+static void _cluster_closedown(void);
+
+/* In tcp-comms.c */
+extern struct dm_hash_table *sock_hash;
+
+static int add_internal_client(int fd, fd_callback_t callback)
+{
+    struct local_client *client;
+
+    DEBUGLOG("Add_internal_client, fd = %d\n", fd);
+
+    /* Add a GULM file descriptor it to the main loop */
+    client = malloc(sizeof(struct local_client));
+    if (!client)
+    {
+	DEBUGLOG("malloc failed\n");
+	return -1;
+    }
+
+    memset(client, 0, sizeof(struct local_client));
+    client->fd = fd;
+    client->type = CLUSTER_INTERNAL;
+    client->callback = callback;
+    add_client(client);
+
+    /* Set Close-on-exec */
+    fcntl(fd, F_SETFD, 1);
+
+    return 0;
+}
+
+/* Gulm library handle */
+static gulm_interface_p gulm_if;
+static lg_core_callbacks_t core_callbacks;
+static lg_lockspace_callbacks_t lock_callbacks;
+
+static void badsig_handler(int sig)
+{
+    DEBUGLOG("got sig %d\n", sig);
+    _cluster_closedown();
+    exit(0);
+}
+
+static void _reread_config(void)
+{
+        /* Re-read CCS node list */
+	DEBUGLOG("Re-reading CCS config\n");
+	get_all_cluster_nodes();
+}
+
+static int _init_cluster(void)
+{
+    int status;
+    int ccs_h;
+    int port = 0;
+    char *portstr;
+
+    /* Get cluster name from CCS */
+    ccs_h = ccs_force_connect(NULL, 0);
+    if (ccs_h < 0)
+    {
+	syslog(LOG_ERR, "Cannot login in to CCSD server\n");
+	return -1;
+    }
+
+    ccs_get(ccs_h, "//cluster/@name", &cluster_name);
+    DEBUGLOG("got cluster name %s\n", cluster_name);
+
+    if (!ccs_get(ccs_h, "//cluster/clvm/@port", &portstr))
+    {
+	port = atoi(portstr);
+	free(portstr);
+	DEBUGLOG("got port number %d\n", port);
+
+	if (port <= 0 && port >= 65536)
+	    port = 0;
+    }
+
+    ccs_disconnect(ccs_h);
+
+    /* Block locking until we are logged in */
+    pthread_mutex_init(&lock_start_mutex, NULL);
+    pthread_mutex_lock(&lock_start_mutex);
+    lock_start_flag = 1;
+
+    node_hash = dm_hash_create(100);
+    lock_hash = dm_hash_create(10);
+
+    /* Get all nodes from CCS */
+    if (get_all_cluster_nodes())
+	return -1;
+
+    /* Initialise GULM library */
+    status = lg_initialize(&gulm_if, cluster_name, "clvmd");
+    if (status)
+    {
+	DEBUGLOG("lg_initialize failed: %d\n", status);
+	return status;
+    }
+
+    /* Connect to core - we are not "important" :-) */
+    status = lg_core_login(gulm_if, 0);
+    if (status)
+    {
+	DEBUGLOG("lg_core_login failed: %d\n", status);
+	return status;
+    }
+
+    /* Initialise the inter-node comms */
+    status = init_comms(port);
+    if (status)
+	return status;
+
+    /* Add core FD to the list */
+    status = add_internal_client(lg_core_selector(gulm_if), read_from_core_sock);
+    if (status)
+    {
+	DEBUGLOG("can't allocate client space\n");
+	return status;
+    }
+
+    /* Connect to the lock server */
+    if (lg_lock_login(gulm_if, "CLVM"))
+    {
+	syslog(LOG_ERR, "Cannot login in to LOCK server\n");
+	DEBUGLOG("Cannot login in to LOCK server\n");
+	exit(88);
+    }
+
+    /* Add lockspace FD to the list */
+    status = add_internal_client(lg_lock_selector(gulm_if), read_from_lock_sock);
+    if (status)
+    {
+	DEBUGLOG("can't allocate client space\n");
+	exit(status);
+    }
+
+    /* Request a list of nodes, we can't really do anything until
+       this comes back */
+    status = lg_core_nodelist(gulm_if);
+    if (status)
+    {
+	DEBUGLOG("lg_core_nodelist failed: %d\n", status);
+	return status;
+    }
+
+    /* So I can kill it without taking GULM down too */
+    signal(SIGINT, badsig_handler);
+    signal(SIGTERM, badsig_handler);
+
+    return 0;
+}
+
+static void _cluster_closedown(void)
+{
+    DEBUGLOG("cluster_closedown\n");
+    in_shutdown = 1;
+    unlock_all();
+    lg_lock_logout(gulm_if);
+    lg_core_logout(gulm_if);
+    lg_release(gulm_if);
+}
+
+/* Expire locks for a named node, or us */
+#define GIO_KEY_SIZE 46
+static void drop_expired_locks(char *nodename)
+{
+    struct utsname nodeinfo;
+    uint8_t mask[GIO_KEY_SIZE];
+
+    DEBUGLOG("Dropping expired locks for %s\n", nodename?nodename:"(null)");
+    memset(mask, 0xff, GIO_KEY_SIZE);
+
+    if (!nodename)
+    {
+	uname(&nodeinfo);
+	nodename = nodeinfo.nodename;
+    }
+
+    if (lg_lock_drop_exp(gulm_if, nodename, mask, GIO_KEY_SIZE))
+    {
+	DEBUGLOG("Error calling lg_lock_drop_exp()\n");
+    }
+}
+
+
+static int read_from_core_sock(struct local_client *client, char *buf, int len, const char *csid,
+			       struct local_client **new_client)
+{
+    int status;
+
+    *new_client = NULL;
+    status = lg_core_handle_messages(gulm_if, &core_callbacks, NULL);
+    return status<0 ? status : 1;
+}
+
+static int read_from_lock_sock(struct local_client *client, char *buf, int len, const char *csid,
+			       struct local_client **new_client)
+{
+    int status;
+
+    *new_client = NULL;
+    status = lg_lock_handle_messages(gulm_if, &lock_callbacks, NULL);
+    return status<0 ? status : 1;
+}
+
+
+/* CORE callback routines */
+static int core_login_reply(void *misc, uint64_t gen, uint32_t error, uint32_t rank, uint8_t corestate)
+{
+   DEBUGLOG("CORE Got a Login reply.  gen:%lld err:%d rank:%d corestate:%d\n",
+         gen, error, rank, corestate);
+
+   if (error)
+       exit(error);
+
+   /* Get the current core state (for quorum) */
+   lg_core_corestate(gulm_if);
+
+   return 0;
+}
+
+static void set_node_state(struct node_info *ninfo, char *csid, uint8_t nodestate)
+{
+    if (nodestate == lg_core_Logged_in)
+    {
+	/* Don't clobber NODE_CLVMD state */
+	if (ninfo->state != NODE_CLVMD)
+	{
+	    if (ninfo->state == NODE_UNKNOWN ||
+		ninfo->state == NODE_DOWN)
+		num_nodes++;
+
+	    ninfo->state = NODE_UP;
+	}
+    }
+    else
+    {
+	if (nodestate == lg_core_Expired ||
+	    nodestate == lg_core_Fenced ||
+	    nodestate == lg_core_Logged_out)
+	{
+	    if (ninfo->state != NODE_DOWN)
+		num_nodes--;
+	    ninfo->state = NODE_DOWN;
+	}
+    }
+    /* Gulm doesn't always send node DOWN events, so even if this a a node UP we must
+     * assume (ahem) that it prevously went down at some time. So we close
+     * the sockets here to make sure that we don't have any dead connections
+     * to that node.
+     */
+    tcp_remove_client(csid);
+
+    DEBUGLOG("set_node_state, '%s' state = %d num_nodes=%d\n",
+	     ninfo->name, ninfo->state, num_nodes);
+}
+
+static struct node_info *add_or_set_node(char *name, struct in6_addr *ip, uint8_t state)
+{
+    struct node_info *ninfo;
+
+    ninfo = dm_hash_lookup_binary(node_hash, (char *)ip, GULM_MAX_CSID_LEN);
+    if (!ninfo)
+    {
+	/* If we can't find that node then re-read the config file in case it
+	   was added after we were started */
+	DEBUGLOG("Node %s not found, re-reading config file\n", name);
+	get_all_cluster_nodes();
+
+	/* Now try again */
+	ninfo = dm_hash_lookup_binary(node_hash, (char *)ip, GULM_MAX_CSID_LEN);
+	if (!ninfo)
+	{
+	    DEBUGLOG("Ignoring node %s, not part of the SAN cluster\n", name);
+	    return NULL;
+	}
+    }
+
+    set_node_state(ninfo, (char *)ip, state);
+
+    return ninfo;
+}
+
+static void _get_our_csid(char *csid)
+{
+	get_our_gulm_csid(csid);
+}
+
+static int core_nodelist(void *misc, lglcb_t type, char *name, struct in6_addr *ip, uint8_t state)
+{
+    DEBUGLOG("CORE nodelist\n");
+
+    if (type == lglcb_start)
+    {
+	DEBUGLOG("Got Nodelist, start\n");
+    }
+    else
+    {
+	if (type == lglcb_item)
+	{
+	    DEBUGLOG("Got nodelist, item: %s, %#x\n", name, state);
+
+	    add_or_set_node(name, ip, state);
+	}
+	else
+	{
+	    if (type == lglcb_stop)
+	    {
+		char ourcsid[GULM_MAX_CSID_LEN];
+
+		DEBUGLOG("Got Nodelist, stop\n");
+		if (gulm_quorate)
+		{
+			clvmd_cluster_init_completed();
+			init_state = INIT_DONE;
+		}
+		else
+		{
+			if (init_state == INIT_NOTDONE)
+				init_state = INIT_WAITQUORATE;
+		}
+
+		/* Mark ourself as up */
+		_get_our_csid(ourcsid);
+		gulm_add_up_node(ourcsid);
+	    }
+	    else
+	    {
+		DEBUGLOG("Unknown lglcb_t %#x\n", type);
+	    }
+	}
+    }
+
+    return 0;
+}
+
+static int core_statechange(void *misc, uint8_t corestate, uint8_t quorate, struct in6_addr *masterip, char *mastername)
+{
+    DEBUGLOG("CORE Got statechange. quorate:%d, corestate:%x mastername:%s\n",
+	     quorate, corestate, mastername);
+
+    gulm_quorate = quorate;
+    if (quorate && init_state == INIT_WAITQUORATE)
+    {
+	    clvmd_cluster_init_completed();
+	    init_state = INIT_DONE;
+    }
+    return 0;
+}
+
+static int core_nodechange(void *misc, char *nodename, struct in6_addr *nodeip, uint8_t nodestate)
+{
+    struct node_info *ninfo;
+
+    DEBUGLOG("CORE node change, name=%s, state = %d\n", nodename, nodestate);
+
+    /* If we don't get nodeip here, try a lookup by name */
+    if (!nodeip)
+	_csid_from_name((char *)nodeip, nodename);
+    if (!nodeip)
+	return 0;
+
+    ninfo = add_or_set_node(nodename, nodeip, nodestate);
+    if (!ninfo)
+	return 0;
+
+    /* Check if we need to drop any expired locks */
+    if (ninfo->state == NODE_DOWN)
+    {
+	drop_expired_locks(nodename);
+    }
+
+    return 0;
+}
+static int core_error(void *misc, uint32_t err)
+{
+    DEBUGLOG("CORE error: %d\n", err);
+    // Not sure what happens here
+    return 0;
+}
+
+/* LOCK callback routines */
+static int lock_login_reply(void *misc, uint32_t error, uint8_t which)
+{
+    DEBUGLOG("LOCK Got a Login reply.  err:%d which:%d\n",
+	     error, which);
+
+    if (error)
+	exit(error);
+
+    /* Drop any expired locks for us that might be hanging around */
+    drop_expired_locks(NULL);
+
+    /* Enable locking operations in other threads */
+    if (lock_start_flag)
+    {
+	lock_start_flag = 0;
+	pthread_mutex_unlock(&lock_start_mutex);
+    }
+
+    return 0;
+}
+
+static int lock_lock_state(void *misc, uint8_t *key, uint16_t keylen,
+			   uint64_t subid, uint64_t start, uint64_t stop,
+			   uint8_t state, uint32_t flags, uint32_t error,
+			   uint8_t *LVB, uint16_t LVBlen)
+{
+    struct lock_wait *lwait;
+
+    DEBUGLOG("LOCK lock state: %s, error = %d\n", key, error);
+
+    /* No waiting process to wake up when we are shutting down */
+    if (in_shutdown)
+	    return 0;
+
+    lwait = dm_hash_lookup(lock_hash, key);
+    if (!lwait)
+    {
+	DEBUGLOG("Can't find hash entry for resource %s\n", key);
+	return 0;
+    }
+    lwait->status = error;
+    pthread_mutex_lock(&lwait->mutex);
+    pthread_cond_signal(&lwait->cond);
+    pthread_mutex_unlock(&lwait->mutex);
+
+    return 0;
+}
+static int lock_error(void *misc, uint32_t err)
+{
+    DEBUGLOG("LOCK error: %d\n", err);
+    // Not sure what happens here
+    return 0;
+}
+
+
+/* CORE callbacks */
+static lg_core_callbacks_t core_callbacks = {
+    .login_reply  = core_login_reply,
+    .nodelist     = core_nodelist,
+    .statechange  = core_statechange,
+    .nodechange   = core_nodechange,
+    .error        = core_error,
+};
+
+/* LOCK callbacks */
+static lg_lockspace_callbacks_t lock_callbacks = {
+    .login_reply   = lock_login_reply,
+    .lock_state    = lock_lock_state,
+    .error         = lock_error,
+};
+
+/* Allow tcp-comms to loop round the list of active nodes */
+int get_next_node_csid(void **context, char *csid)
+{
+    struct node_info *ninfo = NULL;
+
+    /* First node */
+    if (!*context)
+    {
+	*context = dm_hash_get_first(node_hash);
+    }
+    else
+    {
+	*context = dm_hash_get_next(node_hash, *context);
+    }
+    if (*context)
+	ninfo = dm_hash_get_data(node_hash, *context);
+
+    /* Find a node that is UP */
+    while (*context && ninfo->state == NODE_DOWN)
+    {
+	*context = dm_hash_get_next(node_hash, *context);
+	if (*context)
+	{
+	    ninfo = dm_hash_get_data(node_hash, *context);
+	}
+    }
+
+    if (!*context || ninfo->state == NODE_DOWN)
+    {
+	return 0;
+    }
+
+    memcpy(csid, dm_hash_get_key(node_hash, *context), GULM_MAX_CSID_LEN);
+    return 1;
+}
+
+int gulm_name_from_csid(const char *csid, char *name)
+{
+    struct node_info *ninfo;
+
+    ninfo = dm_hash_lookup_binary(node_hash, csid, GULM_MAX_CSID_LEN);
+    if (!ninfo)
+    {
+        sprintf(name, "UNKNOWN %s", print_csid(csid));
+	return -1;
+    }
+
+    strcpy(name, ninfo->name);
+    return 0;
+}
+
+
+static int _csid_from_name(char *csid, const char *name)
+{
+    struct dm_hash_node *hn;
+    struct node_info *ninfo;
+
+    dm_hash_iterate(hn, node_hash)
+    {
+	ninfo = dm_hash_get_data(node_hash, hn);
+	if (strcmp(ninfo->name, name) == 0)
+	{
+	    memcpy(csid, dm_hash_get_key(node_hash, hn), GULM_MAX_CSID_LEN);
+	    return 0;
+	}
+    }
+    return -1;
+}
+
+static int _get_num_nodes()
+{
+    DEBUGLOG("num_nodes = %d\n", num_nodes);
+    return num_nodes;
+}
+
+/* Node is now known to be running a clvmd */
+void gulm_add_up_node(const char *csid)
+{
+    struct node_info *ninfo;
+
+    ninfo = dm_hash_lookup_binary(node_hash, csid, GULM_MAX_CSID_LEN);
+    if (!ninfo) {
+	    DEBUGLOG("gulm_add_up_node no node_hash entry for csid %s\n", print_csid(csid));
+	return;
+    }
+
+    DEBUGLOG("gulm_add_up_node %s\n", ninfo->name);
+
+    if (ninfo->state == NODE_DOWN)
+	    num_nodes++;
+    ninfo->state = NODE_CLVMD;
+
+    return;
+
+}
+/* Node is now known to be NOT running a clvmd */
+void add_down_node(char *csid)
+{
+    struct node_info *ninfo;
+
+    ninfo = dm_hash_lookup_binary(node_hash, csid, GULM_MAX_CSID_LEN);
+    if (!ninfo)
+	return;
+
+    /* Only set it to UP if it was previously known to be
+       running clvmd - gulm may set it DOWN quite soon */
+    if (ninfo->state == NODE_CLVMD)
+	ninfo->state = NODE_UP;
+    drop_expired_locks(ninfo->name);
+    return;
+
+}
+
+/* Call a callback for each node, so the caller knows whether it's up or down */
+static int _cluster_do_node_callback(struct local_client *master_client,
+				     void (*callback)(struct local_client *, const char *csid, int node_up))
+{
+    struct dm_hash_node *hn;
+    struct node_info *ninfo;
+    int somedown = 0;
+
+    dm_hash_iterate(hn, node_hash)
+    {
+	char csid[GULM_MAX_CSID_LEN];
+	struct local_client *client;
+
+	ninfo = dm_hash_get_data(node_hash, hn);
+	memcpy(csid, dm_hash_get_key(node_hash, hn), GULM_MAX_CSID_LEN);
+
+	DEBUGLOG("down_callback. node %s, state = %d\n", ninfo->name, ninfo->state);
+
+	client = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
+	if (!client)
+	{
+	    /* If it's up but not connected, try to make contact */
+	    if (ninfo->state == NODE_UP)
+		    gulm_connect_csid(csid, &client);
+
+	    client = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
+
+	}
+	DEBUGLOG("down_callback2. node %s, state = %d\n", ninfo->name, ninfo->state);
+	if (ninfo->state != NODE_DOWN)
+		callback(master_client, csid, ninfo->state == NODE_CLVMD);
+
+	if (ninfo->state != NODE_CLVMD)
+		somedown = -1;
+    }
+    return somedown;
+}
+
+/* Convert gulm error codes to unix errno numbers */
+static int gulm_to_errno(int gulm_ret)
+{
+    switch (gulm_ret)
+    {
+    case lg_err_TryFailed:
+    case lg_err_AlreadyPend:
+	    errno = EAGAIN;
+	    break;
+
+	/* More?? */
+    default:
+	    errno = EINVAL;
+    }
+
+    return gulm_ret ? -1 : 0;
+}
+
+/* Real locking */
+static int _lock_resource(char *resource, int mode, int flags, int *lockid)
+{
+    int status;
+    struct lock_wait lwait;
+
+    /* Wait until the lock module is ready */
+    if (lock_start_flag)
+    {
+	pthread_mutex_lock(&lock_start_mutex);
+	pthread_mutex_unlock(&lock_start_mutex);
+    }
+
+    pthread_cond_init(&lwait.cond, NULL);
+    pthread_mutex_init(&lwait.mutex, NULL);
+    pthread_mutex_lock(&lwait.mutex);
+
+    /* This needs to be converted from DLM/LVM2 value for GULM */
+    if (flags & LKF_NOQUEUE) flags = lg_lock_flag_Try;
+
+    dm_hash_insert(lock_hash, resource, &lwait);
+    DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
+
+    status = lg_lock_state_req(gulm_if, resource, strlen(resource)+1,
+			       0, 0, 0,
+			       mode, flags, NULL, 0);
+    if (status)
+    {
+	DEBUGLOG("lg_lock_state returned %d\n", status);
+	return status;
+    }
+
+    /* Wait for it to complete */
+    pthread_cond_wait(&lwait.cond, &lwait.mutex);
+    pthread_mutex_unlock(&lwait.mutex);
+
+    dm_hash_remove(lock_hash, resource);
+    DEBUGLOG("lock-resource returning %d\n", lwait.status);
+
+    return gulm_to_errno(lwait.status);
+}
+
+
+static int _unlock_resource(char *resource, int lockid)
+{
+    int status;
+    struct lock_wait lwait;
+
+    pthread_cond_init(&lwait.cond, NULL);
+    pthread_mutex_init(&lwait.mutex, NULL);
+    pthread_mutex_lock(&lwait.mutex);
+
+    dm_hash_insert(lock_hash, resource, &lwait);
+
+    DEBUGLOG("unlock_resource %s\n", resource);
+    status = lg_lock_state_req(gulm_if, resource, strlen(resource)+1,
+			       0, 0, 0,
+			       lg_lock_state_Unlock, 0, NULL, 0);
+
+    if (status)
+    {
+	DEBUGLOG("lg_lock_state(unlock) returned %d\n", status);
+	return status;
+    }
+
+    /* When we are shutting down, don't wait for unlocks
+       to be acknowledged, just do it. */
+    if (in_shutdown)
+	    return status;
+
+    /* Wait for it to complete */
+
+    pthread_cond_wait(&lwait.cond, &lwait.mutex);
+    pthread_mutex_unlock(&lwait.mutex);
+
+    dm_hash_remove(lock_hash, resource);
+
+    return gulm_to_errno(lwait.status);
+}
+
+
+/* These two locking functions MUST be called in a seperate thread from
+   the clvmd main loop because they expect to be woken up by it.
+
+   These are abstractions around the real locking functions (above)
+   as we need to emulate the DLM's EX/PW/CW interaction with GULM using
+   two locks.
+   To aid unlocking, we store the lock mode in the lockid (as GULM
+   doesn't use this).
+*/
+static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
+{
+    int status;
+    char lock1[strlen(resource)+3];
+    char lock2[strlen(resource)+3];
+
+    snprintf(lock1, sizeof(lock1), "%s-1", resource);
+    snprintf(lock2, sizeof(lock2), "%s-2", resource);
+
+    switch (mode)
+    {
+    case LCK_EXCL:
+	status = _lock_resource(lock1, lg_lock_state_Exclusive, flags, lockid);
+	if (status)
+	    goto out;
+
+	/* If we can't get this lock too then bail out */
+	status = _lock_resource(lock2, lg_lock_state_Exclusive, LCK_NONBLOCK, lockid);
+        if (status == lg_err_TryFailed)
+        {
+           _unlock_resource(lock1, *lockid);
+           status = -1;
+           errno = EAGAIN;
+        }
+	break;
+
+    case LCK_PREAD:
+    case LCK_READ:
+	status = _lock_resource(lock1, lg_lock_state_Shared, flags, lockid);
+	if (status)
+		goto out;
+	status = _unlock_resource(lock2, *lockid);
+	break;
+
+    case LCK_WRITE:
+	status = _lock_resource(lock2, lg_lock_state_Exclusive, flags, lockid);
+	if (status)
+		goto out;
+	status = _unlock_resource(lock1, *lockid);
+	break;
+
+    default:
+	status = -1;
+	errno = EINVAL;
+	break;
+    }
+ out:
+    *lockid = mode;
+    return status;
+}
+
+static int _sync_unlock(const char *resource, int lockid)
+{
+    int status = 0;
+    char lock1[strlen(resource)+3];
+    char lock2[strlen(resource)+3];
+
+    snprintf(lock1, sizeof(lock1), "%s-1", resource);
+    snprintf(lock2, sizeof(lock2), "%s-2", resource);
+
+    /* The held lock mode is in the lock id */
+    assert(lockid == LCK_EXCL ||
+	   lockid == LCK_READ ||
+	   lockid == LCK_PREAD ||
+	   lockid == LCK_WRITE);
+
+    status = _unlock_resource(lock1, lockid);
+    if (!status)
+	    status = _unlock_resource(lock2, lockid);
+
+    return status;
+}
+
+static int _is_quorate()
+{
+	return gulm_quorate;
+}
+
+/* Get all the cluster node names & IPs from CCS and
+   add them to our node list so we know who to talk to.
+   Called when we start up and if we get sent SIGHUP.
+*/
+static int get_all_cluster_nodes()
+{
+    int ctree;
+    char *nodename;
+    int error;
+    int i;
+
+    /* Open the config file */
+    ctree = ccs_force_connect(NULL, 1);
+    if (ctree < 0)
+    {
+	log_error("Error connecting to CCS");
+	return -1;
+    }
+
+    for (i=1;;i++)
+    {
+	char nodekey[256];
+	char nodeip[GULM_MAX_CSID_LEN];
+	int  clvmflag = 1;
+	char *clvmflagstr;
+	char key[256];
+
+	sprintf(nodekey, "//cluster/clusternodes/clusternode[%d]/@name", i);
+	error = ccs_get(ctree, nodekey, &nodename);
+	if (error)
+	    break;
+
+	sprintf(key, "//cluster/clusternodes/clusternode[@name=\"%s\"]/clvm", nodename);
+	if (!ccs_get(ctree, key, &clvmflagstr))
+	{
+	    clvmflag = atoi(clvmflagstr);
+	    free(clvmflagstr);
+	}
+
+	DEBUGLOG("Got node %s from ccs(clvmflag = %d)\n", nodename, clvmflag);
+	if ((get_ip_address(nodename, nodeip) == 0) && clvmflag)
+	{
+	    struct node_info *ninfo;
+
+	    /* If it's not in the list, then add it */
+	    ninfo = dm_hash_lookup_binary(node_hash, nodeip, GULM_MAX_CSID_LEN);
+	    if (!ninfo)
+	    {
+		ninfo = malloc(sizeof(struct node_info));
+		if (!ninfo)
+		{
+		    syslog(LOG_ERR, "Cannot alloc memory for node info\n");
+		    ccs_disconnect(ctree);
+		    return -1;
+		}
+		strcpy(ninfo->name, nodename);
+
+		ninfo->state = NODE_DOWN;
+		dm_hash_insert_binary(node_hash, nodeip, GULM_MAX_CSID_LEN, ninfo);
+	    }
+	}
+	else
+	{
+		if (!clvmflag) {
+			DEBUGLOG("node %s has clvm disabled\n", nodename);
+		}
+		else {
+			DEBUGLOG("Cannot resolve host name %s\n", nodename);
+			log_err("Cannot resolve host name %s\n", nodename);
+		}
+	}
+	free(nodename);
+    }
+
+    /* Finished with config file */
+    ccs_disconnect(ctree);
+
+    return 0;
+}
+
+static int _get_main_cluster_fd(void)
+{
+	return get_main_gulm_cluster_fd();
+}
+
+static int _cluster_fd_callback(struct local_client *fd, char *buf, int len, const char *csid, struct local_client **new_client)
+{
+	return cluster_fd_gulm_callback(fd, buf, len, csid, new_client);
+}
+
+static int _cluster_send_message(const void *buf, int msglen, const char *csid, const char *errtext)
+{
+	return gulm_cluster_send_message((char *)buf, msglen, csid, errtext);
+}
+
+static int _get_cluster_name(char *buf, int buflen)
+{
+	strncpy(buf, cluster_name, buflen);
+	return 0;
+}
+
+static struct cluster_ops _cluster_gulm_ops = {
+	.cluster_init_completed   = NULL,
+	.cluster_send_message     = _cluster_send_message,
+	.name_from_csid           = gulm_name_from_csid,
+	.csid_from_name           = _csid_from_name,
+	.get_num_nodes            = _get_num_nodes,
+	.cluster_fd_callback      = _cluster_fd_callback,
+	.get_main_cluster_fd      = _get_main_cluster_fd,
+	.cluster_do_node_callback = _cluster_do_node_callback,
+	.is_quorate               = _is_quorate,
+	.get_our_csid             = _get_our_csid,
+	.add_up_node              = gulm_add_up_node,
+	.reread_config            = _reread_config,
+	.cluster_closedown        = _cluster_closedown,
+	.get_cluster_name         = _get_cluster_name,
+	.sync_lock                = _sync_lock,
+	.sync_unlock              = _sync_unlock,
+};
+
+struct cluster_ops *init_gulm_cluster(void)
+{
+	if (!_init_cluster())
+		return &_cluster_gulm_ops;
+	else
+		return NULL;
+}
Index: src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd-gulm.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd-gulm.h
diff -N src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd-gulm.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd-gulm.h	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,15 @@
+/*	$NetBSD$	*/
+
+
+/* DLM constant that clvmd uses as a generic NONBLOCK lock flag */
+#define LKF_NOQUEUE 1
+
+extern int get_next_node_csid(void **context, char *csid);
+extern void add_down_node(char *csid);
+extern int gulm_fd(void);
+extern int get_ip_address(const char *node, char *addr);
+extern void tcp_remove_client(const char *csid);
+extern int alloc_client(int fd, const char *csid, struct local_client **new_client);
+
+void gulm_add_up_node(const char *csid);
+int gulm_name_from_csid(const char *csid, char *name);
Index: src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd-openais.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd-openais.c
diff -N src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd-openais.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd-openais.c	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,709 @@
+/*	$NetBSD$	*/
+
+/******************************************************************************
+*******************************************************************************
+**
+**  Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+**
+*******************************************************************************
+******************************************************************************/
+
+/* This provides the interface between clvmd and OpenAIS as the cluster
+ * and lock manager.
+ *
+ */
+
+#define _GNU_SOURCE
+#define _FILE_OFFSET_BITS 64
+
+#include <configure.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+#include <utmpx.h>
+#include <syslog.h>
+#include <assert.h>
+#include <libdevmapper.h>
+
+#include <openais/saAis.h>
+#include <openais/saLck.h>
+#include <openais/cpg.h>
+
+#include "locking.h"
+#include "lvm-logging.h"
+#include "clvm.h"
+#include "clvmd-comms.h"
+#include "lvm-functions.h"
+#include "clvmd.h"
+
+/* Timeout value for several openais calls */
+#define TIMEOUT 10
+
+static void cpg_deliver_callback (cpg_handle_t handle,
+				  struct cpg_name *groupName,
+				  uint32_t nodeid,
+				  uint32_t pid,
+				  void *msg,
+				  int msg_len);
+static void cpg_confchg_callback(cpg_handle_t handle,
+				 struct cpg_name *groupName,
+				 struct cpg_address *member_list, int member_list_entries,
+				 struct cpg_address *left_list, int left_list_entries,
+				 struct cpg_address *joined_list, int joined_list_entries);
+static void _cluster_closedown(void);
+
+/* Hash list of nodes in the cluster */
+static struct dm_hash_table *node_hash;
+
+/* For associating lock IDs & resource handles */
+static struct dm_hash_table *lock_hash;
+
+/* Number of active nodes */
+static int num_nodes;
+static unsigned int our_nodeid;
+
+static struct local_client *cluster_client;
+
+/* OpenAIS handles */
+static cpg_handle_t cpg_handle;
+static SaLckHandleT lck_handle;
+
+static struct cpg_name cpg_group_name;
+
+/* Openais callback structs */
+cpg_callbacks_t cpg_callbacks = {
+	.cpg_deliver_fn =            cpg_deliver_callback,
+	.cpg_confchg_fn =            cpg_confchg_callback,
+};
+
+struct node_info
+{
+	enum {NODE_UNKNOWN, NODE_DOWN, NODE_UP, NODE_CLVMD} state;
+	int nodeid;
+};
+
+struct lock_info
+{
+	SaLckResourceHandleT res_handle;
+	SaLckLockIdT         lock_id;
+	SaNameT              lock_name;
+};
+
+/* Set errno to something approximating the right value and return 0 or -1 */
+static int ais_to_errno(SaAisErrorT err)
+{
+	switch(err)
+	{
+	case SA_AIS_OK:
+		return 0;
+        case SA_AIS_ERR_LIBRARY:
+		errno = EINVAL;
+		break;
+        case SA_AIS_ERR_VERSION:
+		errno = EINVAL;
+		break;
+        case SA_AIS_ERR_INIT:
+		errno = EINVAL;
+		break;
+        case SA_AIS_ERR_TIMEOUT:
+		errno = ETIME;
+		break;
+        case SA_AIS_ERR_TRY_AGAIN:
+		errno = EAGAIN;
+		break;
+        case SA_AIS_ERR_INVALID_PARAM:
+		errno = EINVAL;
+		break;
+        case SA_AIS_ERR_NO_MEMORY:
+		errno = ENOMEM;
+		break;
+        case SA_AIS_ERR_BAD_HANDLE:
+		errno = EINVAL;
+		break;
+        case SA_AIS_ERR_BUSY:
+		errno = EBUSY;
+		break;
+        case SA_AIS_ERR_ACCESS:
+		errno = EPERM;
+		break;
+        case SA_AIS_ERR_NOT_EXIST:
+		errno = ENOENT;
+		break;
+        case SA_AIS_ERR_NAME_TOO_LONG:
+		errno = ENAMETOOLONG;
+		break;
+        case SA_AIS_ERR_EXIST:
+		errno = EEXIST;
+		break;
+        case SA_AIS_ERR_NO_SPACE:
+		errno = ENOSPC;
+		break;
+        case SA_AIS_ERR_INTERRUPT:
+		errno = EINTR;
+		break;
+	case SA_AIS_ERR_NAME_NOT_FOUND:
+		errno = ENOENT;
+		break;
+        case SA_AIS_ERR_NO_RESOURCES:
+		errno = ENOMEM;
+		break;
+        case SA_AIS_ERR_NOT_SUPPORTED:
+		errno = EOPNOTSUPP;
+		break;
+        case SA_AIS_ERR_BAD_OPERATION:
+		errno = EINVAL;
+		break;
+        case SA_AIS_ERR_FAILED_OPERATION:
+		errno = EIO;
+		break;
+        case SA_AIS_ERR_MESSAGE_ERROR:
+		errno = EIO;
+		break;
+        case SA_AIS_ERR_QUEUE_FULL:
+		errno = EXFULL;
+		break;
+        case SA_AIS_ERR_QUEUE_NOT_AVAILABLE:
+		errno = EINVAL;
+		break;
+        case SA_AIS_ERR_BAD_FLAGS:
+		errno = EINVAL;
+		break;
+        case SA_AIS_ERR_TOO_BIG:
+		errno = E2BIG;
+		break;
+        case SA_AIS_ERR_NO_SECTIONS:
+		errno = ENOMEM;
+		break;
+	default:
+		errno = EINVAL;
+		break;
+	}
+	return -1;
+}
+
+static char *print_csid(const char *csid)
+{
+	static char buf[128];
+	int id;
+
+	memcpy(&id, csid, sizeof(int));
+	sprintf(buf, "%d", id);
+	return buf;
+}
+
+static int add_internal_client(int fd, fd_callback_t callback)
+{
+	struct local_client *client;
+
+	DEBUGLOG("Add_internal_client, fd = %d\n", fd);
+
+	client = malloc(sizeof(struct local_client));
+	if (!client)
+	{
+		DEBUGLOG("malloc failed\n");
+		return -1;
+	}
+
+	memset(client, 0, sizeof(struct local_client));
+	client->fd = fd;
+	client->type = CLUSTER_INTERNAL;
+	client->callback = callback;
+	add_client(client);
+
+	/* Set Close-on-exec */
+	fcntl(fd, F_SETFD, 1);
+
+	return 0;
+}
+
+static void cpg_deliver_callback (cpg_handle_t handle,
+				  struct cpg_name *groupName,
+				  uint32_t nodeid,
+				  uint32_t pid,
+				  void *msg,
+				  int msg_len)
+{
+	int target_nodeid;
+
+	memcpy(&target_nodeid, msg, OPENAIS_CSID_LEN);
+
+	DEBUGLOG("%u got message from nodeid %d for %d. len %d\n",
+		 our_nodeid, nodeid, target_nodeid, msg_len-4);
+
+	if (nodeid != our_nodeid)
+		if (target_nodeid == our_nodeid || target_nodeid == 0)
+			process_message(cluster_client, (char *)msg+OPENAIS_CSID_LEN,
+					msg_len-OPENAIS_CSID_LEN, (char*)&nodeid);
+}
+
+static void cpg_confchg_callback(cpg_handle_t handle,
+				 struct cpg_name *groupName,
+				 struct cpg_address *member_list, int member_list_entries,
+				 struct cpg_address *left_list, int left_list_entries,
+				 struct cpg_address *joined_list, int joined_list_entries)
+{
+	int i;
+	struct node_info *ninfo;
+
+	DEBUGLOG("confchg callback. %d joined, %d left, %d members\n",
+		 joined_list_entries, left_list_entries, member_list_entries);
+
+	for (i=0; i<joined_list_entries; i++) {
+		ninfo = dm_hash_lookup_binary(node_hash,
+					      (char *)&joined_list[i].nodeid,
+					      OPENAIS_CSID_LEN);
+		if (!ninfo) {
+			ninfo = malloc(sizeof(struct node_info));
+			if (!ninfo) {
+				break;
+			}
+			else {
+				ninfo->nodeid = joined_list[i].nodeid;
+				dm_hash_insert_binary(node_hash,
+						      (char *)&ninfo->nodeid,
+						      OPENAIS_CSID_LEN, ninfo);
+			}
+		}
+		ninfo->state = NODE_CLVMD;
+	}
+
+	for (i=0; i<left_list_entries; i++) {
+		ninfo = dm_hash_lookup_binary(node_hash,
+					      (char *)&left_list[i].nodeid,
+					      OPENAIS_CSID_LEN);
+		if (ninfo)
+			ninfo->state = NODE_DOWN;
+	}
+
+	for (i=0; i<member_list_entries; i++) {
+		if (member_list[i].nodeid == 0) continue;
+		ninfo = dm_hash_lookup_binary(node_hash,
+				(char *)&member_list[i].nodeid,
+				OPENAIS_CSID_LEN);
+		if (!ninfo) {
+			ninfo = malloc(sizeof(struct node_info));
+			if (!ninfo) {
+				break;
+			}
+			else {
+				ninfo->nodeid = member_list[i].nodeid;
+				dm_hash_insert_binary(node_hash,
+						(char *)&ninfo->nodeid,
+						OPENAIS_CSID_LEN, ninfo);
+			}
+		}
+		ninfo->state = NODE_CLVMD;
+	}
+
+	num_nodes = member_list_entries;
+}
+
+static int lck_dispatch(struct local_client *client, char *buf, int len,
+			const char *csid, struct local_client **new_client)
+{
+	*new_client = NULL;
+	saLckDispatch(lck_handle, SA_DISPATCH_ONE);
+	return 1;
+}
+
+static int _init_cluster(void)
+{
+	SaAisErrorT err;
+	SaVersionT  ver = { 'B', 1, 1 };
+	int select_fd;
+
+	node_hash = dm_hash_create(100);
+	lock_hash = dm_hash_create(10);
+
+	err = cpg_initialize(&cpg_handle,
+			     &cpg_callbacks);
+	if (err != SA_AIS_OK) {
+		syslog(LOG_ERR, "Cannot initialise OpenAIS CPG service: %d",
+		       err);
+		DEBUGLOG("Cannot initialise OpenAIS CPG service: %d", err);
+		return ais_to_errno(err);
+	}
+
+	err = saLckInitialize(&lck_handle,
+					NULL,
+			      &ver);
+	if (err != SA_AIS_OK) {
+		cpg_initialize(&cpg_handle, &cpg_callbacks);
+		syslog(LOG_ERR, "Cannot initialise OpenAIS lock service: %d",
+		       err);
+		DEBUGLOG("Cannot initialise OpenAIS lock service: %d\n\n", err);
+		return ais_to_errno(err);
+	}
+
+	/* Connect to the clvmd group */
+	strcpy((char *)cpg_group_name.value, "clvmd");
+	cpg_group_name.length = strlen((char *)cpg_group_name.value);
+	err = cpg_join(cpg_handle, &cpg_group_name);
+	if (err != SA_AIS_OK) {
+		cpg_finalize(cpg_handle);
+		saLckFinalize(lck_handle);
+		syslog(LOG_ERR, "Cannot join clvmd process group");
+		DEBUGLOG("Cannot join clvmd process group: %d\n", err);
+		return ais_to_errno(err);
+	}
+
+	err = cpg_local_get(cpg_handle,
+			    &our_nodeid);
+	if (err != SA_AIS_OK) {
+		cpg_finalize(cpg_handle);
+		saLckFinalize(lck_handle);
+		syslog(LOG_ERR, "Cannot get local node id\n");
+		return ais_to_errno(err);
+	}
+	DEBUGLOG("Our local node id is %d\n", our_nodeid);
+
+	saLckSelectionObjectGet(lck_handle, (SaSelectionObjectT *)&select_fd);
+	add_internal_client(select_fd, lck_dispatch);
+
+	DEBUGLOG("Connected to OpenAIS\n");
+
+	return 0;
+}
+
+static void _cluster_closedown(void)
+{
+	DEBUGLOG("cluster_closedown\n");
+	unlock_all();
+
+	saLckFinalize(lck_handle);
+	cpg_finalize(cpg_handle);
+}
+
+static void _get_our_csid(char *csid)
+{
+	memcpy(csid, &our_nodeid, sizeof(int));
+}
+
+/* OpenAIS doesn't really have nmode names so we
+   just use the node ID in hex instead */
+static int _csid_from_name(char *csid, const char *name)
+{
+	int nodeid;
+	struct node_info *ninfo;
+
+	if (sscanf(name, "%x", &nodeid) == 1) {
+		ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
+		if (ninfo)
+			return nodeid;
+	}
+	return -1;
+}
+
+static int _name_from_csid(const char *csid, char *name)
+{
+	struct node_info *ninfo;
+
+	ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
+	if (!ninfo)
+	{
+		sprintf(name, "UNKNOWN %s", print_csid(csid));
+		return -1;
+	}
+
+	sprintf(name, "%x", ninfo->nodeid);
+	return 0;
+}
+
+static int _get_num_nodes()
+{
+	DEBUGLOG("num_nodes = %d\n", num_nodes);
+	return num_nodes;
+}
+
+/* Node is now known to be running a clvmd */
+static void _add_up_node(const char *csid)
+{
+	struct node_info *ninfo;
+
+	ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
+	if (!ninfo) {
+		DEBUGLOG("openais_add_up_node no node_hash entry for csid %s\n",
+			 print_csid(csid));
+		return;
+	}
+
+	DEBUGLOG("openais_add_up_node %d\n", ninfo->nodeid);
+
+	ninfo->state = NODE_CLVMD;
+
+	return;
+}
+
+/* Call a callback for each node, so the caller knows whether it's up or down */
+static int _cluster_do_node_callback(struct local_client *master_client,
+				     void (*callback)(struct local_client *,
+						      const char *csid, int node_up))
+{
+	struct dm_hash_node *hn;
+	struct node_info *ninfo;
+	int somedown = 0;
+
+	dm_hash_iterate(hn, node_hash)
+	{
+		char csid[OPENAIS_CSID_LEN];
+
+		ninfo = dm_hash_get_data(node_hash, hn);
+		memcpy(csid, dm_hash_get_key(node_hash, hn), OPENAIS_CSID_LEN);
+
+		DEBUGLOG("down_callback. node %d, state = %d\n", ninfo->nodeid,
+			 ninfo->state);
+
+		if (ninfo->state != NODE_DOWN)
+			callback(master_client, csid, ninfo->state == NODE_CLVMD);
+		if (ninfo->state != NODE_CLVMD)
+			somedown = -1;
+	}
+	return somedown;
+}
+
+/* Real locking */
+static int _lock_resource(char *resource, int mode, int flags, int *lockid)
+{
+	struct lock_info *linfo;
+	SaLckResourceHandleT res_handle;
+	SaAisErrorT err;
+	SaLckLockIdT lock_id;
+	SaLckLockStatusT lockStatus;
+
+	/* This needs to be converted from DLM/LVM2 value for OpenAIS LCK */
+	if (flags & LCK_NONBLOCK) flags = SA_LCK_LOCK_NO_QUEUE;
+
+	linfo = malloc(sizeof(struct lock_info));
+	if (!linfo)
+		return -1;
+
+	DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
+
+	linfo->lock_name.length = strlen(resource)+1;
+	strcpy((char *)linfo->lock_name.value, resource);
+
+	err = saLckResourceOpen(lck_handle, &linfo->lock_name,
+				SA_LCK_RESOURCE_CREATE, TIMEOUT, &res_handle);
+	if (err != SA_AIS_OK)
+	{
+		DEBUGLOG("ResourceOpen returned %d\n", err);
+		free(linfo);
+		return ais_to_errno(err);
+	}
+
+	err = saLckResourceLock(
+			res_handle,
+			&lock_id,
+			mode,
+			flags,
+			0,
+			SA_TIME_END,
+			&lockStatus);
+	if (err != SA_AIS_OK && lockStatus != SA_LCK_LOCK_GRANTED)
+	{
+		free(linfo);
+		saLckResourceClose(res_handle);
+		return ais_to_errno(err);
+	}
+			
+	/* Wait for it to complete */
+
+	DEBUGLOG("lock_resource returning %d, lock_id=%llx\n", err,
+		 lock_id);
+
+	linfo->lock_id = lock_id;
+	linfo->res_handle = res_handle;
+
+	dm_hash_insert(lock_hash, resource, linfo);
+
+	return ais_to_errno(err);
+}
+
+
+static int _unlock_resource(char *resource, int lockid)
+{
+	SaAisErrorT err;
+	struct lock_info *linfo;
+
+	DEBUGLOG("unlock_resource %s\n", resource);
+	linfo = dm_hash_lookup(lock_hash, resource);
+	if (!linfo)
+		return 0;
+
+	DEBUGLOG("unlock_resource: lockid: %llx\n", linfo->lock_id);
+	err = saLckResourceUnlock(linfo->lock_id, SA_TIME_END);
+	if (err != SA_AIS_OK)
+	{
+		DEBUGLOG("Unlock returned %d\n", err);
+		return ais_to_errno(err);
+	}
+
+	/* Release the resource */
+	dm_hash_remove(lock_hash, resource);
+	saLckResourceClose(linfo->res_handle);
+	free(linfo);
+
+	return ais_to_errno(err);
+}
+
+static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
+{
+	int status;
+	char lock1[strlen(resource)+3];
+	char lock2[strlen(resource)+3];
+
+	snprintf(lock1, sizeof(lock1), "%s-1", resource);
+	snprintf(lock2, sizeof(lock2), "%s-2", resource);
+
+	switch (mode)
+	{
+	case LCK_EXCL:
+		status = _lock_resource(lock1, SA_LCK_EX_LOCK_MODE, flags, lockid);
+		if (status)
+			goto out;
+
+		/* If we can't get this lock too then bail out */
+		status = _lock_resource(lock2, SA_LCK_EX_LOCK_MODE, LCK_NONBLOCK,
+					lockid);
+		if (status == SA_LCK_LOCK_NOT_QUEUED)
+		{
+			_unlock_resource(lock1, *lockid);
+			status = -1;
+			errno = EAGAIN;
+		}
+		break;
+
+	case LCK_PREAD:
+	case LCK_READ:
+		status = _lock_resource(lock1, SA_LCK_PR_LOCK_MODE, flags, lockid);
+		if (status)
+			goto out;
+		_unlock_resource(lock2, *lockid);
+		break;
+
+	case LCK_WRITE:
+		status = _lock_resource(lock2, SA_LCK_EX_LOCK_MODE, flags, lockid);
+		if (status)
+			goto out;
+		_unlock_resource(lock1, *lockid);
+		break;
+
+	default:
+		status = -1;
+		errno = EINVAL;
+		break;
+	}
+out:
+	*lockid = mode;
+	return status;
+}
+
+static int _sync_unlock(const char *resource, int lockid)
+{
+	int status = 0;
+	char lock1[strlen(resource)+3];
+	char lock2[strlen(resource)+3];
+
+	snprintf(lock1, sizeof(lock1), "%s-1", resource);
+	snprintf(lock2, sizeof(lock2), "%s-2", resource);
+
+	_unlock_resource(lock1, lockid);
+	_unlock_resource(lock2, lockid);
+
+	return status;
+}
+
+/* We are always quorate ! */
+static int _is_quorate()
+{
+	return 1;
+}
+
+static int _get_main_cluster_fd(void)
+{
+	int select_fd;
+
+	cpg_fd_get(cpg_handle, &select_fd);
+	return select_fd;
+}
+
+static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
+				const char *csid,
+				struct local_client **new_client)
+{
+	cluster_client = fd;
+	*new_client = NULL;
+	cpg_dispatch(cpg_handle, SA_DISPATCH_ONE);
+	return 1;
+}
+
+static int _cluster_send_message(const void *buf, int msglen, const char *csid,
+				 const char *errtext)
+{
+	struct iovec iov[2];
+	SaAisErrorT err;
+	int target_node;
+
+	if (csid)
+		memcpy(&target_node, csid, OPENAIS_CSID_LEN);
+	else
+		target_node = 0;
+
+	iov[0].iov_base = &target_node;
+	iov[0].iov_len = sizeof(int);
+	iov[1].iov_base = (char *)buf;
+	iov[1].iov_len = msglen;
+
+	err = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 2);
+	return ais_to_errno(err);
+}
+
+/* We don't have a cluster name to report here */
+static int _get_cluster_name(char *buf, int buflen)
+{
+	strncpy(buf, "OpenAIS", buflen);
+	return 0;
+}
+
+static struct cluster_ops _cluster_openais_ops = {
+	.cluster_init_completed   = NULL,
+	.cluster_send_message     = _cluster_send_message,
+	.name_from_csid           = _name_from_csid,
+	.csid_from_name           = _csid_from_name,
+	.get_num_nodes            = _get_num_nodes,
+	.cluster_fd_callback      = _cluster_fd_callback,
+	.get_main_cluster_fd      = _get_main_cluster_fd,
+	.cluster_do_node_callback = _cluster_do_node_callback,
+	.is_quorate               = _is_quorate,
+	.get_our_csid             = _get_our_csid,
+	.add_up_node              = _add_up_node,
+	.reread_config            = NULL,
+	.cluster_closedown        = _cluster_closedown,
+	.get_cluster_name         = _get_cluster_name,
+	.sync_lock                = _sync_lock,
+	.sync_unlock              = _sync_unlock,
+};
+
+struct cluster_ops *init_openais_cluster(void)
+{
+	if (!_init_cluster())
+		return &_cluster_openais_ops;
+	else
+		return NULL;
+}
Index: src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd.c
diff -N src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd.c	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,2003 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * CLVMD: Cluster LVM daemon
+ */
+
+#define _GNU_SOURCE
+#define _FILE_OFFSET_BITS 64
+
+#include <configure.h>
+#include <libdevmapper.h>
+
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <sys/un.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/utsname.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <signal.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <syslog.h>
+#include <errno.h>
+#include <limits.h>
+#include <libdlm.h>
+
+#include "clvmd-comms.h"
+#include "lvm-functions.h"
+#include "clvm.h"
+#include "version.h"
+#include "clvmd.h"
+#include "refresh_clvmd.h"
+#include "lvm-logging.h"
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define MAX_RETRIES 4
+
+#define ISLOCAL_CSID(c) (memcmp(c, our_csid, max_csid_len) == 0)
+
+/* Head of the fd list. Also contains
+   the cluster_socket details */
+static struct local_client local_client_head;
+
+static unsigned short global_xid = 0;	/* Last transaction ID issued */
+
+struct cluster_ops *clops = NULL;
+
+static char our_csid[MAX_CSID_LEN];
+static unsigned max_csid_len;
+static unsigned max_cluster_message;
+static unsigned max_cluster_member_name_len;
+
+/* Structure of items on the LVM thread list */
+struct lvm_thread_cmd {
+	struct dm_list list;
+
+	struct local_client *client;
+	struct clvm_header *msg;
+	char csid[MAX_CSID_LEN];
+	int remote;		/* Flag */
+	int msglen;
+	unsigned short xid;
+};
+
+debug_t debug;
+static pthread_t lvm_thread;
+static pthread_mutex_t lvm_thread_mutex;
+static pthread_cond_t lvm_thread_cond;
+static pthread_mutex_t lvm_start_mutex;
+static struct dm_list lvm_cmd_head;
+static volatile sig_atomic_t quit = 0;
+static volatile sig_atomic_t reread_config = 0;
+static int child_pipe[2];
+
+/* Reasons the daemon failed initialisation */
+#define DFAIL_INIT       1
+#define DFAIL_LOCAL_SOCK 2
+#define DFAIL_CLUSTER_IF 3
+#define DFAIL_MALLOC     4
+#define DFAIL_TIMEOUT    5
+#define SUCCESS          0
+
+/* Prototypes for code further down */
+static void sigusr2_handler(int sig);
+static void sighup_handler(int sig);
+static void sigterm_handler(int sig);
+static void send_local_reply(struct local_client *client, int status,
+			     int clientid);
+static void free_reply(struct local_client *client);
+static void send_version_message(void);
+static void *pre_and_post_thread(void *arg);
+static int send_message(void *buf, int msglen, const char *csid, int fd,
+			const char *errtext);
+static int read_from_local_sock(struct local_client *thisfd);
+static int process_local_command(struct clvm_header *msg, int msglen,
+				 struct local_client *client,
+				 unsigned short xid);
+static void process_remote_command(struct clvm_header *msg, int msglen, int fd,
+				   const char *csid);
+static int process_reply(const struct clvm_header *msg, int msglen,
+			 const char *csid);
+static int open_local_sock(void);
+static int check_local_clvmd(void);
+static struct local_client *find_client(int clientid);
+static void main_loop(int local_sock, int cmd_timeout);
+static void be_daemon(int start_timeout);
+static int check_all_clvmds_running(struct local_client *client);
+static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
+				     int len, const char *csid,
+				     struct local_client **new_client);
+static void *lvm_thread_fn(void *);
+static int add_to_lvmqueue(struct local_client *client, struct clvm_header *msg,
+			   int msglen, const char *csid);
+static int distribute_command(struct local_client *thisfd);
+static void hton_clvm(struct clvm_header *hdr);
+static void ntoh_clvm(struct clvm_header *hdr);
+static void add_reply_to_list(struct local_client *client, int status,
+			      const char *csid, const char *buf, int len);
+
+static void usage(char *prog, FILE *file)
+{
+	fprintf(file, "Usage:\n");
+	fprintf(file, "%s [Vhd]\n", prog);
+	fprintf(file, "\n");
+	fprintf(file, "   -V       Show version of clvmd\n");
+	fprintf(file, "   -h       Show this help information\n");
+	fprintf(file, "   -d       Set debug level\n");
+	fprintf(file, "            If starting clvmd then don't fork, run in the foreground\n");
+	fprintf(file, "   -R       Tell all running clvmds in the cluster to reload their device cache\n");
+	fprintf(file, "   -C       Sets debug level (from -d) on all clvmd instances clusterwide\n");
+	fprintf(file, "   -t<secs> Command timeout (default 60 seconds)\n");
+	fprintf(file, "   -T<secs> Startup timeout (default none)\n");
+	fprintf(file, "\n");
+}
+
+/* Called to signal the parent how well we got on during initialisation */
+static void child_init_signal(int status)
+{
+        if (child_pipe[1]) {
+	        write(child_pipe[1], &status, sizeof(status));
+		close(child_pipe[1]);
+	}
+	if (status)
+	        exit(status);
+}
+
+
+void debuglog(const char *fmt, ...)
+{
+	time_t P;
+	va_list ap;
+	static int syslog_init = 0;
+
+	if (debug == DEBUG_STDERR) {
+		va_start(ap,fmt);
+		time(&P);
+		fprintf(stderr, "CLVMD[%x]: %.15s ", (int)pthread_self(), ctime(&P)+4 );
+		vfprintf(stderr, fmt, ap);
+		va_end(ap);
+	}
+	if (debug == DEBUG_SYSLOG) {
+		if (!syslog_init) {
+			openlog("clvmd", LOG_PID, LOG_DAEMON);
+			syslog_init = 1;
+		}
+
+		va_start(ap,fmt);
+		vsyslog(LOG_DEBUG, fmt, ap);
+		va_end(ap);
+	}
+}
+
+static const char *decode_cmd(unsigned char cmdl)
+{
+	static char buf[128];
+	const char *command;
+
+	switch (cmdl) {
+	case CLVMD_CMD_TEST:		
+		command = "TEST";	
+		break;
+	case CLVMD_CMD_LOCK_VG:		
+		command = "LOCK_VG";	
+		break;
+	case CLVMD_CMD_LOCK_LV:		
+		command = "LOCK_LV";	
+		break;
+	case CLVMD_CMD_REFRESH:		
+		command = "REFRESH";	
+		break;
+	case CLVMD_CMD_SET_DEBUG:	
+		command = "SET_DEBUG";	
+		break;
+	case CLVMD_CMD_GET_CLUSTERNAME:	
+		command = "GET_CLUSTERNAME";
+		break;
+	case CLVMD_CMD_VG_BACKUP:	
+		command = "VG_BACKUP";	
+		break;
+	case CLVMD_CMD_REPLY:		
+		command = "REPLY";	
+		break;
+	case CLVMD_CMD_VERSION:		
+		command = "VERSION";	
+		break;
+	case CLVMD_CMD_GOAWAY:		
+		command = "GOAWAY";	
+		break;
+	case CLVMD_CMD_LOCK:		
+		command = "LOCK";	
+		break;
+	case CLVMD_CMD_UNLOCK:		
+		command = "UNLOCK";	
+		break;
+	default:			
+		command = "unknown";    
+		break;
+	}
+
+	sprintf(buf, "%s (0x%x)", command, cmdl);
+
+	return buf;
+}
+
+int main(int argc, char *argv[])
+{
+	int local_sock;
+	struct local_client *newfd;
+	struct utsname nodeinfo;
+	signed char opt;
+	int cmd_timeout = DEFAULT_CMD_TIMEOUT;
+	int start_timeout = 0;
+	sigset_t ss;
+	int using_gulm = 0;
+	int debug_opt = 0;
+	int clusterwide_opt = 0;
+
+	/* Deal with command-line arguments */
+	opterr = 0;
+	optind = 0;
+	while ((opt = getopt(argc, argv, "?vVhd::t:RT:C")) != EOF) {
+		switch (opt) {
+		case 'h':
+			usage(argv[0], stdout);
+			exit(0);
+
+		case '?':
+			usage(argv[0], stderr);
+			exit(0);
+
+		case 'R':
+			return refresh_clvmd();
+
+		case 'C':
+			clusterwide_opt = 1;
+			break;
+
+		case 'd':
+			debug_opt = 1;
+			if (optarg)
+				debug = atoi(optarg);
+			else
+				debug = DEBUG_STDERR;
+			break;
+
+		case 't':
+			cmd_timeout = atoi(optarg);
+			if (!cmd_timeout) {
+				fprintf(stderr, "command timeout is invalid\n");
+				usage(argv[0], stderr);
+				exit(1);
+			}
+			break;
+		case 'T':
+			start_timeout = atoi(optarg);
+			if (start_timeout <= 0) {
+				fprintf(stderr, "startup timeout is invalid\n");
+				usage(argv[0], stderr);
+				exit(1);
+			}
+			break;
+
+		case 'V':
+		        printf("Cluster LVM daemon version: %s\n", LVM_VERSION);
+			printf("Protocol version:           %d.%d.%d\n",
+			       CLVMD_MAJOR_VERSION, CLVMD_MINOR_VERSION,
+			       CLVMD_PATCH_VERSION);
+			exit(1);
+			break;
+
+		}
+	}
+
+	/* Setting debug options on an existing clvmd */
+	if (debug_opt && !check_local_clvmd()) {
+
+		/* Sending to stderr makes no sense for a detached daemon */
+		if (debug == DEBUG_STDERR)
+			debug = DEBUG_SYSLOG;
+		return debug_clvmd(debug, clusterwide_opt);
+	}
+
+	/* Fork into the background (unless requested not to) */
+	if (debug != DEBUG_STDERR) {
+		be_daemon(start_timeout);
+	}
+
+	DEBUGLOG("CLVMD started\n");
+
+	/* Open the Unix socket we listen for commands on.
+	   We do this before opening the cluster socket so that
+	   potential clients will block rather than error if we are running
+	   but the cluster is not ready yet */
+	local_sock = open_local_sock();
+	if (local_sock < 0)
+		child_init_signal(DFAIL_LOCAL_SOCK);
+
+	/* Set up signal handlers, USR1 is for cluster change notifications (in cman)
+	   USR2 causes child threads to exit.
+	   HUP causes gulm version to re-read nodes list from CCS.
+	   PIPE should be ignored */
+	signal(SIGUSR2, sigusr2_handler);
+	signal(SIGHUP,  sighup_handler);
+	signal(SIGPIPE, SIG_IGN);
+
+	/* Block SIGUSR2 in the main process */
+	sigemptyset(&ss);
+	sigaddset(&ss, SIGUSR2);
+	sigprocmask(SIG_BLOCK, &ss, NULL);
+
+	/* Initialise the LVM thread variables */
+	dm_list_init(&lvm_cmd_head);
+	pthread_mutex_init(&lvm_thread_mutex, NULL);
+	pthread_cond_init(&lvm_thread_cond, NULL);
+	pthread_mutex_init(&lvm_start_mutex, NULL);
+	init_lvhash();
+
+	/* Start the cluster interface */
+#ifdef USE_CMAN
+	if ((clops = init_cman_cluster())) {
+		max_csid_len = CMAN_MAX_CSID_LEN;
+		max_cluster_message = CMAN_MAX_CLUSTER_MESSAGE;
+		max_cluster_member_name_len = CMAN_MAX_NODENAME_LEN;
+		syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to CMAN");
+	}
+#endif
+#ifdef USE_GULM
+	if (!clops)
+		if ((clops = init_gulm_cluster())) {
+			max_csid_len = GULM_MAX_CSID_LEN;
+			max_cluster_message = GULM_MAX_CLUSTER_MESSAGE;
+			max_cluster_member_name_len = GULM_MAX_CLUSTER_MEMBER_NAME_LEN;
+			using_gulm = 1;
+			syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to GULM");
+		}
+#endif
+#ifdef USE_OPENAIS
+	if (!clops)
+		if ((clops = init_openais_cluster())) {
+			max_csid_len = OPENAIS_CSID_LEN;
+			max_cluster_message = OPENAIS_MAX_CLUSTER_MESSAGE;
+			max_cluster_member_name_len = OPENAIS_MAX_CLUSTER_MEMBER_NAME_LEN;
+			syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to OpenAIS");
+		}
+#endif
+
+	if (!clops) {
+		DEBUGLOG("Can't initialise cluster interface\n");
+		log_error("Can't initialise cluster interface\n");
+		child_init_signal(DFAIL_CLUSTER_IF);
+	}
+	DEBUGLOG("Cluster ready, doing some more initialisation\n");
+
+	/* Save our CSID */
+	uname(&nodeinfo);
+	clops->get_our_csid(our_csid);
+
+	/* Initialise the FD list head */
+	local_client_head.fd = clops->get_main_cluster_fd();
+	local_client_head.type = CLUSTER_MAIN_SOCK;
+	local_client_head.callback = clops->cluster_fd_callback;
+
+	/* Add the local socket to the list */
+	newfd = malloc(sizeof(struct local_client));
+	if (!newfd)
+	        child_init_signal(DFAIL_MALLOC);
+
+	newfd->fd = local_sock;
+	newfd->removeme = 0;
+	newfd->type = LOCAL_RENDEZVOUS;
+	newfd->callback = local_rendezvous_callback;
+	newfd->next = local_client_head.next;
+	local_client_head.next = newfd;
+
+	/* This needs to be started after cluster initialisation
+	   as it may need to take out locks */
+	DEBUGLOG("starting LVM thread\n");
+	pthread_create(&lvm_thread, NULL, lvm_thread_fn,
+			(void *)(long)using_gulm);
+
+	/* Tell the rest of the cluster our version number */
+	/* CMAN can do this immediately, gulm needs to wait until
+	   the core initialisation has finished and the node list
+	   has been gathered */
+	if (clops->cluster_init_completed)
+		clops->cluster_init_completed();
+
+	DEBUGLOG("clvmd ready for work\n");
+	child_init_signal(SUCCESS);
+
+	/* Try to shutdown neatly */
+	signal(SIGTERM, sigterm_handler);
+	signal(SIGINT, sigterm_handler);
+
+	/* Do some work */
+	main_loop(local_sock, cmd_timeout);
+
+	return 0;
+}
+
+/* Called when the GuLM cluster layer has completed initialisation.
+   We send the version message */
+void clvmd_cluster_init_completed()
+{
+	send_version_message();
+}
+
+/* Data on a connected socket */
+static int local_sock_callback(struct local_client *thisfd, char *buf, int len,
+			       const char *csid,
+			       struct local_client **new_client)
+{
+	*new_client = NULL;
+	return read_from_local_sock(thisfd);
+}
+
+/* Data on a connected socket */
+static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
+				     int len, const char *csid,
+				     struct local_client **new_client)
+{
+	/* Someone connected to our local socket, accept it. */
+
+	struct sockaddr_un socka;
+	struct local_client *newfd;
+	socklen_t sl = sizeof(socka);
+	int client_fd = accept(thisfd->fd, (struct sockaddr *) &socka, &sl);
+
+	if (client_fd == -1 && errno == EINTR)
+		return 1;
+
+	if (client_fd >= 0) {
+		newfd = malloc(sizeof(struct local_client));
+		if (!newfd) {
+			close(client_fd);
+			return 1;
+		}
+		newfd->fd = client_fd;
+		newfd->type = LOCAL_SOCK;
+		newfd->xid = 0;
+		newfd->removeme = 0;
+		newfd->callback = local_sock_callback;
+		newfd->bits.localsock.replies = NULL;
+		newfd->bits.localsock.expected_replies = 0;
+		newfd->bits.localsock.cmd = NULL;
+		newfd->bits.localsock.in_progress = FALSE;
+		newfd->bits.localsock.sent_out = FALSE;
+		newfd->bits.localsock.threadid = 0;
+		newfd->bits.localsock.finished = 0;
+		newfd->bits.localsock.pipe_client = NULL;
+		newfd->bits.localsock.private = NULL;
+		newfd->bits.localsock.all_success = 1;
+		DEBUGLOG("Got new connection on fd %d\n", newfd->fd);
+		*new_client = newfd;
+	}
+	return 1;
+}
+
+static int local_pipe_callback(struct local_client *thisfd, char *buf,
+			       int maxlen, const char *csid,
+			       struct local_client **new_client)
+{
+	int len;
+	char buffer[PIPE_BUF];
+	struct local_client *sock_client = thisfd->bits.pipe.client;
+	int status = -1;	/* in error by default */
+
+	len = read(thisfd->fd, buffer, sizeof(int));
+	if (len == -1 && errno == EINTR)
+		return 1;
+
+	if (len == sizeof(int)) {
+		memcpy(&status, buffer, sizeof(int));
+	}
+
+	DEBUGLOG("read on PIPE %d: %d bytes: status: %d\n",
+		 thisfd->fd, len, status);
+
+	/* EOF on pipe or an error, close it */
+	if (len <= 0) {
+		int jstat;
+		void *ret = &status;
+		close(thisfd->fd);
+
+		/* Clear out the cross-link */
+		if (thisfd->bits.pipe.client != NULL)
+			thisfd->bits.pipe.client->bits.localsock.pipe_client =
+			    NULL;
+
+		/* Reap child thread */
+		if (thisfd->bits.pipe.threadid) {
+			jstat = pthread_join(thisfd->bits.pipe.threadid, &ret);
+			thisfd->bits.pipe.threadid = 0;
+			if (thisfd->bits.pipe.client != NULL)
+				thisfd->bits.pipe.client->bits.localsock.
+				    threadid = 0;
+		}
+		return -1;
+	} else {
+		DEBUGLOG("background routine status was %d, sock_client=%p\n",
+			 status, sock_client);
+		/* But has the client gone away ?? */
+		if (sock_client == NULL) {
+			DEBUGLOG
+			    ("Got PIPE response for dead client, ignoring it\n");
+		} else {
+			/* If error then just return that code */
+			if (status)
+				send_local_reply(sock_client, status,
+						 sock_client->fd);
+			else {
+				if (sock_client->bits.localsock.state ==
+				    POST_COMMAND) {
+					send_local_reply(sock_client, 0,
+							 sock_client->fd);
+				} else	// PRE_COMMAND finished.
+				{
+					if (
+					    (status =
+					     distribute_command(sock_client)) !=
+					    0) send_local_reply(sock_client,
+								EFBIG,
+								sock_client->
+								fd);
+				}
+			}
+		}
+	}
+	return len;
+}
+
+/* If a noed is up, look for it in the reply array, if it's not there then
+   add one with "ETIMEDOUT".
+   NOTE: This won't race with real replies because they happen in the same thread.
+*/
+static void timedout_callback(struct local_client *client, const char *csid,
+			      int node_up)
+{
+	if (node_up) {
+		struct node_reply *reply;
+		char nodename[max_cluster_member_name_len];
+
+		clops->name_from_csid(csid, nodename);
+		DEBUGLOG("Checking for a reply from %s\n", nodename);
+		pthread_mutex_lock(&client->bits.localsock.reply_mutex);
+
+		reply = client->bits.localsock.replies;
+		while (reply && strcmp(reply->node, nodename) != 0) {
+			reply = reply->next;
+		}
+
+		pthread_mutex_unlock(&client->bits.localsock.reply_mutex);
+
+		if (!reply) {
+			DEBUGLOG("Node %s timed-out\n", nodename);
+			add_reply_to_list(client, ETIMEDOUT, csid,
+					  "Command timed out", 18);
+		}
+	}
+}
+
+/* Called when the request has timed out on at least one node. We fill in
+   the remaining node entries with ETIMEDOUT and return.
+
+   By the time we get here the node that caused
+   the timeout could have gone down, in which case we will never get the expected
+   number of replies that triggers the post command so we need to do it here
+*/
+static void request_timed_out(struct local_client *client)
+{
+	DEBUGLOG("Request timed-out. padding\n");
+	clops->cluster_do_node_callback(client, timedout_callback);
+
+	if (client->bits.localsock.num_replies !=
+	    client->bits.localsock.expected_replies) {
+		/* Post-process the command */
+		if (client->bits.localsock.threadid) {
+			pthread_mutex_lock(&client->bits.localsock.mutex);
+			client->bits.localsock.state = POST_COMMAND;
+			pthread_cond_signal(&client->bits.localsock.cond);
+			pthread_mutex_unlock(&client->bits.localsock.mutex);
+		}
+	}
+}
+
+/* This is where the real work happens */
+static void main_loop(int local_sock, int cmd_timeout)
+{
+	DEBUGLOG("Using timeout of %d seconds\n", cmd_timeout);
+
+	/* Main loop */
+	while (!quit) {
+		fd_set in;
+		int select_status;
+		struct local_client *thisfd;
+		struct timeval tv = { cmd_timeout, 0 };
+		int quorate = clops->is_quorate();
+
+		/* Wait on the cluster FD and all local sockets/pipes */
+		local_client_head.fd = clops->get_main_cluster_fd();
+		FD_ZERO(&in);
+		for (thisfd = &local_client_head; thisfd != NULL;
+		     thisfd = thisfd->next) {
+
+			if (thisfd->removeme)
+				continue;
+
+			/* if the cluster is not quorate then don't listen for new requests */
+			if ((thisfd->type != LOCAL_RENDEZVOUS &&
+			     thisfd->type != LOCAL_SOCK) || quorate)
+				FD_SET(thisfd->fd, &in);
+		}
+
+		select_status = select(FD_SETSIZE, &in, NULL, NULL, &tv);
+
+		if (reread_config) {
+			int saved_errno = errno;
+
+			reread_config = 0;
+			if (clops->reread_config)
+				clops->reread_config();
+			errno = saved_errno;
+		}
+
+		if (select_status > 0) {
+			struct local_client *lastfd = NULL;
+			char csid[MAX_CSID_LEN];
+			char buf[max_cluster_message];
+
+			for (thisfd = &local_client_head; thisfd != NULL;
+			     thisfd = thisfd->next) {
+
+				if (thisfd->removeme) {
+					struct local_client *free_fd;
+					lastfd->next = thisfd->next;
+					free_fd = thisfd;
+					thisfd = lastfd;
+
+					DEBUGLOG("removeme set for fd %d\n", free_fd->fd);
+
+					/* Queue cleanup, this also frees the client struct */
+					add_to_lvmqueue(free_fd, NULL, 0, NULL);
+					break;
+				}
+
+				if (FD_ISSET(thisfd->fd, &in)) {
+					struct local_client *newfd = NULL;
+					int ret;
+
+					/* Do callback */
+					ret =
+					    thisfd->callback(thisfd, buf,
+							     sizeof(buf), csid,
+							     &newfd);
+					/* Ignore EAGAIN */
+					if (ret < 0 && (errno == EAGAIN ||
+							errno == EINTR)) continue;
+
+					/* Got error or EOF: Remove it from the list safely */
+					if (ret <= 0) {
+						struct local_client *free_fd;
+						int type = thisfd->type;
+
+						/* If the cluster socket shuts down, so do we */
+						if (type == CLUSTER_MAIN_SOCK ||
+						    type == CLUSTER_INTERNAL)
+							goto closedown;
+
+						DEBUGLOG("ret == %d, errno = %d. removing client\n",
+							 ret, errno);
+						lastfd->next = thisfd->next;
+						free_fd = thisfd;
+						thisfd = lastfd;
+						close(free_fd->fd);
+
+						/* Queue cleanup, this also frees the client struct */
+						add_to_lvmqueue(free_fd, NULL, 0, NULL);
+						break;
+					}
+
+					/* New client...simply add it to the list */
+					if (newfd) {
+						newfd->next = thisfd->next;
+						thisfd->next = newfd;
+						break;
+					}
+				}
+				lastfd = thisfd;
+			}
+		}
+
+		/* Select timed out. Check for clients that have been waiting too long for a response */
+		if (select_status == 0) {
+			time_t the_time = time(NULL);
+
+			for (thisfd = &local_client_head; thisfd != NULL;
+			     thisfd = thisfd->next) {
+				if (thisfd->type == LOCAL_SOCK
+				    && thisfd->bits.localsock.sent_out
+				    && thisfd->bits.localsock.sent_time +
+				    cmd_timeout < the_time
+				    && thisfd->bits.localsock.
+				    expected_replies !=
+				    thisfd->bits.localsock.num_replies) {
+					/* Send timed out message + replies we already have */
+					DEBUGLOG
+					    ("Request timed-out (send: %ld, now: %ld)\n",
+					     thisfd->bits.localsock.sent_time,
+					     the_time);
+
+					thisfd->bits.localsock.all_success = 0;
+
+					request_timed_out(thisfd);
+				}
+			}
+		}
+		if (select_status < 0) {
+			if (errno == EINTR)
+				continue;
+
+#ifdef DEBUG
+			perror("select error");
+			exit(-1);
+#endif
+		}
+	}
+
+      closedown:
+	clops->cluster_closedown();
+	close(local_sock);
+}
+
+static __attribute__ ((noreturn)) void wait_for_child(int c_pipe, int timeout)
+{
+	int child_status;
+	int sstat;
+	fd_set fds;
+	struct timeval tv = {timeout, 0};
+
+	FD_ZERO(&fds);
+	FD_SET(c_pipe, &fds);
+
+	sstat = select(c_pipe+1, &fds, NULL, NULL, timeout? &tv: NULL);
+	if (sstat == 0) {
+		fprintf(stderr, "clvmd startup timed out\n");
+		exit(DFAIL_TIMEOUT);
+	}
+	if (sstat == 1) {
+		if (read(c_pipe, &child_status, sizeof(child_status)) !=
+		    sizeof(child_status)) {
+
+			fprintf(stderr, "clvmd failed in initialisation\n");
+			exit(DFAIL_INIT);
+		}
+		else {
+			switch (child_status) {
+			case SUCCESS:
+				break;
+			case DFAIL_INIT:
+				fprintf(stderr, "clvmd failed in initialisation\n");
+				break;
+			case DFAIL_LOCAL_SOCK:
+				fprintf(stderr, "clvmd could not create local socket\n");
+				fprintf(stderr, "Another clvmd is probably already running\n");
+				break;
+			case DFAIL_CLUSTER_IF:
+				fprintf(stderr, "clvmd could not connect to cluster manager\n");
+				fprintf(stderr, "Consult syslog for more information\n");
+				break;
+			case DFAIL_MALLOC:
+				fprintf(stderr, "clvmd failed, not enough memory\n");
+				break;
+			default:
+				fprintf(stderr, "clvmd failed, error was %d\n", child_status);
+				break;
+			}
+			exit(child_status);
+		}
+	}
+	fprintf(stderr, "clvmd startup, select failed: %s\n", strerror(errno));
+	exit(DFAIL_INIT);
+}
+
+/*
+ * Fork into the background and detach from our parent process.
+ * In the interests of user-friendliness we wait for the daemon
+ * to complete initialisation before returning its status
+ * the the user.
+ */
+static void be_daemon(int timeout)
+{
+        pid_t pid;
+	int devnull = open("/dev/null", O_RDWR);
+	if (devnull == -1) {
+		perror("Can't open /dev/null");
+		exit(3);
+	}
+
+	pipe(child_pipe);
+
+	switch (pid = fork()) {
+	case -1:
+		perror("clvmd: can't fork");
+		exit(2);
+
+	case 0:		/* Child */
+	        close(child_pipe[0]);
+		break;
+
+	default:       /* Parent */
+		close(child_pipe[1]);
+		wait_for_child(child_pipe[0], timeout);
+	}
+
+	/* Detach ourself from the calling environment */
+	if (close(0) || close(1) || close(2)) {
+		perror("Error closing terminal FDs");
+		exit(4);
+	}
+	setsid();
+
+	if (dup2(devnull, 0) < 0 || dup2(devnull, 1) < 0
+	    || dup2(devnull, 2) < 0) {
+		perror("Error setting terminal FDs to /dev/null");
+		log_error("Error setting terminal FDs to /dev/null: %m");
+		exit(5);
+	}
+	if (chdir("/")) {
+		log_error("Error setting current directory to /: %m");
+		exit(6);
+	}
+
+}
+
+/* Called when we have a read from the local socket.
+   was in the main loop but it's grown up and is a big girl now */
+static int read_from_local_sock(struct local_client *thisfd)
+{
+	int len;
+	int argslen;
+	int missing_len;
+	char buffer[PIPE_BUF];
+
+	len = read(thisfd->fd, buffer, sizeof(buffer));
+	if (len == -1 && errno == EINTR)
+		return 1;
+
+	DEBUGLOG("Read on local socket %d, len = %d\n", thisfd->fd, len);
+
+	/* EOF or error on socket */
+	if (len <= 0) {
+		int *status;
+		int jstat;
+
+		DEBUGLOG("EOF on local socket: inprogress=%d\n",
+			 thisfd->bits.localsock.in_progress);
+
+		thisfd->bits.localsock.finished = 1;
+
+		/* If the client went away in mid command then tidy up */
+		if (thisfd->bits.localsock.in_progress) {
+			pthread_kill(thisfd->bits.localsock.threadid, SIGUSR2);
+			pthread_mutex_lock(&thisfd->bits.localsock.mutex);
+			thisfd->bits.localsock.state = POST_COMMAND;
+			pthread_cond_signal(&thisfd->bits.localsock.cond);
+			pthread_mutex_unlock(&thisfd->bits.localsock.mutex);
+
+			/* Free any unsent buffers */
+			free_reply(thisfd);
+		}
+
+		/* Kill the subthread & free resources */
+		if (thisfd->bits.localsock.threadid) {
+			DEBUGLOG("Waiting for child thread\n");
+			pthread_mutex_lock(&thisfd->bits.localsock.mutex);
+			thisfd->bits.localsock.state = PRE_COMMAND;
+			pthread_cond_signal(&thisfd->bits.localsock.cond);
+			pthread_mutex_unlock(&thisfd->bits.localsock.mutex);
+
+			jstat =
+			    pthread_join(thisfd->bits.localsock.threadid,
+					 (void **) &status);
+			DEBUGLOG("Joined child thread\n");
+
+			thisfd->bits.localsock.threadid = 0;
+			pthread_cond_destroy(&thisfd->bits.localsock.cond);
+			pthread_mutex_destroy(&thisfd->bits.localsock.mutex);
+
+			/* Remove the pipe client */
+			if (thisfd->bits.localsock.pipe_client != NULL) {
+				struct local_client *newfd;
+				struct local_client *lastfd = NULL;
+				struct local_client *free_fd = NULL;
+
+				close(thisfd->bits.localsock.pipe_client->fd);	/* Close pipe */
+				close(thisfd->bits.localsock.pipe);
+
+				/* Remove pipe client */
+				for (newfd = &local_client_head; newfd != NULL;
+				     newfd = newfd->next) {
+					if (thisfd->bits.localsock.
+					    pipe_client == newfd) {
+						thisfd->bits.localsock.
+						    pipe_client = NULL;
+
+						lastfd->next = newfd->next;
+						free_fd = newfd;
+						newfd->next = lastfd;
+						free(free_fd);
+						break;
+					}
+					lastfd = newfd;
+				}
+			}
+		}
+
+		/* Free the command buffer */
+		free(thisfd->bits.localsock.cmd);
+
+		/* Clear out the cross-link */
+		if (thisfd->bits.localsock.pipe_client != NULL)
+			thisfd->bits.localsock.pipe_client->bits.pipe.client =
+			    NULL;
+
+		close(thisfd->fd);
+		return 0;
+	} else {
+		int comms_pipe[2];
+		struct local_client *newfd;
+		char csid[MAX_CSID_LEN];
+		struct clvm_header *inheader;
+		int status;
+
+		inheader = (struct clvm_header *) buffer;
+
+		/* Fill in the client ID */
+		inheader->clientid = htonl(thisfd->fd);
+
+		/* If we are already busy then return an error */
+		if (thisfd->bits.localsock.in_progress) {
+			struct clvm_header reply;
+			reply.cmd = CLVMD_CMD_REPLY;
+			reply.status = EBUSY;
+			reply.arglen = 0;
+			reply.flags = 0;
+			send_message(&reply, sizeof(reply), our_csid,
+				     thisfd->fd,
+				     "Error sending EBUSY reply to local user");
+			return len;
+		}
+
+		/* Free any old buffer space */
+		free(thisfd->bits.localsock.cmd);
+
+		/* See if we have the whole message */
+		argslen =
+		    len - strlen(inheader->node) - sizeof(struct clvm_header);
+		missing_len = inheader->arglen - argslen;
+
+		if (missing_len < 0)
+			missing_len = 0;
+
+		/* Save the message */
+		thisfd->bits.localsock.cmd = malloc(len + missing_len);
+
+		if (!thisfd->bits.localsock.cmd) {
+			struct clvm_header reply;
+			reply.cmd = CLVMD_CMD_REPLY;
+			reply.status = ENOMEM;
+			reply.arglen = 0;
+			reply.flags = 0;
+			send_message(&reply, sizeof(reply), our_csid,
+				     thisfd->fd,
+				     "Error sending ENOMEM reply to local user");
+			return 0;
+		}
+		memcpy(thisfd->bits.localsock.cmd, buffer, len);
+		thisfd->bits.localsock.cmd_len = len + missing_len;
+		inheader = (struct clvm_header *) thisfd->bits.localsock.cmd;
+
+		/* If we don't have the full message then read the rest now */
+		if (missing_len) {
+			char *argptr =
+			    inheader->node + strlen(inheader->node) + 1;
+
+			while (missing_len > 0 && len >= 0) {
+				DEBUGLOG
+				    ("got %d bytes, need another %d (total %d)\n",
+				     argslen, missing_len, inheader->arglen);
+				len = read(thisfd->fd, argptr + argslen,
+					   missing_len);
+				if (len >= 0) {
+					missing_len -= len;
+					argslen += len;
+				}
+			}
+		}
+
+		/* Initialise and lock the mutex so the subthread will wait after
+		   finishing the PRE routine */
+		if (!thisfd->bits.localsock.threadid) {
+			pthread_mutex_init(&thisfd->bits.localsock.mutex, NULL);
+			pthread_cond_init(&thisfd->bits.localsock.cond, NULL);
+			pthread_mutex_init(&thisfd->bits.localsock.reply_mutex, NULL);
+		}
+
+		/* Only run the command if all the cluster nodes are running CLVMD */
+		if (((inheader->flags & CLVMD_FLAG_LOCAL) == 0) &&
+		    (check_all_clvmds_running(thisfd) == -1)) {
+			thisfd->bits.localsock.expected_replies = 0;
+			thisfd->bits.localsock.num_replies = 0;
+			send_local_reply(thisfd, EHOSTDOWN, thisfd->fd);
+			return len;
+		}
+
+		/* Check the node name for validity */
+		if (inheader->node[0] && clops->csid_from_name(csid, inheader->node)) {
+			/* Error, node is not in the cluster */
+			struct clvm_header reply;
+			DEBUGLOG("Unknown node: '%s'\n", inheader->node);
+
+			reply.cmd = CLVMD_CMD_REPLY;
+			reply.status = ENOENT;
+			reply.flags = 0;
+			reply.arglen = 0;
+			send_message(&reply, sizeof(reply), our_csid,
+				     thisfd->fd,
+				     "Error sending ENOENT reply to local user");
+			thisfd->bits.localsock.expected_replies = 0;
+			thisfd->bits.localsock.num_replies = 0;
+			thisfd->bits.localsock.in_progress = FALSE;
+			thisfd->bits.localsock.sent_out = FALSE;
+			return len;
+		}
+
+		/* If we already have a subthread then just signal it to start */
+		if (thisfd->bits.localsock.threadid) {
+			pthread_mutex_lock(&thisfd->bits.localsock.mutex);
+			thisfd->bits.localsock.state = PRE_COMMAND;
+			pthread_cond_signal(&thisfd->bits.localsock.cond);
+			pthread_mutex_unlock(&thisfd->bits.localsock.mutex);
+			return len;
+		}
+
+		/* Create a pipe and add the reading end to our FD list */
+		pipe(comms_pipe);
+		newfd = malloc(sizeof(struct local_client));
+		if (!newfd) {
+			struct clvm_header reply;
+			close(comms_pipe[0]);
+			close(comms_pipe[1]);
+
+			reply.cmd = CLVMD_CMD_REPLY;
+			reply.status = ENOMEM;
+			reply.arglen = 0;
+			reply.flags = 0;
+			send_message(&reply, sizeof(reply), our_csid,
+				     thisfd->fd,
+				     "Error sending ENOMEM reply to local user");
+			return len;
+		}
+		DEBUGLOG("creating pipe, [%d, %d]\n", comms_pipe[0],
+			 comms_pipe[1]);
+		newfd->fd = comms_pipe[0];
+		newfd->removeme = 0;
+		newfd->type = THREAD_PIPE;
+		newfd->callback = local_pipe_callback;
+		newfd->next = thisfd->next;
+		newfd->bits.pipe.client = thisfd;
+		newfd->bits.pipe.threadid = 0;
+		thisfd->next = newfd;
+
+		/* Store a cross link to the pipe */
+		thisfd->bits.localsock.pipe_client = newfd;
+
+		thisfd->bits.localsock.pipe = comms_pipe[1];
+
+		/* Make sure the thread has a copy of it's own ID */
+		newfd->bits.pipe.threadid = thisfd->bits.localsock.threadid;
+
+		/* Run the pre routine */
+		thisfd->bits.localsock.in_progress = TRUE;
+		thisfd->bits.localsock.state = PRE_COMMAND;
+		DEBUGLOG("Creating pre&post thread\n");
+		status = pthread_create(&thisfd->bits.localsock.threadid, NULL,
+			       pre_and_post_thread, thisfd);
+		DEBUGLOG("Created pre&post thread, state = %d\n", status);
+	}
+	return len;
+}
+
+/* Add a file descriptor from the cluster or comms interface to
+   our list of FDs for select
+*/
+int add_client(struct local_client *new_client)
+{
+	new_client->next = local_client_head.next;
+	local_client_head.next = new_client;
+
+	return 0;
+}
+
+/* Called when the pre-command has completed successfully - we
+   now execute the real command on all the requested nodes */
+static int distribute_command(struct local_client *thisfd)
+{
+	struct clvm_header *inheader =
+	    (struct clvm_header *) thisfd->bits.localsock.cmd;
+	int len = thisfd->bits.localsock.cmd_len;
+
+	thisfd->xid = global_xid++;
+	DEBUGLOG("distribute command: XID = %d\n", thisfd->xid);
+
+	/* Forward it to other nodes in the cluster if needed */
+	if (!(inheader->flags & CLVMD_FLAG_LOCAL)) {
+		/* if node is empty then do it on the whole cluster */
+		if (inheader->node[0] == '\0') {
+			thisfd->bits.localsock.expected_replies =
+			    clops->get_num_nodes();
+			thisfd->bits.localsock.num_replies = 0;
+			thisfd->bits.localsock.sent_time = time(NULL);
+			thisfd->bits.localsock.in_progress = TRUE;
+			thisfd->bits.localsock.sent_out = TRUE;
+
+			/* Do it here first */
+			add_to_lvmqueue(thisfd, inheader, len, NULL);
+
+			DEBUGLOG("Sending message to all cluster nodes\n");
+			inheader->xid = thisfd->xid;
+			send_message(inheader, len, NULL, -1,
+				     "Error forwarding message to cluster");
+		} else {
+                        /* Do it on a single node */
+			char csid[MAX_CSID_LEN];
+
+			if (clops->csid_from_name(csid, inheader->node)) {
+				/* This has already been checked so should not happen */
+				return 0;
+			} else {
+			        /* OK, found a node... */
+				thisfd->bits.localsock.expected_replies = 1;
+				thisfd->bits.localsock.num_replies = 0;
+				thisfd->bits.localsock.in_progress = TRUE;
+
+				/* Are we the requested node ?? */
+				if (memcmp(csid, our_csid, max_csid_len) == 0) {
+					DEBUGLOG("Doing command on local node only\n");
+					add_to_lvmqueue(thisfd, inheader, len, NULL);
+				} else {
+					DEBUGLOG("Sending message to single node: %s\n",
+						 inheader->node);
+					inheader->xid = thisfd->xid;
+					send_message(inheader, len,
+						     csid, -1,
+						     "Error forwarding message to cluster node");
+				}
+			}
+		}
+	} else {
+		/* Local explicitly requested, ignore nodes */
+		thisfd->bits.localsock.in_progress = TRUE;
+		thisfd->bits.localsock.expected_replies = 1;
+		thisfd->bits.localsock.num_replies = 0;
+		add_to_lvmqueue(thisfd, inheader, len, NULL);
+	}
+	return 0;
+}
+
+/* Process a command from a remote node and return the result */
+static void process_remote_command(struct clvm_header *msg, int msglen, int fd,
+			    	   const char *csid)
+{
+	char *replyargs;
+	char nodename[max_cluster_member_name_len];
+	int replylen = 0;
+	int buflen = max_cluster_message - sizeof(struct clvm_header) - 1;
+	int status;
+	int msg_malloced = 0;
+
+	/* Get the node name as we /may/ need it later */
+	clops->name_from_csid(csid, nodename);
+
+	DEBUGLOG("process_remote_command %s for clientid 0x%x XID %d on node %s\n",
+		 decode_cmd(msg->cmd), msg->clientid, msg->xid, nodename);
+
+	/* Check for GOAWAY and sulk */
+	if (msg->cmd == CLVMD_CMD_GOAWAY) {
+
+		DEBUGLOG("Told to go away by %s\n", nodename);
+		log_error("Told to go away by %s\n", nodename);
+		exit(99);
+	}
+
+	/* Version check is internal - don't bother exposing it in
+	   clvmd-command.c */
+	if (msg->cmd == CLVMD_CMD_VERSION) {
+		int version_nums[3];
+		char node[256];
+
+		memcpy(version_nums, msg->args, sizeof(version_nums));
+
+		clops->name_from_csid(csid, node);
+		DEBUGLOG("Remote node %s is version %d.%d.%d\n",
+			 node,
+			 ntohl(version_nums[0]),
+			 ntohl(version_nums[1]), ntohl(version_nums[2]));
+
+		if (ntohl(version_nums[0]) != CLVMD_MAJOR_VERSION) {
+			struct clvm_header byebyemsg;
+			DEBUGLOG
+			    ("Telling node %s to go away because of incompatible version number\n",
+			     node);
+			log_notice
+			    ("Telling node %s to go away because of incompatible version number %d.%d.%d\n",
+			     node, ntohl(version_nums[0]),
+			     ntohl(version_nums[1]), ntohl(version_nums[2]));
+
+			byebyemsg.cmd = CLVMD_CMD_GOAWAY;
+			byebyemsg.status = 0;
+			byebyemsg.flags = 0;
+			byebyemsg.arglen = 0;
+			byebyemsg.clientid = 0;
+			clops->cluster_send_message(&byebyemsg, sizeof(byebyemsg),
+					     our_csid,
+					     "Error Sending GOAWAY message");
+		} else {
+			clops->add_up_node(csid);
+		}
+		return;
+	}
+
+	/* Allocate a default reply buffer */
+	replyargs = malloc(max_cluster_message - sizeof(struct clvm_header));
+
+	if (replyargs != NULL) {
+		/* Run the command */
+		status =
+		    do_command(NULL, msg, msglen, &replyargs, buflen,
+			       &replylen);
+	} else {
+		status = ENOMEM;
+	}
+
+	/* If it wasn't a reply, then reply */
+	if (msg->cmd != CLVMD_CMD_REPLY) {
+		char *aggreply;
+
+		aggreply =
+		    realloc(replyargs, replylen + sizeof(struct clvm_header));
+		if (aggreply) {
+			struct clvm_header *agghead =
+			    (struct clvm_header *) aggreply;
+
+			replyargs = aggreply;
+			/* Move it up so there's room for a header in front of the data */
+			memmove(aggreply + offsetof(struct clvm_header, args),
+				replyargs, replylen);
+
+			agghead->xid = msg->xid;
+			agghead->cmd = CLVMD_CMD_REPLY;
+			agghead->status = status;
+			agghead->flags = 0;
+			agghead->clientid = msg->clientid;
+			agghead->arglen = replylen;
+			agghead->node[0] = '\0';
+			send_message(aggreply,
+				     sizeof(struct clvm_header) +
+				     replylen, csid, fd,
+				     "Error sending command reply");
+		} else {
+			struct clvm_header head;
+
+			DEBUGLOG("Error attempting to realloc return buffer\n");
+			/* Return a failure response */
+			head.cmd = CLVMD_CMD_REPLY;
+			head.status = ENOMEM;
+			head.flags = 0;
+			head.clientid = msg->clientid;
+			head.arglen = 0;
+			head.node[0] = '\0';
+			send_message(&head, sizeof(struct clvm_header), csid,
+				     fd, "Error sending ENOMEM command reply");
+			return;
+		}
+	}
+
+	/* Free buffer if it was malloced */
+	if (msg_malloced) {
+		free(msg);
+	}
+	free(replyargs);
+}
+
+/* Add a reply to a command to the list of replies for this client.
+   If we have got a full set then send them to the waiting client down the local
+   socket */
+static void add_reply_to_list(struct local_client *client, int status,
+			      const char *csid, const char *buf, int len)
+{
+	struct node_reply *reply;
+
+	pthread_mutex_lock(&client->bits.localsock.reply_mutex);
+
+	/* Add it to the list of replies */
+	reply = malloc(sizeof(struct node_reply));
+	if (reply) {
+		reply->status = status;
+		clops->name_from_csid(csid, reply->node);
+		DEBUGLOG("Reply from node %s: %d bytes\n", reply->node, len);
+
+		if (len > 0) {
+			reply->replymsg = malloc(len);
+			if (!reply->replymsg) {
+				reply->status = ENOMEM;
+			} else {
+				memcpy(reply->replymsg, buf, len);
+			}
+		} else {
+			reply->replymsg = NULL;
+		}
+		/* Hook it onto the reply chain */
+		reply->next = client->bits.localsock.replies;
+		client->bits.localsock.replies = reply;
+	} else {
+		/* It's all gone horribly wrong... */
+		pthread_mutex_unlock(&client->bits.localsock.reply_mutex);
+		send_local_reply(client, ENOMEM, client->fd);
+		return;
+	}
+	DEBUGLOG("Got %d replies, expecting: %d\n",
+		 client->bits.localsock.num_replies + 1,
+		 client->bits.localsock.expected_replies);
+
+	/* If we have the whole lot then do the post-process */
+	if (++client->bits.localsock.num_replies ==
+	    client->bits.localsock.expected_replies) {
+		/* Post-process the command */
+		if (client->bits.localsock.threadid) {
+			pthread_mutex_lock(&client->bits.localsock.mutex);
+			client->bits.localsock.state = POST_COMMAND;
+			pthread_cond_signal(&client->bits.localsock.cond);
+			pthread_mutex_unlock(&client->bits.localsock.mutex);
+		}
+	}
+	pthread_mutex_unlock(&client->bits.localsock.reply_mutex);
+}
+
+/* This is the thread that runs the PRE and post commands for a particular connection */
+static __attribute__ ((noreturn)) void *pre_and_post_thread(void *arg)
+{
+	struct local_client *client = (struct local_client *) arg;
+	int status;
+	int write_status;
+	sigset_t ss;
+	int pipe_fd = client->bits.localsock.pipe;
+
+	DEBUGLOG("in sub thread: client = %p\n", client);
+
+	/* Don't start until the LVM thread is ready */
+	pthread_mutex_lock(&lvm_start_mutex);
+	pthread_mutex_unlock(&lvm_start_mutex);
+	DEBUGLOG("Sub thread ready for work.\n");
+
+	/* Ignore SIGUSR1 (handled by master process) but enable
+	   SIGUSR2 (kills subthreads) */
+	sigemptyset(&ss);
+	sigaddset(&ss, SIGUSR1);
+	pthread_sigmask(SIG_BLOCK, &ss, NULL);
+
+	sigdelset(&ss, SIGUSR1);
+	sigaddset(&ss, SIGUSR2);
+	pthread_sigmask(SIG_UNBLOCK, &ss, NULL);
+
+	/* Loop around doing PRE and POST functions until the client goes away */
+	while (!client->bits.localsock.finished) {
+		/* Execute the code */
+		status = do_pre_command(client);
+
+		if (status)
+			client->bits.localsock.all_success = 0;
+
+		DEBUGLOG("Writing status %d down pipe %d\n", status, pipe_fd);
+
+		/* Tell the parent process we have finished this bit */
+		do {
+			write_status = write(pipe_fd, &status, sizeof(int));
+			if (write_status == sizeof(int))
+				break;
+			if (write_status < 0 &&
+			    (errno == EINTR || errno == EAGAIN))
+				continue;
+			log_error("Error sending to pipe: %m\n");
+			break;
+		} while(1);
+
+		if (status) {
+			client->bits.localsock.state = POST_COMMAND;
+			goto next_pre;
+		}
+
+		/* We may need to wait for the condition variable before running the post command */
+		pthread_mutex_lock(&client->bits.localsock.mutex);
+		DEBUGLOG("Waiting to do post command - state = %d\n",
+			 client->bits.localsock.state);
+
+		if (client->bits.localsock.state != POST_COMMAND) {
+			pthread_cond_wait(&client->bits.localsock.cond,
+					  &client->bits.localsock.mutex);
+		}
+		pthread_mutex_unlock(&client->bits.localsock.mutex);
+
+		DEBUGLOG("Got post command condition...\n");
+
+		/* POST function must always run, even if the client aborts */
+		status = 0;
+		do_post_command(client);
+
+		do {
+			write_status = write(pipe_fd, &status, sizeof(int));
+			if (write_status == sizeof(int))
+				break;
+			if (write_status < 0 &&
+			    (errno == EINTR || errno == EAGAIN))
+				continue;
+			log_error("Error sending to pipe: %m\n");
+			break;
+		} while(1);
+next_pre:
+		DEBUGLOG("Waiting for next pre command\n");
+
+		pthread_mutex_lock(&client->bits.localsock.mutex);
+		if (client->bits.localsock.state != PRE_COMMAND &&
+		    !client->bits.localsock.finished) {
+			pthread_cond_wait(&client->bits.localsock.cond,
+					  &client->bits.localsock.mutex);
+		}
+		pthread_mutex_unlock(&client->bits.localsock.mutex);
+
+		DEBUGLOG("Got pre command condition...\n");
+	}
+	DEBUGLOG("Subthread finished\n");
+	pthread_exit((void *) 0);
+}
+
+/* Process a command on the local node and store the result */
+static int process_local_command(struct clvm_header *msg, int msglen,
+				 struct local_client *client,
+				 unsigned short xid)
+{
+	char *replybuf = malloc(max_cluster_message);
+	int buflen = max_cluster_message - sizeof(struct clvm_header) - 1;
+	int replylen = 0;
+	int status;
+
+	DEBUGLOG("process_local_command: %s msg=%p, msglen =%d, client=%p\n",
+		 decode_cmd(msg->cmd), msg, msglen, client);
+
+	if (replybuf == NULL)
+		return -1;
+
+	status = do_command(client, msg, msglen, &replybuf, buflen, &replylen);
+
+	if (status)
+		client->bits.localsock.all_success = 0;
+
+	/* If we took too long then discard the reply */
+	if (xid == client->xid) {
+		add_reply_to_list(client, status, our_csid, replybuf, replylen);
+	} else {
+		DEBUGLOG
+		    ("Local command took too long, discarding xid %d, current is %d\n",
+		     xid, client->xid);
+	}
+
+	free(replybuf);
+	return status;
+}
+
+static int process_reply(const struct clvm_header *msg, int msglen, const char *csid)
+{
+	struct local_client *client = NULL;
+
+	client = find_client(msg->clientid);
+	if (!client) {
+		DEBUGLOG("Got message for unknown client 0x%x\n",
+			 msg->clientid);
+		log_error("Got message for unknown client 0x%x\n",
+			  msg->clientid);
+		return -1;
+	}
+
+	if (msg->status)
+		client->bits.localsock.all_success = 0;
+
+	/* Gather replies together for this client id */
+	if (msg->xid == client->xid) {
+		add_reply_to_list(client, msg->status, csid, msg->args,
+				  msg->arglen);
+	} else {
+		DEBUGLOG("Discarding reply with old XID %d, current = %d\n",
+			 msg->xid, client->xid);
+	}
+	return 0;
+}
+
+/* Send an aggregated reply back to the client */
+static void send_local_reply(struct local_client *client, int status, int fd)
+{
+	struct clvm_header *clientreply;
+	struct node_reply *thisreply = client->bits.localsock.replies;
+	char *replybuf;
+	char *ptr;
+	int message_len = 0;
+
+	DEBUGLOG("Send local reply\n");
+
+	/* Work out the total size of the reply */
+	while (thisreply) {
+		if (thisreply->replymsg)
+			message_len += strlen(thisreply->replymsg) + 1;
+		else
+			message_len++;
+
+		message_len += strlen(thisreply->node) + 1 + sizeof(int);
+
+		thisreply = thisreply->next;
+	}
+
+	/* Add in the size of our header */
+	message_len = message_len + sizeof(struct clvm_header) + 1;
+	replybuf = malloc(message_len);
+
+	clientreply = (struct clvm_header *) replybuf;
+	clientreply->status = status;
+	clientreply->cmd = CLVMD_CMD_REPLY;
+	clientreply->node[0] = '\0';
+	clientreply->flags = 0;
+
+	ptr = clientreply->args;
+
+	/* Add in all the replies, and free them as we go */
+	thisreply = client->bits.localsock.replies;
+	while (thisreply) {
+		struct node_reply *tempreply = thisreply;
+
+		strcpy(ptr, thisreply->node);
+		ptr += strlen(thisreply->node) + 1;
+
+		if (thisreply->status)
+			clientreply->flags |= CLVMD_FLAG_NODEERRS;
+
+		memcpy(ptr, &thisreply->status, sizeof(int));
+		ptr += sizeof(int);
+
+		if (thisreply->replymsg) {
+			strcpy(ptr, thisreply->replymsg);
+			ptr += strlen(thisreply->replymsg) + 1;
+		} else {
+			ptr[0] = '\0';
+			ptr++;
+		}
+		thisreply = thisreply->next;
+
+		free(tempreply->replymsg);
+		free(tempreply);
+	}
+
+	/* Terminate with an empty node name */
+	*ptr = '\0';
+
+	clientreply->arglen = ptr - clientreply->args + 1;
+
+	/* And send it */
+	send_message(replybuf, message_len, our_csid, fd,
+		     "Error sending REPLY to client");
+	free(replybuf);
+
+	/* Reset comms variables */
+	client->bits.localsock.replies = NULL;
+	client->bits.localsock.expected_replies = 0;
+	client->bits.localsock.in_progress = FALSE;
+	client->bits.localsock.sent_out = FALSE;
+}
+
+/* Just free a reply chain baceuse it wasn't used. */
+static void free_reply(struct local_client *client)
+{
+	/* Add in all the replies, and free them as we go */
+	struct node_reply *thisreply = client->bits.localsock.replies;
+	while (thisreply) {
+		struct node_reply *tempreply = thisreply;
+
+		thisreply = thisreply->next;
+
+		free(tempreply->replymsg);
+		free(tempreply);
+	}
+	client->bits.localsock.replies = NULL;
+}
+
+/* Send our version number to the cluster */
+static void send_version_message()
+{
+	char message[sizeof(struct clvm_header) + sizeof(int) * 3];
+	struct clvm_header *msg = (struct clvm_header *) message;
+	int version_nums[3];
+
+	msg->cmd = CLVMD_CMD_VERSION;
+	msg->status = 0;
+	msg->flags = 0;
+	msg->clientid = 0;
+	msg->arglen = sizeof(version_nums);
+
+	version_nums[0] = htonl(CLVMD_MAJOR_VERSION);
+	version_nums[1] = htonl(CLVMD_MINOR_VERSION);
+	version_nums[2] = htonl(CLVMD_PATCH_VERSION);
+
+	memcpy(&msg->args, version_nums, sizeof(version_nums));
+
+	hton_clvm(msg);
+
+	clops->cluster_send_message(message, sizeof(message), NULL,
+			     "Error Sending version number");
+}
+
+/* Send a message to either a local client or another server */
+static int send_message(void *buf, int msglen, const char *csid, int fd,
+			const char *errtext)
+{
+	int len = 0;
+	int saved_errno = 0;
+	struct timespec delay;
+	struct timespec remtime;
+
+	int retry_cnt = 0;
+
+	/* Send remote messages down the cluster socket */
+	if (csid == NULL || !ISLOCAL_CSID(csid)) {
+		hton_clvm((struct clvm_header *) buf);
+		return clops->cluster_send_message(buf, msglen, csid, errtext);
+	} else {
+		int ptr = 0;
+
+		/* Make sure it all goes */
+		do {
+			if (retry_cnt > MAX_RETRIES)
+			{
+				errno = saved_errno;
+				log_error("%s", errtext);
+				errno = saved_errno;
+				break;
+			}
+
+			len = write(fd, buf + ptr, msglen - ptr);
+
+			if (len <= 0) {
+				if (errno == EINTR)
+					continue;
+				if (errno == EAGAIN ||
+				    errno == EIO ||
+				    errno == ENOSPC) {
+					saved_errno = errno;
+					retry_cnt++;
+
+					delay.tv_sec = 0;
+					delay.tv_nsec = 100000;
+					remtime.tv_sec = 0;
+					remtime.tv_nsec = 0;
+					(void) nanosleep (&delay, &remtime);
+
+					continue;
+				}
+				log_error("%s", errtext);
+				break;
+			}
+			ptr += len;
+		} while (ptr < msglen);
+	}
+	return len;
+}
+
+static int process_work_item(struct lvm_thread_cmd *cmd)
+{
+	/* If msg is NULL then this is a cleanup request */
+	if (cmd->msg == NULL) {
+		DEBUGLOG("process_work_item: free fd %d\n", cmd->client->fd);
+		cmd_client_cleanup(cmd->client);
+		free(cmd->client);
+		return 0;
+	}
+
+	if (!cmd->remote) {
+		DEBUGLOG("process_work_item: local\n");
+		process_local_command(cmd->msg, cmd->msglen, cmd->client,
+				      cmd->xid);
+	} else {
+		DEBUGLOG("process_work_item: remote\n");
+		process_remote_command(cmd->msg, cmd->msglen, cmd->client->fd,
+				       cmd->csid);
+	}
+	return 0;
+}
+
+/*
+ * Routine that runs in the "LVM thread".
+ */
+static __attribute__ ((noreturn)) void *lvm_thread_fn(void *arg)
+{
+	struct dm_list *cmdl, *tmp;
+	sigset_t ss;
+	int using_gulm = (int)(long)arg;
+
+	/* Don't let anyone else to do work until we are started */
+	pthread_mutex_lock(&lvm_start_mutex);
+
+	DEBUGLOG("LVM thread function started\n");
+
+	/* Ignore SIGUSR1 & 2 */
+	sigemptyset(&ss);
+	sigaddset(&ss, SIGUSR1);
+	sigaddset(&ss, SIGUSR2);
+	pthread_sigmask(SIG_BLOCK, &ss, NULL);
+
+	/* Initialise the interface to liblvm */
+	init_lvm(using_gulm);
+
+	/* Allow others to get moving */
+	pthread_mutex_unlock(&lvm_start_mutex);
+
+	/* Now wait for some actual work */
+	for (;;) {
+		DEBUGLOG("LVM thread waiting for work\n");
+
+		pthread_mutex_lock(&lvm_thread_mutex);
+		if (dm_list_empty(&lvm_cmd_head))
+			pthread_cond_wait(&lvm_thread_cond, &lvm_thread_mutex);
+
+		dm_list_iterate_safe(cmdl, tmp, &lvm_cmd_head) {
+			struct lvm_thread_cmd *cmd;
+
+			cmd =
+			    dm_list_struct_base(cmdl, struct lvm_thread_cmd, list);
+			dm_list_del(&cmd->list);
+			pthread_mutex_unlock(&lvm_thread_mutex);
+
+			process_work_item(cmd);
+			free(cmd->msg);
+			free(cmd);
+
+			pthread_mutex_lock(&lvm_thread_mutex);
+		}
+		pthread_mutex_unlock(&lvm_thread_mutex);
+	}
+}
+
+/* Pass down some work to the LVM thread */
+static int add_to_lvmqueue(struct local_client *client, struct clvm_header *msg,
+			   int msglen, const char *csid)
+{
+	struct lvm_thread_cmd *cmd;
+
+	cmd = malloc(sizeof(struct lvm_thread_cmd));
+	if (!cmd)
+		return ENOMEM;
+
+	if (msglen) {
+		cmd->msg = malloc(msglen);
+		if (!cmd->msg) {
+			log_error("Unable to allocate buffer space\n");
+			free(cmd);
+			return -1;
+		}
+		memcpy(cmd->msg, msg, msglen);
+	}
+	else {
+		cmd->msg = NULL;
+	}
+	cmd->client = client;
+	cmd->msglen = msglen;
+	cmd->xid = client->xid;
+
+	if (csid) {
+		memcpy(cmd->csid, csid, max_csid_len);
+		cmd->remote = 1;
+	} else {
+		cmd->remote = 0;
+	}
+
+	DEBUGLOG
+	    ("add_to_lvmqueue: cmd=%p. client=%p, msg=%p, len=%d, csid=%p, xid=%d\n",
+	     cmd, client, msg, msglen, csid, cmd->xid);
+	pthread_mutex_lock(&lvm_thread_mutex);
+	dm_list_add(&lvm_cmd_head, &cmd->list);
+	pthread_cond_signal(&lvm_thread_cond);
+	pthread_mutex_unlock(&lvm_thread_mutex);
+
+	return 0;
+}
+
+/* Return 0 if we can talk to an existing clvmd */
+static int check_local_clvmd(void)
+{
+	int local_socket;
+	struct sockaddr_un sockaddr;
+	int ret = 0;
+
+	/* Open local socket */
+	if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
+		return -1;
+	}
+
+	memset(&sockaddr, 0, sizeof(sockaddr));
+	memcpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(CLVMD_SOCKNAME));
+	sockaddr.sun_family = AF_UNIX;
+
+	if (connect(local_socket,(struct sockaddr *) &sockaddr,
+		    sizeof(sockaddr))) {
+		ret = -1;
+	}
+
+	close(local_socket);
+	return ret;
+}
+
+
+/* Open the local socket, that's the one we talk to libclvm down */
+static int open_local_sock()
+{
+	int local_socket;
+	struct sockaddr_un sockaddr;
+
+	/* Open local socket */
+	if (CLVMD_SOCKNAME[0] != '\0')
+		unlink(CLVMD_SOCKNAME);
+	local_socket = socket(PF_UNIX, SOCK_STREAM, 0);
+	if (local_socket < 0) {
+		log_error("Can't create local socket: %m");
+		return -1;
+	}
+	/* Set Close-on-exec & non-blocking */
+	fcntl(local_socket, F_SETFD, 1);
+	fcntl(local_socket, F_SETFL, fcntl(local_socket, F_GETFL, 0) | O_NONBLOCK);
+
+	memset(&sockaddr, 0, sizeof(sockaddr));
+	memcpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(CLVMD_SOCKNAME));
+	sockaddr.sun_family = AF_UNIX;
+	if (bind(local_socket, (struct sockaddr *) &sockaddr, sizeof(sockaddr))) {
+		log_error("can't bind local socket: %m");
+		close(local_socket);
+		return -1;
+	}
+	if (listen(local_socket, 1) != 0) {
+		log_error("listen local: %m");
+		close(local_socket);
+		return -1;
+	}
+	if (CLVMD_SOCKNAME[0] != '\0')
+		chmod(CLVMD_SOCKNAME, 0600);
+
+	return local_socket;
+}
+
+void process_message(struct local_client *client, const char *buf, int len,
+		     const char *csid)
+{
+	struct clvm_header *inheader;
+
+	inheader = (struct clvm_header *) buf;
+	ntoh_clvm(inheader);	/* Byteswap fields */
+	if (inheader->cmd == CLVMD_CMD_REPLY)
+		process_reply(inheader, len, csid);
+	else
+		add_to_lvmqueue(client, inheader, len, csid);
+}
+
+
+static void check_all_callback(struct local_client *client, const char *csid,
+			       int node_up)
+{
+	if (!node_up)
+		add_reply_to_list(client, EHOSTDOWN, csid, "CLVMD not running",
+				  18);
+}
+
+/* Check to see if all CLVMDs are running (ie one on
+   every node in the cluster).
+   If not, returns -1 and prints out a list of errant nodes */
+static int check_all_clvmds_running(struct local_client *client)
+{
+	DEBUGLOG("check_all_clvmds_running\n");
+	return clops->cluster_do_node_callback(client, check_all_callback);
+}
+
+/* Return a local_client struct given a client ID.
+   client IDs are in network byte order */
+static struct local_client *find_client(int clientid)
+{
+	struct local_client *thisfd;
+	for (thisfd = &local_client_head; thisfd != NULL; thisfd = thisfd->next) {
+		if (thisfd->fd == ntohl(clientid))
+			return thisfd;
+	}
+	return NULL;
+}
+
+/* Byte-swapping routines for the header so we
+   work in a heterogeneous environment */
+static void hton_clvm(struct clvm_header *hdr)
+{
+	hdr->status = htonl(hdr->status);
+	hdr->arglen = htonl(hdr->arglen);
+	hdr->xid = htons(hdr->xid);
+	/* Don't swap clientid as it's only a token as far as
+	   remote nodes are concerned */
+}
+
+static void ntoh_clvm(struct clvm_header *hdr)
+{
+	hdr->status = ntohl(hdr->status);
+	hdr->arglen = ntohl(hdr->arglen);
+	hdr->xid = ntohs(hdr->xid);
+}
+
+/* Handler for SIGUSR2 - sent to kill subthreads */
+static void sigusr2_handler(int sig)
+{
+	DEBUGLOG("SIGUSR2 received\n");
+	return;
+}
+
+static void sigterm_handler(int sig)
+{
+	DEBUGLOG("SIGTERM received\n");
+	quit = 1;
+	return;
+}
+
+static void sighup_handler(int sig)
+{
+        DEBUGLOG("got SIGHUP\n");
+	reread_config = 1;
+}
+
+int sync_lock(const char *resource, int mode, int flags, int *lockid)
+{
+	return clops->sync_lock(resource, mode, flags, lockid);
+}
+
+int sync_unlock(const char *resource, int lockid)
+{
+	return clops->sync_unlock(resource, lockid);
+}
+
Index: src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd.h
diff -N src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/clvmd/clvmd.h	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,128 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _CLVMD_H
+#define _CLVMD_H
+
+#define CLVMD_MAJOR_VERSION 0
+#define CLVMD_MINOR_VERSION 2
+#define CLVMD_PATCH_VERSION 1
+
+/* Name of the cluster LVM admin lock */
+#define ADMIN_LOCK_NAME "CLVMD_ADMIN"
+
+/* Default time (in seconds) we will wait for all remote commands to execute
+   before declaring them dead */
+#define DEFAULT_CMD_TIMEOUT 60
+
+/* One of these for each reply we get from command execution on a node */
+struct node_reply {
+	char node[MAX_CLUSTER_MEMBER_NAME_LEN];
+	char *replymsg;
+	int status;
+	struct node_reply *next;
+};
+
+typedef enum {DEBUG_OFF, DEBUG_STDERR, DEBUG_SYSLOG} debug_t;
+
+/*
+ * These exist for the use of local sockets only when we are
+ * collecting responses from all cluster nodes
+ */
+struct localsock_bits {
+	struct node_reply *replies;
+	int num_replies;
+	int expected_replies;
+	time_t sent_time;	/* So we can check for timeouts */
+	int in_progress;	/* Only execute one cmd at a time per client */
+	int sent_out;		/* Flag to indicate that a command was sent
+				   to remote nodes */
+	void *private;		/* Private area for command processor use */
+	void *cmd;		/* Whole command as passed down local socket */
+	int cmd_len;		/* Length of above */
+	int pipe;		/* Pipe to send PRE completion status down */
+	int finished;		/* Flag to tell subthread to exit */
+	int all_success;	/* Set to 0 if any node (or the pre_command)
+				   failed */
+	struct local_client *pipe_client;
+	pthread_t threadid;
+	enum { PRE_COMMAND, POST_COMMAND, QUIT } state;
+	pthread_mutex_t mutex;	/* Main thread and worker synchronisation */
+	pthread_cond_t cond;
+
+	pthread_mutex_t reply_mutex;	/* Protect reply structure */
+};
+
+/* Entries for PIPE clients */
+struct pipe_bits {
+	struct local_client *client;	/* Actual (localsock) client */
+	pthread_t threadid;		/* Our own copy of the thread id */
+};
+
+/* Entries for Network socket clients */
+struct netsock_bits {
+	void *private;
+	int flags;
+};
+
+typedef int (*fd_callback_t) (struct local_client * fd, char *buf, int len,
+			      const char *csid,
+			      struct local_client ** new_client);
+
+/* One of these for each fd we are listening on */
+struct local_client {
+	int fd;
+	enum { CLUSTER_MAIN_SOCK, CLUSTER_DATA_SOCK, LOCAL_RENDEZVOUS,
+		    LOCAL_SOCK, THREAD_PIPE, CLUSTER_INTERNAL } type;
+	struct local_client *next;
+	unsigned short xid;
+	fd_callback_t callback;
+	uint8_t removeme;
+
+	union {
+		struct localsock_bits localsock;
+		struct pipe_bits pipe;
+		struct netsock_bits net;
+	} bits;
+};
+
+#define DEBUGLOG(fmt, args...) debuglog(fmt, ## args);
+
+#ifndef max
+#define max(a,b) ((a)>(b)?(a):(b))
+#endif
+
+/* The real command processor is in clvmd-command.c */
+extern int do_command(struct local_client *client, struct clvm_header *msg,
+		      int msglen, char **buf, int buflen, int *retlen);
+
+/* Pre and post command routines are called only on the local node */
+extern int do_pre_command(struct local_client *client);
+extern int do_post_command(struct local_client *client);
+extern void cmd_client_cleanup(struct local_client *client);
+extern int add_client(struct local_client *new_client);
+
+extern void clvmd_cluster_init_completed(void);
+extern void process_message(struct local_client *client, const char *buf,
+			    int len, const char *csid);
+extern void debuglog(const char *fmt, ... )
+  __attribute__ ((format(printf, 1, 2)));
+
+int sync_lock(const char *resource, int mode, int flags, int *lockid);
+int sync_unlock(const char *resource, int lockid);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/daemons/clvmd/lvm-functions.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/clvmd/lvm-functions.c
diff -N src/external/gpl2/lvm2tools/dist/daemons/clvmd/lvm-functions.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/clvmd/lvm-functions.c	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,757 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define _GNU_SOURCE
+#define _FILE_OFFSET_BITS 64
+
+#include <configure.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+#include <syslog.h>
+#include <assert.h>
+#include <libdevmapper.h>
+#include <libdlm.h>
+
+#include "lvm-types.h"
+#include "clvm.h"
+#include "clvmd-comms.h"
+#include "clvmd.h"
+#include "lvm-functions.h"
+
+/* LVM2 headers */
+#include "toolcontext.h"
+#include "lvmcache.h"
+#include "lvm-logging.h"
+#include "lvm-globals.h"
+#include "activate.h"
+#include "locking.h"
+#include "archiver.h"
+#include "defaults.h"
+
+static struct cmd_context *cmd = NULL;
+static struct dm_hash_table *lv_hash = NULL;
+static pthread_mutex_t lv_hash_lock;
+static pthread_mutex_t lvm_lock;
+static char last_error[1024];
+static int suspended = 0;
+
+struct lv_info {
+	int lock_id;
+	int lock_mode;
+};
+
+#define LCK_MASK (LCK_TYPE_MASK | LCK_SCOPE_MASK)
+
+static const char *decode_locking_cmd(unsigned char cmdl)
+{
+	static char buf[128];
+	const char *type;
+	const char *scope;
+	const char *command;
+
+	switch (cmdl & LCK_TYPE_MASK) {
+	case LCK_NULL:   
+		type = "NULL";   
+		break;
+	case LCK_READ:   
+		type = "READ";   
+		break;
+	case LCK_PREAD:  
+		type = "PREAD";  
+		break;
+	case LCK_WRITE:  
+		type = "WRITE";  
+		break;
+	case LCK_EXCL:   
+		type = "EXCL";   
+		break;
+	case LCK_UNLOCK: 
+		type = "UNLOCK"; 
+		break;
+	default:
+		type = "unknown";
+		break;
+	}
+
+	switch (cmdl & LCK_SCOPE_MASK) {
+	case LCK_VG: 
+		scope = "VG"; 
+		break;
+	case LCK_LV: 
+		scope = "LV"; 
+		break;
+	default:
+		scope = "unknown";
+		break;
+	}
+
+	switch (cmdl & LCK_MASK) {
+	case LCK_LV_EXCLUSIVE & LCK_MASK:
+		command = "LCK_LV_EXCLUSIVE";  
+		break;
+	case LCK_LV_SUSPEND & LCK_MASK:    
+		command = "LCK_LV_SUSPEND";    
+		break;
+	case LCK_LV_RESUME & LCK_MASK:     
+		command = "LCK_LV_RESUME";     
+		break;
+	case LCK_LV_ACTIVATE & LCK_MASK:   
+		command = "LCK_LV_ACTIVATE";   
+		break;
+	case LCK_LV_DEACTIVATE & LCK_MASK: 
+		command = "LCK_LV_DEACTIVATE"; 
+		break;
+	default:
+		command = "unknown";
+		break;
+	}
+
+	sprintf(buf, "0x%x %s (%s|%s%s%s%s%s%s)", cmdl, command, type, scope,
+		cmdl & LCK_NONBLOCK   ? "|NONBLOCK" : "",
+		cmdl & LCK_HOLD       ? "|HOLD" : "",
+		cmdl & LCK_LOCAL      ? "|LOCAL" : "",
+		cmdl & LCK_CLUSTER_VG ? "|CLUSTER_VG" : "",
+		cmdl & LCK_CACHE      ? "|CACHE" : "");
+
+	return buf;
+}
+
+static const char *decode_flags(unsigned char flags)
+{
+	static char buf[128];
+
+	sprintf(buf, "0x%x (%s%s)", flags,
+		flags & LCK_MIRROR_NOSYNC_MODE	  ? "MIRROR_NOSYNC " : "",
+		flags & LCK_DMEVENTD_MONITOR_MODE ? "DMEVENTD_MONITOR " : "");
+
+	return buf;
+}
+
+char *get_last_lvm_error()
+{
+	return last_error;
+}
+
+/* Return the mode a lock is currently held at (or -1 if not held) */
+static int get_current_lock(char *resource)
+{
+	struct lv_info *lvi;
+
+	pthread_mutex_lock(&lv_hash_lock);
+	lvi = dm_hash_lookup(lv_hash, resource);
+	pthread_mutex_unlock(&lv_hash_lock);
+	if (lvi) {
+		return lvi->lock_mode;
+	} else {
+		return -1;
+	}
+}
+
+/* Called at shutdown to tidy the lockspace */
+void unlock_all()
+{
+	struct dm_hash_node *v;
+
+	pthread_mutex_lock(&lv_hash_lock);
+	dm_hash_iterate(v, lv_hash) {
+		struct lv_info *lvi = dm_hash_get_data(lv_hash, v);
+
+		sync_unlock(dm_hash_get_key(lv_hash, v), lvi->lock_id);
+	}
+	pthread_mutex_unlock(&lv_hash_lock);
+}
+
+/* Gets a real lock and keeps the info in the hash table */
+int hold_lock(char *resource, int mode, int flags)
+{
+	int status;
+	int saved_errno;
+	struct lv_info *lvi;
+
+	flags &= LKF_NOQUEUE;	/* Only LKF_NOQUEUE is valid here */
+
+	pthread_mutex_lock(&lv_hash_lock);
+	lvi = dm_hash_lookup(lv_hash, resource);
+	pthread_mutex_unlock(&lv_hash_lock);
+	if (lvi) {
+		/* Already exists - convert it */
+		status =
+		    sync_lock(resource, mode, LKF_CONVERT | flags,
+			      &lvi->lock_id);
+		saved_errno = errno;
+		if (!status)
+			lvi->lock_mode = mode;
+
+		if (status) {
+			DEBUGLOG("hold_lock. convert to %d failed: %s\n", mode,
+				 strerror(errno));
+		}
+		errno = saved_errno;
+	} else {
+		lvi = malloc(sizeof(struct lv_info));
+		if (!lvi)
+			return -1;
+
+		lvi->lock_mode = mode;
+		status = sync_lock(resource, mode, flags, &lvi->lock_id);
+		saved_errno = errno;
+		if (status) {
+			free(lvi);
+			DEBUGLOG("hold_lock. lock at %d failed: %s\n", mode,
+				 strerror(errno));
+		} else {
+		        pthread_mutex_lock(&lv_hash_lock);
+			dm_hash_insert(lv_hash, resource, lvi);
+			pthread_mutex_unlock(&lv_hash_lock);
+		}
+		errno = saved_errno;
+	}
+	return status;
+}
+
+/* Unlock and remove it from the hash table */
+int hold_unlock(char *resource)
+{
+	struct lv_info *lvi;
+	int status;
+	int saved_errno;
+
+	pthread_mutex_lock(&lv_hash_lock);
+	lvi = dm_hash_lookup(lv_hash, resource);
+	pthread_mutex_unlock(&lv_hash_lock);
+	if (!lvi) {
+		DEBUGLOG("hold_unlock, lock not already held\n");
+		return 0;
+	}
+
+	status = sync_unlock(resource, lvi->lock_id);
+	saved_errno = errno;
+	if (!status) {
+	    	pthread_mutex_lock(&lv_hash_lock);
+		dm_hash_remove(lv_hash, resource);
+		pthread_mutex_unlock(&lv_hash_lock);
+		free(lvi);
+	} else {
+		DEBUGLOG("hold_unlock. unlock failed(%d): %s\n", status,
+			 strerror(errno));
+	}
+
+	errno = saved_errno;
+	return status;
+}
+
+/* Watch the return codes here.
+   liblvm API functions return 1(true) for success, 0(false) for failure and don't set errno.
+   libdlm API functions return 0 for success, -1 for failure and do set errno.
+   These functions here return 0 for success or >0 for failure (where the retcode is errno)
+*/
+
+/* Activate LV exclusive or non-exclusive */
+static int do_activate_lv(char *resource, unsigned char lock_flags, int mode)
+{
+	int oldmode;
+	int status;
+	int activate_lv;
+	int exclusive = 0;
+	struct lvinfo lvi;
+
+	/* Is it already open ? */
+	oldmode = get_current_lock(resource);
+	if (oldmode == mode) {
+		return 0;	/* Nothing to do */
+	}
+
+	/* Does the config file want us to activate this LV ? */
+	if (!lv_activation_filter(cmd, resource, &activate_lv))
+		return EIO;
+
+	if (!activate_lv)
+		return 0;	/* Success, we did nothing! */
+
+	/* Do we need to activate exclusively? */
+	if ((activate_lv == 2) || (mode == LKM_EXMODE)) {
+		exclusive = 1;
+		mode = LKM_EXMODE;
+	}
+
+	/* Try to get the lock if it's a clustered volume group */
+	if (lock_flags & LCK_CLUSTER_VG) {
+		status = hold_lock(resource, mode, LKF_NOQUEUE);
+		if (status) {
+			/* Return an LVM-sensible error for this.
+			 * Forcing EIO makes the upper level return this text
+			 * rather than the strerror text for EAGAIN.
+			 */
+			if (errno == EAGAIN) {
+				sprintf(last_error, "Volume is busy on another node");
+				errno = EIO;
+			}
+			return errno;
+		}
+	}
+
+	/* If it's suspended then resume it */
+	if (!lv_info_by_lvid(cmd, resource, &lvi, 0, 0))
+		return EIO;
+
+	if (lvi.suspended)
+		if (!lv_resume(cmd, resource))
+			return EIO;
+
+	/* Now activate it */
+	if (!lv_activate(cmd, resource, exclusive))
+		return EIO;
+
+	return 0;
+}
+
+/* Resume the LV if it was active */
+static int do_resume_lv(char *resource)
+{
+	int oldmode;
+
+	/* Is it open ? */
+	oldmode = get_current_lock(resource);
+	if (oldmode == -1) {
+		DEBUGLOG("do_resume_lv, lock not already held\n");
+		return 0;	/* We don't need to do anything */
+	}
+
+	if (!lv_resume_if_active(cmd, resource))
+		return EIO;
+
+	return 0;
+}
+
+/* Suspend the device if active */
+static int do_suspend_lv(char *resource)
+{
+	int oldmode;
+	struct lvinfo lvi;
+
+	/* Is it open ? */
+	oldmode = get_current_lock(resource);
+	if (oldmode == -1) {
+		DEBUGLOG("do_suspend_lv, lock held at %d\n", oldmode);
+		return 0; /* Not active, so it's OK */
+	}
+
+	/* Only suspend it if it exists */
+	if (!lv_info_by_lvid(cmd, resource, &lvi, 0, 0))
+		return EIO;
+
+	if (lvi.exists) {
+		if (!lv_suspend_if_active(cmd, resource)) {
+			return EIO;
+		}
+	}
+	return 0;
+}
+
+static int do_deactivate_lv(char *resource, unsigned char lock_flags)
+{
+	int oldmode;
+	int status;
+
+	/* Is it open ? */
+	oldmode = get_current_lock(resource);
+	if (oldmode == -1 && (lock_flags & LCK_CLUSTER_VG)) {
+		DEBUGLOG("do_deactivate_lock, lock not already held\n");
+		return 0;	/* We don't need to do anything */
+	}
+
+	if (!lv_deactivate(cmd, resource))
+		return EIO;
+
+	if (lock_flags & LCK_CLUSTER_VG) {
+		status = hold_unlock(resource);
+		if (status)
+			return errno;
+	}
+
+	return 0;
+}
+
+/* This is the LOCK_LV part that happens on all nodes in the cluster -
+   it is responsible for the interaction with device-mapper and LVM */
+int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
+{
+	int status = 0;
+
+	DEBUGLOG("do_lock_lv: resource '%s', cmd = %s, flags = %s\n",
+		 resource, decode_locking_cmd(command), decode_flags(lock_flags));
+
+	pthread_mutex_lock(&lvm_lock);
+	if (!cmd->config_valid || config_files_changed(cmd)) {
+		/* Reinitialise various settings inc. logging, filters */
+		if (do_refresh_cache()) {
+			log_error("Updated config file invalid. Aborting.");
+			pthread_mutex_unlock(&lvm_lock);
+			return EINVAL;
+		}
+	}
+
+	if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
+		init_mirror_in_sync(1);
+
+	if (!(lock_flags & LCK_DMEVENTD_MONITOR_MODE))
+		init_dmeventd_monitor(0);
+
+	switch (command) {
+	case LCK_LV_EXCLUSIVE:
+		status = do_activate_lv(resource, lock_flags, LKM_EXMODE);
+		break;
+
+	case LCK_LV_SUSPEND:
+		status = do_suspend_lv(resource);
+		if (!status)
+			suspended++;
+		break;
+
+	case LCK_UNLOCK:
+	case LCK_LV_RESUME:	/* if active */
+		status = do_resume_lv(resource);
+		if (!status)
+			suspended--;
+		break;
+
+	case LCK_LV_ACTIVATE:
+		status = do_activate_lv(resource, lock_flags, LKM_CRMODE);
+		break;
+
+	case LCK_LV_DEACTIVATE:
+		status = do_deactivate_lv(resource, lock_flags);
+		break;
+
+	default:
+		DEBUGLOG("Invalid LV command 0x%x\n", command);
+		status = EINVAL;
+		break;
+	}
+
+	if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
+		init_mirror_in_sync(0);
+
+	if (!(lock_flags & LCK_DMEVENTD_MONITOR_MODE))
+		init_dmeventd_monitor(DEFAULT_DMEVENTD_MONITOR);
+
+	/* clean the pool for another command */
+	dm_pool_empty(cmd->mem);
+	pthread_mutex_unlock(&lvm_lock);
+
+	DEBUGLOG("Command return is %d\n", status);
+	return status;
+}
+
+/* Functions to do on the local node only BEFORE the cluster-wide stuff above happens */
+int pre_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
+{
+	/* Nearly all the stuff happens cluster-wide. Apart from SUSPEND. Here we get the
+	   lock out on this node (because we are the node modifying the metadata)
+	   before suspending cluster-wide.
+	 */
+	if (command == LCK_LV_SUSPEND) {
+		DEBUGLOG("pre_lock_lv: resource '%s', cmd = %s, flags = %s\n",
+			 resource, decode_locking_cmd(command), decode_flags(lock_flags));
+
+		if (hold_lock(resource, LKM_PWMODE, LKF_NOQUEUE))
+			return errno;
+	}
+	return 0;
+}
+
+/* Functions to do on the local node only AFTER the cluster-wide stuff above happens */
+int post_lock_lv(unsigned char command, unsigned char lock_flags,
+		 char *resource)
+{
+	int status;
+
+	/* Opposite of above, done on resume after a metadata update */
+	if (command == LCK_LV_RESUME) {
+		int oldmode;
+
+		DEBUGLOG
+		    ("post_lock_lv: resource '%s', cmd = %s, flags = %s\n",
+		     resource, decode_locking_cmd(command), decode_flags(lock_flags));
+
+		/* If the lock state is PW then restore it to what it was */
+		oldmode = get_current_lock(resource);
+		if (oldmode == LKM_PWMODE) {
+			struct lvinfo lvi;
+
+			pthread_mutex_lock(&lvm_lock);
+			status = lv_info_by_lvid(cmd, resource, &lvi, 0, 0);
+			pthread_mutex_unlock(&lvm_lock);
+			if (!status)
+				return EIO;
+
+			if (lvi.exists) {
+				if (hold_lock(resource, LKM_CRMODE, 0))
+					return errno;
+			} else {
+				if (hold_unlock(resource))
+					return errno;
+			}
+		}
+	}
+	return 0;
+}
+
+/* Check if a VG is in use by LVM1 so we don't stomp on it */
+int do_check_lvm1(const char *vgname)
+{
+	int status;
+
+	status = check_lvm1_vg_inactive(cmd, vgname);
+
+	return status == 1 ? 0 : EBUSY;
+}
+
+int do_refresh_cache()
+{
+	int ret;
+	DEBUGLOG("Refreshing context\n");
+	log_notice("Refreshing context");
+
+	ret = refresh_toolcontext(cmd);
+	init_full_scan_done(0);
+	lvmcache_label_scan(cmd, 2);
+
+	return ret==1?0:-1;
+}
+
+
+/* Only called at gulm startup. Drop any leftover VG or P_orphan locks
+   that might be hanging around if we died for any reason
+*/
+static void drop_vg_locks()
+{
+	char vg[128];
+	char line[255];
+	FILE *vgs =
+	    popen
+	    ("lvm pvs  --config 'log{command_names=0 prefix=\"\"}' --nolocking --noheadings -o vg_name", "r");
+
+	sync_unlock("P_" VG_ORPHANS, LCK_EXCL);
+	sync_unlock("P_" VG_GLOBAL, LCK_EXCL);
+
+	if (!vgs)
+		return;
+
+	while (fgets(line, sizeof(line), vgs)) {
+		char *vgend;
+		char *vgstart;
+
+		if (line[strlen(line)-1] == '\n')
+			line[strlen(line)-1] = '\0';
+
+		vgstart = line + strspn(line, " ");
+		vgend = vgstart + strcspn(vgstart, " ");
+		*vgend = '\0';
+
+		if (strncmp(vgstart, "WARNING:", 8) == 0)
+			continue;
+
+		sprintf(vg, "V_%s", vgstart);
+		sync_unlock(vg, LCK_EXCL);
+
+	}
+	if (fclose(vgs))
+		DEBUGLOG("vgs fclose failed: %s\n", strerror(errno));
+}
+
+/*
+ * Drop lvmcache metadata
+ */
+void drop_metadata(const char *vgname)
+{
+	DEBUGLOG("Dropping metadata for VG %s\n", vgname);
+	pthread_mutex_lock(&lvm_lock);
+	lvmcache_drop_metadata(vgname);
+	pthread_mutex_unlock(&lvm_lock);
+}
+
+/*
+ * Ideally, clvmd should be started before any LVs are active
+ * but this may not be the case...
+ * I suppose this also comes in handy if clvmd crashes, not that it would!
+ */
+static void *get_initial_state()
+{
+	char lv[64], vg[64], flags[25], vg_flags[25];
+	char uuid[65];
+	char line[255];
+	FILE *lvs =
+	    popen
+	    ("lvm lvs  --config 'log{command_names=0 prefix=\"\"}' --nolocking --noheadings -o vg_uuid,lv_uuid,lv_attr,vg_attr",
+	     "r");
+
+	if (!lvs)
+		return NULL;
+
+	while (fgets(line, sizeof(line), lvs)) {
+	        if (sscanf(line, "%s %s %s %s\n", vg, lv, flags, vg_flags) == 4) {
+
+			/* States: s:suspended a:active S:dropped snapshot I:invalid snapshot */
+		        if (strlen(vg) == 38 &&                         /* is is a valid UUID ? */
+			    (flags[4] == 'a' || flags[4] == 's') &&	/* is it active or suspended? */
+			    vg_flags[5] == 'c') {			/* is it clustered ? */
+				/* Convert hyphen-separated UUIDs into one */
+				memcpy(&uuid[0], &vg[0], 6);
+				memcpy(&uuid[6], &vg[7], 4);
+				memcpy(&uuid[10], &vg[12], 4);
+				memcpy(&uuid[14], &vg[17], 4);
+				memcpy(&uuid[18], &vg[22], 4);
+				memcpy(&uuid[22], &vg[27], 4);
+				memcpy(&uuid[26], &vg[32], 6);
+				memcpy(&uuid[32], &lv[0], 6);
+				memcpy(&uuid[38], &lv[7], 4);
+				memcpy(&uuid[42], &lv[12], 4);
+				memcpy(&uuid[46], &lv[17], 4);
+				memcpy(&uuid[50], &lv[22], 4);
+				memcpy(&uuid[54], &lv[27], 4);
+				memcpy(&uuid[58], &lv[32], 6);
+				uuid[64] = '\0';
+
+				DEBUGLOG("getting initial lock for %s\n", uuid);
+				hold_lock(uuid, LKM_CRMODE, LKF_NOQUEUE);
+			}
+		}
+	}
+	if (fclose(lvs))
+		DEBUGLOG("lvs fclose failed: %s\n", strerror(errno));
+	return NULL;
+}
+
+static void lvm2_log_fn(int level, const char *file, int line,
+			const char *message)
+{
+
+	/* Send messages to the normal LVM2 logging system too,
+	   so we get debug output when it's asked for.
+ 	   We need to NULL the function ptr otherwise it will just call
+	   back into here! */
+	init_log_fn(NULL);
+	print_log(level, file, line, "%s", message);
+	init_log_fn(lvm2_log_fn);
+
+	/*
+	 * Ignore non-error messages, but store the latest one for returning
+	 * to the user.
+	 */
+	if (level != _LOG_ERR && level != _LOG_FATAL)
+		return;
+
+	strncpy(last_error, message, sizeof(last_error));
+	last_error[sizeof(last_error)-1] = '\0';
+}
+
+/* This checks some basic cluster-LVM configuration stuff */
+static void check_config()
+{
+	int locking_type;
+
+	locking_type = find_config_tree_int(cmd, "global/locking_type", 1);
+
+	if (locking_type == 3) /* compiled-in cluster support */
+		return;
+
+	if (locking_type == 2) { /* External library, check name */
+		const char *libname;
+
+		libname = find_config_tree_str(cmd, "global/locking_library",
+					  "");
+		if (strstr(libname, "liblvm2clusterlock.so"))
+			return;
+
+		log_error("Incorrect LVM locking library specified in lvm.conf, cluster operations may not work.");
+		return;
+	}
+	log_error("locking_type not set correctly in lvm.conf, cluster operations will not work.");
+}
+
+void init_lvhash()
+{
+	/* Create hash table for keeping LV locks & status */
+	lv_hash = dm_hash_create(100);
+	pthread_mutex_init(&lv_hash_lock, NULL);
+	pthread_mutex_init(&lvm_lock, NULL);
+}
+
+/* Backups up the LVM metadata if it's changed */
+void lvm_do_backup(const char *vgname)
+{
+	struct volume_group * vg;
+	int consistent = 0;
+
+	DEBUGLOG("Triggering backup of VG metadata for %s. suspended=%d\n", vgname, suspended);
+
+	vg = vg_read(cmd, vgname, NULL /*vgid*/, &consistent);
+	if (vg) {
+		if (consistent)
+			check_current_backup(vg);
+	}
+	else {
+		log_error("Error backing up metadata, can't find VG for group %s", vgname);
+	}
+}
+
+/* Called to initialise the LVM context of the daemon */
+int init_lvm(int using_gulm)
+{
+	if (!(cmd = create_toolcontext(NULL, 0, 1))) {
+		log_error("Failed to allocate command context");
+		return 0;
+	}
+
+	/* Use LOG_DAEMON for syslog messages instead of LOG_USER */
+	init_syslog(LOG_DAEMON);
+	openlog("clvmd", LOG_PID, LOG_DAEMON);
+	init_debug(cmd->current_settings.debug);
+	init_verbose(cmd->current_settings.verbose + VERBOSE_BASE_LEVEL);
+	set_activation(cmd->current_settings.activation);
+	archive_enable(cmd, cmd->current_settings.archive);
+	backup_enable(cmd, cmd->current_settings.backup);
+	cmd->cmd_line = (char *)"clvmd";
+
+	/* Check lvm.conf is setup for cluster-LVM */
+	check_config();
+
+	/* Remove any non-LV locks that may have been left around */
+	if (using_gulm)
+		drop_vg_locks();
+
+	get_initial_state();
+
+	/* Trap log messages so we can pass them back to the user */
+	init_log_fn(lvm2_log_fn);
+
+	return 1;
+}
Index: src/external/gpl2/lvm2tools/dist/daemons/clvmd/lvm-functions.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/clvmd/lvm-functions.h
diff -N src/external/gpl2/lvm2tools/dist/daemons/clvmd/lvm-functions.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/clvmd/lvm-functions.h	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,40 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* Functions in lvm-functions.c */
+
+#ifndef _LVM_FUNCTIONS_H
+#define _LVM_FUNCTIONS_H
+
+extern int pre_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
+		       char *resource);
+extern int do_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
+		      char *resource);
+extern int post_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
+			char *resource);
+extern int do_check_lvm1(const char *vgname);
+extern int do_refresh_cache(void);
+extern int init_lvm(int using_gulm);
+extern void init_lvhash(void);
+extern void lvm_do_backup(const char *vgname);
+extern int hold_unlock(char *resource);
+extern int hold_lock(char *resource, int mode, int flags);
+extern void unlock_all(void);
+extern char *get_last_lvm_error(void);
+extern void drop_metadata(const char *vgname);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/daemons/clvmd/refresh_clvmd.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/clvmd/refresh_clvmd.c
diff -N src/external/gpl2/lvm2tools/dist/daemons/clvmd/refresh_clvmd.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/clvmd/refresh_clvmd.c	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,370 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Tell all clvmds in a cluster to refresh their toolcontext
+ *
+ */
+
+#define _GNU_SOURCE
+#define _FILE_OFFSET_BITS 64
+
+#include <configure.h>
+#include <stddef.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <unistd.h>
+#include <libdevmapper.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <limits.h>
+
+#include "clvm.h"
+#include "refresh_clvmd.h"
+
+typedef struct lvm_response {
+	char node[255];
+	char *response;
+	int status;
+	int len;
+} lvm_response_t;
+
+/*
+ * This gets stuck at the start of memory we allocate so we
+ * can sanity-check it at deallocation time
+ */
+#define LVM_SIGNATURE 0x434C564D
+
+static int _clvmd_sock = -1;
+
+/* Open connection to the clvm daemon */
+static int _open_local_sock(void)
+{
+	int local_socket;
+	struct sockaddr_un sockaddr;
+
+	/* Open local socket */
+	if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
+		fprintf(stderr, "Local socket creation failed: %s", strerror(errno));
+		return -1;
+	}
+
+	memset(&sockaddr, 0, sizeof(sockaddr));
+	memcpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(CLVMD_SOCKNAME));
+
+	sockaddr.sun_family = AF_UNIX;
+
+	if (connect(local_socket,(struct sockaddr *) &sockaddr,
+		    sizeof(sockaddr))) {
+		int saved_errno = errno;
+
+		fprintf(stderr, "connect() failed on local socket: %s\n",
+			  strerror(errno));
+		if (close(local_socket))
+			return -1;
+
+		errno = saved_errno;
+		return -1;
+	}
+
+	return local_socket;
+}
+
+/* Send a request and return the status */
+static int _send_request(const char *inbuf, int inlen, char **retbuf)
+{
+	char outbuf[PIPE_BUF];
+	struct clvm_header *outheader = (struct clvm_header *) outbuf;
+	int len;
+	int off;
+	int buflen;
+	int err;
+
+	/* Send it to CLVMD */
+ rewrite:
+	if ( (err = write(_clvmd_sock, inbuf, inlen)) != inlen) {
+	        if (err == -1 && errno == EINTR)
+		        goto rewrite;
+		fprintf(stderr, "Error writing data to clvmd: %s", strerror(errno));
+		return 0;
+	}
+
+	/* Get the response */
+ reread:
+	if ((len = read(_clvmd_sock, outbuf, sizeof(struct clvm_header))) < 0) {
+	        if (errno == EINTR)
+		        goto reread;
+		fprintf(stderr, "Error reading data from clvmd: %s", strerror(errno));
+		return 0;
+	}
+
+	if (len == 0) {
+		fprintf(stderr, "EOF reading CLVMD");
+		errno = ENOTCONN;
+		return 0;
+	}
+
+	/* Allocate buffer */
+	buflen = len + outheader->arglen;
+	*retbuf = dm_malloc(buflen);
+	if (!*retbuf) {
+		errno = ENOMEM;
+		return 0;
+	}
+
+	/* Copy the header */
+	memcpy(*retbuf, outbuf, len);
+	outheader = (struct clvm_header *) *retbuf;
+
+	/* Read the returned values */
+	off = 1;		/* we've already read the first byte */
+	while (off <= outheader->arglen && len > 0) {
+		len = read(_clvmd_sock, outheader->args + off,
+			   buflen - off - offsetof(struct clvm_header, args));
+		if (len > 0)
+			off += len;
+	}
+
+	/* Was it an error ? */
+	if (outheader->status != 0) {
+		errno = outheader->status;
+
+		/* Only return an error here if there are no node-specific
+		   errors present in the message that might have more detail */
+		if (!(outheader->flags & CLVMD_FLAG_NODEERRS)) {
+			fprintf(stderr, "cluster request failed: %s\n", strerror(errno));
+			return 0;
+		}
+
+	}
+
+	return 1;
+}
+
+/* Build the structure header and parse-out wildcard node names */
+static void _build_header(struct clvm_header *head, int cmd, const char *node,
+			  int len)
+{
+	head->cmd = cmd;
+	head->status = 0;
+	head->flags = 0;
+	head->clientid = 0;
+	head->arglen = len;
+
+	if (node) {
+		/*
+		 * Allow a couple of special node names:
+		 * "*" for all nodes,
+		 * "." for the local node only
+		 */
+		if (strcmp(node, "*") == 0) {
+			head->node[0] = '\0';
+		} else if (strcmp(node, ".") == 0) {
+			head->node[0] = '\0';
+			head->flags = CLVMD_FLAG_LOCAL;
+		} else
+			strcpy(head->node, node);
+	} else
+		head->node[0] = '\0';
+}
+
+/*
+ * Send a message to a(or all) node(s) in the cluster and wait for replies
+ */
+static int _cluster_request(char cmd, const char *node, void *data, int len,
+			   lvm_response_t ** response, int *num)
+{
+	char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1];
+	char *inptr;
+	char *retbuf = NULL;
+	int status;
+	int i;
+	int num_responses = 0;
+	struct clvm_header *head = (struct clvm_header *) outbuf;
+	lvm_response_t *rarray;
+
+	*num = 0;
+
+	if (_clvmd_sock == -1)
+		_clvmd_sock = _open_local_sock();
+
+	if (_clvmd_sock == -1)
+		return 0;
+
+	_build_header(head, cmd, node, len);
+	memcpy(head->node + strlen(head->node) + 1, data, len);
+
+	status = _send_request(outbuf, sizeof(struct clvm_header) +
+			      strlen(head->node) + len, &retbuf);
+	if (!status)
+		goto out;
+
+	/* Count the number of responses we got */
+	head = (struct clvm_header *) retbuf;
+	inptr = head->args;
+	while (inptr[0]) {
+		num_responses++;
+		inptr += strlen(inptr) + 1;
+		inptr += sizeof(int);
+		inptr += strlen(inptr) + 1;
+	}
+
+	/*
+	 * Allocate response array.
+	 * With an extra pair of INTs on the front to sanity
+	 * check the pointer when we are given it back to free
+	 */
+	*response = dm_malloc(sizeof(lvm_response_t) * num_responses +
+			    sizeof(int) * 2);
+	if (!*response) {
+		errno = ENOMEM;
+		status = 0;
+		goto out;
+	}
+
+	rarray = *response;
+
+	/* Unpack the response into an lvm_response_t array */
+	inptr = head->args;
+	i = 0;
+	while (inptr[0]) {
+		strcpy(rarray[i].node, inptr);
+		inptr += strlen(inptr) + 1;
+
+		memcpy(&rarray[i].status, inptr, sizeof(int));
+		inptr += sizeof(int);
+
+		rarray[i].response = dm_malloc(strlen(inptr) + 1);
+		if (rarray[i].response == NULL) {
+			/* Free up everything else and return error */
+			int j;
+			for (j = 0; j < i; j++)
+				dm_free(rarray[i].response);
+			free(*response);
+			errno = ENOMEM;
+			status = -1;
+			goto out;
+		}
+
+		strcpy(rarray[i].response, inptr);
+		rarray[i].len = strlen(inptr);
+		inptr += strlen(inptr) + 1;
+		i++;
+	}
+	*num = num_responses;
+	*response = rarray;
+
+      out:
+	if (retbuf)
+		dm_free(retbuf);
+
+	return status;
+}
+
+/* Free reply array */
+static int _cluster_free_request(lvm_response_t * response, int num)
+{
+	int i;
+
+	for (i = 0; i < num; i++) {
+		dm_free(response[i].response);
+	}
+
+	dm_free(response);
+
+	return 1;
+}
+
+int refresh_clvmd()
+{
+	int num_responses;
+	char args[1]; // No args really.
+	lvm_response_t *response;
+	int saved_errno;
+	int status;
+	int i;
+
+	status = _cluster_request(CLVMD_CMD_REFRESH, "*", args, 0, &response, &num_responses);
+
+	/* If any nodes were down then display them and return an error */
+	for (i = 0; i < num_responses; i++) {
+		if (response[i].status == EHOSTDOWN) {
+			fprintf(stderr, "clvmd not running on node %s",
+				  response[i].node);
+			status = 0;
+			errno = response[i].status;
+		} else if (response[i].status) {
+			fprintf(stderr, "Error resetting node %s: %s",
+				  response[i].node,
+				  response[i].response[0] ?
+				  	response[i].response :
+				  	strerror(response[i].status));
+			status = 0;
+			errno = response[i].status;
+		}
+	}
+
+	saved_errno = errno;
+	_cluster_free_request(response, num_responses);
+	errno = saved_errno;
+
+	return status;
+}
+
+int debug_clvmd(int level, int clusterwide)
+{
+	int num_responses;
+	char args[1];
+	const char *nodes;
+	lvm_response_t *response;
+	int saved_errno;
+	int status;
+	int i;
+
+	args[0] = level;
+	if (clusterwide)
+		nodes = "*";
+	else
+		nodes = ".";
+
+	status = _cluster_request(CLVMD_CMD_SET_DEBUG, nodes, args, 1, &response, &num_responses);
+
+	/* If any nodes were down then display them and return an error */
+	for (i = 0; i < num_responses; i++) {
+		if (response[i].status == EHOSTDOWN) {
+			fprintf(stderr, "clvmd not running on node %s",
+				  response[i].node);
+			status = 0;
+			errno = response[i].status;
+		} else if (response[i].status) {
+			fprintf(stderr, "Error setting debug on node %s: %s",
+				  response[i].node,
+				  response[i].response[0] ?
+				  	response[i].response :
+				  	strerror(response[i].status));
+			status = 0;
+			errno = response[i].status;
+		}
+	}
+
+	saved_errno = errno;
+	_cluster_free_request(response, num_responses);
+	errno = saved_errno;
+
+	return status;
+}
Index: src/external/gpl2/lvm2tools/dist/daemons/clvmd/refresh_clvmd.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/clvmd/refresh_clvmd.h
diff -N src/external/gpl2/lvm2tools/dist/daemons/clvmd/refresh_clvmd.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/clvmd/refresh_clvmd.h	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,20 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+int refresh_clvmd(void);
+int debug_clvmd(int level, int clusterwide);
+
Index: src/external/gpl2/lvm2tools/dist/daemons/clvmd/tcp-comms.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/clvmd/tcp-comms.c
diff -N src/external/gpl2/lvm2tools/dist/daemons/clvmd/tcp-comms.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/clvmd/tcp-comms.c	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,506 @@
+/*	$NetBSD$	*/
+
+/******************************************************************************
+*******************************************************************************
+**
+**  Copyright (C) Sistina Software, Inc.  2002-2003  All rights reserved.
+**  Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+**
+*******************************************************************************
+******************************************************************************/
+
+/* This provides the inter-clvmd communications for a system without CMAN.
+   There is a listening TCP socket which accepts new connections in the
+   normal way.
+   It can also make outgoing connnections to the other clvmd nodes.
+*/
+
+#define _GNU_SOURCE
+#define _FILE_OFFSET_BITS 64
+
+#include <configure.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+#include <syslog.h>
+#include <netdb.h>
+#include <assert.h>
+#include <libdevmapper.h>
+
+#include "clvm.h"
+#include "clvmd-comms.h"
+#include "clvmd.h"
+#include "clvmd-gulm.h"
+
+#define DEFAULT_TCP_PORT 21064
+
+static int listen_fd = -1;
+static int tcp_port;
+struct dm_hash_table *sock_hash;
+
+static int get_our_ip_address(char *addr, int *family);
+static int read_from_tcpsock(struct local_client *fd, char *buf, int len, char *csid,
+			     struct local_client **new_client);
+
+/* Called by init_cluster() to open up the listening socket */
+int init_comms(unsigned short port)
+{
+    struct sockaddr_in6 addr;
+
+    sock_hash = dm_hash_create(100);
+    tcp_port = port ? : DEFAULT_TCP_PORT;
+
+    listen_fd = socket(AF_INET6, SOCK_STREAM, 0);
+
+    if (listen_fd < 0)
+    {
+	return -1;
+    }
+    else
+    {
+	int one = 1;
+	setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int));
+	setsockopt(listen_fd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(int));
+    }
+
+    memset(&addr, 0, sizeof(addr)); // Bind to INADDR_ANY
+    addr.sin6_family = AF_INET6;
+    addr.sin6_port = htons(tcp_port);
+
+    if (bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+    {
+	DEBUGLOG("Can't bind to port: %s\n", strerror(errno));
+	syslog(LOG_ERR, "Can't bind to port %d, is clvmd already running ?", tcp_port);
+	close(listen_fd);
+	return -1;
+    }
+
+    listen(listen_fd, 5);
+
+    /* Set Close-on-exec */
+    fcntl(listen_fd, F_SETFD, 1);
+
+    return 0;
+}
+
+void tcp_remove_client(const char *c_csid)
+{
+    struct local_client *client;
+    char csid[GULM_MAX_CSID_LEN];
+    unsigned int i;
+    memcpy(csid, c_csid, sizeof csid);
+    DEBUGLOG("tcp_remove_client\n");
+
+    /* Don't actually close the socket here - that's the
+       job of clvmd.c whch will do the job when it notices the
+       other end has gone. We just need to remove the client(s) from
+       the hash table so we don't try to use it for sending any more */
+    for (i = 0; i < 2; i++)
+    {
+	client = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
+	if (client)
+	{
+	    dm_hash_remove_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
+	    client->removeme = 1;
+	    close(client->fd);
+	}
+	/* Look for a mangled one too, on the 2nd iteration. */
+	csid[0] ^= 0x80;
+    }
+}
+
+int alloc_client(int fd, const char *c_csid, struct local_client **new_client)
+{
+    struct local_client *client;
+    char csid[GULM_MAX_CSID_LEN];
+    memcpy(csid, c_csid, sizeof csid);
+
+    DEBUGLOG("alloc_client %d csid = %s\n", fd, print_csid(csid));
+
+    /* Create a local_client and return it */
+    client = malloc(sizeof(struct local_client));
+    if (!client)
+    {
+	DEBUGLOG("malloc failed\n");
+	return -1;
+    }
+
+    memset(client, 0, sizeof(struct local_client));
+    client->fd = fd;
+    client->type = CLUSTER_DATA_SOCK;
+    client->callback = read_from_tcpsock;
+    if (new_client)
+	*new_client = client;
+
+    /* Add to our list of node sockets */
+    if (dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN))
+    {
+	DEBUGLOG("alloc_client mangling CSID for second connection\n");
+	/* This is a duplicate connection but we can't close it because
+	   the other end may already have started sending.
+	   So, we mangle the IP address and keep it, all sending will
+	   go out of the main FD
+	*/
+	csid[0] ^= 0x80;
+	client->bits.net.flags = 1; /* indicate mangled CSID */
+
+        /* If it still exists then kill the connection as we should only
+           ever have one incoming connection from each node */
+        if (dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN))
+        {
+	    DEBUGLOG("Multiple incoming connections from node\n");
+            syslog(LOG_ERR, " Bogus incoming connection from %d.%d.%d.%d\n", csid[0],csid[1],csid[2],csid[3]);
+
+	    free(client);
+            errno = ECONNREFUSED;
+            return -1;
+        }
+    }
+    dm_hash_insert_binary(sock_hash, csid, GULM_MAX_CSID_LEN, client);
+
+    return 0;
+}
+
+int get_main_gulm_cluster_fd()
+{
+    return listen_fd;
+}
+
+
+/* Read on main comms (listen) socket, accept it */
+int cluster_fd_gulm_callback(struct local_client *fd, char *buf, int len, const char *csid,
+			struct local_client **new_client)
+{
+    int newfd;
+    struct sockaddr_in6 addr;
+    socklen_t addrlen = sizeof(addr);
+    int status;
+    char name[GULM_MAX_CLUSTER_MEMBER_NAME_LEN];
+
+    DEBUGLOG("cluster_fd_callback\n");
+    *new_client = NULL;
+    newfd = accept(listen_fd, (struct sockaddr *)&addr, &addrlen);
+
+    DEBUGLOG("cluster_fd_callback, newfd=%d (errno=%d)\n", newfd, errno);
+    if (!newfd)
+    {
+	syslog(LOG_ERR, "error in accept: %m");
+	errno = EAGAIN;
+	return -1; /* Don't return an error or clvmd will close the listening FD */
+    }
+
+    /* Check that the client is a member of the cluster
+       and reject if not.
+    */
+    if (gulm_name_from_csid((char *)&addr.sin6_addr, name) < 0)
+    {
+	syslog(LOG_ERR, "Got connect from non-cluster node %s\n",
+	       print_csid((char *)&addr.sin6_addr));
+	DEBUGLOG("Got connect from non-cluster node %s\n",
+		 print_csid((char *)&addr.sin6_addr));
+	close(newfd);
+
+	errno = EAGAIN;
+	return -1;
+    }
+
+    status = alloc_client(newfd, (char *)&addr.sin6_addr, new_client);
+    if (status)
+    {
+	DEBUGLOG("cluster_fd_callback, alloc_client failed, status = %d\n", status);
+	close(newfd);
+	/* See above... */
+	errno = EAGAIN;
+	return -1;
+    }
+    DEBUGLOG("cluster_fd_callback, returning %d, %p\n", newfd, *new_client);
+    return newfd;
+}
+
+/* Try to get at least 'len' bytes from the socket */
+static int really_read(int fd, char *buf, int len)
+{
+	int got, offset;
+
+	got = offset = 0;
+
+	do {
+		got = read(fd, buf+offset, len-offset);
+		DEBUGLOG("really_read. got %d bytes\n", got);
+		offset += got;
+	} while (got > 0 && offset < len);
+
+	if (got < 0)
+		return got;
+	else
+		return offset;
+}
+
+
+static int read_from_tcpsock(struct local_client *client, char *buf, int len, char *csid,
+			     struct local_client **new_client)
+{
+    struct sockaddr_in6 addr;
+    socklen_t slen = sizeof(addr);
+    struct clvm_header *header = (struct clvm_header *)buf;
+    int status;
+    uint32_t arglen;
+
+    DEBUGLOG("read_from_tcpsock fd %d\n", client->fd);
+    *new_client = NULL;
+
+    /* Get "csid" */
+    getpeername(client->fd, (struct sockaddr *)&addr, &slen);
+    memcpy(csid, &addr.sin6_addr, GULM_MAX_CSID_LEN);
+
+    /* Read just the header first, then get the rest if there is any.
+     * Stream sockets, sigh.
+     */
+    status = really_read(client->fd, buf, sizeof(struct clvm_header));
+    if (status > 0)
+    {
+	    int status2;
+
+	    arglen = ntohl(header->arglen);
+
+	    /* Get the rest */
+	    if (arglen && arglen < GULM_MAX_CLUSTER_MESSAGE)
+	    {
+		    status2 = really_read(client->fd, buf+status, arglen);
+		    if (status2 > 0)
+			    status += status2;
+		    else
+			    status = status2;
+	    }
+    }
+
+    DEBUGLOG("read_from_tcpsock, status = %d(errno = %d)\n", status, errno);
+
+    /* Remove it from the hash table if there's an error, clvmd will
+       remove the socket from its lists and free the client struct */
+    if (status == 0 ||
+	(status < 0 && errno != EAGAIN && errno != EINTR))
+    {
+	char remcsid[GULM_MAX_CSID_LEN];
+
+	memcpy(remcsid, csid, GULM_MAX_CSID_LEN);
+	close(client->fd);
+
+	/* If the csid was mangled, then make sure we remove the right entry */
+	if (client->bits.net.flags)
+	    remcsid[0] ^= 0x80;
+	dm_hash_remove_binary(sock_hash, remcsid, GULM_MAX_CSID_LEN);
+
+	/* Tell cluster manager layer */
+	add_down_node(remcsid);
+    }
+    else {
+	    gulm_add_up_node(csid);
+	    /* Send it back to clvmd */
+	    process_message(client, buf, status, csid);
+    }
+    return status;
+}
+
+int gulm_connect_csid(const char *csid, struct local_client **newclient)
+{
+    int fd;
+    struct sockaddr_in6 addr;
+    int status;
+    int one = 1;
+
+    DEBUGLOG("Connecting socket\n");
+    fd = socket(PF_INET6, SOCK_STREAM, 0);
+
+    if (fd < 0)
+    {
+	syslog(LOG_ERR, "Unable to create new socket: %m");
+	return -1;
+    }
+
+    addr.sin6_family = AF_INET6;
+    memcpy(&addr.sin6_addr, csid, GULM_MAX_CSID_LEN);
+    addr.sin6_port = htons(tcp_port);
+
+    DEBUGLOG("Connecting socket %d\n", fd);
+    if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in6)) < 0)
+    {
+	/* "Connection refused" is "normal" because clvmd may not yet be running
+	 * on that node.
+	 */
+	if (errno != ECONNREFUSED)
+	{
+	    syslog(LOG_ERR, "Unable to connect to remote node: %m");
+	}
+	DEBUGLOG("Unable to connect to remote node: %s\n", strerror(errno));
+	close(fd);
+	return -1;
+    }
+
+    /* Set Close-on-exec */
+    fcntl(fd, F_SETFD, 1);
+    setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(int));
+
+    status = alloc_client(fd, csid, newclient);
+    if (status)
+	close(fd);
+    else
+	add_client(*newclient);
+
+    /* If we can connect to it, it must be running a clvmd */
+    gulm_add_up_node(csid);
+    return status;
+}
+
+/* Send a message to a known CSID */
+static int tcp_send_message(void *buf, int msglen, const char *csid, const char *errtext)
+{
+    int status;
+    struct local_client *client;
+    char ourcsid[GULM_MAX_CSID_LEN];
+
+    assert(csid);
+
+    DEBUGLOG("tcp_send_message, csid = %s, msglen = %d\n", print_csid(csid), msglen);
+
+    /* Don't connect to ourself */
+    get_our_gulm_csid(ourcsid);
+    if (memcmp(csid, ourcsid, GULM_MAX_CSID_LEN) == 0)
+	return msglen;
+
+    client = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
+    if (!client)
+    {
+	status = gulm_connect_csid(csid, &client);
+	if (status)
+	    return -1;
+    }
+    DEBUGLOG("tcp_send_message, fd = %d\n", client->fd);
+
+    return write(client->fd, buf, msglen);
+}
+
+
+int gulm_cluster_send_message(void *buf, int msglen, const char *csid, const char *errtext)
+{
+    int status=0;
+
+    DEBUGLOG("cluster send message, csid = %p, msglen = %d\n", csid, msglen);
+
+    /* If csid is NULL then send to all known (not just connected) nodes */
+    if (!csid)
+    {
+	void *context = NULL;
+	char loop_csid[GULM_MAX_CSID_LEN];
+
+	/* Loop round all gulm-known nodes */
+	while (get_next_node_csid(&context, loop_csid))
+	{
+	    status = tcp_send_message(buf, msglen, loop_csid, errtext);
+	    if (status == 0 ||
+		(status < 0 && (errno == EAGAIN || errno == EINTR)))
+		break;
+	}
+    }
+    else
+    {
+
+	status = tcp_send_message(buf, msglen, csid, errtext);
+    }
+    return status;
+}
+
+/* To get our own IP address we get the locally bound address of the
+   socket that's talking to GULM in the assumption(eek) that it will
+   be on the "right" network in a multi-homed system */
+static int get_our_ip_address(char *addr, int *family)
+{
+	struct utsname info;
+
+	uname(&info);
+	get_ip_address(info.nodename, addr);
+
+	return 0;
+}
+
+/* Public version of above for those that don't care what protocol
+   we're using */
+void get_our_gulm_csid(char *csid)
+{
+    static char our_csid[GULM_MAX_CSID_LEN];
+    static int got_csid = 0;
+
+    if (!got_csid)
+    {
+	int family;
+
+	memset(our_csid, 0, sizeof(our_csid));
+	if (get_our_ip_address(our_csid, &family))
+	{
+	    got_csid = 1;
+	}
+    }
+    memcpy(csid, our_csid, GULM_MAX_CSID_LEN);
+}
+
+static void map_v4_to_v6(struct in_addr *ip4, struct in6_addr *ip6)
+{
+   ip6->s6_addr32[0] = 0;
+   ip6->s6_addr32[1] = 0;
+   ip6->s6_addr32[2] = htonl(0xffff);
+   ip6->s6_addr32[3] = ip4->s_addr;
+}
+
+/* Get someone else's IP address from DNS */
+int get_ip_address(const char *node, char *addr)
+{
+    struct hostent *he;
+
+    memset(addr, 0, GULM_MAX_CSID_LEN);
+
+    // TODO: what do we do about multi-homed hosts ???
+    // CCSs ip_interfaces solved this but some bugger removed it.
+
+    /* Try IPv6 first. The man page for gethostbyname implies that
+       it will lookup ip6 & ip4 names, but it seems not to */
+    he = gethostbyname2(node, AF_INET6);
+    if (he)
+    {
+	memcpy(addr, he->h_addr_list[0],
+	       he->h_length);
+    }
+    else
+    {
+	he = gethostbyname2(node, AF_INET);
+	if (!he)
+	    return -1;
+	map_v4_to_v6((struct in_addr *)he->h_addr_list[0], (struct in6_addr *)addr);
+    }
+
+    return 0;
+}
+
+char *print_csid(const char *csid)
+{
+    static char buf[128];
+    int *icsid = (int *)csid;
+
+    sprintf(buf, "[%x.%x.%x.%x]",
+	    icsid[0],icsid[1],icsid[2],icsid[3]);
+
+    return buf;
+}
Index: src/external/gpl2/lvm2tools/dist/daemons/clvmd/tcp-comms.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/clvmd/tcp-comms.h
diff -N src/external/gpl2/lvm2tools/dist/daemons/clvmd/tcp-comms.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/clvmd/tcp-comms.h	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,15 @@
+/*	$NetBSD$	*/
+
+#include <netinet/in.h>
+
+#define GULM_MAX_CLUSTER_MESSAGE 1600
+#define GULM_MAX_CSID_LEN sizeof(struct in6_addr)
+#define GULM_MAX_CLUSTER_MEMBER_NAME_LEN 128
+
+extern int init_comms(unsigned short);
+extern char *print_csid(const char *);
+int get_main_gulm_cluster_fd(void);
+int cluster_fd_gulm_callback(struct local_client *fd, char *buf, int len, const char *csid, struct local_client **new_client);
+int gulm_cluster_send_message(void *buf, int msglen, const char *csid, const char *errtext);
+void get_our_gulm_csid(char *csid);
+int gulm_connect_csid(const char *csid, struct local_client **newclient);
Index: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/.exported_symbols
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/.exported_symbols
diff -N src/external/gpl2/lvm2tools/dist/daemons/dmeventd/.exported_symbols
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/dmeventd/.exported_symbols	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,19 @@
+dm_event_handler_create
+dm_event_handler_destroy
+dm_event_handler_set_dso
+dm_event_handler_set_dev_name
+dm_event_handler_set_uuid
+dm_event_handler_set_major
+dm_event_handler_set_minor
+dm_event_handler_set_event_mask
+dm_event_handler_get_dso
+dm_event_handler_get_devname
+dm_event_handler_get_uuid
+dm_event_handler_get_major
+dm_event_handler_get_minor
+dm_event_handler_get_event_mask
+dm_event_register_handler
+dm_event_unregister_handler
+dm_event_get_registered_device
+dm_event_handler_set_timeout
+dm_event_handler_get_timeout
Index: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/Makefile.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/Makefile.in
diff -N src/external/gpl2/lvm2tools/dist/daemons/dmeventd/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/dmeventd/Makefile.in	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,98 @@
+#
+# Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
+#
+# This file is part of the device-mapper userspace tools.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU Lesser General Public License v.2.1.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+SOURCES = libdevmapper-event.c
+
+LIB_STATIC = libdevmapper-event.a
+LIB_VERSION = $(LIB_VERSION_DM)
+
+ifeq ("@LIB_SUFFIX@","dylib")
+  LIB_SHARED = libdevmapper-event.dylib
+else
+  LIB_SHARED = libdevmapper-event.so
+  VERSIONED_SHLIB = $(LIB_SHARED).$(LIB_VERSION)
+endif
+
+TARGETS = dmeventd
+CLEAN_TARGETS = dmeventd.o
+
+ifneq ($(MAKECMDGOALS),device-mapper)
+  SUBDIRS+=plugins
+endif
+
+include $(top_srcdir)/make.tmpl
+
+all: dmeventd
+device-mapper: dmeventd
+
+LDFLAGS += -ldl -ldevmapper -lpthread
+CLDFLAGS += -ldl -ldevmapper -lpthread
+
+dmeventd: $(LIB_SHARED) $(VERSIONED_SHLIB) dmeventd.o
+	$(CC) -o $@ dmeventd.o $(CFLAGS) $(LDFLAGS) \
+	-L. -ldevmapper-event $(LIBS) -rdynamic
+
+.PHONY: install_dynamic install_static install_include \
+	install_pkgconfig install_dmeventd
+
+INSTALL_TYPE = install_dynamic
+
+ifeq ("@STATIC_LINK@", "yes")
+  INSTALL_TYPE += install_static
+endif
+
+ifeq ("@PKGCONFIG@", "yes")
+  INSTALL_TYPE += install_pkgconfig
+endif
+
+install: $(INSTALL_TYPE) install_include install_dmeventd
+
+install_device-mapper: install
+
+install_include:
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper-event.h \
+		$(includedir)/libdevmapper-event.h
+
+install_dynamic: libdevmapper-event.$(LIB_SUFFIX)
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
+		$(libdir)/libdevmapper-event.$(LIB_SUFFIX).$(LIB_VERSION)
+	$(LN_S) -f libdevmapper-event.$(LIB_SUFFIX).$(LIB_VERSION) \
+		$(libdir)/libdevmapper-event.$(LIB_SUFFIX)
+
+install_dmeventd: dmeventd
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< $(sbindir)/$<
+
+install_pkgconfig:
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper-event.pc \
+		$(usrlibdir)/pkgconfig/devmapper-event.pc
+
+install_static: libdevmapper-event.a
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
+		$(libdir)/libdevmapper-event.a.$(LIB_VERSION)
+	$(LN_S) -f libdevmapper-event.a.$(LIB_VERSION) $(libdir)/libdevmapper-event.a
+
+$(VERSIONED_SHLIB): $(LIB_SHARED)
+	$(RM) -f $@
+	$(LN_S) $(LIB_SHARED) $@
+
+.PHONY: distclean_lib distclean
+
+distclean_lib: 
+	$(RM) libdevmapper-event.pc
+
+distclean: distclean_lib
+
Index: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/dmeventd.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/dmeventd.c
diff -N src/external/gpl2/lvm2tools/dist/daemons/dmeventd/dmeventd.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/dmeventd/dmeventd.c	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,1763 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * dmeventd - dm event daemon to monitor active mapped devices
+ */
+
+#define _GNU_SOURCE
+#define _FILE_OFFSET_BITS 64
+
+#include "configure.h"
+#include "libdevmapper.h"
+#include "libdevmapper-event.h"
+#include "dmeventd.h"
+//#include "libmultilog.h"
+#include "dm-logging.h"
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <pthread.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <unistd.h>
+#include <signal.h>
+#include <arpa/inet.h>		/* for htonl, ntohl */
+
+#ifdef linux
+#  include <malloc.h>
+
+#  define OOM_ADJ_FILE "/proc/self/oom_adj"
+
+/* From linux/oom.h */
+#  define OOM_DISABLE (-17)
+#  define OOM_ADJUST_MIN (-16)
+
+#endif
+
+/* FIXME We use syslog for now, because multilog is not yet implemented */
+#include <syslog.h>
+
+static volatile sig_atomic_t _exit_now = 0;	/* set to '1' when signal is given to exit */
+static volatile sig_atomic_t _thread_registries_empty = 1;	/* registries are empty initially */
+static int _debug = 0;
+
+/* List (un)link macros. */
+#define	LINK(x, head)		dm_list_add(head, &(x)->list)
+#define	LINK_DSO(dso)		LINK(dso, &_dso_registry)
+#define	LINK_THREAD(thread)	LINK(thread, &_thread_registry)
+
+#define	UNLINK(x)		dm_list_del(&(x)->list)
+#define	UNLINK_DSO(x)		UNLINK(x)
+#define	UNLINK_THREAD(x)	UNLINK(x)
+
+#define DAEMON_NAME "dmeventd"
+
+/*
+  Global mutex for thread list access. Has to be held when:
+  - iterating thread list
+  - adding or removing elements from thread list
+  - changing or reading thread_status's fields:
+    processing, status, events
+  Use _lock_mutex() and _unlock_mutex() to hold/release it
+*/
+static pthread_mutex_t _global_mutex;
+
+/*
+  There are three states a thread can attain (see struct
+  thread_status, field int status):
+
+  - DM_THREAD_RUNNING: thread has started up and is either working or
+  waiting for events... transitions to either SHUTDOWN or DONE
+  - DM_THREAD_SHUTDOWN: thread is still doing something, but it is
+  supposed to terminate (and transition to DONE) as soon as it
+  finishes whatever it was doing at the point of flipping state to
+  SHUTDOWN... the thread is still on the thread list
+  - DM_THREAD_DONE: thread has terminated and has been moved over to
+  unused thread list, cleanup pending
+ */
+#define DM_THREAD_RUNNING  0
+#define DM_THREAD_SHUTDOWN 1
+#define DM_THREAD_DONE     2
+
+#define THREAD_STACK_SIZE (300*1024)
+
+#define DEBUGLOG(fmt, args...) _debuglog(fmt, ## args)
+
+/* Data kept about a DSO. */
+struct dso_data {
+	struct dm_list list;
+
+	char *dso_name;		/* DSO name (eg, "evms", "dmraid", "lvm2"). */
+
+	void *dso_handle;	/* Opaque handle as returned from dlopen(). */
+	unsigned int ref_count;	/* Library reference count. */
+
+	/*
+	 * Event processing.
+	 *
+	 * The DSO can do whatever appropriate steps if an event
+	 * happens such as changing the mapping in case a mirror
+	 * fails, update the application metadata etc.
+	 *
+	 * This function gets a dm_task that is a result of
+	 * DM_DEVICE_WAITEVENT ioctl (results equivalent to
+	 * DM_DEVICE_STATUS). It should not destroy it.
+	 * The caller must dispose of the task.
+	 */
+	void (*process_event)(struct dm_task *dmt, enum dm_event_mask event, void **user);
+
+	/*
+	 * Device registration.
+	 *
+	 * When an application registers a device for an event, the DSO
+	 * can carry out appropriate steps so that a later call to
+	 * the process_event() function is sane (eg, read metadata
+	 * and activate a mapping).
+	 */
+	int (*register_device)(const char *device, const char *uuid, int major,
+			       int minor, void **user);
+
+	/*
+	 * Device unregistration.
+	 *
+	 * In case all devices of a mapping (eg, RAID10) are unregistered
+	 * for events, the DSO can recognize this and carry out appropriate
+	 * steps (eg, deactivate mapping, metadata update).
+	 */
+	int (*unregister_device)(const char *device, const char *uuid,
+				 int major, int minor, void **user);
+};
+static DM_LIST_INIT(_dso_registry);
+
+/* Structure to keep parsed register variables from client message. */
+struct message_data {
+	char *id;
+	char *dso_name;		/* Name of DSO. */
+	char *device_uuid;	/* Mapped device path. */
+	union {
+		char *str;	/* Events string as fetched from message. */
+		enum dm_event_mask field;	/* Events bitfield. */
+	} events;
+	union {
+		char *str;
+		uint32_t secs;
+	} timeout;
+	struct dm_event_daemon_message *msg;	/* Pointer to message buffer. */
+};
+
+/*
+ * Housekeeping of thread+device states.
+ *
+ * One thread per mapped device which can block on it until an event
+ * occurs and the event processing function of the DSO gets called.
+ */
+struct thread_status {
+	struct dm_list list;
+
+	pthread_t thread;
+
+	struct dso_data *dso_data;	/* DSO this thread accesses. */
+
+	struct {
+		char *uuid;
+		char *name;
+		int major, minor;
+	} device;
+	uint32_t event_nr;	/* event number */
+	int processing;		/* Set when event is being processed */
+
+	int status;		/* see DM_THREAD_{RUNNING,SHUTDOWN,DONE}
+				   constants above */
+	enum dm_event_mask events;	/* bitfield for event filter. */
+	enum dm_event_mask current_events;	/* bitfield for occured events. */
+	struct dm_task *current_task;
+	time_t next_time;
+	uint32_t timeout;
+	struct dm_list timeout_list;
+	void *dso_private; /* dso per-thread status variable */
+};
+static DM_LIST_INIT(_thread_registry);
+static DM_LIST_INIT(_thread_registry_unused);
+
+static int _timeout_running;
+static DM_LIST_INIT(_timeout_registry);
+static pthread_mutex_t _timeout_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t _timeout_cond = PTHREAD_COND_INITIALIZER;
+
+static void _debuglog(const char *fmt, ...)
+{
+        time_t P;
+        va_list ap;
+ 
+        if (!_debug)
+                return;
+ 
+        va_start(ap,fmt);
+
+        time(&P);
+        fprintf(stderr, "dmeventd[%p]: %.15s ", (void *) pthread_self(), ctime(&P)+4 );
+        vfprintf(stderr, fmt, ap);
+	fprintf(stderr, "\n");
+
+        va_end(ap);
+}
+
+/* Allocate/free the status structure for a monitoring thread. */
+static struct thread_status *_alloc_thread_status(struct message_data *data,
+						  struct dso_data *dso_data)
+{
+	struct thread_status *ret = (typeof(ret)) dm_malloc(sizeof(*ret));
+
+	if (!ret)
+		return NULL;
+
+	memset(ret, 0, sizeof(*ret));
+	if (!(ret->device.uuid = dm_strdup(data->device_uuid))) {
+		dm_free(ret);
+		return NULL;
+	}
+
+	ret->current_task = NULL;
+	ret->device.name = NULL;
+	ret->device.major = ret->device.minor = 0;
+	ret->dso_data = dso_data;
+	ret->events = data->events.field;
+	ret->timeout = data->timeout.secs;
+	dm_list_init(&ret->timeout_list);
+
+	return ret;
+}
+
+static void _free_thread_status(struct thread_status *thread)
+{
+	if (thread->current_task)
+		dm_task_destroy(thread->current_task);
+	dm_free(thread->device.uuid);
+	dm_free(thread->device.name);
+	dm_free(thread);
+}
+
+/* Allocate/free DSO data. */
+static struct dso_data *_alloc_dso_data(struct message_data *data)
+{
+	struct dso_data *ret = (typeof(ret)) dm_malloc(sizeof(*ret));
+
+	if (!ret)
+		return NULL;
+
+	memset(ret, 0, sizeof(*ret));
+	if (!(ret->dso_name = dm_strdup(data->dso_name))) {
+		dm_free(ret);
+		return NULL;
+	}
+
+	return ret;
+}
+
+/* Create a device monitoring thread. */
+static int _pthread_create_smallstack(pthread_t *t, void *(*fun)(void *), void *arg)
+{
+	pthread_attr_t attr;
+	pthread_attr_init(&attr);
+	/*
+	 * We use a smaller stack since it gets preallocated in its entirety
+	 */
+	pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE);
+	return pthread_create(t, &attr, fun, arg);
+}
+
+static void _free_dso_data(struct dso_data *data)
+{
+	dm_free(data->dso_name);
+	dm_free(data);
+}
+
+/*
+ * Fetch a string off src and duplicate it into *ptr.
+ * Pay attention to zero-length strings.
+ */
+/* FIXME? move to libdevmapper to share with the client lib (need to
+   make delimiter a parameter then) */
+static int _fetch_string(char **ptr, char **src, const int delimiter)
+{
+	int ret = 0;
+	char *p;
+	size_t len;
+
+	if ((p = strchr(*src, delimiter)))
+		*p = 0;
+
+	if ((*ptr = dm_strdup(*src))) {
+		if ((len = strlen(*ptr)))
+			*src += len;
+		else {
+			dm_free(*ptr);
+			*ptr = NULL;
+		}
+
+		(*src)++;
+		ret = 1;
+	}
+
+	if (p)
+		*p = delimiter;
+
+	return ret;
+}
+
+/* Free message memory. */
+static void _free_message(struct message_data *message_data)
+{
+	if (message_data->id)
+		dm_free(message_data->id);
+	if (message_data->dso_name)
+		dm_free(message_data->dso_name);
+
+	if (message_data->device_uuid)
+		dm_free(message_data->device_uuid);
+
+}
+
+/* Parse a register message from the client. */
+static int _parse_message(struct message_data *message_data)
+{
+	int ret = 0;
+	char *p = message_data->msg->data;
+	struct dm_event_daemon_message *msg = message_data->msg;
+
+	if (!msg->data)
+		return 0;
+
+	/*
+	 * Retrieve application identifier, mapped device
+	 * path and events # string from message.
+	 */
+	if (_fetch_string(&message_data->id, &p, ' ') &&
+	    _fetch_string(&message_data->dso_name, &p, ' ') &&
+	    _fetch_string(&message_data->device_uuid, &p, ' ') &&
+	    _fetch_string(&message_data->events.str, &p, ' ') &&
+	    _fetch_string(&message_data->timeout.str, &p, ' ')) {
+		if (message_data->events.str) {
+			enum dm_event_mask i = atoi(message_data->events.str);
+
+			/*
+			 * Free string representaion of events.
+			 * Not needed an more.
+			 */
+			dm_free(message_data->events.str);
+			message_data->events.field = i;
+		}
+		if (message_data->timeout.str) {
+			uint32_t secs = atoi(message_data->timeout.str);
+			dm_free(message_data->timeout.str);
+			message_data->timeout.secs = secs ? secs :
+			    DM_EVENT_DEFAULT_TIMEOUT;
+		}
+
+		ret = 1;
+	}
+
+	dm_free(msg->data);
+	msg->data = NULL;
+	msg->size = 0;
+	return ret;
+};
+
+/* Global mutex to lock access to lists et al. See _global_mutex
+   above. */
+static int _lock_mutex(void)
+{
+	return pthread_mutex_lock(&_global_mutex);
+}
+
+static int _unlock_mutex(void)
+{
+	return pthread_mutex_unlock(&_global_mutex);
+}
+
+/* Store pid in pidfile. */
+static int _storepid(int lf)
+{
+	int len;
+	char pid[8];
+
+	if ((len = snprintf(pid, sizeof(pid), "%u\n", getpid())) < 0)
+		return 0;
+
+	if (len > (int) sizeof(pid))
+		len = (int) sizeof(pid);
+
+	if (write(lf, pid, (size_t) len) != len)
+		return 0;
+
+	fsync(lf);
+
+	return 1;
+}
+
+/* Check, if a device exists. */
+static int _fill_device_data(struct thread_status *ts)
+{
+	struct dm_task *dmt;
+	struct dm_info dmi;
+
+	if (!ts->device.uuid)
+		return 0;
+
+	ts->device.name = NULL;
+	ts->device.major = ts->device.minor = 0;
+
+	dmt = dm_task_create(DM_DEVICE_INFO);
+	if (!dmt)
+		return 0;
+
+	dm_task_set_uuid(dmt, ts->device.uuid);
+	if (!dm_task_run(dmt))
+		goto fail;
+
+	ts->device.name = dm_strdup(dm_task_get_name(dmt));
+	if (!ts->device.name)
+		goto fail;
+
+	if (!dm_task_get_info(dmt, &dmi))
+		goto fail;
+
+	ts->device.major = dmi.major;
+	ts->device.minor = dmi.minor;
+
+	dm_task_destroy(dmt);
+	return 1;
+
+      fail:
+	dm_task_destroy(dmt);
+	dm_free(ts->device.name);
+	return 0;
+}
+
+/*
+ * Find an existing thread for a device.
+ *
+ * Mutex must be held when calling this.
+ */
+static struct thread_status *_lookup_thread_status(struct message_data *data)
+{
+	struct thread_status *thread;
+
+	dm_list_iterate_items(thread, &_thread_registry)
+	    if (!strcmp(data->device_uuid, thread->device.uuid))
+		return thread;
+
+	return NULL;
+}
+
+/* Cleanup at exit. */
+static void _exit_dm_lib(void)
+{
+	dm_lib_release();
+	dm_lib_exit();
+}
+
+static void _exit_timeout(void *unused __attribute((unused)))
+{
+	_timeout_running = 0;
+	pthread_mutex_unlock(&_timeout_mutex);
+}
+
+/* Wake up monitor threads every so often. */
+static void *_timeout_thread(void *unused __attribute((unused)))
+{
+	struct timespec timeout;
+	time_t curr_time;
+
+	timeout.tv_nsec = 0;
+	pthread_cleanup_push(_exit_timeout, NULL);
+	pthread_mutex_lock(&_timeout_mutex);
+
+	while (!dm_list_empty(&_timeout_registry)) {
+		struct thread_status *thread;
+
+		timeout.tv_sec = 0;
+		curr_time = time(NULL);
+
+		dm_list_iterate_items_gen(thread, &_timeout_registry, timeout_list) {
+			if (thread->next_time <= curr_time) {
+				thread->next_time = curr_time + thread->timeout;
+				pthread_kill(thread->thread, SIGALRM);
+			}
+
+			if (thread->next_time < timeout.tv_sec || !timeout.tv_sec)
+				timeout.tv_sec = thread->next_time;
+		}
+
+		pthread_cond_timedwait(&_timeout_cond, &_timeout_mutex,
+				       &timeout);
+	}
+
+	pthread_cleanup_pop(1);
+
+	return NULL;
+}
+
+static int _register_for_timeout(struct thread_status *thread)
+{
+	int ret = 0;
+
+	pthread_mutex_lock(&_timeout_mutex);
+
+	thread->next_time = time(NULL) + thread->timeout;
+
+	if (dm_list_empty(&thread->timeout_list)) {
+		dm_list_add(&_timeout_registry, &thread->timeout_list);
+		if (_timeout_running)
+			pthread_cond_signal(&_timeout_cond);
+	}
+
+	if (!_timeout_running) {
+		pthread_t timeout_id;
+
+		if (!(ret = -_pthread_create_smallstack(&timeout_id, _timeout_thread, NULL)))
+			_timeout_running = 1;
+	}
+
+	pthread_mutex_unlock(&_timeout_mutex);
+
+	return ret;
+}
+
+static void _unregister_for_timeout(struct thread_status *thread)
+{
+	pthread_mutex_lock(&_timeout_mutex);
+	if (!dm_list_empty(&thread->timeout_list)) {
+		dm_list_del(&thread->timeout_list);
+		dm_list_init(&thread->timeout_list);
+	}
+	pthread_mutex_unlock(&_timeout_mutex);
+}
+
+static void _no_intr_log(int level, const char *file, int line,
+			const char *f, ...)
+{
+	va_list ap;
+
+	if (errno == EINTR)
+		return;
+	if (level > _LOG_WARN)
+		return;
+
+	va_start(ap, f);
+
+	if (level < _LOG_WARN)
+		vfprintf(stderr, f, ap);
+	else
+		vprintf(f, ap);
+
+	va_end(ap);
+
+	if (level < _LOG_WARN)
+		fprintf(stderr, "\n");
+	else
+		fprintf(stdout, "\n");
+}
+
+static sigset_t _unblock_sigalrm(void)
+{
+	sigset_t set, old;
+
+	sigemptyset(&set);
+	sigaddset(&set, SIGALRM);
+	pthread_sigmask(SIG_UNBLOCK, &set, &old);
+	return old;
+}
+
+#define DM_WAIT_RETRY 0
+#define DM_WAIT_INTR 1
+#define DM_WAIT_FATAL 2
+
+/* Wait on a device until an event occurs. */
+static int _event_wait(struct thread_status *thread, struct dm_task **task)
+{
+	sigset_t set;
+	int ret = DM_WAIT_RETRY;
+	struct dm_task *dmt;
+	struct dm_info info;
+
+	*task = 0;
+
+	if (!(dmt = dm_task_create(DM_DEVICE_WAITEVENT)))
+		return DM_WAIT_RETRY;
+
+	thread->current_task = dmt;
+
+	if (!dm_task_set_uuid(dmt, thread->device.uuid) ||
+	    !dm_task_set_event_nr(dmt, thread->event_nr))
+		goto out;
+
+	/*
+	 * This is so that you can break out of waiting on an event,
+	 * either for a timeout event, or to cancel the thread.
+	 */
+	set = _unblock_sigalrm();
+	dm_log_init(_no_intr_log);
+	errno = 0;
+	if (dm_task_run(dmt)) {
+		thread->current_events |= DM_EVENT_DEVICE_ERROR;
+		ret = DM_WAIT_INTR;
+
+		if ((ret = dm_task_get_info(dmt, &info)))
+			thread->event_nr = info.event_nr;
+	} else if (thread->events & DM_EVENT_TIMEOUT && errno == EINTR) {
+		thread->current_events |= DM_EVENT_TIMEOUT;
+		ret = DM_WAIT_INTR;
+	} else if (thread->status == DM_THREAD_SHUTDOWN && errno == EINTR) {
+		ret = DM_WAIT_FATAL;
+	} else {
+		syslog(LOG_NOTICE, "dm_task_run failed, errno = %d, %s",
+		       errno, strerror(errno));
+		if (errno == ENXIO) {
+			syslog(LOG_ERR, "%s disappeared, detaching",
+			       thread->device.name);
+			ret = DM_WAIT_FATAL;
+		}
+	}
+
+	pthread_sigmask(SIG_SETMASK, &set, NULL);
+	dm_log_init(NULL);
+
+      out:
+	if (ret == DM_WAIT_FATAL || ret == DM_WAIT_RETRY) {
+		dm_task_destroy(dmt);
+		thread->current_task = NULL;
+	} else
+		*task = dmt;
+
+	return ret;
+}
+
+/* Register a device with the DSO. */
+static int _do_register_device(struct thread_status *thread)
+{
+	return thread->dso_data->register_device(thread->device.name,
+						 thread->device.uuid,
+						 thread->device.major,
+						 thread->device.minor,
+						 &(thread->dso_private));
+}
+
+/* Unregister a device with the DSO. */
+static int _do_unregister_device(struct thread_status *thread)
+{
+	return thread->dso_data->unregister_device(thread->device.name,
+						   thread->device.uuid,
+						   thread->device.major,
+						   thread->device.minor,
+						   &(thread->dso_private));
+}
+
+/* Process an event in the DSO. */
+static void _do_process_event(struct thread_status *thread, struct dm_task *task)
+{
+	thread->dso_data->process_event(task, thread->current_events, &(thread->dso_private));
+}
+
+/* Thread cleanup handler to unregister device. */
+static void _monitor_unregister(void *arg)
+{
+	struct thread_status *thread = arg, *thread_iter;
+
+	if (!_do_unregister_device(thread))
+		syslog(LOG_ERR, "%s: %s unregister failed\n", __func__,
+		       thread->device.name);
+	if (thread->current_task)
+		dm_task_destroy(thread->current_task);
+	thread->current_task = NULL;
+
+	_lock_mutex();
+	if (thread->events & DM_EVENT_TIMEOUT) {
+		/* _unregister_for_timeout locks another mutex, we
+		   don't want to deadlock so we release our mutex for
+		   a bit */
+		_unlock_mutex();
+		_unregister_for_timeout(thread);
+		_lock_mutex();
+	}
+	/* we may have been relinked to unused registry since we were
+	   called, so check that */
+	dm_list_iterate_items(thread_iter, &_thread_registry_unused)
+		if (thread_iter == thread) {
+			thread->status = DM_THREAD_DONE;
+			_unlock_mutex();
+			return;
+		}
+	thread->status = DM_THREAD_DONE;
+	UNLINK_THREAD(thread);
+	LINK(thread, &_thread_registry_unused);
+	_unlock_mutex();
+}
+
+static struct dm_task *_get_device_status(struct thread_status *ts)
+{
+	struct dm_task *dmt = dm_task_create(DM_DEVICE_STATUS);
+
+	if (!dmt)
+		return NULL;
+
+	dm_task_set_uuid(dmt, ts->device.uuid);
+
+	if (!dm_task_run(dmt)) {
+		dm_task_destroy(dmt);
+		return NULL;
+	}
+
+	return dmt;
+}
+
+/* Device monitoring thread. */
+static void *_monitor_thread(void *arg)
+{
+	struct thread_status *thread = arg;
+	int wait_error = 0;
+	struct dm_task *task;
+
+	pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
+	pthread_cleanup_push(_monitor_unregister, thread);
+
+	/* Wait for do_process_request() to finish its task. */
+	_lock_mutex();
+	thread->status = DM_THREAD_RUNNING;
+	_unlock_mutex();
+
+	/* Loop forever awaiting/analyzing device events. */
+	while (1) {
+		thread->current_events = 0;
+
+		wait_error = _event_wait(thread, &task);
+		if (wait_error == DM_WAIT_RETRY)
+			continue;
+
+		if (wait_error == DM_WAIT_FATAL)
+			break;
+
+		/* Timeout occurred, task is not filled properly.
+		 * We get device status here for processing it in DSO.
+		 */
+		if (wait_error == DM_WAIT_INTR &&
+		    thread->current_events & DM_EVENT_TIMEOUT) {
+			dm_task_destroy(task);
+			task = _get_device_status(thread);
+			/* FIXME: syslog fail here ? */
+			if (!(thread->current_task = task))
+				continue;
+		}
+
+		/*
+		 * We know that wait succeeded and stored a
+		 * pointer to dm_task with device status into task.
+		 */
+
+		/*
+		 * Check against filter.
+		 *
+		 * If there's current events delivered from _event_wait() AND
+		 * the device got registered for those events AND
+		 * those events haven't been processed yet, call
+		 * the DSO's process_event() handler.
+		 */
+		_lock_mutex();
+		if (thread->status == DM_THREAD_SHUTDOWN) {
+			_unlock_mutex();
+			break;
+		}
+		_unlock_mutex();
+
+		if (thread->events & thread->current_events) {
+			_lock_mutex();
+			thread->processing = 1;
+			_unlock_mutex();
+
+			_do_process_event(thread, task);
+			dm_task_destroy(task);
+			thread->current_task = NULL;
+
+			_lock_mutex();
+			thread->processing = 0;
+			_unlock_mutex();
+		} else {
+			dm_task_destroy(task);
+			thread->current_task = NULL;
+		}
+	}
+
+	pthread_cleanup_pop(1);
+
+	return NULL;
+}
+
+/* Create a device monitoring thread. */
+static int _create_thread(struct thread_status *thread)
+{
+	return _pthread_create_smallstack(&thread->thread, _monitor_thread, thread);
+}
+
+static int _terminate_thread(struct thread_status *thread)
+{
+	return pthread_kill(thread->thread, SIGALRM);
+}
+
+/* DSO reference counting. Call with _global_mutex locked! */
+static void _lib_get(struct dso_data *data)
+{
+	data->ref_count++;
+}
+
+static void _lib_put(struct dso_data *data)
+{
+	if (!--data->ref_count) {
+		dlclose(data->dso_handle);
+		UNLINK_DSO(data);
+		_free_dso_data(data);
+	}
+}
+
+/* Find DSO data. */
+static struct dso_data *_lookup_dso(struct message_data *data)
+{
+	struct dso_data *dso_data, *ret = NULL;
+
+	dm_list_iterate_items(dso_data, &_dso_registry)
+	    if (!strcmp(data->dso_name, dso_data->dso_name)) {
+		_lib_get(dso_data);
+		ret = dso_data;
+		break;
+	}
+
+	return ret;
+}
+
+/* Lookup DSO symbols we need. */
+static int _lookup_symbol(void *dl, void **symbol, const char *name)
+{
+	if ((*symbol = dlsym(dl, name)))
+		return 1;
+
+	return 0;
+}
+
+static int lookup_symbols(void *dl, struct dso_data *data)
+{
+	return _lookup_symbol(dl, (void *) &data->process_event,
+			     "process_event") &&
+	    _lookup_symbol(dl, (void *) &data->register_device,
+			  "register_device") &&
+	    _lookup_symbol(dl, (void *) &data->unregister_device,
+			  "unregister_device");
+}
+
+/* Load an application specific DSO. */
+static struct dso_data *_load_dso(struct message_data *data)
+{
+	void *dl;
+	struct dso_data *ret = NULL;
+
+	if (!(dl = dlopen(data->dso_name, RTLD_NOW))) {
+		const char *dlerr = dlerror();
+		syslog(LOG_ERR, "dmeventd %s dlopen failed: %s", data->dso_name,
+		       dlerr);
+		data->msg->size =
+		    dm_asprintf(&(data->msg->data), "%s %s dlopen failed: %s",
+				data->id, data->dso_name, dlerr);
+		return NULL;
+	}
+
+	if (!(ret = _alloc_dso_data(data))) {
+		dlclose(dl);
+		return NULL;
+	}
+
+	if (!(lookup_symbols(dl, ret))) {
+		_free_dso_data(ret);
+		dlclose(dl);
+		return NULL;
+	}
+
+	/*
+	 * Keep handle to close the library once
+	 * we've got no references to it any more.
+	 */
+	ret->dso_handle = dl;
+	_lib_get(ret);
+
+	_lock_mutex();
+	LINK_DSO(ret);
+	_unlock_mutex();
+
+	return ret;
+}
+
+/* Return success on daemon active check. */
+static int _active(struct message_data *message_data)
+{
+	return 0;
+}
+
+/*
+ * Register for an event.
+ *
+ * Only one caller at a time here, because we use
+ * a FIFO and lock it against multiple accesses.
+ */
+static int _register_for_event(struct message_data *message_data)
+{
+	int ret = 0;
+	struct thread_status *thread, *thread_new = NULL;
+	struct dso_data *dso_data;
+
+	if (!(dso_data = _lookup_dso(message_data)) &&
+	    !(dso_data = _load_dso(message_data))) {
+		stack;
+#ifdef ELIBACC
+		ret = -ELIBACC;
+#else
+		ret = -ENODEV;
+#endif
+		goto out;
+	}
+
+	/* Preallocate thread status struct to avoid deadlock. */
+	if (!(thread_new = _alloc_thread_status(message_data, dso_data))) {
+		stack;
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	if (!_fill_device_data(thread_new)) {
+		stack;
+		ret = -ENODEV;
+		goto out;
+	}
+
+	_lock_mutex();
+
+	/* If creation of timeout thread fails (as it may), we fail
+	   here completely. The client is responsible for either
+	   retrying later or trying to register without timeout
+	   events. However, if timeout thread cannot be started, it
+	   usually means we are so starved on resources that we are
+	   almost as good as dead already... */
+	if (thread_new->events & DM_EVENT_TIMEOUT) {
+		ret = -_register_for_timeout(thread_new);
+		if (ret) {
+		    _unlock_mutex();
+		    goto out;
+		}
+	}
+
+	if (!(thread = _lookup_thread_status(message_data))) {
+		_unlock_mutex();
+
+		if (!(ret = _do_register_device(thread_new)))
+			goto out;
+
+		thread = thread_new;
+		thread_new = NULL;
+
+		/* Try to create the monitoring thread for this device. */
+		_lock_mutex();
+		if ((ret = -_create_thread(thread))) {
+			_unlock_mutex();
+			_do_unregister_device(thread);
+			_free_thread_status(thread);
+			goto out;
+		} else
+			LINK_THREAD(thread);
+	}
+
+	/* Or event # into events bitfield. */
+	thread->events |= message_data->events.field;
+
+	_unlock_mutex();
+
+      out:
+	/*
+	 * Deallocate thread status after releasing
+	 * the lock in case we haven't used it.
+	 */
+	if (thread_new)
+		_free_thread_status(thread_new);
+
+	return ret;
+}
+
+/*
+ * Unregister for an event.
+ *
+ * Only one caller at a time here as with register_for_event().
+ */
+static int _unregister_for_event(struct message_data *message_data)
+{
+	int ret = 0;
+	struct thread_status *thread;
+
+	/*
+	 * Clear event in bitfield and deactivate
+	 * monitoring thread in case bitfield is 0.
+	 */
+	_lock_mutex();
+
+	if (!(thread = _lookup_thread_status(message_data))) {
+		_unlock_mutex();
+		ret = -ENODEV;
+		goto out;
+	}
+
+	if (thread->status == DM_THREAD_DONE) {
+		/* the thread has terminated while we were not
+		   watching */
+		_unlock_mutex();
+		return 0;
+	}
+
+	thread->events &= ~message_data->events.field;
+
+	if (!(thread->events & DM_EVENT_TIMEOUT))
+		_unregister_for_timeout(thread);
+	/*
+	 * In case there's no events to monitor on this device ->
+	 * unlink and terminate its monitoring thread.
+	 */
+	if (!thread->events) {
+		UNLINK_THREAD(thread);
+		LINK(thread, &_thread_registry_unused);
+	}
+	_unlock_mutex();
+
+      out:
+	return ret;
+}
+
+/*
+ * Get registered device.
+ *
+ * Only one caller at a time here as with register_for_event().
+ */
+static int _registered_device(struct message_data *message_data,
+			     struct thread_status *thread)
+{
+	struct dm_event_daemon_message *msg = message_data->msg;
+
+	const char *fmt = "%s %s %s %u";
+	const char *id = message_data->id;
+	const char *dso = thread->dso_data->dso_name;
+	const char *dev = thread->device.uuid;
+	unsigned events = ((thread->status == DM_THREAD_RUNNING)
+			   && (thread->events)) ? thread->events : thread->
+	    events | DM_EVENT_REGISTRATION_PENDING;
+
+	if (msg->data)
+		dm_free(msg->data);
+
+	msg->size = dm_asprintf(&(msg->data), fmt, id, dso, dev, events);
+
+	_unlock_mutex();
+
+	return 0;
+}
+
+static int _want_registered_device(char *dso_name, char *device_uuid,
+				  struct thread_status *thread)
+{
+	/* If DSO names and device paths are equal. */
+	if (dso_name && device_uuid)
+		return !strcmp(dso_name, thread->dso_data->dso_name) &&
+		    !strcmp(device_uuid, thread->device.uuid) &&
+			(thread->status == DM_THREAD_RUNNING ||
+			 (thread->events & DM_EVENT_REGISTRATION_PENDING));
+
+	/* If DSO names are equal. */
+	if (dso_name)
+		return !strcmp(dso_name, thread->dso_data->dso_name) &&
+			(thread->status == DM_THREAD_RUNNING ||
+			 (thread->events & DM_EVENT_REGISTRATION_PENDING));
+
+	/* If device paths are equal. */
+	if (device_uuid)
+		return !strcmp(device_uuid, thread->device.uuid) &&
+			(thread->status == DM_THREAD_RUNNING ||
+			 (thread->events & DM_EVENT_REGISTRATION_PENDING));
+
+	return 1;
+}
+
+static int _get_registered_dev(struct message_data *message_data, int next)
+{
+	struct thread_status *thread, *hit = NULL;
+
+	_lock_mutex();
+
+	/* Iterate list of threads checking if we want a particular one. */
+	dm_list_iterate_items(thread, &_thread_registry)
+		if (_want_registered_device(message_data->dso_name,
+					    message_data->device_uuid,
+					    thread)) {
+			hit = thread;
+			break;
+		}
+
+	/*
+	 * If we got a registered device and want the next one ->
+	 * fetch next conforming element off the list.
+	 */
+	if (hit && !next) {
+		_unlock_mutex();
+		return _registered_device(message_data, hit);
+	}
+
+	if (!hit)
+		goto out;
+
+	thread = hit;
+
+	while (1) {
+		if (dm_list_end(&_thread_registry, &thread->list))
+			goto out;
+
+		thread = dm_list_item(thread->list.n, struct thread_status);
+		if (_want_registered_device(message_data->dso_name, NULL, thread)) {
+			hit = thread;
+			break;
+		}
+	}
+
+	_unlock_mutex();
+	return _registered_device(message_data, hit);
+
+      out:
+	_unlock_mutex();
+	
+	return -ENOENT;
+}
+
+static int _get_registered_device(struct message_data *message_data)
+{
+	return _get_registered_dev(message_data, 0);
+}
+
+static int _get_next_registered_device(struct message_data *message_data)
+{
+	return _get_registered_dev(message_data, 1);
+}
+
+static int _set_timeout(struct message_data *message_data)
+{
+	struct thread_status *thread;
+
+	_lock_mutex();
+	if ((thread = _lookup_thread_status(message_data)))
+		thread->timeout = message_data->timeout.secs;
+	_unlock_mutex();
+
+	return thread ? 0 : -ENODEV;
+}
+
+static int _get_timeout(struct message_data *message_data)
+{
+	struct thread_status *thread;
+	struct dm_event_daemon_message *msg = message_data->msg;
+
+	if (msg->data)
+		dm_free(msg->data);
+
+	_lock_mutex();
+	if ((thread = _lookup_thread_status(message_data))) {
+		msg->size =
+		    dm_asprintf(&(msg->data), "%s %" PRIu32, message_data->id,
+				thread->timeout);
+	} else {
+		msg->data = NULL;
+		msg->size = 0;
+	}
+	_unlock_mutex();
+
+	return thread ? 0 : -ENODEV;
+}
+
+/* Initialize a fifos structure with path names. */
+static void _init_fifos(struct dm_event_fifos *fifos)
+{
+	memset(fifos, 0, sizeof(*fifos));
+
+	fifos->client_path = DM_EVENT_FIFO_CLIENT;
+	fifos->server_path = DM_EVENT_FIFO_SERVER;
+}
+
+/* Open fifos used for client communication. */
+static int _open_fifos(struct dm_event_fifos *fifos)
+{
+	/* Create fifos */
+	if (((mkfifo(fifos->client_path, 0600) == -1) && errno != EEXIST) ||
+	    ((mkfifo(fifos->server_path, 0600) == -1) && errno != EEXIST)) {
+		syslog(LOG_ERR, "%s: Failed to create a fifo.\n", __func__);
+		stack;
+		return -errno;
+	}
+
+	struct stat st;
+
+	/* Warn about wrong permissions if applicable */
+	if ((!stat(fifos->client_path, &st)) && (st.st_mode & 0777) != 0600)
+		syslog(LOG_WARNING, "Fixing wrong permissions on %s",
+		       fifos->client_path);
+
+	if ((!stat(fifos->server_path, &st)) && (st.st_mode & 0777) != 0600)
+		syslog(LOG_WARNING, "Fixing wrong permissions on %s",
+		       fifos->server_path);
+
+	/* If they were already there, make sure permissions are ok. */
+	if (chmod(fifos->client_path, 0600)) {
+		syslog(LOG_ERR, "Unable to set correct file permissions on %s",
+		       fifos->client_path);
+		return -errno;
+	}
+
+	if (chmod(fifos->server_path, 0600)) {
+		syslog(LOG_ERR, "Unable to set correct file permissions on %s",
+		       fifos->server_path);
+		return -errno;
+	}
+
+	/* Need to open read+write or we will block or fail */
+	if ((fifos->server = open(fifos->server_path, O_RDWR)) < 0) {
+		stack;
+		return -errno;
+	}
+
+	/* Need to open read+write for select() to work. */
+	if ((fifos->client = open(fifos->client_path, O_RDWR)) < 0) {
+		stack;
+		close(fifos->server);
+		return -errno;
+	}
+
+	return 0;
+}
+
+/*
+ * Read message from client making sure that data is available
+ * and a complete message is read.  Must not block indefinitely.
+ */
+static int _client_read(struct dm_event_fifos *fifos,
+		       struct dm_event_daemon_message *msg)
+{
+	struct timeval t;
+	unsigned bytes = 0;
+	int ret = 0;
+	fd_set fds;
+	int header = 1;
+	size_t size = 2 * sizeof(uint32_t);	/* status + size */
+	char *buf = alloca(size);
+
+	msg->data = NULL;
+
+	errno = 0;
+	while (bytes < size && errno != EOF) {
+		/* Watch client read FIFO for input. */
+		FD_ZERO(&fds);
+		FD_SET(fifos->client, &fds);
+		t.tv_sec = 1;
+		t.tv_usec = 0;
+		ret = select(fifos->client + 1, &fds, NULL, NULL, &t);
+
+		if (!ret && !bytes)	/* nothing to read */
+			return 0;
+
+		if (!ret)	/* trying to finish read */
+			continue;
+
+		if (ret < 0)	/* error */
+			return 0;
+
+		ret = read(fifos->client, buf + bytes, size - bytes);
+		bytes += ret > 0 ? ret : 0;
+		if (bytes == 2 * sizeof(uint32_t) && header) {
+			msg->cmd = ntohl(*((uint32_t *) buf));
+			msg->size = ntohl(*((uint32_t *) buf + 1));
+			buf = msg->data = dm_malloc(msg->size);
+			size = msg->size;
+			bytes = 0;
+			header = 0;
+		}
+	}
+
+	if (bytes != size) {
+		if (msg->data)
+			dm_free(msg->data);
+		msg->data = NULL;
+		msg->size = 0;
+	}
+
+	return bytes == size;
+}
+
+/*
+ * Write a message to the client making sure that it is ready to write.
+ */
+static int _client_write(struct dm_event_fifos *fifos,
+			struct dm_event_daemon_message *msg)
+{
+	unsigned bytes = 0;
+	int ret = 0;
+	fd_set fds;
+
+	size_t size = 2 * sizeof(uint32_t) + msg->size;
+	char *buf = alloca(size);
+
+	*((uint32_t *)buf) = htonl(msg->cmd);
+	*((uint32_t *)buf + 1) = htonl(msg->size);
+	if (msg->data)
+		memcpy(buf + 2 * sizeof(uint32_t), msg->data, msg->size);
+
+	errno = 0;
+	while (bytes < size && errno != EIO) {
+		do {
+			/* Watch client write FIFO to be ready for output. */
+			FD_ZERO(&fds);
+			FD_SET(fifos->server, &fds);
+		} while (select(fifos->server + 1, NULL, &fds, NULL, NULL) !=
+			 1);
+
+		ret = write(fifos->server, buf + bytes, size - bytes);
+		bytes += ret > 0 ? ret : 0;
+	}
+
+	return bytes == size;
+}
+
+/*
+ * Handle a client request.
+ *
+ * We put the request handling functions into
+ * a list because of the growing number.
+ */
+static int _handle_request(struct dm_event_daemon_message *msg,
+			  struct message_data *message_data)
+{
+	static struct {
+		unsigned int cmd;
+		int (*f)(struct message_data *);
+	} requests[] = {
+		{ DM_EVENT_CMD_REGISTER_FOR_EVENT, _register_for_event},
+		{ DM_EVENT_CMD_UNREGISTER_FOR_EVENT, _unregister_for_event},
+		{ DM_EVENT_CMD_GET_REGISTERED_DEVICE, _get_registered_device},
+		{ DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE,
+			_get_next_registered_device},
+		{ DM_EVENT_CMD_SET_TIMEOUT, _set_timeout},
+		{ DM_EVENT_CMD_GET_TIMEOUT, _get_timeout},
+		{ DM_EVENT_CMD_ACTIVE, _active},
+	}, *req;
+
+	for (req = requests; req < requests + sizeof(requests); req++)
+		if (req->cmd == msg->cmd)
+			return req->f(message_data);
+
+	return -EINVAL;
+}
+
+/* Process a request passed from the communication thread. */
+static int _do_process_request(struct dm_event_daemon_message *msg)
+{
+	int ret;
+	char *answer;
+	static struct message_data message_data;
+
+	/* Parse the message. */
+	memset(&message_data, 0, sizeof(message_data));
+	message_data.msg = msg;
+	if (msg->cmd == DM_EVENT_CMD_HELLO)  {
+		ret = 0;
+		answer = msg->data;
+		if (answer) {
+			msg->size = dm_asprintf(&(msg->data), "%s HELLO", answer);
+			dm_free(answer);
+		} else {
+			msg->size = 0;
+			msg->data = NULL;
+		}
+	} else if (msg->cmd != DM_EVENT_CMD_ACTIVE && !_parse_message(&message_data)) {
+		stack;
+		ret = -EINVAL;
+	} else
+		ret = _handle_request(msg, &message_data);
+
+	msg->cmd = ret;
+	if (!msg->data)
+		msg->size = dm_asprintf(&(msg->data), "%s %s", message_data.id, strerror(-ret));
+
+	_free_message(&message_data);
+
+	return ret;
+}
+
+/* Only one caller at a time. */
+static void _process_request(struct dm_event_fifos *fifos)
+{
+	struct dm_event_daemon_message msg;
+
+	memset(&msg, 0, sizeof(msg));
+
+	/*
+	 * Read the request from the client (client_read, client_write
+	 * give true on success and false on failure).
+	 */
+	if (!_client_read(fifos, &msg))
+		return;
+
+	/* _do_process_request fills in msg (if memory allows for
+	   data, otherwise just cmd and size = 0) */
+	_do_process_request(&msg);
+
+	if (!_client_write(fifos, &msg))
+		stack;
+
+	if (msg.data)
+		dm_free(msg.data);
+}
+
+static void _cleanup_unused_threads(void)
+{
+	int ret;
+	struct dm_list *l;
+	struct thread_status *thread;
+
+	_lock_mutex();
+	while ((l = dm_list_first(&_thread_registry_unused))) {
+		thread = dm_list_item(l, struct thread_status);
+		if (thread->processing)
+			break;	/* cleanup on the next round */
+
+		if (thread->status == DM_THREAD_RUNNING) {
+			thread->status = DM_THREAD_SHUTDOWN;
+			break;
+		}
+
+		if (thread->status == DM_THREAD_SHUTDOWN) {
+			if (!thread->events) {
+				/* turn codes negative -- should we be returning this? */
+				ret = _terminate_thread(thread);
+
+				if (ret == ESRCH) {
+					thread->status = DM_THREAD_DONE;
+				} else if (ret) {
+					syslog(LOG_ERR,
+					       "Unable to terminate thread: %s\n",
+					       strerror(-ret));
+					stack;
+				}
+				break;
+			}
+
+			dm_list_del(l);
+			syslog(LOG_ERR,
+			       "thread can't be on unused list unless !thread->events");
+			thread->status = DM_THREAD_RUNNING;
+			LINK_THREAD(thread);
+
+			continue;
+		}
+
+		if (thread->status == DM_THREAD_DONE) {
+			dm_list_del(l);
+			pthread_join(thread->thread, NULL);
+			_lib_put(thread->dso_data);
+			_free_thread_status(thread);
+		}
+	}
+
+	_unlock_mutex();
+}
+
+static void _sig_alarm(int signum __attribute((unused)))
+{
+	pthread_testcancel();
+}
+
+/* Init thread signal handling. */
+static void _init_thread_signals(void)
+{
+	sigset_t my_sigset;
+	struct sigaction act;
+
+	memset(&act, 0, sizeof(act));
+	act.sa_handler = _sig_alarm;
+	sigaction(SIGALRM, &act, NULL);
+	sigfillset(&my_sigset);
+
+	/* These are used for exiting */
+	sigdelset(&my_sigset, SIGTERM);
+	sigdelset(&my_sigset, SIGINT);
+	sigdelset(&my_sigset, SIGHUP);
+	sigdelset(&my_sigset, SIGQUIT);
+
+	pthread_sigmask(SIG_BLOCK, &my_sigset, NULL);
+}
+
+/*
+ * exit_handler
+ * @sig
+ *
+ * Set the global variable which the process should
+ * be watching to determine when to exit.
+ */
+static void _exit_handler(int sig __attribute((unused)))
+{
+	/*
+	 * We exit when '_exit_now' is set.
+	 * That is, when a signal has been received.
+	 *
+	 * We can not simply set '_exit_now' unless all
+	 * threads are done processing.
+	 */
+	if (!_thread_registries_empty) {
+		syslog(LOG_ERR, "There are still devices being monitored.");
+		syslog(LOG_ERR, "Refusing to exit.");
+	} else
+		_exit_now = 1;
+
+}
+
+static int _lock_pidfile(void)
+{
+	int lf;
+	char pidfile[] = DMEVENTD_PIDFILE;
+
+	if ((lf = open(pidfile, O_CREAT | O_RDWR, 0644)) < 0)
+		exit(EXIT_OPEN_PID_FAILURE);
+
+	if (flock(lf, LOCK_EX | LOCK_NB) < 0)
+		exit(EXIT_LOCKFILE_INUSE);
+
+	if (!_storepid(lf))
+		exit(EXIT_FAILURE);
+
+	return 0;
+}
+
+#ifdef linux
+/*
+ * Protection against OOM killer if kernel supports it
+ */
+static int _set_oom_adj(int val)
+{
+	FILE *fp;
+
+	struct stat st;
+
+	if (stat(OOM_ADJ_FILE, &st) == -1) {
+		if (errno == ENOENT)
+			DEBUGLOG(OOM_ADJ_FILE " not found");
+		else
+			perror(OOM_ADJ_FILE ": stat failed");
+		return 1;
+	}
+
+	if (!(fp = fopen(OOM_ADJ_FILE, "w"))) {
+		perror(OOM_ADJ_FILE ": fopen failed");
+		return 0;
+	}
+
+	fprintf(fp, "%i", val);
+	if (dm_fclose(fp))
+		perror(OOM_ADJ_FILE ": fclose failed");
+
+	return 1;
+}
+#endif
+
+static void _daemonize(void)
+{
+	int child_status;
+	int fd;
+	pid_t pid;
+	struct rlimit rlim;
+	struct timeval tval;
+	sigset_t my_sigset;
+
+	sigemptyset(&my_sigset);
+	if (sigprocmask(SIG_SETMASK, &my_sigset, NULL) < 0) {
+		fprintf(stderr, "Unable to restore signals.\n");
+		exit(EXIT_FAILURE);
+	}
+	signal(SIGTERM, &_exit_handler);
+
+	switch (pid = fork()) {
+	case -1:
+		perror("fork failed:");
+		exit(EXIT_FAILURE);
+
+	case 0:		/* Child */
+		break;
+
+	default:
+		/* Wait for response from child */
+		while (!waitpid(pid, &child_status, WNOHANG) && !_exit_now) {
+			tval.tv_sec = 0;
+			tval.tv_usec = 250000;	/* .25 sec */
+			select(0, NULL, NULL, NULL, &tval);
+		}
+
+		if (_exit_now)	/* Child has signaled it is ok - we can exit now */
+			exit(EXIT_SUCCESS);
+
+		/* Problem with child.  Determine what it is by exit code */
+		switch (WEXITSTATUS(child_status)) {
+		case EXIT_LOCKFILE_INUSE:
+			fprintf(stderr, "Another dmeventd daemon is already running\n");
+			break;
+		case EXIT_DESC_CLOSE_FAILURE:
+		case EXIT_DESC_OPEN_FAILURE:
+		case EXIT_OPEN_PID_FAILURE:
+		case EXIT_FIFO_FAILURE:
+		case EXIT_CHDIR_FAILURE:
+		default:
+			fprintf(stderr, "Child exited with code %d\n", WEXITSTATUS(child_status));
+			break;
+		}
+
+		exit(WEXITSTATUS(child_status));
+	}
+
+	if (chdir("/"))
+		exit(EXIT_CHDIR_FAILURE);
+
+	if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
+		fd = 256;	/* just have to guess */
+	else
+		fd = rlim.rlim_cur;
+
+	for (--fd; fd >= 0; fd--)
+		close(fd);
+
+	if ((open("/dev/null", O_RDONLY) < 0) ||
+	    (open("/dev/null", O_WRONLY) < 0) ||
+	    (open("/dev/null", O_WRONLY) < 0))
+		exit(EXIT_DESC_OPEN_FAILURE);
+
+	setsid();
+}
+
+static void usage(char *prog, FILE *file)
+{
+	fprintf(file, "Usage:\n");
+	fprintf(file, "%s [Vhd]\n", prog);
+	fprintf(file, "\n");
+	fprintf(file, "   -V       Show version of dmeventd\n");
+	fprintf(file, "   -h       Show this help information\n");
+	fprintf(file, "   -d       Don't fork, run in the foreground\n");
+	fprintf(file, "\n");
+}
+
+int main(int argc, char *argv[])
+{
+	int ret;
+	signed char opt;
+	struct dm_event_fifos fifos;
+	//struct sys_log logdata = {DAEMON_NAME, LOG_DAEMON};
+
+	opterr = 0;
+	optind = 0;
+
+	while ((opt = getopt(argc, argv, "?hVd")) != EOF) {
+		switch (opt) {
+		case 'h':
+			usage(argv[0], stdout);
+			exit(0);
+		case '?':
+			usage(argv[0], stderr);
+			exit(0);
+		case 'd':
+			_debug++;
+			break;
+		case 'V':
+			printf("dmeventd version: %s\n", DM_LIB_VERSION);
+			exit(1);
+			break;
+		}
+	}
+
+	if (!_debug)
+		_daemonize();
+
+	openlog("dmeventd", LOG_PID, LOG_DAEMON);
+
+	_lock_pidfile();		/* exits if failure */
+
+	/* Set the rest of the signals to cause '_exit_now' to be set */
+	signal(SIGINT, &_exit_handler);
+	signal(SIGHUP, &_exit_handler);
+	signal(SIGQUIT, &_exit_handler);
+
+#ifdef linux
+	if (!_set_oom_adj(OOM_DISABLE) && !_set_oom_adj(OOM_ADJUST_MIN))
+		syslog(LOG_ERR, "Failed to set oom_adj to protect against OOM killer");
+#endif
+
+	_init_thread_signals();
+
+	//multilog_clear_logging();
+	//multilog_add_type(std_syslog, &logdata);
+	//multilog_init_verbose(std_syslog, _LOG_DEBUG);
+	//multilog_async(1);
+
+	_init_fifos(&fifos);
+
+	pthread_mutex_init(&_global_mutex, NULL);
+
+#ifdef MCL_CURRENT
+	if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1)
+		exit(EXIT_FAILURE);
+#endif
+
+	if ((ret = _open_fifos(&fifos)))
+		exit(EXIT_FIFO_FAILURE);
+
+	/* Signal parent, letting them know we are ready to go. */
+	kill(getppid(), SIGTERM);
+	syslog(LOG_NOTICE, "dmeventd ready for processing.");
+
+	while (!_exit_now) {
+		_process_request(&fifos);
+		_cleanup_unused_threads();
+		if (!dm_list_empty(&_thread_registry)
+		    || !dm_list_empty(&_thread_registry_unused))
+			_thread_registries_empty = 0;
+		else
+			_thread_registries_empty = 1;
+	}
+
+	_exit_dm_lib();
+
+#ifdef MCL_CURRENT
+	munlockall();
+#endif
+	pthread_mutex_destroy(&_global_mutex);
+
+	syslog(LOG_NOTICE, "dmeventd shutting down.");
+	closelog();
+
+	exit(EXIT_SUCCESS);
+}
Index: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/dmeventd.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/dmeventd.h
diff -N src/external/gpl2/lvm2tools/dist/daemons/dmeventd/dmeventd.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/dmeventd/dmeventd.h	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,68 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __DMEVENTD_DOT_H__
+#define __DMEVENTD_DOT_H__
+
+/* FIXME This stuff must be configurable. */
+
+#define	DM_EVENT_DAEMON		"/sbin/dmeventd"
+#define DM_EVENT_LOCKFILE	"/var/lock/dmeventd"
+#define	DM_EVENT_FIFO_CLIENT	"/var/run/dmeventd-client"
+#define	DM_EVENT_FIFO_SERVER	"/var/run/dmeventd-server"
+#define DM_EVENT_PIDFILE	"/var/run/dmeventd.pid"
+
+#define DM_EVENT_DEFAULT_TIMEOUT 10
+
+/* Commands for the daemon passed in the message below. */
+enum dm_event_command {
+	DM_EVENT_CMD_ACTIVE = 1,
+	DM_EVENT_CMD_REGISTER_FOR_EVENT,
+	DM_EVENT_CMD_UNREGISTER_FOR_EVENT,
+	DM_EVENT_CMD_GET_REGISTERED_DEVICE,
+	DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE,
+	DM_EVENT_CMD_SET_TIMEOUT,
+	DM_EVENT_CMD_GET_TIMEOUT,
+	DM_EVENT_CMD_HELLO,
+};
+
+/* Message passed between client and daemon. */
+struct dm_event_daemon_message {
+	uint32_t cmd;
+	uint32_t size;
+	char *data;
+};
+
+/* FIXME Is this meant to be exported?  I can't see where the
+   interface uses it. */
+/* Fifos for client/daemon communication. */
+struct dm_event_fifos {
+	int client;
+	int server;
+	const char *client_path;
+	const char *server_path;
+};
+
+/*      EXIT_SUCCESS             0 -- stdlib.h */
+/*      EXIT_FAILURE             1 -- stdlib.h */
+#define EXIT_LOCKFILE_INUSE      2
+#define EXIT_DESC_CLOSE_FAILURE  3
+#define EXIT_DESC_OPEN_FAILURE   4
+#define EXIT_OPEN_PID_FAILURE    5
+#define EXIT_FIFO_FAILURE        6
+#define EXIT_CHDIR_FAILURE       7
+
+#endif /* __DMEVENTD_DOT_H__ */
Index: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/libdevmapper-event.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/libdevmapper-event.c
diff -N src/external/gpl2/lvm2tools/dist/daemons/dmeventd/libdevmapper-event.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/dmeventd/libdevmapper-event.c	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,811 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "dmlib.h"
+#include "libdevmapper-event.h"
+//#include "libmultilog.h"
+#include "dmeventd.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/file.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <arpa/inet.h>		/* for htonl, ntohl */
+
+static int _sequence_nr = 0;
+
+struct dm_event_handler {
+	char *dso;
+
+	char *dev_name;
+
+	char *uuid;
+	int major;
+	int minor;
+	uint32_t timeout;
+
+	enum dm_event_mask mask;
+};
+
+static void _dm_event_handler_clear_dev_info(struct dm_event_handler *dmevh)
+{
+	if (dmevh->dev_name)
+		dm_free(dmevh->dev_name);
+	if (dmevh->uuid)
+		dm_free(dmevh->uuid);
+	dmevh->dev_name = dmevh->uuid = NULL;
+	dmevh->major = dmevh->minor = 0;
+}
+
+struct dm_event_handler *dm_event_handler_create(void)
+{
+	struct dm_event_handler *dmevh = NULL;
+
+	if (!(dmevh = dm_malloc(sizeof(*dmevh))))
+		return NULL;
+
+	dmevh->dso = dmevh->dev_name = dmevh->uuid = NULL;
+	dmevh->major = dmevh->minor = 0;
+	dmevh->mask = 0;
+	dmevh->timeout = 0;
+
+	return dmevh;
+}
+
+void dm_event_handler_destroy(struct dm_event_handler *dmevh)
+{
+	_dm_event_handler_clear_dev_info(dmevh);
+	if (dmevh->dso)
+		dm_free(dmevh->dso);
+	dm_free(dmevh);
+}
+
+int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path)
+{
+	if (!path) /* noop */
+		return 0;
+	if (dmevh->dso)
+		dm_free(dmevh->dso);
+
+	dmevh->dso = dm_strdup(path);
+	if (!dmevh->dso)
+		return -ENOMEM;
+
+	return 0;
+}
+
+int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *dev_name)
+{
+	if (!dev_name)
+		return 0;
+
+	_dm_event_handler_clear_dev_info(dmevh);
+
+	dmevh->dev_name = dm_strdup(dev_name);
+	if (!dmevh->dev_name)
+		return -ENOMEM;
+	return 0;
+}
+
+int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid)
+{
+	if (!uuid)
+		return 0;
+
+	_dm_event_handler_clear_dev_info(dmevh);
+
+	dmevh->uuid = dm_strdup(uuid);
+	if (!dmevh->dev_name)
+		return -ENOMEM;
+	return 0;
+}
+
+void dm_event_handler_set_major(struct dm_event_handler *dmevh, int major)
+{
+	int minor = dmevh->minor;
+
+	_dm_event_handler_clear_dev_info(dmevh);
+
+	dmevh->major = major;
+	dmevh->minor = minor;
+}
+
+void dm_event_handler_set_minor(struct dm_event_handler *dmevh, int minor)
+{
+	int major = dmevh->major;
+
+	_dm_event_handler_clear_dev_info(dmevh);
+
+	dmevh->major = major;
+	dmevh->minor = minor;
+}
+
+void dm_event_handler_set_event_mask(struct dm_event_handler *dmevh,
+				     enum dm_event_mask evmask)
+{
+	dmevh->mask = evmask;
+}
+
+void dm_event_handler_set_timeout(struct dm_event_handler *dmevh, int timeout)
+{
+	dmevh->timeout = timeout;
+}
+
+const char *dm_event_handler_get_dso(const struct dm_event_handler *dmevh)
+{
+	return dmevh->dso;
+}
+
+const char *dm_event_handler_get_dev_name(const struct dm_event_handler *dmevh)
+{
+	return dmevh->dev_name;
+}
+
+const char *dm_event_handler_get_uuid(const struct dm_event_handler *dmevh)
+{
+	return dmevh->uuid;
+}
+
+int dm_event_handler_get_major(const struct dm_event_handler *dmevh)
+{
+	return dmevh->major;
+}
+
+int dm_event_handler_get_minor(const struct dm_event_handler *dmevh)
+{
+	return dmevh->minor;
+}
+
+int dm_event_handler_get_timeout(const struct dm_event_handler *dmevh)
+{
+	return dmevh->timeout;
+}
+
+enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler *dmevh)
+{
+	return dmevh->mask;
+}
+
+static int _check_message_id(struct dm_event_daemon_message *msg)
+{
+	int pid, seq_nr;
+
+	if ((sscanf(msg->data, "%d:%d", &pid, &seq_nr) != 2) ||
+	    (pid != getpid()) || (seq_nr != _sequence_nr)) {
+		log_error("Ignoring out-of-sequence reply from dmeventd. "
+			  "Expected %d:%d but received %s", getpid(),
+			  _sequence_nr, msg->data);
+		return 0;
+	}
+
+	return 1;
+}
+
+/*
+ * daemon_read
+ * @fifos
+ * @msg
+ *
+ * Read message from daemon.
+ *
+ * Returns: 0 on failure, 1 on success
+ */
+static int _daemon_read(struct dm_event_fifos *fifos,
+			struct dm_event_daemon_message *msg)
+{
+	unsigned bytes = 0;
+	int ret, i;
+	fd_set fds;
+	struct timeval tval = { 0, 0 };
+	size_t size = 2 * sizeof(uint32_t);	/* status + size */
+	char *buf = alloca(size);
+	int header = 1;
+
+	while (bytes < size) {
+		for (i = 0, ret = 0; (i < 20) && (ret < 1); i++) {
+			/* Watch daemon read FIFO for input. */
+			FD_ZERO(&fds);
+			FD_SET(fifos->server, &fds);
+			tval.tv_sec = 1;
+			ret = select(fifos->server + 1, &fds, NULL, NULL,
+				     &tval);
+			if (ret < 0 && errno != EINTR) {
+				log_error("Unable to read from event server");
+				return 0;
+			}
+		}
+		if (ret < 1) {
+			log_error("Unable to read from event server.");
+			return 0;
+		}
+
+		ret = read(fifos->server, buf + bytes, size);
+		if (ret < 0) {
+			if ((errno == EINTR) || (errno == EAGAIN))
+				continue;
+			else {
+				log_error("Unable to read from event server.");
+				return 0;
+			}
+		}
+
+		bytes += ret;
+		if (bytes == 2 * sizeof(uint32_t) && header) {
+			msg->cmd = ntohl(*((uint32_t *)buf));
+			msg->size = ntohl(*((uint32_t *)buf + 1));
+			buf = msg->data = dm_malloc(msg->size);
+			size = msg->size;
+			bytes = 0;
+			header = 0;
+		}
+	}
+
+	if (bytes != size) {
+		if (msg->data)
+			dm_free(msg->data);
+		msg->data = NULL;
+	}
+
+	return bytes == size;
+}
+
+/* Write message to daemon. */
+static int _daemon_write(struct dm_event_fifos *fifos,
+			 struct dm_event_daemon_message *msg)
+{
+	unsigned bytes = 0;
+	int ret = 0;
+	fd_set fds;
+
+	size_t size = 2 * sizeof(uint32_t) + msg->size;
+	char *buf = alloca(size);
+	char drainbuf[128];
+	struct timeval tval = { 0, 0 };
+
+	*((uint32_t *)buf) = htonl(msg->cmd);
+	*((uint32_t *)buf + 1) = htonl(msg->size);
+	memcpy(buf + 2 * sizeof(uint32_t), msg->data, msg->size);
+
+	/* drain the answer fifo */
+	while (1) {
+		FD_ZERO(&fds);
+		FD_SET(fifos->server, &fds);
+		tval.tv_usec = 100;
+		ret = select(fifos->server + 1, &fds, NULL, NULL, &tval);
+		if ((ret < 0) && (errno != EINTR)) {
+			log_error("Unable to talk to event daemon");
+			return 0;
+		}
+		if (ret == 0)
+			break;
+		read(fifos->server, drainbuf, 127);
+	}
+
+	while (bytes < size) {
+		do {
+			/* Watch daemon write FIFO to be ready for output. */
+			FD_ZERO(&fds);
+			FD_SET(fifos->client, &fds);
+			ret = select(fifos->client + 1, NULL, &fds, NULL, NULL);
+			if ((ret < 0) && (errno != EINTR)) {
+				log_error("Unable to talk to event daemon");
+				return 0;
+			}
+		} while (ret < 1);
+
+		ret = write(fifos->client, ((char *) buf) + bytes,
+			    size - bytes);
+		if (ret < 0) {
+			if ((errno == EINTR) || (errno == EAGAIN))
+				continue;
+			else {
+				log_error("Unable to talk to event daemon");
+				return 0;
+			}
+		}
+
+		bytes += ret;
+	}
+
+	return bytes == size;
+}
+
+static int _daemon_talk(struct dm_event_fifos *fifos,
+			struct dm_event_daemon_message *msg, int cmd,
+			const char *dso_name, const char *dev_name,
+			enum dm_event_mask evmask, uint32_t timeout)
+{
+	const char *dso = dso_name ? dso_name : "";
+	const char *dev = dev_name ? dev_name : "";
+	const char *fmt = "%d:%d %s %s %u %" PRIu32;
+	int msg_size;
+	memset(msg, 0, sizeof(*msg));
+
+	/*
+	 * Set command and pack the arguments
+	 * into ASCII message string.
+	 */
+	msg->cmd = cmd;
+	if (cmd == DM_EVENT_CMD_HELLO)
+		fmt = "%d:%d HELLO";
+	if ((msg_size = dm_asprintf(&(msg->data), fmt, getpid(), _sequence_nr,
+				    dso, dev, evmask, timeout)) < 0) {
+		log_error("_daemon_talk: message allocation failed");
+		return -ENOMEM;
+	}
+	msg->size = msg_size;
+
+	/*
+	 * Write command and message to and
+	 * read status return code from daemon.
+	 */
+	if (!_daemon_write(fifos, msg)) {
+		stack;
+		dm_free(msg->data);
+		msg->data = 0;
+		return -EIO;
+	}
+
+	do {
+
+		if (msg->data)
+			dm_free(msg->data);
+		msg->data = 0;
+
+		if (!_daemon_read(fifos, msg)) {
+			stack;
+			return -EIO;
+		}
+	} while (!_check_message_id(msg));
+
+	_sequence_nr++;
+
+	return (int32_t) msg->cmd;
+}
+
+/*
+ * start_daemon
+ *
+ * This function forks off a process (dmeventd) that will handle
+ * the events.  I am currently test opening one of the fifos to
+ * ensure that the daemon is running and listening...  I thought
+ * this would be less expensive than fork/exec'ing every time.
+ * Perhaps there is an even quicker/better way (no, checking the
+ * lock file is _not_ a better way).
+ *
+ * Returns: 1 on success, 0 otherwise
+ */
+static int _start_daemon(struct dm_event_fifos *fifos)
+{
+	int pid, ret = 0;
+	int status;
+	struct stat statbuf;
+
+	if (stat(fifos->client_path, &statbuf))
+		goto start_server;
+
+	if (!S_ISFIFO(statbuf.st_mode)) {
+		log_error("%s is not a fifo.", fifos->client_path);
+		return 0;
+	}
+
+	/* Anyone listening?  If not, errno will be ENXIO */
+	fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK);
+	if (fifos->client >= 0) {
+		/* server is running and listening */
+
+		close(fifos->client);
+		return 1;
+	} else if (errno != ENXIO) {
+		/* problem */
+
+		log_error("%s: Can't open client fifo %s: %s",
+			  __func__, fifos->client_path, strerror(errno));
+		stack;
+		return 0;
+	}
+
+      start_server:
+	/* server is not running */
+	pid = fork();
+
+	if (pid < 0)
+		log_error("Unable to fork.");
+
+	else if (!pid) {
+		execvp(DMEVENTD_PATH, NULL);
+		exit(EXIT_FAILURE);
+	} else {
+		if (waitpid(pid, &status, 0) < 0)
+			log_error("Unable to start dmeventd: %s",
+				  strerror(errno));
+		else if (WEXITSTATUS(status))
+			log_error("Unable to start dmeventd.");
+		else
+			ret = 1;
+	}
+
+	return ret;
+}
+
+/* Initialize client. */
+static int _init_client(struct dm_event_fifos *fifos)
+{
+	/* FIXME? Is fifo the most suitable method? Why not share
+	   comms/daemon code with something else e.g. multipath? */
+
+	/* init fifos */
+	memset(fifos, 0, sizeof(*fifos));
+	fifos->client_path = DM_EVENT_FIFO_CLIENT;
+	fifos->server_path = DM_EVENT_FIFO_SERVER;
+
+	if (!_start_daemon(fifos)) {
+		stack;
+		return 0;
+	}
+
+	/* Open the fifo used to read from the daemon. */
+	if ((fifos->server = open(fifos->server_path, O_RDWR)) < 0) {
+		log_error("%s: open server fifo %s",
+			  __func__, fifos->server_path);
+		stack;
+		return 0;
+	}
+
+	/* Lock out anyone else trying to do communication with the daemon. */
+	if (flock(fifos->server, LOCK_EX) < 0) {
+		log_error("%s: flock %s", __func__, fifos->server_path);
+		close(fifos->server);
+		return 0;
+	}
+
+/*	if ((fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK)) < 0) {*/
+	if ((fifos->client = open(fifos->client_path, O_RDWR | O_NONBLOCK)) < 0) {
+		log_error("%s: Can't open client fifo %s: %s",
+			  __func__, fifos->client_path, strerror(errno));
+		close(fifos->server);
+		stack;
+		return 0;
+	}
+
+	return 1;
+}
+
+static void _dtr_client(struct dm_event_fifos *fifos)
+{
+	if (flock(fifos->server, LOCK_UN))
+		log_error("flock unlock %s", fifos->server_path);
+
+	close(fifos->client);
+	close(fifos->server);
+}
+
+/* Get uuid of a device */
+static struct dm_task *_get_device_info(const struct dm_event_handler *dmevh)
+{
+	struct dm_task *dmt;
+	struct dm_info info;
+
+	if (!(dmt = dm_task_create(DM_DEVICE_INFO))) {
+		log_error("_get_device_info: dm_task creation for info failed");
+		return NULL;
+	}
+
+	if (dmevh->uuid)
+		dm_task_set_uuid(dmt, dmevh->uuid);
+	else if (dmevh->dev_name)
+		dm_task_set_name(dmt, dmevh->dev_name);
+	else if (dmevh->major && dmevh->minor) {
+		dm_task_set_major(dmt, dmevh->major);
+		dm_task_set_minor(dmt, dmevh->minor);
+        }
+
+	/* FIXME Add name or uuid or devno to messages */
+	if (!dm_task_run(dmt)) {
+		log_error("_get_device_info: dm_task_run() failed");
+		goto failed;
+	}
+
+	if (!dm_task_get_info(dmt, &info)) {
+		log_error("_get_device_info: failed to get info for device");
+		goto failed;
+	}
+
+	if (!info.exists) {
+		log_error("_get_device_info: device not found");
+		goto failed;
+	}
+
+	return dmt;
+
+failed:
+	dm_task_destroy(dmt);
+	return NULL;
+}
+
+/* Handle the event (de)registration call and return negative error codes. */
+static int _do_event(int cmd, struct dm_event_daemon_message *msg,
+		     const char *dso_name, const char *dev_name,
+		     enum dm_event_mask evmask, uint32_t timeout)
+{
+	int ret;
+	struct dm_event_fifos fifos;
+
+	if (!_init_client(&fifos)) {
+		stack;
+		return -ESRCH;
+	}
+
+	ret = _daemon_talk(&fifos, msg, DM_EVENT_CMD_HELLO, 0, 0, 0, 0);
+
+	if (msg->data)
+		dm_free(msg->data);
+	msg->data = 0;
+
+	if (!ret)
+		ret = _daemon_talk(&fifos, msg, cmd, dso_name, dev_name, evmask, timeout);
+
+	/* what is the opposite of init? */
+	_dtr_client(&fifos);
+
+	return ret;
+}
+
+/* External library interface. */
+int dm_event_register_handler(const struct dm_event_handler *dmevh)
+{
+	int ret = 1, err;
+	const char *uuid;
+	struct dm_task *dmt;
+	struct dm_event_daemon_message msg = { 0, 0, NULL };
+
+	if (!(dmt = _get_device_info(dmevh))) {
+		stack;
+		return 0;
+	}
+
+	uuid = dm_task_get_uuid(dmt);
+
+	if ((err = _do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, &msg,
+			     dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
+		log_error("%s: event registration failed: %s",
+			  dm_task_get_name(dmt),
+			  msg.data ? msg.data : strerror(-err));
+		ret = 0;
+	}
+
+	if (msg.data)
+		dm_free(msg.data);
+
+	dm_task_destroy(dmt);
+
+	return ret;
+}
+
+int dm_event_unregister_handler(const struct dm_event_handler *dmevh)
+{
+	int ret = 1, err;
+	const char *uuid;
+	struct dm_task *dmt;
+	struct dm_event_daemon_message msg = { 0, 0, NULL };
+
+	if (!(dmt = _get_device_info(dmevh))) {
+		stack;
+		return 0;
+	}
+
+	uuid = dm_task_get_uuid(dmt);
+
+	if ((err = _do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, &msg,
+			    dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
+		log_error("%s: event deregistration failed: %s",
+			  dm_task_get_name(dmt),
+			  msg.data ? msg.data : strerror(-err));
+		ret = 0;
+	}
+
+	if (msg.data)
+		dm_free(msg.data);
+
+	dm_task_destroy(dmt);
+
+	return ret;
+}
+
+/* Fetch a string off src and duplicate it into *dest. */
+/* FIXME: move to separate module to share with the daemon. */
+static char *_fetch_string(char **src, const int delimiter)
+{
+	char *p, *ret;
+
+	if ((p = strchr(*src, delimiter)))
+		*p = 0;
+
+	if ((ret = dm_strdup(*src)))
+		*src += strlen(ret) + 1;
+
+	if (p)
+		*p = delimiter;
+
+	return ret;
+}
+
+/* Parse a device message from the daemon. */
+static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name,
+			 char **uuid, enum dm_event_mask *evmask)
+{
+	char *id = NULL;
+	char *p = msg->data;
+
+	if ((id = _fetch_string(&p, ' ')) &&
+	    (*dso_name = _fetch_string(&p, ' ')) &&
+	    (*uuid = _fetch_string(&p, ' '))) {
+		*evmask = atoi(p);
+
+		dm_free(id);
+		return 0;
+	}
+
+	if (id)
+		dm_free(id);
+	return -ENOMEM;
+}
+
+/*
+ * Returns 0 if handler found; error (-ENOMEM, -ENOENT) otherwise.
+ */
+int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
+{
+	int ret = 0;
+	const char *uuid = NULL;
+	char *reply_dso = NULL, *reply_uuid = NULL;
+	enum dm_event_mask reply_mask = 0;
+	struct dm_task *dmt = NULL;
+	struct dm_event_daemon_message msg = { 0, 0, NULL };
+
+	if (!(dmt = _get_device_info(dmevh))) {
+		stack;
+		return 0;
+	}
+
+	uuid = dm_task_get_uuid(dmt);
+
+	if (!(ret = _do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE :
+			     DM_EVENT_CMD_GET_REGISTERED_DEVICE,
+			      &msg, dmevh->dso, uuid, dmevh->mask, 0))) {
+		/* FIXME this will probably horribly break if we get
+		   ill-formatted reply */
+		ret = _parse_message(&msg, &reply_dso, &reply_uuid, &reply_mask);
+	} else {
+		ret = -ENOENT;
+		goto fail;
+	}
+
+	dm_task_destroy(dmt);
+	dmt = NULL;
+
+	if (msg.data) {
+		dm_free(msg.data);
+		msg.data = NULL;
+	}
+
+	_dm_event_handler_clear_dev_info(dmevh);
+	dmevh->uuid = dm_strdup(reply_uuid);
+	if (!dmevh->uuid) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	if (!(dmt = _get_device_info(dmevh))) {
+		ret = -ENXIO; /* dmeventd probably gave us bogus uuid back */
+		goto fail;
+	}
+
+	dm_event_handler_set_dso(dmevh, reply_dso);
+	dm_event_handler_set_event_mask(dmevh, reply_mask);
+
+	if (reply_dso) {
+		dm_free(reply_dso);
+		reply_dso = NULL;
+	}
+
+	if (reply_uuid) {
+		dm_free(reply_uuid);
+		reply_uuid = NULL;
+	}
+
+	dmevh->dev_name = dm_strdup(dm_task_get_name(dmt));
+	if (!dmevh->dev_name) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	struct dm_info info;
+	if (!dm_task_get_info(dmt, &info)) {
+		ret = -1;
+		goto fail;
+	}
+
+	dmevh->major = info.major;
+	dmevh->minor = info.minor;
+
+	dm_task_destroy(dmt);
+
+	return ret;
+
+ fail:
+	if (msg.data)
+		dm_free(msg.data);
+	if (reply_dso)
+		dm_free(reply_dso);
+	if (reply_uuid)
+		dm_free(reply_uuid);
+	_dm_event_handler_clear_dev_info(dmevh);
+	if (dmt)
+		dm_task_destroy(dmt);
+	return ret;
+}
+
+#if 0				/* left out for now */
+
+static char *_skip_string(char *src, const int delimiter)
+{
+	src = srtchr(src, delimiter);
+	if (src && *(src + 1))
+		return src + 1;
+	return NULL;
+}
+
+int dm_event_set_timeout(const char *device_path, uint32_t timeout)
+{
+	struct dm_event_daemon_message msg = { 0, 0, NULL };
+
+	if (!device_exists(device_path))
+		return -ENODEV;
+
+	return _do_event(DM_EVENT_CMD_SET_TIMEOUT, &msg,
+			 NULL, device_path, 0, timeout);
+}
+
+int dm_event_get_timeout(const char *device_path, uint32_t *timeout)
+{
+	int ret;
+	struct dm_event_daemon_message msg = { 0, 0, NULL };
+
+	if (!device_exists(device_path))
+		return -ENODEV;
+	if (!(ret = _do_event(DM_EVENT_CMD_GET_TIMEOUT, &msg, NULL, device_path,
+			     0, 0))) {
+		char *p = _skip_string(msg.data, ' ');
+		if (!p) {
+			log_error("malformed reply from dmeventd '%s'\n",
+				  msg.data);
+			return -EIO;
+		}
+		*timeout = atoi(p);
+	}
+	if (msg.data)
+		dm_free(msg.data);
+	return ret;
+}
+#endif
Index: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/libdevmapper-event.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/libdevmapper-event.h
diff -N src/external/gpl2/lvm2tools/dist/daemons/dmeventd/libdevmapper-event.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/dmeventd/libdevmapper-event.h	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,108 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Note that this file is released only as part of a technology preview
+ * and its contents may change in future updates in ways that do not
+ * preserve compatibility.
+ */
+
+#ifndef LIB_DMEVENT_H
+#define LIB_DMEVENT_H
+
+#include <stdint.h>
+
+/*
+ * Event library interface.
+ */
+
+enum dm_event_mask {
+	DM_EVENT_SETTINGS_MASK  = 0x0000FF,
+	DM_EVENT_SINGLE		= 0x000001, /* Report multiple errors just once. */
+	DM_EVENT_MULTI		= 0x000002, /* Report all of them. */
+
+	DM_EVENT_ERROR_MASK     = 0x00FF00,
+	DM_EVENT_SECTOR_ERROR	= 0x000100, /* Failure on a particular sector. */
+	DM_EVENT_DEVICE_ERROR	= 0x000200, /* Device failure. */
+	DM_EVENT_PATH_ERROR	= 0x000400, /* Failure on an io path. */
+	DM_EVENT_ADAPTOR_ERROR	= 0x000800, /* Failure of a host adaptor. */
+
+	DM_EVENT_STATUS_MASK    = 0xFF0000,
+	DM_EVENT_SYNC_STATUS	= 0x010000, /* Mirror synchronization completed/failed. */
+	DM_EVENT_TIMEOUT	= 0x020000, /* Timeout has occured */
+
+	DM_EVENT_REGISTRATION_PENDING = 0x1000000, /* Monitor thread is setting-up/shutting-down */
+};
+
+#define DM_EVENT_ALL_ERRORS DM_EVENT_ERROR_MASK
+
+struct dm_event_handler;
+
+struct dm_event_handler *dm_event_handler_create(void);
+void dm_event_handler_destroy(struct dm_event_handler *dmevh);
+
+/*
+ * Path of shared library to handle events.
+ *
+ * All of dso, device_name and uuid strings are duplicated, you do not
+ * need to keep the pointers valid after the call succeeds. Thes may
+ * return -ENOMEM though.
+ */
+int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path);
+
+/*
+ * Identify the device to monitor by exactly one of device_name, uuid or
+ * device number. String arguments are duplicated, see above.
+ */
+int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *device_name);
+
+int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid);
+
+void dm_event_handler_set_major(struct dm_event_handler *dmevh, int major);
+void dm_event_handler_set_minor(struct dm_event_handler *dmevh, int minor);
+void dm_event_handler_set_timeout(struct dm_event_handler *dmevh, int timeout);
+
+/*
+ * Specify mask for events to monitor.
+ */
+void dm_event_handler_set_event_mask(struct dm_event_handler *dmevh,
+				     enum dm_event_mask evmask);
+
+const char *dm_event_handler_get_dso(const struct dm_event_handler *dmevh);
+const char *dm_event_handler_get_dev_name(const struct dm_event_handler *dmevh);
+const char *dm_event_handler_get_uuid(const struct dm_event_handler *dmevh);
+int dm_event_handler_get_major(const struct dm_event_handler *dmevh);
+int dm_event_handler_get_minor(const struct dm_event_handler *dmevh);
+int dm_event_handler_get_timeout(const struct dm_event_handler *dmevh);
+enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler *dmevh);
+
+/* FIXME Review interface (what about this next thing?) */
+int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next);
+
+/*
+ * Initiate monitoring using dmeventd.
+ */
+int dm_event_register_handler(const struct dm_event_handler *dmevh);
+int dm_event_unregister_handler(const struct dm_event_handler *dmevh);
+
+/* Prototypes for DSO interface, see dmeventd.c, struct dso_data for
+   detailed descriptions. */
+void process_event(struct dm_task *dmt, enum dm_event_mask evmask, void **user);
+int register_device(const char *device_name, const char *uuid, int major, int minor, void **user);
+int unregister_device(const char *device_name, const char *uuid, int major,
+		      int minor, void **user);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/libdevmapper-event.pc.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/libdevmapper-event.pc.in
diff -N src/external/gpl2/lvm2tools/dist/daemons/dmeventd/libdevmapper-event.pc.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/dmeventd/libdevmapper-event.pc.in	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: devmapper-event
+Description: device-mapper event library
+Version: @DM_LIB_VERSION@
+Requires: devmapper
+Cflags: -I${includedir}
+Libs: -L${libdir} -ldevmapper-event
+Libs.private: -lpthread -ldl
Index: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/Makefile.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/Makefile.in
diff -N src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/Makefile.in	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+SUBDIRS += mirror snapshot
+
+include $(top_srcdir)/make.tmpl
+
Index: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/mirror/.exported_symbols
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/mirror/.exported_symbols
diff -N src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/mirror/.exported_symbols
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/mirror/.exported_symbols	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,3 @@
+process_event
+register_device
+unregister_device
Index: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/mirror/Makefile.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/mirror/Makefile.in
diff -N src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/mirror/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/mirror/Makefile.in	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,37 @@
+#
+# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+# Copyright (C) 2004-2005, 2008 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+INCLUDES += -I${top_srcdir}/tools
+CLDFLAGS += -L${top_srcdir}/tools -ldevmapper @LVM2CMD_LIB@
+
+SOURCES = dmeventd_mirror.c
+
+ifeq ("@LIB_SUFFIX@","dylib")
+  LIB_SHARED = libdevmapper-event-lvm2mirror.dylib
+else
+  LIB_SHARED = libdevmapper-event-lvm2mirror.so
+endif
+
+LIB_VERSION = $(LIB_VERSION_LVM)
+
+include $(top_srcdir)/make.tmpl
+
+install: libdevmapper-event-lvm2mirror.$(LIB_SUFFIX)
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
+		$(libdir)/$<.$(LIB_VERSION)
+	$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<
Index: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c
diff -N src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,291 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lvm2cmd.h"
+
+#include <libdevmapper.h>
+#include <libdevmapper-event.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <unistd.h>
+
+#include <syslog.h> /* FIXME Replace syslog with multilog */
+/* FIXME Missing openlog? */
+
+#define ME_IGNORE    0
+#define ME_INSYNC    1
+#define ME_FAILURE   2
+
+/*
+ * register_device() is called first and performs initialisation.
+ * Only one device may be registered or unregistered at a time.
+ */
+static pthread_mutex_t _register_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/*
+ * Number of active registrations.
+ */
+static int _register_count = 0;
+
+static struct dm_pool *_mem_pool = NULL;
+static void *_lvm_handle = NULL;
+
+/*
+ * Currently only one event can be processed at a time.
+ */
+static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static int _get_mirror_event(char *params)
+{
+	int i, r = ME_INSYNC;
+	char **args = NULL;
+	char *dev_status_str;
+	char *log_status_str;
+	char *sync_str;
+	char *p = NULL;
+	int log_argc, num_devs;
+
+	/*
+	 * dm core parms:	     0 409600 mirror
+	 * Mirror core parms:	     2 253:4 253:5 400/400
+	 * New-style failure params: 1 AA
+	 * New-style log params:     3 cluster 253:3 A
+	 *			 or  3 disk 253:3 A
+	 *			 or  1 core
+	 */
+
+	/* number of devices */
+	if (!dm_split_words(params, 1, 0, &p))
+		goto out_parse;
+
+	if (!(num_devs = atoi(p)))
+		goto out_parse;
+	p += strlen(p) + 1;
+
+	/* devices names + "400/400" + "1 AA" + 1 or 3 log parms + NULL */
+	args = dm_malloc((num_devs + 7) * sizeof(char *));
+	if (!args || dm_split_words(p, num_devs + 7, 0, args) < num_devs + 5)
+		goto out_parse;
+
+	dev_status_str = args[2 + num_devs];
+	log_argc = atoi(args[3 + num_devs]);
+	log_status_str = args[3 + num_devs + log_argc];
+	sync_str = args[num_devs];
+
+	/* Check for bad mirror devices */
+	for (i = 0; i < num_devs; i++)
+		if (dev_status_str[i] == 'D') {
+			syslog(LOG_ERR, "Mirror device, %s, has failed.\n", args[i]);
+			r = ME_FAILURE;
+		}
+
+	/* Check for bad disk log device */
+	if (log_argc > 1 && log_status_str[0] == 'D') {
+		syslog(LOG_ERR, "Log device, %s, has failed.\n",
+		       args[2 + num_devs + log_argc]);
+		r = ME_FAILURE;
+	}
+
+	if (r == ME_FAILURE)
+		goto out;
+
+	p = strstr(sync_str, "/");
+	if (p) {
+		p[0] = '\0';
+		if (strcmp(sync_str, p+1))
+			r = ME_IGNORE;
+		p[0] = '/';
+	} else
+		goto out_parse;
+
+out:
+	if (args)
+		dm_free(args);
+	return r;
+	
+out_parse:
+	if (args)
+		dm_free(args);
+	syslog(LOG_ERR, "Unable to parse mirror status string.");
+	return ME_IGNORE;
+}
+
+static void _temporary_log_fn(int level, const char *file __attribute((unused)),
+			      int line __attribute((unused)),
+			      const char *format)
+{
+	if (!strncmp(format, "WARNING: ", 9) && (level < 5))
+		syslog(LOG_CRIT, "%s", format);
+	else
+		syslog(LOG_DEBUG, "%s", format);
+}
+
+static int _remove_failed_devices(const char *device)
+{
+	int r;
+#define CMD_SIZE 256	/* FIXME Use system restriction */
+	char cmd_str[CMD_SIZE];
+	char *vg = NULL, *lv = NULL, *layer = NULL;
+
+	if (strlen(device) > 200)  /* FIXME Use real restriction */
+		return -ENAMETOOLONG;	/* FIXME These return code distinctions are not used so remove them! */
+
+	if (!dm_split_lvm_name(_mem_pool, device, &vg, &lv, &layer)) {
+		syslog(LOG_ERR, "Unable to determine VG name from %s",
+		       device);
+		return -ENOMEM;	/* FIXME Replace with generic error return - reason for failure has already got logged */
+	}
+
+	/* FIXME Is any sanity-checking required on %s? */
+	if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "vgreduce --config devices{ignore_suspended_devices=1} --removemissing --force %s", vg)) {
+		/* this error should be caught above, but doesn't hurt to check again */
+		syslog(LOG_ERR, "Unable to form LVM command: Device name too long");
+		dm_pool_empty(_mem_pool);  /* FIXME: not safe with multiple threads */
+		return -ENAMETOOLONG; /* FIXME Replace with generic error return - reason for failure has already got logged */
+	}
+
+	r = lvm2_run(_lvm_handle, cmd_str);
+
+	dm_pool_empty(_mem_pool);  /* FIXME: not safe with multiple threads */
+	return (r == 1) ? 0 : -1;
+}
+
+void process_event(struct dm_task *dmt,
+		   enum dm_event_mask event __attribute((unused)),
+		   void **unused __attribute((unused)))
+{
+	void *next = NULL;
+	uint64_t start, length;
+	char *target_type = NULL;
+	char *params;
+	const char *device = dm_task_get_name(dmt);
+
+	if (pthread_mutex_trylock(&_event_mutex)) {
+		syslog(LOG_NOTICE, "Another thread is handling an event.  Waiting...");
+		pthread_mutex_lock(&_event_mutex);
+	}
+	do {
+		next = dm_get_next_target(dmt, next, &start, &length,
+					  &target_type, &params);
+
+		if (!target_type) {
+			syslog(LOG_INFO, "%s mapping lost.\n", device);
+			continue;
+		}
+
+		if (strcmp(target_type, "mirror")) {
+			syslog(LOG_INFO, "%s has unmirrored portion.\n", device);
+			continue;
+		}
+
+		switch(_get_mirror_event(params)) {
+		case ME_INSYNC:
+			/* FIXME: all we really know is that this
+			   _part_ of the device is in sync
+			   Also, this is not an error
+			*/
+			syslog(LOG_NOTICE, "%s is now in-sync\n", device);
+			break;
+		case ME_FAILURE:
+			syslog(LOG_ERR, "Device failure in %s\n", device);
+			if (_remove_failed_devices(device))
+				/* FIXME Why are all the error return codes unused? Get rid of them? */
+				syslog(LOG_ERR, "Failed to remove faulty devices in %s\n",
+				       device);
+			/* Should check before warning user that device is now linear
+			else
+				syslog(LOG_NOTICE, "%s is now a linear device.\n",
+					device);
+			*/
+			break;
+		case ME_IGNORE:
+			break;
+		default:
+			/* FIXME Provide value then! */
+			syslog(LOG_INFO, "Unknown event received.\n");
+		}
+	} while (next);
+
+	pthread_mutex_unlock(&_event_mutex);
+}
+
+int register_device(const char *device,
+		    const char *uuid __attribute((unused)),
+		    int major __attribute((unused)),
+		    int minor __attribute((unused)),
+		    void **unused __attribute((unused)))
+{
+	int r = 0;
+
+	pthread_mutex_lock(&_register_mutex);
+
+	syslog(LOG_INFO, "Monitoring mirror device %s for events\n", device);
+
+	/*
+	 * Need some space for allocations.  1024 should be more
+	 * than enough for what we need (device mapper name splitting)
+	 */
+	if (!_mem_pool && !(_mem_pool = dm_pool_create("mirror_dso", 1024)))
+		goto out;
+
+	if (!_lvm_handle) {
+		lvm2_log_fn(_temporary_log_fn);
+		if (!(_lvm_handle = lvm2_init())) {
+			dm_pool_destroy(_mem_pool);
+			_mem_pool = NULL;
+			goto out;
+		}
+		lvm2_log_level(_lvm_handle, LVM2_LOG_SUPPRESS);
+		/* FIXME Temporary: move to dmeventd core */
+		lvm2_run(_lvm_handle, "_memlock_inc");
+	}
+
+	_register_count++;
+	r = 1;
+
+out:
+	pthread_mutex_unlock(&_register_mutex);
+
+	return r;
+}
+
+int unregister_device(const char *device,
+		      const char *uuid __attribute((unused)),
+		      int major __attribute((unused)),
+		      int minor __attribute((unused)),
+		      void **unused __attribute((unused)))
+{
+	pthread_mutex_lock(&_register_mutex);
+
+	syslog(LOG_INFO, "No longer monitoring mirror device %s for events\n",
+	       device);
+
+	if (!--_register_count) {
+		dm_pool_destroy(_mem_pool);
+		_mem_pool = NULL;
+		lvm2_run(_lvm_handle, "_memlock_dec");
+		lvm2_exit(_lvm_handle);
+		_lvm_handle = NULL;
+	}
+
+	pthread_mutex_unlock(&_register_mutex);
+
+	return 1;
+}
Index: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/snapshot/.exported_symbols
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/snapshot/.exported_symbols
diff -N src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/snapshot/.exported_symbols
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/snapshot/.exported_symbols	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,3 @@
+process_event
+register_device
+unregister_device
Index: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/snapshot/Makefile.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/snapshot/Makefile.in
diff -N src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/snapshot/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/snapshot/Makefile.in	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,37 @@
+#
+# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+# Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+#
+# This file is part of the LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+INCLUDES += -I${top_srcdir}/tools
+CLDFLAGS += -L${top_srcdir}/tools -ldevmapper @LVM2CMD_LIB@
+
+SOURCES = dmeventd_snapshot.c
+
+ifeq ("@LIB_SUFFIX@","dylib")
+  LIB_SHARED = libdevmapper-event-lvm2snapshot.dylib
+else
+  LIB_SHARED = libdevmapper-event-lvm2snapshot.so
+endif
+
+LIB_VERSION = $(LIB_VERSION_LVM)
+
+include $(top_srcdir)/make.tmpl
+
+install: libdevmapper-event-lvm2snapshot.$(LIB_SUFFIX)
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
+		$(libdir)/$<.$(LIB_VERSION)
+	$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<
Index: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c
diff -N src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c	13 Dec 2008 14:39:31 -0000	1.1.1.1.2.2
@@ -0,0 +1,215 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2007-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "libdevmapper.h"
+#include "libdevmapper-event.h"
+#include "lvm2cmd.h"
+#include "lvm-string.h"
+
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <unistd.h>
+
+#include <syslog.h> /* FIXME Replace syslog with multilog */
+/* FIXME Missing openlog? */
+
+/* First warning when snapshot is 80% full. */
+#define WARNING_THRESH 80
+/* Further warnings at 85%, 90% and 95% fullness. */
+#define WARNING_STEP 5
+
+static pthread_mutex_t _register_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/*
+ * Number of active registrations.
+ */
+static int _register_count = 0;
+
+static struct dm_pool *_mem_pool = NULL;
+static void *_lvm_handle = NULL;
+
+struct snap_status {
+	int invalid;
+	int used;
+	int max;
+};
+
+/*
+ * Currently only one event can be processed at a time.
+ */
+static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static void _temporary_log_fn(int level,
+			      const char *file __attribute((unused)),
+			      int line __attribute((unused)),
+			      const char *format)
+{
+	if (!strncmp(format, "WARNING: ", 9) && (level < 5))
+		syslog(LOG_CRIT, "%s", format);
+	else
+		syslog(LOG_DEBUG, "%s", format);
+}
+
+/* FIXME possibly reconcile this with target_percent when we gain
+   access to regular LVM library here. */
+static void _parse_snapshot_params(char *params, struct snap_status *stat)
+{
+	char *p;
+	/*
+	 * xx/xx	-- fractions used/max
+	 * Invalid	-- snapshot invalidated
+	 * Unknown	-- status unknown
+	 */
+	stat->used = stat->max = 0;
+
+	if (!strncmp(params, "Invalid", 7)) {
+		stat->invalid = 1;
+		return;
+	}
+
+	/*
+	 * When we return without setting non-zero max, the parent is
+	 * responsible for reporting errors.
+	 */
+	if (!strncmp(params, "Unknown", 7))
+		return;
+
+	if (!(p = strstr(params, "/")))
+		return;
+
+	*p = '\0';
+	p++;
+
+	stat->used = atoi(params);
+	stat->max = atoi(p);
+}
+
+void process_event(struct dm_task *dmt,
+		   enum dm_event_mask event __attribute((unused)),
+		   void **private)
+{
+	void *next = NULL;
+	uint64_t start, length;
+	char *target_type = NULL;
+	char *params;
+	struct snap_status stat = { 0 };
+	const char *device = dm_task_get_name(dmt);
+	int percent, *percent_warning = (int*)private;
+
+	/* No longer monitoring, waiting for remove */
+	if (!*percent_warning)
+		return;
+
+	if (pthread_mutex_trylock(&_event_mutex)) {
+		syslog(LOG_NOTICE, "Another thread is handling an event.  Waiting...");
+		pthread_mutex_lock(&_event_mutex);
+	}
+
+	dm_get_next_target(dmt, next, &start, &length, &target_type, &params);
+	if (!target_type)
+		goto out;
+
+	_parse_snapshot_params(params, &stat);
+	/*
+	 * If the snapshot has been invalidated or we failed to parse
+	 * the status string. Report the full status string to syslog.
+	 */
+	if (stat.invalid || !stat.max) {
+		syslog(LOG_ERR, "Snapshot %s changed state to: %s\n", device, params);
+		*percent_warning = 0;
+		goto out;
+	}
+
+	percent = 100 * stat.used / stat.max;
+	if (percent >= *percent_warning) {
+		syslog(LOG_WARNING, "Snapshot %s is now %i%% full.\n", device, percent);
+		/* Print warning on the next multiple of WARNING_STEP. */
+		*percent_warning = (percent / WARNING_STEP) * WARNING_STEP + WARNING_STEP;
+	}
+out:
+	pthread_mutex_unlock(&_event_mutex);
+}
+
+int register_device(const char *device,
+		    const char *uuid __attribute((unused)),
+		    int major __attribute((unused)),
+		    int minor __attribute((unused)),
+		    void **private)
+{
+	int r = 0;
+	int *percent_warning = (int*)private;
+
+	pthread_mutex_lock(&_register_mutex);
+
+	/*
+	 * Need some space for allocations.  1024 should be more
+	 * than enough for what we need (device mapper name splitting)
+	 */
+	if (!_mem_pool && !(_mem_pool = dm_pool_create("snapshot_dso", 1024)))
+		goto out;
+
+	*percent_warning = WARNING_THRESH; /* Print warning if snapshot is full */
+
+	if (!_lvm_handle) {
+		lvm2_log_fn(_temporary_log_fn);
+		if (!(_lvm_handle = lvm2_init())) {
+			dm_pool_destroy(_mem_pool);
+			_mem_pool = NULL;
+			goto out;
+		}
+		lvm2_log_level(_lvm_handle, LVM2_LOG_SUPPRESS);
+		/* FIXME Temporary: move to dmeventd core */
+		lvm2_run(_lvm_handle, "_memlock_inc");
+	}
+
+	syslog(LOG_INFO, "Monitoring snapshot %s\n", device);
+
+	_register_count++;
+	r = 1;
+
+out:
+	pthread_mutex_unlock(&_register_mutex);
+
+	return r;
+}
+
+int unregister_device(const char *device,
+		      const char *uuid __attribute((unused)),
+		      int major __attribute((unused)),
+		      int minor __attribute((unused)),
+		      void **unused __attribute((unused)))
+{
+	pthread_mutex_lock(&_register_mutex);
+
+	syslog(LOG_INFO, "No longer monitoring snapshot %s\n",
+	       device);
+
+	if (!--_register_count) {
+		dm_pool_destroy(_mem_pool);
+		_mem_pool = NULL;
+		lvm2_run(_lvm_handle, "_memlock_dec");
+		lvm2_exit(_lvm_handle);
+		_lvm_handle = NULL;
+	}
+
+	pthread_mutex_unlock(&_register_mutex);
+
+	return 1;
+}
Index: src/external/gpl2/lvm2tools/dist/doc/Makefile.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/doc/Makefile.in
diff -N src/external/gpl2/lvm2tools/dist/doc/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/doc/Makefile.in	15 Jul 2008 13:49:20 -0000	1.1.1.1
@@ -0,0 +1,29 @@
+#
+# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+CONFSRC=example.conf
+CONFDEST=lvm.conf
+
+include $(top_srcdir)/make.tmpl
+
+install:
+	@if [ ! -e $(confdir)/$(CONFDEST) ]; then \
+		echo "Installing $(CONFSRC) as $(confdir)/$(CONFDEST)"; \
+		@INSTALL@ -D $(OWNER) $(GROUP) -m 644 $(CONFSRC) \
+			$(confdir)/$(CONFDEST); \
+	fi
+
Index: src/external/gpl2/lvm2tools/dist/doc/example.conf
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/doc/example.conf
diff -N src/external/gpl2/lvm2tools/dist/doc/example.conf
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/doc/example.conf	12 Dec 2008 16:32:58 -0000	1.1.1.1.2.1
@@ -0,0 +1,411 @@
+# This is an example configuration file for the LVM2 system.
+# It contains the default settings that would be used if there was no
+# /etc/lvm/lvm.conf file.
+#
+# Refer to 'man lvm.conf' for further information including the file layout.
+#
+# To put this file in a different directory and override /etc/lvm set
+# the environment variable LVM_SYSTEM_DIR before running the tools.
+
+
+# This section allows you to configure which block devices should
+# be used by the LVM system.
+devices {
+
+    # Where do you want your volume groups to appear ?
+    dir = "/dev"
+
+    # An array of directories that contain the device nodes you wish
+    # to use with LVM2.
+    scan = [ "/dev" ]
+
+    # If several entries in the scanned directories correspond to the
+    # same block device and the tools need to display a name for device,
+    # all the pathnames are matched against each item in the following
+    # list of regular expressions in turn and the first match is used.
+    preferred_names = [ ]
+
+    # Try to avoid using undescriptive /dev/dm-N names, if present.
+    # preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ]
+
+    # A filter that tells LVM2 to only use a restricted set of devices.
+    # The filter consists of an array of regular expressions.  These
+    # expressions can be delimited by a character of your choice, and
+    # prefixed with either an 'a' (for accept) or 'r' (for reject).
+    # The first expression found to match a device name determines if
+    # the device will be accepted or rejected (ignored).  Devices that
+    # don't match any patterns are accepted.
+
+    # Be careful if there there are symbolic links or multiple filesystem 
+    # entries for the same device as each name is checked separately against
+    # the list of patterns.  The effect is that if any name matches any 'a'
+    # pattern, the device is accepted; otherwise if any name matches any 'r'
+    # pattern it is rejected; otherwise it is accepted.
+
+    # Don't have more than one filter line active at once: only one gets used.
+
+    # Run vgscan after you change this parameter to ensure that
+    # the cache file gets regenerated (see below).
+    # If it doesn't do what you expect, check the output of 'vgscan -vvvv'.
+
+
+    # By default we accept every block device:
+    filter = [ "a/.*/" ]
+
+    # Exclude the cdrom drive
+    # filter = [ "r|/dev/cdrom|" ]
+
+    # When testing I like to work with just loopback devices:
+    # filter = [ "a/loop/", "r/.*/" ]
+
+    # Or maybe all loops and ide drives except hdc:
+    # filter =[ "a|loop|", "r|/dev/hdc|", "a|/dev/ide|", "r|.*|" ]
+
+    # Use anchors if you want to be really specific
+    # filter = [ "a|^/dev/hda8$|", "r/.*/" ]
+
+    # The results of the filtering are cached on disk to avoid
+    # rescanning dud devices (which can take a very long time).
+    # By default this cache is stored in the /etc/lvm/cache directory
+    # in a file called '.cache'.
+    # It is safe to delete the contents: the tools regenerate it.
+    # (The old setting 'cache' is still respected if neither of
+    # these new ones is present.)
+    cache_dir = "/etc/lvm/cache"
+    cache_file_prefix = ""
+
+    # You can turn off writing this cache file by setting this to 0.
+    write_cache_state = 1
+
+    # Advanced settings.
+
+    # List of pairs of additional acceptable block device types found 
+    # in /proc/devices with maximum (non-zero) number of partitions.
+    # types = [ "fd", 16 ]
+
+    # If sysfs is mounted (2.6 kernels) restrict device scanning to 
+    # the block devices it believes are valid.
+    # 1 enables; 0 disables.
+    sysfs_scan = 1	
+
+    # By default, LVM2 will ignore devices used as components of
+    # software RAID (md) devices by looking for md superblocks.
+    # 1 enables; 0 disables.
+    md_component_detection = 1
+
+    # By default, if a PV is placed directly upon an md device, LVM2
+    # will align its data blocks with the the chunk_size exposed in sysfs.
+    # 1 enables; 0 disables.
+    md_chunk_alignment = 1
+
+    # If, while scanning the system for PVs, LVM2 encounters a device-mapper
+    # device that has its I/O suspended, it waits for it to become accessible.
+    # Set this to 1 to skip such devices.  This should only be needed
+    # in recovery situations.
+    ignore_suspended_devices = 0
+}
+
+# This section that allows you to configure the nature of the
+# information that LVM2 reports.
+log {
+
+    # Controls the messages sent to stdout or stderr.
+    # There are three levels of verbosity, 3 being the most verbose.
+    verbose = 0
+
+    # Should we send log messages through syslog?
+    # 1 is yes; 0 is no.
+    syslog = 1
+
+    # Should we log error and debug messages to a file?
+    # By default there is no log file.
+    #file = "/var/log/lvm2.log"
+
+    # Should we overwrite the log file each time the program is run?
+    # By default we append.
+    overwrite = 0
+
+    # What level of log messages should we send to the log file and/or syslog?
+    # There are 6 syslog-like log levels currently in use - 2 to 7 inclusive.
+    # 7 is the most verbose (LOG_DEBUG).
+    level = 0
+    
+    # Format of output messages
+    # Whether or not (1 or 0) to indent messages according to their severity
+    indent = 1
+
+    # Whether or not (1 or 0) to display the command name on each line output
+    command_names = 0
+
+    # A prefix to use before the message text (but after the command name,
+    # if selected).  Default is two spaces, so you can see/grep the severity
+    # of each message.
+    prefix = "  "
+
+    # To make the messages look similar to the original LVM tools use:
+    #   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
+# talk about a 'backup' we mean making a copy of the metadata for the
+# *current* system.  The 'archive' contains old metadata configurations.
+# Backups are stored in a human readeable text format.
+backup {
+
+    # Should we maintain a backup of the current metadata configuration ?
+    # Use 1 for Yes; 0 for No.
+    # Think very hard before turning this off!
+    backup = 1
+
+    # Where shall we keep it ?
+    # Remember to back up this directory regularly!
+    backup_dir = "/etc/lvm/backup"
+
+    # Should we maintain an archive of old metadata configurations.
+    # Use 1 for Yes; 0 for No.
+    # On by default.  Think very hard before turning this off.
+    archive = 1
+
+    # Where should archived files go ?
+    # Remember to back up this directory regularly!
+    archive_dir = "/etc/lvm/archive"
+    
+    # What is the minimum number of archive files you wish to keep ?
+    retain_min = 10
+
+    # What is the minimum time you wish to keep an archive file for ?
+    retain_days = 30
+}
+
+# Settings for the running LVM2 in shell (readline) mode.
+shell {
+
+    # Number of lines of history to store in ~/.lvm_history
+    history_size = 100
+}
+
+
+# Miscellaneous global LVM2 settings
+global {
+    
+    # The file creation mask for any files and directories created.
+    # Interpreted as octal if the first digit is zero.
+    umask = 077
+
+    # Allow other users to read the files
+    #umask = 022
+
+    # Enabling test mode means that no changes to the on disk metadata
+    # will be made.  Equivalent to having the -t option on every
+    # command.  Defaults to off.
+    test = 0
+
+    # Default value for --units argument
+    units = "h"
+
+    # Whether or not to communicate with the kernel device-mapper.
+    # Set to 0 if you want to use the tools to manipulate LVM metadata 
+    # without activating any logical volumes.
+    # If the device-mapper kernel driver is not present in your kernel
+    # setting this to 0 should suppress the error messages.
+    activation = 1
+
+    # If we can't communicate with device-mapper, should we try running 
+    # the LVM1 tools?
+    # This option only applies to 2.4 kernels and is provided to help you
+    # switch between device-mapper kernels and LVM1 kernels.
+    # The LVM1 tools need to be installed with .lvm1 suffices
+    # e.g. vgscan.lvm1 and they will stop working after you start using
+    # the new lvm2 on-disk metadata format.
+    # The default value is set when the tools are built.
+    # fallback_to_lvm1 = 0
+
+    # The default metadata format that commands should use - "lvm1" or "lvm2".
+    # The command line override is -M1 or -M2.
+    # Defaults to "lvm1" if compiled in, else "lvm2".
+    # format = "lvm1"
+
+    # Location of proc filesystem
+    proc = "/proc"
+
+    # Type of locking to use. Defaults to local file-based locking (1).
+    # Turn locking off by setting to 0 (dangerous: risks metadata corruption
+    # if LVM2 commands get run concurrently).
+    # Type 2 uses the external shared library locking_library.
+    # Type 3 uses built-in clustered locking.
+    locking_type = 1
+
+    # If using external locking (type 2) and initialisation fails,
+    # with this set to 1 an attempt will be made to use the built-in
+    # clustered locking.
+    # If you are using a customised locking_library you should set this to 0.
+    fallback_to_clustered_locking = 1
+
+    # If an attempt to initialise type 2 or type 3 locking failed, perhaps
+    # because cluster components such as clvmd are not running, with this set
+    # to 1 an attempt will be made to use local file-based locking (type 1).
+    # If this succeeds, only commands against local volume groups will proceed.
+    # Volume Groups marked as clustered will be ignored.
+    fallback_to_local_locking = 1
+
+    # Local non-LV directory that holds file-based locks while commands are
+    # in progress.  A directory like /tmp that may get wiped on reboot is OK.
+    locking_dir = "/var/lock/lvm"
+
+    # Other entries can go here to allow you to load shared libraries
+    # e.g. if support for LVM1 metadata was compiled as a shared library use
+    #   format_libraries = "liblvm2format1.so" 
+    # Full pathnames can be given.
+
+    # Search this directory first for shared libraries.
+    #   library_dir = "/lib"
+
+    # The external locking library to load if locking_type is set to 2.
+    #   locking_library = "liblvm2clusterlock.so"
+}
+
+activation {
+    # How to fill in missing stripes if activating an incomplete volume.
+    # Using "error" will make inaccessible parts of the device return
+    # I/O errors on access.  You can instead use a device path, in which 
+    # case, that device will be used to in place of missing stripes.
+    # But note that using anything other than "error" with mirrored 
+    # or snapshotted volumes is likely to result in data corruption.
+    missing_stripe_filler = "error"
+
+    # 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
+
+    # If volume_list is defined, each LV is only activated if there is a
+    # match against the list.
+    #   "vgname" and "vgname/lvname" are matched exactly.
+    #   "@tag" matches any tag set in the LV or VG.
+    #   "@*" matches if any tag defined on the host is also set in the LV or VG
+    #
+    # volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ]
+
+    # Size (in KB) of each copy operation when mirroring
+    mirror_region_size = 512
+
+    # Setting to use when there is no readahead value stored in the metadata.
+    #
+    # "none" - Disable readahead.
+    # "auto" - Use default value chosen by kernel.
+    readahead = "auto"
+
+    # 'mirror_image_fault_policy' and 'mirror_log_fault_policy' define
+    # how a device failure affecting a mirror is handled.
+    # A mirror is composed of mirror images (copies) and a log.
+    # A disk log ensures that a mirror does not need to be re-synced
+    # (all copies made the same) every time a machine reboots or crashes.
+    #
+    # In the event of a failure, the specified policy will be used to
+    # determine what happens:
+    #
+    # "remove" - Simply remove the faulty device and run without it.  If
+    #            the log device fails, the mirror would convert to using
+    #            an in-memory log.  This means the mirror will not
+    #            remember its sync status across crashes/reboots and
+    #            the entire mirror will be re-synced.  If a
+    #            mirror image fails, the mirror will convert to a
+    #            non-mirrored device if there is only one remaining good
+    #            copy.
+    #
+    # "allocate" - Remove the faulty device and try to allocate space on
+    #            a new device to be a replacement for the failed device.
+    #            Using this policy for the log is fast and maintains the
+    #            ability to remember sync state through crashes/reboots.
+    #            Using this policy for a mirror device is slow, as it
+    #            requires the mirror to resynchronize the devices, but it
+    #            will preserve the mirror characteristic of the device.
+    #            This policy acts like "remove" if no suitable device and
+    #            space can be allocated for the replacement.
+    #            Currently this is not implemented properly and behaves
+    #            similarly to:
+    #
+    # "allocate_anywhere" - Operates like "allocate", but it does not
+    #            require that the new space being allocated be on a
+    #            device is not part of the mirror.  For a log device
+    #            failure, this could mean that the log is allocated on
+    #            the same device as a mirror device.  For a mirror
+    #            device, this could mean that the mirror device is
+    #            allocated on the same device as another mirror device.
+    #            This policy would not be wise for mirror devices
+    #            because it would break the redundant nature of the
+    #            mirror.  This policy acts like "remove" if no suitable
+    #            device and space can be allocated for the replacement.
+
+    mirror_log_fault_policy = "allocate"
+    mirror_device_fault_policy = "remove"
+}
+
+
+####################
+# Advanced section #
+####################
+
+# Metadata settings
+#
+# metadata {
+    # Default number of copies of metadata to hold on each PV.  0, 1 or 2.
+    # You might want to override it from the command line with 0 
+    # when running pvcreate on new PVs which are to be added to large VGs.
+
+    # pvmetadatacopies = 1
+
+    # Approximate default size of on-disk metadata areas in sectors.
+    # You should increase this if you have large volume groups or
+    # you want to retain a large on-disk history of your metadata changes.
+
+    # pvmetadatasize = 255
+
+    # List of directories holding live copies of text format metadata.
+    # These directories must not be on logical volumes!
+    # It's possible to use LVM2 with a couple of directories here,
+    # 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 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
+    # the supplied toolset to make changes (e.g. vgcfgrestore).
+
+    # dirs = [ "/etc/lvm/metadata", "/mnt/disk2/lvm/metadata2" ]
+#}
+
+# Event daemon
+#
+# dmeventd {
+    # mirror_library is the library used when monitoring a mirror device.
+    #
+    # "libdevmapper-event-lvm2mirror.so" attempts to recover from
+    # failures.  It removes failed devices from a volume group and
+    # reconfigures a mirror as necessary. If no mirror library is
+    # provided, mirrors are not monitored through dmeventd.
+
+    # mirror_library = "libdevmapper-event-lvm2mirror.so"
+
+    # snapshot_library is the library used when monitoring a snapshot device.
+    #
+    # "libdevmapper-event-lvm2snapshot.so" monitors the filling of
+    # snapshots and emits a warning through syslog, when the use of
+    # snapshot exceedes 80%. The warning is repeated when 85%, 90% and
+    # 95% of the snapshot are filled.
+
+    # snapshot_library = "libdevmapper-event-lvm2snapshot.so"
+#}
+
Index: src/external/gpl2/lvm2tools/dist/doc/example_cmdlib.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/doc/example_cmdlib.c
diff -N src/external/gpl2/lvm2tools/dist/doc/example_cmdlib.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/doc/example_cmdlib.c	13 Dec 2008 14:39:32 -0000	1.1.1.1.2.2
@@ -0,0 +1,49 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lvm2cmd.h"
+
+/* All output gets passed to this function line-by-line */
+void test_log_fn(int level, const char *file, int line, const char *format)
+{
+	/* Extract and process output here rather than printing it */
+
+	if (level != 4)
+		return;
+
+	printf("%s\n", format);
+	return;
+}
+
+int main(int argc, char **argv)
+{
+	void *handle;
+	int r;
+
+	lvm2_log_fn(test_log_fn);
+
+	handle = lvm2_init();
+
+	lvm2_log_level(handle, 1);
+	r = lvm2_run(handle, "vgs --noheadings vg1");
+
+	/* More commands here */
+
+	lvm2_exit(handle);
+
+	return r;
+}
+
Index: src/external/gpl2/lvm2tools/dist/doc/pvmove_outline.txt
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/doc/pvmove_outline.txt
diff -N src/external/gpl2/lvm2tools/dist/doc/pvmove_outline.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/doc/pvmove_outline.txt	15 Jul 2008 13:49:21 -0000	1.1.1.1
@@ -0,0 +1,52 @@
+Let's say we have an LV, made up of three segments of different PV's,
+I've also added in the device major:minor as this will be useful
+later:
+
++-----------------------------+
+|  PV1     |   PV2   |   PV3  | 254:3
++----------+---------+--------+
+
+
+Now our hero decides to PV move PV2 to PV4:
+
+1. Suspend our LV (254:3), this starts queueing all io, and flushes
+   all pending io.  Once the suspend has completed we are free to change
+   the mapping table.
+
+2. Set up *another* (254:4) device with the mapping table of our LV.
+
+3. Load a new mapping table into (254:3) that has identity targets for
+   parts that aren't moving, and a mirror target for parts that are.
+
+4. Unsuspend (254:3)
+
+So now we have:
+                           destination of copy
+               +--------------------->--------------+
+               |                                    |
++-----------------------------+               + -----------+
+| Identity | mirror  | Ident. | 254:3         |    PV4     |
++----------+---------+--------+               +------------+
+     |         |         |
+     \/        \/        \/
++-----------------------------+
+|  PV1     |   PV2   |   PV3  | 254:4
++----------+---------+--------+
+
+Any writes to segment2 of the LV get intercepted by the mirror target
+who checks that that chunk has been copied to the new destination, if
+it hasn't it queues the initial copy and defers the current io until
+it has finished.  Then the current io is written to *both* PV2 and the
+PV4.
+
+5. When the copying has completed 254:3 is suspended/pending flushed.
+
+6. 254:4 is taken down
+
+7. metadata is updated on disk
+
+8. 254:3 has new mapping table loaded:
+
++-----------------------------+
+|  PV1     |   PV4   |   PV3  | 254:3
++----------+---------+--------+
Index: src/external/gpl2/lvm2tools/dist/doc/tagging.txt
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/doc/tagging.txt
diff -N src/external/gpl2/lvm2tools/dist/doc/tagging.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/doc/tagging.txt	15 Jul 2008 13:49:21 -0000	1.1.1.1
@@ -0,0 +1,165 @@
+Tagging aims
+============
+  1) Ability to attach an unordered list of tags to LVM metadata objects.
+  2) Ability to add or remove tags easily.
+  3) Ability to select LVM objects for processing according to presence/absence
+     of specific tags.
+  4) Ability to control through the config file which VGs/LVs are activated 
+     on different machines using names or tags.
+  5) Ability to overlay settings from different config files e.g. override
+     some settings in a global config file locally.
+
+Clarifications
+==============
+  1) Tag character set: A-Za-z0-9_+.- 
+     Can't start with hyphen & max length is 128 (NAME_LEN).
+  2) LVM object types that can be tagged:
+       VG, LV, LV segment
+       PV - tags are stored in VG metadata so disappear when PV becomes orphaned
+     Snapshots can't be tagged, but their origin may be.
+  3) A tag can be used in place of any command line LVM object reference that
+     accepts (a) a list of objects; or (b) a single object as long as the
+     tag expands to a single object.  This is not supported everywhere yet.
+     Duplicate arguments in a list after argument expansion may get removed 
+     retaining the first copy of each argument.
+  4) Wherever there may be ambiguity of argument type, a tag must be prefixed 
+     by '@'; elsewhere an '@' prefix is optional.
+  5) LVM1 objects cannot be tagged, as the disk format doesn't support it.
+  6) Tags can be added or removed with --addtag or --deltag.
+
+Config file Extensions
+======================
+  To define host tags in config file:
+
+  tags {
+  	# Set a tag with the hostname
+	hosttags = 1
+
+	tag1 { }
+
+  	tag2 {
+		# If no exact match, tag is not set.
+		host_list = [ "hostname", "dbase" ]
+	}
+  }
+
+Activation config file example
+==============================
+  activation {
+      volume_list = [ "vg1/lvol0", "@database" ]
+  }
+
+  Matches against vgname, vgname/lvname or @tag set in *metadata*.
+  @* matches exactly against *any* tag set on the host.
+  The VG or LV only gets activated if a metadata tag matches.
+  The default if there is no match is not to activate.
+  If volume_list is not present and any tags are defined on the host 
+  then it only activates if a host tag matches a metadata tag.
+  If volume_list is not present and no tags are defined on the host 
+  then it does activate.
+
+Multiple config files
+=====================
+  (a) lvm.conf
+  (b) lvm_<host_tag>.conf
+
+  At startup, load lvm.conf.
+  Process tag settings.
+  If any host tags were defined, load lvm_tag.conf for each tag, if present.
+
+  When searching for a specific config file entry, search order is (b)
+  then (a), stopping at the first match.  
+  Within (b) use reverse order tags got set, so file for last tag set is
+  searched first.
+  New tags set in (b) *do* trigger additional config file loads. 
+
+Usage Examples
+==============
+  1) Simple activation control via metadata with static config files
+
+  lvm.conf:  (Identical on every machine - global settings)
+    tags {
+      hostname_tags = 1
+    }
+
+  From any machine in the cluster, add db1 to the list of machines that
+  activate vg1/lvol2:
+
+  lvchange --tag @db1 vg1/lvol2
+  (followed by lvchange -ay to actually activate it)
+
+
+  2) Multiple hosts.  
+
+    Activate vg1 only on the database hosts, db1 and db2.
+    Activate vg2 only on the fileserver host fs1.
+    Activate nothing initially on the fileserver backup host fsb1, but be
+    prepared for it to take over from fs1.
+
+  Option (i) - centralised admin, static configuration replicated between hosts  
+    # Add @database tag to vg1's metadata
+    vgchange --tag @database vg1
+
+    # Add @fileserver tag to vg2's metadata
+    vgchange --tag @fileserver vg2
+
+    lvm.conf:  (Identical on every machine)
+      tags {
+        database {
+          host_list = [ "db1", "db2" ]
+        }
+        fileserver {
+	  host_list = [ "fs1" ]
+        }
+        fileserverbackup {
+          host_list = [ "fsb1" ]
+        }
+      }
+
+      activation {
+        # Only activate if host has a tag that matches a metadata tag
+        volume_list = [ "@*" ]
+      }
+  
+  In the event of the fileserver host going down, vg2 can be brought up
+  on fsb1 by running *on any node* 'vgchange --tag @fileserverbackup vg2'
+  followed by 'vgchange -ay vg2'
+  
+  
+  Option (ii) - localised admin & configuation
+  (i.e. each host holds *locally* which classes of volumes to activate)
+    # Add @database tag to vg1's metadata
+    vgchange --tag @database vg1
+  
+    # Add @fileserver tag to vg2's metadata
+    vgchange --tag @fileserver vg2
+  
+    lvm.conf:  (Identical on every machine - global settings)
+      tags {
+        hosttags = 1
+      }
+  
+    lvm_db1.conf: (only needs to be on db1 - could be symlink to lvm_db.conf)
+      activation {
+        volume_list = [ "@database" ]
+      }
+  
+    lvm_db2.conf: (only needs to be on db2 - could be symlink to lvm_db.conf)
+      activation {
+        volume_list = [ "@database" ]
+      }
+  
+    lvm_fs1.conf: (only needs to be on fs1 - could be symlink to lvm_fs.conf)
+      activation {
+        volume_list = [ "@fileserver" ]
+      }
+  
+    If fileserver goes down, to bring a spare machine fsb1 in as fileserver,
+    create lvm_fsb1.conf on fsb1 (or symlink to lvm_fs.conf):
+
+      activation {
+        volume_list = [ "@fileserver" ]
+      }
+
+    and run 'vgchange -ay vg2' or 'vgchange -ay @fileserver'
+
Index: src/external/gpl2/lvm2tools/dist/doc/testing.txt
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/doc/testing.txt
diff -N src/external/gpl2/lvm2tools/dist/doc/testing.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/doc/testing.txt	15 Jul 2008 13:49:21 -0000	1.1.1.1
@@ -0,0 +1,41 @@
+Here's how I test new LVM2 builds without interfering with the stable
+LVM2 that is running the LV's on my development box.
+
+1) Create a set of loopback devices.
+
+2) Create a new directory to contain the LVM2 configuration files for
+   this setup.  (I use /etc/lvm_loops)
+
+3) Write a suitable lvm.conf file, this goes in the directory you just
+   created.  eg, my /etc/lvm_loops/lvm.conf looks like:
+
+   log {
+        file="/tmp/lvm2_loop.log"
+        level=9
+        verbose=0
+        overwrite=1
+   }
+
+   devices {
+        scan = "/dev"
+        filter = ["a/loop/", "r/.*/"]
+   }
+
+
+   The important thing to note is the devices section which makes sure
+   that only the loopback devices are considered for LVM2 operations.
+
+4) When you want to use this test setup just set the environment
+   variable LVM_SYSTEM_DIR to point to your config directory
+   (/etc/lvm_loops in my case).
+
+5) It's a good idea to do a vgscan to initialise the filters:
+
+   export LVM_SYSTEM_DIR=/etc/lvm_loops
+   ./lvm vgscan
+
+   where ./lvm is the new build of LVM2 that I'm trying out.
+
+7) Test away.  Make sure that you are explicit about which lvm
+   executable you want to execute (eg, ./lvm if you are in
+   LVM2/tools).
Index: src/external/gpl2/lvm2tools/dist/include/.symlinks
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/.symlinks
diff -N src/external/gpl2/lvm2tools/dist/include/.symlinks
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/.symlinks	12 Dec 2008 16:32:58 -0000	1.1.1.1.2.1
@@ -0,0 +1,59 @@
+../daemons/clvmd/clvm.h
+../daemons/dmeventd/libdevmapper-event.h
+../lib/activate/activate.h
+../lib/activate/targets.h
+../lib/cache/lvmcache.h
+../lib/commands/errors.h
+../lib/commands/toolcontext.h
+../lib/config/config.h
+../lib/config/defaults.h
+../lib/datastruct/btree.h
+../lib/datastruct/lvm-types.h
+../lib/datastruct/str_list.h
+../lib/device/dev-cache.h
+../lib/device/device.h
+../lib/display/display.h
+../lib/filters/filter-composite.h
+../lib/filters/filter-md.h
+../lib/filters/filter-persistent.h
+../lib/filters/filter-regex.h
+../lib/filters/filter-sysfs.h
+../lib/filters/filter.h
+../lib/format1/format1.h
+../lib/format_pool/format_pool.h
+../lib/format_text/archiver.h
+../lib/format_text/format-text.h
+../lib/format_text/text_export.h
+../lib/format_text/text_import.h
+../lib/label/label.h
+../lib/locking/locking.h
+../lib/log/log.h
+../lib/log/lvm-logging.h
+../lib/metadata/lv_alloc.h
+../lib/metadata/metadata.h
+../lib/metadata/metadata-exported.h
+../lib/metadata/pv_alloc.h
+../lib/metadata/segtype.h
+../lib/mm/memlock.h
+../lib/mm/xlate.h
+../lib/misc/configure.h
+../lib/misc/crc.h
+../lib/misc/intl.h
+../lib/misc/util.h
+../lib/misc/last-path-component.h
+../lib/misc/lib.h
+../lib/misc/lvm-exec.h
+../lib/misc/lvm-file.h
+../lib/misc/lvm-globals.h
+../lib/misc/lvm-string.h
+../lib/misc/lvm-wrappers.h
+../lib/misc/sharedlib.h
+../lib/report/report.h
+../lib/uuid/uuid.h
+../libdm/libdevmapper.h
+../libdm/misc/dm-ioctl.h
+../libdm/misc/dm-logging.h
+../libdm/misc/dmlib.h
+../libdm/misc/kdev_t.h
+../po/pogen.h
+../tools/version.h
Index: src/external/gpl2/lvm2tools/dist/include/Makefile.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/Makefile.in
diff -N src/external/gpl2/lvm2tools/dist/include/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/Makefile.in	12 Dec 2008 16:32:58 -0000	1.1.1.1.2.1
@@ -0,0 +1,49 @@
+#
+# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+LN_S = @LN_S@
+
+.PHONY: clean distclean all install pofile install_cluster install_device-mapper
+
+all: .symlinks_created
+
+.symlinks_created: .symlinks
+	find . -maxdepth 1 -type l -exec $(RM) \{\} \;
+	for i in `cat .symlinks`; do $(LN_S) $$i ; done
+	touch $@
+
+distclean:
+	find . -maxdepth 1 -type l -exec $(RM) \{\} \;
+	$(RM) Makefile .include_symlinks .symlinks_created
+
+pofile: all
+
+device-mapper: all
+
+clean:
+
+install:
+
+install_cluster:
+
+install_device-mapper:
+
+cflow:
+
Index: src/external/gpl2/lvm2tools/dist/include/activate.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/activate.h
diff -N src/external/gpl2/lvm2tools/dist/include/activate.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/activate.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,112 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef LVM_ACTIVATE_H
+#define LVM_ACTIVATE_H
+
+#include "metadata-exported.h"
+
+struct lvinfo {
+	int exists;
+	int suspended;
+	unsigned int open_count;
+	int major;
+	int minor;
+	int read_only;
+	int live_table;
+	int inactive_table;
+	uint32_t read_ahead;
+};
+
+/* target attribute flags */
+#define MIRROR_LOG_CLUSTERED	0x00000001U
+
+void set_activation(int activation);
+int activation(void);
+
+int driver_version(char *version, size_t size);
+int library_version(char *version, size_t size);
+int lvm1_present(struct cmd_context *cmd);
+
+int module_present(const char *target_name);
+int target_present(const char *target_name, int use_modprobe);
+int target_version(const char *target_name, uint32_t *maj,
+                   uint32_t *min, uint32_t *patchlevel);
+int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg,
+			 struct dm_list *modules);
+int list_lv_modules(struct dm_pool *mem, const struct logical_volume *lv,
+		    struct dm_list *modules);
+
+void activation_release(void);
+void activation_exit(void);
+
+int lv_suspend(struct cmd_context *cmd, const char *lvid_s);
+int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s);
+int lv_resume(struct cmd_context *cmd, const char *lvid_s);
+int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s);
+int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive);
+int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s,
+			    int exclusive);
+int lv_deactivate(struct cmd_context *cmd, const char *lvid_s);
+
+int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv);
+
+/*
+ * Returns 1 if info structure has been populated, else 0.
+ */
+int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, struct lvinfo *info,
+	    int with_open_count, int with_read_ahead);
+int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
+		    struct lvinfo *info, int with_open_count, int with_read_ahead);
+
+/*
+ * Returns 1 if activate_lv has been set: 1 = activate; 0 = don't.
+ */
+int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
+			 int *activate_lv);
+
+/*
+ * Returns 1 if percent has been set, else 0.
+ */
+int lv_snapshot_percent(const struct logical_volume *lv, float *percent);
+int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
+		      int wait, float *percent, uint32_t *event_nr);
+
+/*
+ * Return number of LVs in the VG that are active.
+ */
+int lvs_in_vg_activated(struct volume_group *vg);
+int lvs_in_vg_activated_by_uuid_only(struct volume_group *vg);
+int lvs_in_vg_opened(const struct volume_group *vg);
+
+int lv_is_active(struct logical_volume *lv);
+
+int monitor_dev_for_events(struct cmd_context *cmd,
+			    struct logical_volume *lv, int do_reg);
+
+/*
+ * Returns 1 if PV has a dependency tree that uses anything in VG.
+ */
+int pv_uses_vg(struct physical_volume *pv,
+	       struct volume_group *vg);
+
+/*
+ * Returns 1 if mapped device is not suspended.
+ */
+int device_is_usable(dev_t dev);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/archiver.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/archiver.h
diff -N src/external/gpl2/lvm2tools/dist/include/archiver.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/archiver.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,63 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_TOOL_ARCHIVE_H
+#define _LVM_TOOL_ARCHIVE_H
+
+#include "metadata-exported.h"
+
+/*
+ * There are two operations that come under the general area of
+ * backups.  'Archiving' occurs just before a volume group
+ * configuration is changed.  The user may configure when
+ * archived files are expired.  Typically archives will be stored
+ * in /etc/lvm/archive.
+ *
+ * A 'backup' is a redundant copy of the *current* volume group
+ * configuration.  As such it should be taken just after the
+ * volume group is changed.  Only 1 backup file will exist.
+ * Typically backups will be stored in /etc/lvm/backups.
+ */
+
+int archive_init(struct cmd_context *cmd, const char *dir,
+		 unsigned int keep_days, unsigned int keep_min);
+void archive_exit(struct cmd_context *cmd);
+
+void archive_enable(struct cmd_context *cmd, int flag);
+int archive(struct volume_group *vg);
+int archive_display(struct cmd_context *cmd, const char *vg_name);
+int archive_display_file(struct cmd_context *cmd, const char *file);
+
+int backup_init(struct cmd_context *cmd, const char *dir);
+void backup_exit(struct cmd_context *cmd);
+
+void backup_enable(struct cmd_context *cmd, int flag);
+int backup(struct volume_group *vg);
+int backup_remove(struct cmd_context *cmd, const char *vg_name);
+
+struct volume_group *backup_read_vg(struct cmd_context *cmd,
+				    const char *vg_name, const char *file);
+int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg);
+int backup_restore_from_file(struct cmd_context *cmd, const char *vg_name,
+			     const char *file);
+int backup_restore(struct cmd_context *cmd, const char *vg_name);
+
+int backup_to_file(const char *file, const char *desc, struct volume_group *vg);
+
+void check_current_backup(struct volume_group *vg);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/btree.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/btree.h
diff -N src/external/gpl2/lvm2tools/dist/include/btree.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/btree.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,34 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_BTREE_H
+#define _LVM_BTREE_H
+
+struct btree;
+
+struct btree *btree_create(struct dm_pool *mem);
+
+void *btree_lookup(const struct btree *t, uint32_t k);
+int btree_insert(struct btree *t, uint32_t k, void *data);
+
+struct btree_iter;
+void *btree_get_data(const struct btree_iter *it);
+
+struct btree_iter *btree_first(const struct btree *t);
+struct btree_iter *btree_next(const struct btree_iter *it);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/clvm.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/clvm.h
diff -N src/external/gpl2/lvm2tools/dist/include/clvm.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/clvm.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,73 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* Definitions for CLVMD server and clients */
+
+/*
+ * The protocol spoken over the cluster and across the local socket.
+ */
+
+#ifndef _CLVM_H
+#define _CLVM_H
+
+struct clvm_header {
+	uint8_t  cmd;	        /* See below */
+	uint8_t  flags;	        /* See below */
+	uint16_t xid;	        /* Transaction ID */
+	uint32_t clientid;	/* Only used in Daemon->Daemon comms */
+	int32_t  status;	/* For replies, whether request succeeded */
+	uint32_t arglen;	/* Length of argument below. 
+				   If >1500 then it will be passed 
+				   around the cluster in the system LV */
+	char node[1];		/* Actually a NUL-terminated string, node name.
+				   If this is empty then the command is 
+				   forwarded to all cluster nodes unless 
+				   FLAG_LOCAL is also set. */
+	char args[1];		/* Arguments for the command follow the 
+				   node name, This member is only
+				   valid if the node name is empty */
+} __attribute__ ((packed));
+
+/* Flags */
+#define CLVMD_FLAG_LOCAL        1	/* Only do this on the local node */
+#define CLVMD_FLAG_SYSTEMLV     2	/* Data in system LV under my node name */
+#define CLVMD_FLAG_NODEERRS     4       /* Reply has errors in node-specific portion */
+
+/* Name of the local socket to communicate between libclvm and clvmd */
+//static const char CLVMD_SOCKNAME[]="/var/run/clvmd";
+static const char CLVMD_SOCKNAME[] = "\0clvmd";
+
+/* Internal commands & replies */
+#define CLVMD_CMD_REPLY    1
+#define CLVMD_CMD_VERSION  2	/* Send version around cluster when we start */
+#define CLVMD_CMD_GOAWAY   3	/* Die if received this - we are running 
+				   an incompatible version */
+#define CLVMD_CMD_TEST     4	/* Just for mucking about */
+
+#define CLVMD_CMD_LOCK              30
+#define CLVMD_CMD_UNLOCK            31
+
+/* Lock/Unlock commands */
+#define CLVMD_CMD_LOCK_LV           50
+#define CLVMD_CMD_LOCK_VG           51
+
+/* Misc functions */
+#define CLVMD_CMD_REFRESH	    40
+#define CLVMD_CMD_GET_CLUSTERNAME   41
+#define CLVMD_CMD_SET_DEBUG	    42
+#define CLVMD_CMD_VG_BACKUP	    43
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/config.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/config.h
diff -N src/external/gpl2/lvm2tools/dist/include/config.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/config.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,115 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_CONFIG_H
+#define _LVM_CONFIG_H
+
+#include "lvm-types.h"
+
+struct device;
+struct cmd_context;
+
+enum {
+	CFG_STRING,
+	CFG_FLOAT,
+	CFG_INT,
+	CFG_EMPTY_ARRAY
+};
+
+struct config_value {
+	int type;
+	union {
+		int64_t i;
+		float r;
+		char *str;
+	} v;
+	struct config_value *next;	/* for arrays */
+};
+
+struct config_node {
+	char *key;
+	struct config_node *sib, *child;
+	struct config_value *v;
+};
+
+struct config_tree {
+	struct config_node *root;
+};
+
+struct config_tree_list {
+	struct dm_list list;
+	struct config_tree *cft;
+};
+
+struct config_tree *create_config_tree(const char *filename, int keep_open);
+struct config_tree *create_config_tree_from_string(struct cmd_context *cmd,
+						   const char *config_settings);
+void destroy_config_tree(struct config_tree *cft);
+
+typedef uint32_t (*checksum_fn_t) (uint32_t initial, const void *buf, uint32_t size);
+
+int read_config_fd(struct config_tree *cft, struct device *dev,
+		   off_t offset, size_t size, off_t offset2, size_t size2,
+		   checksum_fn_t checksum_fn, uint32_t checksum);
+
+int read_config_file(struct config_tree *cft);
+int write_config_file(struct config_tree *cft, const char *file,
+		      int argc, char **argv);
+time_t config_file_timestamp(struct config_tree *cft);
+int config_file_changed(struct config_tree *cft);
+int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft,
+		      struct config_tree *newdata);
+
+struct config_node *find_config_node(const struct config_node *cn,
+				     const char *path);
+const char *find_config_str(const struct config_node *cn, const char *path,
+			    const char *fail);
+int find_config_int(const struct config_node *cn, const char *path, int fail);
+float find_config_float(const struct config_node *cn, const char *path,
+			float fail);
+
+/*
+ * These versions check an override tree, if present, first.
+ */
+struct config_node *find_config_tree_node(struct cmd_context *cmd,
+					  const char *path);
+const char *find_config_tree_str(struct cmd_context *cmd,
+				 const char *path, const char *fail);
+int find_config_tree_int(struct cmd_context *cmd, const char *path,
+			 int fail);
+float find_config_tree_float(struct cmd_context *cmd, const char *path,
+			     float fail);
+
+/*
+ * Understands (0, ~0), (y, n), (yes, no), (on,
+ * off), (true, false).
+ */
+int find_config_bool(const struct config_node *cn, const char *path, int fail);
+int find_config_tree_bool(struct cmd_context *cmd, const char *path, int fail);
+
+int get_config_uint32(const struct config_node *cn, const char *path,
+		      uint32_t *result);
+
+int get_config_uint64(const struct config_node *cn, const char *path,
+		      uint64_t *result);
+
+int get_config_str(const struct config_node *cn, const char *path,
+		   char **result);
+
+unsigned maybe_config_section(const char *str, unsigned len);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/configure.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/configure.h
diff -N src/external/gpl2/lvm2tools/dist/include/configure.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/configure.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,446 @@
+/* lib/misc/configure.h.  Generated from configure.h.in by configure.  */
+/* lib/misc/configure.h.in.  Generated from configure.in by autoheader.  */
+
+/* Define to 1 if the `closedir' function returns void instead of `int'. */
+/* #undef CLOSEDIR_VOID */
+
+/* Define to 1 to include built-in support for clustered LVM locking. */
+/* #undef CLUSTER_LOCKING_INTERNAL */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define to 1 if using `alloca.c'. */
+/* #undef C_ALLOCA */
+
+/* Define to 1 to enable LVM2 device-mapper interaction. */
+#define DEVMAPPER_SUPPORT 1
+
+/* Define to 1 to enable the device-mapper event daemon. */
+/* #undef DMEVENTD */
+
+/* Path to dmeventd binary. */
+/* #undef DMEVENTD_PATH */
+
+/* Path to dmeventd pidfile. */
+/* #undef DMEVENTD_PIDFILE */
+
+/* Library version */
+#define DM_LIB_VERSION "1.02.29 (2008-11-10)"
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define to 1 if you have the <asm/byteorder.h> header file. */
+/* #undef HAVE_ASM_BYTEORDER_H */
+
+/* Define to 1 if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
+
+/* Define to 1 if canonicalize_file_name is available. */
+/* #undef HAVE_CANONICALIZE_FILE_NAME */
+
+/* Define to 1 if you have the <ctype.h> header file. */
+#define HAVE_CTYPE_H 1
+
+/* Define to 1 if you have the <dirent.h> header file. */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+/* #undef HAVE_DLFCN_H */
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+/* #undef HAVE_DOPRNT */
+
+/* Define to 1 if you have the `dup2' function. */
+/* #undef HAVE_DUP2 */
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK 1
+
+/* Define to 1 if you have the `gethostname' function. */
+#define HAVE_GETHOSTNAME 1
+
+/* Define to 1 if getline is available. */
+/* #undef HAVE_GETLINE */
+
+/* Define to 1 if you have the `getmntent' function. */
+/* #undef HAVE_GETMNTENT */
+
+/* Define to 1 if getopt_long is available. */
+#define HAVE_GETOPTLONG 1
+
+/* Define to 1 if you have the <getopt.h> header file. */
+#define HAVE_GETOPT_H 1
+
+/* Define to 1 if you have the `getpagesize' function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if dynamic libraries are available. */
+/* #undef HAVE_LIBDL */
+
+/* Define to 1 if you have the <libgen.h> header file. */
+#define HAVE_LIBGEN_H 1
+
+/* Define to 1 if you have the <libintl.h> header file. */
+/* #undef HAVE_LIBINTL_H */
+
+/* Define to 1 if you have the `readline' library (-lreadline). */
+/* #undef HAVE_LIBREADLINE */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <linux/fs.h> header file. */
+/* #undef HAVE_LINUX_FS_H */
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if `lstat' has the bug that it succeeds when given the
+   zero-length file name argument. */
+/* #undef HAVE_LSTAT_EMPTY_STRING_BUG */
+
+/* Define to 1 if you have the <machine/endian.h> header file. */
+/* #undef HAVE_MACHINE_ENDIAN_H */
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+   to 0 otherwise. */
+#define HAVE_MALLOC 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define to 1 if you have the `memmove' function. */
+/* #undef HAVE_MEMMOVE */
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define to 1 if you have the `mkdir' function. */
+#define HAVE_MKDIR 1
+
+/* Define to 1 if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* Define to 1 if you have the <mntent.h> header file. */
+/* #undef HAVE_MNTENT_H */
+
+/* Define to 1 if you have the `munmap' function. */
+#define HAVE_MUNMAP 1
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the <netdb.h> header file. */
+/* #undef HAVE_NETDB_H */
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+/* #undef HAVE_NETINET_IN_H */
+
+/* Define to 1 if you have the <pthread.h> header file. */
+/* #undef HAVE_PTHREAD_H */
+
+/* Define to 1 if you have the <readline/history.h> header file. */
+/* #undef HAVE_READLINE_HISTORY_H */
+
+/* Define to 1 if you have the <readline/readline.h> header file. */
+/* #undef HAVE_READLINE_READLINE_H */
+
+/* Define to 1 to include support for realtime clock. */
+/* #undef HAVE_REALTIME */
+
+/* Define to 1 if you have the `rl_completion_matches' function. */
+/* #undef HAVE_RL_COMPLETION_MATCHES */
+
+/* Define to 1 if you have the `rmdir' function. */
+#define HAVE_RMDIR 1
+
+/* Define to 1 if you have the <search.h> header file. */
+/* #undef HAVE_SEARCH_H */
+
+/* Define to 1 if you have the `select' function. */
+/* #undef HAVE_SELECT */
+
+/* Define to 1 to include support for selinux. */
+/* #undef HAVE_SELINUX */
+
+/* Define to 1 if you have the <selinux/selinux.h> header file. */
+/* #undef HAVE_SELINUX_SELINUX_H */
+
+/* Define to 1 if sepol_check_context is available. */
+/* #undef HAVE_SEPOL */
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* Define to 1 if you have the `socket' function. */
+/* #undef HAVE_SOCKET */
+
+/* Define to 1 if `stat' has the bug that it succeeds when given the
+   zero-length file name argument. */
+/* #undef HAVE_STAT_EMPTY_STRING_BUG */
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#define HAVE_STDIO_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strchr' function. */
+#define HAVE_STRCHR 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strncasecmp' function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define to 1 if you have the `strrchr' function. */
+#define HAVE_STRRCHR 1
+
+/* Define to 1 if you have the `strstr' function. */
+#define HAVE_STRSTR 1
+
+/* Define to 1 if you have the `strtol' function. */
+#define HAVE_STRTOL 1
+
+/* Define to 1 if you have the `strtoul' function. */
+#define HAVE_STRTOUL 1
+
+/* Define to 1 if `st_rdev' is member of `struct stat'. */
+#define HAVE_STRUCT_STAT_ST_RDEV 1
+
+/* Define to 1 if you have the <syslog.h> header file. */
+#define HAVE_SYSLOG_H 1
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/disk.h> header file. */
+/* #undef HAVE_SYS_DISK_H */
+
+/* Define to 1 if you have the <sys/file.h> header file. */
+#define HAVE_SYS_FILE_H 1
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#define HAVE_SYS_MMAN_H 1
+
+/* Define to 1 if you have the <sys/mount.h> header file. */
+/* #undef HAVE_SYS_MOUNT_H */
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+/* #undef HAVE_SYS_SELECT_H */
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+/* #undef HAVE_SYS_SOCKET_H */
+
+/* Define to 1 if you have the <sys/statvfs.h> header file. */
+#define HAVE_SYS_STATVFS_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
+/* #undef HAVE_SYS_UIO_H */
+
+/* Define to 1 if you have the <sys/un.h> header file. */
+/* #undef HAVE_SYS_UN_H */
+
+/* Define to 1 if you have the <sys/utsname.h> header file. */
+#define HAVE_SYS_UTSNAME_H 1
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define to 1 if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define to 1 if you have the `uname' function. */
+#define HAVE_UNAME 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the <utmpx.h> header file. */
+/* #undef HAVE_UTMPX_H */
+
+/* Define to 1 if you have the `vfork' function. */
+#define HAVE_VFORK 1
+
+/* Define to 1 if you have the <vfork.h> header file. */
+/* #undef HAVE_VFORK_H */
+
+/* Define to 1 if you have the `vprintf' function. */
+#define HAVE_VPRINTF 1
+
+/* Define to 1 if `fork' works. */
+#define HAVE_WORKING_FORK 1
+
+/* Define to 1 if `vfork' works. */
+#define HAVE_WORKING_VFORK 1
+
+/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
+   slash. */
+#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1
+
+/* Define to 1 if 'lvm' should fall back to using LVM1 binaries if
+   device-mapper is missing from the kernel */
+/* #undef LVM1_FALLBACK */
+
+/* Define to 1 to include built-in support for LVM1 metadata. */
+/* #undef LVM1_INTERNAL */
+
+/* Define to 1 to include built-in support for mirrors. */
+#define MIRRORED_INTERNAL 1
+
+/* The path to 'modprobe', if available. */
+/* #undef MODPROBE_CMD */
+
+/* Define to 1 to enable O_DIRECT support. */
+#define O_DIRECT_SUPPORT 1
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME ""
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING ""
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION ""
+
+/* Define to 1 to include built-in support for GFS pool metadata. */
+#define POOL_INTERNAL 1
+
+/* Define to 1 to include the LVM readline shell. */
+/* #undef READLINE_SUPPORT */
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to the type of arg 1 for `select'. */
+/* #undef SELECT_TYPE_ARG1 */
+
+/* Define to the type of args 2, 3 and 4 for `select'. */
+/* #undef SELECT_TYPE_ARG234 */
+
+/* Define to the type of arg 5 for `select'. */
+/* #undef SELECT_TYPE_ARG5 */
+
+/* Define to 1 to include built-in support for snapshots. */
+#define SNAPSHOT_INTERNAL 1
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at runtime.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown */
+/* #undef STACK_DIRECTION */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+/* #undef TM_IN_SYS_TIME */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to rpl_malloc if the replacement function should be used. */
+/* #undef malloc */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef mode_t */
+
+/* Define to `long int' if <sys/types.h> does not define. */
+/* #undef off_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef pid_t */
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define as `fork' if `vfork' does not work. */
+/* #undef vfork */
Index: src/external/gpl2/lvm2tools/dist/include/crc.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/crc.h
diff -N src/external/gpl2/lvm2tools/dist/include/crc.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/crc.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,25 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_CRC_H
+#define _LVM_CRC_H
+
+#define INITIAL_CRC 0xf597a6cf
+
+uint32_t calc_crc(uint32_t initial, const void *buf, uint32_t size);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/defaults.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/defaults.h
diff -N src/external/gpl2/lvm2tools/dist/include/defaults.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/defaults.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,131 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_DEFAULTS_H
+#define _LVM_DEFAULTS_H
+
+#define DEFAULT_ARCHIVE_ENABLED 1
+#define DEFAULT_BACKUP_ENABLED 1
+
+#define DEFAULT_ARCHIVE_SUBDIR "archive"
+#define DEFAULT_BACKUP_SUBDIR "backup"
+#define DEFAULT_CACHE_SUBDIR "cache"
+#define DEFAULT_CACHE_FILE_PREFIX ""
+
+#define DEFAULT_ARCHIVE_DAYS 30
+#define DEFAULT_ARCHIVE_NUMBER 10
+
+#define DEFAULT_SYS_DIR "/etc/lvm"
+#define DEFAULT_DEV_DIR "/dev"
+#define DEFAULT_PROC_DIR "/proc"
+#define DEFAULT_SYSFS_SCAN 1
+#define DEFAULT_MD_COMPONENT_DETECTION 1
+#define DEFAULT_MD_CHUNK_ALIGNMENT 1
+#define DEFAULT_IGNORE_SUSPENDED_DEVICES 1
+
+#define DEFAULT_LOCK_DIR "/var/lock/lvm"
+#define DEFAULT_LOCKING_LIB "liblvm2clusterlock.so"
+#define DEFAULT_FALLBACK_TO_LOCAL_LOCKING 1
+#define DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING 1
+
+#define DEFAULT_MIRRORLOG "disk"
+#define DEFAULT_MIRROR_LOG_FAULT_POLICY "allocate"
+#define DEFAULT_MIRROR_DEV_FAULT_POLICY "remove"
+#define DEFAULT_DMEVENTD_MIRROR_LIB "libdevmapper-event-lvm2mirror.so"
+#define DEFAULT_DMEVENTD_MONITOR 1
+
+#define DEFAULT_UMASK 0077
+
+#ifdef LVM1_FALLBACK
+#  define DEFAULT_FALLBACK_TO_LVM1 1
+#else
+#  define DEFAULT_FALLBACK_TO_LVM1 0
+#endif
+
+#ifdef LVM1_SUPPORT
+#  define DEFAULT_FORMAT "lvm1"
+#else
+#  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_READ_AHEAD "auto"
+#define DEFAULT_EXTENT_SIZE 4096	/* In KB */
+
+#define DEFAULT_MSG_PREFIX "  "
+#define DEFAULT_CMD_NAME 0
+#define DEFAULT_OVERWRITE 0
+
+#ifndef DEFAULT_LOG_FACILITY
+#  define DEFAULT_LOG_FACILITY LOG_USER
+#endif
+
+#define DEFAULT_SYSLOG 1
+#define DEFAULT_VERBOSE 0
+#define DEFAULT_LOGLEVEL 0
+#define DEFAULT_INDENT 1
+#define DEFAULT_UNITS "h"
+#define DEFAULT_SUFFIX 1
+#define DEFAULT_HOSTTAGS 0
+
+#ifdef DEVMAPPER_SUPPORT
+#  define DEFAULT_ACTIVATION 1
+#  define DEFAULT_RESERVED_MEMORY 8192
+#  define DEFAULT_RESERVED_STACK 256
+#  define DEFAULT_PROCESS_PRIORITY -18
+#else
+#  define DEFAULT_ACTIVATION 0
+#endif
+
+#define DEFAULT_STRIPE_FILLER "error"
+#define DEFAULT_MIRROR_REGION_SIZE 512	/* KB */
+#define DEFAULT_INTERVAL 15
+
+#ifdef READLINE_SUPPORT
+#  define DEFAULT_MAX_HISTORY 100
+#endif
+
+#define DEFAULT_REP_ALIGNED 1
+#define DEFAULT_REP_BUFFERED 1
+#define DEFAULT_REP_COLUMNS_AS_ROWS 0
+#define DEFAULT_REP_HEADINGS 1
+#define DEFAULT_REP_PREFIXES 0
+#define DEFAULT_REP_QUOTED 1
+#define DEFAULT_REP_SEPARATOR " "
+
+#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent,move_pv,mirror_log,copy_percent,convert_lv"
+#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_PVSEGS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size"
+
+#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,lv_kernel_major,lv_kernel_minor,origin,snap_percent,move_pv,copy_percent,mirror_log,convert_lv,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,dev_size,pv_uuid"
+#define DEFAULT_SEGS_COLS_VERB "lv_name,vg_name,lv_attr,seg_start,seg_size,stripes,segtype,stripesize,chunksize"
+#define DEFAULT_PVSEGS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size,lv_name,seg_start_pe,segtype,seg_pe_ranges"
+
+#define DEFAULT_LVS_SORT "vg_name,lv_name"
+#define DEFAULT_VGS_SORT "vg_name"
+#define DEFAULT_PVS_SORT "pv_name"
+#define DEFAULT_SEGS_SORT "vg_name,lv_name,seg_start"
+#define DEFAULT_PVSEGS_SORT "pv_name,pvseg_start"
+
+#endif				/* _LVM_DEFAULTS_H */
Index: src/external/gpl2/lvm2tools/dist/include/dev-cache.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/dev-cache.h
diff -N src/external/gpl2/lvm2tools/dist/include/dev-cache.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/dev-cache.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,57 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_DEV_CACHE_H
+#define _LVM_DEV_CACHE_H
+
+#include "device.h"
+
+/*
+ * predicate for devices.
+ */
+struct dev_filter {
+	int (*passes_filter) (struct dev_filter * f, struct device * dev);
+	void (*destroy) (struct dev_filter * f);
+	void *private;
+};
+
+/*
+ * The global device cache.
+ */
+struct cmd_context;
+int dev_cache_init(struct cmd_context *cmd);
+void dev_cache_exit(void);
+
+/* Trigger(1) or avoid(0) a scan */
+void dev_cache_scan(int do_scan);
+int dev_cache_has_scanned(void);
+
+int dev_cache_add_dir(const char *path);
+int dev_cache_add_loopfile(const char *path);
+struct device *dev_cache_get(const char *name, struct dev_filter *f);
+
+void dev_set_preferred_name(struct str_list *sl, struct device *dev);
+
+/*
+ * Object for iterating through the cache.
+ */
+struct dev_iter;
+struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan);
+void dev_iter_destroy(struct dev_iter *iter);
+struct device *dev_iter_get(struct dev_iter *iter);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/device.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/device.h
diff -N src/external/gpl2/lvm2tools/dist/include/device.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/device.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,102 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_DEVICE_H
+#define _LVM_DEVICE_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	/* dm_malloc used */
+#define DEV_OPENED_RW		0x00000008	/* Opened RW */
+#define DEV_OPENED_EXCL		0x00000010	/* Opened EXCL */
+#define DEV_O_DIRECT		0x00000020	/* Use O_DIRECT */
+#define DEV_O_DIRECT_TESTED	0x00000040	/* DEV_O_DIRECT is reliable */
+
+/*
+ * All devices in LVM will be represented by one of these.
+ * pointer comparisons are valid.
+ */
+struct device {
+	struct dm_list aliases;	/* struct str_list from lvm-types.h */
+	dev_t dev;
+
+	/* private */
+	int fd;
+	int open_count;
+	int block_size;
+	uint32_t flags;
+	uint64_t end;
+	struct dm_list open_list;
+
+	char pvid[ID_LEN + 1];
+	char _padding[7];
+};
+
+struct device_list {
+	struct dm_list list;
+	struct device *dev;
+};
+
+struct device_area {
+	struct device *dev;
+	uint64_t start;		/* Bytes */
+	uint64_t size;		/* Bytes */
+};
+
+/*
+ * All io should use these routines.
+ */
+int dev_get_size(const struct device *dev, uint64_t *size);
+int dev_get_sectsize(struct device *dev, uint32_t *size);
+
+/* 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 direct, int quiet);
+int dev_close(struct device *dev);
+int dev_close_immediate(struct device *dev);
+void dev_close_all(void);
+int dev_test_excl(struct device *dev);
+
+int dev_fd(struct device *dev);
+const char *dev_name(const struct device *dev);
+
+int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer);
+int dev_read_circular(struct device *dev, uint64_t offset, size_t len,
+		      uint64_t offset2, size_t len2, void *buf);
+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_set(struct device *dev, uint64_t offset, size_t len, int value);
+void dev_flush(struct device *dev);
+
+struct device *dev_create_file(const char *filename, struct device *dev,
+			       struct str_list *alias, int use_malloc);
+
+/* Return a valid device name from the alias list; NULL otherwise */
+const char *dev_name_confirmed(struct device *dev, int quiet);
+
+/* Does device contain md superblock?  If so, where? */
+int dev_is_md(struct device *dev, uint64_t *sb);
+unsigned long dev_md_chunk_size(const char *sysfs_dir, struct device *dev);
+
+int is_partitioned_dev(struct device *dev);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/display.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/display.h
diff -N src/external/gpl2/lvm2tools/dist/include/display.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/display.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,66 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_DISPLAY_H
+#define _LVM_DISPLAY_H
+
+#include "metadata-exported.h"
+#include "locking.h"
+
+#include <stdint.h>
+
+uint64_t units_to_bytes(const char *units, char *unit_type);
+
+/* Specify size in KB */
+const char *display_size(const struct cmd_context *cmd, uint64_t size);
+const char *display_size_long(const struct cmd_context *cmd, uint64_t size);
+const char *display_size_units(const struct cmd_context *cmd, uint64_t size);
+
+char *display_uuid(char *uuidstr);
+void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre);
+
+void pvdisplay_colons(const struct physical_volume *pv);
+void pvdisplay_segments(const struct physical_volume *pv);
+void pvdisplay_full(const struct cmd_context *cmd,
+		    const struct physical_volume *pv,
+		    void *handle);
+int pvdisplay_short(const struct cmd_context *cmd,
+		    const struct volume_group *vg,
+		    const struct physical_volume *pv, void *handle);
+
+void lvdisplay_colons(const struct logical_volume *lv);
+int lvdisplay_segments(const struct logical_volume *lv);
+int lvdisplay_full(struct cmd_context *cmd, const struct logical_volume *lv,
+		   void *handle);
+
+void vgdisplay_extents(const struct volume_group *vg);
+void vgdisplay_full(const struct volume_group *vg);
+void vgdisplay_colons(const struct volume_group *vg);
+void vgdisplay_short(const struct volume_group *vg);
+
+void display_formats(const struct cmd_context *cmd);
+void display_segtypes(const struct cmd_context *cmd);
+
+/*
+ * Allocation policy display conversion routines.
+ */
+const char *get_alloc_string(alloc_policy_t alloc);
+alloc_policy_t get_alloc_from_string(const char *str);
+
+char yes_no_prompt(const char *prompt, ...);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/dm-ioctl.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/dm-ioctl.h
diff -N src/external/gpl2/lvm2tools/dist/include/dm-ioctl.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/dm-ioctl.h	13 Dec 2008 14:39:32 -0000	1.1.1.1.2.3
@@ -0,0 +1,306 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001 - 2003 Sistina Software (UK) Limited.
+ * Copyright (C) 2004 - 2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is released under the LGPL.
+ */
+
+#ifndef _LINUX_DM_IOCTL_V4_H
+#define _LINUX_DM_IOCTL_V4_H
+
+#ifdef linux
+#  include <linux/types.h>
+#endif
+
+#define DM_DIR "mapper"		/* Slashes not supported */
+#define DM_MAX_TYPE_NAME 16
+#define DM_NAME_LEN 128
+#define DM_UUID_LEN 129
+
+/*
+ * A traditional ioctl interface for the device mapper.
+ *
+ * Each device can have two tables associated with it, an
+ * 'active' table which is the one currently used by io passing
+ * through the device, and an 'inactive' one which is a table
+ * that is being prepared as a replacement for the 'active' one.
+ *
+ * DM_VERSION:
+ * Just get the version information for the ioctl interface.
+ *
+ * DM_REMOVE_ALL:
+ * Remove all dm devices, destroy all tables.  Only really used
+ * for debug.
+ *
+ * DM_LIST_DEVICES:
+ * Get a list of all the dm device names.
+ *
+ * DM_DEV_CREATE:
+ * Create a new device, neither the 'active' or 'inactive' table
+ * slots will be filled.  The device will be in suspended state
+ * after creation, however any io to the device will get errored
+ * since it will be out-of-bounds.
+ *
+ * DM_DEV_REMOVE:
+ * Remove a device, destroy any tables.
+ *
+ * DM_DEV_RENAME:
+ * Rename a device.
+ *
+ * DM_SUSPEND:
+ * This performs both suspend and resume, depending which flag is
+ * passed in.
+ * Suspend: This command will not return until all pending io to
+ * the device has completed.  Further io will be deferred until
+ * the device is resumed.
+ * Resume: It is no longer an error to issue this command on an
+ * unsuspended device.  If a table is present in the 'inactive'
+ * slot, it will be moved to the active slot, then the old table
+ * from the active slot will be _destroyed_.  Finally the device
+ * is resumed.
+ *
+ * DM_DEV_STATUS:
+ * Retrieves the status for the table in the 'active' slot.
+ *
+ * DM_DEV_WAIT:
+ * Wait for a significant event to occur to the device.  This
+ * could either be caused by an event triggered by one of the
+ * targets of the table in the 'active' slot, or a table change.
+ *
+ * DM_TABLE_LOAD:
+ * Load a table into the 'inactive' slot for the device.  The
+ * device does _not_ need to be suspended prior to this command.
+ *
+ * DM_TABLE_CLEAR:
+ * Destroy any table in the 'inactive' slot (ie. abort).
+ *
+ * DM_TABLE_DEPS:
+ * Return a set of device dependencies for the 'active' table.
+ *
+ * DM_TABLE_STATUS:
+ * Return the targets status for the 'active' table.
+ *
+ * DM_TARGET_MSG:
+ * Pass a message string to the target at a specific offset of a device.
+ *
+ * DM_DEV_SET_GEOMETRY:
+ * Set the geometry of a device by passing in a string in this format:
+ *
+ * "cylinders heads sectors_per_track start_sector"
+ *
+ * Beware that CHS geometry is nearly obsolete and only provided
+ * for compatibility with dm devices that can be booted by a PC
+ * BIOS.  See struct hd_geometry for range limits.  Also note that
+ * the geometry is erased if the device size changes.
+ */
+
+/*
+ * All ioctl arguments consist of a single chunk of memory, with
+ * this structure at the start.  If a uuid is specified any
+ * lookup (eg. for a DM_INFO) will be done on that, *not* the
+ * name.
+ */
+struct dm_ioctl {
+	/*
+	 * The version number is made up of three parts:
+	 * major - no backward or forward compatibility,
+	 * minor - only backwards compatible,
+	 * patch - both backwards and forwards compatible.
+	 *
+	 * All clients of the ioctl interface should fill in the
+	 * version number of the interface that they were
+	 * compiled with.
+	 *
+	 * All recognised ioctl commands (ie. those that don't
+	 * return -ENOTTY) fill out this field, even if the
+	 * command failed.
+	 */
+	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 */
+
+	uint32_t target_count;	/* in/out */
+	int32_t open_count;	/* out */
+	uint32_t flags;		/* in/out */
+	uint32_t event_nr;      	/* in/out */
+	uint32_t padding;
+
+	uint64_t dev;		/* in/out */
+
+	char name[DM_NAME_LEN];	/* device name */
+	char uuid[DM_UUID_LEN];	/* unique identifier for
+				 * the block device */
+	char data[7];		/* padding or data */
+};
+
+/*
+ * Used to specify tables.  These structures appear after the
+ * dm_ioctl.
+ */
+struct dm_target_spec {
+	uint64_t sector_start;
+	uint64_t length;
+	int32_t status;		/* used when reading from kernel only */
+
+	/*
+	 * Location of the next dm_target_spec.
+	 * - When specifying targets on a DM_TABLE_LOAD command, this value is
+	 *   the number of bytes from the start of the "current" dm_target_spec
+	 *   to the start of the "next" dm_target_spec.
+	 * - When retrieving targets on a DM_TABLE_STATUS command, this value
+	 *   is the number of bytes from the start of the first dm_target_spec
+	 *   (that follows the dm_ioctl struct) to the start of the "next"
+	 *   dm_target_spec.
+	 */
+	uint32_t next;
+
+	char target_type[DM_MAX_TYPE_NAME];
+
+	/*
+	 * Parameter string starts immediately after this object.
+	 * Be careful to add padding after string to ensure correct
+	 * alignment of subsequent dm_target_spec.
+	 */
+};
+
+/*
+ * Used to retrieve the target dependencies.
+ */
+struct dm_target_deps {
+	uint32_t count;	/* Array size */
+	uint32_t padding;	/* unused */
+	uint64_t dev[0];	/* out */
+};
+
+/*
+ * Used to get a list of all dm devices.
+ */
+struct dm_name_list {
+	uint64_t dev;
+	uint32_t next;		/* offset to the next record from
+				   the _start_ of this */
+	char name[0];
+};
+
+/*
+ * Used to retrieve the target versions
+ */
+struct dm_target_versions {
+        uint32_t next;
+        uint32_t version[3];
+
+        char name[0];
+};
+
+/*
+ * Used to pass message to a target
+ */
+struct dm_target_msg {
+	uint64_t sector;	/* Device sector */
+
+	char message[0];
+};
+
+/*
+ * If you change this make sure you make the corresponding change
+ * to dm-ioctl.c:lookup_ioctl()
+ */
+enum {
+	/* Top level cmds */
+	DM_VERSION_CMD = 0,
+	DM_REMOVE_ALL_CMD,
+	DM_LIST_DEVICES_CMD,
+
+	/* device level cmds */
+	DM_DEV_CREATE_CMD,
+	DM_DEV_REMOVE_CMD,
+	DM_DEV_RENAME_CMD,
+	DM_DEV_SUSPEND_CMD,
+	DM_DEV_STATUS_CMD,
+	DM_DEV_WAIT_CMD,
+
+	/* Table level cmds */
+	DM_TABLE_LOAD_CMD,
+	DM_TABLE_CLEAR_CMD,
+	DM_TABLE_DEPS_CMD,
+	DM_TABLE_STATUS_CMD,
+
+	/* Added later */
+	DM_LIST_VERSIONS_CMD,
+	DM_TARGET_MSG_CMD,
+	DM_DEV_SET_GEOMETRY_CMD
+};
+
+#define DM_IOCTL 0xfd
+
+#define DM_VERSION       _IOWR(DM_IOCTL, DM_VERSION_CMD, struct dm_ioctl)
+#define DM_REMOVE_ALL    _IOWR(DM_IOCTL, DM_REMOVE_ALL_CMD, struct dm_ioctl)
+#define DM_LIST_DEVICES  _IOWR(DM_IOCTL, DM_LIST_DEVICES_CMD, struct dm_ioctl)
+
+#define DM_DEV_CREATE    _IOWR(DM_IOCTL, DM_DEV_CREATE_CMD, struct dm_ioctl)
+#define DM_DEV_REMOVE    _IOWR(DM_IOCTL, DM_DEV_REMOVE_CMD, struct dm_ioctl)
+#define DM_DEV_RENAME    _IOWR(DM_IOCTL, DM_DEV_RENAME_CMD, struct dm_ioctl)
+#define DM_DEV_SUSPEND   _IOWR(DM_IOCTL, DM_DEV_SUSPEND_CMD, struct dm_ioctl)
+#define DM_DEV_STATUS    _IOWR(DM_IOCTL, DM_DEV_STATUS_CMD, struct dm_ioctl)
+#define DM_DEV_WAIT      _IOWR(DM_IOCTL, DM_DEV_WAIT_CMD, struct dm_ioctl)
+
+#define DM_TABLE_LOAD    _IOWR(DM_IOCTL, DM_TABLE_LOAD_CMD, struct dm_ioctl)
+#define DM_TABLE_CLEAR   _IOWR(DM_IOCTL, DM_TABLE_CLEAR_CMD, struct dm_ioctl)
+#define DM_TABLE_DEPS    _IOWR(DM_IOCTL, DM_TABLE_DEPS_CMD, struct dm_ioctl)
+#define DM_TABLE_STATUS  _IOWR(DM_IOCTL, DM_TABLE_STATUS_CMD, struct dm_ioctl)
+
+#define DM_LIST_VERSIONS _IOWR(DM_IOCTL, DM_LIST_VERSIONS_CMD, struct dm_ioctl)
+
+#define DM_TARGET_MSG	 _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, struct dm_ioctl)
+#define DM_DEV_SET_GEOMETRY	_IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
+
+#define DM_VERSION_MAJOR	4
+#define DM_VERSION_MINOR	14
+#define DM_VERSION_PATCHLEVEL	0
+#define DM_VERSION_EXTRA	"-ioctl (2008-04-23)"
+
+/* Status bits */
+#define DM_READONLY_FLAG	(1 << 0) /* In/Out */
+#define DM_SUSPEND_FLAG		(1 << 1) /* In/Out */
+#define DM_PERSISTENT_DEV_FLAG	(1 << 3) /* In */
+
+/*
+ * Flag passed into ioctl STATUS command to get table information
+ * rather than current status.
+ */
+#define DM_STATUS_TABLE_FLAG	(1 << 4) /* In */
+
+/*
+ * Flags that indicate whether a table is present in either of
+ * the two table slots that a device has.
+ */
+#define DM_ACTIVE_PRESENT_FLAG   (1 << 5) /* Out */
+#define DM_INACTIVE_PRESENT_FLAG (1 << 6) /* Out */
+
+/*
+ * Indicates that the buffer passed in wasn't big enough for the
+ * results.
+ */
+#define DM_BUFFER_FULL_FLAG	(1 << 8) /* Out */
+
+/*
+ * This flag is now ignored.
+ */
+#define DM_SKIP_BDGET_FLAG	(1 << 9) /* In */
+
+/*
+ * Set this to avoid attempting to freeze any filesystem when suspending.
+ */
+#define DM_SKIP_LOCKFS_FLAG	(1 << 10) /* In */
+
+/*
+ * Set this to suspend without flushing queued ios.
+ */
+#define DM_NOFLUSH_FLAG		(1 << 11) /* In */
+
+#endif				/* _LINUX_DM_IOCTL_H */
Index: src/external/gpl2/lvm2tools/dist/include/dm-logging.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/dm-logging.h
diff -N src/external/gpl2/lvm2tools/dist/include/dm-logging.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/dm-logging.h	13 Dec 2008 14:39:32 -0000	1.1.1.1.2.3
@@ -0,0 +1,29 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _DM_LOGGING_H
+#define _DM_LOGGING_H
+
+#include "libdevmapper.h"
+
+extern dm_log_fn dm_log;
+
+#define plog(l, x...) dm_log(l, __FILE__, __LINE__, ## x)
+
+#include "log.h"
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/dmlib.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/dmlib.h
diff -N src/external/gpl2/lvm2tools/dist/include/dmlib.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/dmlib.h	13 Dec 2008 14:39:32 -0000	1.1.1.1.2.3
@@ -0,0 +1,28 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * This file must be included first by every device-mapper library source file.
+ */
+#ifndef _DM_LIB_H
+#define _DM_LIB_H
+
+#define DM
+
+#include "lib.h"
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/errors.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/errors.h
diff -N src/external/gpl2/lvm2tools/dist/include/errors.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/errors.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,26 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_ERRORS_H
+#define _LVM_ERRORS_H
+
+#define ECMD_PROCESSED		1
+#define ENO_SUCH_CMD		2
+#define EINVALID_CMD_LINE	3
+#define ECMD_FAILED		5
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/filter-composite.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/filter-composite.h
diff -N src/external/gpl2/lvm2tools/dist/include/filter-composite.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/filter-composite.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,25 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_FILTER_COMPOSITE_H
+#define _LVM_FILTER_COMPOSITE_H
+
+#include "dev-cache.h"
+
+struct dev_filter *composite_filter_create(int n, struct dev_filter **filters);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/filter-md.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/filter-md.h
diff -N src/external/gpl2/lvm2tools/dist/include/filter-md.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/filter-md.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,25 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2004 Luca Berra
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_FILTER_MD_H
+#define _LVM_FILTER_MD_H
+
+#include "dev-cache.h"
+
+struct dev_filter *md_filter_create(void);
+
+#endif
+
Index: src/external/gpl2/lvm2tools/dist/include/filter-persistent.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/filter-persistent.h
diff -N src/external/gpl2/lvm2tools/dist/include/filter-persistent.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/filter-persistent.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,30 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_FILTER_PERSISTENT_H
+#define _LVM_FILTER_PERSISTENT_H
+
+#include "dev-cache.h"
+
+struct dev_filter *persistent_filter_create(struct dev_filter *f,
+					    const char *file);
+
+int persistent_filter_wipe(struct dev_filter *f);
+int persistent_filter_load(struct dev_filter *f, struct config_tree **cft_out);
+int persistent_filter_dump(struct dev_filter *f);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/filter-regex.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/filter-regex.h
diff -N src/external/gpl2/lvm2tools/dist/include/filter-regex.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/filter-regex.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,34 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_FILTER_REGEX_H
+#define _LVM_FILTER_REGEX_H
+
+#include "config.h"
+#include "dev-cache.h"
+
+/*
+ * patterns must be an array of strings of the form:
+ * [ra]<sep><regex><sep>, eg,
+ * r/cdrom/          - reject cdroms
+ * a|loop/[0-4]|     - accept loops 0 to 4
+ * r|.*|             - reject everything else
+ */
+
+struct dev_filter *regex_filter_create(struct config_value *patterns);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/filter-sysfs.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/filter-sysfs.h
diff -N src/external/gpl2/lvm2tools/dist/include/filter-sysfs.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/filter-sysfs.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,25 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_FILTER_SYSFS_H
+#define _LVM_FILTER_SYSFS_H
+
+#include "config.h"
+#include "dev-cache.h"
+
+struct dev_filter *sysfs_filter_create(const char *sysfs_dir);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/filter.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/filter.h
diff -N src/external/gpl2/lvm2tools/dist/include/filter.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/filter.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,43 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_FILTER_H
+#define _LVM_FILTER_H
+
+#include "config.h"
+
+#include <sys/stat.h>
+
+#ifdef linux
+#  define MAJOR(dev)	((dev & 0xfff00) >> 8)
+#  define MINOR(dev)	((dev & 0xff) | ((dev >> 12) & 0xfff00))
+#  define MKDEV(ma,mi)	((mi & 0xff) | (ma << 8) | ((mi & ~0xff) << 12))
+#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,
+					  const struct config_node *cn);
+
+void lvm_type_filter_destroy(struct dev_filter *f);
+
+int md_major(void);
+int max_partitions(int major);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/format-text.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/format-text.h
diff -N src/external/gpl2/lvm2tools/dist/include/format-text.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/format-text.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,69 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_FORMAT_TEXT_H
+#define _LVM_FORMAT_TEXT_H
+
+#include "lvm-types.h"
+#include "metadata.h"
+
+#define FMT_TEXT_NAME "lvm2"
+#define FMT_TEXT_ALIAS "text"
+#define FMT_TEXT_ORPHAN_VG_NAME ORPHAN_VG_NAME(FMT_TEXT_NAME)
+
+/*
+ * Archives a vg config.  'retain_days' is the minimum number of
+ * days that an archive file must be held for.  'min_archives' is
+ * the minimum number of archives required to be kept for each
+ * volume group.
+ */
+int archive_vg(struct volume_group *vg,
+	       const char *dir,
+	       const char *desc, uint32_t retain_days, uint32_t min_archive);
+
+/*
+ * Displays a list of vg backups in a particular archive directory.
+ */
+int archive_list(struct cmd_context *cmd, const char *dir, const char *vgname);
+int archive_list_file(struct cmd_context *cmd, const char *file);
+int backup_list(struct cmd_context *cmd, const char *dir, const char *vgname);
+
+/*
+ * The text format can read and write a volume_group to a file.
+ */
+struct format_type *create_text_format(struct cmd_context *cmd);
+void *create_text_context(struct cmd_context *cmd, const char *path,
+			  const char *desc);
+
+struct labeller *text_labeller_create(const struct format_type *fmt);
+
+int pvhdr_read(struct device *dev, char *buf);
+
+int add_da(struct dm_pool *mem, struct dm_list *das,
+	   uint64_t start, uint64_t size);
+void del_das(struct dm_list *das);
+
+int add_mda(const struct format_type *fmt, struct dm_pool *mem, struct dm_list *mdas,
+	    struct device *dev, uint64_t start, uint64_t size);
+void del_mdas(struct dm_list *mdas);
+
+const char *vgname_from_mda(const struct format_type *fmt,
+			    struct device_area *dev_area, struct id *vgid,
+			    uint32_t *vgstatus, char **creation_host,
+			    uint64_t *mda_free_sectors);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/format1.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/format1.h
diff -N src/external/gpl2/lvm2tools/dist/include/format1.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/format1.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,31 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_FORMAT1_H
+#define _LVM_FORMAT1_H
+
+#include "metadata.h"
+#include "lvmcache.h"
+
+#define FMT_LVM1_NAME "lvm1"
+#define FMT_LVM1_ORPHAN_VG_NAME ORPHAN_VG_NAME(FMT_LVM1_NAME)
+
+#ifdef LVM1_INTERNAL
+struct format_type *init_lvm1_format(struct cmd_context *cmd);
+#endif
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/format_pool.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/format_pool.h
diff -N src/external/gpl2/lvm2tools/dist/include/format_pool.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/format_pool.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,30 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_FORMAT_POOL_H
+#define _LVM_FORMAT_POOL_H
+
+#include "metadata.h"
+
+#define FMT_POOL_NAME "pool"
+#define FMT_POOL_ORPHAN_VG_NAME ORPHAN_VG_NAME(FMT_POOL_NAME)
+
+#ifdef POOL_INTERNAL
+struct format_type *init_pool_format(struct cmd_context *cmd);
+#endif
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/intl.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/intl.h
diff -N src/external/gpl2/lvm2tools/dist/include/intl.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/intl.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,28 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_INTL_H
+#define _LVM_INTL_H
+
+#ifdef INTL_PACKAGE
+#  include <libintl.h>
+#  define _(String) dgettext(INTL_PACKAGE, (String))
+#else
+#  define _(String) (String)
+#endif
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/kdev_t.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/kdev_t.h
diff -N src/external/gpl2/lvm2tools/dist/include/kdev_t.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/kdev_t.h	13 Dec 2008 14:39:32 -0000	1.1.1.1.2.3
@@ -0,0 +1,24 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LIBDM_KDEV_H
+#define _LIBDM_KDEV_H
+
+#define MAJOR(dev)      ((dev & 0xfff00) >> 8)
+#define MINOR(dev)      ((dev & 0xff) | ((dev >> 12) & 0xfff00))
+#define MKDEV(ma,mi)    ((mi & 0xff) | (ma << 8) | ((mi & ~0xff) << 12))
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/label.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/label.h
diff -N src/external/gpl2/lvm2tools/dist/include/label.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/label.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,108 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_LABEL_H
+#define _LVM_LABEL_H
+
+#include "uuid.h"
+#include "device.h"
+
+#define LABEL_ID "LABELONE"
+#define LABEL_SIZE SECTOR_SIZE	/* Think very carefully before changing this */
+#define LABEL_SCAN_SECTORS 4L
+#define LABEL_SCAN_SIZE (LABEL_SCAN_SECTORS << SECTOR_SHIFT)
+
+struct labeller;
+
+/* On disk - 32 bytes */
+struct label_header {
+	int8_t id[8];		/* LABELONE */
+	uint64_t sector_xl;	/* Sector number of this label */
+	uint32_t crc_xl;	/* From next field to end of sector */
+	uint32_t offset_xl;	/* Offset from start of struct to contents */
+	int8_t type[8];		/* LVM2 001 */
+} __attribute__ ((packed));
+
+/* In core */
+struct label {
+	char type[8];
+	uint64_t sector;
+	struct labeller *labeller;
+	void *info;
+};
+
+struct labeller;
+
+struct label_ops {
+	/*
+	 * Is the device labelled with this format ?
+	 */
+	int (*can_handle) (struct labeller * l, void *buf, uint64_t sector);
+
+	/*
+	 * Write a label to a volume.
+	 */
+	int (*write) (struct label * label, void *buf);
+
+	/*
+	 * Read a label from a volume.
+	 */
+	int (*read) (struct labeller * l, struct device * dev,
+		     void *buf, struct label ** label);
+
+	/*
+	 * Additional consistency checks for the paranoid.
+	 */
+	int (*verify) (struct labeller * l, void *buf, uint64_t sector);
+
+	/*
+	 * Populate label_type etc.
+	 */
+	int (*initialise_label) (struct labeller * l, struct label * label);
+
+	/*
+	 * Destroy a previously read label.
+	 */
+	void (*destroy_label) (struct labeller * l, struct label * label);
+
+	/*
+	 * Destructor.
+	 */
+	void (*destroy) (struct labeller * l);
+};
+
+struct labeller {
+	struct label_ops *ops;
+	const void *private;
+};
+
+int label_init(void);
+void label_exit(void);
+
+int label_register_handler(const char *name, struct labeller *handler);
+
+struct labeller *label_get_handler(const char *name);
+
+int label_remove(struct device *dev);
+int label_read(struct device *dev, struct label **result,
+		uint64_t scan_sector);
+int label_write(struct device *dev, struct label *label);
+int label_verify(struct device *dev);
+struct label *label_create(struct labeller *labeller);
+void label_destroy(struct label *label);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/last-path-component.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/last-path-component.h
diff -N src/external/gpl2/lvm2tools/dist/include/last-path-component.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/last-path-component.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,30 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Return the address of the last file name component of NAME.
+ * If NAME ends in a slash, return the empty string.
+ */
+
+#include <string.h>
+
+static inline char *last_path_component(char const *name)
+{
+	char const *slash = strrchr(name, '/');
+	char const *res = slash ? slash + 1 : name;
+
+	return (char *)res;
+}
Index: src/external/gpl2/lvm2tools/dist/include/lib.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/lib.h
diff -N src/external/gpl2/lvm2tools/dist/include/lib.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/lib.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,50 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * This file must be included first by every library source file.
+ */
+#ifndef _LVM_LIB_H
+#define _LVM_LIB_H
+
+#include "configure.h"
+
+#define _REENTRANT
+#define _GNU_SOURCE
+#define _FILE_OFFSET_BITS 64
+
+#include "intl.h"
+#include "libdevmapper.h"
+#include "lvm-globals.h"
+#include "lvm-wrappers.h"
+#include "lvm-types.h"
+#include "util.h"
+
+#ifdef DM
+#  include "dm-logging.h"
+#else
+#  include "lvm-logging.h"
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/libdevmapper-event.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/libdevmapper-event.h
diff -N src/external/gpl2/lvm2tools/dist/include/libdevmapper-event.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/libdevmapper-event.h	13 Dec 2008 14:39:32 -0000	1.1.1.1.2.3
@@ -0,0 +1,108 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Note that this file is released only as part of a technology preview
+ * and its contents may change in future updates in ways that do not
+ * preserve compatibility.
+ */
+
+#ifndef LIB_DMEVENT_H
+#define LIB_DMEVENT_H
+
+#include <stdint.h>
+
+/*
+ * Event library interface.
+ */
+
+enum dm_event_mask {
+	DM_EVENT_SETTINGS_MASK  = 0x0000FF,
+	DM_EVENT_SINGLE		= 0x000001, /* Report multiple errors just once. */
+	DM_EVENT_MULTI		= 0x000002, /* Report all of them. */
+
+	DM_EVENT_ERROR_MASK     = 0x00FF00,
+	DM_EVENT_SECTOR_ERROR	= 0x000100, /* Failure on a particular sector. */
+	DM_EVENT_DEVICE_ERROR	= 0x000200, /* Device failure. */
+	DM_EVENT_PATH_ERROR	= 0x000400, /* Failure on an io path. */
+	DM_EVENT_ADAPTOR_ERROR	= 0x000800, /* Failure of a host adaptor. */
+
+	DM_EVENT_STATUS_MASK    = 0xFF0000,
+	DM_EVENT_SYNC_STATUS	= 0x010000, /* Mirror synchronization completed/failed. */
+	DM_EVENT_TIMEOUT	= 0x020000, /* Timeout has occured */
+
+	DM_EVENT_REGISTRATION_PENDING = 0x1000000, /* Monitor thread is setting-up/shutting-down */
+};
+
+#define DM_EVENT_ALL_ERRORS DM_EVENT_ERROR_MASK
+
+struct dm_event_handler;
+
+struct dm_event_handler *dm_event_handler_create(void);
+void dm_event_handler_destroy(struct dm_event_handler *dmevh);
+
+/*
+ * Path of shared library to handle events.
+ *
+ * All of dso, device_name and uuid strings are duplicated, you do not
+ * need to keep the pointers valid after the call succeeds. Thes may
+ * return -ENOMEM though.
+ */
+int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path);
+
+/*
+ * Identify the device to monitor by exactly one of device_name, uuid or
+ * device number. String arguments are duplicated, see above.
+ */
+int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *device_name);
+
+int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid);
+
+void dm_event_handler_set_major(struct dm_event_handler *dmevh, int major);
+void dm_event_handler_set_minor(struct dm_event_handler *dmevh, int minor);
+void dm_event_handler_set_timeout(struct dm_event_handler *dmevh, int timeout);
+
+/*
+ * Specify mask for events to monitor.
+ */
+void dm_event_handler_set_event_mask(struct dm_event_handler *dmevh,
+				     enum dm_event_mask evmask);
+
+const char *dm_event_handler_get_dso(const struct dm_event_handler *dmevh);
+const char *dm_event_handler_get_dev_name(const struct dm_event_handler *dmevh);
+const char *dm_event_handler_get_uuid(const struct dm_event_handler *dmevh);
+int dm_event_handler_get_major(const struct dm_event_handler *dmevh);
+int dm_event_handler_get_minor(const struct dm_event_handler *dmevh);
+int dm_event_handler_get_timeout(const struct dm_event_handler *dmevh);
+enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler *dmevh);
+
+/* FIXME Review interface (what about this next thing?) */
+int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next);
+
+/*
+ * Initiate monitoring using dmeventd.
+ */
+int dm_event_register_handler(const struct dm_event_handler *dmevh);
+int dm_event_unregister_handler(const struct dm_event_handler *dmevh);
+
+/* Prototypes for DSO interface, see dmeventd.c, struct dso_data for
+   detailed descriptions. */
+void process_event(struct dm_task *dmt, enum dm_event_mask evmask, void **user);
+int register_device(const char *device_name, const char *uuid, int major, int minor, void **user);
+int unregister_device(const char *device_name, const char *uuid, int major,
+		      int minor, void **user);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/libdevmapper.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/libdevmapper.h
diff -N src/external/gpl2/lvm2tools/dist/include/libdevmapper.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/libdevmapper.h	13 Dec 2008 14:39:32 -0000	1.1.1.1.2.3
@@ -0,0 +1,981 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef LIB_DEVICE_MAPPER_H
+#define LIB_DEVICE_MAPPER_H
+
+#include <inttypes.h>
+#include <stdarg.h>
+#include <sys/types.h>
+
+#ifdef linux
+#  include <linux/types.h>
+#endif
+
+#include <limits.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/*****************************************************************
+ * The first section of this file provides direct access to the 
+ * individual device-mapper ioctls.
+ ****************************************************************/
+
+/*
+ * Since it is quite laborious to build the ioctl
+ * arguments for the device-mapper people are
+ * encouraged to use this library.
+ *
+ * You will need to build a struct dm_task for
+ * each ioctl command you want to execute.
+ */
+
+typedef void (*dm_log_fn) (int level, const char *file, int line,
+			   const char *f, ...)
+    __attribute__ ((format(printf, 4, 5)));
+
+/*
+ * The library user may wish to register their own
+ * logging function, by default errors go to stderr.
+ * Use dm_log_init(NULL) to restore the default log fn.
+ */
+void dm_log_init(dm_log_fn fn);
+void dm_log_init_verbose(int level);
+
+enum {
+	DM_DEVICE_CREATE,
+	DM_DEVICE_RELOAD,
+	DM_DEVICE_REMOVE,
+	DM_DEVICE_REMOVE_ALL,
+
+	DM_DEVICE_SUSPEND,
+	DM_DEVICE_RESUME,
+
+	DM_DEVICE_INFO,
+	DM_DEVICE_DEPS,
+	DM_DEVICE_RENAME,
+
+	DM_DEVICE_VERSION,
+
+	DM_DEVICE_STATUS,
+	DM_DEVICE_TABLE,
+	DM_DEVICE_WAITEVENT,
+
+	DM_DEVICE_LIST,
+
+	DM_DEVICE_CLEAR,
+
+	DM_DEVICE_MKNODES,
+
+	DM_DEVICE_LIST_VERSIONS,
+	
+	DM_DEVICE_TARGET_MSG,
+
+	DM_DEVICE_SET_GEOMETRY
+};
+
+struct dm_task;
+
+struct dm_task *dm_task_create(int type);
+void dm_task_destroy(struct dm_task *dmt);
+
+int dm_task_set_name(struct dm_task *dmt, const char *name);
+int dm_task_set_uuid(struct dm_task *dmt, const char *uuid);
+
+/*
+ * Retrieve attributes after an info.
+ */
+struct dm_info {
+	int exists;
+	int suspended;
+	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 */
+
+	int32_t target_count;
+};
+
+struct dm_deps {
+	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];
+};
+
+struct dm_versions {
+	uint32_t next;		/* Offset to next struct from start of this struct */
+	uint32_t version[3];
+
+	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(const struct dm_task *dmt);
+const char *dm_task_get_uuid(const 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);
+struct dm_versions *dm_task_get_versions(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_uid(struct dm_task *dmt, uid_t uid);
+int dm_task_set_gid(struct dm_task *dmt, gid_t gid);
+int dm_task_set_mode(struct dm_task *dmt, mode_t mode);
+int dm_task_set_event_nr(struct dm_task *dmt, uint32_t event_nr);
+int dm_task_set_geometry(struct dm_task *dmt, const char *cylinders, const char *heads, const char *sectors, const char *start);
+int dm_task_set_message(struct dm_task *dmt, const char *message);
+int dm_task_set_sector(struct dm_task *dmt, uint64_t sector);
+int dm_task_no_flush(struct dm_task *dmt);
+int dm_task_no_open_count(struct dm_task *dmt);
+int dm_task_skip_lockfs(struct dm_task *dmt);
+int dm_task_suppress_identical_reload(struct dm_task *dmt);
+
+/*
+ * Control read_ahead.
+ */
+#define DM_READ_AHEAD_AUTO UINT32_MAX	/* Use kernel default readahead */
+#define DM_READ_AHEAD_NONE 0		/* Disable readahead */
+
+#define DM_READ_AHEAD_MINIMUM_FLAG	0x1	/* Value supplied is minimum */
+
+/*
+ * Read ahead is set with DM_DEVICE_CREATE with a table or DM_DEVICE_RESUME.
+ */
+int dm_task_set_read_ahead(struct dm_task *dmt, uint32_t read_ahead,
+			   uint32_t read_ahead_flags);
+uint32_t dm_task_get_read_ahead(const struct dm_task *dmt,
+				uint32_t *read_ahead);
+
+/*
+ * Use these to prepare for a create or reload.
+ */
+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.
+ */
+#define DM_FORMAT_DEV_BUFSIZE	13	/* Minimum bufsize to handle worst case. */
+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,
+			 char **target_type, char **params);
+
+/*
+ * Call this to actually run the ioctl.
+ */
+int dm_task_run(struct dm_task *dmt);
+
+/*
+ * Call this to make or remove the device nodes associated with previously
+ * issued commands.
+ */
+void dm_task_update_nodes(void);
+
+/*
+ * Configure the device-mapper directory
+ */
+int dm_set_dev_dir(const char *dir);
+const char *dm_dir(void);
+
+/*
+ * Determine whether a major number belongs to device-mapper or not.
+ */
+int dm_is_dm_major(uint32_t major);
+
+/*
+ * Release library resources
+ */
+void dm_lib_release(void);
+void dm_lib_exit(void) __attribute((destructor));
+
+/*
+ * Use NULL for all devices.
+ */
+int dm_mknodes(const char *name);
+int dm_driver_version(char *version, size_t size);
+
+/******************************************************
+ * Functions to build and manipulate trees of devices *
+ ******************************************************/
+struct dm_tree;
+struct dm_tree_node;
+
+/*
+ * Initialise an empty dependency tree.
+ *
+ * The tree consists of a root node together with one node for each mapped 
+ * device which has child nodes for each device referenced in its table.
+ *
+ * Every node in the tree has one or more children and one or more parents.
+ *
+ * The root node is the parent/child of every node that doesn't have other 
+ * parents/children.
+ */
+struct dm_tree *dm_tree_create(void);
+void dm_tree_free(struct dm_tree *tree);
+
+/*
+ * Add nodes to the tree for a given device and all the devices it uses.
+ */
+int dm_tree_add_dev(struct dm_tree *tree, uint32_t major, uint32_t minor);
+
+/*
+ * Add a new node to the tree if it doesn't already exist.
+ */
+struct dm_tree_node *dm_tree_add_new_dev(struct dm_tree *tree,
+					 const char *name,
+					 const char *uuid,
+					 uint32_t major, uint32_t minor,
+					 int read_only,
+					 int clear_inactive,
+					 void *context);
+
+/*
+ * Search for a node in the tree.
+ * Set major and minor to 0 or uuid to NULL to get the root node.
+ */
+struct dm_tree_node *dm_tree_find_node(struct dm_tree *tree,
+					  uint32_t major,
+					  uint32_t minor);
+struct dm_tree_node *dm_tree_find_node_by_uuid(struct dm_tree *tree,
+						  const char *uuid);
+
+/*
+ * Use this to walk through all children of a given node.
+ * Set handle to NULL in first call.
+ * Returns NULL after the last child.
+ * Set inverted to use inverted tree.
+ */
+struct dm_tree_node *dm_tree_next_child(void **handle,
+					   struct dm_tree_node *parent,
+					   uint32_t inverted);
+
+/*
+ * Get properties of a node.
+ */
+const char *dm_tree_node_get_name(struct dm_tree_node *node);
+const char *dm_tree_node_get_uuid(struct dm_tree_node *node);
+const struct dm_info *dm_tree_node_get_info(struct dm_tree_node *node);
+void *dm_tree_node_get_context(struct dm_tree_node *node);
+
+/*
+ * Returns the number of children of the given node (excluding the root node).
+ * Set inverted for the number of parents.
+ */
+int dm_tree_node_num_children(struct dm_tree_node *node, uint32_t inverted);
+
+/*
+ * Deactivate a device plus all dependencies.
+ * Ignores devices that don't have a uuid starting with uuid_prefix.
+ */
+int dm_tree_deactivate_children(struct dm_tree_node *dnode,
+				   const char *uuid_prefix,
+				   size_t uuid_prefix_len);
+/*
+ * Preload/create a device plus all dependencies.
+ * Ignores devices that don't have a uuid starting with uuid_prefix.
+ */
+int dm_tree_preload_children(struct dm_tree_node *dnode,
+			     const char *uuid_prefix,
+			     size_t uuid_prefix_len);
+
+/*
+ * Resume a device plus all dependencies.
+ * Ignores devices that don't have a uuid starting with uuid_prefix.
+ */
+int dm_tree_activate_children(struct dm_tree_node *dnode,
+			      const char *uuid_prefix,
+			      size_t uuid_prefix_len);
+
+/*
+ * Suspend a device plus all dependencies.
+ * Ignores devices that don't have a uuid starting with uuid_prefix.
+ */
+int dm_tree_suspend_children(struct dm_tree_node *dnode,
+				   const char *uuid_prefix,
+				   size_t uuid_prefix_len);
+
+/*
+ * Skip the filesystem sync when suspending.
+ * Does nothing with other functions.
+ * Use this when no snapshots are involved.
+ */ 
+void dm_tree_skip_lockfs(struct dm_tree_node *dnode);
+
+/*
+ * Set the 'noflush' flag when suspending devices.
+ * If the kernel supports it, instead of erroring outstanding I/O that
+ * cannot be completed, the I/O is queued and resubmitted when the
+ * device is resumed.  This affects multipath devices when all paths
+ * have failed and queue_if_no_path is set, and mirror devices when
+ * block_on_error is set and the mirror log has failed.
+ */
+void dm_tree_use_no_flush_suspend(struct dm_tree_node *dnode);
+
+/*
+ * Is the uuid prefix present in the tree?
+ * Only returns 0 if every node was checked successfully.
+ * Returns 1 if the tree walk has to be aborted.
+ */
+int dm_tree_children_use_uuid(struct dm_tree_node *dnode,
+				 const char *uuid_prefix,
+				 size_t uuid_prefix_len);
+
+/*
+ * Construct tables for new nodes before activating them.
+ */
+int dm_tree_node_add_snapshot_origin_target(struct dm_tree_node *dnode,
+					       uint64_t size,
+					       const char *origin_uuid);
+int dm_tree_node_add_snapshot_target(struct dm_tree_node *node,
+					uint64_t size,
+					const char *origin_uuid,
+					const char *cow_uuid,
+					int persistent,
+					uint32_t chunk_size);
+int dm_tree_node_add_error_target(struct dm_tree_node *node,
+				     uint64_t size);
+int dm_tree_node_add_zero_target(struct dm_tree_node *node,
+				    uint64_t size);
+int dm_tree_node_add_linear_target(struct dm_tree_node *node,
+				      uint64_t size);
+int dm_tree_node_add_striped_target(struct dm_tree_node *node,
+				       uint64_t size,
+				       uint32_t stripe_size);
+int dm_tree_node_add_mirror_target(struct dm_tree_node *node,
+				      uint64_t size);
+ 
+/* Mirror log flags */
+#define DM_NOSYNC		0x00000001	/* Known already in sync */
+#define DM_FORCESYNC		0x00000002	/* Force resync */
+#define DM_BLOCK_ON_ERROR	0x00000004	/* On error, suspend I/O */
+#define DM_CORELOG		0x00000008	/* In-memory log */
+
+int dm_tree_node_add_mirror_target_log(struct dm_tree_node *node,
+					  uint32_t region_size,
+					  unsigned clustered,
+					  const char *log_uuid,
+					  unsigned area_count,
+					  uint32_t flags);
+int dm_tree_node_add_target_area(struct dm_tree_node *node,
+				    const char *dev_name,
+				    const char *dlid,
+				    uint64_t offset);
+
+/*
+ * Set readahead (in sectors) after loading the node.
+ */
+void dm_tree_node_set_read_ahead(struct dm_tree_node *dnode,
+				 uint32_t read_ahead,
+				 uint32_t read_ahead_flags);
+
+/*****************************************************************************
+ * Library functions
+ *****************************************************************************/
+
+/*******************
+ * Memory management
+ *******************/
+
+void *dm_malloc_aux(size_t s, const char *file, int line);
+void *dm_malloc_aux_debug(size_t s, const char *file, int line);
+char *dm_strdup_aux(const char *str, const char *file, int line);
+void dm_free_aux(void *p);
+void *dm_realloc_aux(void *p, unsigned int s, const char *file, int line);
+int dm_dump_memory_debug(void);
+void dm_bounds_check_debug(void);
+
+#ifdef DEBUG_MEM
+
+#  define dm_malloc(s) dm_malloc_aux_debug((s), __FILE__, __LINE__)
+#  define dm_strdup(s) dm_strdup_aux((s), __FILE__, __LINE__)
+#  define dm_free(p) dm_free_aux(p)
+#  define dm_realloc(p, s) dm_realloc_aux(p, s, __FILE__, __LINE__)
+#  define dm_dump_memory() dm_dump_memory_debug()
+#  define dm_bounds_check() dm_bounds_check_debug()
+
+#else
+
+#  define dm_malloc(s) dm_malloc_aux((s), __FILE__, __LINE__)
+#  define dm_strdup(s) strdup(s)
+#  define dm_free(p) free(p)
+#  define dm_realloc(p, s) realloc(p, s)
+#  define dm_dump_memory() {}
+#  define dm_bounds_check() {}
+
+#endif
+
+
+/*
+ * The pool allocator is useful when you are going to allocate
+ * lots of memory, use the memory for a bit, and then free the
+ * memory in one go.  A surprising amount of code has this usage
+ * profile.
+ *
+ * You should think of the pool as an infinite, contiguous chunk
+ * of memory.  The front of this chunk of memory contains
+ * allocated objects, the second half is free.  dm_pool_alloc grabs
+ * the next 'size' bytes from the free half, in effect moving it
+ * into the allocated half.  This operation is very efficient.
+ *
+ * dm_pool_free frees the allocated object *and* all objects
+ * allocated after it.  It is important to note this semantic
+ * difference from malloc/free.  This is also extremely
+ * efficient, since a single dm_pool_free can dispose of a large
+ * complex object.
+ *
+ * dm_pool_destroy frees all allocated memory.
+ *
+ * eg, If you are building a binary tree in your program, and
+ * know that you are only ever going to insert into your tree,
+ * and not delete (eg, maintaining a symbol table for a
+ * compiler).  You can create yourself a pool, allocate the nodes
+ * from it, and when the tree becomes redundant call dm_pool_destroy
+ * (no nasty iterating through the tree to free nodes).
+ *
+ * eg, On the other hand if you wanted to repeatedly insert and
+ * remove objects into the tree, you would be better off
+ * allocating the nodes from a free list; you cannot free a
+ * single arbitrary node with pool.
+ */
+
+struct dm_pool;
+
+/* constructor and destructor */
+struct dm_pool *dm_pool_create(const char *name, size_t chunk_hint);
+void dm_pool_destroy(struct dm_pool *p);
+
+/* simple allocation/free routines */
+void *dm_pool_alloc(struct dm_pool *p, size_t s);
+void *dm_pool_alloc_aligned(struct dm_pool *p, size_t s, unsigned alignment);
+void dm_pool_empty(struct dm_pool *p);
+void dm_pool_free(struct dm_pool *p, void *ptr);
+
+/*
+ * Object building routines:
+ *
+ * These allow you to 'grow' an object, useful for
+ * building strings, or filling in dynamic
+ * arrays.
+ *
+ * It's probably best explained with an example:
+ *
+ * char *build_string(struct dm_pool *mem)
+ * {
+ *      int i;
+ *      char buffer[16];
+ *
+ *      if (!dm_pool_begin_object(mem, 128))
+ *              return NULL;
+ *
+ *      for (i = 0; i < 50; i++) {
+ *              snprintf(buffer, sizeof(buffer), "%d, ", i);
+ *              if (!dm_pool_grow_object(mem, buffer, 0))
+ *                      goto bad;
+ *      }
+ *
+ *	// add null
+ *      if (!dm_pool_grow_object(mem, "\0", 1))
+ *              goto bad;
+ *
+ *      return dm_pool_end_object(mem);
+ *
+ * bad:
+ *
+ *      dm_pool_abandon_object(mem);
+ *      return NULL;
+ *}
+ *
+ * So start an object by calling dm_pool_begin_object
+ * with a guess at the final object size - if in
+ * doubt make the guess too small.
+ *
+ * Then append chunks of data to your object with
+ * dm_pool_grow_object.  Finally get your object with
+ * a call to dm_pool_end_object.
+ *
+ * Setting delta to 0 means it will use strlen(extra).
+ */
+int dm_pool_begin_object(struct dm_pool *p, size_t hint);
+int dm_pool_grow_object(struct dm_pool *p, const void *extra, size_t delta);
+void *dm_pool_end_object(struct dm_pool *p);
+void dm_pool_abandon_object(struct dm_pool *p);
+
+/* utilities */
+char *dm_pool_strdup(struct dm_pool *p, const char *str);
+char *dm_pool_strndup(struct dm_pool *p, const char *str, size_t n);
+void *dm_pool_zalloc(struct dm_pool *p, size_t s);
+
+/******************
+ * bitset functions
+ ******************/
+
+typedef uint32_t *dm_bitset_t;
+
+dm_bitset_t dm_bitset_create(struct dm_pool *mem, unsigned num_bits);
+void dm_bitset_destroy(dm_bitset_t bs);
+
+void dm_bit_union(dm_bitset_t out, dm_bitset_t in1, dm_bitset_t in2);
+int dm_bit_get_first(dm_bitset_t bs);
+int dm_bit_get_next(dm_bitset_t bs, int last_bit);
+
+#define DM_BITS_PER_INT (sizeof(int) * CHAR_BIT)
+
+#define dm_bit(bs, i) \
+   (bs[(i / DM_BITS_PER_INT) + 1] & (0x1 << (i & (DM_BITS_PER_INT - 1))))
+
+#define dm_bit_set(bs, i) \
+   (bs[(i / DM_BITS_PER_INT) + 1] |= (0x1 << (i & (DM_BITS_PER_INT - 1))))
+
+#define dm_bit_clear(bs, i) \
+   (bs[(i / DM_BITS_PER_INT) + 1] &= ~(0x1 << (i & (DM_BITS_PER_INT - 1))))
+
+#define dm_bit_set_all(bs) \
+   memset(bs + 1, -1, ((*bs / DM_BITS_PER_INT) + 1) * sizeof(int))
+
+#define dm_bit_clear_all(bs) \
+   memset(bs + 1, 0, ((*bs / DM_BITS_PER_INT) + 1) * sizeof(int))
+
+#define dm_bit_copy(bs1, bs2) \
+   memcpy(bs1 + 1, bs2 + 1, ((*bs1 / DM_BITS_PER_INT) + 1) * sizeof(int))
+
+/* Returns number of set bits */
+static inline unsigned hweight32(uint32_t i)
+{
+	unsigned r = (i & 0x55555555) + ((i >> 1) & 0x55555555);
+
+	r =    (r & 0x33333333) + ((r >>  2) & 0x33333333);
+	r =    (r & 0x0F0F0F0F) + ((r >>  4) & 0x0F0F0F0F);
+	r =    (r & 0x00FF00FF) + ((r >>  8) & 0x00FF00FF);
+	return (r & 0x0000FFFF) + ((r >> 16) & 0x0000FFFF);
+}
+
+/****************
+ * hash functions
+ ****************/
+
+struct dm_hash_table;
+struct dm_hash_node;
+
+typedef void (*dm_hash_iterate_fn) (void *data);
+
+struct dm_hash_table *dm_hash_create(unsigned size_hint);
+void dm_hash_destroy(struct dm_hash_table *t);
+void dm_hash_wipe(struct dm_hash_table *t);
+
+void *dm_hash_lookup(struct dm_hash_table *t, const char *key);
+int dm_hash_insert(struct dm_hash_table *t, const char *key, void *data);
+void dm_hash_remove(struct dm_hash_table *t, const char *key);
+
+void *dm_hash_lookup_binary(struct dm_hash_table *t, const char *key, uint32_t len);
+int dm_hash_insert_binary(struct dm_hash_table *t, const char *key, uint32_t len,
+		       void *data);
+void dm_hash_remove_binary(struct dm_hash_table *t, const char *key, uint32_t len);
+
+unsigned dm_hash_get_num_entries(struct dm_hash_table *t);
+void dm_hash_iter(struct dm_hash_table *t, dm_hash_iterate_fn f);
+
+char *dm_hash_get_key(struct dm_hash_table *t, struct dm_hash_node *n);
+void *dm_hash_get_data(struct dm_hash_table *t, struct dm_hash_node *n);
+struct dm_hash_node *dm_hash_get_first(struct dm_hash_table *t);
+struct dm_hash_node *dm_hash_get_next(struct dm_hash_table *t, struct dm_hash_node *n);
+
+#define dm_hash_iterate(v, h) \
+	for (v = dm_hash_get_first(h); v; \
+	     v = dm_hash_get_next(h, v))
+
+/****************
+ * list functions
+ ****************/
+
+/*
+ * A list consists of a list head plus elements.
+ * Each element has 'next' and 'previous' pointers.
+ * The list head's pointers point to the first and the last element.
+ */
+
+struct dm_list {
+	struct dm_list *n, *p;
+};
+
+/*
+ * Initialise a list before use.
+ * The list head's next and previous pointers point back to itself.
+ */
+#define DM_LIST_INIT(name)	struct dm_list name = { &(name), &(name) }
+void dm_list_init(struct dm_list *head);
+
+/*
+ * Insert an element before 'head'.
+ * If 'head' is the list head, this adds an element to the end of the list.
+ */
+void dm_list_add(struct dm_list *head, struct dm_list *elem);
+
+/*
+ * Insert an element after 'head'.
+ * If 'head' is the list head, this adds an element to the front of the list.
+ */
+void dm_list_add_h(struct dm_list *head, struct dm_list *elem);
+
+/*
+ * Delete an element from its list.
+ * Note that this doesn't change the element itself - it may still be safe
+ * to follow its pointers.
+ */
+void dm_list_del(struct dm_list *elem);
+
+/*
+ * Remove an element from existing list and insert before 'head'.
+ */
+void dm_list_move(struct dm_list *head, struct dm_list *elem);
+
+/*
+ * Is the list empty?
+ */
+int dm_list_empty(const struct dm_list *head);
+
+/*
+ * Is this the first element of the list?
+ */
+int dm_list_start(const struct dm_list *head, const struct dm_list *elem);
+
+/*
+ * Is this the last element of the list?
+ */
+int dm_list_end(const struct dm_list *head, const struct dm_list *elem);
+
+/*
+ * Return first element of the list or NULL if empty
+ */
+struct dm_list *dm_list_first(const struct dm_list *head);
+
+/*
+ * Return last element of the list or NULL if empty
+ */
+struct dm_list *dm_list_last(const struct dm_list *head);
+
+/*
+ * Return the previous element of the list, or NULL if we've reached the start.
+ */
+struct dm_list *dm_list_prev(const struct dm_list *head, const struct dm_list *elem);
+
+/*
+ * Return the next element of the list, or NULL if we've reached the end.
+ */
+struct dm_list *dm_list_next(const struct dm_list *head, const struct dm_list *elem);
+
+/*
+ * Given the address v of an instance of 'struct dm_list' called 'head' 
+ * contained in a structure of type t, return the containing structure.
+ */
+#define dm_list_struct_base(v, t, head) \
+    ((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->head))
+
+/*
+ * Given the address v of an instance of 'struct dm_list list' contained in
+ * a structure of type t, return the containing structure.
+ */
+#define dm_list_item(v, t) dm_list_struct_base((v), t, list)
+
+/*
+ * Given the address v of one known element e in a known structure of type t,
+ * return another element f.
+ */
+#define dm_struct_field(v, t, e, f) \
+    (((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->e))->f)
+
+/*
+ * Given the address v of a known element e in a known structure of type t,
+ * return the list head 'list'
+ */
+#define dm_list_head(v, t, e) dm_struct_field(v, t, e, list)
+
+/*
+ * Set v to each element of a list in turn.
+ */
+#define dm_list_iterate(v, head) \
+	for (v = (head)->n; v != head; v = v->n)
+
+/*
+ * Set v to each element in a list in turn, starting from the element 
+ * in front of 'start'.
+ * You can use this to 'unwind' a list_iterate and back out actions on
+ * already-processed elements.
+ * If 'start' is 'head' it walks the list backwards.
+ */
+#define dm_list_uniterate(v, head, start) \
+	for (v = (start)->p; v != head; v = v->p)
+
+/*
+ * A safe way to walk a list and delete and free some elements along
+ * the way.
+ * t must be defined as a temporary variable of the same type as v.
+ */
+#define dm_list_iterate_safe(v, t, head) \
+	for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
+
+/*
+ * Walk a list, setting 'v' in turn to the containing structure of each item.
+ * The containing structure should be the same type as 'v'.
+ * The 'struct dm_list' variable within the containing structure is 'field'.
+ */
+#define dm_list_iterate_items_gen(v, head, field) \
+	for (v = dm_list_struct_base((head)->n, typeof(*v), field); \
+	     &v->field != (head); \
+	     v = dm_list_struct_base(v->field.n, typeof(*v), field))
+
+/*
+ * Walk a list, setting 'v' in turn to the containing structure of each item.
+ * The containing structure should be the same type as 'v'.
+ * The list should be 'struct dm_list list' within the containing structure.
+ */
+#define dm_list_iterate_items(v, head) dm_list_iterate_items_gen(v, (head), list)
+
+/*
+ * Walk a list, setting 'v' in turn to the containing structure of each item.
+ * The containing structure should be the same type as 'v'.
+ * The 'struct dm_list' variable within the containing structure is 'field'.
+ * t must be defined as a temporary variable of the same type as v.
+ */
+#define dm_list_iterate_items_gen_safe(v, t, head, field) \
+	for (v = dm_list_struct_base((head)->n, typeof(*v), field), \
+	     t = dm_list_struct_base(v->field.n, typeof(*v), field); \
+	     &v->field != (head); \
+	     v = t, t = dm_list_struct_base(v->field.n, typeof(*v), field))
+/*
+ * Walk a list, setting 'v' in turn to the containing structure of each item.
+ * The containing structure should be the same type as 'v'.
+ * The list should be 'struct dm_list list' within the containing structure.
+ * t must be defined as a temporary variable of the same type as v.
+ */
+#define dm_list_iterate_items_safe(v, t, head) \
+	dm_list_iterate_items_gen_safe(v, t, (head), list)
+
+/*
+ * Walk a list backwards, setting 'v' in turn to the containing structure 
+ * of each item.
+ * The containing structure should be the same type as 'v'.
+ * The 'struct dm_list' variable within the containing structure is 'field'.
+ */
+#define dm_list_iterate_back_items_gen(v, head, field) \
+	for (v = dm_list_struct_base((head)->p, typeof(*v), field); \
+	     &v->field != (head); \
+	     v = dm_list_struct_base(v->field.p, typeof(*v), field))
+
+/*
+ * Walk a list backwards, setting 'v' in turn to the containing structure 
+ * of each item.
+ * The containing structure should be the same type as 'v'.
+ * The list should be 'struct dm_list list' within the containing structure.
+ */
+#define dm_list_iterate_back_items(v, head) dm_list_iterate_back_items_gen(v, (head), list)
+
+/*
+ * Return the number of elements in a list by walking it.
+ */
+unsigned int dm_list_size(const struct dm_list *head);
+
+/*********
+ * selinux
+ *********/
+int dm_set_selinux_context(const char *path, mode_t mode);
+
+/*********************
+ * string manipulation
+ *********************/
+
+/*
+ * Break up the name of a mapped device into its constituent
+ * Volume Group, Logical Volume and Layer (if present).
+ */
+int dm_split_lvm_name(struct dm_pool *mem, const char *dmname,
+		      char **vgname, char **lvname, char **layer);
+
+/*
+ * Destructively split buffer into NULL-separated words in argv.
+ * Returns number of words.
+ */
+int dm_split_words(char *buffer, unsigned max,
+		   unsigned ignore_comments, /* Not implemented */
+		   char **argv);
+
+/* 
+ * Returns -1 if buffer too small
+ */
+int dm_snprintf(char *buf, size_t bufsize, const char *format, ...);
+
+/*
+ * Returns pointer to the last component of the path.
+ */
+char *dm_basename(const char *path);
+
+/**************************
+ * file/stream manipulation
+ **************************/
+
+/*
+ * Create a directory (with parent directories if necessary).
+ * Returns 1 on success, 0 on failure.
+ */
+int dm_create_dir(const char *dir);
+
+/*
+ * Close a stream, with nicer error checking than fclose's.
+ * Derived from gnulib's close-stream.c.
+ *
+ * Close "stream".  Return 0 if successful, and EOF (setting errno)
+ * otherwise.  Upon failure, set errno to 0 if the error number
+ * cannot be determined.  Useful mainly for writable streams.
+ */
+int dm_fclose(FILE *stream);
+
+/*
+ * Returns size of a buffer which is allocated with dm_malloc.
+ * Pointer to the buffer is stored in *buf.
+ * Returns -1 on failure leaving buf undefined.
+ */
+int dm_asprintf(char **buf, const char *format, ...);
+
+/*********************
+ * regular expressions
+ *********************/
+struct dm_regex;
+
+/*
+ * Initialise an array of num patterns for matching.
+ * Uses memory from mem.
+ */
+struct dm_regex *dm_regex_create(struct dm_pool *mem, const char **patterns,
+				 unsigned num_patterns);
+
+/*
+ * Match string s against the patterns.
+ * Returns the index of the highest pattern in the array that matches,
+ * or -1 if none match.
+ */
+int dm_regex_match(struct dm_regex *regex, const char *s);
+
+/*********************
+ * reporting functions
+ *********************/
+
+struct dm_report_object_type {
+	uint32_t id;			/* Powers of 2 */
+	const char *desc;
+	const char *prefix;		/* field id string prefix (optional) */
+	void *(*data_fn)(void *object);	/* callback from report_object() */
+};
+
+struct dm_report_field;
+
+/*
+ * dm_report_field_type flags
+ */
+#define DM_REPORT_FIELD_MASK		0x000000FF
+#define DM_REPORT_FIELD_ALIGN_MASK	0x0000000F
+#define DM_REPORT_FIELD_ALIGN_LEFT	0x00000001
+#define DM_REPORT_FIELD_ALIGN_RIGHT	0x00000002
+#define DM_REPORT_FIELD_TYPE_MASK	0x000000F0
+#define DM_REPORT_FIELD_TYPE_STRING	0x00000010
+#define DM_REPORT_FIELD_TYPE_NUMBER	0x00000020
+
+struct dm_report;
+struct dm_report_field_type {
+	uint32_t type;		/* object type id */
+	uint32_t flags;		/* DM_REPORT_FIELD_* */
+	uint32_t offset;	/* byte offset in the object */
+	int32_t width;		/* default width */
+	const char id[32];	/* string used to specify the field */
+	const char heading[32];	/* string printed in header */
+	int (*report_fn)(struct dm_report *rh, struct dm_pool *mem,
+			 struct dm_report_field *field, const void *data,
+			 void *private);
+	const char *desc;	/* description of the field */
+};
+
+/*
+ * dm_report_init output_flags
+ */
+#define DM_REPORT_OUTPUT_MASK			0x000000FF
+#define DM_REPORT_OUTPUT_ALIGNED		0x00000001
+#define DM_REPORT_OUTPUT_BUFFERED		0x00000002
+#define DM_REPORT_OUTPUT_HEADINGS		0x00000004
+#define DM_REPORT_OUTPUT_FIELD_NAME_PREFIX	0x00000008
+#define DM_REPORT_OUTPUT_FIELD_UNQUOTED		0x00000010
+#define DM_REPORT_OUTPUT_COLUMNS_AS_ROWS	0x00000020
+
+struct dm_report *dm_report_init(uint32_t *report_types,
+				 const struct dm_report_object_type *types,
+				 const struct dm_report_field_type *fields,
+				 const char *output_fields,
+				 const char *output_separator,
+				 uint32_t output_flags,
+				 const char *sort_keys,
+				 void *private);
+int dm_report_object(struct dm_report *rh, void *object);
+int dm_report_output(struct dm_report *rh);
+void dm_report_free(struct dm_report *rh);
+
+/*
+ * Prefix added to each field name with DM_REPORT_OUTPUT_FIELD_NAME_PREFIX
+ */
+int dm_report_set_output_field_name_prefix(struct dm_report *rh,
+					   const char *report_prefix);
+
+/*
+ * Report functions are provided for simple data types.
+ * They take care of allocating copies of the data.
+ */
+int dm_report_field_string(struct dm_report *rh, struct dm_report_field *field,
+			   const char **data);
+int dm_report_field_int32(struct dm_report *rh, struct dm_report_field *field,
+			  const int32_t *data);
+int dm_report_field_uint32(struct dm_report *rh, struct dm_report_field *field,
+			   const uint32_t *data);
+int dm_report_field_int(struct dm_report *rh, struct dm_report_field *field,
+			const int *data);
+int dm_report_field_uint64(struct dm_report *rh, struct dm_report_field *field,
+			   const uint64_t *data);
+
+/*
+ * For custom fields, allocate the data in 'mem' and use
+ * dm_report_field_set_value().
+ * 'sortvalue' may be NULL if it matches 'value'
+ */
+void dm_report_field_set_value(struct dm_report_field *field, const void *value,
+			       const void *sortvalue);
+
+#endif				/* LIB_DEVICE_MAPPER_H */
Index: src/external/gpl2/lvm2tools/dist/include/locking.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/locking.h
diff -N src/external/gpl2/lvm2tools/dist/include/locking.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/locking.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,145 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_LOCKING_H
+#define _LVM_LOCKING_H
+
+#include "uuid.h"
+#include "config.h"
+
+int init_locking(int type, struct cmd_context *cmd);
+void fin_locking(void);
+void reset_locking(void);
+int vg_write_lock_held(void);
+int locking_is_clustered(void);
+
+/*
+ * LCK_VG:
+ *   Lock/unlock on-disk volume group data.
+ *   Use VG_ORPHANS to lock all orphan PVs.
+ *   Use VG_GLOBAL as a global lock and to wipe the internal cache.
+ *   char *vol holds volume group name.
+ *   Set the LCK_CACHE flag to invalidate 'vol' in the internal cache.
+ *
+ * LCK_LV:
+ *   Lock/unlock an individual logical volume
+ *   char *vol holds lvid
+ */
+int lock_vol(struct cmd_context *cmd, const char *vol, uint32_t flags);
+
+/*
+ * Internal locking representation.
+ *   LCK_VG: Uses prefix V_ unless the vol begins with # (i.e. #global or #orphans)
+ *           or the LCK_CACHE flag is set when it uses the prefix P_.
+ * If LCK_CACHE is set, we do not take out a real lock.
+ */
+
+/*
+ * Does the LVM1 driver have this VG active?
+ */
+int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname);
+
+/*
+ * Lock type - these numbers are the same as VMS and the IBM DLM
+ */
+#define LCK_TYPE_MASK	0x00000007U
+
+#define LCK_NULL	0x00000000U	/* LCK$_NLMODE */
+#define LCK_READ	0x00000001U	/* LCK$_CRMODE */
+					/* LCK$_CWMODE */
+#define LCK_PREAD       0x00000003U	/* LCK$_PRMODE */
+#define LCK_WRITE	0x00000004U	/* LCK$_PWMODE */
+#define LCK_EXCL	0x00000005U	/* LCK$_EXMODE */
+#define LCK_UNLOCK      0x00000006U	/* This is ours */
+
+/*
+ * Lock scope
+ */
+#define LCK_SCOPE_MASK	0x00000008U
+#define LCK_VG		0x00000000U
+#define LCK_LV		0x00000008U
+
+/*
+ * Lock bits
+ */
+#define LCK_NONBLOCK	0x00000010U	/* Don't block waiting for lock? */
+#define LCK_HOLD	0x00000020U	/* Hold lock when lock_vol returns? */
+#define LCK_LOCAL	0x00000040U	/* Don't propagate to other nodes */
+#define LCK_CLUSTER_VG	0x00000080U	/* VG is clustered */
+#define LCK_CACHE	0x00000100U	/* Operation on cache only using P_ lock */
+
+/*
+ * Additional lock bits for cluster communication
+ */
+#define LCK_MIRROR_NOSYNC_MODE	0x00000002U	/* Mirrors don't require sync */
+#define LCK_DMEVENTD_MONITOR_MODE	0x00000004U	/* Register with dmeventd */
+
+/*
+ * Special cases of VG locks.
+ */
+#define VG_ORPHANS	"#orphans"
+#define VG_GLOBAL	"#global"
+
+/*
+ * Common combinations
+ */
+#define LCK_NONE		(LCK_VG | LCK_NULL)
+
+#define LCK_VG_READ		(LCK_VG | LCK_READ | LCK_HOLD)
+#define LCK_VG_WRITE		(LCK_VG | LCK_WRITE | LCK_HOLD)
+#define LCK_VG_UNLOCK		(LCK_VG | LCK_UNLOCK)
+#define LCK_VG_DROP_CACHE	(LCK_VG | LCK_WRITE | LCK_CACHE)
+
+#define LCK_LV_EXCLUSIVE	(LCK_LV | LCK_EXCL | LCK_NONBLOCK)
+#define LCK_LV_SUSPEND		(LCK_LV | LCK_WRITE | LCK_NONBLOCK)
+#define LCK_LV_RESUME		(LCK_LV | LCK_UNLOCK | LCK_NONBLOCK)
+#define LCK_LV_ACTIVATE		(LCK_LV | LCK_READ | LCK_NONBLOCK)
+#define LCK_LV_DEACTIVATE	(LCK_LV | LCK_NULL | LCK_NONBLOCK)
+
+#define LCK_LV_CLUSTERED(lv)	\
+	(vg_is_clustered((lv)->vg) ? LCK_CLUSTER_VG : 0)
+
+#define lock_lv_vol(cmd, lv, flags)	\
+	lock_vol(cmd, (lv)->lvid.s, flags | LCK_LV_CLUSTERED(lv))
+
+#define unlock_vg(cmd, vol)	lock_vol(cmd, vol, LCK_VG_UNLOCK)
+
+#define resume_lv(cmd, lv)	lock_lv_vol(cmd, lv, LCK_LV_RESUME)
+#define suspend_lv(cmd, lv)	lock_lv_vol(cmd, lv, LCK_LV_SUSPEND | LCK_HOLD)
+#define deactivate_lv(cmd, lv)	lock_lv_vol(cmd, lv, LCK_LV_DEACTIVATE)
+#define activate_lv(cmd, lv)	lock_lv_vol(cmd, lv, LCK_LV_ACTIVATE | LCK_HOLD)
+#define activate_lv_excl(cmd, lv)	\
+				lock_lv_vol(cmd, lv, LCK_LV_EXCLUSIVE | LCK_HOLD)
+#define activate_lv_local(cmd, lv)	\
+	lock_lv_vol(cmd, lv, LCK_LV_ACTIVATE | LCK_HOLD | LCK_LOCAL)
+#define deactivate_lv_local(cmd, lv)	\
+	lock_lv_vol(cmd, lv, LCK_LV_DEACTIVATE | LCK_LOCAL)
+#define drop_cached_metadata(vg)	\
+	lock_vol((vg)->cmd, (vg)->name, LCK_VG_DROP_CACHE)
+
+/* Process list of LVs */
+int suspend_lvs(struct cmd_context *cmd, struct dm_list *lvs);
+int resume_lvs(struct cmd_context *cmd, struct dm_list *lvs);
+int activate_lvs(struct cmd_context *cmd, struct dm_list *lvs, unsigned exclusive);
+
+/* Interrupt handling */
+void sigint_clear(void);
+void sigint_allow(void);
+void sigint_restore(void);
+int sigint_caught(void);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/log.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/log.h
diff -N src/external/gpl2/lvm2tools/dist/include/log.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/log.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,81 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_LOG_H
+#define _LVM_LOG_H
+
+/*
+ * printf()-style macros to use for messages:
+ *
+ *   log_error   - always print to stderr.
+ *   log_print   - always print to stdout.  Use this instead of printf.
+ *   log_verbose - print to stdout if verbose is set (-v)
+ *   log_very_verbose - print to stdout if verbose is set twice (-vv)
+ *   log_debug   - print to stdout if verbose is set three times (-vvv)
+ *
+ * In addition, messages will be logged to file or syslog if they
+ * are more serious than the log level specified with the log/debug_level
+ * parameter in the configuration file.  These messages get the file
+ * and line number prepended.  'stack' (without arguments) can be used 
+ * to log this information at debug level.
+ *
+ * log_sys_error and log_sys_very_verbose are for errors from system calls
+ * e.g. log_sys_error("stat", filename);
+ *      /dev/fd/7: stat failed: No such file or directory
+ *
+ */
+
+#include <stdio.h>		/* FILE */
+#include <string.h>		/* strerror() */
+#include <errno.h>
+
+#define _LOG_STDERR 128 /* force things to go to stderr, even if loglevel
+			   would make them go to stdout */
+#define _LOG_DEBUG 7
+#define _LOG_INFO 6
+#define _LOG_NOTICE 5
+#define _LOG_WARN 4
+#define _LOG_ERR 3
+#define _LOG_FATAL 2
+
+#define log_debug(x...) plog(_LOG_DEBUG, x)
+#define log_info(x...) plog(_LOG_INFO, x)
+#define log_notice(x...) plog(_LOG_NOTICE, x)
+#define log_warn(x...) plog(_LOG_WARN | _LOG_STDERR, x)
+#define log_err(x...) plog(_LOG_ERR, x)
+#define log_fatal(x...) plog(_LOG_FATAL, x)
+
+#define stack log_debug("<backtrace>")	/* Backtrace on error */
+#define log_very_verbose(args...) log_info(args)
+#define log_verbose(args...) log_notice(args)
+#define log_print(args...) plog(_LOG_WARN, args)
+#define log_error(args...) log_err(args)
+
+/* 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))
+
+#define return_0	do { stack; return 0; } while (0)
+#define return_NULL	do { stack; return NULL; } while (0)
+#define goto_out	do { stack; goto out; } while (0)
+#define goto_bad	do { stack; goto bad; } while (0)
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/lv_alloc.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/lv_alloc.h
diff -N src/external/gpl2/lvm2tools/dist/include/lv_alloc.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/lv_alloc.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,83 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_LV_ALLOC_H
+
+struct lv_segment *alloc_lv_segment(struct dm_pool *mem,
+				    const struct segment_type *segtype,
+				    struct logical_volume *lv,
+				    uint32_t le, uint32_t len,
+				    uint32_t status,
+				    uint32_t stripe_size,
+				    struct logical_volume *log_lv,
+				    uint32_t area_count,
+				    uint32_t area_len,
+				    uint32_t chunk_size,
+				    uint32_t region_size,
+				    uint32_t extents_copied);
+
+struct lv_segment *alloc_snapshot_seg(struct logical_volume *lv,
+				      uint32_t status, uint32_t old_le_count);
+
+int set_lv_segment_area_pv(struct lv_segment *seg, uint32_t area_num,
+			   struct physical_volume *pv, uint32_t pe);
+int set_lv_segment_area_lv(struct lv_segment *seg, uint32_t area_num,
+			   struct logical_volume *lv, uint32_t le,
+			   uint32_t flags);
+int move_lv_segment_area(struct lv_segment *seg_to, uint32_t area_to,
+			 struct lv_segment *seg_from, uint32_t area_from);
+void release_lv_segment_area(struct lv_segment *seg, uint32_t s,
+			     uint32_t area_reduction);
+
+struct alloc_handle;
+struct alloc_handle *allocate_extents(struct volume_group *vg,
+				      struct logical_volume *lv,
+                                      const struct segment_type *segtype,
+                                      uint32_t stripes,
+                                      uint32_t mirrors, uint32_t log_count,
+				      uint32_t extents,
+                                      struct dm_list *allocatable_pvs,
+				      alloc_policy_t alloc,
+				      struct dm_list *parallel_areas);
+
+int lv_add_segment(struct alloc_handle *ah,
+		   uint32_t first_area, uint32_t num_areas,
+		   struct logical_volume *lv,
+                   const struct segment_type *segtype,
+                   uint32_t stripe_size,
+                   uint32_t status,   
+		   uint32_t region_size,
+                   struct logical_volume *log_lv);
+
+int lv_add_mirror_areas(struct alloc_handle *ah,
+			struct logical_volume *lv, uint32_t le,
+			uint32_t region_size);
+int lv_add_mirror_lvs(struct logical_volume *lv,
+		      struct logical_volume **sub_lvs,
+		      uint32_t num_extra_areas,
+		      uint32_t status, uint32_t region_size);
+
+int lv_add_log_segment(struct alloc_handle *ah, struct logical_volume *log_lv);
+int lv_add_virtual_segment(struct logical_volume *lv, uint32_t status,
+                           uint32_t extents, const struct segment_type *segtype);
+
+void alloc_destroy(struct alloc_handle *ah);
+
+struct dm_list *build_parallel_areas_from_lv(struct cmd_context *cmd,
+					  struct logical_volume *lv);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/lvm-exec.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/lvm-exec.h
diff -N src/external/gpl2/lvm2tools/dist/include/lvm-exec.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/lvm-exec.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,25 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_EXEC_H
+#define _LVM_EXEC_H
+
+#include "lib.h"
+
+int exec_cmd(const char *command, const char *fscmd, const char *lv_path,
+	     const char *size);
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/lvm-file.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/lvm-file.h
diff -N src/external/gpl2/lvm2tools/dist/include/lvm-file.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/lvm-file.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,64 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_FILE_H
+#define _LVM_FILE_H
+
+/*
+ * Create a temporary filename, and opens a descriptor to the file.
+ */
+int create_temp_name(const char *dir, char *buffer, size_t len, int *fd);
+
+/*
+ * NFS-safe rename of a temporary file to a common name, designed
+ * to avoid race conditions and not overwrite the destination if
+ * it exists.
+ */
+int lvm_rename(const char *old, const char *new);
+
+/*
+ * Return 1 if path exists else return 0
+ */
+int path_exists(const char *path);
+int dir_exists(const char *path);
+
+/*
+ * Return 1 if dir is empty
+ */
+int is_empty_dir(const char *dir);
+
+/* Sync directory changes */
+void sync_dir(const char *file);
+
+/* fcntl locking wrappers */
+int fcntl_lock_file(const char *file, short lock_type, int warn_if_read_only);
+void fcntl_unlock_file(int lockfd);
+
+#define is_same_inode(buf1, buf2) \
+  ((buf1).st_ino == (buf2).st_ino && \
+   (buf1).st_dev == (buf2).st_dev)
+
+/*
+ * Close the specified stream, taking care to detect and diagnose any write
+ * error.  If there is an error, use the supplied file name in a diagnostic
+ * that is reported via log_error or log_sys_error, as appropriate.
+ * Use this function to close a stream when you've written data to it via
+ * unchecked fprintf, fputc, etc. calls.  Return 0 on success, EOF on failure.
+ */
+int lvm_fclose(FILE *fp, const char *filename);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/lvm-globals.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/lvm-globals.h
diff -N src/external/gpl2/lvm2tools/dist/include/lvm-globals.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/lvm-globals.h	13 Dec 2008 14:39:32 -0000	1.1.1.1.2.3
@@ -0,0 +1,61 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_GLOBALS_H
+#define _LVM_GLOBALS_H
+
+#define VERBOSE_BASE_LEVEL _LOG_WARN
+#define SECURITY_LEVEL 0
+
+void init_verbose(int level);
+void init_test(int level);
+void init_md_filtering(int level);
+void init_pvmove(int level);
+void init_full_scan_done(int level);
+void init_trust_cache(int trustcache);
+void init_debug(int level);
+void init_cmd_name(int status);
+void init_msg_prefix(const char *prefix);
+void init_indent(int indent);
+void init_ignorelockingfailure(int level);
+void init_lockingfailed(int level);
+void init_security_level(int level);
+void init_mirror_in_sync(int in_sync);
+void init_dmeventd_monitor(int reg);
+void init_ignore_suspended_devices(int ignore);
+void init_error_message_produced(int produced);
+
+void set_cmd_name(const char *cmd_name);
+
+int test_mode(void);
+int md_filtering(void);
+int pvmove_mode(void);
+int full_scan_done(void);
+int trust_cache(void);
+int verbose_level(void);
+int debug_level(void);
+int ignorelockingfailure(void);
+int lockingfailed(void);
+int security_level(void);
+int mirror_in_sync(void);
+int ignore_suspended_devices(void);
+const char *log_command_name(void);
+
+#define DMEVENTD_MONITOR_IGNORE -1
+int dmeventd_monitor_mode(void);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/lvm-logging.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/lvm-logging.h
diff -N src/external/gpl2/lvm2tools/dist/include/lvm-logging.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/lvm-logging.h	13 Dec 2008 14:39:32 -0000	1.1.1.1.2.3
@@ -0,0 +1,55 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_LOGGING_H
+#define _LVM_LOGGING_H
+
+void print_log(int level, const char *file, int line, const char *format, ...)
+    __attribute__ ((format(printf, 4, 5)));
+
+#define plog(l, x...) print_log(l, __FILE__, __LINE__ , ## x)
+
+#include "log.h"
+
+typedef void (*lvm2_log_fn_t) (int level, const char *file, int line,
+			       const char *message);
+
+void init_log_fn(lvm2_log_fn_t log_fn);
+
+void init_indent(int indent);
+void init_msg_prefix(const char *prefix);
+
+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);
+
+int error_message_produced(void);
+
+/* Suppress messages to stdout/stderr (1) or everywhere (2) */
+/* Returns previous setting */
+int log_suppress(int suppress);
+
+/* Suppress messages to syslog */
+void syslog_suppress(int suppress);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/lvm-string.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/lvm-string.h
diff -N src/external/gpl2/lvm2tools/dist/include/lvm-string.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/lvm-string.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,59 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_STRING_H
+#define _LVM_STRING_H
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#define NAME_LEN 128
+
+struct pool;
+
+int emit_to_buffer(char **buffer, size_t *size, const char *fmt, ...)
+  __attribute__ ((format(printf, 3, 4)));
+
+char *build_dm_name(struct dm_pool *mem, const char *vg,
+                    const char *lv, const char *layer);
+
+int validate_name(const char *n);
+
+/*
+ * Returns number of occurrences of c in first len characters of str.
+ */
+unsigned count_chars(const char *str, size_t len, const int c);
+
+/*
+ * Returns what length of escaped string would be including terminating NUL.
+ */
+size_t escaped_len(const char *str);
+
+/*
+ * Copies a string from src to out. 
+ * Double quotation marks and backslashes are quoted with a backslash.
+ * Caller must ensure *out has enough space - see escaped_len().
+ * Returns *out.
+ */
+char *escape_double_quotes(char *out, const char *src);
+
+/*
+ * Removes quoting of double quotation marks and backslashes in situ.
+ */
+void unescape_double_quotes(char *src);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/lvm-types.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/lvm-types.h
diff -N src/external/gpl2/lvm2tools/dist/include/lvm-types.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/lvm-types.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,34 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_TYPES_H
+#define _LVM_TYPES_H
+
+#include <sys/types.h>
+#include <inttypes.h>
+
+/* Define some portable printing types */
+#define PRIsize_t "zu"
+#define PRIptrdiff_t "td"
+#define PRIpid_t PRId32
+
+struct str_list {
+	struct dm_list list;
+	const char *str;
+};
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/lvm-wrappers.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/lvm-wrappers.h
diff -N src/external/gpl2/lvm2tools/dist/include/lvm-wrappers.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/lvm-wrappers.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,23 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_WRAPPERS_H
+#define _LVM_WRAPPERS_H
+
+int lvm_getpagesize(void);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/lvmcache.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/lvmcache.h
diff -N src/external/gpl2/lvm2tools/dist/include/lvmcache.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/lvmcache.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,117 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_CACHE_H
+#define _LVM_CACHE_H
+
+#include "dev-cache.h"
+#include "uuid.h"
+#include "label.h"
+
+#define ORPHAN_PREFIX "#"
+#define ORPHAN_VG_NAME(fmt) ORPHAN_PREFIX "orphans_" fmt
+
+#define CACHE_INVALID	0x00000001
+#define CACHE_LOCKED	0x00000002
+
+/* LVM specific per-volume info */
+/* Eventual replacement for struct physical_volume perhaps? */
+
+struct cmd_context;
+struct format_type;
+struct volume_group;
+
+/* One per VG */
+struct lvmcache_vginfo {
+	struct dm_list list;	/* Join these vginfos together */
+	struct dm_list infos;	/* List head for lvmcache_infos */
+	const struct format_type *fmt;
+	char *vgname;		/* "" == orphan */
+	uint32_t status;
+	char vgid[ID_LEN + 1];
+	char _padding[7];
+	struct lvmcache_vginfo *next; /* Another VG with same name? */
+	char *creation_host;
+	char *vgmetadata;	/* Copy of VG metadata as format_text string */
+	unsigned precommitted;	/* Is vgmetadata live or precommitted? */
+};
+
+/* One per device */
+struct lvmcache_info {
+	struct dm_list list;	/* Join VG members together */
+	struct dm_list mdas;	/* list head for metadata areas */
+	struct dm_list das;	/* list head for data areas */
+	struct lvmcache_vginfo *vginfo;	/* NULL == unknown */
+	struct label *label;
+	const struct format_type *fmt;
+	struct device *dev;
+	uint64_t device_size;	/* Bytes */
+	uint32_t status;
+};
+
+int lvmcache_init(void);
+void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans);
+
+/* Set full_scan to 1 to reread every filtered device label or
+ * 2 to rescan /dev for new devices */
+int lvmcache_label_scan(struct cmd_context *cmd, int full_scan);
+
+/* Add/delete a device */
+struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
+				   struct device *dev,
+				   const char *vgname, const char *vgid,
+				   uint32_t vgstatus);
+int lvmcache_add_orphan_vginfo(const char *vgname, struct format_type *fmt);
+void lvmcache_del(struct lvmcache_info *info);
+
+/* Update things */
+int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
+				  const char *vgname, const char *vgid,
+				  uint32_t vgstatus, const char *hostname);
+int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted);
+
+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, const char *vgid);
+struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname,
+					   const char *vgid);
+struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid);
+struct lvmcache_info *info_from_pvid(const char *pvid, int valid_only);
+const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid);
+struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid);
+int vgs_locked(void);
+int vgname_is_locked(const char *vgname);
+
+/* Returns list of struct str_lists containing pool-allocated copy of vgnames */
+/* Set full_scan to 1 to reread every filtered device label */
+struct dm_list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan);
+
+/* Returns list of struct str_lists containing pool-allocated copy of vgids */
+/* Set full_scan to 1 to reread every filtered device label */
+struct dm_list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan);
+
+/* Returns list of struct str_lists containing pool-allocated copy of pvids */
+struct dm_list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
+				const char *vgid);
+
+/* Returns cached volume group metadata. */
+struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted);
+void lvmcache_drop_metadata(const char *vgname);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/memlock.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/memlock.h
diff -N src/external/gpl2/lvm2tools/dist/include/memlock.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/memlock.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,28 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef LVM_MEMLOCK_H
+#define LVM_MEMLOCK_H
+
+struct cmd_context;
+
+void memlock_inc(void);
+void memlock_dec(void);
+int memlock(void);
+void memlock_init(struct cmd_context *cmd);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/metadata-exported.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/metadata-exported.h
diff -N src/external/gpl2/lvm2tools/dist/include/metadata-exported.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/metadata-exported.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,595 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * This is the representation of LVM metadata that is being adapted
+ * for library export.
+ */
+
+#ifndef _LVM_METADATA_EXPORTED_H
+#define _LVM_METADATA_EXPORTED_H
+
+#include "uuid.h"
+
+struct physical_volume;
+typedef struct physical_volume pv_t;
+struct volume_group;
+typedef struct volume_group vg_t;
+
+struct logical_volume;
+
+struct lv_segment;
+struct pv_segment;
+
+#define MAX_STRIPES 128U
+#define SECTOR_SHIFT 9L
+#define STRIPE_SIZE_MIN ( (unsigned) lvm_getpagesize() >> SECTOR_SHIFT)	/* PAGESIZE in sectors */
+#define STRIPE_SIZE_MAX ( 512L * 1024L >> SECTOR_SHIFT)	/* 512 KB in sectors */
+#define STRIPE_SIZE_LIMIT ((UINT_MAX >> 2) + 1)
+#define PV_MIN_SIZE ( 512L * 1024L >> SECTOR_SHIFT)	/* 512 KB in sectors */
+#define MAX_RESTRICTED_LVS 255	/* Used by FMT_RESTRICTED_LVIDS */
+
+/* Layer suffix */
+#define MIRROR_SYNC_LAYER "_mimagetmp"
+
+/* Various flags */
+/* Note that the bits no longer necessarily correspond to LVM1 disk format */
+
+#define PARTIAL_VG		0x00000001U	/* VG */
+#define EXPORTED_VG          	0x00000002U	/* VG PV */
+#define RESIZEABLE_VG        	0x00000004U	/* VG */
+
+/* May any free extents on this PV be used or must they be left free? */
+#define ALLOCATABLE_PV         	0x00000008U	/* PV */
+
+//#define SPINDOWN_LV          	0x00000010U	/* LV */
+//#define BADBLOCK_ON       	0x00000020U	/* LV */
+#define VISIBLE_LV		0x00000040U	/* LV */
+#define FIXED_MINOR		0x00000080U	/* LV */
+/* FIXME Remove when metadata restructuring is completed */
+#define SNAPSHOT		0x00001000U	/* LV - internal use only */
+#define PVMOVE			0x00002000U	/* VG LV SEG */
+#define LOCKED			0x00004000U	/* LV */
+#define MIRRORED		0x00008000U	/* LV - internal use only */
+//#define VIRTUAL			0x00010000U	/* LV - internal use only */
+#define MIRROR_LOG		0x00020000U	/* LV */
+#define MIRROR_IMAGE		0x00040000U	/* LV */
+#define MIRROR_NOTSYNCED	0x00080000U	/* LV */
+//#define ACTIVATE_EXCL		0x00100000U	/* LV - internal use only */
+//#define PRECOMMITTED		0x00200000U	/* VG - internal use only */
+#define CONVERTING		0x00400000U	/* LV */
+
+#define MISSING_PV              0x00800000U	/* PV */
+#define PARTIAL_LV              0x01000000U	/* LV - derived flag, not
+						   written out in metadata*/
+
+//#define POSTORDER_FLAG	0x02000000U /* Not real flags, reserved for
+//#define POSTORDER_OPEN_FLAG	0x04000000U    temporary use inside vg_read. */
+
+#define LVM_READ              	0x00000100U	/* LV VG */
+#define LVM_WRITE             	0x00000200U	/* LV VG */
+#define CLUSTERED         	0x00000400U	/* VG */
+//#define SHARED            	0x00000800U	/* VG */
+
+/* Format features flags */
+#define FMT_SEGMENTS		0x00000001U	/* Arbitrary segment params? */
+#define FMT_MDAS		0x00000002U	/* Proper metadata areas? */
+#define FMT_TAGS		0x00000004U	/* Tagging? */
+#define FMT_UNLIMITED_VOLS	0x00000008U	/* Unlimited PVs/LVs? */
+#define FMT_RESTRICTED_LVIDS	0x00000010U	/* LVID <= 255 */
+#define FMT_ORPHAN_ALLOCATABLE	0x00000020U	/* Orphan PV allocatable? */
+//#define FMT_PRECOMMIT		0x00000040U	/* Supports pre-commit? */
+#define FMT_RESIZE_PV		0x00000080U	/* Supports pvresize? */
+#define FMT_UNLIMITED_STRIPESIZE 0x00000100U	/* Unlimited stripe size? */
+#define FMT_RESTRICTED_READAHEAD 0x00000200U	/* Readahead restricted to 2-120? */
+
+/* LVM2 external library flags */
+#define CORRECT_INCONSISTENT    0x00000001U /* Correct inconsistent metadata */
+#define FAIL_INCONSISTENT       0x00000002U /* Fail if metadata inconsistent */
+
+/* Mirror conversion type flags */
+#define MIRROR_BY_SEG		0x00000001U	/* segment-by-segment mirror */
+#define MIRROR_BY_LV		0x00000002U	/* mirror using whole mimage LVs */
+#define MIRROR_SKIP_INIT_SYNC	0x00000010U	/* skip initial sync */
+
+/* Ordered list - see lv_manip.c */
+typedef enum {
+	ALLOC_INVALID,
+	ALLOC_CONTIGUOUS,
+	ALLOC_CLING,
+	ALLOC_NORMAL,
+	ALLOC_ANYWHERE,
+	ALLOC_INHERIT
+} alloc_policy_t;
+
+typedef enum {
+	AREA_UNASSIGNED,
+	AREA_PV,
+	AREA_LV
+} area_type_t;
+
+/*
+ * Whether or not to force an operation.
+ */
+typedef enum {
+	PROMPT = 0, /* Issue yes/no prompt to confirm operation */
+	DONT_PROMPT = 1, /* Skip yes/no prompt */
+	DONT_PROMPT_OVERRIDE = 2 /* Skip prompt + override a second condition */
+} force_t;
+
+struct cmd_context;
+struct format_handler;
+struct labeller;
+
+struct format_type {
+	struct dm_list list;
+	struct cmd_context *cmd;
+	struct format_handler *ops;
+	struct labeller *labeller;
+	const char *name;
+	const char *alias;
+	const char *orphan_vg_name;
+	uint32_t features;
+	void *library;
+	void *private;
+};
+
+struct pv_segment {
+	struct dm_list list;	/* Member of pv->segments: ordered list
+				 * covering entire data area on this PV */
+
+	struct physical_volume *pv;
+	uint32_t pe;
+	uint32_t len;
+
+	struct lv_segment *lvseg;	/* NULL if free space */
+	uint32_t lv_area;	/* Index to area in LV segment */
+};
+
+#define pvseg_is_allocated(pvseg) ((pvseg)->lvseg)
+
+struct physical_volume {
+	struct id id;
+	struct device *dev;
+	const struct format_type *fmt;
+	const char *vg_name;
+	struct id vgid;
+
+	uint32_t status;
+	uint64_t size;
+
+	/* physical extents */
+	uint32_t pe_size;
+	uint64_t pe_start;
+	uint32_t pe_count;
+	uint32_t pe_alloc_count;
+	unsigned long pe_align;
+
+	struct dm_list segments;	/* Ordered pv_segments covering complete PV */
+	struct dm_list tags;
+};
+
+struct format_instance {
+	const struct format_type *fmt;
+	struct dm_list metadata_areas;	/* e.g. metadata locations */
+	void *private;
+};
+
+struct volume_group {
+	struct cmd_context *cmd;
+	struct format_instance *fid;
+	uint32_t seqno;		/* Metadata sequence number */
+
+	struct id id;
+	char *name;
+	char *system_id;
+
+	uint32_t status;
+	alloc_policy_t alloc;
+
+	uint32_t extent_size;
+	uint32_t extent_count;
+	uint32_t free_count;
+
+	uint32_t max_lv;
+	uint32_t max_pv;
+
+	/* physical volumes */
+	uint32_t pv_count;
+	struct dm_list pvs;
+
+	/*
+	 * logical volumes
+	 * The following relationship should always hold:
+	 * dm_list_size(lvs) = lv_count + 2 * snapshot_count
+	 *
+	 * Snapshots consist of 2 instances of "struct logical_volume":
+	 * - cow (lv_name is visible to the user)
+	 * - snapshot (lv_name is 'snapshotN')
+	 * Neither of these instances is reflected in lv_count, but we
+	 * multiply the snapshot_count by 2.
+	 *
+	 * Mirrors consist of multiple instances of "struct logical_volume":
+	 * - one for the mirror log
+	 * - one for each mirror leg
+	 * - one for the user-visible mirror LV
+	 * all of the instances are reflected in lv_count.
+	 */
+	uint32_t lv_count;
+	uint32_t snapshot_count;
+	struct dm_list lvs;
+
+	struct dm_list tags;
+};
+
+/* There will be one area for each stripe */
+struct lv_segment_area {
+	area_type_t type;
+	union {
+		struct {
+			struct pv_segment *pvseg;
+		} pv;
+		struct {
+			struct logical_volume *lv;
+			uint32_t le;
+		} lv;
+	} u;
+};
+
+struct segment_type;
+struct lv_segment {
+	struct dm_list list;
+	struct logical_volume *lv;
+
+	const struct segment_type *segtype;
+	uint32_t le;
+	uint32_t len;
+
+	uint32_t status;
+
+	/* FIXME Fields depend on segment type */
+	uint32_t stripe_size;
+	uint32_t area_count;
+	uint32_t area_len;
+	struct logical_volume *origin;
+	struct logical_volume *cow;
+	struct dm_list origin_list;
+	uint32_t chunk_size;	/* For snapshots - in sectors */
+	uint32_t region_size;	/* For mirrors - in sectors */
+	uint32_t extents_copied;
+	struct logical_volume *log_lv;
+
+	struct dm_list tags;
+
+	struct lv_segment_area *areas;
+};
+
+#define seg_type(seg, s)	(seg)->areas[(s)].type
+#define seg_pv(seg, s)		(seg)->areas[(s)].u.pv.pvseg->pv
+#define seg_lv(seg, s)		(seg)->areas[(s)].u.lv.lv
+
+struct logical_volume {
+	union lvid lvid;
+	char *name;
+
+	struct volume_group *vg;
+
+	uint32_t status;
+	alloc_policy_t alloc;
+	uint32_t read_ahead;
+	int32_t major;
+	int32_t minor;
+
+	uint64_t size;		/* Sectors */
+	uint32_t le_count;
+
+	uint32_t origin_count;
+	struct dm_list snapshot_segs;
+	struct lv_segment *snapshot;
+
+	struct dm_list segments;
+	struct dm_list tags;
+	struct dm_list segs_using_this_lv;
+};
+
+struct pe_range {
+	struct dm_list list;
+	uint32_t start;		/* PEs */
+	uint32_t count;		/* PEs */
+};
+
+struct pv_list {
+	struct dm_list list;
+	struct physical_volume *pv;
+	struct dm_list *mdas;	/* Metadata areas */
+	struct dm_list *pe_ranges;	/* Ranges of PEs e.g. for allocation */
+};
+
+struct lv_list {
+	struct dm_list list;
+	struct logical_volume *lv;
+};
+
+/*
+* 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,
+			     const char *vgid, int *consistent);
+struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
+				struct dm_list *mdas, uint64_t *label_sector,
+				int warnings);
+struct dm_list *get_pvs(struct cmd_context *cmd);
+
+/* Set full_scan to 1 to re-read every (filtered) device label */
+struct dm_list *get_vgs(struct cmd_context *cmd, int full_scan);
+struct dm_list *get_vgids(struct cmd_context *cmd, int full_scan);
+int scan_vgs_for_pvs(struct cmd_context *cmd);
+
+int pv_write(struct cmd_context *cmd, struct physical_volume *pv,
+	     struct dm_list *mdas, int64_t label_sector);
+int is_pv(pv_t *pv);
+int is_orphan_vg(const char *vg_name);
+int is_orphan(const pv_t *pv);
+int vgs_are_compatible(struct cmd_context *cmd,
+		       struct volume_group *vg_from,
+		       struct volume_group *vg_to);
+vg_t *vg_lock_and_read(struct cmd_context *cmd, const char *vg_name,
+		       const char *vgid,
+		       uint32_t lock_flags, uint32_t status_flags,
+		       uint32_t misc_flags);
+
+/* pe_start and pe_end relate to any existing data so that new metadata
+* areas can avoid overlap */
+pv_t *pv_create(const struct cmd_context *cmd,
+		      struct device *dev,
+		      struct id *id,
+		      uint64_t size,
+		      uint64_t pe_start,
+		      uint32_t existing_extent_count,
+		      uint32_t existing_extent_size,
+		      int pvmetadatacopies,
+		      uint64_t pvmetadatasize, struct dm_list *mdas);
+int pv_resize(struct physical_volume *pv, struct volume_group *vg,
+             uint32_t new_pe_count);
+int pv_analyze(struct cmd_context *cmd, const char *pv_name,
+	       uint64_t label_sector);
+
+/* FIXME: move internal to library */
+uint32_t pv_list_extents_free(const struct dm_list *pvh);
+
+struct volume_group *vg_create(struct cmd_context *cmd, const char *name,
+			       uint32_t extent_size, uint32_t max_pv,
+			       uint32_t max_lv, alloc_policy_t alloc,
+			       int pv_count, char **pv_names);
+int vg_remove(struct volume_group *vg);
+int vg_remove_single(struct cmd_context *cmd, const char *vg_name,
+		     struct volume_group *vg, int consistent,
+		     force_t force);
+int vg_rename(struct cmd_context *cmd, struct volume_group *vg,
+	      const char *new_name);
+int vg_extend(struct volume_group *vg, int pv_count, char **pv_names);
+int vg_change_pesize(struct cmd_context *cmd, struct volume_group *vg,
+		     uint32_t new_extent_size);
+int vg_split_mdas(struct cmd_context *cmd, struct volume_group *vg_from,
+		  struct volume_group *vg_to);
+
+/* Manipulate LVs */
+struct logical_volume *lv_create_empty(const char *name,
+				       union lvid *lvid,
+				       uint32_t status,
+				       alloc_policy_t alloc,
+				       int import,
+				       struct volume_group *vg);
+
+/* Write out LV contents */
+int set_lv(struct cmd_context *cmd, struct logical_volume *lv,
+           uint64_t sectors, int value);
+
+/* Reduce the size of an LV by extents */
+int lv_reduce(struct logical_volume *lv, uint32_t extents);
+
+/* Empty an LV prior to deleting it */
+int lv_empty(struct logical_volume *lv);
+
+/* Empty an LV and add error segment */
+int replace_lv_with_error_segment(struct logical_volume *lv);
+
+/* Entry point for all LV extent allocations */
+int lv_extend(struct logical_volume *lv,
+	      const struct segment_type *segtype,
+	      uint32_t stripes, uint32_t stripe_size,
+	      uint32_t mirrors, uint32_t extents,
+	      struct physical_volume *mirrored_pv, uint32_t mirrored_pe,
+	      uint32_t status, struct dm_list *allocatable_pvs,
+	      alloc_policy_t alloc);
+
+/* lv must be part of lv->vg->lvs */
+int lv_remove(struct logical_volume *lv);
+
+int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
+		     force_t force);
+
+int lv_remove_with_dependencies(struct cmd_context *cmd, struct logical_volume *lv,
+				force_t force);
+
+int lv_rename(struct cmd_context *cmd, struct logical_volume *lv,
+	      const char *new_name);
+
+/*
+ * Functions for layer manipulation
+ */
+int insert_layer_for_segments_on_pv(struct cmd_context *cmd,
+				    struct logical_volume *lv_where,
+				    struct logical_volume *layer_lv,
+				    uint32_t status,
+				    struct pv_list *pv,
+				    struct dm_list *lvs_changed);
+int remove_layers_for_segments(struct cmd_context *cmd,
+			       struct logical_volume *lv,
+			       struct logical_volume *layer_lv,
+			       uint32_t status_mask, struct dm_list *lvs_changed);
+int remove_layers_for_segments_all(struct cmd_context *cmd,
+				   struct logical_volume *layer_lv,
+				   uint32_t status_mask,
+				   struct dm_list *lvs_changed);
+int split_parent_segments_for_layer(struct cmd_context *cmd,
+				    struct logical_volume *layer_lv);
+int remove_layer_from_lv(struct logical_volume *lv,
+			 struct logical_volume *layer_lv);
+struct logical_volume *insert_layer_for_lv(struct cmd_context *cmd,
+					   struct logical_volume *lv_where,
+					   uint32_t status,
+					   const char *layer_suffix);
+
+/* Find a PV within a given VG */
+struct pv_list *find_pv_in_vg(const struct volume_group *vg,
+			      const char *pv_name);
+pv_t *find_pv_in_vg_by_uuid(const struct volume_group *vg,
+			    const struct id *id);
+
+/* Find an LV within a given VG */
+struct lv_list *find_lv_in_vg(const struct volume_group *vg,
+			      const char *lv_name);
+
+/* FIXME Merge these functions with ones above */
+struct logical_volume *find_lv(const struct volume_group *vg,
+			       const char *lv_name);
+struct physical_volume *find_pv_by_name(struct cmd_context *cmd,
+					const char *pv_name);
+
+/* Find LV segment containing given LE */
+struct lv_segment *first_seg(const struct logical_volume *lv);
+
+
+/*
+* Useful functions for managing snapshots.
+*/
+int lv_is_origin(const struct logical_volume *lv);
+int lv_is_cow(const struct logical_volume *lv);
+int lv_is_visible(const struct logical_volume *lv);
+
+int pv_is_in_vg(struct volume_group *vg, struct physical_volume *pv);
+
+/* Given a cow LV, return return the snapshot lv_segment that uses it */
+struct lv_segment *find_cow(const struct logical_volume *lv);
+
+/* Given a cow LV, return its origin */
+struct logical_volume *origin_from_cow(const struct logical_volume *lv);
+
+int vg_add_snapshot(const char *name,
+		    struct logical_volume *origin, struct logical_volume *cow,
+		    union lvid *lvid, uint32_t extent_count,
+		    uint32_t chunk_size);
+
+int vg_remove_snapshot(struct logical_volume *cow);
+
+int vg_check_status(const struct volume_group *vg, uint32_t status);
+
+/*
+* Mirroring functions
+*/
+struct lv_segment *find_mirror_seg(struct lv_segment *seg);
+int lv_add_mirrors(struct cmd_context *cmd, struct logical_volume *lv,
+		   uint32_t mirrors, uint32_t stripes,
+		   uint32_t region_size, uint32_t log_count,
+		   struct dm_list *pvs, alloc_policy_t alloc, uint32_t flags);
+int lv_remove_mirrors(struct cmd_context *cmd, struct logical_volume *lv,
+		      uint32_t mirrors, uint32_t log_count,
+		      struct dm_list *pvs, uint32_t status_mask);
+
+int is_temporary_mirror_layer(const struct logical_volume *lv);
+struct logical_volume * find_temporary_mirror(const struct logical_volume *lv);
+uint32_t lv_mirror_count(const struct logical_volume *lv);
+uint32_t adjusted_mirror_region_size(uint32_t extent_size, uint32_t extents,
+                                    uint32_t region_size);
+int remove_mirrors_from_segments(struct logical_volume *lv,
+				 uint32_t new_mirrors, uint32_t status_mask);
+int add_mirrors_to_segments(struct cmd_context *cmd, struct logical_volume *lv,
+			    uint32_t mirrors, uint32_t region_size,
+			    struct dm_list *allocatable_pvs, alloc_policy_t alloc);
+
+int remove_mirror_images(struct logical_volume *lv, uint32_t num_mirrors,
+			 struct dm_list *removable_pvs, unsigned remove_log);
+int add_mirror_images(struct cmd_context *cmd, struct logical_volume *lv,
+		      uint32_t mirrors, uint32_t stripes, uint32_t region_size,
+		      struct dm_list *allocatable_pvs, alloc_policy_t alloc,
+		      uint32_t log_count);
+struct logical_volume *detach_mirror_log(struct lv_segment *seg);
+int attach_mirror_log(struct lv_segment *seg, struct logical_volume *lv);
+int remove_mirror_log(struct cmd_context *cmd, struct logical_volume *lv,
+		      struct dm_list *removable_pvs);
+int add_mirror_log(struct cmd_context *cmd, struct logical_volume *lv,
+		   uint32_t log_count, uint32_t region_size,
+		   struct dm_list *allocatable_pvs, alloc_policy_t alloc);
+
+int reconfigure_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors,
+			      struct dm_list *removable_pvs, unsigned remove_log);
+int collapse_mirrored_lv(struct logical_volume *lv);
+int shift_mirror_images(struct lv_segment *mirrored_seg, unsigned mimage);
+
+struct logical_volume *find_pvmove_lv(struct volume_group *vg,
+				      struct device *dev, uint32_t lv_type);
+struct logical_volume *find_pvmove_lv_from_pvname(struct cmd_context *cmd,
+						  struct volume_group *vg,
+						  const char *name,
+						  uint32_t lv_type);
+const char *get_pvmove_pvname_from_lv(struct logical_volume *lv);
+const char *get_pvmove_pvname_from_lv_mirr(struct logical_volume *lv_mirr);
+float copy_percent(struct logical_volume *lv_mirr);
+struct dm_list *lvs_using_lv(struct cmd_context *cmd, struct volume_group *vg,
+			  struct logical_volume *lv);
+
+uint32_t find_free_lvnum(struct logical_volume *lv);
+char *generate_lv_name(struct volume_group *vg, const char *format,
+		       char *buffer, size_t len);
+
+/*
+* Begin skeleton for external LVM library
+*/
+struct device *pv_dev(const pv_t *pv);
+const char *pv_vg_name(const pv_t *pv);
+const char *pv_dev_name(const pv_t *pv);
+uint64_t pv_size(const pv_t *pv);
+uint32_t pv_status(const pv_t *pv);
+uint32_t pv_pe_size(const pv_t *pv);
+uint64_t pv_pe_start(const pv_t *pv);
+uint32_t pv_pe_count(const pv_t *pv);
+uint32_t pv_pe_alloc_count(const pv_t *pv);
+
+int vg_missing_pv_count(const vg_t *vg);
+uint32_t vg_status(const vg_t *vg);
+#define vg_is_clustered(vg) (vg_status((vg)) & CLUSTERED)
+
+struct vgcreate_params {
+	char *vg_name;
+	uint32_t extent_size;
+	size_t max_pv;
+	size_t max_lv;
+	alloc_policy_t alloc;
+	int clustered; /* FIXME: put this into a 'status' variable instead? */
+};
+
+int validate_vg_create_params(struct cmd_context *cmd,
+			      struct vgcreate_params *vp);
+
+int validate_vg_rename_params(struct cmd_context *cmd,
+			      const char *vg_name_old,
+			      const char *vg_name_new);
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/metadata.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/metadata.h
diff -N src/external/gpl2/lvm2tools/dist/include/metadata.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/metadata.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,352 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * This is the in core representation of a volume group and its
+ * associated physical and logical volumes.
+ */
+
+#ifndef _LVM_METADATA_H
+#define _LVM_METADATA_H
+
+#include "ctype.h"
+#include "dev-cache.h"
+#include "lvm-string.h"
+#include "metadata-exported.h"
+
+//#define MAX_STRIPES 128U
+//#define SECTOR_SHIFT 9L
+#define SECTOR_SIZE ( 1L << SECTOR_SHIFT )
+//#define STRIPE_SIZE_MIN ( (unsigned) lvm_getpagesize() >> SECTOR_SHIFT)	/* PAGESIZE in sectors */
+//#define STRIPE_SIZE_MAX ( 512L * 1024L >> SECTOR_SHIFT)	/* 512 KB in sectors */
+//#define STRIPE_SIZE_LIMIT ((UINT_MAX >> 2) + 1)
+//#define PV_MIN_SIZE ( 512L * 1024L >> SECTOR_SHIFT)	/* 512 KB in sectors */
+//#define MAX_RESTRICTED_LVS 255	/* Used by FMT_RESTRICTED_LVIDS */
+#define MIRROR_LOG_SIZE 1	/* Extents */
+
+/* Various flags */
+/* Note that the bits no longer necessarily correspond to LVM1 disk format */
+
+//#define PARTIAL_VG		0x00000001U	/* VG */
+//#define EXPORTED_VG          	0x00000002U	/* VG PV */
+//#define RESIZEABLE_VG        	0x00000004U	/* VG */
+
+/* May any free extents on this PV be used or must they be left free? */
+//#define ALLOCATABLE_PV         	0x00000008U	/* PV */
+
+#define SPINDOWN_LV          	0x00000010U	/* LV */
+#define BADBLOCK_ON       	0x00000020U	/* LV */
+//#define VISIBLE_LV		0x00000040U	/* LV */
+//#define FIXED_MINOR		0x00000080U	/* LV */
+/* FIXME Remove when metadata restructuring is completed */
+//#define SNAPSHOT		0x00001000U	/* LV - internal use only */
+//#define PVMOVE			0x00002000U	/* VG LV SEG */
+//#define LOCKED			0x00004000U	/* LV */
+//#define MIRRORED		0x00008000U	/* LV - internal use only */
+#define VIRTUAL			0x00010000U	/* LV - internal use only */
+//#define MIRROR_LOG		0x00020000U	/* LV */
+//#define MIRROR_IMAGE		0x00040000U	/* LV */
+//#define MIRROR_NOTSYNCED	0x00080000U	/* LV */
+#define ACTIVATE_EXCL		0x00100000U	/* LV - internal use only */
+#define PRECOMMITTED		0x00200000U	/* VG - internal use only */
+//#define CONVERTING		0x00400000U	/* LV */
+
+//#define MISSING_PV		0x00800000U	/* PV */
+//#define PARTIAL_LV		0x01000000U	/* LV - derived flag, not
+//						   written out in metadata*/
+
+#define POSTORDER_FLAG		0x02000000U /* Not real flags, reserved for  */
+#define POSTORDER_OPEN_FLAG	0x04000000U /* temporary use inside vg_read. */
+
+//#define LVM_READ              	0x00000100U	/* LV VG */
+//#define LVM_WRITE             	0x00000200U	/* LV VG */
+//#define CLUSTERED         	0x00000400U	/* VG */
+#define SHARED            	0x00000800U	/* VG */
+
+/* Format features flags */
+//#define FMT_SEGMENTS		0x00000001U	/* Arbitrary segment params? */
+//#define FMT_MDAS		0x00000002U	/* Proper metadata areas? */
+//#define FMT_TAGS		0x00000004U	/* Tagging? */
+//#define FMT_UNLIMITED_VOLS	0x00000008U	/* Unlimited PVs/LVs? */
+//#define FMT_RESTRICTED_LVIDS	0x00000010U	/* LVID <= 255 */
+//#define FMT_ORPHAN_ALLOCATABLE	0x00000020U	/* Orphan PV allocatable? */
+#define FMT_PRECOMMIT		0x00000040U	/* Supports pre-commit? */
+//#define FMT_RESIZE_PV		0x00000080U	/* Supports pvresize? */
+//#define FMT_UNLIMITED_STRIPESIZE 0x00000100U	/* Unlimited stripe size? */
+
+struct metadata_area;
+
+/* Per-format per-metadata area operations */
+struct metadata_area_ops {
+	struct volume_group *(*vg_read) (struct format_instance * fi,
+					 const char *vg_name,
+					 struct metadata_area * mda);
+	struct volume_group *(*vg_read_precommit) (struct format_instance * fi,
+					 const char *vg_name,
+					 struct metadata_area * mda);
+	/*
+	 * Write out complete VG metadata.  You must ensure internal
+	 * consistency before calling. eg. PEs can't refer to PVs not
+	 * part of the VG.
+	 *
+	 * It is also the responsibility of the caller to ensure external
+	 * consistency, eg by calling pv_write() if removing PVs from
+	 * a VG or calling vg_write() a second time if splitting a VG
+	 * into two.
+	 *
+	 * vg_write() should not read or write from any PVs not included
+	 * in the volume_group structure it is handed.
+	 * (format1 currently breaks this rule.)
+	 */
+	int (*vg_write) (struct format_instance * fid, struct volume_group * vg,
+			 struct metadata_area * mda);
+	int (*vg_precommit) (struct format_instance * fid,
+			     struct volume_group * vg,
+			     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);
+
+	/*
+	 * Returns number of free sectors in given metadata area.
+	 */
+	uint64_t (*mda_free_sectors) (struct metadata_area *mda);
+
+	/*
+	 * Check if metadata area belongs to vg
+	 */
+	int (*mda_in_vg) (struct format_instance * fi,
+			    struct volume_group * vg, struct metadata_area *mda);
+	/*
+	 * Analyze a metadata area on a PV.
+	 */
+	int (*pv_analyze_mda) (const struct format_type * fmt,
+			       struct metadata_area *mda);
+
+};
+
+struct metadata_area {
+	struct dm_list list;
+	struct metadata_area_ops *ops;
+	void *metadata_locn;
+};
+
+#define seg_pvseg(seg, s)	(seg)->areas[(s)].u.pv.pvseg
+#define seg_dev(seg, s)		(seg)->areas[(s)].u.pv.pvseg->pv->dev
+#define seg_pe(seg, s)		(seg)->areas[(s)].u.pv.pvseg->pe
+#define seg_le(seg, s)		(seg)->areas[(s)].u.lv.le
+
+struct name_list {
+	struct dm_list list;
+	char *name;
+};
+
+struct mda_list {
+	struct dm_list list;
+	struct device_area mda;
+};
+
+struct peg_list {
+	struct dm_list list;
+	struct pv_segment *peg;
+};
+
+struct seg_list {
+	struct dm_list list;
+	unsigned count;
+	struct lv_segment *seg;
+};
+
+/*
+ * Ownership of objects passes to caller.
+ */
+struct format_handler {
+	/*
+	 * Scan any metadata areas that aren't referenced in PV labels
+	 */
+	int (*scan) (const struct format_type * fmt);
+
+	/*
+	 * Return PV with given path.
+	 */
+	int (*pv_read) (const struct format_type * fmt, const char *pv_name,
+			struct physical_volume * pv, struct dm_list * mdas);
+
+	/*
+	 * Tweak an already filled out a pv ready for importing into a
+	 * vg.  eg. pe_count is format specific.
+	 */
+	int (*pv_setup) (const struct format_type * fmt,
+			 uint64_t pe_start, uint32_t extent_count,
+			 uint32_t extent_size,
+			 int pvmetadatacopies,
+			 uint64_t pvmetadatasize, struct dm_list * mdas,
+			 struct physical_volume * pv, struct volume_group * vg);
+
+	/*
+	 * Write a PV structure to disk. Fails if the PV is in a VG ie
+	 * pv->vg_name must be a valid orphan VG name
+	 */
+	int (*pv_write) (const struct format_type * fmt,
+			 struct physical_volume * pv, struct dm_list * mdas,
+			 int64_t label_sector);
+
+	/*
+	 * Tweak an already filled out a lv eg, check there
+	 * aren't too many extents.
+	 */
+	int (*lv_setup) (struct format_instance * fi,
+			 struct logical_volume * lv);
+
+	/*
+	 * Tweak an already filled out vg.  eg, max_pv is format
+	 * specific.
+	 */
+	int (*vg_setup) (struct format_instance * fi, struct volume_group * vg);
+
+	/*
+	 * Check whether particular segment type is supported.
+	 */
+	int (*segtype_supported) (struct format_instance *fid,
+				  const struct segment_type *segtype);
+
+	/*
+	 * Create format instance with a particular metadata area
+	 */
+	struct format_instance *(*create_instance) (const struct format_type *
+						    fmt, const char *vgname,
+						    const char *vgid,
+						    void *context);
+
+	/*
+	 * Destructor for format instance
+	 */
+	void (*destroy_instance) (struct format_instance * fid);
+
+	/*
+	 * Destructor for format type
+	 */
+	void (*destroy) (const struct format_type * fmt);
+};
+
+/*
+ * Utility functions
+ */
+unsigned long pe_align(struct physical_volume *pv);
+int vg_validate(struct volume_group *vg);
+
+int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv);
+
+/* Manipulate PV structures */
+int pv_add(struct volume_group *vg, struct physical_volume *pv);
+int pv_remove(struct volume_group *vg, struct physical_volume *pv);
+struct physical_volume *pv_find(struct volume_group *vg, const char *pv_name);
+
+/* Find a PV within a given VG */
+int get_pv_from_vg_by_id(const struct format_type *fmt, const char *vg_name,
+			 const char *vgid, const char *pvid,
+			 struct physical_volume *pv);
+
+struct lv_list *find_lv_in_vg_by_lvid(struct volume_group *vg,
+				      const union lvid *lvid);
+
+struct lv_list *find_lv_in_lv_list(const struct dm_list *ll,
+				   const struct logical_volume *lv);
+
+/* Return the VG that contains a given LV (based on path given in lv_name) */
+/* or environment var */
+struct volume_group *find_vg_with_lv(const char *lv_name);
+
+/* Find LV with given lvid (used during activation) */
+struct logical_volume *lv_from_lvid(struct cmd_context *cmd,
+				    const char *lvid_s,
+				    unsigned precommitted);
+
+/* FIXME Merge these functions with ones above */
+struct physical_volume *find_pv(struct volume_group *vg, struct device *dev);
+
+struct pv_list *find_pv_in_pv_list(const struct dm_list *pl,
+				   const struct physical_volume *pv);
+
+/* Find LV segment containing given LE */
+struct lv_segment *find_seg_by_le(const struct logical_volume *lv, uint32_t le);
+
+/* Find PV segment containing given LE */
+struct pv_segment *find_peg_by_pe(const struct physical_volume *pv, uint32_t pe);
+
+/*
+ * Remove a dev_dir if present.
+ */
+const char *strip_dir(const char *vg_name, const char *dir);
+
+/*
+ * Checks that an lv has no gaps or overlapping segments.
+ * Set complete_vg to perform additional VG level checks.
+ */
+int check_lv_segments(struct logical_volume *lv, int complete_vg);
+
+/*
+ * Sometimes (eg, after an lvextend), it is possible to merge two
+ * adjacent segments into a single segment.  This function trys
+ * to merge as many segments as possible.
+ */
+int lv_merge_segments(struct logical_volume *lv);
+
+/*
+ * Ensure there's a segment boundary at a given LE, splitting if necessary
+ */
+int lv_split_segment(struct logical_volume *lv, uint32_t le);
+
+/*
+ * Add/remove upward link from underlying LV to the segment using it
+ * FIXME: ridiculously long name
+ */
+int add_seg_to_segs_using_this_lv(struct logical_volume *lv, struct lv_segment *seg);
+int remove_seg_from_segs_using_this_lv(struct logical_volume *lv, struct lv_segment *seg);
+struct lv_segment *get_only_segment_using_this_lv(struct logical_volume *lv);
+
+/*
+ * For internal metadata caching.
+ */
+int export_vg_to_buffer(struct volume_group *vg, char **buf);
+struct volume_group *import_vg_from_buffer(char *buf,
+					   struct format_instance *fid);
+
+/*
+ * Mirroring functions
+ */
+
+/*
+ * Given mirror image or mirror log segment, find corresponding mirror segment 
+ */
+int fixup_imported_mirrors(struct volume_group *vg);
+
+/*
+ * Begin skeleton for external LVM library
+ */
+struct id pv_id(const pv_t *pv);
+const struct format_type *pv_format_type(const pv_t *pv);
+struct id pv_vgid(const pv_t *pv);
+
+pv_t *pv_by_path(struct cmd_context *cmd, const char *pv_name);
+int add_pv_to_vg(struct volume_group *vg, const char *pv_name,
+		 struct physical_volume *pv);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/netbsd.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/netbsd.h
diff -N src/external/gpl2/lvm2tools/dist/include/netbsd.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/netbsd.h	15 Jul 2008 21:40:05 -0000	1.1.2.2
@@ -0,0 +1,13 @@
+
+/*
+ * NetBSD specific header file.
+ */
+
+#ifndef __NETBSD_H__
+#define __NETBSD_H__
+
+
+/* lib/netbsd/netbsd.c  */
+int nbsd_check_dev(int, const char *);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/pogen.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/pogen.h
diff -N src/external/gpl2/lvm2tools/dist/include/pogen.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/pogen.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,25 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Macros to change log messages into a format that xgettext can handle.
+ *
+ * Note that different PRI* definitions lead to different strings for
+ * different architectures.
+ */
+
+#define print_log(level, file, line, format, args...) print_log(format, args)
+#define dm_log(level, file, line, format, args...) dm_log(format, args)
Index: src/external/gpl2/lvm2tools/dist/include/pv_alloc.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/pv_alloc.h
diff -N src/external/gpl2/lvm2tools/dist/include/pv_alloc.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/pv_alloc.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,30 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_PV_ALLOC_H
+
+int alloc_pv_segment_whole_pv(struct dm_pool *mem, struct physical_volume *pv);
+int peg_dup(struct dm_pool *mem, struct dm_list *peg_new, struct dm_list *peg_old);
+struct pv_segment *assign_peg_to_lvseg(struct physical_volume *pv, uint32_t pe,
+				       uint32_t area_len,
+				       struct lv_segment *seg,
+				       uint32_t area_num);
+int pv_split_segment(struct physical_volume *pv, uint32_t pe);
+int release_pv_segment(struct pv_segment *peg, uint32_t area_reduction);
+int check_pv_segments(struct volume_group *vg);
+void merge_pv_segments(struct pv_segment *peg1, struct pv_segment *peg2);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/report.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/report.h
diff -N src/external/gpl2/lvm2tools/dist/include/report.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/report.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,41 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_REPORT_H
+#define _LVM_REPORT_H
+
+#include "metadata-exported.h"
+
+typedef enum { LVS = 1, PVS = 2, VGS = 4, SEGS = 8, PVSEGS = 16 } report_type_t;
+
+struct field;
+struct report_handle;
+
+typedef int (*field_report_fn) (struct report_handle * dh, struct field * field,
+				const void *data);
+
+void *report_init(struct cmd_context *cmd, const char *format, const char *keys,
+		  report_type_t *report_type, const char *separator,
+		  int aligned, int buffered, int headings, int field_prefixes,
+		  int quoted, int columns_as_rows);
+void report_free(void *handle);
+int report_object(void *handle, struct volume_group *vg,
+		  struct logical_volume *lv, struct physical_volume *pv,
+		  struct lv_segment *seg, struct pv_segment *pvseg);
+int report_output(void *handle);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/segtype.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/segtype.h
diff -N src/external/gpl2/lvm2tools/dist/include/segtype.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/segtype.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,114 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _SEGTYPES_H
+#define _SEGTYPES_H
+
+struct segtype_handler;
+struct cmd_context;
+struct config_tree;
+struct lv_segment;
+struct formatter;
+struct config_node;
+struct dev_manager;
+
+/* Feature flags */
+#define SEG_CAN_SPLIT		0x00000001U
+#define SEG_AREAS_STRIPED	0x00000002U
+#define SEG_AREAS_MIRRORED	0x00000004U
+#define SEG_SNAPSHOT		0x00000008U
+#define SEG_FORMAT1_SUPPORT	0x00000010U
+#define SEG_VIRTUAL		0x00000020U
+#define SEG_CANNOT_BE_ZEROED	0x00000040U
+#define SEG_MONITORED		0x00000080U
+
+#define seg_is_mirrored(seg)	((seg)->segtype->flags & SEG_AREAS_MIRRORED ? 1 : 0)
+#define seg_is_striped(seg)	((seg)->segtype->flags & SEG_AREAS_STRIPED ? 1 : 0)
+#define seg_is_snapshot(seg)	((seg)->segtype->flags & SEG_SNAPSHOT ? 1 : 0)
+#define seg_is_virtual(seg)	((seg)->segtype->flags & SEG_VIRTUAL ? 1 : 0)
+#define seg_can_split(seg)	((seg)->segtype->flags & SEG_CAN_SPLIT ? 1 : 0)
+#define seg_cannot_be_zeroed(seg) ((seg)->segtype->flags & SEG_CANNOT_BE_ZEROED ? 1 : 0)
+#define seg_monitored(seg)	((seg)->segtype->flags & SEG_MONITORED ? 1 : 0)
+
+#define segtype_is_striped(segtype)	((segtype)->flags & SEG_AREAS_STRIPED ? 1 : 0)
+#define segtype_is_mirrored(segtype)	((segtype)->flags & SEG_AREAS_MIRRORED ? 1 : 0)
+#define segtype_is_virtual(segtype)	((segtype)->flags & SEG_VIRTUAL ? 1 : 0)
+
+struct segment_type {
+	struct dm_list list;
+	struct cmd_context *cmd;
+	uint32_t flags;
+	struct segtype_handler *ops;
+	const char *name;
+	void *library;
+	void *private;
+};
+
+struct segtype_handler {
+	const char *(*name) (const struct lv_segment * seg);
+	void (*display) (const struct lv_segment * seg);
+	int (*text_export) (const struct lv_segment * seg,
+			    struct formatter * f);
+	int (*text_import_area_count) (struct config_node * sn,
+				       uint32_t *area_count);
+	int (*text_import) (struct lv_segment * seg,
+			    const struct config_node * sn,
+			    struct dm_hash_table * pv_hash);
+	int (*merge_segments) (struct lv_segment * seg1,
+			       struct lv_segment * seg2);
+	int (*add_target_line) (struct dev_manager *dm, struct dm_pool *mem,
+                                struct cmd_context *cmd, void **target_state,
+                                struct lv_segment *seg,
+                                struct dm_tree_node *node, uint64_t len,
+                                uint32_t *pvmove_mirror_count);
+	int (*target_percent) (void **target_state, struct dm_pool * mem,
+			       struct cmd_context *cmd,
+			       struct lv_segment *seg, char *params,
+			       uint64_t *total_numerator,
+			       uint64_t *total_denominator);
+	int (*target_present) (const struct lv_segment *seg,
+			       unsigned *attributes);
+	int (*modules_needed) (struct dm_pool *mem,
+			       const struct lv_segment *seg,
+			       struct dm_list *modules);
+	void (*destroy) (const struct segment_type * segtype);
+	int (*target_monitored) (struct lv_segment *seg, int *pending);
+	int (*target_monitor_events) (struct lv_segment *seg, int events);
+	int (*target_unmonitor_events) (struct lv_segment *seg, int events);
+};
+
+struct segment_type *get_segtype_from_string(struct cmd_context *cmd,
+					     const char *str);
+
+struct segment_type *init_striped_segtype(struct cmd_context *cmd);
+struct segment_type *init_zero_segtype(struct cmd_context *cmd);
+struct segment_type *init_error_segtype(struct cmd_context *cmd);
+struct segment_type *init_free_segtype(struct cmd_context *cmd);
+
+#ifdef SNAPSHOT_INTERNAL
+struct segment_type *init_snapshot_segtype(struct cmd_context *cmd);
+#endif
+
+#ifdef MIRRORED_INTERNAL
+struct segment_type *init_mirrored_segtype(struct cmd_context *cmd);
+#endif
+
+#ifdef CRYPT_INTERNAL
+struct segment_type *init_crypt_segtype(struct cmd_context *cmd);
+#endif
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/sharedlib.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/sharedlib.h
diff -N src/external/gpl2/lvm2tools/dist/include/sharedlib.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/sharedlib.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,29 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_SHAREDLIB_H
+#define _LVM_SHAREDLIB_H
+
+#include "config.h"
+#include <dlfcn.h>
+
+void get_shared_library_path(struct cmd_context *cmd, const char *libname,
+			     char *path, size_t path_len);
+void *load_shared_library(struct cmd_context *cmd, const char *libname,
+			  const char *what, int silent);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/str_list.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/str_list.h
diff -N src/external/gpl2/lvm2tools/dist/include/str_list.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/str_list.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,30 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_STR_LIST_H
+#define _LVM_STR_LIST_H
+
+struct dm_list *str_list_create(struct dm_pool *mem);
+int str_list_add(struct dm_pool *mem, struct dm_list *sll, const char *str);
+int str_list_del(struct dm_list *sll, const char *str);
+int str_list_match_item(const struct dm_list *sll, const char *str);
+int str_list_match_list(const struct dm_list *sll, const struct dm_list *sll2);
+int str_list_lists_equal(const struct dm_list *sll, const struct dm_list *sll2);
+int str_list_dup(struct dm_pool *mem, struct dm_list *sllnew,
+		 const struct dm_list *sllold);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/targets.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/targets.h
diff -N src/external/gpl2/lvm2tools/dist/include/targets.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/targets.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,36 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_TARGETS_H
+#define _LVM_TARGETS_H
+
+struct dev_manager;
+struct lv_segment;
+
+int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
+		       char *params, size_t paramsize, int *pos,
+		       int start_area, int areas);
+
+int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
+                   struct dm_tree_node *node, uint32_t start_area, uint32_t areas);
+
+int build_dev_string(struct dev_manager *dm, char *dlid, char *devbuf,
+		     size_t bufsize, const char *desc);
+
+char *build_dlid(struct dev_manager *dm, const char *lvid, const char *layer);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/text_export.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/text_export.h
diff -N src/external/gpl2/lvm2tools/dist/include/text_export.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/text_export.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,39 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_TEXT_EXPORT_H
+#define _LVM_TEXT_EXPORT_H
+
+#define outf(args...) do {if (!out_text(args)) return_0;} while (0)
+#define outnl(f) do {if (!f->nl(f)) return_0;} while (0)
+
+struct formatter;
+struct lv_segment;
+
+int out_size(struct formatter *f, uint64_t size, const char *fmt, ...)
+    __attribute__ ((format(printf, 3, 4)));
+
+int out_hint(struct formatter *f, const char *fmt, ...)
+    __attribute__ ((format(printf, 2, 3)));
+
+int out_text(struct formatter *f, const char *fmt, ...)
+    __attribute__ ((format(printf, 2, 3)));
+
+int out_areas(struct formatter *f, const struct lv_segment *seg,
+	      const char *type);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/text_import.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/text_import.h
diff -N src/external/gpl2/lvm2tools/dist/include/text_import.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/text_import.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,28 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_TEXT_IMPORT_H
+#define _LVM_TEXT_IMPORT_H
+
+struct lv_segment;
+struct config_node;
+
+int text_import_areas(struct lv_segment *seg, const struct config_node *sn,
+		      const struct config_node *cn, struct dm_hash_table *pv_hash,
+		      uint32_t flags);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/toolcontext.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/toolcontext.h
diff -N src/external/gpl2/lvm2tools/dist/include/toolcontext.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/toolcontext.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,106 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_TOOLCONTEXT_H
+#define _LVM_TOOLCONTEXT_H
+
+#include "dev-cache.h"
+
+#include <stdio.h>
+#include <limits.h>
+
+/*
+ * Config options that can be changed while commands are processed
+ */
+struct config_info {
+	int debug;
+	int verbose;
+	int test;
+	int syslog;
+	int activation;
+	int suffix;
+	int archive;		/* should we archive ? */
+	int backup;		/* should we backup ? */
+	int read_ahead;		/* DM_READ_AHEAD_NONE or _AUTO */
+	int cache_vgmetadata;
+	const char *msg_prefix;
+	struct format_type *fmt;
+	uint64_t unit_factor;
+	int cmd_name;		/* Show command name? */
+	mode_t umask;
+	char unit_type;
+	char _padding[1];
+};
+
+struct config_tree;
+struct archive_params;
+struct backup_params;
+
+/* FIXME Split into tool & library contexts */
+/* command-instance-related variables needed by library */
+struct cmd_context {
+	struct dm_pool *libmem;	/* For permanent config data */
+	struct dm_pool *mem;	/* Transient: Cleared between each command */
+
+	const struct format_type *fmt;	/* Current format to use by default */
+	struct format_type *fmt_backup;	/* Format to use for backups */
+
+	struct dm_list formats;	/* Available formats */
+	struct dm_list segtypes;	/* Available segment types */
+	const char *hostname;
+	const char *kernel_vsn;
+
+	char *cmd_line;
+	struct command *command;
+	struct arg *args;
+	char **argv;
+	unsigned is_static:1;	/* Static binary? */
+	unsigned is_long_lived:1;	/* Optimises persistent_filter handling */
+	unsigned handles_missing_pvs:1;
+	unsigned partial_activation:1;
+
+	struct dev_filter *filter;
+	int dump_filter;	/* Dump filter when exiting? */
+
+	struct dm_list config_files;
+	int config_valid;
+	struct config_tree *cft;
+	struct config_tree *cft_override;
+	struct config_info default_settings;
+	struct config_info current_settings;
+
+	struct archive_params *archive_params;
+	struct backup_params *backup_params;
+	const char *stripe_filler;
+
+	/* List of defined tags */
+	struct dm_list tags;
+	int hosttags;
+
+	char sys_dir[PATH_MAX];
+	char dev_dir[PATH_MAX];
+	char proc_dir[PATH_MAX];
+	char sysfs_dir[PATH_MAX];
+};
+
+struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static, unsigned is_long_lived);
+void destroy_toolcontext(struct cmd_context *cmd);
+int refresh_toolcontext(struct cmd_context *cmd);
+int config_files_changed(struct cmd_context *cmd);
+int init_lvmcache_orphans(struct cmd_context *cmd);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/util.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/util.h
diff -N src/external/gpl2/lvm2tools/dist/include/util.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/util.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,32 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_UTIL_H
+#define _LVM_UTIL_H
+
+#define min(a, b) ({ typeof(a) _a = (a); \
+		     typeof(b) _b = (b); \
+		     (void) (&_a == &_b); \
+		     _a < _b ? _a : _b; })
+
+#define max(a, b) ({ typeof(a) _a = (a); \
+		     typeof(b) _b = (b); \
+		     (void) (&_a == &_b); \
+		     _a > _b ? _a : _b; })
+
+#define uninitialized_var(x) x = x
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/uuid.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/uuid.h
diff -N src/external/gpl2/lvm2tools/dist/include/uuid.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/uuid.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,59 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_UUID_H
+#define _LVM_UUID_H
+
+#define ID_LEN 32
+#define ID_LEN_S "32"
+
+struct id {
+	int8_t uuid[ID_LEN];
+};
+
+/*
+ * Unique logical volume identifier
+ * With format1 this is VG uuid + LV uuid + '\0' + padding
+ */
+union lvid {
+	struct id id[2];
+	char s[2 * sizeof(struct id) + 1 + 7];
+};
+
+int lvid_from_lvnum(union lvid *lvid, struct id *vgid, uint32_t lv_num);
+int lvnum_from_lvid(union lvid *lvid);
+int lvid_in_restricted_range(union lvid *lvid);
+
+void uuid_from_num(char *uuid, uint32_t num);
+
+int lvid_create(union lvid *lvid, struct id *vgid);
+int id_create(struct id *id);
+int id_valid(struct id *id);
+int id_equal(const struct id *lhs, const struct id *rhs);
+
+/*
+ * Fills 'buffer' with a more human readable form
+ * of the uuid.
+ */
+int id_write_format(const struct id *id, char *buffer, size_t size);
+
+/*
+ * Reads a formatted uuid.
+ */
+int id_read_format(struct id *id, const char *buffer);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/version.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/version.h
diff -N src/external/gpl2/lvm2tools/dist/include/version.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/version.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,5 @@
+/*	$NetBSD$	*/
+
+#ifndef _LVM_VERSION_H
+#define LVM_VERSION "2.2.02.43-cvs (12-08-08)"
+#endif
Index: src/external/gpl2/lvm2tools/dist/include/xlate.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/include/xlate.h
diff -N src/external/gpl2/lvm2tools/dist/include/xlate.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/include/xlate.h	13 Dec 2008 14:39:32 -0000	1.1.2.2
@@ -0,0 +1,66 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_XLATE_H
+#define _LVM_XLATE_H
+
+#ifdef linux
+#  include <endian.h>
+#  include <byteswap.h>
+#else
+#  include <machine/endian.h>
+#  define bswap_16(x) (((x) & 0x00ffU) << 8 | \
+		       ((x) & 0xff00U) >> 8)
+#  define bswap_32(x) (((x) & 0x000000ffU) << 24 | \
+		       ((x) & 0xff000000U) >> 24 | \
+		       ((x) & 0x0000ff00U) << 8  | \
+		       ((x) & 0x00ff0000U) >> 8)
+#  define bswap_64(x) (((x) & 0x00000000000000ffULL) << 56 | \
+		       ((x) & 0xff00000000000000ULL) >> 56 | \
+		       ((x) & 0x000000000000ff00ULL) << 40 | \
+		       ((x) & 0x00ff000000000000ULL) >> 40 | \
+		       ((x) & 0x0000000000ff0000ULL) << 24 | \
+		       ((x) & 0x0000ff0000000000ULL) >> 24 | \
+		       ((x) & 0x00000000ff000000ULL) << 8 | \
+		       ((x) & 0x000000ff00000000ULL) >> 8)
+#endif
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#  define xlate16(x) (x)
+#  define xlate32(x) (x)
+#  define xlate64(x) (x)
+#  define xlate16_be(x) bswap_16(x)
+#  define xlate32_be(x) bswap_32(x)
+#  define xlate64_be(x) bswap_64(x)
+#elif BYTE_ORDER == BIG_ENDIAN
+#  define xlate16(x) bswap_16(x)
+#  define xlate32(x) bswap_32(x)
+#  define xlate64(x) bswap_64(x)
+#  define xlate16_be(x) (x)
+#  define xlate32_be(x) (x)
+#  define xlate64_be(x) (x)
+#else
+#  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))
+#  define xlate16_be(x) __cpu_to_be16((x))
+#  define xlate32_be(x) __cpu_to_be32((x))
+#  define xlate64_be(x) __cpu_to_be64((x))
+#endif
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/Makefile.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/Makefile.in
diff -N src/external/gpl2/lvm2tools/dist/lib/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/Makefile.in	12 Dec 2008 16:32:58 -0000	1.1.1.1.2.1
@@ -0,0 +1,156 @@
+#
+# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+# Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+ifeq ("@LVM1@", "shared")
+  SUBDIRS = format1
+endif
+
+ifeq ("@POOL@", "shared")
+  SUBDIRS += format_pool
+endif
+
+ifeq ("@SNAPSHOTS@", "shared")
+  SUBDIRS += snapshot
+endif
+
+ifeq ("@MIRRORS@", "shared")
+  SUBDIRS += mirror
+endif
+
+SOURCES =\
+	activate/activate.c \
+	cache/lvmcache.c \
+	commands/toolcontext.c \
+	config/config.c \
+	datastruct/btree.c \
+	datastruct/str_list.c \
+	device/dev-cache.c \
+	device/dev-io.c \
+	device/dev-md.c \
+	device/device.c \
+	display/display.c \
+	error/errseg.c \
+	filters/filter-composite.c \
+	filters/filter-persistent.c \
+	filters/filter-regex.c \
+	filters/filter-sysfs.c \
+	filters/filter-md.c \
+	filters/filter.c \
+	format_text/archive.c \
+	format_text/archiver.c \
+	format_text/export.c \
+	format_text/flags.c \
+	format_text/format-text.c \
+	format_text/import.c \
+	format_text/import_vsn1.c \
+	format_text/tags.c \
+	format_text/text_label.c \
+	freeseg/freeseg.c \
+	label/label.c \
+	locking/file_locking.c \
+	locking/locking.c \
+	locking/no_locking.c \
+	log/log.c \
+	metadata/lv_manip.c \
+	metadata/merge.c \
+	metadata/metadata.c \
+	metadata/mirror.c \
+	metadata/pv_manip.c \
+	metadata/pv_map.c \
+	metadata/segtype.c \
+	metadata/snapshot_manip.c \
+	misc/crc.c \
+	misc/lvm-exec.c \
+	misc/lvm-file.c \
+	misc/lvm-globals.c \
+	misc/lvm-string.c \
+	misc/lvm-wrappers.c \
+	misc/timestamp.c \
+	misc/util.c \
+	mm/memlock.c \
+	report/report.c \
+	striped/striped.c \
+	uuid/uuid.c \
+	zero/zero.c
+
+ifeq ("@LVM1@", "internal")
+  SOURCES +=\
+	format1/disk-rep.c \
+	format1/format1.c \
+	format1/import-export.c \
+	format1/import-extents.c \
+	format1/layout.c \
+	format1/lvm1-label.c \
+	format1/vg_number.c
+endif
+
+ifeq ("@POOL@", "internal")
+  SOURCES +=\
+	format_pool/disk_rep.c \
+	format_pool/format_pool.c \
+	format_pool/import_export.c \
+	format_pool/pool_label.c
+endif
+
+ifeq ("@CLUSTER@", "internal")
+  SOURCES += locking/cluster_locking.c
+endif
+
+ifeq ("@CLUSTER@", "shared")
+  SUBDIRS += locking
+endif
+
+ifeq ("@SNAPSHOTS@", "internal")
+  SOURCES += snapshot/snapshot.c
+endif
+
+ifeq ("@MIRRORS@", "internal")
+  SOURCES += mirror/mirrored.c
+endif
+
+ifeq ("@DEVMAPPER@", "yes")
+  SOURCES +=\
+	activate/dev_manager.c \
+	activate/fs.c
+endif
+
+ifeq ("@HAVE_LIBDL@", "yes")
+  SOURCES +=\
+	locking/external_locking.c \
+	misc/sharedlib.c
+endif
+
+ifeq ("@DMEVENTD@", "yes")
+  CLDFLAGS += -ldevmapper-event
+endif
+
+LIB_STATIC = liblvm.a
+
+$(SUBDIRS): $(LIB_STATIC)
+
+CLEAN_TARGETS += liblvm.cflow
+
+include $(top_srcdir)/make.tmpl
+
+liblvm.cflow: $(SOURCES)
+	set -e; (echo -n "SOURCES += "; \
+		 echo $(SOURCES) | \
+		 sed "s/^/ /;s/ / $(top_srcdir)\/lib\//g;s/$$//"; \
+		 ) > $@
+
+cflow: liblvm.cflow
Index: src/external/gpl2/lvm2tools/dist/lib/activate/activate.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/activate/activate.c
diff -N src/external/gpl2/lvm2tools/dist/lib/activate/activate.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/activate/activate.c	13 Dec 2008 14:39:32 -0000	1.1.1.1.2.2
@@ -0,0 +1,1124 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "metadata.h"
+#include "activate.h"
+#include "memlock.h"
+#include "display.h"
+#include "fs.h"
+#include "lvm-exec.h"
+#include "lvm-file.h"
+#include "lvm-string.h"
+#include "toolcontext.h"
+#include "dev_manager.h"
+#include "str_list.h"
+#include "config.h"
+#include "filter.h"
+#include "segtype.h"
+
+#include <limits.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#define _skip(fmt, args...) log_very_verbose("Skipping: " fmt , ## args)
+
+int lvm1_present(struct cmd_context *cmd)
+{
+	char path[PATH_MAX];
+
+	if (dm_snprintf(path, sizeof(path), "%s/lvm/global", cmd->proc_dir)
+	    < 0) {
+		log_error("LVM1 proc global snprintf failed");
+		return 0;
+	}
+
+	if (path_exists(path))
+		return 1;
+	else
+		return 0;
+}
+
+int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg,
+			 struct dm_list *modules)
+{
+	unsigned int s;
+	struct lv_segment *seg2, *snap_seg;
+	struct dm_list *snh;
+
+	if (seg->segtype->ops->modules_needed &&
+	    !seg->segtype->ops->modules_needed(mem, seg, modules)) {
+		log_error("module string allocation failed");
+		return 0;
+	}
+
+	if (lv_is_origin(seg->lv))
+		dm_list_iterate(snh, &seg->lv->snapshot_segs)
+			if (!list_lv_modules(mem,
+					     dm_list_struct_base(snh,
+							      struct lv_segment,
+							      origin_list)->cow,
+					     modules))
+				return_0;
+
+	if (lv_is_cow(seg->lv)) {
+		snap_seg = find_cow(seg->lv);
+		if (snap_seg->segtype->ops->modules_needed &&
+		    !snap_seg->segtype->ops->modules_needed(mem, snap_seg,
+							    modules)) {
+			log_error("snap_seg module string allocation failed");
+			return 0;
+		}
+	}
+
+	for (s = 0; s < seg->area_count; s++) {
+		switch (seg_type(seg, s)) {
+		case AREA_LV:
+			seg2 = find_seg_by_le(seg_lv(seg, s), seg_le(seg, s));
+			if (seg2 && !list_segment_modules(mem, seg2, modules))
+				return_0;
+			break;
+		case AREA_PV:
+		case AREA_UNASSIGNED:
+			;
+		}
+	}
+
+	return 1;
+}
+
+int list_lv_modules(struct dm_pool *mem, const struct logical_volume *lv,
+		    struct dm_list *modules)
+{
+	struct lv_segment *seg;
+
+	dm_list_iterate_items(seg, &lv->segments)
+		if (!list_segment_modules(mem, seg, modules))
+			return_0;
+
+	return 1;
+}
+
+#ifndef DEVMAPPER_SUPPORT
+void set_activation(int act)
+{
+	static int warned = 0;
+
+	if (warned || !act)
+		return;
+
+	log_error("Compiled without libdevmapper support. "
+		  "Can't enable activation.");
+
+	warned = 1;
+}
+int activation(void)
+{
+	return 0;
+}
+int library_version(char *version, size_t size)
+{
+	return 0;
+}
+int driver_version(char *version, size_t size)
+{
+	return 0;
+}
+int target_version(const char *target_name, uint32_t *maj,
+		   uint32_t *min, uint32_t *patchlevel)
+{
+	return 0;
+}
+int target_present(const char *target_name, int use_modprobe)
+{
+	return 0;
+}
+int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, struct lvinfo *info,
+	    int with_open_count, int with_read_ahead)
+{
+	return 0;
+}
+int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
+		    struct lvinfo *info, int with_open_count, int with_read_ahead)
+{
+	return 0;
+}
+int lv_snapshot_percent(const struct logical_volume *lv, float *percent)
+{
+	return 0;
+}
+int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
+		      int wait, float *percent, uint32_t *event_nr)
+{
+	return 0;
+}
+int lvs_in_vg_activated(struct volume_group *vg)
+{
+	return 0;
+}
+int lvs_in_vg_activated_by_uuid_only(struct volume_group *vg)
+{
+	return 0;
+}
+int lvs_in_vg_opened(struct volume_group *vg)
+{
+	return 0;
+}
+int lv_suspend(struct cmd_context *cmd, const char *lvid_s)
+{
+	return 1;
+}
+int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
+{
+	return 1;
+}
+int lv_resume(struct cmd_context *cmd, const char *lvid_s)
+{
+	return 1;
+}
+int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
+{
+	return 1;
+}
+int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
+{
+	return 1;
+}
+int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
+			 int *activate_lv)
+{
+	return 1;
+}
+int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive)
+{
+	return 1;
+}
+int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive)
+{
+	return 1;
+}
+
+int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
+{
+	return 1;
+}
+
+int pv_uses_vg(struct physical_volume *pv,
+	       struct volume_group *vg)
+{
+	return 0;
+}
+
+void activation_release(void)
+{
+	return;
+}
+
+void activation_exit(void)
+{
+	return;
+}
+
+#else				/* DEVMAPPER_SUPPORT */
+
+static int _activation = 1;
+
+void set_activation(int act)
+{
+	if (act == _activation)
+		return;
+
+	_activation = act;
+	if (_activation)
+		log_verbose("Activation enabled. Device-mapper kernel "
+			    "driver will be used.");
+	else
+		log_warn("WARNING: Activation disabled. No device-mapper "
+			  "interaction will be attempted.");
+}
+
+int activation(void)
+{
+	return _activation;
+}
+
+static int _passes_activation_filter(struct cmd_context *cmd,
+				     struct logical_volume *lv)
+{
+	const struct config_node *cn;
+	struct config_value *cv;
+	char *str;
+	char path[PATH_MAX];
+
+	if (!(cn = find_config_tree_node(cmd, "activation/volume_list"))) {
+		/* If no host tags defined, activate */
+		if (dm_list_empty(&cmd->tags))
+			return 1;
+
+		/* If any host tag matches any LV or VG tag, activate */
+		if (str_list_match_list(&cmd->tags, &lv->tags) ||
+		    str_list_match_list(&cmd->tags, &lv->vg->tags))
+			return 1;
+
+		/* Don't activate */
+		return 0;
+	}
+
+	for (cv = cn->v; cv; cv = cv->next) {
+		if (cv->type != CFG_STRING) {
+			log_error("Ignoring invalid string in config file "
+				  "activation/volume_list");
+			continue;
+		}
+		str = cv->v.str;
+		if (!*str) {
+			log_error("Ignoring empty string in config file "
+				  "activation/volume_list");
+			continue;
+		}
+
+		/* Tag? */
+		if (*str == '@') {
+			str++;
+			if (!*str) {
+				log_error("Ignoring empty tag in config file "
+					  "activation/volume_list");
+				continue;
+			}
+			/* If any host tag matches any LV or VG tag, activate */
+			if (!strcmp(str, "*")) {
+				if (str_list_match_list(&cmd->tags, &lv->tags)
+				    || str_list_match_list(&cmd->tags,
+							   &lv->vg->tags))
+					    return 1;
+				else
+					continue;
+			}
+			/* If supplied tag matches LV or VG tag, activate */
+			if (str_list_match_item(&lv->tags, str) ||
+			    str_list_match_item(&lv->vg->tags, str))
+				return 1;
+			else
+				continue;
+		}
+		if (!strchr(str, '/')) {
+			/* vgname supplied */
+			if (!strcmp(str, lv->vg->name))
+				return 1;
+			else
+				continue;
+		}
+		/* vgname/lvname */
+		if (dm_snprintf(path, sizeof(path), "%s/%s", lv->vg->name,
+				 lv->name) < 0) {
+			log_error("dm_snprintf error from %s/%s", lv->vg->name,
+				  lv->name);
+			continue;
+		}
+		if (!strcmp(path, str))
+			return 1;
+	}
+
+	return 0;
+}
+
+int library_version(char *version, size_t size)
+{
+	if (!activation())
+		return 0;
+
+	return dm_get_library_version(version, size);
+}
+
+int driver_version(char *version, size_t size)
+{
+	if (!activation())
+		return 0;
+
+	log_very_verbose("Getting driver version");
+
+	return dm_driver_version(version, size);
+}
+
+int target_version(const char *target_name, uint32_t *maj,
+		   uint32_t *min, uint32_t *patchlevel)
+{
+	int r = 0;
+	struct dm_task *dmt;
+	struct dm_versions *target, *last_target;
+
+	log_very_verbose("Getting target version for %s", target_name);
+	if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
+		return_0;
+
+	if (!dm_task_run(dmt)) {
+		log_debug("Failed to get %s target version", target_name);
+		/* Assume this was because LIST_VERSIONS isn't supported */
+		return 1;
+	}
+
+	target = dm_task_get_versions(dmt);
+
+	do {
+		last_target = target;
+
+		if (!strcmp(target_name, target->name)) {
+			r = 1;
+			*maj = target->version[0];
+			*min = target->version[1];
+			*patchlevel = target->version[2];
+			goto out;
+		}
+
+		target = (void *) target + target->next;
+	} while (last_target != target);
+
+      out:
+	dm_task_destroy(dmt);
+
+	return r;
+}
+
+int module_present(const char *target_name)
+{
+	int ret = 0;
+#ifdef MODPROBE_CMD
+	char module[128];
+
+	if (dm_snprintf(module, sizeof(module), "dm-%s", target_name) < 0) {
+		log_error("module_present module name too long: %s",
+			  target_name);
+		return 0;
+	}
+
+	ret = exec_cmd(MODPROBE_CMD, module, "", "");
+#endif
+	return ret;
+}
+
+int target_present(const char *target_name, int use_modprobe)
+{
+	uint32_t maj, min, patchlevel;
+
+	if (!activation())
+		return 0;
+
+#ifdef MODPROBE_CMD
+	if (use_modprobe) {
+		if (target_version(target_name, &maj, &min, &patchlevel))
+			return 1;
+
+		if (!module_present(target_name))
+			return_0;
+	}
+#endif
+
+	return target_version(target_name, &maj, &min, &patchlevel);
+}
+
+/*
+ * Returns 1 if info structure populated, else 0 on failure.
+ */
+static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv, int with_mknodes,
+		    struct lvinfo *info, int with_open_count, int with_read_ahead, unsigned by_uuid_only)
+{
+	struct dm_info dminfo;
+	char *name = NULL;
+
+	if (!activation())
+		return 0;
+
+	if (!by_uuid_only &&
+	    !(name = build_dm_name(cmd->mem, lv->vg->name, lv->name, NULL)))
+		return_0;
+
+	log_debug("Getting device info for %s", name);
+	if (!dev_manager_info(lv->vg->cmd->mem, name, lv, with_mknodes,
+			      with_open_count, with_read_ahead, &dminfo,
+			      &info->read_ahead)) {
+		if (name)
+			dm_pool_free(cmd->mem, name);
+		return_0;
+	}
+
+	info->exists = dminfo.exists;
+	info->suspended = dminfo.suspended;
+	info->open_count = dminfo.open_count;
+	info->major = dminfo.major;
+	info->minor = dminfo.minor;
+	info->read_only = dminfo.read_only;
+	info->live_table = dminfo.live_table;
+	info->inactive_table = dminfo.inactive_table;
+
+	if (name)
+		dm_pool_free(cmd->mem, name);
+
+	return 1;
+}
+
+int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, struct lvinfo *info,
+	    int with_open_count, int with_read_ahead)
+{
+	return _lv_info(cmd, lv, 0, info, with_open_count, with_read_ahead, 0);
+}
+
+int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
+		    struct lvinfo *info, int with_open_count, int with_read_ahead)
+{
+	struct logical_volume *lv;
+
+	if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
+		return 0;
+
+	return _lv_info(cmd, lv, 0, info, with_open_count, with_read_ahead, 0);
+}
+
+/*
+ * Returns 1 if percent set, else 0 on failure.
+ */
+int lv_snapshot_percent(const struct logical_volume *lv, float *percent)
+{
+	int r;
+	struct dev_manager *dm;
+
+	if (!activation())
+		return 0;
+
+	if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
+		return_0;
+
+	if (!(r = dev_manager_snapshot_percent(dm, lv, percent)))
+		stack;
+
+	dev_manager_destroy(dm);
+
+	return r;
+}
+
+/* FIXME Merge with snapshot_percent */
+int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
+		      int wait, float *percent, uint32_t *event_nr)
+{
+	int r;
+	struct dev_manager *dm;
+	struct lvinfo info;
+
+	/* If mirrored LV is temporarily shrinked to 1 area (= linear),
+	 * it should be considered in-sync. */
+	if (dm_list_size(&lv->segments) == 1 && first_seg(lv)->area_count == 1) {
+		*percent = 100.0;
+		return 1;
+	}
+
+	if (!activation())
+		return 0;
+
+	if (!lv_info(cmd, lv, &info, 0, 0))
+		return_0;
+
+	if (!info.exists)
+		return 0;
+
+	if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
+		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 cmd_context *cmd, struct logical_volume *lv,
+		      unsigned by_uuid_only)
+{
+	struct lvinfo info;
+
+	if (!_lv_info(cmd, lv, 0, &info, 0, 0, by_uuid_only)) {
+		stack;
+		return -1;
+	}
+
+	return info.exists;
+}
+
+static int _lv_open_count(struct cmd_context *cmd, struct logical_volume *lv)
+{
+	struct lvinfo info;
+
+	if (!lv_info(cmd, lv, &info, 1, 0)) {
+		stack;
+		return -1;
+	}
+
+	return info.open_count;
+}
+
+static int _lv_activate_lv(struct logical_volume *lv)
+{
+	int r;
+	struct dev_manager *dm;
+
+	if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
+		return_0;
+
+	if (!(r = dev_manager_activate(dm, lv)))
+		stack;
+
+	dev_manager_destroy(dm);
+	return r;
+}
+
+static int _lv_preload(struct logical_volume *lv)
+{
+	int r;
+	struct dev_manager *dm;
+
+	if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
+		return_0;
+
+	if (!(r = dev_manager_preload(dm, lv)))
+		stack;
+
+	dev_manager_destroy(dm);
+	return r;
+}
+
+static int _lv_deactivate(struct logical_volume *lv)
+{
+	int r;
+	struct dev_manager *dm;
+
+	if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
+		return_0;
+
+	if (!(r = dev_manager_deactivate(dm, lv)))
+		stack;
+
+	dev_manager_destroy(dm);
+	return r;
+}
+
+static int _lv_suspend_lv(struct logical_volume *lv, int lockfs)
+{
+	int r;
+	struct dev_manager *dm;
+
+	if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
+		return_0;
+
+	if (!(r = dev_manager_suspend(dm, lv, lockfs)))
+		stack;
+
+	dev_manager_destroy(dm);
+	return r;
+}
+
+/*
+ * These two functions return the number of visible LVs in the state,
+ * or -1 on error.
+ */
+static int _lvs_in_vg_activated(struct volume_group *vg, unsigned by_uuid_only)
+{
+	struct lv_list *lvl;
+	int count = 0;
+
+	if (!activation())
+		return 0;
+
+	dm_list_iterate_items(lvl, &vg->lvs) {
+		if (lvl->lv->status & VISIBLE_LV)
+			count += (_lv_active(vg->cmd, lvl->lv, by_uuid_only) == 1);
+	}
+
+	return count;
+}
+
+int lvs_in_vg_activated_by_uuid_only(struct volume_group *vg)
+{
+	return _lvs_in_vg_activated(vg, 1);
+}
+
+int lvs_in_vg_activated(struct volume_group *vg)
+{
+	return _lvs_in_vg_activated(vg, 0);
+}
+
+int lvs_in_vg_opened(const struct volume_group *vg)
+{
+	const struct lv_list *lvl;
+	int count = 0;
+
+	if (!activation())
+		return 0;
+
+	dm_list_iterate_items(lvl, &vg->lvs) {
+		if (lvl->lv->status & VISIBLE_LV)
+			count += (_lv_open_count(vg->cmd, lvl->lv) > 0);
+	}
+
+	return count;
+}
+
+/*
+ * Determine whether an LV is active locally or in a cluster.
+ * Assumes vg lock held.
+ * Returns:
+ * 0 - not active locally or on any node in cluster
+ * 1 - active either locally or some node in the cluster
+ */
+int lv_is_active(struct logical_volume *lv)
+{
+	if (_lv_active(lv->vg->cmd, lv, 0))
+		return 1;
+
+	if (!vg_is_clustered(lv->vg))
+		return 0;
+
+	/*
+	 * FIXME: Cluster does not report per-node LV activation status.
+	 * Currently the best we can do is try exclusive local activation.
+	 * If that succeeds, we know the LV is not active elsewhere in the
+	 * cluster.
+	 */
+	if (activate_lv_excl(lv->vg->cmd, lv)) {
+		deactivate_lv(lv->vg->cmd, lv);
+		return 0;
+	}
+
+	/*
+	 * Exclusive local activation failed so assume it is active elsewhere.
+	 */
+	return 1;
+}
+
+/*
+ * Returns 0 if an attempt to (un)monitor the device failed.
+ * Returns 1 otherwise.
+ */
+int monitor_dev_for_events(struct cmd_context *cmd,
+			    struct logical_volume *lv, int monitor)
+{
+#ifdef DMEVENTD
+	int i, pending = 0, monitored;
+	int r = 1;
+	struct dm_list *tmp, *snh, *snht;
+	struct lv_segment *seg;
+	int (*monitor_fn) (struct lv_segment *s, int e);
+	uint32_t s;
+
+	/* skip dmeventd code altogether */
+	if (dmeventd_monitor_mode() == DMEVENTD_MONITOR_IGNORE)
+		return 1;
+
+	/*
+	 * Nothing to do if dmeventd configured not to be used.
+	 */
+	if (monitor && !dmeventd_monitor_mode())
+		return 1;
+
+	/*
+	 * In case of a snapshot device, we monitor lv->snapshot->lv,
+	 * not the actual LV itself.
+	 */
+	if (lv_is_cow(lv))
+		return monitor_dev_for_events(cmd, lv->snapshot->lv, monitor);
+
+	/*
+	 * In case this LV is a snapshot origin, we instead monitor
+	 * each of its respective snapshots (the origin itself does
+	 * not need to be monitored).
+	 *
+	 * TODO: This may change when snapshots of mirrors are allowed.
+	 */
+	if (lv_is_origin(lv)) {
+		dm_list_iterate_safe(snh, snht, &lv->snapshot_segs)
+			if (!monitor_dev_for_events(cmd, dm_list_struct_base(snh,
+				    struct lv_segment, origin_list)->cow, monitor))
+				r = 0;
+		return r;
+	}
+
+	dm_list_iterate(tmp, &lv->segments) {
+		seg = dm_list_item(tmp, struct lv_segment);
+
+		/* Recurse for AREA_LV */
+		for (s = 0; s < seg->area_count; s++) {
+			if (seg_type(seg, s) != AREA_LV)
+				continue;
+			if (!monitor_dev_for_events(cmd, seg_lv(seg, s),
+						    monitor)) {
+				log_error("Failed to %smonitor %s",
+					  monitor ? "" : "un",
+					  seg_lv(seg, s)->name);
+				r = 0;
+			}
+		}
+
+		if (!seg_monitored(seg) || (seg->status & PVMOVE))
+			continue;
+
+		monitor_fn = NULL;
+
+		/* Check monitoring status */
+		if (seg->segtype->ops->target_monitored)
+			monitored = seg->segtype->ops->target_monitored(seg, &pending);
+		else
+			continue;  /* segtype doesn't support registration */
+
+		/*
+		 * FIXME: We should really try again if pending
+		 */
+		monitored = (pending) ? 0 : monitored;
+
+		if (monitor) {
+			if (monitored)
+				log_verbose("%s/%s already monitored.", lv->vg->name, lv->name);
+			else if (seg->segtype->ops->target_monitor_events)
+				monitor_fn = seg->segtype->ops->target_monitor_events;
+		} else {
+			if (!monitored)
+				log_verbose("%s/%s already not monitored.", lv->vg->name, lv->name);
+			else if (seg->segtype->ops->target_unmonitor_events)
+				monitor_fn = seg->segtype->ops->target_unmonitor_events;
+		}
+
+		/* Do [un]monitor */
+		if (!monitor_fn)
+			continue;
+
+		log_verbose("%sonitoring %s/%s", monitor ? "M" : "Not m", lv->vg->name, lv->name);
+
+		/* FIXME specify events */
+		if (!monitor_fn(seg, 0)) {
+			log_error("%s/%s: %s segment monitoring function failed.",
+				  lv->vg->name, lv->name, seg->segtype->name);
+			return 0;
+		}
+
+		/* Check [un]monitor results */
+		/* Try a couple times if pending, but not forever... */
+		for (i = 0; i < 10; i++) {
+			pending = 0;
+			monitored = seg->segtype->ops->target_monitored(seg, &pending);
+			if (pending ||
+			    (!monitored && monitor) ||
+			    (monitored && !monitor))
+				log_very_verbose("%s/%s %smonitoring still pending: waiting...",
+						 lv->vg->name, lv->name, monitor ? "" : "un");
+			else
+				break;
+			sleep(1);
+		}
+
+		r = (monitored && monitor) || (!monitored && !monitor);
+	}
+
+	return r;
+#else
+	return 1;
+#endif
+}
+
+static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
+		       int error_if_not_suspended)
+{
+	struct logical_volume *lv, *lv_pre;
+	struct lvinfo info;
+	int lockfs = 0;
+
+	if (!activation())
+		return 1;
+
+	if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
+		return_0;
+
+	/* Use precommitted metadata if present */
+	if (!(lv_pre = lv_from_lvid(cmd, lvid_s, 1)))
+		return_0;
+
+	if (test_mode()) {
+		_skip("Suspending '%s'.", lv->name);
+		return 1;
+	}
+
+	if (!lv_info(cmd, lv, &info, 0, 0))
+		return_0;
+
+	if (!info.exists || info.suspended)
+		return error_if_not_suspended ? 0 : 1;
+
+	/* If VG was precommitted, preload devices for the LV */
+	if ((lv_pre->vg->status & PRECOMMITTED)) {
+		if (!_lv_preload(lv_pre)) {
+			/* FIXME Revert preloading */
+			return_0;
+		}
+	}
+
+	if (!monitor_dev_for_events(cmd, lv, 0))
+		/* FIXME Consider aborting here */
+		stack;
+
+	memlock_inc();
+
+	if (lv_is_origin(lv_pre) || lv_is_cow(lv_pre))
+		lockfs = 1;
+
+	if (!_lv_suspend_lv(lv, lockfs)) {
+		memlock_dec();
+		fs_unlock();
+		return 0;
+	}
+
+	return 1;
+}
+
+/* Returns success if the device is not active */
+int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
+{
+	return _lv_suspend(cmd, lvid_s, 0);
+}
+
+int lv_suspend(struct cmd_context *cmd, const char *lvid_s)
+{
+	return _lv_suspend(cmd, lvid_s, 1);
+}
+
+static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
+		      int error_if_not_active)
+{
+	struct logical_volume *lv;
+	struct lvinfo info;
+
+	if (!activation())
+		return 1;
+
+	if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
+		return 0;
+
+	if (test_mode()) {
+		_skip("Resuming '%s'.", lv->name);
+		return 1;
+	}
+
+	if (!lv_info(cmd, lv, &info, 0, 0))
+		return_0;
+
+	if (!info.exists || !info.suspended)
+		return error_if_not_active ? 0 : 1;
+
+	if (!_lv_activate_lv(lv))
+		return 0;
+
+	memlock_dec();
+	fs_unlock();
+
+	if (!monitor_dev_for_events(cmd, lv, 1))
+		stack;
+
+	return 1;
+}
+
+/* Returns success if the device is not active */
+int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
+{
+	return _lv_resume(cmd, lvid_s, 0);
+}
+
+int lv_resume(struct cmd_context *cmd, const char *lvid_s)
+{
+	return _lv_resume(cmd, lvid_s, 1);
+}
+
+int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
+{
+	struct logical_volume *lv;
+	struct lvinfo info;
+	int r;
+
+	if (!activation())
+		return 1;
+
+	if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
+		return 0;
+
+	if (test_mode()) {
+		_skip("Deactivating '%s'.", lv->name);
+		return 1;
+	}
+
+	if (!lv_info(cmd, lv, &info, 1, 0))
+		return_0;
+
+	if (!info.exists)
+		return 1;
+
+	if (info.open_count && (lv->status & VISIBLE_LV)) {
+		log_error("LV %s/%s in use: not deactivating", lv->vg->name,
+			  lv->name);
+		return 0;
+	}
+
+	if (!monitor_dev_for_events(cmd, lv, 0))
+		stack;
+
+	memlock_inc();
+	r = _lv_deactivate(lv);
+	memlock_dec();
+	fs_unlock();
+
+	return r;
+}
+
+/* Test if LV passes filter */
+int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
+			 int *activate_lv)
+{
+	struct logical_volume *lv;
+
+	if (!activation())
+		goto activate;
+
+	if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
+		return 0;
+
+	if (!_passes_activation_filter(cmd, lv)) {
+		log_verbose("Not activating %s/%s due to config file settings",
+			    lv->vg->name, lv->name);
+		*activate_lv = 0;
+		return 1;
+	}
+
+      activate:
+	*activate_lv = 1;
+	return 1;
+}
+
+static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
+			int exclusive, int filter)
+{
+	struct logical_volume *lv;
+	struct lvinfo info;
+	int r;
+
+	if (!activation())
+		return 1;
+
+	if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
+		return 0;
+
+	if (filter && !_passes_activation_filter(cmd, lv)) {
+		log_verbose("Not activating %s/%s due to config file settings",
+			    lv->vg->name, lv->name);
+		return 0;
+	}
+
+	if ((!lv->vg->cmd->partial_activation) && (lv->status & PARTIAL_LV)) {
+		log_error("Refusing activation of partial LV %s. Use --partial to override.",
+			  lv->name);
+		return_0;
+	}
+
+	if (test_mode()) {
+		_skip("Activating '%s'.", lv->name);
+		return 1;
+	}
+
+	if (!lv_info(cmd, lv, &info, 0, 0))
+		return_0;
+
+	if (info.exists && !info.suspended && info.live_table)
+		return 1;
+
+	if (exclusive)
+		lv->status |= ACTIVATE_EXCL;
+
+	memlock_inc();
+	r = _lv_activate_lv(lv);
+	memlock_dec();
+	fs_unlock();
+
+	if (r && !monitor_dev_for_events(cmd, lv, 1))
+		stack;
+
+	return r;
+}
+
+/* Activate LV */
+int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive)
+{
+	return _lv_activate(cmd, lvid_s, exclusive, 0);
+}
+
+/* Activate LV only if it passes filter */
+int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive)
+{
+	return _lv_activate(cmd, lvid_s, exclusive, 1);
+}
+
+int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
+{
+	struct lvinfo info;
+	int r = 1;
+
+	if (!lv) {
+		r = dm_mknodes(NULL);
+		fs_unlock();
+		return r;
+	}
+
+	if (!_lv_info(cmd, lv, 1, &info, 0, 0, 0))
+		return_0;
+
+	if (info.exists)
+		r = dev_manager_lv_mknodes(lv);
+	else
+		r = dev_manager_lv_rmnodes(lv);
+
+	fs_unlock();
+
+	return r;
+}
+
+/*
+ * Does PV use VG somewhere in its construction?
+ * Returns 1 on failure.
+ */
+int pv_uses_vg(struct physical_volume *pv,
+	       struct volume_group *vg)
+{
+	if (!activation())
+		return 0;
+
+	if (!dm_is_dm_major(MAJOR(pv->dev->dev)))
+		return 0;
+
+	return dev_manager_device_uses_vg(pv->dev, vg);
+}
+
+void activation_release(void)
+{
+	dev_manager_release();
+}
+
+void activation_exit(void)
+{
+	dev_manager_exit();
+}
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/activate/activate.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/activate/activate.h
diff -N src/external/gpl2/lvm2tools/dist/lib/activate/activate.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/activate/activate.h	13 Dec 2008 14:39:32 -0000	1.1.1.1.2.2
@@ -0,0 +1,112 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef LVM_ACTIVATE_H
+#define LVM_ACTIVATE_H
+
+#include "metadata-exported.h"
+
+struct lvinfo {
+	int exists;
+	int suspended;
+	unsigned int open_count;
+	int major;
+	int minor;
+	int read_only;
+	int live_table;
+	int inactive_table;
+	uint32_t read_ahead;
+};
+
+/* target attribute flags */
+#define MIRROR_LOG_CLUSTERED	0x00000001U
+
+void set_activation(int activation);
+int activation(void);
+
+int driver_version(char *version, size_t size);
+int library_version(char *version, size_t size);
+int lvm1_present(struct cmd_context *cmd);
+
+int module_present(const char *target_name);
+int target_present(const char *target_name, int use_modprobe);
+int target_version(const char *target_name, uint32_t *maj,
+                   uint32_t *min, uint32_t *patchlevel);
+int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg,
+			 struct dm_list *modules);
+int list_lv_modules(struct dm_pool *mem, const struct logical_volume *lv,
+		    struct dm_list *modules);
+
+void activation_release(void);
+void activation_exit(void);
+
+int lv_suspend(struct cmd_context *cmd, const char *lvid_s);
+int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s);
+int lv_resume(struct cmd_context *cmd, const char *lvid_s);
+int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s);
+int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive);
+int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s,
+			    int exclusive);
+int lv_deactivate(struct cmd_context *cmd, const char *lvid_s);
+
+int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv);
+
+/*
+ * Returns 1 if info structure has been populated, else 0.
+ */
+int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, struct lvinfo *info,
+	    int with_open_count, int with_read_ahead);
+int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
+		    struct lvinfo *info, int with_open_count, int with_read_ahead);
+
+/*
+ * Returns 1 if activate_lv has been set: 1 = activate; 0 = don't.
+ */
+int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
+			 int *activate_lv);
+
+/*
+ * Returns 1 if percent has been set, else 0.
+ */
+int lv_snapshot_percent(const struct logical_volume *lv, float *percent);
+int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
+		      int wait, float *percent, uint32_t *event_nr);
+
+/*
+ * Return number of LVs in the VG that are active.
+ */
+int lvs_in_vg_activated(struct volume_group *vg);
+int lvs_in_vg_activated_by_uuid_only(struct volume_group *vg);
+int lvs_in_vg_opened(const struct volume_group *vg);
+
+int lv_is_active(struct logical_volume *lv);
+
+int monitor_dev_for_events(struct cmd_context *cmd,
+			    struct logical_volume *lv, int do_reg);
+
+/*
+ * Returns 1 if PV has a dependency tree that uses anything in VG.
+ */
+int pv_uses_vg(struct physical_volume *pv,
+	       struct volume_group *vg);
+
+/*
+ * Returns 1 if mapped device is not suspended.
+ */
+int device_is_usable(dev_t dev);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/activate/dev_manager.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/activate/dev_manager.c
diff -N src/external/gpl2/lvm2tools/dist/lib/activate/dev_manager.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/activate/dev_manager.c	13 Dec 2008 14:39:32 -0000	1.1.1.1.2.2
@@ -0,0 +1,1238 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "str_list.h"
+#include "dev_manager.h"
+#include "lvm-string.h"
+#include "fs.h"
+#include "defaults.h"
+#include "segtype.h"
+#include "display.h"
+#include "toolcontext.h"
+#include "targets.h"
+#include "config.h"
+#include "filter.h"
+#include "activate.h"
+
+#include <limits.h>
+#include <dirent.h>
+
+#define MAX_TARGET_PARAMSIZE 50000
+#define UUID_PREFIX "LVM-"
+
+typedef enum {
+	PRELOAD,
+	ACTIVATE,
+	DEACTIVATE,
+	SUSPEND,
+	SUSPEND_WITH_LOCKFS,
+	CLEAN
+} action_t;
+
+struct dev_manager {
+	struct dm_pool *mem;
+
+	struct cmd_context *cmd;
+
+	void *target_state;
+	uint32_t pvmove_mirror_count;
+
+	char *vg_name;
+};
+
+struct lv_layer {
+	struct logical_volume *lv;
+	const char *old_name;
+};
+
+static char *_build_dlid(struct dm_pool *mem, const char *lvid, const char *layer)
+{
+	char *dlid;
+	size_t len;
+
+	if (!layer)
+		layer = "";
+
+	len = sizeof(UUID_PREFIX) + sizeof(union lvid) + strlen(layer);
+
+	if (!(dlid = dm_pool_alloc(mem, len))) {
+		log_error("_build_dlid: pool allocation failed for %" PRIsize_t
+			  " %s %s.", len, lvid, layer);
+		return NULL;
+	}
+
+	sprintf(dlid, UUID_PREFIX "%s%s%s", lvid, (*layer) ? "-" : "", layer);
+
+	return dlid;
+}
+
+char *build_dlid(struct dev_manager *dm, const char *lvid, const char *layer)
+{
+	return _build_dlid(dm->mem, lvid, layer);
+}
+
+static int _read_only_lv(struct logical_volume *lv)
+{
+	return (!(lv->vg->status & LVM_WRITE) || !(lv->status & LVM_WRITE));
+}
+
+/*
+ * Low level device-layer operations.
+ */
+static struct dm_task *_setup_task(const char *name, const char *uuid,
+				   uint32_t *event_nr, int task)
+{
+	struct dm_task *dmt;
+
+	if (!(dmt = dm_task_create(task)))
+		return_NULL;
+
+	if (name)
+		dm_task_set_name(dmt, name);
+
+	if (uuid && *uuid)
+		dm_task_set_uuid(dmt, uuid);
+
+	if (event_nr)
+		dm_task_set_event_nr(dmt, *event_nr);
+
+	return dmt;
+}
+
+static int _info_run(const char *name, const char *dlid, struct dm_info *info,
+		     uint32_t *read_ahead, int mknodes, int with_open_count,
+		     int with_read_ahead)
+{
+	int r = 0;
+	struct dm_task *dmt;
+	int dmtask;
+
+	dmtask = mknodes ? DM_DEVICE_MKNODES : DM_DEVICE_INFO;
+
+	if (!(dmt = _setup_task(name, dlid, 0, dmtask)))
+		return_0;
+
+	if (!with_open_count)
+		if (!dm_task_no_open_count(dmt))
+			log_error("Failed to disable open_count");
+
+	if (!dm_task_run(dmt))
+		goto_out;
+
+	if (!dm_task_get_info(dmt, info))
+		goto_out;
+
+	if (with_read_ahead) {
+		if (!dm_task_get_read_ahead(dmt, read_ahead))
+			goto_out;
+	} else if (read_ahead)
+		*read_ahead = DM_READ_AHEAD_NONE;
+
+	r = 1;
+
+      out:
+	dm_task_destroy(dmt);
+	return r;
+}
+
+int device_is_usable(dev_t dev)
+{
+	struct dm_task *dmt;
+	struct dm_info info;
+	const char *name;
+	uint64_t start, length;
+	char *target_type = NULL;
+	char *params;
+	void *next = NULL;
+	int r = 0;
+
+	if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) {
+		log_error("Failed to allocate dm_task struct to check dev status");
+		return 0;
+	}
+
+	if (!dm_task_set_major(dmt, MAJOR(dev)) || !dm_task_set_minor(dmt, MINOR(dev)))
+		goto_out;
+
+	if (!dm_task_run(dmt)) {
+		log_error("Failed to get state of mapped device");
+		goto out;
+	}
+
+	if (!dm_task_get_info(dmt, &info))
+		goto_out;
+
+	if (!info.exists || info.suspended)
+		goto out;
+
+	name = dm_task_get_name(dmt);
+
+	/* FIXME Also check for mirror block_on_error and mpath no paths */
+	/* For now, we exclude all mirrors */
+
+	do {
+		next = dm_get_next_target(dmt, next, &start, &length,
+					  &target_type, &params);
+		/* Skip if target type doesn't match */
+		if (target_type && !strcmp(target_type, "mirror"))
+			goto out;
+	} while (next);
+
+	/* FIXME Also check dependencies? */
+
+	r = 1;
+
+      out:
+	dm_task_destroy(dmt);
+	return r;
+}
+
+static int _info(const char *name, const char *dlid, int mknodes,
+		 int with_open_count, int with_read_ahead,
+		 struct dm_info *info, uint32_t *read_ahead)
+{
+	if (!mknodes && dlid && *dlid) {
+		if (_info_run(NULL, dlid, info, read_ahead, 0, with_open_count,
+			      with_read_ahead) &&
+	    	    info->exists)
+			return 1;
+		else if (_info_run(NULL, dlid + sizeof(UUID_PREFIX) - 1, info,
+				   read_ahead, 0, with_open_count,
+				   with_read_ahead) &&
+			 info->exists)
+			return 1;
+	}
+
+	if (name)
+		return _info_run(name, NULL, info, read_ahead, mknodes,
+				 with_open_count, with_read_ahead);
+
+	return 0;
+}
+
+int dev_manager_info(struct dm_pool *mem, const char *name,
+		     const struct logical_volume *lv, int with_mknodes,
+		     int with_open_count, int with_read_ahead,
+		     struct dm_info *info, uint32_t *read_ahead)
+{
+	const char *dlid;
+
+	if (!(dlid = _build_dlid(mem, lv->lvid.s, NULL))) {
+		log_error("dlid build failed for %s", lv->name);
+		return 0;
+	}
+
+	return _info(name, dlid, with_mknodes, with_open_count, with_read_ahead,
+		     info, read_ahead);
+}
+
+/* FIXME Interface must cope with multiple targets */
+static int _status_run(const char *name, const char *uuid,
+		       unsigned long long *s, unsigned long long *l,
+		       char **t, uint32_t t_size, char **p, uint32_t p_size)
+{
+	int r = 0;
+	struct dm_task *dmt;
+	struct dm_info info;
+	void *next = NULL;
+	uint64_t start, length;
+	char *type = NULL;
+	char *params = NULL;
+
+	if (!(dmt = _setup_task(name, uuid, 0, DM_DEVICE_STATUS)))
+		return_0;
+
+	if (!dm_task_no_open_count(dmt))
+		log_error("Failed to disable open_count");
+
+	if (!dm_task_run(dmt))
+		goto_out;
+
+	if (!dm_task_get_info(dmt, &info) || !info.exists)
+		goto_out;
+
+	do {
+		next = dm_get_next_target(dmt, next, &start, &length,
+					  &type, &params);
+		if (type) {
+			*s = start;
+			*l = length;
+			/* Make sure things are null terminated */
+			strncpy(*t, type, t_size);
+			(*t)[t_size - 1] = '\0';
+			strncpy(*p, params, p_size);
+			(*p)[p_size - 1] = '\0';
+
+			r = 1;
+			/* FIXME Cope with multiple targets! */
+			break;
+		}
+
+	} while (next);
+
+      out:
+	dm_task_destroy(dmt);
+	return r;
+}
+
+static int _status(const char *name, const char *uuid,
+		   unsigned long long *start, unsigned long long *length,
+		   char **type, uint32_t type_size, char **params,
+		   uint32_t param_size) __attribute__ ((unused));
+
+static int _status(const char *name, const char *uuid,
+		   unsigned long long *start, unsigned long long *length,
+		   char **type, uint32_t type_size, char **params,
+		   uint32_t param_size)
+{
+	if (uuid && *uuid) {
+		if (_status_run(NULL, uuid, start, length, type,
+				type_size, params, param_size) &&
+		    *params)
+			return 1;
+		else if (_status_run(NULL, uuid + sizeof(UUID_PREFIX) - 1, start,
+				     length, type, type_size, params,
+				     param_size) &&
+			 *params)
+			return 1;
+	}
+
+	if (name && _status_run(name, NULL, start, length, type, type_size,
+				params, param_size))
+		return 1;
+
+	return 0;
+}
+
+static int _percent_run(struct dev_manager *dm, const char *name,
+			const char *dlid,
+			const char *target_type, int wait,
+			struct logical_volume *lv, float *percent,
+			uint32_t *event_nr)
+{
+	int r = 0;
+	struct dm_task *dmt;
+	struct dm_info info;
+	void *next = NULL;
+	uint64_t start, length;
+	char *type = NULL;
+	char *params = NULL;
+	struct dm_list *segh = &lv->segments;
+	struct lv_segment *seg = NULL;
+	struct segment_type *segtype;
+
+	uint64_t total_numerator = 0, total_denominator = 0;
+
+	*percent = -1;
+
+	if (!(dmt = _setup_task(name, dlid, event_nr,
+				wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS)))
+		return_0;
+
+	if (!dm_task_no_open_count(dmt))
+		log_error("Failed to disable open_count");
+
+	if (!dm_task_run(dmt))
+		goto_out;
+
+	if (!dm_task_get_info(dmt, &info) || !info.exists)
+		goto_out;
+
+	if (event_nr)
+		*event_nr = info.event_nr;
+
+	do {
+		next = dm_get_next_target(dmt, next, &start, &length, &type,
+					  &params);
+		if (lv) {
+			if (!(segh = dm_list_next(&lv->segments, segh))) {
+				log_error("Number of segments in active LV %s "
+					  "does not match metadata", lv->name);
+				goto out;
+			}
+			seg = dm_list_item(segh, struct lv_segment);
+		}
+
+		if (!type || !params || strcmp(type, target_type))
+			continue;
+
+		if (!(segtype = get_segtype_from_string(dm->cmd, type)))
+			continue;
+
+		if (segtype->ops->target_percent &&
+		    !segtype->ops->target_percent(&dm->target_state, dm->mem,
+						  dm->cmd, seg, params,
+						  &total_numerator,
+						  &total_denominator))
+			goto_out;
+
+	} while (next);
+
+	if (lv && (segh = dm_list_next(&lv->segments, segh))) {
+		log_error("Number of segments in active LV %s does not "
+			  "match metadata", lv->name);
+		goto out;
+	}
+
+	if (total_denominator)
+		*percent = (float) total_numerator *100 / total_denominator;
+	else
+		*percent = 100;
+
+	log_debug("LV percent: %f", *percent);
+	r = 1;
+
+      out:
+	dm_task_destroy(dmt);
+	return r;
+}
+
+static int _percent(struct dev_manager *dm, const char *name, const char *dlid,
+		    const char *target_type, int wait,
+		    struct logical_volume *lv, float *percent,
+		    uint32_t *event_nr)
+{
+	if (dlid && *dlid) {
+		if (_percent_run(dm, NULL, dlid, target_type, wait, lv, percent,
+				 event_nr))
+			return 1;
+		else if (_percent_run(dm, NULL, dlid + sizeof(UUID_PREFIX) - 1,
+				      target_type, wait, lv, percent,
+				      event_nr))
+			return 1;
+	}
+
+	if (name && _percent_run(dm, name, NULL, target_type, wait, lv, percent,
+				 event_nr))
+		return 1;
+
+	return 0;
+}
+
+/*
+ * dev_manager implementation.
+ */
+struct dev_manager *dev_manager_create(struct cmd_context *cmd,
+				       const char *vg_name)
+{
+	struct dm_pool *mem;
+	struct dev_manager *dm;
+
+	if (!(mem = dm_pool_create("dev_manager", 16 * 1024)))
+		return_NULL;
+
+	if (!(dm = dm_pool_alloc(mem, sizeof(*dm))))
+		goto_bad;
+
+	dm->cmd = cmd;
+	dm->mem = mem;
+
+	if (!(dm->vg_name = dm_pool_strdup(dm->mem, vg_name)))
+		goto_bad;
+
+	dm->target_state = NULL;
+
+	return dm;
+
+      bad:
+	dm_pool_destroy(mem);
+	return NULL;
+}
+
+void dev_manager_destroy(struct dev_manager *dm)
+{
+	dm_pool_destroy(dm->mem);
+}
+
+void dev_manager_release(void)
+{
+	dm_lib_release();
+}
+
+void dev_manager_exit(void)
+{
+	dm_lib_exit();
+}
+
+int dev_manager_snapshot_percent(struct dev_manager *dm,
+				 const struct logical_volume *lv,
+				 float *percent)
+{
+	char *name;
+	const char *dlid;
+
+	/*
+	 * Build a name for the top layer.
+	 */
+	if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, NULL)))
+		return_0;
+
+	if (!(dlid = build_dlid(dm, lv->lvid.s, NULL)))
+		return_0;
+
+	/*
+	 * Try and get some info on this device.
+	 */
+	log_debug("Getting device status percentage for %s", name);
+	if (!(_percent(dm, name, dlid, "snapshot", 0, NULL, percent,
+		       NULL)))
+		return_0;
+
+	/* FIXME dm_pool_free ? */
+
+	/* If the snapshot isn't available, percent will be -1 */
+	return 1;
+}
+
+/* FIXME Merge with snapshot_percent, auto-detecting target type */
+/* FIXME Cope with more than one target */
+int dev_manager_mirror_percent(struct dev_manager *dm,
+			       struct logical_volume *lv, int wait,
+			       float *percent, uint32_t *event_nr)
+{
+	char *name;
+	const char *dlid;
+
+	/*
+	 * Build a name for the top layer.
+	 */
+	if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, NULL)))
+		return_0;
+
+	/* FIXME dm_pool_free ? */
+
+	if (!(dlid = build_dlid(dm, lv->lvid.s, NULL))) {
+		log_error("dlid build failed for %s", lv->name);
+		return 0;
+	}
+
+	log_debug("Getting device mirror status percentage for %s", name);
+	if (!(_percent(dm, name, dlid, "mirror", wait, lv, percent,
+		       event_nr)))
+		return_0;
+
+	return 1;
+}
+
+#if 0
+	log_very_verbose("%s %s", sus ? "Suspending" : "Resuming", name);
+
+	log_verbose("Loading %s", dl->name);
+			log_very_verbose("Activating %s read-only", dl->name);
+	log_very_verbose("Activated %s %s %03u:%03u", dl->name,
+			 dl->dlid, dl->info.major, dl->info.minor);
+
+	if (_get_flag(dl, VISIBLE))
+		log_verbose("Removing %s", dl->name);
+	else
+		log_very_verbose("Removing %s", dl->name);
+
+	log_debug("Adding target: %" PRIu64 " %" PRIu64 " %s %s",
+		  extent_size * seg->le, extent_size * seg->len, target, params);
+
+	log_debug("Adding target: 0 %" PRIu64 " snapshot-origin %s",
+		  dl->lv->size, params);
+	log_debug("Adding target: 0 %" PRIu64 " snapshot %s", size, params);
+	log_debug("Getting device info for %s", dl->name);
+
+	/* Rename? */
+		if ((suffix = strrchr(dl->dlid + sizeof(UUID_PREFIX) - 1, '-')))
+			suffix++;
+		new_name = build_dm_name(dm->mem, dm->vg_name, dl->lv->name,
+					suffix);
+
+static int _belong_to_vg(const char *vgname, const char *name)
+{
+	const char *v = vgname, *n = name;
+
+	while (*v) {
+		if ((*v != *n) || (*v == '-' && *(++n) != '-'))
+			return 0;
+		v++, n++;
+	}
+
+	if (*n == '-' && *(n + 1) != '-')
+		return 1;
+	else
+		return 0;
+}
+
+	if (!(snap_seg = find_cow(lv)))
+		return 1;
+
+	old_origin = snap_seg->origin;
+
+	/* Was this the last active snapshot with this origin? */
+	dm_list_iterate_items(lvl, active_head) {
+		active = lvl->lv;
+		if ((snap_seg = find_cow(active)) &&
+		    snap_seg->origin == old_origin) {
+			return 1;
+		}
+	}
+
+#endif
+
+/*************************/
+/*  NEW CODE STARTS HERE */
+/*************************/
+
+int dev_manager_lv_mknodes(const struct logical_volume *lv)
+{
+	char *name;
+
+	if (!(name = build_dm_name(lv->vg->cmd->mem, lv->vg->name,
+				   lv->name, NULL)))
+		return_0;
+
+	return fs_add_lv(lv, name);
+}
+
+int dev_manager_lv_rmnodes(const struct logical_volume *lv)
+{
+	return fs_del_lv(lv);
+}
+
+static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
+			       struct logical_volume *lv, const char *layer)
+{
+	char *dlid, *name;
+	struct dm_info info;
+
+	if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, layer)))
+		return_0;
+
+	if (!(dlid = build_dlid(dm, lv->lvid.s, layer)))
+		return_0;
+
+	log_debug("Getting device info for %s [%s]", name, dlid);
+	if (!_info(name, dlid, 0, 1, 0, &info, NULL)) {
+		log_error("Failed to get info for %s [%s].", name, dlid);
+		return 0;
+	}
+
+	if (info.exists && !dm_tree_add_dev(dtree, info.major, info.minor)) {
+		log_error("Failed to add device (%" PRIu32 ":%" PRIu32") to dtree",
+			  info.major, info.minor);
+		return 0;
+	}
+
+	return 1;
+}
+
+/*
+ * Add LV and any known dependencies
+ */
+static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, struct logical_volume *lv)
+{
+	if (!_add_dev_to_dtree(dm, dtree, lv, NULL))
+		return_0;
+
+	/* FIXME Can we avoid doing this every time? */
+	if (!_add_dev_to_dtree(dm, dtree, lv, "real"))
+		return_0;
+
+	if (!_add_dev_to_dtree(dm, dtree, lv, "cow"))
+		return_0;
+
+	if (!_add_dev_to_dtree(dm, dtree, lv, "_mlog"))
+		return_0;
+
+	return 1;
+}
+
+static struct dm_tree *_create_partial_dtree(struct dev_manager *dm, struct logical_volume *lv)
+{
+	struct dm_tree *dtree;
+	struct dm_list *snh, *snht;
+	struct lv_segment *seg;
+	uint32_t s;
+
+	if (!(dtree = dm_tree_create())) {
+		log_error("Partial dtree creation failed for %s.", lv->name);
+		return NULL;
+	}
+
+	if (!_add_lv_to_dtree(dm, dtree, lv))
+		goto_bad;
+
+	/* Add any snapshots of this LV */
+	dm_list_iterate_safe(snh, snht, &lv->snapshot_segs)
+		if (!_add_lv_to_dtree(dm, dtree, dm_list_struct_base(snh, struct lv_segment, origin_list)->cow))
+			goto_bad;
+
+	/* Add any LVs used by segments in this LV */
+	dm_list_iterate_items(seg, &lv->segments)
+		for (s = 0; s < seg->area_count; s++)
+			if (seg_type(seg, s) == AREA_LV && seg_lv(seg, s)) {
+				if (!_add_lv_to_dtree(dm, dtree, seg_lv(seg, s)))
+					goto_bad;
+			}
+
+	return dtree;
+
+bad:
+	dm_tree_free(dtree);
+	return NULL;
+}
+
+static char *_add_error_device(struct dev_manager *dm, struct dm_tree *dtree,
+			       struct lv_segment *seg, int s)
+{
+	char *id, *name;
+	char errid[32];
+	struct dm_tree_node *node;
+	struct lv_segment *seg_i;
+	int segno = -1, i = 0;;
+	uint64_t size = seg->len * seg->lv->vg->extent_size;
+
+	dm_list_iterate_items(seg_i, &seg->lv->segments) {
+		if (seg == seg_i)
+			segno = i;
+		++i;
+	}
+
+	if (segno < 0) {
+		log_error("_add_error_device called with bad segment");
+		return_NULL;
+	}
+
+	sprintf(errid, "missing_%d_%d", segno, s);
+
+	if (!(id = build_dlid(dm, seg->lv->lvid.s, errid))) 
+		return_NULL;
+
+	if (!(name = build_dm_name(dm->mem, seg->lv->vg->name,
+				   seg->lv->name, errid)))
+		return_NULL;
+	if (!(node = dm_tree_add_new_dev(dtree, name, id, 0, 0, 0, 0, 0)))
+		return_NULL;
+	if (!dm_tree_node_add_error_target(node, size))
+		return_NULL;
+
+	return id;
+}
+
+static int _add_error_area(struct dev_manager *dm, struct dm_tree_node *node,
+			   struct lv_segment *seg, int s)
+{
+	char *dlid;
+	uint64_t extent_size = seg->lv->vg->extent_size;
+
+	if (!strcmp(dm->cmd->stripe_filler, "error")) {
+		/*
+		 * FIXME, the tree pointer is first field of dm_tree_node, but
+		 * we don't have the struct definition available.
+		 */
+		struct dm_tree **tree = (struct dm_tree **) node;
+		dlid = _add_error_device(dm, *tree, seg, s);
+		if (!dlid)
+			return_0;
+		dm_tree_node_add_target_area(node, NULL, dlid,
+					     extent_size * seg_le(seg, s));
+	} else
+		dm_tree_node_add_target_area(node,
+					     dm->cmd->stripe_filler,
+					     NULL, UINT64_C(0));
+
+	return 1;
+}
+
+int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
+		   struct dm_tree_node *node, uint32_t start_area,
+		   uint32_t areas)
+{
+	uint64_t extent_size = seg->lv->vg->extent_size;
+	uint32_t s;
+	char *dlid;
+
+	for (s = start_area; s < areas; s++) {
+		if ((seg_type(seg, s) == AREA_PV &&
+		     (!seg_pvseg(seg, s) ||
+		      !seg_pv(seg, s) ||
+		      !seg_dev(seg, s))) ||
+		    (seg_type(seg, s) == AREA_LV && !seg_lv(seg, s))) {
+			if (!_add_error_area(dm, node, seg, s))
+				return_0;
+		} else if (seg_type(seg, s) == AREA_PV)
+			dm_tree_node_add_target_area(node,
+							dev_name(seg_dev(seg, s)),
+							NULL,
+							(seg_pv(seg, s)->pe_start +
+							 (extent_size * seg_pe(seg, s))));
+		else if (seg_type(seg, s) == AREA_LV) {
+			if (!(dlid = build_dlid(dm,
+						 seg_lv(seg, s)->lvid.s,
+						 NULL)))
+				return_0;
+			dm_tree_node_add_target_area(node, NULL, dlid,
+							extent_size * seg_le(seg, s));
+		} else {
+			log_error("Internal error: Unassigned area found in LV %s.",
+				  seg->lv->name);
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+static int _add_origin_target_to_dtree(struct dev_manager *dm,
+					 struct dm_tree_node *dnode,
+					 struct logical_volume *lv)
+{
+	const char *real_dlid;
+
+	if (!(real_dlid = build_dlid(dm, lv->lvid.s, "real")))
+		return_0;
+
+	if (!dm_tree_node_add_snapshot_origin_target(dnode, lv->size, real_dlid))
+		return_0;
+
+	return 1;
+}
+
+static int _add_snapshot_target_to_dtree(struct dev_manager *dm,
+					   struct dm_tree_node *dnode,
+					   struct logical_volume *lv)
+{
+	const char *origin_dlid;
+	const char *cow_dlid;
+	struct lv_segment *snap_seg;
+	uint64_t size;
+
+	if (!(snap_seg = find_cow(lv))) {
+		log_error("Couldn't find snapshot for '%s'.", lv->name);
+		return 0;
+	}
+
+	if (!(origin_dlid = build_dlid(dm, snap_seg->origin->lvid.s, "real")))
+		return_0;
+
+	if (!(cow_dlid = build_dlid(dm, snap_seg->cow->lvid.s, "cow")))
+		return_0;
+
+	size = (uint64_t) snap_seg->len * snap_seg->origin->vg->extent_size;
+
+	if (!dm_tree_node_add_snapshot_target(dnode, size, origin_dlid, cow_dlid, 1, snap_seg->chunk_size))
+		return_0;
+
+	return 1;
+}
+
+static int _add_target_to_dtree(struct dev_manager *dm,
+				  struct dm_tree_node *dnode,
+				  struct lv_segment *seg)
+{
+	uint64_t extent_size = seg->lv->vg->extent_size;
+
+	if (!seg->segtype->ops->add_target_line) {
+		log_error("_emit_target: Internal error: Can't handle "
+			  "segment type %s", seg->segtype->name);
+		return 0;
+	}
+
+	return seg->segtype->ops->add_target_line(dm, dm->mem, dm->cmd,
+						  &dm->target_state, seg,
+						  dnode,
+						  extent_size * seg->len,
+						  &dm-> pvmove_mirror_count);
+}
+
+static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
+				  struct logical_volume *lv, const char *layer);
+
+static int _add_segment_to_dtree(struct dev_manager *dm,
+				   struct dm_tree *dtree,
+				   struct dm_tree_node *dnode,
+				   struct lv_segment *seg,
+				   const char *layer)
+{
+	uint32_t s;
+	struct dm_list *snh;
+	struct lv_segment *seg_present;
+
+	/* Ensure required device-mapper targets are loaded */
+	seg_present = find_cow(seg->lv) ? : seg;
+
+	log_debug("Checking kernel supports %s segment type for %s%s%s",
+		  seg_present->segtype->name, seg->lv->name,
+		  layer ? "-" : "", layer ? : "");
+
+	if (seg_present->segtype->ops->target_present &&
+	    !seg_present->segtype->ops->target_present(seg_present, NULL)) {
+		log_error("Can't expand LV %s: %s target support missing "
+			  "from kernel?", seg->lv->name, seg_present->segtype->name);
+		return 0;
+	}
+
+	/* Add mirror log */
+	if (seg->log_lv &&
+	    !_add_new_lv_to_dtree(dm, dtree, seg->log_lv, NULL))
+		return_0;
+
+	/* If this is a snapshot origin, add real LV */
+	if (lv_is_origin(seg->lv) && !layer) {
+		if (vg_is_clustered(seg->lv->vg)) {
+			log_error("Clustered snapshots are not yet supported");
+			return 0;
+		}
+		if (!_add_new_lv_to_dtree(dm, dtree, seg->lv, "real"))
+			return_0;
+	} else if (lv_is_cow(seg->lv) && !layer) {
+		if (!_add_new_lv_to_dtree(dm, dtree, seg->lv, "cow"))
+			return_0;
+	} else {
+		/* Add any LVs used by this segment */
+		for (s = 0; s < seg->area_count; s++)
+			if ((seg_type(seg, s) == AREA_LV) &&
+			    (!_add_new_lv_to_dtree(dm, dtree, seg_lv(seg, s), NULL)))
+				return_0;
+	}
+
+	/* Now we've added its dependencies, we can add the target itself */
+	if (lv_is_origin(seg->lv) && !layer) {
+		if (!_add_origin_target_to_dtree(dm, dnode, seg->lv))
+			return_0;
+	} else if (lv_is_cow(seg->lv) && !layer) {
+		if (!_add_snapshot_target_to_dtree(dm, dnode, seg->lv))
+			return_0;
+	} else if (!_add_target_to_dtree(dm, dnode, seg))
+		return_0;
+
+	if (lv_is_origin(seg->lv) && !layer)
+		/* Add any snapshots of this LV */
+		dm_list_iterate(snh, &seg->lv->snapshot_segs)
+			if (!_add_new_lv_to_dtree(dm, dtree, dm_list_struct_base(snh, struct lv_segment, origin_list)->cow, NULL))
+				return_0;
+
+	return 1;
+}
+
+static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
+				  struct logical_volume *lv, const char *layer)
+{
+	struct lv_segment *seg;
+	struct lv_layer *lvlayer;
+	struct dm_tree_node *dnode;
+	char *name, *dlid;
+	uint32_t max_stripe_size = UINT32_C(0);
+	uint32_t read_ahead = lv->read_ahead;
+	uint32_t read_ahead_flags = UINT32_C(0);
+
+	if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, layer)))
+		return_0;
+
+	if (!(dlid = build_dlid(dm, lv->lvid.s, layer)))
+		return_0;
+
+	/* We've already processed this node if it already has a context ptr */
+	if ((dnode = dm_tree_find_node_by_uuid(dtree, dlid)) &&
+	    dm_tree_node_get_context(dnode))
+		return 1;
+
+	if (!(lvlayer = dm_pool_alloc(dm->mem, sizeof(*lvlayer)))) {
+		log_error("_add_new_lv_to_dtree: pool alloc failed for %s %s.", lv->name, layer);
+		return 0;
+	}
+
+	lvlayer->lv = lv;
+
+	/*
+	 * Add LV to dtree.
+	 * If we're working with precommitted metadata, clear any
+	 * existing inactive table left behind.
+	 * Major/minor settings only apply to the visible layer.
+	 */
+	if (!(dnode = dm_tree_add_new_dev(dtree, name, dlid,
+					     layer ? UINT32_C(0) : (uint32_t) lv->major,
+					     layer ? UINT32_C(0) : (uint32_t) lv->minor,
+					     _read_only_lv(lv),
+					     (lv->vg->status & PRECOMMITTED) ? 1 : 0,
+					     lvlayer)))
+		return_0;
+
+	/* Store existing name so we can do rename later */
+	lvlayer->old_name = dm_tree_node_get_name(dnode);
+
+	/* Create table */
+	dm->pvmove_mirror_count = 0u;
+	dm_list_iterate_items(seg, &lv->segments) {
+		if (!_add_segment_to_dtree(dm, dtree, dnode, seg, layer))
+			return_0;
+		/* These aren't real segments in the LVM2 metadata */
+		if (lv_is_origin(lv) && !layer)
+			break;
+		if (lv_is_cow(lv) && !layer)
+			break;
+		if (max_stripe_size < seg->stripe_size * seg->area_count)
+			max_stripe_size = seg->stripe_size * seg->area_count;
+	}
+
+	if (read_ahead == DM_READ_AHEAD_AUTO) {
+		/* we need RA at least twice a whole stripe - see the comment in md/raid0.c */
+		read_ahead = max_stripe_size * 2;
+		read_ahead_flags = DM_READ_AHEAD_MINIMUM_FLAG;
+	}
+
+	dm_tree_node_set_read_ahead(dnode, read_ahead, read_ahead_flags);
+
+	return 1;
+}
+
+/* FIXME: symlinks should be created/destroyed at the same time
+ * as the kernel devices but we can't do that from within libdevmapper
+ * at present so we must walk the tree twice instead. */
+
+/*
+ * Create LV symlinks for children of supplied root node.
+ */
+static int _create_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root)
+{
+	void *handle = NULL;
+	struct dm_tree_node *child;
+	struct lv_layer *lvlayer;
+	char *vgname, *lvname, *layer;
+	const char *name;
+	int r = 1;
+
+	while ((child = dm_tree_next_child(&handle, root, 0))) {
+		if (!(lvlayer = (struct lv_layer *) dm_tree_node_get_context(child)))
+			continue;
+
+		/* Detect rename */
+		name = dm_tree_node_get_name(child);
+
+		if (name && lvlayer->old_name && *lvlayer->old_name && strcmp(name, lvlayer->old_name)) {
+			if (!dm_split_lvm_name(dm->mem, lvlayer->old_name, &vgname, &lvname, &layer)) {
+				log_error("_create_lv_symlinks: Couldn't split up old device name %s", lvlayer->old_name);
+				return 0;
+			}
+			fs_rename_lv(lvlayer->lv, name, lvname);
+		} else if (!dev_manager_lv_mknodes(lvlayer->lv))
+			r = 0;
+	}
+
+	return r;
+}
+
+/*
+ * Remove LV symlinks for children of supplied root node.
+ */
+static int _remove_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root)
+{
+	void *handle = NULL;
+	struct dm_tree_node *child;
+	char *vgname, *lvname, *layer;
+	int r = 1;
+
+	while ((child = dm_tree_next_child(&handle, root, 0))) {
+		if (!dm_split_lvm_name(dm->mem, dm_tree_node_get_name(child), &vgname, &lvname, &layer)) {
+			r = 0;
+			continue;
+		}
+
+		if (!*vgname)
+			continue;
+
+		/* only top level layer has symlinks */
+		if (*layer)
+			continue;
+
+		fs_del_lv_byname(dm->cmd->dev_dir, vgname, lvname);
+	}
+
+	return r;
+}
+
+static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root)
+{
+	void *handle = NULL;
+	struct dm_tree_node *child;
+	char *vgname, *lvname, *layer;
+	const char *name, *uuid;
+
+	while ((child = dm_tree_next_child(&handle, root, 0))) {
+		if (!(name = dm_tree_node_get_name(child)))
+			continue;
+
+		if (!(uuid = dm_tree_node_get_uuid(child)))
+			continue;
+
+		if (!dm_split_lvm_name(dm->mem, name, &vgname, &lvname, &layer)) {
+			log_error("_clean_tree: Couldn't split up device name %s.", name);
+			return 0;
+		}
+
+		/* Not meant to be top level? */
+		if (!*layer)
+			continue;
+
+		if (!dm_tree_deactivate_children(root, uuid, strlen(uuid)))
+			return_0;
+	}
+
+	return 1;
+}
+
+static int _tree_action(struct dev_manager *dm, struct logical_volume *lv, action_t action)
+{
+	struct dm_tree *dtree;
+	struct dm_tree_node *root;
+	char *dlid;
+	int r = 0;
+
+	if (!(dtree = _create_partial_dtree(dm, lv)))
+		return_0;
+
+	if (!(root = dm_tree_find_node(dtree, 0, 0))) {
+		log_error("Lost dependency tree root node");
+		goto out;
+	}
+
+	if (!(dlid = build_dlid(dm, lv->lvid.s, NULL)))
+		goto_out;
+
+	/* Only process nodes with uuid of "LVM-" plus VG id. */
+	switch(action) {
+	case CLEAN:
+		/* Deactivate any unused non-toplevel nodes */
+		if (!_clean_tree(dm, root))
+			goto_out;
+		break;
+	case DEACTIVATE:
+ 		/* Deactivate LV and all devices it references that nothing else has open. */
+		if (!dm_tree_deactivate_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
+			goto_out;
+		if (!_remove_lv_symlinks(dm, root))
+			log_error("Failed to remove all device symlinks associated with %s.", lv->name);
+		break;
+	case SUSPEND:
+		dm_tree_skip_lockfs(root);
+		if ((lv->status & MIRRORED) && !(lv->status & PVMOVE))
+			dm_tree_use_no_flush_suspend(root);
+	case SUSPEND_WITH_LOCKFS:
+		if (!dm_tree_suspend_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
+			goto_out;
+		break;
+	case PRELOAD:
+	case ACTIVATE:
+		/* Add all required new devices to tree */
+		if (!_add_new_lv_to_dtree(dm, dtree, lv, NULL))
+			goto_out;
+
+		/* Preload any devices required before any suspensions */
+		if (!dm_tree_preload_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
+			goto_out;
+
+		if ((action == ACTIVATE) &&
+		    !dm_tree_activate_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
+			goto_out;
+
+		if (!_create_lv_symlinks(dm, root)) {
+			log_error("Failed to create symlinks for %s.", lv->name);
+			goto out;
+		}
+		break;
+	default:
+		log_error("_tree_action: Action %u not supported.", action);
+		goto out;
+	}	
+
+	r = 1;
+
+out:
+	dm_tree_free(dtree);
+
+	return r;
+}
+
+int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv)
+{
+	if (!_tree_action(dm, lv, ACTIVATE))
+		return_0;
+
+	return _tree_action(dm, lv, CLEAN);
+}
+
+int dev_manager_preload(struct dev_manager *dm, struct logical_volume *lv)
+{
+	/* FIXME Update the pvmove implementation! */
+	if ((lv->status & PVMOVE) || (lv->status & LOCKED))
+		return 1;
+
+	return _tree_action(dm, lv, PRELOAD);
+}
+
+int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv)
+{
+	int r;
+
+	r = _tree_action(dm, lv, DEACTIVATE);
+
+	fs_del_lv(lv);
+
+	return r;
+}
+
+int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv,
+			int lockfs)
+{
+	return _tree_action(dm, lv, lockfs ? SUSPEND_WITH_LOCKFS : SUSPEND);
+}
+
+/*
+ * Does device use VG somewhere in its construction?
+ * Returns 1 if uncertain.
+ */
+int dev_manager_device_uses_vg(struct device *dev,
+			       struct volume_group *vg)
+{
+	struct dm_tree *dtree;
+	struct dm_tree_node *root;
+	char dlid[sizeof(UUID_PREFIX) + sizeof(struct id) - 1] __attribute((aligned(8)));
+	int r = 1;
+
+	if (!(dtree = dm_tree_create())) {
+		log_error("partial dtree creation failed");
+		return r;
+	}
+
+	if (!dm_tree_add_dev(dtree, (uint32_t) MAJOR(dev->dev), (uint32_t) MINOR(dev->dev))) {
+		log_error("Failed to add device %s (%" PRIu32 ":%" PRIu32") to dtree",
+			  dev_name(dev), (uint32_t) MAJOR(dev->dev), (uint32_t) MINOR(dev->dev));
+		goto out;
+	}
+
+	memcpy(dlid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1);
+	memcpy(dlid + sizeof(UUID_PREFIX) - 1, &vg->id.uuid[0], sizeof(vg->id));
+
+	if (!(root = dm_tree_find_node(dtree, 0, 0))) {
+		log_error("Lost dependency tree root node");
+		goto out;
+	}
+
+	if (dm_tree_children_use_uuid(root, dlid, sizeof(UUID_PREFIX) + sizeof(vg->id) - 1))
+		goto_out;
+
+	r = 0;
+
+out:
+	dm_tree_free(dtree);
+	return r;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/activate/dev_manager.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/activate/dev_manager.h
diff -N src/external/gpl2/lvm2tools/dist/lib/activate/dev_manager.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/activate/dev_manager.h	13 Dec 2008 14:39:32 -0000	1.1.1.1.2.2
@@ -0,0 +1,70 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_DEV_MANAGER_H
+#define _LVM_DEV_MANAGER_H
+
+struct logical_volume;
+struct volume_group;
+struct cmd_context;
+struct dev_manager;
+struct dm_info;
+struct device;
+
+/*
+ * Constructor and destructor.
+ */
+struct dev_manager *dev_manager_create(struct cmd_context *cmd,
+				       const char *vg_name);
+void dev_manager_destroy(struct dev_manager *dm);
+void dev_manager_release(void);
+void dev_manager_exit(void);
+
+/*
+ * The device handler is responsible for creating all the layered
+ * dm devices, and ensuring that all constraints are maintained
+ * (eg, an origin is created before its snapshot, but is not
+ * unsuspended until the snapshot is also created.)
+ */
+int dev_manager_info(struct dm_pool *mem, const char *name,
+		     const struct logical_volume *lv,
+		     int mknodes, int with_open_count, int with_read_ahead,
+		     struct dm_info *info, uint32_t *read_ahead);
+int dev_manager_snapshot_percent(struct dev_manager *dm,
+				 const 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 lockfs);
+int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv);
+int dev_manager_preload(struct dev_manager *dm, struct logical_volume *lv);
+int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv);
+
+int dev_manager_lv_mknodes(const struct logical_volume *lv);
+int dev_manager_lv_rmnodes(const struct logical_volume *lv);
+
+/*
+ * Put the desired changes into effect.
+ */
+int dev_manager_execute(struct dev_manager *dm);
+
+int dev_manager_device_uses_vg(struct device *dev,
+			       struct volume_group *vg);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/activate/fs.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/activate/fs.c
diff -N src/external/gpl2/lvm2tools/dist/lib/activate/fs.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/activate/fs.c	12 Dec 2008 16:32:58 -0000	1.1.1.1.2.3
@@ -0,0 +1,431 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "fs.h"
+#include "toolcontext.h"
+#include "lvm-string.h"
+#include "lvm-file.h"
+#include "memlock.h"
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <limits.h>
+#include <dirent.h>
+
+static int _mk_dir(const char *dev_dir, const char *vg_name)
+{
+	char vg_path[PATH_MAX];
+
+	if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
+			 dev_dir, vg_name) == -1) {
+		log_error("Couldn't construct name of volume "
+			  "group directory.");
+		return 0;
+	}
+
+	if (dir_exists(vg_path))
+		return 1;
+
+	log_very_verbose("Creating directory %s", vg_path);
+	if (mkdir(vg_path, 0777)) {
+		log_sys_error("mkdir", vg_path);
+		return 0;
+	}
+
+	return 1;
+}
+
+static int _rm_dir(const char *dev_dir, const char *vg_name)
+{
+	char vg_path[PATH_MAX];
+
+	if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
+			 dev_dir, vg_name) == -1) {
+		log_error("Couldn't construct name of volume "
+			  "group directory.");
+		return 0;
+	}
+
+	if (dir_exists(vg_path) && is_empty_dir(vg_path)) {
+		log_very_verbose("Removing directory %s", vg_path);
+		rmdir(vg_path);
+	}
+
+	return 1;
+}
+
+static void _rm_blks(const char *dir)
+{
+	const char *name;
+	char path[PATH_MAX];
+	struct dirent *dirent;
+	struct stat buf;
+	DIR *d;
+
+	if (!(d = opendir(dir))) {
+		log_sys_error("opendir", dir);
+		return;
+	}
+
+	while ((dirent = readdir(d))) {
+		name = dirent->d_name;
+
+		if (!strcmp(name, ".") || !strcmp(name, ".."))
+			continue;
+
+		if (dm_snprintf(path, sizeof(path), "%s/%s", dir, name) == -1) {
+			log_error("Couldn't create path for %s", name);
+			continue;
+		}
+
+		if (!lstat(path, &buf)) {
+			if (!S_ISBLK(buf.st_mode))
+				continue;
+			log_very_verbose("Removing %s", path);
+			if (unlink(path) < 0)
+				log_sys_error("unlink", path);
+		}
+#ifdef __NetBSD__
+		if (dm_snprintf(path, sizeof(path), "%s/r%s", dir, name) == -1) {
+			log_error("Couldn't create path for r%s", name);
+			continue;
+		}
+
+		if (!lstat(path, &buf)) {
+			if (!S_ISCHR(buf.st_mode))
+				continue;
+			log_very_verbose("Removing %s", path);
+			if (unlink(path) < 0)
+				log_sys_error("unlink", path);
+		}
+#endif		
+	}
+}
+
+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;
+
+#ifdef __NetBSD__
+	/* Add support for creating links to BSD raw devices */
+	char raw_lv_path[PATH_MAX], raw_link_path[PATH_MAX];
+#endif	
+
+	if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
+			 dev_dir, vg_name) == -1) {
+		log_error("Couldn't create path for volume group dir %s",
+			  vg_name);
+		return 0;
+	}
+
+#ifdef __NetBSD__
+	if (dm_snprintf(raw_lv_path, sizeof(raw_lv_path), "%s/r%s", vg_path,
+		lv_name) == -1) {
+		log_error("Couldn't create source pathname for "
+		    "logical volume link r%s", lv_name);
+		return 0;
+	}
+
+	if (dm_snprintf(raw_link_path, sizeof(raw_link_path), "%s/r%s",
+		dm_dir(), dev) == -1) {
+		log_error("Couldn't create destination pathname for "
+		    "logical volume link for %s", lv_name);
+		return 0;
+	}
+
+	if (!lstat(raw_lv_path, &buf)) {
+		if (!S_ISLNK(buf.st_mode) && !S_ISCHR(buf.st_mode)) {
+			log_error("Symbolic link %s not created: file exists",
+				  raw_link_path);
+			return 0;
+		}
+
+		log_very_verbose("Removing %s", raw_lv_path);
+		if (unlink(raw_lv_path) < 0) {
+			log_sys_error("unlink", raw_lv_path);
+			return 0;
+		}
+	}
+
+	log_very_verbose("Linking %s -> %s", raw_lv_path, raw_link_path);
+	if (symlink(raw_link_path, raw_lv_path) < 0) {
+		log_sys_error("symlink", raw_lv_path);
+		return 0;
+	}
+	
+#endif	
+	if (dm_snprintf(lv_path, sizeof(lv_path), "%s/%s", vg_path,
+			 lv_name) == -1) {
+		log_error("Couldn't create source pathname for "
+			  "logical volume link %s", lv_name);
+		return 0;
+	}
+
+	if (dm_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);
+		return 0;
+	}
+
+	if (dm_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",
+			  vg_name);
+		return 0;
+	}
+
+	/* To reach this point, the VG must have been locked.
+	 * As locking fails if the VG is active under LVM1, it's
+	 * now safe to remove any LVM1 devices we find here
+	 * (as well as any existing LVM2 symlink). */
+	if (!lstat(lvm1_group_path, &buf)) {
+		if (!S_ISCHR(buf.st_mode)) {
+			log_error("Non-LVM1 character device found at %s",
+				  lvm1_group_path);
+		} else {
+			_rm_blks(vg_path);
+
+			log_very_verbose("Removing %s", lvm1_group_path);
+			if (unlink(lvm1_group_path) < 0)
+				log_sys_error("unlink", lvm1_group_path);
+		}
+	}
+
+	if (!lstat(lv_path, &buf)) {
+		if (!S_ISLNK(buf.st_mode) && !S_ISBLK(buf.st_mode)) {
+			log_error("Symbolic link %s not created: file exists",
+				  link_path);
+			return 0;
+		}
+
+		log_very_verbose("Removing %s", lv_path);
+		if (unlink(lv_path) < 0) {
+			log_sys_error("unlink", lv_path);
+			return 0;
+		}
+	}
+
+	log_very_verbose("Linking %s -> %s", lv_path, link_path);
+	if (symlink(link_path, lv_path) < 0) {
+		log_sys_error("symlink", lv_path);
+		return 0;
+	}
+
+#ifdef HAVE_SELINUX
+	if (!dm_set_selinux_context(lv_path, S_IFLNK))
+		return_0;
+#endif
+
+	return 1;
+}
+
+static int _rm_link(const char *dev_dir, const char *vg_name,
+		    const char *lv_name)
+{
+	struct stat buf;
+	char lv_path[PATH_MAX];
+
+#ifdef __NetBSD__
+	/* Add support for removing links to BSD raw devices */
+	char raw_lv_path[PATH_MAX];
+
+	if (dm_snprintf(raw_lv_path, sizeof(raw_lv_path), "%s%s/r%s",
+			 dev_dir, vg_name, lv_name) == -1) {
+		log_error("Couldn't determine link pathname.");
+		return 0;
+	}
+
+	if (lstat(raw_lv_path, &buf) || !S_ISLNK(buf.st_mode)) {
+		if (errno == ENOENT)
+			return 1;
+		log_error("%s not symbolic link - not removing", raw_lv_path);
+		return 0;
+	}
+
+	log_very_verbose("Removing link %s", raw_lv_path);
+	if (unlink(raw_lv_path) < 0) {
+		log_sys_error("unlink", raw_lv_path);
+		return 0;
+	}
+#endif
+	if (dm_snprintf(lv_path, sizeof(lv_path), "%s%s/%s",
+			 dev_dir, vg_name, lv_name) == -1) {
+		log_error("Couldn't determine link pathname.");
+		return 0;
+	}
+
+	if (lstat(lv_path, &buf) || !S_ISLNK(buf.st_mode)) {
+		if (errno == ENOENT)
+			return 1;
+		log_error("%s not symbolic link - not removing", lv_path);
+		return 0;
+	}
+
+	log_very_verbose("Removing link %s", lv_path);
+	if (unlink(lv_path) < 0) {
+		log_sys_error("unlink", lv_path);
+		return 0;
+	}
+
+	return 1;
+}
+
+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)
+{
+	switch (type) {
+	case FS_ADD:
+		if (!_mk_dir(dev_dir, vg_name) ||
+		    !_mk_link(dev_dir, vg_name, lv_name, dev))
+			return_0;
+		break;
+	case FS_DEL:
+		if (!_rm_link(dev_dir, vg_name, lv_name) ||
+		    !_rm_dir(dev_dir, vg_name))
+			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 DM_LIST_INIT(_fs_ops);
+
+struct fs_op_parms {
+	struct dm_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 = dm_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);
+
+	dm_list_add(&_fs_ops, &fsp->list);
+
+	return 1;
+}
+
+static void _pop_fs_ops(void)
+{
+	struct dm_list *fsph, *fspht;
+	struct fs_op_parms *fsp;
+
+	dm_list_iterate_safe(fsph, fspht, &_fs_ops) {
+		fsp = dm_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);
+		dm_list_del(&fsp->list);
+		dm_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))
+			return_0;
+		return 1;
+	}
+
+	return _do_fs_op(type, dev_dir, vg_name, lv_name, dev, old_lv_name);
+}
+
+int fs_add_lv(const 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(const struct logical_volume *lv)
+{
+	return _fs_op(FS_DEL, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
+		      "", "");
+}
+
+int fs_del_lv_byname(const char *dev_dir, const char *vg_name, const char *lv_name)
+{
+	return _fs_op(FS_DEL, dev_dir, vg_name, lv_name, "", "");
+}
+
+int fs_rename_lv(struct logical_volume *lv,
+		 const char *dev, const char *old_name)
+{
+	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();
+	}
+}
Index: src/external/gpl2/lvm2tools/dist/lib/activate/fs.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/activate/fs.h
diff -N src/external/gpl2/lvm2tools/dist/lib/activate/fs.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/activate/fs.h	13 Dec 2008 14:39:32 -0000	1.1.1.1.2.2
@@ -0,0 +1,35 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_FS_H
+#define _LVM_FS_H
+
+#include "metadata.h"
+
+/*
+ * These calls, private to the activate unit, set
+ * up the volume group directory in /dev and the
+ * symbolic links to the dm device.
+ */
+int fs_add_lv(const struct logical_volume *lv, const char *dev);
+int fs_del_lv(const struct logical_volume *lv);
+int fs_del_lv_byname(const char *dev_dir, const char *vg_name, const char *lv_name);
+int fs_rename_lv(struct logical_volume *lv,
+		 const char *dev, const char *old_name);
+void fs_unlock(void);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/activate/targets.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/activate/targets.h
diff -N src/external/gpl2/lvm2tools/dist/lib/activate/targets.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/activate/targets.h	13 Dec 2008 14:39:32 -0000	1.1.1.1.2.2
@@ -0,0 +1,36 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_TARGETS_H
+#define _LVM_TARGETS_H
+
+struct dev_manager;
+struct lv_segment;
+
+int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
+		       char *params, size_t paramsize, int *pos,
+		       int start_area, int areas);
+
+int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
+                   struct dm_tree_node *node, uint32_t start_area, uint32_t areas);
+
+int build_dev_string(struct dev_manager *dm, char *dlid, char *devbuf,
+		     size_t bufsize, const char *desc);
+
+char *build_dlid(struct dev_manager *dm, const char *lvid, const char *layer);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/cache/lvmcache.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/cache/lvmcache.c
diff -N src/external/gpl2/lvm2tools/dist/lib/cache/lvmcache.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/cache/lvmcache.c	13 Dec 2008 14:39:32 -0000	1.1.1.1.2.2
@@ -0,0 +1,1257 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "lvmcache.h"
+#include "toolcontext.h"
+#include "dev-cache.h"
+#include "locking.h"
+#include "metadata.h"
+#include "filter.h"
+#include "memlock.h"
+#include "str_list.h"
+#include "format-text.h"
+#include "format_pool.h"
+#include "format1.h"
+
+static struct dm_hash_table *_pvid_hash = NULL;
+static struct dm_hash_table *_vgid_hash = NULL;
+static struct dm_hash_table *_vgname_hash = NULL;
+static struct dm_hash_table *_lock_hash = NULL;
+static struct dm_list _vginfos;
+static int _scanning_in_progress = 0;
+static int _has_scanned = 0;
+static int _vgs_locked = 0;
+static int _vg_global_lock_held = 0;	/* Global lock held when cache wiped? */
+
+int lvmcache_init(void)
+{
+	dm_list_init(&_vginfos);
+
+	if (!(_vgname_hash = dm_hash_create(128)))
+		return 0;
+
+	if (!(_vgid_hash = dm_hash_create(128)))
+		return 0;
+
+	if (!(_pvid_hash = dm_hash_create(128)))
+		return 0;
+
+	if (!(_lock_hash = dm_hash_create(128)))
+		return 0;
+
+	if (_vg_global_lock_held)
+		lvmcache_lock_vgname(VG_GLOBAL, 0);
+
+	return 1;
+}
+
+/* Volume Group metadata cache functions */
+static void _free_cached_vgmetadata(struct lvmcache_vginfo *vginfo)
+{
+	if (!vginfo || !vginfo->vgmetadata)
+		return;
+
+	dm_free(vginfo->vgmetadata);
+
+	vginfo->vgmetadata = NULL;
+
+	log_debug("Metadata cache: VG %s wiped.", vginfo->vgname);
+}
+
+static void _store_metadata(struct lvmcache_vginfo *vginfo,
+			    struct volume_group *vg, unsigned precommitted)
+{
+	int size;
+
+	if (vginfo->vgmetadata)
+		_free_cached_vgmetadata(vginfo);
+
+	if (!(size = export_vg_to_buffer(vg, &vginfo->vgmetadata))) {
+		stack;
+		return;
+	}
+
+	vginfo->precommitted = precommitted;
+
+	log_debug("Metadata cache: VG %s stored (%d bytes%s).", vginfo->vgname,
+		  size, precommitted ? ", precommitted" : "");
+}
+
+static void _update_cache_info_lock_state(struct lvmcache_info *info,
+					  int locked,
+					  int *cached_vgmetadata_valid)
+{
+	int was_locked = (info->status & CACHE_LOCKED) ? 1 : 0;
+
+	/*
+	 * Cache becomes invalid whenever lock state changes unless
+	 * exclusive VG_GLOBAL is held (i.e. while scanning).
+	 */
+	if (!vgname_is_locked(VG_GLOBAL) && (was_locked != locked)) {
+		info->status |= CACHE_INVALID;
+		*cached_vgmetadata_valid = 0;
+	}
+
+	if (locked)
+		info->status |= CACHE_LOCKED;
+	else
+		info->status &= ~CACHE_LOCKED;
+}
+
+static void _update_cache_vginfo_lock_state(struct lvmcache_vginfo *vginfo,
+					    int locked)
+{
+	struct lvmcache_info *info;
+	int cached_vgmetadata_valid = 1;
+
+	dm_list_iterate_items(info, &vginfo->infos)
+		_update_cache_info_lock_state(info, locked,
+					      &cached_vgmetadata_valid);
+
+	if (!cached_vgmetadata_valid)
+		_free_cached_vgmetadata(vginfo);
+}
+
+static void _update_cache_lock_state(const char *vgname, int locked)
+{
+	struct lvmcache_vginfo *vginfo;
+
+	if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
+		return;
+
+	_update_cache_vginfo_lock_state(vginfo, locked);
+}
+
+static void _drop_metadata(const char *vgname)
+{
+	struct lvmcache_vginfo *vginfo;
+	struct lvmcache_info *info;
+
+	if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
+		return;
+
+	/*
+	 * Invalidate cached PV labels.
+	 * If cached precommitted metadata exists that means we
+	 * already invalidated the PV labels (before caching it)
+	 * and we must not do it again.
+	 */
+
+	if (!vginfo->precommitted)
+		dm_list_iterate_items(info, &vginfo->infos)
+			info->status |= CACHE_INVALID;
+
+	_free_cached_vgmetadata(vginfo);
+}
+
+void lvmcache_drop_metadata(const char *vgname)
+{
+	/* For VG_ORPHANS, we need to invalidate all labels on orphan PVs. */
+	if (!strcmp(vgname, VG_ORPHANS)) {
+		_drop_metadata(FMT_TEXT_ORPHAN_VG_NAME);
+		_drop_metadata(FMT_LVM1_ORPHAN_VG_NAME);
+		_drop_metadata(FMT_POOL_ORPHAN_VG_NAME);
+
+		/* Indicate that PVs could now be missing from the cache */
+		init_full_scan_done(0);
+	} else if (!vgname_is_locked(VG_GLOBAL))
+		_drop_metadata(vgname);
+}
+
+void lvmcache_lock_vgname(const char *vgname, int read_only __attribute((unused)))
+{
+	if (!_lock_hash && !lvmcache_init()) {
+		log_error("Internal cache initialisation failed");
+		return;
+	}
+
+	if (dm_hash_lookup(_lock_hash, vgname))
+		log_error("Internal error: Nested locking attempted on VG %s.",
+			  vgname);
+		
+	if (!dm_hash_insert(_lock_hash, vgname, (void *) 1))
+		log_error("Cache locking failure for %s", vgname);
+
+	_update_cache_lock_state(vgname, 1);
+
+	if (strcmp(vgname, VG_GLOBAL))
+		_vgs_locked++;
+}
+
+int vgname_is_locked(const char *vgname)
+{
+	if (!_lock_hash)
+		return 0;
+
+	return dm_hash_lookup(_lock_hash, vgname) ? 1 : 0;
+}
+
+void lvmcache_unlock_vgname(const char *vgname)
+{
+	if (!dm_hash_lookup(_lock_hash, vgname))
+		log_error("Internal error: Attempt to unlock unlocked VG %s.",
+			  vgname);
+
+	_update_cache_lock_state(vgname, 0);
+
+	dm_hash_remove(_lock_hash, vgname);
+
+	/* FIXME Do this per-VG */
+	if (strcmp(vgname, VG_GLOBAL) && !--_vgs_locked)
+		dev_close_all();
+}
+
+int vgs_locked(void)
+{
+	return _vgs_locked;
+}
+
+static void _vginfo_attach_info(struct lvmcache_vginfo *vginfo,
+				struct lvmcache_info *info)
+{
+	if (!vginfo)
+		return;
+
+	info->vginfo = vginfo;
+	dm_list_add(&vginfo->infos, &info->list);
+}
+
+static void _vginfo_detach_info(struct lvmcache_info *info)
+{
+	if (!dm_list_empty(&info->list)) {
+		dm_list_del(&info->list);
+		dm_list_init(&info->list);
+	}
+
+	info->vginfo = NULL;
+}
+
+/* If vgid supplied, require a match. */
+struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname, const char *vgid)
+{
+	struct lvmcache_vginfo *vginfo;
+
+	if (!vgname)
+		return vginfo_from_vgid(vgid);
+
+	if (!_vgname_hash)
+		return NULL;
+
+	if (!(vginfo = dm_hash_lookup(_vgname_hash, vgname)))
+		return NULL;
+
+	if (vgid)
+		do
+			if (!strncmp(vgid, vginfo->vgid, ID_LEN))
+				return vginfo;
+		while ((vginfo = vginfo->next));
+
+	return vginfo;
+}
+
+const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid)
+{
+	struct lvmcache_vginfo *vginfo;
+	struct lvmcache_info *info;
+	struct label *label;
+	struct dm_list *devh, *tmp;
+	struct dm_list devs;
+	struct device_list *devl;
+	char vgid_found[ID_LEN + 1] __attribute((aligned(8)));
+
+	if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
+		return NULL;
+
+	/* This function is normally called before reading metadata so
+ 	 * we check cached labels here. Unfortunately vginfo is volatile. */
+	dm_list_init(&devs);
+	dm_list_iterate_items(info, &vginfo->infos) {
+		if (!(devl = dm_malloc(sizeof(*devl)))) {
+			log_error("device_list element allocation failed");
+			return NULL;
+		}
+		devl->dev = info->dev;
+		dm_list_add(&devs, &devl->list);
+	}
+
+	memcpy(vgid_found, vginfo->vgid, sizeof(vgid_found));
+
+	dm_list_iterate_safe(devh, tmp, &devs) {
+		devl = dm_list_item(devh, struct device_list);
+		label_read(devl->dev, &label, UINT64_C(0));
+		dm_list_del(&devl->list);
+		dm_free(devl);
+	}
+
+	/* If vginfo changed, caller needs to rescan */
+	if (!(vginfo = vginfo_from_vgname(vgname, vgid_found)) ||
+	    strncmp(vginfo->vgid, vgid_found, ID_LEN))
+		return NULL;
+
+	return vginfo->fmt;
+}
+
+struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid)
+{
+	struct lvmcache_vginfo *vginfo;
+	char id[ID_LEN + 1] __attribute((aligned(8)));
+
+	if (!_vgid_hash || !vgid)
+		return NULL;
+
+	/* vgid not necessarily NULL-terminated */
+	strncpy(&id[0], vgid, ID_LEN);
+	id[ID_LEN] = '\0';
+
+	if (!(vginfo = dm_hash_lookup(_vgid_hash, id)))
+		return NULL;
+
+	return vginfo;
+}
+
+const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid)
+{
+	struct lvmcache_vginfo *vginfo;
+	const char *vgname = NULL;
+
+	if ((vginfo = vginfo_from_vgid(vgid)))
+		vgname = vginfo->vgname;
+
+	if (mem && vgname)
+		return dm_pool_strdup(mem, vgname);
+
+	return vgname;
+}
+
+static int _info_is_valid(struct lvmcache_info *info)
+{
+	if (info->status & CACHE_INVALID)
+		return 0;
+
+	/*
+	 * The caller must hold the VG lock to manipulate metadata.
+	 * In a cluster, remote nodes sometimes read metadata in the
+	 * knowledge that the controlling node is holding the lock.
+	 * So if the VG appears to be unlocked here, it should be safe
+	 * to use the cached value.
+	 */
+	if (info->vginfo && !vgname_is_locked(info->vginfo->vgname))
+		return 1;
+
+	if (!(info->status & CACHE_LOCKED))
+		return 0;
+
+	return 1;
+}
+
+static int _vginfo_is_valid(struct lvmcache_vginfo *vginfo)
+{
+	struct lvmcache_info *info;
+
+	/* Invalid if any info is invalid */
+	dm_list_iterate_items(info, &vginfo->infos)
+		if (!_info_is_valid(info))
+			return 0;
+
+	return 1;
+}
+
+/* vginfo is invalid if it does not contain at least one valid info */
+static int _vginfo_is_invalid(struct lvmcache_vginfo *vginfo)
+{
+	struct lvmcache_info *info;
+
+	dm_list_iterate_items(info, &vginfo->infos)
+		if (_info_is_valid(info))
+			return 0;
+
+	return 1;
+}
+
+/*
+ * If valid_only is set, data will only be returned if the cached data is
+ * known still to be valid.
+ */
+struct lvmcache_info *info_from_pvid(const char *pvid, int valid_only)
+{
+	struct lvmcache_info *info;
+	char id[ID_LEN + 1] __attribute((aligned(8)));
+
+	if (!_pvid_hash || !pvid)
+		return NULL;
+
+	strncpy(&id[0], pvid, ID_LEN);
+	id[ID_LEN] = '\0';
+
+	if (!(info = dm_hash_lookup(_pvid_hash, id)))
+		return NULL;
+
+	if (valid_only && !_info_is_valid(info))
+		return NULL;
+
+	return info;
+}
+
+static void _rescan_entry(struct lvmcache_info *info)
+{
+	struct label *label;
+
+	if (info->status & CACHE_INVALID)
+		label_read(info->dev, &label, UINT64_C(0));
+}
+
+static int _scan_invalid(void)
+{
+	dm_hash_iter(_pvid_hash, (dm_hash_iterate_fn) _rescan_entry);
+
+	return 1;
+}
+
+int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
+{
+	struct label *label;
+	struct dev_iter *iter;
+	struct device *dev;
+	struct format_type *fmt;
+
+	int r = 0;
+
+	/* Avoid recursion when a PVID can't be found! */
+	if (_scanning_in_progress)
+		return 0;
+
+	_scanning_in_progress = 1;
+
+	if (!_vgname_hash && !lvmcache_init()) {
+		log_error("Internal cache initialisation failed");
+		goto out;
+	}
+
+	if (_has_scanned && !full_scan) {
+		r = _scan_invalid();
+		goto out;
+	}
+
+	if (!(iter = dev_iter_create(cmd->filter, (full_scan == 2) ? 1 : 0))) {
+		log_error("dev_iter creation failed");
+		goto out;
+	}
+
+	while ((dev = dev_iter_get(iter)))
+		label_read(dev, &label, UINT64_C(0));
+
+	dev_iter_destroy(iter);
+
+	_has_scanned = 1;
+
+	/* Perform any format-specific scanning e.g. text files */
+	dm_list_iterate_items(fmt, &cmd->formats) {
+		if (fmt->ops->scan && !fmt->ops->scan(fmt))
+			goto out;
+	}
+
+	r = 1;
+
+      out:
+	_scanning_in_progress = 0;
+
+	return r;
+}
+
+struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted)
+{
+	struct lvmcache_vginfo *vginfo;
+	struct volume_group *vg;
+	struct format_instance *fid;
+
+	if (!vgid || !(vginfo = vginfo_from_vgid(vgid)) || !vginfo->vgmetadata)
+		return NULL;
+
+	if (!_vginfo_is_valid(vginfo))
+		return NULL;
+
+	/*
+	 * Don't return cached data if either:
+	 * (i)  precommitted metadata is requested but we don't have it cached
+	 *      - caller should read it off disk;
+	 * (ii) live metadata is requested but we have precommitted metadata cached
+	 *      and no devices are suspended so caller may read it off disk.
+	 *
+	 * If live metadata is requested but we have precommitted metadata cached
+	 * and devices are suspended, we assume this precommitted metadata has
+	 * already been preloaded and committed so it's OK to return it as live.
+	 * Note that we do not clear the PRECOMMITTED flag.
+	 */
+	if ((precommitted && !vginfo->precommitted) ||
+	    (!precommitted && vginfo->precommitted && !memlock()))
+		return NULL;
+
+	if (!(fid =  vginfo->fmt->ops->create_instance(vginfo->fmt,
+						       vginfo->vgname,
+						       vgid, NULL)))
+		return_NULL;
+
+	if (!(vg = import_vg_from_buffer(vginfo->vgmetadata, fid)) ||
+	    !vg_validate(vg)) {
+		_free_cached_vgmetadata(vginfo);
+		return_NULL;
+	}
+
+	log_debug("Using cached %smetadata for VG %s.",
+		  vginfo->precommitted ? "pre-committed" : "", vginfo->vgname);
+
+	return vg;
+}
+
+struct dm_list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan)
+{
+	struct dm_list *vgids;
+	struct lvmcache_vginfo *vginfo;
+
+	lvmcache_label_scan(cmd, full_scan);
+
+	if (!(vgids = str_list_create(cmd->mem))) {
+		log_error("vgids list allocation failed");
+		return NULL;
+	}
+
+	dm_list_iterate_items(vginfo, &_vginfos) {
+		if (!str_list_add(cmd->mem, vgids,
+				  dm_pool_strdup(cmd->mem, vginfo->vgid))) {
+			log_error("strlist allocation failed");
+			return NULL;
+		}
+	}
+
+	return vgids;
+}
+
+struct dm_list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
+{
+	struct dm_list *vgnames;
+	struct lvmcache_vginfo *vginfo;
+
+	lvmcache_label_scan(cmd, full_scan);
+
+	if (!(vgnames = str_list_create(cmd->mem))) {
+		log_error("vgnames list allocation failed");
+		return NULL;
+	}
+
+	dm_list_iterate_items(vginfo, &_vginfos) {
+		if (!str_list_add(cmd->mem, vgnames,
+				  dm_pool_strdup(cmd->mem, vginfo->vgname))) {
+			log_error("strlist allocation failed");
+			return NULL;
+		}
+	}
+
+	return vgnames;
+}
+
+struct dm_list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
+				const char *vgid)
+{
+	struct dm_list *pvids;
+	struct lvmcache_vginfo *vginfo;
+	struct lvmcache_info *info;
+
+	if (!(pvids = str_list_create(cmd->mem))) {
+		log_error("pvids list allocation failed");
+		return NULL;
+	}
+
+	if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
+		return pvids;
+
+	dm_list_iterate_items(info, &vginfo->infos) {
+		if (!str_list_add(cmd->mem, pvids,
+				  dm_pool_strdup(cmd->mem, info->dev->pvid))) {
+			log_error("strlist allocation failed");
+			return NULL;
+		}
+	}
+
+	return pvids;
+}
+
+struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
+{
+	struct label *label;
+	struct lvmcache_info *info;
+
+	/* Already cached ? */
+	if ((info = info_from_pvid((char *) pvid, 0))) {
+		if (label_read(info->dev, &label, UINT64_C(0))) {
+			info = (struct lvmcache_info *) label->info;
+			if (id_equal(pvid, (struct id *) &info->dev->pvid))
+				return info->dev;
+		}
+	}
+
+	lvmcache_label_scan(cmd, 0);
+
+	/* Try again */
+	if ((info = info_from_pvid((char *) pvid, 0))) {
+		if (label_read(info->dev, &label, UINT64_C(0))) {
+			info = (struct lvmcache_info *) label->info;
+			if (id_equal(pvid, (struct id *) &info->dev->pvid))
+				return info->dev;
+		}
+	}
+
+	if (memlock())
+		return NULL;
+
+	lvmcache_label_scan(cmd, 2);
+
+	/* Try again */
+	if ((info = info_from_pvid((char *) pvid, 0))) {
+		if (label_read(info->dev, &label, UINT64_C(0))) {
+			info = (struct lvmcache_info *) label->info;
+			if (id_equal(pvid, (struct id *) &info->dev->pvid))
+				return info->dev;
+		}
+	}
+
+	return NULL;
+}
+
+static int _free_vginfo(struct lvmcache_vginfo *vginfo)
+{
+	struct lvmcache_vginfo *primary_vginfo, *vginfo2;
+	int r = 1;
+
+	_free_cached_vgmetadata(vginfo);
+
+	vginfo2 = primary_vginfo = vginfo_from_vgname(vginfo->vgname, NULL);
+
+	if (vginfo == primary_vginfo) {
+		dm_hash_remove(_vgname_hash, vginfo->vgname);
+		if (vginfo->next && !dm_hash_insert(_vgname_hash, vginfo->vgname,
+						    vginfo->next)) {
+			log_error("_vgname_hash re-insertion for %s failed",
+				  vginfo->vgname);
+			r = 0;
+		}
+	} else do
+		if (vginfo2->next == vginfo) {
+			vginfo2->next = vginfo->next;
+			break;
+		}
+ 	while ((vginfo2 = primary_vginfo->next));
+
+	if (vginfo->vgname)
+		dm_free(vginfo->vgname);
+
+	if (vginfo->creation_host)
+		dm_free(vginfo->creation_host);
+
+	if (*vginfo->vgid && _vgid_hash &&
+	    vginfo_from_vgid(vginfo->vgid) == vginfo)
+		dm_hash_remove(_vgid_hash, vginfo->vgid);
+
+	dm_list_del(&vginfo->list);
+
+	dm_free(vginfo);
+
+	return r;
+}
+
+/*
+ * vginfo must be info->vginfo unless info is NULL
+ */
+static int _drop_vginfo(struct lvmcache_info *info, struct lvmcache_vginfo *vginfo)
+{
+	if (info)
+		_vginfo_detach_info(info);
+
+	/* vginfo still referenced? */
+	if (!vginfo || is_orphan_vg(vginfo->vgname) ||
+	    !dm_list_empty(&vginfo->infos))
+		return 1;
+
+	if (!_free_vginfo(vginfo))
+		return_0;
+
+	return 1;
+}
+
+/* Unused
+void lvmcache_del(struct lvmcache_info *info)
+{
+	if (info->dev->pvid[0] && _pvid_hash)
+		dm_hash_remove(_pvid_hash, info->dev->pvid);
+
+	_drop_vginfo(info, info->vginfo);
+
+	info->label->labeller->ops->destroy_label(info->label->labeller,
+						info->label);
+	dm_free(info);
+
+	return;
+} */
+
+static int _lvmcache_update_pvid(struct lvmcache_info *info, const char *pvid)
+{
+	if (!strcmp(info->dev->pvid, pvid))
+		return 1;
+	if (*info->dev->pvid) {
+		dm_hash_remove(_pvid_hash, info->dev->pvid);
+	}
+	strncpy(info->dev->pvid, pvid, sizeof(info->dev->pvid));
+	if (!dm_hash_insert(_pvid_hash, pvid, info)) {
+		log_error("_lvmcache_update: pvid insertion failed: %s", pvid);
+		return 0;
+	}
+
+	return 1;
+}
+
+/*
+ * vginfo must be info->vginfo unless info is NULL (orphans)
+ */
+static int _lvmcache_update_vgid(struct lvmcache_info *info,
+				 struct lvmcache_vginfo *vginfo,
+				 const char *vgid)
+{
+	if (!vgid || !vginfo ||
+	    !strncmp(vginfo->vgid, vgid, ID_LEN))
+		return 1;
+
+	if (vginfo && *vginfo->vgid)
+		dm_hash_remove(_vgid_hash, vginfo->vgid);
+	if (!vgid) {
+		log_debug("lvmcache: %s: clearing VGID", info ? dev_name(info->dev) : vginfo->vgname);
+		return 1;
+	}
+
+	strncpy(vginfo->vgid, vgid, ID_LEN);
+	vginfo->vgid[ID_LEN] = '\0';
+	if (!dm_hash_insert(_vgid_hash, vginfo->vgid, vginfo)) {
+		log_error("_lvmcache_update: vgid hash insertion failed: %s",
+			  vginfo->vgid);
+		return 0;
+	}
+
+	if (!is_orphan_vg(vginfo->vgname))
+		log_debug("lvmcache: %s: setting %s VGID to %s",
+			  dev_name(info->dev), vginfo->vgname,
+			  vginfo->vgid);
+
+	return 1;
+}
+
+static int _insert_vginfo(struct lvmcache_vginfo *new_vginfo, const char *vgid,
+			  uint32_t vgstatus, const char *creation_host,
+			  struct lvmcache_vginfo *primary_vginfo)
+{
+	struct lvmcache_vginfo *last_vginfo = primary_vginfo;
+	char uuid_primary[64] __attribute((aligned(8)));
+	char uuid_new[64] __attribute((aligned(8)));
+	int use_new = 0;
+	
+	/* Pre-existing VG takes precedence. Unexported VG takes precedence. */
+	if (primary_vginfo) {
+		if (!id_write_format((const struct id *)vgid, uuid_new, sizeof(uuid_new)))
+			return_0;
+
+		if (!id_write_format((const struct id *)&primary_vginfo->vgid, uuid_primary,
+				     sizeof(uuid_primary)))
+			return_0;
+
+		/*
+		 * If   Primary not exported, new exported => keep
+		 * Else Primary exported, new not exported => change
+		 * Else Primary has hostname for this machine => keep
+		 * Else Primary has no hostname, new has one => change
+		 * Else New has hostname for this machine => change
+		 * Else Keep primary.
+		 */
+		if (!(primary_vginfo->status & EXPORTED_VG) &&
+		    (vgstatus & EXPORTED_VG))
+			log_error("WARNING: Duplicate VG name %s: "
+				  "Existing %s takes precedence over "
+				  "exported %s", new_vginfo->vgname,
+				  uuid_primary, uuid_new);
+		else if ((primary_vginfo->status & EXPORTED_VG) &&
+			   !(vgstatus & EXPORTED_VG)) {
+			log_error("WARNING: Duplicate VG name %s: "
+				  "%s takes precedence over exported %s",
+				  new_vginfo->vgname, uuid_new,
+				  uuid_primary);
+			use_new = 1;
+		} else if (primary_vginfo->creation_host &&
+			   !strcmp(primary_vginfo->creation_host,
+				   primary_vginfo->fmt->cmd->hostname))
+			log_error("WARNING: Duplicate VG name %s: "
+				  "Existing %s (created here) takes precedence "
+				  "over %s", new_vginfo->vgname, uuid_primary,
+				  uuid_new);
+		else if (!primary_vginfo->creation_host && creation_host) {
+			log_error("WARNING: Duplicate VG name %s: "
+				  "%s (with creation_host) takes precedence over %s",
+				  new_vginfo->vgname, uuid_new,
+				  uuid_primary);
+			use_new = 1;
+		} else if (creation_host &&
+			   !strcmp(creation_host,
+				   primary_vginfo->fmt->cmd->hostname)) {
+			log_error("WARNING: Duplicate VG name %s: "
+				  "%s (created here) takes precedence over %s",
+				  new_vginfo->vgname, uuid_new,
+				  uuid_primary);
+			use_new = 1;
+		}
+
+		if (!use_new) {
+			while (last_vginfo->next)
+				last_vginfo = last_vginfo->next;
+			last_vginfo->next = new_vginfo;
+			return 1;
+		}
+
+		dm_hash_remove(_vgname_hash, primary_vginfo->vgname);
+	}
+
+	if (!dm_hash_insert(_vgname_hash, new_vginfo->vgname, new_vginfo)) {
+		log_error("cache_update: vg hash insertion failed: %s",
+		  	new_vginfo->vgname);
+		return 0;
+	}
+
+	if (primary_vginfo)
+		new_vginfo->next = primary_vginfo;
+
+	return 1;
+}
+
+static int _lvmcache_update_vgname(struct lvmcache_info *info,
+				   const char *vgname, const char *vgid,
+				   uint32_t vgstatus, const char *creation_host,
+				   const struct format_type *fmt)
+{
+	struct lvmcache_vginfo *vginfo, *primary_vginfo, *orphan_vginfo;
+	struct lvmcache_info *info2, *info3;
+	char mdabuf[32];
+	// struct lvmcache_vginfo  *old_vginfo, *next;
+
+	if (!vgname || (info && info->vginfo && !strcmp(info->vginfo->vgname, vgname)))
+		return 1;
+
+	/* Remove existing vginfo entry */
+	if (info)
+		_drop_vginfo(info, info->vginfo);
+
+	/* Get existing vginfo or create new one */
+	if (!(vginfo = vginfo_from_vgname(vgname, vgid))) {
+/*** FIXME - vginfo ends up duplicated instead of renamed.
+		// Renaming?  This lookup fails.
+		if ((vginfo = vginfo_from_vgid(vgid))) {
+			next = vginfo->next;
+			old_vginfo = vginfo_from_vgname(vginfo->vgname, NULL);
+			if (old_vginfo == vginfo) {
+				dm_hash_remove(_vgname_hash, old_vginfo->vgname);
+				if (old_vginfo->next) {
+					if (!dm_hash_insert(_vgname_hash, old_vginfo->vgname, old_vginfo->next)) {
+						log_error("vg hash re-insertion failed: %s",
+							  old_vginfo->vgname);
+						return 0;
+					}
+				}
+			} else do {
+				if (old_vginfo->next == vginfo) {
+					old_vginfo->next = vginfo->next;
+					break;
+				}
+			} while ((old_vginfo = old_vginfo->next));
+			vginfo->next = NULL;
+
+			dm_free(vginfo->vgname);
+			if (!(vginfo->vgname = dm_strdup(vgname))) {
+				log_error("cache vgname alloc failed for %s", vgname);
+				return 0;
+			}
+
+			// Rename so can assume new name does not already exist
+			if (!dm_hash_insert(_vgname_hash, vginfo->vgname, vginfo->next)) {
+				log_error("vg hash re-insertion failed: %s",
+					  vginfo->vgname);
+		      		return 0;
+			}
+		} else {
+***/
+		if (!(vginfo = dm_malloc(sizeof(*vginfo)))) {
+			log_error("lvmcache_update_vgname: list alloc failed");
+			return 0;
+		}
+		memset(vginfo, 0, sizeof(*vginfo));
+		if (!(vginfo->vgname = dm_strdup(vgname))) {
+			dm_free(vginfo);
+			log_error("cache vgname alloc failed for %s", vgname);
+			return 0;
+		}
+		dm_list_init(&vginfo->infos);
+
+		/*
+		 * If we're scanning and there's an invalidated entry, remove it.
+		 * Otherwise we risk bogus warnings of duplicate VGs.
+		 */
+		while ((primary_vginfo = vginfo_from_vgname(vgname, NULL)) &&
+		       _scanning_in_progress && _vginfo_is_invalid(primary_vginfo))
+			dm_list_iterate_items_safe(info2, info3, &primary_vginfo->infos) {
+				orphan_vginfo = vginfo_from_vgname(primary_vginfo->fmt->orphan_vg_name, NULL);
+				_drop_vginfo(info2, primary_vginfo);	
+				_vginfo_attach_info(orphan_vginfo, info2);
+				if (info2->mdas.n)
+					sprintf(mdabuf, " with %u mdas",
+						dm_list_size(&info2->mdas));
+				else
+					mdabuf[0] = '\0';
+				log_debug("lvmcache: %s: now in VG %s%s%s%s%s",
+					  dev_name(info2->dev),
+					  vgname, orphan_vginfo->vgid[0] ? " (" : "",
+					  orphan_vginfo->vgid[0] ? orphan_vginfo->vgid : "",
+					  orphan_vginfo->vgid[0] ? ")" : "", mdabuf);
+		}
+
+		if (!_insert_vginfo(vginfo, vgid, vgstatus, creation_host,
+				    primary_vginfo)) {
+			dm_free(vginfo->vgname);
+			dm_free(vginfo);
+			return 0;
+		}
+		/* Ensure orphans appear last on list_iterate */
+		if (is_orphan_vg(vgname))
+			dm_list_add(&_vginfos, &vginfo->list);
+		else
+			dm_list_add_h(&_vginfos, &vginfo->list);
+/***
+		}
+***/
+	}
+
+	if (info)
+		_vginfo_attach_info(vginfo, info);
+	else if (!_lvmcache_update_vgid(NULL, vginfo, vgid)) /* Orphans */
+		return_0;
+
+	_update_cache_vginfo_lock_state(vginfo, vgname_is_locked(vgname));
+
+	/* FIXME Check consistency of list! */
+	vginfo->fmt = fmt;
+
+	if (info) {
+		if (info->mdas.n)
+			sprintf(mdabuf, " with %u mdas", dm_list_size(&info->mdas));
+		else
+			mdabuf[0] = '\0';
+		log_debug("lvmcache: %s: now in VG %s%s%s%s%s",
+			  dev_name(info->dev),
+			  vgname, vginfo->vgid[0] ? " (" : "",
+			  vginfo->vgid[0] ? vginfo->vgid : "",
+			  vginfo->vgid[0] ? ")" : "", mdabuf);
+	} else
+		log_debug("lvmcache: initialised VG %s", vgname);
+
+	return 1;
+}
+
+static int _lvmcache_update_vgstatus(struct lvmcache_info *info, uint32_t vgstatus,
+				     const char *creation_host)
+{
+	if (!info || !info->vginfo)
+		return 1;
+
+	if ((info->vginfo->status & EXPORTED_VG) != (vgstatus & EXPORTED_VG))
+		log_debug("lvmcache: %s: VG %s %s exported",
+			  dev_name(info->dev), info->vginfo->vgname,
+			  vgstatus & EXPORTED_VG ? "now" : "no longer");
+
+	info->vginfo->status = vgstatus;
+
+	if (!creation_host)
+		return 1;
+
+	if (info->vginfo->creation_host && !strcmp(creation_host,
+						   info->vginfo->creation_host))
+		return 1;
+
+	if (info->vginfo->creation_host)
+		dm_free(info->vginfo->creation_host);
+
+	if (!(info->vginfo->creation_host = dm_strdup(creation_host))) {
+		log_error("cache creation host alloc failed for %s",
+			  creation_host);
+		return 0;
+	}
+
+	log_debug("lvmcache: %s: VG %s: Set creation host to %s.",
+		  dev_name(info->dev), info->vginfo->vgname, creation_host);
+
+	return 1;
+}
+
+int lvmcache_add_orphan_vginfo(const char *vgname, struct format_type *fmt)
+{
+	if (!_lock_hash && !lvmcache_init()) {
+		log_error("Internal cache initialisation failed");
+		return 0;
+	}
+
+	return _lvmcache_update_vgname(NULL, vgname, vgname, 0, "", fmt);
+}
+
+int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
+				  const char *vgname, const char *vgid,
+				  uint32_t vgstatus, const char *creation_host)
+{
+	if (!vgname && !info->vginfo) {
+		log_error("Internal error: NULL vgname handed to cache");
+		/* FIXME Remove this */
+		vgname = info->fmt->orphan_vg_name;
+		vgid = vgname;
+	}
+
+	/* If PV without mdas is already in a real VG, don't make it orphan */
+	if (is_orphan_vg(vgname) && info->vginfo && !dm_list_size(&info->mdas) &&
+	    !is_orphan_vg(info->vginfo->vgname) && memlock())
+		return 1;
+
+	/* If moving PV from orphan to real VG, always mark it valid */
+	if (!is_orphan_vg(vgname))
+		info->status &= ~CACHE_INVALID;
+
+	if (!_lvmcache_update_vgname(info, vgname, vgid, vgstatus,
+				     creation_host, info->fmt) ||
+	    !_lvmcache_update_vgid(info, info->vginfo, vgid) ||
+	    !_lvmcache_update_vgstatus(info, vgstatus, creation_host))
+		return_0;
+
+	return 1;
+}
+
+int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted)
+{
+	struct pv_list *pvl;
+	struct lvmcache_info *info;
+	struct lvmcache_vginfo *vginfo;
+	char pvid_s[ID_LEN + 1] __attribute((aligned(8)));
+
+	pvid_s[sizeof(pvid_s) - 1] = '\0';
+
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s) - 1);
+		/* FIXME Could pvl->pv->dev->pvid ever be different? */
+		if ((info = info_from_pvid(pvid_s, 0)) &&
+		    !lvmcache_update_vgname_and_id(info, vg->name,
+						   (char *) &vg->id,
+						   vg->status, NULL))
+			return_0;
+	}
+
+	/* store text representation of vg to cache */
+	if (vg->cmd->current_settings.cache_vgmetadata &&
+	    (vginfo = vginfo_from_vgname(vg->name, NULL)))
+		_store_metadata(vginfo, vg, precommitted);
+
+	return 1;
+}
+
+struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
+				   struct device *dev,
+				   const char *vgname, const char *vgid,
+				   uint32_t vgstatus)
+{
+	struct label *label;
+	struct lvmcache_info *existing, *info;
+	char pvid_s[ID_LEN + 1] __attribute((aligned(8)));
+
+	if (!_vgname_hash && !lvmcache_init()) {
+		log_error("Internal cache initialisation failed");
+		return NULL;
+	}
+
+	strncpy(pvid_s, pvid, sizeof(pvid_s));
+	pvid_s[sizeof(pvid_s) - 1] = '\0';
+
+	if (!(existing = info_from_pvid(pvid_s, 0)) &&
+	    !(existing = info_from_pvid(dev->pvid, 0))) {
+		if (!(label = label_create(labeller)))
+			return_NULL;
+		if (!(info = dm_malloc(sizeof(*info)))) {
+			log_error("lvmcache_info allocation failed");
+			label_destroy(label);
+			return NULL;
+		}
+		memset(info, 0, sizeof(*info));
+
+		label->info = info;
+		info->label = label;
+		dm_list_init(&info->list);
+		info->dev = dev;
+	} else {
+		if (existing->dev != dev) {
+			/* Is the existing entry a duplicate pvid e.g. md ? */
+			if (MAJOR(existing->dev->dev) == md_major() &&
+			    MAJOR(dev->dev) != md_major()) {
+				log_very_verbose("Ignoring duplicate PV %s on "
+						 "%s - using md %s",
+						 pvid, dev_name(dev),
+						 dev_name(existing->dev));
+				return NULL;
+			} else if (dm_is_dm_major(MAJOR(existing->dev->dev)) &&
+				   !dm_is_dm_major(MAJOR(dev->dev))) {
+				log_very_verbose("Ignoring duplicate PV %s on "
+						 "%s - using dm %s",
+						 pvid, dev_name(dev),
+						 dev_name(existing->dev));
+				return NULL;
+			} else if (MAJOR(existing->dev->dev) != md_major() &&
+				   MAJOR(dev->dev) == md_major())
+				log_very_verbose("Duplicate PV %s on %s - "
+						 "using md %s", pvid,
+						 dev_name(existing->dev),
+						 dev_name(dev));
+			else if (!dm_is_dm_major(MAJOR(existing->dev->dev)) &&
+				 dm_is_dm_major(MAJOR(dev->dev)))
+				log_very_verbose("Duplicate PV %s on %s - "
+						 "using dm %s", pvid,
+						 dev_name(existing->dev),
+						 dev_name(dev));
+			/* FIXME If both dm, check dependencies */
+			//else if (dm_is_dm_major(MAJOR(existing->dev->dev)) &&
+				 //dm_is_dm_major(MAJOR(dev->dev)))
+				 //
+			else
+				log_error("Found duplicate PV %s: using %s not "
+					  "%s", pvid, dev_name(dev),
+					  dev_name(existing->dev));
+		}
+		/* Switch over to new preferred device */
+		existing->dev = dev;
+		info = existing;
+		/* Has labeller changed? */
+		if (info->label->labeller != labeller) {
+			label_destroy(info->label);
+			if (!(info->label = label_create(labeller)))
+				/* FIXME leaves info without label! */
+				return_NULL;
+			info->label->info = info;
+		}
+		label = info->label;
+	}
+
+	info->fmt = (const struct format_type *) labeller->private;
+	info->status |= CACHE_INVALID;
+
+	if (!_lvmcache_update_pvid(info, pvid_s)) {
+		if (!existing) {
+			dm_free(info);
+			label_destroy(label);
+		}
+		return NULL;
+	}
+
+	if (!lvmcache_update_vgname_and_id(info, vgname, vgid, vgstatus, NULL)) {
+		if (!existing) {
+			dm_hash_remove(_pvid_hash, pvid_s);
+			strcpy(info->dev->pvid, "");
+			dm_free(info);
+			label_destroy(label);
+		}
+		return NULL;
+	}
+
+	return info;
+}
+
+static void _lvmcache_destroy_entry(struct lvmcache_info *info)
+{
+	_vginfo_detach_info(info);
+	strcpy(info->dev->pvid, "");
+	label_destroy(info->label);
+	dm_free(info);
+}
+
+static void _lvmcache_destroy_vgnamelist(struct lvmcache_vginfo *vginfo)
+{
+	struct lvmcache_vginfo *next;
+
+	do {
+		next = vginfo->next;
+		if (!_free_vginfo(vginfo))
+			stack;
+	} while ((vginfo = next));
+}
+
+static void _lvmcache_destroy_lockname(struct dm_hash_node *n)
+{
+	char *vgname;
+
+	if (!dm_hash_get_data(_lock_hash, n))
+		return;
+
+	vgname = dm_hash_get_key(_lock_hash, n);
+
+	if (!strcmp(vgname, VG_GLOBAL))
+		_vg_global_lock_held = 1;
+	else
+		log_error("Internal error: Volume Group %s was not unlocked",
+			  dm_hash_get_key(_lock_hash, n));
+}
+
+void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans)
+{
+	struct dm_hash_node *n;
+	log_verbose("Wiping internal VG cache");
+
+	_has_scanned = 0;
+
+	if (_vgid_hash) {
+		dm_hash_destroy(_vgid_hash);
+		_vgid_hash = NULL;
+	}
+
+	if (_pvid_hash) {
+		dm_hash_iter(_pvid_hash, (dm_hash_iterate_fn) _lvmcache_destroy_entry);
+		dm_hash_destroy(_pvid_hash);
+		_pvid_hash = NULL;
+	}
+
+	if (_vgname_hash) {
+		dm_hash_iter(_vgname_hash,
+			  (dm_hash_iterate_fn) _lvmcache_destroy_vgnamelist);
+		dm_hash_destroy(_vgname_hash);
+		_vgname_hash = NULL;
+	}
+
+	if (_lock_hash) {
+		dm_hash_iterate(n, _lock_hash)
+			_lvmcache_destroy_lockname(n);
+		dm_hash_destroy(_lock_hash);
+		_lock_hash = NULL;
+	}
+
+	if (!dm_list_empty(&_vginfos))
+		log_error("Internal error: _vginfos list should be empty");
+	dm_list_init(&_vginfos);
+
+	if (retain_orphans)
+		init_lvmcache_orphans(cmd);
+}
Index: src/external/gpl2/lvm2tools/dist/lib/cache/lvmcache.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/cache/lvmcache.h
diff -N src/external/gpl2/lvm2tools/dist/lib/cache/lvmcache.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/cache/lvmcache.h	13 Dec 2008 14:39:32 -0000	1.1.1.1.2.2
@@ -0,0 +1,117 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_CACHE_H
+#define _LVM_CACHE_H
+
+#include "dev-cache.h"
+#include "uuid.h"
+#include "label.h"
+
+#define ORPHAN_PREFIX "#"
+#define ORPHAN_VG_NAME(fmt) ORPHAN_PREFIX "orphans_" fmt
+
+#define CACHE_INVALID	0x00000001
+#define CACHE_LOCKED	0x00000002
+
+/* LVM specific per-volume info */
+/* Eventual replacement for struct physical_volume perhaps? */
+
+struct cmd_context;
+struct format_type;
+struct volume_group;
+
+/* One per VG */
+struct lvmcache_vginfo {
+	struct dm_list list;	/* Join these vginfos together */
+	struct dm_list infos;	/* List head for lvmcache_infos */
+	const struct format_type *fmt;
+	char *vgname;		/* "" == orphan */
+	uint32_t status;
+	char vgid[ID_LEN + 1];
+	char _padding[7];
+	struct lvmcache_vginfo *next; /* Another VG with same name? */
+	char *creation_host;
+	char *vgmetadata;	/* Copy of VG metadata as format_text string */
+	unsigned precommitted;	/* Is vgmetadata live or precommitted? */
+};
+
+/* One per device */
+struct lvmcache_info {
+	struct dm_list list;	/* Join VG members together */
+	struct dm_list mdas;	/* list head for metadata areas */
+	struct dm_list das;	/* list head for data areas */
+	struct lvmcache_vginfo *vginfo;	/* NULL == unknown */
+	struct label *label;
+	const struct format_type *fmt;
+	struct device *dev;
+	uint64_t device_size;	/* Bytes */
+	uint32_t status;
+};
+
+int lvmcache_init(void);
+void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans);
+
+/* Set full_scan to 1 to reread every filtered device label or
+ * 2 to rescan /dev for new devices */
+int lvmcache_label_scan(struct cmd_context *cmd, int full_scan);
+
+/* Add/delete a device */
+struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
+				   struct device *dev,
+				   const char *vgname, const char *vgid,
+				   uint32_t vgstatus);
+int lvmcache_add_orphan_vginfo(const char *vgname, struct format_type *fmt);
+void lvmcache_del(struct lvmcache_info *info);
+
+/* Update things */
+int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
+				  const char *vgname, const char *vgid,
+				  uint32_t vgstatus, const char *hostname);
+int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted);
+
+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, const char *vgid);
+struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname,
+					   const char *vgid);
+struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid);
+struct lvmcache_info *info_from_pvid(const char *pvid, int valid_only);
+const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid);
+struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid);
+int vgs_locked(void);
+int vgname_is_locked(const char *vgname);
+
+/* Returns list of struct str_lists containing pool-allocated copy of vgnames */
+/* Set full_scan to 1 to reread every filtered device label */
+struct dm_list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan);
+
+/* Returns list of struct str_lists containing pool-allocated copy of vgids */
+/* Set full_scan to 1 to reread every filtered device label */
+struct dm_list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan);
+
+/* Returns list of struct str_lists containing pool-allocated copy of pvids */
+struct dm_list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
+				const char *vgid);
+
+/* Returns cached volume group metadata. */
+struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted);
+void lvmcache_drop_metadata(const char *vgname);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/commands/errors.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/commands/errors.h
diff -N src/external/gpl2/lvm2tools/dist/lib/commands/errors.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/commands/errors.h	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,26 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_ERRORS_H
+#define _LVM_ERRORS_H
+
+#define ECMD_PROCESSED		1
+#define ENO_SUCH_CMD		2
+#define EINVALID_CMD_LINE	3
+#define ECMD_FAILED		5
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/commands/toolcontext.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/commands/toolcontext.c
diff -N src/external/gpl2/lvm2tools/dist/lib/commands/toolcontext.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/commands/toolcontext.c	17 Dec 2008 01:44:10 -0000	1.1.1.1.2.5
@@ -0,0 +1,1223 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "toolcontext.h"
+#include "metadata.h"
+#include "defaults.h"
+#include "lvm-string.h"
+#include "activate.h"
+#include "filter.h"
+#include "filter-composite.h"
+#include "filter-md.h"
+#include "filter-persistent.h"
+#include "filter-regex.h"
+#include "filter-sysfs.h"
+#include "label.h"
+#include "lvm-file.h"
+#include "format-text.h"
+#include "display.h"
+#include "memlock.h"
+#include "str_list.h"
+#include "segtype.h"
+#include "lvmcache.h"
+#include "dev-cache.h"
+#include "archiver.h"
+
+#ifdef HAVE_LIBDL
+#include "sharedlib.h"
+#endif
+
+#ifdef LVM1_INTERNAL
+#include "format1.h"
+#endif
+
+#ifdef POOL_INTERNAL
+#include "format_pool.h"
+#endif
+
+#include <locale.h>
+#include <sys/stat.h>
+#include <sys/utsname.h>
+#include <syslog.h>
+#include <time.h>
+
+#ifdef linux
+#  include <malloc.h>
+#endif
+
+static int _get_env_vars(struct cmd_context *cmd)
+{
+	const char *e;
+
+	/* Set to "" to avoid using any system directory */
+	if ((e = getenv("LVM_SYSTEM_DIR"))) {
+		if (dm_snprintf(cmd->sys_dir, sizeof(cmd->sys_dir),
+				 "%s", e) < 0) {
+			log_error("LVM_SYSTEM_DIR environment variable "
+				  "is too long.");
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+static void _get_sysfs_dir(struct cmd_context *cmd)
+{
+	static char proc_mounts[PATH_MAX];
+	static char *split[4], buffer[PATH_MAX + 16];
+	FILE *fp;
+	char *sys_mnt = NULL;
+
+	cmd->sysfs_dir[0] = '\0';
+	if (!*cmd->proc_dir) {
+		log_debug("No proc filesystem found: skipping sysfs detection");
+		return;
+	}
+
+	if (dm_snprintf(proc_mounts, sizeof(proc_mounts),
+			 "%s/mounts", cmd->proc_dir) < 0) {
+		log_error("Failed to create /proc/mounts string for sysfs detection");
+		return;
+	}
+
+	if (!(fp = fopen(proc_mounts, "r"))) {
+		log_sys_error("_get_sysfs_dir: fopen %s", proc_mounts);
+		return;
+	}
+
+	while (fgets(buffer, sizeof(buffer), fp)) {
+		if (dm_split_words(buffer, 4, 0, split) == 4 &&
+		    !strcmp(split[2], "sysfs")) {
+			sys_mnt = split[1];
+			break;
+		}
+	}
+
+	if (fclose(fp))
+		log_sys_error("fclose", proc_mounts);
+
+	if (!sys_mnt) {
+		log_error("Failed to find sysfs mount point");
+		return;
+	}
+
+	strncpy(cmd->sysfs_dir, sys_mnt, sizeof(cmd->sysfs_dir));
+}
+
+static void _init_logging(struct cmd_context *cmd)
+{
+	int append = 1;
+	time_t t;
+
+	const char *log_file;
+	char timebuf[26];
+
+	/* Syslog */
+	cmd->default_settings.syslog =
+	    find_config_tree_int(cmd, "log/syslog", DEFAULT_SYSLOG);
+	if (cmd->default_settings.syslog != 1)
+		fin_syslog();
+
+	if (cmd->default_settings.syslog > 1)
+		init_syslog(cmd->default_settings.syslog);
+
+	/* Debug level for log file output */
+	cmd->default_settings.debug =
+	    find_config_tree_int(cmd, "log/level", DEFAULT_LOGLEVEL);
+	init_debug(cmd->default_settings.debug);
+
+	/* Verbose level for tty output */
+	cmd->default_settings.verbose =
+	    find_config_tree_int(cmd, "log/verbose", DEFAULT_VERBOSE);
+	init_verbose(cmd->default_settings.verbose + VERBOSE_BASE_LEVEL);
+
+	/* Log message formatting */
+	init_indent(find_config_tree_int(cmd, "log/indent",
+				    DEFAULT_INDENT));
+
+	cmd->default_settings.msg_prefix = find_config_tree_str(cmd,
+							   "log/prefix",
+							   DEFAULT_MSG_PREFIX);
+	init_msg_prefix(cmd->default_settings.msg_prefix);
+
+	cmd->default_settings.cmd_name = find_config_tree_int(cmd,
+							 "log/command_names",
+							 DEFAULT_CMD_NAME);
+	init_cmd_name(cmd->default_settings.cmd_name);
+
+	/* Test mode */
+	cmd->default_settings.test =
+	    find_config_tree_int(cmd, "global/test", 0);
+
+	/* Settings for logging to file */
+	if (find_config_tree_int(cmd, "log/overwrite", DEFAULT_OVERWRITE))
+		append = 0;
+
+	log_file = find_config_tree_str(cmd, "log/file", 0);
+
+	if (log_file) {
+		release_log_memory();
+		fin_log();
+		init_log_file(log_file, append);
+	}
+
+	log_file = find_config_tree_str(cmd, "log/activate_file", 0);
+	if (log_file)
+		init_log_direct(log_file, append);
+
+	init_log_while_suspended(find_config_tree_int(cmd,
+						 "log/activation", 0));
+
+	t = time(NULL);
+	ctime_r(&t, &timebuf[0]);
+	timebuf[24] = '\0';
+	log_verbose("Logging initialised at %s", timebuf);
+
+	/* Tell device-mapper about our logging */
+#ifdef DEVMAPPER_SUPPORT
+	dm_log_init(print_log);
+#endif
+}
+
+static int _process_config(struct cmd_context *cmd)
+{
+	mode_t old_umask;
+	const char *read_ahead;
+	struct stat st;
+
+	/* umask */
+	cmd->default_settings.umask = find_config_tree_int(cmd,
+						      "global/umask",
+						      DEFAULT_UMASK);
+
+	if ((old_umask = umask((mode_t) cmd->default_settings.umask)) !=
+	    (mode_t) cmd->default_settings.umask)
+		log_verbose("Set umask to %04o", cmd->default_settings.umask);
+
+	/* dev dir */
+	if (dm_snprintf(cmd->dev_dir, sizeof(cmd->dev_dir), "%s/",
+			 find_config_tree_str(cmd, "devices/dir",
+					 DEFAULT_DEV_DIR)) < 0) {
+		log_error("Device directory given in config file too long");
+		return 0;
+	}
+#ifdef DEVMAPPER_SUPPORT
+	dm_set_dev_dir(cmd->dev_dir);
+#endif
+#ifndef __NetBSD__
+
+
+	/* proc dir */
+	if (dm_snprintf(cmd->proc_dir, sizeof(cmd->proc_dir), "%s",
+			 find_config_tree_str(cmd, "global/proc",
+					 DEFAULT_PROC_DIR)) < 0) {
+		log_error("Device directory given in config file too long");
+		return 0;
+	}
+#endif
+	if (*cmd->proc_dir && !dir_exists(cmd->proc_dir)) {
+		log_error("WARNING: proc dir %s not found - some checks will be bypassed",
+			  cmd->proc_dir);
+		*cmd->proc_dir = '\0';
+	}
+
+	_get_sysfs_dir(cmd);
+
+	/* activation? */
+	cmd->default_settings.activation = find_config_tree_int(cmd,
+							   "global/activation",
+							   DEFAULT_ACTIVATION);
+	set_activation(cmd->default_settings.activation);
+
+	cmd->default_settings.suffix = find_config_tree_int(cmd,
+						       "global/suffix",
+						       DEFAULT_SUFFIX);
+
+	if (!(cmd->default_settings.unit_factor =
+	      units_to_bytes(find_config_tree_str(cmd,
+					     "global/units",
+					     DEFAULT_UNITS),
+			     &cmd->default_settings.unit_type))) {
+		log_error("Invalid units specification");
+		return 0;
+	}
+
+	read_ahead = find_config_tree_str(cmd, "activation/readahead", DEFAULT_READ_AHEAD);
+	if (!strcasecmp(read_ahead, "auto"))
+		cmd->default_settings.read_ahead = DM_READ_AHEAD_AUTO;
+	else if (!strcasecmp(read_ahead, "none"))
+		cmd->default_settings.read_ahead = DM_READ_AHEAD_NONE;
+	else {
+		log_error("Invalid readahead specification");
+		return 0;
+	}
+
+	cmd->stripe_filler = find_config_tree_str(cmd,
+						  "activation/missing_stripe_filler",
+						  DEFAULT_STRIPE_FILLER);
+
+	/* FIXME Missing error code checks from the stats, not log_warn?, notify if setting overridden, delay message/check till it is actually used (eg consider if lvm shell - file could appear later after this check)? */
+	if (!strcmp(cmd->stripe_filler, "/dev/ioerror") &&
+	    stat(cmd->stripe_filler, &st))
+		cmd->stripe_filler = "error";
+
+	if (strcmp(cmd->stripe_filler, "error")) {
+		if (stat(cmd->stripe_filler, &st)) {
+			log_warn("WARNING: activation/missing_stripe_filler = \"%s\" "
+				 "is invalid,", cmd->stripe_filler);
+			log_warn("         stat failed: %s", strerror(errno));
+			log_warn("Falling back to \"error\" missing_stripe_filler.");
+			cmd->stripe_filler = "error";
+		} else if (!S_ISBLK(st.st_mode)) {
+			log_warn("WARNING: activation/missing_stripe_filler = \"%s\" "
+				 "is not a block device.", cmd->stripe_filler);
+			log_warn("Falling back to \"error\" missing_stripe_filler.");
+			cmd->stripe_filler = "error";
+		}
+	}
+
+	return 1;
+}
+
+static int _set_tag(struct cmd_context *cmd, const char *tag)
+{
+	log_very_verbose("Setting host tag: %s", dm_pool_strdup(cmd->libmem, tag));
+
+	if (!str_list_add(cmd->libmem, &cmd->tags, tag)) {
+		log_error("_set_tag: str_list_add %s failed", tag);
+		return 0;
+	}
+
+	return 1;
+}
+
+static int _check_host_filters(struct cmd_context *cmd, struct config_node *hn,
+			       int *passes)
+{
+	struct config_node *cn;
+	struct config_value *cv;
+
+	*passes = 1;
+
+	for (cn = hn; cn; cn = cn->sib) {
+		if (!cn->v)
+			continue;
+		if (!strcmp(cn->key, "host_list")) {
+			*passes = 0;
+			if (cn->v->type == CFG_EMPTY_ARRAY)
+				continue;
+			for (cv = cn->v; cv; cv = cv->next) {
+				if (cv->type != CFG_STRING) {
+					log_error("Invalid hostname string "
+						  "for tag %s", cn->key);
+					return 0;
+				}
+				if (!strcmp(cv->v.str, cmd->hostname)) {
+					*passes = 1;
+					return 1;
+				}
+			}
+		}
+		if (!strcmp(cn->key, "host_filter")) {
+			log_error("host_filter not supported yet");
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+static int _init_tags(struct cmd_context *cmd, struct config_tree *cft)
+{
+	const struct config_node *tn, *cn;
+	const char *tag;
+	int passes;
+
+	if (!(tn = find_config_node(cft->root, "tags")) || !tn->child)
+		return 1;
+
+	/* NB hosttags 0 when already 1 intentionally does not delete the tag */
+	if (!cmd->hosttags && find_config_int(cft->root, "tags/hosttags",
+					      DEFAULT_HOSTTAGS)) {
+		/* FIXME Strip out invalid chars: only A-Za-z0-9_+.- */
+		if (!_set_tag(cmd, cmd->hostname))
+			return_0;
+		cmd->hosttags = 1;
+	}
+
+	for (cn = tn->child; cn; cn = cn->sib) {
+		if (cn->v)
+			continue;
+		tag = cn->key;
+		if (*tag == '@')
+			tag++;
+		if (!validate_name(tag)) {
+			log_error("Invalid tag in config file: %s", cn->key);
+			return 0;
+		}
+		if (cn->child) {
+			passes = 0;
+			if (!_check_host_filters(cmd, cn->child, &passes))
+				return_0;
+			if (!passes)
+				continue;
+		}
+		if (!_set_tag(cmd, tag))
+			return_0;
+	}
+
+	return 1;
+}
+
+static int _load_config_file(struct cmd_context *cmd, const char *tag)
+{
+	char config_file[PATH_MAX] = "";
+	const char *filler = "";
+	struct stat info;
+	struct config_tree_list *cfl;
+
+	if (*tag)
+		filler = "_";
+
+	if (dm_snprintf(config_file, sizeof(config_file), "%s/lvm%s%s.conf",
+			 cmd->sys_dir, filler, tag) < 0) {
+		log_error("LVM_SYSTEM_DIR or tag was too long");
+		return 0;
+	}
+
+	if (!(cfl = dm_pool_alloc(cmd->libmem, sizeof(*cfl)))) {
+		log_error("config_tree_list allocation failed");
+		return 0;
+	}
+
+	if (!(cfl->cft = create_config_tree(config_file, 0))) {
+		log_error("config_tree allocation failed");
+		return 0;
+	}
+
+	/* Is there a config file? */
+	if (stat(config_file, &info) == -1) {
+		if (errno == ENOENT) {
+			dm_list_add(&cmd->config_files, &cfl->list);
+			goto out;
+		}
+		log_sys_error("stat", config_file);
+		destroy_config_tree(cfl->cft);
+		return 0;
+	}
+
+	log_very_verbose("Loading config file: %s", config_file);
+	if (!read_config_file(cfl->cft)) {
+		log_error("Failed to load config file %s", config_file);
+		destroy_config_tree(cfl->cft);
+		return 0;
+	}
+
+	dm_list_add(&cmd->config_files, &cfl->list);
+
+      out:
+	if (*tag)
+		_init_tags(cmd, cfl->cft);
+	else
+		/* Use temporary copy of lvm.conf while loading other files */
+		cmd->cft = cfl->cft;
+
+	return 1;
+}
+
+/* Find and read first config file */
+static int _init_lvm_conf(struct cmd_context *cmd)
+{
+	/* No config file if LVM_SYSTEM_DIR is empty */
+	if (!*cmd->sys_dir) {
+		if (!(cmd->cft = create_config_tree(NULL, 0))) {
+			log_error("Failed to create config tree");
+			return 0;
+		}
+		return 1;
+	}
+
+	if (!_load_config_file(cmd, ""))
+		return_0;
+
+	return 1;
+}
+
+/* Read any additional config files */
+static int _init_tag_configs(struct cmd_context *cmd)
+{
+	struct str_list *sl;
+
+	/* Tag list may grow while inside this loop */
+	dm_list_iterate_items(sl, &cmd->tags) {
+		if (!_load_config_file(cmd, sl->str))
+			return_0;
+	}
+
+	return 1;
+}
+
+static int _merge_config_files(struct cmd_context *cmd)
+{
+	struct config_tree_list *cfl;
+
+	/* Replace temporary duplicate copy of lvm.conf */
+	if (cmd->cft->root) {
+		if (!(cmd->cft = create_config_tree(NULL, 0))) {
+			log_error("Failed to create config tree");
+			return 0;
+		}
+	}
+
+	dm_list_iterate_items(cfl, &cmd->config_files) {
+		/* Merge all config trees into cmd->cft using merge/tag rules */
+		if (!merge_config_tree(cmd, cmd->cft, cfl->cft))
+			return_0;
+	}
+
+	return 1;
+}
+
+static void _destroy_tags(struct cmd_context *cmd)
+{
+	struct dm_list *slh, *slht;
+
+	dm_list_iterate_safe(slh, slht, &cmd->tags) {
+		dm_list_del(slh);
+	}
+}
+
+int config_files_changed(struct cmd_context *cmd)
+{
+	struct config_tree_list *cfl;
+
+	dm_list_iterate_items(cfl, &cmd->config_files) {
+		if (config_file_changed(cfl->cft))
+			return 1;
+	}
+
+	return 0;
+}
+
+static void _destroy_tag_configs(struct cmd_context *cmd)
+{
+	struct config_tree_list *cfl;
+
+	if (cmd->cft && cmd->cft->root) {
+		destroy_config_tree(cmd->cft);
+		cmd->cft = NULL;
+	}
+
+	dm_list_iterate_items(cfl, &cmd->config_files) {
+		destroy_config_tree(cfl->cft);
+	}
+
+	dm_list_init(&cmd->config_files);
+}
+
+static int _init_dev_cache(struct cmd_context *cmd)
+{
+	const struct config_node *cn;
+	struct config_value *cv;
+
+	if (!dev_cache_init(cmd))
+		return_0;
+
+	if (!(cn = find_config_tree_node(cmd, "devices/scan"))) {
+		if (!dev_cache_add_dir("/dev")) {
+			log_error("Failed to add /dev to internal "
+				  "device cache");
+			return 0;
+		}
+		log_verbose("device/scan not in config file: "
+			    "Defaulting to /dev");
+		return 1;
+	}
+
+	for (cv = cn->v; cv; cv = cv->next) {
+		if (cv->type != CFG_STRING) {
+			log_error("Invalid string in config file: "
+				  "devices/scan");
+			return 0;
+		}
+
+		if (!dev_cache_add_dir(cv->v.str)) {
+			log_error("Failed to add %s to internal device cache",
+				  cv->v.str);
+			return 0;
+		}
+	}
+
+	if (!(cn = find_config_tree_node(cmd, "devices/loopfiles")))
+		return 1;
+
+	for (cv = cn->v; cv; cv = cv->next) {
+		if (cv->type != CFG_STRING) {
+			log_error("Invalid string in config file: "
+				  "devices/loopfiles");
+			return 0;
+		}
+
+		if (!dev_cache_add_loopfile(cv->v.str)) {
+			log_error("Failed to add loopfile %s to internal "
+				  "device cache", cv->v.str);
+			return 0;
+		}
+	}
+
+
+	return 1;
+}
+
+#define MAX_FILTERS 4
+
+static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
+{
+	unsigned nr_filt = 0;
+	const struct config_node *cn;
+	struct dev_filter *filters[MAX_FILTERS];
+
+	memset(filters, 0, sizeof(filters));
+
+	/*
+	 * Filters listed in order: top one gets applied first.
+	 * Failure to initialise some filters is not fatal.
+	 * Update MAX_FILTERS definition above when adding new filters.
+	 */
+
+	/*
+	 * sysfs filter. Only available on 2.6 kernels.  Non-critical.
+	 * Listed first because it's very efficient at eliminating
+	 * unavailable devices.
+	 */
+	if (find_config_tree_bool(cmd, "devices/sysfs_scan",
+			     DEFAULT_SYSFS_SCAN)) {
+		if ((filters[nr_filt] = sysfs_filter_create(cmd->sysfs_dir)))
+			nr_filt++;
+	}
+
+	/* regex filter. Optional. */
+	if (!(cn = find_config_tree_node(cmd, "devices/filter")))
+		log_very_verbose("devices/filter not found in config file: "
+				 "no regex filter installed");
+
+	else if (!(filters[nr_filt++] = regex_filter_create(cn->v))) {
+		log_error("Failed to create regex device filter");
+		return NULL;
+	}
+
+	/* device type filter. Required. */
+	cn = find_config_tree_node(cmd, "devices/types");
+	if (!(filters[nr_filt++] = lvm_type_filter_create(cmd->proc_dir, cn))) {
+		log_error("Failed to create lvm type filter");
+		return NULL;
+	}
+
+	/* md component filter. Optional, non-critical. */
+	if (find_config_tree_bool(cmd, "devices/md_component_detection",
+			     DEFAULT_MD_COMPONENT_DETECTION)) {
+		init_md_filtering(1);
+		if ((filters[nr_filt] = md_filter_create()))
+			nr_filt++;
+	}
+
+	/* Only build a composite filter if we really need it. */
+	return (nr_filt == 1) ?
+	    filters[0] : composite_filter_create(nr_filt, filters);
+}
+
+static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache)
+{
+	const char *dev_cache = NULL, *cache_dir, *cache_file_prefix;
+	struct dev_filter *f3, *f4;
+	struct stat st;
+	char cache_file[PATH_MAX];
+
+	cmd->dump_filter = 0;
+
+	if (!(f3 = _init_filter_components(cmd)))
+		return 0;
+
+	init_ignore_suspended_devices(find_config_tree_int(cmd,
+	    "devices/ignore_suspended_devices", DEFAULT_IGNORE_SUSPENDED_DEVICES));
+
+	/*
+	 * If 'cache_dir' or 'cache_file_prefix' is set, ignore 'cache'.
+	 */
+	cache_dir = find_config_tree_str(cmd, "devices/cache_dir", NULL);
+	cache_file_prefix = find_config_tree_str(cmd, "devices/cache_file_prefix", NULL);
+
+	if (cache_dir || cache_file_prefix) {
+		if (dm_snprintf(cache_file, sizeof(cache_file),
+		    "%s%s%s/%s.cache",
+		    cache_dir ? "" : cmd->sys_dir,
+		    cache_dir ? "" : "/",
+		    cache_dir ? : DEFAULT_CACHE_SUBDIR,
+		    cache_file_prefix ? : DEFAULT_CACHE_FILE_PREFIX) < 0) {
+			log_error("Persistent cache filename too long.");
+			return 0;
+		}
+	} else if (!(dev_cache = find_config_tree_str(cmd, "devices/cache", NULL)) &&
+		   (dm_snprintf(cache_file, sizeof(cache_file),
+				"%s/%s/%s.cache",
+				cmd->sys_dir, DEFAULT_CACHE_SUBDIR,
+				DEFAULT_CACHE_FILE_PREFIX) < 0)) {
+		log_error("Persistent cache filename too long.");
+		return 0;
+	}
+
+	if (!dev_cache)
+		dev_cache = cache_file;
+
+	if (!(f4 = persistent_filter_create(f3, dev_cache))) {
+		log_error("Failed to create persistent device filter");
+		return 0;
+	}
+
+	/* Should we ever dump persistent filter state? */
+	if (find_config_tree_int(cmd, "devices/write_cache_state", 1))
+		cmd->dump_filter = 1;
+
+	if (!*cmd->sys_dir)
+		cmd->dump_filter = 0;
+
+	/*
+	 * Only load persistent filter device cache on startup if it is newer
+	 * than the config file and this is not a long-lived process.
+	 */
+	if (load_persistent_cache && !cmd->is_long_lived &&
+	    !stat(dev_cache, &st) &&
+	    (st.st_ctime > config_file_timestamp(cmd->cft)) &&
+	    !persistent_filter_load(f4, NULL))
+		log_verbose("Failed to load existing device cache from %s",
+			    dev_cache);
+
+	cmd->filter = f4;
+
+	return 1;
+}
+
+static int _init_formats(struct cmd_context *cmd)
+{
+	const char *format;
+
+	struct format_type *fmt;
+
+#ifdef HAVE_LIBDL
+	const struct config_node *cn;
+#endif
+
+	label_init();
+
+#ifdef LVM1_INTERNAL
+	if (!(fmt = init_lvm1_format(cmd)))
+		return 0;
+	fmt->library = NULL;
+	dm_list_add(&cmd->formats, &fmt->list);
+#endif
+
+#ifdef POOL_INTERNAL
+	if (!(fmt = init_pool_format(cmd)))
+		return 0;
+	fmt->library = NULL;
+	dm_list_add(&cmd->formats, &fmt->list);
+#endif
+
+#ifdef HAVE_LIBDL
+	/* Load any formats in shared libs if not static */
+	if (!cmd->is_static &&
+	    (cn = find_config_tree_node(cmd, "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: "
+					  "global/format_libraries");
+				return 0;
+			}
+			if (!(lib = load_shared_library(cmd, cv->v.str,
+							"format", 0)))
+				return_0;
+
+			if (!(init_format_fn = dlsym(lib, "init_format"))) {
+				log_error("Shared library %s does not contain "
+					  "format functions", cv->v.str);
+				dlclose(lib);
+				return 0;
+			}
+
+			if (!(fmt = init_format_fn(cmd)))
+				return 0;
+			fmt->library = lib;
+			dm_list_add(&cmd->formats, &fmt->list);
+		}
+	}
+#endif
+
+	if (!(fmt = create_text_format(cmd)))
+		return 0;
+	fmt->library = NULL;
+	dm_list_add(&cmd->formats, &fmt->list);
+
+	cmd->fmt_backup = fmt;
+
+	format = find_config_tree_str(cmd, "global/format",
+				 DEFAULT_FORMAT);
+
+	dm_list_iterate_items(fmt, &cmd->formats) {
+		if (!strcasecmp(fmt->name, format) ||
+		    (fmt->alias && !strcasecmp(fmt->alias, format))) {
+			cmd->default_settings.fmt = fmt;
+			return 1;
+		}
+	}
+
+	log_error("_init_formats: Default format (%s) not found", format);
+	return 0;
+}
+
+int init_lvmcache_orphans(struct cmd_context *cmd)
+{
+	struct format_type *fmt;
+
+	dm_list_iterate_items(fmt, &cmd->formats)
+		if (!lvmcache_add_orphan_vginfo(fmt->orphan_vg_name, fmt))
+			return_0;
+
+	return 1;
+}
+
+static int _init_segtypes(struct cmd_context *cmd)
+{
+	struct segment_type *segtype;
+
+#ifdef HAVE_LIBDL
+	const struct config_node *cn;
+#endif
+
+	if (!(segtype = init_striped_segtype(cmd)))
+		return 0;
+	segtype->library = NULL;
+	dm_list_add(&cmd->segtypes, &segtype->list);
+
+	if (!(segtype = init_zero_segtype(cmd)))
+		return 0;
+	segtype->library = NULL;
+	dm_list_add(&cmd->segtypes, &segtype->list);
+
+	if (!(segtype = init_error_segtype(cmd)))
+		return 0;
+	segtype->library = NULL;
+	dm_list_add(&cmd->segtypes, &segtype->list);
+
+	if (!(segtype = init_free_segtype(cmd)))
+		return 0;
+	segtype->library = NULL;
+	dm_list_add(&cmd->segtypes, &segtype->list);
+
+#ifdef SNAPSHOT_INTERNAL
+	if (!(segtype = init_snapshot_segtype(cmd)))
+		return 0;
+	segtype->library = NULL;
+	dm_list_add(&cmd->segtypes, &segtype->list);
+#endif
+
+#ifdef MIRRORED_INTERNAL
+	if (!(segtype = init_mirrored_segtype(cmd)))
+		return 0;
+	segtype->library = NULL;
+	dm_list_add(&cmd->segtypes, &segtype->list);
+#endif
+
+#ifdef HAVE_LIBDL
+	/* Load any formats in shared libs unless static */
+	if (!cmd->is_static &&
+	    (cn = find_config_tree_node(cmd, "global/segment_libraries"))) {
+
+		struct config_value *cv;
+		struct segment_type *(*init_segtype_fn) (struct cmd_context *);
+		void *lib;
+		struct segment_type *segtype2;
+
+		for (cv = cn->v; cv; cv = cv->next) {
+			if (cv->type != CFG_STRING) {
+				log_error("Invalid string in config file: "
+					  "global/segment_libraries");
+				return 0;
+			}
+			if (!(lib = load_shared_library(cmd, cv->v.str,
+							"segment type", 0)))
+				return_0;
+
+			if (!(init_segtype_fn = dlsym(lib, "init_segtype"))) {
+				log_error("Shared library %s does not contain "
+					  "segment type functions", cv->v.str);
+				dlclose(lib);
+				return 0;
+			}
+
+			if (!(segtype = init_segtype_fn(cmd)))
+				return 0;
+			segtype->library = lib;
+			dm_list_add(&cmd->segtypes, &segtype->list);
+
+			dm_list_iterate_items(segtype2, &cmd->segtypes) {
+				if ((segtype == segtype2) ||
+				     strcmp(segtype2->name, segtype->name))
+					continue;
+				log_error("Duplicate segment type %s: "
+					  "unloading shared library %s",
+					  segtype->name, cv->v.str);
+				dm_list_del(&segtype->list);
+				segtype->ops->destroy(segtype);
+				dlclose(lib);
+			}
+		}
+	}
+#endif
+
+	return 1;
+}
+
+static int _init_hostname(struct cmd_context *cmd)
+{
+	struct utsname uts;
+
+	if (uname(&uts)) {
+		log_sys_error("uname", "_init_hostname");
+		return 0;
+	}
+
+	if (!(cmd->hostname = dm_pool_strdup(cmd->libmem, uts.nodename))) {
+		log_error("_init_hostname: dm_pool_strdup failed");
+		return 0;
+	}
+
+	if (!(cmd->kernel_vsn = dm_pool_strdup(cmd->libmem, uts.release))) {
+		log_error("_init_hostname: dm_pool_strdup kernel_vsn failed");
+		return 0;
+	}
+
+	return 1;
+}
+
+static int _init_backup(struct cmd_context *cmd)
+{
+	uint32_t days, min;
+	char default_dir[PATH_MAX];
+	const char *dir;
+
+	if (!cmd->sys_dir) {
+		log_warn("WARNING: Metadata changes will NOT be backed up");
+		backup_init(cmd, "");
+		archive_init(cmd, "", 0, 0);
+		return 1;
+	}
+
+	/* set up archiving */
+	cmd->default_settings.archive =
+	    find_config_tree_bool(cmd, "backup/archive",
+			     DEFAULT_ARCHIVE_ENABLED);
+
+	days = (uint32_t) find_config_tree_int(cmd, "backup/retain_days",
+					  DEFAULT_ARCHIVE_DAYS);
+
+	min = (uint32_t) find_config_tree_int(cmd, "backup/retain_min",
+					 DEFAULT_ARCHIVE_NUMBER);
+
+	if (dm_snprintf
+	    (default_dir, sizeof(default_dir), "%s/%s", cmd->sys_dir,
+	     DEFAULT_ARCHIVE_SUBDIR) == -1) {
+		log_err("Couldn't create default archive path '%s/%s'.",
+			cmd->sys_dir, DEFAULT_ARCHIVE_SUBDIR);
+		return 0;
+	}
+
+	dir = find_config_tree_str(cmd, "backup/archive_dir",
+			      default_dir);
+
+	if (!archive_init(cmd, dir, days, min)) {
+		log_debug("backup_init failed.");
+		return 0;
+	}
+
+	/* set up the backup */
+	cmd->default_settings.backup =
+	    find_config_tree_bool(cmd, "backup/backup",
+			     DEFAULT_BACKUP_ENABLED);
+
+	if (dm_snprintf
+	    (default_dir, sizeof(default_dir), "%s/%s", cmd->sys_dir,
+	     DEFAULT_BACKUP_SUBDIR) == -1) {
+		log_err("Couldn't create default backup path '%s/%s'.",
+			cmd->sys_dir, DEFAULT_BACKUP_SUBDIR);
+		return 0;
+	}
+
+	dir = find_config_tree_str(cmd, "backup/backup_dir", default_dir);
+
+	if (!backup_init(cmd, dir)) {
+		log_debug("backup_init failed.");
+		return 0;
+	}
+
+	return 1;
+}
+
+/* Entry point */
+struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static,
+				       unsigned is_long_lived)
+{
+	struct cmd_context *cmd;
+
+#ifdef M_MMAP_MAX
+	mallopt(M_MMAP_MAX, 0);
+#endif
+
+	if (!setlocale(LC_ALL, ""))
+		log_very_verbose("setlocale failed");
+
+#ifdef INTL_PACKAGE
+	bindtextdomain(INTL_PACKAGE, LOCALEDIR);
+#endif
+
+	init_syslog(DEFAULT_LOG_FACILITY);
+
+	if (!(cmd = dm_malloc(sizeof(*cmd)))) {
+		log_error("Failed to allocate command context");
+		return NULL;
+	}
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->args = the_args;
+	cmd->is_static = is_static;
+	cmd->is_long_lived = is_long_lived;
+	cmd->handles_missing_pvs = 0;
+	cmd->hosttags = 0;
+	dm_list_init(&cmd->formats);
+	dm_list_init(&cmd->segtypes);
+	dm_list_init(&cmd->tags);
+	dm_list_init(&cmd->config_files);
+
+	strcpy(cmd->sys_dir, DEFAULT_SYS_DIR);
+
+	if (!_get_env_vars(cmd))
+		goto error;
+
+	/* Create system directory if it doesn't already exist */
+	if (*cmd->sys_dir && !dm_create_dir(cmd->sys_dir)) {
+		log_error("Failed to create LVM2 system dir for metadata backups, config "
+			  "files and internal cache.");
+		log_error("Set environment variable LVM_SYSTEM_DIR to alternative location "
+			  "or empty string.");
+		goto error;
+	}
+
+	if (!(cmd->libmem = dm_pool_create("library", 4 * 1024))) {
+		log_error("Library memory pool creation failed");
+		goto error;
+	}
+
+	if (!_init_lvm_conf(cmd))
+		goto error;
+
+	_init_logging(cmd);
+
+	if (!_init_hostname(cmd))
+		goto error;
+
+	if (!_init_tags(cmd, cmd->cft))
+		goto error;
+
+	if (!_init_tag_configs(cmd))
+		goto error;
+
+	if (!_merge_config_files(cmd))
+		goto error;
+
+	if (!_process_config(cmd))
+		goto error;
+
+	if (!_init_dev_cache(cmd))
+		goto error;
+
+	if (!_init_filters(cmd, 1))
+		goto error;
+
+	if (!(cmd->mem = dm_pool_create("command", 4 * 1024))) {
+		log_error("Command memory pool creation failed");
+		goto error;
+	}
+
+	memlock_init(cmd);
+
+	if (!_init_formats(cmd))
+		goto error;
+
+	if (!init_lvmcache_orphans(cmd))
+		goto error;
+
+	if (!_init_segtypes(cmd))
+		goto error;
+
+	if (!_init_backup(cmd))
+		goto error;
+
+	cmd->default_settings.cache_vgmetadata = 1;
+	cmd->current_settings = cmd->default_settings;
+
+	cmd->config_valid = 1;
+	return cmd;
+
+      error:
+	dm_free(cmd);
+	return NULL;
+}
+
+static void _destroy_formats(struct dm_list *formats)
+{
+	struct dm_list *fmtl, *tmp;
+	struct format_type *fmt;
+	void *lib;
+
+	dm_list_iterate_safe(fmtl, tmp, formats) {
+		fmt = dm_list_item(fmtl, struct format_type);
+		dm_list_del(&fmt->list);
+		lib = fmt->library;
+		fmt->ops->destroy(fmt);
+#ifdef HAVE_LIBDL
+		if (lib)
+			dlclose(lib);
+#endif
+	}
+}
+
+static void _destroy_segtypes(struct dm_list *segtypes)
+{
+	struct dm_list *sgtl, *tmp;
+	struct segment_type *segtype;
+	void *lib;
+
+	dm_list_iterate_safe(sgtl, tmp, segtypes) {
+		segtype = dm_list_item(sgtl, struct segment_type);
+		dm_list_del(&segtype->list);
+		lib = segtype->library;
+		segtype->ops->destroy(segtype);
+#ifdef HAVE_LIBDL
+		if (lib)
+			dlclose(lib);
+#endif
+	}
+}
+
+int refresh_toolcontext(struct cmd_context *cmd)
+{
+	log_verbose("Reloading config files");
+
+	/*
+	 * Don't update the persistent filter cache as we will
+	 * perform a full rescan.
+	 */
+
+	activation_release();
+	lvmcache_destroy(cmd, 0);
+	label_exit();
+	_destroy_segtypes(&cmd->segtypes);
+	_destroy_formats(&cmd->formats);
+	if (cmd->filter) {
+		cmd->filter->destroy(cmd->filter);
+		cmd->filter = NULL;
+	}
+	dev_cache_exit();
+	_destroy_tags(cmd);
+	_destroy_tag_configs(cmd);
+
+	cmd->config_valid = 0;
+
+	cmd->hosttags = 0;
+
+	if (!_init_lvm_conf(cmd))
+		return 0;
+
+	_init_logging(cmd);
+
+	if (!_init_tags(cmd, cmd->cft))
+		return 0;
+
+	if (!_init_tag_configs(cmd))
+		return 0;
+
+	if (!_merge_config_files(cmd))
+		return 0;
+
+	if (!_process_config(cmd))
+		return 0;
+
+	if (!_init_dev_cache(cmd))
+		return 0;
+
+	if (!_init_filters(cmd, 0))
+		return 0;
+
+	if (!_init_formats(cmd))
+		return 0;
+
+	if (!init_lvmcache_orphans(cmd))
+		return 0;
+
+	if (!_init_segtypes(cmd))
+		return 0;
+
+	/*
+	 * If we are a long-lived process, write out the updated persistent
+	 * device cache for the benefit of short-lived processes.
+	 */
+	if (cmd->is_long_lived && cmd->dump_filter)
+		persistent_filter_dump(cmd->filter);
+
+	cmd->config_valid = 1;
+	return 1;
+}
+
+void destroy_toolcontext(struct cmd_context *cmd)
+{
+	if (cmd->dump_filter)
+		persistent_filter_dump(cmd->filter);
+
+	archive_exit(cmd);
+	backup_exit(cmd);
+	lvmcache_destroy(cmd, 0);
+	label_exit();
+	_destroy_segtypes(&cmd->segtypes);
+	_destroy_formats(&cmd->formats);
+	cmd->filter->destroy(cmd->filter);
+	dm_pool_destroy(cmd->mem);
+	dev_cache_exit();
+	_destroy_tags(cmd);
+	_destroy_tag_configs(cmd);
+	dm_pool_destroy(cmd->libmem);
+	dm_free(cmd);
+
+	release_log_memory();
+	activation_exit();
+	fin_log();
+	fin_syslog();
+}
Index: src/external/gpl2/lvm2tools/dist/lib/commands/toolcontext.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/commands/toolcontext.h
diff -N src/external/gpl2/lvm2tools/dist/lib/commands/toolcontext.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/commands/toolcontext.h	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,106 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_TOOLCONTEXT_H
+#define _LVM_TOOLCONTEXT_H
+
+#include "dev-cache.h"
+
+#include <stdio.h>
+#include <limits.h>
+
+/*
+ * Config options that can be changed while commands are processed
+ */
+struct config_info {
+	int debug;
+	int verbose;
+	int test;
+	int syslog;
+	int activation;
+	int suffix;
+	int archive;		/* should we archive ? */
+	int backup;		/* should we backup ? */
+	int read_ahead;		/* DM_READ_AHEAD_NONE or _AUTO */
+	int cache_vgmetadata;
+	const char *msg_prefix;
+	struct format_type *fmt;
+	uint64_t unit_factor;
+	int cmd_name;		/* Show command name? */
+	mode_t umask;
+	char unit_type;
+	char _padding[1];
+};
+
+struct config_tree;
+struct archive_params;
+struct backup_params;
+
+/* FIXME Split into tool & library contexts */
+/* command-instance-related variables needed by library */
+struct cmd_context {
+	struct dm_pool *libmem;	/* For permanent config data */
+	struct dm_pool *mem;	/* Transient: Cleared between each command */
+
+	const struct format_type *fmt;	/* Current format to use by default */
+	struct format_type *fmt_backup;	/* Format to use for backups */
+
+	struct dm_list formats;	/* Available formats */
+	struct dm_list segtypes;	/* Available segment types */
+	const char *hostname;
+	const char *kernel_vsn;
+
+	char *cmd_line;
+	struct command *command;
+	struct arg *args;
+	char **argv;
+	unsigned is_static:1;	/* Static binary? */
+	unsigned is_long_lived:1;	/* Optimises persistent_filter handling */
+	unsigned handles_missing_pvs:1;
+	unsigned partial_activation:1;
+
+	struct dev_filter *filter;
+	int dump_filter;	/* Dump filter when exiting? */
+
+	struct dm_list config_files;
+	int config_valid;
+	struct config_tree *cft;
+	struct config_tree *cft_override;
+	struct config_info default_settings;
+	struct config_info current_settings;
+
+	struct archive_params *archive_params;
+	struct backup_params *backup_params;
+	const char *stripe_filler;
+
+	/* List of defined tags */
+	struct dm_list tags;
+	int hosttags;
+
+	char sys_dir[PATH_MAX];
+	char dev_dir[PATH_MAX];
+	char proc_dir[PATH_MAX];
+	char sysfs_dir[PATH_MAX];
+};
+
+struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static, unsigned is_long_lived);
+void destroy_toolcontext(struct cmd_context *cmd);
+int refresh_toolcontext(struct cmd_context *cmd);
+int config_files_changed(struct cmd_context *cmd);
+int init_lvmcache_orphans(struct cmd_context *cmd);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/config/config.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/config/config.c
diff -N src/external/gpl2/lvm2tools/dist/lib/config/config.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/config/config.c	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,1284 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "config.h"
+#include "crc.h"
+#include "device.h"
+#include "str_list.h"
+#include "toolcontext.h"
+#include "lvm-string.h"
+#include "lvm-file.h"
+
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+
+#define SECTION_B_CHAR '{'
+#define SECTION_E_CHAR '}'
+
+enum {
+	TOK_INT,
+	TOK_FLOAT,
+	TOK_STRING,		/* Single quotes */
+	TOK_STRING_ESCAPED,	/* Double quotes */
+	TOK_EQ,
+	TOK_SECTION_B,
+	TOK_SECTION_E,
+	TOK_ARRAY_B,
+	TOK_ARRAY_E,
+	TOK_IDENTIFIER,
+	TOK_COMMA,
+	TOK_EOF
+};
+
+struct parser {
+	const char *fb, *fe;		/* file limits */
+
+	int t;			/* token limits and type */
+	const char *tb, *te;
+
+	int fd;			/* descriptor for file being parsed */
+	int line;		/* line number we are on */
+
+	struct dm_pool *mem;
+};
+
+struct cs {
+	struct config_tree cft;
+	struct dm_pool *mem;
+	time_t timestamp;
+	char *filename;
+	int exists;
+	int keep_open;
+	struct device *dev;
+};
+
+struct output_line {
+	FILE *fp;
+	struct dm_pool *mem;
+};
+
+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);
+static struct config_value *_value(struct parser *p);
+static struct config_value *_type(struct parser *p);
+static int _match_aux(struct parser *p, int t);
+static struct config_value *_create_value(struct parser *p);
+static struct config_node *_create_node(struct parser *p);
+static char *_dup_tok(struct parser *p);
+
+static const int sep = '/';
+
+#define MAX_INDENT 32
+
+#define match(t) do {\
+   if (!_match_aux(p, (t))) {\
+	log_error("Parse error at byte %" PRIptrdiff_t " (line %d): unexpected token", \
+		  p->tb - p->fb + 1, p->line); \
+      return 0;\
+   } \
+} while(0);
+
+static int _tok_match(const char *str, const char *b, const char *e)
+{
+	while (*str && (b != e)) {
+		if (*str++ != *b++)
+			return 0;
+	}
+
+	return !(*str || (b != e));
+}
+
+/*
+ * public interface
+ */
+struct config_tree *create_config_tree(const char *filename, int keep_open)
+{
+	struct cs *c;
+	struct dm_pool *mem = dm_pool_create("config", 10 * 1024);
+
+	if (!mem) {
+		log_error("Failed to allocate config pool.");
+		return 0;
+	}
+
+	if (!(c = dm_pool_zalloc(mem, sizeof(*c)))) {
+		log_error("Failed to allocate config tree.");
+		dm_pool_destroy(mem);
+		return 0;
+	}
+
+	c->mem = mem;
+	c->cft.root = (struct config_node *) NULL;
+	c->timestamp = 0;
+	c->exists = 0;
+	c->keep_open = keep_open;
+	c->dev = 0;
+	if (filename)
+		c->filename = dm_pool_strdup(c->mem, filename);
+	return &c->cft;
+}
+
+void destroy_config_tree(struct config_tree *cft)
+{
+	struct cs *c = (struct cs *) cft;
+
+	if (c->dev)
+		dev_close(c->dev);
+
+	dm_pool_destroy(c->mem);
+}
+
+static int _parse_config_file(struct parser *p, struct config_tree *cft)
+{
+	p->tb = p->te = p->fb;
+	p->line = 1;
+	_get_token(p, TOK_SECTION_E);
+	if (!(cft->root = _file(p)))
+		return_0;
+
+	return 1;
+}
+
+struct config_tree *create_config_tree_from_string(struct cmd_context *cmd __attribute((unused)),
+						   const char *config_settings)
+{
+	struct cs *c;
+	struct config_tree *cft;
+	struct parser *p;
+
+	if (!(cft = create_config_tree(NULL, 0)))
+		return_NULL;
+
+	c = (struct cs *) cft;
+	if (!(p = dm_pool_alloc(c->mem, sizeof(*p)))) {
+		log_error("Failed to allocate config tree parser.");
+		destroy_config_tree(cft);
+		return NULL;
+	}
+
+	p->mem = c->mem;
+	p->fb = config_settings;
+	p->fe = config_settings + strlen(config_settings);
+
+	if (!_parse_config_file(p, cft)) {
+		destroy_config_tree(cft);
+		return_NULL;
+	}
+
+	return cft;
+}
+
+int read_config_fd(struct config_tree *cft, struct device *dev,
+		   off_t offset, size_t size, off_t offset2, size_t size2,
+		   checksum_fn_t checksum_fn, uint32_t checksum)
+{
+	struct cs *c = (struct cs *) cft;
+	struct parser *p;
+	int r = 0;
+	int use_mmap = 1;
+	off_t mmap_offset = 0;
+	char *buf = NULL;
+
+	if (!(p = dm_pool_alloc(c->mem, sizeof(*p))))
+		return_0;
+	p->mem = c->mem;
+
+	/* Only use mmap with regular files */
+	if (!(dev->flags & DEV_REGULAR) || size2)
+		use_mmap = 0;
+
+	if (use_mmap) {
+		mmap_offset = offset % lvm_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 (!(buf = dm_malloc(size + size2)))
+			return_0;
+		if (!dev_read_circular(dev, (uint64_t) offset, size,
+				       (uint64_t) offset2, size2, buf)) {
+			goto out;
+		}
+		p->fb = buf;
+	}
+
+	if (checksum_fn && checksum !=
+	    (checksum_fn(checksum_fn(INITIAL_CRC, p->fb, size),
+			 p->fb + size, size2))) {
+		log_error("%s: Checksum error", dev_name(dev));
+		goto out;
+	}
+
+	p->fe = p->fb + size + size2;
+
+	if (!_parse_config_file(p, cft))
+		goto_out;
+
+	r = 1;
+
+      out:
+	if (!use_mmap)
+		dm_free(buf);
+	else {
+		/* unmap the file */
+		if (munmap((char *) (p->fb - mmap_offset), size + mmap_offset)) {
+			log_sys_error("munmap", dev_name(dev));
+			r = 0;
+		}
+	}
+
+	return r;
+}
+
+int read_config_file(struct config_tree *cft)
+{
+	struct cs *c = (struct cs *) cft;
+	struct stat info;
+	int r = 1;
+
+	if (stat(c->filename, &info)) {
+		log_sys_error("stat", c->filename);
+		c->exists = 0;
+		return 0;
+	}
+
+	if (!S_ISREG(info.st_mode)) {
+		log_error("%s is not a regular file", c->filename);
+		c->exists = 0;
+		return 0;
+	}
+
+	c->exists = 1;
+
+	if (info.st_size == 0) {
+		log_verbose("%s is empty", c->filename);
+		return 1;
+	}
+
+	if (!c->dev) {
+		if (!(c->dev = dev_create_file(c->filename, NULL, NULL, 1)))
+			return_0;
+
+		if (!dev_open_flags(c->dev, O_RDONLY, 0, 0))
+			return_0;
+	}
+
+	r = read_config_fd(cft, c->dev, 0, (size_t) info.st_size, 0, 0,
+			   (checksum_fn_t) NULL, 0);
+
+	if (!c->keep_open) {
+		dev_close(c->dev);
+		c->dev = 0;
+	}
+
+	c->timestamp = info.st_ctime;
+
+	return r;
+}
+
+time_t config_file_timestamp(struct config_tree *cft)
+{
+	struct cs *c = (struct cs *) cft;
+
+	return c->timestamp;
+}
+
+/*
+ * Return 1 if config files ought to be reloaded
+ */
+int config_file_changed(struct config_tree *cft)
+{
+	struct cs *c = (struct cs *) cft;
+	struct stat info;
+
+	if (!c->filename)
+		return 0;
+
+	if (stat(c->filename, &info) == -1) {
+		/* Ignore a deleted config file: still use original data */
+		if (errno == ENOENT) {
+			if (!c->exists)
+				return 0;
+			log_very_verbose("Config file %s has disappeared!",
+					 c->filename);
+			goto reload;
+		}
+		log_sys_error("stat", c->filename);
+		log_error("Failed to reload configuration files");
+		return 0;
+	}
+
+	if (!S_ISREG(info.st_mode)) {
+		log_error("Configuration file %s is not a regular file",
+			  c->filename);
+		goto reload;
+	}
+
+	/* Unchanged? */
+	if (c->timestamp == info.st_ctime)
+		return 0;
+
+      reload:
+	log_verbose("Detected config file change to %s", c->filename);
+	return 1;
+}
+
+static int _line_start(struct output_line *outline)
+{
+	if (!dm_pool_begin_object(outline->mem, 128)) {
+		log_error("dm_pool_begin_object failed for config line");
+		return 0;
+	}
+
+	return 1;
+}
+
+static int _line_append(struct output_line *outline, const char *fmt, ...)
+  __attribute__ ((format(printf, 2, 3)));
+static int _line_append(struct output_line *outline, const char *fmt, ...)
+{
+	char buf[4096];
+	va_list ap;
+	int n;
+
+	va_start(ap, fmt);
+	n = vsnprintf(&buf[0], sizeof buf - 1, fmt, ap);
+	if (n < 0 || n > (int) sizeof buf - 1) {
+		log_error("vsnprintf failed for config line");
+		return 0;
+	}
+	va_end(ap);
+
+	if (!dm_pool_grow_object(outline->mem, &buf[0], strlen(buf))) {
+		log_error("dm_pool_grow_object failed for config line");
+		return 0;
+	}
+
+	return 1;
+}
+
+#define line_append(args...) do {if (!_line_append(outline, args)) {return_0;}} while (0)
+
+static int _line_end(struct output_line *outline)
+{
+	const char *line;
+
+	if (!dm_pool_grow_object(outline->mem, "\0", 1)) {
+		log_error("dm_pool_grow_object failed for config line");
+		return 0;
+	}
+
+	line = dm_pool_end_object(outline->mem);
+	if (!outline->fp)
+		log_print("%s", line);
+	else
+		fprintf(outline->fp, "%s\n", line);
+
+	return 1;
+}
+
+static int _write_value(struct output_line *outline, struct config_value *v)
+{
+	char *buf;
+
+	switch (v->type) {
+	case CFG_STRING:
+		if (!(buf = alloca(escaped_len(v->v.str)))) {
+			log_error("temporary stack allocation for a config "
+				  "string failed");
+			return 0;
+		}
+		line_append("\"%s\"", escape_double_quotes(buf, v->v.str));
+		break;
+
+	case CFG_FLOAT:
+		line_append("%f", v->v.r);
+		break;
+
+	case CFG_INT:
+		line_append("%" PRId64, v->v.i);
+		break;
+
+	case CFG_EMPTY_ARRAY:
+		line_append("[]");
+		break;
+
+	default:
+		log_error("_write_value: Unknown value type: %d", v->type);
+
+	}
+
+	return 1;
+}
+
+static int _write_config(struct config_node *n, int only_one,
+			 struct output_line *outline, int level)
+{
+	char space[MAX_INDENT + 1];
+	int l = (level < MAX_INDENT) ? level : MAX_INDENT;
+	int i;
+
+	if (!n)
+		return 1;
+
+	for (i = 0; i < l; i++)
+		space[i] = '\t';
+	space[i] = '\0';
+
+	do {
+		if (!_line_start(outline))
+			return_0;
+		line_append("%s%s", space, n->key);
+		if (!n->v) {
+			/* it's a sub section */
+			line_append(" {");
+			if (!_line_end(outline))
+				return_0;
+			if (!_line_start(outline))
+				return_0;
+			_write_config(n->child, 0, outline, level + 1);
+			line_append("%s}", space);
+		} else {
+			/* it's a value */
+			struct config_value *v = n->v;
+			line_append("=");
+			if (v->next) {
+				line_append("[");
+				while (v) {
+					if (!_write_value(outline, v))
+						return_0;
+					v = v->next;
+					if (v)
+						line_append(", ");
+				}
+				line_append("]");
+			} else
+				if (!_write_value(outline, v))
+					return_0;
+		}
+		if (!_line_end(outline))
+			return_0;
+		n = n->sib;
+	} while (n && !only_one);
+	/* FIXME: add error checking */
+	return 1;
+}
+
+int write_config_file(struct config_tree *cft, const char *file,
+		      int argc, char **argv)
+{
+	struct config_node *cn;
+	int r = 1;
+	struct output_line outline;
+	outline.fp = NULL;
+
+	if (!file)
+		file = "stdout";
+	else if (!(outline.fp = fopen(file, "w"))) {
+		log_sys_error("open", file);
+		return 0;
+	}
+
+	outline.mem = dm_pool_create("config_line", 1024);
+
+	log_verbose("Dumping configuration to %s", file);
+	if (!argc) {
+		if (!_write_config(cft->root, 0, &outline, 0)) {
+			log_error("Failure while writing to %s", file);
+			r = 0;
+		}
+	} else while (argc--) {
+		if ((cn = find_config_node(cft->root, *argv))) {
+			if (!_write_config(cn, 1, &outline, 0)) {
+				log_error("Failure while writing to %s", file);
+				r = 0;
+			}
+		} else {
+			log_error("Configuration node %s not found", *argv);
+			r = 0;
+		}
+		argv++;
+	}
+
+	if (outline.fp && lvm_fclose(outline.fp, file)) {
+		stack;
+		r = 0;
+	}
+
+	dm_pool_destroy(outline.mem);
+	return r;
+}
+
+/*
+ * parser
+ */
+static struct config_node *_file(struct parser *p)
+{
+	struct config_node *root = NULL, *n, *l = NULL;
+	while (p->t != TOK_EOF) {
+		if (!(n = _section(p)))
+			return_0;
+
+		if (!root)
+			root = n;
+		else
+			l->sib = n;
+		l = n;
+	}
+	return root;
+}
+
+static struct config_node *_section(struct parser *p)
+{
+	/* IDENTIFIER SECTION_B_CHAR VALUE* SECTION_E_CHAR */
+	struct config_node *root, *n, *l = NULL;
+	if (!(root = _create_node(p)))
+		return_0;
+
+	if (!(root->key = _dup_tok(p)))
+		return_0;
+
+	match(TOK_IDENTIFIER);
+
+	if (p->t == TOK_SECTION_B) {
+		match(TOK_SECTION_B);
+		while (p->t != TOK_SECTION_E) {
+			if (!(n = _section(p)))
+				return_0;
+
+			if (!root->child)
+				root->child = n;
+			else
+				l->sib = n;
+			l = n;
+		}
+		match(TOK_SECTION_E);
+	} else {
+		match(TOK_EQ);
+		if (!(root->v = _value(p)))
+			return_0;
+	}
+
+	return root;
+}
+
+static struct config_value *_value(struct parser *p)
+{
+	/* '[' TYPE* ']' | TYPE */
+	struct config_value *h = NULL, *l, *ll = NULL;
+	if (p->t == TOK_ARRAY_B) {
+		match(TOK_ARRAY_B);
+		while (p->t != TOK_ARRAY_E) {
+			if (!(l = _type(p)))
+				return_0;
+
+			if (!h)
+				h = l;
+			else
+				ll->next = l;
+			ll = l;
+
+			if (p->t == TOK_COMMA)
+				match(TOK_COMMA);
+		}
+		match(TOK_ARRAY_E);
+		/*
+		 * Special case for an empty array.
+		 */
+		if (!h) {
+			if (!(h = _create_value(p)))
+				return NULL;
+
+			h->type = CFG_EMPTY_ARRAY;
+		}
+
+	} else
+		h = _type(p);
+
+	return h;
+}
+
+static struct config_value *_type(struct parser *p)
+{
+	/* [+-]{0,1}[0-9]+ | [0-9]*\.[0-9]* | ".*" */
+	struct config_value *v = _create_value(p);
+
+	if (!v)
+		return NULL;
+
+	switch (p->t) {
+	case TOK_INT:
+		v->type = CFG_INT;
+		v->v.i = strtoll(p->tb, NULL, 0);	/* FIXME: check error */
+		match(TOK_INT);
+		break;
+
+	case TOK_FLOAT:
+		v->type = CFG_FLOAT;
+		v->v.r = strtod(p->tb, NULL);	/* FIXME: check error */
+		match(TOK_FLOAT);
+		break;
+
+	case TOK_STRING:
+		v->type = CFG_STRING;
+
+		p->tb++, p->te--;	/* strip "'s */
+		if (!(v->v.str = _dup_tok(p)))
+			return_0;
+		p->te++;
+		match(TOK_STRING);
+		break;
+
+	case TOK_STRING_ESCAPED:
+		v->type = CFG_STRING;
+
+		p->tb++, p->te--;	/* strip "'s */
+		if (!(v->v.str = _dup_tok(p)))
+			return_0;
+		unescape_double_quotes(v->v.str);
+		p->te++;
+		match(TOK_STRING_ESCAPED);
+		break;
+
+	default:
+		log_error("Parse error at byte %" PRIptrdiff_t " (line %d): expected a value",
+			  p->tb - p->fb + 1, p->line);
+		return 0;
+	}
+	return v;
+}
+
+static int _match_aux(struct parser *p, int t)
+{
+	if (p->t != t)
+		return 0;
+
+	_get_token(p, t);
+	return 1;
+}
+
+/*
+ * tokeniser
+ */
+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) {
+		p->t = TOK_EOF;
+		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) {
+	case SECTION_B_CHAR:
+		p->t = TOK_SECTION_B;
+		p->te++;
+		break;
+
+	case SECTION_E_CHAR:
+		p->t = TOK_SECTION_E;
+		p->te++;
+		break;
+
+	case '[':
+		p->t = TOK_ARRAY_B;
+		p->te++;
+		break;
+
+	case ']':
+		p->t = TOK_ARRAY_E;
+		p->te++;
+		break;
+
+	case ',':
+		p->t = TOK_COMMA;
+		p->te++;
+		break;
+
+	case '=':
+		p->t = TOK_EQ;
+		p->te++;
+		break;
+
+	case '"':
+		p->t = TOK_STRING_ESCAPED;
+		p->te++;
+		while ((p->te != p->fe) && (*p->te) && (*p->te != '"')) {
+			if ((*p->te == '\\') && (p->te + 1 != p->fe) &&
+			    *(p->te + 1))
+				p->te++;
+			p->te++;
+		}
+
+		if ((p->te != p->fe) && (*p->te))
+			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':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+	case '+':
+	case '-':
+		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;
+		}
+
+	default:
+		p->t = TOK_IDENTIFIER;
+		while ((p->te != p->fe) && (*p->te) && !isspace(*p->te) &&
+		       (*p->te != '#') && (*p->te != '=') &&
+		       (*p->te != SECTION_B_CHAR) &&
+		       (*p->te != SECTION_E_CHAR))
+			p->te++;
+		break;
+	}
+}
+
+static void _eat_space(struct parser *p)
+{
+	while ((p->tb != p->fe) && (*p->tb)) {
+		if (*p->te == '#')
+			while ((p->te != p->fe) && (*p->te) && (*p->te != '\n'))
+				p->te++;
+
+		else if (isspace(*p->te)) {
+			while ((p->te != p->fe) && (*p->te) && isspace(*p->te)) {
+				if (*p->te == '\n')
+					p->line++;
+				p->te++;
+			}
+		}
+
+		else
+			return;
+
+		p->tb = p->te;
+	}
+}
+
+/*
+ * memory management
+ */
+static struct config_value *_create_value(struct parser *p)
+{
+	struct config_value *v = dm_pool_alloc(p->mem, sizeof(*v));
+
+	if (v)
+		memset(v, 0, sizeof(*v));
+
+	return v;
+}
+
+static struct config_node *_create_node(struct parser *p)
+{
+	struct config_node *n = dm_pool_alloc(p->mem, sizeof(*n));
+
+	if (n)
+		memset(n, 0, sizeof(*n));
+
+	return n;
+}
+
+static char *_dup_tok(struct parser *p)
+{
+	size_t len = p->te - p->tb;
+	char *str = dm_pool_alloc(p->mem, len + 1);
+	if (!str)
+		return_0;
+	strncpy(str, p->tb, len);
+	str[len] = '\0';
+	return str;
+}
+
+/*
+ * utility functions
+ */
+static struct config_node *_find_config_node(const struct config_node *cn,
+					     const char *path)
+{
+	const char *e;
+	const struct config_node *cn_found = NULL;
+
+	while (cn) {
+		/* trim any leading slashes */
+		while (*path && (*path == sep))
+			path++;
+
+		/* find the end of this segment */
+		for (e = path; *e && (*e != sep); e++) ;
+
+		/* hunt for the node */
+		cn_found = NULL;
+		while (cn) {
+			if (_tok_match(cn->key, path, e)) {
+				/* Inefficient */
+				if (!cn_found)
+					cn_found = cn;
+				else
+					log_error("WARNING: Ignoring duplicate"
+						  " config node: %s ("
+						  "seeking %s)", cn->key, path);
+			}
+
+			cn = cn->sib;
+		}
+
+		if (cn_found && *e)
+			cn = cn_found->child;
+		else
+			break;	/* don't move into the last node */
+
+		path = e;
+	}
+
+	return (struct config_node *) cn_found;
+}
+
+static struct config_node *_find_first_config_node(const struct config_node *cn1,
+						   const struct config_node *cn2,
+						   const char *path)
+{
+	struct config_node *cn;
+
+	if (cn1 && (cn = _find_config_node(cn1, path)))
+		return cn;
+
+	if (cn2 && (cn = _find_config_node(cn2, path)))
+		return cn;
+
+	return NULL;
+}
+
+struct config_node *find_config_node(const struct config_node *cn,
+				     const char *path)
+{
+	return _find_config_node(cn, path);
+}
+
+static const char *_find_config_str(const struct config_node *cn1,
+				    const struct config_node *cn2,
+				    const char *path, const char *fail)
+{
+	const struct config_node *n = _find_first_config_node(cn1, cn2, path);
+
+	/* Empty strings are ignored */
+	if ((n && n->v && n->v->type == CFG_STRING) && (*n->v->v.str)) {
+		log_very_verbose("Setting %s to %s", path, n->v->v.str);
+		return n->v->v.str;
+	}
+
+	if (fail)
+		log_very_verbose("%s not found in config: defaulting to %s",
+				 path, fail);
+	return fail;
+}
+
+const char *find_config_str(const struct config_node *cn,
+			    const char *path, const char *fail)
+{
+	return _find_config_str(cn, NULL, path, fail);
+}
+
+static int64_t _find_config_int64(const struct config_node *cn1,
+				  const struct config_node *cn2,
+				  const char *path, int64_t fail)
+{
+	const struct config_node *n = _find_first_config_node(cn1, cn2, path);
+
+	if (n && n->v && n->v->type == CFG_INT) {
+		log_very_verbose("Setting %s to %" PRId64, path, n->v->v.i);
+		return n->v->v.i;
+	}
+
+	log_very_verbose("%s not found in config: defaulting to %" PRId64,
+			 path, fail);
+	return fail;
+}
+
+int find_config_int(const struct config_node *cn, const char *path, int fail)
+{
+	/* FIXME Add log_error message on overflow */
+	return (int) _find_config_int64(cn, NULL, path, (int64_t) fail);
+}
+
+static float _find_config_float(const struct config_node *cn1,
+				const struct config_node *cn2,
+				const char *path, float fail)
+{
+	const struct config_node *n = _find_first_config_node(cn1, cn2, path);
+
+	if (n && n->v && n->v->type == CFG_FLOAT) {
+		log_very_verbose("Setting %s to %f", path, n->v->v.r);
+		return n->v->v.r;
+	}
+
+	log_very_verbose("%s not found in config: defaulting to %f",
+			 path, fail);
+
+	return fail;
+
+}
+
+float find_config_float(const struct config_node *cn, const char *path,
+			float fail)
+{
+	return _find_config_float(cn, NULL, path, fail);
+}
+
+struct config_node *find_config_tree_node(struct cmd_context *cmd,
+					  const char *path)
+{
+	return _find_first_config_node(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path);
+}
+
+const char *find_config_tree_str(struct cmd_context *cmd,
+				 const char *path, const char *fail)
+{
+	return _find_config_str(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
+}
+
+int find_config_tree_int(struct cmd_context *cmd, const char *path,
+			 int fail)
+{
+	/* FIXME Add log_error message on overflow */
+	return (int) _find_config_int64(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, (int64_t) fail);
+}
+
+float find_config_tree_float(struct cmd_context *cmd, const char *path,
+			     float fail)
+{
+	return _find_config_float(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
+}
+
+static int _str_in_array(const char *str, const char * const values[])
+{
+	int i;
+
+	for (i = 0; values[i]; i++)
+		if (!strcasecmp(str, values[i]))
+			return 1;
+
+	return 0;
+}
+
+static int _str_to_bool(const char *str, int fail)
+{
+	const char * const _true_values[]  = { "y", "yes", "on", "true", NULL };
+	const char * const _false_values[] = { "n", "no", "off", "false", NULL };
+
+	if (_str_in_array(str, _true_values))
+		return 1;
+
+	if (_str_in_array(str, _false_values))
+		return 0;
+
+	return fail;
+}
+
+static int _find_config_bool(const struct config_node *cn1,
+			     const struct config_node *cn2,
+			     const char *path, int fail)
+{
+	const struct config_node *n = _find_first_config_node(cn1, cn2, path);
+	struct config_value *v;
+
+	if (!n)
+		return fail;
+
+	v = n->v;
+
+	switch (v->type) {
+	case CFG_INT:
+		return v->v.i ? 1 : 0;
+
+	case CFG_STRING:
+		return _str_to_bool(v->v.str, fail);
+	}
+
+	return fail;
+}
+
+int find_config_bool(const struct config_node *cn, const char *path, int fail)
+{
+	return _find_config_bool(cn, NULL, path, fail);
+}
+
+int find_config_tree_bool(struct cmd_context *cmd, const char *path, int fail)
+{
+	return _find_config_bool(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
+}
+
+int get_config_uint32(const struct config_node *cn, const char *path,
+		      uint32_t *result)
+{
+	const struct config_node *n;
+
+	n = find_config_node(cn, path);
+
+	if (!n || !n->v || n->v->type != CFG_INT)
+		return 0;
+
+	*result = n->v->v.i;
+	return 1;
+}
+
+int get_config_uint64(const struct config_node *cn, const char *path,
+		      uint64_t *result)
+{
+	const struct config_node *n;
+
+	n = find_config_node(cn, path);
+
+	if (!n || !n->v || n->v->type != CFG_INT)
+		return 0;
+
+	*result = (uint64_t) n->v->v.i;
+	return 1;
+}
+
+int get_config_str(const struct config_node *cn, const char *path,
+		   char **result)
+{
+	const struct config_node *n;
+
+	n = find_config_node(cn, path);
+
+	if (!n || !n->v || n->v->type != CFG_STRING)
+		return 0;
+
+	*result = n->v->v.str;
+	return 1;
+}
+
+/* Insert cn2 after cn1 */
+static void _insert_config_node(struct config_node **cn1,
+				struct config_node *cn2)
+{
+	if (!*cn1) {
+		*cn1 = cn2;
+		cn2->sib = NULL;
+	} else {
+		cn2->sib = (*cn1)->sib;
+		(*cn1)->sib = cn2;
+	}
+}
+
+/*
+ * Merge section cn2 into section cn1 (which has the same name)
+ * overwriting any existing cn1 nodes with matching names.
+ */
+static void _merge_section(struct config_node *cn1, struct config_node *cn2)
+{
+	struct config_node *cn, *nextn, *oldn;
+	struct config_value *cv;
+
+	for (cn = cn2->child; cn; cn = nextn) {
+		nextn = cn->sib;
+
+		/* Skip "tags" */
+		if (!strcmp(cn->key, "tags"))
+			continue;
+
+		/* Subsection? */
+		if (!cn->v)
+			/* Ignore - we don't have any of these yet */
+			continue;
+		/* Not already present? */
+		if (!(oldn = find_config_node(cn1->child, cn->key))) {
+			_insert_config_node(&cn1->child, cn);
+			continue;
+		}
+		/* Merge certain value lists */
+		if ((!strcmp(cn1->key, "activation") &&
+		     !strcmp(cn->key, "volume_list")) ||
+		    (!strcmp(cn1->key, "devices") &&
+		     (!strcmp(cn->key, "filter") || !strcmp(cn->key, "types")))) {
+			cv = cn->v;
+			while (cv->next)
+				cv = cv->next;
+			cv->next = oldn->v;
+		}
+
+		/* Replace values */
+		oldn->v = cn->v;
+	}
+}
+
+static int _match_host_tags(struct dm_list *tags, struct config_node *tn)
+{
+	struct config_value *tv;
+	const char *str;
+
+	for (tv = tn->v; tv; tv = tv->next) {
+		if (tv->type != CFG_STRING)
+			continue;
+		str = tv->v.str;
+		if (*str == '@')
+			str++;
+		if (!*str)
+			continue;
+		if (str_list_match_item(tags, str))
+			return 1;
+	}
+
+	return 0;
+}
+
+/* Destructively merge a new config tree into an existing one */
+int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft,
+		      struct config_tree *newdata)
+{
+	struct config_node *root = cft->root;
+	struct config_node *cn, *nextn, *oldn, *tn, *cn2;
+
+	for (cn = newdata->root; cn; cn = nextn) {
+		nextn = cn->sib;
+		/* Ignore tags section */
+		if (!strcmp(cn->key, "tags"))
+			continue;
+		/* If there's a tags node, skip if host tags don't match */
+		if ((tn = find_config_node(cn->child, "tags"))) {
+			if (!_match_host_tags(&cmd->tags, tn))
+				continue;
+		}
+		if (!(oldn = find_config_node(root, cn->key))) {
+			_insert_config_node(&cft->root, cn);
+			/* Remove any "tags" nodes */
+			for (cn2 = cn->child; cn2; cn2 = cn2->sib) {
+				if (!strcmp(cn2->key, "tags")) {
+					cn->child = cn2->sib;
+					continue;
+				}
+				if (cn2->sib && !strcmp(cn2->sib->key, "tags")) {
+					cn2->sib = cn2->sib->sib;
+					continue;
+				}
+			}
+			continue;
+		}
+		_merge_section(oldn, cn);
+	}
+
+	return 1;
+}
+
+/*
+ * Convert a token type to the char it represents.
+ */
+static char _token_type_to_char(int type)
+{
+	switch (type) {
+		case TOK_SECTION_B:
+			return SECTION_B_CHAR;
+		case TOK_SECTION_E:
+			return SECTION_E_CHAR;
+		default:
+			return 0;
+	}
+}
+
+/*
+ * Returns:
+ *  # of 'type' tokens in 'str'.
+ */
+static unsigned _count_tokens(const char *str, unsigned len, int type)
+{
+	char c;
+
+	c = _token_type_to_char(type);
+
+	return count_chars(str, len, c);
+}
+
+/*
+ * Heuristic function to make a quick guess as to whether a text
+ * region probably contains a valid config "section".  (Useful for
+ * scanning areas of the disk for old metadata.)
+ * Config sections contain various tokens, may contain other sections
+ * and strings, and are delimited by begin (type 'TOK_SECTION_B') and
+ * end (type 'TOK_SECTION_E') tokens.  As a quick heuristic, we just
+ * count the number of begin and end tokens, and see if they are
+ * non-zero and the counts match.
+ * Full validation of the section should be done with another function
+ * (for example, read_config_fd).
+ *
+ * Returns:
+ *  0 - probably is not a valid config section
+ *  1 - probably _is_ a valid config section
+ */
+unsigned maybe_config_section(const char *str, unsigned len)
+{
+	int begin_count;
+	int end_count;
+
+	begin_count = _count_tokens(str, len, TOK_SECTION_B);
+	end_count = _count_tokens(str, len, TOK_SECTION_E);
+
+	if (begin_count && end_count && (begin_count == end_count))
+		return 1;
+	else
+		return 0;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/config/config.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/config/config.h
diff -N src/external/gpl2/lvm2tools/dist/lib/config/config.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/config/config.h	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,115 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_CONFIG_H
+#define _LVM_CONFIG_H
+
+#include "lvm-types.h"
+
+struct device;
+struct cmd_context;
+
+enum {
+	CFG_STRING,
+	CFG_FLOAT,
+	CFG_INT,
+	CFG_EMPTY_ARRAY
+};
+
+struct config_value {
+	int type;
+	union {
+		int64_t i;
+		float r;
+		char *str;
+	} v;
+	struct config_value *next;	/* for arrays */
+};
+
+struct config_node {
+	char *key;
+	struct config_node *sib, *child;
+	struct config_value *v;
+};
+
+struct config_tree {
+	struct config_node *root;
+};
+
+struct config_tree_list {
+	struct dm_list list;
+	struct config_tree *cft;
+};
+
+struct config_tree *create_config_tree(const char *filename, int keep_open);
+struct config_tree *create_config_tree_from_string(struct cmd_context *cmd,
+						   const char *config_settings);
+void destroy_config_tree(struct config_tree *cft);
+
+typedef uint32_t (*checksum_fn_t) (uint32_t initial, const void *buf, uint32_t size);
+
+int read_config_fd(struct config_tree *cft, struct device *dev,
+		   off_t offset, size_t size, off_t offset2, size_t size2,
+		   checksum_fn_t checksum_fn, uint32_t checksum);
+
+int read_config_file(struct config_tree *cft);
+int write_config_file(struct config_tree *cft, const char *file,
+		      int argc, char **argv);
+time_t config_file_timestamp(struct config_tree *cft);
+int config_file_changed(struct config_tree *cft);
+int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft,
+		      struct config_tree *newdata);
+
+struct config_node *find_config_node(const struct config_node *cn,
+				     const char *path);
+const char *find_config_str(const struct config_node *cn, const char *path,
+			    const char *fail);
+int find_config_int(const struct config_node *cn, const char *path, int fail);
+float find_config_float(const struct config_node *cn, const char *path,
+			float fail);
+
+/*
+ * These versions check an override tree, if present, first.
+ */
+struct config_node *find_config_tree_node(struct cmd_context *cmd,
+					  const char *path);
+const char *find_config_tree_str(struct cmd_context *cmd,
+				 const char *path, const char *fail);
+int find_config_tree_int(struct cmd_context *cmd, const char *path,
+			 int fail);
+float find_config_tree_float(struct cmd_context *cmd, const char *path,
+			     float fail);
+
+/*
+ * Understands (0, ~0), (y, n), (yes, no), (on,
+ * off), (true, false).
+ */
+int find_config_bool(const struct config_node *cn, const char *path, int fail);
+int find_config_tree_bool(struct cmd_context *cmd, const char *path, int fail);
+
+int get_config_uint32(const struct config_node *cn, const char *path,
+		      uint32_t *result);
+
+int get_config_uint64(const struct config_node *cn, const char *path,
+		      uint64_t *result);
+
+int get_config_str(const struct config_node *cn, const char *path,
+		   char **result);
+
+unsigned maybe_config_section(const char *str, unsigned len);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/config/defaults.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/config/defaults.h
diff -N src/external/gpl2/lvm2tools/dist/lib/config/defaults.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/config/defaults.h	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,131 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_DEFAULTS_H
+#define _LVM_DEFAULTS_H
+
+#define DEFAULT_ARCHIVE_ENABLED 1
+#define DEFAULT_BACKUP_ENABLED 1
+
+#define DEFAULT_ARCHIVE_SUBDIR "archive"
+#define DEFAULT_BACKUP_SUBDIR "backup"
+#define DEFAULT_CACHE_SUBDIR "cache"
+#define DEFAULT_CACHE_FILE_PREFIX ""
+
+#define DEFAULT_ARCHIVE_DAYS 30
+#define DEFAULT_ARCHIVE_NUMBER 10
+
+#define DEFAULT_SYS_DIR "/etc/lvm"
+#define DEFAULT_DEV_DIR "/dev"
+#define DEFAULT_PROC_DIR "/proc"
+#define DEFAULT_SYSFS_SCAN 1
+#define DEFAULT_MD_COMPONENT_DETECTION 1
+#define DEFAULT_MD_CHUNK_ALIGNMENT 1
+#define DEFAULT_IGNORE_SUSPENDED_DEVICES 1
+
+#define DEFAULT_LOCK_DIR "/var/lock/lvm"
+#define DEFAULT_LOCKING_LIB "liblvm2clusterlock.so"
+#define DEFAULT_FALLBACK_TO_LOCAL_LOCKING 1
+#define DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING 1
+
+#define DEFAULT_MIRRORLOG "disk"
+#define DEFAULT_MIRROR_LOG_FAULT_POLICY "allocate"
+#define DEFAULT_MIRROR_DEV_FAULT_POLICY "remove"
+#define DEFAULT_DMEVENTD_MIRROR_LIB "libdevmapper-event-lvm2mirror.so"
+#define DEFAULT_DMEVENTD_MONITOR 1
+
+#define DEFAULT_UMASK 0077
+
+#ifdef LVM1_FALLBACK
+#  define DEFAULT_FALLBACK_TO_LVM1 1
+#else
+#  define DEFAULT_FALLBACK_TO_LVM1 0
+#endif
+
+#ifdef LVM1_SUPPORT
+#  define DEFAULT_FORMAT "lvm1"
+#else
+#  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_READ_AHEAD "auto"
+#define DEFAULT_EXTENT_SIZE 4096	/* In KB */
+
+#define DEFAULT_MSG_PREFIX "  "
+#define DEFAULT_CMD_NAME 0
+#define DEFAULT_OVERWRITE 0
+
+#ifndef DEFAULT_LOG_FACILITY
+#  define DEFAULT_LOG_FACILITY LOG_USER
+#endif
+
+#define DEFAULT_SYSLOG 1
+#define DEFAULT_VERBOSE 0
+#define DEFAULT_LOGLEVEL 0
+#define DEFAULT_INDENT 1
+#define DEFAULT_UNITS "h"
+#define DEFAULT_SUFFIX 1
+#define DEFAULT_HOSTTAGS 0
+
+#ifdef DEVMAPPER_SUPPORT
+#  define DEFAULT_ACTIVATION 1
+#  define DEFAULT_RESERVED_MEMORY 8192
+#  define DEFAULT_RESERVED_STACK 256
+#  define DEFAULT_PROCESS_PRIORITY -18
+#else
+#  define DEFAULT_ACTIVATION 0
+#endif
+
+#define DEFAULT_STRIPE_FILLER "error"
+#define DEFAULT_MIRROR_REGION_SIZE 512	/* KB */
+#define DEFAULT_INTERVAL 15
+
+#ifdef READLINE_SUPPORT
+#  define DEFAULT_MAX_HISTORY 100
+#endif
+
+#define DEFAULT_REP_ALIGNED 1
+#define DEFAULT_REP_BUFFERED 1
+#define DEFAULT_REP_COLUMNS_AS_ROWS 0
+#define DEFAULT_REP_HEADINGS 1
+#define DEFAULT_REP_PREFIXES 0
+#define DEFAULT_REP_QUOTED 1
+#define DEFAULT_REP_SEPARATOR " "
+
+#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent,move_pv,mirror_log,copy_percent,convert_lv"
+#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_PVSEGS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size"
+
+#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,lv_kernel_major,lv_kernel_minor,origin,snap_percent,move_pv,copy_percent,mirror_log,convert_lv,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,dev_size,pv_uuid"
+#define DEFAULT_SEGS_COLS_VERB "lv_name,vg_name,lv_attr,seg_start,seg_size,stripes,segtype,stripesize,chunksize"
+#define DEFAULT_PVSEGS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size,lv_name,seg_start_pe,segtype,seg_pe_ranges"
+
+#define DEFAULT_LVS_SORT "vg_name,lv_name"
+#define DEFAULT_VGS_SORT "vg_name"
+#define DEFAULT_PVS_SORT "pv_name"
+#define DEFAULT_SEGS_SORT "vg_name,lv_name,seg_start"
+#define DEFAULT_PVSEGS_SORT "pv_name,pvseg_start"
+
+#endif				/* _LVM_DEFAULTS_H */
Index: src/external/gpl2/lvm2tools/dist/lib/datastruct/btree.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/datastruct/btree.c
diff -N src/external/gpl2/lvm2tools/dist/lib/datastruct/btree.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/datastruct/btree.c	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,139 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "btree.h"
+
+struct node {
+	uint32_t key;
+	struct node *l, *r, *p;
+
+	void *data;
+};
+
+struct btree {
+	struct dm_pool *mem;
+	struct node *root;
+};
+
+struct btree *btree_create(struct dm_pool *mem)
+{
+	struct btree *t = dm_pool_alloc(mem, sizeof(*t));
+
+	if (t) {
+		t->mem = mem;
+		t->root = NULL;
+	}
+
+	return t;
+}
+
+/*
+ * Shuffle the bits in a key, to try and remove
+ * any ordering.
+ */
+static uint32_t _shuffle(uint32_t k)
+{
+#if 1
+	return ((k & 0xff) << 24 |
+		(k & 0xff00) << 8 |
+		(k & 0xff0000) >> 8 | (k & 0xff000000) >> 24);
+#else
+	return k;
+#endif
+}
+
+static struct node **_lookup(struct node *const *c, uint32_t key,
+			     struct node **p)
+{
+	*p = NULL;
+	while (*c) {
+		*p = *c;
+		if ((*c)->key == key)
+			break;
+
+		if (key < (*c)->key)
+			c = &(*c)->l;
+
+		else
+			c = &(*c)->r;
+	}
+
+	return (struct node **)c;
+}
+
+void *btree_lookup(const struct btree *t, uint32_t k)
+{
+	uint32_t key = _shuffle(k);
+	struct node *p, **c = _lookup(&t->root, key, &p);
+	return (*c) ? (*c)->data : NULL;
+}
+
+int btree_insert(struct btree *t, uint32_t k, void *data)
+{
+	uint32_t key = _shuffle(k);
+	struct node *p, **c = _lookup(&t->root, key, &p), *n;
+
+	if (!*c) {
+		if (!(n = dm_pool_alloc(t->mem, sizeof(*n))))
+			return_0;
+
+		n->key = key;
+		n->data = data;
+		n->l = n->r = NULL;
+		n->p = p;
+
+		*c = n;
+	}
+
+	return 1;
+}
+
+void *btree_get_data(const struct btree_iter *it)
+{
+	return ((struct node *) it)->data;
+}
+
+static struct node *_left(struct node *n)
+{
+	while (n->l)
+		n = n->l;
+	return n;
+}
+
+struct btree_iter *btree_first(const struct btree *t)
+{
+	if (!t->root)
+		return NULL;
+
+	return (struct btree_iter *) _left(t->root);
+}
+
+struct btree_iter *btree_next(const struct btree_iter *it)
+{
+	struct node *n = (struct node *) it;
+	uint32_t k = n->key;
+
+	if (n->r)
+		return (struct btree_iter *) _left(n->r);
+
+	do
+		n = n->p;
+	while (n && k > n->key);
+
+	return (struct btree_iter *) n;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/datastruct/btree.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/datastruct/btree.h
diff -N src/external/gpl2/lvm2tools/dist/lib/datastruct/btree.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/datastruct/btree.h	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,34 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_BTREE_H
+#define _LVM_BTREE_H
+
+struct btree;
+
+struct btree *btree_create(struct dm_pool *mem);
+
+void *btree_lookup(const struct btree *t, uint32_t k);
+int btree_insert(struct btree *t, uint32_t k, void *data);
+
+struct btree_iter;
+void *btree_get_data(const struct btree_iter *it);
+
+struct btree_iter *btree_first(const struct btree *t);
+struct btree_iter *btree_next(const struct btree_iter *it);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/datastruct/list.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/datastruct/list.c
diff -N src/external/gpl2/lvm2tools/dist/lib/datastruct/list.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/datastruct/list.c	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,147 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+
+/*
+ * Initialise a list before use.
+ * The list head's next and previous pointers point back to itself.
+ */
+void dm_list_init(struct dm_list *head)
+{
+	head->n = head->p = head;
+}
+
+/*
+ * Insert an element before 'head'.
+ * If 'head' is the list head, this adds an element to the end of the list.
+ */
+void dm_list_add(struct dm_list *head, struct dm_list *elem)
+{
+	assert(head->n);
+
+	elem->n = head;
+	elem->p = head->p;
+
+	head->p->n = elem;
+	head->p = elem;
+}
+
+/*
+ * Insert an element after 'head'.
+ * If 'head' is the list head, this adds an element to the front of the list.
+ */
+void dm_list_add_h(struct dm_list *head, struct dm_list *elem)
+{
+	assert(head->n);
+
+	elem->n = head->n;
+	elem->p = head;
+
+	head->n->p = elem;
+	head->n = elem;
+}
+
+/*
+ * Delete an element from its list.
+ * Note that this doesn't change the element itself - it may still be safe
+ * to follow its pointers.
+ */
+void dm_list_del(struct dm_list *elem)
+{
+	elem->n->p = elem->p;
+	elem->p->n = elem->n;
+}
+
+/*
+ * Remove an element from existing list and insert before 'head'.
+ */
+void dm_list_move(struct dm_list *head, struct dm_list *elem)
+{
+        dm_list_del(elem);
+        dm_list_add(head, elem);
+}
+
+/*
+ * Is the list empty?
+ */
+int dm_list_empty(const struct dm_list *head)
+{
+	return head->n == head;
+}
+
+/*
+ * Is this the first element of the list?
+ */
+int dm_list_start(const struct dm_list *head, const struct dm_list *elem)
+{
+	return elem->p == head;
+}
+
+/*
+ * Is this the last element of the list?
+ */
+int dm_list_end(const struct dm_list *head, const struct dm_list *elem)
+{
+	return elem->n == head;
+}
+
+/*
+ * Return first element of the list or NULL if empty
+ */
+struct dm_list *dm_list_first(const struct dm_list *head)
+{
+	return (dm_list_empty(head) ? NULL : head->n);
+}
+
+/*
+ * Return last element of the list or NULL if empty
+ */
+struct dm_list *dm_list_last(const struct dm_list *head)
+{
+	return (dm_list_empty(head) ? NULL : head->p);
+}
+
+/*
+ * Return the previous element of the list, or NULL if we've reached the start.
+ */
+struct dm_list *dm_list_prev(const struct dm_list *head, const struct dm_list *elem)
+{
+	return (dm_list_start(head, elem) ? NULL : elem->p);
+}
+
+/*
+ * Return the next element of the list, or NULL if we've reached the end.
+ */
+struct dm_list *dm_list_next(const struct dm_list *head, const struct dm_list *elem)
+{
+	return (dm_list_end(head, elem) ? NULL : elem->n);
+}
+
+/*
+ * Return the number of elements in a list by walking it.
+ */
+unsigned int dm_list_size(const struct dm_list *head)
+{
+	unsigned int s = 0;
+	const struct dm_list *v;
+
+	dm_list_iterate(v, head)
+	    s++;
+
+	return s;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/datastruct/list.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/datastruct/list.h
diff -N src/external/gpl2/lvm2tools/dist/lib/datastruct/list.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/datastruct/list.h	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,210 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_LIST_H
+#define _LVM_LIST_H
+
+#include <assert.h>
+
+/*
+ * A list consists of a list head plus elements.
+ * Each element has 'next' and 'previous' pointers.
+ * The list head's pointers point to the first and the last element.
+ */
+
+struct dm_list {
+	struct dm_list *n, *p;
+};
+
+/*
+ * Initialise a list before use.
+ * The list head's next and previous pointers point back to itself.
+ */
+#define DM_LIST_INIT(name)	struct dm_list name = { &(name), &(name) }
+void dm_list_init(struct dm_list *head);
+
+/*
+ * Insert an element before 'head'.
+ * If 'head' is the list head, this adds an element to the end of the list.
+ */
+void dm_list_add(struct dm_list *head, struct dm_list *elem);
+
+/*
+ * Insert an element after 'head'.
+ * If 'head' is the list head, this adds an element to the front of the list.
+ */
+void dm_list_add_h(struct dm_list *head, struct dm_list *elem);
+
+/*
+ * Delete an element from its list.
+ * Note that this doesn't change the element itself - it may still be safe
+ * to follow its pointers.
+ */
+void dm_list_del(struct dm_list *elem);
+
+/*
+ * Remove an element from existing list and insert before 'head'.
+ */
+void dm_list_move(struct dm_list *head, struct dm_list *elem);
+
+/*
+ * Is the list empty?
+ */
+int dm_list_empty(const struct dm_list *head);
+
+/*
+ * Is this the first element of the list?
+ */
+int dm_list_start(const struct dm_list *head, const struct dm_list *elem);
+
+/*
+ * Is this the last element of the list?
+ */
+int dm_list_end(const struct dm_list *head, const struct dm_list *elem);
+
+/*
+ * Return first element of the list or NULL if empty
+ */
+struct dm_list *dm_list_first(const struct dm_list *head);
+
+/*
+ * Return last element of the list or NULL if empty
+ */
+struct dm_list *dm_list_last(const struct dm_list *head);
+
+/*
+ * Return the previous element of the list, or NULL if we've reached the start.
+ */
+struct dm_list *dm_list_prev(const struct dm_list *head, const struct dm_list *elem);
+
+/*
+ * Return the next element of the list, or NULL if we've reached the end.
+ */
+struct dm_list *dm_list_next(const struct dm_list *head, const struct dm_list *elem);
+
+/*
+ * Given the address v of an instance of 'struct dm_list' called 'head' 
+ * contained in a structure of type t, return the containing structure.
+ */
+#define dm_list_struct_base(v, t, head) \
+    ((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->head))
+
+/*
+ * Given the address v of an instance of 'struct dm_list list' contained in
+ * a structure of type t, return the containing structure.
+ */
+#define dm_list_item(v, t) dm_list_struct_base((v), t, list)
+
+/*
+ * Given the address v of one known element e in a known structure of type t,
+ * return another element f.
+ */
+#define dm_struct_field(v, t, e, f) \
+    (((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->e))->f)
+
+/*
+ * Given the address v of a known element e in a known structure of type t,
+ * return the list head 'list'
+ */
+#define dm_list_head(v, t, e) dm_struct_field(v, t, e, list)
+
+/*
+ * Set v to each element of a list in turn.
+ */
+#define dm_list_iterate(v, head) \
+	for (v = (head)->n; v != head; v = v->n)
+
+/*
+ * Set v to each element in a list in turn, starting from the element 
+ * in front of 'start'.
+ * You can use this to 'unwind' a list_iterate and back out actions on
+ * already-processed elements.
+ * If 'start' is 'head' it walks the list backwards.
+ */
+#define dm_list_uniterate(v, head, start) \
+	for (v = (start)->p; v != head; v = v->p)
+
+/*
+ * A safe way to walk a list and delete and free some elements along
+ * the way.
+ * t must be defined as a temporary variable of the same type as v.
+ */
+#define dm_list_iterate_safe(v, t, head) \
+	for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
+
+/*
+ * Walk a list, setting 'v' in turn to the containing structure of each item.
+ * The containing structure should be the same type as 'v'.
+ * The 'struct dm_list' variable within the containing structure is 'field'.
+ */
+#define dm_list_iterate_items_gen(v, head, field) \
+	for (v = dm_list_struct_base((head)->n, typeof(*v), field); \
+	     &v->field != (head); \
+	     v = dm_list_struct_base(v->field.n, typeof(*v), field))
+
+/*
+ * Walk a list, setting 'v' in turn to the containing structure of each item.
+ * The containing structure should be the same type as 'v'.
+ * The list should be 'struct dm_list list' within the containing structure.
+ */
+#define dm_list_iterate_items(v, head) dm_list_iterate_items_gen(v, (head), list)
+
+/*
+ * Walk a list, setting 'v' in turn to the containing structure of each item.
+ * The containing structure should be the same type as 'v'.
+ * The 'struct dm_list' variable within the containing structure is 'field'.
+ * t must be defined as a temporary variable of the same type as v.
+ */
+#define dm_list_iterate_items_gen_safe(v, t, head, field) \
+	for (v = dm_list_struct_base((head)->n, typeof(*v), field), \
+	     t = dm_list_struct_base(v->field.n, typeof(*v), field); \
+	     &v->field != (head); \
+	     v = t, t = dm_list_struct_base(v->field.n, typeof(*v), field))
+/*
+ * Walk a list, setting 'v' in turn to the containing structure of each item.
+ * The containing structure should be the same type as 'v'.
+ * The list should be 'struct dm_list list' within the containing structure.
+ * t must be defined as a temporary variable of the same type as v.
+ */
+#define dm_list_iterate_items_safe(v, t, head) \
+	dm_list_iterate_items_gen_safe(v, t, (head), list)
+
+/*
+ * Walk a list backwards, setting 'v' in turn to the containing structure 
+ * of each item.
+ * The containing structure should be the same type as 'v'.
+ * The 'struct dm_list' variable within the containing structure is 'field'.
+ */
+#define dm_list_iterate_back_items_gen(v, head, field) \
+	for (v = dm_list_struct_base((head)->p, typeof(*v), field); \
+	     &v->field != (head); \
+	     v = dm_list_struct_base(v->field.p, typeof(*v), field))
+
+/*
+ * Walk a list backwards, setting 'v' in turn to the containing structure 
+ * of each item.
+ * The containing structure should be the same type as 'v'.
+ * The list should be 'struct dm_list list' within the containing structure.
+ */
+#define dm_list_iterate_back_items(v, head) dm_list_iterate_back_items_gen(v, (head), list)
+
+/*
+ * Return the number of elements in a list by walking it.
+ */
+unsigned int dm_list_size(const struct dm_list *head);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/datastruct/lvm-types.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/datastruct/lvm-types.h
diff -N src/external/gpl2/lvm2tools/dist/lib/datastruct/lvm-types.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/datastruct/lvm-types.h	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,34 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_TYPES_H
+#define _LVM_TYPES_H
+
+#include <sys/types.h>
+#include <inttypes.h>
+
+/* Define some portable printing types */
+#define PRIsize_t "zu"
+#define PRIptrdiff_t "td"
+#define PRIpid_t PRId32
+
+struct str_list {
+	struct dm_list list;
+	const char *str;
+};
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/datastruct/str_list.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/datastruct/str_list.c
diff -N src/external/gpl2/lvm2tools/dist/lib/datastruct/str_list.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/datastruct/str_list.c	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,123 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "str_list.h"
+
+struct dm_list *str_list_create(struct dm_pool *mem)
+{
+	struct dm_list *sl;
+
+	if (!(sl = dm_pool_alloc(mem, sizeof(struct dm_list))))
+		return_NULL;
+
+	dm_list_init(sl);
+
+	return sl;
+}
+
+int str_list_add(struct dm_pool *mem, struct dm_list *sll, const char *str)
+{
+	struct str_list *sln;
+
+	if (!str)
+		return_0;
+
+	/* Already in list? */
+	if (str_list_match_item(sll, str))
+		return 1;
+
+	if (!(sln = dm_pool_alloc(mem, sizeof(*sln))))
+		return_0;
+
+	sln->str = str;
+	dm_list_add(sll, &sln->list);
+
+	return 1;
+}
+
+int str_list_del(struct dm_list *sll, const char *str)
+{
+	struct dm_list *slh, *slht;
+
+	dm_list_iterate_safe(slh, slht, sll) {
+		if (!strcmp(str, dm_list_item(slh, struct str_list)->str))
+			 dm_list_del(slh);
+	}
+
+	return 1;
+}
+
+int str_list_dup(struct dm_pool *mem, struct dm_list *sllnew,
+		 const struct dm_list *sllold)
+{
+	struct str_list *sl;
+
+	dm_list_init(sllnew);
+
+	dm_list_iterate_items(sl, sllold) {
+		if (!str_list_add(mem, sllnew, dm_pool_strdup(mem, sl->str)))
+			return_0;
+	}
+
+	return 1;
+}
+
+/*
+ * Is item on list?
+ */
+int str_list_match_item(const struct dm_list *sll, const char *str)
+{
+	struct str_list *sl;
+
+	dm_list_iterate_items(sl, sll)
+	    if (!strcmp(str, sl->str))
+		return 1;
+
+	return 0;
+}
+
+/*
+ * Is at least one item on both lists?
+ */
+int str_list_match_list(const struct dm_list *sll, const struct dm_list *sll2)
+{
+	struct str_list *sl;
+
+	dm_list_iterate_items(sl, sll)
+	    if (str_list_match_item(sll2, sl->str))
+		return 1;
+
+	return 0;
+}
+
+/*
+ * Do both lists contain the same set of items?
+ */
+int str_list_lists_equal(const struct dm_list *sll, const struct dm_list *sll2)
+{
+	struct str_list *sl;
+
+	if (dm_list_size(sll) != dm_list_size(sll2))
+		return 0;
+
+	dm_list_iterate_items(sl, sll)
+	    if (!str_list_match_item(sll2, sl->str))
+		return 0;
+
+	return 1;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/datastruct/str_list.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/datastruct/str_list.h
diff -N src/external/gpl2/lvm2tools/dist/lib/datastruct/str_list.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/datastruct/str_list.h	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,30 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_STR_LIST_H
+#define _LVM_STR_LIST_H
+
+struct dm_list *str_list_create(struct dm_pool *mem);
+int str_list_add(struct dm_pool *mem, struct dm_list *sll, const char *str);
+int str_list_del(struct dm_list *sll, const char *str);
+int str_list_match_item(const struct dm_list *sll, const char *str);
+int str_list_match_list(const struct dm_list *sll, const struct dm_list *sll2);
+int str_list_lists_equal(const struct dm_list *sll, const struct dm_list *sll2);
+int str_list_dup(struct dm_pool *mem, struct dm_list *sllnew,
+		 const struct dm_list *sllold);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/device/dev-cache.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/device/dev-cache.c
diff -N src/external/gpl2/lvm2tools/dist/lib/device/dev-cache.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/device/dev-cache.c	12 Dec 2008 16:32:59 -0000	1.1.1.1.2.2
@@ -0,0 +1,799 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "dev-cache.h"
+#include "lvm-types.h"
+#include "btree.h"
+#include "filter.h"
+#include "filter-persistent.h"
+#include "toolcontext.h"
+
+#include <unistd.h>
+#include <sys/param.h>
+#include <dirent.h>
+
+#ifdef __NetBSD__
+#include "netbsd.h"
+#endif
+
+struct dev_iter {
+	struct btree_iter *current;
+	struct dev_filter *filter;
+};
+
+struct dir_list {
+	struct dm_list list;
+	char dir[0];
+};
+
+static struct {
+	struct dm_pool *mem;
+	struct dm_hash_table *names;
+	struct btree *devices;
+	struct dm_regex *preferred_names_matcher;
+
+	int has_scanned;
+	struct dm_list dirs;
+	struct dm_list files;
+
+} _cache;
+
+#define _alloc(x) dm_pool_zalloc(_cache.mem, (x))
+#define _free(x) dm_pool_free(_cache.mem, (x))
+#define _strdup(x) dm_pool_strdup(_cache.mem, (x))
+
+static int _insert(const char *path, int rec);
+
+struct device *dev_create_file(const char *filename, struct device *dev,
+			       struct str_list *alias, int use_malloc)
+{
+	int allocate = !dev;
+
+	if (allocate) {
+		if (use_malloc) {
+			if (!(dev = dm_malloc(sizeof(*dev)))) {
+				log_error("struct device allocation failed");
+				return NULL;
+			}
+			if (!(alias = dm_malloc(sizeof(*alias)))) {
+				log_error("struct str_list allocation failed");
+				dm_free(dev);
+				return NULL;
+			}
+			if (!(alias->str = dm_strdup(filename))) {
+				log_error("filename strdup failed");
+				dm_free(dev);
+				dm_free(alias);
+				return NULL;
+			}
+			dev->flags = DEV_ALLOCED;
+		} else {
+			if (!(dev = _alloc(sizeof(*dev)))) {
+				log_error("struct device allocation failed");
+				return NULL;
+			}
+			if (!(alias = _alloc(sizeof(*alias)))) {
+				log_error("struct str_list allocation failed");
+				_free(dev);
+				return NULL;
+			}
+			if (!(alias->str = _strdup(filename))) {
+				log_error("filename strdup failed");
+				return NULL;
+			}
+		}
+	} else if (!(alias->str = dm_strdup(filename))) {
+		log_error("filename strdup failed");
+		return NULL;
+	}
+
+	dev->flags |= DEV_REGULAR;
+	dm_list_init(&dev->aliases);
+	dm_list_add(&dev->aliases, &alias->list);
+	dev->end = UINT64_C(0);
+	dev->dev = 0;
+	dev->fd = -1;
+	dev->open_count = 0;
+	dev->block_size = -1;
+	memset(dev->pvid, 0, sizeof(dev->pvid));
+	dm_list_init(&dev->open_list);
+
+	return dev;
+}
+
+static struct device *_dev_create(dev_t d)
+{
+	struct device *dev;
+
+	if (!(dev = _alloc(sizeof(*dev)))) {
+		log_error("struct device allocation failed");
+		return NULL;
+	}
+	dev->flags = 0;
+	dm_list_init(&dev->aliases);
+	dev->dev = d;
+	dev->fd = -1;
+	dev->open_count = 0;
+	dev->block_size = -1;
+	dev->end = UINT64_C(0);
+	memset(dev->pvid, 0, sizeof(dev->pvid));
+	dm_list_init(&dev->open_list);
+
+	return dev;
+}
+
+void dev_set_preferred_name(struct str_list *sl, struct device *dev)
+{
+	/*
+	 * Don't interfere with ordering specified in config file.
+	 */
+	if (_cache.preferred_names_matcher)
+		return;
+
+	log_debug("%s: New preferred name", sl->str);
+	dm_list_del(&sl->list);
+	dm_list_add_h(&dev->aliases, &sl->list);
+}
+
+/* Return 1 if we prefer path1 else return 0 */
+static int _compare_paths(const char *path0, const char *path1)
+{
+	int slash0 = 0, slash1 = 0;
+	int m0, m1;
+	const char *p;
+	char p0[PATH_MAX], p1[PATH_MAX];
+	char *s0, *s1;
+	struct stat stat0, stat1;
+
+	/*
+	 * FIXME Better to compare patterns one-at-a-time against all names.
+	 */
+	if (_cache.preferred_names_matcher) {
+		m0 = dm_regex_match(_cache.preferred_names_matcher, path0);
+		m1 = dm_regex_match(_cache.preferred_names_matcher, path1);
+
+		if (m0 != m1) {
+			if (m0 < 0)
+				return 1;
+			if (m1 < 0)
+				return 0;
+			if (m0 < m1)
+				return 1;
+			if (m1 < m0)
+				return 0;
+		}
+	}
+
+	/*
+	 * Built-in rules.
+	 */
+
+	/* Return the path with fewer slashes */
+	for (p = path0; p++; p = (const char *) strchr(p, '/'))
+		slash0++;
+
+	for (p = path1; p++; p = (const char *) strchr(p, '/'))
+		slash1++;
+
+	if (slash0 < slash1)
+		return 0;
+	if (slash1 < slash0)
+		return 1;
+
+	strncpy(p0, path0, PATH_MAX);
+	strncpy(p1, path1, PATH_MAX);
+	s0 = &p0[0] + 1;
+	s1 = &p1[0] + 1;
+
+	/* We prefer symlinks - they exist for a reason!
+	 * So we prefer a shorter path before the first symlink in the name.
+	 * FIXME Configuration option to invert this? */
+	while (s0) {
+		s0 = strchr(s0, '/');
+		s1 = strchr(s1, '/');
+		if (s0) {
+			*s0 = '\0';
+			*s1 = '\0';
+		}
+		if (lstat(p0, &stat0)) {
+			log_sys_very_verbose("lstat", p0);
+			return 1;
+		}
+		if (lstat(p1, &stat1)) {
+			log_sys_very_verbose("lstat", p1);
+			return 0;
+		}
+		if (S_ISLNK(stat0.st_mode) && !S_ISLNK(stat1.st_mode))
+			return 0;
+		if (!S_ISLNK(stat0.st_mode) && S_ISLNK(stat1.st_mode))
+			return 1;
+		if (s0) {
+			*s0++ = '/';
+			*s1++ = '/';
+		}
+	}
+
+	/* ASCII comparison */
+	if (strcmp(path0, path1) < 0)
+		return 0;
+	else
+		return 1;
+}
+
+static int _add_alias(struct device *dev, const char *path)
+{
+	struct str_list *sl = _alloc(sizeof(*sl));
+	struct str_list *strl;
+	const char *oldpath;
+	int prefer_old = 1;
+
+	if (!sl)
+		return_0;
+
+	/* Is name already there? */
+	dm_list_iterate_items(strl, &dev->aliases) {
+		if (!strcmp(strl->str, path)) {
+			log_debug("%s: Already in device cache", path);
+			return 1;
+		}
+	}
+
+	if (!(sl->str = dm_pool_strdup(_cache.mem, path)))
+		return_0;
+
+	if (!dm_list_empty(&dev->aliases)) {
+		oldpath = dm_list_item(dev->aliases.n, struct str_list)->str;
+		prefer_old = _compare_paths(path, oldpath);
+		log_debug("%s: Aliased to %s in device cache%s",
+			  path, oldpath, prefer_old ? "" : " (preferred name)");
+
+	} else
+		log_debug("%s: Added to device cache", path);
+
+	if (prefer_old)
+		dm_list_add(&dev->aliases, &sl->list);
+	else
+		dm_list_add_h(&dev->aliases, &sl->list);
+
+	return 1;
+}
+
+/*
+ * Either creates a new dev, or adds an alias to
+ * an existing dev.
+ */
+static int _insert_dev(const char *path, dev_t d)
+{
+	struct device *dev;
+	static dev_t loopfile_count = 0;
+	int loopfile = 0;
+
+	/* Generate pretend device numbers for loopfiles */
+	if (!d) {
+		if (dm_hash_lookup(_cache.names, path))
+			return 1;
+		d = ++loopfile_count;
+		loopfile = 1;
+	}
+
+	/* is this device already registered ? */
+	if (!(dev = (struct device *) btree_lookup(_cache.devices,
+						   (uint32_t) d))) {
+		/* create new device */
+		if (loopfile) {
+			if (!(dev = dev_create_file(path, NULL, NULL, 0)))
+				return_0;
+		} else if (!(dev = _dev_create(d)))
+			return_0;
+
+		if (!(btree_insert(_cache.devices, (uint32_t) d, dev))) {
+			log_err("Couldn't insert device into binary tree.");
+			_free(dev);
+			return 0;
+		}
+	}
+
+	if (!loopfile && !_add_alias(dev, path)) {
+		log_err("Couldn't add alias to dev cache.");
+		return 0;
+	}
+
+	if (!dm_hash_insert(_cache.names, path, dev)) {
+		log_err("Couldn't add name to hash in dev cache.");
+		return 0;
+	}
+
+	return 1;
+}
+
+static char *_join(const char *dir, const char *name)
+{
+	size_t len = strlen(dir) + strlen(name) + 2;
+	char *r = dm_malloc(len);
+	if (r)
+		snprintf(r, len, "%s/%s", dir, name);
+
+	return r;
+}
+
+/*
+ * Get rid of extra slashes in the path string.
+ */
+static void _collapse_slashes(char *str)
+{
+	char *ptr;
+	int was_slash = 0;
+
+	for (ptr = str; *ptr; ptr++) {
+		if (*ptr == '/') {
+			if (was_slash)
+				continue;
+
+			was_slash = 1;
+		} else
+			was_slash = 0;
+		*str++ = *ptr;
+	}
+
+	*str = *ptr;
+}
+
+static int _insert_dir(const char *dir)
+{
+	int n, dirent_count, r = 1;
+	struct dirent **dirent;
+	char *path;
+
+	dirent_count = scandir(dir, &dirent, NULL, alphasort);
+	if (dirent_count > 0) {
+		for (n = 0; n < dirent_count; n++) {
+			if (dirent[n]->d_name[0] == '.') {
+				free(dirent[n]);
+				continue;
+			}
+
+			if (!(path = _join(dir, dirent[n]->d_name)))
+				return_0;
+
+			_collapse_slashes(path);
+			r &= _insert(path, 1);
+			dm_free(path);
+
+			free(dirent[n]);
+		}
+		free(dirent);
+	}
+
+	return r;
+}
+
+static int _insert_file(const char *path)
+{
+	struct stat info;
+
+	if (stat(path, &info) < 0) {
+		log_sys_very_verbose("stat", path);
+		return 0;
+	}
+
+	if (!S_ISREG(info.st_mode)) {
+		log_debug("%s: Not a regular file", path);
+		return 0;
+	}
+
+	if (!_insert_dev(path, 0))
+		return_0;
+
+	return 1;
+}
+
+static int _insert(const char *path, int rec)
+{
+	struct stat info;
+	int r = 0;
+
+	if (stat(path, &info) < 0) {
+		log_sys_very_verbose("stat", path);
+		return 0;
+	}
+
+	if (S_ISDIR(info.st_mode)) {	/* add a directory */
+		/* check it's not a symbolic link */
+		if (lstat(path, &info) < 0) {
+			log_sys_very_verbose("lstat", path);
+			return 0;
+		}
+
+		if (S_ISLNK(info.st_mode)) {
+			log_debug("%s: Symbolic link to directory", path);
+			return 0;
+		}
+
+		if (rec)
+			r = _insert_dir(path);
+
+	} else {
+		/* add a device */
+#ifdef __NetBSD__		
+		/*
+		 * In NetBSD we have two different types of devices
+		 * raw and block. I can insert only  existing
+		 * raw and block device.
+		 */
+		if (nbsd_check_dev(MAJOR(info.st_rdev),path) < 0) {
+			log_debug("%s: Not a block device.", path);
+			return_0;
+		}
+
+#else
+		if (!S_ISBLK(info.st_mode))
+			log_debug("%s: Not a block device", path);
+#endif
+		if (!_insert_dev(path, info.st_rdev)) {
+			return_0;
+		}
+
+		r = 1;
+	}
+
+	return r;
+}
+
+static void _full_scan(int dev_scan)
+{
+	struct dir_list *dl;
+
+	if (_cache.has_scanned && !dev_scan)
+		return;
+
+	dm_list_iterate_items(dl, &_cache.dirs)
+		_insert_dir(dl->dir);
+
+	dm_list_iterate_items(dl, &_cache.files)
+		_insert_file(dl->dir);
+
+	_cache.has_scanned = 1;
+	init_full_scan_done(1);
+}
+
+int dev_cache_has_scanned(void)
+{
+	return _cache.has_scanned;
+}
+
+void dev_cache_scan(int do_scan)
+{
+	if (!do_scan)
+		_cache.has_scanned = 1;
+	else
+		_full_scan(1);
+}
+
+static int _init_preferred_names(struct cmd_context *cmd)
+{
+	const struct config_node *cn;
+	struct config_value *v;
+	struct dm_pool *scratch = NULL;
+	char **regex;
+	unsigned count = 0;
+	int i, r = 0;
+
+	_cache.preferred_names_matcher = NULL;
+
+	if (!(cn = find_config_tree_node(cmd, "devices/preferred_names")) ||
+	    cn->v->type == CFG_EMPTY_ARRAY) {
+		log_very_verbose("devices/preferred_names not found in config file: "
+				 "using built-in preferences");
+		return 1;
+	}
+
+	for (v = cn->v; v; v = v->next) {
+		if (v->type != CFG_STRING) {
+			log_error("preferred_names patterns must be enclosed in quotes");
+			return 0;
+		}
+
+		count++;
+	}
+
+	if (!(scratch = dm_pool_create("preferred device name matcher", 1024)))
+		return_0;
+
+	if (!(regex = dm_pool_alloc(scratch, sizeof(*regex) * count))) {
+		log_error("Failed to allocate preferred device name "
+			  "pattern list.");
+		goto out;
+	}
+
+	for (v = cn->v, i = count - 1; v; v = v->next, i--) {
+		if (!(regex[i] = dm_pool_strdup(scratch, v->v.str))) {
+			log_error("Failed to allocate a preferred device name "
+				  "pattern.");
+			goto out;
+		}
+	}
+
+	if (!(_cache.preferred_names_matcher =
+		dm_regex_create(_cache.mem,(const char **) regex, count))) {
+		log_error("Preferred device name pattern matcher creation failed.");
+		goto out;
+	}
+
+	r = 1;
+
+out:
+	dm_pool_destroy(scratch);
+
+	return r;
+}
+
+int dev_cache_init(struct cmd_context *cmd)
+{
+	_cache.names = NULL;
+	_cache.has_scanned = 0;
+
+	if (!(_cache.mem = dm_pool_create("dev_cache", 10 * 1024)))
+		return_0;
+
+	if (!(_cache.names = dm_hash_create(128))) {
+		dm_pool_destroy(_cache.mem);
+		_cache.mem = 0;
+		return_0;
+	}
+
+	if (!(_cache.devices = btree_create(_cache.mem))) {
+		log_err("Couldn't create binary tree for dev-cache.");
+		goto bad;
+	}
+
+	dm_list_init(&_cache.dirs);
+	dm_list_init(&_cache.files);
+
+	if (!_init_preferred_names(cmd))
+		goto_bad;
+
+	return 1;
+
+      bad:
+	dev_cache_exit();
+	return 0;
+}
+
+static void _check_closed(struct device *dev)
+{
+	if (dev->fd >= 0)
+		log_err("Device '%s' has been left open.", dev_name(dev));
+}
+
+static void _check_for_open_devices(void)
+{
+	dm_hash_iter(_cache.names, (dm_hash_iterate_fn) _check_closed);
+}
+
+void dev_cache_exit(void)
+{
+	if (_cache.names)
+		_check_for_open_devices();
+
+	if (_cache.preferred_names_matcher)
+		_cache.preferred_names_matcher = NULL;
+
+	if (_cache.mem) {
+		dm_pool_destroy(_cache.mem);
+		_cache.mem = NULL;
+	}
+
+	if (_cache.names) {
+		dm_hash_destroy(_cache.names);
+		_cache.names = NULL;
+	}
+
+	_cache.devices = NULL;
+	_cache.has_scanned = 0;
+	dm_list_init(&_cache.dirs);
+	dm_list_init(&_cache.files);
+}
+
+int dev_cache_add_dir(const char *path)
+{
+	struct dir_list *dl;
+	struct stat st;
+
+	if (stat(path, &st)) {
+		log_error("Ignoring %s: %s", path, strerror(errno));
+		/* But don't fail */
+		return 1;
+	}
+
+	if (!S_ISDIR(st.st_mode)) {
+		log_error("Ignoring %s: Not a directory", path);
+		return 1;
+	}
+
+	if (!(dl = _alloc(sizeof(*dl) + strlen(path) + 1))) {
+		log_error("dir_list allocation failed");
+		return 0;
+	}
+
+	strcpy(dl->dir, path);
+	dm_list_add(&_cache.dirs, &dl->list);
+	return 1;
+}
+
+int dev_cache_add_loopfile(const char *path)
+{
+	struct dir_list *dl;
+	struct stat st;
+
+	if (stat(path, &st)) {
+		log_error("Ignoring %s: %s", path, strerror(errno));
+		/* But don't fail */
+		return 1;
+	}
+
+	if (!S_ISREG(st.st_mode)) {
+		log_error("Ignoring %s: Not a regular file", path);
+		return 1;
+	}
+
+	if (!(dl = _alloc(sizeof(*dl) + strlen(path) + 1))) {
+		log_error("dir_list allocation failed for file");
+		return 0;
+	}
+
+	strcpy(dl->dir, path);
+	dm_list_add(&_cache.files, &dl->list);
+	return 1;
+}
+
+/* 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, int quiet)
+{
+	struct stat buf;
+	const char *name;
+	int r;
+
+	if ((dev->flags & DEV_REGULAR))
+		return dev_name(dev);
+
+	while ((r = stat(name = dm_list_item(dev->aliases.n,
+					  struct str_list)->str, &buf)) ||
+	       (buf.st_rdev != 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 */
+		dm_hash_remove(_cache.names, name);
+
+		/* Leave list alone if there isn't an alternative name */
+		/* so dev_name will always find something to return. */
+		/* Otherwise add the name to the correct device. */
+		if (dm_list_size(&dev->aliases) > 1) {
+			dm_list_del(dev->aliases.n);
+			if (!r)
+				_insert(name, 0);
+			continue;
+		}
+
+		/* Scanning issues this inappropriately sometimes. */
+		log_debug("Aborting - please provide new pathname for what "
+			  "used to be %s", name);
+		return NULL;
+	}
+
+	return dev_name(dev);
+}
+
+struct device *dev_cache_get(const char *name, struct dev_filter *f)
+{
+	struct stat buf;
+	struct device *d = (struct device *) dm_hash_lookup(_cache.names, name);
+
+	if (d && (d->flags & DEV_REGULAR))
+		return d;
+
+	/* If the entry's wrong, remove it */
+	if (d && (stat(name, &buf) || (buf.st_rdev != d->dev))) {
+		dm_hash_remove(_cache.names, name);
+		d = NULL;
+	}
+
+	if (!d) {
+		_insert(name, 0);
+		d = (struct device *) dm_hash_lookup(_cache.names, name);
+		if (!d) {
+			_full_scan(0);
+			d = (struct device *) dm_hash_lookup(_cache.names, name);
+		}
+	}
+
+	return (d && (!f || (d->flags & DEV_REGULAR) ||
+		      f->passes_filter(f, d))) ? d : NULL;
+}
+
+struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan)
+{
+	struct dev_iter *di = dm_malloc(sizeof(*di));
+
+	if (!di) {
+		log_error("dev_iter allocation failed");
+		return NULL;
+	}
+
+	if (dev_scan && !trust_cache()) {
+		/* Flag gets reset between each command */
+		if (!full_scan_done())
+			persistent_filter_wipe(f); /* Calls _full_scan(1) */
+	} else
+		_full_scan(0);
+
+	di->current = btree_first(_cache.devices);
+	di->filter = f;
+
+	return di;
+}
+
+void dev_iter_destroy(struct dev_iter *iter)
+{
+	dm_free(iter);
+}
+
+static struct device *_iter_next(struct dev_iter *iter)
+{
+	struct device *d = btree_get_data(iter->current);
+	iter->current = btree_next(iter->current);
+	return d;
+}
+
+struct device *dev_iter_get(struct dev_iter *iter)
+{
+	while (iter->current) {
+		struct device *d = _iter_next(iter);
+		if (!iter->filter || (d->flags & DEV_REGULAR) ||
+		    iter->filter->passes_filter(iter->filter, d))
+			return d;
+	}
+
+	return NULL;
+}
+
+int dev_fd(struct device *dev)
+{
+	return dev->fd;
+}
+
+const char *dev_name(const struct device *dev)
+{
+	return (dev) ? dm_list_item(dev->aliases.n, struct str_list)->str :
+	    "unknown device";
+}
Index: src/external/gpl2/lvm2tools/dist/lib/device/dev-cache.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/device/dev-cache.h
diff -N src/external/gpl2/lvm2tools/dist/lib/device/dev-cache.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/device/dev-cache.h	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,57 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_DEV_CACHE_H
+#define _LVM_DEV_CACHE_H
+
+#include "device.h"
+
+/*
+ * predicate for devices.
+ */
+struct dev_filter {
+	int (*passes_filter) (struct dev_filter * f, struct device * dev);
+	void (*destroy) (struct dev_filter * f);
+	void *private;
+};
+
+/*
+ * The global device cache.
+ */
+struct cmd_context;
+int dev_cache_init(struct cmd_context *cmd);
+void dev_cache_exit(void);
+
+/* Trigger(1) or avoid(0) a scan */
+void dev_cache_scan(int do_scan);
+int dev_cache_has_scanned(void);
+
+int dev_cache_add_dir(const char *path);
+int dev_cache_add_loopfile(const char *path);
+struct device *dev_cache_get(const char *name, struct dev_filter *f);
+
+void dev_set_preferred_name(struct str_list *sl, struct device *dev);
+
+/*
+ * Object for iterating through the cache.
+ */
+struct dev_iter;
+struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan);
+void dev_iter_destroy(struct dev_iter *iter);
+struct device *dev_iter_get(struct dev_iter *iter);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/device/dev-io.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/device/dev-io.c
diff -N src/external/gpl2/lvm2tools/dist/lib/device/dev-io.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/device/dev-io.c	12 Dec 2008 16:32:59 -0000	1.1.1.1.2.2
@@ -0,0 +1,707 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "lvm-types.h"
+#include "device.h"
+#include "metadata.h"
+#include "lvmcache.h"
+#include "memlock.h"
+#include "locking.h"
+
+#include <limits.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+
+#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
+#  ifndef BLKGETSIZE64		/* fs.h out-of-date */
+#    define BLKGETSIZE64 _IOR(0x12, 114, size_t)
+#  endif /* BLKGETSIZE64 */
+#elif __NetBSD__
+#  include <sys/disk.h>
+#  include <sys/disklabel.h>
+#  include <sys/param.h>
+#else
+#  include <sys/disk.h>
+#  define BLKBSZGET DKIOCGETBLOCKSIZE
+#  define BLKSSZGET DKIOCGETBLOCKSIZE
+#  define BLKGETSIZE64 DKIOCGETBLOCKCOUNT
+#  define BLKFLSBUF DKIOCSYNCHRONIZECACHE
+#  define BLKSIZE_SHIFT 0
+#endif
+
+#ifdef O_DIRECT_SUPPORT
+#  ifndef O_DIRECT
+#    error O_DIRECT support configured but O_DIRECT definition not found in headers
+#  endif
+#endif
+
+static DM_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_error("%s: lseek %" PRIu64 " failed: %s",
+			  dev_name(where->dev), (uint64_t) where->start,
+			  strerror(errno));
+		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)
+			log_error("%s: %s failed after %" PRIu64 " of %" PRIu64
+				  " at %" PRIu64 ": %s", dev_name(where->dev),
+				  should_write ? "write" : "read",
+				  (uint64_t) total,
+				  (uint64_t) where->size,
+				  (uint64_t) where->start, strerror(errno));
+
+		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)
+{
+	const char *name = dev_name(dev);
+#ifdef __NetBSD__
+	struct disklabel	lab;
+#endif
+
+	if ((dev->block_size == -1)) {
+#ifdef __NetBSD__
+		if (ioctl(dev_fd(dev), DIOCGDINFO, &lab) < 0) {
+			dev->block_size = DEV_BSIZE;
+		} else
+			dev->block_size = lab.d_secsize;
+#else
+		if (ioctl(dev_fd(dev), BLKBSZGET, &dev->block_size) < 0) {
+			log_sys_error("ioctl BLKBSZGET", name);
+			return 0;
+		}
+#endif
+		log_debug("%s: block size is %u bytes", name, dev->block_size);
+	}
+
+	*size = (unsigned int) dev->block_size;
+
+	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))
+		return_0;
+
+	if (!block_size)
+		block_size = lvm_getpagesize();
+
+	_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)
+			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;
+}
+
+static int _dev_get_size_file(const struct device *dev, uint64_t *size)
+{
+	const char *name = dev_name(dev);
+	struct stat info;
+
+	if (stat(name, &info)) {
+		log_sys_error("stat", name);
+		return 0;
+	}
+
+	*size = info.st_size;
+	*size >>= SECTOR_SHIFT;	/* Convert to sectors */
+
+	log_very_verbose("%s: size is %" PRIu64 " sectors", name, *size);
+
+	return 1;
+}
+
+static int _dev_get_size_dev(const struct device *dev, uint64_t *size)
+{
+	int fd;
+	const char *name = dev_name(dev);
+#ifdef __NetBSD__
+	struct disklabel	lab;
+	struct dkwedge_info     dkw;
+#endif
+
+	if ((fd = open(name, O_RDONLY)) < 0) {
+		log_sys_error("open", name);
+		return 0;
+		}
+
+#ifdef __NetBSD__
+	if ((*size = lseek (fd, 0, SEEK_END)) < 0) {
+		log_sys_error("lseek SEEK_END", name);
+		close(fd);
+		return 0;
+	}
+
+	if (ioctl(fd, DIOCGDINFO, &lab) < 0) {
+		if (ioctl(fd, DIOCGWEDGEINFO, &dkw) < 0) {
+			log_sys_error("ioctl DIOCGWEDGEINFO", name);
+			close(fd);
+			return 0;
+		} else
+			if (dkw.dkw_size)
+				*size = dkw.dkw_size;
+	} else 
+		if (lab.d_secsize)
+			*size /= lab.d_secsize;
+#else
+	if (ioctl(fd, BLKGETSIZE64, size) < 0) {
+		log_sys_error("ioctl BLKGETSIZE64", name);
+		if (close(fd))
+			log_sys_error("close", name);
+		return 0;
+	}
+
+	*size >>= BLKSIZE_SHIFT;	/* Convert to sectors */
+#endif
+	if (close(fd))
+		log_sys_error("close", name);
+
+	log_very_verbose("%s: size is %" PRIu64 " sectors", name, *size);
+
+	return 1;
+}
+
+/*-----------------------------------------------------------------
+ * Public functions
+ *---------------------------------------------------------------*/
+
+int dev_get_size(const struct device *dev, uint64_t *size)
+{
+	if ((dev->flags & DEV_REGULAR))
+		return _dev_get_size_file(dev, size);
+	else
+		return _dev_get_size_dev(dev, size);
+}
+
+/* FIXME Unused
+int dev_get_sectsize(struct device *dev, uint32_t *size)
+{
+	int fd;
+	int s;
+	const char *name = dev_name(dev);
+
+	if ((fd = open(name, O_RDONLY)) < 0) {
+		log_sys_error("open", name);
+		return 0;
+	}
+
+	if (ioctl(fd, BLKSSZGET, &s) < 0) {
+		log_sys_error("ioctl BLKSSZGET", name);
+		if (close(fd))
+			log_sys_error("close", name);
+		return 0;
+	}
+
+	if (close(fd))
+		log_sys_error("close", name);
+
+	*size = (uint32_t) s;
+
+	log_very_verbose("%s: sector size is %" PRIu32 " bytes", name, *size);
+
+	return 1;
+}
+*/
+
+void dev_flush(struct device *dev)
+{
+#ifdef __linux__
+	if (!(dev->flags & DEV_REGULAR) && ioctl(dev->fd, BLKFLSBUF, 0) >= 0)
+		return;
+#endif
+
+	if (fsync(dev->fd) >= 0)
+		return;
+
+	sync();
+}
+
+int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
+{
+	struct stat buf;
+	const char *name;
+	int need_excl = 0, need_rw = 0;
+
+	if ((flags & O_ACCMODE) == O_RDWR)
+		need_rw = 1;
+
+	if ((flags & O_EXCL))
+		need_excl = 1;
+
+	if (dev->fd >= 0) {
+		if (((dev->flags & DEV_OPENED_RW) || !need_rw) &&
+		    ((dev->flags & DEV_OPENED_EXCL) || !need_excl)) {
+			dev->open_count++;
+			return 1;
+		}
+
+		if (dev->open_count && !need_excl) {
+			/* FIXME Ensure we never get here */
+			log_debug("WARNING: %s already opened read-only",
+				  dev_name(dev));
+			dev->open_count++;
+		}
+
+		dev_close_immediate(dev);
+	}
+
+	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)))
+		return_0;
+
+	if (!(dev->flags & DEV_REGULAR)) {
+		if (stat(name, &buf) < 0) {
+			log_sys_error("%s: stat failed", name);
+			return 0;
+		}
+		if (buf.st_rdev != dev->dev) {
+			log_error("%s: device changed", name);
+			return 0;
+		}
+	}
+
+#ifdef O_DIRECT_SUPPORT
+	if (direct) {
+		if (!(dev->flags & DEV_O_DIRECT_TESTED))
+			dev->flags |= DEV_O_DIRECT;
+
+		if ((dev->flags & DEV_O_DIRECT))
+			flags |= O_DIRECT;
+	}
+#endif
+
+#ifdef O_NOATIME
+	/* Don't update atime on device inodes */
+	if (!(dev->flags & DEV_REGULAR))
+		flags |= O_NOATIME;
+#endif
+
+	if ((dev->fd = open(name, flags, 0777)) < 0) {
+#ifdef O_DIRECT_SUPPORT
+		if (direct && !(dev->flags & DEV_O_DIRECT_TESTED)) {
+			flags &= ~O_DIRECT;
+			if ((dev->fd = open(name, flags, 0777)) >= 0) {
+				dev->flags &= ~DEV_O_DIRECT;
+				log_debug("%s: Not using O_DIRECT", name);
+				goto opened;
+			}
+		}
+#endif
+		if (quiet)
+			log_sys_debug("open", name);
+		else
+			log_sys_error("open", name);
+		return 0;
+	}
+
+#ifdef O_DIRECT_SUPPORT
+      opened:
+	if (direct)
+		dev->flags |= DEV_O_DIRECT_TESTED;
+#endif
+	dev->open_count++;
+	dev->flags &= ~DEV_ACCESSED_W;
+
+	if (need_rw)
+		dev->flags |= DEV_OPENED_RW;
+	else
+		dev->flags &= ~DEV_OPENED_RW;
+
+	if (need_excl)
+		dev->flags |= DEV_OPENED_EXCL;
+	else
+		dev->flags &= ~DEV_OPENED_EXCL;
+
+	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_immediate(dev);
+		return 0;
+	}
+
+#ifndef O_DIRECT_SUPPORT
+	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);
+
+	dm_list_add(&_open_devices, &dev->open_list);
+
+	log_debug("Opened %s %s%s%s", dev_name(dev),
+		  dev->flags & DEV_OPENED_RW ? "RW" : "RO",
+		  dev->flags & DEV_OPENED_EXCL ? " O_EXCL" : "",
+		  dev->flags & DEV_O_DIRECT ? " O_DIRECT" : "");
+
+	return 1;
+}
+
+int dev_open_quiet(struct device *dev)
+{
+	int flags;
+
+	flags = vg_write_lock_held() ? O_RDWR : O_RDONLY;
+
+	return dev_open_flags(dev, flags, 1, 1);
+}
+
+int dev_open(struct device *dev)
+{
+	int flags;
+
+	flags = vg_write_lock_held() ? O_RDWR : O_RDONLY;
+
+	return dev_open_flags(dev, flags, 1, 0);
+}
+
+int dev_test_excl(struct device *dev)
+{
+	int flags;
+	int r;
+
+	flags = vg_write_lock_held() ? O_RDWR : O_RDONLY;
+	flags |= O_EXCL;
+
+	r = dev_open_flags(dev, flags, 1, 1);
+	if (r)
+		dev_close_immediate(dev);
+
+	return r;
+}
+
+static void _close(struct device *dev)
+{
+	if (close(dev->fd))
+		log_sys_error("close", dev_name(dev));
+	dev->fd = -1;
+	dev->block_size = -1;
+	dm_list_del(&dev->open_list);
+
+	log_debug("Closed %s", dev_name(dev));
+
+	if (dev->flags & DEV_ALLOCED) {
+		dm_free((void *) dm_list_item(dev->aliases.n, struct str_list)->
+			 str);
+		dm_free(dev->aliases.n);
+		dm_free(dev);
+	}
+}
+
+static int _dev_close(struct device *dev, int immediate)
+{
+	struct lvmcache_info *info;
+
+	if (dev->fd < 0) {
+		log_error("Attempt to close device '%s' "
+			  "which is not open.", dev_name(dev));
+		return 0;
+	}
+
+#ifndef O_DIRECT_SUPPORT
+	if (dev->flags & DEV_ACCESSED_W)
+		dev_flush(dev);
+#endif
+
+	if (dev->open_count > 0)
+		dev->open_count--;
+
+	if (immediate && dev->open_count)
+		log_debug("%s: Immediate close attempt while still referenced",
+			  dev_name(dev));
+
+	/* Close unless device is known to belong to a locked VG */
+	if (immediate ||
+	    (dev->open_count < 1 &&
+	     (!(info = info_from_pvid(dev->pvid, 0)) ||
+	      !info->vginfo ||
+	      !vgname_is_locked(info->vginfo->vgname))))
+		_close(dev);
+
+	return 1;
+}
+
+int dev_close(struct device *dev)
+{
+	return _dev_close(dev, 0);
+}
+
+int dev_close_immediate(struct device *dev)
+{
+	return _dev_close(dev, 1);
+}
+
+void dev_close_all(void)
+{
+	struct dm_list *doh, *doht;
+	struct device *dev;
+
+	dm_list_iterate_safe(doh, doht, &_open_devices) {
+		dev = dm_list_struct_base(doh, struct device, open_list);
+		if (dev->open_count < 1)
+			_close(dev);
+	}
+}
+
+int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
+{
+	struct device_area where;
+
+	if (!dev->open_count)
+		return_0;
+
+	where.dev = dev;
+	where.start = offset;
+	where.size = len;
+
+	return _aligned_io(&where, buffer, 0);
+}
+
+/*
+ * Read from 'dev' into 'buf', possibly in 2 distinct regions, denoted
+ * by (offset,len) and (offset2,len2).  Thus, the total size of
+ * 'buf' should be len+len2.
+ */
+int dev_read_circular(struct device *dev, uint64_t offset, size_t len,
+		      uint64_t offset2, size_t len2, void *buf)
+{
+	if (!dev_read(dev, offset, len, buf)) {
+		log_error("Read from %s failed", dev_name(dev));
+		return 0;
+	}
+
+	/*
+	 * The second region is optional, and allows for
+	 * a circular buffer on the device.
+	 */
+	if (!len2)
+		return 1;
+
+	if (!dev_read(dev, offset2, len2, buf + len)) {
+		log_error("Circular read from %s failed",
+			  dev_name(dev));
+		return 0;
+	}
+
+	return 1;
+}
+
+/* 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)
+{
+	int r;
+
+	if (!dev->open_count)
+		return_0;
+
+	r = dev_write(dev, dev->end, len, buffer);
+	dev->end += (uint64_t) len;
+
+#ifndef O_DIRECT_SUPPORT
+	dev_flush(dev);
+#endif
+	return r;
+}
+
+int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer)
+{
+	struct device_area where;
+
+	if (!dev->open_count)
+		return_0;
+
+	where.dev = dev;
+	where.start = offset;
+	where.size = len;
+
+	dev->flags |= DEV_ACCESSED_W;
+
+	return _aligned_io(&where, buffer, 1);
+}
+
+int dev_set(struct device *dev, uint64_t offset, size_t len, int value)
+{
+	size_t s;
+	char buffer[4096] __attribute((aligned(8)));
+
+	if (!dev_open(dev))
+		return_0;
+
+	if ((offset % SECTOR_SIZE) || (len % SECTOR_SIZE))
+		log_debug("Wiping %s at %" PRIu64 " length %" PRIsize_t,
+			  dev_name(dev), offset, len);
+	else
+		log_debug("Wiping %s at sector %" PRIu64 " length %" PRIsize_t
+			  " sectors", dev_name(dev), offset >> SECTOR_SHIFT,
+			  len >> SECTOR_SHIFT);
+
+	memset(buffer, value, sizeof(buffer));
+	while (1) {
+		s = len > sizeof(buffer) ? sizeof(buffer) : len;
+		if (!dev_write(dev, offset, s, buffer))
+			break;
+
+		len -= s;
+		if (!len)
+			break;
+
+		offset += s;
+	}
+
+	dev->flags |= DEV_ACCESSED_W;
+
+	if (!dev_close(dev))
+		stack;
+
+	return (len == 0);
+}
Index: src/external/gpl2/lvm2tools/dist/lib/device/dev-md.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/device/dev-md.c
diff -N src/external/gpl2/lvm2tools/dist/lib/device/dev-md.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/device/dev-md.c	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,200 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2004 Luca Berra
+ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "metadata.h"
+#include "xlate.h"
+#include "filter.h"
+
+#ifdef linux
+
+/* Lifted from <linux/raid/md_p.h> because of difficulty including it */
+
+#define MD_SB_MAGIC 0xa92b4efc
+#define MD_RESERVED_BYTES (64 * 1024ULL)
+#define MD_RESERVED_SECTORS (MD_RESERVED_BYTES / 512)
+#define MD_NEW_SIZE_SECTORS(x) ((x & ~(MD_RESERVED_SECTORS - 1)) \
+				- MD_RESERVED_SECTORS)
+
+static int _dev_has_md_magic(struct device *dev, uint64_t sb_offset)
+{
+	uint32_t md_magic;
+
+	/* Version 1 is little endian; version 0.90.0 is machine endian */
+	if (dev_read(dev, sb_offset, sizeof(uint32_t), &md_magic) &&
+	    ((md_magic == xlate32(MD_SB_MAGIC)) ||
+	     (md_magic == MD_SB_MAGIC)))
+		return 1;
+
+	return 0;
+}
+
+/*
+ * Calculate the position of the superblock.
+ * It is always aligned to a 4K boundary and
+ * depending on minor_version, it can be:
+ * 0: At least 8K, but less than 12K, from end of device
+ * 1: At start of device
+ * 2: 4K from start of device.
+ */
+typedef enum {
+	MD_MINOR_VERSION_MIN,
+	MD_MINOR_V0 = MD_MINOR_VERSION_MIN,
+	MD_MINOR_V1,
+	MD_MINOR_V2,
+	MD_MINOR_VERSION_MAX = MD_MINOR_V2
+} md_minor_version_t;
+
+static uint64_t _v1_sb_offset(uint64_t size, md_minor_version_t minor_version)
+{
+	uint64_t uninitialized_var(sb_offset);
+
+	switch(minor_version) {
+	case MD_MINOR_V0:
+		sb_offset = (size - 8 * 2) & ~(4 * 2 - 1ULL);
+		break;
+	case MD_MINOR_V1:
+		sb_offset = 0;
+		break;
+	case MD_MINOR_V2:
+		sb_offset = 4 * 2;
+		break;
+	}
+	sb_offset <<= SECTOR_SHIFT;
+
+	return sb_offset;
+}
+
+/*
+ * Returns -1 on error
+ */
+int dev_is_md(struct device *dev, uint64_t *sb)
+{
+	int ret = 1;
+	md_minor_version_t minor;
+	uint64_t size, sb_offset;
+
+	if (!dev_get_size(dev, &size)) {
+		stack;
+		return -1;
+	}
+
+	if (size < MD_RESERVED_SECTORS * 2)
+		return 0;
+
+	if (!dev_open(dev)) {
+		stack;
+		return -1;
+	}
+
+	/* Check if it is an md component device. */
+	/* Version 0.90.0 */
+	sb_offset = MD_NEW_SIZE_SECTORS(size) << SECTOR_SHIFT;
+	if (_dev_has_md_magic(dev, sb_offset))
+		goto out;
+
+	minor = MD_MINOR_VERSION_MIN;
+	/* Version 1, try v1.0 -> v1.2 */
+	do {
+		sb_offset = _v1_sb_offset(size, minor);
+		if (_dev_has_md_magic(dev, sb_offset))
+			goto out;
+	} while (++minor <= MD_MINOR_VERSION_MAX);
+
+	ret = 0;
+
+out:
+	if (!dev_close(dev))
+		stack;
+
+	if (ret && sb)
+		*sb = sb_offset;
+
+	return ret;
+}
+
+/*
+ * Retrieve chunk size from md device using sysfs.
+ */
+unsigned long dev_md_chunk_size(const char *sysfs_dir, struct device *dev)
+{
+	char path[PATH_MAX+1], buffer[64];
+	FILE *fp;
+	struct stat info;
+	unsigned long chunk_size_bytes = 0UL;
+
+	if (MAJOR(dev->dev) != md_major())
+		return 0;
+
+	if (!sysfs_dir || !*sysfs_dir)
+		return_0;
+
+	if (dm_snprintf(path, PATH_MAX, "%s/dev/block/%d:%d/md/chunk_size",
+	    sysfs_dir, MAJOR(dev->dev), MINOR(dev->dev)) < 0) {
+		log_error("dm_snprintf md chunk_size failed");
+		return 0;
+	}
+
+	/* old sysfs structure */
+	if (stat(path, &info) &&
+	    dm_snprintf(path, PATH_MAX, "%s/block/md%d/md/chunk_size",
+			sysfs_dir, MINOR(dev->dev)) < 0) {
+		log_error("dm_snprintf old md chunk size failed");
+		return 0;
+	}
+
+	if (!(fp = fopen(path, "r"))) {
+		log_sys_error("fopen", path);
+		return 0;
+	}
+
+	if (!fgets(buffer, sizeof(buffer), fp)) {
+		log_sys_error("fgets", path);
+		goto out;
+	}
+
+	if (sscanf(buffer, "%lu", &chunk_size_bytes) != 1) {
+		log_error("sysfs file %s not in expected format: %s", path,
+			  buffer);
+		goto out;
+	}
+
+	log_very_verbose("Device %s md chunk size is %lu bytes.",
+			 dev_name(dev), chunk_size_bytes);
+
+out:
+	if (fclose(fp))
+		log_sys_error("fclose", path);
+
+	return chunk_size_bytes >> SECTOR_SHIFT;
+}
+
+#else
+
+int dev_is_md(struct device *dev __attribute((unused)),
+	      uint64_t *sb __attribute((unused)))
+{
+	return 0;
+}
+
+unsigned long dev_md_chunk_size(const char *sysfs_dir __attribute((unused)),
+				struct device *dev  __attribute((unused)))
+{
+	return 0UL;
+}
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/device/device.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/device/device.c
diff -N src/external/gpl2/lvm2tools/dist/lib/device/device.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/device/device.c	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,282 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "lvm-types.h"
+#include "device.h"
+#include "metadata.h"
+#include "filter.h"
+#include "xlate.h"
+
+/* See linux/genhd.h and fs/partitions/msdos */
+
+#define PART_MAGIC 0xAA55
+#define PART_MAGIC_OFFSET UINT64_C(0x1FE)
+#define PART_OFFSET UINT64_C(0x1BE)
+
+struct partition {
+	uint8_t boot_ind;
+	uint8_t head;
+	uint8_t sector;
+	uint8_t cyl;
+	uint8_t sys_ind;	/* partition type */
+	uint8_t end_head;
+	uint8_t end_sector;
+	uint8_t end_cyl;
+	uint32_t start_sect;
+	uint32_t nr_sects;
+} __attribute__((packed));
+
+static int _is_partitionable(struct device *dev)
+{
+	int parts = max_partitions(MAJOR(dev->dev));
+
+	if ((parts <= 1) || (MINOR(dev->dev) % parts))
+		return 0;
+
+	return 1;
+}
+
+static int _has_partition_table(struct device *dev)
+{
+	int ret = 0;
+	unsigned p;
+	uint16_t buf[SECTOR_SIZE/sizeof(uint16_t)];
+	uint16_t *part_magic;
+	struct partition *part;
+
+	if (!dev_open(dev)) {
+		stack;
+		return -1;
+	}
+
+	if (!dev_read(dev, UINT64_C(0), sizeof(buf), &buf))
+		goto_out;
+
+	/* FIXME Check for other types of partition table too */
+
+	/* Check for msdos partition table */
+	part_magic = buf + PART_MAGIC_OFFSET/sizeof(buf[0]);
+	if ((*part_magic == xlate16(PART_MAGIC))) {
+		part = (struct partition *) (buf + PART_OFFSET/sizeof(buf[0]));
+		for (p = 0; p < 4; p++, part++) {
+			/* Table is invalid if boot indicator not 0 or 0x80 */
+			if ((part->boot_ind & 0x7f)) {
+				ret = 0;
+				break;
+			}
+			/* Must have at least one non-empty partition */
+			if (part->nr_sects)
+				ret = 1;
+		}
+	}
+
+      out:
+	if (!dev_close(dev))
+		stack;
+
+	return ret;
+}
+
+int is_partitioned_dev(struct device *dev)
+{
+	if (!_is_partitionable(dev))
+		return 0;
+
+	return _has_partition_table(dev);
+}
+
+#if 0
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <linux/fs.h>
+#include <linux/major.h>
+#include <linux/genhd.h>
+
+int _get_partition_type(struct dev_filter *filter, struct device *d);
+
+#define MINOR_PART(dev) (MINOR((dev)->dev) % max_partitions(MINOR((dev)->dev)))
+
+int is_extended_partition(struct device *d)
+{
+	return (MINOR_PART(d) > 4) ? 1 : 0;
+}
+
+struct device *dev_primary(struct dev_mgr *dm, struct device *d)
+{
+	struct device *ret;
+
+	ret = dev_by_dev(dm, d->dev - MINOR_PART(dm, d));
+	/* FIXME: Needs replacing with a 'refresh' */
+	if (!ret) {
+		init_dev_scan(dm);
+		ret = dev_by_dev(dm, d->dev - MINOR_PART(dm, d));
+	}
+
+	return ret;
+
+}
+
+int partition_type_is_lvm(struct dev_mgr *dm, struct device *d)
+{
+	int pt;
+
+	pt = _get_partition_type(dm, d);
+
+	if (!pt) {
+		if (is_whole_disk(dm, d))
+			/* FIXME: Overloaded pt=0 in error cases */
+			return 1;
+		else {
+			log_error
+			    ("%s: missing partition table "
+			     "on partitioned device", d->name);
+			return 0;
+		}
+	}
+
+	if (is_whole_disk(dm, d)) {
+		log_error("%s: looks to possess partition table", d->name);
+		return 0;
+	}
+
+	/* check part type */
+	if (pt != LVM_PARTITION && pt != LVM_NEW_PARTITION) {
+		log_error("%s: invalid partition type 0x%x "
+			  "(must be 0x%x)", d->name, pt, LVM_NEW_PARTITION);
+		return 0;
+	}
+
+	if (pt == LVM_PARTITION) {
+		log_error
+		    ("%s: old LVM partition type found - please change to 0x%x",
+		     d->name, LVM_NEW_PARTITION);
+		return 0;
+	}
+
+	return 1;
+}
+
+int _get_partition_type(struct dev_mgr *dm, struct device *d)
+{
+	int pv_handle = -1;
+	struct device *primary;
+	ssize_t read_ret;
+	ssize_t bytes_read = 0;
+	char *buffer;
+	unsigned short *s_buffer;
+	struct partition *part;
+	loff_t offset = 0;
+	loff_t extended_offset = 0;
+	int part_sought;
+	int part_found = 0;
+	int first_partition = 1;
+	int extended_partition = 0;
+	int p;
+
+	if (!(primary = dev_primary(dm, d))) {
+		log_error
+		    ("Failed to find main device containing partition %s",
+		     d->name);
+		return 0;
+	}
+
+	if (!(buffer = dm_malloc(SECTOR_SIZE))) {
+		log_error("Failed to allocate partition table buffer");
+		return 0;
+	}
+
+	/* Get partition table */
+	if ((pv_handle = open(primary->name, O_RDONLY)) < 0) {
+		log_error("%s: open failed: %s", primary->name,
+			  strerror(errno));
+		return 0;
+	}
+
+	s_buffer = (unsigned short *) buffer;
+	part = (struct partition *) (buffer + 0x1be);
+	part_sought = MINOR_PART(dm, d);
+
+	do {
+		bytes_read = 0;
+
+		if (llseek(pv_handle, offset * SECTOR_SIZE, SEEK_SET) == -1) {
+			log_error("%s: llseek failed: %s",
+				  primary->name, strerror(errno));
+			return 0;
+		}
+
+		while ((bytes_read < SECTOR_SIZE) &&
+		       (read_ret =
+			read(pv_handle, buffer + bytes_read,
+			     SECTOR_SIZE - bytes_read)) != -1)
+			bytes_read += read_ret;
+
+		if (read_ret == -1) {
+			log_error("%s: read failed: %s", primary->name,
+				  strerror(errno));
+			return 0;
+		}
+
+		if (s_buffer[255] == 0xAA55) {
+			if (is_whole_disk(dm, d))
+				return -1;
+		} else
+			return 0;
+
+		extended_partition = 0;
+
+		/* Loop through primary partitions */
+		for (p = 0; p < 4; p++) {
+			if (part[p].sys_ind == DOS_EXTENDED_PARTITION ||
+			    part[p].sys_ind == LINUX_EXTENDED_PARTITION
+			    || part[p].sys_ind == WIN98_EXTENDED_PARTITION) {
+				extended_partition = 1;
+				offset = extended_offset + part[p].start_sect;
+				if (extended_offset == 0)
+					extended_offset = part[p].start_sect;
+				if (first_partition == 1)
+					part_found++;
+			} else if (first_partition == 1) {
+				if (p == part_sought) {
+					if (part[p].sys_ind == 0) {
+						/* missing primary? */
+						return 0;
+					}
+				} else
+					part_found++;
+			} else if (!part[p].sys_ind)
+				part_found++;
+
+			if (part_sought == part_found)
+				return part[p].sys_ind;
+
+		}
+		first_partition = 0;
+	}
+	while (extended_partition == 1);
+
+	return 0;
+}
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/device/device.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/device/device.h
diff -N src/external/gpl2/lvm2tools/dist/lib/device/device.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/device/device.h	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,102 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_DEVICE_H
+#define _LVM_DEVICE_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	/* dm_malloc used */
+#define DEV_OPENED_RW		0x00000008	/* Opened RW */
+#define DEV_OPENED_EXCL		0x00000010	/* Opened EXCL */
+#define DEV_O_DIRECT		0x00000020	/* Use O_DIRECT */
+#define DEV_O_DIRECT_TESTED	0x00000040	/* DEV_O_DIRECT is reliable */
+
+/*
+ * All devices in LVM will be represented by one of these.
+ * pointer comparisons are valid.
+ */
+struct device {
+	struct dm_list aliases;	/* struct str_list from lvm-types.h */
+	dev_t dev;
+
+	/* private */
+	int fd;
+	int open_count;
+	int block_size;
+	uint32_t flags;
+	uint64_t end;
+	struct dm_list open_list;
+
+	char pvid[ID_LEN + 1];
+	char _padding[7];
+};
+
+struct device_list {
+	struct dm_list list;
+	struct device *dev;
+};
+
+struct device_area {
+	struct device *dev;
+	uint64_t start;		/* Bytes */
+	uint64_t size;		/* Bytes */
+};
+
+/*
+ * All io should use these routines.
+ */
+int dev_get_size(const struct device *dev, uint64_t *size);
+int dev_get_sectsize(struct device *dev, uint32_t *size);
+
+/* 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 direct, int quiet);
+int dev_close(struct device *dev);
+int dev_close_immediate(struct device *dev);
+void dev_close_all(void);
+int dev_test_excl(struct device *dev);
+
+int dev_fd(struct device *dev);
+const char *dev_name(const struct device *dev);
+
+int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer);
+int dev_read_circular(struct device *dev, uint64_t offset, size_t len,
+		      uint64_t offset2, size_t len2, void *buf);
+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_set(struct device *dev, uint64_t offset, size_t len, int value);
+void dev_flush(struct device *dev);
+
+struct device *dev_create_file(const char *filename, struct device *dev,
+			       struct str_list *alias, int use_malloc);
+
+/* Return a valid device name from the alias list; NULL otherwise */
+const char *dev_name_confirmed(struct device *dev, int quiet);
+
+/* Does device contain md superblock?  If so, where? */
+int dev_is_md(struct device *dev, uint64_t *sb);
+unsigned long dev_md_chunk_size(const char *sysfs_dir, struct device *dev);
+
+int is_partitioned_dev(struct device *dev);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/display/display.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/display/display.c
diff -N src/external/gpl2/lvm2tools/dist/lib/display/display.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/display/display.c	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,775 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "metadata.h"
+#include "display.h"
+#include "activate.h"
+#include "toolcontext.h"
+#include "segtype.h"
+
+#define SIZE_BUF 128
+
+typedef enum { SIZE_LONG = 0, SIZE_SHORT = 1, SIZE_UNIT = 2 } size_len_t;
+
+static const struct {
+	alloc_policy_t alloc;
+	const char str[12]; /* must be changed when size extends 11 chars */
+} _policies[] = {
+	{
+	ALLOC_CONTIGUOUS, "contiguous"}, {
+	ALLOC_CLING, "cling"}, {
+	ALLOC_NORMAL, "normal"}, {
+	ALLOC_ANYWHERE, "anywhere"}, {
+	ALLOC_INHERIT, "inherit"}
+};
+
+static const int _num_policies = sizeof(_policies) / sizeof(*_policies);
+
+uint64_t units_to_bytes(const char *units, char *unit_type)
+{
+	char *ptr = NULL;
+	uint64_t v;
+
+	if (isdigit(*units)) {
+		v = (uint64_t) strtod(units, &ptr);
+		if (ptr == units)
+			return 0;
+		units = ptr;
+	} else
+		v = 1;
+
+	if (v == 1)
+		*unit_type = *units;
+	else
+		*unit_type = 'U';
+
+	switch (*units) {
+	case 'h':
+	case 'H':
+		v = UINT64_C(1);
+		*unit_type = *units;
+		break;
+	case 's':
+		v *= SECTOR_SIZE;
+		break;
+	case 'b':
+	case 'B':
+		v *= UINT64_C(1);
+		break;
+#define KILO UINT64_C(1024)
+	case 'k':
+		v *= KILO;
+		break;
+	case 'm':
+		v *= KILO * KILO;
+		break;
+	case 'g':
+		v *= KILO * KILO * KILO;
+		break;
+	case 't':
+		v *= KILO * KILO * KILO * KILO;
+		break;
+	case 'p':
+		v *= KILO * KILO * KILO * KILO * KILO;
+		break;
+	case 'e':
+		v *= KILO * KILO * KILO * KILO * KILO * KILO;
+		break;
+#undef KILO
+#define KILO UINT64_C(1000)
+	case 'K':
+		v *= KILO;
+		break;
+	case 'M':
+		v *= KILO * KILO;
+		break;
+	case 'G':
+		v *= KILO * KILO * KILO;
+		break;
+	case 'T':
+		v *= KILO * KILO * KILO * KILO;
+		break;
+	case 'P':
+		v *= KILO * KILO * KILO * KILO * KILO;
+		break;
+	case 'E':
+		v *= KILO * KILO * KILO * KILO * KILO * KILO;
+		break;
+#undef KILO
+	default:
+		return 0;
+	}
+
+	if (*(units + 1))
+		return 0;
+
+	return v;
+}
+
+const char *get_alloc_string(alloc_policy_t alloc)
+{
+	int i;
+
+	for (i = 0; i < _num_policies; i++)
+		if (_policies[i].alloc == alloc)
+			return _policies[i].str;
+
+	return NULL;
+}
+
+alloc_policy_t get_alloc_from_string(const char *str)
+{
+	int i;
+
+	for (i = 0; i < _num_policies; i++)
+		if (!strcmp(_policies[i].str, str))
+			return _policies[i].alloc;
+
+	/* Special case for old metadata */
+	if(!strcmp("next free", str))
+		return ALLOC_NORMAL;
+
+	log_error("Unrecognised allocation policy %s", str);
+	return ALLOC_INVALID;
+}
+
+/* Size supplied in sectors */
+static const char *_display_size(const struct cmd_context *cmd,
+				 uint64_t size, size_len_t sl)
+{
+	int s;
+	int suffix = 1, precision;
+	uint64_t byte = UINT64_C(0);
+	uint64_t units = UINT64_C(1024);
+	char *size_buf = NULL;
+	const char * const size_str[][3] = {
+		{" Exabyte", " EB", "E"},
+		{" Petabyte", " PB", "P"},
+		{" Terabyte", " TB", "T"},
+		{" Gigabyte", " GB", "G"},
+		{" Megabyte", " MB", "M"},
+		{" Kilobyte", " KB", "K"},
+		{"", "", ""},
+		{" Byte    ", " B ", "B"},
+		{" Units   ", " Un", "U"},
+		{" Sectors ", " Se", "S"},
+		{"         ", "   ", " "},
+	};
+
+	if (!(size_buf = dm_pool_alloc(cmd->mem, SIZE_BUF))) {
+		log_error("no memory for size display buffer");
+		return "";
+	}
+
+	suffix = cmd->current_settings.suffix;
+
+	for (s = 0; s < 10; s++)
+		if (toupper((int) cmd->current_settings.unit_type) ==
+		    *size_str[s][2])
+			break;
+
+	if (size == UINT64_C(0)) {
+		sprintf(size_buf, "0%s", suffix ? size_str[s][sl] : "");
+		return size_buf;
+	}
+
+	size *= UINT64_C(512);
+
+	if (s < 10)
+		byte = cmd->current_settings.unit_factor;
+	else {
+		suffix = 1;
+		if (cmd->current_settings.unit_type == 'H')
+			units = UINT64_C(1000);
+		else
+			units = UINT64_C(1024);
+		byte = units * units * units * units * units * units;
+		s = 0;
+		while (size_str[s] && size < byte)
+			s++, byte /= units;
+	}
+
+	/* FIXME Make precision configurable */
+	switch(toupper((int) cmd->current_settings.unit_type)) {
+	case 'B':
+	case 'S':
+		precision = 0;
+		break;
+	default:
+		precision = 2;
+	}
+
+	snprintf(size_buf, SIZE_BUF - 1, "%.*f%s", precision,
+		 (double) size / byte, suffix ? size_str[s][sl] : "");
+
+	return size_buf;
+}
+
+const char *display_size_long(const struct cmd_context *cmd, uint64_t size)
+{
+	return _display_size(cmd, size, SIZE_LONG);
+}
+
+const char *display_size_units(const struct cmd_context *cmd, uint64_t size)
+{
+	return _display_size(cmd, size, SIZE_UNIT);
+}
+
+const char *display_size(const struct cmd_context *cmd, uint64_t size)
+{
+	return _display_size(cmd, size, SIZE_SHORT);
+}
+
+void pvdisplay_colons(const struct physical_volume *pv)
+{
+	char uuid[64] __attribute((aligned(8)));
+
+	if (!pv)
+		return;
+
+	if (!id_write_format(&pv->id, uuid, sizeof(uuid))) {
+		stack;
+		return;
+	}
+
+	log_print("%s:%s:%" PRIu64 ":-1:%u:%u:-1:%" PRIu32 ":%u:%u:%u:%s",
+		  pv_dev_name(pv), pv->vg_name, pv->size,
+		  /* FIXME pv->pv_number, Derive or remove? */
+		  pv->status,	/* FIXME Support old or new format here? */
+		  pv->status & ALLOCATABLE_PV,	/* FIXME remove? */
+		  /* FIXME pv->lv_cur, Remove? */
+		  pv->pe_size / 2,
+		  pv->pe_count,
+		  pv->pe_count - pv->pe_alloc_count,
+		  pv->pe_alloc_count, *uuid ? uuid : "none");
+
+	return;
+}
+
+void pvdisplay_segments(const struct physical_volume *pv)
+{
+	const struct pv_segment *pvseg;
+
+	if (pv->pe_size)
+		log_print("--- Physical Segments ---");
+
+	dm_list_iterate_items(pvseg, &pv->segments) {
+		log_print("Physical extent %u to %u:",
+			  pvseg->pe, pvseg->pe + pvseg->len - 1);
+
+		if (pvseg_is_allocated(pvseg)) {
+			log_print("  Logical volume\t%s%s/%s",
+				  pvseg->lvseg->lv->vg->cmd->dev_dir,
+				  pvseg->lvseg->lv->vg->name,
+				  pvseg->lvseg->lv->name);
+			log_print("  Logical extents\t%d to %d",
+				  pvseg->lvseg->le, pvseg->lvseg->le +
+				  pvseg->lvseg->len - 1);
+		} else
+			log_print("  FREE");
+	}
+
+	log_print(" ");
+	return;
+}
+
+/* FIXME Include label fields */
+void pvdisplay_full(const struct cmd_context *cmd,
+		    const struct physical_volume *pv,
+		    void *handle __attribute((unused)))
+{
+	char uuid[64] __attribute((aligned(8)));
+	const char *size;
+
+	uint32_t pe_free;
+	uint64_t data_size, pvsize, unusable;
+
+	if (!pv)
+		return;
+
+	if (!id_write_format(&pv->id, uuid, sizeof(uuid))) {
+		stack;
+		return;
+	}
+
+	log_print("--- %sPhysical volume ---", pv->pe_size ? "" : "NEW ");
+	log_print("PV Name               %s", pv_dev_name(pv));
+	log_print("VG Name               %s%s",
+		  is_orphan(pv) ? "" : pv->vg_name,
+		  pv->status & EXPORTED_VG ? " (exported)" : "");
+
+	data_size = (uint64_t) pv->pe_count * pv->pe_size;
+	if (pv->size > data_size + pv->pe_start) {
+		pvsize = pv->size;
+		unusable = pvsize - data_size;
+	} else {
+		pvsize = data_size + pv->pe_start;
+		unusable = pvsize - pv->size;
+	}
+
+	size = display_size(cmd, pvsize);
+	if (data_size)
+		log_print("PV Size               %s / not usable %s",	/*  [LVM: %s]", */
+			  size, display_size(cmd, unusable));
+	else
+		log_print("PV Size               %s", size);
+
+	/* PV number not part of LVM2 design
+	   log_print("PV#                   %u", pv->pv_number);
+	 */
+
+	pe_free = pv->pe_count - pv->pe_alloc_count;
+	if (pv->pe_count && (pv->status & ALLOCATABLE_PV))
+		log_print("Allocatable           yes %s",
+			  (!pe_free && pv->pe_count) ? "(but full)" : "");
+	else
+		log_print("Allocatable           NO");
+
+	/* LV count is no longer available when displaying PV
+	   log_print("Cur LV                %u", vg->lv_count);
+	 */
+	log_print("PE Size (KByte)       %" PRIu32, pv->pe_size / 2);
+	log_print("Total PE              %u", pv->pe_count);
+	log_print("Free PE               %" PRIu32, pe_free);
+	log_print("Allocated PE          %u", pv->pe_alloc_count);
+	log_print("PV UUID               %s", *uuid ? uuid : "none");
+	log_print(" ");
+
+	return;
+}
+
+int pvdisplay_short(const struct cmd_context *cmd __attribute((unused)),
+		    const struct volume_group *vg __attribute((unused)),
+		    const struct physical_volume *pv,
+		    void *handle __attribute((unused)))
+{
+	char uuid[64] __attribute((aligned(8)));
+
+	if (!pv)
+		return 0;
+
+	if (!id_write_format(&pv->id, uuid, sizeof(uuid)))
+		return_0;
+
+	log_print("PV Name               %s     ", pv_dev_name(pv));
+	/* FIXME  pv->pv_number); */
+	log_print("PV UUID               %s", *uuid ? uuid : "none");
+	log_print("PV Status             %sallocatable",
+		  (pv->status & ALLOCATABLE_PV) ? "" : "NOT ");
+	log_print("Total PE / Free PE    %u / %u",
+		  pv->pe_count, pv->pe_count - pv->pe_alloc_count);
+
+	log_print(" ");
+	return 0;
+}
+
+void lvdisplay_colons(const struct logical_volume *lv)
+{
+	int inkernel;
+	struct lvinfo info;
+	inkernel = lv_info(lv->vg->cmd, lv, &info, 1, 0) && info.exists;
+
+	log_print("%s%s/%s:%s:%d:%d:-1:%d:%" PRIu64 ":%d:-1:%d:%d:%d:%d",
+		  lv->vg->cmd->dev_dir,
+		  lv->vg->name,
+		  lv->name,
+		  lv->vg->name,
+		  (lv->status & (LVM_READ | LVM_WRITE)) >> 8, inkernel ? 1 : 0,
+		  /* FIXME lv->lv_number,  */
+		  inkernel ? info.open_count : 0, lv->size, lv->le_count,
+		  /* FIXME Add num allocated to struct! lv->lv_allocated_le, */
+		  (lv->alloc == ALLOC_CONTIGUOUS ? 2 : 0), lv->read_ahead,
+		  inkernel ? info.major : -1, inkernel ? info.minor : -1);
+	return;
+}
+
+int lvdisplay_full(struct cmd_context *cmd,
+		   const struct logical_volume *lv,
+		   void *handle __attribute((unused)))
+{
+	struct lvinfo info;
+	int inkernel, snap_active = 0;
+	char uuid[64] __attribute((aligned(8)));
+	struct lv_segment *snap_seg = NULL;
+	float snap_percent;	/* fused, fsize; */
+
+	if (!id_write_format(&lv->lvid.id[1], uuid, sizeof(uuid)))
+		return_0;
+
+	inkernel = lv_info(cmd, lv, &info, 1, 1) && info.exists;
+
+	log_print("--- Logical volume ---");
+
+	log_print("LV Name                %s%s/%s", lv->vg->cmd->dev_dir,
+		  lv->vg->name, lv->name);
+	log_print("VG Name                %s", lv->vg->name);
+
+	log_print("LV UUID                %s", uuid);
+
+	log_print("LV Write Access        %s",
+		  (lv->status & LVM_WRITE) ? "read/write" : "read only");
+
+	if (lv_is_origin(lv)) {
+		log_print("LV snapshot status     source of");
+
+		dm_list_iterate_items_gen(snap_seg, &lv->snapshot_segs,
+				       origin_list) {
+			if (inkernel &&
+			    (snap_active = lv_snapshot_percent(snap_seg->cow,
+							       &snap_percent)))
+				if (snap_percent < 0 || snap_percent >= 100)
+					snap_active = 0;
+			log_print("                       %s%s/%s [%s]",
+				  lv->vg->cmd->dev_dir, lv->vg->name,
+				  snap_seg->cow->name,
+				  (snap_active > 0) ? "active" : "INACTIVE");
+		}
+		snap_seg = NULL;
+	} else if ((snap_seg = find_cow(lv))) {
+		if (inkernel &&
+		    (snap_active = lv_snapshot_percent(snap_seg->cow,
+						       &snap_percent)))
+			if (snap_percent < 0 || snap_percent >= 100)
+				snap_active = 0;
+
+		log_print("LV snapshot status     %s destination for %s%s/%s",
+			  (snap_active > 0) ? "active" : "INACTIVE",
+			  lv->vg->cmd->dev_dir, lv->vg->name,
+			  snap_seg->origin->name);
+	}
+
+	if (inkernel && info.suspended)
+		log_print("LV Status              suspended");
+	else
+		log_print("LV Status              %savailable",
+			  inkernel ? "" : "NOT ");
+
+/********* FIXME lv_number
+    log_print("LV #                   %u", lv->lv_number + 1);
+************/
+
+	if (inkernel)
+		log_print("# open                 %u", info.open_count);
+
+	log_print("LV Size                %s",
+		  display_size(cmd,
+			       snap_seg ? snap_seg->origin->size : lv->size));
+
+	log_print("Current LE             %u",
+		  snap_seg ? snap_seg->origin->le_count : lv->le_count);
+
+	if (snap_seg) {
+		log_print("COW-table size         %s",
+			  display_size(cmd, (uint64_t) lv->size));
+		log_print("COW-table LE           %u", lv->le_count);
+
+		if (snap_active)
+			log_print("Allocated to snapshot  %.2f%% ", snap_percent);	
+
+		log_print("Snapshot chunk size    %s",
+			  display_size(cmd, (uint64_t) snap_seg->chunk_size));
+	}
+
+	log_print("Segments               %u", dm_list_size(&lv->segments));
+
+/********* FIXME Stripes & stripesize for each segment
+	log_print("Stripe size (KByte)    %u", lv->stripesize / 2);
+***********/
+
+	log_print("Allocation             %s", get_alloc_string(lv->alloc));
+	if (lv->read_ahead == DM_READ_AHEAD_AUTO)
+		log_print("Read ahead sectors     auto");
+	else if (lv->read_ahead == DM_READ_AHEAD_NONE)
+		log_print("Read ahead sectors     0");
+	else
+		log_print("Read ahead sectors     %u", lv->read_ahead);
+
+	if (inkernel && lv->read_ahead != info.read_ahead)
+		log_print("- currently set to     %u", info.read_ahead);
+
+	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,
+			  info.minor);
+
+	log_print(" ");
+
+	return 0;
+}
+
+void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre)
+{
+	switch (seg_type(seg, s)) {
+	case AREA_PV:
+		/* FIXME Re-check the conditions for 'Missing' */
+		log_print("%sPhysical volume\t%s", pre,
+			  seg_pv(seg, s) ?
+			  pv_dev_name(seg_pv(seg, s)) :
+			    "Missing");
+
+		if (seg_pv(seg, s))
+			log_print("%sPhysical extents\t%d to %d", pre,
+				  seg_pe(seg, s),
+				  seg_pe(seg, s) + seg->area_len - 1);
+		break;
+	case AREA_LV:
+		log_print("%sLogical volume\t%s", pre,
+			  seg_lv(seg, s) ?
+			  seg_lv(seg, s)->name : "Missing");
+
+		if (seg_lv(seg, s))
+			log_print("%sLogical extents\t%d to %d", pre,
+				  seg_le(seg, s),
+				  seg_le(seg, s) + seg->area_len - 1);
+		break;
+	case AREA_UNASSIGNED:
+		log_print("%sUnassigned area", pre);
+	}
+}
+
+int lvdisplay_segments(const struct logical_volume *lv)
+{
+	const struct lv_segment *seg;
+
+	log_print("--- Segments ---");
+
+	dm_list_iterate_items(seg, &lv->segments) {
+		log_print("Logical extent %u to %u:",
+			  seg->le, seg->le + seg->len - 1);
+
+		log_print("  Type\t\t%s", seg->segtype->ops->name(seg));
+
+		if (seg->segtype->ops->display)
+			seg->segtype->ops->display(seg);
+	}
+
+	log_print(" ");
+	return 1;
+}
+
+void vgdisplay_extents(const struct volume_group *vg __attribute((unused)))
+{
+	return;
+}
+
+void vgdisplay_full(const struct volume_group *vg)
+{
+	uint32_t access_str;
+	uint32_t active_pvs;
+	uint32_t lv_count = 0;
+	struct lv_list *lvl;
+	char uuid[64] __attribute((aligned(8)));
+
+	active_pvs = vg->pv_count - vg_missing_pv_count(vg);
+
+	log_print("--- Volume group ---");
+	log_print("VG Name               %s", vg->name);
+	log_print("System ID             %s", vg->system_id);
+	log_print("Format                %s", vg->fid->fmt->name);
+	if (vg->fid->fmt->features & FMT_MDAS) {
+		log_print("Metadata Areas        %d",
+			  dm_list_size(&vg->fid->metadata_areas));
+		log_print("Metadata Sequence No  %d", vg->seqno);
+	}
+	access_str = vg->status & (LVM_READ | LVM_WRITE);
+	log_print("VG Access             %s%s%s%s",
+		  access_str == (LVM_READ | LVM_WRITE) ? "read/write" : "",
+		  access_str == LVM_READ ? "read" : "",
+		  access_str == LVM_WRITE ? "write" : "",
+		  access_str == 0 ? "error" : "");
+	log_print("VG Status             %s%sresizable",
+		  vg->status & EXPORTED_VG ? "exported/" : "",
+		  vg->status & RESIZEABLE_VG ? "" : "NOT ");
+	/* vg number not part of LVM2 design
+	   log_print ("VG #                  %u\n", vg->vg_number);
+	 */
+	if (vg_is_clustered(vg)) {
+		log_print("Clustered             yes");
+		log_print("Shared                %s",
+			  vg->status & SHARED ? "yes" : "no");
+	}
+
+	dm_list_iterate_items(lvl, &vg->lvs)
+		if (lv_is_visible(lvl->lv) && !(lvl->lv->status & SNAPSHOT))
+			lv_count++;
+
+	log_print("MAX LV                %u", vg->max_lv);
+	log_print("Cur LV                %u", lv_count);
+	log_print("Open LV               %u", lvs_in_vg_opened(vg));
+/****** FIXME Max LV Size
+      log_print ( "MAX LV Size           %s",
+               ( s1 = display_size ( LVM_LV_SIZE_MAX(vg))));
+      free ( s1);
+*********/
+	log_print("Max PV                %u", vg->max_pv);
+	log_print("Cur PV                %u", vg->pv_count);
+	log_print("Act PV                %u", active_pvs);
+
+	log_print("VG Size               %s",
+		  display_size(vg->cmd,
+			       (uint64_t) vg->extent_count * vg->extent_size));
+
+	log_print("PE Size               %s",
+		  display_size(vg->cmd, (uint64_t) vg->extent_size));
+
+	log_print("Total PE              %u", vg->extent_count);
+
+	log_print("Alloc PE / Size       %u / %s",
+		  vg->extent_count - vg->free_count,
+		  display_size(vg->cmd,
+			       ((uint64_t) vg->extent_count - vg->free_count) *
+			       vg->extent_size));
+
+	log_print("Free  PE / Size       %u / %s", vg->free_count,
+		  display_size(vg->cmd,
+			       (uint64_t) vg->free_count * vg->extent_size));
+
+	if (!id_write_format(&vg->id, uuid, sizeof(uuid))) {
+		stack;
+		return;
+	}
+
+	log_print("VG UUID               %s", uuid);
+	log_print(" ");
+
+	return;
+}
+
+void vgdisplay_colons(const struct volume_group *vg)
+{
+	uint32_t active_pvs;
+	uint32_t lv_count;
+	struct lv_list *lvl;
+	const char *access_str;
+	char uuid[64] __attribute((aligned(8)));
+
+	active_pvs = vg->pv_count - vg_missing_pv_count(vg);
+
+	dm_list_iterate_items(lvl, &vg->lvs)
+		if (lv_is_visible(lvl->lv) && !(lvl->lv->status & SNAPSHOT))
+			lv_count++;
+
+	switch (vg->status & (LVM_READ | LVM_WRITE)) {
+		case LVM_READ | LVM_WRITE:
+			access_str = "r/w";
+			break;
+		case LVM_READ:
+			access_str = "r";
+			break;
+		case LVM_WRITE:
+			access_str = "w";
+			break;
+		default:
+			access_str = "";
+	}
+
+	if (!id_write_format(&vg->id, uuid, sizeof(uuid))) {
+		stack;
+		return;
+	}
+
+	log_print("%s:%s:%d:-1:%u:%u:%u:-1:%u:%u:%u:%" PRIu64 ":%" PRIu32
+		  ":%u:%u:%u:%s",
+		vg->name,
+		access_str,
+		vg->status,
+		/* internal volume group number; obsolete */
+		vg->max_lv,
+		vg->lv_count,
+		lvs_in_vg_opened(vg),
+		/* FIXME: maximum logical volume size */
+		vg->max_pv,
+		vg->pv_count,
+		active_pvs,
+		(uint64_t) vg->extent_count * (vg->extent_size / 2),
+		vg->extent_size / 2,
+		vg->extent_count,
+		vg->extent_count - vg->free_count,
+		vg->free_count,
+		uuid[0] ? uuid : "none");
+	return;
+}
+
+void vgdisplay_short(const struct volume_group *vg)
+{
+	log_print("\"%s\" %-9s [%-9s used / %s free]", vg->name,
+/********* FIXME if "open" print "/used" else print "/idle"???  ******/
+		  display_size(vg->cmd,
+			       (uint64_t) vg->extent_count * vg->extent_size),
+		  display_size(vg->cmd,
+			       ((uint64_t) vg->extent_count -
+				vg->free_count) * vg->extent_size),
+		  display_size(vg->cmd,
+			       (uint64_t) vg->free_count * vg->extent_size));
+	return;
+}
+
+void display_formats(const struct cmd_context *cmd)
+{
+	const struct format_type *fmt;
+
+	dm_list_iterate_items(fmt, &cmd->formats) {
+		log_print("%s", fmt->name);
+	}
+}
+
+void display_segtypes(const struct cmd_context *cmd)
+{
+	const struct segment_type *segtype;
+
+	dm_list_iterate_items(segtype, &cmd->segtypes) {
+		log_print("%s", segtype->name);
+	}
+}
+
+char yes_no_prompt(const char *prompt, ...)
+{
+	int c = 0, ret = 0;
+	va_list ap;
+
+	sigint_allow();
+	do {
+		if (c == '\n' || !c) {
+			va_start(ap, prompt);
+			vprintf(prompt, ap);
+			va_end(ap);
+		}
+
+		if ((c = getchar()) == EOF) {
+			ret = 'n';
+			break;
+		}
+
+		c = tolower(c);
+		if ((c == 'y') || (c == 'n'))
+			ret = c;
+	} while (!ret || c != '\n');
+
+	sigint_restore();
+
+	if (c != '\n')
+		printf("\n");
+
+	return ret;
+}
+
Index: src/external/gpl2/lvm2tools/dist/lib/display/display.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/display/display.h
diff -N src/external/gpl2/lvm2tools/dist/lib/display/display.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/display/display.h	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,66 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_DISPLAY_H
+#define _LVM_DISPLAY_H
+
+#include "metadata-exported.h"
+#include "locking.h"
+
+#include <stdint.h>
+
+uint64_t units_to_bytes(const char *units, char *unit_type);
+
+/* Specify size in KB */
+const char *display_size(const struct cmd_context *cmd, uint64_t size);
+const char *display_size_long(const struct cmd_context *cmd, uint64_t size);
+const char *display_size_units(const struct cmd_context *cmd, uint64_t size);
+
+char *display_uuid(char *uuidstr);
+void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre);
+
+void pvdisplay_colons(const struct physical_volume *pv);
+void pvdisplay_segments(const struct physical_volume *pv);
+void pvdisplay_full(const struct cmd_context *cmd,
+		    const struct physical_volume *pv,
+		    void *handle);
+int pvdisplay_short(const struct cmd_context *cmd,
+		    const struct volume_group *vg,
+		    const struct physical_volume *pv, void *handle);
+
+void lvdisplay_colons(const struct logical_volume *lv);
+int lvdisplay_segments(const struct logical_volume *lv);
+int lvdisplay_full(struct cmd_context *cmd, const struct logical_volume *lv,
+		   void *handle);
+
+void vgdisplay_extents(const struct volume_group *vg);
+void vgdisplay_full(const struct volume_group *vg);
+void vgdisplay_colons(const struct volume_group *vg);
+void vgdisplay_short(const struct volume_group *vg);
+
+void display_formats(const struct cmd_context *cmd);
+void display_segtypes(const struct cmd_context *cmd);
+
+/*
+ * Allocation policy display conversion routines.
+ */
+const char *get_alloc_string(alloc_policy_t alloc);
+alloc_policy_t get_alloc_from_string(const char *str);
+
+char yes_no_prompt(const char *prompt, ...);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/error/errseg.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/error/errseg.c
diff -N src/external/gpl2/lvm2tools/dist/lib/error/errseg.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/error/errseg.c	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,116 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "toolcontext.h"
+#include "segtype.h"
+#include "display.h"
+#include "text_export.h"
+#include "text_import.h"
+#include "config.h"
+#include "str_list.h"
+#include "targets.h"
+#include "lvm-string.h"
+#include "activate.h"
+#include "str_list.h"
+#include "metadata.h"
+
+static const char *_errseg_name(const struct lv_segment *seg)
+{
+	return seg->segtype->name;
+}
+
+static int _errseg_merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
+{
+	seg1->len += seg2->len;
+	seg1->area_len += seg2->area_len;
+
+	return 1;
+}
+
+#ifdef DEVMAPPER_SUPPORT
+static int _errseg_add_target_line(struct dev_manager *dm __attribute((unused)),
+				struct dm_pool *mem __attribute((unused)),
+				struct cmd_context *cmd __attribute((unused)),
+				void **target_state __attribute((unused)),
+				struct lv_segment *seg __attribute((unused)),
+				struct dm_tree_node *node, uint64_t len,
+				uint32_t *pvmove_mirror_count __attribute((unused)))
+{
+	return dm_tree_node_add_error_target(node, len);
+}
+
+static int _errseg_target_present(const struct lv_segment *seg __attribute((unused)),
+				  unsigned *attributes __attribute((unused)))
+{
+	static int _errseg_checked = 0;
+	static int _errseg_present = 0;
+
+	/* Reported truncated in older kernels */
+	if (!_errseg_checked &&
+	    (target_present("error", 0) || target_present("erro", 0)))
+		_errseg_present = 1;
+
+	_errseg_checked = 1;
+	return _errseg_present;
+}
+#endif
+
+static int _errseg_modules_needed(struct dm_pool *mem,
+				  const struct lv_segment *seg __attribute((unused)),
+				  struct dm_list *modules)
+{
+	if (!str_list_add(mem, modules, "error")) {
+		log_error("error module string list allocation failed");
+		return 0;
+	}
+
+	return 1;
+}
+
+static void _errseg_destroy(const struct segment_type *segtype)
+{
+	dm_free((void *)segtype);
+}
+
+static struct segtype_handler _error_ops = {
+	.name = _errseg_name,
+	.merge_segments = _errseg_merge_segments,
+#ifdef DEVMAPPER_SUPPORT
+	.add_target_line = _errseg_add_target_line,
+	.target_present = _errseg_target_present,
+#endif
+	.modules_needed = _errseg_modules_needed,
+	.destroy = _errseg_destroy,
+};
+
+struct segment_type *init_error_segtype(struct cmd_context *cmd)
+{
+	struct segment_type *segtype = dm_malloc(sizeof(*segtype));
+
+	if (!segtype)
+		return_NULL;
+
+	segtype->cmd = cmd;
+	segtype->ops = &_error_ops;
+	segtype->name = "error";
+	segtype->private = NULL;
+	segtype->flags = SEG_CAN_SPLIT | SEG_VIRTUAL | SEG_CANNOT_BE_ZEROED;
+
+	log_very_verbose("Initialised segtype: %s", segtype->name);
+
+	return segtype;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/filters/filter-composite.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/filters/filter-composite.c
diff -N src/external/gpl2/lvm2tools/dist/lib/filters/filter-composite.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/filters/filter-composite.c	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,77 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "filter-composite.h"
+
+#include <stdarg.h>
+
+static int _and_p(struct dev_filter *f, struct device *dev)
+{
+	struct dev_filter **filters = (struct dev_filter **) f->private;
+
+	while (*filters) {
+		if (!(*filters)->passes_filter(*filters, dev))
+			return 0;
+		filters++;
+	}
+
+	log_debug("Using %s", dev_name(dev));
+
+	return 1;
+}
+
+static void _composite_destroy(struct dev_filter *f)
+{
+	struct dev_filter **filters = (struct dev_filter **) f->private;
+
+	while (*filters) {
+		(*filters)->destroy(*filters);
+		filters++;
+	}
+
+	dm_free(f->private);
+	dm_free(f);
+}
+
+struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
+{
+	struct dev_filter **filters_copy, *cft;
+
+	if (!filters)
+		return_NULL;
+
+	if (!(filters_copy = dm_malloc(sizeof(*filters) * (n + 1)))) {
+		log_error("composite filters allocation failed");
+		return NULL;
+	}
+
+	memcpy(filters_copy, filters, sizeof(*filters) * n);
+	filters_copy[n] = NULL;
+
+	if (!(cft = dm_malloc(sizeof(*cft)))) {
+		log_error("compsoite filters allocation failed");
+		dm_free(filters_copy);
+		return NULL;
+	}
+
+	cft->passes_filter = _and_p;
+	cft->destroy = _composite_destroy;
+	cft->private = filters_copy;
+
+	return cft;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/filters/filter-composite.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/filters/filter-composite.h
diff -N src/external/gpl2/lvm2tools/dist/lib/filters/filter-composite.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/filters/filter-composite.h	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,25 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_FILTER_COMPOSITE_H
+#define _LVM_FILTER_COMPOSITE_H
+
+#include "dev-cache.h"
+
+struct dev_filter *composite_filter_create(int n, struct dev_filter **filters);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/filters/filter-md.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/filters/filter-md.c
diff -N src/external/gpl2/lvm2tools/dist/lib/filters/filter-md.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/filters/filter-md.c	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,76 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2004 Luca Berra
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "filter-md.h"
+#include "metadata.h"
+
+#ifdef linux
+
+static int _ignore_md(struct dev_filter *f __attribute((unused)),
+		      struct device *dev)
+{
+	int ret;
+	
+	if (!md_filtering())
+		return 1;
+	
+	ret = dev_is_md(dev, NULL);
+
+	if (ret == 1) {
+		log_debug("%s: Skipping md component device", dev_name(dev));
+		return 0;
+	}
+
+	if (ret < 0) {
+		log_debug("%s: Skipping: error in md component detection",
+			  dev_name(dev));
+		return 0;
+	}
+
+	return 1;
+}
+
+static void _destroy(struct dev_filter *f)
+{
+	dm_free(f);
+}
+
+struct dev_filter *md_filter_create(void)
+{
+	struct dev_filter *f;
+
+	if (!(f = dm_malloc(sizeof(*f)))) {
+		log_error("md filter allocation failed");
+		return NULL;
+	}
+
+	f->passes_filter = _ignore_md;
+	f->destroy = _destroy;
+	f->private = NULL;
+
+	return f;
+}
+
+#else
+
+struct dev_filter *md_filter_create(void)
+{
+	return NULL;
+}
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/filters/filter-md.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/filters/filter-md.h
diff -N src/external/gpl2/lvm2tools/dist/lib/filters/filter-md.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/filters/filter-md.h	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,25 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2004 Luca Berra
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_FILTER_MD_H
+#define _LVM_FILTER_MD_H
+
+#include "dev-cache.h"
+
+struct dev_filter *md_filter_create(void);
+
+#endif
+
Index: src/external/gpl2/lvm2tools/dist/lib/filters/filter-persistent.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/filters/filter-persistent.c
diff -N src/external/gpl2/lvm2tools/dist/lib/filters/filter-persistent.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/filters/filter-persistent.c	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,335 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "config.h"
+#include "dev-cache.h"
+#include "filter-persistent.h"
+#include "lvm-file.h"
+#include "lvm-string.h"
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+struct pfilter {
+	char *file;
+	struct dm_hash_table *devices;
+	struct dev_filter *real;
+	time_t ctime;
+};
+
+/*
+ * The hash table holds one of these two states
+ * against each entry.
+ */
+#define PF_BAD_DEVICE ((void *) 1)
+#define PF_GOOD_DEVICE ((void *) 2)
+
+static int _init_hash(struct pfilter *pf)
+{
+	if (pf->devices)
+		dm_hash_destroy(pf->devices);
+
+	if (!(pf->devices = dm_hash_create(128)))
+		return_0;
+
+	return 1;
+}
+
+int persistent_filter_wipe(struct dev_filter *f)
+{
+	struct pfilter *pf = (struct pfilter *) f->private;
+
+	log_verbose("Wiping cache of LVM-capable devices");
+	dm_hash_wipe(pf->devices);
+
+	/* Trigger complete device scan */
+	dev_cache_scan(1);
+
+	return 1;
+}
+
+static int _read_array(struct pfilter *pf, struct config_tree *cft,
+		       const char *path, void *data)
+{
+	const struct config_node *cn;
+	struct config_value *cv;
+
+	if (!(cn = find_config_node(cft->root, path))) {
+		log_very_verbose("Couldn't find %s array in '%s'",
+				 path, pf->file);
+		return 0;
+	}
+
+	/*
+	 * iterate through the array, adding
+	 * devices as we go.
+	 */
+	for (cv = cn->v; cv; cv = cv->next) {
+		if (cv->type != CFG_STRING) {
+			log_verbose("Devices array contains a value "
+				    "which is not a string ... ignoring");
+			continue;
+		}
+
+		if (!dm_hash_insert(pf->devices, cv->v.str, data))
+			log_verbose("Couldn't add '%s' to filter ... ignoring",
+				    cv->v.str);
+		/* Populate dev_cache ourselves */
+		dev_cache_get(cv->v.str, NULL);
+	}
+	return 1;
+}
+
+int persistent_filter_load(struct dev_filter *f, struct config_tree **cft_out)
+{
+	struct pfilter *pf = (struct pfilter *) f->private;
+	struct config_tree *cft;
+	struct stat info;
+	int r = 0;
+
+	if (!stat(pf->file, &info))
+		pf->ctime = info.st_ctime;
+	else {
+		log_very_verbose("%s: stat failed: %s", pf->file,
+				 strerror(errno));
+		return_0;
+	}
+
+	if (!(cft = create_config_tree(pf->file, 1)))
+		return_0;
+
+	if (!read_config_file(cft))
+		goto_out;
+
+	_read_array(pf, cft, "persistent_filter_cache/valid_devices",
+		    PF_GOOD_DEVICE);
+	/* We don't gain anything by holding invalid devices */
+	/* _read_array(pf, cft, "persistent_filter_cache/invalid_devices",
+	   PF_BAD_DEVICE); */
+
+	/* Did we find anything? */
+	if (dm_hash_get_num_entries(pf->devices)) {
+		/* We populated dev_cache ourselves */
+		dev_cache_scan(0);
+		r = 1;
+	}
+
+	log_very_verbose("Loaded persistent filter cache from %s", pf->file);
+
+      out:
+	if (r && cft_out)
+		*cft_out = cft;
+	else
+		destroy_config_tree(cft);
+	return r;
+}
+
+static void _write_array(struct pfilter *pf, FILE *fp, const char *path,
+			 void *data)
+{
+	void *d;
+	int first = 1;
+	char *buf, *str;
+	struct dm_hash_node *n;
+
+	for (n = dm_hash_get_first(pf->devices); n;
+	     n = dm_hash_get_next(pf->devices, n)) {
+		d = dm_hash_get_data(pf->devices, n);
+
+		if (d != data)
+			continue;
+
+		if (!first)
+			fprintf(fp, ",\n");
+		else {
+			fprintf(fp, "\t%s=[\n", path);
+			first = 0;
+		}
+
+		str = dm_hash_get_key(pf->devices, n);
+		if (!(buf = alloca(escaped_len(str)))) {
+			log_error("persistent filter device path stack "
+				  "allocation failed");
+			return;
+		}
+		fprintf(fp, "\t\t\"%s\"", escape_double_quotes(buf, str));
+	}
+
+	if (!first)
+		fprintf(fp, "\n\t]\n");
+
+	return;
+}
+
+int persistent_filter_dump(struct dev_filter *f)
+{
+	struct pfilter *pf = (struct pfilter *) f->private;
+	char *tmp_file;
+	struct stat info, info2;
+	struct config_tree *cft = NULL;
+	FILE *fp;
+	int lockfd;
+	int r = 0;
+
+	if (!dm_hash_get_num_entries(pf->devices)) {
+		log_very_verbose("Internal persistent device cache empty "
+				 "- not writing to %s", pf->file);
+		return 0;
+	}
+	if (!dev_cache_has_scanned()) {
+		log_very_verbose("Device cache incomplete - not writing "
+				 "to %s", pf->file);
+		return 0;
+	}
+
+	log_very_verbose("Dumping persistent device cache to %s", pf->file);
+
+	while (1) {
+		if ((lockfd = fcntl_lock_file(pf->file, F_WRLCK, 0)) < 0)
+			return_0;
+
+		/*
+		 * Ensure we locked the file we expected
+		 */
+		if (fstat(lockfd, &info)) {
+			log_sys_error("fstat", pf->file);
+			goto out;
+		}
+		if (stat(pf->file, &info2)) {
+			log_sys_error("stat", pf->file);
+			goto out;
+		}
+
+		if (is_same_inode(info, info2))
+			break;
+	
+		fcntl_unlock_file(lockfd);
+	}
+
+	/*
+	 * If file contents changed since we loaded it, merge new contents
+	 */
+	if (info.st_ctime != pf->ctime)
+		/* Keep cft open to avoid losing lock */
+		persistent_filter_load(f, &cft);
+
+	tmp_file = alloca(strlen(pf->file) + 5);
+	sprintf(tmp_file, "%s.tmp", pf->file);
+
+	if (!(fp = fopen(tmp_file, "w"))) {
+		/* EACCES has been reported over NFS */
+		if (errno != EROFS && errno != EACCES)
+			log_sys_error("fopen", tmp_file);
+		goto out;
+	}
+
+	fprintf(fp, "# This file is automatically maintained by lvm.\n\n");
+	fprintf(fp, "persistent_filter_cache {\n");
+
+	_write_array(pf, fp, "valid_devices", PF_GOOD_DEVICE);
+	/* We don't gain anything by remembering invalid devices */
+	/* _write_array(pf, fp, "invalid_devices", PF_BAD_DEVICE); */
+
+	fprintf(fp, "}\n");
+	if (lvm_fclose(fp, tmp_file))
+		goto_out;
+
+	if (rename(tmp_file, pf->file))
+		log_error("%s: rename to %s failed: %s", tmp_file, pf->file,
+			  strerror(errno));
+
+	r = 1;
+
+out:
+	fcntl_unlock_file(lockfd);
+
+	if (cft)
+		destroy_config_tree(cft);
+
+	return r;
+}
+
+static int _lookup_p(struct dev_filter *f, struct device *dev)
+{
+	struct pfilter *pf = (struct pfilter *) f->private;
+	void *l = dm_hash_lookup(pf->devices, dev_name(dev));
+	struct str_list *sl;
+
+	if (!l) {
+		l = pf->real->passes_filter(pf->real, dev) ?
+		    PF_GOOD_DEVICE : PF_BAD_DEVICE;
+
+		dm_list_iterate_items(sl, &dev->aliases)
+			dm_hash_insert(pf->devices, sl->str, l);
+
+	} else if (l == PF_BAD_DEVICE)
+			log_debug("%s: Skipping (cached)", dev_name(dev));
+
+	return (l == PF_BAD_DEVICE) ? 0 : 1;
+}
+
+static void _persistent_destroy(struct dev_filter *f)
+{
+	struct pfilter *pf = (struct pfilter *) f->private;
+
+	dm_hash_destroy(pf->devices);
+	dm_free(pf->file);
+	pf->real->destroy(pf->real);
+	dm_free(pf);
+	dm_free(f);
+}
+
+struct dev_filter *persistent_filter_create(struct dev_filter *real,
+					    const char *file)
+{
+	struct pfilter *pf;
+	struct dev_filter *f = NULL;
+
+	if (!(pf = dm_malloc(sizeof(*pf))))
+		return_NULL;
+	memset(pf, 0, sizeof(*pf));
+
+	if (!(pf->file = dm_malloc(strlen(file) + 1)))
+		goto_bad;
+
+	strcpy(pf->file, file);
+	pf->real = real;
+
+	if (!(_init_hash(pf))) {
+		log_error("Couldn't create hash table for persistent filter.");
+		goto bad;
+	}
+
+	if (!(f = dm_malloc(sizeof(*f))))
+		goto_bad;
+
+	f->passes_filter = _lookup_p;
+	f->destroy = _persistent_destroy;
+	f->private = pf;
+
+	return f;
+
+      bad:
+	dm_free(pf->file);
+	if (pf->devices)
+		dm_hash_destroy(pf->devices);
+	dm_free(pf);
+	dm_free(f);
+	return NULL;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/filters/filter-persistent.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/filters/filter-persistent.h
diff -N src/external/gpl2/lvm2tools/dist/lib/filters/filter-persistent.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/filters/filter-persistent.h	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,30 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_FILTER_PERSISTENT_H
+#define _LVM_FILTER_PERSISTENT_H
+
+#include "dev-cache.h"
+
+struct dev_filter *persistent_filter_create(struct dev_filter *f,
+					    const char *file);
+
+int persistent_filter_wipe(struct dev_filter *f);
+int persistent_filter_load(struct dev_filter *f, struct config_tree **cft_out);
+int persistent_filter_dump(struct dev_filter *f);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/filters/filter-regex.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/filters/filter-regex.c
diff -N src/external/gpl2/lvm2tools/dist/lib/filters/filter-regex.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/filters/filter-regex.c	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,217 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "filter-regex.h"
+#include "device.h"
+
+struct rfilter {
+	struct dm_pool *mem;
+	dm_bitset_t accept;
+	struct dm_regex *engine;
+};
+
+static int _extract_pattern(struct dm_pool *mem, const char *pat,
+			    char **regex, dm_bitset_t accept, int ix)
+{
+	char sep, *r, *ptr;
+
+	/*
+	 * is this an accept or reject pattern
+	 */
+	switch (*pat) {
+	case 'a':
+		dm_bit_set(accept, ix);
+		break;
+
+	case 'r':
+		dm_bit_clear(accept, ix);
+		break;
+
+	default:
+		log_info("pattern must begin with 'a' or 'r'");
+		return 0;
+	}
+	pat++;
+
+	/*
+	 * get the separator
+	 */
+	switch (*pat) {
+	case '(':
+		sep = ')';
+		break;
+
+	case '[':
+		sep = ']';
+		break;
+
+	case '{':
+		sep = '}';
+		break;
+
+	default:
+		sep = *pat;
+	}
+	pat++;
+
+	/*
+	 * copy the regex
+	 */
+	if (!(r = dm_pool_strdup(mem, pat)))
+		return_0;
+
+	/*
+	 * trim the trailing character, having checked it's sep.
+	 */
+	ptr = r + strlen(r) - 1;
+	if (*ptr != sep) {
+		log_info("invalid separator at end of regex");
+		return 0;
+	}
+	*ptr = '\0';
+
+	regex[ix] = r;
+	return 1;
+}
+
+static int _build_matcher(struct rfilter *rf, struct config_value *val)
+{
+	struct dm_pool *scratch;
+	struct config_value *v;
+	char **regex;
+	unsigned count = 0;
+	int i, r = 0;
+
+	if (!(scratch = dm_pool_create("filter dm_regex", 1024)))
+		return_0;
+
+	/*
+	 * count how many patterns we have.
+	 */
+	for (v = val; v; v = v->next) {
+		if (v->type != CFG_STRING) {
+			log_error("filter patterns must be enclosed in quotes");
+			goto out;
+		}
+
+		count++;
+	}
+
+	/*
+	 * allocate space for them
+	 */
+	if (!(regex = dm_pool_alloc(scratch, sizeof(*regex) * count)))
+		goto_out;
+
+	/*
+	 * create the accept/reject bitset
+	 */
+	rf->accept = dm_bitset_create(rf->mem, count);
+
+	/*
+	 * fill the array back to front because we
+	 * want the opposite precedence to what
+	 * the matcher gives.
+	 */
+	for (v = val, i = count - 1; v; v = v->next, i--)
+		if (!_extract_pattern(scratch, v->v.str, regex, rf->accept, i)) {
+			log_error("invalid filter pattern");
+			goto out;
+		}
+
+	/*
+	 * build the matcher.
+	 */
+	if (!(rf->engine = dm_regex_create(rf->mem, (const char **) regex,
+					   count)))
+		stack;
+	r = 1;
+
+      out:
+	dm_pool_destroy(scratch);
+	return r;
+}
+
+static int _accept_p(struct dev_filter *f, struct device *dev)
+{
+	int m, first = 1, rejected = 0;
+	struct rfilter *rf = (struct rfilter *) f->private;
+	struct str_list *sl;
+
+	dm_list_iterate_items(sl, &dev->aliases) {
+		m = dm_regex_match(rf->engine, sl->str);
+
+		if (m >= 0) {
+			if (dm_bit(rf->accept, m)) {
+				if (!first)
+					dev_set_preferred_name(sl, dev);
+
+				return 1;
+			}
+
+			rejected = 1;
+		}
+
+		first = 0;
+	}
+
+	if (rejected)
+		log_debug("%s: Skipping (regex)", dev_name(dev));
+
+	/*
+	 * pass everything that doesn't match
+	 * anything.
+	 */
+	return !rejected;
+}
+
+static void _regex_destroy(struct dev_filter *f)
+{
+	struct rfilter *rf = (struct rfilter *) f->private;
+	dm_pool_destroy(rf->mem);
+}
+
+struct dev_filter *regex_filter_create(struct config_value *patterns)
+{
+	struct dm_pool *mem = dm_pool_create("filter regex", 10 * 1024);
+	struct rfilter *rf;
+	struct dev_filter *f;
+
+	if (!mem)
+		return_NULL;
+
+	if (!(rf = dm_pool_alloc(mem, sizeof(*rf))))
+		goto_bad;
+
+	rf->mem = mem;
+
+	if (!_build_matcher(rf, patterns))
+		goto_bad;
+
+	if (!(f = dm_pool_zalloc(mem, sizeof(*f))))
+		goto_bad;
+
+	f->passes_filter = _accept_p;
+	f->destroy = _regex_destroy;
+	f->private = rf;
+	return f;
+
+      bad:
+	dm_pool_destroy(mem);
+	return NULL;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/filters/filter-regex.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/filters/filter-regex.h
diff -N src/external/gpl2/lvm2tools/dist/lib/filters/filter-regex.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/filters/filter-regex.h	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,34 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_FILTER_REGEX_H
+#define _LVM_FILTER_REGEX_H
+
+#include "config.h"
+#include "dev-cache.h"
+
+/*
+ * patterns must be an array of strings of the form:
+ * [ra]<sep><regex><sep>, eg,
+ * r/cdrom/          - reject cdroms
+ * a|loop/[0-4]|     - accept loops 0 to 4
+ * r|.*|             - reject everything else
+ */
+
+struct dev_filter *regex_filter_create(struct config_value *patterns);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/filters/filter-sysfs.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/filters/filter-sysfs.c
diff -N src/external/gpl2/lvm2tools/dist/lib/filters/filter-sysfs.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/filters/filter-sysfs.c	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,336 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "filter-sysfs.h"
+#include "lvm-string.h"
+
+#ifdef linux
+
+#include <dirent.h>
+
+static int _locate_sysfs_blocks(const char *sysfs_dir, char *path, size_t len,
+				unsigned *sysfs_depth)
+{
+	struct stat info;
+
+	/*
+	 * unified classification directory for all kernel subsystems
+	 *
+	 * /sys/subsystem/block/devices
+	 * |-- sda -> ../../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda
+	 * |-- sda1 -> ../../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1
+	 *  `-- sr0 -> ../../../devices/pci0000:00/0000:00:1f.2/host1/target1:0:0/1:0:0:0/block/sr0
+	 *
+	 */
+	if (dm_snprintf(path, len, "%s/%s", sysfs_dir,
+			"subsystem/block/devices") >= 0) {
+		if (!stat(path, &info)) {
+			*sysfs_depth = 0;
+			return 1;
+		}
+	}
+
+	/*
+	 * block subsystem as a class
+	 *
+	 * /sys/class/block
+	 * |-- sda -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda
+	 * |-- sda1 -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1
+	 *  `-- sr0 -> ../../devices/pci0000:00/0000:00:1f.2/host1/target1:0:0/1:0:0:0/block/sr0
+	 *
+	 */
+	if (dm_snprintf(path, len, "%s/%s", sysfs_dir, "class/block") >= 0) {
+		if (!stat(path, &info)) {
+			*sysfs_depth = 0;
+			return 1;
+		}
+	}
+
+	/*
+	 * old block subsystem layout with nested directories
+	 *
+	 * /sys/block/
+	 * |-- sda
+	 * |   |-- capability
+	 * |   |-- dev
+	 * ...
+	 * |   |-- sda1
+	 * |   |   |-- dev
+	 * ...
+	 * |
+	 * `-- sr0
+	 *     |-- capability
+	 *     |-- dev
+	 * ...
+	 *
+	 */
+	if (dm_snprintf(path, len, "%s/%s", sysfs_dir, "block") >= 0) {
+		if (!stat(path, &info)) {
+			*sysfs_depth = 1;
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+/*----------------------------------------------------------------
+ * We need to store a set of dev_t.
+ *--------------------------------------------------------------*/
+struct entry {
+	struct entry *next;
+	dev_t dev;
+};
+
+#define SET_BUCKETS 64
+struct dev_set {
+	struct dm_pool *mem;
+	const char *sys_block;
+	unsigned sysfs_depth;
+	int initialised;
+	struct entry *slots[SET_BUCKETS];
+};
+
+static struct dev_set *_dev_set_create(struct dm_pool *mem,
+				       const char *sys_block,
+				       unsigned sysfs_depth)
+{
+	struct dev_set *ds;
+
+	if (!(ds = dm_pool_zalloc(mem, sizeof(*ds))))
+		return NULL;
+
+	ds->mem = mem;
+	ds->sys_block = dm_pool_strdup(mem, sys_block);
+	ds->sysfs_depth = sysfs_depth;
+	ds->initialised = 0;
+
+	return ds;
+}
+
+static unsigned _hash_dev(dev_t dev)
+{
+	return (major(dev) ^ minor(dev)) & (SET_BUCKETS - 1);
+}
+
+/*
+ * Doesn't check that the set already contains dev.
+ */
+static int _set_insert(struct dev_set *ds, dev_t dev)
+{
+	struct entry *e;
+	unsigned h = _hash_dev(dev);
+
+	if (!(e = dm_pool_alloc(ds->mem, sizeof(*e))))
+		return 0;
+
+	e->next = ds->slots[h];
+	e->dev = dev;
+	ds->slots[h] = e;
+
+	return 1;
+}
+
+static int _set_lookup(struct dev_set *ds, dev_t dev)
+{
+	unsigned h = _hash_dev(dev);
+	struct entry *e;
+
+	for (e = ds->slots[h]; e; e = e->next)
+		if (e->dev == dev)
+			return 1;
+
+	return 0;
+}
+
+/*----------------------------------------------------------------
+ * filter methods
+ *--------------------------------------------------------------*/
+static int _parse_dev(const char *file, FILE *fp, dev_t *result)
+{
+	unsigned major, minor;
+	char buffer[64];
+
+	if (!fgets(buffer, sizeof(buffer), fp)) {
+		log_error("Empty sysfs device file: %s", file);
+		return 0;
+	}
+
+	if (sscanf(buffer, "%u:%u", &major, &minor) != 2) {
+		log_info("sysfs device file not correct format");
+		return 0;
+	}
+
+	*result = makedev(major, minor);
+	return 1;
+}
+
+static int _read_dev(const char *file, dev_t *result)
+{
+	int r;
+	FILE *fp;
+
+	if (!(fp = fopen(file, "r"))) {
+		log_sys_error("fopen", file);
+		return 0;
+	}
+
+	r = _parse_dev(file, fp, result);
+
+	if (fclose(fp))
+		log_sys_error("fclose", file);
+
+	return r;
+}
+
+/*
+ * Recurse through sysfs directories, inserting any devs found.
+ */
+static int _read_devs(struct dev_set *ds, const char *dir, unsigned sysfs_depth)
+{
+	struct dirent *d;
+	DIR *dr;
+	struct stat info;
+	char path[PATH_MAX];
+	char file[PATH_MAX];
+	dev_t dev = { 0 };
+	int r = 1;
+
+	if (!(dr = opendir(dir))) {
+		log_sys_error("opendir", dir);
+		return 0;
+	}
+
+	while ((d = readdir(dr))) {
+		if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
+			continue;
+
+		if (dm_snprintf(path, sizeof(path), "%s/%s", dir,
+				 d->d_name) < 0) {
+			log_error("sysfs path name too long: %s in %s",
+				  d->d_name, dir);
+			continue;
+		}
+
+		/* devices have a "dev" file */
+		if (dm_snprintf(file, sizeof(file), "%s/dev", path) < 0) {
+			log_error("sysfs path name too long: %s in %s",
+				  d->d_name, dir);
+			continue;
+		}
+
+		if (!stat(file, &info)) {
+			/* recurse if we found a device and expect subdirs */
+			if (sysfs_depth)
+				_read_devs(ds, path, sysfs_depth - 1);
+
+			/* add the device we have found */
+			if (_read_dev(file, &dev))
+				_set_insert(ds, dev);
+		}
+	}
+
+	if (closedir(dr))
+		log_sys_error("closedir", dir);
+
+	return r;
+}
+
+static int _init_devs(struct dev_set *ds)
+{
+	if (!_read_devs(ds, ds->sys_block, ds->sysfs_depth)) {
+		ds->initialised = -1;
+		return 0;
+	}
+
+	ds->initialised = 1;
+
+	return 1;
+}
+
+
+static int _accept_p(struct dev_filter *f, struct device *dev)
+{
+	struct dev_set *ds = (struct dev_set *) f->private;
+
+	if (!ds->initialised)
+		_init_devs(ds);
+
+	/* Pass through if initialisation failed */
+	if (ds->initialised != 1)
+		return 1;
+
+	if (!_set_lookup(ds, dev->dev)) {
+		log_debug("%s: Skipping (sysfs)", dev_name(dev));
+		return 0;
+	} else
+		return 1;
+}
+
+static void _destroy(struct dev_filter *f)
+{
+	struct dev_set *ds = (struct dev_set *) f->private;
+	dm_pool_destroy(ds->mem);
+}
+
+struct dev_filter *sysfs_filter_create(const char *sysfs_dir)
+{
+	char sys_block[PATH_MAX];
+	unsigned sysfs_depth;
+	struct dm_pool *mem;
+	struct dev_set *ds;
+	struct dev_filter *f;
+
+	if (!*sysfs_dir) {
+		log_verbose("No proc filesystem found: skipping sysfs filter");
+		return NULL;
+	}
+
+	if (!_locate_sysfs_blocks(sysfs_dir, sys_block, sizeof(sys_block), &sysfs_depth))
+		return NULL;
+
+	if (!(mem = dm_pool_create("sysfs", 256))) {
+		log_error("sysfs pool creation failed");
+		return NULL;
+	}
+
+	if (!(ds = _dev_set_create(mem, sys_block, sysfs_depth))) {
+		log_error("sysfs dev_set creation failed");
+		goto bad;
+	}
+
+	if (!(f = dm_pool_zalloc(mem, sizeof(*f))))
+		goto_bad;
+
+	f->passes_filter = _accept_p;
+	f->destroy = _destroy;
+	f->private = ds;
+	return f;
+
+ bad:
+	dm_pool_destroy(mem);
+	return NULL;
+}
+
+#else
+
+struct dev_filter *sysfs_filter_create(const char *sysfs_dir __attribute((unused)))
+{
+	return NULL;
+}
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/filters/filter-sysfs.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/filters/filter-sysfs.h
diff -N src/external/gpl2/lvm2tools/dist/lib/filters/filter-sysfs.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/filters/filter-sysfs.h	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,25 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_FILTER_SYSFS_H
+#define _LVM_FILTER_SYSFS_H
+
+#include "config.h"
+#include "dev-cache.h"
+
+struct dev_filter *sysfs_filter_create(const char *sysfs_dir);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/filters/filter.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/filters/filter.c
diff -N src/external/gpl2/lvm2tools/dist/lib/filters/filter.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/filters/filter.c	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,294 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "dev-cache.h"
+#include "filter.h"
+#include "lvm-string.h"
+#include "config.h"
+#include "metadata.h"
+#include "activate.h"
+
+#include <dirent.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <limits.h>
+
+#define NUMBER_OF_MAJORS 4096
+
+/* 0 means LVM won't use this major number. */
+static int _max_partitions_by_major[NUMBER_OF_MAJORS];
+
+typedef struct {
+	const char *name;
+	const int max_partitions;
+} device_info_t;
+
+static int _md_major = -1;
+static int _device_mapper_major = -1;
+
+int md_major(void)
+{
+	return _md_major;
+}
+
+/*
+ * Devices are only checked for partition tables if their minor number
+ * is a multiple of the number corresponding to their type below
+ * i.e. this gives the granularity of whole-device minor numbers.
+ * Use 1 if the device is not partitionable.
+ *
+ * The list can be supplemented with devices/types in the config file.
+ */
+static const device_info_t device_info[] = {
+	{"ide", 64},		/* IDE disk */
+	{"sd", 16},		/* SCSI disk */
+	{"md", 1},		/* Multiple Disk driver (SoftRAID) */
+	{"loop", 1},		/* Loop device */
+	{"dasd", 4},		/* DASD disk (IBM S/390, zSeries) */
+	{"dac960", 8},		/* DAC960 */
+	{"nbd", 16},		/* Network Block Device */
+	{"ida", 16},		/* Compaq SMART2 */
+	{"cciss", 16},		/* Compaq CCISS array */
+	{"ubd", 16},		/* User-mode virtual block device */
+	{"ataraid", 16},	/* ATA Raid */
+	{"drbd", 16},		/* Distributed Replicated Block Device */
+	{"emcpower", 16},	/* EMC Powerpath */
+	{"power2", 16},		/* EMC Powerpath */
+	{"i2o_block", 16},	/* i2o Block Disk */
+	{"iseries/vd", 8},	/* iSeries disks */
+	{"gnbd", 1},		/* Network block device */
+	{"ramdisk", 1},		/* RAM disk */
+	{"aoe", 16},		/* ATA over Ethernet */
+	{"device-mapper", 1},	/* Other mapped devices */
+	{"xvd", 16},		/* Xen virtual block device */
+	{"vdisk", 8},		/* SUN's LDOM virtual block device */
+	{"ps3disk", 16},	/* PlayStation 3 internal disk */
+	{"virtblk", 8},		/* VirtIO disk */
+	{NULL, 0}
+};
+
+static int _passes_lvm_type_device_filter(struct dev_filter *f __attribute((unused)),
+					  struct device *dev)
+{
+	const char *name = dev_name(dev);
+	int ret = 0;
+	uint64_t size;
+
+	/* Is this a recognised device type? */
+	if (!_max_partitions_by_major[MAJOR(dev->dev)]) {
+		log_debug("%s: Skipping: Unrecognised LVM device type %"
+			  PRIu64, name, (uint64_t) MAJOR(dev->dev));
+		return 0;
+	}
+
+	/* Skip suspended devices */
+	if (MAJOR(dev->dev) == _device_mapper_major &&
+	    ignore_suspended_devices() && !device_is_usable(dev->dev)) {
+		log_debug("%s: Skipping: Suspended dm device", name);
+		return 0;
+	}
+
+	/* Check it's accessible */
+	if (!dev_open_flags(dev, O_RDONLY, 0, 1)) {
+		log_debug("%s: Skipping: open failed", name);
+		return 0;
+	}
+	
+	/* Check it's not too small */
+	if (!dev_get_size(dev, &size)) {
+		log_debug("%s: Skipping: dev_get_size failed", name);
+		goto out;
+	}
+
+	if (size < PV_MIN_SIZE) {
+		log_debug("%s: Skipping: Too small to hold a PV", name);
+		goto out;
+	}
+
+	if (is_partitioned_dev(dev)) {
+		log_debug("%s: Skipping: Partition table signature found",
+			  name);
+		goto out;
+	}
+
+	ret = 1;
+
+      out:
+	dev_close(dev);
+
+	return ret;
+}
+
+static int _scan_proc_dev(const char *proc, const struct config_node *cn)
+{
+	char line[80];
+	char proc_devices[PATH_MAX];
+	FILE *pd = NULL;
+	int i, j = 0;
+	int line_maj = 0;
+	int blocksection = 0;
+	size_t dev_len = 0;
+	struct config_value *cv;
+	char *name;
+
+
+	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 1;
+	}
+
+	/* All types unrecognised initially */
+	memset(_max_partitions_by_major, 0, sizeof(int) * NUMBER_OF_MAJORS);
+
+	if (dm_snprintf(proc_devices, sizeof(proc_devices),
+			 "%s/devices", proc) < 0) {
+		log_error("Failed to create /proc/devices string");
+		return 0;
+	}
+
+	if (!(pd = fopen(proc_devices, "r"))) {
+		log_sys_error("fopen", proc_devices);
+		return 0;
+	}
+
+	while (fgets(line, 80, pd) != NULL) {
+		i = 0;
+		while (line[i] == ' ' && line[i] != '\0')
+			i++;
+
+		/* If it's not a number it may be name of section */
+		line_maj = atoi(((char *) (line + i)));
+		if (!line_maj) {
+			blocksection = (line[i] == 'B') ? 1 : 0;
+			continue;
+		}
+
+		/* We only want block devices ... */
+		if (!blocksection)
+			continue;
+
+		/* Find the start of the device major name */
+		while (line[i] != ' ' && line[i] != '\0')
+			i++;
+		while (line[i] == ' ' && line[i] != '\0')
+			i++;
+
+		/* Look for md device */
+		if (!strncmp("md", line + i, 2) && isspace(*(line + i + 2)))
+			_md_major = line_maj;
+
+		/* Look for device-mapper device */
+		/* FIXME Cope with multiple majors */
+		if (!strncmp("device-mapper", line + i, 13) && isspace(*(line + i + 13)))
+			_device_mapper_major = line_maj;
+
+		/* Go through the valid device names and if there is a
+		   match store max number of partitions */
+		for (j = 0; device_info[j].name != NULL; j++) {
+			dev_len = strlen(device_info[j].name);
+			if (dev_len <= strlen(line + i) &&
+			    !strncmp(device_info[j].name, line + i, dev_len) &&
+			    (line_maj < NUMBER_OF_MAJORS)) {
+				_max_partitions_by_major[line_maj] =
+				    device_info[j].max_partitions;
+				break;
+			}
+		}
+
+		if (!cn)
+			continue;
+
+		/* Check devices/types for local variations */
+		for (cv = cn->v; cv; cv = cv->next) {
+			if (cv->type != CFG_STRING) {
+				log_error("Expecting string in devices/types "
+					  "in config file");
+				if (fclose(pd))
+					log_sys_error("fclose", proc_devices);
+				return 0;
+			}
+			dev_len = strlen(cv->v.str);
+			name = cv->v.str;
+			cv = cv->next;
+			if (!cv || cv->type != CFG_INT) {
+				log_error("Max partition count missing for %s "
+					  "in devices/types in config file",
+					  name);
+				if (fclose(pd))
+					log_sys_error("fclose", proc_devices);
+				return 0;
+			}
+			if (!cv->v.i) {
+				log_error("Zero partition count invalid for "
+					  "%s in devices/types in config file",
+					  name);
+				if (fclose(pd))
+					log_sys_error("fclose", proc_devices);
+				return 0;
+			}
+			if (dev_len <= strlen(line + i) &&
+			    !strncmp(name, line + i, dev_len) &&
+			    (line_maj < NUMBER_OF_MAJORS)) {
+				_max_partitions_by_major[line_maj] = cv->v.i;
+				break;
+			}
+		}
+	}
+
+	if (fclose(pd))
+		log_sys_error("fclose", proc_devices);
+
+	return 1;
+}
+
+int max_partitions(int major)
+{
+	return _max_partitions_by_major[major];
+}
+
+struct dev_filter *lvm_type_filter_create(const char *proc,
+					  const struct config_node *cn)
+{
+	struct dev_filter *f;
+
+	if (!(f = dm_malloc(sizeof(struct dev_filter)))) {
+		log_error("LVM type filter allocation failed");
+		return NULL;
+	}
+
+	f->passes_filter = _passes_lvm_type_device_filter;
+	f->destroy = lvm_type_filter_destroy;
+	f->private = NULL;
+
+	if (!_scan_proc_dev(proc, cn)) {
+		dm_free(f);
+		return_NULL;
+	}
+
+	return f;
+}
+
+void lvm_type_filter_destroy(struct dev_filter *f)
+{
+	dm_free(f);
+	return;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/filters/filter.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/filters/filter.h
diff -N src/external/gpl2/lvm2tools/dist/lib/filters/filter.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/filters/filter.h	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,43 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_FILTER_H
+#define _LVM_FILTER_H
+
+#include "config.h"
+
+#include <sys/stat.h>
+
+#ifdef linux
+#  define MAJOR(dev)	((dev & 0xfff00) >> 8)
+#  define MINOR(dev)	((dev & 0xff) | ((dev >> 12) & 0xfff00))
+#  define MKDEV(ma,mi)	((mi & 0xff) | (ma << 8) | ((mi & ~0xff) << 12))
+#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,
+					  const struct config_node *cn);
+
+void lvm_type_filter_destroy(struct dev_filter *f);
+
+int md_major(void);
+int max_partitions(int major);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/filters/filter_netbsd.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/filters/filter_netbsd.c
diff -N src/external/gpl2/lvm2tools/dist/lib/filters/filter_netbsd.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/filters/filter_netbsd.c	2 Dec 2008 17:29:03 -0000	1.1.2.2
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2008 Adam Hamsik. All rights reserved. 
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "dev-cache.h"
+#include "filter.h"
+#include "lvm-string.h"
+#include "config.h"
+#include "metadata.h"
+#include "activate.h"
+
+#include <sys/sysctl.h>
+
+#include <ctype.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+
+#define NUMBER_OF_MAJORS 4096
+
+#define LVM_SUCCESS 1
+#define LVM_FAILURE 0
+
+/* -1 means LVM won't use this major number. */
+static int _char_device_major[NUMBER_OF_MAJORS];
+static int _block_device_major[NUMBER_OF_MAJORS];
+
+typedef struct {
+	const char *name;
+	const int max_partitions;
+} device_info_t;
+
+static int _md_major = -1;
+static int _device_mapper_major = -1;
+
+int md_major(void)
+{
+	return _md_major;
+}
+
+/*
+ * Devices are only checked for partition tables if their minor number
+ * is a multiple of the number corresponding to their type below
+ * i.e. this gives the granularity of whole-device minor numbers.
+ * Use 1 if the device is not partitionable.
+ *
+ * The list can be supplemented with devices/types in the config file.
+ */
+static const device_info_t device_info[] = {
+	{"wd", 64},
+	{"sd", 64},	
+	{"dk", 1},
+	{"wd", 64},	
+	{"vnd", 1},
+	{"raid", 64},
+	{"cgd", 1},
+	{"ccd", 1},	
+	{NULL, -1}
+};
+
+/*
+ * Test if device passes filter tests and can be inserted in to cache.
+ */
+static int _passes_lvm_type_device_filter(struct dev_filter *f __attribute((unused)),
+					  struct device *dev)
+{
+	const char *name = dev_name(dev);
+	int ret = 0;
+	uint64_t size;
+
+	/* Is this a recognised device type? */
+	if (_char_device_major[MAJOR(dev->dev)] == -1 ){
+		log_debug("%s: Skipping: Unrecognised LVM device type %"
+				  PRIu64, name, (uint64_t) MAJOR(dev->dev));
+		return LVM_FAILURE;
+	}
+
+	/* Skip suspended devices */
+	if (MAJOR(dev->dev) == _device_mapper_major &&
+	    ignore_suspended_devices() && !device_is_usable(dev->dev)) {
+		log_debug("%s: Skipping: Suspended dm device", name);
+		return LVM_FAILURE;
+	}
+	
+	/* Check it's accessible */
+	if (!dev_open_flags(dev, O_RDONLY, 0, 1)) {
+		log_debug("%s: Skipping: open failed", name);
+		return LVM_FAILURE;
+	}
+
+	/* Check it's not too small */
+	if (!dev_get_size(dev, &size)) {
+	       	log_debug("%s: Skipping: dev_get_size failed", name);
+		goto out;
+	}
+	
+	if (size < PV_MIN_SIZE) {
+		log_debug("%s: Skipping: Too small to hold a PV", name);
+		goto out;
+	}
+
+	if (is_partitioned_dev(dev)) {
+		log_debug("%s: Skipping: Partition table signature found",
+			  name);
+		goto out;
+	}
+
+	ret = LVM_SUCCESS;
+
+      out:
+	dev_close(dev);
+
+	return ret;
+}
+
+static int _scan_dev(const struct config_node *cn)
+{
+	size_t val_len,i,j;
+	char *name;
+
+	struct kinfo_drivers *kd;
+	struct config_value *cv;
+	
+	/* All types unrecognised initially */
+	memset(_char_device_major, -1, sizeof(int) * NUMBER_OF_MAJORS);
+	memset(_block_device_major, -1, sizeof(int) * NUMBER_OF_MAJORS);
+
+	/* get size kernel drivers array from kernel*/
+	if (sysctlbyname("kern.drivers", NULL, &val_len, NULL, 0) < 0) {
+		printf("sysctlbyname failed");
+		return LVM_FAILURE;
+	}
+	
+	if ((kd = malloc(val_len)) == NULL){
+		printf("malloc kd info error\n");
+		return LVM_FAILURE;
+	}
+
+	/* get array from kernel */
+	if (sysctlbyname("kern.drivers", kd, &val_len, NULL, 0) < 0) {
+		printf("sysctlbyname failed kd");
+		return LVM_FAILURE;
+	}
+
+	for (i = 0, val_len /= sizeof(*kd); i < val_len; i++) {
+
+		if (!strncmp("device-mapper", kd[i].d_name, 13) ||
+		    !strncmp("dm", kd[i].d_name, 2))
+			_device_mapper_major = kd[i].d_bmajor;
+
+		/* We select only devices with correct char/block major number. */
+		if (kd[i].d_cmajor != -1 && kd[i].d_bmajor != -1) {
+			/* Go through the valid device names and if there is a
+			   match store max number of partitions */
+			for (j = 0; device_info[j].name != NULL; j++){
+				if (!strcmp(device_info[j].name, kd[i].d_name)){
+					_char_device_major[kd[i].d_cmajor] =
+					    device_info[j].max_partitions;
+					_block_device_major[kd[i].d_bmajor] =
+					    device_info[j].max_partitions;
+					break;
+				}
+			}
+		}
+		
+		if (!cn)
+			continue;
+
+		/* Check devices/types for local variations */
+		for (cv = cn->v; cv; cv = cv->next) {
+			if (cv->type != CFG_STRING) {
+				log_error("Expecting string in devices/types "
+					  "in config file");
+				free(kd);
+				return LVM_FAILURE;
+			}
+
+			name = cv->v.str;
+			cv = cv->next;
+			if (!cv || cv->type != CFG_INT) {
+				log_error("Max partition count missing for %s "
+					  "in devices/types in config file",
+					  name);
+				free(kd);
+				return LVM_FAILURE;
+			}
+			if (!cv->v.i) {
+				log_error("Zero partition count invalid for "
+					  "%s in devices/types in config file",
+					  name);
+				free(kd);
+				return LVM_FAILURE;
+			}
+			
+			if (!strncmp(name, kd[i].d_name, strlen(name))){
+					_char_device_major[kd[i].d_cmajor] =
+					    device_info[j].max_partitions;
+					_block_device_major[kd[i].d_bmajor] =
+					    device_info[j].max_partitions;
+					break;
+			}
+		}
+	}
+
+	free(kd);
+
+	return LVM_SUCCESS;
+}
+
+int max_partitions(int major)
+{
+	return _char_device_major[major];
+}
+
+struct dev_filter *lvm_type_filter_create(const char *proc,
+					  const struct config_node *cn)
+{
+	struct dev_filter *f;
+
+	if (!(f = dm_malloc(sizeof(struct dev_filter)))) {
+		log_error("LVM type filter allocation failed");
+		return NULL;
+	}
+
+	f->passes_filter = _passes_lvm_type_device_filter;
+	f->destroy = lvm_type_filter_destroy;
+	f->private = NULL;
+
+	if (!_scan_dev(cn)) {
+		dm_free(f);
+		return_NULL;
+	}
+
+	return f;
+}
+
+void lvm_type_filter_destroy(struct dev_filter *f)
+{
+	dm_free(f);
+	return;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/format1/.exported_symbols
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format1/.exported_symbols
diff -N src/external/gpl2/lvm2tools/dist/lib/format1/.exported_symbols
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format1/.exported_symbols	15 Jul 2008 13:49:32 -0000	1.1.1.1
@@ -0,0 +1 @@
+init_format
Index: src/external/gpl2/lvm2tools/dist/lib/format1/Makefile.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format1/Makefile.in
diff -N src/external/gpl2/lvm2tools/dist/lib/format1/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format1/Makefile.in	12 Dec 2008 16:32:59 -0000	1.1.1.1.2.1
@@ -0,0 +1,37 @@
+#
+# Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+SOURCES =\
+	disk-rep.c \
+	format1.c \
+	import-export.c \
+	import-extents.c \
+	layout.c \
+	lvm1-label.c \
+	vg_number.c
+
+LIB_SHARED = liblvm2format1.so
+LIB_VERSION = $(LIB_VERSION_LVM)
+
+include $(top_srcdir)/make.tmpl
+
+install: liblvm2format1.so
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
+		$(libdir)/liblvm2format1.so.$(LIB_VERSION)
+	$(LN_S) -f liblvm2format1.so.$(LIB_VERSION) $(libdir)/liblvm2format1.so
+
Index: src/external/gpl2/lvm2tools/dist/lib/format1/disk-rep.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format1/disk-rep.c
diff -N src/external/gpl2/lvm2tools/dist/lib/format1/disk-rep.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format1/disk-rep.c	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,737 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "disk-rep.h"
+#include "xlate.h"
+#include "filter.h"
+#include "lvmcache.h"
+
+#include <fcntl.h>
+
+#define xx16(v) disk->v = xlate16(disk->v)
+#define xx32(v) disk->v = xlate32(disk->v)
+#define xx64(v) disk->v = xlate64(disk->v)
+
+/*
+ * Functions to perform the endian conversion
+ * between disk and core.  The same code works
+ * both ways of course.
+ */
+static void _xlate_pvd(struct pv_disk *disk)
+{
+	xx16(version);
+
+	xx32(pv_on_disk.base);
+	xx32(pv_on_disk.size);
+	xx32(vg_on_disk.base);
+	xx32(vg_on_disk.size);
+	xx32(pv_uuidlist_on_disk.base);
+	xx32(pv_uuidlist_on_disk.size);
+	xx32(lv_on_disk.base);
+	xx32(lv_on_disk.size);
+	xx32(pe_on_disk.base);
+	xx32(pe_on_disk.size);
+
+	xx32(pv_major);
+	xx32(pv_number);
+	xx32(pv_status);
+	xx32(pv_allocatable);
+	xx32(pv_size);
+	xx32(lv_cur);
+	xx32(pe_size);
+	xx32(pe_total);
+	xx32(pe_allocated);
+	xx32(pe_start);
+}
+
+static void _xlate_lvd(struct lv_disk *disk)
+{
+	xx32(lv_access);
+	xx32(lv_status);
+	xx32(lv_open);
+	xx32(lv_dev);
+	xx32(lv_number);
+	xx32(lv_mirror_copies);
+	xx32(lv_recovery);
+	xx32(lv_schedule);
+	xx32(lv_size);
+	xx32(lv_snapshot_minor);
+	xx16(lv_chunk_size);
+	xx16(dummy);
+	xx32(lv_allocated_le);
+	xx32(lv_stripes);
+	xx32(lv_stripesize);
+	xx32(lv_badblock);
+	xx32(lv_allocation);
+	xx32(lv_io_timeout);
+	xx32(lv_read_ahead);
+}
+
+static void _xlate_vgd(struct vg_disk *disk)
+{
+	xx32(vg_number);
+	xx32(vg_access);
+	xx32(vg_status);
+	xx32(lv_max);
+	xx32(lv_cur);
+	xx32(lv_open);
+	xx32(pv_max);
+	xx32(pv_cur);
+	xx32(pv_act);
+	xx32(dummy);
+	xx32(vgda);
+	xx32(pe_size);
+	xx32(pe_total);
+	xx32(pe_allocated);
+	xx32(pvg_total);
+}
+
+static void _xlate_extents(struct pe_disk *extents, uint32_t count)
+{
+	unsigned i;
+
+	for (i = 0; i < count; i++) {
+		extents[i].lv_num = xlate16(extents[i].lv_num);
+		extents[i].le_num = xlate16(extents[i].le_num);
+	}
+}
+
+/*
+ * Handle both minor metadata formats.
+ */
+static int _munge_formats(struct pv_disk *pvd)
+{
+	uint32_t pe_start;
+	unsigned b, e;
+
+	switch (pvd->version) {
+	case 1:
+		pvd->pe_start = ((pvd->pe_on_disk.base +
+				  pvd->pe_on_disk.size) >> SECTOR_SHIFT);
+		break;
+
+	case 2:
+		pvd->version = 1;
+		pe_start = pvd->pe_start << SECTOR_SHIFT;
+		pvd->pe_on_disk.size = pe_start - pvd->pe_on_disk.base;
+		break;
+
+	default:
+		return 0;
+	}
+
+	/* UUID too long? */
+	if (pvd->pv_uuid[ID_LEN]) {
+		/* Retain ID_LEN chars from end */
+		for (e = ID_LEN; e < sizeof(pvd->pv_uuid); e++) {
+			if (!pvd->pv_uuid[e]) {
+				e--;
+				break;
+			}
+		}
+		for (b = 0; b < ID_LEN; b++) {
+			pvd->pv_uuid[b] = pvd->pv_uuid[++e - ID_LEN];
+			/* FIXME Remove all invalid chars */
+			if (pvd->pv_uuid[b] == '/')
+				pvd->pv_uuid[b] = '#';
+		}
+		memset(&pvd->pv_uuid[ID_LEN], 0, sizeof(pvd->pv_uuid) - ID_LEN);
+	}
+
+	/* If UUID is missing, create one */
+	if (pvd->pv_uuid[0] == '\0') {
+		uuid_from_num((char *)pvd->pv_uuid, pvd->pv_number);
+		pvd->pv_uuid[ID_LEN] = '\0';
+	}
+
+	return 1;
+}
+
+/*
+ * If exported, remove "PV_EXP" from end of VG name
+ */
+static void _munge_exported_vg(struct pv_disk *pvd)
+{
+	int l;
+	size_t s;
+
+	/* Return if PV not in a VG */
+	if ((!*pvd->vg_name))
+		return;
+	/* FIXME also check vgd->status & VG_EXPORTED? */
+
+	l = strlen((char *)pvd->vg_name);
+	s = sizeof(EXPORTED_TAG);
+	if (!strncmp((char *)pvd->vg_name + l - s + 1, EXPORTED_TAG, s)) {
+		pvd->vg_name[l - s + 1] = '\0';
+		pvd->pv_status |= VG_EXPORTED;
+	}
+}
+
+int munge_pvd(struct device *dev, struct pv_disk *pvd)
+{
+	_xlate_pvd(pvd);
+
+	if (pvd->id[0] != 'H' || pvd->id[1] != 'M') {
+		log_very_verbose("%s does not have a valid LVM1 PV identifier",
+				 dev_name(dev));
+		return 0;
+	}
+
+	if (!_munge_formats(pvd)) {
+		log_very_verbose("format1: Unknown metadata version %d "
+				 "found on %s", pvd->version, dev_name(dev));
+		return 0;
+	}
+
+	/* If VG is exported, set VG name back to the real name */
+	_munge_exported_vg(pvd);
+
+	return 1;
+}
+
+static int _read_pvd(struct device *dev, struct pv_disk *pvd)
+{
+	if (!dev_read(dev, UINT64_C(0), sizeof(*pvd), pvd)) {
+		log_very_verbose("Failed to read PV data from %s",
+				 dev_name(dev));
+		return 0;
+	}
+
+	return munge_pvd(dev, pvd);
+}
+
+static int _read_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
+{
+	if (!dev_read(dev, pos, sizeof(*disk), disk))
+		return_0;
+
+	_xlate_lvd(disk);
+
+	return 1;
+}
+
+int read_vgd(struct device *dev, struct vg_disk *vgd, struct pv_disk *pvd)
+{
+	uint64_t pos = pvd->vg_on_disk.base;
+
+	if (!dev_read(dev, pos, sizeof(*vgd), vgd))
+		return_0;
+
+	_xlate_vgd(vgd);
+
+	if ((vgd->lv_max > MAX_LV) || (vgd->pv_max > MAX_PV))
+		return_0;
+		
+	/* If UUID is missing, create one */
+	if (vgd->vg_uuid[0] == '\0')
+		uuid_from_num((char *)vgd->vg_uuid, vgd->vg_number);
+
+	return 1;
+}
+
+static int _read_uuids(struct disk_list *data)
+{
+	unsigned num_read = 0;
+	struct uuid_list *ul;
+	char buffer[NAME_LEN] __attribute((aligned(8)));
+	uint64_t pos = data->pvd.pv_uuidlist_on_disk.base;
+	uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size;
+
+	while (pos < end && num_read < data->vgd.pv_cur) {
+		if (!dev_read(data->dev, pos, sizeof(buffer), buffer))
+			return_0;
+
+		if (!(ul = dm_pool_alloc(data->mem, sizeof(*ul))))
+			return_0;
+
+		memcpy(ul->uuid, buffer, NAME_LEN);
+		ul->uuid[NAME_LEN - 1] = '\0';
+
+		dm_list_add(&data->uuids, &ul->list);
+
+		pos += NAME_LEN;
+		num_read++;
+	}
+
+	return 1;
+}
+
+static int _check_lvd(struct lv_disk *lvd)
+{
+	return !(lvd->lv_name[0] == '\0');
+}
+
+static int _read_lvs(struct disk_list *data)
+{
+	unsigned int i, lvs_read = 0;
+	uint64_t pos;
+	struct lvd_list *ll;
+	struct vg_disk *vgd = &data->vgd;
+
+	for (i = 0; (i < vgd->lv_max) && (lvs_read < vgd->lv_cur); i++) {
+		pos = data->pvd.lv_on_disk.base + (i * sizeof(struct lv_disk));
+		ll = dm_pool_alloc(data->mem, sizeof(*ll));
+
+		if (!ll)
+			return_0;
+
+		if (!_read_lvd(data->dev, pos, &ll->lvd))
+			return_0;
+
+		if (!_check_lvd(&ll->lvd))
+			continue;
+
+		lvs_read++;
+		dm_list_add(&data->lvds, &ll->list);
+	}
+
+	return 1;
+}
+
+static int _read_extents(struct disk_list *data)
+{
+	size_t len = sizeof(struct pe_disk) * data->pvd.pe_total;
+	struct pe_disk *extents = dm_pool_alloc(data->mem, len);
+	uint64_t pos = data->pvd.pe_on_disk.base;
+
+	if (!extents)
+		return_0;
+
+	if (!dev_read(data->dev, pos, len, extents))
+		return_0;
+
+	_xlate_extents(extents, data->pvd.pe_total);
+	data->extents = extents;
+
+	return 1;
+}
+
+static void __update_lvmcache(const struct format_type *fmt,
+			      struct disk_list *dl,
+			      struct device *dev, const char *vgid,
+			      unsigned exported)
+{
+	struct lvmcache_info *info;
+	const char *vgname = *((char *)dl->pvd.vg_name) ?
+			     (char *)dl->pvd.vg_name : fmt->orphan_vg_name;
+
+	if (!(info = lvmcache_add(fmt->labeller, (char *)dl->pvd.pv_uuid, dev,
+				  vgname, vgid, exported ? EXPORTED_VG : 0))) {
+		stack;
+		return;
+	}
+
+	info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT;
+	dm_list_init(&info->mdas);
+	info->status &= ~CACHE_INVALID;
+}
+
+static struct disk_list *__read_disk(const struct format_type *fmt,
+				     struct device *dev, struct dm_pool *mem,
+				     const char *vg_name)
+{
+	struct disk_list *dl = dm_pool_zalloc(mem, sizeof(*dl));
+	const char *name = dev_name(dev);
+
+	if (!dl)
+		return_NULL;
+
+	dl->dev = dev;
+	dl->mem = mem;
+	dm_list_init(&dl->uuids);
+	dm_list_init(&dl->lvds);
+
+	if (!_read_pvd(dev, &dl->pvd))
+		goto_bad;
+
+	/*
+	 * is it an orphan ?
+	 */
+	if (!*dl->pvd.vg_name) {
+		log_very_verbose("%s is not a member of any format1 VG", name);
+
+		__update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
+		return (vg_name) ? NULL : dl;
+	}
+
+	if (!read_vgd(dl->dev, &dl->vgd, &dl->pvd)) {
+		log_error("Failed to read VG data from PV (%s)", name);
+		__update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
+		goto bad;
+	}
+
+	if (vg_name && strcmp(vg_name, (char *)dl->pvd.vg_name)) {
+		log_very_verbose("%s is not a member of the VG %s",
+				 name, vg_name);
+		__update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
+		goto bad;
+	}
+
+	__update_lvmcache(fmt, dl, dev, (char *)dl->vgd.vg_uuid,
+			  dl->vgd.vg_status & VG_EXPORTED);
+
+	if (!_read_uuids(dl)) {
+		log_error("Failed to read PV uuid list from %s", name);
+		goto bad;
+	}
+
+	if (!_read_lvs(dl)) {
+		log_error("Failed to read LV's from %s", name);
+		goto bad;
+	}
+
+	if (!_read_extents(dl)) {
+		log_error("Failed to read extents from %s", name);
+		goto bad;
+	}
+
+	log_very_verbose("Found %s in %sVG %s", name,
+			 (dl->vgd.vg_status & VG_EXPORTED) ? "exported " : "",
+			 dl->pvd.vg_name);
+
+	return dl;
+
+      bad:
+	dm_pool_free(dl->mem, dl);
+	return NULL;
+}
+
+struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
+			    struct dm_pool *mem, const char *vg_name)
+{
+	struct disk_list *dl;
+
+	if (!dev_open(dev))
+		return_NULL;
+
+	dl = __read_disk(fmt, dev, mem, vg_name);
+
+	if (!dev_close(dev))
+		stack;
+
+	return dl;
+}
+
+static void _add_pv_to_list(struct dm_list *head, struct disk_list *data)
+{
+	struct pv_disk *pvd;
+	struct disk_list *diskl;
+
+	dm_list_iterate_items(diskl, head) {
+		pvd = &diskl->pvd;
+		if (!strncmp((char *)data->pvd.pv_uuid, (char *)pvd->pv_uuid,
+			     sizeof(pvd->pv_uuid))) {
+			if (MAJOR(data->dev->dev) != md_major()) {
+				log_very_verbose("Ignoring duplicate PV %s on "
+						 "%s", pvd->pv_uuid,
+						 dev_name(data->dev));
+				return;
+			}
+			log_very_verbose("Duplicate PV %s - using md %s",
+					 pvd->pv_uuid, dev_name(data->dev));
+			dm_list_del(&diskl->list);
+			break;
+		}
+	}
+	dm_list_add(head, &data->list);
+}
+
+/*
+ * Build a list of pv_d's structures, allocated from mem.
+ * We keep track of the first object allocated from the pool
+ * so we can free off all the memory if something goes wrong.
+ */
+int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
+		   struct dev_filter *filter, struct dm_pool *mem,
+		   struct dm_list *head)
+{
+	struct dev_iter *iter;
+	struct device *dev;
+	struct disk_list *data = NULL;
+	struct lvmcache_vginfo *vginfo;
+	struct lvmcache_info *info;
+
+	/* Fast path if we already saw this VG and cached the list of PVs */
+	if (vg_name && (vginfo = vginfo_from_vgname(vg_name, NULL)) &&
+	    vginfo->infos.n) {
+		dm_list_iterate_items(info, &vginfo->infos) {
+			dev = info->dev;
+			if (dev && !(data = read_disk(fmt, dev, mem, vg_name)))
+				break;
+			_add_pv_to_list(head, data);
+		}
+
+		/* Did we find the whole VG? */
+		if (!vg_name || is_orphan_vg(vg_name) ||
+		    (data && *data->pvd.vg_name &&
+		     dm_list_size(head) == data->vgd.pv_cur))
+			return 1;
+
+		/* Failed */
+		dm_list_init(head);
+		/* vgcache_del(vg_name); */
+	}
+
+	if (!(iter = dev_iter_create(filter, 1))) {
+		log_error("read_pvs_in_vg: dev_iter_create failed");
+		return 0;
+	}
+
+	/* Otherwise do a complete scan */
+	for (dev = dev_iter_get(iter); dev; dev = dev_iter_get(iter)) {
+		if ((data = read_disk(fmt, dev, mem, vg_name))) {
+			_add_pv_to_list(head, data);
+		}
+	}
+	dev_iter_destroy(iter);
+
+	if (dm_list_empty(head))
+		return 0;
+
+	return 1;
+}
+
+static int _write_vgd(struct disk_list *data)
+{
+	struct vg_disk *vgd = &data->vgd;
+	uint64_t pos = data->pvd.vg_on_disk.base;
+
+	log_debug("Writing %s VG metadata to %s at %" PRIu64 " len %" PRIsize_t,
+		  data->pvd.vg_name, dev_name(data->dev), pos, sizeof(*vgd));
+
+	_xlate_vgd(vgd);
+	if (!dev_write(data->dev, pos, sizeof(*vgd), vgd))
+		return_0;
+
+	_xlate_vgd(vgd);
+
+	return 1;
+}
+
+static int _write_uuids(struct disk_list *data)
+{
+	struct uuid_list *ul;
+	uint64_t pos = data->pvd.pv_uuidlist_on_disk.base;
+	uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size;
+
+	dm_list_iterate_items(ul, &data->uuids) {
+		if (pos >= end) {
+			log_error("Too many uuids to fit on %s",
+				  dev_name(data->dev));
+			return 0;
+		}
+
+		log_debug("Writing %s uuidlist to %s at %" PRIu64 " len %d",
+			  data->pvd.vg_name, dev_name(data->dev),
+			  pos, NAME_LEN);
+
+		if (!dev_write(data->dev, pos, NAME_LEN, ul->uuid))
+			return_0;
+
+		pos += NAME_LEN;
+	}
+
+	return 1;
+}
+
+static int _write_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
+{
+	log_debug("Writing %s LV %s metadata to %s at %" PRIu64 " len %"
+		  PRIsize_t, disk->vg_name, disk->lv_name, dev_name(dev),
+		  pos, sizeof(*disk));
+
+	_xlate_lvd(disk);
+	if (!dev_write(dev, pos, sizeof(*disk), disk))
+		return_0;
+
+	_xlate_lvd(disk);
+
+	return 1;
+}
+
+static int _write_lvs(struct disk_list *data)
+{
+	struct lvd_list *ll;
+	uint64_t pos, offset;
+
+	pos = data->pvd.lv_on_disk.base;
+
+	if (!dev_set(data->dev, pos, data->pvd.lv_on_disk.size, 0)) {
+		log_error("Couldn't zero lv area on device '%s'",
+			  dev_name(data->dev));
+		return 0;
+	}
+
+	dm_list_iterate_items(ll, &data->lvds) {
+		offset = sizeof(struct lv_disk) * ll->lvd.lv_number;
+		if (offset + sizeof(struct lv_disk) > data->pvd.lv_on_disk.size) {
+			log_error("lv_number %d too large", ll->lvd.lv_number);
+			return 0;
+		}
+
+		if (!_write_lvd(data->dev, pos + offset, &ll->lvd))
+			return_0;
+	}
+
+	return 1;
+}
+
+static int _write_extents(struct disk_list *data)
+{
+	size_t len = sizeof(struct pe_disk) * data->pvd.pe_total;
+	struct pe_disk *extents = data->extents;
+	uint64_t pos = data->pvd.pe_on_disk.base;
+
+	log_debug("Writing %s extents metadata to %s at %" PRIu64 " len %"
+		  PRIsize_t, data->pvd.vg_name, dev_name(data->dev),
+		  pos, len);
+
+	_xlate_extents(extents, data->pvd.pe_total);
+	if (!dev_write(data->dev, pos, len, extents))
+		return_0;
+
+	_xlate_extents(extents, data->pvd.pe_total);
+
+	return 1;
+}
+
+static int _write_pvd(struct disk_list *data)
+{
+	char *buf;
+	uint64_t pos = data->pvd.pv_on_disk.base;
+	size_t size = data->pvd.pv_on_disk.size;
+
+	if (size < sizeof(struct pv_disk)) {
+		log_error("Invalid PV structure size.");
+		return 0;
+	}
+
+	/* Make sure that the gap between the PV structure and
+	   the next one is zeroed in order to make non LVM tools
+	   happy (idea from AED) */
+	buf = dm_malloc(size);
+	if (!buf) {
+		log_err("Couldn't allocate temporary PV buffer.");
+		return 0;
+	}
+
+	memset(buf, 0, size);
+	memcpy(buf, &data->pvd, sizeof(struct pv_disk));
+
+	log_debug("Writing %s PV metadata to %s at %" PRIu64 " len %"
+		  PRIsize_t, data->pvd.vg_name, dev_name(data->dev),
+		  pos, size);
+
+	_xlate_pvd((struct pv_disk *) buf);
+	if (!dev_write(data->dev, pos, size, buf)) {
+		dm_free(buf);
+		return_0;
+	}
+
+	dm_free(buf);
+	return 1;
+}
+
+/*
+ * assumes the device has been opened.
+ */
+static int __write_all_pvd(const struct format_type *fmt __attribute((unused)),
+			   struct disk_list *data)
+{
+	const char *pv_name = dev_name(data->dev);
+
+	if (!_write_pvd(data)) {
+		log_error("Failed to write PV structure onto %s", pv_name);
+		return 0;
+	}
+
+	/* vgcache_add(data->pvd.vg_name, data->vgd.vg_uuid, data->dev, fmt); */
+	/*
+	 * Stop here for orphan pv's.
+	 */
+	if (data->pvd.vg_name[0] == '\0') {
+		/* if (!test_mode())
+		   vgcache_add(data->pvd.vg_name, NULL, data->dev, fmt); */
+		return 1;
+	}
+
+	/* if (!test_mode())
+	   vgcache_add(data->pvd.vg_name, data->vgd.vg_uuid, data->dev,
+	   fmt); */
+
+	if (!_write_vgd(data)) {
+		log_error("Failed to write VG data to %s", pv_name);
+		return 0;
+	}
+
+	if (!_write_uuids(data)) {
+		log_error("Failed to write PV uuid list to %s", pv_name);
+		return 0;
+	}
+
+	if (!_write_lvs(data)) {
+		log_error("Failed to write LV's to %s", pv_name);
+		return 0;
+	}
+
+	if (!_write_extents(data)) {
+		log_error("Failed to write extents to %s", pv_name);
+		return 0;
+	}
+
+	return 1;
+}
+
+/*
+ * opens the device and hands to the above fn.
+ */
+static int _write_all_pvd(const struct format_type *fmt, struct disk_list *data)
+{
+	int r;
+
+	if (!dev_open(data->dev))
+		return_0;
+
+	r = __write_all_pvd(fmt, data);
+
+	if (!dev_close(data->dev))
+		stack;
+
+	return r;
+}
+
+/*
+ * Writes all the given pv's to disk.  Does very
+ * little sanity checking, so make sure correct
+ * data is passed to here.
+ */
+int write_disks(const struct format_type *fmt, struct dm_list *pvs)
+{
+	struct disk_list *dl;
+
+	dm_list_iterate_items(dl, pvs) {
+		if (!(_write_all_pvd(fmt, dl)))
+			return_0;
+
+		log_very_verbose("Successfully wrote data to %s",
+				 dev_name(dl->dev));
+	}
+
+	return 1;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/format1/disk-rep.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format1/disk-rep.h
diff -N src/external/gpl2/lvm2tools/dist/lib/format1/disk-rep.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format1/disk-rep.h	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,252 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef DISK_REP_FORMAT1_H
+#define DISK_REP_FORMAT1_H
+
+#include "lvm-types.h"
+#include "metadata.h"
+#include "toolcontext.h"
+
+#define MAX_PV 256
+#define MAX_LV 256
+#define MAX_VG 99
+
+#define LVM_BLK_MAJOR 58
+
+#define MAX_PV_SIZE	((uint32_t) -1)	/* 2TB in sectors - 1 */
+#define MIN_PE_SIZE	(8192L >> SECTOR_SHIFT)	/* 8 KB in sectors */
+#define MAX_PE_SIZE	(16L * 1024L * (1024L >> SECTOR_SHIFT) * 1024L)
+#define PE_SIZE_PV_SIZE_REL 5	/* PV size must be at least 5 times PE size */
+#define	MAX_LE_TOTAL	65534	/* 2^16 - 2 */
+#define	MAX_PE_TOTAL	((uint32_t) -2)
+
+#define UNMAPPED_EXTENT 0
+
+/* volume group */
+#define	VG_ACTIVE            0x01	/* vg_status */
+#define	VG_EXPORTED          0x02	/*     "     */
+#define	VG_EXTENDABLE        0x04	/*     "     */
+
+#define	VG_READ              0x01	/* vg_access */
+#define	VG_WRITE             0x02	/*     "     */
+#define	VG_CLUSTERED         0x04	/*     "     */
+#define	VG_SHARED            0x08	/*     "     */
+
+/* logical volume */
+#define	LV_ACTIVE            0x01	/* lv_status */
+#define	LV_SPINDOWN          0x02	/*     "     */
+#define LV_PERSISTENT_MINOR  0x04	/*     "     */
+
+#define	LV_READ              0x01	/* lv_access */
+#define	LV_WRITE             0x02	/*     "     */
+#define	LV_SNAPSHOT          0x04	/*     "     */
+#define	LV_SNAPSHOT_ORG      0x08	/*     "     */
+
+#define	LV_BADBLOCK_ON       0x01	/* lv_badblock */
+
+#define	LV_STRICT            0x01	/* lv_allocation */
+#define	LV_CONTIGUOUS        0x02	/*       "       */
+
+/* physical volume */
+#define	PV_ACTIVE            0x01	/* pv_status */
+#define	PV_ALLOCATABLE       0x02	/* pv_allocatable */
+
+#define EXPORTED_TAG "PV_EXP"	/* Identifier for exported PV */
+#define IMPORTED_TAG "PV_IMP"	/* Identifier for imported PV */
+
+struct data_area {
+	uint32_t base;
+	uint32_t size;
+} __attribute__ ((packed));
+
+struct pv_disk {
+	int8_t id[2];
+	uint16_t version;	/* lvm version */
+	struct data_area pv_on_disk;
+	struct data_area vg_on_disk;
+	struct data_area pv_uuidlist_on_disk;
+	struct data_area lv_on_disk;
+	struct data_area pe_on_disk;
+	int8_t pv_uuid[NAME_LEN];
+	int8_t vg_name[NAME_LEN];
+	int8_t system_id[NAME_LEN];	/* for vgexport/vgimport */
+	uint32_t pv_major;
+	uint32_t pv_number;
+	uint32_t pv_status;
+	uint32_t pv_allocatable;
+	uint32_t pv_size;
+	uint32_t lv_cur;
+	uint32_t pe_size;
+	uint32_t pe_total;
+	uint32_t pe_allocated;
+
+	/* only present on version == 2 pv's */
+	uint32_t pe_start;
+} __attribute__ ((packed));
+
+struct lv_disk {
+	int8_t lv_name[NAME_LEN];
+	int8_t vg_name[NAME_LEN];
+	uint32_t lv_access;
+	uint32_t lv_status;
+	uint32_t lv_open;
+	uint32_t lv_dev;
+	uint32_t lv_number;
+	uint32_t lv_mirror_copies;	/* for future use */
+	uint32_t lv_recovery;	/*       "        */
+	uint32_t lv_schedule;	/*       "        */
+	uint32_t lv_size;
+	uint32_t lv_snapshot_minor;	/* minor number of original */
+	uint16_t lv_chunk_size;	/* chunk size of snapshot */
+	uint16_t dummy;
+	uint32_t lv_allocated_le;
+	uint32_t lv_stripes;
+	uint32_t lv_stripesize;
+	uint32_t lv_badblock;	/* for future use */
+	uint32_t lv_allocation;
+	uint32_t lv_io_timeout;	/* for future use */
+	uint32_t lv_read_ahead;
+} __attribute__ ((packed));
+
+struct vg_disk {
+	int8_t vg_uuid[ID_LEN];	/* volume group UUID */
+	int8_t vg_name_dummy[NAME_LEN - ID_LEN];	/* rest of v1 VG name */
+	uint32_t vg_number;	/* volume group number */
+	uint32_t vg_access;	/* read/write */
+	uint32_t vg_status;	/* active or not */
+	uint32_t lv_max;	/* maximum logical volumes */
+	uint32_t lv_cur;	/* current logical volumes */
+	uint32_t lv_open;	/* open logical volumes */
+	uint32_t pv_max;	/* maximum physical volumes */
+	uint32_t pv_cur;	/* current physical volumes FU */
+	uint32_t pv_act;	/* active physical volumes */
+	uint32_t dummy;
+	uint32_t vgda;		/* volume group descriptor arrays FU */
+	uint32_t pe_size;	/* physical extent size in sectors */
+	uint32_t pe_total;	/* total of physical extents */
+	uint32_t pe_allocated;	/* allocated physical extents */
+	uint32_t pvg_total;	/* physical volume groups FU */
+} __attribute__ ((packed));
+
+struct pe_disk {
+	uint16_t lv_num;
+	uint16_t le_num;
+} __attribute__ ((packed));
+
+struct uuid_list {
+	struct dm_list list;
+	char uuid[NAME_LEN] __attribute((aligned(8)));
+};
+
+struct lvd_list {
+	struct dm_list list;
+	struct lv_disk lvd;
+};
+
+struct disk_list {
+	struct dm_list list;
+	struct dm_pool *mem;
+	struct device *dev;
+
+	struct pv_disk pvd __attribute((aligned(8)));
+	struct vg_disk vgd __attribute((aligned(8)));
+	struct dm_list uuids __attribute((aligned(8)));
+	struct dm_list lvds __attribute((aligned(8)));
+	struct pe_disk *extents __attribute((aligned(8)));
+};
+
+/*
+ * Layout constants.
+ */
+#define METADATA_ALIGN 4096UL
+#define LVM1_PE_ALIGN (65536UL >> SECTOR_SHIFT)      /* PE alignment */
+
+#define	METADATA_BASE 0UL
+#define	PV_SIZE 1024UL
+#define	VG_SIZE 4096UL
+
+/*
+ * Functions to calculate layout info.
+ */
+int calculate_layout(struct disk_list *dl);
+int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size,
+			   uint32_t max_extent_count, uint64_t pe_start);
+
+/*
+ * Low level io routines which read/write
+ * disk_lists.
+ */
+
+struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
+			    struct dm_pool *mem, const char *vg_name);
+
+int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
+		   struct dev_filter *filter,
+		   struct dm_pool *mem, struct dm_list *results);
+
+int write_disks(const struct format_type *fmt, struct dm_list *pvds);
+
+/*
+ * Functions to translate to between disk and in
+ * core structures.
+ */
+int import_pv(const struct format_type *fmt, struct dm_pool *mem,
+	      struct device *dev, struct volume_group *vg,
+	      struct physical_volume *pv, struct pv_disk *pvd,
+	      struct vg_disk *vgd);
+int export_pv(struct cmd_context *cmd, struct dm_pool *mem,
+	      struct volume_group *vg,
+	      struct pv_disk *pvd, struct physical_volume *pv);
+
+int import_vg(struct dm_pool *mem,
+	      struct volume_group *vg, struct disk_list *dl);
+int export_vg(struct vg_disk *vgd, struct volume_group *vg);
+
+int import_lv(struct dm_pool *mem, struct logical_volume *lv, struct lv_disk *lvd);
+
+int import_extents(struct cmd_context *cmd, struct volume_group *vg,
+		   struct dm_list *pvds);
+int export_extents(struct disk_list *dl, uint32_t lv_num,
+		   struct logical_volume *lv, struct physical_volume *pv);
+
+int import_pvs(const struct format_type *fmt, struct dm_pool *mem,
+	       struct volume_group *vg,
+	       struct dm_list *pvds, struct dm_list *results, uint32_t *count);
+
+int import_lvs(struct dm_pool *mem, struct volume_group *vg, struct dm_list *pvds);
+int export_lvs(struct disk_list *dl, struct volume_group *vg,
+	       struct physical_volume *pv, const char *dev_dir);
+
+int import_snapshots(struct dm_pool *mem, struct volume_group *vg,
+		     struct dm_list *pvds);
+
+int export_uuids(struct disk_list *dl, struct volume_group *vg);
+
+void export_numbers(struct dm_list *pvds, struct volume_group *vg);
+
+void export_pv_act(struct dm_list *pvds);
+int munge_pvd(struct device *dev, struct pv_disk *pvd);
+int read_vgd(struct device *dev, struct vg_disk *vgd, struct pv_disk *pvd);
+
+/* blech */
+int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
+		       const char *candidate_vg, int *result);
+int export_vg_number(struct format_instance *fid, struct dm_list *pvds,
+		     const char *vg_name, struct dev_filter *filter);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/format1/format1.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format1/format1.c
diff -N src/external/gpl2/lvm2tools/dist/lib/format1/format1.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format1/format1.c	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,533 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "disk-rep.h"
+#include "limits.h"
+#include "display.h"
+#include "toolcontext.h"
+#include "lvm1-label.h"
+#include "format1.h"
+#include "segtype.h"
+
+/* VG consistency checks */
+static int _check_vgs(struct dm_list *pvs)
+{
+	struct dm_list *pvh, *t;
+	struct disk_list *dl = NULL;
+	struct disk_list *first = NULL;
+
+	uint32_t pv_count = 0;
+	uint32_t exported = 0;
+	int first_time = 1;
+
+	/*
+	 * If there are exported and unexported PVs, ignore exported ones.
+	 * This means an active VG won't be affected if disks are inserted
+	 * bearing an exported VG with the same name.
+	 */
+	dm_list_iterate_items(dl, pvs) {
+		if (first_time) {
+			exported = dl->pvd.pv_status & VG_EXPORTED;
+			first_time = 0;
+			continue;
+		}
+
+		if (exported != (dl->pvd.pv_status & VG_EXPORTED)) {
+			/* Remove exported PVs */
+			dm_list_iterate_safe(pvh, t, pvs) {
+				dl = dm_list_item(pvh, struct disk_list);
+				if (dl->pvd.pv_status & VG_EXPORTED)
+					dm_list_del(pvh);
+			}
+			break;
+		}
+	}
+
+	/* Remove any PVs with VG structs that differ from the first */
+	dm_list_iterate_safe(pvh, t, pvs) {
+		dl = dm_list_item(pvh, struct disk_list);
+
+		if (!first)
+			first = dl;
+
+		else if (memcmp(&first->vgd, &dl->vgd, sizeof(first->vgd))) {
+			log_error("VG data differs between PVs %s and %s",
+				  dev_name(first->dev), dev_name(dl->dev));
+			log_debug("VG data on %s: %s %s %" PRIu32 " %" PRIu32
+				  "  %" PRIu32 " %" PRIu32 " %" PRIu32 " %"
+				  PRIu32 " %" PRIu32 " %" PRIu32 " %" PRIu32
+				  " %" PRIu32 " %" PRIu32 " %" PRIu32 " %"
+				  PRIu32 " %" PRIu32 " %" PRIu32,
+				  dev_name(first->dev), first->vgd.vg_uuid,
+				  first->vgd.vg_name_dummy,
+				  first->vgd.vg_number, first->vgd.vg_access,
+				  first->vgd.vg_status, first->vgd.lv_max,
+				  first->vgd.lv_cur, first->vgd.lv_open,
+				  first->vgd.pv_max, first->vgd.pv_cur,
+				  first->vgd.pv_act, first->vgd.dummy,
+				  first->vgd.vgda, first->vgd.pe_size,
+				  first->vgd.pe_total, first->vgd.pe_allocated,
+				  first->vgd.pvg_total);
+			log_debug("VG data on %s: %s %s %" PRIu32 " %" PRIu32
+				  "  %" PRIu32 " %" PRIu32 " %" PRIu32 " %"
+				  PRIu32 " %" PRIu32 " %" PRIu32 " %" PRIu32
+				  " %" PRIu32 " %" PRIu32 " %" PRIu32 " %"
+				  PRIu32 " %" PRIu32 " %" PRIu32,
+				  dev_name(dl->dev), dl->vgd.vg_uuid,
+				  dl->vgd.vg_name_dummy, dl->vgd.vg_number,
+				  dl->vgd.vg_access, dl->vgd.vg_status,
+				  dl->vgd.lv_max, dl->vgd.lv_cur,
+				  dl->vgd.lv_open, dl->vgd.pv_max,
+				  dl->vgd.pv_cur, dl->vgd.pv_act, dl->vgd.dummy,
+				  dl->vgd.vgda, dl->vgd.pe_size,
+				  dl->vgd.pe_total, dl->vgd.pe_allocated,
+				  dl->vgd.pvg_total);
+			dm_list_del(pvh);
+			return 0;
+		}
+		pv_count++;
+	}
+
+	/* On entry to fn, list known to be non-empty */
+	if (pv_count != first->vgd.pv_cur) {
+		log_error("%d PV(s) found for VG %s: expected %d",
+			  pv_count, first->pvd.vg_name, first->vgd.pv_cur);
+	}
+
+	return 1;
+}
+
+static struct volume_group *_build_vg(struct format_instance *fid,
+				      struct dm_list *pvs)
+{
+	struct dm_pool *mem = fid->fmt->cmd->mem;
+	struct volume_group *vg = dm_pool_alloc(mem, sizeof(*vg));
+	struct disk_list *dl;
+
+	if (!vg)
+		goto_bad;
+
+	if (dm_list_empty(pvs))
+		goto_bad;
+
+	memset(vg, 0, sizeof(*vg));
+
+	vg->cmd = fid->fmt->cmd;
+	vg->fid = fid;
+	vg->seqno = 0;
+	dm_list_init(&vg->pvs);
+	dm_list_init(&vg->lvs);
+	dm_list_init(&vg->tags);
+
+	if (!_check_vgs(pvs))
+		goto_bad;
+
+	dl = dm_list_item(pvs->n, struct disk_list);
+
+	if (!import_vg(mem, vg, dl))
+		goto_bad;
+
+	if (!import_pvs(fid->fmt, mem, vg, pvs, &vg->pvs, &vg->pv_count))
+		goto_bad;
+
+	if (!import_lvs(mem, vg, pvs))
+		goto_bad;
+
+	if (!import_extents(fid->fmt->cmd, vg, pvs))
+		goto_bad;
+
+	if (!import_snapshots(mem, vg, pvs))
+		goto_bad;
+
+	return vg;
+
+      bad:
+	dm_pool_free(mem, vg);
+	return NULL;
+}
+
+static struct volume_group *_format1_vg_read(struct format_instance *fid,
+				     const char *vg_name,
+				     struct metadata_area *mda __attribute((unused)))
+{
+	struct dm_pool *mem = dm_pool_create("lvm1 vg_read", 1024 * 10);
+	struct dm_list pvs;
+	struct volume_group *vg = NULL;
+	dm_list_init(&pvs);
+
+	if (!mem)
+		return_NULL;
+
+	/* Strip dev_dir if present */
+	vg_name = strip_dir(vg_name, fid->fmt->cmd->dev_dir);
+
+	if (!read_pvs_in_vg
+	    (fid->fmt, vg_name, fid->fmt->cmd->filter, mem, &pvs))
+		goto_bad;
+
+	if (!(vg = _build_vg(fid, &pvs)))
+		goto_bad;
+
+      bad:
+	dm_pool_destroy(mem);
+	return vg;
+}
+
+static struct disk_list *_flatten_pv(struct format_instance *fid,
+				     struct dm_pool *mem, struct volume_group *vg,
+				     struct physical_volume *pv,
+				     const char *dev_dir)
+{
+	struct disk_list *dl = dm_pool_alloc(mem, sizeof(*dl));
+
+	if (!dl)
+		return_NULL;
+
+	dl->mem = mem;
+	dl->dev = pv->dev;
+
+	dm_list_init(&dl->uuids);
+	dm_list_init(&dl->lvds);
+
+	if (!export_pv(fid->fmt->cmd, mem, vg, &dl->pvd, pv) ||
+	    !export_vg(&dl->vgd, vg) ||
+	    !export_uuids(dl, vg) ||
+	    !export_lvs(dl, vg, pv, dev_dir) || !calculate_layout(dl)) {
+		dm_pool_free(mem, dl);
+		return_NULL;
+	}
+
+	return dl;
+}
+
+static int _flatten_vg(struct format_instance *fid, struct dm_pool *mem,
+		       struct volume_group *vg,
+		       struct dm_list *pvds, const char *dev_dir,
+		       struct dev_filter *filter)
+{
+	struct pv_list *pvl;
+	struct disk_list *data;
+
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		if (!(data = _flatten_pv(fid, mem, vg, pvl->pv, dev_dir)))
+			return_0;
+
+		dm_list_add(pvds, &data->list);
+	}
+
+	export_numbers(pvds, vg);
+	export_pv_act(pvds);
+
+	if (!export_vg_number(fid, pvds, vg->name, filter))
+		return_0;
+
+	return 1;
+}
+
+static int _format1_vg_write(struct format_instance *fid, struct volume_group *vg,
+		     struct metadata_area *mda __attribute((unused)))
+{
+	struct dm_pool *mem = dm_pool_create("lvm1 vg_write", 1024 * 10);
+	struct dm_list pvds;
+	int r = 0;
+
+	if (!mem)
+		return_0;
+
+	dm_list_init(&pvds);
+
+	r = (_flatten_vg(fid, mem, vg, &pvds, fid->fmt->cmd->dev_dir,
+			 fid->fmt->cmd->filter) &&
+	     write_disks(fid->fmt, &pvds));
+
+	lvmcache_update_vg(vg, 0);
+	dm_pool_destroy(mem);
+	return r;
+}
+
+static int _format1_pv_read(const struct format_type *fmt, const char *pv_name,
+		    struct physical_volume *pv, struct dm_list *mdas __attribute((unused)))
+{
+	struct dm_pool *mem = dm_pool_create("lvm1 pv_read", 1024);
+	struct disk_list *dl;
+	struct device *dev;
+	int r = 0;
+
+	log_very_verbose("Reading physical volume data %s from disk", pv_name);
+
+	if (!mem)
+		return_0;
+
+	if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter)))
+		goto_out;
+
+	if (!(dl = read_disk(fmt, dev, mem, NULL)))
+		goto_out;
+
+	if (!import_pv(fmt, fmt->cmd->mem, dl->dev, NULL, pv, &dl->pvd, &dl->vgd))
+		goto_out;
+
+	pv->fmt = fmt;
+
+	r = 1;
+
+      out:
+	dm_pool_destroy(mem);
+	return r;
+}
+
+static int _format1_pv_setup(const struct format_type *fmt,
+		     uint64_t pe_start, uint32_t extent_count,
+		     uint32_t extent_size,
+		     int pvmetadatacopies __attribute((unused)),
+		     uint64_t pvmetadatasize __attribute((unused)), struct dm_list *mdas __attribute((unused)),
+		     struct physical_volume *pv, struct volume_group *vg __attribute((unused)))
+{
+	if (pv->size > MAX_PV_SIZE)
+		pv->size--;
+	if (pv->size > MAX_PV_SIZE) {
+		log_error("Physical volumes cannot be bigger than %s",
+			  display_size(fmt->cmd, (uint64_t) MAX_PV_SIZE));
+		return 0;
+	}
+
+	/* Nothing more to do if extent size isn't provided */
+	if (!extent_size)
+		return 1;
+
+	/*
+	 * This works out pe_start and pe_count.
+	 */
+	if (!calculate_extent_count(pv, extent_size, extent_count, pe_start))
+		return_0;
+
+	/* Retain existing extent locations exactly */
+	if (((pe_start || extent_count) && (pe_start != pv->pe_start)) ||
+	    (extent_count && (extent_count != pv->pe_count))) {
+		log_error("Metadata would overwrite physical extents");
+		return 0;
+	}
+
+	return 1;
+}
+
+static int _format1_lv_setup(struct format_instance *fid, struct logical_volume *lv)
+{
+	uint64_t max_size = UINT_MAX;
+
+	if (!*lv->lvid.s)
+		lvid_from_lvnum(&lv->lvid, &lv->vg->id, find_free_lvnum(lv));
+
+	if (lv->le_count > MAX_LE_TOTAL) {
+		log_error("logical volumes cannot contain more than "
+			  "%d extents.", MAX_LE_TOTAL);
+		return 0;
+	}
+	if (lv->size > max_size) {
+		log_error("logical volumes cannot be larger than %s",
+			  display_size(fid->fmt->cmd, max_size));
+		return 0;
+	}
+
+	return 1;
+}
+
+static int _format1_pv_write(const struct format_type *fmt, struct physical_volume *pv,
+		     struct dm_list *mdas __attribute((unused)), int64_t sector __attribute((unused)))
+{
+	struct dm_pool *mem;
+	struct disk_list *dl;
+	struct dm_list pvs;
+	struct label *label;
+	struct lvmcache_info *info;
+
+	if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
+				  pv->vg_name, NULL, 0)))
+		return_0;
+	label = info->label;
+	info->device_size = pv->size << SECTOR_SHIFT;
+	info->fmt = fmt;
+
+	dm_list_init(&info->mdas);
+
+	dm_list_init(&pvs);
+
+	/* Ensure any residual PE structure is gone */
+	pv->pe_size = pv->pe_count = 0;
+	pv->pe_start = LVM1_PE_ALIGN;
+
+	if (!(mem = dm_pool_create("lvm1 pv_write", 1024)))
+		return_0;
+
+	if (!(dl = dm_pool_alloc(mem, sizeof(*dl))))
+		goto_bad;
+
+	dl->mem = mem;
+	dl->dev = pv->dev;
+
+	if (!export_pv(fmt->cmd, mem, NULL, &dl->pvd, pv))
+		goto_bad;
+
+	/* must be set to be able to zero gap after PV structure in
+	   dev_write in order to make other disk tools happy */
+	dl->pvd.pv_on_disk.base = METADATA_BASE;
+	dl->pvd.pv_on_disk.size = PV_SIZE;
+	dl->pvd.pe_on_disk.base = LVM1_PE_ALIGN << SECTOR_SHIFT;
+
+	dm_list_add(&pvs, &dl->list);
+	if (!write_disks(fmt, &pvs))
+		goto_bad;
+
+	dm_pool_destroy(mem);
+	return 1;
+
+      bad:
+	dm_pool_destroy(mem);
+	return 0;
+}
+
+static int _format1_vg_setup(struct format_instance *fid, struct volume_group *vg)
+{
+	/* just check max_pv and max_lv */
+	if (!vg->max_lv || vg->max_lv >= MAX_LV)
+		vg->max_lv = MAX_LV - 1;
+
+	if (!vg->max_pv || vg->max_pv >= MAX_PV)
+		vg->max_pv = MAX_PV - 1;
+
+	if (vg->extent_size > MAX_PE_SIZE || vg->extent_size < MIN_PE_SIZE) {
+		log_error("Extent size must be between %s and %s",
+			  display_size(fid->fmt->cmd, (uint64_t) MIN_PE_SIZE),
+			  display_size(fid->fmt->cmd, (uint64_t) MAX_PE_SIZE));
+
+		return 0;
+	}
+
+	if (vg->extent_size % MIN_PE_SIZE) {
+		log_error("Extent size must be multiple of %s",
+			  display_size(fid->fmt->cmd, (uint64_t) MIN_PE_SIZE));
+		return 0;
+	}
+
+	/* Redundant? */
+	if (vg->extent_size & (vg->extent_size - 1)) {
+		log_error("Extent size must be power of 2");
+		return 0;
+	}
+
+	return 1;
+}
+
+static int _format1_segtype_supported(struct format_instance *fid __attribute((unused)),
+				      const struct segment_type *segtype)
+{
+	if (!(segtype->flags & SEG_FORMAT1_SUPPORT))
+		return_0;
+
+	return 1;
+}
+
+static struct metadata_area_ops _metadata_format1_ops = {
+	.vg_read = _format1_vg_read,
+	.vg_write = _format1_vg_write,
+};
+
+static struct format_instance *_format1_create_instance(const struct format_type *fmt,
+						const char *vgname __attribute((unused)),
+						const char *vgid __attribute((unused)),
+						void *private __attribute((unused)))
+{
+	struct format_instance *fid;
+	struct metadata_area *mda;
+
+	if (!(fid = dm_pool_alloc(fmt->cmd->mem, sizeof(*fid))))
+		return_NULL;
+
+	fid->fmt = fmt;
+	dm_list_init(&fid->metadata_areas);
+
+	/* Define a NULL metadata area */
+	if (!(mda = dm_pool_alloc(fmt->cmd->mem, sizeof(*mda)))) {
+		dm_pool_free(fmt->cmd->mem, fid);
+		return_NULL;
+	}
+
+	mda->ops = &_metadata_format1_ops;
+	mda->metadata_locn = NULL;
+	dm_list_add(&fid->metadata_areas, &mda->list);
+
+	return fid;
+}
+
+static void _format1_destroy_instance(struct format_instance *fid __attribute((unused)))
+{
+	return;
+}
+
+static void _format1_destroy(const struct format_type *fmt)
+{
+	dm_free((void *) fmt);
+}
+
+static struct format_handler _format1_ops = {
+	.pv_read = _format1_pv_read,
+	.pv_setup = _format1_pv_setup,
+	.pv_write = _format1_pv_write,
+	.lv_setup = _format1_lv_setup,
+	.vg_setup = _format1_vg_setup,
+	.segtype_supported = _format1_segtype_supported,
+	.create_instance = _format1_create_instance,
+	.destroy_instance = _format1_destroy_instance,
+	.destroy = _format1_destroy,
+};
+
+#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
+{
+	struct format_type *fmt = dm_malloc(sizeof(*fmt));
+
+	if (!fmt)
+		return_NULL;
+
+	fmt->cmd = cmd;
+	fmt->ops = &_format1_ops;
+	fmt->name = FMT_LVM1_NAME;
+	fmt->alias = NULL;
+	fmt->orphan_vg_name = FMT_LVM1_ORPHAN_VG_NAME;
+	fmt->features = FMT_RESTRICTED_LVIDS | FMT_ORPHAN_ALLOCATABLE |
+			FMT_RESTRICTED_READAHEAD;
+	fmt->private = NULL;
+
+	if (!(fmt->labeller = lvm1_labeller_create(fmt))) {
+		log_error("Couldn't create lvm1 label handler.");
+		return NULL;
+	}
+
+	if (!(label_register_handler(FMT_LVM1_NAME, fmt->labeller))) {
+		log_error("Couldn't register lvm1 label handler.");
+		return NULL;
+	}
+
+	log_very_verbose("Initialised format: %s", fmt->name);
+
+	return fmt;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/format1/format1.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format1/format1.h
diff -N src/external/gpl2/lvm2tools/dist/lib/format1/format1.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format1/format1.h	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,31 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_FORMAT1_H
+#define _LVM_FORMAT1_H
+
+#include "metadata.h"
+#include "lvmcache.h"
+
+#define FMT_LVM1_NAME "lvm1"
+#define FMT_LVM1_ORPHAN_VG_NAME ORPHAN_VG_NAME(FMT_LVM1_NAME)
+
+#ifdef LVM1_INTERNAL
+struct format_type *init_lvm1_format(struct cmd_context *cmd);
+#endif
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/format1/import-export.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format1/import-export.c
diff -N src/external/gpl2/lvm2tools/dist/lib/format1/import-export.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format1/import-export.c	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,692 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Translates between disk and in-core formats.
+ */
+
+#include "lib.h"
+#include "disk-rep.h"
+#include "lvm-string.h"
+#include "filter.h"
+#include "toolcontext.h"
+#include "segtype.h"
+#include "pv_alloc.h"
+#include "display.h"
+#include "lvmcache.h"
+#include "metadata.h"
+
+#include <time.h>
+
+static int _check_vg_name(const char *name)
+{
+	return strlen(name) < NAME_LEN;
+}
+
+/*
+ * Extracts the last part of a path.
+ */
+static char *_create_lv_name(struct dm_pool *mem, const char *full_name)
+{
+	const char *ptr = strrchr(full_name, '/');
+
+	if (!ptr)
+		ptr = full_name;
+	else
+		ptr++;
+
+	return dm_pool_strdup(mem, ptr);
+}
+
+int import_pv(const struct format_type *fmt, struct dm_pool *mem,
+	      struct device *dev, struct volume_group *vg,
+	      struct physical_volume *pv, struct pv_disk *pvd,
+	      struct vg_disk *vgd)
+{
+	uint64_t size;
+
+	memset(pv, 0, sizeof(*pv));
+	memcpy(&pv->id, pvd->pv_uuid, ID_LEN);
+
+	pv->dev = dev;
+	if (!*pvd->vg_name)
+		pv->vg_name = fmt->orphan_vg_name;
+	else if (!(pv->vg_name = dm_pool_strdup(mem, (char *)pvd->vg_name))) {
+		log_error("Volume Group name allocation failed.");
+		return 0;
+	}
+
+	memcpy(&pv->vgid, vgd->vg_uuid, sizeof(vg->id));
+
+	/* Store system_id from first PV if PV belongs to a VG */
+	if (vg && !*vg->system_id)
+		strncpy(vg->system_id, (char *)pvd->system_id, NAME_LEN);
+
+	if (vg &&
+	    strncmp(vg->system_id, (char *)pvd->system_id, sizeof(pvd->system_id)))
+		    log_very_verbose("System ID %s on %s differs from %s for "
+				     "volume group", pvd->system_id,
+				     pv_dev_name(pv), vg->system_id);
+
+	/*
+	 * If exported, we still need to flag in pv->status too because
+	 * we don't always have a struct volume_group when we need this.
+	 */
+	if (pvd->pv_status & VG_EXPORTED)
+		pv->status |= EXPORTED_VG;
+
+	if (pvd->pv_allocatable)
+		pv->status |= ALLOCATABLE_PV;
+
+	pv->size = pvd->pv_size;
+	pv->pe_size = pvd->pe_size;
+	pv->pe_start = pvd->pe_start;
+	pv->pe_count = pvd->pe_total;
+	pv->pe_alloc_count = 0;
+	pv->pe_align = 0;
+
+	/* Fix up pv size if missing or impossibly large */
+	if (!pv->size || pv->size > (1ULL << 62)) {
+		if (!dev_get_size(dev, &pv->size)) {
+			log_error("%s: Couldn't get size.", pv_dev_name(pv));
+			return 0;
+		}
+		log_verbose("Fixing up missing format1 size (%s) "
+			    "for PV %s", display_size(fmt->cmd, pv->size),
+			    pv_dev_name(pv));
+		if (vg) {
+			size = pv->pe_count * (uint64_t) vg->extent_size +
+			       pv->pe_start;
+			if (size > pv->size)
+				log_error("WARNING: Physical Volume %s is too "
+					  "large for underlying device",
+					  pv_dev_name(pv));
+		}
+	}
+
+	dm_list_init(&pv->tags);
+	dm_list_init(&pv->segments);
+
+	if (!alloc_pv_segment_whole_pv(mem, pv))
+		return_0;
+
+	return 1;
+}
+
+static int _system_id(struct cmd_context *cmd, char *s, const char *prefix)
+{
+
+	if (dm_snprintf(s, NAME_LEN, "%s%s%lu",
+			 prefix, cmd->hostname, time(NULL)) < 0) {
+		log_error("Generated system_id too long");
+		return 0;
+	}
+
+	return 1;
+}
+
+int export_pv(struct cmd_context *cmd, struct dm_pool *mem __attribute((unused)),
+	      struct volume_group *vg,
+	      struct pv_disk *pvd, struct physical_volume *pv)
+{
+	memset(pvd, 0, sizeof(*pvd));
+
+	pvd->id[0] = 'H';
+	pvd->id[1] = 'M';
+	pvd->version = 1;
+
+	memcpy(pvd->pv_uuid, pv->id.uuid, ID_LEN);
+
+	if (pv->vg_name && !is_orphan(pv)) {
+		if (!_check_vg_name(pv->vg_name))
+			return_0;
+		strncpy((char *)pvd->vg_name, pv->vg_name, sizeof(pvd->vg_name));
+	}
+
+	/* Preserve existing system_id if it exists */
+	if (vg && *vg->system_id)
+		strncpy((char *)pvd->system_id, vg->system_id, sizeof(pvd->system_id));
+
+	/* Is VG already exported or being exported? */
+	if (vg && (vg->status & EXPORTED_VG)) {
+		/* Does system_id need setting? */
+		if (!*vg->system_id ||
+		    strncmp(vg->system_id, EXPORTED_TAG,
+			    sizeof(EXPORTED_TAG) - 1)) {
+			if (!_system_id(cmd, (char *)pvd->system_id, EXPORTED_TAG))
+				return_0;
+		}
+		if (strlen((char *)pvd->vg_name) + sizeof(EXPORTED_TAG) >
+		    sizeof(pvd->vg_name)) {
+			log_error("Volume group name %s too long to export",
+				  pvd->vg_name);
+			return 0;
+		}
+		strcat((char *)pvd->vg_name, EXPORTED_TAG);
+	}
+
+	/* Is VG being imported? */
+	if (vg && !(vg->status & EXPORTED_VG) && *vg->system_id &&
+	    !strncmp(vg->system_id, EXPORTED_TAG, sizeof(EXPORTED_TAG) - 1)) {
+		if (!_system_id(cmd, (char *)pvd->system_id, IMPORTED_TAG))
+			return_0;
+	}
+
+	/* Generate system_id if PV is in VG */
+	if (!pvd->system_id || !*pvd->system_id)
+		if (!_system_id(cmd, (char *)pvd->system_id, ""))
+			return_0;
+
+	/* Update internal system_id if we changed it */
+	if (vg &&
+	    (!*vg->system_id ||
+	     strncmp(vg->system_id, (char *)pvd->system_id, sizeof(pvd->system_id))))
+		    strncpy(vg->system_id, (char *)pvd->system_id, NAME_LEN);
+
+	//pvd->pv_major = MAJOR(pv->dev);
+
+	if (pv->status & ALLOCATABLE_PV)
+		pvd->pv_allocatable = PV_ALLOCATABLE;
+
+	pvd->pv_size = pv->size;
+	pvd->lv_cur = 0;	/* this is set when exporting the lv list */
+	if (vg)
+		pvd->pe_size = vg->extent_size;
+	else
+		pvd->pe_size = pv->pe_size;
+	pvd->pe_total = pv->pe_count;
+	pvd->pe_allocated = pv->pe_alloc_count;
+	pvd->pe_start = pv->pe_start;
+
+	return 1;
+}
+
+int import_vg(struct dm_pool *mem,
+	      struct volume_group *vg, struct disk_list *dl)
+{
+	struct vg_disk *vgd = &dl->vgd;
+	memcpy(vg->id.uuid, vgd->vg_uuid, ID_LEN);
+
+	if (!_check_vg_name((char *)dl->pvd.vg_name))
+		return_0;
+
+	if (!(vg->name = dm_pool_strdup(mem, (char *)dl->pvd.vg_name)))
+		return_0;
+
+	if (!(vg->system_id = dm_pool_alloc(mem, NAME_LEN)))
+		return_0;
+
+	*vg->system_id = '\0';
+
+	if (vgd->vg_status & VG_EXPORTED)
+		vg->status |= EXPORTED_VG;
+
+	if (vgd->vg_status & VG_EXTENDABLE)
+		vg->status |= RESIZEABLE_VG;
+
+	if (vgd->vg_access & VG_READ)
+		vg->status |= LVM_READ;
+
+	if (vgd->vg_access & VG_WRITE)
+		vg->status |= LVM_WRITE;
+
+	if (vgd->vg_access & VG_CLUSTERED)
+		vg->status |= CLUSTERED;
+
+	if (vgd->vg_access & VG_SHARED)
+		vg->status |= SHARED;
+
+	vg->extent_size = vgd->pe_size;
+	vg->extent_count = vgd->pe_total;
+	vg->free_count = vgd->pe_total;
+	vg->max_lv = vgd->lv_max;
+	vg->max_pv = vgd->pv_max;
+	vg->alloc = ALLOC_NORMAL;
+
+	return 1;
+}
+
+int export_vg(struct vg_disk *vgd, struct volume_group *vg)
+{
+	memset(vgd, 0, sizeof(*vgd));
+	memcpy(vgd->vg_uuid, vg->id.uuid, ID_LEN);
+
+	if (vg->status & LVM_READ)
+		vgd->vg_access |= VG_READ;
+
+	if (vg->status & LVM_WRITE)
+		vgd->vg_access |= VG_WRITE;
+
+	if (vg_is_clustered(vg))
+		vgd->vg_access |= VG_CLUSTERED;
+
+	if (vg->status & SHARED)
+		vgd->vg_access |= VG_SHARED;
+
+	if (vg->status & EXPORTED_VG)
+		vgd->vg_status |= VG_EXPORTED;
+
+	if (vg->status & RESIZEABLE_VG)
+		vgd->vg_status |= VG_EXTENDABLE;
+
+	vgd->lv_max = vg->max_lv;
+	vgd->lv_cur = vg->lv_count + vg->snapshot_count;
+
+	vgd->pv_max = vg->max_pv;
+	vgd->pv_cur = vg->pv_count;
+
+	vgd->pe_size = vg->extent_size;
+	vgd->pe_total = vg->extent_count;
+	vgd->pe_allocated = vg->extent_count - vg->free_count;
+
+	return 1;
+}
+
+int import_lv(struct dm_pool *mem, struct logical_volume *lv, struct lv_disk *lvd)
+{
+	lvid_from_lvnum(&lv->lvid, &lv->vg->id, lvd->lv_number);
+
+	if (!(lv->name = _create_lv_name(mem, (char *)lvd->lv_name)))
+		return_0;
+
+	lv->status |= VISIBLE_LV;
+
+	if (lvd->lv_status & LV_SPINDOWN)
+		lv->status |= SPINDOWN_LV;
+
+	if (lvd->lv_status & LV_PERSISTENT_MINOR) {
+		lv->status |= FIXED_MINOR;
+		lv->minor = MINOR(lvd->lv_dev);
+		lv->major = MAJOR(lvd->lv_dev);
+	} else {
+		lv->major = -1;
+		lv->minor = -1;
+	}
+
+	if (lvd->lv_access & LV_READ)
+		lv->status |= LVM_READ;
+
+	if (lvd->lv_access & LV_WRITE)
+		lv->status |= LVM_WRITE;
+
+	if (lvd->lv_badblock)
+		lv->status |= BADBLOCK_ON;
+
+	/* Drop the unused LV_STRICT here */
+	if (lvd->lv_allocation & LV_CONTIGUOUS)
+		lv->alloc = ALLOC_CONTIGUOUS;
+	else
+		lv->alloc = ALLOC_NORMAL;
+
+	if (!lvd->lv_read_ahead)
+		lv->read_ahead = lv->vg->cmd->default_settings.read_ahead;
+	else
+		lv->read_ahead = lvd->lv_read_ahead;
+
+	lv->size = lvd->lv_size;
+	lv->le_count = lvd->lv_allocated_le;
+
+	lv->snapshot = NULL;
+	dm_list_init(&lv->snapshot_segs);
+	dm_list_init(&lv->segments);
+	dm_list_init(&lv->tags);
+	dm_list_init(&lv->segs_using_this_lv);
+
+	return 1;
+}
+
+static void _export_lv(struct lv_disk *lvd, struct volume_group *vg,
+		       struct logical_volume *lv, const char *dev_dir)
+{
+	memset(lvd, 0, sizeof(*lvd));
+	snprintf((char *)lvd->lv_name, sizeof(lvd->lv_name), "%s%s/%s",
+		 dev_dir, vg->name, lv->name);
+
+	strcpy((char *)lvd->vg_name, vg->name);
+
+	if (lv->status & LVM_READ)
+		lvd->lv_access |= LV_READ;
+
+	if (lv->status & LVM_WRITE)
+		lvd->lv_access |= LV_WRITE;
+
+	if (lv->status & SPINDOWN_LV)
+		lvd->lv_status |= LV_SPINDOWN;
+
+	if (lv->status & FIXED_MINOR) {
+		lvd->lv_status |= LV_PERSISTENT_MINOR;
+		lvd->lv_dev = MKDEV(lv->major, lv->minor);
+	} else {
+		lvd->lv_dev = MKDEV(LVM_BLK_MAJOR, lvnum_from_lvid(&lv->lvid));
+	}
+
+	if (lv->read_ahead == DM_READ_AHEAD_AUTO ||
+	    lv->read_ahead == DM_READ_AHEAD_NONE)
+		lvd->lv_read_ahead = 0;
+	else
+		lvd->lv_read_ahead = lv->read_ahead;
+
+	lvd->lv_stripes =
+	    dm_list_item(lv->segments.n, struct lv_segment)->area_count;
+	lvd->lv_stripesize =
+	    dm_list_item(lv->segments.n, struct lv_segment)->stripe_size;
+
+	lvd->lv_size = lv->size;
+	lvd->lv_allocated_le = lv->le_count;
+
+	if (lv->status & BADBLOCK_ON)
+		lvd->lv_badblock = LV_BADBLOCK_ON;
+
+	if (lv->alloc == ALLOC_CONTIGUOUS)
+		lvd->lv_allocation |= LV_CONTIGUOUS;
+}
+
+int export_extents(struct disk_list *dl, uint32_t lv_num,
+		   struct logical_volume *lv, struct physical_volume *pv)
+{
+	struct pe_disk *ped;
+	struct lv_segment *seg;
+	uint32_t pe, s;
+
+	dm_list_iterate_items(seg, &lv->segments) {
+		for (s = 0; s < seg->area_count; s++) {
+			if (!(seg->segtype->flags & SEG_FORMAT1_SUPPORT)) {
+				log_error("Segment type %s in LV %s: "
+					  "unsupported by format1",
+					  seg->segtype->name, lv->name);
+				return 0;
+			}
+			if (seg_type(seg, s) != AREA_PV) {
+				log_error("Non-PV stripe found in LV %s: "
+					  "unsupported by format1", lv->name);
+				return 0;
+			}
+			if (seg_pv(seg, s) != pv)
+				continue;	/* not our pv */
+
+			for (pe = 0; pe < (seg->len / seg->area_count); pe++) {
+				ped = &dl->extents[pe + seg_pe(seg, s)];
+				ped->lv_num = lv_num;
+				ped->le_num = (seg->le / seg->area_count) + pe +
+				    s * (lv->le_count / seg->area_count);
+			}
+		}
+	}
+
+	return 1;
+}
+
+int import_pvs(const struct format_type *fmt, struct dm_pool *mem,
+	       struct volume_group *vg,
+	       struct dm_list *pvds, struct dm_list *results, uint32_t *count)
+{
+	struct disk_list *dl;
+	struct pv_list *pvl;
+
+	*count = 0;
+	dm_list_iterate_items(dl, pvds) {
+		if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl))) ||
+		    !(pvl->pv = dm_pool_alloc(mem, sizeof(*pvl->pv))))
+			return_0;
+
+		if (!import_pv(fmt, mem, dl->dev, vg, pvl->pv, &dl->pvd, &dl->vgd))
+			return_0;
+
+		pvl->pv->fmt = fmt;
+		dm_list_add(results, &pvl->list);
+		(*count)++;
+	}
+
+	return 1;
+}
+
+static struct logical_volume *_add_lv(struct dm_pool *mem,
+				      struct volume_group *vg,
+				      struct lv_disk *lvd)
+{
+	struct lv_list *ll;
+	struct logical_volume *lv;
+
+	if (!(ll = dm_pool_zalloc(mem, sizeof(*ll))) ||
+	    !(ll->lv = dm_pool_zalloc(mem, sizeof(*ll->lv))))
+		return_NULL;
+	lv = ll->lv;
+	lv->vg = vg;
+
+	if (!import_lv(mem, lv, lvd))
+		return_NULL;
+
+	dm_list_add(&vg->lvs, &ll->list);
+	vg->lv_count++;
+
+	return lv;
+}
+
+int import_lvs(struct dm_pool *mem, struct volume_group *vg, struct dm_list *pvds)
+{
+	struct disk_list *dl;
+	struct lvd_list *ll;
+	struct lv_disk *lvd;
+
+	dm_list_iterate_items(dl, pvds) {
+		dm_list_iterate_items(ll, &dl->lvds) {
+			lvd = &ll->lvd;
+
+			if (!find_lv(vg, (char *)lvd->lv_name) &&
+			    !_add_lv(mem, vg, lvd))
+				return_0;
+		}
+	}
+
+	return 1;
+}
+
+/* FIXME: tidy */
+int export_lvs(struct disk_list *dl, struct volume_group *vg,
+	       struct physical_volume *pv, const char *dev_dir)
+{
+	int r = 0;
+	struct lv_list *ll;
+	struct lvd_list *lvdl;
+	size_t len;
+	uint32_t lv_num;
+	struct dm_hash_table *lvd_hash;
+
+	if (!_check_vg_name(vg->name))
+		return_0;
+
+	if (!(lvd_hash = dm_hash_create(32)))
+		return_0;
+
+	/*
+	 * setup the pv's extents array
+	 */
+	len = sizeof(struct pe_disk) * dl->pvd.pe_total;
+	if (!(dl->extents = dm_pool_alloc(dl->mem, len)))
+		goto_out;
+	memset(dl->extents, 0, len);
+
+	dm_list_iterate_items(ll, &vg->lvs) {
+		if (ll->lv->status & SNAPSHOT)
+			continue;
+
+		if (!(lvdl = dm_pool_alloc(dl->mem, sizeof(*lvdl))))
+			goto_out;
+
+		_export_lv(&lvdl->lvd, vg, ll->lv, dev_dir);
+
+		lv_num = lvnum_from_lvid(&ll->lv->lvid);
+		lvdl->lvd.lv_number = lv_num;
+
+		if (!dm_hash_insert(lvd_hash, ll->lv->name, &lvdl->lvd))
+			goto_out;
+
+		if (!export_extents(dl, lv_num + 1, ll->lv, pv))
+			goto_out;
+
+		if (lv_is_origin(ll->lv))
+			lvdl->lvd.lv_access |= LV_SNAPSHOT_ORG;
+
+		if (lv_is_cow(ll->lv)) {
+			lvdl->lvd.lv_access |= LV_SNAPSHOT;
+			lvdl->lvd.lv_chunk_size = ll->lv->snapshot->chunk_size;
+			lvdl->lvd.lv_snapshot_minor =
+			    lvnum_from_lvid(&ll->lv->snapshot->origin->lvid);
+		}
+
+		dm_list_add(&dl->lvds, &lvdl->list);
+		dl->pvd.lv_cur++;
+	}
+
+	r = 1;
+
+      out:
+	dm_hash_destroy(lvd_hash);
+	return r;
+}
+
+/*
+ * FIXME: More inefficient code.
+ */
+int import_snapshots(struct dm_pool *mem __attribute((unused)), struct volume_group *vg,
+		     struct dm_list *pvds)
+{
+	struct logical_volume *lvs[MAX_LV];
+	struct disk_list *dl;
+	struct lvd_list *ll;
+	struct lv_disk *lvd;
+	int lvnum;
+	struct logical_volume *org, *cow;
+
+	/* build an index of lv numbers */
+	memset(lvs, 0, sizeof(lvs));
+	dm_list_iterate_items(dl, pvds) {
+		dm_list_iterate_items(ll, &dl->lvds) {
+			lvd = &ll->lvd;
+
+			lvnum = lvd->lv_number;
+
+			if (lvnum >= MAX_LV) {
+				log_err("Logical volume number "
+					"out of bounds.");
+				return 0;
+			}
+
+			if (!lvs[lvnum] &&
+			    !(lvs[lvnum] = find_lv(vg, (char *)lvd->lv_name))) {
+				log_err("Couldn't find logical volume '%s'.",
+					lvd->lv_name);
+				return 0;
+			}
+		}
+	}
+
+	/*
+	 * Now iterate through yet again adding the snapshots.
+	 */
+	dm_list_iterate_items(dl, pvds) {
+		dm_list_iterate_items(ll, &dl->lvds) {
+			lvd = &ll->lvd;
+
+			if (!(lvd->lv_access & LV_SNAPSHOT))
+				continue;
+
+			lvnum = lvd->lv_number;
+			cow = lvs[lvnum];
+			if (!(org = lvs[lvd->lv_snapshot_minor])) {
+				log_err("Couldn't find origin logical volume "
+					"for snapshot '%s'.", lvd->lv_name);
+				return 0;
+			}
+
+			/* we may have already added this snapshot */
+			if (lv_is_cow(cow))
+				continue;
+
+			/* insert the snapshot */
+			if (!vg_add_snapshot(NULL, org, cow, NULL,
+					     org->le_count,
+					     lvd->lv_chunk_size)) {
+				log_err("Couldn't add snapshot.");
+				return 0;
+			}
+		}
+	}
+
+	return 1;
+}
+
+int export_uuids(struct disk_list *dl, struct volume_group *vg)
+{
+	struct uuid_list *ul;
+	struct pv_list *pvl;
+
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		if (!(ul = dm_pool_alloc(dl->mem, sizeof(*ul))))
+			return_0;
+
+		memset(ul->uuid, 0, sizeof(ul->uuid));
+		memcpy(ul->uuid, pvl->pv->id.uuid, ID_LEN);
+
+		dm_list_add(&dl->uuids, &ul->list);
+	}
+	return 1;
+}
+
+/*
+ * This calculates the nasty pv_number field
+ * used by LVM1.
+ */
+void export_numbers(struct dm_list *pvds, struct volume_group *vg __attribute((unused)))
+{
+	struct disk_list *dl;
+	int pv_num = 1;
+
+	dm_list_iterate_items(dl, pvds)
+		dl->pvd.pv_number = pv_num++;
+}
+
+/*
+ * Calculate vg_disk->pv_act.
+ */
+void export_pv_act(struct dm_list *pvds)
+{
+	struct disk_list *dl;
+	int act = 0;
+
+	dm_list_iterate_items(dl, pvds)
+		if (dl->pvd.pv_status & PV_ACTIVE)
+			act++;
+
+	dm_list_iterate_items(dl, pvds)
+		dl->vgd.pv_act = act;
+}
+
+int export_vg_number(struct format_instance *fid, struct dm_list *pvds,
+		     const char *vg_name, struct dev_filter *filter)
+{
+	struct disk_list *dl;
+	int vg_num;
+
+	if (!get_free_vg_number(fid, filter, vg_name, &vg_num))
+		return_0;
+
+	dm_list_iterate_items(dl, pvds)
+		dl->vgd.vg_number = vg_num;
+
+	return 1;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/format1/import-extents.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format1/import-extents.c
diff -N src/external/gpl2/lvm2tools/dist/lib/format1/import-extents.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format1/import-extents.c	13 Dec 2008 14:39:33 -0000	1.1.1.1.2.2
@@ -0,0 +1,374 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "metadata.h"
+#include "disk-rep.h"
+#include "lv_alloc.h"
+#include "display.h"
+#include "segtype.h"
+
+/*
+ * After much thought I have decided it is easier,
+ * and probably no less efficient, to convert the
+ * pe->le map to a full le->pe map, and then
+ * process this to get the segments form that
+ * we're after.  Any code which goes directly from
+ * the pe->le map to segments would be gladly
+ * accepted, if it is less complicated than this
+ * file.
+ */
+struct pe_specifier {
+	struct physical_volume *pv;
+	uint32_t pe;
+};
+
+struct lv_map {
+	struct logical_volume *lv;
+	uint32_t stripes;
+	uint32_t stripe_size;
+	struct pe_specifier *map;
+};
+
+static struct dm_hash_table *_create_lv_maps(struct dm_pool *mem,
+					  struct volume_group *vg)
+{
+	struct dm_hash_table *maps = dm_hash_create(32);
+	struct lv_list *ll;
+	struct lv_map *lvm;
+
+	if (!maps) {
+		log_err("Unable to create hash table for holding "
+			"extent maps.");
+		return NULL;
+	}
+
+	dm_list_iterate_items(ll, &vg->lvs) {
+		if (ll->lv->status & SNAPSHOT)
+			continue;
+
+		if (!(lvm = dm_pool_alloc(mem, sizeof(*lvm))))
+			goto_bad;
+
+		lvm->lv = ll->lv;
+		if (!(lvm->map = dm_pool_zalloc(mem, sizeof(*lvm->map)
+					     * ll->lv->le_count)))
+			goto_bad;
+
+		if (!dm_hash_insert(maps, ll->lv->name, lvm))
+			goto_bad;
+	}
+
+	return maps;
+
+      bad:
+	dm_hash_destroy(maps);
+	return NULL;
+}
+
+static int _fill_lv_array(struct lv_map **lvs,
+			  struct dm_hash_table *maps, struct disk_list *dl)
+{
+	struct lvd_list *ll;
+	struct lv_map *lvm;
+
+	memset(lvs, 0, sizeof(*lvs) * MAX_LV);
+
+	dm_list_iterate_items(ll, &dl->lvds) {
+		if (!(lvm = dm_hash_lookup(maps, strrchr((char *)ll->lvd.lv_name, '/')
+					+ 1))) {
+			log_err("Physical volume (%s) contains an "
+				"unknown logical volume (%s).",
+				dev_name(dl->dev), ll->lvd.lv_name);
+			return 0;
+		}
+
+		lvm->stripes = ll->lvd.lv_stripes;
+		lvm->stripe_size = ll->lvd.lv_stripesize;
+
+		lvs[ll->lvd.lv_number] = lvm;
+	}
+
+	return 1;
+}
+
+static int _fill_maps(struct dm_hash_table *maps, struct volume_group *vg,
+		      struct dm_list *pvds)
+{
+	struct disk_list *dl;
+	struct physical_volume *pv;
+	struct lv_map *lvms[MAX_LV], *lvm;
+	struct pe_disk *e;
+	uint32_t i, lv_num, le;
+
+	dm_list_iterate_items(dl, pvds) {
+		pv = find_pv(vg, dl->dev);
+		e = dl->extents;
+
+		/* build an array of lv's for this pv */
+		if (!_fill_lv_array(lvms, maps, dl))
+			return_0;
+
+		for (i = 0; i < dl->pvd.pe_total; i++) {
+			lv_num = e[i].lv_num;
+
+			if (lv_num == UNMAPPED_EXTENT)
+				continue;
+
+			else {
+				lv_num--;
+				lvm = lvms[lv_num];
+
+				if (!lvm) {
+					log_error("Invalid LV in extent map "
+						  "(PV %s, PE %" PRIu32
+						  ", LV %" PRIu32
+						  ", LE %" PRIu32 ")",
+						  dev_name(pv->dev), i,
+						  lv_num, e[i].le_num);
+					return 0;
+				}
+
+				le = e[i].le_num;
+
+				if (le >= lvm->lv->le_count) {
+					log_err("logical extent number "
+						"out of bounds");
+					return 0;
+				}
+
+				if (lvm->map[le].pv) {
+					log_err("logical extent (%u) "
+						"already mapped.", le);
+					return 0;
+				}
+
+				lvm->map[le].pv = pv;
+				lvm->map[le].pe = i;
+			}
+		}
+	}
+
+	return 1;
+}
+
+static int _check_single_map(struct lv_map *lvm)
+{
+	uint32_t i;
+
+	for (i = 0; i < lvm->lv->le_count; i++) {
+		if (!lvm->map[i].pv) {
+			log_err("Logical volume (%s) contains an incomplete "
+				"mapping table.", lvm->lv->name);
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+static int _check_maps_are_complete(struct dm_hash_table *maps)
+{
+	struct dm_hash_node *n;
+	struct lv_map *lvm;
+
+	for (n = dm_hash_get_first(maps); n; n = dm_hash_get_next(maps, n)) {
+		lvm = (struct lv_map *) dm_hash_get_data(maps, n);
+
+		if (!_check_single_map(lvm))
+			return_0;
+	}
+	return 1;
+}
+
+static uint32_t _area_length(struct lv_map *lvm, uint32_t le)
+{
+	uint32_t len = 0;
+
+	do
+		len++;
+	while ((lvm->map[le + len].pv == lvm->map[le].pv) &&
+		 (lvm->map[le].pv &&
+		  lvm->map[le + len].pe == lvm->map[le].pe + len));
+
+	return len;
+}
+
+static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
+{
+	uint32_t le = 0, len;
+	struct lv_segment *seg;
+	struct segment_type *segtype;
+
+	if (!(segtype = get_segtype_from_string(cmd, "striped")))
+		return_0;
+
+	while (le < lvm->lv->le_count) {
+		len = _area_length(lvm, le);
+
+		if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv, le,
+					     len, 0, 0, NULL, 1, len, 0, 0, 0))) {
+			log_error("Failed to allocate linear segment.");
+			return 0;
+		}
+
+		if (!set_lv_segment_area_pv(seg, 0, lvm->map[le].pv,
+					    lvm->map[le].pe))
+			return_0;
+
+		dm_list_add(&lvm->lv->segments, &seg->list);
+
+		le += seg->len;
+	}
+
+	return 1;
+}
+
+static int _check_stripe(struct lv_map *lvm, uint32_t area_count,
+			 uint32_t area_len, uint32_t base_le,
+			 uint32_t total_area_len)
+{
+	uint32_t st;
+
+	/*
+	 * Is the next physical extent in every stripe adjacent to the last?
+	 */
+	for (st = 0; st < area_count; st++)
+		if ((lvm->map[base_le + st * total_area_len + area_len].pv !=
+		     lvm->map[base_le + st * total_area_len].pv) ||
+		    (lvm->map[base_le + st * total_area_len].pv &&
+		     lvm->map[base_le + st * total_area_len + area_len].pe !=
+		     lvm->map[base_le + st * total_area_len].pe + area_len))
+			return 0;
+
+	return 1;
+}
+
+static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
+{
+	uint32_t st, first_area_le = 0, total_area_len;
+	uint32_t area_len;
+	struct lv_segment *seg;
+	struct segment_type *segtype;
+
+	/*
+	 * Work out overall striped length
+	 */
+	if (lvm->lv->le_count % lvm->stripes) {
+		log_error("Number of stripes (%u) incompatible "
+			  "with logical extent count (%u) for %s",
+			  lvm->stripes, lvm->lv->le_count, lvm->lv->name);
+	}
+
+	total_area_len = lvm->lv->le_count / lvm->stripes;
+
+	if (!(segtype = get_segtype_from_string(cmd, "striped")))
+		return_0;
+
+	while (first_area_le < total_area_len) {
+		area_len = 1;
+
+		/*
+		 * Find how many extents are contiguous in all stripes
+		 * and so can form part of this segment
+		 */
+		while (_check_stripe(lvm, lvm->stripes,
+				     area_len, first_area_le, total_area_len))
+			area_len++;
+
+		if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv,
+					     lvm->stripes * first_area_le,
+					     lvm->stripes * area_len,
+					     0, lvm->stripe_size, NULL,
+					     lvm->stripes,
+					     area_len, 0, 0, 0))) {
+			log_error("Failed to allocate striped segment.");
+			return 0;
+		}
+
+		/*
+		 * Set up start positions of each stripe in this segment
+		 */
+		for (st = 0; st < seg->area_count; st++)
+			if (!set_lv_segment_area_pv(seg, st,
+			      lvm->map[first_area_le + st * total_area_len].pv,
+			      lvm->map[first_area_le + st * total_area_len].pe))
+				return_0;
+
+		dm_list_add(&lvm->lv->segments, &seg->list);
+
+		first_area_le += area_len;
+	}
+
+	return 1;
+}
+
+static int _build_segments(struct cmd_context *cmd, struct lv_map *lvm)
+{
+	return (lvm->stripes > 1 ? _read_stripes(cmd, lvm) :
+		_read_linear(cmd, lvm));
+}
+
+static int _build_all_segments(struct cmd_context *cmd, struct dm_hash_table *maps)
+{
+	struct dm_hash_node *n;
+	struct lv_map *lvm;
+
+	for (n = dm_hash_get_first(maps); n; n = dm_hash_get_next(maps, n)) {
+		lvm = (struct lv_map *) dm_hash_get_data(maps, n);
+		if (!_build_segments(cmd, lvm))
+			return_0;
+	}
+
+	return 1;
+}
+
+int import_extents(struct cmd_context *cmd, struct volume_group *vg,
+		   struct dm_list *pvds)
+{
+	int r = 0;
+	struct dm_pool *scratch = dm_pool_create("lvm1 import_extents", 10 * 1024);
+	struct dm_hash_table *maps;
+
+	if (!scratch)
+		return_0;
+
+	if (!(maps = _create_lv_maps(scratch, vg))) {
+		log_err("Couldn't allocate logical volume maps.");
+		goto out;
+	}
+
+	if (!_fill_maps(maps, vg, pvds)) {
+		log_err("Couldn't fill logical volume maps.");
+		goto out;
+	}
+
+	if (!_check_maps_are_complete(maps) && !(vg->status & PARTIAL_VG))
+		goto_out;
+
+	if (!_build_all_segments(cmd, maps)) {
+		log_err("Couldn't build extent segments.");
+		goto out;
+	}
+	r = 1;
+
+      out:
+	if (maps)
+		dm_hash_destroy(maps);
+	dm_pool_destroy(scratch);
+	return r;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/format1/layout.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format1/layout.c
diff -N src/external/gpl2/lvm2tools/dist/lib/format1/layout.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format1/layout.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,174 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "disk-rep.h"
+
+/*
+ * Only works with powers of 2.
+ */
+static uint32_t _round_up(uint32_t n, uint32_t size)
+{
+	size--;
+	return (n + size) & ~size;
+}
+
+/* Unused.
+static uint32_t _div_up(uint32_t n, uint32_t size)
+{
+	return _round_up(n, size) / size;
+}
+*/
+
+/*
+ * Each chunk of metadata should be aligned to
+ * METADATA_ALIGN.
+ */
+static uint32_t _next_base(struct data_area *area)
+{
+	return _round_up(area->base + area->size, METADATA_ALIGN);
+}
+
+/*
+ * Quick calculation based on pe_start.
+ */
+static int _adjust_pe_on_disk(struct pv_disk *pvd)
+{
+	uint32_t pe_start = pvd->pe_start << SECTOR_SHIFT;
+
+	if (pe_start < pvd->pe_on_disk.base + pvd->pe_on_disk.size)
+		return 0;
+
+	pvd->pe_on_disk.size = pe_start - pvd->pe_on_disk.base;
+	return 1;
+}
+
+static void _calc_simple_layout(struct pv_disk *pvd)
+{
+	pvd->pv_on_disk.base = METADATA_BASE;
+	pvd->pv_on_disk.size = PV_SIZE;
+
+	pvd->vg_on_disk.base = _next_base(&pvd->pv_on_disk);
+	pvd->vg_on_disk.size = VG_SIZE;
+
+	pvd->pv_uuidlist_on_disk.base = _next_base(&pvd->vg_on_disk);
+	pvd->pv_uuidlist_on_disk.size = MAX_PV * NAME_LEN;
+
+	pvd->lv_on_disk.base = _next_base(&pvd->pv_uuidlist_on_disk);
+	pvd->lv_on_disk.size = MAX_LV * sizeof(struct lv_disk);
+
+	pvd->pe_on_disk.base = _next_base(&pvd->lv_on_disk);
+	pvd->pe_on_disk.size = pvd->pe_total * sizeof(struct pe_disk);
+}
+
+static int _check_vg_limits(struct disk_list *dl)
+{
+	if (dl->vgd.lv_max > MAX_LV) {
+		log_error("MaxLogicalVolumes of %d exceeds format limit of %d "
+			  "for VG '%s'", dl->vgd.lv_max, MAX_LV - 1,
+			  dl->pvd.vg_name);
+		return 0;
+	}
+
+	if (dl->vgd.pv_max > MAX_PV) {
+		log_error("MaxPhysicalVolumes of %d exceeds format limit of %d "
+			  "for VG '%s'", dl->vgd.pv_max, MAX_PV - 1,
+			  dl->pvd.vg_name);
+		return 0;
+	}
+
+	return 1;
+}
+
+/*
+ * This assumes pe_count and pe_start have already
+ * been calculated correctly.
+ */
+int calculate_layout(struct disk_list *dl)
+{
+	struct pv_disk *pvd = &dl->pvd;
+
+	_calc_simple_layout(pvd);
+	if (!_adjust_pe_on_disk(pvd)) {
+		log_error("Insufficient space for metadata and PE's.");
+		return 0;
+	}
+
+	if (!_check_vg_limits(dl))
+		return 0;
+
+	return 1;
+}
+
+/*
+ * The number of extents that can fit on a disk is metadata format dependant.
+ * pe_start is any existing value for pe_start
+ */
+int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size,
+			   uint32_t max_extent_count, uint64_t pe_start)
+{
+	struct pv_disk *pvd = dm_malloc(sizeof(*pvd));
+	uint32_t end;
+
+	if (!pvd)
+		return_0;
+
+	/*
+	 * Guess how many extents will fit, bearing in mind that
+	 * one is going to be knocked off at the start of the
+	 * next loop.
+	 */
+	if (max_extent_count)
+		pvd->pe_total = max_extent_count + 1;
+	else
+		pvd->pe_total = (pv->size / extent_size);
+
+	if (pvd->pe_total < PE_SIZE_PV_SIZE_REL) {
+		log_error("Too few extents on %s.  Try smaller extent size.",
+			  pv_dev_name(pv));
+		dm_free(pvd);
+		return 0;
+	}
+
+	do {
+		pvd->pe_total--;
+		_calc_simple_layout(pvd);
+		end = ((pvd->pe_on_disk.base + pvd->pe_on_disk.size +
+			SECTOR_SIZE - 1) >> SECTOR_SHIFT);
+
+		if (pe_start && end < pe_start)
+			end = pe_start;
+
+		pvd->pe_start = _round_up(end, LVM1_PE_ALIGN);
+
+	} while ((pvd->pe_start + (pvd->pe_total * extent_size))
+		 > pv->size);
+
+	if (pvd->pe_total > MAX_PE_TOTAL) {
+		log_error("Metadata extent limit (%u) exceeded for %s - "
+			  "%u required", MAX_PE_TOTAL, pv_dev_name(pv),
+			  pvd->pe_total);
+		dm_free(pvd);
+		return 0;
+	}
+
+	pv->pe_count = pvd->pe_total;
+	pv->pe_start = pvd->pe_start;
+	/* We can't set pe_size here without breaking LVM1 compatibility */
+	dm_free(pvd);
+	return 1;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/format1/lvm1-label.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format1/lvm1-label.c
diff -N src/external/gpl2/lvm2tools/dist/lib/format1/lvm1-label.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format1/lvm1-label.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,132 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "lvm1-label.h"
+#include "disk-rep.h"
+#include "label.h"
+#include "metadata.h"
+#include "xlate.h"
+#include "format1.h"
+
+#include <sys/stat.h>
+#include <fcntl.h>
+
+static void _not_supported(const char *op)
+{
+	log_err("The '%s' operation is not supported for the lvm1 labeller.",
+		op);
+}
+
+static int _lvm1_can_handle(struct labeller *l __attribute((unused)), void *buf, uint64_t sector)
+{
+	struct pv_disk *pvd = (struct pv_disk *) buf;
+	uint32_t version;
+
+	/* LVM1 label must always be in first sector */
+	if (sector)
+		return 0;
+
+	version = xlate16(pvd->version);
+
+	if (pvd->id[0] == 'H' && pvd->id[1] == 'M' &&
+	    (version == 1 || version == 2))
+		return 1;
+
+	return 0;
+}
+
+static int _lvm1_write(struct label *label __attribute((unused)), void *buf __attribute((unused)))
+{
+	_not_supported("write");
+	return 0;
+}
+
+static int _lvm1_read(struct labeller *l, struct device *dev, void *buf,
+		 struct label **label)
+{
+	struct pv_disk *pvd = (struct pv_disk *) buf;
+	struct vg_disk vgd;
+	struct lvmcache_info *info;
+	const char *vgid = FMT_LVM1_ORPHAN_VG_NAME;
+	const char *vgname = FMT_LVM1_ORPHAN_VG_NAME;
+	unsigned exported = 0;
+
+	munge_pvd(dev, pvd);
+
+	if (*pvd->vg_name) {
+		if (!read_vgd(dev, &vgd, pvd))
+			return_0;
+		vgid = (char *) vgd.vg_uuid;
+		vgname = (char *) pvd->vg_name;
+		exported = pvd->pv_status & VG_EXPORTED;
+	}
+
+	if (!(info = lvmcache_add(l, (char *)pvd->pv_uuid, dev, vgname, vgid,
+				  exported)))
+		return_0;
+	*label = info->label;
+
+	info->device_size = xlate32(pvd->pv_size) << SECTOR_SHIFT;
+	dm_list_init(&info->mdas);
+
+	info->status &= ~CACHE_INVALID;
+
+	return 1;
+}
+
+static int _lvm1_initialise_label(struct labeller *l __attribute((unused)), struct label *label)
+{
+	strcpy(label->type, "LVM1");
+
+	return 1;
+}
+
+static void _lvm1_destroy_label(struct labeller *l __attribute((unused)), struct label *label __attribute((unused)))
+{
+	return;
+}
+
+static void _lvm1_destroy(struct labeller *l)
+{
+	dm_free(l);
+}
+
+struct label_ops _lvm1_ops = {
+	.can_handle = _lvm1_can_handle,
+	.write = _lvm1_write,
+	.read = _lvm1_read,
+	.verify = _lvm1_can_handle,
+	.initialise_label = _lvm1_initialise_label,
+	.destroy_label = _lvm1_destroy_label,
+	.destroy = _lvm1_destroy,
+};
+
+struct labeller *lvm1_labeller_create(struct format_type *fmt)
+{
+	struct labeller *l;
+
+	if (!(l = dm_malloc(sizeof(*l)))) {
+		log_err("Couldn't allocate labeller object.");
+		return NULL;
+	}
+
+	l->ops = &_lvm1_ops;
+	l->private = (const void *) fmt;
+
+	return l;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/format1/lvm1-label.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format1/lvm1-label.h
diff -N src/external/gpl2/lvm2tools/dist/lib/format1/lvm1-label.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format1/lvm1-label.h	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,25 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_LVM1_LABEL_H
+#define _LVM_LVM1_LABEL_H
+
+#include "metadata.h"
+
+struct labeller *lvm1_labeller_create(struct format_type *fmt);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/format1/vg_number.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format1/vg_number.c
diff -N src/external/gpl2/lvm2tools/dist/lib/format1/vg_number.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format1/vg_number.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,64 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "disk-rep.h"
+
+/*
+ * FIXME: Quick hack.  We can use caching to
+ * prevent a total re-read, even so vg_number
+ * causes the tools to check *every* pv.  Yuck.
+ * Put in separate file so it wouldn't contaminate
+ * other code.
+ */
+int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
+		       const char *candidate_vg, int *result)
+{
+	struct dm_list all_pvs;
+	struct disk_list *dl;
+	struct dm_pool *mem = dm_pool_create("lvm1 vg_number", 10 * 1024);
+	int numbers[MAX_VG], i, r = 0;
+
+	dm_list_init(&all_pvs);
+
+	if (!mem)
+		return_0;
+
+	if (!read_pvs_in_vg(fid->fmt, NULL, filter, mem, &all_pvs))
+		goto_out;
+
+	memset(numbers, 0, sizeof(numbers));
+
+	dm_list_iterate_items(dl, &all_pvs) {
+		if (!*dl->pvd.vg_name || !strcmp((char *)dl->pvd.vg_name, candidate_vg))
+			continue;
+
+		numbers[dl->vgd.vg_number] = 1;
+	}
+
+	for (i = 0; i < MAX_VG; i++) {
+		if (!numbers[i]) {
+			r = 1;
+			*result = i;
+			break;
+		}
+	}
+
+      out:
+	dm_pool_destroy(mem);
+	return r;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/format_pool/.exported_symbols
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format_pool/.exported_symbols
diff -N src/external/gpl2/lvm2tools/dist/lib/format_pool/.exported_symbols
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format_pool/.exported_symbols	15 Jul 2008 13:49:34 -0000	1.1.1.1
@@ -0,0 +1 @@
+init_format
Index: src/external/gpl2/lvm2tools/dist/lib/format_pool/Makefile.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format_pool/Makefile.in
diff -N src/external/gpl2/lvm2tools/dist/lib/format_pool/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format_pool/Makefile.in	12 Dec 2008 16:32:59 -0000	1.1.1.1.2.1
@@ -0,0 +1,36 @@
+#
+# Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
+# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+SOURCES =\
+	disk_rep.c \
+	format_pool.c \
+	import_export.c \
+	pool_label.c
+
+LIB_SHARED = liblvm2formatpool.so
+LIB_VERSION = $(LIB_VERSION_LVM)
+
+include $(top_srcdir)/make.tmpl
+
+install: liblvm2formatpool.so
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
+		$(libdir)/liblvm2formatpool.so.$(LIB_VERSION)
+	$(LN_S) -f liblvm2formatpool.so.$(LIB_VERSION) \
+		$(libdir)/liblvm2formatpool.so
+
+
Index: src/external/gpl2/lvm2tools/dist/lib/format_pool/disk_rep.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format_pool/disk_rep.c
diff -N src/external/gpl2/lvm2tools/dist/lib/format_pool/disk_rep.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format_pool/disk_rep.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,370 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "label.h"
+#include "metadata.h"
+#include "lvmcache.h"
+#include "filter.h"
+#include "xlate.h"
+#include "disk_rep.h"
+
+#include <assert.h>
+
+/* FIXME: memcpy might not be portable */
+#define CPIN_8(x, y, z) {memcpy((x), (y), (z));}
+#define CPOUT_8(x, y, z) {memcpy((y), (x), (z));}
+#define CPIN_16(x, y) {(x) = xlate16_be((y));}
+#define CPOUT_16(x, y) {(y) = xlate16_be((x));}
+#define CPIN_32(x, y) {(x) = xlate32_be((y));}
+#define CPOUT_32(x, y) {(y) = xlate32_be((x));}
+#define CPIN_64(x, y) {(x) = xlate64_be((y));}
+#define CPOUT_64(x, y) {(y) = xlate64_be((x));}
+
+static int __read_pool_disk(const struct format_type *fmt, struct device *dev,
+			    struct dm_pool *mem __attribute((unused)), struct pool_list *pl,
+			    const char *vg_name __attribute((unused)))
+{
+	char buf[512] __attribute((aligned(8)));
+
+	/* FIXME: Need to check the cache here first */
+	if (!dev_read(dev, UINT64_C(0), 512, buf)) {
+		log_very_verbose("Failed to read PV data from %s",
+				 dev_name(dev));
+		return 0;
+	}
+
+	if (!read_pool_label(pl, fmt->labeller, dev, buf, NULL))
+		return_0;
+
+	return 1;
+}
+
+static void _add_pl_to_list(struct dm_list *head, struct pool_list *data)
+{
+	struct pool_list *pl;
+
+	dm_list_iterate_items(pl, head) {
+		if (id_equal(&data->pv_uuid, &pl->pv_uuid)) {
+			char uuid[ID_LEN + 7] __attribute((aligned(8)));
+
+			id_write_format(&pl->pv_uuid, uuid, ID_LEN + 7);
+
+			if (MAJOR(data->dev->dev) != md_major()) {
+				log_very_verbose("Ignoring duplicate PV %s on "
+						 "%s", uuid,
+						 dev_name(data->dev));
+				return;
+			}
+			log_very_verbose("Duplicate PV %s - using md %s",
+					 uuid, dev_name(data->dev));
+			dm_list_del(&pl->list);
+			break;
+		}
+	}
+	dm_list_add(head, &data->list);
+}
+
+int read_pool_label(struct pool_list *pl, struct labeller *l,
+		    struct device *dev, char *buf, struct label **label)
+{
+	struct lvmcache_info *info;
+	struct id pvid;
+	struct id vgid;
+	char uuid[ID_LEN + 7] __attribute((aligned(8)));
+	struct pool_disk *pd = &pl->pd;
+
+	pool_label_in(pd, buf);
+
+	get_pool_pv_uuid(&pvid, pd);
+	id_write_format(&pvid, uuid, ID_LEN + 7);
+	log_debug("Calculated uuid %s for %s", uuid, dev_name(dev));
+
+	get_pool_vg_uuid(&vgid, pd);
+	id_write_format(&vgid, uuid, ID_LEN + 7);
+	log_debug("Calculated uuid %s for %s", uuid, pd->pl_pool_name);
+
+	if (!(info = lvmcache_add(l, (char *) &pvid, dev, pd->pl_pool_name,
+				  (char *) &vgid, 0)))
+		return_0;
+	if (label)
+		*label = info->label;
+
+	info->device_size = xlate32_be(pd->pl_blocks) << SECTOR_SHIFT;
+	dm_list_init(&info->mdas);
+
+	info->status &= ~CACHE_INVALID;
+
+	pl->dev = dev;
+	pl->pv = NULL;
+	memcpy(&pl->pv_uuid, &pvid, sizeof(pvid));
+
+	return 1;
+}
+
+/**
+ * pool_label_out - copies a pool_label_t into a char buffer
+ * @pl: ptr to a pool_label_t struct
+ * @buf: ptr to raw space where label info will be copied
+ *
+ * This function is important because it takes care of all of
+ * the endian issues when copying to disk.  This way, when
+ * machines of different architectures are used, they will
+ * be able to interpret ondisk labels correctly.  Always use
+ * this function before writing to disk.
+ */
+void pool_label_out(struct pool_disk *pl, void *buf)
+{
+	struct pool_disk *bufpl = (struct pool_disk *) buf;
+
+	CPOUT_64(pl->pl_magic, bufpl->pl_magic);
+	CPOUT_64(pl->pl_pool_id, bufpl->pl_pool_id);
+	CPOUT_8(pl->pl_pool_name, bufpl->pl_pool_name, POOL_NAME_SIZE);
+	CPOUT_32(pl->pl_version, bufpl->pl_version);
+	CPOUT_32(pl->pl_subpools, bufpl->pl_subpools);
+	CPOUT_32(pl->pl_sp_id, bufpl->pl_sp_id);
+	CPOUT_32(pl->pl_sp_devs, bufpl->pl_sp_devs);
+	CPOUT_32(pl->pl_sp_devid, bufpl->pl_sp_devid);
+	CPOUT_32(pl->pl_sp_type, bufpl->pl_sp_type);
+	CPOUT_64(pl->pl_blocks, bufpl->pl_blocks);
+	CPOUT_32(pl->pl_striping, bufpl->pl_striping);
+	CPOUT_32(pl->pl_sp_dmepdevs, bufpl->pl_sp_dmepdevs);
+	CPOUT_32(pl->pl_sp_dmepid, bufpl->pl_sp_dmepid);
+	CPOUT_32(pl->pl_sp_weight, bufpl->pl_sp_weight);
+	CPOUT_32(pl->pl_minor, bufpl->pl_minor);
+	CPOUT_32(pl->pl_padding, bufpl->pl_padding);
+	CPOUT_8(pl->pl_reserve, bufpl->pl_reserve, 184);
+}
+
+/**
+ * pool_label_in - copies a char buffer into a pool_label_t
+ * @pl: ptr to a pool_label_t struct
+ * @buf: ptr to raw space where label info is copied from
+ *
+ * This function is important because it takes care of all of
+ * the endian issues when information from disk is about to be
+ * used.  This way, when machines of different architectures
+ * are used, they will be able to interpret ondisk labels
+ * correctly.  Always use this function before using labels that
+ * were read from disk.
+ */
+void pool_label_in(struct pool_disk *pl, void *buf)
+{
+	struct pool_disk *bufpl = (struct pool_disk *) buf;
+
+	CPIN_64(pl->pl_magic, bufpl->pl_magic);
+	CPIN_64(pl->pl_pool_id, bufpl->pl_pool_id);
+	CPIN_8(pl->pl_pool_name, bufpl->pl_pool_name, POOL_NAME_SIZE);
+	CPIN_32(pl->pl_version, bufpl->pl_version);
+	CPIN_32(pl->pl_subpools, bufpl->pl_subpools);
+	CPIN_32(pl->pl_sp_id, bufpl->pl_sp_id);
+	CPIN_32(pl->pl_sp_devs, bufpl->pl_sp_devs);
+	CPIN_32(pl->pl_sp_devid, bufpl->pl_sp_devid);
+	CPIN_32(pl->pl_sp_type, bufpl->pl_sp_type);
+	CPIN_64(pl->pl_blocks, bufpl->pl_blocks);
+	CPIN_32(pl->pl_striping, bufpl->pl_striping);
+	CPIN_32(pl->pl_sp_dmepdevs, bufpl->pl_sp_dmepdevs);
+	CPIN_32(pl->pl_sp_dmepid, bufpl->pl_sp_dmepid);
+	CPIN_32(pl->pl_sp_weight, bufpl->pl_sp_weight);
+	CPIN_32(pl->pl_minor, bufpl->pl_minor);
+	CPIN_32(pl->pl_padding, bufpl->pl_padding);
+	CPIN_8(pl->pl_reserve, bufpl->pl_reserve, 184);
+}
+
+static char _calc_char(unsigned int id)
+{
+	/*
+	 * [0-9A-Za-z!#] - 64 printable chars (6-bits)
+	 */
+
+	if (id < 10)
+		return id + 48;
+	if (id < 36)
+		return (id - 10) + 65;
+	if (id < 62)
+		return (id - 36) + 97;
+	if (id == 62)
+		return '!';
+	if (id == 63)
+		return '#';
+
+	return '%';
+}
+
+void get_pool_uuid(char *uuid, uint64_t poolid, uint32_t spid, uint32_t devid)
+{
+	int i;
+	unsigned shifter = 0x003F;
+
+	assert(ID_LEN == 32);
+	memset(uuid, 0, ID_LEN);
+	strcat(uuid, "POOL0000000000");
+
+	/* We grab the entire 64 bits (+2 that get shifted in) */
+	for (i = 13; i < 24; i++) {
+		uuid[i] = _calc_char(((unsigned) poolid) & shifter);
+		poolid = poolid >> 6;
+	}
+
+	/* We grab the entire 32 bits (+4 that get shifted in) */
+	for (i = 24; i < 30; i++) {
+		uuid[i] = _calc_char((unsigned) (spid & shifter));
+		spid = spid >> 6;
+	}
+
+	/*
+	 * Since we can only have 128 devices, we only worry about the
+	 * last 12 bits
+	 */
+	for (i = 30; i < 32; i++) {
+		uuid[i] = _calc_char((unsigned) (devid & shifter));
+		devid = devid >> 6;
+	}
+
+}
+
+static int _read_vg_pds(const struct format_type *fmt, struct dm_pool *mem,
+			struct lvmcache_vginfo *vginfo, struct dm_list *head,
+			uint32_t *devcount)
+{
+	struct lvmcache_info *info;
+	struct pool_list *pl = NULL;
+	struct dm_pool *tmpmem;
+
+	uint32_t sp_count = 0;
+	uint32_t *sp_devs = NULL;
+	uint32_t i;
+
+	/* FIXME: maybe should return a different error in memory
+	 * allocation failure */
+	if (!(tmpmem = dm_pool_create("pool read_vg", 512)))
+		return_0;
+
+	dm_list_iterate_items(info, &vginfo->infos) {
+		if (info->dev &&
+		    !(pl = read_pool_disk(fmt, info->dev, mem, vginfo->vgname)))
+			    break;
+		/*
+		 * We need to keep track of the total expected number
+		 * of devices per subpool
+		 */
+		if (!sp_count) {
+			/* FIXME pl left uninitialised if !info->dev */
+			sp_count = pl->pd.pl_subpools;
+			if (!(sp_devs =
+			      dm_pool_zalloc(tmpmem,
+					  sizeof(uint32_t) * sp_count))) {
+				log_error("Unable to allocate %d 32-bit uints",
+					  sp_count);
+				dm_pool_destroy(tmpmem);
+				return 0;
+			}
+		}
+		/*
+		 * watch out for a pool label with a different subpool
+		 * count than the original - give up if it does
+		 */
+		if (sp_count != pl->pd.pl_subpools)
+			break;
+
+		_add_pl_to_list(head, pl);
+
+		if (sp_count > pl->pd.pl_sp_id && sp_devs[pl->pd.pl_sp_id] == 0)
+			sp_devs[pl->pd.pl_sp_id] = pl->pd.pl_sp_devs;
+	}
+
+	*devcount = 0;
+	for (i = 0; i < sp_count; i++)
+		*devcount += sp_devs[i];
+
+	dm_pool_destroy(tmpmem);
+
+	if (pl && *pl->pd.pl_pool_name)
+		return 1;
+
+	return 0;
+
+}
+
+int read_pool_pds(const struct format_type *fmt, const char *vg_name,
+		  struct dm_pool *mem, struct dm_list *pdhead)
+{
+	struct lvmcache_vginfo *vginfo;
+	uint32_t totaldevs;
+	int full_scan = -1;
+
+	do {
+		/*
+		 * If the cache scanning doesn't work, this will never work
+		 */
+		if (vg_name && (vginfo = vginfo_from_vgname(vg_name, NULL)) &&
+		    vginfo->infos.n) {
+
+			if (_read_vg_pds(fmt, mem, vginfo, pdhead, &totaldevs)) {
+				/*
+				 * If we found all the devices we were
+				 * expecting, return success
+				 */
+				if (dm_list_size(pdhead) == totaldevs)
+					return 1;
+
+				/*
+				 * accept partial pool if we've done a full
+				 * rescan of the cache
+				 */
+				if (full_scan > 0)
+					return 1;
+			}
+		}
+		/* Failed */
+		dm_list_init(pdhead);
+
+		full_scan++;
+		if (full_scan > 1) {
+			log_debug("No devices for vg %s found in cache",
+				  vg_name);
+			return 0;
+		}
+		lvmcache_label_scan(fmt->cmd, full_scan);
+
+	} while (1);
+
+}
+
+struct pool_list *read_pool_disk(const struct format_type *fmt,
+				 struct device *dev, struct dm_pool *mem,
+				 const char *vg_name)
+{
+	struct pool_list *pl;
+
+	if (!dev_open(dev))
+		return_NULL;
+
+	if (!(pl = dm_pool_zalloc(mem, sizeof(*pl)))) {
+		log_error("Unable to allocate pool list structure");
+		return 0;
+	}
+
+	if (!__read_pool_disk(fmt, dev, mem, pl, vg_name))
+		return_NULL;
+
+	if (!dev_close(dev))
+		stack;
+
+	return pl;
+
+}
Index: src/external/gpl2/lvm2tools/dist/lib/format_pool/disk_rep.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format_pool/disk_rep.h
diff -N src/external/gpl2/lvm2tools/dist/lib/format_pool/disk_rep.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format_pool/disk_rep.h	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,158 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef DISK_REP_FORMAT_POOL_H
+#define DISK_REP_FORMAT_POOL_H
+
+#include "label.h"
+#include "metadata.h"
+
+#define MINOR_OFFSET 65536
+
+/* From NSP.cf */
+#define NSPMajorVersion	4
+#define NSPMinorVersion	1
+#define NSPUpdateLevel	3
+
+/* From pool_std.h */
+#define POOL_NAME_SIZE          (256)
+#define POOL_MAGIC 		0x011670
+#define POOL_MAJOR              (121)
+#define POOL_MAX_DEVICES 	128
+
+/* When checking for version matching, the first two numbers **
+** are important for metadata formats, a.k.a pool labels.   **
+** All the numbers are important when checking if the user  **
+** space tools match up with the kernel module............. */
+#define POOL_VERSION		(NSPMajorVersion << 16 | \
+				 NSPMinorVersion <<  8 | \
+				 NSPUpdateLevel)
+
+/* Pool label is at the head of every pool disk partition */
+#define SIZEOF_POOL_LABEL       (8192)
+
+/* in sectors */
+#define POOL_PE_SIZE     (SIZEOF_POOL_LABEL >> SECTOR_SHIFT)
+#define POOL_PE_START    (SIZEOF_POOL_LABEL >> SECTOR_SHIFT)
+
+/* Helper fxns */
+#define get_pool_vg_uuid(id, pd) do { get_pool_uuid((char *)(id), \
+                                                    (pd)->pl_pool_id, 0, 0); \
+                                    } while(0)
+#define get_pool_pv_uuid(id, pd) do { get_pool_uuid((char *)(id), \
+                                                    (pd)->pl_pool_id, \
+                                                    (pd)->pl_sp_id, \
+                                                    (pd)->pl_sp_devid); \
+                                    } while(0)
+#define get_pool_lv_uuid(id, pd) do { get_pool_uuid((char *)&(id)[0], \
+                                                    (pd)->pl_pool_id, 0, 0); \
+                                      get_pool_uuid((char*)&(id)[1], \
+                                                    (pd)->pl_pool_id, 0, 0); \
+                                    } while(0)
+
+struct pool_disk;
+struct pool_list;
+struct user_subpool;
+struct user_device;
+
+struct pool_disk {
+	uint64_t pl_magic;	/* Pool magic number */
+	uint64_t pl_pool_id;	/* Unique pool identifier */
+	char pl_pool_name[POOL_NAME_SIZE];	/* Name of pool */
+	uint32_t pl_version;	/* Pool version */
+	uint32_t pl_subpools;	/* Number of subpools in this pool */
+	uint32_t pl_sp_id;	/* Subpool number within pool */
+	uint32_t pl_sp_devs;	/* Number of data partitions in this subpool */
+	uint32_t pl_sp_devid;	/* Partition number within subpool */
+	uint32_t pl_sp_type;	/* Partition type */
+	uint64_t pl_blocks;	/* Number of blocks in this partition */
+	uint32_t pl_striping;	/* Striping size within subpool */
+	/*
+	 * If the number of DMEP devices is zero, then the next field **
+	 * ** (pl_sp_dmepid) becomes the subpool ID for redirection.  In **
+	 * ** other words, if this subpool does not have the capability  **
+	 * ** to do DMEP, then it must specify which subpool will do it  **
+	 * ** in it's place
+	 */
+
+	/*
+	 * While the next 3 field are no longer used, they must stay to keep **
+	 * ** backward compatibility...........................................
+	 */
+	uint32_t pl_sp_dmepdevs;/* Number of dmep devices in this subpool */
+	uint32_t pl_sp_dmepid;	/* Dmep device number within subpool */
+	uint32_t pl_sp_weight;	/* if dmep dev, pref to using it */
+
+	uint32_t pl_minor;	/* the pool minor number */
+	uint32_t pl_padding;	/* reminder - think about alignment */
+
+	/*
+	 * Even though we're zeroing out 8k at the front of the disk before
+	 * writing the label, putting this in
+	 */
+	char pl_reserve[184];	/* bump the structure size out to 512 bytes */
+};
+
+struct pool_list {
+	struct dm_list list;
+	struct pool_disk pd;
+	struct physical_volume *pv;
+	struct id pv_uuid;
+	struct device *dev;
+};
+
+struct user_subpool {
+	uint32_t initialized;
+	uint32_t id;
+	uint32_t striping;
+	uint32_t num_devs;
+	uint32_t type;
+	uint32_t dummy;
+	struct user_device *devs;
+};
+
+struct user_device {
+	uint32_t initialized;
+	uint32_t sp_id;
+	uint32_t devid;
+	uint32_t dummy;
+	uint64_t blocks;
+	struct physical_volume *pv;
+};
+
+int read_pool_label(struct pool_list *pl, struct labeller *l,
+		    struct device *dev, char *buf, struct label **label);
+void pool_label_out(struct pool_disk *pl, void *buf);
+void pool_label_in(struct pool_disk *pl, void *buf);
+void get_pool_uuid(char *uuid, uint64_t poolid, uint32_t spid, uint32_t devid);
+int import_pool_vg(struct volume_group *vg, struct dm_pool *mem, struct dm_list *pls);
+int import_pool_lvs(struct volume_group *vg, struct dm_pool *mem,
+		    struct dm_list *pls);
+int import_pool_pvs(const struct format_type *fmt, struct volume_group *vg,
+		    struct dm_list *pvs, struct dm_pool *mem, struct dm_list *pls);
+int import_pool_pv(const struct format_type *fmt, struct dm_pool *mem,
+		   struct volume_group *vg, struct physical_volume *pv,
+		   struct pool_list *pl);
+int import_pool_segments(struct dm_list *lvs, struct dm_pool *mem,
+			 struct user_subpool *usp, int sp_count);
+int read_pool_pds(const struct format_type *fmt, const char *vgname,
+		  struct dm_pool *mem, struct dm_list *head);
+struct pool_list *read_pool_disk(const struct format_type *fmt,
+				 struct device *dev, struct dm_pool *mem,
+				 const char *vg_name);
+
+#endif				/* DISK_REP_POOL_FORMAT_H */
Index: src/external/gpl2/lvm2tools/dist/lib/format_pool/format_pool.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format_pool/format_pool.c
diff -N src/external/gpl2/lvm2tools/dist/lib/format_pool/format_pool.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format_pool/format_pool.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,336 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "label.h"
+#include "metadata.h"
+#include "limits.h"
+#include "display.h"
+#include "toolcontext.h"
+#include "lvmcache.h"
+#include "disk_rep.h"
+#include "format_pool.h"
+#include "pool_label.h"
+
+/* Must be called after pvs are imported */
+static struct user_subpool *_build_usp(struct dm_list *pls, struct dm_pool *mem,
+				       int *sps)
+{
+	struct pool_list *pl;
+	struct user_subpool *usp = NULL, *cur_sp = NULL;
+	struct user_device *cur_dev = NULL;
+
+	/*
+	 * FIXME: Need to do some checks here - I'm tempted to add a
+	 * user_pool structure and build the entire thing to check against.
+	 */
+	dm_list_iterate_items(pl, pls) {
+		*sps = pl->pd.pl_subpools;
+		if (!usp && (!(usp = dm_pool_zalloc(mem, sizeof(*usp) * (*sps))))) {
+			log_error("Unable to allocate %d subpool structures",
+				  *sps);
+			return 0;
+		}
+
+		if (cur_sp != &usp[pl->pd.pl_sp_id]) {
+			cur_sp = &usp[pl->pd.pl_sp_id];
+
+			cur_sp->id = pl->pd.pl_sp_id;
+			cur_sp->striping = pl->pd.pl_striping;
+			cur_sp->num_devs = pl->pd.pl_sp_devs;
+			cur_sp->type = pl->pd.pl_sp_type;
+			cur_sp->initialized = 1;
+		}
+
+		if (!cur_sp->devs &&
+		    (!(cur_sp->devs =
+		       dm_pool_zalloc(mem,
+				   sizeof(*usp->devs) * pl->pd.pl_sp_devs)))) {
+
+			log_error("Unable to allocate %d pool_device "
+				  "structures", pl->pd.pl_sp_devs);
+			return 0;
+		}
+
+		cur_dev = &cur_sp->devs[pl->pd.pl_sp_devid];
+		cur_dev->sp_id = cur_sp->id;
+		cur_dev->devid = pl->pd.pl_sp_id;
+		cur_dev->blocks = pl->pd.pl_blocks;
+		cur_dev->pv = pl->pv;
+		cur_dev->initialized = 1;
+	}
+
+	return usp;
+}
+
+static int _check_usp(char *vgname, struct user_subpool *usp, int sp_count)
+{
+	int i;
+	unsigned j;
+
+	for (i = 0; i < sp_count; i++) {
+		if (!usp[i].initialized) {
+			log_error("Missing subpool %d in pool %s", i, vgname);
+			return 0;
+		}
+		for (j = 0; j < usp[i].num_devs; j++) {
+			if (!usp[i].devs[j].initialized) {
+				log_error("Missing device %u for subpool %d"
+					  " in pool %s", j, i, vgname);
+				return 0;
+			}
+
+		}
+	}
+
+	return 1;
+}
+
+static struct volume_group *_build_vg_from_pds(struct format_instance
+					       *fid, struct dm_pool *mem,
+					       struct dm_list *pds)
+{
+	struct dm_pool *smem = fid->fmt->cmd->mem;
+	struct volume_group *vg = NULL;
+	struct user_subpool *usp = NULL;
+	int sp_count;
+
+	if (!(vg = dm_pool_zalloc(smem, sizeof(*vg)))) {
+		log_error("Unable to allocate volume group structure");
+		return NULL;
+	}
+
+	vg->cmd = fid->fmt->cmd;
+	vg->fid = fid;
+	vg->name = NULL;
+	vg->status = 0;
+	vg->extent_count = 0;
+	vg->pv_count = 0;
+	vg->lv_count = 0;
+	vg->snapshot_count = 0;
+	vg->seqno = 1;
+	vg->system_id = NULL;
+	dm_list_init(&vg->pvs);
+	dm_list_init(&vg->lvs);
+	dm_list_init(&vg->tags);
+
+	if (!import_pool_vg(vg, smem, pds))
+		return_NULL;
+
+	if (!import_pool_pvs(fid->fmt, vg, &vg->pvs, smem, pds))
+		return_NULL;
+
+	if (!import_pool_lvs(vg, smem, pds))
+		return_NULL;
+
+	/*
+	 * I need an intermediate subpool structure that contains all the
+	 * relevant info for this.  Then i can iterate through the subpool
+	 * structures for checking, and create the segments
+	 */
+	if (!(usp = _build_usp(pds, mem, &sp_count)))
+		return_NULL;
+
+	/*
+	 * check the subpool structures - we can't handle partial VGs in
+	 * the pool format, so this will error out if we're missing PVs
+	 */
+	if (!_check_usp(vg->name, usp, sp_count))
+		return_NULL;
+
+	if (!import_pool_segments(&vg->lvs, smem, usp, sp_count))
+		return_NULL;
+
+	return vg;
+}
+
+static struct volume_group *_pool_vg_read(struct format_instance *fid,
+				     const char *vg_name,
+				     struct metadata_area *mda __attribute((unused)))
+{
+	struct dm_pool *mem = dm_pool_create("pool vg_read", 1024);
+	struct dm_list pds;
+	struct volume_group *vg = NULL;
+
+	dm_list_init(&pds);
+
+	/* We can safely ignore the mda passed in */
+
+	if (!mem)
+		return_NULL;
+
+	/* Strip dev_dir if present */
+	vg_name = strip_dir(vg_name, fid->fmt->cmd->dev_dir);
+
+	/* Read all the pvs in the vg */
+	if (!read_pool_pds(fid->fmt, vg_name, mem, &pds))
+		goto_out;
+
+	/* Do the rest of the vg stuff */
+	if (!(vg = _build_vg_from_pds(fid, mem, &pds)))
+		goto_out;
+
+      out:
+	dm_pool_destroy(mem);
+	return vg;
+}
+
+static int _pool_pv_setup(const struct format_type *fmt __attribute((unused)),
+			  uint64_t pe_start __attribute((unused)),
+			  uint32_t extent_count __attribute((unused)),
+			  uint32_t extent_size __attribute((unused)),
+			  int pvmetadatacopies __attribute((unused)),
+			  uint64_t pvmetadatasize __attribute((unused)),
+			  struct dm_list *mdas __attribute((unused)),
+			  struct physical_volume *pv __attribute((unused)),
+			  struct volume_group *vg __attribute((unused)))
+{
+	return 1;
+}
+
+static int _pool_pv_read(const struct format_type *fmt, const char *pv_name,
+			 struct physical_volume *pv,
+			 struct dm_list *mdas __attribute((unused)))
+{
+	struct dm_pool *mem = dm_pool_create("pool pv_read", 1024);
+	struct pool_list *pl;
+	struct device *dev;
+	int r = 0;
+
+	log_very_verbose("Reading physical volume data %s from disk", pv_name);
+
+	if (!mem)
+		return_0;
+
+	if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter)))
+		goto_out;
+
+	/*
+	 * I need to read the disk and populate a pv structure here
+	 * I'll probably need to abstract some of this later for the
+	 * vg_read code
+	 */
+	if (!(pl = read_pool_disk(fmt, dev, mem, NULL)))
+		goto_out;
+
+	if (!import_pool_pv(fmt, fmt->cmd->mem, NULL, pv, pl))
+		goto_out;
+
+	pv->fmt = fmt;
+
+	r = 1;
+
+      out:
+	dm_pool_destroy(mem);
+	return r;
+}
+
+/* *INDENT-OFF* */
+static struct metadata_area_ops _metadata_format_pool_ops = {
+	.vg_read = _pool_vg_read,
+};
+/* *INDENT-ON* */
+
+static struct format_instance *_pool_create_instance(const struct format_type *fmt,
+						const char *vgname __attribute((unused)),
+						const char *vgid __attribute((unused)),
+						void *private __attribute((unused)))
+{
+	struct format_instance *fid;
+	struct metadata_area *mda;
+
+	if (!(fid = dm_pool_zalloc(fmt->cmd->mem, sizeof(*fid)))) {
+		log_error("Unable to allocate format instance structure for "
+			  "pool format");
+		return NULL;
+	}
+
+	fid->fmt = fmt;
+	dm_list_init(&fid->metadata_areas);
+
+	/* Define a NULL metadata area */
+	if (!(mda = dm_pool_zalloc(fmt->cmd->mem, sizeof(*mda)))) {
+		log_error("Unable to allocate metadata area structure "
+			  "for pool format");
+		dm_pool_free(fmt->cmd->mem, fid);
+		return NULL;
+	}
+
+	mda->ops = &_metadata_format_pool_ops;
+	mda->metadata_locn = NULL;
+	dm_list_add(&fid->metadata_areas, &mda->list);
+
+	return fid;
+}
+
+static void _pool_destroy_instance(struct format_instance *fid __attribute((unused)))
+{
+	return;
+}
+
+static void _pool_destroy(const struct format_type *fmt)
+{
+	dm_free((void *) fmt);
+}
+
+/* *INDENT-OFF* */
+static struct format_handler _format_pool_ops = {
+	.pv_read = _pool_pv_read,
+	.pv_setup = _pool_pv_setup,
+	.create_instance = _pool_create_instance,
+	.destroy_instance = _pool_destroy_instance,
+	.destroy = _pool_destroy,
+};
+/* *INDENT-ON */
+
+#ifdef POOL_INTERNAL
+struct format_type *init_pool_format(struct cmd_context *cmd)
+#else				/* Shared */
+struct format_type *init_format(struct cmd_context *cmd);
+struct format_type *init_format(struct cmd_context *cmd)
+#endif
+{
+	struct format_type *fmt = dm_malloc(sizeof(*fmt));
+
+	if (!fmt) {
+		log_error("Unable to allocate format type structure for pool "
+			  "format");
+		return NULL;
+	}
+
+	fmt->cmd = cmd;
+	fmt->ops = &_format_pool_ops;
+	fmt->name = FMT_POOL_NAME;
+	fmt->alias = NULL;
+	fmt->orphan_vg_name = FMT_POOL_ORPHAN_VG_NAME;
+	fmt->features = 0;
+	fmt->private = NULL;
+
+	if (!(fmt->labeller = pool_labeller_create(fmt))) {
+		log_error("Couldn't create pool label handler.");
+		return NULL;
+	}
+
+	if (!(label_register_handler(FMT_POOL_NAME, fmt->labeller))) {
+		log_error("Couldn't register pool label handler.");
+		return NULL;
+	}
+
+	log_very_verbose("Initialised format: %s", fmt->name);
+
+	return fmt;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/format_pool/format_pool.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format_pool/format_pool.h
diff -N src/external/gpl2/lvm2tools/dist/lib/format_pool/format_pool.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format_pool/format_pool.h	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,30 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_FORMAT_POOL_H
+#define _LVM_FORMAT_POOL_H
+
+#include "metadata.h"
+
+#define FMT_POOL_NAME "pool"
+#define FMT_POOL_ORPHAN_VG_NAME ORPHAN_VG_NAME(FMT_POOL_NAME)
+
+#ifdef POOL_INTERNAL
+struct format_type *init_pool_format(struct cmd_context *cmd);
+#endif
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/format_pool/import_export.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format_pool/import_export.c
diff -N src/external/gpl2/lvm2tools/dist/lib/format_pool/import_export.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format_pool/import_export.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,307 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "label.h"
+#include "metadata.h"
+#include "lvmcache.h"
+#include "disk_rep.h"
+#include "sptype_names.h"
+#include "lv_alloc.h"
+#include "pv_alloc.h"
+#include "str_list.h"
+#include "display.h"
+#include "segtype.h"
+#include "toolcontext.h"
+
+/* This file contains only imports at the moment... */
+
+int import_pool_vg(struct volume_group *vg, struct dm_pool *mem, struct dm_list *pls)
+{
+	struct pool_list *pl;
+
+	dm_list_iterate_items(pl, pls) {
+		vg->extent_count +=
+		    ((pl->pd.pl_blocks) / POOL_PE_SIZE);
+
+		vg->free_count = vg->extent_count;
+		vg->pv_count++;
+
+		if (vg->name)
+			continue;
+
+		vg->name = dm_pool_strdup(mem, pl->pd.pl_pool_name);
+		get_pool_vg_uuid(&vg->id, &pl->pd);
+		vg->extent_size = POOL_PE_SIZE;
+		vg->status |= LVM_READ | LVM_WRITE | CLUSTERED | SHARED;
+		vg->max_lv = 1;
+		vg->max_pv = POOL_MAX_DEVICES;
+		vg->alloc = ALLOC_NORMAL;
+		vg->lv_count = 0;
+	}
+
+	return 1;
+}
+
+int import_pool_lvs(struct volume_group *vg, struct dm_pool *mem, struct dm_list *pls)
+{
+	struct pool_list *pl;
+	struct lv_list *lvl = dm_pool_zalloc(mem, sizeof(*lvl));
+	struct logical_volume *lv;
+
+	if (!lvl) {
+		log_error("Unable to allocate lv list structure");
+		return 0;
+	}
+
+	if (!(lvl->lv = dm_pool_zalloc(mem, sizeof(*lvl->lv)))) {
+		log_error("Unable to allocate logical volume structure");
+		return 0;
+	}
+
+	lv = lvl->lv;
+	lv->status = 0;
+	lv->vg = vg;
+	lv->alloc = ALLOC_NORMAL;
+	lv->size = 0;
+	lv->name = NULL;
+	lv->le_count = 0;
+	lv->read_ahead = vg->cmd->default_settings.read_ahead;
+	lv->snapshot = NULL;
+	dm_list_init(&lv->snapshot_segs);
+	dm_list_init(&lv->segments);
+	dm_list_init(&lv->tags);
+	dm_list_init(&lv->segs_using_this_lv);
+
+	dm_list_iterate_items(pl, pls) {
+		lv->size += pl->pd.pl_blocks;
+
+		if (lv->name)
+			continue;
+
+		if (!(lv->name = dm_pool_strdup(mem, pl->pd.pl_pool_name)))
+			return_0;
+
+		get_pool_lv_uuid(lv->lvid.id, &pl->pd);
+		log_debug("Calculated lv uuid for lv %s: %s", lv->name,
+			  lv->lvid.s);
+
+		lv->status |= VISIBLE_LV | LVM_READ | LVM_WRITE;
+		lv->major = POOL_MAJOR;
+
+		/* for pool a minor of 0 is dynamic */
+		if (pl->pd.pl_minor) {
+			lv->status |= FIXED_MINOR;
+			lv->minor = pl->pd.pl_minor + MINOR_OFFSET;
+		} else {
+			lv->minor = -1;
+		}
+		lv->snapshot = NULL;
+		dm_list_init(&lv->snapshot_segs);
+		dm_list_init(&lv->segments);
+		dm_list_init(&lv->tags);
+	}
+
+	lv->le_count = lv->size / POOL_PE_SIZE;
+	lvl->lv = lv;
+	dm_list_add(&vg->lvs, &lvl->list);
+	vg->lv_count++;
+
+	return 1;
+}
+
+int import_pool_pvs(const struct format_type *fmt, struct volume_group *vg,
+		    struct dm_list *pvs, struct dm_pool *mem, struct dm_list *pls)
+{
+	struct pv_list *pvl;
+	struct pool_list *pl;
+
+	dm_list_iterate_items(pl, pls) {
+		if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl)))) {
+			log_error("Unable to allocate pv list structure");
+			return 0;
+		}
+		if (!(pvl->pv = dm_pool_zalloc(mem, sizeof(*pvl->pv)))) {
+			log_error("Unable to allocate pv structure");
+			return 0;
+		}
+		if (!import_pool_pv(fmt, mem, vg, pvl->pv, pl)) {
+			return 0;
+		}
+		pl->pv = pvl->pv;
+		pvl->mdas = NULL;
+		pvl->pe_ranges = NULL;
+		dm_list_add(pvs, &pvl->list);
+	}
+
+	return 1;
+}
+
+int import_pool_pv(const struct format_type *fmt, struct dm_pool *mem,
+		   struct volume_group *vg, struct physical_volume *pv,
+		   struct pool_list *pl)
+{
+	struct pool_disk *pd = &pl->pd;
+
+	memset(pv, 0, sizeof(*pv));
+
+	get_pool_pv_uuid(&pv->id, pd);
+	pv->fmt = fmt;
+
+	pv->dev = pl->dev;
+	if (!(pv->vg_name = dm_pool_strdup(mem, pd->pl_pool_name))) {
+		log_error("Unable to duplicate vg_name string");
+		return 0;
+	}
+	if (vg != NULL)
+		memcpy(&pv->vgid, &vg->id, sizeof(vg->id));
+	pv->status = 0;
+	pv->size = pd->pl_blocks;
+	pv->pe_size = POOL_PE_SIZE;
+	pv->pe_start = POOL_PE_START;
+	pv->pe_count = pv->size / POOL_PE_SIZE;
+	pv->pe_alloc_count = 0;
+	pv->pe_align = 0;
+
+	dm_list_init(&pv->tags);
+	dm_list_init(&pv->segments);
+
+	if (!alloc_pv_segment_whole_pv(mem, pv))
+		return_0;
+
+	return 1;
+}
+
+static const char *_cvt_sptype(uint32_t sptype)
+{
+	int i;
+	for (i = 0; sptype_names[i].name[0]; i++) {
+		if (sptype == sptype_names[i].label) {
+			break;
+		}
+	}
+	log_debug("Found sptype %X and converted it to %s",
+		  sptype, sptype_names[i].name);
+	return sptype_names[i].name;
+}
+
+static int _add_stripe_seg(struct dm_pool *mem,
+			   struct user_subpool *usp, struct logical_volume *lv,
+			   uint32_t *le_cur)
+{
+	struct lv_segment *seg;
+	struct segment_type *segtype;
+	unsigned j;
+	uint32_t area_len;
+
+	if (usp->striping & (usp->striping - 1)) {
+		log_error("Stripe size must be a power of 2");
+		return 0;
+	}
+
+	area_len = (usp->devs[0].blocks) / POOL_PE_SIZE;
+
+	if (!(segtype = get_segtype_from_string(lv->vg->cmd,
+						     "striped")))
+		return_0;
+
+	if (!(seg = alloc_lv_segment(mem, segtype, lv, *le_cur,
+				     area_len * usp->num_devs, 0,
+				     usp->striping, NULL, usp->num_devs,
+				     area_len, 0, 0, 0))) {
+		log_error("Unable to allocate striped lv_segment structure");
+		return 0;
+	}
+
+	for (j = 0; j < usp->num_devs; j++)
+		if (!set_lv_segment_area_pv(seg, j, usp->devs[j].pv, 0))
+			return_0;
+
+	/* add the subpool type to the segment tag list */
+	str_list_add(mem, &seg->tags, _cvt_sptype(usp->type));
+
+	dm_list_add(&lv->segments, &seg->list);
+
+	*le_cur += seg->len;
+
+	return 1;
+}
+
+static int _add_linear_seg(struct dm_pool *mem,
+			   struct user_subpool *usp, struct logical_volume *lv,
+			   uint32_t *le_cur)
+{
+	struct lv_segment *seg;
+	struct segment_type *segtype;
+	unsigned j;
+	uint32_t area_len;
+
+	if (!(segtype = get_segtype_from_string(lv->vg->cmd, "striped")))
+		return_0;
+
+	for (j = 0; j < usp->num_devs; j++) {
+		area_len = (usp->devs[j].blocks) / POOL_PE_SIZE;
+
+		if (!(seg = alloc_lv_segment(mem, segtype, lv, *le_cur,
+					     area_len, 0, usp->striping,
+					     NULL, 1, area_len,
+					     POOL_PE_SIZE, 0, 0))) {
+			log_error("Unable to allocate linear lv_segment "
+				  "structure");
+			return 0;
+		}
+
+		/* add the subpool type to the segment tag list */
+		str_list_add(mem, &seg->tags, _cvt_sptype(usp->type));
+
+		if (!set_lv_segment_area_pv(seg, 0, usp->devs[j].pv, 0))
+			return_0;
+		dm_list_add(&lv->segments, &seg->list);
+
+		*le_cur += seg->len;
+	}
+
+	return 1;
+}
+
+int import_pool_segments(struct dm_list *lvs, struct dm_pool *mem,
+			 struct user_subpool *usp, int subpools)
+{
+	struct lv_list *lvl;
+	struct logical_volume *lv;
+	uint32_t le_cur = 0;
+	int i;
+
+	dm_list_iterate_items(lvl, lvs) {
+		lv = lvl->lv;
+
+		if (lv->status & SNAPSHOT)
+			continue;
+
+		for (i = 0; i < subpools; i++) {
+			if (usp[i].striping) {
+				if (!_add_stripe_seg(mem, &usp[i], lv, &le_cur))
+					return_0;
+			} else {
+				if (!_add_linear_seg(mem, &usp[i], lv, &le_cur))
+					return_0;
+			}
+		}
+	}
+
+	return 1;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/format_pool/pool_label.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format_pool/pool_label.c
diff -N src/external/gpl2/lvm2tools/dist/lib/format_pool/pool_label.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format_pool/pool_label.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,109 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "label.h"
+#include "metadata.h"
+#include "xlate.h"
+#include "disk_rep.h"
+#include "pool_label.h"
+
+#include <sys/stat.h>
+#include <fcntl.h>
+
+static void _pool_not_supported(const char *op)
+{
+	log_error("The '%s' operation is not supported for the pool labeller.",
+		  op);
+}
+
+static int _pool_can_handle(struct labeller *l __attribute((unused)), void *buf, uint64_t sector)
+{
+
+	struct pool_disk pd;
+
+	/*
+	 * POOL label must always be in first sector
+	 */
+	if (sector)
+		return 0;
+
+	pool_label_in(&pd, buf);
+
+	/* can ignore 8 rightmost bits for ondisk format check */
+	if ((pd.pl_magic == POOL_MAGIC) &&
+	    (pd.pl_version >> 8 == POOL_VERSION >> 8))
+		return 1;
+
+	return 0;
+}
+
+static int _pool_write(struct label *label __attribute((unused)), void *buf __attribute((unused)))
+{
+	_pool_not_supported("write");
+	return 0;
+}
+
+static int _pool_read(struct labeller *l, struct device *dev, void *buf,
+		 struct label **label)
+{
+	struct pool_list pl;
+
+	return read_pool_label(&pl, l, dev, buf, label);
+}
+
+static int _pool_initialise_label(struct labeller *l __attribute((unused)), struct label *label)
+{
+	strcpy(label->type, "POOL");
+
+	return 1;
+}
+
+static void _pool_destroy_label(struct labeller *l __attribute((unused)), struct label *label __attribute((unused)))
+{
+	return;
+}
+
+static void _label_pool_destroy(struct labeller *l)
+{
+	dm_free(l);
+}
+
+struct label_ops _pool_ops = {
+      .can_handle = _pool_can_handle,
+      .write = _pool_write,
+      .read = _pool_read,
+      .verify = _pool_can_handle,
+      .initialise_label = _pool_initialise_label,
+      .destroy_label = _pool_destroy_label,
+      .destroy = _label_pool_destroy,
+};
+
+struct labeller *pool_labeller_create(struct format_type *fmt)
+{
+	struct labeller *l;
+
+	if (!(l = dm_malloc(sizeof(*l)))) {
+		log_error("Couldn't allocate labeller object.");
+		return NULL;
+	}
+
+	l->ops = &_pool_ops;
+	l->private = (const void *) fmt;
+
+	return l;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/format_pool/pool_label.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format_pool/pool_label.h
diff -N src/external/gpl2/lvm2tools/dist/lib/format_pool/pool_label.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format_pool/pool_label.h	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,25 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_POOL_LABEL_H
+#define _LVM_POOL_LABEL_H
+
+#include "metadata.h"
+
+struct labeller *pool_labeller_create(struct format_type *fmt);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/format_pool/sptype_names.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format_pool/sptype_names.h
diff -N src/external/gpl2/lvm2tools/dist/lib/format_pool/sptype_names.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format_pool/sptype_names.h	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,44 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef SPTYPE_NAMES_H
+#define SPTYPE_NAMES_H
+
+/* This must be kept up to date with sistina/pool/module/pool_sptypes.h */
+
+/*  Generic Labels  */
+#define SPTYPE_DATA                (0x00000000)
+
+/*  GFS specific labels  */
+#define SPTYPE_GFS_DATA            (0x68011670)
+#define SPTYPE_GFS_JOURNAL         (0x69011670)
+
+struct sptype_name {
+	const char *name;
+	uint32_t label;
+};
+
+static const struct sptype_name sptype_names[] = {
+	{"data",	SPTYPE_DATA},
+
+	{"gfs_data",	SPTYPE_GFS_DATA},
+	{"gfs_journal",	SPTYPE_GFS_JOURNAL},
+
+	{"", 0x0}		/*  This must be the last flag.  */
+};
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/format_text/archive.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format_text/archive.c
diff -N src/external/gpl2/lvm2tools/dist/lib/format_text/archive.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format_text/archive.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,380 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "format-text.h"
+
+#include "config.h"
+#include "import-export.h"
+#include "lvm-string.h"
+#include "lvm-file.h"
+#include "toolcontext.h"
+
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#include <time.h>
+
+#define SECS_PER_DAY 86400	/* 24*60*60 */
+
+/*
+ * The format instance is given a directory path upon creation.
+ * Each file in this directory whose name is of the form
+ * '(.*)_[0-9]*.vg' is a config file (see lib/config.[hc]), which
+ * contains a description of a single volume group.
+ *
+ * The prefix ($1 from the above regex) of the config file gives
+ * the volume group name.
+ *
+ * Backup files that have expired will be removed.
+ */
+
+/*
+ * A list of these is built up for our volume group.  Ordered
+ * with the least recent at the head.
+ */
+struct archive_file {
+	struct dm_list list;
+
+	char *path;
+	uint32_t index;
+};
+
+/*
+ * Extract vg name and version number from a filename.
+ */
+static int _split_vg(const char *filename, char *vgname, size_t vg_size,
+		     uint32_t *ix)
+{
+	size_t len, vg_len;
+	const char *dot, *underscore;
+
+	len = strlen(filename);
+	if (len < 7)
+		return 0;
+
+	dot = (filename + len - 3);
+	if (strcmp(".vg", dot))
+		return 0;
+
+	if (!(underscore = strrchr(filename, '_')))
+		return 0;
+
+	if (sscanf(underscore + 1, "%u", ix) != 1)
+		return 0;
+
+	vg_len = underscore - filename;
+	if (vg_len + 1 > vg_size)
+		return 0;
+
+	strncpy(vgname, filename, vg_len);
+	vgname[vg_len] = '\0';
+
+	return 1;
+}
+
+static void _insert_archive_file(struct dm_list *head, struct archive_file *b)
+{
+	struct archive_file *bf = NULL;
+
+	if (dm_list_empty(head)) {
+		dm_list_add(head, &b->list);
+		return;
+	}
+
+	/* index reduces through list */
+	dm_list_iterate_items(bf, head) {
+		if (b->index > bf->index) {
+			dm_list_add(&bf->list, &b->list);
+			return;
+		}
+	}
+
+	dm_list_add_h(&bf->list, &b->list);
+}
+
+static char *_join_file_to_dir(struct dm_pool *mem, const char *dir, const char *name)
+{
+	if (!dm_pool_begin_object(mem, 32) ||
+	    !dm_pool_grow_object(mem, dir, strlen(dir)) ||
+	    !dm_pool_grow_object(mem, "/", 1) ||
+	    !dm_pool_grow_object(mem, name, strlen(name)) ||
+	    !dm_pool_grow_object(mem, "\0", 1))
+		return_NULL;
+
+	return dm_pool_end_object(mem);
+}
+
+/*
+ * Returns a list of archive_files.
+ */
+static struct dm_list *_scan_archive(struct dm_pool *mem,
+				  const char *vgname, const char *dir)
+{
+	int i, count;
+	uint32_t ix;
+	char vgname_found[64], *path;
+	struct dirent **dirent;
+	struct archive_file *af;
+	struct dm_list *results;
+
+	if (!(results = dm_pool_alloc(mem, sizeof(*results))))
+		return_NULL;
+
+	dm_list_init(results);
+
+	/* Sort fails beyond 5-digit indexes */
+	if ((count = scandir(dir, &dirent, NULL, alphasort)) < 0) {
+		log_err("Couldn't scan the archive directory (%s).", dir);
+		return 0;
+	}
+
+	for (i = 0; i < count; i++) {
+		if (!strcmp(dirent[i]->d_name, ".") ||
+		    !strcmp(dirent[i]->d_name, ".."))
+			continue;
+
+		/* check the name is the correct format */
+		if (!_split_vg(dirent[i]->d_name, vgname_found,
+			       sizeof(vgname_found), &ix))
+			continue;
+
+		/* is it the vg we're interested in ? */
+		if (strcmp(vgname, vgname_found))
+			continue;
+
+		if (!(path = _join_file_to_dir(mem, dir, dirent[i]->d_name)))
+			goto_out;
+
+		/*
+		 * Create a new archive_file.
+		 */
+		if (!(af = dm_pool_alloc(mem, sizeof(*af)))) {
+			log_err("Couldn't create new archive file.");
+			results = NULL;
+			goto out;
+		}
+
+		af->index = ix;
+		af->path = path;
+
+		/*
+		 * Insert it to the correct part of the list.
+		 */
+		_insert_archive_file(results, af);
+	}
+
+      out:
+	for (i = 0; i < count; i++)
+		free(dirent[i]);
+	free(dirent);
+
+	return results;
+}
+
+static void _remove_expired(struct dm_list *archives, uint32_t archives_size,
+			    uint32_t retain_days, uint32_t min_archive)
+{
+	struct archive_file *bf;
+	struct stat sb;
+	time_t retain_time;
+
+	/* Make sure there are enough archives to even bother looking for
+	 * expired ones... */
+	if (archives_size <= min_archive)
+		return;
+
+	/* Convert retain_days into the time after which we must retain */
+	retain_time = time(NULL) - (time_t) retain_days *SECS_PER_DAY;
+
+	/* Assume list is ordered newest first (by index) */
+	dm_list_iterate_back_items(bf, archives) {
+		/* Get the mtime of the file and unlink if too old */
+		if (stat(bf->path, &sb)) {
+			log_sys_error("stat", bf->path);
+			continue;
+		}
+
+		if (sb.st_mtime > retain_time)
+			return;
+
+		log_very_verbose("Expiring archive %s", bf->path);
+		if (unlink(bf->path))
+			log_sys_error("unlink", bf->path);
+
+		/* Don't delete any more if we've reached the minimum */
+		if (--archives_size <= min_archive)
+			return;
+	}
+}
+
+int archive_vg(struct volume_group *vg,
+	       const char *dir, const char *desc,
+	       uint32_t retain_days, uint32_t min_archive)
+{
+	int i, fd, renamed = 0;
+	uint32_t ix = 0;
+	struct archive_file *last;
+	FILE *fp = NULL;
+	char temp_file[PATH_MAX], archive_name[PATH_MAX];
+	struct dm_list *archives;
+
+	/*
+	 * Write the vg out to a temporary file.
+	 */
+	if (!create_temp_name(dir, temp_file, sizeof(temp_file), &fd)) {
+		log_err("Couldn't create temporary archive name.");
+		return 0;
+	}
+
+	if (!(fp = fdopen(fd, "w"))) {
+		log_err("Couldn't create FILE object for archive.");
+		if (close(fd))
+			log_sys_error("close", temp_file);
+		return 0;
+	}
+
+	if (!text_vg_export_file(vg, desc, fp)) {
+		if (fclose(fp))
+			log_sys_error("fclose", temp_file);
+		return_0;
+	}
+
+	if (lvm_fclose(fp, temp_file))
+		return_0; /* Leave file behind as evidence of failure */
+
+	/*
+	 * Now we want to rename this file to <vg>_index.vg.
+	 */
+	if (!(archives = _scan_archive(vg->cmd->mem, vg->name, dir)))
+		return_0;
+
+	if (dm_list_empty(archives))
+		ix = 0;
+	else {
+		last = dm_list_item(dm_list_first(archives), struct archive_file);
+		ix = last->index + 1;
+	}
+
+	for (i = 0; i < 10; i++) {
+		if (dm_snprintf(archive_name, sizeof(archive_name),
+				 "%s/%s_%05u.vg", dir, vg->name, ix) < 0) {
+			log_error("Archive file name too long.");
+			return 0;
+		}
+
+		if ((renamed = lvm_rename(temp_file, archive_name)))
+			break;
+
+		ix++;
+	}
+
+	if (!renamed)
+		log_error("Archive rename failed for %s", temp_file);
+
+	_remove_expired(archives, dm_list_size(archives) + renamed, retain_days,
+			min_archive);
+
+	return 1;
+}
+
+static void _display_archive(struct cmd_context *cmd, struct archive_file *af)
+{
+	struct volume_group *vg = NULL;
+	struct format_instance *tf;
+	time_t when;
+	char *desc;
+	void *context;
+
+	log_print(" ");
+	log_print("File:\t\t%s", af->path);
+
+	if (!(context = create_text_context(cmd, af->path, NULL)) ||
+	    !(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
+							 NULL, context))) {
+		log_error("Couldn't create text instance object.");
+		return;
+	}
+
+	/*
+	 * Read the archive file to ensure that it is valid, and
+	 * retrieve the archive time and description.
+	 */
+	/* FIXME Use variation on _vg_read */
+	if (!(vg = text_vg_import_file(tf, af->path, &when, &desc))) {
+		log_print("Unable to read archive file.");
+		tf->fmt->ops->destroy_instance(tf);
+		return;
+	}
+
+	log_print("VG name:    \t%s", vg->name);
+	log_print("Description:\t%s", desc ? : "<No description>");
+	log_print("Backup Time:\t%s", ctime(&when));
+
+	dm_pool_free(cmd->mem, vg);
+	tf->fmt->ops->destroy_instance(tf);
+}
+
+int archive_list(struct cmd_context *cmd, const char *dir, const char *vgname)
+{
+	struct dm_list *archives;
+	struct archive_file *af;
+
+	if (!(archives = _scan_archive(cmd->mem, vgname, dir)))
+		return_0;
+
+	if (dm_list_empty(archives))
+		log_print("No archives found in %s.", dir);
+
+	dm_list_iterate_back_items(af, archives)
+		_display_archive(cmd, af);
+
+	dm_pool_free(cmd->mem, archives);
+
+	return 1;
+}
+
+int archive_list_file(struct cmd_context *cmd, const char *file)
+{
+	struct archive_file af;
+
+	af.path = (char *)file;
+
+	if (!path_exists(af.path)) {
+		log_err("Archive file %s not found.", af.path);
+		return 0;
+	}
+
+	_display_archive(cmd, &af);
+
+	return 1;
+}
+
+int backup_list(struct cmd_context *cmd, const char *dir, const char *vgname)
+{
+	struct archive_file af;
+
+	if (!(af.path = _join_file_to_dir(cmd->mem, dir, vgname)))
+		return_0;
+
+	if (path_exists(af.path))
+		_display_archive(cmd, &af);
+
+	return 1;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/format_text/archiver.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format_text/archiver.c
diff -N src/external/gpl2/lvm2tools/dist/lib/format_text/archiver.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format_text/archiver.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,415 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "archiver.h"
+#include "format-text.h"
+#include "lvm-file.h"
+#include "lvm-string.h"
+#include "lvmcache.h"
+#include "toolcontext.h"
+
+#include <unistd.h>
+
+struct archive_params {
+	int enabled;
+	char *dir;
+	unsigned int keep_days;
+	unsigned int keep_number;
+};
+
+struct backup_params {
+	int enabled;
+	char *dir;
+};
+
+int archive_init(struct cmd_context *cmd, const char *dir,
+		 unsigned int keep_days, unsigned int keep_min)
+{
+	if (!(cmd->archive_params = dm_pool_zalloc(cmd->libmem,
+						sizeof(*cmd->archive_params)))) {
+		log_error("archive_params alloc failed");
+		return 0;
+	}
+
+	cmd->archive_params->dir = NULL;
+
+	if (!*dir)
+		return 1;
+
+	if (!(cmd->archive_params->dir = dm_strdup(dir))) {
+		log_error("Couldn't copy archive directory name.");
+		return 0;
+	}
+
+	cmd->archive_params->keep_days = keep_days;
+	cmd->archive_params->keep_number = keep_min;
+	cmd->archive_params->enabled = 1;
+
+	return 1;
+}
+
+void archive_exit(struct cmd_context *cmd)
+{
+	if (cmd->archive_params->dir)
+		dm_free(cmd->archive_params->dir);
+	memset(cmd->archive_params, 0, sizeof(*cmd->archive_params));
+}
+
+void archive_enable(struct cmd_context *cmd, int flag)
+{
+	cmd->archive_params->enabled = flag;
+}
+
+static char *_build_desc(struct dm_pool *mem, const char *line, int before)
+{
+	size_t len = strlen(line) + 32;
+	char *buffer;
+
+	if (!(buffer = dm_pool_zalloc(mem, strlen(line) + 32)))
+		return_NULL;
+
+	if (snprintf(buffer, len,
+		     "Created %s executing '%s'",
+		     before ? "*before*" : "*after*", line) < 0)
+		return_NULL;
+
+	return buffer;
+}
+
+static int __archive(struct volume_group *vg)
+{
+	char *desc;
+
+	if (!(desc = _build_desc(vg->cmd->mem, vg->cmd->cmd_line, 1)))
+		return_0;
+
+	return archive_vg(vg, vg->cmd->archive_params->dir, desc,
+			  vg->cmd->archive_params->keep_days,
+			  vg->cmd->archive_params->keep_number);
+}
+
+int archive(struct volume_group *vg)
+{
+	if (!vg->cmd->archive_params->enabled || !vg->cmd->archive_params->dir)
+		return 1;
+
+	if (test_mode()) {
+		log_verbose("Test mode: Skipping archiving of volume group.");
+		return 1;
+	}
+
+	if (!dm_create_dir(vg->cmd->archive_params->dir))
+		return 0;
+
+	/* Trap a read-only file system */
+	if ((access(vg->cmd->archive_params->dir, R_OK | W_OK | X_OK) == -1) &&
+	     (errno == EROFS))
+		return 0;
+
+	log_verbose("Archiving volume group \"%s\" metadata (seqno %u).", vg->name,
+		    vg->seqno);
+	if (!__archive(vg)) {
+		log_error("Volume group \"%s\" metadata archive failed.",
+			  vg->name);
+		return 0;
+	}
+
+	return 1;
+}
+
+int archive_display(struct cmd_context *cmd, const char *vg_name)
+{
+	int r1, r2;
+
+	r1 = archive_list(cmd, cmd->archive_params->dir, vg_name);
+	r2 = backup_list(cmd, cmd->backup_params->dir, vg_name);
+
+	return r1 && r2;
+}
+
+int archive_display_file(struct cmd_context *cmd, const char *file)
+{
+	int r;
+
+	r = archive_list_file(cmd, file);
+
+	return r;
+}
+
+int backup_init(struct cmd_context *cmd, const char *dir)
+{
+	if (!(cmd->backup_params = dm_pool_zalloc(cmd->libmem,
+					       sizeof(*cmd->archive_params)))) {
+		log_error("archive_params alloc failed");
+		return 0;
+	}
+
+	cmd->backup_params->dir = NULL;
+	if (!*dir)
+		return 1;
+
+	if (!(cmd->backup_params->dir = dm_strdup(dir))) {
+		log_error("Couldn't copy backup directory name.");
+		return 0;
+	}
+
+	return 1;
+}
+
+void backup_exit(struct cmd_context *cmd)
+{
+	if (cmd->backup_params->dir)
+		dm_free(cmd->backup_params->dir);
+	memset(cmd->backup_params, 0, sizeof(*cmd->backup_params));
+}
+
+void backup_enable(struct cmd_context *cmd, int flag)
+{
+	cmd->backup_params->enabled = flag;
+}
+
+static int __backup(struct volume_group *vg)
+{
+	char name[PATH_MAX];
+	char *desc;
+
+	if (!(desc = _build_desc(vg->cmd->mem, vg->cmd->cmd_line, 0)))
+		return_0;
+
+	if (dm_snprintf(name, sizeof(name), "%s/%s",
+			 vg->cmd->backup_params->dir, vg->name) < 0) {
+		log_error("Failed to generate volume group metadata backup "
+			  "filename.");
+		return 0;
+	}
+
+	return backup_to_file(name, desc, vg);
+}
+
+int backup(struct volume_group *vg)
+{
+	if (!vg->cmd->backup_params->enabled || !vg->cmd->backup_params->dir) {
+		log_warn("WARNING: This metadata update is NOT backed up");
+		return 1;
+	}
+
+	if (test_mode()) {
+		log_verbose("Test mode: Skipping volume group backup.");
+		return 1;
+	}
+
+	if (!dm_create_dir(vg->cmd->backup_params->dir))
+		return 0;
+
+	/* Trap a read-only file system */
+	if ((access(vg->cmd->backup_params->dir, R_OK | W_OK | X_OK) == -1) &&
+	    (errno == EROFS))
+		return 0;
+
+	if (!__backup(vg)) {
+		log_error("Backup of volume group %s metadata failed.",
+			  vg->name);
+		return 0;
+	}
+
+	return 1;
+}
+
+int backup_remove(struct cmd_context *cmd, const char *vg_name)
+{
+	char path[PATH_MAX];
+
+	if (dm_snprintf(path, sizeof(path), "%s/%s",
+			 cmd->backup_params->dir, vg_name) < 0) {
+		log_err("Failed to generate backup filename (for removal).");
+		return 0;
+	}
+
+	/*
+	 * Let this fail silently.
+	 */
+	unlink(path);
+	return 1;
+}
+
+struct volume_group *backup_read_vg(struct cmd_context *cmd,
+				    const char *vg_name, const char *file)
+{
+	struct volume_group *vg = NULL;
+	struct format_instance *tf;
+	struct metadata_area *mda;
+	void *context;
+
+	if (!(context = create_text_context(cmd, file,
+					    cmd->cmd_line)) ||
+	    !(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
+							 NULL, context))) {
+		log_error("Couldn't create text format object.");
+		return NULL;
+	}
+
+	dm_list_iterate_items(mda, &tf->metadata_areas) {
+		if (!(vg = mda->ops->vg_read(tf, vg_name, mda)))
+			stack;
+		break;
+	}
+
+	tf->fmt->ops->destroy_instance(tf);
+	return vg;
+}
+
+/* ORPHAN and VG locks held before calling this */
+int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg)
+{
+	struct pv_list *pvl;
+	struct physical_volume *pv;
+	struct lvmcache_info *info;
+
+	/*
+	 * FIXME: Check that the PVs referenced in the backup are
+	 * not members of other existing VGs.
+	 */
+
+	/* Attempt to write out using currently active format */
+	if (!(vg->fid = cmd->fmt->ops->create_instance(cmd->fmt, vg->name,
+						       NULL, NULL))) {
+		log_error("Failed to allocate format instance");
+		return 0;
+	}
+
+	/* Add any metadata areas on the PVs */
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		pv = pvl->pv;
+		if (!(info = info_from_pvid(pv->dev->pvid, 0))) {
+			log_error("PV %s missing from cache",
+				  pv_dev_name(pv));
+			return 0;
+		}
+		if (cmd->fmt != info->fmt) {
+			log_error("PV %s is a different format (seqno %s)",
+				  pv_dev_name(pv), info->fmt->name);
+			return 0;
+		}
+		if (!vg->fid->fmt->ops->
+		    pv_setup(vg->fid->fmt, UINT64_C(0), 0, 0, 0,
+			     UINT64_C(0), &vg->fid->metadata_areas, pv, vg)) {
+			log_error("Format-specific setup for %s failed",
+				  pv_dev_name(pv));
+			return 0;
+		}
+	}
+
+	if (!vg_write(vg) || !vg_commit(vg))
+		return_0;
+
+	return 1;
+}
+
+/* ORPHAN and VG locks held before calling this */
+int backup_restore_from_file(struct cmd_context *cmd, const char *vg_name,
+			     const char *file)
+{
+	struct volume_group *vg;
+
+	/*
+	 * Read in the volume group from the text file.
+	 */
+	if (!(vg = backup_read_vg(cmd, vg_name, file)))
+		return_0;
+
+	return backup_restore_vg(cmd, vg);
+}
+
+int backup_restore(struct cmd_context *cmd, const char *vg_name)
+{
+	char path[PATH_MAX];
+
+	if (dm_snprintf(path, sizeof(path), "%s/%s",
+			 cmd->backup_params->dir, vg_name) < 0) {
+		log_err("Failed to generate backup filename (for restore).");
+		return 0;
+	}
+
+	return backup_restore_from_file(cmd, vg_name, path);
+}
+
+int backup_to_file(const char *file, const char *desc, struct volume_group *vg)
+{
+	int r = 0;
+	struct format_instance *tf;
+	struct metadata_area *mda;
+	void *context;
+	struct cmd_context *cmd;
+
+	cmd = vg->cmd;
+
+	log_verbose("Creating volume group backup \"%s\" (seqno %u).", file, vg->seqno);
+
+	if (!(context = create_text_context(cmd, file, desc)) ||
+	    !(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
+							 NULL, context))) {
+		log_error("Couldn't create backup object.");
+		return 0;
+	}
+
+	/* Write and commit the metadata area */
+	dm_list_iterate_items(mda, &tf->metadata_areas) {
+		if (!(r = mda->ops->vg_write(tf, vg, mda))) {
+			stack;
+			continue;
+		}
+		if (mda->ops->vg_commit &&
+		    !(r = mda->ops->vg_commit(tf, vg, mda))) {
+			stack;
+		}
+	}
+
+	tf->fmt->ops->destroy_instance(tf);
+	return r;
+}
+
+/*
+ * Update backup (and archive) if they're out-of-date or don't exist.
+ */
+void check_current_backup(struct volume_group *vg)
+{
+	char path[PATH_MAX];
+	struct volume_group *vg_backup;
+
+	if (vg->status & EXPORTED_VG)
+		return;
+
+	if (dm_snprintf(path, sizeof(path), "%s/%s",
+			 vg->cmd->backup_params->dir, vg->name) < 0) {
+		log_debug("Failed to generate backup filename.");
+		return;
+	}
+
+	log_suppress(1);
+	/* Up-to-date backup exists? */
+	if ((vg_backup = backup_read_vg(vg->cmd, vg->name, path)) &&
+	    (vg->seqno == vg_backup->seqno) &&
+	    (id_equal(&vg->id, &vg_backup->id)))
+		return;
+	log_suppress(0);
+
+	if (vg_backup)
+		archive(vg_backup);
+	archive(vg);
+	backup(vg);
+}
Index: src/external/gpl2/lvm2tools/dist/lib/format_text/archiver.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format_text/archiver.h
diff -N src/external/gpl2/lvm2tools/dist/lib/format_text/archiver.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format_text/archiver.h	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,63 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_TOOL_ARCHIVE_H
+#define _LVM_TOOL_ARCHIVE_H
+
+#include "metadata-exported.h"
+
+/*
+ * There are two operations that come under the general area of
+ * backups.  'Archiving' occurs just before a volume group
+ * configuration is changed.  The user may configure when
+ * archived files are expired.  Typically archives will be stored
+ * in /etc/lvm/archive.
+ *
+ * A 'backup' is a redundant copy of the *current* volume group
+ * configuration.  As such it should be taken just after the
+ * volume group is changed.  Only 1 backup file will exist.
+ * Typically backups will be stored in /etc/lvm/backups.
+ */
+
+int archive_init(struct cmd_context *cmd, const char *dir,
+		 unsigned int keep_days, unsigned int keep_min);
+void archive_exit(struct cmd_context *cmd);
+
+void archive_enable(struct cmd_context *cmd, int flag);
+int archive(struct volume_group *vg);
+int archive_display(struct cmd_context *cmd, const char *vg_name);
+int archive_display_file(struct cmd_context *cmd, const char *file);
+
+int backup_init(struct cmd_context *cmd, const char *dir);
+void backup_exit(struct cmd_context *cmd);
+
+void backup_enable(struct cmd_context *cmd, int flag);
+int backup(struct volume_group *vg);
+int backup_remove(struct cmd_context *cmd, const char *vg_name);
+
+struct volume_group *backup_read_vg(struct cmd_context *cmd,
+				    const char *vg_name, const char *file);
+int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg);
+int backup_restore_from_file(struct cmd_context *cmd, const char *vg_name,
+			     const char *file);
+int backup_restore(struct cmd_context *cmd, const char *vg_name);
+
+int backup_to_file(const char *file, const char *desc, struct volume_group *vg);
+
+void check_current_backup(struct volume_group *vg);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/format_text/export.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format_text/export.c
diff -N src/external/gpl2/lvm2tools/dist/lib/format_text/export.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format_text/export.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,764 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "import-export.h"
+#include "metadata.h"
+#include "display.h"
+#include "lvm-string.h"
+#include "segtype.h"
+#include "text_export.h"
+#include "version.h"
+
+#include <stdarg.h>
+#include <time.h>
+#include <sys/utsname.h>
+
+struct formatter;
+typedef int (*out_with_comment_fn) (struct formatter * f, const char *comment,
+				    const char *fmt, va_list ap);
+typedef int (*nl_fn) (struct formatter * f);
+
+/*
+ * Macro for formatted output.
+ * out_with_comment_fn returns -1 if data didn't fit and buffer was expanded.
+ * Then argument list is reset and out_with_comment_fn is called again.
+ */
+#define _out_with_comment(f, buffer, fmt, ap) \
+	do { \
+		va_start(ap, fmt); \
+		r = f->out_with_comment(f, buffer, fmt, ap); \
+		va_end(ap); \
+	} while (r == -1)
+
+/*
+ * The first half of this file deals with
+ * exporting the vg, ie. writing it to a file.
+ */
+struct formatter {
+	struct dm_pool *mem;	/* pv names allocated from here */
+	struct dm_hash_table *pv_names;	/* dev_name -> pv_name (eg, pv1) */
+
+	union {
+		FILE *fp;	/* where we're writing to */
+		struct {
+			char *start;
+			uint32_t size;
+			uint32_t used;
+		} buf;
+	} data;
+
+	out_with_comment_fn out_with_comment;
+	nl_fn nl;
+
+	int indent;		/* current level of indentation */
+	int error;
+	int header;		/* 1 => comments at start; 0 => end */
+};
+
+static struct utsname _utsname;
+
+static void _init(void)
+{
+	static int _initialised = 0;
+
+	if (_initialised)
+		return;
+
+	if (uname(&_utsname)) {
+		log_error("uname failed: %s", strerror(errno));
+		memset(&_utsname, 0, sizeof(_utsname));
+	}
+
+	_initialised = 1;
+}
+
+/*
+ * Formatting functions.
+ */
+
+#define MAX_INDENT 5
+static void _inc_indent(struct formatter *f)
+{
+	if (++f->indent > MAX_INDENT)
+		f->indent = MAX_INDENT;
+}
+
+static void _dec_indent(struct formatter *f)
+{
+	if (!f->indent--) {
+		log_error("Internal error tracking indentation");
+		f->indent = 0;
+	}
+}
+
+/*
+ * Newline function for prettier layout.
+ */
+static int _nl_file(struct formatter *f)
+{
+	fprintf(f->data.fp, "\n");
+
+	return 1;
+}
+
+static int _extend_buffer(struct formatter *f)
+{
+	char *newbuf;
+
+	log_debug("Doubling metadata output buffer to %" PRIu32,
+		  f->data.buf.size * 2);
+	if (!(newbuf = dm_realloc(f->data.buf.start,
+				   f->data.buf.size * 2))) {
+		log_error("Buffer reallocation failed.");
+		return 0;
+	}
+	f->data.buf.start = newbuf;
+	f->data.buf.size *= 2;
+
+	return 1;
+}
+
+static int _nl_raw(struct formatter *f)
+{
+	/* If metadata doesn't fit, extend buffer */
+	if ((f->data.buf.used + 2 > f->data.buf.size) &&
+	    (!_extend_buffer(f)))
+		return_0;
+
+	*(f->data.buf.start + f->data.buf.used) = '\n';
+	f->data.buf.used += 1;
+
+	*(f->data.buf.start + f->data.buf.used) = '\0';
+
+	return 1;
+}
+
+#define COMMENT_TAB 6
+static int _out_with_comment_file(struct formatter *f, const char *comment,
+				  const char *fmt, va_list ap)
+{
+	int i;
+	char white_space[MAX_INDENT + 1];
+
+	if (ferror(f->data.fp))
+		return 0;
+
+	for (i = 0; i < f->indent; i++)
+		white_space[i] = '\t';
+	white_space[i] = '\0';
+	fputs(white_space, f->data.fp);
+	i = vfprintf(f->data.fp, fmt, ap);
+
+	if (comment) {
+		/*
+		 * line comments up if possible.
+		 */
+		i += 8 * f->indent;
+		i /= 8;
+		i++;
+
+		do
+			fputc('\t', f->data.fp);
+
+		while (++i < COMMENT_TAB);
+
+		fputs(comment, f->data.fp);
+	}
+	fputc('\n', f->data.fp);
+
+	return 1;
+}
+
+static int _out_with_comment_raw(struct formatter *f,
+				 const char *comment __attribute((unused)),
+				 const char *fmt, va_list ap)
+{
+	int n;
+
+	n = vsnprintf(f->data.buf.start + f->data.buf.used,
+		      f->data.buf.size - f->data.buf.used, fmt, ap);
+
+	/* If metadata doesn't fit, extend buffer */
+	if (n < 0 || (n + f->data.buf.used + 2 > f->data.buf.size)) {
+		if (!_extend_buffer(f))
+			return_0;
+		return -1; /* Retry */
+	}
+
+	f->data.buf.used += n;
+
+	outnl(f);
+
+	return 1;
+}
+
+/*
+ * Formats a string, converting a size specified
+ * in 512-byte sectors to a more human readable
+ * form (eg, megabytes).  We may want to lift this
+ * for other code to use.
+ */
+static int _sectors_to_units(uint64_t sectors, char *buffer, size_t s)
+{
+	static const char *_units[] = {
+		"Kilobytes",
+		"Megabytes",
+		"Gigabytes",
+		"Terabytes",
+		"Petabytes",
+		"Exabytes",
+		NULL
+	};
+
+	int i;
+	double d = (double) sectors;
+
+	/* to convert to K */
+	d /= 2.0;
+
+	for (i = 0; (d > 1024.0) && _units[i]; i++)
+		d /= 1024.0;
+
+	return dm_snprintf(buffer, s, "# %g %s", d, _units[i]) > 0;
+}
+
+/*
+ * Appends a comment giving a size in more easily
+ * readable form (eg, 4M instead of 8096).
+ */
+int out_size(struct formatter *f, uint64_t size, const char *fmt, ...)
+{
+	char buffer[64];
+	va_list ap;
+	int r;
+
+	if (!_sectors_to_units(size, buffer, sizeof(buffer)))
+		return 0;
+
+	_out_with_comment(f, buffer, fmt, ap);
+
+	return r;
+}
+
+/*
+ * Appends a comment indicating that the line is
+ * only a hint.
+ */
+int out_hint(struct formatter *f, const char *fmt, ...)
+{
+	va_list ap;
+	int r;
+
+	_out_with_comment(f, "# Hint only", fmt, ap);
+
+	return r;
+}
+
+/*
+ * Appends a comment
+ */
+static int _out_comment(struct formatter *f, const char *comment, const char *fmt, ...)
+{
+	va_list ap;
+	int r;
+
+	_out_with_comment(f, comment, fmt, ap);
+
+	return r;
+}
+
+/*
+ * The normal output function.
+ */
+int out_text(struct formatter *f, const char *fmt, ...)
+{
+	va_list ap;
+	int r;
+
+	_out_with_comment(f, NULL, fmt, ap);
+
+	return r;
+}
+
+static int _print_header(struct formatter *f,
+			 const char *desc)
+{
+	char *buf;
+	time_t t;
+
+	t = time(NULL);
+
+	outf(f, "# Generated by LVM2 version %s: %s", LVM_VERSION, ctime(&t));
+	outf(f, CONTENTS_FIELD " = \"" CONTENTS_VALUE "\"");
+	outf(f, FORMAT_VERSION_FIELD " = %d", FORMAT_VERSION_VALUE);
+	outnl(f);
+
+	if (!(buf = alloca(escaped_len(desc)))) {
+		log_error("temporary stack allocation for description"
+			  "string failed");
+		return 0;
+	}
+	outf(f, "description = \"%s\"", escape_double_quotes(buf, desc));
+	outnl(f);
+	outf(f, "creation_host = \"%s\"\t# %s %s %s %s %s", _utsname.nodename,
+	     _utsname.sysname, _utsname.nodename, _utsname.release,
+	     _utsname.version, _utsname.machine);
+	outf(f, "creation_time = %lu\t# %s", t, ctime(&t));
+
+	return 1;
+}
+
+static int _print_flag_config(struct formatter *f, int status, int type)
+{
+	char buffer[4096];
+	if (!print_flags(status, type | STATUS_FLAG, buffer, sizeof(buffer)))
+		return_0;
+	outf(f, "status = %s", buffer);
+
+	if (!print_flags(status, type, buffer, sizeof(buffer)))
+		return_0;
+	outf(f, "flags = %s", buffer);
+
+	return 1;
+}
+
+static int _print_vg(struct formatter *f, struct volume_group *vg)
+{
+	char buffer[4096];
+
+	if (!id_write_format(&vg->id, buffer, sizeof(buffer)))
+		return_0;
+
+	outf(f, "id = \"%s\"", buffer);
+
+	outf(f, "seqno = %u", vg->seqno);
+
+	if (!_print_flag_config(f, vg->status, VG_FLAGS))
+		return_0;
+
+	if (!dm_list_empty(&vg->tags)) {
+		if (!print_tags(&vg->tags, buffer, sizeof(buffer)))
+			return_0;
+		outf(f, "tags = %s", buffer);
+	}
+
+	if (vg->system_id && *vg->system_id)
+		outf(f, "system_id = \"%s\"", vg->system_id);
+
+	if (!out_size(f, (uint64_t) vg->extent_size, "extent_size = %u",
+		      vg->extent_size))
+		return_0;
+	outf(f, "max_lv = %u", vg->max_lv);
+	outf(f, "max_pv = %u", vg->max_pv);
+
+	/* Default policy is NORMAL; INHERIT is meaningless */
+	if (vg->alloc != ALLOC_NORMAL && vg->alloc != ALLOC_INHERIT) {
+		outnl(f);
+		outf(f, "allocation_policy = \"%s\"",
+		     get_alloc_string(vg->alloc));
+	}
+
+	return 1;
+}
+
+/*
+ * Get the pv%d name from the formatters hash
+ * table.
+ */
+static const char *_get_pv_name(struct formatter *f, struct physical_volume *pv)
+{
+	return (pv) ? (const char *)
+	    dm_hash_lookup(f->pv_names, pv_dev_name(pv)) : "Missing";
+}
+
+static int _print_pvs(struct formatter *f, struct volume_group *vg)
+{
+	struct pv_list *pvl;
+	struct physical_volume *pv;
+	char buffer[4096];
+	char *buf;
+	const char *name;
+
+	outf(f, "physical_volumes {");
+	_inc_indent(f);
+
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		pv = pvl->pv;
+
+		if (!(name = _get_pv_name(f, pv)))
+			return_0;
+
+		outnl(f);
+		outf(f, "%s {", name);
+		_inc_indent(f);
+
+		if (!id_write_format(&pv->id, buffer, sizeof(buffer)))
+			return_0;
+
+		outf(f, "id = \"%s\"", buffer);
+
+		if (!(buf = alloca(escaped_len(pv_dev_name(pv))))) {
+			log_error("temporary stack allocation for device name"
+				  "string failed");
+			return 0;
+		}
+
+		if (!out_hint(f, "device = \"%s\"",
+			      escape_double_quotes(buf, pv_dev_name(pv))))
+			return_0;
+		outnl(f);
+
+		if (!_print_flag_config(f, pv->status, PV_FLAGS))
+			return_0;
+
+		if (!dm_list_empty(&pv->tags)) {
+			if (!print_tags(&pv->tags, buffer, sizeof(buffer)))
+				return_0;
+			outf(f, "tags = %s", buffer);
+		}
+
+		if (!out_size(f, pv->size, "dev_size = %" PRIu64, pv->size))
+			return_0;
+
+		outf(f, "pe_start = %" PRIu64, pv->pe_start);
+		if (!out_size(f, vg->extent_size * (uint64_t) pv->pe_count,
+			      "pe_count = %u", pv->pe_count))
+			return_0;
+
+		_dec_indent(f);
+		outf(f, "}");
+	}
+
+	_dec_indent(f);
+	outf(f, "}");
+	return 1;
+}
+
+static int _print_segment(struct formatter *f, struct volume_group *vg,
+			  int count, struct lv_segment *seg)
+{
+	char buffer[4096];
+
+	outf(f, "segment%u {", count);
+	_inc_indent(f);
+
+	outf(f, "start_extent = %u", seg->le);
+	if (!out_size(f, (uint64_t) seg->len * vg->extent_size,
+		      "extent_count = %u", seg->len))
+		return_0;
+
+	outnl(f);
+	outf(f, "type = \"%s\"", seg->segtype->name);
+
+	if (!dm_list_empty(&seg->tags)) {
+		if (!print_tags(&seg->tags, buffer, sizeof(buffer)))
+			return_0;
+		outf(f, "tags = %s", buffer);
+	}
+
+	if (seg->segtype->ops->text_export &&
+	    !seg->segtype->ops->text_export(seg, f))
+		return_0;
+
+	_dec_indent(f);
+	outf(f, "}");
+
+	return 1;
+}
+
+int out_areas(struct formatter *f, const struct lv_segment *seg,
+	      const char *type)
+{
+	const char *name;
+	unsigned int s;
+
+	outnl(f);
+
+	outf(f, "%ss = [", type);
+	_inc_indent(f);
+
+	for (s = 0; s < seg->area_count; s++) {
+		switch (seg_type(seg, s)) {
+		case AREA_PV:
+			if (!(name = _get_pv_name(f, seg_pv(seg, s))))
+				return_0;
+
+			outf(f, "\"%s\", %u%s", name,
+			     seg_pe(seg, s),
+			     (s == seg->area_count - 1) ? "" : ",");
+			break;
+		case AREA_LV:
+			outf(f, "\"%s\", %u%s",
+			     seg_lv(seg, s)->name,
+			     seg_le(seg, s),
+			     (s == seg->area_count - 1) ? "" : ",");
+			break;
+		case AREA_UNASSIGNED:
+			return 0;
+		}
+	}
+
+	_dec_indent(f);
+	outf(f, "]");
+	return 1;
+}
+
+static int _print_lv(struct formatter *f, struct logical_volume *lv)
+{
+	struct lv_segment *seg;
+	char buffer[4096];
+	int seg_count;
+
+	outnl(f);
+	outf(f, "%s {", lv->name);
+	_inc_indent(f);
+
+	/* FIXME: Write full lvid */
+	if (!id_write_format(&lv->lvid.id[1], buffer, sizeof(buffer)))
+		return_0;
+
+	outf(f, "id = \"%s\"", buffer);
+
+	if (!_print_flag_config(f, lv->status, LV_FLAGS))
+		return_0;
+
+	if (!dm_list_empty(&lv->tags)) {
+		if (!print_tags(&lv->tags, buffer, sizeof(buffer)))
+			return_0;
+		outf(f, "tags = %s", buffer);
+	}
+
+	if (lv->alloc != ALLOC_INHERIT)
+		outf(f, "allocation_policy = \"%s\"",
+		     get_alloc_string(lv->alloc));
+
+	switch (lv->read_ahead) {
+	case DM_READ_AHEAD_NONE:
+		_out_comment(f, "# None", "read_ahead = -1");
+		break;
+	case DM_READ_AHEAD_AUTO:
+		/* No output - use default */
+		break;
+	default:
+		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", dm_list_size(&lv->segments));
+	outnl(f);
+
+	seg_count = 1;
+	dm_list_iterate_items(seg, &lv->segments) {
+		if (!_print_segment(f, lv->vg, seg_count++, seg))
+			return_0;
+	}
+
+	_dec_indent(f);
+	outf(f, "}");
+
+	return 1;
+}
+
+static int _print_lvs(struct formatter *f, struct volume_group *vg)
+{
+	struct lv_list *lvl;
+
+	/*
+	 * Don't bother with an lv section if there are no lvs.
+	 */
+	if (dm_list_empty(&vg->lvs))
+		return 1;
+
+	outf(f, "logical_volumes {");
+	_inc_indent(f);
+
+	/*
+	 * Write visible LVs first
+	 */
+	dm_list_iterate_items(lvl, &vg->lvs) {
+		if (!(lvl->lv->status & VISIBLE_LV))
+			continue;
+		if (!_print_lv(f, lvl->lv))
+			return_0;
+	}
+
+	dm_list_iterate_items(lvl, &vg->lvs) {
+		if ((lvl->lv->status & VISIBLE_LV))
+			continue;
+		if (!_print_lv(f, lvl->lv))
+			return_0;
+	}
+
+	_dec_indent(f);
+	outf(f, "}");
+
+	return 1;
+}
+
+/*
+ * In the text format we refer to pv's as 'pv1',
+ * 'pv2' etc.  This function builds a hash table
+ * to enable a quick lookup from device -> name.
+ */
+static int _build_pv_names(struct formatter *f, struct volume_group *vg)
+{
+	int count = 0;
+	struct pv_list *pvl;
+	struct physical_volume *pv;
+	char buffer[32], *name;
+
+	if (!(f->mem = dm_pool_create("text pv_names", 512)))
+		return_0;
+
+	if (!(f->pv_names = dm_hash_create(128)))
+		return_0;
+
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		pv = pvl->pv;
+
+		/* FIXME But skip if there's already an LV called pv%d ! */
+		if (dm_snprintf(buffer, sizeof(buffer), "pv%d", count++) < 0)
+			return_0;
+
+		if (!(name = dm_pool_strdup(f->mem, buffer)))
+			return_0;
+
+		if (!dm_hash_insert(f->pv_names, pv_dev_name(pv), name))
+			return_0;
+	}
+
+	return 1;
+}
+
+static int _text_vg_export(struct formatter *f,
+			   struct volume_group *vg, const char *desc)
+{
+	int r = 0;
+
+	if (!_build_pv_names(f, vg))
+		goto_out;
+
+	if (f->header && !_print_header(f, desc))
+		goto_out;
+
+	if (!out_text(f, "%s {", vg->name))
+		goto_out;
+
+	_inc_indent(f);
+
+	if (!_print_vg(f, vg))
+		goto_out;
+
+	outnl(f);
+	if (!_print_pvs(f, vg))
+		goto_out;
+
+	outnl(f);
+	if (!_print_lvs(f, vg))
+		goto_out;
+
+	_dec_indent(f);
+	if (!out_text(f, "}"))
+		goto_out;
+
+	if (!f->header && !_print_header(f, desc))
+		goto_out;
+
+	r = 1;
+
+      out:
+	if (f->mem)
+		dm_pool_destroy(f->mem);
+
+	if (f->pv_names)
+		dm_hash_destroy(f->pv_names);
+
+	return r;
+}
+
+int text_vg_export_file(struct volume_group *vg, const char *desc, FILE *fp)
+{
+	struct formatter *f;
+	int r;
+
+	_init();
+
+	if (!(f = dm_malloc(sizeof(*f))))
+		return_0;
+
+	memset(f, 0, sizeof(*f));
+	f->data.fp = fp;
+	f->indent = 0;
+	f->header = 1;
+	f->out_with_comment = &_out_with_comment_file;
+	f->nl = &_nl_file;
+
+	r = _text_vg_export(f, vg, desc);
+	if (r)
+		r = !ferror(f->data.fp);
+	dm_free(f);
+	return r;
+}
+
+/* Returns amount of buffer used incl. terminating NUL */
+int text_vg_export_raw(struct volume_group *vg, const char *desc, char **buf)
+{
+	struct formatter *f;
+	int r = 0;
+
+	_init();
+
+	if (!(f = dm_malloc(sizeof(*f))))
+		return_0;
+
+	memset(f, 0, sizeof(*f));
+
+	f->data.buf.size = 65536;	/* Initial metadata limit */
+	if (!(f->data.buf.start = dm_malloc(f->data.buf.size))) {
+		log_error("text_export buffer allocation failed");
+		goto out;
+	}
+
+	f->indent = 0;
+	f->header = 0;
+	f->out_with_comment = &_out_with_comment_raw;
+	f->nl = &_nl_raw;
+
+	if (!_text_vg_export(f, vg, desc)) {
+		dm_free(f->data.buf.start);
+		goto_out;
+	}
+
+	r = f->data.buf.used + 1;
+	*buf = f->data.buf.start;
+
+      out:
+	dm_free(f);
+	return r;
+}
+
+int export_vg_to_buffer(struct volume_group *vg, char **buf)
+{
+	return text_vg_export_raw(vg, "", buf);
+}
+
+#undef outf
+#undef outnl
Index: src/external/gpl2/lvm2tools/dist/lib/format_text/flags.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format_text/flags.c
diff -N src/external/gpl2/lvm2tools/dist/lib/format_text/flags.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format_text/flags.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,183 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "metadata.h"
+#include "import-export.h"
+#include "lvm-string.h"
+
+/*
+ * Bitsets held in the 'status' flags get
+ * converted into arrays of strings.
+ */
+struct flag {
+	const int mask;
+	const char *description;
+	int kind;
+};
+
+static struct flag _vg_flags[] = {
+	{EXPORTED_VG, "EXPORTED", STATUS_FLAG},
+	{RESIZEABLE_VG, "RESIZEABLE", STATUS_FLAG},
+	{PVMOVE, "PVMOVE", STATUS_FLAG},
+	{LVM_READ, "READ", STATUS_FLAG},
+	{LVM_WRITE, "WRITE", STATUS_FLAG},
+	{CLUSTERED, "CLUSTERED", STATUS_FLAG},
+	{SHARED, "SHARED", STATUS_FLAG},
+	{PARTIAL_VG, NULL, 0},
+	{PRECOMMITTED, NULL, 0},
+	{0, NULL, 0}
+};
+
+static struct flag _pv_flags[] = {
+	{ALLOCATABLE_PV, "ALLOCATABLE", STATUS_FLAG},
+	{EXPORTED_VG, "EXPORTED", STATUS_FLAG},
+	{MISSING_PV, "MISSING", COMPATIBLE_FLAG},
+	{0, NULL, 0}
+};
+
+static struct flag _lv_flags[] = {
+	{LVM_READ, "READ", STATUS_FLAG},
+	{LVM_WRITE, "WRITE", STATUS_FLAG},
+	{FIXED_MINOR, "FIXED_MINOR", STATUS_FLAG},
+	{VISIBLE_LV, "VISIBLE", STATUS_FLAG},
+	{PVMOVE, "PVMOVE", STATUS_FLAG},
+	{LOCKED, "LOCKED", STATUS_FLAG},
+	{MIRROR_NOTSYNCED, "NOTSYNCED", STATUS_FLAG},
+	{MIRROR_IMAGE, NULL, 0},
+	{MIRROR_LOG, NULL, 0},
+	{MIRRORED, NULL, 0},
+	{VIRTUAL, NULL, 0},
+	{SNAPSHOT, NULL, 0},
+	{ACTIVATE_EXCL, NULL, 0},
+	{CONVERTING, NULL, 0},
+	{PARTIAL_LV, NULL, 0},
+	{POSTORDER_FLAG, NULL, 0},
+	{0, NULL, 0}
+};
+
+static struct flag *_get_flags(int type)
+{
+	switch (type & ~STATUS_FLAG) {
+	case VG_FLAGS:
+		return _vg_flags;
+
+	case PV_FLAGS:
+		return _pv_flags;
+
+	case LV_FLAGS:
+		return _lv_flags;
+	}
+
+	log_err("Unknown flag set requested.");
+	return NULL;
+}
+
+/*
+ * Converts a bitset to an array of string values,
+ * using one of the tables defined at the top of
+ * the file.
+ */
+int print_flags(uint32_t status, int type, char *buffer, size_t size)
+{
+	int f, first = 1;
+	struct flag *flags;
+
+	if (!(flags = _get_flags(type)))
+		return_0;
+
+	if (!emit_to_buffer(&buffer, &size, "["))
+		return 0;
+
+	for (f = 0; flags[f].mask; f++) {
+		if (status & flags[f].mask) {
+			status &= ~flags[f].mask;
+
+			if ((type & STATUS_FLAG) != flags[f].kind)
+				continue;
+
+			/* Internal-only flag? */
+			if (!flags[f].description)
+				continue;
+
+			if (!first) {
+				if (!emit_to_buffer(&buffer, &size, ", "))
+					return 0;
+			} else
+				first = 0;
+	
+			if (!emit_to_buffer(&buffer, &size, "\"%s\"",
+			    flags[f].description))
+				return 0;
+		}
+	}
+
+	if (!emit_to_buffer(&buffer, &size, "]"))
+		return 0;
+
+	if (status)
+		log_error("Metadata inconsistency: Not all flags successfully "
+			  "exported.");
+
+	return 1;
+}
+
+int read_flags(uint32_t *status, int type, struct config_value *cv)
+{
+	int f;
+	uint32_t s = 0;
+	struct flag *flags;
+
+	if (!(flags = _get_flags(type)))
+		return_0;
+
+	if (cv->type == CFG_EMPTY_ARRAY)
+		goto out;
+
+	while (cv) {
+		if (cv->type != CFG_STRING) {
+			log_err("Status value is not a string.");
+			return 0;
+		}
+
+		for (f = 0; flags[f].description; f++)
+			if (!strcmp(flags[f].description, cv->v.str)) {
+				s |= flags[f].mask;
+				break;
+			}
+
+		if (type == VG_FLAGS && !strcmp(cv->v.str, "PARTIAL")) {
+			/*
+			 * Exception: We no longer write this flag out, but it
+			 * might be encountered in old backup files, so restore
+			 * it in that case. It is never part of live metadata
+			 * though, so only vgcfgrestore needs to be concerned
+			 * by this case.
+			 */
+			s |= PARTIAL_VG;
+		} else if (!flags[f].description && (type & STATUS_FLAG)) {
+			log_err("Unknown status flag '%s'.", cv->v.str);
+			return 0;
+		}
+
+		cv = cv->next;
+	}
+
+      out:
+	*status |= s;
+	return 1;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/format_text/format-text.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format_text/format-text.c
diff -N src/external/gpl2/lvm2tools/dist/lib/format_text/format-text.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format_text/format-text.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,1977 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "format-text.h"
+#include "import-export.h"
+#include "device.h"
+#include "lvm-file.h"
+#include "config.h"
+#include "display.h"
+#include "toolcontext.h"
+#include "lvm-string.h"
+#include "uuid.h"
+#include "layout.h"
+#include "crc.h"
+#include "xlate.h"
+#include "label.h"
+#include "memlock.h"
+#include "lvmcache.h"
+
+#include <unistd.h>
+#include <sys/file.h>
+#include <limits.h>
+#include <dirent.h>
+#include <ctype.h>
+
+static struct mda_header *_raw_read_mda_header(const struct format_type *fmt,
+					       struct device_area *dev_area);
+
+static struct format_instance *_text_create_text_instance(const struct format_type
+						     *fmt, const char *vgname,
+						     const char *vgid,
+						     void *context);
+
+struct text_fid_context {
+	char *raw_metadata_buf;
+	uint32_t raw_metadata_buf_size;
+};
+
+struct dir_list {
+	struct dm_list list;
+	char dir[0];
+};
+
+struct raw_list {
+	struct dm_list list;
+	struct device_area dev_area;
+};
+
+struct text_context {
+	char *path_live;	/* Path to file holding live metadata */
+	char *path_edit;	/* Path to file holding edited metadata */
+	char *desc;		/* Description placed inside file */
+};
+
+/*
+ * NOTE: Currently there can be only one vg per text file.
+ */
+
+static int _text_vg_setup(struct format_instance *fid __attribute((unused)),
+			  struct volume_group *vg)
+{
+	if (vg->extent_size & (vg->extent_size - 1)) {
+		log_error("Extent size must be power of 2");
+		return 0;
+	}
+
+	return 1;
+}
+
+static uint64_t _mda_free_sectors_raw(struct metadata_area *mda)
+{
+	struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
+
+	return mdac->free_sectors;
+}
+
+/*
+ * Check if metadata area belongs to vg
+ */
+static int _mda_in_vg_raw(struct format_instance *fid __attribute((unused)),
+			     struct volume_group *vg, struct metadata_area *mda)
+{
+	struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
+	struct pv_list *pvl;
+
+	dm_list_iterate_items(pvl, &vg->pvs)
+		if (pvl->pv->dev == mdac->area.dev)
+			return 1;
+
+	return 0;
+}
+
+/*
+ * For circular region between region_start and region_start + region_size,
+ * back up one SECTOR_SIZE from 'region_ptr' and return the value.
+ * This allows reverse traversal through text metadata area to find old
+ * metadata.
+ *
+ * Parameters:
+ *   region_start: start of the region (bytes)
+ *   region_size: size of the region (bytes)
+ *   region_ptr: pointer within the region (bytes)
+ *   NOTE: region_start <= region_ptr <= region_start + region_size
+ */
+static uint64_t _get_prev_sector_circular(uint64_t region_start,
+					  uint64_t region_size,
+					  uint64_t region_ptr)
+{
+	if (region_ptr >= region_start + SECTOR_SIZE)
+		return region_ptr - SECTOR_SIZE;
+	else
+		return (region_start + region_size - SECTOR_SIZE);
+}
+
+/*
+ * Analyze a metadata area for old metadata records in the circular buffer.
+ * This function just looks through and makes a first pass at the data in
+ * the sectors for particular things.
+ * FIXME: do something with each metadata area (try to extract vg, write
+ * raw data to file, etc)
+ */
+static int _pv_analyze_mda_raw (const struct format_type * fmt,
+				struct metadata_area *mda)
+{
+	struct mda_header *mdah;
+	struct raw_locn *rlocn;
+	uint64_t area_start;
+	uint64_t area_size;
+	uint64_t prev_sector, prev_sector2;
+	uint64_t latest_mrec_offset;
+	int i;
+	uint64_t offset;
+	uint64_t offset2;
+	size_t size;
+	size_t size2;
+	char *buf=NULL;
+	struct device_area *area;
+	struct mda_context *mdac;
+	int r=0;
+
+	mdac = (struct mda_context *) mda->metadata_locn;
+
+	log_print("Found text metadata area: offset=%" PRIu64 ", size=%"
+		  PRIu64, mdac->area.start, mdac->area.size);
+	area = &mdac->area;
+
+	if (!dev_open(area->dev))
+		return_0;
+
+	if (!(mdah = _raw_read_mda_header(fmt, area)))
+		goto_out;
+
+	rlocn = mdah->raw_locns;
+
+	/*
+	 * The device area includes the metadata header as well as the
+	 * records, so remove the metadata header from the start and size
+	 */
+	area_start = area->start + MDA_HEADER_SIZE;
+	area_size = area->size - MDA_HEADER_SIZE;
+	latest_mrec_offset = rlocn->offset + area->start;
+
+	/*
+	 * Start searching at rlocn (point of live metadata) and go
+	 * backwards.
+	 */
+	prev_sector = _get_prev_sector_circular(area_start, area_size,
+					       latest_mrec_offset);
+	offset = prev_sector;
+	size = SECTOR_SIZE;
+	offset2 = size2 = 0;
+	i = 0;
+	while (prev_sector != latest_mrec_offset) {
+		prev_sector2 = prev_sector;
+		prev_sector = _get_prev_sector_circular(area_start, area_size,
+							prev_sector);
+		if (prev_sector > prev_sector2)
+			goto_out;
+		/*
+		 * FIXME: for some reason, the whole metadata region from
+		 * area->start to area->start+area->size is not used.
+		 * Only ~32KB seems to contain valid metadata records
+		 * (LVM2 format - format_text).  As a result, I end up with
+		 * "maybe_config_section" returning true when there's no valid
+		 * metadata in a sector (sectors with all nulls).
+		 */
+		if (!(buf = dm_pool_alloc(fmt->cmd->mem, size + size2)))
+			goto_out;
+
+		if (!dev_read_circular(area->dev, offset, size,
+				       offset2, size2, buf))
+			goto_out;
+
+		/*
+		 * FIXME: We could add more sophisticated metadata detection
+		 */
+		if (maybe_config_section(buf, size + size2)) {
+			/* FIXME: Validate region, pull out timestamp?, etc */
+			/* FIXME: Do something with this region */
+			log_verbose ("Found LVM2 metadata record at "
+				     "offset=%"PRIu64", size=%"PRIsize_t", "
+				     "offset2=%"PRIu64" size2=%"PRIsize_t,
+				     offset, size, offset2, size2);
+			offset = prev_sector;
+			size = SECTOR_SIZE;
+			offset2 = size2 = 0;
+		} else {
+			/*
+			 * Not a complete metadata record, assume we have
+			 * metadata and just increase the size and offset.
+			 * Start the second region if the previous sector is
+			 * wrapping around towards the end of the disk.
+			 */
+			if (prev_sector > offset) {
+				offset2 = prev_sector;
+				size2 += SECTOR_SIZE;
+			} else {
+				offset = prev_sector;
+				size += SECTOR_SIZE;
+			}
+		}
+		dm_pool_free(fmt->cmd->mem, buf);
+		buf = NULL;
+	}
+
+	r = 1;
+ out:
+	if (buf)
+		dm_pool_free(fmt->cmd->mem, buf);
+	if (!dev_close(area->dev))
+		stack;
+	return r;
+}
+
+
+
+static int _text_lv_setup(struct format_instance *fid __attribute((unused)),
+			  struct logical_volume *lv)
+{
+/******** FIXME Any LV size restriction?
+	uint64_t max_size = UINT_MAX;
+
+	if (lv->size > max_size) {
+		char *dummy = display_size(max_size);
+		log_error("logical volumes cannot be larger than %s", dummy);
+		dm_free(dummy);
+		return 0;
+	}
+*/
+
+	if (!*lv->lvid.s && !lvid_create(&lv->lvid, &lv->vg->id)) {
+		log_error("Random lvid creation failed for %s/%s.",
+			  lv->vg->name, lv->name);
+		return 0;
+	}
+
+	return 1;
+}
+
+static void _xlate_mdah(struct mda_header *mdah)
+{
+	struct raw_locn *rl;
+
+	mdah->version = xlate32(mdah->version);
+	mdah->start = xlate64(mdah->start);
+	mdah->size = xlate64(mdah->size);
+
+	rl = &mdah->raw_locns[0];
+	while (rl->offset) {
+		rl->checksum = xlate32(rl->checksum);
+		rl->offset = xlate64(rl->offset);
+		rl->size = xlate64(rl->size);
+		rl++;
+	}
+}
+
+static struct mda_header *_raw_read_mda_header(const struct format_type *fmt,
+					       struct device_area *dev_area)
+{
+	struct mda_header *mdah;
+
+	if (!(mdah = dm_pool_alloc(fmt->cmd->mem, MDA_HEADER_SIZE))) {
+		log_error("struct mda_header allocation failed");
+		return NULL;
+	}
+
+	if (!dev_read(dev_area->dev, dev_area->start, MDA_HEADER_SIZE, mdah))
+		goto_bad;
+
+	if (mdah->checksum_xl != xlate32(calc_crc(INITIAL_CRC, mdah->magic,
+						  MDA_HEADER_SIZE -
+						  sizeof(mdah->checksum_xl)))) {
+		log_error("Incorrect metadata area header checksum");
+		goto bad;
+	}
+
+	_xlate_mdah(mdah);
+
+	if (strncmp((char *)mdah->magic, FMTT_MAGIC, sizeof(mdah->magic))) {
+		log_error("Wrong magic number in metadata area header");
+		goto bad;
+	}
+
+	if (mdah->version != FMTT_VERSION) {
+		log_error("Incompatible metadata area header version: %d",
+			  mdah->version);
+		goto bad;
+	}
+
+	if (mdah->start != dev_area->start) {
+		log_error("Incorrect start sector in metadata area header: %"
+			  PRIu64, mdah->start);
+		goto bad;
+	}
+
+	return mdah;
+
+bad:
+	dm_pool_free(fmt->cmd->mem, mdah);
+	return NULL;
+}
+
+static int _raw_write_mda_header(const struct format_type *fmt,
+				 struct device *dev,
+				 uint64_t start_byte, struct mda_header *mdah)
+{
+	strncpy((char *)mdah->magic, FMTT_MAGIC, sizeof(mdah->magic));
+	mdah->version = FMTT_VERSION;
+	mdah->start = start_byte;
+
+	_xlate_mdah(mdah);
+	mdah->checksum_xl = xlate32(calc_crc(INITIAL_CRC, mdah->magic,
+					     MDA_HEADER_SIZE -
+					     sizeof(mdah->checksum_xl)));
+
+	if (!dev_write(dev, start_byte, MDA_HEADER_SIZE, mdah))
+		return_0;
+
+	return 1;
+}
+
+static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
+				       struct mda_header *mdah,
+				       const char *vgname,
+				       int *precommitted)
+{
+	size_t len;
+	char vgnamebuf[NAME_LEN + 2] __attribute((aligned(8)));
+	struct raw_locn *rlocn, *rlocn_precommitted;
+	struct lvmcache_info *info;
+
+	rlocn = mdah->raw_locns;	/* Slot 0 */
+	rlocn_precommitted = rlocn + 1;	/* Slot 1 */
+
+	/* Should we use precommitted metadata? */
+	if (*precommitted && rlocn_precommitted->size &&
+	    (rlocn_precommitted->offset != rlocn->offset)) {
+		rlocn = rlocn_precommitted;
+	} else
+		*precommitted = 0;
+
+	/* FIXME Loop through rlocns two-at-a-time.  List null-terminated. */
+	/* FIXME Ignore if checksum incorrect!!! */
+	if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
+		      sizeof(vgnamebuf), vgnamebuf))
+		goto_bad;
+
+	if (!strncmp(vgnamebuf, vgname, len = strlen(vgname)) &&
+	    (isspace(vgnamebuf[len]) || vgnamebuf[len] == '{')) {
+		return rlocn;
+	}
+
+      bad:
+	if ((info = info_from_pvid(dev_area->dev->pvid, 0)))
+		lvmcache_update_vgname_and_id(info, FMT_TEXT_ORPHAN_VG_NAME,
+					      FMT_TEXT_ORPHAN_VG_NAME, 0, NULL);
+
+	return NULL;
+}
+
+/*
+ * Determine offset for uncommitted metadata
+ */
+static uint64_t _next_rlocn_offset(struct raw_locn *rlocn,
+				   struct mda_header *mdah)
+{
+	if (!rlocn)
+		/* Find an empty slot */
+		/* FIXME Assume only one VG per mdah for now */
+		return MDA_HEADER_SIZE;
+
+	/* Start of free space - round up to next sector; circular */
+	return ((rlocn->offset + rlocn->size +
+		(SECTOR_SIZE - rlocn->size % SECTOR_SIZE) -
+		MDA_HEADER_SIZE) % (mdah->size - MDA_HEADER_SIZE))
+	       + MDA_HEADER_SIZE;
+}
+
+static int _raw_holds_vgname(struct format_instance *fid,
+			     struct device_area *dev_area, const char *vgname)
+{
+	int r = 0;
+	int noprecommit = 0;
+	struct mda_header *mdah;
+
+	if (!dev_open(dev_area->dev))
+		return_0;
+
+	if (!(mdah = _raw_read_mda_header(fid->fmt, dev_area)))
+		return_0;
+
+	if (_find_vg_rlocn(dev_area, mdah, vgname, &noprecommit))
+		r = 1;
+
+	if (!dev_close(dev_area->dev))
+		stack;
+
+	return r;
+}
+
+static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
+					      const char *vgname,
+					      struct device_area *area,
+					      int precommitted)
+{
+	struct volume_group *vg = NULL;
+	struct raw_locn *rlocn;
+	struct mda_header *mdah;
+	time_t when;
+	char *desc;
+	uint32_t wrap = 0;
+
+	if (!dev_open(area->dev))
+		return_NULL;
+
+	if (!(mdah = _raw_read_mda_header(fid->fmt, area)))
+		goto_out;
+
+	if (!(rlocn = _find_vg_rlocn(area, mdah, vgname, &precommitted))) {
+		log_debug("VG %s not found on %s", vgname, dev_name(area->dev));
+		goto out;
+	}
+
+	if (rlocn->offset + rlocn->size > mdah->size)
+		wrap = (uint32_t) ((rlocn->offset + rlocn->size) - mdah->size);
+
+	if (wrap > rlocn->offset) {
+		log_error("VG %s metadata too large for circular buffer",
+			  vg->name);
+		goto out;
+	}
+
+	/* FIXME 64-bit */
+	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),
+				     wrap, calc_crc, rlocn->checksum, &when,
+				     &desc)))
+		goto_out;
+	log_debug("Read %s %smetadata (%u) from %s at %" PRIu64 " size %"
+		  PRIu64, vg->name, precommitted ? "pre-commit " : "",
+		  vg->seqno, dev_name(area->dev),
+		  area->start + rlocn->offset, rlocn->size);
+
+	if (precommitted)
+		vg->status |= PRECOMMITTED;
+
+      out:
+	if (!dev_close(area->dev))
+		stack;
+
+	return vg;
+}
+
+static struct volume_group *_vg_read_raw(struct format_instance *fid,
+					 const char *vgname,
+					 struct metadata_area *mda)
+{
+	struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
+
+	return _vg_read_raw_area(fid, vgname, &mdac->area, 0);
+}
+
+static struct volume_group *_vg_read_precommit_raw(struct format_instance *fid,
+						   const char *vgname,
+						   struct metadata_area *mda)
+{
+	struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
+
+	return _vg_read_raw_area(fid, vgname, &mdac->area, 1);
+}
+
+static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
+			 struct metadata_area *mda)
+{
+	struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
+	struct text_fid_context *fidtc = (struct text_fid_context *) fid->private;
+	struct raw_locn *rlocn;
+	struct mda_header *mdah;
+	struct pv_list *pvl;
+	int r = 0;
+       uint64_t new_wrap = 0, old_wrap = 0, new_end;
+	int found = 0;
+	int noprecommit = 0;
+
+	/* Ignore any mda on a PV outside the VG. vgsplit relies on this */
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		if (pvl->pv->dev == mdac->area.dev) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (!found)
+		return 1;
+
+	if (!dev_open(mdac->area.dev))
+		return_0;
+
+	if (!(mdah = _raw_read_mda_header(fid->fmt, &mdac->area)))
+		goto_out;
+
+	rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name, &noprecommit);
+	mdac->rlocn.offset = _next_rlocn_offset(rlocn, mdah);
+
+	if (!fidtc->raw_metadata_buf &&
+	    !(fidtc->raw_metadata_buf_size =
+			text_vg_export_raw(vg, "", &fidtc->raw_metadata_buf))) {
+		log_error("VG %s metadata writing failed", vg->name);
+		goto out;
+	}
+
+	mdac->rlocn.size = fidtc->raw_metadata_buf_size;
+
+	if (mdac->rlocn.offset + mdac->rlocn.size > mdah->size)
+		new_wrap = (mdac->rlocn.offset + mdac->rlocn.size) - mdah->size;
+
+	if (rlocn && (rlocn->offset + rlocn->size > mdah->size))
+		old_wrap = (rlocn->offset + rlocn->size) - mdah->size;
+
+	new_end = new_wrap ? new_wrap + MDA_HEADER_SIZE :
+			    mdac->rlocn.offset + mdac->rlocn.size;
+
+	if ((new_wrap && old_wrap) ||
+	    (rlocn && (new_wrap || old_wrap) && (new_end > rlocn->offset)) ||
+	    (mdac->rlocn.size >= mdah->size)) {
+		log_error("VG %s metadata too large for circular buffer",
+			  vg->name);
+		goto out;
+	}
+
+	log_debug("Writing %s metadata to %s at %" PRIu64 " len %" PRIu64,
+		  vg->name, dev_name(mdac->area.dev), mdac->area.start +
+		  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),
+		       fidtc->raw_metadata_buf))
+		goto_out;
+
+	if (new_wrap) {
+               log_debug("Writing metadata to %s at %" PRIu64 " len %" PRIu64,
+			  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,
+			       fidtc->raw_metadata_buf +
+			       mdac->rlocn.size - new_wrap))
+			goto_out;
+	}
+
+	mdac->rlocn.checksum = calc_crc(INITIAL_CRC, fidtc->raw_metadata_buf,
+					(uint32_t) (mdac->rlocn.size -
+						    new_wrap));
+	if (new_wrap)
+		mdac->rlocn.checksum = calc_crc(mdac->rlocn.checksum,
+						fidtc->raw_metadata_buf +
+						mdac->rlocn.size -
+						new_wrap, (uint32_t) new_wrap);
+
+	r = 1;
+
+      out:
+	if (!r) {
+		if (!dev_close(mdac->area.dev))
+			stack;
+
+		if (fidtc->raw_metadata_buf) {
+			dm_free(fidtc->raw_metadata_buf);
+			fidtc->raw_metadata_buf = NULL;
+		}
+	}
+
+	return r;
+}
+
+static int _vg_commit_raw_rlocn(struct format_instance *fid,
+				struct volume_group *vg,
+				struct metadata_area *mda,
+				int precommit)
+{
+	struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
+	struct text_fid_context *fidtc = (struct text_fid_context *) fid->private;
+	struct mda_header *mdah;
+	struct raw_locn *rlocn;
+	struct pv_list *pvl;
+	int r = 0;
+	int found = 0;
+	int noprecommit = 0;
+
+	/* Ignore any mda on a PV outside the VG. vgsplit relies on this */
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		if (pvl->pv->dev == mdac->area.dev) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (!found)
+		return 1;
+
+	if (!(mdah = _raw_read_mda_header(fid->fmt, &mdac->area)))
+		goto_out;
+
+	if (!(rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name, &noprecommit))) {
+		mdah->raw_locns[0].offset = 0;
+		mdah->raw_locns[0].size = 0;
+		mdah->raw_locns[0].checksum = 0;
+		mdah->raw_locns[1].offset = 0;
+		mdah->raw_locns[1].size = 0;
+		mdah->raw_locns[1].checksum = 0;
+		mdah->raw_locns[2].offset = 0;
+		mdah->raw_locns[2].size = 0;
+		mdah->raw_locns[2].checksum = 0;
+		rlocn = &mdah->raw_locns[0];
+	}
+
+	if (precommit)
+		rlocn++;
+	else {
+		/* If not precommitting, wipe the precommitted rlocn */
+		mdah->raw_locns[1].offset = 0;
+		mdah->raw_locns[1].size = 0;
+		mdah->raw_locns[1].checksum = 0;
+	}
+
+	/* Is there new metadata to commit? */
+	if (mdac->rlocn.size) {
+		rlocn->offset = mdac->rlocn.offset;
+		rlocn->size = mdac->rlocn.size;
+		rlocn->checksum = mdac->rlocn.checksum;
+		log_debug("%sCommitting %s metadata (%u) to %s header at %"
+			  PRIu64, precommit ? "Pre-" : "", vg->name, vg->seqno,
+			  dev_name(mdac->area.dev), mdac->area.start);
+	} else
+		log_debug("Wiping pre-committed %s metadata from %s "
+			  "header at %" PRIu64, vg->name,
+			  dev_name(mdac->area.dev), mdac->area.start);
+
+	if (!_raw_write_mda_header(fid->fmt, mdac->area.dev, mdac->area.start,
+				   mdah)) {
+		dm_pool_free(fid->fmt->cmd->mem, mdah);
+		log_error("Failed to write metadata area header");
+		goto out;
+	}
+
+	r = 1;
+
+      out:
+	if (!precommit) {
+		if (!dev_close(mdac->area.dev))
+			stack;
+		if (fidtc->raw_metadata_buf) {
+			dm_free(fidtc->raw_metadata_buf);
+			fidtc->raw_metadata_buf = NULL;
+		}
+	}
+
+	return r;
+}
+
+static int _vg_commit_raw(struct format_instance *fid, struct volume_group *vg,
+			  struct metadata_area *mda)
+{
+	return _vg_commit_raw_rlocn(fid, vg, mda, 0);
+}
+
+static int _vg_precommit_raw(struct format_instance *fid,
+			     struct volume_group *vg,
+			     struct metadata_area *mda)
+{
+	return _vg_commit_raw_rlocn(fid, vg, mda, 1);
+}
+
+/* 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 pv_list *pvl;
+	int found = 0;
+
+	/* Ignore any mda on a PV outside the VG. vgsplit relies on this */
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		if (pvl->pv->dev == mdac->area.dev) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (!found)
+		return 1;
+
+	/* Wipe pre-committed metadata */
+	mdac->rlocn.size = 0;
+	return _vg_commit_raw_rlocn(fid, vg, mda, 0);
+}
+
+static int _vg_remove_raw(struct format_instance *fid, struct volume_group *vg,
+			  struct metadata_area *mda)
+{
+	struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
+	struct mda_header *mdah;
+	struct raw_locn *rlocn;
+	int r = 0;
+	int noprecommit = 0;
+
+	if (!dev_open(mdac->area.dev))
+		return_0;
+
+	if (!(mdah = _raw_read_mda_header(fid->fmt, &mdac->area)))
+		goto_out;
+
+	if (!(rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name, &noprecommit))) {
+		rlocn = &mdah->raw_locns[0];
+		mdah->raw_locns[1].offset = 0;
+	}
+
+	rlocn->offset = 0;
+	rlocn->size = 0;
+	rlocn->checksum = 0;
+
+	if (!_raw_write_mda_header(fid->fmt, mdac->area.dev, mdac->area.start,
+				   mdah)) {
+		dm_pool_free(fid->fmt->cmd->mem, mdah);
+		log_error("Failed to write metadata area header");
+		goto out;
+	}
+
+	r = 1;
+
+      out:
+	if (!dev_close(mdac->area.dev))
+		stack;
+
+	return r;
+}
+
+static struct volume_group *_vg_read_file_name(struct format_instance *fid,
+					       const char *vgname,
+					       const char *read_path)
+{
+	struct volume_group *vg;
+	time_t when;
+	char *desc;
+
+	if (!(vg = text_vg_import_file(fid, read_path, &when, &desc)))
+		return_NULL;
+
+	/*
+	 * Currently you can only have a single volume group per
+	 * text file (this restriction may remain).  We need to
+	 * check that it contains the correct volume group.
+	 */
+	if (vgname && strcmp(vgname, vg->name)) {
+		dm_pool_free(fid->fmt->cmd->mem, vg);
+		log_err("'%s' does not contain volume group '%s'.",
+			read_path, vgname);
+		return NULL;
+	} else
+		log_debug("Read volume group %s from %s", vg->name, read_path);
+
+	return vg;
+}
+
+static struct volume_group *_vg_read_file(struct format_instance *fid,
+					  const char *vgname,
+					  struct metadata_area *mda)
+{
+	struct text_context *tc = (struct text_context *) mda->metadata_locn;
+
+	return _vg_read_file_name(fid, vgname, tc->path_live);
+}
+
+static struct volume_group *_vg_read_precommit_file(struct format_instance *fid,
+						    const char *vgname,
+						    struct metadata_area *mda)
+{
+	struct text_context *tc = (struct text_context *) mda->metadata_locn;
+	struct volume_group *vg;
+
+	if ((vg = _vg_read_file_name(fid, vgname, tc->path_edit)))
+		vg->status |= PRECOMMITTED;
+	else
+		vg = _vg_read_file_name(fid, vgname, tc->path_live);
+
+	return vg;
+}
+
+static int _vg_write_file(struct format_instance *fid __attribute((unused)),
+			  struct volume_group *vg, struct metadata_area *mda)
+{
+	struct text_context *tc = (struct text_context *) mda->metadata_locn;
+
+	FILE *fp;
+	int fd;
+	char *slash;
+	char temp_file[PATH_MAX], temp_dir[PATH_MAX];
+
+	slash = strrchr(tc->path_edit, '/');
+
+	if (slash == 0)
+		strcpy(temp_dir, ".");
+	else if (slash - tc->path_edit < PATH_MAX) {
+		strncpy(temp_dir, tc->path_edit,
+			(size_t) (slash - tc->path_edit));
+		temp_dir[slash - tc->path_edit] = '\0';
+
+	} else {
+		log_error("Text format failed to determine directory.");
+		return 0;
+	}
+
+	if (!create_temp_name(temp_dir, temp_file, sizeof(temp_file), &fd)) {
+		log_err("Couldn't create temporary text file name.");
+		return 0;
+	}
+
+	if (!(fp = fdopen(fd, "w"))) {
+		log_sys_error("fdopen", temp_file);
+		if (close(fd))
+			log_sys_error("fclose", temp_file);
+		return 0;
+	}
+
+	log_debug("Writing %s metadata to %s", vg->name, temp_file);
+
+	if (!text_vg_export_file(vg, tc->desc, fp)) {
+		log_error("Failed to write metadata to %s.", temp_file);
+		if (fclose(fp))
+			log_sys_error("fclose", temp_file);
+		return 0;
+	}
+
+	if (fsync(fd) && (errno != EROFS) && (errno != EINVAL)) {
+		log_sys_error("fsync", tc->path_edit);
+		if (fclose(fp))
+			log_sys_error("fclose", tc->path_edit);
+		return 0;
+	}
+
+	if (lvm_fclose(fp, tc->path_edit))
+		return_0;
+
+	if (rename(temp_file, tc->path_edit)) {
+		log_debug("Renaming %s to %s", temp_file, tc->path_edit);
+		log_error("%s: rename to %s failed: %s", temp_file,
+			  tc->path_edit, strerror(errno));
+		return 0;
+	}
+
+	return 1;
+}
+
+static int _vg_commit_file_backup(struct format_instance *fid __attribute((unused)),
+				  struct volume_group *vg,
+				  struct metadata_area *mda)
+{
+	struct text_context *tc = (struct text_context *) mda->metadata_locn;
+
+	if (test_mode()) {
+		log_verbose("Test mode: Skipping committing %s metadata (%u)",
+			    vg->name, vg->seqno);
+		if (unlink(tc->path_edit)) {
+			log_debug("Unlinking %s", tc->path_edit);
+			log_sys_error("unlink", tc->path_edit);
+			return 0;
+		}
+	} else {
+		log_debug("Committing %s metadata (%u)", vg->name, vg->seqno);
+		log_debug("Renaming %s to %s", tc->path_edit, tc->path_live);
+		if (rename(tc->path_edit, tc->path_live)) {
+			log_error("%s: rename to %s failed: %s", tc->path_edit,
+				  tc->path_live, strerror(errno));
+			return 0;
+		}
+	}
+
+	sync_dir(tc->path_edit);
+
+	return 1;
+}
+
+static int _vg_commit_file(struct format_instance *fid, struct volume_group *vg,
+			   struct metadata_area *mda)
+{
+	struct text_context *tc = (struct text_context *) mda->metadata_locn;
+	char *slash;
+	char new_name[PATH_MAX];
+	size_t len;
+
+	if (!_vg_commit_file_backup(fid, vg, mda))
+		return 0;
+
+	/* vgrename? */
+	if ((slash = strrchr(tc->path_live, '/')))
+		slash = slash + 1;
+	else
+		slash = tc->path_live;
+
+	if (strcmp(slash, vg->name)) {
+		len = slash - tc->path_live;
+		strncpy(new_name, tc->path_live, len);
+		strcpy(new_name + len, vg->name);
+		log_debug("Renaming %s to %s", tc->path_live, new_name);
+		if (test_mode())
+			log_verbose("Test mode: Skipping rename");
+		else {
+			if (rename(tc->path_live, new_name)) {
+				log_error("%s: rename to %s failed: %s",
+					  tc->path_live, new_name,
+					  strerror(errno));
+				sync_dir(new_name);
+				return 0;
+			}
+		}
+	}
+
+	return 1;
+}
+
+static int _vg_remove_file(struct format_instance *fid __attribute((unused)),
+			   struct volume_group *vg __attribute((unused)),
+			   struct metadata_area *mda)
+{
+	struct text_context *tc = (struct text_context *) mda->metadata_locn;
+
+	if (path_exists(tc->path_edit) && unlink(tc->path_edit)) {
+		log_sys_error("unlink", tc->path_edit);
+		return 0;
+	}
+
+	if (path_exists(tc->path_live) && unlink(tc->path_live)) {
+		log_sys_error("unlink", tc->path_live);
+		return 0;
+	}
+
+	sync_dir(tc->path_live);
+
+	return 1;
+}
+
+static int _scan_file(const struct format_type *fmt)
+{
+	struct dirent *dirent;
+	struct dir_list *dl;
+	struct dm_list *dir_list;
+	char *tmp;
+	DIR *d;
+	struct volume_group *vg;
+	struct format_instance *fid;
+	char path[PATH_MAX];
+	char *vgname;
+
+	dir_list = &((struct mda_lists *) fmt->private)->dirs;
+
+	dm_list_iterate_items(dl, dir_list) {
+		if (!(d = opendir(dl->dir))) {
+			log_sys_error("opendir", dl->dir);
+			continue;
+		}
+		while ((dirent = readdir(d)))
+			if (strcmp(dirent->d_name, ".") &&
+			    strcmp(dirent->d_name, "..") &&
+			    (!(tmp = strstr(dirent->d_name, ".tmp")) ||
+			     tmp != dirent->d_name + strlen(dirent->d_name)
+			     - 4)) {
+				vgname = dirent->d_name;
+				if (dm_snprintf(path, PATH_MAX, "%s/%s",
+						 dl->dir, vgname) < 0) {
+					log_error("Name too long %s/%s",
+						  dl->dir, vgname);
+					break;
+				}
+
+				/* FIXME stat file to see if it's changed */
+				fid = _text_create_text_instance(fmt, NULL, NULL,
+							    NULL);
+				if ((vg = _vg_read_file_name(fid, vgname,
+							     path)))
+					/* FIXME Store creation host in vg */
+					lvmcache_update_vg(vg, 0);
+			}
+
+		if (closedir(d))
+			log_sys_error("closedir", dl->dir);
+	}
+
+	return 1;
+}
+
+const char *vgname_from_mda(const struct format_type *fmt,
+			    struct device_area *dev_area, struct id *vgid,
+			    uint32_t *vgstatus, char **creation_host,
+			    uint64_t *mda_free_sectors)
+{
+	struct raw_locn *rlocn;
+	struct mda_header *mdah;
+	uint32_t wrap = 0;
+	const char *vgname = NULL;
+	unsigned int len = 0;
+	char buf[NAME_LEN + 1] __attribute((aligned(8)));
+	char uuid[64] __attribute((aligned(8)));
+	uint64_t buffer_size, current_usage;
+
+	if (mda_free_sectors)
+		*mda_free_sectors = ((dev_area->size - MDA_HEADER_SIZE) / 2) >> SECTOR_SHIFT;
+
+	if (!dev_open(dev_area->dev))
+		return_NULL;
+
+	if (!(mdah = _raw_read_mda_header(fmt, dev_area)))
+		goto_out;
+
+	/* FIXME Cope with returning a list */
+	rlocn = mdah->raw_locns;
+
+	/* Do quick check for a vgname */
+	if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
+		      NAME_LEN, buf))
+		goto_out;
+
+	while (buf[len] && !isspace(buf[len]) && buf[len] != '{' &&
+	       len < (NAME_LEN - 1))
+		len++;
+
+	buf[len] = '\0';
+
+	/* Ignore this entry if the characters aren't permissible */
+	if (!validate_name(buf))
+		goto_out;
+
+	/* We found a VG - now check the metadata */
+	if (rlocn->offset + rlocn->size > mdah->size)
+		wrap = (uint32_t) ((rlocn->offset + rlocn->size) - mdah->size);
+
+	if (wrap > rlocn->offset) {
+		log_error("%s: metadata too large for circular buffer",
+			  dev_name(dev_area->dev));
+		goto out;
+	}
+
+	/* FIXME 64-bit */
+	if (!(vgname = text_vgname_import(fmt, dev_area->dev,
+					  (off_t) (dev_area->start +
+						   rlocn->offset),
+					  (uint32_t) (rlocn->size - wrap),
+					  (off_t) (dev_area->start +
+						   MDA_HEADER_SIZE),
+					  wrap, calc_crc, rlocn->checksum,
+					  vgid, vgstatus, creation_host)))
+		goto_out;
+
+	/* Ignore this entry if the characters aren't permissible */
+	if (!validate_name(vgname)) {
+		vgname = NULL;
+		goto_out;
+	}
+
+	if (!id_write_format(vgid, uuid, sizeof(uuid))) {
+		vgname = NULL;
+		goto_out;
+	}
+
+	log_debug("%s: Found metadata at %" PRIu64 " size %" PRIu64
+		  " (in area at %" PRIu64 " size %" PRIu64
+		  ") for %s (%s)",
+		  dev_name(dev_area->dev), dev_area->start + rlocn->offset,
+		  rlocn->size, dev_area->start, dev_area->size, vgname, uuid);
+
+	if (mda_free_sectors) {
+		current_usage = (rlocn->size + SECTOR_SIZE - UINT64_C(1)) -
+				 (rlocn->size + SECTOR_SIZE - UINT64_C(1)) % SECTOR_SIZE;
+		buffer_size = mdah->size - MDA_HEADER_SIZE;
+
+		if (current_usage * 2 >= buffer_size)
+			*mda_free_sectors = UINT64_C(0);
+		else
+			*mda_free_sectors = ((buffer_size - 2 * current_usage) / 2) >> SECTOR_SHIFT;
+	}
+
+      out:
+	if (!dev_close(dev_area->dev))
+		stack;
+
+	return vgname;
+}
+
+static int _scan_raw(const struct format_type *fmt)
+{
+	struct raw_list *rl;
+	struct dm_list *raw_list;
+	const char *vgname;
+	struct volume_group *vg;
+	struct format_instance fid;
+	struct id vgid;
+	uint32_t vgstatus;
+
+	raw_list = &((struct mda_lists *) fmt->private)->raws;
+
+	fid.fmt = fmt;
+	dm_list_init(&fid.metadata_areas);
+
+	dm_list_iterate_items(rl, raw_list) {
+		/* FIXME We're reading mdah twice here... */
+		if ((vgname = vgname_from_mda(fmt, &rl->dev_area, &vgid, &vgstatus,
+					      NULL, NULL))) {
+			if ((vg = _vg_read_raw_area(&fid, vgname,
+						    &rl->dev_area, 0)))
+				lvmcache_update_vg(vg, 0);
+		}
+	}
+
+	return 1;
+}
+
+static int _text_scan(const struct format_type *fmt)
+{
+	return (_scan_file(fmt) & _scan_raw(fmt));
+}
+
+/* For orphan, creates new mdas according to policy.
+   Always have an mda between end-of-label and pe_align() boundary */
+static int _mda_setup(const struct format_type *fmt,
+		      uint64_t pe_start, uint64_t pe_end,
+		      int pvmetadatacopies,
+		      uint64_t pvmetadatasize, struct dm_list *mdas,
+		      struct physical_volume *pv,
+		      struct volume_group *vg __attribute((unused)))
+{
+	uint64_t mda_adjustment, disk_size, alignment;
+	uint64_t start1, mda_size1;	/* First area - start of disk */
+	uint64_t start2, mda_size2;	/* Second area - end of disk */
+	uint64_t wipe_size = 8 << SECTOR_SHIFT;
+	size_t pagesize = lvm_getpagesize();
+
+	if (!pvmetadatacopies)
+		return 1;
+
+	alignment = pe_align(pv) << SECTOR_SHIFT;
+	disk_size = pv->size << SECTOR_SHIFT;
+	pe_start <<= SECTOR_SHIFT;
+	pe_end <<= SECTOR_SHIFT;
+
+	if (pe_end > disk_size) {
+		log_error("Physical extents end beyond end of device %s!",
+			  pv_dev_name(pv));
+		return 0;
+	}
+
+	/* Requested metadatasize */
+	mda_size1 = pvmetadatasize << SECTOR_SHIFT;
+
+	/* Place mda straight after label area at start of disk */
+	start1 = LABEL_SCAN_SIZE;
+
+	/* Unless the space available is tiny, round to PAGE_SIZE boundary */
+	if ((!pe_start && !pe_end) ||
+	    ((pe_start > start1) && (pe_start - start1 >= MDA_SIZE_MIN))) {
+		mda_adjustment = start1 % pagesize;
+		if (mda_adjustment)
+			start1 += (pagesize - mda_adjustment);
+	}
+
+	/* Ensure it's not going to be bigger than the disk! */
+	if (start1 + mda_size1 > disk_size) {
+		log_warn("WARNING: metadata area fills disk leaving no "
+			 "space for data on %s.", pv_dev_name(pv));
+		/* Leave some free space for rounding */
+		/* Avoid empty data area as could cause tools problems */
+		mda_size1 = disk_size - start1 - alignment * 2;
+		/* Only have 1 mda in this case */
+		pvmetadatacopies = 1;
+	}
+
+	/* Round up to pe_align() boundary */
+	mda_adjustment = (mda_size1 + start1) % alignment;
+	if (mda_adjustment)
+		mda_size1 += (alignment - mda_adjustment);
+
+	/* If we already have PEs, avoid overlap */
+	if (pe_start || pe_end) {
+		if (pe_start <= start1)
+			mda_size1 = 0;
+		else if (start1 + mda_size1 > pe_start)
+			mda_size1 = pe_start - start1;
+	}
+
+	/* FIXME If creating new mdas, wipe them! */
+	if (mda_size1) {
+		if (!add_mda(fmt, fmt->cmd->mem, mdas, pv->dev, start1,
+			     mda_size1))
+			return 0;
+
+		if (!dev_set((struct device *) pv->dev, start1,
+			     (size_t) (mda_size1 >
+				       wipe_size ? : mda_size1), 0)) {
+			log_error("Failed to wipe new metadata area");
+			return 0;
+		}
+
+		if (pvmetadatacopies == 1)
+			return 1;
+	} else
+		start1 = 0;
+
+	/* A second copy at end of disk */
+	mda_size2 = pvmetadatasize << SECTOR_SHIFT;
+
+	/* Ensure it's not going to be bigger than the disk! */
+	if (mda_size2 > disk_size)
+		mda_size2 = disk_size - start1 - mda_size1;
+
+	mda_adjustment = (disk_size - mda_size2) % alignment;
+	if (mda_adjustment)
+		mda_size2 += mda_adjustment;
+
+	start2 = disk_size - mda_size2;
+
+	/* If we already have PEs, avoid overlap */
+	if (pe_start || pe_end) {
+		if (start2 < pe_end) {
+			mda_size2 -= (pe_end - start2);
+			start2 = pe_end;
+		}
+	}
+
+	/* If we already have a first mda, avoid overlap */
+	if (mda_size1) {
+		if (start2 < start1 + mda_size1) {
+			mda_size2 -= (start1 + mda_size1 - start2);
+			start2 = start1 + mda_size1;
+		}
+		/* No room for any PEs here now! */
+	}
+
+	if (mda_size2) {
+		if (!add_mda(fmt, fmt->cmd->mem, mdas, pv->dev, start2,
+			     mda_size2)) return 0;
+		if (!dev_set(pv->dev, start2,
+			     (size_t) (mda_size1 >
+				       wipe_size ? : mda_size1), 0)) {
+			log_error("Failed to wipe new metadata area");
+			return 0;
+		}
+	} else
+		return 0;
+
+	return 1;
+}
+
+/* Only for orphans */
+/* Set label_sector to -1 if rewriting existing label into same sector */
+static int _text_pv_write(const struct format_type *fmt, struct physical_volume *pv,
+		     struct dm_list *mdas, int64_t label_sector)
+{
+	struct label *label;
+	struct lvmcache_info *info;
+	struct mda_context *mdac;
+	struct metadata_area *mda;
+	char buf[MDA_HEADER_SIZE] __attribute((aligned(8)));
+	struct mda_header *mdah = (struct mda_header *) buf;
+	uint64_t adjustment;
+
+	/* FIXME Test mode don't update cache? */
+
+	if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
+				  FMT_TEXT_ORPHAN_VG_NAME, NULL, 0)))
+		return_0;
+	label = info->label;
+
+	if (label_sector != -1)
+		label->sector = label_sector;
+
+	info->device_size = pv->size << SECTOR_SHIFT;
+	info->fmt = fmt;
+
+	/* If mdas supplied, use them regardless of existing ones, */
+	/* otherwise retain existing ones */
+	if (mdas) {
+		if (info->mdas.n)
+			del_mdas(&info->mdas);
+		else
+			dm_list_init(&info->mdas);
+		dm_list_iterate_items(mda, mdas) {
+			mdac = mda->metadata_locn;
+			log_debug("Creating metadata area on %s at sector %"
+				  PRIu64 " size %" PRIu64 " sectors",
+				  dev_name(mdac->area.dev),
+				  mdac->area.start >> SECTOR_SHIFT,
+				  mdac->area.size >> SECTOR_SHIFT);
+			add_mda(fmt, NULL, &info->mdas, mdac->area.dev,
+				mdac->area.start, mdac->area.size);
+		}
+		/* FIXME Temporary until mda creation supported by tools */
+	} else if (!info->mdas.n) {
+		dm_list_init(&info->mdas);
+	}
+
+	if (info->das.n)
+		del_das(&info->das);
+	else
+		dm_list_init(&info->das);
+
+	/* Set pe_start to first aligned sector after any metadata
+	 * areas that begin before pe_start */
+	pv->pe_start = pe_align(pv);
+	dm_list_iterate_items(mda, &info->mdas) {
+		mdac = (struct mda_context *) mda->metadata_locn;
+		if (pv->dev == mdac->area.dev &&
+		    (mdac->area.start <= (pv->pe_start << SECTOR_SHIFT)) &&
+		    (mdac->area.start + mdac->area.size >
+		     (pv->pe_start << SECTOR_SHIFT))) {
+			pv->pe_start = (mdac->area.start + mdac->area.size)
+			    >> SECTOR_SHIFT;
+			adjustment = pv->pe_start % pe_align(pv);
+			if (adjustment)
+				pv->pe_start += (pe_align(pv) - adjustment);
+		}
+	}
+	if (!add_da
+	    (NULL, &info->das, pv->pe_start << SECTOR_SHIFT, UINT64_C(0)))
+		return_0;
+
+	if (!dev_open(pv->dev))
+		return_0;
+
+	dm_list_iterate_items(mda, &info->mdas) {
+		mdac = mda->metadata_locn;
+		memset(&buf, 0, sizeof(buf));
+		mdah->size = mdac->area.size;
+		if (!_raw_write_mda_header(fmt, mdac->area.dev,
+					   mdac->area.start, mdah)) {
+			if (!dev_close(pv->dev))
+				stack;
+			return_0;
+		}
+	}
+
+	if (!label_write(pv->dev, label)) {
+		dev_close(pv->dev);
+		return_0;
+	}
+
+	if (!dev_close(pv->dev))
+		return_0;
+
+	return 1;
+}
+
+static int _add_raw(struct dm_list *raw_list, struct device_area *dev_area)
+{
+	struct raw_list *rl;
+
+	/* Already present? */
+	dm_list_iterate_items(rl, raw_list) {
+		/* FIXME Check size/overlap consistency too */
+		if (rl->dev_area.dev == dev_area->dev &&
+		    rl->dev_area.start == dev_area->start)
+			return 1;
+	}
+
+	if (!(rl = dm_malloc(sizeof(struct raw_list)))) {
+		log_error("_add_raw allocation failed");
+		return 0;
+	}
+	memcpy(&rl->dev_area, dev_area, sizeof(*dev_area));
+	dm_list_add(raw_list, &rl->list);
+
+	return 1;
+}
+
+static int _get_pv_if_in_vg(struct lvmcache_info *info,
+			    struct physical_volume *pv)
+{
+	if (info->vginfo && info->vginfo->vgname &&
+	    !is_orphan_vg(info->vginfo->vgname) &&
+	    get_pv_from_vg_by_id(info->fmt, info->vginfo->vgname,
+				 info->vginfo->vgid, info->dev->pvid, pv))
+		return 1;
+
+	return 0;
+}
+
+static int _populate_pv_fields(struct lvmcache_info *info,
+			       struct physical_volume *pv)
+{
+	struct data_area_list *da;
+
+	/* Have we already cached vgname? */
+	if (_get_pv_if_in_vg(info, pv))
+		return 1;
+
+	/* Perform full scan (just the first time) and try again */
+	if (!memlock() && !full_scan_done()) {
+		lvmcache_label_scan(info->fmt->cmd, 2);
+
+		if (_get_pv_if_in_vg(info, pv))
+			return 1;
+	}
+
+	/* Orphan */
+	pv->dev = info->dev;
+	pv->fmt = info->fmt;
+	pv->size = info->device_size >> SECTOR_SHIFT;
+	pv->vg_name = FMT_TEXT_ORPHAN_VG_NAME;
+	memcpy(&pv->id, &info->dev->pvid, sizeof(pv->id));
+
+	/* Currently only support exactly one data area */
+	if (dm_list_size(&info->das) != 1) {
+		log_error("Must be exactly one data area (found %d) on PV %s",
+			  dm_list_size(&info->das), dev_name(info->dev));
+		return 0;
+	}
+
+	dm_list_iterate_items(da, &info->das)
+		pv->pe_start = da->disk_locn.offset >> SECTOR_SHIFT;
+
+	return 1;
+}
+
+static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
+		    struct physical_volume *pv, struct dm_list *mdas)
+{
+	struct label *label;
+	struct device *dev;
+	struct lvmcache_info *info;
+	struct metadata_area *mda, *mda_new;
+	struct mda_context *mdac, *mdac_new;
+
+	if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter)))
+		return_0;
+
+	if (!(label_read(dev, &label, UINT64_C(0))))
+		return_0;
+	info = (struct lvmcache_info *) label->info;
+
+	if (!_populate_pv_fields(info, pv))
+		return 0;
+
+	if (!mdas)
+		return 1;
+
+	/* Add copy of mdas to supplied list */
+	dm_list_iterate_items(mda, &info->mdas) {
+		mdac = (struct mda_context *) mda->metadata_locn;
+		if (!(mda_new = dm_pool_alloc(fmt->cmd->mem, sizeof(*mda_new)))) {
+			log_error("metadata_area allocation failed");
+			return 0;
+		}
+		if (!(mdac_new = dm_pool_alloc(fmt->cmd->mem, sizeof(*mdac_new)))) {
+			log_error("metadata_area allocation failed");
+			return 0;
+		}
+		memcpy(mda_new, mda, sizeof(*mda));
+		memcpy(mdac_new, mdac, sizeof(*mdac));
+		mda_new->metadata_locn = mdac_new;
+		dm_list_add(mdas, &mda_new->list);
+	}
+
+	return 1;
+}
+
+static void _text_destroy_instance(struct format_instance *fid __attribute((unused)))
+{
+	return;
+}
+
+static void _free_dirs(struct dm_list *dir_list)
+{
+	struct dm_list *dl, *tmp;
+
+	dm_list_iterate_safe(dl, tmp, dir_list) {
+		dm_list_del(dl);
+		dm_free(dl);
+	}
+}
+
+static void _free_raws(struct dm_list *raw_list)
+{
+	struct dm_list *rl, *tmp;
+
+	dm_list_iterate_safe(rl, tmp, raw_list) {
+		dm_list_del(rl);
+		dm_free(rl);
+	}
+}
+
+static void _text_destroy(const struct format_type *fmt)
+{
+	if (fmt->private) {
+		_free_dirs(&((struct mda_lists *) fmt->private)->dirs);
+		_free_raws(&((struct mda_lists *) fmt->private)->raws);
+		dm_free(fmt->private);
+	}
+
+	dm_free((void *)fmt);
+}
+
+static struct metadata_area_ops _metadata_text_file_ops = {
+	.vg_read = _vg_read_file,
+	.vg_read_precommit = _vg_read_precommit_file,
+	.vg_write = _vg_write_file,
+	.vg_remove = _vg_remove_file,
+	.vg_commit = _vg_commit_file
+};
+
+static struct metadata_area_ops _metadata_text_file_backup_ops = {
+	.vg_read = _vg_read_file,
+	.vg_write = _vg_write_file,
+	.vg_remove = _vg_remove_file,
+	.vg_commit = _vg_commit_file_backup
+};
+
+static struct metadata_area_ops _metadata_text_raw_ops = {
+	.vg_read = _vg_read_raw,
+	.vg_read_precommit = _vg_read_precommit_raw,
+	.vg_write = _vg_write_raw,
+	.vg_remove = _vg_remove_raw,
+	.vg_precommit = _vg_precommit_raw,
+	.vg_commit = _vg_commit_raw,
+	.vg_revert = _vg_revert_raw,
+	.mda_free_sectors = _mda_free_sectors_raw,
+	.mda_in_vg = _mda_in_vg_raw,
+	.pv_analyze_mda = _pv_analyze_mda_raw,
+};
+
+/* pvmetadatasize in sectors */
+static int _text_pv_setup(const struct format_type *fmt,
+		     uint64_t pe_start, uint32_t extent_count,
+		     uint32_t extent_size,
+		     int pvmetadatacopies,
+		     uint64_t pvmetadatasize, struct dm_list *mdas,
+		     struct physical_volume *pv, struct volume_group *vg)
+{
+	struct metadata_area *mda, *mda_new, *mda2;
+	struct mda_context *mdac, *mdac_new, *mdac2;
+	struct dm_list *pvmdas;
+	struct lvmcache_info *info;
+	int found;
+	uint64_t pe_end = 0;
+	unsigned mda_count = 0;
+	uint64_t mda_size2 = 0;
+	uint64_t pe_count;
+
+	/* FIXME Cope with pvchange */
+	/* FIXME Merge code with _text_create_text_instance */
+
+	/* If new vg, add any further mdas on this PV to the fid's mda list */
+	if (vg) {
+		/* Iterate through all mdas on this PV */
+		if ((info = info_from_pvid(pv->dev->pvid, 0))) {
+			pvmdas = &info->mdas;
+			dm_list_iterate_items(mda, pvmdas) {
+				mda_count++;
+				mdac =
+				    (struct mda_context *) mda->metadata_locn;
+
+				/* FIXME Check it isn't already in use */
+
+				/* Reduce usable device size */
+				if (mda_count > 1)
+					mda_size2 = mdac->area.size >> SECTOR_SHIFT;
+
+				/* Ensure it isn't already on list */
+				found = 0;
+				dm_list_iterate_items(mda2, mdas) {
+					if (mda2->ops !=
+					    &_metadata_text_raw_ops) continue;
+					mdac2 =
+					    (struct mda_context *)
+					    mda2->metadata_locn;
+					if (!memcmp
+					    (&mdac2->area, &mdac->area,
+					     sizeof(mdac->area))) {
+						found = 1;
+						break;
+					}
+				}
+				if (found)
+					continue;
+
+				if (!(mda_new = dm_pool_alloc(fmt->cmd->mem,
+							   sizeof(*mda_new))))
+					return_0;
+
+				if (!(mdac_new = dm_pool_alloc(fmt->cmd->mem,
+							    sizeof(*mdac_new))))
+					return_0;
+				/* FIXME multiple dev_areas inside area */
+				memcpy(mda_new, mda, sizeof(*mda));
+				memcpy(mdac_new, mdac, sizeof(*mdac));
+				mda_new->metadata_locn = mdac_new;
+				dm_list_add(mdas, &mda_new->list);
+			}
+		}
+
+		/* FIXME Cope with genuine pe_count 0 */
+
+		/* If missing, estimate pv->size from file-based metadata */
+		if (!pv->size && pv->pe_count)
+			pv->size = pv->pe_count * (uint64_t) vg->extent_size +
+				   pv->pe_start + mda_size2;
+
+		/* Recalculate number of extents that will fit */
+		if (!pv->pe_count) {
+			pe_count = (pv->size - pv->pe_start - mda_size2) /
+				   vg->extent_size;
+			if (pe_count > UINT32_MAX) {
+				log_error("PV %s too large for extent size %s.",
+					  pv_dev_name(pv),
+					  display_size(vg->cmd, (uint64_t) vg->extent_size));
+				return 0;
+			}
+			pv->pe_count = (uint32_t) pe_count;
+		}
+
+		/* Unlike LVM1, we don't store this outside a VG */
+		/* FIXME Default from config file? vgextend cmdline flag? */
+		pv->status |= ALLOCATABLE_PV;
+	} else {
+		if (extent_count)
+			pe_end = pe_start + extent_count * extent_size - 1;
+		if (!_mda_setup(fmt, pe_start, pe_end, pvmetadatacopies,
+				pvmetadatasize, mdas, pv, vg))
+			return_0;
+	}
+
+	return 1;
+}
+
+/* NULL vgname means use only the supplied context e.g. an archive file */
+static struct format_instance *_text_create_text_instance(const struct format_type
+						     *fmt, const char *vgname,
+						     const char *vgid,
+						     void *context)
+{
+	struct format_instance *fid;
+	struct text_fid_context *fidtc;
+	struct metadata_area *mda, *mda_new;
+	struct mda_context *mdac, *mdac_new;
+	struct dir_list *dl;
+	struct raw_list *rl;
+	struct dm_list *dir_list, *raw_list, *mdas;
+	char path[PATH_MAX];
+	struct lvmcache_vginfo *vginfo;
+	struct lvmcache_info *info;
+
+	if (!(fid = dm_pool_alloc(fmt->cmd->mem, sizeof(*fid)))) {
+		log_error("Couldn't allocate format instance object.");
+		return NULL;
+	}
+
+	if (!(fidtc = (struct text_fid_context *)
+			dm_pool_zalloc(fmt->cmd->mem,sizeof(*fidtc)))) {
+		log_error("Couldn't allocate text_fid_context.");
+		return NULL;
+	}
+
+	fidtc->raw_metadata_buf = NULL;
+	fid->private = (void *) fidtc;
+
+	fid->fmt = fmt;
+	dm_list_init(&fid->metadata_areas);
+
+	if (!vgname) {
+		if (!(mda = dm_pool_alloc(fmt->cmd->mem, sizeof(*mda))))
+			return_NULL;
+		mda->ops = &_metadata_text_file_backup_ops;
+		mda->metadata_locn = context;
+		dm_list_add(&fid->metadata_areas, &mda->list);
+	} else {
+		dir_list = &((struct mda_lists *) fmt->private)->dirs;
+
+		dm_list_iterate_items(dl, dir_list) {
+			if (dm_snprintf(path, PATH_MAX, "%s/%s",
+					 dl->dir, vgname) < 0) {
+				log_error("Name too long %s/%s", dl->dir,
+					  vgname);
+				return NULL;
+			}
+
+			context = create_text_context(fmt->cmd, path, NULL);
+			if (!(mda = dm_pool_alloc(fmt->cmd->mem, sizeof(*mda))))
+				return_NULL;
+			mda->ops = &_metadata_text_file_ops;
+			mda->metadata_locn = context;
+			dm_list_add(&fid->metadata_areas, &mda->list);
+		}
+
+		raw_list = &((struct mda_lists *) fmt->private)->raws;
+
+		dm_list_iterate_items(rl, raw_list) {
+			/* FIXME Cache this; rescan below if some missing */
+			if (!_raw_holds_vgname(fid, &rl->dev_area, vgname))
+				continue;
+
+			if (!(mda = dm_pool_alloc(fmt->cmd->mem, sizeof(*mda))))
+				return_NULL;
+
+			if (!(mdac = dm_pool_alloc(fmt->cmd->mem, sizeof(*mdac))))
+				return_NULL;
+			mda->metadata_locn = mdac;
+			/* FIXME Allow multiple dev_areas inside area */
+			memcpy(&mdac->area, &rl->dev_area, sizeof(mdac->area));
+			mda->ops = &_metadata_text_raw_ops;
+			/* FIXME MISTAKE? mda->metadata_locn = context; */
+			dm_list_add(&fid->metadata_areas, &mda->list);
+		}
+
+		/* Scan PVs in VG for any further MDAs */
+		lvmcache_label_scan(fmt->cmd, 0);
+		if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
+			goto_out;
+		dm_list_iterate_items(info, &vginfo->infos) {
+			mdas = &info->mdas;
+			dm_list_iterate_items(mda, mdas) {
+				mdac =
+				    (struct mda_context *) mda->metadata_locn;
+
+				/* FIXME Check it holds this VG */
+				if (!(mda_new = dm_pool_alloc(fmt->cmd->mem,
+							   sizeof(*mda_new))))
+					return_NULL;
+
+				if (!(mdac_new = dm_pool_alloc(fmt->cmd->mem,
+							    sizeof(*mdac_new))))
+					return_NULL;
+				/* FIXME multiple dev_areas inside area */
+				memcpy(mda_new, mda, sizeof(*mda));
+				memcpy(mdac_new, mdac, sizeof(*mdac));
+				mda_new->metadata_locn = mdac_new;
+				dm_list_add(&fid->metadata_areas, &mda_new->list);
+			}
+		}
+		/* FIXME Check raw metadata area count - rescan if required */
+	}
+
+      out:
+	return fid;
+}
+
+void *create_text_context(struct cmd_context *cmd, const char *path,
+			  const char *desc)
+{
+	struct text_context *tc;
+	char *tmp;
+
+	if ((tmp = strstr(path, ".tmp")) && (tmp == path + strlen(path) - 4)) {
+		log_error("%s: Volume group filename may not end in .tmp",
+			  path);
+		return NULL;
+	}
+
+	if (!(tc = dm_pool_alloc(cmd->mem, sizeof(*tc))))
+		return_NULL;
+
+	if (!(tc->path_live = dm_pool_strdup(cmd->mem, path)))
+		goto_bad;
+
+	if (!(tc->path_edit = dm_pool_alloc(cmd->mem, strlen(path) + 5)))
+		goto_bad;
+
+	sprintf(tc->path_edit, "%s.tmp", path);
+
+	if (!desc)
+		desc = "";
+
+	if (!(tc->desc = dm_pool_strdup(cmd->mem, desc)))
+		goto_bad;
+
+	return (void *) tc;
+
+      bad:
+	dm_pool_free(cmd->mem, tc);
+
+	log_err("Couldn't allocate text format context object.");
+	return NULL;
+}
+
+static struct format_handler _text_handler = {
+	.scan = _text_scan,
+	.pv_read = _text_pv_read,
+	.pv_setup = _text_pv_setup,
+	.pv_write = _text_pv_write,
+	.vg_setup = _text_vg_setup,
+	.lv_setup = _text_lv_setup,
+	.create_instance = _text_create_text_instance,
+	.destroy_instance = _text_destroy_instance,
+	.destroy = _text_destroy
+};
+
+static int _add_dir(const char *dir, struct dm_list *dir_list)
+{
+	struct dir_list *dl;
+
+	if (dm_create_dir(dir)) {
+		if (!(dl = dm_malloc(sizeof(struct dm_list) + strlen(dir) + 1))) {
+			log_error("_add_dir allocation failed");
+			return 0;
+		}
+		log_very_verbose("Adding text format metadata dir: %s", dir);
+		strcpy(dl->dir, dir);
+		dm_list_add(dir_list, &dl->list);
+		return 1;
+	}
+
+	return 0;
+}
+
+static int _get_config_disk_area(struct cmd_context *cmd,
+				 struct config_node *cn, struct dm_list *raw_list)
+{
+	struct device_area dev_area;
+	char *id_str;
+	struct id id;
+
+	if (!(cn = cn->child)) {
+		log_error("Empty metadata disk_area section of config file");
+		return 0;
+	}
+
+	if (!get_config_uint64(cn, "start_sector", &dev_area.start)) {
+		log_error("Missing start_sector in metadata disk_area section "
+			  "of config file");
+		return 0;
+	}
+	dev_area.start <<= SECTOR_SHIFT;
+
+	if (!get_config_uint64(cn, "size", &dev_area.size)) {
+		log_error("Missing size in metadata disk_area section "
+			  "of config file");
+		return 0;
+	}
+	dev_area.size <<= SECTOR_SHIFT;
+
+	if (!get_config_str(cn, "id", &id_str)) {
+		log_error("Missing uuid in metadata disk_area section "
+			  "of config file");
+		return 0;
+	}
+
+	if (!id_read_format(&id, id_str)) {
+		log_error("Invalid uuid in metadata disk_area section "
+			  "of config file: %s", id_str);
+		return 0;
+	}
+
+	if (!(dev_area.dev = device_from_pvid(cmd, &id))) {
+		char buffer[64] __attribute((aligned(8)));
+
+		if (!id_write_format(&id, buffer, sizeof(buffer)))
+			log_err("Couldn't find device.");
+		else
+			log_err("Couldn't find device with uuid '%s'.", buffer);
+
+		return 0;
+	}
+
+	return _add_raw(raw_list, &dev_area);
+}
+
+struct format_type *create_text_format(struct cmd_context *cmd)
+{
+	struct format_type *fmt;
+	struct config_node *cn;
+	struct config_value *cv;
+	struct mda_lists *mda_lists;
+
+	if (!(fmt = dm_malloc(sizeof(*fmt))))
+		return_NULL;
+
+	fmt->cmd = cmd;
+	fmt->ops = &_text_handler;
+	fmt->name = FMT_TEXT_NAME;
+	fmt->alias = FMT_TEXT_ALIAS;
+	fmt->orphan_vg_name = ORPHAN_VG_NAME(FMT_TEXT_NAME);
+	fmt->features = FMT_SEGMENTS | FMT_MDAS | FMT_TAGS | FMT_PRECOMMIT |
+			FMT_UNLIMITED_VOLS | FMT_RESIZE_PV |
+			FMT_UNLIMITED_STRIPESIZE;
+
+	if (!(mda_lists = dm_malloc(sizeof(struct mda_lists)))) {
+		log_error("Failed to allocate dir_list");
+		dm_free(fmt);
+		return NULL;
+	}
+
+	dm_list_init(&mda_lists->dirs);
+	dm_list_init(&mda_lists->raws);
+	mda_lists->file_ops = &_metadata_text_file_ops;
+	mda_lists->raw_ops = &_metadata_text_raw_ops;
+	fmt->private = (void *) mda_lists;
+
+	if (!(fmt->labeller = text_labeller_create(fmt))) {
+		log_error("Couldn't create text label handler.");
+		dm_free(fmt);
+		return NULL;
+	}
+
+	if (!(label_register_handler(FMT_TEXT_NAME, fmt->labeller))) {
+		log_error("Couldn't register text label handler.");
+		dm_free(fmt);
+		return NULL;
+	}
+
+	if ((cn = find_config_tree_node(cmd, "metadata/dirs"))) {
+		for (cv = cn->v; cv; cv = cv->next) {
+			if (cv->type != CFG_STRING) {
+				log_error("Invalid string in config file: "
+					  "metadata/dirs");
+				goto err;
+			}
+
+			if (!_add_dir(cv->v.str, &mda_lists->dirs)) {
+				log_error("Failed to add %s to internal device "
+					  "cache", cv->v.str);
+				goto err;
+			}
+		}
+	}
+
+	if ((cn = find_config_tree_node(cmd, "metadata/disk_areas"))) {
+		for (cn = cn->child; cn; cn = cn->sib) {
+			if (!_get_config_disk_area(cmd, cn, &mda_lists->raws))
+				goto err;
+		}
+	}
+
+	log_very_verbose("Initialised format: %s", fmt->name);
+
+	return fmt;
+
+      err:
+	_free_dirs(&mda_lists->dirs);
+
+	dm_free(fmt);
+	return NULL;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/format_text/format-text.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format_text/format-text.h
diff -N src/external/gpl2/lvm2tools/dist/lib/format_text/format-text.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format_text/format-text.h	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,69 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_FORMAT_TEXT_H
+#define _LVM_FORMAT_TEXT_H
+
+#include "lvm-types.h"
+#include "metadata.h"
+
+#define FMT_TEXT_NAME "lvm2"
+#define FMT_TEXT_ALIAS "text"
+#define FMT_TEXT_ORPHAN_VG_NAME ORPHAN_VG_NAME(FMT_TEXT_NAME)
+
+/*
+ * Archives a vg config.  'retain_days' is the minimum number of
+ * days that an archive file must be held for.  'min_archives' is
+ * the minimum number of archives required to be kept for each
+ * volume group.
+ */
+int archive_vg(struct volume_group *vg,
+	       const char *dir,
+	       const char *desc, uint32_t retain_days, uint32_t min_archive);
+
+/*
+ * Displays a list of vg backups in a particular archive directory.
+ */
+int archive_list(struct cmd_context *cmd, const char *dir, const char *vgname);
+int archive_list_file(struct cmd_context *cmd, const char *file);
+int backup_list(struct cmd_context *cmd, const char *dir, const char *vgname);
+
+/*
+ * The text format can read and write a volume_group to a file.
+ */
+struct format_type *create_text_format(struct cmd_context *cmd);
+void *create_text_context(struct cmd_context *cmd, const char *path,
+			  const char *desc);
+
+struct labeller *text_labeller_create(const struct format_type *fmt);
+
+int pvhdr_read(struct device *dev, char *buf);
+
+int add_da(struct dm_pool *mem, struct dm_list *das,
+	   uint64_t start, uint64_t size);
+void del_das(struct dm_list *das);
+
+int add_mda(const struct format_type *fmt, struct dm_pool *mem, struct dm_list *mdas,
+	    struct device *dev, uint64_t start, uint64_t size);
+void del_mdas(struct dm_list *mdas);
+
+const char *vgname_from_mda(const struct format_type *fmt,
+			    struct device_area *dev_area, struct id *vgid,
+			    uint32_t *vgstatus, char **creation_host,
+			    uint64_t *mda_free_sectors);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/format_text/import-export.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format_text/import-export.h
diff -N src/external/gpl2/lvm2tools/dist/lib/format_text/import-export.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format_text/import-export.h	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,89 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_TEXT_IMPORT_EXPORT_H
+#define _LVM_TEXT_IMPORT_EXPORT_H
+
+#include "config.h"
+#include "lvm-types.h"
+#include "metadata.h"
+
+#include <stdio.h>
+
+/*
+ * Constants to identify files this code can parse.
+ */
+#define CONTENTS_FIELD "contents"
+#define CONTENTS_VALUE "Text Format Volume Group"
+
+#define FORMAT_VERSION_FIELD "version"
+#define FORMAT_VERSION_VALUE 1
+
+/*
+ * VGs, PVs and LVs all have status bitsets, we gather together
+ * common code for reading and writing them.
+ */
+enum {
+	COMPATIBLE_FLAG = 0x0,
+	VG_FLAGS,
+	PV_FLAGS,
+	LV_FLAGS,
+	STATUS_FLAG = 0x8,
+};
+
+struct text_vg_version_ops {
+	int (*check_version) (struct config_tree * cf);
+	struct volume_group *(*read_vg) (struct format_instance * fid,
+					 struct config_tree * cf);
+	void (*read_desc) (struct dm_pool * mem, struct config_tree * cf,
+			   time_t *when, char **desc);
+	const char *(*read_vgname) (const struct format_type *fmt,
+				    struct config_tree *cft,
+				    struct id *vgid, uint32_t *vgstatus,
+				    char **creation_host);
+};
+
+struct text_vg_version_ops *text_vg_vsn1_init(void);
+
+int print_flags(uint32_t status, int type, char *buffer, size_t size);
+int read_flags(uint32_t *status, int type, struct config_value *cv);
+
+int print_tags(struct dm_list *tags, char *buffer, size_t size);
+int read_tags(struct dm_pool *mem, struct dm_list *tags, struct config_value *cv);
+
+int text_vg_export_file(struct volume_group *vg, const char *desc, FILE *fp);
+int text_vg_export_raw(struct volume_group *vg, const char *desc, char **buf);
+struct volume_group *text_vg_import_file(struct format_instance *fid,
+					 const char *file,
+					 time_t *when, char **desc);
+struct volume_group *text_vg_import_fd(struct format_instance *fid,
+				       const char *file,
+				       struct device *dev,
+				       off_t offset, uint32_t size,
+				       off_t offset2, uint32_t size2,
+				       checksum_fn_t checksum_fn,
+				       uint32_t checksum,
+				       time_t *when, char **desc);
+const char *text_vgname_import(const struct format_type *fmt,
+			       struct device *dev,
+                               off_t offset, uint32_t size,
+                               off_t offset2, uint32_t size2,
+                               checksum_fn_t checksum_fn, uint32_t checksum,
+                               struct id *vgid, uint32_t *vgstatus,
+			       char **creation_host);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/format_text/import.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format_text/import.c
diff -N src/external/gpl2/lvm2tools/dist/lib/format_text/import.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format_text/import.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,158 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "metadata.h"
+#include "import-export.h"
+#include "display.h"
+#include "toolcontext.h"
+#include "lvmcache.h"
+
+/* FIXME Use tidier inclusion method */
+static struct text_vg_version_ops *(_text_vsn_list[2]);
+
+static int _text_import_initialised = 0;
+
+static void _init_text_import()
+{
+	if (_text_import_initialised)
+		return;
+
+	_text_vsn_list[0] = text_vg_vsn1_init();
+	_text_vsn_list[1] = NULL;
+	_text_import_initialised = 1;
+}
+
+const char *text_vgname_import(const struct format_type *fmt,
+			       struct device *dev,
+			       off_t offset, uint32_t size,
+			       off_t offset2, uint32_t size2,
+			       checksum_fn_t checksum_fn, uint32_t checksum,
+			       struct id *vgid, uint32_t *vgstatus,
+			       char **creation_host)
+{
+	struct config_tree *cft;
+	struct text_vg_version_ops **vsn;
+	const char *vgname = NULL;
+
+	_init_text_import();
+
+	if (!(cft = create_config_tree(NULL, 0)))
+		return_NULL;
+
+	if ((!dev && !read_config_file(cft)) ||
+	    (dev && !read_config_fd(cft, dev, offset, size,
+				    offset2, size2, checksum_fn, checksum)))
+		goto_out;
+
+	/*
+	 * Find a set of version functions that can read this file
+	 */
+	for (vsn = &_text_vsn_list[0]; *vsn; vsn++) {
+		if (!(*vsn)->check_version(cft))
+			continue;
+
+		if (!(vgname = (*vsn)->read_vgname(fmt, cft, vgid, vgstatus,
+						   creation_host)))
+			goto_out;
+
+		break;
+	}
+
+      out:
+	destroy_config_tree(cft);
+	return vgname;
+}
+
+struct volume_group *text_vg_import_fd(struct format_instance *fid,
+				       const char *file,
+				       struct device *dev,
+				       off_t offset, uint32_t size,
+				       off_t offset2, uint32_t size2,
+				       checksum_fn_t checksum_fn,
+				       uint32_t checksum,
+				       time_t *when, char **desc)
+{
+	struct volume_group *vg = NULL;
+	struct config_tree *cft;
+	struct text_vg_version_ops **vsn;
+
+	_init_text_import();
+
+	*desc = NULL;
+	*when = 0;
+
+	if (!(cft = create_config_tree(file, 0)))
+		return_NULL;
+
+	if ((!dev && !read_config_file(cft)) ||
+	    (dev && !read_config_fd(cft, dev, offset, size,
+				    offset2, size2, checksum_fn, checksum))) {
+		log_error("Couldn't read volume group metadata.");
+		goto out;
+	}
+
+	/*
+	 * Find a set of version functions that can read this file
+	 */
+	for (vsn = &_text_vsn_list[0]; *vsn; vsn++) {
+		if (!(*vsn)->check_version(cft))
+			continue;
+
+		if (!(vg = (*vsn)->read_vg(fid, cft)))
+			goto_out;
+
+		(*vsn)->read_desc(fid->fmt->cmd->mem, cft, when, desc);
+		break;
+	}
+
+      out:
+	destroy_config_tree(cft);
+	return vg;
+}
+
+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, NULL, (off_t)0, 0, (off_t)0, 0, NULL, 0,
+				 when, desc);
+}
+
+struct volume_group *import_vg_from_buffer(char *buf,
+                                           struct format_instance *fid)
+{
+	struct volume_group *vg = NULL;
+	struct config_tree *cft;
+	struct text_vg_version_ops **vsn;
+
+	_init_text_import();
+
+	if (!(cft = create_config_tree_from_string(fid->fmt->cmd, buf)))
+		return_NULL;
+
+	for (vsn = &_text_vsn_list[0]; *vsn; vsn++) {
+		if (!(*vsn)->check_version(cft))
+			continue;
+		if (!(vg = (*vsn)->read_vg(fid, cft)))
+			stack;
+		break;
+	}
+
+	destroy_config_tree(cft);
+	return vg;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/format_text/import_vsn1.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format_text/import_vsn1.c
diff -N src/external/gpl2/lvm2tools/dist/lib/format_text/import_vsn1.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format_text/import_vsn1.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,883 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "metadata.h"
+#include "import-export.h"
+#include "display.h"
+#include "toolcontext.h"
+#include "lvmcache.h"
+#include "lv_alloc.h"
+#include "pv_alloc.h"
+#include "segtype.h"
+#include "text_import.h"
+
+typedef int (*section_fn) (struct format_instance * fid, struct dm_pool * mem,
+			   struct volume_group * vg, struct config_node * pvn,
+			   struct config_node * vgn,
+			   struct dm_hash_table * pv_hash);
+
+#define _read_int32(root, path, result) \
+	get_config_uint32(root, path, (uint32_t *) result)
+
+#define _read_uint32(root, path, result) \
+	get_config_uint32(root, path, result)
+
+#define _read_int64(root, path, result) \
+	get_config_uint64(root, path, result)
+
+/*
+ * Logs an attempt to read an invalid format file.
+ */
+static void _invalid_format(const char *str)
+{
+	log_error("Can't process text format file - %s.", str);
+}
+
+/*
+ * Checks that the config file contains vg metadata, and that it
+ * we recognise the version number,
+ */
+static int _check_version(struct config_tree *cft)
+{
+	struct config_node *cn;
+	struct config_value *cv;
+
+	/*
+	 * Check the contents field.
+	 */
+	if (!(cn = find_config_node(cft->root, CONTENTS_FIELD))) {
+		_invalid_format("missing contents field");
+		return 0;
+	}
+
+	cv = cn->v;
+	if (!cv || cv->type != CFG_STRING || strcmp(cv->v.str, CONTENTS_VALUE)) {
+		_invalid_format("unrecognised contents field");
+		return 0;
+	}
+
+	/*
+	 * Check the version number.
+	 */
+	if (!(cn = find_config_node(cft->root, FORMAT_VERSION_FIELD))) {
+		_invalid_format("missing version number");
+		return 0;
+	}
+
+	cv = cn->v;
+	if (!cv || cv->type != CFG_INT || cv->v.i != FORMAT_VERSION_VALUE) {
+		_invalid_format("unrecognised version number");
+		return 0;
+	}
+
+	return 1;
+}
+
+static int _is_converting(struct logical_volume *lv)
+{
+	struct lv_segment *seg;
+
+	if (lv->status & MIRRORED) {
+		seg = first_seg(lv);
+		/* Can't use is_temporary_mirror() because the metadata for
+		 * seg_lv may not be read in and flags may not be set yet. */
+		if (seg_type(seg, 0) == AREA_LV &&
+		    strstr(seg_lv(seg, 0)->name, MIRROR_SYNC_LAYER))
+			return 1;
+	}
+
+	return 0;
+}
+
+static int _read_id(struct id *id, struct config_node *cn, const char *path)
+{
+	struct config_value *cv;
+
+	if (!(cn = find_config_node(cn, path))) {
+		log_error("Couldn't find uuid.");
+		return 0;
+	}
+
+	cv = cn->v;
+	if (!cv || !cv->v.str) {
+		log_error("uuid must be a string.");
+		return 0;
+	}
+
+	if (!id_read_format(id, cv->v.str)) {
+		log_error("Invalid uuid.");
+		return 0;
+	}
+
+	return 1;
+}
+
+static int _read_flag_config(struct config_node *n, uint32_t *status, int type)
+{
+	struct config_node *cn;
+	*status = 0;
+
+	if (!(cn = find_config_node(n, "status"))) {
+		log_error("Could not find status flags.");
+		return 0;
+	}
+
+	if (!(read_flags(status, type | STATUS_FLAG, cn->v))) {
+		log_error("Could not read status flags.");
+		return 0;
+	}
+
+	if ((cn = find_config_node(n, "flags"))) {
+		if (!(read_flags(status, type, cn->v))) {
+			log_error("Could not read flags.");
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+static int _read_pv(struct format_instance *fid, struct dm_pool *mem,
+		    struct volume_group *vg, struct config_node *pvn,
+		    struct config_node *vgn __attribute((unused)),
+		    struct dm_hash_table *pv_hash)
+{
+	struct physical_volume *pv;
+	struct pv_list *pvl;
+	struct config_node *cn;
+	uint64_t size;
+
+	if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl))) ||
+	    !(pvl->pv = dm_pool_zalloc(mem, sizeof(*pvl->pv))))
+		return_0;
+
+	pv = pvl->pv;
+
+	/*
+	 * Add the pv to the pv hash for quick lookup when we read
+	 * the lv segments.
+	 */
+	if (!dm_hash_insert(pv_hash, pvn->key, pv))
+		return_0;
+
+	if (!(pvn = pvn->child)) {
+		log_error("Empty pv section.");
+		return 0;
+	}
+
+	if (!_read_id(&pv->id, pvn, "id")) {
+		log_error("Couldn't read uuid for volume group.");
+		return 0;
+	}
+
+	/*
+	 * Convert the uuid into a device.
+	 */
+	if (!(pv->dev = device_from_pvid(fid->fmt->cmd, &pv->id))) {
+		char buffer[64] __attribute((aligned(8)));
+
+		if (!id_write_format(&pv->id, buffer, sizeof(buffer)))
+			log_error("Couldn't find device.");
+		else
+			log_error("Couldn't find device with uuid '%s'.",
+				  buffer);
+	}
+
+	if (!(pv->vg_name = dm_pool_strdup(mem, vg->name)))
+		return_0;
+
+	memcpy(&pv->vgid, &vg->id, sizeof(vg->id));
+
+	if (!_read_flag_config(pvn, &pv->status, PV_FLAGS)) {
+		log_error("Couldn't read status flags for physical volume.");
+		return 0;
+	}
+
+	if (!pv->dev)
+		pv->status |= MISSING_PV;
+
+	/* Late addition */
+	_read_int64(pvn, "dev_size", &pv->size);
+
+	if (!_read_int64(pvn, "pe_start", &pv->pe_start)) {
+		log_error("Couldn't read extent size for volume group.");
+		return 0;
+	}
+
+	if (!_read_int32(pvn, "pe_count", &pv->pe_count)) {
+		log_error("Couldn't find extent count (pe_count) for "
+			  "physical volume.");
+		return 0;
+	}
+
+	dm_list_init(&pv->tags);
+	dm_list_init(&pv->segments);
+
+	/* Optional tags */
+	if ((cn = find_config_node(pvn, "tags")) &&
+	    !(read_tags(mem, &pv->tags, cn->v))) {
+		log_error("Couldn't read tags for physical volume %s in %s.",
+			  pv_dev_name(pv), vg->name);
+		return 0;
+	}
+
+	/* adjust the volume group. */
+	vg->extent_count += pv->pe_count;
+	vg->free_count += pv->pe_count;
+
+	pv->pe_size = vg->extent_size;
+
+	pv->pe_alloc_count = 0;
+	pv->pe_align = 0;
+	pv->fmt = fid->fmt;
+
+	/* Fix up pv size if missing or impossibly large */
+	if ((!pv->size || pv->size > (1ULL << 62)) && pv->dev) {
+		if (!dev_get_size(pv->dev, &pv->size)) {
+			log_error("%s: Couldn't get size.", pv_dev_name(pv));
+			return 0;
+		}
+		log_verbose("Fixing up missing size (%s) "
+			    "for PV %s", display_size(fid->fmt->cmd, pv->size),
+			    pv_dev_name(pv));
+		if (vg) {
+			size = pv->pe_count * (uint64_t) vg->extent_size +
+			       pv->pe_start;
+			if (size > pv->size)
+				log_error("WARNING: Physical Volume %s is too "
+					  "large for underlying device",
+					  pv_dev_name(pv));
+		}
+	}
+
+	if (!alloc_pv_segment_whole_pv(mem, pv))
+		return_0;
+
+	vg->pv_count++;
+	dm_list_add(&vg->pvs, &pvl->list);
+
+	return 1;
+}
+
+static void _insert_segment(struct logical_volume *lv, struct lv_segment *seg)
+{
+	struct lv_segment *comp;
+
+	dm_list_iterate_items(comp, &lv->segments) {
+		if (comp->le > seg->le) {
+			dm_list_add(&comp->list, &seg->list);
+			return;
+		}
+	}
+
+	lv->le_count += seg->len;
+	dm_list_add(&lv->segments, &seg->list);
+}
+
+static int _read_segment(struct dm_pool *mem, struct volume_group *vg,
+			 struct logical_volume *lv, struct config_node *sn,
+			 struct dm_hash_table *pv_hash)
+{
+	uint32_t area_count = 0u;
+	struct lv_segment *seg;
+	struct config_node *cn;
+	struct config_value *cv;
+	uint32_t start_extent, extent_count;
+	struct segment_type *segtype;
+	const char *segtype_str;
+
+	if (!(sn = sn->child)) {
+		log_error("Empty segment section.");
+		return 0;
+	}
+
+	if (!_read_int32(sn, "start_extent", &start_extent)) {
+		log_error("Couldn't read 'start_extent' for segment '%s'.",
+			  sn->key);
+		return 0;
+	}
+
+	if (!_read_int32(sn, "extent_count", &extent_count)) {
+		log_error("Couldn't read 'extent_count' for segment '%s'.",
+			  sn->key);
+		return 0;
+	}
+
+	segtype_str = "striped";
+
+	if ((cn = find_config_node(sn, "type"))) {
+		cv = cn->v;
+		if (!cv || !cv->v.str) {
+			log_error("Segment type must be a string.");
+			return 0;
+		}
+		segtype_str = cv->v.str;
+	}
+
+	if (!(segtype = get_segtype_from_string(vg->cmd, segtype_str)))
+		return_0;
+
+	if (segtype->ops->text_import_area_count &&
+	    !segtype->ops->text_import_area_count(sn, &area_count))
+		return_0;
+
+	if (!(seg = alloc_lv_segment(mem, segtype, lv, start_extent,
+				     extent_count, 0, 0, NULL, area_count,
+				     extent_count, 0, 0, 0))) {
+		log_error("Segment allocation failed");
+		return 0;
+	}
+
+	if (seg->segtype->ops->text_import &&
+	    !seg->segtype->ops->text_import(seg, sn, pv_hash))
+		return_0;
+
+	/* Optional tags */
+	if ((cn = find_config_node(sn, "tags")) &&
+	    !(read_tags(mem, &seg->tags, cn->v))) {
+		log_error("Couldn't read tags for a segment of %s/%s.",
+			  vg->name, lv->name);
+		return 0;
+	}
+
+	/*
+	 * Insert into correct part of segment list.
+	 */
+	_insert_segment(lv, seg);
+
+	if (seg_is_mirrored(seg))
+		lv->status |= MIRRORED;
+
+	if (seg_is_virtual(seg))
+		lv->status |= VIRTUAL;
+
+	if (_is_converting(lv))
+		lv->status |= CONVERTING;
+
+	return 1;
+}
+
+int text_import_areas(struct lv_segment *seg, const struct config_node *sn,
+		      const struct config_node *cn, struct dm_hash_table *pv_hash,
+		      uint32_t flags)
+{
+	unsigned int s;
+	struct config_value *cv;
+	struct logical_volume *lv1;
+	const char *seg_name = sn->key;
+
+	if (!seg->area_count) {
+		log_error("Zero areas not allowed for segment '%s'", sn->key);
+		return 0;
+	}
+
+	for (cv = cn->v, s = 0; cv && s < seg->area_count; s++, cv = cv->next) {
+
+		/* first we read the pv */
+		const char *bad = "Badly formed areas array for "
+		    "segment '%s'.";
+		struct physical_volume *pv;
+
+		if (cv->type != CFG_STRING) {
+			log_error(bad, sn->key);
+			return 0;
+		}
+
+		if (!cv->next) {
+			log_error(bad, sn->key);
+			return 0;
+		}
+
+		if (cv->next->type != CFG_INT) {
+			log_error(bad, sn->key);
+			return 0;
+		}
+
+		/* FIXME Cope if LV not yet read in */
+		if ((pv = dm_hash_lookup(pv_hash, cv->v.str))) {
+			if (!set_lv_segment_area_pv(seg, s, pv, (uint32_t) cv->next->v.i))
+				return_0;
+		} else if ((lv1 = find_lv(seg->lv->vg, cv->v.str))) {
+			if (!set_lv_segment_area_lv(seg, s, lv1,
+						    (uint32_t) cv->next->v.i,
+						    flags))
+				return_0;
+		} else {
+			log_error("Couldn't find volume '%s' "
+				  "for segment '%s'.",
+				  cv->v.str ? : "NULL", seg_name);
+			return 0;
+		}
+
+		cv = cv->next;
+	}
+
+	/*
+	 * Check we read the correct number of stripes.
+	 */
+	if (cv || (s < seg->area_count)) {
+		log_error("Incorrect number of areas in area array "
+			  "for segment '%s'.", seg_name);
+		return 0;
+	}
+
+	return 1;
+}
+
+static int _read_segments(struct dm_pool *mem, struct volume_group *vg,
+			  struct logical_volume *lv, struct config_node *lvn,
+			  struct dm_hash_table *pv_hash)
+{
+	struct config_node *sn;
+	int count = 0, seg_count;
+
+	for (sn = lvn; sn; sn = sn->sib) {
+
+		/*
+		 * All sub-sections are assumed to be segments.
+		 */
+		if (!sn->v) {
+			if (!_read_segment(mem, vg, lv, sn, pv_hash))
+				return_0;
+
+			count++;
+		}
+		/* FIXME Remove this restriction */
+		if ((lv->status & SNAPSHOT) && count > 1) {
+			log_error("Only one segment permitted for snapshot");
+			return 0;
+		}
+	}
+
+	if (!_read_int32(lvn, "segment_count", &seg_count)) {
+		log_error("Couldn't read segment count for logical volume.");
+		return 0;
+	}
+
+	if (seg_count != count) {
+		log_error("segment_count and actual number of segments "
+			  "disagree.");
+		return 0;
+	}
+
+	/*
+	 * Check there are no gaps or overlaps in the lv.
+	 */
+	if (!check_lv_segments(lv, 0))
+		return_0;
+
+	/*
+	 * Merge segments in case someones been editing things by hand.
+	 */
+	if (!lv_merge_segments(lv))
+		return_0;
+
+	return 1;
+}
+
+static int _read_lvnames(struct format_instance *fid __attribute((unused)),
+			 struct dm_pool *mem,
+			 struct volume_group *vg, struct config_node *lvn,
+			 struct config_node *vgn __attribute((unused)),
+			 struct dm_hash_table *pv_hash __attribute((unused)))
+{
+	struct logical_volume *lv;
+	struct lv_list *lvl;
+	struct config_node *cn;
+
+	if (!(lvl = dm_pool_zalloc(mem, sizeof(*lvl))) ||
+	    !(lvl->lv = dm_pool_zalloc(mem, sizeof(*lvl->lv))))
+		return_0;
+
+	lv = lvl->lv;
+
+	if (!(lv->name = dm_pool_strdup(mem, lvn->key)))
+		return_0;
+
+	if (!(lvn = lvn->child)) {
+		log_error("Empty logical volume section.");
+		return 0;
+	}
+
+	if (!_read_flag_config(lvn, &lv->status, LV_FLAGS)) {
+		log_error("Couldn't read status flags for logical volume %s.",
+			  lv->name);
+		return 0;
+	}
+
+	lv->alloc = ALLOC_INHERIT;
+	if ((cn = find_config_node(lvn, "allocation_policy"))) {
+		struct config_value *cv = cn->v;
+		if (!cv || !cv->v.str) {
+			log_error("allocation_policy must be a string.");
+			return 0;
+		}
+
+		lv->alloc = get_alloc_from_string(cv->v.str);
+		if (lv->alloc == ALLOC_INVALID)
+			return_0;
+	}
+
+	if (!_read_int32(lvn, "read_ahead", &lv->read_ahead))
+		/* If not present, choice of auto or none is configurable */
+		lv->read_ahead = vg->cmd->default_settings.read_ahead;
+	else {
+		switch (lv->read_ahead) {
+		case 0:
+			lv->read_ahead = DM_READ_AHEAD_AUTO;
+			break;
+		case (uint32_t) -1:
+			lv->read_ahead = DM_READ_AHEAD_NONE;
+			break;
+		default:
+			;
+		}
+	}
+
+	lv->snapshot = NULL;
+	dm_list_init(&lv->snapshot_segs);
+	dm_list_init(&lv->segments);
+	dm_list_init(&lv->tags);
+	dm_list_init(&lv->segs_using_this_lv);
+
+	/* Optional tags */
+	if ((cn = find_config_node(lvn, "tags")) &&
+	    !(read_tags(mem, &lv->tags, cn->v))) {
+		log_error("Couldn't read tags for logical volume %s/%s.",
+			  vg->name, lv->name);
+		return 0;
+	}
+
+	lv->vg = vg;
+	vg->lv_count++;
+	dm_list_add(&vg->lvs, &lvl->list);
+
+	return 1;
+}
+
+static int _read_lvsegs(struct format_instance *fid __attribute((unused)),
+			struct dm_pool *mem,
+			struct volume_group *vg, struct config_node *lvn,
+			struct config_node *vgn __attribute((unused)),
+			struct dm_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))
+		return_0;
+
+	lv->size = (uint64_t) lv->le_count * (uint64_t) vg->extent_size;
+
+	/*
+	 * FIXME We now have 2 LVs for each snapshot. The real one was
+	 * created by vg_add_snapshot from the segment text_import.
+	 */
+	if (lv->status & SNAPSHOT) {
+		vg->lv_count--;
+		dm_list_del(&lvl->list);
+		return 1;
+	}
+
+	lv->minor = -1;
+	if ((lv->status & FIXED_MINOR) &&
+	    !_read_int32(lvn, "minor", &lv->minor)) {
+		log_error("Couldn't read minor number for logical "
+			  "volume %s.", lv->name);
+		return 0;
+	}
+
+	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);
+	}
+
+	return 1;
+}
+
+static int _read_sections(struct format_instance *fid,
+			  const char *section, section_fn fn,
+			  struct dm_pool *mem,
+			  struct volume_group *vg, struct config_node *vgn,
+			  struct dm_hash_table *pv_hash, int optional)
+{
+	struct config_node *n;
+
+	if (!(n = find_config_node(vgn, section))) {
+		if (!optional) {
+			log_error("Couldn't find section '%s'.", section);
+			return 0;
+		}
+
+		return 1;
+	}
+
+	for (n = n->child; n; n = n->sib) {
+		if (!fn(fid, mem, vg, n, vgn, pv_hash))
+			return_0;
+	}
+
+	return 1;
+}
+
+static struct volume_group *_read_vg(struct format_instance *fid,
+				     struct config_tree *cft)
+{
+	struct config_node *vgn, *cn;
+	struct volume_group *vg;
+	struct dm_hash_table *pv_hash = NULL;
+	struct dm_pool *mem = fid->fmt->cmd->mem;
+
+	/* skip any top-level values */
+	for (vgn = cft->root; (vgn && vgn->v); vgn = vgn->sib) ;
+
+	if (!vgn) {
+		log_error("Couldn't find volume group in file.");
+		return NULL;
+	}
+
+	if (!(vg = dm_pool_zalloc(mem, sizeof(*vg))))
+		return_NULL;
+	vg->cmd = fid->fmt->cmd;
+
+	/* FIXME Determine format type from file contents */
+	/* eg Set to instance of fmt1 here if reading a format1 backup? */
+	vg->fid = fid;
+
+	if (!(vg->name = dm_pool_strdup(mem, vgn->key)))
+		goto_bad;
+
+	if (!(vg->system_id = dm_pool_zalloc(mem, NAME_LEN)))
+		goto_bad;
+
+	vgn = vgn->child;
+
+	if ((cn = find_config_node(vgn, "system_id")) && cn->v) {
+		if (!cn->v->v.str) {
+			log_error("system_id must be a string");
+			goto bad;
+		}
+		strncpy(vg->system_id, cn->v->v.str, NAME_LEN);
+	}
+
+	if (!_read_id(&vg->id, vgn, "id")) {
+		log_error("Couldn't read uuid for volume group %s.", vg->name);
+		goto bad;
+	}
+
+	if (!_read_int32(vgn, "seqno", &vg->seqno)) {
+		log_error("Couldn't read 'seqno' for volume group %s.",
+			  vg->name);
+		goto bad;
+	}
+
+	if (!_read_flag_config(vgn, &vg->status, VG_FLAGS)) {
+		log_error("Error reading flags of volume group %s.",
+			  vg->name);
+		goto bad;
+	}
+
+	if (!_read_int32(vgn, "extent_size", &vg->extent_size)) {
+		log_error("Couldn't read extent size for volume group %s.",
+			  vg->name);
+		goto bad;
+	}
+
+	/*
+	 * 'extent_count' and 'free_count' get filled in
+	 * implicitly when reading in the pv's and lv's.
+	 */
+
+	if (!_read_int32(vgn, "max_lv", &vg->max_lv)) {
+		log_error("Couldn't read 'max_lv' for volume group %s.",
+			  vg->name);
+		goto bad;
+	}
+
+	if (!_read_int32(vgn, "max_pv", &vg->max_pv)) {
+		log_error("Couldn't read 'max_pv' for volume group %s.",
+			  vg->name);
+		goto bad;
+	}
+
+	vg->alloc = ALLOC_NORMAL;
+	if ((cn = find_config_node(vgn, "allocation_policy"))) {
+		struct config_value *cv = cn->v;
+		if (!cv || !cv->v.str) {
+			log_error("allocation_policy must be a string.");
+			return 0;
+		}
+
+		vg->alloc = get_alloc_from_string(cv->v.str);
+		if (vg->alloc == ALLOC_INVALID)
+			return_0;
+	}
+
+	/*
+	 * The pv hash memoises the pv section names -> pv
+	 * structures.
+	 */
+	if (!(pv_hash = dm_hash_create(32))) {
+		log_error("Couldn't create hash table.");
+		goto bad;
+	}
+
+	dm_list_init(&vg->pvs);
+	if (!_read_sections(fid, "physical_volumes", _read_pv, mem, vg,
+			    vgn, pv_hash, 0)) {
+		log_error("Couldn't find all physical volumes for volume "
+			  "group %s.", vg->name);
+		goto bad;
+	}
+
+	dm_list_init(&vg->lvs);
+	dm_list_init(&vg->tags);
+
+	/* Optional tags */
+	if ((cn = find_config_node(vgn, "tags")) &&
+	    !(read_tags(mem, &vg->tags, cn->v))) {
+		log_error("Couldn't read tags for volume group %s.", vg->name);
+		goto bad;
+	}
+
+	if (!_read_sections(fid, "logical_volumes", _read_lvnames, mem, vg,
+			    vgn, pv_hash, 1)) {
+		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;
+	}
+
+	if (!fixup_imported_mirrors(vg)) {
+		log_error("Failed to fixup mirror pointers after import for "
+			  "volume group %s.", vg->name);
+		goto bad;
+	}
+
+	dm_hash_destroy(pv_hash);
+
+	/*
+	 * Finished.
+	 */
+	return vg;
+
+      bad:
+	if (pv_hash)
+		dm_hash_destroy(pv_hash);
+
+	dm_pool_free(mem, vg);
+	return NULL;
+}
+
+static void _read_desc(struct dm_pool *mem,
+		       struct config_tree *cft, time_t *when, char **desc)
+{
+	const char *d;
+	unsigned int u = 0u;
+
+	log_suppress(1);
+	d = find_config_str(cft->root, "description", "");
+	log_suppress(0);
+	*desc = dm_pool_strdup(mem, d);
+
+	get_config_uint32(cft->root, "creation_time", &u);
+	*when = u;
+}
+
+static const char *_read_vgname(const struct format_type *fmt,
+				struct config_tree *cft, struct id *vgid,
+				uint32_t *vgstatus, char **creation_host)
+{
+	struct config_node *vgn;
+	struct dm_pool *mem = fmt->cmd->mem;
+	char *vgname;
+	int old_suppress;
+
+	old_suppress = log_suppress(2);
+	*creation_host = dm_pool_strdup(mem,
+					find_config_str(cft->root,
+							"creation_host", ""));
+	log_suppress(old_suppress);
+
+	/* skip any top-level values */
+	for (vgn = cft->root; (vgn && vgn->v); vgn = vgn->sib) ;
+
+	if (!vgn) {
+		log_error("Couldn't find volume group in file.");
+		return 0;
+	}
+
+	if (!(vgname = dm_pool_strdup(mem, vgn->key)))
+		return_0;
+
+	vgn = vgn->child;
+
+	if (!_read_id(vgid, vgn, "id")) {
+		log_error("Couldn't read uuid for volume group %s.", vgname);
+		return 0;
+	}
+
+	if (!_read_flag_config(vgn, vgstatus, VG_FLAGS)) {
+		log_error("Couldn't find status flags for volume group %s.",
+			  vgname);
+		return 0;
+	}
+
+	return vgname;
+}
+
+static struct text_vg_version_ops _vsn1_ops = {
+	.check_version = _check_version,
+	.read_vg = _read_vg,
+	.read_desc = _read_desc,
+	.read_vgname = _read_vgname,
+};
+
+struct text_vg_version_ops *text_vg_vsn1_init(void)
+{
+	return &_vsn1_ops;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/format_text/layout.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format_text/layout.h
diff -N src/external/gpl2/lvm2tools/dist/lib/format_text/layout.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format_text/layout.h	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,91 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_TEXT_LAYOUT_H
+#define _LVM_TEXT_LAYOUT_H
+
+#include "config.h"
+#include "lvm-types.h"
+#include "metadata.h"
+#include "uuid.h"
+
+/* On disk */
+struct disk_locn {
+	uint64_t offset;	/* Offset in bytes to start sector */
+	uint64_t size;		/* Bytes */
+} __attribute__ ((packed));
+
+/* Data areas (holding PEs) */
+struct data_area_list {
+	struct dm_list list;
+	struct disk_locn disk_locn;
+};
+
+/* Fields with the suffix _xl should be xlate'd wherever they appear */
+/* On disk */
+struct pv_header {
+	int8_t pv_uuid[ID_LEN];
+
+	/* This size can be overridden if PV belongs to a VG */
+	uint64_t device_size_xl;	/* Bytes */
+
+	/* NULL-terminated list of data areas followed by */
+	/* NULL-terminated list of metadata area headers */
+	struct disk_locn disk_areas_xl[0];	/* Two lists */
+} __attribute__ ((packed));
+
+/* On disk */
+struct raw_locn {
+	uint64_t offset;	/* Offset in bytes to start sector */
+	uint64_t size;		/* Bytes */
+	uint32_t checksum;
+	uint32_t filler;
+} __attribute__ ((packed));
+
+/* On disk */
+/* Structure size limited to one sector */
+struct mda_header {
+	uint32_t checksum_xl;	/* Checksum of rest of mda_header */
+	int8_t magic[16];	/* To aid scans for metadata */
+	uint32_t version;
+	uint64_t start;		/* Absolute start byte of mda_header */
+	uint64_t size;		/* Size of metadata area */
+
+	struct raw_locn raw_locns[0];	/* NULL-terminated list */
+} __attribute__ ((packed));
+
+struct mda_lists {
+	struct dm_list dirs;
+	struct dm_list raws;
+	struct metadata_area_ops *file_ops;
+	struct metadata_area_ops *raw_ops;
+};
+
+struct mda_context {
+	struct device_area area;
+	uint64_t free_sectors;
+	struct raw_locn rlocn;	/* Store inbetween write and commit */
+};
+
+/* FIXME Convert this at runtime */
+#define FMTT_MAGIC "\040\114\126\115\062\040\170\133\065\101\045\162\060\116\052\076"
+#define FMTT_VERSION 1
+#define MDA_HEADER_SIZE 512
+#define LVM2_LABEL "LVM2 001"
+#define MDA_SIZE_MIN (8 * (unsigned) lvm_getpagesize())
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/format_text/tags.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format_text/tags.c
diff -N src/external/gpl2/lvm2tools/dist/lib/format_text/tags.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format_text/tags.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,67 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "metadata.h"
+#include "import-export.h"
+#include "str_list.h"
+#include "lvm-string.h"
+
+int print_tags(struct dm_list *tags, char *buffer, size_t size)
+{
+	struct str_list *sl;
+	int first = 1;
+
+	if (!emit_to_buffer(&buffer, &size, "["))
+		return_0;
+
+	dm_list_iterate_items(sl, tags) {
+		if (!first) {
+			if (!emit_to_buffer(&buffer, &size, ", "))
+				return_0;
+		} else
+			first = 0;
+
+		if (!emit_to_buffer(&buffer, &size, "\"%s\"", sl->str))
+			return_0;
+	}
+
+	if (!emit_to_buffer(&buffer, &size, "]"))
+		return_0;
+
+	return 1;
+}
+
+int read_tags(struct dm_pool *mem, struct dm_list *tags, struct config_value *cv)
+{
+	if (cv->type == CFG_EMPTY_ARRAY)
+		return 1;
+
+	while (cv) {
+		if (cv->type != CFG_STRING) {
+			log_error("Found a tag that is not a string");
+			return 0;
+		}
+
+		if (!str_list_add(mem, tags, dm_pool_strdup(mem, cv->v.str)))
+			return_0;
+
+		cv = cv->next;
+	}
+
+	return 1;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/format_text/text_export.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format_text/text_export.h
diff -N src/external/gpl2/lvm2tools/dist/lib/format_text/text_export.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format_text/text_export.h	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,39 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_TEXT_EXPORT_H
+#define _LVM_TEXT_EXPORT_H
+
+#define outf(args...) do {if (!out_text(args)) return_0;} while (0)
+#define outnl(f) do {if (!f->nl(f)) return_0;} while (0)
+
+struct formatter;
+struct lv_segment;
+
+int out_size(struct formatter *f, uint64_t size, const char *fmt, ...)
+    __attribute__ ((format(printf, 3, 4)));
+
+int out_hint(struct formatter *f, const char *fmt, ...)
+    __attribute__ ((format(printf, 2, 3)));
+
+int out_text(struct formatter *f, const char *fmt, ...)
+    __attribute__ ((format(printf, 2, 3)));
+
+int out_areas(struct formatter *f, const struct lv_segment *seg,
+	      const char *type);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/format_text/text_import.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format_text/text_import.h
diff -N src/external/gpl2/lvm2tools/dist/lib/format_text/text_import.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format_text/text_import.h	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,28 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_TEXT_IMPORT_H
+#define _LVM_TEXT_IMPORT_H
+
+struct lv_segment;
+struct config_node;
+
+int text_import_areas(struct lv_segment *seg, const struct config_node *sn,
+		      const struct config_node *cn, struct dm_hash_table *pv_hash,
+		      uint32_t flags);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/format_text/text_label.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/format_text/text_label.c
diff -N src/external/gpl2/lvm2tools/dist/lib/format_text/text_label.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/format_text/text_label.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,299 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "format-text.h"
+#include "layout.h"
+#include "label.h"
+#include "xlate.h"
+#include "lvmcache.h"
+
+#include <sys/stat.h>
+#include <fcntl.h>
+
+static int _text_can_handle(struct labeller *l __attribute((unused)),
+			    void *buf,
+			    uint64_t sector __attribute((unused)))
+{
+	struct label_header *lh = (struct label_header *) buf;
+
+	if (!strncmp((char *)lh->type, LVM2_LABEL, sizeof(lh->type)))
+		return 1;
+
+	return 0;
+}
+
+static int _text_write(struct label *label, void *buf)
+{
+	struct label_header *lh = (struct label_header *) buf;
+	struct pv_header *pvhdr;
+	struct lvmcache_info *info;
+	struct disk_locn *pvh_dlocn_xl;
+	struct metadata_area *mda;
+	struct mda_context *mdac;
+	struct data_area_list *da;
+
+	/* FIXME Move to where label is created */
+	strncpy(label->type, LVM2_LABEL, sizeof(label->type));
+
+	strncpy((char *)lh->type, label->type, sizeof(label->type));
+
+	pvhdr = (struct pv_header *) ((void *) buf + xlate32(lh->offset_xl));
+	info = (struct lvmcache_info *) label->info;
+	pvhdr->device_size_xl = xlate64(info->device_size);
+	memcpy(pvhdr->pv_uuid, &info->dev->pvid, sizeof(struct id));
+
+	pvh_dlocn_xl = &pvhdr->disk_areas_xl[0];
+
+	/* List of data areas (holding PEs) */
+	dm_list_iterate_items(da, &info->das) {
+		pvh_dlocn_xl->offset = xlate64(da->disk_locn.offset);
+		pvh_dlocn_xl->size = xlate64(da->disk_locn.size);
+		pvh_dlocn_xl++;
+	}
+
+	/* NULL-termination */
+	pvh_dlocn_xl->offset = xlate64(UINT64_C(0));
+	pvh_dlocn_xl->size = xlate64(UINT64_C(0));
+	pvh_dlocn_xl++;
+
+	/* List of metadata area header locations */
+	dm_list_iterate_items(mda, &info->mdas) {
+		mdac = (struct mda_context *) mda->metadata_locn;
+
+		if (mdac->area.dev != info->dev)
+			continue;
+
+		pvh_dlocn_xl->offset = xlate64(mdac->area.start);
+		pvh_dlocn_xl->size = xlate64(mdac->area.size);
+		pvh_dlocn_xl++;
+	}
+
+	/* NULL-termination */
+	pvh_dlocn_xl->offset = xlate64(UINT64_C(0));
+	pvh_dlocn_xl->size = xlate64(UINT64_C(0));
+
+	return 1;
+}
+
+int add_da(struct dm_pool *mem, struct dm_list *das,
+	   uint64_t start, uint64_t size)
+{
+	struct data_area_list *dal;
+
+	if (!mem) {
+		if (!(dal = dm_malloc(sizeof(*dal)))) {
+			log_error("struct data_area_list allocation failed");
+			return 0;
+		}
+	} else {
+		if (!(dal = dm_pool_alloc(mem, sizeof(*dal)))) {
+			log_error("struct data_area_list allocation failed");
+			return 0;
+		}
+	}
+
+	dal->disk_locn.offset = start;
+	dal->disk_locn.size = size;
+
+	dm_list_add(das, &dal->list);
+
+	return 1;
+}
+
+void del_das(struct dm_list *das)
+{
+	struct dm_list *dah, *tmp;
+	struct data_area_list *da;
+
+	dm_list_iterate_safe(dah, tmp, das) {
+		da = dm_list_item(dah, struct data_area_list);
+		dm_list_del(&da->list);
+		dm_free(da);
+	}
+}
+
+int add_mda(const struct format_type *fmt, struct dm_pool *mem, struct dm_list *mdas,
+	    struct device *dev, uint64_t start, uint64_t size)
+{
+/* FIXME List size restricted by pv_header SECTOR_SIZE */
+	struct metadata_area *mdal;
+	struct mda_lists *mda_lists = (struct mda_lists *) fmt->private;
+	struct mda_context *mdac;
+
+	if (!mem) {
+		if (!(mdal = dm_malloc(sizeof(struct metadata_area)))) {
+			log_error("struct mda_list allocation failed");
+			return 0;
+		}
+
+		if (!(mdac = dm_malloc(sizeof(struct mda_context)))) {
+			log_error("struct mda_context allocation failed");
+			dm_free(mdal);
+			return 0;
+		}
+	} else {
+		if (!(mdal = dm_pool_alloc(mem, sizeof(struct metadata_area)))) {
+			log_error("struct mda_list allocation failed");
+			return 0;
+		}
+
+		if (!(mdac = dm_pool_alloc(mem, sizeof(struct mda_context)))) {
+			log_error("struct mda_context allocation failed");
+			return 0;
+		}
+	}
+
+	mdal->ops = mda_lists->raw_ops;
+	mdal->metadata_locn = mdac;
+
+	mdac->area.dev = dev;
+	mdac->area.start = start;
+	mdac->area.size = size;
+	mdac->free_sectors = UINT64_C(0);
+	memset(&mdac->rlocn, 0, sizeof(mdac->rlocn));
+
+	dm_list_add(mdas, &mdal->list);
+	return 1;
+}
+
+void del_mdas(struct dm_list *mdas)
+{
+	struct dm_list *mdah, *tmp;
+	struct metadata_area *mda;
+
+	dm_list_iterate_safe(mdah, tmp, mdas) {
+		mda = dm_list_item(mdah, struct metadata_area);
+		dm_free(mda->metadata_locn);
+		dm_list_del(&mda->list);
+		dm_free(mda);
+	}
+}
+
+static int _text_initialise_label(struct labeller *l __attribute((unused)),
+				  struct label *label)
+{
+	strncpy(label->type, LVM2_LABEL, sizeof(label->type));
+
+	return 1;
+}
+
+static int _text_read(struct labeller *l, struct device *dev, void *buf,
+		 struct label **label)
+{
+	struct label_header *lh = (struct label_header *) buf;
+	struct pv_header *pvhdr;
+	struct lvmcache_info *info;
+	struct disk_locn *dlocn_xl;
+	uint64_t offset;
+	struct metadata_area *mda;
+	struct id vgid;
+	struct mda_context *mdac;
+	const char *vgname;
+	uint32_t vgstatus;
+	char *creation_host;
+
+	pvhdr = (struct pv_header *) ((void *) buf + xlate32(lh->offset_xl));
+
+	if (!(info = lvmcache_add(l, (char *)pvhdr->pv_uuid, dev,
+				  FMT_TEXT_ORPHAN_VG_NAME,
+				  FMT_TEXT_ORPHAN_VG_NAME, 0)))
+		return_0;
+	*label = info->label;
+
+	info->device_size = xlate64(pvhdr->device_size_xl);
+
+	if (info->das.n)
+		del_das(&info->das);
+	dm_list_init(&info->das);
+
+	if (info->mdas.n)
+		del_mdas(&info->mdas);
+	dm_list_init(&info->mdas);
+
+	/* Data areas holding the PEs */
+	dlocn_xl = pvhdr->disk_areas_xl;
+	while ((offset = xlate64(dlocn_xl->offset))) {
+		add_da(NULL, &info->das, offset,
+		       xlate64(dlocn_xl->size));
+		dlocn_xl++;
+	}
+
+	/* Metadata area headers */
+	dlocn_xl++;
+	while ((offset = xlate64(dlocn_xl->offset))) {
+		add_mda(info->fmt, NULL, &info->mdas, dev, offset,
+			xlate64(dlocn_xl->size));
+		dlocn_xl++;
+	}
+
+	dm_list_iterate_items(mda, &info->mdas) {
+		mdac = (struct mda_context *) mda->metadata_locn;
+		if ((vgname = vgname_from_mda(info->fmt, &mdac->area,
+					      &vgid, &vgstatus, &creation_host,
+					      &mdac->free_sectors)) &&
+		    !lvmcache_update_vgname_and_id(info, vgname,
+						   (char *) &vgid, vgstatus,
+						   creation_host))
+			return_0;
+	}
+
+	info->status &= ~CACHE_INVALID;
+
+	return 1;
+}
+
+static void _text_destroy_label(struct labeller *l __attribute((unused)),
+				struct label *label)
+{
+	struct lvmcache_info *info = (struct lvmcache_info *) label->info;
+
+	if (info->mdas.n)
+		del_mdas(&info->mdas);
+	if (info->das.n)
+		del_das(&info->das);
+}
+
+static void _fmt_text_destroy(struct labeller *l)
+{
+	dm_free(l);
+}
+
+struct label_ops _text_ops = {
+	.can_handle = _text_can_handle,
+	.write = _text_write,
+	.read = _text_read,
+	.verify = _text_can_handle,
+	.initialise_label = _text_initialise_label,
+	.destroy_label = _text_destroy_label,
+	.destroy = _fmt_text_destroy,
+};
+
+struct labeller *text_labeller_create(const struct format_type *fmt)
+{
+	struct labeller *l;
+
+	if (!(l = dm_malloc(sizeof(*l)))) {
+		log_err("Couldn't allocate labeller object.");
+		return NULL;
+	}
+
+	l->ops = &_text_ops;
+	l->private = (const void *) fmt;
+
+	return l;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/freeseg/freeseg.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/freeseg/freeseg.c
diff -N src/external/gpl2/lvm2tools/dist/lib/freeseg/freeseg.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/freeseg/freeseg.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,62 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "toolcontext.h"
+#include "segtype.h"
+#include "display.h"
+#include "text_export.h"
+#include "text_import.h"
+#include "config.h"
+#include "str_list.h"
+#include "targets.h"
+#include "lvm-string.h"
+#include "activate.h"
+#include "str_list.h"
+#include "metadata.h"
+
+static const char *_freeseg_name(const struct lv_segment *seg)
+{
+	return seg->segtype->name;
+}
+
+static void _freeseg_destroy(const struct segment_type *segtype)
+{
+	dm_free((void *)segtype);
+}
+
+static struct segtype_handler _freeseg_ops = {
+	.name = _freeseg_name,
+	.destroy = _freeseg_destroy,
+};
+
+struct segment_type *init_free_segtype(struct cmd_context *cmd)
+{
+	struct segment_type *segtype = dm_malloc(sizeof(*segtype));
+
+	if (!segtype)
+		return_NULL;
+
+	segtype->cmd = cmd;
+	segtype->ops = &_freeseg_ops;
+	segtype->name = "free";
+	segtype->private = NULL;
+	segtype->flags = SEG_VIRTUAL | SEG_CANNOT_BE_ZEROED;
+
+	log_very_verbose("Initialised segtype: %s", segtype->name);
+
+	return segtype;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/label/label.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/label/label.c
diff -N src/external/gpl2/lvm2tools/dist/lib/label/label.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/label/label.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,398 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "label.h"
+#include "crc.h"
+#include "xlate.h"
+#include "lvmcache.h"
+#include "metadata.h"
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+/* FIXME Allow for larger labels?  Restricted to single sector currently */
+
+/*
+ * Internal labeller struct.
+ */
+struct labeller_i {
+	struct dm_list list;
+
+	struct labeller *l;
+	char name[0];
+};
+
+static struct dm_list _labellers;
+
+static struct labeller_i *_alloc_li(const char *name, struct labeller *l)
+{
+	struct labeller_i *li;
+	size_t len;
+
+	len = sizeof(*li) + strlen(name) + 1;
+
+	if (!(li = dm_malloc(len))) {
+		log_error("Couldn't allocate memory for labeller list object.");
+		return NULL;
+	}
+
+	li->l = l;
+	strcpy(li->name, name);
+
+	return li;
+}
+
+static void _free_li(struct labeller_i *li)
+{
+	dm_free(li);
+}
+
+int label_init(void)
+{
+	dm_list_init(&_labellers);
+	return 1;
+}
+
+void label_exit(void)
+{
+	struct dm_list *c, *n;
+	struct labeller_i *li;
+
+	for (c = _labellers.n; c != &_labellers; c = n) {
+		n = c->n;
+		li = dm_list_item(c, struct labeller_i);
+		li->l->ops->destroy(li->l);
+		_free_li(li);
+	}
+
+	dm_list_init(&_labellers);
+}
+
+int label_register_handler(const char *name, struct labeller *handler)
+{
+	struct labeller_i *li;
+
+	if (!(li = _alloc_li(name, handler)))
+		return_0;
+
+	dm_list_add(&_labellers, &li->list);
+	return 1;
+}
+
+struct labeller *label_get_handler(const char *name)
+{
+	struct labeller_i *li;
+
+	dm_list_iterate_items(li, &_labellers)
+		if (!strcmp(li->name, name))
+			return li->l;
+
+	return NULL;
+}
+
+static struct labeller *_find_labeller(struct device *dev, char *buf,
+				       uint64_t *label_sector,
+				       uint64_t scan_sector)
+{
+	struct labeller_i *li;
+	struct labeller *r = NULL;
+	struct label_header *lh;
+	struct lvmcache_info *info;
+	uint64_t sector;
+	int found = 0;
+	char readbuf[LABEL_SCAN_SIZE] __attribute((aligned(8)));
+
+	if (!dev_read(dev, scan_sector << SECTOR_SHIFT,
+		      LABEL_SCAN_SIZE, readbuf)) {
+		log_debug("%s: Failed to read label area", dev_name(dev));
+		goto out;
+	}
+
+	/* Scan a few sectors for a valid label */
+	for (sector = 0; sector < LABEL_SCAN_SECTORS;
+	     sector += LABEL_SIZE >> SECTOR_SHIFT) {
+		lh = (struct label_header *) (readbuf +
+					      (sector << SECTOR_SHIFT));
+
+		if (!strncmp((char *)lh->id, LABEL_ID, sizeof(lh->id))) {
+			if (found) {
+				log_error("Ignoring additional label on %s at "
+					  "sector %" PRIu64, dev_name(dev),
+					  sector + scan_sector);
+			}
+			if (xlate64(lh->sector_xl) != sector + scan_sector) {
+				log_info("%s: Label for sector %" PRIu64
+					 " found at sector %" PRIu64
+					 " - ignoring", dev_name(dev),
+					 xlate64(lh->sector_xl),
+					 sector + scan_sector);
+				continue;
+			}
+			if (calc_crc(INITIAL_CRC, &lh->offset_xl, LABEL_SIZE -
+				     ((uintptr_t) &lh->offset_xl - (uintptr_t) lh)) !=
+			    xlate32(lh->crc_xl)) {
+				log_info("Label checksum incorrect on %s - "
+					 "ignoring", dev_name(dev));
+				continue;
+			}
+			if (found)
+				continue;
+		}
+
+		dm_list_iterate_items(li, &_labellers) {
+			if (li->l->ops->can_handle(li->l, (char *) lh,
+						   sector + scan_sector)) {
+				log_very_verbose("%s: %s label detected",
+						 dev_name(dev), li->name);
+				if (found) {
+					log_error("Ignoring additional label "
+						  "on %s at sector %" PRIu64,
+						  dev_name(dev),
+						  sector + scan_sector);
+					continue;
+				}
+				r = li->l;
+				memcpy(buf, lh, LABEL_SIZE);
+				if (label_sector)
+					*label_sector = sector + scan_sector;
+				found = 1;
+				break;
+			}
+		}
+	}
+
+      out:
+	if (!found) {
+		if ((info = info_from_pvid(dev->pvid, 0)))
+			lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
+						      info->fmt->orphan_vg_name,
+						      0, NULL);
+		log_very_verbose("%s: No label detected", dev_name(dev));
+	}
+
+	return r;
+}
+
+/* FIXME Also wipe associated metadata area headers? */
+int label_remove(struct device *dev)
+{
+	char buf[LABEL_SIZE] __attribute((aligned(8)));
+	char readbuf[LABEL_SCAN_SIZE] __attribute((aligned(8)));
+	int r = 1;
+	uint64_t sector;
+	int wipe;
+	struct labeller_i *li;
+	struct label_header *lh;
+
+	memset(buf, 0, LABEL_SIZE);
+
+	log_very_verbose("Scanning for labels to wipe from %s", dev_name(dev));
+
+	if (!dev_open(dev))
+		return_0;
+
+	/*
+	 * 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;
+	}
+
+	/* Scan first few sectors for anything looking like a label */
+	for (sector = 0; sector < LABEL_SCAN_SECTORS;
+	     sector += LABEL_SIZE >> SECTOR_SHIFT) {
+		lh = (struct label_header *) (readbuf +
+					      (sector << SECTOR_SHIFT));
+
+		wipe = 0;
+
+		if (!strncmp((char *)lh->id, LABEL_ID, sizeof(lh->id))) {
+			if (xlate64(lh->sector_xl) == sector)
+				wipe = 1;
+		} else {
+			dm_list_iterate_items(li, &_labellers) {
+				if (li->l->ops->can_handle(li->l, (char *) lh,
+							   sector)) {
+					wipe = 1;
+					break;
+				}
+			}
+		}
+
+		if (wipe) {
+			log_info("%s: Wiping label at sector %" PRIu64,
+				 dev_name(dev), sector);
+			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);
+				r = 0;
+			}
+		}
+	}
+
+      out:
+	if (!dev_close(dev))
+		stack;
+
+	return r;
+}
+
+int label_read(struct device *dev, struct label **result,
+		uint64_t scan_sector)
+{
+	char buf[LABEL_SIZE] __attribute((aligned(8)));
+	struct labeller *l;
+	uint64_t sector;
+	struct lvmcache_info *info;
+	int r = 0;
+
+	if ((info = info_from_pvid(dev->pvid, 1))) {
+		log_debug("Using cached label for %s", dev_name(dev));
+		*result = info->label;
+		return 1;
+	}
+
+	if (!dev_open(dev)) {
+		stack;
+
+		if ((info = info_from_pvid(dev->pvid, 0)))
+			lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
+						      info->fmt->orphan_vg_name,
+						      0, NULL);
+
+		return r;
+	}
+
+	if (!(l = _find_labeller(dev, buf, &sector, scan_sector)))
+		goto out;
+
+	if ((r = (l->ops->read)(l, dev, buf, result)) && result && *result)
+		(*result)->sector = sector;
+
+      out:
+	if (!dev_close(dev))
+		stack;
+
+	return r;
+}
+
+/* Caller may need to use label_get_handler to create label struct! */
+int label_write(struct device *dev, struct label *label)
+{
+	char buf[LABEL_SIZE] __attribute((aligned(8)));
+	struct label_header *lh = (struct label_header *) buf;
+	int r = 1;
+
+	if (!label->labeller->ops->write) {
+		log_err("Label handler does not support label writes");
+		return 0;
+	}
+
+	if ((LABEL_SIZE + (label->sector << SECTOR_SHIFT)) > LABEL_SCAN_SIZE) {
+		log_error("Label sector %" PRIu64 " beyond range (%ld)",
+			  label->sector, LABEL_SCAN_SECTORS);
+		return 0;
+	}
+
+	memset(buf, 0, LABEL_SIZE);
+
+	strncpy((char *)lh->id, LABEL_ID, sizeof(lh->id));
+	lh->sector_xl = xlate64(label->sector);
+	lh->offset_xl = xlate32(sizeof(*lh));
+
+	if (!(label->labeller->ops->write)(label, buf))
+		return_0;
+
+	lh->crc_xl = xlate32(calc_crc(INITIAL_CRC, &lh->offset_xl, LABEL_SIZE -
+				      ((uintptr_t) &lh->offset_xl - (uintptr_t) lh)));
+
+	if (!dev_open(dev))
+		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)) {
+		log_debug("Failed to write label to %s", dev_name(dev));
+		r = 0;
+	}
+
+	if (!dev_close(dev))
+		stack;
+
+	return r;
+}
+
+/* Unused */
+int label_verify(struct device *dev)
+{
+	struct labeller *l;
+	char buf[LABEL_SIZE] __attribute((aligned(8)));
+	uint64_t sector;
+	struct lvmcache_info *info;
+	int r = 0;
+
+	if (!dev_open(dev)) {
+		if ((info = info_from_pvid(dev->pvid, 0)))
+			lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
+						      info->fmt->orphan_vg_name,
+						      0, NULL);
+
+		return_0;
+	}
+
+	if (!(l = _find_labeller(dev, buf, &sector, UINT64_C(0))))
+		goto out;
+
+	r = l->ops->verify ? l->ops->verify(l, buf, sector) : 1;
+
+      out:
+	if (!dev_close(dev))
+		stack;
+
+	return r;
+}
+
+void label_destroy(struct label *label)
+{
+	label->labeller->ops->destroy_label(label->labeller, label);
+	dm_free(label);
+}
+
+struct label *label_create(struct labeller *labeller)
+{
+	struct label *label;
+
+	if (!(label = dm_malloc(sizeof(*label)))) {
+		log_error("label allocaction failed");
+		return NULL;
+	}
+	memset(label, 0, sizeof(*label));
+
+	label->labeller = labeller;
+
+	labeller->ops->initialise_label(labeller, label);
+
+	return label;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/label/label.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/label/label.h
diff -N src/external/gpl2/lvm2tools/dist/lib/label/label.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/label/label.h	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,108 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_LABEL_H
+#define _LVM_LABEL_H
+
+#include "uuid.h"
+#include "device.h"
+
+#define LABEL_ID "LABELONE"
+#define LABEL_SIZE SECTOR_SIZE	/* Think very carefully before changing this */
+#define LABEL_SCAN_SECTORS 4L
+#define LABEL_SCAN_SIZE (LABEL_SCAN_SECTORS << SECTOR_SHIFT)
+
+struct labeller;
+
+/* On disk - 32 bytes */
+struct label_header {
+	int8_t id[8];		/* LABELONE */
+	uint64_t sector_xl;	/* Sector number of this label */
+	uint32_t crc_xl;	/* From next field to end of sector */
+	uint32_t offset_xl;	/* Offset from start of struct to contents */
+	int8_t type[8];		/* LVM2 001 */
+} __attribute__ ((packed));
+
+/* In core */
+struct label {
+	char type[8];
+	uint64_t sector;
+	struct labeller *labeller;
+	void *info;
+};
+
+struct labeller;
+
+struct label_ops {
+	/*
+	 * Is the device labelled with this format ?
+	 */
+	int (*can_handle) (struct labeller * l, void *buf, uint64_t sector);
+
+	/*
+	 * Write a label to a volume.
+	 */
+	int (*write) (struct label * label, void *buf);
+
+	/*
+	 * Read a label from a volume.
+	 */
+	int (*read) (struct labeller * l, struct device * dev,
+		     void *buf, struct label ** label);
+
+	/*
+	 * Additional consistency checks for the paranoid.
+	 */
+	int (*verify) (struct labeller * l, void *buf, uint64_t sector);
+
+	/*
+	 * Populate label_type etc.
+	 */
+	int (*initialise_label) (struct labeller * l, struct label * label);
+
+	/*
+	 * Destroy a previously read label.
+	 */
+	void (*destroy_label) (struct labeller * l, struct label * label);
+
+	/*
+	 * Destructor.
+	 */
+	void (*destroy) (struct labeller * l);
+};
+
+struct labeller {
+	struct label_ops *ops;
+	const void *private;
+};
+
+int label_init(void);
+void label_exit(void);
+
+int label_register_handler(const char *name, struct labeller *handler);
+
+struct labeller *label_get_handler(const char *name);
+
+int label_remove(struct device *dev);
+int label_read(struct device *dev, struct label **result,
+		uint64_t scan_sector);
+int label_write(struct device *dev, struct label *label);
+int label_verify(struct device *dev);
+struct label *label_create(struct labeller *labeller);
+void label_destroy(struct label *label);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/locking/.exported_symbols
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/locking/.exported_symbols
diff -N src/external/gpl2/lvm2tools/dist/lib/locking/.exported_symbols
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/locking/.exported_symbols	15 Jul 2008 13:49:41 -0000	1.1.1.1
@@ -0,0 +1,4 @@
+locking_init
+locking_end
+lock_resource
+reset_locking
Index: src/external/gpl2/lvm2tools/dist/lib/locking/Makefile.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/locking/Makefile.in
diff -N src/external/gpl2/lvm2tools/dist/lib/locking/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/locking/Makefile.in	12 Dec 2008 16:33:00 -0000	1.1.1.1.2.1
@@ -0,0 +1,31 @@
+#
+# Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
+# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+SOURCES = cluster_locking.c
+
+LIB_SHARED = liblvm2clusterlock.so
+LIB_VERSION = $(LIB_VERSION_LVM)
+
+include $(top_srcdir)/make.tmpl
+
+install install_cluster: liblvm2clusterlock.so
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
+		$(libdir)/liblvm2clusterlock.so.$(LIB_VERSION)
+	$(LN_S) -f liblvm2clusterlock.so.$(LIB_VERSION) \
+		$(libdir)/liblvm2clusterlock.so
+
Index: src/external/gpl2/lvm2tools/dist/lib/locking/cluster_locking.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/locking/cluster_locking.c
diff -N src/external/gpl2/lvm2tools/dist/lib/locking/cluster_locking.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/locking/cluster_locking.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,513 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Locking functions for LVM.
+ * The main purpose of this part of the library is to serialise LVM
+ * management operations across a cluster.
+ */
+
+#include "lib.h"
+#include "clvm.h"
+#include "lvm-string.h"
+#include "locking.h"
+#include "locking_types.h"
+
+#include <assert.h>
+#include <stddef.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#ifndef CLUSTER_LOCKING_INTERNAL
+int lock_resource(struct cmd_context *cmd, const char *resource, uint32_t flags);
+void locking_end(void);
+int locking_init(int type, struct config_tree *cf, uint32_t *flags);
+#endif
+
+typedef struct lvm_response {
+	char node[255];
+	char *response;
+	int status;
+	int len;
+} lvm_response_t;
+
+/*
+ * This gets stuck at the start of memory we allocate so we
+ * can sanity-check it at deallocation time
+ */
+#define LVM_SIGNATURE 0x434C564D
+
+/*
+ * NOTE: the LVMD uses the socket FD as the client ID, this means
+ * that any client that calls fork() will inherit the context of
+ * it's parent.
+ */
+static int _clvmd_sock = -1;
+
+/* FIXME Install SIGPIPE handler? */
+
+/* Open connection to the Cluster Manager daemon */
+static int _open_local_sock(void)
+{
+	int local_socket;
+	struct sockaddr_un sockaddr;
+
+	/* Open local socket */
+	if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
+		log_error("Local socket creation failed: %s", strerror(errno));
+		return -1;
+	}
+
+	memset(&sockaddr, 0, sizeof(sockaddr));
+	memcpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(CLVMD_SOCKNAME));
+
+	sockaddr.sun_family = AF_UNIX;
+
+	if (connect(local_socket,(struct sockaddr *) &sockaddr,
+		    sizeof(sockaddr))) {
+		int saved_errno = errno;
+
+		log_error("connect() failed on local socket: %s",
+			  strerror(errno));
+		if (close(local_socket))
+			stack;
+
+		errno = saved_errno;
+		return -1;
+	}
+
+	return local_socket;
+}
+
+/* Send a request and return the status */
+static int _send_request(char *inbuf, int inlen, char **retbuf)
+{
+	char outbuf[PIPE_BUF] __attribute((aligned(8)));
+	struct clvm_header *outheader = (struct clvm_header *) outbuf;
+	int len;
+	int off;
+	int buflen;
+	int err;
+
+	/* Send it to CLVMD */
+ rewrite:
+	if ( (err = write(_clvmd_sock, inbuf, inlen)) != inlen) {
+		if (err == -1 && errno == EINTR)
+			goto rewrite;
+		log_error("Error writing data to clvmd: %s", strerror(errno));
+		return 0;
+	}
+
+	/* Get the response */
+ reread:
+	if ((len = read(_clvmd_sock, outbuf, sizeof(struct clvm_header))) < 0) {
+		if (errno == EINTR)
+			goto reread;
+		log_error("Error reading data from clvmd: %s", strerror(errno));
+		return 0;
+	}
+
+	if (len == 0) {
+		log_error("EOF reading CLVMD");
+		errno = ENOTCONN;
+		return 0;
+	}
+
+	/* Allocate buffer */
+	buflen = len + outheader->arglen;
+	*retbuf = dm_malloc(buflen);
+	if (!*retbuf) {
+		errno = ENOMEM;
+		return 0;
+	}
+
+	/* Copy the header */
+	memcpy(*retbuf, outbuf, len);
+	outheader = (struct clvm_header *) *retbuf;
+
+	/* Read the returned values */
+	off = 1;		/* we've already read the first byte */
+	while (off <= outheader->arglen && len > 0) {
+		len = read(_clvmd_sock, outheader->args + off,
+			   buflen - off - offsetof(struct clvm_header, args));
+		if (len > 0)
+			off += len;
+	}
+
+	/* Was it an error ? */
+	if (outheader->status != 0) {
+		errno = outheader->status;
+
+		/* Only return an error here if there are no node-specific
+		   errors present in the message that might have more detail */
+		if (!(outheader->flags & CLVMD_FLAG_NODEERRS)) {
+			log_error("cluster request failed: %s", strerror(errno));
+			return 0;
+		}
+
+	}
+
+	return 1;
+}
+
+/* Build the structure header and parse-out wildcard node names */
+static void _build_header(struct clvm_header *head, int cmd, const char *node,
+			  int len)
+{
+	head->cmd = cmd;
+	head->status = 0;
+	head->flags = 0;
+	head->clientid = 0;
+	head->arglen = len;
+
+	if (node) {
+		/*
+		 * Allow a couple of special node names:
+		 * "*" for all nodes,
+		 * "." for the local node only
+		 */
+		if (strcmp(node, "*") == 0) {
+			head->node[0] = '\0';
+		} else if (strcmp(node, ".") == 0) {
+			head->node[0] = '\0';
+			head->flags = CLVMD_FLAG_LOCAL;
+		} else
+			strcpy(head->node, node);
+	} else
+		head->node[0] = '\0';
+}
+
+/*
+ * Send a message to a(or all) node(s) in the cluster and wait for replies
+ */
+static int _cluster_request(char cmd, const char *node, void *data, int len,
+			   lvm_response_t ** response, int *num)
+{
+	char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1] __attribute((aligned(8)));
+	char *inptr;
+	char *retbuf = NULL;
+	int status;
+	int i;
+	int num_responses = 0;
+	struct clvm_header *head = (struct clvm_header *) outbuf;
+	lvm_response_t *rarray;
+
+	*num = 0;
+
+	if (_clvmd_sock == -1)
+		_clvmd_sock = _open_local_sock();
+
+	if (_clvmd_sock == -1)
+		return 0;
+
+	_build_header(head, cmd, node, len);
+	memcpy(head->node + strlen(head->node) + 1, data, len);
+
+	status = _send_request(outbuf, sizeof(struct clvm_header) +
+			      strlen(head->node) + len, &retbuf);
+	if (!status)
+		goto out;
+
+	/* Count the number of responses we got */
+	head = (struct clvm_header *) retbuf;
+	inptr = head->args;
+	while (inptr[0]) {
+		num_responses++;
+		inptr += strlen(inptr) + 1;
+		inptr += sizeof(int);
+		inptr += strlen(inptr) + 1;
+	}
+
+	/*
+	 * Allocate response array.
+	 * With an extra pair of INTs on the front to sanity
+	 * check the pointer when we are given it back to free
+	 */
+	*response = dm_malloc(sizeof(lvm_response_t) * num_responses);
+	if (!*response) {
+		errno = ENOMEM;
+		status = 0;
+		goto out;
+	}
+
+	rarray = *response;
+
+	/* Unpack the response into an lvm_response_t array */
+	inptr = head->args;
+	i = 0;
+	while (inptr[0]) {
+		strcpy(rarray[i].node, inptr);
+		inptr += strlen(inptr) + 1;
+
+		memcpy(&rarray[i].status, inptr, sizeof(int));
+		inptr += sizeof(int);
+
+		rarray[i].response = dm_malloc(strlen(inptr) + 1);
+		if (rarray[i].response == NULL) {
+			/* Free up everything else and return error */
+			int j;
+			for (j = 0; j < i; j++)
+				dm_free(rarray[i].response);
+			free(*response);
+			errno = ENOMEM;
+			status = -1;
+			goto out;
+		}
+
+		strcpy(rarray[i].response, inptr);
+		rarray[i].len = strlen(inptr);
+		inptr += strlen(inptr) + 1;
+		i++;
+	}
+	*num = num_responses;
+	*response = rarray;
+
+      out:
+	if (retbuf)
+		dm_free(retbuf);
+
+	return status;
+}
+
+/* Free reply array */
+static int _cluster_free_request(lvm_response_t * response, int num)
+{
+	int i;
+
+	for (i = 0; i < num; i++) {
+		dm_free(response[i].response);
+	}
+
+	dm_free(response);
+
+	return 1;
+}
+
+static int _lock_for_cluster(unsigned char cmd, uint32_t flags, const char *name)
+{
+	int status;
+	int i;
+	char *args;
+	const char *node = "";
+	int len;
+	int saved_errno = errno;
+	lvm_response_t *response = NULL;
+	int num_responses;
+
+	assert(name);
+
+	len = strlen(name) + 3;
+	args = alloca(len);
+	strcpy(args + 2, name);
+
+	args[0] = flags & 0x7F; /* Maskoff lock flags */
+	args[1] = flags & 0xC0; /* Bitmap flags */
+
+	if (mirror_in_sync())
+		args[1] |= LCK_MIRROR_NOSYNC_MODE;
+
+	if (dmeventd_monitor_mode())
+		args[1] |= LCK_DMEVENTD_MONITOR_MODE;
+
+	/*
+	 * VG locks are just that: locks, and have no side effects
+	 * so we only need to do them on the local node because all
+	 * locks are cluster-wide.
+	 * Also, if the lock is exclusive it makes no sense to try to
+	 * acquire it on all nodes, so just do that on the local node too.
+	 * One exception, is that P_ locks /do/ get distributed across
+	 * the cluster because they might have side-effects.
+	 */
+	if (strncmp(name, "P_", 2) &&
+	    (cmd == CLVMD_CMD_LOCK_VG ||
+	     (flags & LCK_TYPE_MASK) == LCK_EXCL ||
+	     (flags & LCK_LOCAL) ||
+	     !(flags & LCK_CLUSTER_VG)))
+		node = ".";
+
+	status = _cluster_request(cmd, node, args, len,
+				  &response, &num_responses);
+
+	/* If any nodes were down then display them and return an error */
+	for (i = 0; i < num_responses; i++) {
+		if (response[i].status == EHOSTDOWN) {
+			log_error("clvmd not running on node %s",
+				  response[i].node);
+			status = 0;
+			errno = response[i].status;
+		} else if (response[i].status) {
+			log_error("Error locking on node %s: %s",
+				  response[i].node,
+				  response[i].response[0] ?
+				  	response[i].response :
+				  	strerror(response[i].status));
+			status = 0;
+			errno = response[i].status;
+		}
+	}
+
+	saved_errno = errno;
+	_cluster_free_request(response, num_responses);
+	errno = saved_errno;
+
+	return status;
+}
+
+/* API entry point for LVM */
+#ifdef CLUSTER_LOCKING_INTERNAL
+static int _lock_resource(struct cmd_context *cmd, const char *resource,
+			  uint32_t flags)
+#else
+int lock_resource(struct cmd_context *cmd, const char *resource, uint32_t flags)
+#endif
+{
+	char lockname[PATH_MAX];
+	int cluster_cmd = 0;
+	const char *lock_scope;
+	const char *lock_type = "";
+
+	assert(strlen(resource) < sizeof(lockname));
+	assert(resource);
+
+	switch (flags & LCK_SCOPE_MASK) {
+	case LCK_VG:
+		/* If the VG name is empty then lock the unused PVs */
+		if (*resource == '#' || (flags & LCK_CACHE))
+			dm_snprintf(lockname, sizeof(lockname), "P_%s",
+				    resource);
+		else
+			dm_snprintf(lockname, sizeof(lockname), "V_%s",
+				    resource);
+
+		lock_scope = "VG";
+		cluster_cmd = CLVMD_CMD_LOCK_VG;
+		flags &= LCK_TYPE_MASK;
+		break;
+
+	case LCK_LV:
+		cluster_cmd = CLVMD_CMD_LOCK_LV;
+		strcpy(lockname, resource);
+		lock_scope = "LV";
+		flags &= 0xffdf;	/* Mask off HOLD flag */
+		break;
+
+	default:
+		log_error("Unrecognised lock scope: %d",
+			  flags & LCK_SCOPE_MASK);
+		return 0;
+	}
+
+	switch(flags & LCK_TYPE_MASK) {
+	case LCK_UNLOCK:
+		lock_type = "UN";
+		break;
+	case LCK_NULL:
+		lock_type = "NL";
+		break;
+	case LCK_READ:
+		lock_type = "CR";
+		break;
+	case LCK_PREAD:
+		lock_type = "PR";
+		break;
+	case LCK_WRITE:
+		lock_type = "PW";
+		break;
+	case LCK_EXCL:
+		lock_type = "EX";
+		break;
+	default:
+		log_error("Unrecognised lock type: %u",
+			  flags & LCK_TYPE_MASK);
+		return 0;
+	}
+
+	/* If we are unlocking a clustered VG, then trigger remote metadata backups */
+	if (cluster_cmd == CLVMD_CMD_LOCK_VG &&
+	    ((flags & LCK_TYPE_MASK) == LCK_UNLOCK) &&
+	    (flags & LCK_CLUSTER_VG)) {
+		log_very_verbose("Requesing backup of VG metadata for %s", resource);
+		_lock_for_cluster(CLVMD_CMD_VG_BACKUP, LCK_CLUSTER_VG, resource);
+	}
+
+	log_very_verbose("Locking %s %s %s %s%s%s%s (0x%x)", lock_scope, lockname,
+			 lock_type,
+			 flags & LCK_NONBLOCK ? "" : "B",
+			 flags & LCK_HOLD ? "H" : "",
+			 flags & LCK_LOCAL ? "L" : "",
+			 flags & LCK_CLUSTER_VG ? "C" : "",
+			 flags);
+
+	/* Send a message to the cluster manager */
+	return _lock_for_cluster(cluster_cmd, flags, lockname);
+}
+
+#ifdef CLUSTER_LOCKING_INTERNAL
+static void _locking_end(void)
+#else
+void locking_end(void)
+#endif
+{
+	if (_clvmd_sock != -1 && close(_clvmd_sock))
+		stack;
+
+	_clvmd_sock = -1;
+}
+
+#ifdef CLUSTER_LOCKING_INTERNAL
+static void _reset_locking(void)
+#else
+void reset_locking(void)
+#endif
+{
+	if (close(_clvmd_sock))
+		stack;
+
+	_clvmd_sock = _open_local_sock();
+	if (_clvmd_sock == -1)
+		stack;
+}
+
+#ifdef CLUSTER_LOCKING_INTERNAL
+int init_cluster_locking(struct locking_type *locking, struct cmd_context *cmd)
+{
+	locking->lock_resource = _lock_resource;
+	locking->fin_locking = _locking_end;
+	locking->reset_locking = _reset_locking;
+	locking->flags = LCK_PRE_MEMLOCK | LCK_CLUSTERED;
+
+	_clvmd_sock = _open_local_sock();
+	if (_clvmd_sock == -1)
+		return 0;
+
+	return 1;
+}
+#else
+int locking_init(int type, struct config_tree *cf, uint32_t *flags)
+{
+	_clvmd_sock = _open_local_sock();
+	if (_clvmd_sock == -1)
+		return 0;
+
+	/* Ask LVM to lock memory before calling us */
+	*flags |= LCK_PRE_MEMLOCK;
+	*flags |= LCK_CLUSTERED;
+
+	return 1;
+}
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/locking/external_locking.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/locking/external_locking.c
diff -N src/external/gpl2/lvm2tools/dist/lib/locking/external_locking.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/locking/external_locking.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,95 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "locking_types.h"
+#include "defaults.h"
+#include "sharedlib.h"
+#include "toolcontext.h"
+
+static void *_locking_lib = NULL;
+static void (*_reset_fn) (void) = NULL;
+static void (*_end_fn) (void) = NULL;
+static int (*_lock_fn) (struct cmd_context * cmd, const char *resource,
+			uint32_t flags) = NULL;
+static int (*_init_fn) (int type, struct config_tree * cft,
+			uint32_t *flags) = NULL;
+
+static int _lock_resource(struct cmd_context *cmd, const char *resource,
+			  uint32_t flags)
+{
+	if (_lock_fn)
+		return _lock_fn(cmd, resource, flags);
+	else
+		return 0;
+}
+
+static void _fin_external_locking(void)
+{
+	if (_end_fn)
+		_end_fn();
+
+	dlclose(_locking_lib);
+
+	_locking_lib = NULL;
+	_init_fn = NULL;
+	_end_fn = NULL;
+	_lock_fn = NULL;
+	_reset_fn = NULL;
+}
+
+static void _reset_external_locking(void)
+{
+	if (_reset_fn)
+		_reset_fn();
+}
+
+int init_external_locking(struct locking_type *locking, struct cmd_context *cmd)
+{
+	const char *libname;
+
+	if (_locking_lib) {
+		log_error("External locking already initialised");
+		return 1;
+	}
+
+	locking->lock_resource = _lock_resource;
+	locking->fin_locking = _fin_external_locking;
+	locking->reset_locking = _reset_external_locking;
+	locking->flags = 0;
+
+	libname = find_config_tree_str(cmd, "global/locking_library",
+				       DEFAULT_LOCKING_LIB);
+
+	if (!(_locking_lib = load_shared_library(cmd, libname, "locking", 1)))
+		return_0;
+
+	/* Get the functions we need */
+	if (!(_init_fn = dlsym(_locking_lib, "locking_init")) ||
+	    !(_lock_fn = dlsym(_locking_lib, "lock_resource")) ||
+	    !(_reset_fn = dlsym(_locking_lib, "reset_locking")) ||
+	    !(_end_fn = dlsym(_locking_lib, "locking_end"))) {
+		log_error("Shared library %s does not contain locking "
+			  "functions", libname);
+		dlclose(_locking_lib);
+		_locking_lib = NULL;
+		return 0;
+	}
+
+	log_verbose("Loaded external locking library %s", libname);
+	return _init_fn(2, cmd->cft, &locking->flags);
+}
Index: src/external/gpl2/lvm2tools/dist/lib/locking/file_locking.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/locking/file_locking.c
diff -N src/external/gpl2/lvm2tools/dist/lib/locking/file_locking.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/locking/file_locking.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,308 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "locking.h"
+#include "locking_types.h"
+#include "activate.h"
+#include "config.h"
+#include "defaults.h"
+#include "lvm-file.h"
+#include "lvm-string.h"
+#include "lvmcache.h"
+
+#include <limits.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#include <signal.h>
+
+struct lock_list {
+	struct dm_list list;
+	int lf;
+	char *res;
+};
+
+static struct dm_list _lock_list;
+static char _lock_dir[NAME_LEN];
+
+static sig_t _oldhandler;
+static sigset_t _fullsigset, _intsigset;
+static volatile sig_atomic_t _handler_installed;
+
+static int _release_lock(const char *file, int unlock)
+{
+	struct lock_list *ll;
+	struct dm_list *llh, *llt;
+
+	struct stat buf1, buf2;
+
+	dm_list_iterate_safe(llh, llt, &_lock_list) {
+		ll = dm_list_item(llh, struct lock_list);
+
+		if (!file || !strcmp(ll->res, file)) {
+			dm_list_del(llh);
+			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) &&
+			    !fstat(ll->lf, &buf2) &&
+			    is_same_inode(buf1, buf2))
+				if (unlink(ll->res))
+					log_sys_error("unlink", ll->res);
+
+			if (close(ll->lf) < 0)
+				log_sys_error("close", ll->res);
+
+			dm_free(ll->res);
+			dm_free(llh);
+
+			if (file)
+				return 1;
+		}
+	}
+
+	return 0;
+}
+
+static void _fin_file_locking(void)
+{
+	_release_lock(NULL, 1);
+}
+
+static void _reset_file_locking(void)
+{
+	_release_lock(NULL, 0);
+}
+
+static void _remove_ctrl_c_handler()
+{
+	siginterrupt(SIGINT, 0);
+	if (!_handler_installed)
+		return;
+
+	_handler_installed = 0;
+
+	sigprocmask(SIG_SETMASK, &_fullsigset, NULL);
+	if (signal(SIGINT, _oldhandler) == SIG_ERR)
+		log_sys_error("signal", "_remove_ctrl_c_handler");
+}
+
+static void _trap_ctrl_c(int sig __attribute((unused)))
+{
+	_remove_ctrl_c_handler();
+	log_error("CTRL-c detected: giving up waiting for lock");
+}
+
+static void _install_ctrl_c_handler()
+{
+	_handler_installed = 1;
+
+	if ((_oldhandler = signal(SIGINT, _trap_ctrl_c)) == SIG_ERR) {
+		_handler_installed = 0;
+		return;
+	}
+
+	sigprocmask(SIG_SETMASK, &_intsigset, NULL);
+	siginterrupt(SIGINT, 1);
+}
+
+static int _lock_file(const char *file, uint32_t flags)
+{
+	int operation;
+	int r = 1;
+	int old_errno;
+
+	struct lock_list *ll;
+	struct stat buf1, buf2;
+	char state;
+
+	switch (flags & LCK_TYPE_MASK) {
+	case LCK_READ:
+		operation = LOCK_SH;
+		state = 'R';
+		break;
+	case LCK_WRITE:
+		operation = LOCK_EX;
+		state = 'W';
+		break;
+	case LCK_UNLOCK:
+		return _release_lock(file, 1);
+	default:
+		log_error("Unrecognised lock type: %d", flags & LCK_TYPE_MASK);
+		return 0;
+	}
+
+	if (!(ll = dm_malloc(sizeof(struct lock_list))))
+		return 0;
+
+	if (!(ll->res = dm_strdup(file))) {
+		dm_free(ll);
+		return 0;
+	}
+
+	ll->lf = -1;
+
+	log_very_verbose("Locking %s %c%c", ll->res, state,
+			 flags & LCK_NONBLOCK ? ' ' : 'B');
+	do {
+		if ((ll->lf > -1) && close(ll->lf))
+			log_sys_error("close", file);
+
+		if ((ll->lf = open(file, O_CREAT | O_APPEND | O_RDWR, 0777))
+		    < 0) {
+			log_sys_error("open", file);
+			goto err;
+		}
+
+		if ((flags & LCK_NONBLOCK))
+			operation |= LOCK_NB;
+		else
+			_install_ctrl_c_handler();
+
+		r = flock(ll->lf, operation);
+		old_errno = errno;
+		if (!(flags & LCK_NONBLOCK))
+			_remove_ctrl_c_handler();
+
+		if (r) {
+			errno = old_errno;
+			log_sys_error("flock", ll->res);
+			close(ll->lf);
+			goto err;
+		}
+
+		if (!stat(ll->res, &buf1) && !fstat(ll->lf, &buf2) &&
+		    is_same_inode(buf1, buf2))
+			break;
+	} while (!(flags & LCK_NONBLOCK));
+
+	dm_list_add(&_lock_list, &ll->list);
+	return 1;
+
+      err:
+	dm_free(ll->res);
+	dm_free(ll);
+	return 0;
+}
+
+static int _file_lock_resource(struct cmd_context *cmd, const char *resource,
+			       uint32_t flags)
+{
+	char lockfile[PATH_MAX];
+
+	switch (flags & LCK_SCOPE_MASK) {
+	case LCK_VG:
+		/* Skip cache refresh for VG_GLOBAL - the caller handles it */
+		if (strcmp(resource, VG_GLOBAL))
+			lvmcache_drop_metadata(resource);
+
+		/* LCK_CACHE does not require a real lock */
+		if (flags & LCK_CACHE)
+			break;
+
+		if (*resource == '#')
+			dm_snprintf(lockfile, sizeof(lockfile),
+				     "%s/P_%s", _lock_dir, resource + 1);
+		else
+			dm_snprintf(lockfile, sizeof(lockfile),
+				     "%s/V_%s", _lock_dir, resource);
+
+		if (!_lock_file(lockfile, flags))
+			return_0;
+		break;
+	case LCK_LV:
+		switch (flags & LCK_TYPE_MASK) {
+		case LCK_UNLOCK:
+			log_very_verbose("Unlocking LV %s", resource);
+			if (!lv_resume_if_active(cmd, resource))
+				return 0;
+			break;
+		case LCK_NULL:
+			log_very_verbose("Locking LV %s (NL)", resource);
+			if (!lv_deactivate(cmd, resource))
+				return 0;
+			break;
+		case LCK_READ:
+			log_very_verbose("Locking LV %s (R)", resource);
+			if (!lv_activate_with_filter(cmd, resource, 0))
+				return 0;
+			break;
+		case LCK_PREAD:
+			log_very_verbose("Locking LV %s (PR) - ignored", resource);
+			break;
+		case LCK_WRITE:
+			log_very_verbose("Locking LV %s (W)", resource);
+			if (!lv_suspend_if_active(cmd, resource))
+				return 0;
+			break;
+		case LCK_EXCL:
+			log_very_verbose("Locking LV %s (EX)", resource);
+			if (!lv_activate_with_filter(cmd, resource, 1))
+				return 0;
+			break;
+		default:
+			break;
+		}
+		break;
+	default:
+		log_error("Unrecognised lock scope: %d",
+			  flags & LCK_SCOPE_MASK);
+		return 0;
+	}
+
+	return 1;
+}
+
+int init_file_locking(struct locking_type *locking, struct cmd_context *cmd)
+{
+	locking->lock_resource = _file_lock_resource;
+	locking->reset_locking = _reset_file_locking;
+	locking->fin_locking = _fin_file_locking;
+	locking->flags = 0;
+
+	/* Get lockfile directory from config file */
+	strncpy(_lock_dir, find_config_tree_str(cmd, "global/locking_dir",
+						DEFAULT_LOCK_DIR),
+		sizeof(_lock_dir));
+
+	if (!dm_create_dir(_lock_dir))
+		return 0;
+
+	/* Trap a read-only file system */
+	if ((access(_lock_dir, R_OK | W_OK | X_OK) == -1) && (errno == EROFS))
+		return 0;
+
+	dm_list_init(&_lock_list);
+
+	if (sigfillset(&_intsigset) || sigfillset(&_fullsigset)) {
+		log_sys_error("sigfillset", "init_file_locking");
+		return 0;
+	}
+
+	if (sigdelset(&_intsigset, SIGINT)) {
+		log_sys_error("sigdelset", "init_file_locking");
+		return 0;
+	}
+
+	return 1;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/locking/locking.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/locking/locking.c
diff -N src/external/gpl2/lvm2tools/dist/lib/locking/locking.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/locking/locking.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,472 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "locking.h"
+#include "locking_types.h"
+#include "lvm-string.h"
+#include "activate.h"
+#include "toolcontext.h"
+#include "memlock.h"
+#include "defaults.h"
+#include "lvmcache.h"
+
+#include <assert.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <unistd.h>
+
+static struct locking_type _locking;
+static sigset_t _oldset;
+
+static int _vg_lock_count = 0;		/* Number of locks held */
+static int _vg_write_lock_held = 0;	/* VG write lock held? */
+static int _signals_blocked = 0;
+
+static volatile sig_atomic_t _sigint_caught = 0;
+static volatile sig_atomic_t _handler_installed;
+static struct sigaction _oldhandler;
+static int _oldmasked;
+
+static void _catch_sigint(int unused __attribute__((unused)))
+{
+	_sigint_caught = 1;
+}
+
+int sigint_caught(void) {
+	return _sigint_caught;
+}
+
+void sigint_clear(void)
+{
+	_sigint_caught = 0;
+}
+
+/*
+ * Temporarily allow keyboard interrupts to be intercepted and noted;
+ * saves interrupt handler state for sigint_restore().  Users should
+ * use the sigint_caught() predicate to check whether interrupt was
+ * requested and act appropriately.  Interrupt flags are never
+ * cleared automatically by this code, but the tools clear the flag
+ * before running each command in lvm_run_command().  All other places
+ * where the flag needs to be cleared need to call sigint_clear().
+ */
+
+void sigint_allow(void)
+{
+	struct sigaction handler;
+	sigset_t sigs;
+
+	/*
+	 * Do not overwrite the backed-up handler data -
+	 * just increase nesting count.
+	 */
+	if (_handler_installed) {
+		_handler_installed++;
+		return;
+	}
+
+	/* Grab old sigaction for SIGINT: shall not fail. */
+	sigaction(SIGINT, NULL, &handler);
+	handler.sa_flags &= ~SA_RESTART; /* Clear restart flag */
+	handler.sa_handler = _catch_sigint;
+
+	_handler_installed = 1;
+
+	/* Override the signal handler: shall not fail. */
+	sigaction(SIGINT, &handler, &_oldhandler);
+
+	/* Unmask SIGINT.  Remember to mask it again on restore. */
+	sigprocmask(0, NULL, &sigs);
+	if ((_oldmasked = sigismember(&sigs, SIGINT))) {
+		sigdelset(&sigs, SIGINT);
+		sigprocmask(SIG_SETMASK, &sigs, NULL);
+	}
+}
+
+void sigint_restore(void)
+{
+	if (!_handler_installed)
+		return;
+
+	if (_handler_installed > 1) {
+		_handler_installed--;
+		return;
+	}
+
+	/* Nesting count went down to 0. */
+	_handler_installed = 0;
+
+	if (_oldmasked) {
+		sigset_t sigs;
+		sigprocmask(0, NULL, &sigs);
+		sigaddset(&sigs, SIGINT);
+		sigprocmask(SIG_SETMASK, &sigs, NULL);
+	}
+
+	sigaction(SIGINT, &_oldhandler, NULL);
+}
+
+static void _block_signals(uint32_t flags __attribute((unused)))
+{
+	sigset_t set;
+
+	if (_signals_blocked)
+		return;
+
+	if (sigfillset(&set)) {
+		log_sys_error("sigfillset", "_block_signals");
+		return;
+	}
+
+	if (sigprocmask(SIG_SETMASK, &set, &_oldset)) {
+		log_sys_error("sigprocmask", "_block_signals");
+		return;
+	}
+
+	_signals_blocked = 1;
+
+	return;
+}
+
+static void _unblock_signals(void)
+{
+	/* Don't unblock signals while any locks are held */
+	if (!_signals_blocked || _vg_lock_count)
+		return;
+
+	if (sigprocmask(SIG_SETMASK, &_oldset, NULL)) {
+		log_sys_error("sigprocmask", "_block_signals");
+		return;
+	}
+
+	_signals_blocked = 0;
+
+	return;
+}
+
+static void _lock_memory(uint32_t flags)
+{
+	if (!(_locking.flags & LCK_PRE_MEMLOCK))
+		return;
+
+	if ((flags & (LCK_SCOPE_MASK | LCK_TYPE_MASK)) == LCK_LV_SUSPEND)
+		memlock_inc();
+}
+
+static void _unlock_memory(uint32_t flags)
+{
+	if (!(_locking.flags & LCK_PRE_MEMLOCK))
+		return;
+
+	if ((flags & (LCK_SCOPE_MASK | LCK_TYPE_MASK)) == LCK_LV_RESUME)
+		memlock_dec();
+}
+
+void reset_locking(void)
+{
+	int was_locked = _vg_lock_count;
+
+	_vg_lock_count = 0;
+	_vg_write_lock_held = 0;
+
+	_locking.reset_locking();
+
+	if (was_locked)
+		_unblock_signals();
+}
+
+static void _update_vg_lock_count(uint32_t flags)
+{
+	if ((flags & LCK_SCOPE_MASK) != LCK_VG)
+		return;
+
+	if ((flags & LCK_TYPE_MASK) == LCK_UNLOCK)
+		_vg_lock_count--;
+	else
+		_vg_lock_count++;
+
+	/* We don't bother to reset this until all VG locks are dropped */
+	if ((flags & LCK_TYPE_MASK) == LCK_WRITE)
+		_vg_write_lock_held = 1;
+	else if (!_vg_lock_count)
+		_vg_write_lock_held = 0;
+}
+
+/*
+ * Select a locking type
+ */
+int init_locking(int type, struct cmd_context *cmd)
+{
+	init_lockingfailed(0);
+
+	switch (type) {
+	case 0:
+		init_no_locking(&_locking, cmd);
+		log_warn("WARNING: Locking disabled. Be careful! "
+			  "This could corrupt your metadata.");
+		return 1;
+
+	case 1:
+		log_very_verbose("File-based locking selected.");
+		if (!init_file_locking(&_locking, cmd))
+			break;
+		return 1;
+
+#ifdef HAVE_LIBDL
+	case 2:
+		if (!cmd->is_static) {
+			log_very_verbose("External locking selected.");
+			if (init_external_locking(&_locking, cmd))
+				return 1;
+		}
+		if (!find_config_tree_int(cmd, "locking/fallback_to_clustered_locking",
+			    find_config_tree_int(cmd, "global/fallback_to_clustered_locking",
+						 DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING)))
+			break;
+#endif
+
+#ifdef CLUSTER_LOCKING_INTERNAL
+		log_very_verbose("Falling back to internal clustered locking.");
+		/* Fall through */
+
+	case 3:
+		log_very_verbose("Cluster locking selected.");
+		if (!init_cluster_locking(&_locking, cmd))
+			break;
+		return 1;
+#endif
+
+	default:
+		log_error("Unknown locking type requested.");
+		return 0;
+	}
+
+	if ((type == 2 || type == 3) &&
+	    find_config_tree_int(cmd, "locking/fallback_to_local_locking",
+	    	    find_config_tree_int(cmd, "global/fallback_to_local_locking",
+					 DEFAULT_FALLBACK_TO_LOCAL_LOCKING))) {
+		log_warn("WARNING: Falling back to local file-based locking.");
+		log_warn("Volume Groups with the clustered attribute will "
+			  "be inaccessible.");
+		if (init_file_locking(&_locking, cmd))
+			return 1;
+	}
+
+	if (!ignorelockingfailure())
+		return 0;
+
+	/* FIXME Ensure only read ops are permitted */
+	log_verbose("Locking disabled - only read operations permitted.");
+
+	init_no_locking(&_locking, cmd);
+	init_lockingfailed(1);
+
+	return 1;
+}
+
+void fin_locking(void)
+{
+	_locking.fin_locking();
+}
+
+/*
+ * Does the LVM1 driver know of this VG name?
+ */
+int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname)
+{
+	struct stat info;
+	char path[PATH_MAX];
+
+	/* We'll allow operations on orphans */
+	if (is_orphan_vg(vgname))
+		return 1;
+
+	/* LVM1 is only present in 2.4 kernels. */
+	if (strncmp(cmd->kernel_vsn, "2.4.", 4))
+		return 1;
+
+	if (dm_snprintf(path, sizeof(path), "%s/lvm/VGs/%s", cmd->proc_dir,
+			 vgname) < 0) {
+		log_error("LVM1 proc VG pathname too long for %s", vgname);
+		return 0;
+	}
+
+	if (stat(path, &info) == 0) {
+		log_error("%s exists: Is the original LVM driver using "
+			  "this volume group?", path);
+		return 0;
+	} else if (errno != ENOENT && errno != ENOTDIR) {
+		log_sys_error("stat", path);
+		return 0;
+	}
+
+	return 1;
+}
+
+/*
+ * VG locking is by VG name.
+ * FIXME This should become VG uuid.
+ */
+static int _lock_vol(struct cmd_context *cmd, const char *resource, uint32_t flags)
+{
+	int ret = 0;
+
+	_block_signals(flags);
+	_lock_memory(flags);
+
+	assert(resource);
+
+	if (!*resource) {
+		log_error("Internal error: Use of P_orphans is deprecated.");
+		return 0;
+	}
+
+	if (*resource == '#' && (flags & LCK_CACHE)) {
+		log_error("Internal error: P_%s referenced", resource);
+		return 0;
+	}
+
+	if ((ret = _locking.lock_resource(cmd, resource, flags))) {
+		if ((flags & LCK_SCOPE_MASK) == LCK_VG &&
+		    !(flags & LCK_CACHE)) {
+			if ((flags & LCK_TYPE_MASK) == LCK_UNLOCK)
+				lvmcache_unlock_vgname(resource);
+			else
+				lvmcache_lock_vgname(resource, (flags & LCK_TYPE_MASK)
+								== LCK_READ);
+		}
+
+		_update_vg_lock_count(flags);
+	}
+
+	_unlock_memory(flags);
+	_unblock_signals();
+
+	return ret;
+}
+
+int lock_vol(struct cmd_context *cmd, const char *vol, uint32_t flags)
+{
+	char resource[258] __attribute((aligned(8)));
+
+	if (flags == LCK_NONE) {
+		log_debug("Internal error: %s: LCK_NONE lock requested", vol);
+		return 1;
+	}
+
+	switch (flags & LCK_SCOPE_MASK) {
+	case LCK_VG:
+		/* Lock VG to change on-disk metadata. */
+		/* If LVM1 driver knows about the VG, it can't be accessed. */
+		if (!check_lvm1_vg_inactive(cmd, vol))
+			return 0;
+	case LCK_LV:
+		/* Suspend LV if it's active. */
+		strncpy(resource, vol, sizeof(resource));
+		break;
+	default:
+		log_error("Unrecognised lock scope: %d",
+			  flags & LCK_SCOPE_MASK);
+		return 0;
+	}
+
+	if (!_lock_vol(cmd, resource, flags))
+		return 0;
+
+	/*
+	 * If a real lock was acquired (i.e. not LCK_CACHE),
+	 * perform an immediate unlock unless LCK_HOLD was requested.
+	 */
+	if (!(flags & LCK_CACHE) && !(flags & LCK_HOLD) &&
+	    ((flags & LCK_TYPE_MASK) != LCK_UNLOCK)) {
+		if (!_lock_vol(cmd, resource,
+			       (flags & ~LCK_TYPE_MASK) | LCK_UNLOCK))
+			return 0;
+	}
+
+	return 1;
+}
+
+/* Unlock list of LVs */
+int resume_lvs(struct cmd_context *cmd, struct dm_list *lvs)
+{
+	struct lv_list *lvl;
+
+	dm_list_iterate_items(lvl, lvs)
+		resume_lv(cmd, lvl->lv);
+
+	return 1;
+}
+
+/* Lock a list of LVs */
+int suspend_lvs(struct cmd_context *cmd, struct dm_list *lvs)
+{
+	struct dm_list *lvh;
+	struct lv_list *lvl;
+
+	dm_list_iterate_items(lvl, lvs) {
+		if (!suspend_lv(cmd, lvl->lv)) {
+			log_error("Failed to suspend %s", lvl->lv->name);
+			dm_list_uniterate(lvh, lvs, &lvl->list) {
+				lvl = dm_list_item(lvh, struct lv_list);
+				resume_lv(cmd, lvl->lv);
+			}
+
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+/* Lock a list of LVs */
+int activate_lvs(struct cmd_context *cmd, struct dm_list *lvs, unsigned exclusive)
+{
+	struct dm_list *lvh;
+	struct lv_list *lvl;
+
+	dm_list_iterate_items(lvl, lvs) {
+		if (!exclusive) {
+			if (!activate_lv(cmd, lvl->lv)) {
+				log_error("Failed to activate %s", lvl->lv->name);
+				return 0;
+			}
+		} else if (!activate_lv_excl(cmd, lvl->lv)) {
+			log_error("Failed to activate %s", lvl->lv->name);
+			dm_list_uniterate(lvh, lvs, &lvl->list) {
+				lvl = dm_list_item(lvh, struct lv_list);
+				activate_lv(cmd, lvl->lv);
+			}
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+int vg_write_lock_held(void)
+{
+	return _vg_write_lock_held;
+}
+
+int locking_is_clustered(void)
+{
+	return (_locking.flags & LCK_CLUSTERED) ? 1 : 0;
+}
+
Index: src/external/gpl2/lvm2tools/dist/lib/locking/locking.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/locking/locking.h
diff -N src/external/gpl2/lvm2tools/dist/lib/locking/locking.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/locking/locking.h	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,145 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_LOCKING_H
+#define _LVM_LOCKING_H
+
+#include "uuid.h"
+#include "config.h"
+
+int init_locking(int type, struct cmd_context *cmd);
+void fin_locking(void);
+void reset_locking(void);
+int vg_write_lock_held(void);
+int locking_is_clustered(void);
+
+/*
+ * LCK_VG:
+ *   Lock/unlock on-disk volume group data.
+ *   Use VG_ORPHANS to lock all orphan PVs.
+ *   Use VG_GLOBAL as a global lock and to wipe the internal cache.
+ *   char *vol holds volume group name.
+ *   Set the LCK_CACHE flag to invalidate 'vol' in the internal cache.
+ *
+ * LCK_LV:
+ *   Lock/unlock an individual logical volume
+ *   char *vol holds lvid
+ */
+int lock_vol(struct cmd_context *cmd, const char *vol, uint32_t flags);
+
+/*
+ * Internal locking representation.
+ *   LCK_VG: Uses prefix V_ unless the vol begins with # (i.e. #global or #orphans)
+ *           or the LCK_CACHE flag is set when it uses the prefix P_.
+ * If LCK_CACHE is set, we do not take out a real lock.
+ */
+
+/*
+ * Does the LVM1 driver have this VG active?
+ */
+int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname);
+
+/*
+ * Lock type - these numbers are the same as VMS and the IBM DLM
+ */
+#define LCK_TYPE_MASK	0x00000007U
+
+#define LCK_NULL	0x00000000U	/* LCK$_NLMODE */
+#define LCK_READ	0x00000001U	/* LCK$_CRMODE */
+					/* LCK$_CWMODE */
+#define LCK_PREAD       0x00000003U	/* LCK$_PRMODE */
+#define LCK_WRITE	0x00000004U	/* LCK$_PWMODE */
+#define LCK_EXCL	0x00000005U	/* LCK$_EXMODE */
+#define LCK_UNLOCK      0x00000006U	/* This is ours */
+
+/*
+ * Lock scope
+ */
+#define LCK_SCOPE_MASK	0x00000008U
+#define LCK_VG		0x00000000U
+#define LCK_LV		0x00000008U
+
+/*
+ * Lock bits
+ */
+#define LCK_NONBLOCK	0x00000010U	/* Don't block waiting for lock? */
+#define LCK_HOLD	0x00000020U	/* Hold lock when lock_vol returns? */
+#define LCK_LOCAL	0x00000040U	/* Don't propagate to other nodes */
+#define LCK_CLUSTER_VG	0x00000080U	/* VG is clustered */
+#define LCK_CACHE	0x00000100U	/* Operation on cache only using P_ lock */
+
+/*
+ * Additional lock bits for cluster communication
+ */
+#define LCK_MIRROR_NOSYNC_MODE	0x00000002U	/* Mirrors don't require sync */
+#define LCK_DMEVENTD_MONITOR_MODE	0x00000004U	/* Register with dmeventd */
+
+/*
+ * Special cases of VG locks.
+ */
+#define VG_ORPHANS	"#orphans"
+#define VG_GLOBAL	"#global"
+
+/*
+ * Common combinations
+ */
+#define LCK_NONE		(LCK_VG | LCK_NULL)
+
+#define LCK_VG_READ		(LCK_VG | LCK_READ | LCK_HOLD)
+#define LCK_VG_WRITE		(LCK_VG | LCK_WRITE | LCK_HOLD)
+#define LCK_VG_UNLOCK		(LCK_VG | LCK_UNLOCK)
+#define LCK_VG_DROP_CACHE	(LCK_VG | LCK_WRITE | LCK_CACHE)
+
+#define LCK_LV_EXCLUSIVE	(LCK_LV | LCK_EXCL | LCK_NONBLOCK)
+#define LCK_LV_SUSPEND		(LCK_LV | LCK_WRITE | LCK_NONBLOCK)
+#define LCK_LV_RESUME		(LCK_LV | LCK_UNLOCK | LCK_NONBLOCK)
+#define LCK_LV_ACTIVATE		(LCK_LV | LCK_READ | LCK_NONBLOCK)
+#define LCK_LV_DEACTIVATE	(LCK_LV | LCK_NULL | LCK_NONBLOCK)
+
+#define LCK_LV_CLUSTERED(lv)	\
+	(vg_is_clustered((lv)->vg) ? LCK_CLUSTER_VG : 0)
+
+#define lock_lv_vol(cmd, lv, flags)	\
+	lock_vol(cmd, (lv)->lvid.s, flags | LCK_LV_CLUSTERED(lv))
+
+#define unlock_vg(cmd, vol)	lock_vol(cmd, vol, LCK_VG_UNLOCK)
+
+#define resume_lv(cmd, lv)	lock_lv_vol(cmd, lv, LCK_LV_RESUME)
+#define suspend_lv(cmd, lv)	lock_lv_vol(cmd, lv, LCK_LV_SUSPEND | LCK_HOLD)
+#define deactivate_lv(cmd, lv)	lock_lv_vol(cmd, lv, LCK_LV_DEACTIVATE)
+#define activate_lv(cmd, lv)	lock_lv_vol(cmd, lv, LCK_LV_ACTIVATE | LCK_HOLD)
+#define activate_lv_excl(cmd, lv)	\
+				lock_lv_vol(cmd, lv, LCK_LV_EXCLUSIVE | LCK_HOLD)
+#define activate_lv_local(cmd, lv)	\
+	lock_lv_vol(cmd, lv, LCK_LV_ACTIVATE | LCK_HOLD | LCK_LOCAL)
+#define deactivate_lv_local(cmd, lv)	\
+	lock_lv_vol(cmd, lv, LCK_LV_DEACTIVATE | LCK_LOCAL)
+#define drop_cached_metadata(vg)	\
+	lock_vol((vg)->cmd, (vg)->name, LCK_VG_DROP_CACHE)
+
+/* Process list of LVs */
+int suspend_lvs(struct cmd_context *cmd, struct dm_list *lvs);
+int resume_lvs(struct cmd_context *cmd, struct dm_list *lvs);
+int activate_lvs(struct cmd_context *cmd, struct dm_list *lvs, unsigned exclusive);
+
+/* Interrupt handling */
+void sigint_clear(void);
+void sigint_allow(void);
+void sigint_restore(void);
+int sigint_caught(void);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/locking/locking_types.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/locking/locking_types.h
diff -N src/external/gpl2/lvm2tools/dist/lib/locking/locking_types.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/locking/locking_types.h	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,47 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "metadata.h"
+#include "config.h"
+
+typedef int (*lock_resource_fn) (struct cmd_context * cmd, const char *resource,
+				 uint32_t flags);
+
+typedef void (*fin_lock_fn) (void);
+typedef void (*reset_lock_fn) (void);
+
+#define LCK_PRE_MEMLOCK	0x00000001	/* Is memlock() needed before calls? */
+#define LCK_CLUSTERED	0x00000002
+
+struct locking_type {
+	uint32_t flags;
+	lock_resource_fn lock_resource;
+
+	reset_lock_fn reset_locking;
+	fin_lock_fn fin_locking;
+};
+
+/*
+ * Locking types
+ */
+int init_no_locking(struct locking_type *locking, struct cmd_context *cmd);
+
+int init_file_locking(struct locking_type *locking, struct cmd_context *cmd);
+
+int init_external_locking(struct locking_type *locking, struct cmd_context *cmd);
+
+int init_cluster_locking(struct locking_type *locking, struct cmd_context *cmd);
Index: src/external/gpl2/lvm2tools/dist/lib/locking/no_locking.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/locking/no_locking.c
diff -N src/external/gpl2/lvm2tools/dist/lib/locking/no_locking.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/locking/no_locking.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,79 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "locking.h"
+#include "locking_types.h"
+#include "lvm-string.h"
+#include "activate.h"
+
+#include <signal.h>
+
+/*
+ * No locking
+ */
+
+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,
+			     uint32_t flags)
+{
+	switch (flags & LCK_SCOPE_MASK) {
+	case LCK_VG:
+		break;
+	case LCK_LV:
+		switch (flags & LCK_TYPE_MASK) {
+		case LCK_NULL:
+			return lv_deactivate(cmd, resource);
+		case LCK_UNLOCK:
+			return lv_resume_if_active(cmd, resource);
+		case LCK_READ:
+			return lv_activate_with_filter(cmd, resource, 0);
+		case LCK_WRITE:
+			return lv_suspend_if_active(cmd, resource);
+		case LCK_EXCL:
+			return lv_activate_with_filter(cmd, resource, 1);
+		default:
+			break;
+		}
+		break;
+	default:
+		log_error("Unrecognised lock scope: %d",
+			  flags & LCK_SCOPE_MASK);
+		return 0;
+	}
+
+	return 1;
+}
+
+int init_no_locking(struct locking_type *locking, struct cmd_context *cmd __attribute((unused)))
+{
+	locking->lock_resource = _no_lock_resource;
+	locking->reset_locking = _no_reset_locking;
+	locking->fin_locking = _no_fin_locking;
+	locking->flags = LCK_CLUSTERED;
+
+	return 1;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/log/log.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/log/log.c
diff -N src/external/gpl2/lvm2tools/dist/lib/log/log.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/log/log.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,299 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "device.h"
+#include "memlock.h"
+#include "lvm-string.h"
+#include "lvm-file.h"
+#include "defaults.h"
+
+#include <stdarg.h>
+#include <syslog.h>
+
+static FILE *_log_file;
+static struct device _log_dev;
+static struct str_list _log_dev_alias;
+
+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_suppress = 0;
+static char _msg_prefix[30] = "  ";
+static int _already_logging = 0;
+
+static lvm2_log_fn_t _lvm2_log_fn = NULL;
+
+void init_log_fn(lvm2_log_fn_t log_fn)
+{
+	if (log_fn)
+		_lvm2_log_fn = log_fn;
+	else
+		_lvm2_log_fn = NULL;
+}
+
+void init_log_file(const char *log_file, int append)
+{
+	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)
+{
+	int open_flags = append ? 0 : O_TRUNC;
+
+	dev_create_file(log_file, &_log_dev, &_log_dev_alias, 1);
+	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)
+{
+	openlog("lvm", LOG_PID, facility);
+	_syslog = 1;
+}
+
+int log_suppress(int suppress)
+{
+	int old_suppress = _log_suppress;
+
+	_log_suppress = suppress;
+
+	return old_suppress;
+}
+
+void release_log_memory(void)
+{
+	if (!_log_direct)
+		return;
+
+	dm_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) {
+		if (dm_fclose(_log_file)) {
+			if (errno)
+			      fprintf(stderr, "failed to write log file: %s\n",
+				      strerror(errno));
+			else
+			      fprintf(stderr, "failed to write log file\n");
+
+		}
+		_log_to_file = 0;
+	}
+}
+
+void fin_syslog()
+{
+	if (_syslog)
+		closelog();
+	_syslog = 0;
+}
+
+void init_msg_prefix(const char *prefix)
+{
+	strncpy(_msg_prefix, prefix, sizeof(_msg_prefix));
+	_msg_prefix[sizeof(_msg_prefix) - 1] = '\0';
+}
+
+void init_indent(int indent)
+{
+	_indent = indent;
+}
+
+void print_log(int level, const char *file, int line, const char *format, ...)
+{
+	va_list ap;
+	char buf[1024], buf2[4096], locn[4096];
+	int bufused, n;
+	const char *message;
+	const char *trformat;		/* Translated format string */
+	int use_stderr = level & _LOG_STDERR;
+
+	level &= ~_LOG_STDERR;
+
+	if (_log_suppress == 2)
+		return;
+
+	if (level <= _LOG_ERR)
+		init_error_message_produced(1);
+
+	trformat = _(format);
+
+	if (_lvm2_log_fn) {
+		va_start(ap, format);
+		n = vsnprintf(buf2, sizeof(buf2) - 1, trformat, ap);
+		va_end(ap);
+
+		if (n < 0) {
+			fprintf(stderr, _("vsnprintf failed: skipping external "
+					"logging function"));
+			goto log_it;
+		}
+
+		buf2[sizeof(buf2) - 1] = '\0';
+		message = &buf2[0];
+
+		_lvm2_log_fn(level, file, line, message);
+
+		return;
+	}
+
+      log_it:
+	if (!_log_suppress) {
+		if (verbose_level() > _LOG_DEBUG)
+			dm_snprintf(locn, sizeof(locn), "#%s:%d ",
+				     file, line);
+		else
+			locn[0] = '\0';
+
+		va_start(ap, format);
+		switch (level) {
+		case _LOG_DEBUG:
+			if (!strcmp("<backtrace>", format) &&
+			    verbose_level() <= _LOG_DEBUG)
+				break;
+			if (verbose_level() >= _LOG_DEBUG) {
+				fprintf(stderr, "%s%s%s", locn, log_command_name(),
+					_msg_prefix);
+				if (_indent)
+					fprintf(stderr, "      ");
+				vfprintf(stderr, trformat, ap);
+				fputc('\n', stderr);
+			}
+			break;
+
+		case _LOG_INFO:
+			if (verbose_level() >= _LOG_INFO) {
+				fprintf(stderr, "%s%s%s", locn, log_command_name(),
+					_msg_prefix);
+				if (_indent)
+					fprintf(stderr, "    ");
+				vfprintf(stderr, trformat, ap);
+				fputc('\n', stderr);
+			}
+			break;
+		case _LOG_NOTICE:
+			if (verbose_level() >= _LOG_NOTICE) {
+				fprintf(stderr, "%s%s%s", locn, log_command_name(),
+					_msg_prefix);
+				if (_indent)
+					fprintf(stderr, "  ");
+				vfprintf(stderr, trformat, ap);
+				fputc('\n', stderr);
+			}
+			break;
+		case _LOG_WARN:
+			if (verbose_level() >= _LOG_WARN) {
+				fprintf(use_stderr ? stderr : stdout, "%s%s",
+					log_command_name(), _msg_prefix);
+				vfprintf(use_stderr ? stderr : stdout, trformat, ap);
+				fputc('\n', use_stderr ? stderr : stdout);
+			}
+			break;
+		case _LOG_ERR:
+			if (verbose_level() >= _LOG_ERR) {
+				fprintf(stderr, "%s%s%s", locn, log_command_name(),
+					_msg_prefix);
+				vfprintf(stderr, trformat, ap);
+				fputc('\n', stderr);
+			}
+			break;
+		case _LOG_FATAL:
+		default:
+			if (verbose_level() >= _LOG_FATAL) {
+				fprintf(stderr, "%s%s%s", locn, log_command_name(),
+					_msg_prefix);
+				vfprintf(stderr, trformat, ap);
+				fputc('\n', stderr);
+			}
+			break;
+		}
+		va_end(ap);
+	}
+
+	if (level > debug_level())
+		return;
+
+	if (_log_to_file && (_log_while_suspended || !memlock())) {
+		fprintf(_log_file, "%s:%d %s%s", file, line, log_command_name(),
+			_msg_prefix);
+
+		va_start(ap, format);
+		vfprintf(_log_file, trformat, ap);
+		va_end(ap);
+
+		fprintf(_log_file, "\n");
+		fflush(_log_file);
+	}
+
+	if (_syslog && (_log_while_suspended || !memlock())) {
+		va_start(ap, format);
+		vsyslog(level, trformat, 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 = dm_snprintf(buf, sizeof(buf) - bufused - 1,
+				      "%s:%d %s%s", file, line, log_command_name(),
+				      _msg_prefix)) == -1)
+			goto done;
+
+		bufused += n;
+
+		va_start(ap, format);
+		n = vsnprintf(buf + bufused - 1, sizeof(buf) - bufused - 1,
+			      trformat, 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;
+	}
+}
Index: src/external/gpl2/lvm2tools/dist/lib/log/log.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/log/log.h
diff -N src/external/gpl2/lvm2tools/dist/lib/log/log.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/log/log.h	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,81 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_LOG_H
+#define _LVM_LOG_H
+
+/*
+ * printf()-style macros to use for messages:
+ *
+ *   log_error   - always print to stderr.
+ *   log_print   - always print to stdout.  Use this instead of printf.
+ *   log_verbose - print to stdout if verbose is set (-v)
+ *   log_very_verbose - print to stdout if verbose is set twice (-vv)
+ *   log_debug   - print to stdout if verbose is set three times (-vvv)
+ *
+ * In addition, messages will be logged to file or syslog if they
+ * are more serious than the log level specified with the log/debug_level
+ * parameter in the configuration file.  These messages get the file
+ * and line number prepended.  'stack' (without arguments) can be used 
+ * to log this information at debug level.
+ *
+ * log_sys_error and log_sys_very_verbose are for errors from system calls
+ * e.g. log_sys_error("stat", filename);
+ *      /dev/fd/7: stat failed: No such file or directory
+ *
+ */
+
+#include <stdio.h>		/* FILE */
+#include <string.h>		/* strerror() */
+#include <errno.h>
+
+#define _LOG_STDERR 128 /* force things to go to stderr, even if loglevel
+			   would make them go to stdout */
+#define _LOG_DEBUG 7
+#define _LOG_INFO 6
+#define _LOG_NOTICE 5
+#define _LOG_WARN 4
+#define _LOG_ERR 3
+#define _LOG_FATAL 2
+
+#define log_debug(x...) plog(_LOG_DEBUG, x)
+#define log_info(x...) plog(_LOG_INFO, x)
+#define log_notice(x...) plog(_LOG_NOTICE, x)
+#define log_warn(x...) plog(_LOG_WARN | _LOG_STDERR, x)
+#define log_err(x...) plog(_LOG_ERR, x)
+#define log_fatal(x...) plog(_LOG_FATAL, x)
+
+#define stack log_debug("<backtrace>")	/* Backtrace on error */
+#define log_very_verbose(args...) log_info(args)
+#define log_verbose(args...) log_notice(args)
+#define log_print(args...) plog(_LOG_WARN, args)
+#define log_error(args...) log_err(args)
+
+/* 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))
+
+#define return_0	do { stack; return 0; } while (0)
+#define return_NULL	do { stack; return NULL; } while (0)
+#define goto_out	do { stack; goto out; } while (0)
+#define goto_bad	do { stack; goto bad; } while (0)
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/log/lvm-logging.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/log/lvm-logging.h
diff -N src/external/gpl2/lvm2tools/dist/lib/log/lvm-logging.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/log/lvm-logging.h	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.3
@@ -0,0 +1,55 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_LOGGING_H
+#define _LVM_LOGGING_H
+
+void print_log(int level, const char *file, int line, const char *format, ...)
+    __attribute__ ((format(printf, 4, 5)));
+
+#define plog(l, x...) print_log(l, __FILE__, __LINE__ , ## x)
+
+#include "log.h"
+
+typedef void (*lvm2_log_fn_t) (int level, const char *file, int line,
+			       const char *message);
+
+void init_log_fn(lvm2_log_fn_t log_fn);
+
+void init_indent(int indent);
+void init_msg_prefix(const char *prefix);
+
+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);
+
+int error_message_produced(void);
+
+/* Suppress messages to stdout/stderr (1) or everywhere (2) */
+/* Returns previous setting */
+int log_suppress(int suppress);
+
+/* Suppress messages to syslog */
+void syslog_suppress(int suppress);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/metadata/lv_alloc.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/metadata/lv_alloc.h
diff -N src/external/gpl2/lvm2tools/dist/lib/metadata/lv_alloc.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/metadata/lv_alloc.h	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,83 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_LV_ALLOC_H
+
+struct lv_segment *alloc_lv_segment(struct dm_pool *mem,
+				    const struct segment_type *segtype,
+				    struct logical_volume *lv,
+				    uint32_t le, uint32_t len,
+				    uint32_t status,
+				    uint32_t stripe_size,
+				    struct logical_volume *log_lv,
+				    uint32_t area_count,
+				    uint32_t area_len,
+				    uint32_t chunk_size,
+				    uint32_t region_size,
+				    uint32_t extents_copied);
+
+struct lv_segment *alloc_snapshot_seg(struct logical_volume *lv,
+				      uint32_t status, uint32_t old_le_count);
+
+int set_lv_segment_area_pv(struct lv_segment *seg, uint32_t area_num,
+			   struct physical_volume *pv, uint32_t pe);
+int set_lv_segment_area_lv(struct lv_segment *seg, uint32_t area_num,
+			   struct logical_volume *lv, uint32_t le,
+			   uint32_t flags);
+int move_lv_segment_area(struct lv_segment *seg_to, uint32_t area_to,
+			 struct lv_segment *seg_from, uint32_t area_from);
+void release_lv_segment_area(struct lv_segment *seg, uint32_t s,
+			     uint32_t area_reduction);
+
+struct alloc_handle;
+struct alloc_handle *allocate_extents(struct volume_group *vg,
+				      struct logical_volume *lv,
+                                      const struct segment_type *segtype,
+                                      uint32_t stripes,
+                                      uint32_t mirrors, uint32_t log_count,
+				      uint32_t extents,
+                                      struct dm_list *allocatable_pvs,
+				      alloc_policy_t alloc,
+				      struct dm_list *parallel_areas);
+
+int lv_add_segment(struct alloc_handle *ah,
+		   uint32_t first_area, uint32_t num_areas,
+		   struct logical_volume *lv,
+                   const struct segment_type *segtype,
+                   uint32_t stripe_size,
+                   uint32_t status,   
+		   uint32_t region_size,
+                   struct logical_volume *log_lv);
+
+int lv_add_mirror_areas(struct alloc_handle *ah,
+			struct logical_volume *lv, uint32_t le,
+			uint32_t region_size);
+int lv_add_mirror_lvs(struct logical_volume *lv,
+		      struct logical_volume **sub_lvs,
+		      uint32_t num_extra_areas,
+		      uint32_t status, uint32_t region_size);
+
+int lv_add_log_segment(struct alloc_handle *ah, struct logical_volume *log_lv);
+int lv_add_virtual_segment(struct logical_volume *lv, uint32_t status,
+                           uint32_t extents, const struct segment_type *segtype);
+
+void alloc_destroy(struct alloc_handle *ah);
+
+struct dm_list *build_parallel_areas_from_lv(struct cmd_context *cmd,
+					  struct logical_volume *lv);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/metadata/lv_manip.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/metadata/lv_manip.c
diff -N src/external/gpl2/lvm2tools/dist/lib/metadata/lv_manip.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/metadata/lv_manip.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.3
@@ -0,0 +1,2689 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "metadata.h"
+#include "locking.h"
+#include "pv_map.h"
+#include "lvm-string.h"
+#include "toolcontext.h"
+#include "lv_alloc.h"
+#include "pv_alloc.h"
+#include "display.h"
+#include "segtype.h"
+#include "archiver.h"
+#include "activate.h"
+
+struct lv_names {
+	const char *old;
+	const char *new;
+};
+
+int add_seg_to_segs_using_this_lv(struct logical_volume *lv,
+				  struct lv_segment *seg)
+{
+	struct seg_list *sl;
+
+	dm_list_iterate_items(sl, &lv->segs_using_this_lv) {
+		if (sl->seg == seg) {
+			sl->count++;
+			return 1;
+		}
+	}
+
+	log_very_verbose("Adding %s:%" PRIu32 " as an user of %s",
+			 seg->lv->name, seg->le, lv->name);
+
+	if (!(sl = dm_pool_zalloc(lv->vg->cmd->mem, sizeof(*sl)))) {
+		log_error("Failed to allocate segment list");
+		return 0;
+	}
+
+	sl->count = 1;
+	sl->seg = seg;
+	dm_list_add(&lv->segs_using_this_lv, &sl->list);
+
+	return 1;
+}
+
+int remove_seg_from_segs_using_this_lv(struct logical_volume *lv,
+				       struct lv_segment *seg)
+{
+	struct seg_list *sl;
+
+	dm_list_iterate_items(sl, &lv->segs_using_this_lv) {
+		if (sl->seg != seg)
+			continue;
+		if (sl->count > 1)
+			sl->count--;
+		else {
+			log_very_verbose("%s:%" PRIu32 " is no longer a user "
+					 "of %s", seg->lv->name, seg->le,
+					 lv->name);
+			dm_list_del(&sl->list);
+		}
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * This is a function specialized for the common case where there is
+ * only one segment which uses the LV.
+ * e.g. the LV is a layer inserted by insert_layer_for_lv().
+ *
+ * In general, walk through lv->segs_using_this_lv.
+ */
+struct lv_segment *get_only_segment_using_this_lv(struct logical_volume *lv)
+{
+	struct seg_list *sl;
+
+	if (dm_list_size(&lv->segs_using_this_lv) != 1) {
+		log_error("%s is expected to have only one segment using it, "
+			  "while it has %d", lv->name,
+			  dm_list_size(&lv->segs_using_this_lv));
+		return NULL;
+	}
+
+	sl = dm_list_item(dm_list_first(&lv->segs_using_this_lv), struct seg_list);
+
+	if (sl->count != 1) {
+		log_error("%s is expected to have only one segment using it, "
+			  "while %s:%" PRIu32 " uses it %d times",
+			  lv->name, sl->seg->lv->name, sl->seg->le, sl->count);
+		return NULL;
+	}
+
+	return sl->seg;
+}
+
+/*
+ * PVs used by a segment of an LV
+ */
+struct seg_pvs {
+	struct dm_list list;
+
+	struct dm_list pvs;	/* struct pv_list */
+
+	uint32_t le;
+	uint32_t len;
+};
+
+static struct seg_pvs *_find_seg_pvs_by_le(struct dm_list *list, uint32_t le)
+{
+	struct seg_pvs *spvs;
+
+	dm_list_iterate_items(spvs, list)
+		if (le >= spvs->le && le < spvs->le + spvs->len)
+			return spvs;
+
+	return NULL;
+}
+
+/*
+ * Find first unused LV number.
+ */
+uint32_t find_free_lvnum(struct logical_volume *lv)
+{
+	int lvnum_used[MAX_RESTRICTED_LVS + 1];
+	uint32_t i = 0;
+	struct lv_list *lvl;
+	int lvnum;
+
+	memset(&lvnum_used, 0, sizeof(lvnum_used));
+
+	dm_list_iterate_items(lvl, &lv->vg->lvs) {
+		lvnum = lvnum_from_lvid(&lvl->lv->lvid);
+		if (lvnum <= MAX_RESTRICTED_LVS)
+			lvnum_used[lvnum] = 1;
+	}
+
+	while (lvnum_used[i])
+		i++;
+
+	/* FIXME What if none are free? */
+
+	return i;
+}
+
+/*
+ * All lv_segments get created here.
+ */
+struct lv_segment *alloc_lv_segment(struct dm_pool *mem,
+				    const struct segment_type *segtype,
+				    struct logical_volume *lv,
+				    uint32_t le, uint32_t len,
+				    uint32_t status,
+				    uint32_t stripe_size,
+				    struct logical_volume *log_lv,
+				    uint32_t area_count,
+				    uint32_t area_len,
+				    uint32_t chunk_size,
+				    uint32_t region_size,
+				    uint32_t extents_copied)
+{
+	struct lv_segment *seg;
+	uint32_t areas_sz = area_count * sizeof(*seg->areas);
+
+	if (!(seg = dm_pool_zalloc(mem, sizeof(*seg))))
+		return_NULL;
+
+	if (!(seg->areas = dm_pool_zalloc(mem, areas_sz))) {
+		dm_pool_free(mem, seg);
+		return_NULL;
+	}
+
+	if (!segtype) {
+		log_error("alloc_lv_segment: Missing segtype.");
+		return NULL;
+	}
+
+	seg->segtype = segtype;
+	seg->lv = lv;
+	seg->le = le;
+	seg->len = len;
+	seg->status = status;
+	seg->stripe_size = stripe_size;
+	seg->area_count = area_count;
+	seg->area_len = area_len;
+	seg->chunk_size = chunk_size;
+	seg->region_size = region_size;
+	seg->extents_copied = extents_copied;
+	seg->log_lv = log_lv;
+	dm_list_init(&seg->tags);
+
+	if (log_lv && !attach_mirror_log(seg, log_lv))
+		return_NULL;
+
+	return seg;
+}
+
+struct lv_segment *alloc_snapshot_seg(struct logical_volume *lv,
+				      uint32_t status, uint32_t old_le_count)
+{
+	struct lv_segment *seg;
+	const struct segment_type *segtype;
+
+	segtype = get_segtype_from_string(lv->vg->cmd, "snapshot");
+	if (!segtype) {
+		log_error("Failed to find snapshot segtype");
+		return NULL;
+	}
+
+	if (!(seg = alloc_lv_segment(lv->vg->cmd->mem, segtype, lv, old_le_count,
+				     lv->le_count - old_le_count, status, 0,
+				     NULL, 0, lv->le_count - old_le_count,
+				     0, 0, 0))) {
+		log_error("Couldn't allocate new snapshot segment.");
+		return NULL;
+	}
+
+	dm_list_add(&lv->segments, &seg->list);
+	lv->status |= VIRTUAL;
+
+	return seg;
+}
+
+void release_lv_segment_area(struct lv_segment *seg, uint32_t s,
+			     uint32_t area_reduction)
+{
+	if (seg_type(seg, s) == AREA_UNASSIGNED)
+		return;
+
+	if (seg_type(seg, s) == AREA_PV) {
+		if (release_pv_segment(seg_pvseg(seg, s), area_reduction) &&
+		    seg->area_len == area_reduction)
+			seg_type(seg, s) = AREA_UNASSIGNED;
+		return;
+	}
+
+	if (seg_lv(seg, s)->status & MIRROR_IMAGE) {
+		lv_reduce(seg_lv(seg, s), area_reduction);
+		return;
+	}
+
+	if (area_reduction == seg->area_len) {
+		log_very_verbose("Remove %s:%" PRIu32 "[%" PRIu32 "] from "
+				 "the top of LV %s:%" PRIu32,
+				 seg->lv->name, seg->le, s,
+				 seg_lv(seg, s)->name, seg_le(seg, s));
+
+		remove_seg_from_segs_using_this_lv(seg_lv(seg, s), seg);
+		seg_lv(seg, s) = NULL;
+		seg_le(seg, s) = 0;
+		seg_type(seg, s) = AREA_UNASSIGNED;
+	}
+}
+
+/*
+ * Move a segment area from one segment to another
+ */
+int move_lv_segment_area(struct lv_segment *seg_to, uint32_t area_to,
+			 struct lv_segment *seg_from, uint32_t area_from)
+{
+	struct physical_volume *pv;
+	struct logical_volume *lv;
+	uint32_t pe, le;
+
+	switch (seg_type(seg_from, area_from)) {
+	case AREA_PV:
+		pv = seg_pv(seg_from, area_from);
+		pe = seg_pe(seg_from, area_from);
+
+		release_lv_segment_area(seg_from, area_from,
+					seg_from->area_len);
+		release_lv_segment_area(seg_to, area_to, seg_to->area_len);
+
+		if (!set_lv_segment_area_pv(seg_to, area_to, pv, pe))
+			return_0;
+
+		break;
+
+	case AREA_LV:
+		lv = seg_lv(seg_from, area_from);
+		le = seg_le(seg_from, area_from);
+
+		release_lv_segment_area(seg_from, area_from,
+					seg_from->area_len);
+		release_lv_segment_area(seg_to, area_to, seg_to->area_len);
+
+		if (!set_lv_segment_area_lv(seg_to, area_to, lv, le, 0))
+			return_0;
+
+		break;
+
+	case AREA_UNASSIGNED:
+		release_lv_segment_area(seg_to, area_to, seg_to->area_len);
+	}
+
+	return 1;
+}
+
+/*
+ * Link part of a PV to an LV segment.
+ */
+int set_lv_segment_area_pv(struct lv_segment *seg, uint32_t area_num,
+			   struct physical_volume *pv, uint32_t pe)
+{
+	seg->areas[area_num].type = AREA_PV;
+
+	if (!(seg_pvseg(seg, area_num) =
+	      assign_peg_to_lvseg(pv, pe, seg->area_len, seg, area_num)))
+		return_0;
+
+	return 1;
+}
+
+/*
+ * Link one LV segment to another.  Assumes sizes already match.
+ */
+int set_lv_segment_area_lv(struct lv_segment *seg, uint32_t area_num,
+			   struct logical_volume *lv, uint32_t le,
+			   uint32_t flags)
+{
+	log_very_verbose("Stack %s:%" PRIu32 "[%" PRIu32 "] on LV %s:%" PRIu32,
+			 seg->lv->name, seg->le, area_num, lv->name, le);
+
+	seg->areas[area_num].type = AREA_LV;
+	seg_lv(seg, area_num) = lv;
+	seg_le(seg, area_num) = le;
+	lv->status |= flags;
+
+	if (!add_seg_to_segs_using_this_lv(lv, seg))
+		return_0;
+
+	return 1;
+}
+
+/*
+ * Prepare for adding parallel areas to an existing segment.
+ */
+static int _lv_segment_add_areas(struct logical_volume *lv,
+				 struct lv_segment *seg,
+				 uint32_t new_area_count)
+{
+	struct lv_segment_area *newareas;
+	uint32_t areas_sz = new_area_count * sizeof(*newareas);
+
+	if (!(newareas = dm_pool_zalloc(lv->vg->cmd->mem, areas_sz)))
+		return_0;
+
+	memcpy(newareas, seg->areas, seg->area_count * sizeof(*seg->areas));
+
+	seg->areas = newareas;
+	seg->area_count = new_area_count;
+
+	return 1;
+}
+
+/*
+ * Reduce the size of an lv_segment.  New size can be zero.
+ */
+static int _lv_segment_reduce(struct lv_segment *seg, uint32_t reduction)
+{
+	uint32_t area_reduction, s;
+
+	/* Caller must ensure exact divisibility */
+	if (seg_is_striped(seg)) {
+		if (reduction % seg->area_count) {
+			log_error("Segment extent reduction %" PRIu32
+				  "not divisible by #stripes %" PRIu32,
+				  reduction, seg->area_count);
+			return 0;
+		}
+		area_reduction = (reduction / seg->area_count);
+	} else
+		area_reduction = reduction;
+
+	for (s = 0; s < seg->area_count; s++)
+		release_lv_segment_area(seg, s, area_reduction);
+
+	seg->len -= reduction;
+	seg->area_len -= area_reduction;
+
+	return 1;
+}
+
+/*
+ * Entry point for all LV reductions in size.
+ */
+static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete)
+{
+	struct lv_list *lvl;
+	struct lv_segment *seg;
+	uint32_t count = extents;
+	uint32_t reduction;
+
+	dm_list_iterate_back_items(seg, &lv->segments) {
+		if (!count)
+			break;
+
+		if (seg->len <= count) {
+			/* remove this segment completely */
+			/* FIXME Check this is safe */
+			if (seg->log_lv && !lv_remove(seg->log_lv))
+				return_0;
+			dm_list_del(&seg->list);
+			reduction = seg->len;
+		} else
+			reduction = count;
+
+		if (!_lv_segment_reduce(seg, reduction))
+			return_0;
+		count -= reduction;
+	}
+
+	lv->le_count -= extents;
+	lv->size = (uint64_t) lv->le_count * lv->vg->extent_size;
+
+	if (!delete)
+		return 1;
+
+	/* Remove the LV if it is now empty */
+	if (!lv->le_count) {
+		if (!(lvl = find_lv_in_vg(lv->vg, lv->name)))
+			return_0;
+
+		dm_list_del(&lvl->list);
+
+		if (!(lv->status & SNAPSHOT))
+			lv->vg->lv_count--;
+	} else if (lv->vg->fid->fmt->ops->lv_setup &&
+		   !lv->vg->fid->fmt->ops->lv_setup(lv->vg->fid, lv))
+		return_0;
+
+	return 1;
+}
+
+/*
+ * Empty an LV.
+ */
+int lv_empty(struct logical_volume *lv)
+{
+	return _lv_reduce(lv, lv->le_count, 0);
+}
+
+/*
+ * Empty an LV and add error segment.
+ */
+int replace_lv_with_error_segment(struct logical_volume *lv)
+{
+	uint32_t len = lv->le_count;
+
+	if (!lv_empty(lv))
+		return_0;
+
+	if (!lv_add_virtual_segment(lv, 0, len,
+				    get_segtype_from_string(lv->vg->cmd,
+							    "error")))
+		return_0;
+
+	return 1;
+}
+
+/*
+ * Remove given number of extents from LV.
+ */
+int lv_reduce(struct logical_volume *lv, uint32_t extents)
+{
+	return _lv_reduce(lv, extents, 1);
+}
+
+/*
+ * Completely remove an LV.
+ */
+int lv_remove(struct logical_volume *lv)
+{
+
+	if (!lv_reduce(lv, lv->le_count))
+		return_0;
+
+	return 1;
+}
+
+/*
+ * A set of contiguous physical extents allocated
+ */
+struct alloced_area {
+	struct dm_list list;
+
+	struct physical_volume *pv;
+	uint32_t pe;
+	uint32_t len;
+};
+
+/*
+ * Details of an allocation attempt
+ */
+struct alloc_handle {
+	struct cmd_context *cmd;
+	struct dm_pool *mem;
+
+	alloc_policy_t alloc;		/* Overall policy */
+	uint32_t area_count;		/* Number of parallel areas */
+	uint32_t area_multiple;		/* seg->len = area_len * area_multiple */
+	uint32_t log_count;		/* Number of parallel 1-extent logs */
+	uint32_t total_area_len;	/* Total number of parallel extents */
+
+	struct dm_list *parallel_areas;	/* PVs to avoid */
+
+	struct alloced_area log_area;	/* Extent used for log */
+	struct dm_list alloced_areas[0];	/* Lists of areas in each stripe */
+};
+
+static uint32_t calc_area_multiple(const struct segment_type *segtype,
+				   const uint32_t area_count)
+{
+	if (!segtype_is_striped(segtype) || !area_count)
+		return 1;
+
+	return area_count;
+}
+
+/*
+ * Preparation for a specific allocation attempt
+ */
+static struct alloc_handle *_alloc_init(struct cmd_context *cmd,
+					struct dm_pool *mem,
+					const struct segment_type *segtype,
+					alloc_policy_t alloc,
+					uint32_t mirrors,
+					uint32_t stripes,
+					uint32_t log_count,
+					struct dm_list *parallel_areas)
+{
+	struct alloc_handle *ah;
+	uint32_t s, area_count;
+
+	if (stripes > 1 && mirrors > 1) {
+		log_error("Striped mirrors are not supported yet");
+		return NULL;
+	}
+
+	if (log_count && stripes > 1) {
+		log_error("Can't mix striping with a mirror log yet.");
+		return NULL;
+	}
+
+	if (segtype_is_virtual(segtype))
+		area_count = 0;
+	else if (mirrors > 1)
+		area_count = mirrors;
+	else
+		area_count = stripes;
+
+	if (!(ah = dm_pool_zalloc(mem, sizeof(*ah) + sizeof(ah->alloced_areas[0]) * area_count))) {
+		log_error("allocation handle allocation failed");
+		return NULL;
+	}
+
+	if (segtype_is_virtual(segtype))
+		return ah;
+
+	ah->cmd = cmd;
+
+	if (!(ah->mem = dm_pool_create("allocation", 1024))) {
+		log_error("allocation pool creation failed");
+		return NULL;
+	}
+
+	ah->area_count = area_count;
+	ah->log_count = log_count;
+	ah->alloc = alloc;
+	ah->area_multiple = calc_area_multiple(segtype, area_count);
+
+	for (s = 0; s < ah->area_count; s++)
+		dm_list_init(&ah->alloced_areas[s]);
+
+	ah->parallel_areas = parallel_areas;
+
+	return ah;
+}
+
+void alloc_destroy(struct alloc_handle *ah)
+{
+	if (ah->mem)
+		dm_pool_destroy(ah->mem);
+}
+
+static int _log_parallel_areas(struct dm_pool *mem, struct dm_list *parallel_areas)
+{
+	struct seg_pvs *spvs;
+	struct pv_list *pvl;
+	char *pvnames;
+
+	if (!parallel_areas)
+		return 1;
+
+	if (!dm_pool_begin_object(mem, 256)) {
+		log_error("dm_pool_begin_object failed");
+		return 0;
+	}
+
+	dm_list_iterate_items(spvs, parallel_areas) {
+		dm_list_iterate_items(pvl, &spvs->pvs) {
+			if (!dm_pool_grow_object(mem, pv_dev_name(pvl->pv), strlen(pv_dev_name(pvl->pv)))) {
+				log_error("dm_pool_grow_object failed");
+				dm_pool_abandon_object(mem);
+				return 0;
+			}
+			if (!dm_pool_grow_object(mem, " ", 1)) {
+				log_error("dm_pool_grow_object failed");
+				dm_pool_abandon_object(mem);
+				return 0;
+			}
+		}
+
+		if (!dm_pool_grow_object(mem, "\0", 1)) {
+			log_error("dm_pool_grow_object failed");
+			dm_pool_abandon_object(mem);
+			return 0;
+		}
+
+		pvnames = dm_pool_end_object(mem);
+		log_debug("Parallel PVs at LE %" PRIu32 " length %" PRIu32 ": %s",
+			  spvs->le, spvs->len, pvnames);
+		dm_pool_free(mem, pvnames);
+	}
+
+	return 1;
+}
+
+static int _setup_alloced_segment(struct logical_volume *lv, uint32_t status,
+				  uint32_t area_count,
+				  uint32_t stripe_size,
+				  const struct segment_type *segtype,
+				  struct alloced_area *aa,
+				  uint32_t region_size,
+				  struct logical_volume *log_lv __attribute((unused)))
+{
+	uint32_t s, extents, area_multiple;
+	struct lv_segment *seg;
+
+	area_multiple = calc_area_multiple(segtype, area_count);
+
+	/* log_lv gets set up elsehere */
+	if (!(seg = alloc_lv_segment(lv->vg->cmd->mem, segtype, lv,
+				     lv->le_count,
+				     aa[0].len * area_multiple,
+				     status, stripe_size, NULL,
+				     area_count,
+				     aa[0].len, 0u, region_size, 0u))) {
+		log_error("Couldn't allocate new LV segment.");
+		return 0;
+	}
+
+	for (s = 0; s < area_count; s++)
+		if (!set_lv_segment_area_pv(seg, s, aa[s].pv, aa[s].pe))
+			return_0;
+
+	dm_list_add(&lv->segments, &seg->list);
+
+	extents = aa[0].len * area_multiple;
+	lv->le_count += extents;
+	lv->size += (uint64_t) extents *lv->vg->extent_size;
+
+	if (segtype_is_mirrored(segtype))
+		lv->status |= MIRRORED;
+
+	return 1;
+}
+
+static int _setup_alloced_segments(struct logical_volume *lv,
+				   struct dm_list *alloced_areas,
+				   uint32_t area_count,
+				   uint32_t status,
+				   uint32_t stripe_size,
+				   const struct segment_type *segtype,
+				   uint32_t region_size,
+				   struct logical_volume *log_lv)
+{
+	struct alloced_area *aa;
+
+	dm_list_iterate_items(aa, &alloced_areas[0]) {
+		if (!_setup_alloced_segment(lv, status, area_count,
+					    stripe_size, segtype, aa,
+					    region_size, log_lv))
+			return_0;
+	}
+
+	return 1;
+}
+
+/*
+ * This function takes a list of pv_areas and adds them to allocated_areas.
+ * If the complete area is not needed then it gets split.
+ * The part used is removed from the pv_map so it can't be allocated twice.
+ */
+static int _alloc_parallel_area(struct alloc_handle *ah, uint32_t needed,
+				struct pv_area **areas,
+				uint32_t *ix, struct pv_area *log_area)
+{
+	uint32_t area_len, remaining;
+	uint32_t s;
+	struct alloced_area *aa;
+
+	remaining = needed - *ix;
+	area_len = remaining / ah->area_multiple;
+
+	/* Reduce area_len to the smallest of the areas */
+	for (s = 0; s < ah->area_count; s++)
+		if (area_len > areas[s]->count)
+			area_len = areas[s]->count;
+
+	if (!(aa = dm_pool_alloc(ah->mem, sizeof(*aa) *
+			      (ah->area_count + (log_area ? 1 : 0))))) {
+		log_error("alloced_area allocation failed");
+		return 0;
+	}
+
+	for (s = 0; s < ah->area_count; s++) {
+		aa[s].pv = areas[s]->map->pv;
+		aa[s].pe = areas[s]->start;
+		aa[s].len = area_len;
+		dm_list_add(&ah->alloced_areas[s], &aa[s].list);
+	}
+
+	ah->total_area_len += area_len;
+
+	for (s = 0; s < ah->area_count; s++)
+		consume_pv_area(areas[s], area_len);
+
+	if (log_area) {
+		ah->log_area.pv = log_area->map->pv;
+		ah->log_area.pe = log_area->start;
+		ah->log_area.len = MIRROR_LOG_SIZE;	/* FIXME Calculate & check this */
+		consume_pv_area(log_area, ah->log_area.len);
+	}
+
+	*ix += area_len * ah->area_multiple;
+
+	return 1;
+}
+
+/*
+ * Call fn for each AREA_PV used by the LV segment at lv:le of length *max_seg_len.
+ * If any constituent area contains more than one segment, max_seg_len is
+ * reduced to cover only the first.
+ * fn should return 0 on error, 1 to continue scanning or >1 to terminate without error.
+ * In the last case, this function passes on the return code.
+ */
+static int _for_each_pv(struct cmd_context *cmd, struct logical_volume *lv,
+			uint32_t le, uint32_t len, uint32_t *max_seg_len,
+			uint32_t first_area, uint32_t max_areas,
+			int top_level_area_index,
+			int only_single_area_segments,
+			int (*fn)(struct cmd_context *cmd,
+				  struct pv_segment *peg, uint32_t s,
+				  void *data),
+			void *data)
+{
+	struct lv_segment *seg;
+	uint32_t s;
+	uint32_t remaining_seg_len, area_len, area_multiple;
+	int r = 1;
+
+	if (!(seg = find_seg_by_le(lv, le))) {
+		log_error("Failed to find segment for %s extent %" PRIu32,
+			  lv->name, le);
+		return 0;
+	}
+
+	/* Remaining logical length of segment */
+	remaining_seg_len = seg->len - (le - seg->le);
+
+	if (remaining_seg_len > len)
+		remaining_seg_len = len;
+
+	if (max_seg_len && *max_seg_len > remaining_seg_len)
+		*max_seg_len = remaining_seg_len;
+
+	area_multiple = calc_area_multiple(seg->segtype, seg->area_count);
+	area_len = remaining_seg_len / area_multiple ? : 1;
+
+	for (s = first_area;
+	     s < seg->area_count && (!max_areas || s <= max_areas);
+	     s++) {
+		if (seg_type(seg, s) == AREA_LV) {
+			if (!(r = _for_each_pv(cmd, seg_lv(seg, s),
+					       seg_le(seg, s) +
+					       (le - seg->le) / area_multiple,
+					       area_len, max_seg_len,
+					       only_single_area_segments ? 0 : 0,
+					       only_single_area_segments ? 1U : 0U,
+					       top_level_area_index != -1 ? top_level_area_index : (int) s,
+					       only_single_area_segments, fn,
+					       data)))
+				stack;
+		} else if (seg_type(seg, s) == AREA_PV)
+			if (!(r = fn(cmd, seg_pvseg(seg, s), top_level_area_index != -1 ? (uint32_t) top_level_area_index : s, data)))
+				stack;
+		if (r != 1)
+			return r;
+	}
+
+	/* FIXME only_single_area_segments used as workaround to skip log LV - needs new param? */
+	if (!only_single_area_segments && seg_is_mirrored(seg) && seg->log_lv) {
+		if (!(r = _for_each_pv(cmd, seg->log_lv, 0, MIRROR_LOG_SIZE,
+				       NULL, 0, 0, 0, only_single_area_segments,
+				       fn, data)))
+			stack;
+		if (r != 1)
+			return r;
+	}
+
+	/* FIXME Add snapshot cow LVs etc. */
+
+	return 1;
+}
+
+static int _comp_area(const void *l, const void *r)
+{
+	const struct pv_area *lhs = *((const struct pv_area **) l);
+	const struct pv_area *rhs = *((const struct pv_area **) r);
+
+	if (lhs->count < rhs->count)
+		return 1;
+
+	else if (lhs->count > rhs->count)
+		return -1;
+
+	return 0;
+}
+
+/*
+ * Search for pvseg that matches condition
+ */
+struct pv_match {
+	int (*condition)(struct pv_segment *pvseg, struct pv_area *pva);
+
+	struct pv_area **areas;
+	struct pv_area *pva;
+	uint32_t areas_size;
+	int s;	/* Area index of match */
+};
+
+/*
+ * Is PV area on the same PV?
+ */
+static int _is_same_pv(struct pv_segment *pvseg, struct pv_area *pva)
+{
+	if (pvseg->pv != pva->map->pv)
+		return 0;
+
+	return 1;
+}
+
+/*
+ * Is PV area contiguous to PV segment?
+ */
+static int _is_contiguous(struct pv_segment *pvseg, struct pv_area *pva)
+{
+	if (pvseg->pv != pva->map->pv)
+		return 0;
+
+	if (pvseg->pe + pvseg->len != pva->start)
+		return 0;
+
+	return 1;
+}
+
+static int _is_condition(struct cmd_context *cmd __attribute((unused)),
+			 struct pv_segment *pvseg, uint32_t s,
+			 void *data)
+{
+	struct pv_match *pvmatch = data;
+
+	if (!pvmatch->condition(pvseg, pvmatch->pva))
+		return 1;	/* Continue */
+
+	if (s >= pvmatch->areas_size)
+		return 1;
+
+	pvmatch->areas[s] = pvmatch->pva;
+
+	return 2;	/* Finished */
+}
+
+/*
+ * Is pva on same PV as any existing areas?
+ */
+static int _check_cling(struct cmd_context *cmd,
+			struct lv_segment *prev_lvseg, struct pv_area *pva,
+			struct pv_area **areas, uint32_t areas_size)
+{
+	struct pv_match pvmatch;
+	int r;
+
+	pvmatch.condition = _is_same_pv;
+	pvmatch.areas = areas;
+	pvmatch.areas_size = areas_size;
+	pvmatch.pva = pva;
+
+	/* FIXME Cope with stacks by flattening */
+	if (!(r = _for_each_pv(cmd, prev_lvseg->lv,
+			       prev_lvseg->le + prev_lvseg->len - 1, 1, NULL,
+			       0, 0, -1, 1,
+			       _is_condition, &pvmatch)))
+		stack;
+
+	if (r != 2)
+		return 0;
+
+	return 1;
+}
+
+/*
+ * Is pva contiguous to any existing areas or on the same PV?
+ */
+static int _check_contiguous(struct cmd_context *cmd,
+			     struct lv_segment *prev_lvseg, struct pv_area *pva,
+			     struct pv_area **areas, uint32_t areas_size)
+{
+	struct pv_match pvmatch;
+	int r;
+
+	pvmatch.condition = _is_contiguous;
+	pvmatch.areas = areas;
+	pvmatch.areas_size = areas_size;
+	pvmatch.pva = pva;
+
+	/* FIXME Cope with stacks by flattening */
+	if (!(r = _for_each_pv(cmd, prev_lvseg->lv,
+			       prev_lvseg->le + prev_lvseg->len - 1, 1, NULL,
+			       0, 0, -1, 1,
+			       _is_condition, &pvmatch)))
+		stack;
+
+	if (r != 2)
+		return 0;
+
+	return 1;
+}
+
+/*
+ * Choose sets of parallel areas to use, respecting any constraints.
+ */
+static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
+				struct dm_list *pvms, struct pv_area **areas,
+				uint32_t areas_size, unsigned can_split,
+				struct lv_segment *prev_lvseg,
+				uint32_t *allocated, uint32_t needed)
+{
+	struct pv_map *pvm;
+	struct pv_area *pva;
+	struct pv_list *pvl;
+	unsigned already_found_one = 0;
+	unsigned contiguous = 0, cling = 0, preferred_count = 0;
+	unsigned ix;
+	unsigned ix_offset = 0;	/* Offset for non-preferred allocations */
+	uint32_t max_parallel;	/* Maximum extents to allocate */
+	uint32_t next_le;
+	struct seg_pvs *spvs;
+	struct dm_list *parallel_pvs;
+	uint32_t free_pes;
+
+	/* Is there enough total space? */
+	free_pes = pv_maps_size(pvms);
+	if (needed - *allocated > free_pes) {
+		log_error("Insufficient free space: %" PRIu32 " extents needed,"
+			  " but only %" PRIu32 " available",
+			  needed - *allocated, free_pes);
+		return 0;
+	}
+
+	/* FIXME Select log PV appropriately if there isn't one yet */
+
+	/* Are there any preceding segments we must follow on from? */
+	if (prev_lvseg) {
+		ix_offset = prev_lvseg->area_count;
+		if ((alloc == ALLOC_CONTIGUOUS))
+			contiguous = 1;
+		else if ((alloc == ALLOC_CLING))
+			cling = 1;
+		else
+			ix_offset = 0;
+	}
+
+	/* FIXME This algorithm needs a lot of cleaning up! */
+	/* FIXME anywhere doesn't find all space yet */
+	/* ix_offset holds the number of allocations that must be contiguous */
+	/* ix holds the number of areas found on other PVs */
+	do {
+		ix = 0;
+		preferred_count = 0;
+
+		parallel_pvs = NULL;
+		max_parallel = needed;
+
+		/*
+		 * If there are existing parallel PVs, avoid them and reduce
+		 * the maximum we can allocate in one go accordingly.
+		 */
+		if (ah->parallel_areas) {
+			next_le = (prev_lvseg ? prev_lvseg->le + prev_lvseg->len : 0) + *allocated / ah->area_multiple;
+			dm_list_iterate_items(spvs, ah->parallel_areas) {
+				if (next_le >= spvs->le + spvs->len)
+					continue;
+
+				if (max_parallel > (spvs->le + spvs->len) * ah->area_multiple)
+					max_parallel = (spvs->le + spvs->len) * ah->area_multiple;
+				parallel_pvs = &spvs->pvs;
+				break;
+			}
+		}
+
+		/*
+		 * Put the smallest area of each PV that is at least the
+		 * size we need into areas array.  If there isn't one
+		 * that fits completely and we're allowed more than one
+		 * LV segment, then take the largest remaining instead.
+		 */
+		dm_list_iterate_items(pvm, pvms) {
+			if (dm_list_empty(&pvm->areas))
+				continue;	/* Next PV */
+
+			if (alloc != ALLOC_ANYWHERE) {
+				/* Don't allocate onto the log pv */
+				if (ah->log_count &&
+				    pvm->pv == ah->log_area.pv)
+					continue;	/* Next PV */
+
+				/* Avoid PVs used by existing parallel areas */
+				if (parallel_pvs)
+					dm_list_iterate_items(pvl, parallel_pvs)
+						if (pvm->pv == pvl->pv)
+							goto next_pv;
+			}
+
+			already_found_one = 0;
+			/* First area in each list is the largest */
+			dm_list_iterate_items(pva, &pvm->areas) {
+				if (contiguous) {
+					if (prev_lvseg &&
+					    _check_contiguous(ah->cmd,
+							      prev_lvseg,
+							      pva, areas,
+							      areas_size)) {
+						preferred_count++;
+						goto next_pv;
+					}
+					continue;
+				}
+
+				if (cling) {
+					if (prev_lvseg &&
+					    _check_cling(ah->cmd,
+							   prev_lvseg,
+							   pva, areas,
+							   areas_size)) {
+						preferred_count++;
+					}
+					goto next_pv;
+				}
+
+				/* Is it big enough on its own? */
+				if (pva->count * ah->area_multiple <
+				    max_parallel - *allocated &&
+				    ((!can_split && !ah->log_count) ||
+				     (already_found_one &&
+				      !(alloc == ALLOC_ANYWHERE))))
+					goto next_pv;
+
+				if (!already_found_one ||
+				    alloc == ALLOC_ANYWHERE) {
+					ix++;
+					already_found_one = 1;
+				}
+
+				areas[ix + ix_offset - 1] = pva;
+
+				goto next_pv;
+			}
+		next_pv:
+			if (ix >= areas_size)
+				break;
+		}
+
+		if ((contiguous || cling) && (preferred_count < ix_offset))
+			break;
+
+		/* Only allocate log_area the first time around */
+		if (ix + ix_offset < ah->area_count +
+			    ((ah->log_count && !ah->log_area.len) ?
+				ah->log_count : 0))
+			/* FIXME With ALLOC_ANYWHERE, need to split areas */
+			break;
+
+		/* sort the areas so we allocate from the biggest */
+		if (ix > 1)
+			qsort(areas + ix_offset, ix, sizeof(*areas),
+			      _comp_area);
+
+		/* First time around, use smallest area as log_area */
+		/* FIXME decide which PV to use at top of function instead */
+		if (!_alloc_parallel_area(ah, max_parallel, areas,
+					  allocated,
+					  (ah->log_count && !ah->log_area.len) ?
+						*(areas + ix_offset + ix - 1) :
+						NULL))
+			return_0;
+
+	} while (!contiguous && *allocated != needed && can_split);
+
+	return 1;
+}
+
+/*
+ * Allocate several segments, each the same size, in parallel.
+ * If mirrored_pv and mirrored_pe are supplied, it is used as
+ * the first area, and additional areas are allocated parallel to it.
+ */
+static int _allocate(struct alloc_handle *ah,
+		     struct volume_group *vg,
+		     struct logical_volume *lv,
+		     uint32_t new_extents,
+		     unsigned can_split,
+		     struct dm_list *allocatable_pvs)
+{
+	struct pv_area **areas;
+	uint32_t allocated = lv ? lv->le_count : 0;
+	uint32_t old_allocated;
+	struct lv_segment *prev_lvseg = NULL;
+	int r = 0;
+	struct dm_list *pvms;
+	uint32_t areas_size;
+	alloc_policy_t alloc;
+
+	if (allocated >= new_extents && !ah->log_count) {
+		log_error("_allocate called with no work to do!");
+		return 1;
+	}
+
+	if (ah->alloc == ALLOC_CONTIGUOUS)
+		can_split = 0;
+
+	if (lv && !dm_list_empty(&lv->segments))
+		prev_lvseg = dm_list_item(dm_list_last(&lv->segments),
+				       struct lv_segment);
+	/*
+	 * Build the sets of available areas on the pv's.
+	 */
+	if (!(pvms = create_pv_maps(ah->mem, vg, allocatable_pvs)))
+		return_0;
+
+	if (!_log_parallel_areas(ah->mem, ah->parallel_areas))
+		stack;
+
+	areas_size = dm_list_size(pvms);
+	if (areas_size && areas_size < (ah->area_count + ah->log_count)) {
+		if (ah->alloc != ALLOC_ANYWHERE) {
+			log_error("Not enough PVs with free space available "
+				  "for parallel allocation.");
+			log_error("Consider --alloc anywhere if desperate.");
+			return 0;
+		}
+		areas_size = ah->area_count + ah->log_count;
+	}
+
+	/* Upper bound if none of the PVs in prev_lvseg is in pvms */
+	/* FIXME Work size out properly */
+	if (prev_lvseg)
+		areas_size += prev_lvseg->area_count;
+
+	/* Allocate an array of pv_areas to hold the largest space on each PV */
+	if (!(areas = dm_malloc(sizeof(*areas) * areas_size))) {
+		log_err("Couldn't allocate areas array.");
+		return 0;
+	}
+
+	/* Attempt each defined allocation policy in turn */
+	for (alloc = ALLOC_CONTIGUOUS; alloc < ALLOC_INHERIT; alloc++) {
+		old_allocated = allocated;
+		if (!_find_parallel_space(ah, alloc, pvms, areas,
+					  areas_size, can_split,
+					  prev_lvseg, &allocated, new_extents))
+			goto_out;
+		if ((allocated == new_extents) || (ah->alloc == alloc) ||
+		    (!can_split && (allocated != old_allocated)))
+			break;
+	}
+
+	if (allocated != new_extents) {
+		log_error("Insufficient suitable %sallocatable extents "
+			  "for logical volume %s: %u more required",
+			  can_split ? "" : "contiguous ",
+			  lv ? lv->name : "",
+			  (new_extents - allocated) * ah->area_count
+			  / ah->area_multiple);
+		goto out;
+	}
+
+	if (ah->log_count && !ah->log_area.len) {
+		log_error("Insufficient extents for log allocation "
+			  "for logical volume %s.",
+			  lv ? lv->name : "");
+		goto out;
+	}
+
+	r = 1;
+
+      out:
+	dm_free(areas);
+	return r;
+}
+
+int lv_add_virtual_segment(struct logical_volume *lv, uint32_t status,
+			   uint32_t extents, const struct segment_type *segtype)
+{
+	struct lv_segment *seg;
+
+	if (!(seg = alloc_lv_segment(lv->vg->cmd->mem, segtype, lv,
+				     lv->le_count, extents, status, 0,
+				     NULL, 0, extents, 0, 0, 0))) {
+		log_error("Couldn't allocate new zero segment.");
+		return 0;
+	}
+
+	dm_list_add(&lv->segments, &seg->list);
+
+	lv->le_count += extents;
+	lv->size += (uint64_t) extents *lv->vg->extent_size;
+
+	lv->status |= VIRTUAL;
+
+	return 1;
+}
+
+/*
+ * Entry point for all extent allocations.
+ */
+struct alloc_handle *allocate_extents(struct volume_group *vg,
+				      struct logical_volume *lv,
+				      const struct segment_type *segtype,
+				      uint32_t stripes,
+				      uint32_t mirrors, uint32_t log_count,
+				      uint32_t extents,
+				      struct dm_list *allocatable_pvs,
+				      alloc_policy_t alloc,
+				      struct dm_list *parallel_areas)
+{
+	struct alloc_handle *ah;
+
+	if (segtype_is_virtual(segtype)) {
+		log_error("allocate_extents does not handle virtual segments");
+		return NULL;
+	}
+
+	if (vg->fid->fmt->ops->segtype_supported &&
+	    !vg->fid->fmt->ops->segtype_supported(vg->fid, segtype)) {
+		log_error("Metadata format (%s) does not support required "
+			  "LV segment type (%s).", vg->fid->fmt->name,
+			  segtype->name);
+		log_error("Consider changing the metadata format by running "
+			  "vgconvert.");
+		return NULL;
+	}
+
+	if (alloc == ALLOC_INHERIT)
+		alloc = vg->alloc;
+
+	if (!(ah = _alloc_init(vg->cmd, vg->cmd->mem, segtype, alloc, mirrors,
+			       stripes, log_count, parallel_areas)))
+		return_NULL;
+
+	if (!segtype_is_virtual(segtype) &&
+	    !_allocate(ah, vg, lv, (lv ? lv->le_count : 0) + extents,
+		       1, allocatable_pvs)) {
+		alloc_destroy(ah);
+		return_NULL;
+	}
+
+	return ah;
+}
+
+/*
+ * Add new segments to an LV from supplied list of areas.
+ */
+int lv_add_segment(struct alloc_handle *ah,
+		   uint32_t first_area, uint32_t num_areas,
+		   struct logical_volume *lv,
+		   const struct segment_type *segtype,
+		   uint32_t stripe_size,
+		   uint32_t status,
+		   uint32_t region_size,
+		   struct logical_volume *log_lv)
+{
+	if (!segtype) {
+		log_error("Missing segtype in lv_add_segment().");
+		return 0;
+	}
+
+	if (segtype_is_virtual(segtype)) {
+		log_error("lv_add_segment cannot handle virtual segments");
+		return 0;
+	}
+
+	if (!_setup_alloced_segments(lv, &ah->alloced_areas[first_area],
+				     num_areas, status,
+				     stripe_size, segtype,
+				     region_size, log_lv))
+		return_0;
+
+	if ((segtype->flags & SEG_CAN_SPLIT) && !lv_merge_segments(lv)) {
+		log_err("Couldn't merge segments after extending "
+			"logical volume.");
+		return 0;
+	}
+
+	if (lv->vg->fid->fmt->ops->lv_setup &&
+	    !lv->vg->fid->fmt->ops->lv_setup(lv->vg->fid, lv))
+		return_0;
+
+	return 1;
+}
+
+/*
+ * "mirror" segment type doesn't support split.
+ * So, when adding mirrors to linear LV segment, first split it,
+ * then convert it to "mirror" and add areas.
+ */
+static struct lv_segment *_convert_seg_to_mirror(struct lv_segment *seg,
+						 uint32_t region_size,
+						 struct logical_volume *log_lv)
+{
+	struct lv_segment *newseg;
+	uint32_t s;
+
+	if (!seg_is_striped(seg)) {
+		log_error("Can't convert non-striped segment to mirrored.");
+		return NULL;
+	}
+
+	if (seg->area_count > 1) {
+		log_error("Can't convert striped segment with multiple areas "
+			  "to mirrored.");
+		return NULL;
+	}
+
+	if (!(newseg = alloc_lv_segment(seg->lv->vg->cmd->mem,
+					get_segtype_from_string(seg->lv->vg->cmd, "mirror"),
+					seg->lv, seg->le, seg->len,
+					seg->status, seg->stripe_size,
+					log_lv,
+					seg->area_count, seg->area_len,
+					seg->chunk_size, region_size,
+					seg->extents_copied))) {
+		log_error("Couldn't allocate converted LV segment");
+		return NULL;
+	}
+
+	for (s = 0; s < seg->area_count; s++)
+		if (!move_lv_segment_area(newseg, s, seg, s))
+			return_NULL;
+
+	dm_list_add(&seg->list, &newseg->list);
+	dm_list_del(&seg->list);
+
+	return newseg;
+}
+
+/*
+ * Add new areas to mirrored segments
+ */
+int lv_add_mirror_areas(struct alloc_handle *ah,
+			struct logical_volume *lv, uint32_t le,
+			uint32_t region_size)
+{
+	struct alloced_area *aa;
+	struct lv_segment *seg;
+	uint32_t current_le = le;
+	uint32_t s, old_area_count, new_area_count;
+
+	dm_list_iterate_items(aa, &ah->alloced_areas[0]) {
+		if (!(seg = find_seg_by_le(lv, current_le))) {
+			log_error("Failed to find segment for %s extent %"
+				  PRIu32, lv->name, current_le);
+			return 0;
+		}
+
+		/* Allocator assures aa[0].len <= seg->area_len */
+		if (aa[0].len < seg->area_len) {
+			if (!lv_split_segment(lv, seg->le + aa[0].len)) {
+				log_error("Failed to split segment at %s "
+					  "extent %" PRIu32, lv->name, le);
+				return 0;
+			}
+		}
+
+		if (!seg_is_mirrored(seg) &&
+		    (!(seg = _convert_seg_to_mirror(seg, region_size, NULL))))
+			return_0;
+
+		old_area_count = seg->area_count;
+		new_area_count = old_area_count + ah->area_count;
+
+		if (!_lv_segment_add_areas(lv, seg, new_area_count))
+			return_0;
+
+		for (s = 0; s < ah->area_count; s++) {
+			if (!set_lv_segment_area_pv(seg, s + old_area_count,
+						    aa[s].pv, aa[s].pe))
+				return_0;
+		}
+
+		current_le += seg->area_len;
+	}
+
+	lv->status |= MIRRORED;
+
+	if (lv->vg->fid->fmt->ops->lv_setup &&
+	    !lv->vg->fid->fmt->ops->lv_setup(lv->vg->fid, lv))
+		return_0;
+
+	return 1;
+}
+
+/*
+ * Add mirror image LVs to mirrored segments
+ */
+int lv_add_mirror_lvs(struct logical_volume *lv,
+		      struct logical_volume **sub_lvs,
+		      uint32_t num_extra_areas,
+		      uint32_t status, uint32_t region_size)
+{
+	struct lv_segment *seg;
+	uint32_t old_area_count, new_area_count;
+	uint32_t m;
+	struct segment_type *mirror_segtype;
+
+	seg = first_seg(lv);
+
+	if (dm_list_size(&lv->segments) != 1 || seg_type(seg, 0) != AREA_LV) {
+		log_error("Mirror layer must be inserted before adding mirrors");
+		return_0;
+	}
+
+	mirror_segtype = get_segtype_from_string(lv->vg->cmd, "mirror");
+	if (seg->segtype != mirror_segtype)
+		if (!(seg = _convert_seg_to_mirror(seg, region_size, NULL)))
+			return_0;
+
+	if (region_size && region_size != seg->region_size) {
+		log_error("Conflicting region_size");
+		return 0;
+	}
+
+	old_area_count = seg->area_count;
+	new_area_count = old_area_count + num_extra_areas;
+
+	if (!_lv_segment_add_areas(lv, seg, new_area_count)) {
+		log_error("Failed to allocate widened LV segment for %s.",
+			  lv->name);
+		return 0;
+	}
+
+	for (m = 0; m < old_area_count; m++)
+		seg_lv(seg, m)->status |= status;
+
+	for (m = old_area_count; m < new_area_count; m++) {
+		if (!set_lv_segment_area_lv(seg, m, sub_lvs[m - old_area_count],
+					    0, status))
+			return_0;
+		sub_lvs[m - old_area_count]->status &= ~VISIBLE_LV;
+	}
+
+	lv->status |= MIRRORED;
+
+	return 1;
+}
+
+/*
+ * Turn an empty LV into a mirror log.
+ */
+int lv_add_log_segment(struct alloc_handle *ah, struct logical_volume *log_lv)
+{
+	struct lv_segment *seg;
+
+	if (dm_list_size(&log_lv->segments)) {
+		log_error("Log segments can only be added to an empty LV");
+		return 0;
+	}
+
+	if (!(seg = alloc_lv_segment(log_lv->vg->cmd->mem,
+				     get_segtype_from_string(log_lv->vg->cmd,
+							     "striped"),
+				     log_lv, 0, ah->log_area.len, MIRROR_LOG,
+				     0, NULL, 1, ah->log_area.len, 0, 0, 0))) {
+		log_error("Couldn't allocate new mirror log segment.");
+		return 0;
+	}
+
+	if (!set_lv_segment_area_pv(seg, 0, ah->log_area.pv, ah->log_area.pe))
+		return_0;
+
+	dm_list_add(&log_lv->segments, &seg->list);
+	log_lv->le_count += ah->log_area.len;
+	log_lv->size += (uint64_t) log_lv->le_count * log_lv->vg->extent_size;
+
+	if (log_lv->vg->fid->fmt->ops->lv_setup &&
+	    !log_lv->vg->fid->fmt->ops->lv_setup(log_lv->vg->fid, log_lv))
+		return_0;
+
+	return 1;
+}
+
+static int _lv_extend_mirror(struct alloc_handle *ah,
+			     struct logical_volume *lv,
+			     uint32_t extents, uint32_t first_area)
+{
+	struct lv_segment *seg;
+	uint32_t m, s;
+
+	seg = first_seg(lv);
+	for (m = first_area, s = 0; s < seg->area_count; s++) {
+		if (is_temporary_mirror_layer(seg_lv(seg, s))) {
+			if (!_lv_extend_mirror(ah, seg_lv(seg, s), extents, m))
+				return_0;
+			m += lv_mirror_count(seg_lv(seg, s));
+			continue;
+		}
+
+		if (!lv_add_segment(ah, m++, 1, seg_lv(seg, s),
+				    get_segtype_from_string(lv->vg->cmd,
+							    "striped"),
+				    0, 0, 0, NULL)) {
+			log_error("Aborting. Failed to extend %s.",
+				  seg_lv(seg, s)->name);
+			return 0;
+		}
+	}
+	seg->area_len += extents;
+	seg->len += extents;
+	lv->le_count += extents;
+	lv->size += (uint64_t) extents *lv->vg->extent_size;
+
+	return 1;
+}
+
+/*
+ * Entry point for single-step LV allocation + extension.
+ */
+int lv_extend(struct logical_volume *lv,
+	      const struct segment_type *segtype,
+	      uint32_t stripes, uint32_t stripe_size,
+	      uint32_t mirrors, uint32_t extents,
+	      struct physical_volume *mirrored_pv __attribute((unused)),
+	      uint32_t mirrored_pe __attribute((unused)),
+	      uint32_t status, struct dm_list *allocatable_pvs,
+	      alloc_policy_t alloc)
+{
+	int r = 1;
+	struct alloc_handle *ah;
+
+	if (segtype_is_virtual(segtype))
+		return lv_add_virtual_segment(lv, status, extents, segtype);
+
+	if (!(ah = allocate_extents(lv->vg, lv, segtype, stripes, mirrors, 0,
+				    extents, allocatable_pvs, alloc, NULL)))
+		return_0;
+
+	if (mirrors < 2) {
+		if (!lv_add_segment(ah, 0, ah->area_count, lv, segtype, stripe_size,
+			    status, 0, NULL))
+			goto_out;
+	} else {
+		if (!_lv_extend_mirror(ah, lv, extents, 0))
+			return_0;
+	}
+
+      out:
+	alloc_destroy(ah);
+	return r;
+}
+
+/*
+ * Minimal LV renaming function.
+ * Metadata transaction should be made by caller.
+ * Assumes new_name is allocated from cmd->mem pool.
+ */
+static int _rename_single_lv(struct logical_volume *lv, char *new_name)
+{
+	struct volume_group *vg = lv->vg;
+
+	if (find_lv_in_vg(vg, new_name)) {
+		log_error("Logical volume \"%s\" already exists in "
+			  "volume group \"%s\"", new_name, vg->name);
+		return 0;
+	}
+
+	if (lv->status & LOCKED) {
+		log_error("Cannot rename locked LV %s", lv->name);
+		return 0;
+	}
+
+	lv->name = new_name;
+
+	return 1;
+}
+
+/*
+ * Rename sub LV.
+ * 'lv_name_old' and 'lv_name_new' are old and new names of the main LV.
+ */
+static int _rename_sub_lv(struct cmd_context *cmd,
+			  struct logical_volume *lv,
+			  const char *lv_name_old, const char *lv_name_new)
+{
+	char *suffix, *new_name;
+	size_t len;
+
+	/*
+	 * A sub LV name starts with lv_name_old + '_'.
+	 * The suffix follows lv_name_old and includes '_'.
+	 */
+	len = strlen(lv_name_old);
+	if (strncmp(lv->name, lv_name_old, len) || lv->name[len] != '_') {
+		log_error("Cannot rename \"%s\": name format not recognized "
+			  "for internal LV \"%s\"",
+			  lv_name_old, lv->name);
+		return 0;
+	}
+	suffix = lv->name + len;
+
+	/*
+	 * Compose a new name for sub lv:
+	 *   e.g. new name is "lvol1_mlog"
+	 *        if the sub LV is "lvol0_mlog" and
+	 *        a new name for main LV is "lvol1"
+	 */
+	len = strlen(lv_name_new) + strlen(suffix) + 1;
+	new_name = dm_pool_alloc(cmd->mem, len);
+	if (!new_name) {
+		log_error("Failed to allocate space for new name");
+		return 0;
+	}
+	if (!dm_snprintf(new_name, len, "%s%s", lv_name_new, suffix)) {
+		log_error("Failed to create new name");
+		return 0;
+	}
+
+	/* Rename it */
+	return _rename_single_lv(lv, new_name);
+}
+
+/* Callback for _for_each_sub_lv */
+static int _rename_cb(struct cmd_context *cmd, struct logical_volume *lv,
+		      void *data)
+{
+	struct lv_names *lv_names = (struct lv_names *) data;
+
+	return _rename_sub_lv(cmd, lv, lv_names->old, lv_names->new);
+}
+
+/*
+ * Loop down sub LVs and call "func" for each.
+ * "func" is responsible to log necessary information on failure.
+ */
+static int _for_each_sub_lv(struct cmd_context *cmd, struct logical_volume *lv,
+			    int (*func)(struct cmd_context *cmd,
+					struct logical_volume *lv,
+					void *data),
+			    void *data)
+{
+	struct lv_segment *seg;
+	uint32_t s;
+
+	dm_list_iterate_items(seg, &lv->segments) {
+		if (seg->log_lv && !func(cmd, seg->log_lv, data))
+			return 0;
+		for (s = 0; s < seg->area_count; s++) {
+			if (seg_type(seg, s) != AREA_LV)
+				continue;
+			if (!func(cmd, seg_lv(seg, s), data))
+				return 0;
+			if (!_for_each_sub_lv(cmd, seg_lv(seg, s), func, data))
+				return 0;
+		}
+	}
+
+	return 1;
+}
+
+
+/*
+ * Core of LV renaming routine.
+ * VG must be locked by caller.
+ */
+int lv_rename(struct cmd_context *cmd, struct logical_volume *lv,
+	      const char *new_name)
+{
+	struct volume_group *vg = lv->vg;
+	struct lv_names lv_names;
+
+	/* rename is not allowed on sub LVs */
+	if (!lv_is_visible(lv)) {
+		log_error("Cannot rename internal LV \"%s\".", lv->name);
+		return 0;
+	}
+
+	if (find_lv_in_vg(vg, new_name)) {
+		log_error("Logical volume \"%s\" already exists in "
+			  "volume group \"%s\"", new_name, vg->name);
+		return 0;
+	}
+
+	if (lv->status & LOCKED) {
+		log_error("Cannot rename locked LV %s", lv->name);
+		return 0;
+	}
+
+	if (!archive(vg))
+		return 0;
+
+	/* rename sub LVs */
+	lv_names.old = lv->name;
+	lv_names.new = new_name;
+	if (!_for_each_sub_lv(cmd, lv, _rename_cb, (void *) &lv_names))
+		return 0;
+
+	/* rename main LV */
+	if (!(lv->name = dm_pool_strdup(cmd->mem, new_name))) {
+		log_error("Failed to allocate space for new name");
+		return 0;
+	}
+
+	log_verbose("Writing out updated volume group");
+	if (!vg_write(vg))
+		return 0;
+
+	backup(vg);
+
+	if (!suspend_lv(cmd, lv)) {
+		stack;
+		vg_revert(vg);
+		return 0;
+	}
+
+	if (!vg_commit(vg)) {
+		stack;
+		resume_lv(cmd, lv);
+		return 0;
+	}
+
+	resume_lv(cmd, lv);
+
+	return 1;
+}
+
+char *generate_lv_name(struct volume_group *vg, const char *format,
+		       char *buffer, size_t len)
+{
+	struct lv_list *lvl;
+	int high = -1, i;
+
+	dm_list_iterate_items(lvl, &vg->lvs) {
+		if (sscanf(lvl->lv->name, format, &i) != 1)
+			continue;
+
+		if (i > high)
+			high = i;
+	}
+
+	if (dm_snprintf(buffer, len, format, high + 1) < 0)
+		return NULL;
+
+	return buffer;
+}
+
+/*
+ * Create a new empty LV.
+ */
+struct logical_volume *lv_create_empty(const char *name,
+				       union lvid *lvid,
+				       uint32_t status,
+				       alloc_policy_t alloc,
+				       int import,
+				       struct volume_group *vg)
+{
+	struct format_instance *fi = vg->fid;
+	struct cmd_context *cmd = vg->cmd;
+	struct lv_list *ll = NULL;
+	struct logical_volume *lv;
+	char dname[NAME_LEN];
+
+	if (vg->max_lv && (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 (strstr(name, "%d") &&
+	    !(name = generate_lv_name(vg, name, dname, sizeof(dname)))) {
+		log_error("Failed to generate unique name for the new "
+			  "logical volume");
+		return NULL;
+	}
+
+	if (!import)
+		log_verbose("Creating logical volume %s", name);
+
+	if (!(ll = dm_pool_zalloc(cmd->mem, sizeof(*ll))) ||
+	    !(ll->lv = dm_pool_zalloc(cmd->mem, sizeof(*ll->lv)))) {
+		log_error("lv_list allocation failed");
+		if (ll)
+			dm_pool_free(cmd->mem, ll);
+		return NULL;
+	}
+
+	lv = ll->lv;
+	lv->vg = vg;
+
+	if (!(lv->name = dm_pool_strdup(cmd->mem, name))) {
+		log_error("lv name strdup failed");
+		if (ll)
+			dm_pool_free(cmd->mem, ll);
+		return NULL;
+	}
+
+	lv->status = status;
+	lv->alloc = alloc;
+	lv->read_ahead = vg->cmd->default_settings.read_ahead;
+	lv->major = -1;
+	lv->minor = -1;
+	lv->size = UINT64_C(0);
+	lv->le_count = 0;
+	lv->snapshot = NULL;
+	dm_list_init(&lv->snapshot_segs);
+	dm_list_init(&lv->segments);
+	dm_list_init(&lv->tags);
+	dm_list_init(&lv->segs_using_this_lv);
+
+	if (lvid)
+		lv->lvid = *lvid;
+
+	if (fi->fmt->ops->lv_setup && !fi->fmt->ops->lv_setup(fi, lv)) {
+		if (ll)
+			dm_pool_free(cmd->mem, ll);
+		return_NULL;
+	}
+
+	if (!import)
+		vg->lv_count++;
+
+	dm_list_add(&vg->lvs, &ll->list);
+
+	return lv;
+}
+
+static int _add_pvs(struct cmd_context *cmd, struct pv_segment *peg,
+		    uint32_t s __attribute((unused)), void *data)
+{
+	struct seg_pvs *spvs = (struct seg_pvs *) data;
+	struct pv_list *pvl;
+
+	/* Don't add again if it's already on list. */
+	if (find_pv_in_pv_list(&spvs->pvs, peg->pv))
+			return 1;
+
+	if (!(pvl = dm_pool_alloc(cmd->mem, sizeof(*pvl)))) {
+		log_error("pv_list allocation failed");
+		return 0;
+	}
+
+	pvl->pv = peg->pv;
+
+	dm_list_add(&spvs->pvs, &pvl->list);
+
+	return 1;
+}
+
+/*
+ * Construct dm_list of segments of LVs showing which PVs they use.
+ */
+struct dm_list *build_parallel_areas_from_lv(struct cmd_context *cmd,
+					  struct logical_volume *lv)
+{
+	struct dm_list *parallel_areas;
+	struct seg_pvs *spvs;
+	uint32_t current_le = 0;
+
+	if (!(parallel_areas = dm_pool_alloc(cmd->mem, sizeof(*parallel_areas)))) {
+		log_error("parallel_areas allocation failed");
+		return NULL;
+	}
+
+	dm_list_init(parallel_areas);
+
+	do {
+		if (!(spvs = dm_pool_zalloc(cmd->mem, sizeof(*spvs)))) {
+			log_error("allocation failed");
+			return NULL;
+		}
+
+		dm_list_init(&spvs->pvs);
+
+		spvs->le = current_le;
+		spvs->len = lv->le_count - current_le;
+
+		dm_list_add(parallel_areas, &spvs->list);
+
+		/* Find next segment end */
+		/* FIXME Unnecessary nesting! */
+		if (!_for_each_pv(cmd, lv, current_le, spvs->len, &spvs->len,
+				  0, 0, -1, 0, _add_pvs, (void *) spvs))
+			return_NULL;
+
+		current_le = spvs->le + spvs->len;
+	} while (current_le < lv->le_count);
+
+	/* FIXME Merge adjacent segments with identical PV lists (avoids need for contiguous allocation attempts between successful allocations) */
+
+	return parallel_areas;
+}
+
+int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
+		     const force_t force)
+{
+	struct volume_group *vg;
+	struct lvinfo info;
+	struct logical_volume *origin = NULL;
+
+	vg = lv->vg;
+
+	if (!vg_check_status(vg, LVM_WRITE))
+		return 0;
+
+	if (lv_is_origin(lv)) {
+		log_error("Can't remove logical volume \"%s\" under snapshot",
+			  lv->name);
+		return 0;
+	}
+
+	if (lv->status & MIRROR_IMAGE) {
+		log_error("Can't remove logical volume %s used by a mirror",
+			  lv->name);
+		return 0;
+	}
+
+	if (lv->status & MIRROR_LOG) {
+		log_error("Can't remove logical volume %s used as mirror log",
+			  lv->name);
+		return 0;
+	}
+
+	if (lv->status & LOCKED) {
+		log_error("Can't remove locked LV %s", lv->name);
+		return 0;
+	}
+
+	/* FIXME Ensure not referred to by another existing LVs */
+
+	if (lv_info(cmd, lv, &info, 1, 0)) {
+		if (info.open_count) {
+			log_error("Can't remove open logical volume \"%s\"",
+				  lv->name);
+			return 0;
+		}
+
+		/*
+		 * Check for confirmation prompts in the following cases:
+		 * 1) Clustered VG, and some remote nodes have the LV active
+		 * 2) Non-clustered VG, but LV active locally
+		 */
+		if (vg_is_clustered(vg) && !activate_lv_excl(cmd, lv) &&
+		    (force == PROMPT)) {
+			if (yes_no_prompt("Logical volume \"%s\" is active on other "
+					  "cluster nodes.  Really remove? [y/n]: ",
+					  lv->name) == 'n') {
+				log_print("Logical volume \"%s\" not removed",
+					  lv->name);
+				return 0;
+			}
+		} else if (info.exists && (force == PROMPT)) {
+			 if (yes_no_prompt("Do you really want to remove active "
+					   "logical volume \"%s\"? [y/n]: ",
+					   lv->name) == 'n') {
+				log_print("Logical volume \"%s\" not removed",
+					  lv->name);
+				return 0;
+			 }
+		}
+	}
+
+	if (!archive(vg))
+		return 0;
+
+	/* FIXME Snapshot commit out of sequence if it fails after here? */
+	if (!deactivate_lv(cmd, lv)) {
+		log_error("Unable to deactivate logical volume \"%s\"",
+			  lv->name);
+		return 0;
+	}
+
+	if (lv_is_cow(lv)) {
+		origin = origin_from_cow(lv);
+		log_verbose("Removing snapshot %s", lv->name);
+		if (!vg_remove_snapshot(lv))
+			return_0;
+	}
+
+	log_verbose("Releasing logical volume \"%s\"", lv->name);
+	if (!lv_remove(lv)) {
+		log_error("Error releasing logical volume \"%s\"", lv->name);
+		return 0;
+	}
+
+	/* store it on disks */
+	if (!vg_write(vg))
+		return 0;
+
+	backup(vg);
+
+	if (!vg_commit(vg))
+		return 0;
+
+	/* If no snapshots left, reload without -real. */
+	if (origin && !lv_is_origin(origin)) {
+		if (!suspend_lv(cmd, origin))
+			log_error("Failed to refresh %s without snapshot.", origin->name);
+		else if (!resume_lv(cmd, origin))
+			log_error("Failed to resume %s.", origin->name);
+	}
+
+	log_print("Logical volume \"%s\" successfully removed", lv->name);
+	return 1;
+}
+
+/*
+ * remove LVs with its dependencies - LV leaf nodes should be removed first
+ */
+int lv_remove_with_dependencies(struct cmd_context *cmd, struct logical_volume *lv,
+				const force_t force)
+{
+	struct dm_list *snh, *snht;
+
+        if (lv_is_origin(lv)) {
+		/* remove snapshot LVs first */
+		dm_list_iterate_safe(snh, snht, &lv->snapshot_segs) {
+			if (!lv_remove_with_dependencies(cmd, dm_list_struct_base(snh, struct lv_segment,
+									       origin_list)->cow,
+							 force))
+				return 0;
+		}
+	}
+
+        return lv_remove_single(cmd, lv, force);
+}
+
+/*
+ * insert_layer_for_segments_on_pv() inserts a layer segment for a segment area.
+ * However, layer modification could split the underlying layer segment.
+ * This function splits the parent area according to keep the 1:1 relationship
+ * between the parent area and the underlying layer segment.
+ * Since the layer LV might have other layers below, build_parallel_areas()
+ * is used to find the lowest-level segment boundaries.
+ */
+static int _split_parent_area(struct lv_segment *seg, uint32_t s,
+			      struct dm_list *layer_seg_pvs)
+{
+	uint32_t parent_area_len, parent_le, layer_le;
+	uint32_t area_multiple;
+	struct seg_pvs *spvs;
+
+	if (seg_is_striped(seg))
+		area_multiple = seg->area_count;
+	else
+		area_multiple = 1;
+
+	parent_area_len = seg->area_len;
+	parent_le = seg->le;
+	layer_le = seg_le(seg, s);
+
+	while (parent_area_len > 0) {
+		/* Find the layer segment pointed at */
+		if (!(spvs = _find_seg_pvs_by_le(layer_seg_pvs, layer_le))) {
+			log_error("layer segment for %s:%" PRIu32 " not found",
+				  seg->lv->name, parent_le);
+			return 0;
+		}
+
+		if (spvs->le != layer_le) {
+			log_error("Incompatible layer boundary: "
+				  "%s:%" PRIu32 "[%" PRIu32 "] on %s:%" PRIu32,
+				  seg->lv->name, parent_le, s,
+				  seg_lv(seg, s)->name, layer_le);
+			return 0;
+		}
+
+		if (spvs->len < parent_area_len) {
+			parent_le += spvs->len * area_multiple;
+			if (!lv_split_segment(seg->lv, parent_le))
+				return_0;
+		}
+
+		parent_area_len -= spvs->len;
+		layer_le += spvs->len;
+	}
+
+	return 1;
+}
+
+/*
+ * Split the parent LV segments if the layer LV below it is splitted.
+ */
+int split_parent_segments_for_layer(struct cmd_context *cmd,
+				    struct logical_volume *layer_lv)
+{
+	struct lv_list *lvl;
+	struct logical_volume *parent_lv;
+	struct lv_segment *seg;
+	uint32_t s;
+	struct dm_list *parallel_areas;
+
+	if (!(parallel_areas = build_parallel_areas_from_lv(cmd, layer_lv)))
+		return_0;
+
+	/* Loop through all LVs except itself */
+	dm_list_iterate_items(lvl, &layer_lv->vg->lvs) {
+		parent_lv = lvl->lv;
+		if (parent_lv == layer_lv)
+			continue;
+
+		/* Find all segments that point at the layer LV */
+		dm_list_iterate_items(seg, &parent_lv->segments) {
+			for (s = 0; s < seg->area_count; s++) {
+				if (seg_type(seg, s) != AREA_LV ||
+				    seg_lv(seg, s) != layer_lv)
+					continue;
+
+				if (!_split_parent_area(seg, s, parallel_areas))
+					return_0;
+			}
+		}
+	}
+
+	return 1;
+}
+
+/* Remove a layer from the LV */
+int remove_layers_for_segments(struct cmd_context *cmd,
+			       struct logical_volume *lv,
+			       struct logical_volume *layer_lv,
+			       uint32_t status_mask, struct dm_list *lvs_changed)
+{
+	struct lv_segment *seg, *lseg;
+	uint32_t s;
+	int lv_changed = 0;
+	struct lv_list *lvl;
+
+	log_very_verbose("Removing layer %s for segments of %s",
+			 layer_lv->name, lv->name);
+
+	/* Find all segments that point at the temporary mirror */
+	dm_list_iterate_items(seg, &lv->segments) {
+		for (s = 0; s < seg->area_count; s++) {
+			if (seg_type(seg, s) != AREA_LV ||
+			    seg_lv(seg, s) != layer_lv)
+				continue;
+
+			/* Find the layer segment pointed at */
+			if (!(lseg = find_seg_by_le(layer_lv, seg_le(seg, s)))) {
+				log_error("Layer segment found: %s:%" PRIu32,
+					  layer_lv->name, seg_le(seg, s));
+				return 0;
+			}
+
+			/* Check the segment params are compatible */
+			if (!seg_is_striped(lseg) || lseg->area_count != 1) {
+				log_error("Layer is not linear: %s:%" PRIu32,
+					  layer_lv->name, lseg->le);
+				return 0;
+			}
+			if ((lseg->status & status_mask) != status_mask) {
+				log_error("Layer status does not match: "
+					  "%s:%" PRIu32 " status: 0x%x/0x%x",
+					  layer_lv->name, lseg->le,
+					  lseg->status, status_mask);
+				return 0;
+			}
+			if (lseg->le != seg_le(seg, s) ||
+			    lseg->area_len != seg->area_len) {
+				log_error("Layer boundary mismatch: "
+					  "%s:%" PRIu32 "-%" PRIu32 " on "
+					  "%s:%" PRIu32 " / "
+					  "%" PRIu32 "-%" PRIu32 " / ",
+					  lv->name, seg->le, seg->area_len,
+					  layer_lv->name, seg_le(seg, s),
+					  lseg->le, lseg->area_len);
+				return 0;
+			}
+
+			if (!move_lv_segment_area(seg, s, lseg, 0))
+				return_0;
+
+			/* Replace mirror with error segment */
+			if (!(lseg->segtype =
+			      get_segtype_from_string(lv->vg->cmd, "error"))) {
+				log_error("Missing error segtype");
+				return 0;
+			}
+			lseg->area_count = 0;
+
+			/* First time, add LV to list of LVs affected */
+			if (!lv_changed && lvs_changed) {
+				if (!(lvl = dm_pool_alloc(cmd->mem, sizeof(*lvl)))) {
+					log_error("lv_list alloc failed");
+					return 0;
+				}
+				lvl->lv = lv;
+				dm_list_add(lvs_changed, &lvl->list);
+				lv_changed = 1;
+			}
+		}
+	}
+	if (lv_changed && !lv_merge_segments(lv))
+		stack;
+
+	return 1;
+}
+
+/* Remove a layer */
+int remove_layers_for_segments_all(struct cmd_context *cmd,
+				   struct logical_volume *layer_lv,
+				   uint32_t status_mask,
+				   struct dm_list *lvs_changed)
+{
+	struct lv_list *lvl;
+	struct logical_volume *lv1;
+
+	/* Loop through all LVs except the temporary mirror */
+	dm_list_iterate_items(lvl, &layer_lv->vg->lvs) {
+		lv1 = lvl->lv;
+		if (lv1 == layer_lv)
+			continue;
+
+		if (!remove_layers_for_segments(cmd, lv1, layer_lv,
+						status_mask, lvs_changed))
+			return_0;
+	}
+
+	if (!lv_empty(layer_lv))
+		return_0;
+
+	return 1;
+}
+
+static int _move_lv_segments(struct logical_volume *lv_to,
+			     struct logical_volume *lv_from,
+			     uint32_t set_status, uint32_t reset_status)
+{
+	struct lv_segment *seg;
+
+	dm_list_iterate_items(seg, &lv_to->segments) {
+		if (seg->origin) {
+			log_error("Can't move snapshot segment");
+			return 0;
+		}
+	}
+
+	lv_to->segments = lv_from->segments;
+	lv_to->segments.n->p = &lv_to->segments;
+	lv_to->segments.p->n = &lv_to->segments;
+
+	dm_list_iterate_items(seg, &lv_to->segments) {
+		seg->lv = lv_to;
+		seg->status &= ~reset_status;
+		seg->status |= set_status;
+	}
+
+	dm_list_init(&lv_from->segments);
+
+	lv_to->le_count = lv_from->le_count;
+	lv_to->size = lv_from->size;
+
+	lv_from->le_count = 0;
+	lv_from->size = 0;
+
+	return 1;
+}
+
+/* Remove a layer from the LV */
+int remove_layer_from_lv(struct logical_volume *lv,
+			 struct logical_volume *layer_lv)
+{
+	struct logical_volume *parent;
+	struct lv_segment *parent_seg;
+	struct segment_type *segtype;
+
+	log_very_verbose("Removing layer %s for %s", layer_lv->name, lv->name);
+
+	if (!(parent_seg = get_only_segment_using_this_lv(layer_lv))) {
+		log_error("Failed to find layer %s in %s",
+		layer_lv->name, lv->name);
+		return 0;
+	}
+	parent = parent_seg->lv;
+
+	/*
+	 * Before removal, the layer should be cleaned up,
+	 * i.e. additional segments and areas should have been removed.
+	 */
+	if (dm_list_size(&parent->segments) != 1 ||
+	    parent_seg->area_count != 1 ||
+	    seg_type(parent_seg, 0) != AREA_LV ||
+	    layer_lv != seg_lv(parent_seg, 0) ||
+	    parent->le_count != layer_lv->le_count)
+		return_0;
+
+	if (!lv_empty(parent))
+		return_0;
+
+	if (!_move_lv_segments(parent, layer_lv, 0, 0))
+		return_0;
+
+	/* Replace the empty layer with error segment */
+	segtype = get_segtype_from_string(lv->vg->cmd, "error");
+	if (!lv_add_virtual_segment(layer_lv, 0, parent->le_count, segtype))
+		return_0;
+
+	return 1;
+}
+
+/*
+ * Create and insert a linear LV "above" lv_where.
+ * After the insertion, a new LV named lv_where->name + suffix is created
+ * and all segments of lv_where is moved to the new LV.
+ * lv_where will have a single segment which maps linearly to the new LV.
+ */
+struct logical_volume *insert_layer_for_lv(struct cmd_context *cmd,
+					   struct logical_volume *lv_where,
+					   uint32_t status,
+					   const char *layer_suffix)
+{
+	struct logical_volume *layer_lv;
+	char *name;
+	size_t len;
+	struct segment_type *segtype;
+	struct lv_segment *mapseg;
+
+	/* create an empty layer LV */
+	len = strlen(lv_where->name) + 32;
+	if (!(name = alloca(len))) {
+		log_error("layer name allocation failed. "
+			  "Remove new LV and retry.");
+		return NULL;
+	}
+
+	if (dm_snprintf(name, len, "%s%s", lv_where->name, layer_suffix) < 0) {
+		log_error("layer name allocation failed. "
+			  "Remove new LV and retry.");
+		return NULL;
+	}
+
+	if (!(layer_lv = lv_create_empty(name, NULL, LVM_READ | LVM_WRITE,
+					 ALLOC_INHERIT, 0, lv_where->vg))) {
+		log_error("Creation of layer LV failed");
+		return NULL;
+	}
+
+	if (lv_is_active(lv_where) && strstr(name, "_mimagetmp")) {
+		log_very_verbose("Creating transient LV %s for mirror conversion in VG %s.", name, lv_where->vg->name);
+
+		segtype = get_segtype_from_string(cmd, "error");
+
+		if (!lv_add_virtual_segment(layer_lv, 0, lv_where->le_count, segtype)) {
+			log_error("Creation of transient LV %s for mirror conversion in VG %s failed.", name, lv_where->vg->name);
+			return NULL;
+		}
+
+		if (!vg_write(lv_where->vg)) {
+			log_error("Failed to write intermediate VG %s metadata for mirror conversion.", lv_where->vg->name);
+			return NULL;
+		}
+
+		if (!vg_commit(lv_where->vg)) {
+			log_error("Failed to commit intermediate VG %s metadata for mirror conversion.", lv_where->vg->name);
+			vg_revert(lv_where->vg);
+			return NULL;
+		}
+
+		if (!activate_lv(cmd, layer_lv)) {
+			log_error("Failed to resume transient error LV %s for mirror conversion in VG %s.", name, lv_where->vg->name);
+			return NULL;
+		}
+	}
+
+	log_very_verbose("Inserting layer %s for %s",
+			 layer_lv->name, lv_where->name);
+
+	if (!_move_lv_segments(layer_lv, lv_where, 0, 0))
+		return_NULL;
+
+	if (!(segtype = get_segtype_from_string(cmd, "striped")))
+		return_NULL;
+
+	/* allocate a new linear segment */
+	if (!(mapseg = alloc_lv_segment(cmd->mem, segtype,
+					lv_where, 0, layer_lv->le_count,
+					status, 0, NULL, 1, layer_lv->le_count,
+					0, 0, 0)))
+		return_NULL;
+
+	/* map the new segment to the original underlying are */
+	if (!set_lv_segment_area_lv(mapseg, 0, layer_lv, 0, 0))
+		return_NULL;
+
+	/* add the new segment to the layer LV */
+	dm_list_add(&lv_where->segments, &mapseg->list);
+	lv_where->le_count = layer_lv->le_count;
+	lv_where->size = lv_where->le_count * lv_where->vg->extent_size;
+
+	return layer_lv;
+}
+
+/*
+ * Extend and insert a linear layer LV beneath the source segment area.
+ */
+static int _extend_layer_lv_for_segment(struct logical_volume *layer_lv,
+					struct lv_segment *seg, uint32_t s,
+					uint32_t status)
+{
+	struct lv_segment *mapseg;
+	struct segment_type *segtype;
+	struct physical_volume *src_pv = seg_pv(seg, s);
+	uint32_t src_pe = seg_pe(seg, s);
+
+	if (seg_type(seg, s) != AREA_PV && seg_type(seg, s) != AREA_LV)
+		return_0;
+
+	if (!(segtype = get_segtype_from_string(layer_lv->vg->cmd, "striped")))
+		return_0;
+
+	/* FIXME Incomplete message? Needs more context */
+	log_very_verbose("Inserting %s:%" PRIu32 "-%" PRIu32 " of %s/%s",
+			 pv_dev_name(src_pv),
+			 src_pe, src_pe + seg->area_len - 1,
+			 seg->lv->vg->name, seg->lv->name);
+
+	/* allocate a new segment */
+	if (!(mapseg = alloc_lv_segment(layer_lv->vg->cmd->mem, segtype,
+					layer_lv, layer_lv->le_count,
+					seg->area_len, status, 0,
+					NULL, 1, seg->area_len, 0, 0, 0)))
+		return_0;
+
+	/* map the new segment to the original underlying are */
+	if (!move_lv_segment_area(mapseg, 0, seg, s))
+		return_0;
+
+	/* add the new segment to the layer LV */
+	dm_list_add(&layer_lv->segments, &mapseg->list);
+	layer_lv->le_count += seg->area_len;
+	layer_lv->size += seg->area_len * layer_lv->vg->extent_size;
+
+	/* map the original area to the new segment */
+	if (!set_lv_segment_area_lv(seg, s, layer_lv, mapseg->le, 0))
+		return_0;
+
+	return 1;
+}
+
+/*
+ * Match the segment area to PEs in the pvl
+ * (the segment area boundary should be aligned to PE ranges by
+ *  _adjust_layer_segments() so that there is no partial overlap.)
+ */
+static int _match_seg_area_to_pe_range(struct lv_segment *seg, uint32_t s,
+				       struct pv_list *pvl)
+{
+	struct pe_range *per;
+	uint32_t pe_start, per_end;
+
+	if (!pvl)
+		return 1;
+
+	if (seg_type(seg, s) != AREA_PV || seg_dev(seg, s) != pvl->pv->dev)
+		return 0;
+
+	pe_start = seg_pe(seg, s);
+
+	/* Do these PEs match to any of the PEs in pvl? */
+	dm_list_iterate_items(per, pvl->pe_ranges) {
+		per_end = per->start + per->count - 1;
+
+		if ((pe_start < per->start) || (pe_start > per_end))
+			continue;
+
+		/* FIXME Missing context in this message - add LV/seg details */
+		log_debug("Matched PE range %s:%" PRIu32 "-%" PRIu32 " against "
+			  "%s %" PRIu32 " len %" PRIu32, dev_name(pvl->pv->dev),
+			  per->start, per_end, dev_name(seg_dev(seg, s)),
+			  seg_pe(seg, s), seg->area_len);
+
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * For each segment in lv_where that uses a PV in pvl directly,
+ * split the segment if it spans more than one underlying PV.
+ */
+static int _align_segment_boundary_to_pe_range(struct logical_volume *lv_where,
+					       struct pv_list *pvl)
+{
+	struct lv_segment *seg;
+	struct pe_range *per;
+	uint32_t pe_start, pe_end, per_end, stripe_multiplier, s;
+
+	if (!pvl)
+		return 1;
+
+	/* Split LV segments to match PE ranges */
+	dm_list_iterate_items(seg, &lv_where->segments) {
+		for (s = 0; s < seg->area_count; s++) {
+			if (seg_type(seg, s) != AREA_PV ||
+			    seg_dev(seg, s) != pvl->pv->dev)
+				continue;
+
+			/* Do these PEs match with the condition? */
+			dm_list_iterate_items(per, pvl->pe_ranges) {
+				pe_start = seg_pe(seg, s);
+				pe_end = pe_start + seg->area_len - 1;
+				per_end = per->start + per->count - 1;
+
+				/* No overlap? */
+				if ((pe_end < per->start) ||
+				    (pe_start > per_end))
+					continue;
+
+				if (seg_is_striped(seg))
+					stripe_multiplier = seg->area_count;
+				else
+					stripe_multiplier = 1;
+
+				if ((per->start != pe_start &&
+				     per->start > pe_start) &&
+				    !lv_split_segment(lv_where, seg->le +
+						      (per->start - pe_start) *
+						      stripe_multiplier))
+					return_0;
+
+				if ((per_end != pe_end &&
+				     per_end < pe_end) &&
+				    !lv_split_segment(lv_where, seg->le +
+						      (per_end - pe_start + 1) *
+						      stripe_multiplier))
+					return_0;
+			}
+		}
+	}
+
+	return 1;
+}
+
+/*
+ * Scan lv_where for segments on a PV in pvl, and for each one found
+ * append a linear segment to lv_layer and insert it between the two.
+ *
+ * If pvl is empty, a layer is placed under the whole of lv_where.
+ * If the layer is inserted, lv_where is added to lvs_changed.
+ */
+int insert_layer_for_segments_on_pv(struct cmd_context *cmd,
+				    struct logical_volume *lv_where,
+				    struct logical_volume *layer_lv,
+				    uint32_t status,
+				    struct pv_list *pvl,
+				    struct dm_list *lvs_changed)
+{
+	struct lv_segment *seg;
+	struct lv_list *lvl;
+	int lv_used = 0;
+	uint32_t s;
+
+	log_very_verbose("Inserting layer %s for segments of %s on %s",
+			 layer_lv->name, lv_where->name,
+			 pvl ? pv_dev_name(pvl->pv) : "any");
+
+	if (!_align_segment_boundary_to_pe_range(lv_where, pvl))
+		return_0;
+
+	/* Work through all segments on the supplied PV */
+	dm_list_iterate_items(seg, &lv_where->segments) {
+		for (s = 0; s < seg->area_count; s++) {
+			if (!_match_seg_area_to_pe_range(seg, s, pvl))
+				continue;
+
+			/* First time, add LV to list of LVs affected */
+			if (!lv_used && lvs_changed) {
+				if (!(lvl = dm_pool_alloc(cmd->mem, sizeof(*lvl)))) {
+					log_error("lv_list alloc failed");
+					return 0;
+				}
+				lvl->lv = lv_where;
+				dm_list_add(lvs_changed, &lvl->list);
+				lv_used = 1;
+			}
+
+			if (!_extend_layer_lv_for_segment(layer_lv, seg, s,
+							  status)) {
+				log_error("Failed to insert segment in layer "
+					  "LV %s under %s:%" PRIu32 "-%" PRIu32,
+					  layer_lv->name, lv_where->name,
+					  seg->le, seg->le + seg->len);
+				return 0;
+			}
+		}
+	}
+
+	return 1;
+}
+
+/*
+ * Initialize the LV with 'value'.
+ */
+int set_lv(struct cmd_context *cmd, struct logical_volume *lv,
+	   uint64_t sectors, int value)
+{
+	struct device *dev;
+	char *name;
+
+	/*
+	 * FIXME:
+	 * <clausen> also, more than 4k
+	 * <clausen> say, reiserfs puts it's superblock 32k in, IIRC
+	 * <ejt_> k, I'll drop a fixme to that effect
+	 *	   (I know the device is at least 4k, but not 32k)
+	 */
+	if (!(name = dm_pool_alloc(cmd->mem, PATH_MAX))) {
+		log_error("Name allocation failed - device not cleared");
+		return 0;
+	}
+#ifdef __NetBSD__
+	if (dm_snprintf(name, PATH_MAX, "%s%s/r%s", cmd->dev_dir,
+			lv->vg->name, lv->name) < 0) {
+		log_error("Name too long - device not cleared (%s)", lv->name);
+		return 0;
+	}
+#else
+	if (dm_snprintf(name, PATH_MAX, "%s%s/%s", cmd->dev_dir,
+			lv->vg->name, lv->name) < 0) {
+		log_error("Name too long - device not cleared (%s)", lv->name);
+		return 0;
+	}
+#endif
+	log_verbose("Clearing start of logical volume \"%s\"", lv->name);
+
+	if (!(dev = dev_cache_get(name, NULL))) {
+		log_error("%s: not found: device not cleared", name);
+		return 0;
+	}
+
+	if (!dev_open_quiet(dev))
+		return_0;
+
+	dev_set(dev, UINT64_C(0),
+		sectors ? (size_t) sectors << SECTOR_SHIFT : (size_t) 4096,
+		value);
+	dev_flush(dev);
+	dev_close_immediate(dev);
+
+	return 1;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/metadata/merge.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/metadata/merge.c
diff -N src/external/gpl2/lvm2tools/dist/lib/metadata/merge.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/metadata/merge.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,368 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "metadata.h"
+#include "toolcontext.h"
+#include "lv_alloc.h"
+#include "pv_alloc.h"
+#include "str_list.h"
+#include "segtype.h"
+
+/*
+ * Attempt to merge two adjacent segments.
+ * Currently only supports striped segments on AREA_PV.
+ * Returns success if successful, in which case 'first'
+ * gets adjusted to contain both areas.
+ */
+static int _merge(struct lv_segment *first, struct lv_segment *second)
+{
+	if (!first || !second || first->segtype != second->segtype ||
+	    !first->segtype->ops->merge_segments) return 0;
+
+	return first->segtype->ops->merge_segments(first, second);
+}
+
+int lv_merge_segments(struct logical_volume *lv)
+{
+	struct dm_list *segh, *t;
+	struct lv_segment *current, *prev = NULL;
+
+	if (lv->status & LOCKED || lv->status & PVMOVE)
+		return 1;
+
+	dm_list_iterate_safe(segh, t, &lv->segments) {
+		current = dm_list_item(segh, struct lv_segment);
+
+		if (_merge(prev, current))
+			dm_list_del(&current->list);
+		else
+			prev = current;
+	}
+
+	return 1;
+}
+
+/*
+ * Verify that an LV's segments are consecutive, complete and don't overlap.
+ */
+int check_lv_segments(struct logical_volume *lv, int complete_vg)
+{
+	struct lv_segment *seg, *seg2;
+	uint32_t le = 0;
+	unsigned seg_count = 0, seg_found;
+	int r = 1;
+	uint32_t area_multiplier, s;
+	struct seg_list *sl;
+
+	dm_list_iterate_items(seg, &lv->segments) {
+		seg_count++;
+		if (seg->le != le) {
+			log_error("LV %s invalid: segment %u should begin at "
+				  "LE %" PRIu32 " (found %" PRIu32 ").",
+				  lv->name, seg_count, le, seg->le);
+			r = 0;
+		}
+
+		area_multiplier = segtype_is_striped(seg->segtype) ?
+					seg->area_count : 1;
+
+		if (seg->area_len * area_multiplier != seg->len) {
+			log_error("LV %s: segment %u has inconsistent "
+				  "area_len %u",
+				  lv->name, seg_count, seg->area_len);
+			r = 0;
+		}
+
+		if (complete_vg && seg->log_lv) {
+			if (!seg_is_mirrored(seg)) {
+				log_error("LV %s: segment %u has log LV but "
+					  "is not mirrored",
+					  lv->name, seg_count);
+				r = 0;
+			}
+
+			if (!(seg->log_lv->status & MIRROR_LOG)) {
+				log_error("LV %s: segment %u log LV %s is not "
+					  "a mirror log",
+					   lv->name, seg_count, seg->log_lv->name);
+				r = 0;
+			}
+
+			if (!(seg2 = first_seg(seg->log_lv)) ||
+			    find_mirror_seg(seg2) != seg) {
+				log_error("LV %s: segment %u log LV does not "
+					  "point back to mirror segment",
+					   lv->name, seg_count);
+				r = 0;
+			}
+		}
+
+		if (complete_vg && seg->status & MIRROR_IMAGE) {
+			if (!find_mirror_seg(seg) ||
+			    !seg_is_mirrored(find_mirror_seg(seg))) {
+				log_error("LV %s: segment %u mirror image "
+					  "is not mirrored",
+					  lv->name, seg_count);
+				r = 0;
+			}
+		}
+
+		if (seg_is_snapshot(seg)) {
+			if (seg->cow && seg->cow == seg->origin) {
+				log_error("LV %s: segment %u has same LV %s for "
+					  "both origin and snapshot",
+					  lv->name, seg_count, seg->cow->name);
+				r = 0;
+			}
+		}
+
+		for (s = 0; s < seg->area_count; s++) {
+			if (seg_type(seg, s) == AREA_UNASSIGNED) {
+				log_error("LV %s: segment %u has unassigned "
+					  "area %u.",
+					  lv->name, seg_count, s);
+				r = 0;
+			} else if (seg_type(seg, s) == AREA_PV) {
+				if (!seg_pvseg(seg, s) ||
+				    seg_pvseg(seg, s)->lvseg != seg ||
+				    seg_pvseg(seg, s)->lv_area != s) {
+					log_error("LV %s: segment %u has "
+						  "inconsistent PV area %u",
+						  lv->name, seg_count, s);
+					r = 0;
+				}
+			} else {
+				if (!seg_lv(seg, s) ||
+				    seg_lv(seg, s)->vg != lv->vg ||
+				    seg_lv(seg, s) == lv) {
+					log_error("LV %s: segment %u has "
+						  "inconsistent LV area %u",
+						  lv->name, seg_count, s);
+					r = 0;
+				}
+
+				if (complete_vg && seg_lv(seg, s) &&
+				    (seg_lv(seg, s)->status & MIRROR_IMAGE) &&
+				    (!(seg2 = find_seg_by_le(seg_lv(seg, s),
+							    seg_le(seg, s))) ||
+				     find_mirror_seg(seg2) != seg)) {
+					log_error("LV %s: segment %u mirror "
+						  "image %u missing mirror ptr",
+						  lv->name, seg_count, s);
+					r = 0;
+				}
+
+/* FIXME I don't think this ever holds?
+				if (seg_le(seg, s) != le) {
+					log_error("LV %s: segment %u has "
+						  "inconsistent LV area %u "
+						  "size",
+						  lv->name, seg_count, s);
+					r = 0;
+				}
+ */
+				seg_found = 0;
+				dm_list_iterate_items(sl, &seg_lv(seg, s)->segs_using_this_lv)
+					if (sl->seg == seg)
+						seg_found++;
+				if (!seg_found) {
+					log_error("LV %s segment %d uses LV %s,"
+						  " but missing ptr from %s to %s",
+						  lv->name, seg_count,
+						  seg_lv(seg, s)->name,
+						  seg_lv(seg, s)->name, lv->name);
+					r = 0;
+				} else if (seg_found > 1) {
+					log_error("LV %s has duplicated links "
+						  "to LV %s segment %d",
+						  seg_lv(seg, s)->name,
+						  lv->name, seg_count);
+					r = 0;
+				}
+			}
+		}
+
+		le += seg->len;
+	}
+
+	dm_list_iterate_items(sl, &lv->segs_using_this_lv) {
+		seg = sl->seg;
+		seg_found = 0;
+		for (s = 0; s < seg->area_count; s++) {
+			if (seg_type(seg, s) != AREA_LV)
+				continue;
+			if (lv == seg_lv(seg, s))
+				seg_found++;
+		}
+		if (seg->log_lv == lv)
+			seg_found++;
+		if (!seg_found) {
+			log_error("LV %s is used by LV %s:%" PRIu32 "-%" PRIu32
+				  ", but missing ptr from %s to %s",
+				  lv->name, seg->lv->name, seg->le,
+				  seg->le + seg->len - 1,
+				  seg->lv->name, lv->name);
+			r = 0;
+		} else if (seg_found != sl->count) {
+			log_error("Reference count mismatch: LV %s has %d "
+				  "links to LV %s:%" PRIu32 "-%" PRIu32
+				  ", which has %d links",
+				  lv->name, sl->count, seg->lv->name, seg->le,
+				  seg->le + seg->len - 1, seg_found);
+			r = 0;
+		}
+
+		seg_found = 0;
+		dm_list_iterate_items(seg2, &seg->lv->segments)
+			if (sl->seg == seg2) {
+				seg_found++;
+				break;
+			}
+		if (!seg_found) {
+			log_error("LV segment %s:%" PRIu32 "-%" PRIu32
+				  "is incorrectly listed as being used by LV %s",
+				  seg->lv->name, seg->le, seg->le + seg->len - 1,
+				  lv->name);
+			r = 0;
+		}
+	}
+
+	if (le != lv->le_count) {
+		log_error("LV %s: inconsistent LE count %u != %u",
+			  lv->name, le, lv->le_count);
+		r = 0;
+	}
+
+	return r;
+}
+
+/*
+ * Split the supplied segment at the supplied logical extent
+ * NB Use LE numbering that works across stripes PV1: 0,2,4 PV2: 1,3,5 etc.
+ */
+static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
+			     uint32_t le)
+{
+	struct lv_segment *split_seg;
+	uint32_t s;
+	uint32_t offset = le - seg->le;
+	uint32_t area_offset;
+
+	if (!seg_can_split(seg)) {
+		log_error("Unable to split the %s segment at LE %" PRIu32
+			  " in LV %s", seg->segtype->name, le, lv->name);
+		return 0;
+	}
+
+	/* Clone the existing segment */
+	if (!(split_seg = alloc_lv_segment(lv->vg->cmd->mem, seg->segtype,
+					   seg->lv, seg->le, seg->len,
+					   seg->status, seg->stripe_size,
+					   seg->log_lv,
+					   seg->area_count, seg->area_len,
+					   seg->chunk_size, seg->region_size,
+					   seg->extents_copied))) {
+		log_error("Couldn't allocate cloned LV segment.");
+		return 0;
+	}
+
+	if (!str_list_dup(lv->vg->cmd->mem, &split_seg->tags, &seg->tags)) {
+		log_error("LV segment tags duplication failed");
+		return 0;
+	}
+
+	/* In case of a striped segment, the offset has to be / stripes */
+	area_offset = offset;
+	if (seg_is_striped(seg))
+		area_offset /= seg->area_count;
+
+	split_seg->area_len -= area_offset;
+	seg->area_len = area_offset;
+
+	split_seg->len -= offset;
+	seg->len = offset;
+
+	split_seg->le = seg->le + seg->len;
+
+	/* Adjust the PV mapping */
+	for (s = 0; s < seg->area_count; s++) {
+		seg_type(split_seg, s) = seg_type(seg, s);
+
+		/* Split area at the offset */
+		switch (seg_type(seg, s)) {
+		case AREA_LV:
+			if (!set_lv_segment_area_lv(split_seg, s, seg_lv(seg, s),
+						    seg_le(seg, s) + seg->area_len, 0))
+				return_0;
+			log_debug("Split %s:%u[%u] at %u: %s LE %u", lv->name,
+				  seg->le, s, le, seg_lv(seg, s)->name,
+				  seg_le(split_seg, s));
+			break;
+
+		case AREA_PV:
+			if (!(seg_pvseg(split_seg, s) =
+			     assign_peg_to_lvseg(seg_pv(seg, s),
+						 seg_pe(seg, s) +
+						     seg->area_len,
+						 seg_pvseg(seg, s)->len -
+						     seg->area_len,
+						 split_seg, s)))
+				return_0;
+			log_debug("Split %s:%u[%u] at %u: %s PE %u", lv->name,
+				  seg->le, s, le,
+				  dev_name(seg_dev(seg, s)),
+				  seg_pe(split_seg, s));
+			break;
+
+		case AREA_UNASSIGNED:
+			log_error("Unassigned area %u found in segment", s);
+			return 0;
+		}
+	}
+
+	/* Add split off segment to the list _after_ the original one */
+	dm_list_add_h(&seg->list, &split_seg->list);
+
+	return 1;
+}
+
+/*
+ * Ensure there's a segment boundary at the given logical extent
+ */
+int lv_split_segment(struct logical_volume *lv, uint32_t le)
+{
+	struct lv_segment *seg;
+
+	if (!(seg = find_seg_by_le(lv, le))) {
+		log_error("Segment with extent %" PRIu32 " in LV %s not found",
+			  le, lv->name);
+		return 0;
+	}
+
+	/* This is a segment start already */
+	if (le == seg->le)
+		return 1;
+
+	if (!_lv_split_segment(lv, seg, le))
+		return_0;
+
+	if (!vg_validate(lv->vg))
+		return_0;
+
+	return 1;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/metadata/metadata-exported.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/metadata/metadata-exported.h
diff -N src/external/gpl2/lvm2tools/dist/lib/metadata/metadata-exported.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/metadata/metadata-exported.h	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,595 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * This is the representation of LVM metadata that is being adapted
+ * for library export.
+ */
+
+#ifndef _LVM_METADATA_EXPORTED_H
+#define _LVM_METADATA_EXPORTED_H
+
+#include "uuid.h"
+
+struct physical_volume;
+typedef struct physical_volume pv_t;
+struct volume_group;
+typedef struct volume_group vg_t;
+
+struct logical_volume;
+
+struct lv_segment;
+struct pv_segment;
+
+#define MAX_STRIPES 128U
+#define SECTOR_SHIFT 9L
+#define STRIPE_SIZE_MIN ( (unsigned) lvm_getpagesize() >> SECTOR_SHIFT)	/* PAGESIZE in sectors */
+#define STRIPE_SIZE_MAX ( 512L * 1024L >> SECTOR_SHIFT)	/* 512 KB in sectors */
+#define STRIPE_SIZE_LIMIT ((UINT_MAX >> 2) + 1)
+#define PV_MIN_SIZE ( 512L * 1024L >> SECTOR_SHIFT)	/* 512 KB in sectors */
+#define MAX_RESTRICTED_LVS 255	/* Used by FMT_RESTRICTED_LVIDS */
+
+/* Layer suffix */
+#define MIRROR_SYNC_LAYER "_mimagetmp"
+
+/* Various flags */
+/* Note that the bits no longer necessarily correspond to LVM1 disk format */
+
+#define PARTIAL_VG		0x00000001U	/* VG */
+#define EXPORTED_VG          	0x00000002U	/* VG PV */
+#define RESIZEABLE_VG        	0x00000004U	/* VG */
+
+/* May any free extents on this PV be used or must they be left free? */
+#define ALLOCATABLE_PV         	0x00000008U	/* PV */
+
+//#define SPINDOWN_LV          	0x00000010U	/* LV */
+//#define BADBLOCK_ON       	0x00000020U	/* LV */
+#define VISIBLE_LV		0x00000040U	/* LV */
+#define FIXED_MINOR		0x00000080U	/* LV */
+/* FIXME Remove when metadata restructuring is completed */
+#define SNAPSHOT		0x00001000U	/* LV - internal use only */
+#define PVMOVE			0x00002000U	/* VG LV SEG */
+#define LOCKED			0x00004000U	/* LV */
+#define MIRRORED		0x00008000U	/* LV - internal use only */
+//#define VIRTUAL			0x00010000U	/* LV - internal use only */
+#define MIRROR_LOG		0x00020000U	/* LV */
+#define MIRROR_IMAGE		0x00040000U	/* LV */
+#define MIRROR_NOTSYNCED	0x00080000U	/* LV */
+//#define ACTIVATE_EXCL		0x00100000U	/* LV - internal use only */
+//#define PRECOMMITTED		0x00200000U	/* VG - internal use only */
+#define CONVERTING		0x00400000U	/* LV */
+
+#define MISSING_PV              0x00800000U	/* PV */
+#define PARTIAL_LV              0x01000000U	/* LV - derived flag, not
+						   written out in metadata*/
+
+//#define POSTORDER_FLAG	0x02000000U /* Not real flags, reserved for
+//#define POSTORDER_OPEN_FLAG	0x04000000U    temporary use inside vg_read. */
+
+#define LVM_READ              	0x00000100U	/* LV VG */
+#define LVM_WRITE             	0x00000200U	/* LV VG */
+#define CLUSTERED         	0x00000400U	/* VG */
+//#define SHARED            	0x00000800U	/* VG */
+
+/* Format features flags */
+#define FMT_SEGMENTS		0x00000001U	/* Arbitrary segment params? */
+#define FMT_MDAS		0x00000002U	/* Proper metadata areas? */
+#define FMT_TAGS		0x00000004U	/* Tagging? */
+#define FMT_UNLIMITED_VOLS	0x00000008U	/* Unlimited PVs/LVs? */
+#define FMT_RESTRICTED_LVIDS	0x00000010U	/* LVID <= 255 */
+#define FMT_ORPHAN_ALLOCATABLE	0x00000020U	/* Orphan PV allocatable? */
+//#define FMT_PRECOMMIT		0x00000040U	/* Supports pre-commit? */
+#define FMT_RESIZE_PV		0x00000080U	/* Supports pvresize? */
+#define FMT_UNLIMITED_STRIPESIZE 0x00000100U	/* Unlimited stripe size? */
+#define FMT_RESTRICTED_READAHEAD 0x00000200U	/* Readahead restricted to 2-120? */
+
+/* LVM2 external library flags */
+#define CORRECT_INCONSISTENT    0x00000001U /* Correct inconsistent metadata */
+#define FAIL_INCONSISTENT       0x00000002U /* Fail if metadata inconsistent */
+
+/* Mirror conversion type flags */
+#define MIRROR_BY_SEG		0x00000001U	/* segment-by-segment mirror */
+#define MIRROR_BY_LV		0x00000002U	/* mirror using whole mimage LVs */
+#define MIRROR_SKIP_INIT_SYNC	0x00000010U	/* skip initial sync */
+
+/* Ordered list - see lv_manip.c */
+typedef enum {
+	ALLOC_INVALID,
+	ALLOC_CONTIGUOUS,
+	ALLOC_CLING,
+	ALLOC_NORMAL,
+	ALLOC_ANYWHERE,
+	ALLOC_INHERIT
+} alloc_policy_t;
+
+typedef enum {
+	AREA_UNASSIGNED,
+	AREA_PV,
+	AREA_LV
+} area_type_t;
+
+/*
+ * Whether or not to force an operation.
+ */
+typedef enum {
+	PROMPT = 0, /* Issue yes/no prompt to confirm operation */
+	DONT_PROMPT = 1, /* Skip yes/no prompt */
+	DONT_PROMPT_OVERRIDE = 2 /* Skip prompt + override a second condition */
+} force_t;
+
+struct cmd_context;
+struct format_handler;
+struct labeller;
+
+struct format_type {
+	struct dm_list list;
+	struct cmd_context *cmd;
+	struct format_handler *ops;
+	struct labeller *labeller;
+	const char *name;
+	const char *alias;
+	const char *orphan_vg_name;
+	uint32_t features;
+	void *library;
+	void *private;
+};
+
+struct pv_segment {
+	struct dm_list list;	/* Member of pv->segments: ordered list
+				 * covering entire data area on this PV */
+
+	struct physical_volume *pv;
+	uint32_t pe;
+	uint32_t len;
+
+	struct lv_segment *lvseg;	/* NULL if free space */
+	uint32_t lv_area;	/* Index to area in LV segment */
+};
+
+#define pvseg_is_allocated(pvseg) ((pvseg)->lvseg)
+
+struct physical_volume {
+	struct id id;
+	struct device *dev;
+	const struct format_type *fmt;
+	const char *vg_name;
+	struct id vgid;
+
+	uint32_t status;
+	uint64_t size;
+
+	/* physical extents */
+	uint32_t pe_size;
+	uint64_t pe_start;
+	uint32_t pe_count;
+	uint32_t pe_alloc_count;
+	unsigned long pe_align;
+
+	struct dm_list segments;	/* Ordered pv_segments covering complete PV */
+	struct dm_list tags;
+};
+
+struct format_instance {
+	const struct format_type *fmt;
+	struct dm_list metadata_areas;	/* e.g. metadata locations */
+	void *private;
+};
+
+struct volume_group {
+	struct cmd_context *cmd;
+	struct format_instance *fid;
+	uint32_t seqno;		/* Metadata sequence number */
+
+	struct id id;
+	char *name;
+	char *system_id;
+
+	uint32_t status;
+	alloc_policy_t alloc;
+
+	uint32_t extent_size;
+	uint32_t extent_count;
+	uint32_t free_count;
+
+	uint32_t max_lv;
+	uint32_t max_pv;
+
+	/* physical volumes */
+	uint32_t pv_count;
+	struct dm_list pvs;
+
+	/*
+	 * logical volumes
+	 * The following relationship should always hold:
+	 * dm_list_size(lvs) = lv_count + 2 * snapshot_count
+	 *
+	 * Snapshots consist of 2 instances of "struct logical_volume":
+	 * - cow (lv_name is visible to the user)
+	 * - snapshot (lv_name is 'snapshotN')
+	 * Neither of these instances is reflected in lv_count, but we
+	 * multiply the snapshot_count by 2.
+	 *
+	 * Mirrors consist of multiple instances of "struct logical_volume":
+	 * - one for the mirror log
+	 * - one for each mirror leg
+	 * - one for the user-visible mirror LV
+	 * all of the instances are reflected in lv_count.
+	 */
+	uint32_t lv_count;
+	uint32_t snapshot_count;
+	struct dm_list lvs;
+
+	struct dm_list tags;
+};
+
+/* There will be one area for each stripe */
+struct lv_segment_area {
+	area_type_t type;
+	union {
+		struct {
+			struct pv_segment *pvseg;
+		} pv;
+		struct {
+			struct logical_volume *lv;
+			uint32_t le;
+		} lv;
+	} u;
+};
+
+struct segment_type;
+struct lv_segment {
+	struct dm_list list;
+	struct logical_volume *lv;
+
+	const struct segment_type *segtype;
+	uint32_t le;
+	uint32_t len;
+
+	uint32_t status;
+
+	/* FIXME Fields depend on segment type */
+	uint32_t stripe_size;
+	uint32_t area_count;
+	uint32_t area_len;
+	struct logical_volume *origin;
+	struct logical_volume *cow;
+	struct dm_list origin_list;
+	uint32_t chunk_size;	/* For snapshots - in sectors */
+	uint32_t region_size;	/* For mirrors - in sectors */
+	uint32_t extents_copied;
+	struct logical_volume *log_lv;
+
+	struct dm_list tags;
+
+	struct lv_segment_area *areas;
+};
+
+#define seg_type(seg, s)	(seg)->areas[(s)].type
+#define seg_pv(seg, s)		(seg)->areas[(s)].u.pv.pvseg->pv
+#define seg_lv(seg, s)		(seg)->areas[(s)].u.lv.lv
+
+struct logical_volume {
+	union lvid lvid;
+	char *name;
+
+	struct volume_group *vg;
+
+	uint32_t status;
+	alloc_policy_t alloc;
+	uint32_t read_ahead;
+	int32_t major;
+	int32_t minor;
+
+	uint64_t size;		/* Sectors */
+	uint32_t le_count;
+
+	uint32_t origin_count;
+	struct dm_list snapshot_segs;
+	struct lv_segment *snapshot;
+
+	struct dm_list segments;
+	struct dm_list tags;
+	struct dm_list segs_using_this_lv;
+};
+
+struct pe_range {
+	struct dm_list list;
+	uint32_t start;		/* PEs */
+	uint32_t count;		/* PEs */
+};
+
+struct pv_list {
+	struct dm_list list;
+	struct physical_volume *pv;
+	struct dm_list *mdas;	/* Metadata areas */
+	struct dm_list *pe_ranges;	/* Ranges of PEs e.g. for allocation */
+};
+
+struct lv_list {
+	struct dm_list list;
+	struct logical_volume *lv;
+};
+
+/*
+* 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,
+			     const char *vgid, int *consistent);
+struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
+				struct dm_list *mdas, uint64_t *label_sector,
+				int warnings);
+struct dm_list *get_pvs(struct cmd_context *cmd);
+
+/* Set full_scan to 1 to re-read every (filtered) device label */
+struct dm_list *get_vgs(struct cmd_context *cmd, int full_scan);
+struct dm_list *get_vgids(struct cmd_context *cmd, int full_scan);
+int scan_vgs_for_pvs(struct cmd_context *cmd);
+
+int pv_write(struct cmd_context *cmd, struct physical_volume *pv,
+	     struct dm_list *mdas, int64_t label_sector);
+int is_pv(pv_t *pv);
+int is_orphan_vg(const char *vg_name);
+int is_orphan(const pv_t *pv);
+int vgs_are_compatible(struct cmd_context *cmd,
+		       struct volume_group *vg_from,
+		       struct volume_group *vg_to);
+vg_t *vg_lock_and_read(struct cmd_context *cmd, const char *vg_name,
+		       const char *vgid,
+		       uint32_t lock_flags, uint32_t status_flags,
+		       uint32_t misc_flags);
+
+/* pe_start and pe_end relate to any existing data so that new metadata
+* areas can avoid overlap */
+pv_t *pv_create(const struct cmd_context *cmd,
+		      struct device *dev,
+		      struct id *id,
+		      uint64_t size,
+		      uint64_t pe_start,
+		      uint32_t existing_extent_count,
+		      uint32_t existing_extent_size,
+		      int pvmetadatacopies,
+		      uint64_t pvmetadatasize, struct dm_list *mdas);
+int pv_resize(struct physical_volume *pv, struct volume_group *vg,
+             uint32_t new_pe_count);
+int pv_analyze(struct cmd_context *cmd, const char *pv_name,
+	       uint64_t label_sector);
+
+/* FIXME: move internal to library */
+uint32_t pv_list_extents_free(const struct dm_list *pvh);
+
+struct volume_group *vg_create(struct cmd_context *cmd, const char *name,
+			       uint32_t extent_size, uint32_t max_pv,
+			       uint32_t max_lv, alloc_policy_t alloc,
+			       int pv_count, char **pv_names);
+int vg_remove(struct volume_group *vg);
+int vg_remove_single(struct cmd_context *cmd, const char *vg_name,
+		     struct volume_group *vg, int consistent,
+		     force_t force);
+int vg_rename(struct cmd_context *cmd, struct volume_group *vg,
+	      const char *new_name);
+int vg_extend(struct volume_group *vg, int pv_count, char **pv_names);
+int vg_change_pesize(struct cmd_context *cmd, struct volume_group *vg,
+		     uint32_t new_extent_size);
+int vg_split_mdas(struct cmd_context *cmd, struct volume_group *vg_from,
+		  struct volume_group *vg_to);
+
+/* Manipulate LVs */
+struct logical_volume *lv_create_empty(const char *name,
+				       union lvid *lvid,
+				       uint32_t status,
+				       alloc_policy_t alloc,
+				       int import,
+				       struct volume_group *vg);
+
+/* Write out LV contents */
+int set_lv(struct cmd_context *cmd, struct logical_volume *lv,
+           uint64_t sectors, int value);
+
+/* Reduce the size of an LV by extents */
+int lv_reduce(struct logical_volume *lv, uint32_t extents);
+
+/* Empty an LV prior to deleting it */
+int lv_empty(struct logical_volume *lv);
+
+/* Empty an LV and add error segment */
+int replace_lv_with_error_segment(struct logical_volume *lv);
+
+/* Entry point for all LV extent allocations */
+int lv_extend(struct logical_volume *lv,
+	      const struct segment_type *segtype,
+	      uint32_t stripes, uint32_t stripe_size,
+	      uint32_t mirrors, uint32_t extents,
+	      struct physical_volume *mirrored_pv, uint32_t mirrored_pe,
+	      uint32_t status, struct dm_list *allocatable_pvs,
+	      alloc_policy_t alloc);
+
+/* lv must be part of lv->vg->lvs */
+int lv_remove(struct logical_volume *lv);
+
+int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
+		     force_t force);
+
+int lv_remove_with_dependencies(struct cmd_context *cmd, struct logical_volume *lv,
+				force_t force);
+
+int lv_rename(struct cmd_context *cmd, struct logical_volume *lv,
+	      const char *new_name);
+
+/*
+ * Functions for layer manipulation
+ */
+int insert_layer_for_segments_on_pv(struct cmd_context *cmd,
+				    struct logical_volume *lv_where,
+				    struct logical_volume *layer_lv,
+				    uint32_t status,
+				    struct pv_list *pv,
+				    struct dm_list *lvs_changed);
+int remove_layers_for_segments(struct cmd_context *cmd,
+			       struct logical_volume *lv,
+			       struct logical_volume *layer_lv,
+			       uint32_t status_mask, struct dm_list *lvs_changed);
+int remove_layers_for_segments_all(struct cmd_context *cmd,
+				   struct logical_volume *layer_lv,
+				   uint32_t status_mask,
+				   struct dm_list *lvs_changed);
+int split_parent_segments_for_layer(struct cmd_context *cmd,
+				    struct logical_volume *layer_lv);
+int remove_layer_from_lv(struct logical_volume *lv,
+			 struct logical_volume *layer_lv);
+struct logical_volume *insert_layer_for_lv(struct cmd_context *cmd,
+					   struct logical_volume *lv_where,
+					   uint32_t status,
+					   const char *layer_suffix);
+
+/* Find a PV within a given VG */
+struct pv_list *find_pv_in_vg(const struct volume_group *vg,
+			      const char *pv_name);
+pv_t *find_pv_in_vg_by_uuid(const struct volume_group *vg,
+			    const struct id *id);
+
+/* Find an LV within a given VG */
+struct lv_list *find_lv_in_vg(const struct volume_group *vg,
+			      const char *lv_name);
+
+/* FIXME Merge these functions with ones above */
+struct logical_volume *find_lv(const struct volume_group *vg,
+			       const char *lv_name);
+struct physical_volume *find_pv_by_name(struct cmd_context *cmd,
+					const char *pv_name);
+
+/* Find LV segment containing given LE */
+struct lv_segment *first_seg(const struct logical_volume *lv);
+
+
+/*
+* Useful functions for managing snapshots.
+*/
+int lv_is_origin(const struct logical_volume *lv);
+int lv_is_cow(const struct logical_volume *lv);
+int lv_is_visible(const struct logical_volume *lv);
+
+int pv_is_in_vg(struct volume_group *vg, struct physical_volume *pv);
+
+/* Given a cow LV, return return the snapshot lv_segment that uses it */
+struct lv_segment *find_cow(const struct logical_volume *lv);
+
+/* Given a cow LV, return its origin */
+struct logical_volume *origin_from_cow(const struct logical_volume *lv);
+
+int vg_add_snapshot(const char *name,
+		    struct logical_volume *origin, struct logical_volume *cow,
+		    union lvid *lvid, uint32_t extent_count,
+		    uint32_t chunk_size);
+
+int vg_remove_snapshot(struct logical_volume *cow);
+
+int vg_check_status(const struct volume_group *vg, uint32_t status);
+
+/*
+* Mirroring functions
+*/
+struct lv_segment *find_mirror_seg(struct lv_segment *seg);
+int lv_add_mirrors(struct cmd_context *cmd, struct logical_volume *lv,
+		   uint32_t mirrors, uint32_t stripes,
+		   uint32_t region_size, uint32_t log_count,
+		   struct dm_list *pvs, alloc_policy_t alloc, uint32_t flags);
+int lv_remove_mirrors(struct cmd_context *cmd, struct logical_volume *lv,
+		      uint32_t mirrors, uint32_t log_count,
+		      struct dm_list *pvs, uint32_t status_mask);
+
+int is_temporary_mirror_layer(const struct logical_volume *lv);
+struct logical_volume * find_temporary_mirror(const struct logical_volume *lv);
+uint32_t lv_mirror_count(const struct logical_volume *lv);
+uint32_t adjusted_mirror_region_size(uint32_t extent_size, uint32_t extents,
+                                    uint32_t region_size);
+int remove_mirrors_from_segments(struct logical_volume *lv,
+				 uint32_t new_mirrors, uint32_t status_mask);
+int add_mirrors_to_segments(struct cmd_context *cmd, struct logical_volume *lv,
+			    uint32_t mirrors, uint32_t region_size,
+			    struct dm_list *allocatable_pvs, alloc_policy_t alloc);
+
+int remove_mirror_images(struct logical_volume *lv, uint32_t num_mirrors,
+			 struct dm_list *removable_pvs, unsigned remove_log);
+int add_mirror_images(struct cmd_context *cmd, struct logical_volume *lv,
+		      uint32_t mirrors, uint32_t stripes, uint32_t region_size,
+		      struct dm_list *allocatable_pvs, alloc_policy_t alloc,
+		      uint32_t log_count);
+struct logical_volume *detach_mirror_log(struct lv_segment *seg);
+int attach_mirror_log(struct lv_segment *seg, struct logical_volume *lv);
+int remove_mirror_log(struct cmd_context *cmd, struct logical_volume *lv,
+		      struct dm_list *removable_pvs);
+int add_mirror_log(struct cmd_context *cmd, struct logical_volume *lv,
+		   uint32_t log_count, uint32_t region_size,
+		   struct dm_list *allocatable_pvs, alloc_policy_t alloc);
+
+int reconfigure_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors,
+			      struct dm_list *removable_pvs, unsigned remove_log);
+int collapse_mirrored_lv(struct logical_volume *lv);
+int shift_mirror_images(struct lv_segment *mirrored_seg, unsigned mimage);
+
+struct logical_volume *find_pvmove_lv(struct volume_group *vg,
+				      struct device *dev, uint32_t lv_type);
+struct logical_volume *find_pvmove_lv_from_pvname(struct cmd_context *cmd,
+						  struct volume_group *vg,
+						  const char *name,
+						  uint32_t lv_type);
+const char *get_pvmove_pvname_from_lv(struct logical_volume *lv);
+const char *get_pvmove_pvname_from_lv_mirr(struct logical_volume *lv_mirr);
+float copy_percent(struct logical_volume *lv_mirr);
+struct dm_list *lvs_using_lv(struct cmd_context *cmd, struct volume_group *vg,
+			  struct logical_volume *lv);
+
+uint32_t find_free_lvnum(struct logical_volume *lv);
+char *generate_lv_name(struct volume_group *vg, const char *format,
+		       char *buffer, size_t len);
+
+/*
+* Begin skeleton for external LVM library
+*/
+struct device *pv_dev(const pv_t *pv);
+const char *pv_vg_name(const pv_t *pv);
+const char *pv_dev_name(const pv_t *pv);
+uint64_t pv_size(const pv_t *pv);
+uint32_t pv_status(const pv_t *pv);
+uint32_t pv_pe_size(const pv_t *pv);
+uint64_t pv_pe_start(const pv_t *pv);
+uint32_t pv_pe_count(const pv_t *pv);
+uint32_t pv_pe_alloc_count(const pv_t *pv);
+
+int vg_missing_pv_count(const vg_t *vg);
+uint32_t vg_status(const vg_t *vg);
+#define vg_is_clustered(vg) (vg_status((vg)) & CLUSTERED)
+
+struct vgcreate_params {
+	char *vg_name;
+	uint32_t extent_size;
+	size_t max_pv;
+	size_t max_lv;
+	alloc_policy_t alloc;
+	int clustered; /* FIXME: put this into a 'status' variable instead? */
+};
+
+int validate_vg_create_params(struct cmd_context *cmd,
+			      struct vgcreate_params *vp);
+
+int validate_vg_rename_params(struct cmd_context *cmd,
+			      const char *vg_name_old,
+			      const char *vg_name_new);
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/metadata/metadata.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/metadata/metadata.c
diff -N src/external/gpl2/lvm2tools/dist/lib/metadata/metadata.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/metadata/metadata.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,2534 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "device.h"
+#include "metadata.h"
+#include "toolcontext.h"
+#include "lvm-string.h"
+#include "lvm-file.h"
+#include "lvmcache.h"
+#include "memlock.h"
+#include "str_list.h"
+#include "pv_alloc.h"
+#include "activate.h"
+#include "display.h"
+#include "locking.h"
+#include "archiver.h"
+#include "defaults.h"
+
+#include <sys/param.h>
+
+/*
+ * FIXME: Check for valid handle before dereferencing field or log error?
+ */
+#define pv_field(handle, field)				\
+	(((const struct physical_volume *)(handle))->field)
+
+static struct physical_volume *_pv_read(struct cmd_context *cmd,
+					const char *pv_name,
+					struct dm_list *mdas,
+					uint64_t *label_sector,
+					int warnings);
+
+static struct physical_volume *_pv_create(const struct format_type *fmt,
+				  struct device *dev,
+				  struct id *id, uint64_t size,
+				  uint64_t pe_start,
+				  uint32_t existing_extent_count,
+				  uint32_t existing_extent_size,
+				  int pvmetadatacopies,
+				  uint64_t pvmetadatasize, struct dm_list *mdas);
+
+static int _pv_write(struct cmd_context *cmd __attribute((unused)),
+		     struct physical_volume *pv,
+	     	     struct dm_list *mdas, int64_t label_sector);
+
+static struct physical_volume *_find_pv_by_name(struct cmd_context *cmd,
+			 			const char *pv_name);
+
+static struct pv_list *_find_pv_in_vg(const struct volume_group *vg,
+				      const char *pv_name);
+
+static struct physical_volume *_find_pv_in_vg_by_uuid(const struct volume_group *vg,
+						      const struct id *id);
+
+unsigned long pe_align(struct physical_volume *pv)
+{
+	if (pv->pe_align)
+		goto out;
+
+	pv->pe_align = MAX(65536UL, lvm_getpagesize()) >> SECTOR_SHIFT;
+
+	/*
+	 * Align to chunk size of underlying md device if present
+	 */
+	if (!pv->dev)
+		goto out;
+
+	if (find_config_tree_bool(pv->fmt->cmd, "devices/md_chunk_alignment",
+				  DEFAULT_MD_CHUNK_ALIGNMENT))
+		pv->pe_align = MAX(pv->pe_align,
+				   dev_md_chunk_size(pv->fmt->cmd->sysfs_dir,
+						     pv->dev));
+
+	log_very_verbose("%s: Setting PE alignment to %lu sectors.",
+			 dev_name(pv->dev), pv->pe_align);
+
+out:
+	return pv->pe_align;
+}
+
+/**
+ * add_pv_to_vg - Add a physical volume to a volume group
+ * @vg - volume group to add to
+ * @pv_name - name of the pv (to be removed)
+ * @pv - physical volume to add to volume group
+ *
+ * Returns:
+ *  0 - failure
+ *  1 - success
+ * FIXME: remove pv_name - obtain safely from pv
+ */
+int add_pv_to_vg(struct volume_group *vg, const char *pv_name,
+		 struct physical_volume *pv)
+{
+	struct pv_list *pvl;
+	struct format_instance *fid = vg->fid;
+	struct dm_pool *mem = fid->fmt->cmd->mem;
+
+	log_verbose("Adding physical volume '%s' to volume group '%s'",
+		    pv_name, vg->name);
+
+	if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl)))) {
+		log_error("pv_list allocation for '%s' failed", pv_name);
+		return 0;
+	}
+
+	if (!is_orphan_vg(pv->vg_name)) {
+		log_error("Physical volume '%s' is already in volume group "
+			  "'%s'", pv_name, pv->vg_name);
+		return 0;
+	}
+
+	if (pv->fmt != fid->fmt) {
+		log_error("Physical volume %s is of different format type (%s)",
+			  pv_name, pv->fmt->name);
+		return 0;
+	}
+
+	/* Ensure PV doesn't depend on another PV already in the VG */
+	if (pv_uses_vg(pv, vg)) {
+		log_error("Physical volume %s might be constructed from same "
+			  "volume group %s", pv_name, vg->name);
+		return 0;
+	}
+
+	if (!(pv->vg_name = dm_pool_strdup(mem, vg->name))) {
+		log_error("vg->name allocation failed for '%s'", pv_name);
+		return 0;
+	}
+
+	memcpy(&pv->vgid, &vg->id, sizeof(vg->id));
+
+	/* Units of 512-byte sectors */
+	pv->pe_size = vg->extent_size;
+
+	/* FIXME Do proper rounding-up alignment? */
+	/* Reserved space for label; this holds 0 for PVs created by LVM1 */
+	if (pv->pe_start < pe_align(pv))
+		pv->pe_start = pe_align(pv);
+
+	/*
+	 * pe_count must always be calculated by pv_setup
+	 */
+	pv->pe_alloc_count = 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);
+		return 0;
+	}
+
+	if (_find_pv_in_vg(vg, pv_name)) {
+		log_error("Physical volume '%s' listed more than once.",
+			  pv_name);
+		return 0;
+	}
+
+	if (vg->pv_count && (vg->pv_count == vg->max_pv)) {
+		log_error("No space for '%s' - volume group '%s' "
+			  "holds max %d physical volume(s).", pv_name,
+			  vg->name, vg->max_pv);
+		return 0;
+	}
+
+	if (!alloc_pv_segment_whole_pv(mem, pv))
+		return_0;
+
+	pvl->pv = pv;
+	dm_list_add(&vg->pvs, &pvl->list);
+
+	if ((uint64_t) vg->extent_count + pv->pe_count > UINT32_MAX) {
+		log_error("Unable to add %s to %s: new extent count (%"
+			  PRIu64 ") exceeds limit (%" PRIu32 ").",
+			  pv_name, vg->name,
+			  (uint64_t) vg->extent_count + pv->pe_count,
+			  UINT32_MAX);
+		return 0;
+	}
+
+	vg->pv_count++;
+	vg->extent_count += pv->pe_count;
+	vg->free_count += pv->pe_count;
+
+	return 1;
+}
+
+static int _copy_pv(struct physical_volume *pv_to,
+		    struct physical_volume *pv_from)
+{
+	memcpy(pv_to, pv_from, sizeof(*pv_to));
+
+	if (!str_list_dup(pv_to->fmt->cmd->mem, &pv_to->tags, &pv_from->tags)) {
+		log_error("PV tags duplication failed");
+		return 0;
+	}
+
+	if (!peg_dup(pv_to->fmt->cmd->mem, &pv_to->segments,
+		     &pv_from->segments))
+		return_0;
+
+	return 1;
+}
+
+int get_pv_from_vg_by_id(const struct format_type *fmt, const char *vg_name,
+			 const char *vgid, const char *pvid,
+			 struct physical_volume *pv)
+{
+	struct volume_group *vg;
+	struct pv_list *pvl;
+	int consistent = 0;
+
+	if (!(vg = vg_read(fmt->cmd, vg_name, vgid, &consistent))) {
+		log_error("get_pv_from_vg_by_id: vg_read failed to read VG %s",
+			  vg_name);
+		return 0;
+	}
+
+	if (!consistent)
+		log_warn("WARNING: Volume group %s is not consistent",
+			 vg_name);
+
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		if (id_equal(&pvl->pv->id, (const struct id *) pvid)) {
+			if (!_copy_pv(pv, pvl->pv))
+				return_0;
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+static int validate_new_vg_name(struct cmd_context *cmd, const char *vg_name)
+{
+	char vg_path[PATH_MAX];
+
+	if (!validate_name(vg_name))
+		return_0;
+
+	snprintf(vg_path, PATH_MAX, "%s%s", cmd->dev_dir, vg_name);
+	if (path_exists(vg_path)) {
+		log_error("%s: already exists in filesystem", vg_path);
+		return 0;
+	}
+
+	return 1;
+}
+
+int validate_vg_rename_params(struct cmd_context *cmd,
+			      const char *vg_name_old,
+			      const char *vg_name_new)
+{
+	unsigned length;
+	char *dev_dir;
+
+	dev_dir = cmd->dev_dir;
+	length = strlen(dev_dir);
+
+	/* Check sanity of new name */
+	if (strlen(vg_name_new) > NAME_LEN - length - 2) {
+		log_error("New volume group path exceeds maximum length "
+			  "of %d!", NAME_LEN - length - 2);
+		return 0;
+	}
+
+	if (!validate_new_vg_name(cmd, vg_name_new)) {
+		log_error("New volume group name \"%s\" is invalid",
+			  vg_name_new);
+		return 0;
+	}
+
+	if (!strcmp(vg_name_old, vg_name_new)) {
+		log_error("Old and new volume group names must differ");
+		return 0;
+	}
+
+	return 1;
+}
+
+int vg_rename(struct cmd_context *cmd, struct volume_group *vg,
+	      const char *new_name)
+{
+	struct dm_pool *mem = cmd->mem;
+	struct pv_list *pvl;
+
+	if (!(vg->name = dm_pool_strdup(mem, new_name))) {
+		log_error("vg->name allocation failed for '%s'", new_name);
+		return 0;
+	}
+
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		if (!(pvl->pv->vg_name = dm_pool_strdup(mem, new_name))) {
+			log_error("pv->vg_name allocation failed for '%s'",
+				  pv_dev_name(pvl->pv));
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+static int remove_lvs_in_vg(struct cmd_context *cmd,
+			    struct volume_group *vg,
+			    force_t force)
+{
+	struct dm_list *lst;
+	struct lv_list *lvl;
+
+	while ((lst = dm_list_first(&vg->lvs))) {
+		lvl = dm_list_item(lst, struct lv_list);
+		if (!lv_remove_with_dependencies(cmd, lvl->lv, force))
+		    return 0;
+	}
+
+	return 1;
+}
+
+/* FIXME: remove redundant vg_name */
+int vg_remove_single(struct cmd_context *cmd, const char *vg_name,
+		     struct volume_group *vg, int consistent,
+		     force_t force __attribute((unused)))
+{
+	struct physical_volume *pv;
+	struct pv_list *pvl;
+	int ret = 1;
+
+	if (!vg || !consistent || vg_missing_pv_count(vg)) {
+		log_error("Volume group \"%s\" not found, is inconsistent "
+			  "or has PVs missing.", vg_name);
+		log_error("Consider vgreduce --removemissing if metadata "
+			  "is inconsistent.");
+		return 0;
+	}
+
+	if (!vg_check_status(vg, EXPORTED_VG))
+		return 0;
+
+	if (vg->lv_count) {
+		if ((force == PROMPT) &&
+		    (yes_no_prompt("Do you really want to remove volume "
+				   "group \"%s\" containing %d "
+				   "logical volumes? [y/n]: ",
+				   vg_name, vg->lv_count) == 'n')) {
+			log_print("Volume group \"%s\" not removed", vg_name);
+			return 0;
+		}
+		if (!remove_lvs_in_vg(cmd, vg, force))
+			return 0;
+	}
+	
+	if (vg->lv_count) {
+		log_error("Volume group \"%s\" still contains %d "
+			  "logical volume(s)", vg_name, vg->lv_count);
+		return 0;
+	}
+
+	if (!archive(vg))
+		return 0;
+
+	if (!vg_remove(vg)) {
+		log_error("vg_remove %s failed", vg_name);
+		return 0;
+	}
+
+	/* init physical volumes */
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		pv = pvl->pv;
+		log_verbose("Removing physical volume \"%s\" from "
+			    "volume group \"%s\"", pv_dev_name(pv), vg_name);
+		pv->vg_name = vg->fid->fmt->orphan_vg_name;
+		pv->status = ALLOCATABLE_PV;
+
+		if (!dev_get_size(pv_dev(pv), &pv->size)) {
+			log_error("%s: Couldn't get size.", pv_dev_name(pv));
+			ret = 0;
+			continue;
+		}
+
+		/* FIXME Write to same sector label was read from */
+		if (!pv_write(cmd, pv, NULL, INT64_C(-1))) {
+			log_error("Failed to remove physical volume \"%s\""
+				  " from volume group \"%s\"",
+				  pv_dev_name(pv), vg_name);
+			ret = 0;
+		}
+	}
+
+	backup_remove(cmd, vg_name);
+
+	if (ret)
+		log_print("Volume group \"%s\" successfully removed", vg_name);
+	else
+		log_error("Volume group \"%s\" not properly removed", vg_name);
+
+	return ret;
+}
+
+int vg_extend(struct volume_group *vg, int pv_count, char **pv_names)
+{
+	int i;
+	struct physical_volume *pv;
+
+	/* attach each pv */
+	for (i = 0; i < pv_count; i++) {
+		if (!(pv = pv_by_path(vg->fid->fmt->cmd, pv_names[i]))) {
+			log_error("%s not identified as an existing "
+				  "physical volume", pv_names[i]);
+			goto bad;
+		}
+		
+		if (!add_pv_to_vg(vg, pv_names[i], pv))
+			goto bad;
+	}
+
+/* FIXME Decide whether to initialise and add new mdahs to format instance */
+
+	return 1;
+	
+      bad:
+	log_error("Unable to add physical volume '%s' to "
+		  "volume group '%s'.", pv_names[i], vg->name);
+	return 0;
+}
+
+const char *strip_dir(const char *vg_name, const char *dev_dir)
+{
+	size_t len = strlen(dev_dir);
+	if (!strncmp(vg_name, dev_dir, len))
+		vg_name += len;
+
+	return vg_name;
+}
+
+/*
+ * Validate parameters to vg_create() before calling.
+ * FIXME: Move inside vg_create library function.
+ * FIXME: Change vgcreate_params struct to individual gets/sets
+ */
+int validate_vg_create_params(struct cmd_context *cmd,
+			      struct vgcreate_params *vp)
+{
+	if (!validate_new_vg_name(cmd, vp->vg_name)) {
+		log_error("New volume group name \"%s\" is invalid",
+			  vp->vg_name);
+		return 1;
+	}
+
+	if (vp->alloc == ALLOC_INHERIT) {
+		log_error("Volume Group allocation policy cannot inherit "
+			  "from anything");
+		return 1;
+	}
+
+	if (!vp->extent_size) {
+		log_error("Physical extent size may not be zero");
+		return 1;
+	}
+
+	if (!(cmd->fmt->features & FMT_UNLIMITED_VOLS)) {
+		if (!vp->max_lv)
+			vp->max_lv = 255;
+		if (!vp->max_pv)
+			vp->max_pv = 255;
+		if (vp->max_lv > 255 || vp->max_pv > 255) {
+			log_error("Number of volumes may not exceed 255");
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name,
+			       uint32_t extent_size, uint32_t max_pv,
+			       uint32_t max_lv, alloc_policy_t alloc,
+			       int pv_count, char **pv_names)
+{
+	struct volume_group *vg;
+	struct dm_pool *mem = cmd->mem;
+	int consistent = 0;
+
+	if (!(vg = dm_pool_zalloc(mem, sizeof(*vg))))
+		return_NULL;
+
+	/* is this vg name already in use ? */
+	if (vg_read(cmd, vg_name, NULL, &consistent)) {
+		log_err("A volume group called '%s' already exists.", vg_name);
+		goto bad;
+	}
+
+	if (!id_create(&vg->id)) {
+		log_err("Couldn't create uuid for volume group '%s'.", vg_name);
+		goto bad;
+	}
+
+	/* Strip dev_dir if present */
+	vg_name = strip_dir(vg_name, cmd->dev_dir);
+
+	vg->cmd = cmd;
+
+	if (!(vg->name = dm_pool_strdup(mem, vg_name)))
+		goto_bad;
+
+	vg->seqno = 0;
+
+	vg->status = (RESIZEABLE_VG | LVM_READ | LVM_WRITE);
+	if (!(vg->system_id = dm_pool_alloc(mem, NAME_LEN)))
+		goto_bad;
+
+	*vg->system_id = '\0';
+
+	vg->extent_size = extent_size;
+	vg->extent_count = 0;
+	vg->free_count = 0;
+
+	vg->max_lv = max_lv;
+	vg->max_pv = max_pv;
+
+	vg->alloc = alloc;
+
+	vg->pv_count = 0;
+	dm_list_init(&vg->pvs);
+
+	vg->lv_count = 0;
+	dm_list_init(&vg->lvs);
+
+	vg->snapshot_count = 0;
+
+	dm_list_init(&vg->tags);
+
+	if (!(vg->fid = cmd->fmt->ops->create_instance(cmd->fmt, vg_name,
+						       NULL, NULL))) {
+		log_error("Failed to create format instance");
+		goto bad;
+	}
+
+	if (vg->fid->fmt->ops->vg_setup &&
+	    !vg->fid->fmt->ops->vg_setup(vg->fid, vg)) {
+		log_error("Format specific setup of volume group '%s' failed.",
+			  vg_name);
+		goto bad;
+	}
+
+	/* attach the pv's */
+	if (!vg_extend(vg, pv_count, pv_names))
+		goto_bad;
+
+	return vg;
+
+      bad:
+	dm_pool_free(mem, vg);
+	return NULL;
+}
+
+static int _recalc_extents(uint32_t *extents, const char *desc1,
+			   const char *desc2, uint32_t old_size,
+			   uint32_t new_size)
+{
+	uint64_t size = (uint64_t) old_size * (*extents);
+
+	if (size % new_size) {
+		log_error("New size %" PRIu64 " for %s%s not an exact number "
+			  "of new extents.", size, desc1, desc2);
+		return 0;
+	}
+
+	size /= new_size;
+
+	if (size > UINT32_MAX) {
+		log_error("New extent count %" PRIu64 " for %s%s exceeds "
+			  "32 bits.", size, desc1, desc2);
+		return 0;
+	}
+
+	*extents = (uint32_t) size;
+
+	return 1;
+}
+
+int vg_change_pesize(struct cmd_context *cmd __attribute((unused)),
+		     struct volume_group *vg, uint32_t new_size)
+{
+	uint32_t old_size = vg->extent_size;
+	struct pv_list *pvl;
+	struct lv_list *lvl;
+	struct physical_volume *pv;
+	struct logical_volume *lv;
+	struct lv_segment *seg;
+	struct pv_segment *pvseg;
+	uint32_t s;
+
+	vg->extent_size = new_size;
+
+	if (vg->fid->fmt->ops->vg_setup &&
+	    !vg->fid->fmt->ops->vg_setup(vg->fid, vg))
+		return_0;
+
+	if (!_recalc_extents(&vg->extent_count, vg->name, "", old_size,
+			     new_size))
+		return_0;
+
+	if (!_recalc_extents(&vg->free_count, vg->name, " free space",
+			     old_size, new_size))
+		return_0;
+
+	/* foreach PV */
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		pv = pvl->pv;
+
+		pv->pe_size = new_size;
+		if (!_recalc_extents(&pv->pe_count, pv_dev_name(pv), "",
+				     old_size, new_size))
+			return_0;
+
+		if (!_recalc_extents(&pv->pe_alloc_count, pv_dev_name(pv),
+				     " allocated space", old_size, new_size))
+			return_0;
+
+		/* foreach free PV Segment */
+		dm_list_iterate_items(pvseg, &pv->segments) {
+			if (pvseg_is_allocated(pvseg))
+				continue;
+
+			if (!_recalc_extents(&pvseg->pe, pv_dev_name(pv),
+					     " PV segment start", old_size,
+					     new_size))
+				return_0;
+			if (!_recalc_extents(&pvseg->len, pv_dev_name(pv),
+					     " PV segment length", old_size,
+					     new_size))
+				return_0;
+		}
+	}
+
+	/* foreach LV */
+	dm_list_iterate_items(lvl, &vg->lvs) {
+		lv = lvl->lv;
+
+		if (!_recalc_extents(&lv->le_count, lv->name, "", old_size,
+				     new_size))
+			return_0;
+
+		dm_list_iterate_items(seg, &lv->segments) {
+			if (!_recalc_extents(&seg->le, lv->name,
+					     " segment start", old_size,
+					     new_size))
+				return_0;
+
+			if (!_recalc_extents(&seg->len, lv->name,
+					     " segment length", old_size,
+					     new_size))
+				return_0;
+
+			if (!_recalc_extents(&seg->area_len, lv->name,
+					     " area length", old_size,
+					     new_size))
+				return_0;
+
+			if (!_recalc_extents(&seg->extents_copied, lv->name,
+					     " extents moved", old_size,
+					     new_size))
+				return_0;
+
+			/* foreach area */
+			for (s = 0; s < seg->area_count; s++) {
+				switch (seg_type(seg, s)) {
+				case AREA_PV:
+					if (!_recalc_extents
+					    (&seg_pe(seg, s),
+					     lv->name,
+					     " pvseg start", old_size,
+					     new_size))
+						return_0;
+					if (!_recalc_extents
+					    (&seg_pvseg(seg, s)->len,
+					     lv->name,
+					     " pvseg length", old_size,
+					     new_size))
+						return_0;
+					break;
+				case AREA_LV:
+					if (!_recalc_extents
+					    (&seg_le(seg, s), lv->name,
+					     " area start", old_size,
+					     new_size))
+						return_0;
+					break;
+				case AREA_UNASSIGNED:
+					log_error("Unassigned area %u found in "
+						  "segment", s);
+					return 0;
+				}
+			}
+		}
+
+	}
+
+	return 1;
+}
+
+/*
+ * Separate metadata areas after splitting a VG.
+ * Also accepts orphan VG as destination (for vgreduce).
+ */
+int vg_split_mdas(struct cmd_context *cmd __attribute((unused)),
+		  struct volume_group *vg_from, struct volume_group *vg_to)
+{
+	struct metadata_area *mda, *mda2;
+	struct dm_list *mdas_from, *mdas_to;
+	int common_mda = 0;
+
+	mdas_from = &vg_from->fid->metadata_areas;
+	mdas_to = &vg_to->fid->metadata_areas;
+
+	dm_list_iterate_items_safe(mda, mda2, mdas_from) {
+		if (!mda->ops->mda_in_vg) {
+			common_mda = 1;
+			continue;
+		}
+
+		if (!mda->ops->mda_in_vg(vg_from->fid, vg_from, mda)) {
+			if (is_orphan_vg(vg_to->name))
+				dm_list_del(&mda->list);
+			else
+				dm_list_move(mdas_to, &mda->list);
+		}
+	}
+
+	if (dm_list_empty(mdas_from) ||
+	    (!is_orphan_vg(vg_to->name) && dm_list_empty(mdas_to)))
+		return common_mda;
+
+	return 1;
+}
+
+/**
+ * pv_create - initialize a physical volume for use with a volume group
+ * @fmt: format type
+ * @dev: PV device to initialize
+ * @id: PV UUID to use for initialization
+ * @size: size of the PV in sectors
+ * @pe_start: physical extent start
+ * @existing_extent_count
+ * @existing_extent_size
+ * @pvmetadatacopies
+ * @pvmetadatasize
+ * @mdas
+ *
+ * Returns:
+ *   PV handle - physical volume initialized successfully
+ *   NULL - invalid parameter or problem initializing the physical volume
+ *
+ * Note:
+ *   FIXME - liblvm todo - tidy up arguments for external use (fmt, mdas, etc)
+ */
+pv_t *pv_create(const struct cmd_context *cmd,
+		struct device *dev,
+		struct id *id, uint64_t size,
+		uint64_t pe_start,
+		uint32_t existing_extent_count,
+		uint32_t existing_extent_size,
+		int pvmetadatacopies,
+		uint64_t pvmetadatasize, struct dm_list *mdas)
+{
+	return _pv_create(cmd->fmt, dev, id, size, pe_start,
+			  existing_extent_count,
+			  existing_extent_size,
+			  pvmetadatacopies,
+			  pvmetadatasize, mdas);
+}
+
+static void _free_pv(struct dm_pool *mem, struct physical_volume *pv)
+{
+	dm_pool_free(mem, pv);
+}
+
+static struct physical_volume *_alloc_pv(struct dm_pool *mem, struct device *dev)
+{
+	struct physical_volume *pv = dm_pool_zalloc(mem, sizeof(*pv));
+
+	if (!pv)
+		return_NULL;
+
+	if (!(pv->vg_name = dm_pool_zalloc(mem, NAME_LEN))) {
+		dm_pool_free(mem, pv);
+		return NULL;
+	}
+
+	pv->pe_size = 0;
+	pv->pe_start = 0;
+	pv->pe_count = 0;
+	pv->pe_alloc_count = 0;
+	pv->pe_align = 0;
+	pv->fmt = NULL;
+	pv->dev = dev;
+
+	pv->status = ALLOCATABLE_PV;
+
+	dm_list_init(&pv->tags);
+	dm_list_init(&pv->segments);
+
+	return pv;
+}
+
+/* Sizes in sectors */
+static struct physical_volume *_pv_create(const struct format_type *fmt,
+				  struct device *dev,
+				  struct id *id, uint64_t size,
+				  uint64_t pe_start,
+				  uint32_t existing_extent_count,
+				  uint32_t existing_extent_size,
+				  int pvmetadatacopies,
+				  uint64_t pvmetadatasize, struct dm_list *mdas)
+{
+	struct dm_pool *mem = fmt->cmd->mem;
+	struct physical_volume *pv = _alloc_pv(mem, dev);
+
+	if (!pv)
+		return NULL;
+
+	if (id)
+		memcpy(&pv->id, id, sizeof(*id));
+	else if (!id_create(&pv->id)) {
+		log_error("Failed to create random uuid for %s.",
+			  dev_name(dev));
+		goto bad;
+	}
+
+	if (!dev_get_size(pv->dev, &pv->size)) {
+		log_error("%s: Couldn't get size.", pv_dev_name(pv));
+		goto bad;
+	}
+
+	if (size) {
+		if (size > pv->size)
+			log_warn("WARNING: %s: Overriding real size. "
+				  "You could lose data.", pv_dev_name(pv));
+		log_verbose("%s: Pretending size is %" PRIu64 " sectors.",
+			    pv_dev_name(pv), size);
+		pv->size = size;
+	}
+
+	if (pv->size < PV_MIN_SIZE) {
+		log_error("%s: Size must exceed minimum of %ld sectors.",
+			  pv_dev_name(pv), PV_MIN_SIZE);
+		goto bad;
+	}
+
+	pv->fmt = fmt;
+	pv->vg_name = fmt->orphan_vg_name;
+
+	if (!fmt->ops->pv_setup(fmt, pe_start, existing_extent_count,
+				existing_extent_size,
+				pvmetadatacopies, pvmetadatasize, mdas,
+				pv, NULL)) {
+		log_error("%s: Format-specific setup of physical volume "
+			  "failed.", pv_dev_name(pv));
+		goto bad;
+	}
+	return pv;
+
+      bad:
+	_free_pv(mem, pv);
+	return NULL;
+}
+
+/* FIXME: liblvm todo - make into function that returns handle */
+struct pv_list *find_pv_in_vg(const struct volume_group *vg,
+			      const char *pv_name)
+{
+	return _find_pv_in_vg(vg, pv_name);
+}
+
+static struct pv_list *_find_pv_in_vg(const struct volume_group *vg,
+				      const char *pv_name)
+{
+	struct pv_list *pvl;
+
+	dm_list_iterate_items(pvl, &vg->pvs)
+		if (pvl->pv->dev == dev_cache_get(pv_name, vg->cmd->filter))
+			return pvl;
+
+	return NULL;
+}
+
+struct pv_list *find_pv_in_pv_list(const struct dm_list *pl,
+				   const struct physical_volume *pv)
+{
+	struct pv_list *pvl;
+
+	dm_list_iterate_items(pvl, pl)
+		if (pvl->pv == pv)
+			return pvl;
+
+	return NULL;
+}
+
+int pv_is_in_vg(struct volume_group *vg, struct physical_volume *pv)
+{
+	struct pv_list *pvl;
+
+	dm_list_iterate_items(pvl, &vg->pvs)
+		if (pv == pvl->pv)
+			 return 1;
+
+	return 0;
+}
+
+/**
+ * find_pv_in_vg_by_uuid - Find PV in VG by PV UUID
+ * @vg: volume group to search
+ * @id: UUID of the PV to match
+ *
+ * Returns:
+ *   PV handle - if UUID of PV found in VG
+ *   NULL - invalid parameter or UUID of PV not found in VG
+ *
+ * Note
+ *   FIXME - liblvm todo - make into function that takes VG handle
+ */
+pv_t *find_pv_in_vg_by_uuid(const struct volume_group *vg,
+			    const struct id *id)
+{
+	return _find_pv_in_vg_by_uuid(vg, id);
+}
+
+
+static struct physical_volume *_find_pv_in_vg_by_uuid(const struct volume_group *vg,
+						      const struct id *id)
+{
+	struct pv_list *pvl;
+
+	dm_list_iterate_items(pvl, &vg->pvs)
+		if (id_equal(&pvl->pv->id, id))
+			return pvl->pv;
+
+	return NULL;
+}
+
+struct lv_list *find_lv_in_vg(const struct volume_group *vg,
+			      const char *lv_name)
+{
+	struct lv_list *lvl;
+	const char *ptr;
+
+	/* Use last component */
+	if ((ptr = strrchr(lv_name, '/')))
+		ptr++;
+	else
+		ptr = lv_name;
+
+	dm_list_iterate_items(lvl, &vg->lvs)
+		if (!strcmp(lvl->lv->name, ptr))
+			return lvl;
+
+	return NULL;
+}
+
+struct lv_list *find_lv_in_lv_list(const struct dm_list *ll,
+				   const struct logical_volume *lv)
+{
+	struct lv_list *lvl;
+
+	dm_list_iterate_items(lvl, ll)
+		if (lvl->lv == lv)
+			return lvl;
+
+	return NULL;
+}
+
+struct lv_list *find_lv_in_vg_by_lvid(struct volume_group *vg,
+				      const union lvid *lvid)
+{
+	struct lv_list *lvl;
+
+	dm_list_iterate_items(lvl, &vg->lvs)
+		if (!strncmp(lvl->lv->lvid.s, lvid->s, sizeof(*lvid)))
+			return lvl;
+
+	return NULL;
+}
+
+struct logical_volume *find_lv(const struct volume_group *vg,
+			       const char *lv_name)
+{
+	struct lv_list *lvl = find_lv_in_vg(vg, lv_name);
+	return lvl ? lvl->lv : NULL;
+}
+
+struct physical_volume *find_pv(struct volume_group *vg, struct device *dev)
+{
+	struct pv_list *pvl;
+
+	dm_list_iterate_items(pvl, &vg->pvs)
+		if (dev == pvl->pv->dev)
+			return pvl->pv;
+
+	return NULL;
+}
+
+/* FIXME: liblvm todo - make into function that returns handle */
+struct physical_volume *find_pv_by_name(struct cmd_context *cmd,
+					const char *pv_name)
+{
+	return _find_pv_by_name(cmd, pv_name);
+}
+
+
+static struct physical_volume *_find_pv_by_name(struct cmd_context *cmd,
+			 			const char *pv_name)
+{
+	struct physical_volume *pv;
+
+	if (!(pv = _pv_read(cmd, pv_name, NULL, NULL, 1))) {
+		log_error("Physical volume %s not found", pv_name);
+		return NULL;
+	}
+
+	if (is_orphan_vg(pv->vg_name)) {
+		/* If a PV has no MDAs - need to search all VGs for it */
+		if (!scan_vgs_for_pvs(cmd))
+			return_NULL;
+		if (!(pv = _pv_read(cmd, pv_name, NULL, NULL, 1))) {
+			log_error("Physical volume %s not found", pv_name);
+			return NULL;
+		}
+	}
+
+	if (is_orphan_vg(pv->vg_name)) {
+		log_error("Physical volume %s not in a volume group", pv_name);
+		return NULL;
+	}
+
+	return pv;
+}
+
+/* Find segment at a given logical extent in an LV */
+struct lv_segment *find_seg_by_le(const struct logical_volume *lv, uint32_t le)
+{
+	struct lv_segment *seg;
+
+	dm_list_iterate_items(seg, &lv->segments)
+		if (le >= seg->le && le < seg->le + seg->len)
+			return seg;
+
+	return NULL;
+}
+
+struct lv_segment *first_seg(const struct logical_volume *lv)
+{
+	struct lv_segment *seg = NULL;
+
+	dm_list_iterate_items(seg, &lv->segments)
+		break;
+
+	return seg;
+}
+
+/* Find segment at a given physical extent in a PV */
+struct pv_segment *find_peg_by_pe(const struct physical_volume *pv, uint32_t pe)
+{
+	struct pv_segment *peg;
+
+	dm_list_iterate_items(peg, &pv->segments)
+		if (pe >= peg->pe && pe < peg->pe + peg->len)
+			return peg;
+
+	return NULL;
+}
+
+int vg_remove(struct volume_group *vg)
+{
+	struct metadata_area *mda;
+
+	/* FIXME Improve recovery situation? */
+	/* Remove each copy of the metadata */
+	dm_list_iterate_items(mda, &vg->fid->metadata_areas) {
+		if (mda->ops->vg_remove &&
+		    !mda->ops->vg_remove(vg->fid, vg, mda))
+			return_0;
+	}
+
+	return 1;
+}
+
+/*
+ * Determine whether two vgs are compatible for merging.
+ */
+int vgs_are_compatible(struct cmd_context *cmd __attribute((unused)),
+		       struct volume_group *vg_from,
+		       struct volume_group *vg_to)
+{
+	struct lv_list *lvl1, *lvl2;
+	struct pv_list *pvl;
+	char *name1, *name2;
+
+	if (lvs_in_vg_activated(vg_from)) {
+		log_error("Logical volumes in \"%s\" must be inactive",
+			  vg_from->name);
+		return 0;
+	}
+
+	/* Check compatibility */
+	if (vg_to->extent_size != vg_from->extent_size) {
+		log_error("Extent sizes differ: %d (%s) and %d (%s)",
+			  vg_to->extent_size, vg_to->name,
+			  vg_from->extent_size, vg_from->name);
+		return 0;
+	}
+
+	if (vg_to->max_pv &&
+	    (vg_to->max_pv < vg_to->pv_count + vg_from->pv_count)) {
+		log_error("Maximum number of physical volumes (%d) exceeded "
+			  " for \"%s\" and \"%s\"", vg_to->max_pv, vg_to->name,
+			  vg_from->name);
+		return 0;
+	}
+
+	if (vg_to->max_lv &&
+	    (vg_to->max_lv < vg_to->lv_count + vg_from->lv_count)) {
+		log_error("Maximum number of logical volumes (%d) exceeded "
+			  " for \"%s\" and \"%s\"", vg_to->max_lv, vg_to->name,
+			  vg_from->name);
+		return 0;
+	}
+
+	/* Metadata types must be the same */
+	if (vg_to->fid->fmt != vg_from->fid->fmt) {
+		log_error("Metadata types differ for \"%s\" and \"%s\"",
+			  vg_to->name, vg_from->name);
+		return 0;
+	}
+
+	/* Clustering attribute must be the same */
+	if (vg_is_clustered(vg_to) != vg_is_clustered(vg_from)) {
+		log_error("Clustered attribute differs for \"%s\" and \"%s\"",
+			  vg_to->name, vg_from->name);
+		return 0;
+	}
+
+	/* Check no conflicts with LV names */
+	dm_list_iterate_items(lvl1, &vg_to->lvs) {
+		name1 = lvl1->lv->name;
+
+		dm_list_iterate_items(lvl2, &vg_from->lvs) {
+			name2 = lvl2->lv->name;
+
+			if (!strcmp(name1, name2)) {
+				log_error("Duplicate logical volume "
+					  "name \"%s\" "
+					  "in \"%s\" and \"%s\"",
+					  name1, vg_to->name, vg_from->name);
+				return 0;
+			}
+		}
+	}
+
+	/* Check no PVs are constructed from either VG */
+	dm_list_iterate_items(pvl, &vg_to->pvs) {
+		if (pv_uses_vg(pvl->pv, vg_from)) {
+			log_error("Physical volume %s might be constructed "
+				  "from same volume group %s.",
+				  pv_dev_name(pvl->pv), vg_from->name);
+			return 0;
+		}
+	}
+
+	dm_list_iterate_items(pvl, &vg_from->pvs) {
+		if (pv_uses_vg(pvl->pv, vg_to)) {
+			log_error("Physical volume %s might be constructed "
+				  "from same volume group %s.",
+				  pv_dev_name(pvl->pv), vg_to->name);
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+struct _lv_postorder_baton {
+	int (*fn)(struct logical_volume *lv, void *data);
+	void *data;
+};
+
+static int _lv_postorder_visit(struct logical_volume *,
+			       int (*fn)(struct logical_volume *lv, void *data),
+			       void *data);
+
+static int _lv_postorder_level(struct logical_volume *lv, void *data)
+{
+	struct _lv_postorder_baton *baton = data;
+	if (lv->status & POSTORDER_OPEN_FLAG)
+		return 1; // a data structure loop has closed...
+	lv->status |= POSTORDER_OPEN_FLAG;
+	int r =_lv_postorder_visit(lv, baton->fn, baton->data);
+	lv->status &= ~POSTORDER_OPEN_FLAG;
+	lv->status |= POSTORDER_FLAG;
+	return r;
+};
+
+static int _lv_each_dependency(struct logical_volume *lv,
+			       int (*fn)(struct logical_volume *lv, void *data),
+			       void *data)
+{
+	int i, s;
+	struct lv_segment *lvseg;
+
+	struct logical_volume *deps[] = {
+		lv->snapshot ? lv->snapshot->origin : 0,
+		lv->snapshot ? lv->snapshot->cow : 0 };
+	for (i = 0; i < sizeof(deps) / sizeof(*deps); ++i) {
+		if (deps[i] && !fn(deps[i], data))
+			return_0;
+	}
+
+	dm_list_iterate_items(lvseg, &lv->segments) {
+		if (lvseg->log_lv && !fn(lvseg->log_lv, data))
+			return_0;
+		for (s = 0; s < lvseg->area_count; ++s) {
+			if (seg_type(lvseg, s) == AREA_LV && !fn(seg_lv(lvseg,s), data))
+				return_0;
+		}
+	}
+	return 1;
+}
+
+static int _lv_postorder_cleanup(struct logical_volume *lv, void *data)
+{
+	if (!(lv->status & POSTORDER_FLAG))
+		return 1;
+	lv->status &= ~POSTORDER_FLAG;
+
+	if (!_lv_each_dependency(lv, _lv_postorder_cleanup, data))
+		return_0;
+	return 1;
+}
+
+static int _lv_postorder_visit(struct logical_volume *lv,
+			       int (*fn)(struct logical_volume *lv, void *data),
+			       void *data)
+{
+	struct _lv_postorder_baton baton;
+	int r;
+
+	if (lv->status & POSTORDER_FLAG)
+		return 1;
+
+	baton.fn = fn;
+	baton.data = data;
+	r = _lv_each_dependency(lv, _lv_postorder_level, &baton);
+	if (r) {
+		r = fn(lv, data);
+		log_verbose("visited %s", lv->name);
+	}
+	return r;
+}
+
+/*
+ * This will walk the LV dependency graph in depth-first order and in the
+ * postorder, call a callback function "fn". The void *data is passed along all
+ * the calls. The callback may return zero to indicate an error and terminate
+ * the depth-first walk. The error is propagated to return value of
+ * _lv_postorder.
+ */
+static int _lv_postorder(struct logical_volume *lv,
+			       int (*fn)(struct logical_volume *lv, void *data),
+			       void *data)
+{
+	int r;
+	r = _lv_postorder_visit(lv, fn, data);
+	_lv_postorder_cleanup(lv, 0);
+	return r;
+}
+
+struct _lv_mark_if_partial_baton {
+	int partial;
+};
+
+static int _lv_mark_if_partial_collect(struct logical_volume *lv, void *data)
+{
+	struct _lv_mark_if_partial_baton *baton = data;
+	if (lv->status & PARTIAL_LV)
+		baton->partial = 1;
+
+	return 1;
+}
+
+static int _lv_mark_if_partial_single(struct logical_volume *lv, void *data)
+{
+	int s;
+	struct _lv_mark_if_partial_baton baton;
+	struct lv_segment *lvseg;
+
+	dm_list_iterate_items(lvseg, &lv->segments) {
+		for (s = 0; s < lvseg->area_count; ++s) {
+			if (seg_type(lvseg, s) == AREA_PV) {
+				if (seg_pv(lvseg, s)->status & MISSING_PV)
+					lv->status |= PARTIAL_LV;
+			}
+		}
+	}
+
+	baton.partial = 0;
+	_lv_each_dependency(lv, _lv_mark_if_partial_collect, &baton);
+
+	if (baton.partial)
+		lv->status |= PARTIAL_LV;
+
+	return 1;
+}
+
+static int _lv_mark_if_partial(struct logical_volume *lv)
+{
+	return _lv_postorder(lv, _lv_mark_if_partial_single, NULL);
+}
+
+/*
+ * Mark LVs with missing PVs using PARTIAL_LV status flag. The flag is
+ * propagated transitively, so LVs referencing other LVs are marked
+ * partial as well, if any of their referenced LVs are marked partial.
+ */
+static int _vg_mark_partial_lvs(struct volume_group *vg)
+{
+	struct logical_volume *lv;
+	struct lv_list *lvl;
+
+	dm_list_iterate_items(lvl, &vg->lvs) {
+		lv = lvl->lv;
+		if (!_lv_mark_if_partial(lv))
+			return_0;
+	}
+	return 1;
+}
+
+int vg_validate(struct volume_group *vg)
+{
+	struct pv_list *pvl, *pvl2;
+	struct lv_list *lvl, *lvl2;
+	char uuid[64] __attribute((aligned(8)));
+	int r = 1;
+	uint32_t lv_count;
+
+	/* FIXME Also check there's no data/metadata overlap */
+
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		dm_list_iterate_items(pvl2, &vg->pvs) {
+			if (pvl == pvl2)
+				break;
+			if (id_equal(&pvl->pv->id,
+				     &pvl2->pv->id)) {
+				if (!id_write_format(&pvl->pv->id, uuid,
+						     sizeof(uuid)))
+					 stack;
+				log_error("Internal error: Duplicate PV id "
+					  "%s detected for %s in %s.",
+					  uuid, pv_dev_name(pvl->pv),
+					  vg->name);
+				r = 0;
+			}
+		}
+
+		if (strcmp(pvl->pv->vg_name, vg->name)) {
+			log_error("Internal error: VG name for PV %s is corrupted",
+				  pv_dev_name(pvl->pv));
+			r = 0;
+		}
+	}
+
+	if (!check_pv_segments(vg)) {
+		log_error("Internal error: PV segments corrupted in %s.",
+			  vg->name);
+		r = 0;
+	}
+
+	if ((lv_count = (uint32_t) dm_list_size(&vg->lvs)) !=
+	    vg->lv_count + 2 * vg->snapshot_count) {
+		log_error("Internal error: #internal LVs (%u) != #LVs (%"
+			  PRIu32 ") + 2 * #snapshots (%" PRIu32 ") in VG %s",
+			  dm_list_size(&vg->lvs), vg->lv_count,
+			  vg->snapshot_count, vg->name);
+		r = 0;
+	}
+
+	dm_list_iterate_items(lvl, &vg->lvs) {
+		dm_list_iterate_items(lvl2, &vg->lvs) {
+			if (lvl == lvl2)
+				break;
+			if (!strcmp(lvl->lv->name, lvl2->lv->name)) {
+				log_error("Internal error: Duplicate LV name "
+					  "%s detected in %s.", lvl->lv->name,
+					  vg->name);
+				r = 0;
+			}
+			if (id_equal(&lvl->lv->lvid.id[1],
+				     &lvl2->lv->lvid.id[1])) {
+				if (!id_write_format(&lvl->lv->lvid.id[1], uuid,
+						     sizeof(uuid)))
+					 stack;
+				log_error("Internal error: Duplicate LV id "
+					  "%s detected for %s and %s in %s.",
+					  uuid, lvl->lv->name, lvl2->lv->name,
+					  vg->name);
+				r = 0;
+			}
+		}
+	}
+
+	dm_list_iterate_items(lvl, &vg->lvs) {
+		if (!check_lv_segments(lvl->lv, 1)) {
+			log_error("Internal error: LV segments corrupted in %s.",
+				  lvl->lv->name);
+			r = 0;
+		}
+	}
+
+	if (!(vg->fid->fmt->features & FMT_UNLIMITED_VOLS) &&
+	    (!vg->max_lv || !vg->max_pv)) {
+		log_error("Internal error: Volume group %s has limited PV/LV count"
+			  " but limit is not set.", vg->name);
+		r = 0;
+	}
+
+	return r;
+}
+
+/*
+ * After vg_write() returns success,
+ * caller MUST call either vg_commit() or vg_revert()
+ */
+int vg_write(struct volume_group *vg)
+{
+	struct dm_list *mdah;
+	struct metadata_area *mda;
+
+	if (!vg_validate(vg))
+		return_0;
+
+	if (vg->status & PARTIAL_VG) {
+		log_error("Cannot update partial volume group %s.", vg->name);
+		return 0;
+	}
+
+	if (vg_missing_pv_count(vg) && !vg->cmd->handles_missing_pvs) {
+		log_error("Cannot update volume group %s while physical "
+			  "volumes are missing.", vg->name);
+		return 0;
+	}
+
+	if (dm_list_empty(&vg->fid->metadata_areas)) {
+		log_error("Aborting vg_write: No metadata areas to write to!");
+		return 0;
+	}
+
+	if (!drop_cached_metadata(vg)) {
+		log_error("Unable to drop cached metadata for VG %s.", vg->name);
+		return 0;
+	}
+
+	vg->seqno++;
+
+	/* Write to each copy of the metadata area */
+	dm_list_iterate_items(mda, &vg->fid->metadata_areas) {
+		if (!mda->ops->vg_write) {
+			log_error("Format does not support writing volume"
+				  "group metadata areas");
+			/* Revert */
+			dm_list_uniterate(mdah, &vg->fid->metadata_areas, &mda->list) {
+				mda = dm_list_item(mdah, struct metadata_area);
+
+				if (mda->ops->vg_revert &&
+				    !mda->ops->vg_revert(vg->fid, vg, mda)) {
+					stack;
+				}
+			}
+			return 0;
+		}
+		if (!mda->ops->vg_write(vg->fid, vg, mda)) {
+			stack;
+			/* Revert */
+			dm_list_uniterate(mdah, &vg->fid->metadata_areas, &mda->list) {
+				mda = dm_list_item(mdah, struct metadata_area);
+
+				if (mda->ops->vg_revert &&
+				    !mda->ops->vg_revert(vg->fid, vg, mda)) {
+					stack;
+				}
+			}
+			return 0;
+		}
+	}
+
+	/* Now pre-commit each copy of the new metadata */
+	dm_list_iterate_items(mda, &vg->fid->metadata_areas) {
+		if (mda->ops->vg_precommit &&
+		    !mda->ops->vg_precommit(vg->fid, vg, mda)) {
+			stack;
+			/* Revert */
+			dm_list_iterate_items(mda, &vg->fid->metadata_areas) {
+				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 metadata_area *mda;
+	int cache_updated = 0;
+	int failed = 0;
+
+	if (!vgname_is_locked(vg->name)) {
+		log_error("Internal error: Attempt to write new VG metadata "
+			  "without locking %s", vg->name);
+		return cache_updated;
+	}
+
+	/* Commit to each copy of the metadata area */
+	dm_list_iterate_items(mda, &vg->fid->metadata_areas) {
+		failed = 0;
+		if (mda->ops->vg_commit &&
+		    !mda->ops->vg_commit(vg->fid, vg, mda)) {
+			stack;
+			failed = 1;
+		}
+		/* Update cache first time we succeed */
+		if (!failed && !cache_updated) {
+			lvmcache_update_vg(vg, 0);
+			cache_updated = 1;
+		}
+	}
+
+	/* If update failed, remove any cached precommitted metadata. */
+	if (!cache_updated && !drop_cached_metadata(vg))
+		log_error("Attempt to drop cached metadata failed "
+			  "after commit for VG %s.", vg->name);
+
+	/* 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 metadata_area *mda;
+
+	dm_list_iterate_items(mda, &vg->fid->metadata_areas) {
+		if (mda->ops->vg_revert &&
+		    !mda->ops->vg_revert(vg->fid, vg, mda)) {
+			stack;
+		}
+	}
+
+	if (!drop_cached_metadata(vg))
+		log_error("Attempt to drop cached metadata failed "
+			  "after reverted update for VG %s.", vg->name);
+
+	return 1;
+}
+
+/* Make orphan PVs look like a VG */
+static struct volume_group *_vg_read_orphans(struct cmd_context *cmd,
+					     const char *orphan_vgname)
+{
+	struct lvmcache_vginfo *vginfo;
+	struct lvmcache_info *info;
+	struct pv_list *pvl;
+	struct volume_group *vg;
+	struct physical_volume *pv;
+
+	lvmcache_label_scan(cmd, 0);
+
+	if (!(vginfo = vginfo_from_vgname(orphan_vgname, NULL)))
+		return_NULL;
+
+	if (!(vg = dm_pool_zalloc(cmd->mem, sizeof(*vg)))) {
+		log_error("vg allocation failed");
+		return NULL;
+	}
+	dm_list_init(&vg->pvs);
+	dm_list_init(&vg->lvs);
+	dm_list_init(&vg->tags);
+	vg->cmd = cmd;
+	if (!(vg->name = dm_pool_strdup(cmd->mem, orphan_vgname))) {
+		log_error("vg name allocation failed");
+		return NULL;
+	}
+
+	/* create format instance with appropriate metadata area */
+	if (!(vg->fid = vginfo->fmt->ops->create_instance(vginfo->fmt,
+							  orphan_vgname, NULL,
+							  NULL))) {
+		log_error("Failed to create format instance");
+		dm_pool_free(cmd->mem, vg);
+		return NULL;
+	}
+
+	dm_list_iterate_items(info, &vginfo->infos) {
+		if (!(pv = _pv_read(cmd, dev_name(info->dev), NULL, NULL, 1))) {
+			continue;
+		}
+		if (!(pvl = dm_pool_zalloc(cmd->mem, sizeof(*pvl)))) {
+			log_error("pv_list allocation failed");
+			return NULL;
+		}
+		pvl->pv = pv;
+		dm_list_add(&vg->pvs, &pvl->list);
+		vg->pv_count++;
+	}
+
+	return vg;
+}
+
+static int _update_pv_list(struct dm_list *all_pvs, struct volume_group *vg)
+{
+	struct pv_list *pvl, *pvl2;
+
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		dm_list_iterate_items(pvl2, all_pvs) {
+			if (pvl->pv->dev == pvl2->pv->dev)
+				goto next_pv;
+		}
+		/* PV is not on list so add it.  Note that we don't copy it. */
+       		if (!(pvl2 = dm_pool_zalloc(vg->cmd->mem, sizeof(*pvl2)))) {
+			log_error("pv_list allocation for '%s' failed",
+				  pv_dev_name(pvl->pv));
+			return 0;
+		}
+		pvl2->pv = pvl->pv;
+		dm_list_add(all_pvs, &pvl2->list);
+  next_pv:
+		;
+	}
+
+	return 1;
+}
+
+int vg_missing_pv_count(const vg_t *vg)
+{
+	int ret = 0;
+	struct pv_list *pvl;
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		if (pvl->pv->status & MISSING_PV)
+			++ ret;
+	}
+	return ret;
+}
+
+/* Caller sets consistent to 1 if it's safe for vg_read to correct
+ * inconsistent metadata on disk (i.e. the VG write lock is held).
+ * This guarantees only consistent metadata is returned.
+ * If consistent is 0, caller must check whether consistent == 1 on return
+ * and take appropriate action if it isn't (e.g. abort; get write lock
+ * and call vg_read again).
+ *
+ * If precommitted is set, use precommitted metadata if present.
+ *
+ * Either of vgname or vgid may be NULL.
+ */
+static struct volume_group *_vg_read(struct cmd_context *cmd,
+				     const char *vgname,
+				     const char *vgid,
+				     int *consistent, unsigned precommitted)
+{
+	struct format_instance *fid;
+	const struct format_type *fmt;
+	struct volume_group *vg, *correct_vg = NULL;
+	struct metadata_area *mda;
+	struct lvmcache_info *info;
+	int inconsistent = 0;
+	int inconsistent_vgid = 0;
+	int inconsistent_pvs = 0;
+	unsigned use_precommitted = precommitted;
+	struct dm_list *pvids;
+	struct pv_list *pvl, *pvl2;
+	struct dm_list all_pvs;
+	char uuid[64] __attribute((aligned(8)));
+
+	if (is_orphan_vg(vgname)) {
+		if (use_precommitted) {
+			log_error("Internal error: vg_read requires vgname "
+				  "with pre-commit.");
+			return NULL;
+		}
+		*consistent = 1;
+		return _vg_read_orphans(cmd, vgname);
+	}
+
+	if ((correct_vg = lvmcache_get_vg(vgid, precommitted))) {
+		if (vg_missing_pv_count(correct_vg)) {
+			log_verbose("There are %d physical volumes missing.",
+				    vg_missing_pv_count(correct_vg));
+			_vg_mark_partial_lvs(correct_vg);
+		}
+		*consistent = 1;
+		return correct_vg;
+	}
+
+	/* 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, vgid))) {
+		lvmcache_label_scan(cmd, 0);
+		if (!(fmt = fmt_from_vgname(vgname, vgid))) {
+			if (memlock())
+				return_NULL;
+			lvmcache_label_scan(cmd, 2);
+			if (!(fmt = fmt_from_vgname(vgname, vgid)))
+				return_NULL;
+		}
+	}
+
+	/* Now determine the correct vgname if none was supplied */
+	if (!vgname && !(vgname = vgname_from_vgid(cmd->mem, vgid)))
+		return_NULL;
+
+	if (use_precommitted && !(fmt->features & FMT_PRECOMMIT))
+		use_precommitted = 0;
+
+	/* create format instance with appropriate metadata area */
+	if (!(fid = fmt->ops->create_instance(fmt, vgname, vgid, NULL))) {
+		log_error("Failed to create format instance");
+		return NULL;
+	}
+
+	/* Store pvids for later so we can check if any are missing */
+	if (!(pvids = lvmcache_get_pvids(cmd, vgname, vgid)))
+		return_NULL;
+
+	/* Ensure contents of all metadata areas match - else do recovery */
+	dm_list_iterate_items(mda, &fid->metadata_areas) {
+		if ((use_precommitted &&
+		     !(vg = mda->ops->vg_read_precommit(fid, vgname, mda))) ||
+		    (!use_precommitted &&
+		     !(vg = mda->ops->vg_read(fid, vgname, mda)))) {
+			inconsistent = 1;
+			continue;
+		}
+		if (!correct_vg) {
+			correct_vg = vg;
+			continue;
+		}
+		/* FIXME Also ensure contents same - checksum compare? */
+		if (correct_vg->seqno != vg->seqno) {
+			inconsistent = 1;
+			if (vg->seqno > correct_vg->seqno)
+				correct_vg = vg;
+		}
+	}
+
+	/* Ensure every PV in the VG was in the cache */
+	if (correct_vg) {
+		/*
+		 * If the VG has PVs without mdas, they may still be
+		 * orphans in the cache: update the cache state here.
+		 */
+		if (!inconsistent &&
+		    dm_list_size(&correct_vg->pvs) > dm_list_size(pvids)) {
+			dm_list_iterate_items(pvl, &correct_vg->pvs) {
+				if (!pvl->pv->dev) {
+					inconsistent_pvs = 1;
+					break;
+				}
+
+				if (str_list_match_item(pvids, pvl->pv->dev->pvid))
+					continue;
+
+				/*
+				 * PV not marked as belonging to this VG in cache.
+				 * Check it's an orphan without metadata area.
+				 */
+				if (!(info = info_from_pvid(pvl->pv->dev->pvid, 1)) ||
+				   !info->vginfo || !is_orphan_vg(info->vginfo->vgname) ||
+				   dm_list_size(&info->mdas)) {
+					inconsistent_pvs = 1;
+					break;
+				}
+			}
+
+			/* If the check passed, let's update VG and recalculate pvids */
+			if (!inconsistent_pvs) {
+				log_debug("Updating cache for PVs without mdas "
+					  "in VG %s.", vgname);
+				lvmcache_update_vg(correct_vg, use_precommitted);
+
+				if (!(pvids = lvmcache_get_pvids(cmd, vgname, vgid)))
+					return_NULL;
+			}
+		}
+
+		if (dm_list_size(&correct_vg->pvs) != dm_list_size(pvids)
+		    + vg_missing_pv_count(correct_vg)) {
+			log_debug("Cached VG %s had incorrect PV list",
+				  vgname);
+
+			if (memlock())
+				inconsistent = 1;
+			else
+				correct_vg = NULL;
+		} else dm_list_iterate_items(pvl, &correct_vg->pvs) {
+			if (pvl->pv->status & MISSING_PV)
+				continue;
+			if (!str_list_match_item(pvids, pvl->pv->dev->pvid)) {
+				log_debug("Cached VG %s had incorrect PV list",
+					  vgname);
+				correct_vg = NULL;
+				break;
+			}
+		}
+	}
+
+	dm_list_init(&all_pvs);
+
+	/* Failed to find VG where we expected it - full scan and retry */
+	if (!correct_vg) {
+		inconsistent = 0;
+
+		if (memlock())
+			return_NULL;
+		lvmcache_label_scan(cmd, 2);
+		if (!(fmt = fmt_from_vgname(vgname, vgid)))
+			return_NULL;
+
+		if (precommitted && !(fmt->features & FMT_PRECOMMIT))
+			use_precommitted = 0;
+
+		/* create format instance with appropriate metadata area */
+		if (!(fid = fmt->ops->create_instance(fmt, vgname, vgid, NULL))) {
+			log_error("Failed to create format instance");
+			return NULL;
+		}
+
+		/* Ensure contents of all metadata areas match - else recover */
+		dm_list_iterate_items(mda, &fid->metadata_areas) {
+			if ((use_precommitted &&
+			     !(vg = mda->ops->vg_read_precommit(fid, vgname,
+								mda))) ||
+			    (!use_precommitted &&
+			     !(vg = mda->ops->vg_read(fid, vgname, mda)))) {
+				inconsistent = 1;
+				continue;
+			}
+			if (!correct_vg) {
+				correct_vg = vg;
+				if (!_update_pv_list(&all_pvs, correct_vg))
+					return_NULL;
+				continue;
+			}
+
+			if (strncmp((char *)vg->id.uuid,
+			    (char *)correct_vg->id.uuid, ID_LEN)) {
+				inconsistent = 1;
+				inconsistent_vgid = 1;
+			}
+
+			/* FIXME Also ensure contents same - checksums same? */
+			if (correct_vg->seqno != vg->seqno) {
+				inconsistent = 1;
+				if (!_update_pv_list(&all_pvs, vg))
+					return_NULL;
+				if (vg->seqno > correct_vg->seqno)
+					correct_vg = vg;
+			}
+		}
+
+		/* Give up looking */
+		if (!correct_vg)
+			return_NULL;
+	}
+
+	lvmcache_update_vg(correct_vg, use_precommitted);
+
+	if (inconsistent) {
+		/* FIXME Test should be if we're *using* precommitted metadata not if we were searching for it */
+		if (use_precommitted) {
+			log_error("Inconsistent pre-commit metadata copies "
+				  "for volume group %s", vgname);
+			return NULL;
+		}
+
+		if (!*consistent)
+			return correct_vg;
+
+		/* Don't touch if vgids didn't match */
+		if (inconsistent_vgid) {
+			log_error("Inconsistent metadata UUIDs found for "
+				  "volume group %s", vgname);
+			*consistent = 0;
+			return correct_vg;
+		}
+
+		log_warn("WARNING: Inconsistent metadata found for VG %s - updating "
+			 "to use version %u", vgname, correct_vg->seqno);
+
+		if (!vg_write(correct_vg)) {
+			log_error("Automatic metadata correction failed");
+			return NULL;
+		}
+
+		if (!vg_commit(correct_vg)) {
+			log_error("Automatic metadata correction commit "
+				  "failed");
+			return NULL;
+		}
+
+		dm_list_iterate_items(pvl, &all_pvs) {
+			dm_list_iterate_items(pvl2, &correct_vg->pvs) {
+				if (pvl->pv->dev == pvl2->pv->dev)
+					goto next_pv;
+			}
+			if (!id_write_format(&pvl->pv->id, uuid, sizeof(uuid)))
+				return_NULL;
+			log_error("Removing PV %s (%s) that no longer belongs to VG %s",
+				  pv_dev_name(pvl->pv), uuid, correct_vg->name);
+			if (!pv_write_orphan(cmd, pvl->pv))
+				return_NULL;
+      next_pv:
+			;
+		}
+	}
+
+	if (vg_missing_pv_count(correct_vg)) {
+		log_verbose("There are %d physical volumes missing.",
+			    vg_missing_pv_count(correct_vg));
+		_vg_mark_partial_lvs(correct_vg);
+	}
+
+	if ((correct_vg->status & PVMOVE) && !pvmove_mode()) {
+		log_error("WARNING: Interrupted pvmove detected in "
+			  "volume group %s", correct_vg->name);
+		log_error("Please restore the metadata by running "
+			  "vgcfgrestore.");
+		return NULL;
+	}
+
+	*consistent = 1;
+	return correct_vg;
+}
+
+struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
+			     const char *vgid, int *consistent)
+{
+	struct volume_group *vg;
+	struct lv_list *lvl;
+
+	if (!(vg = _vg_read(cmd, vgname, vgid, consistent, 0)))
+		return NULL;
+
+	if (!check_pv_segments(vg)) {
+		log_error("Internal error: PV segments corrupted in %s.",
+			  vg->name);
+		return NULL;
+	}
+
+	dm_list_iterate_items(lvl, &vg->lvs) {
+		if (!check_lv_segments(lvl->lv, 1)) {
+			log_error("Internal error: LV segments corrupted in %s.",
+				  lvl->lv->name);
+			return NULL;
+		}
+	}
+
+	return vg;
+}
+
+/* This is only called by lv_from_lvid, which is only called from
+ * activate.c so we know the appropriate VG lock is already held and
+ * the vg_read is therefore safe.
+ */
+static struct volume_group *_vg_read_by_vgid(struct cmd_context *cmd,
+					    const char *vgid,
+					    unsigned precommitted)
+{
+	const char *vgname;
+	struct dm_list *vgnames;
+	struct volume_group *vg;
+	struct lvmcache_vginfo *vginfo;
+	struct str_list *strl;
+	int consistent = 0;
+
+	/* Is corresponding vgname already cached? */
+	if ((vginfo = vginfo_from_vgid(vgid)) &&
+	    vginfo->vgname && !is_orphan_vg(vginfo->vgname)) {
+		if ((vg = _vg_read(cmd, NULL, vgid,
+				   &consistent, precommitted)) &&
+		    !strncmp((char *)vg->id.uuid, vgid, ID_LEN)) {
+
+			if (!consistent) {
+				log_error("Volume group %s metadata is "
+					  "inconsistent", vg->name);
+			}
+			return vg;
+		}
+	}
+
+	/* Mustn't scan if memory locked: ensure cache gets pre-populated! */
+	if (memlock())
+		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. */
+
+	// The slow way - full scan required to cope with vgrename
+	if (!(vgnames = get_vgs(cmd, 2))) {
+		log_error("vg_read_by_vgid: get_vgs failed");
+		return NULL;
+	}
+
+	dm_list_iterate_items(strl, vgnames) {
+		vgname = strl->str;
+		if (!vgname || is_orphan_vg(vgname))
+			continue;	// FIXME Unnecessary?
+		consistent = 0;
+		if ((vg = _vg_read(cmd, vgname, vgid, &consistent,
+				   precommitted)) &&
+		    !strncmp((char *)vg->id.uuid, vgid, ID_LEN)) {
+
+			if (!consistent) {
+				log_error("Volume group %s metadata is "
+					  "inconsistent", vgname);
+				return NULL;
+			}
+			return vg;
+		}
+	}
+
+	return NULL;
+}
+
+/* Only called by activate.c */
+struct logical_volume *lv_from_lvid(struct cmd_context *cmd, const char *lvid_s,
+				    unsigned precommitted)
+{
+	struct lv_list *lvl;
+	struct volume_group *vg;
+	const union lvid *lvid;
+
+	lvid = (const union lvid *) lvid_s;
+
+	log_very_verbose("Finding volume group for uuid %s", lvid_s);
+	if (!(vg = _vg_read_by_vgid(cmd, (char *)lvid->id[0].uuid, precommitted))) {
+		log_error("Volume group for uuid not found: %s", lvid_s);
+		return NULL;
+	}
+
+	log_verbose("Found volume group \"%s\"", vg->name);
+	if (vg->status & EXPORTED_VG) {
+		log_error("Volume group \"%s\" is exported", vg->name);
+		return NULL;
+	}
+	if (!(lvl = find_lv_in_vg_by_lvid(vg, lvid))) {
+		log_very_verbose("Can't find logical volume id %s", lvid_s);
+		return NULL;
+	}
+
+	return lvl->lv;
+}
+
+/**
+ * pv_read - read and return a handle to a physical volume
+ * @cmd: LVM command initiating the pv_read
+ * @pv_name: full device name of the PV, including the path
+ * @mdas: list of metadata areas of the PV
+ * @label_sector: sector number where the PV label is stored on @pv_name
+ * @warnings:
+ *
+ * Returns:
+ *   PV handle - valid pv_name and successful read of the PV, or
+ *   NULL - invalid parameter or error in reading the PV
+ *
+ * Note:
+ *   FIXME - liblvm todo - make into function that returns handle
+ */
+struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
+				struct dm_list *mdas, uint64_t *label_sector,
+				int warnings)
+{
+	return _pv_read(cmd, pv_name, mdas, label_sector, warnings);
+}
+
+/* FIXME Use label functions instead of PV functions */
+static struct physical_volume *_pv_read(struct cmd_context *cmd,
+					const char *pv_name,
+					struct dm_list *mdas,
+					uint64_t *label_sector,
+					int warnings)
+{
+	struct physical_volume *pv;
+	struct label *label;
+	struct lvmcache_info *info;
+	struct device *dev;
+
+	if (!(dev = dev_cache_get(pv_name, cmd->filter)))
+		return_NULL;
+
+	if (!(label_read(dev, &label, UINT64_C(0)))) {
+		if (warnings)
+			log_error("No physical volume label read from %s",
+				  pv_name);
+		return NULL;
+	}
+
+	info = (struct lvmcache_info *) label->info;
+	if (label_sector && *label_sector)
+		*label_sector = label->sector;
+
+	if (!(pv = dm_pool_zalloc(cmd->mem, sizeof(*pv)))) {
+		log_error("pv allocation for '%s' failed", pv_name);
+		return NULL;
+	}
+
+	dm_list_init(&pv->tags);
+	dm_list_init(&pv->segments);
+
+	/* FIXME Move more common code up here */
+	if (!(info->fmt->ops->pv_read(info->fmt, pv_name, pv, mdas))) {
+		log_error("Failed to read existing physical volume '%s'",
+			  pv_name);
+		return NULL;
+	}
+
+	if (!pv->size)
+		return NULL;
+	
+	if (!alloc_pv_segment_whole_pv(cmd->mem, pv))
+		return_NULL;
+
+	return pv;
+}
+
+/* May return empty list */
+struct dm_list *get_vgs(struct cmd_context *cmd, int full_scan)
+{
+	return lvmcache_get_vgnames(cmd, full_scan);
+}
+
+struct dm_list *get_vgids(struct cmd_context *cmd, int full_scan)
+{
+	return lvmcache_get_vgids(cmd, full_scan);
+}
+
+static int _get_pvs(struct cmd_context *cmd, struct dm_list **pvslist)
+{
+	struct str_list *strl;
+	struct dm_list * uninitialized_var(results);
+	const char *vgname, *vgid;
+	struct dm_list *pvh, *tmp;
+	struct dm_list *vgids;
+	struct volume_group *vg;
+	int consistent = 0;
+	int old_pvmove;
+
+	lvmcache_label_scan(cmd, 0);
+
+	if (pvslist) {
+		if (!(results = dm_pool_alloc(cmd->mem, sizeof(*results)))) {
+			log_error("PV list allocation failed");
+			return 0;
+		}
+
+		dm_list_init(results);
+	}
+
+	/* Get list of VGs */
+	if (!(vgids = get_vgids(cmd, 0))) {
+		log_error("get_pvs: get_vgs failed");
+		return 0;
+	}
+
+	/* Read every VG to ensure cache consistency */
+	/* Orphan VG is last on list */
+	old_pvmove = pvmove_mode();
+	init_pvmove(1);
+	dm_list_iterate_items(strl, vgids) {
+		vgid = strl->str;
+		if (!vgid)
+			continue;	/* FIXME Unnecessary? */
+		consistent = 0;
+		if (!(vgname = vgname_from_vgid(NULL, vgid))) {
+			stack;
+			continue;
+		}
+		if (!(vg = vg_read(cmd, vgname, vgid, &consistent))) {
+			stack;
+			continue;
+		}
+		if (!consistent)
+			log_warn("WARNING: Volume Group %s is not consistent",
+				 vgname);
+
+		/* Move PVs onto results list */
+		if (pvslist)
+			dm_list_iterate_safe(pvh, tmp, &vg->pvs)
+				dm_list_add(results, pvh);
+	}
+	init_pvmove(old_pvmove);
+
+	if (pvslist)
+		*pvslist = results;
+	else
+		dm_pool_free(cmd->mem, vgids);
+
+	return 1;
+}
+
+struct dm_list *get_pvs(struct cmd_context *cmd)
+{
+	struct dm_list *results;
+
+	if (!_get_pvs(cmd, &results))
+		return NULL;
+
+	return results;
+}
+
+int scan_vgs_for_pvs(struct cmd_context *cmd)
+{
+	return _get_pvs(cmd, NULL);
+}
+
+/* FIXME: liblvm todo - make into function that takes handle */
+int pv_write(struct cmd_context *cmd __attribute((unused)),
+	     struct physical_volume *pv,
+	     struct dm_list *mdas, int64_t label_sector)
+{
+	return _pv_write(cmd, pv, mdas, label_sector);
+}
+
+static int _pv_write(struct cmd_context *cmd __attribute((unused)),
+		     struct physical_volume *pv,
+	     	     struct dm_list *mdas, int64_t label_sector)
+{
+	if (!pv->fmt->ops->pv_write) {
+		log_error("Format does not support writing physical volumes");
+		return 0;
+	}
+
+	if (!is_orphan_vg(pv->vg_name) || pv->pe_alloc_count) {
+		log_error("Assertion failed: can't _pv_write non-orphan PV "
+			  "(in VG %s)", pv->vg_name);
+		return 0;
+	}
+
+	if (!pv->fmt->ops->pv_write(pv->fmt, pv, mdas, label_sector))
+		return_0;
+
+	return 1;
+}
+
+int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv)
+{
+	const char *old_vg_name = pv->vg_name;
+
+	pv->vg_name = cmd->fmt->orphan_vg_name;
+	pv->status = ALLOCATABLE_PV;
+	pv->pe_alloc_count = 0;
+
+	if (!dev_get_size(pv->dev, &pv->size)) {
+		log_error("%s: Couldn't get size.", pv_dev_name(pv));
+		return 0;
+	}
+
+	if (!_pv_write(cmd, pv, NULL, INT64_C(-1))) {
+		log_error("Failed to clear metadata from physical "
+			  "volume \"%s\" after removal from \"%s\"",
+			  pv_dev_name(pv), old_vg_name);
+		return 0;
+	}
+
+	return 1;
+}
+
+/**
+ * is_orphan_vg - Determine whether a vg_name is an orphan
+ * @vg_name: pointer to the vg_name
+ */
+int is_orphan_vg(const char *vg_name)
+{
+	return (vg_name && vg_name[0] == ORPHAN_PREFIX[0]) ? 1 : 0;
+}
+
+/**
+ * is_orphan - Determine whether a pv is an orphan based on its vg_name
+ * @pv: handle to the physical volume
+ */
+int is_orphan(const pv_t *pv)
+{
+	return is_orphan_vg(pv_field(pv, vg_name));
+}
+
+/**
+ * is_pv - Determine whether a pv is a real pv or dummy one
+ * @pv: handle to device
+ */
+int is_pv(pv_t *pv)
+{
+	return (pv_field(pv, vg_name) ? 1 : 0);
+}
+
+/*
+ * Returns:
+ *  0 - fail
+ *  1 - success
+ */
+int pv_analyze(struct cmd_context *cmd, const char *pv_name,
+	       uint64_t label_sector)
+{
+	struct label *label;
+	struct device *dev;
+	struct metadata_area *mda;
+	struct lvmcache_info *info;
+
+	dev = dev_cache_get(pv_name, cmd->filter);
+	if (!dev) {
+		log_error("Device %s not found (or ignored by filtering).",
+			  pv_name);
+		return 0;
+	}
+
+	/*
+	 * First, scan for LVM labels.
+	 */
+	if (!label_read(dev, &label, label_sector)) {
+		log_error("Could not find LVM label on %s",
+			  pv_name);
+		return 0;
+	}
+
+	log_print("Found label on %s, sector %"PRIu64", type=%s",
+		  pv_name, label->sector, label->type);
+
+	/*
+	 * Next, loop through metadata areas
+	 */
+	info = label->info;
+	dm_list_iterate_items(mda, &info->mdas)
+		mda->ops->pv_analyze_mda(info->fmt, mda);
+
+	return 1;
+}
+
+
+
+/**
+ * vg_check_status - check volume group status flags and log error
+ * @vg - volume group to check status flags
+ * @status - specific status flags to check (e.g. EXPORTED_VG)
+ *
+ * Returns:
+ * 0 - fail
+ * 1 - success
+ */
+int vg_check_status(const struct volume_group *vg, uint32_t status)
+{
+	if ((status & CLUSTERED) &&
+	    (vg_is_clustered(vg)) && !locking_is_clustered() &&
+	    !lockingfailed()) {
+		log_error("Skipping clustered volume group %s", vg->name);
+		return 0;
+	}
+
+	if ((status & EXPORTED_VG) &&
+	    (vg->status & EXPORTED_VG)) {
+		log_error("Volume group %s is exported", vg->name);
+		return 0;
+	}
+
+	if ((status & LVM_WRITE) &&
+	    !(vg->status & LVM_WRITE)) {
+		log_error("Volume group %s is read-only", vg->name);
+		return 0;
+	}
+	if ((status & RESIZEABLE_VG) &&
+	    !(vg->status & RESIZEABLE_VG)) {
+		log_error("Volume group %s is not resizeable.", vg->name);
+		return 0;
+	}
+
+	return 1;
+}
+
+/*
+ * vg_lock_and_read - consolidate vg locking, reading, and status flag checking
+ *
+ * Returns:
+ * NULL - failure
+ * non-NULL - success; volume group handle
+ */
+vg_t *vg_lock_and_read(struct cmd_context *cmd, const char *vg_name,
+		       const char *vgid,
+		       uint32_t lock_flags, uint32_t status_flags,
+		       uint32_t misc_flags)
+{
+	struct volume_group *vg;
+	int consistent = 1;
+
+	if (!(misc_flags & CORRECT_INCONSISTENT))
+		consistent = 0;
+
+	if (!validate_name(vg_name)) {
+		log_error("Volume group name %s has invalid characters",
+			  vg_name);
+		return NULL;
+	}
+
+	if (!lock_vol(cmd, vg_name, lock_flags)) {
+		log_error("Can't get lock for %s", vg_name);
+		return NULL;
+	}
+
+	if (!(vg = vg_read(cmd, vg_name, vgid, &consistent)) ||
+	    ((misc_flags & FAIL_INCONSISTENT) && !consistent)) {
+		log_error("Volume group \"%s\" not found", vg_name);
+		unlock_vg(cmd, vg_name);
+		return NULL;
+	}
+
+	if (!vg_check_status(vg, status_flags)) {
+		unlock_vg(cmd, vg_name);
+		return NULL;
+	}
+
+	return vg;
+}
+
+/*
+ * Gets/Sets for external LVM library
+ */
+struct id pv_id(const pv_t *pv)
+{
+	return pv_field(pv, id);
+}
+
+const struct format_type *pv_format_type(const pv_t *pv)
+{
+	return pv_field(pv, fmt);
+}
+
+struct id pv_vgid(const pv_t *pv)
+{
+	return pv_field(pv, vgid);
+}
+
+struct device *pv_dev(const pv_t *pv)
+{
+	return pv_field(pv, dev);
+}
+
+const char *pv_vg_name(const pv_t *pv)
+{
+	return pv_field(pv, vg_name);
+}
+
+const char *pv_dev_name(const pv_t *pv)
+{
+	return dev_name(pv_dev(pv));
+}
+
+uint64_t pv_size(const pv_t *pv)
+{
+	return pv_field(pv, size);
+}
+
+uint32_t pv_status(const pv_t *pv)
+{
+	return pv_field(pv, status);
+}
+
+uint32_t pv_pe_size(const pv_t *pv)
+{
+	return pv_field(pv, pe_size);
+}
+
+uint64_t pv_pe_start(const pv_t *pv)
+{
+	return pv_field(pv, pe_start);
+}
+
+uint32_t pv_pe_count(const pv_t *pv)
+{
+	return pv_field(pv, pe_count);
+}
+
+uint32_t pv_pe_alloc_count(const pv_t *pv)
+{
+	return pv_field(pv, pe_alloc_count);
+}
+
+uint32_t vg_status(const vg_t *vg)
+{
+	return vg->status;
+}
+
+/**
+ * pv_by_path - Given a device path return a PV handle if it is a PV
+ * @cmd - handle to the LVM command instance
+ * @pv_name - device path to read for the PV
+ *
+ * Returns:
+ *  NULL - device path does not contain a valid PV
+ *  non-NULL - PV handle corresponding to device path
+ *
+ * FIXME: merge with find_pv_by_name ?
+ */
+pv_t *pv_by_path(struct cmd_context *cmd, const char *pv_name)
+{
+	struct dm_list mdas;
+	
+	dm_list_init(&mdas);
+	return _pv_read(cmd, pv_name, &mdas, NULL, 1);
+}
Index: src/external/gpl2/lvm2tools/dist/lib/metadata/metadata.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/metadata/metadata.h
diff -N src/external/gpl2/lvm2tools/dist/lib/metadata/metadata.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/metadata/metadata.h	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,352 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * This is the in core representation of a volume group and its
+ * associated physical and logical volumes.
+ */
+
+#ifndef _LVM_METADATA_H
+#define _LVM_METADATA_H
+
+#include "ctype.h"
+#include "dev-cache.h"
+#include "lvm-string.h"
+#include "metadata-exported.h"
+
+//#define MAX_STRIPES 128U
+//#define SECTOR_SHIFT 9L
+#define SECTOR_SIZE ( 1L << SECTOR_SHIFT )
+//#define STRIPE_SIZE_MIN ( (unsigned) lvm_getpagesize() >> SECTOR_SHIFT)	/* PAGESIZE in sectors */
+//#define STRIPE_SIZE_MAX ( 512L * 1024L >> SECTOR_SHIFT)	/* 512 KB in sectors */
+//#define STRIPE_SIZE_LIMIT ((UINT_MAX >> 2) + 1)
+//#define PV_MIN_SIZE ( 512L * 1024L >> SECTOR_SHIFT)	/* 512 KB in sectors */
+//#define MAX_RESTRICTED_LVS 255	/* Used by FMT_RESTRICTED_LVIDS */
+#define MIRROR_LOG_SIZE 1	/* Extents */
+
+/* Various flags */
+/* Note that the bits no longer necessarily correspond to LVM1 disk format */
+
+//#define PARTIAL_VG		0x00000001U	/* VG */
+//#define EXPORTED_VG          	0x00000002U	/* VG PV */
+//#define RESIZEABLE_VG        	0x00000004U	/* VG */
+
+/* May any free extents on this PV be used or must they be left free? */
+//#define ALLOCATABLE_PV         	0x00000008U	/* PV */
+
+#define SPINDOWN_LV          	0x00000010U	/* LV */
+#define BADBLOCK_ON       	0x00000020U	/* LV */
+//#define VISIBLE_LV		0x00000040U	/* LV */
+//#define FIXED_MINOR		0x00000080U	/* LV */
+/* FIXME Remove when metadata restructuring is completed */
+//#define SNAPSHOT		0x00001000U	/* LV - internal use only */
+//#define PVMOVE			0x00002000U	/* VG LV SEG */
+//#define LOCKED			0x00004000U	/* LV */
+//#define MIRRORED		0x00008000U	/* LV - internal use only */
+#define VIRTUAL			0x00010000U	/* LV - internal use only */
+//#define MIRROR_LOG		0x00020000U	/* LV */
+//#define MIRROR_IMAGE		0x00040000U	/* LV */
+//#define MIRROR_NOTSYNCED	0x00080000U	/* LV */
+#define ACTIVATE_EXCL		0x00100000U	/* LV - internal use only */
+#define PRECOMMITTED		0x00200000U	/* VG - internal use only */
+//#define CONVERTING		0x00400000U	/* LV */
+
+//#define MISSING_PV		0x00800000U	/* PV */
+//#define PARTIAL_LV		0x01000000U	/* LV - derived flag, not
+//						   written out in metadata*/
+
+#define POSTORDER_FLAG		0x02000000U /* Not real flags, reserved for  */
+#define POSTORDER_OPEN_FLAG	0x04000000U /* temporary use inside vg_read. */
+
+//#define LVM_READ              	0x00000100U	/* LV VG */
+//#define LVM_WRITE             	0x00000200U	/* LV VG */
+//#define CLUSTERED         	0x00000400U	/* VG */
+#define SHARED            	0x00000800U	/* VG */
+
+/* Format features flags */
+//#define FMT_SEGMENTS		0x00000001U	/* Arbitrary segment params? */
+//#define FMT_MDAS		0x00000002U	/* Proper metadata areas? */
+//#define FMT_TAGS		0x00000004U	/* Tagging? */
+//#define FMT_UNLIMITED_VOLS	0x00000008U	/* Unlimited PVs/LVs? */
+//#define FMT_RESTRICTED_LVIDS	0x00000010U	/* LVID <= 255 */
+//#define FMT_ORPHAN_ALLOCATABLE	0x00000020U	/* Orphan PV allocatable? */
+#define FMT_PRECOMMIT		0x00000040U	/* Supports pre-commit? */
+//#define FMT_RESIZE_PV		0x00000080U	/* Supports pvresize? */
+//#define FMT_UNLIMITED_STRIPESIZE 0x00000100U	/* Unlimited stripe size? */
+
+struct metadata_area;
+
+/* Per-format per-metadata area operations */
+struct metadata_area_ops {
+	struct volume_group *(*vg_read) (struct format_instance * fi,
+					 const char *vg_name,
+					 struct metadata_area * mda);
+	struct volume_group *(*vg_read_precommit) (struct format_instance * fi,
+					 const char *vg_name,
+					 struct metadata_area * mda);
+	/*
+	 * Write out complete VG metadata.  You must ensure internal
+	 * consistency before calling. eg. PEs can't refer to PVs not
+	 * part of the VG.
+	 *
+	 * It is also the responsibility of the caller to ensure external
+	 * consistency, eg by calling pv_write() if removing PVs from
+	 * a VG or calling vg_write() a second time if splitting a VG
+	 * into two.
+	 *
+	 * vg_write() should not read or write from any PVs not included
+	 * in the volume_group structure it is handed.
+	 * (format1 currently breaks this rule.)
+	 */
+	int (*vg_write) (struct format_instance * fid, struct volume_group * vg,
+			 struct metadata_area * mda);
+	int (*vg_precommit) (struct format_instance * fid,
+			     struct volume_group * vg,
+			     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);
+
+	/*
+	 * Returns number of free sectors in given metadata area.
+	 */
+	uint64_t (*mda_free_sectors) (struct metadata_area *mda);
+
+	/*
+	 * Check if metadata area belongs to vg
+	 */
+	int (*mda_in_vg) (struct format_instance * fi,
+			    struct volume_group * vg, struct metadata_area *mda);
+	/*
+	 * Analyze a metadata area on a PV.
+	 */
+	int (*pv_analyze_mda) (const struct format_type * fmt,
+			       struct metadata_area *mda);
+
+};
+
+struct metadata_area {
+	struct dm_list list;
+	struct metadata_area_ops *ops;
+	void *metadata_locn;
+};
+
+#define seg_pvseg(seg, s)	(seg)->areas[(s)].u.pv.pvseg
+#define seg_dev(seg, s)		(seg)->areas[(s)].u.pv.pvseg->pv->dev
+#define seg_pe(seg, s)		(seg)->areas[(s)].u.pv.pvseg->pe
+#define seg_le(seg, s)		(seg)->areas[(s)].u.lv.le
+
+struct name_list {
+	struct dm_list list;
+	char *name;
+};
+
+struct mda_list {
+	struct dm_list list;
+	struct device_area mda;
+};
+
+struct peg_list {
+	struct dm_list list;
+	struct pv_segment *peg;
+};
+
+struct seg_list {
+	struct dm_list list;
+	unsigned count;
+	struct lv_segment *seg;
+};
+
+/*
+ * Ownership of objects passes to caller.
+ */
+struct format_handler {
+	/*
+	 * Scan any metadata areas that aren't referenced in PV labels
+	 */
+	int (*scan) (const struct format_type * fmt);
+
+	/*
+	 * Return PV with given path.
+	 */
+	int (*pv_read) (const struct format_type * fmt, const char *pv_name,
+			struct physical_volume * pv, struct dm_list * mdas);
+
+	/*
+	 * Tweak an already filled out a pv ready for importing into a
+	 * vg.  eg. pe_count is format specific.
+	 */
+	int (*pv_setup) (const struct format_type * fmt,
+			 uint64_t pe_start, uint32_t extent_count,
+			 uint32_t extent_size,
+			 int pvmetadatacopies,
+			 uint64_t pvmetadatasize, struct dm_list * mdas,
+			 struct physical_volume * pv, struct volume_group * vg);
+
+	/*
+	 * Write a PV structure to disk. Fails if the PV is in a VG ie
+	 * pv->vg_name must be a valid orphan VG name
+	 */
+	int (*pv_write) (const struct format_type * fmt,
+			 struct physical_volume * pv, struct dm_list * mdas,
+			 int64_t label_sector);
+
+	/*
+	 * Tweak an already filled out a lv eg, check there
+	 * aren't too many extents.
+	 */
+	int (*lv_setup) (struct format_instance * fi,
+			 struct logical_volume * lv);
+
+	/*
+	 * Tweak an already filled out vg.  eg, max_pv is format
+	 * specific.
+	 */
+	int (*vg_setup) (struct format_instance * fi, struct volume_group * vg);
+
+	/*
+	 * Check whether particular segment type is supported.
+	 */
+	int (*segtype_supported) (struct format_instance *fid,
+				  const struct segment_type *segtype);
+
+	/*
+	 * Create format instance with a particular metadata area
+	 */
+	struct format_instance *(*create_instance) (const struct format_type *
+						    fmt, const char *vgname,
+						    const char *vgid,
+						    void *context);
+
+	/*
+	 * Destructor for format instance
+	 */
+	void (*destroy_instance) (struct format_instance * fid);
+
+	/*
+	 * Destructor for format type
+	 */
+	void (*destroy) (const struct format_type * fmt);
+};
+
+/*
+ * Utility functions
+ */
+unsigned long pe_align(struct physical_volume *pv);
+int vg_validate(struct volume_group *vg);
+
+int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv);
+
+/* Manipulate PV structures */
+int pv_add(struct volume_group *vg, struct physical_volume *pv);
+int pv_remove(struct volume_group *vg, struct physical_volume *pv);
+struct physical_volume *pv_find(struct volume_group *vg, const char *pv_name);
+
+/* Find a PV within a given VG */
+int get_pv_from_vg_by_id(const struct format_type *fmt, const char *vg_name,
+			 const char *vgid, const char *pvid,
+			 struct physical_volume *pv);
+
+struct lv_list *find_lv_in_vg_by_lvid(struct volume_group *vg,
+				      const union lvid *lvid);
+
+struct lv_list *find_lv_in_lv_list(const struct dm_list *ll,
+				   const struct logical_volume *lv);
+
+/* Return the VG that contains a given LV (based on path given in lv_name) */
+/* or environment var */
+struct volume_group *find_vg_with_lv(const char *lv_name);
+
+/* Find LV with given lvid (used during activation) */
+struct logical_volume *lv_from_lvid(struct cmd_context *cmd,
+				    const char *lvid_s,
+				    unsigned precommitted);
+
+/* FIXME Merge these functions with ones above */
+struct physical_volume *find_pv(struct volume_group *vg, struct device *dev);
+
+struct pv_list *find_pv_in_pv_list(const struct dm_list *pl,
+				   const struct physical_volume *pv);
+
+/* Find LV segment containing given LE */
+struct lv_segment *find_seg_by_le(const struct logical_volume *lv, uint32_t le);
+
+/* Find PV segment containing given LE */
+struct pv_segment *find_peg_by_pe(const struct physical_volume *pv, uint32_t pe);
+
+/*
+ * Remove a dev_dir if present.
+ */
+const char *strip_dir(const char *vg_name, const char *dir);
+
+/*
+ * Checks that an lv has no gaps or overlapping segments.
+ * Set complete_vg to perform additional VG level checks.
+ */
+int check_lv_segments(struct logical_volume *lv, int complete_vg);
+
+/*
+ * Sometimes (eg, after an lvextend), it is possible to merge two
+ * adjacent segments into a single segment.  This function trys
+ * to merge as many segments as possible.
+ */
+int lv_merge_segments(struct logical_volume *lv);
+
+/*
+ * Ensure there's a segment boundary at a given LE, splitting if necessary
+ */
+int lv_split_segment(struct logical_volume *lv, uint32_t le);
+
+/*
+ * Add/remove upward link from underlying LV to the segment using it
+ * FIXME: ridiculously long name
+ */
+int add_seg_to_segs_using_this_lv(struct logical_volume *lv, struct lv_segment *seg);
+int remove_seg_from_segs_using_this_lv(struct logical_volume *lv, struct lv_segment *seg);
+struct lv_segment *get_only_segment_using_this_lv(struct logical_volume *lv);
+
+/*
+ * For internal metadata caching.
+ */
+int export_vg_to_buffer(struct volume_group *vg, char **buf);
+struct volume_group *import_vg_from_buffer(char *buf,
+					   struct format_instance *fid);
+
+/*
+ * Mirroring functions
+ */
+
+/*
+ * Given mirror image or mirror log segment, find corresponding mirror segment 
+ */
+int fixup_imported_mirrors(struct volume_group *vg);
+
+/*
+ * Begin skeleton for external LVM library
+ */
+struct id pv_id(const pv_t *pv);
+const struct format_type *pv_format_type(const pv_t *pv);
+struct id pv_vgid(const pv_t *pv);
+
+pv_t *pv_by_path(struct cmd_context *cmd, const char *pv_name);
+int add_pv_to_vg(struct volume_group *vg, const char *pv_name,
+		 struct physical_volume *pv);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/metadata/mirror.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/metadata/mirror.c
diff -N src/external/gpl2/lvm2tools/dist/lib/metadata/mirror.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/metadata/mirror.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,1608 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "metadata.h"
+#include "toolcontext.h"
+#include "segtype.h"
+#include "display.h"
+#include "archiver.h"
+#include "activate.h"
+#include "lv_alloc.h"
+#include "lvm-string.h"
+#include "str_list.h"
+#include "locking.h"	/* FIXME Should not be used in this file */
+
+#include "defaults.h" /* FIXME: should this be defaults.h? */
+
+/* These are necessary for _write_log_header() */
+#include "xlate.h"
+#define MIRROR_MAGIC 0x4D695272
+#define MIRROR_DISK_VERSION 2
+
+/* These are the flags that represent the mirror failure restoration policies */
+#define MIRROR_REMOVE		 0
+#define MIRROR_ALLOCATE		 1
+#define MIRROR_ALLOCATE_ANYWHERE 2
+
+/*
+ * Returns true if the lv is temporary mirror layer for resync
+ */
+int is_temporary_mirror_layer(const struct logical_volume *lv)
+{
+	if (lv->status & MIRROR_IMAGE
+	    && lv->status & MIRRORED
+	    && !(lv->status & LOCKED))
+		return 1;
+
+	return 0;
+}
+
+/*
+ * Return a temporary LV for resyncing added mirror image.
+ * Add other mirror legs to lvs list.
+ */
+struct logical_volume *find_temporary_mirror(const struct logical_volume *lv)
+{
+	struct lv_segment *seg;
+
+	if (!(lv->status & MIRRORED))
+		return NULL;
+
+	seg = first_seg(lv);
+
+	/* Temporary mirror is always area_num == 0 */
+	if (seg_type(seg, 0) == AREA_LV &&
+	    is_temporary_mirror_layer(seg_lv(seg, 0)))
+		return seg_lv(seg, 0);
+
+	return NULL;
+}
+
+/*
+ * Returns the number of mirrors of the LV
+ */
+uint32_t lv_mirror_count(const struct logical_volume *lv)
+{
+	struct lv_segment *seg;
+	uint32_t s, mirrors;
+
+	if (!(lv->status & MIRRORED))
+		return 1;
+
+	seg = first_seg(lv);
+	mirrors = seg->area_count;
+
+	for (s = 0; s < seg->area_count; s++) {
+		if (seg_type(seg, s) != AREA_LV)
+			continue;
+		if (is_temporary_mirror_layer(seg_lv(seg, s)))
+			mirrors += lv_mirror_count(seg_lv(seg, s)) - 1;
+	}
+
+	return mirrors;
+}
+
+struct lv_segment *find_mirror_seg(struct lv_segment *seg)
+{
+	struct lv_segment *mirror_seg;
+
+	mirror_seg = get_only_segment_using_this_lv(seg->lv);
+
+	if (!mirror_seg) {
+		log_error("Failed to find mirror_seg for %s", seg->lv->name);
+		return NULL;
+	}
+
+	if (!seg_is_mirrored(mirror_seg)) {
+		log_error("%s on %s is not a mirror segments",
+			  mirror_seg->lv->name, seg->lv->name);
+		return NULL;
+	}
+
+	return mirror_seg;
+}
+
+/*
+ * Reduce the region size if necessary to ensure
+ * the volume size is a multiple of the region size.
+ */
+uint32_t adjusted_mirror_region_size(uint32_t extent_size, uint32_t extents,
+				     uint32_t region_size)
+{
+	uint64_t region_max;
+
+	region_max = (1 << (ffs((int)extents) - 1)) * (uint64_t) extent_size;
+
+	if (region_max < UINT32_MAX && region_size > region_max) {
+		region_size = (uint32_t) region_max;
+		log_print("Using reduced mirror region size of %" PRIu32
+			  " sectors", region_size);
+	}
+
+	return region_size;
+}
+
+/*
+ * shift_mirror_images
+ * @mirrored_seg
+ * @mimage:  The position (index) of the image to move to the end
+ *
+ * When dealing with removal of legs, we often move a 'removable leg'
+ * to the back of the 'areas' array.  It is critically important not
+ * to simply swap it for the last area in the array.  This would have
+ * the affect of reordering the remaining legs - altering position of
+ * the primary.  So, we must shuffle all of the areas in the array
+ * to maintain their relative position before moving the 'removable
+ * leg' to the end.
+ *
+ * Short illustration of the problem:
+ *   - Mirror consists of legs A, B, C and we want to remove A
+ *   - We swap A and C and then remove A, leaving C, B
+ * This scenario is problematic in failure cases where A dies, because
+ * B becomes the primary.  If the above happens, we effectively throw
+ * away any changes made between the time of failure and the time of
+ * restructuring the mirror.
+ *
+ * So, any time we want to move areas to the end to be removed, use
+ * this function.
+ */
+int shift_mirror_images(struct lv_segment *mirrored_seg, unsigned mimage)
+{
+	int i;
+	struct lv_segment_area area;
+
+	if (mimage >= mirrored_seg->area_count) {
+		log_error("Invalid index (%u) of mirror image supplied "
+			  "to shift_mirror_images()", mimage);
+		return 0;
+	}
+
+	area = mirrored_seg->areas[mimage];
+
+	/* Shift remaining images down to fill the hole */
+	for (i = mimage + 1; i < mirrored_seg->area_count; i++)
+		mirrored_seg->areas[i-1] = mirrored_seg->areas[i];
+
+	/* Place this one at the end */
+	mirrored_seg->areas[i-1] = area;
+
+	return 1;
+}
+
+/*
+ * This function writes a new header to the mirror log header to the lv
+ *
+ * Returns: 1 on success, 0 on failure
+ */
+static int _write_log_header(struct cmd_context *cmd, struct logical_volume *lv)
+{
+	struct device *dev;
+	char *name;
+	struct { /* The mirror log header */
+		uint32_t magic;
+		uint32_t version;
+		uint64_t nr_regions;
+	} log_header;
+
+	log_header.magic = xlate32(MIRROR_MAGIC);
+	log_header.version = xlate32(MIRROR_DISK_VERSION);
+	log_header.nr_regions = xlate64((uint64_t)-1);
+
+	if (!(name = dm_pool_alloc(cmd->mem, PATH_MAX))) {
+		log_error("Name allocation failed - log header not written (%s)",
+			lv->name);
+		return 0;
+	}
+
+	if (dm_snprintf(name, PATH_MAX, "%s%s/%s", cmd->dev_dir,
+			 lv->vg->name, lv->name) < 0) {
+		log_error("Name too long - log header not written (%s)", lv->name);
+		return 0;
+	}
+
+	log_verbose("Writing log header to device, %s", lv->name);
+
+	if (!(dev = dev_cache_get(name, NULL))) {
+		log_error("%s: not found: log header not written", name);
+		return 0;
+	}
+
+	if (!dev_open_quiet(dev))
+		return 0;
+
+	if (!dev_write(dev, UINT64_C(0), sizeof(log_header), &log_header)) {
+		log_error("Failed to write log header to %s", name);
+		dev_close_immediate(dev);
+		return 0;
+	}
+
+	dev_close_immediate(dev);
+
+	return 1;
+}
+
+/*
+ * Initialize mirror log contents
+ */
+static int _init_mirror_log(struct cmd_context *cmd,
+			    struct logical_volume *log_lv, int in_sync,
+			    struct dm_list *tags, int remove_on_failure)
+{
+	struct str_list *sl;
+	struct lvinfo info;
+	uint32_t orig_status = log_lv->status;
+	int was_active = 0;
+
+	if (!activation() && in_sync) {
+		log_error("Aborting. Unable to create in-sync mirror log "
+			  "while activation is disabled.");
+		return 0;
+	}
+
+	/* If the LV is active, deactivate it first. */
+	if (lv_info(cmd, log_lv, &info, 0, 0) && info.exists) {
+		if (!deactivate_lv(cmd, log_lv))
+			return_0;
+		was_active = 1;
+	}
+
+	/* Temporary make it visible for set_lv() */
+	log_lv->status |= VISIBLE_LV;
+
+	/* Temporary tag mirror log for activation */
+	dm_list_iterate_items(sl, tags)
+		if (!str_list_add(cmd->mem, &log_lv->tags, sl->str)) {
+			log_error("Aborting. Unable to tag mirror log.");
+			goto activate_lv;
+		}
+
+	/* store mirror log on disk(s) */
+	if (!vg_write(log_lv->vg))
+		goto activate_lv;
+
+	backup(log_lv->vg);
+
+	if (!vg_commit(log_lv->vg))
+		goto activate_lv;
+
+	if (!activate_lv(cmd, log_lv)) {
+		log_error("Aborting. Failed to activate mirror log.");
+		goto revert_new_lv;
+	}
+
+	/* Remove the temporary tags */
+	dm_list_iterate_items(sl, tags)
+		if (!str_list_del(&log_lv->tags, sl->str))
+			log_error("Failed to remove tag %s from mirror log.",
+				  sl->str);
+
+	if (activation() && !set_lv(cmd, log_lv, log_lv->size,
+				    in_sync ? -1 : 0)) {
+		log_error("Aborting. Failed to wipe mirror log.");
+		goto deactivate_and_revert_new_lv;
+	}
+
+	if (activation() && !_write_log_header(cmd, log_lv)) {
+		log_error("Aborting. Failed to write mirror log header.");
+		goto deactivate_and_revert_new_lv;
+	}
+
+	if (!deactivate_lv(cmd, log_lv)) {
+		log_error("Aborting. Failed to deactivate mirror log. "
+			  "Manual intervention required.");
+		return 0;
+	}
+
+	log_lv->status &= ~VISIBLE_LV;
+
+	if (was_active && !activate_lv(cmd, log_lv))
+		return_0;
+
+	return 1;
+
+deactivate_and_revert_new_lv:
+	if (!deactivate_lv(cmd, log_lv)) {
+		log_error("Unable to deactivate mirror log LV. "
+			  "Manual intervention required.");
+		return 0;
+	}
+
+revert_new_lv:
+	log_lv->status = orig_status;
+
+	dm_list_iterate_items(sl, tags)
+		if (!str_list_del(&log_lv->tags, sl->str))
+			log_error("Failed to remove tag %s from mirror log.",
+				  sl->str);
+
+	if (remove_on_failure && !lv_remove(log_lv)) {
+		log_error("Manual intervention may be required to remove "
+			  "abandoned log LV before retrying.");
+		return 0;
+	}
+
+	if (!vg_write(log_lv->vg) ||
+	    (backup(log_lv->vg), !vg_commit(log_lv->vg)))
+		log_error("Manual intervention may be required to "
+			  "remove/restore abandoned log LV before retrying.");
+activate_lv:
+	if (was_active && !remove_on_failure && !activate_lv(cmd, log_lv))
+		return_0;
+
+	return 0;
+}
+
+/*
+ * Delete independent/orphan LV, it must acquire lock.
+ */
+static int _delete_lv(struct logical_volume *mirror_lv, struct logical_volume *lv)
+{
+	struct cmd_context *cmd = mirror_lv->vg->cmd;
+	struct str_list *sl;
+
+	/* Inherit tags - maybe needed for activation */
+	if (!str_list_match_list(&mirror_lv->tags, &lv->tags)) {
+		dm_list_iterate_items(sl, &mirror_lv->tags)
+			if (!str_list_add(cmd->mem, &lv->tags, sl->str)) {
+				log_error("Aborting. Unable to tag.");
+				return 0;
+			}
+
+		if (!vg_write(mirror_lv->vg) ||
+		    !vg_commit(mirror_lv->vg)) {
+			log_error("Intermediate VG commit for orphan volume failed.");
+			return 0;
+		}
+	}
+
+	if (!activate_lv(cmd, lv))
+		return_0;
+
+	if (!deactivate_lv(cmd, lv))
+		return_0;
+
+	if (!lv_remove(lv))
+		return_0;
+
+	return 1;
+}
+
+static int _merge_mirror_images(struct logical_volume *lv,
+				const struct dm_list *mimages)
+{
+	uint32_t addition = dm_list_size(mimages);
+	struct logical_volume **img_lvs;
+	struct lv_list *lvl;
+	int i = 0;
+
+	if (!addition)
+		return 1;
+
+	if (!(img_lvs = alloca(sizeof(*img_lvs) * addition)))
+		return_0;
+
+	dm_list_iterate_items(lvl, mimages)
+		img_lvs[i++] = lvl->lv;
+
+	return lv_add_mirror_lvs(lv, img_lvs, addition,
+				 MIRROR_IMAGE, first_seg(lv)->region_size);
+}
+
+/* Unlink the relationship between the segment and its log_lv */
+struct logical_volume *detach_mirror_log(struct lv_segment *mirrored_seg)
+{
+	struct logical_volume *log_lv;
+
+	if (!mirrored_seg->log_lv)
+		return NULL;
+
+	log_lv = mirrored_seg->log_lv;
+	mirrored_seg->log_lv = NULL;
+	log_lv->status |= VISIBLE_LV;
+	log_lv->status &= ~MIRROR_LOG;
+	remove_seg_from_segs_using_this_lv(log_lv, mirrored_seg);
+
+	return log_lv;
+}
+
+/* Check if mirror image LV is removable with regard to given removable_pvs */
+static int _is_mirror_image_removable(struct logical_volume *mimage_lv,
+				      struct dm_list *removable_pvs)
+{
+	struct physical_volume *pv;
+	struct lv_segment *seg;
+	int pv_found;
+	struct pv_list *pvl;
+	uint32_t s;
+
+	dm_list_iterate_items(seg, &mimage_lv->segments) {
+		for (s = 0; s < seg->area_count; s++) {
+			if (seg_type(seg, s) != AREA_PV) {
+				/* FIXME Recurse for AREA_LV? */
+				/* Structure of seg_lv is unknown.
+				 * Not removing this LV for safety. */
+				return 0;
+			}
+
+			pv = seg_pv(seg, s);
+
+			pv_found = 0;
+			dm_list_iterate_items(pvl, removable_pvs) {
+				if (pv->dev->dev == pvl->pv->dev->dev) {
+					pv_found = 1;
+					break;
+				}
+			}
+			if (!pv_found)
+				return 0;
+		}
+	}
+
+	return 1;
+}
+
+/*
+ * Remove num_removed images from mirrored_seg
+ *
+ * Arguments:
+ *   num_removed:   the requested (maximum) number of mirrors to be removed
+ *   removable_pvs: if not NULL, only mirrors using PVs in this list
+ *                  will be removed
+ *   remove_log:    if non-zero, log_lv will be removed
+ *                  (even if it's 0, log_lv will be removed if there is no
+ *                   mirror remaining after the removal)
+ *   collapse:      if non-zero, instead of removing, remove the temporary
+ *                  mirror layer and merge mirrors to the original LV.
+ *                  removable_pvs should be NULL and num_removed should be
+ *                  seg->area_count - 1.
+ *   removed:       if non NULL, the number of removed mirror images is set
+ *                  as a result
+ *
+ * If collapse is non-zero, <removed> is guaranteed to be equal to num_removed.
+ *
+ * Return values:
+ *   Failure (0) means something unexpected has happend and
+ *   the caller should abort.
+ *   Even if no mirror was removed (e.g. no LV matches to 'removable_pvs'),
+ *   returns success (1).
+ */
+static int _remove_mirror_images(struct logical_volume *lv,
+				 uint32_t num_removed,
+				 struct dm_list *removable_pvs,
+				 unsigned remove_log, unsigned collapse,
+				 uint32_t *removed)
+{
+	uint32_t m;
+	uint32_t s;
+	struct logical_volume *sub_lv;
+	struct logical_volume *detached_log_lv = NULL;
+	struct logical_volume *lv1 = NULL;
+	struct lv_segment *mirrored_seg = first_seg(lv);
+	uint32_t old_area_count = mirrored_seg->area_count;
+	uint32_t new_area_count = mirrored_seg->area_count;
+	struct lv_list *lvl;
+	struct dm_list tmp_orphan_lvs;
+
+	if (removed)
+		*removed = 0;
+
+	log_very_verbose("Reducing mirror set from %" PRIu32 " to %"
+			 PRIu32 " image(s)%s.",
+			 old_area_count, old_area_count - num_removed,
+			 remove_log ? " and no log volume" : "");
+
+	if (collapse &&
+	    (removable_pvs || (old_area_count - num_removed != 1))) {
+		log_error("Incompatible parameters to _remove_mirror_images");
+		return 0;
+	}
+
+	/* Move removable_pvs to end of array */
+	if (removable_pvs) {
+		for (s = 0; s < mirrored_seg->area_count &&
+			    old_area_count - new_area_count < num_removed; s++) {
+			sub_lv = seg_lv(mirrored_seg, s);
+
+			if (!is_temporary_mirror_layer(sub_lv) &&
+			    _is_mirror_image_removable(sub_lv, removable_pvs)) {
+				if (!shift_mirror_images(mirrored_seg, s))
+					return_0;
+				new_area_count--;
+			}
+		}
+		if (num_removed && old_area_count == new_area_count)
+			return 1;
+	} else
+		new_area_count = old_area_count - num_removed;
+
+	/* Remove mimage LVs from the segment */
+	dm_list_init(&tmp_orphan_lvs);
+	for (m = new_area_count; m < mirrored_seg->area_count; m++) {
+		seg_lv(mirrored_seg, m)->status &= ~MIRROR_IMAGE;
+		seg_lv(mirrored_seg, m)->status |= VISIBLE_LV;
+		if (!(lvl = dm_pool_alloc(lv->vg->cmd->mem, sizeof(*lvl)))) {
+			log_error("lv_list alloc failed");
+			return 0;
+		}
+		lvl->lv = seg_lv(mirrored_seg, m);
+		dm_list_add(&tmp_orphan_lvs, &lvl->list);
+		release_lv_segment_area(mirrored_seg, m, mirrored_seg->area_len);
+	}
+	mirrored_seg->area_count = new_area_count;
+
+	/* If no more mirrors, remove mirror layer */
+	/* As an exceptional case, if the lv is temporary layer,
+	 * leave the LV as mirrored and let the lvconvert completion
+	 * to remove the layer. */
+	if (new_area_count == 1 && !is_temporary_mirror_layer(lv)) {
+		lv1 = seg_lv(mirrored_seg, 0);
+		lv1->status &= ~MIRROR_IMAGE;
+		lv1->status |= VISIBLE_LV;
+		detached_log_lv = detach_mirror_log(mirrored_seg);
+		if (!remove_layer_from_lv(lv, lv1))
+			return_0;
+		lv->status &= ~MIRRORED;
+		lv->status &= ~MIRROR_NOTSYNCED;
+		if (collapse && !_merge_mirror_images(lv, &tmp_orphan_lvs)) {
+			log_error("Failed to add mirror images");
+			return 0;
+		}
+	} else if (new_area_count == 0) {
+		log_very_verbose("All mimages of %s are gone", lv->name);
+
+		/* All mirror images are gone.
+		 * It can happen for vgreduce --removemissing. */
+		detached_log_lv = detach_mirror_log(mirrored_seg);
+		lv->status &= ~MIRRORED;
+		lv->status &= ~MIRROR_NOTSYNCED;
+		if (!replace_lv_with_error_segment(lv))
+			return_0;
+	} else if (remove_log)
+		detached_log_lv = detach_mirror_log(mirrored_seg);
+
+	/*
+	 * To successfully remove these unwanted LVs we need to
+	 * remove the LVs from the mirror set, commit that metadata
+	 * then deactivate and remove them fully.
+	 */
+
+	if (!vg_write(mirrored_seg->lv->vg)) {
+		log_error("intermediate VG write failed.");
+		return 0;
+	}
+
+	if (!suspend_lv(mirrored_seg->lv->vg->cmd, mirrored_seg->lv)) {
+		log_error("Failed to lock %s", mirrored_seg->lv->name);
+		vg_revert(mirrored_seg->lv->vg);
+		return 0;
+	}
+
+	if (!vg_commit(mirrored_seg->lv->vg)) {
+		resume_lv(mirrored_seg->lv->vg->cmd, mirrored_seg->lv);
+		return 0;
+	}
+
+	log_very_verbose("Updating \"%s\" in kernel", mirrored_seg->lv->name);
+
+	/*
+	 * Avoid having same mirror target loaded twice simultaneously by first
+	 * resuming the removed LV which now contains an error segment.
+	 * As it's now detached from mirrored_seg->lv we must resume it
+	 * explicitly.
+	 */
+	if (lv1 && !resume_lv(lv1->vg->cmd, lv1)) {
+		log_error("Problem resuming temporary LV, %s", lv1->name);
+		return 0;
+	}
+
+	if (!resume_lv(mirrored_seg->lv->vg->cmd, mirrored_seg->lv)) {
+		log_error("Problem reactivating %s", mirrored_seg->lv->name);
+		return 0;
+	}
+
+	/* Save or delete the 'orphan' LVs */
+	if (!collapse) {
+		dm_list_iterate_items(lvl, &tmp_orphan_lvs)
+			if (!_delete_lv(lv, lvl->lv))
+				return_0;
+	}
+
+	if (lv1 && !_delete_lv(lv, lv1))
+		return_0;
+
+	if (detached_log_lv && !_delete_lv(lv, detached_log_lv))
+		return_0;
+
+	/* Mirror with only 1 area is 'in sync'. */
+	if (new_area_count == 1 && is_temporary_mirror_layer(lv)) {
+		if (first_seg(lv)->log_lv &&
+		    !_init_mirror_log(lv->vg->cmd, first_seg(lv)->log_lv,
+				      1, &lv->tags, 0)) {
+			/* As a result, unnecessary sync may run after
+			 * collapsing. But safe.*/
+			log_error("Failed to initialize log device");
+			return_0;
+		}
+	}
+
+	if (removed)
+		*removed = old_area_count - new_area_count;
+
+	log_very_verbose("%" PRIu32 " image(s) removed from %s",
+			 old_area_count - num_removed, lv->name);
+
+	return 1;
+}
+
+/*
+ * Remove the number of mirror images from the LV
+ */
+int remove_mirror_images(struct logical_volume *lv, uint32_t num_mirrors,
+			 struct dm_list *removable_pvs, unsigned remove_log)
+{
+	uint32_t num_removed, removed_once, r;
+	uint32_t existing_mirrors = lv_mirror_count(lv);
+	struct logical_volume *next_lv = lv;
+
+	num_removed = existing_mirrors - num_mirrors;
+
+	/* num_removed can be 0 if the function is called just to remove log */
+	do {
+		if (num_removed < first_seg(next_lv)->area_count)
+			removed_once = num_removed;
+		else
+			removed_once = first_seg(next_lv)->area_count - 1;
+
+		if (!_remove_mirror_images(next_lv, removed_once,
+					   removable_pvs, remove_log, 0, &r))
+			return_0;
+
+		if (r < removed_once) {
+			/* Some mirrors are removed from the temporary mirror,
+			 * but the temporary layer still exists.
+			 * Down the stack and retry for remainder. */
+			next_lv = find_temporary_mirror(next_lv);
+		}
+
+		num_removed -= r;
+	} while (next_lv && num_removed);
+
+	if (num_removed) {
+		if (num_removed == existing_mirrors - num_mirrors)
+			log_error("No mirror images found using specified PVs.");
+		else {
+			log_error("%u images are removed out of requested %u.",
+				  existing_mirrors - lv_mirror_count(lv),
+				  existing_mirrors - num_mirrors);
+		}
+		return 0;
+	}
+
+	return 1;
+}
+
+static int _mirrored_lv_in_sync(struct logical_volume *lv)
+{
+	float sync_percent;
+
+	if (!lv_mirror_percent(lv->vg->cmd, lv, 0, &sync_percent, NULL)) {
+		log_error("Unable to determine mirror sync status of %s/%s.",
+			  lv->vg->name, lv->name);
+		return 0;
+	}
+
+	if (sync_percent >= 100.0)
+		return 1;
+
+	return 0;
+}
+
+/*
+ * Collapsing temporary mirror layers.
+ *
+ * When mirrors are added to already-mirrored LV, a temporary mirror layer
+ * is inserted at the top of the stack to reduce resync work.
+ * The function will remove the intermediate layer and collapse the stack
+ * as far as mirrors are in-sync.
+ *
+ * The function is destructive: to remove intermediate mirror layers,
+ * VG metadata commits and suspend/resume are necessary.
+ */
+int collapse_mirrored_lv(struct logical_volume *lv)
+{
+	struct logical_volume *tmp_lv;
+	struct lv_segment *mirror_seg;
+
+	while ((tmp_lv = find_temporary_mirror(lv))) {
+		mirror_seg = find_mirror_seg(first_seg(tmp_lv));
+		if (!mirror_seg) {
+			log_error("Failed to find mirrored LV for %s",
+				  tmp_lv->name);
+			return 0;
+		}
+
+		if (!_mirrored_lv_in_sync(mirror_seg->lv)) {
+			log_verbose("Not collapsing %s: out-of-sync",
+				    mirror_seg->lv->name);
+			return 1;
+		}
+
+		if (!_remove_mirror_images(mirror_seg->lv,
+					   mirror_seg->area_count - 1,
+					   NULL, 1, 1, NULL)) {
+			log_error("Failed to release mirror images");
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+static int get_mirror_fault_policy(struct cmd_context *cmd __attribute((unused)),
+				   int log_policy)
+{
+	const char *policy;
+
+	if (log_policy)
+		policy = find_config_str(NULL, "activation/mirror_log_fault_policy",
+					 DEFAULT_MIRROR_LOG_FAULT_POLICY);
+	else
+		policy = find_config_str(NULL, "activation/mirror_device_fault_policy",
+					 DEFAULT_MIRROR_DEV_FAULT_POLICY);
+
+	if (!strcmp(policy, "remove"))
+		return MIRROR_REMOVE;
+	else if (!strcmp(policy, "allocate"))
+		return MIRROR_ALLOCATE;
+	else if (!strcmp(policy, "allocate_anywhere"))
+		return MIRROR_ALLOCATE_ANYWHERE;
+
+	if (log_policy)
+		log_error("Bad activation/mirror_log_fault_policy");
+	else
+		log_error("Bad activation/mirror_device_fault_policy");
+
+	return MIRROR_REMOVE;
+}
+
+static int get_mirror_log_fault_policy(struct cmd_context *cmd)
+{
+	return get_mirror_fault_policy(cmd, 1);
+}
+
+static int get_mirror_device_fault_policy(struct cmd_context *cmd)
+{
+	return get_mirror_fault_policy(cmd, 0);
+}
+
+/*
+ * replace_mirror_images
+ * @mirrored_seg: segment (which may be linear now) to restore
+ * @num_mirrors: number of copies we should end up with
+ * @replace_log: replace log if not present
+ * @in_sync: was the original mirror in-sync?
+ *
+ * in_sync will be set to 0 if new mirror devices are being added
+ * In other words, it is only useful if the log (and only the log)
+ * is being restored.
+ *
+ * Returns: 0 on failure, 1 on reconfig, -1 if no reconfig done
+ */
+static int replace_mirror_images(struct lv_segment *mirrored_seg,
+				 uint32_t num_mirrors,
+				 int log_policy, int in_sync)
+{
+	int r = -1;
+	struct logical_volume *lv = mirrored_seg->lv;
+
+	/* FIXME: Use lvconvert rather than duplicating its code */
+
+	if (mirrored_seg->area_count < num_mirrors) {
+		log_error("WARNING: Failed to replace mirror device in %s/%s",
+			  mirrored_seg->lv->vg->name, mirrored_seg->lv->name);
+
+		if ((mirrored_seg->area_count > 1) && !mirrored_seg->log_lv)
+			log_error("WARNING: Use 'lvconvert -m %d %s/%s --corelog' to replace failed devices",
+				  num_mirrors - 1, lv->vg->name, lv->name);
+		else
+			log_error("WARNING: Use 'lvconvert -m %d %s/%s' to replace failed devices",
+				  num_mirrors - 1, lv->vg->name, lv->name);
+		r = 0;
+
+		/* REMEMBER/FIXME: set in_sync to 0 if a new mirror device was added */
+		in_sync = 0;
+	}
+
+	/*
+	 * FIXME: right now, we ignore the allocation policy specified to
+	 * allocate the new log.
+	 */
+	if ((mirrored_seg->area_count > 1) && !mirrored_seg->log_lv &&
+	    (log_policy != MIRROR_REMOVE)) {
+		log_error("WARNING: Failed to replace mirror log device in %s/%s",
+			  lv->vg->name, lv->name);
+
+		log_error("WARNING: Use 'lvconvert -m %d %s/%s' to replace failed devices",
+			  mirrored_seg->area_count - 1 , lv->vg->name, lv->name);
+		r = 0;
+	}
+
+	return r;
+}
+
+int reconfigure_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors,
+			      struct dm_list *removable_pvs, unsigned remove_log)
+{
+	int r;
+	int in_sync;
+	int log_policy, dev_policy;
+	uint32_t old_num_mirrors = mirrored_seg->area_count;
+	int had_log = (mirrored_seg->log_lv) ? 1 : 0;
+
+	/* was the mirror in-sync before problems? */
+	in_sync = _mirrored_lv_in_sync(mirrored_seg->lv);
+
+	/*
+	 * While we are only removing devices, we can have sync set.
+	 * Setting this is only useful if we are moving to core log
+	 * otherwise the disk log will contain the sync information
+	 */
+	init_mirror_in_sync(in_sync);
+
+	r = _remove_mirror_images(mirrored_seg->lv, old_num_mirrors - num_mirrors,
+				  removable_pvs, remove_log, 0, NULL);
+	if (!r)
+		/* Unable to remove bad devices */
+		return 0;
+
+	log_warn("WARNING: Bad device removed from mirror volume, %s/%s",
+		  mirrored_seg->lv->vg->name, mirrored_seg->lv->name);
+
+	log_policy = get_mirror_log_fault_policy(mirrored_seg->lv->vg->cmd);
+	dev_policy = get_mirror_device_fault_policy(mirrored_seg->lv->vg->cmd);
+
+	r = replace_mirror_images(mirrored_seg,
+				  (dev_policy != MIRROR_REMOVE) ?
+				  old_num_mirrors : num_mirrors,
+				  log_policy, in_sync);
+
+	if (!r)
+		/* Failed to replace device(s) */
+		log_error("WARNING: Unable to find substitute device for mirror volume, %s/%s",
+			  mirrored_seg->lv->vg->name, mirrored_seg->lv->name);
+	else if (r > 0)
+		/* Success in replacing device(s) */
+		log_warn("WARNING: Mirror volume, %s/%s restored - substitute for failed device found.",
+			  mirrored_seg->lv->vg->name, mirrored_seg->lv->name);
+	else
+		/* Bad device removed, but not replaced because of policy */
+		if (mirrored_seg->area_count == 1) {
+			log_warn("WARNING: Mirror volume, %s/%s converted to linear due to device failure.",
+				  mirrored_seg->lv->vg->name, mirrored_seg->lv->name);
+		} else if (had_log && !mirrored_seg->log_lv) {
+			log_warn("WARNING: Mirror volume, %s/%s disk log removed due to device failure.",
+				  mirrored_seg->lv->vg->name, mirrored_seg->lv->name);
+		}
+	/*
+	 * If we made it here, we at least removed the bad device.
+	 * Consider this success.
+	 */
+	return 1;
+}
+
+static int _create_mimage_lvs(struct alloc_handle *ah,
+			      uint32_t num_mirrors,
+			      struct logical_volume *lv,
+			      struct logical_volume **img_lvs)
+{
+	uint32_t m;
+	char *img_name;
+	size_t len;
+	
+	len = strlen(lv->name) + 32;
+	if (!(img_name = alloca(len))) {
+		log_error("img_name allocation failed. "
+			  "Remove new LV and retry.");
+		return 0;
+	}
+
+	if (dm_snprintf(img_name, len, "%s_mimage_%%d", lv->name) < 0) {
+		log_error("img_name allocation failed. "
+			  "Remove new LV and retry.");
+		return 0;
+	}
+
+	for (m = 0; m < num_mirrors; m++) {
+		if (!(img_lvs[m] = lv_create_empty(img_name,
+					     NULL, LVM_READ | LVM_WRITE,
+					     ALLOC_INHERIT, 0, lv->vg))) {
+			log_error("Aborting. Failed to create mirror image LV. "
+				  "Remove new LV and retry.");
+			return 0;
+		}
+
+		if (!lv_add_segment(ah, m, 1, img_lvs[m],
+				    get_segtype_from_string(lv->vg->cmd,
+							    "striped"),
+				    0, 0, 0, NULL)) {
+			log_error("Aborting. Failed to add mirror image segment "
+				  "to %s. Remove new LV and retry.",
+				  img_lvs[m]->name);
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+/*
+ * Remove mirrors from each segment.
+ * 'new_mirrors' is the number of mirrors after the removal. '0' for linear.
+ * If 'status_mask' is non-zero, the removal happens only when all segments
+ * has the status bits on.
+ */
+int remove_mirrors_from_segments(struct logical_volume *lv,
+				 uint32_t new_mirrors, uint32_t status_mask)
+{
+	struct lv_segment *seg;
+	uint32_t s;
+
+	/* Check the segment params are compatible */
+	dm_list_iterate_items(seg, &lv->segments) {
+		if (!seg_is_mirrored(seg)) {
+			log_error("Segment is not mirrored: %s:%" PRIu32,
+				  lv->name, seg->le);
+			return 0;
+		} if ((seg->status & status_mask) != status_mask) {
+			log_error("Segment status does not match: %s:%" PRIu32
+				  " status:0x%x/0x%x", lv->name, seg->le,
+				  seg->status, status_mask);
+			return 0;
+		}
+	}
+
+	/* Convert the segments */
+	dm_list_iterate_items(seg, &lv->segments) {
+		if (!new_mirrors && seg->extents_copied == seg->area_len) {
+			if (!move_lv_segment_area(seg, 0, seg, 1))
+				return_0;
+		}
+
+		for (s = new_mirrors + 1; s < seg->area_count; s++)
+			release_lv_segment_area(seg, s, seg->area_len);
+
+		seg->area_count = new_mirrors + 1;
+
+		if (!new_mirrors)
+			seg->segtype = get_segtype_from_string(lv->vg->cmd,
+							       "striped");
+	}
+
+	return 1;
+}
+
+const char *get_pvmove_pvname_from_lv_mirr(struct logical_volume *lv_mirr)
+{
+	struct lv_segment *seg;
+
+	dm_list_iterate_items(seg, &lv_mirr->segments) {
+		if (!seg_is_mirrored(seg))
+			continue;
+		if (seg_type(seg, 0) != AREA_PV)
+			continue;
+		return dev_name(seg_dev(seg, 0));
+	}
+
+	return NULL;
+}
+
+const char *get_pvmove_pvname_from_lv(struct logical_volume *lv)
+{
+	struct lv_segment *seg;
+	uint32_t s;
+
+	dm_list_iterate_items(seg, &lv->segments) {
+		for (s = 0; s < seg->area_count; s++) {
+			if (seg_type(seg, s) != AREA_LV)
+				continue;
+			return get_pvmove_pvname_from_lv_mirr(seg_lv(seg, s));
+		}
+	}
+
+	return NULL;
+}
+
+struct logical_volume *find_pvmove_lv(struct volume_group *vg,
+				      struct device *dev,
+				      uint32_t lv_type)
+{
+	struct lv_list *lvl;
+	struct logical_volume *lv;
+	struct lv_segment *seg;
+
+	/* Loop through all LVs */
+	dm_list_iterate_items(lvl, &vg->lvs) {
+		lv = lvl->lv;
+
+		if (!(lv->status & lv_type))
+			continue;
+
+		/* Check segment origins point to pvname */
+		dm_list_iterate_items(seg, &lv->segments) {
+			if (seg_type(seg, 0) != AREA_PV)
+				continue;
+			if (seg_dev(seg, 0) != dev)
+				continue;
+			return lv;
+		}
+	}
+
+	return NULL;
+}
+
+struct logical_volume *find_pvmove_lv_from_pvname(struct cmd_context *cmd,
+					 	  struct volume_group *vg,
+				      		  const char *name,
+				      		  uint32_t lv_type)
+{
+	struct physical_volume *pv;
+
+	if (!(pv = find_pv_by_name(cmd, name)))
+		return_NULL;
+
+	return find_pvmove_lv(vg, pv->dev, lv_type);
+}
+
+struct dm_list *lvs_using_lv(struct cmd_context *cmd, struct volume_group *vg,
+			  struct logical_volume *lv)
+{
+	struct dm_list *lvs;
+	struct logical_volume *lv1;
+	struct lv_list *lvl, *lvl1;
+	struct lv_segment *seg;
+	uint32_t s;
+
+	if (!(lvs = dm_pool_alloc(cmd->mem, sizeof(*lvs)))) {
+		log_error("lvs list alloc failed");
+		return NULL;
+	}
+
+	dm_list_init(lvs);
+
+	/* Loop through all LVs except the one supplied */
+	dm_list_iterate_items(lvl1, &vg->lvs) {
+		lv1 = lvl1->lv;
+		if (lv1 == lv)
+			continue;
+
+		/* Find whether any segment points at the supplied LV */
+		dm_list_iterate_items(seg, &lv1->segments) {
+			for (s = 0; s < seg->area_count; s++) {
+				if (seg_type(seg, s) != AREA_LV ||
+				    seg_lv(seg, s) != lv)
+					continue;
+				if (!(lvl = dm_pool_alloc(cmd->mem, sizeof(*lvl)))) {
+					log_error("lv_list alloc failed");
+					return NULL;
+				}
+				lvl->lv = lv1;
+				dm_list_add(lvs, &lvl->list);
+				goto next_lv;
+			}
+		}
+	      next_lv:
+		;
+	}
+
+	return lvs;
+}
+
+float copy_percent(struct logical_volume *lv_mirr)
+{
+	uint32_t numerator = 0u, denominator = 0u;
+	struct lv_segment *seg;
+
+	dm_list_iterate_items(seg, &lv_mirr->segments) {
+		denominator += seg->area_len;
+
+		if (seg_is_mirrored(seg) && seg->area_count > 1)
+			numerator += seg->extents_copied;
+		else
+			numerator += seg->area_len;
+	}
+
+	return denominator ? (float) numerator *100 / denominator : 100.0;
+}
+
+/*
+ * Fixup mirror pointers after single-pass segment import
+ */
+int fixup_imported_mirrors(struct volume_group *vg)
+{
+	struct lv_list *lvl;
+	struct lv_segment *seg;
+
+	dm_list_iterate_items(lvl, &vg->lvs) {
+		dm_list_iterate_items(seg, &lvl->lv->segments) {
+			if (seg->segtype !=
+			    get_segtype_from_string(vg->cmd, "mirror"))
+				continue;
+
+			if (seg->log_lv && !add_seg_to_segs_using_this_lv(seg->log_lv, seg))
+				return_0;
+		}
+	}
+
+	return 1;
+}
+
+/*
+ * Add mirrors to "linear" or "mirror" segments
+ */
+int add_mirrors_to_segments(struct cmd_context *cmd, struct logical_volume *lv,
+			    uint32_t mirrors, uint32_t region_size,
+			    struct dm_list *allocatable_pvs, alloc_policy_t alloc)
+{
+	struct alloc_handle *ah;
+	const struct segment_type *segtype;
+	struct dm_list *parallel_areas;
+	uint32_t adjusted_region_size;
+
+	if (!(parallel_areas = build_parallel_areas_from_lv(cmd, lv)))
+		return_0;
+
+	if (!(segtype = get_segtype_from_string(cmd, "mirror")))
+		return_0;
+
+	adjusted_region_size = adjusted_mirror_region_size(lv->vg->extent_size,
+							   lv->le_count,
+							   region_size);
+
+	if (!(ah = allocate_extents(lv->vg, NULL, segtype, 1, mirrors, 0,
+				    lv->le_count, allocatable_pvs, alloc,
+				    parallel_areas))) {
+		log_error("Unable to allocate mirror extents for %s.", lv->name);
+		return 0;
+	}
+
+	if (!lv_add_mirror_areas(ah, lv, 0, adjusted_region_size)) {
+		log_error("Failed to add mirror areas to %s", lv->name);
+		return 0;
+	}
+
+	return 1;
+}
+
+/*
+ * Convert mirror log
+ *
+ * FIXME: Can't handle segment-by-segment mirror (like pvmove)
+ */
+int remove_mirror_log(struct cmd_context *cmd,
+		      struct logical_volume *lv,
+		      struct dm_list *removable_pvs)
+{
+	float sync_percent;
+	struct lvinfo info;
+	struct volume_group *vg = lv->vg;
+
+	/* Unimplemented features */
+	if (dm_list_size(&lv->segments) != 1) {
+		log_error("Multiple-segment mirror is not supported");
+		return 0;
+	}
+
+	/* Had disk log, switch to core. */
+	if (lv_info(cmd, lv, &info, 0, 0) && info.exists) {
+		if (!lv_mirror_percent(cmd, lv, 0, &sync_percent, NULL)) {
+			log_error("Unable to determine mirror sync status.");
+			return 0;
+		}
+	} else if (vg_is_clustered(vg)) {
+		log_error("Unable to convert the log of inactive "
+			  "cluster mirror %s", lv->name);
+		return 0;
+	} else if (yes_no_prompt("Full resync required to convert "
+				 "inactive mirror %s to core log. "
+				 "Proceed? [y/n]: "))
+		sync_percent = 0;
+	else
+		return 0;
+
+	if (sync_percent >= 100.0)
+		init_mirror_in_sync(1);
+	else {
+		/* A full resync will take place */
+		lv->status &= ~MIRROR_NOTSYNCED;
+		init_mirror_in_sync(0);
+	}
+
+	if (!remove_mirror_images(lv, lv_mirror_count(lv),
+				  removable_pvs, 1U))
+		return_0;
+
+	return 1;
+}
+
+static struct logical_volume *_create_mirror_log(struct logical_volume *lv,
+						 struct alloc_handle *ah,
+						 alloc_policy_t alloc,
+						 const char *lv_name,
+						 const char *suffix)
+{
+	struct logical_volume *log_lv;
+	char *log_name;
+	size_t len;
+
+	len = strlen(lv_name) + 32;
+	if (!(log_name = alloca(len))) {
+		log_error("log_name allocation failed.");
+		return NULL;
+	}
+
+	if (dm_snprintf(log_name, len, "%s%s", lv_name, suffix) < 0) {
+		log_error("log_name allocation failed.");
+		return NULL;
+	}
+
+	if (!(log_lv = lv_create_empty(log_name, NULL,
+				       VISIBLE_LV | LVM_READ | LVM_WRITE,
+				       alloc, 0, lv->vg)))
+		return_NULL;
+
+	if (!lv_add_log_segment(ah, log_lv))
+		return_NULL;
+
+	return log_lv;
+}
+
+static struct logical_volume *_set_up_mirror_log(struct cmd_context *cmd,
+						 struct alloc_handle *ah,
+						 struct logical_volume *lv,
+						 uint32_t log_count,
+						 uint32_t region_size __attribute((unused)),
+						 alloc_policy_t alloc,
+						 int in_sync)
+{
+	struct logical_volume *log_lv;
+	const char *suffix, *c;
+	char *lv_name;
+	size_t len;
+	struct lv_segment *seg;
+
+	init_mirror_in_sync(in_sync);
+
+	if (log_count != 1) {
+		log_error("log_count != 1 is not supported.");
+		return NULL;
+	}
+
+	/* Mirror log name is lv_name + suffix, determined as the following:
+	 *   1. suffix is:
+	 *        o "_mlog" for the original mirror LV.
+	 *        o "_mlogtmp_%d" for temporary mirror LV,
+	 *   2. lv_name is:
+	 *        o lv->name, if the log is temporary
+	 *        o otherwise, the top-level LV name
+	 */
+	seg = first_seg(lv);
+	if (seg_type(seg, 0) == AREA_LV &&
+	    strstr(seg_lv(seg, 0)->name, MIRROR_SYNC_LAYER)) {
+		lv_name = lv->name;
+		suffix = "_mlogtmp_%d";
+	} else if ((c = strstr(lv->name, MIRROR_SYNC_LAYER))) {
+		len = c - lv->name + 1;
+		if (!(lv_name = alloca(len)) ||
+		    !dm_snprintf(lv_name, len, "%s", lv->name)) {
+			log_error("mirror log name allocation failed");
+			return 0;
+		}
+		suffix = "_mlog";
+	} else {
+		lv_name = lv->name;
+		suffix = "_mlog";
+	}
+
+	if (!(log_lv = _create_mirror_log(lv, ah, alloc,
+					  (const char *) lv_name, suffix))) {
+		log_error("Failed to create mirror log.");
+		return NULL;
+	}
+
+	if (!_init_mirror_log(cmd, log_lv, in_sync, &lv->tags, 1)) {
+		log_error("Failed to create mirror log.");
+		return NULL;
+	}
+
+	return log_lv;
+}
+
+int attach_mirror_log(struct lv_segment *seg, struct logical_volume *log_lv)
+{
+	seg->log_lv = log_lv;
+	log_lv->status |= MIRROR_LOG;
+	log_lv->status &= ~VISIBLE_LV;
+	return add_seg_to_segs_using_this_lv(log_lv, seg);
+}
+
+int add_mirror_log(struct cmd_context *cmd, struct logical_volume *lv,
+		   uint32_t log_count, uint32_t region_size,
+		   struct dm_list *allocatable_pvs, alloc_policy_t alloc)
+{
+	struct alloc_handle *ah;
+	const struct segment_type *segtype;
+	struct dm_list *parallel_areas;
+	float sync_percent;
+	int in_sync;
+	struct logical_volume *log_lv;
+	struct lvinfo info;
+
+	/* Unimplemented features */
+	if (log_count > 1) {
+		log_error("log_count > 1 is not supported");
+		return 0;
+	}
+
+	if (dm_list_size(&lv->segments) != 1) {
+		log_error("Multiple-segment mirror is not supported");
+		return 0;
+	}
+
+	/*
+	 * We are unable to convert the log of inactive cluster mirrors
+	 * due to the inability to detect whether the mirror is active
+	 * on remote nodes (even though it is inactive on this node)
+	 */
+	if (vg_is_clustered(lv->vg) &&
+	    !(lv_info(cmd, lv, &info, 0, 0) && info.exists)) {
+		log_error("Unable to convert the log of inactive "
+			  "cluster mirror %s", lv->name);
+		return 0;
+	}
+
+	if (!(parallel_areas = build_parallel_areas_from_lv(cmd, lv)))
+		return_0;
+
+	if (!(segtype = get_segtype_from_string(cmd, "mirror")))
+		return_0;
+
+	if (activation() && segtype->ops->target_present &&
+	    !segtype->ops->target_present(NULL, NULL)) {
+		log_error("%s: Required device-mapper target(s) not "
+			  "detected in your kernel", segtype->name);
+		return 0;
+	}
+
+	/* allocate destination extents */
+	ah = allocate_extents(lv->vg, NULL, segtype,
+			      0, 0, log_count, 0,
+			      allocatable_pvs, alloc, parallel_areas);
+	if (!ah) {
+		log_error("Unable to allocate extents for mirror log.");
+		return 0;
+	}
+
+	/* check sync status */
+	if (lv_mirror_percent(cmd, lv, 0, &sync_percent, NULL) &&
+	    sync_percent >= 100.0)
+		in_sync = 1;
+	else
+		in_sync = 0;
+
+	if (!(log_lv = _set_up_mirror_log(cmd, ah, lv, log_count,
+					  region_size, alloc, in_sync)))
+		return_0;
+
+	if (!attach_mirror_log(first_seg(lv), log_lv))
+		return_0;
+
+	alloc_destroy(ah);
+	return 1;
+}
+
+/*
+ * Convert "linear" LV to "mirror".
+ */
+int add_mirror_images(struct cmd_context *cmd, struct logical_volume *lv,
+		      uint32_t mirrors, uint32_t stripes, uint32_t region_size,
+		      struct dm_list *allocatable_pvs, alloc_policy_t alloc,
+		      uint32_t log_count)
+{
+	struct alloc_handle *ah;
+	const struct segment_type *segtype;
+	struct dm_list *parallel_areas;
+	struct logical_volume **img_lvs;
+	struct logical_volume *log_lv = NULL;
+
+	if (stripes > 1) {
+		log_error("stripes > 1 is not supported");
+		return 0;
+	}
+
+	/*
+	 * allocate destination extents
+	 */
+
+	if (!(parallel_areas = build_parallel_areas_from_lv(cmd, lv)))
+		return_0;
+
+	if (!(segtype = get_segtype_from_string(cmd, "mirror")))
+		return_0;
+
+	ah = allocate_extents(lv->vg, NULL, segtype,
+			      stripes, mirrors, log_count, lv->le_count,
+			      allocatable_pvs, alloc, parallel_areas);
+	if (!ah) {
+		log_error("Unable to allocate extents for mirror(s).");
+		return 0;
+	}
+
+	/*
+	 * create and initialize mirror log
+	 */
+	if (log_count &&
+	    !(log_lv = _set_up_mirror_log(cmd, ah, lv, log_count, region_size,
+					  alloc, mirror_in_sync())))
+		return_0;
+
+	/* The log initialization involves vg metadata commit.
+	   So from here on, if failure occurs, the log must be explicitly
+	   removed and the updated vg metadata should be committed. */
+
+	/*
+	 * insert a mirror layer
+	 */
+	if (dm_list_size(&lv->segments) != 1 ||
+	    seg_type(first_seg(lv), 0) != AREA_LV)
+		if (!insert_layer_for_lv(cmd, lv, 0, "_mimage_%d"))
+			goto out_remove_log;
+
+	/*
+	 * create mirror image LVs
+	 */
+	if (!(img_lvs = alloca(sizeof(*img_lvs) * mirrors))) {
+		log_error("img_lvs allocation failed. "
+			  "Remove new LV and retry.");
+		goto out_remove_log;
+	}
+
+	if (!_create_mimage_lvs(ah, mirrors, lv, img_lvs))
+		goto out_remove_log;
+
+	if (!lv_add_mirror_lvs(lv, img_lvs, mirrors,
+			       MIRROR_IMAGE | (lv->status & LOCKED),
+			       region_size)) {
+		log_error("Aborting. Failed to add mirror segment. "
+			  "Remove new LV and retry.");
+		goto out_remove_imgs;
+	}
+
+	if (log_count && !attach_mirror_log(first_seg(lv), log_lv))
+		stack;
+
+	alloc_destroy(ah);
+	return 1;
+
+  out_remove_log:
+	if (log_lv && (!lv_remove(log_lv) || !vg_write(log_lv->vg) ||
+		       (backup(log_lv->vg), !vg_commit(log_lv->vg))))
+		log_error("Manual intervention may be required to remove "
+			  "abandoned log LV before retrying.");
+
+  out_remove_imgs:
+	return 0;
+}
+
+/*
+ * Generic interface for adding mirror and/or mirror log.
+ * 'mirror' is the number of mirrors to be added.
+ * 'pvs' is either allocatable pvs.
+ */
+int lv_add_mirrors(struct cmd_context *cmd, struct logical_volume *lv,
+		   uint32_t mirrors, uint32_t stripes,
+		   uint32_t region_size, uint32_t log_count,
+		   struct dm_list *pvs, alloc_policy_t alloc, uint32_t flags)
+{
+	if (!mirrors && !log_count) {
+		log_error("No conversion is requested");
+		return 0;
+	}
+
+	/* For corelog mirror, activation code depends on
+	 * the global mirror_in_sync status. As we are adding
+	 * a new mirror, it should be set as 'out-of-sync'
+	 * so that the sync starts. */
+	/* However, MIRROR_SKIP_INIT_SYNC even overrides it. */
+	if (flags & MIRROR_SKIP_INIT_SYNC)
+		init_mirror_in_sync(1);
+	else if (!log_count)
+		init_mirror_in_sync(0);
+
+	if (flags & MIRROR_BY_SEG) {
+		if (log_count) {
+			log_error("Persistent log is not supported on "
+				  "segment-by-segment mirroring");
+			return 0;
+		}
+		if (stripes > 1) {
+			log_error("Striped-mirroring is not supported on "
+				  "segment-by-segment mirroring");
+			return 0;
+		}
+
+		return add_mirrors_to_segments(cmd, lv, mirrors,
+					       region_size, pvs, alloc);
+	} else if (flags & MIRROR_BY_LV) {
+		if (!mirrors)
+			return add_mirror_log(cmd, lv, log_count,
+					      region_size, pvs, alloc);
+		return add_mirror_images(cmd, lv, mirrors,
+					 stripes, region_size,
+					 pvs, alloc, log_count);
+	}
+
+	log_error("Unsupported mirror conversion type");
+	return 0;
+}
+
+/*
+ * Generic interface for removing mirror and/or mirror log.
+ * 'mirror' is the number of mirrors to be removed.
+ * 'pvs' is removable pvs.
+ */
+int lv_remove_mirrors(struct cmd_context *cmd __attribute((unused)),
+		      struct logical_volume *lv,
+		      uint32_t mirrors, uint32_t log_count, struct dm_list *pvs,
+		      uint32_t status_mask)
+{
+	uint32_t new_mirrors;
+	struct lv_segment *seg;
+
+	if (!mirrors && !log_count) {
+		log_error("No conversion is requested");
+		return 0;
+	}
+
+	seg = first_seg(lv);
+	if (!seg_is_mirrored(seg)) {
+		log_error("Not a mirror segment");
+		return 0;
+	}
+
+	if (lv_mirror_count(lv) <= mirrors) {
+		log_error("Removing more than existing: %d <= %d",
+			  seg->area_count, mirrors);
+		return 0;
+	}
+	new_mirrors = lv_mirror_count(lv) - mirrors - 1;
+
+	/* MIRROR_BY_LV */
+	if (seg_type(seg, 0) == AREA_LV &&
+	    seg_lv(seg, 0)->status & MIRROR_IMAGE)
+		return remove_mirror_images(lv, new_mirrors + 1,
+					    pvs, log_count ? 1U : 0);
+
+	/* MIRROR_BY_SEG */
+	if (log_count) {
+		log_error("Persistent log is not supported on "
+			  "segment-by-segment mirroring");
+		return 0;
+	}
+	return remove_mirrors_from_segments(lv, new_mirrors, status_mask);
+}
+
Index: src/external/gpl2/lvm2tools/dist/lib/metadata/pv_alloc.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/metadata/pv_alloc.h
diff -N src/external/gpl2/lvm2tools/dist/lib/metadata/pv_alloc.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/metadata/pv_alloc.h	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,30 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_PV_ALLOC_H
+
+int alloc_pv_segment_whole_pv(struct dm_pool *mem, struct physical_volume *pv);
+int peg_dup(struct dm_pool *mem, struct dm_list *peg_new, struct dm_list *peg_old);
+struct pv_segment *assign_peg_to_lvseg(struct physical_volume *pv, uint32_t pe,
+				       uint32_t area_len,
+				       struct lv_segment *seg,
+				       uint32_t area_num);
+int pv_split_segment(struct physical_volume *pv, uint32_t pe);
+int release_pv_segment(struct pv_segment *peg, uint32_t area_reduction);
+int check_pv_segments(struct volume_group *vg);
+void merge_pv_segments(struct pv_segment *peg1, struct pv_segment *peg2);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/metadata/pv_manip.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/metadata/pv_manip.c
diff -N src/external/gpl2/lvm2tools/dist/lib/metadata/pv_manip.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/metadata/pv_manip.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,429 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "metadata.h"
+#include "pv_alloc.h"
+#include "toolcontext.h"
+#include "archiver.h"
+#include "locking.h"
+#include "lvmcache.h"
+
+static struct pv_segment *_alloc_pv_segment(struct dm_pool *mem,
+					    struct physical_volume *pv,
+					    uint32_t pe, uint32_t len,
+					    struct lv_segment *lvseg,
+					    uint32_t lv_area)
+{
+	struct pv_segment *peg;
+
+	if (!(peg = dm_pool_zalloc(mem, sizeof(*peg)))) {
+		log_error("pv_segment allocation failed");
+		return NULL;
+	}
+
+	peg->pv = pv;
+	peg->pe = pe;
+	peg->len = len;
+	peg->lvseg = lvseg;
+	peg->lv_area = lv_area;
+
+	dm_list_init(&peg->list);
+
+	return peg;
+}
+
+int alloc_pv_segment_whole_pv(struct dm_pool *mem, struct physical_volume *pv)
+{
+	struct pv_segment *peg;
+
+	if (!pv->pe_count)
+		return 1;
+
+	/* FIXME Cope with holes in PVs */
+	if (!(peg = _alloc_pv_segment(mem, pv, 0, pv->pe_count, NULL, 0)))
+		return_0;
+
+	dm_list_add(&pv->segments, &peg->list);
+
+	return 1;
+}
+
+int peg_dup(struct dm_pool *mem, struct dm_list *peg_new, struct dm_list *peg_old)
+{
+	struct pv_segment *peg, *pego;
+
+	dm_list_init(peg_new);
+
+	dm_list_iterate_items(pego, peg_old) {
+		if (!(peg = _alloc_pv_segment(mem, pego->pv, pego->pe,
+					      pego->len, pego->lvseg,
+					      pego->lv_area)))
+			return_0;
+		dm_list_add(peg_new, &peg->list);
+	}
+
+	return 1;
+}
+
+/*
+ * Split peg at given extent.
+ * Second part is always deallocated.
+ */
+static int _pv_split_segment(struct physical_volume *pv, struct pv_segment *peg,
+			     uint32_t pe)
+{
+	struct pv_segment *peg_new;
+
+	if (!(peg_new = _alloc_pv_segment(pv->fmt->cmd->mem, peg->pv, pe,
+					  peg->len + peg->pe - pe,
+					  NULL, 0)))
+		return_0;
+
+	peg->len = peg->len - peg_new->len;
+
+	dm_list_add_h(&peg->list, &peg_new->list);
+
+	if (peg->lvseg) {
+		peg->pv->pe_alloc_count -= peg_new->len;
+		peg->lvseg->lv->vg->free_count += peg_new->len;
+	}
+
+	return 1;
+}
+
+/*
+ * Ensure there is a PV segment boundary at the given extent.
+ */
+int pv_split_segment(struct physical_volume *pv, uint32_t pe)
+{
+	struct pv_segment *peg;
+
+	if (pe == pv->pe_count)
+		return 1;
+
+	if (!(peg = find_peg_by_pe(pv, pe))) {
+		log_error("Segment with extent %" PRIu32 " in PV %s not found",
+			  pe, pv_dev_name(pv));
+		return 0;
+	}
+
+	/* This is a peg start already */
+	if (pe == peg->pe)
+		return 1;
+
+	if (!_pv_split_segment(pv, peg, pe))
+		return_0;
+
+	return 1;
+}
+
+static struct pv_segment null_pv_segment = {
+	.pv = NULL,
+	.pe = 0,
+};
+
+struct pv_segment *assign_peg_to_lvseg(struct physical_volume *pv,
+				       uint32_t pe, uint32_t area_len,
+				       struct lv_segment *seg,
+				       uint32_t area_num)
+{
+	struct pv_segment *peg;
+
+	/* Missing format1 PV */
+	if (!pv)
+		return &null_pv_segment;
+
+	if (!pv_split_segment(pv, pe) ||
+	    !pv_split_segment(pv, pe + area_len))
+		return_NULL;
+
+	if (!(peg = find_peg_by_pe(pv, pe))) {
+		log_error("Missing PV segment on %s at %u.",
+			  pv_dev_name(pv), pe);
+		return NULL;
+	}
+
+	peg->lvseg = seg;
+	peg->lv_area = area_num;
+
+	peg->pv->pe_alloc_count += area_len;
+	peg->lvseg->lv->vg->free_count -= area_len;
+
+	return peg;
+}
+
+int release_pv_segment(struct pv_segment *peg, uint32_t area_reduction)
+{
+	if (!peg->lvseg) {
+		log_error("release_pv_segment with unallocated segment: "
+			  "%s PE %" PRIu32, pv_dev_name(peg->pv), peg->pe);
+		return 0;
+	}
+
+	if (peg->lvseg->area_len == area_reduction) {
+		peg->pv->pe_alloc_count -= area_reduction;
+		peg->lvseg->lv->vg->free_count += area_reduction;
+
+		peg->lvseg = NULL;
+		peg->lv_area = 0;
+
+		/* FIXME merge free space */
+
+		return 1;
+	}
+
+	if (!pv_split_segment(peg->pv, peg->pe + peg->lvseg->area_len -
+				       area_reduction))
+		return_0;
+
+	return 1;
+}
+
+/*
+ * Only for use by lv_segment merging routines.
+ */
+void merge_pv_segments(struct pv_segment *peg1, struct pv_segment *peg2)
+{
+	peg1->len += peg2->len;
+
+	dm_list_del(&peg2->list);
+}
+
+/*
+ * Calculate the overlap, in extents, between a struct pv_segment and
+ * a struct pe_range.
+ */
+static uint32_t _overlap_pe(const struct pv_segment *pvseg,
+			    const struct pe_range *per)
+{
+	uint32_t start;
+	uint32_t end;
+
+	start = max(pvseg->pe, per->start);
+	end = min(pvseg->pe + pvseg->len, per->start + per->count);
+	if (end < start)
+		return 0;
+	else
+		return end - start;
+}
+
+/*
+ * Returns: number of free PEs in a struct pv_list
+ */
+uint32_t pv_list_extents_free(const struct dm_list *pvh)
+{
+	struct pv_list *pvl;
+	struct pe_range *per;
+	uint32_t extents = 0;
+	struct pv_segment *pvseg;
+
+	dm_list_iterate_items(pvl, pvh) {
+		dm_list_iterate_items(per, pvl->pe_ranges) {
+			dm_list_iterate_items(pvseg, &pvl->pv->segments) {
+				if (!pvseg_is_allocated(pvseg))
+					extents += _overlap_pe(pvseg, per);
+			}
+		}
+	}
+
+	return extents;
+}
+
+/*
+ * Check all pv_segments in VG for consistency
+ */
+int check_pv_segments(struct volume_group *vg)
+{
+	struct physical_volume *pv;
+	struct pv_list *pvl;
+	struct pv_segment *peg;
+	unsigned s, segno;
+	uint32_t start_pe, alloced;
+	uint32_t pv_count = 0, free_count = 0, extent_count = 0;
+	int ret = 1;
+
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		pv = pvl->pv;
+		segno = 0;
+		start_pe = 0;
+		alloced = 0;
+		pv_count++;
+
+		dm_list_iterate_items(peg, &pv->segments) {
+			s = peg->lv_area;
+
+			/* FIXME Remove this next line eventually */
+			log_debug("%s %u: %6u %6u: %s(%u:%u)",
+				  pv_dev_name(pv), segno++, peg->pe, peg->len,
+				  peg->lvseg ? peg->lvseg->lv->name : "NULL",
+				  peg->lvseg ? peg->lvseg->le : 0, s);
+			/* FIXME Add details here on failure instead */
+			if (start_pe != peg->pe) {
+				log_error("Gap in pvsegs: %u, %u",
+					  start_pe, peg->pe);
+				ret = 0;
+			}
+			if (peg->lvseg) {
+				if (seg_type(peg->lvseg, s) != AREA_PV) {
+					log_error("Wrong lvseg area type");
+					ret = 0;
+				}
+				if (seg_pvseg(peg->lvseg, s) != peg) {
+					log_error("Inconsistent pvseg pointers");
+					ret = 0;
+				}
+				if (peg->lvseg->area_len != peg->len) {
+					log_error("Inconsistent length: %u %u",
+						  peg->len,
+						  peg->lvseg->area_len);
+					ret = 0;
+				}
+				alloced += peg->len;
+			}
+			start_pe += peg->len;
+		}
+
+		if (start_pe != pv->pe_count) {
+			log_error("PV segment pe_count mismatch: %u != %u",
+				  start_pe, pv->pe_count);
+			ret = 0;
+		}
+
+		if (alloced != pv->pe_alloc_count) {
+			log_error("PV segment pe_alloc_count mismatch: "
+				  "%u != %u", alloced, pv->pe_alloc_count);
+			ret = 0;
+		}
+
+		extent_count += start_pe;
+		free_count += (start_pe - alloced);
+	}
+
+	if (pv_count != vg->pv_count) {
+		log_error("PV segment VG pv_count mismatch: %u != %u",
+			  pv_count, vg->pv_count);
+		ret = 0;
+	}
+
+	if (free_count != vg->free_count) {
+		log_error("PV segment VG free_count mismatch: %u != %u",
+			  free_count, vg->free_count);
+		ret = 0;
+	}
+
+	if (extent_count != vg->extent_count) {
+		log_error("PV segment VG extent_count mismatch: %u != %u",
+			  extent_count, vg->extent_count);
+		ret = 0;
+	}
+
+	return ret;
+}
+
+static int _reduce_pv(struct physical_volume *pv, struct volume_group *vg, uint32_t new_pe_count)
+{
+	struct pv_segment *peg, *pegt;
+	uint32_t old_pe_count = pv->pe_count;
+
+	if (new_pe_count < pv->pe_alloc_count) {
+		log_error("%s: cannot resize to %" PRIu32 " extents "
+			  "as %" PRIu32 " are allocated.",
+			  pv_dev_name(pv), new_pe_count,
+			  pv->pe_alloc_count);
+		return 0;
+	}
+
+	/* Check PEs to be removed are not already allocated */
+	dm_list_iterate_items(peg, &pv->segments) {
+ 		if (peg->pe + peg->len <= new_pe_count)
+			continue;
+
+		if (peg->lvseg) {
+			log_error("%s: cannot resize to %" PRIu32 " extents as "
+				  "later ones are allocated.",
+				  pv_dev_name(pv), new_pe_count);
+			return 0;
+		}
+	}
+
+	if (!pv_split_segment(pv, new_pe_count))
+		return_0;
+
+	dm_list_iterate_items_safe(peg, pegt, &pv->segments) {
+ 		if (peg->pe + peg->len > new_pe_count)
+			dm_list_del(&peg->list);
+	}
+
+	pv->pe_count = new_pe_count;
+
+	vg->extent_count -= (old_pe_count - new_pe_count);
+	vg->free_count -= (old_pe_count - new_pe_count);
+
+	return 1;
+}
+
+static int _extend_pv(struct physical_volume *pv, struct volume_group *vg,
+		      uint32_t new_pe_count)
+{
+	struct pv_segment *peg;
+	uint32_t old_pe_count = pv->pe_count;
+
+	if ((uint64_t) new_pe_count * pv->pe_size > pv->size ) {
+		log_error("%s: cannot resize to %" PRIu32 " extents as there "
+			  "is only room for %" PRIu64 ".", pv_dev_name(pv),
+			  new_pe_count, pv->size / pv->pe_size);
+		return 0;
+	}
+
+	peg = _alloc_pv_segment(pv->fmt->cmd->mem, pv,
+				old_pe_count,
+				new_pe_count - old_pe_count,
+				NULL, 0);
+	dm_list_add(&pv->segments, &peg->list);
+
+	pv->pe_count = new_pe_count;
+
+	vg->extent_count += (new_pe_count - old_pe_count);
+	vg->free_count += (new_pe_count - old_pe_count);
+
+	return 1;
+}
+
+/*
+ * Resize a PV in a VG, adding or removing segments as needed.
+ * New size must fit within pv->size.
+ */
+int pv_resize(struct physical_volume *pv,
+	      struct volume_group *vg,
+	      uint32_t new_pe_count)
+{
+	if ((new_pe_count == pv->pe_count)) {
+		log_verbose("No change to size of physical volume %s.",
+			    pv_dev_name(pv));
+		return 1;
+	}
+
+	log_verbose("Resizing physical volume %s from %" PRIu32
+		    " to %" PRIu32 " extents.",
+		    pv_dev_name(pv), pv->pe_count, new_pe_count);
+
+	if (new_pe_count > pv->pe_count)
+		return _extend_pv(pv, vg, new_pe_count);
+	else
+		return _reduce_pv(pv, vg, new_pe_count);
+}
Index: src/external/gpl2/lvm2tools/dist/lib/metadata/pv_map.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/metadata/pv_map.c
diff -N src/external/gpl2/lvm2tools/dist/lib/metadata/pv_map.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/metadata/pv_map.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,208 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "pv_map.h"
+#include "pv_alloc.h"
+
+#include <assert.h>
+
+/*
+ * Areas are maintained in size order, largest first.
+ *
+ * FIXME Cope with overlap.
+ */
+static void _insert_area(struct dm_list *head, struct pv_area *a)
+{
+	struct pv_area *pva;
+
+	dm_list_iterate_items(pva, head) {
+		if (a->count > pva->count)
+			break;
+	}
+
+	dm_list_add(&pva->list, &a->list);
+	a->map->pe_count += a->count;
+}
+
+static int _create_single_area(struct dm_pool *mem, struct pv_map *pvm,
+			       uint32_t start, uint32_t length)
+{
+	struct pv_area *pva;
+
+	if (!(pva = dm_pool_zalloc(mem, sizeof(*pva))))
+		return_0;
+
+	log_debug("Allowing allocation on %s start PE %" PRIu32 " length %"
+		  PRIu32, pv_dev_name(pvm->pv), start, length);
+	pva->map = pvm;
+	pva->start = start;
+	pva->count = length;
+	_insert_area(&pvm->areas, pva);
+
+	return 1;
+}
+
+static int _create_alloc_areas_for_pv(struct dm_pool *mem, struct pv_map *pvm,
+				      uint32_t start, uint32_t count)
+{
+	struct pv_segment *peg;
+	uint32_t pe, end, area_len;
+
+	/* Only select extents from start to end inclusive */
+	end = start + count - 1;
+	if (end > pvm->pv->pe_count - 1)
+		end = pvm->pv->pe_count - 1;
+
+	pe = start;
+
+	/* Walk through complete ordered list of device segments */
+	dm_list_iterate_items(peg, &pvm->pv->segments) {
+		/* pe holds the next extent we want to check */
+
+		/* Beyond the range we're interested in? */
+		if (pe > end)
+			break;
+
+		/* Skip if we haven't reached the first seg we want yet */
+		if (pe > peg->pe + peg->len - 1)
+			continue;
+
+		/* Free? */
+		if (peg->lvseg)
+			goto next;
+
+		/* How much of this peg do we need? */
+		area_len = (end >= peg->pe + peg->len - 1) ?
+			   peg->len - (pe - peg->pe) : end - pe + 1;
+
+		if (!_create_single_area(mem, pvm, pe, area_len))
+			return_0;
+
+      next:
+		pe = peg->pe + peg->len;
+	}
+
+	return 1;
+}
+
+static int _create_all_areas_for_pv(struct dm_pool *mem, struct pv_map *pvm,
+				    struct dm_list *pe_ranges)
+{
+	struct pe_range *aa;
+
+	if (!pe_ranges) {
+		/* Use whole PV */
+		if (!_create_alloc_areas_for_pv(mem, pvm, UINT32_C(0),
+						pvm->pv->pe_count))
+			return_0;
+
+		return 1;
+	}
+
+	dm_list_iterate_items(aa, pe_ranges) {
+		if (!_create_alloc_areas_for_pv(mem, pvm, aa->start,
+						aa->count))
+			return_0;
+	}
+
+	return 1;
+}
+
+static int _create_maps(struct dm_pool *mem, struct dm_list *pvs, struct dm_list *pvms)
+{
+	struct pv_map *pvm, *pvm2;
+	struct pv_list *pvl;
+
+	dm_list_iterate_items(pvl, pvs) {
+		if (!(pvl->pv->status & ALLOCATABLE_PV))
+			continue;
+
+		pvm = NULL;
+
+		dm_list_iterate_items(pvm2, pvms)
+			if (pvm2->pv->dev == pvl->pv->dev) {
+				pvm = pvm2;
+				break;
+			}
+
+		if (!pvm) {
+			if (!(pvm = dm_pool_zalloc(mem, sizeof(*pvm))))
+				return_0;
+
+			pvm->pv = pvl->pv;
+			dm_list_init(&pvm->areas);
+			dm_list_add(pvms, &pvm->list);
+		}
+
+		if (!_create_all_areas_for_pv(mem, pvm, pvl->pe_ranges))
+			return_0;
+	}
+
+	return 1;
+}
+
+/*
+ * Create list of PV areas available for this particular allocation
+ */
+struct dm_list *create_pv_maps(struct dm_pool *mem, struct volume_group *vg,
+			    struct dm_list *allocatable_pvs)
+{
+	struct dm_list *pvms;
+
+	if (!(pvms = dm_pool_zalloc(mem, sizeof(*pvms)))) {
+		log_error("create_pv_maps alloc failed");
+		return NULL;
+	}
+
+	dm_list_init(pvms);
+
+	if (!_create_maps(mem, allocatable_pvs, pvms)) {
+		log_error("Couldn't create physical volume maps in %s",
+			  vg->name);
+		dm_pool_free(mem, pvms);
+		return NULL;
+	}
+
+	return pvms;
+}
+
+void consume_pv_area(struct pv_area *pva, uint32_t to_go)
+{
+	dm_list_del(&pva->list);
+	pva->map->pe_count -= pva->count;
+
+	assert(to_go <= pva->count);
+
+	if (to_go < pva->count) {
+		/* split the area */
+		pva->start += to_go;
+		pva->count -= to_go;
+		_insert_area(&pva->map->areas, pva);
+	}
+}
+
+uint32_t pv_maps_size(struct dm_list *pvms)
+{
+	struct pv_map *pvm;
+	uint32_t pe_count = 0;
+
+	dm_list_iterate_items(pvm, pvms)
+		pe_count += pvm->pe_count;
+
+	return pe_count;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/metadata/pv_map.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/metadata/pv_map.h
diff -N src/external/gpl2/lvm2tools/dist/lib/metadata/pv_map.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/metadata/pv_map.h	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,57 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_PV_MAP_H
+#define _LVM_PV_MAP_H
+
+#include "metadata.h"
+
+/*
+ * The in core rep. only stores a mapping from
+ * logical extents to physical extents against an
+ * lv.  Sometimes, when allocating a new lv for
+ * instance, it is useful to have the inverse
+ * mapping available.
+ */
+
+struct pv_area {
+	struct pv_map *map;
+	uint32_t start;
+	uint32_t count;
+
+	struct dm_list list;		/* pv_map.areas */
+};
+
+struct pv_map {
+	struct physical_volume *pv;
+	struct dm_list areas;		/* struct pv_areas */
+	uint32_t pe_count;		/* Total number of PEs */
+
+	struct dm_list list;
+};
+
+/*
+ * Find intersection between available_pvs and free space in VG
+ */
+struct dm_list *create_pv_maps(struct dm_pool *mem, struct volume_group *vg,
+			    struct dm_list *allocatable_pvs);
+
+void consume_pv_area(struct pv_area *area, uint32_t to_go);
+
+uint32_t pv_maps_size(struct dm_list *pvms);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/metadata/segtype.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/metadata/segtype.c
diff -N src/external/gpl2/lvm2tools/dist/lib/metadata/segtype.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/metadata/segtype.c	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,34 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "toolcontext.h"
+#include "segtype.h"
+
+struct segment_type *get_segtype_from_string(struct cmd_context *cmd,
+					     const char *str)
+{
+	struct segment_type *segtype;
+
+	dm_list_iterate_items(segtype, &cmd->segtypes) {
+		if (!strcmp(segtype->name, str))
+			return segtype;
+	}
+
+	log_error("Unrecognised segment type %s", str);
+	return NULL;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/metadata/segtype.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/metadata/segtype.h
diff -N src/external/gpl2/lvm2tools/dist/lib/metadata/segtype.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/metadata/segtype.h	13 Dec 2008 14:39:34 -0000	1.1.1.1.2.2
@@ -0,0 +1,114 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _SEGTYPES_H
+#define _SEGTYPES_H
+
+struct segtype_handler;
+struct cmd_context;
+struct config_tree;
+struct lv_segment;
+struct formatter;
+struct config_node;
+struct dev_manager;
+
+/* Feature flags */
+#define SEG_CAN_SPLIT		0x00000001U
+#define SEG_AREAS_STRIPED	0x00000002U
+#define SEG_AREAS_MIRRORED	0x00000004U
+#define SEG_SNAPSHOT		0x00000008U
+#define SEG_FORMAT1_SUPPORT	0x00000010U
+#define SEG_VIRTUAL		0x00000020U
+#define SEG_CANNOT_BE_ZEROED	0x00000040U
+#define SEG_MONITORED		0x00000080U
+
+#define seg_is_mirrored(seg)	((seg)->segtype->flags & SEG_AREAS_MIRRORED ? 1 : 0)
+#define seg_is_striped(seg)	((seg)->segtype->flags & SEG_AREAS_STRIPED ? 1 : 0)
+#define seg_is_snapshot(seg)	((seg)->segtype->flags & SEG_SNAPSHOT ? 1 : 0)
+#define seg_is_virtual(seg)	((seg)->segtype->flags & SEG_VIRTUAL ? 1 : 0)
+#define seg_can_split(seg)	((seg)->segtype->flags & SEG_CAN_SPLIT ? 1 : 0)
+#define seg_cannot_be_zeroed(seg) ((seg)->segtype->flags & SEG_CANNOT_BE_ZEROED ? 1 : 0)
+#define seg_monitored(seg)	((seg)->segtype->flags & SEG_MONITORED ? 1 : 0)
+
+#define segtype_is_striped(segtype)	((segtype)->flags & SEG_AREAS_STRIPED ? 1 : 0)
+#define segtype_is_mirrored(segtype)	((segtype)->flags & SEG_AREAS_MIRRORED ? 1 : 0)
+#define segtype_is_virtual(segtype)	((segtype)->flags & SEG_VIRTUAL ? 1 : 0)
+
+struct segment_type {
+	struct dm_list list;
+	struct cmd_context *cmd;
+	uint32_t flags;
+	struct segtype_handler *ops;
+	const char *name;
+	void *library;
+	void *private;
+};
+
+struct segtype_handler {
+	const char *(*name) (const struct lv_segment * seg);
+	void (*display) (const struct lv_segment * seg);
+	int (*text_export) (const struct lv_segment * seg,
+			    struct formatter * f);
+	int (*text_import_area_count) (struct config_node * sn,
+				       uint32_t *area_count);
+	int (*text_import) (struct lv_segment * seg,
+			    const struct config_node * sn,
+			    struct dm_hash_table * pv_hash);
+	int (*merge_segments) (struct lv_segment * seg1,
+			       struct lv_segment * seg2);
+	int (*add_target_line) (struct dev_manager *dm, struct dm_pool *mem,
+                                struct cmd_context *cmd, void **target_state,
+                                struct lv_segment *seg,
+                                struct dm_tree_node *node, uint64_t len,
+                                uint32_t *pvmove_mirror_count);
+	int (*target_percent) (void **target_state, struct dm_pool * mem,
+			       struct cmd_context *cmd,
+			       struct lv_segment *seg, char *params,
+			       uint64_t *total_numerator,
+			       uint64_t *total_denominator);
+	int (*target_present) (const struct lv_segment *seg,
+			       unsigned *attributes);
+	int (*modules_needed) (struct dm_pool *mem,
+			       const struct lv_segment *seg,
+			       struct dm_list *modules);
+	void (*destroy) (const struct segment_type * segtype);
+	int (*target_monitored) (struct lv_segment *seg, int *pending);
+	int (*target_monitor_events) (struct lv_segment *seg, int events);
+	int (*target_unmonitor_events) (struct lv_segment *seg, int events);
+};
+
+struct segment_type *get_segtype_from_string(struct cmd_context *cmd,
+					     const char *str);
+
+struct segment_type *init_striped_segtype(struct cmd_context *cmd);
+struct segment_type *init_zero_segtype(struct cmd_context *cmd);
+struct segment_type *init_error_segtype(struct cmd_context *cmd);
+struct segment_type *init_free_segtype(struct cmd_context *cmd);
+
+#ifdef SNAPSHOT_INTERNAL
+struct segment_type *init_snapshot_segtype(struct cmd_context *cmd);
+#endif
+
+#ifdef MIRRORED_INTERNAL
+struct segment_type *init_mirrored_segtype(struct cmd_context *cmd);
+#endif
+
+#ifdef CRYPT_INTERNAL
+struct segment_type *init_crypt_segtype(struct cmd_context *cmd);
+#endif
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/metadata/snapshot_manip.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/metadata/snapshot_manip.c
diff -N src/external/gpl2/lvm2tools/dist/lib/metadata/snapshot_manip.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/metadata/snapshot_manip.c	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,118 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "metadata.h"
+#include "toolcontext.h"
+#include "lv_alloc.h"
+
+int lv_is_origin(const struct logical_volume *lv)
+{
+	return lv->origin_count ? 1 : 0;
+}
+
+int lv_is_cow(const struct logical_volume *lv)
+{
+	return lv->snapshot ? 1 : 0;
+}
+
+int lv_is_visible(const struct logical_volume *lv)
+{
+	if (lv_is_cow(lv))
+		return lv_is_visible(find_cow(lv)->lv);
+
+	return lv->status & VISIBLE_LV ? 1 : 0;
+}
+
+/* Given a cow LV, return the snapshot lv_segment that uses it */
+struct lv_segment *find_cow(const struct logical_volume *lv)
+{
+	return lv->snapshot;
+}
+
+/* Given a cow LV, return its origin */
+struct logical_volume *origin_from_cow(const struct logical_volume *lv)
+{
+	return lv->snapshot->origin;
+}
+
+int vg_add_snapshot(const char *name, struct logical_volume *origin,
+		    struct logical_volume *cow, union lvid *lvid,
+		    uint32_t extent_count, uint32_t chunk_size)
+{
+	struct logical_volume *snap;
+	struct lv_segment *seg;
+
+	/*
+	 * Is the cow device already being used ?
+	 */
+	if (lv_is_cow(cow)) {
+		log_err("'%s' is already in use as a snapshot.", cow->name);
+		return 0;
+	}
+
+	if (cow == origin) {
+		log_error("Snapshot and origin LVs must differ.");
+		return 0;
+	}
+
+	if (!(snap = lv_create_empty(name ? name : "snapshot%d",
+				     lvid, LVM_READ | LVM_WRITE | VISIBLE_LV,
+				     ALLOC_INHERIT, 1, origin->vg)))
+		return_0;
+
+	snap->le_count = extent_count;
+
+	if (!(seg = alloc_snapshot_seg(snap, 0, 0)))
+		return_0;
+
+	seg->chunk_size = chunk_size;
+	seg->origin = origin;
+	seg->cow = cow;
+	seg->lv->status |= SNAPSHOT;
+
+	origin->origin_count++;
+	origin->vg->snapshot_count++;
+	origin->vg->lv_count--;
+	cow->snapshot = seg;
+
+	cow->status &= ~VISIBLE_LV;
+
+	dm_list_add(&origin->snapshot_segs, &seg->origin_list);
+
+	return 1;
+}
+
+int vg_remove_snapshot(struct logical_volume *cow)
+{
+	dm_list_del(&cow->snapshot->origin_list);
+	cow->snapshot->origin->origin_count--;
+
+	if (!lv_remove(cow->snapshot->lv)) {
+		log_error("Failed to remove internal snapshot LV %s",
+			  cow->snapshot->lv->name);
+		return 0;
+	}
+
+	cow->snapshot = NULL;
+
+	cow->vg->snapshot_count--;
+	cow->vg->lv_count++;
+	cow->status |= VISIBLE_LV;
+
+	return 1;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/mirror/.exported_symbols
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/mirror/.exported_symbols
diff -N src/external/gpl2/lvm2tools/dist/lib/mirror/.exported_symbols
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/mirror/.exported_symbols	15 Jul 2008 13:49:52 -0000	1.1.1.1
@@ -0,0 +1 @@
+init_segtype
Index: src/external/gpl2/lvm2tools/dist/lib/mirror/Makefile.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/mirror/Makefile.in
diff -N src/external/gpl2/lvm2tools/dist/lib/mirror/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/mirror/Makefile.in	12 Dec 2008 16:33:00 -0000	1.1.1.1.2.1
@@ -0,0 +1,30 @@
+#
+# Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
+# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+SOURCES = mirrored.c
+
+LIB_SHARED = liblvm2mirror.so
+LIB_VERSION = $(LIB_VERSION_LVM)
+
+include $(top_srcdir)/make.tmpl
+
+install: liblvm2mirror.so
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
+		$(libdir)/liblvm2mirror.so.$(LIB_VERSION)
+	$(LN_S) -f liblvm2mirror.so.$(LIB_VERSION) $(libdir)/liblvm2mirror.so
+
Index: src/external/gpl2/lvm2tools/dist/lib/mirror/mirrored.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/mirror/mirrored.c
diff -N src/external/gpl2/lvm2tools/dist/lib/mirror/mirrored.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/mirror/mirrored.c	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,583 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "toolcontext.h"
+#include "metadata.h"
+#include "segtype.h"
+#include "display.h"
+#include "text_export.h"
+#include "text_import.h"
+#include "config.h"
+#include "defaults.h"
+#include "lvm-string.h"
+#include "targets.h"
+#include "activate.h"
+#include "sharedlib.h"
+#include "str_list.h"
+
+#ifdef DMEVENTD
+#  include "libdevmapper-event.h"
+#endif
+
+static int _block_on_error_available = 0;
+static unsigned _mirror_attributes = 0;
+
+enum {
+	MIRR_DISABLED,
+	MIRR_RUNNING,
+	MIRR_COMPLETED
+};
+
+struct mirror_state {
+	uint32_t default_region_size;
+};
+
+static const char *_mirrored_name(const struct lv_segment *seg)
+{
+	return seg->segtype->name;
+}
+
+static void _mirrored_display(const struct lv_segment *seg)
+{
+	const char *size;
+	uint32_t s;
+
+	log_print("  Mirrors\t\t%u", seg->area_count);
+	log_print("  Mirror size\t\t%u", seg->area_len);
+	if (seg->log_lv)
+		log_print("  Mirror log volume\t%s", seg->log_lv->name);
+
+	if (seg->region_size) {
+		size = display_size(seg->lv->vg->cmd,
+				    (uint64_t) seg->region_size);
+		log_print("  Mirror region size\t%s", size);
+	}
+
+	log_print("  Mirror original:");
+	display_stripe(seg, 0, "    ");
+	log_print("  Mirror destinations:");
+	for (s = 1; s < seg->area_count; s++)
+		display_stripe(seg, s, "    ");
+	log_print(" ");
+}
+
+static int _mirrored_text_import_area_count(struct config_node *sn, uint32_t *area_count)
+{
+	if (!get_config_uint32(sn, "mirror_count", area_count)) {
+		log_error("Couldn't read 'mirror_count' for "
+			  "segment '%s'.", sn->key);
+		return 0;
+	}
+
+	return 1;
+}
+
+static int _mirrored_text_import(struct lv_segment *seg, const struct config_node *sn,
+			struct dm_hash_table *pv_hash)
+{
+	const struct config_node *cn;
+	char *logname = NULL;
+
+	if (find_config_node(sn, "extents_moved")) {
+		if (get_config_uint32(sn, "extents_moved",
+				      &seg->extents_copied))
+			seg->status |= PVMOVE;
+		else {
+			log_error("Couldn't read 'extents_moved' for "
+				  "segment '%s'.", sn->key);
+			return 0;
+		}
+	}
+
+	if (find_config_node(sn, "region_size")) {
+		if (!get_config_uint32(sn, "region_size",
+				      &seg->region_size)) {
+			log_error("Couldn't read 'region_size' for "
+				  "segment '%s'.", sn->key);
+			return 0;
+		}
+	}
+
+	if ((cn = find_config_node(sn, "mirror_log"))) {
+		if (!cn->v || !cn->v->v.str) {
+			log_error("Mirror log type must be a string.");
+			return 0;
+		}
+		logname = cn->v->v.str;
+		if (!(seg->log_lv = find_lv(seg->lv->vg, logname))) {
+			log_error("Unrecognised mirror log in segment %s.",
+				  sn->key);
+			return 0;
+		}
+		seg->log_lv->status |= MIRROR_LOG;
+	}
+
+	if (logname && !seg->region_size) {
+		log_error("Missing region size for mirror log for segment "
+			  "'%s'.", sn->key);
+		return 0;
+	}
+
+	if (!(cn = find_config_node(sn, "mirrors"))) {
+		log_error("Couldn't find mirrors array for segment "
+			  "'%s'.", sn->key);
+		return 0;
+	}
+
+	return text_import_areas(seg, sn, cn, pv_hash, MIRROR_IMAGE);
+}
+
+static int _mirrored_text_export(const struct lv_segment *seg, struct formatter *f)
+{
+	outf(f, "mirror_count = %u", seg->area_count);
+	if (seg->status & PVMOVE)
+		out_size(f, (uint64_t) seg->extents_copied * seg->lv->vg->extent_size,
+			 "extents_moved = %" PRIu32, seg->extents_copied);
+	if (seg->log_lv)
+		outf(f, "mirror_log = \"%s\"", seg->log_lv->name);
+	if (seg->region_size)
+		outf(f, "region_size = %" PRIu32, seg->region_size);
+
+	return out_areas(f, seg, "mirror");
+}
+
+#ifdef DEVMAPPER_SUPPORT
+static struct mirror_state *_mirrored_init_target(struct dm_pool *mem,
+					 struct cmd_context *cmd)
+{
+	struct mirror_state *mirr_state;
+
+	if (!(mirr_state = dm_pool_alloc(mem, sizeof(*mirr_state)))) {
+		log_error("struct mirr_state allocation failed");
+		return NULL;
+	}
+
+	mirr_state->default_region_size = 2 *
+	    find_config_tree_int(cmd,
+			    "activation/mirror_region_size",
+			    DEFAULT_MIRROR_REGION_SIZE);
+
+	return mirr_state;
+}
+
+static int _mirrored_target_percent(void **target_state, struct dm_pool *mem,
+			   struct cmd_context *cmd, struct lv_segment *seg,
+			   char *params, uint64_t *total_numerator,
+			   uint64_t *total_denominator)
+{
+	struct mirror_state *mirr_state;
+	uint64_t numerator, denominator;
+	unsigned mirror_count, m;
+	int used;
+	char *pos = params;
+
+	if (!*target_state)
+		*target_state = _mirrored_init_target(mem, cmd);
+
+	mirr_state = *target_state;
+
+	/* Status line: <#mirrors> (maj:min)+ <synced>/<total_regions> */
+	log_debug("Mirror status: %s", params);
+
+	if (sscanf(pos, "%u %n", &mirror_count, &used) != 1) {
+		log_error("Failure parsing mirror status mirror count: %s",
+			  params);
+		return 0;
+	}
+	pos += used;
+
+	for (m = 0; m < mirror_count; m++) {
+		if (sscanf(pos, "%*x:%*x %n", &used) != 0) {
+			log_error("Failure parsing mirror status devices: %s",
+				  params);
+			return 0;
+		}
+		pos += used;
+	}
+
+	if (sscanf(pos, "%" PRIu64 "/%" PRIu64 "%n", &numerator, &denominator,
+		   &used) != 2) {
+		log_error("Failure parsing mirror status fraction: %s", params);
+		return 0;
+	}
+	pos += used;
+
+	*total_numerator += numerator;
+	*total_denominator += denominator;
+
+	if (seg)
+		seg->extents_copied = seg->area_len * numerator / denominator;
+
+	return 1;
+}
+
+static int _add_log(struct dev_manager *dm, struct lv_segment *seg,
+		    struct dm_tree_node *node, uint32_t area_count, uint32_t region_size)
+{
+	unsigned clustered = 0;
+	char *log_dlid = NULL;
+	uint32_t log_flags = 0;
+
+	/*
+	 * Use clustered mirror log for non-exclusive activation
+	 * in clustered VG.
+	 */
+	if ((!(seg->lv->status & ACTIVATE_EXCL) &&
+	      (vg_is_clustered(seg->lv->vg))))
+		clustered = 1;
+
+	if (seg->log_lv) {
+		/* If disk log, use its UUID */
+		if (!(log_dlid = build_dlid(dm, seg->log_lv->lvid.s, NULL))) {
+			log_error("Failed to build uuid for log LV %s.",
+				  seg->log_lv->name);
+			return 0;
+		}
+	} else {
+		/* If core log, use mirror's UUID and set DM_CORELOG flag */
+		if (!(log_dlid = build_dlid(dm, seg->lv->lvid.s, NULL))) {
+			log_error("Failed to build uuid for mirror LV %s.",
+				  seg->lv->name);
+			return 0;
+		}
+		log_flags |= DM_CORELOG;
+	}
+
+	if (mirror_in_sync() && !(seg->status & PVMOVE))
+		log_flags |= DM_NOSYNC;
+
+	if (_block_on_error_available && !(seg->status & PVMOVE))
+		log_flags |= DM_BLOCK_ON_ERROR;
+
+	return dm_tree_node_add_mirror_target_log(node, region_size, clustered, log_dlid, area_count, log_flags);
+}
+
+static int _mirrored_add_target_line(struct dev_manager *dm, struct dm_pool *mem,
+				struct cmd_context *cmd, void **target_state,
+				struct lv_segment *seg,
+				struct dm_tree_node *node, uint64_t len,
+				uint32_t *pvmove_mirror_count)
+{
+	struct mirror_state *mirr_state;
+	uint32_t area_count = seg->area_count;
+	unsigned start_area = 0u;
+	int mirror_status = MIRR_RUNNING;
+	uint32_t region_size, region_max;
+	int r;
+
+	if (!*target_state)
+		*target_state = _mirrored_init_target(mem, cmd);
+
+	mirr_state = *target_state;
+
+	/*
+	 * Mirror segment could have only 1 area temporarily
+	 * if the segment is under conversion.
+	 */
+ 	if (seg->area_count == 1)
+		mirror_status = MIRR_DISABLED;
+
+	/*
+	 * For pvmove, only have one mirror segment RUNNING at once.
+	 * Segments before this are COMPLETED and use 2nd area.
+	 * Segments after this are DISABLED and use 1st area.
+	 */
+	if (seg->status & PVMOVE) {
+		if (seg->extents_copied == seg->area_len) {
+			mirror_status = MIRR_COMPLETED;
+			start_area = 1;
+		} else if ((*pvmove_mirror_count)++) {
+			mirror_status = MIRR_DISABLED;
+			area_count = 1;
+		}
+		/* else MIRR_RUNNING */
+	}
+
+	if (mirror_status != MIRR_RUNNING) {
+		if (!dm_tree_node_add_linear_target(node, len))
+			return_0;
+		goto done;
+	}
+
+	if (!(seg->status & PVMOVE)) {
+		if (!seg->region_size) {
+			log_error("Missing region size for mirror segment.");
+			return 0;
+		}
+		region_size = seg->region_size;
+	} else {
+		/* Find largest power of 2 region size unit we can use */
+		region_max = (1 << (ffs((int)seg->area_len) - 1)) *
+		      seg->lv->vg->extent_size;
+
+		region_size = mirr_state->default_region_size;
+		if (region_max < region_size) {
+			region_size = region_max;
+			log_verbose("Using reduced mirror region size of %u sectors",
+				    region_size);
+		}
+	}
+
+	if (!dm_tree_node_add_mirror_target(node, len))
+		return_0;
+
+	if ((r = _add_log(dm, seg, node, area_count, region_size)) <= 0) {
+		stack;
+		return r;
+	}
+
+      done:
+	return add_areas_line(dm, seg, node, start_area, area_count);
+}
+
+static int _mirrored_target_present(const struct lv_segment *seg __attribute((unused)),
+				    unsigned *attributes)
+{
+	static int _mirrored_checked = 0;
+	static int _mirrored_present = 0;
+	uint32_t maj, min, patchlevel;
+	unsigned maj2, min2, patchlevel2;
+	char vsn[80];
+
+	if (!_mirrored_checked) {
+		_mirrored_present = target_present("mirror", 1);
+
+		/*
+		 * block_on_error available with mirror target >= 1.1 and <= 1.11
+		 * or with 1.0 in RHEL4U3 driver >= 4.5
+		 */
+		/* FIXME Move this into libdevmapper */
+
+		if (target_version("mirror", &maj, &min, &patchlevel) &&
+		    maj == 1 &&
+		    ((min >= 1 && min <= 11) ||
+		     (min == 0 && driver_version(vsn, sizeof(vsn)) &&
+		      sscanf(vsn, "%u.%u.%u", &maj2, &min2, &patchlevel2) == 3 &&
+		      maj2 == 4 && min2 == 5 && patchlevel2 == 0)))	/* RHEL4U3 */
+			_block_on_error_available = 1;
+	}
+
+	/*
+	 * Check only for modules if atttributes requested and no previous check.
+	 * FIXME: Fails incorrectly if cmirror was built into kernel.
+	 */
+	if (attributes) {
+		if (!_mirror_attributes && module_present("log-clustered"))
+			_mirror_attributes |= MIRROR_LOG_CLUSTERED;
+		*attributes = _mirror_attributes;
+	}
+	_mirrored_checked = 1;
+
+	return _mirrored_present;
+}
+
+#ifdef DMEVENTD
+static int _get_mirror_dso_path(struct cmd_context *cmd, char **dso)
+{
+	char *path;
+	const char *libpath;
+
+	if (!(path = dm_pool_alloc(cmd->mem, PATH_MAX))) {
+		log_error("Failed to allocate dmeventd library path.");
+		return 0;
+	}
+
+	libpath = find_config_tree_str(cmd, "dmeventd/mirror_library",
+				       DEFAULT_DMEVENTD_MIRROR_LIB);
+
+	get_shared_library_path(cmd, libpath, path, PATH_MAX);
+
+	*dso = path;
+
+	return 1;
+}
+
+static struct dm_event_handler *_create_dm_event_handler(const char *dmname,
+							 const char *dso,
+							 enum dm_event_mask mask)
+{
+	struct dm_event_handler *dmevh;
+
+	if (!(dmevh = dm_event_handler_create()))
+		return_0;
+
+       if (dm_event_handler_set_dso(dmevh, dso))
+		goto fail;
+
+	if (dm_event_handler_set_dev_name(dmevh, dmname))
+		goto fail;
+
+	dm_event_handler_set_event_mask(dmevh, mask);
+	return dmevh;
+
+fail:
+	dm_event_handler_destroy(dmevh);
+	return NULL;
+}
+
+static int _target_monitored(struct lv_segment *seg, int *pending)
+{
+	char *dso, *name;
+	struct logical_volume *lv;
+	struct volume_group *vg;
+	enum dm_event_mask evmask = 0;
+	struct dm_event_handler *dmevh;
+
+	lv = seg->lv;
+	vg = lv->vg;
+
+	*pending = 0;
+	if (!_get_mirror_dso_path(vg->cmd, &dso))
+		return_0;
+
+	if (!(name = build_dm_name(vg->cmd->mem, vg->name, lv->name, NULL)))
+		return_0;
+
+	if (!(dmevh = _create_dm_event_handler(name, dso, DM_EVENT_ALL_ERRORS)))
+		return_0;
+
+	if (dm_event_get_registered_device(dmevh, 0)) {
+		dm_event_handler_destroy(dmevh);
+		return 0;
+	}
+
+	evmask = dm_event_handler_get_event_mask(dmevh);
+	if (evmask & DM_EVENT_REGISTRATION_PENDING) {
+		*pending = 1;
+		evmask &= ~DM_EVENT_REGISTRATION_PENDING;
+	}
+
+	dm_event_handler_destroy(dmevh);
+
+	return evmask;
+}
+
+/* FIXME This gets run while suspended and performs banned operations. */
+static int _target_set_events(struct lv_segment *seg,
+			      int evmask __attribute((unused)), int set)
+{
+	char *dso, *name;
+	struct logical_volume *lv;
+	struct volume_group *vg;
+	struct dm_event_handler *dmevh;
+	int r;
+
+	lv = seg->lv;
+	vg = lv->vg;
+
+	if (!_get_mirror_dso_path(vg->cmd, &dso))
+		return_0;
+
+	if (!(name = build_dm_name(vg->cmd->mem, vg->name, lv->name, NULL)))
+		return_0;
+
+	if (!(dmevh = _create_dm_event_handler(name, dso, DM_EVENT_ALL_ERRORS)))
+		return_0;
+
+	r = set ? dm_event_register_handler(dmevh) : dm_event_unregister_handler(dmevh);
+	dm_event_handler_destroy(dmevh);
+	if (!r)
+		return_0;
+
+	log_info("%s %s for events", set ? "Monitored" : "Unmonitored", name);
+
+	return 1;
+}
+
+static int _target_monitor_events(struct lv_segment *seg, int events)
+{
+	return _target_set_events(seg, events, 1);
+}
+
+static int _target_unmonitor_events(struct lv_segment *seg, int events)
+{
+	return _target_set_events(seg, events, 0);
+}
+
+#endif /* DMEVENTD */
+#endif /* DEVMAPPER_SUPPORT */
+
+static int _mirrored_modules_needed(struct dm_pool *mem,
+				    const struct lv_segment *seg,
+				    struct dm_list *modules)
+{
+	if (seg->log_lv &&
+	    !list_segment_modules(mem, first_seg(seg->log_lv), modules))
+		return_0;
+
+	if (vg_is_clustered(seg->lv->vg) &&
+	    !str_list_add(mem, modules, "clog")) {
+		log_error("cluster log string list allocation failed");
+		return 0;
+	}
+
+	if (!str_list_add(mem, modules, "mirror")) {
+		log_error("mirror string list allocation failed");
+		return 0;
+	}
+
+	return 1;
+}
+
+static void _mirrored_destroy(const struct segment_type *segtype)
+{
+	dm_free((void *) segtype);
+}
+
+static struct segtype_handler _mirrored_ops = {
+	.name = _mirrored_name,
+	.display = _mirrored_display,
+	.text_import_area_count = _mirrored_text_import_area_count,
+	.text_import = _mirrored_text_import,
+	.text_export = _mirrored_text_export,
+#ifdef DEVMAPPER_SUPPORT
+	.add_target_line = _mirrored_add_target_line,
+	.target_percent = _mirrored_target_percent,
+	.target_present = _mirrored_target_present,
+#ifdef DMEVENTD
+	.target_monitored = _target_monitored,
+	.target_monitor_events = _target_monitor_events,
+	.target_unmonitor_events = _target_unmonitor_events,
+#endif
+#endif
+	.modules_needed = _mirrored_modules_needed,
+	.destroy = _mirrored_destroy,
+};
+
+#ifdef MIRRORED_INTERNAL
+struct segment_type *init_mirrored_segtype(struct cmd_context *cmd)
+#else				/* Shared */
+struct segment_type *init_segtype(struct cmd_context *cmd);
+struct segment_type *init_segtype(struct cmd_context *cmd)
+#endif
+{
+	struct segment_type *segtype = dm_malloc(sizeof(*segtype));
+
+	if (!segtype)
+		return_NULL;
+
+	segtype->cmd = cmd;
+	segtype->ops = &_mirrored_ops;
+	segtype->name = "mirror";
+	segtype->private = NULL;
+	segtype->flags = SEG_AREAS_MIRRORED | SEG_MONITORED;
+
+	log_very_verbose("Initialised segtype: %s", segtype->name);
+
+	return segtype;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/misc/configure.h.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/misc/configure.h.in
diff -N src/external/gpl2/lvm2tools/dist/lib/misc/configure.h.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/misc/configure.h.in	12 Dec 2008 16:33:00 -0000	1.1.1.1.2.1
@@ -0,0 +1,445 @@
+/* lib/misc/configure.h.in.  Generated from configure.in by autoheader.  */
+
+/* Define to 1 if the `closedir' function returns void instead of `int'. */
+#undef CLOSEDIR_VOID
+
+/* Define to 1 to include built-in support for clustered LVM locking. */
+#undef CLUSTER_LOCKING_INTERNAL
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+#undef CRAY_STACKSEG_END
+
+/* Define to 1 if using `alloca.c'. */
+#undef C_ALLOCA
+
+/* Define to 1 to enable LVM2 device-mapper interaction. */
+#undef DEVMAPPER_SUPPORT
+
+/* Define to 1 to enable the device-mapper event daemon. */
+#undef DMEVENTD
+
+/* Path to dmeventd binary. */
+#undef DMEVENTD_PATH
+
+/* Path to dmeventd pidfile. */
+#undef DMEVENTD_PIDFILE
+
+/* Library version */
+#undef DM_LIB_VERSION
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#undef HAVE_ALLOCA
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+#undef HAVE_ALLOCA_H
+
+/* Define to 1 if you have the <asm/byteorder.h> header file. */
+#undef HAVE_ASM_BYTEORDER_H
+
+/* Define to 1 if you have the <assert.h> header file. */
+#undef HAVE_ASSERT_H
+
+/* Define to 1 if canonicalize_file_name is available. */
+#undef HAVE_CANONICALIZE_FILE_NAME
+
+/* Define to 1 if you have the <ctype.h> header file. */
+#undef HAVE_CTYPE_H
+
+/* Define to 1 if you have the <dirent.h> header file. */
+#undef HAVE_DIRENT_H
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+#undef HAVE_DOPRNT
+
+/* Define to 1 if you have the `dup2' function. */
+#undef HAVE_DUP2
+
+/* Define to 1 if you have the <errno.h> header file. */
+#undef HAVE_ERRNO_H
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the `fork' function. */
+#undef HAVE_FORK
+
+/* Define to 1 if you have the `gethostname' function. */
+#undef HAVE_GETHOSTNAME
+
+/* Define to 1 if getline is available. */
+#undef HAVE_GETLINE
+
+/* Define to 1 if you have the `getmntent' function. */
+#undef HAVE_GETMNTENT
+
+/* Define to 1 if getopt_long is available. */
+#undef HAVE_GETOPTLONG
+
+/* Define to 1 if you have the <getopt.h> header file. */
+#undef HAVE_GETOPT_H
+
+/* Define to 1 if you have the `getpagesize' function. */
+#undef HAVE_GETPAGESIZE
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if dynamic libraries are available. */
+#undef HAVE_LIBDL
+
+/* Define to 1 if you have the <libgen.h> header file. */
+#undef HAVE_LIBGEN_H
+
+/* Define to 1 if you have the <libintl.h> header file. */
+#undef HAVE_LIBINTL_H
+
+/* Define to 1 if you have the `readline' library (-lreadline). */
+#undef HAVE_LIBREADLINE
+
+/* Define to 1 if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define to 1 if you have the <linux/fs.h> header file. */
+#undef HAVE_LINUX_FS_H
+
+/* Define to 1 if you have the <locale.h> header file. */
+#undef HAVE_LOCALE_H
+
+/* Define to 1 if `lstat' has the bug that it succeeds when given the
+   zero-length file name argument. */
+#undef HAVE_LSTAT_EMPTY_STRING_BUG
+
+/* Define to 1 if you have the <machine/endian.h> header file. */
+#undef HAVE_MACHINE_ENDIAN_H
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+   to 0 otherwise. */
+#undef HAVE_MALLOC
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
+/* Define to 1 if you have the `memmove' function. */
+#undef HAVE_MEMMOVE
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `memset' function. */
+#undef HAVE_MEMSET
+
+/* Define to 1 if you have the `mkdir' function. */
+#undef HAVE_MKDIR
+
+/* Define to 1 if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* Define to 1 if you have the <mntent.h> header file. */
+#undef HAVE_MNTENT_H
+
+/* Define to 1 if you have the `munmap' function. */
+#undef HAVE_MUNMAP
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+#undef HAVE_NDIR_H
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#undef HAVE_NETINET_IN_H
+
+/* Define to 1 if you have the <pthread.h> header file. */
+#undef HAVE_PTHREAD_H
+
+/* Define to 1 if you have the <readline/history.h> header file. */
+#undef HAVE_READLINE_HISTORY_H
+
+/* Define to 1 if you have the <readline/readline.h> header file. */
+#undef HAVE_READLINE_READLINE_H
+
+/* Define to 1 to include support for realtime clock. */
+#undef HAVE_REALTIME
+
+/* Define to 1 if you have the `rl_completion_matches' function. */
+#undef HAVE_RL_COMPLETION_MATCHES
+
+/* Define to 1 if you have the `rmdir' function. */
+#undef HAVE_RMDIR
+
+/* Define to 1 if you have the <search.h> header file. */
+#undef HAVE_SEARCH_H
+
+/* Define to 1 if you have the `select' function. */
+#undef HAVE_SELECT
+
+/* Define to 1 to include support for selinux. */
+#undef HAVE_SELINUX
+
+/* Define to 1 if you have the <selinux/selinux.h> header file. */
+#undef HAVE_SELINUX_SELINUX_H
+
+/* Define to 1 if sepol_check_context is available. */
+#undef HAVE_SEPOL
+
+/* Define to 1 if you have the `setlocale' function. */
+#undef HAVE_SETLOCALE
+
+/* Define to 1 if you have the <signal.h> header file. */
+#undef HAVE_SIGNAL_H
+
+/* Define to 1 if you have the `socket' function. */
+#undef HAVE_SOCKET
+
+/* Define to 1 if `stat' has the bug that it succeeds when given the
+   zero-length file name argument. */
+#undef HAVE_STAT_EMPTY_STRING_BUG
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#undef HAVE_STDARG_H
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#undef HAVE_STDDEF_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#undef HAVE_STRCASECMP
+
+/* Define to 1 if you have the `strchr' function. */
+#undef HAVE_STRCHR
+
+/* Define to 1 if you have the `strdup' function. */
+#undef HAVE_STRDUP
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strncasecmp' function. */
+#undef HAVE_STRNCASECMP
+
+/* Define to 1 if you have the `strrchr' function. */
+#undef HAVE_STRRCHR
+
+/* Define to 1 if you have the `strstr' function. */
+#undef HAVE_STRSTR
+
+/* Define to 1 if you have the `strtol' function. */
+#undef HAVE_STRTOL
+
+/* Define to 1 if you have the `strtoul' function. */
+#undef HAVE_STRTOUL
+
+/* Define to 1 if `st_rdev' is member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_RDEV
+
+/* Define to 1 if you have the <syslog.h> header file. */
+#undef HAVE_SYSLOG_H
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+   */
+#undef HAVE_SYS_DIR_H
+
+/* Define to 1 if you have the <sys/disk.h> header file. */
+#undef HAVE_SYS_DISK_H
+
+/* Define to 1 if you have the <sys/file.h> header file. */
+#undef HAVE_SYS_FILE_H
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_H
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#undef HAVE_SYS_MMAN_H
+
+/* Define to 1 if you have the <sys/mount.h> header file. */
+#undef HAVE_SYS_MOUNT_H
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+   */
+#undef HAVE_SYS_NDIR_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#undef HAVE_SYS_RESOURCE_H
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/statvfs.h> header file. */
+#undef HAVE_SYS_STATVFS_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
+#undef HAVE_SYS_UIO_H
+
+/* Define to 1 if you have the <sys/un.h> header file. */
+#undef HAVE_SYS_UN_H
+
+/* Define to 1 if you have the <sys/utsname.h> header file. */
+#undef HAVE_SYS_UTSNAME_H
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#undef HAVE_SYS_WAIT_H
+
+/* Define to 1 if you have the <termios.h> header file. */
+#undef HAVE_TERMIOS_H
+
+/* Define to 1 if you have the <time.h> header file. */
+#undef HAVE_TIME_H
+
+/* Define to 1 if you have the `uname' function. */
+#undef HAVE_UNAME
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the <utmpx.h> header file. */
+#undef HAVE_UTMPX_H
+
+/* Define to 1 if you have the `vfork' function. */
+#undef HAVE_VFORK
+
+/* Define to 1 if you have the <vfork.h> header file. */
+#undef HAVE_VFORK_H
+
+/* Define to 1 if you have the `vprintf' function. */
+#undef HAVE_VPRINTF
+
+/* Define to 1 if `fork' works. */
+#undef HAVE_WORKING_FORK
+
+/* Define to 1 if `vfork' works. */
+#undef HAVE_WORKING_VFORK
+
+/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
+   slash. */
+#undef LSTAT_FOLLOWS_SLASHED_SYMLINK
+
+/* Define to 1 if 'lvm' should fall back to using LVM1 binaries if
+   device-mapper is missing from the kernel */
+#undef LVM1_FALLBACK
+
+/* Define to 1 to include built-in support for LVM1 metadata. */
+#undef LVM1_INTERNAL
+
+/* Define to 1 to include built-in support for mirrors. */
+#undef MIRRORED_INTERNAL
+
+/* The path to 'modprobe', if available. */
+#undef MODPROBE_CMD
+
+/* Define to 1 to enable O_DIRECT support. */
+#undef O_DIRECT_SUPPORT
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 to include built-in support for GFS pool metadata. */
+#undef POOL_INTERNAL
+
+/* Define to 1 to include the LVM readline shell. */
+#undef READLINE_SUPPORT
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#undef RETSIGTYPE
+
+/* Define to the type of arg 1 for `select'. */
+#undef SELECT_TYPE_ARG1
+
+/* Define to the type of args 2, 3 and 4 for `select'. */
+#undef SELECT_TYPE_ARG234
+
+/* Define to the type of arg 5 for `select'. */
+#undef SELECT_TYPE_ARG5
+
+/* Define to 1 to include built-in support for snapshots. */
+#undef SNAPSHOT_INTERNAL
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at runtime.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown */
+#undef STACK_DIRECTION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+#undef TM_IN_SYS_TIME
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to rpl_malloc if the replacement function should be used. */
+#undef malloc
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef mode_t
+
+/* Define to `long int' if <sys/types.h> does not define. */
+#undef off_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef pid_t
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define as `fork' if `vfork' does not work. */
+#undef vfork
Index: src/external/gpl2/lvm2tools/dist/lib/misc/crc.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/misc/crc.c
diff -N src/external/gpl2/lvm2tools/dist/lib/misc/crc.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/misc/crc.c	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,40 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+
+#include "crc.h"
+
+/* Calculate an endian-independent CRC of supplied buffer */
+uint32_t calc_crc(uint32_t initial, const void *buf, uint32_t size)
+{
+	static const uint32_t crctab[] = {
+		0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
+		0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
+		0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
+		0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
+	};
+	uint32_t i, crc = initial;
+	const uint8_t *data = (const uint8_t *) buf;
+
+	for (i = 0; i < size; i++) {
+		crc ^= *data++;
+		crc = (crc >> 4) ^ crctab[crc & 0xf];
+		crc = (crc >> 4) ^ crctab[crc & 0xf];
+	}
+	return crc;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/misc/crc.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/misc/crc.h
diff -N src/external/gpl2/lvm2tools/dist/lib/misc/crc.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/misc/crc.h	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,25 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_CRC_H
+#define _LVM_CRC_H
+
+#define INITIAL_CRC 0xf597a6cf
+
+uint32_t calc_crc(uint32_t initial, const void *buf, uint32_t size);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/misc/intl.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/misc/intl.h
diff -N src/external/gpl2/lvm2tools/dist/lib/misc/intl.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/misc/intl.h	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,28 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_INTL_H
+#define _LVM_INTL_H
+
+#ifdef INTL_PACKAGE
+#  include <libintl.h>
+#  define _(String) dgettext(INTL_PACKAGE, (String))
+#else
+#  define _(String) (String)
+#endif
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/misc/last-path-component.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/misc/last-path-component.h
diff -N src/external/gpl2/lvm2tools/dist/lib/misc/last-path-component.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/misc/last-path-component.h	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,30 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Return the address of the last file name component of NAME.
+ * If NAME ends in a slash, return the empty string.
+ */
+
+#include <string.h>
+
+static inline char *last_path_component(char const *name)
+{
+	char const *slash = strrchr(name, '/');
+	char const *res = slash ? slash + 1 : name;
+
+	return (char *)res;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/misc/lib.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/misc/lib.h
diff -N src/external/gpl2/lvm2tools/dist/lib/misc/lib.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/misc/lib.h	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,50 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * This file must be included first by every library source file.
+ */
+#ifndef _LVM_LIB_H
+#define _LVM_LIB_H
+
+#include "configure.h"
+
+#define _REENTRANT
+#define _GNU_SOURCE
+#define _FILE_OFFSET_BITS 64
+
+#include "intl.h"
+#include "libdevmapper.h"
+#include "lvm-globals.h"
+#include "lvm-wrappers.h"
+#include "lvm-types.h"
+#include "util.h"
+
+#ifdef DM
+#  include "dm-logging.h"
+#else
+#  include "lvm-logging.h"
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/misc/lvm-exec.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/misc/lvm-exec.c
diff -N src/external/gpl2/lvm2tools/dist/lib/misc/lvm-exec.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/misc/lvm-exec.c	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,66 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "lvm-exec.h"
+
+#include <unistd.h>
+#include <sys/wait.h>
+
+/*
+ * Execute and wait for external command
+ */
+int exec_cmd(const char *command, const char *fscmd, const char *lv_path,
+	     const char *size)
+{
+	pid_t pid;
+	int status;
+
+	log_verbose("Executing: %s %s %s %s", command, fscmd, lv_path, size);
+
+	if ((pid = fork()) == -1) {
+		log_error("fork failed: %s", strerror(errno));
+		return 0;
+	}
+
+	if (!pid) {
+		/* Child */
+		/* FIXME Use execve directly */
+		execlp(command, command, fscmd, lv_path, size, NULL);
+		log_sys_error("execlp", command);
+		exit(errno);
+	}
+
+	/* Parent */
+	if (wait4(pid, &status, 0, NULL) != pid) {
+		log_error("wait4 child process %u failed: %s", pid,
+			  strerror(errno));
+		return 0;
+	}
+
+	if (!WIFEXITED(status)) {
+		log_error("Child %u exited abnormally", pid);
+		return 0;
+	}
+
+	if (WEXITSTATUS(status)) {
+		log_error("%s failed: %u", command, WEXITSTATUS(status));
+		return 0;
+	}
+
+	return 1;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/misc/lvm-exec.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/misc/lvm-exec.h
diff -N src/external/gpl2/lvm2tools/dist/lib/misc/lvm-exec.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/misc/lvm-exec.h	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,25 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_EXEC_H
+#define _LVM_EXEC_H
+
+#include "lib.h"
+
+int exec_cmd(const char *command, const char *fscmd, const char *lv_path,
+	     const char *size);
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/misc/lvm-file.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/misc/lvm-file.c
diff -N src/external/gpl2/lvm2tools/dist/lib/misc/lvm-file.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/misc/lvm-file.c	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,286 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "lvm-file.h"
+#include "lvm-string.h"
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#include <dirent.h>
+
+/*
+ * Creates a temporary filename, and opens a descriptor to the
+ * file.  Both the filename and descriptor are needed so we can
+ * rename the file after successfully writing it.  Grab
+ * NFS-supported exclusive fcntl discretionary lock.
+ */
+int create_temp_name(const char *dir, char *buffer, size_t len, int *fd)
+{
+	int i, num;
+	pid_t pid;
+	char hostname[255];
+	struct flock lock = {
+		.l_type = F_WRLCK,
+		.l_whence = 0,
+		.l_start = 0,
+		.l_len = 0
+	};
+
+	num = rand();
+	pid = getpid();
+	if (gethostname(hostname, sizeof(hostname)) < 0) {
+		log_sys_error("gethostname", "");
+		strcpy(hostname, "nohostname");
+	}
+
+	for (i = 0; i < 20; i++, num++) {
+
+		if (dm_snprintf(buffer, len, "%s/.lvm_%s_%d_%d",
+				 dir, hostname, pid, num) == -1) {
+			log_err("Not enough space to build temporary file "
+				"string.");
+			return 0;
+		}
+
+		*fd = open(buffer, O_CREAT | O_EXCL | O_WRONLY | O_APPEND,
+			   S_IRUSR | S_IRGRP | S_IROTH |
+			   S_IWUSR | S_IWGRP | S_IWOTH);
+		if (*fd < 0)
+			continue;
+
+		if (!fcntl(*fd, F_SETLK, &lock))
+			return 1;
+
+		if (close(*fd))
+			log_sys_error("close", buffer);
+	}
+
+	return 0;
+}
+
+/*
+ * NFS-safe rename of a temporary file to a common name, designed
+ * to avoid race conditions and not overwrite the destination if
+ * it exists.
+ *
+ * Try to create the new filename as a hard link to the original.
+ * Check the link count of the original file to see if it worked.
+ * (Assumes nothing else touches our temporary file!)  If it
+ * worked, unlink the old filename.
+ */
+int lvm_rename(const char *old, const char *new)
+{
+	struct stat buf;
+
+	if (link(old, new)) {
+		log_error("%s: rename to %s failed: %s", old, new,
+			  strerror(errno));
+		return 0;
+	}
+
+	if (stat(old, &buf)) {
+		log_sys_error("stat", old);
+		return 0;
+	}
+
+	if (buf.st_nlink != 2) {
+		log_error("%s: rename to %s failed", old, new);
+		return 0;
+	}
+
+	if (unlink(old)) {
+		log_sys_error("unlink", old);
+		return 0;
+	}
+
+	return 1;
+}
+
+int path_exists(const char *path)
+{
+	struct stat info;
+
+	if (!*path)
+		return 0;
+
+	if (stat(path, &info) < 0)
+		return 0;
+
+	return 1;
+}
+
+int dir_exists(const char *path)
+{
+	struct stat info;
+
+	if (!*path)
+		return 0;
+
+	if (stat(path, &info) < 0)
+		return 0;
+
+	if (!S_ISDIR(info.st_mode))
+		return 0;
+
+	return 1;
+}
+
+int is_empty_dir(const char *dir)
+{
+	struct dirent *dirent;
+	DIR *d;
+
+	if (!(d = opendir(dir))) {
+		log_sys_error("opendir", dir);
+		return 0;
+	}
+
+	while ((dirent = readdir(d)))
+		if (strcmp(dirent->d_name, ".") && strcmp(dirent->d_name, ".."))
+			break;
+
+	if (closedir(d)) {
+		log_sys_error("closedir", dir);
+	}
+
+	return dirent ? 0 : 1;
+}
+
+void sync_dir(const char *file)
+{
+	int fd;
+	char *dir, *c;
+
+	if (!(dir = dm_strdup(file))) {
+		log_error("sync_dir failed in strdup");
+		return;
+	}
+
+	if (!dir_exists(dir)) {
+		c = dir + strlen(dir);
+		while (*c != '/' && c > dir)
+			c--;
+
+		if (c == dir)
+			*c++ = '.';
+
+		*c = '\0';
+	}
+
+	if ((fd = open(dir, O_RDONLY)) == -1) {
+		log_sys_error("open", dir);
+		goto out;
+	}
+
+	if (fsync(fd) && (errno != EROFS) && (errno != EINVAL))
+		log_sys_error("fsync", dir);
+
+	if (close(fd))
+		log_sys_error("close", dir);
+
+      out:
+	dm_free(dir);
+}
+
+/*
+ * Attempt to obtain fcntl lock on a file, if necessary creating file first
+ * or waiting.
+ * Returns file descriptor on success, else -1.
+ * mode is F_WRLCK or F_RDLCK
+ */
+int fcntl_lock_file(const char *file, short lock_type, int warn_if_read_only)
+{
+	int lockfd;
+	char *dir;
+	char *c;
+	struct flock lock = {
+		.l_type = lock_type,
+		.l_whence = 0,
+		.l_start = 0,
+		.l_len = 0
+	};
+
+	if (!(dir = dm_strdup(file))) {
+		log_error("fcntl_lock_file failed in strdup.");
+		return -1;
+	}
+
+	if ((c = strrchr(dir, '/')))
+		*c = '\0';
+
+	if (!dm_create_dir(dir)) {
+		dm_free(dir);
+		return -1;
+	}
+
+	dm_free(dir);
+
+	log_very_verbose("Locking %s (%s, %hd)", file,
+			 (lock_type == F_WRLCK) ? "F_WRLCK" : "F_RDLCK",
+			 lock_type);
+	if ((lockfd = open(file, O_RDWR | O_CREAT, 0777)) < 0) {
+		/* EACCES has been reported on NFS */
+		if (warn_if_read_only || (errno != EROFS && errno != EACCES))
+			log_sys_error("open", file);
+		else
+			stack;
+
+		return -1;
+	}
+
+	if (fcntl(lockfd, F_SETLKW, &lock)) {
+		log_sys_error("fcntl", file);
+		close(lockfd);
+		return -1;
+	}
+
+	return lockfd;
+}
+
+void fcntl_unlock_file(int lockfd)
+{
+	struct flock lock = {
+		.l_type = F_UNLCK,
+		.l_whence = 0,
+		.l_start = 0,
+		.l_len = 0
+	};
+
+	log_very_verbose("Unlocking fd %d", lockfd);
+
+	if (fcntl(lockfd, F_SETLK, &lock) == -1)
+		log_error("fcntl unlock failed on fd %d: %s", lockfd,
+			  strerror(errno));
+
+	if (close(lockfd))
+		log_error("lock file close failed on fd %d: %s", lockfd,
+			  strerror(errno));
+}
+
+int lvm_fclose(FILE *fp, const char *filename)
+{
+	if (!dm_fclose(fp))
+		return 0;
+	if (errno == 0)
+		log_error("%s: write error", filename);
+	else
+		log_sys_error("write error", filename);
+	return EOF;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/misc/lvm-file.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/misc/lvm-file.h
diff -N src/external/gpl2/lvm2tools/dist/lib/misc/lvm-file.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/misc/lvm-file.h	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,64 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_FILE_H
+#define _LVM_FILE_H
+
+/*
+ * Create a temporary filename, and opens a descriptor to the file.
+ */
+int create_temp_name(const char *dir, char *buffer, size_t len, int *fd);
+
+/*
+ * NFS-safe rename of a temporary file to a common name, designed
+ * to avoid race conditions and not overwrite the destination if
+ * it exists.
+ */
+int lvm_rename(const char *old, const char *new);
+
+/*
+ * Return 1 if path exists else return 0
+ */
+int path_exists(const char *path);
+int dir_exists(const char *path);
+
+/*
+ * Return 1 if dir is empty
+ */
+int is_empty_dir(const char *dir);
+
+/* Sync directory changes */
+void sync_dir(const char *file);
+
+/* fcntl locking wrappers */
+int fcntl_lock_file(const char *file, short lock_type, int warn_if_read_only);
+void fcntl_unlock_file(int lockfd);
+
+#define is_same_inode(buf1, buf2) \
+  ((buf1).st_ino == (buf2).st_ino && \
+   (buf1).st_dev == (buf2).st_dev)
+
+/*
+ * Close the specified stream, taking care to detect and diagnose any write
+ * error.  If there is an error, use the supplied file name in a diagnostic
+ * that is reported via log_error or log_sys_error, as appropriate.
+ * Use this function to close a stream when you've written data to it via
+ * unchecked fprintf, fputc, etc. calls.  Return 0 on success, EOF on failure.
+ */
+int lvm_fclose(FILE *fp, const char *filename);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/misc/lvm-globals.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/misc/lvm-globals.c
diff -N src/external/gpl2/lvm2tools/dist/lib/misc/lvm-globals.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/misc/lvm-globals.c	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.3
@@ -0,0 +1,203 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "device.h"
+#include "memlock.h"
+#include "lvm-string.h"
+#include "lvm-file.h"
+#include "defaults.h"
+
+#include <stdarg.h>
+
+static int _verbose_level = VERBOSE_BASE_LEVEL;
+static int _test = 0;
+static int _md_filtering = 0;
+static int _pvmove = 0;
+static int _full_scan_done = 0;	/* Restrict to one full scan during each cmd */
+static int _trust_cache = 0; /* Don't scan when incomplete VGs encountered */
+static int _debug_level = 0;
+static int _log_cmd_name = 0;
+static int _ignorelockingfailure = 0;
+static int _lockingfailed = 0;
+static int _security_level = SECURITY_LEVEL;
+static char _cmd_name[30] = "";
+static int _mirror_in_sync = 0;
+static int _dmeventd_monitor = DEFAULT_DMEVENTD_MONITOR;
+static int _ignore_suspended_devices = 0;
+static int _error_message_produced = 0;
+
+void init_verbose(int level)
+{
+	_verbose_level = level;
+}
+
+void init_test(int level)
+{
+	if (!_test && level)
+		log_print("Test mode: Metadata will NOT be updated.");
+	_test = level;
+}
+
+void init_md_filtering(int level)
+{
+	_md_filtering = level;
+}
+
+void init_pvmove(int level)
+{
+	_pvmove = level;
+}
+
+void init_full_scan_done(int level)
+{
+	_full_scan_done = level;
+}
+
+void init_trust_cache(int trustcache)
+{
+	_trust_cache = trustcache;
+}
+
+void init_ignorelockingfailure(int level)
+{
+	_ignorelockingfailure = level;
+}
+
+void init_lockingfailed(int level)
+{
+	_lockingfailed = level;
+}
+
+void init_security_level(int level)
+{
+	_security_level = level;
+}
+
+void init_mirror_in_sync(int in_sync)
+{
+	_mirror_in_sync = in_sync;
+}
+
+void init_dmeventd_monitor(int reg)
+{
+	_dmeventd_monitor = reg;
+}
+
+void init_ignore_suspended_devices(int ignore)
+{
+	_ignore_suspended_devices = ignore;
+}
+
+void init_cmd_name(int status)
+{
+	_log_cmd_name = status;
+}
+
+void set_cmd_name(const char *cmd)
+{
+	strncpy(_cmd_name, cmd, sizeof(_cmd_name));
+	_cmd_name[sizeof(_cmd_name) - 1] = '\0';
+}
+
+const char *log_command_name()
+{
+	if (!_log_cmd_name)
+		return "";
+
+	return _cmd_name;
+}
+
+void init_error_message_produced(int value)
+{
+	_error_message_produced = value;
+}
+
+int error_message_produced(void)
+{
+	return _error_message_produced;
+}
+
+int test_mode()
+{
+	return _test;
+}
+
+int md_filtering()
+{
+	return _md_filtering;
+}
+
+int pvmove_mode()
+{
+	return _pvmove;
+}
+
+int full_scan_done()
+{
+	return _full_scan_done;
+}
+
+int trust_cache()
+{
+	return _trust_cache;
+}
+
+int lockingfailed()
+{
+	return _lockingfailed;
+}
+
+int ignorelockingfailure()
+{
+	return _ignorelockingfailure;
+}
+
+int security_level()
+{
+	return _security_level;
+}
+
+int mirror_in_sync(void)
+{
+	return _mirror_in_sync;
+}
+
+int dmeventd_monitor_mode(void)
+{
+	return _dmeventd_monitor;
+}
+
+int ignore_suspended_devices(void)
+{
+	return _ignore_suspended_devices;
+}
+
+void init_debug(int level)
+{
+	_debug_level = level;
+}
+
+int verbose_level()
+{
+	return _verbose_level;
+}
+
+int debug_level()
+{
+	return _debug_level;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/misc/lvm-globals.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/misc/lvm-globals.h
diff -N src/external/gpl2/lvm2tools/dist/lib/misc/lvm-globals.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/misc/lvm-globals.h	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.3
@@ -0,0 +1,61 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_GLOBALS_H
+#define _LVM_GLOBALS_H
+
+#define VERBOSE_BASE_LEVEL _LOG_WARN
+#define SECURITY_LEVEL 0
+
+void init_verbose(int level);
+void init_test(int level);
+void init_md_filtering(int level);
+void init_pvmove(int level);
+void init_full_scan_done(int level);
+void init_trust_cache(int trustcache);
+void init_debug(int level);
+void init_cmd_name(int status);
+void init_msg_prefix(const char *prefix);
+void init_indent(int indent);
+void init_ignorelockingfailure(int level);
+void init_lockingfailed(int level);
+void init_security_level(int level);
+void init_mirror_in_sync(int in_sync);
+void init_dmeventd_monitor(int reg);
+void init_ignore_suspended_devices(int ignore);
+void init_error_message_produced(int produced);
+
+void set_cmd_name(const char *cmd_name);
+
+int test_mode(void);
+int md_filtering(void);
+int pvmove_mode(void);
+int full_scan_done(void);
+int trust_cache(void);
+int verbose_level(void);
+int debug_level(void);
+int ignorelockingfailure(void);
+int lockingfailed(void);
+int security_level(void);
+int mirror_in_sync(void);
+int ignore_suspended_devices(void);
+const char *log_command_name(void);
+
+#define DMEVENTD_MONITOR_IGNORE -1
+int dmeventd_monitor_mode(void);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/misc/lvm-string.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/misc/lvm-string.c
diff -N src/external/gpl2/lvm2tools/dist/lib/misc/lvm-string.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/misc/lvm-string.c	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,225 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "lvm-string.h"
+
+#include <ctype.h>
+
+int emit_to_buffer(char **buffer, size_t *size, const char *fmt, ...)
+{
+	int n;
+	va_list ap;
+
+	va_start(ap, fmt);
+	n = vsnprintf(*buffer, *size, fmt, ap);
+	va_end(ap);
+
+	if (n < 0 || ((size_t)n == *size))
+		return 0;
+
+	*buffer += n;
+	*size -= n;
+	return 1;
+}
+
+/*
+ * Count occurences of 'c' in 'str' until we reach a null char.
+ *
+ * Returns:
+ *  len - incremented for each char we encounter.
+ *  count - number of occurrences of 'c' and 'c2'.
+ */
+static void _count_chars(const char *str, size_t *len, int *count,
+			 const int c1, const int c2)
+{
+	const char *ptr;
+
+	for (ptr = str; *ptr; ptr++, (*len)++)
+		if (*ptr == c1 || *ptr == c2)
+			(*count)++;
+}
+
+/*
+ * Count occurences of 'c' in 'str' of length 'size'.
+ *
+ * Returns:
+ *   Number of occurrences of 'c'
+ */
+unsigned count_chars(const char *str, size_t len, const int c)
+{
+	size_t i;
+	unsigned count = 0;
+
+	for (i = 0; i < len; i++)
+		if (str[i] == c)
+			count++;
+
+	return count;
+}
+
+/*
+ * Length of string after escaping double quotes and backslashes.
+ */
+size_t escaped_len(const char *str)
+{
+	size_t len = 1;
+	int count = 0;
+
+	_count_chars(str, &len, &count, '\"', '\\');
+
+	return count + len;
+}
+
+/*
+ * Copies a string, quoting orig_char with quote_char.
+ * Optionally also quote quote_char.
+ */
+static void _quote_characters(char **out, const char *src,
+			      const int orig_char, const int quote_char,
+			      int quote_quote_char)
+{
+	while (*src) {
+		if (*src == orig_char ||
+		    (*src == quote_char && quote_quote_char))
+			*(*out)++ = quote_char;
+
+		*(*out)++ = *src++;
+	}
+}
+
+/*
+ * Unquote orig_char in string.
+ * Also unquote quote_char.
+ */
+static void _unquote_characters(char *src, const int orig_char,
+				const int quote_char)
+{
+	char *out = src;
+
+	while (*src) {
+		if (*src == quote_char &&
+		    (*(src + 1) == orig_char || *(src + 1) == quote_char))
+			src++;
+
+		*out++ = *src++;
+	}
+
+	*out = '\0';
+}
+
+/*
+ * Copies a string, quoting hyphens with hyphens.
+ */
+static void _quote_hyphens(char **out, const char *src)
+{
+	return _quote_characters(out, src, '-', '-', 0);
+}
+
+/*
+ * <vg>-<lv>-<layer> or if !layer just <vg>-<lv>.
+ */
+char *build_dm_name(struct dm_pool *mem, const char *vgname,
+		    const char *lvname, const char *layer)
+{
+	size_t len = 1;
+	int hyphens = 1;
+	char *r, *out;
+
+	_count_chars(vgname, &len, &hyphens, '-', 0);
+	_count_chars(lvname, &len, &hyphens, '-', 0);
+
+	if (layer && *layer) {
+		_count_chars(layer, &len, &hyphens, '-', 0);
+		hyphens++;
+	}
+
+	len += hyphens;
+
+	if (!(r = dm_pool_alloc(mem, len))) {
+		log_error("build_dm_name: Allocation failed for %" PRIsize_t
+			  " for %s %s %s.", len, vgname, lvname, layer);
+		return NULL;
+	}
+
+	out = r;
+	_quote_hyphens(&out, vgname);
+	*out++ = '-';
+	_quote_hyphens(&out, lvname);
+
+	if (layer && *layer) {
+		/* No hyphen if the layer begins with _ e.g. _mlog */
+		if (*layer != '_')
+			*out++ = '-';
+		_quote_hyphens(&out, layer);
+	}
+	*out = '\0';
+
+	return r;
+}
+
+/*
+ * Copies a string, quoting double quotes with backslashes.
+ */
+char *escape_double_quotes(char *out, const char *src)
+{
+	char *buf = out;
+
+	_quote_characters(&buf, src, '\"', '\\', 1);
+	*buf = '\0';
+
+	return out;
+}
+
+/*
+ * Undo quoting in situ.
+ */
+void unescape_double_quotes(char *src)
+{
+	_unquote_characters(src, '\"', '\\');
+}
+
+/*
+ * Device layer names are all of the form <vg>-<lv>-<layer>, any
+ * other hyphens that appear in these names are quoted with yet
+ * another hyphen.  The top layer of any device has no layer
+ * name.  eg, vg0-lvol0.
+ */
+int validate_name(const char *n)
+{
+	register char c;
+	register int len = 0;
+
+	if (!n || !*n)
+		return 0;
+
+	/* Hyphen used as VG-LV separator - ambiguity if LV starts with it */
+	if (*n == '-')
+		return 0;
+
+	if (!strcmp(n, ".") || !strcmp(n, ".."))
+		return 0;
+
+	while ((len++, c = *n++))
+		if (!isalnum(c) && c != '.' && c != '_' && c != '-' && c != '+')
+			return 0;
+
+	if (len > NAME_LEN)
+		return 0;
+
+	return 1;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/misc/lvm-string.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/misc/lvm-string.h
diff -N src/external/gpl2/lvm2tools/dist/lib/misc/lvm-string.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/misc/lvm-string.h	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,59 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_STRING_H
+#define _LVM_STRING_H
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#define NAME_LEN 128
+
+struct pool;
+
+int emit_to_buffer(char **buffer, size_t *size, const char *fmt, ...)
+  __attribute__ ((format(printf, 3, 4)));
+
+char *build_dm_name(struct dm_pool *mem, const char *vg,
+                    const char *lv, const char *layer);
+
+int validate_name(const char *n);
+
+/*
+ * Returns number of occurrences of c in first len characters of str.
+ */
+unsigned count_chars(const char *str, size_t len, const int c);
+
+/*
+ * Returns what length of escaped string would be including terminating NUL.
+ */
+size_t escaped_len(const char *str);
+
+/*
+ * Copies a string from src to out. 
+ * Double quotation marks and backslashes are quoted with a backslash.
+ * Caller must ensure *out has enough space - see escaped_len().
+ * Returns *out.
+ */
+char *escape_double_quotes(char *out, const char *src);
+
+/*
+ * Removes quoting of double quotation marks and backslashes in situ.
+ */
+void unescape_double_quotes(char *src);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/misc/lvm-wrappers.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/misc/lvm-wrappers.c
diff -N src/external/gpl2/lvm2tools/dist/lib/misc/lvm-wrappers.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/misc/lvm-wrappers.c	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,24 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+
+#include <unistd.h>
+
+int lvm_getpagesize(void)
+{
+	return getpagesize();
+}
Index: src/external/gpl2/lvm2tools/dist/lib/misc/lvm-wrappers.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/misc/lvm-wrappers.h
diff -N src/external/gpl2/lvm2tools/dist/lib/misc/lvm-wrappers.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/misc/lvm-wrappers.h	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,23 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_WRAPPERS_H
+#define _LVM_WRAPPERS_H
+
+int lvm_getpagesize(void);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/misc/sharedlib.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/misc/sharedlib.c
diff -N src/external/gpl2/lvm2tools/dist/lib/misc/sharedlib.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/misc/sharedlib.c	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,69 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "config.h"
+#include "lvm-string.h"
+#include "sharedlib.h"
+#include "toolcontext.h"
+
+#include <limits.h>
+#include <sys/stat.h>
+#include <dlfcn.h>
+
+void get_shared_library_path(struct cmd_context *cmd, const char *libname,
+			     char *path, size_t path_len)
+{
+	struct stat info;
+	const char *lib_dir;
+
+	/* If libname doesn't begin with '/' then use lib_dir/libname,
+	 * if present */
+	if (libname[0] == '/' ||
+	    !(lib_dir = find_config_tree_str(cmd, "global/library_dir", 0)) ||
+	    (dm_snprintf(path, path_len, "%s/%s", lib_dir,
+			  libname) == -1) || stat(path, &info) == -1)
+		strncpy(path, libname, path_len);
+}
+
+void *load_shared_library(struct cmd_context *cmd, const char *libname,
+			  const char *desc, int silent)
+{
+	char path[PATH_MAX];
+	void *library;
+
+	if (cmd->is_static) {
+		log_error("Not loading shared %s library %s in static mode.",
+			  desc, libname);
+		return NULL;
+	}
+
+	get_shared_library_path(cmd, libname, path, sizeof(path));
+
+	log_very_verbose("Opening shared %s library %s", desc, path);
+
+	if (!(library = dlopen(path, RTLD_LAZY | RTLD_GLOBAL))) {
+		if (silent && ignorelockingfailure())
+			log_verbose("Unable to open external %s library %s: %s",
+				    desc, path, dlerror());
+		else
+			log_error("Unable to open external %s library %s: %s",
+				  desc, path, dlerror());
+	}
+
+	return library;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/misc/sharedlib.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/misc/sharedlib.h
diff -N src/external/gpl2/lvm2tools/dist/lib/misc/sharedlib.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/misc/sharedlib.h	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,29 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_SHAREDLIB_H
+#define _LVM_SHAREDLIB_H
+
+#include "config.h"
+#include <dlfcn.h>
+
+void get_shared_library_path(struct cmd_context *cmd, const char *libname,
+			     char *path, size_t path_len);
+void *load_shared_library(struct cmd_context *cmd, const char *libname,
+			  const char *what, int silent);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/misc/timestamp.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/misc/timestamp.c
diff -N src/external/gpl2/lvm2tools/dist/lib/misc/timestamp.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/misc/timestamp.c	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,132 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2006 Rackable Systems All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Abstract out the time methods used so they can be adjusted later -
+ * the results of these routines should stay in-core.  This implementation
+ * requires librt.
+ */
+
+#include "lib.h"
+#include <stdlib.h>
+
+#include "timestamp.h"
+
+/*
+ * The realtime section uses clock_gettime with the CLOCK_MONOTONIC
+ * parameter to prevent issues with time warps
+ */
+#ifdef HAVE_REALTIME
+
+#include <time.h>
+#include <bits/time.h>
+
+struct timestamp {
+	struct timespec t;
+};
+
+struct timestamp *get_timestamp(void)
+{
+	struct timestamp *ts = NULL;
+
+	if (!(ts = dm_malloc(sizeof(*ts))))
+		return_NULL;
+
+	if (clock_gettime(CLOCK_MONOTONIC, &ts->t)) {
+		log_sys_error("clock_gettime", "get_timestamp");
+		return NULL;
+	}
+
+	return ts;
+}
+
+/* cmp_timestamp: Compare two timestamps
+ *
+ * Return: -1 if t1 is less than t2
+ *          0 if t1 is equal to t2
+ *          1 if t1 is greater than t2
+ */
+int cmp_timestamp(struct timestamp *t1, struct timestamp *t2)
+{
+	if(t1->t.tv_sec < t2->t.tv_sec)
+		return -1;
+	if(t1->t.tv_sec > t2->t.tv_sec)
+		return 1;
+
+	if(t1->t.tv_nsec < t2->t.tv_nsec)
+		return -1;
+	if(t1->t.tv_nsec > t2->t.tv_nsec)
+		return 1;
+
+	return 0;
+}
+
+#else /* ! HAVE_REALTIME */
+
+/*
+ * The !realtime section just uses gettimeofday and is therefore subject
+ * to ntp-type time warps - not sure if should allow that.
+ */
+
+#include <sys/time.h>
+
+struct timestamp {
+	struct timeval t;
+};
+
+struct timestamp *get_timestamp(void)
+{
+	struct timestamp *ts = NULL;
+
+	if (!(ts = dm_malloc(sizeof(*ts))))
+		return_NULL;
+
+	if (gettimeofday(&ts->t, NULL)) {
+		log_sys_error("gettimeofday", "get_timestamp");
+		return NULL;
+	}
+
+	return ts;
+}
+
+/* cmp_timestamp: Compare two timestamps
+ *
+ * Return: -1 if t1 is less than t2
+ *          0 if t1 is equal to t2
+ *          1 if t1 is greater than t2
+ */
+int cmp_timestamp(struct timestamp *t1, struct timestamp *t2)
+{
+	if(t1->t.tv_sec < t2->t.tv_sec)
+		return -1;
+	if(t1->t.tv_sec > t2->t.tv_sec)
+		return 1;
+
+	if(t1->t.tv_usec < t2->t.tv_usec)
+		return -1;
+	if(t1->t.tv_usec > t2->t.tv_usec)
+		return 1;
+
+	return 0;
+}
+
+#endif /* HAVE_REALTIME */
+
+void destroy_timestamp(struct timestamp *t)
+{
+	if (t)
+		dm_free(t);
+}
Index: src/external/gpl2/lvm2tools/dist/lib/misc/timestamp.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/misc/timestamp.h
diff -N src/external/gpl2/lvm2tools/dist/lib/misc/timestamp.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/misc/timestamp.h	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,35 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2006 Rackable Systems All rights reserved.  
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_TIMESTAMP_H
+#define _LVM_TIMESTAMP_H
+
+struct timestamp;
+
+struct timestamp *get_timestamp(void);
+
+/* cmp_timestamp: Compare two timestamps
+ * 
+ * Return: -1 if t1 is less than t2
+ *  	    0 if t1 is equal to t2
+ *          1 if t1 is greater than t2
+ */
+int cmp_timestamp(struct timestamp *t1, struct timestamp *t2);
+
+void destroy_timestamp(struct timestamp *t);
+
+#endif /* _LVM_TIMESTAMP_H */
+
Index: src/external/gpl2/lvm2tools/dist/lib/misc/util.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/misc/util.c
diff -N src/external/gpl2/lvm2tools/dist/lib/misc/util.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/misc/util.c	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,24 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Return the address of the last file name component of NAME.
+ * If NAME ends in a slash, return the empty string.
+ */
+
+#include "lib.h"
+
+/* empty for now.  */
Index: src/external/gpl2/lvm2tools/dist/lib/misc/util.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/misc/util.h
diff -N src/external/gpl2/lvm2tools/dist/lib/misc/util.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/misc/util.h	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,32 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_UTIL_H
+#define _LVM_UTIL_H
+
+#define min(a, b) ({ typeof(a) _a = (a); \
+		     typeof(b) _b = (b); \
+		     (void) (&_a == &_b); \
+		     _a < _b ? _a : _b; })
+
+#define max(a, b) ({ typeof(a) _a = (a); \
+		     typeof(b) _b = (b); \
+		     (void) (&_a == &_b); \
+		     _a > _b ? _a : _b; })
+
+#define uninitialized_var(x) x = x
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/mm/memlock.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/mm/memlock.c
diff -N src/external/gpl2/lvm2tools/dist/lib/mm/memlock.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/mm/memlock.c	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,160 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "memlock.h"
+#include "defaults.h"
+#include "config.h"
+#include "toolcontext.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;
+}
+void memlock_init(struct cmd_context *cmd)
+{
+	return;
+}
+
+#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 = lvm_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_mem(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 %d failed: %s",
+				  _default_priority, strerror(errno));
+}
+
+static void _unlock_mem(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_mem();
+	log_debug("memlock_count inc to %d", _memlock_count);
+}
+
+void memlock_dec(void)
+{
+	if (_memlock_count && (!--_memlock_count))
+		_unlock_mem();
+	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_tree_int(cmd,
+				      "activation/reserved_stack",
+				      DEFAULT_RESERVED_STACK) * 1024;
+	_size_malloc_tmp = find_config_tree_int(cmd,
+					   "activation/reserved_memory",
+					   DEFAULT_RESERVED_MEMORY) * 1024;
+	_default_priority = find_config_tree_int(cmd,
+					    "activation/process_priority",
+					    DEFAULT_PROCESS_PRIORITY);
+}
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/mm/memlock.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/mm/memlock.h
diff -N src/external/gpl2/lvm2tools/dist/lib/mm/memlock.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/mm/memlock.h	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,28 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef LVM_MEMLOCK_H
+#define LVM_MEMLOCK_H
+
+struct cmd_context;
+
+void memlock_inc(void);
+void memlock_dec(void);
+int memlock(void);
+void memlock_init(struct cmd_context *cmd);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/mm/xlate.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/mm/xlate.h
diff -N src/external/gpl2/lvm2tools/dist/lib/mm/xlate.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/mm/xlate.h	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,66 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_XLATE_H
+#define _LVM_XLATE_H
+
+#ifdef linux
+#  include <endian.h>
+#  include <byteswap.h>
+#else
+#  include <machine/endian.h>
+#  define bswap_16(x) (((x) & 0x00ffU) << 8 | \
+		       ((x) & 0xff00U) >> 8)
+#  define bswap_32(x) (((x) & 0x000000ffU) << 24 | \
+		       ((x) & 0xff000000U) >> 24 | \
+		       ((x) & 0x0000ff00U) << 8  | \
+		       ((x) & 0x00ff0000U) >> 8)
+#  define bswap_64(x) (((x) & 0x00000000000000ffULL) << 56 | \
+		       ((x) & 0xff00000000000000ULL) >> 56 | \
+		       ((x) & 0x000000000000ff00ULL) << 40 | \
+		       ((x) & 0x00ff000000000000ULL) >> 40 | \
+		       ((x) & 0x0000000000ff0000ULL) << 24 | \
+		       ((x) & 0x0000ff0000000000ULL) >> 24 | \
+		       ((x) & 0x00000000ff000000ULL) << 8 | \
+		       ((x) & 0x000000ff00000000ULL) >> 8)
+#endif
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#  define xlate16(x) (x)
+#  define xlate32(x) (x)
+#  define xlate64(x) (x)
+#  define xlate16_be(x) bswap_16(x)
+#  define xlate32_be(x) bswap_32(x)
+#  define xlate64_be(x) bswap_64(x)
+#elif BYTE_ORDER == BIG_ENDIAN
+#  define xlate16(x) bswap_16(x)
+#  define xlate32(x) bswap_32(x)
+#  define xlate64(x) bswap_64(x)
+#  define xlate16_be(x) (x)
+#  define xlate32_be(x) (x)
+#  define xlate64_be(x) (x)
+#else
+#  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))
+#  define xlate16_be(x) __cpu_to_be16((x))
+#  define xlate32_be(x) __cpu_to_be32((x))
+#  define xlate64_be(x) __cpu_to_be64((x))
+#endif
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/netbsd/dev.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/netbsd/dev.c
diff -N src/external/gpl2/lvm2tools/dist/lib/netbsd/dev.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/netbsd/dev.c	15 Jul 2008 21:40:05 -0000	1.1.2.2
@@ -0,0 +1,70 @@
+/*
+ * NetBSD specific device routines are added to this file.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <sys/sysctl.h>
+
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <limits.h>
+
+#include "netbsd.h"
+
+#define LVM_FAILURE -1
+
+/*
+ * Find major numbers for char/block parts of all block devices.
+ * In NetBSD every block device has it's char counter part.
+ * Return success only for device drivers with defined char/block
+ * major numbers.
+ */
+int
+nbsd_check_dev(int major, const char *path)
+{
+
+	size_t val_len,i;
+
+	struct kinfo_drivers *kd;
+
+	/* XXX HACK */	
+	if (strcmp(path,"/dev/console") == 0)
+		return LVM_FAILURE;
+	
+	/* get size kernel drivers array from kernel*/
+	if (sysctlbyname("kern.drivers",NULL,&val_len,NULL,0) < 0) {
+		printf("sysctlbyname failed");
+		return LVM_FAILURE;
+	}
+	
+	if ((kd = malloc (val_len)) == NULL){
+		printf("malloc kd info error\n");
+		return LVM_FAILURE;
+	}
+	
+	/* get array from kernel */
+	if (sysctlbyname("kern.drivers", kd, &val_len, NULL, 0) < 0) {
+		printf("sysctlbyname failed kd");
+		return LVM_FAILURE;
+	}
+
+	for (i = 0, val_len /= sizeof(*kd); i < val_len; i++)
+		/* We select only devices with correct char/block major number. */
+		if (kd[i].d_cmajor != -1 && kd[i].d_bmajor != -1) {
+			
+			if (kd[i].d_cmajor == major)
+				return kd[i].d_bmajor;
+			
+			if (kd[i].d_bmajor == major)
+				return kd[i].d_cmajor;
+			
+		}
+	
+	return LVM_FAILURE;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/netbsd/netbsd.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/netbsd/netbsd.h
diff -N src/external/gpl2/lvm2tools/dist/lib/netbsd/netbsd.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/netbsd/netbsd.h	15 Jul 2008 21:40:05 -0000	1.1.2.2
@@ -0,0 +1,13 @@
+
+/*
+ * NetBSD specific header file.
+ */
+
+#ifndef __NETBSD_H__
+#define __NETBSD_H__
+
+
+/* lib/netbsd/netbsd.c  */
+int nbsd_check_dev(int, const char *);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/report/columns.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/report/columns.h
diff -N src/external/gpl2/lvm2tools/dist/lib/report/columns.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/report/columns.h	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,95 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* 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", "Unique identifier")
+FIELD(LVS, lv, STR, "LV", lvid, 4, lvname, "lv_name", "Name.  LVs created for internal use are enclosed in brackets.")
+FIELD(LVS, lv, STR, "Attr", lvid, 4, lvstatus, "lv_attr", "Various attributes - see man page.")
+FIELD(LVS, lv, NUM, "Maj", major, 3, int32, "lv_major", "Persistent major number or -1 if not persistent.")
+FIELD(LVS, lv, NUM, "Min", minor, 3, int32, "lv_minor", "Persistent minor number or -1 if not persistent.")
+FIELD(LVS, lv, NUM, "Rahead", lvid, 6, lvreadahead, "lv_read_ahead", "Read ahead setting in current units.")
+FIELD(LVS, lv, STR, "KMaj", lvid, 4, lvkmaj, "lv_kernel_major", "Currently assigned major number or -1 if LV is not active.")
+FIELD(LVS, lv, STR, "KMin", lvid, 4, lvkmin, "lv_kernel_minor", "Currently assigned minor number or -1 if LV is not active.")
+FIELD(LVS, lv, NUM, "KRahead", lvid, 7, lvkreadahead, "lv_kernel_read_ahead", "Currently-in-use read ahead setting in current units.")
+FIELD(LVS, lv, NUM, "LSize", size, 5, size64, "lv_size", "Size of LV in current units.")
+FIELD(LVS, lv, NUM, "#Seg", lvid, 4, lvsegcount, "seg_count", "Number of segments in LV.")
+FIELD(LVS, lv, STR, "Origin", lvid, 6, origin, "origin", "For snapshots, the origin device of this LV")
+FIELD(LVS, lv, NUM, "Snap%", lvid, 6, snpercent, "snap_percent", "For snapshots, the percentage full if LV is active.")
+FIELD(LVS, lv, NUM, "Copy%", lvid, 6, copypercent, "copy_percent", "For mirrors and pvmove, current percentage in-sync.")
+FIELD(LVS, lv, STR, "Move", lvid, 4, movepv, "move_pv", "For pvmove, Source PV of temporary LV created by pvmove")
+FIELD(LVS, lv, STR, "Convert", lvid, 7, convertlv, "convert_lv", "For lvconvert, Name of temporary LV created by lvconvert")
+FIELD(LVS, lv, STR, "LV Tags", tags, 7, tags, "lv_tags", "Tags, if any.")
+FIELD(LVS, lv, STR, "Log", lvid, 3, loglv, "mirror_log", "For mirrors, the LV holding the synchronisation log.")
+FIELD(LVS, lv, STR, "Modules", lvid, 7, modules, "modules", "Kernel device-mapper modules required for this LV.")
+
+FIELD(PVS, pv, STR, "Fmt", id, 3, pvfmt, "pv_fmt", "Type of metadata.")
+FIELD(PVS, pv, STR, "PV UUID", id, 38, uuid, "pv_uuid", "Unique identifier.")
+FIELD(PVS, pv, NUM, "PSize", id, 5, pvsize, "pv_size", "Size of PV in current units.")
+FIELD(PVS, pv, NUM, "DevSize", dev, 7, devsize, "dev_size", "Size of underlying device in current units.")
+FIELD(PVS, pv, NUM, "1st PE", pe_start, 7, size64, "pe_start", "Offset to the start of data on the underlying device.")
+FIELD(PVS, pv, NUM, "PFree", id, 5, pvfree, "pv_free", "Total amount of unallocated space in current units.")
+FIELD(PVS, pv, NUM, "Used", id, 4, pvused, "pv_used", "Total amount of allocated space in current units.")
+FIELD(PVS, pv, STR, "PV", dev, 10, dev_name, "pv_name", "Name.")
+FIELD(PVS, pv, STR, "Attr", status, 4, pvstatus, "pv_attr", "Various attributes - see man page.")
+FIELD(PVS, pv, NUM, "PE", pe_count, 3, uint32, "pv_pe_count", "Total number of Physical Extents.")
+FIELD(PVS, pv, NUM, "Alloc", pe_alloc_count, 5, uint32, "pv_pe_alloc_count", "Total number of allocated Physical Extents.")
+FIELD(PVS, pv, STR, "PV Tags", tags, 7, tags, "pv_tags", "Tags, if any.")
+FIELD(PVS, pv, NUM, "#PMda", id, 5, pvmdas, "pv_mda_count", "Number of metadata areas on this device.")
+FIELD(PVS, pv, NUM, "#PMdaFree", id, 9, pvmdafree, "pv_mda_free", "Free metadata area space on this device in current units.")
+
+FIELD(VGS, vg, STR, "Fmt", cmd, 3, vgfmt, "vg_fmt", "Type of metadata.")
+FIELD(VGS, vg, STR, "VG UUID", id, 38, uuid, "vg_uuid", "Unique identifier.")
+FIELD(VGS, vg, STR, "VG", name, 4, string, "vg_name", "Name.")
+FIELD(VGS, vg, STR, "Attr", cmd, 5, vgstatus, "vg_attr", "Various attributes - see man page.")
+FIELD(VGS, vg, NUM, "VSize", cmd, 5, vgsize, "vg_size", "Total size of VG in current units.")
+FIELD(VGS, vg, NUM, "VFree", cmd, 5, vgfree, "vg_free", "Total amount of free space in current units.")
+FIELD(VGS, vg, STR, "SYS ID", system_id, 6, string, "vg_sysid", "System ID indicating when and where it was created.")
+FIELD(VGS, vg, NUM, "Ext", extent_size, 3, size32, "vg_extent_size", "Size of Physical Extents in current units.")
+FIELD(VGS, vg, NUM, "#Ext", extent_count, 4, uint32, "vg_extent_count", "Total number of Physical Extents.")
+FIELD(VGS, vg, NUM, "Free", free_count, 4, uint32, "vg_free_count", "Total number of unallocated Physical Extents.")
+FIELD(VGS, vg, NUM, "MaxLV", max_lv, 5, uint32, "max_lv", "Maximum number of LVs allowed in VG or 0 if unlimited.")
+FIELD(VGS, vg, NUM, "MaxPV", max_pv, 5, uint32, "max_pv", "Maximum number of PVs allowed in VG or 0 if unlimited.")
+FIELD(VGS, vg, NUM, "#PV", pv_count, 3, uint32, "pv_count", "Number of PVs.")
+FIELD(VGS, vg, NUM, "#LV", cmd, 3, lvcount, "lv_count", "Number of LVs.")
+FIELD(VGS, vg, NUM, "#SN", snapshot_count, 3, uint32, "snap_count", "Number of snapshots.")
+FIELD(VGS, vg, NUM, "Seq", seqno, 3, uint32, "vg_seqno", "Revision number of internal metadata.  Incremented whenever it changes.")
+FIELD(VGS, vg, STR, "VG Tags", tags, 7, tags, "vg_tags", "Tags, if any.")
+FIELD(VGS, vg, NUM, "#VMda", cmd, 5, vgmdas, "vg_mda_count", "Number of metadata areas in use by this VG.")
+FIELD(VGS, vg, NUM, "#VMdaFree", cmd, 9, vgmdafree, "vg_mda_free", "Free metadata area space for this VG in current units.")
+
+FIELD(SEGS, seg, STR, "Type", list, 4, segtype, "segtype", "Type of LV segment")
+FIELD(SEGS, seg, NUM, "#Str", area_count, 4, uint32, "stripes", "Number of stripes or mirror legs.")
+FIELD(SEGS, seg, NUM, "Stripe", stripe_size, 6, size32, "stripesize", "For stripes, amount of data placed on one device before switching to the next.")
+FIELD(SEGS, seg, NUM, "Stripe", stripe_size, 6, size32, "stripe_size", "For stripes, amount of data placed on one device before switching to the next.")
+FIELD(SEGS, seg, NUM, "Region", region_size, 6, size32, "regionsize", "For mirrors, the unit of data copied when synchronising devices.")
+FIELD(SEGS, seg, NUM, "Region", region_size, 6, size32, "region_size", "For mirrors, the unit of data copied when synchronising devices.")
+FIELD(SEGS, seg, NUM, "Chunk", list, 5, chunksize, "chunksize", "For snapshots, the unit of data used when tracking changes.")
+FIELD(SEGS, seg, NUM, "Chunk", list, 5, chunksize, "chunk_size", "For snapshots, the unit of data used when tracking changes.")
+FIELD(SEGS, seg, NUM, "Start", list, 5, segstart, "seg_start", "Offset within the LV to the start of the segment in current units.")
+FIELD(SEGS, seg, NUM, "Start", list, 5, segstartpe, "seg_start_pe", "Offset within the LV to the start of the segment in physical extents.")
+FIELD(SEGS, seg, NUM, "SSize", list, 5, segsize, "seg_size", "Size of segment in current units.")
+FIELD(SEGS, seg, STR, "Seg Tags", tags, 8, tags, "seg_tags", "Tags, if any.")
+FIELD(SEGS, seg, STR, "PE Ranges", list, 9, peranges, "seg_pe_ranges", "Ranges of Physical Extents of underlying devices in command line format.")
+FIELD(SEGS, seg, STR, "Devices", list, 5, devices, "devices", "Underlying devices used with starting extent numbers.")
+
+FIELD(PVSEGS, pvseg, NUM, "Start", pe, 5, uint32, "pvseg_start", "Physical Extent number of start of segment.")
+FIELD(PVSEGS, pvseg, NUM, "SSize", len, 5, uint32, "pvseg_size", "Number of extents in segment.")
+/* *INDENT-ON* */
Index: src/external/gpl2/lvm2tools/dist/lib/report/report.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/report/report.c
diff -N src/external/gpl2/lvm2tools/dist/lib/report/report.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/report/report.c	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,1138 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "metadata.h"
+#include "report.h"
+#include "toolcontext.h"
+#include "lvm-string.h"
+#include "display.h"
+#include "activate.h"
+#include "segtype.h"
+#include "str_list.h"
+#include "lvmcache.h"
+
+struct lvm_report_object {
+	struct volume_group *vg;
+	struct logical_volume *lv;
+	struct physical_volume *pv;
+	struct lv_segment *seg;
+	struct pv_segment *pvseg;
+};
+
+/*
+ * For macro use
+ */
+static union {
+	struct physical_volume _pv;
+	struct logical_volume _lv;
+	struct volume_group _vg;
+	struct lv_segment _seg;
+	struct pv_segment _pvseg;
+} _dummy;
+
+static char _alloc_policy_char(alloc_policy_t alloc)
+{
+	switch (alloc) {
+	case ALLOC_CONTIGUOUS:
+		return 'c';
+	case ALLOC_CLING:
+		return 'l';
+	case ALLOC_NORMAL:
+		return 'n';
+	case ALLOC_ANYWHERE:
+		return 'a';
+	default:
+		return 'i';
+	}
+}
+
+static const uint64_t _minusone = UINT64_C(-1);
+
+/*
+ * Data-munging functions to prepare each data type for display and sorting
+ */
+static int _string_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
+			struct dm_report_field *field,
+			const void *data, void *private __attribute((unused)))
+{
+	return dm_report_field_string(rh, field, (const char **) data);
+}
+
+static int _dev_name_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
+			  struct dm_report_field *field,
+			  const void *data, void *private __attribute((unused)))
+{
+	const char *name = dev_name(*(const struct device **) data);
+
+	return dm_report_field_string(rh, field, &name);
+}
+
+static int _format_pvsegs(struct dm_pool *mem, struct dm_report_field *field,
+			  const void *data, int range_format)
+{
+	const struct lv_segment *seg = (const struct lv_segment *) data;
+	unsigned int s;
+	const char *name = NULL;
+	uint32_t extent = 0;
+	char extent_str[32];
+
+	if (!dm_pool_begin_object(mem, 256)) {
+		log_error("dm_pool_begin_object failed");
+		return 0;
+	}
+
+	for (s = 0; s < seg->area_count; s++) {
+		switch (seg_type(seg, s)) {
+		case AREA_LV:
+			name = seg_lv(seg, s)->name;
+			extent = seg_le(seg, s);
+			break;
+		case AREA_PV:
+			name = dev_name(seg_dev(seg, s));
+			extent = seg_pe(seg, s);
+			break;
+		case AREA_UNASSIGNED:
+			name = "unassigned";
+			extent = 0;
+		}
+
+		if (!dm_pool_grow_object(mem, name, strlen(name))) {
+			log_error("dm_pool_grow_object failed");
+			return 0;
+		}
+
+		if (dm_snprintf(extent_str, sizeof(extent_str),
+				"%s%" PRIu32 "%s",
+				range_format ? ":" : "(", extent,
+				range_format ? "-"  : ")") < 0) {
+			log_error("Extent number dm_snprintf failed");
+			return 0;
+		}
+		if (!dm_pool_grow_object(mem, extent_str, strlen(extent_str))) {
+			log_error("dm_pool_grow_object failed");
+			return 0;
+		}
+
+		if (range_format) {
+			if (dm_snprintf(extent_str, sizeof(extent_str),
+					"%" PRIu32, extent + seg->area_len - 1) < 0) {
+				log_error("Extent number dm_snprintf failed");
+				return 0;
+			}
+			if (!dm_pool_grow_object(mem, extent_str, strlen(extent_str))) {
+				log_error("dm_pool_grow_object failed");
+				return 0;
+			}
+		}
+
+		if ((s != seg->area_count - 1) &&
+		    !dm_pool_grow_object(mem, range_format ? " " : ",", 1)) {
+			log_error("dm_pool_grow_object failed");
+			return 0;
+		}
+	}
+
+	if (!dm_pool_grow_object(mem, "\0", 1)) {
+		log_error("dm_pool_grow_object failed");
+		return 0;
+	}
+
+	dm_report_field_set_value(field, dm_pool_end_object(mem), NULL);
+
+	return 1;
+}
+
+static int _devices_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
+			 struct dm_report_field *field,
+			 const void *data, void *private __attribute((unused)))
+{
+	return _format_pvsegs(mem, field, data, 0);
+}
+
+static int _peranges_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
+			  struct dm_report_field *field,
+			  const void *data, void *private __attribute((unused)))
+{
+	return _format_pvsegs(mem, field, data, 1);
+}
+
+static int _tags_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
+		      struct dm_report_field *field,
+		      const void *data, void *private __attribute((unused)))
+{
+	const struct dm_list *tags = (const struct dm_list *) data;
+	struct str_list *sl;
+
+	if (!dm_pool_begin_object(mem, 256)) {
+		log_error("dm_pool_begin_object failed");
+		return 0;
+	}
+
+	dm_list_iterate_items(sl, tags) {
+		if (!dm_pool_grow_object(mem, sl->str, strlen(sl->str)) ||
+		    (sl->list.n != tags && !dm_pool_grow_object(mem, ",", 1))) {
+			log_error("dm_pool_grow_object failed");
+			return 0;
+		}
+	}
+
+	if (!dm_pool_grow_object(mem, "\0", 1)) {
+		log_error("dm_pool_grow_object failed");
+		return 0;
+	}
+
+	dm_report_field_set_value(field, dm_pool_end_object(mem), NULL);
+
+	return 1;
+}
+
+static int _modules_disp(struct dm_report *rh, struct dm_pool *mem,
+			 struct dm_report_field *field,
+			 const void *data, void *private)
+{
+	const struct logical_volume *lv = (const struct logical_volume *) data;
+	struct dm_list *modules;
+
+	if (!(modules = str_list_create(mem))) {
+		log_error("modules str_list allocation failed");
+		return 0;
+	}
+
+	if (!list_lv_modules(mem, lv, modules))
+		return_0;
+
+	return _tags_disp(rh, mem, field, modules, private);
+}
+
+static int _vgfmt_disp(struct dm_report *rh, struct dm_pool *mem,
+		       struct dm_report_field *field,
+		       const void *data, void *private)
+{
+	const struct volume_group *vg = (const struct volume_group *) data;
+
+	if (!vg->fid) {
+		dm_report_field_set_value(field, "", NULL);
+		return 1;
+	}
+
+	return _string_disp(rh, mem, field, &vg->fid->fmt->name, private);
+}
+
+static int _pvfmt_disp(struct dm_report *rh, struct dm_pool *mem,
+		       struct dm_report_field *field,
+		       const void *data, void *private)
+{
+	const struct physical_volume *pv =
+	    (const struct physical_volume *) data;
+
+	if (!pv->fmt) {
+		dm_report_field_set_value(field, "", NULL);
+		return 1;
+	}
+
+	return _string_disp(rh, mem, field, &pv->fmt->name, private);
+}
+
+static int _lvkmaj_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
+			struct dm_report_field *field,
+			const void *data, void *private __attribute((unused)))
+{
+	const struct logical_volume *lv = (const struct logical_volume *) data;
+	struct lvinfo info;
+
+	if (lv_info(lv->vg->cmd, lv, &info, 0, 0) && info.exists)
+		return dm_report_field_int(rh, field, &info.major);
+
+	return dm_report_field_uint64(rh, field, &_minusone);
+}
+
+static int _lvkmin_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
+			struct dm_report_field *field,
+			const void *data, void *private __attribute((unused)))
+{
+	const struct logical_volume *lv = (const struct logical_volume *) data;
+	struct lvinfo info;
+
+	if (lv_info(lv->vg->cmd, lv, &info, 0, 0) && info.exists)
+		return dm_report_field_int(rh, field, &info.minor);
+
+	return dm_report_field_uint64(rh, field, &_minusone);
+}
+
+static int _lv_mimage_in_sync(const struct logical_volume *lv)
+{
+	float percent;
+	struct lv_segment *mirror_seg = find_mirror_seg(first_seg(lv));
+
+	if (!(lv->status & MIRROR_IMAGE) || !mirror_seg)
+		return_0;
+
+	if (!lv_mirror_percent(lv->vg->cmd, mirror_seg->lv, 0, &percent, NULL))
+		return_0;
+
+	if (percent >= 100.0)
+		return 1;
+
+	return 0;
+}
+
+static int _lvstatus_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
+			  struct dm_report_field *field,
+			  const void *data, void *private __attribute((unused)))
+{
+	const struct logical_volume *lv = (const struct logical_volume *) data;
+	struct lvinfo info;
+	char *repstr;
+	float snap_percent;
+
+	if (!(repstr = dm_pool_zalloc(mem, 7))) {
+		log_error("dm_pool_alloc failed");
+		return 0;
+	}
+
+	/* Blank if this is a "free space" LV. */
+	if (!*lv->name)
+		goto out;
+
+	if (lv->status & PVMOVE)
+		repstr[0] = 'p';
+	else if (lv->status & CONVERTING)
+		repstr[0] = 'c';
+	else if (lv->status & MIRRORED) {
+		if (lv->status & MIRROR_NOTSYNCED)
+			repstr[0] = 'M';
+		else
+			repstr[0] = 'm';
+	}else if (lv->status & MIRROR_IMAGE)
+		if (_lv_mimage_in_sync(lv))
+			repstr[0] = 'i';
+		else
+			repstr[0] = 'I';
+	else if (lv->status & MIRROR_LOG)
+		repstr[0] = 'l';
+	else if (lv->status & VIRTUAL)
+		repstr[0] = 'v';
+	else if (lv_is_origin(lv))
+		repstr[0] = 'o';
+	else if (lv_is_cow(lv))
+		repstr[0] = 's';
+	else
+		repstr[0] = '-';
+
+	if (lv->status & PVMOVE)
+		repstr[1] = '-';
+	else if (lv->status & LVM_WRITE)
+		repstr[1] = 'w';
+	else if (lv->status & LVM_READ)
+		repstr[1] = 'r';
+	else
+		repstr[1] = '-';
+
+	repstr[2] = _alloc_policy_char(lv->alloc);
+
+	if (lv->status & LOCKED)
+		repstr[2] = toupper(repstr[2]);
+
+	if (lv->status & FIXED_MINOR)
+		repstr[3] = 'm';	/* Fixed Minor */
+	else
+		repstr[3] = '-';
+
+	if (lv_info(lv->vg->cmd, lv, &info, 1, 0) && info.exists) {
+		if (info.suspended)
+			repstr[4] = 's';	/* Suspended */
+		else if (info.live_table)
+			repstr[4] = 'a';	/* Active */
+		else if (info.inactive_table)
+			repstr[4] = 'i';	/* Inactive with table */
+		else
+			repstr[4] = 'd';	/* Inactive without table */
+
+		/* Snapshot dropped? */
+		if (info.live_table && lv_is_cow(lv) &&
+		    (!lv_snapshot_percent(lv, &snap_percent) ||
+		     snap_percent < 0 || snap_percent >= 100)) {
+			repstr[0] = toupper(repstr[0]);
+			if (info.suspended)
+				repstr[4] = 'S'; /* Susp Inv snapshot */
+			else
+				repstr[4] = 'I'; /* Invalid snapshot */
+		}
+
+		if (info.open_count)
+			repstr[5] = 'o';	/* Open */
+		else
+			repstr[5] = '-';
+	} else {
+		repstr[4] = '-';
+		repstr[5] = '-';
+	}
+
+out:
+	dm_report_field_set_value(field, repstr, NULL);
+	return 1;
+}
+
+static int _pvstatus_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
+			  struct dm_report_field *field,
+			  const void *data, void *private __attribute((unused)))
+{
+	const uint32_t status = *(const uint32_t *) data;
+	char *repstr;
+
+	if (!(repstr = dm_pool_zalloc(mem, 3))) {
+		log_error("dm_pool_alloc failed");
+		return 0;
+	}
+
+	if (status & ALLOCATABLE_PV)
+		repstr[0] = 'a';
+	else
+		repstr[0] = '-';
+
+	if (status & EXPORTED_VG)
+		repstr[1] = 'x';
+	else
+		repstr[1] = '-';
+
+	dm_report_field_set_value(field, repstr, NULL);
+	return 1;
+}
+
+static int _vgstatus_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
+			  struct dm_report_field *field,
+			  const void *data, void *private __attribute((unused)))
+{
+	const struct volume_group *vg = (const struct volume_group *) data;
+	char *repstr;
+
+	if (!(repstr = dm_pool_zalloc(mem, 7))) {
+		log_error("dm_pool_alloc failed");
+		return 0;
+	}
+
+	if (vg->status & LVM_WRITE)
+		repstr[0] = 'w';
+	else
+		repstr[0] = 'r';
+
+	if (vg->status & RESIZEABLE_VG)
+		repstr[1] = 'z';
+	else
+		repstr[1] = '-';
+
+	if (vg->status & EXPORTED_VG)
+		repstr[2] = 'x';
+	else
+		repstr[2] = '-';
+
+	if (vg_missing_pv_count(vg))
+		repstr[3] = 'p';
+	else
+		repstr[3] = '-';
+
+	repstr[4] = _alloc_policy_char(vg->alloc);
+
+	if (vg_is_clustered(vg))
+		repstr[5] = 'c';
+	else
+		repstr[5] = '-';
+
+	dm_report_field_set_value(field, repstr, NULL);
+	return 1;
+}
+
+static int _segtype_disp(struct dm_report *rh __attribute((unused)),
+			 struct dm_pool *mem __attribute((unused)),
+			 struct dm_report_field *field,
+			 const void *data, void *private __attribute((unused)))
+{
+	const struct lv_segment *seg = (const struct lv_segment *) data;
+
+	if (seg->area_count == 1) {
+		dm_report_field_set_value(field, "linear", NULL);
+		return 1;
+	}
+
+	dm_report_field_set_value(field, seg->segtype->ops->name(seg), NULL);
+	return 1;
+}
+
+static int _origin_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
+			struct dm_report_field *field,
+			const void *data, void *private __attribute((unused)))
+{
+	const struct logical_volume *lv = (const struct logical_volume *) data;
+
+	if (lv_is_cow(lv))
+		return dm_report_field_string(rh, field,
+					      (const char **) &origin_from_cow(lv)->name);
+
+	dm_report_field_set_value(field, "", NULL);
+	return 1;
+}
+
+static int _loglv_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
+		       struct dm_report_field *field,
+		       const void *data, void *private __attribute((unused)))
+{
+	const struct logical_volume *lv = (const struct logical_volume *) data;
+	struct lv_segment *seg;
+
+	dm_list_iterate_items(seg, &lv->segments) {
+		if (!seg_is_mirrored(seg) || !seg->log_lv)
+			continue;
+		return dm_report_field_string(rh, field,
+					      (const char **) &seg->log_lv->name);
+	}
+
+	dm_report_field_set_value(field, "", NULL);
+	return 1;
+}
+
+static int _lvname_disp(struct dm_report *rh, struct dm_pool *mem,
+			struct dm_report_field *field,
+			const void *data, void *private __attribute((unused)))
+{
+	const struct logical_volume *lv = (const struct logical_volume *) data;
+	char *repstr, *lvname;
+	size_t len;
+
+	if (lv_is_visible(lv)) {
+		repstr = lv->name;
+		return dm_report_field_string(rh, field, (const char **) &repstr);
+	}
+
+	len = strlen(lv->name) + 3;
+	if (!(repstr = dm_pool_zalloc(mem, len))) {
+		log_error("dm_pool_alloc failed");
+		return 0;
+	}
+
+	if (dm_snprintf(repstr, len, "[%s]", lv->name) < 0) {
+		log_error("lvname snprintf failed");
+		return 0;
+	}
+
+	if (!(lvname = dm_pool_strdup(mem, lv->name))) {
+		log_error("dm_pool_strdup failed");
+		return 0;
+	}
+
+	dm_report_field_set_value(field, repstr, lvname);
+
+	return 1;
+}
+
+static int _movepv_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
+			struct dm_report_field *field,
+			const void *data, void *private __attribute((unused)))
+{
+	const struct logical_volume *lv = (const struct logical_volume *) data;
+	const char *name;
+	struct lv_segment *seg;
+
+	dm_list_iterate_items(seg, &lv->segments) {
+		if (!(seg->status & PVMOVE))
+			continue;
+		name = dev_name(seg_dev(seg, 0));
+		return dm_report_field_string(rh, field, &name);
+	}
+
+	dm_report_field_set_value(field, "", NULL);
+	return 1;
+}
+
+static int _convertlv_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
+			   struct dm_report_field *field,
+			   const void *data, void *private __attribute((unused)))
+{
+	const struct logical_volume *lv = (const struct logical_volume *) data;
+	const char *name = NULL;
+	struct lv_segment *seg;
+
+	if (lv->status & CONVERTING) {
+		if (lv->status & MIRRORED) {
+			seg = first_seg(lv);
+
+			/* Temporary mirror is always area_num == 0 */
+			if (seg_type(seg, 0) == AREA_LV &&
+			    is_temporary_mirror_layer(seg_lv(seg, 0)))
+				name = seg_lv(seg, 0)->name;
+		}
+	}
+
+	if (name)
+		return dm_report_field_string(rh, field, &name);
+
+	dm_report_field_set_value(field, "", NULL);
+	return 1;
+}
+
+static int _size32_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
+			struct dm_report_field *field,
+			const void *data, void *private)
+{
+	const uint32_t size = *(const uint32_t *) data;
+	const char *disp, *repstr;
+	uint64_t *sortval;
+
+	if (!*(disp = display_size_units(private, (uint64_t) size)))
+		return_0;
+
+	if (!(repstr = dm_pool_strdup(mem, disp))) {
+		log_error("dm_pool_strdup failed");
+		return 0;
+	}
+
+	if (!(sortval = dm_pool_alloc(mem, sizeof(uint64_t)))) {
+		log_error("dm_pool_alloc failed");
+		return 0;
+	}
+
+	*sortval = (const uint64_t) size;
+
+	dm_report_field_set_value(field, repstr, sortval);
+
+	return 1;
+}
+
+static int _size64_disp(struct dm_report *rh __attribute((unused)),
+			struct dm_pool *mem,
+			struct dm_report_field *field,
+			const void *data, void *private)
+{
+	const uint64_t size = *(const uint64_t *) data;
+	const char *disp, *repstr;
+	uint64_t *sortval;
+
+	if (!*(disp = display_size_units(private, size)))
+		return_0;
+
+	if (!(repstr = dm_pool_strdup(mem, disp))) {
+		log_error("dm_pool_strdup failed");
+		return 0;
+	}
+
+	if (!(sortval = dm_pool_alloc(mem, sizeof(uint64_t)))) {
+		log_error("dm_pool_alloc failed");
+		return 0;
+	}
+
+	*sortval = size;
+	dm_report_field_set_value(field, repstr, sortval);
+
+	return 1;
+}
+
+static int _lvreadahead_disp(struct dm_report *rh, struct dm_pool *mem,
+			     struct dm_report_field *field,
+			     const void *data, void *private __attribute((unused)))
+{
+	const struct logical_volume *lv = (const struct logical_volume *) data;
+
+	if (lv->read_ahead == DM_READ_AHEAD_AUTO) {
+		dm_report_field_set_value(field, "auto", &_minusone);
+		return 1;
+	}
+
+	return _size32_disp(rh, mem, field, &lv->read_ahead, private);
+}
+
+static int _lvkreadahead_disp(struct dm_report *rh, struct dm_pool *mem,
+			      struct dm_report_field *field,
+			      const void *data,
+			      void *private)
+{
+	const struct logical_volume *lv = (const struct logical_volume *) data;
+	struct lvinfo info;
+
+	if (!lv_info(lv->vg->cmd, lv, &info, 0, 1) || !info.exists)
+		return dm_report_field_uint64(rh, field, &_minusone);
+
+	return _size32_disp(rh, mem, field, &info.read_ahead, private);
+}
+
+static int _vgsize_disp(struct dm_report *rh, struct dm_pool *mem,
+			struct dm_report_field *field,
+			const void *data, void *private)
+{
+	const struct volume_group *vg = (const struct volume_group *) data;
+	uint64_t size;
+
+	size = (uint64_t) vg->extent_count * vg->extent_size;
+
+	return _size64_disp(rh, mem, field, &size, private);
+}
+
+static int _segstart_disp(struct dm_report *rh, struct dm_pool *mem,
+			  struct dm_report_field *field,
+			  const void *data, void *private)
+{
+	const struct lv_segment *seg = (const struct lv_segment *) data;
+	uint64_t start;
+
+	start = (uint64_t) seg->le * seg->lv->vg->extent_size;
+
+	return _size64_disp(rh, mem, field, &start, private);
+}
+
+static int _segstartpe_disp(struct dm_report *rh,
+			    struct dm_pool *mem __attribute((unused)),
+			    struct dm_report_field *field,
+			    const void *data,
+			    void *private __attribute((unused)))
+{
+	const struct lv_segment *seg = (const struct lv_segment *) data;
+
+	return dm_report_field_uint32(rh, field, &seg->le);
+}
+
+static int _segsize_disp(struct dm_report *rh, struct dm_pool *mem,
+			 struct dm_report_field *field,
+			 const void *data, void *private)
+{
+	const struct lv_segment *seg = (const struct lv_segment *) data;
+	uint64_t size;
+
+	size = (uint64_t) seg->len * seg->lv->vg->extent_size;
+
+	return _size64_disp(rh, mem, field, &size, private);
+}
+
+static int _chunksize_disp(struct dm_report *rh, struct dm_pool *mem,
+			   struct dm_report_field *field,
+			   const void *data, void *private)
+{
+	const struct lv_segment *seg = (const struct lv_segment *) data;
+	uint64_t size;
+
+	if (lv_is_cow(seg->lv))
+		size = (uint64_t) find_cow(seg->lv)->chunk_size;
+	else
+		size = 0;
+
+	return _size64_disp(rh, mem, field, &size, private);
+}
+
+static int _pvused_disp(struct dm_report *rh, struct dm_pool *mem,
+			struct dm_report_field *field,
+			const void *data, void *private)
+{
+	const struct physical_volume *pv =
+	    (const struct physical_volume *) data;
+	uint64_t used;
+
+	if (!pv->pe_count)
+		used = 0LL;
+	else
+		used = (uint64_t) pv->pe_alloc_count * pv->pe_size;
+
+	return _size64_disp(rh, mem, field, &used, private);
+}
+
+static int _pvfree_disp(struct dm_report *rh, struct dm_pool *mem,
+			struct dm_report_field *field,
+			const void *data, void *private)
+{
+	const struct physical_volume *pv =
+	    (const struct physical_volume *) data;
+	uint64_t freespace;
+
+	if (!pv->pe_count)
+		freespace = pv->size;
+	else
+		freespace = (uint64_t) (pv->pe_count - pv->pe_alloc_count) * pv->pe_size;
+
+	return _size64_disp(rh, mem, field, &freespace, private);
+}
+
+static int _pvsize_disp(struct dm_report *rh, struct dm_pool *mem,
+			struct dm_report_field *field,
+			const void *data, void *private)
+{
+	const struct physical_volume *pv =
+	    (const struct physical_volume *) data;
+	uint64_t size;
+
+	if (!pv->pe_count)
+		size = pv->size;
+	else
+		size = (uint64_t) pv->pe_count * pv->pe_size;
+
+	return _size64_disp(rh, mem, field, &size, private);
+}
+
+static int _devsize_disp(struct dm_report *rh, struct dm_pool *mem,
+			 struct dm_report_field *field,
+			 const void *data, void *private)
+{
+	const struct device *dev = *(const struct device **) data;
+	uint64_t size;
+
+	if (!dev_get_size(dev, &size))
+		size = 0;
+
+	return _size64_disp(rh, mem, field, &size, private);
+}
+
+static int _vgfree_disp(struct dm_report *rh, struct dm_pool *mem,
+			struct dm_report_field *field,
+			const void *data, void *private)
+{
+	const struct volume_group *vg = (const struct volume_group *) data;
+	uint64_t freespace;
+
+	freespace = (uint64_t) vg->free_count * vg->extent_size;
+
+	return _size64_disp(rh, mem, field, &freespace, private);
+}
+
+static int _uuid_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
+		      struct dm_report_field *field,
+		      const void *data, void *private __attribute((unused)))
+{
+	char *repstr = NULL;
+
+	if (!(repstr = dm_pool_alloc(mem, 40))) {
+		log_error("dm_pool_alloc failed");
+		return 0;
+	}
+
+	if (!id_write_format((const struct id *) data, repstr, 40))
+		return_0;
+
+	dm_report_field_set_value(field, repstr, NULL);
+	return 1;
+}
+
+static int _uint32_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
+			struct dm_report_field *field,
+			const void *data, void *private __attribute((unused)))
+{
+	return dm_report_field_uint32(rh, field, data);
+}
+
+static int _int32_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
+		       struct dm_report_field *field,
+		       const void *data, void *private __attribute((unused)))
+{
+	return dm_report_field_int32(rh, field, data);
+}
+
+static int _pvmdas_disp(struct dm_report *rh, struct dm_pool *mem,
+			struct dm_report_field *field,
+			const void *data, void *private)
+{
+	struct lvmcache_info *info;
+	uint32_t count;
+	const char *pvid = (const char *)(&((struct id *) data)->uuid);
+
+	info = info_from_pvid(pvid, 0);
+	count = info ? dm_list_size(&info->mdas) : 0;
+
+	return _uint32_disp(rh, mem, field, &count, private);
+}
+
+static int _vgmdas_disp(struct dm_report *rh, struct dm_pool *mem,
+			struct dm_report_field *field,
+			const void *data, void *private)
+{
+	const struct volume_group *vg = (const struct volume_group *) data;
+	uint32_t count;
+
+	count = dm_list_size(&vg->fid->metadata_areas);
+
+	return _uint32_disp(rh, mem, field, &count, private);
+}
+
+static int _pvmdafree_disp(struct dm_report *rh, struct dm_pool *mem,
+			   struct dm_report_field *field,
+			   const void *data, void *private)
+{
+	struct lvmcache_info *info;
+	uint64_t freespace = UINT64_MAX, mda_free;
+	const char *pvid = (const char *)(&((struct id *) data)->uuid);
+	struct metadata_area *mda;
+
+	info = info_from_pvid(pvid, 0);
+
+	dm_list_iterate_items(mda, &info->mdas) {
+		if (!mda->ops->mda_free_sectors)
+			continue;
+		mda_free = mda->ops->mda_free_sectors(mda);
+		if (mda_free < freespace)
+			freespace = mda_free;
+	}
+
+	if (freespace == UINT64_MAX)
+		freespace = UINT64_C(0);
+
+	return _size64_disp(rh, mem, field, &freespace, private);
+}
+
+static int _vgmdafree_disp(struct dm_report *rh, struct dm_pool *mem,
+			   struct dm_report_field *field,
+			   const void *data, void *private)
+{
+	const struct volume_group *vg = (const struct volume_group *) data;
+	uint64_t freespace = UINT64_MAX, mda_free;
+	struct metadata_area *mda;
+
+	dm_list_iterate_items(mda, &vg->fid->metadata_areas) {
+		if (!mda->ops->mda_free_sectors)
+			continue;
+		mda_free = mda->ops->mda_free_sectors(mda);
+		if (mda_free < freespace)
+			freespace = mda_free;
+	}
+
+	if (freespace == UINT64_MAX)
+		freespace = UINT64_C(0);
+
+	return _size64_disp(rh, mem, field, &freespace, private);
+}
+
+static int _lvcount_disp(struct dm_report *rh, struct dm_pool *mem,
+			 struct dm_report_field *field,
+			 const void *data, void *private)
+{
+	const struct volume_group *vg = (const struct volume_group *) data;
+        struct lv_list *lvl;
+	uint32_t count = 0;
+
+        dm_list_iterate_items(lvl, &vg->lvs)
+		if (lv_is_visible(lvl->lv) && !(lvl->lv->status & SNAPSHOT))
+			count++;
+
+	return _uint32_disp(rh, mem, field, &count, private);
+}
+
+static int _lvsegcount_disp(struct dm_report *rh, struct dm_pool *mem,
+			    struct dm_report_field *field,
+			    const void *data, void *private)
+{
+	const struct logical_volume *lv = (const struct logical_volume *) data;
+	uint32_t count;
+
+	count = dm_list_size(&lv->segments);
+
+	return _uint32_disp(rh, mem, field, &count, private);
+}
+
+static int _snpercent_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
+			   struct dm_report_field *field,
+			   const void *data, void *private __attribute((unused)))
+{
+	const struct logical_volume *lv = (const struct logical_volume *) data;
+	struct lvinfo info;
+	float snap_percent;
+	uint64_t *sortval;
+	char *repstr;
+
+	/* Suppress snapshot percentage if not using driver */
+	if (!activation()) {
+		dm_report_field_set_value(field, "", NULL);
+		return 1;
+	}
+
+	if (!(sortval = dm_pool_alloc(mem, sizeof(uint64_t)))) {
+		log_error("dm_pool_alloc failed");
+		return 0;
+	}
+
+	if (!lv_is_cow(lv) ||
+	    (lv_info(lv->vg->cmd, lv, &info, 0, 0) && !info.exists)) {
+		*sortval = UINT64_C(0);
+		dm_report_field_set_value(field, "", sortval);
+		return 1;
+	}
+
+	if (!lv_snapshot_percent(lv, &snap_percent) || snap_percent < 0) {
+		*sortval = UINT64_C(100);
+		dm_report_field_set_value(field, "100.00", sortval);
+		return 1;
+	}
+
+	if (!(repstr = dm_pool_zalloc(mem, 8))) {
+		log_error("dm_pool_alloc failed");
+		return 0;
+	}
+
+	if (dm_snprintf(repstr, 7, "%.2f", snap_percent) < 0) {
+		log_error("snapshot percentage too large");
+		return 0;
+	}
+
+	*sortval = snap_percent * UINT64_C(1000);
+	dm_report_field_set_value(field, repstr, sortval);
+
+	return 1;
+}
+
+static int _copypercent_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
+			     struct dm_report_field *field,
+			     const void *data, void *private __attribute((unused)))
+{
+	struct logical_volume *lv = (struct logical_volume *) data;
+	float percent;
+	uint64_t *sortval;
+	char *repstr;
+
+	if (!(sortval = dm_pool_alloc(mem, sizeof(uint64_t)))) {
+		log_error("dm_pool_alloc failed");
+		return 0;
+	}
+
+	if ((!(lv->status & PVMOVE) && !(lv->status & MIRRORED)) ||
+	    !lv_mirror_percent(lv->vg->cmd, lv, 0, &percent, NULL)) {
+		*sortval = UINT64_C(0);
+		dm_report_field_set_value(field, "", sortval);
+		return 1;
+	}
+
+	percent = copy_percent(lv);
+
+	if (!(repstr = dm_pool_zalloc(mem, 8))) {
+		log_error("dm_pool_alloc failed");
+		return 0;
+	}
+
+	if (dm_snprintf(repstr, 7, "%.2f", percent) < 0) {
+		log_error("copy percentage too large");
+		return 0;
+	}
+
+	*sortval = percent * UINT64_C(1000);
+	dm_report_field_set_value(field, repstr, sortval);
+
+	return 1;
+}
+
+/* Report object types */
+
+/* necessary for displaying something for PVs not belonging to VG */
+static struct volume_group _dummy_vg = {
+	.name = (char *) "",
+};
+
+static void *_obj_get_vg(void *obj)
+{
+	struct volume_group *vg = ((struct lvm_report_object *)obj)->vg;
+
+	return vg ? vg : &_dummy_vg;
+}
+
+static void *_obj_get_lv(void *obj)
+{
+	return ((struct lvm_report_object *)obj)->lv;
+}
+
+static void *_obj_get_pv(void *obj)
+{
+	return ((struct lvm_report_object *)obj)->pv;
+}
+
+static void *_obj_get_seg(void *obj)
+{
+	return ((struct lvm_report_object *)obj)->seg;
+}
+
+static void *_obj_get_pvseg(void *obj)
+{
+	return ((struct lvm_report_object *)obj)->pvseg;
+}
+
+static const struct dm_report_object_type _report_types[] = {
+	{ VGS, "Volume Group", "vg_", _obj_get_vg },
+	{ LVS, "Logical Volume", "lv_", _obj_get_lv },
+	{ PVS, "Physical Volume", "pv_", _obj_get_pv },
+	{ SEGS, "Logical Volume Segment", "seg_", _obj_get_seg },
+	{ PVSEGS, "Physical Volume Segment", "pvseg_", _obj_get_pvseg },
+	{ 0, "", "", NULL },
+};
+
+/*
+ * Import column definitions
+ */
+
+#define STR DM_REPORT_FIELD_TYPE_STRING
+#define NUM DM_REPORT_FIELD_TYPE_NUMBER
+#define FIELD(type, strct, sorttype, head, field, width, func, id, desc) {type, sorttype, (off_t)((uintptr_t)&_dummy._ ## strct.field - (uintptr_t)&_dummy._ ## strct), width, id, head, &_ ## func ## _disp, desc},
+
+static struct dm_report_field_type _fields[] = {
+#include "columns.h"
+{0, 0, 0, 0, "", "", NULL, NULL},
+};
+
+#undef STR
+#undef NUM
+#undef FIELD
+
+void *report_init(struct cmd_context *cmd, const char *format, const char *keys,
+		  report_type_t *report_type, const char *separator,
+		  int aligned, int buffered, int headings, int field_prefixes,
+		  int quoted, int columns_as_rows)
+{
+	uint32_t report_flags = 0;
+	void *rh;
+
+	if (aligned)
+		report_flags |= DM_REPORT_OUTPUT_ALIGNED;
+
+	if (buffered)
+		report_flags |= DM_REPORT_OUTPUT_BUFFERED;
+
+	if (headings)
+		report_flags |= DM_REPORT_OUTPUT_HEADINGS;
+
+	if (field_prefixes)
+		report_flags |= DM_REPORT_OUTPUT_FIELD_NAME_PREFIX;
+
+	if (!quoted)
+		report_flags |= DM_REPORT_OUTPUT_FIELD_UNQUOTED;
+
+	if (columns_as_rows)
+		report_flags |= DM_REPORT_OUTPUT_COLUMNS_AS_ROWS;
+
+	rh = dm_report_init(report_type, _report_types, _fields, format,
+			    separator, report_flags, keys, cmd);
+
+	if (field_prefixes)
+		dm_report_set_output_field_name_prefix(rh, "lvm2_");
+
+	return rh;
+}
+
+/*
+ * Create a row of data for an object
+ */
+int report_object(void *handle, struct volume_group *vg,
+		  struct logical_volume *lv, struct physical_volume *pv,
+		  struct lv_segment *seg, struct pv_segment *pvseg)
+{
+	struct lvm_report_object obj;
+
+	obj.vg = vg;
+	obj.lv = lv;
+	obj.pv = pv;
+	obj.seg = seg;
+	obj.pvseg = pvseg;
+
+	return dm_report_object(handle, &obj);
+}
Index: src/external/gpl2/lvm2tools/dist/lib/report/report.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/report/report.h
diff -N src/external/gpl2/lvm2tools/dist/lib/report/report.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/report/report.h	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,41 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_REPORT_H
+#define _LVM_REPORT_H
+
+#include "metadata-exported.h"
+
+typedef enum { LVS = 1, PVS = 2, VGS = 4, SEGS = 8, PVSEGS = 16 } report_type_t;
+
+struct field;
+struct report_handle;
+
+typedef int (*field_report_fn) (struct report_handle * dh, struct field * field,
+				const void *data);
+
+void *report_init(struct cmd_context *cmd, const char *format, const char *keys,
+		  report_type_t *report_type, const char *separator,
+		  int aligned, int buffered, int headings, int field_prefixes,
+		  int quoted, int columns_as_rows);
+void report_free(void *handle);
+int report_object(void *handle, struct volume_group *vg,
+		  struct logical_volume *lv, struct physical_volume *pv,
+		  struct lv_segment *seg, struct pv_segment *pvseg);
+int report_output(void *handle);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/snapshot/.exported_symbols
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/snapshot/.exported_symbols
diff -N src/external/gpl2/lvm2tools/dist/lib/snapshot/.exported_symbols
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/snapshot/.exported_symbols	15 Jul 2008 13:49:54 -0000	1.1.1.1
@@ -0,0 +1 @@
+init_segtype
Index: src/external/gpl2/lvm2tools/dist/lib/snapshot/Makefile.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/snapshot/Makefile.in
diff -N src/external/gpl2/lvm2tools/dist/lib/snapshot/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/snapshot/Makefile.in	12 Dec 2008 16:33:01 -0000	1.1.1.1.2.1
@@ -0,0 +1,31 @@
+#
+# Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+SOURCES = snapshot.c
+
+LIB_SHARED = liblvm2snapshot.so
+LIB_VERSION = $(LIB_VERSION_LVM)
+
+include $(top_srcdir)/make.tmpl
+
+install: liblvm2snapshot.so
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
+		$(libdir)/liblvm2snapshot.so.$(LIB_VERSION)
+	$(LN_S) -f liblvm2snapshot.so.$(LIB_VERSION) \
+		$(libdir)/liblvm2snapshot.so
+
Index: src/external/gpl2/lvm2tools/dist/lib/snapshot/snapshot.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/snapshot/snapshot.c
diff -N src/external/gpl2/lvm2tools/dist/lib/snapshot/snapshot.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/snapshot/snapshot.c	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,319 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "toolcontext.h"
+#include "metadata.h"
+#include "segtype.h"
+#include "text_export.h"
+#include "config.h"
+#include "activate.h"
+#include "str_list.h"
+#ifdef DMEVENTD
+#  include "sharedlib.h"
+#  include "libdevmapper-event.h"
+#endif
+
+static const char *_snap_name(const struct lv_segment *seg)
+{
+	return seg->segtype->name;
+}
+
+static int _snap_text_import(struct lv_segment *seg, const struct config_node *sn,
+			struct dm_hash_table *pv_hash __attribute((unused)))
+{
+	uint32_t chunk_size;
+	const char *org_name, *cow_name;
+	struct logical_volume *org, *cow;
+
+	seg->lv->status |= SNAPSHOT;
+
+	if (!get_config_uint32(sn, "chunk_size", &chunk_size)) {
+		log_error("Couldn't read chunk size for snapshot.");
+		return 0;
+	}
+
+	log_suppress(1);
+
+	if (!(cow_name = find_config_str(sn, "cow_store", NULL))) {
+		log_suppress(0);
+		log_error("Snapshot cow storage not specified.");
+		return 0;
+	}
+
+	if (!(org_name = find_config_str(sn, "origin", NULL))) {
+		log_suppress(0);
+		log_error("Snapshot origin not specified.");
+		return 0;
+	}
+
+	log_suppress(0);
+
+	if (!(cow = find_lv(seg->lv->vg, cow_name))) {
+		log_error("Unknown logical volume specified for "
+			  "snapshot cow store.");
+		return 0;
+	}
+
+	if (!(org = find_lv(seg->lv->vg, org_name))) {
+		log_error("Unknown logical volume specified for "
+			  "snapshot origin.");
+		return 0;
+	}
+
+	if (!vg_add_snapshot(seg->lv->name, org, cow,
+			     &seg->lv->lvid, seg->len, chunk_size))
+		return_0;
+
+	return 1;
+}
+
+static int _snap_text_export(const struct lv_segment *seg, struct formatter *f)
+{
+	outf(f, "chunk_size = %u", seg->chunk_size);
+	outf(f, "origin = \"%s\"", seg->origin->name);
+	outf(f, "cow_store = \"%s\"", seg->cow->name);
+
+	return 1;
+}
+
+#ifdef DEVMAPPER_SUPPORT
+static int _snap_target_percent(void **target_state __attribute((unused)),
+			   struct dm_pool *mem __attribute((unused)),
+			   struct cmd_context *cmd __attribute((unused)),
+			   struct lv_segment *seg __attribute((unused)),
+			   char *params, uint64_t *total_numerator,
+			   uint64_t *total_denominator)
+{
+	uint64_t numerator, denominator;
+
+	if (sscanf(params, "%" PRIu64 "/%" PRIu64,
+		   &numerator, &denominator) == 2) {
+		*total_numerator += numerator;
+		*total_denominator += denominator;
+	}
+
+	return 1;
+}
+
+static int _snap_target_present(const struct lv_segment *seg __attribute((unused)),
+				unsigned *attributes __attribute((unused)))
+{
+	static int _snap_checked = 0;
+	static int _snap_present = 0;
+
+	if (!_snap_checked)
+		_snap_present = target_present("snapshot", 1) &&
+		    target_present("snapshot-origin", 0);
+
+	_snap_checked = 1;
+
+	return _snap_present;
+}
+
+#ifdef DMEVENTD
+static int _get_snapshot_dso_path(struct cmd_context *cmd, char **dso)
+{
+	char *path;
+	const char *libpath;
+
+	if (!(path = dm_pool_alloc(cmd->mem, PATH_MAX))) {
+		log_error("Failed to allocate dmeventd library path.");
+		return 0;
+	}
+
+	libpath = find_config_tree_str(cmd, "dmeventd/snapshot_library", NULL);
+	if (!libpath)
+		return 0;
+
+	get_shared_library_path(cmd, libpath, path, PATH_MAX);
+
+	*dso = path;
+
+	return 1;
+}
+
+static struct dm_event_handler *_create_dm_event_handler(const char *dmname,
+							 const char *dso,
+							 const int timeout,
+							 enum dm_event_mask mask)
+{
+	struct dm_event_handler *dmevh;
+
+	if (!(dmevh = dm_event_handler_create()))
+		return_0;
+
+       if (dm_event_handler_set_dso(dmevh, dso))
+		goto fail;
+
+	if (dm_event_handler_set_dev_name(dmevh, dmname))
+		goto fail;
+
+	dm_event_handler_set_timeout(dmevh, timeout);
+	dm_event_handler_set_event_mask(dmevh, mask);
+	return dmevh;
+
+fail:
+	dm_event_handler_destroy(dmevh);
+	return NULL;
+}
+
+static int _target_registered(struct lv_segment *seg, int *pending)
+{
+	char *dso, *name;
+	struct logical_volume *lv;
+	struct volume_group *vg;
+	enum dm_event_mask evmask = 0;
+	struct dm_event_handler *dmevh;
+
+	lv = seg->lv;
+	vg = lv->vg;
+
+	*pending = 0;
+	if (!_get_snapshot_dso_path(vg->cmd, &dso))
+		return_0;
+
+	if (!(name = build_dm_name(vg->cmd->mem, vg->name, seg->cow->name, NULL)))
+		return_0;
+
+	if (!(dmevh = _create_dm_event_handler(name, dso, 0, DM_EVENT_ALL_ERRORS)))
+		return_0;
+
+	if (dm_event_get_registered_device(dmevh, 0)) {
+		dm_event_handler_destroy(dmevh);
+		return 0;
+	}
+
+	evmask = dm_event_handler_get_event_mask(dmevh);
+	if (evmask & DM_EVENT_REGISTRATION_PENDING) {
+		*pending = 1;
+		evmask &= ~DM_EVENT_REGISTRATION_PENDING;
+	}
+
+	dm_event_handler_destroy(dmevh);
+
+	return evmask;
+}
+
+/* FIXME This gets run while suspended and performs banned operations. */
+static int _target_set_events(struct lv_segment *seg,
+			      int events __attribute((unused)), int set)
+{
+	char *dso, *name;
+	struct volume_group *vg = seg->lv->vg;
+	struct dm_event_handler *dmevh;
+	int r;
+
+	if (!_get_snapshot_dso_path(vg->cmd, &dso))
+		return_0;
+
+	if (!(name = build_dm_name(vg->cmd->mem, vg->name, seg->cow->name, NULL)))
+		return_0;
+
+	/* FIXME: make timeout configurable */
+	if (!(dmevh = _create_dm_event_handler(name, dso, 10,
+		DM_EVENT_ALL_ERRORS|DM_EVENT_TIMEOUT)))
+		return_0;
+
+	r = set ? dm_event_register_handler(dmevh) : dm_event_unregister_handler(dmevh);
+	dm_event_handler_destroy(dmevh);
+	if (!r)
+		return_0;
+
+	log_info("%s %s for events", set ? "Registered" : "Unregistered", name);
+
+	return 1;
+}
+
+static int _target_register_events(struct lv_segment *seg,
+				   int events)
+{
+	return _target_set_events(seg, events, 1);
+}
+
+static int _target_unregister_events(struct lv_segment *seg,
+				     int events)
+{
+	return _target_set_events(seg, events, 0);
+}
+
+#endif /* DMEVENTD */
+#endif
+
+static int _snap_modules_needed(struct dm_pool *mem,
+				const struct lv_segment *seg __attribute((unused)),
+				struct dm_list *modules)
+{
+	if (!str_list_add(mem, modules, "snapshot")) {
+		log_error("snapshot string list allocation failed");
+		return 0;
+	}
+
+	return 1;
+}
+
+static void _snap_destroy(const struct segment_type *segtype)
+{
+	dm_free((void *)segtype);
+}
+
+static struct segtype_handler _snapshot_ops = {
+	.name = _snap_name,
+	.text_import = _snap_text_import,
+	.text_export = _snap_text_export,
+#ifdef DEVMAPPER_SUPPORT
+	.target_percent = _snap_target_percent,
+	.target_present = _snap_target_present,
+#ifdef DMEVENTD
+	.target_monitored = _target_registered,
+	.target_monitor_events = _target_register_events,
+	.target_unmonitor_events = _target_unregister_events,
+#endif
+#endif
+	.modules_needed = _snap_modules_needed,
+	.destroy = _snap_destroy,
+};
+
+#ifdef SNAPSHOT_INTERNAL
+struct segment_type *init_snapshot_segtype(struct cmd_context *cmd)
+#else				/* Shared */
+struct segment_type *init_segtype(struct cmd_context *cmd);
+struct segment_type *init_segtype(struct cmd_context *cmd)
+#endif
+{
+	struct segment_type *segtype = dm_malloc(sizeof(*segtype));
+#ifdef DMEVENTD
+	char *dso;
+#endif
+
+	if (!segtype)
+		return_NULL;
+
+	segtype->cmd = cmd;
+	segtype->ops = &_snapshot_ops;
+	segtype->name = "snapshot";
+	segtype->private = NULL;
+	segtype->flags = SEG_SNAPSHOT;
+
+#ifdef DMEVENTD
+	if (_get_snapshot_dso_path(cmd, &dso))
+		segtype->flags |= SEG_MONITORED;
+#endif
+	log_very_verbose("Initialised segtype: %s", segtype->name);
+
+	return segtype;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/striped/striped.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/striped/striped.c
diff -N src/external/gpl2/lvm2tools/dist/lib/striped/striped.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/striped/striped.c	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,232 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "toolcontext.h"
+#include "segtype.h"
+#include "display.h"
+#include "text_export.h"
+#include "text_import.h"
+#include "config.h"
+#include "str_list.h"
+#include "targets.h"
+#include "lvm-string.h"
+#include "activate.h"
+#include "pv_alloc.h"
+#include "metadata.h"
+
+static const char *_striped_name(const struct lv_segment *seg)
+{
+	return (seg->area_count == 1) ? "linear" : seg->segtype->name;
+}
+
+static void _striped_display(const struct lv_segment *seg)
+{
+	uint32_t s;
+
+	if (seg->area_count == 1)
+		display_stripe(seg, 0, "  ");
+	else {
+		log_print("  Stripes\t\t%u", seg->area_count);
+		log_print("  Stripe size\t\t%u KB", seg->stripe_size / 2);
+
+		for (s = 0; s < seg->area_count; s++) {
+			log_print("  Stripe %d:", s);
+			display_stripe(seg, s, "    ");
+		}
+	}
+	log_print(" ");
+}
+
+static int _striped_text_import_area_count(struct config_node *sn, uint32_t *area_count)
+{
+	if (!get_config_uint32(sn, "stripe_count", area_count)) {
+		log_error("Couldn't read 'stripe_count' for "
+			  "segment '%s'.", sn->key);
+		return 0;
+	}
+
+	return 1;
+}
+
+static int _striped_text_import(struct lv_segment *seg, const struct config_node *sn,
+			struct dm_hash_table *pv_hash)
+{
+	struct config_node *cn;
+
+	if ((seg->area_count != 1) &&
+	    !get_config_uint32(sn, "stripe_size", &seg->stripe_size)) {
+		log_error("Couldn't read stripe_size for segment '%s'.",
+			  sn->key);
+		return 0;
+	}
+
+	if (!(cn = find_config_node(sn, "stripes"))) {
+		log_error("Couldn't find stripes array for segment "
+			  "'%s'.", sn->key);
+		return 0;
+	}
+
+	seg->area_len /= seg->area_count;
+
+	return text_import_areas(seg, sn, cn, pv_hash, 0);
+}
+
+static int _striped_text_export(const struct lv_segment *seg, struct formatter *f)
+{
+
+	outf(f, "stripe_count = %u%s", seg->area_count,
+	     (seg->area_count == 1) ? "\t# linear" : "");
+
+	if (seg->area_count > 1)
+		out_size(f, (uint64_t) seg->stripe_size,
+			 "stripe_size = %u", seg->stripe_size);
+
+	return out_areas(f, seg, "stripe");
+}
+
+/*
+ * Test whether two segments could be merged by the current merging code
+ */
+static int _striped_segments_compatible(struct lv_segment *first,
+				struct lv_segment *second)
+{
+	uint32_t width;
+	unsigned s;
+
+	if ((first->area_count != second->area_count) ||
+	    (first->stripe_size != second->stripe_size))
+		return 0;
+
+	for (s = 0; s < first->area_count; s++) {
+
+		/* FIXME Relax this to first area type != second area type */
+		/*       plus the additional AREA_LV checks needed */
+		if ((seg_type(first, s) != AREA_PV) ||
+		    (seg_type(second, s) != AREA_PV))
+			return 0;
+
+		width = first->area_len;
+
+		if ((seg_pv(first, s) !=
+		     seg_pv(second, s)) ||
+		    (seg_pe(first, s) + width !=
+		     seg_pe(second, s)))
+			return 0;
+	}
+
+	if (!str_list_lists_equal(&first->tags, &second->tags))
+		return 0;
+
+	return 1;
+}
+
+static int _striped_merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
+{
+	uint32_t s;
+
+	if (!_striped_segments_compatible(seg1, seg2))
+		return 0;
+
+	seg1->len += seg2->len;
+	seg1->area_len += seg2->area_len;
+
+	for (s = 0; s < seg1->area_count; s++)
+		if (seg_type(seg1, s) == AREA_PV)
+			merge_pv_segments(seg_pvseg(seg1, s),
+					  seg_pvseg(seg2, s));
+
+	return 1;
+}
+
+#ifdef DEVMAPPER_SUPPORT
+static int _striped_add_target_line(struct dev_manager *dm,
+				struct dm_pool *mem __attribute((unused)),
+				struct cmd_context *cmd __attribute((unused)),
+				void **target_state __attribute((unused)),
+				struct lv_segment *seg,
+				struct dm_tree_node *node, uint64_t len,
+				uint32_t *pvmove_mirror_count __attribute((unused)))
+{
+	if (!seg->area_count) {
+		log_error("Internal error: striped add_target_line called "
+			  "with no areas for %s.", seg->lv->name);
+		return 0;
+	}
+	if (seg->area_count == 1) {
+		if (!dm_tree_node_add_linear_target(node, len))
+			return_0;
+	} else if (!dm_tree_node_add_striped_target(node, len,
+						  seg->stripe_size))
+		return_0;
+
+	return add_areas_line(dm, seg, node, 0u, seg->area_count);
+}
+
+static int _striped_target_present(const struct lv_segment *seg __attribute((unused)),
+				   unsigned *attributes __attribute((unused)))
+{
+	static int _striped_checked = 0;
+	static int _striped_present = 0;
+
+	if (!_striped_checked)
+		_striped_present = target_present("linear", 0) &&
+			  target_present("striped", 0);
+
+	_striped_checked = 1;
+
+	return _striped_present;
+}
+#endif
+
+static void _striped_destroy(const struct segment_type *segtype)
+{
+	dm_free((void *)segtype);
+}
+
+static struct segtype_handler _striped_ops = {
+	.name = _striped_name,
+	.display = _striped_display,
+	.text_import_area_count = _striped_text_import_area_count,
+	.text_import = _striped_text_import,
+	.text_export = _striped_text_export,
+	.merge_segments = _striped_merge_segments,
+#ifdef DEVMAPPER_SUPPORT
+	.add_target_line = _striped_add_target_line,
+	.target_present = _striped_target_present,
+#endif
+	.destroy = _striped_destroy,
+};
+
+struct segment_type *init_striped_segtype(struct cmd_context *cmd)
+{
+	struct segment_type *segtype = dm_malloc(sizeof(*segtype));
+
+	if (!segtype)
+		return_NULL;
+
+	segtype->cmd = cmd;
+	segtype->ops = &_striped_ops;
+	segtype->name = "striped";
+	segtype->private = NULL;
+	segtype->flags =
+	    SEG_CAN_SPLIT | SEG_AREAS_STRIPED | SEG_FORMAT1_SUPPORT;
+
+	log_very_verbose("Initialised segtype: %s", segtype->name);
+
+	return segtype;
+}
Index: src/external/gpl2/lvm2tools/dist/lib/uuid/uuid.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/uuid/uuid.c
diff -N src/external/gpl2/lvm2tools/dist/lib/uuid/uuid.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/uuid/uuid.c	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,219 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "uuid.h"
+
+#include <assert.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <ctype.h>
+
+static const char _c[] =
+    "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#";
+
+static int _built_inverse;
+static char _inverse_c[256];
+
+int lvid_create(union lvid *lvid, struct id *vgid)
+{
+	memcpy(lvid->id, vgid, sizeof(*lvid->id));
+	return id_create(&lvid->id[1]);
+}
+
+void uuid_from_num(char *uuid, uint32_t num)
+{
+	unsigned i;
+
+	for (i = ID_LEN; i; i--) {
+		uuid[i - 1] = _c[num % (sizeof(_c) - 1)];
+		num /= sizeof(_c) - 1;
+	}
+}
+
+int lvid_from_lvnum(union lvid *lvid, struct id *vgid, uint32_t lv_num)
+{
+	int i;
+
+	memcpy(lvid->id, vgid, sizeof(*lvid->id));
+
+	for (i = ID_LEN; i; i--) {
+		lvid->id[1].uuid[i - 1] = _c[lv_num % (sizeof(_c) - 1)];
+		lv_num /= sizeof(_c) - 1;
+	}
+
+	lvid->s[sizeof(lvid->s) - 1] = '\0';
+
+	return 1;
+}
+
+int lvnum_from_lvid(union lvid *lvid)
+{
+	int i, lv_num = 0;
+	char *c;
+
+	for (i = 0; i < ID_LEN; i++) {
+		lv_num *= sizeof(_c) - 1;
+		if ((c = strchr(_c, lvid->id[1].uuid[i])))
+			lv_num += (int) (c - _c);
+		if (lv_num < 0)
+			lv_num = 0;
+	}
+
+	return lv_num;
+}
+
+int lvid_in_restricted_range(union lvid *lvid)
+{
+	int i;
+
+	for (i = 0; i < ID_LEN - 3; i++)
+		if (lvid->id[1].uuid[i] != '0')
+			return 0;
+
+	for (i = ID_LEN - 3; i < ID_LEN; i++)
+		if (!isdigit(lvid->id[1].uuid[i]))
+			return 0;
+
+	return 1;
+}
+
+
+int id_create(struct id *id)
+{
+	int randomfile;
+	unsigned i;
+	size_t len = sizeof(id->uuid);
+
+	memset(id->uuid, 0, len);
+	if ((randomfile = open("/dev/urandom", O_RDONLY)) < 0) {
+		log_sys_error("open", "id_create: /dev/urandom");
+		return 0;
+	}
+
+	if (read(randomfile, id->uuid, len) != (ssize_t) len) {
+		log_sys_error("read", "id_create: /dev/urandom");
+		if (close(randomfile))
+			stack;
+		return 0;
+	}
+	if (close(randomfile))
+		stack;
+
+	/*
+	 * Skip out the last 2 chars in randomized creation for LVM1
+	 * backwards compatibility.
+	 */
+	for (i = 0; i < len; i++)
+		id->uuid[i] = _c[id->uuid[i] % (sizeof(_c) - 3)];
+
+	return 1;
+}
+
+/*
+ * The only validity check we have is that
+ * the uuid just contains characters from
+ * '_c'.  A checksum would have been nice :(
+ */
+static void _build_inverse(void)
+{
+	const char *ptr;
+
+	if (_built_inverse)
+		return;
+
+	memset(_inverse_c, 0, sizeof(_inverse_c));
+
+	for (ptr = _c; *ptr; ptr++)
+		_inverse_c[(int) *ptr] = (char) 0x1;
+}
+
+int id_valid(struct id *id)
+{
+	int i;
+
+	_build_inverse();
+
+	for (i = 0; i < ID_LEN; i++)
+		if (!_inverse_c[id->uuid[i]]) {
+			log_err("UUID contains invalid character");
+			return 0;
+		}
+
+	return 1;
+}
+
+int id_equal(const struct id *lhs, const struct id *rhs)
+{
+	return !memcmp(lhs->uuid, rhs->uuid, sizeof(lhs->uuid));
+}
+
+#define GROUPS (ID_LEN / 4)
+
+int id_write_format(const struct id *id, char *buffer, size_t size)
+{
+	int i, tot;
+
+	static unsigned group_size[] = { 6, 4, 4, 4, 4, 4, 6 };
+
+	assert(ID_LEN == 32);
+
+	/* split into groups separated by dashes */
+	if (size < (32 + 6 + 1)) {
+		log_err("Couldn't write uuid, buffer too small.");
+		return 0;
+	}
+
+	for (i = 0, tot = 0; i < 7; i++) {
+		memcpy(buffer, id->uuid + tot, group_size[i]);
+		buffer += group_size[i];
+		tot += group_size[i];
+		*buffer++ = '-';
+	}
+
+	*--buffer = '\0';
+	return 1;
+}
+
+int id_read_format(struct id *id, const char *buffer)
+{
+	int out = 0;
+
+	/* just strip out any dashes */
+	while (*buffer) {
+
+		if (*buffer == '-') {
+			buffer++;
+			continue;
+		}
+
+		if (out >= ID_LEN) {
+			log_err("Too many characters to be uuid.");
+			return 0;
+		}
+
+		id->uuid[out++] = *buffer++;
+	}
+
+	if (out != ID_LEN) {
+		log_err("Couldn't read uuid, incorrect number of characters.");
+		return 0;
+	}
+
+	return id_valid(id);
+}
Index: src/external/gpl2/lvm2tools/dist/lib/uuid/uuid.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/uuid/uuid.h
diff -N src/external/gpl2/lvm2tools/dist/lib/uuid/uuid.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/uuid/uuid.h	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,59 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_UUID_H
+#define _LVM_UUID_H
+
+#define ID_LEN 32
+#define ID_LEN_S "32"
+
+struct id {
+	int8_t uuid[ID_LEN];
+};
+
+/*
+ * Unique logical volume identifier
+ * With format1 this is VG uuid + LV uuid + '\0' + padding
+ */
+union lvid {
+	struct id id[2];
+	char s[2 * sizeof(struct id) + 1 + 7];
+};
+
+int lvid_from_lvnum(union lvid *lvid, struct id *vgid, uint32_t lv_num);
+int lvnum_from_lvid(union lvid *lvid);
+int lvid_in_restricted_range(union lvid *lvid);
+
+void uuid_from_num(char *uuid, uint32_t num);
+
+int lvid_create(union lvid *lvid, struct id *vgid);
+int id_create(struct id *id);
+int id_valid(struct id *id);
+int id_equal(const struct id *lhs, const struct id *rhs);
+
+/*
+ * Fills 'buffer' with a more human readable form
+ * of the uuid.
+ */
+int id_write_format(const struct id *id, char *buffer, size_t size);
+
+/*
+ * Reads a formatted uuid.
+ */
+int id_read_format(struct id *id, const char *buffer);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/lib/zero/zero.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/lib/zero/zero.c
diff -N src/external/gpl2/lvm2tools/dist/lib/zero/zero.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/lib/zero/zero.c	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,114 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "toolcontext.h"
+#include "segtype.h"
+#include "display.h"
+#include "text_export.h"
+#include "text_import.h"
+#include "config.h"
+#include "str_list.h"
+#include "targets.h"
+#include "lvm-string.h"
+#include "activate.h"
+#include "metadata.h"
+
+static const char *_zero_name(const struct lv_segment *seg)
+{
+	return seg->segtype->name;
+}
+
+static int _zero_merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
+{
+	seg1->len += seg2->len;
+	seg1->area_len += seg2->area_len;
+
+	return 1;
+}
+
+#ifdef DEVMAPPER_SUPPORT
+static int _zero_add_target_line(struct dev_manager *dm __attribute((unused)),
+				 struct dm_pool *mem __attribute((unused)),
+				 struct cmd_context *cmd __attribute((unused)),
+				 void **target_state __attribute((unused)),
+				 struct lv_segment *seg __attribute((unused)),
+				 struct dm_tree_node *node,uint64_t len,
+				 uint32_t *pvmove_mirror_count __attribute((unused)))
+{
+	return dm_tree_node_add_zero_target(node, len);
+}
+
+static int _zero_target_present(const struct lv_segment *seg __attribute((unused)),
+				unsigned *attributes __attribute((unused)))
+{
+	static int _zero_checked = 0;
+	static int _zero_present = 0;
+
+	if (!_zero_checked)
+		_zero_present = target_present("zero", 0);
+
+	_zero_checked = 1;
+
+	return _zero_present;
+}
+#endif
+
+static int _zero_modules_needed(struct dm_pool *mem,
+				const struct lv_segment *seg __attribute((unused)),
+				struct dm_list *modules)
+{
+	if (!str_list_add(mem, modules, "zero")) {
+		log_error("zero module string list allocation failed");
+		return 0;
+	}
+
+	return 1;
+}
+
+static void _zero_destroy(const struct segment_type *segtype)
+{
+	dm_free((void *) segtype);
+}
+
+static struct segtype_handler _zero_ops = {
+	.name = _zero_name,
+	.merge_segments = _zero_merge_segments,
+#ifdef DEVMAPPER_SUPPORT
+	.add_target_line = _zero_add_target_line,
+	.target_present = _zero_target_present,
+#endif
+	.modules_needed = _zero_modules_needed,
+	.destroy = _zero_destroy,
+};
+
+struct segment_type *init_zero_segtype(struct cmd_context *cmd)
+{
+	struct segment_type *segtype = dm_malloc(sizeof(*segtype));
+
+	if (!segtype)
+		return_NULL;
+
+	segtype->cmd = cmd;
+	segtype->ops = &_zero_ops;
+	segtype->name = "zero";
+	segtype->private = NULL;
+	segtype->flags = SEG_CAN_SPLIT | SEG_VIRTUAL | SEG_CANNOT_BE_ZEROED;
+
+	log_very_verbose("Initialised segtype: %s", segtype->name);
+
+	return segtype;
+}
Index: src/external/gpl2/lvm2tools/dist/libdm/.exported_symbols
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/.exported_symbols
diff -N src/external/gpl2/lvm2tools/dist/libdm/.exported_symbols
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/.exported_symbols	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,150 @@
+dm_lib_release
+dm_lib_exit
+dm_driver_version
+dm_create_dir
+dm_fclose
+dm_get_library_version
+dm_log
+dm_log_init
+dm_log_init_verbose
+dm_task_create
+dm_task_destroy
+dm_task_set_name
+dm_task_set_uuid
+dm_task_get_driver_version
+dm_task_get_info
+dm_task_get_deps
+dm_task_get_name
+dm_task_get_names
+dm_task_get_versions
+dm_task_get_uuid
+dm_task_get_read_ahead
+dm_task_set_ro
+dm_task_set_newname
+dm_task_set_event_nr
+dm_task_set_major
+dm_task_set_minor
+dm_task_set_sector
+dm_task_set_message
+dm_task_set_uid
+dm_task_set_gid
+dm_task_set_mode
+dm_task_set_read_ahead
+dm_task_suppress_identical_reload
+dm_task_add_target
+dm_task_no_flush
+dm_task_no_open_count
+dm_task_skip_lockfs
+dm_task_update_nodes
+dm_task_run
+dm_get_next_target
+dm_set_dev_dir
+dm_dir
+dm_format_dev
+dm_tree_create
+dm_tree_free
+dm_tree_add_dev
+dm_tree_add_new_dev
+dm_tree_node_get_name
+dm_tree_node_get_uuid
+dm_tree_node_get_info
+dm_tree_node_get_context
+dm_tree_node_num_children
+dm_tree_node_num_parents
+dm_tree_find_node
+dm_tree_find_node_by_uuid
+dm_tree_next_child
+dm_tree_next_parent
+dm_tree_deactivate_children
+dm_tree_activate_children
+dm_tree_preload_children
+dm_tree_suspend_children
+dm_tree_children_use_uuid
+dm_tree_node_add_snapshot_origin_target
+dm_tree_node_add_snapshot_target
+dm_tree_node_add_error_target
+dm_tree_node_add_zero_target
+dm_tree_node_add_linear_target
+dm_tree_node_add_striped_target
+dm_tree_node_add_mirror_target
+dm_tree_node_add_mirror_target_log
+dm_tree_node_add_target_area
+dm_tree_node_set_read_ahead
+dm_tree_skip_lockfs
+dm_tree_use_no_flush_suspend
+dm_is_dm_major
+dm_mknodes
+dm_malloc_aux
+dm_malloc_aux_debug
+dm_strdup_aux
+dm_free_aux
+dm_realloc_aux
+dm_dump_memory_debug
+dm_bounds_check_debug
+dm_pool_create
+dm_pool_destroy
+dm_pool_alloc
+dm_pool_alloc_aligned
+dm_pool_empty
+dm_pool_free
+dm_pool_begin_object
+dm_pool_grow_object
+dm_pool_end_object
+dm_pool_abandon_object
+dm_pool_strdup
+dm_pool_strndup
+dm_pool_zalloc
+dm_bitset_create
+dm_bitset_destroy
+dm_bit_union
+dm_bit_get_first
+dm_bit_get_next
+dm_hash_create
+dm_hash_destroy
+dm_hash_wipe
+dm_hash_lookup
+dm_hash_insert
+dm_hash_remove
+dm_hash_lookup_binary
+dm_hash_insert_binary
+dm_hash_remove_binary
+dm_hash_get_num_entries
+dm_hash_iter
+dm_hash_get_key
+dm_hash_get_data
+dm_hash_get_first
+dm_hash_get_next
+dm_set_selinux_context
+dm_task_set_geometry
+dm_split_lvm_name
+dm_split_words
+dm_snprintf
+dm_basename
+dm_asprintf
+dm_report_init
+dm_report_object
+dm_report_output
+dm_report_free
+dm_report_get_private
+dm_report_field_string
+dm_report_field_int
+dm_report_field_int32
+dm_report_field_uint32
+dm_report_field_uint64
+dm_report_field_set_value
+dm_report_set_output_field_name_prefix
+dm_regex_create
+dm_regex_match
+dm_list_init
+dm_list_add
+dm_list_add_h
+dm_list_del
+dm_list_move
+dm_list_empty
+dm_list_start
+dm_list_end
+dm_list_first
+dm_list_last
+dm_list_prev
+dm_list_next
+dm_list_size
Index: src/external/gpl2/lvm2tools/dist/libdm/Makefile.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/Makefile.in
diff -N src/external/gpl2/lvm2tools/dist/libdm/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/Makefile.in	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,106 @@
+#
+# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+# Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+#
+# This file is part of the device-mapper userspace tools.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU Lesser General Public License v.2.1.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+SOURCES =\
+	datastruct/bitset.c \
+	datastruct/hash.c \
+	datastruct/list.c \
+	libdm-common.c \
+	libdm-file.c \
+	libdm-deptree.c \
+	libdm-string.c \
+	libdm-report.c \
+	mm/dbg_malloc.c \
+	mm/pool.c \
+	regex/matcher.c \
+	regex/parse_rx.c \
+	regex/ttree.c \
+	$(interface)/libdm-iface.c
+
+INCLUDES = -I$(interface) -I.
+
+LIB_STATIC = $(interface)/libdevmapper.a
+
+ifeq ("@LIB_SUFFIX@","dylib")
+  LIB_SHARED = $(interface)/libdevmapper.dylib
+else
+  LIB_SHARED = $(interface)/libdevmapper.so
+endif
+VERSIONED_SHLIB = libdevmapper.$(LIB_SUFFIX).$(LIB_VERSION_DM)
+LIB_VERSION = $(LIB_VERSION_DM)
+
+DEFS += -DDM_DEVICE_UID=@DM_DEVICE_UID@ -DDM_DEVICE_GID=@DM_DEVICE_GID@ \
+	-DDM_DEVICE_MODE=@DM_DEVICE_MODE@
+
+include ../make.tmpl
+
+device-mapper: all
+
+.PHONY: install_dynamic install_static install_include \
+	install_ioctl install_ioctl_static \
+	install_pkgconfig
+
+INSTALL_TYPE = install_dynamic
+
+ifeq ("@STATIC_LINK@", "yes")
+  INSTALL_TYPE += install_static
+endif
+
+ifeq ("@PKGCONFIG@", "yes")
+  INSTALL_TYPE += install_pkgconfig
+endif
+
+install: $(INSTALL_TYPE) install_include
+
+install_device-mapper: install
+
+install_include:
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper.h \
+		$(includedir)/libdevmapper.h
+
+install_dynamic: install_@interface@
+	$(LN_S) -f libdevmapper.$(LIB_SUFFIX).$(LIB_VERSION_DM) \
+		$(libdir)/libdevmapper.$(LIB_SUFFIX)
+
+install_static: install_@interface@_static
+	$(LN_S) -f libdevmapper.a.$(LIB_VERSION_DM) $(libdir)/libdevmapper.a
+
+install_ioctl: ioctl/libdevmapper.$(LIB_SUFFIX)
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
+		$(libdir)/libdevmapper.$(LIB_SUFFIX).$(LIB_VERSION_DM)
+
+install_pkgconfig:
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper.pc \
+		$(usrlibdir)/pkgconfig/devmapper.pc
+
+install_ioctl_static: ioctl/libdevmapper.a
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
+		$(libdir)/libdevmapper.a.$(LIB_VERSION_DM)
+
+$(VERSIONED_SHLIB): %.$(LIB_SUFFIX).$(LIB_VERSION_DM): $(interface)/%.$(LIB_SUFFIX)
+	rm -f $@
+	$(LN_S) $< $@
+	rm -f libdevmapper.so
+	$(LN_S) $< libdevmapper.so
+
+.PHONY: distclean_lib distclean
+
+distclean_lib:
+	$(RM) libdevmapper.pc
+
+distclean: distclean_lib
Index: src/external/gpl2/lvm2tools/dist/libdm/libdevmapper.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/libdevmapper.h
diff -N src/external/gpl2/lvm2tools/dist/libdm/libdevmapper.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/libdevmapper.h	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,981 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef LIB_DEVICE_MAPPER_H
+#define LIB_DEVICE_MAPPER_H
+
+#include <inttypes.h>
+#include <stdarg.h>
+#include <sys/types.h>
+
+#ifdef linux
+#  include <linux/types.h>
+#endif
+
+#include <limits.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/*****************************************************************
+ * The first section of this file provides direct access to the 
+ * individual device-mapper ioctls.
+ ****************************************************************/
+
+/*
+ * Since it is quite laborious to build the ioctl
+ * arguments for the device-mapper people are
+ * encouraged to use this library.
+ *
+ * You will need to build a struct dm_task for
+ * each ioctl command you want to execute.
+ */
+
+typedef void (*dm_log_fn) (int level, const char *file, int line,
+			   const char *f, ...)
+    __attribute__ ((format(printf, 4, 5)));
+
+/*
+ * The library user may wish to register their own
+ * logging function, by default errors go to stderr.
+ * Use dm_log_init(NULL) to restore the default log fn.
+ */
+void dm_log_init(dm_log_fn fn);
+void dm_log_init_verbose(int level);
+
+enum {
+	DM_DEVICE_CREATE,
+	DM_DEVICE_RELOAD,
+	DM_DEVICE_REMOVE,
+	DM_DEVICE_REMOVE_ALL,
+
+	DM_DEVICE_SUSPEND,
+	DM_DEVICE_RESUME,
+
+	DM_DEVICE_INFO,
+	DM_DEVICE_DEPS,
+	DM_DEVICE_RENAME,
+
+	DM_DEVICE_VERSION,
+
+	DM_DEVICE_STATUS,
+	DM_DEVICE_TABLE,
+	DM_DEVICE_WAITEVENT,
+
+	DM_DEVICE_LIST,
+
+	DM_DEVICE_CLEAR,
+
+	DM_DEVICE_MKNODES,
+
+	DM_DEVICE_LIST_VERSIONS,
+	
+	DM_DEVICE_TARGET_MSG,
+
+	DM_DEVICE_SET_GEOMETRY
+};
+
+struct dm_task;
+
+struct dm_task *dm_task_create(int type);
+void dm_task_destroy(struct dm_task *dmt);
+
+int dm_task_set_name(struct dm_task *dmt, const char *name);
+int dm_task_set_uuid(struct dm_task *dmt, const char *uuid);
+
+/*
+ * Retrieve attributes after an info.
+ */
+struct dm_info {
+	int exists;
+	int suspended;
+	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 */
+
+	int32_t target_count;
+};
+
+struct dm_deps {
+	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];
+};
+
+struct dm_versions {
+	uint32_t next;		/* Offset to next struct from start of this struct */
+	uint32_t version[3];
+
+	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(const struct dm_task *dmt);
+const char *dm_task_get_uuid(const 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);
+struct dm_versions *dm_task_get_versions(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_uid(struct dm_task *dmt, uid_t uid);
+int dm_task_set_gid(struct dm_task *dmt, gid_t gid);
+int dm_task_set_mode(struct dm_task *dmt, mode_t mode);
+int dm_task_set_event_nr(struct dm_task *dmt, uint32_t event_nr);
+int dm_task_set_geometry(struct dm_task *dmt, const char *cylinders, const char *heads, const char *sectors, const char *start);
+int dm_task_set_message(struct dm_task *dmt, const char *message);
+int dm_task_set_sector(struct dm_task *dmt, uint64_t sector);
+int dm_task_no_flush(struct dm_task *dmt);
+int dm_task_no_open_count(struct dm_task *dmt);
+int dm_task_skip_lockfs(struct dm_task *dmt);
+int dm_task_suppress_identical_reload(struct dm_task *dmt);
+
+/*
+ * Control read_ahead.
+ */
+#define DM_READ_AHEAD_AUTO UINT32_MAX	/* Use kernel default readahead */
+#define DM_READ_AHEAD_NONE 0		/* Disable readahead */
+
+#define DM_READ_AHEAD_MINIMUM_FLAG	0x1	/* Value supplied is minimum */
+
+/*
+ * Read ahead is set with DM_DEVICE_CREATE with a table or DM_DEVICE_RESUME.
+ */
+int dm_task_set_read_ahead(struct dm_task *dmt, uint32_t read_ahead,
+			   uint32_t read_ahead_flags);
+uint32_t dm_task_get_read_ahead(const struct dm_task *dmt,
+				uint32_t *read_ahead);
+
+/*
+ * Use these to prepare for a create or reload.
+ */
+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.
+ */
+#define DM_FORMAT_DEV_BUFSIZE	13	/* Minimum bufsize to handle worst case. */
+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,
+			 char **target_type, char **params);
+
+/*
+ * Call this to actually run the ioctl.
+ */
+int dm_task_run(struct dm_task *dmt);
+
+/*
+ * Call this to make or remove the device nodes associated with previously
+ * issued commands.
+ */
+void dm_task_update_nodes(void);
+
+/*
+ * Configure the device-mapper directory
+ */
+int dm_set_dev_dir(const char *dir);
+const char *dm_dir(void);
+
+/*
+ * Determine whether a major number belongs to device-mapper or not.
+ */
+int dm_is_dm_major(uint32_t major);
+
+/*
+ * Release library resources
+ */
+void dm_lib_release(void);
+void dm_lib_exit(void) __attribute((destructor));
+
+/*
+ * Use NULL for all devices.
+ */
+int dm_mknodes(const char *name);
+int dm_driver_version(char *version, size_t size);
+
+/******************************************************
+ * Functions to build and manipulate trees of devices *
+ ******************************************************/
+struct dm_tree;
+struct dm_tree_node;
+
+/*
+ * Initialise an empty dependency tree.
+ *
+ * The tree consists of a root node together with one node for each mapped 
+ * device which has child nodes for each device referenced in its table.
+ *
+ * Every node in the tree has one or more children and one or more parents.
+ *
+ * The root node is the parent/child of every node that doesn't have other 
+ * parents/children.
+ */
+struct dm_tree *dm_tree_create(void);
+void dm_tree_free(struct dm_tree *tree);
+
+/*
+ * Add nodes to the tree for a given device and all the devices it uses.
+ */
+int dm_tree_add_dev(struct dm_tree *tree, uint32_t major, uint32_t minor);
+
+/*
+ * Add a new node to the tree if it doesn't already exist.
+ */
+struct dm_tree_node *dm_tree_add_new_dev(struct dm_tree *tree,
+					 const char *name,
+					 const char *uuid,
+					 uint32_t major, uint32_t minor,
+					 int read_only,
+					 int clear_inactive,
+					 void *context);
+
+/*
+ * Search for a node in the tree.
+ * Set major and minor to 0 or uuid to NULL to get the root node.
+ */
+struct dm_tree_node *dm_tree_find_node(struct dm_tree *tree,
+					  uint32_t major,
+					  uint32_t minor);
+struct dm_tree_node *dm_tree_find_node_by_uuid(struct dm_tree *tree,
+						  const char *uuid);
+
+/*
+ * Use this to walk through all children of a given node.
+ * Set handle to NULL in first call.
+ * Returns NULL after the last child.
+ * Set inverted to use inverted tree.
+ */
+struct dm_tree_node *dm_tree_next_child(void **handle,
+					   struct dm_tree_node *parent,
+					   uint32_t inverted);
+
+/*
+ * Get properties of a node.
+ */
+const char *dm_tree_node_get_name(struct dm_tree_node *node);
+const char *dm_tree_node_get_uuid(struct dm_tree_node *node);
+const struct dm_info *dm_tree_node_get_info(struct dm_tree_node *node);
+void *dm_tree_node_get_context(struct dm_tree_node *node);
+
+/*
+ * Returns the number of children of the given node (excluding the root node).
+ * Set inverted for the number of parents.
+ */
+int dm_tree_node_num_children(struct dm_tree_node *node, uint32_t inverted);
+
+/*
+ * Deactivate a device plus all dependencies.
+ * Ignores devices that don't have a uuid starting with uuid_prefix.
+ */
+int dm_tree_deactivate_children(struct dm_tree_node *dnode,
+				   const char *uuid_prefix,
+				   size_t uuid_prefix_len);
+/*
+ * Preload/create a device plus all dependencies.
+ * Ignores devices that don't have a uuid starting with uuid_prefix.
+ */
+int dm_tree_preload_children(struct dm_tree_node *dnode,
+			     const char *uuid_prefix,
+			     size_t uuid_prefix_len);
+
+/*
+ * Resume a device plus all dependencies.
+ * Ignores devices that don't have a uuid starting with uuid_prefix.
+ */
+int dm_tree_activate_children(struct dm_tree_node *dnode,
+			      const char *uuid_prefix,
+			      size_t uuid_prefix_len);
+
+/*
+ * Suspend a device plus all dependencies.
+ * Ignores devices that don't have a uuid starting with uuid_prefix.
+ */
+int dm_tree_suspend_children(struct dm_tree_node *dnode,
+				   const char *uuid_prefix,
+				   size_t uuid_prefix_len);
+
+/*
+ * Skip the filesystem sync when suspending.
+ * Does nothing with other functions.
+ * Use this when no snapshots are involved.
+ */ 
+void dm_tree_skip_lockfs(struct dm_tree_node *dnode);
+
+/*
+ * Set the 'noflush' flag when suspending devices.
+ * If the kernel supports it, instead of erroring outstanding I/O that
+ * cannot be completed, the I/O is queued and resubmitted when the
+ * device is resumed.  This affects multipath devices when all paths
+ * have failed and queue_if_no_path is set, and mirror devices when
+ * block_on_error is set and the mirror log has failed.
+ */
+void dm_tree_use_no_flush_suspend(struct dm_tree_node *dnode);
+
+/*
+ * Is the uuid prefix present in the tree?
+ * Only returns 0 if every node was checked successfully.
+ * Returns 1 if the tree walk has to be aborted.
+ */
+int dm_tree_children_use_uuid(struct dm_tree_node *dnode,
+				 const char *uuid_prefix,
+				 size_t uuid_prefix_len);
+
+/*
+ * Construct tables for new nodes before activating them.
+ */
+int dm_tree_node_add_snapshot_origin_target(struct dm_tree_node *dnode,
+					       uint64_t size,
+					       const char *origin_uuid);
+int dm_tree_node_add_snapshot_target(struct dm_tree_node *node,
+					uint64_t size,
+					const char *origin_uuid,
+					const char *cow_uuid,
+					int persistent,
+					uint32_t chunk_size);
+int dm_tree_node_add_error_target(struct dm_tree_node *node,
+				     uint64_t size);
+int dm_tree_node_add_zero_target(struct dm_tree_node *node,
+				    uint64_t size);
+int dm_tree_node_add_linear_target(struct dm_tree_node *node,
+				      uint64_t size);
+int dm_tree_node_add_striped_target(struct dm_tree_node *node,
+				       uint64_t size,
+				       uint32_t stripe_size);
+int dm_tree_node_add_mirror_target(struct dm_tree_node *node,
+				      uint64_t size);
+ 
+/* Mirror log flags */
+#define DM_NOSYNC		0x00000001	/* Known already in sync */
+#define DM_FORCESYNC		0x00000002	/* Force resync */
+#define DM_BLOCK_ON_ERROR	0x00000004	/* On error, suspend I/O */
+#define DM_CORELOG		0x00000008	/* In-memory log */
+
+int dm_tree_node_add_mirror_target_log(struct dm_tree_node *node,
+					  uint32_t region_size,
+					  unsigned clustered,
+					  const char *log_uuid,
+					  unsigned area_count,
+					  uint32_t flags);
+int dm_tree_node_add_target_area(struct dm_tree_node *node,
+				    const char *dev_name,
+				    const char *dlid,
+				    uint64_t offset);
+
+/*
+ * Set readahead (in sectors) after loading the node.
+ */
+void dm_tree_node_set_read_ahead(struct dm_tree_node *dnode,
+				 uint32_t read_ahead,
+				 uint32_t read_ahead_flags);
+
+/*****************************************************************************
+ * Library functions
+ *****************************************************************************/
+
+/*******************
+ * Memory management
+ *******************/
+
+void *dm_malloc_aux(size_t s, const char *file, int line);
+void *dm_malloc_aux_debug(size_t s, const char *file, int line);
+char *dm_strdup_aux(const char *str, const char *file, int line);
+void dm_free_aux(void *p);
+void *dm_realloc_aux(void *p, unsigned int s, const char *file, int line);
+int dm_dump_memory_debug(void);
+void dm_bounds_check_debug(void);
+
+#ifdef DEBUG_MEM
+
+#  define dm_malloc(s) dm_malloc_aux_debug((s), __FILE__, __LINE__)
+#  define dm_strdup(s) dm_strdup_aux((s), __FILE__, __LINE__)
+#  define dm_free(p) dm_free_aux(p)
+#  define dm_realloc(p, s) dm_realloc_aux(p, s, __FILE__, __LINE__)
+#  define dm_dump_memory() dm_dump_memory_debug()
+#  define dm_bounds_check() dm_bounds_check_debug()
+
+#else
+
+#  define dm_malloc(s) dm_malloc_aux((s), __FILE__, __LINE__)
+#  define dm_strdup(s) strdup(s)
+#  define dm_free(p) free(p)
+#  define dm_realloc(p, s) realloc(p, s)
+#  define dm_dump_memory() {}
+#  define dm_bounds_check() {}
+
+#endif
+
+
+/*
+ * The pool allocator is useful when you are going to allocate
+ * lots of memory, use the memory for a bit, and then free the
+ * memory in one go.  A surprising amount of code has this usage
+ * profile.
+ *
+ * You should think of the pool as an infinite, contiguous chunk
+ * of memory.  The front of this chunk of memory contains
+ * allocated objects, the second half is free.  dm_pool_alloc grabs
+ * the next 'size' bytes from the free half, in effect moving it
+ * into the allocated half.  This operation is very efficient.
+ *
+ * dm_pool_free frees the allocated object *and* all objects
+ * allocated after it.  It is important to note this semantic
+ * difference from malloc/free.  This is also extremely
+ * efficient, since a single dm_pool_free can dispose of a large
+ * complex object.
+ *
+ * dm_pool_destroy frees all allocated memory.
+ *
+ * eg, If you are building a binary tree in your program, and
+ * know that you are only ever going to insert into your tree,
+ * and not delete (eg, maintaining a symbol table for a
+ * compiler).  You can create yourself a pool, allocate the nodes
+ * from it, and when the tree becomes redundant call dm_pool_destroy
+ * (no nasty iterating through the tree to free nodes).
+ *
+ * eg, On the other hand if you wanted to repeatedly insert and
+ * remove objects into the tree, you would be better off
+ * allocating the nodes from a free list; you cannot free a
+ * single arbitrary node with pool.
+ */
+
+struct dm_pool;
+
+/* constructor and destructor */
+struct dm_pool *dm_pool_create(const char *name, size_t chunk_hint);
+void dm_pool_destroy(struct dm_pool *p);
+
+/* simple allocation/free routines */
+void *dm_pool_alloc(struct dm_pool *p, size_t s);
+void *dm_pool_alloc_aligned(struct dm_pool *p, size_t s, unsigned alignment);
+void dm_pool_empty(struct dm_pool *p);
+void dm_pool_free(struct dm_pool *p, void *ptr);
+
+/*
+ * Object building routines:
+ *
+ * These allow you to 'grow' an object, useful for
+ * building strings, or filling in dynamic
+ * arrays.
+ *
+ * It's probably best explained with an example:
+ *
+ * char *build_string(struct dm_pool *mem)
+ * {
+ *      int i;
+ *      char buffer[16];
+ *
+ *      if (!dm_pool_begin_object(mem, 128))
+ *              return NULL;
+ *
+ *      for (i = 0; i < 50; i++) {
+ *              snprintf(buffer, sizeof(buffer), "%d, ", i);
+ *              if (!dm_pool_grow_object(mem, buffer, 0))
+ *                      goto bad;
+ *      }
+ *
+ *	// add null
+ *      if (!dm_pool_grow_object(mem, "\0", 1))
+ *              goto bad;
+ *
+ *      return dm_pool_end_object(mem);
+ *
+ * bad:
+ *
+ *      dm_pool_abandon_object(mem);
+ *      return NULL;
+ *}
+ *
+ * So start an object by calling dm_pool_begin_object
+ * with a guess at the final object size - if in
+ * doubt make the guess too small.
+ *
+ * Then append chunks of data to your object with
+ * dm_pool_grow_object.  Finally get your object with
+ * a call to dm_pool_end_object.
+ *
+ * Setting delta to 0 means it will use strlen(extra).
+ */
+int dm_pool_begin_object(struct dm_pool *p, size_t hint);
+int dm_pool_grow_object(struct dm_pool *p, const void *extra, size_t delta);
+void *dm_pool_end_object(struct dm_pool *p);
+void dm_pool_abandon_object(struct dm_pool *p);
+
+/* utilities */
+char *dm_pool_strdup(struct dm_pool *p, const char *str);
+char *dm_pool_strndup(struct dm_pool *p, const char *str, size_t n);
+void *dm_pool_zalloc(struct dm_pool *p, size_t s);
+
+/******************
+ * bitset functions
+ ******************/
+
+typedef uint32_t *dm_bitset_t;
+
+dm_bitset_t dm_bitset_create(struct dm_pool *mem, unsigned num_bits);
+void dm_bitset_destroy(dm_bitset_t bs);
+
+void dm_bit_union(dm_bitset_t out, dm_bitset_t in1, dm_bitset_t in2);
+int dm_bit_get_first(dm_bitset_t bs);
+int dm_bit_get_next(dm_bitset_t bs, int last_bit);
+
+#define DM_BITS_PER_INT (sizeof(int) * CHAR_BIT)
+
+#define dm_bit(bs, i) \
+   (bs[(i / DM_BITS_PER_INT) + 1] & (0x1 << (i & (DM_BITS_PER_INT - 1))))
+
+#define dm_bit_set(bs, i) \
+   (bs[(i / DM_BITS_PER_INT) + 1] |= (0x1 << (i & (DM_BITS_PER_INT - 1))))
+
+#define dm_bit_clear(bs, i) \
+   (bs[(i / DM_BITS_PER_INT) + 1] &= ~(0x1 << (i & (DM_BITS_PER_INT - 1))))
+
+#define dm_bit_set_all(bs) \
+   memset(bs + 1, -1, ((*bs / DM_BITS_PER_INT) + 1) * sizeof(int))
+
+#define dm_bit_clear_all(bs) \
+   memset(bs + 1, 0, ((*bs / DM_BITS_PER_INT) + 1) * sizeof(int))
+
+#define dm_bit_copy(bs1, bs2) \
+   memcpy(bs1 + 1, bs2 + 1, ((*bs1 / DM_BITS_PER_INT) + 1) * sizeof(int))
+
+/* Returns number of set bits */
+static inline unsigned hweight32(uint32_t i)
+{
+	unsigned r = (i & 0x55555555) + ((i >> 1) & 0x55555555);
+
+	r =    (r & 0x33333333) + ((r >>  2) & 0x33333333);
+	r =    (r & 0x0F0F0F0F) + ((r >>  4) & 0x0F0F0F0F);
+	r =    (r & 0x00FF00FF) + ((r >>  8) & 0x00FF00FF);
+	return (r & 0x0000FFFF) + ((r >> 16) & 0x0000FFFF);
+}
+
+/****************
+ * hash functions
+ ****************/
+
+struct dm_hash_table;
+struct dm_hash_node;
+
+typedef void (*dm_hash_iterate_fn) (void *data);
+
+struct dm_hash_table *dm_hash_create(unsigned size_hint);
+void dm_hash_destroy(struct dm_hash_table *t);
+void dm_hash_wipe(struct dm_hash_table *t);
+
+void *dm_hash_lookup(struct dm_hash_table *t, const char *key);
+int dm_hash_insert(struct dm_hash_table *t, const char *key, void *data);
+void dm_hash_remove(struct dm_hash_table *t, const char *key);
+
+void *dm_hash_lookup_binary(struct dm_hash_table *t, const char *key, uint32_t len);
+int dm_hash_insert_binary(struct dm_hash_table *t, const char *key, uint32_t len,
+		       void *data);
+void dm_hash_remove_binary(struct dm_hash_table *t, const char *key, uint32_t len);
+
+unsigned dm_hash_get_num_entries(struct dm_hash_table *t);
+void dm_hash_iter(struct dm_hash_table *t, dm_hash_iterate_fn f);
+
+char *dm_hash_get_key(struct dm_hash_table *t, struct dm_hash_node *n);
+void *dm_hash_get_data(struct dm_hash_table *t, struct dm_hash_node *n);
+struct dm_hash_node *dm_hash_get_first(struct dm_hash_table *t);
+struct dm_hash_node *dm_hash_get_next(struct dm_hash_table *t, struct dm_hash_node *n);
+
+#define dm_hash_iterate(v, h) \
+	for (v = dm_hash_get_first(h); v; \
+	     v = dm_hash_get_next(h, v))
+
+/****************
+ * list functions
+ ****************/
+
+/*
+ * A list consists of a list head plus elements.
+ * Each element has 'next' and 'previous' pointers.
+ * The list head's pointers point to the first and the last element.
+ */
+
+struct dm_list {
+	struct dm_list *n, *p;
+};
+
+/*
+ * Initialise a list before use.
+ * The list head's next and previous pointers point back to itself.
+ */
+#define DM_LIST_INIT(name)	struct dm_list name = { &(name), &(name) }
+void dm_list_init(struct dm_list *head);
+
+/*
+ * Insert an element before 'head'.
+ * If 'head' is the list head, this adds an element to the end of the list.
+ */
+void dm_list_add(struct dm_list *head, struct dm_list *elem);
+
+/*
+ * Insert an element after 'head'.
+ * If 'head' is the list head, this adds an element to the front of the list.
+ */
+void dm_list_add_h(struct dm_list *head, struct dm_list *elem);
+
+/*
+ * Delete an element from its list.
+ * Note that this doesn't change the element itself - it may still be safe
+ * to follow its pointers.
+ */
+void dm_list_del(struct dm_list *elem);
+
+/*
+ * Remove an element from existing list and insert before 'head'.
+ */
+void dm_list_move(struct dm_list *head, struct dm_list *elem);
+
+/*
+ * Is the list empty?
+ */
+int dm_list_empty(const struct dm_list *head);
+
+/*
+ * Is this the first element of the list?
+ */
+int dm_list_start(const struct dm_list *head, const struct dm_list *elem);
+
+/*
+ * Is this the last element of the list?
+ */
+int dm_list_end(const struct dm_list *head, const struct dm_list *elem);
+
+/*
+ * Return first element of the list or NULL if empty
+ */
+struct dm_list *dm_list_first(const struct dm_list *head);
+
+/*
+ * Return last element of the list or NULL if empty
+ */
+struct dm_list *dm_list_last(const struct dm_list *head);
+
+/*
+ * Return the previous element of the list, or NULL if we've reached the start.
+ */
+struct dm_list *dm_list_prev(const struct dm_list *head, const struct dm_list *elem);
+
+/*
+ * Return the next element of the list, or NULL if we've reached the end.
+ */
+struct dm_list *dm_list_next(const struct dm_list *head, const struct dm_list *elem);
+
+/*
+ * Given the address v of an instance of 'struct dm_list' called 'head' 
+ * contained in a structure of type t, return the containing structure.
+ */
+#define dm_list_struct_base(v, t, head) \
+    ((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->head))
+
+/*
+ * Given the address v of an instance of 'struct dm_list list' contained in
+ * a structure of type t, return the containing structure.
+ */
+#define dm_list_item(v, t) dm_list_struct_base((v), t, list)
+
+/*
+ * Given the address v of one known element e in a known structure of type t,
+ * return another element f.
+ */
+#define dm_struct_field(v, t, e, f) \
+    (((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->e))->f)
+
+/*
+ * Given the address v of a known element e in a known structure of type t,
+ * return the list head 'list'
+ */
+#define dm_list_head(v, t, e) dm_struct_field(v, t, e, list)
+
+/*
+ * Set v to each element of a list in turn.
+ */
+#define dm_list_iterate(v, head) \
+	for (v = (head)->n; v != head; v = v->n)
+
+/*
+ * Set v to each element in a list in turn, starting from the element 
+ * in front of 'start'.
+ * You can use this to 'unwind' a list_iterate and back out actions on
+ * already-processed elements.
+ * If 'start' is 'head' it walks the list backwards.
+ */
+#define dm_list_uniterate(v, head, start) \
+	for (v = (start)->p; v != head; v = v->p)
+
+/*
+ * A safe way to walk a list and delete and free some elements along
+ * the way.
+ * t must be defined as a temporary variable of the same type as v.
+ */
+#define dm_list_iterate_safe(v, t, head) \
+	for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
+
+/*
+ * Walk a list, setting 'v' in turn to the containing structure of each item.
+ * The containing structure should be the same type as 'v'.
+ * The 'struct dm_list' variable within the containing structure is 'field'.
+ */
+#define dm_list_iterate_items_gen(v, head, field) \
+	for (v = dm_list_struct_base((head)->n, typeof(*v), field); \
+	     &v->field != (head); \
+	     v = dm_list_struct_base(v->field.n, typeof(*v), field))
+
+/*
+ * Walk a list, setting 'v' in turn to the containing structure of each item.
+ * The containing structure should be the same type as 'v'.
+ * The list should be 'struct dm_list list' within the containing structure.
+ */
+#define dm_list_iterate_items(v, head) dm_list_iterate_items_gen(v, (head), list)
+
+/*
+ * Walk a list, setting 'v' in turn to the containing structure of each item.
+ * The containing structure should be the same type as 'v'.
+ * The 'struct dm_list' variable within the containing structure is 'field'.
+ * t must be defined as a temporary variable of the same type as v.
+ */
+#define dm_list_iterate_items_gen_safe(v, t, head, field) \
+	for (v = dm_list_struct_base((head)->n, typeof(*v), field), \
+	     t = dm_list_struct_base(v->field.n, typeof(*v), field); \
+	     &v->field != (head); \
+	     v = t, t = dm_list_struct_base(v->field.n, typeof(*v), field))
+/*
+ * Walk a list, setting 'v' in turn to the containing structure of each item.
+ * The containing structure should be the same type as 'v'.
+ * The list should be 'struct dm_list list' within the containing structure.
+ * t must be defined as a temporary variable of the same type as v.
+ */
+#define dm_list_iterate_items_safe(v, t, head) \
+	dm_list_iterate_items_gen_safe(v, t, (head), list)
+
+/*
+ * Walk a list backwards, setting 'v' in turn to the containing structure 
+ * of each item.
+ * The containing structure should be the same type as 'v'.
+ * The 'struct dm_list' variable within the containing structure is 'field'.
+ */
+#define dm_list_iterate_back_items_gen(v, head, field) \
+	for (v = dm_list_struct_base((head)->p, typeof(*v), field); \
+	     &v->field != (head); \
+	     v = dm_list_struct_base(v->field.p, typeof(*v), field))
+
+/*
+ * Walk a list backwards, setting 'v' in turn to the containing structure 
+ * of each item.
+ * The containing structure should be the same type as 'v'.
+ * The list should be 'struct dm_list list' within the containing structure.
+ */
+#define dm_list_iterate_back_items(v, head) dm_list_iterate_back_items_gen(v, (head), list)
+
+/*
+ * Return the number of elements in a list by walking it.
+ */
+unsigned int dm_list_size(const struct dm_list *head);
+
+/*********
+ * selinux
+ *********/
+int dm_set_selinux_context(const char *path, mode_t mode);
+
+/*********************
+ * string manipulation
+ *********************/
+
+/*
+ * Break up the name of a mapped device into its constituent
+ * Volume Group, Logical Volume and Layer (if present).
+ */
+int dm_split_lvm_name(struct dm_pool *mem, const char *dmname,
+		      char **vgname, char **lvname, char **layer);
+
+/*
+ * Destructively split buffer into NULL-separated words in argv.
+ * Returns number of words.
+ */
+int dm_split_words(char *buffer, unsigned max,
+		   unsigned ignore_comments, /* Not implemented */
+		   char **argv);
+
+/* 
+ * Returns -1 if buffer too small
+ */
+int dm_snprintf(char *buf, size_t bufsize, const char *format, ...);
+
+/*
+ * Returns pointer to the last component of the path.
+ */
+char *dm_basename(const char *path);
+
+/**************************
+ * file/stream manipulation
+ **************************/
+
+/*
+ * Create a directory (with parent directories if necessary).
+ * Returns 1 on success, 0 on failure.
+ */
+int dm_create_dir(const char *dir);
+
+/*
+ * Close a stream, with nicer error checking than fclose's.
+ * Derived from gnulib's close-stream.c.
+ *
+ * Close "stream".  Return 0 if successful, and EOF (setting errno)
+ * otherwise.  Upon failure, set errno to 0 if the error number
+ * cannot be determined.  Useful mainly for writable streams.
+ */
+int dm_fclose(FILE *stream);
+
+/*
+ * Returns size of a buffer which is allocated with dm_malloc.
+ * Pointer to the buffer is stored in *buf.
+ * Returns -1 on failure leaving buf undefined.
+ */
+int dm_asprintf(char **buf, const char *format, ...);
+
+/*********************
+ * regular expressions
+ *********************/
+struct dm_regex;
+
+/*
+ * Initialise an array of num patterns for matching.
+ * Uses memory from mem.
+ */
+struct dm_regex *dm_regex_create(struct dm_pool *mem, const char **patterns,
+				 unsigned num_patterns);
+
+/*
+ * Match string s against the patterns.
+ * Returns the index of the highest pattern in the array that matches,
+ * or -1 if none match.
+ */
+int dm_regex_match(struct dm_regex *regex, const char *s);
+
+/*********************
+ * reporting functions
+ *********************/
+
+struct dm_report_object_type {
+	uint32_t id;			/* Powers of 2 */
+	const char *desc;
+	const char *prefix;		/* field id string prefix (optional) */
+	void *(*data_fn)(void *object);	/* callback from report_object() */
+};
+
+struct dm_report_field;
+
+/*
+ * dm_report_field_type flags
+ */
+#define DM_REPORT_FIELD_MASK		0x000000FF
+#define DM_REPORT_FIELD_ALIGN_MASK	0x0000000F
+#define DM_REPORT_FIELD_ALIGN_LEFT	0x00000001
+#define DM_REPORT_FIELD_ALIGN_RIGHT	0x00000002
+#define DM_REPORT_FIELD_TYPE_MASK	0x000000F0
+#define DM_REPORT_FIELD_TYPE_STRING	0x00000010
+#define DM_REPORT_FIELD_TYPE_NUMBER	0x00000020
+
+struct dm_report;
+struct dm_report_field_type {
+	uint32_t type;		/* object type id */
+	uint32_t flags;		/* DM_REPORT_FIELD_* */
+	uint32_t offset;	/* byte offset in the object */
+	int32_t width;		/* default width */
+	const char id[32];	/* string used to specify the field */
+	const char heading[32];	/* string printed in header */
+	int (*report_fn)(struct dm_report *rh, struct dm_pool *mem,
+			 struct dm_report_field *field, const void *data,
+			 void *private);
+	const char *desc;	/* description of the field */
+};
+
+/*
+ * dm_report_init output_flags
+ */
+#define DM_REPORT_OUTPUT_MASK			0x000000FF
+#define DM_REPORT_OUTPUT_ALIGNED		0x00000001
+#define DM_REPORT_OUTPUT_BUFFERED		0x00000002
+#define DM_REPORT_OUTPUT_HEADINGS		0x00000004
+#define DM_REPORT_OUTPUT_FIELD_NAME_PREFIX	0x00000008
+#define DM_REPORT_OUTPUT_FIELD_UNQUOTED		0x00000010
+#define DM_REPORT_OUTPUT_COLUMNS_AS_ROWS	0x00000020
+
+struct dm_report *dm_report_init(uint32_t *report_types,
+				 const struct dm_report_object_type *types,
+				 const struct dm_report_field_type *fields,
+				 const char *output_fields,
+				 const char *output_separator,
+				 uint32_t output_flags,
+				 const char *sort_keys,
+				 void *private);
+int dm_report_object(struct dm_report *rh, void *object);
+int dm_report_output(struct dm_report *rh);
+void dm_report_free(struct dm_report *rh);
+
+/*
+ * Prefix added to each field name with DM_REPORT_OUTPUT_FIELD_NAME_PREFIX
+ */
+int dm_report_set_output_field_name_prefix(struct dm_report *rh,
+					   const char *report_prefix);
+
+/*
+ * Report functions are provided for simple data types.
+ * They take care of allocating copies of the data.
+ */
+int dm_report_field_string(struct dm_report *rh, struct dm_report_field *field,
+			   const char **data);
+int dm_report_field_int32(struct dm_report *rh, struct dm_report_field *field,
+			  const int32_t *data);
+int dm_report_field_uint32(struct dm_report *rh, struct dm_report_field *field,
+			   const uint32_t *data);
+int dm_report_field_int(struct dm_report *rh, struct dm_report_field *field,
+			const int *data);
+int dm_report_field_uint64(struct dm_report *rh, struct dm_report_field *field,
+			   const uint64_t *data);
+
+/*
+ * For custom fields, allocate the data in 'mem' and use
+ * dm_report_field_set_value().
+ * 'sortvalue' may be NULL if it matches 'value'
+ */
+void dm_report_field_set_value(struct dm_report_field *field, const void *value,
+			       const void *sortvalue);
+
+#endif				/* LIB_DEVICE_MAPPER_H */
Index: src/external/gpl2/lvm2tools/dist/libdm/libdevmapper.pc.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/libdevmapper.pc.in
diff -N src/external/gpl2/lvm2tools/dist/libdm/libdevmapper.pc.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/libdevmapper.pc.in	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: devmapper
+Description: device-mapper library
+Version: @DM_LIB_PATCHLEVEL@
+Cflags: -I${includedir} 
+Libs: -L${libdir} -ldevmapper
+Libs.private: -lselinux -lsepol
Index: src/external/gpl2/lvm2tools/dist/libdm/libdm-common.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/libdm-common.c
diff -N src/external/gpl2/lvm2tools/dist/libdm/libdm-common.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/libdm-common.c	17 Dec 2008 00:48:49 -0000	1.1.1.1.2.4
@@ -0,0 +1,806 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "dmlib.h"
+#include "libdm-targets.h"
+#include "libdm-common.h"
+#ifdef linux
+#include "kdev_t.h"
+#endif
+#include "dm-ioctl.h"
+
+#include <stdarg.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#ifdef linux
+#  include <linux/fs.h>
+#endif
+
+#ifdef HAVE_SELINUX
+#  include <selinux/selinux.h>
+#endif
+
+#ifdef __NetBSD__
+#include <netbsd-dm.h>
+#endif
+
+#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.
+ */
+static void _default_log(int level, const char *file __attribute((unused)),
+			 int line __attribute((unused)), const char *f, ...)
+{
+	va_list ap;
+	int use_stderr = level & _LOG_STDERR;
+
+	level &= ~_LOG_STDERR;
+
+	if (level > _LOG_WARN && !_verbose)
+		return;
+
+	va_start(ap, f);
+
+	if (level < _LOG_WARN)
+		vfprintf(stderr, f, ap);
+	else
+		vfprintf(use_stderr ? stderr : stdout, f, ap);
+
+	va_end(ap);
+
+	if (level < _LOG_WARN)
+		fprintf(stderr, "\n");
+	else
+		fprintf(use_stderr ? stderr : stdout, "\n");
+}
+
+dm_log_fn dm_log = _default_log;
+
+void dm_log_init(dm_log_fn fn)
+{
+	if (fn)
+		dm_log = fn;
+	else
+		dm_log = _default_log;
+}
+
+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 */
+	if (strchr(dev_name, '/'))
+		snprintf(buffer, len, "%s", dev_name);
+	else
+		snprintf(buffer, len, "%s/%s", _dm_dir, dev_name);
+}
+
+int dm_get_library_version(char *version, size_t size)
+{
+	strncpy(version, DM_LIB_VERSION, size);
+	return 1;
+}
+
+struct dm_task *dm_task_create(int type)
+{
+	struct dm_task *dmt = dm_malloc(sizeof(*dmt));
+
+	if (!dmt) {
+		log_error("dm_task_create: malloc(%" PRIsize_t ") failed",
+			  sizeof(*dmt));
+		return NULL;
+	}
+
+	if (!dm_check_version()) {
+		dm_free(dmt);
+		return NULL;
+	}
+
+	memset(dmt, 0, sizeof(*dmt));
+
+	dmt->type = type;
+	dmt->minor = -1;
+	dmt->major = -1;
+	dmt->uid = DM_DEVICE_UID;
+	dmt->gid = DM_DEVICE_GID;
+	dmt->mode = DM_DEVICE_MODE;
+	dmt->no_open_count = 0;
+	dmt->read_ahead = DM_READ_AHEAD_AUTO;
+	dmt->read_ahead_flags = 0;
+
+	return dmt;
+}
+
+int dm_task_set_name(struct dm_task *dmt, const char *name)
+{
+	char *pos;
+	char path[PATH_MAX];
+	struct stat st1, st2;
+
+	if (dmt->dev_name) {
+		dm_free(dmt->dev_name);
+		dmt->dev_name = NULL;
+	}
+
+	/* If path was supplied, remove it if it points to the same device
+	 * as its last component.
+	 */
+	if ((pos = strrchr(name, '/'))) {
+		snprintf(path, sizeof(path), "%s/%s", _dm_dir, pos + 1);
+
+		if (stat(name, &st1) || stat(path, &st2) ||
+		    !(st1.st_dev == st2.st_dev)) {
+			log_error("dm_task_set_name: Device %s not found",
+				  name);
+			return 0;
+		}
+
+		name = pos + 1;
+	}
+
+	if (!(dmt->dev_name = dm_strdup(name))) {
+		log_error("dm_task_set_name: strdup(%s) failed", name);
+		return 0;
+	}
+
+	return 1;
+}
+
+int dm_task_set_uuid(struct dm_task *dmt, const char *uuid)
+{
+	if (dmt->uuid) {
+		dm_free(dmt->uuid);
+		dmt->uuid = NULL;
+	}
+
+	if (!(dmt->uuid = dm_strdup(uuid))) {
+		log_error("dm_task_set_uuid: strdup(%s) failed", uuid);
+		return 0;
+	}
+
+	return 1;
+}
+
+int dm_task_set_major(struct dm_task *dmt, int major)
+{
+	dmt->major = major;
+
+	return 1;
+}
+
+int dm_task_set_minor(struct dm_task *dmt, int minor)
+{
+	dmt->minor = minor;
+
+	return 1;
+}
+
+int dm_task_set_uid(struct dm_task *dmt, uid_t uid)
+{
+	dmt->uid = uid;
+
+	return 1;
+}
+
+int dm_task_set_gid(struct dm_task *dmt, gid_t gid)
+{
+	dmt->gid = gid;
+
+	return 1;
+}
+
+int dm_task_set_mode(struct dm_task *dmt, mode_t mode)
+{
+	dmt->mode = mode;
+
+	return 1;
+}
+
+int dm_task_add_target(struct dm_task *dmt, uint64_t start, uint64_t size,
+		       const char *ttype, const char *params)
+{
+	struct target *t = create_target(start, size, ttype, params);
+
+	if (!t)
+		return 0;
+
+	if (!dmt->head)
+		dmt->head = dmt->tail = t;
+	else {
+		dmt->tail->next = t;
+		dmt->tail = t;
+	}
+
+	return 1;
+}
+
+#ifdef HAVE_SELINUX
+int dm_set_selinux_context(const char *path, mode_t mode)
+{
+	security_context_t scontext;
+
+	if (is_selinux_enabled() <= 0)
+		return 1;
+
+	if (matchpathcon(path, mode, &scontext) < 0) {
+		log_error("%s: matchpathcon %07o failed: %s", path, mode,
+			  strerror(errno));
+		return 0;
+	}
+
+	log_debug("Setting SELinux context for %s to %s.", path, scontext);
+
+	if ((lsetfilecon(path, scontext) < 0) && (errno != ENOTSUP)) {
+		log_sys_error("lsetfilecon", path);
+		freecon(scontext);
+		return 0;
+	}
+
+	freecon(scontext);
+	return 1;
+}
+#endif
+
+static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor,
+			 uid_t uid, gid_t gid, mode_t mode)
+{
+	char path[PATH_MAX];
+	struct stat info;
+	dev_t dev = MKDEV(major, minor);
+	mode_t old_mask;
+
+	#ifdef __NetBSD__
+	char rpath[PATH_MAX];
+	uint32_t raw_major;
+	dev_t rdev;
+	char raw_devname[DM_NAME_LEN+1]; /* r + other device name */
+
+	nbsd_get_dm_major(&raw_major,DM_CHAR_MAJOR);
+	rdev = MKDEV(raw_major,minor);
+
+	snprintf(raw_devname,sizeof(raw_devname),"r%s",dev_name);
+
+	_build_dev_path(rpath, sizeof(rpath), raw_devname);
+
+	if (stat(rpath, &info) >= 0) {
+		if (!S_ISCHR(info.st_mode)) {
+			log_error("A non-raw device file at '%s' "
+			    "is already present", rpath);
+			return 0;
+		}
+
+		/* If right inode already exists we don't touch uid etc. */
+		if (info.st_rdev == rdev)
+			return 1;
+
+		if (unlink(rpath) < 0) {
+			log_error("Unable to unlink device node for '%s'",
+			    raw_devname);
+			return 0;
+		}
+	}
+
+	old_mask = umask(0);
+
+	if (mknod(rpath, S_IFCHR | mode, rdev) < 0) {
+		log_error("Unable to make device node for '%s'", raw_devname);
+		return 0;
+	}
+#endif
+	
+	_build_dev_path(path, sizeof(path), dev_name);
+
+	if (stat(path, &info) >= 0) {
+		if (!S_ISBLK(info.st_mode)) {
+			log_error("A non-block device file at '%s' "
+				  "is already present", path);
+			return 0;
+		}
+
+		/* If right inode already exists we don't touch uid etc. */
+		if (info.st_rdev == dev)
+			return 1;
+
+		if (unlink(path) < 0) {
+			log_error("Unable to unlink device node for '%s'",
+				  dev_name);
+			return 0;
+		}
+	}
+
+	old_mask = umask(0);
+	if (mknod(path, S_IFBLK | mode, dev) < 0) {
+		log_error("Unable to make device node for '%s'", dev_name);
+		return 0;
+	}
+	umask(old_mask);
+
+	if (chown(path, uid, gid) < 0) {
+		log_sys_error("chown", path);
+		return 0;
+	}
+
+	log_debug("Created %s", path);
+
+#ifdef HAVE_SELINUX
+	if (!dm_set_selinux_context(path, S_IFBLK))
+		return 0;
+#endif
+
+	return 1;
+}
+
+static int _rename_dev_node(const char *old_name, const char *new_name)
+{
+	char oldpath[PATH_MAX];
+	char newpath[PATH_MAX];
+	struct stat info;
+
+#ifdef __NetBSD__
+	char rpath[PATH_MAX];
+	char nrpath[PATH_MAX];
+	char raw_devname[DM_NAME_LEN+1]; /* r + other device name */
+	char nraw_devname[DM_NAME_LEN+1]; /* r + other device name */
+
+	snprintf(nraw_devname,sizeof(raw_devname),"r%s",new_name);
+	snprintf(raw_devname,sizeof(raw_devname),"r%s",old_name);
+
+	_build_dev_path(nrpath, sizeof(nrpath), nraw_devname);
+	_build_dev_path(rpath, sizeof(rpath), raw_devname);
+
+	if (stat(nrpath, &info) == 0) {
+		if (S_ISBLK(info.st_mode)) {
+			log_error("A block device file at '%s' "
+			    "is present where raw device should be.", newpath);
+			return 0;
+		}
+
+		if (unlink(nrpath) < 0) {
+			log_error("Unable to unlink device node for '%s'",
+			    nraw_devname);
+			return 0;
+		}
+	}
+
+	if (rename(rpath, nrpath) < 0) {
+		log_error("Unable to rename device node from '%s' to '%s'",
+		    raw_devname, nraw_devname);
+		return 0;
+	}
+
+	log_debug("Renamed %s to %s", rpath, nrpath);
+
+#endif
+	
+	_build_dev_path(oldpath, sizeof(oldpath), old_name);
+	_build_dev_path(newpath, sizeof(newpath), new_name);
+
+	if (stat(newpath, &info) == 0) {
+		if (!S_ISBLK(info.st_mode)) {
+			log_error("A non-block device file at '%s' "
+				  "is already present", newpath);
+			return 0;
+		}
+
+		if (unlink(newpath) < 0) {
+			if (errno == EPERM) {
+				/* devfs, entry has already been renamed */
+				return 1;
+			}
+			log_error("Unable to unlink device node for '%s'",
+				  new_name);
+			return 0;
+		}
+	}
+
+	if (rename(oldpath, newpath) < 0) {
+		log_error("Unable to rename device node from '%s' to '%s'",
+			  old_name, new_name);
+		return 0;
+	}
+
+	log_debug("Renamed %s to %s", oldpath, newpath);
+
+	return 1;
+}
+
+static int _rm_dev_node(const char *dev_name)
+{
+	char path[PATH_MAX];
+	struct stat info;
+
+#ifdef __NetBSD__
+	char rpath[PATH_MAX];
+	char raw_devname[DM_NAME_LEN+1]; /* r + other device name */
+
+	snprintf(raw_devname,sizeof(raw_devname),"r%s",dev_name);
+
+	_build_dev_path(rpath, sizeof(rpath), raw_devname);
+
+	if (stat(rpath, &info) < 0)
+		return 1;
+
+	if (unlink(rpath) < 0) {
+		log_error("Unable to unlink device node for '%s'", raw_devname);
+		return 0;
+	}
+
+	log_debug("Removed %s", rpath);
+#endif
+	
+	_build_dev_path(path, sizeof(path), dev_name);
+
+	if (stat(path, &info) < 0)
+		return 1;
+
+	if (unlink(path) < 0) {
+		log_error("Unable to unlink device node for '%s'", dev_name);
+		return 0;
+	}
+
+	log_debug("Removed %s", path);
+
+	return 1;
+}
+
+#ifdef linux
+static int _open_dev_node(const char *dev_name)
+{
+	int fd = -1;
+	char path[PATH_MAX];
+
+	_build_dev_path(path, sizeof(path), dev_name);
+
+	if ((fd = open(path, O_RDONLY, 0)) < 0)
+		log_sys_error("open", path);
+
+	return fd;
+}
+
+int get_dev_node_read_ahead(const char *dev_name, uint32_t *read_ahead)
+{
+	int r = 1;
+	int fd;
+	long read_ahead_long;
+
+	if (!*dev_name) {
+		log_error("Empty device name passed to BLKRAGET");
+		return 0;
+	}
+
+	if ((fd = _open_dev_node(dev_name)) < 0)
+		return_0;
+
+	if (ioctl(fd, BLKRAGET, &read_ahead_long)) {
+		log_sys_error("BLKRAGET", dev_name);
+		*read_ahead = 0;
+		r = 0;
+	}  else {
+		*read_ahead = (uint32_t) read_ahead_long;
+		log_debug("%s: read ahead is %" PRIu32, dev_name, *read_ahead);
+	}
+
+	if (close(fd))
+		stack;
+
+	return r;
+}
+
+static int _set_read_ahead(const char *dev_name, uint32_t read_ahead)
+{
+	int r = 1;
+	int fd;
+	long read_ahead_long = (long) read_ahead;
+
+	if (!*dev_name) {
+		log_error("Empty device name passed to BLKRAGET");
+		return 0;
+	}
+
+	if ((fd = _open_dev_node(dev_name)) < 0)
+		return_0;
+
+	log_debug("%s: Setting read ahead to %" PRIu32, dev_name, read_ahead);
+
+	if (ioctl(fd, BLKRASET, read_ahead_long)) {
+		log_sys_error("BLKRASET", dev_name);
+		r = 0;
+	}
+
+	if (close(fd))
+		stack;
+
+	return r;
+}
+
+static int _set_dev_node_read_ahead(const char *dev_name, uint32_t read_ahead,
+				    uint32_t read_ahead_flags)
+{
+	uint32_t current_read_ahead;
+
+	if (read_ahead == DM_READ_AHEAD_AUTO)
+		return 1;
+
+	if (read_ahead == DM_READ_AHEAD_NONE)
+		read_ahead = 0;
+
+	if (read_ahead_flags & DM_READ_AHEAD_MINIMUM_FLAG) {
+		if (!get_dev_node_read_ahead(dev_name, &current_read_ahead))
+			return_0;
+
+		if (current_read_ahead > read_ahead) {
+			log_debug("%s: retaining kernel read ahead of %" PRIu32
+				  " (requested %" PRIu32 ")",           
+				  dev_name, current_read_ahead, read_ahead);
+			return 1;
+		}
+	}
+
+	return _set_read_ahead(dev_name, read_ahead);
+}
+
+#else
+
+int get_dev_node_read_ahead(const char *dev_name, uint32_t *read_ahead)
+{
+	*read_ahead = 0;
+
+	return 1;
+}
+
+static int _set_dev_node_read_ahead(const char *dev_name, uint32_t read_ahead,
+				    uint32_t read_ahead_flags)
+{
+	return 1;
+}
+#endif
+
+typedef enum {
+	NODE_ADD,
+	NODE_DEL,
+	NODE_RENAME,
+	NODE_READ_AHEAD
+} node_op_t;
+
+static int _do_node_op(node_op_t type, const char *dev_name, uint32_t major,
+		       uint32_t minor, uid_t uid, gid_t gid, mode_t mode,
+		       const char *old_name, uint32_t read_ahead,
+		       uint32_t read_ahead_flags)
+{
+	switch (type) {
+	case NODE_ADD:
+		return _add_dev_node(dev_name, major, minor, uid, gid, mode);
+	case NODE_DEL:
+		return _rm_dev_node(dev_name);
+	case NODE_RENAME:
+		return _rename_dev_node(old_name, dev_name);
+	case NODE_READ_AHEAD:
+		return _set_dev_node_read_ahead(dev_name, read_ahead,
+						read_ahead_flags);
+	}
+
+	return 1;
+}
+
+static DM_LIST_INIT(_node_ops);
+
+struct node_op_parms {
+	struct dm_list list;
+	node_op_t type;
+	char *dev_name;
+	uint32_t major;
+	uint32_t minor;
+	uid_t uid;
+	gid_t gid;
+	mode_t mode;
+	uint32_t read_ahead;
+	uint32_t read_ahead_flags;
+	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, uid_t uid, gid_t gid, mode_t mode,
+			  const char *old_name, uint32_t read_ahead,
+			  uint32_t read_ahead_flags)
+{
+	struct node_op_parms *nop;
+	struct dm_list *noph, *nopht;
+	size_t len = strlen(dev_name) + strlen(old_name) + 2;
+	char *pos;
+
+	/*
+	 * Ignore any outstanding operations on the node if deleting it
+	 */
+	if (type == NODE_DEL) {
+		dm_list_iterate_safe(noph, nopht, &_node_ops) {
+			nop = dm_list_item(noph, struct node_op_parms);
+			if (!strcmp(dev_name, nop->dev_name)) {
+				dm_list_del(&nop->list);
+				dm_free(nop);
+			}
+		}
+	}
+
+	if (!(nop = dm_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;
+	nop->uid = uid;
+	nop->gid = gid;
+	nop->mode = mode;
+	nop->read_ahead = read_ahead;
+	nop->read_ahead_flags = read_ahead_flags;
+
+	_store_str(&pos, &nop->dev_name, dev_name);
+	_store_str(&pos, &nop->old_name, old_name);
+
+	dm_list_add(&_node_ops, &nop->list);
+
+	return 1;
+}
+
+static void _pop_node_ops(void)
+{
+	struct dm_list *noph, *nopht;
+	struct node_op_parms *nop;
+
+	dm_list_iterate_safe(noph, nopht, &_node_ops) {
+		nop = dm_list_item(noph, struct node_op_parms);
+		_do_node_op(nop->type, nop->dev_name, nop->major, nop->minor,
+			    nop->uid, nop->gid, nop->mode, nop->old_name,
+			    nop->read_ahead, nop->read_ahead_flags);
+		dm_list_del(&nop->list);
+		dm_free(nop);
+	}
+}
+
+int add_dev_node(const char *dev_name, uint32_t major, uint32_t minor,
+		 uid_t uid, gid_t gid, mode_t mode)
+{
+	log_debug("%s: Stacking NODE_ADD (%" PRIu32 ",%" PRIu32 ") %u:%u 0%o",
+		  dev_name, major, minor, uid, gid, mode);
+
+	return _stack_node_op(NODE_ADD, dev_name, major, minor, uid, gid, mode,
+			      "", 0, 0);
+}
+
+int rename_dev_node(const char *old_name, const char *new_name)
+{
+	log_debug("%s: Stacking NODE_RENAME to %s", old_name, new_name);
+
+	return _stack_node_op(NODE_RENAME, new_name, 0, 0, 0, 0, 0, old_name,
+			      0, 0);
+}
+
+int rm_dev_node(const char *dev_name)
+{
+	log_debug("%s: Stacking NODE_DEL (replaces other stacked ops)", dev_name);
+
+	return _stack_node_op(NODE_DEL, dev_name, 0, 0, 0, 0, 0, "", 0, 0);
+}
+
+int set_dev_node_read_ahead(const char *dev_name, uint32_t read_ahead,
+			    uint32_t read_ahead_flags)
+{
+	if (read_ahead == DM_READ_AHEAD_AUTO)
+		return 1;
+
+	log_debug("%s: Stacking NODE_READ_AHEAD %" PRIu32 " (flags=%" PRIu32
+		  ")", dev_name, read_ahead, read_ahead_flags);
+
+	return _stack_node_op(NODE_READ_AHEAD, dev_name, 0, 0, 0, 0, 0, "",
+			      read_ahead, read_ahead_flags);
+}
+
+void update_devs(void)
+{
+	_pop_node_ops();
+}
+
+int dm_set_dev_dir(const char *dev_dir)
+{
+	size_t len;
+	const char *slash;
+	if (*dev_dir != '/') {
+		log_debug("Invalid dev_dir value, %s: "
+			  "not an absolute name.", dev_dir);
+		return 0;
+	}
+
+	len = strlen(dev_dir);
+	slash = dev_dir[len-1] == '/' ? "" : "/";
+
+	if (snprintf(_dm_dir, sizeof _dm_dir, "%s%s%s", dev_dir, slash, DM_DIR)
+	    >= sizeof _dm_dir) {
+		log_debug("Invalid dev_dir value, %s: name too long.", dev_dir);
+		return 0;
+	}
+
+	return 1;
+}
+
+const char *dm_dir(void)
+{
+	return _dm_dir;
+}
+
+int dm_mknodes(const char *name)
+{
+	struct dm_task *dmt;
+	int r = 0;
+
+	if (!(dmt = dm_task_create(DM_DEVICE_MKNODES)))
+		return 0;
+
+	if (name && !dm_task_set_name(dmt, name))
+		goto out;
+
+	if (!dm_task_no_open_count(dmt))
+		goto out;
+
+	r = dm_task_run(dmt);
+
+out:
+	dm_task_destroy(dmt);
+	return r;
+}
+
+int dm_driver_version(char *version, size_t size)
+{
+	struct dm_task *dmt;
+	int r = 0;
+
+	if (!(dmt = dm_task_create(DM_DEVICE_VERSION)))
+		return 0;
+
+	if (!dm_task_run(dmt))
+		log_error("Failed to get driver version");
+
+	if (!dm_task_get_driver_version(dmt, version, size))
+		goto out;
+
+	r = 1;
+
+out:
+	dm_task_destroy(dmt);
+	return r;
+}
+
Index: src/external/gpl2/lvm2tools/dist/libdm/libdm-common.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/libdm-common.h
diff -N src/external/gpl2/lvm2tools/dist/libdm/libdm-common.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/libdm-common.h	13 Dec 2008 14:39:35 -0000	1.1.1.1.2.2
@@ -0,0 +1,36 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef LIB_DMCOMMON_H
+#define LIB_DMCOMMON_H
+
+#include "libdevmapper.h"
+
+struct target *create_target(uint64_t start,
+			     uint64_t len,
+			     const char *type, const char *params);
+
+int add_dev_node(const char *dev_name, uint32_t minor, uint32_t major,
+		 uid_t uid, gid_t gid, mode_t mode);
+int rm_dev_node(const char *dev_name);
+int rename_dev_node(const char *old_name, const char *new_name);
+int get_dev_node_read_ahead(const char *dev_name, uint32_t *read_ahead);
+int set_dev_node_read_ahead(const char *dev_name, uint32_t read_ahead,
+			    uint32_t read_ahead_flags);
+void update_devs(void);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/libdm/libdm-deptree.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/libdm-deptree.c
diff -N src/external/gpl2/lvm2tools/dist/libdm/libdm-deptree.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/libdm-deptree.c	18 Dec 2008 01:19:29 -0000	1.1.1.1.2.3
@@ -0,0 +1,1860 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "dmlib.h"
+#include "libdm-targets.h"
+#include "libdm-common.h"
+#include "kdev_t.h"
+#include "dm-ioctl.h"
+
+#include <stdarg.h>
+#include <sys/param.h>
+
+#define MAX_TARGET_PARAMSIZE 500000
+
+/* FIXME Fix interface so this is used only by LVM */
+#define UUID_PREFIX "LVM-"
+
+/* Supported segment types */
+enum {
+	SEG_ERROR, 
+	SEG_LINEAR,
+	SEG_MIRRORED,
+	SEG_SNAPSHOT,
+	SEG_SNAPSHOT_ORIGIN,
+	SEG_STRIPED,
+	SEG_ZERO,
+};
+
+/* FIXME Add crypt and multipath support */
+
+struct {
+	unsigned type;
+	const char *target;
+} dm_segtypes[] = {
+	{ SEG_ERROR, "error" },
+	{ SEG_LINEAR, "linear" },
+	{ SEG_MIRRORED, "mirror" },
+	{ SEG_SNAPSHOT, "snapshot" },
+	{ SEG_SNAPSHOT_ORIGIN, "snapshot-origin" },
+	{ SEG_STRIPED, "striped" },
+	{ SEG_ZERO, "zero"},
+};
+
+/* Some segment types have a list of areas of other devices attached */
+struct seg_area {
+	struct dm_list list;
+
+	struct dm_tree_node *dev_node;
+
+	uint64_t offset;
+};
+
+/* Per-segment properties */
+struct load_segment {
+	struct dm_list list;
+
+	unsigned type;
+
+	uint64_t size;
+
+	unsigned area_count;		/* Linear + Striped + Mirrored */
+	struct dm_list areas;		/* Linear + Striped + Mirrored */
+
+	uint32_t stripe_size;		/* Striped */
+
+	int persistent;			/* Snapshot */
+	uint32_t chunk_size;		/* Snapshot */
+	struct dm_tree_node *cow;	/* Snapshot */
+	struct dm_tree_node *origin;	/* Snapshot + Snapshot origin */
+
+	struct dm_tree_node *log;	/* Mirror */
+	uint32_t region_size;		/* Mirror */
+	unsigned clustered;		/* Mirror */
+	unsigned mirror_area_count;	/* Mirror */
+	uint32_t flags;			/* Mirror log */
+	char *uuid;			/* Clustered mirror log */
+};
+
+/* Per-device properties */
+struct load_properties {
+	int read_only;
+	uint32_t major;
+	uint32_t minor;
+
+	uint32_t read_ahead;
+	uint32_t read_ahead_flags;
+
+	unsigned segment_count;
+	unsigned size_changed;
+	struct dm_list segs;
+
+	const char *new_name;
+};
+
+/* Two of these used to join two nodes with uses and used_by. */
+struct dm_tree_link {
+	struct dm_list list;
+	struct dm_tree_node *node;
+};
+
+struct dm_tree_node {
+	struct dm_tree *dtree;
+
+        const char *name;
+        const char *uuid;
+        struct dm_info info;
+
+        struct dm_list uses;       	/* Nodes this node uses */
+        struct dm_list used_by;    	/* Nodes that use this node */
+
+	int activation_priority;	/* 0 gets activated first */
+
+	void *context;			/* External supplied context */
+
+	struct load_properties props;	/* For creation/table (re)load */
+};
+
+struct dm_tree {
+	struct dm_pool *mem;
+	struct dm_hash_table *devs;
+	struct dm_hash_table *uuids;
+	struct dm_tree_node root;
+	int skip_lockfs;		/* 1 skips lockfs (for non-snapshots) */
+	int no_flush;		/* 1 sets noflush (mirrors/multipath) */
+};
+
+/* FIXME Consider exporting this */
+static int _dm_snprintf(char *buf, size_t bufsize, const char *format, ...)
+{
+        int n;
+        va_list ap;
+
+        va_start(ap, format);
+        n = vsnprintf(buf, bufsize, format, ap);
+        va_end(ap);
+
+        if (n < 0 || (n > (int) bufsize - 1))
+                return -1;
+
+        return n;
+}
+
+struct dm_tree *dm_tree_create(void)
+{
+	struct dm_tree *dtree;
+
+	if (!(dtree = dm_malloc(sizeof(*dtree)))) {
+		log_error("dm_tree_create malloc failed");
+		return NULL;
+	}
+
+	memset(dtree, 0, sizeof(*dtree));
+	dtree->root.dtree = dtree;
+	dm_list_init(&dtree->root.uses);
+	dm_list_init(&dtree->root.used_by);
+	dtree->skip_lockfs = 0;
+	dtree->no_flush = 0;
+
+	if (!(dtree->mem = dm_pool_create("dtree", 1024))) {
+		log_error("dtree pool creation failed");
+		dm_free(dtree);
+		return NULL;
+	}
+
+	if (!(dtree->devs = dm_hash_create(8))) {
+		log_error("dtree hash creation failed");
+		dm_pool_destroy(dtree->mem);
+		dm_free(dtree);
+		return NULL;
+	}
+
+	if (!(dtree->uuids = dm_hash_create(32))) {
+		log_error("dtree uuid hash creation failed");
+		dm_hash_destroy(dtree->devs);
+		dm_pool_destroy(dtree->mem);
+		dm_free(dtree);
+		return NULL;
+	}
+
+	return dtree;
+}
+
+void dm_tree_free(struct dm_tree *dtree)
+{
+	if (!dtree)
+		return;
+
+	dm_hash_destroy(dtree->uuids);
+	dm_hash_destroy(dtree->devs);
+	dm_pool_destroy(dtree->mem);
+	dm_free(dtree);
+}
+
+static int _nodes_are_linked(struct dm_tree_node *parent,
+			     struct dm_tree_node *child)
+{
+	struct dm_tree_link *dlink;
+
+	dm_list_iterate_items(dlink, &parent->uses)
+		if (dlink->node == child)
+			return 1;
+
+	return 0;
+}
+
+static int _link(struct dm_list *list, struct dm_tree_node *node)
+{
+	struct dm_tree_link *dlink;
+
+	if (!(dlink = dm_pool_alloc(node->dtree->mem, sizeof(*dlink)))) {
+		log_error("dtree link allocation failed");
+		return 0;
+	}
+
+	dlink->node = node;
+	dm_list_add(list, &dlink->list);
+
+	return 1;
+}
+
+static int _link_nodes(struct dm_tree_node *parent,
+		       struct dm_tree_node *child)
+{
+	if (_nodes_are_linked(parent, child))
+		return 1;
+
+	if (!_link(&parent->uses, child))
+		return 0;
+
+	if (!_link(&child->used_by, parent))
+		return 0;
+
+	return 1;
+}
+
+static void _unlink(struct dm_list *list, struct dm_tree_node *node)
+{
+	struct dm_tree_link *dlink;
+
+	dm_list_iterate_items(dlink, list)
+		if (dlink->node == node) {
+			dm_list_del(&dlink->list);
+			break;
+		}
+}
+
+static void _unlink_nodes(struct dm_tree_node *parent,
+			  struct dm_tree_node *child)
+{
+	if (!_nodes_are_linked(parent, child))
+		return;
+
+	_unlink(&parent->uses, child);
+	_unlink(&child->used_by, parent);
+}
+
+static int _add_to_toplevel(struct dm_tree_node *node)
+{
+	return _link_nodes(&node->dtree->root, node);
+}
+
+static void _remove_from_toplevel(struct dm_tree_node *node)
+{
+	return _unlink_nodes(&node->dtree->root, node);
+}
+
+static int _add_to_bottomlevel(struct dm_tree_node *node)
+{
+	return _link_nodes(node, &node->dtree->root);
+}
+
+static void _remove_from_bottomlevel(struct dm_tree_node *node)
+{
+	return _unlink_nodes(node, &node->dtree->root);
+}
+
+static int _link_tree_nodes(struct dm_tree_node *parent, struct dm_tree_node *child)
+{
+	/* Don't link to root node if child already has a parent */
+	if ((parent == &parent->dtree->root)) {
+		if (dm_tree_node_num_children(child, 1))
+			return 1;
+	} else
+		_remove_from_toplevel(child);
+
+	if ((child == &child->dtree->root)) {
+		if (dm_tree_node_num_children(parent, 0))
+			return 1;
+	} else
+		_remove_from_bottomlevel(parent);
+
+	return _link_nodes(parent, child);
+}
+
+static struct dm_tree_node *_create_dm_tree_node(struct dm_tree *dtree,
+						 const char *name,
+						 const char *uuid,
+						 struct dm_info *info,
+						 void *context)
+{
+	struct dm_tree_node *node;
+	uint64_t dev;
+
+	if (!(node = dm_pool_zalloc(dtree->mem, sizeof(*node)))) {
+		log_error("_create_dm_tree_node alloc failed");
+		return NULL;
+	}
+
+	node->dtree = dtree;
+
+	node->name = name;
+	node->uuid = uuid;
+	node->info = *info;
+	node->context = context;
+	node->activation_priority = 0;
+
+	dm_list_init(&node->uses);
+	dm_list_init(&node->used_by);
+	dm_list_init(&node->props.segs);
+
+	dev = MKDEV(info->major, info->minor);
+
+	if (!dm_hash_insert_binary(dtree->devs, (const char *) &dev,
+				sizeof(dev), node)) {
+		log_error("dtree node hash insertion failed");
+		dm_pool_free(dtree->mem, node);
+		return NULL;
+	}
+
+	if (uuid && *uuid &&
+	    !dm_hash_insert(dtree->uuids, uuid, node)) {
+		log_error("dtree uuid hash insertion failed");
+		dm_hash_remove_binary(dtree->devs, (const char *) &dev,
+				      sizeof(dev));
+		dm_pool_free(dtree->mem, node);
+		return NULL;
+	}
+
+	return node;
+}
+
+static struct dm_tree_node *_find_dm_tree_node(struct dm_tree *dtree,
+					       uint32_t major, uint32_t minor)
+{
+	uint64_t dev = MKDEV(major, minor);
+
+	return dm_hash_lookup_binary(dtree->devs, (const char *) &dev,
+				  sizeof(dev));
+}
+
+static struct dm_tree_node *_find_dm_tree_node_by_uuid(struct dm_tree *dtree,
+						       const char *uuid)
+{
+	struct dm_tree_node *node;
+
+	if ((node = dm_hash_lookup(dtree->uuids, uuid)))
+		return node;
+
+	if (strncmp(uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1))
+		return NULL;
+
+	return dm_hash_lookup(dtree->uuids, uuid + sizeof(UUID_PREFIX) - 1);
+}
+
+static int _deps(struct dm_task **dmt, struct dm_pool *mem, uint32_t major, uint32_t minor,
+		 const char **name, const char **uuid,
+		 struct dm_info *info, struct dm_deps **deps)
+{
+	memset(info, 0, sizeof(*info));
+
+	if (!dm_is_dm_major(major)) {
+		*name = "";
+		*uuid = "";
+		*deps = NULL;
+		info->major = major;
+		info->minor = minor;
+		info->exists = 0;
+		info->live_table = 0;
+		info->inactive_table = 0;
+		info->read_only = 0;
+		return 1;
+	}
+
+	if (!(*dmt = dm_task_create(DM_DEVICE_DEPS))) {
+		log_error("deps dm_task creation failed");
+		return 0;
+	}
+
+	if (!dm_task_set_major(*dmt, major)) {
+		log_error("_deps: failed to set major for (%" PRIu32 ":%" PRIu32 ")",
+			  major, minor);
+		goto failed;
+	}
+
+	if (!dm_task_set_minor(*dmt, minor)) {
+		log_error("_deps: failed to set minor for (%" PRIu32 ":%" PRIu32 ")",
+			  major, minor);
+		goto failed;
+	}
+
+	if (!dm_task_run(*dmt)) {
+		log_error("_deps: task run failed for (%" PRIu32 ":%" PRIu32 ")",
+			  major, minor);
+		goto failed;
+	}
+
+	if (!dm_task_get_info(*dmt, info)) {
+		log_error("_deps: failed to get info for (%" PRIu32 ":%" PRIu32 ")",
+			  major, minor);
+		goto failed;
+	}
+
+	if (!info->exists) {
+		*name = "";
+		*uuid = "";
+		*deps = NULL;
+	} else {
+		if (info->major != major) {
+			log_error("Inconsistent dtree major number: %u != %u",
+				  major, info->major);
+			goto failed;
+		}
+		if (info->minor != minor) {
+			log_error("Inconsistent dtree minor number: %u != %u",
+				  minor, info->minor);
+			goto failed;
+		}
+		if (!(*name = dm_pool_strdup(mem, dm_task_get_name(*dmt)))) {
+			log_error("name pool_strdup failed");
+			goto failed;
+		}
+		if (!(*uuid = dm_pool_strdup(mem, dm_task_get_uuid(*dmt)))) {
+			log_error("uuid pool_strdup failed");
+			goto failed;
+		}
+		*deps = dm_task_get_deps(*dmt);
+	}
+
+	return 1;
+
+failed:
+	dm_task_destroy(*dmt);
+	return 0;
+}
+
+static struct dm_tree_node *_add_dev(struct dm_tree *dtree,
+				     struct dm_tree_node *parent,
+				     uint32_t major, uint32_t minor)
+{
+	struct dm_task *dmt = NULL;
+	struct dm_info info;
+	struct dm_deps *deps = NULL;
+	const char *name = NULL;
+	const char *uuid = NULL;
+	struct dm_tree_node *node = NULL;
+	uint32_t i;
+	int new = 0;
+
+	/* Already in tree? */
+	if (!(node = _find_dm_tree_node(dtree, major, minor))) {
+		if (!_deps(&dmt, dtree->mem, major, minor, &name, &uuid, &info, &deps))
+			return_NULL;
+
+		if (!(node = _create_dm_tree_node(dtree, name, uuid,
+						  &info, NULL)))
+			goto_out;
+		new = 1;
+	}
+
+	if (!_link_tree_nodes(parent, node)) {
+		node = NULL;
+		goto_out;
+	}
+
+	/* If node was already in tree, no need to recurse. */
+	if (!new)
+		goto out;
+
+	/* Can't recurse if not a mapped device or there are no dependencies */
+	if (!node->info.exists || !deps->count) {
+		if (!_add_to_bottomlevel(node)) {
+			stack;
+			node = NULL;
+		}
+		goto out;
+	}
+
+	/* Add dependencies to tree */
+	for (i = 0; i < deps->count; i++)
+		if (!_add_dev(dtree, node, MAJOR(deps->device[i]),
+			      MINOR(deps->device[i]))) {
+			node = NULL;
+			goto_out;
+		}
+
+out:
+	if (dmt)
+		dm_task_destroy(dmt);
+
+	return node;
+}
+
+static int _node_clear_table(struct dm_tree_node *dnode)
+{
+	struct dm_task *dmt;
+	struct dm_info *info;
+	const char *name;
+	int r;
+
+	if (!(info = &dnode->info)) {
+		log_error("_node_clear_table failed: missing info");
+		return 0;
+	}
+
+	if (!(name = dm_tree_node_get_name(dnode))) {
+		log_error("_node_clear_table failed: missing name");
+		return 0;
+	}
+
+	/* Is there a table? */
+	if (!info->exists || !info->inactive_table)
+		return 1;
+
+	log_verbose("Clearing inactive table %s (%" PRIu32 ":%" PRIu32 ")",
+		    name, info->major, info->minor);
+
+	if (!(dmt = dm_task_create(DM_DEVICE_CLEAR))) {
+		dm_task_destroy(dmt);
+		log_error("Table clear dm_task creation failed for %s", name);
+		return 0;
+	}
+
+	if (!dm_task_set_major(dmt, info->major) ||
+	    !dm_task_set_minor(dmt, info->minor)) {
+		log_error("Failed to set device number for %s table clear", name);
+		dm_task_destroy(dmt);
+		return 0;
+	}
+
+	r = dm_task_run(dmt);
+
+	if (!dm_task_get_info(dmt, info)) {
+		log_error("_node_clear_table failed: info missing after running task for %s", name);
+		r = 0;
+	}
+
+	dm_task_destroy(dmt);
+
+	return r;
+}
+
+struct dm_tree_node *dm_tree_add_new_dev(struct dm_tree *dtree,
+					    const char *name,
+					    const char *uuid,
+					    uint32_t major, uint32_t minor,
+					    int read_only,
+					    int clear_inactive,
+					    void *context)
+{
+	struct dm_tree_node *dnode;
+	struct dm_info info;
+	const char *name2;
+	const char *uuid2;
+
+	/* Do we need to add node to tree? */
+	if (!(dnode = dm_tree_find_node_by_uuid(dtree, uuid))) {
+		if (!(name2 = dm_pool_strdup(dtree->mem, name))) {
+			log_error("name pool_strdup failed");
+			return NULL;
+		}
+		if (!(uuid2 = dm_pool_strdup(dtree->mem, uuid))) {
+			log_error("uuid pool_strdup failed");
+			return NULL;
+		}
+
+		info.major = 0;
+		info.minor = 0;
+		info.exists = 0;
+		info.live_table = 0;
+		info.inactive_table = 0;
+		info.read_only = 0;
+
+		if (!(dnode = _create_dm_tree_node(dtree, name2, uuid2,
+						   &info, context)))
+			return_NULL;
+
+		/* Attach to root node until a table is supplied */
+		if (!_add_to_toplevel(dnode) || !_add_to_bottomlevel(dnode))
+			return_NULL;
+
+		dnode->props.major = major;
+		dnode->props.minor = minor;
+		dnode->props.new_name = NULL;
+		dnode->props.size_changed = 0;
+	} else if (strcmp(name, dnode->name)) {
+		/* Do we need to rename node? */
+		if (!(dnode->props.new_name = dm_pool_strdup(dtree->mem, name))) {
+			log_error("name pool_strdup failed");
+			return 0;
+		}
+	}
+
+	dnode->props.read_only = read_only ? 1 : 0;
+	dnode->props.read_ahead = DM_READ_AHEAD_AUTO;
+	dnode->props.read_ahead_flags = 0;
+
+	if (clear_inactive && !_node_clear_table(dnode))
+		return_NULL;
+
+	dnode->context = context;
+
+	return dnode;
+}
+
+void dm_tree_node_set_read_ahead(struct dm_tree_node *dnode,
+				 uint32_t read_ahead,
+				 uint32_t read_ahead_flags)
+{                          
+	dnode->props.read_ahead = read_ahead;
+	dnode->props.read_ahead_flags = read_ahead_flags;
+}
+
+int dm_tree_add_dev(struct dm_tree *dtree, uint32_t major, uint32_t minor)
+{
+	return _add_dev(dtree, &dtree->root, major, minor) ? 1 : 0;
+}
+
+const char *dm_tree_node_get_name(struct dm_tree_node *node)
+{
+	return node->info.exists ? node->name : "";
+}
+
+const char *dm_tree_node_get_uuid(struct dm_tree_node *node)
+{
+	return node->info.exists ? node->uuid : "";
+}
+
+const struct dm_info *dm_tree_node_get_info(struct dm_tree_node *node)
+{
+	return &node->info;
+}
+
+void *dm_tree_node_get_context(struct dm_tree_node *node)
+{
+	return node->context;
+}
+
+int dm_tree_node_num_children(struct dm_tree_node *node, uint32_t inverted)
+{
+	if (inverted) {
+		if (_nodes_are_linked(&node->dtree->root, node))
+			return 0;
+		return dm_list_size(&node->used_by);
+	}
+
+	if (_nodes_are_linked(node, &node->dtree->root))
+		return 0;
+
+	return dm_list_size(&node->uses);
+}
+
+/*
+ * Returns 1 if no prefix supplied
+ */
+static int _uuid_prefix_matches(const char *uuid, const char *uuid_prefix, size_t uuid_prefix_len)
+{
+	if (!uuid_prefix)
+		return 1;
+
+	if (!strncmp(uuid, uuid_prefix, uuid_prefix_len))
+		return 1;
+
+	/* Handle transition: active device uuids might be missing the prefix */
+	if (uuid_prefix_len <= 4)
+		return 0;
+
+	if (!strncmp(uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1))
+		return 0;
+
+	if (strncmp(uuid_prefix, UUID_PREFIX, sizeof(UUID_PREFIX) - 1))
+		return 0;
+
+	if (!strncmp(uuid, uuid_prefix + sizeof(UUID_PREFIX) - 1, uuid_prefix_len - (sizeof(UUID_PREFIX) - 1)))
+		return 1;
+
+	return 0;
+}
+
+/*
+ * Returns 1 if no children.
+ */
+static int _children_suspended(struct dm_tree_node *node,
+			       uint32_t inverted,
+			       const char *uuid_prefix,
+			       size_t uuid_prefix_len)
+{
+	struct dm_list *list;
+	struct dm_tree_link *dlink;
+	const struct dm_info *dinfo;
+	const char *uuid;
+
+	if (inverted) {
+		if (_nodes_are_linked(&node->dtree->root, node))
+			return 1;
+		list = &node->used_by;
+	} else {
+		if (_nodes_are_linked(node, &node->dtree->root))
+			return 1;
+		list = &node->uses;
+	}
+
+	dm_list_iterate_items(dlink, list) {
+		if (!(uuid = dm_tree_node_get_uuid(dlink->node))) {
+			stack;
+			continue;
+		}
+
+		/* Ignore if it doesn't belong to this VG */
+		if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
+			continue;
+
+		if (!(dinfo = dm_tree_node_get_info(dlink->node))) {
+			stack;	/* FIXME Is this normal? */
+			return 0;
+		}
+
+		if (!dinfo->suspended)
+			return 0;
+	}
+
+	return 1;
+}
+
+/*
+ * Set major and minor to zero for root of tree.
+ */
+struct dm_tree_node *dm_tree_find_node(struct dm_tree *dtree,
+					  uint32_t major,
+					  uint32_t minor)
+{
+	if (!major && !minor)
+		return &dtree->root;
+
+	return _find_dm_tree_node(dtree, major, minor);
+}
+
+/*
+ * Set uuid to NULL for root of tree.
+ */
+struct dm_tree_node *dm_tree_find_node_by_uuid(struct dm_tree *dtree,
+						  const char *uuid)
+{
+	if (!uuid || !*uuid)
+		return &dtree->root;
+
+	return _find_dm_tree_node_by_uuid(dtree, uuid);
+}
+
+/*
+ * First time set *handle to NULL.
+ * Set inverted to invert the tree.
+ */
+struct dm_tree_node *dm_tree_next_child(void **handle,
+					   struct dm_tree_node *parent,
+					   uint32_t inverted)
+{
+	struct dm_list **dlink = (struct dm_list **) handle;
+	struct dm_list *use_list;
+
+	if (inverted)
+		use_list = &parent->used_by;
+	else
+		use_list = &parent->uses;
+
+	if (!*dlink)
+		*dlink = dm_list_first(use_list);
+	else
+		*dlink = dm_list_next(use_list, *dlink);
+
+	return (*dlink) ? dm_list_item(*dlink, struct dm_tree_link)->node : NULL;
+}
+
+/*
+ * Deactivate a device with its dependencies if the uuid prefix matches.
+ */
+static int _info_by_dev(uint32_t major, uint32_t minor, int with_open_count,
+			struct dm_info *info)
+{
+	struct dm_task *dmt;
+	int r;
+
+	if (!(dmt = dm_task_create(DM_DEVICE_INFO))) {
+		log_error("_info_by_dev: dm_task creation failed");
+		return 0;
+	}
+
+	if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {
+		log_error("_info_by_dev: Failed to set device number");
+		dm_task_destroy(dmt);
+		return 0;
+	}
+
+	if (!with_open_count && !dm_task_no_open_count(dmt))
+		log_error("Failed to disable open_count");
+
+	if ((r = dm_task_run(dmt)))
+		r = dm_task_get_info(dmt, info);
+
+	dm_task_destroy(dmt);
+
+	return r;
+}
+
+static int _deactivate_node(const char *name, uint32_t major, uint32_t minor)
+{
+	struct dm_task *dmt;
+	int r;
+
+	log_verbose("Removing %s (%" PRIu32 ":%" PRIu32 ")", name, major, minor);
+
+	if (!(dmt = dm_task_create(DM_DEVICE_REMOVE))) {
+		log_error("Deactivation dm_task creation failed for %s", name);
+		return 0;
+	}
+
+	if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {
+		log_error("Failed to set device number for %s deactivation", name);
+		dm_task_destroy(dmt);
+		return 0;
+	}
+
+	if (!dm_task_no_open_count(dmt))
+		log_error("Failed to disable open_count");
+
+	r = dm_task_run(dmt);
+
+	/* FIXME Until kernel returns actual name so dm-ioctl.c can handle it */
+	rm_dev_node(name);
+
+	/* FIXME Remove node from tree or mark invalid? */
+
+	dm_task_destroy(dmt);
+
+	return r;
+}
+
+static int _rename_node(const char *old_name, const char *new_name, uint32_t major, uint32_t minor)
+{
+	struct dm_task *dmt;
+	int r = 0;
+
+	log_verbose("Renaming %s (%" PRIu32 ":%" PRIu32 ") to %s", old_name, major, minor, new_name);
+
+	if (!(dmt = dm_task_create(DM_DEVICE_RENAME))) {
+		log_error("Rename dm_task creation failed for %s", old_name);
+		return 0;
+	}
+
+	if (!dm_task_set_name(dmt, old_name)) {
+		log_error("Failed to set name for %s rename.", old_name);
+		goto out;
+	}
+
+	if (!dm_task_set_newname(dmt, new_name))
+                goto_out;
+
+	if (!dm_task_no_open_count(dmt))
+		log_error("Failed to disable open_count");
+
+	r = dm_task_run(dmt);
+
+out:
+	dm_task_destroy(dmt);
+
+	return r;
+}
+
+/* FIXME Merge with _suspend_node? */
+static int _resume_node(const char *name, uint32_t major, uint32_t minor,
+			uint32_t read_ahead, uint32_t read_ahead_flags,
+			struct dm_info *newinfo)
+{
+	struct dm_task *dmt;
+	int r;
+
+	log_verbose("Resuming %s (%" PRIu32 ":%" PRIu32 ")", name, major, minor);
+
+	if (!(dmt = dm_task_create(DM_DEVICE_RESUME))) {
+		log_error("Suspend dm_task creation failed for %s", name);
+		return 0;
+	}
+
+	/* FIXME Kernel should fill in name on return instead */
+	if (!dm_task_set_name(dmt, name)) {
+		log_error("Failed to set readahead device name for %s", name);
+		dm_task_destroy(dmt);
+		return 0;
+	}
+
+	if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {
+		log_error("Failed to set device number for %s resumption.", name);
+		dm_task_destroy(dmt);
+		return 0;
+	}
+
+	if (!dm_task_no_open_count(dmt))
+		log_error("Failed to disable open_count");
+
+	if (!dm_task_set_read_ahead(dmt, read_ahead, read_ahead_flags))
+		log_error("Failed to set read ahead");
+
+	if ((r = dm_task_run(dmt)))
+		r = dm_task_get_info(dmt, newinfo);
+
+	dm_task_destroy(dmt);
+
+	return r;
+}
+
+static int _suspend_node(const char *name, uint32_t major, uint32_t minor,
+			 int skip_lockfs, int no_flush, struct dm_info *newinfo)
+{
+	struct dm_task *dmt;
+	int r;
+
+	log_verbose("Suspending %s (%" PRIu32 ":%" PRIu32 ")%s%s",
+		    name, major, minor,
+		    skip_lockfs ? "" : " with filesystem sync",
+		    no_flush ? "" : " with device flush");
+
+	if (!(dmt = dm_task_create(DM_DEVICE_SUSPEND))) {
+		log_error("Suspend dm_task creation failed for %s", name);
+		return 0;
+	}
+
+	if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {
+		log_error("Failed to set device number for %s suspension.", name);
+		dm_task_destroy(dmt);
+		return 0;
+	}
+
+	if (!dm_task_no_open_count(dmt))
+		log_error("Failed to disable open_count");
+
+	if (skip_lockfs && !dm_task_skip_lockfs(dmt))
+		log_error("Failed to set skip_lockfs flag.");
+
+	if (no_flush && !dm_task_no_flush(dmt))
+		log_error("Failed to set no_flush flag.");
+
+	if ((r = dm_task_run(dmt)))
+		r = dm_task_get_info(dmt, newinfo);
+
+	dm_task_destroy(dmt);
+
+	return r;
+}
+
+int dm_tree_deactivate_children(struct dm_tree_node *dnode,
+				   const char *uuid_prefix,
+				   size_t uuid_prefix_len)
+{
+	void *handle = NULL;
+	struct dm_tree_node *child = dnode;
+	struct dm_info info;
+	const struct dm_info *dinfo;
+	const char *name;
+	const char *uuid;
+
+	while ((child = dm_tree_next_child(&handle, dnode, 0))) {
+		if (!(dinfo = dm_tree_node_get_info(child))) {
+			stack;
+			continue;
+		}
+
+		if (!(name = dm_tree_node_get_name(child))) {
+			stack;
+			continue;
+		}
+
+		if (!(uuid = dm_tree_node_get_uuid(child))) {
+			stack;
+			continue;
+		}
+
+		/* Ignore if it doesn't belong to this VG */
+		if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
+			continue;
+
+		/* Refresh open_count */
+		if (!_info_by_dev(dinfo->major, dinfo->minor, 1, &info) ||
+		    !info.exists || info.open_count)
+			continue;
+
+		if (!_deactivate_node(name, info.major, info.minor)) {
+			log_error("Unable to deactivate %s (%" PRIu32
+				  ":%" PRIu32 ")", name, info.major,
+				  info.minor);
+			continue;
+		}
+
+		if (dm_tree_node_num_children(child, 0))
+			dm_tree_deactivate_children(child, uuid_prefix, uuid_prefix_len);
+	}
+
+	return 1;
+}
+
+void dm_tree_skip_lockfs(struct dm_tree_node *dnode)
+{
+	dnode->dtree->skip_lockfs = 1;
+}
+
+void dm_tree_use_no_flush_suspend(struct dm_tree_node *dnode)
+{
+	dnode->dtree->no_flush = 1;
+}
+
+int dm_tree_suspend_children(struct dm_tree_node *dnode,
+				   const char *uuid_prefix,
+				   size_t uuid_prefix_len)
+{
+	void *handle = NULL;
+	struct dm_tree_node *child = dnode;
+	struct dm_info info, newinfo;
+	const struct dm_info *dinfo;
+	const char *name;
+	const char *uuid;
+
+	/* Suspend nodes at this level of the tree */
+	while ((child = dm_tree_next_child(&handle, dnode, 0))) {
+		if (!(dinfo = dm_tree_node_get_info(child))) {
+			stack;
+			continue;
+		}
+
+		if (!(name = dm_tree_node_get_name(child))) {
+			stack;
+			continue;
+		}
+
+		if (!(uuid = dm_tree_node_get_uuid(child))) {
+			stack;
+			continue;
+		}
+
+		/* Ignore if it doesn't belong to this VG */
+		if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
+			continue;
+
+		/* Ensure immediate parents are already suspended */
+		if (!_children_suspended(child, 1, uuid_prefix, uuid_prefix_len))
+			continue;
+
+		if (!_info_by_dev(dinfo->major, dinfo->minor, 0, &info) ||
+		    !info.exists || info.suspended)
+			continue;
+
+		if (!_suspend_node(name, info.major, info.minor,
+				   child->dtree->skip_lockfs,
+				   child->dtree->no_flush, &newinfo)) {
+			log_error("Unable to suspend %s (%" PRIu32
+				  ":%" PRIu32 ")", name, info.major,
+				  info.minor);
+			continue;
+		}
+
+		/* Update cached info */
+		child->info = newinfo;
+	}
+
+	/* Then suspend any child nodes */
+	handle = NULL;
+
+	while ((child = dm_tree_next_child(&handle, dnode, 0))) {
+		if (!(uuid = dm_tree_node_get_uuid(child))) {
+			stack;
+			continue;
+		}
+
+		/* Ignore if it doesn't belong to this VG */
+		if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
+			continue;
+
+		if (dm_tree_node_num_children(child, 0))
+			dm_tree_suspend_children(child, uuid_prefix, uuid_prefix_len);
+	}
+
+	return 1;
+}
+
+int dm_tree_activate_children(struct dm_tree_node *dnode,
+				 const char *uuid_prefix,
+				 size_t uuid_prefix_len)
+{
+	void *handle = NULL;
+	struct dm_tree_node *child = dnode;
+	struct dm_info newinfo;
+	const char *name;
+	const char *uuid;
+	int priority;
+
+	/* Activate children first */
+	while ((child = dm_tree_next_child(&handle, dnode, 0))) {
+		if (!(uuid = dm_tree_node_get_uuid(child))) {
+			stack;
+			continue;
+		}
+
+		if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
+			continue;
+
+		if (dm_tree_node_num_children(child, 0))
+			dm_tree_activate_children(child, uuid_prefix, uuid_prefix_len);
+	}
+
+	handle = NULL;
+
+	for (priority = 0; priority < 2; priority++) {
+		while ((child = dm_tree_next_child(&handle, dnode, 0))) {
+			if (!(uuid = dm_tree_node_get_uuid(child))) {
+				stack;
+				continue;
+			}
+
+			if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
+				continue;
+
+			if (priority != child->activation_priority)
+				continue;
+
+			if (!(name = dm_tree_node_get_name(child))) {
+				stack;
+				continue;
+			}
+
+			/* Rename? */
+			if (child->props.new_name) {
+				if (!_rename_node(name, child->props.new_name, child->info.major, child->info.minor)) {
+					log_error("Failed to rename %s (%" PRIu32
+						  ":%" PRIu32 ") to %s", name, child->info.major,
+						  child->info.minor, child->props.new_name);
+					return 0;
+				}
+				child->name = child->props.new_name;
+				child->props.new_name = NULL;
+			}
+
+			if (!child->info.inactive_table && !child->info.suspended)
+				continue;
+
+			if (!_resume_node(child->name, child->info.major, child->info.minor,
+					  child->props.read_ahead,
+					  child->props.read_ahead_flags, &newinfo)) {
+				log_error("Unable to resume %s (%" PRIu32
+					  ":%" PRIu32 ")", child->name, child->info.major,
+					  child->info.minor);
+				continue;
+			}
+
+			/* Update cached info */
+			child->info = newinfo;
+		}
+	}
+
+	handle = NULL;
+
+	return 1;
+}
+
+static int _create_node(struct dm_tree_node *dnode)
+{
+	int r = 0;
+	struct dm_task *dmt;
+
+	log_verbose("Creating %s", dnode->name);
+
+	if (!(dmt = dm_task_create(DM_DEVICE_CREATE))) {
+		log_error("Create dm_task creation failed for %s", dnode->name);
+		return 0;
+	}
+
+	if (!dm_task_set_name(dmt, dnode->name)) {
+		log_error("Failed to set device name for %s", dnode->name);
+		goto out;
+	}
+
+	if (!dm_task_set_uuid(dmt, dnode->uuid)) {
+		log_error("Failed to set uuid for %s", dnode->name);
+		goto out;
+	}
+
+	if (dnode->props.major &&
+	    (!dm_task_set_major(dmt, dnode->props.major) ||
+	     !dm_task_set_minor(dmt, dnode->props.minor))) {
+		log_error("Failed to set device number for %s creation.", dnode->name);
+		goto out;
+	}
+
+	if (dnode->props.read_only && !dm_task_set_ro(dmt)) {
+		log_error("Failed to set read only flag for %s", dnode->name);
+		goto out;
+	}
+
+	if (!dm_task_no_open_count(dmt))
+		log_error("Failed to disable open_count");
+
+	if ((r = dm_task_run(dmt)))
+		r = dm_task_get_info(dmt, &dnode->info);
+
+out:
+	dm_task_destroy(dmt);
+
+	return r;
+}
+
+
+static int _build_dev_string(char *devbuf, size_t bufsize, struct dm_tree_node *node)
+{
+	if (!dm_format_dev(devbuf, bufsize, node->info.major, node->info.minor)) {
+                log_error("Failed to format %s device number for %s as dm "
+                          "target (%u,%u)",
+                          node->name, node->uuid, node->info.major, node->info.minor);
+                return 0;
+	}
+
+	return 1;
+}
+
+static int _emit_areas_line(struct dm_task *dmt __attribute((unused)),
+			    struct load_segment *seg, char *params,
+			    size_t paramsize, int *pos)
+{
+	struct seg_area *area;
+	char devbuf[DM_FORMAT_DEV_BUFSIZE];
+	int tw;
+	const char *prefix = "";
+
+	dm_list_iterate_items(area, &seg->areas) {
+		if (!_build_dev_string(devbuf, sizeof(devbuf), area->dev_node))
+			return_0;
+
+		if ((tw = _dm_snprintf(params + *pos, paramsize - *pos, "%s%s %" PRIu64,
+					prefix, devbuf, area->offset)) < 0) {
+                        stack;	/* Out of space */
+                        return -1;
+                }
+
+		prefix = " ";
+		*pos += tw;
+	}
+
+	return 1;
+}
+
+static int _emit_segment_line(struct dm_task *dmt, struct load_segment *seg, uint64_t *seg_start, char *params, size_t paramsize)
+{
+	unsigned log_parm_count;
+        int pos = 0;
+	int tw;
+        int r;
+	char originbuf[DM_FORMAT_DEV_BUFSIZE], cowbuf[DM_FORMAT_DEV_BUFSIZE];
+	char logbuf[DM_FORMAT_DEV_BUFSIZE];
+	const char *logtype;
+
+	switch(seg->type) {
+	case SEG_ERROR:
+	case SEG_ZERO:
+	case SEG_LINEAR:
+		break;
+	case SEG_MIRRORED:
+		log_parm_count = 1;	/* Region size */
+		log_parm_count += hweight32(seg->flags);	/* [no]sync, block_on_error etc. */
+
+		if (seg->flags & DM_CORELOG)
+			log_parm_count--;   /* DM_CORELOG does not count in the param list */
+
+		if (seg->clustered) {
+			if (seg->uuid)
+				log_parm_count++;
+			if ((tw = _dm_snprintf(params + pos, paramsize - pos, "clustered-")) < 0) {
+                        	stack;	/* Out of space */
+                        	return -1;
+                	}
+			pos += tw;
+		}
+
+		if (!seg->log)
+			logtype = "core";
+		else {
+			logtype = "disk";
+			log_parm_count++;
+			if (!_build_dev_string(logbuf, sizeof(logbuf), seg->log))
+				return_0;
+		}
+
+		if ((tw = _dm_snprintf(params + pos, paramsize - pos, "%s %u ", logtype, log_parm_count)) < 0) {
+                        stack;	/* Out of space */
+                        return -1;
+                }
+		pos += tw;
+
+		if (seg->log) {
+			if ((tw = _dm_snprintf(params + pos, paramsize - pos, "%s ", logbuf)) < 0) {
+                        	stack;	/* Out of space */
+                        	return -1;
+                	}
+			pos += tw;
+		}
+
+		if ((tw = _dm_snprintf(params + pos, paramsize - pos, "%u ", seg->region_size)) < 0) {
+                       	stack; /* Out of space */
+                       	return -1;
+               	}
+		pos += tw;
+
+		if (seg->clustered && seg->uuid) {
+			if ((tw = _dm_snprintf(params + pos, paramsize - pos, "%s ", seg->uuid)) < 0) {
+				stack;  /* Out of space */
+				return -1;
+			}
+			pos += tw;
+		}
+
+		if ((seg->flags & DM_NOSYNC)) {
+			if ((tw = _dm_snprintf(params + pos, paramsize - pos, "nosync ")) < 0) {
+                       		stack; /* Out of space */
+                       		return -1;
+               		}
+			pos += tw;
+		} else if ((seg->flags & DM_FORCESYNC)) {
+			if ((tw = _dm_snprintf(params + pos, paramsize - pos, "sync ")) < 0) {
+                       		stack; /* Out of space */
+                       		return -1;
+               		}
+			pos += tw;
+		}
+
+		if ((seg->flags & DM_BLOCK_ON_ERROR)) {
+			if ((tw = _dm_snprintf(params + pos, paramsize - pos, "block_on_error ")) < 0) {
+                       		stack; /* Out of space */
+                       		return -1;
+               		}
+			pos += tw;
+		}
+
+		if ((tw = _dm_snprintf(params + pos, paramsize - pos, "%u ", seg->mirror_area_count)) < 0) {
+                       	stack; /* Out of space */
+                       	return -1;
+               	}
+		pos += tw;
+
+		break;
+	case SEG_SNAPSHOT:
+		if (!_build_dev_string(originbuf, sizeof(originbuf), seg->origin))
+			return_0;
+		if (!_build_dev_string(cowbuf, sizeof(cowbuf), seg->cow))
+			return_0;
+		if ((pos = _dm_snprintf(params, paramsize, "%s %s %c %d",
+                                        originbuf, cowbuf,
+					seg->persistent ? 'P' : 'N',
+                                        seg->chunk_size)) < 0) {
+                        stack;	/* Out of space */
+                        return -1;
+                }
+		break;
+	case SEG_SNAPSHOT_ORIGIN:
+		if (!_build_dev_string(originbuf, sizeof(originbuf), seg->origin))
+			return_0;
+		if ((pos = _dm_snprintf(params, paramsize, "%s",
+                                        originbuf)) < 0) {
+                        stack;	/* Out of space */
+                        return -1;
+                }
+		break;
+	case SEG_STRIPED:
+		if ((pos = _dm_snprintf(params, paramsize, "%u %u ",
+                                         seg->area_count,
+                                         seg->stripe_size)) < 0) {
+                        stack;	/* Out of space */
+                        return -1;
+                }
+		break;
+	}
+
+	switch(seg->type) {
+	case SEG_ERROR:
+	case SEG_SNAPSHOT:
+	case SEG_SNAPSHOT_ORIGIN:
+	case SEG_ZERO:
+		break;
+	case SEG_LINEAR:
+	case SEG_MIRRORED:
+	case SEG_STRIPED:
+		if ((r = _emit_areas_line(dmt, seg, params, paramsize, &pos)) <= 0) {
+			stack;
+			return r;
+		}
+		break;
+	}
+
+	log_debug("Adding target: %" PRIu64 " %" PRIu64 " %s %s",
+		  *seg_start, seg->size, dm_segtypes[seg->type].target, params);
+
+	if (!dm_task_add_target(dmt, *seg_start, seg->size, dm_segtypes[seg->type].target, params))
+		return_0;
+
+	*seg_start += seg->size;
+
+	return 1;
+}
+
+static int _emit_segment(struct dm_task *dmt, struct load_segment *seg,
+			 uint64_t *seg_start)
+{
+	char *params;
+	size_t paramsize = 4096;
+	int ret;
+
+	do {
+		if (!(params = dm_malloc(paramsize))) {
+			log_error("Insufficient space for target parameters.");
+			return 0;
+		}
+
+		params[0] = '\0';
+		ret = _emit_segment_line(dmt, seg, seg_start, params, paramsize);
+		dm_free(params);
+
+		if (!ret)
+			stack;
+
+		if (ret >= 0)
+			return ret;
+
+		log_debug("Insufficient space in params[%" PRIsize_t
+			  "] for target parameters.", paramsize);
+
+		paramsize *= 2;
+	} while (paramsize < MAX_TARGET_PARAMSIZE);
+
+	log_error("Target parameter size too big. Aborting.");
+	return 0;
+}
+
+static int _load_node(struct dm_tree_node *dnode)
+{
+	int r = 0;
+	struct dm_task *dmt;
+	struct load_segment *seg;
+	uint64_t seg_start = 0;
+
+	log_verbose("Loading %s table", dnode->name);
+
+	if (!(dmt = dm_task_create(DM_DEVICE_RELOAD))) {
+		log_error("Reload dm_task creation failed for %s", dnode->name);
+		return 0;
+	}
+
+	if (!dm_task_set_major(dmt, dnode->info.major) ||
+	    !dm_task_set_minor(dmt, dnode->info.minor)) {
+		log_error("Failed to set device number for %s reload.", dnode->name);
+		goto out;
+	}
+
+	if (dnode->props.read_only && !dm_task_set_ro(dmt)) {
+		log_error("Failed to set read only flag for %s", dnode->name);
+		goto out;
+	}
+
+	if (!dm_task_no_open_count(dmt))
+		log_error("Failed to disable open_count");
+
+	dm_list_iterate_items(seg, &dnode->props.segs)
+		if (!_emit_segment(dmt, seg, &seg_start))
+			goto_out;
+
+	if (!dm_task_suppress_identical_reload(dmt))
+		log_error("Failed to suppress reload of identical tables.");
+
+	if ((r = dm_task_run(dmt))) {
+		r = dm_task_get_info(dmt, &dnode->info);
+		if (r && !dnode->info.inactive_table)
+			log_verbose("Suppressed %s identical table reload.",
+				    dnode->name);
+
+		if ((dnode->props.size_changed =
+		     (dm_task_get_existing_table_size(dmt) == seg_start) ? 0 : 1))
+			log_debug("Table size changed from %" PRIu64 " to %"
+				  PRIu64 " for %s",
+				  dm_task_get_existing_table_size(dmt),
+				  seg_start, dnode->name);
+	}
+
+	dnode->props.segment_count = 0;
+
+out:
+	dm_task_destroy(dmt);
+
+	return r;
+}
+
+int dm_tree_preload_children(struct dm_tree_node *dnode,
+			     const char *uuid_prefix,
+			     size_t uuid_prefix_len)
+{
+	void *handle = NULL;
+	struct dm_tree_node *child;
+	struct dm_info newinfo;
+
+	/* Preload children first */
+	while ((child = dm_tree_next_child(&handle, dnode, 0))) {
+		/* Skip existing non-device-mapper devices */
+		if (!child->info.exists && child->info.major)
+			continue;
+
+		/* Ignore if it doesn't belong to this VG */
+		if (child->info.exists &&
+		    !_uuid_prefix_matches(child->uuid, uuid_prefix, uuid_prefix_len))
+			continue;
+
+		if (dm_tree_node_num_children(child, 0))
+			dm_tree_preload_children(child, uuid_prefix, uuid_prefix_len);
+
+		/* FIXME Cope if name exists with no uuid? */
+		if (!child->info.exists) {
+			if (!_create_node(child)) {
+				stack;
+				return 0;
+			}
+		}
+
+		if (!child->info.inactive_table && child->props.segment_count) {
+			if (!_load_node(child)) {
+				stack;
+				return 0;
+			}
+		}
+
+		/* Resume device immediately if it has parents and its size changed */
+		if (!dm_tree_node_num_children(child, 1) || !child->props.size_changed)
+			continue;
+
+		if (!child->info.inactive_table && !child->info.suspended)
+			continue;
+
+		if (!_resume_node(child->name, child->info.major, child->info.minor,
+				  child->props.read_ahead,
+				  child->props.read_ahead_flags, &newinfo)) {
+			log_error("Unable to resume %s (%" PRIu32
+				  ":%" PRIu32 ")", child->name, child->info.major,
+				  child->info.minor);
+			continue;
+		}
+
+		/* Update cached info */
+		child->info = newinfo;
+	}
+
+	handle = NULL;
+
+	return 1;
+}
+
+/*
+ * Returns 1 if unsure.
+ */
+int dm_tree_children_use_uuid(struct dm_tree_node *dnode,
+				 const char *uuid_prefix,
+				 size_t uuid_prefix_len)
+{
+	void *handle = NULL;
+	struct dm_tree_node *child = dnode;
+	const char *uuid;
+
+	while ((child = dm_tree_next_child(&handle, dnode, 0))) {
+		if (!(uuid = dm_tree_node_get_uuid(child))) {
+			log_error("Failed to get uuid for dtree node.");
+			return 1;
+		}
+
+		if (_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
+			return 1;
+
+		if (dm_tree_node_num_children(child, 0))
+			dm_tree_children_use_uuid(child, uuid_prefix, uuid_prefix_len);
+	}
+
+	return 0;
+}
+
+/*
+ * Target functions
+ */
+static struct load_segment *_add_segment(struct dm_tree_node *dnode, unsigned type, uint64_t size)
+{
+	struct load_segment *seg;
+
+	if (!(seg = dm_pool_zalloc(dnode->dtree->mem, sizeof(*seg)))) {
+		log_error("dtree node segment allocation failed");
+		return NULL;
+	}
+
+	seg->type = type;
+	seg->size = size;
+	seg->area_count = 0;
+	dm_list_init(&seg->areas);
+	seg->stripe_size = 0;
+	seg->persistent = 0;
+	seg->chunk_size = 0;
+	seg->cow = NULL;
+	seg->origin = NULL;
+
+	dm_list_add(&dnode->props.segs, &seg->list);
+	dnode->props.segment_count++;
+
+	return seg;
+}
+
+int dm_tree_node_add_snapshot_origin_target(struct dm_tree_node *dnode,
+                                               uint64_t size,
+                                               const char *origin_uuid)
+{
+	struct load_segment *seg;
+	struct dm_tree_node *origin_node;
+
+	if (!(seg = _add_segment(dnode, SEG_SNAPSHOT_ORIGIN, size)))
+		return_0;
+
+	if (!(origin_node = dm_tree_find_node_by_uuid(dnode->dtree, origin_uuid))) {
+		log_error("Couldn't find snapshot origin uuid %s.", origin_uuid);
+		return 0;
+	}
+
+	seg->origin = origin_node;
+	if (!_link_tree_nodes(dnode, origin_node))
+		return_0;
+
+	/* Resume snapshot origins after new snapshots */
+	dnode->activation_priority = 1;
+
+	return 1;
+}
+
+int dm_tree_node_add_snapshot_target(struct dm_tree_node *node,
+                                        uint64_t size,
+                                        const char *origin_uuid,
+                                        const char *cow_uuid,
+                                        int persistent,
+                                        uint32_t chunk_size)
+{
+	struct load_segment *seg;
+	struct dm_tree_node *origin_node, *cow_node;
+
+	if (!(seg = _add_segment(node, SEG_SNAPSHOT, size)))
+		return_0;
+
+	if (!(origin_node = dm_tree_find_node_by_uuid(node->dtree, origin_uuid))) {
+		log_error("Couldn't find snapshot origin uuid %s.", origin_uuid);
+		return 0;
+	}
+
+	seg->origin = origin_node;
+	if (!_link_tree_nodes(node, origin_node))
+		return_0;
+
+	if (!(cow_node = dm_tree_find_node_by_uuid(node->dtree, cow_uuid))) {
+		log_error("Couldn't find snapshot origin uuid %s.", cow_uuid);
+		return 0;
+	}
+
+	seg->cow = cow_node;
+	if (!_link_tree_nodes(node, cow_node))
+		return_0;
+
+	seg->persistent = persistent ? 1 : 0;
+	seg->chunk_size = chunk_size;
+
+	return 1;
+}
+
+int dm_tree_node_add_error_target(struct dm_tree_node *node,
+                                     uint64_t size)
+{
+	if (!_add_segment(node, SEG_ERROR, size))
+		return_0;
+
+	return 1;
+}
+
+int dm_tree_node_add_zero_target(struct dm_tree_node *node,
+                                    uint64_t size)
+{
+	if (!_add_segment(node, SEG_ZERO, size))
+		return_0;
+
+	return 1;
+}
+
+int dm_tree_node_add_linear_target(struct dm_tree_node *node,
+                                      uint64_t size)
+{
+	if (!_add_segment(node, SEG_LINEAR, size))
+		return_0;
+
+	return 1;
+}
+
+int dm_tree_node_add_striped_target(struct dm_tree_node *node,
+                                       uint64_t size,
+                                       uint32_t stripe_size)
+{
+	struct load_segment *seg;
+
+	if (!(seg = _add_segment(node, SEG_STRIPED, size)))
+		return_0;
+
+	seg->stripe_size = stripe_size;
+
+	return 1;
+}
+
+int dm_tree_node_add_mirror_target_log(struct dm_tree_node *node,
+					  uint32_t region_size,
+					  unsigned clustered, 
+					  const char *log_uuid,
+					  unsigned area_count,
+					  uint32_t flags)
+{
+	struct dm_tree_node *log_node = NULL;
+	struct load_segment *seg;
+
+	if (!node->props.segment_count) {
+		log_error("Internal error: Attempt to add target area to missing segment.");
+		return 0;
+	}
+
+	seg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
+
+	if (log_uuid) {
+		if (!(seg->uuid = dm_pool_strdup(node->dtree->mem, log_uuid))) {
+			log_error("log uuid pool_strdup failed");
+			return 0;
+		}
+		if (!(flags & DM_CORELOG)) {
+			if (!(log_node = dm_tree_find_node_by_uuid(node->dtree, log_uuid))) {
+				log_error("Couldn't find mirror log uuid %s.", log_uuid);
+				return 0;
+			}
+
+			if (!_link_tree_nodes(node, log_node))
+				return_0;
+		}
+	}
+
+	seg->log = log_node;
+	seg->region_size = region_size;
+	seg->clustered = clustered;
+	seg->mirror_area_count = area_count;
+	seg->flags = flags;
+
+	return 1;
+}
+
+int dm_tree_node_add_mirror_target(struct dm_tree_node *node,
+                                      uint64_t size)
+{
+	struct load_segment *seg;
+
+	if (!(seg = _add_segment(node, SEG_MIRRORED, size)))
+		return_0;
+
+	return 1;
+}
+
+static int _add_area(struct dm_tree_node *node, struct load_segment *seg, struct dm_tree_node *dev_node, uint64_t offset)
+{
+	struct seg_area *area;
+
+	if (!(area = dm_pool_zalloc(node->dtree->mem, sizeof (*area)))) {
+		log_error("Failed to allocate target segment area.");
+		return 0;
+	}
+
+	area->dev_node = dev_node;
+	area->offset = offset;
+
+	dm_list_add(&seg->areas, &area->list);
+	seg->area_count++;
+
+	return 1;
+}
+
+int dm_tree_node_add_target_area(struct dm_tree_node *node,
+                                    const char *dev_name,
+                                    const char *uuid,
+                                    uint64_t offset)
+{
+	struct load_segment *seg;
+	struct stat info;
+	struct dm_tree_node *dev_node;
+
+	if ((!dev_name || !*dev_name) && (!uuid || !*uuid)) {
+		log_error("dm_tree_node_add_target_area called without device");
+		return 0;
+	}
+
+	if (uuid) {
+		if (!(dev_node = dm_tree_find_node_by_uuid(node->dtree, uuid))) {
+			log_error("Couldn't find area uuid %s.", uuid);
+			return 0;
+		}
+		if (!_link_tree_nodes(node, dev_node))
+			return_0;
+	} else {
+        	if (stat(dev_name, &info) < 0) {
+			log_error("Device %s not found.", dev_name);
+			return 0;
+		}
+#ifndef __NetBSD__
+        	if (!S_ISBLK(info.st_mode)) {
+			log_error("Device %s is not a block device.", dev_name);
+			return 0;
+		}
+#else
+		if (S_ISBLK(info.st_mode)) {
+			log_error("Device %s is a block device. Use raw devices on NetBSD.", dev_name);
+			return 0;
+		}
+#endif		
+		/* FIXME Check correct macro use */
+		if (!(dev_node = _add_dev(node->dtree, node, MAJOR(info.st_rdev), MINOR(info.st_rdev))))
+			return_0;
+	}
+
+	if (!node->props.segment_count) {
+		log_error("Internal error: Attempt to add target area to missing segment.");
+		return 0;
+	}
+
+	seg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
+
+	if (!_add_area(node, seg, dev_node, offset))
+		return_0;
+
+	return 1;
+}
Index: src/external/gpl2/lvm2tools/dist/libdm/libdm-file.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/libdm-file.c
diff -N src/external/gpl2/lvm2tools/dist/libdm/libdm-file.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/libdm-file.c	13 Dec 2008 14:39:36 -0000	1.1.1.1.2.2
@@ -0,0 +1,88 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "dmlib.h"
+
+#include <sys/file.h>
+#include <fcntl.h>
+#include <dirent.h>
+
+static int _create_dir_recursive(const char *dir)
+{
+	char *orig, *s;
+	int rc, r = 0;
+
+	log_verbose("Creating directory \"%s\"", dir);
+	/* Create parent directories */
+	orig = s = dm_strdup(dir);
+	while ((s = strchr(s, '/')) != NULL) {
+		*s = '\0';
+		if (*orig) {
+			rc = mkdir(orig, 0777);
+			if (rc < 0 && errno != EEXIST) {
+				if (errno != EROFS)
+					log_sys_error("mkdir", orig);
+				goto out;
+			}
+		}
+		*s++ = '/';
+	}
+
+	/* Create final directory */
+	rc = mkdir(dir, 0777);
+	if (rc < 0 && errno != EEXIST) {
+		if (errno != EROFS)
+			log_sys_error("mkdir", orig);
+		goto out;
+	}
+
+	r = 1;
+out:
+	dm_free(orig);
+	return r;
+}
+
+int dm_create_dir(const char *dir)
+{
+	struct stat info;
+
+	if (!*dir)
+		return 1;
+
+	if (stat(dir, &info) < 0)
+		return _create_dir_recursive(dir);
+
+	if (S_ISDIR(info.st_mode))
+		return 1;
+
+	log_error("Directory \"%s\" not found", dir);
+	return 0;
+}
+
+int dm_fclose(FILE *stream)
+{
+	int prev_fail = ferror(stream);
+	int fclose_fail = fclose(stream);
+
+	/* If there was a previous failure, but fclose succeeded,
+	   clear errno, since ferror does not set it, and its value
+	   may be unrelated to the ferror-reported failure.  */
+	if (prev_fail && !fclose_fail)
+		errno = 0;
+
+	return prev_fail || fclose_fail ? EOF : 0;
+}
Index: src/external/gpl2/lvm2tools/dist/libdm/libdm-report.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/libdm-report.c
diff -N src/external/gpl2/lvm2tools/dist/libdm/libdm-report.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/libdm-report.c	13 Dec 2008 14:39:36 -0000	1.1.1.1.2.2
@@ -0,0 +1,1007 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "dmlib.h"
+
+#include <ctype.h>
+
+/*
+ * Internal flags
+ */
+#define RH_SORT_REQUIRED	0x00000100
+#define RH_HEADINGS_PRINTED	0x00000200
+
+struct dm_report {
+	struct dm_pool *mem;
+
+	uint32_t report_types;
+	const char *output_field_name_prefix;
+	const char *field_prefix;
+	uint32_t flags;
+	const char *separator;
+
+	uint32_t keys_count;
+
+	/* Ordered list of fields needed for this report */
+	struct dm_list field_props;
+
+	/* Rows of report data */
+	struct dm_list rows;
+
+	/* Array of field definitions */
+	const struct dm_report_field_type *fields;
+	const struct dm_report_object_type *types;
+
+	/* To store caller private data */
+	void *private;
+};
+
+/*
+ * Internal per-field flags
+ */
+#define FLD_HIDDEN	0x00000100
+#define FLD_SORT_KEY	0x00000200
+#define FLD_ASCENDING	0x00000400
+#define FLD_DESCENDING	0x00000800
+
+struct field_properties {
+	struct dm_list list;
+	uint32_t field_num;
+	uint32_t sort_posn;
+	int32_t width;
+	const struct dm_report_object_type *type;
+	uint32_t flags;
+};
+
+/*
+ * Report data field
+ */
+struct dm_report_field {
+	struct dm_list list;
+	struct field_properties *props;
+
+	const char *report_string;	/* Formatted ready for display */
+	const void *sort_value;		/* Raw value for sorting */
+};
+
+struct row {
+	struct dm_list list;
+	struct dm_report *rh;
+	struct dm_list fields;			  /* Fields in display order */
+	struct dm_report_field *(*sort_fields)[]; /* Fields in sort order */
+};
+
+static const struct dm_report_object_type *_find_type(struct dm_report *rh,
+						      uint32_t report_type)
+{
+	const struct dm_report_object_type *t;
+
+	for (t = rh->types; t->data_fn; t++)
+		if (t->id == report_type)
+			return t;
+
+	return NULL;
+}
+
+/*
+ * Data-munging functions to prepare each data type for display and sorting
+ */
+
+int dm_report_field_string(struct dm_report *rh,
+			   struct dm_report_field *field, const char **data)
+{
+	char *repstr;
+
+	if (!(repstr = dm_pool_strdup(rh->mem, *data))) {
+		log_error("dm_report_field_string: dm_pool_strdup failed");
+		return 0;
+	}
+
+	field->report_string = repstr;
+	field->sort_value = (const void *) field->report_string;
+
+	return 1;
+}
+
+int dm_report_field_int(struct dm_report *rh,
+			struct dm_report_field *field, const int *data)
+{
+	const int value = *data;
+	uint64_t *sortval;
+	char *repstr;
+
+	if (!(repstr = dm_pool_zalloc(rh->mem, 13))) {
+		log_error("dm_report_field_int: dm_pool_alloc failed");
+		return 0;
+	}
+
+	if (!(sortval = dm_pool_alloc(rh->mem, sizeof(int64_t)))) {
+		log_error("dm_report_field_int: dm_pool_alloc failed");
+		return 0;
+	}
+
+	if (dm_snprintf(repstr, 12, "%d", value) < 0) {
+		log_error("dm_report_field_int: int too big: %d", value);
+		return 0;
+	}
+
+	*sortval = (const uint64_t) value;
+	field->sort_value = sortval;
+	field->report_string = repstr;
+
+	return 1;
+}
+
+int dm_report_field_uint32(struct dm_report *rh,
+			   struct dm_report_field *field, const uint32_t *data)
+{
+	const uint32_t value = *data;
+	uint64_t *sortval;
+	char *repstr;
+
+	if (!(repstr = dm_pool_zalloc(rh->mem, 12))) {
+		log_error("dm_report_field_uint32: dm_pool_alloc failed");
+		return 0;
+	}
+
+	if (!(sortval = dm_pool_alloc(rh->mem, sizeof(uint64_t)))) {
+		log_error("dm_report_field_uint32: dm_pool_alloc failed");
+		return 0;
+	}
+
+	if (dm_snprintf(repstr, 11, "%u", value) < 0) {
+		log_error("dm_report_field_uint32: uint32 too big: %u", value);
+		return 0;
+	}
+
+	*sortval = (const uint64_t) value;
+	field->sort_value = sortval;
+	field->report_string = repstr;
+
+	return 1;
+}
+
+int dm_report_field_int32(struct dm_report *rh,
+			  struct dm_report_field *field, const int32_t *data)
+{
+	const int32_t value = *data;
+	uint64_t *sortval;
+	char *repstr;
+
+	if (!(repstr = dm_pool_zalloc(rh->mem, 13))) {
+		log_error("dm_report_field_int32: dm_pool_alloc failed");
+		return 0;
+	}
+
+	if (!(sortval = dm_pool_alloc(rh->mem, sizeof(int64_t)))) {
+		log_error("dm_report_field_int32: dm_pool_alloc failed");
+		return 0;
+	}
+
+	if (dm_snprintf(repstr, 12, "%d", value) < 0) {
+		log_error("dm_report_field_int32: int32 too big: %d", value);
+		return 0;
+	}
+
+	*sortval = (const uint64_t) value;
+	field->sort_value = sortval;
+	field->report_string = repstr;
+
+	return 1;
+}
+
+int dm_report_field_uint64(struct dm_report *rh,
+			   struct dm_report_field *field, const uint64_t *data)
+{
+	const int value = *data;
+	uint64_t *sortval;
+	char *repstr;
+
+	if (!(repstr = dm_pool_zalloc(rh->mem, 22))) {
+		log_error("dm_report_field_uint64: dm_pool_alloc failed");
+		return 0;
+	}
+
+	if (!(sortval = dm_pool_alloc(rh->mem, sizeof(uint64_t)))) {
+		log_error("dm_report_field_uint64: dm_pool_alloc failed");
+		return 0;
+	}
+
+	if (dm_snprintf(repstr, 21, "%d", value) < 0) {
+		log_error("dm_report_field_uint64: uint64 too big: %d", value);
+		return 0;
+	}
+
+	*sortval = (const uint64_t) value;
+	field->sort_value = sortval;
+	field->report_string = repstr;
+
+	return 1;
+}
+
+/*
+ * Helper functions for custom report functions
+ */
+void dm_report_field_set_value(struct dm_report_field *field, const void *value, const void *sortvalue)
+{
+	field->report_string = (const char *) value;
+	field->sort_value = sortvalue ? : value;
+}
+
+/*
+ * show help message
+ */
+static void _display_fields(struct dm_report *rh)
+{
+	uint32_t f;
+	const struct dm_report_object_type *type;
+	const char *desc, *last_desc = "";
+	size_t id_len = 0;
+
+	for (f = 0; rh->fields[f].report_fn; f++)
+		if (strlen(rh->fields[f].id) > id_len)
+			id_len = strlen(rh->fields[f].id);
+
+	for (f = 0; rh->fields[f].report_fn; f++) {
+		if ((type = _find_type(rh, rh->fields[f].type)) && type->desc)
+			desc = type->desc;
+		else
+			desc = " ";
+		if (desc != last_desc) {
+			if (*last_desc)
+				log_warn(" ");
+			log_warn("%s Fields", desc);
+			log_warn("%*.*s", (int) strlen(desc) + 7,
+				 (int) strlen(desc) + 7,
+				 "-------------------------------------------------------------------------------");
+		}
+
+		/* FIXME Add line-wrapping at terminal width (or 80 cols) */
+		log_warn("  %-*s - %s", (int) id_len, rh->fields[f].id, rh->fields[f].desc);
+		last_desc = desc;
+	}
+}
+
+/*
+ * Initialise report handle
+ */
+static int _copy_field(struct dm_report *rh, struct field_properties *dest,
+		       uint32_t field_num)
+{
+	dest->field_num = field_num;
+	dest->width = rh->fields[field_num].width;
+	dest->flags = rh->fields[field_num].flags & DM_REPORT_FIELD_MASK;
+
+	/* set object type method */
+	dest->type = _find_type(rh, rh->fields[field_num].type);
+	if (!dest->type) {
+		log_error("dm_report: field not match: %s",
+			  rh->fields[field_num].id);
+		return 0;
+	}
+
+	return 1;
+}
+
+static struct field_properties * _add_field(struct dm_report *rh,
+					    uint32_t field_num, uint32_t flags)
+{
+	struct field_properties *fp;
+
+	rh->report_types |= rh->fields[field_num].type;
+
+	if (!(fp = dm_pool_zalloc(rh->mem, sizeof(struct field_properties)))) {
+		log_error("dm_report: struct field_properties allocation "
+			  "failed");
+		return NULL;
+	}
+
+	if (!_copy_field(rh, fp, field_num)) {
+		stack;
+		dm_pool_free(rh->mem, fp);
+		return NULL;
+	}
+
+	fp->flags |= flags;
+
+	/*
+	 * Place hidden fields at the front so dm_list_end() will
+	 * tell us when we've reached the last visible field.
+	 */
+	if (fp->flags & FLD_HIDDEN)
+		dm_list_add_h(&rh->field_props, &fp->list);
+	else
+		dm_list_add(&rh->field_props, &fp->list);
+
+	return fp;
+}
+
+/*
+ * Compare name1 against name2 or prefix plus name2
+ * name2 is not necessarily null-terminated.
+ * len2 is the length of name2.
+ */
+static int _is_same_field(const char *name1, const char *name2,
+			  size_t len2, const char *prefix)
+{
+	size_t prefix_len;
+
+	/* Exact match? */
+	if (!strncasecmp(name1, name2, len2) && strlen(name1) == len2)
+		return 1;
+
+	/* Match including prefix? */
+	prefix_len = strlen(prefix);
+	if (!strncasecmp(prefix, name1, prefix_len) &&
+	    !strncasecmp(name1 + prefix_len, name2, len2) &&
+	    strlen(name1) == prefix_len + len2)
+		return 1;
+
+	return 0;
+}
+
+static int _field_match(struct dm_report *rh, const char *field, size_t flen)
+{
+	uint32_t f;
+
+	if (!flen)
+		return 0;
+
+	for (f = 0; rh->fields[f].report_fn; f++)
+		if (_is_same_field(rh->fields[f].id, field, flen,
+				   rh->field_prefix))
+			return _add_field(rh, f, 0) ? 1 : 0;
+
+	return 0;
+}
+
+static int _add_sort_key(struct dm_report *rh, uint32_t field_num,
+			 uint32_t flags)
+{
+	struct field_properties *fp, *found = NULL;
+
+	dm_list_iterate_items(fp, &rh->field_props) {
+		if (fp->field_num == field_num) {
+			found = fp;
+			break;
+		}
+	}
+
+	if (!found && !(found = _add_field(rh, field_num, FLD_HIDDEN)))
+		return_0;
+
+	if (found->flags & FLD_SORT_KEY) {
+		log_error("dm_report: Ignoring duplicate sort field: %s",
+			  rh->fields[field_num].id);
+		return 1;
+	}
+
+	found->flags |= FLD_SORT_KEY;
+	found->sort_posn = rh->keys_count++;
+	found->flags |= flags;
+
+	return 1;
+}
+
+static int _key_match(struct dm_report *rh, const char *key, size_t len)
+{
+	uint32_t f;
+	uint32_t flags;
+
+	if (!len)
+		return 0;
+
+	if (*key == '+') {
+		key++;
+		len--;
+		flags = FLD_ASCENDING;
+	} else if (*key == '-') {
+		key++;
+		len--;
+		flags = FLD_DESCENDING;
+	} else
+		flags = FLD_ASCENDING;
+
+	if (!len) {
+		log_error("dm_report: Missing sort field name");
+		return 0;
+	}
+
+	for (f = 0; rh->fields[f].report_fn; f++)
+		if (_is_same_field(rh->fields[f].id, key, len,
+				   rh->field_prefix))
+			return _add_sort_key(rh, f, flags);
+
+	return 0;
+}
+
+static int _parse_options(struct dm_report *rh, const char *format)
+{
+	const char *ws;		/* Word start */
+	const char *we = format;	/* Word end */
+
+	while (*we) {
+		/* Allow consecutive commas */
+		while (*we && *we == ',')
+			we++;
+
+		/* start of the field name */
+		ws = we;
+		while (*we && *we != ',')
+			we++;
+
+		if (!_field_match(rh, ws, (size_t) (we - ws))) {
+			_display_fields(rh);
+			log_warn(" ");
+			if (strcasecmp(ws, "help") && strcmp(ws, "?"))
+				log_error("Unrecognised field: %.*s",
+					  (int) (we - ws), ws);
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+static int _parse_keys(struct dm_report *rh, const char *keys)
+{
+	const char *ws;		/* Word start */
+	const char *we = keys;	/* Word end */
+
+	while (*we) {
+		/* Allow consecutive commas */
+		while (*we && *we == ',')
+			we++;
+		ws = we;
+		while (*we && *we != ',')
+			we++;
+		if (!_key_match(rh, ws, (size_t) (we - ws))) {
+			log_error("dm_report: Unrecognised field: %.*s",
+				  (int) (we - ws), ws);
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+struct dm_report *dm_report_init(uint32_t *report_types,
+				 const struct dm_report_object_type *types,
+				 const struct dm_report_field_type *fields,
+				 const char *output_fields,
+				 const char *output_separator,
+				 uint32_t output_flags,
+				 const char *sort_keys,
+				 void *private)
+{
+	struct dm_report *rh;
+	const struct dm_report_object_type *type;
+
+	if (!(rh = dm_malloc(sizeof(*rh)))) {
+		log_error("dm_report_init: dm_malloc failed");
+		return 0;
+	}
+	memset(rh, 0, sizeof(*rh));
+
+	/*
+	 * rh->report_types is updated in _parse_options() and _parse_keys()
+	 * to contain all types corresponding to the fields specified by
+	 * options or keys.
+	 */
+	if (report_types)
+		rh->report_types = *report_types;
+
+	rh->separator = output_separator;
+	rh->fields = fields;
+	rh->types = types;
+	rh->private = private;
+
+	rh->flags |= output_flags & DM_REPORT_OUTPUT_MASK;
+
+	/* With columns_as_rows we must buffer and not align. */
+	if (output_flags & DM_REPORT_OUTPUT_COLUMNS_AS_ROWS) {
+		if (!(output_flags & DM_REPORT_OUTPUT_BUFFERED))
+			rh->flags |= DM_REPORT_OUTPUT_BUFFERED;
+		if (output_flags & DM_REPORT_OUTPUT_ALIGNED)
+			rh->flags &= ~DM_REPORT_OUTPUT_ALIGNED;
+	}
+
+	if (output_flags & DM_REPORT_OUTPUT_BUFFERED)
+		rh->flags |= RH_SORT_REQUIRED;
+
+	dm_list_init(&rh->field_props);
+	dm_list_init(&rh->rows);
+
+	if ((type = _find_type(rh, rh->report_types)) && type->prefix)
+		rh->field_prefix = type->prefix;
+	else
+		rh->field_prefix = "";
+
+	if (!(rh->mem = dm_pool_create("report", 10 * 1024))) {
+		log_error("dm_report_init: allocation of memory pool failed");
+		dm_free(rh);
+		return NULL;
+	}
+
+	/* Generate list of fields for output based on format string & flags */
+	if (!_parse_options(rh, output_fields)) {
+		dm_report_free(rh);
+		return NULL;
+	}
+
+	if (!_parse_keys(rh, sort_keys)) {
+		dm_report_free(rh);
+		return NULL;
+	}
+
+	/* Return updated types value for further compatility check by caller */
+	if (report_types)
+		*report_types = rh->report_types;
+
+	return rh;
+}
+
+void dm_report_free(struct dm_report *rh)
+{
+	dm_pool_destroy(rh->mem);
+	dm_free(rh);
+}
+
+static char *_toupperstr(char *str)
+{
+	char *u = str;
+
+	do
+		*u = toupper(*u);
+	while (*u++);
+
+	return str;
+}
+
+int dm_report_set_output_field_name_prefix(struct dm_report *rh, const char *output_field_name_prefix)
+{
+	char *prefix;
+
+	if (!(prefix = dm_pool_strdup(rh->mem, output_field_name_prefix))) {
+		log_error("dm_report_set_output_field_name_prefix: dm_pool_strdup failed");
+		return 0;
+	}
+
+	rh->output_field_name_prefix = _toupperstr(prefix);
+	
+	return 1;
+}
+
+/*
+ * Create a row of data for an object
+ */
+static void * _report_get_field_data(struct dm_report *rh,
+			      struct field_properties *fp, void *object)
+{
+	void *ret = fp->type->data_fn(object);
+
+	if (!ret)
+		return NULL;
+
+	return ret + rh->fields[fp->field_num].offset;
+}
+
+int dm_report_object(struct dm_report *rh, void *object)
+{
+	struct field_properties *fp;
+	struct row *row;
+	struct dm_report_field *field;
+	void *data = NULL;
+
+	if (!(row = dm_pool_zalloc(rh->mem, sizeof(*row)))) {
+		log_error("dm_report_object: struct row allocation failed");
+		return 0;
+	}
+
+	row->rh = rh;
+
+	if ((rh->flags & RH_SORT_REQUIRED) &&
+	    !(row->sort_fields =
+		dm_pool_zalloc(rh->mem, sizeof(struct dm_report_field *) *
+			       rh->keys_count))) {
+		log_error("dm_report_object: "
+			  "row sort value structure allocation failed");
+		return 0;
+	}
+
+	dm_list_init(&row->fields);
+	dm_list_add(&rh->rows, &row->list);
+
+	/* For each field to be displayed, call its report_fn */
+	dm_list_iterate_items(fp, &rh->field_props) {
+		if (!(field = dm_pool_zalloc(rh->mem, sizeof(*field)))) {
+			log_error("dm_report_object: "
+				  "struct dm_report_field allocation failed");
+			return 0;
+		}
+		field->props = fp;
+
+		data = _report_get_field_data(rh, fp, object);
+		if (!data)
+			return 0;
+
+		if (!rh->fields[fp->field_num].report_fn(rh, rh->mem,
+							 field, data,
+							 rh->private)) {
+			log_error("dm_report_object: "
+				  "report function failed for field %s",
+				  rh->fields[fp->field_num].id);
+			return 0;
+		}
+
+		if ((strlen(field->report_string) > field->props->width))
+			field->props->width = strlen(field->report_string);
+
+		if ((rh->flags & RH_SORT_REQUIRED) &&
+		    (field->props->flags & FLD_SORT_KEY)) {
+			(*row->sort_fields)[field->props->sort_posn] = field;
+		}
+		dm_list_add(&row->fields, &field->list);
+	}
+
+	if (!(rh->flags & DM_REPORT_OUTPUT_BUFFERED))
+		return dm_report_output(rh);
+
+	return 1;
+}
+
+/*
+ * Print row of headings
+ */
+static int _report_headings(struct dm_report *rh)
+{
+	struct field_properties *fp;
+	const char *heading;
+	char buf[1024];
+
+	if (rh->flags & RH_HEADINGS_PRINTED)
+		return 1;
+
+	rh->flags |= RH_HEADINGS_PRINTED;
+
+	if (!(rh->flags & DM_REPORT_OUTPUT_HEADINGS))
+		return 1;
+
+	if (!dm_pool_begin_object(rh->mem, 128)) {
+		log_error("dm_report: "
+			  "dm_pool_begin_object failed for headings");
+		return 0;
+	}
+
+	/* First heading line */
+	dm_list_iterate_items(fp, &rh->field_props) {
+		if (fp->flags & FLD_HIDDEN)
+			continue;
+
+		heading = rh->fields[fp->field_num].heading;
+		if (rh->flags & DM_REPORT_OUTPUT_ALIGNED) {
+			if (dm_snprintf(buf, sizeof(buf), "%-*.*s",
+					 fp->width, fp->width, heading) < 0) {
+				log_error("dm_report: snprintf heading failed");
+				goto bad;
+			}
+			if (!dm_pool_grow_object(rh->mem, buf, fp->width)) {
+				log_error("dm_report: Failed to generate report headings for printing");
+				goto bad;
+			}
+		} else if (!dm_pool_grow_object(rh->mem, heading, 0)) {
+			log_error("dm_report: Failed to generate report headings for printing");
+			goto bad;
+		}
+
+		if (!dm_list_end(&rh->field_props, &fp->list))
+			if (!dm_pool_grow_object(rh->mem, rh->separator, 0)) {
+				log_error("dm_report: Failed to generate report headings for printing");
+				goto bad;
+			}
+	}
+	if (!dm_pool_grow_object(rh->mem, "\0", 1)) {
+		log_error("dm_report: Failed to generate report headings for printing");
+		goto bad;
+	}
+	log_print("%s", (char *) dm_pool_end_object(rh->mem));
+
+	return 1;
+
+      bad:
+	dm_pool_abandon_object(rh->mem);
+	return 0;
+}
+
+/*
+ * Sort rows of data
+ */
+static int _row_compare(const void *a, const void *b)
+{
+	const struct row *rowa = *(const struct row **) a;
+	const struct row *rowb = *(const struct row **) b;
+	const struct dm_report_field *sfa, *sfb;
+	uint32_t cnt;
+
+	for (cnt = 0; cnt < rowa->rh->keys_count; cnt++) {
+		sfa = (*rowa->sort_fields)[cnt];
+		sfb = (*rowb->sort_fields)[cnt];
+		if (sfa->props->flags & DM_REPORT_FIELD_TYPE_NUMBER) {
+			const uint64_t numa =
+			    *(const uint64_t *) sfa->sort_value;
+			const uint64_t numb =
+			    *(const uint64_t *) sfb->sort_value;
+
+			if (numa == numb)
+				continue;
+
+			if (sfa->props->flags & FLD_ASCENDING) {
+				return (numa > numb) ? 1 : -1;
+			} else {	/* FLD_DESCENDING */
+				return (numa < numb) ? 1 : -1;
+			}
+		} else {	/* DM_REPORT_FIELD_TYPE_STRING */
+			const char *stra = (const char *) sfa->sort_value;
+			const char *strb = (const char *) sfb->sort_value;
+			int cmp = strcmp(stra, strb);
+
+			if (!cmp)
+				continue;
+
+			if (sfa->props->flags & FLD_ASCENDING) {
+				return (cmp > 0) ? 1 : -1;
+			} else {	/* FLD_DESCENDING */
+				return (cmp < 0) ? 1 : -1;
+			}
+		}
+	}
+
+	return 0;		/* Identical */
+}
+
+static int _sort_rows(struct dm_report *rh)
+{
+	struct row *(*rows)[];
+	uint32_t count = 0;
+	struct row *row;
+
+	if (!(rows = dm_pool_alloc(rh->mem, sizeof(**rows) *
+				dm_list_size(&rh->rows)))) {
+		log_error("dm_report: sort array allocation failed");
+		return 0;
+	}
+
+	dm_list_iterate_items(row, &rh->rows)
+		(*rows)[count++] = row;
+
+	qsort(rows, count, sizeof(**rows), _row_compare);
+
+	dm_list_init(&rh->rows);
+	while (count--)
+		dm_list_add_h(&rh->rows, &(*rows)[count]->list);
+
+	return 1;
+}
+
+/*
+ * Produce report output
+ */
+static int _output_field(struct dm_report *rh, struct dm_report_field *field)
+{
+	char *field_id;
+	int32_t width;
+	uint32_t align;
+	const char *repstr;
+	char buf[4096];
+
+	if (rh->flags & DM_REPORT_OUTPUT_FIELD_NAME_PREFIX) {
+		if (!(field_id = strdup(rh->fields[field->props->field_num].id))) {
+			log_error("dm_report: Failed to copy field name");
+			return 0;
+		}
+
+		if (!dm_pool_grow_object(rh->mem, rh->output_field_name_prefix, 0)) {
+			log_error("dm_report: Unable to extend output line");
+			return 0;
+		}
+
+		if (!dm_pool_grow_object(rh->mem, _toupperstr(field_id), 0)) {
+			log_error("dm_report: Unable to extend output line");
+			return 0;
+		}
+
+		free(field_id);
+
+		if (!dm_pool_grow_object(rh->mem, "=", 1)) {
+			log_error("dm_report: Unable to extend output line");
+			return 0;
+		}
+
+		if (!(rh->flags & DM_REPORT_OUTPUT_FIELD_UNQUOTED) &&
+		    !dm_pool_grow_object(rh->mem, "\'", 1)) {
+			log_error("dm_report: Unable to extend output line");
+			return 0;
+		}
+	}
+
+	repstr = field->report_string;
+	width = field->props->width;
+	if (!(rh->flags & DM_REPORT_OUTPUT_ALIGNED)) {
+		if (!dm_pool_grow_object(rh->mem, repstr, 0)) {
+			log_error("dm_report: Unable to extend output line");
+			return 0;
+		}
+	} else {
+		if (!(align = field->props->flags & DM_REPORT_FIELD_ALIGN_MASK))
+			align = (field->props->flags & DM_REPORT_FIELD_TYPE_NUMBER) ? 
+				DM_REPORT_FIELD_ALIGN_RIGHT : DM_REPORT_FIELD_ALIGN_LEFT;
+		if (align & DM_REPORT_FIELD_ALIGN_LEFT) {
+			if (dm_snprintf(buf, sizeof(buf), "%-*.*s",
+					 width, width, repstr) < 0) {
+				log_error("dm_report: left-aligned snprintf() failed");
+				return 0;
+			}
+			if (!dm_pool_grow_object(rh->mem, buf, width)) {
+				log_error("dm_report: Unable to extend output line");
+				return 0;
+			}
+		} else if (align & DM_REPORT_FIELD_ALIGN_RIGHT) {
+			if (dm_snprintf(buf, sizeof(buf), "%*.*s",
+					 width, width, repstr) < 0) {
+				log_error("dm_report: right-aligned snprintf() failed");
+				return 0;
+			}
+			if (!dm_pool_grow_object(rh->mem, buf, width)) {
+				log_error("dm_report: Unable to extend output line");
+				return 0;
+			}
+		}
+	}
+
+	if ((rh->flags & DM_REPORT_OUTPUT_FIELD_NAME_PREFIX) &&
+	    !(rh->flags & DM_REPORT_OUTPUT_FIELD_UNQUOTED))
+		if (!dm_pool_grow_object(rh->mem, "\'", 1)) {
+			log_error("dm_report: Unable to extend output line");
+			return 0;
+		}
+
+	return 1;
+}
+
+static int _output_as_rows(struct dm_report *rh)
+{
+	struct field_properties *fp;
+	struct dm_report_field *field;
+	struct row *row;
+
+	if (!dm_pool_begin_object(rh->mem, 512)) {
+		log_error("dm_report: Unable to allocate output line");
+		return 0;
+	}
+
+	dm_list_iterate_items(fp, &rh->field_props) {
+		if (fp->flags & FLD_HIDDEN) {
+			dm_list_iterate_items(row, &rh->rows) {
+				field = dm_list_item(dm_list_first(&row->fields), struct dm_report_field);
+				dm_list_del(&field->list);
+			}
+			continue;
+		}
+
+		if ((rh->flags & DM_REPORT_OUTPUT_HEADINGS)) {
+			if (!dm_pool_grow_object(rh->mem, rh->fields[fp->field_num].heading, 0)) {
+				log_error("dm_report: Failed to extend row for field name");
+				goto bad;
+			}
+			if (!dm_pool_grow_object(rh->mem, rh->separator, 0)) {
+				log_error("dm_report: Failed to extend row with separator");
+				goto bad;
+			}
+		}
+
+		dm_list_iterate_items(row, &rh->rows) {
+			if ((field = dm_list_item(dm_list_first(&row->fields), struct dm_report_field))) {
+				if (!_output_field(rh, field))
+					goto bad;
+				dm_list_del(&field->list);
+			}
+
+			if (!dm_list_end(&rh->rows, &row->list))
+				if (!dm_pool_grow_object(rh->mem, rh->separator, 0)) {
+					log_error("dm_report: Unable to extend output line");
+					goto bad;
+				}
+		}
+
+		if (!dm_pool_grow_object(rh->mem, "\0", 1)) {
+			log_error("dm_report: Failed to terminate row");
+			goto bad;
+		}
+		log_print("%s", (char *) dm_pool_end_object(rh->mem));
+	}
+
+	return 1;
+
+      bad:
+	dm_pool_abandon_object(rh->mem);
+	return 0;
+}
+
+static int _output_as_columns(struct dm_report *rh)
+{
+	struct dm_list *fh, *rowh, *ftmp, *rtmp;
+	struct row *row = NULL;
+	struct dm_report_field *field;
+
+	/* If headings not printed yet, calculate field widths and print them */
+	if (!(rh->flags & RH_HEADINGS_PRINTED))
+		_report_headings(rh);
+
+	/* Print and clear buffer */
+	dm_list_iterate_safe(rowh, rtmp, &rh->rows) {
+		if (!dm_pool_begin_object(rh->mem, 512)) {
+			log_error("dm_report: Unable to allocate output line");
+			return 0;
+		}
+		row = dm_list_item(rowh, struct row);
+		dm_list_iterate_safe(fh, ftmp, &row->fields) {
+			field = dm_list_item(fh, struct dm_report_field);
+			if (field->props->flags & FLD_HIDDEN)
+				continue;
+
+			if (!_output_field(rh, field))
+				goto bad;
+
+			if (!dm_list_end(&row->fields, fh))
+				if (!dm_pool_grow_object(rh->mem, rh->separator, 0)) {
+					log_error("dm_report: Unable to extend output line");
+					goto bad;
+				}
+
+			dm_list_del(&field->list);
+		}
+		if (!dm_pool_grow_object(rh->mem, "\0", 1)) {
+			log_error("dm_report: Unable to terminate output line");
+			goto bad;
+		}
+		log_print("%s", (char *) dm_pool_end_object(rh->mem));
+		dm_list_del(&row->list);
+	}
+
+	if (row)
+		dm_pool_free(rh->mem, row);
+
+	return 1;
+
+      bad:
+	dm_pool_abandon_object(rh->mem);
+	return 0;
+}
+
+int dm_report_output(struct dm_report *rh)
+{
+	if (dm_list_empty(&rh->rows))
+		return 1;
+
+	if ((rh->flags & RH_SORT_REQUIRED))
+		_sort_rows(rh);
+
+	if ((rh->flags & DM_REPORT_OUTPUT_COLUMNS_AS_ROWS))
+		return _output_as_rows(rh);
+	else
+		return _output_as_columns(rh);
+}
Index: src/external/gpl2/lvm2tools/dist/libdm/libdm-string.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/libdm-string.c
diff -N src/external/gpl2/lvm2tools/dist/libdm/libdm-string.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/libdm-string.c	13 Dec 2008 14:39:36 -0000	1.1.1.1.2.2
@@ -0,0 +1,164 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2006-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "dmlib.h"
+#include "libdevmapper.h"
+
+#include <ctype.h>
+
+/*
+ * consume characters while they match the predicate function.
+ */
+static char *_consume(char *buffer, int (*fn) (int))
+{
+	while (*buffer && fn(*buffer))
+		buffer++;
+
+	return buffer;
+}
+
+static int _isword(int c)
+{
+	return !isspace(c);
+}
+
+/*
+ * Split buffer into NULL-separated words in argv.
+ * Returns number of words.
+ */
+int dm_split_words(char *buffer, unsigned max,
+		   unsigned ignore_comments __attribute((unused)),
+		   char **argv)
+{
+	unsigned arg;
+
+	for (arg = 0; arg < max; arg++) {
+		buffer = _consume(buffer, isspace);
+		if (!*buffer)
+			break;
+
+		argv[arg] = buffer;
+		buffer = _consume(buffer, _isword);
+
+		if (*buffer) {
+			*buffer = '\0';
+			buffer++;
+		}
+	}
+
+	return arg;
+}
+
+/*
+ * Remove hyphen quoting from a component of a name.
+ * NULL-terminates the component and returns start of next component.
+ */
+static char *_unquote(char *component)
+{
+	char *c = component;
+	char *o = c;
+	char *r;
+
+	while (*c) {
+		if (*(c + 1)) {
+			if (*c == '-') {
+				if (*(c + 1) == '-')
+					c++;
+				else
+					break;
+			}
+		}
+		*o = *c;
+		o++;
+		c++;
+	}
+
+	r = (*c) ? c + 1 : c;
+	*o = '\0';
+
+	return r;
+}
+
+int dm_split_lvm_name(struct dm_pool *mem, const char *dmname,
+		      char **vgname, char **lvname, char **layer)
+{
+	if (!(*vgname = dm_pool_strdup(mem, dmname)))
+		return 0;
+
+	_unquote(*layer = _unquote(*lvname = _unquote(*vgname)));
+
+	return 1;
+}
+
+/*
+ * On error, up to glibc 2.0.6, snprintf returned -1 if buffer was too small;
+ * From glibc 2.1 it returns number of chars (excl. trailing null) that would 
+ * have been written had there been room.
+ *
+ * dm_snprintf reverts to the old behaviour.
+ */
+int dm_snprintf(char *buf, size_t bufsize, const char *format, ...)
+{
+	int n;
+	va_list ap;
+
+	va_start(ap, format);
+	n = vsnprintf(buf, bufsize, format, ap);
+	va_end(ap);
+
+	if (n < 0 || ((unsigned) n + 1 > bufsize))
+		return -1;
+
+	return n;
+}
+
+char *dm_basename(const char *path)
+{
+	char *p = strrchr(path, '/');
+
+	return p ? p + 1 : (char *) path;
+}
+
+int dm_asprintf(char **result, const char *format, ...)
+{
+	int n, ok = 0, size = 32;
+	va_list ap;
+	char *buf = dm_malloc(size);
+
+	*result = 0;
+
+	if (!buf)
+		return -1;
+
+	while (!ok) {
+		va_start(ap, format);
+		n = vsnprintf(buf, size, format, ap);
+		if (0 <= n && n < size)
+			ok = 1;
+		else {
+			dm_free(buf);
+			size *= 2;
+			buf = dm_malloc(size);
+			if (!buf)
+				return -1;
+		};
+		va_end(ap);
+	}
+
+	*result = dm_strdup(buf);
+	dm_free(buf);
+	return n + 1;
+}
Index: src/external/gpl2/lvm2tools/dist/libdm/datastruct/bitset.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/datastruct/bitset.c
diff -N src/external/gpl2/lvm2tools/dist/libdm/datastruct/bitset.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/datastruct/bitset.c	13 Dec 2008 14:39:36 -0000	1.1.1.1.2.2
@@ -0,0 +1,99 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "dmlib.h"
+
+/* FIXME: calculate this. */
+#define INT_SHIFT 5
+
+dm_bitset_t dm_bitset_create(struct dm_pool *mem, unsigned num_bits)
+{
+	unsigned n = (num_bits / DM_BITS_PER_INT) + 2;
+	size_t size = sizeof(int) * n;
+	dm_bitset_t bs;
+	
+	if (mem)
+		bs = dm_pool_zalloc(mem, size);
+	else
+		bs = dm_malloc(size);
+
+	if (!bs)
+		return NULL;
+
+	*bs = num_bits;
+
+	if (!mem)
+		dm_bit_clear_all(bs);
+
+	return bs;
+}
+
+void dm_bitset_destroy(dm_bitset_t bs)
+{
+	dm_free(bs);
+}
+
+void dm_bit_union(dm_bitset_t out, dm_bitset_t in1, dm_bitset_t in2)
+{
+	int i;
+	for (i = (in1[0] / DM_BITS_PER_INT) + 1; i; i--)
+		out[i] = in1[i] | in2[i];
+}
+
+/*
+ * FIXME: slow
+ */
+static inline int _test_word(uint32_t test, int bit)
+{
+	while (bit < (int) DM_BITS_PER_INT) {
+		if (test & (0x1 << bit))
+			return bit;
+		bit++;
+	}
+
+	return -1;
+}
+
+int dm_bit_get_next(dm_bitset_t bs, int last_bit)
+{
+	int bit, word;
+	uint32_t test;
+
+	last_bit++;		/* otherwise we'll return the same bit again */
+
+	/*
+	 * bs[0] holds number of bits
+	 */
+	while (last_bit < (int) bs[0]) {
+		word = last_bit >> INT_SHIFT;
+		test = bs[word + 1];
+		bit = last_bit & (DM_BITS_PER_INT - 1);
+
+		if ((bit = _test_word(test, bit)) >= 0)
+			return (word * DM_BITS_PER_INT) + bit;
+
+		last_bit = last_bit - (last_bit & (DM_BITS_PER_INT - 1)) +
+		    DM_BITS_PER_INT;
+	}
+
+	return -1;
+}
+
+int dm_bit_get_first(dm_bitset_t bs)
+{
+	return dm_bit_get_next(bs, -1);
+}
Index: src/external/gpl2/lvm2tools/dist/libdm/datastruct/bitset.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/datastruct/bitset.h
diff -N src/external/gpl2/lvm2tools/dist/libdm/datastruct/bitset.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/datastruct/bitset.h	13 Dec 2008 14:39:36 -0000	1.1.1.1.2.2
@@ -0,0 +1,54 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _DM_BITSET_H
+#define _DM_BITSET_H
+
+#include "pool.h"
+
+#include <limits.h>
+
+typedef uint32_t *bitset_t;
+
+bitset_t bitset_create(struct pool *mem, unsigned num_bits);
+void bitset_destroy(bitset_t bs);
+
+void bit_union(bitset_t out, bitset_t in1, bitset_t in2);
+int bit_get_first(bitset_t bs);
+int bit_get_next(bitset_t bs, int last_bit);
+
+#define BITS_PER_INT (sizeof(int) * CHAR_BIT)
+
+#define bit(bs, i) \
+   (bs[(i / BITS_PER_INT) + 1] & (0x1 << (i & (BITS_PER_INT - 1))))
+
+#define bit_set(bs, i) \
+   (bs[(i / BITS_PER_INT) + 1] |= (0x1 << (i & (BITS_PER_INT - 1))))
+
+#define bit_clear(bs, i) \
+   (bs[(i / BITS_PER_INT) + 1] &= ~(0x1 << (i & (BITS_PER_INT - 1))))
+
+#define bit_set_all(bs) \
+   memset(bs + 1, -1, ((*bs / BITS_PER_INT) + 1) * sizeof(int))
+
+#define bit_clear_all(bs) \
+   memset(bs + 1, 0, ((*bs / BITS_PER_INT) + 1) * sizeof(int))
+
+#define bit_copy(bs1, bs2) \
+   memcpy(bs1 + 1, bs2 + 1, ((*bs1 / BITS_PER_INT) + 1) * sizeof(int))
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/libdm/datastruct/hash.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/datastruct/hash.c
diff -N src/external/gpl2/lvm2tools/dist/libdm/datastruct/hash.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/datastruct/hash.c	13 Dec 2008 14:39:36 -0000	1.1.1.1.2.2
@@ -0,0 +1,270 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "dmlib.h"
+
+struct dm_hash_node {
+	struct dm_hash_node *next;
+	void *data;
+	unsigned keylen;
+	char key[0];
+};
+
+struct dm_hash_table {
+	unsigned num_nodes;
+	unsigned num_slots;
+	struct dm_hash_node **slots;
+};
+
+/* Permutation of the Integers 0 through 255 */
+static unsigned char _nums[] = {
+	1, 14, 110, 25, 97, 174, 132, 119, 138, 170, 125, 118, 27, 233, 140, 51,
+	87, 197, 177, 107, 234, 169, 56, 68, 30, 7, 173, 73, 188, 40, 36, 65,
+	49, 213, 104, 190, 57, 211, 148, 223, 48, 115, 15, 2, 67, 186, 210, 28,
+	12, 181, 103, 70, 22, 58, 75, 78, 183, 167, 238, 157, 124, 147, 172,
+	144,
+	176, 161, 141, 86, 60, 66, 128, 83, 156, 241, 79, 46, 168, 198, 41, 254,
+	178, 85, 253, 237, 250, 154, 133, 88, 35, 206, 95, 116, 252, 192, 54,
+	221,
+	102, 218, 255, 240, 82, 106, 158, 201, 61, 3, 89, 9, 42, 155, 159, 93,
+	166, 80, 50, 34, 175, 195, 100, 99, 26, 150, 16, 145, 4, 33, 8, 189,
+	121, 64, 77, 72, 208, 245, 130, 122, 143, 55, 105, 134, 29, 164, 185,
+	194,
+	193, 239, 101, 242, 5, 171, 126, 11, 74, 59, 137, 228, 108, 191, 232,
+	139,
+	6, 24, 81, 20, 127, 17, 91, 92, 251, 151, 225, 207, 21, 98, 113, 112,
+	84, 226, 18, 214, 199, 187, 13, 32, 94, 220, 224, 212, 247, 204, 196,
+	43,
+	249, 236, 45, 244, 111, 182, 153, 136, 129, 90, 217, 202, 19, 165, 231,
+	71,
+	230, 142, 96, 227, 62, 179, 246, 114, 162, 53, 160, 215, 205, 180, 47,
+	109,
+	44, 38, 31, 149, 135, 0, 216, 52, 63, 23, 37, 69, 39, 117, 146, 184,
+	163, 200, 222, 235, 248, 243, 219, 10, 152, 131, 123, 229, 203, 76, 120,
+	209
+};
+
+static struct dm_hash_node *_create_node(const char *str, unsigned len)
+{
+	struct dm_hash_node *n = dm_malloc(sizeof(*n) + len);
+
+	if (n) {
+		memcpy(n->key, str, len);
+		n->keylen = len;
+	}
+
+	return n;
+}
+
+static unsigned long _hash(const char *str, unsigned len)
+{
+	unsigned long h = 0, g;
+	unsigned i;
+
+	for (i = 0; i < len; i++) {
+		h <<= 4;
+		h += _nums[(unsigned char) *str++];
+		g = h & ((unsigned long) 0xf << 16u);
+		if (g) {
+			h ^= g >> 16u;
+			h ^= g >> 5u;
+		}
+	}
+
+	return h;
+}
+
+struct dm_hash_table *dm_hash_create(unsigned size_hint)
+{
+	size_t len;
+	unsigned new_size = 16u;
+	struct dm_hash_table *hc = dm_malloc(sizeof(*hc));
+
+	if (!hc) {
+		stack;
+		return 0;
+	}
+
+	memset(hc, 0, sizeof(*hc));
+
+	/* round size hint up to a power of two */
+	while (new_size < size_hint)
+		new_size = new_size << 1;
+
+	hc->num_slots = new_size;
+	len = sizeof(*(hc->slots)) * new_size;
+	if (!(hc->slots = dm_malloc(len))) {
+		stack;
+		goto bad;
+	}
+	memset(hc->slots, 0, len);
+	return hc;
+
+      bad:
+	dm_free(hc->slots);
+	dm_free(hc);
+	return 0;
+}
+
+static void _free_nodes(struct dm_hash_table *t)
+{
+	struct dm_hash_node *c, *n;
+	unsigned i;
+
+	for (i = 0; i < t->num_slots; i++)
+		for (c = t->slots[i]; c; c = n) {
+			n = c->next;
+			dm_free(c);
+		}
+}
+
+void dm_hash_destroy(struct dm_hash_table *t)
+{
+	_free_nodes(t);
+	dm_free(t->slots);
+	dm_free(t);
+}
+
+static struct dm_hash_node **_find(struct dm_hash_table *t, const char *key,
+				   uint32_t len)
+{
+	unsigned h = _hash(key, len) & (t->num_slots - 1);
+	struct dm_hash_node **c;
+
+	for (c = &t->slots[h]; *c; c = &((*c)->next))
+		if (!memcmp(key, (*c)->key, len))
+			break;
+
+	return c;
+}
+
+void *dm_hash_lookup_binary(struct dm_hash_table *t, const char *key,
+			 uint32_t len)
+{
+	struct dm_hash_node **c = _find(t, key, len);
+
+	return *c ? (*c)->data : 0;
+}
+
+int dm_hash_insert_binary(struct dm_hash_table *t, const char *key,
+			  uint32_t len, void *data)
+{
+	struct dm_hash_node **c = _find(t, key, len);
+
+	if (*c)
+		(*c)->data = data;
+	else {
+		struct dm_hash_node *n = _create_node(key, len);
+
+		if (!n)
+			return 0;
+
+		n->data = data;
+		n->next = 0;
+		*c = n;
+		t->num_nodes++;
+	}
+
+	return 1;
+}
+
+void dm_hash_remove_binary(struct dm_hash_table *t, const char *key,
+			uint32_t len)
+{
+	struct dm_hash_node **c = _find(t, key, len);
+
+	if (*c) {
+		struct dm_hash_node *old = *c;
+		*c = (*c)->next;
+		dm_free(old);
+		t->num_nodes--;
+	}
+}
+
+void *dm_hash_lookup(struct dm_hash_table *t, const char *key)
+{
+	return dm_hash_lookup_binary(t, key, strlen(key) + 1);
+}
+
+int dm_hash_insert(struct dm_hash_table *t, const char *key, void *data)
+{
+	return dm_hash_insert_binary(t, key, strlen(key) + 1, data);
+}
+
+void dm_hash_remove(struct dm_hash_table *t, const char *key)
+{
+	dm_hash_remove_binary(t, key, strlen(key) + 1);
+}
+
+unsigned dm_hash_get_num_entries(struct dm_hash_table *t)
+{
+	return t->num_nodes;
+}
+
+void dm_hash_iter(struct dm_hash_table *t, dm_hash_iterate_fn f)
+{
+	struct dm_hash_node *c, *n;
+	unsigned i;
+
+	for (i = 0; i < t->num_slots; i++)
+		for (c = t->slots[i]; c; c = n) {
+			n = c->next;
+			f(c->data);
+		}
+}
+
+void dm_hash_wipe(struct dm_hash_table *t)
+{
+	_free_nodes(t);
+	memset(t->slots, 0, sizeof(struct dm_hash_node *) * t->num_slots);
+	t->num_nodes = 0u;
+}
+
+char *dm_hash_get_key(struct dm_hash_table *t __attribute((unused)),
+		      struct dm_hash_node *n)
+{
+	return n->key;
+}
+
+void *dm_hash_get_data(struct dm_hash_table *t __attribute((unused)),
+		       struct dm_hash_node *n)
+{
+	return n->data;
+}
+
+static struct dm_hash_node *_next_slot(struct dm_hash_table *t, unsigned s)
+{
+	struct dm_hash_node *c = NULL;
+	unsigned i;
+
+	for (i = s; i < t->num_slots && !c; i++)
+		c = t->slots[i];
+
+	return c;
+}
+
+struct dm_hash_node *dm_hash_get_first(struct dm_hash_table *t)
+{
+	return _next_slot(t, 0);
+}
+
+struct dm_hash_node *dm_hash_get_next(struct dm_hash_table *t, struct dm_hash_node *n)
+{
+	unsigned h = _hash(n->key, n->keylen) & (t->num_slots - 1);
+
+	return n->next ? n->next : _next_slot(t, h + 1);
+}
Index: src/external/gpl2/lvm2tools/dist/libdm/datastruct/hash.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/datastruct/hash.h
diff -N src/external/gpl2/lvm2tools/dist/libdm/datastruct/hash.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/datastruct/hash.h	13 Dec 2008 14:39:36 -0000	1.1.1.1.2.2
@@ -0,0 +1,51 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _DM_HASH_H
+#define _DM_HASH_H
+
+struct hash_table;
+struct hash_node;
+
+typedef void (*iterate_fn) (void *data);
+
+struct hash_table *hash_create(unsigned size_hint);
+void hash_destroy(struct hash_table *t);
+void hash_wipe(struct hash_table *t);
+
+void *hash_lookup(struct hash_table *t, const char *key);
+int hash_insert(struct hash_table *t, const char *key, void *data);
+void hash_remove(struct hash_table *t, const char *key);
+
+void *hash_lookup_binary(struct hash_table *t, const char *key, uint32_t len);
+int hash_insert_binary(struct hash_table *t, const char *key, uint32_t len,
+		       void *data);
+void hash_remove_binary(struct hash_table *t, const char *key, uint32_t len);
+
+unsigned hash_get_num_entries(struct hash_table *t);
+void hash_iter(struct hash_table *t, iterate_fn f);
+
+char *hash_get_key(struct hash_table *t, struct hash_node *n);
+void *hash_get_data(struct hash_table *t, struct hash_node *n);
+struct hash_node *hash_get_first(struct hash_table *t);
+struct hash_node *hash_get_next(struct hash_table *t, struct hash_node *n);
+
+#define hash_iterate(v, h) \
+	for (v = hash_get_first(h); v; \
+	     v = hash_get_next(h, v))
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/libdm/datastruct/list.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/datastruct/list.c
diff -N src/external/gpl2/lvm2tools/dist/libdm/datastruct/list.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/datastruct/list.c	13 Dec 2008 14:39:36 -0000	1.1.1.1.2.2
@@ -0,0 +1,148 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include <assert.h>
+
+/*
+ * Initialise a list before use.
+ * The list head's next and previous pointers point back to itself.
+ */
+void dm_list_init(struct dm_list *head)
+{
+	head->n = head->p = head;
+}
+
+/*
+ * Insert an element before 'head'.
+ * If 'head' is the list head, this adds an element to the end of the list.
+ */
+void dm_list_add(struct dm_list *head, struct dm_list *elem)
+{
+	assert(head->n);
+
+	elem->n = head;
+	elem->p = head->p;
+
+	head->p->n = elem;
+	head->p = elem;
+}
+
+/*
+ * Insert an element after 'head'.
+ * If 'head' is the list head, this adds an element to the front of the list.
+ */
+void dm_list_add_h(struct dm_list *head, struct dm_list *elem)
+{
+	assert(head->n);
+
+	elem->n = head->n;
+	elem->p = head;
+
+	head->n->p = elem;
+	head->n = elem;
+}
+
+/*
+ * Delete an element from its list.
+ * Note that this doesn't change the element itself - it may still be safe
+ * to follow its pointers.
+ */
+void dm_list_del(struct dm_list *elem)
+{
+	elem->n->p = elem->p;
+	elem->p->n = elem->n;
+}
+
+/*
+ * Remove an element from existing list and insert before 'head'.
+ */
+void dm_list_move(struct dm_list *head, struct dm_list *elem)
+{
+        dm_list_del(elem);
+        dm_list_add(head, elem);
+}
+
+/*
+ * Is the list empty?
+ */
+int dm_list_empty(const struct dm_list *head)
+{
+	return head->n == head;
+}
+
+/*
+ * Is this the first element of the list?
+ */
+int dm_list_start(const struct dm_list *head, const struct dm_list *elem)
+{
+	return elem->p == head;
+}
+
+/*
+ * Is this the last element of the list?
+ */
+int dm_list_end(const struct dm_list *head, const struct dm_list *elem)
+{
+	return elem->n == head;
+}
+
+/*
+ * Return first element of the list or NULL if empty
+ */
+struct dm_list *dm_list_first(const struct dm_list *head)
+{
+	return (dm_list_empty(head) ? NULL : head->n);
+}
+
+/*
+ * Return last element of the list or NULL if empty
+ */
+struct dm_list *dm_list_last(const struct dm_list *head)
+{
+	return (dm_list_empty(head) ? NULL : head->p);
+}
+
+/*
+ * Return the previous element of the list, or NULL if we've reached the start.
+ */
+struct dm_list *dm_list_prev(const struct dm_list *head, const struct dm_list *elem)
+{
+	return (dm_list_start(head, elem) ? NULL : elem->p);
+}
+
+/*
+ * Return the next element of the list, or NULL if we've reached the end.
+ */
+struct dm_list *dm_list_next(const struct dm_list *head, const struct dm_list *elem)
+{
+	return (dm_list_end(head, elem) ? NULL : elem->n);
+}
+
+/*
+ * Return the number of elements in a list by walking it.
+ */
+unsigned int dm_list_size(const struct dm_list *head)
+{
+	unsigned int s = 0;
+	const struct dm_list *v;
+
+	dm_list_iterate(v, head)
+	    s++;
+
+	return s;
+}
Index: src/external/gpl2/lvm2tools/dist/libdm/datastruct/list.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/datastruct/list.h
diff -N src/external/gpl2/lvm2tools/dist/libdm/datastruct/list.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/datastruct/list.h	13 Dec 2008 14:39:36 -0000	1.1.1.1.2.2
@@ -0,0 +1,210 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_LIST_H
+#define _LVM_LIST_H
+
+#include <assert.h>
+
+/*
+ * A list consists of a list head plus elements.
+ * Each element has 'next' and 'previous' pointers.
+ * The list head's pointers point to the first and the last element.
+ */
+
+struct dm_list {
+	struct dm_list *n, *p;
+};
+
+/*
+ * Initialise a list before use.
+ * The list head's next and previous pointers point back to itself.
+ */
+#define DM_LIST_INIT(name)	struct dm_list name = { &(name), &(name) }
+void dm_list_init(struct dm_list *head);
+
+/*
+ * Insert an element before 'head'.
+ * If 'head' is the list head, this adds an element to the end of the list.
+ */
+void dm_list_add(struct dm_list *head, struct dm_list *elem);
+
+/*
+ * Insert an element after 'head'.
+ * If 'head' is the list head, this adds an element to the front of the list.
+ */
+void dm_list_add_h(struct dm_list *head, struct dm_list *elem);
+
+/*
+ * Delete an element from its list.
+ * Note that this doesn't change the element itself - it may still be safe
+ * to follow its pointers.
+ */
+void dm_list_del(struct dm_list *elem);
+
+/*
+ * Remove an element from existing list and insert before 'head'.
+ */
+void dm_list_move(struct dm_list *head, struct dm_list *elem);
+
+/*
+ * Is the list empty?
+ */
+int dm_list_empty(const struct dm_list *head);
+
+/*
+ * Is this the first element of the list?
+ */
+int dm_list_start(const struct dm_list *head, const struct dm_list *elem);
+
+/*
+ * Is this the last element of the list?
+ */
+int dm_list_end(const struct dm_list *head, const struct dm_list *elem);
+
+/*
+ * Return first element of the list or NULL if empty
+ */
+struct dm_list *dm_list_first(const struct dm_list *head);
+
+/*
+ * Return last element of the list or NULL if empty
+ */
+struct dm_list *dm_list_last(const struct dm_list *head);
+
+/*
+ * Return the previous element of the list, or NULL if we've reached the start.
+ */
+struct dm_list *dm_list_prev(const struct dm_list *head, const struct dm_list *elem);
+
+/*
+ * Return the next element of the list, or NULL if we've reached the end.
+ */
+struct dm_list *dm_list_next(const struct dm_list *head, const struct dm_list *elem);
+
+/*
+ * Given the address v of an instance of 'struct dm_list' called 'head' 
+ * contained in a structure of type t, return the containing structure.
+ */
+#define dm_list_struct_base(v, t, head) \
+    ((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->head))
+
+/*
+ * Given the address v of an instance of 'struct dm_list list' contained in
+ * a structure of type t, return the containing structure.
+ */
+#define dm_list_item(v, t) dm_list_struct_base((v), t, list)
+
+/*
+ * Given the address v of one known element e in a known structure of type t,
+ * return another element f.
+ */
+#define dm_struct_field(v, t, e, f) \
+    (((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->e))->f)
+
+/*
+ * Given the address v of a known element e in a known structure of type t,
+ * return the list head 'list'
+ */
+#define dm_list_head(v, t, e) dm_struct_field(v, t, e, list)
+
+/*
+ * Set v to each element of a list in turn.
+ */
+#define dm_list_iterate(v, head) \
+	for (v = (head)->n; v != head; v = v->n)
+
+/*
+ * Set v to each element in a list in turn, starting from the element 
+ * in front of 'start'.
+ * You can use this to 'unwind' a list_iterate and back out actions on
+ * already-processed elements.
+ * If 'start' is 'head' it walks the list backwards.
+ */
+#define dm_list_uniterate(v, head, start) \
+	for (v = (start)->p; v != head; v = v->p)
+
+/*
+ * A safe way to walk a list and delete and free some elements along
+ * the way.
+ * t must be defined as a temporary variable of the same type as v.
+ */
+#define dm_list_iterate_safe(v, t, head) \
+	for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
+
+/*
+ * Walk a list, setting 'v' in turn to the containing structure of each item.
+ * The containing structure should be the same type as 'v'.
+ * The 'struct dm_list' variable within the containing structure is 'field'.
+ */
+#define dm_list_iterate_items_gen(v, head, field) \
+	for (v = dm_list_struct_base((head)->n, typeof(*v), field); \
+	     &v->field != (head); \
+	     v = dm_list_struct_base(v->field.n, typeof(*v), field))
+
+/*
+ * Walk a list, setting 'v' in turn to the containing structure of each item.
+ * The containing structure should be the same type as 'v'.
+ * The list should be 'struct dm_list list' within the containing structure.
+ */
+#define dm_list_iterate_items(v, head) dm_list_iterate_items_gen(v, (head), list)
+
+/*
+ * Walk a list, setting 'v' in turn to the containing structure of each item.
+ * The containing structure should be the same type as 'v'.
+ * The 'struct dm_list' variable within the containing structure is 'field'.
+ * t must be defined as a temporary variable of the same type as v.
+ */
+#define dm_list_iterate_items_gen_safe(v, t, head, field) \
+	for (v = dm_list_struct_base((head)->n, typeof(*v), field), \
+	     t = dm_list_struct_base(v->field.n, typeof(*v), field); \
+	     &v->field != (head); \
+	     v = t, t = dm_list_struct_base(v->field.n, typeof(*v), field))
+/*
+ * Walk a list, setting 'v' in turn to the containing structure of each item.
+ * The containing structure should be the same type as 'v'.
+ * The list should be 'struct dm_list list' within the containing structure.
+ * t must be defined as a temporary variable of the same type as v.
+ */
+#define dm_list_iterate_items_safe(v, t, head) \
+	dm_list_iterate_items_gen_safe(v, t, (head), list)
+
+/*
+ * Walk a list backwards, setting 'v' in turn to the containing structure 
+ * of each item.
+ * The containing structure should be the same type as 'v'.
+ * The 'struct dm_list' variable within the containing structure is 'field'.
+ */
+#define dm_list_iterate_back_items_gen(v, head, field) \
+	for (v = dm_list_struct_base((head)->p, typeof(*v), field); \
+	     &v->field != (head); \
+	     v = dm_list_struct_base(v->field.p, typeof(*v), field))
+
+/*
+ * Walk a list backwards, setting 'v' in turn to the containing structure 
+ * of each item.
+ * The containing structure should be the same type as 'v'.
+ * The list should be 'struct dm_list list' within the containing structure.
+ */
+#define dm_list_iterate_back_items(v, head) dm_list_iterate_back_items_gen(v, (head), list)
+
+/*
+ * Return the number of elements in a list by walking it.
+ */
+unsigned int dm_list_size(const struct dm_list *head);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/libdm/ioctl/libdm-compat.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/ioctl/libdm-compat.h
diff -N src/external/gpl2/lvm2tools/dist/libdm/ioctl/libdm-compat.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/ioctl/libdm-compat.h	13 Dec 2008 14:39:36 -0000	1.1.1.1.2.2
@@ -0,0 +1,125 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LINUX_LIBDM_COMPAT_H
+#define _LINUX_LIBDM_COMPAT_H
+
+#include "kdev_t.h"
+#include "dm-ioctl.h"
+#include <inttypes.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} },
+	{ "clear",	0,			{4, 0, 0} },
+	{ "mknodes",	0,			{4, 0, 0} },
+	{ "versions",	0,			{4, 1, 0} },
+	{ "message",	0,			{4, 2, 0} },
+	{ "setgeometry",0,			{4, 6, 0} },
+};
+/* *INDENT-ON* */
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/libdm/ioctl/libdm-iface.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/ioctl/libdm-iface.c
diff -N src/external/gpl2/lvm2tools/dist/libdm/ioctl/libdm-iface.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/ioctl/libdm-iface.c	13 Dec 2008 14:39:36 -0000	1.1.1.1.2.2
@@ -0,0 +1,1776 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "dmlib.h"
+#include "libdm-targets.h"
+#include "libdm-common.h"
+
+#ifdef DM_COMPAT
+#  include "libdm-compat.h"
+#endif
+
+#include <fcntl.h>
+#include <dirent.h>
+#include <sys/ioctl.h>
+#include <limits.h>
+
+#ifdef linux
+#  include "kdev_t.h"
+#  include <linux/limits.h>
+#else
+#  define MAJOR(x) major((x))
+#  define MINOR(x) minor((x))
+#  define MKDEV(x,y) makedev((x),(y))
+#endif
+
+#include "dm-ioctl.h"
+
+/*
+ * 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) || \
+      (DM_VERSION_MAJOR == 4 && DM_VERSION_MINOR >= 0))
+#error The version of dm-ioctl.h included is incompatible.
+#endif
+
+/* FIXME This should be exported in device-mapper.h */
+#define DM_NAME "device-mapper"
+
+#define PROC_MISC "/proc/misc"
+#define PROC_DEVICES "/proc/devices"
+#define MISC_NAME "misc"
+
+#define NUMBER_OF_MAJORS 4096
+
+/* dm major version no for running kernel */
+static unsigned _dm_version = DM_VERSION_MAJOR;
+static unsigned _dm_version_minor = 0;
+static unsigned _dm_version_patchlevel = 0;
+static int _log_suppress = 0;
+
+static dm_bitset_t _dm_bitset = NULL;
+static int _control_fd = -1;
+static int _version_checked = 0;
+static int _version_ok = 1;
+static unsigned _ioctl_buffer_double_factor = 0;
+
+/*
+ * 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}},
+	{"mknodes",	DM_DEV_STATUS,		{4, 0, 0}},
+#ifdef DM_LIST_VERSIONS
+	{"versions",	DM_LIST_VERSIONS,	{4, 1, 0}},
+#endif
+#ifdef DM_TARGET_MSG
+	{"message",	DM_TARGET_MSG,		{4, 2, 0}},
+#endif
+#ifdef DM_DEV_SET_GEOMETRY
+	{"setgeometry",	DM_DEV_SET_GEOMETRY,	{4, 6, 0}},
+#endif
+};
+/* *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 agn = --a;
+
+	return (void *) (((unsigned long) ptr + agn) & ~agn);
+}
+
+#ifdef DM_IOCTLS
+/*
+ * Set number to NULL to populate _dm_bitset - otherwise first
+ * match is returned.
+ */
+static int _get_proc_number(const char *file, const char *name,
+			    uint32_t *number)
+{
+	FILE *fl;
+	char nm[256];
+	int c;
+	uint32_t num;
+
+	if (!(fl = fopen(file, "r"))) {
+		log_sys_error("fopen", file);
+		return 0;
+	}
+
+	while (!feof(fl)) {
+		if (fscanf(fl, "%d %255s\n", &num, &nm[0]) == 2) {
+			if (!strcmp(name, nm)) {
+				if (number) {
+					*number = num;
+					if (fclose(fl))
+						log_sys_error("fclose", file);
+					return 1;
+				}
+				dm_bit_set(_dm_bitset, num);
+			}
+		} else do {
+			c = fgetc(fl);
+		} while (c != EOF && c != '\n');
+	}
+	if (fclose(fl))
+		log_sys_error("fclose", file);
+
+	if (number) {
+		log_error("%s: No entry for %s found", file, name);
+		return 0;
+	}
+
+	return 1;
+}
+
+static int _control_device_number(uint32_t *major, uint32_t *minor)
+{
+	if (!_get_proc_number(PROC_DEVICES, MISC_NAME, major) ||
+	    !_get_proc_number(PROC_MISC, DM_NAME, minor)) {
+		*major = 0;
+		return 0;
+	}
+
+	return 1;
+}
+
+/*
+ * Returns 1 if exists; 0 if it doesn't; -1 if it's wrong
+ */
+static int _control_exists(const char *control, uint32_t major, uint32_t minor)
+{
+	struct stat buf;
+
+	if (stat(control, &buf) < 0) {
+		if (errno != ENOENT)
+			log_sys_error("stat", control);
+		return 0;
+	}
+
+	if (!S_ISCHR(buf.st_mode)) {
+		log_verbose("%s: Wrong inode type", control);
+		if (!unlink(control))
+			return 0;
+		log_sys_error("unlink", control);
+		return -1;
+	}
+
+	if (major && buf.st_rdev != MKDEV(major, minor)) {
+		log_verbose("%s: Wrong device number: (%u, %u) instead of "
+			    "(%u, %u)", control,
+			    MAJOR(buf.st_mode), MINOR(buf.st_mode),
+			    major, minor);
+		if (!unlink(control))
+			return 0;
+		log_sys_error("unlink", control);
+		return -1;
+	}
+
+	return 1;
+}
+
+static int _create_control(const char *control, uint32_t major, uint32_t minor)
+{
+	int ret;
+	mode_t old_umask;
+
+	if (!major)
+		return 0;
+
+	old_umask = umask(0022);
+	ret = dm_create_dir(dm_dir());
+	umask(old_umask);
+
+	if (!ret)
+		return 0;
+
+	log_verbose("Creating device %s (%u, %u)", control, major, minor);
+
+	if (mknod(control, S_IFCHR | S_IRUSR | S_IWUSR,
+		  MKDEV(major, minor)) < 0)  {
+		log_sys_error("mknod", control);
+		return 0;
+	}
+
+#ifdef HAVE_SELINUX
+	if (!dm_set_selinux_context(control, S_IFCHR)) {
+		stack;
+		return 0;
+	}
+#endif
+
+	return 1;
+}
+#endif
+
+static int _create_dm_bitset(void)
+{
+#ifdef DM_IOCTLS
+	if (_dm_bitset)
+		return 1;
+
+	if (!(_dm_bitset = dm_bitset_create(NULL, NUMBER_OF_MAJORS)))
+		return 0;
+
+	if (!_get_proc_number(PROC_DEVICES, DM_NAME, NULL)) {
+		dm_bitset_destroy(_dm_bitset);
+		_dm_bitset = NULL;
+		return 0;
+	}
+
+	return 1;
+#else
+	return 0;
+#endif
+}
+
+int dm_is_dm_major(uint32_t major)
+{
+	if (!_create_dm_bitset())
+		return 0;
+
+	return dm_bit(_dm_bitset, major) ? 1 : 0;
+}
+
+static int _open_control(void)
+{
+#ifdef DM_IOCTLS
+	char control[PATH_MAX];
+	uint32_t major = 0, minor;
+
+	if (_control_fd != -1)
+		return 1;
+
+	snprintf(control, sizeof(control), "%s/control", dm_dir());
+
+	if (!_control_device_number(&major, &minor))
+		log_error("Is device-mapper driver missing from kernel?");
+
+	if (!_control_exists(control, major, minor) &&
+	    !_create_control(control, major, minor))
+		goto error;
+
+	if ((_control_fd = open(control, O_RDWR)) < 0) {
+		log_sys_error("open", control);
+		goto error;
+	}
+
+	if (!_create_dm_bitset()) {
+		log_error("Failed to set up list of device-mapper major numbers");
+		return 0;
+	}
+
+	return 1;
+
+error:
+	log_error("Failure to communicate with kernel device-mapper driver.");
+	return 0;
+#else
+	return 1;
+#endif
+}
+
+void dm_task_destroy(struct dm_task *dmt)
+{
+	struct target *t, *n;
+
+	for (t = dmt->head; t; t = n) {
+		n = t->next;
+		dm_free(t->params);
+		dm_free(t->type);
+		dm_free(t);
+	}
+
+	if (dmt->dev_name)
+		dm_free(dmt->dev_name);
+
+	if (dmt->newname)
+		dm_free(dmt->newname);
+
+	if (dmt->message)
+		dm_free(dmt->message);
+
+	if (dmt->dmi.v4)
+		dm_free(dmt->dmi.v4);
+
+	if (dmt->uuid)
+		dm_free(dmt->uuid);
+
+	dm_free(dmt);
+}
+
+/*
+ * Protocol Version 1 compatibility functions.
+ */
+
+#ifdef DM_COMPAT
+
+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(const struct dm_task *dmt)
+{
+	return (dmt->dmi.v1->name);
+}
+
+static const char *_dm_task_get_uuid_v1(const 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 = dm_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:
+	dm_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];
+
+	log_warn("WARNING: Device list may be incomplete with interface "
+		  "version 1.");
+	log_warn("Please upgrade your kernel device-mapper driver.");
+
+	if (!(d = opendir(dev_dir))) {
+		log_sys_error("opendir", dev_dir);
+		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_sys_error("stat", path);
+			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_sys_error("closedir", dev_dir);
+
+	return r;
+}
+
+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%s [%u]", _cmd_data_v1[dmt->type].name,
+		  dmi->name, dmi->uuid, dmt->newname ? " " : "",
+		  dmt->newname ? dmt->newname : "",
+		  dmi->data_size);
+	if (dmt->type == DM_DEVICE_LIST) {
+		if (!_dm_names_v1(dmi))
+			goto bad;
+	} 
+#ifdef DM_IOCTLS
+	else if (ioctl(_control_fd, command, dmi) < 0) {
+		if (_log_suppress)
+			log_verbose("device-mapper: %s ioctl failed: %s", 
+				    _cmd_data_v1[dmt->type].name,
+				    strerror(errno));
+		else
+			log_error("device-mapper: %s ioctl failed: %s",
+				  _cmd_data_v1[dmt->type].name,
+				  strerror(errno));
+		goto bad;
+	}
+#else /* Userspace alternative for testing */
+#endif
+
+	if (dmi->flags & DM_BUFFER_FULL_FLAG)
+		/* FIXME Increase buffer size and retry operation (if query) */
+		log_error("WARNING: libdevmapper buffer too small for data");
+
+	switch (dmt->type) {
+	case DM_DEVICE_CREATE:
+		add_dev_node(dmt->dev_name, MAJOR(dmi->dev), MINOR(dmi->dev),
+			     dmt->uid, dmt->gid, dmt->mode);
+		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_MKNODES:
+		if (dmi->flags & DM_EXISTS_FLAG)
+			add_dev_node(dmt->dev_name, MAJOR(dmi->dev),
+				     MINOR(dmi->dev),
+				     dmt->uid, dmt->gid, dmt->mode);
+		else
+			rm_dev_node(dmt->dev_name);
+		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;
+		dm_free(dmi);	/* We'll use what info returned */
+		return 1;
+	}
+
+	dmt->dmi.v1 = dmi;
+	return 1;
+
+      bad:
+	dm_free(dmi);
+	return 0;
+}
+
+#endif
+
+/*
+ * Protocol Version 4 functions.
+ */
+
+int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size)
+{
+	unsigned *v;
+
+#ifdef DM_COMPAT
+	if (_dm_version == 1)
+		return _dm_task_get_driver_version_v1(dmt, version, size);
+#endif
+
+	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]);
+	_dm_version_minor = v[1];
+	_dm_version_patchlevel = 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 %u 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)
+{
+	struct target *t = (struct target *) next;
+
+	if (!t)
+		t = dmt->head;
+
+	if (!t)
+		return NULL;
+
+	*start = t->start;
+	*length = t->length;
+	*target_type = t->type;
+	*params = t->params;
+
+	return t->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 + dmi->data_start;
+	char *outptr = outbuf;
+	uint32_t i;
+	struct dm_target_spec *spec;
+
+	for (i = 0; i < dmi->target_count; i++) {
+		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 = outbuf + spec->next;
+	}
+
+	return 1;
+}
+
+int dm_format_dev(char *buf, int bufsize, uint32_t dev_major,
+		  uint32_t dev_minor)
+{
+	int r;
+
+#ifdef DM_COMPAT
+	if (_dm_version == 1)
+		return _dm_format_dev_v1(buf, bufsize, dev_major, dev_minor);
+#endif
+
+	if (bufsize < 8)
+		return 0;
+
+	r = snprintf(buf, (size_t) bufsize, "%u:%u", 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)
+{
+#ifdef DM_COMPAT
+	if (_dm_version == 1)
+		return _dm_task_get_info_v1(dmt, info);
+#endif
+
+	if (!dmt->dmi.v4)
+		return 0;
+
+	memset(info, 0, sizeof(*info));
+
+	info->exists = dmt->dmi.v4->flags & DM_EXISTS_FLAG ? 1 : 0;
+	if (!info->exists)
+		return 1;
+
+	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;
+}
+
+uint32_t dm_task_get_read_ahead(const struct dm_task *dmt, uint32_t *read_ahead)
+{              
+	const char *dev_name;
+
+	*read_ahead = 0;
+
+#ifdef DM_COMPAT
+	/* Not supporting this */
+        if (_dm_version == 1)
+                return 1;
+#endif  
+
+        if (!dmt->dmi.v4 || !(dmt->dmi.v4->flags & DM_EXISTS_FLAG))
+		return 0;
+
+	if (*dmt->dmi.v4->name)
+		dev_name = dmt->dmi.v4->name;
+	else if (dmt->dev_name)
+		dev_name = dmt->dev_name;
+	else {
+		log_error("Get read ahead request failed: device name unrecorded.");
+		return 0;
+	}
+
+	return get_dev_node_read_ahead(dev_name, read_ahead);
+}
+
+const char *dm_task_get_name(const struct dm_task *dmt)
+{
+#ifdef DM_COMPAT
+	if (_dm_version == 1)
+		return _dm_task_get_name_v1(dmt);
+#endif
+
+	return (dmt->dmi.v4->name);
+}
+
+const char *dm_task_get_uuid(const struct dm_task *dmt)
+{
+#ifdef DM_COMPAT
+	if (_dm_version == 1)
+		return _dm_task_get_uuid_v1(dmt);
+#endif
+
+	return (dmt->dmi.v4->uuid);
+}
+
+struct dm_deps *dm_task_get_deps(struct dm_task *dmt)
+{
+#ifdef DM_COMPAT
+	if (_dm_version == 1)
+		return _dm_task_get_deps_v1(dmt);
+#endif
+
+	return (struct dm_deps *) (((void *) dmt->dmi.v4) +
+				   dmt->dmi.v4->data_start);
+}
+
+struct dm_names *dm_task_get_names(struct dm_task *dmt)
+{
+#ifdef DM_COMPAT
+	if (_dm_version == 1)
+		return _dm_task_get_names_v1(dmt);
+#endif
+
+	return (struct dm_names *) (((void *) dmt->dmi.v4) +
+				    dmt->dmi.v4->data_start);
+}
+
+struct dm_versions *dm_task_get_versions(struct dm_task *dmt)
+{
+	return (struct dm_versions *) (((void *) dmt->dmi.v4) +
+				       dmt->dmi.v4->data_start);
+}
+
+int dm_task_set_ro(struct dm_task *dmt)
+{
+	dmt->read_only = 1;
+	return 1;
+}
+
+int dm_task_set_read_ahead(struct dm_task *dmt, uint32_t read_ahead,
+			   uint32_t read_ahead_flags)
+{
+	dmt->read_ahead = read_ahead;
+	dmt->read_ahead_flags = read_ahead_flags;
+
+	return 1;
+}
+
+int dm_task_suppress_identical_reload(struct dm_task *dmt)
+{
+	dmt->suppress_identical_reload = 1;
+	return 1;
+}
+
+int dm_task_set_newname(struct dm_task *dmt, const char *newname)
+{
+	if (!(dmt->newname = dm_strdup(newname))) {
+		log_error("dm_task_set_newname: strdup(%s) failed", newname);
+		return 0;
+	}
+
+	return 1;
+}
+
+int dm_task_set_message(struct dm_task *dmt, const char *message)
+{
+	if (!(dmt->message = dm_strdup(message))) {
+		log_error("dm_task_set_message: strdup(%s) failed", message);
+		return 0;
+	}
+
+	return 1;
+}
+
+int dm_task_set_sector(struct dm_task *dmt, uint64_t sector)
+{
+	dmt->sector = sector;
+
+	return 1;
+}
+
+int dm_task_set_geometry(struct dm_task *dmt, const char *cylinders, const char *heads, const char *sectors, const char *start)
+{
+	size_t len = strlen(cylinders) + 1 + strlen(heads) + 1 + strlen(sectors) + 1 + strlen(start) + 1;
+
+	if (!(dmt->geometry = dm_malloc(len))) {
+		log_error("dm_task_set_geometry: dm_malloc failed");
+		return 0;
+	}
+
+	if (sprintf(dmt->geometry, "%s %s %s %s", cylinders, heads, sectors, start) < 0) {
+		log_error("dm_task_set_geometry: sprintf failed");
+		return 0;
+	}
+
+	return 1;
+}
+
+int dm_task_no_flush(struct dm_task *dmt)
+{
+	dmt->no_flush = 1;
+
+	return 1;
+}
+
+int dm_task_no_open_count(struct dm_task *dmt)
+{
+	dmt->no_open_count = 1;
+
+	return 1;
+}
+
+int dm_task_skip_lockfs(struct dm_task *dmt)
+{
+	dmt->skip_lockfs = 1;
+
+	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)
+{
+	struct target *t = dm_malloc(sizeof(*t));
+
+	if (!t) {
+		log_error("create_target: malloc(%" PRIsize_t ") failed",
+			  sizeof(*t));
+		return NULL;
+	}
+
+	memset(t, 0, sizeof(*t));
+
+	if (!(t->params = dm_strdup(params))) {
+		log_error("create_target: strdup(params) failed");
+		goto bad;
+	}
+
+	if (!(t->type = dm_strdup(type))) {
+		log_error("create_target: strdup(type) failed");
+		goto bad;
+	}
+
+	t->start = start;
+	t->length = len;
+	return t;
+
+      bad:
+	dm_free(t->params);
+	dm_free(t->type);
+	dm_free(t);
+	return NULL;
+}
+
+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 += 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);
+
+	sp.next = out - out_sp;
+	memcpy(out_sp, &sp, sp_size);
+
+	return out;
+}
+
+static int _lookup_dev_name(uint64_t dev, char *buf, size_t len)
+{
+	struct dm_names *names;
+	unsigned next = 0;
+	struct dm_task *dmt;
+	int r = 0;
+ 
+	if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
+		return 0;
+ 
+	if (!dm_task_run(dmt))
+		goto out;
+
+	if (!(names = dm_task_get_names(dmt)))
+		goto out;
+ 
+	if (!names->dev)
+		goto out;
+ 
+	do {
+		names = (void *) names + next;
+		if (names->dev == dev) {
+			strncpy(buf, names->name, len);
+			r = 1;
+			break;
+		}
+		next = names->next;
+	} while (next);
+
+      out:
+	dm_task_destroy(dmt);
+	return r;
+}
+
+static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
+{
+	const size_t min_size = 16 * 1024;
+	const int (*version)[3];
+
+	struct dm_ioctl *dmi;
+	struct target *t;
+	struct dm_target_msg *tmsg;
+	size_t len = sizeof(struct dm_ioctl);
+	void *b, *e;
+	int count = 0;
+
+	for (t = dmt->head; t; t = t->next) {
+		len += sizeof(struct dm_target_spec);
+		len += strlen(t->params) + 1 + ALIGNMENT;
+		count++;
+	}
+
+	if (count && (dmt->sector || dmt->message)) {
+		log_error("targets and message are incompatible");
+		return NULL;
+	}
+
+	if (count && dmt->newname) {
+		log_error("targets and newname are incompatible");
+		return NULL;
+	}
+
+	if (count && dmt->geometry) {
+		log_error("targets and geometry are incompatible");
+		return NULL;
+	}
+
+	if (dmt->newname && (dmt->sector || dmt->message)) {
+		log_error("message and newname are incompatible");
+		return NULL;
+	}
+
+	if (dmt->newname && dmt->geometry) {
+		log_error("geometry and newname are incompatible");
+		return NULL;
+	}
+
+	if (dmt->geometry && (dmt->sector || dmt->message)) {
+		log_error("geometry and message are incompatible");
+		return NULL;
+	}
+
+	if (dmt->sector && !dmt->message) {
+		log_error("message is required with sector");
+		return NULL;
+	}
+
+	if (dmt->newname)
+		len += strlen(dmt->newname) + 1;
+
+	if (dmt->message)
+		len += sizeof(struct dm_target_msg) + strlen(dmt->message) + 1;
+
+	if (dmt->geometry)
+		len += strlen(dmt->geometry) + 1;
+
+	/*
+	 * Give len a minimum size so that we have space to store
+	 * dependencies or status information.
+	 */
+	if (len < min_size)
+		len = min_size;
+
+	/* Increase buffer size if repeating because buffer was too small */
+	while (repeat_count--)
+		len *= 2;
+
+	if (!(dmi = dm_malloc(len)))
+		return NULL;
+
+	memset(dmi, 0, len);
+
+	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);
+
+	if (dmt->minor >= 0) {
+		if (dmt->major <= 0) {
+			log_error("Missing major number for persistent device.");
+			goto bad;
+		}
+		dmi->flags |= DM_PERSISTENT_DEV_FLAG;
+		dmi->dev = MKDEV(dmt->major, dmt->minor);
+	}
+
+	/* Does driver support device number referencing? */
+	if (_dm_version_minor < 3 && !dmt->dev_name && !dmt->uuid && dmi->dev) {
+		if (!_lookup_dev_name(dmi->dev, dmi->name, sizeof(dmi->name))) {
+			log_error("Unable to find name for device (%" PRIu32
+				  ":%" PRIu32 ")", dmt->major, dmt->minor);
+			goto bad;
+		}
+		log_verbose("device (%" PRIu32 ":%" PRIu32 ") is %s "
+			    "for compatibility with old kernel",
+			    dmt->major, dmt->minor, dmi->name);
+	}
+
+	/* FIXME Until resume ioctl supplies name, use dev_name for readahead */
+	if (dmt->dev_name && (dmt->type != DM_DEVICE_RESUME || dmt->minor < 0 ||
+			      dmt->major < 0))
+		strncpy(dmi->name, dmt->dev_name, sizeof(dmi->name));
+
+	if (dmt->uuid)
+		strncpy(dmi->uuid, dmt->uuid, sizeof(dmi->uuid));
+
+	if (dmt->type == DM_DEVICE_SUSPEND)
+		dmi->flags |= DM_SUSPEND_FLAG;
+	if (dmt->no_flush)
+		dmi->flags |= DM_NOFLUSH_FLAG;
+	if (dmt->read_only)
+		dmi->flags |= DM_READONLY_FLAG;
+	if (dmt->skip_lockfs)
+		dmi->flags |= DM_SKIP_LOCKFS_FLAG;
+
+	dmi->target_count = count;
+	dmi->event_nr = dmt->event_nr;
+
+	b = (void *) (dmi + 1);
+	e = (void *) ((char *) dmi + len);
+
+	for (t = dmt->head; t; t = t->next)
+		if (!(b = _add_target(t, b, e)))
+			goto bad;
+
+	if (dmt->newname)
+		strcpy(b, dmt->newname);
+
+	if (dmt->message) {
+		tmsg = (struct dm_target_msg *) b;
+		tmsg->sector = dmt->sector;
+		strcpy(tmsg->message, dmt->message);
+	}
+
+	if (dmt->geometry)
+		strcpy(b, dmt->geometry);
+
+	return dmi;
+
+      bad:
+	dm_free(dmi);
+	return NULL;
+}
+
+static int _process_mapper_dir(struct dm_task *dmt)
+{
+	struct dirent *dirent;
+	DIR *d;
+	const char *dir;
+	int r = 1;
+
+	dir = dm_dir();
+	if (!(d = opendir(dir))) {
+		log_sys_error("opendir", dir);
+		return 0;
+	}
+
+	while ((dirent = readdir(d))) {
+		if (!strcmp(dirent->d_name, ".") ||
+		    !strcmp(dirent->d_name, "..") ||
+		    !strcmp(dirent->d_name, "control"))
+			continue;
+		dm_task_set_name(dmt, dirent->d_name);
+		dm_task_run(dmt);
+	}
+
+	if (closedir(d))
+		log_sys_error("closedir", dir);
+
+	return r;
+}
+
+static int _process_all_v4(struct dm_task *dmt)
+{
+	struct dm_task *task;
+	struct dm_names *names;
+	unsigned next = 0;
+	int r = 1;
+
+	if (!(task = dm_task_create(DM_DEVICE_LIST)))
+		return 0;
+
+	if (!dm_task_run(task)) {
+		r = 0;
+		goto out;
+	}
+
+	if (!(names = dm_task_get_names(task))) {
+		r = 0;
+		goto out;
+	}
+
+	if (!names->dev)
+		goto out;
+
+	do {
+		names = (void *) names + next;
+		if (!dm_task_set_name(dmt, names->name)) {
+			r = 0;
+			goto out;
+		}
+		if (!dm_task_run(dmt))
+			r = 0;
+		next = names->next;
+	} while (next);
+
+      out:
+	dm_task_destroy(task);
+	return r;
+}
+
+static int _mknodes_v4(struct dm_task *dmt)
+{
+	(void) _process_mapper_dir(dmt);
+
+	return _process_all_v4(dmt);
+}
+
+static int _create_and_load_v4(struct dm_task *dmt)
+{
+	struct dm_task *task;
+	int r;
+
+	/* 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;
+	}
+
+	/* Copy across relevant fields */
+	if (dmt->dev_name && !dm_task_set_name(task, dmt->dev_name)) {
+		dm_task_destroy(task);
+		return 0;
+	}
+
+	if (dmt->uuid && !dm_task_set_uuid(task, dmt->uuid)) {
+		dm_task_destroy(task);
+		return 0;
+	}
+
+	task->major = dmt->major;
+	task->minor = dmt->minor;
+	task->uid = dmt->uid;
+	task->gid = dmt->gid;
+	task->mode = dmt->mode;
+
+	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)
+		goto revert;
+
+	/* Use the original structure last so the info will be correct */
+	dmt->type = DM_DEVICE_RESUME;
+	dm_free(dmt->uuid);
+	dmt->uuid = NULL;
+
+	r = dm_task_run(dmt);
+
+	if (r)
+		return r;
+
+      revert:
+ 	dmt->type = DM_DEVICE_REMOVE;
+	dm_free(dmt->uuid);
+	dmt->uuid = NULL;
+
+	if (!dm_task_run(dmt))
+		log_error("Failed to revert device creation.");
+
+	return r;
+}
+
+uint64_t dm_task_get_existing_table_size(struct dm_task *dmt)
+{
+	return dmt->existing_table_size;
+}
+
+static int _reload_with_suppression_v4(struct dm_task *dmt)
+{
+	struct dm_task *task;
+	struct target *t1, *t2;
+	int r;
+
+	/* New task to get existing table information */
+	if (!(task = dm_task_create(DM_DEVICE_TABLE))) {
+		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;
+	}
+
+	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);
+
+	if (!r) {
+		dm_task_destroy(task);
+		return r;
+	}
+
+	/* Store existing table size */
+	t2 = task->head;
+	while (t2 && t2->next)
+		t2 = t2->next;
+	dmt->existing_table_size = t2 ? t2->start + t2->length : 0;
+
+	if ((task->dmi.v4->flags & DM_READONLY_FLAG) ? 1 : 0 != dmt->read_only)
+		goto no_match;
+
+	t1 = dmt->head;
+	t2 = task->head;
+
+	while (t1 && t2) {
+		while (t2->params[strlen(t2->params) - 1] == ' ')
+			t2->params[strlen(t2->params) - 1] = '\0';
+		if ((t1->start != t2->start) ||
+		    (t1->length != t2->length) ||
+		    (strcmp(t1->type, t2->type)) ||
+		    (strcmp(t1->params, t2->params)))
+			goto no_match;
+		t1 = t1->next;
+		t2 = t2->next;
+	}
+	
+	if (!t1 && !t2) {
+		dmt->dmi.v4 = task->dmi.v4;
+		task->dmi.v4 = NULL;
+		dm_task_destroy(task);
+		return 1;
+	}
+
+no_match:
+	dm_task_destroy(task);
+
+	/* Now do the original reload */
+	dmt->suppress_identical_reload = 0;
+	r = dm_task_run(dmt);
+
+	return r;
+}
+
+static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
+				     unsigned repeat_count)
+{
+	struct dm_ioctl *dmi;
+
+	dmi = _flatten(dmt, repeat_count);
+	if (!dmi) {
+		log_error("Couldn't create ioctl argument.");
+		return NULL;
+	}
+
+	if (dmt->type == DM_DEVICE_TABLE)
+		dmi->flags |= DM_STATUS_TABLE_FLAG;
+
+	dmi->flags |= DM_EXISTS_FLAG;	/* FIXME */
+
+	if (dmt->no_open_count)
+		dmi->flags |= DM_SKIP_BDGET_FLAG;
+
+	log_debug("dm %s %s %s%s%s %s%.0d%s%.0d%s"
+		  "%s%c%c%s %.0" PRIu64 " %s [%u]",
+		  _cmd_data_v4[dmt->type].name,
+		  dmi->name, dmi->uuid, dmt->newname ? " " : "",
+		  dmt->newname ? dmt->newname : "",
+		  dmt->major > 0 ? "(" : "",
+		  dmt->major > 0 ? dmt->major : 0,
+		  dmt->major > 0 ? ":" : "",
+		  dmt->minor > 0 ? dmt->minor : 0,
+		  dmt->major > 0 && dmt->minor == 0 ? "0" : "",
+		  dmt->major > 0 ? ") " : "",
+		  dmt->no_open_count ? 'N' : 'O',
+		  dmt->no_flush ? 'N' : 'F',
+		  dmt->skip_lockfs ? "S " : "",
+		  dmt->sector, dmt->message ? dmt->message : "",
+		  dmi->data_size);
+#ifdef DM_IOCTLS
+	if (ioctl(_control_fd, command, dmi) < 0) {
+		if (errno == ENXIO && ((dmt->type == DM_DEVICE_INFO) ||
+				       (dmt->type == DM_DEVICE_MKNODES) ||
+				       (dmt->type == DM_DEVICE_STATUS)))
+			dmi->flags &= ~DM_EXISTS_FLAG;	/* FIXME */
+		else {
+			if (_log_suppress)
+				log_verbose("device-mapper: %s ioctl "
+					    "failed: %s",
+				    	    _cmd_data_v4[dmt->type].name,
+					    strerror(errno));
+			else
+				log_error("device-mapper: %s ioctl "
+					  "failed: %s",
+				    	   _cmd_data_v4[dmt->type].name,
+					  strerror(errno));
+			dm_free(dmi);
+			return NULL;
+		}
+	}
+#else /* Userspace alternative for testing */
+#endif
+	return dmi;
+}
+
+void dm_task_update_nodes(void)
+{
+	update_devs();
+}
+
+int dm_task_run(struct dm_task *dmt)
+{
+	struct dm_ioctl *dmi;
+	unsigned command;
+
+#ifdef DM_COMPAT
+	if (_dm_version == 1)
+		return _dm_task_run_v1(dmt);
+#endif
+
+	if ((unsigned) dmt->type >=
+	    (sizeof(_cmd_data_v4) / sizeof(*_cmd_data_v4))) {
+		log_error("Internal error: unknown device-mapper task %d",
+			  dmt->type);
+		return 0;
+	}
+
+	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 (dmt->type == DM_DEVICE_MKNODES && !dmt->dev_name &&
+	    !dmt->uuid && dmt->major <= 0)
+		return _mknodes_v4(dmt);
+
+	if ((dmt->type == DM_DEVICE_RELOAD) && dmt->suppress_identical_reload)
+		return _reload_with_suppression_v4(dmt);
+
+	if (!_open_control())
+		return 0;
+
+repeat_ioctl:
+	if (!(dmi = _do_dm_ioctl(dmt, command, _ioctl_buffer_double_factor)))
+		return 0;
+
+	if (dmi->flags & DM_BUFFER_FULL_FLAG) {
+		switch (dmt->type) {
+		case DM_DEVICE_LIST_VERSIONS:
+		case DM_DEVICE_LIST:
+		case DM_DEVICE_DEPS:
+		case DM_DEVICE_STATUS:
+		case DM_DEVICE_TABLE:
+		case DM_DEVICE_WAITEVENT:
+			_ioctl_buffer_double_factor++;
+			dm_free(dmi);
+			goto repeat_ioctl;
+		default:
+			log_error("WARNING: libdevmapper buffer too small for data");
+		}
+	}
+
+	switch (dmt->type) {
+	case DM_DEVICE_CREATE:
+		if (dmt->dev_name && *dmt->dev_name)
+			add_dev_node(dmt->dev_name, MAJOR(dmi->dev),
+				     MINOR(dmi->dev), dmt->uid, dmt->gid,
+				     dmt->mode);
+		break;
+
+	case DM_DEVICE_REMOVE:
+		/* FIXME Kernel needs to fill in dmi->name */
+		if (dmt->dev_name)
+			rm_dev_node(dmt->dev_name);
+		break;
+
+	case DM_DEVICE_RENAME:
+		/* FIXME Kernel needs to fill in dmi->name */
+		if (dmt->dev_name)
+			rename_dev_node(dmt->dev_name, dmt->newname);
+		break;
+
+	case DM_DEVICE_RESUME:
+		/* FIXME Kernel needs to fill in dmi->name */
+		set_dev_node_read_ahead(dmt->dev_name, dmt->read_ahead,
+					dmt->read_ahead_flags);
+		break;
+	
+	case DM_DEVICE_MKNODES:
+		if (dmi->flags & DM_EXISTS_FLAG)
+			add_dev_node(dmi->name, MAJOR(dmi->dev),
+				     MINOR(dmi->dev),
+				     dmt->uid, dmt->gid, dmt->mode);
+		else if (dmt->dev_name)
+			rm_dev_node(dmt->dev_name);
+		break;
+
+	case DM_DEVICE_STATUS:
+	case DM_DEVICE_TABLE:
+	case DM_DEVICE_WAITEVENT:
+		if (!_unmarshal_status(dmt, dmi))
+			goto bad;
+		break;
+	}
+
+	/* Was structure reused? */
+	if (dmt->dmi.v4)
+		dm_free(dmt->dmi.v4);
+	dmt->dmi.v4 = dmi;
+	return 1;
+
+      bad:
+	dm_free(dmi);
+	return 0;
+}
+
+void dm_lib_release(void)
+{
+	if (_control_fd != -1) {
+		close(_control_fd);
+		_control_fd = -1;
+	}
+	update_devs();
+}
+
+void dm_lib_exit(void)
+{
+	dm_lib_release();
+	if (_dm_bitset)
+		dm_bitset_destroy(_dm_bitset);
+	_dm_bitset = NULL;
+	dm_dump_memory();
+	_version_ok = 1;
+	_version_checked = 0;
+}
Index: src/external/gpl2/lvm2tools/dist/libdm/ioctl/libdm-nbsd-iface.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/ioctl/libdm-nbsd-iface.c
diff -N src/external/gpl2/lvm2tools/dist/libdm/ioctl/libdm-nbsd-iface.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/ioctl/libdm-nbsd-iface.c	17 Dec 2008 01:40:22 -0000	1.1.2.3
@@ -0,0 +1,1153 @@
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2008 Adam Hamsik. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "dmlib.h"
+#include "libdm-targets.h"
+#include "libdm-common.h"
+
+#include <sys/ioctl.h>
+#include <sys/sysctl.h>
+
+#include <fcntl.h>
+#include <dirent.h>
+#include <limits.h>
+
+#include <netbsd-dm.h>
+
+#include <dm-ioctl.h>
+
+/*
+ * 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) || \
+      (DM_VERSION_MAJOR == 4 && DM_VERSION_MINOR >= 0))
+#error The version of dm-ioctl.h included is incompatible.
+#endif
+
+/* dm major version no for running kernel */
+static unsigned _dm_version_minor = 0;
+static unsigned _dm_version_patchlevel = 0;
+
+static int _control_fd = -1;
+static int _version_checked = 0;
+static int _version_ok = 1;
+static unsigned _ioctl_buffer_double_factor = 0;
+
+/* *INDENT-OFF* */
+
+/*
+ * XXX Remove this structure and write another own one
+ * I don't understand why ioctl calls has different
+ * names then dm task type
+ */
+static struct cmd_data _cmd_data_v4[] = {
+	{"create",	DM_DEV_CREATE,		{4, 0, 0}},
+	{"reload",	DM_TABLE_LOAD,		{4, 0, 0}}, /* DM_DEVICE_RELOAD */
+	{"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}}, /* DM_DEVICE_DEPS */
+	{"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}}, /* DM_DEVICE_TABLE */
+	{"waitevent",	DM_DEV_WAIT,		{4, 0, 0}},
+	{"names",	DM_LIST_DEVICES,	{4, 0, 0}},
+	{"clear",	DM_TABLE_CLEAR,		{4, 0, 0}},
+	{"mknodes",	DM_DEV_STATUS,		{4, 0, 0}},
+#ifdef DM_LIST_VERSIONS
+	{"targets",	DM_LIST_VERSIONS,	{4, 1, 0}},
+#endif
+#ifdef DM_TARGET_MSG
+	{"message",	DM_TARGET_MSG,		{4, 2, 0}},
+#endif
+#ifdef DM_DEV_SET_GEOMETRY
+	{"setgeometry",	DM_DEV_SET_GEOMETRY,	{4, 6, 0}},
+#endif
+};
+/* *INDENT-ON* */
+
+/*
+ * In NetBSD we use sysctl to get kernel drivers info. control device
+ * has predefined minor number 0 and major number = char major number
+ * of dm driver. First slot is therefore ocupied with control device
+ * and minor device starts from 1;
+ */
+
+static int _control_device_number(uint32_t *major, uint32_t *minor)
+{
+
+	nbsd_get_dm_major(major, DM_CHAR_MAJOR);
+	
+	*minor = 0;
+	
+	return 1;
+}
+
+/*
+ * Returns 1 if exists; 0 if it doesn't; -1 if it's wrong
+ */
+static int _control_exists(const char *control, uint32_t major, uint32_t minor)
+{
+	struct stat buf;
+
+	if (stat(control, &buf) < 0) {
+		if (errno != ENOENT)
+			log_sys_error("stat", control);
+		return 0;
+	}
+
+	if (!S_ISCHR(buf.st_mode)) {
+		log_verbose("%s: Wrong inode type", control);
+		if (!unlink(control))
+			return 0;
+		log_sys_error("unlink", control);
+		return -1;
+	}
+
+	if (major && buf.st_rdev != MKDEV(major, minor)) {
+		log_verbose("%s: Wrong device number: (%u, %u) instead of "
+			    "(%u, %u)", control,
+			    MAJOR(buf.st_mode), MINOR(buf.st_mode),
+			    major, minor);
+		if (!unlink(control))
+			return 0;
+		log_sys_error("unlink", control);
+		return -1;
+	}
+
+	return 1;
+}
+
+static int _create_control(const char *control, uint32_t major, uint32_t minor)
+{
+	int ret;
+	mode_t old_umask;
+
+	if (!major)
+		return 0;
+
+	old_umask = umask(0022);
+	ret = dm_create_dir(dm_dir());
+	umask(old_umask);
+
+	if (!ret)
+		return 0;
+
+	log_verbose("Creating device %s (%u, %u)", control, major, minor);
+
+	if (mknod(control, S_IFCHR | S_IRUSR | S_IWUSR,
+		  MKDEV(major, minor)) < 0)  {
+		log_sys_error("mknod", control);
+		return 0;
+	}
+
+
+	return 1;
+}
+
+/* Check if major is device-mapper block device major number */
+int dm_is_dm_major(uint32_t major)
+{
+	uint32_t dm_major;
+
+	nbsd_get_dm_major(&dm_major, DM_BLOCK_MAJOR);
+	
+	if (major == dm_major)
+		return 1;
+
+	return 0;
+}
+
+/* Open control device if doesn't exist create it. */
+static int _open_control(void)
+{
+	char control[PATH_MAX];
+	uint32_t major = 0, minor = 0;
+
+	if (_control_fd != -1)
+		return 1;
+
+	snprintf(control, sizeof(control), "%s/control", dm_dir());
+
+	if (!_control_device_number(&major, &minor))
+		log_error("Is device-mapper driver missing from kernel?");
+
+	if (!_control_exists(control, major, minor) &&
+	    !_create_control(control, major, minor))
+		goto error;
+
+	if ((_control_fd = open(control, O_RDWR)) < 0) {
+		log_sys_error("open", control);
+		goto error;
+	}
+
+	return 1;
+
+error:
+	log_error("Failure to communicate with kernel device-mapper driver.");
+	return 0;
+}
+
+/*
+ * Destroy dm task structure there are some dynamically alocated values there.
+ * name, uuid, head, tail list.
+ */
+void dm_task_destroy(struct dm_task *dmt)
+{
+	struct target *t, *n;
+
+	for (t = dmt->head; t; t = n) {
+		n = t->next;
+		dm_free(t->params);
+		dm_free(t->type);
+		dm_free(t);
+	}
+
+	if (dmt->dev_name)
+		dm_free(dmt->dev_name);
+
+	if (dmt->newname)
+		dm_free(dmt->newname);
+
+	if (dmt->message)
+		dm_free(dmt->message);
+
+	if (dmt->dmi.v4)
+		dm_free(dmt->dmi.v4);
+
+	if (dmt->uuid)
+		dm_free(dmt->uuid);
+
+	dm_free(dmt);
+
+}
+
+/* Get kernel driver version from dm_ioctl structure. */
+int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size)
+{
+	unsigned *v;
+
+	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]);
+	_dm_version_minor = v[1];
+	_dm_version_patchlevel = v[2];
+
+	return 1;
+}
+
+/* Get kernel driver protocol version and comapre it with library version. */
+static int _check_version(char *version, size_t size)
+{
+	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;
+	}
+
+	r = dm_task_run(task);
+	dm_task_get_driver_version(task, version, size);
+	dm_task_destroy(task);
+
+	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 dmversion[64];
+
+	if (_version_checked)
+		return _version_ok;
+
+	_version_checked = 1;
+
+	if (_check_version(dmversion, sizeof(dmversion)))
+		return 1;
+
+
+	return 0;
+}
+
+/* Get next target(table description) from list pointed by dmt->head. */
+void *dm_get_next_target(struct dm_task *dmt, void *next,
+			 uint64_t *start, uint64_t *length,
+			 char **target_type, char **params)
+{
+	struct target *t = (struct target *) next;
+
+	if (!t)
+		t = dmt->head;
+
+	if (!t)
+		return NULL;
+
+	*start = t->start;
+	*length = t->length;
+	*target_type = t->type;
+	*params = t->params;
+
+	return t->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 + dmi->data_start;
+	char *outptr = outbuf;
+	uint32_t i;
+	struct dm_target_spec *spec;
+
+	for (i = 0; i < dmi->target_count; i++) {
+		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 = outbuf + spec->next;
+	}
+
+	return 1;
+}
+
+/*
+ * @dev_major is major number of char device
+ *
+ * I have to find it's block device number and lookup dev in
+ * device database to find device path.
+ *
+ */
+
+int dm_format_dev(char *buf, int bufsize, uint32_t dev_major,
+		  uint32_t dev_minor)
+{
+	int r;
+	uint32_t major, dm_major;
+	char *name;
+	mode_t mode;
+	dev_t dev;
+	size_t val_len,i;
+	struct kinfo_drivers *kd;
+	
+	mode = 0;
+	
+	nbsd_get_dm_major(&dm_major, DM_BLOCK_MAJOR);
+
+	log_error("format_dev %d--%d %d", dev_major, dev_minor, bufsize);
+
+	if (bufsize < 8)
+		return 0;
+	
+	if (sysctlbyname("kern.drivers",NULL,&val_len,NULL,0) < 0) {
+		printf("sysctlbyname failed");
+		return 0;
+	}
+
+	if ((kd = malloc (val_len)) == NULL){
+		printf("malloc kd info error\n");
+		return 0;
+	}
+
+	if (sysctlbyname("kern.drivers", kd, &val_len, NULL, 0) < 0) {
+		printf("sysctlbyname failed kd");
+		return 0;
+	}
+
+	for (i = 0, val_len /= sizeof(*kd); i < val_len; i++){
+		if (kd[i].d_cmajor == dev_major) {
+			major = kd[i].d_bmajor;
+			break;
+		}
+	}
+	
+	dev = MKDEV(major,dev_minor);
+
+	mode |= S_IFBLK;
+	
+	name = devname(dev,mode);
+
+	r = snprintf(buf, (size_t) bufsize, "/dev/%s",name);
+
+	free(kd);
+	
+	if (r < 0 || r > bufsize - 1 || name == NULL)
+		return 0;
+	
+	return 1;
+}
+
+/* Fill info from dm_ioctl structure. Look at DM_EXISTS_FLAG*/
+int dm_task_get_info(struct dm_task *dmt, struct dm_info *info)
+{
+	if (!dmt->dmi.v4)
+		return 0;
+
+	memset(info, 0, sizeof(*info));
+
+	info->exists = dmt->dmi.v4->flags & DM_EXISTS_FLAG ? 1 : 0;
+	if (!info->exists)
+		return 1;
+
+	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;
+	
+	nbsd_get_dm_major(&info->major, DM_BLOCK_MAJOR); /* get netbsd dm device major number */
+	info->minor = MINOR(dmt->dmi.v4->dev);
+	
+	return 1;
+}
+
+/* Unsupported on NetBSD */
+uint32_t dm_task_get_read_ahead(const struct dm_task *dmt, uint32_t *read_ahead)
+{
+	*read_ahead = DM_READ_AHEAD_NONE;
+	return 1;
+}
+
+const char *dm_task_get_name(const struct dm_task *dmt)
+{
+
+	return (dmt->dmi.v4->name);
+}
+
+const char *dm_task_get_uuid(const struct dm_task *dmt)
+{
+
+	return (dmt->dmi.v4->uuid);
+}
+
+struct dm_deps *dm_task_get_deps(struct dm_task *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)
+{
+	return (struct dm_names *) (((void *) dmt->dmi.v4) +
+				    dmt->dmi.v4->data_start);
+}
+
+struct dm_versions *dm_task_get_versions(struct dm_task *dmt)
+{
+	return (struct dm_versions *) (((void *) dmt->dmi.v4) +
+				       dmt->dmi.v4->data_start);
+}
+
+int dm_task_set_ro(struct dm_task *dmt)
+{
+	dmt->read_only = 1;
+	return 1;
+}
+
+/* Unsupported on NetBSD */
+int dm_task_set_read_ahead(struct dm_task *dmt, uint32_t read_ahead,
+			   uint32_t read_ahead_flags)
+{
+	return 1;
+}
+
+int dm_task_suppress_identical_reload(struct dm_task *dmt)
+{
+	dmt->suppress_identical_reload = 1;
+	return 1;
+}
+
+int dm_task_set_newname(struct dm_task *dmt, const char *newname)
+{
+	if (!(dmt->newname = dm_strdup(newname))) {
+		log_error("dm_task_set_newname: strdup(%s) failed", newname);
+		return 0;
+	}
+
+	return 1;
+}
+
+int dm_task_set_message(struct dm_task *dmt, const char *message)
+{
+	if (!(dmt->message = dm_strdup(message))) {
+		log_error("dm_task_set_message: strdup(%s) failed", message);
+		return 0;
+	}
+
+	return 1;
+}
+
+int dm_task_set_sector(struct dm_task *dmt, uint64_t sector)
+{
+	dmt->sector = sector;
+
+	return 1;
+}
+
+/* Unsupported in NetBSD */
+int dm_task_set_geometry(struct dm_task *dmt, const char *cylinders,
+    const char *heads, const char *sectors, const char *start)
+{
+	return 0;
+}
+
+int dm_task_no_flush(struct dm_task *dmt)
+{
+	dmt->no_flush = 1;
+
+	return 1;
+}
+
+int dm_task_no_open_count(struct dm_task *dmt)
+{
+	dmt->no_open_count = 1;
+
+	return 1;
+}
+
+int dm_task_skip_lockfs(struct dm_task *dmt)
+{
+	dmt->skip_lockfs = 1;
+
+	return 1;
+}
+
+int dm_task_set_event_nr(struct dm_task *dmt, uint32_t event_nr)
+{
+	dmt->event_nr = event_nr;
+
+	return 1;
+}
+
+/* Allocate one target(table description) entry. */
+struct target *create_target(uint64_t start, uint64_t len, const char *type,
+			     const char *params)
+{
+	struct target *t = dm_malloc(sizeof(*t));
+
+	if (!t) {
+		log_error("create_target: malloc(%" PRIsize_t ") failed",
+			  sizeof(*t));
+		return NULL;
+	}
+
+	memset(t, 0, sizeof(*t));
+
+	if (!(t->params = dm_strdup(params))) {
+		log_error("create_target: strdup(params) failed");
+		goto bad;
+	}
+
+	if (!(t->type = dm_strdup(type))) {
+		log_error("create_target: strdup(type) failed");
+		goto bad;
+	}
+
+	t->start = start;
+	t->length = len;
+	return t;
+
+      bad:
+	dm_free(t->params);
+	dm_free(t->type);
+	dm_free(t);
+	return NULL;
+}
+
+/* Parse given dm task structure to proplib dictionary.  */
+static int _flatten(struct dm_task *dmt, prop_dictionary_t dm_dict)
+{
+	prop_array_t cmd_array;
+	prop_dictionary_t target_spec;
+	
+	struct target *t;
+	
+	size_t len;
+	char type[DM_MAX_TYPE_NAME];
+	
+	uint32_t major, flags;
+	int count = 0;
+	const int (*version)[3];
+	
+	flags = 0;
+	version = &_cmd_data_v4[dmt->type].version;
+
+	cmd_array = prop_array_create();
+
+	for (t = dmt->head; t; t = t->next) {
+		target_spec = prop_dictionary_create();
+
+		prop_dictionary_set_uint64(target_spec,DM_TABLE_START,t->start);
+		prop_dictionary_set_uint64(target_spec,DM_TABLE_LENGTH,t->length);
+
+		strlcpy(type,t->type,DM_MAX_TYPE_NAME);
+
+		prop_dictionary_set_cstring(target_spec,DM_TABLE_TYPE,type);
+		prop_dictionary_set_cstring(target_spec,DM_TABLE_PARAMS,t->params);
+
+		prop_array_set(cmd_array,count,target_spec);
+
+		prop_object_release(target_spec);
+		
+		count++;
+	}
+
+	
+	if (count && (dmt->sector || dmt->message)) {
+		log_error("targets and message are incompatible");
+		return -1;
+	}
+
+	if (count && dmt->newname) {
+		log_error("targets and newname are incompatible");
+		return -1;
+	}
+
+	if (count && dmt->geometry) {
+		log_error("targets and geometry are incompatible");
+		return -1;
+	}
+
+	if (dmt->newname && (dmt->sector || dmt->message)) {
+		log_error("message and newname are incompatible");
+		return -1;
+	}
+
+	if (dmt->newname && dmt->geometry) {
+		log_error("geometry and newname are incompatible");
+		return -1;
+	}
+
+	if (dmt->geometry && (dmt->sector || dmt->message)) {
+		log_error("geometry and message are incompatible");
+		return -1;
+	}
+
+	if (dmt->sector && !dmt->message) {
+		log_error("message is required with sector");
+		return -1;
+	}
+
+	if (dmt->newname)
+		len += strlen(dmt->newname) + 1;
+
+	if (dmt->message)
+		len += sizeof(struct dm_target_msg) + strlen(dmt->message) + 1;
+
+	if (dmt->geometry)
+		len += strlen(dmt->geometry) + 1;
+
+	nbsd_dmi_add_version((*version), dm_dict);
+	    
+	nbsd_get_dm_major(&major, DM_BLOCK_MAJOR);
+	/* 
+	 * Only devices with major which is equal to netbsd dm major 
+	 * dm devices in NetBSD can't have more majors then one assigned to dm.
+	 */
+	if (dmt->major != major && dmt->major != -1)
+		return -1;
+		
+	if (dmt->minor >= 0) {
+		flags |= DM_PERSISTENT_DEV_FLAG;
+		
+		prop_dictionary_set_uint32(dm_dict, DM_IOCTL_MINOR, dmt->minor);
+	}
+
+	/* Set values to dictionary. */
+	if (dmt->dev_name)
+		prop_dictionary_set_cstring(dm_dict, DM_IOCTL_NAME, dmt->dev_name);
+
+	if (dmt->uuid)
+		prop_dictionary_set_cstring(dm_dict, DM_IOCTL_UUID, dmt->uuid);
+	
+	if (dmt->type == DM_DEVICE_SUSPEND)
+		flags |= DM_SUSPEND_FLAG;
+	if (dmt->no_flush)
+		flags |= DM_NOFLUSH_FLAG;
+	if (dmt->read_only)
+		flags |= DM_READONLY_FLAG;
+	if (dmt->skip_lockfs)
+		flags |= DM_SKIP_LOCKFS_FLAG;
+
+	prop_dictionary_set_uint32(dm_dict, DM_IOCTL_FLAGS, flags);
+
+	prop_dictionary_set_uint32(dm_dict, DM_IOCTL_EVENT, dmt->event_nr);
+
+	if (dmt->newname)
+		prop_array_set_cstring(cmd_array, 0, dmt->newname);
+	
+	/* Add array for all COMMAND specific data. */
+	prop_dictionary_set(dm_dict, DM_IOCTL_CMD_DATA, cmd_array);
+	prop_object_release(cmd_array);
+	
+	return 0;
+}
+
+static int _process_mapper_dir(struct dm_task *dmt)
+{
+	struct dirent *dirent;
+	DIR *d;
+	const char *dir;
+	int r = 1;
+
+	dir = dm_dir();
+	if (!(d = opendir(dir))) {
+		log_sys_error("opendir", dir);
+		return 0;
+	}
+
+	while ((dirent = readdir(d))) {
+		if (!strcmp(dirent->d_name, ".") ||
+		    !strcmp(dirent->d_name, "..") ||
+		    !strcmp(dirent->d_name, "control"))
+			continue;
+		dm_task_set_name(dmt, dirent->d_name);
+		dm_task_run(dmt);
+	}
+
+	if (closedir(d))
+		log_sys_error("closedir", dir);
+
+	return r;
+}
+
+/* Get list of all devices. */
+static int _process_all_v4(struct dm_task *dmt)
+{
+	struct dm_task *task;
+	struct dm_names *names;
+	unsigned next = 0;
+	int r = 1;
+
+	if (!(task = dm_task_create(DM_DEVICE_LIST)))
+		return 0;
+
+	if (!dm_task_run(task)) {
+		r = 0;
+		goto out;
+	}
+
+	if (!(names = dm_task_get_names(task))) {
+		r = 0;
+		goto out;
+	}
+
+	if (!names->dev)
+		goto out;
+
+	do {
+		names = (void *) names + next;
+		if (!dm_task_set_name(dmt, names->name)) {
+			r = 0;
+			goto out;
+		}
+		if (!dm_task_run(dmt))
+			r = 0;
+		next = names->next;
+	} while (next);
+
+      out:
+	dm_task_destroy(task);
+	return r;
+}
+
+static int _mknodes_v4(struct dm_task *dmt)
+{
+	(void) _process_mapper_dir(dmt);
+
+	return _process_all_v4(dmt);
+}
+
+/* Create new device and load table to it. */
+static int _create_and_load_v4(struct dm_task *dmt)
+{
+	struct dm_task *task;
+	int r;
+
+	printf("create and load called \n");
+	
+	/* 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;
+	}
+
+	/* Copy across relevant fields */
+	if (dmt->dev_name && !dm_task_set_name(task, dmt->dev_name)) {
+		dm_task_destroy(task);
+		return 0;
+	}
+
+	if (dmt->uuid && !dm_task_set_uuid(task, dmt->uuid)) {
+		dm_task_destroy(task);
+		return 0;
+	}
+
+	task->major = dmt->major;
+	task->minor = dmt->minor;
+	task->uid = dmt->uid;
+	task->gid = dmt->gid;
+	task->mode = dmt->mode;
+
+	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)
+		goto revert;
+
+	/* Use the original structure last so the info will be correct */
+	dmt->type = DM_DEVICE_RESUME;
+	dm_free(dmt->uuid);
+	dmt->uuid = NULL;
+
+	r = dm_task_run(dmt);
+
+	if (r)
+		return r;
+
+      revert:
+ 	dmt->type = DM_DEVICE_REMOVE;
+	dm_free(dmt->uuid);
+	dmt->uuid = NULL;
+
+	if (!dm_task_run(dmt))
+		log_error("Failed to revert device creation.");
+
+	return r;
+}
+
+uint64_t dm_task_get_existing_table_size(struct dm_task *dmt)
+{
+	return dmt->existing_table_size;
+}
+
+static int _reload_with_suppression_v4(struct dm_task *dmt)
+{
+	struct dm_task *task;
+	struct target *t1, *t2;
+	int r;
+	
+	/* New task to get existing table information */
+	if (!(task = dm_task_create(DM_DEVICE_TABLE))) {
+		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;
+	}
+
+	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);
+
+	if (!r) {
+		dm_task_destroy(task);
+		return r;
+	}
+
+	/* Store existing table size */
+	t2 = task->head;
+	while (t2 && t2->next)
+		t2 = t2->next;
+	dmt->existing_table_size = t2 ? t2->start + t2->length : 0;
+	
+	if ((task->dmi.v4->flags & DM_READONLY_FLAG) ? 1 : 0 != dmt->read_only)
+		goto no_match;
+
+	t1 = dmt->head;
+	t2 = task->head;
+
+	while (t1 && t2) {
+		while (t2->params[strlen(t2->params) - 1] == ' ')
+			t2->params[strlen(t2->params) - 1] = '\0';
+		if ((t1->start != t2->start) ||
+		    (t1->length != t2->length) ||
+		    (strcmp(t1->type, t2->type)) ||
+		    (strcmp(t1->params, t2->params)))
+			goto no_match;
+		t1 = t1->next;
+		t2 = t2->next;
+	}
+	
+	if (!t1 && !t2) {
+		dmt->dmi.v4 = task->dmi.v4;
+		task->dmi.v4 = NULL;
+		dm_task_destroy(task);
+		return 1;
+	}
+
+no_match:
+	dm_task_destroy(task);
+
+	/* Now do the original reload */
+	dmt->suppress_identical_reload = 0;
+	r = dm_task_run(dmt);
+
+	return r;
+}
+
+/*
+ * This function is heart of NetBSD libdevmapper-> device-mapper kernel protocol
+ * It creates proplib_dictionary from dm task structure and sends it to NetBSD
+ * kernel driver. After succesfull ioctl it create dmi structure from returned
+ * proplib dictionary. This way I keep number of changes in NetBSD version of
+ * libdevmapper as small as posible.
+ */
+static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command)
+{
+	struct dm_ioctl *dmi;
+	prop_dictionary_t dm_dict_in, dm_dict_out;
+	
+	uint32_t flags;
+
+	dm_dict_in = NULL;
+	
+	dm_dict_in = prop_dictionary_create(); /* Dictionary send to kernel */
+	dm_dict_out = prop_dictionary_create(); /* Dictionary received from kernel */
+
+	/* Set command name to dictionary */
+	prop_dictionary_set_cstring(dm_dict_in, DM_IOCTL_COMMAND,
+	    _cmd_data_v4[dmt->type].name);
+
+	/* Parse dmi from libdevmapper to dictionary */
+	if (_flatten(dmt, dm_dict_in) < 0)
+		goto bad;
+
+	prop_dictionary_get_uint32(dm_dict_in, DM_IOCTL_FLAGS, &flags);
+		
+	if (dmt->type == DM_DEVICE_TABLE)
+		flags |= DM_STATUS_TABLE_FLAG;
+
+	if (dmt->no_open_count)
+		flags |= DM_SKIP_BDGET_FLAG;
+
+	flags |= DM_EXISTS_FLAG;
+	
+	/* Set flags to dictionary. */
+	prop_dictionary_set_uint32(dm_dict_in,DM_IOCTL_FLAGS,flags);
+	
+	prop_dictionary_externalize_to_file(dm_dict_in,"/tmp/test_in");
+	
+	log_very_verbose("Ioctl type  %s --- flags %d",_cmd_data_v4[dmt->type].name,flags);
+	//printf("name %s, major %d minor %d\n uuid %s\n", 
+        //dm_task_get_name(dmt), dmt->minor, dmt->major, dm_task_get_uuid(dmt));
+	/* Send dictionary to kernel and wait for reply. */
+	if (prop_dictionary_sendrecv_ioctl(dm_dict_in,_control_fd,
+		NETBSD_DM_IOCTL,&dm_dict_out) != 0) {
+
+		if (errno == ENOENT &&
+		    ((dmt->type == DM_DEVICE_INFO) ||
+			(dmt->type == DM_DEVICE_MKNODES) ||
+			(dmt->type == DM_DEVICE_STATUS))) {
+
+			/*
+			 * Linux version doesn't fail when ENOENT is returned
+			 * for nonexisting device after info, deps, mknodes call.
+			 * It returns dmi sent to kernel with DM_EXISTS_FLAG = 0;
+			 */
+			
+			dmi = nbsd_dm_dict_to_dmi(dm_dict_in,_cmd_data_v4[dmt->type].cmd);
+
+			dmi->flags &= ~DM_EXISTS_FLAG; 
+
+			prop_object_release(dm_dict_in);
+			prop_object_release(dm_dict_out);
+
+			goto out;
+		} else {
+			log_error("ioctl %s call failed with errno %d\n", 
+					  _cmd_data_v4[dmt->type].name, errno);
+
+			prop_object_release(dm_dict_in);
+			prop_object_release(dm_dict_out);
+
+			goto bad;
+		}
+	}
+
+	prop_dictionary_externalize_to_file(dm_dict_out,"/tmp/test_out");
+
+	/* Parse kernel dictionary to dmi structure and return it to libdevmapper. */
+	dmi = nbsd_dm_dict_to_dmi(dm_dict_out,_cmd_data_v4[dmt->type].cmd);
+
+	prop_object_release(dm_dict_in);
+	prop_object_release(dm_dict_out);
+out:	
+	return dmi;
+bad:
+	return NULL;
+}
+
+/* Create new edvice nodes in mapper/ dir. */
+void dm_task_update_nodes(void)
+{
+	update_devs();
+}
+
+/* Run dm command which is descirbed in dm_task structure. */
+int dm_task_run(struct dm_task *dmt)
+{
+	struct dm_ioctl *dmi;
+	unsigned command;
+
+	if ((unsigned) dmt->type >=
+	    (sizeof(_cmd_data_v4) / sizeof(*_cmd_data_v4))) {
+		log_error("Internal error: unknown device-mapper task %d",
+			  dmt->type);
+		return 0;
+	}
+
+	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 (dmt->type == DM_DEVICE_MKNODES && !dmt->dev_name &&
+	    !dmt->uuid && dmt->major <= 0)
+		return _mknodes_v4(dmt);
+
+	if ((dmt->type == DM_DEVICE_RELOAD) && dmt->suppress_identical_reload)
+		return _reload_with_suppression_v4(dmt);
+	
+	if (!_open_control())
+		return 0;
+
+	if (!(dmi = _do_dm_ioctl(dmt, command)))
+		return 0;
+
+	switch (dmt->type) {
+	case DM_DEVICE_CREATE:
+		add_dev_node(dmt->dev_name, MAJOR(dmi->dev), MINOR(dmi->dev),
+			     dmt->uid, dmt->gid, dmt->mode);
+		break;
+
+	case DM_DEVICE_REMOVE:
+		/* FIXME Kernel needs to fill in dmi->name */
+		if (dmt->dev_name)
+			rm_dev_node(dmt->dev_name);
+		break;
+
+	case DM_DEVICE_RENAME:
+		/* FIXME Kernel needs to fill in dmi->name */
+		if (dmt->dev_name)
+			rename_dev_node(dmt->dev_name, dmt->newname);
+		break;
+
+	case DM_DEVICE_RESUME:
+		/* FIXME Kernel needs to fill in dmi->name */
+		set_dev_node_read_ahead(dmt->dev_name, dmt->read_ahead,
+					dmt->read_ahead_flags);
+		break;
+	
+	case DM_DEVICE_MKNODES:
+		if (dmi->flags & DM_EXISTS_FLAG)
+			add_dev_node(dmi->name, MAJOR(dmi->dev),
+				     MINOR(dmi->dev),
+				     dmt->uid, dmt->gid, dmt->mode);
+		else if (dmt->dev_name)
+			rm_dev_node(dmt->dev_name);
+		break;
+
+	case DM_DEVICE_STATUS:
+	case DM_DEVICE_TABLE:
+	case DM_DEVICE_WAITEVENT:
+		if (!_unmarshal_status(dmt, dmi))
+			goto bad;
+		break;
+	}
+
+	/* Was structure reused? */
+	if (dmt->dmi.v4)
+		dm_free(dmt->dmi.v4);
+
+	dmt->dmi.v4 = dmi;
+	return 1;
+
+      bad:
+	dm_free(dmi);
+	return 0;
+}
+
+void dm_lib_release(void)
+{
+	if (_control_fd != -1) {
+		close(_control_fd);
+		_control_fd = -1;
+	}
+	update_devs();
+}
+
+void dm_lib_exit(void)
+{
+	dm_lib_release();
+	dm_dump_memory();
+	_version_ok = 1;
+	_version_checked = 0;
+}
Index: src/external/gpl2/lvm2tools/dist/libdm/ioctl/libdm-targets.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/ioctl/libdm-targets.h
diff -N src/external/gpl2/lvm2tools/dist/libdm/ioctl/libdm-targets.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/ioctl/libdm-targets.h	13 Dec 2008 14:39:36 -0000	1.1.1.1.2.2
@@ -0,0 +1,77 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef LIB_DMTARGETS_H
+#define LIB_DMTARGETS_H
+
+#include <inttypes.h>
+#include <sys/types.h>
+
+struct dm_ioctl;
+struct dm_ioctl_v1;
+
+struct target {
+	uint64_t start;
+	uint64_t length;
+	char *type;
+	char *params;
+
+	struct target *next;
+};
+
+struct dm_task {
+	int type;
+	char *dev_name;
+
+	struct target *head, *tail;
+
+	int read_only;
+	uint32_t event_nr;
+	int major;
+	int minor;
+	uid_t uid;
+	gid_t gid;
+	mode_t mode;
+	uint32_t read_ahead;
+	uint32_t read_ahead_flags;
+	union {
+		struct dm_ioctl *v4;
+		struct dm_ioctl_v1 *v1;
+	} dmi;
+	char *newname;
+	char *message;
+	char *geometry;
+	uint64_t sector;
+	int no_flush;
+	int no_open_count;
+	int skip_lockfs;
+	int suppress_identical_reload;
+	uint64_t existing_table_size;
+
+	char *uuid;
+};
+
+struct cmd_data {
+	const char *name;
+	const int cmd;
+	const int version[3];
+};
+
+int dm_check_version(void);
+uint64_t dm_task_get_existing_table_size(struct dm_task *dmt);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/libdm/ioctl/libdm_netbsd.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/ioctl/libdm_netbsd.c
diff -N src/external/gpl2/lvm2tools/dist/libdm/ioctl/libdm_netbsd.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/ioctl/libdm_netbsd.c	17 Dec 2008 00:48:49 -0000	1.1.2.2
@@ -0,0 +1,502 @@
+/*
+ * Copyright (c) 1996, 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Adam Hamsik.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+#include <err.h>
+#include <errno.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <netbsd-dm.h>
+
+#include <dm-ioctl.h>
+
+#include "lib.h"
+
+#define DMI_SIZE 16 * 1024
+
+static int dm_list_versions(prop_dictionary_t, struct dm_ioctl *);
+static int dm_list_devices(prop_dictionary_t, struct dm_ioctl *);
+static int dm_dev_deps(prop_dictionary_t, struct dm_ioctl *);
+static int dm_table_status(prop_dictionary_t, struct dm_ioctl *);
+
+int
+nbsd_get_dm_major(uint32_t *major,  int type)
+{
+	size_t val_len,i;
+	struct kinfo_drivers *kd;
+
+	if (sysctlbyname("kern.drivers",NULL,&val_len,NULL,0) < 0) {
+		printf("sysctlbyname failed");
+		return 0;
+	}
+
+	if ((kd = malloc (val_len)) == NULL){
+		printf("malloc kd info error\n");
+		return 0;
+	}
+
+	if (sysctlbyname("kern.drivers", kd, &val_len, NULL, 0) < 0) {
+		printf("sysctlbyname failed kd");
+		return 0;
+	}
+
+	for (i = 0, val_len /= sizeof(*kd); i < val_len; i++) {
+
+		if (strncmp(kd[i].d_name,DM_NAME,strlen(kd[i].d_name)) == 0){
+
+			if (type == DM_CHAR_MAJOR)
+				/* Set major to dm-driver char major number. */
+				*major = kd[i].d_cmajor;
+			else
+				if (type == DM_BLOCK_MAJOR)
+					*major = kd[i].d_bmajor;
+			
+			free(kd);
+
+			return 1;
+		}
+	}
+
+	free(kd);
+	
+	return 0;
+}
+
+int
+nbsd_dmi_add_version(const int *version, prop_dictionary_t dm_dict)
+{
+	prop_array_t ver;
+	size_t i;
+
+	if ((ver = prop_array_create()) == NULL)
+		return -1;
+
+       	for (i=0;i<3;i++)
+		prop_array_set_uint32(ver,i,version[i]);
+
+	if ((prop_dictionary_set(dm_dict,"version",ver)) == false)
+		return -1;
+
+	prop_object_release(ver);
+	
+	return 0;
+}
+
+struct dm_ioctl*
+nbsd_dm_dict_to_dmi(prop_dictionary_t dm_dict,const int cmd)
+{
+	struct dm_ioctl *dmi;
+	prop_array_t ver;
+	
+	size_t i;
+	int r;
+	char *name, *uuid;
+	uint32_t major,minor;
+	
+	name = NULL;
+	uuid = NULL;
+	minor = 0;
+	
+	nbsd_get_dm_major(&major, DM_BLOCK_MAJOR);
+	
+	if (!(dmi = dm_malloc(DMI_SIZE)))
+		return NULL;
+
+	memset(dmi,0,DMI_SIZE);
+	
+	prop_dictionary_get_int32(dm_dict, DM_IOCTL_OPEN, &dmi->open_count);
+	prop_dictionary_get_uint32(dm_dict, DM_IOCTL_EVENT, &dmi->event_nr);
+	prop_dictionary_get_uint32(dm_dict, DM_IOCTL_FLAGS, &dmi->flags);
+	prop_dictionary_get_uint32(dm_dict, DM_IOCTL_TARGET_COUNT, 
+		&dmi->target_count);
+
+	if (prop_dictionary_get_uint32(dm_dict, DM_IOCTL_MINOR, &minor))
+		dmi->dev = MKDEV(major, minor);
+	else
+		dmi->dev = 0;
+	
+	/* Copy name and uuid to dm_ioctl. */
+	if (prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_NAME,
+		(const char **)&name)){
+		strlcpy(dmi->name, name, DM_NAME_LEN);
+	} else
+		dmi->name[0] = '\0';
+	
+	if (prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_UUID,
+		(const char **)&uuid)){
+		strlcpy(dmi->uuid, uuid, DM_UUID_LEN);
+	}  else
+		dmi->uuid[0] = '\0';
+
+	/* dmi parsing values, size of dmi block and offset to data. */
+	dmi->data_size  = DMI_SIZE;
+	dmi->data_start = sizeof(struct dm_ioctl);
+	
+	/* Get kernel version from dm_dict. */
+	ver = prop_dictionary_get(dm_dict,DM_IOCTL_VERSION);
+	
+	for(i=0; i<3; i++)
+		prop_array_get_uint32(ver,i,&dmi->version[i]);
+
+	switch (cmd){
+
+	case DM_LIST_VERSIONS:
+		r = dm_list_versions(dm_dict,dmi);
+		if (r >= 0)
+			dmi->target_count = r;
+		break;
+
+	case DM_LIST_DEVICES:
+		r = dm_list_devices(dm_dict,dmi);
+		if (r >= 0)
+			dmi->target_count = r;
+		break;	
+
+	case DM_TABLE_STATUS:
+		r = dm_table_status(dm_dict,dmi);
+		if (r >= 0)
+			dmi->target_count = r;
+		break;	
+
+	case DM_TABLE_DEPS:
+		r = dm_dev_deps(dm_dict,dmi);
+		if (r >= 0)
+			dmi->target_count = r;
+		break;	
+	}	
+	
+	return dmi;
+}
+
+/*
+ * Parse dm_dict when targets command was called and fill dm_ioctl buffer with it.
+ *
+ * Return number of targets or if failed <0 error.
+ */
+
+static int
+dm_list_versions(prop_dictionary_t dm_dict, struct dm_ioctl *dmi)
+{
+	struct dm_target_versions *dmtv,*odmtv;
+
+	prop_array_t targets,ver;
+	prop_dictionary_t target_dict;
+	prop_object_iterator_t iter;
+	
+	char *name;
+	size_t j,i,slen,rec_size;
+	
+	odmtv = NULL;
+	name = NULL;
+	j = 0;
+	
+	dmtv = (struct dm_target_versions *)((uint8_t *)dmi + dmi->data_start);
+
+/*	printf("dmi: vers: %d.%d.%d data_size: %d data_start: %d name: %s t_count: %d\n",
+	    dmi->version[0],dmi->version[1],dmi->version[2],dmi->data_size,dmi->data_start,
+	    dmi->name,dmi->target_count);
+
+	printf("dmi: size: %d -- %p --- %p \n",sizeof(struct dm_ioctl),dmi,dmi+dmi->data_start);
+	printf("dmtv: size: %p --- %p\n",dmtv,(struct dm_target_versions *)(dmi+312));*/
+
+	/* get prop_array of target_version dictionaries */
+	if ((targets = prop_dictionary_get(dm_dict,DM_IOCTL_CMD_DATA))){
+
+		iter = prop_array_iterator(targets);
+		if (!iter)
+			err(EXIT_FAILURE,"dm_list_versions %s",__func__);
+
+		while((target_dict = prop_object_iterator_next(iter)) != NULL){
+			j++;
+	
+			prop_dictionary_get_cstring_nocopy(target_dict,
+			    DM_TARGETS_NAME,(const char **)&name);
+			
+			slen = strlen(name) + 1;
+			rec_size = sizeof(struct dm_target_versions) + slen + 1;
+
+			if (rec_size > dmi->data_size)
+				return -ENOMEM;
+			
+			ver = prop_dictionary_get(target_dict,DM_TARGETS_VERSION);
+						
+			for (i=0; i<3; i++)
+				prop_array_get_uint32(ver,i,&dmtv->version[i]);
+
+			dmtv->next = rec_size;
+
+			strlcpy(dmtv->name,name,slen);
+
+			odmtv = dmtv;
+			
+			dmtv =(struct dm_target_versions *)((uint8_t *)dmtv + rec_size);
+		}
+
+		if (odmtv != NULL)
+			odmtv->next = 0;
+	}			
+
+	prop_object_iterator_release(iter);
+	return j;
+}
+
+/*
+ * List all available dm devices in system. 
+ */	
+static int
+dm_list_devices(prop_dictionary_t dm_dict, struct dm_ioctl *dmi)
+{
+	struct dm_name_list *dml,*odml;
+	
+	prop_array_t targets;
+	prop_dictionary_t target_dict;
+	prop_object_iterator_t iter;
+
+	uint32_t minor;
+	uint32_t major;
+	
+	char *name;
+	size_t j,slen,rec_size;
+
+	odml = NULL;
+	name = NULL;
+	minor = 0;
+	j = 0;
+
+	nbsd_get_dm_major(&major,DM_BLOCK_MAJOR);
+		
+	dml = (struct dm_name_list *)((uint8_t *)dmi + dmi->data_start);
+
+	if ((targets = prop_dictionary_get(dm_dict,DM_IOCTL_CMD_DATA))){
+
+		iter = prop_array_iterator(targets);
+		if (!iter)
+			err(EXIT_FAILURE,"dm_list_devices %s",__func__);
+
+		while((target_dict = prop_object_iterator_next(iter)) != NULL){
+
+			prop_dictionary_get_cstring_nocopy(target_dict,
+			    DM_DEV_NAME,(const char **)&name);
+
+			prop_dictionary_get_uint32(target_dict,DM_DEV_DEV,&minor);
+
+			dml->dev = MKDEV(major,minor);
+			
+			slen = strlen(name) + 1;
+			rec_size = sizeof(struct dm_name_list) + slen + 1;
+
+			if (rec_size > dmi->data_size)
+				return -ENOMEM;
+			
+			dml->next = rec_size;
+			
+			strlcpy(dml->name,name,slen);
+			
+			odml = dml;
+			
+			dml =(struct dm_name_list *)((uint8_t *)dml + rec_size);
+
+			j++;
+		}
+
+		if (odml != NULL)
+			odml->next = 0;
+	}
+	prop_object_iterator_release(iter);
+	return j;
+}
+
+/*
+ * Print status of each table, target arguments, start sector, 
+ * size and target name.
+ */
+static int
+dm_table_status(prop_dictionary_t dm_dict,struct dm_ioctl *dmi)
+{
+	struct dm_target_spec *dmts, *odmts;
+
+	prop_array_t targets;
+	prop_dictionary_t target_dict;
+	prop_object_iterator_t iter;
+
+	char *type,*params,*params_start;
+
+	bool prm;
+	size_t j,plen,rec_size,next;
+
+	j = 0;
+	next = 0;
+	params = NULL;
+	odmts = NULL;
+	rec_size = 0;
+	plen = -1;
+	prm = false;
+	
+	dmts = (struct dm_target_spec *)((uint8_t *)dmi + dmi->data_start);	
+		
+	if ((targets = prop_dictionary_get(dm_dict,DM_IOCTL_CMD_DATA))){
+
+		iter = prop_array_iterator(targets);
+		if (!iter)
+			err(EXIT_FAILURE,"dm_table_status %s",__func__);
+
+		while((target_dict = prop_object_iterator_next(iter)) != NULL){
+
+			prop_dictionary_get_cstring_nocopy(target_dict,
+			    DM_TABLE_TYPE,(const char **)&type);
+
+			prm = prop_dictionary_get_cstring_nocopy(target_dict,
+			    DM_TABLE_PARAMS,(const char **)&params);
+
+			prop_dictionary_get_uint64(target_dict,DM_TABLE_START,&dmts->sector_start);
+			prop_dictionary_get_uint64(target_dict,DM_TABLE_LENGTH,&dmts->length);
+			prop_dictionary_get_int32(target_dict,DM_TABLE_STAT,&dmts->status);
+
+			if (prm)
+				plen = strlen(params) + 1;
+
+			rec_size = sizeof(struct dm_target_spec) + plen;
+
+			/*
+			 * In linux when copying table status from kernel next is
+			 * number of bytes from the start of the first dm_target_spec
+			 * structure. I don't know why but, it has to be done this way.
+			 */
+			next += rec_size; 
+			
+			if (rec_size > dmi->data_size)
+				return -ENOMEM;
+
+			dmts->next = next;
+			
+			strlcpy(dmts->target_type, type, DM_MAX_TYPE_NAME);
+
+			params_start = (char *)dmts + sizeof(struct dm_target_spec);
+
+			if (prm) 
+				strlcpy(params_start, params, plen);
+			else
+				params_start = "\0";
+
+			
+			odmts = dmts;
+			
+			dmts = (struct dm_target_spec *)((uint8_t *)dmts + rec_size);
+
+			j++;
+			
+		}
+
+		if (odmts != NULL)
+			odmts->next = 0;
+	}			
+	prop_object_iterator_release(iter);
+
+	return j;
+}
+
+/*
+ * Print dm device dependiences, get minor/major number for 
+ * devices. From kernel I will receive major:minor number of 
+ * block device used with target. I have to translate it to 
+ * raw device numbers and use them, because all other parts of lvm2tools 
+ * uses raw devices internaly.
+ */
+static int
+dm_dev_deps(prop_dictionary_t dm_dict, struct dm_ioctl *dmi)
+{
+	struct dm_target_deps *dmtd;
+	struct kinfo_drivers *kd;
+	
+	prop_array_t targets;
+	prop_object_iterator_t iter;
+	
+	uint32_t major;
+	
+	size_t val_len, i, j;
+
+	uint64_t dev_tmp;
+
+	dev_tmp = 0;
+	j = 0;
+	i = 0;
+	
+	if (sysctlbyname("kern.drivers",NULL,&val_len,NULL,0) < 0) {
+		printf("sysctlbyname failed");
+		return 0;
+	}
+
+	if ((kd = malloc (val_len)) == NULL){
+		printf("malloc kd info error\n");
+		return 0;
+	}
+
+	if (sysctlbyname("kern.drivers", kd, &val_len, NULL, 0) < 0) {
+		printf("sysctlbyname failed kd");
+		return 0;
+	}
+	
+	dmtd = (struct dm_target_deps *)((uint8_t *)dmi + dmi->data_start);
+
+	if ((targets = prop_dictionary_get(dm_dict, DM_IOCTL_CMD_DATA))){
+
+		iter = prop_array_iterator(targets);
+		if (!iter)
+			err(EXIT_FAILURE,"dm_target_deps %s", __func__);
+
+		while((prop_object_iterator_next(iter)) != NULL){
+
+			prop_array_get_uint64(targets, j, &dev_tmp);
+			
+			for (i = 0, val_len /= sizeof(*kd); i < val_len; i++){
+				if (kd[i].d_bmajor == MAJOR(dev_tmp)) {
+					major = kd[i].d_cmajor;
+					break;
+				}
+			}
+			
+			dmtd->dev[j] = MKDEV(major,MINOR(dev_tmp));
+			
+			j++;
+		}
+	}	
+	
+	dmtd->count = j;
+
+	prop_object_iterator_release(iter);
+	
+	return j;
+}
Index: src/external/gpl2/lvm2tools/dist/libdm/misc/dm-ioctl.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/misc/dm-ioctl.h
diff -N src/external/gpl2/lvm2tools/dist/libdm/misc/dm-ioctl.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/misc/dm-ioctl.h	13 Dec 2008 14:39:36 -0000	1.1.1.1.2.2
@@ -0,0 +1,306 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001 - 2003 Sistina Software (UK) Limited.
+ * Copyright (C) 2004 - 2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is released under the LGPL.
+ */
+
+#ifndef _LINUX_DM_IOCTL_V4_H
+#define _LINUX_DM_IOCTL_V4_H
+
+#ifdef linux
+#  include <linux/types.h>
+#endif
+
+#define DM_DIR "mapper"		/* Slashes not supported */
+#define DM_MAX_TYPE_NAME 16
+#define DM_NAME_LEN 128
+#define DM_UUID_LEN 129
+
+/*
+ * A traditional ioctl interface for the device mapper.
+ *
+ * Each device can have two tables associated with it, an
+ * 'active' table which is the one currently used by io passing
+ * through the device, and an 'inactive' one which is a table
+ * that is being prepared as a replacement for the 'active' one.
+ *
+ * DM_VERSION:
+ * Just get the version information for the ioctl interface.
+ *
+ * DM_REMOVE_ALL:
+ * Remove all dm devices, destroy all tables.  Only really used
+ * for debug.
+ *
+ * DM_LIST_DEVICES:
+ * Get a list of all the dm device names.
+ *
+ * DM_DEV_CREATE:
+ * Create a new device, neither the 'active' or 'inactive' table
+ * slots will be filled.  The device will be in suspended state
+ * after creation, however any io to the device will get errored
+ * since it will be out-of-bounds.
+ *
+ * DM_DEV_REMOVE:
+ * Remove a device, destroy any tables.
+ *
+ * DM_DEV_RENAME:
+ * Rename a device.
+ *
+ * DM_SUSPEND:
+ * This performs both suspend and resume, depending which flag is
+ * passed in.
+ * Suspend: This command will not return until all pending io to
+ * the device has completed.  Further io will be deferred until
+ * the device is resumed.
+ * Resume: It is no longer an error to issue this command on an
+ * unsuspended device.  If a table is present in the 'inactive'
+ * slot, it will be moved to the active slot, then the old table
+ * from the active slot will be _destroyed_.  Finally the device
+ * is resumed.
+ *
+ * DM_DEV_STATUS:
+ * Retrieves the status for the table in the 'active' slot.
+ *
+ * DM_DEV_WAIT:
+ * Wait for a significant event to occur to the device.  This
+ * could either be caused by an event triggered by one of the
+ * targets of the table in the 'active' slot, or a table change.
+ *
+ * DM_TABLE_LOAD:
+ * Load a table into the 'inactive' slot for the device.  The
+ * device does _not_ need to be suspended prior to this command.
+ *
+ * DM_TABLE_CLEAR:
+ * Destroy any table in the 'inactive' slot (ie. abort).
+ *
+ * DM_TABLE_DEPS:
+ * Return a set of device dependencies for the 'active' table.
+ *
+ * DM_TABLE_STATUS:
+ * Return the targets status for the 'active' table.
+ *
+ * DM_TARGET_MSG:
+ * Pass a message string to the target at a specific offset of a device.
+ *
+ * DM_DEV_SET_GEOMETRY:
+ * Set the geometry of a device by passing in a string in this format:
+ *
+ * "cylinders heads sectors_per_track start_sector"
+ *
+ * Beware that CHS geometry is nearly obsolete and only provided
+ * for compatibility with dm devices that can be booted by a PC
+ * BIOS.  See struct hd_geometry for range limits.  Also note that
+ * the geometry is erased if the device size changes.
+ */
+
+/*
+ * All ioctl arguments consist of a single chunk of memory, with
+ * this structure at the start.  If a uuid is specified any
+ * lookup (eg. for a DM_INFO) will be done on that, *not* the
+ * name.
+ */
+struct dm_ioctl {
+	/*
+	 * The version number is made up of three parts:
+	 * major - no backward or forward compatibility,
+	 * minor - only backwards compatible,
+	 * patch - both backwards and forwards compatible.
+	 *
+	 * All clients of the ioctl interface should fill in the
+	 * version number of the interface that they were
+	 * compiled with.
+	 *
+	 * All recognised ioctl commands (ie. those that don't
+	 * return -ENOTTY) fill out this field, even if the
+	 * command failed.
+	 */
+	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 */
+
+	uint32_t target_count;	/* in/out */
+	int32_t open_count;	/* out */
+	uint32_t flags;		/* in/out */
+	uint32_t event_nr;      	/* in/out */
+	uint32_t padding;
+
+	uint64_t dev;		/* in/out */
+
+	char name[DM_NAME_LEN];	/* device name */
+	char uuid[DM_UUID_LEN];	/* unique identifier for
+				 * the block device */
+	char data[7];		/* padding or data */
+};
+
+/*
+ * Used to specify tables.  These structures appear after the
+ * dm_ioctl.
+ */
+struct dm_target_spec {
+	uint64_t sector_start;
+	uint64_t length;
+	int32_t status;		/* used when reading from kernel only */
+
+	/*
+	 * Location of the next dm_target_spec.
+	 * - When specifying targets on a DM_TABLE_LOAD command, this value is
+	 *   the number of bytes from the start of the "current" dm_target_spec
+	 *   to the start of the "next" dm_target_spec.
+	 * - When retrieving targets on a DM_TABLE_STATUS command, this value
+	 *   is the number of bytes from the start of the first dm_target_spec
+	 *   (that follows the dm_ioctl struct) to the start of the "next"
+	 *   dm_target_spec.
+	 */
+	uint32_t next;
+
+	char target_type[DM_MAX_TYPE_NAME];
+
+	/*
+	 * Parameter string starts immediately after this object.
+	 * Be careful to add padding after string to ensure correct
+	 * alignment of subsequent dm_target_spec.
+	 */
+};
+
+/*
+ * Used to retrieve the target dependencies.
+ */
+struct dm_target_deps {
+	uint32_t count;	/* Array size */
+	uint32_t padding;	/* unused */
+	uint64_t dev[0];	/* out */
+};
+
+/*
+ * Used to get a list of all dm devices.
+ */
+struct dm_name_list {
+	uint64_t dev;
+	uint32_t next;		/* offset to the next record from
+				   the _start_ of this */
+	char name[0];
+};
+
+/*
+ * Used to retrieve the target versions
+ */
+struct dm_target_versions {
+        uint32_t next;
+        uint32_t version[3];
+
+        char name[0];
+};
+
+/*
+ * Used to pass message to a target
+ */
+struct dm_target_msg {
+	uint64_t sector;	/* Device sector */
+
+	char message[0];
+};
+
+/*
+ * If you change this make sure you make the corresponding change
+ * to dm-ioctl.c:lookup_ioctl()
+ */
+enum {
+	/* Top level cmds */
+	DM_VERSION_CMD = 0,
+	DM_REMOVE_ALL_CMD,
+	DM_LIST_DEVICES_CMD,
+
+	/* device level cmds */
+	DM_DEV_CREATE_CMD,
+	DM_DEV_REMOVE_CMD,
+	DM_DEV_RENAME_CMD,
+	DM_DEV_SUSPEND_CMD,
+	DM_DEV_STATUS_CMD,
+	DM_DEV_WAIT_CMD,
+
+	/* Table level cmds */
+	DM_TABLE_LOAD_CMD,
+	DM_TABLE_CLEAR_CMD,
+	DM_TABLE_DEPS_CMD,
+	DM_TABLE_STATUS_CMD,
+
+	/* Added later */
+	DM_LIST_VERSIONS_CMD,
+	DM_TARGET_MSG_CMD,
+	DM_DEV_SET_GEOMETRY_CMD
+};
+
+#define DM_IOCTL 0xfd
+
+#define DM_VERSION       _IOWR(DM_IOCTL, DM_VERSION_CMD, struct dm_ioctl)
+#define DM_REMOVE_ALL    _IOWR(DM_IOCTL, DM_REMOVE_ALL_CMD, struct dm_ioctl)
+#define DM_LIST_DEVICES  _IOWR(DM_IOCTL, DM_LIST_DEVICES_CMD, struct dm_ioctl)
+
+#define DM_DEV_CREATE    _IOWR(DM_IOCTL, DM_DEV_CREATE_CMD, struct dm_ioctl)
+#define DM_DEV_REMOVE    _IOWR(DM_IOCTL, DM_DEV_REMOVE_CMD, struct dm_ioctl)
+#define DM_DEV_RENAME    _IOWR(DM_IOCTL, DM_DEV_RENAME_CMD, struct dm_ioctl)
+#define DM_DEV_SUSPEND   _IOWR(DM_IOCTL, DM_DEV_SUSPEND_CMD, struct dm_ioctl)
+#define DM_DEV_STATUS    _IOWR(DM_IOCTL, DM_DEV_STATUS_CMD, struct dm_ioctl)
+#define DM_DEV_WAIT      _IOWR(DM_IOCTL, DM_DEV_WAIT_CMD, struct dm_ioctl)
+
+#define DM_TABLE_LOAD    _IOWR(DM_IOCTL, DM_TABLE_LOAD_CMD, struct dm_ioctl)
+#define DM_TABLE_CLEAR   _IOWR(DM_IOCTL, DM_TABLE_CLEAR_CMD, struct dm_ioctl)
+#define DM_TABLE_DEPS    _IOWR(DM_IOCTL, DM_TABLE_DEPS_CMD, struct dm_ioctl)
+#define DM_TABLE_STATUS  _IOWR(DM_IOCTL, DM_TABLE_STATUS_CMD, struct dm_ioctl)
+
+#define DM_LIST_VERSIONS _IOWR(DM_IOCTL, DM_LIST_VERSIONS_CMD, struct dm_ioctl)
+
+#define DM_TARGET_MSG	 _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, struct dm_ioctl)
+#define DM_DEV_SET_GEOMETRY	_IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
+
+#define DM_VERSION_MAJOR	4
+#define DM_VERSION_MINOR	14
+#define DM_VERSION_PATCHLEVEL	0
+#define DM_VERSION_EXTRA	"-ioctl (2008-04-23)"
+
+/* Status bits */
+#define DM_READONLY_FLAG	(1 << 0) /* In/Out */
+#define DM_SUSPEND_FLAG		(1 << 1) /* In/Out */
+#define DM_PERSISTENT_DEV_FLAG	(1 << 3) /* In */
+
+/*
+ * Flag passed into ioctl STATUS command to get table information
+ * rather than current status.
+ */
+#define DM_STATUS_TABLE_FLAG	(1 << 4) /* In */
+
+/*
+ * Flags that indicate whether a table is present in either of
+ * the two table slots that a device has.
+ */
+#define DM_ACTIVE_PRESENT_FLAG   (1 << 5) /* Out */
+#define DM_INACTIVE_PRESENT_FLAG (1 << 6) /* Out */
+
+/*
+ * Indicates that the buffer passed in wasn't big enough for the
+ * results.
+ */
+#define DM_BUFFER_FULL_FLAG	(1 << 8) /* Out */
+
+/*
+ * This flag is now ignored.
+ */
+#define DM_SKIP_BDGET_FLAG	(1 << 9) /* In */
+
+/*
+ * Set this to avoid attempting to freeze any filesystem when suspending.
+ */
+#define DM_SKIP_LOCKFS_FLAG	(1 << 10) /* In */
+
+/*
+ * Set this to suspend without flushing queued ios.
+ */
+#define DM_NOFLUSH_FLAG		(1 << 11) /* In */
+
+#endif				/* _LINUX_DM_IOCTL_H */
Index: src/external/gpl2/lvm2tools/dist/libdm/misc/dm-logging.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/misc/dm-logging.h
diff -N src/external/gpl2/lvm2tools/dist/libdm/misc/dm-logging.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/misc/dm-logging.h	13 Dec 2008 14:39:36 -0000	1.1.1.1.2.2
@@ -0,0 +1,29 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _DM_LOGGING_H
+#define _DM_LOGGING_H
+
+#include "libdevmapper.h"
+
+extern dm_log_fn dm_log;
+
+#define plog(l, x...) dm_log(l, __FILE__, __LINE__, ## x)
+
+#include "log.h"
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/libdm/misc/dmlib.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/misc/dmlib.h
diff -N src/external/gpl2/lvm2tools/dist/libdm/misc/dmlib.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/misc/dmlib.h	13 Dec 2008 14:39:36 -0000	1.1.1.1.2.2
@@ -0,0 +1,28 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * This file must be included first by every device-mapper library source file.
+ */
+#ifndef _DM_LIB_H
+#define _DM_LIB_H
+
+#define DM
+
+#include "lib.h"
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/libdm/misc/kdev_t.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/misc/kdev_t.h
diff -N src/external/gpl2/lvm2tools/dist/libdm/misc/kdev_t.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/misc/kdev_t.h	13 Dec 2008 14:39:36 -0000	1.1.1.1.2.2
@@ -0,0 +1,24 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LIBDM_KDEV_H
+#define _LIBDM_KDEV_H
+
+#define MAJOR(dev)      ((dev & 0xfff00) >> 8)
+#define MINOR(dev)      ((dev & 0xff) | ((dev >> 12) & 0xfff00))
+#define MKDEV(ma,mi)    ((mi & 0xff) | (ma << 8) | ((mi & ~0xff) << 12))
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/libdm/mm/dbg_malloc.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/mm/dbg_malloc.c
diff -N src/external/gpl2/lvm2tools/dist/libdm/mm/dbg_malloc.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/mm/dbg_malloc.c	13 Dec 2008 14:39:36 -0000	1.1.1.1.2.2
@@ -0,0 +1,246 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "dmlib.h"
+
+#include <assert.h>
+#include <stdarg.h>
+
+char *dm_strdup_aux(const char *str, const char *file, int line)
+{
+	char *ret;
+
+	if (!str) {
+		log_error("Internal error: dm_strdup called with NULL pointer");
+		return NULL;
+	}
+
+	if ((ret = dm_malloc_aux_debug(strlen(str) + 1, file, line)))
+		strcpy(ret, str);
+
+	return ret;
+}
+
+struct memblock {
+	struct memblock *prev, *next;	/* All allocated blocks are linked */
+	size_t length;		/* Size of the requested block */
+	int id;			/* Index of the block */
+	const char *file;	/* File that allocated */
+	int line;		/* Line that allocated */
+	void *magic;		/* Address of this block */
+} __attribute__((aligned(8)));
+
+static struct {
+	unsigned block_serialno;/* Non-decreasing serialno of block */
+	unsigned blocks_allocated; /* Current number of blocks allocated */
+	unsigned blocks_max;	/* Max no of concurrently-allocated blocks */
+	unsigned int bytes, mbytes;
+
+} _mem_stats = {
+0, 0, 0, 0, 0};
+
+static struct memblock *_head = 0;
+static struct memblock *_tail = 0;
+
+void *dm_malloc_aux_debug(size_t s, const char *file, int line)
+{
+	struct memblock *nb;
+	size_t tsize = s + sizeof(*nb) + sizeof(unsigned long);
+
+	if (s > 50000000) {
+		log_error("Huge memory allocation (size %" PRIsize_t
+			  ") rejected - metadata corruption?", s);
+		return 0;
+	}
+
+	if (!(nb = malloc(tsize))) {
+		log_error("couldn't allocate any memory, size = %" PRIsize_t,
+			  s);
+		return 0;
+	}
+
+	/* set up the file and line info */
+	nb->file = file;
+	nb->line = line;
+
+	dm_bounds_check();
+
+	/* setup fields */
+	nb->magic = nb + 1;
+	nb->length = s;
+	nb->id = ++_mem_stats.block_serialno;
+	nb->next = 0;
+
+	/* stomp a pretty pattern across the new memory
+	   and fill in the boundary bytes */
+	{
+		char *ptr = (char *) (nb + 1);
+		size_t i;
+		for (i = 0; i < s; i++)
+			*ptr++ = i & 0x1 ? (char) 0xba : (char) 0xbe;
+
+		for (i = 0; i < sizeof(unsigned long); i++)
+			*ptr++ = (char) nb->id;
+	}
+
+	nb->prev = _tail;
+
+	/* link to tail of the list */
+	if (!_head)
+		_head = _tail = nb;
+	else {
+		_tail->next = nb;
+		_tail = nb;
+	}
+
+	_mem_stats.blocks_allocated++;
+	if (_mem_stats.blocks_allocated > _mem_stats.blocks_max)
+		_mem_stats.blocks_max = _mem_stats.blocks_allocated;
+
+	_mem_stats.bytes += s;
+	if (_mem_stats.bytes > _mem_stats.mbytes)
+		_mem_stats.mbytes = _mem_stats.bytes;
+
+	/* log_debug("Allocated: %u %u %u", nb->id, _mem_stats.blocks_allocated,
+		  _mem_stats.bytes); */
+
+	return nb + 1;
+}
+
+void dm_free_aux(void *p)
+{
+	char *ptr;
+	size_t i;
+	struct memblock *mb = ((struct memblock *) p) - 1;
+	if (!p)
+		return;
+
+	dm_bounds_check();
+
+	/* sanity check */
+	assert(mb->magic == p);
+
+	/* check data at the far boundary */
+	ptr = ((char *) mb) + sizeof(struct memblock) + mb->length;
+	for (i = 0; i < sizeof(unsigned long); i++)
+		if (*ptr++ != (char) mb->id)
+			assert(!"Damage at far end of block");
+
+	/* have we freed this before ? */
+	assert(mb->id != 0);
+
+	/* unlink */
+	if (mb->prev)
+		mb->prev->next = mb->next;
+	else
+		_head = mb->next;
+
+	if (mb->next)
+		mb->next->prev = mb->prev;
+	else
+		_tail = mb->prev;
+
+	mb->id = 0;
+
+	/* stomp a different pattern across the memory */
+	ptr = ((char *) mb) + sizeof(struct memblock);
+	for (i = 0; i < mb->length; i++)
+		*ptr++ = i & 1 ? (char) 0xde : (char) 0xad;
+
+	assert(_mem_stats.blocks_allocated);
+	_mem_stats.blocks_allocated--;
+	_mem_stats.bytes -= mb->length;
+
+	/* free the memory */
+	free(mb);
+}
+
+void *dm_realloc_aux(void *p, unsigned int s, const char *file, int line)
+{
+	void *r;
+	struct memblock *mb = ((struct memblock *) p) - 1;
+
+	r = dm_malloc_aux_debug(s, file, line);
+
+	if (p) {
+		memcpy(r, p, mb->length);
+		dm_free_aux(p);
+	}
+
+	return r;
+}
+
+int dm_dump_memory_debug(void)
+{
+	unsigned long tot = 0;
+	struct memblock *mb;
+	char str[32];
+	size_t c;
+
+	if (_head)
+		log_very_verbose("You have a memory leak:");
+
+	for (mb = _head; mb; mb = mb->next) {
+		for (c = 0; c < sizeof(str) - 1; c++) {
+			if (c >= mb->length)
+				str[c] = ' ';
+			else if (*(char *)(mb->magic + c) == '\0')
+				str[c] = '\0';
+			else if (*(char *)(mb->magic + c) < ' ')
+				str[c] = '?';
+			else
+				str[c] = *(char *)(mb->magic + c);
+		}
+		str[sizeof(str) - 1] = '\0';
+
+		dm_log(_LOG_INFO, mb->file, mb->line,
+		       "block %d at %p, size %" PRIsize_t "\t [%s]",
+		       mb->id, mb->magic, mb->length, str);
+		tot += mb->length;
+	}
+
+	if (_head)
+		log_very_verbose("%ld bytes leaked in total", tot);
+
+	return 1;
+}
+
+void dm_bounds_check_debug(void)
+{
+	struct memblock *mb = _head;
+	while (mb) {
+		size_t i;
+		char *ptr = ((char *) (mb + 1)) + mb->length;
+		for (i = 0; i < sizeof(unsigned long); i++)
+			if (*ptr++ != (char) mb->id)
+				assert(!"Memory smash");
+
+		mb = mb->next;
+	}
+}
+
+void *dm_malloc_aux(size_t s, const char *file __attribute((unused)),
+		    int line __attribute((unused)))
+{
+	if (s > 50000000) {
+		log_error("Huge memory allocation (size %" PRIsize_t
+			  ") rejected - metadata corruption?", s);
+		return 0;
+	}
+
+	return malloc(s);
+}
Index: src/external/gpl2/lvm2tools/dist/libdm/mm/dbg_malloc.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/mm/dbg_malloc.h
diff -N src/external/gpl2/lvm2tools/dist/libdm/mm/dbg_malloc.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/mm/dbg_malloc.h	13 Dec 2008 14:39:36 -0000	1.1.1.1.2.2
@@ -0,0 +1,48 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _DM_DBG_MALLOC_H
+#define _DM_DBG_MALLOC_H
+
+#include <stdlib.h>
+#include <string.h>
+
+void *malloc_aux(size_t s, const char *file, int line);
+#define dm_malloc(s) malloc_aux((s), __FILE__, __LINE__)
+
+char *dbg_strdup(const char *str);
+
+#ifdef DEBUG_MEM
+
+void free_aux(void *p);
+void *realloc_aux(void *p, unsigned int s, const char *file, int line);
+int dump_memory(void);
+void bounds_check(void);
+
+#  define dm_free(p) free_aux(p)
+#  define dbg_realloc(p, s) realloc_aux(p, s, __FILE__, __LINE__)
+
+#else
+
+#  define dm_free(p) do {if (p) free(p); } while (0)
+#  define dbg_realloc(p, s) realloc(p, s)
+#  define dump_memory()
+#  define bounds_check()
+
+#endif
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/libdm/mm/pool-debug.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/mm/pool-debug.c
diff -N src/external/gpl2/lvm2tools/dist/libdm/mm/pool-debug.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/mm/pool-debug.c	13 Dec 2008 14:39:36 -0000	1.1.1.1.2.2
@@ -0,0 +1,264 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "dmlib.h"
+
+struct block {
+	struct block *next;
+	size_t size;
+	void *data;
+};
+
+typedef struct {
+	unsigned block_serialno;	/* Non-decreasing serialno of block */
+	unsigned blocks_allocated;	/* Current number of blocks allocated */
+	unsigned blocks_max;	/* Max no of concurrently-allocated blocks */
+	unsigned int bytes, maxbytes;
+} pool_stats;
+
+struct dm_pool {
+	const char *name;
+
+	int begun;
+	struct block *object;
+
+	struct block *blocks;
+	struct block *tail;
+
+	pool_stats stats;
+};
+
+/* by default things come out aligned for doubles */
+#define DEFAULT_ALIGNMENT __alignof__ (double)
+
+struct pool *dm_pool_create(const char *name, size_t chunk_hint)
+{
+	struct dm_pool *mem = dm_malloc(sizeof(*mem));
+
+	if (!mem) {
+		log_error("Couldn't create memory pool %s (size %"
+			  PRIsize_t ")", name, sizeof(*mem));
+		return NULL;
+	}
+
+	mem->name = name;
+	mem->begun = 0;
+	mem->object = 0;
+	mem->blocks = mem->tail = NULL;
+
+	mem->stats.block_serialno = 0;
+	mem->stats.blocks_allocated = 0;
+	mem->stats.blocks_max = 0;
+	mem->stats.bytes = 0;
+	mem->stats.maxbytes = 0;
+
+#ifdef DEBUG_POOL
+	log_debug("Created mempool %s", name);
+#endif
+
+	return mem;
+}
+
+static void _free_blocks(struct dm_pool *p, struct block *b)
+{
+	struct block *n;
+
+	while (b) {
+		p->stats.bytes -= b->size;
+		p->stats.blocks_allocated--;
+
+		n = b->next;
+		dm_free(b->data);
+		dm_free(b);
+		b = n;
+	}
+}
+
+static void _pool_stats(struct dm_pool *p, const char *action)
+{
+#ifdef DEBUG_POOL
+	log_debug("%s mempool %s: %u/%u bytes, %u/%u blocks, "
+		  "%u allocations)", action, p->name, p->stats.bytes,
+		  p->stats.maxbytes, p->stats.blocks_allocated,
+		  p->stats.blocks_max, p->stats.block_serialno);
+#else
+	;
+#endif
+}
+
+void dm_pool_destroy(struct dm_pool *p)
+{
+	_pool_stats(p, "Destroying");
+	_free_blocks(p, p->blocks);
+	dm_free(p);
+}
+
+void *dm_pool_alloc(struct dm_pool *p, size_t s)
+{
+	return dm_pool_alloc_aligned(p, s, DEFAULT_ALIGNMENT);
+}
+
+static void _append_block(struct dm_pool *p, struct block *b)
+{
+	if (p->tail) {
+		p->tail->next = b;
+		p->tail = b;
+	} else
+		p->blocks = p->tail = b;
+
+	p->stats.block_serialno++;
+	p->stats.blocks_allocated++;
+	if (p->stats.blocks_allocated > p->stats.blocks_max)
+		p->stats.blocks_max = p->stats.blocks_allocated;
+
+	p->stats.bytes += b->size;
+	if (p->stats.bytes > p->stats.maxbytes)
+		p->stats.maxbytes = p->stats.bytes;
+}
+
+static struct block *_new_block(size_t s, unsigned alignment)
+{
+	static const char *_oom = "Out of memory";
+
+	/* FIXME: I'm currently ignoring the alignment arg. */
+	size_t len = sizeof(struct block) + s;
+	struct block *b = dm_malloc(len);
+
+	/*
+	 * Too lazy to implement alignment for debug version, and
+	 * I don't think LVM will use anything but default
+	 * align.
+	 */
+	assert(alignment == DEFAULT_ALIGNMENT);
+
+	if (!b) {
+		log_err(_oom);
+		return NULL;
+	}
+
+	if (!(b->data = dm_malloc(s))) {
+		log_err(_oom);
+		dm_free(b);
+		return NULL;
+	}
+
+	b->next = NULL;
+	b->size = s;
+
+	return b;
+}
+
+void *dm_pool_alloc_aligned(struct dm_pool *p, size_t s, unsigned alignment)
+{
+	struct block *b = _new_block(s, alignment);
+
+	if (!b)
+		return NULL;
+
+	_append_block(p, b);
+
+	return b->data;
+}
+
+void dm_pool_empty(struct dm_pool *p)
+{
+	_pool_stats(p, "Emptying");
+	_free_blocks(p, p->blocks);
+	p->blocks = p->tail = NULL;
+}
+
+void dm_pool_free(struct dm_pool *p, void *ptr)
+{
+	struct block *b, *prev = NULL;
+
+	_pool_stats(p, "Freeing (before)");
+
+	for (b = p->blocks; b; b = b->next) {
+		if (b->data == ptr)
+			break;
+		prev = b;
+	}
+
+	/*
+	 * If this fires then you tried to free a
+	 * pointer that either wasn't from this
+	 * pool, or isn't the start of a block.
+	 */
+	assert(b);
+
+	_free_blocks(p, b);
+
+	if (prev) {
+		p->tail = prev;
+		prev->next = NULL;
+	} else
+		p->blocks = p->tail = NULL;
+
+	_pool_stats(p, "Freeing (after)");
+}
+
+int dm_pool_begin_object(struct dm_pool *p, size_t init_size)
+{
+	assert(!p->begun);
+	p->begun = 1;
+	return 1;
+}
+
+int dm_pool_grow_object(struct dm_pool *p, const void *extra, size_t delta)
+{
+	struct block *new;
+	size_t size = delta ? : strlen(extra);
+
+	assert(p->begun);
+
+	if (p->object)
+		size += p->object->size;
+
+	if (!(new = _new_block(size, DEFAULT_ALIGNMENT))) {
+		log_err("Couldn't extend object.");
+		return 0;
+	}
+
+	if (p->object) {
+		memcpy(new->data, p->object->data, p->object->size);
+		dm_free(p->object->data);
+		dm_free(p->object);
+	}
+	p->object = new;
+
+	memcpy(new->data + size - delta, extra, delta);
+
+	return 1;
+}
+
+void *dm_pool_end_object(struct dm_pool *p)
+{
+	assert(p->begun);
+	_append_block(p, p->object);
+
+	p->begun = 0;
+	p->object = NULL;
+	return p->tail->data;
+}
+
+void dm_pool_abandon_object(struct dm_pool *p)
+{
+	assert(p->begun);
+	dm_free(p->object);
+	p->begun = 0;
+	p->object = NULL;
+}
Index: src/external/gpl2/lvm2tools/dist/libdm/mm/pool-fast.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/mm/pool-fast.c
diff -N src/external/gpl2/lvm2tools/dist/libdm/mm/pool-fast.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/mm/pool-fast.c	13 Dec 2008 14:39:36 -0000	1.1.1.1.2.2
@@ -0,0 +1,239 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.   
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "dmlib.h"
+
+struct chunk {
+	char *begin, *end;
+	struct chunk *prev;
+};
+
+struct dm_pool {
+	struct chunk *chunk, *spare_chunk;	/* spare_chunk is a one entry free
+						   list to stop 'bobbling' */
+	size_t chunk_size;
+	size_t object_len;
+	unsigned object_alignment;
+};
+
+void _align_chunk(struct chunk *c, unsigned alignment);
+struct chunk *_new_chunk(struct dm_pool *p, size_t s);
+
+/* by default things come out aligned for doubles */
+#define DEFAULT_ALIGNMENT __alignof__ (double)
+
+struct dm_pool *dm_pool_create(const char *name, size_t chunk_hint)
+{
+	size_t new_size = 1024;
+	struct dm_pool *p = dm_malloc(sizeof(*p));
+
+	if (!p) {
+		log_error("Couldn't create memory pool %s (size %"
+			  PRIsize_t ")", name, sizeof(*p));
+		return 0;
+	}
+	memset(p, 0, sizeof(*p));
+
+	/* round chunk_hint up to the next power of 2 */
+	p->chunk_size = chunk_hint + sizeof(struct chunk);
+	while (new_size < p->chunk_size)
+		new_size <<= 1;
+	p->chunk_size = new_size;
+	return p;
+}
+
+void dm_pool_destroy(struct dm_pool *p)
+{
+	struct chunk *c, *pr;
+	dm_free(p->spare_chunk);
+	c = p->chunk;
+	while (c) {
+		pr = c->prev;
+		dm_free(c);
+		c = pr;
+	}
+
+	dm_free(p);
+}
+
+void *dm_pool_alloc(struct dm_pool *p, size_t s)
+{
+	return dm_pool_alloc_aligned(p, s, DEFAULT_ALIGNMENT);
+}
+
+void *dm_pool_alloc_aligned(struct dm_pool *p, size_t s, unsigned alignment)
+{
+	struct chunk *c = p->chunk;
+	void *r;
+
+	/* realign begin */
+	if (c)
+		_align_chunk(c, alignment);
+
+	/* have we got room ? */
+	if (!c || (c->begin > c->end) || (c->end - c->begin < s)) {
+		/* allocate new chunk */
+		size_t needed = s + alignment + sizeof(struct chunk);
+		c = _new_chunk(p, (needed > p->chunk_size) ?
+			       needed : p->chunk_size);
+
+		if (!c)
+			return NULL;
+
+		_align_chunk(c, alignment);
+	}
+
+	r = c->begin;
+	c->begin += s;
+	return r;
+}
+
+void dm_pool_empty(struct dm_pool *p)
+{
+	struct chunk *c;
+
+	for (c = p->chunk; c && c->prev; c = c->prev)
+		;
+
+	if (c)
+		dm_pool_free(p, (char *) (c + 1));
+}
+
+void dm_pool_free(struct dm_pool *p, void *ptr)
+{
+	struct chunk *c = p->chunk;
+
+	while (c) {
+		if (((char *) c < (char *) ptr) &&
+		    ((char *) c->end > (char *) ptr)) {
+			c->begin = ptr;
+			break;
+		}
+
+		if (p->spare_chunk)
+			dm_free(p->spare_chunk);
+		p->spare_chunk = c;
+		c = c->prev;
+	}
+
+	if (!c)
+		log_error("Internal error: pool_free asked to free pointer "
+			  "not in pool");
+	else
+		p->chunk = c;
+}
+
+int dm_pool_begin_object(struct dm_pool *p, size_t hint)
+{
+	struct chunk *c = p->chunk;
+	const size_t align = DEFAULT_ALIGNMENT;
+
+	p->object_len = 0;
+	p->object_alignment = align;
+
+	if (c)
+		_align_chunk(c, align);
+
+	if (!c || (c->begin > c->end) || (c->end - c->begin < hint)) {
+		/* allocate a new chunk */
+		c = _new_chunk(p,
+			       hint > (p->chunk_size - sizeof(struct chunk)) ?
+			       hint + sizeof(struct chunk) + align :
+			       p->chunk_size);
+
+		if (!c)
+			return 0;
+
+		_align_chunk(c, align);
+	}
+
+	return 1;
+}
+
+int dm_pool_grow_object(struct dm_pool *p, const void *extra, size_t delta)
+{
+	struct chunk *c = p->chunk, *nc;
+
+	if (!delta)
+		delta = strlen(extra);
+
+	if (c->end - (c->begin + p->object_len) < delta) {
+		/* move into a new chunk */
+		if (p->object_len + delta > (p->chunk_size / 2))
+			nc = _new_chunk(p, (p->object_len + delta) * 2);
+		else
+			nc = _new_chunk(p, p->chunk_size);
+
+		if (!nc)
+			return 0;
+
+		_align_chunk(p->chunk, p->object_alignment);
+		memcpy(p->chunk->begin, c->begin, p->object_len);
+		c = p->chunk;
+	}
+
+	memcpy(c->begin + p->object_len, extra, delta);
+	p->object_len += delta;
+	return 1;
+}
+
+void *dm_pool_end_object(struct dm_pool *p)
+{
+	struct chunk *c = p->chunk;
+	void *r = c->begin;
+	c->begin += p->object_len;
+	p->object_len = 0u;
+	p->object_alignment = DEFAULT_ALIGNMENT;
+	return r;
+}
+
+void dm_pool_abandon_object(struct dm_pool *p)
+{
+	p->object_len = 0;
+	p->object_alignment = DEFAULT_ALIGNMENT;
+}
+
+void _align_chunk(struct chunk *c, unsigned alignment)
+{
+	c->begin += alignment - ((unsigned long) c->begin & (alignment - 1));
+}
+
+struct chunk *_new_chunk(struct dm_pool *p, size_t s)
+{
+	struct chunk *c;
+
+	if (p->spare_chunk &&
+	    ((p->spare_chunk->end - (char *) p->spare_chunk) >= s)) {
+		/* reuse old chunk */
+		c = p->spare_chunk;
+		p->spare_chunk = 0;
+	} else {
+		if (!(c = dm_malloc(s))) {
+			log_error("Out of memory.  Requested %" PRIsize_t
+				  " bytes.", s);
+			return NULL;
+		}
+
+		c->end = (char *) c + s;
+	}
+
+	c->prev = p->chunk;
+	c->begin = (char *) (c + 1);
+	p->chunk = c;
+
+	return c;
+}
Index: src/external/gpl2/lvm2tools/dist/libdm/mm/pool.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/mm/pool.c
diff -N src/external/gpl2/lvm2tools/dist/libdm/mm/pool.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/mm/pool.c	13 Dec 2008 14:39:36 -0000	1.1.1.1.2.2
@@ -0,0 +1,56 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "dmlib.h"
+
+#ifdef DEBUG_POOL
+#include "pool-debug.c"
+#else
+#include "pool-fast.c"
+#endif
+
+char *dm_pool_strdup(struct dm_pool *p, const char *str)
+{
+	char *ret = dm_pool_alloc(p, strlen(str) + 1);
+
+	if (ret)
+		strcpy(ret, str);
+
+	return ret;
+}
+
+char *dm_pool_strndup(struct dm_pool *p, const char *str, size_t n)
+{
+	char *ret = dm_pool_alloc(p, n + 1);
+
+	if (ret) {
+		strncpy(ret, str, n);
+		ret[n] = '\0';
+	}
+
+	return ret;
+}
+
+void *dm_pool_zalloc(struct dm_pool *p, size_t s)
+{
+	void *ptr = dm_pool_alloc(p, s);
+
+	if (ptr)
+		memset(ptr, 0, s);
+
+	return ptr;
+}
Index: src/external/gpl2/lvm2tools/dist/libdm/mm/pool.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/mm/pool.h
diff -N src/external/gpl2/lvm2tools/dist/libdm/mm/pool.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/mm/pool.h	13 Dec 2008 14:39:36 -0000	1.1.1.1.2.2
@@ -0,0 +1,123 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _DM_POOL_H
+#define _DM_POOL_H
+
+#include <string.h>
+#include <stdlib.h>
+
+/*
+ * The pool allocator is useful when you are going to allocate
+ * lots of memory, use the memory for a bit, and then free the
+ * memory in one go.  A surprising amount of code has this usage
+ * profile.
+ *
+ * You should think of the pool as an infinite, contiguous chunk
+ * of memory.  The front of this chunk of memory contains
+ * allocated objects, the second half is free.  pool_alloc grabs
+ * the next 'size' bytes from the free half, in effect moving it
+ * into the allocated half.  This operation is very efficient.
+ *
+ * pool_free frees the allocated object *and* all objects
+ * allocated after it.  It is important to note this semantic
+ * difference from malloc/free.  This is also extremely
+ * efficient, since a single pool_free can dispose of a large
+ * complex object.
+ *
+ * pool_destroy frees all allocated memory.
+ *
+ * eg, If you are building a binary tree in your program, and
+ * know that you are only ever going to insert into your tree,
+ * and not delete (eg, maintaining a symbol table for a
+ * compiler).  You can create yourself a pool, allocate the nodes
+ * from it, and when the tree becomes redundant call pool_destroy
+ * (no nasty iterating through the tree to free nodes).
+ *
+ * eg, On the other hand if you wanted to repeatedly insert and
+ * remove objects into the tree, you would be better off
+ * allocating the nodes from a free list; you cannot free a
+ * single arbitrary node with pool.
+ */
+
+struct pool;
+
+/* constructor and destructor */
+struct pool *pool_create(const char *name, size_t chunk_hint);
+void pool_destroy(struct pool *p);
+
+/* simple allocation/free routines */
+void *pool_alloc(struct pool *p, size_t s);
+void *pool_alloc_aligned(struct pool *p, size_t s, unsigned alignment);
+void pool_empty(struct pool *p);
+void pool_free(struct pool *p, void *ptr);
+
+/*
+ * Object building routines:
+ *
+ * These allow you to 'grow' an object, useful for
+ * building strings, or filling in dynamic
+ * arrays.
+ *
+ * It's probably best explained with an example:
+ *
+ * char *build_string(struct pool *mem)
+ * {
+ *      int i;
+ *      char buffer[16];
+ *
+ *      if (!pool_begin_object(mem, 128))
+ *              return NULL;
+ *
+ *      for (i = 0; i < 50; i++) {
+ *              snprintf(buffer, sizeof(buffer), "%d, ", i);
+ *              if (!pool_grow_object(mem, buffer, strlen(buffer)))
+ *                      goto bad;
+ *      }
+ *
+ *	// add null
+ *      if (!pool_grow_object(mem, "\0", 1))
+ *              goto bad;
+ *
+ *      return pool_end_object(mem);
+ *
+ * bad:
+ *
+ *      pool_abandon_object(mem);
+ *      return NULL;
+ *}
+ *
+ * So start an object by calling pool_begin_object
+ * with a guess at the final object size - if in
+ * doubt make the guess too small.
+ *
+ * Then append chunks of data to your object with
+ * pool_grow_object.  Finally get your object with
+ * a call to pool_end_object.
+ *
+ */
+int pool_begin_object(struct pool *p, size_t hint);
+int pool_grow_object(struct pool *p, const void *extra, size_t delta);
+void *pool_end_object(struct pool *p);
+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);
+void *pool_zalloc(struct pool *p, size_t s);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/libdm/regex/matcher.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/regex/matcher.c
diff -N src/external/gpl2/lvm2tools/dist/libdm/regex/matcher.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/regex/matcher.c	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,360 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "dmlib.h"
+#include "parse_rx.h"
+#include "ttree.h"
+#include "assert.h"
+
+struct dfa_state {
+	int final;
+	struct dfa_state *lookup[256];
+};
+
+struct state_queue {
+	struct dfa_state *s;
+	dm_bitset_t bits;
+	struct state_queue *next;
+};
+
+struct dm_regex {		/* Instance variables for the lexer */
+	struct dfa_state *start;
+	unsigned num_nodes;
+	int nodes_entered;
+	struct rx_node **nodes;
+	struct dm_pool *scratch, *mem;
+};
+
+#define TARGET_TRANS '\0'
+
+static int _count_nodes(struct rx_node *rx)
+{
+	int r = 1;
+
+	if (rx->left)
+		r += _count_nodes(rx->left);
+
+	if (rx->right)
+		r += _count_nodes(rx->right);
+
+	return r;
+}
+
+static void _fill_table(struct dm_regex *m, struct rx_node *rx)
+{
+	assert((rx->type != OR) || (rx->left && rx->right));
+
+	if (rx->left)
+		_fill_table(m, rx->left);
+
+	if (rx->right)
+		_fill_table(m, rx->right);
+
+	m->nodes[m->nodes_entered++] = rx;
+}
+
+static void _create_bitsets(struct dm_regex *m)
+{
+	int i;
+
+	for (i = 0; i < m->num_nodes; i++) {
+		struct rx_node *n = m->nodes[i];
+		n->firstpos = dm_bitset_create(m->scratch, m->num_nodes);
+		n->lastpos = dm_bitset_create(m->scratch, m->num_nodes);
+		n->followpos = dm_bitset_create(m->scratch, m->num_nodes);
+	}
+}
+
+static void _calc_functions(struct dm_regex *m)
+{
+	int i, j, final = 1;
+	struct rx_node *rx, *c1, *c2;
+
+	for (i = 0; i < m->num_nodes; i++) {
+		rx = m->nodes[i];
+		c1 = rx->left;
+		c2 = rx->right;
+
+		if (dm_bit(rx->charset, TARGET_TRANS))
+			rx->final = final++;
+
+		switch (rx->type) {
+		case CAT:
+			if (c1->nullable)
+				dm_bit_union(rx->firstpos,
+					  c1->firstpos, c2->firstpos);
+			else
+				dm_bit_copy(rx->firstpos, c1->firstpos);
+
+			if (c2->nullable)
+				dm_bit_union(rx->lastpos,
+					  c1->lastpos, c2->lastpos);
+			else
+				dm_bit_copy(rx->lastpos, c2->lastpos);
+
+			rx->nullable = c1->nullable && c2->nullable;
+			break;
+
+		case PLUS:
+			dm_bit_copy(rx->firstpos, c1->firstpos);
+			dm_bit_copy(rx->lastpos, c1->lastpos);
+			rx->nullable = c1->nullable;
+			break;
+
+		case OR:
+			dm_bit_union(rx->firstpos, c1->firstpos, c2->firstpos);
+			dm_bit_union(rx->lastpos, c1->lastpos, c2->lastpos);
+			rx->nullable = c1->nullable || c2->nullable;
+			break;
+
+		case QUEST:
+		case STAR:
+			dm_bit_copy(rx->firstpos, c1->firstpos);
+			dm_bit_copy(rx->lastpos, c1->lastpos);
+			rx->nullable = 1;
+			break;
+
+		case CHARSET:
+			dm_bit_set(rx->firstpos, i);
+			dm_bit_set(rx->lastpos, i);
+			rx->nullable = 0;
+			break;
+
+		default:
+			log_error("Internal error: Unknown calc node type");
+		}
+
+		/*
+		 * followpos has it's own switch
+		 * because PLUS and STAR do the
+		 * same thing.
+		 */
+		switch (rx->type) {
+		case CAT:
+			for (j = 0; j < m->num_nodes; j++) {
+				if (dm_bit(c1->lastpos, j)) {
+					struct rx_node *n = m->nodes[j];
+					dm_bit_union(n->followpos,
+						  n->followpos, c2->firstpos);
+				}
+			}
+			break;
+
+		case PLUS:
+		case STAR:
+			for (j = 0; j < m->num_nodes; j++) {
+				if (dm_bit(rx->lastpos, j)) {
+					struct rx_node *n = m->nodes[j];
+					dm_bit_union(n->followpos,
+						  n->followpos, rx->firstpos);
+				}
+			}
+			break;
+		}
+	}
+}
+
+static struct dfa_state *_create_dfa_state(struct dm_pool *mem)
+{
+	return dm_pool_zalloc(mem, sizeof(struct dfa_state));
+}
+
+static struct state_queue *_create_state_queue(struct dm_pool *mem,
+					       struct dfa_state *dfa,
+					       dm_bitset_t bits)
+{
+	struct state_queue *r = dm_pool_alloc(mem, sizeof(*r));
+
+	if (!r) {
+		stack;
+		return NULL;
+	}
+
+	r->s = dfa;
+	r->bits = dm_bitset_create(mem, bits[0]);	/* first element is the size */
+	dm_bit_copy(r->bits, bits);
+	r->next = 0;
+	return r;
+}
+
+static int _calc_states(struct dm_regex *m, struct rx_node *rx)
+{
+	unsigned iwidth = (m->num_nodes / DM_BITS_PER_INT) + 1;
+	struct ttree *tt = ttree_create(m->scratch, iwidth);
+	struct state_queue *h, *t, *tmp;
+	struct dfa_state *dfa, *ldfa;
+	int i, a, set_bits = 0, count = 0;
+	dm_bitset_t bs, dfa_bits;
+
+	if (!tt)
+		return_0;
+
+	if (!(bs = dm_bitset_create(m->scratch, m->num_nodes)))
+		return_0;
+
+	/* create first state */
+	dfa = _create_dfa_state(m->mem);
+	m->start = dfa;
+	ttree_insert(tt, rx->firstpos + 1, dfa);
+
+	/* prime the queue */
+	h = t = _create_state_queue(m->scratch, dfa, rx->firstpos);
+	while (h) {
+		/* pop state off front of the queue */
+		dfa = h->s;
+		dfa_bits = h->bits;
+		h = h->next;
+
+		/* iterate through all the inputs for this state */
+		dm_bit_clear_all(bs);
+		for (a = 0; a < 256; a++) {
+			/* iterate through all the states in firstpos */
+			for (i = dm_bit_get_first(dfa_bits);
+			     i >= 0; i = dm_bit_get_next(dfa_bits, i)) {
+				if (dm_bit(m->nodes[i]->charset, a)) {
+					if (a == TARGET_TRANS)
+						dfa->final = m->nodes[i]->final;
+
+					dm_bit_union(bs, bs,
+						  m->nodes[i]->followpos);
+					set_bits = 1;
+				}
+			}
+
+			if (set_bits) {
+				ldfa = ttree_lookup(tt, bs + 1);
+				if (!ldfa) {
+					/* push */
+					ldfa = _create_dfa_state(m->mem);
+					ttree_insert(tt, bs + 1, ldfa);
+					tmp =
+					    _create_state_queue(m->scratch,
+								ldfa, bs);
+					if (!h)
+						h = t = tmp;
+					else {
+						t->next = tmp;
+						t = tmp;
+					}
+
+					count++;
+				}
+
+				dfa->lookup[a] = ldfa;
+				set_bits = 0;
+				dm_bit_clear_all(bs);
+			}
+		}
+	}
+
+	log_debug("Matcher built with %d dfa states", count);
+	return 1;
+}
+
+struct dm_regex *dm_regex_create(struct dm_pool *mem, const char **patterns,
+				 unsigned num_patterns)
+{
+	char *all, *ptr;
+	int i;
+	size_t len = 0;
+	struct rx_node *rx;
+	struct dm_pool *scratch = dm_pool_create("regex matcher", 10 * 1024);
+	struct dm_regex *m;
+
+	if (!scratch)
+		return_NULL;
+
+	if (!(m = dm_pool_alloc(mem, sizeof(*m)))) {
+		dm_pool_destroy(scratch);
+		return_NULL;
+	}
+
+	memset(m, 0, sizeof(*m));
+
+	/* join the regexps together, delimiting with zero */
+	for (i = 0; i < num_patterns; i++)
+		len += strlen(patterns[i]) + 8;
+
+	ptr = all = dm_pool_alloc(scratch, len + 1);
+
+	if (!all)
+		goto_bad;
+
+	for (i = 0; i < num_patterns; i++) {
+		ptr += sprintf(ptr, "(.*(%s)%c)", patterns[i], TARGET_TRANS);
+		if (i < (num_patterns - 1))
+			*ptr++ = '|';
+	}
+
+	/* parse this expression */
+	if (!(rx = rx_parse_tok(scratch, all, ptr))) {
+		log_error("Couldn't parse regex");
+		goto bad;
+	}
+
+	m->mem = mem;
+	m->scratch = scratch;
+	m->num_nodes = _count_nodes(rx);
+	m->nodes = dm_pool_alloc(scratch, sizeof(*m->nodes) * m->num_nodes);
+
+	if (!m->nodes)
+		goto_bad;
+
+	_fill_table(m, rx);
+	_create_bitsets(m);
+	_calc_functions(m);
+	_calc_states(m, rx);
+	dm_pool_destroy(scratch);
+	m->scratch = NULL;
+
+	return m;
+
+      bad:
+	dm_pool_destroy(scratch);
+	dm_pool_free(mem, m);
+	return NULL;
+}
+
+static struct dfa_state *_step_matcher(int c, struct dfa_state *cs, int *r)
+{
+	if (!(cs = cs->lookup[(unsigned char) c]))
+		return NULL;
+
+	if (cs->final && (cs->final > *r))
+		*r = cs->final;
+
+	return cs;
+}
+
+int dm_regex_match(struct dm_regex *regex, const char *s)
+{
+	struct dfa_state *cs = regex->start;
+	int r = 0;
+
+	if (!(cs = _step_matcher(HAT_CHAR, cs, &r)))
+		goto out;
+
+	for (; *s; s++)
+		if (!(cs = _step_matcher(*s, cs, &r)))
+			goto out;
+
+	_step_matcher(DOLLAR_CHAR, cs, &r);
+
+      out:
+	/* subtract 1 to get back to zero index */
+	return r - 1;
+}
Index: src/external/gpl2/lvm2tools/dist/libdm/regex/parse_rx.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/regex/parse_rx.c
diff -N src/external/gpl2/lvm2tools/dist/libdm/regex/parse_rx.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/regex/parse_rx.c	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,362 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "dmlib.h"
+#include "parse_rx.h"
+
+struct parse_sp {		/* scratch pad for the parsing process */
+	struct dm_pool *mem;
+	int type;		/* token type, 0 indicates a charset */
+	dm_bitset_t charset;	/* The current charset */
+	const char *cursor;	/* where we are in the regex */
+	const char *rx_end;	/* 1pte for the expression being parsed */
+};
+
+static struct rx_node *_or_term(struct parse_sp *ps);
+
+static void _single_char(struct parse_sp *ps, unsigned int c, const char *ptr)
+{
+	ps->type = 0;
+	ps->cursor = ptr + 1;
+	dm_bit_clear_all(ps->charset);
+	dm_bit_set(ps->charset, c);
+}
+
+/*
+ * Get the next token from the regular expression.
+ * Returns: 1 success, 0 end of input, -1 error.
+ */
+static int _rx_get_token(struct parse_sp *ps)
+{
+	int neg = 0, range = 0;
+	char c, lc = 0;
+	const char *ptr = ps->cursor;
+	if (ptr == ps->rx_end) {	/* end of input ? */
+		ps->type = -1;
+		return 0;
+	}
+
+	switch (*ptr) {
+		/* charsets and ncharsets */
+	case '[':
+		ptr++;
+		if (*ptr == '^') {
+			dm_bit_set_all(ps->charset);
+
+			/* never transition on zero */
+			dm_bit_clear(ps->charset, 0);
+			neg = 1;
+			ptr++;
+
+		} else
+			dm_bit_clear_all(ps->charset);
+
+		while ((ptr < ps->rx_end) && (*ptr != ']')) {
+			if (*ptr == '\\') {
+				/* an escaped character */
+				ptr++;
+				switch (*ptr) {
+				case 'n':
+					c = '\n';
+					break;
+				case 'r':
+					c = '\r';
+					break;
+				case 't':
+					c = '\t';
+					break;
+				default:
+					c = *ptr;
+				}
+			} else if (*ptr == '-' && lc) {
+				/* we've got a range on our hands */
+				range = 1;
+				ptr++;
+				if (ptr == ps->rx_end) {
+					log_error("Incomplete range"
+						  "specification");
+					return -1;
+				}
+				c = *ptr;
+			} else
+				c = *ptr;
+
+			if (range) {
+				/* add lc - c into the bitset */
+				if (lc > c) {
+					char tmp = c;
+					c = lc;
+					lc = tmp;
+				}
+
+				for (; lc <= c; lc++) {
+					if (neg)
+						dm_bit_clear(ps->charset, lc);
+					else
+						dm_bit_set(ps->charset, lc);
+				}
+				range = 0;
+			} else {
+				/* add c into the bitset */
+				if (neg)
+					dm_bit_clear(ps->charset, c);
+				else
+					dm_bit_set(ps->charset, c);
+			}
+			ptr++;
+			lc = c;
+		}
+
+		if (ptr >= ps->rx_end) {
+			ps->type = -1;
+			return -1;
+		}
+
+		ps->type = 0;
+		ps->cursor = ptr + 1;
+		break;
+
+		/* These characters are special, we just return their ASCII
+		   codes as the type.  Sorted into ascending order to help the
+		   compiler */
+	case '(':
+	case ')':
+	case '*':
+	case '+':
+	case '?':
+	case '|':
+		ps->type = (int) *ptr;
+		ps->cursor = ptr + 1;
+		break;
+
+	case '^':
+		_single_char(ps, HAT_CHAR, ptr);
+		break;
+
+	case '$':
+		_single_char(ps, DOLLAR_CHAR, ptr);
+		break;
+
+	case '.':
+		/* The 'all but newline' character set */
+		ps->type = 0;
+		ps->cursor = ptr + 1;
+		dm_bit_set_all(ps->charset);
+		dm_bit_clear(ps->charset, (int) '\n');
+		dm_bit_clear(ps->charset, (int) '\r');
+		dm_bit_clear(ps->charset, 0);
+		break;
+
+	case '\\':
+		/* escaped character */
+		ptr++;
+		if (ptr >= ps->rx_end) {
+			log_error("Badly quoted character at end "
+				  "of expression");
+			ps->type = -1;
+			return -1;
+		}
+
+		ps->type = 0;
+		ps->cursor = ptr + 1;
+		dm_bit_clear_all(ps->charset);
+		switch (*ptr) {
+		case 'n':
+			dm_bit_set(ps->charset, (int) '\n');
+			break;
+		case 'r':
+			dm_bit_set(ps->charset, (int) '\r');
+			break;
+		case 't':
+			dm_bit_set(ps->charset, (int) '\t');
+			break;
+		default:
+			dm_bit_set(ps->charset, (int) *ptr);
+		}
+		break;
+
+	default:
+		/* add a single character to the bitset */
+		ps->type = 0;
+		ps->cursor = ptr + 1;
+		dm_bit_clear_all(ps->charset);
+		dm_bit_set(ps->charset, (int) *ptr);
+		break;
+	}
+
+	return 1;
+}
+
+static struct rx_node *_node(struct dm_pool *mem, int type,
+			     struct rx_node *l, struct rx_node *r)
+{
+	struct rx_node *n = dm_pool_zalloc(mem, sizeof(*n));
+
+	if (n) {
+		if (!(n->charset = dm_bitset_create(mem, 256))) {
+			dm_pool_free(mem, n);
+			return NULL;
+		}
+
+		n->type = type;
+		n->left = l;
+		n->right = r;
+	}
+
+	return n;
+}
+
+static struct rx_node *_term(struct parse_sp *ps)
+{
+	struct rx_node *n;
+
+	switch (ps->type) {
+	case 0:
+		if (!(n = _node(ps->mem, CHARSET, NULL, NULL))) {
+			stack;
+			return NULL;
+		}
+
+		dm_bit_copy(n->charset, ps->charset);
+		_rx_get_token(ps);	/* match charset */
+		break;
+
+	case '(':
+		_rx_get_token(ps);	/* match '(' */
+		n = _or_term(ps);
+		if (ps->type != ')') {
+			log_error("missing ')' in regular expression");
+			return 0;
+		}
+		_rx_get_token(ps);	/* match ')' */
+		break;
+
+	default:
+		n = 0;
+	}
+
+	return n;
+}
+
+static struct rx_node *_closure_term(struct parse_sp *ps)
+{
+	struct rx_node *l, *n;
+
+	if (!(l = _term(ps)))
+		return NULL;
+
+	for (;;) {
+		switch (ps->type) {
+		case '*':
+			n = _node(ps->mem, STAR, l, NULL);
+			break;
+
+		case '+':
+			n = _node(ps->mem, PLUS, l, NULL);
+			break;
+
+		case '?':
+			n = _node(ps->mem, QUEST, l, NULL);
+			break;
+
+		default:
+			return l;
+		}
+
+		if (!n) {
+			stack;
+			return NULL;
+		}
+
+		_rx_get_token(ps);
+		l = n;
+	}
+
+	return n;
+}
+
+static struct rx_node *_cat_term(struct parse_sp *ps)
+{
+	struct rx_node *l, *r, *n;
+
+	if (!(l = _closure_term(ps)))
+		return NULL;
+
+	if (ps->type == '|')
+		return l;
+
+	if (!(r = _cat_term(ps)))
+		return l;
+
+	if (!(n = _node(ps->mem, CAT, l, r)))
+		stack;
+
+	return n;
+}
+
+static struct rx_node *_or_term(struct parse_sp *ps)
+{
+	struct rx_node *l, *r, *n;
+
+	if (!(l = _cat_term(ps)))
+		return NULL;
+
+	if (ps->type != '|')
+		return l;
+
+	_rx_get_token(ps);		/* match '|' */
+
+	if (!(r = _or_term(ps))) {
+		log_error("Badly formed 'or' expression");
+		return NULL;
+	}
+
+	if (!(n = _node(ps->mem, OR, l, r)))
+		stack;
+
+	return n;
+}
+
+struct rx_node *rx_parse_tok(struct dm_pool *mem,
+			     const char *begin, const char *end)
+{
+	struct rx_node *r;
+	struct parse_sp *ps = dm_pool_zalloc(mem, sizeof(*ps));
+
+	if (!ps) {
+		stack;
+		return NULL;
+	}
+
+	ps->mem = mem;
+	ps->charset = dm_bitset_create(mem, 256);
+	ps->cursor = begin;
+	ps->rx_end = end;
+	_rx_get_token(ps);		/* load the first token */
+
+	if (!(r = _or_term(ps))) {
+		log_error("Parse error in regex");
+		dm_pool_free(mem, ps);
+	}
+
+	return r;
+}
+
+struct rx_node *rx_parse_str(struct dm_pool *mem, const char *str)
+{
+	return rx_parse_tok(mem, str, str + strlen(str));
+}
Index: src/external/gpl2/lvm2tools/dist/libdm/regex/parse_rx.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/regex/parse_rx.h
diff -N src/external/gpl2/lvm2tools/dist/libdm/regex/parse_rx.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/regex/parse_rx.h	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,54 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _DM_PARSE_REGEX_H
+#define _DM_PARSE_REGEX_H
+
+enum {
+	CAT,
+	STAR,
+	PLUS,
+	OR,
+	QUEST,
+	CHARSET
+};
+
+/*
+ * We're never going to be running the regex on non-printable
+ * chars, so we can use a couple of these chars to represent the
+ * start and end of a string.
+ */
+#define HAT_CHAR 0x2
+#define DOLLAR_CHAR 0x3
+
+struct rx_node {
+	int type;
+	dm_bitset_t charset;
+	struct rx_node *left, *right;
+
+	/* used to build the dfa for the toker */
+	int nullable, final;
+	dm_bitset_t firstpos;
+	dm_bitset_t lastpos;
+	dm_bitset_t followpos;
+};
+
+struct rx_node *rx_parse_str(struct dm_pool *mem, const char *str);
+struct rx_node *rx_parse_tok(struct dm_pool *mem,
+			     const char *begin, const char *end);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/libdm/regex/ttree.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/regex/ttree.c
diff -N src/external/gpl2/lvm2tools/dist/libdm/regex/ttree.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/regex/ttree.c	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,119 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "dmlib.h"
+#include "ttree.h"
+
+struct node {
+	unsigned k;
+	struct node *l, *m, *r;
+	void *data;
+};
+
+struct ttree {
+	int klen;
+	struct dm_pool *mem;
+	struct node *root;
+};
+
+static struct node **_lookup_single(struct node **c, unsigned int k)
+{
+	while (*c) {
+		if (k < (*c)->k)
+			c = &((*c)->l);
+
+		else if (k > (*c)->k)
+			c = &((*c)->r);
+
+		else {
+			c = &((*c)->m);
+			break;
+		}
+	}
+
+	return c;
+}
+
+void *ttree_lookup(struct ttree *tt, unsigned *key)
+{
+	struct node **c = &tt->root;
+	int count = tt->klen;
+
+	while (*c && count) {
+		c = _lookup_single(c, *key++);
+		count--;
+	}
+
+	return *c ? (*c)->data : NULL;
+}
+
+static struct node *_tree_node(struct dm_pool *mem, unsigned int k)
+{
+	struct node *n = dm_pool_zalloc(mem, sizeof(*n));
+
+	if (n)
+		n->k = k;
+
+	return n;
+}
+
+int ttree_insert(struct ttree *tt, unsigned int *key, void *data)
+{
+	struct node **c = &tt->root;
+	int count = tt->klen;
+	unsigned int k;
+
+	do {
+		k = *key++;
+		c = _lookup_single(c, k);
+		count--;
+
+	} while (*c && count);
+
+	if (!*c) {
+		count++;
+
+		while (count--) {
+			if (!(*c = _tree_node(tt->mem, k))) {
+				stack;
+				return 0;
+			}
+
+			k = *key++;
+
+			if (count)
+				c = &((*c)->m);
+		}
+	}
+	(*c)->data = data;
+
+	return 1;
+}
+
+struct ttree *ttree_create(struct dm_pool *mem, unsigned int klen)
+{
+	struct ttree *tt;
+
+	if (!(tt = dm_pool_zalloc(mem, sizeof(*tt)))) {
+		stack;
+		return NULL;
+	}
+
+	tt->klen = klen;
+	tt->mem = mem;
+	return tt;
+}
Index: src/external/gpl2/lvm2tools/dist/libdm/regex/ttree.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/libdm/regex/ttree.h
diff -N src/external/gpl2/lvm2tools/dist/libdm/regex/ttree.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/libdm/regex/ttree.h	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,28 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _DM_TTREE_H
+#define _DM_TTREE_H
+
+struct ttree;
+
+struct ttree *ttree_create(struct dm_pool *mem, unsigned int klen);
+
+void *ttree_lookup(struct ttree *tt, unsigned *key);
+int ttree_insert(struct ttree *tt, unsigned *key, void *data);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/man/Makefile.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/Makefile.in
diff -N src/external/gpl2/lvm2tools/dist/man/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/Makefile.in	12 Dec 2008 16:33:01 -0000	1.1.1.1.2.1
@@ -0,0 +1,89 @@
+#
+# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+# Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+ifeq ("@FSADM@", "yes")
+FSADMMAN = fsadm.8
+else
+FSADMMAN =
+endif
+
+MAN5=lvm.conf.5
+MAN8=lvchange.8 lvconvert.8 lvcreate.8 lvdisplay.8 lvextend.8 lvm.8 \
+	lvmchange.8 lvmdiskscan.8 lvmdump.8 \
+	lvreduce.8 lvremove.8 lvrename.8 lvresize.8 lvs.8 \
+	lvscan.8 pvchange.8 pvck.8 pvcreate.8 pvdisplay.8 pvmove.8 pvremove.8 \
+	pvresize.8 pvs.8 pvscan.8 vgcfgbackup.8 vgcfgrestore.8 vgchange.8 \
+	vgck.8 vgcreate.8 vgconvert.8 vgdisplay.8 vgexport.8 vgextend.8 \
+	vgimport.8 vgmerge.8 vgmknodes.8 vgreduce.8 vgremove.8 vgrename.8 \
+	vgs.8 vgscan.8 vgsplit.8 $(FSADMMAN)
+MAN8CLUSTER=clvmd.8
+MAN8DM=dmsetup.8
+MAN5DIR=${mandir}/man5
+MAN8DIR=${mandir}/man8
+
+CLEAN_TARGETS=$(MAN5) $(MAN8) $(MAN8CLUSTER) $(FSADMMAN) $(MAN8DM)
+
+include $(top_srcdir)/make.tmpl
+
+ifneq ("@CLVMD@", "none")
+  install: install_cluster
+endif
+
+all: man
+
+.PHONY: man
+
+device-mapper: $(MAN8DM)
+
+man: $(MAN5) $(MAN8) $(MAN8CLUSTER)
+
+$(MAN5) $(MAN8) $(MAN8CLUSTER):	Makefile
+
+%: %.in
+	$(SED) -e "s/#VERSION#/$(LVM_VERSION)/" $< > $@
+
+install: install_device-mapper
+	@echo "Installing $(MAN8) in $(MAN8DIR)"
+	@for f in $(MAN8); \
+	do \
+	   $(RM) $(MAN8DIR)/$$f; \
+	   @INSTALL@ -D $(OWNER) $(GROUP) -m 444 $$f $(MAN8DIR)/$$f; \
+	done
+
+	@echo "Installing $(MAN5) in $(MAN5DIR)"
+	@for f in $(MAN5); \
+	do \
+	   $(RM) $(MAN5DIR)/$$f; \
+	   @INSTALL@ -D $(OWNER) $(GROUP) -m 444 $$f $(MAN5DIR)/$$f; \
+	done
+
+install_cluster:
+	@echo "Installing $(MAN8CLUSTER) in $(MAN8DIR)"
+	@for f in $(MAN8CLUSTER); \
+	do \
+	   $(RM) $(MAN8DIR)/$$f; \
+	   @INSTALL@ -D $(OWNER) $(GROUP) -m 444 $$f $(MAN8DIR)/$$f; \
+	done
+
+install_device-mapper:
+	@echo "Installing $(MAN8DM) in $(MAN8DIR)"
+	@for f in $(MAN8DM); \
+	do \
+	   $(RM) $(MAN8DIR)/$$f; \
+	   @INSTALL@ -D $(OWNER) $(GROUP) -m 444 $$f $(MAN8DIR)/$$f; \
+	done
Index: src/external/gpl2/lvm2tools/dist/man/clvmd.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/clvmd.8
diff -N src/external/gpl2/lvm2tools/dist/man/clvmd.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/clvmd.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,82 @@
+.\"	$NetBSD$
+.\"
+.TH CLVMD 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Red Hat Inc" \" -*- nroff -*-
+.SH NAME
+clvmd \- cluster LVM daemon
+.SH SYNOPSIS
+.B clvmd
+[\-d [<value>]] [\-C] [\-h]
+[\-R]
+[\-t <timeout>]
+[\-T <start timeout>]
+[\-V]
+.SH DESCRIPTION
+clvmd is the daemon that distributes LVM metadata updates around a cluster.
+It must be running on all nodes in the cluster and will give an error 
+if a node in the cluster does not have this daemon running.
+.SH OPTIONS
+.TP
+.I \-d [<value>]
+Enable debug logging. Value can be 0, 1 or 2.
+.br
+0 disables debug logging in a running clvmd
+.br
+1 sends debug logs to stderr (clvmd will not fork in this case)
+.br
+2 sends debug logs to syslog
+.br
+If 
+.B -d 
+is specified without a value then 1 is assumed if you are starting a
+new clvmd, 2 if you are enabling debug in a running clvmd.
+.TP
+.I \-C
+Only valid if 
+.B -d 
+is also specified. Tells all clvmds in a cluster to enable/disable debug logging.
+Without this switch, only the local clvmd will change its debug level to that
+given with 
+.B -d.
+.br
+This does not work correctly if specified on the command-line that starts clvmd.
+If you want to start clvmd 
+.B and 
+enable cluster-wide logging then the command needs to be issued twice, eg:
+.br
+clvmd
+.br
+clvmd -d2
+.br
+.TP
+.I \-t <timeout>
+Specifies the timeout for commands to run around the cluster. This should not
+be so small that commands with many disk updates to do will fail, so you
+may need to increase this on systems with very large disk farms. 
+The default is 30 seconds.
+.TP
+.I \-T <start timeout>
+Specifies the timeout for clvmd daemon startup. If the daemon does not report 
+that it has started up within this time then the parent command will exit with 
+status of 5. This does NOT mean that clvmd has not started! What it means is 
+that the startup of clvmd has been delayed for some reason; the most likely 
+cause of this is an inquorate cluster though it could be due to locking 
+latencies on a cluster with large numbers of logical volumes. If you get the 
+return code of 5 it is usually not necessary to restart clvmd - it will start
+as soon as that blockage has cleared. This flag is to allow startup scripts
+to exit in a timely fashion even if the cluster is stalled for some reason.
+.br
+The default is 0 (no timeout) and the value is in seconds. Don't set this too
+small or you will experience spurious errors. 10 or 20 seconds might be
+sensible.
+.br
+This timeout will be ignored if you start clvmd with the -d switch.
+.TP
+.I \-R
+Tells all the running clvmds in the cluster to reload their device cache and
+re-read the lvm configuration file. This command should be run whenever the
+devices on a cluster system are changed.
+.TP
+.I \-V
+Display the version of the cluster LVM daemon.
+.SH SEE ALSO
+.BR lvm (8)
Index: src/external/gpl2/lvm2tools/dist/man/clvmd.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/clvmd.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/clvmd.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/clvmd.8.in	12 Dec 2008 16:33:01 -0000	1.1.1.1.2.2
@@ -0,0 +1,80 @@
+.TH CLVMD 8 "LVM TOOLS #VERSION#" "Red Hat Inc" \" -*- nroff -*-
+.SH NAME
+clvmd \- cluster LVM daemon
+.SH SYNOPSIS
+.B clvmd
+[\-d [<value>]] [\-C] [\-h]
+[\-R]
+[\-t <timeout>]
+[\-T <start timeout>]
+[\-V]
+.SH DESCRIPTION
+clvmd is the daemon that distributes LVM metadata updates around a cluster.
+It must be running on all nodes in the cluster and will give an error 
+if a node in the cluster does not have this daemon running.
+.SH OPTIONS
+.TP
+.I \-d [<value>]
+Enable debug logging. Value can be 0, 1 or 2.
+.br
+0 disables debug logging in a running clvmd
+.br
+1 sends debug logs to stderr (clvmd will not fork in this case)
+.br
+2 sends debug logs to syslog
+.br
+If 
+.B -d 
+is specified without a value then 1 is assumed if you are starting a
+new clvmd, 2 if you are enabling debug in a running clvmd.
+.TP
+.I \-C
+Only valid if 
+.B -d 
+is also specified. Tells all clvmds in a cluster to enable/disable debug logging.
+Without this switch, only the local clvmd will change its debug level to that
+given with 
+.B -d.
+.br
+This does not work correctly if specified on the command-line that starts clvmd.
+If you want to start clvmd 
+.B and 
+enable cluster-wide logging then the command needs to be issued twice, eg:
+.br
+clvmd
+.br
+clvmd -d2
+.br
+.TP
+.I \-t <timeout>
+Specifies the timeout for commands to run around the cluster. This should not
+be so small that commands with many disk updates to do will fail, so you
+may need to increase this on systems with very large disk farms. 
+The default is 30 seconds.
+.TP
+.I \-T <start timeout>
+Specifies the timeout for clvmd daemon startup. If the daemon does not report 
+that it has started up within this time then the parent command will exit with 
+status of 5. This does NOT mean that clvmd has not started! What it means is 
+that the startup of clvmd has been delayed for some reason; the most likely 
+cause of this is an inquorate cluster though it could be due to locking 
+latencies on a cluster with large numbers of logical volumes. If you get the 
+return code of 5 it is usually not necessary to restart clvmd - it will start
+as soon as that blockage has cleared. This flag is to allow startup scripts
+to exit in a timely fashion even if the cluster is stalled for some reason.
+.br
+The default is 0 (no timeout) and the value is in seconds. Don't set this too
+small or you will experience spurious errors. 10 or 20 seconds might be
+sensible.
+.br
+This timeout will be ignored if you start clvmd with the -d switch.
+.TP
+.I \-R
+Tells all the running clvmds in the cluster to reload their device cache and
+re-read the lvm configuration file. This command should be run whenever the
+devices on a cluster system are changed.
+.TP
+.I \-V
+Display the version of the cluster LVM daemon.
+.SH SEE ALSO
+.BR lvm (8)
Index: src/external/gpl2/lvm2tools/dist/man/dmsetup.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/dmsetup.8
diff -N src/external/gpl2/lvm2tools/dist/man/dmsetup.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/dmsetup.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.3
@@ -0,0 +1,364 @@
+.\"	$NetBSD$
+.\"
+.TH DMSETUP 8 "Apr 06 2006" "Linux" "MAINTENANCE COMMANDS"
+.SH NAME
+dmsetup \- low level logical volume management
+.SH SYNOPSIS
+.ad l
+.B dmsetup help
+.I [-c|-C|--columns]
+.br
+.B dmsetup create 
+.I device_name [-u uuid] [--notable | --table <table> | table_file]
+.br
+.B dmsetup remove
+.I [-f|--force] device_name
+.br
+.B dmsetup remove_all
+.I [-f|--force]
+.br
+.B dmsetup suspend
+.I [--nolockfs] [--noflush] device_name
+.br
+.B dmsetup resume
+.I device_name
+.br
+.B dmsetup load
+.I device_name [--table <table> | table_file]
+.br
+.B dmsetup clear
+.I device_name
+.br
+.B dmsetup reload
+.I device_name [--table <table> | table_file]
+.br
+.B dmsetup rename
+.I device_name new_name
+.br
+.B dmsetup message
+.I device_name sector message
+.br
+.B dmsetup ls
+.I [--target target_type] [--exec command] [--tree [-o options]]
+.br
+.B dmsetup info 
+.I [device_name]
+.br
+.B dmsetup info -c|-C|--columns
+.I [--noheadings] [--separator separator] [-o fields] [-O|--sort sort_fields]
+.I [device_name]
+.br
+.B dmsetup deps
+.I [device_name]
+.br
+.B dmsetup status
+.I [--target target_type]
+.I [device_name]
+.br
+.B dmsetup table
+.I [--target target_type]
+.I [device_name]
+.br
+.B dmsetup wait
+.I device_name
+.I [event_nr]
+.br
+.B dmsetup mknodes
+.I [device_name]
+.br
+.B dmsetup targets
+.br
+.B dmsetup version
+.br
+.B dmsetup setgeometry
+.I device_name cyl head sect start
+.br
+
+.B devmap_name
+.I major minor
+.br
+.B devmap_name 
+.I major:minor
+.ad b
+.SH DESCRIPTION
+dmsetup manages logical devices that use the device-mapper driver.  
+Devices are created by loading a table that specifies a target for
+each sector (512 bytes) in the logical device.
+
+The first argument to dmsetup is a command. 
+The second argument is the logical device name or uuid.
+
+Invoking the command as \fBdevmap_name\fP is equivalent to
+.br
+\fBdmsetup info -c --noheadings -j \fImajor\fB -m \fIminor\fP.
+.SH OPTIONS
+.IP \fB-c|-C|--columns
+.br
+Display output in columns rather than as Field: Value lines.
+.IP \fB-j|--major\ \fImajor
+.br
+Specify the major number.
+.IP \fB-m|--minor\ \fIminor
+.br
+Specify the minor number.
+.IP \fB-n|--noheadings
+.br
+Suppress the headings line when using columnar output.
+.IP \fB--noopencount
+.br
+Tell the kernel not to supply the open reference count for the device.
+.IP \fB--notable
+.br
+When creating a device, don't load any table.
+.IP \fB-o|--options
+.br
+Specify which fields to display.
+.IP \fB-r|--readonly
+.br
+Set the table being loaded read-only.
+.IP \fB--readahead\ [+]<sectors>|auto|none
+.br    
+Specify read ahead size in units of sectors.
+The default value is "auto" which allows the kernel to choose
+a suitable value automatically.  The + prefix lets you
+specify a minimum value which will not be used if it is
+smaller than the value chosen by the kernel.
+"None" is equivalent to specifying zero.
+.IP \fB--table\ <table>
+.br
+Specify a one-line table directly on the command line.
+.IP \fB-u|--uuid
+.br
+Specify the uuid.
+.IP \fB-v|--verbose\ [-v|--verbose]
+.br
+Produce additional output.
+.IP \fB--version
+.br
+Display the library and kernel driver version.
+.SH COMMANDS
+.IP \fBcreate
+.I device_name [-u uuid] [--notable | --table <table> | table_file]
+.br
+Creates a device with the given name.
+If table_file or <table> is supplied, the table is loaded and made live.
+Otherwise a table is read from standard input unless --notable is used.
+The optional uuid can be used in place of
+device_name in subsequent dmsetup commands.  
+If successful a device will appear as
+/dev/device-mapper/<device-name>.  
+See below for information on the table format.
+.IP \fBdeps
+.I [device_name]
+.br
+Outputs a list of (major, minor) pairs for devices referenced by the
+live table for the specified device.
+.IP \fBhelp
+.I [-c|-C|--columns]
+.br
+Outputs a summary of the commands available, optionally including
+the list of report fields.
+.IP \fBinfo
+.I [device_name]
+.br
+Outputs some brief information about the device in the form:
+.br
+    State: SUSPENDED|ACTIVE, READ-ONLY
+.br
+    Tables present: LIVE and/or INACTIVE
+.br
+    Open reference count
+.br
+    Last event sequence number (used by \fBwait\fP)
+.br
+    Major and minor device number
+.br
+    Number of targets in the live table
+.br
+    UUID
+.IP \fBinfo -c|-C|--columns
+.I [--noheadings] [--separator separator] [-o fields] [-O|--sort sort_fields]
+.I [device_name]
+.br
+Output you can customise.
+Fields are comma-separated and chosen from the following list:
+name, major, minor, attr, open, segments, events, uuid.
+Attributes are: (L)ive, (I)nactive, (s)uspended, (r)ead-only, read-(w)rite.
+Precede the list with '+' to append
+to the default selection of columns instead of replacing it.
+Precede any sort_field with - for a reverse sort on that column.
+.IP \fBls
+.I [--target target_type]
+.I [--exec command]
+.I [--tree [-o options]]
+.br
+List device names.  Optionally only list devices that have at least
+one target of the specified type.  Optionally execute a command for
+each device.  The device name is appended to the supplied command.
+--tree displays dependencies between devices as a tree.
+It accepts a comma-separate list of options.
+Some specify the information displayed against each node:
+device/nodevice; active, open, rw, uuid.
+Others specify how the tree is displayed:
+ascii, utf, vt100; compact, inverted, notrunc.
+.IP \fBload|reload
+.I device_name [--table <table> | table_file]
+.br
+Loads <table> or table_file into the inactive table slot for device_name.
+If neither is supplied, reads a table from standard input.
+.IP \fBmessage
+.I device_name sector message
+.br
+Send message to target. If sector not needed use 0.
+.IP \fBmknodes
+.I [device_name]
+.br
+Ensure that the node in /dev/mapper for device_name is correct.
+If no device_name is supplied, ensure that all nodes in /dev/mapper 
+correspond to mapped devices currently loaded by the device-mapper kernel
+driver, adding, changing or removing nodes as necessary.
+.IP \fBremove
+.I [-f|--force] device_name
+.br
+Removes a device.  It will no longer be visible to dmsetup.
+Open devices cannot be removed except with older kernels
+that contain a version of device-mapper prior to 4.8.0.
+In this case the device will be deleted when its open_count 
+drops to zero.  From version 4.8.0 onwards, if a device can't
+be removed because an uninterruptible process is waiting for
+I/O to return from it, adding --force will replace the table 
+with one that fails all I/O, which might allow the 
+process to be killed.
+.IP \fBremove_all
+.I [-f|--force]
+.br
+Attempts to remove all device definitions i.e. reset the driver.
+Use with care!  From version 4.8.0 onwards, if devices can't
+be removed because uninterruptible processess are waiting for
+I/O to return from them, adding --force will replace the table 
+with one that fails all I/O, which might allow the 
+process to be killed.  This also runs \fBmknodes\fP afterwards.
+.IP \fBrename
+.I device_name new_name
+.br
+Renames a device.
+.IP \fBresume
+.I device_name
+.br
+Un-suspends a device.  
+If an inactive table has been loaded, it becomes live.
+Postponed I/O then gets re-queued for processing.
+.IP \fBsetgeometry
+.I device_name cyl head sect start
+.br
+Sets the device geometry to C/H/S.
+.IP \fBstatus
+.I [--target target_type]
+.I [device_name]
+.br
+Outputs status information for each of the device's targets.
+With --target, only information relating to the specified target type
+is displayed.
+.IP \fBsuspend
+.I [--nolockfs] [--noflush]
+.I device_name
+.br
+Suspends a device.  Any I/O that has already been mapped by the device
+but has not yet completed will be flushed.  Any further I/O to that
+device will be postponed for as long as the device is suspended.
+If there's a filesystem on the device which supports the operation, 
+an attempt will be made to sync it first unless --nolockfs is specified.
+Some targets such as recent (October 2006) versions of multipath may support
+the --noflush option.  This lets outstanding I/O that has not yet reached the
+device to remain unflushed.
+.IP \fBtable
+.I [--target target_type]
+.I [device_name]
+.br
+Outputs the current table for the device in a format that can be fed
+back in using the create or load commands.
+With --target, only information relating to the specified target type
+is displayed.
+.IP \fBtargets
+.br
+Displays the names and versions of the currently-loaded targets.
+.IP \fBversion
+.br
+Outputs version information.
+.IP \fBwait
+.I device_name
+.I [event_nr]
+.br
+Sleeps until the event counter for device_name exceeds event_nr.
+Use -v to see the event number returned.
+To wait until the next event is triggered, use \fBinfo\fP to find
+the last event number.  
+.SH TABLE FORMAT
+Each line of the table specifies a single target and is of the form:
+.br
+    logical_start_sector num_sectors target_type target_args
+.br
+.br
+
+There are currently three simple target types available together 
+with more complex optional ones that implement snapshots and mirrors.
+
+.IP \fBlinear
+.I destination_device start_sector
+.br
+The traditional linear mapping.
+
+.IP \fBstriped
+.I num_stripes chunk_size [destination start_sector]+
+.br
+Creates a striped area.
+.br
+e.g. striped 2 32 /dev/hda1 0 /dev/hdb1 0
+will map the first chunk (16k) as follows:
+.br
+    LV chunk 1 -> hda1, chunk 1
+.br
+    LV chunk 2 -> hdb1, chunk 1
+.br
+    LV chunk 3 -> hda1, chunk 2
+.br
+    LV chunk 4 -> hdb1, chunk 2
+.br
+    etc.
+
+.IP \fBerror
+.br
+Errors any I/O that goes to this area.  Useful for testing or
+for creating devices with holes in them.
+
+.SH EXAMPLES
+
+# A table to join two disks together
+.br
+.br
+0 1028160 linear /dev/hda 0
+.br
+1028160 3903762 linear /dev/hdb 0
+
+
+# A table to stripe across the two disks, 
+.br
+# and add the spare space from
+.br
+# hdb to the back of the volume
+
+0 2056320 striped 2 32 /dev/hda 0 /dev/hdb 0
+.br
+2056320 2875602 linear /dev/hdb 1028160
+
+.SH ENVIRONMENT VARIABLES
+.TP
+\fBDM_DEV_DIR\fP
+The device directory name.
+Defaults to "/dev" and must be an absolute path.
+
+.SH AUTHORS
+Original version: Joe Thornber (thornber@sistina.com)
+
+.SH SEE ALSO
+Device-mapper resource page: http://sources.redhat.com/dm/
Index: src/external/gpl2/lvm2tools/dist/man/dmsetup.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/dmsetup.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/dmsetup.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/dmsetup.8.in	12 Dec 2008 16:33:01 -0000	1.1.1.1.2.2
@@ -0,0 +1,362 @@
+.TH DMSETUP 8 "Apr 06 2006" "Linux" "MAINTENANCE COMMANDS"
+.SH NAME
+dmsetup \- low level logical volume management
+.SH SYNOPSIS
+.ad l
+.B dmsetup help
+.I [-c|-C|--columns]
+.br
+.B dmsetup create 
+.I device_name [-u uuid] [--notable | --table <table> | table_file]
+.br
+.B dmsetup remove
+.I [-f|--force] device_name
+.br
+.B dmsetup remove_all
+.I [-f|--force]
+.br
+.B dmsetup suspend
+.I [--nolockfs] [--noflush] device_name
+.br
+.B dmsetup resume
+.I device_name
+.br
+.B dmsetup load
+.I device_name [--table <table> | table_file]
+.br
+.B dmsetup clear
+.I device_name
+.br
+.B dmsetup reload
+.I device_name [--table <table> | table_file]
+.br
+.B dmsetup rename
+.I device_name new_name
+.br
+.B dmsetup message
+.I device_name sector message
+.br
+.B dmsetup ls
+.I [--target target_type] [--exec command] [--tree [-o options]]
+.br
+.B dmsetup info 
+.I [device_name]
+.br
+.B dmsetup info -c|-C|--columns
+.I [--noheadings] [--separator separator] [-o fields] [-O|--sort sort_fields]
+.I [device_name]
+.br
+.B dmsetup deps
+.I [device_name]
+.br
+.B dmsetup status
+.I [--target target_type]
+.I [device_name]
+.br
+.B dmsetup table
+.I [--target target_type]
+.I [device_name]
+.br
+.B dmsetup wait
+.I device_name
+.I [event_nr]
+.br
+.B dmsetup mknodes
+.I [device_name]
+.br
+.B dmsetup targets
+.br
+.B dmsetup version
+.br
+.B dmsetup setgeometry
+.I device_name cyl head sect start
+.br
+
+.B devmap_name
+.I major minor
+.br
+.B devmap_name 
+.I major:minor
+.ad b
+.SH DESCRIPTION
+dmsetup manages logical devices that use the device-mapper driver.  
+Devices are created by loading a table that specifies a target for
+each sector (512 bytes) in the logical device.
+
+The first argument to dmsetup is a command. 
+The second argument is the logical device name or uuid.
+
+Invoking the command as \fBdevmap_name\fP is equivalent to
+.br
+\fBdmsetup info -c --noheadings -j \fImajor\fB -m \fIminor\fP.
+.SH OPTIONS
+.IP \fB-c|-C|--columns
+.br
+Display output in columns rather than as Field: Value lines.
+.IP \fB-j|--major\ \fImajor
+.br
+Specify the major number.
+.IP \fB-m|--minor\ \fIminor
+.br
+Specify the minor number.
+.IP \fB-n|--noheadings
+.br
+Suppress the headings line when using columnar output.
+.IP \fB--noopencount
+.br
+Tell the kernel not to supply the open reference count for the device.
+.IP \fB--notable
+.br
+When creating a device, don't load any table.
+.IP \fB-o|--options
+.br
+Specify which fields to display.
+.IP \fB-r|--readonly
+.br
+Set the table being loaded read-only.
+.IP \fB--readahead\ [+]<sectors>|auto|none
+.br    
+Specify read ahead size in units of sectors.
+The default value is "auto" which allows the kernel to choose
+a suitable value automatically.  The + prefix lets you
+specify a minimum value which will not be used if it is
+smaller than the value chosen by the kernel.
+"None" is equivalent to specifying zero.
+.IP \fB--table\ <table>
+.br
+Specify a one-line table directly on the command line.
+.IP \fB-u|--uuid
+.br
+Specify the uuid.
+.IP \fB-v|--verbose\ [-v|--verbose]
+.br
+Produce additional output.
+.IP \fB--version
+.br
+Display the library and kernel driver version.
+.SH COMMANDS
+.IP \fBcreate
+.I device_name [-u uuid] [--notable | --table <table> | table_file]
+.br
+Creates a device with the given name.
+If table_file or <table> is supplied, the table is loaded and made live.
+Otherwise a table is read from standard input unless --notable is used.
+The optional uuid can be used in place of
+device_name in subsequent dmsetup commands.  
+If successful a device will appear as
+/dev/device-mapper/<device-name>.  
+See below for information on the table format.
+.IP \fBdeps
+.I [device_name]
+.br
+Outputs a list of (major, minor) pairs for devices referenced by the
+live table for the specified device.
+.IP \fBhelp
+.I [-c|-C|--columns]
+.br
+Outputs a summary of the commands available, optionally including
+the list of report fields.
+.IP \fBinfo
+.I [device_name]
+.br
+Outputs some brief information about the device in the form:
+.br
+    State: SUSPENDED|ACTIVE, READ-ONLY
+.br
+    Tables present: LIVE and/or INACTIVE
+.br
+    Open reference count
+.br
+    Last event sequence number (used by \fBwait\fP)
+.br
+    Major and minor device number
+.br
+    Number of targets in the live table
+.br
+    UUID
+.IP \fBinfo -c|-C|--columns
+.I [--noheadings] [--separator separator] [-o fields] [-O|--sort sort_fields]
+.I [device_name]
+.br
+Output you can customise.
+Fields are comma-separated and chosen from the following list:
+name, major, minor, attr, open, segments, events, uuid.
+Attributes are: (L)ive, (I)nactive, (s)uspended, (r)ead-only, read-(w)rite.
+Precede the list with '+' to append
+to the default selection of columns instead of replacing it.
+Precede any sort_field with - for a reverse sort on that column.
+.IP \fBls
+.I [--target target_type]
+.I [--exec command]
+.I [--tree [-o options]]
+.br
+List device names.  Optionally only list devices that have at least
+one target of the specified type.  Optionally execute a command for
+each device.  The device name is appended to the supplied command.
+--tree displays dependencies between devices as a tree.
+It accepts a comma-separate list of options.
+Some specify the information displayed against each node:
+device/nodevice; active, open, rw, uuid.
+Others specify how the tree is displayed:
+ascii, utf, vt100; compact, inverted, notrunc.
+.IP \fBload|reload
+.I device_name [--table <table> | table_file]
+.br
+Loads <table> or table_file into the inactive table slot for device_name.
+If neither is supplied, reads a table from standard input.
+.IP \fBmessage
+.I device_name sector message
+.br
+Send message to target. If sector not needed use 0.
+.IP \fBmknodes
+.I [device_name]
+.br
+Ensure that the node in /dev/mapper for device_name is correct.
+If no device_name is supplied, ensure that all nodes in /dev/mapper 
+correspond to mapped devices currently loaded by the device-mapper kernel
+driver, adding, changing or removing nodes as necessary.
+.IP \fBremove
+.I [-f|--force] device_name
+.br
+Removes a device.  It will no longer be visible to dmsetup.
+Open devices cannot be removed except with older kernels
+that contain a version of device-mapper prior to 4.8.0.
+In this case the device will be deleted when its open_count 
+drops to zero.  From version 4.8.0 onwards, if a device can't
+be removed because an uninterruptible process is waiting for
+I/O to return from it, adding --force will replace the table 
+with one that fails all I/O, which might allow the 
+process to be killed.
+.IP \fBremove_all
+.I [-f|--force]
+.br
+Attempts to remove all device definitions i.e. reset the driver.
+Use with care!  From version 4.8.0 onwards, if devices can't
+be removed because uninterruptible processess are waiting for
+I/O to return from them, adding --force will replace the table 
+with one that fails all I/O, which might allow the 
+process to be killed.  This also runs \fBmknodes\fP afterwards.
+.IP \fBrename
+.I device_name new_name
+.br
+Renames a device.
+.IP \fBresume
+.I device_name
+.br
+Un-suspends a device.  
+If an inactive table has been loaded, it becomes live.
+Postponed I/O then gets re-queued for processing.
+.IP \fBsetgeometry
+.I device_name cyl head sect start
+.br
+Sets the device geometry to C/H/S.
+.IP \fBstatus
+.I [--target target_type]
+.I [device_name]
+.br
+Outputs status information for each of the device's targets.
+With --target, only information relating to the specified target type
+is displayed.
+.IP \fBsuspend
+.I [--nolockfs] [--noflush]
+.I device_name
+.br
+Suspends a device.  Any I/O that has already been mapped by the device
+but has not yet completed will be flushed.  Any further I/O to that
+device will be postponed for as long as the device is suspended.
+If there's a filesystem on the device which supports the operation, 
+an attempt will be made to sync it first unless --nolockfs is specified.
+Some targets such as recent (October 2006) versions of multipath may support
+the --noflush option.  This lets outstanding I/O that has not yet reached the
+device to remain unflushed.
+.IP \fBtable
+.I [--target target_type]
+.I [device_name]
+.br
+Outputs the current table for the device in a format that can be fed
+back in using the create or load commands.
+With --target, only information relating to the specified target type
+is displayed.
+.IP \fBtargets
+.br
+Displays the names and versions of the currently-loaded targets.
+.IP \fBversion
+.br
+Outputs version information.
+.IP \fBwait
+.I device_name
+.I [event_nr]
+.br
+Sleeps until the event counter for device_name exceeds event_nr.
+Use -v to see the event number returned.
+To wait until the next event is triggered, use \fBinfo\fP to find
+the last event number.  
+.SH TABLE FORMAT
+Each line of the table specifies a single target and is of the form:
+.br
+    logical_start_sector num_sectors target_type target_args
+.br
+.br
+
+There are currently three simple target types available together 
+with more complex optional ones that implement snapshots and mirrors.
+
+.IP \fBlinear
+.I destination_device start_sector
+.br
+The traditional linear mapping.
+
+.IP \fBstriped
+.I num_stripes chunk_size [destination start_sector]+
+.br
+Creates a striped area.
+.br
+e.g. striped 2 32 /dev/hda1 0 /dev/hdb1 0
+will map the first chunk (16k) as follows:
+.br
+    LV chunk 1 -> hda1, chunk 1
+.br
+    LV chunk 2 -> hdb1, chunk 1
+.br
+    LV chunk 3 -> hda1, chunk 2
+.br
+    LV chunk 4 -> hdb1, chunk 2
+.br
+    etc.
+
+.IP \fBerror
+.br
+Errors any I/O that goes to this area.  Useful for testing or
+for creating devices with holes in them.
+
+.SH EXAMPLES
+
+# A table to join two disks together
+.br
+.br
+0 1028160 linear /dev/hda 0
+.br
+1028160 3903762 linear /dev/hdb 0
+
+
+# A table to stripe across the two disks, 
+.br
+# and add the spare space from
+.br
+# hdb to the back of the volume
+
+0 2056320 striped 2 32 /dev/hda 0 /dev/hdb 0
+.br
+2056320 2875602 linear /dev/hdb 1028160
+
+.SH ENVIRONMENT VARIABLES
+.TP
+\fBDM_DEV_DIR\fP
+The device directory name.
+Defaults to "/dev" and must be an absolute path.
+
+.SH AUTHORS
+Original version: Joe Thornber (thornber@sistina.com)
+
+.SH SEE ALSO
+Device-mapper resource page: http://sources.redhat.com/dm/
Index: src/external/gpl2/lvm2tools/dist/man/fsadm.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/fsadm.8
diff -N src/external/gpl2/lvm2tools/dist/man/fsadm.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/fsadm.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,58 @@
+.\"	$NetBSD$
+.\"
+.TH "FSADM" "8" "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Red Hat, Inc" "\""
+.SH "NAME"
+fsadm \- utility to resize or check filesystem on a device
+.SH "SYNOPSIS"
+.B fsdam
+.RI [options]\ check\ device
+
+.B fsdam
+.RI [options]\ resize\ device\ [new_size[BKMGTEP]]
+
+.SH "DESCRIPTION"
+\fBfsadm\fR utility resizes or checks the filesystem on a device. It tries to use the same API for \fBExt2/3\fR, \fBReiserFS\fR and \fBXFS\fR filesystem and simply resize and filesystem check operation.
+.SH "OPTIONS"
+.TP 
+\fB\-h \-\-help\fR
+\(em print help message
+.TP 
+\fB\-v \-\-verbose\fR
+\(em be more verbose
+.TP 
+\fB\-e \-\-ext\-offline\fR
+\(em unmount Ext2/3 filesystem before doing resize
+.TP 
+\fB\-f \-\-force\fR
+\(em bypass some sanity checks
+.TP 
+\fB\-n \-\-dry\-run\fR
+\(em print commands without running them
+.TP 
+\fB\-y \-\-yes\fR
+\(em answer "yes" at any prompts
+.TP  
+\fBnew_size\fR
+\(em Absolute number of filesystem blocks to be in the filesystem, or an absolute size using a suffix (in powers of 1024). If new_size is not supplied, the whole device is used.
+
+
+.SH "EXAMPLES"
+"fsadm \-e \-y resize /dev/vg/test 1000M" tries to resize the size of the filesystem on logical volume /dev/vg/test. If /dev/vg/test contains Ext2/3 filesystem it will be unmounted prior the resize. All [y|n] questions will be answered 'y'.
+.SH "ENVIRONMENT VARIABLES"
+.TP 
+\fBTMPDIR\fP 
+Where the temporary directory should be created.
+.TP 
+.BR 
+.SH "SEE ALSO"
+.BR lvm (8), 
+.BR lvresize (8), 
+.BR lvm.conf (5),
+.BR tune2fs (8),
+.BR resize2fs (8),
+.BR reiserfstune (8),
+.BR resize_reiserfs (8),
+.BR xfs_info (8),
+.BR xfs_growfs (8),
+.BR xfs_check (8)
+
Index: src/external/gpl2/lvm2tools/dist/man/fsadm.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/fsadm.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/fsadm.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/fsadm.8.in	12 Dec 2008 16:33:01 -0000	1.1.1.1.2.2
@@ -0,0 +1,56 @@
+.TH "FSADM" "8" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
+.SH "NAME"
+fsadm \- utility to resize or check filesystem on a device
+.SH "SYNOPSIS"
+.B fsdam
+.RI [options]\ check\ device
+
+.B fsdam
+.RI [options]\ resize\ device\ [new_size[BKMGTEP]]
+
+.SH "DESCRIPTION"
+\fBfsadm\fR utility resizes or checks the filesystem on a device. It tries to use the same API for \fBExt2/3\fR, \fBReiserFS\fR and \fBXFS\fR filesystem and simply resize and filesystem check operation.
+.SH "OPTIONS"
+.TP 
+\fB\-h \-\-help\fR
+\(em print help message
+.TP 
+\fB\-v \-\-verbose\fR
+\(em be more verbose
+.TP 
+\fB\-e \-\-ext\-offline\fR
+\(em unmount Ext2/3 filesystem before doing resize
+.TP 
+\fB\-f \-\-force\fR
+\(em bypass some sanity checks
+.TP 
+\fB\-n \-\-dry\-run\fR
+\(em print commands without running them
+.TP 
+\fB\-y \-\-yes\fR
+\(em answer "yes" at any prompts
+.TP  
+\fBnew_size\fR
+\(em Absolute number of filesystem blocks to be in the filesystem, or an absolute size using a suffix (in powers of 1024). If new_size is not supplied, the whole device is used.
+
+
+.SH "EXAMPLES"
+"fsadm \-e \-y resize /dev/vg/test 1000M" tries to resize the size of the filesystem on logical volume /dev/vg/test. If /dev/vg/test contains Ext2/3 filesystem it will be unmounted prior the resize. All [y|n] questions will be answered 'y'.
+.SH "ENVIRONMENT VARIABLES"
+.TP 
+\fBTMPDIR\fP 
+Where the temporary directory should be created.
+.TP 
+.BR 
+.SH "SEE ALSO"
+.BR lvm (8), 
+.BR lvresize (8), 
+.BR lvm.conf (5),
+.BR tune2fs (8),
+.BR resize2fs (8),
+.BR reiserfstune (8),
+.BR resize_reiserfs (8),
+.BR xfs_info (8),
+.BR xfs_growfs (8),
+.BR xfs_check (8)
+
Index: src/external/gpl2/lvm2tools/dist/man/lvchange.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvchange.8
diff -N src/external/gpl2/lvm2tools/dist/man/lvchange.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvchange.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,97 @@
+.\"	$NetBSD$
+.\"
+.TH LVCHANGE 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvchange \- change attributes of a logical volume
+.SH SYNOPSIS
+.B lvchange
+[\-\-addtag Tag]
+[\-A/\-\-autobackup y/n] [\-a/\-\-available y/n/ey/en/ly/ln]
+[\-\-alloc AllocationPolicy]
+[\-C/\-\-contiguous y/n] [\-d/\-\-debug] [\-\-deltag Tag]
+[\-\-resync]
+[\-h/\-?/\-\-help]
+[\-\-ignorelockingfailure]
+[\-\-ignoremonitoring]
+[\-\-monitor {y|n}]
+[\-M/\-\-persistent y/n] [\-\-minor minor]
+[\-P/\-\-partial]
+[\-p/\-\-permission r|rw] [\-r/\-\-readahead ReadAheadSectors|auto|none]
+[\-\-refresh]
+[\-t/\-\-test]
+[\-v/\-\-verbose] LogicalVolumePath [LogicalVolumePath...]
+.SH DESCRIPTION
+lvchange allows you to change the attributes of a logical volume
+including making them known to the kernel ready for use.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-a, \-\-available y/n/ey/en/ly/ln
+Controls the availability of the logical volumes for use.
+Communicates with the kernel device-mapper driver via
+libdevmapper to activate (-ay) or deactivate (-an) the 
+logical volumes.
+.IP
+If clustered locking is enabled, -aey will activate exclusively
+on one node and -aly will activate only on the local node.
+To deactivate only on the local node use -aln.
+Logical volumes with single-host snapshots are always activated 
+exclusively because they can only be used on one node at once.
+.TP
+.I \-C, \-\-contiguous y/n
+Tries to set or reset the contiguous allocation policy for
+logical volumes. It's only possible to change a non-contiguous
+logical volume's allocation policy to contiguous, if all of the
+allocated physical extents are already contiguous.
+.TP
+.I \-\-resync
+Forces the complete resynchronization of a mirror.  In normal
+circumstances you should not need this option because synchronization
+happens automatically.  Data is read from the primary mirror device
+and copied to the others, so this can take a considerable amount of
+time - and during this time you are without a complete redundant copy
+of your data.
+.TP
+.I \-\-minor minor
+Set the minor number.
+.TP
+.I \-\-monitor y/n
+Controls whether or not a mirrored logical volume is monitored by
+dmeventd, if it is installed.
+If a device used by a monitored mirror reports an I/O error,
+the failure is handled according to 
+\fBmirror_image_fault_policy\fP and \fBmirror_log_fault_policy\fP
+set in \fBlvm.conf\fP.
+.TP
+.I \-\-ignoremonitoring
+Make no attempt to interact with dmeventd unless \-\-monitor
+is specified.
+Do not use this if dmeventd is already monitoring a device.
+.TP
+.I \-M, \-\-persistent y/n
+Set to y to make the minor number specified persistent.
+.TP
+.I \-p, \-\-permission r|rw
+Change access permission to read-only or read/write.
+.TP
+.I \-r, \-\-readahead ReadAheadSectors|auto|none
+Set read ahead sector count of this logical volume.
+For volume groups with metadata in lvm1 format, this must
+be a value between 2 and 120 sectors.
+The default value is "auto" which allows the kernel to choose
+a suitable value automatically.
+"None" is equivalent to specifying zero.
+.TP
+.I \-\-refresh
+If the logical volume is active, reload its metadata.
+This is not necessary in normal operation, but may be useful
+if something has gone wrong or if you're doing clustering 
+manually without a clustered lock manager.
+.SH Examples
+"lvchange -pr vg00/lvol1" changes the permission on 
+volume lvol1 in volume group vg00 to be read-only.
+
+.SH SEE ALSO
+.BR lvm (8), 
+.BR lvcreate (8),
+.BR vgchange (8)
Index: src/external/gpl2/lvm2tools/dist/man/lvchange.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvchange.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/lvchange.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvchange.8.in	12 Dec 2008 16:33:01 -0000	1.1.1.1.2.2
@@ -0,0 +1,95 @@
+.TH LVCHANGE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvchange \- change attributes of a logical volume
+.SH SYNOPSIS
+.B lvchange
+[\-\-addtag Tag]
+[\-A/\-\-autobackup y/n] [\-a/\-\-available y/n/ey/en/ly/ln]
+[\-\-alloc AllocationPolicy]
+[\-C/\-\-contiguous y/n] [\-d/\-\-debug] [\-\-deltag Tag]
+[\-\-resync]
+[\-h/\-?/\-\-help]
+[\-\-ignorelockingfailure]
+[\-\-ignoremonitoring]
+[\-\-monitor {y|n}]
+[\-M/\-\-persistent y/n] [\-\-minor minor]
+[\-P/\-\-partial]
+[\-p/\-\-permission r|rw] [\-r/\-\-readahead ReadAheadSectors|auto|none]
+[\-\-refresh]
+[\-t/\-\-test]
+[\-v/\-\-verbose] LogicalVolumePath [LogicalVolumePath...]
+.SH DESCRIPTION
+lvchange allows you to change the attributes of a logical volume
+including making them known to the kernel ready for use.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-a, \-\-available y/n/ey/en/ly/ln
+Controls the availability of the logical volumes for use.
+Communicates with the kernel device-mapper driver via
+libdevmapper to activate (-ay) or deactivate (-an) the 
+logical volumes.
+.IP
+If clustered locking is enabled, -aey will activate exclusively
+on one node and -aly will activate only on the local node.
+To deactivate only on the local node use -aln.
+Logical volumes with single-host snapshots are always activated 
+exclusively because they can only be used on one node at once.
+.TP
+.I \-C, \-\-contiguous y/n
+Tries to set or reset the contiguous allocation policy for
+logical volumes. It's only possible to change a non-contiguous
+logical volume's allocation policy to contiguous, if all of the
+allocated physical extents are already contiguous.
+.TP
+.I \-\-resync
+Forces the complete resynchronization of a mirror.  In normal
+circumstances you should not need this option because synchronization
+happens automatically.  Data is read from the primary mirror device
+and copied to the others, so this can take a considerable amount of
+time - and during this time you are without a complete redundant copy
+of your data.
+.TP
+.I \-\-minor minor
+Set the minor number.
+.TP
+.I \-\-monitor y/n
+Controls whether or not a mirrored logical volume is monitored by
+dmeventd, if it is installed.
+If a device used by a monitored mirror reports an I/O error,
+the failure is handled according to 
+\fBmirror_image_fault_policy\fP and \fBmirror_log_fault_policy\fP
+set in \fBlvm.conf\fP.
+.TP
+.I \-\-ignoremonitoring
+Make no attempt to interact with dmeventd unless \-\-monitor
+is specified.
+Do not use this if dmeventd is already monitoring a device.
+.TP
+.I \-M, \-\-persistent y/n
+Set to y to make the minor number specified persistent.
+.TP
+.I \-p, \-\-permission r|rw
+Change access permission to read-only or read/write.
+.TP
+.I \-r, \-\-readahead ReadAheadSectors|auto|none
+Set read ahead sector count of this logical volume.
+For volume groups with metadata in lvm1 format, this must
+be a value between 2 and 120 sectors.
+The default value is "auto" which allows the kernel to choose
+a suitable value automatically.
+"None" is equivalent to specifying zero.
+.TP
+.I \-\-refresh
+If the logical volume is active, reload its metadata.
+This is not necessary in normal operation, but may be useful
+if something has gone wrong or if you're doing clustering 
+manually without a clustered lock manager.
+.SH Examples
+"lvchange -pr vg00/lvol1" changes the permission on 
+volume lvol1 in volume group vg00 to be read-only.
+
+.SH SEE ALSO
+.BR lvm (8), 
+.BR lvcreate (8),
+.BR vgchange (8)
Index: src/external/gpl2/lvm2tools/dist/man/lvconvert.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvconvert.8
diff -N src/external/gpl2/lvm2tools/dist/man/lvconvert.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvconvert.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,112 @@
+.\"	$NetBSD$
+.\"
+.TH LVCONVERT 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Red Hat, Inc" \" -*- nroff -*-
+.SH NAME
+lvconvert \- convert a logical volume from linear to mirror or snapshot
+.SH SYNOPSIS
+.B lvconvert
+\-m/\-\-mirrors Mirrors [\-\-mirrorlog {disk|core}] [\-\-corelog] [\-R/\-\-regionsize MirrorLogRegionSize]
+[\-A/\-\-alloc AllocationPolicy]
+[\-b/\-\-background] [\-i/\-\-interval Seconds]
+[\-h/\-?/\-\-help]
+[\-v/\-\-verbose]
+[\-\-version]
+.br
+LogicalVolume[Path] [PhysicalVolume[Path]...]
+.br
+
+.br
+.B lvconvert
+\-s/\-\-snapshot [\-c/\-\-chunksize ChunkSize]
+[\-h/\-?/\-\-help]
+[\-v/\-\-verbose]
+[\-Z/\-\-zero y/n]
+[\-\-version]
+.br
+OriginalLogicalVolume[Path] SnapshotLogicalVolume[Path]
+.SH DESCRIPTION
+lvconvert will change a linear logical volume to a mirror
+logical volume or to a snapshot of linear volume and vice versa.
+It is also used to add and remove disk logs from mirror devices.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.br
+Exactly one of \-\-mirrors or \-\-snapshot arguments required.
+.br
+.TP
+.I \-m, \-\-mirrors Mirrors
+Specifies the degree of the mirror you wish to create.
+For example, "-m 1" would convert the original logical
+volume to a mirror volume with 2-sides; that is, a
+linear volume plus one copy.
+.TP
+.I \-\-mirrorlog {disk|core}
+Specifies the type of log to use.
+The default is disk, which is persistent and requires
+a small amount of storage space, usually on a separate device
+from the data being mirrored. 
+Core may be useful for short-lived mirrors: It means the mirror is
+regenerated by copying the data from the first device again every
+time the device is activated - perhaps, for example, after every reboot.
+.TP
+.I \-\-corelog
+The optional argument "--corelog" is the same as specifying "--mirrorlog core".
+.TP
+.I \-R, \-\-regionsize MirrorLogRegionSize
+A mirror is divided into regions of this size (in MB), and the mirror log
+uses this granularity to track which regions are in sync.
+.TP
+.I \-b, \-\-background
+Run the daemon in the background.
+.TP
+.I \-i, \-\-interval Seconds
+Report progress as a percentage at regular intervals.
+.br
+.TP
+.I \-s, \-\-snapshot
+Create a snapshot from existing logical volume using another
+existing logical volume as its origin.
+.TP
+.I \-c, \-\-chunksize ChunkSize
+Power of 2 chunk size for the snapshot logical volume between 4k and 512k.
+.TP
+.I \-Z, \-\-zero y/n
+Controls zeroing of the first KB of data in the snapshot.
+If the volume is read-only the snapshot will not be zeroed.
+.br
+.SH Examples
+"lvconvert -m1 vg00/lvol1"
+.br
+converts the linear logical volume "vg00/lvol1" to
+a two-way mirror logical volume.
+
+"lvconvert --mirrorlog core vg00/lvol1"
+.br
+converts a mirror with a disk log to a
+mirror with an in-memory log.
+
+"lvconvert --mirrorlog disk vg00/lvol1"
+.br
+converts a mirror with an in-memory log
+to a mirror with a disk log.
+
+"lvconvert -m0 vg00/lvol1"
+.br
+converts a mirror logical volume to a linear logical
+volume.
+.br
+
+.br
+"lvconvert -s vg00/lvol1 vg00/lvol2"
+.br
+converts logical volume "vg00/lvol2" to snapshot of original volume "vg00/lvol1"
+
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgcreate (8),
+.BR lvremove (8),
+.BR lvrename (8),
+.BR lvextend (8),
+.BR lvreduce (8),
+.BR lvdisplay (8),
+.BR lvscan (8)
Index: src/external/gpl2/lvm2tools/dist/man/lvconvert.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvconvert.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/lvconvert.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvconvert.8.in	12 Dec 2008 16:33:01 -0000	1.1.1.1.2.2
@@ -0,0 +1,110 @@
+.TH LVCONVERT 8 "LVM TOOLS #VERSION#" "Red Hat, Inc" \" -*- nroff -*-
+.SH NAME
+lvconvert \- convert a logical volume from linear to mirror or snapshot
+.SH SYNOPSIS
+.B lvconvert
+\-m/\-\-mirrors Mirrors [\-\-mirrorlog {disk|core}] [\-\-corelog] [\-R/\-\-regionsize MirrorLogRegionSize]
+[\-A/\-\-alloc AllocationPolicy]
+[\-b/\-\-background] [\-i/\-\-interval Seconds]
+[\-h/\-?/\-\-help]
+[\-v/\-\-verbose]
+[\-\-version]
+.br
+LogicalVolume[Path] [PhysicalVolume[Path]...]
+.br
+
+.br
+.B lvconvert
+\-s/\-\-snapshot [\-c/\-\-chunksize ChunkSize]
+[\-h/\-?/\-\-help]
+[\-v/\-\-verbose]
+[\-Z/\-\-zero y/n]
+[\-\-version]
+.br
+OriginalLogicalVolume[Path] SnapshotLogicalVolume[Path]
+.SH DESCRIPTION
+lvconvert will change a linear logical volume to a mirror
+logical volume or to a snapshot of linear volume and vice versa.
+It is also used to add and remove disk logs from mirror devices.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.br
+Exactly one of \-\-mirrors or \-\-snapshot arguments required.
+.br
+.TP
+.I \-m, \-\-mirrors Mirrors
+Specifies the degree of the mirror you wish to create.
+For example, "-m 1" would convert the original logical
+volume to a mirror volume with 2-sides; that is, a
+linear volume plus one copy.
+.TP
+.I \-\-mirrorlog {disk|core}
+Specifies the type of log to use.
+The default is disk, which is persistent and requires
+a small amount of storage space, usually on a separate device
+from the data being mirrored. 
+Core may be useful for short-lived mirrors: It means the mirror is
+regenerated by copying the data from the first device again every
+time the device is activated - perhaps, for example, after every reboot.
+.TP
+.I \-\-corelog
+The optional argument "--corelog" is the same as specifying "--mirrorlog core".
+.TP
+.I \-R, \-\-regionsize MirrorLogRegionSize
+A mirror is divided into regions of this size (in MB), and the mirror log
+uses this granularity to track which regions are in sync.
+.TP
+.I \-b, \-\-background
+Run the daemon in the background.
+.TP
+.I \-i, \-\-interval Seconds
+Report progress as a percentage at regular intervals.
+.br
+.TP
+.I \-s, \-\-snapshot
+Create a snapshot from existing logical volume using another
+existing logical volume as its origin.
+.TP
+.I \-c, \-\-chunksize ChunkSize
+Power of 2 chunk size for the snapshot logical volume between 4k and 512k.
+.TP
+.I \-Z, \-\-zero y/n
+Controls zeroing of the first KB of data in the snapshot.
+If the volume is read-only the snapshot will not be zeroed.
+.br
+.SH Examples
+"lvconvert -m1 vg00/lvol1"
+.br
+converts the linear logical volume "vg00/lvol1" to
+a two-way mirror logical volume.
+
+"lvconvert --mirrorlog core vg00/lvol1"
+.br
+converts a mirror with a disk log to a
+mirror with an in-memory log.
+
+"lvconvert --mirrorlog disk vg00/lvol1"
+.br
+converts a mirror with an in-memory log
+to a mirror with a disk log.
+
+"lvconvert -m0 vg00/lvol1"
+.br
+converts a mirror logical volume to a linear logical
+volume.
+.br
+
+.br
+"lvconvert -s vg00/lvol1 vg00/lvol2"
+.br
+converts logical volume "vg00/lvol2" to snapshot of original volume "vg00/lvol1"
+
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgcreate (8),
+.BR lvremove (8),
+.BR lvrename (8),
+.BR lvextend (8),
+.BR lvreduce (8),
+.BR lvdisplay (8),
+.BR lvscan (8)
Index: src/external/gpl2/lvm2tools/dist/man/lvcreate.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvcreate.8
diff -N src/external/gpl2/lvm2tools/dist/man/lvcreate.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvcreate.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,193 @@
+.\"	$NetBSD$
+.\"
+.TH LVCREATE 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvcreate \- create a logical volume in an existing volume group
+.SH SYNOPSIS
+.B lvcreate
+[\-\-addtag Tag]
+[\-\-alloc AllocationPolicy]
+[\-A/\-\-autobackup y/n] [\-C/\-\-contiguous y/n] [\-d/\-\-debug]
+[\-h/\-?/\-\-help]
+[\-i/\-\-stripes Stripes [\-I/\-\-stripesize StripeSize]]
+{\-l/\-\-extents LogicalExtentsNumber[%{VG|PVS|FREE}] |
+ \-L/\-\-size LogicalVolumeSize[kKmMgGtT]}
+[\-M/\-\-persistent y/n] [\-\-minor minor]
+[\-m/\-\-mirrors Mirrors [\-\-nosync] [\-\-mirrorlog {disk|core}] [\-\-corelog]
+[\-R/\-\-regionsize MirrorLogRegionSize]]
+[\-n/\-\-name LogicalVolumeName]
+[\-p/\-\-permission r|rw] [\-r/\-\-readahead ReadAheadSectors|auto|none]
+[\-t/\-\-test]
+[\-v/\-\-verbose] [\-Z/\-\-zero y/n]
+VolumeGroupName [PhysicalVolumePath...]
+.br
+
+.br
+.B lvcreate
+{\-l/\-\-extents LogicalExtentsNumber[%{VG|FREE}] |
+ \-L/\-\-size LogicalVolumeSize[kKmMgGtT]}
+[\-c/\-\-chunksize ChunkSize]
+\-s/\-\-snapshot \-n/\-\-name SnapshotLogicalVolumeName OriginalLogicalVolumePath
+.SH DESCRIPTION
+lvcreate creates a new logical volume in a volume group ( see
+.B vgcreate(8), vgchange(8)
+) by allocating logical extents from the free physical extent pool
+of that volume group.  If there are not enough free physical extents then
+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)
+).
+.br
+The second form supports the creation of snapshot logical volumes which 
+keep the contents of the original logical volume for backup purposes.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-c, \-\-chunksize ChunkSize
+Power of 2 chunk size for the snapshot logical volume between 4k and 512k.
+.TP
+.I \-C, \-\-contiguous y/n
+Sets or resets the contiguous allocation policy for
+logical volumes. Default is no contiguous allocation based
+on a next free principle.
+.TP
+.I \-i, \-\-stripes Stripes
+Gives the number of stripes.
+This is equal to the number of physical volumes to scatter
+the logical volume.
+.TP
+.I \-I, \-\-stripesize StripeSize
+Gives the number of kilobytes for the granularity of the stripes.
+.br
+StripeSize must be 2^n (n = 2 to 9) for metadata in LVM1 format.
+For metadata in LVM2 format, the stripe size may be a larger
+power of 2 but must not exceed the physical extent size.
+.TP
+.I \-l, \-\-extents LogicalExtentsNumber[%{VG|PVS|FREE}]
+Gives the number of logical extents to allocate for the new
+logical volume.
+This can also be expressed as a percentage of the total space
+in the Volume Group with the suffix %VG, of the remaining
+free space in the Volume Group with the suffix %FREE, or
+of the remaining free space for the specified PhysicalVolume(s)
+with the suffix %PVS,
+.TP
+.I \-L, \-\-size LogicalVolumeSize[kKmMgGtTpPeE]
+Gives the size to allocate for the new logical volume.
+A size suffix of K for kilobytes, M for megabytes,
+G for gigabytes, T for terabytes, P for petabytes
+or E for exabytes is optional.
+.br
+Default unit is megabytes.
+.TP
+.I \-\-minor minor
+Set the minor number.
+.TP
+.I \-M, \-\-persistent y/n
+Set to y to make the minor number specified persistent.
+.TP
+.I \-m, \-\-mirrors Mirrors
+Creates a mirrored logical volume with Mirrors copies.  For example,
+specifying "-m 1" would result in a mirror with two-sides; that is, a
+linear volume plus one copy.
+
+Specifying the optional argument --nosync will cause the creation
+of the mirror to skip the initial resynchronization.  Any data written
+afterwards will be mirrored, but the original contents will not be
+copied.  This is useful for skipping a potentially long and resource
+intensive initial sync of an empty device.
+
+The optional argument --mirrorlog specifies the type of log to be used.
+The default is disk, which is persistent and requires
+a small amount of storage space, usually on a separate device from the
+data being mirrored. Using core means the mirror is regenerated
+by copying the data from the first device again each time the
+device is activated, for example, after every reboot.
+
+The optional argument --corelog is equivalent to --mirrorlog core.
+
+.TP
+.I \-n, \-\-name LogicalVolumeName
+The name for the new logical volume.
+.br
+Without this option a default names of "lvol#" will be generated where
+# is the LVM internal number of the logical volume.
+.TP
+.I \-p, \-\-permission r|rw
+Set access permissions to read only or read and write.
+.br
+Default is read and write.
+.TP
+.I \-r, \-\-readahead ReadAheadSectors|auto|none
+Set read ahead sector count of this logical volume.
+For volume groups with metadata in lvm1 format, this must
+be a value between 2 and 120.
+The default value is "auto" which allows the kernel to choose
+a suitable value automatically.
+"None" is equivalent to specifying zero.
+.TP
+.I \-R, \-\-regionsize MirrorLogRegionSize
+A mirror is divided into regions of this size (in MB), and the mirror log 
+uses this granularity to track which regions are in sync.
+.TP
+.I \-s, \-\-snapshot
+Create a snapshot logical volume (or snapshot) for an existing, so called
+original logical volume (or origin).
+Snapshots provide a 'frozen image' of the contents of the origin
+while the origin can still be updated. They enable consistent
+backups and online recovery of removed/overwritten data/files. The snapshot
+does not need the same amount of storage the origin has. In a typical scenario,
+15-20% might be enough. In case the snapshot runs out of storage, use
+.B lvextend(8)
+to grow it. Shrinking a snapshot is supported by
+.B lvreduce(8)
+as well. Run
+.B lvdisplay(8)
+on the snapshot in order to check how much data is allocated to it.
+.TP
+.I \-Z, \-\-zero y/n
+Controls zeroing of the first KB of data in the new logical volume.
+.br
+Default is yes.
+.br
+Volume will not be zeroed if read only flag is set.
+.br
+Snapshot volumes are zeroed always.
+
+.br
+Warning: trying to mount an unzeroed logical volume can cause the system to
+hang.
+.SH Examples
+"lvcreate -i 3 -I 8 -L 100M vg00" tries to create a striped logical
+volume with 3 stripes, a stripesize of 8KB and a size of 100MB in the volume
+group named vg00. The logical volume name will be chosen by lvcreate.
+
+"lvcreate -m1 -L 500M vg00" tries to create a mirror logical volume
+with 2 sides with a useable size of 500 MiB.  This operation would
+require 3 devices - two for the mirror devices and one for the disk
+log.
+
+"lvcreate -m1 --mirrorlog core -L 500M vg00" tries to create a mirror logical volume
+with 2 sides with a useable size of 500 MiB.  This operation would
+require 2 devices - the log is "in-memory".
+
+"lvcreate --size 100m --snapshot --name snap /dev/vg00/lvol1"
+.br
+creates a snapshot logical volume named /dev/vg00/snap which has access to the
+contents of the original logical volume named /dev/vg00/lvol1
+at snapshot logical volume creation time. If the original logical volume
+contains a file system, you can mount the snapshot logical volume on an
+arbitrary directory in order to access the contents of the filesystem to run
+a backup while the original filesystem continues to get updated.
+
+.SH SEE ALSO
+.BR lvm (8), 
+.BR vgcreate (8), 
+.BR lvremove (8), 
+.BR lvrename (8)
+.BR lvextend (8), 
+.BR lvreduce (8), 
+.BR lvdisplay (8), 
+.BR lvscan (8)
Index: src/external/gpl2/lvm2tools/dist/man/lvcreate.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvcreate.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/lvcreate.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvcreate.8.in	12 Dec 2008 16:33:01 -0000	1.1.1.1.2.2
@@ -0,0 +1,191 @@
+.TH LVCREATE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvcreate \- create a logical volume in an existing volume group
+.SH SYNOPSIS
+.B lvcreate
+[\-\-addtag Tag]
+[\-\-alloc AllocationPolicy]
+[\-A/\-\-autobackup y/n] [\-C/\-\-contiguous y/n] [\-d/\-\-debug]
+[\-h/\-?/\-\-help]
+[\-i/\-\-stripes Stripes [\-I/\-\-stripesize StripeSize]]
+{\-l/\-\-extents LogicalExtentsNumber[%{VG|PVS|FREE}] |
+ \-L/\-\-size LogicalVolumeSize[kKmMgGtT]}
+[\-M/\-\-persistent y/n] [\-\-minor minor]
+[\-m/\-\-mirrors Mirrors [\-\-nosync] [\-\-mirrorlog {disk|core}] [\-\-corelog]
+[\-R/\-\-regionsize MirrorLogRegionSize]]
+[\-n/\-\-name LogicalVolumeName]
+[\-p/\-\-permission r|rw] [\-r/\-\-readahead ReadAheadSectors|auto|none]
+[\-t/\-\-test]
+[\-v/\-\-verbose] [\-Z/\-\-zero y/n]
+VolumeGroupName [PhysicalVolumePath...]
+.br
+
+.br
+.B lvcreate
+{\-l/\-\-extents LogicalExtentsNumber[%{VG|FREE}] |
+ \-L/\-\-size LogicalVolumeSize[kKmMgGtT]}
+[\-c/\-\-chunksize ChunkSize]
+\-s/\-\-snapshot \-n/\-\-name SnapshotLogicalVolumeName OriginalLogicalVolumePath
+.SH DESCRIPTION
+lvcreate creates a new logical volume in a volume group ( see
+.B vgcreate(8), vgchange(8)
+) by allocating logical extents from the free physical extent pool
+of that volume group.  If there are not enough free physical extents then
+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)
+).
+.br
+The second form supports the creation of snapshot logical volumes which 
+keep the contents of the original logical volume for backup purposes.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-c, \-\-chunksize ChunkSize
+Power of 2 chunk size for the snapshot logical volume between 4k and 512k.
+.TP
+.I \-C, \-\-contiguous y/n
+Sets or resets the contiguous allocation policy for
+logical volumes. Default is no contiguous allocation based
+on a next free principle.
+.TP
+.I \-i, \-\-stripes Stripes
+Gives the number of stripes.
+This is equal to the number of physical volumes to scatter
+the logical volume.
+.TP
+.I \-I, \-\-stripesize StripeSize
+Gives the number of kilobytes for the granularity of the stripes.
+.br
+StripeSize must be 2^n (n = 2 to 9) for metadata in LVM1 format.
+For metadata in LVM2 format, the stripe size may be a larger
+power of 2 but must not exceed the physical extent size.
+.TP
+.I \-l, \-\-extents LogicalExtentsNumber[%{VG|PVS|FREE}]
+Gives the number of logical extents to allocate for the new
+logical volume.
+This can also be expressed as a percentage of the total space
+in the Volume Group with the suffix %VG, of the remaining
+free space in the Volume Group with the suffix %FREE, or
+of the remaining free space for the specified PhysicalVolume(s)
+with the suffix %PVS,
+.TP
+.I \-L, \-\-size LogicalVolumeSize[kKmMgGtTpPeE]
+Gives the size to allocate for the new logical volume.
+A size suffix of K for kilobytes, M for megabytes,
+G for gigabytes, T for terabytes, P for petabytes
+or E for exabytes is optional.
+.br
+Default unit is megabytes.
+.TP
+.I \-\-minor minor
+Set the minor number.
+.TP
+.I \-M, \-\-persistent y/n
+Set to y to make the minor number specified persistent.
+.TP
+.I \-m, \-\-mirrors Mirrors
+Creates a mirrored logical volume with Mirrors copies.  For example,
+specifying "-m 1" would result in a mirror with two-sides; that is, a
+linear volume plus one copy.
+
+Specifying the optional argument --nosync will cause the creation
+of the mirror to skip the initial resynchronization.  Any data written
+afterwards will be mirrored, but the original contents will not be
+copied.  This is useful for skipping a potentially long and resource
+intensive initial sync of an empty device.
+
+The optional argument --mirrorlog specifies the type of log to be used.
+The default is disk, which is persistent and requires
+a small amount of storage space, usually on a separate device from the
+data being mirrored. Using core means the mirror is regenerated
+by copying the data from the first device again each time the
+device is activated, for example, after every reboot.
+
+The optional argument --corelog is equivalent to --mirrorlog core.
+
+.TP
+.I \-n, \-\-name LogicalVolumeName
+The name for the new logical volume.
+.br
+Without this option a default names of "lvol#" will be generated where
+# is the LVM internal number of the logical volume.
+.TP
+.I \-p, \-\-permission r|rw
+Set access permissions to read only or read and write.
+.br
+Default is read and write.
+.TP
+.I \-r, \-\-readahead ReadAheadSectors|auto|none
+Set read ahead sector count of this logical volume.
+For volume groups with metadata in lvm1 format, this must
+be a value between 2 and 120.
+The default value is "auto" which allows the kernel to choose
+a suitable value automatically.
+"None" is equivalent to specifying zero.
+.TP
+.I \-R, \-\-regionsize MirrorLogRegionSize
+A mirror is divided into regions of this size (in MB), and the mirror log 
+uses this granularity to track which regions are in sync.
+.TP
+.I \-s, \-\-snapshot
+Create a snapshot logical volume (or snapshot) for an existing, so called
+original logical volume (or origin).
+Snapshots provide a 'frozen image' of the contents of the origin
+while the origin can still be updated. They enable consistent
+backups and online recovery of removed/overwritten data/files. The snapshot
+does not need the same amount of storage the origin has. In a typical scenario,
+15-20% might be enough. In case the snapshot runs out of storage, use
+.B lvextend(8)
+to grow it. Shrinking a snapshot is supported by
+.B lvreduce(8)
+as well. Run
+.B lvdisplay(8)
+on the snapshot in order to check how much data is allocated to it.
+.TP
+.I \-Z, \-\-zero y/n
+Controls zeroing of the first KB of data in the new logical volume.
+.br
+Default is yes.
+.br
+Volume will not be zeroed if read only flag is set.
+.br
+Snapshot volumes are zeroed always.
+
+.br
+Warning: trying to mount an unzeroed logical volume can cause the system to
+hang.
+.SH Examples
+"lvcreate -i 3 -I 8 -L 100M vg00" tries to create a striped logical
+volume with 3 stripes, a stripesize of 8KB and a size of 100MB in the volume
+group named vg00. The logical volume name will be chosen by lvcreate.
+
+"lvcreate -m1 -L 500M vg00" tries to create a mirror logical volume
+with 2 sides with a useable size of 500 MiB.  This operation would
+require 3 devices - two for the mirror devices and one for the disk
+log.
+
+"lvcreate -m1 --mirrorlog core -L 500M vg00" tries to create a mirror logical volume
+with 2 sides with a useable size of 500 MiB.  This operation would
+require 2 devices - the log is "in-memory".
+
+"lvcreate --size 100m --snapshot --name snap /dev/vg00/lvol1"
+.br
+creates a snapshot logical volume named /dev/vg00/snap which has access to the
+contents of the original logical volume named /dev/vg00/lvol1
+at snapshot logical volume creation time. If the original logical volume
+contains a file system, you can mount the snapshot logical volume on an
+arbitrary directory in order to access the contents of the filesystem to run
+a backup while the original filesystem continues to get updated.
+
+.SH SEE ALSO
+.BR lvm (8), 
+.BR vgcreate (8), 
+.BR lvremove (8), 
+.BR lvrename (8)
+.BR lvextend (8), 
+.BR lvreduce (8), 
+.BR lvdisplay (8), 
+.BR lvscan (8)
Index: src/external/gpl2/lvm2tools/dist/man/lvdisplay.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvdisplay.8
diff -N src/external/gpl2/lvm2tools/dist/man/lvdisplay.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvdisplay.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,63 @@
+.\"	$NetBSD$
+.\"
+.TH LVDISPLAY 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvdisplay \- display attributes of a logical volume
+.SH SYNOPSIS
+.B lvdisplay
+[\-c/\-\-colon] [\-d/\-\-debug] [\-h/\-?/\-\-help]
+[\-\-ignorelockingfailure]
+[\-\-maps] [\-P/\-\-partial]
+[\-v/\-\-verbose] LogicalVolumePath [LogicalVolumePath...]
+.SH DESCRIPTION
+lvdisplay allows you to see the attributes of a logical volume
+like size, read/write status, snapshot information etc.
+.P
+\fBlvs\fP (8) is an alternative that provides the same information 
+in the style of \fBps\fP (1).  \fBlvs\fP is recommended over
+\fBlvdisplay\fP.
+
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-c, \-\-colon
+Generate colon separated output for easier parsing in scripts or programs.
+N.B. \fBlvs\fP (8) provides considerably more control over the output.
+.nf
+
+The values are:
+
+* logical volume name
+* volume group name
+* logical volume access
+* logical volume status
+* internal logical volume number
+* open count of logical volume
+* logical volume size in sectors
+* current logical extents associated to logical volume
+* allocated logical extents of logical volume
+* allocation policy of logical volume
+* read ahead sectors of logical volume
+* major device number of logical volume
+* minor device number of logical volume
+
+.fi
+.TP
+.I \-m, \-\-maps
+Display the mapping of logical extents to physical volumes and
+physical extents.
+.SH Examples
+"lvdisplay -v /dev/vg00/lvol2" shows attributes of that logical volume.
+If snapshot
+logical volumes have been created for this original logical volume,
+this command shows a list of all snapshot logical volumes and their
+status (active or inactive) as well.
+
+"lvdisplay /dev/vg00/snapshot" shows the attributes of this snapshot
+logical volume and also which original logical volume
+it is associated with.
+
+.SH SEE ALSO
+.BR lvm (8), 
+.BR lvcreate (8), 
+.BR lvscan (8)
Index: src/external/gpl2/lvm2tools/dist/man/lvdisplay.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvdisplay.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/lvdisplay.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvdisplay.8.in	12 Dec 2008 16:33:01 -0000	1.1.1.1.2.2
@@ -0,0 +1,61 @@
+.TH LVDISPLAY 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvdisplay \- display attributes of a logical volume
+.SH SYNOPSIS
+.B lvdisplay
+[\-c/\-\-colon] [\-d/\-\-debug] [\-h/\-?/\-\-help]
+[\-\-ignorelockingfailure]
+[\-\-maps] [\-P/\-\-partial]
+[\-v/\-\-verbose] LogicalVolumePath [LogicalVolumePath...]
+.SH DESCRIPTION
+lvdisplay allows you to see the attributes of a logical volume
+like size, read/write status, snapshot information etc.
+.P
+\fBlvs\fP (8) is an alternative that provides the same information 
+in the style of \fBps\fP (1).  \fBlvs\fP is recommended over
+\fBlvdisplay\fP.
+
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-c, \-\-colon
+Generate colon separated output for easier parsing in scripts or programs.
+N.B. \fBlvs\fP (8) provides considerably more control over the output.
+.nf
+
+The values are:
+
+* logical volume name
+* volume group name
+* logical volume access
+* logical volume status
+* internal logical volume number
+* open count of logical volume
+* logical volume size in sectors
+* current logical extents associated to logical volume
+* allocated logical extents of logical volume
+* allocation policy of logical volume
+* read ahead sectors of logical volume
+* major device number of logical volume
+* minor device number of logical volume
+
+.fi
+.TP
+.I \-m, \-\-maps
+Display the mapping of logical extents to physical volumes and
+physical extents.
+.SH Examples
+"lvdisplay -v /dev/vg00/lvol2" shows attributes of that logical volume.
+If snapshot
+logical volumes have been created for this original logical volume,
+this command shows a list of all snapshot logical volumes and their
+status (active or inactive) as well.
+
+"lvdisplay /dev/vg00/snapshot" shows the attributes of this snapshot
+logical volume and also which original logical volume
+it is associated with.
+
+.SH SEE ALSO
+.BR lvm (8), 
+.BR lvcreate (8), 
+.BR lvscan (8)
Index: src/external/gpl2/lvm2tools/dist/man/lvextend.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvextend.8
diff -N src/external/gpl2/lvm2tools/dist/man/lvextend.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvextend.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,71 @@
+.\"	$NetBSD$
+.\"
+.TH LVEXTEND 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvextend \- extend the size of a logical volume
+.SH SYNOPSIS
+.B lvextend
+[\-\-alloc AllocationPolicy]
+[\-A/\-\-autobackup y/n] [\-d/\-\-debug] [\-h/\-?/\-\-help]
+[\-i/\-\-stripes Stripes [\-I/\-\-stripesize StripeSize]]
+{\-l/\-\-extents [+]LogicalExtentsNumber[%{VG|LV|PVS|FREE}] |
+\-L/\-\-size [+]LogicalVolumeSize[kKmMgGtT]}
+[\-t/\-\-test]
+[\-v/\-\-verbose] LogicalVolumePath [PhysicalVolumePath...]
+.SH DESCRIPTION
+lvextend allows you to extend the size of a logical volume.
+Extension of snapshot logical volumes (see
+.B lvcreate(8)
+for information to create snapshots) is supported as well.
+But to change the number of copies in a mirrored logical
+volume use 
+.BR lvconvert (8).
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-l, \-\-extents [+]LogicalExtentsNumber[%{VG|LV|PVS|FREE}]
+Extend or set the logical volume size in units of logical extents.
+With the + sign the value is added to the actual size
+of the logical volume and without it, the value is taken as an absolute one.
+The number can also be expressed as a percentage of the total space
+in the Volume Group with the suffix %VG, relative to the existing
+size of the Logical Volume with the suffix %LV, of the remaining
+free space for the specified PhysicalVolume(s) with the suffix %PVS,
+or as a percentage of the remaining free space in the Volume Group
+with the suffix %FREE.
+.TP
+.I \-L, \-\-size [+]LogicalVolumeSize[kKmMgGtTpPeE]
+Extend or set the logical volume size in units of megabytes.
+A size suffix of M for megabytes,
+G for gigabytes, T for terabytes, P for petabytes 
+or E for exabytes is optional.
+With the + sign the value is added to the actual size
+of the logical volume and without it, the value is taken as an absolute one.
+.TP
+.I \-i, \-\-stripes Stripes
+Gives the number of stripes for the extension.
+Not applicable to LVs using the original metadata LVM format, which must
+use a single value throughout.
+.TP
+.I \-I, \-\-stripesize StripeSize
+Gives the number of kilobytes for the granularity of the stripes.
+Not applicable to LVs using the original metadata LVM format, which must
+use a single value throughout.
+.br
+StripeSize must be 2^n (n = 2 to 9)
+.SH Examples
+"lvextend -L +54 /dev/vg01/lvol10 /dev/sdk3" tries to extend the size of
+that logical volume by 54MB on physical volume /dev/sdk3.
+This is only possible if /dev/sdk3 is a member of volume group vg01 and
+there are enough free physical extents in it.
+
+"lvextend /dev/vg01/lvol01 /dev/sdk3" tries to extend the size of that
+logical volume by the amount of free space on physical volume /dev/sdk3.
+This is equivalent to specifying "-l +100%PVS" on the command line.
+.SH SEE ALSO
+.BR lvm (8), 
+.BR lvcreate (8), 
+.BR lvconvert (8), 
+.BR lvreduce (8), 
+.BR lvresize (8), 
+.BR lvchange (8)
Index: src/external/gpl2/lvm2tools/dist/man/lvextend.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvextend.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/lvextend.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvextend.8.in	12 Dec 2008 16:33:01 -0000	1.1.1.1.2.2
@@ -0,0 +1,69 @@
+.TH LVEXTEND 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvextend \- extend the size of a logical volume
+.SH SYNOPSIS
+.B lvextend
+[\-\-alloc AllocationPolicy]
+[\-A/\-\-autobackup y/n] [\-d/\-\-debug] [\-h/\-?/\-\-help]
+[\-i/\-\-stripes Stripes [\-I/\-\-stripesize StripeSize]]
+{\-l/\-\-extents [+]LogicalExtentsNumber[%{VG|LV|PVS|FREE}] |
+\-L/\-\-size [+]LogicalVolumeSize[kKmMgGtT]}
+[\-t/\-\-test]
+[\-v/\-\-verbose] LogicalVolumePath [PhysicalVolumePath...]
+.SH DESCRIPTION
+lvextend allows you to extend the size of a logical volume.
+Extension of snapshot logical volumes (see
+.B lvcreate(8)
+for information to create snapshots) is supported as well.
+But to change the number of copies in a mirrored logical
+volume use 
+.BR lvconvert (8).
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-l, \-\-extents [+]LogicalExtentsNumber[%{VG|LV|PVS|FREE}]
+Extend or set the logical volume size in units of logical extents.
+With the + sign the value is added to the actual size
+of the logical volume and without it, the value is taken as an absolute one.
+The number can also be expressed as a percentage of the total space
+in the Volume Group with the suffix %VG, relative to the existing
+size of the Logical Volume with the suffix %LV, of the remaining
+free space for the specified PhysicalVolume(s) with the suffix %PVS,
+or as a percentage of the remaining free space in the Volume Group
+with the suffix %FREE.
+.TP
+.I \-L, \-\-size [+]LogicalVolumeSize[kKmMgGtTpPeE]
+Extend or set the logical volume size in units of megabytes.
+A size suffix of M for megabytes,
+G for gigabytes, T for terabytes, P for petabytes 
+or E for exabytes is optional.
+With the + sign the value is added to the actual size
+of the logical volume and without it, the value is taken as an absolute one.
+.TP
+.I \-i, \-\-stripes Stripes
+Gives the number of stripes for the extension.
+Not applicable to LVs using the original metadata LVM format, which must
+use a single value throughout.
+.TP
+.I \-I, \-\-stripesize StripeSize
+Gives the number of kilobytes for the granularity of the stripes.
+Not applicable to LVs using the original metadata LVM format, which must
+use a single value throughout.
+.br
+StripeSize must be 2^n (n = 2 to 9)
+.SH Examples
+"lvextend -L +54 /dev/vg01/lvol10 /dev/sdk3" tries to extend the size of
+that logical volume by 54MB on physical volume /dev/sdk3.
+This is only possible if /dev/sdk3 is a member of volume group vg01 and
+there are enough free physical extents in it.
+
+"lvextend /dev/vg01/lvol01 /dev/sdk3" tries to extend the size of that
+logical volume by the amount of free space on physical volume /dev/sdk3.
+This is equivalent to specifying "-l +100%PVS" on the command line.
+.SH SEE ALSO
+.BR lvm (8), 
+.BR lvcreate (8), 
+.BR lvconvert (8), 
+.BR lvreduce (8), 
+.BR lvresize (8), 
+.BR lvchange (8)
Index: src/external/gpl2/lvm2tools/dist/man/lvm.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvm.8
diff -N src/external/gpl2/lvm2tools/dist/man/lvm.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvm.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,318 @@
+.\"	$NetBSD$
+.\"
+.TH LVM 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvm \- LVM2 tools
+.SH SYNOPSIS
+.B lvm
+[command | file]
+.SH DESCRIPTION
+\fBlvm\fP provides the command-line tools for LVM2.  A separate
+manual page describes each command in detail.
+.LP
+If \fBlvm\fP is invoked with no arguments it presents a readline prompt
+(assuming it was compiled with readline support).
+LVM commands may be entered interactively at this prompt with 
+readline facilities including history and command name and option 
+completion.  Refer to \fBreadline\fP(3) for details.
+.LP
+If \fBlvm\fP is invoked with argv[0] set to the name of a specific
+LVM command (for example by using a hard or soft link) it acts as 
+that command.  
+.LP
+Where commands take VG or LV names as arguments, the full path name is
+optional.  An LV called "lvol0" in a VG called "vg0" can be specified
+as "vg0/lvol0".  Where a list of VGs is required but is left empty, 
+a list of all VGs will be substituted.  Where a list of LVs is required
+but a VG is given, a list of all the LVs in that VG will be substituted.
+So "lvdisplay vg0" will display all the LVs in "vg0".
+Tags can also be used - see \fBaddtag\fP below.
+.LP
+One advantage of using the built-in shell is that configuration 
+information gets cached internally between commands.  
+.LP
+A file containing a simple script with one command per line 
+can also be given on the command line.  The script can also be
+executed directly if the first line is #! followed by the absolute
+path of \fBlvm\fP.
+.SH BUILT-IN COMMANDS
+The following commands are built into lvm without links normally
+being created in the filesystem for them.
+.TP
+\fBdumpconfig\fP \(em Display the configuration information after 
+loading \fBlvm.conf\fP (5) and any other configuration files.
+.TP
+\fBformats\fP \(em Display recognised metadata formats.
+.TP
+\fBhelp\fP \(em Display the help text.
+.TP
+\fBpvdata\fP \(em Not implemented in LVM2.
+.TP
+\fBsegtypes\fP \(em Display recognised logical volume segment types.
+.TP
+\fBversion\fP \(em Display version information.
+.LP
+.SH COMMANDS
+The following commands implement the core LVM functionality.
+.TP
+\fBpvchange\fP \(em Change attributes of a physical volume.
+.TP
+\fBpvck\fP \(em Check physical volume metadata.
+.TP
+\fBpvcreate\fP \(em Initialize a disk or partition for use by LVM.
+.TP
+\fBpvdisplay\fP \(em Display attributes of a physical volume.
+.TP
+\fBpvmove\fP \(em Move physical extents.
+.TP
+\fBpvremove\fP \(em Remove a physical volume.
+.TP
+\fBpvresize\fP \(em Resize a disk or partition in use by LVM2.
+.TP
+\fBpvs\fP \(em Report information about physical volumes.
+.TP
+\fBpvscan\fP \(em Scan all disks for physical volumes.
+.TP
+\fBvgcfgbackup\fP \(em Backup volume group descriptor area.
+.TP
+\fBvgcfgrestore\fP \(em Restore volume group descriptor area.
+.TP
+\fBvgchange\fP \(em Change attributes of a volume group.
+.TP
+\fBvgck\fP \(em Check volume group metadata.
+.TP
+\fBvgconvert\fP \(em Convert volume group metadata format.
+.TP
+\fBvgcreate\fP \(em Create a volume group.
+.TP
+\fBvgdisplay\fP \(em Display attributes of volume groups.
+.TP
+\fBvgexport\fP \(em Make volume groups unknown to the system.
+.TP
+\fBvgextend\fP \(em Add physical volumes to a volume group.
+.TP
+\fBvgimport\fP \(em Make exported volume groups known to the system.
+.TP
+\fBvgmerge\fP \(em Merge two volume groups.
+.TP
+\fBvgmknodes\fP \(em Recreate volume group directory and logical volume special files
+.TP
+\fBvgreduce\fP \(em Reduce a volume group by removing one or more physical volumes.
+.TP
+\fBvgremove\fP \(em Remove a volume group.
+.TP
+\fBvgrename\fP \(em Rename a volume group.
+.TP
+\fBvgs\fP \(em Report information about volume groups.
+.TP
+\fBvgscan\fP \(em Scan all disks for volume groups and rebuild caches.
+.TP
+\fBvgsplit\fP \(em Split a volume group into two, moving any logical volumes from one volume group to another by moving entire physical volumes.
+.TP
+\fBlvchange\fP \(em Change attributes of a logical volume.
+.TP
+\fBlvconvert\fP \(em Convert a logical volume from linear to mirror or snapshot.
+.TP
+\fBlvcreate\fP \(em Create a logical volume in an existing volume group.
+.TP
+\fBlvdisplay\fP \(em Display attributes of a logical volume.
+.TP
+\fBlvextend\fP \(em Extend the size of a logical volume.
+.TP
+\fBlvmchange\fP \(em Change attributes of the logical volume manager.
+.TP
+\fBlvmdiskscan\fP \(em Scan for all devices visible to LVM2.
+.TP
+\fBlvmdump\fP \(em Create lvm2 information dumps for diagnostic purposes.
+.TP
+\fBlvreduce\fP \(em Reduce the size of a logical volume.
+.TP
+\fBlvremove\fP \(em Remove a logical volume.
+.TP
+\fBlvrename\fP \(em Rename a logical volume.
+.TP
+\fBlvresize\fP \(em Resize a logical volume.
+.TP
+\fBlvs\fP \(em Report information about logical volumes.
+.TP
+\fBlvscan\fP \(em Scan (all disks) for logical volumes.
+.TP
+The following commands are not implemented in LVM2 but might be in the future: lvmsadc, lvmsar, pvdata.
+.SH OPTIONS
+The following options are available for many of the commands. 
+They are implemented generically and documented here rather 
+than repeated on individual manual pages.
+.TP
+\fB-h | --help\fP \(em Display the help text.
+.TP
+\fB--version\fP \(em Display version information.
+.TP
+\fB-v | --verbose\fP \(em Set verbose level.
+Repeat from 1 to 3 times to increase the detail of messages 
+sent to stdout and stderr.  Overrides config file setting.
+.TP
+\fB-d | --debug\fP \(em Set debug level.
+Repeat from 1 to 6 times to increase the detail of messages sent 
+to the log file and/or syslog (if configured).
+Overrides config file setting.
+.TP
+\fB--quiet\fP \(em Suppress output and log messages.
+Overrides -d and -v.
+.TP
+\fB-t | --test\fP \(em Run in test mode.
+Commands will not update metadata.
+This is implemented by disabling all metadata writing but nevertheless
+returning success to the calling function.  This may lead to unusual
+error messages in multi-stage operations if a tool relies on reading
+back metadata it believes has changed but hasn't.
+.TP
+\fB--driverloaded\fP { \fBy\fP | \fBn\fP }
+Whether or not the device-mapper kernel driver is loaded.
+If you set this to \fBn\fP, no attempt will be made to contact the driver.
+.TP
+\fB-A | --autobackup\fP { \fBy\fP | \fBn\fP }
+Whether or not to metadata should be backed up automatically after a change.  
+You are strongly advised not to disable this!
+See
+.B vgcfgbackup (8).
+.TP
+\fB-P | --partial\fP
+When set, the tools will do their best to provide access to volume groups
+that are only partially available.  Where part of a logical volume is 
+missing, \fB/dev/ioerror\fP will be substituted, and you could use
+\fBdmsetup (8)\fP to set this up to return I/O errors when accessed,
+or create it as a large block device of nulls.  Metadata may not be
+changed with this option. To insert a replacement physical volume
+of the same or large size use \fBpvcreate -u\fP to set the uuid to 
+match the original followed by \fBvgcfgrestore (8)\fP.
+.TP
+\fB-M | --metadatatype type\fP
+Specifies which type of on-disk metadata to use, such as \fBlvm1\fP 
+or \fBlvm2\fP, which can be abbreviated to \fB1\fP or \fB2\fP respectively.
+The default (lvm2) can be changed by setting \fBformat\fP in the \fBglobal\fP
+section of the config file.
+.TP
+\fB--ignorelockingfailure\fP
+This lets you proceed with read-only metadata operations such as
+\fBlvchange -ay\fP and \fBvgchange -ay\fP even if the locking module fails.
+One use for this is in a system init script if the lock directory 
+is mounted read-only when the script runs.
+.TP
+\fB--addtag tag\fP
+Add the tag \fBtag\fP to a PV, VG or LV.  
+A tag is a word that can be used to group LVM2 objects of the same type 
+together. 
+Tags can be given on the command line in place of PV, VG or LV 
+arguments.  Tags should be prefixed with @ to avoid ambiguity.
+Each tag is expanded by replacing it with all objects possessing
+that tag which are of the type expected by its position on the command line.
+PVs can only possess tags while they are part of a Volume Group:
+PV tags are discarded if the PV is removed from the VG.
+As an example, you could tag some LVs as \fBdatabase\fP and others 
+as \fBuserdata\fP and then activate the database ones 
+with \fBlvchange -ay @database\fP.
+Objects can possess multiple tags simultaneously.
+Only the new LVM2 metadata format supports tagging: objects using the
+LVM1 metadata format cannot be tagged because the on-disk format does not
+support it.
+Snapshots cannot be tagged.
+Characters allowed in tags are: A-Z a-z 0-9 _ + . -
+.TP
+\fB--deltag tag\fP
+Delete the tag \fBtag\fP from a PV, VG or LV, if it's present.
+.TP
+\fB--alloc AllocationPolicy\fP
+The allocation policy to use: \fBcontiguous\fP, \fBcling\fP, \fBnormal\fP, \fBanywhere\fP or \fBinherit\fP.
+When a command needs to allocate physical extents from the volume group,
+the allocation policy controls how they are chosen.  
+Each volume group and logical volume has an allocation policy.
+The default for a volume group is \fBnormal\fP which applies
+common-sense rules such as not placing parallel stripes on the same
+physical volume.  The default for a logical volume is \fBinherit\fP
+which applies the same policy as for the volume group.  These policies can
+be changed using \fBlvchange\fP (8) and \fBvgchange\fP (8) or over-ridden
+on the command line of any command that performs allocation.
+The \fBcontiguous\fP policy requires that new extents be placed adjacent
+to existing extents. 
+The \fBcling\fP policy places new extents on the same physical
+volume as existing extents in the same stripe of the Logical Volume.
+If there are sufficient free extents to satisfy
+an allocation request but \fBnormal\fP doesn't use them,
+\fBanywhere\fP will - even if that reduces performance by
+placing two stripes on the same physical volume.
+.IP
+N.B. The policies described above are not implemented fully yet.
+In particular, contiguous free space cannot be broken up to
+satisfy allocation attempts.
+.SH ENVIRONMENT VARIABLES
+.TP
+\fBLVM_SYSTEM_DIR\fP 
+Directory containing lvm.conf and other LVM
+system files.
+Defaults to "/etc/lvm".
+.TP
+\fBHOME\fP 
+Directory containing .lvm_history if the internal readline shell
+is invoked.
+.TP
+\fBLVM_VG_NAME\fP 
+The volume group name that is assumed for 
+any reference to a logical volume that doesn't specify a path.
+Not set by default.
+.SH VALID NAMES
+The following characters are valid for VG and LV names:
+\fBa-z A-Z 0-9 + _ . -\fP
+.LP
+VG and LV names cannot begin with a hyphen.
+There are also various reserved names that are used internally by lvm that can not be used as LV or VG names.
+A VG cannot be called anything that exists in /dev/ at the time of creation, nor can it be called '.' or '..'.
+A LV cannot be called '.' '..' 'snapshot' or 'pvmove'. The LV name may also not contain the strings '_mlog' or '_mimage'
+
+
+.SH DIAGNOSTICS
+All tools return a status code of zero on success or non-zero on failure.
+.SH FILES
+.I /etc/lvm/lvm.conf
+.br
+.I $HOME/.lvm_history
+.SH SEE ALSO
+.BR clvmd (8),
+.BR lvchange (8),
+.BR lvcreate (8),
+.BR lvdisplay (8),
+.BR lvextend (8),
+.BR lvmchange (8),
+.BR lvmdiskscan (8),
+.BR lvreduce (8),
+.BR lvremove (8),
+.BR lvrename (8),
+.BR lvresize (8),
+.BR lvs (8),
+.BR lvscan (8),
+.BR pvchange (8),
+.BR pvck (8),
+.BR pvcreate (8),
+.BR pvdisplay (8),
+.BR pvmove (8),
+.BR pvremove (8),
+.BR pvs (8),
+.BR pvscan (8),
+.BR vgcfgbackup (8),
+.BR vgchange  (8),
+.BR vgck (8),
+.BR vgconvert (8),
+.BR vgcreate (8),
+.BR vgdisplay (8),
+.BR vgextend (8),
+.BR vgimport (8),
+.BR vgmerge (8),
+.BR vgmknodes (8),
+.BR vgreduce (8),
+.BR vgremove (8),
+.BR vgrename (8),
+.BR vgs (8),
+.BR vgscan (8),
+.BR vgsplit (8),
+.BR readline (3),
+.BR lvm.conf (5)
+
Index: src/external/gpl2/lvm2tools/dist/man/lvm.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvm.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/lvm.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvm.8.in	12 Dec 2008 16:33:01 -0000	1.1.1.1.2.2
@@ -0,0 +1,316 @@
+.TH LVM 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvm \- LVM2 tools
+.SH SYNOPSIS
+.B lvm
+[command | file]
+.SH DESCRIPTION
+\fBlvm\fP provides the command-line tools for LVM2.  A separate
+manual page describes each command in detail.
+.LP
+If \fBlvm\fP is invoked with no arguments it presents a readline prompt
+(assuming it was compiled with readline support).
+LVM commands may be entered interactively at this prompt with 
+readline facilities including history and command name and option 
+completion.  Refer to \fBreadline\fP(3) for details.
+.LP
+If \fBlvm\fP is invoked with argv[0] set to the name of a specific
+LVM command (for example by using a hard or soft link) it acts as 
+that command.  
+.LP
+Where commands take VG or LV names as arguments, the full path name is
+optional.  An LV called "lvol0" in a VG called "vg0" can be specified
+as "vg0/lvol0".  Where a list of VGs is required but is left empty, 
+a list of all VGs will be substituted.  Where a list of LVs is required
+but a VG is given, a list of all the LVs in that VG will be substituted.
+So "lvdisplay vg0" will display all the LVs in "vg0".
+Tags can also be used - see \fBaddtag\fP below.
+.LP
+One advantage of using the built-in shell is that configuration 
+information gets cached internally between commands.  
+.LP
+A file containing a simple script with one command per line 
+can also be given on the command line.  The script can also be
+executed directly if the first line is #! followed by the absolute
+path of \fBlvm\fP.
+.SH BUILT-IN COMMANDS
+The following commands are built into lvm without links normally
+being created in the filesystem for them.
+.TP
+\fBdumpconfig\fP \(em Display the configuration information after 
+loading \fBlvm.conf\fP (5) and any other configuration files.
+.TP
+\fBformats\fP \(em Display recognised metadata formats.
+.TP
+\fBhelp\fP \(em Display the help text.
+.TP
+\fBpvdata\fP \(em Not implemented in LVM2.
+.TP
+\fBsegtypes\fP \(em Display recognised logical volume segment types.
+.TP
+\fBversion\fP \(em Display version information.
+.LP
+.SH COMMANDS
+The following commands implement the core LVM functionality.
+.TP
+\fBpvchange\fP \(em Change attributes of a physical volume.
+.TP
+\fBpvck\fP \(em Check physical volume metadata.
+.TP
+\fBpvcreate\fP \(em Initialize a disk or partition for use by LVM.
+.TP
+\fBpvdisplay\fP \(em Display attributes of a physical volume.
+.TP
+\fBpvmove\fP \(em Move physical extents.
+.TP
+\fBpvremove\fP \(em Remove a physical volume.
+.TP
+\fBpvresize\fP \(em Resize a disk or partition in use by LVM2.
+.TP
+\fBpvs\fP \(em Report information about physical volumes.
+.TP
+\fBpvscan\fP \(em Scan all disks for physical volumes.
+.TP
+\fBvgcfgbackup\fP \(em Backup volume group descriptor area.
+.TP
+\fBvgcfgrestore\fP \(em Restore volume group descriptor area.
+.TP
+\fBvgchange\fP \(em Change attributes of a volume group.
+.TP
+\fBvgck\fP \(em Check volume group metadata.
+.TP
+\fBvgconvert\fP \(em Convert volume group metadata format.
+.TP
+\fBvgcreate\fP \(em Create a volume group.
+.TP
+\fBvgdisplay\fP \(em Display attributes of volume groups.
+.TP
+\fBvgexport\fP \(em Make volume groups unknown to the system.
+.TP
+\fBvgextend\fP \(em Add physical volumes to a volume group.
+.TP
+\fBvgimport\fP \(em Make exported volume groups known to the system.
+.TP
+\fBvgmerge\fP \(em Merge two volume groups.
+.TP
+\fBvgmknodes\fP \(em Recreate volume group directory and logical volume special files
+.TP
+\fBvgreduce\fP \(em Reduce a volume group by removing one or more physical volumes.
+.TP
+\fBvgremove\fP \(em Remove a volume group.
+.TP
+\fBvgrename\fP \(em Rename a volume group.
+.TP
+\fBvgs\fP \(em Report information about volume groups.
+.TP
+\fBvgscan\fP \(em Scan all disks for volume groups and rebuild caches.
+.TP
+\fBvgsplit\fP \(em Split a volume group into two, moving any logical volumes from one volume group to another by moving entire physical volumes.
+.TP
+\fBlvchange\fP \(em Change attributes of a logical volume.
+.TP
+\fBlvconvert\fP \(em Convert a logical volume from linear to mirror or snapshot.
+.TP
+\fBlvcreate\fP \(em Create a logical volume in an existing volume group.
+.TP
+\fBlvdisplay\fP \(em Display attributes of a logical volume.
+.TP
+\fBlvextend\fP \(em Extend the size of a logical volume.
+.TP
+\fBlvmchange\fP \(em Change attributes of the logical volume manager.
+.TP
+\fBlvmdiskscan\fP \(em Scan for all devices visible to LVM2.
+.TP
+\fBlvmdump\fP \(em Create lvm2 information dumps for diagnostic purposes.
+.TP
+\fBlvreduce\fP \(em Reduce the size of a logical volume.
+.TP
+\fBlvremove\fP \(em Remove a logical volume.
+.TP
+\fBlvrename\fP \(em Rename a logical volume.
+.TP
+\fBlvresize\fP \(em Resize a logical volume.
+.TP
+\fBlvs\fP \(em Report information about logical volumes.
+.TP
+\fBlvscan\fP \(em Scan (all disks) for logical volumes.
+.TP
+The following commands are not implemented in LVM2 but might be in the future: lvmsadc, lvmsar, pvdata.
+.SH OPTIONS
+The following options are available for many of the commands. 
+They are implemented generically and documented here rather 
+than repeated on individual manual pages.
+.TP
+\fB-h | --help\fP \(em Display the help text.
+.TP
+\fB--version\fP \(em Display version information.
+.TP
+\fB-v | --verbose\fP \(em Set verbose level.
+Repeat from 1 to 3 times to increase the detail of messages 
+sent to stdout and stderr.  Overrides config file setting.
+.TP
+\fB-d | --debug\fP \(em Set debug level.
+Repeat from 1 to 6 times to increase the detail of messages sent 
+to the log file and/or syslog (if configured).
+Overrides config file setting.
+.TP
+\fB--quiet\fP \(em Suppress output and log messages.
+Overrides -d and -v.
+.TP
+\fB-t | --test\fP \(em Run in test mode.
+Commands will not update metadata.
+This is implemented by disabling all metadata writing but nevertheless
+returning success to the calling function.  This may lead to unusual
+error messages in multi-stage operations if a tool relies on reading
+back metadata it believes has changed but hasn't.
+.TP
+\fB--driverloaded\fP { \fBy\fP | \fBn\fP }
+Whether or not the device-mapper kernel driver is loaded.
+If you set this to \fBn\fP, no attempt will be made to contact the driver.
+.TP
+\fB-A | --autobackup\fP { \fBy\fP | \fBn\fP }
+Whether or not to metadata should be backed up automatically after a change.  
+You are strongly advised not to disable this!
+See
+.B vgcfgbackup (8).
+.TP
+\fB-P | --partial\fP
+When set, the tools will do their best to provide access to volume groups
+that are only partially available.  Where part of a logical volume is 
+missing, \fB/dev/ioerror\fP will be substituted, and you could use
+\fBdmsetup (8)\fP to set this up to return I/O errors when accessed,
+or create it as a large block device of nulls.  Metadata may not be
+changed with this option. To insert a replacement physical volume
+of the same or large size use \fBpvcreate -u\fP to set the uuid to 
+match the original followed by \fBvgcfgrestore (8)\fP.
+.TP
+\fB-M | --metadatatype type\fP
+Specifies which type of on-disk metadata to use, such as \fBlvm1\fP 
+or \fBlvm2\fP, which can be abbreviated to \fB1\fP or \fB2\fP respectively.
+The default (lvm2) can be changed by setting \fBformat\fP in the \fBglobal\fP
+section of the config file.
+.TP
+\fB--ignorelockingfailure\fP
+This lets you proceed with read-only metadata operations such as
+\fBlvchange -ay\fP and \fBvgchange -ay\fP even if the locking module fails.
+One use for this is in a system init script if the lock directory 
+is mounted read-only when the script runs.
+.TP
+\fB--addtag tag\fP
+Add the tag \fBtag\fP to a PV, VG or LV.  
+A tag is a word that can be used to group LVM2 objects of the same type 
+together. 
+Tags can be given on the command line in place of PV, VG or LV 
+arguments.  Tags should be prefixed with @ to avoid ambiguity.
+Each tag is expanded by replacing it with all objects possessing
+that tag which are of the type expected by its position on the command line.
+PVs can only possess tags while they are part of a Volume Group:
+PV tags are discarded if the PV is removed from the VG.
+As an example, you could tag some LVs as \fBdatabase\fP and others 
+as \fBuserdata\fP and then activate the database ones 
+with \fBlvchange -ay @database\fP.
+Objects can possess multiple tags simultaneously.
+Only the new LVM2 metadata format supports tagging: objects using the
+LVM1 metadata format cannot be tagged because the on-disk format does not
+support it.
+Snapshots cannot be tagged.
+Characters allowed in tags are: A-Z a-z 0-9 _ + . -
+.TP
+\fB--deltag tag\fP
+Delete the tag \fBtag\fP from a PV, VG or LV, if it's present.
+.TP
+\fB--alloc AllocationPolicy\fP
+The allocation policy to use: \fBcontiguous\fP, \fBcling\fP, \fBnormal\fP, \fBanywhere\fP or \fBinherit\fP.
+When a command needs to allocate physical extents from the volume group,
+the allocation policy controls how they are chosen.  
+Each volume group and logical volume has an allocation policy.
+The default for a volume group is \fBnormal\fP which applies
+common-sense rules such as not placing parallel stripes on the same
+physical volume.  The default for a logical volume is \fBinherit\fP
+which applies the same policy as for the volume group.  These policies can
+be changed using \fBlvchange\fP (8) and \fBvgchange\fP (8) or over-ridden
+on the command line of any command that performs allocation.
+The \fBcontiguous\fP policy requires that new extents be placed adjacent
+to existing extents. 
+The \fBcling\fP policy places new extents on the same physical
+volume as existing extents in the same stripe of the Logical Volume.
+If there are sufficient free extents to satisfy
+an allocation request but \fBnormal\fP doesn't use them,
+\fBanywhere\fP will - even if that reduces performance by
+placing two stripes on the same physical volume.
+.IP
+N.B. The policies described above are not implemented fully yet.
+In particular, contiguous free space cannot be broken up to
+satisfy allocation attempts.
+.SH ENVIRONMENT VARIABLES
+.TP
+\fBLVM_SYSTEM_DIR\fP 
+Directory containing lvm.conf and other LVM
+system files.
+Defaults to "/etc/lvm".
+.TP
+\fBHOME\fP 
+Directory containing .lvm_history if the internal readline shell
+is invoked.
+.TP
+\fBLVM_VG_NAME\fP 
+The volume group name that is assumed for 
+any reference to a logical volume that doesn't specify a path.
+Not set by default.
+.SH VALID NAMES
+The following characters are valid for VG and LV names:
+\fBa-z A-Z 0-9 + _ . -\fP
+.LP
+VG and LV names cannot begin with a hyphen.
+There are also various reserved names that are used internally by lvm that can not be used as LV or VG names.
+A VG cannot be called anything that exists in /dev/ at the time of creation, nor can it be called '.' or '..'.
+A LV cannot be called '.' '..' 'snapshot' or 'pvmove'. The LV name may also not contain the strings '_mlog' or '_mimage'
+
+
+.SH DIAGNOSTICS
+All tools return a status code of zero on success or non-zero on failure.
+.SH FILES
+.I /etc/lvm/lvm.conf
+.br
+.I $HOME/.lvm_history
+.SH SEE ALSO
+.BR clvmd (8),
+.BR lvchange (8),
+.BR lvcreate (8),
+.BR lvdisplay (8),
+.BR lvextend (8),
+.BR lvmchange (8),
+.BR lvmdiskscan (8),
+.BR lvreduce (8),
+.BR lvremove (8),
+.BR lvrename (8),
+.BR lvresize (8),
+.BR lvs (8),
+.BR lvscan (8),
+.BR pvchange (8),
+.BR pvck (8),
+.BR pvcreate (8),
+.BR pvdisplay (8),
+.BR pvmove (8),
+.BR pvremove (8),
+.BR pvs (8),
+.BR pvscan (8),
+.BR vgcfgbackup (8),
+.BR vgchange  (8),
+.BR vgck (8),
+.BR vgconvert (8),
+.BR vgcreate (8),
+.BR vgdisplay (8),
+.BR vgextend (8),
+.BR vgimport (8),
+.BR vgmerge (8),
+.BR vgmknodes (8),
+.BR vgreduce (8),
+.BR vgremove (8),
+.BR vgrename (8),
+.BR vgs (8),
+.BR vgscan (8),
+.BR vgsplit (8),
+.BR readline (3),
+.BR lvm.conf (5)
+
Index: src/external/gpl2/lvm2tools/dist/man/lvm.conf.5
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvm.conf.5
diff -N src/external/gpl2/lvm2tools/dist/man/lvm.conf.5
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvm.conf.5	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,397 @@
+.\"	$NetBSD$
+.\"
+.TH LVM.CONF 5 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvm.conf \- Configuration file for LVM2
+.SH SYNOPSIS
+.B /etc/lvm/lvm.conf
+.SH DESCRIPTION
+lvm.conf is loaded during the initialisation phase of 
+\fBlvm\fP (8).  This file can in turn lead to other files
+being loaded - settings read in later override earlier
+settings.  File timestamps are checked between commands and if 
+any have changed, all the files are reloaded.  
+.LP
+Use \fBlvm dumpconfig\fP to check what settings are in use.
+.SH SYNTAX
+.LP
+This section describes the configuration file syntax.
+.LP
+Whitespace is not significant unless it is within quotes. 
+This provides a wide choice of acceptable indentation styles.
+Comments begin with # and continue to the end of the line.
+They are treated as whitespace.
+.LP
+Here is an informal grammar:
+.TP
+\fBfile = value*\fP
+.br
+A configuration file consists of a set of values.
+.TP
+\fBvalue = section | assignment\fP
+.br
+A value can either be a new section, or an assignment.
+.TP
+\fBsection = identifier '{' value* '}'\fP
+.br
+A section is groups associated values together.  
+.br
+It is denoted by a name and delimited by curly brackets.
+.br
+e.g.	backup {
+.br
+		...
+.br
+	}
+.TP
+\fBassignment = identifier '=' (array | type)\fP
+.br
+An assignment associates a type with an identifier.
+.br
+e.g.	max_archives = 42
+.br
+.TP
+\fBarray = '[' (type ',')* type ']' | '[' ']'\fP
+.br
+Inhomogeneous arrays are supported. 
+.br
+Elements must be separated by commas.  
+.br
+An empty array is acceptable.
+.TP
+\fBtype = integer | float | string\fP
+\fBinteger = [0-9]*\fP
+.br
+\fBfloat = [0-9]*\.[0-9]*\fP
+.br
+\fBstring = '"' .* '"'\fP
+.IP
+Strings must be enclosed in double quotes.
+
+.SH SECTIONS
+.LP
+The sections that may be present in the file are:
+.TP
+\fBdevices\fP \(em Device settings
+.IP
+\fBdir\fP \(em Directory in which to create volume group device nodes.
+Defaults to "/dev".  Commands also accept this as a prefix on volume 
+group names.
+.IP
+\fBscan\fP \(em List of directories to scan recursively for 
+LVM physical volumes.
+Devices in directories outside this hierarchy will be ignored.
+Defaults to "/dev".
+.IP
+\fBpreferred_names\fP \(em List of patterns compared in turn against
+all the pathnames referencing the same device in in the scanned directories.
+The pathname that matches the earliest pattern in the list is the
+one used in any output.  As an example, if device-mapper multipathing
+is used, the following will select multipath device names:
+.br
+\fBdevices { preferred_names = [ "^/dev/mapper/mpath" ] }\fP
+.IP
+\fBfilter\fP \(em List of patterns to apply to devices found by a scan.
+Patterns are regular expressions delimited by any character and preceded
+by \fBa\fP (for accept) or \fBr\fP (for reject).  The list is traversed
+in order, and the first regex that matches determines if the device
+will be accepted or rejected (ignored).  Devices that don't match
+any patterns are accepted. If you want to reject patterns that
+don't match, end the list with "r/.*/".
+If there are several names for the same device (e.g. symbolic links
+in /dev), if any name matches any \fBa\fP pattern, the
+device is accepted; otherwise if any name matches any \fBr\fP
+pattern it is rejected; otherwise it is accepted.
+As an example, to ignore /dev/cdrom you could use:
+.br
+\fBdevices { filter=["r|cdrom|"] }\fP 
+.IP
+\fBcache_dir\fP \(em Persistent filter cache file directory.
+Defaults to "/etc/lvm/cache".
+.IP
+\fBwrite_cache_state\fP \(em Set to 0 to disable the writing out of the 
+persistent filter cache file when \fBlvm\fP exits.
+Defaults to 1.
+.IP
+\fBtypes\fP \(em List of pairs of additional acceptable block device types
+found in /proc/devices together with maximum (non-zero) number of
+partitions (normally 16).  By default, LVM2 supports ide, sd, md, loop, 
+dasd, dac960, nbd, ida, cciss, ubd, ataraid, drbd, power2, i2o_block
+and iseries/vd.  Block devices with major
+numbers of different types are ignored by LVM2.  
+Example: \fBtypes = ["fd", 16]\fP.
+To create physical volumes on device-mapper volumes
+created outside LVM2, perhaps encrypted ones from \fBcryptsetup\fP,
+you'll need \fBtypes = ["device-mapper", 16]\fP.  But if you do this,
+be careful to avoid recursion within LVM2.  The figure for number 
+of partitions is not currently used in LVM2 - and might never be.
+.IP
+\fBsysfs_scan\fP (em If set to 1 and your kernel supports sysfs and 
+it is mounted, sysfs will be used as a quick way of filtering out
+block devices that are not present.
+.IP
+\fBmd_component_detection\fP (em If set to 1, LVM2 will ignore devices
+used as components of software RAID (md) devices by looking for md
+superblocks. This doesn't always work satisfactorily e.g. if a device 
+has been reused without wiping the md superblocks first.
+.TP
+\fBlog\fP \(em Default log settings
+.IP
+\fBfile\fP \(em Location of log file.  If this entry is not present, no
+log file is written.
+.IP
+\fBoverwrite\fP \(em Set to 1 to overwrite the log file each time a tool
+is invoked.  By default tools append messages to the log file.
+.IP
+\fBlevel\fP \(em Log level (0-9) of messages to write to the file.
+9 is the most verbose; 0 should produce no output.
+.IP
+\fBverbose\fP \(em Default level (0-3) of messages sent to stdout or stderr.
+3 is the most verbose; 0 should produce the least output.
+.IP
+\fBsyslog\fP \(em Set to 1 (the default) to send log messages through syslog.
+Turn off by setting to 0.  If you set to an integer greater than one,
+this is used - unvalidated - as the facility.  The default is LOG_USER.  
+See /usr/include/sys/syslog.h for safe facility values to use.
+For example, LOG_LOCAL0 might be 128.
+.IP
+\fBindent\fP \(em When set to 1 (the default) messages are indented 
+according to their severity, two spaces per level.  
+Set to 0 to turn off indentation.
+.IP
+\fBcommand_names\fP \(em When set to 1, the command name is used as a
+prefix for each message.
+Default is 0 (off).
+.IP
+\fBprefix\fP \(em Prefix used for all messages (after the command name).
+Default is two spaces.
+.IP
+\fBactivation\fP \(em Set to 1 to log messages while
+devices are suspended during activation.  
+Only set this temporarily while debugging a problem because
+in low memory situations this setting can cause your machine to lock up.
+.TP
+\fBbackup\fP \(em Configuration for metadata backups.
+.IP
+\fBarchive_dir\fP \(em Directory used for automatic metadata archives.
+Backup copies of former metadata for each volume group are archived here.
+Defaults to "/etc/lvm/archive".
+.IP
+\fBbackup_dir\fP \(em Directory used for automatic metadata backups.
+A single backup copy of the current metadata for each volume group 
+is stored here.
+Defaults to "/etc/lvm/backup".
+.IP
+\fBarchive\fP \(em Whether or not tools automatically archive existing
+metadata into \fBarchive_dir\fP before making changes to it.
+Default is 1 (automatic archives enabled).  
+Set to 0 to disable.  
+Disabling this might make metadata recovery difficult or impossible 
+if something goes wrong.
+.IP
+\fBbackup\fP \(em Whether or not tools make an automatic backup 
+into \fBbackup_dir\fP after changing metadata.  
+Default is 1 (automatic backups enabled).  Set to 0 to disable.
+Disabling this might make metadata recovery difficult or impossible 
+if something goes wrong.
+.IP
+\fBretain_min\fP \(em Minimum number of archives to keep.
+Defaults to 10.
+.IP
+\fBretain_days\fP \(em Minimum number of days to keep archive files.
+Defaults to 30.
+.TP
+\fBshell\fP \(em LVM2 built-in readline shell settings
+.IP
+\fBhistory_size\fP \(em Maximum number of lines of shell history to retain (default 100) in $HOME/.lvm_history
+.TP
+\fBglobal\fP \(em Global settings
+.IP
+\fBtest\fP \(em If set to 1, run tools in test mode i.e. no changes to
+the on-disk metadata will get made.  It's equivalent to having the
+-t option on every command.
+.IP
+\fBactivation\fP \(em Set to 0 to turn off all communication with
+the device-mapper driver.  Useful if you want to manipulate logical
+volumes while device-mapper is not present in your kernel.
+.IP
+\fBproc\fP \(em Mount point of proc filesystem.
+Defaults to /proc.
+.IP
+\fBumask\fP \(em File creation mask for any files and directories created.
+Interpreted as octal if the first digit is zero.
+Defaults to 077.  
+Use 022 to allow other users to read the files by default.
+.IP
+\fBformat\fP \(em The default value of \fB--metadatatype\fP used
+to determine which format of metadata to use when creating new 
+physical volumes and volume groups. \fBlvm1\fP or \fBlvm2\fP.
+.IP
+\fBfallback_to_lvm1\fP \(em Set this to 1 if you need to 
+be able to switch between 2.4 kernels using LVM1 and kernels
+including device-mapper.
+The LVM2 tools should be installed as normal and
+the LVM1 tools should be installed with a .lvm1 suffix e.g.
+vgscan.lvm1.  
+If an LVM2 tool is then run but unable to communicate
+with device-mapper, it will automatically invoke the equivalent LVM1 
+version of the tool.  Note that for LVM1 tools to 
+manipulate physical volumes and volume groups created by LVM2 you 
+must use \fB--metadataformat lvm1\fP when creating them.
+.IP
+\fBlibrary_dir\fP \(em A directory searched for LVM2's shared libraries
+ahead of the places \fBdlopen\fP (3) searches.
+.IP
+\fBformat_libraries\fP \(em A list of shared libraries to load that contain
+code to process different formats of metadata. For example, liblvm2formatpool.so
+is needed to read GFS pool metadata if LVM2 was configured \fB--with-pool=shared\fP.
+.IP
+\fBlocking_type\fP \(em What type of locking to use.
+1 is the default, which use flocks on files in \fBlocking_dir\fP
+(see below) to
+avoid conflicting LVM2 commands running concurrently on a single
+machine. 0 disables locking and risks corrupting your metadata.
+If set to 2, the tools will load the external \fBlocking_library\fP
+(see below).
+If the tools were configured \fB--with-cluster=internal\fP 
+(the default) then 3 means to use built-in cluster-wide locking.
+All changes to logical volumes and their states are communicated
+using locks.
+.IP
+\fBlocking_dir\fP \(em The directory LVM2 places its file locks
+if \fBlocking_type\fP is set to 1.  The default is \fB/var/lock/lvm\fP.
+.IP
+\fBlocking_library\fP \(em The name of the external locking
+library to load if \fBlocking_type\fP is set to 2.
+The default is \fBliblvm2clusterlock.so\fP.  If you need to write
+such a library, look at the lib/locking source code directory.
+.TP
+\fBtags\fP \(em Host tag settings
+.IP
+\fBhosttags\fP \(em If set to 1, create a host tag with the machine name.
+Setting this to 0 does nothing, neither creating nor destroying any tag.
+The machine name used is the nodename as returned by \fBuname\fP (2).
+.IP
+Additional host tags to be set can be listed here as subsections. 
+The @ prefix for tags is optional.
+Each of these host tag subsections can contain a \fBhost_list\fP 
+array of host names. If any one of these entries matches the machine 
+name exactly then the host tag gets defined on this particular host, 
+otherwise it doesn't.
+.IP
+After lvm.conf has been processed, LVM2 works through each host
+tag that has been defined in turn, and if there is a configuration
+file called lvm_\fB<host_tag>\fP.conf it attempts to load it.
+Any settings read in override settings found in earlier files.
+Any additional host tags defined get appended to the search list,
+so in turn they can lead to further configuration files being processed.
+Use \fBlvm dumpconfig\fP to check the result of config
+file processing.
+.IP
+The following example always sets host tags \fBtag1\fP and
+sets \fBtag2\fP on machines fs1 and fs2:
+.IP
+tags { tag1 { } tag2 { host_list = [ "fs1", "fs2" ] } }
+.IP
+These options are useful if you are replicating configuration files
+around a cluster.  Use of \fBhosttags = 1\fP means every machine
+can have static and identical local configuration files yet use 
+different settings and activate different logical volumes by
+default.  See also \fBvolume_list\fP below and \fB--addtag\fP 
+in \fBlvm\fP (8).
+.TP
+\fBactivation\fP \(em Settings affecting device-mapper activation
+.IP
+\fBmissing_stripe_filler\fP \(em When activating an incomplete logical
+volume in partial mode, this option dictates how the missing data is
+replaced.  A value of "error" will cause activation to create error
+mappings for the missing data, meaning that read access to missing
+portions of the volume will result in I/O errors. You can instead also
+use a device path, and in that case this device will be used in place of
+missing stripes. However, note that using anything other than
+"error" with mirrored or snapshotted volumes is likely to result in data
+corruption.  For instructions on how to create a device that always
+returns zeros, see \fBlvcreate\fP (8).
+.IP
+\fBmirror_region_size\fP \(em Unit size in KB for copy operations
+when mirroring.
+.IP
+\fBreadahead\fP \(em Used when there is no readahead value stored 
+in the volume group metadata.  Set to \fBnone\fP to disable
+readahead in these circumstances or \fBauto\fP to use the default
+value chosen by the kernel.
+.IP
+\fBreserved_memory\fP, \fBreserved_stack\fP \(em How many KB to reserve 
+for LVM2 to use while logical volumes are suspended.  If insufficient 
+memory is reserved before suspension, there is a risk of machine deadlock.
+.IP
+\fBprocess_priority\fP \(em The nice value to use while devices are
+suspended.  This is set to a high priority so that logical volumes
+are suspended (with I/O generated by other processes to those
+logical volumes getting queued) for the shortest possible time.
+.IP
+\fBvolume_list\fP \(em This acts as a filter through which
+all requests to activate a logical volume on this machine
+are passed.  A logical volume is only activated if it matches
+an item in the list.  Tags must be preceded by @ and are checked
+against all tags defined in the logical volume and volume group 
+metadata for a match.
+@* is short-hand to check every tag set on the host machine (see
+\fBtags\fP above).
+Logical volume and volume groups can also be included in the list
+by name e.g. vg00, vg00/lvol1.
+.TP
+\fBmetadata\fP \(em Advanced metadata settings
+.IP
+\fBpvmetadatacopies\fP \(em When creating a physical volume using the
+LVM2 metadata format, this is the default number of copies of metadata
+to store on each physical volume.  
+Currently it can be set to 0, 1 or 2.  The default is 1.  
+If set to 2, one copy is placed at the beginning of the disk
+and the other is placed at the end.
+It can be overridden on the command line with \fB--metadatacopies\fP.
+If creating a volume group with just one physical volume, it's a
+good idea to have 2 copies.  If creating a large volume group with
+many physical volumes, you may decide that 3 copies of the metadata
+is sufficient, i.e. setting it to 1 on three of the physical volumes,
+and 0 on the rest.  Every volume group must contain at least one 
+physical volume with at least 1 copy of the metadata (unless using
+the text files described below).  The disadvantage of having lots
+of copies is that every time the tools access the volume group, every
+copy of the metadata has to be accessed, and this slows down the
+tools.
+.IP
+\fBpvmetadatasize\fP \(em Approximate number of sectors to set aside
+for each copy of the metadata. Volume groups with large numbers of
+physical or logical volumes, or volumes groups containing complex 
+logical volume structures will need additional space for their metadata.
+The metadata areas are treated as circular buffers, so
+unused space becomes filled with an archive of the most recent
+previous versions of the metadata.
+.IP
+\fBdirs\fP \(em List of directories holding live copies of LVM2
+metadata as text files.  These directories must not be on logical
+volumes.  It is possible to use LVM2 with a couple of directories
+here, preferably on different (non-logical-volume) filesystems
+and with no other on-disk metadata, \fBpvmetadatacopies = 0\fP.
+Alternatively these directories can be in addition to the
+on-disk metadata areas.  This feature was created during the
+development of the LVM2 metadata before the new on-disk metadata
+areas were designed and no longer gets tested.  
+It is not supported under low-memory conditions, and it is 
+important never to edit these metadata files unless you fully 
+understand how things work: to make changes you should always use 
+the tools as normal, or else vgcfgbackup, edit backup, vgcfgrestore.
+.SH FILES
+.I /etc/lvm/lvm.conf
+.I /etc/lvm/archive
+.I /etc/lvm/backup
+.I /etc/lvm/cache/.cache
+.I /var/lock/lvm
+.SH SEE ALSO
+.BR lvm (8),
+.BR umask (2),
+.BR uname (2),
+.BR dlopen (3),
+.BR syslog (3),
+.BR syslog.conf (5)
Index: src/external/gpl2/lvm2tools/dist/man/lvm.conf.5.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvm.conf.5.in
diff -N src/external/gpl2/lvm2tools/dist/man/lvm.conf.5.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvm.conf.5.in	12 Dec 2008 16:33:01 -0000	1.1.1.1.2.2
@@ -0,0 +1,395 @@
+.TH LVM.CONF 5 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvm.conf \- Configuration file for LVM2
+.SH SYNOPSIS
+.B /etc/lvm/lvm.conf
+.SH DESCRIPTION
+lvm.conf is loaded during the initialisation phase of 
+\fBlvm\fP (8).  This file can in turn lead to other files
+being loaded - settings read in later override earlier
+settings.  File timestamps are checked between commands and if 
+any have changed, all the files are reloaded.  
+.LP
+Use \fBlvm dumpconfig\fP to check what settings are in use.
+.SH SYNTAX
+.LP
+This section describes the configuration file syntax.
+.LP
+Whitespace is not significant unless it is within quotes. 
+This provides a wide choice of acceptable indentation styles.
+Comments begin with # and continue to the end of the line.
+They are treated as whitespace.
+.LP
+Here is an informal grammar:
+.TP
+\fBfile = value*\fP
+.br
+A configuration file consists of a set of values.
+.TP
+\fBvalue = section | assignment\fP
+.br
+A value can either be a new section, or an assignment.
+.TP
+\fBsection = identifier '{' value* '}'\fP
+.br
+A section is groups associated values together.  
+.br
+It is denoted by a name and delimited by curly brackets.
+.br
+e.g.	backup {
+.br
+		...
+.br
+	}
+.TP
+\fBassignment = identifier '=' (array | type)\fP
+.br
+An assignment associates a type with an identifier.
+.br
+e.g.	max_archives = 42
+.br
+.TP
+\fBarray = '[' (type ',')* type ']' | '[' ']'\fP
+.br
+Inhomogeneous arrays are supported. 
+.br
+Elements must be separated by commas.  
+.br
+An empty array is acceptable.
+.TP
+\fBtype = integer | float | string\fP
+\fBinteger = [0-9]*\fP
+.br
+\fBfloat = [0-9]*\.[0-9]*\fP
+.br
+\fBstring = '"' .* '"'\fP
+.IP
+Strings must be enclosed in double quotes.
+
+.SH SECTIONS
+.LP
+The sections that may be present in the file are:
+.TP
+\fBdevices\fP \(em Device settings
+.IP
+\fBdir\fP \(em Directory in which to create volume group device nodes.
+Defaults to "/dev".  Commands also accept this as a prefix on volume 
+group names.
+.IP
+\fBscan\fP \(em List of directories to scan recursively for 
+LVM physical volumes.
+Devices in directories outside this hierarchy will be ignored.
+Defaults to "/dev".
+.IP
+\fBpreferred_names\fP \(em List of patterns compared in turn against
+all the pathnames referencing the same device in in the scanned directories.
+The pathname that matches the earliest pattern in the list is the
+one used in any output.  As an example, if device-mapper multipathing
+is used, the following will select multipath device names:
+.br
+\fBdevices { preferred_names = [ "^/dev/mapper/mpath" ] }\fP
+.IP
+\fBfilter\fP \(em List of patterns to apply to devices found by a scan.
+Patterns are regular expressions delimited by any character and preceded
+by \fBa\fP (for accept) or \fBr\fP (for reject).  The list is traversed
+in order, and the first regex that matches determines if the device
+will be accepted or rejected (ignored).  Devices that don't match
+any patterns are accepted. If you want to reject patterns that
+don't match, end the list with "r/.*/".
+If there are several names for the same device (e.g. symbolic links
+in /dev), if any name matches any \fBa\fP pattern, the
+device is accepted; otherwise if any name matches any \fBr\fP
+pattern it is rejected; otherwise it is accepted.
+As an example, to ignore /dev/cdrom you could use:
+.br
+\fBdevices { filter=["r|cdrom|"] }\fP 
+.IP
+\fBcache_dir\fP \(em Persistent filter cache file directory.
+Defaults to "/etc/lvm/cache".
+.IP
+\fBwrite_cache_state\fP \(em Set to 0 to disable the writing out of the 
+persistent filter cache file when \fBlvm\fP exits.
+Defaults to 1.
+.IP
+\fBtypes\fP \(em List of pairs of additional acceptable block device types
+found in /proc/devices together with maximum (non-zero) number of
+partitions (normally 16).  By default, LVM2 supports ide, sd, md, loop, 
+dasd, dac960, nbd, ida, cciss, ubd, ataraid, drbd, power2, i2o_block
+and iseries/vd.  Block devices with major
+numbers of different types are ignored by LVM2.  
+Example: \fBtypes = ["fd", 16]\fP.
+To create physical volumes on device-mapper volumes
+created outside LVM2, perhaps encrypted ones from \fBcryptsetup\fP,
+you'll need \fBtypes = ["device-mapper", 16]\fP.  But if you do this,
+be careful to avoid recursion within LVM2.  The figure for number 
+of partitions is not currently used in LVM2 - and might never be.
+.IP
+\fBsysfs_scan\fP (em If set to 1 and your kernel supports sysfs and 
+it is mounted, sysfs will be used as a quick way of filtering out
+block devices that are not present.
+.IP
+\fBmd_component_detection\fP (em If set to 1, LVM2 will ignore devices
+used as components of software RAID (md) devices by looking for md
+superblocks. This doesn't always work satisfactorily e.g. if a device 
+has been reused without wiping the md superblocks first.
+.TP
+\fBlog\fP \(em Default log settings
+.IP
+\fBfile\fP \(em Location of log file.  If this entry is not present, no
+log file is written.
+.IP
+\fBoverwrite\fP \(em Set to 1 to overwrite the log file each time a tool
+is invoked.  By default tools append messages to the log file.
+.IP
+\fBlevel\fP \(em Log level (0-9) of messages to write to the file.
+9 is the most verbose; 0 should produce no output.
+.IP
+\fBverbose\fP \(em Default level (0-3) of messages sent to stdout or stderr.
+3 is the most verbose; 0 should produce the least output.
+.IP
+\fBsyslog\fP \(em Set to 1 (the default) to send log messages through syslog.
+Turn off by setting to 0.  If you set to an integer greater than one,
+this is used - unvalidated - as the facility.  The default is LOG_USER.  
+See /usr/include/sys/syslog.h for safe facility values to use.
+For example, LOG_LOCAL0 might be 128.
+.IP
+\fBindent\fP \(em When set to 1 (the default) messages are indented 
+according to their severity, two spaces per level.  
+Set to 0 to turn off indentation.
+.IP
+\fBcommand_names\fP \(em When set to 1, the command name is used as a
+prefix for each message.
+Default is 0 (off).
+.IP
+\fBprefix\fP \(em Prefix used for all messages (after the command name).
+Default is two spaces.
+.IP
+\fBactivation\fP \(em Set to 1 to log messages while
+devices are suspended during activation.  
+Only set this temporarily while debugging a problem because
+in low memory situations this setting can cause your machine to lock up.
+.TP
+\fBbackup\fP \(em Configuration for metadata backups.
+.IP
+\fBarchive_dir\fP \(em Directory used for automatic metadata archives.
+Backup copies of former metadata for each volume group are archived here.
+Defaults to "/etc/lvm/archive".
+.IP
+\fBbackup_dir\fP \(em Directory used for automatic metadata backups.
+A single backup copy of the current metadata for each volume group 
+is stored here.
+Defaults to "/etc/lvm/backup".
+.IP
+\fBarchive\fP \(em Whether or not tools automatically archive existing
+metadata into \fBarchive_dir\fP before making changes to it.
+Default is 1 (automatic archives enabled).  
+Set to 0 to disable.  
+Disabling this might make metadata recovery difficult or impossible 
+if something goes wrong.
+.IP
+\fBbackup\fP \(em Whether or not tools make an automatic backup 
+into \fBbackup_dir\fP after changing metadata.  
+Default is 1 (automatic backups enabled).  Set to 0 to disable.
+Disabling this might make metadata recovery difficult or impossible 
+if something goes wrong.
+.IP
+\fBretain_min\fP \(em Minimum number of archives to keep.
+Defaults to 10.
+.IP
+\fBretain_days\fP \(em Minimum number of days to keep archive files.
+Defaults to 30.
+.TP
+\fBshell\fP \(em LVM2 built-in readline shell settings
+.IP
+\fBhistory_size\fP \(em Maximum number of lines of shell history to retain (default 100) in $HOME/.lvm_history
+.TP
+\fBglobal\fP \(em Global settings
+.IP
+\fBtest\fP \(em If set to 1, run tools in test mode i.e. no changes to
+the on-disk metadata will get made.  It's equivalent to having the
+-t option on every command.
+.IP
+\fBactivation\fP \(em Set to 0 to turn off all communication with
+the device-mapper driver.  Useful if you want to manipulate logical
+volumes while device-mapper is not present in your kernel.
+.IP
+\fBproc\fP \(em Mount point of proc filesystem.
+Defaults to /proc.
+.IP
+\fBumask\fP \(em File creation mask for any files and directories created.
+Interpreted as octal if the first digit is zero.
+Defaults to 077.  
+Use 022 to allow other users to read the files by default.
+.IP
+\fBformat\fP \(em The default value of \fB--metadatatype\fP used
+to determine which format of metadata to use when creating new 
+physical volumes and volume groups. \fBlvm1\fP or \fBlvm2\fP.
+.IP
+\fBfallback_to_lvm1\fP \(em Set this to 1 if you need to 
+be able to switch between 2.4 kernels using LVM1 and kernels
+including device-mapper.
+The LVM2 tools should be installed as normal and
+the LVM1 tools should be installed with a .lvm1 suffix e.g.
+vgscan.lvm1.  
+If an LVM2 tool is then run but unable to communicate
+with device-mapper, it will automatically invoke the equivalent LVM1 
+version of the tool.  Note that for LVM1 tools to 
+manipulate physical volumes and volume groups created by LVM2 you 
+must use \fB--metadataformat lvm1\fP when creating them.
+.IP
+\fBlibrary_dir\fP \(em A directory searched for LVM2's shared libraries
+ahead of the places \fBdlopen\fP (3) searches.
+.IP
+\fBformat_libraries\fP \(em A list of shared libraries to load that contain
+code to process different formats of metadata. For example, liblvm2formatpool.so
+is needed to read GFS pool metadata if LVM2 was configured \fB--with-pool=shared\fP.
+.IP
+\fBlocking_type\fP \(em What type of locking to use.
+1 is the default, which use flocks on files in \fBlocking_dir\fP
+(see below) to
+avoid conflicting LVM2 commands running concurrently on a single
+machine. 0 disables locking and risks corrupting your metadata.
+If set to 2, the tools will load the external \fBlocking_library\fP
+(see below).
+If the tools were configured \fB--with-cluster=internal\fP 
+(the default) then 3 means to use built-in cluster-wide locking.
+All changes to logical volumes and their states are communicated
+using locks.
+.IP
+\fBlocking_dir\fP \(em The directory LVM2 places its file locks
+if \fBlocking_type\fP is set to 1.  The default is \fB/var/lock/lvm\fP.
+.IP
+\fBlocking_library\fP \(em The name of the external locking
+library to load if \fBlocking_type\fP is set to 2.
+The default is \fBliblvm2clusterlock.so\fP.  If you need to write
+such a library, look at the lib/locking source code directory.
+.TP
+\fBtags\fP \(em Host tag settings
+.IP
+\fBhosttags\fP \(em If set to 1, create a host tag with the machine name.
+Setting this to 0 does nothing, neither creating nor destroying any tag.
+The machine name used is the nodename as returned by \fBuname\fP (2).
+.IP
+Additional host tags to be set can be listed here as subsections. 
+The @ prefix for tags is optional.
+Each of these host tag subsections can contain a \fBhost_list\fP 
+array of host names. If any one of these entries matches the machine 
+name exactly then the host tag gets defined on this particular host, 
+otherwise it doesn't.
+.IP
+After lvm.conf has been processed, LVM2 works through each host
+tag that has been defined in turn, and if there is a configuration
+file called lvm_\fB<host_tag>\fP.conf it attempts to load it.
+Any settings read in override settings found in earlier files.
+Any additional host tags defined get appended to the search list,
+so in turn they can lead to further configuration files being processed.
+Use \fBlvm dumpconfig\fP to check the result of config
+file processing.
+.IP
+The following example always sets host tags \fBtag1\fP and
+sets \fBtag2\fP on machines fs1 and fs2:
+.IP
+tags { tag1 { } tag2 { host_list = [ "fs1", "fs2" ] } }
+.IP
+These options are useful if you are replicating configuration files
+around a cluster.  Use of \fBhosttags = 1\fP means every machine
+can have static and identical local configuration files yet use 
+different settings and activate different logical volumes by
+default.  See also \fBvolume_list\fP below and \fB--addtag\fP 
+in \fBlvm\fP (8).
+.TP
+\fBactivation\fP \(em Settings affecting device-mapper activation
+.IP
+\fBmissing_stripe_filler\fP \(em When activating an incomplete logical
+volume in partial mode, this option dictates how the missing data is
+replaced.  A value of "error" will cause activation to create error
+mappings for the missing data, meaning that read access to missing
+portions of the volume will result in I/O errors. You can instead also
+use a device path, and in that case this device will be used in place of
+missing stripes. However, note that using anything other than
+"error" with mirrored or snapshotted volumes is likely to result in data
+corruption.  For instructions on how to create a device that always
+returns zeros, see \fBlvcreate\fP (8).
+.IP
+\fBmirror_region_size\fP \(em Unit size in KB for copy operations
+when mirroring.
+.IP
+\fBreadahead\fP \(em Used when there is no readahead value stored 
+in the volume group metadata.  Set to \fBnone\fP to disable
+readahead in these circumstances or \fBauto\fP to use the default
+value chosen by the kernel.
+.IP
+\fBreserved_memory\fP, \fBreserved_stack\fP \(em How many KB to reserve 
+for LVM2 to use while logical volumes are suspended.  If insufficient 
+memory is reserved before suspension, there is a risk of machine deadlock.
+.IP
+\fBprocess_priority\fP \(em The nice value to use while devices are
+suspended.  This is set to a high priority so that logical volumes
+are suspended (with I/O generated by other processes to those
+logical volumes getting queued) for the shortest possible time.
+.IP
+\fBvolume_list\fP \(em This acts as a filter through which
+all requests to activate a logical volume on this machine
+are passed.  A logical volume is only activated if it matches
+an item in the list.  Tags must be preceded by @ and are checked
+against all tags defined in the logical volume and volume group 
+metadata for a match.
+@* is short-hand to check every tag set on the host machine (see
+\fBtags\fP above).
+Logical volume and volume groups can also be included in the list
+by name e.g. vg00, vg00/lvol1.
+.TP
+\fBmetadata\fP \(em Advanced metadata settings
+.IP
+\fBpvmetadatacopies\fP \(em When creating a physical volume using the
+LVM2 metadata format, this is the default number of copies of metadata
+to store on each physical volume.  
+Currently it can be set to 0, 1 or 2.  The default is 1.  
+If set to 2, one copy is placed at the beginning of the disk
+and the other is placed at the end.
+It can be overridden on the command line with \fB--metadatacopies\fP.
+If creating a volume group with just one physical volume, it's a
+good idea to have 2 copies.  If creating a large volume group with
+many physical volumes, you may decide that 3 copies of the metadata
+is sufficient, i.e. setting it to 1 on three of the physical volumes,
+and 0 on the rest.  Every volume group must contain at least one 
+physical volume with at least 1 copy of the metadata (unless using
+the text files described below).  The disadvantage of having lots
+of copies is that every time the tools access the volume group, every
+copy of the metadata has to be accessed, and this slows down the
+tools.
+.IP
+\fBpvmetadatasize\fP \(em Approximate number of sectors to set aside
+for each copy of the metadata. Volume groups with large numbers of
+physical or logical volumes, or volumes groups containing complex 
+logical volume structures will need additional space for their metadata.
+The metadata areas are treated as circular buffers, so
+unused space becomes filled with an archive of the most recent
+previous versions of the metadata.
+.IP
+\fBdirs\fP \(em List of directories holding live copies of LVM2
+metadata as text files.  These directories must not be on logical
+volumes.  It is possible to use LVM2 with a couple of directories
+here, preferably on different (non-logical-volume) filesystems
+and with no other on-disk metadata, \fBpvmetadatacopies = 0\fP.
+Alternatively these directories can be in addition to the
+on-disk metadata areas.  This feature was created during the
+development of the LVM2 metadata before the new on-disk metadata
+areas were designed and no longer gets tested.  
+It is not supported under low-memory conditions, and it is 
+important never to edit these metadata files unless you fully 
+understand how things work: to make changes you should always use 
+the tools as normal, or else vgcfgbackup, edit backup, vgcfgrestore.
+.SH FILES
+.I /etc/lvm/lvm.conf
+.I /etc/lvm/archive
+.I /etc/lvm/backup
+.I /etc/lvm/cache/.cache
+.I /var/lock/lvm
+.SH SEE ALSO
+.BR lvm (8),
+.BR umask (2),
+.BR uname (2),
+.BR dlopen (3),
+.BR syslog (3),
+.BR syslog.conf (5)
Index: src/external/gpl2/lvm2tools/dist/man/lvmchange.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvmchange.8
diff -N src/external/gpl2/lvm2tools/dist/man/lvmchange.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvmchange.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,12 @@
+.\"	$NetBSD$
+.\"
+.TH LVMCHANGE 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvmchange \- change attributes of the logical volume manager
+.SH SYNOPSIS
+.B lvmchange
+.SH DESCRIPTION
+lvmchange is not currently supported under LVM2, although
+\fBdmsetup (8)\fP has a \fBremove_all\fP command.
+.SH SEE ALSO
+.BR dmsetup (8)
Index: src/external/gpl2/lvm2tools/dist/man/lvmchange.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvmchange.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/lvmchange.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvmchange.8.in	12 Dec 2008 16:33:01 -0000	1.1.1.1.2.2
@@ -0,0 +1,10 @@
+.TH LVMCHANGE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvmchange \- change attributes of the logical volume manager
+.SH SYNOPSIS
+.B lvmchange
+.SH DESCRIPTION
+lvmchange is not currently supported under LVM2, although
+\fBdmsetup (8)\fP has a \fBremove_all\fP command.
+.SH SEE ALSO
+.BR dmsetup (8)
Index: src/external/gpl2/lvm2tools/dist/man/lvmdiskscan.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvmdiskscan.8
diff -N src/external/gpl2/lvm2tools/dist/man/lvmdiskscan.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvmdiskscan.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,26 @@
+.\"	$NetBSD$
+.\"
+.TH LVMDISKSCAN 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvmdiskscan \- scan for all devices visible to LVM2
+.SH SYNOPSIS
+.B lvmdiskscan
+[\-d/\-\-debug] [\-h/\-?/\-\-help] 
+[\-l/\-\-lvmpartition]
+[\-v/\-\-verbose]
+.SH DESCRIPTION
+\fBlvmdiskscan\fP scans all SCSI, (E)IDE disks, multiple devices and a bunch
+of other block devices in the system looking for LVM physical volumes.
+The size reported is the real device size.
+Define a filter in \fBlvm.conf\fP(5) to restrict 
+the scan to avoid a CD ROM, for example.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-l, \-\-lvmpartition
+Only reports Physical Volumes.
+.SH SEE ALSO
+.BR lvm (8), 
+.BR lvm.conf (5),
+.BR pvscan (8),
+.BR vgscan (8)
Index: src/external/gpl2/lvm2tools/dist/man/lvmdiskscan.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvmdiskscan.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/lvmdiskscan.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvmdiskscan.8.in	12 Dec 2008 16:33:01 -0000	1.1.1.1.2.2
@@ -0,0 +1,24 @@
+.TH LVMDISKSCAN 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvmdiskscan \- scan for all devices visible to LVM2
+.SH SYNOPSIS
+.B lvmdiskscan
+[\-d/\-\-debug] [\-h/\-?/\-\-help] 
+[\-l/\-\-lvmpartition]
+[\-v/\-\-verbose]
+.SH DESCRIPTION
+\fBlvmdiskscan\fP scans all SCSI, (E)IDE disks, multiple devices and a bunch
+of other block devices in the system looking for LVM physical volumes.
+The size reported is the real device size.
+Define a filter in \fBlvm.conf\fP(5) to restrict 
+the scan to avoid a CD ROM, for example.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-l, \-\-lvmpartition
+Only reports Physical Volumes.
+.SH SEE ALSO
+.BR lvm (8), 
+.BR lvm.conf (5),
+.BR pvscan (8),
+.BR vgscan (8)
Index: src/external/gpl2/lvm2tools/dist/man/lvmdump.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvmdump.8
diff -N src/external/gpl2/lvm2tools/dist/man/lvmdump.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvmdump.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,52 @@
+.\"	$NetBSD$
+.\"
+.TH LVMDUMP 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Red Hat, Inc."
+.SH NAME
+lvmdump - create lvm2 information dumps for diagnostic purposes
+.SH SYNOPSIS
+\fBlvmdump\fP [options] [-d directory]
+.SH DESCRIPTION
+\fBlvmdump\fP is a tool to dump various information concerning LVM2. By default, it creates a tarball suitable for submission along with a problem report.
+.PP
+The content of the tarball is as follows:
+.br
+- dmsetup info
+.br
+- table of currently running processes
+.br
+- recent entries from /var/log/messages (containing system messages)
+.br
+- complete lvm configuration and cache
+.br
+- list of device nodes present under /dev
+.br
+- if enabled with -m, metadata dump will be also included
+.br
+- if enabled with -a, debug output of vgscan, pvscan and list of all available volume groups, physical volumes and logical volumes will be included
+.br
+- if enabled with -c, cluster status info
+.SH OPTIONS
+.TP
+\fB\-h\fR \(em print help message
+.TP
+\fB\-a\fR \(em advanced collection 
+\fBWARNING\fR: if lvm is already hung, then this script may hang as well if \fB\-a\fR is used
+.TP
+\fB\-m\fR \(em gather LVM metadata from the PVs
+This option generates a 1:1 dump of the metadata area from all PVs visible to the system, which can cause the dump to increase in size considerably. However, the metadata dump may represent a valuable diagnostic resource.
+.TP
+\fB\-d\fR directory \(em dump into a directory instead of tarball
+By default, lvmdump will produce a single compressed tarball containing all the information. Using this option, it can be instructed to only produce the raw dump tree, rooted in \fBdirectory\fP.
+.TP
+\fB\-c\fR \(em if clvmd is running, gather cluster data as well
+.SH ENVIRONMENT VARIABLES
+.TP
+\fBLVM_BINARY\fP 
+The LVM2 binary to use.
+Defaults to "lvm".
+Sometimes you might need to set this to "/sbin/lvm.static", for example.
+.TP
+\fBDMSETUP_BINARY\fP 
+The dmsetup binary to use.
+Defaults to "dmsetup".
+.PP
Index: src/external/gpl2/lvm2tools/dist/man/lvmdump.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvmdump.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/lvmdump.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvmdump.8.in	12 Dec 2008 16:33:01 -0000	1.1.1.1.2.2
@@ -0,0 +1,50 @@
+.TH LVMDUMP 8 "LVM TOOLS #VERSION#" "Red Hat, Inc."
+.SH NAME
+lvmdump - create lvm2 information dumps for diagnostic purposes
+.SH SYNOPSIS
+\fBlvmdump\fP [options] [-d directory]
+.SH DESCRIPTION
+\fBlvmdump\fP is a tool to dump various information concerning LVM2. By default, it creates a tarball suitable for submission along with a problem report.
+.PP
+The content of the tarball is as follows:
+.br
+- dmsetup info
+.br
+- table of currently running processes
+.br
+- recent entries from /var/log/messages (containing system messages)
+.br
+- complete lvm configuration and cache
+.br
+- list of device nodes present under /dev
+.br
+- if enabled with -m, metadata dump will be also included
+.br
+- if enabled with -a, debug output of vgscan, pvscan and list of all available volume groups, physical volumes and logical volumes will be included
+.br
+- if enabled with -c, cluster status info
+.SH OPTIONS
+.TP
+\fB\-h\fR \(em print help message
+.TP
+\fB\-a\fR \(em advanced collection 
+\fBWARNING\fR: if lvm is already hung, then this script may hang as well if \fB\-a\fR is used
+.TP
+\fB\-m\fR \(em gather LVM metadata from the PVs
+This option generates a 1:1 dump of the metadata area from all PVs visible to the system, which can cause the dump to increase in size considerably. However, the metadata dump may represent a valuable diagnostic resource.
+.TP
+\fB\-d\fR directory \(em dump into a directory instead of tarball
+By default, lvmdump will produce a single compressed tarball containing all the information. Using this option, it can be instructed to only produce the raw dump tree, rooted in \fBdirectory\fP.
+.TP
+\fB\-c\fR \(em if clvmd is running, gather cluster data as well
+.SH ENVIRONMENT VARIABLES
+.TP
+\fBLVM_BINARY\fP 
+The LVM2 binary to use.
+Defaults to "lvm".
+Sometimes you might need to set this to "/sbin/lvm.static", for example.
+.TP
+\fBDMSETUP_BINARY\fP 
+The dmsetup binary to use.
+Defaults to "dmsetup".
+.PP
Index: src/external/gpl2/lvm2tools/dist/man/lvreduce.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvreduce.8
diff -N src/external/gpl2/lvm2tools/dist/man/lvreduce.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvreduce.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,69 @@
+.\"	$NetBSD$
+.\"
+.TH LVREDUCE 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvreduce \- reduce the size of a logical volume
+.SH SYNOPSIS
+.B lvreduce
+[\-A/\-\-autobackup y/n] [\-d/\-\-debug] [\-f/\-\-force]
+[\-h/\-?/\-\-help]
+{\-l/\-\-extents [\-]LogicalExtentsNumber[%{VG|LV|FREE}] |
+\-L/\-\-size [\-]LogicalVolumeSize[kKmMgGtT]}
+[\-t/\-\-test]
+[\-v/\-\-verbose] LogicalVolume[Path]
+.SH DESCRIPTION
+lvreduce allows you to reduce the size of a logical volume.
+Be careful when reducing a logical volume's size, because data in the
+reduced part is lost!!! 
+.br 
+You should therefore ensure that any filesystem on the volume is 
+resized
+.I before
+running lvreduce so that the extents that are to be removed are not in use.
+.br
+Shrinking snapshot logical volumes (see
+.B lvcreate(8)
+for information to create snapshots) is supported as well.
+But to change the number of copies in a mirrored logical
+volume use 
+.B lvconvert (8).
+.br
+Sizes will be rounded if necessary - for example, the volume size must
+be an exact number of extents and the size of a striped segment must
+be a multiple of the number of stripes.
+.br
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-f, \-\-force
+Force size reduction without any question.
+.TP
+.I \-l, \-\-extents [\-]LogicalExtentsNumber[%{VG|LV|FREE}]
+Reduce or set the logical volume size in units of logical extents.
+With the - sign the value will be subtracted from
+the logical volume's actual size and without it the will be taken as
+an absolute size.
+The number can also be expressed as a percentage of the total space
+in the Volume Group with the suffix %VG or relative to the existing
+size of the Logical Volume with the suffix %LV or as a percentage of the remaining
+free space in the Volume Group with the suffix %FREE.
+.TP
+.I \-L, \-\-size [\-]LogicalVolumeSize[kKmMgGtTpPeE]
+Reduce or set the logical volume size in units of megabyte by default.
+A size suffix of k for kilobyte, m for megabyte, 
+g for gigabytes, t for terabytes, p for petabytes 
+or e for exabytes is optional.
+With the - sign the value will be subtracted from
+the logical volume's actual size and without it it will be taken as
+an absolute size.
+.SH Example
+"lvreduce -l -3 vg00/lvol1" reduces the size of logical volume lvol1
+in volume group vg00 by 3 logical extents.
+.SH SEE ALSO
+.BR lvchange (8),
+.BR lvconvert (8), 
+.BR lvcreate (8), 
+.BR lvextend (8), 
+.BR lvm (8), 
+.BR lvresize (8),
+.BR vgreduce (8)
Index: src/external/gpl2/lvm2tools/dist/man/lvreduce.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvreduce.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/lvreduce.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvreduce.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,67 @@
+.TH LVREDUCE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvreduce \- reduce the size of a logical volume
+.SH SYNOPSIS
+.B lvreduce
+[\-A/\-\-autobackup y/n] [\-d/\-\-debug] [\-f/\-\-force]
+[\-h/\-?/\-\-help]
+{\-l/\-\-extents [\-]LogicalExtentsNumber[%{VG|LV|FREE}] |
+\-L/\-\-size [\-]LogicalVolumeSize[kKmMgGtT]}
+[\-t/\-\-test]
+[\-v/\-\-verbose] LogicalVolume[Path]
+.SH DESCRIPTION
+lvreduce allows you to reduce the size of a logical volume.
+Be careful when reducing a logical volume's size, because data in the
+reduced part is lost!!! 
+.br 
+You should therefore ensure that any filesystem on the volume is 
+resized
+.I before
+running lvreduce so that the extents that are to be removed are not in use.
+.br
+Shrinking snapshot logical volumes (see
+.B lvcreate(8)
+for information to create snapshots) is supported as well.
+But to change the number of copies in a mirrored logical
+volume use 
+.B lvconvert (8).
+.br
+Sizes will be rounded if necessary - for example, the volume size must
+be an exact number of extents and the size of a striped segment must
+be a multiple of the number of stripes.
+.br
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-f, \-\-force
+Force size reduction without any question.
+.TP
+.I \-l, \-\-extents [\-]LogicalExtentsNumber[%{VG|LV|FREE}]
+Reduce or set the logical volume size in units of logical extents.
+With the - sign the value will be subtracted from
+the logical volume's actual size and without it the will be taken as
+an absolute size.
+The number can also be expressed as a percentage of the total space
+in the Volume Group with the suffix %VG or relative to the existing
+size of the Logical Volume with the suffix %LV or as a percentage of the remaining
+free space in the Volume Group with the suffix %FREE.
+.TP
+.I \-L, \-\-size [\-]LogicalVolumeSize[kKmMgGtTpPeE]
+Reduce or set the logical volume size in units of megabyte by default.
+A size suffix of k for kilobyte, m for megabyte, 
+g for gigabytes, t for terabytes, p for petabytes 
+or e for exabytes is optional.
+With the - sign the value will be subtracted from
+the logical volume's actual size and without it it will be taken as
+an absolute size.
+.SH Example
+"lvreduce -l -3 vg00/lvol1" reduces the size of logical volume lvol1
+in volume group vg00 by 3 logical extents.
+.SH SEE ALSO
+.BR lvchange (8),
+.BR lvconvert (8), 
+.BR lvcreate (8), 
+.BR lvextend (8), 
+.BR lvm (8), 
+.BR lvresize (8),
+.BR vgreduce (8)
Index: src/external/gpl2/lvm2tools/dist/man/lvremove.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvremove.8
diff -N src/external/gpl2/lvm2tools/dist/man/lvremove.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvremove.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,42 @@
+.\"	$NetBSD$
+.\"
+.TH LVREMOVE 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvremove \- remove a logical volume
+.SH SYNOPSIS
+.B lvremove
+[\-A/\-\-autobackup y/n] [\-d/\-\-debug] [\-f/\-\-force]
+[\-h/\-?/\-\-help] 
+[\-t/\-\-test]
+[\-v/\-\-verbose] LogicalVolumePath [LogicalVolumePath...]
+.SH DESCRIPTION
+\fBlvremove\fP removes one or more logical volumes.
+Confirmation will be requested before deactivating any active logical
+volume prior to removal.  Logical volumes cannot be deactivated
+or removed while they are open (e.g. if they contain a mounted filesystem).
+.sp
+If the logical volume is clustered then it must be deactivated on all
+nodes in the cluster before it can be removed. A single lvchange command
+issued from one node can do this.
+.SH OPTIONS
+See \fBlvm\fP(8) for common options.
+.TP
+.I \-f, \-\-force
+Remove active logical volumes without confirmation.
+.SH EXAMPLES
+Remove the active logical volume lvol1 in volume group vg00 
+without asking for confirmation:
+.sp
+\	\fBlvremove -f vg00/lvol1\fP
+.sp
+Remove all logical volumes in volume group vg00:
+.sp
+\	\fBlvremove vg00\fP
+.SH SEE ALSO
+.BR lvcreate (8), 
+.BR lvdisplay (8),
+.BR lvchange (8),  
+.BR lvm (8), 
+.BR lvs (8),
+.BR lvscan (8),
+.BR vgremove (8)
Index: src/external/gpl2/lvm2tools/dist/man/lvremove.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvremove.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/lvremove.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvremove.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,40 @@
+.TH LVREMOVE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvremove \- remove a logical volume
+.SH SYNOPSIS
+.B lvremove
+[\-A/\-\-autobackup y/n] [\-d/\-\-debug] [\-f/\-\-force]
+[\-h/\-?/\-\-help] 
+[\-t/\-\-test]
+[\-v/\-\-verbose] LogicalVolumePath [LogicalVolumePath...]
+.SH DESCRIPTION
+\fBlvremove\fP removes one or more logical volumes.
+Confirmation will be requested before deactivating any active logical
+volume prior to removal.  Logical volumes cannot be deactivated
+or removed while they are open (e.g. if they contain a mounted filesystem).
+.sp
+If the logical volume is clustered then it must be deactivated on all
+nodes in the cluster before it can be removed. A single lvchange command
+issued from one node can do this.
+.SH OPTIONS
+See \fBlvm\fP(8) for common options.
+.TP
+.I \-f, \-\-force
+Remove active logical volumes without confirmation.
+.SH EXAMPLES
+Remove the active logical volume lvol1 in volume group vg00 
+without asking for confirmation:
+.sp
+\	\fBlvremove -f vg00/lvol1\fP
+.sp
+Remove all logical volumes in volume group vg00:
+.sp
+\	\fBlvremove vg00\fP
+.SH SEE ALSO
+.BR lvcreate (8), 
+.BR lvdisplay (8),
+.BR lvchange (8),  
+.BR lvm (8), 
+.BR lvs (8),
+.BR lvscan (8),
+.BR vgremove (8)
Index: src/external/gpl2/lvm2tools/dist/man/lvrename.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvrename.8
diff -N src/external/gpl2/lvm2tools/dist/man/lvrename.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvrename.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,49 @@
+.\"	$NetBSD$
+.\"
+.TH LVRENAME 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvrename \- rename a logical volume
+.SH SYNOPSIS
+.B lvrename
+.RB [ \-A | \-\-autobackup " {" y | n }]
+.RB [ \-d | \-\-debug ]
+.RB [ \-f | \-\-force ]
+.RB [ \-h | \-\-help ]
+.RB [ \-t | \-\-test ]
+.RB [ \-v | \-\-verbose ]
+.RB [ \-\-version ]
+.TP
+.IR "OldLogicalVolumePath NewLogicalVolume" { Path | Name }
+.TP
+.I VolumeGroupName OldLogicalVolumeName NewLogicalVolumeName
+.SH DESCRIPTION
+.B lvrename
+renames an existing logical volume from
+.IR OldLogicalVolume { Name | Path }
+to
+.IR NewLogicalVolume { Name | Path }.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.SH EXAMPLE
+To rename
+.B lvold
+in volume group
+.B vg02
+to
+.BR lvnew :
+.nf
+
+\	lvrename /dev/vg02/lvold /dev/vg02/lvnew
+
+.fi
+An alternate syntax to rename this logical volume is
+.nf
+
+\	lvrename vg02 lvold lvnew
+
+.fi
+.SH SEE ALSO
+.BR lvm (8), 
+.BR lvchange (8),
+.BR vgcreate (8), 
+.BR vgrename (8)
Index: src/external/gpl2/lvm2tools/dist/man/lvrename.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvrename.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/lvrename.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvrename.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,47 @@
+.TH LVRENAME 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvrename \- rename a logical volume
+.SH SYNOPSIS
+.B lvrename
+.RB [ \-A | \-\-autobackup " {" y | n }]
+.RB [ \-d | \-\-debug ]
+.RB [ \-f | \-\-force ]
+.RB [ \-h | \-\-help ]
+.RB [ \-t | \-\-test ]
+.RB [ \-v | \-\-verbose ]
+.RB [ \-\-version ]
+.TP
+.IR "OldLogicalVolumePath NewLogicalVolume" { Path | Name }
+.TP
+.I VolumeGroupName OldLogicalVolumeName NewLogicalVolumeName
+.SH DESCRIPTION
+.B lvrename
+renames an existing logical volume from
+.IR OldLogicalVolume { Name | Path }
+to
+.IR NewLogicalVolume { Name | Path }.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.SH EXAMPLE
+To rename
+.B lvold
+in volume group
+.B vg02
+to
+.BR lvnew :
+.nf
+
+\	lvrename /dev/vg02/lvold /dev/vg02/lvnew
+
+.fi
+An alternate syntax to rename this logical volume is
+.nf
+
+\	lvrename vg02 lvold lvnew
+
+.fi
+.SH SEE ALSO
+.BR lvm (8), 
+.BR lvchange (8),
+.BR vgcreate (8), 
+.BR vgrename (8)
Index: src/external/gpl2/lvm2tools/dist/man/lvresize.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvresize.8
diff -N src/external/gpl2/lvm2tools/dist/man/lvresize.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvresize.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,68 @@
+.\"	$NetBSD$
+.\"
+.TH LVRESIZE 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvresize \- resize a logical volume
+.SH SYNOPSIS
+.B lvresize
+[\-\-alloc AllocationPolicy]
+[\-A/\-\-autobackup y/n] [\-d/\-\-debug] [\-h/\-?/\-\-help]
+[\-i/\-\-stripes Stripes [\-I/\-\-stripesize StripeSize]]
+{\-l/\-\-extents [+]LogicalExtentsNumber[%{VG|LV|PVS|FREE}] |
+\-L/\-\-size [+]LogicalVolumeSize[kKmMgGtT]}
+[\-t/\-\-test]
+[\-v/\-\-verbose] LogicalVolumePath [PhysicalVolumePath...]
+.SH DESCRIPTION
+lvresize allows you to resize a logical volume.
+Be careful when reducing a logical volume's size, because data in the reduced
+part is lost!!!
+You should therefore ensure that any filesystem on the volume is
+shrunk first so that the extents that are to be removed are not in use.
+Resizing snapshot logical volumes (see
+.B lvcreate(8)
+for information about creating snapshots) is supported as well.
+But to change the number of copies in a mirrored logical
+volume use 
+.BR lvconvert (8).
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-l, \-\-extents [+/-]LogicalExtentsNumber[%{VG|LV|PVS|FREE}]
+Change or set the logical volume size in units of logical extents.
+With the + or - sign the value is added to or subtracted from the actual size
+of the logical volume and without it, the value is taken as an absolute one.
+The number can also be expressed as a percentage of the total space
+in the Volume Group with the suffix %VG, relative to the existing
+size of the Logical Volume with the suffix %LV, as a percentage of
+the remaining free space of the PhysicalVolumes on the command line with the
+suffix %PVS, or as a percentage of the remaining free space in the
+Volume Group with the suffix %FREE.
+.TP
+.I \-L, \-\-size [+/-]LogicalVolumeSize[kKmMgGtTpPeE]
+Change or set the logical volume size in units of megabytes.
+A size suffix of M for megabytes,
+G for gigabytes, T for terabytes, P for petabytes 
+or E for exabytes is optional.
+With the + or - sign the value is added to or subtracted from
+the actual size of the logical volume and without it, the value is taken as an
+absolute one.
+.TP
+.I \-i, \-\-stripes Stripes
+Gives the number of stripes to use when extending a Logical Volume.
+Defaults to whatever the last segment of the Logical Volume uses.
+Not applicable to LVs using the original metadata LVM format, which must
+use a single value throughout.
+.TP
+.I \-I, \-\-stripesize StripeSize
+Gives the number of kilobytes for the granularity of the stripes.
+Defaults to whatever the last segment of the Logical Volume uses.
+Not applicable to LVs using the original metadata LVM format, which
+must use a single value throughout.
+.br
+StripeSize must be 2^n (n = 2 to 9)
+.SH SEE ALSO
+.BR lvm (8), 
+.BR lvconvert (8),
+.BR lvcreate (8), 
+.BR lvreduce (8), 
+.BR lvchange (8)
Index: src/external/gpl2/lvm2tools/dist/man/lvresize.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvresize.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/lvresize.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvresize.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,66 @@
+.TH LVRESIZE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvresize \- resize a logical volume
+.SH SYNOPSIS
+.B lvresize
+[\-\-alloc AllocationPolicy]
+[\-A/\-\-autobackup y/n] [\-d/\-\-debug] [\-h/\-?/\-\-help]
+[\-i/\-\-stripes Stripes [\-I/\-\-stripesize StripeSize]]
+{\-l/\-\-extents [+]LogicalExtentsNumber[%{VG|LV|PVS|FREE}] |
+\-L/\-\-size [+]LogicalVolumeSize[kKmMgGtT]}
+[\-t/\-\-test]
+[\-v/\-\-verbose] LogicalVolumePath [PhysicalVolumePath...]
+.SH DESCRIPTION
+lvresize allows you to resize a logical volume.
+Be careful when reducing a logical volume's size, because data in the reduced
+part is lost!!!
+You should therefore ensure that any filesystem on the volume is
+shrunk first so that the extents that are to be removed are not in use.
+Resizing snapshot logical volumes (see
+.B lvcreate(8)
+for information about creating snapshots) is supported as well.
+But to change the number of copies in a mirrored logical
+volume use 
+.BR lvconvert (8).
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-l, \-\-extents [+/-]LogicalExtentsNumber[%{VG|LV|PVS|FREE}]
+Change or set the logical volume size in units of logical extents.
+With the + or - sign the value is added to or subtracted from the actual size
+of the logical volume and without it, the value is taken as an absolute one.
+The number can also be expressed as a percentage of the total space
+in the Volume Group with the suffix %VG, relative to the existing
+size of the Logical Volume with the suffix %LV, as a percentage of
+the remaining free space of the PhysicalVolumes on the command line with the
+suffix %PVS, or as a percentage of the remaining free space in the
+Volume Group with the suffix %FREE.
+.TP
+.I \-L, \-\-size [+/-]LogicalVolumeSize[kKmMgGtTpPeE]
+Change or set the logical volume size in units of megabytes.
+A size suffix of M for megabytes,
+G for gigabytes, T for terabytes, P for petabytes 
+or E for exabytes is optional.
+With the + or - sign the value is added to or subtracted from
+the actual size of the logical volume and without it, the value is taken as an
+absolute one.
+.TP
+.I \-i, \-\-stripes Stripes
+Gives the number of stripes to use when extending a Logical Volume.
+Defaults to whatever the last segment of the Logical Volume uses.
+Not applicable to LVs using the original metadata LVM format, which must
+use a single value throughout.
+.TP
+.I \-I, \-\-stripesize StripeSize
+Gives the number of kilobytes for the granularity of the stripes.
+Defaults to whatever the last segment of the Logical Volume uses.
+Not applicable to LVs using the original metadata LVM format, which
+must use a single value throughout.
+.br
+StripeSize must be 2^n (n = 2 to 9)
+.SH SEE ALSO
+.BR lvm (8), 
+.BR lvconvert (8),
+.BR lvcreate (8), 
+.BR lvreduce (8), 
+.BR lvchange (8)
Index: src/external/gpl2/lvm2tools/dist/man/lvs.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvs.8
diff -N src/external/gpl2/lvm2tools/dist/man/lvs.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvs.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,91 @@
+.\"	$NetBSD$
+.\"
+.TH LVS 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvs \- report information about logical volumes
+.SH SYNOPSIS
+.B lvs
+[\-\-aligned] [\-d/\-\-debug] [\-h/\-?/\-\-help]
+[\-\-ignorelockingfailure] [\-\-noheadings] [\-\-nosuffix]
+[\-o/\-\-options [+]Field[,Field]]
+[\-O/\-\-sort [+/-]Key1[,[+/-]Key2[,...]]]
+[\-P/\-\-partial] [\-\-segments]
+[\-\-separator Separator] [\-\-unbuffered]
+[\-\-units hsbkmgtHKMGT]
+[\-v/\-\-verbose] 
+[\-\-version] [VolumeGroupName [VolumeGroupName...]]
+.SH DESCRIPTION
+lvs produces formatted output about logical volumes.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-\-aligned
+Use with \-\-separator to align the output columns.
+.TP
+.I \-\-noheadings
+Suppress the headings line that is normally the first line of output.
+Useful if grepping the output.
+.TP
+.I \-\-nosuffix
+Suppress the suffix on output sizes.  Use with \-\-units (except h and H)
+if processing the output.
+.TP
+.I \-o, \-\-options
+Comma-separated ordered list of columns.  Precede the list with '+' to append
+to the default selection of columns instead of replacing it.  Column names are: 
+lv_uuid, lv_name, lv_attr, lv_major, lv_minor, lv_kernel_major, lv_kernel_minor,
+lv_size, seg_count, origin, snap_percent,
+copy_percent, move_pv, lv_tags,
+segtype, stripes,
+stripesize, chunksize, seg_start, seg_size, seg_tags, devices,
+regionsize, mirror_log, modules.
+.IP
+With \-\-segments, any "seg_" prefixes are optional; otherwise any "lv_"
+prefixes are optional.  Columns mentioned in \fBvgs (8)\fP 
+can also be chosen.
+Use \fb-o help\fP to view the full list of fields available.
+.IP
+The lv_attr bits are: 
+.RS
+.IP 1 3
+Volume type: (m)irrored, (M)irrored without initial sync, (o)rigin, (p)vmove, (s)napshot, 
+invalid (S)napshot, (v)irtual, mirror (i)mage, mirror (I)mage out-of-sync,
+under (c)onversion
+.IP 2 3
+Permissions: (w)riteable, (r)ead-only
+.IP 3 3
+Allocation policy: (c)ontiguous, c(l)ing, (n)ormal, (a)nywhere, (i)nherited
+This is capitalised if the volume is currently locked against allocation
+changes, for example during \fBpvmove\fP (8).
+.IP 4 3
+fixed (m)inor
+.IP 5 3
+State: (a)ctive, (s)uspended, (I)nvalid snapshot, invalid (S)uspended snapshot,
+mapped (d)evice present without tables, mapped device present with (i)nactive table
+.IP 6 3
+device (o)pen
+.RE
+.TP
+.I \-\-segments
+Use default columns that emphasize segment information.
+.TP
+.I \-O, \-\-sort
+Comma-separated ordered list of columns to sort by.  Replaces the default
+selection. Precede any column with - for a reverse sort on that column.
+.TP
+.I \-\-separator Separator
+String to use to separate each column.  Useful if grepping the output.
+.TP
+.I \-\-unbuffered
+Produce output immediately without sorting or aligning the columns properly.
+.TP
+.I \-\-units hsbkmgtHKMGT
+All sizes are output in these units: (h)uman-readable, (s)ectors, (b)ytes,
+(k)ilobytes, (m)egabytes, (g)igabytes, (t)erabytes.  Capitalise to use multiples
+of 1000 (S.I.) instead of 1024.  Can also specify custom (u)nits e.g.
+\-\-units 3M
+.SH SEE ALSO
+.BR lvm (8),
+.BR lvdisplay (8),
+.BR pvs (8),
+.BR vgs (8)
Index: src/external/gpl2/lvm2tools/dist/man/lvs.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvs.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/lvs.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvs.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,89 @@
+.TH LVS 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvs \- report information about logical volumes
+.SH SYNOPSIS
+.B lvs
+[\-\-aligned] [\-d/\-\-debug] [\-h/\-?/\-\-help]
+[\-\-ignorelockingfailure] [\-\-noheadings] [\-\-nosuffix]
+[\-o/\-\-options [+]Field[,Field]]
+[\-O/\-\-sort [+/-]Key1[,[+/-]Key2[,...]]]
+[\-P/\-\-partial] [\-\-segments]
+[\-\-separator Separator] [\-\-unbuffered]
+[\-\-units hsbkmgtHKMGT]
+[\-v/\-\-verbose] 
+[\-\-version] [VolumeGroupName [VolumeGroupName...]]
+.SH DESCRIPTION
+lvs produces formatted output about logical volumes.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-\-aligned
+Use with \-\-separator to align the output columns.
+.TP
+.I \-\-noheadings
+Suppress the headings line that is normally the first line of output.
+Useful if grepping the output.
+.TP
+.I \-\-nosuffix
+Suppress the suffix on output sizes.  Use with \-\-units (except h and H)
+if processing the output.
+.TP
+.I \-o, \-\-options
+Comma-separated ordered list of columns.  Precede the list with '+' to append
+to the default selection of columns instead of replacing it.  Column names are: 
+lv_uuid, lv_name, lv_attr, lv_major, lv_minor, lv_kernel_major, lv_kernel_minor,
+lv_size, seg_count, origin, snap_percent,
+copy_percent, move_pv, lv_tags,
+segtype, stripes,
+stripesize, chunksize, seg_start, seg_size, seg_tags, devices,
+regionsize, mirror_log, modules.
+.IP
+With \-\-segments, any "seg_" prefixes are optional; otherwise any "lv_"
+prefixes are optional.  Columns mentioned in \fBvgs (8)\fP 
+can also be chosen.
+Use \fb-o help\fP to view the full list of fields available.
+.IP
+The lv_attr bits are: 
+.RS
+.IP 1 3
+Volume type: (m)irrored, (M)irrored without initial sync, (o)rigin, (p)vmove, (s)napshot, 
+invalid (S)napshot, (v)irtual, mirror (i)mage, mirror (I)mage out-of-sync,
+under (c)onversion
+.IP 2 3
+Permissions: (w)riteable, (r)ead-only
+.IP 3 3
+Allocation policy: (c)ontiguous, c(l)ing, (n)ormal, (a)nywhere, (i)nherited
+This is capitalised if the volume is currently locked against allocation
+changes, for example during \fBpvmove\fP (8).
+.IP 4 3
+fixed (m)inor
+.IP 5 3
+State: (a)ctive, (s)uspended, (I)nvalid snapshot, invalid (S)uspended snapshot,
+mapped (d)evice present without tables, mapped device present with (i)nactive table
+.IP 6 3
+device (o)pen
+.RE
+.TP
+.I \-\-segments
+Use default columns that emphasize segment information.
+.TP
+.I \-O, \-\-sort
+Comma-separated ordered list of columns to sort by.  Replaces the default
+selection. Precede any column with - for a reverse sort on that column.
+.TP
+.I \-\-separator Separator
+String to use to separate each column.  Useful if grepping the output.
+.TP
+.I \-\-unbuffered
+Produce output immediately without sorting or aligning the columns properly.
+.TP
+.I \-\-units hsbkmgtHKMGT
+All sizes are output in these units: (h)uman-readable, (s)ectors, (b)ytes,
+(k)ilobytes, (m)egabytes, (g)igabytes, (t)erabytes.  Capitalise to use multiples
+of 1000 (S.I.) instead of 1024.  Can also specify custom (u)nits e.g.
+\-\-units 3M
+.SH SEE ALSO
+.BR lvm (8),
+.BR lvdisplay (8),
+.BR pvs (8),
+.BR vgs (8)
Index: src/external/gpl2/lvm2tools/dist/man/lvscan.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvscan.8
diff -N src/external/gpl2/lvm2tools/dist/man/lvscan.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvscan.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,27 @@
+.\"	$NetBSD$
+.\"
+.TH LVSCAN 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvscan \- scan (all disks) for logical volumes
+.SH SYNOPSIS
+.B lvscan
+.RB [ \-b | \-\-blockdevice ]
+.RB [ \-d | \-\-debug ]
+.RB [ \-h | \-\-help ]
+.RB [ \-\-ignorelockingfailure ]
+.RB [ \-P | \-\-partial ]
+.RB [ \-v | \-\-verbose ]
+.SH DESCRIPTION
+.B lvscan
+scans all known volume groups or all supported LVM block devices
+in the system for defined logical volumes.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.BR \-b ", " \-\-blockdevice
+Adds the device major and minor numbers to the display
+of each logical volume.
+.SH SEE ALSO
+.BR lvm (8), 
+.BR lvcreate (8),
+.BR lvdisplay (8)
Index: src/external/gpl2/lvm2tools/dist/man/lvscan.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/lvscan.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/lvscan.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/lvscan.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,25 @@
+.TH LVSCAN 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+lvscan \- scan (all disks) for logical volumes
+.SH SYNOPSIS
+.B lvscan
+.RB [ \-b | \-\-blockdevice ]
+.RB [ \-d | \-\-debug ]
+.RB [ \-h | \-\-help ]
+.RB [ \-\-ignorelockingfailure ]
+.RB [ \-P | \-\-partial ]
+.RB [ \-v | \-\-verbose ]
+.SH DESCRIPTION
+.B lvscan
+scans all known volume groups or all supported LVM block devices
+in the system for defined logical volumes.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.BR \-b ", " \-\-blockdevice
+Adds the device major and minor numbers to the display
+of each logical volume.
+.SH SEE ALSO
+.BR lvm (8), 
+.BR lvcreate (8),
+.BR lvdisplay (8)
Index: src/external/gpl2/lvm2tools/dist/man/pvchange.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/pvchange.8
diff -N src/external/gpl2/lvm2tools/dist/man/pvchange.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/pvchange.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,36 @@
+.\"	$NetBSD$
+.\"
+.TH PVCHANGE 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+pvchange \- change attributes of a physical volume
+.SH SYNOPSIS
+.B pvchange
+[\-\-addtag Tag]
+[\-A/\-\-autobackup y/n] [\-d/\-\-debug] 
+[\-\-deltag Tag]
+[\-h/\-?/\-\-help]
+[\-t/\-\-test]
+[\-v/\-\-verbose] [\-a/\-\-all] [\-x/\-\-allocatable y/n]
+[\-u/\-\-uuid] [PhysicalVolumePath...]
+.SH DESCRIPTION
+pvchange allows you to change the allocation permissions of one or
+more physical volumes.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-a, \-\-all
+If PhysicalVolumePath is not specified on the command line all
+physical volumes are searched for and used.
+.TP
+.I \-u, \-\-uuid
+Generate new random UUID for specified physical volumes.
+.TP
+.I \-x, \-\-allocatable y/n
+Enable or disable allocation of physical extents on this physical volume.
+.SH Example
+"pvchange -x n /dev/sdk1" disallows the allocation of physical extents
+on this physical volume (possibly because of disk errors, or because it will
+be removed after freeing it.
+.SH SEE ALSO
+.BR lvm (8), 
+.BR pvcreate (8)
Index: src/external/gpl2/lvm2tools/dist/man/pvchange.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/pvchange.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/pvchange.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/pvchange.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,34 @@
+.TH PVCHANGE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+pvchange \- change attributes of a physical volume
+.SH SYNOPSIS
+.B pvchange
+[\-\-addtag Tag]
+[\-A/\-\-autobackup y/n] [\-d/\-\-debug] 
+[\-\-deltag Tag]
+[\-h/\-?/\-\-help]
+[\-t/\-\-test]
+[\-v/\-\-verbose] [\-a/\-\-all] [\-x/\-\-allocatable y/n]
+[\-u/\-\-uuid] [PhysicalVolumePath...]
+.SH DESCRIPTION
+pvchange allows you to change the allocation permissions of one or
+more physical volumes.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-a, \-\-all
+If PhysicalVolumePath is not specified on the command line all
+physical volumes are searched for and used.
+.TP
+.I \-u, \-\-uuid
+Generate new random UUID for specified physical volumes.
+.TP
+.I \-x, \-\-allocatable y/n
+Enable or disable allocation of physical extents on this physical volume.
+.SH Example
+"pvchange -x n /dev/sdk1" disallows the allocation of physical extents
+on this physical volume (possibly because of disk errors, or because it will
+be removed after freeing it.
+.SH SEE ALSO
+.BR lvm (8), 
+.BR pvcreate (8)
Index: src/external/gpl2/lvm2tools/dist/man/pvck.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/pvck.8
diff -N src/external/gpl2/lvm2tools/dist/man/pvck.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/pvck.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,35 @@
+.\"	$NetBSD$
+.\"
+.TH PVCK 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+pvck \- check physical volume metadata
+.SH SYNOPSIS
+.B pvck
+.RB [ \-d | \-\-debug ]
+.RB [ \-h | \-\-help ]
+.RB [ \-v | \-\-verbose ]
+.RB [ \-\-labelsector ]
+.IR PhysicalVolume " [" PhysicalVolume ...]
+.SH DESCRIPTION
+pvck checks physical volume LVM metadata for consistency.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.BR \-\-labelsector " sector"
+By default, 4 sectors of \fBPhysicalVolume\fP are scanned for an LVM label,
+starting at sector 0.  This parameter allows you to specify a different
+starting sector for the scan and is useful for recovery situations.  For
+example, suppose the partition table is corrupted or lost on /dev/sda,
+but you suspect there was an LVM partition at approximately 100 MB.  This
+area of the disk may be scanned by using the \fB--labelsector\fP parameter
+with a value of 204800 (100 * 1024 * 1024 / 512 = 204800):
+.sp
+.BI "pvck --labelsector 204800 /dev/sda"
+.sp
+Note that a script can be used with \fB--labelsector\fP to automate the
+process of finding LVM labels.
+.SH SEE ALSO
+.BR lvm (8),
+.BR pvcreate (8),
+.BR pvscan (8)
+.BR vgck (8)
Index: src/external/gpl2/lvm2tools/dist/man/pvck.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/pvck.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/pvck.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/pvck.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,33 @@
+.TH PVCK 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+pvck \- check physical volume metadata
+.SH SYNOPSIS
+.B pvck
+.RB [ \-d | \-\-debug ]
+.RB [ \-h | \-\-help ]
+.RB [ \-v | \-\-verbose ]
+.RB [ \-\-labelsector ]
+.IR PhysicalVolume " [" PhysicalVolume ...]
+.SH DESCRIPTION
+pvck checks physical volume LVM metadata for consistency.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.BR \-\-labelsector " sector"
+By default, 4 sectors of \fBPhysicalVolume\fP are scanned for an LVM label,
+starting at sector 0.  This parameter allows you to specify a different
+starting sector for the scan and is useful for recovery situations.  For
+example, suppose the partition table is corrupted or lost on /dev/sda,
+but you suspect there was an LVM partition at approximately 100 MB.  This
+area of the disk may be scanned by using the \fB--labelsector\fP parameter
+with a value of 204800 (100 * 1024 * 1024 / 512 = 204800):
+.sp
+.BI "pvck --labelsector 204800 /dev/sda"
+.sp
+Note that a script can be used with \fB--labelsector\fP to automate the
+process of finding LVM labels.
+.SH SEE ALSO
+.BR lvm (8),
+.BR pvcreate (8),
+.BR pvscan (8)
+.BR vgck (8)
Index: src/external/gpl2/lvm2tools/dist/man/pvcreate.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/pvcreate.8
diff -N src/external/gpl2/lvm2tools/dist/man/pvcreate.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/pvcreate.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,139 @@
+.\"	$NetBSD$
+.\"
+.TH PVCREATE 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+pvcreate \- initialize a disk or partition for use by LVM
+.SH SYNOPSIS
+.B pvcreate
+.RB [ \-d | \-\-debug ]
+.RB [ \-f [ f ]| \-\-force " [" \-\-force ]]
+.RB [ \-y | \-\-yes ]
+.RB [ \-h | \-\-help ]
+.RB [ \-t | \-\-test ]
+.RB [ \-v | \-\-verbose ]
+.RB [ \-\-labelsector ]
+.RB [ \-M | \-\-metadatatype type ]
+.RB [ \-\-metadatacopies #copies ]
+.RB [ \-\-metadatasize size ]
+.RB [ \-\-restorefile file ]
+.RB [ \-\-setphysicalvolumesize size ]
+.RB [ \-u | \-\-uuid uuid ]
+.RB [ \-\-version ]
+.RB [ \-Z | \-\-zero y/n ]
+.IR PhysicalVolume " [" PhysicalVolume ...]
+.SH DESCRIPTION
+.B pvcreate
+initializes
+.I PhysicalVolume
+for later use by the Logical Volume Manager (LVM).  Each
+.I PhysicalVolume
+can be a disk partition, whole disk, meta device, or loopback file.
+For DOS disk partitions, the partition id should be set to 0x8e using
+.BR fdisk "(8), " cfdisk "(8), "
+or a equivalent.  For
+.B whole disk devices only
+the partition table must be erased, which will effectively destroy all
+data on that disk.  This can be done by zeroing the first sector with:
+.sp
+.BI "dd if=/dev/zero of=" PhysicalVolume " bs=512 count=1"
+.sp
+Continue with
+.BR vgcreate (8)
+to create a new volume group on
+.IR PhysicalVolume ,
+or
+.BR vgextend (8)
+to add
+.I PhysicalVolume
+to an existing volume group.
+.SH OPTIONS
+See \fBlvm\fP(8) for common options.
+.TP
+.BR \-f ", " \-\-force
+Force the creation without any confirmation.  You can not recreate
+(reinitialize) a physical volume belonging to an existing volume group.
+In an emergency you can override this behaviour with -ff.
+.TP
+.BR \-u ", " \-\-uuid " uuid"
+Specify the uuid for the device.  
+Without this option, \fBpvcreate\fP generates a random uuid.
+All of your physical volumes must have unique uuids.
+You need to use this option before restoring a backup of LVM metadata 
+onto a replacement device - see \fBvgcfgrestore\fP(8).
+.TP
+.BR \-y ", " \-\-yes
+Answer yes to all questions.
+.TP
+.BR \-Z ", " \-\-zero " y/n"
+Whether or not the first 4 sectors (2048 bytes) of the device should be 
+wiped.
+If this option is not given, the 
+default is to wipe these sectors unless either or both of the --restorefile 
+or --uuid options were specified.
+.SH NEW METADATA OPTIONS
+LVM2 introduces a new format for storing metadata on disk.
+This new format is more efficient and resilient than the format the 
+original version of LVM used and offers the advanced user greater 
+flexibility and control.
+.sp
+The new format may be selected on the command line with \fB-M2\fP or by 
+setting \fBformat = "lvm2"\fP in the \fBglobal\fP section of \fBlvm.conf\fP.
+Each physical volume in the same volume group must use the same format, but
+different volume groups on a machine may use different formats 
+simultaneously: the tools can handle both formats.
+Additional formats can be added as shared libraries.
+.sp
+Additional tools for manipulating the locations and sizes of metadata areas 
+will be written in due course.  Use the verbose/debug options on the tools
+to see where the metadata areas are placed.
+.TP
+.BR \-\-metadatasize " size"
+The approximate amount of space to be set aside for each metadata area.
+(The size you specify may get rounded.)
+.TP
+.BR \-\-metadatacopies " copies"
+The number of metadata areas to set aside on each PV.  Currently
+this can be 0, 1 or 2.  
+If set to 2, two copies of the volume group metadata 
+are held on the PV, one at the front of the PV and one at the end.  
+If set to 1 (the default), one copy is kept at the front of the PV 
+(starting in the 5th sector).
+If set to 0, no copies are kept on this PV - you might wish to use this
+with VGs containing large numbers of PVs.  But if you do this and
+then later use \fBvgsplit\fP you must ensure that each VG is still going 
+to have a suitable number of copies of the metadata after the split!
+.TP
+.BR \-\-restorefile " file"
+In conjunction with \fB--uuid\fP, this extracts the location and size
+of the data on the PV from the file (produced by \fBvgcfgbackup\fP)
+and ensures that the metadata that the program produces is consistent 
+with the contents of the file i.e. the physical extents will be in 
+the same place and not get overwritten by new metadata.  This provides
+a mechanism to upgrade the metadata format or to add/remove metadata
+areas. Use with care. See also \fBvgconvert\fP(8).
+.TP
+.BR \-\-labelsector " sector"
+By default the PV is labelled with an LVM2 identifier in its second 
+sector (sector 1).  This lets you use a different sector near the
+start of the disk (between 0 and 3 inclusive - see LABEL_SCAN_SECTORS
+in the source).  Use with care.
+.TP
+.BR \-\-setphysicalvolumesize " size"
+Overrides the automatically-detected size of the PV.  Use with care.
+.SH Example
+Initialize partition #4 on the third SCSI disk and the entire fifth
+SCSI disk for later use by LVM:
+.sp
+.B pvcreate /dev/sdc4 /dev/sde
+.sp
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgcreate (8), 
+.BR vgextend (8), 
+.BR lvcreate (8), 
+.BR cfdisk (8), 
+.BR fdisk (8), 
+.BR losetup (8), 
+.BR mdadm (8), 
+.BR vgcfgrestore (8), 
+.BR vgconvert (8)
Index: src/external/gpl2/lvm2tools/dist/man/pvcreate.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/pvcreate.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/pvcreate.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/pvcreate.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,137 @@
+.TH PVCREATE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+pvcreate \- initialize a disk or partition for use by LVM
+.SH SYNOPSIS
+.B pvcreate
+.RB [ \-d | \-\-debug ]
+.RB [ \-f [ f ]| \-\-force " [" \-\-force ]]
+.RB [ \-y | \-\-yes ]
+.RB [ \-h | \-\-help ]
+.RB [ \-t | \-\-test ]
+.RB [ \-v | \-\-verbose ]
+.RB [ \-\-labelsector ]
+.RB [ \-M | \-\-metadatatype type ]
+.RB [ \-\-metadatacopies #copies ]
+.RB [ \-\-metadatasize size ]
+.RB [ \-\-restorefile file ]
+.RB [ \-\-setphysicalvolumesize size ]
+.RB [ \-u | \-\-uuid uuid ]
+.RB [ \-\-version ]
+.RB [ \-Z | \-\-zero y/n ]
+.IR PhysicalVolume " [" PhysicalVolume ...]
+.SH DESCRIPTION
+.B pvcreate
+initializes
+.I PhysicalVolume
+for later use by the Logical Volume Manager (LVM).  Each
+.I PhysicalVolume
+can be a disk partition, whole disk, meta device, or loopback file.
+For DOS disk partitions, the partition id should be set to 0x8e using
+.BR fdisk "(8), " cfdisk "(8), "
+or a equivalent.  For
+.B whole disk devices only
+the partition table must be erased, which will effectively destroy all
+data on that disk.  This can be done by zeroing the first sector with:
+.sp
+.BI "dd if=/dev/zero of=" PhysicalVolume " bs=512 count=1"
+.sp
+Continue with
+.BR vgcreate (8)
+to create a new volume group on
+.IR PhysicalVolume ,
+or
+.BR vgextend (8)
+to add
+.I PhysicalVolume
+to an existing volume group.
+.SH OPTIONS
+See \fBlvm\fP(8) for common options.
+.TP
+.BR \-f ", " \-\-force
+Force the creation without any confirmation.  You can not recreate
+(reinitialize) a physical volume belonging to an existing volume group.
+In an emergency you can override this behaviour with -ff.
+.TP
+.BR \-u ", " \-\-uuid " uuid"
+Specify the uuid for the device.  
+Without this option, \fBpvcreate\fP generates a random uuid.
+All of your physical volumes must have unique uuids.
+You need to use this option before restoring a backup of LVM metadata 
+onto a replacement device - see \fBvgcfgrestore\fP(8).
+.TP
+.BR \-y ", " \-\-yes
+Answer yes to all questions.
+.TP
+.BR \-Z ", " \-\-zero " y/n"
+Whether or not the first 4 sectors (2048 bytes) of the device should be 
+wiped.
+If this option is not given, the 
+default is to wipe these sectors unless either or both of the --restorefile 
+or --uuid options were specified.
+.SH NEW METADATA OPTIONS
+LVM2 introduces a new format for storing metadata on disk.
+This new format is more efficient and resilient than the format the 
+original version of LVM used and offers the advanced user greater 
+flexibility and control.
+.sp
+The new format may be selected on the command line with \fB-M2\fP or by 
+setting \fBformat = "lvm2"\fP in the \fBglobal\fP section of \fBlvm.conf\fP.
+Each physical volume in the same volume group must use the same format, but
+different volume groups on a machine may use different formats 
+simultaneously: the tools can handle both formats.
+Additional formats can be added as shared libraries.
+.sp
+Additional tools for manipulating the locations and sizes of metadata areas 
+will be written in due course.  Use the verbose/debug options on the tools
+to see where the metadata areas are placed.
+.TP
+.BR \-\-metadatasize " size"
+The approximate amount of space to be set aside for each metadata area.
+(The size you specify may get rounded.)
+.TP
+.BR \-\-metadatacopies " copies"
+The number of metadata areas to set aside on each PV.  Currently
+this can be 0, 1 or 2.  
+If set to 2, two copies of the volume group metadata 
+are held on the PV, one at the front of the PV and one at the end.  
+If set to 1 (the default), one copy is kept at the front of the PV 
+(starting in the 5th sector).
+If set to 0, no copies are kept on this PV - you might wish to use this
+with VGs containing large numbers of PVs.  But if you do this and
+then later use \fBvgsplit\fP you must ensure that each VG is still going 
+to have a suitable number of copies of the metadata after the split!
+.TP
+.BR \-\-restorefile " file"
+In conjunction with \fB--uuid\fP, this extracts the location and size
+of the data on the PV from the file (produced by \fBvgcfgbackup\fP)
+and ensures that the metadata that the program produces is consistent 
+with the contents of the file i.e. the physical extents will be in 
+the same place and not get overwritten by new metadata.  This provides
+a mechanism to upgrade the metadata format or to add/remove metadata
+areas. Use with care. See also \fBvgconvert\fP(8).
+.TP
+.BR \-\-labelsector " sector"
+By default the PV is labelled with an LVM2 identifier in its second 
+sector (sector 1).  This lets you use a different sector near the
+start of the disk (between 0 and 3 inclusive - see LABEL_SCAN_SECTORS
+in the source).  Use with care.
+.TP
+.BR \-\-setphysicalvolumesize " size"
+Overrides the automatically-detected size of the PV.  Use with care.
+.SH Example
+Initialize partition #4 on the third SCSI disk and the entire fifth
+SCSI disk for later use by LVM:
+.sp
+.B pvcreate /dev/sdc4 /dev/sde
+.sp
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgcreate (8), 
+.BR vgextend (8), 
+.BR lvcreate (8), 
+.BR cfdisk (8), 
+.BR fdisk (8), 
+.BR losetup (8), 
+.BR mdadm (8), 
+.BR vgcfgrestore (8), 
+.BR vgconvert (8)
Index: src/external/gpl2/lvm2tools/dist/man/pvdisplay.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/pvdisplay.8
diff -N src/external/gpl2/lvm2tools/dist/man/pvdisplay.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/pvdisplay.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,52 @@
+.\"	$NetBSD$
+.\"
+.TH PVDISPLAY 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+pvdisplay \- display attributes of a physical volume
+.SH SYNOPSIS
+.B pvdisplay
+[\-c/\-\-colon] [\-d/\-\-debug] [\-h/\-?/\-\-help] [\-s/\-\-short]
+[\-v[v]/\-\-verbose [\-\-verbose]]
+PhysicalVolumePath [PhysicalVolumePath...]
+.SH DESCRIPTION
+pvdisplay allows you to see the attributes of one or more physical volumes
+like size, physical extent size, space used for the volume group descriptor
+area and so on.
+.P
+\fBpvs\fP (8) is an alternative that provides the same information 
+in the style of \fBps\fP (1).
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-c, \-\-colon
+Generate colon separated output for easier parsing in scripts or programs.
+N.B. \fBpvs\fP (8) provides considerably more control over the output.
+.nf
+
+The values are:
+
+* physical volume device name
+* volume group name
+* physical volume size in kilobytes
+* internal physical volume number (obsolete)
+* physical volume status
+* physical volume (not) allocatable
+* current number of logical volumes on this physical volume
+* physical extent size in kilobytes
+* total number of physical extents
+* free number of physical extents
+* allocated number of physical extents
+
+.fi
+.TP
+.I \-s, \-\-short
+Only display the size of the given physical volumes.
+.TP
+.I \-m, \-\-maps
+Display the mapping of physical extents to logical volumes and
+logical extents.
+.SH SEE ALSO
+.BR lvm (8),
+.BR pvcreate (8),
+.BR lvcreate (8),
+.BR vgcreate (8)
Index: src/external/gpl2/lvm2tools/dist/man/pvdisplay.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/pvdisplay.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/pvdisplay.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/pvdisplay.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,50 @@
+.TH PVDISPLAY 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+pvdisplay \- display attributes of a physical volume
+.SH SYNOPSIS
+.B pvdisplay
+[\-c/\-\-colon] [\-d/\-\-debug] [\-h/\-?/\-\-help] [\-s/\-\-short]
+[\-v[v]/\-\-verbose [\-\-verbose]]
+PhysicalVolumePath [PhysicalVolumePath...]
+.SH DESCRIPTION
+pvdisplay allows you to see the attributes of one or more physical volumes
+like size, physical extent size, space used for the volume group descriptor
+area and so on.
+.P
+\fBpvs\fP (8) is an alternative that provides the same information 
+in the style of \fBps\fP (1).
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-c, \-\-colon
+Generate colon separated output for easier parsing in scripts or programs.
+N.B. \fBpvs\fP (8) provides considerably more control over the output.
+.nf
+
+The values are:
+
+* physical volume device name
+* volume group name
+* physical volume size in kilobytes
+* internal physical volume number (obsolete)
+* physical volume status
+* physical volume (not) allocatable
+* current number of logical volumes on this physical volume
+* physical extent size in kilobytes
+* total number of physical extents
+* free number of physical extents
+* allocated number of physical extents
+
+.fi
+.TP
+.I \-s, \-\-short
+Only display the size of the given physical volumes.
+.TP
+.I \-m, \-\-maps
+Display the mapping of physical extents to logical volumes and
+logical extents.
+.SH SEE ALSO
+.BR lvm (8),
+.BR pvcreate (8),
+.BR lvcreate (8),
+.BR vgcreate (8)
Index: src/external/gpl2/lvm2tools/dist/man/pvmove.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/pvmove.8
diff -N src/external/gpl2/lvm2tools/dist/man/pvmove.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/pvmove.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,101 @@
+.\"	$NetBSD$
+.\"
+.TH PVMOVE 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+pvmove \- move physical extents
+.SH SYNOPSIS
+.B pvmove
+[\-\-abort]
+[\-\-alloc AllocationPolicy]
+[\-b/\-\-background]
+[\-d/\-\-debug] [\-h/\-\-help] [\-i/\-\-interval Seconds] [\-v/\-\-verbose]
+[\-n/\-\-name LogicalVolume] 
+[SourcePhysicalVolume[:PE[-PE]...] [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 (e.g. the machine crashes)
+then run \fBpvmove\fP again without any PhysicalVolume arguments to
+restart any moves that were in progress from the last checkpoint.
+Alternatively use \fBpvmove --abort\fP at any time to abort them
+at the last checkpoint.
+
+You can run more than one pvmove at once provided they are moving data
+off different SourcePhysicalVolumes, but additional pvmoves will ignore
+any logical volumes already in the process of being changed, so some
+data might not get moved.
+
+\fBpvmove\fP works as follows:
+
+1. A temporary 'pvmove' logical volume is created to store
+details of all the data movements required.
+
+2. Every logical volume in the volume group is searched
+for contiguous data that need moving
+according to the command line arguments.
+For each piece of data found, a new segment is added to the end of the
+pvmove LV.
+This segment takes the form of a temporary mirror to copy the data 
+from the original location to a newly-allocated location. 
+The original LV is updated to use the new temporary mirror segment
+in the pvmove LV instead of accessing the data directly.
+
+3. The volume group metadata is updated on disk.
+
+4. The first segment of the pvmove logical volume is activated and starts
+to mirror the first part of the data.  Only one segment is mirrored at once
+as this is usually more efficient.
+
+5. A daemon repeatedly checks progress at the specified time interval.
+When it detects that the first temporary mirror is in-sync,
+it breaks that mirror so that only the new location for that data gets used 
+and writes a checkpoint into the volume group metadata on disk.
+Then it activates the mirror for the next segment of the pvmove LV.
+
+6. When there are no more segments left to be mirrored, 
+the temporary logical volume is removed and the volume group metadata 
+is updated so that the logical volumes reflect the new data locations.
+
+Note that this new process cannot support the original LVM1
+type of on-disk metadata.  Metadata can be converted using \fBvgconvert\fP(8).
+
+.SH OPTIONS
+.TP
+.I \-\-abort
+Abort any moves in progress.
+.TP
+.I \-b, \-\-background
+Run the daemon in the background.
+.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
+.sp
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgconvert (8)
Index: src/external/gpl2/lvm2tools/dist/man/pvmove.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/pvmove.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/pvmove.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/pvmove.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,99 @@
+.TH PVMOVE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+pvmove \- move physical extents
+.SH SYNOPSIS
+.B pvmove
+[\-\-abort]
+[\-\-alloc AllocationPolicy]
+[\-b/\-\-background]
+[\-d/\-\-debug] [\-h/\-\-help] [\-i/\-\-interval Seconds] [\-v/\-\-verbose]
+[\-n/\-\-name LogicalVolume] 
+[SourcePhysicalVolume[:PE[-PE]...] [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 (e.g. the machine crashes)
+then run \fBpvmove\fP again without any PhysicalVolume arguments to
+restart any moves that were in progress from the last checkpoint.
+Alternatively use \fBpvmove --abort\fP at any time to abort them
+at the last checkpoint.
+
+You can run more than one pvmove at once provided they are moving data
+off different SourcePhysicalVolumes, but additional pvmoves will ignore
+any logical volumes already in the process of being changed, so some
+data might not get moved.
+
+\fBpvmove\fP works as follows:
+
+1. A temporary 'pvmove' logical volume is created to store
+details of all the data movements required.
+
+2. Every logical volume in the volume group is searched
+for contiguous data that need moving
+according to the command line arguments.
+For each piece of data found, a new segment is added to the end of the
+pvmove LV.
+This segment takes the form of a temporary mirror to copy the data 
+from the original location to a newly-allocated location. 
+The original LV is updated to use the new temporary mirror segment
+in the pvmove LV instead of accessing the data directly.
+
+3. The volume group metadata is updated on disk.
+
+4. The first segment of the pvmove logical volume is activated and starts
+to mirror the first part of the data.  Only one segment is mirrored at once
+as this is usually more efficient.
+
+5. A daemon repeatedly checks progress at the specified time interval.
+When it detects that the first temporary mirror is in-sync,
+it breaks that mirror so that only the new location for that data gets used 
+and writes a checkpoint into the volume group metadata on disk.
+Then it activates the mirror for the next segment of the pvmove LV.
+
+6. When there are no more segments left to be mirrored, 
+the temporary logical volume is removed and the volume group metadata 
+is updated so that the logical volumes reflect the new data locations.
+
+Note that this new process cannot support the original LVM1
+type of on-disk metadata.  Metadata can be converted using \fBvgconvert\fP(8).
+
+.SH OPTIONS
+.TP
+.I \-\-abort
+Abort any moves in progress.
+.TP
+.I \-b, \-\-background
+Run the daemon in the background.
+.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
+.sp
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgconvert (8)
Index: src/external/gpl2/lvm2tools/dist/man/pvremove.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/pvremove.8
diff -N src/external/gpl2/lvm2tools/dist/man/pvremove.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/pvremove.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,24 @@
+.\"	$NetBSD$
+.\"
+.TH PVREMOVE 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+pvremove \- remove a physical volume
+.SH SYNOPSIS
+.B pvremove
+.RB [ \-d | \-\-debug]
+.RB [ \-f [ f ]| \-\-force " [" \-\-force ]]
+.RB [\-h | \-\-help]
+.RB [ \-t | \-\-test ]
+.RB [ \-v [ v ]| \-\-verbose " [" \-\-verbose ]]
+.RB [ \-y | \-\-yes ]
+.IR PhysicalVolume " [" PhysicalVolume ...]
+.SH DESCRIPTION
+.B pvremove
+wipes the label on a device so that LVM will no longer recognise it
+as a physical volume.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.SH SEE ALSO
+.BR lvm (8),
+.BR pvcreate (8),
+.BR pvdisplay (8)
Index: src/external/gpl2/lvm2tools/dist/man/pvremove.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/pvremove.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/pvremove.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/pvremove.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,22 @@
+.TH PVREMOVE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+pvremove \- remove a physical volume
+.SH SYNOPSIS
+.B pvremove
+.RB [ \-d | \-\-debug]
+.RB [ \-f [ f ]| \-\-force " [" \-\-force ]]
+.RB [\-h | \-\-help]
+.RB [ \-t | \-\-test ]
+.RB [ \-v [ v ]| \-\-verbose " [" \-\-verbose ]]
+.RB [ \-y | \-\-yes ]
+.IR PhysicalVolume " [" PhysicalVolume ...]
+.SH DESCRIPTION
+.B pvremove
+wipes the label on a device so that LVM will no longer recognise it
+as a physical volume.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.SH SEE ALSO
+.BR lvm (8),
+.BR pvcreate (8),
+.BR pvdisplay (8)
Index: src/external/gpl2/lvm2tools/dist/man/pvresize.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/pvresize.8
diff -N src/external/gpl2/lvm2tools/dist/man/pvresize.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/pvresize.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,51 @@
+.\"	$NetBSD$
+.\"
+.TH PVRESIZE 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+pvresize \- resize a disk or partition in use by LVM2
+.SH SYNOPSIS
+.B pvresize
+.RB [ \-d | \-\-debug ]
+.RB [ \-h | \-\-help ]
+.RB [ \-t | \-\-test ]
+.RB [ \-v | \-\-verbose ]
+.RB [ \-\-setphysicalvolumesize size ]
+.IR PhysicalVolume " [" PhysicalVolume ...]
+.SH DESCRIPTION
+.B pvresize
+resizes
+.I PhysicalVolume
+which may already be in a volume group and have active logical volumes
+allocated on it.
+.SH OPTIONS
+See \fBlvm\fP(8) for common options.
+.TP
+.BR \-\-setphysicalvolumesize " size"
+Overrides the automatically-detected size of the PV.  Use with care, or
+prior to reducing the physical size of the device.
+.SH EXAMPLES
+Expand the PV on /dev/sda1 after enlarging the partition with fdisk:
+.sp
+.B pvresize /dev/sda1
+.sp
+Shrink the PV on /dev/sda1 prior to shrinking the partition with fdisk
+(ensure that the PV size is appropriate for your intended new partition
+size):
+.sp
+.B pvresize --setphysicalvolumesize 40G /dev/sda1
+.sp
+.SH RESTRICTIONS
+.B pvresize
+will refuse to shrink
+.I PhysicalVolume
+if it has allocated extents after where its new end would be. In the future,
+it should relocate these elsewhere in the volume group if there is sufficient
+free space, like
+.B pvmove
+does.
+.sp
+.B pvresize
+won't currently work correctly on LVM1 volumes or PVs with extra
+metadata areas.
+.SH SEE ALSO
+.BR lvm "(8), " pvmove "(8), " lvresize "(8), " fdisk "(8)"
Index: src/external/gpl2/lvm2tools/dist/man/pvresize.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/pvresize.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/pvresize.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/pvresize.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,49 @@
+.TH PVRESIZE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+pvresize \- resize a disk or partition in use by LVM2
+.SH SYNOPSIS
+.B pvresize
+.RB [ \-d | \-\-debug ]
+.RB [ \-h | \-\-help ]
+.RB [ \-t | \-\-test ]
+.RB [ \-v | \-\-verbose ]
+.RB [ \-\-setphysicalvolumesize size ]
+.IR PhysicalVolume " [" PhysicalVolume ...]
+.SH DESCRIPTION
+.B pvresize
+resizes
+.I PhysicalVolume
+which may already be in a volume group and have active logical volumes
+allocated on it.
+.SH OPTIONS
+See \fBlvm\fP(8) for common options.
+.TP
+.BR \-\-setphysicalvolumesize " size"
+Overrides the automatically-detected size of the PV.  Use with care, or
+prior to reducing the physical size of the device.
+.SH EXAMPLES
+Expand the PV on /dev/sda1 after enlarging the partition with fdisk:
+.sp
+.B pvresize /dev/sda1
+.sp
+Shrink the PV on /dev/sda1 prior to shrinking the partition with fdisk
+(ensure that the PV size is appropriate for your intended new partition
+size):
+.sp
+.B pvresize --setphysicalvolumesize 40G /dev/sda1
+.sp
+.SH RESTRICTIONS
+.B pvresize
+will refuse to shrink
+.I PhysicalVolume
+if it has allocated extents after where its new end would be. In the future,
+it should relocate these elsewhere in the volume group if there is sufficient
+free space, like
+.B pvmove
+does.
+.sp
+.B pvresize
+won't currently work correctly on LVM1 volumes or PVs with extra
+metadata areas.
+.SH SEE ALSO
+.BR lvm "(8), " pvmove "(8), " lvresize "(8), " fdisk "(8)"
Index: src/external/gpl2/lvm2tools/dist/man/pvs.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/pvs.8
diff -N src/external/gpl2/lvm2tools/dist/man/pvs.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/pvs.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,66 @@
+.\"	$NetBSD$
+.\"
+.TH PVS 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+pvs \- report information about physical volumes
+.SH SYNOPSIS
+.B pvs
+[\-\-aligned] [\-d/\-\-debug] [\-h/\-?/\-\-help]
+[\-\-ignorelockingfailure] [\-\-noheadings] [\-\-nosuffix]
+[\-o/\-\-options [+]Field[,Field]]
+[\-O/\-\-sort [+/-]Key1[,[+/-]Key2[,...]]]
+[\-\-separator Separator] [\-\-unbuffered]
+[\-\-units hsbkmgtHKMGT]
+[\-v/\-\-verbose] 
+[\-\-version] [PhysicalVolume [PhysicalVolume...]]
+.SH DESCRIPTION
+pvs produces formatted output about physical volumes.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-\-aligned
+Use with \-\-separator to align the output columns.
+.TP
+.I \-\-noheadings
+Suppress the headings line that is normally the first line of output.
+Useful if grepping the output.
+.TP
+.I \-\-nosuffix
+Suppress the suffix on output sizes.  Use with \-\-units (except h and H)
+if processing the output.
+.TP
+.I \-o, \-\-options
+Comma-separated ordered list of columns.  Precede the list with '+' to append
+to the default selection of columns.  Column names are: pv_fmt, pv_uuid,
+pv_size, dev_size, pv_free, pv_used, pv_name, pv_attr, pv_pe_count, 
+pv_pe_alloc_count, pv_tags, pvseg_start, pvseg_size, pe_start.
+With --segments, any "pvseg_" prefixes are optional; otherwise any
+"pv_" prefixes are optional.  Columns mentioned in \fBvgs (8)\fP can also
+be chosen. The pv_attr bits are: (a)llocatable and e(x)ported.
+Use \fb-o help\fP to view the full list of fields available.
+.TP
+.I \-\-segments
+Produces one line of output for each contiguous allocation of space on each
+Physical Volume, showing the start (pvseg_start) and length (pvseg_size) in
+units of physical extents.
+.TP
+.I \-O, \-\-sort
+Comma-separated ordered list of columns to sort by.  Replaces the default
+selection. Precede any column with - for a reverse sort on that column.
+.TP
+.I \-\-separator Separator
+String to use to separate each column.  Useful if grepping the output.
+.TP
+.I \-\-unbuffered
+Produce output immediately without sorting or aligning the columns properly.
+.TP
+.I \-\-units hsbkmgtHKMGT
+All sizes are output in these units: (h)uman-readable, (s)ectors, (b)ytes,
+(k)ilobytes, (m)egabytes, (g)igabytes, (t)erabytes.  Capitalise to use multiples
+of 1000 (S.I.) instead of 1024.  Can also specify custom (u)nits e.g.
+\-\-units 3M
+.SH SEE ALSO
+.BR lvm (8),
+.BR pvdisplay (8),
+.BR lvs (8),
+.BR vgs (8)
Index: src/external/gpl2/lvm2tools/dist/man/pvs.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/pvs.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/pvs.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/pvs.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,64 @@
+.TH PVS 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+pvs \- report information about physical volumes
+.SH SYNOPSIS
+.B pvs
+[\-\-aligned] [\-d/\-\-debug] [\-h/\-?/\-\-help]
+[\-\-ignorelockingfailure] [\-\-noheadings] [\-\-nosuffix]
+[\-o/\-\-options [+]Field[,Field]]
+[\-O/\-\-sort [+/-]Key1[,[+/-]Key2[,...]]]
+[\-\-separator Separator] [\-\-unbuffered]
+[\-\-units hsbkmgtHKMGT]
+[\-v/\-\-verbose] 
+[\-\-version] [PhysicalVolume [PhysicalVolume...]]
+.SH DESCRIPTION
+pvs produces formatted output about physical volumes.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-\-aligned
+Use with \-\-separator to align the output columns.
+.TP
+.I \-\-noheadings
+Suppress the headings line that is normally the first line of output.
+Useful if grepping the output.
+.TP
+.I \-\-nosuffix
+Suppress the suffix on output sizes.  Use with \-\-units (except h and H)
+if processing the output.
+.TP
+.I \-o, \-\-options
+Comma-separated ordered list of columns.  Precede the list with '+' to append
+to the default selection of columns.  Column names are: pv_fmt, pv_uuid,
+pv_size, dev_size, pv_free, pv_used, pv_name, pv_attr, pv_pe_count, 
+pv_pe_alloc_count, pv_tags, pvseg_start, pvseg_size, pe_start.
+With --segments, any "pvseg_" prefixes are optional; otherwise any
+"pv_" prefixes are optional.  Columns mentioned in \fBvgs (8)\fP can also
+be chosen. The pv_attr bits are: (a)llocatable and e(x)ported.
+Use \fb-o help\fP to view the full list of fields available.
+.TP
+.I \-\-segments
+Produces one line of output for each contiguous allocation of space on each
+Physical Volume, showing the start (pvseg_start) and length (pvseg_size) in
+units of physical extents.
+.TP
+.I \-O, \-\-sort
+Comma-separated ordered list of columns to sort by.  Replaces the default
+selection. Precede any column with - for a reverse sort on that column.
+.TP
+.I \-\-separator Separator
+String to use to separate each column.  Useful if grepping the output.
+.TP
+.I \-\-unbuffered
+Produce output immediately without sorting or aligning the columns properly.
+.TP
+.I \-\-units hsbkmgtHKMGT
+All sizes are output in these units: (h)uman-readable, (s)ectors, (b)ytes,
+(k)ilobytes, (m)egabytes, (g)igabytes, (t)erabytes.  Capitalise to use multiples
+of 1000 (S.I.) instead of 1024.  Can also specify custom (u)nits e.g.
+\-\-units 3M
+.SH SEE ALSO
+.BR lvm (8),
+.BR pvdisplay (8),
+.BR lvs (8),
+.BR vgs (8)
Index: src/external/gpl2/lvm2tools/dist/man/pvscan.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/pvscan.8
diff -N src/external/gpl2/lvm2tools/dist/man/pvscan.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/pvscan.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,36 @@
+.\"	$NetBSD$
+.\"
+.TH PVSCAN 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+pvscan \- scan all disks for physical volumes
+.SH SYNOPSIS
+.B pvscan
+.RB [ \-d | \-\-debug]
+.RB [\-e | \-\-exported]
+.RB [\-h | \-\-help]
+.RB [\-\-ignorelockingfailure]
+.RB [ \-n | \-\-novolumegroup]
+.RB [\-s | \-\-short]
+.RB [\-u | \-\-uuid]
+.RB [ \-v [ v ]| \-\-verbose " [" \-\-verbose ]]
+.SH DESCRIPTION
+.B pvscan
+scans all supported LVM block devices in the system for physical volumes.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.BR \-e ", " \-\-exported
+Only show physical volumes belonging to exported volume groups.
+.TP
+.BR \-n ", " \-\-novolumegroup
+Only show physical volumes not belonging to any volume group.
+.TP
+.BR \-s ", " \-\-short
+Short listing format.
+.TP
+.BR \-u ", " \-\-uuid
+Show UUIDs (Uniform Unique Identifiers) in addition to device special names.
+.SH SEE ALSO
+.BR lvm (8),
+.BR pvcreate (8),
+.BR pvdisplay (8)
Index: src/external/gpl2/lvm2tools/dist/man/pvscan.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/pvscan.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/pvscan.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/pvscan.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,34 @@
+.TH PVSCAN 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+pvscan \- scan all disks for physical volumes
+.SH SYNOPSIS
+.B pvscan
+.RB [ \-d | \-\-debug]
+.RB [\-e | \-\-exported]
+.RB [\-h | \-\-help]
+.RB [\-\-ignorelockingfailure]
+.RB [ \-n | \-\-novolumegroup]
+.RB [\-s | \-\-short]
+.RB [\-u | \-\-uuid]
+.RB [ \-v [ v ]| \-\-verbose " [" \-\-verbose ]]
+.SH DESCRIPTION
+.B pvscan
+scans all supported LVM block devices in the system for physical volumes.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.BR \-e ", " \-\-exported
+Only show physical volumes belonging to exported volume groups.
+.TP
+.BR \-n ", " \-\-novolumegroup
+Only show physical volumes not belonging to any volume group.
+.TP
+.BR \-s ", " \-\-short
+Short listing format.
+.TP
+.BR \-u ", " \-\-uuid
+Show UUIDs (Uniform Unique Identifiers) in addition to device special names.
+.SH SEE ALSO
+.BR lvm (8),
+.BR pvcreate (8),
+.BR pvdisplay (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgcfgbackup.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgcfgbackup.8
diff -N src/external/gpl2/lvm2tools/dist/man/vgcfgbackup.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgcfgbackup.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,34 @@
+.\"	$NetBSD$
+.\"
+.TH VGCFGBACKUP 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgcfgbackup \- backup volume group descriptor area
+.SH SYNOPSIS
+.B vgcfgbackup
+.RB [ \-d | \-\-debug ]
+.RB [ \-f | \-\-file " filename" ]
+.RB [ \-h | \-\-help ]
+.RB [ \-\-ignorelockingfailure ]
+.RB [ \-P | \-\-partial ]
+.RB [ \-v | \-\-verbose ]
+.RI [ VolumeGroupName ...]
+.SH DESCRIPTION
+.B vgcfgbackup
+allows you to backup the metadata 
+of your volume groups.
+If you don't name any volume groups on the command line, all of them 
+will be backed up.
+.sp
+In a default installation, each volume group gets backed up into a separate
+file bearing the name of the volume group in the directory /etc/lvm/backup.
+You can write the backup to an alternative file using -f.  In this case
+if you are backing up more than one volume group the filename is
+treated as a template, and %s gets replaced by the volume group name.
+.sp
+NB. This DOESN'T backup user/system data in logical
+volume(s)!  Backup /etc/lvm regularly too.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgcfgrestore (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgcfgbackup.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgcfgbackup.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/vgcfgbackup.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgcfgbackup.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,32 @@
+.TH VGCFGBACKUP 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgcfgbackup \- backup volume group descriptor area
+.SH SYNOPSIS
+.B vgcfgbackup
+.RB [ \-d | \-\-debug ]
+.RB [ \-f | \-\-file " filename" ]
+.RB [ \-h | \-\-help ]
+.RB [ \-\-ignorelockingfailure ]
+.RB [ \-P | \-\-partial ]
+.RB [ \-v | \-\-verbose ]
+.RI [ VolumeGroupName ...]
+.SH DESCRIPTION
+.B vgcfgbackup
+allows you to backup the metadata 
+of your volume groups.
+If you don't name any volume groups on the command line, all of them 
+will be backed up.
+.sp
+In a default installation, each volume group gets backed up into a separate
+file bearing the name of the volume group in the directory /etc/lvm/backup.
+You can write the backup to an alternative file using -f.  In this case
+if you are backing up more than one volume group the filename is
+treated as a template, and %s gets replaced by the volume group name.
+.sp
+NB. This DOESN'T backup user/system data in logical
+volume(s)!  Backup /etc/lvm regularly too.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgcfgrestore (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgcfgrestore.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgcfgrestore.8
diff -N src/external/gpl2/lvm2tools/dist/man/vgcfgrestore.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgcfgrestore.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,46 @@
+.\"	$NetBSD$
+.\"
+.TH VGCFGRESTORE 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgcfgrestore \- restore volume group descriptor area
+.SH SYNOPSIS
+.B vgcfgrestore
+.RB [ \-d | \-\-debug ]
+.RB [ \-f | \-\-file " filename" ]
+.RB [ \-l[l] | \-\-list ]
+.RB [ \-h | \-\-help ]
+.RB [ \-M | \-\-Metadatatype 1|2]
+.RB [ \-t | \-\-test ]
+.RB [ \-v | \-\-verbose ]
+.RI \fIVolumeGroupName\fP
+.SH DESCRIPTION
+.B vgcfgrestore
+allows you to restore the metadata of \fIVolumeGroupName\fP from a text 
+backup file produced by \fBvgcfgbackup\fP.  You can specify a backup file 
+with \fP--file\fP.  If no backup file is specified, the most recent
+one is used.  Use \fB--list\fP for a list of the available
+backup and archive files of \fIVolumeGroupName\fP.
+.SH OPTIONS
+.TP
+\fB-l | --list\fP \(em List files pertaining to \fIVolumeGroupName\fP
+List metadata backup and archive files pertaining to \fIVolumeGroupName\fP.
+May be used with the \fB-f\fP option.  Does not restore \fIVolumeGroupName\fP.
+.TP
+\fB-f | --file\fP filename \(em Name of LVM metadata backup file
+Specifies a metadata backup or archive file to be used for restoring 
+VolumeGroupName.  Often this file has been created with \fBvgcfgbackup\fP.
+.TP
+See \fBlvm\fP for common options.
+.SH REPLACING PHYSICAL VOLUMES
+\fBvgdisplay --partial --verbose\fP will show you the UUIDs and sizes of
+any PVs that are no longer present.
+If a PV in the VG is lost and you wish to substitute 
+another of the same size, use 
+\fBpvcreate --restorefile filename --uuid uuid\fP (plus additional 
+arguments as appropriate) to initialise it with the same UUID as 
+the missing PV.  Repeat for all other missing PVs in the VG. 
+Then use \fBvgcfgrestore --file filename\fP to restore the volume
+group's metadata.
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgcreate (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgcfgrestore.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgcfgrestore.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/vgcfgrestore.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgcfgrestore.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,44 @@
+.TH VGCFGRESTORE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgcfgrestore \- restore volume group descriptor area
+.SH SYNOPSIS
+.B vgcfgrestore
+.RB [ \-d | \-\-debug ]
+.RB [ \-f | \-\-file " filename" ]
+.RB [ \-l[l] | \-\-list ]
+.RB [ \-h | \-\-help ]
+.RB [ \-M | \-\-Metadatatype 1|2]
+.RB [ \-t | \-\-test ]
+.RB [ \-v | \-\-verbose ]
+.RI \fIVolumeGroupName\fP
+.SH DESCRIPTION
+.B vgcfgrestore
+allows you to restore the metadata of \fIVolumeGroupName\fP from a text 
+backup file produced by \fBvgcfgbackup\fP.  You can specify a backup file 
+with \fP--file\fP.  If no backup file is specified, the most recent
+one is used.  Use \fB--list\fP for a list of the available
+backup and archive files of \fIVolumeGroupName\fP.
+.SH OPTIONS
+.TP
+\fB-l | --list\fP \(em List files pertaining to \fIVolumeGroupName\fP
+List metadata backup and archive files pertaining to \fIVolumeGroupName\fP.
+May be used with the \fB-f\fP option.  Does not restore \fIVolumeGroupName\fP.
+.TP
+\fB-f | --file\fP filename \(em Name of LVM metadata backup file
+Specifies a metadata backup or archive file to be used for restoring 
+VolumeGroupName.  Often this file has been created with \fBvgcfgbackup\fP.
+.TP
+See \fBlvm\fP for common options.
+.SH REPLACING PHYSICAL VOLUMES
+\fBvgdisplay --partial --verbose\fP will show you the UUIDs and sizes of
+any PVs that are no longer present.
+If a PV in the VG is lost and you wish to substitute 
+another of the same size, use 
+\fBpvcreate --restorefile filename --uuid uuid\fP (plus additional 
+arguments as appropriate) to initialise it with the same UUID as 
+the missing PV.  Repeat for all other missing PVs in the VG. 
+Then use \fBvgcfgrestore --file filename\fP to restore the volume
+group's metadata.
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgcreate (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgchange.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgchange.8
diff -N src/external/gpl2/lvm2tools/dist/man/vgchange.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgchange.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,154 @@
+.\"	$NetBSD$
+.\"
+.TH VGCHANGE 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgchange \- change attributes of a volume group
+.SH SYNOPSIS
+.B vgchange
+.RB [ \-\-addtag
+.IR Tag ]
+.RB [ \-\-alloc
+.IR AllocationPolicy ]
+.RB [ \-A | \-\-autobackup " {" y | n }]
+.RB [ \-a | \-\-available " [e|l] {" y | n }]
+.RB [ \-\-monitor " {" y | n }]
+.RB [ \-c | \-\-clustered " {" y | n }]
+.RB [ \-u | \-\-uuid ]
+.RB [ \-d | \-\-debug]
+.RB [ \-\-deltag
+.IR Tag ]
+.RB [ \-h | \-\-help]
+.RB [ \-\-ignorelockingfailure]
+.RB [ \-\-ignoremonitoring]
+.RB [ \-l | \-\-logicalvolume
+.IR MaxLogicalVolumes ]
+.RB [ -p | \-\-maxphysicalvolumes
+.IR MaxPhysicalVolumes ]
+.RB [ \-P | \-\-partial]
+.RB [ \-s | \-\-physicalextentsize
+.IR PhysicalExtentSize [ \fBkKmMgGtT\fR ]]
+.RB [ -t | \-\-test]
+.RB [ \-v | \-\-verbose]
+.RB [ \-\-version ]
+.RB [ \-x | \-\-resizeable " {" y | n }]
+.RI [ VolumeGroupName ...]
+.SH DESCRIPTION
+.B vgchange
+allows you to change the attributes of one or more volume groups.
+Its main purpose is to activate and deactivate
+.IR VolumeGroupName ,
+or all volume groups if none is specified.  Only active volume groups
+are subject to changes and allow access to their logical volumes.
+[Not yet implemented: During volume group activation, if
+.B vgchange
+recognizes snapshot logical volumes which were dropped because they ran
+out of space, it displays a message informing the administrator that such
+snapshots should be removed (see
+.BR lvremove (8)).
+]
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.BR \-A ", " \-\-autobackup " " { y | n }
+Controls automatic backup of metadata after the change.  See
+.B vgcfgbackup (8).
+Default is yes.
+.TP
+.BR \-a ", " \-\-available " " [e|l] { y | n }
+Controls the availability of the logical volumes in the volume 
+group for input/output.
+In other words, makes the logical volumes known/unknown to the kernel.
+.IP
+If clustered locking is enabled, add 'e' to activate/deactivate
+exclusively on one node or 'l' to activate/deactivate only
+on the local node.  
+Logical volumes with single-host snapshots are always activated
+exclusively because they can only be used on one node at once.
+.TP
+.BR \-c ", " \-\-clustered " " { y | n }
+If clustered locking is enabled, this indicates whether this
+Volume Group is shared with other nodes in the cluster or whether
+it contains only local disks that are not visible on the other nodes.
+If the cluster infrastructure is unavailable on a particular node at a
+particular time, you may still be able to use Volume Groups that
+are not marked as clustered.
+.TP
+.BR \-u ", " \-\-uuid
+Generate new random UUID for specified Volume Groups.
+.TP
+.BR \-\-monitor " " { y | n }
+Controls whether or not a mirrored logical volume is monitored by
+dmeventd, if it is installed.
+If a device used by a monitored mirror reports an I/O error,
+the failure is handled according to 
+.BR mirror_image_fault_policy
+and 
+.BR mirror_log_fault_policy
+set in 
+.BR lvm.conf (5).
+.TP
+.BR \-\-ignoremonitoring
+Make no attempt to interact with dmeventd unless 
+.BR \-\-monitor
+is specified.
+Do not use this if dmeventd is already monitoring a device.
+.TP
+.BR \-l ", " \-\-logicalvolume " " \fIMaxLogicalVolumes\fR
+Changes the maximum logical volume number of an existing inactive
+volume group.
+.TP
+.BR \-p ", " \-\-maxphysicalvolumes " " \fIMaxPhysicalVolumes\fR
+Changes the maximum number of physical volumes that can belong
+to this volume group.
+For volume groups with metadata in lvm1 format, the limit is 255.
+If the metadata uses lvm2 format, the value 0
+removes this restriction: there is then no limit.
+If you have a large number of physical volumes in
+a volume group with metadata in lvm2 format,
+for tool performance reasons, you should consider
+some use of \fB--metadatacopies 0\fP
+as described in \fBpvcreate(8)\fP.
+.TP
+.BR \-s ", " \-\-physicalextentsize " " \fIPhysicalExtentSize\fR[\fBkKmMgGtT\fR]
+Changes the physical extent size on physical volumes of this volume group.
+A size suffix (k for kilobytes up to t for terabytes) is optional, megabytes
+is the default if no suffix is present.
+The default is 4 MB and it must be at least 1 KB and a power of 2.
+ 
+Before increasing the physical extent size, you might need to use lvresize,
+pvresize and/or pvmove so that everything fits.  For example, every
+contiguous range of extents used in a logical volume must start and 
+end on an extent boundary.
+ 
+If the volume group metadata uses lvm1 format, extents can vary in size from
+8KB to 16GB and there is a limit of 65534 extents in each logical volume.  The
+default of 4 MB leads to a maximum logical volume size of around 256GB.
+ 
+If the volume group metadata uses lvm2 format those restrictions do not apply,
+but having a large number of extents will slow down the tools but have no
+impact on I/O performance to the logical volume.  The smallest PE is 1KB.
+ 
+The 2.4 kernel has a limitation of 2TB per block device.
+.TP
+.BR \-x ", " \-\-resizeable " " { y | n }
+Enables or disables the extension/reduction of this volume group
+with/by physical volumes.
+.SH EXAMPLES
+To activate all known volume groups in the system:
+.nf
+
+\	vgchange -a y
+
+.fi
+To change the maximum number of logical volumes of inactive volume group
+.B vg00
+to 128.
+.nf
+
+\	vgchange -l 128 /dev/vg00
+
+.fi
+.SH SEE ALSO
+.BR lvchange (8),
+.BR lvm (8),
+.BR vgcreate (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgchange.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgchange.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/vgchange.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgchange.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,152 @@
+.TH VGCHANGE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgchange \- change attributes of a volume group
+.SH SYNOPSIS
+.B vgchange
+.RB [ \-\-addtag
+.IR Tag ]
+.RB [ \-\-alloc
+.IR AllocationPolicy ]
+.RB [ \-A | \-\-autobackup " {" y | n }]
+.RB [ \-a | \-\-available " [e|l] {" y | n }]
+.RB [ \-\-monitor " {" y | n }]
+.RB [ \-c | \-\-clustered " {" y | n }]
+.RB [ \-u | \-\-uuid ]
+.RB [ \-d | \-\-debug]
+.RB [ \-\-deltag
+.IR Tag ]
+.RB [ \-h | \-\-help]
+.RB [ \-\-ignorelockingfailure]
+.RB [ \-\-ignoremonitoring]
+.RB [ \-l | \-\-logicalvolume
+.IR MaxLogicalVolumes ]
+.RB [ -p | \-\-maxphysicalvolumes
+.IR MaxPhysicalVolumes ]
+.RB [ \-P | \-\-partial]
+.RB [ \-s | \-\-physicalextentsize
+.IR PhysicalExtentSize [ \fBkKmMgGtT\fR ]]
+.RB [ -t | \-\-test]
+.RB [ \-v | \-\-verbose]
+.RB [ \-\-version ]
+.RB [ \-x | \-\-resizeable " {" y | n }]
+.RI [ VolumeGroupName ...]
+.SH DESCRIPTION
+.B vgchange
+allows you to change the attributes of one or more volume groups.
+Its main purpose is to activate and deactivate
+.IR VolumeGroupName ,
+or all volume groups if none is specified.  Only active volume groups
+are subject to changes and allow access to their logical volumes.
+[Not yet implemented: During volume group activation, if
+.B vgchange
+recognizes snapshot logical volumes which were dropped because they ran
+out of space, it displays a message informing the administrator that such
+snapshots should be removed (see
+.BR lvremove (8)).
+]
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.BR \-A ", " \-\-autobackup " " { y | n }
+Controls automatic backup of metadata after the change.  See
+.B vgcfgbackup (8).
+Default is yes.
+.TP
+.BR \-a ", " \-\-available " " [e|l] { y | n }
+Controls the availability of the logical volumes in the volume 
+group for input/output.
+In other words, makes the logical volumes known/unknown to the kernel.
+.IP
+If clustered locking is enabled, add 'e' to activate/deactivate
+exclusively on one node or 'l' to activate/deactivate only
+on the local node.  
+Logical volumes with single-host snapshots are always activated
+exclusively because they can only be used on one node at once.
+.TP
+.BR \-c ", " \-\-clustered " " { y | n }
+If clustered locking is enabled, this indicates whether this
+Volume Group is shared with other nodes in the cluster or whether
+it contains only local disks that are not visible on the other nodes.
+If the cluster infrastructure is unavailable on a particular node at a
+particular time, you may still be able to use Volume Groups that
+are not marked as clustered.
+.TP
+.BR \-u ", " \-\-uuid
+Generate new random UUID for specified Volume Groups.
+.TP
+.BR \-\-monitor " " { y | n }
+Controls whether or not a mirrored logical volume is monitored by
+dmeventd, if it is installed.
+If a device used by a monitored mirror reports an I/O error,
+the failure is handled according to 
+.BR mirror_image_fault_policy
+and 
+.BR mirror_log_fault_policy
+set in 
+.BR lvm.conf (5).
+.TP
+.BR \-\-ignoremonitoring
+Make no attempt to interact with dmeventd unless 
+.BR \-\-monitor
+is specified.
+Do not use this if dmeventd is already monitoring a device.
+.TP
+.BR \-l ", " \-\-logicalvolume " " \fIMaxLogicalVolumes\fR
+Changes the maximum logical volume number of an existing inactive
+volume group.
+.TP
+.BR \-p ", " \-\-maxphysicalvolumes " " \fIMaxPhysicalVolumes\fR
+Changes the maximum number of physical volumes that can belong
+to this volume group.
+For volume groups with metadata in lvm1 format, the limit is 255.
+If the metadata uses lvm2 format, the value 0
+removes this restriction: there is then no limit.
+If you have a large number of physical volumes in
+a volume group with metadata in lvm2 format,
+for tool performance reasons, you should consider
+some use of \fB--metadatacopies 0\fP
+as described in \fBpvcreate(8)\fP.
+.TP
+.BR \-s ", " \-\-physicalextentsize " " \fIPhysicalExtentSize\fR[\fBkKmMgGtT\fR]
+Changes the physical extent size on physical volumes of this volume group.
+A size suffix (k for kilobytes up to t for terabytes) is optional, megabytes
+is the default if no suffix is present.
+The default is 4 MB and it must be at least 1 KB and a power of 2.
+ 
+Before increasing the physical extent size, you might need to use lvresize,
+pvresize and/or pvmove so that everything fits.  For example, every
+contiguous range of extents used in a logical volume must start and 
+end on an extent boundary.
+ 
+If the volume group metadata uses lvm1 format, extents can vary in size from
+8KB to 16GB and there is a limit of 65534 extents in each logical volume.  The
+default of 4 MB leads to a maximum logical volume size of around 256GB.
+ 
+If the volume group metadata uses lvm2 format those restrictions do not apply,
+but having a large number of extents will slow down the tools but have no
+impact on I/O performance to the logical volume.  The smallest PE is 1KB.
+ 
+The 2.4 kernel has a limitation of 2TB per block device.
+.TP
+.BR \-x ", " \-\-resizeable " " { y | n }
+Enables or disables the extension/reduction of this volume group
+with/by physical volumes.
+.SH EXAMPLES
+To activate all known volume groups in the system:
+.nf
+
+\	vgchange -a y
+
+.fi
+To change the maximum number of logical volumes of inactive volume group
+.B vg00
+to 128.
+.nf
+
+\	vgchange -l 128 /dev/vg00
+
+.fi
+.SH SEE ALSO
+.BR lvchange (8),
+.BR lvm (8),
+.BR vgcreate (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgck.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgck.8
diff -N src/external/gpl2/lvm2tools/dist/man/vgck.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgck.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,17 @@
+.\"	$NetBSD$
+.\"
+.TH VGCK 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgck \- check volume group metadata
+.SH SYNOPSIS
+.B vgck
+[\-d/\-\-debug] [\-h/\-?/\-\-help] [\-v/\-\-verbose] [VolumeGroupName...]
+.SH DESCRIPTION
+vgck checks LVM metadata for each named volume group for consistency.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgcreate (8),
+.BR vgchange (8),
+.BR vgscan (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgck.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgck.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/vgck.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgck.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,15 @@
+.TH VGCK 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgck \- check volume group metadata
+.SH SYNOPSIS
+.B vgck
+[\-d/\-\-debug] [\-h/\-?/\-\-help] [\-v/\-\-verbose] [VolumeGroupName...]
+.SH DESCRIPTION
+vgck checks LVM metadata for each named volume group for consistency.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgcreate (8),
+.BR vgchange (8),
+.BR vgscan (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgconvert.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgconvert.8
diff -N src/external/gpl2/lvm2tools/dist/man/vgconvert.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgconvert.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,41 @@
+.\"	$NetBSD$
+.\"
+.TH VGCONVERT 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgconvert \- convert volume group metadata format
+.SH SYNOPSIS
+.B vgconvert
+.RB [ \-d | \-\-debug ]
+.RB [ \-h | \-\-help ]
+.RB [ \-t | \-\-test ]
+.RB [ \-v | \-\-verbose ]
+.RB [ \-\-labelsector ]
+.RB [ \-M | \-\-metadatatype type ]
+.RB [ \-\-metadatacopies #copies ]
+.RB [ \-\-metadatasize size ]
+.RB [ \-\-version ]
+.IR VolumeGroupName " [" VolumeGroupName ...]
+.SH DESCRIPTION
+.B vgconvert
+converts 
+.I VolumeGroupName
+metadata from one format to another provided that the metadata
+fits into the same space.
+.SH OPTIONS
+See \fBlvm\fP(8) and \fBpvcreate\fP(8) for options.
+.SH EXAMPLE
+Convert volume group vg1 from LVM1 metadata format to the new LVM2 
+metadata format.
+.sp
+.B vgconvert -M2 vg1
+.SH RECOVERY
+Use \fBpvscan\fP(8) to see which PVs lost their metadata.
+Run \fBpvcreate\fP(8) with the --uuid and --restorefile options on each
+such PV to reformat it as it was, using the archive file that
+\fBvgconvert\fP(8) created at the start of the procedure.
+Finally run \fBvgcfgrestore\fP(8) with that archive file to restore
+the original metadata.
+.SH SEE ALSO
+.BR lvm (8),
+.BR pvcreate (8),
+.BR vgcfgrestore (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgconvert.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgconvert.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/vgconvert.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgconvert.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,39 @@
+.TH VGCONVERT 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgconvert \- convert volume group metadata format
+.SH SYNOPSIS
+.B vgconvert
+.RB [ \-d | \-\-debug ]
+.RB [ \-h | \-\-help ]
+.RB [ \-t | \-\-test ]
+.RB [ \-v | \-\-verbose ]
+.RB [ \-\-labelsector ]
+.RB [ \-M | \-\-metadatatype type ]
+.RB [ \-\-metadatacopies #copies ]
+.RB [ \-\-metadatasize size ]
+.RB [ \-\-version ]
+.IR VolumeGroupName " [" VolumeGroupName ...]
+.SH DESCRIPTION
+.B vgconvert
+converts 
+.I VolumeGroupName
+metadata from one format to another provided that the metadata
+fits into the same space.
+.SH OPTIONS
+See \fBlvm\fP(8) and \fBpvcreate\fP(8) for options.
+.SH EXAMPLE
+Convert volume group vg1 from LVM1 metadata format to the new LVM2 
+metadata format.
+.sp
+.B vgconvert -M2 vg1
+.SH RECOVERY
+Use \fBpvscan\fP(8) to see which PVs lost their metadata.
+Run \fBpvcreate\fP(8) with the --uuid and --restorefile options on each
+such PV to reformat it as it was, using the archive file that
+\fBvgconvert\fP(8) created at the start of the procedure.
+Finally run \fBvgcfgrestore\fP(8) with that archive file to restore
+the original metadata.
+.SH SEE ALSO
+.BR lvm (8),
+.BR pvcreate (8),
+.BR vgcfgrestore (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgcreate.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgcreate.8
diff -N src/external/gpl2/lvm2tools/dist/man/vgcreate.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgcreate.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,112 @@
+.\"	$NetBSD$
+.\"
+.TH VGCREATE 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgcreate \- create a volume group
+.SH SYNOPSIS
+.B vgcreate
+.RB [ \-\-addtag
+.IR Tag ]
+.RB [ \-\-alloc 
+.IR AllocationPolicy ]
+.RB [ \-A | \-\-autobackup " {" y | n }]
+.RB [ \-c | \-\-clustered " {" y | n }]
+.RB [ \-d | \-\-debug ]
+.RB [ \-h | \-\-help ]
+.RB [ \-l | \-\-maxlogicalvolumes
+.IR MaxLogicalVolumes ]
+.RB [ -M | \-\-metadatatype type]
+.RB [ -p | \-\-maxphysicalvolumes
+.IR MaxPhysicalVolumes ]
+.RB [ \-s | \-\-physicalextentsize
+.IR PhysicalExtentSize [ \fBkKmMgGtT\fR ]]
+.RB [ \-t | \-\-test ]
+.RB [ \-v | \-\-verbose ]
+.RB [ \-\-version ]
+.I VolumeGroupName PhysicalVolumePath
+.RI [ PhysicalVolumePath ...]
+.SH DESCRIPTION
+.B vgcreate
+creates a new volume group called
+.I VolumeGroupName
+using the block special device
+.IR PhysicalVolumePath
+previously configured for LVM with
+.BR pvcreate (8).
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.BR \-c ", " \-\-clustered " " { y | n }
+If clustered locking is enabled, this defaults to \fBy\fP indicating that 
+this Volume Group is shared with other nodes in the cluster.
+
+If the new Volume Group contains only local disks that are not visible 
+on the other nodes, you must specify \fB\-\-clustered\ n\fP.
+If the cluster infrastructure is unavailable on a particular node at a
+particular time, you may still be able to use such Volume Groups.
+.TP
+.BR \-l ", " \-\-maxlogicalvolumes " " \fIMaxLogicalVolumes\fR
+Sets the maximum number of logical volumes allowed in this
+volume group. 
+The setting can be changed with \fBvgchange\fP.
+For volume groups with metadata in lvm1 format, the limit
+and default value is 255.  
+If the metadata uses lvm2 format, the default value is 0
+which removes this restriction: there is then no limit.
+.TP
+.BR \-p ", " \-\-maxphysicalvolumes " " \fIMaxPhysicalVolumes\fR
+Sets the maximum number of physical volumes that can belong
+to this volume group.
+The setting can be changed with \fBvgchange\fP.
+For volume groups with metadata in lvm1 format, the limit
+and default value is 255.  
+If the metadata uses lvm2 format, the default value is 0
+which removes this restriction: there is then no limit.
+If you have a large number of physical volumes in
+a volume group with metadata in lvm2 format, 
+for tool performance reasons, you should consider 
+some use of \fB--metadatacopies 0\fP
+as described in \fBpvcreate(8)\fP.
+.TP
+.BR \-s ", " \-\-physicalextentsize " " \fIPhysicalExtentSize\fR[\fBkKmMgGtT\fR]
+Sets the physical extent size on physical volumes of this volume group.
+A size suffix (k for kilobytes up to t for terabytes) is optional, megabytes
+is the default if no suffix is present.  
+The default is 4 MB and it must be at least 1 KB and a power of 2.
+
+Once this value has been set, it is difficult to change it without recreating
+the volume group which would involve backing up and restoring data on any 
+logical volumes.  However, if no extents need moving for the new
+value to apply, it can be altered using vgchange \-s.
+
+If the volume group metadata uses lvm1 format, extents can vary in size from
+8KB to 16GB and there is a limit of 65534 extents in each logical volume.  The
+default of 4 MB leads to a maximum logical volume size of around 256GB.  
+
+If the volume group metadata uses lvm2 format those restrictions do not apply,
+but having a large number of extents will slow down the tools but have no
+impact on I/O performance to the logical volume.  The smallest PE is 1KB.
+
+The 2.4 kernel has a limitation of 2TB per block device.
+.SH EXAMPLES
+To create a volume group named
+.B test_vg 
+using physical volumes
+.BR /dev/hdk1 ", and " /dev/hdl1
+with default physical extent size of 4MB:
+.nf
+
+\	vgcreate test_vg /dev/sdk1 /dev/sdl1
+
+.fi
+.SH SEE ALSO
+.BR lvm (8),
+.BR pvdisplay (8),
+.BR pvcreate (8),
+.BR vgdisplay (8),
+.BR vgextend (8),
+.BR vgreduce (8),
+.BR lvcreate (8),
+.BR lvdisplay (8),
+.BR lvextend (8),
+.BR lvreduce (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgcreate.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgcreate.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/vgcreate.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgcreate.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,110 @@
+.TH VGCREATE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgcreate \- create a volume group
+.SH SYNOPSIS
+.B vgcreate
+.RB [ \-\-addtag
+.IR Tag ]
+.RB [ \-\-alloc 
+.IR AllocationPolicy ]
+.RB [ \-A | \-\-autobackup " {" y | n }]
+.RB [ \-c | \-\-clustered " {" y | n }]
+.RB [ \-d | \-\-debug ]
+.RB [ \-h | \-\-help ]
+.RB [ \-l | \-\-maxlogicalvolumes
+.IR MaxLogicalVolumes ]
+.RB [ -M | \-\-metadatatype type]
+.RB [ -p | \-\-maxphysicalvolumes
+.IR MaxPhysicalVolumes ]
+.RB [ \-s | \-\-physicalextentsize
+.IR PhysicalExtentSize [ \fBkKmMgGtT\fR ]]
+.RB [ \-t | \-\-test ]
+.RB [ \-v | \-\-verbose ]
+.RB [ \-\-version ]
+.I VolumeGroupName PhysicalVolumePath
+.RI [ PhysicalVolumePath ...]
+.SH DESCRIPTION
+.B vgcreate
+creates a new volume group called
+.I VolumeGroupName
+using the block special device
+.IR PhysicalVolumePath
+previously configured for LVM with
+.BR pvcreate (8).
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.BR \-c ", " \-\-clustered " " { y | n }
+If clustered locking is enabled, this defaults to \fBy\fP indicating that 
+this Volume Group is shared with other nodes in the cluster.
+
+If the new Volume Group contains only local disks that are not visible 
+on the other nodes, you must specify \fB\-\-clustered\ n\fP.
+If the cluster infrastructure is unavailable on a particular node at a
+particular time, you may still be able to use such Volume Groups.
+.TP
+.BR \-l ", " \-\-maxlogicalvolumes " " \fIMaxLogicalVolumes\fR
+Sets the maximum number of logical volumes allowed in this
+volume group. 
+The setting can be changed with \fBvgchange\fP.
+For volume groups with metadata in lvm1 format, the limit
+and default value is 255.  
+If the metadata uses lvm2 format, the default value is 0
+which removes this restriction: there is then no limit.
+.TP
+.BR \-p ", " \-\-maxphysicalvolumes " " \fIMaxPhysicalVolumes\fR
+Sets the maximum number of physical volumes that can belong
+to this volume group.
+The setting can be changed with \fBvgchange\fP.
+For volume groups with metadata in lvm1 format, the limit
+and default value is 255.  
+If the metadata uses lvm2 format, the default value is 0
+which removes this restriction: there is then no limit.
+If you have a large number of physical volumes in
+a volume group with metadata in lvm2 format, 
+for tool performance reasons, you should consider 
+some use of \fB--metadatacopies 0\fP
+as described in \fBpvcreate(8)\fP.
+.TP
+.BR \-s ", " \-\-physicalextentsize " " \fIPhysicalExtentSize\fR[\fBkKmMgGtT\fR]
+Sets the physical extent size on physical volumes of this volume group.
+A size suffix (k for kilobytes up to t for terabytes) is optional, megabytes
+is the default if no suffix is present.  
+The default is 4 MB and it must be at least 1 KB and a power of 2.
+
+Once this value has been set, it is difficult to change it without recreating
+the volume group which would involve backing up and restoring data on any 
+logical volumes.  However, if no extents need moving for the new
+value to apply, it can be altered using vgchange \-s.
+
+If the volume group metadata uses lvm1 format, extents can vary in size from
+8KB to 16GB and there is a limit of 65534 extents in each logical volume.  The
+default of 4 MB leads to a maximum logical volume size of around 256GB.  
+
+If the volume group metadata uses lvm2 format those restrictions do not apply,
+but having a large number of extents will slow down the tools but have no
+impact on I/O performance to the logical volume.  The smallest PE is 1KB.
+
+The 2.4 kernel has a limitation of 2TB per block device.
+.SH EXAMPLES
+To create a volume group named
+.B test_vg 
+using physical volumes
+.BR /dev/hdk1 ", and " /dev/hdl1
+with default physical extent size of 4MB:
+.nf
+
+\	vgcreate test_vg /dev/sdk1 /dev/sdl1
+
+.fi
+.SH SEE ALSO
+.BR lvm (8),
+.BR pvdisplay (8),
+.BR pvcreate (8),
+.BR vgdisplay (8),
+.BR vgextend (8),
+.BR vgreduce (8),
+.BR lvcreate (8),
+.BR lvdisplay (8),
+.BR lvextend (8),
+.BR lvreduce (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgdisplay.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgdisplay.8
diff -N src/external/gpl2/lvm2tools/dist/man/vgdisplay.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgdisplay.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,75 @@
+.\"	$NetBSD$
+.\"
+.TH VGDISPLAY 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgdisplay \- display attributes of volume groups
+.SH SYNOPSIS
+.B vgdisplay
+.RB [ \-A | \-\-activevolumegroups ]
+.RB [ \-c | \-\-colon ]
+.RB [ \-d | \-\-debug ]
+.RB [ \-h | \-\-help ]
+.RB [ \-\-ignorelockingfailure ]
+.RB [ \-P | \-\-partial ]
+.RB [ \-s | \-\-short ]
+.RB [ \-v [ v ]| \-\-verbose " [" \-\-verbose ]]
+.RB [ \-\-version ]
+.RI [ VolumeGroupName ...]
+.SH DESCRIPTION
+.B vgdisplay
+allows you to see the attributes of
+.I VolumeGroupName
+(or all volume groups if none is given) with it's physical and logical
+volumes and their sizes etc.
+.P
+\fBvgs\fP (8) is an alternative that provides the same information 
+in the style of \fBps\fP (1).
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.BR \-A ", " \-\-activevolumegroups
+Only select the active volume groups.
+.TP
+.BR \-c ", " \-\-colon
+Generate colon separated output for easier parsing in scripts or programs.
+N.B. \fBvgs\fP (8) provides considerably more control over the output.
+.nf
+
+The values are:
+
+1  volume group name
+2  volume group access
+3  volume group status
+4  internal volume group number
+5  maximum number of logical volumes
+6  current number of logical volumes
+7  open count of all logical volumes in this volume group
+8  maximum logical volume size
+9  maximum number of physical volumes
+10 current number of physical volumes
+11 actual number of physical volumes
+12 size of volume group in kilobytes
+13 physical extent size
+14 total number of physical extents for this volume group
+15 allocated number of physical extents for this volume group
+16 free number of physical extents for this volume group
+17 uuid of volume group
+
+.fi
+.TP
+.BR \-s ", " \-\-short
+Give a short listing showing the existence of volume groups.
+.TP
+.BR \-v ", " \-\-verbose
+Display verbose information containing long listings of physical
+and logical volumes.  If given twice, also display verbose runtime
+information of vgdisplay's activities.
+.TP
+.BR \-\-version
+Display version and exit successfully.
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgs (8),
+.BR pvcreate (8),
+.BR vgcreate (8),
+.BR lvcreate (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgdisplay.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgdisplay.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/vgdisplay.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgdisplay.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,73 @@
+.TH VGDISPLAY 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgdisplay \- display attributes of volume groups
+.SH SYNOPSIS
+.B vgdisplay
+.RB [ \-A | \-\-activevolumegroups ]
+.RB [ \-c | \-\-colon ]
+.RB [ \-d | \-\-debug ]
+.RB [ \-h | \-\-help ]
+.RB [ \-\-ignorelockingfailure ]
+.RB [ \-P | \-\-partial ]
+.RB [ \-s | \-\-short ]
+.RB [ \-v [ v ]| \-\-verbose " [" \-\-verbose ]]
+.RB [ \-\-version ]
+.RI [ VolumeGroupName ...]
+.SH DESCRIPTION
+.B vgdisplay
+allows you to see the attributes of
+.I VolumeGroupName
+(or all volume groups if none is given) with it's physical and logical
+volumes and their sizes etc.
+.P
+\fBvgs\fP (8) is an alternative that provides the same information 
+in the style of \fBps\fP (1).
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.BR \-A ", " \-\-activevolumegroups
+Only select the active volume groups.
+.TP
+.BR \-c ", " \-\-colon
+Generate colon separated output for easier parsing in scripts or programs.
+N.B. \fBvgs\fP (8) provides considerably more control over the output.
+.nf
+
+The values are:
+
+1  volume group name
+2  volume group access
+3  volume group status
+4  internal volume group number
+5  maximum number of logical volumes
+6  current number of logical volumes
+7  open count of all logical volumes in this volume group
+8  maximum logical volume size
+9  maximum number of physical volumes
+10 current number of physical volumes
+11 actual number of physical volumes
+12 size of volume group in kilobytes
+13 physical extent size
+14 total number of physical extents for this volume group
+15 allocated number of physical extents for this volume group
+16 free number of physical extents for this volume group
+17 uuid of volume group
+
+.fi
+.TP
+.BR \-s ", " \-\-short
+Give a short listing showing the existence of volume groups.
+.TP
+.BR \-v ", " \-\-verbose
+Display verbose information containing long listings of physical
+and logical volumes.  If given twice, also display verbose runtime
+information of vgdisplay's activities.
+.TP
+.BR \-\-version
+Display version and exit successfully.
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgs (8),
+.BR pvcreate (8),
+.BR vgcreate (8),
+.BR lvcreate (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgexport.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgexport.8
diff -N src/external/gpl2/lvm2tools/dist/man/vgexport.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgexport.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,29 @@
+.\"	$NetBSD$
+.\"
+.TH VGEXPORT 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgexport \- make volume groups unknown to the system
+.SH SYNOPSIS
+.B vgexport
+[\-a/\-\-all]
+[\-d/\-\-debug] [\-h/\-?/\-\-help] 
+[\-v/\-\-verbose]
+VolumeGroupName [VolumeGroupName...]
+.SH DESCRIPTION
+vgexport allows you to make the inactive 
+.IR VolumeGroupName (s)
+unknown to the system.
+You can then move all the Physical Volumes in that Volume Group to
+a different system for later
+.BR vgimport (8).
+Most LVM2 tools ignore exported Volume Groups.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-a, \-\-all
+Export all inactive Volume Groups.
+.SH SEE ALSO
+.BR lvm (8),
+.BR pvscan (8),
+.BR vgimport (8),
+.BR vgscan (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgexport.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgexport.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/vgexport.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgexport.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,27 @@
+.TH VGEXPORT 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgexport \- make volume groups unknown to the system
+.SH SYNOPSIS
+.B vgexport
+[\-a/\-\-all]
+[\-d/\-\-debug] [\-h/\-?/\-\-help] 
+[\-v/\-\-verbose]
+VolumeGroupName [VolumeGroupName...]
+.SH DESCRIPTION
+vgexport allows you to make the inactive 
+.IR VolumeGroupName (s)
+unknown to the system.
+You can then move all the Physical Volumes in that Volume Group to
+a different system for later
+.BR vgimport (8).
+Most LVM2 tools ignore exported Volume Groups.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-a, \-\-all
+Export all inactive Volume Groups.
+.SH SEE ALSO
+.BR lvm (8),
+.BR pvscan (8),
+.BR vgimport (8),
+.BR vgscan (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgextend.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgextend.8
diff -N src/external/gpl2/lvm2tools/dist/man/vgextend.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgextend.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,27 @@
+.\"	$NetBSD$
+.\"
+.TH VGEXTEND 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgextend \- add physical volumes to a volume group
+.SH SYNOPSIS
+.B vgextend
+[\-A/\-\-autobackup y/n] [\-d/\-\-debug] [\-h/\-?/\-\-help] 
+[\-t/\-\-test]
+[\-v/\-\-verbose]
+VolumeGroupName PhysicalDevicePath [PhysicalDevicePath...]
+.SH DESCRIPTION
+vgextend allows you to add one or more initialized physical volumes ( see
+.B pvcreate(8)
+) to an existing volume group to extend it in size.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.SH Examples
+"vgextend vg00 /dev/sda4 /dev/sdn1" tries to extend the existing volume
+group "vg00" by the new physical volumes (see
+.B pvcreate(8)
+) "/dev/sdn1" and /dev/sda4".
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgcreate (8),
+.BR vgreduce (8),
+.BR pvcreate (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgextend.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgextend.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/vgextend.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgextend.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,25 @@
+.TH VGEXTEND 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgextend \- add physical volumes to a volume group
+.SH SYNOPSIS
+.B vgextend
+[\-A/\-\-autobackup y/n] [\-d/\-\-debug] [\-h/\-?/\-\-help] 
+[\-t/\-\-test]
+[\-v/\-\-verbose]
+VolumeGroupName PhysicalDevicePath [PhysicalDevicePath...]
+.SH DESCRIPTION
+vgextend allows you to add one or more initialized physical volumes ( see
+.B pvcreate(8)
+) to an existing volume group to extend it in size.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.SH Examples
+"vgextend vg00 /dev/sda4 /dev/sdn1" tries to extend the existing volume
+group "vg00" by the new physical volumes (see
+.B pvcreate(8)
+) "/dev/sdn1" and /dev/sda4".
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgcreate (8),
+.BR vgreduce (8),
+.BR pvcreate (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgimport.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgimport.8
diff -N src/external/gpl2/lvm2tools/dist/man/vgimport.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgimport.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,27 @@
+.\"	$NetBSD$
+.\"
+.TH VGIMPORT 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgimport \- make exported volume groups known to the system
+.SH SYNOPSIS
+.B vgimport
+[\-a/\-\-all]
+[\-d/\-\-debug] [\-h/\-?/\-\-help] 
+[\-v/\-\-verbose]
+VolumeGroupName [VolumeGroupName...]
+.SH DESCRIPTION
+.B vgimport
+allows you to make a Volume Group that was previously exported using
+.BR vgexport (8)
+known to the system again, perhaps after moving its Physical Volumes
+from a different machine.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-a, \-\-all
+Import all exported Volume Groups.
+.SH SEE ALSO
+.BR lvm (8),
+.BR pvscan (8),
+.BR vgexport (8),
+.BR vgscan (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgimport.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgimport.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/vgimport.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgimport.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,25 @@
+.TH VGIMPORT 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgimport \- make exported volume groups known to the system
+.SH SYNOPSIS
+.B vgimport
+[\-a/\-\-all]
+[\-d/\-\-debug] [\-h/\-?/\-\-help] 
+[\-v/\-\-verbose]
+VolumeGroupName [VolumeGroupName...]
+.SH DESCRIPTION
+.B vgimport
+allows you to make a Volume Group that was previously exported using
+.BR vgexport (8)
+known to the system again, perhaps after moving its Physical Volumes
+from a different machine.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-a, \-\-all
+Import all exported Volume Groups.
+.SH SEE ALSO
+.BR lvm (8),
+.BR pvscan (8),
+.BR vgexport (8),
+.BR vgscan (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgmerge.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgmerge.8
diff -N src/external/gpl2/lvm2tools/dist/man/vgmerge.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgmerge.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,31 @@
+.\"	$NetBSD$
+.\"
+.TH VGMERGE 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgmerge \- merge two volume groups
+.SH SYNOPSIS
+.B vgmerge
+[\-A/\-\-autobackup y/n] [\-d/\-\-debug] [\-h/\-?/\-\-help] [\-l/\-\-list]
+[\-t/\-\-test] [\-v/\-\-verbose] DestinationVolumeGroupName
+SourceVolumeGroupName
+.SH DESCRIPTION
+vgmerge merges two existing volume groups. The inactive SourceVolumeGroupName
+will be merged into the DestinationVolumeGroupName if physical extent sizes
+are equal and physical and logical volume summaries of both volume groups
+fit into DestinationVolumeGroupName's limits.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.I \-l, \-\-list
+Display merged DestinationVolumeGroupName like "vgdisplay -v".
+.TP 
+.I \-t, \-\-test
+Do a test run WITHOUT making any real changes.
+.SH Examples
+"vgmerge -v databases my_vg" merges the inactive volume group named "my_vg" 
+into the active or inactive volume group named "databases" giving verbose
+runtime information.
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgcreate (8),
+.BR vgextend (8),
+.BR vgreduce (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgmerge.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgmerge.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/vgmerge.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgmerge.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,29 @@
+.TH VGMERGE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgmerge \- merge two volume groups
+.SH SYNOPSIS
+.B vgmerge
+[\-A/\-\-autobackup y/n] [\-d/\-\-debug] [\-h/\-?/\-\-help] [\-l/\-\-list]
+[\-t/\-\-test] [\-v/\-\-verbose] DestinationVolumeGroupName
+SourceVolumeGroupName
+.SH DESCRIPTION
+vgmerge merges two existing volume groups. The inactive SourceVolumeGroupName
+will be merged into the DestinationVolumeGroupName if physical extent sizes
+are equal and physical and logical volume summaries of both volume groups
+fit into DestinationVolumeGroupName's limits.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.I \-l, \-\-list
+Display merged DestinationVolumeGroupName like "vgdisplay -v".
+.TP 
+.I \-t, \-\-test
+Do a test run WITHOUT making any real changes.
+.SH Examples
+"vgmerge -v databases my_vg" merges the inactive volume group named "my_vg" 
+into the active or inactive volume group named "databases" giving verbose
+runtime information.
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgcreate (8),
+.BR vgextend (8),
+.BR vgreduce (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgmknodes.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgmknodes.8
diff -N src/external/gpl2/lvm2tools/dist/man/vgmknodes.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgmknodes.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,19 @@
+.\"	$NetBSD$
+.\"
+.TH VGMKNODES 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgmknodes \- recreate volume group directory and logical volume special files
+.SH SYNOPSIS
+.B vgmknodes
+[\-d/\-\-debug] [\-h/\-?/\-\-help] 
+[\-v/\-\-verbose]
+[[VolumeGroupName | LogicalVolumePath]...]
+.SH DESCRIPTION
+Checks the LVM2 special files in /dev that are needed for active 
+logical volumes and creates any missing ones and removes unused ones.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgscan (8),
+.BR dmsetup (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgmknodes.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgmknodes.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/vgmknodes.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgmknodes.8.in	12 Dec 2008 16:33:02 -0000	1.1.1.1.2.2
@@ -0,0 +1,17 @@
+.TH VGMKNODES 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgmknodes \- recreate volume group directory and logical volume special files
+.SH SYNOPSIS
+.B vgmknodes
+[\-d/\-\-debug] [\-h/\-?/\-\-help] 
+[\-v/\-\-verbose]
+[[VolumeGroupName | LogicalVolumePath]...]
+.SH DESCRIPTION
+Checks the LVM2 special files in /dev that are needed for active 
+logical volumes and creates any missing ones and removes unused ones.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgscan (8),
+.BR dmsetup (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgreduce.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgreduce.8
diff -N src/external/gpl2/lvm2tools/dist/man/vgreduce.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgreduce.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,41 @@
+.\"	$NetBSD$
+.\"
+.TH VGREDUCE 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+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...]
+.SH DESCRIPTION
+vgreduce allows you to remove one or more unused physical volumes
+from a volume group.
+.SH OPTIONS
+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, if there are no
+logical volumes allocated on those. This resumes normal operation of the volume
+group (new logical volumes may again be created, changed and so on).
+
+If this is not possible (there are logical volumes referencing the missing
+physical volumes) and you cannot or do not want to remove them manually, you
+can run this option with --force to have vgreduce remove any partial LVs.
+
+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)
Index: src/external/gpl2/lvm2tools/dist/man/vgreduce.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgreduce.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/vgreduce.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgreduce.8.in	12 Dec 2008 16:33:03 -0000	1.1.1.1.2.2
@@ -0,0 +1,39 @@
+.TH VGREDUCE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+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...]
+.SH DESCRIPTION
+vgreduce allows you to remove one or more unused physical volumes
+from a volume group.
+.SH OPTIONS
+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, if there are no
+logical volumes allocated on those. This resumes normal operation of the volume
+group (new logical volumes may again be created, changed and so on).
+
+If this is not possible (there are logical volumes referencing the missing
+physical volumes) and you cannot or do not want to remove them manually, you
+can run this option with --force to have vgreduce remove any partial LVs.
+
+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)
Index: src/external/gpl2/lvm2tools/dist/man/vgremove.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgremove.8
diff -N src/external/gpl2/lvm2tools/dist/man/vgremove.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgremove.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,30 @@
+.\"	$NetBSD$
+.\"
+.TH VGREMOVE 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgremove \- remove a volume group
+.SH SYNOPSIS
+.B vgremove
+[\-d/\-\-debug] [\-f/\-\-force] [\-h/\-?/\-\-help]
+[\-t/\-\-test] [\-v/\-\-verbose]
+VolumeGroupName [VolumeGroupName...]
+.SH DESCRIPTION
+vgremove allows you to remove one or more volume groups.
+If one or more physical volumes in the volume group are lost,
+consider \fBvgreduce --removemissing\fP to make the volume group
+metadata consistent again.
+.sp
+If there are logical volumes that exist in the volume group,
+a prompt will be given to confirm removal.  You can override
+the prompt with \fB-f\fP.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.BR \-f ", " \-\-force
+Force the removal of any logical volumes on the volume group
+without confirmation.
+.SH SEE ALSO
+.BR lvm (8),
+.BR lvremove (8),
+.BR vgcreate (8),
+.BR vgreduce (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgremove.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgremove.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/vgremove.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgremove.8.in	12 Dec 2008 16:33:03 -0000	1.1.1.1.2.2
@@ -0,0 +1,28 @@
+.TH VGREMOVE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgremove \- remove a volume group
+.SH SYNOPSIS
+.B vgremove
+[\-d/\-\-debug] [\-f/\-\-force] [\-h/\-?/\-\-help]
+[\-t/\-\-test] [\-v/\-\-verbose]
+VolumeGroupName [VolumeGroupName...]
+.SH DESCRIPTION
+vgremove allows you to remove one or more volume groups.
+If one or more physical volumes in the volume group are lost,
+consider \fBvgreduce --removemissing\fP to make the volume group
+metadata consistent again.
+.sp
+If there are logical volumes that exist in the volume group,
+a prompt will be given to confirm removal.  You can override
+the prompt with \fB-f\fP.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.BR \-f ", " \-\-force
+Force the removal of any logical volumes on the volume group
+without confirmation.
+.SH SEE ALSO
+.BR lvm (8),
+.BR lvremove (8),
+.BR vgcreate (8),
+.BR vgreduce (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgrename.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgrename.8
diff -N src/external/gpl2/lvm2tools/dist/man/vgrename.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgrename.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,51 @@
+.\"	$NetBSD$
+.\"
+.TH VGRENAME 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgrename \- rename a volume group
+.SH SYNOPSIS
+.B vgrename
+[\-A/\-\-autobackup y/n]
+[\-d/\-\-debug]
+[\-h/\-?/\-\-help]
+[\-t/\-\-test]
+[\-v/\-\-verbose]
+.IR OldVolumeGroup { Path | Name | UUID }
+.IR NewVolumeGroup { Path | Name }
+.SH DESCRIPTION
+vgrename renames an existing (see
+.B vgcreate(8)
+) volume group from
+.IR OldVolumeGroup { Name | Path | UUID }
+to
+.IR NewVolumeGroup { Name | Path }.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.SH Examples
+"vgrename /dev/vg02 /dev/my_volume_group" renames existing
+volume group "vg02" to "my_volume_group".
+.TP
+"vgrename vg02 my_volume_group" does the same.
+.TP
+"vgrename Zvlifi-Ep3t-e0Ng-U42h-o0ye-KHu1-nl7Ns4 VolGroup00_tmp"
+changes the name of the Volume Group with UUID
+Zvlifi-Ep3t-e0Ng-U42h-o0ye-KHu1-nl7Ns4 to 
+"VolGroup00_tmp".
+
+All the Volume Groups visible to a system need to have different
+names.  Otherwise many LVM2 commands will refuse to run or give
+warning messages.
+
+This situation could arise when disks are moved between machines.  If
+a disk is connected and it contains a Volume Group with the same name
+as the Volume Group containing your root filesystem the machine might
+not even boot correctly.  However, the two Volume Groups should have
+different UUIDs (unless the disk was cloned) so you can rename
+one of the conflicting Volume Groups with
+\fBvgrename\fP.
+.TP
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgchange (8),
+.BR vgcreate (8),
+.BR lvrename (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgrename.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgrename.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/vgrename.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgrename.8.in	12 Dec 2008 16:33:03 -0000	1.1.1.1.2.2
@@ -0,0 +1,49 @@
+.TH VGRENAME 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgrename \- rename a volume group
+.SH SYNOPSIS
+.B vgrename
+[\-A/\-\-autobackup y/n]
+[\-d/\-\-debug]
+[\-h/\-?/\-\-help]
+[\-t/\-\-test]
+[\-v/\-\-verbose]
+.IR OldVolumeGroup { Path | Name | UUID }
+.IR NewVolumeGroup { Path | Name }
+.SH DESCRIPTION
+vgrename renames an existing (see
+.B vgcreate(8)
+) volume group from
+.IR OldVolumeGroup { Name | Path | UUID }
+to
+.IR NewVolumeGroup { Name | Path }.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.SH Examples
+"vgrename /dev/vg02 /dev/my_volume_group" renames existing
+volume group "vg02" to "my_volume_group".
+.TP
+"vgrename vg02 my_volume_group" does the same.
+.TP
+"vgrename Zvlifi-Ep3t-e0Ng-U42h-o0ye-KHu1-nl7Ns4 VolGroup00_tmp"
+changes the name of the Volume Group with UUID
+Zvlifi-Ep3t-e0Ng-U42h-o0ye-KHu1-nl7Ns4 to 
+"VolGroup00_tmp".
+
+All the Volume Groups visible to a system need to have different
+names.  Otherwise many LVM2 commands will refuse to run or give
+warning messages.
+
+This situation could arise when disks are moved between machines.  If
+a disk is connected and it contains a Volume Group with the same name
+as the Volume Group containing your root filesystem the machine might
+not even boot correctly.  However, the two Volume Groups should have
+different UUIDs (unless the disk was cloned) so you can rename
+one of the conflicting Volume Groups with
+\fBvgrename\fP.
+.TP
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgchange (8),
+.BR vgcreate (8),
+.BR lvrename (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgs.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgs.8
diff -N src/external/gpl2/lvm2tools/dist/man/vgs.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgs.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,79 @@
+.\"	$NetBSD$
+.\"
+.TH VGS 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgs \- report information about volume groups
+.SH SYNOPSIS
+.B vgs
+[\-\-aligned] [\-d/\-\-debug] [\-h/\-?/\-\-help]
+[\-\-ignorelockingfailure] [\-\-noheadings] [\-\-nosuffix]
+[\-o/\-\-options [+]Field[,Field]]
+[\-O/\-\-sort [+/-]Key1[,[+/-]Key2[,...]]]
+[\-P/\-\-partial]
+[\-\-separator Separator] [\-\-unbuffered]
+[\-\-units hsbkmgtHKMGT]
+[\-v/\-\-verbose] 
+[\-\-version] [VolumeGroupName [VolumeGroupName...]]
+.SH DESCRIPTION
+vgs produces formatted output about volume groups.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-\-aligned
+Use with \-\-separator to align the output columns.
+.TP
+.I \-\-noheadings
+Suppress the headings line that is normally the first line of output.
+Useful if grepping the output.
+.TP
+.I \-\-nosuffix
+Suppress the suffix on output sizes.  Use with \-\-units (except h and H)
+if processing the output.
+.TP
+.I \-o, \-\-options
+Comma-separated ordered list of columns.  Precede the list with '+' to append
+to the default selection of columns.  Column names are: vg_fmt, vg_uuid,
+vg_name, vg_attr, vg_size, vg_free, vg_sysid, vg_extent_size, vg_extent_count,
+vg_free_count, max_lv, max_pv, pv_count, lv_count, snap_count, vg_seqno,
+vg_tags.
+Any "vg_" prefixes are optional.  Columns mentioned in either \fBpvs (8)\fP 
+or \fBlvs (8)\fP can also be chosen, but columns cannot be taken from both
+at the same time.  
+Use \fb-o help\fP to view the full list of fields available.
+.IP
+The vg_attr bits are:
+.RS
+.IP 1 3
+Permissions: (w)riteable, (r)ead-only
+.IP 2 3
+Resi(z)eable
+.IP 3 3
+E(x)ported
+.IP 4 3
+(p)artial
+.IP 5 3
+Allocation policy: (c)ontiguous, c(l)ing, (n)ormal, (a)nywhere, (i)nherited
+.IP 6 3
+(c)lustered
+.RE
+.TP
+.I \-O, \-\-sort
+Comma-separated ordered list of columns to sort by.  Replaces the default
+selection. Precede any column with - for a reverse sort on that column.
+.TP
+.I \-\-separator Separator
+String to use to separate each column.  Useful if grepping the output.
+.TP
+.I \-\-unbuffered
+Produce output immediately without sorting or aligning the columns properly.
+.TP
+.I \-\-units hsbkmgtHKMGT
+All sizes are output in these units: (h)uman-readable, (s)ectors, (b)ytes,
+(k)ilobytes, (m)egabytes, (g)igabytes, (t)erabytes.  Capitalise to use multiples
+of 1000 (S.I.) instead of 1024.  Can also specify custom (u)nits e.g.
+\-\-units 3M
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgdisplay (8),
+.BR pvs (8),
+.BR lvs (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgs.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgs.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/vgs.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgs.8.in	12 Dec 2008 16:33:03 -0000	1.1.1.1.2.2
@@ -0,0 +1,77 @@
+.TH VGS 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgs \- report information about volume groups
+.SH SYNOPSIS
+.B vgs
+[\-\-aligned] [\-d/\-\-debug] [\-h/\-?/\-\-help]
+[\-\-ignorelockingfailure] [\-\-noheadings] [\-\-nosuffix]
+[\-o/\-\-options [+]Field[,Field]]
+[\-O/\-\-sort [+/-]Key1[,[+/-]Key2[,...]]]
+[\-P/\-\-partial]
+[\-\-separator Separator] [\-\-unbuffered]
+[\-\-units hsbkmgtHKMGT]
+[\-v/\-\-verbose] 
+[\-\-version] [VolumeGroupName [VolumeGroupName...]]
+.SH DESCRIPTION
+vgs produces formatted output about volume groups.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-\-aligned
+Use with \-\-separator to align the output columns.
+.TP
+.I \-\-noheadings
+Suppress the headings line that is normally the first line of output.
+Useful if grepping the output.
+.TP
+.I \-\-nosuffix
+Suppress the suffix on output sizes.  Use with \-\-units (except h and H)
+if processing the output.
+.TP
+.I \-o, \-\-options
+Comma-separated ordered list of columns.  Precede the list with '+' to append
+to the default selection of columns.  Column names are: vg_fmt, vg_uuid,
+vg_name, vg_attr, vg_size, vg_free, vg_sysid, vg_extent_size, vg_extent_count,
+vg_free_count, max_lv, max_pv, pv_count, lv_count, snap_count, vg_seqno,
+vg_tags.
+Any "vg_" prefixes are optional.  Columns mentioned in either \fBpvs (8)\fP 
+or \fBlvs (8)\fP can also be chosen, but columns cannot be taken from both
+at the same time.  
+Use \fb-o help\fP to view the full list of fields available.
+.IP
+The vg_attr bits are:
+.RS
+.IP 1 3
+Permissions: (w)riteable, (r)ead-only
+.IP 2 3
+Resi(z)eable
+.IP 3 3
+E(x)ported
+.IP 4 3
+(p)artial
+.IP 5 3
+Allocation policy: (c)ontiguous, c(l)ing, (n)ormal, (a)nywhere, (i)nherited
+.IP 6 3
+(c)lustered
+.RE
+.TP
+.I \-O, \-\-sort
+Comma-separated ordered list of columns to sort by.  Replaces the default
+selection. Precede any column with - for a reverse sort on that column.
+.TP
+.I \-\-separator Separator
+String to use to separate each column.  Useful if grepping the output.
+.TP
+.I \-\-unbuffered
+Produce output immediately without sorting or aligning the columns properly.
+.TP
+.I \-\-units hsbkmgtHKMGT
+All sizes are output in these units: (h)uman-readable, (s)ectors, (b)ytes,
+(k)ilobytes, (m)egabytes, (g)igabytes, (t)erabytes.  Capitalise to use multiples
+of 1000 (S.I.) instead of 1024.  Can also specify custom (u)nits e.g.
+\-\-units 3M
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgdisplay (8),
+.BR pvs (8),
+.BR lvs (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgscan.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgscan.8
diff -N src/external/gpl2/lvm2tools/dist/man/vgscan.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgscan.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,30 @@
+.\"	$NetBSD$
+.\"
+.TH VGSCAN 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgscan \- scan all disks for volume groups and rebuild caches
+.SH SYNOPSIS
+.B vgscan
+[\-d/\-\-debug] [\-h/\-?/\-\-help] 
+[\-\-ignorelockingfailure]
+[\-\-mknodes]
+[\-P/\-\-partial]
+[\-v/\-\-verbose]
+.SH DESCRIPTION
+vgscan scans all SCSI, (E)IDE disks, multiple devices and a bunch
+of other disk devices in the system looking for LVM physical volumes
+and volume groups.  Define a filter in \fBlvm.conf\fP(5) to restrict 
+the scan to avoid a CD ROM, for example.
+.LP
+In LVM2, vgscans take place automatically; but you might still need to
+run one explicitly after changing hardware.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-\-mknodes
+Also checks the LVM special files in /dev that are needed for active 
+logical volumes and creates any missing ones and removes unused ones.
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgcreate (8),
+.BR vgchange (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgscan.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgscan.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/vgscan.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgscan.8.in	12 Dec 2008 16:33:03 -0000	1.1.1.1.2.2
@@ -0,0 +1,28 @@
+.TH VGSCAN 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgscan \- scan all disks for volume groups and rebuild caches
+.SH SYNOPSIS
+.B vgscan
+[\-d/\-\-debug] [\-h/\-?/\-\-help] 
+[\-\-ignorelockingfailure]
+[\-\-mknodes]
+[\-P/\-\-partial]
+[\-v/\-\-verbose]
+.SH DESCRIPTION
+vgscan scans all SCSI, (E)IDE disks, multiple devices and a bunch
+of other disk devices in the system looking for LVM physical volumes
+and volume groups.  Define a filter in \fBlvm.conf\fP(5) to restrict 
+the scan to avoid a CD ROM, for example.
+.LP
+In LVM2, vgscans take place automatically; but you might still need to
+run one explicitly after changing hardware.
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.TP
+.I \-\-mknodes
+Also checks the LVM special files in /dev that are needed for active 
+logical volumes and creates any missing ones and removes unused ones.
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgcreate (8),
+.BR vgchange (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgsplit.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgsplit.8
diff -N src/external/gpl2/lvm2tools/dist/man/vgsplit.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgsplit.8	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,68 @@
+.\"	$NetBSD$
+.\"
+.TH VGSPLIT 8 "LVM TOOLS 2.2.02.43-cvs (12-08-08)" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgsplit \- split a volume group into two
+.SH SYNOPSIS
+.B vgsplit
+.RB [ \-\-alloc
+.IR AllocationPolicy ]
+.RB [ \-A | \-\-autobackup " {" y | n }]
+.RB [ \-c | \-\-clustered " {" y | n }]
+.RB [ \-d | \-\-debug ]
+.RB [ \-h | \-\-help ]
+.RB [ \-l | \-\-maxlogicalvolumes
+.IR MaxLogicalVolumes ]
+.RB [ -M | \-\-metadatatype
+.IR type ]
+.RB [ -p | \-\-maxphysicalvolumes
+.IR MaxPhysicalVolumes ]
+.RB [ \-n | \-\-name 
+.IR LogicalVolumeName ]
+.RB [ \-t | \-\-test ]
+.RB [ \-v | \-\-verbose ]
+SourceVolumeGroupName DestinationVolumeGroupName
+[ PhysicalVolumePath ...]
+.SH DESCRIPTION
+.B vgsplit 
+moves one or more physical volumes from
+.I SourceVolumeGroupName
+into
+.I DestinationVolumeGroupName\fP.  The physical volumes moved can be
+specified either explicitly via \fIPhysicalVolumePath\fP, or implicitly by
+\fB-n\fP \fILogicalVolumeName\fP, in which case only physical volumes
+underlying the specified logical volume will be moved.
+
+If
+.I DestinationVolumeGroupName
+does not exist, a new volume group will be created.  The default attributes
+for the new volume group can be specified with \fB\-\-alloc\fR,
+\fB\-\-clustered\fR, \fB\-\-maxlogicalvolumes\fR, \fB\-\-metadatatype\fR,
+and \fB\-\-maxphysicalvolumes\fR (see \fBvgcreate(8)\fR for a description
+of these options).  If any of these options are not given, default
+attribute(s) are taken from
+.I SourceVolumeGroupName\fP.
+
+If
+.I DestinationVolumeGroupName
+does exist, it will be checked for compatibility with
+.I SourceVolumeGroupName
+before the physical volumes are moved. Specifying any of the above default
+volume group attributes with an existing destination volume group is an error,
+and no split will occur.
+
+Logical volumes cannot be split between volume groups. \fBVgsplit(8)\fP only
+moves complete physical volumes: To move part of a physical volume, use
+\fBpvmove(8)\fP.  Each existing logical volume must be entirely on the physical
+volumes forming either the source or the destination volume group.  For this
+reason, \fBvgsplit(8)\fP may fail with an error if a split would result in a
+logical volume being split across volume groups.
+
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgcreate (8),
+.BR vgextend (8),
+.BR vgreduce (8),
+.BR vgmerge (8)
Index: src/external/gpl2/lvm2tools/dist/man/vgsplit.8.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/man/vgsplit.8.in
diff -N src/external/gpl2/lvm2tools/dist/man/vgsplit.8.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/man/vgsplit.8.in	12 Dec 2008 16:33:03 -0000	1.1.1.1.2.2
@@ -0,0 +1,66 @@
+.TH VGSPLIT 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+vgsplit \- split a volume group into two
+.SH SYNOPSIS
+.B vgsplit
+.RB [ \-\-alloc
+.IR AllocationPolicy ]
+.RB [ \-A | \-\-autobackup " {" y | n }]
+.RB [ \-c | \-\-clustered " {" y | n }]
+.RB [ \-d | \-\-debug ]
+.RB [ \-h | \-\-help ]
+.RB [ \-l | \-\-maxlogicalvolumes
+.IR MaxLogicalVolumes ]
+.RB [ -M | \-\-metadatatype
+.IR type ]
+.RB [ -p | \-\-maxphysicalvolumes
+.IR MaxPhysicalVolumes ]
+.RB [ \-n | \-\-name 
+.IR LogicalVolumeName ]
+.RB [ \-t | \-\-test ]
+.RB [ \-v | \-\-verbose ]
+SourceVolumeGroupName DestinationVolumeGroupName
+[ PhysicalVolumePath ...]
+.SH DESCRIPTION
+.B vgsplit 
+moves one or more physical volumes from
+.I SourceVolumeGroupName
+into
+.I DestinationVolumeGroupName\fP.  The physical volumes moved can be
+specified either explicitly via \fIPhysicalVolumePath\fP, or implicitly by
+\fB-n\fP \fILogicalVolumeName\fP, in which case only physical volumes
+underlying the specified logical volume will be moved.
+
+If
+.I DestinationVolumeGroupName
+does not exist, a new volume group will be created.  The default attributes
+for the new volume group can be specified with \fB\-\-alloc\fR,
+\fB\-\-clustered\fR, \fB\-\-maxlogicalvolumes\fR, \fB\-\-metadatatype\fR,
+and \fB\-\-maxphysicalvolumes\fR (see \fBvgcreate(8)\fR for a description
+of these options).  If any of these options are not given, default
+attribute(s) are taken from
+.I SourceVolumeGroupName\fP.
+
+If
+.I DestinationVolumeGroupName
+does exist, it will be checked for compatibility with
+.I SourceVolumeGroupName
+before the physical volumes are moved. Specifying any of the above default
+volume group attributes with an existing destination volume group is an error,
+and no split will occur.
+
+Logical volumes cannot be split between volume groups. \fBVgsplit(8)\fP only
+moves complete physical volumes: To move part of a physical volume, use
+\fBpvmove(8)\fP.  Each existing logical volume must be entirely on the physical
+volumes forming either the source or the destination volume group.  For this
+reason, \fBvgsplit(8)\fP may fail with an error if a split would result in a
+logical volume being split across volume groups.
+
+.SH OPTIONS
+See \fBlvm\fP for common options.
+.SH SEE ALSO
+.BR lvm (8),
+.BR vgcreate (8),
+.BR vgextend (8),
+.BR vgreduce (8),
+.BR vgmerge (8)
Index: src/external/gpl2/lvm2tools/dist/po/Makefile.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/po/Makefile.in
diff -N src/external/gpl2/lvm2tools/dist/po/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/po/Makefile.in	12 Dec 2008 16:33:03 -0000	1.1.1.1.2.1
@@ -0,0 +1,65 @@
+#
+# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+LANGS=de
+
+TARGETS=$(LANGS:%=lvm2_%.mo) $(LANGS:%=dm_%.mo)
+
+DM_POSOURCES = $(top_srcdir)/dmsetup/*.pot $(top_srcdir)/libdm/*.pot \
+	       $(top_srcdir)/libdm/*/*.pot
+
+LVM_POSOURCES = $(top_srcdir)/tools/*.pot $(top_srcdir)/lib/*/*.pot
+
+include $(top_srcdir)/make.tmpl
+
+lvm2.po: Makefile $(LVM_POSOURCES)
+	@echo Compiling string table
+	@xgettext -C -F --keyword=print_log --keyword=log_debug \
+		--keyword=log_info --keyword=_ --keyword=N_ \
+		--keyword=log_notice --keyword=log_warn --keyword=log_err \
+		--keyword=log_fatal --keyword=log_debug --keyword=log_error \
+		--keyword=log_print --keyword=log_verbose \
+		--keyword=log_very_verbose -d - \
+		$(LVM_POSOURCES) > $@
+
+device-mapper.po: Makefile $(DM_POSOURCES)
+	@echo Compiling string table
+	@xgettext -C -F --keyword=dm_log --keyword=log_debug \
+		--keyword=log_info --keyword=_ --keyword=N_ \
+		--keyword=log_notice --keyword=log_warn --keyword=log_err \
+		--keyword=log_fatal --keyword=log_debug --keyword=log_error \
+		--keyword=log_print --keyword=log_verbose \
+		--keyword=log_very_verbose -d - \
+		$(DM_POSOURCES) > $@
+
+pofile: lvm2.po device-mapper.po
+
+# FIXME
+install: $(TARGETS)
+	@echo Installing translation files in $(localedir)
+	@( \
+		for lang in $(LANGS); do \
+			$(INSTALL) -D $(OWNER) $(GROUP) -m 444 $$lang.mo \
+			    $(localedir)/$$lang/LC_MESSAGES/lvm2.mo;\
+	  done; \
+	)
+	@( \
+		for lang in $(LANGS); do \
+			$(INSTALL) -D $(OWNER) $(GROUP) -m 444 $$lang.mo \
+			    $(localedir)/$$lang/LC_MESSAGES/device-mapper.mo;\
+	  done; \
+	)
Index: src/external/gpl2/lvm2tools/dist/po/de.po
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/po/de.po
diff -N src/external/gpl2/lvm2tools/dist/po/de.po
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/po/de.po	15 Jul 2008 13:50:01 -0000	1.1.1.1
@@ -0,0 +1,10 @@
+# Dummy test file
+msgid ""
+msgstr ""
+"PO-Revision-Date: 2004-02-13 20:35+0000\n"
+"Last-Translator: Nobody <nobody@nowhere>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-15\n"
+"Content-Transfer-Encoding: 8bit\n"
+
Index: src/external/gpl2/lvm2tools/dist/po/lvm2.po
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/po/lvm2.po
diff -N src/external/gpl2/lvm2tools/dist/po/lvm2.po
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/po/lvm2.po	15 Jul 2008 13:50:07 -0000	1.1.1.1
@@ -0,0 +1,7630 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-04-27 21:46+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: activate/activate.c:44
+msgid "LVM1 proc global snprintf failed"
+msgstr ""
+
+#: activate/activate.c:63
+msgid "module string allocation failed"
+msgstr ""
+
+#: activate/activate.c:74 activate/activate.c:91 activate/activate.c:109
+#: activate/activate.c:364 activate/activate.c:417 activate/activate.c:438
+#: activate/activate.c:445 activate/activate.c:492 activate/activate.c:495
+#: activate/activate.c:514 activate/activate.c:520 activate/activate.c:523
+#: activate/activate.c:536 activate/activate.c:548 activate/activate.c:561
+#: activate/activate.c:564 activate/activate.c:576 activate/activate.c:579
+#: activate/activate.c:591 activate/activate.c:594 activate/activate.c:606
+#: activate/activate.c:609 activate/activate.c:764 activate/activate.c:768
+#: activate/activate.c:776 activate/activate.c:785 activate/activate.c:791
+#: activate/activate.c:836 activate/activate.c:848 activate/activate.c:882
+#: activate/activate.c:894 activate/activate.c:953 activate/activate.c:967
+#: activate/activate.c:996 activate/dev_manager.c:104
+#: activate/dev_manager.c:130 activate/dev_manager.c:139
+#: activate/dev_manager.c:142 activate/dev_manager.c:168
+#: activate/dev_manager.c:176 activate/dev_manager.c:250
+#: activate/dev_manager.c:258 activate/dev_manager.c:261
+#: activate/dev_manager.c:339 activate/dev_manager.c:347
+#: activate/dev_manager.c:350 activate/dev_manager.c:379
+#: activate/dev_manager.c:434 activate/dev_manager.c:439
+#: activate/dev_manager.c:452 activate/dev_manager.c:489
+#: activate/dev_manager.c:492 activate/dev_manager.c:500
+#: activate/dev_manager.c:523 activate/dev_manager.c:535
+#: activate/dev_manager.c:611 activate/dev_manager.c:628
+#: activate/dev_manager.c:631 activate/dev_manager.c:654
+#: activate/dev_manager.c:658 activate/dev_manager.c:661
+#: activate/dev_manager.c:664 activate/dev_manager.c:682
+#: activate/dev_manager.c:689 activate/dev_manager.c:698
+#: activate/dev_manager.c:737 activate/dev_manager.c:757
+#: activate/dev_manager.c:760 activate/dev_manager.c:780
+#: activate/dev_manager.c:783 activate/dev_manager.c:788
+#: activate/dev_manager.c:842 activate/dev_manager.c:851
+#: activate/dev_manager.c:854 activate/dev_manager.c:860
+#: activate/dev_manager.c:866 activate/dev_manager.c:869
+#: activate/dev_manager.c:871 activate/dev_manager.c:877
+#: activate/dev_manager.c:891 activate/dev_manager.c:894
+#: activate/dev_manager.c:920 activate/dev_manager.c:929
+#: activate/dev_manager.c:996 activate/dev_manager.c:1010
+#: activate/dev_manager.c:1018 activate/dev_manager.c:1025
+#: activate/dev_manager.c:1030 activate/dev_manager.c:1038
+#: activate/dev_manager.c:1044 activate/dev_manager.c:1048
+#: activate/dev_manager.c:1052 activate/dev_manager.c:1075
+#: activate/dev_manager.c:1138 activate/fs.c:179 activate/fs.c:229
+#: activate/fs.c:236 activate/fs.c:243 activate/fs.c:246 activate/fs.c:320
+#: archiver.c:68 archiver.c:75 archiver.c:87 archiver.c:163 archiver.c:236
+#: archiver.c:286 archiver.c:303 archiver.c:345 archiver.c:350
+#: cache/lvmcache.c:486 cache/lvmcache.c:490 cache/lvmcache.c:704
+#: cache/lvmcache.c:724 cache/lvmcache.c:750 cache/lvmcache.c:810
+#: commands/toolcontext.c:276 commands/toolcontext.c:295
+#: commands/toolcontext.c:302 commands/toolcontext.c:379
+#: commands/toolcontext.c:394 commands/toolcontext.c:418
+#: commands/toolcontext.c:469 commands/toolcontext.c:685
+#: commands/toolcontext.c:781 config/config.c:148 config/config.c:161
+#: config/config.c:176 config/config.c:194 config/config.c:215
+#: config/config.c:235 config/config.c:282 config/config.c:285
+#: config/config.c:467 config/config.c:485 config/config.c:490
+#: config/config.c:500 config/config.c:514 config/config.c:530
+#: config/config.c:586 config/config.c:777 datastruct/btree.c:90
+#: datastruct/str_list.c:24 datastruct/str_list.c:38 datastruct/str_list.c:47
+#: datastruct/str_list.c:77 device/dev-cache.c:240 device/dev-cache.c:253
+#: device/dev-cache.c:298 device/dev-cache.c:302 device/dev-cache.c:373
+#: device/dev-cache.c:404 device/dev-cache.c:443 device/dev-cache.c:511
+#: device/dev-cache.c:547 device/dev-cache.c:552 device/dev-cache.c:567
+#: device/dev-io.c:174 device/dev-io.c:204 device/dev-io.c:358
+#: device/dev-io.c:556 device/dev-io.c:606 device/dev-io.c:624
+#: device/dev-io.c:643 device/dev-io.c:671 device/dev-md.c:41
+#: device/dev-md.c:49 device/dev-md.c:66 device/device.c:61 device/device.c:66
+#: device/device.c:90 display/display.c:243 display/display.c:274
+#: display/display.c:333 display/display.c:379 display/display.c:605
+#: display/display.c:641 error/errseg.c:101 filters/filter-composite.c:54
+#: filters/filter-persistent.c:46 filters/filter-persistent.c:110
+#: filters/filter-persistent.c:114 filters/filter-persistent.c:117
+#: filters/filter-persistent.c:197 filters/filter-persistent.c:299
+#: filters/filter-persistent.c:305 filters/filter-persistent.c:316
+#: filters/filter-regex.c:74 filters/filter-regex.c:101
+#: filters/filter-regex.c:119 filters/filter-regex.c:142
+#: filters/filter-regex.c:196 filters/filter-regex.c:201
+#: filters/filter-regex.c:206 filters/filter-regex.c:209
+#: filters/filter-sysfs.c:288 filters/filter.c:278 format1/disk-rep.c:221
+#: format1/disk-rep.c:233 format1/disk-rep.c:238 format1/disk-rep.c:257
+#: format1/disk-rep.c:260 format1/disk-rep.c:291 format1/disk-rep.c:294
+#: format1/disk-rep.c:313 format1/disk-rep.c:316 format1/disk-rep.c:334
+#: format1/disk-rep.c:351 format1/disk-rep.c:361 format1/disk-rep.c:421
+#: format1/disk-rep.c:428 format1/disk-rep.c:522 format1/disk-rep.c:547
+#: format1/disk-rep.c:563 format1/disk-rep.c:591 format1/disk-rep.c:609
+#: format1/disk-rep.c:646 format1/disk-rep.c:711 format1/disk-rep.c:718
+#: format1/disk-rep.c:734 format1/format1.c:134 format1/format1.c:137
+#: format1/format1.c:149 format1/format1.c:154 format1/format1.c:157
+#: format1/format1.c:160 format1/format1.c:163 format1/format1.c:166
+#: format1/format1.c:171 format1/format1.c:186 format1/format1.c:195
+#: format1/format1.c:198 format1/format1.c:213 format1/format1.c:227
+#: format1/format1.c:245 format1/format1.c:256 format1/format1.c:271
+#: format1/format1.c:297 format1/format1.c:302 format1/format1.c:307
+#: format1/format1.c:312 format1/format1.c:348 format1/format1.c:394
+#: format1/format1.c:410 format1/format1.c:415 format1/format1.c:421
+#: format1/format1.c:431 format1/format1.c:477 format1/format1.c:498
+#: format1/format1.c:507 format1/format1.c:551 format1/import-export.c:63
+#: format1/import-export.c:118 format1/import-export.c:151
+#: format1/import-export.c:168 format1/import-export.c:185
+#: format1/import-export.c:193 format1/import-export.c:228
+#: format1/import-export.c:233 format1/import-export.c:238
+#: format1/import-export.c:316 format1/import-export.c:448
+#: format1/import-export.c:453 format1/import-export.c:474
+#: format1/import-export.c:481 format1/import-export.c:503
+#: format1/import-export.c:524 format1/import-export.c:529
+#: format1/import-export.c:538 format1/import-export.c:548
+#: format1/import-export.c:558 format1/import-export.c:563
+#: format1/import-export.c:666 format1/import-export.c:714
+#: format1/import-extents.c:63 format1/import-extents.c:68
+#: format1/import-extents.c:71 format1/import-extents.c:122
+#: format1/import-extents.c:193 format1/import-extents.c:220
+#: format1/import-extents.c:235 format1/import-extents.c:284
+#: format1/import-extents.c:314 format1/import-extents.c:338
+#: format1/import-extents.c:354 format1/import-extents.c:369
+#: format1/layout.c:126 format1/lvm1-label.c:75 format1/vg_number.c:37
+#: format1/vg_number.c:42 format_pool/disk_rep.c:49 format_pool/disk_rep.c:102
+#: format_pool/disk_rep.c:256 format_pool/disk_rep.c:358
+#: format_pool/disk_rep.c:368 format_pool/disk_rep.c:373
+#: format_pool/format_pool.c:132 format_pool/format_pool.c:137
+#: format_pool/format_pool.c:142 format_pool/format_pool.c:152
+#: format_pool/format_pool.c:161 format_pool/format_pool.c:166
+#: format_pool/format_pool.c:186 format_pool/format_pool.c:195
+#: format_pool/format_pool.c:201 format_pool/format_pool.c:231
+#: format_pool/format_pool.c:236 format_pool/format_pool.c:246
+#: format_pool/format_pool.c:251 format_pool/import_export.c:93
+#: format_pool/import_export.c:180 format_pool/import_export.c:218
+#: format_pool/import_export.c:232 format_pool/import_export.c:256
+#: format_pool/import_export.c:276 format_pool/import_export.c:304
+#: format_pool/import_export.c:309 format_text/archive.c:117
+#: format_text/archive.c:138 format_text/archive.c:165
+#: format_text/archive.c:258 format_text/archive.c:274
+#: format_text/archive.c:350 format_text/archive.c:370
+#: format_text/archiver.c:82 format_text/archiver.c:89
+#: format_text/archiver.c:101 format_text/archiver.c:189
+#: format_text/archiver.c:267 format_text/archiver.c:317
+#: format_text/archiver.c:334 format_text/archiver.c:376
+#: format_text/archiver.c:381 format_text/export.c:138
+#: format_text/export.c:198 format_text/export.c:206 format_text/export.c:293
+#: format_text/export.c:294 format_text/export.c:295 format_text/export.c:296
+#: format_text/export.c:298 format_text/export.c:299 format_text/export.c:300
+#: format_text/export.c:303 format_text/export.c:313 format_text/export.c:317
+#: format_text/export.c:319 format_text/export.c:322 format_text/export.c:325
+#: format_text/export.c:329 format_text/export.c:332 format_text/export.c:336
+#: format_text/export.c:340 format_text/export.c:343 format_text/export.c:344
+#: format_text/export.c:348 format_text/export.c:349 format_text/export.c:373
+#: format_text/export.c:380 format_text/export.c:384 format_text/export.c:385
+#: format_text/export.c:389 format_text/export.c:393 format_text/export.c:395
+#: format_text/export.c:398 format_text/export.c:401 format_text/export.c:404
+#: format_text/export.c:408 format_text/export.c:411 format_text/export.c:415
+#: format_text/export.c:419 format_text/export.c:422 format_text/export.c:427
+#: format_text/export.c:431 format_text/export.c:440 format_text/export.c:443
+#: format_text/export.c:446 format_text/export.c:450 format_text/export.c:451
+#: format_text/export.c:455 format_text/export.c:458 format_text/export.c:463
+#: format_text/export.c:468 format_text/export.c:479 format_text/export.c:481
+#: format_text/export.c:488 format_text/export.c:492 format_text/export.c:497
+#: format_text/export.c:508 format_text/export.c:518 format_text/export.c:519
+#: format_text/export.c:524 format_text/export.c:528 format_text/export.c:531
+#: format_text/export.c:534 format_text/export.c:538 format_text/export.c:541
+#: format_text/export.c:545 format_text/export.c:549 format_text/export.c:551
+#: format_text/export.c:553 format_text/export.c:554 format_text/export.c:555
+#: format_text/export.c:560 format_text/export.c:566 format_text/export.c:581
+#: format_text/export.c:591 format_text/export.c:600 format_text/export.c:606
+#: format_text/export.c:624 format_text/export.c:627 format_text/export.c:634
+#: format_text/export.c:637 format_text/export.c:640 format_text/export.c:652
+#: format_text/export.c:657 format_text/export.c:660 format_text/export.c:665
+#: format_text/export.c:667 format_text/export.c:669 format_text/export.c:671
+#: format_text/export.c:673 format_text/export.c:677 format_text/export.c:680
+#: format_text/export.c:702 format_text/export.c:729 format_text/export.c:747
+#: format_text/flags.c:94 format_text/flags.c:138
+#: format_text/format-text.c:158 format_text/format-text.c:161
+#: format_text/format-text.c:195 format_text/format-text.c:199
+#: format_text/format-text.c:238 format_text/format-text.c:295
+#: format_text/format-text.c:346 format_text/format-text.c:378
+#: format_text/format-text.c:420 format_text/format-text.c:425
+#: format_text/format-text.c:433 format_text/format-text.c:451
+#: format_text/format-text.c:456 format_text/format-text.c:481
+#: format_text/format-text.c:494 format_text/format-text.c:542
+#: format_text/format-text.c:547 format_text/format-text.c:587
+#: format_text/format-text.c:601 format_text/format-text.c:619
+#: format_text/format-text.c:650 format_text/format-text.c:700
+#: format_text/format-text.c:757 format_text/format-text.c:762
+#: format_text/format-text.c:785 format_text/format-text.c:799
+#: format_text/format-text.c:1059 format_text/format-text.c:1064
+#: format_text/format-text.c:1072 format_text/format-text.c:1082
+#: format_text/format-text.c:1103 format_text/format-text.c:1107
+#: format_text/format-text.c:1113 format_text/format-text.c:1125
+#: format_text/format-text.c:1309 format_text/format-text.c:1365
+#: format_text/format-text.c:1370 format_text/format-text.c:1380
+#: format_text/format-text.c:1382 format_text/format-text.c:1390
+#: format_text/format-text.c:1430 format_text/format-text.c:1436
+#: format_text/format-text.c:1621 format_text/format-text.c:1627
+#: format_text/format-text.c:1666 format_text/format-text.c:1711
+#: format_text/format-text.c:1730 format_text/format-text.c:1746
+#: format_text/format-text.c:1751 format_text/format-text.c:1765
+#: format_text/format-text.c:1777 format_text/format-text.c:1783
+#: format_text/format-text.c:1813 format_text/format-text.c:1818
+#: format_text/format-text.c:1823 format_text/format-text.c:1832
+#: format_text/format-text.c:1935 format_text/import.c:47
+#: format_text/import.c:52 format_text/import.c:63 format_text/import.c:98
+#: format_text/import.c:115 format_text/import_vsn1.c:123
+#: format_text/import_vsn1.c:134 format_text/import_vsn1.c:167
+#: format_text/import_vsn1.c:237 format_text/import_vsn1.c:303
+#: format_text/import_vsn1.c:309 format_text/import_vsn1.c:322
+#: format_text/import_vsn1.c:387 format_text/import_vsn1.c:429
+#: format_text/import_vsn1.c:457 format_text/import_vsn1.c:465
+#: format_text/import_vsn1.c:482 format_text/import_vsn1.c:489
+#: format_text/import_vsn1.c:518 format_text/import_vsn1.c:576
+#: format_text/import_vsn1.c:629 format_text/import_vsn1.c:654
+#: format_text/import_vsn1.c:664 format_text/import_vsn1.c:667
+#: format_text/import_vsn1.c:735 format_text/import_vsn1.c:846
+#: format_text/tags.c:28 format_text/tags.c:35 format_text/tags.c:42
+#: format_text/tags.c:48 format_text/tags.c:67 format_text/text_label.c:210
+#: format_text/text_label.c:246 label/label.c:90 label/label.c:207
+#: label/label.c:258 label/label.c:274 label/label.c:284 label/label.c:291
+#: label/label.c:321 label/label.c:329 label/label.c:341 label/label.c:360
+#: label/label.c:364 label/label.c:370 locking/cluster_locking.c:85
+#: locking/cluster_locking.c:420 locking/cluster_locking.c:432
+#: locking/cluster_locking.c:436 locking/external_locking.c:77 lvchange.c:57
+#: lvchange.c:99 lvchange.c:116 lvchange.c:122 lvchange.c:136 lvchange.c:143
+#: lvchange.c:150 lvchange.c:268 lvchange.c:282 lvchange.c:353 lvchange.c:361
+#: lvchange.c:395 lvchange.c:472 lvchange.c:479 lvchange.c:526 lvchange.c:534
+#: lvconvert.c:96 lvconvert.c:147 lvconvert.c:211 lvconvert.c:222
+#: lvconvert.c:273 lvconvert.c:285 lvconvert.c:298 lvconvert.c:332
+#: lvconvert.c:354 lvconvert.c:369 lvconvert.c:378 lvconvert.c:397
+#: lvconvert.c:404 lvconvert.c:470 lvconvert.c:481 lvconvert.c:544
+#: lvconvert.c:585 lvcreate.c:133 lvcreate.c:349 lvcreate.c:373 lvcreate.c:399
+#: lvcreate.c:529 lvcreate.c:661 lvcreate.c:698 lvcreate.c:728 lvcreate.c:755
+#: lvcreate.c:763 lvcreate.c:769 lvcreate.c:776 lvcreate.c:868
+#: lvmcmdline.c:830 lvmcmdline.c:836 lvmcmdline.c:839 lvmcmdline.c:842
+#: lvmcmdline.c:846 lvmcmdline.c:853 lvmcmdline.c:885 lvmcmdline.c:896
+#: lvmcmdline.c:906 lvmcmdline.c:936 lvmcmdline.c:1022 lvremove.c:99
+#: lvrename.c:85 lvrename.c:164 lvrename.c:175 lvrename.c:182 lvrename.c:188
+#: lvresize.c:466 lvresize.c:522 lvresize.c:529 lvresize.c:536 lvresize.c:547
+#: lvresize.c:554 lvresize.c:560 lvresize.c:579 lvresize.c:593 lvresize.c:618
+#: metadata/lv_manip.c:85 metadata/lv_manip.c:91 metadata/lv_manip.c:192
+#: metadata/lv_manip.c:227 metadata/lv_manip.c:258 metadata/lv_manip.c:316
+#: metadata/lv_manip.c:325 metadata/lv_manip.c:340 metadata/lv_manip.c:349
+#: metadata/lv_manip.c:379 metadata/lv_manip.c:580 metadata/lv_manip.c:588
+#: metadata/lv_manip.c:623 metadata/lv_manip.c:735 metadata/lv_manip.c:738
+#: metadata/lv_manip.c:748 metadata/lv_manip.c:846 metadata/lv_manip.c:874
+#: metadata/lv_manip.c:1048 metadata/lv_manip.c:1095 metadata/lv_manip.c:1100
+#: metadata/lv_manip.c:1130 metadata/lv_manip.c:1221 metadata/lv_manip.c:1228
+#: metadata/lv_manip.c:1265 metadata/lv_manip.c:1277 metadata/lv_manip.c:1306
+#: metadata/lv_manip.c:1316 metadata/lv_manip.c:1364 metadata/lv_manip.c:1429
+#: metadata/lv_manip.c:1436 metadata/lv_manip.c:1548 metadata/lv_manip.c:1619
+#: metadata/merge.c:253 metadata/merge.c:292 metadata/merge.c:297
+#: metadata/metadata.c:119 metadata/metadata.c:154 metadata/metadata.c:182
+#: metadata/metadata.c:252 metadata/metadata.c:276 metadata/metadata.c:284
+#: metadata/metadata.c:322 metadata/metadata.c:372 metadata/metadata.c:378
+#: metadata/metadata.c:384 metadata/metadata.c:395 metadata/metadata.c:401
+#: metadata/metadata.c:413 metadata/metadata.c:419 metadata/metadata.c:431
+#: metadata/metadata.c:439 metadata/metadata.c:446 metadata/metadata.c:453
+#: metadata/metadata.c:460 metadata/metadata.c:473 metadata/metadata.c:481
+#: metadata/metadata.c:490 metadata/metadata.c:549 metadata/metadata.c:564
+#: metadata/metadata.c:754 metadata/metadata.c:779 metadata/metadata.c:815
+#: metadata/metadata.c:846 metadata/metadata.c:874 metadata/metadata.c:880
+#: metadata/metadata.c:887 metadata/metadata.c:898 metadata/metadata.c:903
+#: metadata/metadata.c:925 metadata/metadata.c:947 metadata/metadata.c:964
+#: metadata/metadata.c:1063 metadata/metadata.c:1068 metadata/metadata.c:1079
+#: metadata/metadata.c:1137 metadata/metadata.c:1142 metadata/metadata.c:1168
+#: metadata/metadata.c:1183 metadata/metadata.c:1191 metadata/metadata.c:1246
+#: metadata/metadata.c:1250 metadata/metadata.c:1399 metadata/metadata.c:1433
+#: metadata/metadata.c:1490 metadata/metadata.c:1494 metadata/metadata.c:1527
+#: metadata/mirror.c:106 metadata/mirror.c:109 metadata/mirror.c:112
+#: metadata/mirror.c:205 metadata/mirror.c:484 metadata/mirror.c:526
+#: metadata/mirror.c:560 metadata/mirror.c:599 metadata/mirror.c:608
+#: metadata/mirror.c:736 metadata/mirror.c:757 metadata/mirror.c:762
+#: metadata/mirror.c:836 metadata/pv_manip.c:54 metadata/pv_manip.c:73
+#: metadata/pv_manip.c:94 metadata/pv_manip.c:131 metadata/pv_manip.c:156
+#: metadata/pv_manip.c:197 metadata/pv_manip.c:332 metadata/pv_map.c:44
+#: metadata/pv_map.c:92 metadata/pv_map.c:112 metadata/pv_map.c:122
+#: metadata/pv_map.c:149 metadata/pv_map.c:159 metadata/snapshot_manip.c:70
+#: metadata/snapshot_manip.c:77 mirror/mirrored.c:144 mirror/mirrored.c:149
+#: mirror/mirrored.c:151 mirror/mirrored.c:304 mirror/mirrored.c:328
+#: mirror/mirrored.c:331 mirror/mirrored.c:501 mirror/mirrored.c:552
+#: misc/lvm-file.c:291 misc/timestamp.c:44 pvchange.c:191 pvmove.c:102
+#: pvmove.c:107 pvmove.c:192 pvmove.c:220 pvmove.c:227 pvmove.c:292
+#: pvmove.c:299 pvmove.c:308 pvmove.c:337 pvmove.c:349 pvmove.c:356
+#: pvmove.c:363 pvmove.c:371 pvmove.c:383 pvmove.c:524 pvresize.c:165
+#: pvscan.c:55 report/report.c:187 report/report.c:513 report/report.c:543
+#: report/report.c:699 reporter.c:289 snapshot/snapshot.c:74
+#: snapshot/snapshot.c:83 snapshot/snapshot.c:84 snapshot/snapshot.c:85
+#: snapshot/snapshot.c:169 striped/striped.c:89 striped/striped.c:169
+#: striped/striped.c:172 striped/striped.c:216 toollib.c:912 toollib.c:962
+#: toollib.c:1020 toollib.c:1060 toollib.c:1085 toollib.c:1194 toollib.c:1332
+#: toollib.c:1337 toollib.c:1350 toollib.c:1357 uuid/uuid.c:90 uuid/uuid.c:94
+#: vgcfgbackup.c:69 vgcfgbackup.c:78 vgcfgbackup.c:85 vgchange.c:420
+#: vgmerge.c:193 vgreduce.c:29 vgreduce.c:96 vgreduce.c:102 vgreduce.c:124
+#: vgreduce.c:130 vgreduce.c:148 vgreduce.c:196 vgreduce.c:217 vgreduce.c:241
+#: vgreduce.c:307 vgreduce.c:353 zero/zero.c:99
+msgid "<backtrace>"
+msgstr ""
+
+#: activate/activate.c:81
+msgid "snap_seg module string allocation failed"
+msgstr ""
+
+#: activate/activate.c:245
+msgid "Activation enabled. Device-mapper kernel driver will be used."
+msgstr ""
+
+#: activate/activate.c:248
+msgid ""
+"WARNING: Activation disabled. No device-mapper interaction will be attempted."
+msgstr ""
+
+#: activate/activate.c:281
+msgid "Ignoring invalid string in config file activation/volume_list"
+msgstr ""
+
+#: activate/activate.c:287
+msgid "Ignoring empty string in config file activation/volume_list"
+msgstr ""
+
+#: activate/activate.c:296
+msgid "Ignoring empty tag in config file activation/volume_list"
+msgstr ""
+
+#: activate/activate.c:326
+#, c-format
+msgid "dm_snprintf error from %s/%s"
+msgstr ""
+
+#: activate/activate.c:350
+msgid "Getting driver version"
+msgstr ""
+
+#: activate/activate.c:362
+#, c-format
+msgid "Getting target version for %s"
+msgstr ""
+
+#: activate/activate.c:367
+#, c-format
+msgid "Failed to get %s target version"
+msgstr ""
+
+#: activate/activate.c:411
+#, c-format
+msgid "target_present module name too long: %s"
+msgstr ""
+
+#: activate/activate.c:440
+#, c-format
+msgid "Getting device info for %s"
+msgstr ""
+
+#: activate/activate.c:771
+#, c-format
+msgid "Skipping: Suspending '%s'."
+msgstr ""
+
+#: activate/activate.c:831
+#, c-format
+msgid "Skipping: Resuming '%s'."
+msgstr ""
+
+#: activate/activate.c:877
+#, c-format
+msgid "Skipping: Deactivating '%s'."
+msgstr ""
+
+#: activate/activate.c:888
+#, c-format
+msgid "LV %s/%s in use: not deactivating"
+msgstr ""
+
+#: activate/activate.c:917 activate/activate.c:942
+#, c-format
+msgid "Not activating %s/%s due to config file settings"
+msgstr ""
+
+#: activate/activate.c:948
+#, c-format
+msgid "Skipping: Activating '%s'."
+msgstr ""
+
+#: activate/dev_manager.c:75
+#, c-format
+msgid "_build_dlid: pool allocation failed for %zu %s %s."
+msgstr ""
+
+#: activate/dev_manager.c:136 activate/dev_manager.c:255
+#: activate/dev_manager.c:344
+msgid "Failed to disable open_count"
+msgstr ""
+
+#: activate/dev_manager.c:163
+msgid "Failed to allocate dm_task struct to check dev status"
+msgstr ""
+
+#: activate/dev_manager.c:171
+msgid "Failed to get state of mapped device"
+msgstr ""
+
+#: activate/dev_manager.c:229 activate/dev_manager.c:528
+#, c-format
+msgid "dlid build failed for %s"
+msgstr ""
+
+#: activate/dev_manager.c:360 activate/dev_manager.c:384
+#, c-format
+msgid "Number of segments in active LV %s does not match metadata"
+msgstr ""
+
+#: activate/dev_manager.c:394
+#, c-format
+msgid "LV percent: %f"
+msgstr ""
+
+#: activate/dev_manager.c:497
+#, c-format
+msgid "Getting device status percentage for %s"
+msgstr ""
+
+#: activate/dev_manager.c:532
+#, c-format
+msgid "Getting device mirror status percentage for %s"
+msgstr ""
+
+#: activate/dev_manager.c:633
+#, c-format
+msgid "Getting device info for %s [%s]"
+msgstr ""
+
+#: activate/dev_manager.c:635
+#, c-format
+msgid "Failed to get info for %s [%s]."
+msgstr ""
+
+#: activate/dev_manager.c:640
+#, c-format
+msgid "Failed to add device (%u:%u) to dtree"
+msgstr ""
+
+#: activate/dev_manager.c:677
+#, c-format
+msgid "Partial dtree creation failed for %s."
+msgstr ""
+
+#: activate/dev_manager.c:741
+#, c-format
+msgid "Internal error: Unassigned area found in LV %s."
+msgstr ""
+
+#: activate/dev_manager.c:775
+#, c-format
+msgid "Couldn't find snapshot for '%s'."
+msgstr ""
+
+#: activate/dev_manager.c:800
+#, c-format
+msgid "_emit_target: Internal error: Can't handle segment type %s"
+msgstr ""
+
+#: activate/dev_manager.c:828
+#, c-format
+msgid "Checking kernel supports %s segment type for %s%s%s"
+msgstr ""
+
+#: activate/dev_manager.c:834
+#, c-format
+msgid "Can't expand LV %s: %s target support missing from kernel?"
+msgstr ""
+
+#: activate/dev_manager.c:847
+msgid "Clustered snapshots are not yet supported"
+msgstr ""
+
+#: activate/dev_manager.c:902
+#, c-format
+msgid "_add_new_lv_to_dtree: pool alloc failed for %s %s."
+msgstr ""
+
+#: activate/dev_manager.c:961
+#, c-format
+msgid "_create_lv_symlinks: Couldn't split up old device name %s"
+msgstr ""
+
+#: activate/dev_manager.c:987
+#, c-format
+msgid "_clean_tree: Couldn't split up device name %s."
+msgstr ""
+
+#: activate/dev_manager.c:1013 activate/dev_manager.c:1133
+msgid "Lost dependency tree root node"
+msgstr ""
+
+#: activate/dev_manager.c:1055
+#, c-format
+msgid "Failed to create symlinks for %s."
+msgstr ""
+
+#: activate/dev_manager.c:1060
+#, c-format
+msgid "_tree_action: Action %u not supported."
+msgstr ""
+
+#: activate/dev_manager.c:1119
+msgid "partial dtree creation failed"
+msgstr ""
+
+#: activate/dev_manager.c:1124
+#, c-format
+msgid "Failed to add device %s (%u:%u) to dtree"
+msgstr ""
+
+#: activate/fs.c:35 activate/fs.c:58
+msgid "Couldn't construct name of volume group directory."
+msgstr ""
+
+#: activate/fs.c:43
+#, c-format
+msgid "Creating directory %s"
+msgstr ""
+
+#: activate/fs.c:45 activate/fs.c:80 activate/fs.c:100 activate/fs.c:153
+#: activate/fs.c:166 activate/fs.c:173 activate/fs.c:208
+#: commands/toolcontext.c:342 commands/toolcontext.c:820 config/config.c:209
+#: config/config.c:247 config/config.c:262 config/config.c:328
+#: config/config.c:428 config/config.c:452 device/dev-cache.c:208
+#: device/dev-cache.c:212 device/dev-cache.c:394 device/dev-cache.c:417
+#: device/dev-cache.c:424 device/dev-cache.c:681 device/dev-cache.c:683
+#: device/dev-io.c:131 device/dev-io.c:231 device/dev-io.c:249
+#: device/dev-io.c:254 device/dev-io.c:256 device/dev-io.c:262
+#: device/dev-io.c:396 device/dev-io.c:398 device/dev-io.c:481
+#: filters/filter-persistent.c:203 filters/filter-persistent.c:207
+#: filters/filter-persistent.c:230 filters/filter-persistent.c:243
+#: filters/filter-sysfs.c:42 filters/filter-sysfs.c:58
+#: filters/filter-sysfs.c:156 filters/filter-sysfs.c:163
+#: filters/filter-sysfs.c:182 filters/filter-sysfs.c:225 filters/filter.c:164
+#: filters/filter.c:221 filters/filter.c:232 filters/filter.c:240
+#: filters/filter.c:253 format_text/archive.c:214 format_text/archive.c:223
+#: format_text/archive.c:253 format_text/archive.c:260
+#: format_text/archive.c:265 format_text/format-text.c:873
+#: format_text/format-text.c:875 format_text/format-text.c:884
+#: format_text/format-text.c:889 format_text/format-text.c:891
+#: format_text/format-text.c:896 format_text/format-text.c:921
+#: format_text/format-text.c:983 format_text/format-text.c:988
+#: format_text/format-text.c:1013 format_text/format-text.c:1040
+#: locking/file_locking.c:61 locking/file_locking.c:69
+#: locking/file_locking.c:72 locking/file_locking.c:105
+#: locking/file_locking.c:167 locking/file_locking.c:171
+#: locking/file_locking.c:187 locking/file_locking.c:296
+#: locking/file_locking.c:301 locking/locking.c:45 locking/locking.c:50
+#: locking/locking.c:66 locking/locking.c:221 log/log.c:69 lvmcmdline.c:1092
+#: lvmcmdline.c:1130 misc/lvm-exec.c:42 misc/lvm-file.c:47 misc/lvm-file.c:70
+#: misc/lvm-file.c:97 misc/lvm-file.c:107 misc/lvm-file.c:157
+#: misc/lvm-file.c:170 misc/lvm-file.c:199 misc/lvm-file.c:208
+#: misc/lvm-file.c:236 misc/lvm-file.c:241 misc/lvm-file.c:244
+#: misc/lvm-file.c:289 misc/lvm-file.c:297 misc/timestamp.c:47 mm/memlock.c:97
+#: mm/memlock.c:105 mm/memlock.c:116 uuid/uuid.c:83 uuid/uuid.c:88
+#, c-format
+msgid "%s: %s failed: %s"
+msgstr ""
+
+#: activate/fs.c:64
+#, c-format
+msgid "Removing directory %s"
+msgstr ""
+
+#: activate/fs.c:91
+#, c-format
+msgid "Couldn't create path for %s"
+msgstr ""
+
+#: activate/fs.c:98 activate/fs.c:151 activate/fs.c:164
+#, c-format
+msgid "Removing %s"
+msgstr ""
+
+#: activate/fs.c:114
+#, c-format
+msgid "Couldn't create path for volume group dir %s"
+msgstr ""
+
+#: activate/fs.c:121
+#, c-format
+msgid "Couldn't create source pathname for logical volume link %s"
+msgstr ""
+
+#: activate/fs.c:128
+#, c-format
+msgid "Couldn't create destination pathname for logical volume link for %s"
+msgstr ""
+
+#: activate/fs.c:135
+#, c-format
+msgid "Couldn't create pathname for LVM1 group file for %s"
+msgstr ""
+
+#: activate/fs.c:146
+#, c-format
+msgid "Non-LVM1 character device found at %s"
+msgstr ""
+
+#: activate/fs.c:159
+#, c-format
+msgid "Symbolic link %s not created: file exists"
+msgstr ""
+
+#: activate/fs.c:171
+#, c-format
+msgid "Linking %s -> %s"
+msgstr ""
+
+#: activate/fs.c:195
+msgid "Couldn't determine link pathname."
+msgstr ""
+
+#: activate/fs.c:202
+#, c-format
+msgid "%s not symbolic link - not removing"
+msgstr ""
+
+#: activate/fs.c:206
+#, c-format
+msgid "Removing link %s"
+msgstr ""
+
+#: activate/fs.c:282
+msgid "No space to stack fs operation"
+msgstr ""
+
+#: archiver.c:40 format_text/archiver.c:53
+msgid "Couldn't copy archive directory name."
+msgstr ""
+
+#: archiver.c:102 format_text/archiver.c:116
+msgid "Test mode: Skipping archiving of volume group."
+msgstr ""
+
+#: archiver.c:109
+#, c-format
+msgid "Archiving volume group \"%s\" metadata."
+msgstr ""
+
+#: archiver.c:111 format_text/archiver.c:131
+#, c-format
+msgid "Volume group \"%s\" metadata archive failed."
+msgstr ""
+
+#: archiver.c:138 format_text/archiver.c:164
+msgid "Couldn't copy backup directory name."
+msgstr ""
+
+#: archiver.c:169 format_text/archiver.c:195
+msgid "Failed to generate volume group metadata backup filename."
+msgstr ""
+
+#: archiver.c:180 format_text/archiver.c:206
+msgid "WARNING: This metadata update is NOT backed up"
+msgstr ""
+
+#: archiver.c:185 format_text/archiver.c:211
+msgid "Test mode: Skipping volume group backup."
+msgstr ""
+
+#: archiver.c:193 format_text/archiver.c:224
+#, c-format
+msgid "Backup of volume group %s metadata failed."
+msgstr ""
+
+#: archiver.c:207 format_text/archiver.c:238
+msgid "Failed to generate backup filename (for removal)."
+msgstr ""
+
+#: archiver.c:230 format_text/archiver.c:261
+msgid "Couldn't create text format object."
+msgstr ""
+
+#: archiver.c:259 format_text/archiver.c:290
+msgid "Failed to allocate format instance"
+msgstr ""
+
+#: archiver.c:267 format_text/archiver.c:298
+#, c-format
+msgid "PV %s missing from cache"
+msgstr ""
+
+#: archiver.c:272
+#, c-format
+msgid "PV %s is a different format (%s)"
+msgstr ""
+
+#: archiver.c:279 format_text/archiver.c:310
+#, c-format
+msgid "Format-specific setup for %s failed"
+msgstr ""
+
+#: archiver.c:316 format_text/archiver.c:347
+msgid "Failed to generate backup filename (for restore)."
+msgstr ""
+
+#: archiver.c:333
+#, c-format
+msgid "Creating volume group backup \"%s\""
+msgstr ""
+
+#: archiver.c:338 format_text/archiver.c:369
+msgid "Couldn't create backup object."
+msgstr ""
+
+#: cache/lvmcache.c:56 cache/lvmcache.c:235 cache/lvmcache.c:740
+msgid "Internal cache initialisation failed"
+msgstr ""
+
+#: cache/lvmcache.c:61
+#, c-format
+msgid "Cache locking failure for %s"
+msgstr ""
+
+#: cache/lvmcache.c:127
+msgid "device_list element allocation failed"
+msgstr ""
+
+#: cache/lvmcache.c:245 toollib.c:638
+msgid "dev_iter creation failed"
+msgstr ""
+
+#: cache/lvmcache.c:278
+msgid "vgids list allocation failed"
+msgstr ""
+
+#: cache/lvmcache.c:285 cache/lvmcache.c:308 cache/lvmcache.c:334
+#: toollib.c:271 toollib.c:306 toollib.c:314 toollib.c:326 toollib.c:405
+#: toollib.c:547 toollib.c:561 toollib.c:698
+msgid "strlist allocation failed"
+msgstr ""
+
+#: cache/lvmcache.c:301
+msgid "vgnames list allocation failed"
+msgstr ""
+
+#: cache/lvmcache.c:324
+msgid "pvids list allocation failed"
+msgstr ""
+
+#: cache/lvmcache.c:395
+#, c-format
+msgid "vg hash re-insertion failed: %s"
+msgstr ""
+
+#: cache/lvmcache.c:440
+#, c-format
+msgid "_lvmcache_update: pvid insertion failed: %s"
+msgstr ""
+
+#: cache/lvmcache.c:456
+#, c-format
+msgid "lvmcache: %s: clearing VGID"
+msgstr ""
+
+#: cache/lvmcache.c:463
+#, c-format
+msgid "_lvmcache_update: vgid hash insertion failed: %s"
+msgstr ""
+
+#: cache/lvmcache.c:468
+#, c-format
+msgid "lvmcache: %s: setting %s VGID to %s"
+msgstr ""
+
+#: cache/lvmcache.c:502
+#, c-format
+msgid ""
+"WARNING: Duplicate VG name %s: Existing %s takes precedence over exported %s"
+msgstr ""
+
+#: cache/lvmcache.c:508
+#, c-format
+msgid "WARNING: Duplicate VG name %s: %s takes precedence over exported %s"
+msgstr ""
+
+#: cache/lvmcache.c:516
+#, c-format
+msgid ""
+"WARNING: Duplicate VG name %s: Existing %s (created here) takes precedence "
+"over %s"
+msgstr ""
+
+#: cache/lvmcache.c:521
+#, c-format
+msgid ""
+"WARNING: Duplicate VG name %s: %s (with creation_host) takes precedence over "
+"%s"
+msgstr ""
+
+#: cache/lvmcache.c:529
+#, c-format
+msgid ""
+"WARNING: Duplicate VG name %s: %s (created here) takes precedence over %s"
+msgstr ""
+
+#: cache/lvmcache.c:547
+#, c-format
+msgid "cache_update: vg hash insertion failed: %s"
+msgstr ""
+
+#: cache/lvmcache.c:619
+msgid "lvmcache_update_vgname: list alloc failed"
+msgstr ""
+
+#: cache/lvmcache.c:625
+#, c-format
+msgid "cache vgname alloc failed for %s"
+msgstr ""
+
+#: cache/lvmcache.c:652
+#, c-format
+msgid "lvmcache: %s: now %s%s%s%s%s"
+msgstr ""
+
+#: cache/lvmcache.c:668
+#, c-format
+msgid "lvmcache: %s: VG %s %s exported"
+msgstr ""
+
+#: cache/lvmcache.c:685
+#, c-format
+msgid "cache creation host alloc failed for %s"
+msgstr ""
+
+#: cache/lvmcache.c:690
+#, c-format
+msgid "lvmcache: %s: VG %s: Set creation host to %s."
+msgstr ""
+
+#: cache/lvmcache.c:754
+msgid "lvmcache_info allocation failed"
+msgstr ""
+
+#: cache/lvmcache.c:769
+#, c-format
+msgid "Ignoring duplicate PV %s on %s - using md %s"
+msgstr ""
+
+#: cache/lvmcache.c:776
+#, c-format
+msgid "Ignoring duplicate PV %s on %s - using dm %s"
+msgstr ""
+
+#: cache/lvmcache.c:783
+#, c-format
+msgid "Duplicate PV %s on %s - using md %s"
+msgstr ""
+
+#: cache/lvmcache.c:789
+#, c-format
+msgid "Duplicate PV %s on %s - using dm %s"
+msgstr ""
+
+#: cache/lvmcache.c:798
+#, c-format
+msgid "Found duplicate PV %s: using %s not %s"
+msgstr ""
+
+#: cache/lvmcache.c:872
+msgid "Wiping internal VG cache"
+msgstr ""
+
+#: commands/toolcontext.c:70
+msgid "LVM_SYSTEM_DIR environment variable is too long."
+msgstr ""
+
+#: commands/toolcontext.c:146
+#, c-format
+msgid "Logging initialised at %s"
+msgstr ""
+
+#: commands/toolcontext.c:165
+#, c-format
+msgid "Set umask to %04o"
+msgstr ""
+
+#: commands/toolcontext.c:171 commands/toolcontext.c:182
+msgid "Device directory given in config file too long"
+msgstr ""
+
+#: commands/toolcontext.c:187
+#, c-format
+msgid "Warning: proc dir %s not found - some checks will be bypassed"
+msgstr ""
+
+#: commands/toolcontext.c:207 lvmcmdline.c:723
+msgid "Invalid units specification"
+msgstr ""
+
+#: commands/toolcontext.c:216
+#, c-format
+msgid "Setting host tag: %s"
+msgstr ""
+
+#: commands/toolcontext.c:219
+#, c-format
+msgid "_set_tag: str_list_add %s failed"
+msgstr ""
+
+#: commands/toolcontext.c:243
+#, c-format
+msgid "Invalid hostname string for tag %s"
+msgstr ""
+
+#: commands/toolcontext.c:254
+msgid "host_filter not supported yet"
+msgstr ""
+
+#: commands/toolcontext.c:289
+#, c-format
+msgid "Invalid tag in config file: %s"
+msgstr ""
+
+#: commands/toolcontext.c:322
+msgid "LVM_SYSTEM_DIR or tag was too long"
+msgstr ""
+
+#: commands/toolcontext.c:327
+msgid "config_tree_list allocation failed"
+msgstr ""
+
+#: commands/toolcontext.c:332
+msgid "config_tree allocation failed"
+msgstr ""
+
+#: commands/toolcontext.c:347
+#, c-format
+msgid "Loading config file: %s"
+msgstr ""
+
+#: commands/toolcontext.c:349
+#, c-format
+msgid "Failed to load config file %s"
+msgstr ""
+
+#: commands/toolcontext.c:372 commands/toolcontext.c:410
+msgid "Failed to create config tree"
+msgstr ""
+
+#: commands/toolcontext.c:473
+msgid "Failed to add /dev to internal device cache"
+msgstr ""
+
+#: commands/toolcontext.c:477
+msgid "device/scan not in config file: Defaulting to /dev"
+msgstr ""
+
+#: commands/toolcontext.c:484
+msgid "Invalid string in config file: devices/scan"
+msgstr ""
+
+#: commands/toolcontext.c:490 format_text/format-text.c:1980
+#, c-format
+msgid "Failed to add %s to internal device cache"
+msgstr ""
+
+#: commands/toolcontext.c:501
+msgid "Invalid string in config file: devices/loopfiles"
+msgstr ""
+
+#: commands/toolcontext.c:507
+#, c-format
+msgid "Failed to add loopfile %s to internal device cache"
+msgstr ""
+
+#: commands/toolcontext.c:546
+msgid "devices/filter not found in config file: no regex filter installed"
+msgstr ""
+
+#: commands/toolcontext.c:550
+msgid "Failed to create regex device filter"
+msgstr ""
+
+#: commands/toolcontext.c:557
+msgid "Failed to create lvm type filter"
+msgstr ""
+
+#: commands/toolcontext.c:602 commands/toolcontext.c:610
+msgid "Persistent cache filename too long."
+msgstr ""
+
+#: commands/toolcontext.c:615
+msgid "Failed to create persistent device filter"
+msgstr ""
+
+#: commands/toolcontext.c:634
+#, c-format
+msgid "Failed to load existing device cache from %s"
+msgstr ""
+
+#: commands/toolcontext.c:679
+msgid "Invalid string in config file: global/format_libraries"
+msgstr ""
+
+#: commands/toolcontext.c:690
+#, c-format
+msgid "Shared library %s does not contain format functions"
+msgstr ""
+
+#: commands/toolcontext.c:722
+#, c-format
+msgid "_init_formats: Default format (%s) not found"
+msgstr ""
+
+#: commands/toolcontext.c:775
+msgid "Invalid string in config file: global/segment_libraries"
+msgstr ""
+
+#: commands/toolcontext.c:786
+#, c-format
+msgid "Shared library %s does not contain segment type functions"
+msgstr ""
+
+#: commands/toolcontext.c:801
+#, c-format
+msgid "Duplicate segment type %s: unloading shared library %s"
+msgstr ""
+
+#: commands/toolcontext.c:825
+msgid "_init_hostname: dm_pool_strdup failed"
+msgstr ""
+
+#: commands/toolcontext.c:830
+msgid "_init_hostname: dm_pool_strdup kernel_vsn failed"
+msgstr ""
+
+#: commands/toolcontext.c:844
+msgid "WARNING: Metadata changes will NOT be backed up"
+msgstr ""
+
+#: commands/toolcontext.c:864
+#, c-format
+msgid "Couldn't create default archive path '%s/%s'."
+msgstr ""
+
+#: commands/toolcontext.c:873 commands/toolcontext.c:893
+msgid "backup_init failed."
+msgstr ""
+
+#: commands/toolcontext.c:885
+#, c-format
+msgid "Couldn't create default backup path '%s/%s'."
+msgstr ""
+
+#: commands/toolcontext.c:911
+msgid "setlocale failed"
+msgstr ""
+
+#: commands/toolcontext.c:920
+msgid "Failed to allocate command context"
+msgstr ""
+
+#: commands/toolcontext.c:940
+msgid ""
+"Failed to create LVM2 system dir for metadata backups, config files and "
+"internal cache."
+msgstr ""
+
+#: commands/toolcontext.c:942
+msgid ""
+"Set environment variable LVM_SYSTEM_DIR to alternative location or empty "
+"string."
+msgstr ""
+
+#: commands/toolcontext.c:948
+msgid "Library memory pool creation failed"
+msgstr ""
+
+#: commands/toolcontext.c:979
+msgid "Command memory pool creation failed"
+msgstr ""
+
+#: commands/toolcontext.c:1042
+msgid "Reloading config files"
+msgstr ""
+
+#: config/config.c:111
+msgid "Failed to allocate config pool."
+msgstr ""
+
+#: config/config.c:116
+msgid "Failed to allocate config tree."
+msgstr ""
+
+#: config/config.c:165
+msgid "Failed to allocate config tree parser."
+msgstr ""
+
+#: config/config.c:228
+#, c-format
+msgid "%s: Checksum error"
+msgstr ""
+
+#: config/config.c:268
+#, c-format
+msgid "%s is not a regular file"
+msgstr ""
+
+#: config/config.c:276
+#, c-format
+msgid "%s is empty"
+msgstr ""
+
+#: config/config.c:324
+#, c-format
+msgid "Config file %s has disappeared!"
+msgstr ""
+
+#: config/config.c:329
+msgid "Failed to reload configuration files"
+msgstr ""
+
+#: config/config.c:334
+#, c-format
+msgid "Configuration file %s is not a regular file"
+msgstr ""
+
+#: config/config.c:344
+#, c-format
+msgid "Detected config file change to %s"
+msgstr ""
+
+#: config/config.c:368
+#, c-format
+msgid "_write_value: Unknown value type: %d"
+msgstr ""
+
+#: config/config.c:432
+#, c-format
+msgid "Dumping configuration to %s"
+msgstr ""
+
+#: config/config.c:435 config/config.c:441
+#, c-format
+msgid "Failure while writing to %s"
+msgstr ""
+
+#: config/config.c:445
+#, c-format
+msgid "Configuration node %s not found"
+msgstr ""
+
+#: config/config.c:494 config/config.c:497 config/config.c:510
+#: config/config.c:512 config/config.c:527 config/config.c:541
+#: config/config.c:543 config/config.c:572 config/config.c:578
+#: config/config.c:590
+#, c-format
+msgid "Parse error at byte %td (line %d): unexpected token"
+msgstr ""
+
+#: config/config.c:594
+#, c-format
+msgid "Parse error at byte %td (line %d): expected a value"
+msgstr ""
+
+#: config/config.c:810
+#, c-format
+msgid "WARNING: Ignoring duplicate config node: %s (seeking %s)"
+msgstr ""
+
+#: config/config.c:858
+#, c-format
+msgid "Setting %s to %s"
+msgstr ""
+
+#: config/config.c:863
+#, c-format
+msgid "%s not found in config: defaulting to %s"
+msgstr ""
+
+#: config/config.c:881
+#, c-format
+msgid "Setting %s to %ld"
+msgstr ""
+
+#: config/config.c:885
+#, c-format
+msgid "%s not found in config: defaulting to %ld"
+msgstr ""
+
+#: config/config.c:903
+#, c-format
+msgid "Setting %s to %f"
+msgstr ""
+
+#: config/config.c:907
+#, c-format
+msgid "%s not found in config: defaulting to %f"
+msgstr ""
+
+#: device/dev-cache.c:64 device/dev-cache.c:81 device/dev-cache.c:118
+msgid "struct device allocation failed"
+msgstr ""
+
+#: device/dev-cache.c:68 device/dev-cache.c:85
+msgid "struct str_list allocation failed"
+msgstr ""
+
+#: device/dev-cache.c:73 device/dev-cache.c:90 device/dev-cache.c:95
+msgid "filename strdup failed"
+msgstr ""
+
+#: device/dev-cache.c:142
+#, c-format
+msgid "%s: New preferred name"
+msgstr ""
+
+#: device/dev-cache.c:247
+#, c-format
+msgid "%s: Already in device cache"
+msgstr ""
+
+#: device/dev-cache.c:260
+#, c-format
+msgid "%s: Aliased to %s in device cache%s"
+msgstr ""
+
+#: device/dev-cache.c:264
+#, c-format
+msgid "%s: Added to device cache"
+msgstr ""
+
+#: device/dev-cache.c:307
+msgid "Couldn't insert device into binary tree."
+msgstr ""
+
+#: device/dev-cache.c:314
+msgid "Couldn't add alias to dev cache."
+msgstr ""
+
+#: device/dev-cache.c:319
+msgid "Couldn't add name to hash in dev cache."
+msgstr ""
+
+#: device/dev-cache.c:399
+#, c-format
+msgid "%s: Not a regular file"
+msgstr ""
+
+#: device/dev-cache.c:429
+#, c-format
+msgid "%s: Symbolic link to directory"
+msgstr ""
+
+#: device/dev-cache.c:438
+#, c-format
+msgid "%s: Not a block device"
+msgstr ""
+
+#: device/dev-cache.c:496
+msgid ""
+"devices/preferred_names not found in config file: using built-in preferences"
+msgstr ""
+
+#: device/dev-cache.c:503
+msgid "preferred_names patterns must be enclosed in quotes"
+msgstr ""
+
+#: device/dev-cache.c:514
+msgid "Failed to allocate preferred device name pattern list."
+msgstr ""
+
+#: device/dev-cache.c:521
+msgid "Failed to allocate a preferred device name pattern."
+msgstr ""
+
+#: device/dev-cache.c:529
+msgid "Preferred device name pattern matcher creation failed."
+msgstr ""
+
+#: device/dev-cache.c:559
+msgid "Couldn't create binary tree for dev-cache."
+msgstr ""
+
+#: device/dev-cache.c:579
+#, c-format
+msgid "Device '%s' has been left open."
+msgstr ""
+
+#: device/dev-cache.c:617 device/dev-cache.c:643
+#, c-format
+msgid "Ignoring %s: %s"
+msgstr ""
+
+#: device/dev-cache.c:623
+#, c-format
+msgid "Ignoring %s: Not a directory"
+msgstr ""
+
+#: device/dev-cache.c:628
+msgid "dir_list allocation failed"
+msgstr ""
+
+#: device/dev-cache.c:649
+#, c-format
+msgid "Ignoring %s: Not a regular file"
+msgstr ""
+
+#: device/dev-cache.c:654
+msgid "dir_list allocation failed for file"
+msgstr ""
+
+#: device/dev-cache.c:686 device/dev-cache.c:690
+#, c-format
+msgid "Path %s no longer valid for device(%d,%d)"
+msgstr ""
+
+#: device/dev-cache.c:707
+#, c-format
+msgid "Aborting - please provide new pathname for what used to be %s"
+msgstr ""
+
+#: device/dev-cache.c:747
+msgid "dev_iter allocation failed"
+msgstr ""
+
+#: device/dev-io.c:67
+#, c-format
+msgid "Attempt to read an unopened device (%s)."
+msgstr ""
+
+#: device/dev-io.c:79
+#, c-format
+msgid "Read size too large: %lu"
+msgstr ""
+
+#: device/dev-io.c:84
+#, c-format
+msgid "%s: lseek %lu failed: %s"
+msgstr ""
+
+#: device/dev-io.c:98
+#, c-format
+msgid "%s: %s failed after %lu of %lu at %lu: %s"
+msgstr ""
+
+#: device/dev-io.c:134
+#, c-format
+msgid "%s: block size is %u bytes"
+msgstr ""
+
+#: device/dev-io.c:191
+msgid "Bounce buffer alloca failed"
+msgstr ""
+
+#: device/dev-io.c:238 device/dev-io.c:264
+#, c-format
+msgid "%s: size is %lu sectors"
+msgstr ""
+
+#: device/dev-io.c:343
+#, c-format
+msgid "WARNING: %s already opened read-only"
+msgstr ""
+
+#: device/dev-io.c:352
+#, c-format
+msgid "WARNING: dev_open(%s) called while suspended"
+msgstr ""
+
+#: device/dev-io.c:364
+#, c-format
+msgid "%s: stat failed: Has device name changed?"
+msgstr ""
+
+#: device/dev-io.c:390
+#, c-format
+msgid "%s: Not using O_DIRECT"
+msgstr ""
+
+#: device/dev-io.c:422
+#, c-format
+msgid "%s: fstat failed: Has device name changed?"
+msgstr ""
+
+#: device/dev-io.c:437
+#, c-format
+msgid "Opened %s %s%s%s"
+msgstr ""
+
+#: device/dev-io.c:486
+#, c-format
+msgid "Closed %s"
+msgstr ""
+
+#: device/dev-io.c:501
+#, c-format
+msgid "Attempt to close device '%s' which is not open."
+msgstr ""
+
+#: device/dev-io.c:515
+#, c-format
+msgid "%s: Immediate close attempt while still referenced"
+msgstr ""
+
+#: device/dev-io.c:576
+#, c-format
+msgid "Read from %s failed"
+msgstr ""
+
+#: device/dev-io.c:588
+#, c-format
+msgid "Circular read from %s failed"
+msgstr ""
+
+#: device/dev-io.c:648
+#, c-format
+msgid "Wiping %s at %lu length %zu"
+msgstr ""
+
+#: device/dev-io.c:651
+#, c-format
+msgid "Wiping %s at sector %lu length %zu sectors"
+msgstr ""
+
+#: display/display.c:145
+#, c-format
+msgid "Unrecognised allocation policy %s"
+msgstr ""
+
+#: display/display.c:172
+msgid "no memory for size display buffer"
+msgstr ""
+
+#: display/display.c:247
+#, c-format
+msgid "%s:%s:%lu:-1:%u:%u:-1:%u:%u:%u:%u:%s"
+msgstr ""
+
+#: display/display.c:278
+#, c-format
+msgid "--- %sPhysical volume ---"
+msgstr ""
+
+#: display/display.c:279
+#, c-format
+msgid "PV Name               %s"
+msgstr ""
+
+#: display/display.c:280
+#, c-format
+msgid "VG Name               %s%s"
+msgstr ""
+
+#: display/display.c:290
+#, c-format
+msgid "PV Size               %s / not usable %s"
+msgstr ""
+
+#: display/display.c:296
+#, c-format
+msgid "PV Size               %s"
+msgstr ""
+
+#: display/display.c:304
+#, c-format
+msgid "Allocatable           yes %s"
+msgstr ""
+
+#: display/display.c:307
+msgid "Allocatable           NO"
+msgstr ""
+
+#: display/display.c:312
+#, c-format
+msgid "PE Size (KByte)       %u"
+msgstr ""
+
+#: display/display.c:313 display/display.c:592
+#, c-format
+msgid "Total PE              %u"
+msgstr ""
+
+#: display/display.c:314
+#, c-format
+msgid "Free PE               %u"
+msgstr ""
+
+#: display/display.c:315
+#, c-format
+msgid "Allocated PE          %u"
+msgstr ""
+
+#: display/display.c:316 display/display.c:339
+#, c-format
+msgid "PV UUID               %s"
+msgstr ""
+
+#: display/display.c:317 display/display.c:345 display/display.c:476
+#: display/display.c:527 display/display.c:610 format_text/archive.c:315
+#: lvmcmdline.c:769 mirror/mirrored.c:73 striped/striped.c:49
+msgid " "
+msgstr ""
+
+#: display/display.c:337
+#, c-format
+msgid "PV Name               %s     "
+msgstr ""
+
+#: display/display.c:340
+#, c-format
+msgid "PV Status             %sallocatable"
+msgstr ""
+
+#: display/display.c:342
+#, c-format
+msgid "Total PE / Free PE    %u / %u"
+msgstr ""
+
+#: display/display.c:355
+#, c-format
+msgid "%s%s/%s:%s:%d:%d:-1:%d:%lu:%d:-1:%d:%d:%d:%d"
+msgstr ""
+
+#: display/display.c:385
+msgid "--- Logical volume ---"
+msgstr ""
+
+#: display/display.c:387
+#, c-format
+msgid "LV Name                %s%s/%s"
+msgstr ""
+
+#: display/display.c:389
+#, c-format
+msgid "VG Name                %s"
+msgstr ""
+
+#: display/display.c:391
+#, c-format
+msgid "LV UUID                %s"
+msgstr ""
+
+#: display/display.c:393
+#, c-format
+msgid "LV Write Access        %s"
+msgstr ""
+
+#: display/display.c:397
+msgid "LV snapshot status     source of"
+msgstr ""
+
+#: display/display.c:406
+#, c-format
+msgid "                       %s%s/%s [%s]"
+msgstr ""
+
+#: display/display.c:419
+#, c-format
+msgid "LV snapshot status     %s destination for %s%s/%s"
+msgstr ""
+
+#: display/display.c:426
+msgid "LV Status              suspended"
+msgstr ""
+
+#: display/display.c:428
+#, c-format
+msgid "LV Status              %savailable"
+msgstr ""
+
+#: display/display.c:436
+#, c-format
+msgid "# open                 %u"
+msgstr ""
+
+#: display/display.c:438
+#, c-format
+msgid "LV Size                %s"
+msgstr ""
+
+#: display/display.c:442
+#, c-format
+msgid "Current LE             %u"
+msgstr ""
+
+#: display/display.c:446
+#, c-format
+msgid "COW-table size         %s"
+msgstr ""
+
+#: display/display.c:448
+#, c-format
+msgid "COW-table LE           %u"
+msgstr ""
+
+#: display/display.c:451
+#, c-format
+msgid "Allocated to snapshot  %.2f%% "
+msgstr ""
+
+#: display/display.c:453
+#, c-format
+msgid "Snapshot chunk size    %s"
+msgstr ""
+
+#: display/display.c:457
+#, c-format
+msgid "Segments               %u"
+msgstr ""
+
+#: display/display.c:463
+#, c-format
+msgid "Allocation             %s"
+msgstr ""
+
+#: display/display.c:464
+#, c-format
+msgid "Read ahead sectors     %u"
+msgstr ""
+
+#: display/display.c:468
+#, c-format
+msgid "Persistent major       %d"
+msgstr ""
+
+#: display/display.c:469
+#, c-format
+msgid "Persistent minor       %d"
+msgstr ""
+
+#: display/display.c:473
+#, c-format
+msgid "Block device           %d:%d"
+msgstr ""
+
+#: display/display.c:486
+#, c-format
+msgid "%sPhysical volume\t%s"
+msgstr ""
+
+#: display/display.c:492
+#, c-format
+msgid "%sPhysical extents\t%d to %d"
+msgstr ""
+
+#: display/display.c:497
+#, c-format
+msgid "%sLogical volume\t%s"
+msgstr ""
+
+#: display/display.c:502
+#, c-format
+msgid "%sLogical extents\t%d to %d"
+msgstr ""
+
+#: display/display.c:507
+#, c-format
+msgid "%sUnassigned area"
+msgstr ""
+
+#: display/display.c:515
+msgid "--- Segments ---"
+msgstr ""
+
+#: display/display.c:518
+#, c-format
+msgid "Logical extent %u to %u:"
+msgstr ""
+
+#: display/display.c:521
+#, c-format
+msgid "  Type\t\t%s"
+msgstr ""
+
+#: display/display.c:547
+msgid "--- Volume group ---"
+msgstr ""
+
+#: display/display.c:548
+#, c-format
+msgid "VG Name               %s"
+msgstr ""
+
+#: display/display.c:549
+#, c-format
+msgid "System ID             %s"
+msgstr ""
+
+#: display/display.c:550
+#, c-format
+msgid "Format                %s"
+msgstr ""
+
+#: display/display.c:552
+#, c-format
+msgid "Metadata Areas        %d"
+msgstr ""
+
+#: display/display.c:554
+#, c-format
+msgid "Metadata Sequence No  %d"
+msgstr ""
+
+#: display/display.c:557
+#, c-format
+msgid "VG Access             %s%s%s%s"
+msgstr ""
+
+#: display/display.c:562
+#, c-format
+msgid "VG Status             %s%sresizable"
+msgstr ""
+
+#: display/display.c:569
+msgid "Clustered             yes"
+msgstr ""
+
+#: display/display.c:570
+#, c-format
+msgid "Shared                %s"
+msgstr ""
+
+#: display/display.c:573
+#, c-format
+msgid "MAX LV                %u"
+msgstr ""
+
+#: display/display.c:574
+#, c-format
+msgid "Cur LV                %u"
+msgstr ""
+
+#: display/display.c:575
+#, c-format
+msgid "Open LV               %u"
+msgstr ""
+
+#: display/display.c:581
+#, c-format
+msgid "Max PV                %u"
+msgstr ""
+
+#: display/display.c:582
+#, c-format
+msgid "Cur PV                %u"
+msgstr ""
+
+#: display/display.c:583
+#, c-format
+msgid "Act PV                %u"
+msgstr ""
+
+#: display/display.c:585
+#, c-format
+msgid "VG Size               %s"
+msgstr ""
+
+#: display/display.c:589
+#, c-format
+msgid "PE Size               %s"
+msgstr ""
+
+#: display/display.c:594
+#, c-format
+msgid "Alloc PE / Size       %u / %s"
+msgstr ""
+
+#: display/display.c:600
+#, c-format
+msgid "Free  PE / Size       %u / %s"
+msgstr ""
+
+#: display/display.c:609
+#, c-format
+msgid "VG UUID               %s"
+msgstr ""
+
+#: display/display.c:645
+#, c-format
+msgid "%s:%s:%d:-1:%u:%u:%u:-1:%u:%u:%u:%lu:%u:%u:%u:%u:%s"
+msgstr ""
+
+#: display/display.c:669
+#, c-format
+msgid "\"%s\" %-9s [%-9s used / %s free]"
+msgstr ""
+
+#: display/display.c:686 display/display.c:695 pvscan.c:34
+#, c-format
+msgid "%s"
+msgstr ""
+
+#: error/errseg.c:73
+msgid "error module string list allocation failed"
+msgstr ""
+
+#: error/errseg.c:109 mirror/mirrored.c:562 snapshot/snapshot.c:179
+#: striped/striped.c:227 zero/zero.c:109
+#, c-format
+msgid "Initialised segtype: %s"
+msgstr ""
+
+#: filters/filter-composite.c:31
+#, c-format
+msgid "Using %s"
+msgstr ""
+
+#: filters/filter-composite.c:59
+msgid "composite filters allocation failed"
+msgstr ""
+
+#: filters/filter-composite.c:67
+msgid "compsoite filters allocation failed"
+msgstr ""
+
+#: filters/filter-md.c:31
+#, c-format
+msgid "%s: Skipping md component device"
+msgstr ""
+
+#: filters/filter-md.c:36
+#, c-format
+msgid "%s: Skipping: error in md component detection"
+msgstr ""
+
+#: filters/filter-md.c:54
+msgid "md filter allocation failed"
+msgstr ""
+
+#: filters/filter-persistent.c:57
+msgid "Wiping cache of LVM-capable devices"
+msgstr ""
+
+#: filters/filter-persistent.c:73
+#, c-format
+msgid "Couldn't find %s array in '%s'"
+msgstr ""
+
+#: filters/filter-persistent.c:84
+msgid "Devices array contains a value which is not a string ... ignoring"
+msgstr ""
+
+#: filters/filter-persistent.c:90
+#, c-format
+msgid "Couldn't add '%s' to filter ... ignoring"
+msgstr ""
+
+#: filters/filter-persistent.c:108
+#, c-format
+msgid "%s: stat failed: %s"
+msgstr ""
+
+#: filters/filter-persistent.c:132
+#, c-format
+msgid "Loaded persistent filter cache from %s"
+msgstr ""
+
+#: filters/filter-persistent.c:183
+#, c-format
+msgid "Internal persistent device cache empty - not writing to %s"
+msgstr ""
+
+#: filters/filter-persistent.c:188
+#, c-format
+msgid "Device cache incomplete - not writing to %s"
+msgstr ""
+
+#: filters/filter-persistent.c:193
+#, c-format
+msgid "Dumping persistent device cache to %s"
+msgstr ""
+
+#: filters/filter-persistent.c:248 format_text/format-text.c:902
+#: format_text/format-text.c:928 format_text/format-text.c:965
+#: misc/lvm-file.c:91
+#, c-format
+msgid "%s: rename to %s failed: %s"
+msgstr ""
+
+#: filters/filter-persistent.c:276
+#, c-format
+msgid "%s: Skipping (cached)"
+msgstr ""
+
+#: filters/filter-persistent.c:311
+msgid "Couldn't create hash table for persistent filter."
+msgstr ""
+
+#: filters/filter-regex.c:44
+msgid "pattern must begin with 'a' or 'r'"
+msgstr ""
+
+#: filters/filter-regex.c:83
+msgid "invalid separator at end of regex"
+msgstr ""
+
+#: filters/filter-regex.c:108
+msgid "filter patterns must be enclosed in quotes"
+msgstr ""
+
+#: filters/filter-regex.c:133
+msgid "invalid filter pattern"
+msgstr ""
+
+#: filters/filter-regex.c:174
+#, c-format
+msgid "%s: Skipping (regex)"
+msgstr ""
+
+#: filters/filter-sysfs.c:31
+msgid "No proc filesystem found: skipping sysfs filter"
+msgstr ""
+
+#: filters/filter-sysfs.c:37
+msgid "Failed to create /proc/mounts string"
+msgstr ""
+
+#: filters/filter-sysfs.c:137
+#, c-format
+msgid "Empty sysfs device file: %s"
+msgstr ""
+
+#: filters/filter-sysfs.c:142
+msgid "sysfs device file not correct format"
+msgstr ""
+
+#: filters/filter-sysfs.c:192
+#, c-format
+msgid "sysfs path name too long: %s in %s"
+msgstr ""
+
+#: filters/filter-sysfs.c:255
+#, c-format
+msgid "%s: Skipping (sysfs)"
+msgstr ""
+
+#: filters/filter-sysfs.c:278
+msgid "sysfs pool creation failed"
+msgstr ""
+
+#: filters/filter-sysfs.c:283
+msgid "sysfs dev_set creation failed"
+msgstr ""
+
+#: filters/filter.c:90
+#, c-format
+msgid "%s: Skipping: Unrecognised LVM device type %lu"
+msgstr ""
+
+#: filters/filter.c:98
+#, c-format
+msgid "%s: Skipping: Suspended dm device"
+msgstr ""
+
+#: filters/filter.c:104
+#, c-format
+msgid "%s: Skipping: open failed"
+msgstr ""
+
+#: filters/filter.c:110
+#, c-format
+msgid "%s: Skipping: dev_get_size failed"
+msgstr ""
+
+#: filters/filter.c:115
+#, c-format
+msgid "%s: Skipping: Too small to hold a PV"
+msgstr ""
+
+#: filters/filter.c:120
+#, c-format
+msgid "%s: Skipping: Partition table signature found"
+msgstr ""
+
+#: filters/filter.c:147
+msgid "No proc filesystem found: using all block device types"
+msgstr ""
+
+#: filters/filter.c:159
+msgid "Failed to create /proc/devices string"
+msgstr ""
+
+#: filters/filter.c:218
+msgid "Expecting string in devices/types in config file"
+msgstr ""
+
+#: filters/filter.c:228
+#, c-format
+msgid "Max partition count missing for %s in devices/types in config file"
+msgstr ""
+
+#: filters/filter.c:236
+#, c-format
+msgid "Zero partition count invalid for %s in devices/types in config file"
+msgstr ""
+
+#: filters/filter.c:269
+msgid "LVM type filter allocation failed"
+msgstr ""
+
+#: format1/disk-rep.c:190
+#, c-format
+msgid "%s does not have a valid LVM1 PV identifier"
+msgstr ""
+
+#: format1/disk-rep.c:196
+#, c-format
+msgid "format1: Unknown metadata version %d found on %s"
+msgstr ""
+
+#: format1/disk-rep.c:210 format_pool/disk_rep.c:43
+#, c-format
+msgid "Failed to read PV data from %s"
+msgstr ""
+
+#: format1/disk-rep.c:367
+#, c-format
+msgid "%s is not a member of any format1 VG"
+msgstr ""
+
+#: format1/disk-rep.c:374
+#, c-format
+msgid "Failed to read VG data from PV (%s)"
+msgstr ""
+
+#: format1/disk-rep.c:380
+#, c-format
+msgid "%s is not a member of the VG %s"
+msgstr ""
+
+#: format1/disk-rep.c:390
+#, c-format
+msgid "Failed to read PV uuid list from %s"
+msgstr ""
+
+#: format1/disk-rep.c:395
+#, c-format
+msgid "Failed to read LV's from %s"
+msgstr ""
+
+#: format1/disk-rep.c:400
+#, c-format
+msgid "Failed to read extents from %s"
+msgstr ""
+
+#: format1/disk-rep.c:404
+#, c-format
+msgid "Found %s in %sVG %s"
+msgstr ""
+
+#: format1/disk-rep.c:443 format_pool/disk_rep.c:67
+#, c-format
+msgid "Ignoring duplicate PV %s on %s"
+msgstr ""
+
+#: format1/disk-rep.c:448 format_pool/disk_rep.c:72
+#, c-format
+msgid "Duplicate PV %s - using md %s"
+msgstr ""
+
+#: format1/disk-rep.c:494
+msgid "read_pvs_in_vg: dev_iter_create failed"
+msgstr ""
+
+#: format1/disk-rep.c:517
+#, c-format
+msgid "Writing %s VG metadata to %s at %lu len %zu"
+msgstr ""
+
+#: format1/disk-rep.c:537
+#, c-format
+msgid "Too many uuids to fit on %s"
+msgstr ""
+
+#: format1/disk-rep.c:542
+#, c-format
+msgid "Writing %s uuidlist to %s at %lu len %d"
+msgstr ""
+
+#: format1/disk-rep.c:557
+#, c-format
+msgid "Writing %s LV %s metadata to %s at %lu len %zu"
+msgstr ""
+
+#: format1/disk-rep.c:578
+#, c-format
+msgid "Couldn't zero lv area on device '%s'"
+msgstr ""
+
+#: format1/disk-rep.c:586
+#, c-format
+msgid "lv_number %d too large"
+msgstr ""
+
+#: format1/disk-rep.c:603
+#, c-format
+msgid "Writing %s extents metadata to %s at %lu len %zu"
+msgstr ""
+
+#: format1/disk-rep.c:623
+msgid "Invalid PV structure size."
+msgstr ""
+
+#: format1/disk-rep.c:632
+msgid "Couldn't allocate temporary PV buffer."
+msgstr ""
+
+#: format1/disk-rep.c:639
+#, c-format
+msgid "Writing %s PV metadata to %s at %lu len %zu"
+msgstr ""
+
+#: format1/disk-rep.c:662
+#, c-format
+msgid "Failed to write PV structure onto %s"
+msgstr ""
+
+#: format1/disk-rep.c:681
+#, c-format
+msgid "Failed to write VG data to %s"
+msgstr ""
+
+#: format1/disk-rep.c:686
+#, c-format
+msgid "Failed to write PV uuid list to %s"
+msgstr ""
+
+#: format1/disk-rep.c:691
+#, c-format
+msgid "Failed to write LV's to %s"
+msgstr ""
+
+#: format1/disk-rep.c:696
+#, c-format
+msgid "Failed to write extents to %s"
+msgstr ""
+
+#: format1/disk-rep.c:736
+#, c-format
+msgid "Successfully wrote data to %s"
+msgstr ""
+
+#: format1/format1.c:72
+#, c-format
+msgid "VG data differs between PVs %s and %s"
+msgstr ""
+
+#: format1/format1.c:74 format1/format1.c:89
+#, c-format
+msgid "VG data on %s: %s %s %u %u  %u %u %u %u %u %u %u %u %u %u %u %u %u"
+msgstr ""
+
+#: format1/format1.c:115
+#, c-format
+msgid "%d PV(s) found for VG %s: expected %d"
+msgstr ""
+
+#: format1/format1.c:294 format_pool/format_pool.c:228
+#, c-format
+msgid "Reading physical volume data %s from disk"
+msgstr ""
+
+#: format1/format1.c:335
+#, c-format
+msgid "Physical volumes cannot be bigger than %s"
+msgstr ""
+
+#: format1/format1.c:355
+msgid "Metadata would overwrite physical extents"
+msgstr ""
+
+#: format1/format1.c:370
+#, c-format
+msgid "logical volumes cannot contain more than %d extents."
+msgstr ""
+
+#: format1/format1.c:375
+#, c-format
+msgid "logical volumes cannot be larger than %s"
+msgstr ""
+
+#: format1/format1.c:451
+#, c-format
+msgid "Extent size must be between %s and %s"
+msgstr ""
+
+#: format1/format1.c:459
+#, c-format
+msgid "Extent size must be multiple of %s"
+msgstr ""
+
+#: format1/format1.c:466 format_text/format-text.c:79
+msgid "Extent size must be power of 2"
+msgstr ""
+
+#: format1/format1.c:563
+msgid "Couldn't create lvm1 label handler."
+msgstr ""
+
+#: format1/format1.c:568
+msgid "Couldn't register lvm1 label handler."
+msgstr ""
+
+#: format1/format1.c:572 format_pool/format_pool.c:354
+#: format_text/format-text.c:1994
+#, c-format
+msgid "Initialised format: %s"
+msgstr ""
+
+#: format1/import-export.c:75
+#, c-format
+msgid "System ID %s on %s differs from %s for volume group"
+msgstr ""
+
+#: format1/import-export.c:98 format_text/import_vsn1.c:220
+#: metadata/metadata.c:569 metadata/metadata.c:1542 pvresize.c:121
+#: vgreduce.c:395 vgremove.c:62
+#, c-format
+msgid "%s: Couldn't get size."
+msgstr ""
+
+#: format1/import-export.c:101 format_text/import_vsn1.c:223
+#, c-format
+msgid "Fixing up missing format1 size (%s) for PV %s"
+msgstr ""
+
+#: format1/import-export.c:108 format_text/import_vsn1.c:230
+#, c-format
+msgid "WARNING: Physical Volume %s is too large for underlying device"
+msgstr ""
+
+#: format1/import-export.c:130
+msgid "Generated system_id too long"
+msgstr ""
+
+#: format1/import-export.c:174
+#, c-format
+msgid "Volume group name %s too long to export"
+msgstr ""
+
+#: format1/import-export.c:412
+#, c-format
+msgid "Segment type %s in LV %s: unsupported by format1"
+msgstr ""
+
+#: format1/import-export.c:418
+#, c-format
+msgid "Non-PV stripe found in LV %s: unsupported by format1"
+msgstr ""
+
+#: format1/import-export.c:610
+msgid "Logical volume number out of bounds."
+msgstr ""
+
+#: format1/import-export.c:617
+#, c-format
+msgid "Couldn't find logical volume '%s'."
+msgstr ""
+
+#: format1/import-export.c:637
+#, c-format
+msgid "Couldn't find origin logical volume for snapshot '%s'."
+msgstr ""
+
+#: format1/import-export.c:650
+msgid "Couldn't add snapshot."
+msgstr ""
+
+#: format1/import-extents.c:53
+msgid "Unable to create hash table for holding extent maps."
+msgstr ""
+
+#: format1/import-extents.c:92
+#, c-format
+msgid "Physical volume (%s) contains an unknown logical volume (%s)."
+msgstr ""
+
+#: format1/import-extents.c:137
+#, c-format
+msgid "Invalid LV in extent map (PV %s, PE %u, LV %u, LE %u)"
+msgstr ""
+
+#: format1/import-extents.c:149
+msgid "logical extent number out of bounds"
+msgstr ""
+
+#: format1/import-extents.c:155
+#, c-format
+msgid "logical extent (%u) already mapped."
+msgstr ""
+
+#: format1/import-extents.c:175
+#, c-format
+msgid "Logical volume (%s) contains an incomplete mapping table."
+msgstr ""
+
+#: format1/import-extents.c:229
+msgid "Failed to allocate linear segment."
+msgstr ""
+
+#: format1/import-extents.c:276
+#, c-format
+msgid ""
+"Number of stripes (%u) incompatible with logical extent count (%u) for %s"
+msgstr ""
+
+#: format1/import-extents.c:303
+msgid "Failed to allocate striped segment."
+msgstr ""
+
+#: format1/import-extents.c:359
+msgid "Couldn't allocate logical volume maps."
+msgstr ""
+
+#: format1/import-extents.c:364
+msgid "Couldn't fill logical volume maps."
+msgstr ""
+
+#: format1/import-extents.c:374
+msgid "Couldn't build extent segments."
+msgstr ""
+
+#: format1/layout.c:79
+#, c-format
+msgid "MaxLogicalVolumes of %d exceeds format limit of %d for VG '%s'"
+msgstr ""
+
+#: format1/layout.c:86
+#, c-format
+msgid "MaxPhysicalVolumes of %d exceeds format limit of %d for VG '%s'"
+msgstr ""
+
+#: format1/layout.c:105
+msgid "Insufficient space for metadata and PE's."
+msgstr ""
+
+#: format1/layout.c:141
+#, c-format
+msgid "Too few extents on %s.  Try smaller extent size."
+msgstr ""
+
+#: format1/layout.c:162
+#, c-format
+msgid "Metadata extent limit (%u) exceeded for %s - %u required"
+msgstr ""
+
+#: format1/lvm1-label.c:29
+#, c-format
+msgid "The '%s' operation is not supported for the lvm1 labeller."
+msgstr ""
+
+#: format1/lvm1-label.c:120 format_pool/pool_label.c:99
+#: format_text/text_label.c:285
+msgid "Couldn't allocate labeller object."
+msgstr ""
+
+#: format_pool/disk_rep.c:94 format_pool/disk_rep.c:98
+#, c-format
+msgid "Calculated uuid %s for %s"
+msgstr ""
+
+#: format_pool/disk_rep.c:274
+#, c-format
+msgid "Unable to allocate %d 32-bit uints"
+msgstr ""
+
+#: format_pool/disk_rep.c:341
+#, c-format
+msgid "No devices for vg %s found in cache"
+msgstr ""
+
+#: format_pool/disk_rep.c:363
+msgid "Unable to allocate pool list structure"
+msgstr ""
+
+#: format_pool/format_pool.c:44
+#, c-format
+msgid "Unable to allocate %d subpool structures"
+msgstr ""
+
+#: format_pool/format_pool.c:64
+#, c-format
+msgid "Unable to allocate %d pool_device structures"
+msgstr ""
+
+#: format_pool/format_pool.c:87
+#, c-format
+msgid "Missing subpool %d in pool %s"
+msgstr ""
+
+#: format_pool/format_pool.c:92
+#, c-format
+msgid "Missing device %u for subpool %d in pool %s"
+msgstr ""
+
+#: format_pool/format_pool.c:113
+msgid "Unable to allocate volume group structure"
+msgstr ""
+
+#: format_pool/format_pool.c:279
+msgid "Unable to allocate format instance structure for pool format"
+msgstr ""
+
+#: format_pool/format_pool.c:289
+msgid "Unable to allocate metadata area structure for pool format"
+msgstr ""
+
+#: format_pool/format_pool.c:332
+msgid "Unable to allocate format type structure for pool format"
+msgstr ""
+
+#: format_pool/format_pool.c:345
+msgid "Couldn't create pool label handler."
+msgstr ""
+
+#: format_pool/format_pool.c:350
+msgid "Couldn't register pool label handler."
+msgstr ""
+
+#: format_pool/import_export.c:64
+msgid "Unable to allocate lv list structure"
+msgstr ""
+
+#: format_pool/import_export.c:69
+msgid "Unable to allocate logical volume structure"
+msgstr ""
+
+#: format_pool/import_export.c:98
+#, c-format
+msgid "Calculated lv uuid for lv %s: %s"
+msgstr ""
+
+#: format_pool/import_export.c:133
+msgid "Unable to allocate pv list structure"
+msgstr ""
+
+#: format_pool/import_export.c:137
+msgid "Unable to allocate pv structure"
+msgstr ""
+
+#: format_pool/import_export.c:165
+msgid "Unable to duplicate vg_name string"
+msgstr ""
+
+#: format_pool/import_export.c:195
+#, c-format
+msgid "Found sptype %X and converted it to %s"
+msgstr ""
+
+#: format_pool/import_export.c:210
+msgid "Stripe size must be a power of 2"
+msgstr ""
+
+#: format_pool/import_export.c:226
+msgid "Unable to allocate striped lv_segment structure"
+msgstr ""
+
+#: format_pool/import_export.c:267
+msgid "Unable to allocate linear lv_segment structure"
+msgstr ""
+
+#: format_pool/pool_label.c:28
+#, c-format
+msgid "The '%s' operation is not supported for the pool labeller."
+msgstr ""
+
+#: format_text/archive.c:146
+#, c-format
+msgid "Couldn't scan the archive directory (%s)."
+msgstr ""
+
+#: format_text/archive.c:173
+msgid "Couldn't create new archive file."
+msgstr ""
+
+#: format_text/archive.c:221
+#, c-format
+msgid "Expiring archive %s"
+msgstr ""
+
+#: format_text/archive.c:246
+msgid "Couldn't create temporary archive name."
+msgstr ""
+
+#: format_text/archive.c:251
+msgid "Couldn't create FILE object for archive."
+msgstr ""
+
+#: format_text/archive.c:288
+msgid "Archive file name too long."
+msgstr ""
+
+#: format_text/archive.c:299
+#, c-format
+msgid "Archive rename failed for %s"
+msgstr ""
+
+#: format_text/archive.c:316
+#, c-format
+msgid "File:\t\t%s"
+msgstr ""
+
+#: format_text/archive.c:321
+msgid "Couldn't create text instance object."
+msgstr ""
+
+#: format_text/archive.c:331
+msgid "Unable to read archive file."
+msgstr ""
+
+#: format_text/archive.c:336
+#, c-format
+msgid "VG name:    \t%s"
+msgstr ""
+
+#: format_text/archive.c:337
+#, c-format
+msgid "Description:\t%s"
+msgstr ""
+
+#: format_text/archive.c:338
+#, c-format
+msgid "Backup Time:\t%s"
+msgstr ""
+
+#: format_text/archive.c:355
+#, c-format
+msgid "No archives found in %s."
+msgstr ""
+
+#: format_text/archiver.c:43 format_text/archiver.c:155
+msgid "archive_params alloc failed"
+msgstr ""
+
+#: format_text/archiver.c:128
+#, c-format
+msgid "Archiving volume group \"%s\" metadata (seqno %u)."
+msgstr ""
+
+#: format_text/archiver.c:303
+#, c-format
+msgid "PV %s is a different format (seqno %s)"
+msgstr ""
+
+#: format_text/archiver.c:364
+#, c-format
+msgid "Creating volume group backup \"%s\" (seqno %u)."
+msgstr ""
+
+#: format_text/archiver.c:402
+msgid "Failed to generate backup filename."
+msgstr ""
+
+#: format_text/export.c:80
+#, c-format
+msgid "uname failed: %s"
+msgstr ""
+
+#: format_text/export.c:101
+msgid "Internal error tracking indentation"
+msgstr ""
+
+#: format_text/export.c:120
+#, c-format
+msgid "Doubling metadata output buffer to %u"
+msgstr ""
+
+#: format_text/export.c:124
+msgid "Buffer reallocation failed."
+msgstr ""
+
+#: format_text/export.c:737
+msgid "text_export buffer allocation failed"
+msgstr ""
+
+#: format_text/flags.c:79
+msgid "Unknown flag set requested."
+msgstr ""
+
+#: format_text/flags.c:125
+msgid "Metadata inconsistency: Not all flags successfully exported."
+msgstr ""
+
+#: format_text/flags.c:147
+msgid "Status value is not a string."
+msgstr ""
+
+#: format_text/flags.c:158
+#, c-format
+msgid "Unknown status flag '%s'."
+msgstr ""
+
+#: format_text/format-text.c:152
+#, c-format
+msgid "Found text metadata area, offset=%lu, size=%lu"
+msgstr ""
+
+#: format_text/format-text.c:207
+#, c-format
+msgid ""
+"Found LVM2 metadata record at offset=%lu, size=%lu, offset2=%lu size2=%lu"
+msgstr ""
+
+#: format_text/format-text.c:259
+#, c-format
+msgid "Random lvid creation failed for %s/%s."
+msgstr ""
+
+#: format_text/format-text.c:290
+msgid "struct mda_header allocation failed"
+msgstr ""
+
+#: format_text/format-text.c:302
+msgid "Incorrect metadata area header checksum"
+msgstr ""
+
+#: format_text/format-text.c:309
+msgid "Wrong magic number in metadata area header"
+msgstr ""
+
+#: format_text/format-text.c:314
+#, c-format
+msgid "Incompatible metadata area header version: %d"
+msgstr ""
+
+#: format_text/format-text.c:320
+#, c-format
+msgid "Incorrect start sector in metadata area header: %lu"
+msgstr ""
+
+#: format_text/format-text.c:461
+#, c-format
+msgid "VG %s not found on %s"
+msgstr ""
+
+#: format_text/format-text.c:469 format_text/format-text.c:574
+#, c-format
+msgid "VG %s metadata too large for circular buffer"
+msgstr ""
+
+#: format_text/format-text.c:484
+#, c-format
+msgid "Read %s %smetadata (%u) from %s at %lu size %lu"
+msgstr ""
+
+#: format_text/format-text.c:557
+#, c-format
+msgid "VG %s metadata writing failed"
+msgstr ""
+
+#: format_text/format-text.c:579
+#, c-format
+msgid "Writing %s metadata to %s at %lu len %lu"
+msgstr ""
+
+#: format_text/format-text.c:592
+#, c-format
+msgid "Writing metadata to %s at %lu len %u"
+msgstr ""
+
+#: format_text/format-text.c:681
+#, c-format
+msgid "%sCommitting %s metadata (%u) to %s header at %lu"
+msgstr ""
+
+#: format_text/format-text.c:685
+#, c-format
+msgid "Wiping pre-committed %s metadata from %s header at %lu"
+msgstr ""
+
+#: format_text/format-text.c:691 format_text/format-text.c:777
+msgid "Failed to write metadata area header"
+msgstr ""
+
+#: format_text/format-text.c:810
+#, c-format
+msgid "'%s' does not contain volume group '%s'."
+msgstr ""
+
+#: format_text/format-text.c:814
+#, c-format
+msgid "Read volume group %s from %s"
+msgstr ""
+
+#: format_text/format-text.c:863
+msgid "Text format failed to determine directory."
+msgstr ""
+
+#: format_text/format-text.c:868
+msgid "Couldn't create temporary text file name."
+msgstr ""
+
+#: format_text/format-text.c:879
+#, c-format
+msgid "Writing %s metadata to %s"
+msgstr ""
+
+#: format_text/format-text.c:882
+#, c-format
+msgid "Failed to write metadata to %s."
+msgstr ""
+
+#: format_text/format-text.c:901 format_text/format-text.c:926
+#: format_text/format-text.c:960
+#, c-format
+msgid "Renaming %s to %s"
+msgstr ""
+
+#: format_text/format-text.c:917
+#, c-format
+msgid "Test mode: Skipping committing %s metadata (%u)"
+msgstr ""
+
+#: format_text/format-text.c:920
+#, c-format
+msgid "Unlinking %s"
+msgstr ""
+
+#: format_text/format-text.c:925
+#, c-format
+msgid "Committing %s metadata (%u)"
+msgstr ""
+
+#: format_text/format-text.c:962
+msgid "Test mode: Skipping rename"
+msgstr ""
+
+#: format_text/format-text.c:1025 format_text/format-text.c:1723
+#, c-format
+msgid "Name too long %s/%s"
+msgstr ""
+
+#: format_text/format-text.c:1089
+#, c-format
+msgid "%s: metadata too large for circular buffer"
+msgstr ""
+
+#: format_text/format-text.c:1118
+#, c-format
+msgid "%s: Found metadata at %lu size %lu for %s (%s)"
+msgstr ""
+
+#: format_text/format-text.c:1186
+#, c-format
+msgid "Physical extents end beyond end of device %s!"
+msgstr ""
+
+#: format_text/format-text.c:1207
+#, c-format
+msgid "Warning: metadata area fills disk leaving no space for data on %s."
+msgstr ""
+
+#: format_text/format-text.c:1238 format_text/format-text.c:1283
+msgid "Failed to wipe new metadata area"
+msgstr ""
+
+#: format_text/format-text.c:1329
+#, c-format
+msgid "Creating metadata area on %s at sector %lu size %lu sectors"
+msgstr ""
+
+#: format_text/format-text.c:1410
+msgid "_add_raw allocation failed"
+msgstr ""
+
+#: format_text/format-text.c:1470
+#, c-format
+msgid "Must be exactly one data area (found %d) on PV %s"
+msgstr ""
+
+#: format_text/format-text.c:1485 format_text/format-text.c:1489
+msgid "metadata_area allocation failed"
+msgstr ""
+
+#: format_text/format-text.c:1650
+#, c-format
+msgid "PV %s too large for extent size %s."
+msgstr ""
+
+#: format_text/format-text.c:1693
+msgid "Couldn't allocate format instance object."
+msgstr ""
+
+#: format_text/format-text.c:1699
+msgid "Couldn't allocate text_fid_context."
+msgstr ""
+
+#: format_text/format-text.c:1807
+#, c-format
+msgid "%s: Volume group filename may not end in .tmp"
+msgstr ""
+
+#: format_text/format-text.c:1841
+msgid "Couldn't allocate text format context object."
+msgstr ""
+
+#: format_text/format-text.c:1863
+msgid "_add_dir allocation failed"
+msgstr ""
+
+#: format_text/format-text.c:1866
+#, c-format
+msgid "Adding text format metadata dir: %s"
+msgstr ""
+
+#: format_text/format-text.c:1883
+msgid "Empty metadata disk_area section of config file"
+msgstr ""
+
+#: format_text/format-text.c:1888
+msgid "Missing start_sector in metadata disk_area section of config file"
+msgstr ""
+
+#: format_text/format-text.c:1895
+msgid "Missing size in metadata disk_area section of config file"
+msgstr ""
+
+#: format_text/format-text.c:1902
+msgid "Missing uuid in metadata disk_area section of config file"
+msgstr ""
+
+#: format_text/format-text.c:1908
+#, c-format
+msgid "Invalid uuid in metadata disk_area section of config file: %s"
+msgstr ""
+
+#: format_text/format-text.c:1917 format_text/import_vsn1.c:155
+msgid "Couldn't find device."
+msgstr ""
+
+#: format_text/format-text.c:1919 format_text/import_vsn1.c:157
+#, c-format
+msgid "Couldn't find device with uuid '%s'."
+msgstr ""
+
+#: format_text/format-text.c:1948
+msgid "Failed to allocate dir_list"
+msgstr ""
+
+#: format_text/format-text.c:1960
+msgid "Couldn't create text label handler."
+msgstr ""
+
+#: format_text/format-text.c:1966
+msgid "Couldn't register text label handler."
+msgstr ""
+
+#: format_text/format-text.c:1974
+msgid "Invalid string in config file: metadata/dirs"
+msgstr ""
+
+#: format_text/import.c:103
+msgid "Couldn't read volume group metadata."
+msgstr ""
+
+#: format_text/import_vsn1.c:46
+#, c-format
+msgid "Can't process text format file - %s."
+msgstr ""
+
+#: format_text/import_vsn1.c:94
+msgid "Couldn't find uuid."
+msgstr ""
+
+#: format_text/import_vsn1.c:100
+msgid "uuid must be a string."
+msgstr ""
+
+#: format_text/import_vsn1.c:105
+msgid "Invalid uuid."
+msgstr ""
+
+#: format_text/import_vsn1.c:139
+msgid "Empty pv section."
+msgstr ""
+
+#: format_text/import_vsn1.c:144
+msgid "Couldn't read uuid for volume group."
+msgstr ""
+
+#: format_text/import_vsn1.c:174
+msgid "Couldn't find status flags for physical volume."
+msgstr ""
+
+#: format_text/import_vsn1.c:179
+msgid "Couldn't read status flags for physical volume."
+msgstr ""
+
+#: format_text/import_vsn1.c:187
+msgid "Couldn't read extent size for volume group."
+msgstr ""
+
+#: format_text/import_vsn1.c:192
+msgid "Couldn't find extent count (pe_count) for physical volume."
+msgstr ""
+
+#: format_text/import_vsn1.c:203
+#, c-format
+msgid "Couldn't read tags for physical volume %s in %s."
+msgstr ""
+
+#: format_text/import_vsn1.c:275
+msgid "Empty segment section."
+msgstr ""
+
+#: format_text/import_vsn1.c:280
+#, c-format
+msgid "Couldn't read 'start_extent' for segment '%s'."
+msgstr ""
+
+#: format_text/import_vsn1.c:286
+#, c-format
+msgid "Couldn't read 'extent_count' for segment '%s'."
+msgstr ""
+
+#: format_text/import_vsn1.c:296
+msgid "Segment type must be a string."
+msgstr ""
+
+#: format_text/import_vsn1.c:316
+msgid "Segment allocation failed"
+msgstr ""
+
+#: format_text/import_vsn1.c:329
+#, c-format
+msgid "Couldn't read tags for a segment of %s/%s."
+msgstr ""
+
+#: format_text/import_vsn1.c:358
+#, c-format
+msgid "Zero areas not allowed for segment '%s'"
+msgstr ""
+
+#: format_text/import_vsn1.c:394
+#, c-format
+msgid "Couldn't find volume '%s' for segment '%s'."
+msgstr ""
+
+#: format_text/import_vsn1.c:407
+#, c-format
+msgid "Incorrect number of areas in area array for segment '%s'."
+msgstr ""
+
+#: format_text/import_vsn1.c:437
+msgid "Only one segment permitted for snapshot"
+msgstr ""
+
+#: format_text/import_vsn1.c:443
+msgid "Couldn't read segment count for logical volume."
+msgstr ""
+
+#: format_text/import_vsn1.c:448
+msgid "segment_count and actual number of segments disagree."
+msgstr ""
+
+#: format_text/import_vsn1.c:494 format_text/import_vsn1.c:562
+msgid "Empty logical volume section."
+msgstr ""
+
+#: format_text/import_vsn1.c:499
+msgid "Couldn't find status flags for logical volume."
+msgstr ""
+
+#: format_text/import_vsn1.c:504
+msgid "Couldn't read status flags for logical volume."
+msgstr ""
+
+#: format_text/import_vsn1.c:512 format_text/import_vsn1.c:729
+msgid "allocation_policy must be a string."
+msgstr ""
+
+#: format_text/import_vsn1.c:535
+#, c-format
+msgid "Couldn't read tags for logical volume %s/%s."
+msgstr ""
+
+#: format_text/import_vsn1.c:555
+#, c-format
+msgid "Lost logical volume reference %s"
+msgstr ""
+
+#: format_text/import_vsn1.c:568
+#, c-format
+msgid "Couldn't read uuid for logical volume %s."
+msgstr ""
+
+#: format_text/import_vsn1.c:595
+#, c-format
+msgid "Couldn't read minor number for logical volume %s."
+msgstr ""
+
+#: format_text/import_vsn1.c:603
+#, c-format
+msgid "Couldn't read major number for logical volume %s."
+msgstr ""
+
+#: format_text/import_vsn1.c:620
+#, c-format
+msgid "Couldn't find section '%s'."
+msgstr ""
+
+#: format_text/import_vsn1.c:649 format_text/import_vsn1.c:841
+msgid "Couldn't find volume group in file."
+msgstr ""
+
+#: format_text/import_vsn1.c:673
+msgid "system_id must be a string"
+msgstr ""
+
+#: format_text/import_vsn1.c:680 format_text/import_vsn1.c:851
+#, c-format
+msgid "Couldn't read uuid for volume group %s."
+msgstr ""
+
+#: format_text/import_vsn1.c:685
+#, c-format
+msgid "Couldn't read 'seqno' for volume group %s."
+msgstr ""
+
+#: format_text/import_vsn1.c:691 format_text/import_vsn1.c:856
+#, c-format
+msgid "Couldn't find status flags for volume group %s."
+msgstr ""
+
+#: format_text/import_vsn1.c:697 format_text/import_vsn1.c:862
+#, c-format
+msgid "Couldn't read status flags for volume group %s."
+msgstr ""
+
+#: format_text/import_vsn1.c:703
+#, c-format
+msgid "Couldn't read extent size for volume group %s."
+msgstr ""
+
+#: format_text/import_vsn1.c:714
+#, c-format
+msgid "Couldn't read 'max_lv' for volume group %s."
+msgstr ""
+
+#: format_text/import_vsn1.c:720
+#, c-format
+msgid "Couldn't read 'max_pv' for volume group %s."
+msgstr ""
+
+#: format_text/import_vsn1.c:745
+msgid "Couldn't create hash table."
+msgstr ""
+
+#: format_text/import_vsn1.c:752
+#, c-format
+msgid "Couldn't find all physical volumes for volume group %s."
+msgstr ""
+
+#: format_text/import_vsn1.c:763
+#, c-format
+msgid "Couldn't read tags for volume group %s."
+msgstr ""
+
+#: format_text/import_vsn1.c:769
+#, c-format
+msgid "Couldn't read all logical volume names for volume group %s."
+msgstr ""
+
+#: format_text/import_vsn1.c:776
+#, c-format
+msgid "Couldn't read all logical volumes for volume group %s."
+msgstr ""
+
+#: format_text/import_vsn1.c:782
+#, c-format
+msgid "Failed to fixup mirror pointers after import for volume group %s."
+msgstr ""
+
+#: format_text/tags.c:62
+msgid "Found a tag that is not a string"
+msgstr ""
+
+#: format_text/text_label.c:98 format_text/text_label.c:103
+msgid "struct data_area_list allocation failed"
+msgstr ""
+
+#: format_text/text_label.c:138 format_text/text_label.c:149
+msgid "struct mda_list allocation failed"
+msgstr ""
+
+#: format_text/text_label.c:143 format_text/text_label.c:154
+msgid "struct mda_context allocation failed"
+msgstr ""
+
+#: label/label.c:49
+msgid "Couldn't allocate memory for labeller list object."
+msgstr ""
+
+#: label/label.c:123 label/label.c:218
+#, c-format
+msgid "%s: Failed to read label area"
+msgstr ""
+
+#: label/label.c:135 label/label.c:164
+#, c-format
+msgid "Ignoring additional label on %s at sector %lu"
+msgstr ""
+
+#: label/label.c:140
+#, c-format
+msgid "%s: Label for sector %lu found at sector %lu - ignoring"
+msgstr ""
+
+#: label/label.c:150
+#, c-format
+msgid "Label checksum incorrect on %s - ignoring"
+msgstr ""
+
+#: label/label.c:161
+#, c-format
+msgid "%s: %s label detected"
+msgstr ""
+
+#: label/label.c:185
+#, c-format
+msgid "%s: No label detected"
+msgstr ""
+
+#: label/label.c:204
+#, c-format
+msgid "Scanning for labels to wipe from %s"
+msgstr ""
+
+#: label/label.c:244
+#, c-format
+msgid "%s: Wiping label at sector %lu"
+msgstr ""
+
+#: label/label.c:248
+#, c-format
+msgid "Failed to remove label from %s at sector %lu"
+msgstr ""
+
+#: label/label.c:304
+msgid "Label handler does not support label writes"
+msgstr ""
+
+#: label/label.c:309
+#, c-format
+msgid "Label sector %lu beyond range (%ld)"
+msgstr ""
+
+#: label/label.c:333
+#, c-format
+msgid "%s: Writing label to sector %lu"
+msgstr ""
+
+#: label/label.c:336
+#, c-format
+msgid "Failed to write label to %s"
+msgstr ""
+
+#: label/label.c:386
+msgid "label allocaction failed"
+msgstr ""
+
+#: locking/cluster_locking.c:69
+#, c-format
+msgid "Local socket creation failed: %s"
+msgstr ""
+
+#: locking/cluster_locking.c:82
+#, c-format
+msgid "connect() failed on local socket: %s"
+msgstr ""
+
+#: locking/cluster_locking.c:109
+#, c-format
+msgid "Error writing data to clvmd: %s"
+msgstr ""
+
+#: locking/cluster_locking.c:118
+#, c-format
+msgid "Error reading data from clvmd: %s"
+msgstr ""
+
+#: locking/cluster_locking.c:123
+msgid "EOF reading CLVMD"
+msgstr ""
+
+#: locking/cluster_locking.c:156
+#, c-format
+msgid "cluster request failed: %s"
+msgstr ""
+
+#: locking/cluster_locking.c:346
+#, c-format
+msgid "clvmd not running on node %s"
+msgstr ""
+
+#: locking/cluster_locking.c:351
+#, c-format
+msgid "Error locking on node %s: %s"
+msgstr ""
+
+#: locking/cluster_locking.c:402 locking/file_locking.c:266
+#: locking/locking.c:265 locking/no_locking.c:71
+#, c-format
+msgid "Unrecognised lock scope: %d"
+msgstr ""
+
+#: locking/cluster_locking.c:408
+#, c-format
+msgid "Locking %s at 0x%x"
+msgstr ""
+
+#: locking/external_locking.c:64
+msgid "External locking already initialised"
+msgstr ""
+
+#: locking/external_locking.c:86
+#, c-format
+msgid "Shared library %s does not contain locking functions"
+msgstr ""
+
+#: locking/external_locking.c:93
+#, c-format
+msgid "Loaded external locking library %s"
+msgstr ""
+
+#: locking/file_locking.c:59
+#, c-format
+msgid "Unlocking %s"
+msgstr ""
+
+#: locking/file_locking.c:111
+msgid "CTRL-c detected: giving up waiting for lock"
+msgstr ""
+
+#: locking/file_locking.c:149
+#, c-format
+msgid "Unrecognised lock type: %d"
+msgstr ""
+
+#: locking/file_locking.c:163
+#, c-format
+msgid "Locking %s %c%c"
+msgstr ""
+
+#: locking/file_locking.c:237
+#, c-format
+msgid "Unlocking LV %s"
+msgstr ""
+
+#: locking/file_locking.c:242
+#, c-format
+msgid "Locking LV %s (NL)"
+msgstr ""
+
+#: locking/file_locking.c:247
+#, c-format
+msgid "Locking LV %s (R)"
+msgstr ""
+
+#: locking/file_locking.c:252
+#, c-format
+msgid "Locking LV %s (W)"
+msgstr ""
+
+#: locking/file_locking.c:257
+#, c-format
+msgid "Locking LV %s (EX)"
+msgstr ""
+
+#: locking/locking.c:133
+msgid ""
+"WARNING: Locking disabled. Be careful! This could corrupt your metadata."
+msgstr ""
+
+#: locking/locking.c:138
+msgid "File-based locking selected."
+msgstr ""
+
+#: locking/locking.c:146
+msgid "External locking selected."
+msgstr ""
+
+#: locking/locking.c:156
+msgid "Falling back to internal clustered locking."
+msgstr ""
+
+#: locking/locking.c:160
+msgid "Cluster locking selected."
+msgstr ""
+
+#: locking/locking.c:167
+msgid "Unknown locking type requested."
+msgstr ""
+
+#: locking/locking.c:174
+msgid "WARNING: Falling back to local file-based locking."
+msgstr ""
+
+#: locking/locking.c:175
+msgid "Volume Groups with the clustered attribute will be inaccessible."
+msgstr ""
+
+#: locking/locking.c:185
+msgid "Locking disabled - only read operations permitted."
+msgstr ""
+
+#: locking/locking.c:212
+#, c-format
+msgid "LVM1 proc VG pathname too long for %s"
+msgstr ""
+
+#: locking/locking.c:217
+#, c-format
+msgid "%s exists: Is the original LVM driver using this volume group?"
+msgstr ""
+
+#: locking/locking.c:302 lvresize.c:573
+#, c-format
+msgid "Failed to suspend %s"
+msgstr ""
+
+#: locking/locking.c:323
+#, c-format
+msgid "Failed to activate %s"
+msgstr ""
+
+#: log/log.c:145
+msgid "Test mode: Metadata will NOT be updated."
+msgstr ""
+
+#: lvchange.c:27
+#, c-format
+msgid "Logical volume \"%s\" is already writable"
+msgstr ""
+
+#: lvchange.c:33
+#, c-format
+msgid "Logical volume \"%s\" is already read only"
+msgstr ""
+
+#: lvchange.c:40
+#, c-format
+msgid "Cannot change permissions of mirror \"%s\" while active."
+msgstr ""
+
+#: lvchange.c:47
+#, c-format
+msgid "Setting logical volume \"%s\" read/write"
+msgstr ""
+
+#: lvchange.c:51
+#, c-format
+msgid "Setting logical volume \"%s\" read-only"
+msgstr ""
+
+#: lvchange.c:55 lvchange.c:314 lvchange.c:350 lvchange.c:393 lvchange.c:470
+#: lvchange.c:524 lvconvert.c:401
+#, c-format
+msgid "Updating logical volume \"%s\" on disk(s)"
+msgstr ""
+
+#: lvchange.c:64 lvchange.c:402 lvconvert.c:409 metadata/mirror.c:227
+#, c-format
+msgid "Failed to lock %s"
+msgstr ""
+
+#: lvchange.c:74 lvchange.c:412
+#, c-format
+msgid "Updating permissions for \"%s\" in kernel"
+msgstr ""
+
+#: lvchange.c:76 lvchange.c:414 lvconvert.c:422 lvresize.c:585
+#: metadata/mirror.c:240
+#, c-format
+msgid "Problem reactivating %s"
+msgstr ""
+
+#: lvchange.c:89
+#, c-format
+msgid "Logical volume, %s, is not active"
+msgstr ""
+
+#: lvchange.c:113
+#, c-format
+msgid "Deactivating logical volume \"%s\" locally"
+msgstr ""
+
+#: lvchange.c:120
+#, c-format
+msgid "Deactivating logical volume \"%s\""
+msgstr ""
+
+#: lvchange.c:127
+#, c-format
+msgid "Locking failed: ignoring clustered logical volume %s"
+msgstr ""
+
+#: lvchange.c:133
+#, c-format
+msgid "Activating logical volume \"%s\" exclusively"
+msgstr ""
+
+#: lvchange.c:140
+#, c-format
+msgid "Activating logical volume \"%s\" locally"
+msgstr ""
+
+#: lvchange.c:147
+#, c-format
+msgid "Activating logical volume \"%s\""
+msgstr ""
+
+#: lvchange.c:157
+#, c-format
+msgid "Spawning background pvmove process for %s"
+msgstr ""
+
+#: lvchange.c:168
+#, c-format
+msgid "Refreshing logical volume \"%s\" (if active)"
+msgstr ""
+
+#: lvchange.c:183
+#, c-format
+msgid "Unable to resync %s because it is not mirrored."
+msgstr ""
+
+#: lvchange.c:189
+#, c-format
+msgid "Unable to resync pvmove volume %s"
+msgstr ""
+
+#: lvchange.c:194
+#, c-format
+msgid "Unable to resync locked volume %s"
+msgstr ""
+
+#: lvchange.c:200
+#, c-format
+msgid "Can't resync open logical volume \"%s\""
+msgstr ""
+
+#: lvchange.c:210
+#, c-format
+msgid "Logical volume \"%s\" not resynced"
+msgstr ""
+
+#: lvchange.c:220
+#, c-format
+msgid "Can't get exclusive access to clustered volume %s"
+msgstr ""
+
+#: lvchange.c:226
+#, c-format
+msgid "Unable to deactivate %s for resync"
+msgstr ""
+
+#: lvchange.c:232
+#, c-format
+msgid "Starting resync of %s%s%s mirror \"%s\""
+msgstr ""
+
+#: lvchange.c:246
+#, c-format
+msgid "Failed to reactivate %s to resynchronize mirror"
+msgstr ""
+
+#: lvchange.c:262
+msgid "Failed to write intermediate VG metadata."
+msgstr ""
+
+#: lvchange.c:276
+msgid "Failed to commit intermediate VG metadata."
+msgstr ""
+
+#: lvchange.c:288
+#, c-format
+msgid "Unable to activate %s for mirror log resync"
+msgstr ""
+
+#: lvchange.c:293
+#, c-format
+msgid "Clearing log device %s"
+msgstr ""
+
+#: lvchange.c:295
+#, c-format
+msgid "Unable to reset sync status for %s"
+msgstr ""
+
+#: lvchange.c:297
+msgid "Failed to deactivate log LV after wiping failed"
+msgstr ""
+
+#: lvchange.c:303
+#, c-format
+msgid "Unable to deactivate log LV %s after wiping for resync"
+msgstr ""
+
+#: lvchange.c:316
+msgid "Failed to update metadata on disk."
+msgstr ""
+
+#: lvchange.c:321
+#, c-format
+msgid "Failed to reactivate %s after resync"
+msgstr ""
+
+#: lvchange.c:338
+#, c-format
+msgid "Allocation policy of logical volume \"%s\" is already %s"
+msgstr ""
+
+#: lvchange.c:347
+#, c-format
+msgid "Setting contiguous allocation policy for \"%s\" to %s"
+msgstr ""
+
+#: lvchange.c:383
+#, c-format
+msgid "Read ahead is already %u for \"%s\""
+msgstr ""
+
+#: lvchange.c:390
+#, c-format
+msgid "Setting read ahead to %u for \"%s\""
+msgstr ""
+
+#: lvchange.c:429
+#, c-format
+msgid "Minor number is already not persistent for \"%s\""
+msgstr ""
+
+#: lvchange.c:436
+#, c-format
+msgid "Disabling persistent device number for \"%s\""
+msgstr ""
+
+#: lvchange.c:440
+msgid "Minor number must be specified with -My"
+msgstr ""
+
+#: lvchange.c:444
+msgid "Major number must be specified with -My"
+msgstr ""
+
+#: lvchange.c:453
+#, c-format
+msgid "%s device number not changed."
+msgstr ""
+
+#: lvchange.c:457
+#, c-format
+msgid "Ensuring %s is inactive."
+msgstr ""
+
+#: lvchange.c:459
+#, c-format
+msgid "%s: deactivation failed"
+msgstr ""
+
+#: lvchange.c:465
+#, c-format
+msgid "Setting persistent device number to (%d, %d) for \"%s\""
+msgstr ""
+
+#: lvchange.c:484
+#, c-format
+msgid "Re-activating logical volume \"%s\""
+msgstr ""
+
+#: lvchange.c:486
+#, c-format
+msgid "%s: reactivation failed"
+msgstr ""
+
+#: lvchange.c:500 lvcreate.c:680 pvchange.c:49 vgchange.c:440 vgcreate.c:107
+msgid "Failed to get tag"
+msgstr ""
+
+#: lvchange.c:505
+#, c-format
+msgid "Logical volume %s/%s does not support tags"
+msgstr ""
+
+#: lvchange.c:512 lvcreate.c:746
+#, c-format
+msgid "Failed to add tag %s to %s/%s"
+msgstr ""
+
+#: lvchange.c:518
+#, c-format
+msgid "Failed to remove tag %s from %s/%s"
+msgstr ""
+
+#: lvchange.c:551
+#, c-format
+msgid "Only -a permitted with read-only volume group \"%s\""
+msgstr ""
+
+#: lvchange.c:560
+#, c-format
+msgid "Can't change logical volume \"%s\" under snapshot"
+msgstr ""
+
+#: lvchange.c:566
+#, c-format
+msgid "Can't change snapshot logical volume \"%s\""
+msgstr ""
+
+#: lvchange.c:572
+#, c-format
+msgid "Unable to change pvmove LV %s"
+msgstr ""
+
+#: lvchange.c:574
+msgid "Use 'pvmove --abort' to abandon a pvmove"
+msgstr ""
+
+#: lvchange.c:579
+#, c-format
+msgid "Unable to change mirror log LV %s directly"
+msgstr ""
+
+#: lvchange.c:584
+#, c-format
+msgid "Unable to change mirror image LV %s directly"
+msgstr ""
+
+#: lvchange.c:590
+#, c-format
+msgid "Unable to change internal LV %s directly"
+msgstr ""
+
+#: lvchange.c:648
+#, c-format
+msgid "Logical volume \"%s\" changed"
+msgstr ""
+
+#: lvchange.c:683
+msgid ""
+"Need 1 or more of -a, -C, -j, -m, -M, -p, -r, --resync, --refresh, --alloc, "
+"--addtag, --deltag or --monitor"
+msgstr ""
+
+#: lvchange.c:694
+msgid "Only -a permitted with --ignorelockingfailure"
+msgstr ""
+
+#: lvchange.c:699
+msgid "Please give logical volume path(s)"
+msgstr ""
+
+#: lvchange.c:705
+msgid "--major and --minor require -My"
+msgstr ""
+
+#: lvchange.c:710
+msgid "Only give one logical volume when specifying minor"
+msgstr ""
+
+#: lvchange.c:715
+msgid "Only one of --alloc and --contiguous permitted"
+msgstr ""
+
+#: lvconvert.c:50 lvcreate.c:69
+msgid "Please specify a logical volume to act as the snapshot origin."
+msgstr ""
+
+#: lvconvert.c:58 lvcreate.c:77
+msgid "The origin name should include the volume group."
+msgstr ""
+
+#: lvconvert.c:69
+msgid "Please provide logical volume path"
+msgstr ""
+
+#: lvconvert.c:79 lvrename.c:38
+#, c-format
+msgid "Please use a single volume group name (\"%s\" or \"%s\")"
+msgstr ""
+
+#: lvconvert.c:88 lvrename.c:52
+msgid "Please provide a valid volume group name"
+msgstr ""
+
+#: lvconvert.c:110
+msgid "Exactly one of --mirrors or --snapshot arguments required."
+msgstr ""
+
+#: lvconvert.c:129
+msgid "--regionsize is only available with mirrors"
+msgstr ""
+
+#: lvconvert.c:134 lvcreate.c:336
+msgid "Negative chunk size is invalid"
+msgstr ""
+
+#: lvconvert.c:140 lvcreate.c:342
+msgid "Chunk size must be a power of 2 in the range 4K to 512K"
+msgstr ""
+
+#: lvconvert.c:144 lvcreate.c:346
+#, c-format
+msgid "Setting chunksize to %d sectors."
+msgstr ""
+
+#: lvconvert.c:156
+msgid "--chunksize is only available with snapshots"
+msgstr ""
+
+#: lvconvert.c:162
+msgid "--zero is only available with snapshots"
+msgstr ""
+
+#: lvconvert.c:174 lvcreate.c:253
+msgid "Negative regionsize is invalid"
+msgstr ""
+
+#: lvconvert.c:184 lvcreate.c:262
+msgid "Negative regionsize in configuration file is invalid"
+msgstr ""
+
+#: lvconvert.c:192 lvcreate.c:276
+#, c-format
+msgid "Region size (%u) must be a multiple of machine memory page size (%d)"
+msgstr ""
+
+#: lvconvert.c:200 lvcreate.c:270
+#, c-format
+msgid "Region size (%u) must be a power of 2"
+msgstr ""
+
+#: lvconvert.c:206 lvcreate.c:283
+msgid "Non-zero region size must be supplied."
+msgstr ""
+
+#: lvconvert.c:216 lvcreate.c:390 metadata/mirror.c:566
+#, c-format
+msgid "%s: Required device-mapper target(s) not detected in your kernel"
+msgstr ""
+
+#: lvconvert.c:249
+#, c-format
+msgid "Logical volume %s only has %u mirrors."
+msgstr ""
+
+#: lvconvert.c:259
+msgid "Mirror log region size cannot be changed on an existing mirror."
+msgstr ""
+
+#: lvconvert.c:266
+#, c-format
+msgid "Logical volume %s is already not mirrored."
+msgstr ""
+
+#: lvconvert.c:277
+#, c-format
+msgid "Logical volume %s has multiple mirror segments."
+msgstr ""
+
+#: lvconvert.c:287 lvconvert.c:320
+msgid "Unable to determine mirror sync status."
+msgstr ""
+
+#: lvconvert.c:311 lvconvert.c:389 lvcreate.c:721
+msgid "Failed to create mirror log."
+msgstr ""
+
+#: lvconvert.c:335
+#, c-format
+msgid "Logical volume %s already has %u mirror(s)."
+msgstr ""
+
+#: lvconvert.c:346
+msgid "Adding mirror images is not supported yet."
+msgstr ""
+
+#: lvconvert.c:363
+msgid "Mirrors of striped volumes are not yet supported."
+msgstr ""
+
+#: lvconvert.c:419 metadata/mirror.c:237
+#, c-format
+msgid "Updating \"%s\" in kernel"
+msgstr ""
+
+#: lvconvert.c:426
+#, c-format
+msgid "Logical volume %s converted."
+msgstr ""
+
+#: lvconvert.c:438 lvcreate.c:608
+#, c-format
+msgid "Couldn't find origin volume '%s'."
+msgstr ""
+
+#: lvconvert.c:443
+#, c-format
+msgid "Unable to create a snapshot of a %s LV."
+msgstr ""
+
+#: lvconvert.c:450 lvcreate.c:799
+#, c-format
+msgid "WARNING: \"%s\" not zeroed"
+msgstr ""
+
+#: lvconvert.c:452
+msgid "Aborting. Failed to wipe snapshot exception store."
+msgstr ""
+
+#: lvconvert.c:458
+#, c-format
+msgid "Couldn't deactivate LV %s."
+msgstr ""
+
+#: lvconvert.c:464 lvcreate.c:812
+msgid "Couldn't create snapshot."
+msgstr ""
+
+#: lvconvert.c:475 lvcreate.c:821
+#, c-format
+msgid "Failed to suspend origin %s"
+msgstr ""
+
+#: lvconvert.c:484 lvcreate.c:830
+#, c-format
+msgid "Problem reactivating origin %s"
+msgstr ""
+
+#: lvconvert.c:488
+#, c-format
+msgid "Logical volume %s converted to snapshot."
+msgstr ""
+
+#: lvconvert.c:499
+#, c-format
+msgid "Cannot convert locked LV %s"
+msgstr ""
+
+#: lvconvert.c:504
+#, c-format
+msgid "Can't convert logical volume \"%s\" under snapshot"
+msgstr ""
+
+#: lvconvert.c:510
+#, c-format
+msgid "Can't convert snapshot logical volume \"%s\""
+msgstr ""
+
+#: lvconvert.c:516
+#, c-format
+msgid "Unable to convert pvmove LV %s"
+msgstr ""
+
+#: lvconvert.c:548 lvrename.c:100 vgrename.c:62
+#, c-format
+msgid "Checking for existing volume group \"%s\""
+msgstr ""
+
+#: lvconvert.c:551 lvcreate.c:863 lvrename.c:103 lvresize.c:613 pvchange.c:59
+#: pvmove.c:59 pvresize.c:69 vgcreate.c:140 vgextend.c:53 vgmerge.c:34
+#: vgmerge.c:65 vgreduce.c:476 vgrename.c:94 vgrename.c:133 vgsplit.c:240
+#: vgsplit.c:277
+#, c-format
+msgid "Can't get lock for %s"
+msgstr ""
+
+#: lvconvert.c:556 lvcreate.c:492 lvrename.c:108 pvmove.c:64 vgdisplay.c:24
+#: vgmerge.c:39 vgmerge.c:72 vgreduce.c:482 vgsplit.c:245
+#, c-format
+msgid "Volume group \"%s\" doesn't exist"
+msgstr ""
+
+#: lvconvert.c:562 lvcreate.c:498 lvrename.c:114 lvresize.c:146 pvchange.c:72
+#: pvdisplay.c:41 pvmove.c:71 pvresize.c:83 reporter.c:76 reporter.c:124
+#: toollib.c:363 toollib.c:383 toollib.c:490 toollib.c:741 vgextend.c:64
+#: vgmerge.c:46 vgmerge.c:78 vgreduce.c:489 vgreduce.c:511 vgrename.c:107
+#: vgsplit.c:252
+#, c-format
+msgid "Skipping clustered volume group %s"
+msgstr ""
+
+#: lvconvert.c:567 lvcreate.c:503 lvrename.c:119 metadata/metadata.c:1377
+#: polldaemon.c:195 pvchange.c:78 pvmove.c:76 pvresize.c:89 toollib.c:163
+#: vgchange.c:534 vgck.c:34 vgconvert.c:54 vgextend.c:69 vgmerge.c:52
+#: vgmerge.c:83 vgreduce.c:541 vgremove.c:35 vgrename.c:113 vgsplit.c:258
+#, c-format
+msgid "Volume group \"%s\" is exported"
+msgstr ""
+
+#: lvconvert.c:572 lvcreate.c:508 lvremove.c:28 lvrename.c:124 pvchange.c:84
+#: pvmove.c:82 pvresize.c:95 vgchange.c:529 vgconvert.c:49 vgexport.c:42
+#: vgextend.c:74 vgmerge.c:58 vgmerge.c:88 vgreduce.c:547 vgrename.c:117
+#: vgsplit.c:270
+#, c-format
+msgid "Volume group \"%s\" is read-only"
+msgstr ""
+
+#: lvconvert.c:577
+#, c-format
+msgid "Logical volume \"%s\" not found in volume group \"%s\""
+msgstr ""
+
+#: lvcreate.c:93 lvresize.c:105
+msgid "Please provide a volume group name"
+msgstr ""
+
+#: lvcreate.c:100
+msgid "Volume group name expected (no slash)"
+msgstr ""
+
+#: lvcreate.c:115
+#, c-format
+msgid "Inconsistent volume group names given: \"%s\" and \"%s\""
+msgstr ""
+
+#: lvcreate.c:138
+#, c-format
+msgid "Logical volume name \"%s\" is invalid"
+msgstr ""
+
+#: lvcreate.c:151 lvresize.c:65
+msgid "Please specify either size or extents (not both)"
+msgstr ""
+
+#: lvcreate.c:157
+msgid "Negative number of extents is invalid"
+msgstr ""
+
+#: lvcreate.c:167
+msgid "Negative size is invalid"
+msgstr ""
+
+#: lvcreate.c:189
+msgid "Negative stripesize is invalid"
+msgstr ""
+
+#: lvcreate.c:194 lvresize.c:192
+#, c-format
+msgid "Stripe size cannot be larger than %s"
+msgstr ""
+
+#: lvcreate.c:202
+msgid "Ignoring stripesize argument with single stripe"
+msgstr ""
+
+#: lvcreate.c:210 lvresize.c:330
+#, c-format
+msgid "Using default stripesize %s"
+msgstr ""
+
+#: lvcreate.c:215
+#, c-format
+msgid "Too few physical volumes on command line for %d-way striping"
+msgstr ""
+
+#: lvcreate.c:221
+#, c-format
+msgid "Number of stripes (%d) must be between %d and %d"
+msgstr ""
+
+#: lvcreate.c:229 lvresize.c:407
+#, c-format
+msgid "Invalid stripe size %s"
+msgstr ""
+
+#: lvcreate.c:246
+#, c-format
+msgid "Too few physical volumes on command line for %d-way mirroring"
+msgstr ""
+
+#: lvcreate.c:309
+msgid "Redundant stripes argument: default is 1"
+msgstr ""
+
+#: lvcreate.c:323
+msgid "Redundant mirrors argument: default is 0"
+msgstr ""
+
+#: lvcreate.c:325 lvresize.c:180
+msgid "Mirrors argument may not be negative"
+msgstr ""
+
+#: lvcreate.c:332
+msgid "-Z is incompatible with snapshots"
+msgstr ""
+
+#: lvcreate.c:354
+msgid "-c is only available with snapshots"
+msgstr ""
+
+#: lvcreate.c:361
+msgid "mirrors and snapshots are currently incompatible"
+msgstr ""
+
+#: lvcreate.c:367
+msgid "mirrors and stripes are currently incompatible"
+msgstr ""
+
+#: lvcreate.c:378
+msgid "--corelog is only available with mirrors"
+msgstr ""
+
+#: lvcreate.c:383
+msgid "--nosync is only available with mirrors"
+msgstr ""
+
+#: lvcreate.c:419
+msgid "Conflicting contiguous and alloc arguments"
+msgstr ""
+
+#: lvcreate.c:448
+msgid "Please specify minor number with --minor when using -My"
+msgstr ""
+
+#: lvcreate.c:453
+msgid "Please specify major number with --major when using -My"
+msgstr ""
+
+#: lvcreate.c:459
+msgid "--major and --minor incompatible with -Mn"
+msgstr ""
+
+#: lvcreate.c:489 pvmove.c:305 toollib.c:481 vgreduce.c:474
+#, c-format
+msgid "Finding volume group \"%s\""
+msgstr ""
+
+#: lvcreate.c:513 lvrename.c:129
+#, c-format
+msgid "Logical volume \"%s\" already exists in volume group \"%s\""
+msgstr ""
+
+#: lvcreate.c:519
+msgid "Metadata does not support mirroring."
+msgstr ""
+
+#: lvcreate.c:536
+#, c-format
+msgid "Reducing requested stripe size %s to maximum, physical extent size %s"
+msgstr ""
+
+#: lvcreate.c:547
+#, c-format
+msgid "Stripe size may not exceed %s"
+msgstr ""
+
+#: lvcreate.c:559 lvresize.c:237
+#, c-format
+msgid "Rounding up size to full physical extent %s"
+msgstr ""
+
+#: lvcreate.c:564
+#, c-format
+msgid "Volume too large (%s) for extent size %s. Upper limit is %s."
+msgstr ""
+
+#: lvcreate.c:583
+#, c-format
+msgid "Please express size as %%VG or %%FREE."
+msgstr ""
+
+#: lvcreate.c:590
+#, c-format
+msgid "Rounding size (%d extents) up to stripe boundary size (%d extents)"
+msgstr ""
+
+#: lvcreate.c:598
+msgid "Can't create snapshot without using device-mapper kernel driver"
+msgstr ""
+
+#: lvcreate.c:604
+msgid "Clustered snapshots are not yet supported."
+msgstr ""
+
+#: lvcreate.c:613
+msgid "Snapshots of snapshots are not supported yet."
+msgstr ""
+
+#: lvcreate.c:618
+msgid "Snapshots of locked devices are not supported yet"
+msgstr ""
+
+#: lvcreate.c:625
+msgid "Snapshots and mirrors may not yet be mixed."
+msgstr ""
+
+#: lvcreate.c:634
+msgid "Unable to create new logical volume with no extents"
+msgstr ""
+
+#: lvcreate.c:640
+#, c-format
+msgid "Insufficient free extents (%u) in volume group %s: %u required"
+msgstr ""
+
+#: lvcreate.c:646
+#, c-format
+msgid "Number of stripes (%u) must not exceed number of physical volumes (%d)"
+msgstr ""
+
+#: lvcreate.c:653
+msgid "Can't create mirror without using device-mapper kernel driver."
+msgstr ""
+
+#: lvcreate.c:672
+msgid "Failed to generate LV name."
+msgstr ""
+
+#: lvcreate.c:685 vgchange.c:445
+#, c-format
+msgid "Volume group %s does not support tags"
+msgstr ""
+
+#: lvcreate.c:709
+msgid ""
+"WARNING: New mirror won't be synchronised. Don't read what you didn't write!"
+msgstr ""
+
+#: lvcreate.c:733
+msgid "Setting read ahead sectors"
+msgstr ""
+
+#: lvcreate.c:741
+#, c-format
+msgid "Setting device number to (%d, %d)"
+msgstr ""
+
+#: lvcreate.c:782
+msgid ""
+"Aborting. Failed to activate snapshot exception store. Remove new LV and "
+"retry."
+msgstr ""
+
+#: lvcreate.c:787
+msgid "Failed to activate new LV."
+msgstr ""
+
+#: lvcreate.c:794
+msgid ""
+"Aborting. Failed to wipe snapshot exception store. Remove new LV and retry."
+msgstr ""
+
+#: lvcreate.c:837
+#, c-format
+msgid "Logical volume \"%s\" created"
+msgstr ""
+
+#: lvdisplay.c:39 lvdisplay.c:48 pvdisplay.c:89 pvdisplay.c:99 vgdisplay.c:67
+#: vgdisplay.c:76
+msgid "Incompatible options selected"
+msgstr ""
+
+#: lvdisplay.c:53
+msgid "Options -v and -c are incompatible"
+msgstr ""
+
+#: lvmchange.c:21
+msgid "With LVM2 and the device mapper, this program is obsolete."
+msgstr ""
+
+#: lvmcmdline.c:289
+msgid "Minor number outside range 0-255"
+msgstr ""
+
+#: lvmcmdline.c:304
+msgid "Major number outside range 0-255"
+msgstr ""
+
+#: lvmcmdline.c:402
+msgid "Couldn't allocate memory."
+msgstr ""
+
+#: lvmcmdline.c:451
+msgid "Out of memory."
+msgstr ""
+
+#: lvmcmdline.c:504
+#, c-format
+msgid ""
+"%s: %s\n"
+"\n"
+"%s"
+msgstr ""
+
+#: lvmcmdline.c:598
+msgid "Unrecognised option."
+msgstr ""
+
+#: lvmcmdline.c:604
+#, c-format
+msgid "Option%s%c%s%s may not be repeated"
+msgstr ""
+
+#: lvmcmdline.c:613
+msgid "Option requires argument."
+msgstr ""
+
+#: lvmcmdline.c:620
+#, c-format
+msgid "Invalid argument %s"
+msgstr ""
+
+#: lvmcmdline.c:639
+#, c-format
+msgid "%s and %s are synonyms.  Please only supply one."
+msgstr ""
+
+#: lvmcmdline.c:667
+#, c-format
+msgid "LVM version:     %s"
+msgstr ""
+
+#: lvmcmdline.c:669
+#, c-format
+msgid "Library version: %s"
+msgstr ""
+
+#: lvmcmdline.c:671
+#, c-format
+msgid "Driver version:  %s"
+msgstr ""
+
+#: lvmcmdline.c:706
+msgid "Partial mode. Incomplete volume groups will be activated read-only."
+msgstr ""
+
+#: lvmcmdline.c:729
+msgid "--trustcache is incompatible with --all"
+msgstr ""
+
+#: lvmcmdline.c:733
+msgid ""
+"WARNING: Cache file of PVs will be trusted.  New devices holding PVs may get "
+"ignored."
+msgstr ""
+
+#: lvmcmdline.c:767
+msgid "Available lvm commands:"
+msgstr ""
+
+#: lvmcmdline.c:768
+msgid "Use 'lvm help <command>' for more information"
+msgstr ""
+
+#: lvmcmdline.c:774
+#, c-format
+msgid "%-16.16s%s"
+msgstr ""
+
+#: lvmcmdline.c:794
+msgid "Failed to set overridden configuration entries."
+msgstr ""
+
+#: lvmcmdline.c:858
+msgid "Couldn't copy command line."
+msgstr ""
+
+#: lvmcmdline.c:871
+#, c-format
+msgid "Parsing: %s"
+msgstr ""
+
+#: lvmcmdline.c:877
+msgid "Error during parsing of command line."
+msgstr ""
+
+#: lvmcmdline.c:890
+msgid "Updated config file invalid. Aborting."
+msgstr ""
+
+#: lvmcmdline.c:899
+#, c-format
+msgid "Processing: %s"
+msgstr ""
+
+#: lvmcmdline.c:902
+msgid "O_DIRECT will be used"
+msgstr ""
+
+#: lvmcmdline.c:915
+#, c-format
+msgid "Locking type %d initialisation failed."
+msgstr ""
+
+#: lvmcmdline.c:927
+msgid "Test mode: Wiping internal cache"
+msgstr ""
+
+#: lvmcmdline.c:951
+#, c-format
+msgid "Completed: %s"
+msgstr ""
+
+#: lvmcmdline.c:1073
+#, c-format
+msgid "Line too long (max 255) beginning: %s"
+msgstr ""
+
+#: lvmcmdline.c:1080
+#, c-format
+msgid "Too many arguments: %s"
+msgstr ""
+
+#: lvmcmdline.c:1125
+msgid "Failed to create LVM1 tool pathname"
+msgstr ""
+
+#: lvmcmdline.c:1173
+msgid "Falling back to LVM1 tools, but no command specified."
+msgstr ""
+
+#: lvmcmdline.c:1189
+msgid "Please supply an LVM command."
+msgstr ""
+
+#: lvmcmdline.c:1203
+msgid "No such command.  Try 'help'."
+msgstr ""
+
+#: lvmdiskscan.c:38 lvmdiskscan.c:108
+msgid "dev_iter_create failed"
+msgstr ""
+
+#: lvmdiskscan.c:66
+#, c-format
+msgid "%-*s [%15s] %s"
+msgstr ""
+
+#: lvmdiskscan.c:83 lvmdiskscan.c:117
+#, c-format
+msgid "Couldn't get size of \"%s\""
+msgstr ""
+
+#: lvmdiskscan.c:88
+#, c-format
+msgid "dev_close on \"%s\" failed"
+msgstr ""
+
+#: lvmdiskscan.c:103
+msgid "WARNING: only considering LVM devices"
+msgstr ""
+
+#: lvmdiskscan.c:137
+#, c-format
+msgid "%d disk%s"
+msgstr ""
+
+#: lvmdiskscan.c:139
+#, c-format
+msgid "%d partition%s"
+msgstr ""
+
+#: lvmdiskscan.c:142
+#, c-format
+msgid "%d LVM physical volume whole disk%s"
+msgstr ""
+
+#: lvmdiskscan.c:144
+#, c-format
+msgid "%d LVM physical volume%s"
+msgstr ""
+
+#: lvremove.c:33
+#, c-format
+msgid "Can't remove logical volume \"%s\" under snapshot"
+msgstr ""
+
+#: lvremove.c:39
+#, c-format
+msgid "Can't remove logical volume %s used by a mirror"
+msgstr ""
+
+#: lvremove.c:45
+#, c-format
+msgid "Can't remove logical volume %s used as mirror log"
+msgstr ""
+
+#: lvremove.c:51
+#, c-format
+msgid "Can't remove locked LV %s"
+msgstr ""
+
+#: lvremove.c:59
+#, c-format
+msgid "Can't remove open logical volume \"%s\""
+msgstr ""
+
+#: lvremove.c:68
+#, c-format
+msgid "Logical volume \"%s\" not removed"
+msgstr ""
+
+#: lvremove.c:82
+#, c-format
+msgid "Can't get exclusive access to volume \"%s\""
+msgstr ""
+
+#: lvremove.c:90
+#, c-format
+msgid "Unable to deactivate logical volume \"%s\""
+msgstr ""
+
+#: lvremove.c:97
+#, c-format
+msgid "Removing snapshot %s"
+msgstr ""
+
+#: lvremove.c:104
+#, c-format
+msgid "Releasing logical volume \"%s\""
+msgstr ""
+
+#: lvremove.c:106
+#, c-format
+msgid "Error releasing logical volume \"%s\""
+msgstr ""
+
+#: lvremove.c:122
+#, c-format
+msgid "Failed to refresh %s without snapshot."
+msgstr ""
+
+#: lvremove.c:124
+#, c-format
+msgid "Failed to resume %s."
+msgstr ""
+
+#: lvremove.c:127
+#, c-format
+msgid "Logical volume \"%s\" successfully removed"
+msgstr ""
+
+#: lvremove.c:134
+msgid "Please enter one or more logical volume paths"
+msgstr ""
+
+#: lvrename.c:47
+msgid "Old and new logical volume names required"
+msgstr ""
+
+#: lvrename.c:59
+#, c-format
+msgid "Logical volume names must have the same volume group (\"%s\" or \"%s\")"
+msgstr ""
+
+#: lvrename.c:74
+#, c-format
+msgid "New logical volume path exceeds maximum length of %zu!"
+msgstr ""
+
+#: lvrename.c:80
+msgid "New logical volume name may not be blank"
+msgstr ""
+
+#: lvrename.c:90
+#, c-format
+msgid "New logical volume name \"%s\" is invalid"
+msgstr ""
+
+#: lvrename.c:96
+msgid "Old and new logical volume names must differ"
+msgstr ""
+
+#: lvrename.c:135
+#, c-format
+msgid "Existing logical volume \"%s\" not found in volume group \"%s\""
+msgstr ""
+
+#: lvrename.c:143
+#, c-format
+msgid "Cannot rename locked LV %s"
+msgstr ""
+
+#: lvrename.c:150 lvrename.c:158
+#, c-format
+msgid "Mirrored LV, \"%s\" cannot be renamed: %s"
+msgstr ""
+
+#: lvrename.c:169
+msgid "Failed to allocate space for new name"
+msgstr ""
+
+#: lvrename.c:173 vgmerge.c:223 vgrename.c:165
+msgid "Writing out updated volume group"
+msgstr ""
+
+#: lvrename.c:197
+#, c-format
+msgid "Renamed \"%s\" to \"%s\" in volume group \"%s\""
+msgstr ""
+
+#: lvresize.c:83
+msgid "Negative argument not permitted - use lvreduce"
+msgstr ""
+
+#: lvresize.c:88
+msgid "Positive sign not permitted - use lvextend"
+msgstr ""
+
+#: lvresize.c:96
+msgid "Please provide the logical volume name"
+msgstr ""
+
+#: lvresize.c:140
+#, c-format
+msgid "Volume group %s doesn't exist"
+msgstr ""
+
+#: lvresize.c:151
+#, c-format
+msgid "Volume group %s is exported"
+msgstr ""
+
+#: lvresize.c:156
+#, c-format
+msgid "Volume group %s is read-only"
+msgstr ""
+
+#: lvresize.c:162
+#, c-format
+msgid "Logical volume %s not found in volume group %s"
+msgstr ""
+
+#: lvresize.c:171
+msgid "Varied striping not supported. Ignoring."
+msgstr ""
+
+#: lvresize.c:178
+msgid "Mirrors not supported. Ignoring."
+msgstr ""
+
+#: lvresize.c:187
+msgid "Stripesize may not be negative."
+msgstr ""
+
+#: lvresize.c:198
+msgid "Varied stripesize not supported. Ignoring."
+msgstr ""
+
+#: lvresize.c:200
+#, c-format
+msgid "Reducing stripe size %s to maximum, physical extent size %s"
+msgstr ""
+
+#: lvresize.c:211
+msgid "Mirrors and striping cannot be combined yet."
+msgstr ""
+
+#: lvresize.c:215
+msgid "Stripe size must be power of 2"
+msgstr ""
+
+#: lvresize.c:223
+#, c-format
+msgid "Can't resize locked LV %s"
+msgstr ""
+
+#: lvresize.c:263
+#, c-format
+msgid "Unable to reduce %s below 1 extent"
+msgstr ""
+
+#: lvresize.c:272
+msgid "New size of 0 not permitted"
+msgstr ""
+
+#: lvresize.c:277 lvresize.c:414
+#, c-format
+msgid "New size (%d extents) matches existing size (%d extents)"
+msgstr ""
+
+#: lvresize.c:291
+#, c-format
+msgid "VolumeType does not match (%s)"
+msgstr ""
+
+#: lvresize.c:308
+msgid "Please specify number of stripes (-i) and stripesize (-I)"
+msgstr ""
+
+#: lvresize.c:322
+#, c-format
+msgid "Using stripesize of last segment %s"
+msgstr ""
+
+#: lvresize.c:346
+#, c-format
+msgid "Extending %u mirror images."
+msgstr ""
+
+#: lvresize.c:352
+msgid "Cannot vary number of mirrors in LV yet."
+msgstr ""
+
+#: lvresize.c:362
+msgid "Ignoring stripes, stripesize and mirrors arguments when reducing"
+msgstr ""
+
+#: lvresize.c:391
+msgid "Stripesize for striped segment should not be 0!"
+msgstr ""
+
+#: lvresize.c:400
+#, c-format
+msgid ""
+"Rounding size (%d extents) down to stripe boundary size for segment (%d "
+"extents)"
+msgstr ""
+
+#: lvresize.c:421
+#, c-format
+msgid "New size given (%d extents) not larger than existing size (%d extents)"
+msgstr ""
+
+#: lvresize.c:431
+#, c-format
+msgid "New size given (%d extents) not less than existing size (%d extents)"
+msgstr ""
+
+#: lvresize.c:441
+msgid "Mirrors cannot be resized while active yet."
+msgstr ""
+
+#: lvresize.c:447
+msgid "Snapshot origin volumes cannot be reduced in size yet."
+msgstr ""
+
+#: lvresize.c:455
+msgid ""
+"Snapshot origin volumes can be resized only while inactive: try lvchange -an"
+msgstr ""
+
+#: lvresize.c:463
+msgid "Ignoring PVs on command line when reducing"
+msgstr ""
+
+#: lvresize.c:474
+msgid "lv_info failed: aborting"
+msgstr ""
+
+#: lvresize.c:479
+#, c-format
+msgid "Logical volume %s must be activated before resizing filesystem"
+msgstr ""
+
+#: lvresize.c:485
+#, c-format
+msgid "WARNING: Reducing active%s logical volume to %s"
+msgstr ""
+
+#: lvresize.c:490
+msgid "THIS MAY DESTROY YOUR DATA (filesystem etc.)"
+msgstr ""
+
+#: lvresize.c:497
+#, c-format
+msgid "Logical volume %s NOT reduced"
+msgstr ""
+
+#: lvresize.c:508
+#, c-format
+msgid "Couldn't create LV path for %s"
+msgstr ""
+
+#: lvresize.c:516
+msgid "Couldn't generate new LV size string"
+msgstr ""
+
+#: lvresize.c:540
+#, c-format
+msgid "%sing logical volume %s to %s"
+msgstr ""
+
+#: lvresize.c:589
+#, c-format
+msgid "Logical volume %s successfully resized"
+msgstr ""
+
+#: lvresize.c:611
+#, c-format
+msgid "Finding volume group %s"
+msgstr ""
+
+#: lvscan.c:64
+#, c-format
+msgid "%s%s '%s%s/%s' [%s] %s"
+msgstr ""
+
+#: lvscan.c:79
+msgid "No additional command line arguments allowed"
+msgstr ""
+
+#: metadata/lv_manip.c:96
+msgid "alloc_lv_segment: Missing segtype."
+msgstr ""
+
+#: metadata/lv_manip.c:131
+msgid "Failed to find snapshot segtype"
+msgstr ""
+
+#: metadata/lv_manip.c:139
+msgid "Couldn't allocate new snapshot segment."
+msgstr ""
+
+#: metadata/lv_manip.c:280
+#, c-format
+msgid "Segment extent reduction %unot divisible by #stripes %u"
+msgstr ""
+
+#: metadata/lv_manip.c:445
+msgid "Striped mirrors are not supported yet"
+msgstr ""
+
+#: metadata/lv_manip.c:450
+msgid "Can't mix striping or mirroring with creation of a mirrored PV yet"
+msgstr ""
+
+#: metadata/lv_manip.c:456
+msgid "Can't mix striping or pvmove with a mirror log yet."
+msgstr ""
+
+#: metadata/lv_manip.c:471
+msgid "allocation handle allocation failed"
+msgstr ""
+
+#: metadata/lv_manip.c:481
+msgid "allocation pool creation failed"
+msgstr ""
+
+#: metadata/lv_manip.c:516 report/report.c:92 report/report.c:152
+msgid "dm_pool_begin_object failed"
+msgstr ""
+
+#: metadata/lv_manip.c:523 metadata/lv_manip.c:528 metadata/lv_manip.c:535
+#: report/report.c:112 report/report.c:123 report/report.c:129
+#: report/report.c:135 report/report.c:159 report/report.c:165
+msgid "dm_pool_grow_object failed"
+msgstr ""
+
+#: metadata/lv_manip.c:541
+#, c-format
+msgid "Parallel PVs at LE %u length %u: %s"
+msgstr ""
+
+#: metadata/lv_manip.c:574
+msgid "Couldn't allocate new LV segment."
+msgstr ""
+
+#: metadata/lv_manip.c:654
+msgid "alloced_area allocation failed"
+msgstr ""
+
+#: metadata/lv_manip.c:705
+#, c-format
+msgid "Failed to find segment for %s extent %u"
+msgstr ""
+
+#: metadata/lv_manip.c:907
+#, c-format
+msgid "Insufficient free space: %u extents needed, but only %u available"
+msgstr ""
+
+#: metadata/lv_manip.c:1081
+msgid "_allocate called with no work to do!"
+msgstr ""
+
+#: metadata/lv_manip.c:1105
+msgid "Not enough PVs with free space available for parallel allocation."
+msgstr ""
+
+#: metadata/lv_manip.c:1107
+msgid "Consider --alloc anywhere if desperate."
+msgstr ""
+
+#: metadata/lv_manip.c:1120
+msgid "Couldn't allocate areas array."
+msgstr ""
+
+#: metadata/lv_manip.c:1137
+#, c-format
+msgid ""
+"Insufficient suitable %sallocatable extents for logical volume %s: %u more "
+"required"
+msgstr ""
+
+#: metadata/lv_manip.c:1147
+#, c-format
+msgid "Insufficient extents for log allocation for logical volume %s."
+msgstr ""
+
+#: metadata/lv_manip.c:1168
+msgid "Couldn't allocate new zero segment."
+msgstr ""
+
+#: metadata/lv_manip.c:1201
+msgid "allocate_extents does not handle virtual segments"
+msgstr ""
+
+#: metadata/lv_manip.c:1207
+#, c-format
+msgid "Metadata format (%s) does not support required LV segment type (%s)."
+msgstr ""
+
+#: metadata/lv_manip.c:1210
+msgid "Consider changing the metadata format by running vgconvert."
+msgstr ""
+
+#: metadata/lv_manip.c:1251
+msgid "Missing segtype in lv_add_segment()."
+msgstr ""
+
+#: metadata/lv_manip.c:1256
+msgid "lv_add_segment cannot handle virtual segments"
+msgstr ""
+
+#: metadata/lv_manip.c:1270
+msgid "Couldn't merge segments after extending logical volume."
+msgstr ""
+
+#: metadata/lv_manip.c:1292
+msgid "Log segments can only be added to an empty LV"
+msgstr ""
+
+#: metadata/lv_manip.c:1301
+msgid "Couldn't allocate new mirror log segment."
+msgstr ""
+
+#: metadata/lv_manip.c:1339
+#, c-format
+msgid "Log LV %s is empty."
+msgstr ""
+
+#: metadata/lv_manip.c:1349
+msgid "Couldn't allocate new mirror segment."
+msgstr ""
+
+#: metadata/lv_manip.c:1384
+msgid "Mirrored LV must only have one segment."
+msgstr ""
+
+#: metadata/lv_manip.c:1394
+#, c-format
+msgid "Failed to allocate widened LV segment for %s."
+msgstr ""
+
+#: metadata/lv_manip.c:1446
+#, c-format
+msgid "Aborting. Failed to extend %s."
+msgstr ""
+
+#: metadata/lv_manip.c:1499
+#, c-format
+msgid "Maximum number of logical volumes (%u) reached in volume group %s"
+msgstr ""
+
+#: metadata/lv_manip.c:1506
+msgid "Failed to generate unique name for the new logical volume"
+msgstr ""
+
+#: metadata/lv_manip.c:1512
+#, c-format
+msgid "Creating logical volume %s"
+msgstr ""
+
+#: metadata/lv_manip.c:1516
+msgid "lv_list allocation failed"
+msgstr ""
+
+#: metadata/lv_manip.c:1526
+msgid "lv name strdup failed"
+msgstr ""
+
+#: metadata/lv_manip.c:1574 metadata/metadata.c:986
+msgid "pv_list allocation failed"
+msgstr ""
+
+#: metadata/lv_manip.c:1596
+msgid "parallel_areas allocation failed"
+msgstr ""
+
+#: metadata/lv_manip.c:1604
+msgid "allocation failed"
+msgstr ""
+
+#: metadata/merge.c:72
+#, c-format
+msgid "LV %s invalid: segment %u should begin at LE %u (found %u)."
+msgstr ""
+
+#: metadata/merge.c:82
+#, c-format
+msgid "LV %s: segment %u has inconsistent area_len %u"
+msgstr ""
+
+#: metadata/merge.c:90
+#, c-format
+msgid "LV %s: segment %u has log LV but is not mirrored"
+msgstr ""
+
+#: metadata/merge.c:97
+#, c-format
+msgid "LV %s: segment %u log LV %s is not a mirror log"
+msgstr ""
+
+#: metadata/merge.c:105
+#, c-format
+msgid "LV %s: segment %u log LV does not point back to mirror segment"
+msgstr ""
+
+#: metadata/merge.c:115
+#, c-format
+msgid "LV %s: segment %u mirror image is not mirrored"
+msgstr ""
+
+#: metadata/merge.c:124
+#, c-format
+msgid "LV %s: segment %u has unassigned area %u."
+msgstr ""
+
+#: metadata/merge.c:132
+#, c-format
+msgid "LV %s: segment %u has inconsistent PV area %u"
+msgstr ""
+
+#: metadata/merge.c:141
+#, c-format
+msgid "LV %s: segment %u has inconsistent LV area %u"
+msgstr ""
+
+#: metadata/merge.c:152
+#, c-format
+msgid "LV %s: segment %u mirror image %u missing mirror ptr"
+msgstr ""
+
+#: metadata/merge.c:174
+#, c-format
+msgid "LV %s: inconsistent LE count %u != %u"
+msgstr ""
+
+#: metadata/merge.c:195
+#, c-format
+msgid "Unable to split the %s segment at LE %u in LV %s"
+msgstr ""
+
+#: metadata/merge.c:208
+msgid "Couldn't allocate cloned LV segment."
+msgstr ""
+
+#: metadata/merge.c:213
+msgid "LV segment tags duplication failed"
+msgstr ""
+
+#: metadata/merge.c:240
+#, c-format
+msgid "Split %s:%u[%u] at %u: %s LE %u"
+msgstr ""
+
+#: metadata/merge.c:256
+#, c-format
+msgid "Split %s:%u[%u] at %u: %s PE %u"
+msgstr ""
+
+#: metadata/merge.c:263 metadata/metadata.c:495
+#, c-format
+msgid "Unassigned area %u found in segment"
+msgstr ""
+
+#: metadata/merge.c:282
+#, c-format
+msgid "Segment with extent %u in LV %s not found"
+msgstr ""
+
+#: metadata/metadata.c:43
+#, c-format
+msgid "Adding physical volume '%s' to volume group '%s'"
+msgstr ""
+
+#: metadata/metadata.c:47 metadata/metadata.c:1008
+#, c-format
+msgid "pv_list allocation for '%s' failed"
+msgstr ""
+
+#: metadata/metadata.c:53
+#, c-format
+msgid "%s not identified as an existing physical volume"
+msgstr ""
+
+#: metadata/metadata.c:59
+#, c-format
+msgid "Physical volume '%s' is already in volume group '%s'"
+msgstr ""
+
+#: metadata/metadata.c:65
+#, c-format
+msgid "Physical volume %s is of different format type (%s)"
+msgstr ""
+
+#: metadata/metadata.c:72
+#, c-format
+msgid "Physical volume %s might be constructed from same volume group %s"
+msgstr ""
+
+#: metadata/metadata.c:78 metadata/metadata.c:199
+#, c-format
+msgid "vg->name allocation failed for '%s'"
+msgstr ""
+
+#: metadata/metadata.c:100
+#, c-format
+msgid "Format-specific setup of physical volume '%s' failed."
+msgstr ""
+
+#: metadata/metadata.c:106
+#, c-format
+msgid "Physical volume '%s' listed more than once."
+msgstr ""
+
+#: metadata/metadata.c:112
+#, c-format
+msgid "No space for '%s' - volume group '%s' holds max %d physical volume(s)."
+msgstr ""
+
+#: metadata/metadata.c:127
+#, c-format
+msgid "Unable to add %s to %s: new extent count (%lu) exceeds limit (%u)."
+msgstr ""
+
+#: metadata/metadata.c:148
+msgid "PV tags duplication failed"
+msgstr ""
+
+#: metadata/metadata.c:170
+#, c-format
+msgid "get_pv_from_vg_by_id: vg_read failed to read VG %s"
+msgstr ""
+
+#: metadata/metadata.c:176
+#, c-format
+msgid "Warning: Volume group %s is not consistent"
+msgstr ""
+
+#: metadata/metadata.c:205
+#, c-format
+msgid "pv->vg_name allocation failed for '%s'"
+msgstr ""
+
+#: metadata/metadata.c:222
+#, c-format
+msgid "Unable to add physical volume '%s' to volume group '%s'."
+msgstr ""
+
+#: metadata/metadata.c:260
+#, c-format
+msgid "A volume group called '%s' already exists."
+msgstr ""
+
+#: metadata/metadata.c:266
+#, c-format
+msgid "Couldn't create uuid for volume group '%s'."
+msgstr ""
+
+#: metadata/metadata.c:309 metadata/metadata.c:1085 metadata/metadata.c:1151
+msgid "Failed to create format instance"
+msgstr ""
+
+#: metadata/metadata.c:315
+#, c-format
+msgid "Format specific setup of volume group '%s' failed."
+msgstr ""
+
+#: metadata/metadata.c:338
+#, c-format
+msgid "New size %lu for %s%s not an exact number of new extents."
+msgstr ""
+
+#: metadata/metadata.c:346
+#, c-format
+msgid "New extent count %lu for %s%s exceeds 32 bits."
+msgstr ""
+
+#: metadata/metadata.c:556
+#, c-format
+msgid "Failed to create random uuid for %s."
+msgstr ""
+
+#: metadata/metadata.c:575 pvresize.c:128
+#, c-format
+msgid "WARNING: %s: Overriding real size. You could lose data."
+msgstr ""
+
+#: metadata/metadata.c:577
+#, c-format
+msgid "%s: Pretending size is %lu sectors."
+msgstr ""
+
+#: metadata/metadata.c:583 pvresize.c:136
+#, c-format
+msgid "%s: Size must exceed minimum of %ld sectors."
+msgstr ""
+
+#: metadata/metadata.c:601
+#, c-format
+msgid "%s: Format-specific setup of physical volume failed."
+msgstr ""
+
+#: metadata/metadata.c:699
+#, c-format
+msgid "Physical volume %s not found"
+msgstr ""
+
+#: metadata/metadata.c:704
+#, c-format
+msgid "Physical volume %s not in a volume group"
+msgstr ""
+
+#: metadata/metadata.c:780
+#, c-format
+msgid "Internal error: Duplicate PV id %s detected for %s in %s."
+msgstr ""
+
+#: metadata/metadata.c:789
+#, c-format
+msgid "Internal error: VG name for PV %s is corrupted"
+msgstr ""
+
+#: metadata/metadata.c:796 metadata/metadata.c:1278
+#, c-format
+msgid "Internal error: PV segments corrupted in %s."
+msgstr ""
+
+#: metadata/metadata.c:806
+#, c-format
+msgid "Internal error: Duplicate LV name %s detected in %s."
+msgstr ""
+
+#: metadata/metadata.c:816
+#, c-format
+msgid "Internal error: Duplicate LV id %s detected for %s and %s in %s."
+msgstr ""
+
+#: metadata/metadata.c:827 metadata/metadata.c:1285
+#, c-format
+msgid "Internal error: LV segments corrupted in %s."
+msgstr ""
+
+#: metadata/metadata.c:851
+#, c-format
+msgid "Cannot change metadata for partial volume group %s"
+msgstr ""
+
+#: metadata/metadata.c:857
+msgid "Aborting vg_write: No metadata areas to write to!"
+msgstr ""
+
+#: metadata/metadata.c:866
+msgid "Format does not support writing volumegroup metadata areas"
+msgstr ""
+
+#: metadata/metadata.c:969
+msgid "vg allocation failed"
+msgstr ""
+
+#: metadata/metadata.c:977
+msgid "vg name allocation failed"
+msgstr ""
+
+#: metadata/metadata.c:1049
+msgid "Internal error: vg_read requires vgname with pre-commit."
+msgstr ""
+
+#: metadata/metadata.c:1113 metadata/metadata.c:1122
+#, c-format
+msgid "Cached VG %s had incorrect PV list"
+msgstr ""
+
+#: metadata/metadata.c:1201
+#, c-format
+msgid "Inconsistent pre-commit metadata copies for volume group %s"
+msgstr ""
+
+#: metadata/metadata.c:1212
+#, c-format
+msgid "Inconsistent metadata copies found for partial volume group %s"
+msgstr ""
+
+#: metadata/metadata.c:1220
+#, c-format
+msgid "Inconsistent metadata UUIDs found for volume group %s"
+msgstr ""
+
+#: metadata/metadata.c:1226
+#, c-format
+msgid "Inconsistent metadata found for VG %s - updating to use version %u"
+msgstr ""
+
+#: metadata/metadata.c:1230
+msgid "Automatic metadata correction failed"
+msgstr ""
+
+#: metadata/metadata.c:1235
+msgid "Automatic metadata correction commit failed"
+msgstr ""
+
+#: metadata/metadata.c:1247
+#, c-format
+msgid "Removing PV %s (%s) that no longer belongs to VG %s"
+msgstr ""
+
+#: metadata/metadata.c:1257
+#, c-format
+msgid "WARNING: Interrupted pvmove detected in volume group %s"
+msgstr ""
+
+#: metadata/metadata.c:1259
+msgid "Please restore the metadata by running vgcfgrestore."
+msgstr ""
+
+#: metadata/metadata.c:1316 metadata/metadata.c:1348
+#, c-format
+msgid "Volume group %s metadata is inconsistent"
+msgstr ""
+
+#: metadata/metadata.c:1335
+msgid "vg_read_by_vgid: get_vgs failed"
+msgstr ""
+
+#: metadata/metadata.c:1369
+#, c-format
+msgid "Finding volume group for uuid %s"
+msgstr ""
+
+#: metadata/metadata.c:1371
+#, c-format
+msgid "Volume group for uuid not found: %s"
+msgstr ""
+
+#: metadata/metadata.c:1375
+#, c-format
+msgid "Found volume group \"%s\""
+msgstr ""
+
+#: metadata/metadata.c:1381
+#, c-format
+msgid "Can't find logical volume id %s"
+msgstr ""
+
+#: metadata/metadata.c:1405
+#, c-format
+msgid "No physical volume label read from %s"
+msgstr ""
+
+#: metadata/metadata.c:1415
+#, c-format
+msgid "pv allocation for '%s' failed"
+msgstr ""
+
+#: metadata/metadata.c:1424
+#, c-format
+msgid "Failed to read existing physical volume '%s'"
+msgstr ""
+
+#: metadata/metadata.c:1466
+msgid "PV list allocation failed"
+msgstr ""
+
+#: metadata/metadata.c:1474
+msgid "get_pvs: get_vgs failed"
+msgstr ""
+
+#: metadata/metadata.c:1498
+#, c-format
+msgid "Warning: Volume Group %s is not consistent"
+msgstr ""
+
+#: metadata/metadata.c:1516
+msgid "Format does not support writing physical volumes"
+msgstr ""
+
+#: metadata/metadata.c:1521
+#, c-format
+msgid "Assertion failed: can't _pv_write non-orphan PV (in VG %s)"
+msgstr ""
+
+#: metadata/metadata.c:1547 vgreduce.c:410
+#, c-format
+msgid ""
+"Failed to clear metadata from physical volume \"%s\" after removal from \"%s"
+"\""
+msgstr ""
+
+#: metadata/metadata.c:1570 pvcreate.c:81
+#, c-format
+msgid "Device %s not found (or ignored by filtering)."
+msgstr ""
+
+#: metadata/metadata.c:1579
+#, c-format
+msgid "Could not find LVM label on %s"
+msgstr ""
+
+#: metadata/metadata.c:1584
+#, c-format
+msgid "Found label on %s, sector %lu, type=%s"
+msgstr ""
+
+#: metadata/mirror.c:52 mirror/mirrored.c:322
+#, c-format
+msgid "Using reduced mirror region size of %u sectors"
+msgstr ""
+
+#: metadata/mirror.c:94
+msgid "Aborting. Unable to tag."
+msgstr ""
+
+#: metadata/mirror.c:100
+msgid "Intermediate VG commit for orphan volume failed."
+msgstr ""
+
+#: metadata/mirror.c:138
+#, c-format
+msgid "Reducing mirror set from %u to %u image(s)%s."
+msgstr ""
+
+#: metadata/mirror.c:183
+msgid "No mirror images found using specified PVs."
+msgstr ""
+
+#: metadata/mirror.c:222
+msgid "intermediate VG write failed."
+msgstr ""
+
+#: metadata/mirror.c:277
+msgid "Bad activation/mirror_log_fault_policy"
+msgstr ""
+
+#: metadata/mirror.c:279
+msgid "Bad activation/mirror_device_fault_policy"
+msgstr ""
+
+#: metadata/mirror.c:317
+#, c-format
+msgid "WARNING: Failed to replace mirror device in %s/%s"
+msgstr ""
+
+#: metadata/mirror.c:321
+#, c-format
+msgid ""
+"WARNING: Use 'lvconvert -m %d %s/%s --corelog' to replace failed devices"
+msgstr ""
+
+#: metadata/mirror.c:324 metadata/mirror.c:341
+#, c-format
+msgid "WARNING: Use 'lvconvert -m %d %s/%s' to replace failed devices"
+msgstr ""
+
+#: metadata/mirror.c:338
+#, c-format
+msgid "WARNING: Failed to replace mirror log device in %s/%s"
+msgstr ""
+
+#: metadata/mirror.c:362
+#, c-format
+msgid "WARNING: Unable to determine mirror sync status of %s/%s."
+msgstr ""
+
+#: metadata/mirror.c:380
+#, c-format
+msgid "WARNING: Bad device removed from mirror volume, %s/%s"
+msgstr ""
+
+#: metadata/mirror.c:393
+#, c-format
+msgid "WARNING: Unable to find substitute device for mirror volume, %s/%s"
+msgstr ""
+
+#: metadata/mirror.c:397
+#, c-format
+msgid ""
+"WARNING: Mirror volume, %s/%s restored - substitute for failed device found."
+msgstr ""
+
+#: metadata/mirror.c:402
+#, c-format
+msgid ""
+"WARNING: Mirror volume, %s/%s converted to linear due to device failure."
+msgstr ""
+
+#: metadata/mirror.c:405
+#, c-format
+msgid "WARNING: Mirror volume, %s/%s disk log removed due to device failure."
+msgstr ""
+
+#: metadata/mirror.c:428 metadata/mirror.c:434
+msgid "img_name allocation failed. Remove new LV and retry."
+msgstr ""
+
+#: metadata/mirror.c:443
+msgid "Aborting. Failed to create mirror image LV. Remove new LV and retry."
+msgstr ""
+
+#: metadata/mirror.c:455
+#, c-format
+msgid ""
+"Aborting. Failed to add mirror image segment to %s. Remove new LV and retry."
+msgstr ""
+
+#: metadata/mirror.c:477 metadata/mirror.c:518
+msgid "img_lvs allocation failed. Remove new LV and retry."
+msgstr ""
+
+#: metadata/mirror.c:499
+msgid "Aborting. Failed to add mirror segment. Remove new LV and retry."
+msgstr ""
+
+#: metadata/mirror.c:632
+#, c-format
+msgid "Matched PE range %u-%u against %s %u len %u"
+msgstr ""
+
+#: metadata/mirror.c:641 metadata/mirror.c:872 vgreduce.c:139
+msgid "lv_list alloc failed"
+msgstr ""
+
+#: metadata/mirror.c:651
+#, c-format
+msgid "Moving %s:%u-%u of %s/%s"
+msgstr ""
+
+#: metadata/mirror.c:664
+msgid "Unable to allocate temporary LV for pvmove."
+msgstr ""
+
+#: metadata/mirror.c:679
+#, c-format
+msgid "Moving %u extents of logical volume %s/%s"
+msgstr ""
+
+#: metadata/mirror.c:711
+msgid "No segment found with LE"
+msgstr ""
+
+#: metadata/mirror.c:722
+msgid "Incompatible segments"
+msgstr ""
+
+#: metadata/mirror.c:747
+msgid "Missing error segtype"
+msgstr ""
+
+#: metadata/mirror.c:853
+msgid "lvs list alloc failed"
+msgstr ""
+
+#: metadata/pv_manip.c:30
+msgid "pv_segment allocation failed"
+msgstr ""
+
+#: metadata/pv_manip.c:121
+#, c-format
+msgid "Segment with extent %u in PV %s not found"
+msgstr ""
+
+#: metadata/pv_manip.c:161
+#, c-format
+msgid "Missing PV segment on %s at %u."
+msgstr ""
+
+#: metadata/pv_manip.c:178
+#, c-format
+msgid "release_pv_segment with unallocated segment: %s PE %u"
+msgstr ""
+
+#: metadata/pv_manip.c:238
+#, c-format
+msgid "%s %u: %6u %6u: %s(%u:%u)"
+msgstr ""
+
+#: metadata/pv_manip.c:244
+#, c-format
+msgid "Gap in pvsegs: %u, %u"
+msgstr ""
+
+#: metadata/pv_manip.c:250
+msgid "Wrong lvseg area type"
+msgstr ""
+
+#: metadata/pv_manip.c:254
+msgid "Inconsistent pvseg pointers"
+msgstr ""
+
+#: metadata/pv_manip.c:258
+#, c-format
+msgid "Inconsistent length: %u %u"
+msgstr ""
+
+#: metadata/pv_manip.c:269
+#, c-format
+msgid "PV segment pe_count mismatch: %u != %u"
+msgstr ""
+
+#: metadata/pv_manip.c:275
+#, c-format
+msgid "PV segment pe_alloc_count mismatch: %u != %u"
+msgstr ""
+
+#: metadata/pv_manip.c:285
+#, c-format
+msgid "PV segment VG pv_count mismatch: %u != %u"
+msgstr ""
+
+#: metadata/pv_manip.c:291
+#, c-format
+msgid "PV segment VG free_count mismatch: %u != %u"
+msgstr ""
+
+#: metadata/pv_manip.c:297
+#, c-format
+msgid "PV segment VG extent_count mismatch: %u != %u"
+msgstr ""
+
+#: metadata/pv_manip.c:311
+#, c-format
+msgid "%s: cannot resize to %u extents as %u are allocated."
+msgstr ""
+
+#: metadata/pv_manip.c:324
+#, c-format
+msgid "%s: cannot resize to %u extents as later ones are allocated."
+msgstr ""
+
+#: metadata/pv_manip.c:356
+#, c-format
+msgid "%s: cannot resize to %u extents as there is only room for %lu."
+msgstr ""
+
+#: metadata/pv_manip.c:385
+#, c-format
+msgid "No change to size of physical volume %s."
+msgstr ""
+
+#: metadata/pv_manip.c:390
+#, c-format
+msgid "Resizing physical volume %s from %u to %u extents."
+msgstr ""
+
+#: metadata/pv_map.c:48
+#, c-format
+msgid "Allowing allocation on %s start PE %u length %u"
+msgstr ""
+
+#: metadata/pv_map.c:176
+msgid "create_pv_maps alloc failed"
+msgstr ""
+
+#: metadata/pv_map.c:183
+#, c-format
+msgid "Couldn't create physical volume maps in %s"
+msgstr ""
+
+#: metadata/segtype.c:30
+#, c-format
+msgid "Unrecognised segment type %s"
+msgstr ""
+
+#: metadata/snapshot_manip.c:63
+#, c-format
+msgid "'%s' is already in use as a snapshot."
+msgstr ""
+
+#: metadata/snapshot_manip.c:104
+#, c-format
+msgid "Failed to remove internal snapshot LV %s"
+msgstr ""
+
+#: mirror/mirrored.c:57
+#, c-format
+msgid "  Mirrors\t\t%u"
+msgstr ""
+
+#: mirror/mirrored.c:58
+#, c-format
+msgid "  Mirror size\t\t%u"
+msgstr ""
+
+#: mirror/mirrored.c:60
+#, c-format
+msgid "  Mirror log volume\t%s"
+msgstr ""
+
+#: mirror/mirrored.c:65
+#, c-format
+msgid "  Mirror region size\t%s"
+msgstr ""
+
+#: mirror/mirrored.c:68
+msgid "  Mirror original:"
+msgstr ""
+
+#: mirror/mirrored.c:70
+msgid "  Mirror destinations:"
+msgstr ""
+
+#: mirror/mirrored.c:79
+#, c-format
+msgid "Couldn't read 'mirror_count' for segment '%s'."
+msgstr ""
+
+#: mirror/mirrored.c:98
+#, c-format
+msgid "Couldn't read 'extents_moved' for segment '%s'."
+msgstr ""
+
+#: mirror/mirrored.c:107
+#, c-format
+msgid "Couldn't read 'region_size' for segment '%s'."
+msgstr ""
+
+#: mirror/mirrored.c:115
+msgid "Mirror log type must be a string."
+msgstr ""
+
+#: mirror/mirrored.c:120
+#, c-format
+msgid "Unrecognised mirror log in segment %s."
+msgstr ""
+
+#: mirror/mirrored.c:128
+#, c-format
+msgid "Missing region size for mirror log for segment '%s'."
+msgstr ""
+
+#: mirror/mirrored.c:134
+#, c-format
+msgid "Couldn't find mirrors array for segment '%s'."
+msgstr ""
+
+#: mirror/mirrored.c:163
+msgid "struct mirr_state allocation failed"
+msgstr ""
+
+#: mirror/mirrored.c:193
+#, c-format
+msgid "Mirror status: %s"
+msgstr ""
+
+#: mirror/mirrored.c:196
+#, c-format
+msgid "Failure parsing mirror status mirror count: %s"
+msgstr ""
+
+#: mirror/mirrored.c:204
+#, c-format
+msgid "Failure parsing mirror status devices: %s"
+msgstr ""
+
+#: mirror/mirrored.c:213
+#, c-format
+msgid "Failure parsing mirror status fraction: %s"
+msgstr ""
+
+#: mirror/mirrored.c:245
+#, c-format
+msgid "Failed to build uuid for log LV %s."
+msgstr ""
+
+#: mirror/mirrored.c:252
+#, c-format
+msgid "Failed to build uuid for mirror LV %s."
+msgstr ""
+
+#: mirror/mirrored.c:310
+msgid "Missing region size for mirror segment."
+msgstr ""
+
+#: mirror/mirrored.c:505
+msgid "cluster log string list allocation failed"
+msgstr ""
+
+#: mirror/mirrored.c:510
+msgid "mirror string list allocation failed"
+msgstr ""
+
+#: misc/lvm-exec.c:31
+#, c-format
+msgid "Executing: %s %s %s %s"
+msgstr ""
+
+#: misc/lvm-exec.c:34 polldaemon.c:39
+#, c-format
+msgid "fork failed: %s"
+msgstr ""
+
+#: misc/lvm-exec.c:48
+#, c-format
+msgid "wait4 child process %u failed: %s"
+msgstr ""
+
+#: misc/lvm-exec.c:54
+#, c-format
+msgid "Child %u exited abnormally"
+msgstr ""
+
+#: misc/lvm-exec.c:59
+#, c-format
+msgid "%s failed: %u"
+msgstr ""
+
+#: misc/lvm-file.c:55
+msgid "Not enough space to build temporary file string."
+msgstr ""
+
+#: misc/lvm-file.c:102
+#, c-format
+msgid "%s: rename to %s failed"
+msgstr ""
+
+#: misc/lvm-file.c:148
+#, c-format
+msgid "Creating directory \"%s\""
+msgstr ""
+
+#: misc/lvm-file.c:189
+#, c-format
+msgid "Directory \"%s\" not found"
+msgstr ""
+
+#: misc/lvm-file.c:220
+msgid "sync_dir failed in strdup"
+msgstr ""
+
+#: misc/lvm-file.c:269
+msgid "fcntl_lock_file failed in strdup."
+msgstr ""
+
+#: misc/lvm-file.c:283
+#, c-format
+msgid "Locking %s (%s, %hd)"
+msgstr ""
+
+#: misc/lvm-file.c:313
+#, c-format
+msgid "Unlocking fd %d"
+msgstr ""
+
+#: misc/lvm-file.c:316
+#, c-format
+msgid "fcntl unlock failed on fd %d: %s"
+msgstr ""
+
+#: misc/lvm-file.c:320
+#, c-format
+msgid "lock file close failed on fd %d: %s"
+msgstr ""
+
+#: misc/lvm-string.c:107
+#, c-format
+msgid "build_dm_name: Allocation failed for %zu for %s %s %s."
+msgstr ""
+
+#: misc/sharedlib.c:48
+#, c-format
+msgid "Not loading shared %s library %s in static mode."
+msgstr ""
+
+#: misc/sharedlib.c:55
+#, c-format
+msgid "Opening shared %s library %s"
+msgstr ""
+
+#: misc/sharedlib.c:59 misc/sharedlib.c:62
+#, c-format
+msgid "Unable to open external %s library %s: %s"
+msgstr ""
+
+#: mm/memlock.c:99
+msgid "Locking memory"
+msgstr ""
+
+#: mm/memlock.c:108 mm/memlock.c:122
+#, c-format
+msgid "setpriority %u failed: %s"
+msgstr ""
+
+#: mm/memlock.c:118
+msgid "Unlocking memory"
+msgstr ""
+
+#: mm/memlock.c:130
+#, c-format
+msgid "memlock_count inc to %d"
+msgstr ""
+
+#: mm/memlock.c:137
+#, c-format
+msgid "memlock_count dec to %d"
+msgstr ""
+
+#: polldaemon.c:34
+msgid "Forking background process"
+msgstr ""
+
+#: polldaemon.c:49
+#, c-format
+msgid "Background process failed to setsid: %s"
+msgstr ""
+
+#: polldaemon.c:80
+msgid "Failed to generate list of copied LVs: can't abort."
+msgstr ""
+
+#: polldaemon.c:90
+msgid "ABORTING: Mirror percentage check failed."
+msgstr ""
+
+#: polldaemon.c:96 polldaemon.c:98
+#, c-format
+msgid "%s: Moved: %.1f%%"
+msgstr ""
+
+#: polldaemon.c:107
+msgid "ABORTING: Failed to generate list of copied LVs"
+msgstr ""
+
+#: polldaemon.c:119
+msgid "ABORTING: Segment progression failed."
+msgstr ""
+
+#: polldaemon.c:149
+#, c-format
+msgid "ABORTING: Can't reread VG for %s"
+msgstr ""
+
+#: polldaemon.c:156
+#, c-format
+msgid "ABORTING: Can't find mirror LV in %s for %s"
+msgstr ""
+
+#: polldaemon.c:184
+#, c-format
+msgid "Couldn't read volume group %s"
+msgstr ""
+
+#: polldaemon.c:189
+#, c-format
+msgid "Volume Group %s inconsistent - skipping"
+msgstr ""
+
+#: polldaemon.c:241
+#, c-format
+msgid "Checking progress every %u seconds"
+msgstr ""
+
+#: pvchange.c:55
+#, c-format
+msgid "Finding volume group of physical volume \"%s\""
+msgstr ""
+
+#: pvchange.c:65 pvresize.c:75
+#, c-format
+msgid "Unable to find volume group of \"%s\""
+msgstr ""
+
+#: pvchange.c:90 pvresize.c:101
+#, c-format
+msgid "Unable to find \"%s\" in volume group \"%s\""
+msgstr ""
+
+#: pvchange.c:97
+#, c-format
+msgid "Volume group containing %s does not support tags"
+msgstr ""
+
+#: pvchange.c:103
+#, c-format
+msgid "Volume group containing %s has active logical volumes"
+msgstr ""
+
+#: pvchange.c:112
+#, c-format
+msgid "Can't change tag on Physical Volume %s not in volume group"
+msgstr ""
+
+#: pvchange.c:117 pvresize.c:48
+msgid "Can't get lock for orphans"
+msgstr ""
+
+#: pvchange.c:123 pvresize.c:54
+#, c-format
+msgid "Unable to read PV \"%s\""
+msgstr ""
+
+#: pvchange.c:132
+#, c-format
+msgid "Allocatability not supported by orphan %s format PV %s"
+msgstr ""
+
+#: pvchange.c:140
+#, c-format
+msgid "Physical volume \"%s\" is already allocatable"
+msgstr ""
+
+#: pvchange.c:150
+#, c-format
+msgid "Physical volume \"%s\" is already unallocatable"
+msgstr ""
+
+#: pvchange.c:160
+#, c-format
+msgid "Setting physical volume \"%s\" allocatable"
+msgstr ""
+
+#: pvchange.c:164
+#, c-format
+msgid "Setting physical volume \"%s\" NOT allocatable"
+msgstr ""
+
+#: pvchange.c:172
+#, c-format
+msgid "Failed to add tag %s to physical volume %s"
+msgstr ""
+
+#: pvchange.c:178
+#, c-format
+msgid "Failed to remove tag %s from physical volume%s"
+msgstr ""
+
+#: pvchange.c:186
+#, c-format
+msgid "Failed to generate new random UUID for %s."
+msgstr ""
+
+#: pvchange.c:194
+#, c-format
+msgid "Changing uuid of %s to %s."
+msgstr ""
+
+#: pvchange.c:201
+#, c-format
+msgid "pv_write with new uuid failed for %s."
+msgstr ""
+
+#: pvchange.c:210 pvresize.c:174
+#, c-format
+msgid "Updating physical volume \"%s\""
+msgstr ""
+
+#: pvchange.c:214 pvresize.c:178
+#, c-format
+msgid "Failed to store physical volume \"%s\" in volume group \"%s\""
+msgstr ""
+
+#: pvchange.c:223 pvresize.c:187
+#, c-format
+msgid "Failed to store physical volume \"%s\""
+msgstr ""
+
+#: pvchange.c:230 pvresize.c:194
+#, c-format
+msgid "Physical volume \"%s\" changed"
+msgstr ""
+
+#: pvchange.c:252
+msgid "Please give exactly one option of -x, -uuid, --addtag or --deltag"
+msgstr ""
+
+#: pvchange.c:258
+msgid "Please give a physical volume path"
+msgstr ""
+
+#: pvchange.c:263
+msgid "Option a and PhysicalVolumePath are exclusive"
+msgstr ""
+
+#: pvchange.c:268 toollib.c:683
+msgid "Using physical volume(s) on command line"
+msgstr ""
+
+#: pvchange.c:273
+#, c-format
+msgid "Failed to read physical volume %s"
+msgstr ""
+
+#: pvchange.c:281 toollib.c:766
+msgid "Scanning for physical volume names"
+msgstr ""
+
+#: pvchange.c:292
+#, c-format
+msgid "%d physical volume%s changed / %d physical volume%s not changed"
+msgstr ""
+
+#: pvck.c:32
+#, c-format
+msgid "Scanning %s"
+msgstr ""
+
+#: pvcreate.c:37 pvremove.c:31
+#, c-format
+msgid "%s: Not LVM partition type: use -f to override"
+msgstr ""
+
+#: pvcreate.c:49
+#, c-format
+msgid ""
+"Can't initialize physical volume \"%s\" of volume group \"%s\" without -ff"
+msgstr ""
+
+#: pvcreate.c:57
+#, c-format
+msgid "%s: physical volume not initialized"
+msgstr ""
+
+#: pvcreate.c:72 pvcreate.c:168 pvremove.c:81 vgcreate.c:135 vgextend.c:40
+#: vgremove.c:96
+msgid "Can't get lock for orphan PVs"
+msgstr ""
+
+#: pvcreate.c:86
+#, c-format
+msgid "Can't open %s exclusively.  Mounted filesystem?"
+msgstr ""
+
+#: pvcreate.c:98
+#, c-format
+msgid "Wiping software RAID md superblock on %s"
+msgstr ""
+
+#: pvcreate.c:100
+#, c-format
+msgid "Failed to wipe RAID md superblock on %s"
+msgstr ""
+
+#: pvcreate.c:107
+#, c-format
+msgid "WARNING: Forcing physical volume creation on %s%s%s%s"
+msgstr ""
+
+#: pvcreate.c:140
+#, c-format
+msgid "uuid %s already in use on \"%s\""
+msgstr ""
+
+#: pvcreate.c:152
+#, c-format
+msgid "Unable to read volume group from %s"
+msgstr ""
+
+#: pvcreate.c:158
+#, c-format
+msgid "Can't find uuid %s in backup file %s"
+msgstr ""
+
+#: pvcreate.c:176 pvresize.c:212
+msgid "Physical volume size may not be negative"
+msgstr ""
+
+#: pvcreate.c:182 vgconvert.c:66
+msgid "Metadata size may not be negative"
+msgstr ""
+
+#: pvcreate.c:199 pvremove.c:89
+#, c-format
+msgid "%s: Couldn't find device.  Check your filters?"
+msgstr ""
+
+#: pvcreate.c:208 vgconvert.c:127
+#, c-format
+msgid "Failed to setup physical volume \"%s\""
+msgstr ""
+
+#: pvcreate.c:212 vgconvert.c:138
+#, c-format
+msgid "Set up physical volume for \"%s\" with %lu available sectors"
+msgstr ""
+
+#: pvcreate.c:217 vgconvert.c:143
+#, c-format
+msgid "Failed to wipe existing label on %s"
+msgstr ""
+
+#: pvcreate.c:222
+#, c-format
+msgid "Zeroing start of device %s"
+msgstr ""
+
+#: pvcreate.c:224
+#, c-format
+msgid "%s not opened: device not zeroed"
+msgstr ""
+
+#: pvcreate.c:229
+#, c-format
+msgid "%s not wiped: aborting"
+msgstr ""
+
+#: pvcreate.c:236 vgconvert.c:150
+#, c-format
+msgid "Writing physical volume data to disk \"%s\""
+msgstr ""
+
+#: pvcreate.c:240 vgconvert.c:155
+#, c-format
+msgid "Failed to write physical volume \"%s\""
+msgstr ""
+
+#: pvcreate.c:244 vgconvert.c:161
+#, c-format
+msgid "Physical volume \"%s\" successfully created"
+msgstr ""
+
+#: pvcreate.c:261 pvremove.c:123
+msgid "Please enter a physical volume path"
+msgstr ""
+
+#: pvcreate.c:266
+msgid "--uuid is required with --restorefile"
+msgstr ""
+
+#: pvcreate.c:271
+msgid "Can only set uuid on one volume at once"
+msgstr ""
+
+#: pvcreate.c:276 pvremove.c:128
+msgid "Option y can only be given with option f"
+msgstr ""
+
+#: pvcreate.c:281 vgconvert.c:205
+#, c-format
+msgid "labelsector must be less than %lu"
+msgstr ""
+
+#: pvcreate.c:289 vgconvert.c:213
+msgid "Metadata parameters only apply to text format"
+msgstr ""
+
+#: pvcreate.c:295 vgconvert.c:219
+msgid "Metadatacopies may only be 0, 1 or 2"
+msgstr ""
+
+#: pvdisplay.c:30 reporter.c:65 reporter.c:113 toollib.c:347 toollib.c:477
+#, c-format
+msgid "Can't lock %s: skipping"
+msgstr ""
+
+#: pvdisplay.c:35 reporter.c:70 reporter.c:118
+#, c-format
+msgid "Can't read %s: skipping"
+msgstr ""
+
+#: pvdisplay.c:54
+#, c-format
+msgid "Device \"%s\" has a capacity of %s"
+msgstr ""
+
+#: pvdisplay.c:60
+#, c-format
+msgid "Physical volume \"%s\" of volume group \"%s\" is exported"
+msgstr ""
+
+#: pvdisplay.c:64
+#, c-format
+msgid "\"%s\" is a new physical volume of \"%s\""
+msgstr ""
+
+#: pvdisplay.c:104
+msgid "Option -v not allowed with option -c"
+msgstr ""
+
+#: pvmove.c:34
+msgid "--name takes a logical volume name"
+msgstr ""
+
+#: pvmove.c:39
+msgid "Named LV and old PV must be in the same VG"
+msgstr ""
+
+#: pvmove.c:45
+msgid "Incomplete LV name supplied with --name"
+msgstr ""
+
+#: pvmove.c:127
+msgid "No extents available for allocation"
+msgstr ""
+
+#: pvmove.c:150
+msgid "Creation of temporary pvmove LV failed"
+msgstr ""
+
+#: pvmove.c:157
+msgid "lvs_changed list struct allocation failed"
+msgstr ""
+
+#: pvmove.c:170
+#, c-format
+msgid "Skipping snapshot-related LV %s"
+msgstr ""
+
+#: pvmove.c:174
+#, c-format
+msgid "Skipping mirror LV %s"
+msgstr ""
+
+#: pvmove.c:178
+#, c-format
+msgid "Skipping mirror log LV %s"
+msgstr ""
+
+#: pvmove.c:182
+#, c-format
+msgid "Skipping mirror image LV %s"
+msgstr ""
+
+#: pvmove.c:186
+#, c-format
+msgid "Skipping locked LV %s"
+msgstr ""
+
+#: pvmove.c:199
+#, c-format
+msgid "No data to move for %s"
+msgstr ""
+
+#: pvmove.c:210
+msgid "Updating volume group metadata"
+msgstr ""
+
+#: pvmove.c:212 pvmove.c:236
+msgid "ABORTING: Volume group metadata update failed."
+msgstr ""
+
+#: pvmove.c:249
+msgid "ABORTING: Temporary mirror activation failed.  Run pvmove --abort."
+msgstr ""
+
+#: pvmove.c:257 pvmove.c:438
+#, c-format
+msgid "Unable to reactivate logical volume \"%s\""
+msgstr ""
+
+#: pvmove.c:265
+msgid "Unable to resume logical volumes"
+msgstr ""
+
+#: pvmove.c:313
+#, c-format
+msgid "Detected pvmove in progress for %s"
+msgstr ""
+
+#: pvmove.c:315
+msgid "Ignoring remaining command line arguments"
+msgstr ""
+
+#: pvmove.c:318
+msgid "ABORTING: Failed to generate list of moving LVs"
+msgstr ""
+
+#: pvmove.c:326
+msgid "ABORTING: Temporary mirror activation failed."
+msgstr ""
+
+#: pvmove.c:403
+msgid "ABORTING: Removal of temporary mirror failed"
+msgstr ""
+
+#: pvmove.c:409 pvmove.c:428 pvmove.c:462
+msgid "ABORTING: Failed to write new data locations to disk."
+msgstr ""
+
+#: pvmove.c:416
+msgid "Locking LVs to remove temporary mirror failed"
+msgstr ""
+
+#: pvmove.c:422
+msgid "Suspension of temporary mirror LV failed"
+msgstr ""
+
+#: pvmove.c:448
+#, c-format
+msgid "ABORTING: Unable to deactivate temporary logical volume \"%s\""
+msgstr ""
+
+#: pvmove.c:453
+msgid "Removing temporary pvmove LV"
+msgstr ""
+
+#: pvmove.c:455
+msgid "ABORTING: Removal of temporary pvmove LV failed"
+msgstr ""
+
+#: pvmove.c:460
+msgid "Writing out final volume group after pvmove"
+msgstr ""
+
+#: pvmove.c:480
+#, c-format
+msgid "ABORTING: Can't reread PV %s"
+msgstr ""
+
+#: pvmove.c:516 toollib.c:1074
+msgid "Failed to clone PV name"
+msgstr ""
+
+#: pvremove.c:41 vgsplit.c:107
+#, c-format
+msgid "Physical Volume %s not found"
+msgstr ""
+
+#: pvremove.c:52
+#, c-format
+msgid ""
+"Can't pvremove physical volume \"%s\" of volume group \"%s\" without -ff"
+msgstr ""
+
+#: pvremove.c:60
+#, c-format
+msgid "%s: physical volume label not removed"
+msgstr ""
+
+#: pvremove.c:65
+#, c-format
+msgid "WARNING: Wiping physical volume label from %s%s%s%s"
+msgstr ""
+
+#: pvremove.c:95
+#, c-format
+msgid "Can't open %s exclusively - not removing. Mounted filesystem?"
+msgstr ""
+
+#: pvremove.c:102
+#, c-format
+msgid "Failed to wipe existing label(s) on %s"
+msgstr ""
+
+#: pvremove.c:106
+#, c-format
+msgid "Labels on physical volume \"%s\" successfully wiped"
+msgstr ""
+
+#: pvresize.c:60
+#, c-format
+msgid "%s: too many metadata areas for pvresize"
+msgstr ""
+
+#: pvresize.c:113
+#, c-format
+msgid "Physical volume %s format does not support resizing."
+msgstr ""
+
+#: pvresize.c:130
+#, c-format
+msgid "%s: Pretending size is %lu not %lu sectors."
+msgstr ""
+
+#: pvresize.c:143
+#, c-format
+msgid "%s: Size must exceed physical extent start of %lu sectors."
+msgstr ""
+
+#: pvresize.c:156
+#, c-format
+msgid ""
+"%s: Size must leave space for at least one physical extent of %u sectors."
+msgstr ""
+
+#: pvresize.c:171
+#, c-format
+msgid "Resizing volume \"%s\" to %lu sectors."
+msgstr ""
+
+#: pvresize.c:207
+msgid "Please supply physical volume(s)"
+msgstr ""
+
+#: pvresize.c:224
+#, c-format
+msgid "%d physical volume(s) resized / %d physical volume(s) not resized"
+msgstr ""
+
+#: pvscan.c:66
+#, c-format
+msgid "PV %-*s    %-*s %s [%s]"
+msgstr ""
+
+#: pvscan.c:76
+#, c-format
+msgid "PV %-*s  is in exported VG %s [%s / %s free]"
+msgstr ""
+
+#: pvscan.c:89
+#, c-format
+msgid "PV %-*s VG %-*s %s [%s / %s free]"
+msgstr ""
+
+#: pvscan.c:117
+msgid "Options -e and -n are incompatible"
+msgstr ""
+
+#: pvscan.c:122
+#, c-format
+msgid "WARNING: only considering physical volumes %s"
+msgstr ""
+
+#: pvscan.c:129
+msgid "Walking through all physical volumes"
+msgstr ""
+
+#: pvscan.c:182
+msgid "No matching physical volumes found"
+msgstr ""
+
+#: pvscan.c:186
+#, c-format
+msgid "Total: %d [%s] / in use: %d [%s] / in no VG: %d [%s]"
+msgstr ""
+
+#: report/report.c:118
+msgid "Extent number dm_snprintf failed"
+msgstr ""
+
+#: report/report.c:182
+msgid "modules str_list allocation failed"
+msgstr ""
+
+#: report/report.c:259 report/report.c:342 report/report.c:368
+#: report/report.c:466 report/report.c:523 report/report.c:553
+#: report/report.c:694 report/report.c:750 report/report.c:768
+#: report/report.c:793 report/report.c:807
+msgid "dm_pool_alloc failed"
+msgstr ""
+
+#: report/report.c:471
+msgid "lvname snprintf failed"
+msgstr ""
+
+#: report/report.c:476 report/report.c:518 report/report.c:548
+msgid "dm_pool_strdup failed"
+msgstr ""
+
+#: report/report.c:773
+msgid "snapshot percentage too large"
+msgstr ""
+
+#: report/report.c:812
+msgid "copy percentage too large"
+msgstr ""
+
+#: reporter.c:24 reporter.c:146 reporter.c:158
+#, c-format
+msgid "Volume group %s not found"
+msgstr ""
+
+#: reporter.c:254
+#, c-format
+msgid "Invalid options string: %s"
+msgstr ""
+
+#: reporter.c:260
+msgid "options string allocation failed"
+msgstr ""
+
+#: reporter.c:297
+msgid "Can't report LV and PV fields at the same time"
+msgstr ""
+
+#: snapshot/snapshot.c:40
+msgid "Couldn't read chunk size for snapshot."
+msgstr ""
+
+#: snapshot/snapshot.c:48
+msgid "Snapshot cow storage not specified."
+msgstr ""
+
+#: snapshot/snapshot.c:54
+msgid "Snapshot origin not specified."
+msgstr ""
+
+#: snapshot/snapshot.c:61
+msgid "Unknown logical volume specified for snapshot cow store."
+msgstr ""
+
+#: snapshot/snapshot.c:67
+msgid "Unknown logical volume specified for snapshot origin."
+msgstr ""
+
+#: snapshot/snapshot.c:135
+msgid "snapshot string list allocation failed"
+msgstr ""
+
+#: striped/striped.c:41
+#, c-format
+msgid "  Stripes\t\t%u"
+msgstr ""
+
+#: striped/striped.c:42
+#, c-format
+msgid "  Stripe size\t\t%u KB"
+msgstr ""
+
+#: striped/striped.c:45
+#, c-format
+msgid "  Stripe %d:"
+msgstr ""
+
+#: striped/striped.c:55
+#, c-format
+msgid "Couldn't read 'stripe_count' for segment '%s'."
+msgstr ""
+
+#: striped/striped.c:70
+#, c-format
+msgid "Couldn't read stripe_size for segment '%s'."
+msgstr ""
+
+#: striped/striped.c:76
+#, c-format
+msgid "Couldn't find stripes array for segment '%s'."
+msgstr ""
+
+#: striped/striped.c:163
+#, c-format
+msgid "Internal error: striped add_target_line called with no areas for %s."
+msgstr ""
+
+#: stub.h:24 stub.h:31
+msgid "Command not implemented yet."
+msgstr ""
+
+#: stub.h:38
+msgid "There's no 'pvdata' command in LVM2."
+msgstr ""
+
+#: stub.h:39
+msgid ""
+"Use lvs, pvs, vgs instead; or use vgcfgbackup and read the text file backup."
+msgstr ""
+
+#: stub.h:40
+msgid ""
+"Metadata in LVM1 format can still be displayed using LVM1's pvdata command."
+msgstr ""
+
+#: toollib.c:115
+#, c-format
+msgid "skip_dev_dir: Couldn't split up device name %s"
+msgstr ""
+
+#: toollib.c:124 toollib.c:322
+msgid "vg/lv string alloc failed"
+msgstr ""
+
+#: toollib.c:215
+msgid "One or more specified logical volume(s) not found."
+msgstr ""
+
+#: toollib.c:251
+msgid "Using logical volume(s) on command line"
+msgstr ""
+
+#: toollib.c:264 toollib.c:540 toollib.c:689 toollib.c:1051
+#, c-format
+msgid "Skipping invalid tag %s"
+msgstr ""
+
+#: toollib.c:281 toollib.c:807 toollib.c:818
+#, c-format
+msgid "\"%s\": Invalid path for Logical Volume"
+msgstr ""
+
+#: toollib.c:335
+msgid "Finding all logical volumes"
+msgstr ""
+
+#: toollib.c:337 toollib.c:572
+msgid "No volume groups found"
+msgstr ""
+
+#: toollib.c:357 toollib.c:483 toollib.c:731 vgcfgbackup.c:59 vgck.c:24
+#: vgreduce.c:505 vgscan.c:23
+#, c-format
+msgid "Volume group \"%s\" not found"
+msgstr ""
+
+#: toollib.c:369 vgchange.c:523 vgck.c:29 vgconvert.c:43 vgscan.c:30
+#, c-format
+msgid "Volume group \"%s\" inconsistent"
+msgstr ""
+
+#: toollib.c:534
+msgid "Using volume group(s) on command line"
+msgstr ""
+
+#: toollib.c:555
+#, c-format
+msgid "Invalid volume group name: %s"
+msgstr ""
+
+#: toollib.c:570
+msgid "Finding all volume groups"
+msgstr ""
+
+#: toollib.c:705 toollib.c:1080
+#, c-format
+msgid "Physical Volume \"%s\" not found in Volume Group \"%s\""
+msgstr ""
+
+#: toollib.c:716
+#, c-format
+msgid "Failed to read physical volume \"%s\""
+msgstr ""
+
+#: toollib.c:755
+msgid "Using all physical volume(s) in volume group"
+msgstr ""
+
+#: toollib.c:825
+msgid "Allocation of vg_name failed"
+msgstr ""
+
+#: toollib.c:835
+#, c-format
+msgid "Path required for Logical Volume \"%s\""
+msgstr ""
+
+#: toollib.c:858
+#, c-format
+msgid "Environment Volume Group in LVM_VG_NAME invalid: \"%s\""
+msgstr ""
+
+#: toollib.c:874
+#, c-format
+msgid "Adding PE range: start PE %u length %u on %s"
+msgstr ""
+
+#: toollib.c:882
+#, c-format
+msgid "Overlapping PE ranges specified (%u-%u, %u-%u) on %s"
+msgstr ""
+
+#: toollib.c:892 toollib.c:1039 toollib.c:1103
+msgid "Allocation of list failed"
+msgstr ""
+
+#: toollib.c:956
+#, c-format
+msgid "PE range error: start extent %u to end extent %u"
+msgstr ""
+
+#: toollib.c:971
+#, c-format
+msgid "Physical extent parsing error at %s"
+msgstr ""
+
+#: toollib.c:984
+#, c-format
+msgid "Physical volume %s not allocatable"
+msgstr ""
+
+#: toollib.c:990
+#, c-format
+msgid "No free extents on physical volume \"%s\""
+msgstr ""
+
+#: toollib.c:1002 toollib.c:1110
+msgid "Unable to allocate physical volume list."
+msgstr ""
+
+#: toollib.c:1009
+msgid "Allocation of pe_ranges list failed"
+msgstr ""
+
+#: toollib.c:1091
+msgid "No specified PVs have space available"
+msgstr ""
+
+#: toollib.c:1137
+#, c-format
+msgid "Can't lock %s for metadata recovery: skipping"
+msgstr ""
+
+#: toollib.c:1148
+msgid ""
+"Names starting \"snapshot\" are reserved. Please choose a different LV name."
+msgstr ""
+
+#: toollib.c:1154
+msgid ""
+"Names starting \"pvmove\" are reserved. Please choose a different LV name."
+msgstr ""
+
+#: toollib.c:1160
+msgid ""
+"Names including \"_mlog\" are reserved. Please choose a different LV name."
+msgstr ""
+
+#: toollib.c:1166
+msgid ""
+"Names including \"_mimage\" are reserved. Please choose a different LV name."
+msgstr ""
+
+#: toollib.c:1183
+#, c-format
+msgid "%s: already exists in filesystem"
+msgstr ""
+
+#: toollib.c:1227
+msgid "Name allocation failed - device not cleared"
+msgstr ""
+
+#: toollib.c:1233
+#, c-format
+msgid "Name too long - device not cleared (%s)"
+msgstr ""
+
+#: toollib.c:1237
+#, c-format
+msgid "Clearing start of logical volume \"%s\""
+msgstr ""
+
+#: toollib.c:1240
+#, c-format
+msgid "%s: not found: device not cleared"
+msgstr ""
+
+#: toollib.c:1276
+#, c-format
+msgid "Name allocation failed - log header not written (%s)"
+msgstr ""
+
+#: toollib.c:1283
+#, c-format
+msgid "Name too long - log header not written (%s)"
+msgstr ""
+
+#: toollib.c:1287
+#, c-format
+msgid "Writing log header to device, %s"
+msgstr ""
+
+#: toollib.c:1290
+#, c-format
+msgid "%s: not found: log header not written"
+msgstr ""
+
+#: toollib.c:1298
+#, c-format
+msgid "Failed to write log header to %s"
+msgstr ""
+
+#: toollib.c:1324
+msgid "log_name allocation failed. Remove new LV and retry."
+msgstr ""
+
+#: toollib.c:1344
+msgid "Aborting. Unable to tag mirror log."
+msgstr ""
+
+#: toollib.c:1362
+msgid ""
+"Aborting. Unable to create in-sync mirror log while activation is disabled."
+msgstr ""
+
+#: toollib.c:1368
+msgid "Aborting. Failed to activate mirror log. Remove new LVs and retry."
+msgstr ""
+
+#: toollib.c:1375
+#, c-format
+msgid "Failed to remove tag %s from mirror log."
+msgstr ""
+
+#: toollib.c:1380
+msgid "Aborting. Failed to wipe mirror log. Remove new LV and retry."
+msgstr ""
+
+#: toollib.c:1386
+msgid "Aborting. Failed to write mirror log header. Remove new LV and retry."
+msgstr ""
+
+#: toollib.c:1392
+msgid "Aborting. Failed to deactivate mirror log. Remove new LV and retry."
+msgstr ""
+
+#: uuid/uuid.c:132
+msgid "UUID contains invalid character"
+msgstr ""
+
+#: uuid/uuid.c:156
+msgid "Couldn't write uuid, buffer too small."
+msgstr ""
+
+#: uuid/uuid.c:184
+msgid "Too many characters to be uuid."
+msgstr ""
+
+#: uuid/uuid.c:192
+msgid "Couldn't read uuid, incorrect number of characters."
+msgstr ""
+
+#: vgcfgbackup.c:27
+msgid "Failed to allocate filename."
+msgstr ""
+
+#: vgcfgbackup.c:32
+#, c-format
+msgid "Error processing filename template %s"
+msgstr ""
+
+#: vgcfgbackup.c:39
+#, c-format
+msgid ""
+"VGs must be backed up into different files. Use %%s in filename for VG name."
+msgstr ""
+
+#: vgcfgbackup.c:64
+#, c-format
+msgid "Warning: Volume group \"%s\" inconsistent"
+msgstr ""
+
+#: vgcfgbackup.c:76
+msgid "No backup taken: specify filename with -f to backup an inconsistent VG"
+msgstr ""
+
+#: vgcfgbackup.c:90
+#, c-format
+msgid "Volume group \"%s\" successfully backed up."
+msgstr ""
+
+#: vgcfgrestore.c:23
+msgid "Please specify a *single* volume group to restore."
+msgstr ""
+
+#: vgcfgrestore.c:30 vgextend.c:45 vgreduce.c:469 vgsplit.c:228
+#, c-format
+msgid "Volume group name \"%s\" is invalid"
+msgstr ""
+
+#: vgcfgrestore.c:46
+msgid "Unable to lock orphans"
+msgstr ""
+
+#: vgcfgrestore.c:51
+#, c-format
+msgid "Unable to lock volume group %s"
+msgstr ""
+
+#: vgcfgrestore.c:62
+msgid "Restore failed."
+msgstr ""
+
+#: vgcfgrestore.c:66
+#, c-format
+msgid "Restored volume group %s"
+msgstr ""
+
+#: vgchange.c:92
+#, c-format
+msgid "Spawning background process for %s %s"
+msgstr ""
+
+#: vgchange.c:111
+#, c-format
+msgid "%d logical volume(s) in volume group \"%s\" %smonitored"
+msgstr ""
+
+#: vgchange.c:132
+#, c-format
+msgid "Can't deactivate volume group \"%s\" with %d open logical volume(s)"
+msgstr ""
+
+#: vgchange.c:138
+#, c-format
+msgid "Locking inactive: ignoring clustered volume group %s"
+msgstr ""
+
+#: vgchange.c:148
+#, c-format
+msgid "%d logical volume(s) in volume group \"%s\" already active"
+msgstr ""
+
+#: vgchange.c:152
+#, c-format
+msgid "%d existing logical volume(s) in volume group \"%s\" %smonitored"
+msgstr ""
+
+#: vgchange.c:160
+#, c-format
+msgid "Activated logical volumes in volume group \"%s\""
+msgstr ""
+
+#: vgchange.c:164
+#, c-format
+msgid "Deactivated logical volumes in volume group \"%s\""
+msgstr ""
+
+#: vgchange.c:167
+#, c-format
+msgid "%d logical volume(s) in volume group \"%s\" now active"
+msgstr ""
+
+#: vgchange.c:179 vgcreate.c:47
+msgid "Volume Group allocation policy cannot inherit from anything"
+msgstr ""
+
+#: vgchange.c:185
+#, c-format
+msgid "Volume group allocation policy is already %s"
+msgstr ""
+
+#: vgchange.c:200 vgchange.c:235 vgchange.c:282 vgchange.c:324 vgchange.c:371
+#: vgchange.c:429 vgchange.c:471 vgchange.c:504
+#, c-format
+msgid "Volume group \"%s\" successfully changed"
+msgstr ""
+
+#: vgchange.c:211
+#, c-format
+msgid "Volume group \"%s\" is already resizeable"
+msgstr ""
+
+#: vgchange.c:217
+#, c-format
+msgid "Volume group \"%s\" is already not resizeable"
+msgstr ""
+
+#: vgchange.c:247
+#, c-format
+msgid "Volume group \"%s\" is already clustered"
+msgstr ""
+
+#: vgchange.c:253
+#, c-format
+msgid "Volume group \"%s\" is already not clustered"
+msgstr ""
+
+#: vgchange.c:261
+#, c-format
+msgid "Volume group %s contains snapshots that are not yet supported."
+msgstr ""
+
+#: vgchange.c:293
+#, c-format
+msgid "Volume group \"%s\" must be resizeable to change MaxLogicalVolume"
+msgstr ""
+
+#: vgchange.c:302
+msgid "MaxLogicalVolume limit is 255"
+msgstr ""
+
+#: vgchange.c:308
+#, c-format
+msgid "MaxLogicalVolume is less than the current number %d of LVs for \"%s\""
+msgstr ""
+
+#: vgchange.c:335
+#, c-format
+msgid "Volume group \"%s\" must be resizeable to change MaxPhysicalVolumes"
+msgstr ""
+
+#: vgchange.c:341
+msgid "MaxPhysicalVolumes may not be negative"
+msgstr ""
+
+#: vgchange.c:349
+msgid "MaxPhysicalVolume limit is 255"
+msgstr ""
+
+#: vgchange.c:355
+#, c-format
+msgid "MaxPhysicalVolumes is less than the current number %d of PVs for \"%s\""
+msgstr ""
+
+#: vgchange.c:381
+#, c-format
+msgid "Volume group \"%s\" must be resizeable to change PE size"
+msgstr ""
+
+#: vgchange.c:387 vgcreate.c:64
+msgid "Physical extent size may not be negative"
+msgstr ""
+
+#: vgchange.c:393 vgcreate.c:83
+msgid "Physical extent size may not be zero"
+msgstr ""
+
+#: vgchange.c:398
+#, c-format
+msgid "Physical extent size of VG %s is already %s"
+msgstr ""
+
+#: vgchange.c:404
+msgid "Physical extent size must be a power of 2."
+msgstr ""
+
+#: vgchange.c:411
+msgid "New extent size is not a perfect fit"
+msgstr ""
+
+#: vgchange.c:454 vgcreate.c:117
+#, c-format
+msgid "Failed to add tag %s to volume group %s"
+msgstr ""
+
+#: vgchange.c:460
+#, c-format
+msgid "Failed to remove tag %s from volume group %s"
+msgstr ""
+
+#: vgchange.c:482
+msgid "Volume group has active logical volumes"
+msgstr ""
+
+#: vgchange.c:490
+#, c-format
+msgid "Failed to generate new random UUID for VG %s."
+msgstr ""
+
+#: vgchange.c:516 vgconvert.c:36 vgexport.c:27
+#, c-format
+msgid "Unable to find volume group \"%s\""
+msgstr ""
+
+#: vgchange.c:588
+msgid ""
+"One of -a, -c, -l, -p, -s, -x, --uuid, --alloc, --addtag or --deltag required"
+msgstr ""
+
+#: vgchange.c:600
+msgid ""
+"Only one of -a, -c, -l, -p, -s, -x, --uuid, --alloc, --addtag or --deltag "
+"allowed"
+msgstr ""
+
+#: vgchange.c:607
+msgid "--ignorelockingfailure only available with -a"
+msgstr ""
+
+#: vgchange.c:613
+msgid "-A option not necessary with -a option"
+msgstr ""
+
+#: vgconvert.c:59
+#, c-format
+msgid "Volume group \"%s\" already uses format %s"
+msgstr ""
+
+#: vgconvert.c:87
+#, c-format
+msgid "Archive of \"%s\" metadata failed."
+msgstr ""
+
+#: vgconvert.c:100
+#, c-format
+msgid "Logical volume %s must be deactivated before conversion."
+msgstr ""
+
+#: vgconvert.c:130 vgconvert.c:145 vgconvert.c:157 vgconvert.c:170
+#: vgconvert.c:186
+msgid "Use pvcreate and vgcfgrestore to repair from archived metadata."
+msgstr ""
+
+#: vgconvert.c:166
+#, c-format
+msgid "Deleting existing metadata for VG %s"
+msgstr ""
+
+#: vgconvert.c:168
+#, c-format
+msgid "Removal of existing metadata for %s failed."
+msgstr ""
+
+#: vgconvert.c:177
+#, c-format
+msgid "Test mode: Skipping metadata writing for VG %s in format %s"
+msgstr ""
+
+#: vgconvert.c:182
+#, c-format
+msgid "Writing metadata for VG %s using format %s"
+msgstr ""
+
+#: vgconvert.c:185
+#, c-format
+msgid "Conversion failed for volume group %s."
+msgstr ""
+
+#: vgconvert.c:190
+#, c-format
+msgid "Volume group %s successfully converted"
+msgstr ""
+
+#: vgconvert.c:200
+msgid "Please enter volume group(s)"
+msgstr ""
+
+#: vgcreate.c:31
+msgid "Please provide volume group name and physical volumes"
+msgstr ""
+
+#: vgcreate.c:37
+msgid "Please enter physical volume name(s)"
+msgstr ""
+
+#: vgcreate.c:58
+msgid "Number of volumes may not exceed 255"
+msgstr ""
+
+#: vgcreate.c:69
+msgid "Max Logical Volumes may not be negative"
+msgstr ""
+
+#: vgcreate.c:74
+msgid "Max Physical Volumes may not be negative"
+msgstr ""
+
+#: vgcreate.c:88 vgrename.c:52 vgsplit.c:290
+#, c-format
+msgid "New volume group name \"%s\" is invalid"
+msgstr ""
+
+#: vgcreate.c:98
+#, c-format
+msgid "Warning: Setting maxlogicalvolumes to %d (0 means unlimited)"
+msgstr ""
+
+#: vgcreate.c:102
+#, c-format
+msgid "Warning: Setting maxphysicalvolumes to %d (0 means unlimited)"
+msgstr ""
+
+#: vgcreate.c:112
+msgid "Volume group format does not support tags"
+msgstr ""
+
+#: vgcreate.c:163
+#, c-format
+msgid "Volume group \"%s\" successfully created"
+msgstr ""
+
+#: vgdisplay.c:29
+#, c-format
+msgid "WARNING: Volume group \"%s\" inconsistent"
+msgstr ""
+
+#: vgdisplay.c:32
+#, c-format
+msgid "WARNING: volume group \"%s\" is exported"
+msgstr ""
+
+#: vgdisplay.c:52
+msgid "--- Physical volumes ---"
+msgstr ""
+
+#: vgdisplay.c:81
+msgid "Option -c is not allowed with option -s"
+msgstr ""
+
+#: vgdisplay.c:86
+msgid "Option -A is not allowed with volume group names"
+msgstr ""
+
+#: vgexport.c:32
+#, c-format
+msgid "Volume group %s inconsistent"
+msgstr ""
+
+#: vgexport.c:37
+#, c-format
+msgid "Volume group \"%s\" is already exported"
+msgstr ""
+
+#: vgexport.c:47
+#, c-format
+msgid "Volume group \"%s\" has active logical volumes"
+msgstr ""
+
+#: vgexport.c:67
+#, c-format
+msgid "Volume group \"%s\" successfully exported"
+msgstr ""
+
+#: vgexport.c:78 vgimport.c:68
+msgid "Please supply volume groups or use -a for all."
+msgstr ""
+
+#: vgexport.c:83 vgimport.c:73
+msgid "No arguments permitted when using -a for all."
+msgstr ""
+
+#: vgextend.c:25
+msgid "Please enter volume group name and physical volume(s)"
+msgstr ""
+
+#: vgextend.c:31
+msgid "Please enter physical volume(s)"
+msgstr ""
+
+#: vgextend.c:50 vgmerge.c:32 vgmerge.c:63 vgsplit.c:238 vgsplit.c:275
+#, c-format
+msgid "Checking for volume group \"%s\""
+msgstr ""
+
+#: vgextend.c:58
+#, c-format
+msgid "Volume group \"%s\" not found."
+msgstr ""
+
+#: vgextend.c:79
+#, c-format
+msgid "Volume group \"%s\" is not resizeable."
+msgstr ""
+
+#: vgextend.c:98
+#, c-format
+msgid "Volume group \"%s\" will be extended by %d new physical volumes"
+msgstr ""
+
+#: vgextend.c:110
+#, c-format
+msgid "Volume group \"%s\" successfully extended"
+msgstr ""
+
+#: vgimport.c:27
+#, c-format
+msgid "Unable to find exported volume group \"%s\""
+msgstr ""
+
+#: vgimport.c:33
+#, c-format
+msgid "Volume group \"%s\" is not exported"
+msgstr ""
+
+#: vgimport.c:38
+#, c-format
+msgid "Volume group \"%s\" is partially missing"
+msgstr ""
+
+#: vgimport.c:57
+#, c-format
+msgid "Volume group \"%s\" successfully imported"
+msgstr ""
+
+#: vgmerge.c:28 vgsplit.c:234
+#, c-format
+msgid "Duplicate volume group name \"%s\""
+msgstr ""
+
+#: vgmerge.c:93 vgsplit.c:297
+#, c-format
+msgid "Logical volumes in \"%s\" must be inactive"
+msgstr ""
+
+#: vgmerge.c:100
+#, c-format
+msgid "Extent sizes differ: %d (%s) and %d (%s)"
+msgstr ""
+
+#: vgmerge.c:108
+#, c-format
+msgid "Maximum number of physical volumes (%d) exceeded  for \"%s\" and \"%s\""
+msgstr ""
+
+#: vgmerge.c:116
+#, c-format
+msgid "Maximum number of logical volumes (%d) exceeded  for \"%s\" and \"%s\""
+msgstr ""
+
+#: vgmerge.c:130
+#, c-format
+msgid "Duplicate logical volume name \"%s\" in \"%s\" and \"%s\""
+msgstr ""
+
+#: vgmerge.c:142 vgmerge.c:151
+#, c-format
+msgid "Physical volume %s might be constructed from same volume group %s."
+msgstr ""
+
+#: vgmerge.c:186
+#, c-format
+msgid "Failed to generate new random LVID for %s"
+msgstr ""
+
+#: vgmerge.c:197
+#, c-format
+msgid "Changed LVID for %s to %s"
+msgstr ""
+
+#: vgmerge.c:235
+#, c-format
+msgid "Volume group \"%s\" successfully merged into \"%s\""
+msgstr ""
+
+#: vgmerge.c:252
+msgid "Please enter 2 or more volume groups to merge"
+msgstr ""
+
+#: vgreduce.c:24
+msgid "Volume Groups must always contain at least one PV"
+msgstr ""
+
+#: vgreduce.c:33
+#, c-format
+msgid "Removing PV with UUID %s from VG %s"
+msgstr ""
+
+#: vgreduce.c:36
+#, c-format
+msgid "LVs still present on PV with UUID %s: Can't remove from VG %s"
+msgstr ""
+
+#: vgreduce.c:61
+#, c-format
+msgid "%s/%s has missing extents: removing (including dependencies)"
+msgstr ""
+
+#: vgreduce.c:68
+#, c-format
+msgid "Deactivating (if active) logical volume %s (origin of %s)"
+msgstr ""
+
+#: vgreduce.c:72 vgreduce.c:89 vgreduce.c:333
+#, c-format
+msgid "Failed to deactivate LV %s"
+msgstr ""
+
+#: vgreduce.c:99 vgreduce.c:146 vgreduce.c:348
+#, c-format
+msgid "Removing LV %s from VG %s"
+msgstr ""
+
+#: vgreduce.c:191
+#, c-format
+msgid "Non-mirror-image LV %s found: can't remove."
+msgstr ""
+
+#: vgreduce.c:207
+msgid "Aborting because --mirrorsonly was specified."
+msgstr ""
+
+#: vgreduce.c:232 vgreduce.c:529
+#, c-format
+msgid "Failed to write out a consistent VG for %s"
+msgstr ""
+
+#: vgreduce.c:250
+#, c-format
+msgid "Failed to commit consistent VG for %s"
+msgstr ""
+
+#: vgreduce.c:258
+msgid "Failed to resume LVs using error segments."
+msgstr ""
+
+#: vgreduce.c:290
+#, c-format
+msgid "The log device for %s/%s has failed."
+msgstr ""
+
+#: vgreduce.c:296
+#, c-format
+msgid "Log device for %s/%s has failed."
+msgstr ""
+
+#: vgreduce.c:312
+#, c-format
+msgid "Failed to write out updated VG for %s"
+msgstr ""
+
+#: vgreduce.c:318
+#, c-format
+msgid "Failed to commit updated VG for %s"
+msgstr ""
+
+#: vgreduce.c:329
+#, c-format
+msgid "Deactivating (if active) logical volume %s"
+msgstr ""
+
+#: vgreduce.c:371
+#, c-format
+msgid "Physical volume \"%s\" still in use"
+msgstr ""
+
+#: vgreduce.c:376
+#, c-format
+msgid "Can't remove final physical volume \"%s\" from volume group \"%s\""
+msgstr ""
+
+#: vgreduce.c:386
+#, c-format
+msgid "Removing \"%s\" from volume group \"%s\""
+msgstr ""
+
+#: vgreduce.c:404
+#, c-format
+msgid "Removal of physical volume \"%s\" from \"%s\" failed"
+msgstr ""
+
+#: vgreduce.c:418
+#, c-format
+msgid "Removed \"%s\" from volume group \"%s\""
+msgstr ""
+
+#: vgreduce.c:431
+msgid "Please give volume group name and physical volume paths"
+msgstr ""
+
+#: vgreduce.c:437
+msgid "Please give volume group name"
+msgstr ""
+
+#: vgreduce.c:443
+msgid "--mirrorsonly requires --removemissing"
+msgstr ""
+
+#: vgreduce.c:449
+msgid "Please enter physical volume paths or option -a"
+msgstr ""
+
+#: vgreduce.c:454
+msgid "Option -a and physical volume paths mutually exclusive"
+msgstr ""
+
+#: vgreduce.c:460
+msgid "Please only specify the volume group"
+msgstr ""
+
+#: vgreduce.c:496
+#, c-format
+msgid "Volume group \"%s\" is already consistent"
+msgstr ""
+
+#: vgreduce.c:537
+#, c-format
+msgid "Wrote out consistent volume group %s"
+msgstr ""
+
+#: vgreduce.c:553
+#, c-format
+msgid "Volume group \"%s\" is not reducible"
+msgstr ""
+
+#: vgremove.c:27
+#, c-format
+msgid "Volume group \"%s\" not found or inconsistent."
+msgstr ""
+
+#: vgremove.c:29
+msgid "Consider vgreduce --removemissing if metadata is inconsistent."
+msgstr ""
+
+#: vgremove.c:40
+#, c-format
+msgid "Volume group \"%s\" still contains %d logical volume(s)"
+msgstr ""
+
+#: vgremove.c:49
+#, c-format
+msgid "vg_remove %s failed"
+msgstr ""
+
+#: vgremove.c:56
+#, c-format
+msgid "Removing physical volume \"%s\" from volume group \"%s\""
+msgstr ""
+
+#: vgremove.c:69
+#, c-format
+msgid "Failed to remove physical volume \"%s\" from volume group \"%s\""
+msgstr ""
+
+#: vgremove.c:79
+#, c-format
+msgid "Volume group \"%s\" successfully removed"
+msgstr ""
+
+#: vgremove.c:81
+#, c-format
+msgid "Volume group \"%s\" not properly removed"
+msgstr ""
+
+#: vgremove.c:91
+msgid "Please enter one or more volume group paths"
+msgstr ""
+
+#: vgrename.c:34
+msgid "Old and new volume group names need specifying"
+msgstr ""
+
+#: vgrename.c:46
+#, c-format
+msgid "New volume group path exceeds maximum length of %d!"
+msgstr ""
+
+#: vgrename.c:58
+msgid "Old and new volume group names must differ"
+msgstr ""
+
+#: vgrename.c:66
+msgid "No complete volume groups found"
+msgstr ""
+
+#: vgrename.c:76
+#, c-format
+msgid "Found more than one VG called %s. Please supply VG uuid."
+msgstr ""
+
+#: vgrename.c:99
+#, c-format
+msgid "Volume group %s %s%s%snot found."
+msgstr ""
+
+#: vgrename.c:123
+#, c-format
+msgid "Volume group \"%s\" still has active LVs"
+msgstr ""
+
+#: vgrename.c:129
+#, c-format
+msgid "Checking for new volume group \"%s\""
+msgstr ""
+
+#: vgrename.c:139
+#, c-format
+msgid "New volume group \"%s\" already exists"
+msgstr ""
+
+#: vgrename.c:154
+#, c-format
+msgid "Renaming \"%s\" to \"%s\""
+msgstr ""
+
+#: vgrename.c:156
+msgid "Test mode: Skipping rename."
+msgstr ""
+
+#: vgrename.c:158
+#, c-format
+msgid "Renaming \"%s\" to \"%s\" failed: %s"
+msgstr ""
+
+#: vgrename.c:177
+#, c-format
+msgid "Volume group \"%s\" successfully renamed to \"%s\""
+msgstr ""
+
+#: vgscan.c:36
+#, c-format
+msgid "Found %svolume group \"%s\" using metadata type %s"
+msgstr ""
+
+#: vgscan.c:50
+msgid "Too many parameters on command line"
+msgstr ""
+
+#: vgscan.c:57
+msgid "Reading all physical volumes.  This may take a while..."
+msgstr ""
+
+#: vgsplit.c:25
+#, c-format
+msgid "Physical volume %s not in volume group %s"
+msgstr ""
+
+#: vgsplit.c:90
+#, c-format
+msgid "Can't split Logical Volume %s between two Volume Groups"
+msgstr ""
+
+#: vgsplit.c:152
+#, c-format
+msgid "Snapshot %s split"
+msgstr ""
+
+#: vgsplit.c:193
+#, c-format
+msgid "Mirror %s split"
+msgstr ""
+
+#: vgsplit.c:218
+msgid "Existing VG, new VG and physical volumes required."
+msgstr ""
+
+#: vgsplit.c:264
+#, c-format
+msgid "Volume group \"%s\" is not resizeable"
+msgstr ""
+
+#: vgsplit.c:285
+#, c-format
+msgid "Volume group \"%s\" already exists"
+msgstr ""
+
+#: vgsplit.c:339
+msgid "Cannot split: Nowhere to store metadata for new Volume Group"
+msgstr ""
+
+#: vgsplit.c:348
+msgid "Writing out updated volume groups"
+msgstr ""
+
+#: vgsplit.c:370
+#, c-format
+msgid "Volume group \"%s\" became inconsistent: please fix manually"
+msgstr ""
+
+#: vgsplit.c:385
+#, c-format
+msgid "Volume group \"%s\" successfully split from \"%s\""
+msgstr ""
+
+#: zero/zero.c:71
+msgid "zero module string list allocation failed"
+msgstr ""
Index: src/external/gpl2/lvm2tools/dist/po/pogen.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/po/pogen.h
diff -N src/external/gpl2/lvm2tools/dist/po/pogen.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/po/pogen.h	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,25 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Macros to change log messages into a format that xgettext can handle.
+ *
+ * Note that different PRI* definitions lead to different strings for
+ * different architectures.
+ */
+
+#define print_log(level, file, line, format, args...) print_log(format, args)
+#define dm_log(level, file, line, format, args...) dm_log(format, args)
Index: src/external/gpl2/lvm2tools/dist/scripts/Makefile.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/scripts/Makefile.in
diff -N src/external/gpl2/lvm2tools/dist/scripts/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/scripts/Makefile.in	12 Dec 2008 16:33:03 -0000	1.1.1.1.2.1
@@ -0,0 +1,26 @@
+#
+# Copyright (C) 2006 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+include $(top_srcdir)/make.tmpl
+
+install:
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) lvm_dump.sh \
+		$(sbindir)/lvmdump
+ifeq ("@FSADM@", "yes")
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) fsadm.sh \
+		$(sbindir)/fsadm
+endif
Index: src/external/gpl2/lvm2tools/dist/scripts/clvmd_fix_conf.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/scripts/clvmd_fix_conf.sh
diff -N src/external/gpl2/lvm2tools/dist/scripts/clvmd_fix_conf.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/scripts/clvmd_fix_conf.sh	15 Jul 2008 13:50:08 -0000	1.1.1.1
@@ -0,0 +1,162 @@
+#!/bin/sh
+#
+# Edit an lvm.conf file to enable cluster locking.
+#
+# $1 is the directory where the locking library is installed.
+# $2 (optional) is the config file
+# $3 (optional) is the locking library name
+#
+#
+PREFIX=$1
+LVMCONF=$2
+LIB=$3
+
+if [ -z "$PREFIX" ]
+then
+  echo "usage: $0 <prefix> [<config file>] [<library>]"
+  echo ""
+  echo "<prefix>|UNDO  location of the cluster locking shared library. (no default)"
+  echo "               UNDO will reset the locking back to local"
+  echo "<config file>  name of the LVM config file (default: /etc/lvm/lvm.conf)"
+  echo "<library>      name of the shared library (default: liblvm2clusterlock.so)"
+  echo ""
+  exit 0
+fi
+
+[ -z "$LVMCONF" ] && LVMCONF="/etc/lvm/lvm.conf"
+[ -z "$LIB" ] && LIB="liblvm2clusterlock.so"
+
+if [ "$PREFIX" = "UNDO" ]
+then
+  locking_type="1"
+else
+  locking_type="2"
+
+  if [ "${PREFIX:0:1}" != "/" ]
+  then
+    echo "Prefix must be an absolute path name (starting with a /)"
+    exit 12
+  fi
+
+  if [ ! -f "$PREFIX/$LIB" ]
+  then
+    echo "$PREFIX/$LIB does not exist, did you do a \"make install\" ?"
+    exit 11
+  fi
+fi
+
+if [ ! -f "$LVMCONF" ]
+then
+  echo "$LVMCONF does not exist"
+  exit 10
+fi
+
+
+SCRIPTFILE=`mktemp -t lvmscript.XXXXXXXXXX`
+TMPFILE=`mktemp -t lvmtmp.XXXXXXXXXX`
+
+
+# Flags so we know which parts of the file we can replace and which need
+# adding. These are return codes from grep, so zero means it IS present!
+have_type=1
+have_dir=1
+have_library=1
+have_global=1
+
+grep -q '^[[:blank:]]*locking_type[[:blank:]]*=' $LVMCONF
+have_type=$?
+
+grep -q '^[[:blank:]]*library_dir[[:blank:]]*=' $LVMCONF
+have_dir=$?
+
+grep -q '^[[:blank:]]*locking_library[[:blank:]]*=' $LVMCONF
+have_library=$?
+
+# Those options are in section "global {" so we must have one if any are present.
+if [ "$have_type" = "0" -o "$have_dir" = "0" -o "$have_library" = "0" ]
+then
+
+    # See if we can find it...
+    grep -q '^[[:blank:]]*global[[:blank:]]*{' $LVMCONF
+    have_global=$?
+    
+    if [ "$have_global" = "1" ] 
+	then
+	echo "global keys but no 'global {' found, can't edit file"
+	exit 12
+    fi
+fi
+
+# So if we don't have "global {" we need to create one and 
+# populate it
+
+if [ "$have_global" = "1" ]
+then
+    cat $LVMCONF - <<EOF > $TMPFILE
+global {
+    # Enable locking for cluster LVM
+    locking_type = $locking_type
+    library_dir = "$PREFIX"
+    locking_library = "$LIB"
+}
+EOF
+    if [ $? != 0 ]
+    then
+	echo "failed to create temporary config file, $LVMCONF not updated"
+	exit 1
+    fi
+else
+    #
+    # We have a "global {" section, so add or replace the
+    # locking entries as appropriate
+    #
+
+    if [ "$have_type" = "0" ] 
+    then
+	SEDCMD=" s/^[[:blank:]]*locking_type[[:blank:]]*=.*/\ \ \ \ locking_type = $locking_type/g"
+    else
+	SEDCMD=" /global[[:blank:]]*{/a\ \ \ \ locking_type = 2"
+    fi
+    
+    if [ "$have_dir" = "0" ] 
+    then
+	SEDCMD="${SEDCMD}\ns'^[[:blank:]]*library_dir[[:blank:]]*=.*'\ \ \ \ library_dir = \"$PREFIX\"'g"
+    else
+	SEDCMD="${SEDCMD}\n/global[[:blank:]]*{/a\ \ \ \ library_dir = \"$PREFIX\""
+    fi
+
+    if [ "$have_library" = "0" ] 
+    then
+	SEDCMD="${SEDCMD}\ns/^[[:blank:]]*locking_library[[:blank:]]*=.*/\ \ \ \ locking_library = \"$LIB\"/g"
+    else
+	SEDCMD="${SEDCMD}\n/global[[:blank:]]*{/a\ \ \ \ locking_library = \"$LIB\""
+    fi
+
+    echo -e $SEDCMD > $SCRIPTFILE
+    sed  <$LVMCONF >$TMPFILE -f $SCRIPTFILE
+    if [ $? != 0 ]
+    then
+	echo "sed failed, $LVMCONF not updated"
+	exit 1
+    fi
+fi
+
+# Now we have a suitably editted config file in a temp place,
+# backup the original and copy our new one into place.
+
+cp $LVMCONF $LVMCONF.nocluster
+if [ $? != 0 ]
+    then
+    echo "failed to backup old config file, $LVMCONF not updated"
+    exit 2
+fi
+
+cp $TMPFILE $LVMCONF
+if [ $? != 0 ]
+    then
+    echo "failed to copy new config file into place, check $LVMCONF is still OK"
+    exit 3
+fi
+
+rm -f $SCRIPTFILE $TMPFILE
+
Index: src/external/gpl2/lvm2tools/dist/scripts/clvmd_init
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/scripts/clvmd_init
diff -N src/external/gpl2/lvm2tools/dist/scripts/clvmd_init
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/scripts/clvmd_init	15 Jul 2008 13:50:08 -0000	1.1.1.1
@@ -0,0 +1,90 @@
+#!/bin/bash
+#
+#	/etc/rc.d/init.d/clvmd
+#
+# Starts the clvm daemon
+# NOTE: These startup levels may not be right yet - it depends on where
+#       the rest of the cluster startup goes.
+#
+# chkconfig: 345 72 5
+# description: distributes LVM commands in a clustered environment. \
+#    a clvmd must be run on all nodes in a cluster for clustered LVM \
+#    operations to work.
+# processname: clvmd
+
+# Source function library.
+. /etc/init.d/functions
+
+BINARY=/usr/sbin/clvmd
+LOCKFILE=/var/lock/subsys/clvmd
+
+test -x "$BINARY" || exit 0
+
+RETVAL=0
+
+#
+#	See how we were called.
+#
+
+prog="clvmd"
+
+start() {
+	# Check if clvmd is already running
+	if [ ! -f "$LOCKFILE" ]; then
+	    echo -n $"Starting $prog: "
+	    daemon $BINARY
+	    RETVAL=$?
+	    [ $RETVAL -eq 0 ] && touch $LOCKFILE
+	    echo
+	fi
+	return $RETVAL
+}
+
+stop() {
+	echo -n $"Stopping $prog: "
+	killproc $BINARY
+	RETVAL=$?
+	[ $RETVAL -eq 0 ] && rm -f $LOCKFILE
+	echo
+        return $RETVAL
+}
+
+
+restart() {
+	stop
+	start
+}	
+
+reload() {
+	restart
+}	
+
+status_clvm() {
+ 	status $BINARY
+}
+
+case "$1" in
+start)
+	start
+	;;
+stop)
+	stop
+	;;
+reload|restart)
+	restart
+	;;
+condrestart)
+	if [ -f $LOCKFILE ]; then
+	    restart
+	fi
+	;;
+status)
+	status_clvm
+	;;
+*)
+	echo $"Usage: $0 {start|stop|restart|condrestart|status}"
+	exit 1
+esac
+
+exit $?
+exit $RETVAL
Index: src/external/gpl2/lvm2tools/dist/scripts/clvmd_init_rhel4
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/scripts/clvmd_init_rhel4
diff -N src/external/gpl2/lvm2tools/dist/scripts/clvmd_init_rhel4
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/scripts/clvmd_init_rhel4	15 Jul 2008 13:50:08 -0000	1.1.1.1
@@ -0,0 +1,140 @@
+#!/bin/bash
+#
+# chkconfig: - 24 76
+# description: Starts and stops clvmd
+#
+#	       
+### BEGIN INIT INFO
+# Provides: 
+### END INIT INFO
+
+. /etc/init.d/functions
+
+LVDISPLAY="/usr/sbin/lvdisplay"
+VGCHANGE="/usr/sbin/vgchange"
+VGSCAN="/usr/sbin/vgscan"
+VGDISPLAY="/usr/sbin/vgdisplay"
+VGS="/usr/sbin/vgs"
+CLVMDOPTS="-T20"
+
+[ -f /etc/sysconfig/cluster ] && . /etc/sysconfig/cluster
+
+LOCK_FILE="/var/lock/subsys/clvmd"
+
+start()
+{
+	for rtrn in 0
+	do
+		if ! pidof clvmd > /dev/null 
+		then 
+			echo -n "Starting clvmd: "
+			daemon clvmd $CLVMDOPTS
+			rtrn=$?
+			echo
+			if [ $rtrn -ne 0 ]
+			then
+				break
+			fi
+ 		fi	
+		# refresh cache
+		$VGSCAN  > /dev/null 2>&1
+		
+		if [ -n "$LVM_VGS" ]
+		then
+			for vg in $LVM_VGS
+			do
+				action "Activating VG $vg:" $VGCHANGE -ayl $vg || rtrn=$?
+			done
+		else
+			action "Activating VGs:" $VGCHANGE -ayl || rtrn=$?
+		fi
+	done
+
+	return $rtrn
+}
+
+stop()
+{
+	for rtrn in 0
+	do
+		if [ -n "$LVM_VGS" ]
+		then
+			for vg in $LVM_VGS
+			do
+				action "Deactivating VG $vg:" $VGCHANGE -anl $vg || rtrn=$?
+			done
+		else
+			# Hack to only deactivate clustered volumes
+			clustervgs=`$VGDISPLAY 2> /dev/null | awk 'BEGIN {RS="VG Name"} {if (/Clustered/) print $1;}'`
+			for vg in $clustervgs; do
+				action "Deactivating VG $vg:" $VGCHANGE -anl $vg || rtrn=$?
+			done
+		fi
+
+		[ $rtrn -ne 0 ] && break
+
+		echo -n "Stopping clvm:"
+		killproc clvmd -TERM
+		rtrn=$?
+		echo
+	done
+	
+	return $rtrn
+}
+
+wait_for_finish()
+{
+	count=0
+
+	while [ "$count" -le 10 -a -n "`pidof clvmd`" ]
+	do
+		sleep 1
+		count=$((count + 1))
+	done
+	
+	if [ `pidof clvmd` ]
+	then
+		return 1
+	else
+		return 0
+	fi
+}
+
+rtrn=1
+
+# See how we were called.
+case "$1" in
+  start)
+	start
+	rtrn=$?
+	[ $rtrn = 0 ] && touch $LOCK_FILE
+	;;
+
+  stop)
+	stop
+	rtrn=$?
+	[ $rtrn = 0 ] && rm -f $LOCK_FILE
+	;;
+
+  restart)
+	if stop
+	then
+		wait_for_finish
+		start
+	fi 
+	rtrn=$?
+	;;
+
+  status)
+	status clvmd
+	rtrn=$?
+	vols=$( $LVDISPLAY -C --nohead 2> /dev/null | awk '($3 ~ /....a./) {print $1}' )
+	echo active volumes: ${vols:-"(none)"}
+	;;
+
+  *)
+	echo $"Usage: $0 {start|stop|restart|status}"
+	;;
+esac
+
+exit $rtrn
Index: src/external/gpl2/lvm2tools/dist/scripts/fsadm.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/scripts/fsadm.sh
diff -N src/external/gpl2/lvm2tools/dist/scripts/fsadm.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/scripts/fsadm.sh	15 Jul 2008 13:50:08 -0000	1.1.1.1
@@ -0,0 +1,400 @@
+#!/bin/sh
+#
+# Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+# Author: Zdenek Kabelac <zkabelac at redhat.com>
+#
+# Script for resizing devices (usable for LVM resize)
+#
+# Needed utilities:
+#   mount, umount, grep, readlink, blockdev, blkid, fsck, xfs_check
+#
+# ext2/ext3: resize2fs, tune2fs
+# reiserfs: resize_reiserfs, reiserfstune
+# xfs: xfs_growfs, xfs_info
+#
+
+TOOL=fsadm
+
+PATH=/sbin:/usr/sbin:/bin:/usr/sbin:$PATH
+
+# utilities
+TUNE_EXT=tune2fs
+RESIZE_EXT=resize2fs
+TUNE_REISER=reiserfstune
+RESIZE_REISER=resize_reiserfs
+TUNE_XFS=xfs_info
+RESIZE_XFS=xfs_growfs
+
+MOUNT=mount
+UMOUNT=umount
+MKDIR=mkdir
+RMDIR=rmdir
+BLOCKDEV=blockdev
+BLKID=blkid
+GREP=grep
+CUT=cut
+READLINK=readlink
+READLINK_E="-e"
+FSCK=fsck
+XFS_CHECK=xfs_check
+
+LVRESIZE=lvresize
+
+YES=
+DRY=0
+VERB=
+FORCE=
+EXTOFF=0
+DO_LVRESIZE=0
+FSTYPE=unknown
+VOLUME=unknown
+TEMPDIR="${TMPDIR:-/tmp}/${TOOL}_${RANDOM}$$/m"
+BLOCKSIZE=
+BLOCKCOUNT=
+MOUNTPOINT=
+MOUNTED=
+REMOUNT=
+
+IFS_OLD=$IFS
+
+tool_usage() {
+	echo "${TOOL}: Utility to resize or check the filesystem on a device"
+	echo
+	echo "  ${TOOL} [options] check device"
+	echo "    - Check the filesystem on device using fsck"
+	echo
+	echo "  ${TOOL} [options] resize device [new_size[BKMGTPE]]"
+	echo "    - Change the size of the filesystem on device to new_size"
+	echo
+	echo "  Options:"
+	echo "    -h | --help         Show this help message"
+	echo "    -v | --verbose      Be verbose"
+	echo "    -e | --ext-offline  unmount filesystem before Ext2/3 resize"
+	echo "    -f | --force        Bypass sanity checks"
+	echo "    -n | --dry-run      Print commands without running them"
+	echo "    -l | --lvresize     Resize given device (if it is LVM device)"
+	echo "    -y | --yes          Answer \"yes\" at any prompts"
+	echo
+	echo "  new_size - Absolute number of filesystem blocks to be in the filesystem,"
+	echo "             or an absolute size using a suffix (in powers of 1024)."
+	echo "             If new_size is not supplied, the whole device is used."
+
+	exit
+}
+
+verbose() {
+	test -n "$VERB" && echo "$TOOL: $@" || true
+}
+
+error() {
+	echo "$TOOL: $@" >&2
+	cleanup 1
+}
+
+dry() {
+	if [ "$DRY" -ne 0 ]; then
+		verbose "Dry execution $@"
+		return 0
+	fi
+	verbose "Executing $@"
+	$@
+}
+
+cleanup() {
+	trap '' 2
+	# reset MOUNTPOINT - avoid recursion
+	test "$MOUNTPOINT" = "$TEMPDIR" && MOUNTPOINT="" temp_umount
+	if [ -n "$REMOUNT" ]; then
+		verbose "Remounting unmounted filesystem back"
+		dry $MOUNT "$VOLUME" "$MOUNTED"
+	fi
+	IFS=$IFS_OLD
+	trap 2
+
+	# start LVRESIZE with the filesystem modification flag
+	# and allow recursive call of fsadm
+	unset FSADM_RUNNING
+	test "$DO_LVRESIZE" -eq 2 && exec $LVRESIZE $VERB -r -L$(( $NEWSIZE / 1048576 )) $VOLUME
+	exit ${1:-0}
+}
+
+# convert parameter from Exa/Peta/Tera/Giga/Mega/Kilo/Bytes and blocks
+# (2^(60/50/40/30/20/10/0))
+decode_size() {
+	case "$1" in
+	 *[eE]) NEWSIZE=$(( ${1%[eE]} * 1152921504606846976 )) ;;
+	 *[pP]) NEWSIZE=$(( ${1%[pP]} * 1125899906842624 )) ;;
+	 *[tT]) NEWSIZE=$(( ${1%[tT]} * 1099511627776 )) ;;
+	 *[gG]) NEWSIZE=$(( ${1%[gG]} * 1073741824 )) ;;
+	 *[mM]) NEWSIZE=$(( ${1%[mM]} * 1048576 )) ;;
+	 *[kK]) NEWSIZE=$(( ${1%[kK]} * 1024 )) ;;
+	 *[bB]) NEWSIZE=${1%[bB]} ;;
+	     *) NEWSIZE=$(( $1 * $2 )) ;;
+	esac
+	#NEWBLOCKCOUNT=$(round_block_size $NEWSIZE $2)
+	NEWBLOCKCOUNT=$(( $NEWSIZE / $2 ))
+
+	if [ $DO_LVRESIZE -eq 1 ]; then
+		# start lvresize, but first cleanup mounted dirs
+		DO_LVRESIZE=2
+		cleanup 0
+	fi
+}
+
+# detect filesystem on the given device
+# dereference device name if it is symbolic link
+detect_fs() {
+        VOLUME=${1#/dev/}
+	VOLUME=$($READLINK $READLINK_E -n "/dev/$VOLUME") || error "Cannot get readlink $1"
+	# use /dev/null as cache file to be sure about the result
+	# use 'cut' to be compatible with older version of blkid that does not provide option '-o value'
+	FSTYPE=$($BLKID -c /dev/null -s TYPE "$VOLUME" | $CUT -d \" -f 2) || error "Cannot get FSTYPE of \"$VOLUME\""
+	verbose "\"$FSTYPE\" filesystem found on \"$VOLUME\""
+}
+
+# check if the given device is already mounted and where
+detect_mounted()  {
+	$MOUNT >/dev/null || error "Cannot detect mounted device $VOLUME"
+	MOUNTED=$($MOUNT | $GREP "$VOLUME")
+	MOUNTED=${MOUNTED##* on }
+	MOUNTED=${MOUNTED% type *} # allow type in the mount name
+	test -n "$MOUNTED"
+}
+
+# get the full size of device in bytes
+detect_device_size() {
+	# check if blockdev supports getsize64
+	$BLOCKDEV 2>&1 | $GREP getsize64 >/dev/null 
+	if test $? -eq 0; then 
+		DEVSIZE=$($BLOCKDEV --getsize64 "$VOLUME") || error "Cannot read size of device \"$VOLUME\""
+	else
+		DEVSIZE=$($BLOCKDEV --getsize "$VOLUME") || error "Cannot read size of device \"$VOLUME\""
+		SSSIZE=$($BLOCKDEV --getss "$VOLUME") || error "Cannot block size read device \"$VOLUME\""
+		DEVSIZE=$(($DEVSIZE * $SSSIZE))
+	fi
+}
+
+# round up $1 / $2
+# could be needed to gaurantee 'at least given size'
+# but it makes many troubles
+round_up_block_size() {
+	echo $(( ($1 + $2 - 1) / $2 ))
+}
+
+temp_mount() {
+	dry $MKDIR -p -m 0000 "$TEMPDIR" || error "Failed to create $TEMPDIR"
+	dry $MOUNT "$VOLUME" "$TEMPDIR" || error "Failed to mount $TEMPDIR"
+}
+
+temp_umount() {
+	dry $UMOUNT "$TEMPDIR" || error "Failed to umount $TEMPDIR"
+	dry $RMDIR "${TEMPDIR}" || error "Failed to remove $TEMPDIR"
+	dry $RMDIR "${TEMPDIR%%m}" || error "Failed to remove ${TEMPDIR%%m}"
+}
+
+yes_no() {
+	echo -n "$@? [Y|n] "
+	if [ -n "$YES" ]; then
+		ANS="y"; echo -n $ANS
+	else
+		read -n 1 ANS
+	fi
+	test -n "$ANS" && echo
+	case "$ANS" in
+	  "y" | "Y" | "" ) return 0 ;;
+	esac
+	return 1
+}
+
+try_umount() {
+	yes_no "Do you want to unmount \"$MOUNTED\"" && dry $UMOUNT "$MOUNTED" && return 0
+	error "Cannot proceed test with mounted filesystem \"$MOUNTED\""
+}
+
+validate_parsing() {
+	test -n "$BLOCKSIZE" -a -n "$BLOCKCOUNT" || error "Cannot parse $1 output"
+}
+####################################
+# Resize ext2/ext3 filesystem
+# - unmounted or mounted for upsize
+# - unmounted for downsize
+####################################
+resize_ext() {
+	verbose "Parsing $TUNE_EXT -l \"$VOLUME\""
+	for i in $($TUNE_EXT -l "$VOLUME"); do
+		case "$i" in
+		  "Block size"*) BLOCKSIZE=${i##*  } ;;
+		  "Block count"*) BLOCKCOUNT=${i##*  } ;;
+		esac
+	done
+	validate_parsing $TUNE_EXT
+	decode_size $1 $BLOCKSIZE
+	FSFORCE=$FORCE
+
+	if [ "$NEWBLOCKCOUNT" -lt "$BLOCKCOUNT" -o "$EXTOFF" -eq 1 ]; then
+		detect_mounted && verbose "$RESIZE_EXT needs unmounted filesystem" && try_umount
+		REMOUNT=$MOUNTED
+		# CHECKME: after umount resize2fs requires fsck or -f flag.
+		FSFORCE="-f"
+	fi
+
+	verbose "Resizing \"$VOLUME\" $BLOCKCOUNT -> $NEWBLOCKCOUNT blocks ($NEWSIZE bytes, bs:$BLOCKSIZE)"
+	dry $RESIZE_EXT $FSFORCE "$VOLUME" $NEWBLOCKCOUNT
+}
+
+#############################
+# Resize reiserfs filesystem
+# - unmounted for upsize
+# - unmounted for downsize
+#############################
+resize_reiser() {
+	detect_mounted
+	if [ -n "$MOUNTED" ]; then
+		verbose "ReiserFS resizes only unmounted filesystem"
+		try_umount
+		REMOUNT=$MOUNTED
+	fi
+	verbose "Parsing $TUNE_REISER \"$VOLUME\""
+	for i in $($TUNE_REISER "$VOLUME"); do
+		case "$i" in
+		  "Blocksize"*) BLOCKSIZE=${i##*: } ;;
+		  "Count of blocks"*) BLOCKCOUNT=${i##*: } ;;
+		esac
+	done
+	validate_parsing $TUNE_REISER
+	decode_size $1 $BLOCKSIZE
+	verbose "Resizing \"$VOLUME\" $BLOCKCOUNT -> $NEWBLOCKCOUNT blocks ($NEWSIZE bytes, bs: $NEWBLOCKCOUNT)"
+	if [ -n "$YES" ]; then
+		dry echo y | $RESIZE_REISER -s $NEWSIZE "$VOLUME"
+	else
+		dry $RESIZE_REISER -s $NEWSIZE "$VOLUME"
+	fi
+}
+
+########################
+# Resize XFS filesystem
+# - mounted for upsize
+# - can not downsize
+########################
+resize_xfs() {
+	detect_mounted
+	MOUNTPOINT=$MOUNTED
+	if [ -z "$MOUNTED" ]; then
+		MOUNTPOINT=$TEMPDIR
+		temp_mount || error "Cannot mount Xfs filesystem"
+	fi
+	verbose "Parsing $TUNE_XFS \"$MOUNTPOINT\""
+	for i in $($TUNE_XFS "$MOUNTPOINT"); do
+		case "$i" in
+		  "data"*) BLOCKSIZE=${i##*bsize=} ; BLOCKCOUNT=${i##*blocks=} ;;
+		esac
+	done
+	BLOCKSIZE=${BLOCKSIZE%%[^0-9]*}
+	BLOCKCOUNT=${BLOCKCOUNT%%[^0-9]*}
+	validate_parsing $TUNE_XFS
+	decode_size $1 $BLOCKSIZE
+	if [ $NEWBLOCKCOUNT -gt $BLOCKCOUNT ]; then
+		verbose "Resizing Xfs mounted on \"$MOUNTPOINT\" to fill device \"$VOLUME\""
+		dry $RESIZE_XFS $MOUNTPOINT
+	elif [ $NEWBLOCKCOUNT -eq $BLOCKCOUNT ]; then
+		verbose "Xfs filesystem already has the right size"
+	else
+		error "Xfs filesystem shrinking is unsupported"
+	fi
+}
+
+####################
+# Resize filesystem
+####################
+resize() {
+	NEWSIZE=$2
+	detect_fs "$1"
+	detect_device_size
+	verbose "Device \"$VOLUME\" has $DEVSIZE bytes"
+	# if the size parameter is missing use device size
+	#if [ -n "$NEWSIZE" -a $NEWSIZE <
+	test -z "$NEWSIZE" && NEWSIZE=${DEVSIZE}b
+	trap cleanup 2
+	#IFS=$'\n'  # don't use bash-ism ??
+	IFS="$(printf \"\\n\")"  # needed for parsing output
+	case "$FSTYPE" in
+	  "ext3"|"ext2") resize_ext $NEWSIZE ;;
+	  "reiserfs") resize_reiser $NEWSIZE ;;
+	  "xfs") resize_xfs $NEWSIZE ;;
+	  *) error "Filesystem \"$FSTYPE\" on device \"$VOLUME\" is not supported by this tool" ;;
+	esac || error "Resize $FSTYPE failed"
+	cleanup 0
+}
+
+###################
+# Check filesystem
+###################
+check() {
+	detect_fs "$1"
+	case "$FSTYPE" in
+	  "xfs") dry $XFS_CHECK "$VOLUME" ;;
+	  *) dry $FSCK $YES "$VOLUME" ;;
+	esac
+}
+
+#############################
+# start point of this script
+# - parsing parameters
+#############################
+
+# test if we are not invoked recursively
+test -n "$FSADM_RUNNING" && exit 0
+
+# test some prerequisities
+test -n "$TUNE_EXT" -a -n "$RESIZE_EXT" -a -n "$TUNE_REISER" -a -n "$RESIZE_REISER" \
+  -a -n "$TUNE_XFS" -a -n "$RESIZE_XFS" -a -n "$MOUNT" -a -n "$UMOUNT" -a -n "$MKDIR" \
+  -a -n "$RMDIR" -a -n "$BLOCKDEV" -a -n "$BLKID" -a -n "$GREP" -a -n "$READLINK" \
+  -a -n "$FSCK" -a -n "$XFS_CHECK" -a -n "LVRESIZE" -a -n "$CUT" \
+  || error "Required command definitions in the script are missing!"
+
+$($READLINK -e -n / >/dev/null 2>&1) || READLINK_E="-f"
+TEST64BIT=$(( 1000 * 1000000000000 ))
+test $TEST64BIT -eq 1000000000000000 || error "Shell does not handle 64bit arithmetic"
+$(echo Y | $GREP Y >/dev/null) || error "Grep does not work properly"
+
+
+if [ "$1" = "" ] ; then
+	tool_usage
+fi
+
+while [ "$1" != "" ]
+do
+	case "$1" in
+	 "-h"|"--help") tool_usage ;;
+	 "-v"|"--verbose") VERB="-v" ;;
+	 "-n"|"--dry-run") DRY=1 ;;
+	 "-f"|"--force") FORCE="-f" ;;
+	 "-e"|"--ext-offline") EXTOFF=1 ;;
+	 "-y"|"--yes") YES="-y" ;;
+	 "-l"|"--lvresize") DO_LVRESIZE=1 ;;
+	 "check") shift; CHECK=$1 ;;
+	 "resize") shift; RESIZE=$1; shift; NEWSIZE=$1 ;;
+	 *) error "Wrong argument \"$1\". (see: $TOOL --help)"
+	esac
+	shift
+done
+
+if [ -n "$CHECK" ]; then
+	check "$CHECK"
+elif [ -n "$RESIZE" ]; then
+	export FSADM_RUNNING="fsadm"
+	resize "$RESIZE" "$NEWSIZE"
+else
+	error "Missing command. (see: $TOOL --help)"
+fi
Index: src/external/gpl2/lvm2tools/dist/scripts/last_cvs_update.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/scripts/last_cvs_update.sh
diff -N src/external/gpl2/lvm2tools/dist/scripts/last_cvs_update.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/scripts/last_cvs_update.sh	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,163 @@
+#!/bin/sh
+#$Header$
+################################################################################
+##
+##    Copyright 2001 Sistina Software, Inc.
+##
+##    This is free software released under the GNU General Public License.
+##    There is no warranty for this software.  See the file COPYING for
+##    details.
+##
+##    See the file CONTRIBUTORS for a list of contributors.
+##
+##    This file is maintained by:
+##      AJ Lewis <lewis@sistina.com>
+## 
+##    File name: last_cvs_update.sh
+##
+##    Description: displays the last file updated by CVS commands and the date
+##                 it was updated.  May be given a relative or absolute path.
+##                 Based on this information, you should be able to do a 
+##                 cvs co -D $date GFS and get the same version of the source
+##                 tree as this tool was run on.
+##                 
+##                 Will also give you the CVS tag the source tree is based off
+##                 off when appropriate
+## 
+##                 Output format:
+##                 [Tag:  $TAG]
+##                 The last file updated by CVS was:
+##                 $path/$file
+##                 on
+##                 $date
+##
+################################################################################
+
+if [[ -z $1 ]];
+ then path=.;
+else
+ if [[ $1 == "-h" ]];
+   then echo "usage: $0 [ -h | path ]"
+        exit 0;
+ else
+   if [[ -d $1 ]]
+     then path=$1;
+   else
+     echo "usage: $0 [ -h | path ]"
+     exit 0;
+   fi
+ fi
+fi
+
+# grab the tag from the path passed in
+if [[ -f $path/CVS/Tag ]];
+  then echo "Tag: " `cat $path/CVS/Tag | sed -e 's/^[NT]//'`
+fi
+
+awk '
+BEGIN {                            
+  FS = "/"                         
+}
+{
+    # find the path for the Entries file
+    path = FILENAME
+    sub(/^\.\//, "", path)
+    
+    # remove the CVS part of it
+    sub(/CVS\/Entries/, "", path)
+    
+    # add the path the the filename that was modified, and put the date it was
+    # modified in as well
+    print path $2 " " $4
+
+}' `find $path -name "Entries" -printf "%h/%f "` | awk '
+# converts string name of month the a numeral
+function cvt_month(month) {
+  if(month == "Jan")
+    return 0
+  if(month == "Feb")
+    return 1
+  if(month == "Mar")
+    return 2
+  if(month == "Apr")
+    return 3
+  if(month == "May")
+    return 4
+  if(month == "Jun")
+    return 5
+  if(month == "Jul")
+    return 6
+  if(month == "Aug")
+    return 7
+  if(month == "Sep")
+    return 8
+  if(month == "Oct")
+    return 9
+  if(month == "Nov")
+    return 10
+  if(month == "Dec")
+    return 11
+  return -1
+}
+BEGIN {                            
+  FS = " "                         
+  latest=""
+  maxyear = 0
+  maxdate = 0
+  maxmonth = "Jan"
+  maxtime = "00:00:00"
+}
+{
+   # check year first
+   if (maxyear < $6) {
+      date = $2 " " $3 " " $4 " " $5 " " $6
+      file = $1
+      maxyear = $6
+      maxmonth = $3
+      maxdate = $4
+      maxtime = $5
+   }
+   else {
+      if (maxyear == $6) {
+        # then month if year is the same
+        if (cvt_month(maxmonth) < cvt_month($3)) {
+          date = $2 " " $3 " " $4 " " $5 " " $6
+          file = $1
+	  maxmonth = $3
+	  maxdate = $4
+	  maxtime = $5
+        }
+        else {
+          if (cvt_month(maxmonth) == cvt_month($3)) {
+	    #then date if month is the same
+            if (maxdate < $4) {
+              date = $2 " " $3 " " $4 " " $5 " " $6
+              file = $1
+	      maxdate = $4
+	      maxtime = $5
+	    }
+	    else {
+	      if (maxdate == $4) {
+	        # then time if date is the same
+	        if (maxtime < $5) {
+		  date = $2 " " $3 " " $4 " " $5 " " $6
+                  file = $1
+		  maxtime = $5
+		}
+              }
+	    }
+	  }
+        }
+      }
+   }
+}
+
+END {
+   # strip leading "./" from filename
+   sub(/^\.\//, "", file)
+   print "The last file updated by CVS was:"
+   print file 
+   print "on"
+   print date " GMT"
+}'
+
Index: src/external/gpl2/lvm2tools/dist/scripts/lvm2_monitoring_init_rhel4
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/scripts/lvm2_monitoring_init_rhel4
diff -N src/external/gpl2/lvm2tools/dist/scripts/lvm2_monitoring_init_rhel4
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/scripts/lvm2_monitoring_init_rhel4	15 Jul 2008 13:50:08 -0000	1.1.1.1
@@ -0,0 +1,100 @@
+#!/bin/bash
+#
+# Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+# This file is part of LVM2.
+# It is required for the proper handling of failures of LVM2 mirror
+# devices that were created using the -m option of lvcreate.
+#
+#
+# chkconfig: 12345 02 99
+# description: Starts and stops dmeventd monitoring for lvm2
+#	       
+### BEGIN INIT INFO
+# Provides: 
+### END INIT INFO
+
+. /etc/init.d/functions
+
+VGCHANGE="/usr/sbin/vgchange"
+WARN=1
+
+start()
+{
+	ret=0
+	# TODO do we want to separate out already active groups only?
+	VGS=`vgs --noheadings -o name 2> /dev/null`
+	for vg in $VGS
+	do
+	    action "Starting monitoring for VG $vg:" $VGCHANGE --monitor y $vg || ret=$?
+	done
+
+	return $ret
+}
+
+
+stop()
+{
+	ret=0
+	# TODO do we want to separate out already active groups only?
+	if test "$WARN" = "1"; then
+	   echo "Not stopping monitoring, this is a dangerous operation. Please use force-stop to override."
+	   return 1
+	fi
+	VGS=`vgs --noheadings -o name 2> /dev/null`
+	for vg in $VGS
+	do
+	    action "Stopping monitoring for VG $vg:" $VGCHANGE --monitor n $vg || ret=$?
+	done
+	return $ret
+}
+
+result=1
+
+# See how we were called.
+case "$1" in
+  start)
+	start
+	result=$?
+	;;
+
+  force-stop)
+	WARN=0
+	stop
+	result=$?
+	;;
+
+  stop)
+	test "$runlevel" = "0" && WARN=0
+	test "$runlevel" = "6" && WARN=0
+	stop
+	result=$?
+	;;
+
+  restart)
+	WARN=0
+	if stop
+	then
+		start
+	fi 
+	result=$?
+	;;
+
+  status)
+	# TODO anyone with an idea how to dump monitored volumes?
+	;;
+
+  *)
+	echo $"Usage: $0 {start|stop|restart|status|force-stop}"
+	;;
+esac
+
+exit $result
Index: src/external/gpl2/lvm2tools/dist/scripts/lvm_dump.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/scripts/lvm_dump.sh
diff -N src/external/gpl2/lvm2tools/dist/scripts/lvm_dump.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/scripts/lvm_dump.sh	12 Dec 2008 16:33:03 -0000	1.1.1.1.2.1
@@ -0,0 +1,234 @@
+#!/bin/bash
+# We use some bash-isms (getopts?)
+
+# Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+# lvm_dump: This script is used to collect pertinent information for
+#           the debugging of lvm issues.
+
+# following external commands are used throughout the script
+# echo and test are internal in bash at least
+MKDIR=mkdir # need -p
+TAR=tar # need czf
+RM=rm # need -rf
+CP=cp
+TAIL=tail # we need -n
+LS=ls # need -la
+PS=ps # need alx
+SED=sed
+DD=dd
+CUT=cut
+DATE=date
+BASENAME=basename
+UNAME=uname
+
+# user may override lvm and dmsetup location by setting LVM_BINARY
+# and DMSETUP_BINARY respectively
+LVM=${LVM_BINARY-lvm}
+DMSETUP=${DMSETUP_BINARY-dmsetup}
+
+die() {
+    code=$1; shift
+    echo "$@" 1>&2
+    exit $code
+}
+
+"$LVM" version >& /dev/null || die 2 "Could not run lvm binary '$LVM'"
+"$DMSETUP" version >& /dev/null || DMSETUP=:
+
+function usage {
+	echo "$0 [options]"
+	echo "    -h print this message"
+	echo "    -a advanced collection - warning: if lvm is already hung,"
+	echo "       then this script may hang as well if -a is used"
+	echo "    -m gather LVM metadata from the PVs"
+	echo "    -d <directory> dump into a directory instead of tarball"
+	echo "    -c if running clvmd, gather cluster data as well"
+	echo ""
+	
+	exit 1
+}
+
+advanced=0
+clustered=0
+metadata=0
+while getopts :acd:hm opt; do
+	case $opt in 
+		s)      sysreport=1 ;;
+		a)	advanced=1 ;;
+		c)	clustered=1 ;;
+		d)	userdir=$OPTARG ;;
+		h)	usage ;;
+		m)	metadata=1 ;;
+		:)	echo "$0: $OPTARG requires a value:"; usage ;;
+		\?)     echo "$0: unknown option $OPTARG"; usage ;;
+		*)	usage ;;
+	esac
+done
+
+NOW=`$DATE -u +%G%m%d%k%M%S | /usr/bin/tr -d ' '`
+if test -n "$userdir"; then
+	dir="$userdir"
+else
+	dirbase="lvmdump-$HOSTNAME-$NOW"
+	dir="$HOME/$dirbase"
+fi
+
+test -e $dir && die 3 "Fatal: $dir already exists"
+$MKDIR -p $dir || die 4 "Fatal: could not create $dir"
+
+log="$dir/lvmdump.log"
+
+myecho() {
+	echo "$@"
+	echo "$@" >> "$log"
+}
+
+log() {
+	echo "$@" >> "$log"
+	eval "$@"
+}
+
+warnings() {
+	if test "$UID" != "0" && test "$EUID" != "0"; then
+		myecho "WARNING! Running as non-privileged user, dump is likely incomplete!"
+	elif test "$DMSETUP" = ":"; then
+		myecho "WARNING! Could not run dmsetup, dump is likely incomplete."
+	fi
+}
+
+warnings
+
+myecho "Creating dump directory: $dir"
+echo " "
+
+if (( $advanced )); then
+	myecho "Gathering LVM volume info..."
+
+	myecho "  vgscan..."
+	log "\"$LVM\" vgscan -vvvv > \"$dir/vgscan\" 2>&1"
+
+	myecho "  pvscan..."
+	log "\"$LVM\" pvscan -v >> \"$dir/pvscan\" 2>> \"$log\""
+
+	myecho "  lvs..."
+	log "\"$LVM\" lvs -a -o +devices >> \"$dir/lvs\" 2>> \"$log\""
+
+	myecho "  pvs..."
+	log "\"$LVM\" pvs -a -v > \"$dir/pvs\" 2>> \"$log\""
+
+	myecho "  vgs..."
+	log "\"$LVM\" vgs -v > \"$dir/vgs\" 2>> \"$log\""
+fi
+
+if (( $clustered )); then
+	myecho "Gathering cluster info..."
+
+	{
+	for i in nodes status services; do
+		cap_i=$(echo $i|tr a-z A-Z)
+		printf "$cap_i:\n----------------------------------\n"
+		log "cman_tool $i 2>> \"$log\""
+		echo
+	done
+
+	echo "LOCKS:"
+	echo "----------------------------------"
+	if [ -f /proc/cluster/dlm_locks ]
+	then
+		echo clvmd > /proc/cluster/dlm_locks
+		cat /proc/cluster/dlm_locks
+		echo
+		echo "RESOURCE DIR:"
+		cat /proc/cluster/dlm_dir
+		echo
+		echo "DEBUG LOG:"
+		cat /proc/cluster/dlm_debug
+		echo
+	fi
+	if [ -f /debug/dlm/clvmd ]
+	then
+		cat /debug/dlm/clvmd
+		echo
+		echo "WAITERS:"
+		cat /debug/dlm/clvmd_waiters
+		echo
+		echo "MASTER:"
+		cat /debug/dlm/clvmd_master
+	fi
+	} > $dir/cluster_info
+fi
+
+myecho "Gathering LVM & device-mapper version info..."
+echo "LVM VERSION:" > "$dir/versions"
+"$LVM" lvs --version >> "$dir/versions" 2>> "$log"
+echo "DEVICE MAPPER VERSION:" >> "$dir/versions"
+"$DMSETUP" --version >> "$dir/versions" 2>> "$log"
+echo "KERNEL VERSION:" >> "$dir/versions"
+"$UNAME" -a >> "$dir/versions" 2>> "$log"
+echo "DM TARGETS VERSIONS:" >> "$dir/versions"
+"$DMSETUP" targets >> "$dir/versions" 2>> "$log"
+
+myecho "Gathering dmsetup info..."
+log "\"$DMSETUP\" info -c > \"$dir/dmsetup_info\" 2>> \"$log\""
+log "\"$DMSETUP\" table > \"$dir/dmsetup_table\" 2>> \"$log\""
+log "\"$DMSETUP\" status > \"$dir/dmsetup_status\" 2>> \"$log\""
+
+myecho "Gathering process info..."
+log "$PS alx > \"$dir/ps_info\" 2>> \"$log\""
+
+myecho "Gathering console messages..."
+log "$TAIL -n 75 /var/log/messages > \"$dir/messages\" 2>> \"$log\""
+
+myecho "Gathering /etc/lvm info..."
+log "$CP -a /etc/lvm \"$dir/lvm\" 2>> \"$log\""
+
+myecho "Gathering /dev listing..."
+log "$LS -laR /dev > \"$dir/dev_listing\" 2>> \"$log\""
+
+myecho "Gathering /sys/block listing..."
+log "$LS -laR /sys/block > \"$dir/sysblock_listing\""
+
+if (( $metadata )); then
+	myecho "Gathering LVM metadata from Physical Volumes..."
+
+	log "$MKDIR -p \"$dir/metadata\""
+
+	pvs="$("$LVM" pvs --separator , --noheadings --units s --nosuffix -o \
+	    name,pe_start 2>> "$log" | $SED -e 's/^ *//')"
+	for line in $pvs
+	do
+		test -z "$line" && continue
+		pv="$(echo $line | $CUT -d, -f1)"
+		pe_start="$(echo $line | $CUT -d, -f2)"
+		name="$($BASENAME "$pv")"
+		myecho "  $pv"
+		log "$DD if=$pv \"of=$dir/metadata/$name\" bs=512 count=$pe_start 2>> \"$log\""
+	done
+fi
+
+if test -z "$userdir"; then
+	lvm_dump="$dirbase.tgz"
+	myecho "Creating report tarball in $HOME/$lvm_dump..."
+fi
+
+warnings
+
+if test -z "$userdir"; then
+	cd "$HOME"
+	"$TAR" czf "$lvm_dump" "$dirbase" 2>/dev/null
+	"$RM" -rf "$dir"
+fi
+
+exit 0
+
Index: src/external/gpl2/lvm2tools/dist/scripts/lvmconf.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/scripts/lvmconf.sh
diff -N src/external/gpl2/lvm2tools/dist/scripts/lvmconf.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/scripts/lvmconf.sh	15 Jul 2008 13:50:08 -0000	1.1.1.1
@@ -0,0 +1,259 @@
+#!/bin/sh
+#
+# Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+#
+# This file is part of the lvm2-cluster package.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#
+# Edit an lvm.conf file to adjust various properties
+#
+
+function usage
+{
+    echo "usage: $0 <command>"
+    echo ""
+    echo "Commands:"
+    echo "Enable clvm:  --enable-cluster [--lockinglibdir <dir>] [--lockinglib <lib>]"
+    echo "Disable clvm: --disable-cluster"
+    echo "Set locking library: --lockinglibdir <dir> [--lockinglib <lib>]"
+    echo ""
+    echo "Global options:"
+    echo "Config file location: --file <configfile>"
+    echo ""
+}
+
+
+function parse_args
+{
+    while [ -n "$1" ]; do
+        case $1 in
+            --enable-cluster)
+                LOCKING_TYPE=2
+                shift
+                ;;
+            --disable-cluster)
+                LOCKING_TYPE=1
+                shift
+                ;;
+            --lockinglibdir)
+                if [ -n "$2" ]; then
+                    LOCKINGLIBDIR=$2
+                    shift 2
+                else
+                    usage
+                    exit 1
+                fi
+                ;;
+            --lockinglib)
+                if [ -n "$2" ]; then
+                    LOCKINGLIB=$2
+                    shift 2
+                else
+                    usage
+                    exit 1
+                fi
+                ;;
+            --file)
+                if [ -n "$2" ]; then
+                    CONFIGFILE=$2
+                    shift 2
+                else
+                    usage
+                    exit 1
+                fi
+                ;;
+            *)
+                usage
+                exit 1
+        esac
+    done
+}
+
+function validate_args
+{
+    [ -z "$CONFIGFILE" ] && CONFIGFILE="/etc/lvm/lvm.conf"
+
+    if [ ! -f "$CONFIGFILE" ]
+            then
+            echo "$CONFIGFILE does not exist"
+            exit 10
+    fi
+
+    if [ -z "$LOCKING_TYPE" ] && [ -z "$LOCKINGLIBDIR" ]; then
+        usage
+        exit 1
+    fi
+
+    if [ -n "$LOCKINGLIBDIR" ]; then
+
+        [ -z "$LOCKINGLIB" ] && LOCKINGLIB="liblvm2clusterlock.so"
+            
+        if [ "${LOCKINGLIBDIR:0:1}" != "/" ]
+            then
+            echo "Prefix must be an absolute path name (starting with a /)"
+            exit 12
+        fi
+    
+        if [ ! -f "$LOCKINGLIBDIR/$LOCKINGLIB" ]
+            then
+            echo "$LOCKINGLIBDIR/$LOCKINGLIB does not exist, did you do a \"make install\" ?"
+            exit 11
+        fi
+        
+    fi
+
+    if [ "$LOCKING_TYPE" = "1" ] && [ -n "$LOCKINGLIBDIR" -o -n "$LOCKINGLIB" ]; then
+	echo "Superfluous locking lib parameter, ignoring"
+    fi
+}
+
+umask 0077
+
+parse_args "$@"
+
+validate_args
+
+
+SCRIPTFILE=/etc/lvm/.lvmconf-script.tmp
+TMPFILE=/etc/lvm/.lvmconf-tmp.tmp
+
+
+# Flags so we know which parts of the file we can replace and which need
+# adding. These are return codes from grep, so zero means it IS present!
+have_type=1
+have_dir=1
+have_library=1
+have_global=1
+
+grep -q '^[[:blank:]]*locking_type[[:blank:]]*=' $CONFIGFILE
+have_type=$?
+
+grep -q '^[[:blank:]]*library_dir[[:blank:]]*=' $CONFIGFILE
+have_dir=$?
+
+grep -q '^[[:blank:]]*locking_library[[:blank:]]*=' $CONFIGFILE
+have_library=$?
+
+# Those options are in section "global {" so we must have one if any are present.
+if [ "$have_type" = "0" -o "$have_dir" = "0" -o "$have_library" = "0" ]
+then
+
+    # See if we can find it...
+    grep -q '^[[:blank:]]*global[[:blank:]]*{' $CONFIGFILE
+    have_global=$?
+    
+    if [ "$have_global" = "1" ] 
+	then
+	echo "global keys but no 'global {' found, can't edit file"
+	exit 13
+    fi
+fi
+
+if [ "$LOCKING_TYPE" = "2" ] && [ -z "$LOCKINGLIBDIR" ] && [ "$have_dir" = "1" ]; then
+	echo "no library_dir specified in $CONFIGFILE"
+	exit 16
+fi
+
+# So if we don't have "global {" we need to create one and 
+# populate it
+
+if [ "$have_global" = "1" ]
+then
+    if [ -z "$LOCKING_TYPE" ]; then
+	LOCKING_TYPE=1
+    fi
+    if [ "$LOCKING_TYPE" = "2" ]; then
+        cat $CONFIGFILE - <<EOF > $TMPFILE
+global {
+    # Enable locking for cluster LVM
+    locking_type = $LOCKING_TYPE
+    library_dir = "$LOCKINGLIBDIR"
+    locking_library = "$LOCKINGLIB"
+}
+EOF
+    fi # if we aren't setting cluster locking, we don't need to create a global section
+
+    if [ $? != 0 ]
+    then
+	echo "failed to create temporary config file, $CONFIGFILE not updated"
+	exit 14
+    fi
+else
+    #
+    # We have a "global {" section, so add or replace the
+    # locking entries as appropriate
+    #
+
+    if [ -n "$LOCKING_TYPE" ]; then
+	if [ "$have_type" = "0" ] 
+	then
+	    SEDCMD=" s/^[[:blank:]]*locking_type[[:blank:]]*=.*/\ \ \ \ locking_type = $LOCKING_TYPE/g"
+	else
+	    SEDCMD=" /global[[:blank:]]*{/a\ \ \ \ locking_type = $LOCKING_TYPE"
+	fi
+    fi
+    
+    if [ -n "$LOCKINGLIBDIR" ]; then
+        if [ "$have_dir" = "0" ] 
+            then
+            SEDCMD="${SEDCMD}\ns'^[[:blank:]]*library_dir[[:blank:]]*=.*'\ \ \ \ library_dir = \"$LOCKINGLIBDIR\"'g"
+        else
+            SEDCMD="${SEDCMD}\n/global[[:blank:]]*{/a\ \ \ \ library_dir = \"$LOCKINGLIBDIR\""
+        fi
+
+        if [ "$have_library" = "0" ] 
+            then
+            SEDCMD="${SEDCMD}\ns/^[[:blank:]]*locking_library[[:blank:]]*=.*/\ \ \ \ locking_library = \"$LOCKINGLIB\"/g"
+        else
+            SEDCMD="${SEDCMD}\n/global[[:blank:]]*{/a\ \ \ \ locking_library = \"$LOCKINGLIB\""
+        fi
+    fi
+
+    if [ "$LOCKING_TYPE" = "1" ]; then
+        # if we're not using cluster locking, remove the library dir and locking library name
+        if [ "$have_dir" = "0" ] 
+            then
+            SEDCMD="${SEDCMD}\n/^[[:blank:]]*library_dir[[:blank:]]*=.*/d"
+        fi
+
+        if [ "$have_library" = "0" ] 
+            then
+            SEDCMD="${SEDCMD}\n/^[[:blank:]]*locking_library[[:blank:]]*=.*/d"
+        fi
+    fi
+
+    echo -e $SEDCMD > $SCRIPTFILE
+    sed  <$CONFIGFILE >$TMPFILE -f $SCRIPTFILE
+    if [ $? != 0 ]
+    then
+	echo "sed failed, $CONFIGFILE not updated"
+	exit 15
+    fi
+fi
+
+# Now we have a suitably editted config file in a temp place,
+# backup the original and copy our new one into place.
+
+cp $CONFIGFILE $CONFIGFILE.lvmconfold
+if [ $? != 0 ]
+    then
+    echo "failed to backup old config file, $CONFIGFILE not updated"
+    exit 2
+fi
+
+cp $TMPFILE $CONFIGFILE
+if [ $? != 0 ]
+    then
+    echo "failed to copy new config file into place, check $CONFIGFILE is still OK"
+    exit 3
+fi
+
+rm -f $SCRIPTFILE $TMPFILE
Index: src/external/gpl2/lvm2tools/dist/scripts/vg_convert
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/scripts/vg_convert
diff -N src/external/gpl2/lvm2tools/dist/scripts/vg_convert
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/scripts/vg_convert	15 Jul 2008 13:50:08 -0000	1.1.1.1
@@ -0,0 +1,18 @@
+#!/bin/sh -x
+
+# Original script used to convert a VG from LVM1 to LVM2 metadata format.
+# Superceded by 'vgconvert', but left here to show how to do it step-by-step.
+
+# Takes vgname as parameter.  No error checking.  Uses temp file 'lvmbackup'.
+
+echo "Please use the 'vgconvert' tool instead"
+exit 1
+
+./vgcfgbackup $1 || exit 1
+./vgcfgbackup --file lvmbackup $1 || exit 1
+
+CMDS=`./pvscan -u | sed -ne "s/.*PV \(.*\) with UUID \(.*\) VG $1 .*/.\/pvcreate -ff -y -M lvm2 --restorefile lvmbackup -u \2 \1 ; /p"`
+
+sh -x -c "$CMDS" || exit 1
+
+./vgcfgrestore --file lvmbackup -M lvm2 $1 || exit 1
Index: src/external/gpl2/lvm2tools/dist/scripts/lvm2create_initrd/Makefile
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/scripts/lvm2create_initrd/Makefile
diff -N src/external/gpl2/lvm2tools/dist/scripts/lvm2create_initrd/Makefile
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/scripts/lvm2create_initrd/Makefile	15 Jul 2008 13:50:08 -0000	1.1.1.1
@@ -0,0 +1,6 @@
+all:
+	echo "Nothing to do for make all"
+
+manpage:
+	pod2man --center="create LVM2 initrd" --name='lvm2create_initrd' --section=8 -r 'lvm2create_initrd' ./lvm2create_initrd.pod > lvm2create_initrd.8
+
Index: src/external/gpl2/lvm2tools/dist/scripts/lvm2create_initrd/README
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/scripts/lvm2create_initrd/README
diff -N src/external/gpl2/lvm2tools/dist/scripts/lvm2create_initrd/README
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/scripts/lvm2create_initrd/README	15 Jul 2008 13:50:08 -0000	1.1.1.1
@@ -0,0 +1,40 @@
+http://poochiereds.net/svn/lvm2/
+
+This is the lvm2create_initrd script written by Miguel Cabeca, with some small
+modifications by myself.
+
+Here are some other requirements and tips for using it:
+
+1) this script uses busybox on the initrd image, hence busybox needs to be
+installed when you create your initrd.
+
+2) Make sure /etc/lvm/lvm.conf is set up correctly before running this. In
+particular, if you're using LVM on RAID, make sure that you have a filter that
+excludes the RAID component devices (this may not be necessary with the latest
+patch by Luca Berra, but it doesn't hurt).
+
+3) This initrd image does not support modules. If you need to plug in any
+kernel modules during the initrd phase, then you'll need to hand-modify the
+image.
+
+4) The generated initrd image supports an 'lvm2rescue' mode as well. If you add
+the parameter 'lvmrescue' on the kernel command line, it will run a shell at
+the end of the initrd 'init' script. This can be helpful when trying to fix a
+corrupt root volume or root LVM2 volume group.
+
+5) No userspace md tools are installed, so if you're using LVM on RAID, then
+you'll probably want to mark your RAID partitions as type 'fd' so that the
+kernel will start them automagically (or hand-modify the image).
+
+6) I'm not sure if devfs will work with this or not. udev, however does work,
+and is recommended. Because the dm-* devices use dynamically allocated major
+and minor numbers, kernel upgrades and the like can renumber your devices. To
+fix this, you need to run a 'vgscan --mknodes' prior to fscking and mounting
+your rootfs. Doing this with a static /dev creates a problem though -- you
+will be modifying the root filesystem before it has been fsck'ed. udev gets
+around this by mounting a ramdisk over /dev, but you'll probably need to add
+a startup script that creates devices in /dev. The lvm2udev script in this
+directory is an example of such a beast.
+
+--
+Jeffrey Layton <jtlayton@poochiereds.net>
Index: src/external/gpl2/lvm2tools/dist/scripts/lvm2create_initrd/lvm2create_initrd
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/scripts/lvm2create_initrd/lvm2create_initrd
diff -N src/external/gpl2/lvm2tools/dist/scripts/lvm2create_initrd/lvm2create_initrd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/scripts/lvm2create_initrd/lvm2create_initrd	15 Jul 2008 13:50:09 -0000	1.1.1.1
@@ -0,0 +1,502 @@
+#!/bin/bash
+#
+# lvm2create_initrd 
+#
+# Miguel Cabeca 
+# cabeca (at) ist (dot) utl (dot) pt
+#
+# Inspiration to write this script came from various sources
+#
+# Original LVM lvmcreate_initrd: ftp://ftp.sistina.com/pub/LVM/1.0/
+# Kernel initrd.txt: http://www.kernel.org/
+# EVMS INSTALL.initrd & linuxrc: http://evms.sourceforge.net/
+# Jeffrey Layton's lvm2create_initrd: http://poochiereds.net/svn/lvm2create_initrd/
+# Christophe Saout's initrd & linuxrc: http://www.saout.de/misc/
+#
+# This script was only tested with kernel 2.6 with everything required to boot 
+# the root filesystem built-in (not as modules). Ex: SCSI or IDE, RAID, device mapper
+# It does not support devfs as it is deprecated in the 2.6 kernel series
+#
+# It needs lvm2 tools, busybox, pivot_root, MAKEDEV
+#
+# It has been tested on Debian sid (unstable) only
+#
+# Changelog
+# 26/02/2004	Initial release -- Miguel Cabeca
+# 27/02/2004	Removed the BUSYBOXSYMLINKS var. The links are now determined at runtime.
+#		some changes in init script to call a shell if something goes wrong. -- Miguel Cabeca
+# 19/04/2004    Several small changes. Pass args to init so single user mode works. Add some
+#               PATH entries to /sbin/init shell script so chroot works without /usr mounted. Remove
+#               mkdir /initrd so we don't cause problems if root filesystem is corrupted. -- Jeff Layton
+# 15/05/2004	initial support for modules, create lvm.conf from lvm dumpconfig, other cleanups -- Jeff Layton
+# 14/11/2006	Update handling of ldd output to handle hardcoded library links and virtual dll linux-gate.
+#		Add support for Gentoo-style MAKEDEV. Remove hardcoded BINUTILS paths -- Douglas Mayle
+#
+# Copyright Miguel Cabeca, Jeffrey Layton, 2004
+#
+#    This program is free software; you can redistribute it and/or modify
+#    it under the terms of the GNU General Public License as published by
+#    the Free Software Foundation; either version 2 of the License, or
+#    (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU General Public License for more details.
+#
+#    You should have received a copy of the GNU General Public License
+#    along with this program; if not, write to the Free Software
+#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+# $Id$
+
+TMPMNT=/tmp/mnt.$$
+DEVRAM=/tmp/initrd.$$
+
+# set defaults
+BINFILES=${BINFILES:-"`which lvm` `which bash` `which busybox` `which pivot_root`"}
+BASICDEVICES=${BASICDEVICES:-"std consoleonly fd"}
+BLOCKDEVICES=${BLOCKDEVICES:-"md hda hdb hdc hdd sda sdb sdc sdd"}
+MAKEDEV=${MAKEDEV:-"debian"}
+
+# Uncomment this if you want to disable automatic size detection
+#INITRDSIZE=4096
+
+PATH=/bin:/sbin:/usr/bin:/usr/sbin:$PATH
+
+usage () {
+	echo "Create an initial ramdisk image for LVM2 root filesystem"
+	echo "$cmd: [-h] [-v] [-c lvm.conf] [-m modulelist] [-e extrafiles] -r [raiddevs] [-R mdadm.conf] [-M style] [kernel version]"
+	echo "      -h|--help      print this usage message"
+	echo "      -v|--verbose   verbose progress messages"
+	echo "      -c|--lvmconf   path to lvm.conf (/etc/lvm/lvm.conf)"
+	echo "      -m|--modules   modules to copy to initrd image"
+	echo "      -e|--extra     extra files to add to initrd"
+	echo "      -r|--raid      raid devices to start in initrd"
+	echo "      -R|--raidconf  location of mdadm.conf file to include"
+	echo "      -M|--makedev   set MAKEDEV type (debian or redhat)"
+}
+
+verbose () {
+   [ "$VERBOSE" ] && echo "`echo $cmd | tr '[a-z0-9/_]' ' '` -- $1" || true
+}
+
+cleanup () {
+  [ "`mount | grep $DEVRAM`" ] && verbose "unmounting $DEVRAM" && umount $DEVRAM
+  [ -f $DEVRAM ] && verbose "removing $DEVRAM" && rm $DEVRAM
+  [ -d $TMPMNT ] && verbose "removing $TMPMNT" && rmdir $TMPMNT
+  verbose "exit with code $1"
+  exit $1
+}
+
+trap "
+  verbose 'Caught interrupt'
+  echo 'Bye bye...'
+  cleanup 1
+" 1 2 3 15
+
+create_init () {
+   cat << 'INIT' > $TMPMNT/sbin/init
+#!/bin/bash
+
+# include in the path some dirs from the real root filesystem
+# for chroot, blockdev
+PATH="/sbin:/bin:/usr/sbin:/usr/bin:/lib/lvm-200:/initrd/bin:/initrd/sbin"
+PRE="initrd:"
+
+do_shell(){
+    /bin/echo
+    /bin/echo "*** Entering LVM2 rescue shell. Exit shell to continue booting. ***"
+    /bin/echo
+    /bin/bash
+}
+
+echo "$PRE Remounting / read/write"
+mount -t ext2 -o remount,rw /dev/ram0 /
+
+
+# We need /proc for device mapper
+echo "$PRE Mounting /proc"
+mount -t proc none /proc
+
+# plug in modules listed in /etc/modules
+if [ -f /etc/modules ]; then
+    echo -n "$PRE plugging in kernel modules:"
+    cat /etc/modules |
+    while read module; do
+        echo -n " $module"
+        modprobe $module
+    done
+    echo '.'
+fi
+
+# start raid devices if raid_autostart file exists
+if [ -f /etc/raid_autostart ]; then
+    if [ ! -f /etc/mdadm/mdadm.conf ]; then
+        mdoptions='--super-minor=dev'
+    fi
+    cat /etc/raid_autostart|
+    while read dev; do
+    	echo "Starting RAID device $dev"
+        /sbin/mdadm --assemble $dev $mdoptions 
+    done
+fi
+
+# Create the /dev/mapper/control device for the ioctl
+# interface using the major and minor numbers that have been allocated
+# dynamically.
+
+echo -n "$PRE Finding device mapper major and minor numbers "
+
+MAJOR=$(sed -n 's/^ *\([0-9]\+\) \+misc$/\1/p' /proc/devices)
+MINOR=$(sed -n 's/^ *\([0-9]\+\) \+device-mapper$/\1/p' /proc/misc)
+if test -n "$MAJOR" -a -n "$MINOR" ; then
+	mkdir -p -m 755 /dev/mapper
+	mknod -m 600 /dev/mapper/control c $MAJOR $MINOR
+fi
+
+echo "($MAJOR,$MINOR)"
+
+# Device-Mapper dynamically allocates all device numbers. This means it is possible 
+# that the root volume specified to LILO or Grub may have a different number when the
+# initrd runs than when the system was last running. In order to make sure the
+# correct volume is mounted as root, the init script must determine what the
+# desired root volume name is by getting the LVM2 root volume name from the kernel command line. In order for
+# this to work correctly, "lvm2root=/dev/Volume_Group_Name/Root_Volume_Name" needs to be passed 
+# to the kernel command line (where Root_Volume_Name is replaced by your actual
+# root volume's name.
+for arg in `cat /proc/cmdline`; do
+	echo $arg | grep '^lvm2root=' > /dev/null
+	if [ $? -eq 0 ]; then
+		rootvol=${arg#lvm2root=}
+		break
+	fi
+done
+
+echo "$PRE Activating LVM2 volumes"
+
+
+# run a shell if we're passed lvm2rescue on commandline
+grep lvm2rescue /proc/cmdline 1>/dev/null 2>&1
+if [ $? -eq 0 ]; then
+    lvm vgchange --ignorelockingfailure -P -a y
+    do_shell
+else
+    lvm vgchange --ignorelockingfailure -a y
+fi
+
+echo "$PRE Mounting root filesystem $rootvol ro"
+mkdir /rootvol
+if ! mount -t auto -o ro $rootvol /rootvol; then
+	echo "\t*FAILED*";
+	do_shell
+fi
+
+echo "$PRE Umounting /proc"
+umount /proc
+
+echo "$PRE Changing roots"
+cd /rootvol
+if ! pivot_root . initrd ; then
+	echo "\t*FAILED*"
+	do_shell
+fi
+
+echo "$PRE Proceeding with boot..."
+
+exec chroot . /bin/sh -c "umount /initrd; blockdev --flushbufs /dev/ram0 ; exec /sbin/init $*" < dev/console > dev/console 2>&1
+
+INIT
+   chmod 555 $TMPMNT/sbin/init
+}
+
+# create lvm.conf file from dumpconfig. Just use filter options
+create_lvmconf () {
+    echo 'devices {' > $TMPMNT/etc/lvm/lvm.conf
+    lvm dumpconfig | grep 'filter=' >> $TMPMNT/etc/lvm/lvm.conf
+    echo '}' >> $TMPMNT/etc/lvm/lvm.conf
+}
+
+#
+# Main
+#
+
+cmd=`basename $0`
+
+VERSION=`uname -r`
+
+while [ $# -gt 0 ]; do
+   case $1 in
+   -h|--help) usage; exit 0;;
+   -v|--verbose)  VERBOSE="y";;
+   -c|--lvmconf)  LVMCONF=$2; shift;;
+   -m|--modules)  MODULES=$2; shift;;
+   -e|--extra)    EXTRAFILES=$2; shift;;
+   -r|--raid)     RAID=$2; shift;;
+   -R|--raidconf) RAIDCONF=$2; shift;;
+   -M|--makedev)  MAKEDEV=$2; shift;;
+   [2-9].[0-9]*.[0-9]*) VERSION=$1;;
+   *) echo "$cmd -- invalid option '$1'"; usage; exit 0;;
+   esac
+   shift
+done
+
+INITRD=${INITRD:-"/boot/initrd-lvm2-$VERSION.gz"}
+
+echo "$cmd -- make LVM initial ram disk $INITRD"
+echo ""
+
+if [ -n "$RAID" ]; then
+    BINFILES="$BINFILES /sbin/mdadm"
+    RAIDCONF=${RAIDCONF:-"/etc/mdadm/mdadm.conf"}
+    if [ -r $RAIDCONF ]; then
+	EXTRAFILES="$EXTRAFILES $RAIDCONF"
+    else
+        echo "$cmd -- WARNING: No $RAIDCONF! Your RAID device minor numbers must match their superblock values!"
+    fi
+fi
+
+# add modprobe if we declared any modules
+if [ -n "$MODULES" ]; then
+    BINFILES="$BINFILES /sbin/modprobe /sbin/insmod /sbin/rmmod"
+fi
+
+for a in $BINFILES $EXTRAFILES; do
+    if [ ! -r "$a" ] ; then
+	echo "$cmd -- ERROR: you need $a"
+	exit 1;
+    fi;
+done
+
+# Figure out which shared libraries we actually need in our initrd
+echo "$cmd -- finding required shared libraries"
+verbose "BINFILES: `echo $BINFILES`"
+
+# We need to strip certain lines from ldd output.  This is the full output of an example ldd:
+#lvmhost~ # ldd /sbin/lvm /bin/bash
+#/sbin/lvm:
+#        not a dynamic executable
+#/bin/bash:
+#        linux-gate.so.1 =>  (0xbfffe000)
+#        libncurses.so.5 => /lib/libncurses.so.5 (0xb7ee3000)
+#        libdl.so.2 => /lib/libdl.so.2 (0xb7edf000)
+#        libc.so.6 => /lib/libc.so.6 (0xb7dc1000)
+#        /lib/ld-linux.so.2 (0xb7f28000)
+#
+# 1) Lines with a ":" contain the name of the original binary we're examining, and so are unnecessary.
+#    We need to strip them because they contain "/", and can be confused with links with a hardcoded path.
+# 2) The linux-gate library is a virtual dll that does not exist on disk, but is instead loaded automatically
+#    into the process space, and can't be copied to the ramdisk
+#
+# After these lines have been stripped, we're interested in the lines remaining if they
+# 1) Contain "=>" because they are pathless links, and the value following the token is the path on the disk
+# 2) Contain "/" because it's a link with a hardcoded path, and so we're interested in the link itself.
+LIBFILES=`ldd $BINFILES 2>/dev/null |grep -v -E \(linux-gate\|:\) | awk '{if (/=>/) { print $3 } else if (/\//) { print $1 }}' | sort -u`
+if [ $? -ne 0 ]; then
+   echo "$cmd -- ERROR figuring out needed shared libraries"
+   exit 1
+fi
+
+verbose "Shared libraries needed: `echo $LIBFILES`"
+
+INITRDFILES="$BINFILES $LIBFILES $MODULES $EXTRAFILES"
+
+# tack on stuff for modules if we declared any and the files exist
+if [ -n "$MODULES" ]; then
+    if [ -f "/etc/modprobe.conf" ]; then
+	INITRDFILES="$INITRDFILES /etc/modprobe.conf"
+    fi
+    if [ -f "/lib/modules/modprobe.conf" ]; then
+	INITRDFILES="$INITRDFILES /lib/modules/modprobe.conf"
+    fi
+fi
+
+# Calculate the the size of the ramdisk image.
+# Don't forget that inodes take up space too, as does the filesystem metadata.
+echo "$cmd -- calculating initrd filesystem parameters"
+if [ -z "$INITRDSIZE" ]; then
+   echo "$cmd -- calculating loopback file size"
+   verbose "finding size"
+   INITRDSIZE="`du -Lck $INITRDFILES | tail -1 | cut -f 1`"
+   verbose "minimum: $INITRDSIZE kB for files + inodes + filesystem metadata"
+   INITRDSIZE=`expr $INITRDSIZE + 512`  # enough for ext2 fs + a bit
+fi
+
+echo "$cmd -- making loopback file ($INITRDSIZE kB)"
+verbose "using $DEVRAM as a temporary loopback file"
+dd if=/dev/zero of=$DEVRAM count=$INITRDSIZE bs=1024 > /dev/null 2>&1
+if [ $? -ne 0 ]; then
+   echo "$cmd -- ERROR creating loopback file"
+   cleanup 1
+fi
+
+echo "$cmd -- making ram disk filesystem"
+verbose "mke2fs -F -m0 -L LVM-$VERSION $DEVRAM $INITRDSIZE"
+[ "$VERBOSE" ] && OPT_Q="" || OPT_Q="-q"
+mke2fs $OPT_Q -F -m0 -L LVM-$VERSION $DEVRAM $INITRDSIZE
+if [ $? -ne 0 ]; then
+   echo "$cmd -- ERROR making ram disk filesystem"
+   echo "$cmd -- ERROR you need to use mke2fs >= 1.14 or increase INITRDSIZE"
+   cleanup 1
+fi
+
+verbose "creating mountpoint $TMPMNT"
+mkdir $TMPMNT
+if [ $? -ne 0 ]; then
+   echo "$cmd -- ERROR making $TMPMNT"
+   cleanup 1
+fi
+
+echo "$cmd -- mounting ram disk filesystem"
+verbose "mount -o loop $DEVRAM $TMPMNT"
+mount -oloop $DEVRAM $TMPMNT
+if [ $? -ne 0 ]; then
+   echo "$cmd -- ERROR mounting $DEVRAM on $TMPMNT"
+   cleanup 1
+fi
+
+verbose "creating basic set of directories in $TMPMNT"
+(cd $TMPMNT; mkdir bin dev etc lib proc sbin var)
+if [ $? -ne 0 ]; then
+   echo "$cmd -- ERROR creating directories in $TMPMNT"
+   cleanup 1
+fi
+
+# Add some /dev files. We have to handle different types of MAKEDEV invocations
+# here, so this is rather messy.
+RETCODE=0
+echo "$cmd -- adding required /dev files"
+verbose "BASICDEVICES: `echo $BASICDEVICES`"
+verbose "BLOCKDEVICES: `echo $BLOCKDEVICES`"
+[ "$VERBOSE" ] && OPT_Q="-v" || OPT_Q=""
+case "$MAKEDEV" in 
+debian)
+    (cd $TMPMNT/dev; /dev/MAKEDEV $OPT_Q $BASICDEVICES $BLOCKDEVICES)
+    RETCODE=$?
+    ;;
+redhat)
+    (cd $TMPMNT/dev; /dev/MAKEDEV $OPT_Q -d $TMPMNT/dev -m 2)
+    RETCODE=$?
+    ;;
+gentoo)
+    (cd $TMPMNT/dev; /usr/sbin/MAKEDEV $OPT_Q $BASICDEVICES $BLOCKDEVICES)
+    RETCODE=$?
+    ;;
+*)
+    echo "$cmd -- ERROR: $MAKEDEV is not a known MAKEDEV style."
+    RETCODE=1
+    ;;
+esac
+
+
+if [ $RETCODE -ne 0 ]; then
+   echo "$cmd -- ERROR adding /dev files"
+   cleanup 1
+fi
+
+
+# copy necessary files to ram disk
+echo "$cmd -- copying initrd files to ram disk"
+[ "$VERBOSE" ] && OPT_Q="-v" || OPT_Q="--quiet"
+verbose "find \$INITRDFILES | cpio -pdmL $OPT_Q $TMPMNT"
+find $INITRDFILES | cpio -pdmL $OPT_Q $TMPMNT
+if [ $? -ne 0 ]; then
+   echo "$cmd -- ERROR cpio to ram disk"
+   cleanup 1
+fi
+
+
+echo "$cmd -- creating symlinks to busybox"
+shopt -s extglob
+[ "$VERBOSE" ] && OPT_Q="-v" || OPT_Q=""
+BUSYBOXSYMLINKS=`busybox 2>&1| awk '/^Currently defined functions:$/ {i++;next} i'|tr ',\t\n' ' '`
+for link in ${BUSYBOXSYMLINKS//@(linuxrc|init|busybox)}; do 
+	ln -s $OPT_Q busybox $TMPMNT/bin/$link;
+done
+shopt -u extglob
+
+echo "$cmd -- creating new $TMPMNT/sbin/init"
+create_init
+if [ $? -ne 0 ]; then
+   echo "$cmd -- ERROR creating init"
+   cleanup
+   exit 1
+fi
+
+# copy LVMCONF into place or create a stripped down one from lvm dumpconfig
+mkdir -p $TMPMNT/etc/lvm
+if [ -n "$LVMCONF" ]; then
+    echo "$cmd -- copying $LVMCONF to $TMPMNT/etc/lvm/lvm.conf"
+    if [ -f "$LVMCONF" ]; then
+        cp $LVMCONF $TMPMNT/etc/lvm/lvm.conf
+    else
+        echo "$cmd -- ERROR: $LVMCONF does not exist!"
+	cleanup
+	exit 1
+    fi
+else
+    echo "$cmd -- creating new $TMPMNT/etc/lvm/lvm.conf"
+    create_lvmconf
+fi
+
+if [ -n "$RAID" ]; then
+    RAIDLIST="$TMPMNT/etc/raid_autostart"
+    echo "$cmd -- creating $RAIDLIST file."
+    for device in $RAID; do
+        echo $device >> $RAIDLIST
+    done
+fi
+
+# create modules.dep and /etc/modules files if needed
+if [ -n "$MODULES" ]; then
+    echo "$cmd -- creating $MODDIR/modules.dep file and $TMPMNT/etc/modules"
+    depmod -b $TMPMNT $VERSION
+    for module in $MODULES; do
+        basename $module | sed 's/\.k\{0,1\}o$//' >> $TMPMNT/etc/modules
+    done
+fi
+
+verbose "removing $TMPMNT/lost+found"
+rmdir $TMPMNT/lost+found
+
+echo "$cmd -- ummounting ram disk"
+umount $DEVRAM
+if [ $? -ne 0 ]; then
+   echo "$cmd -- ERROR umounting $DEVRAM"
+   cleanup 1
+fi
+
+echo "$cmd -- creating compressed initrd $INITRD"
+verbose "dd if=$DEVRAM bs=1k count=$INITRDSIZE | gzip -9"
+dd if=$DEVRAM bs=1k count=$INITRDSIZE 2>/dev/null | gzip -9 > $INITRD
+if [ $? -ne 0 ]; then
+   echo "$cmd -- ERROR creating $INITRD"
+   cleanup 1
+fi
+
+
+cat << FINALTXT
+--------------------------------------------------------
+Your initrd is ready in $INITRD
+
+Don't forget to set root=/dev/ram0 in kernel parameters
+Don't forget to set lvm2root=/dev/VG/LV in kernel parameters, where LV is your root volume
+If you use lilo try adding/modifying an entry similar to this one in lilo.conf:
+
+image=/boot/vmlinuz-lvm2-$VERSION
+        label="ramdisk_LVM"
+        initrd=/boot/initrd-lvm2-$VERSION.gz
+        append="root=/dev/ram0 lvm2root=/dev/system/root <other parameters>"
+
+If using grub try adding/modifying an entry similar to this one in menu.lst
+
+title ramdisk LVM
+        kernel /boot/vmlinuz-lvm2-$VERSION root=/dev/ram0 lvm2root=/dev/system/root <other parameters>
+        initrd /boot/initrd-lvm2-$VERSION.gz
+
+You can also pass lvm2rescue to the kernel to get a shell
+--------------------------------------------------------
+FINALTXT
+
+cleanup 0
+
Index: src/external/gpl2/lvm2tools/dist/scripts/lvm2create_initrd/lvm2create_initrd.8
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/scripts/lvm2create_initrd/lvm2create_initrd.8
diff -N src/external/gpl2/lvm2tools/dist/scripts/lvm2create_initrd/lvm2create_initrd.8
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/scripts/lvm2create_initrd/lvm2create_initrd.8	15 Jul 2008 13:50:09 -0000	1.1.1.1
@@ -0,0 +1,281 @@
+.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.14
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sh \" Subsection heading
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  | will give a
+.\" real vertical bar.  \*(C+ will give a nicer C++.  Capital omega is used to
+.\" do unbreakable dashes and therefore won't be available.  \*(C` and \*(C'
+.\" expand to `' in nroff, nothing in troff, for use with C<>.
+.tr \(*W-|\(bv\*(Tr
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` ""
+.    ds C' ""
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+'br\}
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.if \nF \{\
+.    de IX
+.    tm Index:\\$1\t\\n%\t"\\$2"
+..
+.    nr % 0
+.    rr F
+.\}
+.\"
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.hy 0
+.if n .na
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "lvm2create_initrd 8"
+.TH lvm2create_initrd 8 "2004-06-05" "lvm2create_initrd" "create LVM2 initrd"
+.SH "NAME"
+lvm2create_initrd \- create initrd image for booting to root\e\-on\e\-LVM2
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+\&\fBlvm2create_initrd\fR [ \fB\-h|\-\-help\fR ] [ \fB\-v|\-\-verbose\fR ] [ \fB\-c|\-\-lvmconf\fR \fI/path/to/lvm.conf\fR ] [ \fB\-m|\-\-modules\fR "\fImodule1 module2 ...\fR" ] [ \fB\-e|\-\-extra\fR "\fIfile1 file2 ...\fR" ] [ \fB\-r|\-\-raid\fR "\fI/dev/md1 /dev/md2 ...\fR" ]
+[ \fB\-R|\-\-raidconf\fR \fI/path/to/mdadm.conf\fR ] [ \fB\-M|\-\-makedev\fR \fIstyle\fR ]
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+lvm2create_initrd creates an initial ramdisk (initrd) image suitable for booting to system that has an \s-1LVM2\s0 volume as its root filesystem.
+.PP
+To boot to such a setup, you'll
+either need a bootloader that understands \s-1LVM2\s0 volumes, or you'll need a
+filesystem on a regular volume to act as a boot partition (typically mounted
+on /boot).
+.PP
+The resulting initrd image is fairly full\-featured. It can harbor and load
+kernel modules, start \s-1MD\s0 devices, and boot to a shell to perform rescue
+operations.
+.Sh "Booting to your initrd Image:"
+.IX Subsection "Booting to your initrd Image:"
+The filesystem image created is an ext2fs filesystem, hence your kernel must have
+ext2fs built into it statically in order to boot to the image.
+.PP
+Once you create your initrd image, you must pass the correct options to the kernel when
+you boot using it. Your kernel command line should look something like this:
+.PP
+\&\fBroot=/dev/ram0 lvm2root=/dev/rootvg/root [ lvm2rescue ]\fR
+.PP
+of course there may be other options.
+.IP "\fBroot=/dev/ram0\fR" 4
+.IX Item "root=/dev/ram0"
+This option is required. It tells the kernel that the root filesystem should initially
+be set to the ramdisk (/dev/ram0).
+.IP "\fBlvm2root=/dev/rootvg/root\fR" 4
+.IX Item "lvm2root=/dev/rootvg/root"
+This option is also required. It tells the initrd image which \s-1LVM2\s0 device the root filesystem is located on.
+.IP "\fBlvm2rescue\fR" 4
+.IX Item "lvm2rescue"
+Causes the initrd image to run a shell prior to mounting the root filesystem. This is
+helpful in disaster situations where your initrd image is accessable, but there is
+a problem with the root filesystem (corrupted image, incorrect device setup, etc.). This
+option is (of course) optional.
+.SH "OPTIONS"
+.IX Header "OPTIONS"
+Most of parameters that can be set via command-line options can also be set
+via environment variables. Options specified on the command-line always take
+precedence.
+.IP "\fB\-h|\-\-help\fR" 4
+.IX Item "-h|--help"
+Display short help text and exit. If used, other options are ignored.
+.IP "\fB\-v|\-\-verbose\fR" 4
+.IX Item "-v|--verbose"
+Turn on extra verbosity for debugging, etc.
+.IP "\fB\-c|\-\-lvmconf\fR \fI/path/to/lvm.conf\fR" 4
+.IX Item "-c|--lvmconf /path/to/lvm.conf"
+Specify an lvm.conf file to include in the image. This is useful if you have
+special device filters or other options you wish to use during the initrd
+stage. If this option is not
+included, then a lvm.conf file is created that contains only the current
+device filter from an \fBlvm dumpconfig\fR. This can also be set via the \fB$LVMCONF\fR
+environment variable.
+.ie n .IP "\fB\-m|\-\-modules\fR ""\fI/path/to/module1.ko /path/to/module2.ko ...\fR""" 4
+.el .IP "\fB\-m|\-\-modules\fR ``\fI/path/to/module1.ko /path/to/module2.ko ...\fR''" 4
+.IX Item "-m|--modules ""/path/to/module1.ko /path/to/module2.ko ..."""
+Specify modules to include and plug in during the initrd phase. This option
+takes a quoted, space-separated list of modules. Full pathnames are required.
+These modules are loaded into the kernel early in the initrd phase of the boot
+process. The current modprobe.conf file is also copied to the initrd image
+as well. This can also be specified via the \fB$MODULES\fR environment variable.
+.ie n .IP "\fB\-e|\-\-extra\fR ""\fI/path/to/file1 /path/to/file2 ...\fR""" 4
+.el .IP "\fB\-e|\-\-extra\fR ``\fI/path/to/file1 /path/to/file2 ...\fR''" 4
+.IX Item "-e|--extra ""/path/to/file1 /path/to/file2 ..."""
+Extra files that should be included in the initrd image. These files will be
+copied to the same location in the initrd image that they are in the current
+filesystem. Again full pathnames are required. This can also be specified via
+the \fB$EXTRAFILES\fR environment variable.
+.ie n .IP "\fB\-r|\-\-raid\fR ""\fI/dev/md1 /dev/md2...\fR""" 4
+.el .IP "\fB\-r|\-\-raid\fR ``\fI/dev/md1 /dev/md2...\fR''" 4
+.IX Item "-r|--raid ""/dev/md1 /dev/md2..."""
+\&\s-1RAID\s0 devices to be started prior to scanning for \s-1LVM2\s0 volume groups. If this
+option is used then then \fBmdadm\fR program must be installed. This can also be
+specified via the \fB$RAID\fR environment variable.
+.ie n .IP "\fB\-R|\-\-raidconf\fR ""\fI/path/to/mdadm.conf\fR""" 4
+.el .IP "\fB\-R|\-\-raidconf\fR ``\fI/path/to/mdadm.conf\fR''" 4
+.IX Item "-R|--raidconf ""/path/to/mdadm.conf"""
+Location of a mdadm.conf file to include. If this is not specified, then no
+files are included, and any devices specified with the \fB\-r\fR option above
+must have minor numbers that match their superblock values. This can also be
+specified via the \fB$RAIDCONF\fR environment variable.
+.IP "\fB\-M|\-\-makedev\fR \fIstyle\fR" 4
+.IX Item "-M|--makedev style"
+Set \s-1MAKEDEV\s0 invocation style. The script currently supports 2 styles of
+\&\s-1MAKEDEV\s0 programs \fIdebian\fR and \fIredhat\fR. The default is \fIdebian\fR. Set
+to \fIredhat\fR if using the RedHat/Fedora binary \s-1MAKEDEV\s0 program. Please send
+a bug report to maintainer if your distrib doesn't work with any of the
+current options.
+.SH "ENVIRONMENT VARIABLES"
+.IX Header "ENVIRONMENT VARIABLES"
+Most of the options to this script can be set via environment variables. In
+situations where both are set, then the command-line options take precedence.
+.IP "\fB$LVMCONF\fR" 4
+.IX Item "$LVMCONF"
+Same as \-c option.
+.IP "\fB$MODULES\fR" 4
+.IX Item "$MODULES"
+Same as \-m option.
+.IP "\fB$EXTRAFILES\fR" 4
+.IX Item "$EXTRAFILES"
+Same as \-e option.
+.IP "\fB$RAID\fR" 4
+.IX Item "$RAID"
+Same as \-r option.
+.IP "\fB$RAIDCONF\fR" 4
+.IX Item "$RAIDCONF"
+Same as \-R option.
+.IP "\fB$MAKEDEV\fR" 4
+.IX Item "$MAKEDEV"
+Same as \-M option.
+.IP "\fB$BASICDEVICES\fR" 4
+.IX Item "$BASICDEVICES"
+Overrides the default value of \f(CW$BASICDEVICES\fR in the script (which is \*(L"std consoleonly fd\*(R"). These values are passed to the \fB\s-1MAKEDEV\s0\fR program to create device
+entries in the initrd image.
+.IP "\fB$BLOCKDEVICES\fR" 4
+.IX Item "$BLOCKDEVICES"
+Overrides the default value of \f(CW$BLOCKDEVICES\fR in the script (which is \*(L"md hda hdb hdc hdd sda sdb sdc sdd\*(R"). This value is passed to the \fB\s-1MAKEDEV\s0\fR program to
+create device entries in the initrd image.
+.IP "\fB$BINFILES\fR" 4
+.IX Item "$BINFILES"
+Overrides the default value of \f(CW$BINFILES\fR (which is \*(L"/lib/lvm\-200/lvm /bin/bash /bin/busybox /sbin/pivot_root\*(R"). The difference between using this and adding
+a file to the \f(CW$EXTRAFILES\fR list above is that libraries that these depend upon are also included. You can still use \f(CW$EXTRAFILES\fR to achieve the same effect, but
+you must resolve library dependencies youself.
+.IP "\fB$INITRDSIZE\fR" 4
+.IX Item "$INITRDSIZE"
+Force a particular size for your initrd image. The default is to total up the size of
+the included files and to add 512K as a buffer.
+.SH "BUGS"
+.IX Header "BUGS"
+I don't like having to specify a \-M option to set the \s-1MAKEDEV\s0 style, but I know
+of no way to reliably detect what type of \s-1MAKEDEV\s0 is being used. We'll probably
+have to add other \s-1MAKEDEV\s0 styles in the future as this script is tested on
+other distributions.
+.SH "AUTHORS"
+.IX Header "AUTHORS"
+The script was originally written by Miguel Cabeca, with significant
+improvements by Jeffrey Layton. Comments, bug reports and patches should be
+sent to Jeffrey Layton at \fBjtlayton@poochiereds.net\fR.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\fB\s-1MAKEDEV\s0\fR(8), \fBmdadm\fR(8), \fBbusybox\fR(8), \fBlvm.conf\fR(5)
Index: src/external/gpl2/lvm2tools/dist/scripts/lvm2create_initrd/lvm2create_initrd.pod
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/scripts/lvm2create_initrd/lvm2create_initrd.pod
diff -N src/external/gpl2/lvm2tools/dist/scripts/lvm2create_initrd/lvm2create_initrd.pod
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/scripts/lvm2create_initrd/lvm2create_initrd.pod	15 Jul 2008 13:50:12 -0000	1.1.1.1
@@ -0,0 +1,187 @@
+=head1 NAME
+
+lvm2create_initrd - create initrd image for booting to root\-on\-LVM2
+
+=head1 SYNOPSIS
+
+B<lvm2create_initrd> [ B<-h|--help> ] [ B<-v|--verbose> ] [ B<-c|--lvmconf> I</path/to/lvm.conf> ] [ B<-m|--modules> "I<module1 module2 ...>" ] [ B<-e|--extra> "I<file1 file2 ...>" ] [ B<-r|--raid> "I</dev/md1 /dev/md2 ...>" ]
+[ B<-R|--raidconf> I</path/to/mdadm.conf> ] [ B<-M|--makedev> I<style> ]
+
+=head1 DESCRIPTION
+
+lvm2create_initrd creates an initial ramdisk (initrd) image suitable for booting to system that has an LVM2 volume as its root filesystem.
+
+To boot to such a setup, you'll
+either need a bootloader that understands LVM2 volumes, or you'll need a
+filesystem on a regular volume to act as a boot partition (typically mounted
+on /boot).
+
+The resulting initrd image is fairly full-featured. It can harbor and load
+kernel modules, start MD devices, and boot to a shell to perform rescue
+operations.
+
+=head2 Booting to your initrd Image:
+
+The filesystem image created is an ext2fs filesystem, hence your kernel must have
+ext2fs built into it statically in order to boot to the image.
+
+Once you create your initrd image, you must pass the correct options to the kernel when
+you boot using it. Your kernel command line should look something like this:
+
+B<root=/dev/ram0 lvm2root=/dev/rootvg/root [ lvm2rescue ]>
+
+of course there may be other options.
+
+=over
+
+=item B<root=/dev/ram0>
+
+This option is required. It tells the kernel that the root filesystem should initially
+be set to the ramdisk (/dev/ram0).
+
+=item B<lvm2root=/dev/rootvg/root>
+
+This option is also required. It tells the initrd image which LVM2 device the root filesystem is located on.
+
+=item B<lvm2rescue>
+
+Causes the initrd image to run a shell prior to mounting the root filesystem. This is
+helpful in disaster situations where your initrd image is accessable, but there is
+a problem with the root filesystem (corrupted image, incorrect device setup, etc.). This
+option is (of course) optional.
+
+=back
+
+=head1 OPTIONS
+
+Most of parameters that can be set via command-line options can also be set
+via environment variables. Options specified on the command-line always take
+precedence.
+
+=over
+
+=item B<-h|--help>
+
+Display short help text and exit. If used, other options are ignored.
+
+=item B<-v|--verbose>
+
+Turn on extra verbosity for debugging, etc.
+
+=item B<-c|--lvmconf> I</path/to/lvm.conf>
+
+Specify an lvm.conf file to include in the image. This is useful if you have
+special device filters or other options you wish to use during the initrd
+stage. If this option is not
+included, then a lvm.conf file is created that contains only the current
+device filter from an B<lvm dumpconfig>. This can also be set via the B<$LVMCONF>
+environment variable.
+
+=item B<-m|--modules> "I</path/to/module1.ko /path/to/module2.ko ...>"
+
+Specify modules to include and plug in during the initrd phase. This option
+takes a quoted, space-separated list of modules. Full pathnames are required.
+These modules are loaded into the kernel early in the initrd phase of the boot
+process. The current modprobe.conf file is also copied to the initrd image
+as well. This can also be specified via the B<$MODULES> environment variable.
+
+=item B<-e|--extra> "I</path/to/file1 /path/to/file2 ...>"
+
+Extra files that should be included in the initrd image. These files will be
+copied to the same location in the initrd image that they are in the current
+filesystem. Again full pathnames are required. This can also be specified via
+the B<$EXTRAFILES> environment variable.
+
+=item B<-r|--raid> "I</dev/md1 /dev/md2...>"
+
+RAID devices to be started prior to scanning for LVM2 volume groups. If this
+option is used then then B<mdadm> program must be installed. This can also be
+specified via the B<$RAID> environment variable.
+
+=item B<-R|--raidconf> "I</path/to/mdadm.conf>"
+
+Location of a mdadm.conf file to include. If this is not specified, then no
+files are included, and any devices specified with the B<-r> option above
+must have minor numbers that match their superblock values. This can also be
+specified via the B<$RAIDCONF> environment variable.
+
+=item B<-M|--makedev> I<style>
+
+Set MAKEDEV invocation style. The script currently supports 2 styles of
+MAKEDEV programs I<debian> and I<redhat>. The default is I<debian>. Set
+to I<redhat> if using the RedHat/Fedora binary MAKEDEV program. Please send
+a bug report to maintainer if your distrib doesn't work with any of the
+current options.
+
+=back
+
+=head1 ENVIRONMENT VARIABLES
+
+Most of the options to this script can be set via environment variables. In
+situations where both are set, then the command-line options take precedence.
+
+=over
+
+=item B<$LVMCONF>
+
+Same as -c option.
+
+=item B<$MODULES>
+
+Same as -m option.
+
+=item B<$EXTRAFILES>
+
+Same as -e option.
+
+=item B<$RAID>
+
+Same as -r option.
+
+=item B<$RAIDCONF>
+
+Same as -R option.
+
+=item B<$MAKEDEV>
+
+Same as -M option.
+
+=item B<$BASICDEVICES>
+
+Overrides the default value of $BASICDEVICES in the script (which is "std consoleonly fd"). These values are passed to the B<MAKEDEV> program to create device
+entries in the initrd image.
+
+=item B<$BLOCKDEVICES>
+
+Overrides the default value of $BLOCKDEVICES in the script (which is "md hda hdb hdc hdd sda sdb sdc sdd"). This value is passed to the B<MAKEDEV> program to
+create device entries in the initrd image.
+
+=item B<$BINFILES>
+
+Overrides the default value of $BINFILES (which is "/lib/lvm-200/lvm /bin/bash /bin/busybox /sbin/pivot_root"). The difference between using this and adding
+a file to the $EXTRAFILES list above is that libraries that these depend upon are also included. You can still use $EXTRAFILES to achieve the same effect, but
+you must resolve library dependencies youself.
+
+=item B<$INITRDSIZE>
+
+Force a particular size for your initrd image. The default is to total up the size of
+the included files and to add 512K as a buffer.
+
+=back
+
+=head1 BUGS
+
+I don't like having to specify a -M option to set the MAKEDEV style, but I know
+of no way to reliably detect what type of MAKEDEV is being used. We'll probably
+have to add other MAKEDEV styles in the future as this script is tested on
+other distributions.
+
+=head1 AUTHORS
+
+The script was originally written by Miguel Cabeca, with significant
+improvements by Jeffrey Layton. Comments, bug reports and patches should be
+sent to Jeffrey Layton at S<B<jtlayton@poochiereds.net>>.
+
+=head1 SEE ALSO
+
+B<MAKEDEV>(8), B<mdadm>(8), B<busybox>(8), B<lvm.conf>(5)
Index: src/external/gpl2/lvm2tools/dist/scripts/lvm2create_initrd/lvm2udev
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/scripts/lvm2create_initrd/lvm2udev
diff -N src/external/gpl2/lvm2tools/dist/scripts/lvm2create_initrd/lvm2udev
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/scripts/lvm2create_initrd/lvm2udev	15 Jul 2008 13:50:12 -0000	1.1.1.1
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+# $Id$
+
+# simple startup script to create lvm2 devices if /dev is a mountpoint, there
+# are active dm- devices, and an executable /sbin/vgscan.
+
+# this script is licensed under GPLv2.
+# See http://www.gnu.org/licenses/gpl.html
+
+case $1 in
+start)
+    # is /dev a mountpoint?
+    mountpoint -q /dev
+    DEVMNTPOINT=$?
+
+    # check to see if there are active dm entries under /sys
+    ls /sys/block/dm-*/dev 1>/dev/null 2>&1
+    ACTIVEDMDEVS=$?
+
+    # mknodes if conditions are right
+    if [ $DEVMNTPOINT -eq 0 -a $ACTIVEDMDEVS -eq 0 -a -x /sbin/vgscan ]; then
+        /sbin/vgscan --mknodes --ignorelockingfailure
+    fi
+    ;;
+stop)
+    exit 0
+    ;;
+*)
+    echo "usage:"
+    echo "    $0 start|stop"
+    ;;
+esac
Index: src/external/gpl2/lvm2tools/dist/test/.gitignore
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/.gitignore
diff -N src/external/gpl2/lvm2tools/dist/test/.gitignore
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/.gitignore	15 Jul 2008 13:50:12 -0000	1.1.1.1
@@ -0,0 +1,4 @@
+.bin-dir-stamp
+Makefile
+bin
+init.sh
Index: src/external/gpl2/lvm2tools/dist/test/Makefile.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/Makefile.in
diff -N src/external/gpl2/lvm2tools/dist/test/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/Makefile.in	12 Dec 2008 16:33:03 -0000	1.1.1.1.2.1
@@ -0,0 +1,80 @@
+# Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#TEST_OPTS=--verbose --debug
+SHELL_PATH ?= $(SHELL)
+TAR ?= $(TAR)
+RM ?= rm -f
+
+subdir := $(shell pwd|sed 's,.*/,,')
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+top_builddir = @top_builddir@
+abs_srcdir = @abs_srcdir@
+abs_builddir = @abs_builddir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+
+all: init.sh
+	sh harness.sh
+
+init.sh: Makefile.in .bin-dir-stamp
+	rm -f $@-t $@
+	echo 'top_srcdir=$(top_srcdir)' >> $@-t
+	echo 'abs_top_builddir=$(abs_top_builddir)' >> $@-t
+	echo 'abs_top_srcdir=$(abs_top_builddir)' >> $@-t
+	echo 'PATH=$(abs_top_builddir)/test/bin:$$PATH' >> $@-t
+	echo 'export LD_LIBRARY_PATH="$(abs_top_builddir)/libdm:$(abs_top_builddir)/dmeventd"' >> $@-t
+	echo 'abs_srcdir=$(abs_srcdir)' >> $@-t
+	echo 'abs_builddir=$(abs_builddir)' >> $@-t
+	echo 'export PATH' >> $@-t
+	chmod a-w $@-t
+	mv $@-t $@
+
+# Shell quote;
+SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
+
+T = $(wildcard t-*.sh)
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
+$(T): init.sh
+	sh harness.sh $@
+
+.bin-dir-stamp: lvm-wrapper
+	rm -rf bin
+	mkdir bin
+	for i in lvm $$(cat $(top_srcdir)/tools/.commands); do \
+	  ln -s ../lvm-wrapper bin/$$i; \
+	done
+	ln -s "$(abs_top_builddir)/tools/dmsetup" bin/dmsetup
+	touch $@
+
+lvm-wrapper: Makefile
+	rm -f $@-t $@
+	echo '#!/bin/sh'                                          >  $@-t
+	echo 'cmd=$$(echo ./$$0|sed "s,.*/,,")'                   >> $@-t
+	echo 'test "$$cmd" = lvm &&'                              >> $@-t
+	echo 'exec "$(abs_top_builddir)/tools/lvm" "$$@"'         >> $@-t
+	echo 'exec "$(abs_top_builddir)/tools/lvm" "$$cmd" "$$@"' >> $@-t
+	chmod a-w,a+x $@-t
+	mv $@-t $@
+
+clean:
+	rm -rf init.sh lvm-wrapper bin .bin-dir-stamp
+
+distclean: clean
+
+.PHONY: $(T) clean distclean
+.NOTPARALLEL:
Index: src/external/gpl2/lvm2tools/dist/test/harness.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/harness.sh
diff -N src/external/gpl2/lvm2tools/dist/test/harness.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/harness.sh	12 Dec 2008 16:33:03 -0000	1.1.1.1.2.2
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+tests="$@"
+test -z "$tests" && tests=`echo t-*.sh`
+
+for t in $tests; do
+    printf "Running %-40s" "$t ..."
+    out=`bash ./$t 2>&1`
+    ret=$?
+    if test $ret = 0; then
+	echo " passed."
+    elif test $ret = 200; then
+        skipped="$skipped $t"
+	echo " skipped."
+    else
+	echo " FAILED!"
+	len=`echo $t | wc -c`
+	# fancy formatting...
+	printf -- "--- Output: $t -"
+	for i in `seq $(($len + 14)) 78`; do echo -n "-"; done; echo
+	printf "%s\n" "$out"
+	printf -- "--- End: $t ----"
+	for i in `seq $(($len + 14)) 78`; do echo -n "-"; done; echo
+	failed="$failed $t"
+    fi
+done
+
+if test -n "$failed"; then
+    echo "Tests skipped:"
+    for t in $skipped; do
+	printf "\t%s\n" $t
+    done
+    echo "TESTS FAILED:"
+    for t in $failed; do
+	printf "\t%s\n" $t
+    done
+    exit 1
+else
+    echo "All tests passed."
+fi
Index: src/external/gpl2/lvm2tools/dist/test/lvm-utils.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/lvm-utils.sh
diff -N src/external/gpl2/lvm2tools/dist/test/lvm-utils.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/lvm-utils.sh	12 Dec 2008 16:33:03 -0000	1.1.1.1.2.1
@@ -0,0 +1,190 @@
+# Put lvm-related utilities here.
+# This file is sourced from test-lib.sh.
+
+# Copyright (C) 2007, 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+export LVM_SUPPRESS_FD_WARNINGS=1
+
+ME=$(basename "$0")
+warn() { echo >&2 "$ME: $@"; }
+
+unsafe_losetup_()
+{
+  f=$1
+
+  test -n "$G_dev_" \
+    || error "Internal error: unsafe_losetup_ called before init_root_dir_"
+
+  # Iterate through $G_dev_/loop{,/}{0,1,2,3,4,5,6,7,8,9}
+  for slash in '' /; do
+    for i in 0 1 2 3 4 5 6 7 8 9; do
+      dev=$G_dev_/loop$slash$i
+      losetup $dev > /dev/null 2>&1 && continue;
+      losetup "$dev" "$f" > /dev/null && { echo "$dev"; return 0; }
+      break
+    done
+  done
+
+  return 1
+}
+
+loop_setup_()
+{
+  file=$1
+  dd if=/dev/zero of="$file" bs=1M count=1 seek=1000 > /dev/null 2>&1 \
+    || { warn "loop_setup_ failed: Unable to create tmp file $file"; return 1; }
+
+  # NOTE: this requires a new enough version of losetup
+  dev=$(unsafe_losetup_ "$file" 2>/dev/null) \
+    || { warn "loop_setup_ failed: Unable to create loopback device"; return 1; }
+
+  echo "$dev"
+  return 0;
+}
+
+compare_vg_field_()
+{
+    local vg1=$1;
+    local vg2=$2;
+    local field=$3;
+    local val1;
+    local val2;
+
+    val1=$(vgs --noheadings -o $field $vg1)
+    val2=$(vgs --noheadings -o $field $vg2)
+if test "$verbose" = "t"
+then
+  echo "compare_vg_field_ VG1: $val1 VG2: $val2"
+fi
+  return $(test $val1 == $val2 )
+}
+
+check_vg_field_()
+{
+    local vg=$1;
+    local field=$2;
+    local expected=$3;
+    local actual;
+
+    actual=$(vgs --noheadings -o $field $vg)
+if test "$verbose" = "t"
+then
+  echo "check_vg_field_ VG=$vg, field=$field, actual=$actual, expected=$expected"
+fi
+  return $(test $actual == $expected)
+}
+
+check_pv_field_()
+{
+    local pv=$1;
+    local field=$2;
+    local expected=$3;
+    local actual;
+
+    actual=$(pvs --noheadings -o $field $pv)
+if test "$verbose" = "t"
+then
+  echo "check_pv_field_ PV=$pv, field=$field, actual=$actual, expected=$expected"
+fi
+  return $(test $actual == $expected)
+}
+
+check_lv_field_()
+{
+    local lv=$1;
+    local field=$2;
+    local expected=$3;
+    local actual;
+
+    actual=$(lvs --noheadings -o $field $lv)
+if test "$verbose" = "t"
+then
+  echo "check_lv_field_ LV=$lv, field=$field, actual=$actual, expected=$expected"
+fi
+  return $(test $actual == $expected)
+}
+
+vg_validate_pvlv_counts_()
+{
+	local local_vg=$1
+	local num_pvs=$2
+	local num_lvs=$3
+	local num_snaps=$4
+
+	check_vg_field_ $local_vg pv_count $num_pvs &&
+	check_vg_field_ $local_vg lv_count $num_lvs &&
+	check_vg_field_ $local_vg snap_count $num_snaps
+}
+
+dmsetup_has_dm_devdir_support_()
+{
+  # Detect support for the envvar.  If it's supported, the
+  # following command will fail with the expected diagnostic.
+  out=$(DM_DEV_DIR=j dmsetup version 2>&1)
+  test "$?:$out" = "1:Invalid DM_DEV_DIR envvar value." -o \
+       "$?:$out" = "1:Invalid DM_DEV_DIR environment variable value."
+}
+
+# set up private /dev and /etc
+init_root_dir_()
+{
+  test -n "$test_dir_rand_" \
+    || error "Internal error: called init_root_dir_ before" \
+      "defining \$test_dir_rand_"
+
+  # Define these two globals.
+  G_root_=$test_dir_rand_/root
+  G_dev_=$G_root_/dev
+
+  export LVM_SYSTEM_DIR=$G_root_/etc
+  export DM_DEV_DIR=$G_dev_
+
+  # Only the first caller does anything.
+  mkdir -p $G_root_/etc $G_dev_ $G_dev_/mapper $G_root_/lib
+  for i in 0 1 2 3 4 5 6 7; do
+    mknod $G_root_/dev/loop$i b 7 $i
+  done
+  for i in $abs_top_builddir/dmeventd/mirror/*.so $abs_top_builddir/dmeventd/snapshot/*.so
+  do
+    # NOTE: This check is necessary because the loop above will give us the value
+    # "$abs_top_builddir/dmeventd/mirror/*.so" if no files ending in 'so' exist.
+    # This is the best way I could quickly determine to skip over this bogus value.
+    if [ -f $i ]; then
+      echo Setting up symlink from $i to $G_root_/lib
+      ln -s $i $G_root_/lib
+    fi
+  done
+  cat > $G_root_/etc/lvm.conf <<-EOF
+  devices {
+    dir = "$G_dev_"
+    scan = "$G_dev_"
+    filter = [ "a/loop/", "a/mirror/", "a/mapper/", "r/.*/" ]
+    cache_dir = "$G_root_/etc"
+    sysfs_scan = 0
+  }
+  log {
+    verbose = $verboselevel
+    syslog = 0
+    indent = 1
+  }
+  backup {
+    backup = 0
+    archive = 0
+  }
+  global {
+    library_dir = "$G_root_/lib"
+  }
+EOF
+}
+
+if test $(this_test_) != 000-basic; then
+  init_root_dir_
+fi
Index: src/external/gpl2/lvm2tools/dist/test/mkdtemp
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/mkdtemp
diff -N src/external/gpl2/lvm2tools/dist/test/mkdtemp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/mkdtemp	15 Jul 2008 13:50:12 -0000	1.1.1.1
@@ -0,0 +1,120 @@
+#!/bin/sh
+# Create a temporary directory, sort of like mktemp -d does.
+
+# Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+# Written by Jim Meyering.
+
+# Usage: mkdtemp /tmp phoey.XXXXXXXXXX
+
+# First, try to use the mktemp program.
+# Failing that, we'll roll our own mktemp-like function:
+#  - try to get random bytes from /dev/urandom
+#  - failing that, generate output from a combination of quickly-varying
+#      sources and gzip.  Ignore non-varying gzip header, and extract
+#      "random" bits from there.
+#  - given those bits, map to file-name bytes using tr, and try to create
+#      the desired directory.
+#  - make only $MAX_TRIES attempts
+
+ME=$(basename "$0")
+die() { echo >&2 "$ME: $@"; exit 1; }
+
+MAX_TRIES=4
+
+rand_bytes()
+{
+  n=$1
+
+  chars=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
+
+  dev_rand=/dev/urandom
+  if test -r "$dev_rand"; then
+    # Note: 256-length($chars) == 194; 3 copies of $chars is 186 + 8 = 194.
+    head -c$n "$dev_rand" | tr -c $chars 01234567$chars$chars$chars
+    return
+  fi
+
+  cmds='date; date +%N; free; who -a; w; ps auxww; ps ef; netstat -n'
+  data=$( (eval "$cmds") 2>&1 | gzip )
+
+  n_plus_50=$(expr $n + 50)
+
+  # Ensure that $data has length at least 50+$n
+  while :; do
+    len=$(echo "$data"|wc -c)
+    test $n_plus_50 -le $len && break;
+    data=$( (echo "$data"; eval "$cmds") 2>&1 | gzip )
+  done
+
+  echo "$data" \
+    | dd bs=1 skip=50 count=$n 2>/dev/null \
+    | tr -c $chars 01234567$chars$chars$chars
+}
+
+mkdtemp()
+{
+  case $# in
+  2);;
+  *) die "Usage: $ME DIR TEMPLATE";;
+  esac
+
+  destdir=$1
+  template=$2
+
+  case $template in
+  *XXXX) ;;
+  *) die "invalid template: $template (must have a suffix of at least 4 X's)";;
+  esac
+
+  fail=0
+
+  # First, try to use mktemp.
+  d=$(env -u TMPDIR mktemp -d -t -p "$destdir" "$template" 2>/dev/null) \
+    || fail=1
+
+  # The resulting name must be in the specified directory.
+  case $d in "$destdir"*);; *) fail=1;; esac
+
+  # It must have created the directory.
+  test -d "$d" || fail=1
+
+  # It must have 0700 permissions.
+  perms=$(ls -dgo "$d" 2>/dev/null) || fail=1
+  case $perms in drwx------*) ;; *) fail=1;; esac
+
+  test $fail = 0 && {
+    echo "$d"
+    return
+  }
+
+  # If we reach this point, we'll have to create a directory manually.
+
+  # Get a copy of the template without its suffix of X's.
+  base_template=$(echo "$template"|sed 's/XX*$//')
+
+  # Calculate how many X's we've just removed.
+  nx=$(expr length "$template" - length "$base_template")
+
+  err=
+  i=1
+  while :; do
+    X=$(rand_bytes $nx)
+    candidate_dir="$destdir/$base_template$X"
+    err=$(mkdir -m 0700 "$candidate_dir" 2>&1) \
+      && { echo "$candidate_dir"; return; }
+    test $MAX_TRIES -le $i && break;
+    i=$(expr $i + 1)
+  done
+  die "$err"
+}
+
+mkdtemp "$@"
Index: src/external/gpl2/lvm2tools/dist/test/t-000-basic.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-000-basic.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-000-basic.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-000-basic.sh	12 Dec 2008 16:33:03 -0000	1.1.1.1.2.1
@@ -0,0 +1,25 @@
+# Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+. ./test-utils.sh
+
+lvm version
+
+v=$abs_top_srcdir/tools/version.h
+sed -n "/#define LVM_VERSION ./s///p" "$v" | sed "s/ .*//" > expected
+
+lvm pvmove --version|sed -n "1s/.*: *\([0-9][^ ]*\) .*/\1/p" > actual
+
+# ensure they are the same
+diff -u actual expected
+
+# Need mdadm for some pvcreate tests
+# verify mdadm is installed and in path (needed for pvcreate tests) ... is it?
+which mdadm
Index: src/external/gpl2/lvm2tools/dist/test/t-covercmd.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-covercmd.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-covercmd.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-covercmd.sh	12 Dec 2008 16:33:03 -0000	1.1.1.1.2.2
@@ -0,0 +1,77 @@
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#
+# tests basic functionality of read-ahead and ra regressions
+#
+
+. ./test-utils.sh
+
+get_lvs_()
+{
+  case $(lvs --units s --nosuffix --noheadings -o $1_read_ahead "$vg"/"$lv") in
+    *$2) true ;;
+    *) false ;;
+  esac
+}
+
+aux prepare_devs 5
+
+pvcreate $dev1
+pvcreate --metadatacopies 0 $dev2
+pvcreate --metadatacopies 0 $dev3
+pvcreate $dev4
+pvcreate --metadatacopies 0 $dev5
+vgcreate -c n $vg $devs
+lvcreate -n $lv -l 5 -i5 -I256 $vg
+
+# test *scan and *display tools
+pvscan
+vgscan
+lvscan
+lvmdiskscan
+vgdisplay --units k
+lvdisplay --units g
+for i in b k m g t p e H B K M G T P E ; do
+    pvdisplay --units "$i" "$dev1"
+done
+
+# test vgexport vgimport tools
+vgchange -an $vg
+vgexport $vg
+vgimport $vg
+vgchange -ay $vg
+
+# "-persistent y --major 254 --minor 20"
+# "-persistent n"
+# test various lvm utils
+for i in dumpconfig formats segtypes; do
+    lvm "$i"
+done
+
+for i in pr "p rw" an ay "-monitor y" "-monitor n" \
+        -resync -refresh "-addtag MYTAG" "-deltag MYETAG"; do
+    lvchange -$i "$vg"/"$lv"
+done
+
+pvck "$d1"
+vgck "$vg"
+lvrename "$vg" "$lv" "$lv-rename"
+vgcfgbackup -f "$(pwd)/backup.$$" "$vg"
+vgchange -an "$vg"
+vgcfgrestore  -f "$(pwd)/backup.$$" "$vg"
+vgremove -f "$vg"
+pvresize --setphysicalvolumesize 10M "$dev1"
+
+# test various errors and obsoleted tools
+not lvmchange
+not lvrename "$vg"
+not lvrename "$vg-xxx"
+not lvrename "$vg"  "$vg"/"$lv-rename" "$vg"/"$lv"
Index: src/external/gpl2/lvm2tools/dist/test/t-lvcreate-pvtags.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-lvcreate-pvtags.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-lvcreate-pvtags.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-lvcreate-pvtags.sh	12 Dec 2008 16:33:03 -0000	1.1.1.1.2.1
@@ -0,0 +1,42 @@
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+. ./test-utils.sh
+
+aux prepare_pvs 3
+# not required, just testing
+aux pvcreate --metadatacopies 0 $dev1
+
+vgcreate $vg $devs
+pvchange --addtag fast $devs
+
+# 3 stripes with 3 PVs (selected by tag, @fast) is fine
+lvcreate -l3 -i3 $vg @fast
+
+# too many stripes(4) for 3 PVs
+not lvcreate -l4 -i4 $vg @fast
+
+# 2 stripes is too many with just one PV
+not lvcreate -l2 -i2 $vg $G_dev_/mapper/pv1
+
+# lvcreate mirror
+lvcreate -l1 -m1 $vg @fast
+
+# lvcreate mirror w/corelog
+lvcreate -l1 -m2 --corelog $vg @fast
+
+# lvcreate mirror w/no free PVs
+not lvcreate -l1 -m2 $vg @fast
+
+# lvcreate mirror (corelog, w/no free PVs)
+not lvcreate -l1 -m3 --corelog $vg @fast
+
+# lvcreate mirror with a single PV arg
+not lvcreate -l1 -m1 --corelog $vg $dev1
Index: src/external/gpl2/lvm2tools/dist/test/t-lvcreate-usage.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-lvcreate-usage.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-lvcreate-usage.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-lvcreate-usage.sh	12 Dec 2008 16:33:03 -0000	1.1.1.1.2.1
@@ -0,0 +1,60 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+# 'Exercise some lvcreate diagnostics'
+
+. ./test-utils.sh
+
+aux prepare_pvs 2
+aux pvcreate --metadatacopies 0 $dev1
+vgcreate -cn $vg $devs
+
+# "lvcreate rejects repeated invocation (run 2 times) (bz178216)" 
+lvcreate -n $lv -l 4 $vg 
+not lvcreate -n $lv -l 4 $vg
+lvremove -ff $vg/$lv
+
+# "lvcreate rejects a negative stripe_size"
+not lvcreate -L 64M -n $lv -i2 --stripesize -4 $vg 2>err;
+grep "^  Negative stripesize is invalid\$" err
+
+# 'lvcreate rejects a too-large stripesize'
+not lvcreate -L 64M -n $lv -i2 --stripesize 4294967291 $vg 2>err
+grep "^  Stripe size cannot be larger than 512.00 GB\$" err
+
+# 'lvcreate w/single stripe succeeds with diagnostics to stdout' 
+lvcreate -L 64M -n $lv -i1 --stripesize 4 $vg >out 2>err 
+grep "^  Redundant stripes argument: default is 1\$" out 
+grep "^  Ignoring stripesize argument with single stripe\$" out 
+lvdisplay $vg 
+lvremove -ff $vg
+
+# 'lvcreate w/default (64KB) stripe size succeeds with diagnostics to stdout'
+lvcreate -L 64M -n $lv -i2 $vg > out
+grep "^  Using default stripesize" out 
+lvdisplay $vg 
+check_lv_field_ $vg/$lv stripesize "64.00K" 
+lvremove -ff $vg
+
+# 'lvcreate rejects an invalid number of stripes' 
+not lvcreate -L 64M -n $lv -i129 $vg 2>err
+grep "^  Number of stripes (129) must be between 1 and 128\$" err
+
+# 'lvcreate rejects an invalid regionsize (bz186013)' 
+not lvcreate -L 64M -n $lv -R0 $vg 2>err
+grep "Non-zero region size must be supplied." err
+
+# The case on lvdisplay output is to verify that the LV was not created.
+# 'lvcreate rejects an invalid stripe size'
+not lvcreate -L 64M -n $lv -i2 --stripesize 3 $vg 2>err
+grep "^  Invalid stripe size 3\.00 KB\$" err
+case $(lvdisplay $vg) in "") true ;; *) false ;; esac
+
Index: src/external/gpl2/lvm2tools/dist/test/t-lvextend-percent-extents.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-lvextend-percent-extents.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-lvextend-percent-extents.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-lvextend-percent-extents.sh	12 Dec 2008 16:33:03 -0000	1.1.1.1.2.1
@@ -0,0 +1,74 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+# 'Check extents percentage arguments'
+
+. ./test-utils.sh
+
+aux prepare_vg 2 128
+
+lvcreate -L 64M -n $lv $vg
+
+# 'lvextend rejects both size and extents without PVs'
+not lvextend -l 10 -L 64M $vg/$lv 2>err
+grep "^  Please specify either size or extents but not both.\$" err
+
+# 'lvextend rejects both size and extents with PVs'
+not lvextend -l 10 -L 64M $vg/$lv $dev1 2>err
+grep "^  Please specify either size or extents but not both.\$" err
+
+# 'lvextend accepts no size or extents but one PV - bz154691'
+lvextend $vg/$lv $dev1 >out
+grep "^  Logical volume $lv successfully resized\$" out
+check_pv_field_ $dev1 pv_free "0"
+
+# 'Reset LV to original size' 
+lvremove -f $vg/$lv 
+lvcreate -L 64M -n $lv $vg
+
+# 'lvextend accepts no size but extents 100%PVS and two PVs - bz154691'
+lvextend -l +100%PVS $vg/$lv $dev1 $dev2 >out
+grep "^  Logical volume $lv successfully resized\$" out 
+check_pv_field_ $dev1 pv_free "0" 
+check_pv_field_ $dev2 pv_free "0"
+
+# Exercise the range overlap code.  Allocate every 2 extents.
+#
+#      Physical Extents
+#          1         2
+#012345678901234567890123
+#
+#aaXXaaXXaaXXaaXXaaXXaaXX - (a)llocated
+#rrrXXXrrrXXXrrrXXXrrrXXX - (r)ange on cmdline
+#ooXXXXXXoXXXooXXXXXXoXXX - (o)verlap of range and allocated
+#
+# Key: a - allocated
+#      F - free
+#      r - part of a range on the cmdline
+#      N - not on cmdline
+#
+# Create the LV with 12 extents, allocated every other 2 extents.
+# Then extend it, with a range of PVs on the cmdline of every other 3 extents.
+# Total number of extents should be 12 + overlap = 12 + 6 = 18.
+# Thus, total size for the LV should be 18 * 4M = 72M
+#
+# 'Reset LV to 12 extents, allocate every other 2 extents' 
+create_pvs=`for i in $(seq 0 4 20); do echo -n "\$dev1:$i-$(($i + 1)) "; done` 
+lvremove -f $vg/$lv
+lvcreate -l 12 -n $lv $vg $create_pvs
+check_lv_field_ $vg/$lv lv_size "48.00M"
+
+# 'lvextend with partially allocated PVs and extents 100%PVS with PE ranges' 
+extend_pvs=`for i in $(seq 0 6 18); do echo -n "\$dev1:$i-$(($i + 2)) "; done` 
+lvextend -l +100%PVS $vg/$lv $extend_pvs >out
+grep "^  Logical volume $lv successfully resized\$" out 
+check_lv_field_ $vg/$lv lv_size "72.00M"
+
Index: src/external/gpl2/lvm2tools/dist/test/t-lvmcache-exercise.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-lvmcache-exercise.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-lvmcache-exercise.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-lvmcache-exercise.sh	12 Dec 2008 16:33:03 -0000	1.1.1.1.2.1
@@ -0,0 +1,23 @@
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+. ./test-utils.sh
+
+aux prepare_pvs 5
+
+vgcreate $vg1 $dev1
+vgcreate $vg2 $dev3
+
+disable_dev $dev1
+pvscan
+vgcreate $vg1 $dev2
+enable_dev $dev1
+pvs
+pvs
Index: src/external/gpl2/lvm2tools/dist/test/t-lvresize-usage.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-lvresize-usage.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-lvresize-usage.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-lvresize-usage.sh	12 Dec 2008 16:33:03 -0000	1.1.1.1.2.1
@@ -0,0 +1,20 @@
+# Copyright (C) 2007-2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+. ./test-utils.sh
+
+aux prepare_vg 2
+
+lvcreate -L 10M -n lv -i2 $vg
+lvresize -l +4 $vg/lv
+lvremove -ff $vg
+
+lvcreate -L 64M -n $lv -i2 $vg
+not lvresize -v -l +4 xxx/$lv
Index: src/external/gpl2/lvm2tools/dist/test/t-mdata-strings.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-mdata-strings.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-mdata-strings.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-mdata-strings.sh	12 Dec 2008 16:33:03 -0000	1.1.1.1.2.1
@@ -0,0 +1,33 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+# 'Test for proper escaping of strings in metadata (bz431474)'
+
+. ./test-utils.sh
+
+aux prepare_devs 1
+
+pv_suffix="__\"!@#\$%^&*()'\\\"__"
+
+# 'set up temp files, loopback devices' 
+name=$(basename "$dev1")
+dmsetup rename "$name" "$name$pv_suffix" 
+dev1=$(dirname "$dev1")/$name$pv_suffix
+
+# 'pvcreate, vgcreate on filename with backslashed chars' 
+pvcreate "$dev1" 
+vgcreate $vg "$dev1"
+
+# 'no parse errors and VG really exists' 
+vgs 2>err
+not grep "Parse error" err;
+vgs $vg
+
Index: src/external/gpl2/lvm2tools/dist/test/t-metadata.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-metadata.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-metadata.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-metadata.sh	12 Dec 2008 16:33:03 -0000	1.1.1.1.2.2
@@ -0,0 +1,35 @@
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+. ./test-utils.sh
+
+aux prepare_devs 5
+
+pvcreate $dev1
+pvcreate --metadatacopies 0 $dev2
+pvcreate --metadatacopies 0 $dev3
+pvcreate $dev4
+pvcreate --metadatacopies 0 $dev5
+
+vgcreate -c n "$vg" $devs
+lvcreate -n $lv -l 1 -i5 -I256 $vg
+
+pvchange -x n $dev1
+pvchange -x y $dev1
+vgchange -a n $vg
+pvchange --uuid $dev1
+pvchange --uuid $dev2
+vgremove -f $vg
+
+pvcreate -M1 $dev1
+pvcreate -M1 $dev2
+pvcreate -M1 $dev3
+vgcreate -M1 $vg $dev1 $dev2 $dev3
+pvchange --uuid $dev1
Index: src/external/gpl2/lvm2tools/dist/test/t-mirror-basic.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-mirror-basic.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-mirror-basic.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-mirror-basic.sh	12 Dec 2008 16:33:03 -0000	1.1.1.1.2.1
@@ -0,0 +1,284 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+# Copyright (C) 2007 NEC Corporation
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+test_description="ensure that basic operations on mirrored LV works"
+
+. ./test-utils.sh
+
+dmsetup_has_dm_devdir_support_ || exit 200
+
+# ---------------------------------------------------------------------
+# Utilities
+
+lvdev_()
+{
+  echo "$G_dev_/$1/$2"
+}
+
+mimages_are_redundant_ ()
+{
+  local vg=$1
+  local lv=$vg/$2
+  local i
+
+  rm -f out
+  for i in $(lvs -odevices --noheadings $lv | sed 's/([^)]*)//g; s/,/ /g'); do
+    lvs -a -odevices --noheadings $vg/$i | sed 's/([^)]*)//g; s/,/ /g' | \
+      sort | uniq >> out
+  done
+
+  # if any duplication is found, it's not redundant
+  sort out | uniq -d | grep . && return 1
+
+  return 0
+}
+
+lv_is_contiguous_ ()
+{
+  local lv=$1
+
+  # if the lv has multiple segments, it's not contiguous
+  [ $(lvs -a --segments --noheadings $lv | wc -l) -ne 1 ] && return 1
+
+  return 0
+}
+
+lv_is_clung_ ()
+{
+  local lv=$1
+
+  # if any duplication is found, it's not redundant
+  [ $(lvs -a -odevices --noheadings $lv | sed 's/([^)]*)//g' | \
+        sort | uniq | wc -l) -ne 1 ] && return 1
+
+  return 0
+}
+
+mimages_are_contiguous_ ()
+{
+  local vg=$1
+  local lv=$vg/$2
+  local i
+
+  for i in $(lvs -odevices --noheadings $lv | sed 's/([^)]*)//g; s/,/ /g'); do
+    lv_is_contiguous_ $vg/$i || return 1
+  done
+
+  return 0
+}
+
+mimages_are_clung_ ()
+{
+  local vg=$1
+  local lv=$vg/$2
+  local i
+
+  for i in $(lvs -odevices --noheadings $lv | sed 's/([^)]*)//g; s/,/ /g'); do
+    lv_is_clung_ $vg/$i || return 1
+  done
+
+  return 0
+}
+
+mirrorlog_is_on_()
+{
+  local lv="$1"_mlog
+  shift 1
+  lvs -a -odevices --noheadings $lv | sed 's/,/\n/g' > out
+  for d in $*; do grep "$d(" out; done
+  for d in $*; do ! grep -v "$d(" out; done
+  return 0
+}
+
+save_dev_sum_()
+{
+  mkfs.ext3 $1 > /dev/null &&
+  md5sum $1 > md5.$(basename $1)
+}
+
+check_dev_sum_()
+{
+  md5sum $1 > md5.tmp && cmp md5.$(basename $1) md5.tmp
+}
+
+# ---------------------------------------------------------------------
+# Initialize PVs and VGs
+
+aux prepare_vg 5 80
+
+# ---------------------------------------------------------------------
+# Common environment setup/cleanup for each sub testcases
+
+prepare_lvs_()
+{
+  lvremove -ff $vg;
+	if dmsetup table|grep $vg; then
+		echo "ERROR: lvremove did leave some some mappings in DM behind!"
+		return 1
+	fi
+  :
+}
+
+check_and_cleanup_lvs_()
+{
+  lvs -a -o+devices $vg
+  lvremove -ff $vg
+	if dmsetup table|grep $vg; then
+		echo "ERROR: lvremove did leave some some mappings in DM behind!"
+		return 1
+	fi
+}
+
+#COMM "check environment setup/cleanup"
+prepare_lvs_ 
+check_and_cleanup_lvs_
+
+# ---------------------------------------------------------------------
+# mirrored LV tests
+
+# ---
+# create
+
+#COMM "create 2-way mirror with disklog from 3 PVs"
+prepare_lvs_ 
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1 
+mimages_are_redundant_ $vg $lv1 
+mirrorlog_is_on_ $vg/$lv1 $dev3 
+check_and_cleanup_lvs_
+
+#COMM "create 2-way mirror with corelog from 2 PVs"
+prepare_lvs_ 
+lvcreate -l2 -m1 --mirrorlog core -n $lv1 $vg $dev1 $dev2 
+mimages_are_redundant_ $vg $lv1 
+check_and_cleanup_lvs_
+
+#COMM "create 3-way mirror with disklog from 4 PVs"
+prepare_lvs_ 
+lvcreate -l2 -m2 -n $lv1 $vg $dev1 $dev2 $dev4 $dev3:0-1 
+mimages_are_redundant_ $vg $lv1 
+mirrorlog_is_on_ $vg/$lv1 $dev3 
+check_and_cleanup_lvs_
+
+#COMM "lvcreate --nosync is in 100% sync after creation (bz429342)"
+prepare_lvs_ 
+lvcreate -l2 -m1 --nosync -n $lv1 $vg $dev1 $dev2 $dev3:0-1 2>out
+grep "New mirror won't be synchronised." out
+lvs -o copy_percent --noheadings $vg/$lv1 |grep 100.00
+check_and_cleanup_lvs_
+
+# ---
+# convert
+
+#COMM "convert from linear to 2-way mirror"
+prepare_lvs_ 
+lvcreate -l2 -n $lv1 $vg $dev1 
+lvconvert -m+1 $vg/$lv1 $dev2 $dev3:0-1 
+mimages_are_redundant_ $vg $lv1 
+mirrorlog_is_on_ $vg/$lv1 $dev3 
+check_and_cleanup_lvs_
+
+#COMM "convert from 2-way mirror to linear"
+prepare_lvs_ 
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1 
+lvconvert -m-1 $vg/$lv1 
+mimages_are_redundant_ $vg $lv1 
+check_and_cleanup_lvs_
+
+for status in active inactive; do 
+# bz192865 lvconvert log of an inactive mirror lv
+#COMM "convert from disklog to corelog"
+prepare_lvs_ 
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1 
+	test $status = "inactive" && lvchange -an $vg/$lv1
+	yes | lvconvert --mirrorlog core $vg/$lv1 
+mimages_are_redundant_ $vg $lv1 
+check_and_cleanup_lvs_
+
+#COMM "convert from corelog to disklog"
+prepare_lvs_ 
+lvcreate -l2 -m1 --mirrorlog core -n $lv1 $vg $dev1 $dev2 
+	test $status = "inactive" && lvchange -an $vg/$lv1
+lvconvert --mirrorlog disk $vg/$lv1 $dev3:0-1 
+mimages_are_redundant_ $vg $lv1 
+mirrorlog_is_on_ $vg/$lv1 $dev3 
+check_and_cleanup_lvs_
+done
+
+# ---
+# resize
+
+#COMM "extend 2-way mirror"
+prepare_lvs_ 
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1 
+lvchange -an $vg/$lv1 
+lvextend -l+2 $vg/$lv1 
+mimages_are_redundant_ $vg $lv1 
+mimages_are_contiguous_ $vg $lv1 
+check_and_cleanup_lvs_
+
+#COMM "reduce 2-way mirror"
+prepare_lvs_ 
+lvcreate -l4 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1 
+lvchange -an $vg/$lv1 
+lvreduce -l-2 $vg/$lv1 
+check_and_cleanup_lvs_
+
+#COMM "extend 2-way mirror (cling if not contiguous)"
+prepare_lvs_ 
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1 
+lvcreate -l1 -n $lv2 $vg $dev1 
+lvcreate -l1 -n $lv3 $vg $dev2 
+lvchange -an $vg/$lv1 
+lvextend -l+2 $vg/$lv1 
+mimages_are_redundant_ $vg $lv1 
+mimages_are_clung_ $vg $lv1 
+check_and_cleanup_lvs_
+
+# ---
+# failure cases
+
+#COMM "create 2-way mirror with disklog from 2 PVs"
+prepare_lvs_ 
+not lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2
+# "(cleanup previous test)"
+check_and_cleanup_lvs_
+
+#COMM "convert linear to 2-way mirror with 1 PV"
+prepare_lvs_ 
+lvcreate -l2 -n $lv1 $vg $dev1 
+not lvconvert -m+1 --mirrorlog core $vg/$lv1 $dev1
+# "(cleanup previous test)"
+check_and_cleanup_lvs_
+
+# ---
+# resync
+# FIXME: using dm-delay to properly check whether the resync really started
+
+#COMM "force resync 2-way active mirror"
+prepare_lvs_ 
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1 
+mirrorlog_is_on_ $vg/$lv1 $dev3 
+yes | lvchange --resync $vg/$lv1 
+mirrorlog_is_on_ $vg/$lv1 $dev3 
+check_and_cleanup_lvs_
+
+#COMM "force resync 2-way inactive mirror"
+prepare_lvs_ 
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1 
+lvchange -an $vg/$lv1 
+mirrorlog_is_on_ $vg/$lv1 $dev3 
+lvchange --resync $vg/$lv1 
+mirrorlog_is_on_ $vg/$lv1 $dev3 
+check_and_cleanup_lvs_
+
+# ---------------------------------------------------------------------
+
Index: src/external/gpl2/lvm2tools/dist/test/t-mirror-lvconvert.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-mirror-lvconvert.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-mirror-lvconvert.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-mirror-lvconvert.sh	12 Dec 2008 16:33:03 -0000	1.1.1.1.2.1
@@ -0,0 +1,315 @@
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+# Copyright (C) 2007 NEC Corporation
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+. ./test-utils.sh
+
+dmsetup_has_dm_devdir_support_ || exit 200
+
+mimages_are_redundant_ ()
+{
+  local vg=$1
+  local lv=$vg/$2
+  local i
+
+  rm -f out
+  for i in $(lvs -odevices --noheadings $lv | sed 's/([^)]*)//g; s/,/ /g'); do
+    lvs -a -odevices --noheadings $vg/$i | sed 's/([^)]*)//g; s/,/ /g' | \
+      sort | uniq >> out
+  done
+
+  # if any duplication is found, it's not redundant
+  sort out | uniq -d | grep . && return 1
+
+  return 0
+}
+
+lv_is_contiguous_ ()
+{
+  local lv=$1
+
+  # if the lv has multiple segments, it's not contiguous
+  [ $(lvs -a --segments --noheadings $lv | wc -l) -ne 1 ] && return 1
+
+  return 0
+}
+
+mimages_are_contiguous_ ()
+{
+  local vg=$1
+  local lv=$vg/$2
+  local i
+
+  for i in $(lvs -odevices --noheadings $lv | sed 's/([^)]*)//g; s/,/ /g'); do
+    lv_is_contiguous_ $vg/$i || return 1
+  done
+
+  return 0
+}
+
+mirrorlog_is_on_()
+{
+  local lv="$1"_mlog
+  shift 1
+  lvs -a -odevices --noheadings $lv | sed 's/,/\n/g' > out
+  for d in $*; do grep "$d(" out || return 1; done
+  for d in $*; do grep -v "$d(" out > out2 || true; mv out2 out; done
+  grep . out && return 1
+  return 0
+}
+
+save_dev_sum_()
+{
+  mkfs.ext3 $1 > /dev/null &&
+  md5sum $1 > md5.$(basename $1)
+}
+
+check_dev_sum_()
+{
+  md5sum $1 > md5.tmp && cmp md5.$(basename $1) md5.tmp
+}
+
+check_mirror_count_()
+{
+  local lv=$1
+  local mirrors=$2
+  [ "$mirrors" -eq "$(lvs --noheadings -ostripes $lv)" ]
+}
+
+check_mirror_log_()
+{
+  local lv=$1
+  local mlog=$(lvs --noheadings -omirror_log $lv | sed -e 's/ //g')
+  [ "$(basename $lv)_mlog" = "$mlog" ]
+}
+
+wait_conversion_()
+{
+  local lv=$1
+  while (lvs --noheadings -oattr "$lv" | grep -q '^ *c'); do sleep 1; done
+}
+
+check_no_tmplvs_()
+{
+  local lv=$1
+  lvs -a --noheadings -oname $(dirname $lv) > out
+  ! grep tmp out
+}
+
+aux prepare_vg 5
+
+# ---------------------------------------------------------------------
+# Common environment setup/cleanup for each sub testcases
+
+prepare_lvs_()
+{
+  lvremove -ff $vg
+	if dmsetup table|grep $vg; then
+		echo "ERROR: lvremove did leave some some mappings in DM behind!"
+		return 1
+	fi
+	:
+}
+
+check_and_cleanup_lvs_()
+{
+  lvs -a -o+devices $vg
+  lvremove -ff $vg
+	if dmsetup table|grep $vg; then
+		echo "ERROR: lvremove did leave some some mappings in DM behind!"
+		return 1
+	fi
+}
+
+prepare_lvs_
+check_and_cleanup_lvs_
+
+# ---------------------------------------------------------------------
+# mirrored LV tests
+
+# ---
+# add mirror to mirror
+
+# add 1 mirror
+prepare_lvs_
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1
+check_mirror_count_ $vg/$lv1 2
+check_mirror_log_ $vg/$lv1
+lvconvert -m+1 -i1 $vg/$lv1 $dev4
+check_no_tmplvs_ $vg/$lv1
+check_mirror_count_ $vg/$lv1 3
+mimages_are_redundant_ $vg $lv1
+mirrorlog_is_on_ $vg/$lv1 $dev3
+check_and_cleanup_lvs_
+
+# add 2 mirrors
+prepare_lvs_
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1
+check_mirror_count_ $vg/$lv1 2
+check_mirror_log_ $vg/$lv1
+lvconvert -m+2 -i1 $vg/$lv1 $dev4 $dev5
+check_no_tmplvs_ $vg/$lv1
+check_mirror_count_ $vg/$lv1 4
+mimages_are_redundant_ $vg $lv1
+mirrorlog_is_on_ $vg/$lv1 $dev3
+check_and_cleanup_lvs_
+
+# add 1 mirror to core log mirror
+prepare_lvs_
+lvcreate -l2 -m1 --mirrorlog core -n $lv1 $vg $dev1 $dev2
+check_mirror_count_ $vg/$lv1 2
+not check_mirror_log_ $vg/$lv1
+lvconvert -m+1 -i1 --mirrorlog core $vg/$lv1 $dev4 
+check_no_tmplvs_ $vg/$lv1 
+check_mirror_count_ $vg/$lv1 3 
+not check_mirror_log_ $vg/$lv1
+mimages_are_redundant_ $vg $lv1 
+check_and_cleanup_lvs_
+
+# add 2 mirrors to core log mirror" 
+prepare_lvs_ 
+lvcreate -l2 -m1 --mirrorlog core -n $lv1 $vg $dev1 $dev2 
+check_mirror_count_ $vg/$lv1 2 
+not check_mirror_log_ $vg/$lv1 
+lvconvert -m+2 -i1 --mirrorlog core $vg/$lv1 $dev4 $dev5 
+check_no_tmplvs_ $vg/$lv1 
+check_mirror_count_ $vg/$lv1 4 
+not check_mirror_log_ $vg/$lv1
+mimages_are_redundant_ $vg $lv1 
+check_and_cleanup_lvs_
+
+# ---
+# add to converting mirror
+
+# add 1 mirror then add 1 more mirror during conversion
+prepare_lvs_
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1
+check_mirror_count_ $vg/$lv1 2
+check_mirror_log_ $vg/$lv1
+lvconvert -m+1 -b $vg/$lv1 $dev4
+lvconvert -m+1 -i3 $vg/$lv1 $dev5
+check_no_tmplvs_ $vg/$lv1
+check_mirror_count_ $vg/$lv1 4
+mimages_are_redundant_ $vg $lv1
+mirrorlog_is_on_ $vg/$lv1 $dev3
+check_and_cleanup_lvs_
+
+# ---
+# add mirror and disk log
+
+# "add 1 mirror and disk log" 
+prepare_lvs_ 
+lvcreate -l2 -m1 --mirrorlog core -n $lv1 $vg $dev1 $dev2 
+check_mirror_count_ $vg/$lv1 2 
+not check_mirror_log_ $vg/$lv1 
+lvconvert -m+1 --mirrorlog disk -i1 $vg/$lv1 $dev4 $dev3:0-1 
+check_no_tmplvs_ $vg/$lv1 
+check_mirror_count_ $vg/$lv1 3 
+check_mirror_log_ $vg/$lv1 
+mimages_are_redundant_ $vg $lv1 
+mirrorlog_is_on_ $vg/$lv1 $dev3 
+check_and_cleanup_lvs_
+
+# ---
+# check polldaemon restarts
+
+# convert inactive mirror and start polling
+prepare_lvs_
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1
+check_mirror_count_ $vg/$lv1 2
+lvchange -an $vg/$lv1
+lvconvert -m+1 $vg/$lv1 $dev4
+lvchange -ay $vg/$lv1
+wait_conversion_ $vg/$lv1
+lvs -a
+check_no_tmplvs_ $vg/$lv1
+check_and_cleanup_lvs_
+
+# ---------------------------------------------------------------------
+# removal during conversion
+
+# "remove newly added mirror" 
+prepare_lvs_ 
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1 
+check_mirror_count_ $vg/$lv1 2 
+check_mirror_log_ $vg/$lv1 
+lvconvert -m+1 -b $vg/$lv1 $dev4 
+lvconvert -m-1 $vg/$lv1 $dev4 
+wait_conversion_ $vg/$lv1 
+check_no_tmplvs_ $vg/$lv1 
+check_mirror_count_ $vg/$lv1 2 
+mimages_are_redundant_ $vg $lv1 
+mirrorlog_is_on_ $vg/$lv1 $dev3 
+check_and_cleanup_lvs_
+
+# "remove one of newly added mirrors" 
+prepare_lvs_ 
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1 
+check_mirror_count_ $vg/$lv1 2 
+check_mirror_log_ $vg/$lv1 
+lvconvert -m+2 -b $vg/$lv1 $dev4 $dev5 
+lvconvert -m-1 $vg/$lv1 $dev4 
+lvconvert -i1 $vg/$lv1 
+wait_conversion_ $vg/$lv1 
+check_no_tmplvs_ $vg/$lv1 
+check_mirror_count_ $vg/$lv1 3 
+mimages_are_redundant_ $vg $lv1 
+mirrorlog_is_on_ $vg/$lv1 $dev3 
+check_and_cleanup_lvs_
+
+# "remove from original mirror (the original is still mirror)"
+prepare_lvs_ 
+lvcreate -l2 -m2 -n $lv1 $vg $dev1 $dev2 $dev5 $dev3:0-1 
+check_mirror_count_ $vg/$lv1 3 
+check_mirror_log_ $vg/$lv1 
+lvconvert -m+1 -b $vg/$lv1 $dev4 
+lvconvert -m-1 $vg/$lv1 $dev2 
+lvconvert -i1 $vg/$lv1 
+wait_conversion_ $vg/$lv1 
+check_no_tmplvs_ $vg/$lv1 
+check_mirror_count_ $vg/$lv1 3 
+mimages_are_redundant_ $vg $lv1 
+mirrorlog_is_on_ $vg/$lv1 $dev3 
+check_and_cleanup_lvs_
+
+# "remove from original mirror (the original becomes linear)"
+prepare_lvs_ 
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1 
+check_mirror_count_ $vg/$lv1 2 
+check_mirror_log_ $vg/$lv1 
+lvconvert -m+1 -b $vg/$lv1 $dev4 
+lvconvert -m-1 $vg/$lv1 $dev2 
+lvconvert -i1 $vg/$lv1 
+wait_conversion_ $vg/$lv1 
+check_no_tmplvs_ $vg/$lv1 
+check_mirror_count_ $vg/$lv1 2 
+mimages_are_redundant_ $vg $lv1 
+mirrorlog_is_on_ $vg/$lv1 $dev3 
+check_and_cleanup_lvs_
+
+# ---------------------------------------------------------------------
+
+# "rhbz440405: lvconvert -m0 incorrectly fails if all PEs allocated"
+prepare_lvs_ 
+lvcreate -l`pvs --noheadings -ope_count $dev1` -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0 
+check_mirror_count_ $vg/$lv1 2 
+check_mirror_log_ $vg/$lv1 
+lvconvert -m0 $vg/$lv1 $dev1 
+check_no_tmplvs_ $vg/$lv1 
+check_mirror_count_ $vg/$lv1 1 
+check_and_cleanup_lvs_
+
+# "rhbz264241: lvm mirror doesn't lose it's "M" --nosync attribute after being down and the up converted"
+prepare_lvs_
+lvcreate -l2 -m1 -n$lv1 --nosync $vg 
+lvconvert -m0 $vg/$lv1
+lvconvert -m1 $vg/$lv1
+lvs --noheadings -o attr $vg/$lv1 | grep '^ *m'
+
Index: src/external/gpl2/lvm2tools/dist/test/t-mirror-names.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-mirror-names.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-mirror-names.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-mirror-names.sh	12 Dec 2008 16:33:04 -0000	1.1.1.1.2.1
@@ -0,0 +1,158 @@
+#!/bin/sh
+# Copyright (C) 2007-2008 Red Hat, Inc. All rights reserved.
+# Copyright (C) 2007-2008 NEC Corporation
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+test_description="check namings of mirrored LV"
+
+. ./test-utils.sh
+
+dmsetup_has_dm_devdir_support_ || exit 200
+
+# ---------------------------------------------------------------------
+# Utilities
+
+lv_devices_() {
+  local d
+  local lv=$1
+  shift
+  local devices=$*
+
+  local devs=$(lvs -a -odevices --noheadings $lv | sed 's/([0-9]*)//g' |
+               sed 's/ //g' | sed 's/,/ /g')
+
+  for d in $devs; do
+    (echo $devices | grep -q $d)  || return 1
+    devices=$(echo $devices | sed "s/$d//")
+  done
+
+  [ "$(echo $devices | sed 's/ //g')" = "" ]
+}
+
+lv_mirror_log_() {
+  local lv=$1
+
+  echo $(lvs -a -omirror_log --noheadings $lv | sed 's/ //g')
+}
+
+lv_convert_lv_() {
+  local lv=$1
+
+  echo $(lvs -a -oconvert_lv --noheadings $lv | sed 's/ //g')
+}
+
+# ---------------------------------------------------------------------
+# Initialize PVs and VGs
+
+aux prepare_vg 5 80
+
+# ---------------------------------------------------------------------
+# Common environment setup/cleanup for each sub testcases
+
+prepare_lvs_() {
+	lvremove -ff $vg
+	if dmsetup table|grep $vg; then
+		echo "ERROR: lvremove did leave some some mappings in DM behind!"
+		return 1
+	fi
+  :
+}
+
+check_and_cleanup_lvs_() {
+  lvs -a -o+devices $vg 
+  lvremove -ff $vg
+	if dmsetup table|grep $vg; then
+		echo "ERROR: lvremove did leave some some mappings in DM behind!"
+		return 1
+	fi
+}
+
+prepare_lvs_ 
+check_and_cleanup_lvs_
+
+# ---------------------------------------------------------------------
+# basic
+
+#COMM "init: lvcreate" 
+prepare_lvs_
+
+#COMM "mirror images are ${lv1}_mimage_x"
+lvcreate -l2 -m1 -n $lv1 $vg 
+lv_devices_ $vg/$lv1 "$lv1"_mimage_0 "$lv1"_mimage_1
+
+#COMM "mirror log is ${lv1}_mlog"
+lv_mirror_log_ $vg/$lv1 "$lv1"_mlog
+
+# "cleanup" 
+check_and_cleanup_lvs_
+
+#COMM "mirror with name longer than 22 characters (bz221322)"
+name="LVwithanamelogerthan22characters_butidontwonttocounthem"
+lvcreate -m1 -l2 -n"$name" $vg
+lvs $vg/"$name"
+check_and_cleanup_lvs_
+
+# ---------------------------------------------------------------------
+# lvrename
+
+#COMM "init: lvrename" 
+prepare_lvs_
+
+#COMM "renamed mirror names: $lv1 to $lv2" 
+lvcreate -l2 -m1 -n $lv1 $vg 
+lvrename $vg/$lv1 $vg/$lv2 
+lv_devices_ $vg/$lv2 "$lv2"_mimage_0 "$lv2"_mimage_1 
+lv_mirror_log_ $vg/$lv2 "$lv2"_mlog
+
+#COMM "cleanup" 
+check_and_cleanup_lvs_
+
+# ---------------------------------------------------------------------
+# lvconvert
+
+#COMM "init: lvconvert" 
+prepare_lvs_
+
+#COMM "converting mirror names is ${lv1}_mimagetmp_2"
+lvcreate -l2 -m1 -n $lv1 $vg 
+lvconvert -m+1 -i1000 -b $vg/$lv1 
+convlv=$(lv_convert_lv_ "$vg/$lv1") 
+test "$convlv" = "$lv1"_mimagetmp_2 
+lv_devices_ $vg/$lv1 "$convlv" "$lv1"_mimage_2 
+lv_devices_ "$vg/$convlv" "$lv1"_mimage_0 "$lv1"_mimage_1 
+loglv=$(lv_mirror_log_ "$vg/$convlv") 
+test "$loglv" = "$lv1"_mlog
+
+#COMM "mirror log name after re-adding is ${lv1}_mlog" \
+lvconvert --mirrorlog core $vg/$lv1 
+lvconvert --mirrorlog disk $vg/$lv1 
+convlv=$(lv_convert_lv_ "$vg/$lv1") 
+lv_devices_ $vg/$lv1 "$convlv" "$lv1"_mimage_2 
+lv_devices_ "$vg/$convlv" "$lv1"_mimage_0 "$lv1"_mimage_1 
+loglv=$(lv_mirror_log_ "$vg/$convlv") 
+test "$loglv" = "$lv1"_mlog
+
+#COMM "renamed converting mirror names: $lv1 to $lv2" \
+lvrename $vg/$lv1 $vg/$lv2 
+convlv=$(lv_convert_lv_ "$vg/$lv2") 
+lv_devices_ $vg/$lv2 "$convlv" "$lv2"_mimage_2 
+lv_devices_ "$vg/$convlv" "$lv2"_mimage_0 "$lv2"_mimage_1 
+loglv=$(lv_mirror_log_ "$vg/$convlv") 
+test "$loglv" = "$lv2"_mlog
+
+#COMM "cleanup" 
+check_and_cleanup_lvs_
+
+# Temporary mirror log should have "_mlogtmp_<n>" suffix
+# but currently lvconvert doesn't have an option to add the log.
+# If such feature is added in future, a test for that should
+# be added.
+
+# ---------------------------------------------------------------------
Index: src/external/gpl2/lvm2tools/dist/test/t-mirror-vgreduce-removemissing.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-mirror-vgreduce-removemissing.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-mirror-vgreduce-removemissing.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-mirror-vgreduce-removemissing.sh	12 Dec 2008 16:33:04 -0000	1.1.1.1.2.1
@@ -0,0 +1,421 @@
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+# Copyright (C) 2007 NEC Corporation
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+test_description="ensure that 'vgreduce --removemissing' works on mirrored LV"
+
+. ./test-utils.sh
+
+dmsetup_has_dm_devdir_support_ || exit 200
+
+lv_is_on_ ()
+{
+	local lv=$vg/$1
+	shift
+	local pvs=$*
+
+	echo "Check if $lv is exactly on PVs $pvs"
+	rm -f out1 out2
+	echo $pvs | sed 's/ /\n/g' | sort | uniq > out1
+
+	lvs -a -odevices --noheadings $lv | \
+	sed 's/([^)]*)//g; s/[ ,]/\n/g' | sort | uniq > out2
+
+	diff --ignore-blank-lines out1 out2
+}
+
+mimages_are_on_ ()
+{
+	local lv=$1
+	shift
+	local pvs="$*"
+	local mimages
+	local i
+
+	echo "Check if mirror images of $lv are on PVs $pvs"
+	rm -f out1 out2
+	echo $pvs | sed 's/ /\n/g' | sort | uniq > out1
+
+	mimages=$(lvs --noheadings -a -o lv_name $vg | grep "${lv}_mimage_" | \
+		sed 's/\[//g; s/\]//g')
+	for i in $mimages; do
+		echo "Checking $vg/$i"
+		lvs -a -odevices --noheadings $vg/$i | \
+			sed 's/([^)]*)//g; s/ //g; s/,/ /g' | sort | uniq >> out2
+	done
+
+	diff --ignore-blank-lines out1 out2
+}
+
+mirrorlog_is_on_()
+{
+	local lv="$1"_mlog
+	shift
+	lv_is_on_ $lv $*
+}
+
+lv_is_linear_()
+{
+	echo "Check if $1 is linear LV (i.e. not a mirror)"
+	lvs -o stripes,attr --noheadings $vg/$1 | sed 's/ //g'
+	lvs -o stripes,attr --noheadings $vg/$1 | sed 's/ //g' | grep -q '^1-'
+}
+
+rest_pvs_()
+{
+	local index=$1
+	local num=$2
+	local rem=""
+	local n
+
+	for n in $(seq 1 $(($index - 1))) $(seq $(($index + 1)) $num); do
+		eval local dev=$\dev$n
+		rem="$rem $dev"
+	done
+
+	echo "$rem"
+}
+
+# ---------------------------------------------------------------------
+# Initialize PVs and VGs
+
+prepare_vg 5
+
+# ---------------------------------------------------------------------
+# Common environment setup/cleanup for each sub testcases
+
+prepare_lvs_()
+{
+	lvremove -ff $vg;
+	if dmsetup table|grep $vg; then
+		echo "ERROR: lvremove did leave some some mappings in DM behind!"
+		return 1
+	fi
+	:
+}
+
+check_and_cleanup_lvs_()
+{
+	lvs -a -o+devices $vg 
+	lvremove -ff $vg
+	if dmsetup table|grep $vg; then
+		echo "ERROR: lvremove did leave some some mappings in DM behind!"
+		return 1
+	fi
+}
+
+recover_vg_()
+{
+	enable_dev $* 
+	pvcreate -ff $* 
+	vgextend $vg $* 
+	check_and_cleanup_lvs_
+}
+
+#COMM "check environment setup/cleanup" 
+prepare_lvs_ 
+check_and_cleanup_lvs_
+
+# ---------------------------------------------------------------------
+# one of mirror images has failed
+
+#COMM "basic: fail the 2nd mirror image of 2-way mirrored LV"
+prepare_lvs_
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1
+lvchange -an $vg/$lv1
+aux mimages_are_on_ $lv1 $dev1 $dev2
+mirrorlog_is_on_ $lv1 $dev3
+disable_dev $dev2
+vgreduce --removemissing --force $vg
+lv_is_linear_ $lv1
+lv_is_on_ $lv1 $dev1
+
+# "cleanup"
+recover_vg_ $dev2
+
+# ---------------------------------------------------------------------
+# LV has 3 images in flat,
+# 1 out of 3 images fails
+
+#COMM test_3way_mirror_fail_1_ <PV# to fail>
+test_3way_mirror_fail_1_()
+{
+	local index=$1
+
+	lvcreate -l2 -m2 -n $lv1 $vg $dev1 $dev2 $dev3 $dev4:0-1
+	lvchange -an $vg/$lv1
+	aux mimages_are_on_ $lv1 $dev1 $dev2 $dev3
+	mirrorlog_is_on_ $lv1 $dev4
+	eval disable_dev \$dev$index
+	vgreduce --removemissing --force $vg
+	lvs -a -o+devices $vg
+	mimages_are_on_ $lv1 $(rest_pvs_ $index 3)
+	mirrorlog_is_on_ $lv1 $dev4
+}
+
+for n in $(seq 1 3); do
+	#COMM fail mirror image $(($n - 1)) of 3-way mirrored LV"
+	prepare_lvs_
+	test_3way_mirror_fail_1_ $n
+	eval recover_vg_ \$dev$n
+done
+
+# ---------------------------------------------------------------------
+# LV has 3 images in flat,
+# 2 out of 3 images fail
+
+#COMM test_3way_mirror_fail_2_ <PV# NOT to fail>
+test_3way_mirror_fail_2_()
+{
+	local index=$1
+
+	lvcreate -l2 -m2 -n $lv1 $vg $dev1 $dev2 $dev3 $dev4:0-1
+	lvchange -an $vg/$lv1
+	mimages_are_on_ $lv1 $dev1 $dev2 $dev3
+	mirrorlog_is_on_ $lv1 $dev4
+	rest_pvs_ $index 3
+	disable_dev $(rest_pvs_ $index 3)
+	vgreduce --force --removemissing $vg
+	lvs -a -o+devices $vg
+	aux lv_is_linear_ $lv1
+	eval lv_is_on_ $lv1 \$dev$n
+}
+
+for n in $(seq 1 3); do
+	#COMM fail mirror images other than mirror image $(($n - 1)) of 3-way mirrored LV
+	prepare_lvs_
+	test_3way_mirror_fail_2_ $n
+	recover_vg_ $(rest_pvs_ $n 3)
+done
+
+# ---------------------------------------------------------------------
+# LV has 4 images, 1 of them is in the temporary mirror for syncing.
+# 1 out of 4 images fails
+
+#COMM test_3way_mirror_plus_1_fail_1_ <PV# to fail>
+test_3way_mirror_plus_1_fail_1_()
+{
+	local index=$1
+
+	lvcreate -l2 -m2 -n $lv1 $vg $dev1 $dev2 $dev3 $dev5:0-1 
+	lvchange -an $vg/$lv1 
+	lvconvert -m+1 $vg/$lv1 $dev4 
+	mimages_are_on_ $lv1 $dev1 $dev2 $dev3 $dev4 
+	mirrorlog_is_on_ $lv1 $dev5 
+	eval disable_dev \$dev$n 
+	vgreduce --removemissing --force $vg 
+	lvs -a -o+devices $vg 
+	mimages_are_on_ $lv1 $(rest_pvs_ $index 4) 
+	mirrorlog_is_on_ $lv1 $dev5
+}
+
+for n in $(seq 1 4); do
+	#COMM "fail mirror image $(($n - 1)) of 4-way (1 converting) mirrored LV"
+	prepare_lvs_
+	test_3way_mirror_plus_1_fail_1_ $n
+	eval recover_vg_ \$dev$n
+done
+
+# ---------------------------------------------------------------------
+# LV has 4 images, 1 of them is in the temporary mirror for syncing.
+# 3 out of 4 images fail
+
+#COMM test_3way_mirror_plus_1_fail_3_ <PV# NOT to fail>
+test_3way_mirror_plus_1_fail_3_()
+{
+	local index=$1
+
+	lvcreate -l2 -m2 -n $lv1 $vg $dev1 $dev2 $dev3 $dev5:0-1 
+	lvchange -an $vg/$lv1 
+	lvconvert -m+1 $vg/$lv1 $dev4 
+	mimages_are_on_ $lv1 $dev1 $dev2 $dev3 $dev4 
+	mirrorlog_is_on_ $lv1 $dev5 
+	disable_dev $(rest_pvs_ $index 4) 
+	vgreduce --removemissing --force $vg 
+	lvs -a -o+devices $vg 
+	eval local dev=\$dev$n
+	mimages_are_on_ $lv1 $dev || lv_is_on_ $lv1 $dev
+	not mirrorlog_is_on_ $lv1 $dev5
+}
+
+for n in $(seq 1 4); do
+	#COMM "fail mirror images other than mirror image $(($n - 1)) of 4-way (1 converting) mirrored LV"
+	prepare_lvs_
+	test_3way_mirror_plus_1_fail_3_ $n
+	recover_vg_ $(rest_pvs_ $n 4)
+done
+
+# ---------------------------------------------------------------------
+# LV has 4 images, 2 of them are in the temporary mirror for syncing.
+# 1 out of 4 images fail
+
+# test_2way_mirror_plus_2_fail_1_ <PV# to fail>
+test_2way_mirror_plus_2_fail_1_()
+{
+	local index=$1
+
+	lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0-1 
+	lvchange -an $vg/$lv1 
+	lvconvert -m+2 $vg/$lv1 $dev3 $dev4 
+	mimages_are_on_ $lv1 $dev1 $dev2 $dev3 $dev4 
+	mirrorlog_is_on_ $lv1 $dev5 
+	eval disable_dev \$dev$n 
+	vgreduce --removemissing --force $vg 
+	lvs -a -o+devices $vg 
+	mimages_are_on_ $lv1 $(rest_pvs_ $index 4) 
+	mirrorlog_is_on_ $lv1 $dev5
+}
+
+for n in $(seq 1 4); do
+	#COMM "fail mirror image $(($n - 1)) of 4-way (2 converting) mirrored LV" 
+	prepare_lvs_ 
+	test_2way_mirror_plus_2_fail_1_ $n
+	eval recover_vg_ \$dev$n
+done
+
+# ---------------------------------------------------------------------
+# LV has 4 images, 2 of them are in the temporary mirror for syncing.
+# 3 out of 4 images fail
+
+# test_2way_mirror_plus_2_fail_3_ <PV# NOT to fail>
+test_2way_mirror_plus_2_fail_3_()
+{
+	local index=$1
+
+	lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0-1 
+	lvchange -an $vg/$lv1 
+	lvconvert -m+2 $vg/$lv1 $dev3 $dev4 
+	mimages_are_on_ $lv1 $dev1 $dev2 $dev3 $dev4 
+	mirrorlog_is_on_ $lv1 $dev5 
+	disable_dev $(rest_pvs_ $index 4) 
+	vgreduce --removemissing --force $vg 
+	lvs -a -o+devices $vg 
+	eval local dev=\$dev$n
+	mimages_are_on_ $lv1 $dev || lv_is_on_ $lv1 $dev
+	not mirrorlog_is_on_ $lv1 $dev5
+}
+
+for n in $(seq 1 4); do
+	#COMM "fail mirror images other than mirror image $(($n - 1)) of 4-way (2 converting) mirrored LV"
+	prepare_lvs_
+	test_2way_mirror_plus_2_fail_3_ $n
+	recover_vg_ $(rest_pvs_ $n 4)
+done
+
+# ---------------------------------------------------------------------
+# log device is gone (flat mirror and stacked mirror)
+
+#COMM "fail mirror log of 2-way mirrored LV" 
+prepare_lvs_ 
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0-1 
+lvchange -an $vg/$lv1 
+mimages_are_on_ $lv1 $dev1 $dev2 
+mirrorlog_is_on_ $lv1 $dev5 
+disable_dev $dev5 
+vgreduce --removemissing --force $vg 
+mimages_are_on_ $lv1 $dev1 $dev2 
+not mirrorlog_is_on_ $lv1 $dev5
+recover_vg_ $dev5
+
+#COMM "fail mirror log of 3-way (1 converting) mirrored LV" 
+prepare_lvs_ 
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0-1 
+lvchange -an $vg/$lv1 
+lvconvert -m+1 $vg/$lv1 $dev3 
+mimages_are_on_ $lv1 $dev1 $dev2 $dev3 
+mirrorlog_is_on_ $lv1 $dev5 
+disable_dev $dev5 
+vgreduce --removemissing --force $vg 
+mimages_are_on_ $lv1 $dev1 $dev2 $dev3 
+not mirrorlog_is_on_ $lv1 $dev5
+recover_vg_ $dev5
+
+# ---------------------------------------------------------------------
+# all images are gone (flat mirror and stacked mirror)
+
+#COMM "fail all mirror images of 2-way mirrored LV"
+prepare_lvs_ 
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0-1 
+lvchange -an $vg/$lv1 
+mimages_are_on_ $lv1 $dev1 $dev2 
+mirrorlog_is_on_ $lv1 $dev5 
+disable_dev $dev1 $dev2 
+vgreduce --removemissing --force $vg 
+not lvs $vg/$lv1
+recover_vg_ $dev1 $dev2
+
+#COMM "fail all mirror images of 3-way (1 converting) mirrored LV"
+prepare_lvs_ 
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0-1 
+lvchange -an $vg/$lv1 
+lvconvert -m+1 $vg/$lv1 $dev3 
+mimages_are_on_ $lv1 $dev1 $dev2 $dev3 
+mirrorlog_is_on_ $lv1 $dev5 
+disable_dev $dev1 $dev2 $dev3 
+vgreduce --removemissing --force $vg 
+not lvs $vg/$lv1
+recover_vg_ $dev1 $dev2 $dev3
+
+# ---------------------------------------------------------------------
+# Multiple LVs
+
+#COMM "fail a mirror image of one of mirrored LV"
+prepare_lvs_ 
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0-1 
+lvchange -an $vg/$lv1 
+lvcreate -l2 -m1 -n $lv2 $vg $dev3 $dev4 $dev5:1-1 
+lvchange -an $vg/$lv2 
+mimages_are_on_ $lv1 $dev1 $dev2 
+mimages_are_on_ $lv2 $dev3 $dev4 
+mirrorlog_is_on_ $lv1 $dev5 
+mirrorlog_is_on_ $lv2 $dev5 
+disable_dev $dev2 
+vgreduce --removemissing --force $vg 
+mimages_are_on_ $lv2 $dev3 $dev4 
+mirrorlog_is_on_ $lv2 $dev5 
+lv_is_linear_ $lv1 
+lv_is_on_ $lv1 $dev1
+recover_vg_ $dev2
+
+#COMM "fail mirror images, one for each mirrored LV"
+prepare_lvs_ 
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0-1 
+lvchange -an $vg/$lv1 
+lvcreate -l2 -m1 -n $lv2 $vg $dev3 $dev4 $dev5:1-1 
+lvchange -an $vg/$lv2 
+mimages_are_on_ $lv1 $dev1 $dev2 
+mimages_are_on_ $lv2 $dev3 $dev4 
+mirrorlog_is_on_ $lv1 $dev5 
+mirrorlog_is_on_ $lv2 $dev5 
+disable_dev $dev2 
+disable_dev $dev4 
+vgreduce --removemissing --force $vg 
+lv_is_linear_ $lv1 
+lv_is_on_ $lv1 $dev1 
+lv_is_linear_ $lv2 
+lv_is_on_ $lv2 $dev3
+recover_vg_ $dev2 $dev4
+
+# ---------------------------------------------------------------------
+# no failure
+
+#COMM "no failures"
+prepare_lvs_ 
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0-1 
+lvchange -an $vg/$lv1 
+mimages_are_on_ $lv1 $dev1 $dev2 
+mirrorlog_is_on_ $lv1 $dev5 
+vgreduce --removemissing --force $vg 
+mimages_are_on_ $lv1 $dev1 $dev2 
+mirrorlog_is_on_ $lv1 $dev5
+check_and_cleanup_lvs_
+
+# ---------------------------------------------------------------------
+
Index: src/external/gpl2/lvm2tools/dist/test/t-partial-activate.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-partial-activate.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-partial-activate.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-partial-activate.sh	12 Dec 2008 16:33:04 -0000	1.1.1.1.2.2
@@ -0,0 +1,12 @@
+. ./test-utils.sh
+
+aux prepare_vg 3
+
+lvcreate -m 1 -l 1 -n mirror $vg
+lvchange -a n $vg/mirror
+disable_dev $dev1
+
+# FIXME should this return an error code due to that big fat WARNING?
+vgreduce --removemissing $vg
+not lvchange -v -a y $vg/mirror
+lvchange -v --partial -a y $vg/mirror
Index: src/external/gpl2/lvm2tools/dist/test/t-pool-labels.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-pool-labels.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-pool-labels.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-pool-labels.sh	12 Dec 2008 16:33:04 -0000	1.1.1.1.2.2
@@ -0,0 +1,39 @@
+# Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+. ./test-utils.sh
+
+# create the old GFS pool labeled linear devices
+create_pool_label_()
+{
+  # FIXME
+  # echo -e is bashism, dash builtin sh doesn't do \xNN in printf either
+  # printf comes from coreutils, and is probably not posix either
+  env printf "\x01\x16\x70\x06\x5f\xcf\xff\xb9\xf8\x24\x8apool1" | dd of=$2 bs=5 seek=1 conv=notrunc
+  env printf "\x04\x01\x03\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x0$1\x68\x01\x16\x70\x00\x00\x00\x00\x00\x06\x5f\xd0" | dd of=$2 bs=273 seek=1 conv=notrunc
+}
+
+env printf "" || exit 200 # skip if printf is not available
+
+aux prepare_devs 2
+
+create_pool_label_ 0 "$dev1"
+create_pool_label_ 1 "$dev2"
+
+# check that pvcreate fails without -ff on the pool device
+not pvcreate "$dev1"
+
+# check that vgdisplay and pvcreate -ff works with the pool device
+vgdisplay --config 'global { locking_type = 0 }'
+disable_dev "$dev2"
+# FIXME! since pool1 cannot be opened, vgdisplay gives error... should we say
+# "not" there instead, checking that it indeed does fail?
+vgdisplay --config 'global { locking_type = 0 }' || true
+pvcreate -ff -y "$dev1"
Index: src/external/gpl2/lvm2tools/dist/test/t-pv-range-overflow.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-pv-range-overflow.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-pv-range-overflow.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-pv-range-overflow.sh	12 Dec 2008 16:33:04 -0000	1.1.1.1.2.1
@@ -0,0 +1,32 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+# 'Ensure that pvmove diagnoses PE-range values 2^32 and larger.'
+
+. ./test-utils.sh
+
+aux prepare_vg 2
+
+lvcreate -L4 -n"$lv" $vg
+
+# Test for the bogus diagnostic reported in BZ 284771
+# http://bugzilla.redhat.com/284771.
+# 'run pvmove with an unrecognized LV name to show bad diagnostic'
+not pvmove -v -nbogus $dev1 $dev2 2> err
+grep "  Logical volume bogus not found." err
+
+# With lvm-2.02.28 and earlier, on a system with 64-bit "long int",
+# the PE range parsing code would accept values up to 2^64-1, but would
+# silently truncate them to int32_t.  I.e., $dev1:$(echo 2^32|bc) would be
+# treated just like $dev1:0.
+# 'run the offending pvmove command'
+not pvmove -v -n$lv $dev1:4294967296 $dev2
+
Index: src/external/gpl2/lvm2tools/dist/test/t-pvchange-usage.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-pvchange-usage.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-pvchange-usage.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-pvchange-usage.sh	12 Dec 2008 16:33:04 -0000	1.1.1.1.2.2
@@ -0,0 +1,64 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+# 'Test pvchange option values'
+
+. ./test-utils.sh
+
+aux prepare_devs 4
+
+for mda in 0 1 2 
+do
+# "setup pv with metadatacopies = $mda" 
+	pvcreate $dev4 
+	pvcreate --metadatacopies $mda $dev1 
+	vgcreate $vg1 $dev1 $dev4 
+
+# "pvchange adds/dels tag to pvs with metadatacopies = $mda " 
+	pvchange $dev1 --addtag test$mda 
+	check_pv_field_ $dev1 pv_tags test$mda 
+	pvchange $dev1 --deltag test$mda 
+	check_pv_field_ $dev1 pv_tags " "
+
+# "vgchange disable/enable allocation for pvs with metadatacopies = $mda (bz452982)"
+	pvchange $dev1 -x n 
+	check_pv_field_ $dev1 pv_attr  --  
+	pvchange $dev1 -x y 
+	check_pv_field_ $dev1 pv_attr  a- 
+
+# 'remove pv'
+	vgremove $vg1 
+	pvremove $dev1 $dev4
+done
+
+# "pvchange uuid"
+pvcreate --metadatacopies 0 $dev1 
+pvcreate --metadatacopies 2 $dev2 
+vgcreate $vg1 $dev1 $dev2 
+pvchange -u $dev1 
+pvchange -u $dev2 
+vg_validate_pvlv_counts_ $vg1 2 0 0
+
+# "pvchange rejects uuid change under an active lv" 
+lvcreate -l 16 -i 2 -n $lv --alloc anywhere $vg1 
+vg_validate_pvlv_counts_ $vg1 2 1 0 
+not pvchange -u $dev1
+lvchange -an "$vg1"/"$lv" 
+pvchange -u $dev1
+
+# "cleanup" 
+lvremove -f "$vg1"/"$lv"
+vgremove $vg1
+
+# "pvchange reject --addtag to lvm1 pv"
+pvcreate -M1 $dev1 
+not pvchange $dev1 --addtag test
+
Index: src/external/gpl2/lvm2tools/dist/test/t-pvcreate-metadata0.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-pvcreate-metadata0.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-pvcreate-metadata0.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-pvcreate-metadata0.sh	12 Dec 2008 16:33:04 -0000	1.1.1.1.2.2
@@ -0,0 +1,32 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#
+# Testcase for bugzilla #450651
+# also checks that vgremove properly removes all lv devices in the right order
+#
+# 'Test pvcreate without metadata on all pvs'
+
+. ./test-utils.sh
+
+aux prepare_devs 2 128
+
+#lv_snap=$lv2
+pvcreate "$dev1"
+pvcreate --metadatacopies 0 "$dev2"
+
+# "check lv snapshot" 
+vgcreate -c n "$vg" "$dev1" "$dev2" 
+lvcreate -n "$lv" -l 60%FREE "$vg" 
+lvcreate -s -n $lv2 -l 10%FREE "$vg"/"$lv" 
+pvdisplay 
+lvdisplay
+vgremove -f "$vg"
Index: src/external/gpl2/lvm2tools/dist/test/t-pvcreate-operation.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-pvcreate-operation.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-pvcreate-operation.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-pvcreate-operation.sh	12 Dec 2008 16:33:04 -0000	1.1.1.1.2.2
@@ -0,0 +1,102 @@
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+. ./test-utils.sh
+
+aux prepare_devs 4
+
+for mdatype in 1 2
+do
+
+# pvcreate (lvm$mdatype) succeeds when run repeatedly (pv not in a vg) (bz178216)
+    pvcreate -M$mdatype $dev1
+    pvcreate -M$mdatype $dev1
+    pvremove -f $dev1
+
+# pvcreate (lvm$mdatype) fails when PV belongs to VG" \
+    pvcreate -M$mdatype $dev1
+    vgcreate -M$mdatype $vg1 $dev1
+    not pvcreate -M$mdatype $dev1
+
+    vgremove -f $vg1
+    pvremove -f $dev1
+
+# pvcreate (lvm$mdatype) fails when PV1 does and PV2 does not belong to VG
+    pvcreate -M$mdatype $dev1
+    pvcreate -M$mdatype $dev2
+    vgcreate -M$mdatype $vg1 $dev1
+
+# pvcreate a second time on $dev2 and $dev1
+    not pvcreate -M$mdatype $dev2 $dev1
+
+    vgremove -f $vg1
+    pvremove -f $dev2
+    pvremove -f $dev1
+
+# NOTE: Force pvcreate after test completion to ensure clean device
+#test_expect_success \
+#  "pvcreate (lvm$mdatype) fails on md component device" \
+#  'mdadm -C -l raid0 -n 2 /dev/md0 $dev1 $dev2 &&
+#   pvcreate -M$mdatype $dev1;
+#   status=$?; echo status=$status; test $status != 0 &&
+#   mdadm --stop /dev/md0 &&
+#   pvcreate -ff -y -M$mdatype $dev1 $dev2 &&
+#   pvremove -f $dev1 $dev2'
+done
+
+# pvcreate (lvm2) fails without -ff when PV with metadatacopies=0 belongs to VG
+pvcreate --metadatacopies 0 $dev1
+pvcreate --metadatacopies 1 $dev2
+vgcreate $vg1 $dev1 $dev2
+not pvcreate $dev1
+vgremove -f $vg1
+pvremove -f $dev2
+pvremove -f $dev1
+
+# pvcreate (lvm2) succeeds with -ff when PV with metadatacopies=0 belongs to VG
+pvcreate --metadatacopies 0 $dev1 
+pvcreate --metadatacopies 1 $dev2
+vgcreate $vg1 $dev1 $dev2 
+pvcreate -ff -y $dev1 
+vgreduce --removemissing $vg1 
+vgremove -ff $vg1 
+pvremove -f $dev2 
+pvremove -f $dev1
+
+for i in 0 1 2 3
+do
+# pvcreate (lvm2) succeeds writing LVM label at sector $i
+    pvcreate --labelsector $i $dev1
+    dd if=$dev1 bs=512 skip=$i count=1 status=noxfer 2>&1 | strings | grep -q LABELONE;
+    pvremove -f $dev1
+done
+
+# pvcreate (lvm2) fails writing LVM label at sector 4
+not pvcreate --labelsector 4 $dev1
+
+backupfile=mybackupfile-$(this_test_)
+uuid1=freddy-fred-fred-fred-fred-fred-freddy
+uuid2=freddy-fred-fred-fred-fred-fred-fredie
+bogusuuid=fred
+
+# pvcreate rejects uuid option with less than 32 characters
+not pvcreate --uuid $bogusuuid $dev1
+
+# pvcreate rejects uuid already in use
+pvcreate --uuid $uuid1 $dev1
+not pvcreate --uuid $uuid1 $dev2
+
+# pvcreate rejects non-existent file given with restorefile
+not pvcreate --uuid $uuid1 --restorefile $backupfile $dev1
+
+# pvcreate rejects restorefile with uuid not found in file
+pvcreate --uuid $uuid1 $dev1
+vgcfgbackup -f $backupfile
+not pvcreate --uuid $uuid2 --restorefile $backupfile $dev2
Index: src/external/gpl2/lvm2tools/dist/test/t-pvcreate-usage.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-pvcreate-usage.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-pvcreate-usage.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-pvcreate-usage.sh	12 Dec 2008 16:33:04 -0000	1.1.1.1.2.2
@@ -0,0 +1,72 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+test_description='Test pvcreate option values'
+
+. ./test-utils.sh
+
+aux prepare_devs 4
+
+#COMM 'pvcreate rejects negative setphysicalvolumesize'
+not pvcreate --setphysicalvolumesize -1024 $dev1
+
+#COMM 'pvcreate rejects negative metadatasize'
+not pvcreate --metadatasize -1024 $dev1
+
+# x. metadatasize 0, defaults to 255
+# FIXME: unable to check default value, not in reporting cmds
+# should default to 255 according to code
+#   check_pv_field_ pv_mda_size 255 
+#COMM 'pvcreate accepts metadatasize 0'
+pvcreate --metadatasize 0 $dev1
+pvremove $dev1
+
+# x. metadatasize too large
+# For some reason we allow this, even though there's no room for data?
+##COMM  'pvcreate rejects metadatasize too large' 
+#not pvcreate --metadatasize 100000000000000 $dev1
+
+#COMM 'pvcreate rejects metadatacopies < 0'
+not pvcreate --metadatacopies -1 $dev1
+
+#COMM 'pvcreate accepts metadatacopies = 0, 1, 2'
+pvcreate --metadatacopies 0 $dev1 
+pvcreate --metadatacopies 1 $dev2 
+pvcreate --metadatacopies 2 $dev3 
+check_pv_field_ $dev1 pv_mda_count 0 
+check_pv_field_ $dev2 pv_mda_count 1 
+check_pv_field_ $dev3 pv_mda_count 2 
+pvremove $dev1 
+pvremove $dev2 
+pvremove $dev3
+
+#COMM 'pvcreate rejects metadatacopies > 2'
+not pvcreate --metadatacopies 3 $dev1
+
+#COMM 'pvcreate rejects invalid device'
+not pvcreate $dev1bogus
+
+#COMM 'pvcreate rejects labelsector < 0'
+not pvcreate --labelsector -1 $dev1
+
+#COMM 'pvcreate rejects labelsector > 1000000000000'
+not pvcreate --labelsector 1000000000000 $dev1
+
+# other possibilites based on code inspection (not sure how hard)
+# x. device too small (min of 512 * 1024 KB)
+# x. device filtered out
+# x. unable to open /dev/urandom RDONLY
+# x. device too large (pe_count > UINT32_MAX)
+# x. device read-only
+# x. unable to open device readonly
+# x. BLKGETSIZE64 fails
+# x. set size to value inconsistent with device / PE size
+
Index: src/external/gpl2/lvm2tools/dist/test/t-pvmove-basic.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-pvmove-basic.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-pvmove-basic.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-pvmove-basic.sh	12 Dec 2008 16:33:04 -0000	1.1.1.1.2.1
@@ -0,0 +1,372 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+# Copyright (C) 2007 NEC Corporation
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+test_description="ensure that pvmove works with basic options"
+
+. ./test-utils.sh
+
+dmsetup_has_dm_devdir_support_ || exit 200
+
+# ---------------------------------------------------------------------
+# Utilities
+
+lvdev_() {
+  echo "$G_dev_/$1/$2"
+}
+
+lv_is_on_() {
+  local lv=$1 #allready vg/lv
+  shift 1
+  lvs -a -odevices --noheadings $lv | sed 's/,/\n/g' > out
+#is on all specified devs
+  for d in $*; do grep "$d(" out; done
+#isn't on any other dev (we are set -e remember)
+  for d in $*; do ! grep -v "$d(" out; done
+  return 0
+}
+
+save_dev_sum_() {
+  mkfs.ext3 $1 > /dev/null &&
+  md5sum $1 > md5.$(basename $1)
+}
+
+check_dev_sum_() {
+  md5sum $1 > md5.tmp && cmp md5.$(basename $1) md5.tmp
+}
+
+# ---------------------------------------------------------------------
+# Initialize PVs and VGs
+
+aux prepare_vg 5 80
+
+# ---------------------------------------------------------------------
+# Common environment setup/cleanup for each sub testcases
+
+prepare_lvs_() {
+  lvcreate -l2 -n $lv1 $vg $dev1 
+    lv_is_on_ $vg/$lv1 $dev1 
+  lvcreate -l9 -i3 -n $lv2 $vg $dev2 $dev3 $dev4 
+    lv_is_on_ $vg/$lv2 $dev2 $dev3 $dev4 
+  lvextend -l+2 $vg/$lv1 $dev2 
+    lv_is_on_ $vg/$lv1 $dev1 $dev2 
+  lvextend -l+2 $vg/$lv1 $dev3 
+    lv_is_on_ $vg/$lv1 $dev1 $dev2 $dev3 
+  lvextend -l+2 $vg/$lv1 $dev1 
+    lv_is_on_ $vg/$lv1 $dev1 $dev2 $dev3 $dev1 
+  lvcreate -l1 -n $lv3 $vg $dev2 
+    lv_is_on_ $vg/$lv3 $dev2 
+  save_dev_sum_ $(lvdev_ $vg $lv1) 
+  save_dev_sum_ $(lvdev_ $vg $lv2) 
+  save_dev_sum_ $(lvdev_ $vg $lv3) 
+  lvs -a -o devices --noheadings $vg/$lv1 > ${lv1}_devs 
+  lvs -a -o devices --noheadings $vg/$lv2 > ${lv2}_devs 
+  lvs -a -o devices --noheadings $vg/$lv3 > ${lv3}_devs
+}
+
+lv_not_changed_() {
+  lvs -a -o devices --noheadings $1 > out
+  diff $(basename $1)_devs out
+}
+
+check_and_cleanup_lvs_() {
+  lvs -a -o+devices $vg
+  check_dev_sum_ $(lvdev_ $vg $lv1)
+  check_dev_sum_ $(lvdev_ $vg $lv2)
+  check_dev_sum_ $(lvdev_ $vg $lv3)
+  lvs -a -o name $vg > out && ! grep ^pvmove out
+  lvremove -ff $vg
+	if ! dmsetup table|not grep $vg; then
+		echo "ERROR: lvremove did leave some some mappings in DM behind!" &&
+		return 1
+	fi
+	:
+}
+
+#COMM "check environment setup/cleanup"
+prepare_lvs_
+check_and_cleanup_lvs_
+
+# ---------------------------------------------------------------------
+# pvmove tests
+
+# ---
+# filter by LV
+
+#COMM "only specified LV is moved: from pv2 to pv5 only for lv1"
+prepare_lvs_ 
+pvmove -i1 -n $vg/$lv1 $dev2 $dev5 
+lv_is_on_ $vg/$lv1 $dev1 $dev5 $dev3 $dev1 
+lv_not_changed_ $vg/$lv2 
+lv_not_changed_ $vg/$lv3 
+check_and_cleanup_lvs_
+
+# ---
+# segments in a LV
+
+#COMM "the 1st seg of 3-segs LV is moved: from pv1 of lv1 to pv4"
+prepare_lvs_ 
+pvmove -i1 -n $vg/$lv1 $dev1 $dev4 
+lv_is_on_ $vg/$lv1 $dev4 $dev2 $dev3 $dev4 
+lv_not_changed_ $vg/$lv2 
+lv_not_changed_ $vg/$lv3 
+check_and_cleanup_lvs_
+
+#COMM "the 2nd seg of 3-segs LV is moved: from pv2 of lv1 to pv4"
+prepare_lvs_ 
+pvmove -i1 -n $vg/$lv1 $dev2 $dev4 
+lv_is_on_ $vg/$lv1 $dev1 $dev4 $dev3 $dev1 
+lv_not_changed_ $vg/$lv2 
+lv_not_changed_ $vg/$lv3 
+check_and_cleanup_lvs_
+
+#COMM "the 3rd seg of 3-segs LV is moved: from pv3 of lv1 to pv4"
+prepare_lvs_ 
+pvmove -i1 -n $vg/$lv1 $dev3 $dev4 
+lv_is_on_ $vg/$lv1 $dev1 $dev2 $dev4 $dev1 
+lv_not_changed_ $vg/$lv2 
+lv_not_changed_ $vg/$lv3 
+check_and_cleanup_lvs_
+
+# ---
+# multiple LVs matching
+
+#COMM "1 out of 3 LVs is moved: from pv4 to pv5"
+prepare_lvs_ 
+pvmove -i1 $dev4 $dev5 
+lv_not_changed_ $vg/$lv1 
+lv_is_on_ $vg/$lv2 $dev2 $dev3 $dev5 
+lv_not_changed_ $vg/$lv3 
+check_and_cleanup_lvs_
+
+#COMM "2 out of 3 LVs are moved: from pv3 to pv5"
+prepare_lvs_ 
+pvmove -i1 $dev3 $dev5 
+lv_is_on_ $vg/$lv1 $dev1 $dev2 $dev5 $dev1 
+lv_is_on_ $vg/$lv2 $dev2 $dev5 $dev4 
+lv_not_changed_ $vg/$lv3 
+check_and_cleanup_lvs_
+
+#COMM "3 out of 3 LVs are moved: from pv2 to pv5"
+prepare_lvs_ 
+pvmove -i1 $dev2 $dev5 
+lv_is_on_ $vg/$lv1 $dev1 $dev5 $dev3 $dev1 
+lv_is_on_ $vg/$lv2 $dev5 $dev3 $dev4 
+lv_is_on_ $vg/$lv3 $dev5 
+check_and_cleanup_lvs_
+
+# ---
+# areas of striping
+
+#COMM "move the 1st stripe: from pv2 of lv2 to pv1"
+prepare_lvs_ 
+pvmove -i1 -n $vg/$lv2 $dev2 $dev1 
+lv_not_changed_ $vg/$lv1 
+lv_is_on_ $vg/$lv2 $dev1 $dev3 $dev4 
+lv_not_changed_ $vg/$lv3 
+check_and_cleanup_lvs_
+
+#COMM "move the 2nd stripe: from pv3 of lv2 to pv1"
+prepare_lvs_ 
+pvmove -i1 -n $vg/$lv2 $dev3 $dev1 
+lv_not_changed_ $vg/$lv1 
+lv_is_on_ $vg/$lv2 $dev2 $dev1 $dev4 
+lv_not_changed_ $vg/$lv3 
+check_and_cleanup_lvs_
+
+#COMM "move the 3rd stripe: from pv4 of lv2 to pv1"
+prepare_lvs_ 
+pvmove -i1 -n $vg/$lv2 $dev4 $dev1 
+lv_not_changed_ $vg/$lv1 
+lv_is_on_ $vg/$lv2 $dev2 $dev3 $dev1 
+lv_not_changed_ $vg/$lv3 
+check_and_cleanup_lvs_
+
+# ---
+# partial segment match (source segment splitted)
+
+#COMM "match to the start of segment:from pv2:0-0 to pv5"
+prepare_lvs_ 
+pvmove -i1 $dev2:0-0 $dev5 
+lv_not_changed_ $vg/$lv1 
+lv_is_on_ $vg/$lv2 $dev5 $dev2 $dev3 $dev4 
+lv_not_changed_ $vg/$lv3 
+check_and_cleanup_lvs_
+
+#COMM "match to the middle of segment: from pv2:1-1 to pv5"
+prepare_lvs_ 
+pvmove -i1 $dev2:1-1 $dev5 
+lv_not_changed_ $vg/$lv1 
+lv_is_on_ $vg/$lv2 $dev2 $dev5 $dev2 $dev3 $dev4 
+lv_not_changed_ $vg/$lv3 
+check_and_cleanup_lvs_
+
+#COMM "match to the end of segment: from pv2:2-2 to pv5"
+prepare_lvs_ 
+pvmove -i1 $dev2:2-2 $dev5 
+lv_not_changed_ $vg/$lv1 
+lv_is_on_ $vg/$lv2 $dev2 $dev5 $dev3 $dev4 
+lv_not_changed_ $vg/$lv3 
+check_and_cleanup_lvs_
+
+# ---
+# destination segment splitted
+
+#COMM "no destination split: from pv2:0-2 to pv5"
+prepare_lvs_ 
+pvmove -i1 $dev2:0-2 $dev5 
+lv_not_changed_ $vg/$lv1 
+lv_is_on_ $vg/$lv2 $dev5 $dev3 $dev4 
+lv_not_changed_ $vg/$lv3 
+check_and_cleanup_lvs_
+
+#COMM "destination split into 2: from pv2:0-2 to pv5:5-5 and pv4:5-6"
+prepare_lvs_ 
+pvmove -i1 $dev2:0-2 $dev5:5-5 $dev4:5-6 
+lv_not_changed_ $vg/$lv1 
+lv_is_on_ $vg/$lv2 $dev5 $dev4 $dev3 $dev4 
+lv_not_changed_ $vg/$lv3 
+check_and_cleanup_lvs_
+
+#COMM "destination split into 3: from pv2:0-2 to {pv3,4,5}:5-5"
+prepare_lvs_ 
+pvmove -i1 $dev2:0-2 $dev3:5-5 $dev4:5-5 $dev5:5-5 
+lv_not_changed_ $vg/$lv1 
+lv_is_on_ $vg/$lv2 $dev3 $dev4 $dev5 $dev3 $dev4 
+lv_not_changed_ $vg/$lv3 
+check_and_cleanup_lvs_
+
+# ---
+# alloc policy (anywhere, contiguous) with both success and failure cases
+
+#COMM "alloc normal on same PV for source and destination: from pv3:0-2 to pv3:5-7" 
+prepare_lvs_ 
+not pvmove -i1 $dev3:0-2 $dev3:5-7
+# "(cleanup previous test)"
+lv_not_changed_ $vg/$lv1 
+lv_not_changed_ $vg/$lv2 
+lv_not_changed_ $vg/$lv3 
+check_and_cleanup_lvs_
+
+#COMM "alloc anywhere on same PV for source and destination: from pv3:0-2 to pv3:5-7"
+prepare_lvs_ 
+pvmove -i1 --alloc anywhere $dev3:0-2 $dev3:5-7 
+lv_not_changed_ $vg/$lv1 
+lv_is_on_ $vg/$lv2 $dev2 $dev3 $dev4 
+lv_not_changed_ $vg/$lv3 
+check_and_cleanup_lvs_
+
+#COMM "alloc anywhere but better area available: from pv3:0-2 to pv3:5-7 or pv5:5-6,pv4:5-5"
+prepare_lvs_ 
+pvmove -i1 --alloc anywhere $dev3:0-2 $dev3:5-7 $dev5:5-6 $dev4:5-5 
+lv_not_changed_ $vg/$lv1 
+lv_is_on_ $vg/$lv2 $dev2 $dev5 $dev4 $dev4 
+lv_not_changed_ $vg/$lv3 
+check_and_cleanup_lvs_
+
+#COMM "alloc contiguous but area not available: from pv2:0-2 to pv5:5-5 and pv4:5-6"
+prepare_lvs_ 
+not pvmove -i1 --alloc contiguous $dev2:0-2 $dev5:5-5 $dev4:5-6
+# "(cleanup previous test)"
+lv_not_changed_ $vg/$lv1 
+lv_not_changed_ $vg/$lv2 
+lv_not_changed_ $vg/$lv3 
+check_and_cleanup_lvs_
+
+#COMM "alloc contiguous and contiguous area available: from pv2:0-2 to pv5:0-0,pv5:3-5 and pv4:5-6"
+prepare_lvs_ 
+pvmove -i1 --alloc contiguous $dev2:0-2 $dev5:0-0 $dev5:3-5 $dev4:5-6 
+lv_not_changed_ $vg/$lv1 
+lv_is_on_ $vg/$lv2 $dev5 $dev3 $dev4 
+lv_not_changed_ $vg/$lv3 
+check_and_cleanup_lvs_
+
+# ---
+# multiple segments in a LV
+
+#COMM "multiple source LVs: from pv3 to pv5"
+prepare_lvs_ 
+pvmove -i1 $dev3 $dev5 
+lv_is_on_ $vg/$lv1 $dev1 $dev2 $dev5 
+lv_is_on_ $vg/$lv2 $dev2 $dev5 $dev4 
+lv_not_changed_ $vg/$lv3 
+check_and_cleanup_lvs_
+
+# ---
+# move inactive LV
+
+#COMM "move inactive LV: from pv2 to pv5"
+prepare_lvs_ 
+lvchange -an $vg/$lv1 
+lvchange -an $vg/$lv3 
+pvmove -i1 $dev2 $dev5 
+lv_is_on_ $vg/$lv1 $dev1 $dev5 $dev3 
+lv_is_on_ $vg/$lv2 $dev5 $dev3 $dev4 
+lv_is_on_ $vg/$lv3 $dev5 
+check_and_cleanup_lvs_
+
+# ---
+# other failure cases
+
+#COMM "no PEs to move: from pv3 to pv1"
+prepare_lvs_ 
+pvmove -i1 $dev3 $dev1 
+not pvmove -i1 $dev3 $dev1
+# "(cleanup previous test)"
+lv_is_on_ $vg/$lv1 $dev1 $dev2 $dev1 
+lv_is_on_ $vg/$lv2 $dev2 $dev1 $dev4 
+lv_not_changed_ $vg/$lv3 
+check_and_cleanup_lvs_
+
+#COMM "no space available: from pv2:0-0 to pv1:0-0" 
+prepare_lvs_ 
+not pvmove -i1 $dev2:0-0 $dev1:0-0
+# "(cleanup previous test)"
+lv_not_changed_ $vg/$lv1 
+lv_not_changed_ $vg/$lv2 
+lv_not_changed_ $vg/$lv3 
+check_and_cleanup_lvs_
+
+#COMM 'same source and destination: from pv1 to pv1'
+prepare_lvs_ 
+not pvmove -i1 $dev1 $dev1
+#"(cleanup previous test)"
+lv_not_changed_ $vg/$lv1 
+lv_not_changed_ $vg/$lv2 
+lv_not_changed_ $vg/$lv3 
+check_and_cleanup_lvs_
+
+#COMM "sum of specified destination PEs is large enough, but it includes source PEs and the free PEs are not enough"
+prepare_lvs_ 
+not pvmove --alloc anywhere $dev1:0-2 $dev1:0-2 $dev5:0-0 2> err
+#"(cleanup previous test)"
+grep "Insufficient free space" err 
+lv_not_changed_ $vg/$lv1 
+lv_not_changed_ $vg/$lv2 
+lv_not_changed_ $vg/$lv3 
+check_and_cleanup_lvs_
+
+# ---------------------------------------------------------------------
+
+#COMM "pvmove abort"
+prepare_lvs_ 
+pvmove -i100 -b $dev1 $dev3 
+pvmove --abort 
+check_and_cleanup_lvs_
+
+#COMM "pvmove out of --metadatacopies 0 PV (bz252150)"
+vgremove -ff $vg
+pvcreate $devs
+pvcreate --metadatacopies 0 $dev1 $dev2
+vgcreate $vg $devs
+lvcreate -l4 -n $lv1 $vg $dev1
+pvmove $dev1
+
Index: src/external/gpl2/lvm2tools/dist/test/t-pvremove-usage.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-pvremove-usage.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-pvremove-usage.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-pvremove-usage.sh	12 Dec 2008 16:33:04 -0000	1.1.1.1.2.2
@@ -0,0 +1,68 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+. ./test-utils.sh
+
+aux prepare_devs 3
+pvcreate $dev1
+pvcreate --metadatacopies 0 $dev2
+pvcreate --metadatacopies 2 $dev3
+
+# check pvremove fails when bogus pv given
+not pvremove $dev2 bogus
+
+# failing, but still removing everything what can be removed
+# is somewhat odd as default, what do we have -f for?
+pvs | not grep $dev2
+pvcreate  --metadatacopies 0 $dev2
+
+# check pvremove refuses to remove pv in a vg
+vgcreate -c n $vg $dev1 $dev2
+not pvremove $dev2 $dev3
+
+for mdacp in 0 1 2; do
+    # check pvremove truly wipes the label (pvscan wont find) (---metadatacopies $mdacp)
+    pvcreate --metadatacopies $mdacp $dev3
+    pvremove $dev3
+    pvscan | not grep $dev3
+
+	# bz179473 refuse to wipe non-PV device without -f
+    not pvremove $dev3
+    pvremove -f $dev3
+
+    # reset setup
+    vgremove -ff $vg
+    pvcreate --metadatacopies $mdacp $dev1
+    pvcreate $dev2
+    vgcreate $vg $dev1 $dev2 
+
+    # pvremove -f fails when pv in a vg (---metadatacopies $mdacp)
+    not pvremove -f $dev1
+    pvs $dev1
+
+    # pvremove -ff fails without confirmation when pv in a vg (---metadatacopies $mdacp)
+    echo n | not pvremove -ff $dev1
+
+    # pvremove -ff succeds with confirmation when pv in a vg (---metadatacopies $mdacp)
+    yes | pvremove -ff $dev1
+    not pvs $dev1
+
+    vgreduce --removemissing $vg
+    pvcreate --metadatacopies $mdacp $dev1
+    vgextend $vg $dev1
+
+    # pvremove -ff -y is sufficient when pv in a vg (---metadatacopies $mdacp)" '
+    echo n | pvremove -ff -y $dev1
+
+    vgreduce --removemissing $vg
+    pvcreate --metadatacopies $mdacp $dev1
+    vgextend $vg $dev1
+done
Index: src/external/gpl2/lvm2tools/dist/test/t-read-ahead.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-read-ahead.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-read-ahead.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-read-ahead.sh	12 Dec 2008 16:33:04 -0000	1.1.1.1.2.1
@@ -0,0 +1,45 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#
+# tests basic functionality of read-ahead and ra regressions
+#
+
+test_description='Test read-ahead functionality'
+
+. ./test-utils.sh
+
+
+get_lvs_() {
+   lvs --units s --nosuffix --noheadings -o $1 "$vg"/"$lv"
+}
+
+check_lvs_() {
+   case $(get_lvs_ $1) in
+    *$2) true ;;
+    *) false ;;
+   esac
+}
+
+aux prepare_vg 5
+
+#COMM "test various read ahead settings (bz450922)"
+lvcreate -n "$lv" -l 100%FREE -i5 -I256 "$vg"     
+ra="$(get_lvs_ lv_kernel_read_ahead)"
+test "$(( ( $ra / 5 ) * 5 ))" -eq $ra
+lvdisplay "$vg"/"$lv"                             
+lvchange -r auto "$vg"/"$lv" 2>&1 | grep auto     
+check_lvs_ lv_read_ahead auto                                  
+check_lvs_ lv_kernel_read_ahead 5120                           
+lvchange -r 400 "$vg/$lv"                         
+check_lvs_ lv_read_ahead 400                                   
+lvremove -ff "$vg"
+
Index: src/external/gpl2/lvm2tools/dist/test/t-unlost-pv.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-unlost-pv.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-unlost-pv.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-unlost-pv.sh	12 Dec 2008 16:33:04 -0000	1.1.1.1.2.2
@@ -0,0 +1,39 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+. ./test-utils.sh
+
+aux prepare_vg 3
+
+lvcreate -m 1 -l 1 -n mirror $vg
+lvchange -a n $vg/mirror
+
+check() {
+vgscan 2>&1 | tee vgscan.out
+grep "Inconsistent metadata found for VG $vg" vgscan.out
+vgscan 2>&1 | tee vgscan.out
+not grep "Inconsistent metadata found for VG $vg" vgscan.out
+}
+
+# try orphaning a missing PV (bz45867)
+disable_dev $dev1
+vgreduce --removemissing --force $vg
+enable_dev $dev1
+check
+
+exit 0 # FIXME, bug demonstration code follows
+# try to just change metadata; we expect the new version (with MISSING_PV set
+# on the reappeared volume) to be written out to the previously missing PV
+vgextend $vg $dev1
+disable_dev $dev1
+lvremove $vg/mirror
+enable_dev $dev1
+check
Index: src/external/gpl2/lvm2tools/dist/test/t-vgcreate-usage.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-vgcreate-usage.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-vgcreate-usage.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-vgcreate-usage.sh	12 Dec 2008 16:33:04 -0000	1.1.1.1.2.1
@@ -0,0 +1,68 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+test_description='Exercise some vgcreate diagnostics'
+
+. ./test-utils.sh
+
+aux prepare_devs 3
+pvcreate $dev1 $dev2
+pvcreate --metadatacopies 0 $dev3
+
+#COMM 'vgcreate accepts 8.00M physicalextentsize for VG'
+vgcreate $vg --physicalextentsize 8.00M $dev1 $dev2 
+check_vg_field_ $vg vg_extent_size 8.00M 
+vgremove $vg
+
+#COMM 'vgcreate accepts smaller (128) maxlogicalvolumes for VG'
+vgcreate $vg --maxlogicalvolumes 128 $dev1 $dev2 
+check_vg_field_ $vg max_lv 128 
+vgremove $vg
+
+#COMM 'vgcreate accepts smaller (128) maxphysicalvolumes for VG'
+vgcreate $vg --maxphysicalvolumes 128 $dev1 $dev2
+check_vg_field_ $vg max_pv 128
+vgremove $vg
+
+#COMM 'vgcreate rejects a zero physical extent size'
+not vgcreate --physicalextentsize 0 $vg $dev1 $dev2 2>err
+grep "^  Physical extent size may not be zero\$" err
+
+#COMM 'vgcreate rejects "inherit" allocation policy'
+not vgcreate --alloc inherit $vg $dev1 $dev2 2>err
+grep "^  Volume Group allocation policy cannot inherit from anything\$" err
+
+#COMM 'vgcreate rejects vgname "."'
+vginvalid=.; 
+not vgcreate $vginvalid $dev1 $dev2 2>err
+grep "New volume group name \"$vginvalid\" is invalid\$" err
+
+#COMM 'vgcreate rejects vgname greater than 128 characters'
+vginvalid=thisnameisridiculouslylongtotestvalidationcodecheckingmaximumsizethisiswhathappenswhenprogrammersgetboredandorarenotcreativedonttrythisathome
+not vgcreate $vginvalid $dev1 $dev2 2>err
+grep "New volume group name \"$vginvalid\" is invalid\$" err
+
+#COMM 'vgcreate rejects already existing vgname "/tmp/$vg"'
+#touch /tmp/$vg
+#not vgcreate $vg $dev1 $dev2 2>err
+#grep "New volume group name \"$vg\" is invalid\$" err
+
+#COMM "vgcreate rejects repeated invocation (run 2 times) (bz178216)"
+vgcreate $vg $dev1 $dev2
+not vgcreate $vg $dev1 $dev2
+vgremove -ff $vg
+
+#COMM 'vgcreate rejects MaxLogicalVolumes > 255'
+not vgcreate --metadatatype 1 --maxlogicalvolumes 1024 $vg $dev1 $dev2 2>err
+grep "^  Number of volumes may not exceed 255\$" err
+
+#COMM "vgcreate fails when the only pv has --metadatacopies 0"
+not vgcreate $vg $dev3
Index: src/external/gpl2/lvm2tools/dist/test/t-vgmerge-operation.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-vgmerge-operation.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-vgmerge-operation.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-vgmerge-operation.sh	12 Dec 2008 16:33:04 -0000	1.1.1.1.2.1
@@ -0,0 +1,81 @@
+#!/bin/sh
+# Copyright (C) 2007-2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+test_description='Test vgmerge operation'
+
+. ./test-utils.sh
+
+aux prepare_pvs 4 64
+
+# 'vgmerge succeeds with single linear LV in source VG'
+vgcreate $vg1 $dev1 $dev2 
+vgcreate $vg2 $dev3 $dev4 
+lvcreate -l 4 -n $lv1 $vg1 $dev1 
+vgchange -an $vg1 
+vg_validate_pvlv_counts_ $vg1 2 1 0 
+vg_validate_pvlv_counts_ $vg2 2 0 0 
+vgmerge $vg2 $vg1 
+vg_validate_pvlv_counts_ $vg2 4 1 0 
+vgremove -f $vg2
+
+# 'vgmerge succeeds with single linear LV in source and destination VG'
+vgcreate $vg1 $dev1 $dev2 
+vgcreate $vg2 $dev3 $dev4 
+lvcreate -l 4 -n $lv1 $vg1 
+lvcreate -l 4 -n $lv2 $vg2 
+vgchange -an $vg1 
+vgchange -an $vg2 
+vg_validate_pvlv_counts_ $vg1 2 1 0 
+vg_validate_pvlv_counts_ $vg2 2 1 0 
+vgmerge $vg2 $vg1 
+vg_validate_pvlv_counts_ $vg2 4 2 0 
+vgremove -f $vg2
+
+# 'vgmerge succeeds with linear LV + snapshots in source VG'
+vgcreate $vg1 $dev1 $dev2 
+vgcreate $vg2 $dev3 $dev4 
+lvcreate -l 16 -n $lv1 $vg1 
+lvcreate -l 4 -s -n $lv2 $vg1/$lv1 
+vgchange -an $vg1 
+vg_validate_pvlv_counts_ $vg1 2 2 1 
+vg_validate_pvlv_counts_ $vg2 2 0 0 
+vgmerge $vg2 $vg1 
+vg_validate_pvlv_counts_ $vg2 4 2 1 
+lvremove -f $vg2/$lv2 
+vgremove -f $vg2
+
+# 'vgmerge succeeds with mirrored LV in source VG'
+vgcreate $vg1 $dev1 $dev2 $dev3 
+vgcreate $vg2 $dev4 
+lvcreate -l 4 -n $lv1 -m1 $vg1 
+vgchange -an $vg1 
+vg_validate_pvlv_counts_ $vg1 3 1 0 
+vg_validate_pvlv_counts_ $vg2 1 0 0 
+vgmerge $vg2 $vg1 
+vg_validate_pvlv_counts_ $vg2 4 1 0 
+lvremove -f $vg2/$lv1 
+vgremove -f $vg2
+
+# 'vgmerge rejects LV name collision'
+vgcreate $vg1 $dev1 $dev2
+vgcreate $vg2 $dev3 $dev4
+lvcreate -l 4 -n $lv1 $vg1
+lvcreate -l 4 -n $lv1 $vg2
+vgchange -an $vg1
+aux vg_validate_pvlv_counts_ $vg1 2 1 0
+aux vg_validate_pvlv_counts_ $vg2 2 1 0
+not vgmerge $vg2 $vg1 2>err
+grep "Duplicate logical volume name \"$lv1\" in \"$vg2\" and \"$vg1" err
+aux vg_validate_pvlv_counts_ $vg1 2 1 0
+aux vg_validate_pvlv_counts_ $vg2 2 1 0
+vgremove -f $vg1
+vgremove -f $vg2
+
Index: src/external/gpl2/lvm2tools/dist/test/t-vgmerge-usage.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-vgmerge-usage.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-vgmerge-usage.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-vgmerge-usage.sh	12 Dec 2008 16:33:04 -0000	1.1.1.1.2.1
@@ -0,0 +1,69 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+# 'Test vgmerge command options for validity'
+
+. ./test-utils.sh
+
+aux prepare_pvs 4
+
+# 'vgmerge normal operation'
+vgcreate $vg1 $dev1 $dev2 
+vgcreate $vg2 $dev3 $dev4 
+vgmerge $vg1 $vg2 
+vgremove $vg1
+
+# 'vgmerge rejects duplicate vg name'
+vgcreate $vg1 $dev1 $dev2 
+vgcreate $vg2 $dev3 $dev4 
+not vgmerge $vg1 $vg1 2>err
+grep "^  Duplicate volume group name \"$vg1\"\$" err 
+vgremove $vg2 
+vgremove $vg1
+
+# 'vgmerge rejects vgs with incompatible extent_size'
+vgcreate --physicalextentsize 4M $vg1 $dev1 $dev2 
+vgcreate --physicalextentsize 8M $vg2 $dev3 $dev4 
+not vgmerge $vg1 $vg2 2>err
+grep "^  Extent sizes differ" err 
+vgremove $vg2 
+vgremove $vg1
+
+# 'vgmerge rejects vgmerge because max_pv is exceeded'
+vgcreate --maxphysicalvolumes 2 $vg1 $dev1 $dev2 
+vgcreate --maxphysicalvolumes 2 $vg2 $dev3 $dev4 
+not vgmerge $vg1 $vg2 2>err
+grep "^  Maximum number of physical volumes (2) exceeded" err 
+vgremove $vg2 
+vgremove $vg1
+
+# 'vgmerge rejects vg with active lv'
+vgcreate $vg1 $dev1 $dev2 
+vgcreate $vg2 $dev3 $dev4 
+lvcreate -l 4 -n lv1 $vg2 
+not vgmerge $vg1 $vg2 2>err
+grep "^  Logical volumes in \"$vg2\" must be inactive\$" err 
+vgremove -f $vg2 
+vgremove -f $vg1
+
+# 'vgmerge rejects vgmerge because max_lv is exceeded' 
+vgcreate --maxlogicalvolumes 2 $vg1 $dev1 $dev2 
+vgcreate --maxlogicalvolumes 2 $vg2 $dev3 $dev4 
+lvcreate -l 4 -n lv1 $vg1 
+lvcreate -l 4 -n lv2 $vg1 
+lvcreate -l 4 -n lv3 $vg2 
+vgchange -an $vg1 
+vgchange -an $vg2 
+not vgmerge $vg1 $vg2 2>err
+grep "^  Maximum number of logical volumes (2) exceeded" err 
+vgremove -f $vg2 
+vgremove -f $vg1
+
Index: src/external/gpl2/lvm2tools/dist/test/t-vgreduce-usage.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-vgreduce-usage.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-vgreduce-usage.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-vgreduce-usage.sh	12 Dec 2008 16:33:04 -0000	1.1.1.1.2.2
@@ -0,0 +1,85 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+. ./test-utils.sh
+
+aux prepare_devs 4
+
+for mdatype in 1 2
+do
+    # setup PVs
+    pvcreate -M$mdatype $dev1 $dev2 
+
+    # (lvm$mdatype) vgreduce removes only the specified pv from vg (bz427382)" '
+    vgcreate -M$mdatype $vg1 $dev1 $dev2
+    vgreduce $vg1 $dev1
+    check_pv_field_ $dev2 vg_name $vg1
+    vgremove -f $vg1
+
+    # (lvm$mdatype) vgreduce rejects removing the last pv (--all)
+    vgcreate -M$mdatype $vg1 $dev1 $dev2
+    not vgreduce --all $vg1
+    vgremove -f $vg1
+
+    # (lvm$mdatype) vgreduce rejects removing the last pv
+    vgcreate -M$mdatype $vg1 $dev1 $dev2
+    not vgreduce $vg1 $dev1 $dev2
+    vgremove -f $vg1
+
+    pvremove -ff $dev1 $dev2
+done
+
+mdatype=2 # we only expect the following to work for lvm2 metadata
+
+# (lvm$mdatype) setup PVs (--metadatacopies 0)
+pvcreate -M$mdatype $dev1 $dev2
+pvcreate --metadatacopies 0 -M$mdatype $dev3 $dev4
+
+# (lvm$mdatype) vgreduce rejects removing pv with the last mda copy (bz247448)
+vgcreate -M$mdatype $vg1 $dev1 $dev3
+not vgreduce $vg1 $dev1
+vgremove -f $vg1
+
+#COMM "(lvm$mdatype) vgreduce --removemissing --force repares to linear (bz221921)"
+# (lvm$mdatype) setup: create mirror & damage one pv
+vgcreate -M$mdatype $vg1 $dev1 $dev2 $dev3
+lvcreate -n $lv1 -m1 -l 4 $vg1
+lvcreate -n $lv2  -l 4 $vg1 $dev2
+lvcreate -n $lv3 -l 4 $vg1 $dev3
+vgchange -an $vg1
+aux disable_dev $dev1
+# (lvm$mdatype) vgreduce --removemissing --force repares to linear
+vgreduce --removemissing --force $vg1
+check_lv_field_ $vg1/$lv1 segtype linear
+vg_validate_pvlv_counts_ $vg1 2 3 0
+# cleanup
+aux enable_dev $dev1
+vgremove -ff $vg1
+
+#COMM "vgreduce rejects --removemissing --mirrorsonly --force when nonmirror lv lost too"
+# (lvm$mdatype) setup: create mirror + linear lvs
+vgcreate -M$mdatype $vg1 $devs
+lvcreate -n $lv2 -l 4 $vg1
+lvcreate -m1 -n $lv1 -l 4 $vg1 $dev1 $dev2 $dev3
+lvcreate -n $lv3 -l 4 $vg1 $dev3
+pvs --segments -o +lv_name # for record only
+# (lvm$mdatype) setup: damage one pv
+vgchange -an $vg1 
+aux disable_dev $dev1
+#pvcreate -ff -y $dev1
+# vgreduce rejects --removemissing --mirrorsonly --force when nonmirror lv lost too
+not vgreduce --removemissing --mirrorsonly --force $vg1
+
+aux enable_dev $dev1
+
+pvs -P # for record
+lvs -P # for record
+vgs -P # for record
Index: src/external/gpl2/lvm2tools/dist/test/t-vgrename-usage.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-vgrename-usage.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-vgrename-usage.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-vgrename-usage.sh	12 Dec 2008 16:33:04 -0000	1.1.1.1.2.1
@@ -0,0 +1,29 @@
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+. ./test-utils.sh
+
+aux prepare_devs 4
+pvcreate $dev1 $dev2
+pvcreate --metadatacopies 0 $dev3 $dev4
+
+# vgrename normal operation - rename vg1 to vg2
+vgcreate $vg1 $dev1 $dev2
+vgrename $vg1 $vg2
+check_vg_field_ $vg2 vg_name $vg2
+vgremove $vg2
+
+# vgrename by uuid (bz231187)
+vgcreate $vg1 $dev1 $dev3
+UUID=$(vgs --noheading -o vg_uuid $vg1)
+check_vg_field_ $vg1 vg_uuid $UUID
+vgrename $UUID $vg2
+check_vg_field_ $vg2 vg_name $vg2
+vgremove $vg2
Index: src/external/gpl2/lvm2tools/dist/test/t-vgsplit-operation.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-vgsplit-operation.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-vgsplit-operation.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-vgsplit-operation.sh	12 Dec 2008 16:33:04 -0000	1.1.1.1.2.1
@@ -0,0 +1,290 @@
+#!/bin/sh
+# Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+# Test vgsplit operation, including different LV types
+
+. ./test-utils.sh
+
+COMM() {  
+	LAST_TEST="$@"
+}
+
+prepare_pvs 5 257
+# FIXME: paramaterize lvm1 vs lvm2 metadata; most of these tests should run
+# fine with lvm1 metadata as well; for now, just add disks 5 and 6 as lvm1
+# metadata
+
+#
+# vgsplit can be done into a new or existing VG
+#
+for i in new existing
+do
+	#
+	# We can have PVs or LVs on the cmdline
+	#
+	for j in PV LV
+	do
+COMM "vgsplit correctly splits single linear LV into $i VG ($j args)"
+		vgcreate $vg1 $dev1 $dev2 
+		if [ $i = existing ]; then
+		   vgcreate $vg2 $dev3 $dev4
+		fi 
+		lvcreate -l 4 -n $lv1 $vg1 $dev1 
+		vgchange -an $vg1 
+		if [ $j = PV ]; then
+		  vgsplit $vg1 $vg2 $dev1
+		else
+		  vgsplit -n $lv1 $vg1 $vg2
+		fi 
+		vg_validate_pvlv_counts_ $vg1 1 0 0 
+		if [ $i = existing ]; then
+		   aux vg_validate_pvlv_counts_ $vg2 3 1 0
+		else
+		   aux vg_validate_pvlv_counts_ $vg2 1 1 0
+		fi 
+		lvremove -f $vg2/$lv1 
+		vgremove -f $vg2 
+		vgremove -f $vg1
+
+COMM "vgsplit correctly splits single striped LV into $i VG ($j args)"
+		vgcreate $vg1 $dev1 $dev2 
+		if [ $i = existing ]; then
+		   vgcreate $vg2 $dev3 $dev4
+		fi 
+		lvcreate -l 4 -i 2 -n $lv1 $vg1 $dev1 $dev2 
+		vgchange -an $vg1 
+		if [ $j = PV ]; then
+		  vgsplit $vg1 $vg2 $dev1 $dev2
+		else
+		  vgsplit -n $lv1 $vg1 $vg2
+		fi 
+		if [ $i = existing ]; then
+		  aux vg_validate_pvlv_counts_ $vg2 4 1 0
+		else
+		  aux vg_validate_pvlv_counts_ $vg2 2 1 0
+		fi 
+		lvremove -f $vg2/$lv1 
+		vgremove -f $vg2
+
+COMM "vgsplit correctly splits mirror LV into $i VG ($j args)" 
+		vgcreate $vg1 $dev1 $dev2 $dev3 
+		if [ $i = existing ]; then
+		  vgcreate $vg2 $dev4
+		fi 
+		lvcreate -l 64 -m1 -n $lv1 $vg1 $dev1 $dev2 $dev3 
+		vgchange -an $vg1 
+		if [ $j = PV ]; then
+		  vgsplit $vg1 $vg2 $dev1 $dev2 $dev3
+		else
+		  vgsplit -n $lv1 $vg1 $vg2
+		fi 
+		if [ $i = existing ]; then
+		  aux vg_validate_pvlv_counts_ $vg2 4 1 0
+		else
+		  aux vg_validate_pvlv_counts_ $vg2 3 1 0
+		fi 
+		lvremove -f $vg2/$lv1 
+		vgremove -f $vg2
+
+COMM "vgsplit correctly splits origin and snapshot LV into $i VG ($j args)" 
+		vgcreate $vg1 $dev1 $dev2 
+		if [ $i = existing ]; then
+		  vgcreate $vg2 $dev3 $dev4
+		fi 
+		lvcreate -l 64 -i 2 -n $lv1 $vg1 $dev1 $dev2 
+		lvcreate -l 4 -i 2 -s -n $lv2 $vg1/$lv1 
+		vgchange -an $vg1 
+		if [ $j = PV ]; then
+		  vgsplit $vg1 $vg2 $dev1 $dev2
+		else
+		  vgsplit -n $lv1 $vg1 $vg2
+		fi 
+		if [ $i = existing ]; then
+		  aux vg_validate_pvlv_counts_ $vg2 4 2 1
+		else
+		  aux vg_validate_pvlv_counts_ $vg2 2 2 1
+		fi 
+		lvremove -f $vg2/$lv2 
+		lvremove -f $vg2/$lv1 
+		vgremove -f $vg2
+
+COMM "vgsplit correctly splits linear LV but not snap+origin LV into $i VG ($j args)" 
+		vgcreate $vg1 $dev1 $dev2 
+		if [ $i = existing ]; then
+		  vgcreate $vg2 $dev3
+		fi 
+		lvcreate -l 64 -i 2 -n $lv1 $vg1 
+		lvcreate -l 4 -i 2 -s -n $lv2 $vg1/$lv1 
+		vgextend $vg1 $dev4 
+		lvcreate -l 64 -n $lv3 $vg1 $dev4 
+		vgchange -an $vg1 
+		if [ $j = PV ]; then
+		  vgsplit $vg1 $vg2 $dev4
+		else
+		  vgsplit -n $lv3 $vg1 $vg2
+		fi 
+		if [ $i = existing ]; then
+		  aux vg_validate_pvlv_counts_ $vg2 2 1 0
+		  aux vg_validate_pvlv_counts_ $vg1 2 2 1
+		else
+		  aux vg_validate_pvlv_counts_ $vg2 1 1 0
+		  aux vg_validate_pvlv_counts_ $vg1 2 2 1
+		fi 
+		lvremove -f $vg1/$lv2 
+		lvremove -f $vg1/$lv1 
+		lvremove -f $vg2/$lv3 
+		vgremove -f $vg1 
+		vgremove -f $vg2
+
+COMM "vgsplit correctly splits linear LV but not mirror LV into $i VG ($j args)" 
+		vgcreate $vg1 $dev1 $dev2 $dev3 
+		if [ $i = existing ]; then
+		  vgcreate $vg2 $dev5
+		fi 
+		lvcreate -l 64 -m1 -n $lv1 $vg1 $dev1 $dev2 $dev3 
+		vgextend $vg1 $dev4 
+		lvcreate -l 64 -n $lv2 $vg1 $dev4 
+		vgchange -an $vg1 
+		vgs
+		lvs 
+		pvs
+		if [ $j = PV ]; then
+		  vgsplit $vg1 $vg2 $dev4
+		else
+		  vgsplit -n $lv2 $vg1 $vg2
+		fi 
+		if [ $i = existing ]; then
+		  aux vg_validate_pvlv_counts_ $vg1 3 1 0
+		  aux vg_validate_pvlv_counts_ $vg2 2 1 0
+		else
+		vgs
+		lvs 
+		pvs
+		  aux vg_validate_pvlv_counts_ $vg1 3 1 0
+		  aux vg_validate_pvlv_counts_ $vg2 1 1 0
+		fi 
+		lvremove -f $vg1/$lv1 
+		lvremove -f $vg2/$lv2 
+		vgremove -f $vg1 
+		vgremove -f $vg2
+
+	done
+done
+
+#
+# Test more complex setups where the code has to find associated PVs and
+# LVs to split the VG correctly
+# 
+COMM "vgsplit fails splitting 3 striped LVs into VG when only 1 LV specified" 
+vgcreate $vg1 $dev1 $dev2 $dev3 $dev4 
+lvcreate -l 4 -n $lv1 -i 2 $vg1 $dev1 $dev2 
+lvcreate -l 4 -n $lv2 -i 2 $vg1 $dev2 $dev3 
+lvcreate -l 4 -n $lv3 -i 2 $vg1 $dev3 $dev4 
+vgchange -an $vg1 
+not vgsplit -n $lv1 $vg1 $vg2
+vgremove -ff $vg1
+
+COMM "vgsplit fails splitting one LV with 2 snapshots, only origin LV specified" 
+vgcreate $vg1 $dev1 $dev2 $dev3 $dev4 
+lvcreate -l 16 -n $lv1 $vg1 $dev1 $dev2 
+lvcreate -l 4 -n $lv2 -s $vg1/$lv1 
+lvcreate -l 4 -n $lv3 -s $vg1/$lv1 
+vg_validate_pvlv_counts_ $vg1 4 3 2 
+vgchange -an $vg1 
+not vgsplit -n $lv1 $vg1 $vg2;
+lvremove -f $vg1/$lv2 
+lvremove -f $vg1/$lv3 
+lvremove -f $vg1/$lv1 
+vgremove -ff $vg1
+
+COMM "vgsplit fails splitting one LV with 2 snapshots, only snapshot LV specified" 
+vgcreate $vg1 $dev1 $dev2 $dev3 $dev4 
+lvcreate -l 16 -n $lv1 $vg1 $dev1 $dev2 
+lvcreate -l 4 -n $lv2 -s $vg1/$lv1 
+lvcreate -l 4 -n $lv3 -s $vg1/$lv1 
+vg_validate_pvlv_counts_ $vg1 4 3 2 
+vgchange -an $vg1 
+not vgsplit -n $lv2 $vg1 $vg2
+lvremove -f $vg1/$lv2 
+lvremove -f $vg1/$lv3 
+lvremove -f $vg1/$lv1 
+vgremove -ff $vg1
+
+COMM "vgsplit fails splitting one mirror LV, only one PV specified" 
+vgcreate $vg1 $dev1 $dev2 $dev3 $dev4 
+lvcreate -l 16 -n $lv1 -m1 $vg1 $dev1 $dev2 $dev3 
+vg_validate_pvlv_counts_ $vg1 4 1 0 
+vgchange -an $vg1 
+not vgsplit $vg1 $vg2 $dev2 
+vgremove -ff $vg1
+
+COMM "vgsplit fails splitting 1 mirror + 1 striped LV, only striped LV specified" 
+vgcreate $vg1 $dev1 $dev2 $dev3 $dev4 
+lvcreate -l 16 -n $lv1 -m1 $vg1 $dev1 $dev2 $dev3 
+lvcreate -l 16 -n $lv2 -i 2 $vg1 $dev3 $dev4 
+vg_validate_pvlv_counts_ $vg1 4 2 0 
+vgchange -an $vg1 
+not vgsplit -n $lv2 $vg1 $vg2 2>err
+vgremove -ff $vg1
+
+#
+# Verify vgsplit rejects active LVs only when active LVs involved in split
+#
+COMM "vgsplit fails, active mirror involved in split" 
+vgcreate $vg1 $dev1 $dev2 $dev3 $dev4 
+lvcreate -l 16 -n $lv1 -m1 $vg1 $dev1 $dev2 $dev3 
+lvcreate -l 16 -n $lv2 $vg1 $dev4 
+lvchange -an $vg1/$lv2 
+vg_validate_pvlv_counts_ $vg1 4 2 0 
+not vgsplit -n $lv1 $vg1 $vg2;
+vg_validate_pvlv_counts_ $vg1 4 2 0 
+vgremove -ff $vg1
+
+COMM "vgsplit succeeds, active mirror not involved in split" 
+vgcreate $vg1 $dev1 $dev2 $dev3 $dev4 
+lvcreate -l 16 -n $lv1 -m1 $vg1 $dev1 $dev2 $dev3 
+lvcreate -l 16 -n $lv2 $vg1 $dev4 
+lvchange -an $vg1/$lv2 
+vg_validate_pvlv_counts_ $vg1 4 2 0 
+vgsplit -n $lv2 $vg1 $vg2 
+vg_validate_pvlv_counts_ $vg1 3 1 0 
+vg_validate_pvlv_counts_ $vg2 1 1 0 
+vgremove -ff $vg1 
+vgremove -ff $vg2
+
+COMM "vgsplit fails, active snapshot involved in split" 
+vgcreate $vg1 $dev1 $dev2 $dev3 $dev4 
+lvcreate -l 64 -i 2 -n $lv1 $vg1 $dev1 $dev2 
+lvcreate -l 4 -i 2 -s -n $lv2 $vg1/$lv1 
+lvcreate -l 64 -i 2 -n $lv3 $vg1 $dev3 $dev4 
+lvchange -an $vg1/$lv3 
+vg_validate_pvlv_counts_ $vg1 4 3 1 
+not vgsplit -n $lv2 $vg1 $vg2;
+vg_validate_pvlv_counts_ $vg1 4 3 1 
+lvremove -f $vg1/$lv2 
+vgremove -ff $vg1
+
+COMM "vgsplit succeeds, active snapshot not involved in split" 
+vgcreate $vg1 $dev1 $dev2 $dev3 
+lvcreate -l 64 -i 2 -n $lv1 $vg1 $dev1 $dev2 
+lvcreate -l 4 -s -n $lv2 $vg1/$lv1 
+vgextend $vg1 $dev4 
+lvcreate -l 64 -n $lv3 $vg1 $dev4 
+lvchange -an $vg1/$lv3 
+vg_validate_pvlv_counts_ $vg1 4 3 1 
+vgsplit -n $lv3 $vg1 $vg2 
+vg_validate_pvlv_counts_ $vg1 3 2 1 
+vg_validate_pvlv_counts_ $vg2 1 1 0 
+vgchange -an $vg1 
+lvremove -f $vg1/$lv2 
+vgremove -ff $vg1 
+vgremove -ff $vg2
+
Index: src/external/gpl2/lvm2tools/dist/test/t-vgsplit-usage.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/t-vgsplit-usage.sh
diff -N src/external/gpl2/lvm2tools/dist/test/t-vgsplit-usage.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/t-vgsplit-usage.sh	12 Dec 2008 16:33:04 -0000	1.1.1.1.2.1
@@ -0,0 +1,180 @@
+#!/bin/sh
+# Copyright (C) 2007-2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+# Test vgsplit command options for validity
+
+. ./test-utils.sh
+
+aux prepare_devs 5
+
+# FIXME: paramaterize lvm1 vs lvm2 metadata; most of these tests should run
+# fine with lvm1 metadata as well; for now, just add disks 5 and 6 as lvm1
+# metadata
+
+for mdatype in 1 2
+do
+
+pvcreate -M$mdatype $devs
+
+# vgsplit accepts new vg as destination of split
+# lvm1 -- bz244792
+vgcreate -M$mdatype $vg1 $devs
+vgsplit $vg1 $vg2 $dev1 1>err
+grep "New volume group \"$vg2\" successfully split from \"$vg1\"" err 
+vgremove $vg1 
+vgremove $vg2
+
+# vgsplit accepts existing vg as destination of split
+vgcreate -M$mdatype $vg1 $dev1 $dev2 
+vgcreate -M$mdatype $vg2 $dev3 $dev4 
+vgsplit $vg1 $vg2 $dev1 1>err
+grep "Existing volume group \"$vg2\" successfully split from \"$vg1\"" err 
+vgremove $vg1 
+vgremove $vg2
+
+# vgsplit accepts --maxphysicalvolumes 128 on new VG
+vgcreate -M$mdatype $vg1 $dev1 $dev2 
+vgsplit --maxphysicalvolumes 128 $vg1 $vg2 $dev1 
+check_vg_field_ $vg2 max_pv 128 
+vgremove $vg1 
+vgremove $vg2
+
+# vgsplit accepts --maxlogicalvolumes 128 on new VG
+vgcreate -M$mdatype $vg1 $dev1 $dev2 
+vgsplit --maxlogicalvolumes 128 $vg1 $vg2 $dev1 
+check_vg_field_ $vg2 max_lv 128 
+vgremove $vg1 
+vgremove $vg2
+
+# vgsplit rejects split because max_pv of destination would be exceeded
+vgcreate -M$mdatype --maxphysicalvolumes 2 $vg1 $dev1 $dev2
+vgcreate -M$mdatype --maxphysicalvolumes 2 $vg2 $dev3 $dev4
+not vgsplit $vg1 $vg2 $dev1 2>err;
+grep "^  Maximum number of physical volumes (2) exceeded" err
+vgremove $vg2
+vgremove $vg1
+
+# vgsplit rejects split because maxphysicalvolumes given with existing vg
+vgcreate -M$mdatype --maxphysicalvolumes 2 $vg1 $dev1 $dev2 
+vgcreate -M$mdatype --maxphysicalvolumes 2 $vg2 $dev3 $dev4 
+not vgsplit --maxphysicalvolumes 2 $vg1 $vg2 $dev1 2>err;
+grep "^  Volume group \"$vg2\" exists, but new VG option specified" err 
+vgremove $vg2 
+vgremove $vg1
+
+# vgsplit rejects split because maxlogicalvolumes given with existing vg
+vgcreate -M$mdatype --maxlogicalvolumes 2 $vg1 $dev1 $dev2 
+vgcreate -M$mdatype --maxlogicalvolumes 2 $vg2 $dev3 $dev4 
+not vgsplit --maxlogicalvolumes 2 $vg1 $vg2 $dev1 2>err
+grep "^  Volume group \"$vg2\" exists, but new VG option specified" err 
+vgremove $vg2 
+vgremove $vg1
+
+# vgsplit rejects split because alloc given with existing vg
+vgcreate -M$mdatype --alloc cling $vg1 $dev1 $dev2 
+vgcreate -M$mdatype --alloc cling $vg2 $dev3 $dev4 
+not vgsplit --alloc cling $vg1 $vg2 $dev1 2>err;
+grep "^  Volume group \"$vg2\" exists, but new VG option specified" err 
+vgremove $vg2 
+vgremove $vg1
+
+# vgsplit rejects split because clustered given with existing vg
+vgcreate -M$mdatype --clustered n $vg1 $dev1 $dev2 
+vgcreate -M$mdatype --clustered n $vg2 $dev3 $dev4 
+not vgsplit --clustered n $vg1 $vg2 $dev1 2>err
+grep "^  Volume group \"$vg2\" exists, but new VG option specified" err 
+vgremove $vg2 
+vgremove $vg1
+
+# vgsplit rejects vg with active lv
+pvcreate -M$mdatype -ff $dev3 $dev4 
+vgcreate -M$mdatype $vg1 $dev1 $dev2 
+vgcreate -M$mdatype $vg2 $dev3 $dev4 
+lvcreate -l 4 -n $lv1 $vg1 
+not vgsplit $vg1 $vg2 $dev1 2>err;
+grep "^  Logical volumes in \"$vg1\" must be inactive\$" err 
+vgremove -f $vg2 
+vgremove -f $vg1
+
+# vgsplit rejects split because max_lv is exceeded
+vgcreate -M$mdatype --maxlogicalvolumes 2 $vg1 $dev1 $dev2 
+vgcreate -M$mdatype --maxlogicalvolumes 2 $vg2 $dev3 $dev4 
+lvcreate -l 4 -n $lv1 $vg1 
+lvcreate -l 4 -n $lv2 $vg1 
+lvcreate -l 4 -n $lv3 $vg2 
+vgchange -an $vg1 
+vgchange -an $vg2 
+not vgsplit $vg1 $vg2 $dev1 2>err;
+grep "^  Maximum number of logical volumes (2) exceeded" err 
+vgremove -f $vg2 
+vgremove -f $vg1
+
+# vgsplit verify default - max_lv attribute from new VG is same as source VG" \
+vgcreate -M$mdatype $vg1 $dev1 $dev2 
+lvcreate -l 4 -n $lv1 $vg1 
+vgchange -an $vg1 
+vgsplit $vg1 $vg2 $dev1 
+compare_vg_field_ $vg1 $vg2 max_lv 
+vgremove -f $vg2 
+vgremove -f $vg1
+
+# vgsplit verify default - max_pv attribute from new VG is same as source VG" \
+vgcreate -M$mdatype $vg1 $dev1 $dev2 
+lvcreate -l 4 -n $lv1 $vg1 
+vgchange -an $vg1 
+vgsplit $vg1 $vg2 $dev1 
+compare_vg_field_ $vg1 $vg2 max_pv 
+vgremove -f $vg2 
+vgremove -f $vg1
+
+# vgsplit verify default - vg_fmt attribute from new VG is same as source VG" \
+vgcreate -M$mdatype $vg1 $dev1 $dev2 
+lvcreate -l 4 -n $lv1 $vg1 
+vgchange -an $vg1 
+vgsplit $vg1 $vg2 $dev1 
+compare_vg_field_ $vg1 $vg2 vg_fmt 
+vgremove -f $vg2 
+vgremove -f $vg1
+
+# vgsplit rejects split because PV not in VG
+vgcreate -M$mdatype $vg1 $dev1 $dev2 
+vgcreate -M$mdatype $vg2 $dev3 $dev4 
+lvcreate -l 4 -n $lv1 $vg1 
+lvcreate -l 4 -n $lv2 $vg1 
+vgchange -an $vg1 
+not vgsplit $vg1 $vg2 $dev3 2>err;
+vgremove -f $vg2 
+vgremove -f $vg1
+done
+
+# ONLY LVM2 metadata
+# setup PVs" '
+pvcreate --metadatacopies 0 $dev5
+
+# vgsplit rejects to give away pv with the last mda copy
+vgcreate $vg1 $dev5 $dev2  
+lvcreate -l 10 -n $lv1  $vg1 
+lvchange -an $vg1/$lv1 
+vg_validate_pvlv_counts_ $vg1 2 1 0 
+not vgsplit  $vg1 $vg2 $dev5;
+vg_validate_pvlv_counts_ $vg1 2 1 0 
+vgremove -ff $vg1
+
+# vgsplit rejects split because metadata types differ
+pvcreate -ff -M1 $dev3 $dev4 
+pvcreate -ff $dev1 $dev2 
+vgcreate -M1 $vg1 $dev3 $dev4 
+vgcreate $vg2 $dev1 $dev2 
+not vgsplit $vg1 $vg2 $dev3 2>err;
+grep "^  Metadata types differ" err 
+vgremove $vg2 
+vgremove $vg1
+
Index: src/external/gpl2/lvm2tools/dist/test/test-lib.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/test-lib.sh
diff -N src/external/gpl2/lvm2tools/dist/test/test-lib.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/test-lib.sh	12 Dec 2008 16:33:04 -0000	1.1.1.1.2.1
@@ -0,0 +1,272 @@
+#!/bin/sh
+# Derived from git's t/test-lib.sh, which is Copyright (c) 2005 Junio C Hamano
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+# For repeatability, reset the environment to known value.
+LANG=C
+LC_ALL=C
+TZ=UTC
+export LANG LC_ALL TZ
+
+. ./init.sh || { echo >&2 you must run make first; exit 1; }
+
+# Protect ourselves from common misconfiguration to export
+# CDPATH into the environment
+unset CDPATH
+
+# Each test should start with something like this, after copyright notices:
+#
+# test_description='Description of this test...
+# This test checks if command xyzzy does the right thing...
+# '
+# . ./test-lib.sh
+
+error () {
+	echo "* error: $*"
+	exit 1
+}
+
+say () {
+	echo "* $*"
+}
+
+this_test_() { expr "./$0" : '.*/t-\([^/]*\)\.sh$'; }
+
+test "${test_description}" != "" ||
+error "Test script did not set test_description."
+
+verboselevel=0
+while test "$#" -ne 0
+do
+	case "$1" in
+	-d|--d|--de|--deb|--debu|--debug)
+		debug=t ;;
+	-i|--i|--im|--imm|--imme|--immed|--immedi|--immedia|--immediat|--immediate)
+		immediate=t ;;
+	-h|--h|--he|--hel|--help)
+		echo "$test_description"
+		exit 0 ;;
+	-v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
+		verbose=t ;;
+	-vv|-vvv|-vvvv)
+		verboselevel=${#1}
+		verboselevel=$(($verboselevel - 1))
+		verbose=t ;;
+	*)
+		echo "$0: unsupported option $1"
+		exit 0 ;;
+	esac
+        shift
+done
+
+exec 5>&1
+if test "$verbose" = "t"
+then
+	exec 4>&2 3>&1
+else
+	exec 4>/dev/null 3>/dev/null
+fi
+
+test_failure=0
+test_count=0
+
+trap 'echo >&5 "FATAL: Unexpected exit with code $?"; exit 1' exit
+
+# You are not expected to call test_ok_ and test_failure_ directly, use
+# the text_expect_* functions instead.
+
+test_ok_ () {
+	test_count=$(expr "$test_count" + 1)
+	say "  ok $test_count: $@"
+}
+
+test_failure_ () {
+	test_count=$(expr "$test_count" + 1)
+	test_failure=$(expr "$test_failure" + 1);
+	say "FAIL $test_count: $1"
+	shift
+	echo "$@" | sed -e 's/^/	/'
+	test "$immediate" = "" || exit 1
+}
+
+test_debug () {
+	test "$debug" = "" || eval "$1"
+}
+
+test_run_ () {
+	eval >&3 2>&4 "$1"
+	eval_ret="$?"
+	return 0
+}
+
+test_skip () {
+	this_test=$(this_test_)
+	this_test="$this_test.$(expr "$test_count" + 1)"
+	to_skip=
+	for skp in $SKIP_TESTS
+	do
+		case "$this_test" in
+		$skp)
+			to_skip=t
+		esac
+	done
+	case "$to_skip" in
+	t)
+		say >&3 "skipping test: $@"
+		test_count=$(expr "$test_count" + 1)
+		say "skip $test_count: $1"
+		: true
+		;;
+	*)
+		false
+		;;
+	esac
+}
+
+test_expect_failure () {
+	test "$#" = 2 ||
+	error "bug in the test script: not 2 parameters to test-expect-failure"
+	if ! test_skip "$@"
+	then
+		say >&3 "expecting failure: $2"
+		test_run_ "$2"
+		if [ "$?" = 0 -a "$eval_ret" != 0 -a "$eval_ret" -lt 129 ]
+		then
+			test_ok_ "$1"
+		else
+			test_failure_ "$@"
+		fi
+	fi
+	echo >&3 ""
+}
+
+test_expect_success () {
+	test "$#" = 2 ||
+	error "bug in the test script: not 2 parameters to test-expect-success"
+	if ! test_skip "$@"
+	then
+		say >&3 "expecting success: $2"
+		test_run_ "$2"
+		if [ "$?" = 0 -a "$eval_ret" = 0 ]
+		then
+			test_ok_ "$1"
+		else
+			test_failure_ "$@"
+		fi
+	fi
+	echo >&3 ""
+}
+
+test_expect_code () {
+	test "$#" = 3 ||
+	error "bug in the test script: not 3 parameters to test-expect-code"
+	if ! test_skip "$@"
+	then
+		say >&3 "expecting exit code $1: $3"
+		test_run_ "$3"
+		if [ "$?" = 0 -a "$eval_ret" = "$1" ]
+		then
+			test_ok_ "$2"
+		else
+			test_failure_ "$@"
+		fi
+	fi
+	echo >&3 ""
+}
+
+test_done () {
+	case "$test_failure" in
+	0)
+		# We could:
+		# cd .. && rm -fr trash
+		# but that means we forbid any tests that use their own
+		# subdirectory from calling test_done without coming back
+		# to where they started from.
+		# The Makefile provided will clean this test area so
+		# we will leave things as they are.
+
+		say "passed all $test_count test(s)"
+		exit 0 ;;
+
+	*)
+		say "failed $test_failure among $test_count test(s)"
+		exit 1 ;;
+
+	esac
+}
+
+this_test=$(this_test_)
+
+skip_=0
+# If $privileges_required_ is nonempty, non-root skips this test.
+if test "$privileges_required_" != ''; then
+    uid=`id -u` || error 'failed to run "id -u"'
+    if test "$uid" != 0; then
+	SKIP_TESTS="$SKIP_TESTS $this_test"
+	say "you have insufficient privileges for test $this_test"
+	skip_=1
+    fi
+fi
+
+pwd_=`pwd`
+
+test_dir_=${LVM_TEST_DIR-.}
+test "$test_dir_" = . && test_dir_=$pwd_
+
+# This is a stub function that is run upon trap (upon regular exit and
+# interrupt).  Override it with a per-test function, e.g., to unmount
+# a partition, or to undo any other global state changes.
+cleanup_() { :; }
+
+for skp in $SKIP_TESTS
+do
+	to_skip=
+	for skp in $SKIP_TESTS
+	do
+		case "$this_test" in
+		$skp)
+			to_skip=t
+		esac
+	done
+	case "$to_skip" in
+	t)
+		say >&3 "skipping test $this_test altogether"
+		say "skip all tests in $this_test"
+		trap - exit
+		test_done
+	esac
+done
+
+test_dir_rand_=$($abs_srcdir/mkdtemp $test_dir_ lvm-$this_test.XXXXXXXXXX) \
+    || error "failed to create temporary directory in $test_dir_"
+
+testlib_cleanup_() {
+    d="$test_dir_rand_";
+    cd "$test_dir_" && chmod -R u+rwx "$d" && rm -rf "$d"
+}
+
+# Run each test from within a temporary sub-directory named after the
+# test itself, and arrange to remove it upon exception or normal exit.
+trap 'st=$?; cleanup_; testlib_cleanup_; exit $st' 0
+trap '(exit $?); exit $?' 1 2 13 15
+
+cd $test_dir_rand_ || error "failed to cd to $test_dir_rand_"
+
+if test $skip_ = 0; then
+  . $abs_srcdir/lvm-utils.sh || exit 1
+fi
+
+if ( diff --version < /dev/null 2>&1 | grep GNU ) 2>&1 > /dev/null; then
+  compare='diff -u'
+elif ( cmp --version < /dev/null 2>&1 | grep GNU ) 2>&1 > /dev/null; then
+  compare='cmp -s'
+else
+  compare=cmp
+fi
Index: src/external/gpl2/lvm2tools/dist/test/test-utils.sh
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/test/test-utils.sh
diff -N src/external/gpl2/lvm2tools/dist/test/test-utils.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/test/test-utils.sh	12 Dec 2008 16:33:04 -0000	1.1.1.1.2.2
@@ -0,0 +1,180 @@
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+test_description="foo" # silence test-lib for now
+. ./test-lib.sh
+
+aux() {
+        # use just "$@" for verbose operation
+	"$@" > /dev/null 2> /dev/null
+	#"$@"
+}
+
+not () { "$@" && exit 1 || return 0; }
+
+STACKTRACE() {
+	trap - ERR;
+	i=0;
+	while FUNC=${FUNCNAME[$i]}; test "$FUNC" != "main"; do 
+		echo "$i ${FUNC}() called from ${BASH_SOURCE[$i]}:${BASH_LINENO[$i]}"
+		i=$(($i + 1));
+	done
+}	
+
+teardown() {
+	echo $LOOP
+	echo $PREFIX
+
+	test -n "$PREFIX" && {
+		rm -rf /dev/$PREFIX*
+		while dmsetup table | grep -q ^$PREFIX; do
+			for s in `dmsetup table | grep ^$PREFIX| cut -f1 -d:`; do
+				dmsetup resume $s 2>/dev/null > /dev/null || true
+				dmsetup remove $s 2>/dev/null > /dev/null || true
+			done
+		done
+	}
+
+	test -n "$LOOP" && losetup -d $LOOP
+	test -n "$LOOPFILE" && rm -f $LOOPFILE
+
+	cleanup_ # user-overridable cleanup
+	testlib_cleanup_ # call test-lib cleanup routine, too
+}
+
+make_ioerror() {
+	echo 0 10000000 error | dmsetup create ioerror
+	dmsetup resume ioerror
+	ln -s /dev/mapper/ioerror /dev/ioerror
+}
+
+prepare_loop() {
+	size=$1
+	test -n "$size" || size=32
+
+	test -n "$LOOP" && return 0
+	trap 'aux teardown' EXIT # don't forget to clean up
+	trap 'set +vex; STACKTRACE; set -vex' ERR
+	#trap - ERR
+
+	LOOPFILE="$PWD/test.img"
+	dd if=/dev/zero of="$LOOPFILE" bs=$((1024*1024)) count=1 seek=$(($size-1))
+	if LOOP=`losetup -s -f "$LOOPFILE" 2>/dev/null`; then
+		return 0
+	elif LOOP=`losetup -f` && losetup $LOOP "$LOOPFILE"; then
+		# no -s support
+		return 0
+	else
+		# no -f support 
+		# Iterate through $G_dev_/loop{,/}{0,1,2,3,4,5,6,7,8,9}
+		for slash in '' /; do
+			for i in 0 1 2 3 4 5 6 7 8 9; do
+				local dev=$G_dev_/loop$slash$i
+				! losetup $dev >/dev/null 2>&1 || continue
+				# got a free
+				losetup "$dev" "$LOOPFILE"
+				LOOP=$dev
+			done
+		done
+		test -n "$LOOP" # confirm or fail
+		return 0
+	fi
+	exit 1 # should not happen
+}
+
+prepare_devs() {
+	local n="$1"
+	test -z "$n" && n=3
+	local devsize="$2"
+	test -z "$devsize" && devsize=33
+
+	prepare_loop $(($n*$devsize))
+
+	PREFIX="LVMTEST$$"
+
+	local loopsz=`blockdev --getsz $LOOP`
+	local size=$(($loopsz/$n))
+
+	for i in `seq 1 $n`; do
+		local name="${PREFIX}pv$i"
+		local dev="$G_dev_/mapper/$name"
+		eval "dev$i=$dev"
+		devs="$devs $dev"
+		echo 0 $size linear $LOOP $((($i-1)*$size)) > $name.table
+		dmsetup create $name $name.table
+		dmsetup resume $name
+	done
+
+    # set up some default names
+	vg=${PREFIX}vg
+	vg1=${PREFIX}vg1
+	vg2=${PREFIX}vg2
+	lv=LV
+	lv1=LV1
+	lv2=LV2
+	lv3=LV3
+}
+
+disable_dev() {
+	for dev in "$@"; do
+        # first we make the device inaccessible
+		echo 0 10000000 error | dmsetup load $dev
+		dmsetup resume $dev
+        # now let's try to get rid of it if it's unused
+        #dmsetup remove $dev
+	done
+}
+
+enable_dev() {
+	for dev in "$@"; do
+		local name=`echo "$dev" | sed -e 's,.*/,,'`
+		dmsetup create $name $name.table || dmsetup load $name $name.table
+		dmsetup resume $dev
+	done
+}
+
+prepare_pvs() {
+	prepare_devs "$@"
+	pvcreate $devs
+}
+
+prepare_vg() {
+	prepare_pvs "$@"
+	vgcreate $vg $devs
+}
+
+prepare_lvmconf() {
+	cat > $G_root_/etc/lvm.conf <<-EOF
+  devices {
+    dir = "$G_dev_"
+    scan = "$G_dev_"
+    filter = [ "a/dev\/mirror/", "a/dev\/mapper/", "r/.*/" ]
+    cache_dir = "$G_root_/etc"
+    sysfs_scan = 0
+  }
+  log {
+    verbose = $verboselevel
+    syslog = 0
+    indent = 1
+  }
+  backup {
+    backup = 0
+    archive = 0
+  }
+  global {
+    library_dir = "$G_root_/lib"
+     locking_dir = "$G_root_/var/lock/lvm"
+  }
+EOF
+}
+
+set -vexE
+aux prepare_lvmconf
+
Index: src/external/gpl2/lvm2tools/dist/tools/.exported_symbols
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/.exported_symbols
diff -N src/external/gpl2/lvm2tools/dist/tools/.exported_symbols
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/.exported_symbols	15 Jul 2008 13:50:14 -0000	1.1.1.1
@@ -0,0 +1,5 @@
+lvm2_init
+lvm2_run
+lvm2_log_level
+lvm2_log_fn
+lvm2_exit
Index: src/external/gpl2/lvm2tools/dist/tools/Makefile.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/Makefile.in
diff -N src/external/gpl2/lvm2tools/dist/tools/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/Makefile.in	12 Dec 2008 16:33:04 -0000	1.1.1.1.2.1
@@ -0,0 +1,195 @@
+#
+# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+# Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+SOURCES =\
+	dumpconfig.c \
+	formats.c \
+	lvchange.c \
+	lvconvert.c \
+	lvcreate.c \
+	lvdisplay.c \
+	lvextend.c \
+	lvmchange.c \
+	lvmcmdline.c \
+	lvmdiskscan.c \
+	lvreduce.c \
+	lvremove.c \
+	lvrename.c \
+	lvresize.c \
+	lvscan.c \
+	polldaemon.c \
+	pvchange.c \
+	pvck.c \
+	pvcreate.c \
+	pvdisplay.c \
+	pvmove.c \
+	pvremove.c \
+	pvresize.c \
+	pvscan.c \
+	reporter.c \
+	segtypes.c \
+	toollib.c \
+	vgcfgbackup.c \
+	vgcfgrestore.c \
+	vgchange.c \
+	vgck.c \
+	vgcreate.c \
+	vgconvert.c \
+	vgdisplay.c \
+	vgexport.c \
+	vgextend.c \
+	vgimport.c \
+	vgmerge.c \
+	vgmknodes.c \
+	vgreduce.c \
+	vgremove.c \
+	vgrename.c \
+	vgscan.c \
+	vgsplit.c
+
+TARGETS =\
+	.commands \
+	lvm
+
+INSTALL_LVM_TARGETS = install_tools_dynamic
+INSTALL_DMSETUP_TARGETS = install_dmsetup_dynamic
+INSTALL_CMDLIB_TARGETS = install_cmdlib_dynamic
+
+ifeq ("@STATIC_LINK@", "yes")
+  TARGETS += lvm.static
+  INSTALL_LVM_TARGETS += install_tools_static
+  INSTALL_DMSETUP_TARGETS += install_dmsetup_static
+  INSTALL_CMDLIB_TARGETS += install_cmdlib_static
+endif
+
+LVMLIBS = -llvm
+
+CLEAN_TARGETS = liblvm2cmd.so liblvm2cmd.a liblvm2cmd-static.a lvm lvm.o \
+		lvm2cmd.o lvm2cmd-static.o lvm2cmdlib.o lvm.static \
+		lvm.cflow lvm.xref lvm.tree lvm.rxref lvm.rtree \
+		lvmcmdlib.o lvm-static.o dmsetup.o
+
+ifeq ("@CMDLIB@", "yes")
+	TARGETS += liblvm2cmd.so
+	INSTALL_LVM_TARGETS += $(INSTALL_CMDLIB_TARGETS)
+endif
+
+ifeq ("@DMEVENTD@", "yes")
+	LVMLIBS += -ldevmapper-event -lpthread
+endif
+
+LVMLIBS += -ldevmapper
+
+DEFS += -DLVM_SHARED_PATH=\"$(exec_prefix)/sbin/lvm\"
+
+include $(top_srcdir)/make.tmpl
+
+device-mapper: dmsetup
+
+dmsetup: dmsetup.o $(top_srcdir)/libdm/libdevmapper.$(LIB_SUFFIX)
+	$(CC) -o $@ dmsetup.o $(CFLAGS) $(LDFLAGS) \
+	      -L$(top_srcdir)/libdm -L$(DESTDIR)/lib -ldevmapper $(LIBS)
+
+dmsetup.static: dmsetup.o $(interfacedir)/libdevmapper.a
+	$(CC) -o $@ dmsetup.o $(CFLAGS) $(LDFLAGS) -static \
+	      -L$(interfacedir) -L$(DESTDIR)/lib -ldevmapper $(LIBS) \
+	      $(LIB_PTHREAD)
+
+all: device-mapper
+
+lvm: $(OBJECTS) lvm.o $(top_srcdir)/lib/liblvm.a
+	$(CC) -o $@ $(CFLAGS) $(OBJECTS) lvm.o \
+		$(LDFLAGS) $(LVMLIBS) $(LIBS) -rdynamic
+
+LIB_PTHREAD = @LIB_PTHREAD@
+lvm.static: $(OBJECTS) lvm-static.o $(top_srcdir)/lib/liblvm.a
+	$(CC) -o $@ $(CFLAGS) $(OBJECTS) lvm-static.o -static \
+		-L$(interfacedir) $(LDFLAGS) $(LVMLIBS) $(LIBS) $(LIB_PTHREAD) -rdynamic
+
+liblvm2cmd.a: $(top_srcdir)/lib/liblvm.a $(OBJECTS) lvmcmdlib.o lvm2cmd.o
+	cat $(top_srcdir)/lib/liblvm.a > $@
+	$(AR) rs $@ $(OBJECTS) lvmcmdlib.o lvm2cmd.o
+
+liblvm2cmd-static.a: $(top_srcdir)/lib/liblvm.a $(OBJECTS) lvmcmdlib.o lvm2cmd-static.o
+	cat $(top_srcdir)/lib/liblvm.a > $@
+	$(AR) rs $@ $(OBJECTS) lvmcmdlib.o lvm2cmd-static.o
+
+liblvm2cmd.so: liblvm2cmd.a $(LDDEPS)
+
+.commands: commands.h cmdnames.h Makefile
+	$(CC) -E -P cmdnames.h 2> /dev/null | \
+		egrep -v '^ *(|#.*|dumpconfig|formats|help|pvdata|segtypes|version) *$$' > .commands
+
+.PHONY: install_cmdlib_dynamic install_cmdlib_static \
+	install_tools_dynamic install_tools_static
+
+ifneq ("@CFLOW_CMD@", "")
+CFLOW_FLAGS += --cpp="$(CC) -E"
+.PHONY: lvm.cflow
+-include $(top_srcdir)/lib/liblvm.cflow
+lvm.cflow: $(SOURCES)
+	@CFLOW_CMD@ -o$@ $(CFLOW_FLAGS) $(INCLUDES) $(DEFS) $(SOURCES)
+lvm.rxref: $(SOURCES)
+	@CFLOW_CMD@ -o$@ --cpp="$(CC) -E" -r --omit-arguments -x $(INCLUDES) $(DEFS) $(SOURCES)
+lvm.xref: $(SOURCES)
+	@CFLOW_CMD@ -o$@ --cpp="$(CC) -E" --omit-arguments -x $(INCLUDES) $(DEFS) $(SOURCES)
+lvm.rtree: $(SOURCES)
+	@CFLOW_CMD@ -o$@ --cpp="$(CC) -E" -r --omit-arguments -T -b $(INCLUDES) $(DEFS) $(SOURCES)
+lvm.tree: $(SOURCES)
+	@CFLOW_CMD@ -o$@ --cpp="$(CC) -E" --omit-arguments -T -b $(INCLUDES) $(DEFS) $(SOURCES)
+cflow: lvm.cflow lvm.xref lvm.tree lvm.rtree lvm.rxref
+endif
+
+install_cmdlib_dynamic: liblvm2cmd.so
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) liblvm2cmd.so \
+		$(libdir)/liblvm2cmd.so.$(LIB_VERSION)
+	$(LN_S) -f liblvm2cmd.so.$(LIB_VERSION) $(libdir)/liblvm2cmd.so
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 444 lvm2cmd.h \
+		$(includedir)/lvm2cmd.h
+
+install_cmdlib_static: liblvm2cmd-static.a
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) liblvm2cmd-static.a \
+		$(libdir)/liblvm2cmd.a.$(LIB_VERSION)
+	$(LN_S) -f liblvm2cmd.a.$(LIB_VERSION) $(libdir)/liblvm2cmd.a
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 444 lvm2cmd.h \
+		$(includedir)/lvm2cmd.h
+
+install_tools_dynamic: lvm .commands
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) lvm \
+		$(sbindir)/lvm
+	@echo Creating symbolic links for individual commands in $(sbindir)
+	@( \
+		for v in `cat .commands`; do \
+			cd $(sbindir); \
+			$(LN_S) -f lvm $$v; \
+		done; \
+	)
+
+install_tools_static: lvm.static
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) lvm.static \
+		$(staticdir)/lvm.static
+
+install_dmsetup_dynamic: dmsetup
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< $(sbindir)/$<
+
+install_dmsetup_static: dmsetup.static
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< $(sbindir)/$<
+
+install_device-mapper: $(INSTALL_DMSETUP_TARGETS)
+
+install: $(INSTALL_LVM_TARGETS) install_device-mapper
Index: src/external/gpl2/lvm2tools/dist/tools/args.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/args.h
diff -N src/external/gpl2/lvm2tools/dist/tools/args.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/args.h	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,136 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Put all long args that don't have a
+ * corresponding short option first ...
+ */
+/* *INDENT-OFF* */
+arg(version_ARG, '\0', "version", NULL, 0)
+arg(quiet_ARG, '\0', "quiet", NULL, 0)
+arg(physicalvolumesize_ARG, '\0', "setphysicalvolumesize", size_mb_arg, 0)
+arg(ignorelockingfailure_ARG, '\0', "ignorelockingfailure", NULL, 0)
+arg(nolocking_ARG, '\0', "nolocking", NULL, 0)
+arg(metadatacopies_ARG, '\0', "metadatacopies", int_arg, 0)
+arg(metadatasize_ARG, '\0', "metadatasize", size_mb_arg, 0)
+arg(restorefile_ARG, '\0', "restorefile", string_arg, 0)
+arg(labelsector_ARG, '\0', "labelsector", int_arg, 0)
+arg(driverloaded_ARG, '\0', "driverloaded", yes_no_arg, 0)
+arg(aligned_ARG, '\0', "aligned", NULL, 0)
+arg(unbuffered_ARG, '\0', "unbuffered", NULL, 0)
+arg(noheadings_ARG, '\0', "noheadings", NULL, 0)
+arg(segments_ARG, '\0', "segments", NULL, 0)
+arg(units_ARG, '\0', "units", string_arg, 0)
+arg(nosuffix_ARG, '\0', "nosuffix", NULL, 0)
+arg(removemissing_ARG, '\0', "removemissing", NULL, 0)
+arg(abort_ARG, '\0', "abort", NULL, 0)
+arg(addtag_ARG, '\0', "addtag", tag_arg, 0)
+arg(deltag_ARG, '\0', "deltag", tag_arg, 0)
+arg(refresh_ARG, '\0', "refresh", NULL, 0)
+arg(mknodes_ARG, '\0', "mknodes", NULL, 0)
+arg(minor_ARG, '\0', "minor", minor_arg, 0)
+arg(type_ARG, '\0', "type", segtype_arg, 0)
+arg(alloc_ARG, '\0', "alloc", alloc_arg, 0)
+arg(separator_ARG, '\0', "separator", string_arg, 0)
+arg(mirrorsonly_ARG, '\0', "mirrorsonly", NULL, 0)
+arg(nosync_ARG, '\0', "nosync", NULL, 0)
+arg(resync_ARG, '\0', "resync", NULL, 0)
+arg(corelog_ARG, '\0', "corelog", NULL, 0)
+arg(mirrorlog_ARG, '\0', "mirrorlog", string_arg, 0)
+arg(monitor_ARG, '\0', "monitor", yes_no_arg, 0)
+arg(config_ARG, '\0', "config", string_arg, 0)
+arg(trustcache_ARG, '\0', "trustcache", NULL, 0)
+arg(ignoremonitoring_ARG, '\0', "ignoremonitoring", NULL, 0)
+arg(nameprefixes_ARG, '\0', "nameprefixes", NULL, 0)
+arg(unquoted_ARG, '\0', "unquoted", NULL, 0)
+arg(rows_ARG, '\0', "rows", NULL, 0)
+
+/* Allow some variations */
+arg(resizable_ARG, '\0', "resizable", yes_no_arg, 0)
+arg(allocation_ARG, '\0', "allocation", yes_no_arg, 0)
+
+/*
+ * ... and now the short args.
+ */
+arg(available_ARG, 'a', "available", yes_no_excl_arg, 0)
+arg(all_ARG, 'a', "all", NULL, 0)
+arg(autobackup_ARG, 'A', "autobackup", yes_no_arg, 0)
+arg(activevolumegroups_ARG, 'A', "activevolumegroups", NULL, 0)
+arg(background_ARG, 'b', "background", NULL, 0)
+arg(blockdevice_ARG, 'b', "blockdevice", NULL, 0)
+arg(chunksize_ARG, 'c', "chunksize", size_kb_arg, 0)
+arg(clustered_ARG, 'c', "clustered", yes_no_arg, 0)
+arg(colon_ARG, 'c', "colon", NULL, 0)
+arg(columns_ARG, 'C', "columns", NULL, 0)
+arg(contiguous_ARG, 'C', "contiguous", yes_no_arg, 0)
+arg(debug_ARG, 'd', "debug", NULL, ARG_REPEATABLE)
+arg(disk_ARG, 'D', "disk", NULL, 0)
+arg(exported_ARG, 'e', "exported", NULL, 0)
+arg(physicalextent_ARG, 'E', "physicalextent", NULL, 0)
+arg(file_ARG, 'f', "file", string_arg, 0)
+arg(force_ARG, 'f', "force", NULL, ARG_REPEATABLE)
+arg(full_ARG, 'f', "full", NULL, 0)
+arg(help_ARG, 'h', "help", NULL, 0)
+arg(help2_ARG, '?', "", NULL, 0)
+arg(stripesize_ARG, 'I', "stripesize", size_kb_arg, 0)
+arg(stripes_ARG, 'i', "stripes", int_arg, 0)
+arg(interval_ARG, 'i', "interval", int_arg, 0)
+arg(iop_version_ARG, 'i', "iop_version", NULL, 0)
+arg(logicalvolume_ARG, 'l', "logicalvolume", int_arg, 0)
+arg(maxlogicalvolumes_ARG, 'l', "maxlogicalvolumes", int_arg, 0)
+arg(extents_ARG, 'l', "extents", int_arg_with_sign_and_percent, 0)
+arg(lvmpartition_ARG, 'l', "lvmpartition", NULL, 0)
+arg(list_ARG, 'l', "list", NULL, 0)
+arg(size_ARG, 'L', "size", size_mb_arg, 0)
+arg(logicalextent_ARG, 'L', "logicalextent", int_arg_with_sign, 0)
+arg(persistent_ARG, 'M', "persistent", yes_no_arg, 0)
+arg(major_ARG, 'j', "major", major_arg, 0)
+arg(mirrors_ARG, 'm', "mirrors", int_arg_with_sign, 0)
+arg(metadatatype_ARG, 'M', "metadatatype", metadatatype_arg, 0)
+arg(maps_ARG, 'm', "maps", NULL, 0)
+arg(name_ARG, 'n', "name", string_arg, 0)
+arg(oldpath_ARG, 'n', "oldpath", NULL, 0)
+arg(nofsck_ARG, 'n', "nofsck", NULL, 0)
+arg(novolumegroup_ARG, 'n', "novolumegroup", NULL, 0)
+arg(options_ARG, 'o', "options", string_arg, 0)
+arg(sort_ARG, 'O', "sort", string_arg, 0)
+arg(permission_ARG, 'p', "permission", permission_arg, 0)
+arg(maxphysicalvolumes_ARG, 'p', "maxphysicalvolumes", int_arg, 0)
+arg(partial_ARG, 'P', "partial", NULL, 0)
+arg(physicalvolume_ARG, 'P', "physicalvolume", NULL, 0)
+arg(readahead_ARG, 'r', "readahead", readahead_arg, 0)
+arg(resizefs_ARG, 'r', "resizefs", NULL, 0)
+arg(reset_ARG, 'R', "reset", NULL, 0)
+arg(regionsize_ARG, 'R', "regionsize", size_mb_arg, 0)
+arg(physicalextentsize_ARG, 's', "physicalextentsize", size_mb_arg, 0)
+arg(stdin_ARG, 's', "stdin", NULL, 0)
+arg(snapshot_ARG, 's', "snapshot", NULL, 0)
+arg(short_ARG, 's', "short", NULL, 0)
+arg(test_ARG, 't', "test", NULL, 0)
+arg(uuid_ARG, 'u', "uuid", NULL, 0)
+arg(uuidstr_ARG, 'u', "uuid", string_arg, 0)
+arg(uuidlist_ARG, 'U', "uuidlist", NULL, 0)
+arg(verbose_ARG, 'v', "verbose", NULL, ARG_REPEATABLE)
+arg(volumegroup_ARG, 'V', "volumegroup", NULL, 0)
+arg(allocatable_ARG, 'x', "allocatable", yes_no_arg, 0)
+arg(resizeable_ARG, 'x', "resizeable", yes_no_arg, 0)
+arg(yes_ARG, 'y', "yes", NULL, 0)
+arg(zero_ARG, 'Z', "zero", yes_no_arg, 0)
+
+/* this should always be last */
+arg(ARG_COUNT, '-', "", NULL, 0)
+/* *INDENT-ON* */
Index: src/external/gpl2/lvm2tools/dist/tools/cmdnames.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/cmdnames.h
diff -N src/external/gpl2/lvm2tools/dist/tools/cmdnames.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/cmdnames.h	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,20 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define xx(a, b, c...) a
+
+#include "commands.h"
Index: src/external/gpl2/lvm2tools/dist/tools/commands.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/commands.h
diff -N src/external/gpl2/lvm2tools/dist/tools/commands.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/commands.h	13 Dec 2008 14:39:37 -0000	1.1.1.1.2.2
@@ -0,0 +1,965 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/***********  Replace with script?
+xx(e2fsadm,
+   "Resize logical volume and ext2 filesystem",
+   "e2fsadm "
+   "[-d|--debug] " "[-h|--help] " "[-n|--nofsck]" "\n"
+   "\t{[-l|--extents] [+|-]LogicalExtentsNumber |" "\n"
+   "\t [-L|--size] [+|-]LogicalVolumeSize[kKmMgGtTpPeE]}" "\n"
+   "\t[-t|--test] "  "\n"
+   "\t[-v|--verbose] "  "\n"
+   "\t[--version] " "\n"
+   "\tLogicalVolumePath" "\n",
+
+    extents_ARG, size_ARG, nofsck_ARG, test_ARG)
+*********/
+
+xx(dumpconfig,
+   "Dump active configuration",
+   0,
+   "dumpconfig "
+   "\t[-f|--file filename] " "\n"
+   "[ConfigurationVariable...]\n",
+   file_ARG)
+
+xx(formats,
+   "List available metadata formats",
+   0,
+   "formats\n")
+
+xx(help,
+   "Display help for commands",
+   0,
+   "help <command>" "\n")
+
+/*********
+xx(lvactivate,
+   "Activate logical volume on given partition(s)",
+   "lvactivate "
+   "\t[-d|--debug]\n"
+   "\t[-h|--help]\n"
+   "\t[-v|--verbose]\n"
+   "Logical Volume(s)\n")
+***********/
+
+xx(lvchange,
+   "Change the attributes of logical volume(s)",
+   CACHE_VGMETADATA,
+   "lvchange\n"
+   "\t[-A|--autobackup y|n]\n"
+   "\t[-a|--available [e|l]y|n]\n"
+   "\t[--addtag Tag]\n"
+   "\t[--alloc AllocationPolicy]\n"
+   "\t[-C|--contiguous y|n]\n"
+   "\t[-d|--debug]\n"
+   "\t[--deltag Tag]\n"
+   "\t[-f|--force]\n"
+   "\t[-h|--help]\n"
+   "\t[--ignorelockingfailure]\n"
+   "\t[--ignoremonitoring]\n"
+   "\t[--monitor {y|n}]\n"
+   "\t[-M|--persistent y|n] [--major major] [--minor minor]\n"
+   "\t[-P|--partial] " "\n"
+   "\t[-p|--permission r|rw]\n"
+   "\t[-r|--readahead ReadAheadSectors|auto|none]\n"
+   "\t[--refresh]\n"
+   "\t[--resync]\n"
+   "\t[-t|--test]\n"
+   "\t[-v|--verbose]\n"
+   "\t[-y|--yes]\n"
+   "\t[--version]" "\n"
+   "\tLogicalVolume[Path] [LogicalVolume[Path]...]\n",
+
+   alloc_ARG, autobackup_ARG, available_ARG, contiguous_ARG, force_ARG,
+   ignorelockingfailure_ARG, ignoremonitoring_ARG, major_ARG, minor_ARG,
+   monitor_ARG, partial_ARG, permission_ARG, persistent_ARG, readahead_ARG,
+   resync_ARG, refresh_ARG, addtag_ARG, deltag_ARG, test_ARG, yes_ARG)
+
+xx(lvconvert,
+   "Change logical volume layout",
+   0,
+   "lvconvert "
+   "[-m|--mirrors Mirrors [{--mirrorlog {disk|core}|--corelog}]]\n"
+   "\t[-R|--regionsize MirrorLogRegionSize]\n"
+   "\t[--alloc AllocationPolicy]\n"
+   "\t[-b|--background]\n"
+   "\t[-d|--debug]\n"
+   "\t[-h|-?|--help]\n"
+   "\t[-i|--interval seconds]\n"
+   "\t[-v|--verbose]\n"
+   "\t[--version]" "\n"
+   "\tLogicalVolume[Path] [PhysicalVolume[Path]...]\n\n"
+
+   "lvconvert "
+   "[-s|--snapshot]\n"
+   "\t[-c|--chunksize]\n"
+   "\t[-d|--debug]\n"
+   "\t[-h|-?|--help]\n"
+   "\t[-v|--verbose]\n"
+   "\t[-Z|--zero {y|n}]\n"
+   "\t[--version]" "\n"
+   "\tOriginalLogicalVolume[Path] SnapshotLogicalVolume[Path]\n",
+
+   alloc_ARG, background_ARG, chunksize_ARG, corelog_ARG, interval_ARG,
+   mirrorlog_ARG, mirrors_ARG, regionsize_ARG, snapshot_ARG, test_ARG, zero_ARG)
+
+xx(lvcreate,
+   "Create a logical volume",
+   0,
+   "lvcreate " "\n"
+   "\t[-A|--autobackup {y|n}]\n"
+   "\t[--addtag Tag]\n"
+   "\t[--alloc AllocationPolicy]\n"
+   "\t[-C|--contiguous {y|n}]\n"
+   "\t[-d|--debug]\n"
+   "\t[-h|-?|--help]\n"
+   "\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
+   "\t{-l|--extents LogicalExtentsNumber |\n"
+   "\t -L|--size LogicalVolumeSize[kKmMgGtTpPeE]}\n"
+   "\t[-M|--persistent {y|n}] [--major major] [--minor minor]\n"
+   "\t[-m|--mirrors Mirrors [--nosync] [{--mirrorlog {disk|core}|--corelog}]]\n"
+   "\t[-n|--name LogicalVolumeName]\n"
+   "\t[-p|--permission {r|rw}]\n"
+   "\t[-r|--readahead ReadAheadSectors|auto|none]\n"
+   "\t[-R|--regionsize MirrorLogRegionSize]\n"
+   "\t[-t|--test]\n"
+   "\t[--type VolumeType]\n"
+   "\t[-v|--verbose]\n"
+   "\t[-Z|--zero {y|n}]\n"
+   "\t[--version]\n"
+   "\tVolumeGroupName [PhysicalVolumePath...]\n\n"
+
+   "lvcreate -s|--snapshot\n"
+   "\t[-c|--chunksize]\n"
+   "\t[-A|--autobackup {y|n}]\n"
+   "\t[--addtag Tag]\n"
+   "\t[--alloc AllocationPolicy]\n"
+   "\t[-C|--contiguous {y|n}]\n"
+   "\t[-d|--debug]\n"
+   "\t[-h|-?|--help]\n"
+   "\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
+   "\t{-l|--extents LogicalExtentsNumber[%{VG|LV|PVS|FREE}] |\n"
+   "\t -L|--size LogicalVolumeSize[kKmMgGtTpPeE]}\n"
+   "\t[-M|--persistent {y|n}] [--major major] [--minor minor]\n"
+   "\t[-n|--name LogicalVolumeName]\n"
+   "\t[-p|--permission {r|rw}]\n"
+   "\t[-r|--readahead ReadAheadSectors|auto|none]\n"
+   "\t[-t|--test]\n"
+   "\t[-v|--verbose]\n"
+   "\t[--version]\n"
+   "\tOriginalLogicalVolume[Path] [PhysicalVolumePath...]\n\n",
+
+   addtag_ARG, alloc_ARG, autobackup_ARG, chunksize_ARG, contiguous_ARG,
+   corelog_ARG, extents_ARG, major_ARG, minor_ARG, mirrorlog_ARG, mirrors_ARG,
+   name_ARG, nosync_ARG, permission_ARG, persistent_ARG, readahead_ARG,
+   regionsize_ARG, size_ARG, snapshot_ARG, stripes_ARG, stripesize_ARG,
+   test_ARG, type_ARG, zero_ARG)
+
+xx(lvdisplay,
+   "Display information about a logical volume",
+   0,
+   "lvdisplay\n"
+   "\t[-a|--all]\n"
+   "\t[-c|--colon]\n"
+   "\t[-d|--debug]\n"
+   "\t[-h|--help]\n"
+   "\t[--ignorelockingfailure]\n"
+   "\t[-m|--maps]\n"
+   "\t[--nosuffix]\n"
+   "\t[-P|--partial] " "\n"
+   "\t[--units hsbkmgtHKMGT]\n"
+   "\t[-v|--verbose]\n"
+   "\t[--version]" "\n"
+   "\t[LogicalVolume[Path] [LogicalVolume[Path]...]]\n"
+   "\n"
+   "lvdisplay --columns|-C\n"
+   "\t[--aligned]\n"
+   "\t[-a|--all]\n"
+   "\t[-d|--debug]\n"
+   "\t[-h|--help]\n"
+   "\t[--ignorelockingfailure]\n"
+   "\t[--noheadings]\n"
+   "\t[--nosuffix]\n"
+   "\t[-o|--options [+]Field[,Field]]\n"
+   "\t[-O|--sort [+|-]key1[,[+|-]key2[,...]]]\n"
+   "\t[-P|--partial] " "\n"
+   "\t[--segments]\n"
+   "\t[--separator Separator]\n"
+   "\t[--unbuffered]\n"
+   "\t[--units hsbkmgtHKMGT]\n"
+   "\t[-v|--verbose]\n"
+   "\t[--version]" "\n"
+   "\t[LogicalVolume[Path] [LogicalVolume[Path]...]]\n",
+
+    aligned_ARG, all_ARG, colon_ARG, columns_ARG, disk_ARG,
+    ignorelockingfailure_ARG, maps_ARG, noheadings_ARG, nosuffix_ARG,
+    options_ARG, sort_ARG, partial_ARG, segments_ARG, separator_ARG,
+    unbuffered_ARG, units_ARG)
+
+xx(lvextend,
+   "Add space to a logical volume",
+   0,
+   "lvextend\n"
+   "\t[-A|--autobackup y|n]\n"
+   "\t[--alloc AllocationPolicy]\n"
+   "\t[-d|--debug]\n"
+   "\t[-f|--force]\n"
+   "\t[-h|--help]\n"
+   "\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
+   "\t{-l|--extents [+]LogicalExtentsNumber[%{VG|PVS|FREE}] |\n"
+   "\t -L|--size [+]LogicalVolumeSize[kKmMgGtTpPeE]}\n"
+   "\t[-m|--mirrors Mirrors]\n"
+   "\t[-n|--nofsck]\n"
+   "\t[-r|--resizefs]\n"
+   "\t[-t|--test]\n"
+   "\t[--type VolumeType]\n"
+   "\t[-v|--verbose]\n"
+   "\t[--version]" "\n"
+   "\tLogicalVolume[Path] [ PhysicalVolumePath... ]\n",
+
+   alloc_ARG, autobackup_ARG, extents_ARG, force_ARG, mirrors_ARG,
+   nofsck_ARG, resizefs_ARG, size_ARG, stripes_ARG, stripesize_ARG,
+   test_ARG, type_ARG)
+
+xx(lvmchange,
+   "With the device mapper, this is obsolete and does nothing.",
+   0,
+   "lvmchange\n"
+   "\t[-d|--debug]\n"
+   "\t[-h|--help]\n"
+   "\t[-R|--reset]\n"
+   "\t[-v|--verbose]\n"
+   "\t[--version]" "\n",
+
+    reset_ARG)
+
+xx(lvmdiskscan,
+   "List devices that may be used as physical volumes",
+   0,
+   "lvmdiskscan\n"
+   "\t[-d|--debug]\n"
+   "\t[-h|--help]\n"
+   "\t[-l|--lvmpartition]\n"
+   "\t[--version]" "\n",
+
+   lvmpartition_ARG)
+
+xx(lvmsadc,
+   "Collect activity data",
+   0,
+   "lvmsadc\n"
+   "\t[-d|--debug]\n"
+   "\t[-h|--help]\n"
+   "\t[-v|--verbose]\n"
+   "\t[--version]" "\n"
+   "\t[LogFilePath]\n" )
+
+xx(lvmsar,
+   "Create activity report",
+   0,
+   "lvmsar\n"
+   "\t[-d|--debug]\n"
+   "\t[-f|--full]\n"
+   "\t[-h|--help]\n"
+   "\t[-s|--stdin]\n"
+   "\t[-v|--verbose]\n"
+   "\t[--version]" "\n"
+   "\tLogFilePath\n",
+
+   full_ARG, stdin_ARG)
+
+xx(lvreduce,
+   "Reduce the size of a logical volume",
+   0,
+   "lvreduce\n"
+   "\t[-A|--autobackup y|n]\n"
+   "\t[-d|--debug]\n"
+   "\t[-f|--force]\n"
+   "\t[-h|--help]\n"
+   "\t{-l|--extents [-]LogicalExtentsNumber[%{VG|LV|FREE}] |\n"
+   "\t -L|--size [-]LogicalVolumeSize[kKmMgGtTpPeE]}\n"
+   "\t[-n|--nofsck]\n"
+   "\t[-r|--resizefs]\n"
+   "\t[-t|--test]\n"
+   "\t[-v|--verbose]\n"
+   "\t[-y|--yes]\n"
+   "\t[--version]" "\n"
+   "\tLogicalVolume[Path]\n",
+
+   autobackup_ARG, force_ARG,  extents_ARG, nofsck_ARG, resizefs_ARG,
+   size_ARG, test_ARG, yes_ARG)
+
+xx(lvremove,
+   "Remove logical volume(s) from the system",
+   0,
+   "lvremove\n"
+   "\t[-A|--autobackup y|n]\n"
+   "\t[-d|--debug]\n"
+   "\t[-f|--force]\n"
+   "\t[-h|--help]\n"
+   "\t[-t|--test]\n"
+   "\t[-v|--verbose]\n"
+   "\t[--version]" "\n"
+   "\tLogicalVolume[Path] [LogicalVolume[Path]...]\n",
+
+   autobackup_ARG, force_ARG, test_ARG)
+
+xx(lvrename,
+   "Rename a logical volume",
+   0,
+   "lvrename "
+   "\t[-A|--autobackup {y|n}] " "\n"
+   "\t[-d|--debug] " "\n"
+   "\t[-h|-?|--help] " "\n"
+   "\t[-t|--test] " "\n"
+   "\t[-v|--verbose]" "\n"
+   "\t[--version] " "\n"
+   "\t{ OldLogicalVolumePath NewLogicalVolumePath |" "\n"
+   "\t  VolumeGroupName OldLogicalVolumeName NewLogicalVolumeName }\n",
+
+   autobackup_ARG, test_ARG)
+
+xx(lvresize,
+   "Resize a logical volume",
+   0,
+   "lvresize\n"
+   "\t[-A|--autobackup y|n]\n"
+   "\t[--alloc AllocationPolicy]\n"
+   "\t[-d|--debug]\n"
+   "\t[-f|--force]\n"
+   "\t[-h|--help]\n"
+   "\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
+   "\t{-l|--extents [+|-]LogicalExtentsNumber[%{VG|LV|PVS|FREE}] |\n"
+   "\t -L|--size [+|-]LogicalVolumeSize[kKmMgGtTpPeE]}\n"
+   "\t[-n|--nofsck]\n"
+   "\t[-r|--resizefs]\n"
+   "\t[-t|--test]\n"
+   "\t[--type VolumeType]\n"
+   "\t[-v|--verbose]\n"
+   "\t[--version]" "\n"
+   "\tLogicalVolume[Path] [ PhysicalVolumePath... ]\n",
+
+   alloc_ARG, autobackup_ARG, extents_ARG, force_ARG, nofsck_ARG,
+   resizefs_ARG, size_ARG, stripes_ARG, stripesize_ARG, test_ARG,
+   type_ARG)
+
+xx(lvs,
+   "Display information about logical volumes",
+   0,
+   "lvs" "\n"
+   "\t[-a|--all]\n"
+   "\t[--aligned]\n"
+   "\t[-d|--debug]\n"
+   "\t[-h|--help]\n"
+   "\t[--ignorelockingfailure]\n"
+   "\t[--nameprefixes]\n"
+   "\t[--noheadings]\n"
+   "\t[--nosuffix]\n"
+   "\t[-o|--options [+]Field[,Field]]\n"
+   "\t[-O|--sort [+|-]key1[,[+|-]key2[,...]]]\n"
+   "\t[-P|--partial] " "\n"
+   "\t[--rows]\n"
+   "\t[--segments]\n"
+   "\t[--separator Separator]\n"
+   "\t[--trustcache]\n"
+   "\t[--unbuffered]\n"
+   "\t[--units hsbkmgtHKMGT]\n"
+   "\t[--unquoted]\n"
+   "\t[-v|--verbose]\n"
+   "\t[--version]" "\n"
+   "\t[LogicalVolume[Path] [LogicalVolume[Path]...]]\n",
+
+   aligned_ARG, all_ARG, ignorelockingfailure_ARG, nameprefixes_ARG,
+   noheadings_ARG, nolocking_ARG, nosuffix_ARG, options_ARG, partial_ARG, 
+   rows_ARG, segments_ARG, separator_ARG, sort_ARG, trustcache_ARG,
+   unbuffered_ARG, units_ARG, unquoted_ARG)
+
+xx(lvscan,
+   "List all logical volumes in all volume groups",
+   0,
+   "lvscan " "\n"
+   "\t[-a|--all]\n"
+   "\t[-b|--blockdevice] " "\n"
+   "\t[-d|--debug] " "\n"
+   "\t[-h|-?|--help] " "\n"
+   "\t[--ignorelockingfailure]\n"
+   "\t[-P|--partial] " "\n"
+   "\t[-v|--verbose] " "\n"
+   "\t[--version]\n",
+
+   all_ARG, blockdevice_ARG, disk_ARG, ignorelockingfailure_ARG, partial_ARG)
+
+xx(pvchange,
+   "Change attributes of physical volume(s)",
+   0,
+   "pvchange\n"
+   "\t[-a|--all]\n"
+   "\t[-A|--autobackup y|n]\n"
+   "\t[-d|--debug]\n"
+   "\t[-h|--help]\n"
+   "\t[-t|--test]\n"
+   "\t[-u|--uuid]\n"
+   "\t[-x|--allocatable y|n]\n"
+   "\t[-v|--verbose]\n"
+   "\t[--addtag Tag]\n"
+   "\t[--deltag Tag]\n"
+   "\t[--version]" "\n"
+   "\t[PhysicalVolumePath...]\n",
+
+   all_ARG, allocatable_ARG, allocation_ARG, autobackup_ARG, deltag_ARG,
+   addtag_ARG, test_ARG, uuid_ARG)
+
+xx(pvresize,
+   "Resize physical volume(s)",
+   0,
+   "pvresize " "\n"
+   "\t[-d|--debug]" "\n"
+   "\t[-h|-?|--help] " "\n"
+   "\t[--setphysicalvolumesize PhysicalVolumeSize[kKmMgGtTpPeE]" "\n"
+   "\t[-t|--test] " "\n"
+   "\t[-v|--verbose] " "\n"
+   "\t[--version] " "\n"
+   "\tPhysicalVolume [PhysicalVolume...]\n",
+
+   physicalvolumesize_ARG, test_ARG)
+
+xx(pvck,
+   "Check the consistency of physical volume(s)",
+   0,
+   "pvck "
+   "\t[-d|--debug]\n"
+   "\t[-h|--help]\n"
+   "\t[--labelsector sector] " "\n"
+   "\t[-v|--verbose]\n"
+   "\t[--version]" "\n"
+   "\tPhysicalVolume [PhysicalVolume...]\n",
+
+   labelsector_ARG)
+
+xx(pvcreate,
+   "Initialize physical volume(s) for use by LVM",
+   0,
+   "pvcreate " "\n"
+   "\t[--restorefile file]\n"
+   "\t[-d|--debug]" "\n"
+   "\t[-f[f]|--force [--force]] " "\n"
+   "\t[-h|-?|--help] " "\n"
+   "\t[--labelsector sector] " "\n"
+   "\t[-M|--metadatatype 1|2]" "\n"
+   "\t[--metadatacopies #copies]" "\n"
+   "\t[--metadatasize MetadataSize[kKmMgGtTpPeE]]" "\n"
+   "\t[--setphysicalvolumesize PhysicalVolumeSize[kKmMgGtTpPeE]" "\n"
+   "\t[-t|--test] " "\n"
+   "\t[-u|--uuid uuid] " "\n"
+   "\t[-v|--verbose] " "\n"
+   "\t[-y|--yes]" "\n"
+   "\t[-Z|--zero {y|n}]\n"
+   "\t[--version] " "\n"
+   "\tPhysicalVolume [PhysicalVolume...]\n",
+
+   force_ARG, test_ARG, labelsector_ARG, metadatatype_ARG, metadatacopies_ARG,
+   metadatasize_ARG, physicalvolumesize_ARG, restorefile_ARG, uuidstr_ARG,
+   yes_ARG, zero_ARG)
+
+xx(pvdata,
+   "Display the on-disk metadata for physical volume(s)",
+   0,
+   "pvdata " "\n"
+   "\t[-a|--all] " "\n"
+   "\t[-d|--debug] " "\n"
+   "\t[-E|--physicalextent] " "\n"
+   "\t[-h|-?|--help]" "\n"
+   "\t[-L|--logicalvolume] " "\n"
+   "\t[-P[P]|--physicalvolume [--physicalvolume]]" "\n"
+   "\t[-U|--uuidlist] " "\n"
+   "\t[-v[v]|--verbose [--verbose]] " "\n"
+   "\t[-V|--volumegroup]" "\n"
+   "\t[--version] " "\n"
+   "\tPhysicalVolume [PhysicalVolume...]\n",
+
+   all_ARG,  logicalextent_ARG, physicalextent_ARG,
+   physicalvolume_ARG, uuidlist_ARG, volumegroup_ARG)
+
+xx(pvdisplay,
+   "Display various attributes of physical volume(s)",
+   0,
+   "pvdisplay\n"
+   "\t[-c|--colon]\n"
+   "\t[-d|--debug]\n"
+   "\t[-h|--help]\n"
+   "\t[--ignorelockingfailure]\n"
+   "\t[-m|--maps]\n"
+   "\t[--nosuffix]\n"
+   "\t[-s|--short]\n"
+   "\t[--units hsbkmgtHKMGT]\n"
+   "\t[-v|--verbose]\n"
+   "\t[--version]" "\n"
+   "\t[PhysicalVolumePath [PhysicalVolumePath...]]\n"
+   "\n"
+   "pvdisplay --columns|-C\n"
+   "\t[--aligned]\n"
+   "\t[-a|--all]\n"
+   "\t[-d|--debug]\n"
+   "\t[-h|--help]\n"
+   "\t[--ignorelockingfailure]\n"
+   "\t[--noheadings]\n"
+   "\t[--nosuffix]\n"
+   "\t[-o|--options [+]Field[,Field]]\n"
+   "\t[-O|--sort [+|-]key1[,[+|-]key2[,...]]]\n"
+   "\t[--separator Separator]\n"
+   "\t[--unbuffered]\n"
+   "\t[--units hsbkmgtHKMGT]\n"
+   "\t[-v|--verbose]\n"
+   "\t[--version]" "\n"
+   "\t[PhysicalVolumePath [PhysicalVolumePath...]]\n",
+
+   aligned_ARG, all_ARG, colon_ARG, columns_ARG, ignorelockingfailure_ARG,
+   maps_ARG, noheadings_ARG, nosuffix_ARG, options_ARG, separator_ARG,
+   short_ARG, sort_ARG, unbuffered_ARG, units_ARG)
+
+xx(pvmove,
+   "Move extents from one physical volume to another",
+   0,
+   "pvmove " "\n"
+   "\t[--abort]\n"
+   "\t[-A|--autobackup {y|n}]\n"
+   "\t[--alloc AllocationPolicy]\n"
+   "\t[-b|--background]\n"
+   "\t[-d|--debug]\n "
+   "\t[-h|-?|--help]\n"
+   "\t[-i|--interval seconds]\n"
+   "\t[-t|--test]\n "
+   "\t[-v|--verbose]\n "
+   "\t[--version]\n"
+   "\t[{-n|--name} LogicalVolume]\n"
+/* "\t[{-n|--name} LogicalVolume[:LogicalExtent[-LogicalExtent]...]]\n" */
+   "\tSourcePhysicalVolume[:PhysicalExtent[-PhysicalExtent]...]}\n"
+   "\t[DestinationPhysicalVolume[:PhysicalExtent[-PhysicalExtent]...]...]\n",
+
+   abort_ARG, alloc_ARG, autobackup_ARG, background_ARG,
+   interval_ARG, name_ARG, test_ARG)
+
+xx(pvremove,
+   "Remove LVM label(s) from physical volume(s)",
+   0,
+   "pvremove " "\n"
+   "\t[-d|--debug]" "\n"
+   "\t[-f[f]|--force [--force]] " "\n"
+   "\t[-h|-?|--help] " "\n"
+   "\t[-t|--test] " "\n"
+   "\t[-v|--verbose] " "\n"
+   "\t[-y|--yes]" "\n"
+   "\t[--version] " "\n"
+   "\tPhysicalVolume [PhysicalVolume...]\n",
+
+   force_ARG, test_ARG, yes_ARG)
+
+xx(pvs,
+   "Display information about physical volumes",
+   0,
+   "pvs" "\n"
+   "\t[--aligned]\n"
+   "\t[-a|--all]\n"
+   "\t[-d|--debug]" "\n"
+   "\t[-h|-?|--help] " "\n"
+   "\t[--ignorelockingfailure]\n"
+   "\t[--nameprefixes]\n"
+   "\t[--noheadings]\n"
+   "\t[--nosuffix]\n"
+   "\t[-o|--options [+]Field[,Field]]\n"
+   "\t[-O|--sort [+|-]key1[,[+|-]key2[,...]]]\n"
+   "\t[-P|--partial] " "\n"
+   "\t[--rows]\n"
+   "\t[--segments]\n"
+   "\t[--separator Separator]\n"
+   "\t[--trustcache]\n"
+   "\t[--unbuffered]\n"
+   "\t[--units hsbkmgtHKMGT]\n"
+   "\t[--unquoted]\n"
+   "\t[-v|--verbose]\n"
+   "\t[--version]\n"
+   "\t[PhysicalVolume [PhysicalVolume...]]\n",
+
+   aligned_ARG, all_ARG, ignorelockingfailure_ARG, nameprefixes_ARG,
+   noheadings_ARG, nolocking_ARG, nosuffix_ARG, options_ARG, partial_ARG,
+   rows_ARG, segments_ARG, separator_ARG, sort_ARG, trustcache_ARG,
+   unbuffered_ARG, units_ARG, unquoted_ARG)
+
+xx(pvscan,
+   "List all physical volumes",
+   0,
+   "pvscan " "\n"
+   "\t[-d|--debug] " "\n"
+   "\t{-e|--exported | -n|--novolumegroup} " "\n"
+   "\t[-h|-?|--help]" "\n"
+   "\t[--ignorelockingfailure]\n"
+   "\t[-P|--partial] " "\n"
+   "\t[-s|--short] " "\n"
+   "\t[-u|--uuid] " "\n"
+   "\t[-v|--verbose] " "\n"
+   "\t[--version]\n",
+
+   exported_ARG, ignorelockingfailure_ARG, novolumegroup_ARG, partial_ARG,
+   short_ARG, uuid_ARG)
+
+xx(segtypes,
+   "List available segment types",
+   0,
+   "segtypes\n")
+
+xx(vgcfgbackup,
+   "Backup volume group configuration(s)",
+   0,
+   "vgcfgbackup " "\n"
+   "\t[-d|--debug] " "\n"
+   "\t[-f|--file filename] " "\n"
+   "\t[-h|-?|--help] " "\n"
+   "\t[--ignorelockingfailure]\n"
+   "\t[-P|--partial] " "\n"
+   "\t[-v|--verbose]" "\n"
+   "\t[--version] " "\n"
+   "\t[VolumeGroupName...]\n",
+
+   file_ARG, ignorelockingfailure_ARG, partial_ARG)
+
+xx(vgcfgrestore,
+   "Restore volume group configuration",
+   0,
+   "vgcfgrestore " "\n"
+   "\t[-d|--debug] " "\n"
+   "\t[-f|--file filename] " "\n"
+   "\t[-l[l]|--list [--list]]" "\n"
+   "\t[-M|--metadatatype 1|2]" "\n"
+   "\t[-n|--name VolumeGroupName] " "\n"
+   "\t[-h|--help]" "\n"
+   "\t[-t|--test] " "\n"
+   "\t[-v|--verbose]" "\n"
+   "\t[--version] " "\n"
+   "\tVolumeGroupName",
+
+   file_ARG, list_ARG, metadatatype_ARG, name_ARG, test_ARG)
+
+xx(vgchange,
+   "Change volume group attributes",
+   CACHE_VGMETADATA,
+   "vgchange" "\n"
+   "\t[-A|--autobackup {y|n}] " "\n"
+   "\t[--alloc AllocationPolicy] " "\n"
+   "\t[-P|--partial] " "\n"
+   "\t[-d|--debug] " "\n"
+   "\t[-h|--help] " "\n"
+   "\t[--ignorelockingfailure]\n"
+   "\t[--ignoremonitoring]\n"
+   "\t[--monitor {y|n}]\n"
+   "\t[-t|--test]" "\n"
+   "\t[-u|--uuid] " "\n"
+   "\t[-v|--verbose] " "\n"
+   "\t[--version]" "\n"
+   "\t{-a|--available [e|l]{y|n}  |" "\n"
+   "\t -c|--clustered {y|n} |" "\n"
+   "\t -x|--resizeable {y|n} |" "\n"
+   "\t -l|--logicalvolume MaxLogicalVolumes |" "\n"
+   "\t -p|--maxphysicalvolumes MaxPhysicalVolumes |" "\n"
+   "\t -s|--physicalextentsize PhysicalExtentSize[kKmMgGtTpPeE] |" "\n"
+   "\t --addtag Tag |\n"
+   "\t --deltag Tag}\n"
+   "\t[VolumeGroupName...]\n",
+
+   addtag_ARG, alloc_ARG, allocation_ARG, autobackup_ARG, available_ARG,
+   clustered_ARG, deltag_ARG, ignorelockingfailure_ARG, ignoremonitoring_ARG,
+   logicalvolume_ARG, maxphysicalvolumes_ARG, monitor_ARG, partial_ARG,
+   physicalextentsize_ARG, resizeable_ARG, resizable_ARG, test_ARG, uuid_ARG)
+
+xx(vgck,
+   "Check the consistency of volume group(s)",
+   0,
+   "vgck "
+   "\t[-d|--debug]\n"
+   "\t[-h|--help]\n"
+   "\t[-v|--verbose]\n"
+   "\t[--version]" "\n"
+   "\t[VolumeGroupName...]\n" )
+
+xx(vgconvert,
+   "Change volume group metadata format",
+   0,
+   "vgconvert  " "\n"
+   "\t[-d|--debug]" "\n"
+   "\t[-h|--help] " "\n"
+   "\t[--labelsector sector] " "\n"
+   "\t[-M|--metadatatype 1|2]" "\n"
+   "\t[--metadatacopies #copies]" "\n"
+   "\t[--metadatasize MetadataSize[kKmMgGtTpPeE]]" "\n"
+   "\t[-t|--test] " "\n"
+   "\t[-v|--verbose] " "\n"
+   "\t[--version] " "\n"
+   "\tVolumeGroupName [VolumeGroupName...]\n",
+
+   force_ARG, test_ARG, labelsector_ARG, metadatatype_ARG, metadatacopies_ARG,
+   metadatasize_ARG )
+
+xx(vgcreate,
+   "Create a volume group",
+   0,
+   "vgcreate" "\n"
+   "\t[-A|--autobackup {y|n}] " "\n"
+   "\t[--addtag Tag] " "\n"
+   "\t[--alloc AllocationPolicy] " "\n"
+   "\t[-c|--clustered {y|n}] " "\n"
+   "\t[-d|--debug]" "\n"
+   "\t[-h|--help]" "\n"
+   "\t[-l|--maxlogicalvolumes MaxLogicalVolumes]" "\n"
+   "\t[-M|--metadatatype 1|2] " "\n"
+   "\t[-p|--maxphysicalvolumes MaxPhysicalVolumes] " "\n"
+   "\t[-s|--physicalextentsize PhysicalExtentSize[kKmMgGtTpPeE]] " "\n"
+   "\t[-t|--test] " "\n"
+   "\t[-v|--verbose]" "\n"
+   "\t[--version] " "\n"
+   "\tVolumeGroupName PhysicalVolume [PhysicalVolume...]\n",
+
+   addtag_ARG, alloc_ARG, autobackup_ARG, clustered_ARG, maxlogicalvolumes_ARG,
+   maxphysicalvolumes_ARG, metadatatype_ARG, physicalextentsize_ARG, test_ARG)
+
+xx(vgdisplay,
+   "Display volume group information",
+   0,
+   "vgdisplay " "\n"
+   "\t[-c|--colon | -s|--short | -v|--verbose]" "\n"
+   "\t[-d|--debug] " "\n"
+   "\t[-h|--help] " "\n"
+   "\t[--ignorelockingfailure]" "\n"
+   "\t[--nosuffix]\n"
+   "\t[-P|--partial] " "\n"
+   "\t[--units hsbkmgtHKMGT]\n"
+   "\t[-A|--activevolumegroups | [-D|--disk]" "\n"
+   "\t[--version]" "\n"
+   "\t[VolumeGroupName [VolumeGroupName...]]\n"
+   "\n"
+   "vgdisplay --columns|-C\n"
+   "\t[--aligned]\n"
+   "\t[-d|--debug] " "\n"
+   "\t[-h|--help] " "\n"
+   "\t[--ignorelockingfailure]" "\n"
+   "\t[--noheadings]\n"
+   "\t[--nosuffix]\n"
+   "\t[-o|--options [+]Field[,Field]]\n"
+   "\t[-O|--sort [+|-]key1[,[+|-]key2[,...]]]\n"
+   "\t[-P|--partial] " "\n"
+   "\t[--separator Separator]\n"
+   "\t[--unbuffered]\n"
+   "\t[--units hsbkmgtHKMGT]\n"
+   "\t[--verbose]" "\n"
+   "\t[--version]" "\n"
+   "\t[VolumeGroupName [VolumeGroupName...]]\n",
+
+   activevolumegroups_ARG, aligned_ARG, colon_ARG, columns_ARG, disk_ARG,
+   ignorelockingfailure_ARG, noheadings_ARG, nosuffix_ARG, options_ARG,
+   partial_ARG, short_ARG, separator_ARG, sort_ARG, unbuffered_ARG, units_ARG)
+
+xx(vgexport,
+   "Unregister volume group(s) from the system",
+   0,
+   "vgexport " "\n"
+   "\t[-a|--all] " "\n"
+   "\t[-d|--debug] " "\n"
+   "\t[-h|--help]" "\n"
+   "\t[-v|--verbose] " "\n"
+   "\t[--version] " "\n"
+   "\tVolumeGroupName [VolumeGroupName...]\n",
+
+   all_ARG, test_ARG)
+
+xx(vgextend,
+   "Add physical volumes to a volume group",
+   0,
+   "vgextend\n"
+   "\t[-A|--autobackup y|n]\n"
+   "\t[-d|--debug]\n"
+   "\t[-h|--help]\n"
+   "\t[-t|--test]\n"
+   "\t[-v|--verbose]\n"
+   "\t[--version]" "\n"
+   "\tVolumeGroupName PhysicalDevicePath [PhysicalDevicePath...]\n",
+
+   autobackup_ARG, test_ARG)
+
+xx(vgimport,
+   "Register exported volume group with system",
+   0,
+   "vgimport " "\n"
+   "\t[-a|--all]\n"
+   "\t[-d|--debug] " "\n"
+   "\t[-f|--force] " "\n"
+   "\t[-h|--help] " "\n"
+   "\t[-t|--test] " "\n"
+   "\t[-v|--verbose]" "\n"
+   "\t[--version]" "\n"
+   "\tVolumeGroupName..." "\n",
+
+   all_ARG, force_ARG, test_ARG)
+
+xx(vgmerge,
+   "Merge volume groups",
+   0,
+   "vgmerge\n"
+   "\t[-A|--autobackup y|n]\n"
+   "\t[-d|--debug]\n"
+   "\t[-h|--help]\n"
+   "\t[-l|--list]\n"
+   "\t[-t|--test]\n"
+   "\t[-v|--verbose]\n"
+   "\t[--version]" "\n"
+   "\tDestinationVolumeGroupName SourceVolumeGroupName\n",
+
+   autobackup_ARG, list_ARG, test_ARG)
+
+xx(vgmknodes,
+   "Create the special files for volume group devices in /dev",
+   0,
+   "vgmknodes\n"
+   "\t[-d|--debug]\n"
+   "\t[-h|--help]\n"
+   "\t[--ignorelockingfailure]\n"
+   "\t[-v|--verbose]\n"
+   "\t[--version]" "\n"
+   "\t[VolumeGroupName...]\n",
+
+   ignorelockingfailure_ARG)
+
+xx(vgreduce,
+   "Remove physical volume(s) from a volume group",
+   0,
+   "vgreduce\n"
+   "\t[-a|--all]\n"
+   "\t[-A|--autobackup y|n]\n"
+   "\t[-d|--debug]\n"
+   "\t[-h|--help]\n"
+   "\t[--mirrorsonly]\n"
+   "\t[--removemissing]\n"
+   "\t[-f|--force]\n"
+   "\t[-t|--test]\n"
+   "\t[-v|--verbose]\n"
+   "\t[--version]" "\n"
+   "\tVolumeGroupName\n"
+   "\t[PhysicalVolumePath...]\n",
+
+   all_ARG, autobackup_ARG, force_ARG, mirrorsonly_ARG, removemissing_ARG,
+   test_ARG)
+
+xx(vgremove,
+   "Remove volume group(s)",
+   0,
+   "vgremove\n"
+   "\t[-d|--debug]\n"
+   "\t[-f|--force]\n"
+   "\t[-h|--help]\n"
+   "\t[-t|--test]\n"
+   "\t[-v|--verbose]\n"
+   "\t[--version]" "\n"
+   "\tVolumeGroupName [VolumeGroupName...]\n",
+
+   force_ARG, test_ARG)
+
+xx(vgrename,
+   "Rename a volume group",
+   0,
+   "vgrename\n"
+   "\t[-A|--autobackup y|n]\n"
+   "\t[-d|--debug]\n"
+   "\t[-h|--help]\n"
+   "\t[-t|--test]\n"
+   "\t[-v|--verbose]\n"
+   "\t[--version]" "\n"
+   "\tOldVolumeGroupPath NewVolumeGroupPath |\n"
+   "\tOldVolumeGroupName NewVolumeGroupName\n",
+
+   autobackup_ARG, force_ARG, test_ARG)
+
+xx(vgs,
+   "Display information about volume groups",
+   0,
+   "vgs" "\n"
+   "\t[--aligned]\n"
+   "\t[-a|--all]\n"
+   "\t[-d|--debug]\n"
+   "\t[-h|--help]\n"
+   "\t[--ignorelockingfailure]\n"
+   "\t[--nameprefixes]\n"
+   "\t[--noheadings]\n"
+   "\t[--nosuffix]\n"
+   "\t[-o|--options [+]Field[,Field]]\n"
+   "\t[-O|--sort [+|-]key1[,[+|-]key2[,...]]]\n"
+   "\t[-P|--partial] " "\n"
+   "\t[--rows]\n"
+   "\t[--separator Separator]\n"
+   "\t[--trustcache]\n"
+   "\t[--unbuffered]\n"
+   "\t[--units hsbkmgtHKMGT]\n"
+   "\t[--unquoted]\n"
+   "\t[-v|--verbose]\n"
+   "\t[--version]\n"
+   "\t[VolumeGroupName [VolumeGroupName...]]\n",
+
+   aligned_ARG, all_ARG, ignorelockingfailure_ARG, nameprefixes_ARG,
+   noheadings_ARG, nolocking_ARG, nosuffix_ARG, options_ARG, partial_ARG, 
+   rows_ARG, separator_ARG, sort_ARG, trustcache_ARG, unbuffered_ARG, units_ARG,
+   unquoted_ARG)
+
+xx(vgscan,
+   "Search for all volume groups",
+   0,
+   "vgscan "
+   "\t[-d|--debug]\n"
+   "\t[-h|--help]\n"
+   "\t[--ignorelockingfailure]\n"
+   "\t[--mknodes]\n"
+   "\t[-P|--partial] " "\n"
+   "\t[-v|--verbose]\n"
+   "\t[--version]" "\n",
+
+   ignorelockingfailure_ARG, mknodes_ARG, partial_ARG)
+
+xx(vgsplit,
+   "Move physical volumes into a new or existing volume group",
+   0,
+   "vgsplit " "\n"
+   "\t[-A|--autobackup {y|n}] " "\n"
+   "\t[--alloc AllocationPolicy] " "\n"
+   "\t[-c|--clustered {y|n}] " "\n"
+   "\t[-d|--debug] " "\n"
+   "\t[-h|--help] " "\n"
+   "\t[-l|--maxlogicalvolumes MaxLogicalVolumes]" "\n"
+   "\t[-M|--metadatatype 1|2] " "\n"
+   "\t[-n|--name LogicalVolumeName]\n"
+   "\t[-p|--maxphysicalvolumes MaxPhysicalVolumes] " "\n"
+   "\t[-t|--test] " "\n"
+   "\t[-v|--verbose] " "\n"
+   "\t[--version]" "\n"
+   "\tSourceVolumeGroupName DestinationVolumeGroupName" "\n"
+   "\t[PhysicalVolumePath...]\n",
+
+   alloc_ARG, autobackup_ARG, clustered_ARG,
+   maxlogicalvolumes_ARG, maxphysicalvolumes_ARG,
+   metadatatype_ARG, name_ARG, test_ARG)
+
+xx(version,
+   "Display software and driver version information",
+   0,
+   "version\n" )
+
Index: src/external/gpl2/lvm2tools/dist/tools/dmsetup.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/dmsetup.c
diff -N src/external/gpl2/lvm2tools/dist/tools/dmsetup.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/dmsetup.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.3
@@ -0,0 +1,2764 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2005-2007 NEC Corporation
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * It includes tree drawing code based on pstree: http://psmisc.sourceforge.net/
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define _GNU_SOURCE
+#define _FILE_OFFSET_BITS 64
+
+#include "configure.h"
+
+#include "dm-logging.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <unistd.h>
+#include <libgen.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <locale.h>
+#include <langinfo.h>
+
+#include <fcntl.h>
+#include <sys/stat.h>
+
+/* FIXME Unused so far */
+#undef HAVE_SYS_STATVFS_H
+
+#ifdef HAVE_SYS_STATVFS_H
+#  include <sys/statvfs.h>
+#endif
+
+#ifdef HAVE_SYS_IOCTL_H
+#  include <sys/ioctl.h>
+#endif
+
+#if HAVE_TERMIOS_H
+#  include <termios.h>
+#endif
+
+#ifdef HAVE_GETOPTLONG
+#  include <getopt.h>
+#  define GETOPTLONG_FN(a, b, c, d, e) getopt_long((a), (b), (c), (d), (e))
+#  define OPTIND_INIT 0
+#else
+struct option {
+};
+extern int optind;
+extern char *optarg;
+#  define GETOPTLONG_FN(a, b, c, d, e) getopt((a), (b), (c))
+#  define OPTIND_INIT 1
+#endif
+
+#ifndef TEMP_FAILURE_RETRY
+# define TEMP_FAILURE_RETRY(expression) \
+  (__extension__                                                              \
+    ({ long int __result;                                                     \
+       do __result = (long int) (expression);                                 \
+       while (__result == -1L && errno == EINTR);                             \
+       __result; }))
+#endif
+
+#ifdef linux
+#  include "kdev_t.h"
+#else
+#  define MAJOR(x) major((x))
+#  define MINOR(x) minor((x))
+#  define MKDEV(x,y) makedev((x),(y))
+#endif
+
+#define LINE_SIZE 4096
+#define ARGS_MAX 256
+#define LOOP_TABLE_SIZE (PATH_MAX + 255)
+
+#define DEFAULT_DM_DEV_DIR "/dev"
+
+/* FIXME Should be imported */
+#ifndef DM_MAX_TYPE_NAME
+#  define DM_MAX_TYPE_NAME 16
+#endif
+
+/* FIXME Should be elsewhere */
+#define SECTOR_SHIFT 9L
+
+#define err(msg, x...) fprintf(stderr, msg "\n", ##x)
+
+/*
+ * We have only very simple switches ATM.
+ */
+enum {
+	READ_ONLY = 0,
+	COLS_ARG,
+	EXEC_ARG,
+	FORCE_ARG,
+	GID_ARG,
+	MAJOR_ARG,
+	MINOR_ARG,
+	MODE_ARG,
+	NAMEPREFIXES_ARG,
+	NOFLUSH_ARG,
+	NOHEADINGS_ARG,
+	NOLOCKFS_ARG,
+	NOOPENCOUNT_ARG,
+	NOTABLE_ARG,
+	OPTIONS_ARG,
+	READAHEAD_ARG,
+	ROWS_ARG,
+	SEPARATOR_ARG,
+	SHOWKEYS_ARG,
+	SORT_ARG,
+	TABLE_ARG,
+	TARGET_ARG,
+	TREE_ARG,
+	UID_ARG,
+	UNBUFFERED_ARG,
+	UNQUOTED_ARG,
+	UUID_ARG,
+	VERBOSE_ARG,
+	VERSION_ARG,
+	NUM_SWITCHES
+};
+
+typedef enum {
+	DR_TASK = 1,
+	DR_INFO = 2,
+	DR_DEPS = 4,
+	DR_TREE = 8	/* Complete dependency tree required */
+} report_type_t;
+
+static int _switches[NUM_SWITCHES];
+static int _int_args[NUM_SWITCHES];
+static char *_string_args[NUM_SWITCHES];
+static int _num_devices;
+static char *_uuid;
+static char *_table;
+static char *_target;
+static char *_command;
+static uint32_t _read_ahead_flags;
+static struct dm_tree *_dtree;
+static struct dm_report *_report;
+static report_type_t _report_type;
+
+/*
+ * Commands
+ */
+
+typedef int (*command_fn) (int argc, char **argv, void *data);
+
+struct command {
+	const char *name;
+	const char *help;
+	int min_args;
+	int max_args;
+	command_fn fn;
+};
+
+static int _parse_line(struct dm_task *dmt, char *buffer, const char *file,
+		       int line)
+{
+	char ttype[LINE_SIZE], *ptr, *comment;
+	unsigned long long start, size;
+	int n;
+
+	/* trim trailing space */
+	for (ptr = buffer + strlen(buffer) - 1; ptr >= buffer; ptr--)
+		if (!isspace((int) *ptr))
+			break;
+	ptr++;
+	*ptr = '\0';
+
+	/* trim leading space */
+	for (ptr = buffer; *ptr && isspace((int) *ptr); ptr++)
+		;
+
+	if (!*ptr || *ptr == '#')
+		return 1;
+
+	if (sscanf(ptr, "%llu %llu %s %n",
+		   &start, &size, ttype, &n) < 3) {
+		err("Invalid format on line %d of table %s", line, file);
+		return 0;
+	}
+
+	ptr += n;
+	if ((comment = strchr(ptr, (int) '#')))
+		*comment = '\0';
+
+	if (!dm_task_add_target(dmt, start, size, ttype, ptr))
+		return 0;
+
+	return 1;
+}
+
+static int _parse_file(struct dm_task *dmt, const char *file)
+{
+	char *buffer = NULL;
+	size_t buffer_size = 0;
+	FILE *fp;
+	int r = 0, line = 0;
+
+	/* one-line table on cmdline */
+	if (_table)
+		return _parse_line(dmt, _table, "", ++line);
+
+	/* OK for empty stdin */
+	if (file) {
+		if (!(fp = fopen(file, "r"))) {
+			err("Couldn't open '%s' for reading", file);
+			return 0;
+		}
+	} else
+		fp = stdin;
+
+#ifndef HAVE_GETLINE
+	buffer_size = LINE_SIZE;
+	if (!(buffer = dm_malloc(buffer_size))) {
+		err("Failed to malloc line buffer.");
+		return 0;
+	}
+
+	while (fgets(buffer, (int) buffer_size, fp))
+#else
+	while (getline(&buffer, &buffer_size, fp) > 0)
+#endif
+		if (!_parse_line(dmt, buffer, file ? : "on stdin", ++line))
+			goto out;
+
+	r = 1;
+
+      out:
+#ifndef HAVE_GETLINE
+	dm_free(buffer);
+#else
+	free(buffer);
+#endif
+	if (file && fclose(fp))
+		fprintf(stderr, "%s: fclose failed: %s", file, strerror(errno));
+
+	return r;
+}
+
+struct dmsetup_report_obj {
+	struct dm_task *task;
+	struct dm_info *info;
+	struct dm_task *deps_task;
+	struct dm_tree_node *tree_node;
+};
+
+static struct dm_task *_get_deps_task(int major, int minor)
+{
+	struct dm_task *dmt;
+	struct dm_info info;
+
+	if (!(dmt = dm_task_create(DM_DEVICE_DEPS)))
+		return NULL;
+
+	if (!dm_task_set_major(dmt, major) ||
+	    !dm_task_set_minor(dmt, minor))
+		goto err;
+
+	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
+		goto err;
+
+	if (!dm_task_run(dmt))
+		goto err;
+
+	if (!dm_task_get_info(dmt, &info))
+		goto err;
+
+	if (!info.exists)
+		goto err;
+
+	return dmt;
+
+      err:
+	dm_task_destroy(dmt);
+	return NULL;
+}
+
+static int _display_info_cols(struct dm_task *dmt, struct dm_info *info)
+{
+	struct dmsetup_report_obj obj;
+	int r = 0;
+
+	if (!info->exists) {
+		fprintf(stderr, "Device does not exist.\n");
+		return 0;
+	}
+
+	obj.task = dmt;
+	obj.info = info;
+	obj.deps_task = NULL;
+
+	if (_report_type & DR_TREE)
+		obj.tree_node = dm_tree_find_node(_dtree, info->major, info->minor);
+
+	if (_report_type & DR_DEPS)
+		obj.deps_task = _get_deps_task(info->major, info->minor);
+
+	if (!dm_report_object(_report, &obj))
+		goto out;
+
+	r = 1;
+
+      out:
+	if (obj.deps_task)
+		dm_task_destroy(obj.deps_task);
+	return r;
+}
+
+static void _display_info_long(struct dm_task *dmt, struct dm_info *info)
+{
+	const char *uuid;
+	uint32_t read_ahead;
+
+	if (!info->exists) {
+		printf("Device does not exist.\n");
+		return;
+	}
+
+	printf("Name:              %s\n", dm_task_get_name(dmt));
+
+	printf("State:             %s%s\n",
+	       info->suspended ? "SUSPENDED" : "ACTIVE",
+	       info->read_only ? " (READ-ONLY)" : "");
+
+	/* FIXME Old value is being printed when it's being changed. */
+	if (dm_task_get_read_ahead(dmt, &read_ahead))
+		printf("Read Ahead:        %" PRIu32 "\n", read_ahead);
+
+	if (!info->live_table && !info->inactive_table)
+		printf("Tables present:    None\n");
+	else
+		printf("Tables present:    %s%s%s\n",
+		       info->live_table ? "LIVE" : "",
+		       info->live_table && info->inactive_table ? " & " : "",
+		       info->inactive_table ? "INACTIVE" : "");
+
+	if (info->open_count != -1)
+		printf("Open count:        %d\n", info->open_count);
+
+	printf("Event number:      %" PRIu32 "\n", info->event_nr);
+	printf("Major, minor:      %d, %d\n", info->major, info->minor);
+
+	if (info->target_count != -1)
+		printf("Number of targets: %d\n", info->target_count);
+
+	if ((uuid = dm_task_get_uuid(dmt)) && *uuid)
+		printf("UUID: %s\n", uuid);
+
+	printf("\n");
+}
+
+static int _display_info(struct dm_task *dmt)
+{
+	struct dm_info info;
+
+	if (!dm_task_get_info(dmt, &info))
+		return 0;
+
+	if (!_switches[COLS_ARG])
+		_display_info_long(dmt, &info);
+	else
+		/* FIXME return code */
+		_display_info_cols(dmt, &info);
+
+	return info.exists ? 1 : 0;
+}
+
+static int _set_task_device(struct dm_task *dmt, const char *name, int optional)
+{
+	if (name) {
+		if (!dm_task_set_name(dmt, name))
+			return 0;
+	} else if (_switches[UUID_ARG]) {
+		if (!dm_task_set_uuid(dmt, _uuid))
+			return 0;
+	} else if (_switches[MAJOR_ARG] && _switches[MINOR_ARG]) {
+		if (!dm_task_set_major(dmt, _int_args[MAJOR_ARG]) ||
+		    !dm_task_set_minor(dmt, _int_args[MINOR_ARG]))
+			return 0;
+	} else if (!optional) {
+		fprintf(stderr, "No device specified.\n");
+		return 0;
+	}
+
+	return 1;
+}
+
+static int _load(int argc, char **argv, void *data __attribute((unused)))
+{
+	int r = 0;
+	struct dm_task *dmt;
+	const char *file = NULL;
+	const char *name = NULL;
+
+	if (_switches[NOTABLE_ARG]) {
+		err("--notable only available when creating new device\n");
+		return 0;
+	}
+
+	if (!_switches[UUID_ARG] && !_switches[MAJOR_ARG]) {
+		if (argc == 1) {
+			err("Please specify device.\n");
+			return 0;
+		}
+		name = argv[1];
+		argc--;
+		argv++;
+	} else if (argc > 2) {
+		err("Too many command line arguments.\n");
+		return 0;
+	}
+
+	if (argc == 2)
+		file = argv[1];
+
+	if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
+		return 0;
+
+	if (!_set_task_device(dmt, name, 0))
+		goto out;
+
+	if (!_switches[NOTABLE_ARG] && !_parse_file(dmt, file))
+		goto out;
+
+	if (_switches[READ_ONLY] && !dm_task_set_ro(dmt))
+		goto out;
+
+	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
+		goto out;
+
+	if (!dm_task_run(dmt))
+		goto out;
+
+	r = 1;
+
+	if (_switches[VERBOSE_ARG])
+		r = _display_info(dmt);
+
+      out:
+	dm_task_destroy(dmt);
+
+	return r;
+}
+
+static int _create(int argc, char **argv, void *data __attribute((unused)))
+{
+	int r = 0;
+	struct dm_task *dmt;
+	const char *file = NULL;
+
+	if (argc == 3)
+		file = argv[2];
+
+	if (!(dmt = dm_task_create(DM_DEVICE_CREATE)))
+		return 0;
+
+	if (!dm_task_set_name(dmt, argv[1]))
+		goto out;
+
+	if (_switches[UUID_ARG] && !dm_task_set_uuid(dmt, _uuid))
+		goto out;
+
+	if (!_switches[NOTABLE_ARG] && !_parse_file(dmt, file))
+		goto out;
+
+	if (_switches[READ_ONLY] && !dm_task_set_ro(dmt))
+		goto out;
+
+	if (_switches[MAJOR_ARG] && !dm_task_set_major(dmt, _int_args[MAJOR_ARG]))
+		goto out;
+
+	if (_switches[MINOR_ARG] && !dm_task_set_minor(dmt, _int_args[MINOR_ARG]))
+		goto out;
+
+	if (_switches[UID_ARG] && !dm_task_set_uid(dmt, _int_args[UID_ARG]))
+		goto out;
+
+	if (_switches[GID_ARG] && !dm_task_set_gid(dmt, _int_args[GID_ARG]))
+		goto out;
+
+	if (_switches[MODE_ARG] && !dm_task_set_mode(dmt, _int_args[MODE_ARG]))
+		goto out;
+
+	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
+		goto out;
+
+	if (_switches[READAHEAD_ARG] &&
+	    !dm_task_set_read_ahead(dmt, _int_args[READAHEAD_ARG],
+				    _read_ahead_flags))
+		goto out;
+
+	if (!dm_task_run(dmt))
+		goto out;
+
+	r = 1;
+
+	if (_switches[VERBOSE_ARG])
+		r = _display_info(dmt);
+
+      out:
+	dm_task_destroy(dmt);
+
+	return r;
+}
+
+static int _rename(int argc, char **argv, void *data __attribute((unused)))
+{
+	int r = 0;
+	struct dm_task *dmt;
+
+	if (!(dmt = dm_task_create(DM_DEVICE_RENAME)))
+		return 0;
+
+	/* FIXME Kernel doesn't support uuid or device number here yet */
+	if (!_set_task_device(dmt, (argc == 3) ? argv[1] : NULL, 0))
+		goto out;
+
+	if (!dm_task_set_newname(dmt, argv[argc - 1]))
+		goto out;
+
+	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
+		goto out;
+
+	if (!dm_task_run(dmt))
+		goto out;
+
+	r = 1;
+
+      out:
+	dm_task_destroy(dmt);
+
+	return r;
+}
+
+static int _message(int argc, char **argv, void *data __attribute((unused)))
+{
+	int r = 0, i;
+	size_t sz = 1;
+	struct dm_task *dmt;
+	char *str;
+
+	if (!(dmt = dm_task_create(DM_DEVICE_TARGET_MSG)))
+		return 0;
+
+	if (_switches[UUID_ARG] || _switches[MAJOR_ARG]) {
+		if (!_set_task_device(dmt, NULL, 0))
+			goto out;
+	} else {
+		if (!_set_task_device(dmt, argv[1], 0))
+			goto out;
+		argc--;
+		argv++;
+	}
+
+	if (!dm_task_set_sector(dmt, (uint64_t) atoll(argv[1])))
+		goto out;
+
+	argc -= 2;
+	argv += 2;
+
+	if (argc <= 0)
+		err("No message supplied.\n");
+
+	for (i = 0; i < argc; i++)
+		sz += strlen(argv[i]) + 1;
+
+	if (!(str = dm_malloc(sz))) {
+		err("message string allocation failed");
+		goto out;
+	}
+
+	memset(str, 0, sz);
+
+	for (i = 0; i < argc; i++) {
+		if (i)
+			strcat(str, " ");
+		strcat(str, argv[i]);
+	}
+
+	if (!dm_task_set_message(dmt, str))
+		goto out;
+
+	dm_free(str);
+
+	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
+		goto out;
+
+	if (!dm_task_run(dmt))
+		goto out;
+
+	r = 1;
+
+      out:
+	dm_task_destroy(dmt);
+
+	return r;
+}
+
+static int _setgeometry(int argc, char **argv, void *data __attribute((unused)))
+{
+	int r = 0;
+	struct dm_task *dmt;
+
+	if (!(dmt = dm_task_create(DM_DEVICE_SET_GEOMETRY)))
+		return 0;
+
+	if (_switches[UUID_ARG] || _switches[MAJOR_ARG]) {
+		if (!_set_task_device(dmt, NULL, 0))
+			goto out;
+	} else {
+		if (!_set_task_device(dmt, argv[1], 0))
+			goto out;
+		argc--;
+		argv++;
+	}
+
+	if (!dm_task_set_geometry(dmt, argv[1], argv[2], argv[3], argv[4]))
+		goto out;
+
+	/* run the task */
+	if (!dm_task_run(dmt))
+		goto out;
+
+	r = 1;
+
+      out:
+	dm_task_destroy(dmt);
+
+	return r;
+}
+
+static int _version(int argc __attribute((unused)), char **argv __attribute((unused)), void *data __attribute((unused)))
+{
+	char version[80];
+
+	if (dm_get_library_version(version, sizeof(version)))
+		printf("Library version:   %s\n", version);
+
+	if (!dm_driver_version(version, sizeof(version)))
+		return 0;
+
+	printf("Driver version:    %s\n", version);
+
+	return 1;
+}
+
+static int _simple(int task, const char *name, uint32_t event_nr, int display)
+{
+	int r = 0;
+
+	struct dm_task *dmt;
+
+	if (!(dmt = dm_task_create(task)))
+		return 0;
+
+	if (!_set_task_device(dmt, name, 0))
+		goto out;
+
+	if (event_nr && !dm_task_set_event_nr(dmt, event_nr))
+		goto out;
+
+	if (_switches[NOFLUSH_ARG] && !dm_task_no_flush(dmt))
+		goto out;
+
+	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
+		goto out;
+
+	if (_switches[NOLOCKFS_ARG] && !dm_task_skip_lockfs(dmt))
+		goto out;
+
+	if (_switches[READAHEAD_ARG] &&
+	    !dm_task_set_read_ahead(dmt, _int_args[READAHEAD_ARG],
+				    _read_ahead_flags))
+		goto out;
+
+	r = dm_task_run(dmt);
+
+	if (r && display && _switches[VERBOSE_ARG])
+		r = _display_info(dmt);
+
+      out:
+	dm_task_destroy(dmt);
+	return r;
+}
+
+static int _suspend(int argc, char **argv, void *data __attribute((unused)))
+{
+	return _simple(DM_DEVICE_SUSPEND, argc > 1 ? argv[1] : NULL, 0, 1);
+}
+
+static int _resume(int argc, char **argv, void *data __attribute((unused)))
+{
+	return _simple(DM_DEVICE_RESUME, argc > 1 ? argv[1] : NULL, 0, 1);
+}
+
+static int _clear(int argc, char **argv, void *data __attribute((unused)))
+{
+	return _simple(DM_DEVICE_CLEAR, argc > 1 ? argv[1] : NULL, 0, 1);
+}
+
+static int _wait(int argc, char **argv, void *data __attribute((unused)))
+{
+	const char *name = NULL;
+
+	if (!_switches[UUID_ARG] && !_switches[MAJOR_ARG]) {
+		if (argc == 1) {
+			err("No device specified.");
+			return 0;
+		}
+		name = argv[1];
+		argc--, argv++;
+	}
+
+	return _simple(DM_DEVICE_WAITEVENT, name,
+		       (argc > 1) ? (uint32_t) atoi(argv[argc - 1]) : 0, 1);
+}
+
+static int _process_all(int argc, char **argv, int silent,
+			int (*fn) (int argc, char **argv, void *data))
+{
+	int r = 1;
+	struct dm_names *names;
+	unsigned next = 0;
+
+	struct dm_task *dmt;
+
+	if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
+		return 0;
+
+	if (!dm_task_run(dmt)) {
+		r = 0;
+		goto out;
+	}
+
+	if (!(names = dm_task_get_names(dmt))) {
+		r = 0;
+		goto out;
+	}
+
+	if (!names->dev) {
+		if (!silent)
+			printf("No devices found\n");
+		goto out;
+	}
+
+	do {
+		names = (void *) names + next;
+		if (!fn(argc, argv, (void *) names))
+			r = 0;
+		next = names->next;
+	} while (next);
+
+      out:
+	dm_task_destroy(dmt);
+	return r;
+}
+
+static uint64_t _get_device_size(const char *name)
+{
+	uint64_t start, length, size = UINT64_C(0);
+	struct dm_info info;
+	char *target_type, *params;
+	struct dm_task *dmt;
+	void *next = NULL;
+
+	if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
+		return 0;
+
+	if (!_set_task_device(dmt, name, 0))
+		goto out;
+
+	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
+		goto out;
+
+	if (!dm_task_run(dmt))
+		goto out;
+
+	if (!dm_task_get_info(dmt, &info) || !info.exists)
+		goto out;
+
+	do {
+		next = dm_get_next_target(dmt, next, &start, &length,
+					  &target_type, &params);
+		size += length;
+	} while (next);
+
+      out:
+	dm_task_destroy(dmt);
+	return size;
+}
+
+static int _error_device(int argc __attribute((unused)), char **argv __attribute((unused)), void *data)
+{
+	struct dm_names *names = (struct dm_names *) data;
+	struct dm_task *dmt;
+	const char *name;
+	uint64_t size;
+	int r = 0;
+
+	if (data)
+		name = names->name;
+	else
+		name = argv[1];
+
+	size = _get_device_size(name);
+
+	if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
+		return 0;
+
+	if (!_set_task_device(dmt, name, 0))
+		goto error;
+
+	if (!dm_task_add_target(dmt, UINT64_C(0), size, "error", ""))
+		goto error;
+
+	if (_switches[READ_ONLY] && !dm_task_set_ro(dmt))
+		goto error;
+
+	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
+		goto error;
+
+	if (!dm_task_run(dmt))
+		goto error;
+
+	if (!_simple(DM_DEVICE_RESUME, name, 0, 0)) {
+		_simple(DM_DEVICE_CLEAR, name, 0, 0);
+		goto error;
+	}
+
+	r = 1;
+
+error:
+	dm_task_destroy(dmt);
+	return r;
+}
+
+static int _remove(int argc, char **argv, void *data __attribute((unused)))
+{
+	int r;
+
+	if (_switches[FORCE_ARG] && argc > 1)
+		r = _error_device(argc, argv, NULL);
+
+	return _simple(DM_DEVICE_REMOVE, argc > 1 ? argv[1] : NULL, 0, 0);
+}
+
+static int _count_devices(int argc __attribute((unused)), char **argv __attribute((unused)), void *data __attribute((unused)))
+{
+	_num_devices++;
+
+	return 1;
+}
+
+static int _remove_all(int argc __attribute((unused)), char **argv __attribute((unused)), void *data __attribute((unused)))
+{
+	int r;
+
+	/* Remove all closed devices */
+	r =  _simple(DM_DEVICE_REMOVE_ALL, "", 0, 0) | dm_mknodes(NULL);
+
+	if (!_switches[FORCE_ARG])
+		return r;
+
+	_num_devices = 0;
+	r |= _process_all(argc, argv, 1, _count_devices);
+
+	/* No devices left? */
+	if (!_num_devices)
+		return r;
+
+	r |= _process_all(argc, argv, 1, _error_device);
+	r |= _simple(DM_DEVICE_REMOVE_ALL, "", 0, 0) | dm_mknodes(NULL);
+
+	_num_devices = 0;
+	r |= _process_all(argc, argv, 1, _count_devices);
+	if (!_num_devices)
+		return r;
+
+	fprintf(stderr, "Unable to remove %d device(s).\n", _num_devices);
+
+	return r;
+}
+
+static void _display_dev(struct dm_task *dmt, const char *name)
+{
+	struct dm_info info;
+
+	if (dm_task_get_info(dmt, &info))
+		printf("%s\t(%u, %u)\n", name, info.major, info.minor);
+}
+
+static int _mknodes(int argc, char **argv, void *data __attribute((unused)))
+{
+	return dm_mknodes(argc > 1 ? argv[1] : NULL);
+}
+
+static int _exec_command(const char *name)
+{
+	int n;
+	static char path[PATH_MAX];
+	static char *args[ARGS_MAX + 1];
+	static int argc = 0;
+	char *c;
+	pid_t pid;
+
+	if (argc < 0)
+		return 0;
+
+	if (!dm_mknodes(name))
+		return 0;
+
+	n = snprintf(path, sizeof(path), "%s/%s", dm_dir(), name);
+	if (n < 0 || n > (int) sizeof(path) - 1)
+		return 0;
+
+	if (!argc) {
+		c = _command;
+		while (argc < ARGS_MAX) {
+			while (*c && isspace(*c))
+				c++;
+			if (!*c)
+				break;
+			args[argc++] = c;
+			while (*c && !isspace(*c))
+				c++;
+			if (*c)
+				*c++ = '\0';
+		}
+
+		if (!argc) {
+			argc = -1;
+			return 0;
+		}
+
+		if (argc == ARGS_MAX) {
+			err("Too many args to --exec\n");
+			argc = -1;
+			return 0;
+		}
+
+		args[argc++] = path;
+		args[argc] = NULL;
+	}
+
+	if (!(pid = fork())) {
+		execvp(args[0], args);
+		exit(127);
+	} else if (pid < (pid_t) 0)
+		return 0;
+
+	TEMP_FAILURE_RETRY(waitpid(pid, NULL, 0));
+
+	return 1;
+}
+
+static int _status(int argc, char **argv, void *data)
+{
+	int r = 0;
+	struct dm_task *dmt;
+	void *next = NULL;
+	uint64_t start, length;
+	char *target_type = NULL;
+	char *params, *c;
+	int cmd;
+	struct dm_names *names = (struct dm_names *) data;
+	const char *name = NULL;
+	int matched = 0;
+	int ls_only = 0;
+	struct dm_info info;
+
+	if (data)
+		name = names->name;
+	else {
+		if (argc == 1 && !_switches[UUID_ARG] && !_switches[MAJOR_ARG])
+			return _process_all(argc, argv, 0, _status);
+		if (argc == 2)
+			name = argv[1];
+	}
+
+	if (!strcmp(argv[0], "table"))
+		cmd = DM_DEVICE_TABLE;
+	else
+		cmd = DM_DEVICE_STATUS;
+
+	if (!strcmp(argv[0], "ls"))
+		ls_only = 1;
+
+	if (!(dmt = dm_task_create(cmd)))
+		return 0;
+
+	if (!_set_task_device(dmt, name, 0))
+		goto out;
+
+	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
+		goto out;
+
+	if (!dm_task_run(dmt))
+		goto out;
+
+	if (!dm_task_get_info(dmt, &info) || !info.exists)
+		goto out;
+
+	if (!name)
+		name = dm_task_get_name(dmt);
+
+	/* Fetch targets and print 'em */
+	do {
+		next = dm_get_next_target(dmt, next, &start, &length,
+					  &target_type, &params);
+		/* Skip if target type doesn't match */
+		if (_switches[TARGET_ARG] &&
+		    (!target_type || strcmp(target_type, _target)))
+			continue;
+		if (ls_only) {
+			if (!_switches[EXEC_ARG] || !_command ||
+			    _switches[VERBOSE_ARG])
+				_display_dev(dmt, name);
+			next = NULL;
+		} else if (!_switches[EXEC_ARG] || !_command ||
+			   _switches[VERBOSE_ARG]) {
+			if (!matched && _switches[VERBOSE_ARG])
+				_display_info(dmt);
+			if (data && !_switches[VERBOSE_ARG])
+				printf("%s: ", name);
+			if (target_type) {
+				/* Suppress encryption key */
+				if (!_switches[SHOWKEYS_ARG] &&
+				    cmd == DM_DEVICE_TABLE &&
+				    !strcmp(target_type, "crypt")) {
+					c = params;
+					while (*c && *c != ' ')
+						c++;
+					if (*c)
+						c++;
+					while (*c && *c != ' ')
+						*c++ = '0';
+				}
+				printf("%" PRIu64 " %" PRIu64 " %s %s",
+				       start, length, target_type, params);
+			}
+			printf("\n");
+		}
+		matched = 1;
+	} while (next);
+
+	if (data && _switches[VERBOSE_ARG] && matched && !ls_only)
+		printf("\n");
+
+	if (matched && _switches[EXEC_ARG] && _command && !_exec_command(name))
+		goto out;
+
+	r = 1;
+
+      out:
+	dm_task_destroy(dmt);
+	return r;
+}
+
+/* Show target names and their version numbers */
+static int _targets(int argc __attribute((unused)), char **argv __attribute((unused)), void *data __attribute((unused)))
+{
+	int r = 0;
+	struct dm_task *dmt;
+	struct dm_versions *target;
+	struct dm_versions *last_target;
+
+	if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
+		return 0;
+
+	if (!dm_task_run(dmt))
+		goto out;
+
+	target = dm_task_get_versions(dmt);
+
+	/* Fetch targets and print 'em */
+	do {
+		last_target = target;
+
+		printf("%-16s v%d.%d.%d\n", target->name, target->version[0],
+		       target->version[1], target->version[2]);
+
+		target = (void *) target + target->next;
+	} while (last_target != target);
+
+	r = 1;
+
+      out:
+	dm_task_destroy(dmt);
+	return r;
+}
+
+static int _info(int argc, char **argv, void *data)
+{
+	int r = 0;
+
+	struct dm_task *dmt;
+	struct dm_names *names = (struct dm_names *) data;
+	char *name = NULL;
+
+	if (data)
+		name = names->name;
+	else {
+		if (argc == 1 && !_switches[UUID_ARG] && !_switches[MAJOR_ARG])
+			return _process_all(argc, argv, 0, _info);
+		if (argc == 2)
+			name = argv[1];
+	}
+
+	if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
+		return 0;
+
+	if (!_set_task_device(dmt, name, 0))
+		goto out;
+
+	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
+		goto out;
+
+	if (!dm_task_run(dmt))
+		goto out;
+
+	r = _display_info(dmt);
+
+      out:
+	dm_task_destroy(dmt);
+	return r;
+}
+
+static int _deps(int argc, char **argv, void *data)
+{
+	int r = 0;
+	uint32_t i;
+	struct dm_deps *deps;
+	struct dm_task *dmt;
+	struct dm_info info;
+	struct dm_names *names = (struct dm_names *) data;
+	char *name = NULL;
+
+	if (data)
+		name = names->name;
+	else {
+		if (argc == 1 && !_switches[UUID_ARG] && !_switches[MAJOR_ARG])
+			return _process_all(argc, argv, 0, _deps);
+		if (argc == 2)
+			name = argv[1];
+	}
+
+	if (!(dmt = dm_task_create(DM_DEVICE_DEPS)))
+		return 0;
+
+	if (!_set_task_device(dmt, name, 0))
+		goto out;
+
+	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
+		goto out;
+
+	if (!dm_task_run(dmt))
+		goto out;
+
+	if (!dm_task_get_info(dmt, &info))
+		goto out;
+
+	if (!(deps = dm_task_get_deps(dmt)))
+		goto out;
+
+	if (!info.exists) {
+		printf("Device does not exist.\n");
+		r = 1;
+		goto out;
+	}
+
+	if (_switches[VERBOSE_ARG])
+		_display_info(dmt);
+
+	if (data && !_switches[VERBOSE_ARG])
+		printf("%s: ", name);
+	printf("%d dependencies\t:", deps->count);
+
+	for (i = 0; i < deps->count; i++)
+		printf(" (%d, %d)",
+		       (int) MAJOR(deps->device[i]),
+		       (int) MINOR(deps->device[i]));
+	printf("\n");
+
+	if (data && _switches[VERBOSE_ARG])
+		printf("\n");
+
+	r = 1;
+
+      out:
+	dm_task_destroy(dmt);
+	return r;
+}
+
+static int _display_name(int argc __attribute((unused)), char **argv __attribute((unused)), void *data)
+{
+	struct dm_names *names = (struct dm_names *) data;
+
+	printf("%s\t(%d, %d)\n", names->name,
+	       (int) MAJOR(names->dev), (int) MINOR(names->dev));
+
+	return 1;
+}
+
+/*
+ * Tree drawing code
+ */
+
+enum {
+	TR_DEVICE=0,	/* display device major:minor number */
+	TR_TABLE,
+	TR_STATUS,
+	TR_ACTIVE,
+	TR_RW,
+	TR_OPENCOUNT,
+	TR_UUID,
+	TR_COMPACT,
+	TR_TRUNCATE,
+	TR_BOTTOMUP,
+	NUM_TREEMODE,
+};
+
+static int _tree_switches[NUM_TREEMODE];
+
+#define TR_PRINT_ATTRIBUTE ( _tree_switches[TR_ACTIVE] || \
+			     _tree_switches[TR_RW] || \
+			     _tree_switches[TR_OPENCOUNT] || \
+			     _tree_switches[TR_UUID] )
+
+#define TR_PRINT_TARGETS ( _tree_switches[TR_TABLE] || \
+			   _tree_switches[TR_STATUS] )
+
+/* Compact - fewer newlines */
+#define TR_PRINT_COMPACT (_tree_switches[TR_COMPACT] && \
+			  !TR_PRINT_ATTRIBUTE && \
+			  !TR_PRINT_TARGETS)
+
+/* FIXME Get rid of this */
+#define MAX_DEPTH 100
+
+/* Drawing character definition from pstree */
+/* [pstree comment] UTF-8 defines by Johan Myreen, updated by Ben Winslow */
+#define UTF_V	"\342\224\202"	/* U+2502, Vertical line drawing char */
+#define UTF_VR	"\342\224\234"	/* U+251C, Vertical and right */
+#define UTF_H	"\342\224\200"	/* U+2500, Horizontal */
+#define UTF_UR	"\342\224\224"	/* U+2514, Up and right */
+#define UTF_HD	"\342\224\254"	/* U+252C, Horizontal and down */
+
+#define VT_BEG	"\033(0\017"	/* use graphic chars */
+#define VT_END	"\033(B"	/* back to normal char set */
+#define VT_V	"x"		/* see UTF definitions above */
+#define VT_VR	"t"
+#define VT_H	"q"
+#define VT_UR	"m"
+#define VT_HD	"w"
+
+static struct {
+	const char *empty_2;	/*    */
+	const char *branch_2;	/* |- */
+	const char *vert_2;	/* |  */
+	const char *last_2;	/* `- */
+	const char *single_3;	/* --- */
+	const char *first_3;	/* -+- */
+}
+_tsym_ascii = {
+	"  ",
+	"|-",
+	"| ",
+	"`-",
+	"---",
+	"-+-"
+},
+_tsym_utf = {
+	"  ",
+	UTF_VR UTF_H,
+	UTF_V " ",
+	UTF_UR UTF_H,
+	UTF_H UTF_H UTF_H,
+	UTF_H UTF_HD UTF_H
+},
+_tsym_vt100 = {
+	"  ",
+	VT_BEG VT_VR VT_H VT_END,
+	VT_BEG VT_V VT_END " ",
+	VT_BEG VT_UR VT_H VT_END,
+	VT_BEG VT_H VT_H VT_H VT_END,
+	VT_BEG VT_H VT_HD VT_H VT_END
+},
+*_tsym = &_tsym_ascii;
+
+/*
+ * Tree drawing functions.
+ */
+/* FIXME Get rid of these statics - use dynamic struct */
+/* FIXME Explain what these vars are for */
+static int _tree_width[MAX_DEPTH], _tree_more[MAX_DEPTH];
+static int _termwidth = 80;	/* Maximum output width */
+static int _cur_x = 1;		/* Current horizontal output position */
+static char _last_char = 0;
+
+static void _out_char(const unsigned c)
+{
+	/* Only first UTF-8 char counts */
+	_cur_x += ((c & 0xc0) != 0x80);
+
+	if (!_tree_switches[TR_TRUNCATE]) {
+		putchar((int) c);
+		return;
+	}
+
+	/* Truncation? */
+	if (_cur_x <= _termwidth)
+		putchar((int) c);
+
+	if (_cur_x == _termwidth + 1 && ((c & 0xc0) != 0x80)) {
+		if (_last_char || (c & 0x80)) {
+			putchar('.');
+			putchar('.');
+			putchar('.');
+		} else {
+			_last_char = c;
+			_cur_x--;
+		}
+	}
+}
+
+static void _out_string(const char *str)
+{
+	while (*str)
+		_out_char((unsigned char) *str++);
+}
+
+/* non-negative integers only */
+static unsigned _out_int(unsigned num)
+{
+	unsigned digits = 0;
+	unsigned divi;
+
+	if (!num) {
+		_out_char('0');
+		return 1;
+	}
+
+	/* non zero case */
+	for (divi = 1; num / divi; divi *= 10)
+		digits++;
+
+	for (divi /= 10; divi; divi /= 10)
+		_out_char('0' + (num / divi) % 10);
+
+	return digits;
+}
+
+static void _out_newline(void)
+{
+	if (_last_char && _cur_x == _termwidth)
+		putchar(_last_char);
+	_last_char = 0;
+	putchar('\n');
+	_cur_x = 1;
+}
+
+static void _out_prefix(unsigned depth)
+{
+	unsigned x, d;
+
+	for (d = 0; d < depth; d++) {
+		for (x = _tree_width[d] + 1; x > 0; x--)
+			_out_char(' ');
+
+		_out_string(d == depth - 1 ?
+				!_tree_more[depth] ? _tsym->last_2 : _tsym->branch_2
+			   : _tree_more[d + 1] ?
+				_tsym->vert_2 : _tsym->empty_2);
+	}
+}
+
+/*
+ * Display tree
+ */
+static void _display_tree_attributes(struct dm_tree_node *node)
+{
+	int attr = 0;
+	const char *uuid;
+	const struct dm_info *info;
+
+	uuid = dm_tree_node_get_uuid(node);
+	info = dm_tree_node_get_info(node);
+
+	if (!info->exists)
+		return;
+
+	if (_tree_switches[TR_ACTIVE]) {
+		_out_string(attr++ ? ", " : " [");
+		_out_string(info->suspended ? "SUSPENDED" : "ACTIVE");
+	}
+
+	if (_tree_switches[TR_RW]) {
+		_out_string(attr++ ? ", " : " [");
+		_out_string(info->read_only ? "RO" : "RW");
+	}
+
+	if (_tree_switches[TR_OPENCOUNT]) {
+		_out_string(attr++ ? ", " : " [");
+		(void) _out_int((unsigned) info->open_count);
+	}
+
+	if (_tree_switches[TR_UUID]) {
+		_out_string(attr++ ? ", " : " [");
+		_out_string(uuid && *uuid ? uuid : "");
+	}
+
+	if (attr)
+		_out_char(']');
+}
+
+static void _display_tree_node(struct dm_tree_node *node, unsigned depth,
+			       unsigned first_child __attribute((unused)),
+			       unsigned last_child, unsigned has_children)
+{
+	int offset;
+	const char *name;
+	const struct dm_info *info;
+	int first_on_line = 0;
+
+	/* Sub-tree for targets has 2 more depth */
+	if (depth + 2 > MAX_DEPTH)
+		return;
+
+	name = dm_tree_node_get_name(node);
+
+	if ((!name || !*name) && !_tree_switches[TR_DEVICE])
+		return;
+
+	/* Indicate whether there are more nodes at this depth */
+	_tree_more[depth] = !last_child;
+	_tree_width[depth] = 0;
+
+	if (_cur_x == 1)
+		first_on_line = 1;
+
+	if (!TR_PRINT_COMPACT || first_on_line)
+		_out_prefix(depth);
+
+	/* Remember the starting point for compact */
+	offset = _cur_x;
+
+	if (TR_PRINT_COMPACT && !first_on_line)
+		_out_string(_tree_more[depth] ? _tsym->first_3 : _tsym->single_3);
+
+	/* display node */
+	if (name)
+		_out_string(name);
+
+	info = dm_tree_node_get_info(node);
+
+	if (_tree_switches[TR_DEVICE]) {
+		_out_string(name ? " (" : "(");
+		(void) _out_int(info->major);
+		_out_char(':');
+		(void) _out_int(info->minor);
+		_out_char(')');
+	}
+
+	/* display additional info */
+	if (TR_PRINT_ATTRIBUTE)
+		_display_tree_attributes(node);
+
+	if (TR_PRINT_COMPACT)
+		_tree_width[depth] = _cur_x - offset;
+
+	if (!TR_PRINT_COMPACT || !has_children)
+		_out_newline();
+
+	if (TR_PRINT_TARGETS) {
+		_tree_more[depth + 1] = has_children;
+		// FIXME _display_tree_targets(name, depth + 2);
+	}
+}
+
+/*
+ * Walk the dependency tree
+ */
+static void _display_tree_walk_children(struct dm_tree_node *node,
+					unsigned depth)
+{
+	struct dm_tree_node *child, *next_child;
+	void *handle = NULL;
+	uint32_t inverted = _tree_switches[TR_BOTTOMUP];
+	unsigned first_child = 1;
+	unsigned has_children;
+
+	next_child = dm_tree_next_child(&handle, node, inverted);
+
+	while ((child = next_child)) {
+		next_child = dm_tree_next_child(&handle, node, inverted);
+		has_children =
+		    dm_tree_node_num_children(child, inverted) ? 1 : 0;
+
+		_display_tree_node(child, depth, first_child,
+				   next_child ? 0U : 1U, has_children);
+
+		if (has_children)
+			_display_tree_walk_children(child, depth + 1);
+
+		first_child = 0;
+	}
+}
+
+static int _add_dep(int argc __attribute((unused)), char **argv __attribute((unused)), void *data)
+{
+	struct dm_names *names = (struct dm_names *) data;
+
+	if (!dm_tree_add_dev(_dtree, (unsigned) MAJOR(names->dev), (unsigned) MINOR(names->dev)))
+		return 0;
+
+	return 1;
+}
+
+/*
+ * Create and walk dependency tree
+ */
+static int _build_whole_deptree(void)
+{
+	if (_dtree)
+		return 1;
+
+	if (!(_dtree = dm_tree_create()))
+		return 0;
+
+	if (!_process_all(0, NULL, 0, _add_dep))
+		return 0;
+
+	return 1;
+}
+
+static int _display_tree(int argc __attribute((unused)),
+			 char **argv __attribute((unused)),
+			 void *data __attribute((unused)))
+{
+	if (!_build_whole_deptree())
+		return 0;
+
+	_display_tree_walk_children(dm_tree_find_node(_dtree, 0, 0), 0);
+
+	return 1;
+}
+
+/*
+ * Report device information
+ */
+
+/* dm specific display functions */
+
+static int _int32_disp(struct dm_report *rh,
+		       struct dm_pool *mem __attribute((unused)),
+		       struct dm_report_field *field, const void *data,
+		       void *private __attribute((unused)))
+{
+	const int32_t value = *(const int32_t *)data;
+
+	return dm_report_field_int32(rh, field, &value);
+}
+
+static int _uint32_disp(struct dm_report *rh,
+			struct dm_pool *mem __attribute((unused)),
+			struct dm_report_field *field, const void *data,
+			void *private __attribute((unused)))
+{
+	const uint32_t value = *(const int32_t *)data;
+
+	return dm_report_field_uint32(rh, field, &value);
+}
+
+static int _dm_name_disp(struct dm_report *rh,
+			 struct dm_pool *mem __attribute((unused)),
+			 struct dm_report_field *field, const void *data,
+			 void *private __attribute((unused)))
+{
+	const char *name = dm_task_get_name((const struct dm_task *) data);
+
+	return dm_report_field_string(rh, field, &name);
+}
+
+static int _dm_uuid_disp(struct dm_report *rh,
+			 struct dm_pool *mem __attribute((unused)),
+			 struct dm_report_field *field,
+			 const void *data, void *private __attribute((unused)))
+{
+	const char *uuid = dm_task_get_uuid((const struct dm_task *) data);
+
+	if (!uuid || !*uuid)
+		uuid = "";
+
+	return dm_report_field_string(rh, field, &uuid);
+}
+
+static int _dm_read_ahead_disp(struct dm_report *rh,
+			       struct dm_pool *mem __attribute((unused)),
+			       struct dm_report_field *field, const void *data,
+			       void *private __attribute((unused)))
+{
+	uint32_t value;
+
+	if (!dm_task_get_read_ahead((const struct dm_task *) data, &value))
+		value = 0;
+
+	return dm_report_field_uint32(rh, field, &value);
+}
+
+static int _dm_info_status_disp(struct dm_report *rh,
+				struct dm_pool *mem __attribute((unused)),
+				struct dm_report_field *field, const void *data,
+				void *private __attribute((unused)))
+{
+	char buf[5];
+	const char *s = buf;
+	const struct dm_info *info = data;
+
+	buf[0] = info->live_table ? 'L' : '-';
+	buf[1] = info->inactive_table ? 'I' : '-';
+	buf[2] = info->suspended ? 's' : '-';
+	buf[3] = info->read_only ? 'r' : 'w';
+	buf[4] = '\0';
+
+	return dm_report_field_string(rh, field, &s);
+}
+
+static int _dm_info_table_loaded_disp(struct dm_report *rh,
+				      struct dm_pool *mem __attribute((unused)),
+				      struct dm_report_field *field,
+				      const void *data,
+				      void *private __attribute((unused)))
+{
+	const struct dm_info *info = data;
+
+	if (info->live_table) {
+		if (info->inactive_table)
+			dm_report_field_set_value(field, "Both", NULL);
+		else
+			dm_report_field_set_value(field, "Live", NULL);
+		return 1;
+	}
+
+	if (info->inactive_table)
+		dm_report_field_set_value(field, "Inactive", NULL);
+	else
+		dm_report_field_set_value(field, "None", NULL);
+
+	return 1;
+}
+
+static int _dm_info_suspended_disp(struct dm_report *rh,
+				   struct dm_pool *mem __attribute((unused)),
+				   struct dm_report_field *field,
+				   const void *data,
+				   void *private __attribute((unused)))
+{
+	const struct dm_info *info = data;
+
+	if (info->suspended)
+		dm_report_field_set_value(field, "Suspended", NULL);
+	else
+		dm_report_field_set_value(field, "Active", NULL);
+
+	return 1;
+}
+
+static int _dm_info_read_only_disp(struct dm_report *rh,
+				   struct dm_pool *mem __attribute((unused)),
+				   struct dm_report_field *field,
+				   const void *data,
+				   void *private __attribute((unused)))
+{
+	const struct dm_info *info = data;
+
+	if (info->read_only)
+		dm_report_field_set_value(field, "Read-only", NULL);
+	else
+		dm_report_field_set_value(field, "Writeable", NULL);
+
+	return 1;
+}
+
+
+static int _dm_info_devno_disp(struct dm_report *rh, struct dm_pool *mem,
+			       struct dm_report_field *field, const void *data,
+			       void *private)
+{
+	char buf[DM_MAX_TYPE_NAME], *repstr;
+	struct dm_info *info = (struct dm_info *) data;
+
+	if (!dm_pool_begin_object(mem, 8)) {
+		log_error("dm_pool_begin_object failed");
+		return 0;
+	}
+
+	if (dm_snprintf(buf, sizeof(buf), "%d:%d",
+			info->major, info->minor) < 0) {
+		log_error("dm_pool_alloc failed");
+		goto out_abandon;
+	}
+
+	if (!dm_pool_grow_object(mem, buf, strlen(buf) + 1)) {
+		log_error("dm_pool_grow_object failed");
+		goto out_abandon;
+	}
+
+	repstr = dm_pool_end_object(mem);
+	dm_report_field_set_value(field, repstr, repstr);
+	return 1;
+
+      out_abandon:
+	dm_pool_abandon_object(mem);
+	return 0;
+}
+
+static int _dm_tree_names(struct dm_report *rh, struct dm_pool *mem,
+			  struct dm_report_field *field, const void *data,
+			  void *private, unsigned inverted)
+{
+	struct dm_tree_node *node = (struct dm_tree_node *) data, *parent;
+	void *t = NULL;
+	const char *name;
+	int first_node = 1;
+	char *repstr;
+
+	if (!dm_pool_begin_object(mem, 16)) {
+		log_error("dm_pool_begin_object failed");
+		return 0;
+	}
+
+	while ((parent = dm_tree_next_child(&t, node, inverted))) {
+		name = dm_tree_node_get_name(parent);
+		if (!name || !*name)
+			continue;
+		if (!first_node && !dm_pool_grow_object(mem, ",", 1)) {
+			log_error("dm_pool_grow_object failed");
+			goto out_abandon;
+		}
+		if (!dm_pool_grow_object(mem, name, 0)) {
+			log_error("dm_pool_grow_object failed");
+			goto out_abandon;
+		}
+		if (first_node)
+			first_node = 0;
+	}
+
+	if (!dm_pool_grow_object(mem, "\0", 1)) {
+		log_error("dm_pool_grow_object failed");
+		goto out_abandon;
+	}
+
+	repstr = dm_pool_end_object(mem);
+	dm_report_field_set_value(field, repstr, repstr);
+	return 1;
+
+      out_abandon:
+	dm_pool_abandon_object(mem);
+	return 0;
+}
+
+static int _dm_deps_names_disp(struct dm_report *rh,
+				      struct dm_pool *mem,
+				      struct dm_report_field *field,
+				      const void *data, void *private)
+{
+	return _dm_tree_names(rh, mem, field, data, private, 0);
+}
+
+static int _dm_tree_parents_names_disp(struct dm_report *rh,
+				       struct dm_pool *mem,
+				       struct dm_report_field *field,
+				       const void *data, void *private)
+{
+	return _dm_tree_names(rh, mem, field, data, private, 1);
+}
+
+static int _dm_tree_parents_devs_disp(struct dm_report *rh, struct dm_pool *mem,
+				      struct dm_report_field *field,
+				      const void *data, void *private)
+{
+	struct dm_tree_node *node = (struct dm_tree_node *) data, *parent;
+	void *t = NULL;
+	const struct dm_info *info;
+	int first_node = 1;
+	char buf[DM_MAX_TYPE_NAME], *repstr;
+
+	if (!dm_pool_begin_object(mem, 16)) {
+		log_error("dm_pool_begin_object failed");
+		return 0;
+	}
+
+	while ((parent = dm_tree_next_child(&t, node, 1))) {
+		info = dm_tree_node_get_info(parent);
+		if (!info->major && !info->minor)
+			continue;
+		if (!first_node && !dm_pool_grow_object(mem, ",", 1)) {
+			log_error("dm_pool_grow_object failed");
+			goto out_abandon;
+		}
+		if (dm_snprintf(buf, sizeof(buf), "%d:%d",
+				info->major, info->minor) < 0) {
+			log_error("dm_snprintf failed");
+			goto out_abandon;
+		}
+		if (!dm_pool_grow_object(mem, buf, 0)) {
+			log_error("dm_pool_grow_object failed");
+			goto out_abandon;
+		}
+		if (first_node)
+			first_node = 0;
+	}
+
+	if (!dm_pool_grow_object(mem, "\0", 1)) {
+		log_error("dm_pool_grow_object failed");
+		goto out_abandon;
+	}
+
+	repstr = dm_pool_end_object(mem);
+	dm_report_field_set_value(field, repstr, repstr);
+	return 1;
+
+      out_abandon:
+	dm_pool_abandon_object(mem);
+	return 0;
+}
+
+static int _dm_tree_parents_count_disp(struct dm_report *rh,
+				       struct dm_pool *mem,
+				       struct dm_report_field *field,
+				       const void *data, void *private)
+{
+	struct dm_tree_node *node = (struct dm_tree_node *) data;
+	int num_parent = dm_tree_node_num_children(node, 1);
+
+	return dm_report_field_int(rh, field, &num_parent);
+}
+
+static int _dm_deps_disp(struct dm_report *rh, struct dm_pool *mem,
+			 struct dm_report_field *field, const void *data,
+			 void *private)
+{
+	struct dm_deps *deps = (struct dm_deps *) data;
+	int i;
+	char buf[DM_MAX_TYPE_NAME], *repstr;
+
+	if (!dm_pool_begin_object(mem, 16)) {
+		log_error("dm_pool_begin_object failed");
+		return 0;
+	}
+
+	for (i = 0; i < deps->count; i++) {
+		if (dm_snprintf(buf, sizeof(buf), "%d:%d",
+		       (int) MAJOR(deps->device[i]),
+		       (int) MINOR(deps->device[i])) < 0) {
+			log_error("dm_snprintf failed");
+			goto out_abandon;
+		}
+		if (!dm_pool_grow_object(mem, buf, 0)) {
+			log_error("dm_pool_grow_object failed");
+			goto out_abandon;
+		}
+		if (i + 1 < deps->count && !dm_pool_grow_object(mem, ",", 1)) {
+			log_error("dm_pool_grow_object failed");
+			goto out_abandon;
+		}
+	}
+
+	if (!dm_pool_grow_object(mem, "\0", 1)) {
+		log_error("dm_pool_grow_object failed");
+		goto out_abandon;
+	}
+
+	repstr = dm_pool_end_object(mem);
+	dm_report_field_set_value(field, repstr, repstr);
+	return 1;
+
+      out_abandon:
+	dm_pool_abandon_object(mem);
+	return 0;
+}
+
+static void *_task_get_obj(void *obj)
+{
+	return ((struct dmsetup_report_obj *)obj)->task;
+}
+
+static void *_info_get_obj(void *obj)
+{
+	return ((struct dmsetup_report_obj *)obj)->info;
+}
+
+static void *_deps_get_obj(void *obj)
+{
+	return dm_task_get_deps(((struct dmsetup_report_obj *)obj)->deps_task);
+}
+
+static void *_tree_get_obj(void *obj)
+{
+	return ((struct dmsetup_report_obj *)obj)->tree_node;
+}
+
+static const struct dm_report_object_type _report_types[] = {
+	{ DR_TASK, "Mapped Device Name", "", _task_get_obj },
+	{ DR_INFO, "Mapped Device Information", "", _info_get_obj },
+	{ DR_DEPS, "Mapped Device Relationship Information", "", _deps_get_obj },
+	{ DR_TREE, "Mapped Device Relationship Information", "", _tree_get_obj },
+	{ 0, "", "", NULL },
+};
+
+/* Column definitions */
+#define OFFSET_OF(strct, field) (((char*)&((struct strct*)0)->field) - (char*)0)
+#define STR (DM_REPORT_FIELD_TYPE_STRING)
+#define NUM (DM_REPORT_FIELD_TYPE_NUMBER)
+#define FIELD_O(type, strct, sorttype, head, field, width, func, id, desc) {DR_ ## type, sorttype, OFFSET_OF(strct, field), width, id, head, &_ ## func ## _disp, desc},
+#define FIELD_F(type, sorttype, head, width, func, id, desc) {DR_ ## type, sorttype, 0, width, id, head, &_ ## func ## _disp, desc},
+
+static const struct dm_report_field_type _report_fields[] = {
+/* *INDENT-OFF* */
+FIELD_F(TASK, STR, "Name", 16, dm_name, "name", "Name of mapped device.")
+FIELD_F(TASK, STR, "UUID", 32, dm_uuid, "uuid", "Unique (optional) identifier for mapped device.")
+
+/* FIXME Next one should be INFO */
+FIELD_F(TASK, NUM, "RAhead", 6, dm_read_ahead, "read_ahead", "Read ahead in sectors.")
+
+FIELD_F(INFO, STR, "Stat", 4, dm_info_status, "attr", "(L)ive, (I)nactive, (s)uspended, (r)ead-only, read-(w)rite.")
+FIELD_F(INFO, STR, "Tables", 6, dm_info_table_loaded, "tables_loaded", "Which of the live and inactive table slots are filled.")
+FIELD_F(INFO, STR, "Suspended", 9, dm_info_suspended, "suspended", "Whether the device is suspended.")
+FIELD_F(INFO, STR, "Read-only", 9, dm_info_read_only, "readonly", "Whether the device is read-only or writeable.")
+FIELD_F(INFO, STR, "DevNo", 5, dm_info_devno, "devno", "Device major and minor numbers")
+FIELD_O(INFO, dm_info, NUM, "Maj", major, 3, int32, "major", "Block device major number.")
+FIELD_O(INFO, dm_info, NUM, "Min", minor, 3, int32, "minor", "Block device minor number.")
+FIELD_O(INFO, dm_info, NUM, "Open", open_count, 4, int32, "open", "Number of references to open device, if requested.")
+FIELD_O(INFO, dm_info, NUM, "Targ", target_count, 4, int32, "segments", "Number of segments in live table, if present.")
+FIELD_O(INFO, dm_info, NUM, "Event", event_nr, 6, uint32, "events", "Number of most recent event.")
+
+FIELD_O(DEPS, dm_deps, NUM, "#Devs", count, 5, int32, "device_count", "Number of devices used by this one.")
+FIELD_F(TREE, STR, "DevNames", 8, dm_deps_names, "devs_used", "List of names of mapped devices used by this one.")
+FIELD_F(DEPS, STR, "DevNos", 6, dm_deps, "devnos_used", "List of device numbers of devices used by this one.")
+
+FIELD_F(TREE, NUM, "#Refs", 5, dm_tree_parents_count, "device_ref_count", "Number of mapped devices referencing this one.")
+FIELD_F(TREE, STR, "RefNames", 8, dm_tree_parents_names, "names_using_dev", "List of names of mapped devices using this one.")
+FIELD_F(TREE, STR, "RefDevNos", 9, dm_tree_parents_devs, "devnos_using_dev", "List of device numbers of mapped devices using this one.")
+{0, 0, 0, 0, "", "", NULL, NULL},
+/* *INDENT-ON* */
+};
+
+#undef STR
+#undef NUM
+#undef FIELD_O
+#undef FIELD_F
+
+static const char *default_report_options = "name,major,minor,attr,open,segments,events,uuid";
+
+static int _report_init(struct command *c)
+{
+	char *options = (char *) default_report_options;
+	const char *keys = "";
+	const char *separator = " ";
+	int aligned = 1, headings = 1, buffered = 1, field_prefixes = 0;
+	int quoted = 1, columns_as_rows = 0;
+	uint32_t flags = 0;
+	size_t len = 0;
+	int r = 0;
+
+	/* emulate old dmsetup behaviour */
+	if (_switches[NOHEADINGS_ARG]) {
+		separator = ":";
+		aligned = 0;
+		headings = 0;
+	}
+
+	if (_switches[UNBUFFERED_ARG])
+		buffered = 0;
+
+	if (_switches[ROWS_ARG])
+		columns_as_rows = 1;
+
+	if (_switches[UNQUOTED_ARG])
+		quoted = 0;
+
+	if (_switches[NAMEPREFIXES_ARG]) {
+		aligned = 0;
+		field_prefixes = 1;
+	}
+
+	if (_switches[OPTIONS_ARG] && _string_args[OPTIONS_ARG]) {
+		if (*_string_args[OPTIONS_ARG] != '+')
+			options = _string_args[OPTIONS_ARG];
+		else {
+			len = strlen(default_report_options) +
+			      strlen(_string_args[OPTIONS_ARG]) + 1;
+			if (!(options = dm_malloc(len))) {
+				err("Failed to allocate option string.");
+				return 0;
+			}
+			if (dm_snprintf(options, len, "%s,%s",
+					default_report_options,
+					&_string_args[OPTIONS_ARG][1]) < 0) {
+				err("snprintf failed");
+				goto out;
+			}
+		}
+	}
+
+	if (_switches[SORT_ARG] && _string_args[SORT_ARG]) {
+		keys = _string_args[SORT_ARG];
+		buffered = 1;
+		if (c && (!strcmp(c->name, "status") || !strcmp(c->name, "table"))) {
+			err("--sort is not yet supported with status and table");
+			goto out;
+		}
+	}
+
+	if (_switches[SEPARATOR_ARG] && _string_args[SEPARATOR_ARG]) {
+		separator = _string_args[SEPARATOR_ARG];
+		aligned = 0;
+	}
+
+	if (aligned)
+		flags |= DM_REPORT_OUTPUT_ALIGNED;
+
+	if (buffered)
+		flags |= DM_REPORT_OUTPUT_BUFFERED;
+
+	if (headings)
+		flags |= DM_REPORT_OUTPUT_HEADINGS;
+
+	if (field_prefixes)
+		flags |= DM_REPORT_OUTPUT_FIELD_NAME_PREFIX;
+
+	if (!quoted)
+		flags |= DM_REPORT_OUTPUT_FIELD_UNQUOTED;
+
+	if (columns_as_rows)
+		flags |= DM_REPORT_OUTPUT_COLUMNS_AS_ROWS;
+
+	if (!(_report = dm_report_init(&_report_type,
+				       _report_types, _report_fields,
+				       options, separator, flags, keys, NULL)))
+		goto out;
+
+	if ((_report_type & DR_TREE) && !_build_whole_deptree()) {
+		err("Internal device dependency tree creation failed.");
+		goto out;
+	}
+
+	if (field_prefixes)
+		dm_report_set_output_field_name_prefix(_report, "dm_");
+
+	r = 1;
+
+out:
+	if (len)
+		dm_free(options);
+
+	return r;
+}
+
+/*
+ * List devices
+ */
+static int _ls(int argc, char **argv, void *data)
+{
+	if ((_switches[TARGET_ARG] && _target) ||
+	    (_switches[EXEC_ARG] && _command))
+		return _status(argc, argv, data);
+	else if ((_switches[TREE_ARG]))
+		return _display_tree(argc, argv, data);
+	else
+		return _process_all(argc, argv, 0, _display_name);
+}
+
+static int _help(int argc, char **argv, void *data);
+
+/*
+ * Dispatch table
+ */
+static struct command _commands[] = {
+	{"help", "[-c|-C|--columns]", 0, 0, _help},
+	{"create", "<dev_name> [-j|--major <major> -m|--minor <minor>]\n"
+	  "\t                  [-U|--uid <uid>] [-G|--gid <gid>] [-M|--mode <octal_mode>]\n"
+	  "\t                  [-u|uuid <uuid>]\n"
+	  "\t                  [--notable | --table <table> | <table_file>]",
+	 1, 2, _create},
+	{"remove", "[-f|--force] <device>", 0, 1, _remove},
+	{"remove_all", "[-f|--force]", 0, 0, _remove_all},
+	{"suspend", "[--noflush] <device>", 0, 1, _suspend},
+	{"resume", "<device>", 0, 1, _resume},
+	{"load", "<device> [<table_file>]", 0, 2, _load},
+	{"clear", "<device>", 0, 1, _clear},
+	{"reload", "<device> [<table_file>]", 0, 2, _load},
+	{"rename", "<device> <new_name>", 1, 2, _rename},
+	{"message", "<device> <sector> <message>", 2, -1, _message},
+	{"ls", "[--target <target_type>] [--exec <command>] [--tree [-o options]]", 0, 0, _ls},
+	{"info", "[<device>]", 0, 1, _info},
+	{"deps", "[<device>]", 0, 1, _deps},
+	{"status", "[<device>] [--target <target_type>]", 0, 1, _status},
+	{"table", "[<device>] [--target <target_type>] [--showkeys]", 0, 1, _status},
+	{"wait", "<device> [<event_nr>]", 0, 2, _wait},
+	{"mknodes", "[<device>]", 0, 1, _mknodes},
+	{"targets", "", 0, 0, _targets},
+	{"version", "", 0, 0, _version},
+	{"setgeometry", "<device> <cyl> <head> <sect> <start>", 5, 5, _setgeometry},
+	{NULL, NULL, 0, 0, NULL}
+};
+
+static void _usage(FILE *out)
+{
+	int i;
+
+	fprintf(out, "Usage:\n\n");
+	fprintf(out, "dmsetup [--version] [-v|--verbose [-v|--verbose ...]]\n"
+		"        [-r|--readonly] [--noopencount] [--nolockfs]\n"
+		"        [--readahead [+]<sectors>|auto|none]\n"
+		"        [-c|-C|--columns] [-o <fields>] [-O|--sort <sort_fields>]\n"
+		"        [--nameprefixes] [--noheadings] [--separator <separator>]\n\n");
+	for (i = 0; _commands[i].name; i++)
+		fprintf(out, "\t%s %s\n", _commands[i].name, _commands[i].help);
+	fprintf(out, "\n<device> may be device name or -u <uuid> or "
+		     "-j <major> -m <minor>\n");
+	fprintf(out, "<fields> are comma-separated.  Use 'help -c' for list.\n");
+	fprintf(out, "Table_file contents may be supplied on stdin.\n");
+	fprintf(out, "Tree options are: ascii, utf, vt100; compact, inverted, notrunc;\n"
+		     "                  [no]device, active, open, rw and uuid.\n");
+	fprintf(out, "\n");
+	return;
+}
+
+static void _losetup_usage(FILE *out)
+{
+	fprintf(out, "Usage:\n\n");
+	fprintf(out, "losetup [-d|-a] [-e encryption] "
+		     "[-o offset] [-f|loop_device] [file]\n\n");
+}
+
+static int _help(int argc __attribute((unused)),
+		 char **argv __attribute((unused)),
+		 void *data __attribute((unused)))
+{
+	_usage(stderr);
+
+	if (_switches[COLS_ARG]) {
+		_switches[OPTIONS_ARG] = 1;
+		_string_args[OPTIONS_ARG] = (char *) "help";
+		_switches[SORT_ARG] = 0;
+	
+		(void) _report_init(NULL);
+	}
+
+	return 1;
+}
+
+static struct command *_find_command(const char *name)
+{
+	int i;
+
+	for (i = 0; _commands[i].name; i++)
+		if (!strcmp(_commands[i].name, name))
+			return _commands + i;
+
+	return NULL;
+}
+
+static int _process_tree_options(const char *options)
+{
+	const char *s, *end;
+	struct winsize winsz;
+	size_t len;
+
+	/* Symbol set default */
+	if (!strcmp(nl_langinfo(CODESET), "UTF-8"))
+		_tsym = &_tsym_utf;
+	else
+		_tsym = &_tsym_ascii;
+
+	/* Default */
+	_tree_switches[TR_DEVICE] = 1;
+	_tree_switches[TR_TRUNCATE] = 1;
+
+	/* parse */
+	for (s = options; s && *s; s++) {
+		len = 0;
+		for (end = s; *end && *end != ','; end++, len++)
+			;
+		if (!strncmp(s, "device", len))
+			_tree_switches[TR_DEVICE] = 1;
+		else if (!strncmp(s, "nodevice", len))
+			_tree_switches[TR_DEVICE] = 0;
+		else if (!strncmp(s, "status", len))
+			_tree_switches[TR_STATUS] = 1;
+		else if (!strncmp(s, "table", len))
+			_tree_switches[TR_TABLE] = 1;
+		else if (!strncmp(s, "active", len))
+			_tree_switches[TR_ACTIVE] = 1;
+		else if (!strncmp(s, "open", len))
+			_tree_switches[TR_OPENCOUNT] = 1;
+		else if (!strncmp(s, "uuid", len))
+			_tree_switches[TR_UUID] = 1;
+		else if (!strncmp(s, "rw", len))
+			_tree_switches[TR_RW] = 1;
+		else if (!strncmp(s, "utf", len))
+			_tsym = &_tsym_utf;
+		else if (!strncmp(s, "vt100", len))
+			_tsym = &_tsym_vt100;
+		else if (!strncmp(s, "ascii", len))
+			_tsym = &_tsym_ascii;
+		else if (!strncmp(s, "inverted", len))
+			_tree_switches[TR_BOTTOMUP] = 1;
+		else if (!strncmp(s, "compact", len))
+			_tree_switches[TR_COMPACT] = 1;
+		else if (!strncmp(s, "notrunc", len))
+			_tree_switches[TR_TRUNCATE] = 0;
+		else {
+			fprintf(stderr, "Tree options not recognised: %s\n", s);
+			return 0;
+		}
+		if (!*end)
+			break;
+		s = end;
+	}
+
+	/* Truncation doesn't work well with vt100 drawing char */
+	if (_tsym != &_tsym_vt100)
+		if (ioctl(1, (unsigned long) TIOCGWINSZ, &winsz) >= 0 && winsz.ws_col > 3)
+			_termwidth = winsz.ws_col - 3;
+
+	return 1;
+}
+
+/*
+ * Returns the full absolute path, or NULL if the path could
+ * not be resolved.
+ */
+static char *_get_abspath(const char *path)
+{
+	char *_path;
+
+#ifdef HAVE_CANONICALIZE_FILE_NAME
+	_path = canonicalize_file_name(path);
+#else
+	/* FIXME Provide alternative */
+#endif
+	return _path;
+}
+
+static char *parse_loop_device_name(const char *dev, const char *dev_dir)
+{
+	char *buf;
+	char *device;
+
+	if (!(buf = dm_malloc(PATH_MAX)))
+		return NULL;
+
+	if (dev[0] == '/') {
+		if (!(device = _get_abspath(dev)))
+			goto error;
+
+		if (strncmp(device, dev_dir, strlen(dev_dir)))
+			goto error;
+
+		/* If dev_dir does not end in a slash, ensure that the
+		   following byte in the device string is "/".  */
+		if (dev_dir[strlen(dev_dir) - 1] != '/' &&
+		    device[strlen(dev_dir)] != '/')
+			goto error;
+
+		strncpy(buf, strrchr(device, '/') + 1, (size_t) PATH_MAX);
+		dm_free(device);
+
+	} else {
+		/* check for device number */
+		if (!strncmp(dev, "loop", strlen("loop")))
+			strncpy(buf, dev, (size_t) PATH_MAX);
+		else
+			goto error;
+	}
+
+	return buf;
+
+error:
+	return NULL;
+}
+
+/*
+ *  create a table for a mapped device using the loop target.
+ */
+static int _loop_table(char *table, size_t tlen, char *file,
+		       char *dev __attribute((unused)), off_t off)
+{
+	struct stat fbuf;
+	off_t size, sectors;
+	int fd = -1;
+#ifdef HAVE_SYS_STATVFS_H
+	struct statvfs fsbuf;
+	off_t blksize;
+#endif
+
+	if (!_switches[READ_ONLY])
+		fd = open(file, O_RDWR);
+
+	if (fd < 0) {
+		_switches[READ_ONLY]++;
+		fd = open(file, O_RDONLY);
+	}
+
+	if (fd < 0)
+		goto error;
+
+	if (fstat(fd, &fbuf))
+		goto error;
+
+	size = (fbuf.st_size - off);
+	sectors = size >> SECTOR_SHIFT;
+
+	if (_switches[VERBOSE_ARG])
+		fprintf(stderr, "losetup: set loop size to %llukB "
+			"(%llu sectors)\n", (long long unsigned) sectors >> 1,
+			(long long unsigned) sectors);
+
+#ifdef HAVE_SYS_STATVFS_H
+	if (fstatvfs(fd, &fsbuf))
+		goto error;
+
+	/* FIXME Fragment size currently unused */
+	blksize = fsbuf.f_frsize;
+#endif
+
+	close(fd);
+
+	if (dm_snprintf(table, tlen, "%llu %llu loop %s %llu\n", 0ULL,
+			(long long unsigned)sectors, file, off) < 0)
+		return 0;
+
+	if (_switches[VERBOSE_ARG] > 1)
+		fprintf(stderr, "Table: %s\n", table);
+
+	return 1;
+
+error:
+	if (fd > -1)
+		close(fd);
+	return 0;
+}
+
+static int _process_losetup_switches(const char *base, int *argc, char ***argv,
+				     const char *dev_dir)
+{
+	static int ind;
+	int c;
+	int encrypt_loop = 0, delete = 0, find = 0, show_all = 0;
+	char *device_name = NULL;
+	char *loop_file = NULL;
+	off_t offset = 0;
+
+#ifdef HAVE_GETOPTLONG
+	static struct option long_options[] = {
+		{0, 0, 0, 0}
+	};
+#endif
+
+	optarg = 0;
+	optind = OPTIND_INIT;
+	while ((ind = -1, c = GETOPTLONG_FN(*argc, *argv, "ade:fo:v",
+					    long_options, NULL)) != -1 ) {
+		if (c == ':' || c == '?')
+			return 0;
+		if (c == 'a')
+			show_all++;
+		if (c == 'd')
+			delete++;
+		if (c == 'e')
+			encrypt_loop++;
+		if (c == 'f')
+			find++;
+		if (c == 'o')
+			offset = atoi(optarg);
+		if (c == 'v')
+			_switches[VERBOSE_ARG]++;
+	}
+
+	*argv += optind ;
+	*argc -= optind ;
+
+	if (encrypt_loop){
+		fprintf(stderr, "%s: Sorry, cryptoloop is not yet implemented "
+				"in this version.\n", base);
+		return 0;
+	}
+
+	if (show_all) {
+		fprintf(stderr, "%s: Sorry, show all is not yet implemented "
+				"in this version.\n", base);
+		return 0;
+	}
+
+	if (find) {
+		fprintf(stderr, "%s: Sorry, find is not yet implemented "
+				"in this version.\n", base);
+		if (!*argc)
+			return 0;
+	}
+
+	if (!*argc) {
+		fprintf(stderr, "%s: Please specify loop_device.\n", base);
+		_losetup_usage(stderr);
+		return 0;
+	}
+
+	if (!(device_name = parse_loop_device_name((*argv)[0], dev_dir))) {
+		fprintf(stderr, "%s: Could not parse loop_device %s\n",
+			base, (*argv)[0]);
+		_losetup_usage(stderr);
+		return 0;
+	}
+
+	if (delete) {
+		*argc = 2;
+
+		(*argv)[1] = device_name;
+		(*argv)[0] = (char *) "remove";
+
+		return 1;
+	}
+
+	if (*argc != 2) {
+		fprintf(stderr, "%s: Too few arguments\n", base);
+		_losetup_usage(stderr);
+		dm_free(device_name);
+		return 0;
+	}
+
+	/* FIXME move these to make them available to native dmsetup */
+	if (!(loop_file = _get_abspath((*argv)[(find) ? 0 : 1]))) {
+		fprintf(stderr, "%s: Could not parse loop file name %s\n",
+			base, (*argv)[1]);
+		_losetup_usage(stderr);
+		dm_free(device_name);
+		return 0;
+	}
+
+	/* FIXME Missing free */
+	_table = dm_malloc(LOOP_TABLE_SIZE);
+	if (!_loop_table(_table, (size_t) LOOP_TABLE_SIZE, loop_file, device_name, offset)) {
+		fprintf(stderr, "Could not build device-mapper table for %s\n", (*argv)[0]);
+		dm_free(device_name);
+		return 0;
+	}
+	_switches[TABLE_ARG]++;
+
+	(*argv)[0] = (char *) "create";
+	(*argv)[1] = device_name ;
+
+	return 1;
+}
+
+static int _process_switches(int *argc, char ***argv, const char *dev_dir)
+{
+	char *base, *namebase, *s;
+	static int ind;
+	int c, r;
+
+#ifdef HAVE_GETOPTLONG
+	static struct option long_options[] = {
+		{"readonly", 0, &ind, READ_ONLY},
+		{"columns", 0, &ind, COLS_ARG},
+		{"exec", 1, &ind, EXEC_ARG},
+		{"force", 0, &ind, FORCE_ARG},
+		{"gid", 1, &ind, GID_ARG},
+		{"major", 1, &ind, MAJOR_ARG},
+		{"minor", 1, &ind, MINOR_ARG},
+		{"mode", 1, &ind, MODE_ARG},
+		{"nameprefixes", 0, &ind, NAMEPREFIXES_ARG},
+		{"noflush", 0, &ind, NOFLUSH_ARG},
+		{"noheadings", 0, &ind, NOHEADINGS_ARG},
+		{"nolockfs", 0, &ind, NOLOCKFS_ARG},
+		{"noopencount", 0, &ind, NOOPENCOUNT_ARG},
+		{"notable", 0, &ind, NOTABLE_ARG},
+		{"options", 1, &ind, OPTIONS_ARG},
+		{"readahead", 1, &ind, READAHEAD_ARG},
+		{"rows", 0, &ind, ROWS_ARG},
+		{"separator", 1, &ind, SEPARATOR_ARG},
+		{"showkeys", 0, &ind, SHOWKEYS_ARG},
+		{"sort", 1, &ind, SORT_ARG},
+		{"table", 1, &ind, TABLE_ARG},
+		{"target", 1, &ind, TARGET_ARG},
+		{"tree", 0, &ind, TREE_ARG},
+		{"uid", 1, &ind, UID_ARG},
+		{"uuid", 1, &ind, UUID_ARG},
+		{"unbuffered", 0, &ind, UNBUFFERED_ARG},
+		{"unquoted", 0, &ind, UNQUOTED_ARG},
+		{"verbose", 1, &ind, VERBOSE_ARG},
+		{"version", 0, &ind, VERSION_ARG},
+		{0, 0, 0, 0}
+	};
+#else
+	struct option long_options;
+#endif
+
+	/*
+	 * Zero all the index counts.
+	 */
+	memset(&_switches, 0, sizeof(_switches));
+	memset(&_int_args, 0, sizeof(_int_args));
+	_read_ahead_flags = 0;
+
+	namebase = strdup((*argv)[0]);
+	base = basename(namebase);
+
+	if (!strcmp(base, "devmap_name")) {
+		free(namebase);
+		_switches[COLS_ARG]++;
+		_switches[NOHEADINGS_ARG]++;
+		_switches[OPTIONS_ARG]++;
+		_switches[MAJOR_ARG]++;
+		_switches[MINOR_ARG]++;
+		_string_args[OPTIONS_ARG] = (char *) "name";
+
+		if (*argc == 3) {
+			_int_args[MAJOR_ARG] = atoi((*argv)[1]);
+			_int_args[MINOR_ARG] = atoi((*argv)[2]);
+			*argc -= 2;
+			*argv += 2;
+		} else if ((*argc == 2) &&
+			   (2 == sscanf((*argv)[1], "%i:%i",
+					&_int_args[MAJOR_ARG],
+					&_int_args[MINOR_ARG]))) {
+			*argc -= 1;
+			*argv += 1;
+		} else {
+			fprintf(stderr, "Usage: devmap_name <major> <minor>\n");
+			return 0;
+		}
+
+		(*argv)[0] = (char *) "info";
+		return 1;
+	}
+
+	if (!strcmp(base, "losetup") || !strcmp(base, "dmlosetup")){
+		r = _process_losetup_switches(base, argc, argv, dev_dir);
+		free(namebase);
+		return r;
+	}
+
+	free(namebase);
+
+	optarg = 0;
+	optind = OPTIND_INIT;
+	while ((ind = -1, c = GETOPTLONG_FN(*argc, *argv, "cCfGj:m:Mno:O:ru:Uv",
+					    long_options, NULL)) != -1) {
+		if (c == ':' || c == '?')
+			return 0;
+		if (c == 'c' || c == 'C' || ind == COLS_ARG)
+			_switches[COLS_ARG]++;
+		if (c == 'f' || ind == FORCE_ARG)
+			_switches[FORCE_ARG]++;
+		if (c == 'r' || ind == READ_ONLY)
+			_switches[READ_ONLY]++;
+		if (c == 'j' || ind == MAJOR_ARG) {
+			_switches[MAJOR_ARG]++;
+			_int_args[MAJOR_ARG] = atoi(optarg);
+		}
+		if (c == 'm' || ind == MINOR_ARG) {
+			_switches[MINOR_ARG]++;
+			_int_args[MINOR_ARG] = atoi(optarg);
+		}
+		if (c == 'n' || ind == NOTABLE_ARG)
+			_switches[NOTABLE_ARG]++;
+		if (c == 'o' || ind == OPTIONS_ARG) {
+			_switches[OPTIONS_ARG]++;
+			_string_args[OPTIONS_ARG] = optarg;
+		}
+		if (ind == SEPARATOR_ARG) {
+			_switches[SEPARATOR_ARG]++;
+			_string_args[SEPARATOR_ARG] = optarg;
+		}
+		if (c == 'O' || ind == SORT_ARG) {
+			_switches[SORT_ARG]++;
+			_string_args[SORT_ARG] = optarg;
+		}
+		if (c == 'v' || ind == VERBOSE_ARG)
+			_switches[VERBOSE_ARG]++;
+		if (c == 'u' || ind == UUID_ARG) {
+			_switches[UUID_ARG]++;
+			_uuid = optarg;
+		}
+		if (c == 'G' || ind == GID_ARG) {
+			_switches[GID_ARG]++;
+			_int_args[GID_ARG] = atoi(optarg);
+		}
+		if (c == 'U' || ind == UID_ARG) {
+			_switches[UID_ARG]++;
+			_int_args[UID_ARG] = atoi(optarg);
+		}
+		if (c == 'M' || ind == MODE_ARG) {
+			_switches[MODE_ARG]++;
+			/* FIXME Accept modes as per chmod */
+			_int_args[MODE_ARG] = (int) strtol(optarg, NULL, 8);
+		}
+		if ((ind == EXEC_ARG)) {
+			_switches[EXEC_ARG]++;
+			_command = optarg;
+		}
+		if ((ind == TARGET_ARG)) {
+			_switches[TARGET_ARG]++;
+			_target = optarg;
+		}
+		if ((ind == NAMEPREFIXES_ARG))
+			_switches[NAMEPREFIXES_ARG]++;
+		if ((ind == NOFLUSH_ARG))
+			_switches[NOFLUSH_ARG]++;
+		if ((ind == NOHEADINGS_ARG))
+			_switches[NOHEADINGS_ARG]++;
+		if ((ind == NOLOCKFS_ARG))
+			_switches[NOLOCKFS_ARG]++;
+		if ((ind == NOOPENCOUNT_ARG))
+			_switches[NOOPENCOUNT_ARG]++;
+		if ((ind == READAHEAD_ARG)) {
+			_switches[READAHEAD_ARG]++;
+			if (!strcasecmp(optarg, "auto"))
+				_int_args[READAHEAD_ARG] = DM_READ_AHEAD_AUTO;
+			else if (!strcasecmp(optarg, "none"))
+                		_int_args[READAHEAD_ARG] = DM_READ_AHEAD_NONE;
+			else {
+				for (s = optarg; isspace(*s); s++)
+					;
+				if (*s == '+')
+					_read_ahead_flags = DM_READ_AHEAD_MINIMUM_FLAG;
+				_int_args[READAHEAD_ARG] = atoi(optarg);
+				if (_int_args[READAHEAD_ARG] < -1) {
+					log_error("Negative read ahead value "
+						  "(%d) is not understood.",
+						  _int_args[READAHEAD_ARG]);
+					return 0;
+				}
+			}
+		}
+		if ((ind == ROWS_ARG))
+			_switches[ROWS_ARG]++;
+		if ((ind == SHOWKEYS_ARG))
+			_switches[SHOWKEYS_ARG]++;
+		if ((ind == TABLE_ARG)) {
+			_switches[TABLE_ARG]++;
+			_table = optarg;
+		}
+		if ((ind == TREE_ARG))
+			_switches[TREE_ARG]++;
+		if ((ind == UNQUOTED_ARG))
+			_switches[UNQUOTED_ARG]++;
+		if ((ind == VERSION_ARG))
+			_switches[VERSION_ARG]++;
+	}
+
+	if (_switches[VERBOSE_ARG] > 1)
+		dm_log_init_verbose(_switches[VERBOSE_ARG] - 1);
+
+	if ((_switches[MAJOR_ARG] && !_switches[MINOR_ARG]) ||
+	    (!_switches[MAJOR_ARG] && _switches[MINOR_ARG])) {
+		fprintf(stderr, "Please specify both major number and "
+				"minor number.\n");
+		return 0;
+	}
+
+	if (_switches[TREE_ARG] && !_process_tree_options(_string_args[OPTIONS_ARG]))
+		return 0;
+
+	if (_switches[TABLE_ARG] && _switches[NOTABLE_ARG]) {
+		fprintf(stderr, "--table and --notable are incompatible.\n");
+		return 0;
+	}
+
+	*argv += optind;
+	*argc -= optind;
+	return 1;
+}
+
+int main(int argc, char **argv)
+{
+	struct command *c;
+	int r = 1;
+	const char *dev_dir;
+
+	(void) setlocale(LC_ALL, "");
+
+	dev_dir = getenv ("DM_DEV_DIR");
+	if (dev_dir && *dev_dir) {
+		if (!dm_set_dev_dir(dev_dir)) {
+			fprintf(stderr, "Invalid DM_DEV_DIR environment variable value.\n");
+			goto out;
+		}
+	} else
+		dev_dir = DEFAULT_DM_DEV_DIR;
+
+	if (!_process_switches(&argc, &argv, dev_dir)) {
+		fprintf(stderr, "Couldn't process command line.\n");
+		goto out;
+	}
+
+	if (_switches[VERSION_ARG]) {
+		c = _find_command("version");
+		goto doit;
+	}
+
+	if (argc == 0) {
+		_usage(stderr);
+		goto out;
+	}
+
+	if (!(c = _find_command(argv[0]))) {
+		fprintf(stderr, "Unknown command\n");
+		_usage(stderr);
+		goto out;
+	}
+
+	if (argc < c->min_args + 1 ||
+	    (c->max_args >= 0 && argc > c->max_args + 1)) {
+		fprintf(stderr, "Incorrect number of arguments\n");
+		_usage(stderr);
+		goto out;
+	}
+
+	if (_switches[COLS_ARG] && !_report_init(c))
+		goto out;
+
+      doit:
+	if (!c->fn(argc, argv, NULL)) {
+		fprintf(stderr, "Command failed\n");
+		goto out;
+	}
+
+	r = 0;
+
+out:
+	if (_report) {
+		dm_report_output(_report);
+		dm_report_free(_report);
+	}
+
+	if (_dtree)
+		dm_tree_free(_dtree);
+
+	return r;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/dumpconfig.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/dumpconfig.c
diff -N src/external/gpl2/lvm2tools/dist/tools/dumpconfig.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/dumpconfig.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,31 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+int dumpconfig(struct cmd_context *cmd, int argc, char **argv)
+{
+	const char *file = NULL;
+
+	if (arg_count(cmd, file_ARG))
+		file = arg_str_value(cmd, file_ARG, "");
+
+	if (!write_config_file(cmd->cft, file, argc, argv))
+		return ECMD_FAILED;
+
+	return ECMD_PROCESSED;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/formats.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/formats.c
diff -N src/external/gpl2/lvm2tools/dist/tools/formats.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/formats.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,26 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+int formats(struct cmd_context *cmd, int argc __attribute((unused)),
+	    char **argv __attribute((unused)))
+{
+	display_formats(cmd);
+
+	return ECMD_PROCESSED;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/lvchange.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/lvchange.c
diff -N src/external/gpl2/lvm2tools/dist/tools/lvchange.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/lvchange.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,738 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+static int lvchange_permission(struct cmd_context *cmd,
+			       struct logical_volume *lv)
+{
+	uint32_t lv_access;
+	struct lvinfo info;
+
+	lv_access = arg_uint_value(cmd, permission_ARG, 0);
+
+	if ((lv_access & LVM_WRITE) && (lv->status & LVM_WRITE)) {
+		log_error("Logical volume \"%s\" is already writable",
+			  lv->name);
+		return 0;
+	}
+
+	if (!(lv_access & LVM_WRITE) && !(lv->status & LVM_WRITE)) {
+		log_error("Logical volume \"%s\" is already read only",
+			  lv->name);
+		return 0;
+	}
+
+	if ((lv->status & MIRRORED) && (vg_is_clustered(lv->vg)) &&
+	    lv_info(cmd, lv, &info, 0, 0) && info.exists) {
+		log_error("Cannot change permissions of mirror \"%s\" "
+			  "while active.", lv->name);
+		return 0;
+	}
+
+	if (lv_access & LVM_WRITE) {
+		lv->status |= LVM_WRITE;
+		log_verbose("Setting logical volume \"%s\" read/write",
+			    lv->name);
+	} else {
+		lv->status &= ~LVM_WRITE;
+		log_verbose("Setting logical volume \"%s\" read-only",
+			    lv->name);
+	}
+
+	log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
+	if (!vg_write(lv->vg))
+		return_0;
+
+	backup(lv->vg);
+
+	if (!suspend_lv(cmd, lv)) {
+		log_error("Failed to lock %s", lv->name);
+		vg_revert(lv->vg);
+		return 0;
+	}
+
+	if (!vg_commit(lv->vg)) {
+		resume_lv(cmd, lv);
+		return 0;
+	}
+
+	log_very_verbose("Updating permissions for \"%s\" in kernel", lv->name);
+	if (!resume_lv(cmd, lv)) {
+		log_error("Problem reactivating %s", lv->name);
+		return 0;
+	}
+
+	return 1;
+}
+
+static int lvchange_monitoring(struct cmd_context *cmd,
+			       struct logical_volume *lv)
+{
+	struct lvinfo info;
+
+	if (!lv_info(cmd, lv, &info, 0, 0) || !info.exists) {
+		log_error("Logical volume, %s, is not active", lv->name);
+		return 0;
+	}
+
+	/* do not monitor pvmove lv's */
+	if (lv->status & PVMOVE)
+		return 1;
+
+	if ((dmeventd_monitor_mode() != DMEVENTD_MONITOR_IGNORE) &&
+	    !monitor_dev_for_events(cmd, lv, dmeventd_monitor_mode()))
+		stack;
+
+	return 1;
+}
+
+static int lvchange_availability(struct cmd_context *cmd,
+				 struct logical_volume *lv)
+{
+	int activate;
+	const char *pvname;
+	char *lv_full_name;
+	uint32_t len;
+
+	activate = arg_uint_value(cmd, available_ARG, 0);
+
+	if (activate == CHANGE_ALN) {
+		log_verbose("Deactivating logical volume \"%s\" locally",
+			    lv->name);
+		if (!deactivate_lv_local(cmd, lv))
+			return_0;
+	} else if (activate == CHANGE_AN) {
+		log_verbose("Deactivating logical volume \"%s\"", lv->name);
+		if (!deactivate_lv(cmd, lv))
+			return_0;
+	} else {
+		if (lockingfailed() && (vg_is_clustered(lv->vg))) {
+			log_verbose("Locking failed: ignoring clustered "
+				    "logical volume %s", lv->name);
+			return 0;
+		}
+
+		if (lv_is_origin(lv) || (activate == CHANGE_AE)) {
+			log_verbose("Activating logical volume \"%s\" "
+				    "exclusively", lv->name);
+			if (!activate_lv_excl(cmd, lv))
+				return_0;
+		} else if (activate == CHANGE_ALY) {
+			log_verbose("Activating logical volume \"%s\" locally",
+				    lv->name);
+			if (!activate_lv_local(cmd, lv))
+				return_0;
+		} else {
+			log_verbose("Activating logical volume \"%s\"",
+				    lv->name);
+			if (!activate_lv(cmd, lv))
+				return_0;
+		}
+
+		if ((lv->status & LOCKED) &&
+		    (pvname = get_pvmove_pvname_from_lv(lv))) {
+			log_verbose("Spawning background pvmove process for %s",
+				    pvname);
+			pvmove_poll(cmd, pvname, 1);
+		}
+
+		if (lv->status & CONVERTING) {
+			len = strlen(lv->vg->name) + strlen(lv->name) + 2;
+			if (!(lv_full_name = alloca(len)))
+				return_0;
+			if (!dm_snprintf(lv_full_name, len, "%s/%s",
+					 lv->vg->name, lv->name))
+				return_0;
+			log_verbose("Spawning background lvconvert process for %s",
+				    lv->name);
+			lvconvert_poll(cmd, lv_full_name, 1);
+		}
+	}
+
+	return 1;
+}
+
+static int lvchange_refresh(struct cmd_context *cmd, struct logical_volume *lv)
+{
+	log_verbose("Refreshing logical volume \"%s\" (if active)", lv->name);
+	if (!suspend_lv(cmd, lv) || !resume_lv(cmd, lv))
+		return 0;
+
+	return 1;
+}
+
+static int lvchange_resync(struct cmd_context *cmd,
+			      struct logical_volume *lv)
+{
+	int active = 0;
+	int monitored;
+	struct lvinfo info;
+	struct logical_volume *log_lv;
+
+	if (!(lv->status & MIRRORED)) {
+		log_error("Unable to resync %s because it is not mirrored.",
+			  lv->name);
+		return 1;
+	}
+
+	if (lv->status & PVMOVE) {
+		log_error("Unable to resync pvmove volume %s", lv->name);
+		return 0;
+	}
+
+	if (lv->status & LOCKED) {
+		log_error("Unable to resync locked volume %s", lv->name);
+		return 0;
+	}
+
+	if (lv_info(cmd, lv, &info, 1, 0)) {
+		if (info.open_count) {
+			log_error("Can't resync open logical volume \"%s\"",
+				  lv->name);
+			return ECMD_FAILED;
+		}
+
+		if (info.exists) {
+			if (!arg_count(cmd, yes_ARG) &&
+			    yes_no_prompt("Do you really want to deactivate "
+					  "logical volume %s to resync it? [y/n]: ",
+					  lv->name) == 'n') {
+				log_print("Logical volume \"%s\" not resynced",
+					  lv->name);
+				return ECMD_FAILED;
+			}
+
+			if (sigint_caught())
+				return ECMD_FAILED;
+
+			active = 1;
+		}
+	}
+
+	/* Activate exclusively to ensure no nodes still have LV active */
+	monitored = dmeventd_monitor_mode();
+	init_dmeventd_monitor(0);
+
+	if (vg_is_clustered(lv->vg) && !activate_lv_excl(cmd, lv)) {
+		log_error("Can't get exclusive access to clustered volume %s",
+			  lv->name);
+		return ECMD_FAILED;
+	}
+
+	if (!deactivate_lv(cmd, lv)) {
+		log_error("Unable to deactivate %s for resync", lv->name);
+		return 0;
+	}
+
+	init_dmeventd_monitor(monitored);
+
+	log_lv = first_seg(lv)->log_lv;
+
+	log_very_verbose("Starting resync of %s%s%s mirror \"%s\"",
+			 (active) ? "active " : "",
+			 vg_is_clustered(lv->vg) ? "clustered " : "",
+			 (log_lv) ? "disk-logged" : "core-logged",
+			 lv->name);
+
+	/*
+	 * If this mirror has a core log (i.e. !log_lv),
+	 * then simply deactivating/activating will cause
+	 * it to reset the sync status.  We only need to
+	 * worry about persistent logs.
+	 */
+	if (!log_lv && !(lv->status & MIRROR_NOTSYNCED)) {
+		if (active && !activate_lv(cmd, lv)) {
+			log_error("Failed to reactivate %s to resynchronize "
+				  "mirror", lv->name);
+			return 0;
+		}
+		return 1;
+	}
+
+	lv->status &= ~MIRROR_NOTSYNCED;
+
+	if (log_lv) {
+		/* Separate mirror log so we can clear it */
+		detach_mirror_log(first_seg(lv));
+
+		if (!vg_write(lv->vg)) {
+			log_error("Failed to write intermediate VG metadata.");
+			if (!attach_mirror_log(first_seg(lv), log_lv))
+				stack;
+			if (active && !activate_lv(cmd, lv))
+				stack;
+			return 0;
+		}
+
+		backup(lv->vg);
+
+		if (!vg_commit(lv->vg)) {
+			log_error("Failed to commit intermediate VG metadata.");
+			if (!attach_mirror_log(first_seg(lv), log_lv))
+				stack;
+			if (active && !activate_lv(cmd, lv))
+				stack;
+			return 0;
+		}
+
+		if (!activate_lv(cmd, log_lv)) {
+			log_error("Unable to activate %s for mirror log resync",
+				  log_lv->name);
+			return 0;
+		}
+
+		log_very_verbose("Clearing log device %s", log_lv->name);
+		if (!set_lv(cmd, log_lv, log_lv->size, 0)) {
+			log_error("Unable to reset sync status for %s", lv->name);
+			if (!deactivate_lv(cmd, log_lv))
+				log_error("Failed to deactivate log LV after "
+					  "wiping failed");
+			return 0;
+		}
+
+		if (!deactivate_lv(cmd, log_lv)) {
+			log_error("Unable to deactivate log LV %s after wiping "
+				  "for resync", log_lv->name);
+			return 0;
+		}
+
+		/* Put mirror log back in place */
+		if (!attach_mirror_log(first_seg(lv), log_lv))
+			stack;
+	}
+
+	log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
+	if (!vg_write(lv->vg) || !vg_commit(lv->vg)) {
+		log_error("Failed to update metadata on disk.");
+		return 0;
+	}
+
+	if (active && !activate_lv(cmd, lv)) {
+		log_error("Failed to reactivate %s after resync", lv->name);
+		return 0;
+	}
+
+	return 1;
+}
+
+static int lvchange_alloc(struct cmd_context *cmd, struct logical_volume *lv)
+{
+	int want_contiguous = 0;
+	alloc_policy_t alloc;
+
+	want_contiguous = strcmp(arg_str_value(cmd, contiguous_ARG, "n"), "n");
+	alloc = want_contiguous ? ALLOC_CONTIGUOUS : ALLOC_INHERIT;
+	alloc = arg_uint_value(cmd, alloc_ARG, alloc);
+
+	if (alloc == lv->alloc) {
+		log_error("Allocation policy of logical volume \"%s\" is "
+			  "already %s", lv->name, get_alloc_string(alloc));
+		return 0;
+	}
+
+	lv->alloc = alloc;
+
+	/* FIXME If contiguous, check existing extents already are */
+
+	log_verbose("Setting contiguous allocation policy for \"%s\" to %s",
+		    lv->name, get_alloc_string(alloc));
+
+	log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
+
+	if (!vg_write(lv->vg))
+		return_0;
+
+	backup(lv->vg);
+
+	/* No need to suspend LV for this change */
+	if (!vg_commit(lv->vg))
+		return_0;
+
+	return 1;
+}
+
+static int lvchange_readahead(struct cmd_context *cmd,
+			      struct logical_volume *lv)
+{
+	unsigned read_ahead = 0;
+	unsigned pagesize = (unsigned) lvm_getpagesize() >> SECTOR_SHIFT;
+
+	read_ahead = arg_uint_value(cmd, readahead_ARG, 0);
+
+	if (read_ahead != DM_READ_AHEAD_AUTO &&
+	    (lv->vg->fid->fmt->features & FMT_RESTRICTED_READAHEAD) &&
+	    (read_ahead < 2 || read_ahead > 120)) {
+		log_error("Metadata only supports readahead values between 2 and 120.");
+		return 0;
+	}
+
+	if (read_ahead != DM_READ_AHEAD_AUTO &&
+	    read_ahead != DM_READ_AHEAD_NONE && read_ahead % pagesize) {
+		read_ahead = (read_ahead / pagesize) * pagesize;
+		log_verbose("Rounding down readahead to %u sectors, a multiple "
+			    "of page size %u.", read_ahead, pagesize);
+	}
+
+	if (lv->read_ahead == read_ahead) {
+		if (read_ahead == DM_READ_AHEAD_AUTO)
+			log_error("Read ahead is already auto for \"%s\"", lv->name);
+		else
+			log_error("Read ahead is already %u for \"%s\"",
+				  read_ahead, lv->name);
+		return 0;
+	}
+
+	lv->read_ahead = read_ahead;
+
+	log_verbose("Setting read ahead to %u for \"%s\"", read_ahead,
+		    lv->name);
+
+	log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
+	if (!vg_write(lv->vg))
+		return_0;
+
+	backup(lv->vg);
+
+	if (!suspend_lv(cmd, lv)) {
+		log_error("Failed to lock %s", lv->name);
+		vg_revert(lv->vg);
+		return 0;
+	}
+
+	if (!vg_commit(lv->vg)) {
+		resume_lv(cmd, lv);
+		return 0;
+	}
+
+	log_very_verbose("Updating permissions for \"%s\" in kernel", lv->name);
+	if (!resume_lv(cmd, lv)) {
+		log_error("Problem reactivating %s", lv->name);
+		return 0;
+	}
+
+	return 1;
+}
+
+static int lvchange_persistent(struct cmd_context *cmd,
+			       struct logical_volume *lv)
+{
+	struct lvinfo info;
+	int active = 0;
+
+	if (!strcmp(arg_str_value(cmd, persistent_ARG, "n"), "n")) {
+		if (!(lv->status & FIXED_MINOR)) {
+			log_error("Minor number is already not persistent "
+				  "for \"%s\"", lv->name);
+			return 0;
+		}
+		lv->status &= ~FIXED_MINOR;
+		lv->minor = -1;
+		lv->major = -1;
+		log_verbose("Disabling persistent device number for \"%s\"",
+			    lv->name);
+	} else {
+		if (!arg_count(cmd, minor_ARG) && lv->minor < 0) {
+			log_error("Minor number must be specified with -My");
+			return 0;
+		}
+		if (!arg_count(cmd, major_ARG) && lv->major < 0) {
+			log_error("Major number must be specified with -My");
+			return 0;
+		}
+		if (lv_info(cmd, lv, &info, 0, 0) && info.exists)
+			active = 1;
+		if (active && !arg_count(cmd, force_ARG) &&
+		    yes_no_prompt("Logical volume %s will be "
+				  "deactivated temporarily. "
+				  "Continue? [y/n]: ", lv->name) == 'n') {
+			log_print("%s device number not changed.",
+				  lv->name);
+			return 0;
+		}
+
+		if (sigint_caught())
+			return 0;
+
+		log_verbose("Ensuring %s is inactive.", lv->name);
+		if (!deactivate_lv(cmd, lv)) {
+			log_error("%s: deactivation failed", lv->name);
+			return 0;
+		}
+		lv->status |= FIXED_MINOR;
+		lv->minor = arg_int_value(cmd, minor_ARG, lv->minor);
+		lv->major = arg_int_value(cmd, major_ARG, lv->major);
+		log_verbose("Setting persistent device number to (%d, %d) "
+			    "for \"%s\"", lv->major, lv->minor, lv->name);
+
+	}
+
+	log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
+	if (!vg_write(lv->vg))
+		return_0;
+
+	backup(lv->vg);
+
+	if (!vg_commit(lv->vg))
+		return_0;
+
+	if (active) {
+		log_verbose("Re-activating logical volume \"%s\"", lv->name);
+		if (!activate_lv(cmd, lv)) {
+			log_error("%s: reactivation failed", lv->name);
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+static int lvchange_tag(struct cmd_context *cmd, struct logical_volume *lv,
+			int arg)
+{
+	const char *tag;
+
+	if (!(tag = arg_str_value(cmd, arg, NULL))) {
+		log_error("Failed to get tag");
+		return 0;
+	}
+
+	if (!(lv->vg->fid->fmt->features & FMT_TAGS)) {
+		log_error("Logical volume %s/%s does not support tags",
+			  lv->vg->name, lv->name);
+		return 0;
+	}
+
+	if ((arg == addtag_ARG)) {
+		if (!str_list_add(cmd->mem, &lv->tags, tag)) {
+			log_error("Failed to add tag %s to %s/%s",
+				  tag, lv->vg->name, lv->name);
+			return 0;
+		}
+	} else {
+		if (!str_list_del(&lv->tags, tag)) {
+			log_error("Failed to remove tag %s from %s/%s",
+				  tag, lv->vg->name, lv->name);
+			return 0;
+		}
+	}
+
+	log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
+	if (!vg_write(lv->vg))
+		return_0;
+
+	backup(lv->vg);
+
+	/* No need to suspend LV for this change */
+	if (!vg_commit(lv->vg))
+		return_0;
+
+	return 1;
+}
+
+static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
+			   void *handle __attribute((unused)))
+{
+	int doit = 0, docmds = 0;
+	int archived = 0;
+
+	if (!(lv->vg->status & LVM_WRITE) &&
+	    (arg_count(cmd, contiguous_ARG) || arg_count(cmd, permission_ARG) ||
+	     arg_count(cmd, readahead_ARG) || arg_count(cmd, persistent_ARG) ||
+	     arg_count(cmd, alloc_ARG))) {
+		log_error("Only -a permitted with read-only volume "
+			  "group \"%s\"", lv->vg->name);
+		return EINVALID_CMD_LINE;
+	}
+
+	if (lv_is_origin(lv) &&
+	    (arg_count(cmd, contiguous_ARG) || arg_count(cmd, permission_ARG) ||
+	     arg_count(cmd, readahead_ARG) || arg_count(cmd, persistent_ARG) ||
+	     arg_count(cmd, alloc_ARG))) {
+		log_error("Can't change logical volume \"%s\" under snapshot",
+			  lv->name);
+		return ECMD_FAILED;
+	}
+
+	if (lv_is_cow(lv)) {
+		log_error("Can't change snapshot logical volume \"%s\"",
+			  lv->name);
+		return ECMD_FAILED;
+	}
+
+	if (lv->status & PVMOVE) {
+		log_error("Unable to change pvmove LV %s", lv->name);
+		if (arg_count(cmd, available_ARG))
+			log_error("Use 'pvmove --abort' to abandon a pvmove");
+		return ECMD_FAILED;
+	}
+
+	if (lv->status & MIRROR_LOG) {
+		log_error("Unable to change mirror log LV %s directly", lv->name);
+		return ECMD_FAILED;
+	}
+
+	if (lv->status & MIRROR_IMAGE) {
+		log_error("Unable to change mirror image LV %s directly",
+			  lv->name);
+		return ECMD_FAILED;
+	}
+
+	if (!(lv->status & VISIBLE_LV)) {
+		log_error("Unable to change internal LV %s directly",
+			  lv->name);
+		return ECMD_FAILED;
+	}
+
+	init_dmeventd_monitor(arg_int_value(cmd, monitor_ARG,
+					    (cmd->is_static || arg_count(cmd, ignoremonitoring_ARG)) ?
+					    DMEVENTD_MONITOR_IGNORE : DEFAULT_DMEVENTD_MONITOR));
+
+	/* access permission change */
+	if (arg_count(cmd, permission_ARG)) {
+		if (!archive(lv->vg))
+			return ECMD_FAILED;
+		archived = 1;
+		doit += lvchange_permission(cmd, lv);
+		docmds++;
+	}
+
+	/* allocation policy change */
+	if (arg_count(cmd, contiguous_ARG) || arg_count(cmd, alloc_ARG)) {
+		if (!archived && !archive(lv->vg))
+			return ECMD_FAILED;
+		archived = 1;
+		doit += lvchange_alloc(cmd, lv);
+		docmds++;
+	}
+
+	/* read ahead sector change */
+	if (arg_count(cmd, readahead_ARG)) {
+		if (!archived && !archive(lv->vg))
+			return ECMD_FAILED;
+		archived = 1;
+		doit += lvchange_readahead(cmd, lv);
+		docmds++;
+	}
+
+	/* read ahead sector change */
+	if (arg_count(cmd, persistent_ARG)) {
+		if (!archived && !archive(lv->vg))
+			return ECMD_FAILED;
+		archived = 1;
+		doit += lvchange_persistent(cmd, lv);
+		docmds++;
+		if (sigint_caught())
+			return ECMD_FAILED;
+	}
+
+	/* add tag */
+	if (arg_count(cmd, addtag_ARG)) {
+		if (!archived && !archive(lv->vg))
+			return ECMD_FAILED;
+		archived = 1;
+		doit += lvchange_tag(cmd, lv, addtag_ARG);
+		docmds++;
+	}
+
+	/* del tag */
+	if (arg_count(cmd, deltag_ARG)) {
+		if (!archived && !archive(lv->vg))
+			return ECMD_FAILED;
+		archived = 1;
+		doit += lvchange_tag(cmd, lv, deltag_ARG);
+		docmds++;
+	}
+
+	if (doit)
+		log_print("Logical volume \"%s\" changed", lv->name);
+
+	if (arg_count(cmd, resync_ARG))
+		if (!lvchange_resync(cmd, lv))
+			return ECMD_FAILED;
+
+	/* availability change */
+	if (arg_count(cmd, available_ARG)) {
+		if (!lvchange_availability(cmd, lv))
+			return ECMD_FAILED;
+	}
+
+	if (arg_count(cmd, refresh_ARG))
+		if (!lvchange_refresh(cmd, lv))
+			return ECMD_FAILED;
+
+	if (!arg_count(cmd, available_ARG) &&
+	    !arg_count(cmd, refresh_ARG) &&
+	    arg_count(cmd, monitor_ARG)) {
+		if (!lvchange_monitoring(cmd, lv))
+			return ECMD_FAILED;
+	}
+
+	if (doit != docmds)
+		return ECMD_FAILED;
+
+	return ECMD_PROCESSED;
+}
+
+int lvchange(struct cmd_context *cmd, int argc, char **argv)
+{
+	if (!arg_count(cmd, available_ARG) && !arg_count(cmd, contiguous_ARG)
+	    && !arg_count(cmd, permission_ARG) && !arg_count(cmd, readahead_ARG)
+	    && !arg_count(cmd, minor_ARG) && !arg_count(cmd, major_ARG)
+	    && !arg_count(cmd, persistent_ARG) && !arg_count(cmd, addtag_ARG)
+	    && !arg_count(cmd, deltag_ARG) && !arg_count(cmd, refresh_ARG)
+	    && !arg_count(cmd, alloc_ARG) && !arg_count(cmd, monitor_ARG)
+	    && !arg_count(cmd, resync_ARG)) {
+		log_error("Need 1 or more of -a, -C, -j, -m, -M, -p, -r, "
+			  "--resync, --refresh, --alloc, --addtag, --deltag "
+			  "or --monitor");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (arg_count(cmd, ignorelockingfailure_ARG) &&
+	    (arg_count(cmd, contiguous_ARG) || arg_count(cmd, permission_ARG) ||
+	     arg_count(cmd, readahead_ARG) || arg_count(cmd, persistent_ARG) ||
+	     arg_count(cmd, addtag_ARG) || arg_count(cmd, deltag_ARG) ||
+	     arg_count(cmd, refresh_ARG) || arg_count(cmd, alloc_ARG))) {
+		log_error("Only -a permitted with --ignorelockingfailure");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (!argc) {
+		log_error("Please give logical volume path(s)");
+		return EINVALID_CMD_LINE;
+	}
+
+	if ((arg_count(cmd, minor_ARG) || arg_count(cmd, major_ARG)) &&
+	    !arg_count(cmd, persistent_ARG)) {
+		log_error("--major and --minor require -My");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (arg_count(cmd, minor_ARG) && argc != 1) {
+		log_error("Only give one logical volume when specifying minor");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (arg_count(cmd, contiguous_ARG) && arg_count(cmd, alloc_ARG)) {
+		log_error("Only one of --alloc and --contiguous permitted");
+		return EINVALID_CMD_LINE;
+	}
+
+	return process_each_lv(cmd, argc, argv, LCK_VG_WRITE, NULL,
+			       &lvchange_single);
+}
Index: src/external/gpl2/lvm2tools/dist/tools/lvconvert.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/lvconvert.c
diff -N src/external/gpl2/lvm2tools/dist/tools/lvconvert.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/lvconvert.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,784 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+#include "polldaemon.h"
+#include "lv_alloc.h"
+
+struct lvconvert_params {
+	int snapshot;
+	int zero;
+
+	const char *origin;
+	const char *lv_name;
+	const char *lv_name_full;
+	const char *vg_name;
+	int wait_completion;
+	int need_polling;
+
+	uint32_t chunk_size;
+	uint32_t region_size;
+
+	uint32_t mirrors;
+	sign_t mirrors_sign;
+
+	struct segment_type *segtype;
+
+	alloc_policy_t alloc;
+
+	int pv_count;
+	char **pvs;
+	struct dm_list *pvh;
+};
+
+static int _lvconvert_name_params(struct lvconvert_params *lp,
+				  struct cmd_context *cmd,
+				  int *pargc, char ***pargv)
+{
+	char *ptr;
+	const char *vg_name = NULL;
+
+	if (lp->snapshot) {
+		if (!*pargc) {
+			log_error("Please specify a logical volume to act as "
+				  "the snapshot origin.");
+			return 0;
+		}
+
+		lp->origin = *pargv[0];
+		(*pargv)++, (*pargc)--;
+		if (!(lp->vg_name = extract_vgname(cmd, lp->origin))) {
+			log_error("The origin name should include the "
+				  "volume group.");
+			return 0;
+		}
+
+		/* Strip the volume group from the origin */
+		if ((ptr = strrchr(lp->origin, (int) '/')))
+			lp->origin = ptr + 1;
+	}
+
+	if (!*pargc) {
+		log_error("Please provide logical volume path");
+		return 0;
+	}
+
+	lp->lv_name = lp->lv_name_full = (*pargv)[0];
+	(*pargv)++, (*pargc)--;
+
+	if (strchr(lp->lv_name_full, '/') &&
+	    (vg_name = extract_vgname(cmd, lp->lv_name_full)) &&
+	    lp->vg_name && strcmp(vg_name, lp->vg_name)) {
+		log_error("Please use a single volume group name "
+			  "(\"%s\" or \"%s\")", vg_name, lp->vg_name);
+		return 0;
+	}
+
+	if (!lp->vg_name)
+		lp->vg_name = vg_name;
+
+	if (!validate_name(lp->vg_name)) {
+		log_error("Please provide a valid volume group name");
+		return 0;
+	}
+
+	if ((ptr = strrchr(lp->lv_name_full, '/')))
+		lp->lv_name = ptr + 1;
+
+	if (!apply_lvname_restrictions(lp->lv_name))
+		return_0;
+
+	return 1;
+}
+
+static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd,
+			int argc, char **argv)
+{
+	int region_size;
+	int pagesize = lvm_getpagesize();
+
+	memset(lp, 0, sizeof(*lp));
+
+	if (arg_count(cmd, snapshot_ARG) &&
+	    (arg_count(cmd, mirrorlog_ARG) || arg_count(cmd, mirrors_ARG))) {
+		log_error("--snapshots argument cannot be mixed "
+			  "with --mirrors or --log");
+		return 0;
+	}
+
+	if (!arg_count(cmd, background_ARG))
+		lp->wait_completion = 1;
+
+	if (arg_count(cmd, snapshot_ARG))
+		lp->snapshot = 1;
+
+	if (arg_count(cmd, mirrors_ARG)) {
+		lp->mirrors = arg_uint_value(cmd, mirrors_ARG, 0);
+		lp->mirrors_sign = arg_sign_value(cmd, mirrors_ARG, 0);
+	}
+
+	lp->alloc = ALLOC_INHERIT;
+	if (arg_count(cmd, alloc_ARG))
+		lp->alloc = arg_uint_value(cmd, alloc_ARG, lp->alloc);
+
+	if (lp->snapshot) {
+		if (arg_count(cmd, regionsize_ARG)) {
+			log_error("--regionsize is only available with mirrors");
+			return 0;
+		}
+
+		if (arg_sign_value(cmd, chunksize_ARG, 0) == SIGN_MINUS) {
+			log_error("Negative chunk size is invalid");
+			return 0;
+		}
+		lp->chunk_size = arg_uint_value(cmd, chunksize_ARG, 8);
+		if (lp->chunk_size < 8 || lp->chunk_size > 1024 ||
+		    (lp->chunk_size & (lp->chunk_size - 1))) {
+			log_error("Chunk size must be a power of 2 in the "
+				  "range 4K to 512K");
+			return 0;
+		}
+		log_verbose("Setting chunksize to %d sectors.", lp->chunk_size);
+
+		if (!(lp->segtype = get_segtype_from_string(cmd, "snapshot")))
+			return_0;
+
+		lp->zero = strcmp(arg_str_value(cmd, zero_ARG,
+						(lp->segtype->flags &
+						 SEG_CANNOT_BE_ZEROED) ?
+						"n" : "y"), "n");
+
+	} else {	/* Mirrors */
+		if (arg_count(cmd, chunksize_ARG)) {
+			log_error("--chunksize is only available with "
+				  "snapshots");
+			return 0;
+		}
+
+		if (arg_count(cmd, zero_ARG)) {
+			log_error("--zero is only available with snapshots");
+			return 0;
+		}
+
+		/*
+	 	 * --regionsize is only valid if converting an LV into a mirror.
+	 	 * Checked when we know the state of the LV being converted.
+	 	 */
+
+		if (arg_count(cmd, regionsize_ARG)) {
+			if (arg_sign_value(cmd, regionsize_ARG, 0) ==
+				    SIGN_MINUS) {
+				log_error("Negative regionsize is invalid");
+				return 0;
+			}
+			lp->region_size = arg_uint_value(cmd, regionsize_ARG, 0);
+		} else {
+			region_size = 2 * find_config_tree_int(cmd,
+						"activation/mirror_region_size",
+						DEFAULT_MIRROR_REGION_SIZE);
+			if (region_size < 0) {
+				log_error("Negative regionsize in "
+					  "configuration file is invalid");
+				return 0;
+			}
+			lp->region_size = region_size;
+		}
+
+		if (lp->region_size % (pagesize >> SECTOR_SHIFT)) {
+			log_error("Region size (%" PRIu32 ") must be "
+				  "a multiple of machine memory "
+				  "page size (%d)",
+				  lp->region_size, pagesize >> SECTOR_SHIFT);
+			return 0;
+		}
+
+		if (lp->region_size & (lp->region_size - 1)) {
+			log_error("Region size (%" PRIu32
+				  ") must be a power of 2", lp->region_size);
+			return 0;
+		}
+
+		if (!lp->region_size) {
+			log_error("Non-zero region size must be supplied.");
+			return 0;
+		}
+
+		if (!(lp->segtype = get_segtype_from_string(cmd, "mirror")))
+			return_0;
+	}
+
+	if (activation() && lp->segtype->ops->target_present &&
+	    !lp->segtype->ops->target_present(NULL, NULL)) {
+		log_error("%s: Required device-mapper target(s) not "
+			  "detected in your kernel", lp->segtype->name);
+		return 0;
+	}
+
+	if (!_lvconvert_name_params(lp, cmd, &argc, &argv))
+		return_0;
+
+	lp->pv_count = argc;
+	lp->pvs = argv;
+
+	return 1;
+}
+
+
+static struct volume_group *_get_lvconvert_vg(struct cmd_context *cmd,
+					      const char *lv_name)
+{
+	dev_close_all();
+
+        return vg_lock_and_read(cmd, extract_vgname(cmd, lv_name),
+				NULL, LCK_VG_WRITE,
+ 				CLUSTERED | EXPORTED_VG | LVM_WRITE,
+				CORRECT_INCONSISTENT | FAIL_INCONSISTENT);
+}
+
+static struct logical_volume *_get_lvconvert_lv(struct cmd_context *cmd __attribute((unused)),
+						struct volume_group *vg,
+						const char *name,
+						uint32_t lv_type __attribute((unused)))
+{
+	return find_lv(vg, name);
+}
+
+static int _update_lvconvert_mirror(struct cmd_context *cmd __attribute((unused)),
+				    struct volume_group *vg __attribute((unused)),
+				    struct logical_volume *lv __attribute((unused)),
+				    struct dm_list *lvs_changed __attribute((unused)),
+				    unsigned flags __attribute((unused)))
+{
+	/* lvconvert mirror doesn't require periodical metadata update */
+	return 1;
+}
+
+static int _finish_lvconvert_mirror(struct cmd_context *cmd,
+				    struct volume_group *vg,
+				    struct logical_volume *lv,
+				    struct dm_list *lvs_changed __attribute((unused)))
+{
+	if (!collapse_mirrored_lv(lv)) {
+		log_error("Failed to remove temporary sync layer.");
+		return 0;
+	}
+
+	lv->status &= ~CONVERTING;
+
+	log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
+
+	if (!vg_write(vg))
+		return_0;
+
+	backup(vg);
+
+	if (!suspend_lv(cmd, lv)) {
+		log_error("Failed to lock %s", lv->name);
+		vg_revert(vg);
+		return 0;
+	}
+
+	if (!vg_commit(vg)) {
+		resume_lv(cmd, lv);
+		return 0;
+	}
+
+	log_very_verbose("Updating \"%s\" in kernel", lv->name);
+
+	if (!resume_lv(cmd, lv)) {
+		log_error("Problem reactivating %s", lv->name);
+		return 0;
+	}
+
+	log_print("Logical volume %s converted.", lv->name);
+
+	return 1;
+}
+
+static struct poll_functions _lvconvert_mirror_fns = {
+	.get_copy_vg = _get_lvconvert_vg,
+	.get_copy_lv = _get_lvconvert_lv,
+	.update_metadata = _update_lvconvert_mirror,
+	.finish_copy = _finish_lvconvert_mirror,
+};
+
+int lvconvert_poll(struct cmd_context *cmd, const char *lv_name,
+		   unsigned background)
+{
+	return poll_daemon(cmd, lv_name, background, 0, &_lvconvert_mirror_fns,
+			   "Converted");
+}
+
+static int _insert_lvconvert_layer(struct cmd_context *cmd,
+				   struct logical_volume *lv)
+{
+	char *format, *layer_name;
+	size_t len;
+	int i;
+
+	/*
+ 	 * We would like to give the same number for this layer
+ 	 * and the newly added mimage.
+ 	 * However, LV name of newly added mimage is determined *after*
+	 * the LV name of this layer is determined.
+	 *
+	 * So, use generate_lv_name() to generate mimage name first
+	 * and take the number from it.
+	 */
+
+	len = strlen(lv->name) + 32;
+	if (!(format = alloca(len)) ||
+	    !(layer_name = alloca(len)) ||
+	    dm_snprintf(format, len, "%s_mimage_%%d", lv->name) < 0) {
+		log_error("lvconvert: layer name allocation failed.");
+		return 0;
+	}
+
+	if (!generate_lv_name(lv->vg, format, layer_name, len) ||
+	    sscanf(layer_name, format, &i) != 1) {
+		log_error("lvconvert: layer name generation failed.");
+		return 0;
+	}
+
+	if (dm_snprintf(layer_name, len, MIRROR_SYNC_LAYER "_%d", i) < 0) {
+		log_error("layer name allocation failed.");
+		return 0;
+	}
+
+	if (!insert_layer_for_lv(cmd, lv, 0, layer_name)) {
+		log_error("Failed to insert resync layer");
+		return 0;
+	}
+
+	return 1;
+}
+
+/* walk down the stacked mirror LV to the original mirror LV */
+static struct logical_volume *_original_lv(struct logical_volume *lv)
+{
+	struct logical_volume *next_lv = lv, *tmp_lv;
+
+	while ((tmp_lv = find_temporary_mirror(next_lv)))
+		next_lv = tmp_lv;
+
+	return next_lv;
+}
+
+static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * lv,
+			     struct lvconvert_params *lp)
+{
+	struct lv_segment *seg;
+	uint32_t existing_mirrors;
+	const char *mirrorlog;
+	unsigned corelog = 0;
+	struct logical_volume *original_lv;
+
+	seg = first_seg(lv);
+	existing_mirrors = lv_mirror_count(lv);
+
+	/* If called with no argument, try collapsing the resync layers */
+	if (!arg_count(cmd, mirrors_ARG) && !arg_count(cmd, mirrorlog_ARG) &&
+	    !arg_count(cmd, corelog_ARG) && !arg_count(cmd, regionsize_ARG)) {
+		lp->need_polling = 1;
+		return 1;
+	}
+
+	/*
+	 * Adjust required number of mirrors
+	 *
+	 * We check mirrors_ARG again to see if it
+	 * was supplied.  If not, they want the mirror
+	 * count to remain the same.  They may be changing
+	 * the logging type.
+	 */
+	if (!arg_count(cmd, mirrors_ARG))
+		lp->mirrors = existing_mirrors;
+	else if (lp->mirrors_sign == SIGN_PLUS)
+		lp->mirrors = existing_mirrors + lp->mirrors;
+	else if (lp->mirrors_sign == SIGN_MINUS)
+		lp->mirrors = existing_mirrors - lp->mirrors;
+	else
+		lp->mirrors += 1;
+
+	/*
+	 * Did the user try to subtract more legs than available?
+	 */
+	if (lp->mirrors < 1) {
+		log_error("Logical volume %s only has %" PRIu32 " mirrors.",
+			  lv->name, existing_mirrors);
+		return 0;
+	}
+
+	/*
+	 * Adjust log type
+	 */
+	if (arg_count(cmd, corelog_ARG))
+		corelog = 1;
+
+	mirrorlog = arg_str_value(cmd, mirrorlog_ARG,
+				  corelog ? "core" : DEFAULT_MIRRORLOG);
+	if (!strcmp("disk", mirrorlog)) {
+		if (corelog) {
+			log_error("--mirrorlog disk and --corelog "
+				  "are incompatible");
+			return 0;
+		}
+		corelog = 0;
+	} else if (!strcmp("core", mirrorlog))
+		corelog = 1;
+	else {
+		log_error("Unknown mirrorlog type: %s", mirrorlog);
+		return 0;
+	}
+
+	log_verbose("Setting logging type to %s", mirrorlog);
+
+	/*
+	 * Region size must not change on existing mirrors
+	 */
+	if (arg_count(cmd, regionsize_ARG) && (lv->status & MIRRORED) &&
+	    (lp->region_size != seg->region_size)) {
+		log_error("Mirror log region size cannot be changed on "
+			  "an existing mirror.");
+		return 0;
+	}
+
+	/*
+	 * Converting from mirror to linear
+	 */
+	if ((lp->mirrors == 1)) {
+		if (!(lv->status & MIRRORED)) {
+			log_error("Logical volume %s is already not mirrored.",
+				  lv->name);
+			return 1;
+		}
+
+		if (!lv_remove_mirrors(cmd, lv, existing_mirrors - 1, 1,
+				       lp->pv_count ? lp->pvh : NULL, 0))
+			return_0;
+		goto commit_changes;
+	}
+
+	/*
+	 * Converting from linear to mirror
+	 */
+	if (!(lv->status & MIRRORED)) {
+		/* FIXME Share code with lvcreate */
+
+		/* FIXME Why is this restriction here?  Fix it! */
+		dm_list_iterate_items(seg, &lv->segments) {
+			if (seg_is_striped(seg) && seg->area_count > 1) {
+				log_error("Mirrors of striped volumes are not yet supported.");
+				return 0;
+			}
+		}
+
+		if (!lv_add_mirrors(cmd, lv, lp->mirrors - 1, 1,
+				    adjusted_mirror_region_size(
+						lv->vg->extent_size,
+						lv->le_count,
+						lp->region_size),
+				    corelog ? 0U : 1U, lp->pvh, lp->alloc,
+				    MIRROR_BY_LV))
+			return_0;
+		if (lp->wait_completion)
+			lp->need_polling = 1;
+		goto commit_changes;
+	}
+
+	/*
+	 * Converting from mirror to mirror with different leg count,
+	 * or different log type.
+	 */
+	if (dm_list_size(&lv->segments) != 1) {
+		log_error("Logical volume %s has multiple "
+			  "mirror segments.", lv->name);
+		return 0;
+	}
+
+	if (lp->mirrors == existing_mirrors) {
+		/*
+		 * Convert Mirror log type
+		 */
+		original_lv = _original_lv(lv);
+		if (!first_seg(original_lv)->log_lv && !corelog) {
+			if (!add_mirror_log(cmd, original_lv, 1,
+					    adjusted_mirror_region_size(
+							lv->vg->extent_size,
+							lv->le_count,
+							lp->region_size),
+					    lp->pvh, lp->alloc))
+				return_0;
+		} else if (first_seg(original_lv)->log_lv && corelog) {
+			if (!remove_mirror_log(cmd, original_lv,
+					       lp->pv_count ? lp->pvh : NULL))
+				return_0;
+		} else {
+			/* No change */
+			log_error("Logical volume %s already has %"
+				  PRIu32 " mirror(s).", lv->name,
+				  lp->mirrors - 1);
+			if (lv->status & CONVERTING)
+				lp->need_polling = 1;
+			return 1;
+		}
+	} else if (lp->mirrors > existing_mirrors) {
+		if (lv->status & MIRROR_NOTSYNCED) {
+			log_error("Not adding mirror to mirrored LV "
+				  "without initial resync");
+			return 0;
+		}
+		/*
+		 * Log addition/removal should be done before the layer
+		 * insertion to make the end result consistent with
+		 * linear-to-mirror conversion.
+		 */
+		original_lv = _original_lv(lv);
+		if (!first_seg(original_lv)->log_lv && !corelog) {
+			if (!add_mirror_log(cmd, original_lv, 1,
+					    adjusted_mirror_region_size(
+							lv->vg->extent_size,
+							lv->le_count,
+							lp->region_size),
+					    lp->pvh, lp->alloc))
+				return_0;
+		} else if (first_seg(original_lv)->log_lv && corelog) {
+			if (!remove_mirror_log(cmd, original_lv,
+					       lp->pv_count ? lp->pvh : NULL))
+				return_0;
+		}
+		/* Insert a temporary layer for syncing,
+		 * only if the original lv is using disk log. */
+		if (seg->log_lv && !_insert_lvconvert_layer(cmd, lv)) {
+			log_error("Failed to insert resync layer");
+			return 0;
+		}
+		/* FIXME: can't have multiple mlogs. force corelog. */
+		if (!lv_add_mirrors(cmd, lv, lp->mirrors - existing_mirrors, 1,
+				    adjusted_mirror_region_size(
+						lv->vg->extent_size,
+						lv->le_count,
+						lp->region_size),
+				    0U, lp->pvh, lp->alloc,
+				    MIRROR_BY_LV))
+			return_0;
+		lv->status |= CONVERTING;
+		lp->need_polling = 1;
+	} else {
+		/* Reduce number of mirrors */
+		if (!lv_remove_mirrors(cmd, lv, existing_mirrors - lp->mirrors,
+				       corelog ? 1U : 0U,
+				       lp->pv_count ? lp->pvh : NULL, 0))
+			return_0;
+	}
+
+commit_changes:
+	log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
+
+	if (!vg_write(lv->vg))
+		return_0;
+
+	backup(lv->vg);
+
+	if (!suspend_lv(cmd, lv)) {
+		log_error("Failed to lock %s", lv->name);
+		vg_revert(lv->vg);
+		return 0;
+	}
+
+	if (!vg_commit(lv->vg)) {
+		resume_lv(cmd, lv);
+		return 0;
+	}
+
+	log_very_verbose("Updating \"%s\" in kernel", lv->name);
+
+	if (!resume_lv(cmd, lv)) {
+		log_error("Problem reactivating %s", lv->name);
+		return 0;
+	}
+
+	if (!lp->need_polling)
+		log_print("Logical volume %s converted.", lv->name);
+
+	return 1;
+}
+
+static int lvconvert_snapshot(struct cmd_context *cmd,
+			      struct logical_volume *lv,
+			      struct lvconvert_params *lp)
+{
+	struct logical_volume *org;
+
+	if (!(org = find_lv(lv->vg, lp->origin))) {
+		log_error("Couldn't find origin volume '%s'.", lp->origin);
+		return 0;
+	}
+
+	if (org == lv) {
+		log_error("Unable to use \"%s\" as both snapshot and origin.",
+			  lv->name);
+		return 0;
+	}
+
+	if (org->status & (LOCKED|PVMOVE|MIRRORED) || lv_is_cow(org)) {
+		log_error("Unable to create a snapshot of a %s LV.",
+			  org->status & LOCKED ? "locked" :
+			  org->status & PVMOVE ? "pvmove" :
+			  org->status & MIRRORED ? "mirrored" :
+			  "snapshot");
+		return 0;
+	}
+
+	if (!lp->zero || !(lv->status & LVM_WRITE))
+		log_warn("WARNING: \"%s\" not zeroed", lv->name);
+	else if (!set_lv(cmd, lv, UINT64_C(0), 0)) {
+		log_error("Aborting. Failed to wipe snapshot "
+			  "exception store.");
+		return 0;
+	}
+
+	if (!deactivate_lv(cmd, lv)) {
+		log_error("Couldn't deactivate LV %s.", lv->name);
+		return 0;
+	}
+
+	if (!vg_add_snapshot(NULL, org, lv, NULL, org->le_count,
+			     lp->chunk_size)) {
+		log_error("Couldn't create snapshot.");
+		return 0;
+	}
+
+	/* store vg on disk(s) */
+	if (!vg_write(lv->vg))
+		return_0;
+
+	backup(lv->vg);
+
+	if (!suspend_lv(cmd, org)) {
+		log_error("Failed to suspend origin %s", org->name);
+		vg_revert(lv->vg);
+		return 0;
+	}
+
+	if (!vg_commit(lv->vg))
+		return_0;
+
+	if (!resume_lv(cmd, org)) {
+		log_error("Problem reactivating origin %s", org->name);
+		return 0;
+	}
+
+	log_print("Logical volume %s converted to snapshot.", lv->name);
+
+	return 1;
+}
+
+static int lvconvert_single(struct cmd_context *cmd, struct logical_volume *lv,
+			    void *handle)
+{
+	struct lvconvert_params *lp = handle;
+
+	if (lv->status & LOCKED) {
+		log_error("Cannot convert locked LV %s", lv->name);
+		return ECMD_FAILED;
+	}
+
+	if (lv_is_origin(lv)) {
+		log_error("Can't convert logical volume \"%s\" under snapshot",
+			  lv->name);
+		return ECMD_FAILED;
+	}
+
+	if (lv_is_cow(lv)) {
+		log_error("Can't convert snapshot logical volume \"%s\"",
+			  lv->name);
+		return ECMD_FAILED;
+	}
+
+	if (lv->status & PVMOVE) {
+		log_error("Unable to convert pvmove LV %s", lv->name);
+		return ECMD_FAILED;
+	}
+
+	if (lp->snapshot) {
+		if (lv->status & MIRRORED) {
+			log_error("Unable to convert mirrored LV \"%s\" into a snapshot.", lv->name);
+			return ECMD_FAILED;
+		}
+		if (!archive(lv->vg))
+			return ECMD_FAILED;
+		if (!lvconvert_snapshot(cmd, lv, lp))
+			return ECMD_FAILED;
+	} else if (arg_count(cmd, mirrors_ARG) || (lv->status & MIRRORED)) {
+		if (!archive(lv->vg))
+			return ECMD_FAILED;
+		if (!lvconvert_mirrors(cmd, lv, lp))
+			return ECMD_FAILED;
+	}
+
+	return ECMD_PROCESSED;
+}
+
+int lvconvert(struct cmd_context * cmd, int argc, char **argv)
+{
+	struct volume_group *vg;
+	struct lv_list *lvl;
+	struct lvconvert_params lp;
+	int ret = ECMD_FAILED;
+	struct lvinfo info;
+
+	if (!_read_params(&lp, cmd, argc, argv)) {
+		stack;
+		return EINVALID_CMD_LINE;
+	}
+
+	log_verbose("Checking for existing volume group \"%s\"", lp.vg_name);
+
+	if (!(vg = vg_lock_and_read(cmd, lp.vg_name, NULL, LCK_VG_WRITE,
+				    CLUSTERED | EXPORTED_VG | LVM_WRITE,
+				    CORRECT_INCONSISTENT)))
+		return ECMD_FAILED;
+
+	if (!(lvl = find_lv_in_vg(vg, lp.lv_name))) {
+		log_error("Logical volume \"%s\" not found in "
+			  "volume group \"%s\"", lp.lv_name, lp.vg_name);
+		goto bad;
+	}
+
+	if (lp.pv_count) {
+		if (!(lp.pvh = create_pv_list(cmd->mem, vg, lp.pv_count,
+					      lp.pvs, 0)))
+			goto_bad;
+	} else
+		lp.pvh = &vg->pvs;
+
+	ret = lvconvert_single(cmd, lvl->lv, &lp);
+
+bad:
+	unlock_vg(cmd, lp.vg_name);
+
+	if (ret == ECMD_PROCESSED && lp.need_polling) {
+		if (!lv_info(cmd, lvl->lv, &info, 1, 0) || !info.exists) {
+			log_print("Conversion starts after activation");
+			return ret;
+		}
+		ret = lvconvert_poll(cmd, lp.lv_name_full,
+				     lp.wait_completion ? 0 : 1U);
+	}
+
+	return ret;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/lvcreate.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/lvcreate.c
diff -N src/external/gpl2/lvm2tools/dist/tools/lvcreate.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/lvcreate.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,911 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+#include "lv_alloc.h"
+
+#include <fcntl.h>
+
+struct lvcreate_params {
+	/* flags */
+	int snapshot;
+	int zero;
+	int major;
+	int minor;
+	int corelog;
+	int nosync;
+
+	char *origin;
+	const char *vg_name;
+	const char *lv_name;
+
+	uint32_t stripes;
+	uint32_t stripe_size;
+	uint32_t chunk_size;
+	uint32_t region_size;
+
+	uint32_t mirrors;
+
+	const struct segment_type *segtype;
+
+	/* size */
+	uint32_t extents;
+	uint64_t size;
+	percent_t percent;
+
+	uint32_t permission;
+	uint32_t read_ahead;
+	alloc_policy_t alloc;
+
+	int pv_count;
+	char **pvs;
+};
+
+static int _lvcreate_name_params(struct lvcreate_params *lp,
+				 struct cmd_context *cmd,
+				 int *pargc, char ***pargv)
+{
+	int argc = *pargc;
+	char **argv = *pargv, *ptr;
+	char *vg_name;
+
+	if (arg_count(cmd, name_ARG))
+		lp->lv_name = arg_value(cmd, name_ARG);
+
+	if (lp->snapshot) {
+		if (!argc) {
+			log_err("Please specify a logical volume to act as "
+				"the snapshot origin.");
+			return 0;
+		}
+
+		lp->origin = argv[0];
+		(*pargv)++, (*pargc)--;
+		if (!(lp->vg_name = extract_vgname(cmd, lp->origin))) {
+			log_err("The origin name should include the "
+				"volume group.");
+			return 0;
+		}
+
+		/* Strip the volume group from the origin */
+		if ((ptr = strrchr(lp->origin, (int) '/')))
+			lp->origin = ptr + 1;
+
+	} else {
+		/*
+		 * If VG not on command line, try -n arg and then
+		 * environment.
+		 */
+		if (!argc) {
+			if (!(lp->vg_name = extract_vgname(cmd, lp->lv_name))) {
+				log_err("Please provide a volume group name");
+				return 0;
+			}
+
+		} else {
+			vg_name = skip_dev_dir(cmd, argv[0], NULL);
+			if (strrchr(vg_name, '/')) {
+				log_error("Volume group name expected "
+					  "(no slash)");
+				return 0;
+			}
+
+			/*
+			 * Ensure lv_name doesn't contain a
+			 * different VG.
+			 */
+			if (lp->lv_name && strchr(lp->lv_name, '/')) {
+				if (!(lp->vg_name =
+				      extract_vgname(cmd, lp->lv_name)))
+					return 0;
+
+				if (strcmp(lp->vg_name, vg_name)) {
+					log_error("Inconsistent volume group "
+						  "names "
+						  "given: \"%s\" and \"%s\"",
+						  lp->vg_name, vg_name);
+					return 0;
+				}
+			}
+
+			lp->vg_name = vg_name;
+			(*pargv)++, (*pargc)--;
+		}
+	}
+
+	if (!validate_name(lp->vg_name)) {
+		log_error("Volume group name %s has invalid characters",
+			  lp->vg_name);
+		return 0;
+	}
+
+	if (lp->lv_name) {
+		if ((ptr = strrchr(lp->lv_name, '/')))
+			lp->lv_name = ptr + 1;
+
+		if (!apply_lvname_restrictions(lp->lv_name))
+			return_0;
+
+		if (!validate_name(lp->lv_name)) {
+			log_error("Logical volume name \"%s\" is invalid",
+				  lp->lv_name);
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+static int _read_size_params(struct lvcreate_params *lp,
+			     struct cmd_context *cmd)
+{
+	if (arg_count(cmd, extents_ARG) + arg_count(cmd, size_ARG) != 1) {
+		log_error("Please specify either size or extents (not both)");
+		return 0;
+	}
+
+	if (arg_count(cmd, extents_ARG)) {
+		if (arg_sign_value(cmd, extents_ARG, 0) == SIGN_MINUS) {
+			log_error("Negative number of extents is invalid");
+			return 0;
+		}
+		lp->extents = arg_uint_value(cmd, extents_ARG, 0);
+		lp->percent = arg_percent_value(cmd, extents_ARG, PERCENT_NONE);
+	}
+
+	/* Size returned in kilobyte units; held in sectors */
+	if (arg_count(cmd, size_ARG)) {
+		if (arg_sign_value(cmd, size_ARG, 0) == SIGN_MINUS) {
+			log_error("Negative size is invalid");
+			return 0;
+		}
+		lp->size = arg_uint64_value(cmd, size_ARG, UINT64_C(0));
+		lp->percent = PERCENT_NONE;
+	}
+
+	return 1;
+}
+
+/*
+ * Generic stripe parameter checks.
+ * FIXME: Should eventually be moved into lvm library.
+ */
+static int _validate_stripe_params(struct cmd_context *cmd,
+				   struct lvcreate_params *lp)
+{
+	if (lp->stripes == 1 && lp->stripe_size) {
+		log_print("Ignoring stripesize argument with single stripe");
+		lp->stripe_size = 0;
+	}
+
+	if (lp->stripes > 1 && !lp->stripe_size) {
+		lp->stripe_size = find_config_tree_int(cmd,
+						  "metadata/stripesize",
+						  DEFAULT_STRIPESIZE) * 2;
+		log_print("Using default stripesize %s",
+			  display_size(cmd, (uint64_t) lp->stripe_size));
+	}
+
+	if (lp->stripes < 1 || lp->stripes > MAX_STRIPES) {
+		log_error("Number of stripes (%d) must be between %d and %d",
+			  lp->stripes, 1, MAX_STRIPES);
+		return 0;
+	}
+
+	/* MAX size check is in _lvcreate */
+	if (lp->stripes > 1 && (lp->stripe_size < STRIPE_SIZE_MIN ||
+				lp->stripe_size & (lp->stripe_size - 1))) {
+		log_error("Invalid stripe size %s",
+			  display_size(cmd, (uint64_t) lp->stripe_size));
+		return 0;
+	}
+
+	return 1;
+}
+
+/* The stripe size is limited by the size of a uint32_t, but since the
+ * value given by the user is doubled, and the final result must be a
+ * power of 2, we must divide UINT_MAX by four and add 1 (to round it
+ * up to the power of 2) */
+static int _read_stripe_params(struct lvcreate_params *lp,
+			       struct cmd_context *cmd)
+{
+	if (arg_count(cmd, stripesize_ARG)) {
+		if (arg_sign_value(cmd, stripesize_ARG, 0) == SIGN_MINUS) {
+			log_error("Negative stripesize is invalid");
+			return 0;
+		}
+		/* Check to make sure we won't overflow lp->stripe_size */
+		if(arg_uint_value(cmd, stripesize_ARG, 0) > STRIPE_SIZE_LIMIT * 2) {
+			log_error("Stripe size cannot be larger than %s",
+				  display_size(cmd, (uint64_t) STRIPE_SIZE_LIMIT));
+			return 0;
+		}
+		lp->stripe_size = arg_uint_value(cmd, stripesize_ARG, 0);
+	}
+
+
+	if (!_validate_stripe_params(cmd, lp))
+		return 0;
+
+	return 1;
+}
+
+/*
+ * Generic mirror parameter checks.
+ * FIXME: Should eventually be moved into lvm library.
+ */
+static int _validate_mirror_params(const struct cmd_context *cmd __attribute((unused)),
+				   const struct lvcreate_params *lp)
+{
+	int pagesize = lvm_getpagesize();
+
+	if (lp->region_size & (lp->region_size - 1)) {
+		log_error("Region size (%" PRIu32 ") must be a power of 2",
+			  lp->region_size);
+		return 0;
+	}
+
+	if (lp->region_size % (pagesize >> SECTOR_SHIFT)) {
+		log_error("Region size (%" PRIu32 ") must be a multiple of "
+			  "machine memory page size (%d)",
+			  lp->region_size, pagesize >> SECTOR_SHIFT);
+		return 0;
+	}
+
+	if (!lp->region_size) {
+		log_error("Non-zero region size must be supplied.");
+		return 0;
+	}
+
+	return 1;
+}
+
+static int _read_mirror_params(struct lvcreate_params *lp,
+			       struct cmd_context *cmd)
+{
+	int region_size;
+	const char *mirrorlog;
+
+	if (arg_count(cmd, corelog_ARG))
+		lp->corelog = 1;
+
+	mirrorlog = arg_str_value(cmd, mirrorlog_ARG,
+				  lp->corelog ? "core" : DEFAULT_MIRRORLOG);
+
+	if (!strcmp("disk", mirrorlog)) {
+		if (lp->corelog) {
+			log_error("--mirrorlog disk and --corelog "
+				  "are incompatible");
+			return 0;
+		}
+		lp->corelog = 0;
+	} else if (!strcmp("core", mirrorlog))
+		lp->corelog = 1;
+	else {
+		log_error("Unknown mirrorlog type: %s", mirrorlog);
+		return 0;
+	}
+
+	log_verbose("Setting logging type to %s", mirrorlog);
+
+	lp->nosync = arg_count(cmd, nosync_ARG) ? 1 : 0;
+
+	if (arg_count(cmd, regionsize_ARG)) {
+		if (arg_sign_value(cmd, regionsize_ARG, 0) == SIGN_MINUS) {
+			log_error("Negative regionsize is invalid");
+			return 0;
+		}
+		lp->region_size = arg_uint_value(cmd, regionsize_ARG, 0);
+	} else {
+		region_size = 2 * find_config_tree_int(cmd,
+					"activation/mirror_region_size",
+					DEFAULT_MIRROR_REGION_SIZE);
+		if (region_size < 0) {
+			log_error("Negative regionsize in configuration file "
+				  "is invalid");
+			return 0;
+		}
+		lp->region_size = region_size;
+	}
+
+	if (!_validate_mirror_params(cmd, lp))
+		return 0;
+
+	return 1;
+}
+
+static int _lvcreate_params(struct lvcreate_params *lp, struct cmd_context *cmd,
+			    int argc, char **argv)
+{
+	int contiguous;
+	unsigned pagesize;
+
+	memset(lp, 0, sizeof(*lp));
+
+	/*
+	 * Check selected options are compatible and determine segtype
+	 */
+	lp->segtype = (const struct segment_type *)
+	    arg_ptr_value(cmd, type_ARG,
+			  get_segtype_from_string(cmd, "striped"));
+
+	lp->stripes = arg_uint_value(cmd, stripes_ARG, 1);
+	if (arg_count(cmd, stripes_ARG) && lp->stripes == 1)
+		log_print("Redundant stripes argument: default is 1");
+
+	if (arg_count(cmd, snapshot_ARG) || seg_is_snapshot(lp))
+		lp->snapshot = 1;
+
+	lp->mirrors = 1;
+
+	/* Default to 2 mirrored areas if --type mirror */
+	if (seg_is_mirrored(lp))
+		lp->mirrors = 2;
+
+	if (arg_count(cmd, mirrors_ARG)) {
+		lp->mirrors = arg_uint_value(cmd, mirrors_ARG, 0) + 1;
+		if (lp->mirrors == 1)
+			log_print("Redundant mirrors argument: default is 0");
+		if (arg_sign_value(cmd, mirrors_ARG, 0) == SIGN_MINUS) {
+			log_error("Mirrors argument may not be negative");
+			return 0;
+		}
+	}
+
+	if (lp->snapshot) {
+		if (arg_count(cmd, zero_ARG)) {
+			log_error("-Z is incompatible with snapshots");
+			return 0;
+		}
+		if (arg_sign_value(cmd, chunksize_ARG, 0) == SIGN_MINUS) {
+			log_error("Negative chunk size is invalid");
+			return 0;
+		}
+		lp->chunk_size = arg_uint_value(cmd, chunksize_ARG, 8);
+		if (lp->chunk_size < 8 || lp->chunk_size > 1024 ||
+		    (lp->chunk_size & (lp->chunk_size - 1))) {
+			log_error("Chunk size must be a power of 2 in the "
+				  "range 4K to 512K");
+			return 0;
+		}
+		log_verbose("Setting chunksize to %d sectors.", lp->chunk_size);
+
+		if (!(lp->segtype = get_segtype_from_string(cmd, "snapshot")))
+			return_0;
+	} else {
+		if (arg_count(cmd, chunksize_ARG)) {
+			log_error("-c is only available with snapshots");
+			return 0;
+		}
+	}
+
+	if (lp->mirrors > 1) {
+		if (lp->snapshot) {
+			log_error("mirrors and snapshots are currently "
+				  "incompatible");
+			return 0;
+		}
+
+		if (lp->stripes > 1) {
+			log_error("mirrors and stripes are currently "
+				  "incompatible");
+			return 0;
+		}
+
+		if (!(lp->segtype = get_segtype_from_string(cmd, "striped")))
+			return_0;
+	} else {
+		if (arg_count(cmd, corelog_ARG)) {
+			log_error("--corelog is only available with mirrors");
+			return 0;
+		}
+
+		if (arg_count(cmd, nosync_ARG)) {
+			log_error("--nosync is only available with mirrors");
+			return 0;
+		}
+	}
+
+	if (activation() && lp->segtype->ops->target_present &&
+	    !lp->segtype->ops->target_present(NULL, NULL)) {
+		log_error("%s: Required device-mapper target(s) not "
+			  "detected in your kernel", lp->segtype->name);
+		return 0;
+	}
+
+	if (!_lvcreate_name_params(lp, cmd, &argc, &argv) ||
+	    !_read_size_params(lp, cmd) ||
+	    !_read_stripe_params(lp, cmd) ||
+	    !_read_mirror_params(lp, cmd))
+		return_0;
+
+	/*
+	 * Should we zero the lv.
+	 */
+	lp->zero = strcmp(arg_str_value(cmd, zero_ARG,
+		(lp->segtype->flags & SEG_CANNOT_BE_ZEROED) ? "n" : "y"), "n");
+
+	/*
+	 * Alloc policy
+	 */
+	contiguous = strcmp(arg_str_value(cmd, contiguous_ARG, "n"), "n");
+
+	lp->alloc = contiguous ? ALLOC_CONTIGUOUS : ALLOC_INHERIT;
+
+	lp->alloc = arg_uint_value(cmd, alloc_ARG, lp->alloc);
+
+	if (contiguous && (lp->alloc != ALLOC_CONTIGUOUS)) {
+		log_error("Conflicting contiguous and alloc arguments");
+		return 0;
+	}
+
+	/*
+	 * Read ahead.
+	 */
+	lp->read_ahead = arg_uint_value(cmd, readahead_ARG, DM_READ_AHEAD_NONE);
+	pagesize = lvm_getpagesize() >> SECTOR_SHIFT;
+	if (lp->read_ahead != DM_READ_AHEAD_AUTO &&
+	    lp->read_ahead != DM_READ_AHEAD_NONE &&
+	    lp->read_ahead % pagesize) {
+		lp->read_ahead = (lp->read_ahead / pagesize) * pagesize;
+		log_verbose("Rounding down readahead to %u sectors, a multiple "
+			    "of page size %u.", lp->read_ahead, pagesize);
+	}
+
+	/*
+	 * Permissions.
+	 */
+	if (arg_count(cmd, permission_ARG))
+		lp->permission = arg_uint_value(cmd, permission_ARG, 0);
+	else
+		lp->permission = LVM_READ | LVM_WRITE;
+
+	/* Must not zero read only volume */
+	if (!(lp->permission & LVM_WRITE))
+		lp->zero = 0;
+
+	lp->minor = arg_int_value(cmd, minor_ARG, -1);
+	lp->major = arg_int_value(cmd, major_ARG, -1);
+
+	/* Persistent minor */
+	if (arg_count(cmd, persistent_ARG)) {
+		if (!strcmp(arg_str_value(cmd, persistent_ARG, "n"), "y")) {
+			if (lp->minor == -1) {
+				log_error("Please specify minor number with "
+					  "--minor when using -My");
+				return 0;
+			}
+			if (lp->major == -1) {
+				log_error("Please specify major number with "
+					  "--major when using -My");
+				return 0;
+			}
+		} else {
+			if ((lp->minor != -1) || (lp->major != -1)) {
+				log_error("--major and --minor incompatible "
+					  "with -Mn");
+				return 0;
+			}
+		}
+	} else if (arg_count(cmd, minor_ARG) || arg_count(cmd, major_ARG)) {
+		log_error("--major and --minor require -My");
+		return 0;
+	}
+
+	lp->pv_count = argc;
+	lp->pvs = argv;
+
+	return 1;
+}
+
+static int _lvcreate(struct cmd_context *cmd, struct volume_group *vg,
+		     struct lvcreate_params *lp)
+{
+	uint32_t size_rest;
+	uint32_t status = 0;
+	uint64_t tmp_size;
+	struct logical_volume *lv, *org = NULL;
+	struct dm_list *pvh;
+	const char *tag = NULL;
+	int origin_active = 0;
+	char lv_name_buf[128];
+	const char *lv_name;
+	struct lvinfo info;
+	uint32_t pv_extent_count;
+
+	if (lp->lv_name && find_lv_in_vg(vg, lp->lv_name)) {
+		log_error("Logical volume \"%s\" already exists in "
+			  "volume group \"%s\"", lp->lv_name, lp->vg_name);
+		return 0;
+	}
+
+	if (lp->mirrors > 1 && !(vg->fid->fmt->features & FMT_SEGMENTS)) {
+		log_error("Metadata does not support mirroring.");
+		return 0;
+	}
+
+	if (lp->read_ahead != DM_READ_AHEAD_AUTO &&
+	    lp->read_ahead != DM_READ_AHEAD_NONE &&
+	    (vg->fid->fmt->features & FMT_RESTRICTED_READAHEAD) &&
+	    (lp->read_ahead < 2 || lp->read_ahead > 120)) {
+		log_error("Metadata only supports readahead values between 2 and 120.");
+		return 0;
+	}
+
+	if (lp->stripe_size > vg->extent_size) {
+		log_error("Reducing requested stripe size %s to maximum, "
+			  "physical extent size %s",
+			  display_size(cmd, (uint64_t) lp->stripe_size),
+			  display_size(cmd, (uint64_t) vg->extent_size));
+		lp->stripe_size = vg->extent_size;
+	}
+
+	/* Need to check the vg's format to verify this - the cmd format isn't setup properly yet */
+	if (lp->stripes > 1 &&
+	    !(vg->fid->fmt->features & FMT_UNLIMITED_STRIPESIZE) &&
+	    (lp->stripe_size > STRIPE_SIZE_MAX)) {
+		log_error("Stripe size may not exceed %s",
+			  display_size(cmd, (uint64_t) STRIPE_SIZE_MAX));
+		return 0;
+	}
+
+	if (lp->size) {
+		/* No of 512-byte sectors */
+		tmp_size = lp->size;
+
+		if (tmp_size % vg->extent_size) {
+			tmp_size += vg->extent_size - tmp_size %
+			    vg->extent_size;
+			log_print("Rounding up size to full physical extent %s",
+				  display_size(cmd, tmp_size));
+		}
+
+		if (tmp_size > (uint64_t) UINT32_MAX * vg->extent_size) {
+			log_error("Volume too large (%s) for extent size %s. "
+				  "Upper limit is %s.",
+				  display_size(cmd, tmp_size),
+				  display_size(cmd, (uint64_t) vg->extent_size),
+				  display_size(cmd, (uint64_t) UINT32_MAX *
+						   vg->extent_size));
+			return 0;
+		}
+		lp->extents = (uint64_t) tmp_size / vg->extent_size;
+	}
+
+	/*
+	 * Create the pv list.
+	 */
+	if (lp->pv_count) {
+		if (!(pvh = create_pv_list(cmd->mem, vg,
+					   lp->pv_count, lp->pvs, 1)))
+			return_0;
+	} else
+		pvh = &vg->pvs;
+
+	switch(lp->percent) {
+		case PERCENT_VG:
+			lp->extents = lp->extents * vg->extent_count / 100;
+			break;
+		case PERCENT_FREE:
+			lp->extents = lp->extents * vg->free_count / 100;
+			break;
+		case PERCENT_PVS:
+			if (!lp->pv_count) {
+				log_error("Please specify physical volume(s) "
+					  "with %%PVS");
+				return 0;
+			}
+			pv_extent_count = pv_list_extents_free(pvh);
+			lp->extents = lp->extents * pv_extent_count / 100;
+			break;
+		case PERCENT_LV:
+			log_error("Please express size as %%VG, %%PVS, or "
+				  "%%FREE.");
+			return 0;
+		case PERCENT_NONE:
+			break;
+	}
+
+	if ((size_rest = lp->extents % lp->stripes)) {
+		log_print("Rounding size (%d extents) up to stripe boundary "
+			  "size (%d extents)", lp->extents,
+			  lp->extents - size_rest + lp->stripes);
+		lp->extents = lp->extents - size_rest + lp->stripes;
+	}
+
+	if (lp->zero && !activation()) {
+		log_error("Can't wipe start of new LV without using "
+			  "device-mapper kernel driver");
+		return 0;
+	}
+
+	status |= lp->permission | VISIBLE_LV;
+
+	if (lp->snapshot) {
+		if (!activation()) {
+			log_error("Can't create snapshot without using "
+				  "device-mapper kernel driver");
+			return 0;
+		}
+		/* FIXME Allow exclusive activation. */
+		if (vg_is_clustered(vg)) {
+			log_error("Clustered snapshots are not yet supported.");
+			return 0;
+		}
+		if (!(org = find_lv(vg, lp->origin))) {
+			log_err("Couldn't find origin volume '%s'.",
+				lp->origin);
+			return 0;
+		}
+		if (lv_is_cow(org)) {
+			log_error("Snapshots of snapshots are not supported "
+				  "yet.");
+			return 0;
+		}
+		if (org->status & LOCKED) {
+			log_error("Snapshots of locked devices are not "
+				  "supported yet");
+			return 0;
+		}
+		if (org->status & MIRROR_IMAGE ||
+		    org->status & MIRROR_LOG ||
+		    org->status & MIRRORED) {
+			log_error("Snapshots and mirrors may not yet be mixed.");
+			return 0;
+		}
+
+		/* Must zero cow */
+		status |= LVM_WRITE;
+
+		if (!lv_info(cmd, org, &info, 0, 0)) {
+			log_error("Check for existence of snapshot origin "
+				  "'%s' failed.", org->name);
+			return 0;
+		}
+		origin_active = info.exists;
+	}
+
+	if (!lp->extents) {
+		log_error("Unable to create new logical volume with no extents");
+		return 0;
+	}
+
+	if (!seg_is_virtual(lp) &&
+	    vg->free_count < lp->extents) {
+		log_error("Insufficient free extents (%u) in volume group %s: "
+			  "%u required", vg->free_count, vg->name, lp->extents);
+		return 0;
+	}
+
+	if (lp->stripes > dm_list_size(pvh) && lp->alloc != ALLOC_ANYWHERE) {
+		log_error("Number of stripes (%u) must not exceed "
+			  "number of physical volumes (%d)", lp->stripes,
+			  dm_list_size(pvh));
+		return 0;
+	}
+
+	if (lp->mirrors > 1 && !activation()) {
+		log_error("Can't create mirror without using "
+			  "device-mapper kernel driver.");
+		return 0;
+	}
+
+	/* The snapshot segment gets created later */
+	if (lp->snapshot &&
+	    !(lp->segtype = get_segtype_from_string(cmd, "striped")))
+		return_0;
+
+	if (!archive(vg))
+		return 0;
+
+	if (lp->lv_name)
+		lv_name = lp->lv_name;
+	else {
+		if (!generate_lv_name(vg, "lvol%d", lv_name_buf, sizeof(lv_name_buf))) {
+			log_error("Failed to generate LV name.");
+			return 0;
+		}
+		lv_name = &lv_name_buf[0];
+	}
+
+	if (arg_count(cmd, addtag_ARG)) {
+		if (!(tag = arg_str_value(cmd, addtag_ARG, NULL))) {
+			log_error("Failed to get tag");
+			return 0;
+		}
+
+		if (!(vg->fid->fmt->features & FMT_TAGS)) {
+			log_error("Volume group %s does not support tags",
+				  vg->name);
+			return 0;
+		}
+	}
+
+	if (lp->mirrors > 1) {
+		init_mirror_in_sync(lp->nosync);
+
+		if (lp->nosync) {
+			log_warn("WARNING: New mirror won't be synchronised. "
+				  "Don't read what you didn't write!");
+			status |= MIRROR_NOTSYNCED;
+		}
+	}
+
+	if (!(lv = lv_create_empty(lv_name ? lv_name : "lvol%d", NULL,
+				   status, lp->alloc, 0, vg)))
+		return_0;
+
+	if (lp->read_ahead) {
+		log_verbose("Setting read ahead sectors");
+		lv->read_ahead = lp->read_ahead;
+	}
+
+	if (lp->minor >= 0) {
+		lv->major = lp->major;
+		lv->minor = lp->minor;
+		lv->status |= FIXED_MINOR;
+		log_verbose("Setting device number to (%d, %d)", lv->major,
+			    lv->minor);
+	}
+
+	if (tag && !str_list_add(cmd->mem, &lv->tags, tag)) {
+		log_error("Failed to add tag %s to %s/%s",
+			  tag, lv->vg->name, lv->name);
+		return 0;
+	}
+
+	if (!lv_extend(lv, lp->segtype, lp->stripes, lp->stripe_size,
+		       1, lp->extents, NULL, 0u, 0u, pvh, lp->alloc))
+		return_0;
+
+	if (lp->mirrors > 1) {
+		if (!lv_add_mirrors(cmd, lv, lp->mirrors - 1, lp->stripes,
+				    adjusted_mirror_region_size(
+						vg->extent_size,
+						lv->le_count,
+						lp->region_size),
+				    lp->corelog ? 0U : 1U, pvh, lp->alloc,
+				    MIRROR_BY_LV |
+				    (lp->nosync ? MIRROR_SKIP_INIT_SYNC : 0))) {
+			stack;
+			goto revert_new_lv;
+		}
+	}
+
+	/* store vg on disk(s) */
+	if (!vg_write(vg))
+		return_0;
+
+	backup(vg);
+
+	if (!vg_commit(vg))
+		return_0;
+
+	if (lp->snapshot) {
+		if (!activate_lv_excl(cmd, lv)) {
+			log_error("Aborting. Failed to activate snapshot "
+				  "exception store.");
+			goto revert_new_lv;
+		}
+	} else if (!activate_lv(cmd, lv)) {
+		if (lp->zero) {
+			log_error("Aborting. Failed to activate new LV to wipe "
+				  "the start of it.");
+			goto deactivate_and_revert_new_lv;
+		}
+		log_error("Failed to activate new LV.");
+		return 0;
+	}
+
+	if (!lp->zero && !lp->snapshot)
+		log_error("WARNING: \"%s\" not zeroed", lv->name);
+	else if (!set_lv(cmd, lv, UINT64_C(0), 0)) {
+		log_error("Aborting. Failed to wipe %s.",
+			  lp->snapshot ? "snapshot exception store" :
+					 "start of new LV");
+		goto deactivate_and_revert_new_lv;
+	}
+
+	if (lp->snapshot) {
+		/* Reset permission after zeroing */
+		if (!(lp->permission & LVM_WRITE))
+			lv->status &= ~LVM_WRITE;
+
+		/* COW area must be deactivated if origin is not active */
+		if (!origin_active && !deactivate_lv(cmd, lv)) {
+			log_error("Aborting. Couldn't deactivate snapshot "
+				  "COW area. Manual intervention required.");
+			return 0;
+		}
+
+		/* cow LV remains active and becomes snapshot LV */
+
+		if (!vg_add_snapshot(NULL, org, lv, NULL,
+				     org->le_count, lp->chunk_size)) {
+			log_error("Couldn't create snapshot.");
+			return 0;
+		}
+
+		/* store vg on disk(s) */
+		if (!vg_write(vg))
+			return_0;
+
+		if (!suspend_lv(cmd, org)) {
+			log_error("Failed to suspend origin %s", org->name);
+			vg_revert(vg);
+			return 0;
+		}
+
+		if (!vg_commit(vg))
+			return_0;
+
+		if (!resume_lv(cmd, org)) {
+			log_error("Problem reactivating origin %s", org->name);
+			return 0;
+		}
+	}
+	/* FIXME out of sequence */
+	backup(vg);
+
+	log_print("Logical volume \"%s\" created", lv->name);
+
+	/*
+	 * FIXME: as a sanity check we could try reading the
+	 * last block of the device ?
+	 */
+
+	return 1;
+
+deactivate_and_revert_new_lv:
+	if (!deactivate_lv(cmd, lv)) {
+		log_error("Unable to deactivate failed new LV. "
+			  "Manual intervention required.");
+		return 0;
+	}
+
+revert_new_lv:
+	/* FIXME Better to revert to backup of metadata? */
+	if (!lv_remove(lv) || !vg_write(vg) || (backup(vg), !vg_commit(vg)))
+		log_error("Manual intervention may be required to remove "
+			  "abandoned LV(s) before retrying.");
+	return 0;
+}
+
+int lvcreate(struct cmd_context *cmd, int argc, char **argv)
+{
+	int r = ECMD_PROCESSED;
+	struct lvcreate_params lp;
+	struct volume_group *vg;
+
+	memset(&lp, 0, sizeof(lp));
+
+	if (!_lvcreate_params(&lp, cmd, argc, argv))
+		return EINVALID_CMD_LINE;
+
+	log_verbose("Finding volume group \"%s\"", lp.vg_name);
+	if (!(vg = vg_lock_and_read(cmd, lp.vg_name, NULL, LCK_VG_WRITE,
+				    CLUSTERED | EXPORTED_VG | LVM_WRITE,
+				    CORRECT_INCONSISTENT)))
+		return ECMD_FAILED;
+
+	if (!_lvcreate(cmd, vg, &lp))
+		r = ECMD_FAILED;
+
+	unlock_vg(cmd, lp.vg_name);
+	return r;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/lvdisplay.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/lvdisplay.c
diff -N src/external/gpl2/lvm2tools/dist/tools/lvdisplay.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/lvdisplay.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,61 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+static int _lvdisplay_single(struct cmd_context *cmd, struct logical_volume *lv,
+			     void *handle)
+{
+	if (!arg_count(cmd, all_ARG) && !lv_is_visible(lv))
+		return ECMD_PROCESSED;
+
+	if (arg_count(cmd, colon_ARG))
+		lvdisplay_colons(lv);
+	else {
+		lvdisplay_full(cmd, lv, handle);
+		if (arg_count(cmd, maps_ARG))
+			lvdisplay_segments(lv);
+	}
+
+	return ECMD_PROCESSED;
+}
+
+int lvdisplay(struct cmd_context *cmd, int argc, char **argv)
+{
+	if (arg_count(cmd, columns_ARG)) {
+		if (arg_count(cmd, colon_ARG) || arg_count(cmd, maps_ARG)) {
+			log_error("Incompatible options selected");
+			return EINVALID_CMD_LINE;
+		}
+		return lvs(cmd, argc, argv);
+	} else if (arg_count(cmd, aligned_ARG) ||
+		   arg_count(cmd, noheadings_ARG) ||
+		   arg_count(cmd, options_ARG) ||
+		   arg_count(cmd, separator_ARG) ||
+		   arg_count(cmd, sort_ARG) || arg_count(cmd, unbuffered_ARG)) {
+		log_error("Incompatible options selected");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (arg_count(cmd, colon_ARG) && arg_count(cmd, verbose_ARG)) {
+		log_error("Options -v and -c are incompatible");
+		return EINVALID_CMD_LINE;
+	}
+
+	return process_each_lv(cmd, argc, argv, LCK_VG_READ, NULL,
+			       &_lvdisplay_single);
+}
Index: src/external/gpl2/lvm2tools/dist/tools/lvextend.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/lvextend.c
diff -N src/external/gpl2/lvm2tools/dist/tools/lvextend.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/lvextend.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,23 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+int lvextend(struct cmd_context *cmd, int argc, char **argv)
+{
+	return lvresize(cmd, argc, argv);
+}
Index: src/external/gpl2/lvm2tools/dist/tools/lvm-static.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/lvm-static.c
diff -N src/external/gpl2/lvm2tools/dist/tools/lvm-static.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/lvm-static.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,29 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lvm2cmdline.h"
+
+int main(int argc, char **argv)
+{
+	return lvm2_main(argc, argv, 1);
+}
+
+int lvm_shell(struct cmd_context *cmd __attribute((unused)),
+	      struct cmdline_context *cmdline __attribute((unused)))
+{
+	return 0;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/lvm.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/lvm.c
diff -N src/external/gpl2/lvm2tools/dist/tools/lvm.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/lvm.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,252 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+#include "lvm2cmdline.h"
+
+int main(int argc, char **argv)
+{
+	return lvm2_main(argc, argv, 0);
+}
+
+#ifdef READLINE_SUPPORT
+
+#  include <readline/readline.h>
+#  include <readline/history.h>
+#  ifndef HAVE_RL_COMPLETION_MATCHES
+#    define rl_completion_matches(a, b) completion_matches((char *)a, b)
+#  endif
+
+static struct cmdline_context *_cmdline;
+
+/* List matching commands */
+static char *_list_cmds(const char *text, int state)
+{
+	static int i = 0;
+	static size_t len = 0;
+
+	/* Initialise if this is a new completion attempt */
+	if (!state) {
+		i = 0;
+		len = strlen(text);
+	}
+
+	while (i < _cmdline->num_commands)
+		if (!strncmp(text, _cmdline->commands[i++].name, len))
+			return strdup(_cmdline->commands[i - 1].name);
+
+	return NULL;
+}
+
+/* List matching arguments */
+static char *_list_args(const char *text, int state)
+{
+	static int match_no = 0;
+	static size_t len = 0;
+	static struct command *com;
+
+	/* Initialise if this is a new completion attempt */
+	if (!state) {
+		char *s = rl_line_buffer;
+		int j = 0;
+
+		match_no = 0;
+		com = NULL;
+		len = strlen(text);
+
+		/* Find start of first word in line buffer */
+		while (isspace(*s))
+			s++;
+
+		/* Look for word in list of commands */
+		for (j = 0; j < _cmdline->num_commands; j++) {
+			const char *p;
+			char *q = s;
+
+			p = _cmdline->commands[j].name;
+			while (*p == *q) {
+				p++;
+				q++;
+			}
+			if ((!*p) && *q == ' ') {
+				com = _cmdline->commands + j;
+				break;
+			}
+		}
+
+		if (!com)
+			return NULL;
+	}
+
+	/* Short form arguments */
+	if (len < 3) {
+		while (match_no < com->num_args) {
+			char s[3];
+			char c;
+			if (!(c = (_cmdline->the_args +
+				   com->valid_args[match_no++])->short_arg))
+				continue;
+
+			sprintf(s, "-%c", c);
+			if (!strncmp(text, s, len))
+				return strdup(s);
+		}
+	}
+
+	/* Long form arguments */
+	if (match_no < com->num_args)
+		match_no = com->num_args;
+
+	while (match_no - com->num_args < com->num_args) {
+		const char *l;
+		l = (_cmdline->the_args +
+		     com->valid_args[match_no++ - com->num_args])->long_arg;
+		if (*(l + 2) && !strncmp(text, l, len))
+			return strdup(l);
+	}
+
+	return NULL;
+}
+
+/* Custom completion function */
+static char **_completion(const char *text, int start_pos,
+			  int end_pos __attribute((unused)))
+{
+	char **match_list = NULL;
+	int p = 0;
+
+	while (isspace((int) *(rl_line_buffer + p)))
+		p++;
+
+	/* First word should be one of our commands */
+	if (start_pos == p)
+		match_list = rl_completion_matches(text, _list_cmds);
+
+	else if (*text == '-')
+		match_list = rl_completion_matches(text, _list_args);
+	/* else other args */
+
+	/* No further completion */
+	rl_attempted_completion_over = 1;
+	return match_list;
+}
+
+static int _hist_file(char *buffer, size_t size)
+{
+	char *e = getenv("HOME");
+
+	if (dm_snprintf(buffer, size, "%s/.lvm_history", e) < 0) {
+		log_error("$HOME/.lvm_history: path too long");
+		return 0;
+	}
+
+	return 1;
+}
+
+static void _read_history(struct cmd_context *cmd)
+{
+	char hist_file[PATH_MAX];
+
+	if (!_hist_file(hist_file, sizeof(hist_file)))
+		return;
+
+	if (read_history(hist_file))
+		log_very_verbose("Couldn't read history from %s.", hist_file);
+
+	stifle_history(find_config_tree_int(cmd, "shell/history_size",
+				       DEFAULT_MAX_HISTORY));
+
+}
+
+static void _write_history(void)
+{
+	char hist_file[PATH_MAX];
+
+	if (!_hist_file(hist_file, sizeof(hist_file)))
+		return;
+
+	if (write_history(hist_file))
+		log_very_verbose("Couldn't write history to %s.", hist_file);
+}
+
+int lvm_shell(struct cmd_context *cmd, struct cmdline_context *cmdline)
+{
+	int argc, ret;
+	char *input = NULL, *args[MAX_ARGS], **argv;
+
+	rl_readline_name = "lvm";
+	rl_attempted_completion_function = (CPPFunction *) _completion;
+
+	_read_history(cmd);
+
+	_cmdline = cmdline;
+
+	_cmdline->interactive = 1;
+	while (1) {
+		free(input);
+		input = readline("lvm> ");
+
+		/* EOF */
+		if (!input) {
+			printf("\n");
+			break;
+		}
+
+		/* empty line */
+		if (!*input)
+			continue;
+
+		add_history(input);
+
+		argv = args;
+
+		if (lvm_split(input, &argc, argv, MAX_ARGS) == MAX_ARGS) {
+			log_error("Too many arguments, sorry.");
+			continue;
+		}
+
+		if (!strcmp(argv[0], "lvm")) {
+			argv++;
+			argc--;
+		}
+
+		if (!argc)
+			continue;
+
+		if (!strcmp(argv[0], "quit") || !strcmp(argv[0], "exit")) {
+			remove_history(history_length - 1);
+			log_error("Exiting.");
+			break;
+		}
+
+		ret = lvm_run_command(cmd, argc, argv);
+		if (ret == ENO_SUCH_CMD)
+			log_error("No such command '%s'.  Try 'help'.",
+				  argv[0]);
+
+                if ((ret != ECMD_PROCESSED) && !error_message_produced()) {
+			log_debug("Internal error: Failed command did not use log_error");
+			log_error("Command failed with status code %d.", ret);
+		}
+		_write_history();
+	}
+
+	free(input);
+	return 0;
+}
+
+#endif	/* READLINE_SUPPORT */
Index: src/external/gpl2/lvm2tools/dist/tools/lvm2cmd-static.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/lvm2cmd-static.c
diff -N src/external/gpl2/lvm2tools/dist/tools/lvm2cmd-static.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/lvm2cmd-static.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,23 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lvm2cmdline.h"
+#include "lvm2cmd.h"
+
+void *lvm2_init(void)
+{
+	return cmdlib_lvm2_init(1);
+}
Index: src/external/gpl2/lvm2tools/dist/tools/lvm2cmd.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/lvm2cmd.c
diff -N src/external/gpl2/lvm2tools/dist/tools/lvm2cmd.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/lvm2cmd.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,29 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2006-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lvm2cmdline.h"
+#include "lvm2cmd.h"
+
+void *lvm2_init(void)
+{
+	return cmdlib_lvm2_init(0);
+}
+
+int lvm_shell(struct cmd_context *cmd __attribute((unused)),
+	      struct cmdline_context *cmdline __attribute((unused)))
+{
+	return 0;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/lvm2cmd.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/lvm2cmd.h
diff -N src/external/gpl2/lvm2tools/dist/tools/lvm2cmd.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/lvm2cmd.h	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,67 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_CMDLIB_H
+#define _LVM_CMDLIB_H
+
+#ifndef _LVM_LOG_H
+typedef void (*lvm2_log_fn_t) (int level, const char *file, int line,
+			       const char *message);
+#endif
+
+#define LVM2_LOG_SUPPRESS	0
+
+/* Logging levels */
+#define LVM2_LOG_FATAL		2
+#define LVM2_LOG_ERROR		3
+#define LVM2_LOG_PRINT		4
+#define LVM2_LOG_VERBOSE 	5
+#define LVM2_LOG_VERY_VERBOSE	6
+#define LVM2_LOG_DEBUG		7
+
+/*
+ * Define external function to replace the built-in logging function.
+ * It receives output line-by-line.
+ *
+ * level is the logging level (see above)
+ * file & line refer to the source code where the message originates.
+ */
+void lvm2_log_fn(lvm2_log_fn_t log_fn);
+
+/*
+ * Initialise library.
+ * Returns a handle so repeated use of lvm2_run is more efficient.
+ */ 
+void *lvm2_init(void);
+
+/*
+ * Set log level (as above) if using built-in logging function. 
+ * Default is LVM2_LOG_PRINT.  Use LVM2_LOG_SUPPRESS to suppress output.
+ */
+void lvm2_log_level(void *handle, int level);
+
+/*
+ * Run an LVM2 command. 
+ * Use NULL handle if the call is a one-off and you don't want to bother 
+ * calling lvm2_init/lvm2_exit.
+ */
+int lvm2_run(void *handle, const char *cmdline);
+
+/* Release handle */
+void lvm2_exit(void *handle);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/tools/lvm2cmdline.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/lvm2cmdline.h
diff -N src/external/gpl2/lvm2tools/dist/tools/lvm2cmdline.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/lvm2cmdline.h	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,42 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_CMDLINE_H
+#define _LVM_CMDLINE_H
+
+struct cmd_context;
+
+struct cmdline_context {
+        struct arg *the_args;
+        struct command *commands;
+        int num_commands;
+        int commands_size;
+        int interactive;
+};
+
+int lvm2_main(int argc, char **argv, unsigned is_static);
+
+void *cmdlib_lvm2_init(unsigned is_static);
+void lvm_fin(struct cmd_context *cmd);
+
+struct cmd_context *init_lvm(unsigned is_static);
+void lvm_register_commands(void);
+int lvm_split(char *str, int *argc, char **argv, int max);
+int lvm_run_command(struct cmd_context *cmd, int argc, char **argv);
+int lvm_shell(struct cmd_context *cmd, struct cmdline_context *cmdline);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/tools/lvmchange.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/lvmchange.c
diff -N src/external/gpl2/lvm2tools/dist/tools/lvmchange.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/lvmchange.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,25 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+int lvmchange(struct cmd_context *cmd __attribute((unused)),
+	      int argc __attribute((unused)), char **argv __attribute((unused)))
+{
+	log_print("With LVM2 and the device mapper, this program is obsolete.");
+	return ECMD_FAILED;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/lvmcmdlib.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/lvmcmdlib.c
diff -N src/external/gpl2/lvm2tools/dist/tools/lvmcmdlib.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/lvmcmdlib.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,120 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+#include "lvm2cmdline.h"
+#include "label.h"
+#include "memlock.h"
+#include "version.h"
+
+#include "lvm2cmd.h"
+
+#include <signal.h>
+#include <syslog.h>
+#include <libgen.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <sys/resource.h>
+
+void *cmdlib_lvm2_init(unsigned is_static)
+{
+	struct cmd_context *cmd;
+
+	lvm_register_commands();
+
+	if (!(cmd = init_lvm(is_static)))
+		return NULL;
+
+	return (void *) cmd;
+}
+
+int lvm2_run(void *handle, const char *cmdline)
+{
+	int argc, ret, oneoff = 0;
+	char *args[MAX_ARGS], **argv, *cmdcopy = NULL;
+	struct cmd_context *cmd;
+
+	argv = args;
+
+	if (!handle) {
+		oneoff = 1;
+		if (!(handle = lvm2_init())) {
+			log_error("Handle initialisation failed.");
+			return ECMD_FAILED;
+		}
+	}
+
+	cmd = (struct cmd_context *) handle;
+
+	cmd->argv = argv;
+
+	if (!(cmdcopy = dm_strdup(cmdline))) {
+		log_error("Cmdline copy failed.");
+		ret = ECMD_FAILED;
+		goto out;
+	}
+
+	if (lvm_split(cmdcopy, &argc, argv, MAX_ARGS) == MAX_ARGS) {
+		log_error("Too many arguments.  Limit is %d.", MAX_ARGS);
+		ret = EINVALID_CMD_LINE;
+		goto out;
+	}
+
+	if (!argc) {
+		log_error("No command supplied");
+		ret = EINVALID_CMD_LINE;
+		goto out;
+	}
+
+	/* FIXME Temporary - move to libdevmapper */
+	ret = ECMD_PROCESSED;
+	if (!strcmp(cmdline, "_memlock_inc"))
+		memlock_inc();
+	else if (!strcmp(cmdline, "_memlock_dec"))
+		memlock_dec();
+	else
+		ret = lvm_run_command(cmd, argc, argv);
+
+      out:
+	dm_free(cmdcopy);
+
+	if (oneoff)
+		lvm2_exit(handle);
+
+	return ret;
+}
+
+void lvm2_log_level(void *handle, int level)
+{
+	struct cmd_context *cmd = (struct cmd_context *) handle;
+
+	cmd->default_settings.verbose = level - VERBOSE_BASE_LEVEL;
+
+	return;
+}
+
+void lvm2_log_fn(lvm2_log_fn_t log_fn)
+{
+	init_log_fn(log_fn);
+}
+
+void lvm2_exit(void *handle)
+{
+	struct cmd_context *cmd = (struct cmd_context *) handle;
+
+	lvm_fin(cmd);
+}
Index: src/external/gpl2/lvm2tools/dist/tools/lvmcmdline.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/lvmcmdline.c
diff -N src/external/gpl2/lvm2tools/dist/tools/lvmcmdline.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/lvmcmdline.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,1300 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+#include "lvm2cmdline.h"
+#include "label.h"
+#include "version.h"
+
+#include "stub.h"
+#include "lvm2cmd.h"
+#include "last-path-component.h"
+
+#include <signal.h>
+#include <syslog.h>
+#include <libgen.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <sys/resource.h>
+
+#ifdef HAVE_GETOPTLONG
+#  include <getopt.h>
+#  define GETOPTLONG_FN(a, b, c, d, e) getopt_long((a), (b), (c), (d), (e))
+#  define OPTIND_INIT 0
+#else
+struct option {
+};
+extern int optind;
+extern char *optarg;
+#  define GETOPTLONG_FN(a, b, c, d, e) getopt((a), (b), (c))
+#  define OPTIND_INIT 1
+#endif
+
+/*
+ * Table of valid switches
+ */
+static struct arg _the_args[ARG_COUNT + 1] = {
+#define arg(a, b, c, d, e) {b, "", "--" c, d, e, 0, NULL, 0, 0, INT64_C(0), UINT64_C(0), SIGN_NONE, PERCENT_NONE, NULL},
+#include "args.h"
+#undef arg
+};
+
+static struct cmdline_context _cmdline;
+
+int yes_no_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a)
+{
+	a->sign = SIGN_NONE;
+	a->percent = PERCENT_NONE;
+
+	if (!strcmp(a->value, "y")) {
+		a->i_value = 1;
+		a->ui_value = 1;
+	}
+
+	else if (!strcmp(a->value, "n")) {
+		a->i_value = 0;
+		a->ui_value = 0;
+	}
+
+	else
+		return 0;
+
+	return 1;
+}
+
+int yes_no_excl_arg(struct cmd_context *cmd __attribute((unused)),
+		    struct arg *a)
+{
+	a->sign = SIGN_NONE;
+	a->percent = PERCENT_NONE;
+
+	if (!strcmp(a->value, "e") || !strcmp(a->value, "ey") ||
+	    !strcmp(a->value, "ye")) {
+		a->i_value = CHANGE_AE;
+		a->ui_value = CHANGE_AE;
+	}
+
+	else if (!strcmp(a->value, "y")) {
+		a->i_value = CHANGE_AY;
+		a->ui_value = CHANGE_AY;
+	}
+
+	else if (!strcmp(a->value, "n") || !strcmp(a->value, "en") ||
+		 !strcmp(a->value, "ne")) {
+		a->i_value = CHANGE_AN;
+		a->ui_value = CHANGE_AN;
+	}
+
+	else if (!strcmp(a->value, "ln") || !strcmp(a->value, "nl")) {
+		a->i_value = CHANGE_ALN;
+		a->ui_value = CHANGE_ALN;
+	}
+
+	else if (!strcmp(a->value, "ly") || !strcmp(a->value, "yl")) {
+		a->i_value = CHANGE_ALY;
+		a->ui_value = CHANGE_ALY;
+	}
+
+	else
+		return 0;
+
+	return 1;
+}
+
+int metadatatype_arg(struct cmd_context *cmd, struct arg *a)
+{
+	struct format_type *fmt;
+	char *format;
+
+	format = a->value;
+
+	dm_list_iterate_items(fmt, &cmd->formats) {
+		if (!strcasecmp(fmt->name, format) ||
+		    !strcasecmp(fmt->name + 3, format) ||
+		    (fmt->alias && !strcasecmp(fmt->alias, format))) {
+			a->ptr = fmt;
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+static int _get_int_arg(struct arg *a, char **ptr)
+{
+	char *val;
+	long v;
+
+	a->percent = PERCENT_NONE;
+
+	val = a->value;
+	switch (*val) {
+	case '+':
+		a->sign = SIGN_PLUS;
+		val++;
+		break;
+	case '-':
+		a->sign = SIGN_MINUS;
+		val++;
+		break;
+	default:
+		a->sign = SIGN_NONE;
+	}
+
+	if (!isdigit(*val))
+		return 0;
+
+	v = strtol(val, ptr, 10);
+
+	if (*ptr == val)
+		return 0;
+
+	a->i_value = (int32_t) v;
+	a->ui_value = (uint32_t) v;
+	a->i64_value = (int64_t) v;
+	a->ui64_value = (uint64_t) v;
+
+	return 1;
+}
+
+/* Size stored in sectors */
+static int _size_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a, int factor)
+{
+	char *ptr;
+	int i;
+	static const char *suffixes = "kmgtpe";
+	char *val;
+	double v;
+
+	a->percent = PERCENT_NONE;
+
+	val = a->value;
+	switch (*val) {
+	case '+':
+		a->sign = SIGN_PLUS;
+		val++;
+		break;
+	case '-':
+		a->sign = SIGN_MINUS;
+		val++;
+		break;
+	default:
+		a->sign = SIGN_NONE;
+	}
+
+	if (!isdigit(*val))
+		return 0;
+
+	v = strtod(val, &ptr);
+
+	if (ptr == val)
+		return 0;
+
+	if (*ptr) {
+		for (i = strlen(suffixes) - 1; i >= 0; i--)
+			if (suffixes[i] == tolower((int) *ptr))
+				break;
+
+		if (i < 0)
+			return 0;
+
+		while (i-- > 0)
+			v *= 1024;
+
+		v *= 2;
+	} else
+		v *= factor;
+
+	a->i_value = (int32_t) v;
+	a->ui_value = (uint32_t) v;
+	a->i64_value = (int64_t) v;
+	a->ui64_value = (uint64_t) v;
+
+	return 1;
+}
+
+int size_kb_arg(struct cmd_context *cmd, struct arg *a)
+{
+	return _size_arg(cmd, a, 2);
+}
+
+int size_mb_arg(struct cmd_context *cmd, struct arg *a)
+{
+	return _size_arg(cmd, a, 2048);
+}
+
+int int_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a)
+{
+	char *ptr;
+
+	if (!_get_int_arg(a, &ptr) || (*ptr) || (a->sign == SIGN_MINUS))
+		return 0;
+
+	return 1;
+}
+
+int int_arg_with_sign(struct cmd_context *cmd __attribute((unused)), struct arg *a)
+{
+	char *ptr;
+
+	if (!_get_int_arg(a, &ptr) || (*ptr))
+		return 0;
+
+	return 1;
+}
+
+int int_arg_with_sign_and_percent(struct cmd_context *cmd __attribute((unused)),
+				  struct arg *a)
+{
+	char *ptr;
+
+	if (!_get_int_arg(a, &ptr))
+		return 0;
+
+	if (!*ptr)
+		return 1;
+
+	if (*ptr++ != '%')
+		return 0;
+
+	if (!strcasecmp(ptr, "V") || !strcasecmp(ptr, "VG"))
+		a->percent = PERCENT_VG;
+	else if (!strcasecmp(ptr, "L") || !strcasecmp(ptr, "LV"))
+		a->percent = PERCENT_LV;
+	else if (!strcasecmp(ptr, "P") || !strcasecmp(ptr, "PV") ||
+		 !strcasecmp(ptr, "PVS"))
+		a->percent = PERCENT_PVS;
+	else if (!strcasecmp(ptr, "F") || !strcasecmp(ptr, "FR") ||
+		 !strcasecmp(ptr, "FREE"))
+		a->percent = PERCENT_FREE;
+	else
+		return 0;
+
+	return 1;
+}
+
+int minor_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a)
+{
+	char *ptr;
+
+	if (!_get_int_arg(a, &ptr) || (*ptr) || (a->sign == SIGN_MINUS))
+		return 0;
+
+	if (a->i_value > 255) {
+		log_error("Minor number outside range 0-255");
+		return 0;
+	}
+
+	return 1;
+}
+
+int major_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a)
+{
+	char *ptr;
+
+	if (!_get_int_arg(a, &ptr) || (*ptr) || (a->sign == SIGN_MINUS))
+		return 0;
+
+	if (a->i_value > 255) {
+		log_error("Major number outside range 0-255");
+		return 0;
+	}
+
+	/* FIXME Also Check against /proc/devices */
+
+	return 1;
+}
+
+int string_arg(struct cmd_context *cmd __attribute((unused)),
+	       struct arg *a __attribute((unused)))
+{
+	return 1;
+}
+
+int tag_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a)
+{
+	char *pos = a->value;
+
+	if (*pos == '@')
+		pos++;
+
+	if (!validate_name(pos))
+		return 0;
+
+	a->value = pos;
+
+	return 1;
+}
+
+int permission_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a)
+{
+	a->sign = SIGN_NONE;
+
+	if ((!strcmp(a->value, "rw")) || (!strcmp(a->value, "wr")))
+		a->ui_value = LVM_READ | LVM_WRITE;
+
+	else if (!strcmp(a->value, "r"))
+		a->ui_value = LVM_READ;
+
+	else
+		return 0;
+
+	return 1;
+}
+
+int alloc_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a)
+{
+	alloc_policy_t alloc;
+
+	a->sign = SIGN_NONE;
+
+	alloc = get_alloc_from_string(a->value);
+	if (alloc == ALLOC_INVALID)
+		return 0;
+
+	a->ui_value = (uint32_t) alloc;
+
+	return 1;
+}
+
+int segtype_arg(struct cmd_context *cmd, struct arg *a)
+{
+	if (!(a->ptr = (void *) get_segtype_from_string(cmd, a->value)))
+		return 0;
+
+	return 1;
+}
+
+/*
+ * Positive integer, zero or "auto".
+ */
+int readahead_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a)
+{
+	if (!strcasecmp(a->value, "auto")) {
+		a->ui_value = DM_READ_AHEAD_AUTO;
+		return 1;
+	}
+
+	if (!strcasecmp(a->value, "none")) {
+		a->ui_value = DM_READ_AHEAD_NONE;
+		return 1;
+	}
+
+	if (!_size_arg(cmd, a, 1))
+		return 0;
+
+	if (a->sign == SIGN_MINUS)
+		return 0;
+
+	return 1;
+}
+
+static void __alloc(int size)
+{
+	if (!(_cmdline.commands = dm_realloc(_cmdline.commands, sizeof(*_cmdline.commands) * size))) {
+		log_fatal("Couldn't allocate memory.");
+		exit(ECMD_FAILED);
+	}
+
+	_cmdline.commands_size = size;
+}
+
+static void _alloc_command(void)
+{
+	if (!_cmdline.commands_size)
+		__alloc(32);
+
+	if (_cmdline.commands_size <= _cmdline.num_commands)
+		__alloc(2 * _cmdline.commands_size);
+}
+
+static void _create_new_command(const char *name, command_fn command,
+				unsigned flags,
+				const char *desc, const char *usagestr,
+				int nargs, int *args)
+{
+	struct command *nc;
+
+	_alloc_command();
+
+	nc = _cmdline.commands + _cmdline.num_commands++;
+
+	nc->name = name;
+	nc->desc = desc;
+	nc->usage = usagestr;
+	nc->fn = command;
+	nc->flags = flags;
+	nc->num_args = nargs;
+	nc->valid_args = args;
+}
+
+static void _register_command(const char *name, command_fn fn, const char *desc,
+			      unsigned flags, const char *usagestr, ...)
+{
+	int nargs = 0, i;
+	int *args;
+	va_list ap;
+
+	/* count how many arguments we have */
+	va_start(ap, usagestr);
+	while (va_arg(ap, int) >= 0)
+		 nargs++;
+	va_end(ap);
+
+	/* allocate space for them */
+	if (!(args = dm_malloc(sizeof(*args) * nargs))) {
+		log_fatal("Out of memory.");
+		exit(ECMD_FAILED);
+	}
+
+	/* fill them in */
+	va_start(ap, usagestr);
+	for (i = 0; i < nargs; i++)
+		args[i] = va_arg(ap, int);
+	va_end(ap);
+
+	/* enter the command in the register */
+	_create_new_command(name, fn, flags, desc, usagestr, nargs, args);
+}
+
+void lvm_register_commands(void)
+{
+#define xx(a, b, c, d...) _register_command(# a, a, b, c, ## d, \
+					    driverloaded_ARG, \
+					    debug_ARG, help_ARG, help2_ARG, \
+					    version_ARG, verbose_ARG, \
+					    quiet_ARG, config_ARG, -1);
+#include "commands.h"
+#undef xx
+}
+
+static struct command *_find_command(const char *name)
+{
+	int i;
+	char *base;
+
+	base = last_path_component(name);
+
+	for (i = 0; i < _cmdline.num_commands; i++) {
+		if (!strcmp(base, _cmdline.commands[i].name))
+			break;
+	}
+
+	if (i >= _cmdline.num_commands)
+		return 0;
+
+	return _cmdline.commands + i;
+}
+
+static void _short_usage(const char *name)
+{
+	log_error("Run `%s --help' for more information.", name);
+}
+
+static void _usage(const char *name)
+{
+	struct command *com = _find_command(name);
+
+	if (!com)
+		return;
+
+	log_print("%s: %s\n\n%s", com->name, com->desc, com->usage);
+}
+
+/*
+ * Sets up the short and long argument.  If there
+ * is no short argument then the index of the
+ * argument in the the_args array is set as the
+ * long opt value.  Yuck.  Of course this means we
+ * can't have more than 'a' long arguments.
+ */
+static void _add_getopt_arg(int arg, char **ptr, struct option **o)
+{
+	struct arg *a = _cmdline.the_args + arg;
+
+	if (a->short_arg) {
+		*(*ptr)++ = a->short_arg;
+
+		if (a->fn)
+			*(*ptr)++ = ':';
+	}
+#ifdef HAVE_GETOPTLONG
+	if (*(a->long_arg + 2)) {
+		(*o)->name = a->long_arg + 2;
+		(*o)->has_arg = a->fn ? 1 : 0;
+		(*o)->flag = NULL;
+		if (a->short_arg)
+			(*o)->val = a->short_arg;
+		else
+			(*o)->val = arg;
+		(*o)++;
+	}
+#endif
+}
+
+static struct arg *_find_arg(struct command *com, int opt)
+{
+	struct arg *a;
+	int i, arg;
+
+	for (i = 0; i < com->num_args; i++) {
+		arg = com->valid_args[i];
+		a = _cmdline.the_args + arg;
+
+		/*
+		 * opt should equal either the
+		 * short arg, or the index into
+		 * the_args.
+		 */
+		if ((a->short_arg && (opt == a->short_arg)) ||
+		    (!a->short_arg && (opt == arg)))
+			return a;
+	}
+
+	return 0;
+}
+
+static int _process_command_line(struct cmd_context *cmd, int *argc,
+				 char ***argv)
+{
+	int i, opt;
+	char str[((ARG_COUNT + 1) * 2) + 1], *ptr = str;
+	struct option opts[ARG_COUNT + 1], *o = opts;
+	struct arg *a;
+
+	for (i = 0; i < ARG_COUNT; i++) {
+		a = _cmdline.the_args + i;
+
+		/* zero the count and arg */
+		a->count = 0;
+		a->value = 0;
+		a->i_value = 0;
+		a->ui_value = 0;
+		a->i64_value = 0;
+		a->ui64_value = 0;
+	}
+
+	/* fill in the short and long opts */
+	for (i = 0; i < cmd->command->num_args; i++)
+		_add_getopt_arg(cmd->command->valid_args[i], &ptr, &o);
+
+	*ptr = '\0';
+	memset(o, 0, sizeof(*o));
+
+	/* initialise getopt_long & scan for command line switches */
+	optarg = 0;
+	optind = OPTIND_INIT;
+	while ((opt = GETOPTLONG_FN(*argc, *argv, str, opts, NULL)) >= 0) {
+
+		if (opt == '?')
+			return 0;
+
+		a = _find_arg(cmd->command, opt);
+
+		if (!a) {
+			log_fatal("Unrecognised option.");
+			return 0;
+		}
+
+		if (a->count && !(a->flags & ARG_REPEATABLE)) {
+			log_error("Option%s%c%s%s may not be repeated",
+				  a->short_arg ? " -" : "",
+				  a->short_arg ? : ' ',
+				  (a->short_arg && a->long_arg) ?
+				  "/" : "", a->long_arg ? : "");
+			return 0;
+		}
+
+		if (a->fn) {
+			if (!optarg) {
+				log_error("Option requires argument.");
+				return 0;
+			}
+
+			a->value = optarg;
+
+			if (!a->fn(cmd, a)) {
+				log_error("Invalid argument %s", optarg);
+				return 0;
+			}
+		}
+
+		a->count++;
+	}
+
+	*argc -= optind;
+	*argv += optind;
+	return 1;
+}
+
+static int _merge_synonym(struct cmd_context *cmd, int oldarg, int newarg)
+{
+	const struct arg *old;
+	struct arg *new;
+
+	if (arg_count(cmd, oldarg) && arg_count(cmd, newarg)) {
+		log_error("%s and %s are synonyms.  Please only supply one.",
+			  _cmdline.the_args[oldarg].long_arg, _cmdline.the_args[newarg].long_arg);
+		return 0;
+	}
+
+	if (!arg_count(cmd, oldarg))
+		return 1;
+
+	old = _cmdline.the_args + oldarg;
+	new = _cmdline.the_args + newarg;
+
+	new->count = old->count;
+	new->value = old->value;
+	new->i_value = old->i_value;
+	new->ui_value = old->ui_value;
+	new->i64_value = old->i64_value;
+	new->ui64_value = old->ui64_value;
+	new->sign = old->sign;
+
+	return 1;
+}
+
+int version(struct cmd_context *cmd __attribute((unused)),
+	    int argc __attribute((unused)),
+	    char **argv __attribute((unused)))
+{
+	char vsn[80];
+
+	log_print("LVM version:     %s", LVM_VERSION);
+	if (library_version(vsn, sizeof(vsn)))
+		log_print("Library version: %s", vsn);
+	if (driver_version(vsn, sizeof(vsn)))
+		log_print("Driver version:  %s", vsn);
+
+	return ECMD_PROCESSED;
+}
+
+static int _get_settings(struct cmd_context *cmd)
+{
+	cmd->current_settings = cmd->default_settings;
+
+	if (arg_count(cmd, debug_ARG))
+		cmd->current_settings.debug = _LOG_FATAL +
+		    (arg_count(cmd, debug_ARG) - 1);
+
+	if (arg_count(cmd, verbose_ARG))
+		cmd->current_settings.verbose = arg_count(cmd, verbose_ARG);
+
+	if (arg_count(cmd, quiet_ARG)) {
+		cmd->current_settings.debug = 0;
+		cmd->current_settings.verbose = 0;
+	}
+
+	if (arg_count(cmd, test_ARG))
+		cmd->current_settings.test = arg_count(cmd, test_ARG);
+
+	if (arg_count(cmd, driverloaded_ARG)) {
+		cmd->current_settings.activation =
+		    arg_int_value(cmd, driverloaded_ARG,
+				  cmd->default_settings.activation);
+	}
+
+	cmd->current_settings.archive = arg_int_value(cmd, autobackup_ARG, cmd->current_settings.archive);
+	cmd->current_settings.backup = arg_int_value(cmd, autobackup_ARG, cmd->current_settings.backup);
+	cmd->current_settings.cache_vgmetadata = cmd->command->flags & CACHE_VGMETADATA ? 1 : 0;
+	cmd->partial_activation = 0;
+
+	if (arg_count(cmd, partial_ARG)) {
+		cmd->partial_activation = 1;
+		log_print("Partial mode. Incomplete volume groups will "
+			  "be activated read-only.");
+	}
+
+	if (arg_count(cmd, ignorelockingfailure_ARG))
+		init_ignorelockingfailure(1);
+	else
+		init_ignorelockingfailure(0);
+
+	if (arg_count(cmd, nosuffix_ARG))
+		cmd->current_settings.suffix = 0;
+
+	if (arg_count(cmd, units_ARG))
+		if (!(cmd->current_settings.unit_factor =
+		      units_to_bytes(arg_str_value(cmd, units_ARG, ""),
+				     &cmd->current_settings.unit_type))) {
+			log_error("Invalid units specification");
+			return EINVALID_CMD_LINE;
+		}
+
+	if (arg_count(cmd, trustcache_ARG)) {
+		if (arg_count(cmd, all_ARG)) {
+			log_error("--trustcache is incompatible with --all");
+			return EINVALID_CMD_LINE;
+		}
+		init_trust_cache(1);
+		log_warn("WARNING: Cache file of PVs will be trusted.  "
+			  "New devices holding PVs may get ignored.");
+	} else
+		init_trust_cache(0);
+
+	/* Handle synonyms */
+	if (!_merge_synonym(cmd, resizable_ARG, resizeable_ARG) ||
+	    !_merge_synonym(cmd, allocation_ARG, allocatable_ARG) ||
+	    !_merge_synonym(cmd, allocation_ARG, resizeable_ARG))
+		return EINVALID_CMD_LINE;
+
+	/* Zero indicates success */
+	return 0;
+}
+
+static int _process_common_commands(struct cmd_context *cmd)
+{
+	if (arg_count(cmd, help_ARG) || arg_count(cmd, help2_ARG)) {
+		_usage(cmd->command->name);
+		return ECMD_PROCESSED;
+	}
+
+	if (arg_count(cmd, version_ARG)) {
+		return version(cmd, 0, (char **) NULL);
+	}
+
+	/* Zero indicates it's OK to continue processing this command */
+	return 0;
+}
+
+static void _display_help(void)
+{
+	int i;
+
+	log_error("Available lvm commands:");
+	log_error("Use 'lvm help <command>' for more information");
+	log_error(" ");
+
+	for (i = 0; i < _cmdline.num_commands; i++) {
+		struct command *com = _cmdline.commands + i;
+
+		log_error("%-16.16s%s", com->name, com->desc);
+	}
+}
+
+int help(struct cmd_context *cmd __attribute((unused)), int argc, char **argv)
+{
+	if (!argc)
+		_display_help();
+	else {
+		int i;
+		for (i = 0; i < argc; i++)
+			_usage(argv[i]);
+	}
+
+	return 0;
+}
+
+static int _override_settings(struct cmd_context *cmd)
+{
+	if (!(cmd->cft_override = create_config_tree_from_string(cmd, arg_str_value(cmd, config_ARG, "")))) {
+		log_error("Failed to set overridden configuration entries.");
+		return EINVALID_CMD_LINE;
+	}
+
+	return 0;
+}
+
+static void _apply_settings(struct cmd_context *cmd)
+{
+	init_debug(cmd->current_settings.debug);
+	init_verbose(cmd->current_settings.verbose + VERBOSE_BASE_LEVEL);
+	init_test(cmd->current_settings.test);
+	init_full_scan_done(0);
+	init_mirror_in_sync(0);
+
+	init_msg_prefix(cmd->default_settings.msg_prefix);
+	init_cmd_name(cmd->default_settings.cmd_name);
+
+	archive_enable(cmd, cmd->current_settings.archive);
+	backup_enable(cmd, cmd->current_settings.backup);
+
+	set_activation(cmd->current_settings.activation);
+
+	cmd->fmt = arg_ptr_value(cmd, metadatatype_ARG,
+				 cmd->current_settings.fmt);
+	cmd->handles_missing_pvs = 0;
+}
+
+static char *_copy_command_line(struct cmd_context *cmd, int argc, char **argv)
+{
+	int i, space;
+
+	/*
+	 * Build up the complete command line, used as a
+	 * description for backups.
+	 */
+	if (!dm_pool_begin_object(cmd->mem, 128))
+		goto_bad;
+
+	for (i = 0; i < argc; i++) {
+		space = strchr(argv[i], ' ') ? 1 : 0;
+
+		if (space && !dm_pool_grow_object(cmd->mem, "'", 1))
+			goto_bad;
+
+		if (!dm_pool_grow_object(cmd->mem, argv[i], strlen(argv[i])))
+			goto_bad;
+
+		if (space && !dm_pool_grow_object(cmd->mem, "'", 1))
+			goto_bad;
+
+		if (i < (argc - 1))
+			if (!dm_pool_grow_object(cmd->mem, " ", 1))
+				goto_bad;
+	}
+
+	/*
+	 * Terminate.
+	 */
+	if (!dm_pool_grow_object(cmd->mem, "\0", 1))
+		goto_bad;
+
+	return dm_pool_end_object(cmd->mem);
+
+      bad:
+	log_err("Couldn't copy command line.");
+	dm_pool_abandon_object(cmd->mem);
+	return NULL;
+}
+
+int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
+{
+	int ret = 0;
+	int locking_type;
+
+	init_error_message_produced(0);
+
+	/* each command should start out with sigint flag cleared */
+	sigint_clear();
+
+	if (!(cmd->cmd_line = _copy_command_line(cmd, argc, argv)))
+		return ECMD_FAILED;
+
+	log_debug("Parsing: %s", cmd->cmd_line);
+
+	if (!(cmd->command = _find_command(argv[0])))
+		return ENO_SUCH_CMD;
+
+	if (!_process_command_line(cmd, &argc, &argv)) {
+		log_error("Error during parsing of command line.");
+		return EINVALID_CMD_LINE;
+	}
+
+	set_cmd_name(cmd->command->name);
+
+	if (arg_count(cmd, config_ARG))
+		if ((ret = _override_settings(cmd)))
+			goto_out;
+
+	if (arg_count(cmd, config_ARG) || !cmd->config_valid || config_files_changed(cmd)) {
+		/* Reinitialise various settings inc. logging, filters */
+		if (!refresh_toolcontext(cmd)) {
+			log_error("Updated config file invalid. Aborting.");
+			return ECMD_FAILED;
+		}
+	}
+
+	if ((ret = _get_settings(cmd)))
+		goto_out;
+	_apply_settings(cmd);
+
+	log_debug("Processing: %s", cmd->cmd_line);
+
+#ifdef O_DIRECT_SUPPORT
+	log_debug("O_DIRECT will be used");
+#endif
+
+	if ((ret = _process_common_commands(cmd)))
+		goto_out;
+
+	if (arg_count(cmd, nolocking_ARG))
+		locking_type = 0;
+	else
+		locking_type = find_config_tree_int(cmd,
+					       "global/locking_type", 1);
+
+	if (!init_locking(locking_type, cmd)) {
+		log_error("Locking type %d initialisation failed.",
+			  locking_type);
+		ret = ECMD_FAILED;
+		goto out;
+	}
+
+	ret = cmd->command->fn(cmd, argc, argv);
+
+	fin_locking();
+
+      out:
+	if (test_mode()) {
+		log_verbose("Test mode: Wiping internal cache");
+		lvmcache_destroy(cmd, 1);
+	}
+
+	if (cmd->cft_override) {
+		destroy_config_tree(cmd->cft_override);
+		cmd->cft_override = NULL;
+		/* Move this? */
+		if (!refresh_toolcontext(cmd))
+			stack;
+	}
+
+	/* FIXME Move this? */
+	cmd->current_settings = cmd->default_settings;
+	_apply_settings(cmd);
+
+	/*
+	 * free off any memory the command used.
+	 */
+	dm_pool_empty(cmd->mem);
+
+	if (ret == EINVALID_CMD_LINE && !_cmdline.interactive)
+		_short_usage(cmd->command->name);
+
+	log_debug("Completed: %s", cmd->cmd_line);
+
+	return ret;
+}
+
+int lvm_split(char *str, int *argc, char **argv, int max)
+{
+	char *b = str, *e;
+	*argc = 0;
+
+	while (*b) {
+		while (*b && isspace(*b))
+			b++;
+
+		if ((!*b) || (*b == '#'))
+			break;
+
+		e = b;
+		while (*e && !isspace(*e))
+			e++;
+
+		argv[(*argc)++] = b;
+		if (!*e)
+			break;
+		*e++ = '\0';
+		b = e;
+		if (*argc == max)
+			break;
+	}
+
+	return *argc;
+}
+
+static void _init_rand(void)
+{
+	srand((unsigned) time(NULL) + (unsigned) getpid());
+}
+
+static const char *_get_cmdline(pid_t pid)
+{
+	static char _proc_cmdline[32];
+	char buf[256];
+	int fd;
+
+	snprintf(buf, sizeof(buf), DEFAULT_PROC_DIR "/%u/cmdline", pid);
+	if ((fd = open(buf, O_RDONLY)) > 0) {
+		read(fd, _proc_cmdline, sizeof(_proc_cmdline) - 1);
+		_proc_cmdline[sizeof(_proc_cmdline) - 1] = '\0';
+		close(fd);
+	} else
+		_proc_cmdline[0] = '\0';
+
+	return _proc_cmdline;
+}
+
+static const char *_get_filename(int fd)
+{
+	static char filename[PATH_MAX];
+	char buf[32];	/* Assumes short DEFAULT_PROC_DIR */
+	int size;
+
+	snprintf(buf, sizeof(buf), DEFAULT_PROC_DIR "/self/fd/%u", fd);
+
+	if ((size = readlink(buf, filename, sizeof(filename) - 1)) == -1)
+		filename[0] = '\0';
+	else
+		filename[size] = '\0';
+
+	return filename;
+}
+
+static void _close_descriptor(int fd, unsigned suppress_warnings,
+			      const char *command, pid_t ppid,
+			      const char *parent_cmdline)
+{
+	int r;
+	const char *filename;
+
+	/* Ignore bad file descriptors */
+	if (fcntl(fd, F_GETFD) == -1 && errno == EBADF)
+		return;
+
+	if (!suppress_warnings)
+		filename = _get_filename(fd);
+
+	r = close(fd);
+	if (suppress_warnings)
+		return;
+
+	if (!r)
+		fprintf(stderr, "File descriptor %d (%s) leaked on "
+			"%s invocation.", fd, filename, command);
+	else if (errno == EBADF)
+		return;
+	else
+		fprintf(stderr, "Close failed on stray file descriptor "
+			"%d (%s): %s", fd, filename, strerror(errno));
+
+	fprintf(stderr, " Parent PID %" PRIpid_t ": %s\n", ppid, parent_cmdline);
+}
+
+static void _close_stray_fds(const char *command)
+{
+	struct rlimit rlim;
+	int fd;
+	unsigned suppress_warnings = 0;
+	pid_t ppid = getppid();
+	const char *parent_cmdline = _get_cmdline(ppid);
+
+	if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
+		fprintf(stderr, "getrlimit(RLIMIT_NOFILE) failed: %s\n",
+			strerror(errno));
+		return;
+	}
+
+	if (getenv("LVM_SUPPRESS_FD_WARNINGS"))
+		suppress_warnings = 1;
+
+	for (fd = 3; fd < rlim.rlim_cur; fd++)
+		_close_descriptor(fd, suppress_warnings, command, ppid,
+				  parent_cmdline);
+}
+
+struct cmd_context *init_lvm(unsigned is_static)
+{
+	struct cmd_context *cmd;
+
+	_cmdline.the_args = &_the_args[0];
+
+	if (!(cmd = create_toolcontext(_cmdline.the_args, is_static, 0)))
+		return_NULL;
+
+	_init_rand();
+
+	_apply_settings(cmd);
+
+	return cmd;
+}
+
+static void _fin_commands(void)
+{
+	int i;
+
+	for (i = 0; i < _cmdline.num_commands; i++)
+		dm_free(_cmdline.commands[i].valid_args);
+
+	dm_free(_cmdline.commands);
+}
+
+void lvm_fin(struct cmd_context *cmd)
+{
+	_fin_commands();
+	destroy_toolcontext(cmd);
+}
+
+static int _run_script(struct cmd_context *cmd, int argc, char **argv)
+{
+	FILE *script;
+
+	char buffer[CMD_LEN];
+	int ret = 0;
+	int magic_number = 0;
+	char *script_file = argv[0];
+
+	if ((script = fopen(script_file, "r")) == NULL)
+		return ENO_SUCH_CMD;
+
+	while (fgets(buffer, sizeof(buffer), script) != NULL) {
+		if (!magic_number) {
+			if (buffer[0] == '#' && buffer[1] == '!')
+				magic_number = 1;
+			else {
+				ret = ENO_SUCH_CMD;
+				break;
+			}
+		}
+		if ((strlen(buffer) == sizeof(buffer) - 1)
+		    && (buffer[sizeof(buffer) - 1] - 2 != '\n')) {
+			buffer[50] = '\0';
+			log_error("Line too long (max 255) beginning: %s",
+				  buffer);
+			ret = EINVALID_CMD_LINE;
+			break;
+		}
+		if (lvm_split(buffer, &argc, argv, MAX_ARGS) == MAX_ARGS) {
+			buffer[50] = '\0';
+			log_error("Too many arguments: %s", buffer);
+			ret = EINVALID_CMD_LINE;
+			break;
+		}
+		if (!argc)
+			continue;
+		if (!strcmp(argv[0], "quit") || !strcmp(argv[0], "exit"))
+			break;
+		ret = lvm_run_command(cmd, argc, argv);
+		if (ret != ECMD_PROCESSED) {
+			if (!error_message_produced()) {
+				log_debug("Internal error: Failed command did not use log_error");
+				log_error("Command failed with status code %d.", ret);
+			}
+			break;
+		}
+	}
+
+	if (fclose(script))
+		log_sys_error("fclose", script_file);
+
+	return ret;
+}
+
+/*
+ * Determine whether we should fall back and exec the equivalent LVM1 tool
+ */
+static int _lvm1_fallback(struct cmd_context *cmd)
+{
+	char vsn[80];
+	int dm_present;
+
+	if (!find_config_tree_int(cmd, "global/fallback_to_lvm1",
+			     DEFAULT_FALLBACK_TO_LVM1) ||
+	    strncmp(cmd->kernel_vsn, "2.4.", 4))
+		return 0;
+
+	log_suppress(1);
+	dm_present = driver_version(vsn, sizeof(vsn));
+	log_suppress(0);
+
+	if (dm_present || !lvm1_present(cmd))
+		return 0;
+
+	return 1;
+}
+
+static void _exec_lvm1_command(char **argv)
+{
+	char path[PATH_MAX];
+
+	if (dm_snprintf(path, sizeof(path), "%s.lvm1", argv[0]) < 0) {
+		log_error("Failed to create LVM1 tool pathname");
+		return;
+	}
+
+	execvp(path, argv);
+	log_sys_error("execvp", path);
+}
+
+static void _nonroot_warning()
+{
+	if (getuid() || geteuid())
+		log_warn("WARNING: Running as a non-root user. Functionality may be unavailable.");
+}
+
+int lvm2_main(int argc, char **argv, unsigned is_static)
+{
+	char *base;
+	int ret, alias = 0;
+	struct cmd_context *cmd;
+
+	base = last_path_component(argv[0]);
+	if (strcmp(base, "lvm") && strcmp(base, "lvm.static") &&
+	    strcmp(base, "initrd-lvm"))
+		alias = 1;
+
+	_close_stray_fds(base);
+
+	if (is_static && strcmp(base, "lvm.static") &&
+	    path_exists(LVM_SHARED_PATH) &&
+	    !getenv("LVM_DID_EXEC")) {
+		setenv("LVM_DID_EXEC", base, 1);
+		execvp(LVM_SHARED_PATH, argv);
+		unsetenv("LVM_DID_EXEC");
+	}
+
+	if (!(cmd = init_lvm(is_static)))
+		return -1;
+
+	cmd->argv = argv;
+	lvm_register_commands();
+
+	if (_lvm1_fallback(cmd)) {
+		/* Attempt to run equivalent LVM1 tool instead */
+		if (!alias) {
+			argv++;
+			argc--;
+			alias = 0;
+		}
+		if (!argc) {
+			log_error("Falling back to LVM1 tools, but no "
+				  "command specified.");
+			return ECMD_FAILED;
+		}
+		_exec_lvm1_command(argv);
+		return ECMD_FAILED;
+	}
+#ifdef READLINE_SUPPORT
+	if (!alias && argc == 1) {
+		_nonroot_warning();
+		ret = lvm_shell(cmd, &_cmdline);
+		goto out;
+	}
+#endif
+
+	if (!alias) {
+		if (argc < 2) {
+			log_fatal("Please supply an LVM command.");
+			_display_help();
+			ret = EINVALID_CMD_LINE;
+			goto out;
+		}
+
+		argc--;
+		argv++;
+	}
+
+	_nonroot_warning();
+	ret = lvm_run_command(cmd, argc, argv);
+	if ((ret == ENO_SUCH_CMD) && (!alias))
+		ret = _run_script(cmd, argc, argv);
+	if (ret == ENO_SUCH_CMD)
+		log_error("No such command.  Try 'help'.");
+
+	if ((ret != ECMD_PROCESSED) && !error_message_produced()) {
+		log_debug("Internal error: Failed command did not use log_error");
+		log_error("Command failed with status code %d.", ret);
+	}
+
+      out:
+	lvm_fin(cmd);
+	if (ret == ECMD_PROCESSED)
+		ret = 0;
+	return ret;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/lvmdiskscan.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/lvmdiskscan.c
diff -N src/external/gpl2/lvm2tools/dist/tools/lvmdiskscan.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/lvmdiskscan.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,156 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Changelog
+ *
+ *   05/02/2002 - First drop [HM]
+ */
+
+#include "tools.h"
+
+int disks_found;
+int parts_found;
+int pv_disks_found;
+int pv_parts_found;
+int max_len;
+
+static int _get_max_dev_name_len(struct dev_filter *filter)
+{
+	int len = 0;
+	int maxlen = 0;
+	struct dev_iter *iter;
+	struct device *dev;
+
+	if (!(iter = dev_iter_create(filter, 1))) {
+		log_error("dev_iter_create failed");
+		return 0;
+	}
+
+	/* Do scan */
+	for (dev = dev_iter_get(iter); dev; dev = dev_iter_get(iter)) {
+		len = strlen(dev_name(dev));
+		if (len > maxlen)
+			maxlen = len;
+	}
+	dev_iter_destroy(iter);
+
+	return maxlen;
+}
+
+static void _count(struct device *dev, int *disks, int *parts)
+{
+	int c = dev_name(dev)[strlen(dev_name(dev)) - 1];
+
+	if (!isdigit(c))
+		(*disks)++;
+	else
+		(*parts)++;
+}
+
+static void _print(struct cmd_context *cmd, const struct device *dev,
+		   uint64_t size, const char *what)
+{
+	log_print("%-*s [%15s] %s", max_len, dev_name(dev),
+		  display_size(cmd, size), what ? : "");
+}
+
+static int _check_device(struct cmd_context *cmd, struct device *dev)
+{
+	char buffer;
+	uint64_t size;
+
+	if (!dev_open(dev)) {
+		return 0;
+	}
+	if (!dev_read(dev, UINT64_C(0), (size_t) 1, &buffer)) {
+		dev_close(dev);
+		return 0;
+	}
+	if (!dev_get_size(dev, &size)) {
+		log_error("Couldn't get size of \"%s\"", dev_name(dev));
+	}
+	_print(cmd, dev, size, NULL);
+	_count(dev, &disks_found, &parts_found);
+	if (!dev_close(dev)) {
+		log_error("dev_close on \"%s\" failed", dev_name(dev));
+		return 0;
+	}
+	return 1;
+}
+
+int lvmdiskscan(struct cmd_context *cmd, int argc __attribute((unused)),
+		char **argv __attribute((unused)))
+{
+	uint64_t size;
+	struct dev_iter *iter;
+	struct device *dev;
+	struct label *label;
+
+	/* initialise these here to avoid problems with the lvm shell */
+	disks_found = 0;
+	parts_found = 0;
+	pv_disks_found = 0;
+	pv_parts_found = 0;
+
+	if (arg_count(cmd, lvmpartition_ARG))
+		log_warn("WARNING: only considering LVM devices");
+
+	max_len = _get_max_dev_name_len(cmd->filter);
+
+	if (!(iter = dev_iter_create(cmd->filter, 0))) {
+		log_error("dev_iter_create failed");
+		return ECMD_FAILED;
+	}
+
+	/* Do scan */
+	for (dev = dev_iter_get(iter); dev; dev = dev_iter_get(iter)) {
+		/* Try if it is a PV first */
+		if ((label_read(dev, &label, UINT64_C(0)))) {
+			if (!dev_get_size(dev, &size)) {
+				log_error("Couldn't get size of \"%s\"",
+					  dev_name(dev));
+				continue;
+			}
+			_print(cmd, dev, size, "LVM physical volume");
+			_count(dev, &pv_disks_found, &pv_parts_found);
+			continue;
+		}
+		/* If user just wants PVs we are done */
+		if (arg_count(cmd, lvmpartition_ARG))
+			continue;
+
+		/* What other device is it? */
+		if (!_check_device(cmd, dev))
+			continue;
+	}
+	dev_iter_destroy(iter);
+
+	/* Display totals */
+	if (!arg_count(cmd, lvmpartition_ARG)) {
+		log_print("%d disk%s",
+			  disks_found, disks_found == 1 ? "" : "s");
+		log_print("%d partition%s",
+			  parts_found, parts_found == 1 ? "" : "s");
+	}
+	log_print("%d LVM physical volume whole disk%s",
+		  pv_disks_found, pv_disks_found == 1 ? "" : "s");
+	log_print("%d LVM physical volume%s",
+		  pv_parts_found, pv_parts_found == 1 ? "" : "s");
+
+	return ECMD_PROCESSED;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/lvreduce.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/lvreduce.c
diff -N src/external/gpl2/lvm2tools/dist/tools/lvreduce.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/lvreduce.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,23 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+int lvreduce(struct cmd_context *cmd, int argc, char **argv)
+{
+	return lvresize(cmd, argc, argv);
+}
Index: src/external/gpl2/lvm2tools/dist/tools/lvremove.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/lvremove.c
diff -N src/external/gpl2/lvm2tools/dist/tools/lvremove.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/lvremove.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,40 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
+			   void *handle __attribute((unused)))
+{
+	if (!lv_remove_single(cmd, lv, arg_count(cmd, force_ARG)))
+		return ECMD_FAILED;
+
+	return ECMD_PROCESSED;
+}
+
+int lvremove(struct cmd_context *cmd, int argc, char **argv)
+{
+	if (!argc) {
+		log_error("Please enter one or more logical volume paths");
+		return EINVALID_CMD_LINE;
+	}
+
+	cmd->handles_missing_pvs = 1;
+
+	return process_each_lv(cmd, argc, argv, LCK_VG_WRITE, NULL,
+			       &lvremove_single);
+}
Index: src/external/gpl2/lvm2tools/dist/tools/lvrename.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/lvrename.c
diff -N src/external/gpl2/lvm2tools/dist/tools/lvrename.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/lvrename.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,130 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+#include "lvm-types.h"
+
+
+/*
+ * lvrename command implementation.
+ * Check arguments and call lv_rename() to execute the request.
+ */
+int lvrename(struct cmd_context *cmd, int argc, char **argv)
+{
+	size_t maxlen;
+	char *lv_name_old, *lv_name_new;
+	const char *vg_name, *vg_name_new, *vg_name_old;
+	char *st;
+
+	struct volume_group *vg;
+	struct lv_list *lvl;
+
+	if (argc == 3) {
+		vg_name = skip_dev_dir(cmd, argv[0], NULL);
+		lv_name_old = argv[1];
+		lv_name_new = argv[2];
+		if (strchr(lv_name_old, '/') &&
+		    (vg_name_old = extract_vgname(cmd, lv_name_old)) &&
+		    strcmp(vg_name_old, vg_name)) {
+			log_error("Please use a single volume group name "
+				  "(\"%s\" or \"%s\")", vg_name, vg_name_old);
+			return EINVALID_CMD_LINE;
+		}
+	} else if (argc == 2) {
+		lv_name_old = argv[0];
+		lv_name_new = argv[1];
+		vg_name = extract_vgname(cmd, lv_name_old);
+	} else {
+		log_error("Old and new logical volume names required");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (!validate_name(vg_name)) {
+		log_error("Please provide a valid volume group name");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (strchr(lv_name_new, '/') &&
+	    (vg_name_new = extract_vgname(cmd, lv_name_new)) &&
+	    strcmp(vg_name, vg_name_new)) {
+		log_error("Logical volume names must "
+			  "have the same volume group (\"%s\" or \"%s\")",
+			  vg_name, vg_name_new);
+		return EINVALID_CMD_LINE;
+	}
+
+	if ((st = strrchr(lv_name_old, '/')))
+		lv_name_old = st + 1;
+
+	if ((st = strrchr(lv_name_new, '/')))
+		lv_name_new = st + 1;
+
+	/* Check sanity of new name */
+	maxlen = NAME_LEN - strlen(vg_name) - strlen(cmd->dev_dir) - 3;
+	if (strlen(lv_name_new) > maxlen) {
+		log_error("New logical volume path exceeds maximum length "
+			  "of %" PRIsize_t "!", maxlen);
+		return ECMD_FAILED;
+	}
+
+	if (!*lv_name_new) {
+		log_error("New logical volume name may not be blank");
+		return ECMD_FAILED;
+	}
+
+	if (!apply_lvname_restrictions(lv_name_new)) {
+		stack;
+		return ECMD_FAILED;
+	}
+
+	if (!validate_name(lv_name_new)) {
+		log_error("New logical volume name \"%s\" is invalid",
+		     lv_name_new);
+		return EINVALID_CMD_LINE;
+	}
+
+	if (!strcmp(lv_name_old, lv_name_new)) {
+		log_error("Old and new logical volume names must differ");
+		return EINVALID_CMD_LINE;
+	}
+
+	log_verbose("Checking for existing volume group \"%s\"", vg_name);
+	if (!(vg = vg_lock_and_read(cmd, vg_name, NULL, LCK_VG_WRITE,
+				    CLUSTERED | EXPORTED_VG | LVM_WRITE,
+				    CORRECT_INCONSISTENT)))
+		return ECMD_FAILED;
+
+	if (!(lvl = find_lv_in_vg(vg, lv_name_old))) {
+		log_error("Existing logical volume \"%s\" not found in "
+			  "volume group \"%s\"", lv_name_old, vg_name);
+		goto error;
+	}
+
+	if (!lv_rename(cmd, lvl->lv, lv_name_new))
+		goto error;
+
+	unlock_vg(cmd, vg_name);
+
+	log_print("Renamed \"%s\" to \"%s\" in volume group \"%s\"",
+		  lv_name_old, lv_name_new, vg_name);
+
+	return ECMD_PROCESSED;
+
+      error:
+	unlock_vg(cmd, vg_name);
+	return ECMD_FAILED;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/lvresize.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/lvresize.c
diff -N src/external/gpl2/lvm2tools/dist/tools/lvresize.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/lvresize.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,679 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+#define SIZE_BUF 128
+
+struct lvresize_params {
+	const char *vg_name;
+	const char *lv_name;
+
+	uint32_t stripes;
+	uint32_t stripe_size;
+	uint32_t mirrors;
+
+	const struct segment_type *segtype;
+
+	/* size */
+	uint32_t extents;
+	uint64_t size;
+	sign_t sign;
+	percent_t percent;
+
+	enum {
+		LV_ANY = 0,
+		LV_REDUCE = 1,
+		LV_EXTEND = 2
+	} resize;
+
+	int resizefs;
+	int nofsck;
+
+	int argc;
+	char **argv;
+};
+
+static int validate_stripesize(struct cmd_context *cmd,
+			       const struct volume_group *vg,
+			       struct lvresize_params *lp)
+{
+	if (arg_sign_value(cmd, stripesize_ARG, 0) == SIGN_MINUS) {
+		log_error("Stripesize may not be negative.");
+		return 0;
+	}
+
+	if (arg_uint_value(cmd, stripesize_ARG, 0) > STRIPE_SIZE_LIMIT * 2) {
+		log_error("Stripe size cannot be larger than %s",
+			  display_size(cmd, (uint64_t) STRIPE_SIZE_LIMIT));
+		return 0;
+	}
+
+	if (!(vg->fid->fmt->features & FMT_SEGMENTS))
+		log_warn("Varied stripesize not supported. Ignoring.");
+	else if (arg_uint_value(cmd, stripesize_ARG, 0) > vg->extent_size * 2) {
+		log_error("Reducing stripe size %s to maximum, "
+			  "physical extent size %s",
+			  display_size(cmd,
+				       (uint64_t) arg_uint_value(cmd, stripesize_ARG, 0)),
+			  display_size(cmd, (uint64_t) vg->extent_size));
+		lp->stripe_size = vg->extent_size;
+	} else
+		lp->stripe_size = arg_uint_value(cmd, stripesize_ARG, 0);
+
+	if (lp->mirrors) {
+		log_error("Mirrors and striping cannot be combined yet.");
+		return 0;
+	}
+	if (lp->stripe_size & (lp->stripe_size - 1)) {
+		log_error("Stripe size must be power of 2");
+		return 0;
+	}
+
+	return 1;
+}
+
+static int confirm_resizefs_reduce(struct cmd_context *cmd,
+				   const struct volume_group *vg,
+				   const struct logical_volume *lv,
+				   const struct lvresize_params *lp)
+{
+	struct lvinfo info;
+
+	memset(&info, 0, sizeof(info));
+
+	if (!lv_info(cmd, lv, &info, 1, 0) && driver_version(NULL, 0)) {
+		log_error("lv_info failed: aborting");
+		return 0;
+	}
+
+	if (lp->resizefs && !info.exists) {
+		log_error("Logical volume %s must be activated "
+			  "before resizing filesystem", lp->lv_name);
+		return 0;
+	}
+
+	if (info.exists && !lp->resizefs && (lp->resize == LV_REDUCE)) {
+		log_warn("WARNING: Reducing active%s logical volume "
+			 "to %s", info.open_count ? " and open" : "",
+			 display_size(cmd, (uint64_t) lp->extents *
+				      vg->extent_size));
+
+		log_warn("THIS MAY DESTROY YOUR DATA "
+			 "(filesystem etc.)");
+
+		if (!arg_count(cmd, force_ARG)) {
+			if (yes_no_prompt("Do you really want to "
+					  "reduce %s? [y/n]: ",
+					  lp->lv_name) == 'n') {
+				log_print("Logical volume %s NOT "
+					  "reduced", lp->lv_name);
+				return 0;
+			}
+			if (sigint_caught())
+				return 0;
+		}
+	}
+
+	return 1;
+}
+
+static int do_resizefs_reduce(const struct cmd_context *cmd,
+			      const struct volume_group *vg,
+			      const struct lvresize_params *lp)
+{
+	char lv_path[PATH_MAX];
+	char size_buf[SIZE_BUF];
+
+	if (dm_snprintf(lv_path, PATH_MAX, "%s%s/%s", cmd->dev_dir,
+			lp->vg_name, lp->lv_name) < 0) {
+		log_error("Couldn't create LV path for %s",
+			  lp->lv_name);
+		return 0;
+	}
+
+	if (dm_snprintf(size_buf, SIZE_BUF, "%" PRIu64,
+			(uint64_t) lp->extents * vg->extent_size / 2) < 0) {
+		log_error("Couldn't generate new LV size string");
+		return 0;
+	}
+
+	if (!lp->nofsck)
+		if (!exec_cmd("fsadm", "check", lv_path, NULL))
+			return_0;
+
+	if (lp->resize == LV_REDUCE)
+		if (!exec_cmd("fsadm", "resize", lv_path, size_buf))
+			return_0;
+
+	return 1;
+}
+
+static int _lvresize_params(struct cmd_context *cmd, int argc, char **argv,
+			    struct lvresize_params *lp)
+{
+	const char *cmd_name;
+	char *st;
+	unsigned dev_dir_found = 0;
+
+	lp->sign = SIGN_NONE;
+	lp->resize = LV_ANY;
+
+	cmd_name = command_name(cmd);
+	if (!strcmp(cmd_name, "lvreduce"))
+		lp->resize = LV_REDUCE;
+	if (!strcmp(cmd_name, "lvextend"))
+		lp->resize = LV_EXTEND;
+
+	/*
+	 * Allow omission of extents and size if the user has given us
+	 * one or more PVs.  Most likely, the intent was "resize this
+	 * LV the best you can with these PVs"
+	 */
+	if ((arg_count(cmd, extents_ARG) + arg_count(cmd, size_ARG) == 0) &&
+	    (argc >= 2)) {
+		lp->extents = 100;
+		lp->percent = PERCENT_PVS;
+		lp->sign = SIGN_PLUS;
+	} else if ((arg_count(cmd, extents_ARG) +
+		    arg_count(cmd, size_ARG) != 1)) {
+		log_error("Please specify either size or extents but not "
+			  "both.");
+		return 0;
+	}
+
+	if (arg_count(cmd, extents_ARG)) {
+		lp->extents = arg_uint_value(cmd, extents_ARG, 0);
+		lp->sign = arg_sign_value(cmd, extents_ARG, SIGN_NONE);
+		lp->percent = arg_percent_value(cmd, extents_ARG, PERCENT_NONE);
+	}
+
+	/* Size returned in kilobyte units; held in sectors */
+	if (arg_count(cmd, size_ARG)) {
+		lp->size = arg_uint64_value(cmd, size_ARG, UINT64_C(0));
+		lp->sign = arg_sign_value(cmd, size_ARG, SIGN_NONE);
+		lp->percent = PERCENT_NONE;
+	}
+
+	if (lp->resize == LV_EXTEND && lp->sign == SIGN_MINUS) {
+		log_error("Negative argument not permitted - use lvreduce");
+		return 0;
+	}
+
+	if (lp->resize == LV_REDUCE && lp->sign == SIGN_PLUS) {
+		log_error("Positive sign not permitted - use lvextend");
+		return 0;
+	}
+
+	lp->resizefs = arg_count(cmd, resizefs_ARG) ? 1 : 0;
+	lp->nofsck = arg_count(cmd, nofsck_ARG) ? 1 : 0;
+
+	if (!argc) {
+		log_error("Please provide the logical volume name");
+		return 0;
+	}
+
+	lp->lv_name = argv[0];
+	argv++;
+	argc--;
+
+	if (!(lp->lv_name = skip_dev_dir(cmd, lp->lv_name, &dev_dir_found)) ||
+	    !(lp->vg_name = extract_vgname(cmd, lp->lv_name))) {
+		log_error("Please provide a volume group name");
+		return 0;
+	}
+
+	if (!validate_name(lp->vg_name)) {
+		log_error("Volume group name %s has invalid characters",
+			  lp->vg_name);
+		return 0;
+	}
+
+	if ((st = strrchr(lp->lv_name, '/')))
+		lp->lv_name = st + 1;
+
+	lp->argc = argc;
+	lp->argv = argv;
+
+	return 1;
+}
+
+static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
+		     struct lvresize_params *lp)
+{
+	struct logical_volume *lv;
+	struct lvinfo info;
+	uint32_t stripesize_extents = 0;
+	uint32_t seg_stripes = 0, seg_stripesize = 0, seg_size = 0;
+	uint32_t seg_mirrors = 0;
+	uint32_t extents_used = 0;
+	uint32_t size_rest;
+	uint32_t pv_extent_count = 0;
+	alloc_policy_t alloc;
+	struct logical_volume *lock_lv;
+	struct lv_list *lvl;
+	struct lv_segment *seg;
+	uint32_t seg_extents;
+	uint32_t sz, str;
+	struct dm_list *pvh = NULL;
+	char size_buf[SIZE_BUF];
+	char lv_path[PATH_MAX];
+
+	/* does LV exist? */
+	if (!(lvl = find_lv_in_vg(vg, lp->lv_name))) {
+		log_error("Logical volume %s not found in volume group %s",
+			  lp->lv_name, lp->vg_name);
+		return ECMD_FAILED;
+	}
+
+	if (arg_count(cmd, stripes_ARG)) {
+		if (vg->fid->fmt->features & FMT_SEGMENTS)
+			lp->stripes = arg_uint_value(cmd, stripes_ARG, 1);
+		else
+			log_warn("Varied striping not supported. Ignoring.");
+	}
+
+	if (arg_count(cmd, mirrors_ARG)) {
+		if (vg->fid->fmt->features & FMT_SEGMENTS)
+			lp->mirrors = arg_uint_value(cmd, mirrors_ARG, 1) + 1;
+		else
+			log_warn("Mirrors not supported. Ignoring.");
+		if (arg_sign_value(cmd, mirrors_ARG, 0) == SIGN_MINUS) {
+			log_error("Mirrors argument may not be negative");
+			return EINVALID_CMD_LINE;
+		}
+	}
+
+	if (arg_count(cmd, stripesize_ARG)) {
+		if (!validate_stripesize(cmd, vg, lp))
+			return EINVALID_CMD_LINE;
+	}
+
+	lv = lvl->lv;
+
+	if (lv->status & LOCKED) {
+		log_error("Can't resize locked LV %s", lv->name);
+		return ECMD_FAILED;
+	}
+
+	if (lv->status & CONVERTING) {
+		log_error("Can't resize %s while lvconvert in progress", lv->name);
+		return ECMD_FAILED;
+	}
+
+	alloc = arg_uint_value(cmd, alloc_ARG, lv->alloc);
+
+	if (lp->size) {
+		if (lp->size % vg->extent_size) {
+			if (lp->sign == SIGN_MINUS)
+				lp->size -= lp->size % vg->extent_size;
+			else
+				lp->size += vg->extent_size -
+				    (lp->size % vg->extent_size);
+
+			log_print("Rounding up size to full physical extent %s",
+				  display_size(cmd, (uint64_t) lp->size));
+		}
+
+		lp->extents = lp->size / vg->extent_size;
+	}
+
+	if (!(pvh = lp->argc ? create_pv_list(cmd->mem, vg, lp->argc,
+						     lp->argv, 1) : &vg->pvs)) {
+		stack;
+		return ECMD_FAILED;
+	}
+
+	switch(lp->percent) {
+		case PERCENT_VG:
+			lp->extents = lp->extents * vg->extent_count / 100;
+			break;
+		case PERCENT_FREE:
+			lp->extents = lp->extents * vg->free_count / 100;
+			break;
+		case PERCENT_LV:
+			lp->extents = lp->extents * lv->le_count / 100;
+			break;
+		case PERCENT_PVS:
+			pv_extent_count = pv_list_extents_free(pvh);
+			lp->extents = lp->extents * pv_extent_count / 100;
+			break;
+		case PERCENT_NONE:
+			break;
+	}
+
+	if (lp->sign == SIGN_PLUS)
+		lp->extents += lv->le_count;
+
+	if (lp->sign == SIGN_MINUS) {
+		if (lp->extents >= lv->le_count) {
+			log_error("Unable to reduce %s below 1 extent",
+				  lp->lv_name);
+			return EINVALID_CMD_LINE;
+		}
+
+		lp->extents = lv->le_count - lp->extents;
+	}
+
+	if (!lp->extents) {
+		log_error("New size of 0 not permitted");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (lp->extents == lv->le_count) {
+		log_error("New size (%d extents) matches existing size "
+			  "(%d extents)", lp->extents, lv->le_count);
+		return EINVALID_CMD_LINE;
+	}
+
+	seg_size = lp->extents - lv->le_count;
+
+	/* Use segment type of last segment */
+	dm_list_iterate_items(seg, &lv->segments) {
+		lp->segtype = seg->segtype;
+	}
+
+	/* FIXME Support LVs with mixed segment types */
+	if (lp->segtype != arg_ptr_value(cmd, type_ARG, lp->segtype)) {
+		log_error("VolumeType does not match (%s)", lp->segtype->name);
+		return EINVALID_CMD_LINE;
+	}
+
+	/* If extending, find stripes, stripesize & size of last segment */
+	if ((lp->extents > lv->le_count) &&
+	    !(lp->stripes == 1 || (lp->stripes > 1 && lp->stripe_size))) {
+		dm_list_iterate_items(seg, &lv->segments) {
+			if (!seg_is_striped(seg))
+				continue;
+
+			sz = seg->stripe_size;
+			str = seg->area_count;
+
+			if ((seg_stripesize && seg_stripesize != sz
+			     && !lp->stripe_size) ||
+			    (seg_stripes && seg_stripes != str && !lp->stripes)) {
+				log_error("Please specify number of "
+					  "stripes (-i) and stripesize (-I)");
+				return EINVALID_CMD_LINE;
+			}
+
+			seg_stripesize = sz;
+			seg_stripes = str;
+		}
+
+		if (!lp->stripes)
+			lp->stripes = seg_stripes;
+
+		if (!lp->stripe_size && lp->stripes > 1) {
+			if (seg_stripesize) {
+				log_print("Using stripesize of last segment %s",
+					  display_size(cmd, (uint64_t) seg_stripesize));
+				lp->stripe_size = seg_stripesize;
+			} else {
+				lp->stripe_size =
+					find_config_tree_int(cmd,
+							"metadata/stripesize",
+							DEFAULT_STRIPESIZE) * 2;
+				log_print("Using default stripesize %s",
+					  display_size(cmd, (uint64_t) lp->stripe_size));
+			}
+		}
+	}
+
+	/* If extending, find mirrors of last segment */
+	if ((lp->extents > lv->le_count)) {
+		dm_list_iterate_back_items(seg, &lv->segments) {
+			if (seg_is_mirrored(seg))
+				seg_mirrors = lv_mirror_count(seg->lv);
+			else
+				seg_mirrors = 0;
+			break;
+		}
+		if (!arg_count(cmd, mirrors_ARG) && seg_mirrors) {
+			log_print("Extending %" PRIu32 " mirror images.",
+				  seg_mirrors);
+			lp->mirrors = seg_mirrors;
+		}
+		if ((arg_count(cmd, mirrors_ARG) || seg_mirrors) &&
+		    (lp->mirrors != seg_mirrors)) {
+			log_error("Cannot vary number of mirrors in LV yet.");
+			return EINVALID_CMD_LINE;
+		}
+	}
+
+	/* If reducing, find stripes, stripesize & size of last segment */
+	if (lp->extents < lv->le_count) {
+		extents_used = 0;
+
+		if (lp->stripes || lp->stripe_size || lp->mirrors)
+			log_error("Ignoring stripes, stripesize and mirrors "
+				  "arguments when reducing");
+
+		dm_list_iterate_items(seg, &lv->segments) {
+			seg_extents = seg->len;
+
+			if (seg_is_striped(seg)) {
+				seg_stripesize = seg->stripe_size;
+				seg_stripes = seg->area_count;
+			}
+
+			if (seg_is_mirrored(seg))
+				seg_mirrors = lv_mirror_count(seg->lv);
+			else
+				seg_mirrors = 0;
+
+			if (lp->extents <= extents_used + seg_extents)
+				break;
+
+			extents_used += seg_extents;
+		}
+
+		seg_size = lp->extents - extents_used;
+		lp->stripe_size = seg_stripesize;
+		lp->stripes = seg_stripes;
+		lp->mirrors = seg_mirrors;
+	}
+
+	if (lp->stripes > 1 && !lp->stripe_size) {
+		log_error("Stripesize for striped segment should not be 0!");
+		return EINVALID_CMD_LINE;
+	}
+
+	if ((lp->stripes > 1)) {
+		if (!(stripesize_extents = lp->stripe_size / vg->extent_size))
+			stripesize_extents = 1;
+
+		if ((size_rest = seg_size % (lp->stripes * stripesize_extents))) {
+			log_print("Rounding size (%d extents) down to stripe "
+				  "boundary size for segment (%d extents)",
+				  lp->extents, lp->extents - size_rest);
+			lp->extents = lp->extents - size_rest;
+		}
+
+		if (lp->stripe_size < STRIPE_SIZE_MIN) {
+			log_error("Invalid stripe size %s",
+				  display_size(cmd, (uint64_t) lp->stripe_size));
+			return EINVALID_CMD_LINE;
+		}
+	}
+
+	if (lp->extents == lv->le_count) {
+		log_error("New size (%d extents) matches existing size "
+			  "(%d extents)", lp->extents, lv->le_count);
+		return EINVALID_CMD_LINE;
+	}
+
+	if (lp->extents < lv->le_count) {
+		if (lp->resize == LV_EXTEND) {
+			log_error("New size given (%d extents) not larger "
+				  "than existing size (%d extents)",
+				  lp->extents, lv->le_count);
+			return EINVALID_CMD_LINE;
+		} else
+			lp->resize = LV_REDUCE;
+	}
+
+	if (lp->extents > lv->le_count) {
+		if (lp->resize == LV_REDUCE) {
+			log_error("New size given (%d extents) not less than "
+				  "existing size (%d extents)", lp->extents,
+				  lv->le_count);
+			return EINVALID_CMD_LINE;
+		} else
+			lp->resize = LV_EXTEND;
+	}
+
+	if (lp->mirrors && activation() &&
+	    lv_info(cmd, lv, &info, 0, 0) && info.exists) {
+		log_error("Mirrors cannot be resized while active yet.");
+		return ECMD_FAILED;
+	}
+
+	if (lv_is_origin(lv)) {
+		if (lp->resize == LV_REDUCE) {
+			log_error("Snapshot origin volumes cannot be reduced "
+				  "in size yet.");
+			return ECMD_FAILED;
+		}
+
+		memset(&info, 0, sizeof(info));
+
+		if (lv_info(cmd, lv, &info, 0, 0) && info.exists) {
+			log_error("Snapshot origin volumes can be resized "
+				  "only while inactive: try lvchange -an");
+			return ECMD_FAILED;
+		}
+	}
+
+	if (lp->resize == LV_REDUCE) {
+		if (lp->argc)
+			log_warn("Ignoring PVs on command line when reducing");
+	}
+
+	if (lp->resize == LV_REDUCE || lp->resizefs) {
+		if (!confirm_resizefs_reduce(cmd, vg, lv, lp))
+			return ECMD_FAILED;
+	}
+
+	if (lp->resizefs) {
+		if (!do_resizefs_reduce(cmd, vg, lp))
+		    return ECMD_FAILED;
+	}
+
+	if (!archive(vg)) {
+		stack;
+		return ECMD_FAILED;
+	}
+
+	log_print("%sing logical volume %s to %s",
+		  (lp->resize == LV_REDUCE) ? "Reduc" : "Extend",
+		  lp->lv_name,
+		  display_size(cmd, (uint64_t) lp->extents * vg->extent_size));
+
+	if (lp->resize == LV_REDUCE) {
+		if (!lv_reduce(lv, lv->le_count - lp->extents)) {
+			stack;
+			return ECMD_FAILED;
+		}
+	} else if (!lv_extend(lv, lp->segtype, lp->stripes,
+			      lp->stripe_size, lp->mirrors,
+			      lp->extents - lv->le_count,
+			      NULL, 0u, 0u, pvh, alloc)) {
+		stack;
+		return ECMD_FAILED;
+	}
+
+	/* store vg on disk(s) */
+	if (!vg_write(vg)) {
+		stack;
+		return ECMD_FAILED;
+	}
+
+	backup(vg);
+
+	/* If snapshot, must suspend all associated devices */
+	if (lv_is_cow(lv))
+		lock_lv = origin_from_cow(lv);
+	else
+		lock_lv = lv;
+
+	if (!suspend_lv(cmd, lock_lv)) {
+		log_error("Failed to suspend %s", lp->lv_name);
+		vg_revert(vg);
+		return ECMD_FAILED;
+	}
+
+	if (!vg_commit(vg)) {
+		stack;
+		resume_lv(cmd, lock_lv);
+		return ECMD_FAILED;
+	}
+
+	if (!resume_lv(cmd, lock_lv)) {
+		log_error("Problem reactivating %s", lp->lv_name);
+		return ECMD_FAILED;
+	}
+
+	log_print("Logical volume %s successfully resized", lp->lv_name);
+
+	if (lp->resizefs && (lp->resize == LV_EXTEND)) {
+		if (dm_snprintf(lv_path, PATH_MAX, "%s%s/%s", cmd->dev_dir,
+				lp->vg_name, lp->lv_name) < 0) {
+			log_error("Couldn't create LV path for %s",
+				  lp->lv_name);
+			return ECMD_FAILED;
+		}
+		if (dm_snprintf(size_buf, SIZE_BUF, "%" PRIu64,
+				(uint64_t) lp->extents * vg->extent_size / 2) < 0) {
+		    log_error("Couldn't generate new LV size string");
+		    return ECMD_FAILED;
+		}
+		if (!exec_cmd("fsadm", "resize", lv_path, size_buf)) {
+			stack;
+			return ECMD_FAILED;
+		}
+	}
+
+	return ECMD_PROCESSED;
+}
+
+int lvresize(struct cmd_context *cmd, int argc, char **argv)
+{
+	struct lvresize_params lp;
+	struct volume_group *vg;
+	int r;
+
+	memset(&lp, 0, sizeof(lp));
+
+	if (!_lvresize_params(cmd, argc, argv, &lp))
+		return EINVALID_CMD_LINE;
+
+	log_verbose("Finding volume group %s", lp.vg_name);
+	if (!(vg = vg_lock_and_read(cmd, lp.vg_name, NULL, LCK_VG_WRITE,
+				    CLUSTERED | EXPORTED_VG | LVM_WRITE,
+				    CORRECT_INCONSISTENT))) {
+		stack;
+		return ECMD_FAILED;
+	}
+
+	if (!(r = _lvresize(cmd, vg, &lp)))
+		stack;
+
+	unlock_vg(cmd, lp.vg_name);
+
+	return r;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/lvscan.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/lvscan.c
diff -N src/external/gpl2/lvm2tools/dist/tools/lvscan.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/lvscan.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,87 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+static int lvscan_single(struct cmd_context *cmd, struct logical_volume *lv,
+			 void *handle __attribute((unused)))
+{
+	struct lvinfo info;
+	int lv_total = 0;
+	uint64_t lv_capacity_total = 0;
+	int inkernel, snap_active = 1;
+	struct lv_segment *snap_seg = NULL;
+	float snap_percent;     /* fused, fsize; */
+
+	const char *active_str, *snapshot_str;
+
+	if (!arg_count(cmd, all_ARG) && !lv_is_visible(lv))
+		return ECMD_PROCESSED;
+
+	inkernel = lv_info(cmd, lv, &info, 1, 0) && info.exists;
+	if (lv_is_origin(lv)) {
+		dm_list_iterate_items_gen(snap_seg, &lv->snapshot_segs,
+				       origin_list) {
+			if (inkernel &&
+			    (snap_active = lv_snapshot_percent(snap_seg->cow,
+							       &snap_percent)))
+				if (snap_percent < 0 || snap_percent >= 100)
+					snap_active = 0;
+		}
+		snap_seg = NULL;
+	} else if (lv_is_cow(lv)) {
+		if (inkernel &&
+		    (snap_active = lv_snapshot_percent(lv, &snap_percent)))
+			if (snap_percent < 0 || snap_percent >= 100)
+				snap_active = 0;
+	}
+
+/* FIXME Add -D arg to skip this! */
+	if (inkernel && snap_active)
+		active_str = "ACTIVE   ";
+	else
+		active_str = "inactive ";
+
+	if (lv_is_origin(lv))
+		snapshot_str = "Original";
+	else if (lv_is_cow(lv))
+		snapshot_str = "Snapshot";
+	else
+		snapshot_str = "        ";
+
+	log_print("%s%s '%s%s/%s' [%s] %s", active_str, snapshot_str,
+		  cmd->dev_dir, lv->vg->name, lv->name,
+		  display_size(cmd, lv->size),
+		  get_alloc_string(lv->alloc));
+
+	lv_total++;
+
+	lv_capacity_total += lv->size;
+
+	return ECMD_PROCESSED;
+}
+
+int lvscan(struct cmd_context *cmd, int argc, char **argv)
+{
+	if (argc) {
+		log_error("No additional command line arguments allowed");
+		return EINVALID_CMD_LINE;
+	}
+
+	return process_each_lv(cmd, argc, argv, LCK_VG_READ, NULL,
+			       &lvscan_single);
+}
Index: src/external/gpl2/lvm2tools/dist/tools/polldaemon.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/polldaemon.c
diff -N src/external/gpl2/lvm2tools/dist/tools/polldaemon.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/polldaemon.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,271 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+#include "polldaemon.h"
+#include <signal.h>
+#include <sys/wait.h>
+
+static void _sigchld_handler(int sig __attribute((unused)))
+{
+	while (wait4(-1, NULL, WNOHANG | WUNTRACED, NULL) > 0) ;
+}
+
+static int _become_daemon(struct cmd_context *cmd)
+{
+	pid_t pid;
+	struct sigaction act = {
+		{_sigchld_handler},
+		.sa_flags = SA_NOCLDSTOP,
+	};
+
+	log_verbose("Forking background process");
+
+	sigaction(SIGCHLD, &act, NULL);
+
+	if ((pid = fork()) == -1) {
+		log_error("fork failed: %s", strerror(errno));
+		return 1;
+	}
+
+	/* Parent */
+	if (pid > 0)
+		return 0;
+
+	/* Child */
+	if (setsid() == -1)
+		log_error("Background process failed to setsid: %s",
+			  strerror(errno));
+	init_verbose(VERBOSE_BASE_LEVEL);
+
+	close(STDIN_FILENO);
+	close(STDOUT_FILENO);
+	close(STDERR_FILENO);
+
+	strncpy(*cmd->argv, "(lvm2copyd)", strlen(*cmd->argv));
+
+	reset_locking();
+	dev_close_all();
+
+	return 1;
+}
+
+static int _check_mirror_status(struct cmd_context *cmd,
+				struct volume_group *vg,
+				struct logical_volume *lv_mirr,
+				const char *name, struct daemon_parms *parms,
+				int *finished)
+{
+	struct dm_list *lvs_changed;
+	float segment_percent = 0.0, overall_percent = 0.0;
+	uint32_t event_nr = 0;
+
+	/* By default, caller should not retry */
+	*finished = 1;
+
+	if (parms->aborting) {
+		if (!(lvs_changed = lvs_using_lv(cmd, vg, lv_mirr))) {
+			log_error("Failed to generate list of copied LVs: "
+				  "can't abort.");
+			return 0;
+		}
+		parms->poll_fns->finish_copy(cmd, vg, lv_mirr, lvs_changed);
+		return 0;
+	}
+
+	if (!lv_mirror_percent(cmd, lv_mirr, !parms->interval, &segment_percent,
+			       &event_nr)) {
+		log_error("ABORTING: Mirror percentage check failed.");
+		return 0;
+	}
+
+	overall_percent = copy_percent(lv_mirr);
+	if (parms->progress_display)
+		log_print("%s: %s: %.1f%%", name, parms->progress_title,
+			  overall_percent);
+	else
+		log_verbose("%s: %s: %.1f%%", name, parms->progress_title,
+			    overall_percent);
+
+	if (segment_percent < 100.0) {
+		/* The only case the caller *should* try again later */
+		*finished = 0;
+		return 1;
+	}
+
+	if (!(lvs_changed = lvs_using_lv(cmd, vg, lv_mirr))) {
+		log_error("ABORTING: Failed to generate list of copied LVs");
+		return 0;
+	}
+
+	/* Finished? Or progress to next segment? */
+	if (overall_percent >= 100.0) {
+		if (!parms->poll_fns->finish_copy(cmd, vg, lv_mirr,
+						  lvs_changed))
+			return 0;
+	} else {
+		if (!parms->poll_fns->update_metadata(cmd, vg, lv_mirr,
+						      lvs_changed, 0)) {
+			log_error("ABORTING: Segment progression failed.");
+			parms->poll_fns->finish_copy(cmd, vg, lv_mirr,
+						     lvs_changed);
+			return 0;
+		}
+		*finished = 0;	/* Another segment */
+	}
+
+	return 1;
+}
+
+static int _wait_for_single_mirror(struct cmd_context *cmd, const char *name,
+				   struct daemon_parms *parms)
+{
+	struct volume_group *vg;
+	struct logical_volume *lv_mirr;
+	int finished = 0;
+
+	/* Poll for mirror completion */
+	while (!finished) {
+		/* FIXME Also needed in vg/lvchange -ay? */
+		/* FIXME Use alarm for regular intervals instead */
+		if (parms->interval && !parms->aborting) {
+			sleep(parms->interval);
+			/* Devices might have changed while we slept */
+			init_full_scan_done(0);
+		}
+
+		/* Locks the (possibly renamed) VG again */
+		if (!(vg = parms->poll_fns->get_copy_vg(cmd, name))) {
+			log_error("ABORTING: Can't reread VG for %s", name);
+			/* What more could we do here? */
+			return 0;
+		}
+
+		if (!(lv_mirr = parms->poll_fns->get_copy_lv(cmd, vg, name,
+							     parms->lv_type))) {
+			log_error("ABORTING: Can't find mirror LV in %s for %s",
+				  vg->name, name);
+			unlock_vg(cmd, vg->name);
+			return 0;
+		}
+
+		if (!_check_mirror_status(cmd, vg, lv_mirr, name, parms,
+					  &finished)) {
+			unlock_vg(cmd, vg->name);
+			return 0;
+		}
+
+		unlock_vg(cmd, vg->name);
+	}
+
+	return 1;
+}
+
+static int _poll_vg(struct cmd_context *cmd, const char *vgname,
+		    struct volume_group *vg, int consistent, void *handle)
+{
+	struct daemon_parms *parms = (struct daemon_parms *) handle;
+	struct lv_list *lvl;
+	struct logical_volume *lv_mirr;
+	const char *name;
+	int finished;
+
+	if (!vg) {
+		log_error("Couldn't read volume group %s", vgname);
+		return ECMD_FAILED;
+	}
+
+	if (!consistent) {
+		log_error("Volume Group %s inconsistent - skipping", vgname);
+		/* FIXME Should we silently recover it here or not? */
+		return ECMD_FAILED;
+	}
+
+	if (!vg_check_status(vg, EXPORTED_VG))
+		return ECMD_FAILED;
+
+	dm_list_iterate_items(lvl, &vg->lvs) {
+		lv_mirr = lvl->lv;
+		if (!(lv_mirr->status & parms->lv_type))
+			continue;
+		if (!(name = parms->poll_fns->get_copy_name_from_lv(lv_mirr)))
+			continue;
+		/* FIXME Need to do the activation from _set_up_pvmove here
+		 *       if it's not running and we're not aborting */
+		if (_check_mirror_status(cmd, vg, lv_mirr, name,
+					 parms, &finished) && !finished)
+			parms->outstanding_count++;
+	}
+
+	return ECMD_PROCESSED;
+
+}
+
+static void _poll_for_all_vgs(struct cmd_context *cmd,
+			      struct daemon_parms *parms)
+{
+	while (1) {
+		parms->outstanding_count = 0;
+		process_each_vg(cmd, 0, NULL, LCK_VG_WRITE, 1, parms, _poll_vg);
+		if (!parms->outstanding_count)
+			break;
+		sleep(parms->interval);
+	}
+}
+
+int poll_daemon(struct cmd_context *cmd, const char *name, unsigned background,
+		uint32_t lv_type, struct poll_functions *poll_fns,
+		const char *progress_title)
+{
+	struct daemon_parms parms;
+
+	parms.aborting = arg_count(cmd, abort_ARG) ? 1 : 0;
+	parms.background = background;
+	parms.interval = arg_uint_value(cmd, interval_ARG, DEFAULT_INTERVAL);
+	parms.progress_display = 1;
+	parms.progress_title = progress_title;
+	parms.lv_type = lv_type;
+	parms.poll_fns = poll_fns;
+
+	if (parms.interval && !parms.aborting)
+		log_verbose("Checking progress every %u seconds",
+			    parms.interval);
+
+	if (!parms.interval) {
+		parms.progress_display = 0;
+
+		/* FIXME Disabled multiple-copy wait_event */
+		if (!name)
+			parms.interval = DEFAULT_INTERVAL;
+	}
+
+	if (parms.background) {
+		if (!_become_daemon(cmd))
+			return ECMD_PROCESSED;	/* Parent */
+		parms.progress_display = 0;
+		/* FIXME Use wait_event (i.e. interval = 0) and */
+		/*       fork one daemon per copy? */
+	}
+
+	if (name) {
+		if (!_wait_for_single_mirror(cmd, name, &parms))
+			return ECMD_FAILED;
+	} else
+		_poll_for_all_vgs(cmd, &parms);
+
+	return ECMD_PROCESSED;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/polldaemon.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/polldaemon.h
diff -N src/external/gpl2/lvm2tools/dist/tools/polldaemon.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/polldaemon.h	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,56 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_TOOL_POLLDAEMON_H
+#define _LVM_TOOL_POLLDAEMON_H
+
+#include "metadata-exported.h"
+
+struct poll_functions {
+	const char *(*get_copy_name_from_lv) (struct logical_volume *lv_mirr);
+	struct volume_group *(*get_copy_vg) (struct cmd_context *cmd,
+					     const char *name);
+	struct logical_volume *(*get_copy_lv) (struct cmd_context *cmd,
+					       struct volume_group *vg,
+					       const char *name,
+					       uint32_t lv_type);
+	int (*update_metadata) (struct cmd_context *cmd,
+				struct volume_group *vg,
+				struct logical_volume *lv_mirr,
+				struct dm_list *lvs_changed, unsigned flags);
+	int (*finish_copy) (struct cmd_context *cmd,
+			    struct volume_group *vg,
+			    struct logical_volume *lv_mirr,
+			    struct dm_list *lvs_changed);
+};
+
+struct daemon_parms {
+	unsigned interval;
+	unsigned aborting;
+	unsigned background;
+	unsigned outstanding_count;
+	unsigned progress_display;
+	const char *progress_title;
+	uint32_t lv_type;
+	struct poll_functions *poll_fns;
+};
+
+int poll_daemon(struct cmd_context *cmd, const char *name, unsigned background,
+		uint32_t lv_type, struct poll_functions *poll_fns,
+		const char *progress_title);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/tools/pvchange.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/pvchange.c
diff -N src/external/gpl2/lvm2tools/dist/tools/pvchange.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/pvchange.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,304 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+/* FIXME Locking.  PVs in VG. */
+
+static int _pvchange_single(struct cmd_context *cmd, struct physical_volume *pv,
+			    void *handle __attribute((unused)))
+{
+	struct volume_group *vg = NULL;
+	const char *vg_name = NULL;
+	struct pv_list *pvl;
+	uint64_t sector;
+	uint32_t orig_pe_alloc_count;
+	/* FIXME Next three only required for format1. */
+	uint32_t orig_pe_count, orig_pe_size;
+	uint64_t orig_pe_start;
+
+	const char *pv_name = pv_dev_name(pv);
+	const char *tag = NULL;
+	const char *orig_vg_name;
+	char uuid[64] __attribute((aligned(8)));
+
+	int allocatable = 0;
+	int tagarg = 0;
+
+	if (arg_count(cmd, addtag_ARG))
+		tagarg = addtag_ARG;
+	else if (arg_count(cmd, deltag_ARG))
+		tagarg = deltag_ARG;
+
+	if (arg_count(cmd, allocatable_ARG))
+		allocatable = !strcmp(arg_str_value(cmd, allocatable_ARG, "n"),
+				      "y");
+	else if (tagarg && !(tag = arg_str_value(cmd, tagarg, NULL))) {
+		log_error("Failed to get tag");
+		return 0;
+	}
+
+	/* If in a VG, must change using volume group. */
+	if (!is_orphan(pv)) {
+		vg_name = pv_vg_name(pv);
+
+		log_verbose("Finding volume group %s of physical volume %s",
+			    vg_name, pv_name);
+		if (!(vg = vg_lock_and_read(cmd, vg_name, NULL, LCK_VG_WRITE,
+					    CLUSTERED | EXPORTED_VG | LVM_WRITE,
+					    CORRECT_INCONSISTENT)))
+			return_0;
+
+		if (!(pvl = find_pv_in_vg(vg, pv_name))) {
+			unlock_vg(cmd, vg_name);
+			log_error
+			    ("Unable to find \"%s\" in volume group \"%s\"",
+			     pv_name, vg->name);
+			return 0;
+		}
+		if (tagarg && !(vg->fid->fmt->features & FMT_TAGS)) {
+			unlock_vg(cmd, vg_name);
+			log_error("Volume group containing %s does not "
+				  "support tags", pv_name);
+			return 0;
+		}
+		if (arg_count(cmd, uuid_ARG) && lvs_in_vg_activated(vg)) {
+			unlock_vg(cmd, vg_name);
+			log_error("Volume group containing %s has active "
+				  "logical volumes", pv_name);
+			return 0;
+		}
+		pv = pvl->pv;
+		if (!archive(vg))
+			return 0;
+	} else {
+		if (tagarg) {
+			log_error("Can't change tag on Physical Volume %s not "
+				  "in volume group", pv_name);
+			return 0;
+		}
+
+		vg_name = VG_ORPHANS;
+
+		if (!lock_vol(cmd, vg_name, LCK_VG_WRITE)) {
+			log_error("Can't get lock for orphans");
+			return 0;
+		}
+
+		if (!(pv = pv_read(cmd, pv_name, NULL, &sector, 1))) {
+			unlock_vg(cmd, vg_name);
+			log_error("Unable to read PV \"%s\"", pv_name);
+			return 0;
+		}
+	}
+
+	if (arg_count(cmd, allocatable_ARG)) {
+		if (is_orphan(pv) &&
+		    !(pv->fmt->features & FMT_ORPHAN_ALLOCATABLE)) {
+			log_error("Allocatability not supported by orphan "
+				  "%s format PV %s", pv->fmt->name, pv_name);
+			unlock_vg(cmd, vg_name);
+			return 0;
+		}
+
+		/* change allocatability for a PV */
+		if (allocatable && (pv_status(pv) & ALLOCATABLE_PV)) {
+			log_error("Physical volume \"%s\" is already "
+				  "allocatable", pv_name);
+			unlock_vg(cmd, vg_name);
+			return 1;
+		}
+
+		if (!allocatable && !(pv_status(pv) & ALLOCATABLE_PV)) {
+			log_error("Physical volume \"%s\" is already "
+				  "unallocatable", pv_name);
+			unlock_vg(cmd, vg_name);
+			return 1;
+		}
+
+		if (allocatable) {
+			log_verbose("Setting physical volume \"%s\" "
+				    "allocatable", pv_name);
+			pv->status |= ALLOCATABLE_PV;
+		} else {
+			log_verbose("Setting physical volume \"%s\" NOT "
+				    "allocatable", pv_name);
+			pv->status &= ~ALLOCATABLE_PV;
+		}
+	} else if (tagarg) {
+		/* tag or deltag */
+		if ((tagarg == addtag_ARG)) {
+			if (!str_list_add(cmd->mem, &pv->tags, tag)) {
+				log_error("Failed to add tag %s to physical "
+					  "volume %s", tag, pv_name);
+				unlock_vg(cmd, vg_name);
+				return 0;
+			}
+		} else {
+			if (!str_list_del(&pv->tags, tag)) {
+				log_error("Failed to remove tag %s from "
+					  "physical volume" "%s", tag, pv_name);
+				unlock_vg(cmd, vg_name);
+				return 0;
+			}
+		}
+	} else {
+		/* --uuid: Change PV ID randomly */
+		if (!id_create(&pv->id)) {
+			log_error("Failed to generate new random UUID for %s.",
+				  pv_name);
+			unlock_vg(cmd, vg_name);
+			return 0;
+		}
+		if (!id_write_format(&pv->id, uuid, sizeof(uuid))) {
+			unlock_vg(cmd, vg_name);
+			return_0;
+		}
+		log_verbose("Changing uuid of %s to %s.", pv_name, uuid);
+		if (!is_orphan(pv)) {
+			orig_vg_name = pv_vg_name(pv);
+			orig_pe_alloc_count = pv_pe_alloc_count(pv);
+
+			/* FIXME format1 pv_write doesn't preserve these. */
+			orig_pe_size = pv_pe_size(pv);
+			orig_pe_start = pv_pe_start(pv);
+			orig_pe_count = pv_pe_count(pv);
+
+			pv->vg_name = pv->fmt->orphan_vg_name;
+			pv->pe_alloc_count = 0;
+			if (!(pv_write(cmd, pv, NULL, INT64_C(-1)))) {
+				log_error("pv_write with new uuid failed "
+					  "for %s.", pv_name);
+				unlock_vg(cmd, vg_name);
+				return 0;
+			}
+			pv->vg_name = orig_vg_name;
+			pv->pe_alloc_count = orig_pe_alloc_count;
+
+			pv->pe_size = orig_pe_size;
+			pv->pe_start = orig_pe_start;
+			pv->pe_count = orig_pe_count;
+		}
+	}
+
+	log_verbose("Updating physical volume \"%s\"", pv_name);
+	if (!is_orphan(pv)) {
+		if (!vg_write(vg) || !vg_commit(vg)) {
+			unlock_vg(cmd, vg_name);
+			log_error("Failed to store physical volume \"%s\" in "
+				  "volume group \"%s\"", pv_name, vg->name);
+			return 0;
+		}
+		backup(vg);
+	} else if (!(pv_write(cmd, pv, NULL, INT64_C(-1)))) {
+		unlock_vg(cmd, vg_name);
+		log_error("Failed to store physical volume \"%s\"",
+			  pv_name);
+		return 0;
+	}
+
+	unlock_vg(cmd, vg_name);
+
+	log_print("Physical volume \"%s\" changed", pv_name);
+
+	return 1;
+}
+
+int pvchange(struct cmd_context *cmd, int argc, char **argv)
+{
+	int opt = 0;
+	int done = 0;
+	int total = 0;
+
+	struct physical_volume *pv;
+	char *pv_name;
+
+	struct pv_list *pvl;
+	struct dm_list *pvslist;
+	struct dm_list mdas;
+
+	if (arg_count(cmd, allocatable_ARG) + arg_count(cmd, addtag_ARG) +
+	    arg_count(cmd, deltag_ARG) + arg_count(cmd, uuid_ARG) != 1) {
+		log_error("Please give exactly one option of -x, -uuid, "
+			  "--addtag or --deltag");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (!(arg_count(cmd, all_ARG)) && !argc) {
+		log_error("Please give a physical volume path");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (arg_count(cmd, all_ARG) && argc) {
+		log_error("Option a and PhysicalVolumePath are exclusive");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (argc) {
+		log_verbose("Using physical volume(s) on command line");
+		for (; opt < argc; opt++) {
+			pv_name = argv[opt];
+			dm_list_init(&mdas);
+			if (!(pv = pv_read(cmd, pv_name, &mdas, NULL, 1))) {
+				log_error("Failed to read physical volume %s",
+					  pv_name);
+				continue;
+			}
+			/*
+			 * If a PV has no MDAs it may appear to be an
+			 * orphan until the metadata is read off
+			 * another PV in the same VG.  Detecting this
+			 * means checking every VG by scanning every
+			 * PV on the system.
+			 */
+			if (is_orphan(pv) && !dm_list_size(&mdas)) {
+				if (!scan_vgs_for_pvs(cmd)) {
+					log_error("Rescan for PVs without "
+						  "metadata areas failed.");
+					continue;
+				}
+				if (!(pv = pv_read(cmd, pv_name,
+						   NULL, NULL, 1))) {
+					log_error("Failed to read "
+						  "physical volume %s",
+						  pv_name);
+					continue;
+				}
+			}
+
+			total++;
+			done += _pvchange_single(cmd, pv, NULL);
+		}
+	} else {
+		log_verbose("Scanning for physical volume names");
+		if (!(pvslist = get_pvs(cmd))) {
+			return ECMD_FAILED;
+		}
+
+		dm_list_iterate_items(pvl, pvslist) {
+			total++;
+			done += _pvchange_single(cmd, pvl->pv, NULL);
+		}
+	}
+
+	log_print("%d physical volume%s changed / %d physical volume%s "
+		  "not changed",
+		  done, done == 1 ? "" : "s",
+		  total - done, (total - done) == 1 ? "" : "s");
+
+	return (total == done) ? ECMD_PROCESSED : ECMD_FAILED;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/pvck.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/pvck.c
diff -N src/external/gpl2/lvm2tools/dist/tools/pvck.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/pvck.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,42 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+int pvck(struct cmd_context *cmd, int argc, char **argv)
+{
+	int i;
+
+	/* FIXME: validate cmdline options */
+	/* FIXME: what does the cmdline look like? */
+	/*
+	 * Use what's on the cmdline directly, and avoid calling into
+	 * some of the other infrastructure functions, so as to avoid
+	 * hitting some of the lvmcache behavior, scanning other devices,
+	 * etc.
+	 */
+	for (i = 0; i < argc; i++) {
+		/* FIXME: warning and/or check if in use? */
+		log_verbose("Scanning %s", argv[i]);
+
+		pv_analyze(cmd, argv[i],
+			   arg_uint64_value(cmd, labelsector_ARG,
+					   UINT64_C(0)));
+	}
+
+	return ECMD_PROCESSED;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/pvcreate.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/pvcreate.c
diff -N src/external/gpl2/lvm2tools/dist/tools/pvcreate.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/pvcreate.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,374 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+#include "metadata.h"
+
+struct pvcreate_params {
+	int zero;
+	uint64_t size;
+	int pvmetadatacopies;
+	uint64_t pvmetadatasize;
+	int64_t labelsector;
+	struct id id; /* FIXME: redundant */
+	struct id *idp; /* 0 if no --uuid option */
+	uint64_t pe_start;
+	uint32_t extent_count;
+	uint32_t extent_size;
+	const char *restorefile; /* 0 if no --restorefile option */
+	force_t force;
+	unsigned yes;
+};
+
+const char _really_init[] =
+    "Really INITIALIZE physical volume \"%s\" of volume group \"%s\" [y/n]? ";
+
+/*
+ * See if we may pvcreate on this device.
+ * 0 indicates we may not.
+ */
+static int pvcreate_check(struct cmd_context *cmd, const char *name,
+			  struct pvcreate_params *pp)
+{
+	struct physical_volume *pv;
+	struct device *dev;
+	uint64_t md_superblock;
+
+	/* FIXME Check partition type is LVM unless --force is given */
+
+	/* Is there a pv here already? */
+	pv = pv_read(cmd, name, NULL, NULL, 0);
+
+	/*
+	 * If a PV has no MDAs it may appear to be an orphan until the
+	 * metadata is read off another PV in the same VG.  Detecting
+	 * this means checking every VG by scanning every PV on the
+	 * system.
+	 */
+	if (pv && is_orphan(pv)) {
+		if (!scan_vgs_for_pvs(cmd))
+			return_0;
+		pv = pv_read(cmd, name, NULL, NULL, 0);
+	}
+
+	/* Allow partial & exported VGs to be destroyed. */
+	/* We must have -ff to overwrite a non orphan */
+	if (pv && !is_orphan(pv) && pp->force != DONT_PROMPT_OVERRIDE) {
+		log_error("Can't initialize physical volume \"%s\" of "
+			  "volume group \"%s\" without -ff", name, pv_vg_name(pv));
+		return 0;
+	}
+
+	/* prompt */
+	if (pv && !is_orphan(pv) && !pp->yes &&
+	    yes_no_prompt(_really_init, name, pv_vg_name(pv)) == 'n') {
+		log_print("%s: physical volume not initialized", name);
+		return 0;
+	}
+
+	if (sigint_caught())
+		return 0;
+
+	dev = dev_cache_get(name, cmd->filter);
+
+	/* Is there an md superblock here? */
+	if (!dev && md_filtering()) {
+		unlock_vg(cmd, VG_ORPHANS);
+
+		persistent_filter_wipe(cmd->filter);
+		lvmcache_destroy(cmd, 1);
+
+		init_md_filtering(0);
+		if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE)) {
+			log_error("Can't get lock for orphan PVs");
+			init_md_filtering(1);
+			return 0;
+		}
+		dev = dev_cache_get(name, cmd->filter);
+		init_md_filtering(1);
+	}
+
+	if (!dev) {
+		log_error("Device %s not found (or ignored by filtering).", name);
+		return 0;
+	}
+
+	/*
+ 	 * This test will fail if the device belongs to an MD array.
+	 */
+	if (!dev_test_excl(dev)) {
+		/* FIXME Detect whether device-mapper itself is still using it */
+		log_error("Can't open %s exclusively.  Mounted filesystem?",
+			  name);
+		return 0;
+	}
+
+	/* Wipe superblock? */
+	if (dev_is_md(dev, &md_superblock) &&
+	    ((!pp->idp && !pp->restorefile) || pp->yes ||
+	     (yes_no_prompt("Software RAID md superblock "
+			    "detected on %s. Wipe it? [y/n] ", name) == 'y'))) {
+		log_print("Wiping software RAID md superblock on %s", name);
+		if (!dev_set(dev, md_superblock, 4, 0)) {
+			log_error("Failed to wipe RAID md superblock on %s",
+				  name);
+			return 0;
+		}
+	}
+
+	if (sigint_caught())
+		return 0;
+
+	if (pv && !is_orphan(pv) && pp->force) {
+		log_warn("WARNING: Forcing physical volume creation on "
+			  "%s%s%s%s", name,
+			  !is_orphan(pv) ? " of volume group \"" : "",
+			  !is_orphan(pv) ? pv_vg_name(pv) : "",
+			  !is_orphan(pv) ? "\"" : "");
+	}
+
+	return 1;
+}
+
+static int pvcreate_single(struct cmd_context *cmd, const char *pv_name,
+			   void *handle)
+{
+	struct pvcreate_params *pp = (struct pvcreate_params *) handle;
+	void *pv;
+	struct device *dev;
+	struct dm_list mdas;
+
+	if (pp->idp) {
+		if ((dev = device_from_pvid(cmd, pp->idp)) &&
+		    (dev != dev_cache_get(pv_name, cmd->filter))) {
+			log_error("uuid %s already in use on \"%s\"",
+				  pp->idp->uuid, dev_name(dev));
+			return 0;
+		}
+	}
+
+	if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE)) {
+		log_error("Can't get lock for orphan PVs");
+		return 0;
+	}
+
+	if (!pvcreate_check(cmd, pv_name, pp))
+		goto error;
+
+	if (sigint_caught())
+		goto error;
+
+	if (!(dev = dev_cache_get(pv_name, cmd->filter))) {
+		log_error("%s: Couldn't find device.  Check your filters?",
+			  pv_name);
+		goto error;
+	}
+
+	dm_list_init(&mdas);
+	if (!(pv = pv_create(cmd, dev, pp->idp, pp->size, pp->pe_start,
+			     pp->extent_count, pp->extent_size,
+			     pp->pvmetadatacopies,
+			     pp->pvmetadatasize,&mdas))) {
+		log_error("Failed to setup physical volume \"%s\"", pv_name);
+		goto error;
+	}
+
+	log_verbose("Set up physical volume for \"%s\" with %" PRIu64
+		    " available sectors", pv_name, pv_size(pv));
+
+	/* Wipe existing label first */
+	if (!label_remove(pv_dev(pv))) {
+		log_error("Failed to wipe existing label on %s", pv_name);
+		goto error;
+	}
+
+	if (pp->zero) {
+		log_verbose("Zeroing start of device %s", pv_name);
+		if (!dev_open_quiet(dev)) {
+			log_error("%s not opened: device not zeroed", pv_name);
+			goto error;
+		}
+
+		if (!dev_set(dev, UINT64_C(0), (size_t) 2048, 0)) {
+			log_error("%s not wiped: aborting", pv_name);
+			dev_close(dev);
+			goto error;
+		}
+		dev_close(dev);
+	}
+
+	log_very_verbose("Writing physical volume data to disk \"%s\"",
+			 pv_name);
+	if (!(pv_write(cmd, (struct physical_volume *)pv, &mdas,
+		       pp->labelsector))) {
+		log_error("Failed to write physical volume \"%s\"", pv_name);
+		goto error;
+	}
+
+	log_print("Physical volume \"%s\" successfully created", pv_name);
+
+	unlock_vg(cmd, VG_ORPHANS);
+	return 1;
+
+      error:
+	unlock_vg(cmd, VG_ORPHANS);
+	return 0;
+}
+
+/*
+ * Intial sanity checking of command-line arguments and fill in 'pp' fields.
+ *
+ * Input arguments:
+ * cmd, argc, argv
+ *
+ * Output arguments:
+ * pp: structure allocated by caller, fields written / validated here
+ */
+static int pvcreate_validate_params(struct cmd_context *cmd,
+				    int argc, char **argv,
+				    struct pvcreate_params *pp)
+{
+	const char *uuid = NULL;
+	void *existing_pv;
+	struct volume_group *vg;
+
+	memset(pp, 0, sizeof(*pp));
+
+	if (!argc) {
+		log_error("Please enter a physical volume path");
+		return 0;
+	}
+
+	if (arg_count(cmd, restorefile_ARG) && !arg_count(cmd, uuidstr_ARG)) {
+		log_error("--uuid is required with --restorefile");
+		return 0;
+	}
+
+	if (arg_count(cmd, uuidstr_ARG) && argc != 1) {
+		log_error("Can only set uuid on one volume at once");
+		return 0;
+	}
+
+ 	if (arg_count(cmd, uuidstr_ARG)) {
+		uuid = arg_str_value(cmd, uuidstr_ARG, "");
+		if (!id_read_format(&pp->id, uuid))
+			return 0;
+		pp->idp = &pp->id;
+	}
+
+	if (arg_count(cmd, restorefile_ARG)) {
+		pp->restorefile = arg_str_value(cmd, restorefile_ARG, "");
+		/* The uuid won't already exist */
+		if (!(vg = backup_read_vg(cmd, NULL, pp->restorefile))) {
+			log_error("Unable to read volume group from %s",
+				  pp->restorefile);
+			return 0;
+		}
+		if (!(existing_pv = find_pv_in_vg_by_uuid(vg, pp->idp))) {
+			log_error("Can't find uuid %s in backup file %s",
+				  uuid, pp->restorefile);
+			return 0;
+		}
+		pp->pe_start = pv_pe_start(existing_pv);
+		pp->extent_size = pv_pe_size(existing_pv);
+		pp->extent_count = pv_pe_count(existing_pv);
+	}
+
+	if (arg_count(cmd, yes_ARG) && !arg_count(cmd, force_ARG)) {
+		log_error("Option y can only be given with option f");
+		return 0;
+	}
+
+	pp->yes = arg_count(cmd, yes_ARG);
+	pp->force = arg_count(cmd, force_ARG);
+
+	if (arg_int_value(cmd, labelsector_ARG, 0) >= LABEL_SCAN_SECTORS) {
+		log_error("labelsector must be less than %lu",
+			  LABEL_SCAN_SECTORS);
+		return 0;
+	} else {
+		pp->labelsector = arg_int64_value(cmd, labelsector_ARG,
+						  DEFAULT_LABELSECTOR);
+	}
+
+	if (!(cmd->fmt->features & FMT_MDAS) &&
+	    (arg_count(cmd, metadatacopies_ARG) ||
+	     arg_count(cmd, metadatasize_ARG))) {
+		log_error("Metadata parameters only apply to text format");
+		return 0;
+	}
+
+	if (arg_count(cmd, metadatacopies_ARG) &&
+	    arg_int_value(cmd, metadatacopies_ARG, -1) > 2) {
+		log_error("Metadatacopies may only be 0, 1 or 2");
+		return 0;
+	}
+
+	if (arg_count(cmd, zero_ARG))
+		pp->zero = strcmp(arg_str_value(cmd, zero_ARG, "y"), "n");
+	else if (arg_count(cmd, restorefile_ARG) || arg_count(cmd, uuidstr_ARG))
+		pp->zero = 0;
+	else
+		pp->zero = 1;
+
+	if (arg_sign_value(cmd, physicalvolumesize_ARG, 0) == SIGN_MINUS) {
+		log_error("Physical volume size may not be negative");
+		return 0;
+	}
+	pp->size = arg_uint64_value(cmd, physicalvolumesize_ARG, UINT64_C(0));
+
+	if (arg_sign_value(cmd, metadatasize_ARG, 0) == SIGN_MINUS) {
+		log_error("Metadata size may not be negative");
+		return 0;
+	}
+
+	pp->pvmetadatasize = arg_uint64_value(cmd, metadatasize_ARG, UINT64_C(0));
+	if (!pp->pvmetadatasize)
+		pp->pvmetadatasize = find_config_tree_int(cmd,
+						 "metadata/pvmetadatasize",
+						 DEFAULT_PVMETADATASIZE);
+
+	pp->pvmetadatacopies = arg_int_value(cmd, metadatacopies_ARG, -1);
+	if (pp->pvmetadatacopies < 0)
+		pp->pvmetadatacopies = find_config_tree_int(cmd,
+						   "metadata/pvmetadatacopies",
+						   DEFAULT_PVMETADATACOPIES);
+
+	return 1;
+}
+
+
+int pvcreate(struct cmd_context *cmd, int argc, char **argv)
+{
+	int i;
+	int ret = ECMD_PROCESSED;
+	struct pvcreate_params pp;
+
+	if (!pvcreate_validate_params(cmd, argc, argv, &pp)) {
+		return EINVALID_CMD_LINE;
+	}
+
+	for (i = 0; i < argc; i++) {
+		if (!pvcreate_single(cmd, argv[i], &pp))
+			ret = ECMD_FAILED;
+
+		if (sigint_caught())
+			return ret;
+	}
+
+	return ret;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/pvdisplay.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/pvdisplay.c
diff -N src/external/gpl2/lvm2tools/dist/tools/pvdisplay.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/pvdisplay.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,117 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+static int _pvdisplay_single(struct cmd_context *cmd,
+			     struct volume_group *vg,
+			     struct physical_volume *pv, void *handle)
+{
+	struct pv_list *pvl;
+	int ret = ECMD_PROCESSED;
+	uint64_t size;
+
+	const char *pv_name = pv_dev_name(pv);
+	const char *vg_name = NULL;
+
+	if (!is_orphan(pv) && !vg) {
+		vg_name = pv_vg_name(pv);
+		if (!(vg = vg_lock_and_read(cmd, vg_name, (char *)&pv->vgid,
+					    LCK_VG_READ, CLUSTERED, 0))) {
+		 	log_error("Skipping volume group %s", vg_name);
+			/* FIXME If CLUSTERED should return ECMD_PROCESSED here */
+		 	return ECMD_FAILED;
+	 	}
+
+	 	/*
+		 * Replace possibly incomplete PV structure with new one
+		 * allocated in vg_read() path.
+		 */
+		 if (!(pvl = find_pv_in_vg(vg, pv_name))) {
+			 log_error("Unable to find \"%s\" in volume group \"%s\"",
+				   pv_name, vg->name);
+			 ret = ECMD_FAILED;
+			 goto out;
+		 }
+
+		 pv = pvl->pv;
+	}
+
+	if (is_orphan(pv))
+		size = pv_size(pv);
+	else
+		size = (pv_pe_count(pv) - pv_pe_alloc_count(pv)) *
+			pv_pe_size(pv);
+
+	if (arg_count(cmd, short_ARG)) {
+		log_print("Device \"%s\" has a capacity of %s", pv_name,
+			  display_size(cmd, size));
+		goto out;
+	}
+
+	if (pv_status(pv) & EXPORTED_VG)
+		log_print("Physical volume \"%s\" of volume group \"%s\" "
+			  "is exported", pv_name, pv_vg_name(pv));
+
+	if (is_orphan(pv))
+		log_print("\"%s\" is a new physical volume of \"%s\"",
+			  pv_name, display_size(cmd, size));
+
+	if (arg_count(cmd, colon_ARG)) {
+		pvdisplay_colons(pv);
+		goto out;
+	}
+
+	pvdisplay_full(cmd, pv, handle);
+
+	if (arg_count(cmd, maps_ARG))
+		pvdisplay_segments(pv);
+
+out:
+	if (vg_name)
+		unlock_vg(cmd, vg_name);
+
+	return ret;
+}
+
+int pvdisplay(struct cmd_context *cmd, int argc, char **argv)
+{
+	if (arg_count(cmd, columns_ARG)) {
+		if (arg_count(cmd, colon_ARG) || arg_count(cmd, maps_ARG) ||
+		    arg_count(cmd, short_ARG)) {
+			log_error("Incompatible options selected");
+			return EINVALID_CMD_LINE;
+		}
+		return pvs(cmd, argc, argv);
+	} else if (arg_count(cmd, aligned_ARG) ||
+		   arg_count(cmd, all_ARG) ||
+		   arg_count(cmd, noheadings_ARG) ||
+		   arg_count(cmd, options_ARG) ||
+		   arg_count(cmd, separator_ARG) ||
+		   arg_count(cmd, sort_ARG) || arg_count(cmd, unbuffered_ARG)) {
+		log_error("Incompatible options selected");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (arg_count(cmd, colon_ARG) && arg_count(cmd, maps_ARG)) {
+		log_error("Option -v not allowed with option -c");
+		return EINVALID_CMD_LINE;
+	}
+
+	return process_each_pv(cmd, argc, argv, NULL, LCK_VG_READ, NULL,
+			       _pvdisplay_single);
+}
Index: src/external/gpl2/lvm2tools/dist/tools/pvmove.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/pvmove.c
diff -N src/external/gpl2/lvm2tools/dist/tools/pvmove.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/pvmove.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,630 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+#include "polldaemon.h"
+#include "display.h"
+
+#define PVMOVE_FIRST_TIME   0x00000001      /* Called for first time */
+
+static int _pvmove_target_present(struct cmd_context *cmd, int clustered)
+{
+	const struct segment_type *segtype;
+	unsigned attr = 0;
+	int found = 1;
+	static int _clustered_found = -1;
+
+	if (clustered && _clustered_found >= 0)
+		return _clustered_found;
+
+	if (!(segtype = get_segtype_from_string(cmd, "mirror")))
+		return_0;
+
+	if (activation() && segtype->ops->target_present &&
+	    !segtype->ops->target_present(NULL, clustered ? &attr : NULL))
+		found = 0;
+
+	if (activation() && clustered) {
+		if (found && (attr & MIRROR_LOG_CLUSTERED))
+			_clustered_found = found = 1;
+		else
+			_clustered_found = found = 0;
+	}
+
+	return found;
+}
+
+static unsigned _pvmove_is_exclusive(struct cmd_context *cmd,
+				     struct volume_group *vg)
+{
+	if (vg_is_clustered(vg))
+		if (!_pvmove_target_present(cmd, 1))
+			return 1;
+
+	return 0;
+}
+
+/* Allow /dev/vgname/lvname, vgname/lvname or lvname */
+static const char *_extract_lvname(struct cmd_context *cmd, const char *vgname,
+				   const char *arg)
+{
+	const char *lvname;
+
+	/* Is an lvname supplied directly? */
+	if (!strchr(arg, '/'))
+		return arg;
+
+	lvname = skip_dev_dir(cmd, arg, NULL);
+	while (*lvname == '/')
+		lvname++;
+	if (!strchr(lvname, '/')) {
+		log_error("--name takes a logical volume name");
+		return NULL;
+	}
+	if (strncmp(vgname, lvname, strlen(vgname)) ||
+	    (lvname += strlen(vgname), *lvname != '/')) {
+		log_error("Named LV and old PV must be in the same VG");
+		return NULL;
+	}
+	while (*lvname == '/')
+		lvname++;
+	if (!*lvname) {
+		log_error("Incomplete LV name supplied with --name");
+		return NULL;
+	}
+	return lvname;
+}
+
+static struct volume_group *_get_vg(struct cmd_context *cmd, const char *vgname)
+{
+	struct volume_group *vg;
+
+	dev_close_all();
+
+	if (!(vg = vg_lock_and_read(cmd, vgname, NULL, LCK_VG_WRITE,
+				    CLUSTERED | EXPORTED_VG | LVM_WRITE,
+				    CORRECT_INCONSISTENT | FAIL_INCONSISTENT)))
+		 return NULL;
+
+	return vg;
+}
+
+/* Create list of PVs for allocation of replacement extents */
+static struct dm_list *_get_allocatable_pvs(struct cmd_context *cmd, int argc,
+					 char **argv, struct volume_group *vg,
+					 struct physical_volume *pv,
+					 alloc_policy_t alloc)
+{
+	struct dm_list *allocatable_pvs, *pvht, *pvh;
+	struct pv_list *pvl;
+
+	if (argc)
+		allocatable_pvs = create_pv_list(cmd->mem, vg, argc, argv, 1);
+	else
+		allocatable_pvs = clone_pv_list(cmd->mem, &vg->pvs);
+
+	if (!allocatable_pvs)
+		return_NULL;
+
+	dm_list_iterate_safe(pvh, pvht, allocatable_pvs) {
+		pvl = dm_list_item(pvh, struct pv_list);
+
+		/* Don't allocate onto the PV we're clearing! */
+		if ((alloc != ALLOC_ANYWHERE) && (pvl->pv->dev == pv_dev(pv))) {
+			dm_list_del(&pvl->list);
+			continue;
+		}
+
+		/* Remove PV if full */
+		if ((pvl->pv->pe_count == pvl->pv->pe_alloc_count))
+			dm_list_del(&pvl->list);
+	}
+
+	if (dm_list_empty(allocatable_pvs)) {
+		log_error("No extents available for allocation");
+		return NULL;
+	}
+
+	return allocatable_pvs;
+}
+
+/*
+ * Replace any LV segments on given PV with temporary mirror.
+ * Returns list of LVs changed.
+ */
+static int _insert_pvmove_mirrors(struct cmd_context *cmd,
+				  struct logical_volume *lv_mirr,
+				  struct dm_list *source_pvl,
+				  struct logical_volume *lv,
+				  struct dm_list *lvs_changed)
+
+{
+	struct pv_list *pvl;
+	uint32_t prev_le_count;
+
+	/* Only 1 PV may feature in source_pvl */
+	pvl = dm_list_item(source_pvl->n, struct pv_list);
+
+	prev_le_count = lv_mirr->le_count;
+	if (!insert_layer_for_segments_on_pv(cmd, lv, lv_mirr, PVMOVE,
+					     pvl, lvs_changed))
+		return_0;
+
+	/* check if layer was inserted */
+	if (lv_mirr->le_count - prev_le_count) {
+		lv->status |= LOCKED;
+
+		log_verbose("Moving %u extents of logical volume %s/%s",
+			    lv_mirr->le_count - prev_le_count,
+			    lv->vg->name, lv->name);
+	}
+
+	return 1;
+}
+
+/* Create new LV with mirror segments for the required copies */
+static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
+						struct volume_group *vg,
+						struct dm_list *source_pvl,
+						const char *lv_name,
+						struct dm_list *allocatable_pvs,
+						alloc_policy_t alloc,
+						struct dm_list **lvs_changed)
+{
+	struct logical_volume *lv_mirr, *lv;
+	struct lv_list *lvl;
+	uint32_t log_count = 0;
+	int lv_found = 0;
+
+	/* FIXME Cope with non-contiguous => splitting existing segments */
+	if (!(lv_mirr = lv_create_empty("pvmove%d", NULL,
+					LVM_READ | LVM_WRITE,
+					ALLOC_CONTIGUOUS, 0, vg))) {
+		log_error("Creation of temporary pvmove LV failed");
+		return NULL;
+	}
+
+	lv_mirr->status |= (PVMOVE | LOCKED);
+
+	if (!(*lvs_changed = dm_pool_alloc(cmd->mem, sizeof(**lvs_changed)))) {
+		log_error("lvs_changed list struct allocation failed");
+		return NULL;
+	}
+
+	dm_list_init(*lvs_changed);
+
+	/* Find segments to be moved and set up mirrors */
+	dm_list_iterate_items(lvl, &vg->lvs) {
+		lv = lvl->lv;
+		if ((lv == lv_mirr))
+			continue;
+		if (lv_name) {
+			if (strcmp(lv->name, lv_name))
+				continue;
+			lv_found = 1;
+		}
+		if (lv_is_origin(lv) || lv_is_cow(lv)) {
+			log_print("Skipping snapshot-related LV %s", lv->name);
+			continue;
+		}
+		if (lv->status & MIRRORED) {
+			log_print("Skipping mirror LV %s", lv->name);
+			continue;
+		}
+		if (lv->status & MIRROR_LOG) {
+			log_print("Skipping mirror log LV %s", lv->name);
+			continue;
+		}
+		if (lv->status & MIRROR_IMAGE) {
+			log_print("Skipping mirror image LV %s", lv->name);
+			continue;
+		}
+		if (lv->status & LOCKED) {
+			log_print("Skipping locked LV %s", lv->name);
+			continue;
+		}
+		if (!_insert_pvmove_mirrors(cmd, lv_mirr, source_pvl, lv,
+					    *lvs_changed))
+			return_NULL;
+	}
+
+	if (lv_name && !lv_found) {
+		log_error("Logical volume %s not found.", lv_name);
+		return NULL;
+	}
+
+	/* Is temporary mirror empty? */
+	if (!lv_mirr->le_count) {
+		log_error("No data to move for %s", vg->name);
+		return NULL;
+	}
+
+	if (!lv_add_mirrors(cmd, lv_mirr, 1, 1, 0, log_count,
+			    allocatable_pvs, alloc, MIRROR_BY_SEG)) {
+		log_error("Failed to convert pvmove LV to mirrored");
+		return_NULL;
+	}
+
+	if (!split_parent_segments_for_layer(cmd, lv_mirr)) {
+		log_error("Failed to split segments being moved");
+		return_NULL;
+	}
+
+	return lv_mirr;
+}
+
+static int _activate_lv(struct cmd_context *cmd, struct logical_volume *lv_mirr,
+			unsigned exclusive)
+{
+	if (exclusive)
+		return activate_lv_excl(cmd, lv_mirr);
+
+	return activate_lv(cmd, lv_mirr);
+}
+
+static int _update_metadata(struct cmd_context *cmd, struct volume_group *vg,
+			    struct logical_volume *lv_mirr,
+			    struct dm_list *lvs_changed, unsigned flags)
+{
+	unsigned exclusive = _pvmove_is_exclusive(cmd, vg);
+	unsigned first_time = (flags & PVMOVE_FIRST_TIME) ? 1 : 0;
+
+	log_verbose("Updating volume group metadata");
+	if (!vg_write(vg)) {
+		log_error("ABORTING: Volume group metadata update failed.");
+		return 0;
+	}
+
+	backup(vg);
+
+	/* Suspend lvs_changed */
+	if (!suspend_lvs(cmd, lvs_changed))
+		return_0;
+
+	/* Suspend mirrors on subsequent calls */
+	if (!first_time) {
+		if (!suspend_lv(cmd, lv_mirr)) {
+			stack;
+			resume_lvs(cmd, lvs_changed);
+			vg_revert(vg);
+			return 0;
+		}
+	}
+
+	/* Commit on-disk metadata */
+	if (!vg_commit(vg)) {
+		log_error("ABORTING: Volume group metadata update failed.");
+		if (!first_time)
+			resume_lv(cmd, lv_mirr);
+		resume_lvs(cmd, lvs_changed);
+		return 0;
+	}
+
+	/* Activate the temporary mirror LV */
+	/* Only the first mirror segment gets activated as a mirror */
+	/* FIXME: Add option to use a log */
+	if (first_time) {
+		if (!_activate_lv(cmd, lv_mirr, exclusive)) {
+			if (!test_mode())
+				log_error("ABORTING: Temporary mirror "
+					  "activation failed.  "
+					  "Run pvmove --abort.");
+			/* FIXME Resume using *original* metadata here! */
+			resume_lvs(cmd, lvs_changed);
+			return 0;
+		}
+	} else if (!resume_lv(cmd, lv_mirr)) {
+		log_error("Unable to reactivate logical volume \"%s\"",
+			  lv_mirr->name);
+		resume_lvs(cmd, lvs_changed);
+		return 0;
+	}
+
+	/* Unsuspend LVs */
+	if (!resume_lvs(cmd, lvs_changed)) {
+		log_error("Unable to resume logical volumes");
+		return 0;
+	}
+
+	return 1;
+}
+
+static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
+			  int argc, char **argv)
+{
+	const char *lv_name = NULL;
+	char *pv_name_arg;
+	struct volume_group *vg;
+	struct dm_list *source_pvl;
+	struct dm_list *allocatable_pvs;
+	alloc_policy_t alloc;
+	struct dm_list *lvs_changed;
+	struct physical_volume *pv;
+	struct logical_volume *lv_mirr;
+	unsigned first_time = 1;
+	unsigned exclusive;
+
+	pv_name_arg = argv[0];
+	argc--;
+	argv++;
+
+	/* Find PV (in VG) */
+	if (!(pv = find_pv_by_name(cmd, pv_name))) {
+		stack;
+		return EINVALID_CMD_LINE;
+	}
+
+	if (arg_count(cmd, name_ARG)) {
+		if (!(lv_name = _extract_lvname(cmd, pv_vg_name(pv),
+						arg_value(cmd, name_ARG)))) {
+			stack;
+			return EINVALID_CMD_LINE;
+		}
+
+		if (!validate_name(lv_name)) {
+			log_error("Logical volume name %s is invalid", lv_name);
+			return EINVALID_CMD_LINE;
+		}
+	}
+
+	/* Read VG */
+	log_verbose("Finding volume group \"%s\"", pv_vg_name(pv));
+
+	if (!(vg = _get_vg(cmd, pv_vg_name(pv)))) {
+		stack;
+		return ECMD_FAILED;
+	}
+
+	exclusive = _pvmove_is_exclusive(cmd, vg);
+
+	if ((lv_mirr = find_pvmove_lv(vg, pv_dev(pv), PVMOVE))) {
+		log_print("Detected pvmove in progress for %s", pv_name);
+		if (argc || lv_name)
+			log_error("Ignoring remaining command line arguments");
+
+		if (!(lvs_changed = lvs_using_lv(cmd, vg, lv_mirr))) {
+			log_error
+			    ("ABORTING: Failed to generate list of moving LVs");
+			unlock_vg(cmd, pv_vg_name(pv));
+			return ECMD_FAILED;
+		}
+
+		/* Ensure mirror LV is active */
+		if (!_activate_lv(cmd, lv_mirr, exclusive)) {
+			log_error
+			    ("ABORTING: Temporary mirror activation failed.");
+			unlock_vg(cmd, pv_vg_name(pv));
+			return ECMD_FAILED;
+		}
+
+		first_time = 0;
+	} else {
+		/* Determine PE ranges to be moved */
+		if (!(source_pvl = create_pv_list(cmd->mem, vg, 1,
+						  &pv_name_arg, 0))) {
+			stack;
+			unlock_vg(cmd, pv_vg_name(pv));
+			return ECMD_FAILED;
+		}
+
+		alloc = arg_uint_value(cmd, alloc_ARG, ALLOC_INHERIT);
+		if (alloc == ALLOC_INHERIT)
+			alloc = vg->alloc;
+
+		/* Get PVs we can use for allocation */
+		if (!(allocatable_pvs = _get_allocatable_pvs(cmd, argc, argv,
+							     vg, pv, alloc))) {
+			stack;
+			unlock_vg(cmd, pv_vg_name(pv));
+			return ECMD_FAILED;
+		}
+
+		if (!archive(vg)) {
+			unlock_vg(cmd, pv_vg_name(pv));
+			stack;
+			return ECMD_FAILED;
+		}
+
+		if (!(lv_mirr = _set_up_pvmove_lv(cmd, vg, source_pvl, lv_name,
+						  allocatable_pvs, alloc,
+						  &lvs_changed))) {
+			stack;
+			unlock_vg(cmd, pv_vg_name(pv));
+			return ECMD_FAILED;
+		}
+	}
+
+	/* Lock lvs_changed and activate (with old metadata) */
+	if (!activate_lvs(cmd, lvs_changed, exclusive)) {
+		stack;
+		unlock_vg(cmd, pv_vg_name(pv));
+		return ECMD_FAILED;
+	}
+
+	/* FIXME Presence of a mirror once set PVMOVE - now remove associated logic */
+	/* init_pvmove(1); */
+	/* vg->status |= PVMOVE; */
+
+	if (first_time) {
+		if (!_update_metadata
+		    (cmd, vg, lv_mirr, lvs_changed, PVMOVE_FIRST_TIME)) {
+			stack;
+			unlock_vg(cmd, pv_vg_name(pv));
+			return ECMD_FAILED;
+		}
+	}
+
+	/* LVs are all in status LOCKED */
+	unlock_vg(cmd, pv_vg_name(pv));
+
+	return ECMD_PROCESSED;
+}
+
+static int _finish_pvmove(struct cmd_context *cmd, struct volume_group *vg,
+			  struct logical_volume *lv_mirr,
+			  struct dm_list *lvs_changed)
+{
+	int r = 1;
+	struct dm_list lvs_completed;
+	struct lv_list *lvl;
+
+	/* Update metadata to remove mirror segments and break dependencies */
+	dm_list_init(&lvs_completed);
+	if (!lv_remove_mirrors(cmd, lv_mirr, 1, 0, NULL, PVMOVE) ||
+	    !remove_layers_for_segments_all(cmd, lv_mirr, PVMOVE,
+					    &lvs_completed)) {
+		log_error("ABORTING: Removal of temporary mirror failed");
+		return 0;
+	}
+
+	dm_list_iterate_items(lvl, &lvs_completed)
+		/* FIXME Assumes only one pvmove at a time! */
+		lvl->lv->status &= ~LOCKED;
+
+	/* Store metadata without dependencies on mirror segments */
+	if (!vg_write(vg)) {
+		log_error("ABORTING: Failed to write new data locations "
+			  "to disk.");
+		return 0;
+	}
+
+	/* Suspend LVs changed */
+	if (!suspend_lvs(cmd, lvs_changed)) {
+		log_error("Locking LVs to remove temporary mirror failed");
+		r = 0;
+	}
+
+	/* Suspend mirror LV to flush pending I/O */
+	if (!suspend_lv(cmd, lv_mirr)) {
+		log_error("Suspension of temporary mirror LV failed");
+		r = 0;
+	}
+
+	/* Store metadata without dependencies on mirror segments */
+	if (!vg_commit(vg)) {
+		log_error("ABORTING: Failed to write new data locations "
+			  "to disk.");
+		vg_revert(vg);
+		resume_lv(cmd, lv_mirr);
+		resume_lvs(cmd, lvs_changed);
+		return 0;
+	}
+
+	/* Release mirror LV.  (No pending I/O because it's been suspended.) */
+	if (!resume_lv(cmd, lv_mirr)) {
+		log_error("Unable to reactivate logical volume \"%s\"",
+			  lv_mirr->name);
+		r = 0;
+	}
+
+	/* Unsuspend LVs */
+	resume_lvs(cmd, lvs_changed);
+
+	/* Deactivate mirror LV */
+	if (!deactivate_lv(cmd, lv_mirr)) {
+		log_error("ABORTING: Unable to deactivate temporary logical "
+			  "volume \"%s\"", lv_mirr->name);
+		r = 0;
+	}
+
+	log_verbose("Removing temporary pvmove LV");
+	if (!lv_remove(lv_mirr)) {
+		log_error("ABORTING: Removal of temporary pvmove LV failed");
+		return 0;
+	}
+
+	/* Store it on disks */
+	log_verbose("Writing out final volume group after pvmove");
+	if (!vg_write(vg) || !vg_commit(vg)) {
+		log_error("ABORTING: Failed to write new data locations "
+			  "to disk.");
+		return 0;
+	}
+
+	/* FIXME backup positioning */
+	backup(vg);
+
+	return r;
+}
+
+static struct volume_group *_get_move_vg(struct cmd_context *cmd,
+					 const char *name)
+{
+	struct physical_volume *pv;
+
+	/* Reread all metadata in case it got changed */
+	if (!(pv = find_pv_by_name(cmd, name))) {
+		log_error("ABORTING: Can't reread PV %s", name);
+		/* What more could we do here? */
+		return NULL;
+	}
+
+	return _get_vg(cmd, pv_vg_name(pv));
+}
+
+static struct poll_functions _pvmove_fns = {
+	.get_copy_name_from_lv = get_pvmove_pvname_from_lv_mirr,
+	.get_copy_vg = _get_move_vg,
+	.get_copy_lv = find_pvmove_lv_from_pvname,
+	.update_metadata = _update_metadata,
+	.finish_copy = _finish_pvmove,
+};
+
+int pvmove_poll(struct cmd_context *cmd, const char *pv_name,
+		unsigned background)
+{
+	return poll_daemon(cmd, pv_name, background, PVMOVE, &_pvmove_fns,
+			   "Moved");
+}
+
+int pvmove(struct cmd_context *cmd, int argc, char **argv)
+{
+	char *pv_name = NULL;
+	char *colon;
+	int ret;
+
+	/* dm raid1 target must be present in every case */
+	if (!_pvmove_target_present(cmd, 0)) {
+		log_error("Required device-mapper target(s) not "
+			  "detected in your kernel");
+		return ECMD_FAILED;
+	}
+
+	if (argc) {
+		pv_name = argv[0];
+
+		/* Drop any PE lists from PV name */
+		if ((colon = strchr(pv_name, ':'))) {
+			if (!(pv_name = dm_pool_strndup(cmd->mem, pv_name,
+						     (unsigned) (colon -
+								 pv_name)))) {
+				log_error("Failed to clone PV name");
+				return ECMD_FAILED;
+			}
+		}
+
+		if (!arg_count(cmd, abort_ARG) &&
+		    (ret = _set_up_pvmove(cmd, pv_name, argc, argv)) !=
+		    ECMD_PROCESSED) {
+			stack;
+			return ret;
+		}
+	}
+
+	return pvmove_poll(cmd, pv_name,
+			   arg_count(cmd, background_ARG) ? 1U : 0);
+}
Index: src/external/gpl2/lvm2tools/dist/tools/pvremove.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/pvremove.c
diff -N src/external/gpl2/lvm2tools/dist/tools/pvremove.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/pvremove.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,160 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+const char _really_wipe[] =
+    "Really WIPE LABELS from physical volume \"%s\" of volume group \"%s\" [y/n]? ";
+
+/*
+ * Decide whether it is "safe" to wipe the labels on this device.
+ * 0 indicates we may not.
+ */
+static int pvremove_check(struct cmd_context *cmd, const char *name)
+{
+	struct physical_volume *pv;
+	struct dm_list mdas;
+
+	dm_list_init(&mdas);
+
+	/* FIXME Check partition type is LVM unless --force is given */
+
+	/* Is there a pv here already? */
+	/* If not, this is an error unless you used -f. */
+	if (!(pv = pv_read(cmd, name, &mdas, NULL, 1))) {
+		if (arg_count(cmd, force_ARG))
+			return 1;
+		log_error("Physical Volume %s not found", name);
+		return 0;
+	}
+
+	/*
+	 * If a PV has no MDAs it may appear to be an
+	 * orphan until the metadata is read off
+	 * another PV in the same VG.  Detecting this
+	 * means checking every VG by scanning every
+	 * PV on the system.
+	 */
+	if (is_orphan(pv) && !dm_list_size(&mdas)) {
+		if (!scan_vgs_for_pvs(cmd)) {
+			log_error("Rescan for PVs without metadata areas "
+				  "failed.");
+			return 0;
+		}
+		if (!(pv = pv_read(cmd, name, NULL, NULL, 1))) {
+			log_error("Failed to read physical volume %s", name);
+			return 0;
+		}
+	}
+
+	/* orphan ? */
+	if (is_orphan(pv))
+		return 1;
+
+	/* Allow partial & exported VGs to be destroyed. */
+	/* we must have -ff to overwrite a non orphan */
+	if (arg_count(cmd, force_ARG) < 2) {
+		log_error("Can't pvremove physical volume \"%s\" of "
+			  "volume group \"%s\" without -ff", name, pv_vg_name(pv));
+		return 0;
+	}
+
+	/* prompt */
+	if (!arg_count(cmd, yes_ARG) &&
+	    yes_no_prompt(_really_wipe, name, pv_vg_name(pv)) == 'n') {
+		log_print("%s: physical volume label not removed", name);
+		return 0;
+	}
+
+	if (arg_count(cmd, force_ARG)) {
+		log_warn("WARNING: Wiping physical volume label from "
+			  "%s%s%s%s", name,
+			  !is_orphan(pv) ? " of volume group \"" : "",
+			  !is_orphan(pv) ? pv_vg_name(pv) : "",
+			  !is_orphan(pv) ? "\"" : "");
+	}
+
+	return 1;
+}
+
+static int pvremove_single(struct cmd_context *cmd, const char *pv_name,
+			   void *handle __attribute((unused)))
+{
+	struct device *dev;
+	int ret = ECMD_FAILED;
+
+	if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE)) {
+		log_error("Can't get lock for orphan PVs");
+		return ECMD_FAILED;
+	}
+
+	if (!pvremove_check(cmd, pv_name))
+		goto error;
+
+	if (!(dev = dev_cache_get(pv_name, cmd->filter))) {
+		log_error("%s: Couldn't find device.  Check your filters?",
+			  pv_name);
+		goto error;
+	}
+
+	if (!dev_test_excl(dev)) {
+		/* FIXME Detect whether device-mapper is still using the device */
+		log_error("Can't open %s exclusively - not removing. "
+			  "Mounted filesystem?", dev_name(dev));
+		goto error;
+	}
+
+	/* Wipe existing label(s) */
+	if (!label_remove(dev)) {
+		log_error("Failed to wipe existing label(s) on %s", pv_name);
+		goto error;
+	}
+
+	log_print("Labels on physical volume \"%s\" successfully wiped",
+		  pv_name);
+
+	ret = ECMD_PROCESSED;
+
+      error:
+	unlock_vg(cmd, VG_ORPHANS);
+
+	return ret;
+}
+
+int pvremove(struct cmd_context *cmd, int argc, char **argv)
+{
+	int i, r;
+	int ret = ECMD_PROCESSED;
+
+	if (!argc) {
+		log_error("Please enter a physical volume path");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (arg_count(cmd, yes_ARG) && !arg_count(cmd, force_ARG)) {
+		log_error("Option y can only be given with option f");
+		return EINVALID_CMD_LINE;
+	}
+
+	for (i = 0; i < argc; i++) {
+		r = pvremove_single(cmd, argv[i], NULL);
+		if (r > ret)
+			ret = r;
+	}
+
+	return ret;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/pvresize.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/pvresize.c
diff -N src/external/gpl2/lvm2tools/dist/tools/pvresize.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/pvresize.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,238 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2005 Zak Kipling. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+struct pvresize_params {
+	uint64_t new_size;
+
+	unsigned done;
+	unsigned total;
+};
+
+static int _pv_resize_single(struct cmd_context *cmd,
+			     struct volume_group *vg,
+			     struct physical_volume *pv,
+			     const uint64_t new_size)
+{
+	struct pv_list *pvl;
+	int consistent = 1;
+	uint64_t size = 0;
+	uint32_t new_pe_count = 0;
+	struct dm_list mdas;
+	const char *pv_name = pv_dev_name(pv);
+	const char *vg_name;
+	struct lvmcache_info *info;
+	int mda_count = 0;
+
+	dm_list_init(&mdas);
+
+	if (is_orphan_vg(pv_vg_name(pv))) {
+		vg_name = VG_ORPHANS;
+		if (!lock_vol(cmd, vg_name, LCK_VG_WRITE)) {
+			log_error("Can't get lock for orphans");
+			return 0;
+		}
+
+		if (!(pv = pv_read(cmd, pv_name, &mdas, NULL, 1))) {
+			unlock_vg(cmd, vg_name);
+			log_error("Unable to read PV \"%s\"", pv_name);
+			return 0;
+		}
+
+		mda_count = dm_list_size(&mdas);
+	} else {
+		vg_name = pv_vg_name(pv);
+
+		if (!lock_vol(cmd, vg_name, LCK_VG_WRITE)) {
+			log_error("Can't get lock for %s", pv_vg_name(pv));
+			return 0;
+		}
+
+		if (!(vg = vg_read(cmd, vg_name, NULL, &consistent))) {
+			unlock_vg(cmd, vg_name);
+			log_error("Unable to find volume group of \"%s\"",
+				  pv_name);
+			return 0;
+		}
+
+		if (!vg_check_status(vg, CLUSTERED | EXPORTED_VG | LVM_WRITE)) {
+			unlock_vg(cmd, vg_name);
+			return 0;
+		}
+
+		if (!(pvl = find_pv_in_vg(vg, pv_name))) {
+			unlock_vg(cmd, vg_name);
+			log_error("Unable to find \"%s\" in volume group \"%s\"",
+				  pv_name, vg->name);
+			return 0;
+		}
+
+		pv = pvl->pv;
+
+		if (!(info = info_from_pvid(pv->dev->pvid, 0))) {
+			unlock_vg(cmd, vg_name);
+			log_error("Can't get info for PV %s in volume group %s",
+				  pv_name, vg->name);
+			return 0;
+		}
+
+		mda_count = dm_list_size(&info->mdas);
+
+		if (!archive(vg))
+			return 0;
+	}
+
+	/* FIXME Create function to test compatibility properly */
+	if (mda_count > 1) {
+		log_error("%s: too many metadata areas for pvresize", pv_name);
+		unlock_vg(cmd, vg_name);
+		return 0;
+	}
+
+	if (!(pv->fmt->features & FMT_RESIZE_PV)) {
+		log_error("Physical volume %s format does not support resizing.",
+			  pv_name);
+		unlock_vg(cmd, vg_name);
+		return 0;
+	}
+
+	/* Get new size */
+	if (!dev_get_size(pv_dev(pv), &size)) {
+		log_error("%s: Couldn't get size.", pv_name);
+		unlock_vg(cmd, vg_name);
+		return 0;
+	}
+	
+	if (new_size) {
+		if (new_size > size)
+			log_warn("WARNING: %s: Overriding real size. "
+				  "You could lose data.", pv_name);
+		log_verbose("%s: Pretending size is %" PRIu64 " not %" PRIu64
+			    " sectors.", pv_name, new_size, pv_size(pv));
+		size = new_size;
+	}
+
+	if (size < PV_MIN_SIZE) {
+		log_error("%s: Size must exceed minimum of %ld sectors.",
+			  pv_name, PV_MIN_SIZE);
+		unlock_vg(cmd, vg_name);
+		return 0;
+	}
+
+	if (size < pv_pe_start(pv)) {
+		log_error("%s: Size must exceed physical extent start of "
+			  "%" PRIu64 " sectors.", pv_name, pv_pe_start(pv));
+		unlock_vg(cmd, vg_name);
+		return 0;
+	}
+
+	pv->size = size;
+
+	if (vg) {
+		pv->size -= pv_pe_start(pv);
+		new_pe_count = pv_size(pv) / vg->extent_size;
+		
+ 		if (!new_pe_count) {
+			log_error("%s: Size must leave space for at "
+				  "least one physical extent of "
+				  "%" PRIu32 " sectors.", pv_name,
+				  pv_pe_size(pv));
+			unlock_vg(cmd, vg_name);
+			return 0;
+		}
+
+		if (!pv_resize(pv, vg, new_pe_count)) {
+			unlock_vg(cmd, vg_name);
+			return_0;
+		}
+	}
+
+	log_verbose("Resizing volume \"%s\" to %" PRIu64 " sectors.",
+		    pv_name, pv_size(pv));
+
+	log_verbose("Updating physical volume \"%s\"", pv_name);
+	if (!is_orphan_vg(pv_vg_name(pv))) {
+		if (!vg_write(vg) || !vg_commit(vg)) {
+			unlock_vg(cmd, pv_vg_name(pv));
+			log_error("Failed to store physical volume \"%s\" in "
+				  "volume group \"%s\"", pv_name, vg->name);
+			return 0;
+		}
+		backup(vg);
+		unlock_vg(cmd, vg_name);
+	} else {
+		if (!(pv_write(cmd, pv, NULL, INT64_C(-1)))) {
+			unlock_vg(cmd, VG_ORPHANS);
+			log_error("Failed to store physical volume \"%s\"",
+				  pv_name);
+			return 0;
+		}
+		unlock_vg(cmd, vg_name);
+	}
+
+	log_print("Physical volume \"%s\" changed", pv_name);
+	return 1;
+}
+
+static int _pvresize_single(struct cmd_context *cmd,
+			    struct volume_group *vg,
+			    struct physical_volume *pv,
+			    void *handle)
+{
+	struct pvresize_params *params = (struct pvresize_params *) handle;
+
+	params->total++;
+
+	if (!_pv_resize_single(cmd, vg, pv, params->new_size))
+		return ECMD_FAILED;
+	
+	params->done++;
+
+	return ECMD_PROCESSED;
+}
+
+int pvresize(struct cmd_context *cmd, int argc, char **argv)
+{
+	struct pvresize_params params;
+	int ret;
+
+	if (!argc) {
+		log_error("Please supply physical volume(s)");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (arg_sign_value(cmd, physicalvolumesize_ARG, 0) == SIGN_MINUS) {
+		log_error("Physical volume size may not be negative");
+		return 0;
+	}
+
+	params.new_size = arg_uint64_value(cmd, physicalvolumesize_ARG,
+					   UINT64_C(0));
+
+	params.done = 0;
+	params.total = 0;
+
+	ret = process_each_pv(cmd, argc, argv, NULL, LCK_VG_WRITE, &params,
+			      _pvresize_single);
+
+	log_print("%d physical volume(s) resized / %d physical volume(s) "
+		  "not resized", params.done, params.total - params.done);
+
+	return ret;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/pvscan.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/pvscan.c
diff -N src/external/gpl2/lvm2tools/dist/tools/pvscan.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/pvscan.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,207 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+int pv_max_name_len = 0;
+int vg_max_name_len = 0;
+
+static void _pvscan_display_single(struct cmd_context *cmd,
+				   struct physical_volume *pv,
+				   void *handle __attribute((unused)))
+{
+	char uuid[64] __attribute((aligned(8)));
+	unsigned vg_name_len = 0;
+
+	char pv_tmp_name[NAME_LEN] = { 0, };
+	char vg_tmp_name[NAME_LEN] = { 0, };
+	char vg_name_this[NAME_LEN] = { 0, };
+
+	/* short listing? */
+	if (arg_count(cmd, short_ARG) > 0) {
+		log_print("%s", pv_dev_name(pv));
+		return;
+	}
+
+	if (arg_count(cmd, verbose_ARG) > 1) {
+		/* FIXME As per pv_display! Drop through for now. */
+		/* pv_show(pv); */
+
+		/* FIXME - Moved to Volume Group structure */
+		/* log_print("System Id             %s", pv->vg->system_id); */
+
+		/* log_print(" "); */
+		/* return; */
+	}
+
+	memset(pv_tmp_name, 0, sizeof(pv_tmp_name));
+
+	vg_name_len = strlen(pv_vg_name(pv)) + 1;
+
+	if (arg_count(cmd, uuid_ARG)) {
+		if (!id_write_format(&pv->id, uuid, sizeof(uuid))) {
+			stack;
+			return;
+		}
+
+		sprintf(pv_tmp_name, "%-*s with UUID %s",
+			pv_max_name_len - 2, pv_dev_name(pv), uuid);
+	} else {
+		sprintf(pv_tmp_name, "%s", pv_dev_name(pv));
+	}
+
+	if (is_orphan(pv)) {
+		log_print("PV %-*s    %-*s %s [%s]",
+			  pv_max_name_len, pv_tmp_name,
+			  vg_max_name_len, " ",
+			  pv->fmt ? pv->fmt->name : "    ",
+			  display_size(cmd, pv_size(pv)));
+		return;
+	}
+
+	if (pv_status(pv) & EXPORTED_VG) {
+		strncpy(vg_name_this, pv_vg_name(pv), vg_name_len);
+		log_print("PV %-*s  is in exported VG %s "
+			  "[%s / %s free]",
+			  pv_max_name_len, pv_tmp_name,
+			  vg_name_this,
+			  display_size(cmd, (uint64_t) pv_pe_count(pv) *
+				       pv_pe_size(pv)),
+			  display_size(cmd, (uint64_t) (pv_pe_count(pv) -
+						pv_pe_alloc_count(pv))
+				       * pv_pe_size(pv)));
+		return;
+	}
+
+	sprintf(vg_tmp_name, "%s", pv_vg_name(pv));
+	log_print("PV %-*s VG %-*s %s [%s / %s free]", pv_max_name_len,
+		  pv_tmp_name, vg_max_name_len, vg_tmp_name,
+		  pv->fmt ? pv->fmt->name : "    ",
+		  display_size(cmd, (uint64_t) pv_pe_count(pv) *
+					       pv_pe_size(pv)),
+		  display_size(cmd, (uint64_t) (pv_pe_count(pv) -
+						pv_pe_alloc_count(pv)) *
+					   pv_pe_size(pv)));
+	return;
+}
+
+int pvscan(struct cmd_context *cmd, int argc __attribute((unused)),
+	   char **argv __attribute((unused)))
+{
+	int new_pvs_found = 0;
+	int pvs_found = 0;
+
+	struct dm_list *pvslist;
+	struct pv_list *pvl;
+	struct physical_volume *pv;
+
+	uint64_t size_total = 0;
+	uint64_t size_new = 0;
+
+	int len = 0;
+	pv_max_name_len = 0;
+	vg_max_name_len = 0;
+
+	if (arg_count(cmd, novolumegroup_ARG) && arg_count(cmd, exported_ARG)) {
+		log_error("Options -e and -n are incompatible");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (arg_count(cmd, exported_ARG) || arg_count(cmd, novolumegroup_ARG))
+		log_warn("WARNING: only considering physical volumes %s",
+			  arg_count(cmd, exported_ARG) ?
+			  "of exported volume group(s)" : "in no volume group");
+
+	if (!lock_vol(cmd, VG_GLOBAL, LCK_VG_WRITE)) {
+		log_error("Unable to obtain global lock.");
+		return ECMD_FAILED;
+	}
+
+	persistent_filter_wipe(cmd->filter);
+	lvmcache_destroy(cmd, 1);
+
+	log_verbose("Walking through all physical volumes");
+	if (!(pvslist = get_pvs(cmd))) {
+		unlock_vg(cmd, VG_GLOBAL);
+		return ECMD_FAILED;
+	}
+
+	/* eliminate exported/new if required */
+	dm_list_iterate_items(pvl, pvslist) {
+		pv = pvl->pv;
+
+		if ((arg_count(cmd, exported_ARG)
+		     && !(pv_status(pv) & EXPORTED_VG))
+		    || (arg_count(cmd, novolumegroup_ARG) && (!is_orphan(pv)))) {
+			dm_list_del(&pvl->list);
+			continue;
+		}
+
+		/* Also check for MD use? */
+/*******
+		if (MAJOR(pv_create_kdev_t(pv[p]->pv_name)) != MD_MAJOR) {
+			log_print
+			    ("WARNING: physical volume \"%s\" belongs to a meta device",
+			     pv[p]->pv_name);
+		}
+		if (MAJOR(pv[p]->pv_dev) != MD_MAJOR)
+			continue;
+********/
+		pvs_found++;
+
+		if (is_orphan(pv)) {
+			new_pvs_found++;
+			size_new += pv_size(pv);
+			size_total += pv_size(pv);
+		} else
+			size_total += pv_pe_count(pv) * pv_pe_size(pv);
+	}
+
+	/* find maximum pv name length */
+	pv_max_name_len = vg_max_name_len = 0;
+	dm_list_iterate_items(pvl, pvslist) {
+		pv = pvl->pv;
+		len = strlen(pv_dev_name(pv));
+		if (pv_max_name_len < len)
+			pv_max_name_len = len;
+		len = strlen(pv_vg_name(pv));
+		if (vg_max_name_len < len)
+			vg_max_name_len = len;
+	}
+	pv_max_name_len += 2;
+	vg_max_name_len += 2;
+
+	dm_list_iterate_items(pvl, pvslist)
+	    _pvscan_display_single(cmd, pvl->pv, NULL);
+
+	if (!pvs_found) {
+		log_print("No matching physical volumes found");
+		unlock_vg(cmd, VG_GLOBAL);
+		return ECMD_PROCESSED;
+	}
+
+	log_print("Total: %d [%s] / in use: %d [%s] / in no VG: %d [%s]",
+		  pvs_found,
+		  display_size(cmd, size_total),
+		  pvs_found - new_pvs_found,
+		  display_size(cmd, (size_total - size_new)),
+		  new_pvs_found, display_size(cmd, size_new));
+
+	unlock_vg(cmd, VG_GLOBAL);
+
+	return ECMD_PROCESSED;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/reporter.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/reporter.c
diff -N src/external/gpl2/lvm2tools/dist/tools/reporter.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/reporter.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,416 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+#include "report.h"
+
+static int _vgs_single(struct cmd_context *cmd __attribute((unused)),
+		       const char *vg_name, struct volume_group *vg,
+		       int consistent __attribute((unused)), void *handle)
+{
+	if (!vg) {
+		log_error("Volume group %s not found", vg_name);
+		return ECMD_FAILED;
+	}
+
+	if (!report_object(handle, vg, NULL, NULL, NULL, NULL))
+		return ECMD_FAILED;
+
+	check_current_backup(vg);
+
+	return ECMD_PROCESSED;
+}
+
+static int _lvs_single(struct cmd_context *cmd, struct logical_volume *lv,
+		       void *handle)
+{
+	if (!arg_count(cmd, all_ARG) && !lv_is_visible(lv))
+		return ECMD_PROCESSED;
+
+	if (!report_object(handle, lv->vg, lv, NULL, NULL, NULL))
+		return ECMD_FAILED;
+
+	return ECMD_PROCESSED;
+}
+
+static int _segs_single(struct cmd_context *cmd __attribute((unused)),
+			struct lv_segment *seg, void *handle)
+{
+	if (!report_object(handle, seg->lv->vg, seg->lv, NULL, seg, NULL))
+		return ECMD_FAILED;
+
+	return ECMD_PROCESSED;
+}
+
+static int _pvsegs_sub_single(struct cmd_context *cmd __attribute((unused)),
+			      struct volume_group *vg,
+			      struct pv_segment *pvseg, void *handle)
+{
+	int ret = ECMD_PROCESSED;
+	struct lv_segment *seg = pvseg->lvseg;
+
+	struct logical_volume _free_logical_volume = {
+		.vg = vg,
+		.name = (char *) "",
+	        .snapshot = NULL,
+		.status = VISIBLE_LV,
+		.major = -1,
+		.minor = -1,
+	};
+
+	struct lv_segment _free_lv_segment = {
+        	.lv = &_free_logical_volume,
+        	.le = 0,
+        	.status = 0,
+        	.stripe_size = 0,
+        	.area_count = 0,
+        	.area_len = 0,
+        	.origin = NULL,
+        	.cow = NULL,
+        	.chunk_size = 0,
+        	.region_size = 0,
+        	.extents_copied = 0,
+        	.log_lv = NULL,
+        	.areas = NULL,
+	};
+
+        _free_lv_segment.segtype = get_segtype_from_string(cmd, "free");
+	_free_lv_segment.len = pvseg->len;
+	dm_list_init(&_free_logical_volume.tags);
+	dm_list_init(&_free_logical_volume.segments);
+	dm_list_init(&_free_logical_volume.segs_using_this_lv);
+
+	if (!report_object(handle, vg, seg ? seg->lv : &_free_logical_volume, pvseg->pv,
+			   seg ? : &_free_lv_segment, pvseg))
+		ret = ECMD_FAILED;
+
+	return ret;
+}
+
+static int _lvsegs_single(struct cmd_context *cmd, struct logical_volume *lv,
+			  void *handle)
+{
+	if (!arg_count(cmd, all_ARG) && !lv_is_visible(lv))
+		return ECMD_PROCESSED;
+
+	return process_each_segment_in_lv(cmd, lv, handle, _segs_single);
+}
+
+static int _pvsegs_single(struct cmd_context *cmd, struct volume_group *vg,
+			  struct physical_volume *pv, void *handle)
+{
+	return process_each_segment_in_pv(cmd, vg, pv, handle,
+					  _pvsegs_sub_single);
+}
+
+static int _pvs_single(struct cmd_context *cmd, struct volume_group *vg,
+		       struct physical_volume *pv, void *handle)
+{
+	struct pv_list *pvl;
+	int ret = ECMD_PROCESSED;
+	const char *vg_name = NULL;
+
+	if (is_pv(pv) && !is_orphan(pv) && !vg) {
+		vg_name = pv_vg_name(pv);
+
+		if (!(vg = vg_lock_and_read(cmd, vg_name, (char *)&pv->vgid,
+					    LCK_VG_READ, CLUSTERED, 0))) {
+			log_error("Skipping volume group %s", vg_name);
+			return ECMD_FAILED;
+		}
+
+		/*
+		 * Replace possibly incomplete PV structure with new one
+		 * allocated in vg_read() path.
+		*/
+		if (!(pvl = find_pv_in_vg(vg, pv_dev_name(pv)))) {
+			log_error("Unable to find \"%s\" in volume group \"%s\"",
+				  pv_dev_name(pv), vg->name);
+			ret = ECMD_FAILED;
+			goto out;
+		}
+
+		 pv = pvl->pv;
+	}
+
+	if (!report_object(handle, vg, NULL, pv, NULL, NULL))
+		ret = ECMD_FAILED;
+
+out:
+	if (vg_name)
+		unlock_vg(cmd, vg_name);
+
+	return ret;
+}
+
+static int _pvs_in_vg(struct cmd_context *cmd, const char *vg_name,
+		      struct volume_group *vg,
+		      int consistent __attribute((unused)),
+		      void *handle)
+{
+	if (!vg) {
+		log_error("Volume group %s not found", vg_name);
+		return ECMD_FAILED;
+	}
+
+	return process_each_pv_in_vg(cmd, vg, NULL, handle, &_pvs_single);
+}
+
+static int _pvsegs_in_vg(struct cmd_context *cmd, const char *vg_name,
+			 struct volume_group *vg,
+			 int consistent __attribute((unused)),
+			 void *handle)
+{
+	if (!vg) {
+		log_error("Volume group %s not found", vg_name);
+		return ECMD_FAILED;
+	}
+
+	return process_each_pv_in_vg(cmd, vg, NULL, handle, &_pvsegs_single);
+}
+
+static int _report(struct cmd_context *cmd, int argc, char **argv,
+		   report_type_t report_type)
+{
+	void *report_handle;
+	const char *opts;
+	char *str;
+	const char *keys = NULL, *options = NULL, *separator;
+	int r = ECMD_PROCESSED;
+	int aligned, buffered, headings, field_prefixes, quoted;
+	int columns_as_rows;
+	unsigned args_are_pvs;
+
+	aligned = find_config_tree_int(cmd, "report/aligned",
+				  DEFAULT_REP_ALIGNED);
+	buffered = find_config_tree_int(cmd, "report/buffered",
+				   DEFAULT_REP_BUFFERED);
+	headings = find_config_tree_int(cmd, "report/headings",
+				   DEFAULT_REP_HEADINGS);
+	separator = find_config_tree_str(cmd, "report/separator",
+				    DEFAULT_REP_SEPARATOR);
+	field_prefixes = find_config_tree_int(cmd, "report/prefixes",
+					      DEFAULT_REP_PREFIXES);
+	quoted = find_config_tree_int(cmd, "report/quoted",
+				     DEFAULT_REP_QUOTED);
+	columns_as_rows = find_config_tree_int(cmd, "report/columns_as_rows",
+					       DEFAULT_REP_COLUMNS_AS_ROWS);
+
+	args_are_pvs = (report_type == PVS || report_type == PVSEGS) ? 1 : 0;
+
+	switch (report_type) {
+	case LVS:
+		keys = find_config_tree_str(cmd, "report/lvs_sort",
+				       DEFAULT_LVS_SORT);
+		if (!arg_count(cmd, verbose_ARG))
+			options = find_config_tree_str(cmd,
+						  "report/lvs_cols",
+						  DEFAULT_LVS_COLS);
+		else
+			options = find_config_tree_str(cmd,
+						  "report/lvs_cols_verbose",
+						  DEFAULT_LVS_COLS_VERB);
+		break;
+	case VGS:
+		keys = find_config_tree_str(cmd, "report/vgs_sort",
+				       DEFAULT_VGS_SORT);
+		if (!arg_count(cmd, verbose_ARG))
+			options = find_config_tree_str(cmd,
+						  "report/vgs_cols",
+						  DEFAULT_VGS_COLS);
+		else
+			options = find_config_tree_str(cmd,
+						  "report/vgs_cols_verbose",
+						  DEFAULT_VGS_COLS_VERB);
+		break;
+	case PVS:
+		keys = find_config_tree_str(cmd, "report/pvs_sort",
+				       DEFAULT_PVS_SORT);
+		if (!arg_count(cmd, verbose_ARG))
+			options = find_config_tree_str(cmd,
+						  "report/pvs_cols",
+						  DEFAULT_PVS_COLS);
+		else
+			options = find_config_tree_str(cmd,
+						  "report/pvs_cols_verbose",
+						  DEFAULT_PVS_COLS_VERB);
+		break;
+	case SEGS:
+		keys = find_config_tree_str(cmd, "report/segs_sort",
+				       DEFAULT_SEGS_SORT);
+		if (!arg_count(cmd, verbose_ARG))
+			options = find_config_tree_str(cmd,
+						  "report/segs_cols",
+						  DEFAULT_SEGS_COLS);
+		else
+			options = find_config_tree_str(cmd,
+						  "report/segs_cols_verbose",
+						  DEFAULT_SEGS_COLS_VERB);
+		break;
+	case PVSEGS:
+		keys = find_config_tree_str(cmd, "report/pvsegs_sort",
+				       DEFAULT_PVSEGS_SORT);
+		if (!arg_count(cmd, verbose_ARG))
+			options = find_config_tree_str(cmd,
+						  "report/pvsegs_cols",
+						  DEFAULT_PVSEGS_COLS);
+		else
+			options = find_config_tree_str(cmd,
+						  "report/pvsegs_cols_verbose",
+						  DEFAULT_PVSEGS_COLS_VERB);
+		break;
+	}
+
+	/* If -o supplied use it, else use default for report_type */
+	if (arg_count(cmd, options_ARG)) {
+		opts = arg_str_value(cmd, options_ARG, "");
+		if (!opts || !*opts) {
+			log_error("Invalid options string: %s", opts);
+			return EINVALID_CMD_LINE;
+		}
+		if (*opts == '+') {
+			if (!(str = dm_pool_alloc(cmd->mem,
+					 strlen(options) + strlen(opts) + 1))) {
+				log_error("options string allocation failed");
+				return ECMD_FAILED;
+			}
+			strcpy(str, options);
+			strcat(str, ",");
+			strcat(str, opts + 1);
+			options = str;
+		} else
+			options = opts;
+	}
+
+	/* -O overrides default sort settings */
+	if (arg_count(cmd, sort_ARG))
+		keys = arg_str_value(cmd, sort_ARG, "");
+
+	if (arg_count(cmd, separator_ARG))
+		separator = arg_str_value(cmd, separator_ARG, " ");
+	if (arg_count(cmd, separator_ARG))
+		aligned = 0;
+	if (arg_count(cmd, aligned_ARG))
+		aligned = 1;
+	if (arg_count(cmd, unbuffered_ARG) && !arg_count(cmd, sort_ARG))
+		buffered = 0;
+	if (arg_count(cmd, noheadings_ARG))
+		headings = 0;
+	if (arg_count(cmd, nameprefixes_ARG)) {
+		aligned = 0;
+		field_prefixes = 1;
+	}
+	if (arg_count(cmd, unquoted_ARG))
+		quoted = 0;
+	if (arg_count(cmd, rows_ARG))
+		columns_as_rows = 1;
+
+	if (!(report_handle = report_init(cmd, options, keys, &report_type,
+					  separator, aligned, buffered,
+					  headings, field_prefixes, quoted,
+					  columns_as_rows))) {
+		stack;
+		return ECMD_FAILED;
+	}
+
+	/* Ensure options selected are compatible */
+	if (report_type & SEGS)
+		report_type |= LVS;
+	if (report_type & PVSEGS)
+		report_type |= PVS;
+	if ((report_type & LVS) && (report_type & PVS) && !args_are_pvs) {
+		log_error("Can't report LV and PV fields at the same time");
+		dm_report_free(report_handle);
+		return ECMD_FAILED;
+	}
+
+	/* Change report type if fields specified makes this necessary */
+	if ((report_type & PVSEGS) ||
+	    ((report_type & PVS) && (report_type & LVS)))
+		report_type = PVSEGS;
+	else if (report_type & PVS)
+		report_type = PVS;
+	else if (report_type & SEGS)
+		report_type = SEGS;
+	else if (report_type & LVS)
+		report_type = LVS;
+
+	switch (report_type) {
+	case LVS:
+		r = process_each_lv(cmd, argc, argv, LCK_VG_READ, report_handle,
+				    &_lvs_single);
+		break;
+	case VGS:
+		r = process_each_vg(cmd, argc, argv, LCK_VG_READ, 0,
+				    report_handle, &_vgs_single);
+		break;
+	case PVS:
+		if (args_are_pvs)
+			r = process_each_pv(cmd, argc, argv, NULL, LCK_VG_READ,
+					    report_handle, &_pvs_single);
+		else
+			r = process_each_vg(cmd, argc, argv, LCK_VG_READ, 0,
+					    report_handle, &_pvs_in_vg);
+		break;
+	case SEGS:
+		r = process_each_lv(cmd, argc, argv, LCK_VG_READ, report_handle,
+				    &_lvsegs_single);
+		break;
+	case PVSEGS:
+		if (args_are_pvs)
+			r = process_each_pv(cmd, argc, argv, NULL, LCK_VG_READ,
+					    report_handle, &_pvsegs_single);
+		else
+			r = process_each_vg(cmd, argc, argv, LCK_VG_READ, 0,
+					    report_handle, &_pvsegs_in_vg);
+		break;
+	}
+
+	dm_report_output(report_handle);
+
+	dm_report_free(report_handle);
+	return r;
+}
+
+int lvs(struct cmd_context *cmd, int argc, char **argv)
+{
+	report_type_t type;
+
+	if (arg_count(cmd, segments_ARG))
+		type = SEGS;
+	else
+		type = LVS;
+
+	return _report(cmd, argc, argv, type);
+}
+
+int vgs(struct cmd_context *cmd, int argc, char **argv)
+{
+	return _report(cmd, argc, argv, VGS);
+}
+
+int pvs(struct cmd_context *cmd, int argc, char **argv)
+{
+	report_type_t type;
+
+	if (arg_count(cmd, segments_ARG))
+		type = PVSEGS;
+	else
+		type = PVS;
+
+	return _report(cmd, argc, argv, type);
+}
Index: src/external/gpl2/lvm2tools/dist/tools/segtypes.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/segtypes.c
diff -N src/external/gpl2/lvm2tools/dist/tools/segtypes.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/segtypes.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,26 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+int segtypes(struct cmd_context *cmd, int argc __attribute((unused)),
+	     char **argv __attribute((unused)))
+{
+	display_segtypes(cmd);
+
+	return ECMD_PROCESSED;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/stub.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/stub.h
diff -N src/external/gpl2/lvm2tools/dist/tools/stub.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/stub.h	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,45 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define unimplemented \
+	log_error("Command not implemented yet."); return ECMD_FAILED
+
+/*int e2fsadm(struct cmd_context *cmd, int argc, char **argv) unimplemented*/
+int lvmsadc(struct cmd_context *cmd __attribute((unused)),
+	    int argc __attribute((unused)),
+	    char **argv __attribute((unused)))
+{
+	unimplemented;
+}
+
+int lvmsar(struct cmd_context *cmd __attribute((unused)),
+	   int argc __attribute((unused)),
+	   char **argv __attribute((unused)))
+{
+	unimplemented;
+}
+
+int pvdata(struct cmd_context *cmd __attribute((unused)),
+	   int argc __attribute((unused)),
+	   char **argv __attribute((unused)))
+{
+	log_error("There's no 'pvdata' command in LVM2.");
+	log_error("Use lvs, pvs, vgs instead; or use vgcfgbackup and read the text file backup.");
+	log_error("Metadata in LVM1 format can still be displayed using LVM1's pvdata command.");
+	return ECMD_FAILED;
+}
+
Index: src/external/gpl2/lvm2tools/dist/tools/toollib.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/toollib.c
diff -N src/external/gpl2/lvm2tools/dist/tools/toollib.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/toollib.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,1292 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+#include "lv_alloc.h"
+#include "xlate.h"
+
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+/* Command line args */
+unsigned arg_count(const struct cmd_context *cmd, int a)
+{
+	return cmd->args[a].count;
+}
+
+const char *arg_value(struct cmd_context *cmd, int a)
+{
+	return cmd->args[a].value;
+}
+
+const char *arg_str_value(struct cmd_context *cmd, int a, const char *def)
+{
+	return arg_count(cmd, a) ? cmd->args[a].value : def;
+}
+
+int32_t arg_int_value(struct cmd_context *cmd, int a, const int32_t def)
+{
+	return arg_count(cmd, a) ? cmd->args[a].i_value : def;
+}
+
+uint32_t arg_uint_value(struct cmd_context *cmd, int a, const uint32_t def)
+{
+	return arg_count(cmd, a) ? cmd->args[a].ui_value : def;
+}
+
+int64_t arg_int64_value(struct cmd_context *cmd, int a, const int64_t def)
+{
+	return arg_count(cmd, a) ? cmd->args[a].i64_value : def;
+}
+
+uint64_t arg_uint64_value(struct cmd_context *cmd, int a, const uint64_t def)
+{
+	return arg_count(cmd, a) ? cmd->args[a].ui64_value : def;
+}
+
+const void *arg_ptr_value(struct cmd_context *cmd, int a, const void *def)
+{
+	return arg_count(cmd, a) ? cmd->args[a].ptr : def;
+}
+
+sign_t arg_sign_value(struct cmd_context *cmd, int a, const sign_t def)
+{
+	return arg_count(cmd, a) ? cmd->args[a].sign : def;
+}
+
+percent_t arg_percent_value(struct cmd_context *cmd, int a, const percent_t def)
+{
+	return arg_count(cmd, a) ? cmd->args[a].percent : def;
+}
+
+int arg_count_increment(struct cmd_context *cmd, int a)
+{
+	return cmd->args[a].count++;
+}
+
+const char *command_name(struct cmd_context *cmd)
+{
+	return cmd->command->name;
+}
+
+/*
+ * Strip dev_dir if present
+ */
+char *skip_dev_dir(struct cmd_context *cmd, const char *vg_name,
+		   unsigned *dev_dir_found)
+{
+	const char *dmdir = dm_dir();
+	size_t dmdir_len = strlen(dmdir), vglv_sz;
+	char *vgname, *lvname, *layer, *vglv;
+
+	/* FIXME Do this properly */
+	if (*vg_name == '/') {
+		while (*vg_name == '/')
+			vg_name++;
+		vg_name--;
+	}
+
+	/* Reformat string if /dev/mapper found */
+	if (!strncmp(vg_name, dmdir, dmdir_len) && vg_name[dmdir_len] == '/') {
+		if (dev_dir_found)
+			*dev_dir_found = 1;
+		vg_name += dmdir_len;
+		while (*vg_name == '/')
+			vg_name++;
+
+		if (!dm_split_lvm_name(cmd->mem, vg_name, &vgname, &lvname, &layer) ||
+		    *layer) {
+			log_error("skip_dev_dir: Couldn't split up device name %s",
+				  vg_name);
+			return (char *) vg_name;
+		}
+		vglv_sz = strlen(vgname) + strlen(lvname) + 2;
+		if (!(vglv = dm_pool_alloc(cmd->mem, vglv_sz)) ||
+		    dm_snprintf(vglv, vglv_sz, "%s%s%s", vgname,
+				 *lvname ? "/" : "",
+				 lvname) < 0) {
+			log_error("vg/lv string alloc failed");
+			return (char *) vg_name;
+		}
+		return vglv;
+	}
+
+	if (!strncmp(vg_name, cmd->dev_dir, strlen(cmd->dev_dir))) {
+		if (dev_dir_found)
+			*dev_dir_found = 1;
+		vg_name += strlen(cmd->dev_dir);
+		while (*vg_name == '/')
+			vg_name++;
+	} else if (dev_dir_found)
+		*dev_dir_found = 0;
+
+	return (char *) vg_name;
+}
+
+/*
+ * Metadata iteration functions
+ */
+int process_each_lv_in_vg(struct cmd_context *cmd,
+			  const struct volume_group *vg,
+			  const struct dm_list *arg_lvnames,
+			  const struct dm_list *tags,
+			  void *handle,
+			  process_single_lv_fn_t process_single)
+{
+	int ret_max = ECMD_PROCESSED;
+	int ret = 0;
+	unsigned process_all = 0;
+	unsigned process_lv = 0;
+	unsigned tags_supplied = 0;
+	unsigned lvargs_supplied = 0;
+	unsigned lvargs_matched = 0;
+
+	struct lv_list *lvl;
+
+	if (!vg_check_status(vg, EXPORTED_VG))
+		return ECMD_FAILED;
+
+	if (tags && !dm_list_empty(tags))
+		tags_supplied = 1;
+
+	if (arg_lvnames && !dm_list_empty(arg_lvnames))
+		lvargs_supplied = 1;
+
+	/* Process all LVs in this VG if no restrictions given */
+	if (!tags_supplied && !lvargs_supplied)
+		process_all = 1;
+
+	/* Or if VG tags match */
+	if (!process_lv && tags_supplied &&
+	    str_list_match_list(tags, &vg->tags)) {
+		process_all = 1;
+	}
+
+	dm_list_iterate_items(lvl, &vg->lvs) {
+		if (lvl->lv->status & SNAPSHOT)
+			continue;
+
+		/* Should we process this LV? */
+		if (process_all)
+			process_lv = 1;
+		else
+			process_lv = 0;
+
+		/* LV tag match? */
+		if (!process_lv && tags_supplied &&
+		    str_list_match_list(tags, &lvl->lv->tags)) {
+			process_lv = 1;
+		}
+
+		/* LV name match? */
+		if (lvargs_supplied &&
+		    str_list_match_item(arg_lvnames, lvl->lv->name)) {
+			process_lv = 1;
+			lvargs_matched++;
+		}
+
+		if (!process_lv)
+			continue;
+
+		ret = process_single(cmd, lvl->lv, handle);
+		if (ret > ret_max)
+			ret_max = ret;
+		if (sigint_caught())
+			return ret_max;
+	}
+
+	if (lvargs_supplied && lvargs_matched != dm_list_size(arg_lvnames)) {
+		log_error("One or more specified logical volume(s) not found.");
+		if (ret_max < ECMD_FAILED)
+			ret_max = ECMD_FAILED;
+	}
+
+	return ret_max;
+}
+
+int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
+		    uint32_t lock_type, void *handle,
+		    int (*process_single) (struct cmd_context * cmd,
+					   struct logical_volume * lv,
+					   void *handle))
+{
+	int opt = 0;
+	int ret_max = ECMD_PROCESSED;
+	int ret = 0;
+	int consistent;
+
+	struct dm_list *tags_arg;
+	struct dm_list *vgnames;	/* VGs to process */
+	struct str_list *sll, *strl;
+	struct volume_group *vg;
+	struct dm_list tags, lvnames;
+	struct dm_list arg_lvnames;	/* Cmdline vgname or vgname/lvname */
+	char *vglv;
+	size_t vglv_sz;
+
+	const char *vgname;
+
+	dm_list_init(&tags);
+	dm_list_init(&arg_lvnames);
+
+	if (argc) {
+		struct dm_list arg_vgnames;
+
+		log_verbose("Using logical volume(s) on command line");
+		dm_list_init(&arg_vgnames);
+
+		for (; opt < argc; opt++) {
+			const char *lv_name = argv[opt];
+			char *vgname_def;
+			unsigned dev_dir_found = 0;
+
+			/* Do we have a tag or vgname or lvname? */
+			vgname = lv_name;
+
+			if (*vgname == '@') {
+				if (!validate_name(vgname + 1)) {
+					log_error("Skipping invalid tag %s",
+						  vgname);
+					continue;
+				}
+				if (!str_list_add(cmd->mem, &tags,
+						  dm_pool_strdup(cmd->mem,
+							      vgname + 1))) {
+					log_error("strlist allocation failed");
+					return ECMD_FAILED;
+				}
+				continue;
+			}
+
+			/* FIXME Jumbled parsing */
+			vgname = skip_dev_dir(cmd, vgname, &dev_dir_found);
+
+			if (*vgname == '/') {
+				log_error("\"%s\": Invalid path for Logical "
+					  "Volume", argv[opt]);
+				if (ret_max < ECMD_FAILED)
+					ret_max = ECMD_FAILED;
+				continue;
+			}
+			lv_name = vgname;
+			if (strchr(vgname, '/')) {
+				/* Must be an LV */
+				lv_name = strchr(vgname, '/');
+				while (*lv_name == '/')
+					lv_name++;
+				if (!(vgname = extract_vgname(cmd, vgname))) {
+					if (ret_max < ECMD_FAILED)
+						ret_max = ECMD_FAILED;
+					continue;
+				}
+			} else if (!dev_dir_found &&
+				   (vgname_def = default_vgname(cmd))) {
+				vgname = vgname_def;
+			} else
+				lv_name = NULL;
+
+			if (!str_list_add(cmd->mem, &arg_vgnames,
+					  dm_pool_strdup(cmd->mem, vgname))) {
+				log_error("strlist allocation failed");
+				return ECMD_FAILED;
+			}
+
+			if (!lv_name) {
+				if (!str_list_add(cmd->mem, &arg_lvnames,
+						  dm_pool_strdup(cmd->mem,
+							      vgname))) {
+					log_error("strlist allocation failed");
+					return ECMD_FAILED;
+				}
+			} else {
+				vglv_sz = strlen(vgname) + strlen(lv_name) + 2;
+				if (!(vglv = dm_pool_alloc(cmd->mem, vglv_sz)) ||
+				    dm_snprintf(vglv, vglv_sz, "%s/%s", vgname,
+						 lv_name) < 0) {
+					log_error("vg/lv string alloc failed");
+					return ECMD_FAILED;
+				}
+				if (!str_list_add(cmd->mem, &arg_lvnames, vglv)) {
+					log_error("strlist allocation failed");
+					return ECMD_FAILED;
+				}
+			}
+		}
+		vgnames = &arg_vgnames;
+	}
+
+	if (!argc || !dm_list_empty(&tags)) {
+		log_verbose("Finding all logical volumes");
+		if (!(vgnames = get_vgs(cmd, 0)) || dm_list_empty(vgnames)) {
+			log_error("No volume groups found");
+			return ret_max;
+		}
+	}
+
+	dm_list_iterate_items(strl, vgnames) {
+		vgname = strl->str;
+		if (is_orphan_vg(vgname))
+			continue;	/* FIXME Unnecessary? */
+		if (!lock_vol(cmd, vgname, lock_type)) {
+			log_error("Can't lock %s: skipping", vgname);
+			continue;
+		}
+		if (lock_type & LCK_WRITE)
+			consistent = 1;
+		else
+			consistent = 0;
+		if (!(vg = vg_read(cmd, vgname, NULL, &consistent)) || !consistent) {
+			unlock_vg(cmd, vgname);
+			if (!vg)
+				log_error("Volume group \"%s\" "
+					  "not found", vgname);
+			else {
+				if (!vg_check_status(vg, CLUSTERED)) {
+					if (ret_max < ECMD_FAILED)
+						ret_max = ECMD_FAILED;
+					continue;
+				}
+				log_error("Volume group \"%s\" "
+					  "inconsistent", vgname);
+			}
+
+			if (!vg || !(vg = recover_vg(cmd, vgname, lock_type))) {
+				if (ret_max < ECMD_FAILED)
+					ret_max = ECMD_FAILED;
+				continue;
+			}
+		}
+
+		if (!vg_check_status(vg, CLUSTERED)) {
+			unlock_vg(cmd, vgname);
+			if (ret_max < ECMD_FAILED)
+				ret_max = ECMD_FAILED;
+			continue;
+		}
+
+		tags_arg = &tags;
+		dm_list_init(&lvnames);	/* LVs to be processed in this VG */
+		dm_list_iterate_items(sll, &arg_lvnames) {
+			const char *vg_name = sll->str;
+			const char *lv_name = strchr(vg_name, '/');
+
+			if ((!lv_name && !strcmp(vg_name, vgname))) {
+				/* Process all LVs in this VG */
+				tags_arg = NULL;
+				dm_list_init(&lvnames);
+				break;
+			} else if (!strncmp(vg_name, vgname, strlen(vgname)) &&
+				   strlen(vgname) == (size_t) (lv_name - vg_name)) {
+				if (!str_list_add(cmd->mem, &lvnames,
+						  dm_pool_strdup(cmd->mem,
+							      lv_name + 1))) {
+					log_error("strlist allocation failed");
+					return ECMD_FAILED;
+				}
+			}
+		}
+
+		ret = process_each_lv_in_vg(cmd, vg, &lvnames, tags_arg,
+					    handle, process_single);
+		unlock_vg(cmd, vgname);
+		if (ret > ret_max)
+			ret_max = ret;
+		if (sigint_caught())
+			break;
+	}
+
+	return ret_max;
+}
+
+int process_each_segment_in_pv(struct cmd_context *cmd,
+			       struct volume_group *vg,
+			       struct physical_volume *pv,
+			       void *handle,
+			       int (*process_single) (struct cmd_context * cmd,
+						      struct volume_group * vg,
+						      struct pv_segment * pvseg,
+						      void *handle))
+{
+	struct pv_segment *pvseg;
+	const char *vg_name = NULL;
+	int ret_max = ECMD_PROCESSED;
+	int ret;
+
+	if (!vg && !is_orphan(pv)) {
+		vg_name = pv_vg_name(pv);
+
+		if (!(vg = vg_lock_and_read(cmd, vg_name, NULL, LCK_VG_READ,
+					    CLUSTERED, 0))) {
+			log_error("Skipping volume group %s", vg_name);
+			return ECMD_FAILED;
+		}
+	}
+
+	dm_list_iterate_items(pvseg, &pv->segments) {
+		ret = process_single(cmd, vg, pvseg, handle);
+		if (ret > ret_max)
+			ret_max = ret;
+		if (sigint_caught())
+			break;
+	}
+
+	if (vg_name)
+		unlock_vg(cmd, vg_name);
+
+	return ret_max;
+}
+
+int process_each_segment_in_lv(struct cmd_context *cmd,
+			       struct logical_volume *lv,
+			       void *handle,
+			       int (*process_single) (struct cmd_context * cmd,
+						      struct lv_segment * seg,
+						      void *handle))
+{
+	struct lv_segment *seg;
+	int ret_max = ECMD_PROCESSED;
+	int ret;
+
+	dm_list_iterate_items(seg, &lv->segments) {
+		ret = process_single(cmd, seg, handle);
+		if (ret > ret_max)
+			ret_max = ret;
+		if (sigint_caught())
+			break;
+	}
+
+	return ret_max;
+}
+
+static int _process_one_vg(struct cmd_context *cmd, const char *vg_name,
+			   const char *vgid,
+			   struct dm_list *tags, struct dm_list *arg_vgnames,
+			   uint32_t lock_type, int consistent, void *handle,
+			   int ret_max,
+			   int (*process_single) (struct cmd_context * cmd,
+						  const char *vg_name,
+						  struct volume_group * vg,
+						  int consistent, void *handle))
+{
+	struct volume_group *vg;
+	int ret = 0;
+
+	if (!lock_vol(cmd, vg_name, lock_type)) {
+		log_error("Can't lock volume group %s: skipping", vg_name);
+		return ret_max;
+	}
+
+	log_verbose("Finding volume group \"%s\"", vg_name);
+	if (!(vg = vg_read(cmd, vg_name, vgid, &consistent))) {
+		log_error("Volume group \"%s\" not found", vg_name);
+		unlock_vg(cmd, vg_name);
+		return ECMD_FAILED;
+	}
+
+	if (!vg_check_status(vg, CLUSTERED)) {
+		unlock_vg(cmd, vg_name);
+		return ECMD_FAILED;
+	}
+
+	if (!dm_list_empty(tags)) {
+		/* Only process if a tag matches or it's on arg_vgnames */
+		if (!str_list_match_item(arg_vgnames, vg_name) &&
+		    !str_list_match_list(tags, &vg->tags)) {
+			unlock_vg(cmd, vg_name);
+			return ret_max;
+		}
+	}
+
+	if ((ret = process_single(cmd, vg_name, vg, consistent,
+				  handle)) > ret_max) {
+		ret_max = ret;
+	}
+
+	unlock_vg(cmd, vg_name);
+
+	return ret_max;
+}
+
+int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
+		    uint32_t lock_type, int consistent, void *handle,
+		    int (*process_single) (struct cmd_context * cmd,
+					   const char *vg_name,
+					   struct volume_group * vg,
+					   int consistent, void *handle))
+{
+	int opt = 0;
+	int ret_max = ECMD_PROCESSED;
+
+	struct str_list *sl;
+	struct dm_list *vgnames, *vgids;
+	struct dm_list arg_vgnames, tags;
+
+	const char *vg_name, *vgid;
+
+	dm_list_init(&tags);
+	dm_list_init(&arg_vgnames);
+
+	if (argc) {
+		log_verbose("Using volume group(s) on command line");
+
+		for (; opt < argc; opt++) {
+			vg_name = argv[opt];
+			if (*vg_name == '@') {
+				if (!validate_name(vg_name + 1)) {
+					log_error("Skipping invalid tag %s",
+						  vg_name);
+					continue;
+				}
+				if (!str_list_add(cmd->mem, &tags,
+						  dm_pool_strdup(cmd->mem,
+							      vg_name + 1))) {
+					log_error("strlist allocation failed");
+					return ECMD_FAILED;
+				}
+				continue;
+			}
+
+			vg_name = skip_dev_dir(cmd, vg_name, NULL);
+			if (strchr(vg_name, '/')) {
+				log_error("Invalid volume group name: %s",
+					  vg_name);
+				continue;
+			}
+			if (!str_list_add(cmd->mem, &arg_vgnames,
+					  dm_pool_strdup(cmd->mem, vg_name))) {
+				log_error("strlist allocation failed");
+				return ECMD_FAILED;
+			}
+		}
+
+		vgnames = &arg_vgnames;
+	}
+
+	if (!argc || !dm_list_empty(&tags)) {
+		log_verbose("Finding all volume groups");
+		if (!(vgids = get_vgids(cmd, 0)) || dm_list_empty(vgids)) {
+			log_error("No volume groups found");
+			return ret_max;
+		}
+		dm_list_iterate_items(sl, vgids) {
+			vgid = sl->str;
+			if (!vgid || !(vg_name = vgname_from_vgid(cmd->mem, vgid)) ||
+			    is_orphan_vg(vg_name))
+				continue;
+			ret_max = _process_one_vg(cmd, vg_name, vgid, &tags,
+						  &arg_vgnames,
+					  	  lock_type, consistent, handle,
+					  	  ret_max, process_single);
+			if (sigint_caught())
+				return ret_max;
+		}
+	} else {
+		dm_list_iterate_items(sl, vgnames) {
+			vg_name = sl->str;
+			if (is_orphan_vg(vg_name))
+				continue;	/* FIXME Unnecessary? */
+			ret_max = _process_one_vg(cmd, vg_name, NULL, &tags,
+						  &arg_vgnames,
+					  	  lock_type, consistent, handle,
+					  	  ret_max, process_single);
+			if (sigint_caught())
+				return ret_max;
+		}
+	}
+
+	return ret_max;
+}
+
+int process_each_pv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
+			  const struct dm_list *tags, void *handle,
+			  process_single_pv_fn_t process_single)
+{
+	int ret_max = ECMD_PROCESSED;
+	int ret = 0;
+	struct pv_list *pvl;
+
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		if (tags && !dm_list_empty(tags) &&
+		    !str_list_match_list(tags, &pvl->pv->tags)) {
+			continue;
+		}
+		if ((ret = process_single(cmd, vg, pvl->pv, handle)) > ret_max)
+			ret_max = ret;
+		if (sigint_caught())
+			return ret_max;
+	}
+
+	return ret_max;
+}
+
+static int _process_all_devs(struct cmd_context *cmd, void *handle,
+		    int (*process_single) (struct cmd_context * cmd,
+					   struct volume_group * vg,
+					   struct physical_volume * pv,
+					   void *handle))
+{
+	struct physical_volume *pv;
+	struct physical_volume pv_dummy;
+	struct dev_iter *iter;
+	struct device *dev;
+
+	int ret_max = ECMD_PROCESSED;
+	int ret = 0;
+
+	if (!scan_vgs_for_pvs(cmd)) {
+		stack;
+		return ECMD_FAILED;
+	}
+
+	if (!(iter = dev_iter_create(cmd->filter, 1))) {
+		log_error("dev_iter creation failed");
+		return ECMD_FAILED;
+	}
+
+	while ((dev = dev_iter_get(iter))) {
+		if (!(pv = pv_read(cmd, dev_name(dev), NULL, NULL, 0))) {
+			memset(&pv_dummy, 0, sizeof(pv_dummy));
+			dm_list_init(&pv_dummy.tags);
+			dm_list_init(&pv_dummy.segments);
+			pv_dummy.dev = dev;
+			pv_dummy.fmt = NULL;
+			pv = &pv_dummy;
+		}
+		ret = process_single(cmd, NULL, pv, handle);
+		if (ret > ret_max)
+			ret_max = ret;
+		if (sigint_caught())
+			break;
+	}
+
+	dev_iter_destroy(iter);
+
+	return ret_max;
+}
+
+int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
+		    struct volume_group *vg, uint32_t lock_type, void *handle,
+		    int (*process_single) (struct cmd_context * cmd,
+					   struct volume_group * vg,
+					   struct physical_volume * pv,
+					   void *handle))
+{
+	int opt = 0;
+	int ret_max = ECMD_PROCESSED;
+	int ret = 0;
+
+	struct pv_list *pvl;
+	struct physical_volume *pv;
+	struct dm_list *pvslist, *vgnames;
+	struct dm_list tags;
+	struct str_list *sll;
+	char *tagname;
+	int consistent = 1;
+	int scanned = 0;
+
+	dm_list_init(&tags);
+
+	if (argc) {
+		log_verbose("Using physical volume(s) on command line");
+		for (; opt < argc; opt++) {
+			if (*argv[opt] == '@') {
+				tagname = argv[opt] + 1;
+
+				if (!validate_name(tagname)) {
+					log_error("Skipping invalid tag %s",
+						  tagname);
+					if (ret_max < EINVALID_CMD_LINE)
+						ret_max = EINVALID_CMD_LINE;
+					continue;
+				}
+				if (!str_list_add(cmd->mem, &tags,
+						  dm_pool_strdup(cmd->mem,
+							      tagname))) {
+					log_error("strlist allocation failed");
+					return ECMD_FAILED;
+				}
+				continue;
+			}
+			if (vg) {
+				if (!(pvl = find_pv_in_vg(vg, argv[opt]))) {
+					log_error("Physical Volume \"%s\" not "
+						  "found in Volume Group "
+						  "\"%s\"", argv[opt],
+						  vg->name);
+					ret_max = ECMD_FAILED;
+					continue;
+				}
+				pv = pvl->pv;
+			} else {
+				if (!(pv = pv_read(cmd, argv[opt], NULL,
+						   NULL, 1))) {
+					log_error("Failed to read physical "
+						  "volume \"%s\"", argv[opt]);
+					ret_max = ECMD_FAILED;
+					continue;
+				}
+
+				/*
+				 * If a PV has no MDAs it may appear to be an
+				 * orphan until the metadata is read off
+				 * another PV in the same VG.  Detecting this
+				 * means checking every VG by scanning every
+				 * PV on the system.
+				 */
+				if (!scanned && is_orphan(pv)) {
+					if (!scan_vgs_for_pvs(cmd)) {
+						stack;
+						ret_max = ECMD_FAILED;
+						continue;
+					}
+					scanned = 1;
+					if (!(pv = pv_read(cmd, argv[opt],
+							   NULL, NULL, 1))) {
+						log_error("Failed to read "
+							  "physical volume "
+							  "\"%s\"", argv[opt]);
+						ret_max = ECMD_FAILED;
+						continue;
+					}
+				}
+			}
+
+			ret = process_single(cmd, vg, pv, handle);
+			if (ret > ret_max)
+				ret_max = ret;
+			if (sigint_caught())
+				return ret_max;
+		}
+		if (!dm_list_empty(&tags) && (vgnames = get_vgs(cmd, 0)) &&
+			   !dm_list_empty(vgnames)) {
+			dm_list_iterate_items(sll, vgnames) {
+				if (!lock_vol(cmd, sll->str, lock_type)) {
+					log_error("Can't lock %s: skipping", sll->str);
+					continue;
+				}
+				if (!(vg = vg_read(cmd, sll->str, NULL, &consistent))) {
+					log_error("Volume group \"%s\" not found", sll->str);
+					unlock_vg(cmd, sll->str);
+					ret_max = ECMD_FAILED;
+					continue;
+				}
+				if (!consistent) {
+					unlock_vg(cmd, sll->str);
+					continue;
+				}
+
+				if (!vg_check_status(vg, CLUSTERED)) {
+					unlock_vg(cmd, sll->str);
+					continue;
+				}
+
+				ret = process_each_pv_in_vg(cmd, vg, &tags,
+							    handle,
+							    process_single);
+
+				unlock_vg(cmd, sll->str);
+
+				if (ret > ret_max)
+					ret_max = ret;
+				if (sigint_caught())
+					return ret_max;
+			}
+		}
+	} else {
+		if (vg) {
+			log_verbose("Using all physical volume(s) in "
+				    "volume group");
+			ret = process_each_pv_in_vg(cmd, vg, NULL, handle,
+						    process_single);
+			if (ret > ret_max)
+				ret_max = ret;
+			if (sigint_caught())
+				return ret_max;
+		} else if (arg_count(cmd, all_ARG)) {
+			ret = _process_all_devs(cmd, handle, process_single);
+			if (ret > ret_max)
+				ret_max = ret;
+			if (sigint_caught())
+				return ret_max;
+		} else {
+			log_verbose("Scanning for physical volume names");
+			if (!(pvslist = get_pvs(cmd)))
+				return ECMD_FAILED;
+
+			dm_list_iterate_items(pvl, pvslist) {
+				ret = process_single(cmd, NULL, pvl->pv,
+						     handle);
+				if (ret > ret_max)
+					ret_max = ret;
+				if (sigint_caught())
+					return ret_max;
+			}
+		}
+	}
+
+	return ret_max;
+}
+
+/*
+ * Determine volume group name from a logical volume name
+ */
+const char *extract_vgname(struct cmd_context *cmd, const char *lv_name)
+{
+	const char *vg_name = lv_name;
+	char *st;
+	char *dev_dir = cmd->dev_dir;
+	int dev_dir_provided = 0;
+
+	/* Path supplied? */
+	if (vg_name && strchr(vg_name, '/')) {
+		/* Strip dev_dir (optional) */
+		if (*vg_name == '/') {
+			while (*vg_name == '/')
+				vg_name++;
+			vg_name--;
+		}
+		if (!strncmp(vg_name, dev_dir, strlen(dev_dir))) {
+			vg_name += strlen(dev_dir);
+			dev_dir_provided = 1;
+			while (*vg_name == '/')
+				vg_name++;
+		}
+		if (*vg_name == '/') {
+			log_error("\"%s\": Invalid path for Logical "
+				  "Volume", lv_name);
+			return 0;
+		}
+
+		/* Require exactly one set of consecutive slashes */
+		if ((st = strchr(vg_name, '/')))
+			while (*st == '/')
+				st++;
+
+		if (!strchr(vg_name, '/') || strchr(st, '/')) {
+			log_error("\"%s\": Invalid path for Logical Volume",
+				  lv_name);
+			return 0;
+		}
+
+		vg_name = dm_pool_strdup(cmd->mem, vg_name);
+		if (!vg_name) {
+			log_error("Allocation of vg_name failed");
+			return 0;
+		}
+
+		*strchr(vg_name, '/') = '\0';
+		return vg_name;
+	}
+
+	if (!(vg_name = default_vgname(cmd))) {
+		if (lv_name)
+			log_error("Path required for Logical Volume \"%s\"",
+				  lv_name);
+		return 0;
+	}
+
+	return vg_name;
+}
+
+/*
+ * Extract default volume group name from environment
+ */
+char *default_vgname(struct cmd_context *cmd)
+{
+	char *vg_path;
+
+	/* Take default VG from environment? */
+	vg_path = getenv("LVM_VG_NAME");
+	if (!vg_path)
+		return 0;
+
+	vg_path = skip_dev_dir(cmd, vg_path, NULL);
+
+	if (strchr(vg_path, '/')) {
+		log_error("Environment Volume Group in LVM_VG_NAME invalid: "
+			  "\"%s\"", vg_path);
+		return 0;
+	}
+
+	return dm_pool_strdup(cmd->mem, vg_path);
+}
+
+/*
+ * Process physical extent range specifiers
+ */
+static int _add_pe_range(struct dm_pool *mem, const char *pvname,
+			 struct dm_list *pe_ranges, uint32_t start, uint32_t count)
+{
+	struct pe_range *per;
+
+	log_debug("Adding PE range: start PE %" PRIu32 " length %" PRIu32
+		  " on %s", start, count, pvname);
+
+	/* Ensure no overlap with existing areas */
+	dm_list_iterate_items(per, pe_ranges) {
+		if (((start < per->start) && (start + count - 1 >= per->start))
+		    || ((start >= per->start) &&
+			(per->start + per->count - 1) >= start)) {
+			log_error("Overlapping PE ranges specified (%" PRIu32
+				  "-%" PRIu32 ", %" PRIu32 "-%" PRIu32 ")"
+				  " on %s",
+				  start, start + count - 1, per->start,
+				  per->start + per->count - 1, pvname);
+			return 0;
+		}
+	}
+
+	if (!(per = dm_pool_alloc(mem, sizeof(*per)))) {
+		log_error("Allocation of list failed");
+		return 0;
+	}
+
+	per->start = start;
+	per->count = count;
+	dm_list_add(pe_ranges, &per->list);
+
+	return 1;
+}
+
+static int xstrtouint32(const char *s, char **p, int base, uint32_t *result)
+{
+	unsigned long ul;
+
+	errno = 0;
+	ul = strtoul(s, p, base);
+	if (errno || *p == s || (uint32_t) ul != ul)
+		return -1;
+	*result = ul;
+	return 0;
+}
+
+static int _parse_pes(struct dm_pool *mem, char *c, struct dm_list *pe_ranges,
+		      const char *pvname, uint32_t size)
+{
+	char *endptr;
+	uint32_t start, end;
+
+	/* Default to whole PV */
+	if (!c) {
+		if (!_add_pe_range(mem, pvname, pe_ranges, UINT32_C(0), size))
+			return_0;
+		return 1;
+	}
+
+	while (*c) {
+		if (*c != ':')
+			goto error;
+
+		c++;
+
+		/* Disallow :: and :\0 */
+		if (*c == ':' || !*c)
+			goto error;
+
+		/* Default to whole range */
+		start = UINT32_C(0);
+		end = size - 1;
+
+		/* Start extent given? */
+		if (isdigit(*c)) {
+			if (xstrtouint32(c, &endptr, 10, &start))
+				goto error;
+			c = endptr;
+			/* Just one number given? */
+			if (!*c || *c == ':')
+				end = start;
+		}
+		/* Range? */
+		if (*c == '-') {
+			c++;
+			if (isdigit(*c)) {
+				if (xstrtouint32(c, &endptr, 10, &end))
+					goto error;
+				c = endptr;
+			}
+		}
+		if (*c && *c != ':')
+			goto error;
+
+		if ((start > end) || (end > size - 1)) {
+			log_error("PE range error: start extent %" PRIu32 " to "
+				  "end extent %" PRIu32, start, end);
+			return 0;
+		}
+
+		if (!_add_pe_range(mem, pvname, pe_ranges, start, end - start + 1))
+			return_0;
+
+	}
+
+	return 1;
+
+      error:
+	log_error("Physical extent parsing error at %s", c);
+	return 0;
+}
+
+static int _create_pv_entry(struct dm_pool *mem, struct pv_list *pvl,
+			     char *colon, int allocatable_only, struct dm_list *r)
+{
+	const char *pvname;
+	struct pv_list *new_pvl = NULL, *pvl2;
+	struct dm_list *pe_ranges;
+
+	pvname = pv_dev_name(pvl->pv);
+	if (allocatable_only && !(pvl->pv->status & ALLOCATABLE_PV)) {
+		log_error("Physical volume %s not allocatable", pvname);
+		return 1;
+	}
+
+	if (allocatable_only &&
+	    (pvl->pv->pe_count == pvl->pv->pe_alloc_count)) {
+		log_err("No free extents on physical volume \"%s\"", pvname);
+		return 1;
+	}
+
+	dm_list_iterate_items(pvl2, r)
+		if (pvl->pv->dev == pvl2->pv->dev) {
+			new_pvl = pvl2;
+			break;
+		}
+	
+	if (!new_pvl) {
+		if (!(new_pvl = dm_pool_alloc(mem, sizeof(*new_pvl)))) {
+			log_err("Unable to allocate physical volume list.");
+			return 0;
+		}
+
+		memcpy(new_pvl, pvl, sizeof(*new_pvl));
+
+		if (!(pe_ranges = dm_pool_alloc(mem, sizeof(*pe_ranges)))) {
+			log_error("Allocation of pe_ranges list failed");
+			return 0;
+		}
+		dm_list_init(pe_ranges);
+		new_pvl->pe_ranges = pe_ranges;
+		dm_list_add(r, &new_pvl->list);
+	}
+
+	/* Determine selected physical extents */
+	if (!_parse_pes(mem, colon, new_pvl->pe_ranges, pv_dev_name(pvl->pv),
+			pvl->pv->pe_count))
+		return_0;
+
+	return 1;
+}
+
+struct dm_list *create_pv_list(struct dm_pool *mem, struct volume_group *vg, int argc,
+			    char **argv, int allocatable_only)
+{
+	struct dm_list *r;
+	struct pv_list *pvl;
+	struct dm_list tags, arg_pvnames;
+	const char *pvname = NULL;
+	char *colon, *tagname;
+	int i;
+
+	/* Build up list of PVs */
+	if (!(r = dm_pool_alloc(mem, sizeof(*r)))) {
+		log_error("Allocation of list failed");
+		return NULL;
+	}
+	dm_list_init(r);
+
+	dm_list_init(&tags);
+	dm_list_init(&arg_pvnames);
+
+	for (i = 0; i < argc; i++) {
+		if (*argv[i] == '@') {
+			tagname = argv[i] + 1;
+			if (!validate_name(tagname)) {
+				log_error("Skipping invalid tag %s", tagname);
+				continue;
+			}
+			dm_list_iterate_items(pvl, &vg->pvs) {
+				if (str_list_match_item(&pvl->pv->tags,
+							tagname)) {
+					if (!_create_pv_entry(mem, pvl, NULL,
+							      allocatable_only,
+							      r))
+						return_NULL;
+				}
+			}
+			continue;
+		}
+
+		pvname = argv[i];
+
+		if ((colon = strchr(pvname, ':'))) {
+			if (!(pvname = dm_pool_strndup(mem, pvname,
+						    (unsigned) (colon -
+								pvname)))) {
+				log_error("Failed to clone PV name");
+				return NULL;
+			}
+		}
+
+		if (!(pvl = find_pv_in_vg(vg, pvname))) {
+			log_err("Physical Volume \"%s\" not found in "
+				"Volume Group \"%s\"", pvname, vg->name);
+			return NULL;
+		}
+		if (!_create_pv_entry(mem, pvl, colon, allocatable_only, r))
+			return_NULL;
+	}
+
+	if (dm_list_empty(r))
+		log_error("No specified PVs have space available");
+
+	return dm_list_empty(r) ? NULL : r;
+}
+
+struct dm_list *clone_pv_list(struct dm_pool *mem, struct dm_list *pvsl)
+{
+	struct dm_list *r;
+	struct pv_list *pvl, *new_pvl;
+
+	/* Build up list of PVs */
+	if (!(r = dm_pool_alloc(mem, sizeof(*r)))) {
+		log_error("Allocation of list failed");
+		return NULL;
+	}
+	dm_list_init(r);
+
+	dm_list_iterate_items(pvl, pvsl) {
+		if (!(new_pvl = dm_pool_zalloc(mem, sizeof(*new_pvl)))) {
+			log_error("Unable to allocate physical volume list.");
+			return NULL;
+		}
+
+		memcpy(new_pvl, pvl, sizeof(*new_pvl));
+		dm_list_add(r, &new_pvl->list);
+	}
+
+	return r;
+}
+
+/*
+ * Attempt metadata recovery
+ */
+struct volume_group *recover_vg(struct cmd_context *cmd, const char *vgname,
+				uint32_t lock_type)
+{
+	int consistent = 1;
+
+	/* Don't attempt automatic recovery without proper locking */
+	if (lockingfailed())
+		return NULL;
+
+	lock_type &= ~LCK_TYPE_MASK;
+	lock_type |= LCK_WRITE;
+
+	if (!lock_vol(cmd, vgname, lock_type)) {
+		log_error("Can't lock %s for metadata recovery: skipping",
+			  vgname);
+		return NULL;
+	}
+
+	return vg_read(cmd, vgname, NULL, &consistent);
+}
+
+int apply_lvname_restrictions(const char *name)
+{
+	if (!strncmp(name, "snapshot", 8)) {
+		log_error("Names starting \"snapshot\" are reserved. "
+			  "Please choose a different LV name.");
+		return 0;
+	}
+
+	if (!strncmp(name, "pvmove", 6)) {
+		log_error("Names starting \"pvmove\" are reserved. "
+			  "Please choose a different LV name.");
+		return 0;
+	}
+
+	if (strstr(name, "_mlog")) {
+		log_error("Names including \"_mlog\" are reserved. "
+			  "Please choose a different LV name.");
+		return 0;
+	}
+
+	if (strstr(name, "_mimage")) {
+		log_error("Names including \"_mimage\" are reserved. "
+			  "Please choose a different LV name.");
+		return 0;
+	}
+
+	return 1;
+}
+
+int is_reserved_lvname(const char *name)
+{
+	int rc, old_suppress;
+
+	old_suppress = log_suppress(2);
+	rc = !apply_lvname_restrictions(name);
+	log_suppress(old_suppress);
+
+	return rc;
+}
+
+/*
+ * Set members of struct vgcreate_params from cmdline.
+ * Do preliminary validation with arg_*() interface.
+ * Further, more generic validation is done in validate_vgcreate_params().
+ * This function is to remain in tools directory.
+ */
+int fill_vg_create_params(struct cmd_context *cmd,
+			  char *vg_name, struct vgcreate_params *vp_new,
+			  struct vgcreate_params *vp_def)
+{
+	vp_new->vg_name = skip_dev_dir(cmd, vg_name, NULL);
+	vp_new->max_lv = arg_uint_value(cmd, maxlogicalvolumes_ARG,
+					vp_def->max_lv);
+	vp_new->max_pv = arg_uint_value(cmd, maxphysicalvolumes_ARG,
+					vp_def->max_pv);
+	vp_new->alloc = arg_uint_value(cmd, alloc_ARG, vp_def->alloc);
+
+	/* Units of 512-byte sectors */
+	vp_new->extent_size =
+	    arg_uint_value(cmd, physicalextentsize_ARG, vp_def->extent_size);
+
+	if (arg_count(cmd, clustered_ARG))
+		vp_new->clustered =
+			!strcmp(arg_str_value(cmd, clustered_ARG,
+					      vp_def->clustered ? "y":"n"), "y");
+	else
+		/* Default depends on current locking type */
+		vp_new->clustered = locking_is_clustered();
+
+	if (arg_sign_value(cmd, physicalextentsize_ARG, 0) == SIGN_MINUS) {
+		log_error("Physical extent size may not be negative");
+		return 1;
+	}
+
+	if (arg_sign_value(cmd, maxlogicalvolumes_ARG, 0) == SIGN_MINUS) {
+		log_error("Max Logical Volumes may not be negative");
+		return 1;
+	}
+
+	if (arg_sign_value(cmd, maxphysicalvolumes_ARG, 0) == SIGN_MINUS) {
+		log_error("Max Physical Volumes may not be negative");
+		return 1;
+	}
+
+	return 0;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/toollib.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/toollib.h
diff -N src/external/gpl2/lvm2tools/dist/tools/toollib.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/toollib.h	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,105 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. 
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_TOOLLIB_H
+#define _LVM_TOOLLIB_H
+
+#include "metadata-exported.h"
+
+int autobackup_set(void);
+int autobackup_init(const char *backup_dir, int keep_days, int keep_number,
+		    int autobackup);
+int autobackup(struct volume_group *vg);
+
+struct volume_group *recover_vg(struct cmd_context *cmd, const char *vgname,
+				uint32_t lock_type);
+
+int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
+		    uint32_t lock_type, int consistent, void *handle,
+		    int (*process_single) (struct cmd_context * cmd,
+					   const char *vg_name,
+					   struct volume_group * vg,
+					   int consistent, void *handle));
+
+int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
+		    struct volume_group *vg, uint32_t lock_type, void *handle,
+		    int (*process_single) (struct cmd_context * cmd,
+					   struct volume_group * vg,
+					   struct physical_volume * pv,
+					   void *handle));
+int process_each_segment_in_pv(struct cmd_context *cmd,
+			       struct volume_group *vg,
+			       struct physical_volume *pv,
+			       void *handle,
+			       int (*process_single) (struct cmd_context * cmd,
+						      struct volume_group * vg,
+						      struct pv_segment * pvseg,
+						      void *handle));
+
+int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
+		    uint32_t lock_type, void *handle,
+		    int (*process_single) (struct cmd_context * cmd,
+					   struct logical_volume * lv,
+					   void *handle));
+
+int process_each_segment_in_lv(struct cmd_context *cmd,
+			       struct logical_volume *lv, void *handle,
+			       int (*process_single) (struct cmd_context * cmd,
+						      struct lv_segment * seg,
+						      void *handle));
+
+typedef int (*process_single_pv_fn_t) (struct cmd_context *cmd,
+				  struct volume_group *vg,
+				  struct physical_volume *pv,
+				  void *handle);
+
+int process_each_pv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
+			  const struct dm_list *tags, void *handle,
+			  process_single_pv_fn_t process_single);
+
+typedef int (*process_single_lv_fn_t) (struct cmd_context *cmd,
+				  struct logical_volume *lv,
+				  void *handle);
+
+int process_each_lv_in_vg(struct cmd_context *cmd,
+			  const struct volume_group *vg,
+			  const struct dm_list *arg_lvnames,
+			  const struct dm_list *tags,
+			  void *handle,
+			  process_single_lv_fn_t process_single);
+
+char *default_vgname(struct cmd_context *cmd);
+const char *extract_vgname(struct cmd_context *cmd, const char *lv_name);
+char *skip_dev_dir(struct cmd_context *cmd, const char *vg_name,
+		   unsigned *dev_dir_found);
+
+/*
+ * Builds a list of pv's from the names in argv.  Used in
+ * lvcreate/extend.
+ */
+struct dm_list *create_pv_list(struct dm_pool *mem, struct volume_group *vg, int argc,
+			    char **argv, int allocatable_only);
+
+struct dm_list *clone_pv_list(struct dm_pool *mem, struct dm_list *pvs);
+
+int apply_lvname_restrictions(const char *name);
+int is_reserved_lvname(const char *name);
+
+int fill_vg_create_params(struct cmd_context *cmd,
+			  char *vg_name, struct vgcreate_params *vp_new,
+			  struct vgcreate_params *vp_def);
+#endif
Index: src/external/gpl2/lvm2tools/dist/tools/tools.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/tools.h
diff -N src/external/gpl2/lvm2tools/dist/tools/tools.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/tools.h	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,175 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_TOOLS_H
+#define _LVM_TOOLS_H
+
+#define _GNU_SOURCE
+#define _FILE_OFFSET_BITS 64
+
+#include <configure.h>
+#include <assert.h>
+#include <libdevmapper.h>
+
+#include "lvm-types.h"
+#include "lvm-logging.h"
+#include "activate.h"
+#include "archiver.h"
+#include "lvmcache.h"
+#include "config.h"
+#include "defaults.h"
+#include "dev-cache.h"
+#include "device.h"
+#include "display.h"
+#include "errors.h"
+#include "filter.h"
+#include "filter-composite.h"
+#include "filter-persistent.h"
+#include "filter-regex.h"
+#include "metadata-exported.h"
+#include "locking.h"
+#include "lvm-exec.h"
+#include "lvm-file.h"
+#include "lvm-string.h"
+#include "segtype.h"
+#include "str_list.h"
+#include "toolcontext.h"
+#include "toollib.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <sys/types.h>
+
+#define CMD_LEN 256
+#define MAX_ARGS 64
+
+/* command functions */
+typedef int (*command_fn) (struct cmd_context * cmd, int argc, char **argv);
+
+#define xx(a, b...) int a(struct cmd_context *cmd, int argc, char **argv);
+#include "commands.h"
+#undef xx
+
+/* define the enums for the command line switches */
+enum {
+#define arg(a, b, c, d, e) a ,
+#include "args.h"
+#undef arg
+};
+
+typedef enum {
+	SIGN_NONE = 0,
+	SIGN_PLUS = 1,
+	SIGN_MINUS = 2
+} sign_t;
+
+typedef enum {
+	PERCENT_NONE = 0,
+	PERCENT_VG,
+	PERCENT_FREE,
+	PERCENT_LV,
+	PERCENT_PVS
+} percent_t;
+
+enum {
+	CHANGE_AY = 0,
+	CHANGE_AN = 1,
+	CHANGE_AE = 2,
+	CHANGE_ALY = 3,
+	CHANGE_ALN = 4
+};
+
+#define ARG_REPEATABLE 0x00000001
+
+/* a global table of possible arguments */
+struct arg {
+	const char short_arg;
+	char _padding[7];
+	const char *long_arg;
+
+	int (*fn) (struct cmd_context * cmd, struct arg * a);
+	uint32_t flags;
+
+	unsigned count;
+	char *value;
+	int32_t i_value;
+	uint32_t ui_value;
+	int64_t i64_value;
+	uint64_t ui64_value;
+	sign_t sign;
+	percent_t percent;
+	void *ptr;
+};
+
+#define CACHE_VGMETADATA 0x00000001
+
+/* a register of the lvm commands */
+struct command {
+	const char *name;
+	const char *desc;
+	const char *usage;
+	command_fn fn;
+
+	unsigned flags;
+
+	int num_args;
+	int *valid_args;
+};
+
+void usage(const char *name);
+
+/* the argument verify/normalise functions */
+int yes_no_arg(struct cmd_context *cmd, struct arg *a);
+int yes_no_excl_arg(struct cmd_context *cmd, struct arg *a);
+int size_kb_arg(struct cmd_context *cmd, struct arg *a);
+int size_mb_arg(struct cmd_context *cmd, struct arg *a);
+int int_arg(struct cmd_context *cmd, struct arg *a);
+int int_arg_with_sign(struct cmd_context *cmd, struct arg *a);
+int int_arg_with_sign_and_percent(struct cmd_context *cmd, struct arg *a);
+int major_arg(struct cmd_context *cmd, struct arg *a);
+int minor_arg(struct cmd_context *cmd, struct arg *a);
+int string_arg(struct cmd_context *cmd, struct arg *a);
+int tag_arg(struct cmd_context *cmd, struct arg *a);
+int permission_arg(struct cmd_context *cmd, struct arg *a);
+int metadatatype_arg(struct cmd_context *cmd, struct arg *a);
+int units_arg(struct cmd_context *cmd, struct arg *a);
+int segtype_arg(struct cmd_context *cmd, struct arg *a);
+int alloc_arg(struct cmd_context *cmd, struct arg *a);
+int readahead_arg(struct cmd_context *cmd, struct arg *a);
+
+/* we use the enums to access the switches */
+unsigned int arg_count(const struct cmd_context *cmd, int a);
+const char *arg_value(struct cmd_context *cmd, int a);
+const char *arg_str_value(struct cmd_context *cmd, int a, const char *def);
+int32_t arg_int_value(struct cmd_context *cmd, int a, const int32_t def); 
+uint32_t arg_uint_value(struct cmd_context *cmd, int a, const uint32_t def);
+int64_t arg_int64_value(struct cmd_context *cmd, int a, const int64_t def);
+uint64_t arg_uint64_value(struct cmd_context *cmd, int a, const uint64_t def);
+const void *arg_ptr_value(struct cmd_context *cmd, int a, const void *def);
+sign_t arg_sign_value(struct cmd_context *cmd, int a, const sign_t def);
+percent_t arg_percent_value(struct cmd_context *cmd, int a, const percent_t def);
+int arg_count_increment(struct cmd_context *cmd, int a);
+
+const char *command_name(struct cmd_context *cmd);
+
+int pvmove_poll(struct cmd_context *cmd, const char *pv, unsigned background);
+int lvconvert_poll(struct cmd_context *cmd, const char *lv_name, unsigned background);
+
+#endif
Index: src/external/gpl2/lvm2tools/dist/tools/version.h.in
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/version.h.in
diff -N src/external/gpl2/lvm2tools/dist/tools/version.h.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/version.h.in	15 Jul 2008 13:50:26 -0000	1.1.1.1
@@ -0,0 +1,3 @@
+#ifndef _LVM_VERSION_H
+#define LVM_VERSION @LVM_VERSION@
+#endif
Index: src/external/gpl2/lvm2tools/dist/tools/vgcfgbackup.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/vgcfgbackup.c
diff -N src/external/gpl2/lvm2tools/dist/tools/vgcfgbackup.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/vgcfgbackup.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,111 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+static char *_expand_filename(const char *template, const char *vg_name,
+			      char **last_filename)
+{
+	char *filename;
+
+	if (security_level())
+		return dm_strdup(template);
+
+	if (!(filename = dm_malloc(PATH_MAX))) {
+		log_error("Failed to allocate filename.");
+		return NULL;
+	}
+
+	if (snprintf(filename, PATH_MAX, template, vg_name) < 0) {
+		log_error("Error processing filename template %s",
+			   template);
+		dm_free(filename);	
+		return NULL;
+	}
+	if (*last_filename && !strncmp(*last_filename, filename, PATH_MAX)) {
+		log_error("VGs must be backed up into different files. "
+			  "Use %%s in filename for VG name.");
+		dm_free(filename);
+		return NULL;
+	}
+
+	dm_free(*last_filename);
+	*last_filename = filename;
+
+	return filename;
+}
+
+static int vg_backup_single(struct cmd_context *cmd, const char *vg_name,
+			    struct volume_group *vg, int consistent,
+			    void *handle)
+{
+	char **last_filename = (char **)handle;
+	char *filename;
+
+	if (!vg) {
+		log_error("Volume group \"%s\" not found", vg_name);
+		return ECMD_FAILED;
+	}
+
+	if (!consistent)
+		log_error("WARNING: Volume group \"%s\" inconsistent", vg_name);
+
+	if (arg_count(cmd, file_ARG)) {
+		if (!(filename = _expand_filename(arg_value(cmd, file_ARG),
+						  vg->name, last_filename))) {
+			stack;
+			return ECMD_FAILED;
+		}
+
+		if (!backup_to_file(filename, vg->cmd->cmd_line, vg))
+			return ECMD_FAILED;
+	} else {
+		if (!consistent) {
+			log_error("No backup taken: specify filename with -f "
+				  "to backup an inconsistent VG");
+			stack;
+			return ECMD_FAILED;
+		}
+
+		/* just use the normal backup code */
+		backup_enable(cmd, 1);	/* force a backup */
+		if (!backup(vg)) {
+			stack;
+			return ECMD_FAILED;
+		}
+	}
+
+	log_print("Volume group \"%s\" successfully backed up.", vg_name);
+	return ECMD_PROCESSED;
+}
+
+int vgcfgbackup(struct cmd_context *cmd, int argc, char **argv)
+{
+	int ret;
+	char *last_filename = NULL;
+
+	init_pvmove(1);
+
+	ret = process_each_vg(cmd, argc, argv, LCK_VG_READ, 0, &last_filename,
+			      &vg_backup_single);
+
+	dm_free(last_filename);
+
+	init_pvmove(0);
+
+	return ret;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/vgcfgrestore.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/vgcfgrestore.c
diff -N src/external/gpl2/lvm2tools/dist/tools/vgcfgrestore.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/vgcfgrestore.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,74 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+int vgcfgrestore(struct cmd_context *cmd, int argc, char **argv)
+{
+	char *vg_name = NULL;
+
+	if (argc == 1) {
+		vg_name = skip_dev_dir(cmd, argv[0], NULL);
+		if (!validate_name(vg_name)) {
+			log_error("Volume group name \"%s\" is invalid", vg_name);
+			return ECMD_FAILED;
+		}
+	} else if (!(arg_count(cmd, list_ARG) && arg_count(cmd, file_ARG))) {
+		log_err("Please specify a *single* volume group to restore.");
+		return ECMD_FAILED;
+	}
+
+	/*
+	 * FIXME: overloading the -l arg for now to display a
+	 * list of archive files for a particular vg
+	 */
+	if (arg_count(cmd, list_ARG)) {
+		if (!(arg_count(cmd,file_ARG) ?
+			archive_display_file(cmd,
+					arg_str_value(cmd, file_ARG, "")) :
+			archive_display(cmd, vg_name)))
+			return ECMD_FAILED;
+		return ECMD_PROCESSED;
+	}
+
+	if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE)) {
+		log_error("Unable to lock orphans");
+		return ECMD_FAILED;
+	}
+
+	if (!lock_vol(cmd, vg_name, LCK_VG_WRITE | LCK_NONBLOCK)) {
+		log_error("Unable to lock volume group %s", vg_name);
+		unlock_vg(cmd, VG_ORPHANS);
+		return ECMD_FAILED;
+	}
+
+	if (!(arg_count(cmd, file_ARG) ?
+	      backup_restore_from_file(cmd, vg_name,
+				       arg_str_value(cmd, file_ARG, "")) :
+	      backup_restore(cmd, vg_name))) {
+		unlock_vg(cmd, vg_name);
+		unlock_vg(cmd, VG_ORPHANS);
+		log_err("Restore failed.");
+		return ECMD_FAILED;
+	}
+
+	log_print("Restored volume group %s", vg_name);
+
+	unlock_vg(cmd, vg_name);
+	unlock_vg(cmd, VG_ORPHANS);
+	return ECMD_PROCESSED;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/vgchange.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/vgchange.c
diff -N src/external/gpl2/lvm2tools/dist/tools/vgchange.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/vgchange.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,627 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+static int _monitor_lvs_in_vg(struct cmd_context *cmd,
+			       struct volume_group *vg, int reg)
+{
+	struct lv_list *lvl;
+	struct logical_volume *lv;
+	struct lvinfo info;
+	int lv_active;
+	int count = 0;
+
+	dm_list_iterate_items(lvl, &vg->lvs) {
+		lv = lvl->lv;
+
+		if (!lv_info(cmd, lv, &info, 0, 0))
+			lv_active = 0;
+		else
+			lv_active = info.exists;
+
+		/*
+		 * FIXME: Need to consider all cases... PVMOVE, etc
+		 */
+		if ((lv->status & PVMOVE) || !lv_active)
+			continue;
+
+		if (!monitor_dev_for_events(cmd, lv, reg)) {
+			continue;
+		} else
+			count++;
+	}
+
+	/*
+	 * returns the number of _new_ monitored devices
+	 */
+
+	return count;
+}
+
+static int _activate_lvs_in_vg(struct cmd_context *cmd,
+			       struct volume_group *vg, int activate)
+{
+	struct lv_list *lvl;
+	struct logical_volume *lv;
+	const char *pvname;
+	int count = 0;
+
+	dm_list_iterate_items(lvl, &vg->lvs) {
+		lv = lvl->lv;
+
+		/* Only request activation of snapshot origin devices */
+		if ((lv->status & SNAPSHOT) || lv_is_cow(lv))
+			continue;
+
+		/* Only request activation of mirror LV */
+		if ((lv->status & MIRROR_IMAGE) || (lv->status & MIRROR_LOG))
+			continue;
+
+		/* Can't deactivate a pvmove LV */
+		/* FIXME There needs to be a controlled way of doing this */
+		if (((activate == CHANGE_AN) || (activate == CHANGE_ALN)) &&
+		    ((lv->status & PVMOVE) ))
+			continue;
+
+		if (activate == CHANGE_AN) {
+			if (!deactivate_lv(cmd, lv))
+				continue;
+		} else if (activate == CHANGE_ALN) {
+			if (!deactivate_lv_local(cmd, lv))
+				continue;
+		} else if (lv_is_origin(lv) || (activate == CHANGE_AE)) {
+			if (!activate_lv_excl(cmd, lv))
+				continue;
+		} else if (activate == CHANGE_ALY) {
+			if (!activate_lv_local(cmd, lv))
+				continue;
+		} else if (!activate_lv(cmd, lv))
+			continue;
+
+		if ((lv->status & PVMOVE) &&
+		    (pvname = get_pvmove_pvname_from_lv_mirr(lv))) {
+			log_verbose("Spawning background process for %s %s",
+				    lv->name, pvname);
+			pvmove_poll(cmd, pvname, 1);
+			continue;
+		}
+
+		count++;
+	}
+
+	return count;
+}
+
+static int _vgchange_monitoring(struct cmd_context *cmd, struct volume_group *vg)
+{
+	int active, monitored;
+
+	if ((active = lvs_in_vg_activated(vg)) &&
+	    dmeventd_monitor_mode() != DMEVENTD_MONITOR_IGNORE) {
+		monitored = _monitor_lvs_in_vg(cmd, vg, dmeventd_monitor_mode());
+		log_print("%d logical volume(s) in volume group "
+			    "\"%s\" %smonitored",
+			    monitored, vg->name, (dmeventd_monitor_mode()) ? "" : "un");
+	}
+
+	return ECMD_PROCESSED;
+}
+
+static int _vgchange_available(struct cmd_context *cmd, struct volume_group *vg)
+{
+	int lv_open, active, monitored;
+	int available;
+	int activate = 1;
+
+	available = arg_uint_value(cmd, available_ARG, 0);
+
+	if ((available == CHANGE_AN) || (available == CHANGE_ALN))
+		activate = 0;
+
+	/* FIXME: Force argument to deactivate them? */
+	if (!activate && (lv_open = lvs_in_vg_opened(vg))) {
+		log_error("Can't deactivate volume group \"%s\" with %d open "
+			  "logical volume(s)", vg->name, lv_open);
+		return ECMD_FAILED;
+	}
+
+	if (activate && lockingfailed() && (vg_is_clustered(vg))) {
+		log_error("Locking inactive: ignoring clustered "
+			  "volume group %s", vg->name);
+		return ECMD_FAILED;
+	}
+
+	/* FIXME Move into library where clvmd can use it */
+	if (activate && !lockingfailed())
+		check_current_backup(vg);
+
+	if (activate && (active = lvs_in_vg_activated(vg))) {
+		log_verbose("%d logical volume(s) in volume group \"%s\" "
+			    "already active", active, vg->name);
+		if (dmeventd_monitor_mode() != DMEVENTD_MONITOR_IGNORE) {
+			monitored = _monitor_lvs_in_vg(cmd, vg, dmeventd_monitor_mode());
+			log_verbose("%d existing logical volume(s) in volume "
+				    "group \"%s\" %smonitored",
+				    monitored, vg->name,
+				    dmeventd_monitor_mode() ? "" : "un");
+		}
+	}
+
+	if (activate && _activate_lvs_in_vg(cmd, vg, available))
+		log_verbose("Activated logical volumes in "
+			    "volume group \"%s\"", vg->name);
+
+	if (!activate && _activate_lvs_in_vg(cmd, vg, available))
+		log_verbose("Deactivated logical volumes in "
+			    "volume group \"%s\"", vg->name);
+
+	log_print("%d logical volume(s) in volume group \"%s\" now active",
+		  lvs_in_vg_activated(vg), vg->name);
+	return ECMD_PROCESSED;
+}
+
+static int _vgchange_alloc(struct cmd_context *cmd, struct volume_group *vg)
+{
+	alloc_policy_t alloc;
+
+	alloc = arg_uint_value(cmd, alloc_ARG, ALLOC_NORMAL);
+
+	if (alloc == ALLOC_INHERIT) {
+		log_error("Volume Group allocation policy cannot inherit "
+			  "from anything");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (alloc == vg->alloc) {
+		log_error("Volume group allocation policy is already %s",
+			  get_alloc_string(vg->alloc));
+		return ECMD_FAILED;
+	}
+
+	if (!archive(vg))
+		return ECMD_FAILED;
+
+	vg->alloc = alloc;
+
+	if (!vg_write(vg) || !vg_commit(vg))
+		return ECMD_FAILED;
+
+	backup(vg);
+
+	log_print("Volume group \"%s\" successfully changed", vg->name);
+
+	return ECMD_PROCESSED;
+}
+
+static int _vgchange_resizeable(struct cmd_context *cmd,
+				struct volume_group *vg)
+{
+	int resizeable = !strcmp(arg_str_value(cmd, resizeable_ARG, "n"), "y");
+
+	if (resizeable && (vg_status(vg) & RESIZEABLE_VG)) {
+		log_error("Volume group \"%s\" is already resizeable",
+			  vg->name);
+		return ECMD_FAILED;
+	}
+
+	if (!resizeable && !(vg_status(vg) & RESIZEABLE_VG)) {
+		log_error("Volume group \"%s\" is already not resizeable",
+			  vg->name);
+		return ECMD_FAILED;
+	}
+
+	if (!archive(vg))
+		return ECMD_FAILED;
+
+	if (resizeable)
+		vg->status |= RESIZEABLE_VG;
+	else
+		vg->status &= ~RESIZEABLE_VG;
+
+	if (!vg_write(vg) || !vg_commit(vg))
+		return ECMD_FAILED;
+
+	backup(vg);
+
+	log_print("Volume group \"%s\" successfully changed", vg->name);
+
+	return ECMD_PROCESSED;
+}
+
+static int _vgchange_clustered(struct cmd_context *cmd,
+			       struct volume_group *vg)
+{
+	int clustered = !strcmp(arg_str_value(cmd, clustered_ARG, "n"), "y");
+	struct lv_list *lvl;
+
+	if (clustered && (vg_is_clustered(vg))) {
+		log_error("Volume group \"%s\" is already clustered",
+			  vg->name);
+		return ECMD_FAILED;
+	}
+
+	if (!clustered && !(vg_is_clustered(vg))) {
+		log_error("Volume group \"%s\" is already not clustered",
+			  vg->name);
+		return ECMD_FAILED;
+	}
+
+	if (clustered) {
+		dm_list_iterate_items(lvl, &vg->lvs) {
+			if (lv_is_origin(lvl->lv) || lv_is_cow(lvl->lv)) {
+				log_error("Volume group %s contains snapshots "
+					  "that are not yet supported.",
+					  vg->name);
+				return ECMD_FAILED;
+			}
+		}
+	}
+
+	if (!archive(vg))
+		return ECMD_FAILED;
+
+	if (clustered)
+		vg->status |= CLUSTERED;
+	else
+		vg->status &= ~CLUSTERED;
+
+	if (!vg_write(vg) || !vg_commit(vg))
+		return ECMD_FAILED;
+
+	backup(vg);
+
+	log_print("Volume group \"%s\" successfully changed", vg->name);
+
+	return ECMD_PROCESSED;
+}
+
+static int _vgchange_logicalvolume(struct cmd_context *cmd,
+				   struct volume_group *vg)
+{
+	uint32_t max_lv = arg_uint_value(cmd, logicalvolume_ARG, 0);
+
+	if (!(vg_status(vg) & RESIZEABLE_VG)) {
+		log_error("Volume group \"%s\" must be resizeable "
+			  "to change MaxLogicalVolume", vg->name);
+		return ECMD_FAILED;
+	}
+
+	if (!(vg->fid->fmt->features & FMT_UNLIMITED_VOLS)) {
+		if (!max_lv)
+			max_lv = 255;
+		else if (max_lv > 255) {
+			log_error("MaxLogicalVolume limit is 255");
+			return ECMD_FAILED;
+		}
+	}
+
+	if (max_lv && max_lv < vg->lv_count) {
+		log_error("MaxLogicalVolume is less than the current number "
+			  "%d of LVs for \"%s\"", vg->lv_count,
+			  vg->name);
+		return ECMD_FAILED;
+	}
+
+	if (!archive(vg))
+		return ECMD_FAILED;
+
+	vg->max_lv = max_lv;
+
+	if (!vg_write(vg) || !vg_commit(vg))
+		return ECMD_FAILED;
+
+	backup(vg);
+
+	log_print("Volume group \"%s\" successfully changed", vg->name);
+
+	return ECMD_PROCESSED;
+}
+
+static int _vgchange_physicalvolumes(struct cmd_context *cmd,
+				     struct volume_group *vg)
+{
+	uint32_t max_pv = arg_uint_value(cmd, maxphysicalvolumes_ARG, 0);
+
+	if (!(vg_status(vg) & RESIZEABLE_VG)) {
+		log_error("Volume group \"%s\" must be resizeable "
+			  "to change MaxPhysicalVolumes", vg->name);
+		return ECMD_FAILED;
+	}
+
+	if (arg_sign_value(cmd, maxphysicalvolumes_ARG, 0) == SIGN_MINUS) {
+		log_error("MaxPhysicalVolumes may not be negative");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (!(vg->fid->fmt->features & FMT_UNLIMITED_VOLS)) {
+		if (!max_pv)
+			max_pv = 255;
+		else if (max_pv > 255) {
+			log_error("MaxPhysicalVolume limit is 255");
+			return ECMD_FAILED;
+		}
+	}
+
+	if (max_pv && max_pv < vg->pv_count) {
+		log_error("MaxPhysicalVolumes is less than the current number "
+			  "%d of PVs for \"%s\"", vg->pv_count,
+			  vg->name);
+		return ECMD_FAILED;
+	}
+
+	if (!archive(vg))
+		return ECMD_FAILED;
+
+	vg->max_pv = max_pv;
+
+	if (!vg_write(vg) || !vg_commit(vg))
+		return ECMD_FAILED;
+
+	backup(vg);
+
+	log_print("Volume group \"%s\" successfully changed", vg->name);
+
+	return ECMD_PROCESSED;
+}
+
+static int _vgchange_pesize(struct cmd_context *cmd, struct volume_group *vg)
+{
+	uint32_t extent_size;
+
+	if (!(vg_status(vg) & RESIZEABLE_VG)) {
+		log_error("Volume group \"%s\" must be resizeable "
+			  "to change PE size", vg->name);
+		return ECMD_FAILED;
+	}
+
+	if (arg_sign_value(cmd, physicalextentsize_ARG, 0) == SIGN_MINUS) {
+		log_error("Physical extent size may not be negative");
+		return EINVALID_CMD_LINE;
+	}
+
+	extent_size = arg_uint_value(cmd, physicalextentsize_ARG, 0);
+	if (!extent_size) {
+		log_error("Physical extent size may not be zero");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (extent_size == vg->extent_size) {
+		log_error("Physical extent size of VG %s is already %s",
+			  vg->name, display_size(cmd, (uint64_t) extent_size));
+		return ECMD_PROCESSED;
+	}
+
+	if (extent_size & (extent_size - 1)) {
+		log_error("Physical extent size must be a power of 2.");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (extent_size > vg->extent_size) {
+		if ((uint64_t) vg->extent_size * vg->extent_count % extent_size) {
+			/* FIXME Adjust used PV sizes instead */
+			log_error("New extent size is not a perfect fit");
+			return EINVALID_CMD_LINE;
+		}
+	}
+
+	if (!archive(vg))
+		return ECMD_FAILED;
+
+	if (!vg_change_pesize(cmd, vg, extent_size)) {
+		stack;
+		return ECMD_FAILED;
+	}
+
+	if (!vg_write(vg) || !vg_commit(vg))
+		return ECMD_FAILED;
+
+	backup(vg);
+
+	log_print("Volume group \"%s\" successfully changed", vg->name);
+
+	return ECMD_PROCESSED;
+}
+
+static int _vgchange_tag(struct cmd_context *cmd, struct volume_group *vg,
+			 int arg)
+{
+	const char *tag;
+
+	if (!(tag = arg_str_value(cmd, arg, NULL))) {
+		log_error("Failed to get tag");
+		return ECMD_FAILED;
+	}
+
+	if (!(vg->fid->fmt->features & FMT_TAGS)) {
+		log_error("Volume group %s does not support tags", vg->name);
+		return ECMD_FAILED;
+	}
+
+	if (!archive(vg))
+		return ECMD_FAILED;
+
+	if ((arg == addtag_ARG)) {
+		if (!str_list_add(cmd->mem, &vg->tags, tag)) {
+			log_error("Failed to add tag %s to volume group %s",
+				  tag, vg->name);
+			return ECMD_FAILED;
+		}
+	} else {
+		if (!str_list_del(&vg->tags, tag)) {
+			log_error("Failed to remove tag %s from volume group "
+				  "%s", tag, vg->name);
+			return ECMD_FAILED;
+		}
+	}
+
+	if (!vg_write(vg) || !vg_commit(vg))
+		return ECMD_FAILED;
+
+	backup(vg);
+
+	log_print("Volume group \"%s\" successfully changed", vg->name);
+
+	return ECMD_PROCESSED;
+}
+
+static int _vgchange_uuid(struct cmd_context *cmd __attribute((unused)),
+			  struct volume_group *vg)
+{
+	struct lv_list *lvl;
+
+	if (lvs_in_vg_activated(vg)) {
+		log_error("Volume group has active logical volumes");
+		return ECMD_FAILED;
+	}
+
+	if (!archive(vg))
+		return ECMD_FAILED;
+
+	if (!id_create(&vg->id)) {
+		log_error("Failed to generate new random UUID for VG %s.",
+			  vg->name);
+		return ECMD_FAILED;
+	}
+
+	dm_list_iterate_items(lvl, &vg->lvs) {
+		memcpy(&lvl->lv->lvid, &vg->id, sizeof(vg->id));
+	}
+
+	if (!vg_write(vg) || !vg_commit(vg))
+		return ECMD_FAILED;
+
+	backup(vg);
+
+	log_print("Volume group \"%s\" successfully changed", vg->name);
+
+	return ECMD_PROCESSED;
+}
+
+static int vgchange_single(struct cmd_context *cmd, const char *vg_name,
+			   struct volume_group *vg, int consistent,
+			   void *handle __attribute((unused)))
+{
+	int r = ECMD_FAILED;
+
+	if (!vg) {
+		log_error("Unable to find volume group \"%s\"", vg_name);
+		return ECMD_FAILED;
+	}
+
+	if (!consistent) {
+		unlock_vg(cmd, vg_name);
+		dev_close_all();
+		log_error("Volume group \"%s\" inconsistent", vg_name);
+		if (!(vg = recover_vg(cmd, vg_name, LCK_VG_WRITE)))
+			return ECMD_FAILED;
+	}
+
+	if (!(vg_status(vg) & LVM_WRITE) && !arg_count(cmd, available_ARG)) {
+		log_error("Volume group \"%s\" is read-only", vg->name);
+		return ECMD_FAILED;
+	}
+
+	if (vg_status(vg) & EXPORTED_VG) {
+		log_error("Volume group \"%s\" is exported", vg_name);
+		return ECMD_FAILED;
+	}
+
+	init_dmeventd_monitor(arg_int_value(cmd, monitor_ARG,
+					    (cmd->is_static || arg_count(cmd, ignoremonitoring_ARG)) ?
+					    DMEVENTD_MONITOR_IGNORE : DEFAULT_DMEVENTD_MONITOR));
+
+	if (arg_count(cmd, available_ARG))
+		r = _vgchange_available(cmd, vg);
+
+	else if (arg_count(cmd, monitor_ARG))
+		r = _vgchange_monitoring(cmd, vg);
+
+	else if (arg_count(cmd, resizeable_ARG))
+		r = _vgchange_resizeable(cmd, vg);
+
+	else if (arg_count(cmd, logicalvolume_ARG))
+		r = _vgchange_logicalvolume(cmd, vg);
+
+	else if (arg_count(cmd, maxphysicalvolumes_ARG))
+		r = _vgchange_physicalvolumes(cmd, vg);
+
+	else if (arg_count(cmd, addtag_ARG))
+		r = _vgchange_tag(cmd, vg, addtag_ARG);
+
+	else if (arg_count(cmd, deltag_ARG))
+		r = _vgchange_tag(cmd, vg, deltag_ARG);
+
+	else if (arg_count(cmd, physicalextentsize_ARG))
+		r = _vgchange_pesize(cmd, vg);
+
+	else if (arg_count(cmd, uuid_ARG))
+		r = _vgchange_uuid(cmd, vg);
+
+	else if (arg_count(cmd, alloc_ARG))
+		r = _vgchange_alloc(cmd, vg);
+
+	else if (arg_count(cmd, clustered_ARG))
+		r = _vgchange_clustered(cmd, vg);
+
+	return r;
+}
+
+int vgchange(struct cmd_context *cmd, int argc, char **argv)
+{
+	if (!
+	    (arg_count(cmd, available_ARG) + arg_count(cmd, logicalvolume_ARG) +
+	     arg_count(cmd, maxphysicalvolumes_ARG) +
+	     arg_count(cmd, resizeable_ARG) + arg_count(cmd, deltag_ARG) +
+	     arg_count(cmd, addtag_ARG) + arg_count(cmd, uuid_ARG) +
+	     arg_count(cmd, physicalextentsize_ARG) +
+	     arg_count(cmd, clustered_ARG) + arg_count(cmd, alloc_ARG) +
+	     arg_count(cmd, monitor_ARG))) {
+		log_error("One of -a, -c, -l, -p, -s, -x, --uuid, --alloc, "
+			  "--addtag or --deltag required");
+		return EINVALID_CMD_LINE;
+	}
+
+	/* FIXME Cope with several changes at once! */
+	if (arg_count(cmd, available_ARG) + arg_count(cmd, logicalvolume_ARG) +
+	    arg_count(cmd, maxphysicalvolumes_ARG) +
+	    arg_count(cmd, resizeable_ARG) + arg_count(cmd, deltag_ARG) +
+	    arg_count(cmd, addtag_ARG) + arg_count(cmd, alloc_ARG) +
+	    arg_count(cmd, uuid_ARG) + arg_count(cmd, clustered_ARG) +
+	    arg_count(cmd, physicalextentsize_ARG) > 1) {
+		log_error("Only one of -a, -c, -l, -p, -s, -x, --uuid, "
+			  "--alloc, --addtag or --deltag allowed");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (arg_count(cmd, ignorelockingfailure_ARG) &&
+	    !arg_count(cmd, available_ARG)) {
+		log_error("--ignorelockingfailure only available with -a");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (arg_count(cmd, available_ARG) == 1
+	    && arg_count(cmd, autobackup_ARG)) {
+		log_error("-A option not necessary with -a option");
+		return EINVALID_CMD_LINE;
+	}
+
+	return process_each_vg(cmd, argc, argv,
+			       (arg_count(cmd, available_ARG)) ?
+			       LCK_VG_READ : LCK_VG_WRITE, 0, NULL,
+			       &vgchange_single);
+}
Index: src/external/gpl2/lvm2tools/dist/tools/vgck.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/vgck.c
diff -N src/external/gpl2/lvm2tools/dist/tools/vgck.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/vgck.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,45 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+static int vgck_single(struct cmd_context *cmd __attribute((unused)),
+		       const char *vg_name,
+		       struct volume_group *vg, int consistent,
+		       void *handle __attribute((unused)))
+{
+	if (!vg) {
+		log_error("Volume group \"%s\" not found", vg_name);
+		return ECMD_FAILED;
+	}
+
+	if (!consistent) {
+		log_error("Volume group \"%s\" inconsistent", vg_name);
+		return ECMD_FAILED;
+	}
+
+	if (!vg_check_status(vg, EXPORTED_VG))
+		return ECMD_FAILED;
+
+	return ECMD_PROCESSED;
+}
+
+int vgck(struct cmd_context *cmd, int argc, char **argv)
+{
+	return process_each_vg(cmd, argc, argv, LCK_VG_READ, 0, NULL,
+			       &vgck_single);
+}
Index: src/external/gpl2/lvm2tools/dist/tools/vgconvert.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/vgconvert.c
diff -N src/external/gpl2/lvm2tools/dist/tools/vgconvert.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/vgconvert.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,240 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+static int vgconvert_single(struct cmd_context *cmd, const char *vg_name,
+			    struct volume_group *vg, int consistent,
+			    void *handle __attribute((unused)))
+{
+	struct physical_volume *pv, *existing_pv;
+	struct logical_volume *lv;
+	struct lv_list *lvl;
+	uint64_t size = 0;
+	struct dm_list mdas;
+	int pvmetadatacopies = 0;
+	uint64_t pvmetadatasize = 0;
+	uint64_t pe_end = 0, pe_start = 0;
+	struct pv_list *pvl;
+	int change_made = 0;
+	struct lvinfo info;
+	int active = 0;
+
+	if (!vg) {
+		log_error("Unable to find volume group \"%s\"", vg_name);
+		return ECMD_FAILED;
+	}
+
+	if (!consistent) {
+		unlock_vg(cmd, vg_name);
+		dev_close_all();
+		log_error("Volume group \"%s\" inconsistent", vg_name);
+		if (!(vg = recover_vg(cmd, vg_name, LCK_VG_WRITE)))
+			return ECMD_FAILED;
+	}
+
+	if (!vg_check_status(vg, LVM_WRITE | EXPORTED_VG))
+		return ECMD_FAILED;
+
+	if (vg->fid->fmt == cmd->fmt) {
+		log_error("Volume group \"%s\" already uses format %s",
+			  vg_name, cmd->fmt->name);
+		return ECMD_FAILED;
+	}
+
+	if (cmd->fmt->features & FMT_MDAS) {
+		if (arg_sign_value(cmd, metadatasize_ARG, 0) == SIGN_MINUS) {
+			log_error("Metadata size may not be negative");
+			return EINVALID_CMD_LINE;
+		}
+
+		pvmetadatasize = arg_uint64_value(cmd, metadatasize_ARG,
+						  UINT64_C(0));
+		if (!pvmetadatasize)
+			pvmetadatasize =
+			    find_config_tree_int(cmd,
+					    "metadata/pvmetadatasize",
+					    DEFAULT_PVMETADATASIZE);
+
+		pvmetadatacopies = arg_int_value(cmd, metadatacopies_ARG, -1);
+		if (pvmetadatacopies < 0)
+			pvmetadatacopies =
+			    find_config_tree_int(cmd,
+					    "metadata/pvmetadatacopies",
+					     DEFAULT_PVMETADATACOPIES);
+	}
+
+	if (!archive(vg)) {
+		log_error("Archive of \"%s\" metadata failed.", vg_name);
+		return ECMD_FAILED;
+	}
+
+	/* Set PV/LV limit if converting from unlimited metadata format */
+	if (vg->fid->fmt->features & FMT_UNLIMITED_VOLS &&
+	    !(cmd->fmt->features & FMT_UNLIMITED_VOLS)) {
+		if (!vg->max_lv)
+			vg->max_lv = 255;
+		if (!vg->max_pv)
+			vg->max_pv = 255;
+	}
+
+	/* If converting to restricted lvid, check if lvid is compatible */
+	if (!(vg->fid->fmt->features & FMT_RESTRICTED_LVIDS) &&
+	    cmd->fmt->features & FMT_RESTRICTED_LVIDS)
+		dm_list_iterate_items(lvl, &vg->lvs)
+			if (!lvid_in_restricted_range(&lvl->lv->lvid)) {
+				log_error("Logical volume %s lvid format is"
+					  " incompatible with requested"
+					  " metadata format.", lvl->lv->name);
+				return ECMD_FAILED;
+			}
+
+	/* Attempt to change any LVIDs that are too big */
+	if (cmd->fmt->features & FMT_RESTRICTED_LVIDS) {
+		dm_list_iterate_items(lvl, &vg->lvs) {
+			lv = lvl->lv;
+			if (lv->status & SNAPSHOT)
+				continue;
+			if (lvnum_from_lvid(&lv->lvid) < MAX_RESTRICTED_LVS)
+				continue;
+			if (lv_info(cmd, lv, &info, 0, 0) && info.exists) {
+				log_error("Logical volume %s must be "
+					  "deactivated before conversion.",
+					   lv->name);
+				active++;
+				continue;
+			}
+			lvid_from_lvnum(&lv->lvid, &lv->vg->id, find_free_lvnum(lv));
+
+		}
+	}
+
+	if (active)
+		return ECMD_FAILED;
+
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		existing_pv = pvl->pv;
+
+		pe_start = pv_pe_start(existing_pv);
+		pe_end = pv_pe_count(existing_pv) * pv_pe_size(existing_pv)
+		    + pe_start - 1;
+
+		dm_list_init(&mdas);
+		if (!(pv = pv_create(cmd, pv_dev(existing_pv),
+				     &existing_pv->id, size,
+				     pe_start, pv_pe_count(existing_pv),
+				     pv_pe_size(existing_pv), pvmetadatacopies,
+				     pvmetadatasize, &mdas))) {
+			log_error("Failed to setup physical volume \"%s\"",
+				  pv_dev_name(existing_pv));
+			if (change_made)
+				log_error("Use pvcreate and vgcfgrestore to "
+					  "repair from archived metadata.");
+			return ECMD_FAILED;
+		}
+
+		/* Need to revert manually if it fails after this point */
+		change_made = 1;
+
+		log_verbose("Set up physical volume for \"%s\" with %" PRIu64
+			    " available sectors", pv_dev_name(pv), pv_size(pv));
+
+		/* Wipe existing label first */
+		if (!label_remove(pv_dev(pv))) {
+			log_error("Failed to wipe existing label on %s",
+				  pv_dev_name(pv));
+			log_error("Use pvcreate and vgcfgrestore to repair "
+				  "from archived metadata.");
+			return ECMD_FAILED;
+		}
+
+		log_very_verbose("Writing physical volume data to disk \"%s\"",
+				 pv_dev_name(pv));
+		if (!(pv_write(cmd, pv, &mdas,
+			       arg_int64_value(cmd, labelsector_ARG,
+					       DEFAULT_LABELSECTOR)))) {
+			log_error("Failed to write physical volume \"%s\"",
+				  pv_dev_name(pv));
+			log_error("Use pvcreate and vgcfgrestore to repair "
+				  "from archived metadata.");
+			return ECMD_FAILED;
+		}
+		log_verbose("Physical volume \"%s\" successfully created",
+			    pv_dev_name(pv));
+
+	}
+
+	log_verbose("Deleting existing metadata for VG %s", vg_name);
+	if (!vg_remove(vg)) {
+		log_error("Removal of existing metadata for %s failed.",
+			  vg_name);
+		log_error("Use pvcreate and vgcfgrestore to repair "
+			  "from archived metadata.");
+		return ECMD_FAILED;
+	}
+
+	/* FIXME Cache the label format change so we don't have to skip this */
+	if (test_mode()) {
+		log_verbose("Test mode: Skipping metadata writing for VG %s in"
+			    " format %s", vg_name, cmd->fmt->name);
+		return ECMD_PROCESSED;
+	}
+
+	log_verbose("Writing metadata for VG %s using format %s", vg_name,
+		    cmd->fmt->name);
+	if (!backup_restore_vg(cmd, vg)) {
+		log_error("Conversion failed for volume group %s.", vg_name);
+		log_error("Use pvcreate and vgcfgrestore to repair from "
+			  "archived metadata.");
+		return ECMD_FAILED;
+	}
+	log_print("Volume group %s successfully converted", vg_name);
+
+	backup(vg);
+
+	return ECMD_PROCESSED;
+}
+
+int vgconvert(struct cmd_context *cmd, int argc, char **argv)
+{
+	if (!argc) {
+		log_error("Please enter volume group(s)");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (arg_int_value(cmd, labelsector_ARG, 0) >= LABEL_SCAN_SECTORS) {
+		log_error("labelsector must be less than %lu",
+			  LABEL_SCAN_SECTORS);
+		return EINVALID_CMD_LINE;
+	}
+
+	if (!(cmd->fmt->features & FMT_MDAS) &&
+	    (arg_count(cmd, metadatacopies_ARG) ||
+	     arg_count(cmd, metadatasize_ARG))) {
+		log_error("Metadata parameters only apply to text format");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (arg_count(cmd, metadatacopies_ARG) &&
+	    arg_int_value(cmd, metadatacopies_ARG, -1) > 2) {
+		log_error("Metadatacopies may only be 0, 1 or 2");
+		return EINVALID_CMD_LINE;
+	}
+
+	return process_each_vg(cmd, argc, argv, LCK_VG_WRITE, 0, NULL,
+			       &vgconvert_single);
+}
Index: src/external/gpl2/lvm2tools/dist/tools/vgcreate.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/vgcreate.c
diff -N src/external/gpl2/lvm2tools/dist/tools/vgcreate.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/vgcreate.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,126 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+int vgcreate(struct cmd_context *cmd, int argc, char **argv)
+{
+	struct vgcreate_params vp_new;
+	struct vgcreate_params vp_def;
+	struct volume_group *vg;
+	const char *tag;
+	const char *clustered_message = "";
+
+	if (!argc) {
+		log_error("Please provide volume group name and "
+			  "physical volumes");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (argc == 1) {
+		log_error("Please enter physical volume name(s)");
+		return EINVALID_CMD_LINE;
+	}
+
+	vp_def.vg_name = NULL;
+	vp_def.extent_size = DEFAULT_EXTENT_SIZE * 2;
+	vp_def.max_pv = 0;
+	vp_def.max_lv = 0;
+	vp_def.alloc = ALLOC_NORMAL;
+	vp_def.clustered = 0;
+	if (fill_vg_create_params(cmd, argv[0], &vp_new, &vp_def))
+		return EINVALID_CMD_LINE;
+
+	if (validate_vg_create_params(cmd, &vp_new))
+	    return EINVALID_CMD_LINE;
+
+	/* Create the new VG */
+	if (!(vg = vg_create(cmd, vp_new.vg_name, vp_new.extent_size,
+			     vp_new.max_pv, vp_new.max_lv, vp_new.alloc,
+			     argc - 1, argv + 1)))
+		return ECMD_FAILED;
+
+	if (vp_new.max_lv != vg->max_lv)
+		log_warn("WARNING: Setting maxlogicalvolumes to %d "
+			 "(0 means unlimited)", vg->max_lv);
+
+	if (vp_new.max_pv != vg->max_pv)
+		log_warn("WARNING: Setting maxphysicalvolumes to %d "
+			 "(0 means unlimited)", vg->max_pv);
+
+	if (arg_count(cmd, addtag_ARG)) {
+		if (!(tag = arg_str_value(cmd, addtag_ARG, NULL))) {
+			log_error("Failed to get tag");
+			return ECMD_FAILED;
+		}
+
+		if (!(vg->fid->fmt->features & FMT_TAGS)) {
+			log_error("Volume group format does not support tags");
+			return ECMD_FAILED;
+		}
+
+		if (!str_list_add(cmd->mem, &vg->tags, tag)) {
+			log_error("Failed to add tag %s to volume group %s",
+				  tag, vp_new.vg_name);
+			return ECMD_FAILED;
+		}
+	}
+
+	/* FIXME: move this inside vg_create? */
+	if (vp_new.clustered) {
+		vg->status |= CLUSTERED;
+		clustered_message = "Clustered ";
+	} else {
+		vg->status &= ~CLUSTERED;
+		if (locking_is_clustered())
+			clustered_message = "Non-clustered ";
+	}
+
+	if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE)) {
+		log_error("Can't get lock for orphan PVs");
+		return ECMD_FAILED;
+	}
+
+	if (!lock_vol(cmd, vp_new.vg_name, LCK_VG_WRITE | LCK_NONBLOCK)) {
+		log_error("Can't get lock for %s", vp_new.vg_name);
+		unlock_vg(cmd, VG_ORPHANS);
+		return ECMD_FAILED;
+	}
+
+	if (!archive(vg)) {
+		unlock_vg(cmd, vp_new.vg_name);
+		unlock_vg(cmd, VG_ORPHANS);
+		return ECMD_FAILED;
+	}
+
+	/* Store VG on disk(s) */
+	if (!vg_write(vg) || !vg_commit(vg)) {
+		unlock_vg(cmd, vp_new.vg_name);
+		unlock_vg(cmd, VG_ORPHANS);
+		return ECMD_FAILED;
+	}
+
+	unlock_vg(cmd, vp_new.vg_name);
+	unlock_vg(cmd, VG_ORPHANS);
+
+	backup(vg);
+
+	log_print("%s%colume group \"%s\" successfully created",
+		  clustered_message, *clustered_message ? 'v' : 'V', vg->name);
+
+	return ECMD_PROCESSED;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/vgdisplay.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/vgdisplay.c
diff -N src/external/gpl2/lvm2tools/dist/tools/vgdisplay.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/vgdisplay.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,117 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+static int vgdisplay_single(struct cmd_context *cmd, const char *vg_name,
+			    struct volume_group *vg, int consistent,
+			    void *handle __attribute((unused)))
+{
+	/* FIXME Do the active check here if activevolumegroups_ARG ? */
+	if (!vg) {
+		log_error("Volume group \"%s\" doesn't exist", vg_name);
+		return ECMD_FAILED;
+	}
+
+	if (!consistent)
+		log_error("WARNING: Volume group \"%s\" inconsistent", vg_name);
+
+	vg_check_status(vg, EXPORTED_VG);
+
+	if (arg_count(cmd, colon_ARG)) {
+		vgdisplay_colons(vg);
+		return ECMD_PROCESSED;
+	}
+
+	if (arg_count(cmd, short_ARG)) {
+		vgdisplay_short(vg);
+		return ECMD_PROCESSED;
+	}
+
+	vgdisplay_full(vg);	/* was vg_show */
+
+	if (arg_count(cmd, verbose_ARG)) {
+		vgdisplay_extents(vg);
+
+		process_each_lv_in_vg(cmd, vg, NULL, NULL, NULL,
+				      (process_single_lv_fn_t)lvdisplay_full);
+
+		log_print("--- Physical volumes ---");
+		process_each_pv_in_vg(cmd, vg, NULL, NULL,
+				      (process_single_pv_fn_t)pvdisplay_short);
+	}
+
+	check_current_backup(vg);
+
+	return ECMD_PROCESSED;
+}
+
+int vgdisplay(struct cmd_context *cmd, int argc, char **argv)
+{
+	if (arg_count(cmd, columns_ARG)) {
+		if (arg_count(cmd, colon_ARG) ||
+		    arg_count(cmd, activevolumegroups_ARG) ||
+		    arg_count(cmd, short_ARG)) {
+			log_error("Incompatible options selected");
+			return EINVALID_CMD_LINE;
+		}
+		return vgs(cmd, argc, argv);
+	} else if (arg_count(cmd, aligned_ARG) ||
+		   arg_count(cmd, noheadings_ARG) ||
+		   arg_count(cmd, options_ARG) ||
+		   arg_count(cmd, separator_ARG) ||
+		   arg_count(cmd, sort_ARG) || arg_count(cmd, unbuffered_ARG)) {
+		log_error("Incompatible options selected");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (arg_count(cmd, colon_ARG) && arg_count(cmd, short_ARG)) {
+		log_error("Option -c is not allowed with option -s");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (argc && arg_count(cmd, activevolumegroups_ARG)) {
+		log_error("Option -A is not allowed with volume group names");
+		return EINVALID_CMD_LINE;
+	}
+
+	/* FIXME -D disk_ARG is now redundant */
+
+/********* FIXME: Do without this - or else 2(+) passes!
+	   Figure out longest volume group name
+	for (c = opt; opt < argc; opt++) {
+		len = strlen(argv[opt]);
+		if (len > max_len)
+			max_len = len;
+	}
+**********/
+
+	return process_each_vg(cmd, argc, argv, LCK_VG_READ, 0, NULL,
+			       vgdisplay_single);
+
+/******** FIXME Need to count number processed
+	  Add this to process_each_vg if arg_count(cmd,activevolumegroups_ARG) ?
+
+	if (opt == argc) {
+		log_print("no ");
+		if (arg_count(cmd,activevolumegroups_ARG))
+			printf("active ");
+		printf("volume groups found\n\n");
+		return LVM_E_NO_VG;
+	}
+************/
+}
Index: src/external/gpl2/lvm2tools/dist/tools/vgexport.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/vgexport.c
diff -N src/external/gpl2/lvm2tools/dist/tools/vgexport.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/vgexport.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,85 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+static int vgexport_single(struct cmd_context *cmd __attribute((unused)),
+			   const char *vg_name,
+			   struct volume_group *vg, int consistent,
+			   void *handle __attribute((unused)))
+{
+	struct pv_list *pvl;
+	struct physical_volume *pv;
+
+	if (!vg) {
+		log_error("Unable to find volume group \"%s\"", vg_name);
+		goto error;
+	}
+
+	if (!consistent) {
+		log_error("Volume group %s inconsistent", vg_name);
+		goto error;
+	}
+
+	if (!vg_check_status(vg, EXPORTED_VG | LVM_WRITE)) {
+		goto error;
+	}
+
+	if (lvs_in_vg_activated(vg)) {
+		log_error("Volume group \"%s\" has active logical volumes",
+			  vg_name);
+		goto error;
+	}
+
+	if (!archive(vg))
+		goto error;
+
+	vg->status |= EXPORTED_VG;
+
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		pv = pvl->pv;
+		pv->status |= EXPORTED_VG;
+	}
+
+	if (!vg_write(vg) || !vg_commit(vg))
+		goto error;
+
+	backup(vg);
+
+	log_print("Volume group \"%s\" successfully exported", vg->name);
+
+	return ECMD_PROCESSED;
+
+      error:
+	return ECMD_FAILED;
+}
+
+int vgexport(struct cmd_context *cmd, int argc, char **argv)
+{
+	if (!argc && !arg_count(cmd, all_ARG)) {
+		log_error("Please supply volume groups or use -a for all.");
+		return ECMD_FAILED;
+	}
+
+	if (argc && arg_count(cmd, all_ARG)) {
+		log_error("No arguments permitted when using -a for all.");
+		return ECMD_FAILED;
+	}
+
+	return process_each_vg(cmd, argc, argv, LCK_VG_WRITE, 1, NULL,
+			       &vgexport_single);
+}
Index: src/external/gpl2/lvm2tools/dist/tools/vgextend.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/vgextend.c
diff -N src/external/gpl2/lvm2tools/dist/tools/vgextend.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/vgextend.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,88 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+int vgextend(struct cmd_context *cmd, int argc, char **argv)
+{
+	char *vg_name;
+	struct volume_group *vg = NULL;
+
+	if (!argc) {
+		log_error("Please enter volume group name and "
+			  "physical volume(s)");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (argc == 1) {
+		log_error("Please enter physical volume(s)");
+		return EINVALID_CMD_LINE;
+	}
+
+	vg_name = skip_dev_dir(cmd, argv[0], NULL);
+	argc--;
+	argv++;
+
+	if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE)) {
+		log_error("Can't get lock for orphan PVs");
+		return ECMD_FAILED;
+	}
+
+	log_verbose("Checking for volume group \"%s\"", vg_name);
+	if (!(vg = vg_lock_and_read(cmd, vg_name, NULL, LCK_VG_WRITE | LCK_NONBLOCK,
+				    CLUSTERED | EXPORTED_VG |
+				    LVM_WRITE | RESIZEABLE_VG,
+				    CORRECT_INCONSISTENT | FAIL_INCONSISTENT))) {
+		 unlock_vg(cmd, VG_ORPHANS);
+		return ECMD_FAILED;
+	 }
+/********** FIXME
+	log_print("maximum logical volume size is %s",
+		  (dummy = lvm_show_size(LVM_LV_SIZE_MAX(vg) / 2, LONG)));
+	dm_free(dummy);
+	dummy = NULL;
+**********/
+
+	if (!archive(vg))
+		goto error;
+
+	/* extend vg */
+	if (!vg_extend(vg, argc, argv))
+		goto error;
+
+	/* ret > 0 */
+	log_verbose("Volume group \"%s\" will be extended by %d new "
+		    "physical volumes", vg_name, argc);
+
+	/* store vg on disk(s) */
+	if (!vg_write(vg) || !vg_commit(vg))
+		goto error;
+
+	backup(vg);
+
+	unlock_vg(cmd, vg_name);
+	unlock_vg(cmd, VG_ORPHANS);
+
+	log_print("Volume group \"%s\" successfully extended", vg_name);
+
+	return ECMD_PROCESSED;
+
+      error:
+	unlock_vg(cmd, vg_name);
+	unlock_vg(cmd, VG_ORPHANS);
+	return ECMD_FAILED;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/vgimport.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/vgimport.c
diff -N src/external/gpl2/lvm2tools/dist/tools/vgimport.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/vgimport.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,81 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+static int vgimport_single(struct cmd_context *cmd __attribute((unused)),
+			   const char *vg_name,
+			   struct volume_group *vg, int consistent,
+			   void *handle __attribute((unused)))
+{
+	struct pv_list *pvl;
+	struct physical_volume *pv;
+
+	if (!vg || !consistent) {
+		log_error("Unable to find exported volume group \"%s\"",
+			  vg_name);
+		goto error;
+	}
+
+	if (!(vg_status(vg) & EXPORTED_VG)) {
+		log_error("Volume group \"%s\" is not exported", vg_name);
+		goto error;
+	}
+
+	if (vg_status(vg) & PARTIAL_VG) {
+		log_error("Volume group \"%s\" is partially missing", vg_name);
+		goto error;
+	}
+
+	if (!archive(vg))
+		goto error;
+
+	vg->status &= ~EXPORTED_VG;
+
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		pv = pvl->pv;
+		pv->status &= ~EXPORTED_VG;
+	}
+
+	if (!vg_write(vg) || !vg_commit(vg))
+		goto error;
+
+	backup(vg);
+
+	log_print("Volume group \"%s\" successfully imported", vg->name);
+
+	return ECMD_PROCESSED;
+
+      error:
+	return ECMD_FAILED;
+}
+
+int vgimport(struct cmd_context *cmd, int argc, char **argv)
+{
+	if (!argc && !arg_count(cmd, all_ARG)) {
+		log_error("Please supply volume groups or use -a for all.");
+		return ECMD_FAILED;
+	}
+
+	if (argc && arg_count(cmd, all_ARG)) {
+		log_error("No arguments permitted when using -a for all.");
+		return ECMD_FAILED;
+	}
+
+	return process_each_vg(cmd, argc, argv, LCK_VG_WRITE, 1, NULL,
+			       &vgimport_single);
+}
Index: src/external/gpl2/lvm2tools/dist/tools/vgmerge.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/vgmerge.c
diff -N src/external/gpl2/lvm2tools/dist/tools/vgmerge.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/vgmerge.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,157 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
+			   const char *vg_name_from)
+{
+	struct volume_group *vg_to, *vg_from;
+	struct lv_list *lvl1, *lvl2;
+
+	if (!strcmp(vg_name_to, vg_name_from)) {
+		log_error("Duplicate volume group name \"%s\"", vg_name_from);
+		return ECMD_FAILED;
+	}
+
+	log_verbose("Checking for volume group \"%s\"", vg_name_to);
+	if (!(vg_to = vg_lock_and_read(cmd, vg_name_to, NULL, LCK_VG_WRITE,
+				       CLUSTERED | EXPORTED_VG | LVM_WRITE,
+				       CORRECT_INCONSISTENT | FAIL_INCONSISTENT)))
+		 return ECMD_FAILED;
+
+	log_verbose("Checking for volume group \"%s\"", vg_name_from);
+	if (!(vg_from = vg_lock_and_read(cmd, vg_name_from, NULL,
+					 LCK_VG_WRITE | LCK_NONBLOCK,
+					 CLUSTERED | EXPORTED_VG | LVM_WRITE,
+					 CORRECT_INCONSISTENT | FAIL_INCONSISTENT))) {
+		unlock_vg(cmd, vg_name_to);
+		return ECMD_FAILED;
+	}
+
+	if (!vgs_are_compatible(cmd, vg_from, vg_to))
+		goto_bad;
+
+	/* FIXME List arg: vg_show_with_pv_and_lv(vg_to); */
+
+	if (!archive(vg_from) || !archive(vg_to))
+		goto_bad;
+
+	drop_cached_metadata(vg_from);
+
+	/* Merge volume groups */
+	while (!dm_list_empty(&vg_from->pvs)) {
+		struct dm_list *pvh = vg_from->pvs.n;
+		struct physical_volume *pv;
+
+		dm_list_move(&vg_to->pvs, pvh);
+
+		pv = dm_list_item(pvh, struct pv_list)->pv;
+		pv->vg_name = dm_pool_strdup(cmd->mem, vg_to->name);
+	}
+	vg_to->pv_count += vg_from->pv_count;
+
+	/* Fix up LVIDs */
+	dm_list_iterate_items(lvl1, &vg_to->lvs) {
+		union lvid *lvid1 = &lvl1->lv->lvid;
+		char uuid[64] __attribute((aligned(8)));
+
+		dm_list_iterate_items(lvl2, &vg_from->lvs) {
+			union lvid *lvid2 = &lvl2->lv->lvid;
+
+			if (id_equal(&lvid1->id[1], &lvid2->id[1])) {
+				if (!id_create(&lvid2->id[1])) {
+					log_error("Failed to generate new "
+						  "random LVID for %s",
+						  lvl2->lv->name);
+					goto bad;
+				}
+				if (!id_write_format(&lvid2->id[1], uuid,
+						     sizeof(uuid)))
+					goto_bad;
+
+				log_verbose("Changed LVID for %s to %s",
+					    lvl2->lv->name, uuid);
+			}
+		}
+	}
+
+	while (!dm_list_empty(&vg_from->lvs)) {
+		struct dm_list *lvh = vg_from->lvs.n;
+
+		dm_list_move(&vg_to->lvs, lvh);
+	}
+
+	while (!dm_list_empty(&vg_from->fid->metadata_areas)) {
+		struct dm_list *mdah = vg_from->fid->metadata_areas.n;
+
+		dm_list_move(&vg_to->fid->metadata_areas, mdah);
+	}
+
+	vg_to->lv_count += vg_from->lv_count;
+	vg_to->snapshot_count += vg_from->snapshot_count;
+
+	vg_to->extent_count += vg_from->extent_count;
+	vg_to->free_count += vg_from->free_count;
+
+	/* store it on disks */
+	log_verbose("Writing out updated volume group");
+	if (!vg_write(vg_to) || !vg_commit(vg_to))
+		goto_bad;
+
+	/* FIXME Remove /dev/vgfrom */
+
+	backup(vg_to);
+
+	unlock_vg(cmd, vg_name_from);
+	unlock_vg(cmd, vg_name_to);
+
+	log_print("Volume group \"%s\" successfully merged into \"%s\"",
+		  vg_from->name, vg_to->name);
+	return ECMD_PROCESSED;
+
+      bad:
+	unlock_vg(cmd, vg_name_from);
+	unlock_vg(cmd, vg_name_to);
+	return ECMD_FAILED;
+}
+
+int vgmerge(struct cmd_context *cmd, int argc, char **argv)
+{
+	char *vg_name_to, *vg_name_from;
+	int opt = 0;
+	int ret = 0, ret_max = 0;
+
+	if (argc < 2) {
+		log_error("Please enter 2 or more volume groups to merge");
+		return EINVALID_CMD_LINE;
+	}
+
+	vg_name_to = skip_dev_dir(cmd, argv[0], NULL);
+	argc--;
+	argv++;
+
+	for (; opt < argc; opt++) {
+		vg_name_from = skip_dev_dir(cmd, argv[opt], NULL);
+
+		ret = _vgmerge_single(cmd, vg_name_to, vg_name_from);
+		if (ret > ret_max)
+			ret_max = ret;
+	}
+
+	return ret_max;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/vgmknodes.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/vgmknodes.c
diff -N src/external/gpl2/lvm2tools/dist/tools/vgmknodes.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/vgmknodes.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,40 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+static int _vgmknodes_single(struct cmd_context *cmd, struct logical_volume *lv,
+			     void *handle __attribute((unused)))
+{
+	if (!lv_mknodes(cmd, lv))
+		return ECMD_FAILED;
+
+	return ECMD_PROCESSED;
+}
+
+int vgmknodes(struct cmd_context *cmd, int argc, char **argv)
+{
+	int r;
+
+	r = process_each_lv(cmd, argc, argv, LCK_VG_READ, NULL,
+			    &_vgmknodes_single);
+
+	if (!lv_mknodes(cmd, NULL) && (r < ECMD_FAILED))
+		r = ECMD_FAILED;
+
+	return r;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/vgreduce.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/vgreduce.c
diff -N src/external/gpl2/lvm2tools/dist/tools/vgreduce.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/vgreduce.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,613 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+#include "lv_alloc.h"
+
+static int _remove_pv(struct volume_group *vg, struct pv_list *pvl, int silent)
+{
+	char uuid[64] __attribute((aligned(8)));
+
+	if (vg->pv_count == 1) {
+		log_error("Volume Groups must always contain at least one PV");
+		return 0;
+	}
+
+	if (!id_write_format(&pvl->pv->id, uuid, sizeof(uuid)))
+		return_0;
+
+	log_verbose("Removing PV with UUID %s from VG %s", uuid, vg->name);
+
+	if (pvl->pv->pe_alloc_count) {
+		if (!silent)
+			log_error("LVs still present on PV with UUID %s: "
+				  "Can't remove from VG %s", uuid, vg->name);
+		return 0;
+	}
+
+	vg->free_count -= pvl->pv->pe_count;
+	vg->extent_count -= pvl->pv->pe_count;
+	vg->pv_count--;
+
+	dm_list_del(&pvl->list);
+
+	return 1;
+}
+
+static int _remove_lv(struct cmd_context *cmd, struct logical_volume *lv,
+		      int *list_unsafe, struct dm_list *lvs_changed)
+{
+	struct lv_segment *snap_seg;
+	struct dm_list *snh, *snht;
+	struct logical_volume *cow;
+	struct lv_list *lvl;
+	struct lvinfo info;
+	int first = 1;
+
+	log_verbose("%s/%s has missing extents: removing (including "
+		    "dependencies)", lv->vg->name, lv->name);
+
+	/* FIXME Cope properly with stacked devices & snapshots. */
+
+	/* If snapshot device is missing, deactivate origin. */
+	if (lv_is_cow(lv) && (snap_seg = find_cow(lv))) {
+		log_verbose("Deactivating (if active) logical volume %s "
+			    "(origin of %s)", snap_seg->origin->name, lv->name);
+
+		if (!test_mode() && !deactivate_lv(cmd, snap_seg->origin)) {
+			log_error("Failed to deactivate LV %s",
+				  snap_seg->origin->name);
+			return 0;
+		}
+
+		/* Use the origin LV */
+		lv = snap_seg->origin;
+	}
+
+	/* Remove snapshot dependencies */
+	dm_list_iterate_safe(snh, snht, &lv->snapshot_segs) {
+		snap_seg = dm_list_struct_base(snh, struct lv_segment,
+					    origin_list);
+		cow = snap_seg->cow;
+
+		if (first && !test_mode() &&
+		    !deactivate_lv(cmd, snap_seg->origin)) {
+			log_error("Failed to deactivate LV %s",
+				  snap_seg->origin->name);
+			return 0;
+		}
+
+		*list_unsafe = 1;	/* May remove caller's lvht! */
+		if (!vg_remove_snapshot(cow))
+			return_0;
+		log_verbose("Removing LV %s from VG %s", cow->name,
+			    lv->vg->name);
+		if (!lv_remove(cow))
+			return_0;
+
+		first = 0;
+	}
+
+	/*
+	 * If LV is active, replace it with error segment
+	 * and add to list of LVs to be removed later.
+	 * Doesn't apply to snapshots/origins yet - they're already deactivated.
+	 */
+	/*
+	 * If the LV is a part of mirror segment,
+	 * the mirrored LV also should be cleaned up.
+	 * Clean-up is currently done by caller (_make_vg_consistent()).
+	 */
+	if ((lv_info(cmd, lv, &info, 0, 0) && info.exists) ||
+	    find_mirror_seg(first_seg(lv))) {
+		if (!replace_lv_with_error_segment(lv))
+			return_0;
+
+		if (!(lvl = dm_pool_alloc(cmd->mem, sizeof(*lvl)))) {
+			log_error("lv_list alloc failed");
+			return 0;
+		}
+		lvl->lv = lv;
+		dm_list_add(lvs_changed, &lvl->list);
+	} else {
+		/* Remove LV immediately. */
+		log_verbose("Removing LV %s from VG %s", lv->name, lv->vg->name);
+		if (!lv_remove(lv))
+			return_0;
+	}
+
+	return 1;
+}
+
+static int _consolidate_vg(struct cmd_context *cmd, struct volume_group *vg)
+{
+	struct pv_list *pvl;
+	struct lv_list *lvl;
+	int r = 1;
+
+	dm_list_iterate_items(lvl, &vg->lvs)
+		if (lvl->lv->status & PARTIAL_LV) {
+			log_warn("WARNING: Partial LV %s needs to be repaired "
+				 "or removed. ", lvl->lv->name);
+			r = 0;
+		}
+
+	if (!r) {
+		cmd->handles_missing_pvs = 1;
+		log_warn("WARNING: There are still partial LVs in VG %s.", vg->name);
+		log_warn("To remove them unconditionally use: vgreduce --removemissing --force.");
+		log_warn("Proceeding to remove empty missing PVs.");
+	}
+
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		if (pvl->pv->dev && !(pvl->pv->status & MISSING_PV))
+			continue;
+		if (r && !_remove_pv(vg, pvl, 0))
+			return_0;
+	}
+
+	return r;
+}
+
+static int _make_vg_consistent(struct cmd_context *cmd, struct volume_group *vg)
+{
+	struct dm_list *pvh, *pvht;
+	struct dm_list *lvh, *lvht;
+	struct pv_list *pvl;
+	struct lv_list *lvl, *lvl2, *lvlt;
+	struct logical_volume *lv;
+	struct physical_volume *pv;
+	struct lv_segment *seg, *mirrored_seg;
+	unsigned s;
+	uint32_t mimages, remove_log;
+	int list_unsafe, only_mirror_images_found;
+	DM_LIST_INIT(lvs_changed);
+	only_mirror_images_found = 1;
+
+	/* Deactivate & remove necessary LVs */
+      restart_loop:
+	list_unsafe = 0;	/* Set if we delete a different list-member */
+
+	dm_list_iterate_safe(lvh, lvht, &vg->lvs) {
+		lv = dm_list_item(lvh, struct lv_list)->lv;
+
+		/* Are any segments of this LV on missing PVs? */
+		dm_list_iterate_items(seg, &lv->segments) {
+			for (s = 0; s < seg->area_count; s++) {
+				if (seg_type(seg, s) != AREA_PV)
+					continue;
+
+				/* FIXME Also check for segs on deleted LVs (incl pvmove) */
+
+				pv = seg_pv(seg, s);
+				if (!pv || !pv_dev(pv) ||
+				    (pv->status & MISSING_PV)) {
+					if (arg_count(cmd, mirrorsonly_ARG) &&
+					    !(lv->status & MIRROR_IMAGE)) {
+						log_error("Non-mirror-image LV %s found: can't remove.", lv->name);
+						only_mirror_images_found = 0;
+						continue;
+					}
+					if (!_remove_lv(cmd, lv, &list_unsafe, &lvs_changed))
+						return_0;
+					if (list_unsafe)
+						goto restart_loop;
+				}
+			}
+		}
+	}
+
+	if (!only_mirror_images_found) {
+		log_error("Aborting because --mirrorsonly was specified.");
+		return 0;
+	}
+
+	/*
+	 * Remove missing PVs. FIXME: This duplicates _consolidate_vg above,
+	 * but we cannot use that right now, since the LV removal code in this
+	 * function leaves the VG in a "somewhat inconsistent" state and
+	 * _consolidate_vg doesn't like that -- specifically, mirrors are fixed
+	 * up *after* the PVs are removed. All this should be gradually
+	 * superseded by lvconvert --repair.
+	 */
+	dm_list_iterate_safe(pvh, pvht, &vg->pvs) {
+		pvl = dm_list_item(pvh, struct pv_list);
+		if (pvl->pv->dev)
+			continue;
+		if (!_remove_pv(vg, pvl, 0))
+			return_0;
+	}
+
+	/* FIXME Recovery.  For now people must clean up by hand. */
+
+	if (!dm_list_empty(&lvs_changed)) {
+		if (!vg_write(vg)) {
+			log_error("Failed to write out a consistent VG for %s",
+				  vg->name);
+			return 0;
+		}
+
+		if (!test_mode()) {
+			/* Suspend lvs_changed */
+			if (!suspend_lvs(cmd, &lvs_changed)) {
+				stack;
+				vg_revert(vg);
+				return 0;
+			}
+		}
+
+		if (!vg_commit(vg)) {
+			log_error("Failed to commit consistent VG for %s",
+				  vg->name);
+			vg_revert(vg);
+			return 0;
+		}
+
+		if (!test_mode()) {
+			if (!resume_lvs(cmd, &lvs_changed)) {
+				log_error("Failed to resume LVs using error segments.");
+				return 0;
+			}
+		}
+
+  lvs_changed_altered:
+		/* Remove lost mirror images from mirrors */
+		dm_list_iterate_items(lvl, &vg->lvs) {
+  mirrored_seg_altered:
+			mirrored_seg = first_seg(lvl->lv);
+			if (!seg_is_mirrored(mirrored_seg))
+				continue;
+
+			mimages = mirrored_seg->area_count;
+			remove_log = 0;
+
+			for (s = 0; s < mirrored_seg->area_count; s++) {
+				dm_list_iterate_items_safe(lvl2, lvlt, &lvs_changed) {
+					if (seg_type(mirrored_seg, s) != AREA_LV ||
+					    lvl2->lv != seg_lv(mirrored_seg, s))
+						continue;
+					dm_list_del(&lvl2->list);
+					if (!shift_mirror_images(mirrored_seg, s))
+						return_0;
+					mimages--;	/* FIXME Assumes uniqueness */
+				}
+			}
+
+			if (mirrored_seg->log_lv) {
+				dm_list_iterate_items(seg, &mirrored_seg->log_lv->segments) {
+					/* FIXME: The second test shouldn't be required */
+					if ((seg->segtype ==
+					     get_segtype_from_string(vg->cmd, "error"))) {
+						log_print("The log device for %s/%s has failed.",
+							  vg->name, mirrored_seg->lv->name);
+						remove_log = 1;
+						break;
+					}
+					if (!strcmp(seg->segtype->name, "error")) {
+						log_print("Log device for %s/%s has failed.",
+							  vg->name, mirrored_seg->lv->name);
+						remove_log = 1;
+						break;
+					}
+				}
+			}
+
+			if ((mimages != mirrored_seg->area_count) || remove_log){
+				if (!reconfigure_mirror_images(mirrored_seg, mimages,
+							       NULL, remove_log))
+					return_0;
+
+				if (!vg_write(vg)) {
+					log_error("Failed to write out updated "
+						  "VG for %s", vg->name);
+					return 0;
+				}
+		
+				if (!vg_commit(vg)) {
+					log_error("Failed to commit updated VG "
+						  "for %s", vg->name);
+					vg_revert(vg);
+					return 0;
+				}
+
+				/* mirrored LV no longer has valid mimages.
+				 * So add it to lvs_changed for removal.
+				 * For this LV may be an area of other mirror,
+				 * restart the loop. */
+				if (!mimages) {
+					if (!_remove_lv(cmd, lvl->lv,
+						 &list_unsafe, &lvs_changed))
+						return_0;
+					goto lvs_changed_altered;
+				}
+
+				/* As a result of reconfigure_mirror_images(),
+				 * first_seg(lv) may now be different seg.
+				 * e.g. a temporary layer might be removed.
+				 * So check the mirrored_seg again. */
+				goto mirrored_seg_altered;
+			}
+		}
+
+		/* Deactivate error LVs */
+		if (!test_mode()) {
+			dm_list_iterate_items_safe(lvl, lvlt, &lvs_changed) {
+				log_verbose("Deactivating (if active) logical volume %s",
+					    lvl->lv->name);
+
+				if (!deactivate_lv(cmd, lvl->lv)) {
+					log_error("Failed to deactivate LV %s",
+						  lvl->lv->name);
+					/*
+					 * We failed to deactivate.
+					 * Probably because this was a mirror log.
+					 * Don't try to lv_remove it.
+					 * Continue work on others.
+					 */
+					dm_list_del(&lvl->list);
+				}
+			}
+		}
+
+		/* Remove remaining LVs */
+		dm_list_iterate_items(lvl, &lvs_changed) {
+			log_verbose("Removing LV %s from VG %s", lvl->lv->name,
+				    lvl->lv->vg->name);
+				/* Skip LVs already removed by mirror code */
+				if (find_lv_in_vg(vg, lvl->lv->name) &&
+				    !lv_remove(lvl->lv))
+					return_0;
+		}
+	}
+
+	return 1;
+}
+
+/* Or take pv_name instead? */
+static int _vgreduce_single(struct cmd_context *cmd, struct volume_group *vg,
+			    struct physical_volume *pv,
+			    void *handle __attribute((unused)))
+{
+	struct pv_list *pvl;
+	struct volume_group *orphan_vg;
+	int consistent = 1;
+	const char *name = pv_dev_name(pv);
+
+	if (pv_pe_alloc_count(pv)) {
+		log_error("Physical volume \"%s\" still in use", name);
+		return ECMD_FAILED;
+	}
+
+	if (vg->pv_count == 1) {
+		log_error("Can't remove final physical volume \"%s\" from "
+			  "volume group \"%s\"", name, vg->name);
+		return ECMD_FAILED;
+	}
+
+	if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE | LCK_NONBLOCK)) {
+		log_error("Can't get lock for orphan PVs");
+		return ECMD_FAILED;
+	}
+
+	pvl = find_pv_in_vg(vg, name);
+
+	if (!archive(vg)) {
+		unlock_vg(cmd, VG_ORPHANS);
+		return ECMD_FAILED;
+	}
+
+	log_verbose("Removing \"%s\" from volume group \"%s\"", name, vg->name);
+
+	if (pvl)
+		dm_list_del(&pvl->list);
+
+	pv->vg_name = vg->fid->fmt->orphan_vg_name;
+	pv->status = ALLOCATABLE_PV;
+
+	if (!dev_get_size(pv_dev(pv), &pv->size)) {
+		log_error("%s: Couldn't get size.", pv_dev_name(pv));
+		unlock_vg(cmd, VG_ORPHANS);
+		return ECMD_FAILED;
+	}
+
+	vg->pv_count--;
+	vg->free_count -= pv_pe_count(pv) - pv_pe_alloc_count(pv);
+	vg->extent_count -= pv_pe_count(pv);
+
+	if(!(orphan_vg = vg_read(cmd, vg->fid->fmt->orphan_vg_name, NULL, &consistent)) ||
+	   !consistent) {
+		log_error("Unable to read existing orphan PVs");
+		unlock_vg(cmd, VG_ORPHANS);
+		return ECMD_FAILED;
+	}
+
+	if (!vg_split_mdas(cmd, vg, orphan_vg) || !vg->pv_count) {
+		log_error("Cannot remove final metadata area on \"%s\" from \"%s\"",
+			  name, vg->name);
+		unlock_vg(cmd, VG_ORPHANS);
+		return ECMD_FAILED;
+	}
+
+	if (!vg_write(vg) || !vg_commit(vg)) {
+		log_error("Removal of physical volume \"%s\" from "
+			  "\"%s\" failed", name, vg->name);
+		unlock_vg(cmd, VG_ORPHANS);
+		return ECMD_FAILED;
+	}
+
+	if (!pv_write(cmd, pv, NULL, INT64_C(-1))) {
+		log_error("Failed to clear metadata from physical "
+			  "volume \"%s\" "
+			  "after removal from \"%s\"", name, vg->name);
+		unlock_vg(cmd, VG_ORPHANS);
+		return ECMD_FAILED;
+	}
+
+	unlock_vg(cmd, VG_ORPHANS);
+	backup(vg);
+
+	log_print("Removed \"%s\" from volume group \"%s\"", name, vg->name);
+
+	return ECMD_PROCESSED;
+}
+
+int vgreduce(struct cmd_context *cmd, int argc, char **argv)
+{
+	struct volume_group *vg;
+	char *vg_name;
+	int ret = 1;
+	int consistent = 1;
+	int fixed = 1;
+	int repairing = arg_count(cmd, removemissing_ARG);
+
+	if (!argc && !repairing) {
+		log_error("Please give volume group name and "
+			  "physical volume paths");
+		return EINVALID_CMD_LINE;
+	}
+	
+	if (!argc && repairing) {
+		log_error("Please give volume group name");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (arg_count(cmd, mirrorsonly_ARG) && !repairing) {
+		log_error("--mirrorsonly requires --removemissing");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (argc == 1 && !arg_count(cmd, all_ARG) && !repairing) {
+		log_error("Please enter physical volume paths or option -a");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (argc > 1 && arg_count(cmd, all_ARG)) {
+		log_error("Option -a and physical volume paths mutually "
+			  "exclusive");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (argc > 1 && repairing) {
+		log_error("Please only specify the volume group");
+		return EINVALID_CMD_LINE;
+	}
+
+	vg_name = skip_dev_dir(cmd, argv[0], NULL);
+	argv++;
+	argc--;
+
+	if (!validate_name(vg_name)) {
+		log_error("Volume group name \"%s\" is invalid",
+			  vg_name);
+		return ECMD_FAILED;
+	}
+
+	log_verbose("Finding volume group \"%s\"", vg_name);
+	if (!lock_vol(cmd, vg_name, LCK_VG_WRITE)) {
+		log_error("Can't get lock for %s", vg_name);
+		return ECMD_FAILED;
+	}
+
+	if ((!(vg = vg_read(cmd, vg_name, NULL, &consistent)) || !consistent)
+	    && !repairing) {
+		log_error("Volume group \"%s\" doesn't exist", vg_name);
+		unlock_vg(cmd, vg_name);
+		return ECMD_FAILED;
+	}
+
+	if (vg && !vg_check_status(vg, CLUSTERED)) {
+		unlock_vg(cmd, vg_name);
+		return ECMD_FAILED;
+	}
+
+	if (repairing) {
+		if (vg && consistent && !vg_missing_pv_count(vg)) {
+			log_error("Volume group \"%s\" is already consistent",
+				  vg_name);
+			unlock_vg(cmd, vg_name);
+			return ECMD_PROCESSED;
+		}
+
+		consistent = !arg_count(cmd, force_ARG);
+		if (!(vg = vg_read(cmd, vg_name, NULL, &consistent))) {
+			log_error("Volume group \"%s\" not found", vg_name);
+			unlock_vg(cmd, vg_name);
+			return ECMD_FAILED;
+		}
+		if (!vg_check_status(vg, CLUSTERED)) {
+			unlock_vg(cmd, vg_name);
+			return ECMD_FAILED;
+		}
+		if (!archive(vg)) {
+			unlock_vg(cmd, vg_name);
+			return ECMD_FAILED;
+		}
+
+		if (arg_count(cmd, force_ARG)) {
+			if (!_make_vg_consistent(cmd, vg)) {
+				unlock_vg(cmd, vg_name);
+				return ECMD_FAILED;
+			}
+		} else
+			fixed = _consolidate_vg(cmd, vg);
+
+		if (!vg_write(vg) || !vg_commit(vg)) {
+			log_error("Failed to write out a consistent VG for %s",
+				  vg_name);
+			unlock_vg(cmd, vg_name);
+			return ECMD_FAILED;
+		}
+
+		backup(vg);
+
+		if (fixed)
+			log_print("Wrote out consistent volume group %s",
+				  vg_name);
+
+	} else {
+		if (!vg_check_status(vg, EXPORTED_VG | LVM_WRITE | RESIZEABLE_VG)) {
+			unlock_vg(cmd, vg_name);
+			return ECMD_FAILED;
+		}
+
+		/* FIXME: Pass private struct through to all these functions */
+		/* and update in batch here? */
+		ret = process_each_pv(cmd, argc, argv, vg, LCK_NONE, NULL,
+				      _vgreduce_single);
+
+	}
+
+	unlock_vg(cmd, vg_name);
+
+	return ret;
+
+/******* FIXME
+	log_error ("no empty physical volumes found in volume group \"%s\"", vg_name);
+
+	log_verbose
+	    ("volume group \"%s\" will be reduced by %d physical volume%s",
+	     vg_name, np, np > 1 ? "s" : "");
+	log_verbose ("reducing volume group \"%s\" by physical volume \"%s\"",
+		     vg_name, pv_names[p]);
+
+	log_print
+	    ("volume group \"%s\" %ssuccessfully reduced by physical volume%s:",
+	     vg_name, error > 0 ? "NOT " : "", p > 1 ? "s" : "");
+		log_print("%s", pv_this[p]->pv_name);
+********/
+
+}
Index: src/external/gpl2/lvm2tools/dist/tools/vgremove.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/vgremove.c
diff -N src/external/gpl2/lvm2tools/dist/tools/vgremove.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/vgremove.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,52 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+static int vgremove_single(struct cmd_context *cmd, const char *vg_name,
+			   struct volume_group *vg, int consistent,
+			   void *handle __attribute((unused)))
+{
+	if (!vg_remove_single(cmd, vg_name, vg, consistent,
+			      arg_count(cmd, force_ARG)))
+		return ECMD_FAILED;
+
+	return ECMD_PROCESSED;
+}
+
+int vgremove(struct cmd_context *cmd, int argc, char **argv)
+{
+	int ret;
+
+	if (!argc) {
+		log_error("Please enter one or more volume group paths");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE)) {
+		log_error("Can't get lock for orphan PVs");
+		return ECMD_FAILED;
+	}
+
+	ret = process_each_vg(cmd, argc, argv,
+			      LCK_VG_WRITE | LCK_NONBLOCK, 1,
+			      NULL, &vgremove_single);
+
+	unlock_vg(cmd, VG_ORPHANS);
+
+	return ret;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/vgrename.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/vgrename.c
diff -N src/external/gpl2/lvm2tools/dist/tools/vgrename.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/vgrename.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,181 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+static int vg_rename_path(struct cmd_context *cmd, const char *old_vg_path,
+			  const char *new_vg_path)
+{
+	char *dev_dir;
+	struct id id;
+	int consistent = 1;
+	int match = 0;
+	int found_id = 0;
+	struct dm_list *vgids;
+	struct str_list *sl;
+	char *vg_name_new;
+	const char *vgid = NULL, *vg_name, *vg_name_old;
+	char old_path[NAME_LEN], new_path[NAME_LEN];
+	struct volume_group *vg, *vg_new;
+
+	vg_name_old = skip_dev_dir(cmd, old_vg_path, NULL);
+	vg_name_new = skip_dev_dir(cmd, new_vg_path, NULL);
+
+	dev_dir = cmd->dev_dir;
+
+	if (!validate_vg_rename_params(cmd, vg_name_old, vg_name_new))
+		return 0;
+
+	log_verbose("Checking for existing volume group \"%s\"", vg_name_old);
+
+	/* Avoid duplicates */
+	if (!(vgids = get_vgids(cmd, 0)) || dm_list_empty(vgids)) {
+		log_error("No complete volume groups found");
+		return 0;
+	}
+
+	dm_list_iterate_items(sl, vgids) {
+		vgid = sl->str;
+		if (!vgid || !(vg_name = vgname_from_vgid(NULL, vgid)) ||
+		    is_orphan_vg(vg_name))
+			continue;
+		if (!strcmp(vg_name, vg_name_old)) {
+			if (match) {
+				log_error("Found more than one VG called %s. "
+					  "Please supply VG uuid.", vg_name_old);
+				return 0;
+			}
+			match = 1;
+		}
+	}
+
+	log_suppress(2);
+	found_id = id_read_format(&id, vg_name_old);
+	log_suppress(0);
+	if (found_id && (vg_name = vgname_from_vgid(cmd->mem, (char *)id.uuid))) {
+		vg_name_old = vg_name;
+		vgid = (char *)id.uuid;
+	} else
+		vgid = NULL;
+
+	if (!lock_vol(cmd, vg_name_old, LCK_VG_WRITE)) {
+		log_error("Can't get lock for %s", vg_name_old);
+		return 0;
+	}
+
+	if (!(vg = vg_read(cmd, vg_name_old, vgid, &consistent)) || !consistent) {
+		log_error("Volume group %s %s%s%snot found.", vg_name_old,
+		vgid ? "(" : "", vgid ? vgid : "", vgid ? ") " : "");
+		unlock_vg(cmd, vg_name_old);
+		return 0;
+	}
+
+	if (!vg_check_status(vg, CLUSTERED | LVM_WRITE)) {
+		unlock_vg(cmd, vg_name_old);
+		return 0;
+	}
+
+	/* Don't return failure for EXPORTED_VG */
+	vg_check_status(vg, EXPORTED_VG);
+
+	if (lvs_in_vg_activated_by_uuid_only(vg)) {
+		unlock_vg(cmd, vg_name_old);
+		log_error("Volume group \"%s\" still has active LVs",
+			  vg_name_old);
+		/* FIXME Remove this restriction */
+		return 0;
+	}
+
+	log_verbose("Checking for new volume group \"%s\"", vg_name_new);
+
+	if (!lock_vol(cmd, vg_name_new, LCK_VG_WRITE | LCK_NONBLOCK)) {
+		unlock_vg(cmd, vg_name_old);
+		log_error("Can't get lock for %s", vg_name_new);
+		return 0;
+	}
+
+	consistent = 0;
+	if ((vg_new = vg_read(cmd, vg_name_new, NULL, &consistent))) {
+		log_error("New volume group \"%s\" already exists",
+			  vg_name_new);
+		goto error;
+	}
+
+	if (!archive(vg))
+		goto error;
+
+	/* Remove references based on old name */
+	drop_cached_metadata(vg);
+
+	/* Change the volume group name */
+	vg_rename(cmd, vg, vg_name_new);
+
+	sprintf(old_path, "%s%s", dev_dir, vg_name_old);
+	sprintf(new_path, "%s%s", dev_dir, vg_name_new);
+
+	if (activation() && dir_exists(old_path)) {
+		log_verbose("Renaming \"%s\" to \"%s\"", old_path, new_path);
+		if (test_mode())
+			log_verbose("Test mode: Skipping rename.");
+		else if (rename(old_path, new_path)) {
+			log_error("Renaming \"%s\" to \"%s\" failed: %s",
+				  old_path, new_path, strerror(errno));
+			goto error;
+		}
+	}
+
+	/* store it on disks */
+	log_verbose("Writing out updated volume group");
+	if (!vg_write(vg) || !vg_commit(vg)) {
+		goto error;
+	}
+
+/******* FIXME Rename any active LVs! *****/
+
+	backup(vg);
+
+	unlock_vg(cmd, vg_name_new);
+	unlock_vg(cmd, vg_name_old);
+
+	log_print("Volume group \"%s\" successfully renamed to \"%s\"",
+		  vg_name_old, vg_name_new);
+
+	/* FIXME lvmcache corruption - vginfo duplicated instead of renamed */
+	persistent_filter_wipe(cmd->filter);
+	lvmcache_destroy(cmd, 1);
+
+	return 1;
+
+      error:
+	unlock_vg(cmd, vg_name_new);
+	unlock_vg(cmd, vg_name_old);
+	return 0;
+}
+
+int vgrename(struct cmd_context *cmd, int argc, char **argv)
+{
+	if (argc != 2) {
+		log_error("Old and new volume group names need specifying");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (!vg_rename_path(cmd, argv[0], argv[1]))
+		return ECMD_FAILED;
+	
+	return ECMD_PROCESSED;
+}
+
Index: src/external/gpl2/lvm2tools/dist/tools/vgscan.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/vgscan.c
diff -N src/external/gpl2/lvm2tools/dist/tools/vgscan.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/vgscan.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,77 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+static int vgscan_single(struct cmd_context *cmd, const char *vg_name,
+			 struct volume_group *vg, int consistent,
+			 void *handle __attribute((unused)))
+{
+	if (!vg) {
+		log_error("Volume group \"%s\" not found", vg_name);
+		return ECMD_FAILED;
+	}
+
+	if (!consistent) {
+		unlock_vg(cmd, vg_name);
+		dev_close_all();
+		log_error("Volume group \"%s\" inconsistent", vg_name);
+		/* Don't allow partial switch to this program */
+		if (!(vg = recover_vg(cmd, vg_name, LCK_VG_WRITE)))
+			return ECMD_FAILED;
+	}
+
+	log_print("Found %svolume group \"%s\" using metadata type %s",
+		  (vg_status(vg) & EXPORTED_VG) ? "exported " : "", vg_name,
+		  vg->fid->fmt->name);
+
+	check_current_backup(vg);
+
+	return ECMD_PROCESSED;
+}
+
+int vgscan(struct cmd_context *cmd, int argc, char **argv)
+{
+	int maxret, ret;
+
+	if (argc) {
+		log_error("Too many parameters on command line");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (!lock_vol(cmd, VG_GLOBAL, LCK_VG_WRITE)) {
+		log_error("Unable to obtain global lock.");
+		return ECMD_FAILED;
+	}
+
+	persistent_filter_wipe(cmd->filter);
+	lvmcache_destroy(cmd, 1);
+
+	log_print("Reading all physical volumes.  This may take a while...");
+
+	maxret = process_each_vg(cmd, argc, argv, LCK_VG_READ, 0, NULL,
+				 &vgscan_single);
+
+	if (arg_count(cmd, mknodes_ARG)) {
+		ret = vgmknodes(cmd, argc, argv);
+		if (ret > maxret)
+			maxret = ret;
+	}
+
+	unlock_vg(cmd, VG_GLOBAL);
+	return maxret;
+}
Index: src/external/gpl2/lvm2tools/dist/tools/vgsplit.c
===================================================================
RCS file: src/external/gpl2/lvm2tools/dist/tools/vgsplit.c
diff -N src/external/gpl2/lvm2tools/dist/tools/vgsplit.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/dist/tools/vgsplit.c	13 Dec 2008 14:39:38 -0000	1.1.1.1.2.2
@@ -0,0 +1,482 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "tools.h"
+
+static int _move_pv(struct volume_group *vg_from, struct volume_group *vg_to,
+		    const char *pv_name)
+{
+	struct physical_volume *pv;
+	struct pv_list *pvl;
+
+	/* FIXME: handle tags */
+	if (!(pvl = find_pv_in_vg(vg_from, pv_name))) {
+		log_error("Physical volume %s not in volume group %s",
+			  pv_name, vg_from->name);
+		return 0;
+	}
+
+	dm_list_move(&vg_to->pvs, &pvl->list);
+
+	vg_from->pv_count--;
+	vg_to->pv_count++;
+
+	pv = pvl->pv;
+
+	vg_from->extent_count -= pv_pe_count(pv);
+	vg_to->extent_count += pv_pe_count(pv);
+
+	vg_from->free_count -= pv_pe_count(pv) - pv_pe_alloc_count(pv);
+	vg_to->free_count += pv_pe_count(pv) - pv_pe_alloc_count(pv);
+
+	return 1;
+}
+
+static int _move_pvs_used_by_lv(struct volume_group *vg_from,
+				   struct volume_group *vg_to,
+				   const char *lv_name)
+{
+	struct lv_segment *lvseg;
+	unsigned s;
+	struct lv_list *lvl;
+	struct logical_volume *lv;
+
+	/* FIXME: handle tags */
+	if (!(lvl = find_lv_in_vg(vg_from, lv_name))) {
+		log_error("Logical volume %s not in volume group %s",
+			  lv_name, vg_from->name);
+		return 0;
+	}
+
+	dm_list_iterate_items(lvseg, &lvl->lv->segments) {
+		if (lvseg->log_lv)
+			if (!_move_pvs_used_by_lv(vg_from, vg_to,
+						     lvseg->log_lv->name))
+				return_0;
+		for (s = 0; s < lvseg->area_count; s++) {
+			if (seg_type(lvseg, s) == AREA_PV) {
+				if (!_move_pv(vg_from, vg_to,
+					      pv_dev_name(seg_pv(lvseg, s))))
+					return_0;
+			} else if (seg_type(lvseg, s) == AREA_LV) {
+				lv = seg_lv(lvseg, s);
+				if (!_move_pvs_used_by_lv(vg_from, vg_to,
+							     lv->name))
+				    return_0;
+			}
+		}
+	}
+	return 1;
+}
+
+/* FIXME Why not (lv->vg == vg) ? */
+static int _lv_is_in_vg(struct volume_group *vg, struct logical_volume *lv)
+{
+	struct lv_list *lvl;
+
+	dm_list_iterate_items(lvl, &vg->lvs)
+		if (lv == lvl->lv)
+			 return 1;
+
+	return 0;
+}
+
+static int _move_one_lv(struct volume_group *vg_from,
+			 struct volume_group *vg_to,
+			 struct dm_list *lvh)
+{
+	struct logical_volume *lv = dm_list_item(lvh, struct lv_list)->lv;
+
+	dm_list_move(&vg_to->lvs, lvh);
+	
+	if (lv_is_active(lv)) {
+		log_error("Logical volume \"%s\" must be inactive", lv->name);
+		return 0;
+	}
+
+	if (lv->status & SNAPSHOT) {
+		vg_from->snapshot_count--;
+		vg_to->snapshot_count++;
+	} else if (!lv_is_cow(lv)) {
+		vg_from->lv_count--;
+		vg_to->lv_count++;
+	}
+	return 1;
+}	
+
+static int _move_lvs(struct volume_group *vg_from, struct volume_group *vg_to)
+{
+	struct dm_list *lvh, *lvht;
+	struct logical_volume *lv;
+	struct lv_segment *seg;
+	struct physical_volume *pv;
+	struct volume_group *vg_with;
+	unsigned s;
+
+	dm_list_iterate_safe(lvh, lvht, &vg_from->lvs) {
+		lv = dm_list_item(lvh, struct lv_list)->lv;
+
+		if ((lv->status & SNAPSHOT))
+			continue;
+
+		if ((lv->status & MIRRORED))
+			continue;
+
+		/* Ensure all the PVs used by this LV remain in the same */
+		/* VG as each other */
+		vg_with = NULL;
+		dm_list_iterate_items(seg, &lv->segments) {
+			for (s = 0; s < seg->area_count; s++) {
+				/* FIXME Check AREA_LV too */
+				if (seg_type(seg, s) != AREA_PV)
+					continue;
+
+				pv = seg_pv(seg, s);
+				if (vg_with) {
+					if (!pv_is_in_vg(vg_with, pv)) {
+						log_error("Can't split Logical "
+							  "Volume %s between "
+							  "two Volume Groups",
+							  lv->name);
+						return 0;
+					}
+					continue;
+				}
+
+				if (pv_is_in_vg(vg_from, pv)) {
+					vg_with = vg_from;
+					continue;
+				}
+				if (pv_is_in_vg(vg_to, pv)) {
+					vg_with = vg_to;
+					continue;
+				}
+				log_error("Physical Volume %s not found",
+					  pv_dev_name(pv));
+				return 0;
+			}
+
+		}
+			
+		if (vg_with == vg_from)
+			continue;
+
+		/* Move this LV */
+		if (!_move_one_lv(vg_from, vg_to, lvh))
+			return_0;
+	}
+
+	/* FIXME Ensure no LVs contain segs pointing at LVs in the other VG */
+
+	return 1;
+}
+
+/*
+ * Move the hidden / internal "snapshotN" LVs.from 'vg_from' to 'vg_to'.
+ */
+static int _move_snapshots(struct volume_group *vg_from,
+			   struct volume_group *vg_to)
+{
+	struct dm_list *lvh, *lvht;
+	struct logical_volume *lv;
+	struct lv_segment *seg;
+	int cow_from = 0;
+	int origin_from = 0;
+
+	dm_list_iterate_safe(lvh, lvht, &vg_from->lvs) {
+		lv = dm_list_item(lvh, struct lv_list)->lv;
+
+		if (!(lv->status & SNAPSHOT))
+			continue;
+
+		dm_list_iterate_items(seg, &lv->segments) {
+			cow_from = _lv_is_in_vg(vg_from, seg->cow);
+			origin_from = _lv_is_in_vg(vg_from, seg->origin);
+
+			if (cow_from && origin_from)
+				continue;
+			if ((!cow_from && origin_from) ||
+			     (cow_from && !origin_from)) {
+				log_error("Can't split snapshot %s between"
+					  " two Volume Groups", seg->cow->name);
+				return 0;
+			}
+
+			/*
+			 * At this point, the cow and origin should already be
+			 * in vg_to.
+			 */
+			if (_lv_is_in_vg(vg_to, seg->cow) &&
+			    _lv_is_in_vg(vg_to, seg->origin)) {
+				if (!_move_one_lv(vg_from, vg_to, lvh))
+					return_0;
+			}
+		}
+
+	}
+
+	return 1;
+}
+
+static int _move_mirrors(struct volume_group *vg_from,
+			 struct volume_group *vg_to)
+{
+	struct dm_list *lvh, *lvht;
+	struct logical_volume *lv;
+	struct lv_segment *seg;
+	unsigned s, seg_in, log_in;
+
+	dm_list_iterate_safe(lvh, lvht, &vg_from->lvs) {
+		lv = dm_list_item(lvh, struct lv_list)->lv;
+
+		if (!(lv->status & MIRRORED))
+			continue;
+
+		seg = first_seg(lv);
+
+		seg_in = 0;
+		for (s = 0; s < seg->area_count; s++)
+			if (_lv_is_in_vg(vg_to, seg_lv(seg, s)))
+			    seg_in++;
+
+		log_in = (!seg->log_lv || _lv_is_in_vg(vg_to, seg->log_lv));
+		
+		if ((seg_in && seg_in < seg->area_count) ||
+		    (seg_in && seg->log_lv && !log_in) ||
+		    (!seg_in && seg->log_lv && log_in)) {
+			log_error("Can't split mirror %s between "
+				  "two Volume Groups", lv->name);
+			return 0;
+		}
+
+		if (seg_in == seg->area_count && log_in) {
+			if (!_move_one_lv(vg_from, vg_to, lvh))
+				return_0;
+		}
+	}
+
+	return 1;
+}
+
+/*
+ * Has the user given an option related to a new vg as the split destination?
+ */
+static int new_vg_option_specified(struct cmd_context *cmd)
+{
+	return(arg_count(cmd, clustered_ARG) ||
+	       arg_count(cmd, alloc_ARG) ||
+	       arg_count(cmd, maxphysicalvolumes_ARG) ||
+	       arg_count(cmd, maxlogicalvolumes_ARG));
+}
+
+int vgsplit(struct cmd_context *cmd, int argc, char **argv)
+{
+	struct vgcreate_params vp_new;
+	struct vgcreate_params vp_def;
+	char *vg_name_from, *vg_name_to;
+	struct volume_group *vg_to, *vg_from;
+	int opt;
+	int existing_vg;
+	int consistent;
+	const char *lv_name;
+
+	if ((arg_count(cmd, name_ARG) + argc) < 3) {
+		log_error("Existing VG, new VG and either physical volumes "
+			  "or logical volume required.");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (arg_count(cmd, name_ARG) && (argc > 2)) {
+		log_error("A logical volume name cannot be given with "
+			  "physical volumes.");
+		return ECMD_FAILED;
+	}
+
+	if (arg_count(cmd, name_ARG))
+		lv_name = arg_value(cmd, name_ARG);
+	else
+		lv_name = NULL;
+
+	vg_name_from = skip_dev_dir(cmd, argv[0], NULL);
+	vg_name_to = skip_dev_dir(cmd, argv[1], NULL);
+	argc -= 2;
+	argv += 2;
+
+	if (!strcmp(vg_name_to, vg_name_from)) {
+		log_error("Duplicate volume group name \"%s\"", vg_name_from);
+		return ECMD_FAILED;
+	}
+
+	log_verbose("Checking for volume group \"%s\"", vg_name_from);
+	if (!(vg_from = vg_lock_and_read(cmd, vg_name_from, NULL, LCK_VG_WRITE,
+				       CLUSTERED | EXPORTED_VG |
+				       RESIZEABLE_VG | LVM_WRITE,
+				       CORRECT_INCONSISTENT | FAIL_INCONSISTENT)))
+		 return ECMD_FAILED;
+
+	log_verbose("Checking for new volume group \"%s\"", vg_name_to);
+	if (!lock_vol(cmd, vg_name_to, LCK_VG_WRITE | LCK_NONBLOCK)) {
+		log_error("Can't get lock for %s", vg_name_to);
+		unlock_vg(cmd, vg_name_from);
+		return ECMD_FAILED;
+	}
+
+	consistent = 0;
+	if ((vg_to = vg_read(cmd, vg_name_to, NULL, &consistent))) {
+		existing_vg = 1;
+		if (new_vg_option_specified(cmd)) {
+			log_error("Volume group \"%s\" exists, but new VG "
+				    "option specified", vg_name_to);
+			goto_bad;
+		}
+		if (!vgs_are_compatible(cmd, vg_from,vg_to))
+			goto_bad;
+	} else {
+		existing_vg = 0;
+
+		/* Set metadata format of original VG */
+		/* FIXME: need some common logic */
+		cmd->fmt = vg_from->fid->fmt;
+
+		vp_def.vg_name = NULL;
+		vp_def.extent_size = vg_from->extent_size;
+		vp_def.max_pv = vg_from->max_pv;
+		vp_def.max_lv = vg_from->max_lv;
+		vp_def.alloc = vg_from->alloc;
+		vp_def.clustered = 0;
+
+		if (fill_vg_create_params(cmd, vg_name_to, &vp_new, &vp_def)) {
+			unlock_vg(cmd, vg_name_from);
+			unlock_vg(cmd, vg_name_to);
+			return EINVALID_CMD_LINE;
+		}
+
+		if (validate_vg_create_params(cmd, &vp_new)) {
+			unlock_vg(cmd, vg_name_from);
+			unlock_vg(cmd, vg_name_to);
+			return EINVALID_CMD_LINE;
+		}
+
+		if (!(vg_to = vg_create(cmd, vg_name_to, vp_new.extent_size,
+					vp_new.max_pv, vp_new.max_lv,
+					vp_new.alloc, 0, NULL)))
+			goto_bad;
+
+		if (vg_is_clustered(vg_from))
+			vg_to->status |= CLUSTERED;
+	}
+
+	/* Archive vg_from before changing it */
+	if (!archive(vg_from))
+		goto_bad;
+
+	/* Move PVs across to new structure */
+	for (opt = 0; opt < argc; opt++) {
+		if (!_move_pv(vg_from, vg_to, argv[opt]))
+			goto_bad;
+	}
+
+	/* If an LV given on the cmdline, move used_by PVs */
+	if (lv_name && !_move_pvs_used_by_lv(vg_from, vg_to, lv_name))
+		goto_bad;
+
+	/* Move required LVs across, checking consistency */
+	if (!(_move_lvs(vg_from, vg_to)))
+		goto_bad;
+
+	/* Move required snapshots across */
+	if (!(_move_snapshots(vg_from, vg_to)))
+		goto_bad;
+
+	/* Move required mirrors across */
+	if (!(_move_mirrors(vg_from, vg_to)))
+		goto_bad;
+
+	/* Split metadata areas and check if both vgs have at least one area */
+	if (!(vg_split_mdas(cmd, vg_from, vg_to)) && vg_from->pv_count) {
+		log_error("Cannot split: Nowhere to store metadata for new Volume Group");
+		goto_bad;
+	}
+
+	/* Set proper name for all PVs in new VG */
+	if (!vg_rename(cmd, vg_to, vg_name_to))
+		goto_bad;
+
+	/* store it on disks */
+	log_verbose("Writing out updated volume groups");
+
+	/*
+	 * First, write out the new VG as EXPORTED.  We do this first in case
+	 * there is a crash - we will still have the new VG information, in an
+	 * exported state.  Recovery after this point would be removal of the
+	 * new VG and redoing the vgsplit.
+	 * FIXME: recover automatically or instruct the user?
+	 */
+	vg_to->status |= EXPORTED_VG;
+
+	if (!archive(vg_to))
+		goto_bad;
+
+	if (!vg_write(vg_to) || !vg_commit(vg_to))
+		goto_bad;
+
+	backup(vg_to);
+
+	/*
+	 * Next, write out the updated old VG.  If we crash after this point,
+	 * recovery is a vgimport on the new VG.
+	 * FIXME: recover automatically or instruct the user?
+	 */
+	if (vg_from->pv_count) {
+		if (!vg_write(vg_from) || !vg_commit(vg_from))
+			goto_bad;
+
+		backup(vg_from);
+	}
+
+	/*
+	 * Finally, remove the EXPORTED flag from the new VG and write it out.
+	 */
+	consistent = 1;
+	if (!test_mode() &&
+	    (!(vg_to = vg_read(cmd, vg_name_to, NULL, &consistent)) ||
+	     !consistent)) {
+		log_error("Volume group \"%s\" became inconsistent: please "
+			  "fix manually", vg_name_to);
+		goto_bad;
+	}
+
+	vg_to->status &= ~EXPORTED_VG;
+
+	if (!vg_write(vg_to) || !vg_commit(vg_to))
+		goto_bad;
+
+	backup(vg_to);
+
+	unlock_vg(cmd, vg_name_from);
+	unlock_vg(cmd, vg_name_to);
+
+	log_print("%s volume group \"%s\" successfully split from \"%s\"",
+		  existing_vg ? "Existing" : "New",
+		  vg_to->name, vg_from->name);
+	return ECMD_PROCESSED;
+
+      bad:
+	unlock_vg(cmd, vg_name_from);
+	unlock_vg(cmd, vg_name_to);
+	return ECMD_FAILED;
+}
Index: src/external/gpl2/lvm2tools/lib/Makefile
===================================================================
RCS file: src/external/gpl2/lvm2tools/lib/Makefile
diff -N src/external/gpl2/lvm2tools/lib/Makefile
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/lib/Makefile	16 Dec 2008 00:43:53 -0000	1.1.2.3
@@ -0,0 +1,5 @@
+#	$NetBSD: Makefile,v 1.1.2.3 2008/12/16 00:43:53 haad Exp $
+
+SUBDIR=	libdevmapper liblvm 
+
+.include <bsd.subdir.mk>
Index: src/external/gpl2/lvm2tools/lib/libdevmapper/Makefile
===================================================================
RCS file: src/external/gpl2/lvm2tools/lib/libdevmapper/Makefile
diff -N src/external/gpl2/lvm2tools/lib/libdevmapper/Makefile
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/lib/libdevmapper/Makefile	16 Dec 2008 00:40:59 -0000	1.1.2.1
@@ -0,0 +1,34 @@
+#	$NetBSD: Makefile,v 1.1.2.1 2008/12/16 00:40:59 haad Exp $
+
+USE_SHLIBDIR=	yes
+USE_FORT?=	no
+NOLINT=		#defined
+
+.include "../../lvm2tools.mk"
+
+LIB=		devmapper
+
+CFLAGS+= -fno-inline
+
+CPPFLAGS+=	-I${LIBDM_SRCDIR} -I${LIBDM_SRCDIR}/misc -I${LIBDM_SRCDIR}/mm \
+		-I${LIBDM_SRCDIR}/datastruct -I${LIBDM_SRCDIR}/ioctl \
+		-I${LVM2TOOLS_DISTDIR}/include -I. -D__NetBSD__
+
+
+CPPFLAGS+=	-D__LIB_DEVMAPPER__ -DDM_DEVICE_UID=0 \
+		-DDM_DEVICE_GID=0 -DDM_DEVICE_MODE=0600
+
+LDADD+=		-lprop
+
+SRCS+=		bitset.c hash.c list.c libdm-common.c libdm-file.c \
+		libdm-deptree.c	libdm-string.c libdm-report.c \
+		dbg_malloc.c pool.c matcher.c parse_rx.c ttree.c \
+		libdm-nbsd-iface.c libdm_netbsd.c
+
+.PATH: ${LIBDM_SRCDIR}/
+.PATH: ${LIBDM_SRCDIR}/datastruct
+.PATH: ${LIBDM_SRCDIR}/mm
+.PATH: ${LIBDM_SRCDIR}/regex
+.PATH: ${LIBDM_SRCDIR}/ioctl
+
+.include <bsd.lib.mk>
Index: src/external/gpl2/lvm2tools/lib/libdevmapper/netbsd-dm.h
===================================================================
RCS file: src/external/gpl2/lvm2tools/lib/libdevmapper/netbsd-dm.h
diff -N src/external/gpl2/lvm2tools/lib/libdevmapper/netbsd-dm.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/lib/libdevmapper/netbsd-dm.h	17 Dec 2008 00:49:40 -0000	1.1.2.1
@@ -0,0 +1,174 @@
+#ifndef __NETBSD_DM_H__
+#define __NETBSD_DM_H__
+
+#include <prop/proplib.h>
+
+#define DM_CMD_LEN 16
+
+#define DM_IOCTL 0xfd
+
+#define DM_IOCTL_CMD 0
+
+#define NETBSD_DM_IOCTL       _IOWR(DM_IOCTL, DM_IOCTL_CMD, struct plistref)
+
+
+/*
+ * DM-ioctl dictionary.
+ *
+ * This contains general information about dm device.
+ *
+ * <dict>
+ *     <key>command</key>
+ *     <string>...</string>
+ *
+ *     <key>event_nr</key>
+ *     <integer>...</integer>
+ *
+ *     <key>name</key>
+ *     <string>...</string>
+ *
+ *     <key>uuid</key>
+ *     <string>...</string>
+ *
+ *     <key>dev</key>
+ *     <integer></integer> 
+ *
+ *     <key>flags</key>
+ *     <integer></integer>
+ *
+ *     <key>version</key>
+ *      <array>
+ *       <integer>...</integer>
+ *       <integer>...</integer>
+ *       <integer>...</integer>
+ *      </array>
+ *
+ *      <key>cmd_data</key>
+ *       <array>
+ *        <!-- See below for command
+ *             specific dictionaries -->
+ *       </array>
+ * </dict>
+ *
+ * Available commands from _cmd_data_v4.
+ *
+ * create, reload, remove, remove_all, suspend,
+ * resume, info, deps, rename, version, status,
+ * table, waitevent, names, clear, mknodes,
+ * targets, message, setgeometry
+ *
+ */
+
+/*
+ * DM_LIST_VERSIONS command dictionary entry.
+ * Lists all available targets with their version.
+ *
+ * <array>
+ *   <dict>
+ *    <key>name<key>
+ *    <string>...</string>
+ *
+ *    <key>version</key>
+ *      <array>
+ *       <integer>...</integer>
+ *       <integer>...</integer>
+ *       <integer>...</integer>
+ *      </array>
+ *   </dict>
+ * </array>
+ *
+ */
+
+#define DM_IOCTL_COMMAND      "command"
+#define DM_IOCTL_VERSION      "version"
+#define DM_IOCTL_OPEN         "open_count"
+#define DM_IOCTL_MINOR        "minor"
+#define DM_IOCTL_NAME         "name"
+#define DM_IOCTL_UUID         "uuid"
+#define DM_IOCTL_TARGET_COUNT "target_count"
+#define DM_IOCTL_EVENT        "event_nr"
+#define DM_IOCTL_FLAGS        "flags"
+#define DM_IOCTL_CMD_DATA     "cmd_data"
+
+#define DM_TARGETS_NAME       "name"
+#define DM_TARGETS_VERSION    "ver"
+
+#define DM_DEV_NEWNAME        "newname"
+#define DM_DEV_NAME           "name"
+#define DM_DEV_DEV            "dev"
+
+#define DM_TABLE_TYPE         "type"
+#define DM_TABLE_START        "start"
+#define DM_TABLE_STAT         "status"
+#define DM_TABLE_LENGTH       "length"
+#define DM_TABLE_PARAMS       "params"
+
+
+/* Status bits */
+#define DM_READONLY_FLAG	(1 << 0) /* In/Out */
+#define DM_SUSPEND_FLAG		(1 << 1) /* In/Out */
+#define DM_EXISTS_FLAG          (1 << 2) /* In/Out */ /* XXX. This flag is undocumented. */ 
+#define DM_PERSISTENT_DEV_FLAG	(1 << 3) /* In */
+
+/*
+ * Flag passed into ioctl STATUS command to get table information
+ * rather than current status.
+ */
+#define DM_STATUS_TABLE_FLAG	(1 << 4) /* In */
+
+/*
+ * Flags that indicate whether a table is present in either of
+ * the two table slots that a device has.
+ */
+#define DM_ACTIVE_PRESENT_FLAG   (1 << 5) /* Out */
+#define DM_INACTIVE_PRESENT_FLAG (1 << 6) /* Out */
+
+/*
+ * Indicates that the buffer passed in wasn't big enough for the
+ * results.
+ */
+#define DM_BUFFER_FULL_FLAG	(1 << 8) /* Out */
+
+/*
+ * This flag is now ignored.
+ */
+#define DM_SKIP_BDGET_FLAG	(1 << 9) /* In */
+
+/*
+ * Set this to avoid attempting to freeze any filesystem when suspending.
+ */
+#define DM_SKIP_LOCKFS_FLAG	(1 << 10) /* In */
+
+/*
+ * Set this to suspend without flushing queued ios.
+ */
+#define DM_NOFLUSH_FLAG		(1 << 11) /* In */
+
+
+#ifdef __LIB_DEVMAPPER__
+
+#  define MAJOR(x) major((x))
+#  define MINOR(x) minor((x))
+#  define MKDEV(x,y) makedev((x),(y))
+
+/* Name of device-mapper driver in kernel */
+#define DM_NAME "dm"
+
+/* Types for nbsd_get_dm_major */
+#define DM_CHAR_MAJOR 1
+#define DM_BLOCK_MAJOR 2	
+
+/* libdm_netbsd.c */
+
+int nbsd_get_dm_major(uint32_t *, int); /* Get dm device major numbers */
+
+int nbsd_dmi_add_cmd(const char *, prop_dictionary_t);
+int nbsd_dmi_add_version(const int [3], prop_dictionary_t);
+int nbsd_dm_add_uint(const char *, uint64_t, prop_dictionary_t);
+int nbsd_dm_add_str(const char *, char *, prop_dictionary_t );
+
+struct dm_ioctl* nbsd_dm_dict_to_dmi(prop_dictionary_t, const int);
+
+#endif /* __LIB_DEVMAPPER__ */
+
+#endif /* __NETBSD_DM_H__ */
Index: src/external/gpl2/lvm2tools/lib/libdevmapper/shlib_version
===================================================================
RCS file: src/external/gpl2/lvm2tools/lib/libdevmapper/shlib_version
diff -N src/external/gpl2/lvm2tools/lib/libdevmapper/shlib_version
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/lib/libdevmapper/shlib_version	16 Dec 2008 00:40:59 -0000	1.1.2.1
@@ -0,0 +1,2 @@
+major=0
+minor=0
Index: src/external/gpl2/lvm2tools/lib/liblvm/Makefile
===================================================================
RCS file: src/external/gpl2/lvm2tools/lib/liblvm/Makefile
diff -N src/external/gpl2/lvm2tools/lib/liblvm/Makefile
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/lib/liblvm/Makefile	16 Dec 2008 01:17:12 -0000	1.1.2.4
@@ -0,0 +1,63 @@
+#	$NetBSD: Makefile,v 1.1.2.4 2008/12/16 01:17:12 haad Exp $
+
+LIBISPRIVATE=	yes
+
+USE_FORT?=	no
+NOLINT=		#defined
+
+.include "../../lvm2tools.mk"
+
+LIB=		lvm
+
+CPPFLAGS+=	-I${LVM2TOOLS_DISTDIR}/lib -I${LVM2TOOLS_DISTDIR}/include \
+		-I. 
+
+SRCS+=		activate.c lvmcache.c toolcontext.c config.c btree.c \
+		str_list.c dev-cache.c dev-io.c dev-md.c device.c \
+		display.c errseg.c filter-composite.c \
+		filter-persistent.c \
+		filter-regex.c filter-sysfs.c filter-md.c archive.c \
+		archiver.c export.c flags.c format-text.c import.c \
+		import_vsn1.c tags.c text_label.c freeseg.c label.c \
+		file_locking.c locking.c no_locking.c log.c lv_manip.c \
+		merge.c metadata.c mirror.c pv_manip.c pv_map.c segtype.c \
+		snapshot_manip.c crc.c lvm-exec.c lvm-file.c lvm-string.c \
+		lvm-wrappers.c timestamp.c util.c memlock.c report.c \
+		striped.c uuid.c zero.c disk-rep.c format1.c import-export.c \
+		import-extents.c layout.c lvm1-label.c vg_number.c \
+		disk_rep.c format_pool.c import_export.c pool_label.c \
+		filter_netbsd.c snapshot.c mirrored.c dev_manager.c fs.c dev.c \
+		lvm-globals.c
+
+LDADD+=		-lprop
+
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/activate
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/cache
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/commands
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/config
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/datastruct
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/device
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/display
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/error
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/filters
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/format1
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/format_pool
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/format_text
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/freeseg
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/label
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/locking
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/log
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/metadata
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/mirror
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/misc
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/mm
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/report
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/snapshot
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/striped
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/uuid
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/zero
+.PATH:	${LVM2TOOLS_DISTDIR}/lib/netbsd
+
+.include <bsd.lib.mk>
+.include <bsd.subdir.mk>
Index: src/external/gpl2/lvm2tools/sbin/Makefile
===================================================================
RCS file: src/external/gpl2/lvm2tools/sbin/Makefile
diff -N src/external/gpl2/lvm2tools/sbin/Makefile
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/sbin/Makefile	16 Dec 2008 00:43:53 -0000	1.1.2.3
@@ -0,0 +1,5 @@
+#	$NetBSD: Makefile,v 1.1.2.3 2008/12/16 00:43:53 haad Exp $
+
+SUBDIR= dmsetup	lvm
+
+.include <bsd.subdir.mk>
Index: src/external/gpl2/lvm2tools/sbin/dmsetup/Makefile
===================================================================
RCS file: src/external/gpl2/lvm2tools/sbin/dmsetup/Makefile
diff -N src/external/gpl2/lvm2tools/sbin/dmsetup/Makefile
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/sbin/dmsetup/Makefile	16 Dec 2008 00:41:34 -0000	1.1.2.1
@@ -0,0 +1,31 @@
+#	$NetBSD: Makefile,v 1.1.2.1 2008/12/16 00:41:34 haad Exp $
+
+USE_FORT?=	no
+NOLINT=		#defined
+
+.include "../../lvm2tools.mk"
+
+.PATH:  ${LVM2TOOLS_DISTDIR}/man
+
+PROG=		dmsetup
+
+MAN=		dmsetup.8
+MLINKS=		dmsetup.8 dmsetup.1
+
+BINDIR=		/sbin
+
+CPPFLAGS+=      -I${LIBDM_SRCDIR}/ -I${LIBDM_SRCDIR}/misc \
+		-I. -I${LIBDM_SRCDIR}/ioctl -I${LVM2TOOLS_DISTDIR}/include
+
+CPPFLAGS+=	-D__LIB_DEVMAPPER__ -DDM_DEVICE_UID=0 \
+		-DDM_DEVICE_GID=0 -DDM_DEVICE_MODE=0600
+
+LIBDM_OBJDIR!=	cd ${LVM2TOOLS_SRCDIR}/lib/libdevmapper && ${PRINTOBJDIR}
+LDADD+=		-L${LIBDM_OBJDIR} -ldevmapper
+DPADD+=		${LIBDM_OBJDIR}/libdevmapper.a
+
+LDADD+=		-lprop
+
+.PATH:	${LVM2TOOLS_DISTDIR}/tools
+
+.include <bsd.prog.mk>
Index: src/external/gpl2/lvm2tools/sbin/lvm/Makefile
===================================================================
RCS file: src/external/gpl2/lvm2tools/sbin/lvm/Makefile
diff -N src/external/gpl2/lvm2tools/sbin/lvm/Makefile
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/external/gpl2/lvm2tools/sbin/lvm/Makefile	16 Dec 2008 01:17:12 -0000	1.1.2.7
@@ -0,0 +1,102 @@
+
+
+USE_FORT?=	no
+NOLINT=		#defined
+
+.include "../../lvm2tools.mk"
+
+.PATH:	${LVM2TOOLS_DISTDIR}/man
+
+PROG=		lvm
+
+BINDIR=		/sbin
+
+SRCS=		dumpconfig.c formats.c lvchange.c lvconvert.c lvcreate.c \
+		lvdisplay.c lvextend.c lvmchange.c lvmcmdline.c \
+		lvmdiskscan.c lvreduce.c lvremove.c lvrename.c lvresize.c \
+		lvscan.c polldaemon.c pvchange.c pvck.c pvcreate.c \
+		pvdisplay.c pvmove.c pvremove.c pvresize.c pvscan.c \
+		reporter.c segtypes.c toollib.c vgcfgbackup.c \
+		vgcfgrestore.c vgchange.c vgck.c vgconvert.c vgcreate.c \
+		vgdisplay.c vgexport.c vgextend.c vgimport.c vgmerge.c \
+		vgmknodes.c vgreduce.c vgremove.c vgrename.c vgscan.c \
+		vgsplit.c lvm.c
+
+CFLAGS+= 	-fno-inline
+
+CPPFLAGS+=	-I${LVM2TOOLS_DISTDIR}/lib -I${LVM2TOOLS_DISTDIR}/include \
+		-I. -I${LIBDM_INCLUDE} -I${LVM2TOOLS_DISTDIR}/tools -I${LVM2TOOLS_DISTDIR}/libdm
+
+CPPFLAGS+=	-DLVM_SHARED_PATH=\"$(BINDIR)/lvm\"
+
+
+MAN= 		lvchange.8 lvconvert.8 lvcreate.8 lvdisplay.8 lvextend.8 \
+		lvm.8 lvm.conf.5 lvmchange.8 lvmdiskscan.8 lvmdump.8 \
+		lvreduce.8 lvremove.8 lvrename.8 lvresize.8 lvs.8 \
+		lvscan.8 pvchange.8 pvck.8 pvcreate.8 pvdisplay.8 \
+		pvmove.8 pvremove.8 pvresize.8 pvs.8 pvscan.8 \
+		vgcfgbackup.8 vgcfgrestore.8 vgchange.8 vgck.8 vgconvert.8 \
+		vgcreate.8 vgdisplay.8 vgexport.8 vgextend.8 vgimport.8 \
+		vgmerge.8 vgmknodes.8 vgreduce.8 vgremove.8 vgrename.8 \
+		vgs.8 vgscan.8 vgsplit.8
+
+
+MKLINKS+=	lvchange.8 lvchange.1 \
+                lvconvert.8 lvconvert.1 \
+                lvcreate.8 lvcreate.1 \
+                lvdisplay.8 lvdisplay.1 \
+                lvextend.8 lvextend.1 \
+                lvm.8 lvm.1 \
+                lvm.conf lvm.1 \
+                lvmchange.8 lvmchange.1 \
+                lvmdiskscan.8 lvmdiskscan.1 \
+                lvmdump.8 lvmdump.1 \
+                lvreduce.8 lvreduce.1 \
+                lvremove.8 lvremove.1 \
+                lvrename.8 lvrename.1 \
+                lvresize.8 lvresize.1 \
+                lvs.8 lvs.1 \
+                lvscan.8 lvscan.1 \
+                pvchange.8 pvchange.1 \
+                pvck.8 pvck.1 \
+                pvcreate.8 pvcreate.1 \
+                pvdisplay.8 pvdisplay.1 \
+                pvmove.8 pvmove.1 \
+                pvremove.8 pvremove.1 \
+                pvresize.8 pvresize.1 \
+                pvs.8 pvs.1 \
+                pvscan.8 pvscan.1 \
+                vgcfgbackup.8 vgcfgbackup.1 \
+                vgcfgrestore.8 vgcfgrestore.1 \
+                vgchange.8 vgchange.1 \
+                vgck.8 vgck.1 \
+                vgconvert.8 vgconvert.1 \
+                vgcreate.8 vgcreate.1 \
+                vgdisplay.8 vgdisplay.1 \
+                vgexport.8 vgexport.1 \
+                vgextend.8 vgextend.1 \
+                vgimport.8 vgimport.1 \
+                vgmerge.8 vgmerge.1 \
+                vgmknodes.8 vgmknodes.1 \
+                vgreduce.8 vgreduce.1 \
+                vgremove.8 vgremove.1 \
+                vgrename.8 vgrename.1 \
+                vgs.8 vgs.1 \
+                vgscan.8 vgscan.1 \
+                vgsplit.8 vgsplit.1
+
+LIBLVM_OBJDIR!= cd ${LVM2TOOLS_SRCDIR}/lib/liblvm && ${PRINTOBJDIR}
+LDADD+=         -L${LIBLVM_OBJDIR} -llvm
+DPADD+=         ${LIBLVM_OBJDIR}/liblvm.a
+
+LIBDM_OBJDIR!=  cd ${LVM2TOOLS_SRCDIR}/lib/libdevmapper && ${PRINTOBJDIR}
+LDADD+=         -L${LIBDM_OBJDIR} -ldevmapper
+DPADD+=         ${LIBDM_OBJDIR}/libdevmapper.a
+
+LDADD+=		-lprop
+
+
+.PATH:	${LVM2TOOLS_DISTDIR}/tools
+
+
+.include <bsd.prog.mk>
