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 + +.if (${MKLVM} != "no") +SUBDIR+= lvm2tools +.endif + +.include 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 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 + +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. + + + Copyright (C) + + 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. + + , 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. + + + Copyright (C) + + 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. + + , 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
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 filter to dmsetup table/status/ls. + Add --exec 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 &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 +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#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 if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + 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 +#include +#include +#include +/* 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 to if __STDC__ is defined, since + # 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 +#else +# include +#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 +_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 to if __STDC__ is defined, since + # 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 +#else +# include +#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 +_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 +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 +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 +#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 +#include +#include +#include + +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 + +_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 + +_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 +#include +#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 +#include +#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 +#include +#include + +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 +#include + +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 +#include + +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 declares $ac_func. + For example, HP-UX 11i 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 to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 +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 +# define alloca _alloca +# else +# ifdef HAVE_ALLOCA_H +# include +# 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 declares $ac_func. + For example, HP-UX 11i 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 to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 declares $ac_func. + For example, HP-UX 11i 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 to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 +#ifdef HAVE_VFORK_H +# include +#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 , but some compilers + (e.g. gcc -O) don't grok . 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 +#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 declares $ac_func. + For example, HP-UX 11i 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 to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 +#include + +#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 +# 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 declares pow. + For example, HP-UX 11i declares gettimeofday. */ +#define pow innocuous_pow + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char pow (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 declares $ac_func. + For example, HP-UX 11i 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 to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 declares _doprnt. + For example, HP-UX 11i declares gettimeofday. */ +#define _doprnt innocuous__doprnt + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char _doprnt (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 declares $ac_func. + For example, HP-UX 11i 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 to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 declares $ac_func. + For example, HP-UX 11i 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 to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 +#endif +#ifdef HAVE_SYS_SOCKET_H +# include +#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 declares $ac_func. + For example, HP-UX 11i 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 to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 ." + +_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 >$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 >$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 < /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 . +# Please send patches to . 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 ." + +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 /* 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 + + 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 + #include + + 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 + 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 + #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' /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 + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # 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 < +# include +#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 + 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 +# 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 < 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 . 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 ." + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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= 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 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +# 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 +# include +# 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#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; inodeid = joined_list[i].nodeid; + dm_hash_insert_binary(node_hash, + (char *)&ninfo->nodeid, + OPENAIS_CSID_LEN, ninfo); + } + } + ninfo->state = NODE_CLVMD; + } + + for (i=0; istate = NODE_DOWN; + } + + for (i=0; inodeid = 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 Command timeout (default 60 seconds)\n"); + fprintf(file, " -T 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for htonl, ntohl */ + +#ifdef linux +# include + +# 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 + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* 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 + +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include /* 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, ¶ms); + + 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 +#include +#include +#include +#include +#include +#include + +#include /* 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, ¶ms); + 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_.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 and it should be used (not on Ultrix). + */ +/* #undef HAVE_ALLOCA_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ASM_BYTEORDER_H */ + +/* Define to 1 if you have the 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 header file. */ +#define HAVE_CTYPE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DIRENT_H 1 + +/* Define to 1 if you have the 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 header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the 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 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 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 header file. */ +#define HAVE_LIBGEN_H 1 + +/* Define to 1 if you have the 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 header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LINUX_FS_H */ + +/* Define to 1 if you have the 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 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 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 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 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 header file, and it defines `DIR'. */ +/* #undef HAVE_NDIR_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETDB_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETINET_IN_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PTHREAD_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_READLINE_HISTORY_H */ + +/* Define to 1 if you have the 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 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 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 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 header file. */ +#define HAVE_STDARG_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDDEF_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the 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 header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the 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 header file. */ +#define HAVE_SYSLOG_H 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_DIR_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_DISK_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_FILE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_MMAN_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_MOUNT_H */ + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_NDIR_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SELECT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SOCKET_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STATVFS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_UIO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_UN_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UTSNAME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define to 1 if you have the 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 header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the 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 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 and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to 1 if your 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 does not define. */ +/* #undef mode_t */ + +/* Define to `long int' if does not define. */ +/* #undef off_t */ + +/* Define to `int' if does not define. */ +/* #undef pid_t */ + +/* Define to `unsigned int' if 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 + +#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 + +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 +#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], 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 + +#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 +# 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 + +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 +#include +#include +#include +#include +#include + +#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 + +/* + * 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 +#include +#include + +#ifdef linux +# include +#endif + +#include +#include +#include +#include + +/***************************************************************** + * 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 /* FILE */ +#include /* strerror() */ +#include + +#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 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 +#include + +#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 +#include + +/* 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 + +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 +#include + +/* + * 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 +# include +#else +# include +# 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 +# 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 +#include +#include + +#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 +#include + +#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, ¶ms); + /* 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, ¶ms); + 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, + ¶ms); + 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 +#include +#include +#include +#include + +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 +#include +#include +#include +#include + +#ifdef linux +# include +#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 +#include + +/* + * 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 +#include +#include +#include +#include + +#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 + +/* + * 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 +#include + +/* 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 +#include +#include + +#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 +#include +#include +#include +#include + +#ifdef linux +# define u64 uint64_t /* Missing without __KERNEL__ */ +# undef WNOHANG /* Avoid redefinition */ +# undef WUNTRACED /* Avoid redefinition */ +# include /* 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 +# include +# include +#else +# include +# 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 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +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 + +#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 + +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 + +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 +#include +#include + +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], 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 + +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 +#include +#include +#include +#include + +#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 + +#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 + +#include +#include +#include +#include +#include + +#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 + +#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 + +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 +#include + +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 + +/* 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 +#include + +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 +#include +#include +#include +#include +#include + +#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 _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 ? : ""); + 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 + +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 +#include +#include + +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 +#include +#include +#include +#include + +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 + +/* + * 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 +#include + +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 +#include +#include + +/* 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, §or, 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, §or, 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 +#include +#include +#include +#include + +#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 +#include +#include +#include +#include +#include + +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 +#include +#include +#include +#include + +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 + +/* + * 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 +#include + +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("", 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 /* FILE */ +#include /* strerror() */ +#include + +#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 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: + * also, more than 4k + * say, reiserfs puts it's superblock 32k in, IIRC + * 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(¤t->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 + +/* + * 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, 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 + +/* + * 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)+ / */ + 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 and it should be used (not on Ultrix). + */ +#undef HAVE_ALLOCA_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ASM_BYTEORDER_H + +/* Define to 1 if you have the 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 header file. */ +#undef HAVE_CTYPE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_DIRENT_H + +/* Define to 1 if you have the 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 header file. */ +#undef HAVE_ERRNO_H + +/* Define to 1 if you have the 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 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 header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if dynamic libraries are available. */ +#undef HAVE_LIBDL + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBGEN_H + +/* Define to 1 if you have the 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 header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_FS_H + +/* Define to 1 if you have the 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 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 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 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 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 header file, and it defines `DIR'. */ +#undef HAVE_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETDB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_PTHREAD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_READLINE_HISTORY_H + +/* Define to 1 if you have the 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 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 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 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 header file. */ +#undef HAVE_STDARG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDDEF_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDIO_H + +/* Define to 1 if you have the 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 header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the 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 header file. */ +#undef HAVE_SYSLOG_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_DIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_DISK_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_FILE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MMAN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MOUNT_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SELECT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STATVFS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UTSNAME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_WAIT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TERMIOS_H + +/* Define to 1 if you have the 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 header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the 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 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 and . */ +#undef TIME_WITH_SYS_TIME + +/* Define to 1 if your 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 does not define. */ +#undef mode_t + +/* Define to `long int' if does not define. */ +#undef off_t + +/* Define to `int' if does not define. */ +#undef pid_t + +/* Define to `unsigned int' if 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 +# 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 + +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 +#include +#include +#include +#include +#include + +#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 +#include + +/* + * 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 +#include +#include +#include +#include + +/* + * 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 + +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 + +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); +} + +/* + * -- or if !layer just -. + */ +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 --, 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 +#include + +#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 + +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 +#include +#include + +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 + +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 + +#include "timestamp.h" + +/* + * The realtime section uses clock_gettime with the CLOCK_MONOTONIC + * parameter to prevent issues with time warps + */ +#ifdef HAVE_REALTIME + +#include +#include + +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 + +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 +#include +#include +#include +#include +#include + +#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 +# include +#else +# include +# 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 +# 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 +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include + +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 +#include +#include + +#ifdef linux +# include +#endif + +#include +#include +#include +#include + +/***************************************************************** + * 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 +#include +#include +#include + +#ifdef linux +# include +#endif + +#ifdef HAVE_SELINUX +# include +#endif + +#ifdef __NetBSD__ +#include +#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, ¤t_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 +#include + +#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 +#include +#include + +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 + +/* + * 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 + +/* + * 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 + +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 + +/* + * 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 + +/* + * 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 +#include + +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 +#include +#include +#include + +#ifdef linux +# include "kdev_t.h" +# include +#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 +#include + +#include +#include +#include + +#include + +#include + +/* + * 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 +#include + +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 +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include + +#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 **)¶ms); + + 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 +#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 +#include + +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 +#include + +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 +#include + +/* + * 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 []] [\-C] [\-h] +[\-R] +[\-t ] +[\-T ] +[\-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 [] +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 +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 +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 []] [\-C] [\-h] +[\-R] +[\-t ] +[\-T ] +[\-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 [] +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 +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 +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_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_file] +.br +.B dmsetup clear +.I device_name +.br +.B dmsetup reload +.I device_name [--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\ [+]|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\
+.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_file] +.br +Creates a device with the given name. +If table_file or
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/. +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_file] +.br +Loads
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_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_file] +.br +.B dmsetup clear +.I device_name +.br +.B dmsetup reload +.I device_name [--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\ [+]|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\
+.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_file] +.br +Creates a device with the given name. +If table_file or
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/. +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_file] +.br +Loads
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\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\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 \n" +"Language-Team: LANGUAGE \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 , 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 \n" +"Language-Team: LANGUAGE \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 "" +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 ' 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 [] []" + echo "" + echo "|UNDO location of the cluster locking shared library. (no default)" + echo " UNDO will reset the locking back to local" + echo " name of the LVM config file (default: /etc/lvm/lvm.conf)" + echo " 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 - < $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 +# +# 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 +## +## 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 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 " + echo "" + echo "Commands:" + echo "Enable clvm: --enable-cluster [--lockinglibdir ] [--lockinglib ]" + echo "Disable clvm: --disable-cluster" + echo "Set locking library: --lockinglibdir [--lockinglib ]" + echo "" + echo "Global options:" + echo "Config file location: --file " + 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 - < $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 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 " + +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 + 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 [ B<-h|--help> ] [ B<-v|--verbose> ] [ B<-c|--lvmconf> I ] [ B<-m|--modules> "I" ] [ B<-e|--extra> "I" ] [ B<-r|--raid> "I" ] +[ B<-R|--raidconf> I ] [ B<-M|--makedev> I