[Ocfs-tools-commits] rev 2 - in trunk: . advanced advanced/sizetest bugfix debugocfs format format/inc fsck libocfs libocfs/Common libocfs/Common/inc libocfs/Linux libocfs/Linux/inc load_ocfs ocfs_uid_gen ocfstool vendor vendor/common vendor/redhat vendor/unitedlinux

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Thu Jan 29 02:00:05 CST 2004


Author: manish
Date: 2004-01-29 02:00:03 -0600 (Thu, 29 Jan 2004)
New Revision: 2

Added:
   trunk/COPYING
   trunk/Config.make.in
   trunk/Makefile
   trunk/Postamble.make
   trunk/Preamble.make
   trunk/README
   trunk/advanced/
   trunk/advanced/sizetest/
   trunk/advanced/sizetest/Makefile
   trunk/advanced/sizetest/disk.txt
   trunk/advanced/sizetest/diskstructs.c
   trunk/advanced/sizetest/net.txt
   trunk/advanced/sizetest/netstructs.c
   trunk/advanced/sizetest/sizetest.c
   trunk/advanced/sizetest/sizetest.h
   trunk/autogen.sh
   trunk/bugfix/
   trunk/bugfix/Makefile
   trunk/bugfix/bug3016598-README.txt
   trunk/bugfix/bug3016598.c
   trunk/bugfix/bug3123542-README.txt
   trunk/bugfix/bug3123542.c
   trunk/bugfix/generic.c
   trunk/bugfix/ver.c
   trunk/config.guess
   trunk/config.sub
   trunk/configure.in
   trunk/debugocfs/
   trunk/debugocfs/Cscope.make
   trunk/debugocfs/Makefile
   trunk/debugocfs/debugocfs.1.in
   trunk/debugocfs/debugocfs.c
   trunk/debugocfs/debugocfs.h
   trunk/debugocfs/debugocfs.txt
   trunk/debugocfs/extfinder.c
   trunk/debugocfs/io.c
   trunk/debugocfs/libdebugocfs.c
   trunk/debugocfs/libdebugocfs.h
   trunk/debugocfs/main.c
   trunk/debugocfs/print.c
   trunk/debugocfs/test.c
   trunk/format/
   trunk/format/Cscope.make
   trunk/format/Makefile
   trunk/format/format.c
   trunk/format/frmtport.c
   trunk/format/inc/
   trunk/format/inc/format.h
   trunk/format/inc/frmtport.h
   trunk/format/inc/resize.h
   trunk/format/mkfs.ocfs.1.in
   trunk/format/mounted.c
   trunk/format/resize.c
   trunk/format/resizeocfs.1.in
   trunk/fsck/
   trunk/fsck/Cscope.make
   trunk/fsck/Makefile
   trunk/fsck/class_print.c
   trunk/fsck/class_rw.c
   trunk/fsck/classes.h
   trunk/fsck/defaults.c
   trunk/fsck/defaults.h
   trunk/fsck/fsck.c
   trunk/fsck/fsck.h
   trunk/fsck/fsck.ocfs.1.in
   trunk/fsck/fsck_io.c
   trunk/fsck/fsck_print.c
   trunk/fsck/fsck_print.h
   trunk/fsck/layout.c
   trunk/fsck/layout.h
   trunk/fsck/mkgetconst
   trunk/fsck/parse.c
   trunk/fsck/sig.c
   trunk/fsck/sig.h
   trunk/fsck/ver.c
   trunk/fsck/verify.c
   trunk/fsck/verify.h
   trunk/install-sh
   trunk/libocfs/
   trunk/libocfs/Common/
   trunk/libocfs/Common/inc/
   trunk/libocfs/Common/inc/ocfs.h
   trunk/libocfs/Common/inc/ocfsbool.h
   trunk/libocfs/Common/inc/ocfscom.h
   trunk/libocfs/Common/inc/ocfsconst.h
   trunk/libocfs/Common/inc/ocfsdef.h
   trunk/libocfs/Common/inc/ocfsdisk.h
   trunk/libocfs/Common/inc/ocfsdlm.h
   trunk/libocfs/Common/inc/ocfserr.h
   trunk/libocfs/Common/inc/ocfsgenalloc.h
   trunk/libocfs/Common/inc/ocfsgencreate.h
   trunk/libocfs/Common/inc/ocfsgendirnode.h
   trunk/libocfs/Common/inc/ocfsgendlm.h
   trunk/libocfs/Common/inc/ocfsgenmisc.h
   trunk/libocfs/Common/inc/ocfsgennm.h
   trunk/libocfs/Common/inc/ocfsgensysfile.h
   trunk/libocfs/Common/inc/ocfsgentrans.h
   trunk/libocfs/Common/inc/ocfsgenutil.h
   trunk/libocfs/Common/inc/ocfsgenvolcfg.h
   trunk/libocfs/Common/inc/ocfsgenvote.h
   trunk/libocfs/Common/inc/ocfsheartbeat.h
   trunk/libocfs/Common/inc/ocfstrace.h
   trunk/libocfs/Common/inc/ocfstrans.h
   trunk/libocfs/Common/inc/ocfsver.h
   trunk/libocfs/Common/inc/ocfsvol.h
   trunk/libocfs/Common/ocfsgenalloc.c
   trunk/libocfs/Common/ocfsgencreate.c
   trunk/libocfs/Common/ocfsgendirnode.c
   trunk/libocfs/Common/ocfsgendlm.c
   trunk/libocfs/Common/ocfsgenmisc.c
   trunk/libocfs/Common/ocfsgennm.c
   trunk/libocfs/Common/ocfsgensysfile.c
   trunk/libocfs/Common/ocfsgentrans.c
   trunk/libocfs/Common/ocfsgenutil.c
   trunk/libocfs/Common/ocfsgenvolcfg.c
   trunk/libocfs/Common/ocfsheartbeat.c
   trunk/libocfs/Linux/
   trunk/libocfs/Linux/inc/
   trunk/libocfs/Linux/inc/ocfsbitmap.h
   trunk/libocfs/Linux/inc/ocfsdlmp.h
   trunk/libocfs/Linux/inc/ocfsfile.h
   trunk/libocfs/Linux/inc/ocfshash.h
   trunk/libocfs/Linux/inc/ocfsioctl.h
   trunk/libocfs/Linux/inc/ocfsiosup.h
   trunk/libocfs/Linux/inc/ocfsipc.h
   trunk/libocfs/Linux/inc/ocfsmain.h
   trunk/libocfs/Linux/inc/ocfsmount.h
   trunk/libocfs/Linux/inc/ocfsport.h
   trunk/libocfs/Linux/inc/ocfsproc.h
   trunk/libocfs/Linux/ocfsbitmap.c
   trunk/libocfs/Linux/ocfsdlm.c
   trunk/libocfs/Linux/ocfsfile.c
   trunk/libocfs/Linux/ocfshash.c
   trunk/libocfs/Linux/ocfsmount.c
   trunk/libocfs/Linux/ocfsport.c
   trunk/libocfs/Makefile
   trunk/libocfs/bindraw.c
   trunk/libocfs/libocfs.c
   trunk/libocfs/libocfs.h
   trunk/load_ocfs/
   trunk/load_ocfs/Makefile
   trunk/load_ocfs/load_ocfs
   trunk/load_ocfs/load_ocfs.1.in
   trunk/mkinstalldirs
   trunk/ocfs_uid_gen/
   trunk/ocfs_uid_gen/Makefile
   trunk/ocfs_uid_gen/ocfs_uid_gen
   trunk/ocfs_uid_gen/ocfs_uid_gen.1.in
   trunk/ocfstool/
   trunk/ocfstool/Makefile
   trunk/ocfstool/ocfsbitmap.c
   trunk/ocfstool/ocfsbitmap.h
   trunk/ocfstool/ocfsbrowser.c
   trunk/ocfstool/ocfsbrowser.h
   trunk/ocfstool/ocfscellmap.c
   trunk/ocfstool/ocfscellmap.h
   trunk/ocfstool/ocfsformat.c
   trunk/ocfstool/ocfsformat.h
   trunk/ocfstool/ocfsfreespace.c
   trunk/ocfstool/ocfsfreespace.h
   trunk/ocfstool/ocfsgenconfig.c
   trunk/ocfstool/ocfsgenconfig.h
   trunk/ocfstool/ocfsgeneral.c
   trunk/ocfstool/ocfsgeneral.h
   trunk/ocfstool/ocfsguiutil.c
   trunk/ocfstool/ocfsguiutil.h
   trunk/ocfstool/ocfsmount.c
   trunk/ocfstool/ocfsmount.h
   trunk/ocfstool/ocfsnodemap.c
   trunk/ocfstool/ocfsnodemap.h
   trunk/ocfstool/ocfsplist.c
   trunk/ocfstool/ocfsplist.h
   trunk/ocfstool/ocfsprocess.c
   trunk/ocfstool/ocfsprocess.h
   trunk/ocfstool/ocfstool.1.in
   trunk/ocfstool/ocfstool.c
   trunk/vendor/
   trunk/vendor/Makefile
   trunk/vendor/common/
   trunk/vendor/common/Makefile
   trunk/vendor/common/ocfs-tools.spec.in
   trunk/vendor/redhat/
   trunk/vendor/redhat/Makefile
   trunk/vendor/redhat/ocfs.init
   trunk/vendor/unitedlinux/
   trunk/vendor/unitedlinux/Makefile
   trunk/vendor/unitedlinux/ocfs.init
Log:
Initial import


Added: trunk/COPYING
===================================================================
--- trunk/COPYING	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/COPYING	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.

Added: trunk/Config.make.in
===================================================================
--- trunk/Config.make.in	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/Config.make.in	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,56 @@
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+
+DIST_VERSION = @DIST_VERSION@
+RPM_VERSION = @RPM_VERSION@
+
+MAJOR_VERSION = @MAJOR_VERSION@
+MINOR_VERSION = @MINOR_VERSION@
+MICRO_VERSION = @MICRO_VERSION@
+EXTRA_VERSION = @EXTRA_VERSION@
+
+SHELL = @SHELL@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+mandir = @mandir@
+
+top_builddir = .
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+LN_S = @LN_S@
+
+CC = @CC@
+CPP = @CPP@
+AR = @AR@
+RANLIB = @RANLIB@
+
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_LIBS = @GTK_LIBS@
+
+OCFSTOOL = @OCFSTOOL@
+
+OCFS_DEBUG = @OCFS_DEBUG@
+OCFS_MEMDEBUG = @OCFS_MEMDEBUG@
+OCFS_TRACE = @OCFS_TRACE@
+OCFS_PROCESSOR = @OCFS_PROCESSOR@
+
+RPMBUILD = @RPMBUILD@
+RPM_TOPDIR = @RPM_TOPDIR@
+
+TOOLSARCH = @TOOLSARCH@

Added: trunk/Makefile
===================================================================
--- trunk/Makefile	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/Makefile	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,48 @@
+TOPDIR = .
+ 
+include $(TOPDIR)/Preamble.make
+
+SUBDIRS = libocfs debugocfs format fsck bugfix load_ocfs ocfs_uid_gen
+
+ifdef OCFSTOOL
+SUBDIRS += ocfstool
+endif
+
+SUBDIRS += vendor
+
+DIST_FILES = \
+	COPYING		\
+	README		\
+	Config.make.in	\
+	Preamble.make	\
+	Postamble.make	\
+	aclocal.m4	\
+	config.guess	\
+	config.sub	\
+	configure	\
+	configure.in	\
+	install-sh	\
+	mkinstalldirs
+
+.PHONY: dist dist-bye dist-fresh distclean
+
+dist-bye:
+	-rm -rf $(DIST_TOPDIR)
+
+dist-fresh: dist-bye
+	$(TOPDIR)/mkinstalldirs $(DIST_TOPDIR)
+
+dist: dist-fresh dist-all
+	GZIP=$(GZIP_OPTS) tar chozf $(DIST_TOPDIR).tar.gz $(DIST_TOPDIR)
+	$(MAKE) dist-bye
+
+distclean: clean
+	rm -f Config.make config.status config.cache config.log
+
+srpm: dist
+	$(RPMBUILD) -bs --define "_sourcedir $(RPM_TOPDIR)" --define "_srcrpmdir $(RPM_TOPDIR)" $(TOPDIR)/vendor/common/ocfs-tools.spec
+
+rpm: srpm
+	$(RPMBUILD) --rebuild --target $(TOOLSARCH) "ocfs-tools-$(DIST_VERSION)-$(RPM_VERSION).src.rpm"
+
+include $(TOPDIR)/Postamble.make

Added: trunk/Postamble.make
===================================================================
--- trunk/Postamble.make	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/Postamble.make	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,153 @@
+ifdef VERSION_SRC
+
+ifndef VERSION_FILES
+$(error Need VERSION_FILES defined for version objects)
+endif
+
+ifndef VERSION_PREFIX
+$(error Need VERSION_PREFIX defined for version objects)
+endif
+
+VERSION_OBJ = $(subst .c,.o,$(VERSION_SRC))
+
+VERSION_NUM = $(VERSION_PREFIX)_BUILD_VERSION
+VERSION_DATE = $(VERSION_PREFIX)_BUILD_DATE
+VERSION_MD5 = $(VERSION_PREFIX)_BUILD_MD5
+
+VERDEFS = -D$(VERSION_NUM)=\""$(VERSION)"\" \
+	  -D$(VERSION_DATE)=\""$(shell LANG=C date)"\" \
+	  -D$(VERSION_MD5)=\""$(shell cat stamp-md5)"\"
+
+VERMAGIC = $(if $(filter $(VERSION_OBJ),$@),$(VERDEFS))
+
+ifneq ($(MAKECMDGOALS),install)
+VERSTAMP = stamp
+endif
+
+stamp: ;
+
+stamp-md5: $(VERSION_FILES)
+	@cat $(VERSION_FILES) Makefile | md5sum | sed -e 's/ .*//' > stamp-md5
+
+$(VERSION_OBJ): stamp-md5 $(VERSTAMP)
+endif
+
+
+LOCAL_CFLAGS = $($(subst /,_,$(basename $@))_CFLAGS)
+LOCAL_CPPFLAGS = $($(subst /,_,$(basename $@))_CPPFLAGS)
+
+%.o: %.c
+	$(CC) $(CFLAGS) $(LOCAL_CFLAGS) $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(INCLUDES) $(DEFINES) $(VERMAGIC) -o $@ -c $<
+
+%.p: %.c
+	$(CC) $(CFLAGS) $(LOCAL_CFLAGS) $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(INCLUDES) $(DEFINES) $(VERMAGIC) -E -o $@ -c $<
+
+%.s: %.c
+	$(CC) $(CFLAGS) $(LOCAL_CFLAGS) $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(INCLUDES) $(DEFINES) $(VERMAGIC) -S -o $@ -c $<
+
+
+
+.PHONY: subdirs $(SUBDIRS)
+subdirs: $(SUBDIRS)
+
+$(SUBDIRS):
+	$(MAKE) -C $@
+
+.PHONY: all-rules
+all-rules: subdirs $(LIBRARIES) $(BIN_PROGRAMS) $(SBIN_PROGRAMS) $(MODULES) $(MANS)
+
+
+INSTALL_SUBDIRS = $(addsuffix -install,$(SUBDIRS))
+
+.PHONY: install-rules install-subdirs $(INSTALL_RULES) install-bin-programs install-bin-extra install-sbin-programs install-sbin-extra
+
+install-subdirs: $(INSTALL_SUBDIRS)
+
+$(INSTALL_SUBDIRS):
+	$(MAKE) -C $(subst -install,,$@) install
+
+install-bin-programs: $(BIN_PROGRAMS)
+ifdef BIN_PROGRAMS
+	$(SHELL) $(TOPDIR)/mkinstalldirs $(DESTDIR)$(bindir)
+	for prog in $(BIN_PROGRAMS); do \
+	  $(INSTALL_PROGRAM) $$prog $(DESTDIR)$(bindir)/$$prog; \
+	done
+endif
+
+install-bin-extra: $(BIN_EXTRA)
+ifdef BIN_EXTRA
+	$(SHELL) $(TOPDIR)/mkinstalldirs $(DESTDIR)$(bindir)
+	for prog in $(BIN_EXTRA); do \
+	  $(INSTALL_PROGRAM) $$prog $(DESTDIR)$(bindir)/$$prog; \
+	done
+endif
+
+install-sbin-programs: $(SBIN_PROGRAMS)
+ifdef SBIN_PROGRAMS
+	$(SHELL) $(TOPDIR)/mkinstalldirs $(DESTDIR)$(sbindir)
+	for prog in $(SBIN_PROGRAMS); do \
+	  $(INSTALL_PROGRAM) $$prog $(DESTDIR)$(sbindir)/$$prog; \
+	done
+endif
+
+install-sbin-extra: $(SBIN_EXTRA)
+ifdef SBIN_EXTRA
+	$(SHELL) $(TOPDIR)/mkinstalldirs $(DESTDIR)$(sbindir)
+	for prog in $(SBIN_EXTRA); do \
+	  $(INSTALL_PROGRAM) $$prog $(DESTDIR)$(sbindir)/$$prog; \
+	done
+endif
+
+install-mans: $(MANS)
+ifdef MANS
+	$(SHELL) $(TOPDIR)/mkinstalldirs $(DESTDIR)$(mandir)
+	for man in $(MANS); do \
+	  dir=`echo $$man | sed -e 's/^.*\\./man/'`; \
+	  $(SHELL) $(TOPDIR)/mkinstalldirs $(DESTDIR)$(mandir)/$$dir; \
+	  $(INSTALL_DATA) $$man $(DESTDIR)$(mandir)/$$dir/$$man; \
+	done
+endif
+
+install-rules: install-subdirs $(INSTALL_RULES) install-bin-programs install-bin-extra install-sbin-programs install-sbin-extra install-mans
+
+
+CLEAN_SUBDIRS = $(addsuffix -clean,$(SUBDIRS))
+
+.PHONY: clean clean-subdirs $(CLEAN_RULES) $(CLEAN_SUBDIRS)
+
+clean-subdirs: $(CLEAN_SUBDIRS)
+
+$(CLEAN_SUBDIRS):
+	$(MAKE) -C $(subst -clean,,$@) clean
+
+clean: clean-subdirs $(CLEAN_RULES)
+	rm -f *.o *.p core $(BIN_PROGRAMS) $(SBIN_PROGRAMS) $(LIBRARIES) stamp-md5
+
+
+DIST_SUBDIRS = $(addsuffix -dist,$(SUBDIRS))
+
+.PHONY: dist-all dist-mkdir dist-copy dist-subdirs $(DIST_RULES) $(DIST_SUBDIRS)
+
+dist-subdirs: $(DIST_SUBDIRS)
+
+$(DIST_SUBDIRS):
+	$(MAKE) -C $(subst -dist,,$@) dist-all \
+	  DIST_CURDIR=$(DIST_CURDIR)/$(subst -dist,,$@)
+
+dist-mkdir:
+	$(SHELL) $(TOPDIR)/mkinstalldirs $(DIST_DIR)
+
+DIST_ALL_FILES = Makefile $(BIN_EXTRA) $(SBIN_EXTRA) $(MANS) $(VERSION_FILES) $(DIST_FILES)
+
+dist-copy: dist-mkdir $(DIST_ALL_FILES) $(DIST_RULES)
+	@for file in $(DIST_ALL_FILES); do \
+	  echo " cp -p $$file $(DIST_DIR)/$$file"; \
+	  cp -p $$file $(DIST_DIR)/$$file; \
+        done
+
+dist-all: dist-copy dist-subdirs
+	 
+
+ifeq (Cscope.make,$(wildcard Cscope.make))
+include Cscope.make
+endif

Added: trunk/Preamble.make
===================================================================
--- trunk/Preamble.make	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/Preamble.make	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,43 @@
+ifeq ($(TOPDIR)/Config.make,$(wildcard $(TOPDIR)/Config.make))
+include $(TOPDIR)/Config.make
+else
+.PHONY: dummy-notconfigured
+dummy-notconfigured:
+	@echo "Please run the configure script first"
+endif
+
+LIBRARIES =
+PROGRAMS =
+MODULES =
+MANS =
+
+INSTALL_RULES =
+
+CLEAN_FILES =
+CLEAN_RULES = 
+
+DIST_FILES =
+DIST_RULES =
+
+INCLUDES =
+DEFINES = 
+
+CFLAGS += $($(subst /,_,$(basename $@))_CFLAGS)
+CFLAGS += -pipe
+
+LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
+
+VERSION_FILES =
+VERSION_PREFIX =
+VERSION_SRC =
+
+DIST_TOPDIR = $(TOPDIR)/$(PACKAGE)-$(DIST_VERSION)
+DIST_CURDIR = .
+DIST_DIR = $(DIST_TOPDIR)/$(DIST_CURDIR)
+
+GZIP_OPTS = --best
+
+.PHONY: all strip install
+all: all-rules
+strip: strip-rules
+install: install-rules

Added: trunk/README
===================================================================
--- trunk/README	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/README	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1 @@
+These are common tools for ocfs v1 and v2.

Added: trunk/advanced/sizetest/Makefile
===================================================================
--- trunk/advanced/sizetest/Makefile	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/advanced/sizetest/Makefile	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,51 @@
+TOPDIR = ../..
+
+include $(TOPDIR)/Preamble.make
+
+DEFINES=-DMODULE -DLINUX -D__KERNEL__
+CFLAGS=-I../../libocfs/Common/inc -I$(INC) -I../../libocfs/Linux/inc
+LDADD=-nostdlib
+
+OPTIMIZE = -O2
+
+ifeq ($(OCFS_PROCESSOR),x86_64)
+  CFLAGS += -m64
+endif
+ifeq ($(OCFS_PROCESSOR),ia64)
+endif
+ifeq ($(OCFS_PROCESSOR),i686)
+endif
+
+ifdef OCFS_DEBUG
+  CFLAGS += -g
+  DEFINES += -DDEBUG
+endif
+
+CFLAGS += $(DEFINES) -w
+
+DIST_RULES = dist-incdir
+
+VERSION_FILES = diskstructs.c netstructs.c
+VERSION_SRC = diskstructs.c netstructs.c
+VERSION_PREFIX = OCFS
+
+BIN_PROGRAMS = diskstructs netstructs sizetest hexsizetest
+
+all: diskstructs netstructs sizetest hexsizetest
+
+diskstructs: diskstructs.c
+	$(LINK)
+
+netstructs: netstructs.c
+	$(LINK)
+
+sizetest: sizetest.c
+	$(LINK)
+
+hexsizetest: sizetest.c
+	$(LINK) -DUSE_HEX
+
+dist-incdir:
+	$(TOPDIR)/mkinstalldirs $(DIST_DIR)/inc
+
+include $(TOPDIR)/Postamble.make

Added: trunk/advanced/sizetest/disk.txt
===================================================================
--- trunk/advanced/sizetest/disk.txt	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/advanced/sizetest/disk.txt	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,940 @@
+sizeof(ocfs_alloc_ext) = 24
+	file_off = 0 (8)
+	num_bytes = 8 (8)
+	disk_off = 16 (8)
+
+sizeof(ocfs_publish) = 84
+	time = 0 (8)
+	vote = 8 (4)
+	dirty = 12 (4)
+	vote_type = 16 (4)
+	vote_map = 20 (8)
+	publ_seq_num = 28 (8)
+	dir_ent = 36 (8)
+	hbm[i] = 44 (1)
+	hbm[i] = 45 (1)
+	hbm[i] = 46 (1)
+	hbm[i] = 47 (1)
+	hbm[i] = 48 (1)
+	hbm[i] = 49 (1)
+	hbm[i] = 50 (1)
+	hbm[i] = 51 (1)
+	hbm[i] = 52 (1)
+	hbm[i] = 53 (1)
+	hbm[i] = 54 (1)
+	hbm[i] = 55 (1)
+	hbm[i] = 56 (1)
+	hbm[i] = 57 (1)
+	hbm[i] = 58 (1)
+	hbm[i] = 59 (1)
+	hbm[i] = 60 (1)
+	hbm[i] = 61 (1)
+	hbm[i] = 62 (1)
+	hbm[i] = 63 (1)
+	hbm[i] = 64 (1)
+	hbm[i] = 65 (1)
+	hbm[i] = 66 (1)
+	hbm[i] = 67 (1)
+	hbm[i] = 68 (1)
+	hbm[i] = 69 (1)
+	hbm[i] = 70 (1)
+	hbm[i] = 71 (1)
+	hbm[i] = 72 (1)
+	hbm[i] = 73 (1)
+	hbm[i] = 74 (1)
+	hbm[i] = 75 (1)
+	comm_seq_num = 76 (8)
+
+sizeof(ocfs_vote) = 52
+	vote[i] = 0 (1)
+	vote[i] = 1 (1)
+	vote[i] = 2 (1)
+	vote[i] = 3 (1)
+	vote[i] = 4 (1)
+	vote[i] = 5 (1)
+	vote[i] = 6 (1)
+	vote[i] = 7 (1)
+	vote[i] = 8 (1)
+	vote[i] = 9 (1)
+	vote[i] = 10 (1)
+	vote[i] = 11 (1)
+	vote[i] = 12 (1)
+	vote[i] = 13 (1)
+	vote[i] = 14 (1)
+	vote[i] = 15 (1)
+	vote[i] = 16 (1)
+	vote[i] = 17 (1)
+	vote[i] = 18 (1)
+	vote[i] = 19 (1)
+	vote[i] = 20 (1)
+	vote[i] = 21 (1)
+	vote[i] = 22 (1)
+	vote[i] = 23 (1)
+	vote[i] = 24 (1)
+	vote[i] = 25 (1)
+	vote[i] = 26 (1)
+	vote[i] = 27 (1)
+	vote[i] = 28 (1)
+	vote[i] = 29 (1)
+	vote[i] = 30 (1)
+	vote[i] = 31 (1)
+	vote_seq_num = 32 (8)
+	dir_ent = 40 (8)
+	open_handle = 48 (1)
+
+sizeof(ocfs_file_entry) = 484
+	disk_lock = 0 (48)
+	signature = 48 (8)
+	local_ext = 56 (4)
+	next_free_ext = 60 (1)
+	next_del = 61 (1)
+	granularity = 64 (4)
+	filename = 68 (255)
+	filename_len = 324 (2)
+	file_size = 328 (8)
+	alloc_size = 336 (8)
+	create_time = 344 (8)
+	modify_time = 352 (8)
+	extents[i] = 360 (24)
+	extents[i] = 384 (24)
+	extents[i] = 408 (24)
+	dir_node_ptr = 432 (8)
+	this_sector = 440 (8)
+	last_ext_ptr = 448 (8)
+	sync_flags = 456 (4)
+	link_cnt = 460 (4)
+	attribs = 464 (4)
+	prot_bits = 468 (4)
+	uid = 472 (4)
+	gid = 476 (4)
+	dev_major = 480 (2)
+	dev_minor = 482 (2)
+
+sizeof(ocfs_index_node) = 20
+	down_ptr = 0 (8)
+	file_ent_ptr = 8 (8)
+	name_len = 16 (1)
+	name = 17 (1)
+
+sizeof(ocfs_index_hdr) = 508
+	disk_lock = 0 (48)
+	signature = 48 (8)
+	up_tree_ptr = 56 (8)
+	node_disk_off = 64 (8)
+	state = 72 (1)
+	down_ptr = 76 (8)
+	num_ents = 84 (1)
+	depth = 85 (1)
+	num_ent_used = 86 (1)
+	dir_node_flags = 87 (1)
+	sync_flags = 88 (1)
+	index = 89 (256)
+	reserved = 345 (161)
+	file_ent = 506 (1)
+
+sizeof(ocfs_dir_node) = 512
+	disk_lock = 0 (48)
+	signature = 48 (8)
+	alloc_file_off = 56 (8)
+	alloc_node = 64 (4)
+	free_node_ptr = 68 (8)
+	node_disk_off = 76 (8)
+	next_node_ptr = 84 (8)
+	indx_node_ptr = 92 (8)
+	next_del_ent_node = 100 (8)
+	head_del_ent_node = 108 (8)
+	first_del = 116 (1)
+	num_del = 117 (1)
+	num_ents = 118 (1)
+	depth = 119 (1)
+	num_ent_used = 120 (1)
+	dir_node_flags = 121 (1)
+	sync_flags = 122 (1)
+	index = 123 (256)
+	index_dirty = 379 (1)
+	bad_off = 380 (1)
+	reserved = 381 (127)
+	file_ent = 508 (1)
+
+sizeof(ocfs_extent_group) = 504
+	signature = 0 (8)
+	next_free_ext = 8 (4)
+	curr_sect = 12 (4)
+	max_sects = 16 (4)
+	type = 20 (4)
+	granularity = 24 (4)
+	alloc_node = 28 (4)
+	this_ext = 32 (8)
+	next_data_ext = 40 (8)
+	alloc_file_off = 48 (8)
+	last_ext_ptr = 56 (8)
+	up_hdr_node_ptr = 64 (8)
+	extents[i] = 72 (24)
+	extents[i] = 96 (24)
+	extents[i] = 120 (24)
+	extents[i] = 144 (24)
+	extents[i] = 168 (24)
+	extents[i] = 192 (24)
+	extents[i] = 216 (24)
+	extents[i] = 240 (24)
+	extents[i] = 264 (24)
+	extents[i] = 288 (24)
+	extents[i] = 312 (24)
+	extents[i] = 336 (24)
+	extents[i] = 360 (24)
+	extents[i] = 384 (24)
+	extents[i] = 408 (24)
+	extents[i] = 432 (24)
+	extents[i] = 456 (24)
+	extents[i] = 480 (24)
+
+sizeof(ocfs_bitmap_lock) = 52
+	disk_lock = 0 (48)
+	used_bits = 48 (4)
+
+sizeof(ocfs_offset_map) = 20
+	length = 0 (4)
+	log_disk_off = 4 (8)
+	actual_disk_off = 12 (8)
+
+sizeof(ocfs_vol_disk_hdr) = 440
+	minor_version = 0 (4)
+	major_version = 4 (4)
+	signature = 8 (128)
+	mount_point = 136 (128)
+	serial_num = 264 (8)
+	device_size = 272 (8)
+	start_off = 280 (8)
+	bitmap_off = 288 (8)
+	publ_off = 296 (8)
+	vote_off = 304 (8)
+	root_bitmap_off = 312 (8)
+	data_start_off = 320 (8)
+	root_bitmap_size = 328 (8)
+	root_off = 336 (8)
+	root_size = 344 (8)
+	cluster_size = 352 (8)
+	num_nodes = 360 (8)
+	num_clusters = 368 (8)
+	dir_node_size = 376 (8)
+	file_node_size = 384 (8)
+	internal_off = 392 (8)
+	node_cfg_off = 400 (8)
+	node_cfg_size = 408 (8)
+	new_cfg_off = 416 (8)
+	prot_bits = 424 (4)
+	uid = 428 (4)
+	gid = 432 (4)
+	excl_mount = 436 (4)
+
+sizeof(ocfs_disk_lock) = 48
+	curr_master = 0 (4)
+	file_lock = 4 (1)
+	last_write_time = 8 (8)
+	last_read_time = 16 (8)
+	writer_node_num = 24 (4)
+	reader_node_num = 28 (4)
+	oin_node_map = 32 (8)
+	dlock_seq_num = 40 (8)
+
+sizeof(ocfs_vol_label) = 200
+	disk_lock = 0 (48)
+	label = 48 (64)
+	label_len = 112 (2)
+	vol_id = 114 (16)
+	vol_id_len = 130 (2)
+	cluster_name = 132 (64)
+	cluster_name_len = 196 (2)
+
+sizeof(ocfs_ipc_config_info) = 76
+	type = 0 (1)
+	ip_addr = 1 (33)
+	ip_port = 36 (4)
+	ip_mask = 40 (33)
+
+sizeof(ocfs_guid) = 32
+	guid = 0 (32)
+	id.host_id = 0 (20)
+	id.mac_id = 20 (12)
+
+sizeof(ocfs_disk_node_config_info) = 192
+	disk_lock = 0 (48)
+	node_name = 48 (33)
+	guid = 81 (32)
+	ipc_config = 116 (76)
+
+sizeof(ocfs_node_config_hdr) = 76
+	disk_lock = 0 (48)
+	signature = 48 (8)
+	version = 56 (4)
+	num_nodes = 60 (4)
+	last_node = 64 (4)
+	cfg_seq_num = 68 (8)
+
+sizeof(ocfs_cdsl) = 1032
+	name = 0 (1024)
+	flags = 1024 (4)
+	operation = 1028 (4)
+
+sizeof(ocfs_free_bitmap) = 24
+	length = 0 (8)
+	file_off = 8 (8)
+	type = 16 (4)
+	node_num = 20 (4)
+
+sizeof(ocfs_free_extent_log) = 16
+	index = 0 (4)
+	disk_off = 8 (8)
+
+sizeof(ocfs_free_log) = 3608
+	num_free_upds = 0 (4)
+	free_bitmap[i] = 8 (24)
+	free_bitmap[i] = 32 (24)
+	free_bitmap[i] = 56 (24)
+	free_bitmap[i] = 80 (24)
+	free_bitmap[i] = 104 (24)
+	free_bitmap[i] = 128 (24)
+	free_bitmap[i] = 152 (24)
+	free_bitmap[i] = 176 (24)
+	free_bitmap[i] = 200 (24)
+	free_bitmap[i] = 224 (24)
+	free_bitmap[i] = 248 (24)
+	free_bitmap[i] = 272 (24)
+	free_bitmap[i] = 296 (24)
+	free_bitmap[i] = 320 (24)
+	free_bitmap[i] = 344 (24)
+	free_bitmap[i] = 368 (24)
+	free_bitmap[i] = 392 (24)
+	free_bitmap[i] = 416 (24)
+	free_bitmap[i] = 440 (24)
+	free_bitmap[i] = 464 (24)
+	free_bitmap[i] = 488 (24)
+	free_bitmap[i] = 512 (24)
+	free_bitmap[i] = 536 (24)
+	free_bitmap[i] = 560 (24)
+	free_bitmap[i] = 584 (24)
+	free_bitmap[i] = 608 (24)
+	free_bitmap[i] = 632 (24)
+	free_bitmap[i] = 656 (24)
+	free_bitmap[i] = 680 (24)
+	free_bitmap[i] = 704 (24)
+	free_bitmap[i] = 728 (24)
+	free_bitmap[i] = 752 (24)
+	free_bitmap[i] = 776 (24)
+	free_bitmap[i] = 800 (24)
+	free_bitmap[i] = 824 (24)
+	free_bitmap[i] = 848 (24)
+	free_bitmap[i] = 872 (24)
+	free_bitmap[i] = 896 (24)
+	free_bitmap[i] = 920 (24)
+	free_bitmap[i] = 944 (24)
+	free_bitmap[i] = 968 (24)
+	free_bitmap[i] = 992 (24)
+	free_bitmap[i] = 1016 (24)
+	free_bitmap[i] = 1040 (24)
+	free_bitmap[i] = 1064 (24)
+	free_bitmap[i] = 1088 (24)
+	free_bitmap[i] = 1112 (24)
+	free_bitmap[i] = 1136 (24)
+	free_bitmap[i] = 1160 (24)
+	free_bitmap[i] = 1184 (24)
+	free_bitmap[i] = 1208 (24)
+	free_bitmap[i] = 1232 (24)
+	free_bitmap[i] = 1256 (24)
+	free_bitmap[i] = 1280 (24)
+	free_bitmap[i] = 1304 (24)
+	free_bitmap[i] = 1328 (24)
+	free_bitmap[i] = 1352 (24)
+	free_bitmap[i] = 1376 (24)
+	free_bitmap[i] = 1400 (24)
+	free_bitmap[i] = 1424 (24)
+	free_bitmap[i] = 1448 (24)
+	free_bitmap[i] = 1472 (24)
+	free_bitmap[i] = 1496 (24)
+	free_bitmap[i] = 1520 (24)
+	free_bitmap[i] = 1544 (24)
+	free_bitmap[i] = 1568 (24)
+	free_bitmap[i] = 1592 (24)
+	free_bitmap[i] = 1616 (24)
+	free_bitmap[i] = 1640 (24)
+	free_bitmap[i] = 1664 (24)
+	free_bitmap[i] = 1688 (24)
+	free_bitmap[i] = 1712 (24)
+	free_bitmap[i] = 1736 (24)
+	free_bitmap[i] = 1760 (24)
+	free_bitmap[i] = 1784 (24)
+	free_bitmap[i] = 1808 (24)
+	free_bitmap[i] = 1832 (24)
+	free_bitmap[i] = 1856 (24)
+	free_bitmap[i] = 1880 (24)
+	free_bitmap[i] = 1904 (24)
+	free_bitmap[i] = 1928 (24)
+	free_bitmap[i] = 1952 (24)
+	free_bitmap[i] = 1976 (24)
+	free_bitmap[i] = 2000 (24)
+	free_bitmap[i] = 2024 (24)
+	free_bitmap[i] = 2048 (24)
+	free_bitmap[i] = 2072 (24)
+	free_bitmap[i] = 2096 (24)
+	free_bitmap[i] = 2120 (24)
+	free_bitmap[i] = 2144 (24)
+	free_bitmap[i] = 2168 (24)
+	free_bitmap[i] = 2192 (24)
+	free_bitmap[i] = 2216 (24)
+	free_bitmap[i] = 2240 (24)
+	free_bitmap[i] = 2264 (24)
+	free_bitmap[i] = 2288 (24)
+	free_bitmap[i] = 2312 (24)
+	free_bitmap[i] = 2336 (24)
+	free_bitmap[i] = 2360 (24)
+	free_bitmap[i] = 2384 (24)
+	free_bitmap[i] = 2408 (24)
+	free_bitmap[i] = 2432 (24)
+	free_bitmap[i] = 2456 (24)
+	free_bitmap[i] = 2480 (24)
+	free_bitmap[i] = 2504 (24)
+	free_bitmap[i] = 2528 (24)
+	free_bitmap[i] = 2552 (24)
+	free_bitmap[i] = 2576 (24)
+	free_bitmap[i] = 2600 (24)
+	free_bitmap[i] = 2624 (24)
+	free_bitmap[i] = 2648 (24)
+	free_bitmap[i] = 2672 (24)
+	free_bitmap[i] = 2696 (24)
+	free_bitmap[i] = 2720 (24)
+	free_bitmap[i] = 2744 (24)
+	free_bitmap[i] = 2768 (24)
+	free_bitmap[i] = 2792 (24)
+	free_bitmap[i] = 2816 (24)
+	free_bitmap[i] = 2840 (24)
+	free_bitmap[i] = 2864 (24)
+	free_bitmap[i] = 2888 (24)
+	free_bitmap[i] = 2912 (24)
+	free_bitmap[i] = 2936 (24)
+	free_bitmap[i] = 2960 (24)
+	free_bitmap[i] = 2984 (24)
+	free_bitmap[i] = 3008 (24)
+	free_bitmap[i] = 3032 (24)
+	free_bitmap[i] = 3056 (24)
+	free_bitmap[i] = 3080 (24)
+	free_bitmap[i] = 3104 (24)
+	free_bitmap[i] = 3128 (24)
+	free_bitmap[i] = 3152 (24)
+	free_bitmap[i] = 3176 (24)
+	free_bitmap[i] = 3200 (24)
+	free_bitmap[i] = 3224 (24)
+	free_bitmap[i] = 3248 (24)
+	free_bitmap[i] = 3272 (24)
+	free_bitmap[i] = 3296 (24)
+	free_bitmap[i] = 3320 (24)
+	free_bitmap[i] = 3344 (24)
+	free_bitmap[i] = 3368 (24)
+	free_bitmap[i] = 3392 (24)
+	free_bitmap[i] = 3416 (24)
+	free_bitmap[i] = 3440 (24)
+	free_bitmap[i] = 3464 (24)
+	free_bitmap[i] = 3488 (24)
+	free_bitmap[i] = 3512 (24)
+	free_bitmap[i] = 3536 (24)
+	free_bitmap[i] = 3560 (24)
+	free_bitmap[i] = 3584 (24)
+
+sizeof(ocfs_delete_log) = 32
+	node_num = 0 (8)
+	ent_del = 8 (8)
+	parent_dirnode_off = 16 (8)
+	flags = 24 (4)
+
+sizeof(ocfs_recovery_log) = 8
+	node_num = 0 (8)
+
+sizeof(ocfs_alloc_log) = 24
+	length = 0 (8)
+	file_off = 8 (8)
+	type = 16 (4)
+	node_num = 20 (4)
+
+sizeof(ocfs_dir_log) = 24
+	orig_off = 0 (8)
+	saved_off = 8 (8)
+	length = 16 (8)
+
+sizeof(ocfs_lock_log) = 7208
+	num_lock_upds = 0 (4)
+	lock_upd[i] = 8 (16)
+	lock_upd[i] = 24 (16)
+	lock_upd[i] = 40 (16)
+	lock_upd[i] = 56 (16)
+	lock_upd[i] = 72 (16)
+	lock_upd[i] = 88 (16)
+	lock_upd[i] = 104 (16)
+	lock_upd[i] = 120 (16)
+	lock_upd[i] = 136 (16)
+	lock_upd[i] = 152 (16)
+	lock_upd[i] = 168 (16)
+	lock_upd[i] = 184 (16)
+	lock_upd[i] = 200 (16)
+	lock_upd[i] = 216 (16)
+	lock_upd[i] = 232 (16)
+	lock_upd[i] = 248 (16)
+	lock_upd[i] = 264 (16)
+	lock_upd[i] = 280 (16)
+	lock_upd[i] = 296 (16)
+	lock_upd[i] = 312 (16)
+	lock_upd[i] = 328 (16)
+	lock_upd[i] = 344 (16)
+	lock_upd[i] = 360 (16)
+	lock_upd[i] = 376 (16)
+	lock_upd[i] = 392 (16)
+	lock_upd[i] = 408 (16)
+	lock_upd[i] = 424 (16)
+	lock_upd[i] = 440 (16)
+	lock_upd[i] = 456 (16)
+	lock_upd[i] = 472 (16)
+	lock_upd[i] = 488 (16)
+	lock_upd[i] = 504 (16)
+	lock_upd[i] = 520 (16)
+	lock_upd[i] = 536 (16)
+	lock_upd[i] = 552 (16)
+	lock_upd[i] = 568 (16)
+	lock_upd[i] = 584 (16)
+	lock_upd[i] = 600 (16)
+	lock_upd[i] = 616 (16)
+	lock_upd[i] = 632 (16)
+	lock_upd[i] = 648 (16)
+	lock_upd[i] = 664 (16)
+	lock_upd[i] = 680 (16)
+	lock_upd[i] = 696 (16)
+	lock_upd[i] = 712 (16)
+	lock_upd[i] = 728 (16)
+	lock_upd[i] = 744 (16)
+	lock_upd[i] = 760 (16)
+	lock_upd[i] = 776 (16)
+	lock_upd[i] = 792 (16)
+	lock_upd[i] = 808 (16)
+	lock_upd[i] = 824 (16)
+	lock_upd[i] = 840 (16)
+	lock_upd[i] = 856 (16)
+	lock_upd[i] = 872 (16)
+	lock_upd[i] = 888 (16)
+	lock_upd[i] = 904 (16)
+	lock_upd[i] = 920 (16)
+	lock_upd[i] = 936 (16)
+	lock_upd[i] = 952 (16)
+	lock_upd[i] = 968 (16)
+	lock_upd[i] = 984 (16)
+	lock_upd[i] = 1000 (16)
+	lock_upd[i] = 1016 (16)
+	lock_upd[i] = 1032 (16)
+	lock_upd[i] = 1048 (16)
+	lock_upd[i] = 1064 (16)
+	lock_upd[i] = 1080 (16)
+	lock_upd[i] = 1096 (16)
+	lock_upd[i] = 1112 (16)
+	lock_upd[i] = 1128 (16)
+	lock_upd[i] = 1144 (16)
+	lock_upd[i] = 1160 (16)
+	lock_upd[i] = 1176 (16)
+	lock_upd[i] = 1192 (16)
+	lock_upd[i] = 1208 (16)
+	lock_upd[i] = 1224 (16)
+	lock_upd[i] = 1240 (16)
+	lock_upd[i] = 1256 (16)
+	lock_upd[i] = 1272 (16)
+	lock_upd[i] = 1288 (16)
+	lock_upd[i] = 1304 (16)
+	lock_upd[i] = 1320 (16)
+	lock_upd[i] = 1336 (16)
+	lock_upd[i] = 1352 (16)
+	lock_upd[i] = 1368 (16)
+	lock_upd[i] = 1384 (16)
+	lock_upd[i] = 1400 (16)
+	lock_upd[i] = 1416 (16)
+	lock_upd[i] = 1432 (16)
+	lock_upd[i] = 1448 (16)
+	lock_upd[i] = 1464 (16)
+	lock_upd[i] = 1480 (16)
+	lock_upd[i] = 1496 (16)
+	lock_upd[i] = 1512 (16)
+	lock_upd[i] = 1528 (16)
+	lock_upd[i] = 1544 (16)
+	lock_upd[i] = 1560 (16)
+	lock_upd[i] = 1576 (16)
+	lock_upd[i] = 1592 (16)
+	lock_upd[i] = 1608 (16)
+	lock_upd[i] = 1624 (16)
+	lock_upd[i] = 1640 (16)
+	lock_upd[i] = 1656 (16)
+	lock_upd[i] = 1672 (16)
+	lock_upd[i] = 1688 (16)
+	lock_upd[i] = 1704 (16)
+	lock_upd[i] = 1720 (16)
+	lock_upd[i] = 1736 (16)
+	lock_upd[i] = 1752 (16)
+	lock_upd[i] = 1768 (16)
+	lock_upd[i] = 1784 (16)
+	lock_upd[i] = 1800 (16)
+	lock_upd[i] = 1816 (16)
+	lock_upd[i] = 1832 (16)
+	lock_upd[i] = 1848 (16)
+	lock_upd[i] = 1864 (16)
+	lock_upd[i] = 1880 (16)
+	lock_upd[i] = 1896 (16)
+	lock_upd[i] = 1912 (16)
+	lock_upd[i] = 1928 (16)
+	lock_upd[i] = 1944 (16)
+	lock_upd[i] = 1960 (16)
+	lock_upd[i] = 1976 (16)
+	lock_upd[i] = 1992 (16)
+	lock_upd[i] = 2008 (16)
+	lock_upd[i] = 2024 (16)
+	lock_upd[i] = 2040 (16)
+	lock_upd[i] = 2056 (16)
+	lock_upd[i] = 2072 (16)
+	lock_upd[i] = 2088 (16)
+	lock_upd[i] = 2104 (16)
+	lock_upd[i] = 2120 (16)
+	lock_upd[i] = 2136 (16)
+	lock_upd[i] = 2152 (16)
+	lock_upd[i] = 2168 (16)
+	lock_upd[i] = 2184 (16)
+	lock_upd[i] = 2200 (16)
+	lock_upd[i] = 2216 (16)
+	lock_upd[i] = 2232 (16)
+	lock_upd[i] = 2248 (16)
+	lock_upd[i] = 2264 (16)
+	lock_upd[i] = 2280 (16)
+	lock_upd[i] = 2296 (16)
+	lock_upd[i] = 2312 (16)
+	lock_upd[i] = 2328 (16)
+	lock_upd[i] = 2344 (16)
+	lock_upd[i] = 2360 (16)
+	lock_upd[i] = 2376 (16)
+	lock_upd[i] = 2392 (16)
+	lock_upd[i] = 2408 (16)
+	lock_upd[i] = 2424 (16)
+	lock_upd[i] = 2440 (16)
+	lock_upd[i] = 2456 (16)
+	lock_upd[i] = 2472 (16)
+	lock_upd[i] = 2488 (16)
+	lock_upd[i] = 2504 (16)
+	lock_upd[i] = 2520 (16)
+	lock_upd[i] = 2536 (16)
+	lock_upd[i] = 2552 (16)
+	lock_upd[i] = 2568 (16)
+	lock_upd[i] = 2584 (16)
+	lock_upd[i] = 2600 (16)
+	lock_upd[i] = 2616 (16)
+	lock_upd[i] = 2632 (16)
+	lock_upd[i] = 2648 (16)
+	lock_upd[i] = 2664 (16)
+	lock_upd[i] = 2680 (16)
+	lock_upd[i] = 2696 (16)
+	lock_upd[i] = 2712 (16)
+	lock_upd[i] = 2728 (16)
+	lock_upd[i] = 2744 (16)
+	lock_upd[i] = 2760 (16)
+	lock_upd[i] = 2776 (16)
+	lock_upd[i] = 2792 (16)
+	lock_upd[i] = 2808 (16)
+	lock_upd[i] = 2824 (16)
+	lock_upd[i] = 2840 (16)
+	lock_upd[i] = 2856 (16)
+	lock_upd[i] = 2872 (16)
+	lock_upd[i] = 2888 (16)
+	lock_upd[i] = 2904 (16)
+	lock_upd[i] = 2920 (16)
+	lock_upd[i] = 2936 (16)
+	lock_upd[i] = 2952 (16)
+	lock_upd[i] = 2968 (16)
+	lock_upd[i] = 2984 (16)
+	lock_upd[i] = 3000 (16)
+	lock_upd[i] = 3016 (16)
+	lock_upd[i] = 3032 (16)
+	lock_upd[i] = 3048 (16)
+	lock_upd[i] = 3064 (16)
+	lock_upd[i] = 3080 (16)
+	lock_upd[i] = 3096 (16)
+	lock_upd[i] = 3112 (16)
+	lock_upd[i] = 3128 (16)
+	lock_upd[i] = 3144 (16)
+	lock_upd[i] = 3160 (16)
+	lock_upd[i] = 3176 (16)
+	lock_upd[i] = 3192 (16)
+	lock_upd[i] = 3208 (16)
+	lock_upd[i] = 3224 (16)
+	lock_upd[i] = 3240 (16)
+	lock_upd[i] = 3256 (16)
+	lock_upd[i] = 3272 (16)
+	lock_upd[i] = 3288 (16)
+	lock_upd[i] = 3304 (16)
+	lock_upd[i] = 3320 (16)
+	lock_upd[i] = 3336 (16)
+	lock_upd[i] = 3352 (16)
+	lock_upd[i] = 3368 (16)
+	lock_upd[i] = 3384 (16)
+	lock_upd[i] = 3400 (16)
+	lock_upd[i] = 3416 (16)
+	lock_upd[i] = 3432 (16)
+	lock_upd[i] = 3448 (16)
+	lock_upd[i] = 3464 (16)
+	lock_upd[i] = 3480 (16)
+	lock_upd[i] = 3496 (16)
+	lock_upd[i] = 3512 (16)
+	lock_upd[i] = 3528 (16)
+	lock_upd[i] = 3544 (16)
+	lock_upd[i] = 3560 (16)
+	lock_upd[i] = 3576 (16)
+	lock_upd[i] = 3592 (16)
+	lock_upd[i] = 3608 (16)
+	lock_upd[i] = 3624 (16)
+	lock_upd[i] = 3640 (16)
+	lock_upd[i] = 3656 (16)
+	lock_upd[i] = 3672 (16)
+	lock_upd[i] = 3688 (16)
+	lock_upd[i] = 3704 (16)
+	lock_upd[i] = 3720 (16)
+	lock_upd[i] = 3736 (16)
+	lock_upd[i] = 3752 (16)
+	lock_upd[i] = 3768 (16)
+	lock_upd[i] = 3784 (16)
+	lock_upd[i] = 3800 (16)
+	lock_upd[i] = 3816 (16)
+	lock_upd[i] = 3832 (16)
+	lock_upd[i] = 3848 (16)
+	lock_upd[i] = 3864 (16)
+	lock_upd[i] = 3880 (16)
+	lock_upd[i] = 3896 (16)
+	lock_upd[i] = 3912 (16)
+	lock_upd[i] = 3928 (16)
+	lock_upd[i] = 3944 (16)
+	lock_upd[i] = 3960 (16)
+	lock_upd[i] = 3976 (16)
+	lock_upd[i] = 3992 (16)
+	lock_upd[i] = 4008 (16)
+	lock_upd[i] = 4024 (16)
+	lock_upd[i] = 4040 (16)
+	lock_upd[i] = 4056 (16)
+	lock_upd[i] = 4072 (16)
+	lock_upd[i] = 4088 (16)
+	lock_upd[i] = 4104 (16)
+	lock_upd[i] = 4120 (16)
+	lock_upd[i] = 4136 (16)
+	lock_upd[i] = 4152 (16)
+	lock_upd[i] = 4168 (16)
+	lock_upd[i] = 4184 (16)
+	lock_upd[i] = 4200 (16)
+	lock_upd[i] = 4216 (16)
+	lock_upd[i] = 4232 (16)
+	lock_upd[i] = 4248 (16)
+	lock_upd[i] = 4264 (16)
+	lock_upd[i] = 4280 (16)
+	lock_upd[i] = 4296 (16)
+	lock_upd[i] = 4312 (16)
+	lock_upd[i] = 4328 (16)
+	lock_upd[i] = 4344 (16)
+	lock_upd[i] = 4360 (16)
+	lock_upd[i] = 4376 (16)
+	lock_upd[i] = 4392 (16)
+	lock_upd[i] = 4408 (16)
+	lock_upd[i] = 4424 (16)
+	lock_upd[i] = 4440 (16)
+	lock_upd[i] = 4456 (16)
+	lock_upd[i] = 4472 (16)
+	lock_upd[i] = 4488 (16)
+	lock_upd[i] = 4504 (16)
+	lock_upd[i] = 4520 (16)
+	lock_upd[i] = 4536 (16)
+	lock_upd[i] = 4552 (16)
+	lock_upd[i] = 4568 (16)
+	lock_upd[i] = 4584 (16)
+	lock_upd[i] = 4600 (16)
+	lock_upd[i] = 4616 (16)
+	lock_upd[i] = 4632 (16)
+	lock_upd[i] = 4648 (16)
+	lock_upd[i] = 4664 (16)
+	lock_upd[i] = 4680 (16)
+	lock_upd[i] = 4696 (16)
+	lock_upd[i] = 4712 (16)
+	lock_upd[i] = 4728 (16)
+	lock_upd[i] = 4744 (16)
+	lock_upd[i] = 4760 (16)
+	lock_upd[i] = 4776 (16)
+	lock_upd[i] = 4792 (16)
+	lock_upd[i] = 4808 (16)
+	lock_upd[i] = 4824 (16)
+	lock_upd[i] = 4840 (16)
+	lock_upd[i] = 4856 (16)
+	lock_upd[i] = 4872 (16)
+	lock_upd[i] = 4888 (16)
+	lock_upd[i] = 4904 (16)
+	lock_upd[i] = 4920 (16)
+	lock_upd[i] = 4936 (16)
+	lock_upd[i] = 4952 (16)
+	lock_upd[i] = 4968 (16)
+	lock_upd[i] = 4984 (16)
+	lock_upd[i] = 5000 (16)
+	lock_upd[i] = 5016 (16)
+	lock_upd[i] = 5032 (16)
+	lock_upd[i] = 5048 (16)
+	lock_upd[i] = 5064 (16)
+	lock_upd[i] = 5080 (16)
+	lock_upd[i] = 5096 (16)
+	lock_upd[i] = 5112 (16)
+	lock_upd[i] = 5128 (16)
+	lock_upd[i] = 5144 (16)
+	lock_upd[i] = 5160 (16)
+	lock_upd[i] = 5176 (16)
+	lock_upd[i] = 5192 (16)
+	lock_upd[i] = 5208 (16)
+	lock_upd[i] = 5224 (16)
+	lock_upd[i] = 5240 (16)
+	lock_upd[i] = 5256 (16)
+	lock_upd[i] = 5272 (16)
+	lock_upd[i] = 5288 (16)
+	lock_upd[i] = 5304 (16)
+	lock_upd[i] = 5320 (16)
+	lock_upd[i] = 5336 (16)
+	lock_upd[i] = 5352 (16)
+	lock_upd[i] = 5368 (16)
+	lock_upd[i] = 5384 (16)
+	lock_upd[i] = 5400 (16)
+	lock_upd[i] = 5416 (16)
+	lock_upd[i] = 5432 (16)
+	lock_upd[i] = 5448 (16)
+	lock_upd[i] = 5464 (16)
+	lock_upd[i] = 5480 (16)
+	lock_upd[i] = 5496 (16)
+	lock_upd[i] = 5512 (16)
+	lock_upd[i] = 5528 (16)
+	lock_upd[i] = 5544 (16)
+	lock_upd[i] = 5560 (16)
+	lock_upd[i] = 5576 (16)
+	lock_upd[i] = 5592 (16)
+	lock_upd[i] = 5608 (16)
+	lock_upd[i] = 5624 (16)
+	lock_upd[i] = 5640 (16)
+	lock_upd[i] = 5656 (16)
+	lock_upd[i] = 5672 (16)
+	lock_upd[i] = 5688 (16)
+	lock_upd[i] = 5704 (16)
+	lock_upd[i] = 5720 (16)
+	lock_upd[i] = 5736 (16)
+	lock_upd[i] = 5752 (16)
+	lock_upd[i] = 5768 (16)
+	lock_upd[i] = 5784 (16)
+	lock_upd[i] = 5800 (16)
+	lock_upd[i] = 5816 (16)
+	lock_upd[i] = 5832 (16)
+	lock_upd[i] = 5848 (16)
+	lock_upd[i] = 5864 (16)
+	lock_upd[i] = 5880 (16)
+	lock_upd[i] = 5896 (16)
+	lock_upd[i] = 5912 (16)
+	lock_upd[i] = 5928 (16)
+	lock_upd[i] = 5944 (16)
+	lock_upd[i] = 5960 (16)
+	lock_upd[i] = 5976 (16)
+	lock_upd[i] = 5992 (16)
+	lock_upd[i] = 6008 (16)
+	lock_upd[i] = 6024 (16)
+	lock_upd[i] = 6040 (16)
+	lock_upd[i] = 6056 (16)
+	lock_upd[i] = 6072 (16)
+	lock_upd[i] = 6088 (16)
+	lock_upd[i] = 6104 (16)
+	lock_upd[i] = 6120 (16)
+	lock_upd[i] = 6136 (16)
+	lock_upd[i] = 6152 (16)
+	lock_upd[i] = 6168 (16)
+	lock_upd[i] = 6184 (16)
+	lock_upd[i] = 6200 (16)
+	lock_upd[i] = 6216 (16)
+	lock_upd[i] = 6232 (16)
+	lock_upd[i] = 6248 (16)
+	lock_upd[i] = 6264 (16)
+	lock_upd[i] = 6280 (16)
+	lock_upd[i] = 6296 (16)
+	lock_upd[i] = 6312 (16)
+	lock_upd[i] = 6328 (16)
+	lock_upd[i] = 6344 (16)
+	lock_upd[i] = 6360 (16)
+	lock_upd[i] = 6376 (16)
+	lock_upd[i] = 6392 (16)
+	lock_upd[i] = 6408 (16)
+	lock_upd[i] = 6424 (16)
+	lock_upd[i] = 6440 (16)
+	lock_upd[i] = 6456 (16)
+	lock_upd[i] = 6472 (16)
+	lock_upd[i] = 6488 (16)
+	lock_upd[i] = 6504 (16)
+	lock_upd[i] = 6520 (16)
+	lock_upd[i] = 6536 (16)
+	lock_upd[i] = 6552 (16)
+	lock_upd[i] = 6568 (16)
+	lock_upd[i] = 6584 (16)
+	lock_upd[i] = 6600 (16)
+	lock_upd[i] = 6616 (16)
+	lock_upd[i] = 6632 (16)
+	lock_upd[i] = 6648 (16)
+	lock_upd[i] = 6664 (16)
+	lock_upd[i] = 6680 (16)
+	lock_upd[i] = 6696 (16)
+	lock_upd[i] = 6712 (16)
+	lock_upd[i] = 6728 (16)
+	lock_upd[i] = 6744 (16)
+	lock_upd[i] = 6760 (16)
+	lock_upd[i] = 6776 (16)
+	lock_upd[i] = 6792 (16)
+	lock_upd[i] = 6808 (16)
+	lock_upd[i] = 6824 (16)
+	lock_upd[i] = 6840 (16)
+	lock_upd[i] = 6856 (16)
+	lock_upd[i] = 6872 (16)
+	lock_upd[i] = 6888 (16)
+	lock_upd[i] = 6904 (16)
+	lock_upd[i] = 6920 (16)
+	lock_upd[i] = 6936 (16)
+	lock_upd[i] = 6952 (16)
+	lock_upd[i] = 6968 (16)
+	lock_upd[i] = 6984 (16)
+	lock_upd[i] = 7000 (16)
+	lock_upd[i] = 7016 (16)
+	lock_upd[i] = 7032 (16)
+	lock_upd[i] = 7048 (16)
+	lock_upd[i] = 7064 (16)
+	lock_upd[i] = 7080 (16)
+	lock_upd[i] = 7096 (16)
+	lock_upd[i] = 7112 (16)
+	lock_upd[i] = 7128 (16)
+	lock_upd[i] = 7144 (16)
+	lock_upd[i] = 7160 (16)
+	lock_upd[i] = 7176 (16)
+	lock_upd[i] = 7192 (16)
+
+sizeof(ocfs_lock_update) = 16
+	orig_off = 0 (8)
+	new_off = 8 (8)
+
+sizeof(ocfs_bcast_rel_log) = 8
+	lock_id = 0 (8)
+
+sizeof(ocfs_cleanup_record) = 7224
+	log_id = 0 (8)
+	log_type = 8 (4)
+	rec.lock = 16 (7208)
+	rec.alloc = 16 (24)
+	rec.bcast = 16 (8)
+	rec.del = 16 (32)
+	rec.free = 16 (3608)
+
+sizeof(ocfs_log_record) = 48
+	log_id = 0 (8)
+	log_type = 8 (4)
+	rec.dir = 16 (24)
+	rec.alloc = 16 (24)
+	rec.recovery = 16 (8)
+	rec.bcast = 16 (8)
+	rec.del = 16 (32)
+	rec.extent = 16 (16)
+

Added: trunk/advanced/sizetest/diskstructs.c
===================================================================
--- trunk/advanced/sizetest/diskstructs.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/advanced/sizetest/diskstructs.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,632 @@
+/*
+ * diskstructs.c
+ *
+ * Prints sizes and offsets of structures and its elements.
+ * Useful to ensure cross platform compatibility.
+ *
+ * Copyright (C) 2003 Oracle Corporation.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Sunil Mushran, Manish Singh, Wim Coekaerts
+ */
+
+#include "sizetest.h"
+
+bool show_all = false;
+
+void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr)
+{
+    return;
+}
+
+static void print_ocfs_offset_map()
+{
+	ocfs_offset_map s;
+
+	SHOW_SIZEOF(ocfs_offset_map, s);
+	if (show_all) {
+		SHOW_OFFSET(length, s);
+		SHOW_OFFSET(log_disk_off, s);
+		SHOW_OFFSET(actual_disk_off, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_cleanup_record()
+{
+	ocfs_cleanup_record s;
+
+	SHOW_SIZEOF(ocfs_cleanup_record, s);
+	if (show_all) {
+		SHOW_OFFSET(log_id, s);
+		SHOW_OFFSET(log_type, s);;
+		SHOW_OFFSET(rec.lock, s);
+		SHOW_OFFSET(rec.alloc, s);
+		SHOW_OFFSET(rec.bcast, s);
+		SHOW_OFFSET(rec.del, s);
+		SHOW_OFFSET(rec.free, s);
+		printf("\n");
+	}
+}
+
+
+void usage(void)
+{
+	printf("usage: diskstructs [all]\n");
+	return ;
+}
+
+
+static void print_ocfs_alloc_ext()
+{
+	ocfs_alloc_ext s;
+
+	SHOW_SIZEOF(ocfs_alloc_ext, s);
+	if (show_all) {
+		SHOW_OFFSET(file_off, s);
+		SHOW_OFFSET(num_bytes, s);
+		SHOW_OFFSET(disk_off, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_publish()
+{
+	ocfs_publish s;
+	int i;
+
+	SHOW_SIZEOF(ocfs_publish, s);
+	if (show_all) {
+		SHOW_OFFSET(time, s);
+		SHOW_OFFSET(vote, s);
+		SHOW_OFFSET(dirty, s);
+		SHOW_OFFSET(vote_type, s);
+		SHOW_OFFSET(vote_map, s);
+		SHOW_OFFSET(publ_seq_num, s);
+		SHOW_OFFSET(dir_ent, s);
+		for (i = 0; i < OCFS_MAXIMUM_NODES; ++i)
+			SHOW_OFFSET(hbm[i], s);
+		SHOW_OFFSET(comm_seq_num, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_vote()
+{
+	ocfs_vote s;
+	int i;
+
+	SHOW_SIZEOF(ocfs_vote, s);
+	if (show_all) {
+		for (i = 0; i < OCFS_MAXIMUM_NODES; ++i)
+			SHOW_OFFSET(vote[i], s);
+		SHOW_OFFSET(vote_seq_num, s);
+		SHOW_OFFSET(dir_ent, s);
+		SHOW_OFFSET(open_handle, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_file_entry()
+{
+	ocfs_file_entry s;
+	int i;
+
+	SHOW_SIZEOF(ocfs_file_entry, s);
+	if (show_all) {
+		SHOW_OFFSET(disk_lock, s);
+		SHOW_OFFSET(signature, s);
+		SHOW_OFFSET(local_ext, s);
+		SHOW_OFFSET(next_free_ext, s);
+		SHOW_OFFSET(next_del, s);
+		SHOW_OFFSET(granularity, s);
+		SHOW_OFFSET(filename, s);
+		SHOW_OFFSET(filename_len, s);
+		SHOW_OFFSET(file_size, s);
+		SHOW_OFFSET(alloc_size, s);
+		SHOW_OFFSET(create_time, s);
+		SHOW_OFFSET(modify_time, s);
+		for (i = 0; i < OCFS_MAX_FILE_ENTRY_EXTENTS; ++i)
+			SHOW_OFFSET(extents[i], s);
+		SHOW_OFFSET(dir_node_ptr, s);
+		SHOW_OFFSET(this_sector, s);
+		SHOW_OFFSET(last_ext_ptr, s);
+		SHOW_OFFSET(sync_flags, s);
+		SHOW_OFFSET(link_cnt, s);
+		SHOW_OFFSET(attribs, s);
+		SHOW_OFFSET(prot_bits, s);
+		SHOW_OFFSET(uid, s);
+		SHOW_OFFSET(gid, s);
+		SHOW_OFFSET(dev_major, s);
+		SHOW_OFFSET(dev_minor, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_index_node()
+{
+	ocfs_index_node s;
+
+	SHOW_SIZEOF(ocfs_index_node, s);
+	if (show_all) {
+		SHOW_OFFSET(down_ptr, s);
+		SHOW_OFFSET(file_ent_ptr, s);
+		SHOW_OFFSET(name_len, s);
+		SHOW_OFFSET(name, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_index_hdr()
+{
+	ocfs_index_hdr s;
+
+	SHOW_SIZEOF(ocfs_index_hdr, s);
+	if (show_all) {
+		SHOW_OFFSET(disk_lock, s);
+		SHOW_OFFSET(signature, s);
+		SHOW_OFFSET(up_tree_ptr, s);
+		SHOW_OFFSET(node_disk_off, s);
+		SHOW_OFFSET(state, s);
+		SHOW_OFFSET(down_ptr, s);
+		SHOW_OFFSET(num_ents, s);
+		SHOW_OFFSET(depth, s);
+		SHOW_OFFSET(num_ent_used, s);
+		SHOW_OFFSET(dir_node_flags, s);
+		SHOW_OFFSET(sync_flags, s);
+		SHOW_OFFSET(index, s);
+		SHOW_OFFSET(reserved, s);
+		SHOW_OFFSET(file_ent, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_dir_node()
+{
+	ocfs_dir_node s;
+
+	SHOW_SIZEOF(ocfs_dir_node, s);
+	if (show_all) {
+		SHOW_OFFSET(disk_lock, s);
+		SHOW_OFFSET(signature, s);
+		SHOW_OFFSET(alloc_file_off, s);
+		SHOW_OFFSET(alloc_node, s);
+		SHOW_OFFSET(free_node_ptr, s);
+		SHOW_OFFSET(node_disk_off, s);
+		SHOW_OFFSET(next_node_ptr, s);
+		SHOW_OFFSET(indx_node_ptr, s);
+		SHOW_OFFSET(next_del_ent_node, s);
+		SHOW_OFFSET(head_del_ent_node, s);
+		SHOW_OFFSET(first_del, s);
+		SHOW_OFFSET(num_del, s);
+		SHOW_OFFSET(num_ents, s);
+		SHOW_OFFSET(depth, s);
+		SHOW_OFFSET(num_ent_used, s);
+		SHOW_OFFSET(dir_node_flags, s);
+		SHOW_OFFSET(sync_flags, s);
+		SHOW_OFFSET(index, s);
+		SHOW_OFFSET(index_dirty, s);
+		SHOW_OFFSET(bad_off, s);
+		SHOW_OFFSET(reserved, s);
+		SHOW_OFFSET(file_ent, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_extent_group()
+{
+	ocfs_extent_group s;
+	int i;
+
+	SHOW_SIZEOF(ocfs_extent_group, s);
+	if (show_all) {
+		SHOW_OFFSET(signature, s);
+		SHOW_OFFSET(next_free_ext, s);
+		SHOW_OFFSET(curr_sect, s);
+		SHOW_OFFSET(max_sects, s);
+		SHOW_OFFSET(type, s);
+		SHOW_OFFSET(granularity, s);
+		SHOW_OFFSET(alloc_node, s);
+		SHOW_OFFSET(this_ext, s);
+		SHOW_OFFSET(next_data_ext, s);
+		SHOW_OFFSET(alloc_file_off, s);
+		SHOW_OFFSET(last_ext_ptr, s);
+		SHOW_OFFSET(up_hdr_node_ptr, s);
+		for (i = 0; i < OCFS_MAX_DATA_EXTENTS; ++i)
+			SHOW_OFFSET(extents[i], s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_bitmap_lock()
+{
+	ocfs_bitmap_lock s;
+
+	SHOW_SIZEOF(ocfs_bitmap_lock, s);
+	if (show_all) {
+		SHOW_OFFSET(disk_lock, s);
+		SHOW_OFFSET(used_bits, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_vol_disk_hdr()
+{
+	ocfs_vol_disk_hdr s;
+
+	SHOW_SIZEOF(ocfs_vol_disk_hdr, s);
+	if (show_all) {
+		SHOW_OFFSET(minor_version, s);
+		SHOW_OFFSET(major_version, s);
+		SHOW_OFFSET(signature, s);
+		SHOW_OFFSET(mount_point, s);
+		SHOW_OFFSET(serial_num, s);
+		SHOW_OFFSET(device_size, s);
+		SHOW_OFFSET(start_off, s);
+		SHOW_OFFSET(bitmap_off, s);
+		SHOW_OFFSET(publ_off, s);
+		SHOW_OFFSET(vote_off, s);
+		SHOW_OFFSET(root_bitmap_off, s);
+		SHOW_OFFSET(data_start_off, s);
+		SHOW_OFFSET(root_bitmap_size, s);
+		SHOW_OFFSET(root_off, s);
+		SHOW_OFFSET(root_size, s);
+		SHOW_OFFSET(cluster_size, s);
+		SHOW_OFFSET(num_nodes, s);
+		SHOW_OFFSET(num_clusters, s);
+		SHOW_OFFSET(dir_node_size, s);
+		SHOW_OFFSET(file_node_size, s);
+		SHOW_OFFSET(internal_off, s);
+		SHOW_OFFSET(node_cfg_off, s);
+		SHOW_OFFSET(node_cfg_size, s);
+		SHOW_OFFSET(new_cfg_off, s);
+		SHOW_OFFSET(prot_bits, s);
+		SHOW_OFFSET(uid, s);
+		SHOW_OFFSET(gid, s);
+		SHOW_OFFSET(excl_mount, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_disk_lock()
+{
+	ocfs_disk_lock s;
+
+	SHOW_SIZEOF(ocfs_disk_lock, s);
+	if (show_all) {
+		SHOW_OFFSET(curr_master, s);
+		SHOW_OFFSET(file_lock, s);
+		SHOW_OFFSET(last_write_time, s);
+		SHOW_OFFSET(last_read_time, s);
+		SHOW_OFFSET(writer_node_num, s);
+		SHOW_OFFSET(reader_node_num, s);
+		SHOW_OFFSET(oin_node_map, s);
+		SHOW_OFFSET(dlock_seq_num, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_vol_label()
+{
+	ocfs_vol_label s;
+
+	SHOW_SIZEOF(ocfs_vol_label, s);
+	if (show_all) {
+		SHOW_OFFSET(disk_lock, s);
+		SHOW_OFFSET(label, s);
+		SHOW_OFFSET(label_len, s);
+		SHOW_OFFSET(vol_id, s);
+		SHOW_OFFSET(vol_id_len, s);
+		SHOW_OFFSET(cluster_name, s);
+		SHOW_OFFSET(cluster_name_len, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_ipc_config_info()
+{
+	ocfs_ipc_config_info s;
+
+	SHOW_SIZEOF(ocfs_ipc_config_info, s);
+	if (show_all) {
+		SHOW_OFFSET(type, s);
+		SHOW_OFFSET(ip_addr, s);
+		SHOW_OFFSET(ip_port, s);
+		SHOW_OFFSET(ip_mask, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_guid()
+{
+	ocfs_guid s;
+
+	SHOW_SIZEOF(ocfs_guid, s);
+	if (show_all) {
+		SHOW_OFFSET(guid, s);
+		SHOW_OFFSET(id.host_id, s);
+		SHOW_OFFSET(id.mac_id, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_disk_node_config_info()
+{
+	ocfs_disk_node_config_info s;
+
+	SHOW_SIZEOF(ocfs_disk_node_config_info, s);
+	if (show_all) {
+		SHOW_OFFSET(disk_lock, s);
+		SHOW_OFFSET(node_name, s);
+		SHOW_OFFSET(guid, s);
+		SHOW_OFFSET(ipc_config, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_node_config_hdr()
+{
+	ocfs_node_config_hdr s;
+
+	SHOW_SIZEOF(ocfs_node_config_hdr, s);
+	if (show_all) {
+		SHOW_OFFSET(disk_lock, s);
+		SHOW_OFFSET(signature, s);
+		SHOW_OFFSET(version, s);
+		SHOW_OFFSET(num_nodes, s);
+		SHOW_OFFSET(last_node, s);
+		SHOW_OFFSET(cfg_seq_num, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_cdsl()
+{
+	ocfs_cdsl s;
+
+	SHOW_SIZEOF(ocfs_cdsl, s);
+	if (show_all) {
+		SHOW_OFFSET(name, s);
+		SHOW_OFFSET(flags, s);
+		SHOW_OFFSET(operation, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_free_bitmap()
+{
+	ocfs_free_bitmap s;
+
+	SHOW_SIZEOF(ocfs_free_bitmap, s);
+	if (show_all) {
+		SHOW_OFFSET(length, s);
+		SHOW_OFFSET(file_off, s);
+		SHOW_OFFSET(type, s);
+		SHOW_OFFSET(node_num, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_free_extent_log()
+{
+	ocfs_free_extent_log s;
+
+	SHOW_SIZEOF(ocfs_free_extent_log, s);
+	if (show_all) {
+		SHOW_OFFSET(index, s);
+		SHOW_OFFSET(disk_off, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_free_log()
+{
+	ocfs_free_log s;
+	int i;
+
+	SHOW_SIZEOF(ocfs_free_log, s);
+	if (show_all) {
+		SHOW_OFFSET(num_free_upds, s);
+		for (i = 0; i < FREE_LOG_SIZE; ++i)
+			SHOW_OFFSET(free_bitmap[i], s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_delete_log()
+{
+	ocfs_delete_log s;
+
+	SHOW_SIZEOF(ocfs_delete_log, s);
+	if (show_all) {
+		SHOW_OFFSET(node_num, s);
+		SHOW_OFFSET(ent_del, s);
+		SHOW_OFFSET(parent_dirnode_off, s);
+		SHOW_OFFSET(flags, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_recovery_log()
+{
+	ocfs_recovery_log s;
+
+	SHOW_SIZEOF(ocfs_recovery_log, s);
+	if (show_all) {
+		SHOW_OFFSET(node_num, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_alloc_log()
+{
+	ocfs_alloc_log s;
+
+	SHOW_SIZEOF(ocfs_alloc_log, s);
+	if (show_all) {
+		SHOW_OFFSET(length, s);
+		SHOW_OFFSET(file_off, s);
+		SHOW_OFFSET(type, s);
+		SHOW_OFFSET(node_num, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_dir_log()
+{
+	ocfs_dir_log s;
+
+	SHOW_SIZEOF(ocfs_dir_log, s);
+	if (show_all) {
+		SHOW_OFFSET(orig_off, s);
+		SHOW_OFFSET(saved_off, s);
+		SHOW_OFFSET(length, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_lock_update()
+{
+	ocfs_lock_update s;
+
+	SHOW_SIZEOF(ocfs_lock_update, s);
+	if (show_all) {
+		SHOW_OFFSET(orig_off, s);
+		SHOW_OFFSET(new_off, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_lock_log()
+{
+	ocfs_lock_log s;
+	int i;
+
+	SHOW_SIZEOF(ocfs_lock_log, s);
+	if (show_all) {
+		SHOW_OFFSET(num_lock_upds, s);
+		for (i = 0; i < LOCK_UPDATE_LOG_SIZE; ++i)
+			SHOW_OFFSET(lock_upd[i], s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_bcast_rel_log()
+{
+	ocfs_bcast_rel_log s;
+
+	SHOW_SIZEOF(ocfs_bcast_rel_log, s);
+	if (show_all) {
+		SHOW_OFFSET(lock_id, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_log_record()
+{
+	ocfs_log_record s;
+
+	SHOW_SIZEOF(ocfs_log_record, s);
+	if (show_all) {
+		SHOW_OFFSET(log_id, s);
+		SHOW_OFFSET(log_type, s);
+		SHOW_OFFSET(rec.dir, s);
+		SHOW_OFFSET(rec.alloc, s);
+		SHOW_OFFSET(rec.recovery, s);
+		SHOW_OFFSET(rec.bcast, s);
+		SHOW_OFFSET(rec.del, s);
+		SHOW_OFFSET(rec.extent, s);
+		printf("\n");
+	}
+}
+
+
+int main(int argc, char **argv)
+{
+	if (argc > 1) {
+		if (!strncasecmp(*++argv, "all", 3))
+			show_all = true;
+		else {
+			usage();
+			exit (1);
+		}
+	}
+
+	print_ocfs_alloc_ext();
+	print_ocfs_publish();
+	print_ocfs_vote();
+	print_ocfs_file_entry();
+	print_ocfs_index_node();
+	print_ocfs_index_hdr();
+	print_ocfs_dir_node();
+	print_ocfs_extent_group();
+	print_ocfs_bitmap_lock();
+
+	print_ocfs_offset_map();
+
+	print_ocfs_vol_disk_hdr();
+	print_ocfs_disk_lock();
+	print_ocfs_vol_label();
+	print_ocfs_ipc_config_info();
+	print_ocfs_guid();
+	print_ocfs_disk_node_config_info();
+	print_ocfs_node_config_hdr();
+	print_ocfs_cdsl();
+
+	print_ocfs_free_bitmap();
+	print_ocfs_free_extent_log();
+	print_ocfs_free_log();
+	print_ocfs_delete_log();
+	print_ocfs_recovery_log();
+	print_ocfs_alloc_log();
+	print_ocfs_dir_log();
+	print_ocfs_lock_log();
+	print_ocfs_lock_update();
+	print_ocfs_bcast_rel_log();
+	print_ocfs_cleanup_record();
+	print_ocfs_log_record();
+
+	return 0;
+}				/* main */

Added: trunk/advanced/sizetest/net.txt
===================================================================
--- trunk/advanced/sizetest/net.txt	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/advanced/sizetest/net.txt	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,24 @@
+sizeof(ocfs_dlm_msg_hdr) = 24
+	lock_id = 0 (8)
+	flags = 8 (4)
+	lock_seq_num = 12 (8)
+	open_handle = 20 (1)
+
+sizeof(ocfs_dlm_reply_master) = 28
+	h = 0 (24)
+	status = 24 (4)
+
+sizeof(ocfs_dlm_disk_vote_reply) = 28
+	h = 0 (24)
+	status = 24 (4)
+
+sizeof(ocfs_dlm_msg) = 44
+	magic = 0 (4)
+	msg_len = 4 (4)
+	vol_id = 8 (16)
+	src_node = 24 (4)
+	dst_node = 28 (4)
+	msg_type = 32 (4)
+	check_sum = 36 (4)
+	msg_buf = 40 (1)
+

Added: trunk/advanced/sizetest/netstructs.c
===================================================================
--- trunk/advanced/sizetest/netstructs.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/advanced/sizetest/netstructs.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,120 @@
+/*
+ * netstructs.c
+ *
+ * Prints sizes and offsets of structures and its elements.
+ * Useful to ensure cross platform compatibility.
+ *
+ * Copyright (C) 2003 Oracle Corporation.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Sunil Mushran, Manish Singh, Wim Coekaerts
+ */
+
+#include "sizetest.h"
+
+bool show_all = false;
+
+void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr)
+{
+    return;
+}
+
+void usage(void)
+{
+	printf("usage: netstructs [all]\n");
+	return ;
+}
+
+
+static void print_ocfs_dlm_msg_hdr()
+{
+	ocfs_dlm_msg_hdr s;
+
+	SHOW_SIZEOF(ocfs_dlm_msg_hdr, s);
+	if (show_all) {
+		SHOW_OFFSET(lock_id, s);
+		SHOW_OFFSET(flags, s);
+		SHOW_OFFSET(lock_seq_num, s);
+		SHOW_OFFSET(open_handle, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_dlm_reply_master()
+{
+	ocfs_dlm_reply_master s;
+
+	SHOW_SIZEOF(ocfs_dlm_reply_master, s);
+	if (show_all) {
+		SHOW_OFFSET(h, s);
+		SHOW_OFFSET(status, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_dlm_disk_vote_reply()
+{
+	ocfs_dlm_disk_vote_reply s;
+
+	SHOW_SIZEOF(ocfs_dlm_disk_vote_reply, s);
+	if (show_all) {
+		SHOW_OFFSET(h, s);
+		SHOW_OFFSET(status, s);
+		printf("\n");
+	}
+}
+
+
+static void print_ocfs_dlm_msg()
+{
+	ocfs_dlm_msg s;
+
+	SHOW_SIZEOF(ocfs_dlm_msg, s);
+	if (show_all) {
+		SHOW_OFFSET(magic, s);
+		SHOW_OFFSET(msg_len, s);
+		SHOW_OFFSET(vol_id, s);
+		SHOW_OFFSET(src_node, s);
+		SHOW_OFFSET(dst_node, s);
+		SHOW_OFFSET(msg_type, s);
+		SHOW_OFFSET(check_sum, s);
+		SHOW_OFFSET(msg_buf, s);
+		printf("\n");
+	}
+}
+
+
+int main(int argc, char **argv)
+{
+	if (argc > 1) {
+		if (!strncasecmp(*++argv, "all", 3))
+			show_all = true;
+		else {
+			usage();
+			exit (1);
+		}
+	}
+
+	print_ocfs_dlm_msg_hdr();
+	print_ocfs_dlm_reply_master();
+	print_ocfs_dlm_disk_vote_reply();
+	print_ocfs_dlm_msg();
+
+	return 0;
+}				/* main */

Added: trunk/advanced/sizetest/sizetest.c
===================================================================
--- trunk/advanced/sizetest/sizetest.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/advanced/sizetest/sizetest.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,950 @@
+/*
+ * sizetest.c
+ *
+ * Prints sizes and offsets of structures and its elements.
+ * Useful to ensure cross platform compatibility.
+ *
+ * Copyright (C) 2003 Oracle Corporation.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Sunil Mushran, Manish Singh, Wim Coekaerts
+ */
+
+#include "sizetest.h"
+
+bool show_all = false;
+
+void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr)
+{
+    return;
+}
+
+static void print_ocfs_extent_map()
+{
+    ocfs_extent_map i;
+    SHOW_SIZEOF(ocfs_extent_map, i);
+}
+
+static void print_ocfs_offset_map()
+{
+    ocfs_offset_map i;
+    SHOW_SIZEOF(ocfs_offset_map, i);
+    SHOW_OFFSET(length, i);
+    SHOW_OFFSET(log_disk_off, i);
+    SHOW_OFFSET(actual_disk_off, i);
+}
+
+static void print_ocfs_io_runs()
+{
+    ocfs_io_runs i;
+    SHOW_SIZEOF(ocfs_io_runs, i);
+}
+
+static void print_ocfs_inode_offsets()
+{
+    ocfs_inode i;
+    SHOW_SIZEOF(ocfs_inode, i);
+
+    if (show_all)
+    	SHOW_OFFSET(main_res, i);
+}
+ 
+static void print_ocfs_dlm_reply_master_offsets()
+{
+    ocfs_dlm_reply_master d;
+    SHOW_SIZEOF(ocfs_dlm_reply_master, d);
+}
+
+static void print_ocfs_dlm_msg_offsets()
+{
+    ocfs_dlm_msg d;
+    SHOW_SIZEOF(ocfs_dlm_msg, d);
+}
+
+static void print_ocfs_cleanup_record_offsets()
+{
+    ocfs_cleanup_record c;
+    SHOW_SIZEOF(ocfs_cleanup_record, c);
+}
+
+static void print_ocfs_global_ctxt_offsets()
+{
+    ocfs_global_ctxt c;
+
+    SHOW_SIZEOF(ocfs_global_ctxt, c);
+
+    if (show_all) {
+        SHOW_OFFSET(obj_id, c);
+        SHOW_OFFSET(res, c);
+        SHOW_OFFSET(osb_next, c);
+        SHOW_OFFSET(oin_cache, c);
+        SHOW_OFFSET(ofile_cache, c);
+        SHOW_OFFSET(fe_cache, c);
+        SHOW_OFFSET(lockres_cache, c);
+        SHOW_OFFSET(flags, c);
+        SHOW_OFFSET(node_name, c);
+        SHOW_OFFSET(cluster_name, c);
+        SHOW_OFFSET(comm_info, c);
+        SHOW_OFFSET(hbm, c);
+    }
+}
+
+static void print_ocfs_super_offsets()
+{
+    ocfs_super s;
+
+    SHOW_SIZEOF(ocfs_super, s);
+
+    if (show_all) {
+        SHOW_OFFSET(obj_id, s);
+        SHOW_OFFSET(osb_res, s);
+        SHOW_OFFSET(osb_next, s);
+        SHOW_OFFSET(osb_id, s);
+        SHOW_OFFSET(complete, s);
+        SHOW_OFFSET(dlm_task, s);
+        SHOW_OFFSET(osb_flags, s);
+        SHOW_OFFSET(file_open_cnt, s);
+        SHOW_OFFSET(publ_map, s);
+        SHOW_OFFSET(root_sect_node, s);
+        SHOW_OFFSET(cache_lock_list, s);
+        SHOW_OFFSET(sb, s);
+        SHOW_OFFSET(oin_root_dir, s);
+        SHOW_OFFSET(vol_layout, s);
+        SHOW_OFFSET(vol_node_map, s);
+        SHOW_OFFSET(node_cfg_info, s);
+        SHOW_OFFSET(cfg_seq_num, s);
+        SHOW_OFFSET(cfg_initialized, s);
+        SHOW_OFFSET(num_cfg_nodes, s);
+        SHOW_OFFSET(node_num, s);
+        SHOW_OFFSET(hbm, s);
+        SHOW_OFFSET(hbt, s);
+        SHOW_OFFSET(log_disk_off, s);
+        SHOW_OFFSET(log_meta_disk_off, s);
+        SHOW_OFFSET(log_file_size, s);
+        SHOW_OFFSET(sect_size, s);
+        SHOW_OFFSET(needs_flush, s);
+        SHOW_OFFSET(commit_cache_exec, s);
+        SHOW_OFFSET(map_lock, s);
+        SHOW_OFFSET(metadata_map, s);
+        SHOW_OFFSET(trans_map, s);
+        SHOW_OFFSET(cluster_bitmap, s);
+        SHOW_OFFSET(max_dir_node_ent, s);
+        SHOW_OFFSET(vol_state, s);
+        SHOW_OFFSET(curr_trans_id, s);
+        SHOW_OFFSET(trans_in_progress, s);
+        SHOW_OFFSET(log_lock, s);
+        SHOW_OFFSET(recovery_lock, s);
+        SHOW_OFFSET(node_recovering, s);
+        SHOW_OFFSET(vol_alloc_lock, s);
+        SHOW_OFFSET(lock_timer, s);
+        SHOW_OFFSET(lock_stop, s);
+        SHOW_OFFSET(lock_event, s);
+        SHOW_OFFSET(cache_fs, s);
+    }
+}
+
+static void print_ocfs_lock_res_offsets()
+{
+    ocfs_lock_res l;
+
+    SHOW_SIZEOF(ocfs_lock_res, l);
+
+    if (show_all) {
+        SHOW_OFFSET(signature, l);
+        SHOW_OFFSET(lock_type, l);		
+//        SHOW_OFFSET(ref_cnt, l);		
+        SHOW_OFFSET(master_node_num, l);
+        SHOW_OFFSET(last_upd_seq_num, l);
+        SHOW_OFFSET(last_lock_upd, l);
+        SHOW_OFFSET(sector_num, l);
+        SHOW_OFFSET(oin_openmap, l);
+        SHOW_OFFSET(in_use, l);
+        SHOW_OFFSET(thread_id, l);
+        SHOW_OFFSET(cache_list, l);
+        SHOW_OFFSET(in_cache_list, l);
+        SHOW_OFFSET(lock_state, l);
+        SHOW_OFFSET(oin, l);
+        SHOW_OFFSET(lock_mutex, l);
+        SHOW_OFFSET(voted_event, l);
+        SHOW_OFFSET(req_vote_map, l);
+        SHOW_OFFSET(got_vote_map, l);
+        SHOW_OFFSET(vote_status, l);
+        SHOW_OFFSET(last_write_time, l);
+        SHOW_OFFSET(last_read_time, l);
+        SHOW_OFFSET(writer_node_num, l);
+        SHOW_OFFSET(reader_node_num, l);
+    }
+}
+
+static void print_superops_offsets()
+{
+    struct super_operations s;
+
+    SHOW_SIZEOF(struct super_operations, s);
+
+    if (show_all) {
+        SHOW_OFFSET(read_inode, s);
+        SHOW_OFFSET(read_inode2, s);
+        SHOW_OFFSET(dirty_inode, s);
+        SHOW_OFFSET(write_inode, s);
+        SHOW_OFFSET(put_inode, s);
+        SHOW_OFFSET(delete_inode, s);
+        SHOW_OFFSET(put_super, s);
+        SHOW_OFFSET(write_super, s);
+        SHOW_OFFSET(write_super_lockfs, s);
+        SHOW_OFFSET(unlockfs, s);
+        SHOW_OFFSET(statfs, s);
+        SHOW_OFFSET(remount_fs, s);
+        SHOW_OFFSET(clear_inode, s);
+        SHOW_OFFSET(umount_begin, s);
+    }
+}
+ 
+static void print_super_offsets()
+{
+    struct super_block s;
+
+    SHOW_SIZEOF(struct super_block, s);
+
+    if (show_all) {
+        SHOW_OFFSET(s_op, s);
+        SHOW_OFFSET(s_list, s);
+        SHOW_OFFSET(s_dev, s);
+        SHOW_OFFSET(s_blocksize, s);
+        SHOW_OFFSET(s_blocksize_bits, s);
+        SHOW_OFFSET(s_dirt, s);
+        SHOW_OFFSET(s_maxbytes, s);
+        SHOW_OFFSET(s_type, s);
+        SHOW_OFFSET(s_op, s);
+        SHOW_OFFSET(dq_op, s);
+        SHOW_OFFSET(s_flags, s);
+        SHOW_OFFSET(s_magic, s);
+        SHOW_OFFSET(s_root, s);
+        SHOW_OFFSET(s_umount, s);
+        SHOW_OFFSET(s_lock, s);
+        SHOW_OFFSET(s_count, s);
+        SHOW_OFFSET(s_active, s);
+        SHOW_OFFSET(s_dirty, s);
+        SHOW_OFFSET(s_locked_inodes, s);
+        SHOW_OFFSET(s_files, s);
+        SHOW_OFFSET(s_bdev, s);
+        SHOW_OFFSET(s_instances, s);
+        SHOW_OFFSET(s_dquot, s);
+        SHOW_OFFSET(u, s);
+    }
+}
+ 
+static void print_filp_offsets()
+{
+    struct file f;
+
+    SHOW_SIZEOF(struct file, f);
+
+    if (show_all) {
+        SHOW_OFFSET(f_list, f);
+        SHOW_OFFSET(f_dentry, f);
+        SHOW_OFFSET(f_vfsmnt, f);
+        SHOW_OFFSET(f_op, f);
+        SHOW_OFFSET(f_count, f);
+        SHOW_OFFSET(f_flags, f);
+        SHOW_OFFSET(f_mode, f);
+        SHOW_OFFSET(f_pos, f);
+        SHOW_OFFSET(f_reada, f);
+        SHOW_OFFSET(f_ramax, f);
+        SHOW_OFFSET(f_raend, f);
+        SHOW_OFFSET(f_ralen, f);
+        SHOW_OFFSET(f_rawin, f);
+        SHOW_OFFSET(f_owner, f);
+        SHOW_OFFSET(f_uid, f);
+        SHOW_OFFSET(f_gid, f);
+        SHOW_OFFSET(f_error, f);
+        SHOW_OFFSET(f_version, f);
+        SHOW_OFFSET(private_data, f);
+        //SHOW_OFFSET(f_iobuf, f);
+        //SHOW_OFFSET(f_iobuf_lock, f);
+    }
+}
+
+static void print_inode_offsets()
+{
+    struct inode ino;
+
+    SHOW_SIZEOF(struct inode, ino);
+
+    if (show_all) {
+        SHOW_OFFSET(i_hash, ino);
+        SHOW_OFFSET(i_list, ino);
+        SHOW_OFFSET(i_dentry, ino);
+        SHOW_OFFSET(i_dirty_buffers, ino);
+        //SHOW_OFFSET(i_dirty_data_buffers, ino);
+        SHOW_OFFSET(i_ino, ino);
+        SHOW_OFFSET(i_count, ino);
+        SHOW_OFFSET(i_dev, ino);
+        SHOW_OFFSET(i_mode, ino);
+        SHOW_OFFSET(i_nlink, ino);
+        SHOW_OFFSET(i_uid, ino);
+        SHOW_OFFSET(i_gid, ino);
+        SHOW_OFFSET(i_rdev, ino);
+        SHOW_OFFSET(i_size, ino);
+        SHOW_OFFSET(i_atime, ino);
+        SHOW_OFFSET(i_mtime, ino);
+        SHOW_OFFSET(i_ctime, ino);
+        SHOW_OFFSET(i_blksize, ino);
+        SHOW_OFFSET(i_blocks, ino);
+        SHOW_OFFSET(i_version, ino);
+        SHOW_OFFSET(i_bytes, ino);
+        SHOW_OFFSET(i_sem, ino);
+#ifndef __LP64__
+        SHOW_OFFSET(i_truncate_sem, ino);
+#endif
+        SHOW_OFFSET(i_zombie, ino);
+        SHOW_OFFSET(i_op, ino);
+        SHOW_OFFSET(i_fop, ino);    
+        SHOW_OFFSET(i_sb, ino);
+        SHOW_OFFSET(i_wait, ino);
+        SHOW_OFFSET(i_flock, ino);
+        SHOW_OFFSET(i_mapping, ino);
+        SHOW_OFFSET(i_data, ino);    
+        SHOW_OFFSET(i_dquot, ino);
+        //SHOW_OFFSET(i_devices, ino);
+        SHOW_OFFSET(i_pipe, ino);
+        SHOW_OFFSET(i_bdev, ino);
+        SHOW_OFFSET(i_cdev, ino);
+        SHOW_OFFSET(i_dnotify_mask, ino); 
+        SHOW_OFFSET(i_dnotify, ino); 
+        SHOW_OFFSET(i_state, ino);
+        SHOW_OFFSET(i_flags, ino);
+        SHOW_OFFSET(i_sock, ino);
+        SHOW_OFFSET(i_writecount, ino);
+        SHOW_OFFSET(i_attr_flags, ino);
+        SHOW_OFFSET(i_generation, ino);
+        SHOW_OFFSET(u.generic_ip, ino);
+    }
+}
+
+static void print_dentry_offsets()
+{
+    struct qstr qs;
+    struct dentry den;
+
+    SHOW_SIZEOF(struct dentry, den);
+
+    if (show_all) {
+        SHOW_OFFSET(d_count, den);
+        SHOW_OFFSET(d_flags, den);
+        SHOW_OFFSET(d_inode, den);
+        SHOW_OFFSET(d_parent, den);
+        SHOW_OFFSET(d_hash, den);
+        SHOW_OFFSET(d_lru, den);
+        SHOW_OFFSET(d_child, den);
+        SHOW_OFFSET(d_subdirs, den);    
+        SHOW_OFFSET(d_alias, den);
+        SHOW_OFFSET(d_mounted, den);
+        SHOW_OFFSET(d_name, den);
+        SHOW_OFFSET(d_time, den);
+        SHOW_OFFSET(d_op, den);
+        SHOW_OFFSET(d_sb, den);    
+        SHOW_OFFSET(d_vfs_flags, den);
+        SHOW_OFFSET(d_fsdata, den);
+        SHOW_OFFSET(d_iname, den); 
+        SHOW_SIZEOF(struct qstr, qs);
+        SHOW_OFFSET(name, qs);
+        SHOW_OFFSET(len, qs);
+        SHOW_OFFSET(hash, qs);
+    }
+}
+
+void usage(void)
+{
+	printf("usage: sizetest [all]\n");
+	return ;
+}
+
+
+static void print_ocfs_alloc_ext()
+{
+	ocfs_alloc_ext s;
+	SHOW_SIZEOF(ocfs_alloc_ext, s);
+	SHOW_OFFSET(file_off, s);			
+	SHOW_OFFSET(num_bytes, s);		
+	SHOW_OFFSET(disk_off, s);			
+}
+
+
+static void print_ocfs_publish()
+{
+	ocfs_publish s;
+	SHOW_SIZEOF(ocfs_publish, s);
+	SHOW_OFFSET(time, s);                     
+	SHOW_OFFSET(vote, s);                     
+	SHOW_OFFSET(dirty, s);                     
+	SHOW_OFFSET(vote_type, s);                  
+	SHOW_OFFSET(vote_map, s);                   
+	SHOW_OFFSET(publ_seq_num, s);               
+	SHOW_OFFSET(dir_ent, s);                    
+	SHOW_OFFSET(hbm, s);
+	SHOW_OFFSET(comm_seq_num, s);		
+}
+
+
+static void print_ocfs_vote()
+{
+	ocfs_vote s;
+	SHOW_SIZEOF(ocfs_vote, s);
+	SHOW_OFFSET(vote, s);   
+	SHOW_OFFSET(vote_seq_num, s);              
+	SHOW_OFFSET(dir_ent, s);                   
+	SHOW_OFFSET(open_handle, s);                
+}
+
+
+static void print_ocfs_file_entry()
+{
+	ocfs_file_entry s;
+	SHOW_SIZEOF(ocfs_file_entry, s);
+	SHOW_OFFSET(disk_lock, s);       
+	SHOW_OFFSET(signature, s);
+	SHOW_OFFSET(local_ext, s);		        
+	SHOW_OFFSET(next_free_ext, s);             
+	SHOW_OFFSET(next_del, s);                  
+	SHOW_OFFSET(granularity, s);	        
+	SHOW_OFFSET(filename, s);
+	SHOW_OFFSET(filename_len, s);               
+	SHOW_OFFSET(file_size, s);                  
+	SHOW_OFFSET(alloc_size, s);		        
+	SHOW_OFFSET(create_time, s);                
+	SHOW_OFFSET(modify_time, s);	        
+	SHOW_OFFSET(extents, s);
+	SHOW_OFFSET(dir_node_ptr, s);               
+	SHOW_OFFSET(this_sector, s);                
+	SHOW_OFFSET(last_ext_ptr, s);               
+	SHOW_OFFSET(sync_flags, s);		  
+	SHOW_OFFSET(link_cnt, s);                   
+	SHOW_OFFSET(attribs, s);                    
+	SHOW_OFFSET(prot_bits, s);                  
+	SHOW_OFFSET(uid, s);                        
+	SHOW_OFFSET(gid, s);                        
+	SHOW_OFFSET(dev_major, s);                  
+	SHOW_OFFSET(dev_minor, s);                  
+}
+
+
+static void print_ocfs_index_node()
+{
+	ocfs_index_node s;
+	SHOW_SIZEOF(ocfs_index_node, s);
+	SHOW_OFFSET(down_ptr, s);
+	SHOW_OFFSET(file_ent_ptr, s);
+	SHOW_OFFSET(name_len, s);
+	SHOW_OFFSET(name, s);
+}
+
+
+static void print_ocfs_index_hdr()
+{
+	ocfs_index_hdr s;
+	SHOW_SIZEOF(ocfs_index_hdr, s);
+	SHOW_OFFSET(disk_lock, s);
+	SHOW_OFFSET(signature, s);
+	SHOW_OFFSET(up_tree_ptr, s);	
+	SHOW_OFFSET(node_disk_off, s);
+	SHOW_OFFSET(state, s);
+	SHOW_OFFSET(down_ptr, s);
+	SHOW_OFFSET(num_ents, s);
+	SHOW_OFFSET(depth, s);
+	SHOW_OFFSET(num_ent_used, s);	
+	SHOW_OFFSET(dir_node_flags, s);	
+	SHOW_OFFSET(sync_flags, s);		
+	SHOW_OFFSET(index, s);
+	SHOW_OFFSET(reserved, s);
+	SHOW_OFFSET(file_ent, s);	
+}
+
+
+static void print_ocfs_dir_node()
+{
+	ocfs_dir_node s;
+	SHOW_SIZEOF(ocfs_dir_node, s);
+	SHOW_OFFSET(disk_lock, s);       
+	SHOW_OFFSET(signature, s);               
+	SHOW_OFFSET(alloc_file_off, s);             
+	SHOW_OFFSET(alloc_node, s);                 
+	SHOW_OFFSET(free_node_ptr, s);              
+	SHOW_OFFSET(node_disk_off, s);              
+	SHOW_OFFSET(next_node_ptr, s);              
+	SHOW_OFFSET(indx_node_ptr, s);              
+	SHOW_OFFSET(next_del_ent_node, s);          
+	SHOW_OFFSET(head_del_ent_node, s);          
+	SHOW_OFFSET(first_del, s);                  
+	SHOW_OFFSET(num_del, s);                    
+	SHOW_OFFSET(num_ents, s);	                
+	SHOW_OFFSET(depth, s);		        
+	SHOW_OFFSET(num_ent_used, s);	        
+	SHOW_OFFSET(dir_node_flags, s);	        
+	SHOW_OFFSET(sync_flags, s);		 
+	SHOW_OFFSET(index, s);                 
+	SHOW_OFFSET(index_dirty, s);                
+	SHOW_OFFSET(bad_off, s);                    
+	SHOW_OFFSET(reserved, s);              
+	SHOW_OFFSET(file_ent, s);                
+}
+
+
+static void print_ocfs_vol_node_map()
+{
+	ocfs_vol_node_map s;
+	SHOW_SIZEOF(ocfs_vol_node_map, s);
+	SHOW_OFFSET(time, s);
+	SHOW_OFFSET(scan_time, s);
+	SHOW_OFFSET(scan_rate, s);
+	SHOW_OFFSET(miss_cnt, s);
+	SHOW_OFFSET(dismount, s);
+	SHOW_OFFSET(largest_seq_num, s);
+}
+
+
+static void print_ocfs_vol_layout()
+{
+	ocfs_vol_layout s;
+	SHOW_SIZEOF(ocfs_vol_layout, s);
+	SHOW_OFFSET(start_off, s);
+	SHOW_OFFSET(num_nodes, s);
+	SHOW_OFFSET(cluster_size, s);
+	SHOW_OFFSET(mount_point, s);
+	SHOW_OFFSET(vol_id, s);
+	SHOW_OFFSET(label, s);
+	SHOW_OFFSET(label_len, s);
+	SHOW_OFFSET(size, s);
+	SHOW_OFFSET(root_start_off, s);
+	SHOW_OFFSET(serial_num, s);
+	SHOW_OFFSET(root_size, s);
+	SHOW_OFFSET(publ_sect_off, s);
+	SHOW_OFFSET(vote_sect_off, s);
+	SHOW_OFFSET(root_bitmap_off, s);
+	SHOW_OFFSET(root_bitmap_size, s);
+	SHOW_OFFSET(data_start_off, s);
+	SHOW_OFFSET(num_clusters, s);
+	SHOW_OFFSET(root_int_off, s);
+	SHOW_OFFSET(dir_node_size, s);
+	SHOW_OFFSET(file_node_size, s);
+	SHOW_OFFSET(bitmap_off, s);
+	SHOW_OFFSET(node_cfg_off, s);
+	SHOW_OFFSET(node_cfg_size, s);
+	SHOW_OFFSET(new_cfg_off, s);
+	SHOW_OFFSET(prot_bits, s);
+	SHOW_OFFSET(uid, s);
+	SHOW_OFFSET(gid, s);
+}
+
+
+static void print_ocfs_extent_group()
+{
+	ocfs_extent_group s;
+	SHOW_SIZEOF(ocfs_extent_group, s);
+	SHOW_OFFSET(signature, s);				
+	SHOW_OFFSET(next_free_ext, s);				
+	SHOW_OFFSET(curr_sect, s);				
+	SHOW_OFFSET(max_sects, s);				
+	SHOW_OFFSET(type, s);					
+	SHOW_OFFSET(granularity, s);				
+	SHOW_OFFSET(alloc_node, s);				
+	SHOW_OFFSET(this_ext, s);					
+	SHOW_OFFSET(next_data_ext, s);				
+	SHOW_OFFSET(alloc_file_off, s);				
+	SHOW_OFFSET(last_ext_ptr, s);				
+	SHOW_OFFSET(up_hdr_node_ptr, s);				
+	SHOW_OFFSET(extents, s);	
+}
+
+
+static void print_ocfs_bitmap_lock()
+{
+	ocfs_bitmap_lock s;
+	SHOW_SIZEOF(ocfs_bitmap_lock, s);
+	SHOW_OFFSET(disk_lock, s);
+	SHOW_OFFSET(used_bits, s);
+}
+
+
+static void print_ocfs_vol_disk_hdr()
+{
+	ocfs_vol_disk_hdr s;
+	SHOW_SIZEOF(ocfs_vol_disk_hdr, s);
+	SHOW_OFFSET(minor_version, s);                       
+	SHOW_OFFSET(major_version, s);                       
+	SHOW_OFFSET(signature, s);	 
+	SHOW_OFFSET(mount_point, s);	 
+	SHOW_OFFSET(serial_num, s);                          
+	SHOW_OFFSET(device_size, s);	                 
+	SHOW_OFFSET(start_off, s);		                 
+	SHOW_OFFSET(bitmap_off, s);		                 
+	SHOW_OFFSET(publ_off, s);		                 
+	SHOW_OFFSET(vote_off, s);		                 
+	SHOW_OFFSET(root_bitmap_off, s);                     
+	SHOW_OFFSET(data_start_off, s);                      
+	SHOW_OFFSET(root_bitmap_size, s);                    
+	SHOW_OFFSET(root_off, s);                            
+	SHOW_OFFSET(root_size, s);                           
+	SHOW_OFFSET(cluster_size, s);	                 
+	SHOW_OFFSET(num_nodes, s);		                 
+	SHOW_OFFSET(num_clusters, s);	                 
+	SHOW_OFFSET(dir_node_size, s);	                 
+	SHOW_OFFSET(file_node_size, s);	                 
+	SHOW_OFFSET(internal_off, s);                        
+	SHOW_OFFSET(node_cfg_off, s);	                 
+	SHOW_OFFSET(node_cfg_size, s);	                 
+	SHOW_OFFSET(new_cfg_off, s);	                 
+	SHOW_OFFSET(prot_bits, s);                           
+	SHOW_OFFSET(uid, s);                                 
+	SHOW_OFFSET(gid, s);                                 
+	SHOW_OFFSET(excl_mount, s);                          
+}
+
+
+static void print_ocfs_disk_lock()
+{
+	ocfs_disk_lock s;
+	SHOW_SIZEOF(ocfs_disk_lock, s);
+	SHOW_OFFSET(curr_master, s);			
+	SHOW_OFFSET(file_lock, s);				
+	SHOW_OFFSET(last_write_time, s);			
+	SHOW_OFFSET(last_read_time, s);			
+	SHOW_OFFSET(writer_node_num, s);			
+	SHOW_OFFSET(reader_node_num, s);			
+	SHOW_OFFSET(oin_node_map, s);			
+	SHOW_OFFSET(dlock_seq_num, s);			
+}
+
+
+static void print_ocfs_vol_label()
+{
+	ocfs_vol_label s;
+	SHOW_SIZEOF(ocfs_vol_label, s);
+	SHOW_OFFSET(disk_lock, s);                
+	SHOW_OFFSET(label, s);            
+	SHOW_OFFSET(label_len, s);                           
+	SHOW_OFFSET(vol_id, s);           
+	SHOW_OFFSET(vol_id_len, s);                          
+	SHOW_OFFSET(cluster_name, s);  
+	SHOW_OFFSET(cluster_name_len, s);                    
+}
+
+
+static void print_ocfs_ipc_config_info()
+{
+	ocfs_ipc_config_info s;
+	SHOW_SIZEOF(ocfs_ipc_config_info, s);
+	SHOW_OFFSET(type, s);					
+	SHOW_OFFSET(ip_addr, s);
+	SHOW_OFFSET(ip_port, s);					
+	SHOW_OFFSET(ip_mask, s);
+}
+
+
+static void print_ocfs_guid()
+{
+	ocfs_guid s;
+	SHOW_SIZEOF(ocfs_guid, s);
+	SHOW_OFFSET(id.host_id, s);
+	SHOW_OFFSET(id.mac_id, s);
+}
+
+
+static void print_ocfs_disk_node_config_info()
+{
+	ocfs_disk_node_config_info s;
+	SHOW_SIZEOF(ocfs_disk_node_config_info, s);
+	SHOW_OFFSET(disk_lock, s);			
+	SHOW_OFFSET(node_name, s);
+	SHOW_OFFSET(guid, s);					
+	SHOW_OFFSET(ipc_config, s);		
+}
+
+
+static void print_ocfs_node_config_hdr()
+{
+	ocfs_node_config_hdr s;
+	SHOW_SIZEOF(ocfs_node_config_hdr, s);
+	SHOW_OFFSET(disk_lock, s);			
+	SHOW_OFFSET(signature, s);		
+	SHOW_OFFSET(version, s);					
+	SHOW_OFFSET(num_nodes, s);				
+	SHOW_OFFSET(last_node, s);				
+	SHOW_OFFSET(cfg_seq_num, s);				
+}
+
+
+static void print_ocfs_cdsl()
+{
+	ocfs_cdsl s;
+	SHOW_SIZEOF(ocfs_cdsl, s);
+	SHOW_OFFSET(name, s);
+	SHOW_OFFSET(flags, s);
+	SHOW_OFFSET(operation, s);
+}
+
+
+static void print_ocfs_free_bitmap()
+{
+	ocfs_free_bitmap s;
+	SHOW_SIZEOF(ocfs_free_bitmap, s);
+	SHOW_OFFSET(length, s);
+	SHOW_OFFSET(file_off, s);
+	SHOW_OFFSET(type, s);
+	SHOW_OFFSET(node_num, s);
+}
+
+
+static void print_ocfs_free_extent_log()
+{
+	ocfs_free_extent_log s;
+	SHOW_SIZEOF(ocfs_free_extent_log, s);
+	SHOW_OFFSET(index, s);
+	SHOW_OFFSET(disk_off, s);
+}
+
+
+static void print_ocfs_free_log()
+{
+	ocfs_free_log s;
+	SHOW_SIZEOF(ocfs_free_log, s);
+	SHOW_OFFSET(num_free_upds, s); 
+	SHOW_OFFSET(free_bitmap, s);
+}
+
+
+static void print_ocfs_delete_log()
+{
+	ocfs_delete_log s;
+	SHOW_SIZEOF(ocfs_delete_log, s);
+	SHOW_OFFSET(node_num, s);
+	SHOW_OFFSET(ent_del, s);
+	SHOW_OFFSET(parent_dirnode_off, s);
+	SHOW_OFFSET(flags, s);
+}
+
+
+static void print_ocfs_recovery_log()
+{
+	ocfs_recovery_log s;
+	SHOW_SIZEOF(ocfs_recovery_log, s);
+	SHOW_OFFSET(node_num, s);
+}
+
+
+static void print_ocfs_alloc_log()
+{
+	ocfs_alloc_log s;
+	SHOW_SIZEOF(ocfs_alloc_log, s);
+	SHOW_OFFSET(length, s);
+	SHOW_OFFSET(file_off, s);
+	SHOW_OFFSET(type, s);
+	SHOW_OFFSET(node_num, s);
+}
+
+
+static void print_ocfs_dir_log()
+{
+	ocfs_dir_log s;
+	SHOW_SIZEOF(ocfs_dir_log, s);
+	SHOW_OFFSET(orig_off, s);
+	SHOW_OFFSET(saved_off, s);
+	SHOW_OFFSET(length, s);
+}
+
+
+static void print_ocfs_lock_update()
+{
+	ocfs_lock_update s;
+	SHOW_SIZEOF(ocfs_lock_update, s);
+	SHOW_OFFSET(orig_off, s);
+	SHOW_OFFSET(new_off, s);
+}
+
+
+static void print_ocfs_lock_log()
+{
+	ocfs_lock_log s;
+	SHOW_SIZEOF(ocfs_lock_log, s);
+	SHOW_OFFSET(num_lock_upds, s);
+	SHOW_OFFSET(lock_upd, s);
+}
+
+
+static void print_ocfs_bcast_rel_log()
+{
+	ocfs_bcast_rel_log s;
+	SHOW_SIZEOF(ocfs_bcast_rel_log, s);
+	SHOW_OFFSET(lock_id, s);
+}
+
+
+static void print_ocfs_cleanup_record()
+{
+	ocfs_cleanup_record s;
+	SHOW_SIZEOF(ocfs_cleanup_record, s);
+	SHOW_OFFSET(log_id, s);
+	SHOW_OFFSET(log_type, s);
+	SHOW_OFFSET(rec.lock, s);
+	SHOW_OFFSET(rec.alloc, s);
+	SHOW_OFFSET(rec.bcast, s);
+	SHOW_OFFSET(rec.del, s);
+	SHOW_OFFSET(rec.free, s);
+}
+
+
+static void print_ocfs_log_record()
+{
+	ocfs_log_record s;
+	SHOW_SIZEOF(ocfs_log_record, s);
+	SHOW_OFFSET(log_id, s);
+	SHOW_OFFSET(log_type, s);
+	SHOW_OFFSET(rec.dir, s);
+	SHOW_OFFSET(rec.alloc, s);
+	SHOW_OFFSET(rec.recovery, s);
+	SHOW_OFFSET(rec.bcast, s);
+	SHOW_OFFSET(rec.del, s);
+	SHOW_OFFSET(rec.extent, s);
+}
+
+
+static void print_ocfs_dlm_msg_hdr()
+{
+	ocfs_dlm_msg_hdr s;
+	SHOW_SIZEOF(ocfs_dlm_msg_hdr, s);
+	SHOW_OFFSET(lock_id, s);
+	SHOW_OFFSET(flags, s);
+	SHOW_OFFSET(lock_seq_num, s);
+	SHOW_OFFSET(open_handle, s);
+}
+
+static void print_ocfs_dlm_reply_master()
+{
+	ocfs_dlm_reply_master s;
+	SHOW_SIZEOF(ocfs_dlm_reply_master, s);
+	SHOW_OFFSET(h, s);
+	SHOW_OFFSET(status, s);
+}
+
+
+static void print_ocfs_dlm_disk_vote_reply()
+{
+	ocfs_dlm_disk_vote_reply s;
+	SHOW_SIZEOF(ocfs_dlm_disk_vote_reply, s);
+	SHOW_OFFSET(h, s);
+	SHOW_OFFSET(status, s);
+}
+
+
+static void print_ocfs_dlm_msg()
+{
+	ocfs_dlm_msg s;
+	SHOW_SIZEOF(ocfs_dlm_msg, s);
+	SHOW_OFFSET(magic, s);
+	SHOW_OFFSET(msg_len, s);
+	SHOW_OFFSET(vol_id, s);
+	SHOW_OFFSET(src_node, s);
+	SHOW_OFFSET(dst_node, s);
+	SHOW_OFFSET(msg_type, s);
+	SHOW_OFFSET(check_sum, s);
+	SHOW_OFFSET(msg_buf, s);
+}
+
+
+static void print_ocfs_recv_ctxt()
+{
+	ocfs_recv_ctxt s;
+	SHOW_SIZEOF(ocfs_recv_ctxt, s);
+	SHOW_OFFSET(msg_len, s);
+	SHOW_OFFSET(msg, s);
+	SHOW_OFFSET(status, s);
+#ifdef LINUX_2_5
+	SHOW_OFFSET(ipc_wq, s);
+#else
+	SHOW_OFFSET(ipc_tq, s);
+#endif
+}
+
+int main(int argc, char **argv)
+{
+    if (argc > 1) {
+        if (!strncasecmp(*++argv, "all", 3))
+            show_all = true;
+        else {
+            usage();
+            exit (1);
+        }
+    }
+
+    print_inode_offsets();
+    print_dentry_offsets();
+    print_filp_offsets();
+    print_super_offsets();
+    print_superops_offsets();
+    print_ocfs_lock_res_offsets();
+    print_ocfs_super_offsets();
+    print_ocfs_global_ctxt_offsets();
+    print_ocfs_cleanup_record_offsets();
+    print_ocfs_dlm_reply_master_offsets();
+    print_ocfs_dlm_msg_offsets();
+    print_ocfs_inode_offsets();
+    print_ocfs_alloc_ext();
+    print_ocfs_io_runs();
+    print_ocfs_offset_map();
+    print_ocfs_log_record();
+    print_ocfs_vol_disk_hdr();
+    print_ocfs_file_entry();
+    print_ocfs_extent_group();
+    print_ocfs_alloc_ext();
+    print_ocfs_publish();
+    print_ocfs_vote();
+    print_ocfs_file_entry();
+    print_ocfs_index_node();
+    print_ocfs_index_hdr();
+    print_ocfs_dir_node();
+    print_ocfs_vol_node_map();
+    print_ocfs_vol_layout();
+    print_ocfs_extent_group();
+    print_ocfs_bitmap_lock();
+    print_ocfs_vol_disk_hdr();
+    print_ocfs_disk_lock();
+    print_ocfs_vol_label();
+    print_ocfs_ipc_config_info();
+    print_ocfs_guid();
+    print_ocfs_disk_node_config_info();
+    print_ocfs_node_config_hdr();
+    print_ocfs_cdsl();
+    print_ocfs_free_bitmap();
+    print_ocfs_free_extent_log();
+    print_ocfs_free_log();
+    print_ocfs_delete_log();
+    print_ocfs_recovery_log();
+    print_ocfs_alloc_log();
+    print_ocfs_dir_log();
+    print_ocfs_lock_update();
+    print_ocfs_lock_log();
+    print_ocfs_bcast_rel_log();
+    print_ocfs_cleanup_record();
+    print_ocfs_log_record();
+    print_ocfs_dlm_msg_hdr();
+    print_ocfs_dlm_reply_master();
+    print_ocfs_dlm_disk_vote_reply();
+    print_ocfs_dlm_msg();
+    print_ocfs_recv_ctxt();
+    print_ocfs_extent_map();
+    return 0;
+}

Added: trunk/advanced/sizetest/sizetest.h
===================================================================
--- trunk/advanced/sizetest/sizetest.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/advanced/sizetest/sizetest.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,43 @@
+/*
+ * sizetest.h
+ *
+ * Prints sizes and offsets of structures and its elements.
+ * Useful to ensure cross platform compatibility.
+ *
+ * Copyright (C) 2003 Oracle Corporation.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Sunil Mushran, Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _SIZETEST_H_
+#define _SIZETEST_H_
+
+#include <ocfs.h>
+
+#ifdef USE_HEX
+# define NUMFORMAT  "0x%x"
+#else
+#define NUMFORMAT  "%d"
+# endif
+
+#define SHOW_SIZEOF(x,y)  printf("sizeof("#x") = "NUMFORMAT"\n", sizeof(##y))
+
+#define SHOW_OFFSET(x,y)  printf("\t"#x" = "NUMFORMAT" (%d)\n", \
+				(void *)&(##y.##x)-(void *)&##y, sizeof(##y.##x))
+
+#endif		/* _SIZETEST_H_ */

Added: trunk/autogen.sh
===================================================================
--- trunk/autogen.sh	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/autogen.sh	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+aclocal
+autoconf
+./configure "$@"


Property changes on: trunk/autogen.sh
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/bugfix/Makefile
===================================================================
--- trunk/bugfix/Makefile	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/bugfix/Makefile	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,61 @@
+TOPDIR = ..
+
+include $(TOPDIR)/Preamble.make
+
+WARNINGS = -Wall -Wstrict-prototypes -Wno-format -Wmissing-prototypes \
+           -Wmissing-declarations
+
+ifdef OCFS_DEBUG
+OPTS = -g
+endif
+
+CFLAGS = $(OPTS) -fno-strict-aliasing $(WARNINGS) -pthread
+
+DIST_FILES = bug3123542.c bug3016598.c bug3123542-README.txt bug3016598-README.txt
+
+SBIN_PROGRAMS = bug3016598 bug3123542
+
+INCLUDES = -I$(TOPDIR)/libocfs/Common/inc -I$(TOPDIR)/libocfs/Linux/inc -Iinc -I$(TOPDIR)/libocfs
+DEFINES = -DLINUX -DUSERSPACE_TOOL
+
+OPTIMIZE = -O2
+
+ifeq ($(OCFS_PROCESSOR),ppc64)
+endif
+ifeq ($(OCFS_PROCESSOR),x86_64)
+endif
+ifeq ($(OCFS_PROCESSOR),ia64)
+endif
+ifeq ($(OCFS_PROCESSOR),i686)
+  DEFINES += -D__ILP32__
+endif
+ifeq ($(OCFS_PROCESSOR),i586)
+  DEFINES += -D__ILP32__
+endif
+
+CFLAGS += $(OPTIMIZE)
+
+ifdef OCFS_DEBUG
+DEFINES += -DDEBUG
+endif
+ifdef OCFS_TRACE
+DEFINES += -DTRACE
+endif
+
+
+VERSION_FILES = generic.c ver.c
+VERSION_SRC = ver.c
+VERSION_PREFIX = BUGFIX
+
+DIST_RULES = dist-incdir
+
+bug3016598: bug3016598.o ver.o generic.o
+	$(LINK) -L$(TOPDIR)/libocfs -locfs
+
+bug3123542: bug3123542.o ver.o generic.o
+	$(LINK) -L$(TOPDIR)/libocfs -locfs
+
+dist-incdir:
+	$(TOPDIR)/mkinstalldirs $(DIST_DIR)/inc
+
+include $(TOPDIR)/Postamble.make

Added: trunk/bugfix/bug3016598-README.txt
===================================================================
--- trunk/bugfix/bug3016598-README.txt	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/bugfix/bug3016598-README.txt	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,102 @@
+bug 3016598
+===========
+
+Symptoms
+--------
+* "rmdir foo" of an empty directory "foo" in OCFS fails (or even rm -rf foo)
+* debugocfs output for the undeletable directory shows that num_ent_used
+  is still greater than 0  
+  (ex. debugocfs -d /path/to/dir/ /dev/device)
+* if the "old" file entries immediately following this directory block
+  are inspected with debugocfs, the sync_flags field will be set to
+  OCFS_SYNC_FLAG_MARK_FOR_DELETION on all remaining files in the
+  directory, and thus they are not visible 
+  (ex. debugocfs -X -h ## -l ## -t ocfs_file_entry /dev/device, where 
+   the -h and -l params are the high and low 64-bit offsets to the block in
+   question.  to find the first block in a directory, add 512 to the 
+   node_disk_off field from the "debugocfs -d" above.  each subsequent
+   file entry will be 512 bytes after the previous)
+
+
+Cause
+-----
+At certain rare times in OCFS, a file will be marked as deleted but
+its parent directory will never decrement the num_ent_used count of
+existing files in that directory.  However, the deleted file will be
+marked as such, and therefore skipped when a file listing (ls) is done
+in that directory.  The directory will appear empty but the user will be
+unable to delete it.  This is different from a directory which cannot be
+deleted because it is in use by a process on the node attempting the
+delete or another node in the cluster.  Use standard tools (lsof, fuser)
+to determine whether the directory is simply in use, or whether you
+actually have this corruption in the filesystem.
+
+
+Solution
+--------
+bug3016598 executable:
+
+* The bug3016598 executable is a one-off patch which will "mount" the
+  filesystem, take locks on necessary filesystem structures, make a fix
+  to any affected indices, unlock and unmount.  While it is safe to run
+  this utility (if directed to do so by support), you should attempt to
+  minimize activity on the affected partition and/or directory while
+  running.
+* Use this utility if you are concerned about downtime and cannot afford
+  to bring down the entire cluster to clean up the filesystem.  If the
+  filesystem is already dismounted on all nodes, please see the
+  fsck.ocfs option below.
+* DO NOT run more that one instance of this utility on this node or
+  other nodes in the cluster.
+* DO NOT run any other one-off patch utilities on this node or any other 
+  nodes in the cluster at the same time.
+* DO NOT run fsck.ocfs at the same time as this utility.  (you can and
+  should run fsck.ocfs.ro (readonly) before and after running this patch
+  to verify that the problem is fixed and that no other filesystem
+  corruptions have taken place)
+* This utility requires an autoconfig slot (it defaults to the last one,
+  number 31) and will not be able to run if all slots are filled.  Other
+  nodes will see the utility as a full-fledged node.
+
+
+fsck.ocfs (included as part of OCFS tools):
+
+* The fsck.ocfs command is a full filesystem checker for OCFS.  It does
+  *not* do any filesystem locking and therefore can only be run when the
+  volume in question is dismounted on all nodes.  
+* This utility checks many structures within the filesystem for
+  validity, and can also fix bug 3016598, in addition to several other
+  bugs.
+* A heartbeat check will be performed before running to attempt to
+  prevent the user from making changes while any nodes have this
+  filesystem mounted.  DO NOT circumvent this by mounting on another
+  node immediately after the heartbeat check.  Wait until fsck.ocfs
+  completes before mounting.
+
+
+fsck.ocfs.ro (included as part of OCFS tools):
+
+* This is a readonly version of fsck.ocfs that can be run at any time to
+  detect any of the problems normally found by fsck.ocfs.  Redirect the
+  output of this command to a file to assist support in determining any
+  problems with your filesystem.
+* Can be safely run at any time, but may temporarily do a great deal of
+  I/O against the device.  
+* Sometimes reports false positives for problems.  Filesystem structures
+  are in-flight during some system calls.  Re-run the utility few more
+  times to see if the errors reported are still present.
+
+
+Note about all utilities:
+
+* These utilities require at least read access (and write access for
+  fsck.ocfs and bug3016598) on the device to be checked.
+* For a consistent view of the filesystem, these commands need to use
+  DIRECT-IO to access the device.  With some versions of the linux
+  kernel, this can only be done if you first bind a raw device (see
+  man raw(8) for more details) to the block device.  Also, in some
+  kernel versions, attempting to do DIRECT-IO to a block device will
+  fail, and in other versions it may silently succeed but not actually
+  give you direct access to the device.  It is safest to always bind a
+  raw device to the block device and use this as your target.  Remember
+  to free up the raw device when finished.

Added: trunk/bugfix/bug3016598.c
===================================================================
--- trunk/bugfix/bug3016598.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/bugfix/bug3016598.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,156 @@
+#include <libocfs.h>
+
+extern int fd;
+extern ocfs_super *osb;
+extern struct super_block sb;
+extern ocfs_vol_disk_hdr *vdh;
+extern ocfs_file_entry *fe;
+extern __u32 debug_context;
+extern __u32 debug_level;
+extern __u32 debug_exclude;
+extern ocfs_global_ctxt OcfsGlobalCtxt;
+
+
+
+int do_bugfix(void);
+void print_bugfix_string(void);
+bool find_the_bug(ocfs_dir_node *dir);
+int fix_the_bug(ocfs_dir_node *dir, __u64 offset, __u64 lock_id);
+int scan_directory(__u64 top, int *found);
+
+
+int do_bugfix()
+{
+	int ret;
+	int found = 0;
+
+	ret = scan_directory(vdh->root_off, &found);
+	
+	if (found)
+		printf("Undeletable directory was found %d times.\n", found);
+	else
+		printf("Undeletable directory was not found!  OK.\n");
+
+	return ret;
+}
+
+void print_bugfix_string()
+{
+	fprintf(stderr, "\nThis utility fixes bug#3016598, the undeletable directory bug.\n");
+}
+
+int scan_directory(__u64 top, int *found)
+{
+	int ret, i;
+	__u64 off;
+	ocfs_dir_node *dir = NULL;
+
+	if ((dir = malloc_aligned(OCFS_DEFAULT_DIR_NODE_SIZE)) == NULL) {
+		fprintf(stderr, "failed to alloc %d bytes!  exiting!\n", OCFS_DEFAULT_DIR_NODE_SIZE);
+		exit(ENOMEM);
+	}
+	memset(dir, 0, OCFS_DEFAULT_DIR_NODE_SIZE);
+
+	off = top;
+	while (1) {
+		ret = ocfs_read_dir_node(osb, dir, off);
+		if (ret < 0) {
+			fprintf(stderr, "error during read of %llu : %s\n", off, strerror(errno));
+			return ret;
+		}
+		
+		if (find_the_bug(dir)) {
+			(*found)++;
+			ret = fix_the_bug(dir, off, top);
+		}
+
+		for (i=0; i < dir->num_ent_used; i++)
+		{
+			ocfs_file_entry *fe;
+			fe = FILEENT(dir, i);
+			if (fe->sync_flags && !(fe->sync_flags & DELETED_FLAGS) &&
+			    	fe->attribs & OCFS_ATTRIB_DIRECTORY)
+			{
+				ret = scan_directory(fe->extents[0].disk_off, found);
+			}
+		}
+
+			
+		if (dir->next_node_ptr == -1)
+			break;
+		else
+			off = dir->next_node_ptr;
+	}
+	if (dir)
+		free_aligned(dir);
+
+	if (!found)
+		printf("Undeletable directory was not found!  OK.\n");		
+	return ret;
+}
+
+bool find_the_bug(ocfs_dir_node *dir)
+{
+	int deleted_files, i;
+	
+	/* check the undeletable dir bug, BUG #3016598 */
+	for (i=0, deleted_files=0; i < dir->num_ent_used; i++) {
+		if ((FILEENT(dir, i))->sync_flags & OCFS_SYNC_FLAG_MARK_FOR_DELETION)
+			deleted_files++;
+	}
+	if (dir->num_ent_used && dir->num_ent_used == deleted_files) {
+		/* we hit the bug... fix by zeroing num_ent_used */
+		return true;
+	}
+	return false;
+}
+
+int fix_the_bug(ocfs_dir_node *dir, __u64 offset, __u64 lock_id)
+{
+	int ret = 0, tmpret;
+	ocfs_lock_res *lockres = NULL;
+	ocfs_file_entry *lock_fe = NULL;
+	__u8 num_ent_used = dir->num_ent_used;
+
+
+	/* if we are changing the block being locked   */
+	/* we need to make sure to use the same buffer */
+	if (offset != lock_id) {
+		memset(fe, 0, 512);
+		lock_fe = fe;
+	} else
+		lock_fe = (ocfs_file_entry *)dir;
+
+	if (offset != lock_id) {
+		// it seems that the bug only happens on the topmost
+		return 0;
+	}
+	
+	printf("Undeletable directory found. Fixing.\n");
+
+	// locking the toplevel dir
+	ret = ocfs_acquire_lock (osb, lock_id, OCFS_DLM_EXCLUSIVE_LOCK, FLAG_DIR, 
+				 &lockres, lock_fe);
+
+	if (ret < 0) {
+		fprintf(stderr, "failed to lock directory\n");
+		goto done;
+	}
+	
+	dir->num_ent_used = 0;
+	ret = ocfs_write_disk(osb, dir, 512, offset);
+	if (ret == -1) {
+		fprintf(stderr, "failed to write at offset %u/%u\n", offset);
+		dir->num_ent_used = num_ent_used;
+	}
+	tmpret = ocfs_release_lock(osb, lock_id, OCFS_DLM_EXCLUSIVE_LOCK, FLAG_DIR, 
+			      lockres, lock_fe);
+	if (tmpret < 0) {
+		fprintf(stderr, "failed to release lock\n");
+		if (ret == 0)
+			ret = tmpret;
+	}
+done:
+	printf("Undeletable directory : %s!\n", ret==0 ? "FIXED" : "NOT FIXED");
+	return ret;
+}

Added: trunk/bugfix/bug3123542-README.txt
===================================================================
--- trunk/bugfix/bug3123542-README.txt	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/bugfix/bug3123542-README.txt	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,112 @@
+bug 3123542
+===========
+
+Symptoms
+--------
+* "ls -l" in a directory produces output like the following:
+
+sh-2.05a$ ls -l /ocfs/include/linux/
+ls: /ocfs/include/linux/mroute.h: No such file or directory
+ls: /ocfs/include/linux/mount.h: No such file or directory
+ls: /ocfs/include/linux/modsetver.h: No such file or directory
+ls: /ocfs/include/linux/mm.h: No such file or directory
+total 2871
+-rwxr-xr-x    1 khackel  khackel      7295 Sep 16 10:42 a.out.h
+-rwxr-xr-x    1 khackel  khackel     11089 Sep 16 10:43 ac97_codec.h
+-rwxr-xr-x    1 khackel  khackel      2589 Sep 16 10:43 acct.h
+-rwxr-xr-x    1 khackel  khackel      1338 Sep 16 10:43 adfs_fs.h
+-rwxr-xr-x    1 khackel  khackel       525 Sep 16 10:43 adfs_fs_i.h
+....
+
+* lookup (eg. stat) of a file known to exist fails, but readdir() finds
+  the file as it should
+
+
+Cause
+-----
+In OCFS, unlike most Unix filesystems, filenames are stored as part of
+the file (inode) instead of in the parent directory inode.  All of the
+file information, including its permissions, name, lock, etc., are
+stored in a sector on disk for that file.  The parent directory merely
+maintains an index on these files to keep them sorted alphabetically.
+These directory blocks can maintain exactly 254 files, so for each
+multiple of 254 files within one directory, there will be another
+alpha-sorted index.
+In some rare cases (eg. a node crash) one of these directory indexes may
+be corrupted.  This results in a directory block search that can no
+longer find some filenames because searches through these blocks are
+done alphabetically.  Functions which still scan all blocks of this
+directory will succeed as normal because the index is not needed for a
+full search.  Ultimately this means that the "lost" files are actually
+still intact on disk and not corrupted.  Only the directory index needs
+to be rebuilt.
+
+
+Solution
+--------
+bug3123542 executable:
+
+* The bug3123542 executable is a one-off patch which will "mount" the
+  filesystem, take locks on necessary filesystem structures, make a fix
+  to any affected indices, unlock and unmount.  While it is safe to run
+  this utility (if directed to do so by support), you should attempt to
+  minimize activity on the affected partition and/or directory while
+  running.
+* Use this utility if you are concerned about downtime and cannot afford
+  to bring down the entire cluster to clean up the filesystem.  If the
+  filesystem is already dismounted on all nodes, please see the
+  fsck.ocfs option below.
+* DO NOT run more that one instance of this utility on this node or
+  other nodes in the cluster.
+* DO NOT run any other one-off patch utilities on this node or any other 
+  nodes in the cluster at the same time.
+* DO NOT run fsck.ocfs at the same time as this utility.  (you can and
+  should run fsck.ocfs.ro (readonly) before and after running this patch
+  to verify that the problem is fixed and that no other filesystem
+  corruptions have taken place)
+* This utility requires an autoconfig slot (it defaults to the last one,
+  number 31) and will not be able to run if all slots are filled.  Other
+  nodes will see the utility as a full-fledged node.
+
+
+fsck.ocfs (included as part of OCFS tools):
+
+* The fsck.ocfs command is a full filesystem checker for OCFS.  It does
+  *not* do any filesystem locking and therefore can only be run when the
+  volume in question is dismounted on all nodes.  
+* This utility checks many structures within the filesystem for
+  validity, and can also fix bug 3123542, in addition to several other
+  bugs.
+* A heartbeat check will be performed before running to attempt to
+  prevent the user from making changes while any nodes have this
+  filesystem mounted.  DO NOT circumvent this by mounting on another
+  node immediately after the heartbeat check.  Wait until fsck.ocfs
+  completes before mounting.
+
+
+fsck.ocfs.ro (included as part of OCFS tools):
+
+* This is a readonly version of fsck.ocfs that can be run at any time to
+  detect any of the problems normally found by fsck.ocfs.  Redirect the
+  output of this command to a file to assist support in determining any
+  problems with your filesystem.
+* Can be safely run at any time, but may temporarily do a great deal of
+  I/O against the device.  
+* Sometimes reports false positives for problems.  Filesystem structures
+  are in-flight during some system calls.  Re-run the utility few more
+  times to see if the errors reported are still present.
+
+
+Note about all utilities:
+
+* These utilities require at least read access (and write access for
+  fsck.ocfs and bug3123542) on the device to be checked.
+* For a consistent view of the filesystem, these commands need to use
+  DIRECT-IO to access the device.  With some versions of the linux
+  kernel, this can only be done if you first bind a raw device (see
+  man raw(8) for more details) to the block device.  Also, in some
+  kernel versions, attempting to do DIRECT-IO to a block device will
+  fail, and in other versions it may silently succeed but not actually
+  give you direct access to the device.  It is safest to always bind a
+  raw device to the block device and use this as your target.  Remember
+  to free up the raw device when finished.

Added: trunk/bugfix/bug3123542.c
===================================================================
--- trunk/bugfix/bug3123542.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/bugfix/bug3123542.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,189 @@
+#include <libocfs.h>
+
+extern int fd;
+extern ocfs_super *osb;
+extern struct super_block sb;
+extern ocfs_vol_disk_hdr *vdh;
+extern ocfs_file_entry *fe;
+extern __u32 debug_context;
+extern __u32 debug_level;
+extern __u32 debug_exclude;
+extern ocfs_global_ctxt OcfsGlobalCtxt;
+
+
+
+int do_bugfix(void);
+void print_bugfix_string(void);
+bool find_the_bug(ocfs_dir_node *dir);
+int fix_the_bug(ocfs_dir_node *dir, __u64 offset, __u64 lock_id);
+int scan_directory(__u64 top, int *found);
+static int fe_compare_func(const void *m1, const void *m2);
+
+
+__u8 *dirindex = NULL, *idxtmp = NULL;
+ocfs_dir_node *globaldir = NULL;
+
+
+int do_bugfix()
+{
+	int ret;
+	int found = 0;
+
+	if ((dirindex = malloc(256)) == NULL) {
+		return ENOMEM;
+	}
+	if ((idxtmp = malloc(256)) == NULL) {
+		free(dirindex);
+		return ENOMEM;
+	}
+	ret = scan_directory(vdh->root_off, &found);
+	if (dirindex)
+		free(dirindex);
+	
+	if (found)
+		printf("Bad dir index was found %d times.\n", found);
+	else
+		printf("Bad dir index was not found!  OK.\n");
+
+	return ret;
+}
+
+void print_bugfix_string()
+{
+	fprintf(stderr, "\nThis utility fixes bug#3123542, the bad directory index bug.\n");
+}
+
+int scan_directory(__u64 top, int *found)
+{
+	int ret, i;
+	__u64 off;
+	ocfs_dir_node *dir = NULL;
+
+	if ((dir = malloc_aligned(OCFS_DEFAULT_DIR_NODE_SIZE)) == NULL) {
+		fprintf(stderr, "failed to alloc %d bytes!  exiting!\n", OCFS_DEFAULT_DIR_NODE_SIZE);
+		exit(ENOMEM);
+	}
+	memset(dir, 0, OCFS_DEFAULT_DIR_NODE_SIZE);
+
+	off = top;
+	while (1) {
+		ret = ocfs_read_dir_node(osb, dir, off);
+		if (ret < 0) {
+			fprintf(stderr, "error during read of %llu : %s\n", off, strerror(errno));
+			return ret;
+		}
+		
+		if (find_the_bug(dir)) {
+			(*found)++;
+			ret = fix_the_bug(dir, off, top);
+		}
+
+		for (i=0; i < dir->num_ent_used; i++)
+		{
+			ocfs_file_entry *fe;
+			fe = FILEENT(dir, i);
+			if (fe->sync_flags && !(fe->sync_flags & DELETED_FLAGS) &&
+			    	fe->attribs & OCFS_ATTRIB_DIRECTORY)
+			{
+				ret = scan_directory(fe->extents[0].disk_off, found);
+			}
+		}
+
+			
+		if (dir->next_node_ptr == -1)
+			break;
+		else
+			off = dir->next_node_ptr;
+	}
+	if (dir)
+		free_aligned(dir);
+
+	return ret;
+}
+
+bool find_the_bug(ocfs_dir_node *dir)
+{
+	/* check the dir->index integrity */
+	globaldir = dir;
+	memset(dirindex, 0, 256);
+	memcpy(dirindex, dir->index, dir->num_ent_used);
+	qsort(dirindex, dir->num_ent_used, sizeof(__u8), fe_compare_func);
+
+	if (memcmp(dirindex, dir->index, dir->num_ent_used) != 0)
+		return true;
+
+	return false;
+}
+
+int fix_the_bug(ocfs_dir_node *dir, __u64 offset, __u64 lock_id)
+{
+	int ret = 0, tmpret;
+	ocfs_lock_res *lockres = NULL;
+	ocfs_file_entry *lock_fe = NULL;
+   
+	/* if we are changing the block being locked   */
+	/* we need to make sure to use the same buffer */
+	if (offset != lock_id) {
+		memset(fe, 0, 512);
+		lock_fe = fe;
+	} else
+		lock_fe = (ocfs_file_entry *)dir;
+
+	printf("Bad dir index found. Fixing.\n");
+
+	// locking the toplevel dir
+	ret = ocfs_acquire_lock (osb, lock_id, OCFS_DLM_EXCLUSIVE_LOCK, FLAG_DIR, 
+				 &lockres, lock_fe);
+
+	if (ret < 0) {
+		fprintf(stderr, "failed to lock directory\n");
+		goto done;
+	}
+	
+	memcpy(idxtmp, dir->index, 256);
+	memcpy(dir->index, dirindex, dir->num_ent_used);
+	ret = ocfs_write_disk(osb, dir, 512, offset);
+	if (ret == -1) {
+		fprintf(stderr, "failed to write at offset %u/%u\n", offset);
+		memcpy(dir->index, idxtmp, 256);
+	}
+	tmpret = ocfs_release_lock(osb, lock_id, OCFS_DLM_EXCLUSIVE_LOCK, FLAG_DIR, 
+			      lockres, lock_fe);
+	if (tmpret < 0) {
+		fprintf(stderr, "failed to release lock\n");
+		if (ret == 0)
+			ret = tmpret;
+	}
+done:
+	printf("Bad dir index : %s!\n", ret==0 ? "FIXED" : "NOT FIXED");
+	return ret;
+}
+
+static int fe_compare_func(const void *m1, const void *m2)
+{
+	ocfs_file_entry *fe1, *fe2;
+	__u8 idx1, idx2;
+	int ret;
+
+	if (globaldir == NULL) {
+		fprintf(stderr, "globaldir is null!  exiting!\n");
+		exit(EINVAL);
+	}
+
+	idx1 = *(__u8 *)m1;
+	idx2 = *(__u8 *)m2;
+
+	fe1 = (ocfs_file_entry *) ((char *)FIRST_FILE_ENTRY(globaldir) + (idx1 * OCFS_SECTOR_SIZE));
+	fe2 = (ocfs_file_entry *) ((char *)FIRST_FILE_ENTRY(globaldir) + (idx2 * OCFS_SECTOR_SIZE));
+	if (fe1->sync_flags & OCFS_SYNC_FLAG_NAME_DELETED ||
+	    (!(fe1->sync_flags & OCFS_SYNC_FLAG_VALID)) ||
+	    fe2->sync_flags & OCFS_SYNC_FLAG_NAME_DELETED ||
+	    (!(fe2->sync_flags & OCFS_SYNC_FLAG_VALID))) {
+		return 0;
+	}
+	ret = strncmp(fe1->filename, fe2->filename, 255);
+	
+	return -ret;
+}
+
+

Added: trunk/bugfix/generic.c
===================================================================
--- trunk/bugfix/generic.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/bugfix/generic.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,178 @@
+#include <libocfs.h>
+
+
+void usage(int argc, char **argv);
+void init_global_context(void);
+void version(char *progname);
+bool disclaimer(void);
+
+
+extern void print_bugfix_string(void);
+extern int do_bugfix(void);
+
+
+int fd = -1;
+ocfs_super *osb = NULL;
+struct super_block sb;
+ocfs_vol_disk_hdr *vdh = NULL;
+ocfs_file_entry *fe = NULL;
+__u32 debug_context = 0;
+__u32 debug_level = 0;
+__u32 debug_exclude = 0;
+ocfs_global_ctxt OcfsGlobalCtxt;
+
+
+
+#define DISCLAIMER_MESSAGE      \
+"WARNING:       This utility fixes a particular bug with OCFS.  Only run this utility \n"\
+"               if directed to do so by Oracle personnel.  \n"\
+"!!! NOTE !!!:  DO NOT run more than one instance of this command, or any other bugfix \n"\
+"               commands at the same time on this volume!  Doing so MAY CORRUPT YOUR \n"\
+"               FILESYSTEM!  Also, please attempt to limit the I/O being performed on \n"\
+"               this partition at the time that you run the command.\n"\
+"\n"\
+"Are you sure you want to run this utility? (yes, [no]) "
+
+
+void usage(int argc, char **argv)
+{
+	fprintf(stderr, "\n");
+	fprintf(stderr, "usage: %s /dev/device\n", argv[0]);
+	fprintf(stderr, "       where /dev/device is a raw device bound to your ocfs block device\n");
+	fprintf(stderr, "       (please see the raw(8) manpage for more information) or an ocfs \n");
+	fprintf(stderr, "       block device which supports direct-I/O\n");
+	fprintf(stderr, "\n");
+	print_bugfix_string();
+}
+
+void init_global_context()
+{
+	char *tmp;
+
+	memset(&OcfsGlobalCtxt, 0, sizeof(ocfs_global_ctxt));
+	OcfsGlobalCtxt.obj_id.type = OCFS_TYPE_GLOBAL_DATA;
+	OcfsGlobalCtxt.obj_id.size = sizeof (ocfs_global_ctxt);
+	OcfsGlobalCtxt.pref_node_num = 31;
+	OcfsGlobalCtxt.node_name = "user-tool";
+	OcfsGlobalCtxt.comm_info.type = OCFS_UDP;
+	OcfsGlobalCtxt.comm_info.ip_addr = "0.0.0.0";
+	OcfsGlobalCtxt.comm_info.ip_port = OCFS_IPC_DEFAULT_PORT;
+	OcfsGlobalCtxt.comm_info.ip_mask = NULL;
+	OcfsGlobalCtxt.comm_info_read = true;
+	memset(&OcfsGlobalCtxt.guid.id.host_id, 'f', HOSTID_LEN);
+	memset(&OcfsGlobalCtxt.guid.id.mac_id,  '0', MACID_LEN);
+
+	tmp = getenv("debug_level");
+	if (tmp)
+		debug_level = atoi(tmp);
+	tmp = getenv("debug_context");
+	if (tmp)
+		debug_context = atoi(tmp);
+	tmp = getenv("debug_exclude");
+	if (tmp)
+		debug_exclude = atoi(tmp);
+}
+
+
+bool disclaimer()
+{
+	char response[10];
+	int i;
+
+	print_bugfix_string();
+	printf(DISCLAIMER_MESSAGE);
+
+	if (fgets(response, 10, stdin) == NULL)
+		return false;
+	
+	for (i=0; i<10; i++)
+		if (response[i] == '\n' || response[i] == '\r')
+			response[i] = '\0';
+
+	if (strcasecmp(response, "yes")==0) {
+		return true;
+	}
+	return false;
+}
+
+
+int main(int argc, char **argv)
+{
+	int ret = 0;
+	bool mounted = false;
+	int flags;
+	struct stat st;
+
+	init_global_context();
+	version(argv[0]);
+
+	if (argc < 2 || stat(argv[1], &st) != 0 ||
+	    !(S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) ) {
+		usage(argc, argv);
+		exit(EINVAL);
+	}
+
+	if (S_ISCHR(st.st_mode))
+		flags = O_RDWR | O_LARGEFILE | O_SYNC;
+	else
+		flags = O_RDWR | O_LARGEFILE | O_DIRECT | O_SYNC;
+
+	if (!disclaimer()) 
+		exit(EINVAL);
+	
+	fd = open(argv[1], flags);
+	if (fd == -1) {
+		usage(argc, argv);
+		exit(EINVAL);
+	}
+	
+	if ((vdh = malloc_aligned(1024)) == NULL) {
+		fprintf(stderr, "failed to alloc %d bytes!  exiting!\n", 1024);
+		exit(ENOMEM);
+	}
+	if ((fe = malloc_aligned(512)) == NULL) {
+		fprintf(stderr, "failed to alloc %d bytes!  exiting!\n", 512);
+		exit(ENOMEM);
+	}
+
+	memset(vdh, 0, 1024);
+	memset(fe, 0, 512);
+	memset(&sb, 0, sizeof(struct super_block));
+	sb.s_dev = fd;
+
+	ret = ocfs_read_disk_header ((__u8 **)&vdh, &sb);
+	if (ret < 0) {
+		fprintf(stderr, "failed to read header\n");
+		goto done;
+	}
+
+	ret = ocfs_mount_volume (&sb, false);
+	if (ret < 0) {
+		fprintf(stderr, "failed to mount\n");
+		goto done;
+	}
+	
+	mounted = true;
+	osb = sb.u.generic_sbp;
+
+	ret = do_bugfix();
+
+
+done:
+	if (mounted) {
+		int tmp;
+		if ((tmp = ocfs_dismount_volume (&sb)) < 0) {
+			fprintf(stderr, "dismount failed, ret = %d\n", tmp);
+			if (ret == 0)
+				ret = tmp;
+		}
+	}
+	if (fe)
+		free_aligned(fe);
+	if (vdh)
+		free_aligned(vdh);
+	if (fd != -1)
+		close(fd);
+
+	exit(ret);
+}

Added: trunk/bugfix/ver.c
===================================================================
--- trunk/bugfix/ver.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/bugfix/ver.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,41 @@
+/*
+ * ver.c
+ *
+ * prints version
+ *
+ * Copyright (C) 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Sunil Mushran
+ */
+
+#include <stdio.h>
+
+void version(char *progname);
+
+/*
+ * version()
+ *
+ */
+void version(char *progname)
+{
+	printf("%s %s %s (build %s)\n", progname,
+					BUGFIX_BUILD_VERSION,
+					BUGFIX_BUILD_DATE,
+					BUGFIX_BUILD_MD5);
+	return ;
+}				/* version */

Added: trunk/config.guess
===================================================================
--- trunk/config.guess	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/config.guess	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,1432 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+timestamp='2004-01-05'
+
+# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Per Bothner <per at bothner.com>.
+# Please send patches to <config-patches at gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches at gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&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 -q "$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 ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi at 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 ;;
+	    *) 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 0 ;;
+    amiga:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    arc:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    hp300:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mac68k:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    macppc:OpenBSD:*:*)
+	echo powerpc-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mvme68k:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mvme88k:OpenBSD:*:*)
+	echo m88k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mvmeppc:OpenBSD:*:*)
+	echo powerpc-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    pegasos:OpenBSD:*:*)
+	echo powerpc-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    pmax:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    sgi:OpenBSD:*:*)
+	echo mipseb-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    sun3:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    wgrisc:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    *:OpenBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    alpha:OSF1:*:*)
+	if test $UNAME_RELEASE = "V4.0"; then
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+	fi
+	# 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 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/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	exit 0 ;;
+    Alpha*:OpenVMS:*:*)
+	echo alpha-hp-vms
+	exit 0 ;;
+    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 0 ;;
+    21064:Windows_NT:50:3)
+	echo alpha-dec-winnt3.5
+	exit 0 ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit 0;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit 0 ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-morphos
+	exit 0 ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit 0 ;;
+    *:OS400:*:*)
+        echo powerpc-ibm-os400
+	exit 0 ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit 0;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit 0;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee at 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 0 ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit 0 ;;
+    DRS?6000:unix:4.0:6*)
+	echo sparc-icl-nx6
+	exit 0 ;;
+    DRS?6000:UNIX_SV:4.2*:7*)
+	case `/usr/bin/uname -p` in
+	    sparc) echo sparc-icl-nx7 && exit 0 ;;
+	esac ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    i86pc:SunOS:5.*:*)
+	echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    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 0 ;;
+    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 0 ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit 0 ;;
+    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 0 ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos${UNAME_RELEASE}
+	exit 0 ;;
+    # 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 0 ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit 0 ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit 0 ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit 0 ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten${UNAME_RELEASE}
+	exit 0 ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit 0 ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit 0 ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit 0 ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit 0 ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c \
+	  && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+	  && exit 0
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit 0 ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit 0 ;;
+    Motorola:*:4.3:PL8-*)
+	echo powerpc-harris-powermax
+	exit 0 ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+	echo powerpc-harris-powermax
+	exit 0 ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit 0 ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit 0 ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit 0 ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit 0 ;;
+    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 0 ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit 0 ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit 0 ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit 0 ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit 0 ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+	exit 0 ;;
+    ????????: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 0 ;;              # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit 0 ;;
+    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 0 ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		eval $set_cc_for_build
+		sed 's/^		//' << EOF >$dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		$CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+		echo rs6000-ibm-aix3.2.5
+	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 0 ;;
+    *:AIX:*:[45])
+	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 0 ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit 0 ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+	echo romp-ibm-bsd4.4
+	exit 0 ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+	exit 0 ;;                           # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit 0 ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit 0 ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit 0 ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit 0 ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	case "${UNAME_MACHINE}" in
+	    9000/31? )            HP_ARCH=m68000 ;;
+	    9000/[34]?? )         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+		if [ -x /usr/bin/getconf ]; then
+		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                        esac ;;
+                    esac
+		fi
+		if [ "${HP_ARCH}" = "" ]; then
+		    eval $set_cc_for_build
+		    sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+              	{
+              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+              	case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+              	    switch (bits)
+              		{
+              		case 64: puts ("hppa2.0w"); break;
+              		case 32: puts ("hppa2.0n"); break;
+              		default: puts ("hppa2.0"); break;
+              		} break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+              	    puts ("hppa2.0"); break;
+              #endif
+              	default: puts ("hppa1.0"); break;
+              	}
+                  exit (0);
+              }
+EOF
+		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+		    test -z "$HP_ARCH" && HP_ARCH=hppa
+		fi ;;
+	esac
+	if [ ${HP_ARCH} = "hppa2.0w" ]
+	then
+	    # avoid double evaluation of $set_cc_for_build
+	    test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
+	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
+	    then
+		HP_ARCH="hppa2.0w"
+	    else
+		HP_ARCH="hppa64"
+	    fi
+	fi
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit 0 ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux${HPUX_REV}
+	exit 0 ;;
+    3050*:HI-UX:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+	echo unknown-hitachi-hiuxwe2
+	exit 0 ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+	echo hppa1.1-hp-bsd
+	exit 0 ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit 0 ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit 0 ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+	echo hppa1.1-hp-osf
+	exit 0 ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit 0 ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo ${UNAME_MACHINE}-unknown-osf1mk
+	else
+	    echo ${UNAME_MACHINE}-unknown-osf1
+	fi
+	exit 0 ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit 0 ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+        exit 0 ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+        exit 0 ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+        exit 0 ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+        exit 0 ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+        exit 0 ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    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 0 ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    *:UNICOS/mp:*:*)
+	echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    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 0 ;;
+    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 0 ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    *:BSD/OS:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    *:FreeBSD:*:*)
+	# Determine whether the default compiler uses glibc.
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <features.h>
+	#if __GLIBC__ >= 2
+	LIBC=gnu
+	#else
+	LIBC=
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+	# GNU/KFreeBSD systems have a "k" prefix to indicate we are using
+	# FreeBSD's kernel, but not the complete OS.
+	case ${LIBC} in gnu) kernel_only='k' ;; esac
+	echo ${UNAME_MACHINE}-unknown-${kernel_only}freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
+	exit 0 ;;
+    i*:CYGWIN*:*)
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit 0 ;;
+    i*:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
+	exit 0 ;;
+    i*:PW*:*)
+	echo ${UNAME_MACHINE}-pc-pw32
+	exit 0 ;;
+    x86:Interix*:[34]*)
+	echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+	exit 0 ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+	echo i${UNAME_MACHINE}-pc-mks
+	exit 0 ;;
+    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 0 ;;
+    i*:UWIN*:*)
+	echo ${UNAME_MACHINE}-pc-uwin
+	exit 0 ;;
+    p*:CYGWIN*:*)
+	echo powerpcle-unknown-cygwin
+	exit 0 ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    *:GNU:*:*)
+	# the GNU system
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit 0 ;;
+    *: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 0 ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit 0 ;;
+    arm*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    cris:Linux:*:*)
+	echo cris-axis-linux-gnu
+	exit 0 ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    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 | grep ^CPU=`
+	test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+	;;
+    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 | grep ^CPU=`
+	test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+	;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-gnu
+	exit 0 ;;
+    ppc64:Linux:*:*)
+	echo powerpc64-unknown-linux-gnu
+	exit 0 ;;
+    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 0 ;;
+    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 0 ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-gnu
+	exit 0 ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo ${UNAME_MACHINE}-ibm-linux
+	exit 0 ;;
+    sh64*:Linux:*:*)
+    	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    sh*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    x86_64:Linux:*:*)
+	echo x86_64-unknown-linux-gnu
+	exit 0 ;;
+    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 0 ;;
+	  coff-i386)
+		echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+		exit 0 ;;
+	  "")
+		# 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 0 ;;
+	esac
+	# Determine whether the default compiler is a.out or elf
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <features.h>
+	#ifdef __ELF__
+	# ifdef __GLIBC__
+	#  if __GLIBC__ >= 2
+	LIBC=gnu
+	#  else
+	LIBC=gnulibc1
+	#  endif
+	# else
+	LIBC=gnulibc1
+	# endif
+	#else
+	#ifdef __INTEL_COMPILER
+	LIBC=gnu
+	#else
+	LIBC=gnuaout
+	#endif
+	#endif
+	#ifdef __dietlibc__
+	LIBC=dietlibc
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+	test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
+	test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+	;;
+    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 0 ;;
+    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 0 ;;
+    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 0 ;;
+    i*86:XTS-300:*:STOP)
+	echo ${UNAME_MACHINE}-unknown-stop
+	exit 0 ;;
+    i*86:atheos:*:*)
+	echo ${UNAME_MACHINE}-unknown-atheos
+	exit 0 ;;
+	i*86:syllable:*:*)
+	echo ${UNAME_MACHINE}-pc-syllable
+	exit 0 ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit 0 ;;
+    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 0 ;;
+    i*86:*:5:[78]*)
+	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 0 ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	exit 0 ;;
+    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 0 ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit 0 ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit 0 ;;
+    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 0 ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit 0 ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+	echo m68k-convergent-sysv
+	exit 0 ;;
+    M680?0:D-NIX:5.3:*)
+	echo m68k-diab-dnix
+	exit 0 ;;
+    M68*:*:R3V[567]*:*)
+	test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+    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)
+	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 0
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && echo i486-ncr-sysv4 && exit 0 ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit 0 ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv${UNAME_RELEASE}
+	exit 0 ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit 0 ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit 0 ;;
+    *: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 0 ;;
+    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                      # says <Richard.M.Bartel at ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit 0 ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes at openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit 0 ;;
+    *:*:*:FTX*)
+	# From seanf at swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit 0 ;;
+    *:VOS:*:*)
+	# From Paul.Green at stratus.com.
+	echo hppa1.1-stratus-vos
+	exit 0 ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux${UNAME_RELEASE}
+	exit 0 ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit 0 ;;
+    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 0 ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit 0 ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit 0 ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit 0 ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux${UNAME_RELEASE}
+	exit 0 ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux${UNAME_RELEASE}
+	exit 0 ;;
+    SX-6:SUPER-UX:*:*)
+	echo sx6-nec-superux${UNAME_RELEASE}
+	exit 0 ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+	exit 0 ;;
+    *:Rhapsody:*:*)
+	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+	exit 0 ;;
+    *:Darwin:*:*)
+	case `uname -p` in
+	    *86) UNAME_PROCESSOR=i686 ;;
+	    powerpc) UNAME_PROCESSOR=powerpc ;;
+	esac
+	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+	exit 0 ;;
+    *: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 0 ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit 0 ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk${UNAME_RELEASE}
+	exit 0 ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit 0 ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit 0 ;;
+    DS/*:UNIX_System_V:*:*)
+	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+	exit 0 ;;
+    *: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 0 ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit 0 ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit 0 ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit 0 ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit 0 ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit 0 ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit 0 ;;
+    SEI:*:*:SEIUX)
+        echo mips-sei-seiux${UNAME_RELEASE}
+	exit 0 ;;
+    *:DRAGONFLY:*:*)
+	echo ${UNAME_MACHINE}-unknown-dragonfly${UNAME_RELEASE}
+	exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+	  ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+	printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+	printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# 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 0 ;;
+    c2*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit 0 ;;
+    c34*)
+	echo c34-convex-bsd
+	exit 0 ;;
+    c38*)
+	echo c38-convex-bsd
+	exit 0 ;;
+    c4*)
+	echo c4-convex-bsd
+	exit 0 ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+    ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches at gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:


Property changes on: trunk/config.guess
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/config.sub
===================================================================
--- trunk/config.sub	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/config.sub	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,1537 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+timestamp='2004-01-05'
+
+# 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Please send patches to <config-patches at gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches at gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit 0;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | linux-dietlibc | 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)
+		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
+		;;
+	-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/'`
+		;;
+	-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 \
+	| c4x | clipper \
+	| d10v | d30v | dlx | dsp16xx \
+	| fr30 | frv \
+	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| i370 | i860 | i960 | ia64 \
+	| ip2k | iq2000 \
+	| m32r | m68000 | m68k | m88k | mcore \
+	| mips | mipsbe | mipseb | mipsel | mipsle \
+	| mips16 \
+	| mips64 | mips64el \
+	| mips64vr | mips64vrel \
+	| mips64orion | mips64orionel \
+	| mips64vr4100 | mips64vr4100el \
+	| mips64vr4300 | mips64vr4300el \
+	| mips64vr5000 | mips64vr5000el \
+	| mipsisa32 | mipsisa32el \
+	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa64 | mipsisa64el \
+	| mipsisa64r2 | mipsisa64r2el \
+	| mipsisa64sb1 | mipsisa64sb1el \
+	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipstx39 | mipstx39el \
+	| mn10200 | mn10300 \
+	| msp430 \
+	| ns16k | ns32k \
+	| openrisc | or32 \
+	| pdp10 | pdp11 | pj | pjl \
+	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+	| pyramid \
+	| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+	| sh64 | sh64le \
+	| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
+	| strongarm \
+	| tahoe | thumb | tic4x | tic80 | tron \
+	| v850 | v850e \
+	| we32k \
+	| x86 | xscale | 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)
+		;;
+
+	# 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-* \
+	| bs2000-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+	| clipper-* | cydra-* \
+	| d10v-* | d30v-* | dlx-* \
+	| elxsi-* \
+	| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+	| h8300-* | h8500-* \
+	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| i*86-* | i860-* | i960-* | ia64-* \
+	| ip2k-* | iq2000-* \
+	| m32r-* \
+	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+	| m88110-* | m88k-* | mcore-* \
+	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+	| mips16-* \
+	| mips64-* | mips64el-* \
+	| mips64vr-* | mips64vrel-* \
+	| mips64orion-* | mips64orionel-* \
+	| mips64vr4100-* | mips64vr4100el-* \
+	| mips64vr4300-* | mips64vr4300el-* \
+	| mips64vr5000-* | mips64vr5000el-* \
+	| mipsisa32-* | mipsisa32el-* \
+	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa64-* | mipsisa64el-* \
+	| mipsisa64r2-* | mipsisa64r2el-* \
+	| mipsisa64sb1-* | mipsisa64sb1el-* \
+	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipstx39-* | mipstx39el-* \
+	| msp430-* \
+	| none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
+	| orion-* \
+	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+	| pyramid-* \
+	| romp-* | rs6000-* \
+	| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+	| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
+	| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+	| tahoe-* | thumb-* \
+	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+	| tron-* \
+	| v850-* | v850e-* | vax-* \
+	| we32k-* \
+	| x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
+	| xtensa-* \
+	| ymp-* \
+	| z8k-*)
+		;;
+	# 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
+		;;
+	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
+		;;
+	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
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	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
+		;;
+	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
+		;;
+	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
+		;;
+	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
+		;;
+	mmix*)
+		basic_machine=mmix-knuth
+		os=-mmixware
+		;;
+	monitor)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	morphos)
+		basic_machine=powerpc-unknown
+		os=-morphos
+		;;
+	msdos)
+		basic_machine=i386-pc
+		os=-msdos
+		;;
+	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
+		;;
+	nv1)
+		basic_machine=nv1-cray
+		os=-unicosmp
+		;;
+	nsr-tandem)
+		basic_machine=nsr-tandem
+		;;
+	op50n-* | op60c-*)
+		basic_machine=hppa1.1-oki
+		os=-proelf
+		;;
+	or32 | or32-*)
+		basic_machine=or32-unknown
+		os=-coff
+		;;
+	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
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+	pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	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
+		;;
+	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
+		;;
+	sei)
+		basic_machine=mips-sei
+		os=-seiux
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	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
+		;;
+	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
+		;;
+	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
+		;;
+	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
+		;;
+	sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
+		basic_machine=sh-unknown
+		;;
+	sh64)
+		basic_machine=sh64-unknown
+		;;
+	sparc | sparcv9 | sparcv9b)
+		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* | -netbsd* | -openbsd* | -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-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*)
+	# 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* \
+	      | -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
+		;;
+	-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
+	*-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
+		;;
+	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
+		;;
+	*-ibm)
+		os=-aix
+		;;
+	*-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 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:


Property changes on: trunk/config.sub
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/configure.in
===================================================================
--- trunk/configure.in	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/configure.in	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,156 @@
+AC_INIT(libocfs/Makefile)
+
+PACKAGE=ocfs-tools
+VERSION=1.1
+
+AC_SUBST(PACKAGE)
+
+# Adjust these for the software version.
+MAJOR_VERSION=1
+MINOR_VERSION=1
+MICRO_VERSION=0
+EXTRA_VERSION=BETA
+
+# Adjust this only to bump the RPM packaging version
+RPM_VERSION=1
+
+DIST_VERSION=$MAJOR_VERSION.$MINOR_VERSION.$MICRO_VERSION
+VERSION=$DIST_VERSION-$EXTRA_VERSION
+
+AC_SUBST(MAJOR_VERSION)
+AC_SUBST(MINOR_VERSION)
+AC_SUBST(MICRO_VERSION)
+AC_SUBST(EXTRA_VERSION)
+
+AC_SUBST(DIST_VERSION)
+AC_SUBST(VERSION)
+AC_SUBST(RPM_VERSION)
+
+AC_CANONICAL_HOST
+
+OCFS_PROCESSOR=
+
+case "$host" in
+  *-*-linux*)
+    ;;
+  *)
+    AC_MSG_ERROR([This filesystem will only work on Linux])
+    ;;
+esac
+
+case "$host_cpu" in
+  powerpc64)
+    OCFS_PROCESSOR="ppc64"
+    ;;
+  ia64)
+    OCFS_PROCESSOR="ia64"
+    ;;
+  x86_64)
+    OCFS_PROCESSOR="x86_64"
+    ;;
+  i386|i486|i586|i686|i786|k6|k7)
+    OCFS_PROCESSOR="i686"
+    ;;
+  *)
+    AC_MSG_ERROR([not configured for "$host_cpu"])
+    ;;
+esac
+
+AC_SUBST(OCFS_PROCESSOR)
+
+if test -z "$TOOLSARCH"; then
+    case "$host_cpu" in
+    x86_64|i386|ppc|ia64)
+        TOOLSARCH="$host_cpu"
+        ;;
+    i486|i586|i686|i786|k6|k7)
+        TOOLSARCH="i386"
+        ;;
+    powerpc64)
+        TOOLSARCH="ppc"
+        ;;
+    *)
+        AC_MSG_RESULT([not found])
+        AC_MSG_ERROR([invalid or unsupported CPU type])
+        ;;
+    esac
+fi
+
+AC_SUBST(TOOLSARCH)
+
+AC_PROG_CC
+AC_PROG_CPP
+
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_RANLIB
+
+AC_PATH_PROG(AR, ar)
+
+AC_CHECK_PROGS(RPMBUILD, rpmbuild rpm)
+AC_MSG_CHECKING([absolute rpm file directory])
+RPM_TOPDIR="`pwd`"
+AC_MSG_RESULT([$RPM_TOPDIR])
+AC_SUBST(RPM_TOPDIR)
+
+AC_HEADER_STDC
+AC_C_CONST
+
+if test "x$GCC" != "xyes"; then
+  AC_MSG_ERROR(GCC is required)
+fi
+
+AC_ARG_ENABLE(debug, [  --enable-debug=[yes/no]         Turn on debugging [default=no]],,enable_debug=no)
+OCFS_DEBUG=
+if test "x$enable_debug" = "xyes"; then
+  OCFS_DEBUG=yes
+fi
+AC_SUBST(OCFS_DEBUG)
+
+AC_ARG_ENABLE(memdebug, [  --enable-memdebug=[yes/no]     Turn on memory debugging [default=no]],,enable_memdebug=no)
+OCFS_MEMDEBUG=
+if test "x$enable_memdebug" = "xyes"; then
+  OCFS_MEMDEBUG=yes
+fi
+AC_SUBST(OCFS_MEMDEBUG)
+
+AC_ARG_ENABLE(trace, [  --enable-trace=[yes/no]         Turn on tracing [default=no]],,enable_trace=no)
+OCFS_TRACE=
+if test "x$enable_trace" = "xyes"; then
+  OCFS_TRACE=yes
+fi
+AC_SUBST(OCFS_TRACE)
+
+GLIB_REQUIRED_VERSION=1.2.8
+GTK_REQUIRED_VERSION=1.2.8
+
+AM_PATH_GLIB($GLIB_REQUIRED_VERSION, :,
+  AC_MSG_ERROR([Glib $GLIB_REQUIRED_VERSION or better is required.]))
+
+OCFSTOOL=
+
+AC_ARG_ENABLE(ocfstool, [  --enable-ocfstool=[yes/no]       Build GUI frontend [default=yes]],,enable_ocfstool=yes)
+
+if test "x$enable_ocfstool" = "xyes"; then
+  AM_PATH_GTK($GTK_REQUIRED_VERSION, have_gtk=yes, have_gtk=no)
+                                                                                
+  if test "x$have_gtk" = "xyes"; then
+    OCFSTOOL=yes
+  else
+    AC_MSG_WARN([GTK+ $GTK_REQUIRED_VERSION or better not found, ocfstool will not be built])
+  fi
+fi
+                                                                                
+AC_SUBST(OCFSTOOL)
+
+AC_OUTPUT([
+Config.make
+debugocfs/debugocfs.1
+fsck/fsck.ocfs.1
+format/mkfs.ocfs.1
+format/resizeocfs.1
+ocfs_uid_gen/ocfs_uid_gen.1
+load_ocfs/load_ocfs.1
+ocfstool/ocfstool.1
+vendor/common/ocfs-tools.spec
+])

Added: trunk/debugocfs/Cscope.make
===================================================================
--- trunk/debugocfs/Cscope.make	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/debugocfs/Cscope.make	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,8 @@
+cscope:
+	rm -f cscope.*
+	echo "-k" >> cscope.files
+	echo "-I ../../ocfs2/Common/inc" >> cscope.files
+	echo "-I ../../ocfs2/Linux/inc" >> cscope.files
+	find . -name '*.c' -print >>cscope.files
+	find . -name '*.h' -print >>cscope.files
+	cscope -b

Added: trunk/debugocfs/Makefile
===================================================================
--- trunk/debugocfs/Makefile	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/debugocfs/Makefile	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,75 @@
+TOPDIR = ..
+
+include $(TOPDIR)/Preamble.make
+
+ifdef OCFS_DEBUG
+  OPTS = -g
+endif
+
+BIN_PROGRAMS = debugocfs extfinder
+
+LIBRARIES = libdebugocfs.a
+
+# Too many warnings in 1.0 branch (cleaned in 2.0)
+#WARNINGS = -Wall -Wstrict-prototypes -Wno-format -Wmissing-prototypes \
+#           -Wmissing-declarations
+
+CFLAGS = $(OPTS) -fno-strict-aliasing $(WARNINGS)
+
+INCLUDES = -I. -I$(TOPDIR)/libocfs/Common/inc -I$(TOPDIR)/libocfs/Linux/inc -I$(TOPDIR)/libocfs
+DEFINES = -DLINUX -DUSERSPACE_TOOL -DDEBUGOCFS
+
+OPTIMIZE = -O2
+
+ifeq ($(OCFS_PROCESSOR),ppc64)
+endif
+ifeq ($(OCFS_PROCESSOR),x86_64)
+  CFLAGS += -m64
+endif
+ifeq ($(OCFS_PROCESSOR),ia64)
+endif
+ifeq ($(OCFS_PROCESSOR),i686)
+  DEFINES += -D__ILP32__
+endif
+
+CFLAGS += $(OPTIMIZE)
+
+ifdef OCFS_DEBUG
+  DEFINES += -DDEBUG
+endif
+
+extfinder_CFLAGS = $(GLIB_CFLAGS)
+
+test_CFLAGS = $(GLIB_CFLAGS)
+
+CLEAN_FILES = test
+
+MANS = debugocfs.1
+
+VERSION_FILES = debugocfs.c debugocfs.h libdebugocfs.h test.c print.c libdebugocfs.c io.c main.c extfinder.c
+VERSION_SRC = main.c extfinder.c
+VERSION_PREFIX = OCFS
+
+DIST_FILES = $(VERSION_FILES) $(VERSION_SRC) debugocfs.1.in
+
+test: test.o libdebugocfs.a
+	$(LINK) -L. -ldebugocfs $(GTK_LIBS)
+
+extfinder: extfinder.o ../libocfs/libocfs.a
+	$(LINK) $(GLIB_LIBS) -lglib 
+
+debugocfs: print.o debugocfs.o io.o main.o ../libocfs/libocfs.a
+	$(LINK) -pthread -L$(TOPDIR)/libocfs -locfs
+
+dbg.o: debugocfs.c
+	$(CC) $(CFLAGS) $(INCLUDES) $(GTK_CFLAGS) -DLIBDEBUGOCFS $(DEFINES) -o $@ -c $<
+
+libdebugocfs.o: libdebugocfs.c
+	$(CC) $(CFLAGS) $(INCLUDES) $(GTK_CFLAGS) -DLIBDEBUGOCFS $(DEFINES) -o $@ -c $<
+
+libdebugocfs.a: io.o dbg.o libdebugocfs.o
+	rm -f $@
+	$(AR) r $@ $^
+	$(RANLIB) $@
+
+include $(TOPDIR)/Postamble.make

Added: trunk/debugocfs/debugocfs.1.in
===================================================================
--- trunk/debugocfs/debugocfs.1.in	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/debugocfs/debugocfs.1.in	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,108 @@
+.TH "debugocfs" "1" "November 2003" "Version @VERSION@" "OCFS Manual Pages"
+.SH "NAME"
+debugocfs \- Utility to dump information from an OCFS partition.
+.SH "SYNOPSIS"
+\fBdebugocfs\fR [\-?] [\-h] [\-g] [\-l] [\-v range] [\-p range] [\-d /dir/name] [\-D /dir/name] [\-f /file/name [\-s /path/to/file]] [\-a range] [\-A range] [\-b range] [\-B range] [\-r range] [\-c range] [\-L range] [\-M range] [\-n nodenum] /dev/name
+.SH "DESCRIPTION"
+.PP 
+\fBdebugocfs\fR is a utility used to dump an OCFS file system information. The \fBdebugocfs\fR utility is to be used under support direction and should use a bound specific raw device instead of the proper device (/dev/sdxx).
+.SH "OPTIONS"
+.TP
+\fB\-h\fR 
+Dumps the OCFS header information.
+
+.TP
+\fB\-g\fR 
+Dumps the OCFS bitmap information.
+
+.TP
+\fB\-l\fR 
+Dumps the OCFS full listing of all file entries.
+
+.TP
+\fB\-v\fR 
+Dumps the OCFS vote sector information.
+
+.TP
+\fB\-2\fR 
+Prints 8-byte number as 2 4byte numbers.
+
+.TP
+\fB\-p\fR \fIrange\fR
+Dumps the OCFS publish sector for a given \fIrange\fR.. 
+
+
+.TP
+\fB\-d\fR \fI/dir/name/\fR
+Dumps first ocfs_dir_node structure for a given path "\fI/dir/name\fR".
+
+.TP
+\fB\-D\fR \fI/dir/name\fR
+Dumps all ocfs_dir_node structures for a given path "\fI/dir/name\fR".
+
+.TP
+\fB\-f\fR \fI/file/name\fR
+Dumps ocfs_file_entry structure for a given file "\fI/file/name\fR".
+
+.TP
+\fB\-F\fR \fI/file/name\fR
+Dumps ocfs_file_entry and ocfs_extent_group structures for a given file "\fI/file/name\fR".
+
+.TP
+\fB\-s\fR \fI/path/to/file\fR
+suck file out to a given location "\fI/path/to/file\fR".
+
+.TP
+\fB\-a\fR \fIrange\fR
+Dumps file allocation system file for a given \fIrange\fR.
+
+.TP
+\fB\-A\fR \fIrange\fR
+Dumps dir allocation system file for a given \fIrange\fR.
+
+.TP
+\fB\-b\fR \fIrange\fR
+Dumps file allocation bitmap system file for a given \fIrange\fR.
+
+.TP
+\fB\-B\fR \fIrange\fR
+Dumps dir allocation bitmap system file for a given \fIrange\fR.
+
+.TP
+\fB\-r\fR \fIrange\fR
+Recover log file system file for a given \fIrange\fR.
+
+.TP
+\fB\-c\fR \fIrange\fR
+Cleanup log system file for a given \fIrange\fR.
+
+.TP
+\fB\-L\fR \fIrange\fR
+dumps vol metadata log system file for a given \fIrange\fR.
+
+.TP
+\fB\-M\fR \fIrange\fR
+dumps vol metadata system file for a given \fIrange\fR.
+
+.TP
+\fB\-n\fR \fInodename\fR
+Perform action as node number given
+
+.TP
+\fB/dev/name:\fR 
+Readable bound raw device (/dev/raw/rawxx). One needs to bind a Linux raw character device to the block device (/dev/sdxx) in order to use this program.
+
+.TP
+\fBrange:\fR 
+Node numbers to inspect (0-31), commas and dashes ok (i.e.:\fI0-3,5,14-17\fR).
+.SH "BUGS"
+Stuff.
+
+.SH "SEE ALSO"
+.BR ocfs(5)
+
+.SH "AUTHORS"
+Oracle Corporation
+
+.SH "COPYRIGHT"
+Copyright \(co 2002 Oracle Corporation

Added: trunk/debugocfs/debugocfs.c
===================================================================
--- trunk/debugocfs/debugocfs.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/debugocfs/debugocfs.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,527 @@
+/*
+ * debugocfs.c
+ *
+ * Advanced filesystem debugging/recovery tool and library
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Kurt Hackel
+ */
+
+#include "debugocfs.h"
+#include <time.h>
+
+#ifdef LIBDEBUGOCFS
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "glib.h"
+#include "libdebugocfs.h"
+#endif
+
+__u32 debug_context = 0;
+__u32 debug_level = 0;
+__u32 debug_exclude = 0;
+
+ocfs_global_ctxt OcfsGlobalCtxt;
+
+__u32 OcfsDebugCtxt = OCFS_DEBUG_CONTEXT_INIT;
+__u32 OcfsDebugLevel = OCFS_DEBUG_LEVEL_ERROR;
+extern user_args args;
+
+
+/* fills in boolean arr[] (possibly shifted by off) with ranges supplied in str */
+int parse_numeric_range(char *str, int arr[], int min, int max, int off)
+{
+    char *next_range, *dash;
+    int begin, end;
+    char *endptr;
+
+    while (1)
+    {
+	next_range = strsep(&str, ",");
+	if (next_range == NULL || *next_range == '\0')
+	    break;
+	if ((dash = strchr(next_range, '-')) != NULL)
+	{
+	    if (*(dash + 1) == '\0' || strchr(dash + 1, '-') != NULL)
+		return false;
+	    *dash = '\0';
+	    begin = strtol(next_range, &endptr, 10);
+	    if (endptr == next_range || begin < min || begin >= max)
+		return false;
+	    end = strtol(dash + 1, &endptr, 10);
+	    if (endptr == dash + 1 || end < min || end >= max || begin > end)
+		return false;
+	    while (begin <= end)
+		arr[off + begin++] = true;
+	}
+	else
+	{
+	    begin = strtol(next_range, &endptr, 10);
+	    if (begin < min || begin >= max)
+		return false;
+	    arr[off + begin] = true;
+	}
+    }
+    return true;
+}
+
+
+
+
+/* directory walking functions */
+
+void walk_dir_nodes(int fd, __u64 offset, const char *parent, void *buf)
+{
+    ocfs_dir_node *dir;
+    int i;
+    __u64 dirPartOffset;
+
+    dir = (ocfs_dir_node *) malloc_aligned(DIR_NODE_SIZE);
+    dirPartOffset = offset;
+
+    while (1)
+    {
+	if (dirPartOffset == 0)
+	{
+	    /* this is an error, but silently fail */
+	    break;
+	}
+	read_dir_node(fd, dir, dirPartOffset);
+	for (i = 0; i < dir->num_ent_used; i++)
+	{
+	    ocfs_file_entry *fe;
+	    int off = 512;	/* move past the dirnode header */
+
+	    off += (512 * dir->index[i]);
+	    fe = (ocfs_file_entry *) (((void *) dir) + off);
+
+#ifdef LIBDEBUGOCFS
+            handle_one_file_entry(fd, fe, buf);
+#else
+            handle_one_file_entry(fd, fe, (void *)parent);
+#endif
+	}
+	/* is there another directory chained off of this one? */
+	if (dir->next_node_ptr == -1)
+	    break;		// nope, we're done
+	else
+	    dirPartOffset = dir->next_node_ptr;	// keep going
+
+    }
+    free(dir);
+}
+
+void get_file_data_mapping(ocfs_super * vcb, ocfs_file_entry * fe,
+			   filedata * data)
+{
+    int status;
+    ocfs_inode fcb;
+    __s64 lbo;
+    __s64 vbo = 0;
+
+    if (!data)
+	return;
+
+    data->num = 0;
+    data->array = NULL;
+    data->linkname = NULL;
+    data->user = fe->uid;
+    data->group = fe->gid;
+    data->major = data->minor = 0;
+    data->mode = fe->prot_bits;
+    switch (fe->attribs & (~OCFS_ATTRIB_FILE_CDSL))
+    {
+	case OCFS_ATTRIB_DIRECTORY:
+	    data->mode |= S_IFDIR;
+	    break;
+	case OCFS_ATTRIB_CHAR:
+	    data->mode |= S_IFCHR;
+	    data->major = fe->dev_major;
+	    data->minor = fe->dev_minor;
+	    break;
+	case OCFS_ATTRIB_BLOCK:
+	    data->mode |= S_IFBLK;
+	    data->major = fe->dev_major;
+	    data->minor = fe->dev_minor;
+	    break;
+	case OCFS_ATTRIB_FIFO:
+	    data->mode |= S_IFIFO;
+	    break;
+	case OCFS_ATTRIB_SYMLINK:
+	    data->linkname = (char *) calloc(fe->file_size + 1, 1);
+	    status =
+		ocfs_read_disk(vcb, data->linkname, fe->file_size,
+			     fe->extents[0].disk_off);
+	    data->mode |= S_IFLNK;
+	    break;
+	case OCFS_ATTRIB_SOCKET:
+	    data->mode |= S_IFSOCK;
+	    break;
+	default:		// if 0 after &ing with ~OCFS_ATTRIB_FILE_CDSL, it's a file
+	case OCFS_ATTRIB_REG:
+	    if (fe->attribs & OCFS_ATTRIB_FILE_CDSL)
+	    {
+		// do the cdsl sleight-of-hand and overwrite the file entry
+		__u64 offsets[MAX_NODES];
+
+		ocfs_read_disk(vcb, offsets, (MAX_NODES * sizeof(__u64)),
+			     fe->extents[0].disk_off);
+		ocfs_read_disk(vcb, fe, OCFS_SECTOR_SIZE,
+			     offsets[vcb->node_num]);
+	    }
+	    data->mode |= S_IFREG;
+	    fcb.alloc_size = 0;
+	    fcb.file_disk_off = fe->this_sector;
+	    ocfs_extent_map_init(&(fcb.map));
+	    status =
+		ocfs_lookup_file_allocation(vcb, &fcb, vbo, &lbo, fe->file_size,
+					 &data->num, (void *) &data->array);
+	    ocfs_extent_map_destroy(&(fcb.map));
+	    break;
+    }
+
+}
+
+#ifndef LIBDEBUGOCFS
+void traverse_extent(ocfs_super * vcb, ocfs_extent_group * exthdr, int flag)
+{
+	ocfs_extent_group *ext;
+	int i, fd;
+	bool prev_ptr_error;
+
+	if ((ext = malloc_aligned(512)) == NULL) {
+		printf("error: out of memory\n");
+		return ;
+	}
+
+	fd = (int) vcb->sb->s_dev;
+
+	for (i = 0; i < exthdr->next_free_ext; ++i) {
+		if (!exthdr->extents[i].disk_off)
+			continue;
+
+		read_extent(fd, ext, exthdr->extents[i].disk_off);
+
+		if (exthdr->this_ext != ext->up_hdr_node_ptr)
+			prev_ptr_error = true;
+		else
+			prev_ptr_error = false;
+
+		if (flag == EXTENT_HEADER) {
+			if (!IS_VALID_EXTENT_HEADER (ext)) {
+				printf("\tInvalid extent header\n\n");
+				continue;
+			}
+		} else {
+			if (!IS_VALID_EXTENT_DATA (ext)) {
+				printf("\tInvalid extent data\n\n");
+				continue;
+			}
+		}
+
+		print_extent(ext, args.twoFourbyte, prev_ptr_error);
+
+		if (flag == EXTENT_HEADER) {
+			if (ext->granularity)
+				traverse_extent(vcb, ext, EXTENT_HEADER);
+			else
+				traverse_extent(vcb, ext, EXTENT_DATA);
+		}
+	}
+
+	free(ext);
+
+    return ;
+}
+
+void traverse_fe_extents(ocfs_super * vcb, ocfs_file_entry *fe)
+{
+	int i, fd;
+	ocfs_extent_group *ext;
+	int type;
+	bool prev_ptr_error;
+
+	if ((ext = malloc_aligned(512)) == NULL) {
+		printf("error: out of memory\n");
+		return ;
+	}
+
+	fd = (int) vcb->sb->s_dev;
+    
+	for (i = 0; i < fe->next_free_ext; i++) {
+		if (!fe->extents[i].disk_off)
+			continue;
+
+		read_extent(fd, ext, fe->extents[i].disk_off);
+
+		if (fe->this_sector != ext->up_hdr_node_ptr)
+			prev_ptr_error = true;
+		else
+			prev_ptr_error = false;
+
+		if (fe->granularity) {
+			if (!IS_VALID_EXTENT_HEADER (ext)) {
+				printf("\tInvalid extent header\n\n");
+				continue;
+			}
+
+ 			print_extent(ext, args.twoFourbyte, prev_ptr_error);
+			type = ext->granularity ? EXTENT_HEADER : EXTENT_DATA;
+			traverse_extent(vcb, ext, type);
+		} else {
+			if (!IS_VALID_EXTENT_DATA (ext)) {
+				printf("\tInvalid extent data\n\n");
+				continue;
+			}
+ 			print_extent(ext, args.twoFourbyte, prev_ptr_error);
+		}
+	}
+
+	free(ext);
+}
+#endif
+
+/*
+ * for LIBDEBUGOCFS: returns the dir offset for FIND_MODE_DIR 
+ *                   or the parent dir offset for FIND_MODE_FILE
+ * for executable:   finds and prints either the ocfs_dir_node or
+ *                   ocfs_file_entry structure, depending upon mode
+ */
+void find_file_entry(ocfs_super * vcb, __u64 offset, const char *parent,
+		     const char *searchFor, int mode, void *buf)
+{
+    ocfs_dir_node *dir, *foundDir;
+    int i, fd;
+    char *newname;
+    __u64 ret = 0, dirPartOffset;
+
+    fd = (int) vcb->sb->s_dev;
+    dir = (ocfs_dir_node *) malloc_aligned(DIR_NODE_SIZE);
+    dirPartOffset = offset;
+
+    while (1)
+    {
+	if (dirPartOffset == 0)
+	{
+	    /* this is an error, but silently fail */
+	    break;
+	}
+	read_dir_node(fd, dir, dirPartOffset);
+	for (i = 0; i < dir->num_ent_used; i++)
+	{
+	    ocfs_file_entry *fe;
+	    int off = 512;	/* move past the dirnode header */
+
+	    off += (512 * dir->index[i]);
+	    fe = (ocfs_file_entry *) (((void *) dir) + off);
+
+	    if (!fe->sync_flags || (fe->sync_flags & DELETED_FLAGS))
+		    continue;
+
+	    newname =
+		(char *) malloc_aligned(strlen(parent) + strlen(fe->filename) + 2);
+
+	    if (fe->attribs & OCFS_ATTRIB_DIRECTORY)
+	    {
+		sprintf(newname, "%s%s/", parent, fe->filename);
+		if (strcmp(searchFor, newname) == 0)
+		{
+		    if (mode == FIND_MODE_FILE || mode == FIND_MODE_FILE_EXTENT)
+			ret = offset;	// return the first part of the dir chain
+		    else if (mode == FIND_MODE_DIR)
+			ret = fe->extents[0].disk_off;
+		    else if (mode == FIND_MODE_FILE_DATA)
+			get_file_data_mapping(vcb, fe, buf);
+
+#ifndef LIBDEBUGOCFS
+		    printf("\tName = %s\n", newname);
+		    if (mode == FIND_MODE_FILE || mode == FIND_MODE_FILE_EXTENT)
+		    {
+			print_file_entry(fe);
+			if (!fe->local_ext && mode == FIND_MODE_FILE_EXTENT)
+				traverse_fe_extents(vcb, fe);
+		    }
+		    else if (mode == FIND_MODE_DIR)
+		    {
+			__u64 dir_off = fe->extents[0].disk_off;
+			foundDir = (ocfs_dir_node *) malloc_aligned(DIR_NODE_SIZE);
+
+			while(1) {
+				read_dir_node(fd, foundDir, dir_off);
+				print_dir_node(foundDir);
+				if (!args.showDirentAll ||
+				    foundDir->next_node_ptr == INVALID_NODE_POINTER)
+					break;
+				dir_off = foundDir->next_node_ptr;
+				memset(foundDir, 0, DIR_NODE_SIZE);
+				printf("dirinfo:\n");
+			}
+			free(foundDir);
+		    }
+#endif
+		    free(newname);
+		    break;
+		}
+		else if (strstr(searchFor, newname) == searchFor)
+		{
+		    find_file_entry(vcb, fe->extents[0].disk_off, newname,
+				    searchFor, mode, (void *) (&ret));
+		    free(newname);
+		    break;
+		}
+	    }
+	    else		/* not a directory */
+	    {
+		sprintf(newname, "%s%s", parent, fe->filename);
+		if (strcmp(searchFor, newname) == 0)
+		{
+		    if (mode == FIND_MODE_FILE || mode == FIND_MODE_FILE_EXTENT)
+			ret = offset;	// return the first part of the dir chain
+		    else if (mode == FIND_MODE_DIR)
+			ret = 0;	// file found, not dir 
+		    else if (mode == FIND_MODE_FILE_DATA)
+			get_file_data_mapping(vcb, fe, buf);
+
+#ifndef LIBDEBUGOCFS
+		    if (mode == FIND_MODE_DIR)
+		    {
+			printf("found a file named %s, not a directory.\n",
+			       newname);
+			exit(1);
+		    }
+		    printf("\tName = %s\n", newname);
+		    print_file_entry(fe);
+		    if (!fe->local_ext && mode == FIND_MODE_FILE_EXTENT)
+			    traverse_fe_extents(vcb, fe);
+#endif
+		    free(newname);
+		    break;
+		}
+	    }
+	    free(newname);
+	}
+	/* is there another directory chained off of this one? */
+	if (dir->next_node_ptr == -1)
+	    break;		// nope, we're done
+	else
+	    dirPartOffset = dir->next_node_ptr;	// keep going
+    }
+
+    free(dir);
+    if ((mode == FIND_MODE_FILE || mode == FIND_MODE_DIR ||
+	 mode == FIND_MODE_FILE_EXTENT) && buf)
+	*(__u64 *) buf = ret;
+}
+
+
+int suck_file(ocfs_super * vcb, const char *path, const char *file)
+{
+    int fd, newfd, mode, i, ret = 0;
+    filedata data;
+    mode_t oldmask;
+    ocfs_io_runs *run;
+
+    fd = (int) vcb->sb->s_dev;
+    oldmask = umask(0000);
+
+    if (unlink(file) == -1)
+    {
+#ifndef LIBDEBUGOCFS
+	printf("failed to unlink file: %s\n", file);
+#endif
+    }
+
+    if (access(file, F_OK) == -1)
+    {
+	find_file_entry(vcb, vcb->vol_layout.root_start_off, "/",
+			path, FIND_MODE_FILE_DATA, &data);
+
+	if (S_ISLNK(data.mode) && data.linkname)
+	{
+	    newfd = symlink(data.linkname, file);
+	    free(data.linkname);
+	}
+	else if (S_ISFIFO(data.mode) || S_ISCHR(data.mode) ||
+		 S_ISBLK(data.mode))
+	{
+	    if (S_ISFIFO(data.mode))
+		data.major = data.minor = 0;
+	    newfd = mknod(file, data.mode, makedev(data.major, data.minor));
+	}
+	else if (S_ISSOCK(data.mode))
+	{
+	    // unimplemented...
+	}
+	else if (S_ISDIR(data.mode))
+	    newfd = mkdir(file, data.mode);
+	else if (S_ISREG(data.mode))
+	{
+	    void *filebuf = malloc_aligned(FILE_BUFFER_SIZE);
+	    __u32 remaining, readlen;
+
+	    newfd = creat(file, data.mode);
+	    if (newfd != -1)
+	    {
+		for (i = 0; i < data.num; i++)
+		{
+		    run = (ocfs_io_runs *) & (data.array[i]);
+
+		    // in new file: seek to run->Offset
+		    // in ocfs: read from run->disk_off, run->byte_cnt bytes
+		    remaining = run->byte_cnt;
+		    myseek64(newfd, run->offset, SEEK_SET);
+		    myseek64(fd, run->disk_off, SEEK_SET);
+		    while (remaining > 0)
+		    {
+			readlen =
+			    remaining <
+			    FILE_BUFFER_SIZE ? remaining : FILE_BUFFER_SIZE;
+			if (read(fd, filebuf, readlen) != readlen ||
+			    write(newfd, filebuf, readlen) != readlen)
+			{
+			    ret = 2;
+			    goto do_close;
+			}
+			remaining -= readlen;
+		    }
+		}
+	    }
+	}
+
+      do_close:
+	if (newfd != -1)
+	    close(newfd);
+	if (chown(file, data.user, data.group) == -1)
+        {
+#ifndef LIBDEBUGOCFS
+	    printf("chown failed!\n");	// error
+#endif
+        }
+    }
+    else
+    {
+	ret = 1;
+    }
+
+  bail:
+    umask(oldmask);
+    return ret;
+}

Added: trunk/debugocfs/debugocfs.h
===================================================================
--- trunk/debugocfs/debugocfs.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/debugocfs/debugocfs.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,156 @@
+/*
+ * debugocfs.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002, 2004 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Author: Kurt Hackel, Sunil Mushran
+ */
+
+#ifndef _DEBUGOCFS_H_
+#define _DEBUGOCFS_H_
+
+#define _LARGEFILE64_SOURCE
+#include <libocfs.h>
+
+#define MAX_NODES  OCFS_MAXIMUM_NODES
+#define MAX_SYSTEM_FILES    (CLEANUP_FILE_BASE_ID + OCFS_MAXIMUM_NODES)	/* 193? */
+#define DIR_NODE_SIZE  (1024 * 128)
+
+
+/* modes for find_file_entry */
+enum 
+{
+    FIND_MODE_DIR,
+    FIND_MODE_FILE,
+    FIND_MODE_FILE_EXTENT,
+    FIND_MODE_FILE_DATA
+};
+
+#define DEFAULT_NODE_NUMBER   (0)
+
+typedef struct _user_args
+{
+    int nodenum;
+    int showHeader;
+    int showBitmap;
+    int showPublish;
+    int showVote;
+    int showListing;
+    int showDirent;
+    int showDirentAll;
+    int showFileent;
+    int showFileext;
+    int twoFourbyte;
+    int showSystemFiles;
+    int suckFile;
+    int publishNodes[MAX_NODES];
+    int voteNodes[MAX_NODES];
+    int systemFiles[MAX_SYSTEM_FILES];
+    char *dirent;
+    char *fileent;
+    char *suckTo;
+}
+user_args;
+
+typedef struct _filedata
+{
+    ocfs_io_runs *array;
+    __u32 num;
+    mode_t mode;
+    uid_t user;
+    gid_t group;
+    unsigned int major;
+    unsigned int minor;
+    char *linkname;
+}
+filedata;
+
+/* print functions */
+void print_dir_node(void *buf);
+void print_disk_lock(void *buf);
+void print_vol_label(void *buf);
+void print_vol_disk_header(void *buf);
+void print_publish_sector(void *buf);
+void print_vote_sector(void *buf);
+void print_file_entry(void *buf);
+void print_extent_ex(void *buf);
+void print_extent(void *buf, int twolongs, bool prev_ptr_error);
+void print_cdsl_offsets(void *buf);
+void print_record(void *rec, int type);
+void print_system_file(int fd, ocfs_vol_disk_hdr * v, int fileid);
+
+/* helpers */
+void print_synch_flags(int flags);
+void print_publish_flags(int type);
+void print_vote_type(int type);
+void print_log_type(int type);
+void print_lock_type(__u8 lock);
+void print___u64_as_bitmap(__u64 x);
+void print_node_pointer(__u64 ptr);
+
+void handle_one_file_entry(int fd, ocfs_file_entry *fe, void *buf);
+
+
+ocfs_super *get_fake_vcb(int fd, ocfs_vol_disk_hdr * hdr, int nodenum);
+void walk_dir_nodes(int fd, __u64 offset, const char *parent, void *buf);
+void find_file_entry(ocfs_super * vcb, __u64 offset, const char *parent,
+		     const char *searchFor, int mode, void *buf);
+void traverse_fe_extents(ocfs_super * vcb, ocfs_file_entry *fe);
+void traverse_extent(ocfs_super * vcb, ocfs_extent_group * exthdr, int flag);
+
+#if 0
+void read_vol_disk_header(int fd, ocfs_vol_disk_hdr * v);
+int write_vol_disk_header(int fd, ocfs_vol_disk_hdr * v);
+void read_vote_sector(int fd, ocfs_vote * vs, __u64 offset);
+void read_publish_sector(int fd, ocfs_publish * ps, __u64 offset);
+void read_system_file(int fd, ocfs_vol_disk_hdr * v, int fileid,
+		      ocfs_file_entry * fe);
+void read_dir_node(int fd, ocfs_dir_node * d, __u64 offset);
+void read_extent(int fd, ocfs_extent_group * e, __u64 offset);
+void read_cdsl_data(int fd, void *data, __u64 offset);
+void read_vol_label(int fd, ocfs_vol_label * v);
+loff_t myseek64(int fd, loff_t off, int whence);
+int suck_file(ocfs_super * vcb, const char *path, const char *file);
+
+int write_publish_sector(int fd, ocfs_publish * ps, __u64 offset);
+int write_vote_sector(int fd, ocfs_vote * vs, __u64 offset);
+int write_system_file(int fd, ocfs_vol_disk_hdr * v, int fileid,
+		      ocfs_file_entry * fe);
+int write_vol_disk_header(int fd, ocfs_vol_disk_hdr * v);
+int write_vol_label(int fd, ocfs_vol_label * v);
+int write_dir_node_header(int fd, ocfs_dir_node * d, __u64 offset);
+int write_file_entry(int fd, ocfs_file_entry * f, __u64 offset);
+
+
+int ocfs_lookup_file_allocation(ocfs_super * VCB, ocfs_inode * FCB, __s64 Vbo, __s64 * Lbo, __u32 ByteCount, __u32 * NumIndex, void **Buffer);
+int AdjustAllocation(ocfs_io_runs ** IoRuns, __u32 * ioRunSize);
+bool ocfs_add_extent_map_entry(ocfs_super * VCB, ocfs_extent_map * MCB, __s64 Vbo, __s64 Lbo, __u64 ByteCount);
+int ocfs_update_extent_map(ocfs_super * VCB, ocfs_extent_map * MCB, void *Buffer, __s64 * localVbo, __u64 * remainingLength, __u32 Flag);
+int ocfs_read_sector(ocfs_super * vcb, void *buf, __u64 off);
+
+ocfs_file_entry *ocfs_allocate_file_entry();
+void *ocfs_linux_dbg_alloc(int Size, char *file, int line);
+bool ocfs_lookup_extent_map_entry (ocfs_super * osb, ocfs_extent_map * Map, __s64 Vbo, __s64 * Lbo, __u64 * SectorCount, __u32 * Index);
+bool ocfs_extent_map_lookup (ocfs_extent_map * map, __s64 virtual, __s64 * physical, __s64 * sectorcount, __u32 * index);
+#endif
+
+void usage(void);
+
+#endif

Added: trunk/debugocfs/debugocfs.txt
===================================================================
--- trunk/debugocfs/debugocfs.txt	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/debugocfs/debugocfs.txt	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,533 @@
+* introduction
+  * what is ocfs?
+  * on-disk structures and layout
+  * using debugocfs to inspect on-disk structures
+* explanation of features
+  * -h : volume header
+  * -g : global bitmap
+  * -v : vote sector
+  * -p : publish sector
+  * -f : ocfs_file_entry structure
+  * -F : ocfs_file_entry and ocfs_extent_group structures
+  * -d : ocfs_dir_node structure
+  * -a : file allocation system file
+  * -A : dir allocation system file
+  * -b : file allocation bitmap system file
+  * -B : dir allocation bitmap system file
+  * -r : recover log file system file
+  * -c : cleanup log system file
+  * -L : vol metadata log system file
+  * -M : vol metadata system file
+* usage scenarios
+  * Before you get started
+  * Erratic behavior or unable to mount
+  * File size, last modified, etc. for a file is incorrect
+  * Deleted file shows in a directory
+  * Non-deleted file does not show
+  * Single filename shows up more than once
+  * Hang occurs while extending/truncating/removing a datafile
+* Disclaimer
+
+
+
+==============================================================
+
+* introduction
+  * what is ocfs?
+
+The Oracle Clustered Filesystem (ocfs) is an open-source project created
+by Oracle to allow RAC database administrators to more easily create and
+set up clustered databases without having to configure raw partitions.
+Unlike raw partitions, the user is presented with a normal filesystem
+interface, and is able to use most normal filesystem structures such as
+directories, regular files and symlinks (hard links are not currently
+implemented).  Database administration activities that are often
+complicated by the use of raw partitions are simplified by the use of
+ocfs, such as resizing, truncating, adding or deleting datafiles.
+Additionally, ocfs is an extent-based filesystem which allows for large
+contiguous allocations, optimal for files such as oracle datafiles.
+
+There are several differences between ocfs and a normal local filesystem
+(such as ext3) that should be taken into consideration.  While a local
+filesystem is able to keep most metadata and data cached in various
+caches at any point in time, ocfs needs to communicate all metadata
+changes to any other mounted nodes when they occur, and for oracle use,
+will also synchronously commit all data to disk as well.  This limits
+ocfs with respect to use as a general-purpose filesystem because
+accesses to ordinary file metadata such as file size or last modified
+date may need to do an IO in order to fetch the information.  This extra
+IO will slow down such accesses considerably.
+
+Another important consideration is that since ocfs is a clustered
+filesystem, it must not only take local locks when making metadata
+changes (using semaphores, etc), but it must also cooperatively lock
+between nodes using a distributed lock manager.  Meanwhile, for crash
+recovery, ocfs also needs to journal critical changes to disk so that
+filesystem structures are not corrupted.  The lock manager (called a
+DLM) which ocfs uses is a simple lock manager which currently uses only
+the ocfs disk partition itself to communicate using a publish-vote
+mechanism.  Each node intending to lock a piece of metadata on disk will
+publish its intent to lock to a specific location on disk.  Meanwhile,
+all nodes will continuously read other nodes' published information and
+cast a vote regarding whether or not there is a conflict that should
+prevent the requestor from getting the lock.
+
+  * on-disk structures and layout
+
+To ensure proper coordination between nodes, ocfs defines a rigid
+on-disk format and specific on-disk structures.
+
++-+-----+-----+-----+-----------+-------+-------+----
+| |     |     |     |           |       |       | ...
++-+-----+-----+-----+-----------+-------+-------+----
+ ^   ^     ^     ^        ^         ^       ^     
+ |   |     |     |        |         |       |
+ |   |     |     |        |         |       +-- dir hierarchy
+ |   |     |     |        |         +-- system files (see below)
+ |   |     |     |        +-- global bitmap 
+ |   |     |     +-- vote sectors (32)
+ |   |     +-- publish sectors (32)
+ |   +-- autoconfig sectors
+ +-- disk header
+
+
+The disk header sector acts as the superblock of an ocfs filesystem,
+storing all of the vital information for properly bootstrapping the
+mount.  The disk header stores pointers to each of the following disk
+structures.  If this should be corrupted, you may be unable to mount the
+filesystem or the filesystem may be corrupted.
+
+The autoconfig sectors are used by ocfs to automatically assign
+identities to new nodes as they attach to an ocfs volume.  There are a
+total of 32 slots available, so each node will receive a nodenum between
+0 and 31.  For a given mount you can look at /proc/ocfs/###/nodenum to
+determine your node's number for that volume.  The ### in this case is a
+sequential mount id (which only has meaning on a single node), and to
+determine the mountpoint for this mount you can dump
+/proc/ocfs/###/mountpoint.  The first node to mount an ocfs volume after
+formatting will always be node zero, and no other nodes are allowed to
+attach to this volume while the ocfs partition is prepared the first
+time.
+
+After the autoconfig sectors, there are 32 publish sectors followed by
+32 vote sectors.  Upon mounting, a node mangager daemon (ex. [ocfsnm-0])
+will be started and will continually update a timestamp in the publish
+sector for this node, as well as read each of the other publish sectors.
+This allows for one daemon to handle both node monitoring (checking if a
+node is dead and needs recovery) and lock management simultaneously, at
+approximately 1/2 second intervals.  If the ocfsnm detects that a node
+has requested a vote for a certain resource, it will find the status of
+that resource on the local node to determine whether or not to allow the
+other node to take the lock.  Once the determination has been made, the
+ocfsnm will write its response into the corresponding vote sector, and
+the process which requested the lock on the other node will collect up
+all responses and decide whether the lock can be taken, cannot be taken,
+or should be retried.
+
+As ocfs is an extent-based filesystem, a bitmap of all extents in the
+filesystem is stored just after the vote sectors.  The extent size is
+chosen at format time, and the maximum number of possible extents is
+bounded at 8 million (since the global bitmap is 1MB max).  When
+choosing a cluster size, one should take into consideration the maximum
+size to which the ocfs partition is likely to grow, and also the degree
+of contiguousness desired.  For instance, a standard ocfs clustersize is
+128 KB, which means that even with a highly fragmented file you will at
+least get 128k of oracle data in one contiguous chunk.  On a 32GB
+partition, you would end up with about 32 thousand total extents with a 
+1mb cluster size, 250 thousand with a 128k cluster size, and 8 million
+with a 4k cluster size.  If you plan on having many small files (not
+recommended) or plan on using autoextended datafiles, you may wish to
+format with a smaller cluster size to maximize the number of total
+extents.  If you plan on having fewer files of large size and intend to
+manually extend these files in large chunks, you should choose a larger 
+cluster size to increase contiguousness.
+
+The system files which follow the global bitmap a laid out as follows:
+
++---+---+---+---+---+---+---+---+
+|   |   |   |   |   |   |   |   |
++---+---+---+---+---+---+---+---+
+  ^   ^   ^   ^   ^   ^   ^   ^
+  |   |   |   |   |   |   |   |
+  |   |   |   |   |   |   |   +-- cleanup log
+  |   |   |   |   |   |   +-- recover log
+  |   |   |   |   |   +-- file extent bitmap
+  |   |   |   |   +-- file extent data
+  |   |   |   +-- dir bitmap
+  |   |   +-- dir data
+  |   +-- volume metadata log 
+  +-- volume metadata 
+
+For each system file type there are 32 file entries, one for each
+possible node in the cluster.  The first two types (volume metadata and
+volume metadata log) are not used in the current version of ocfs.
+
+The directory data and directory bitmap system files are used to
+sub-allocate space from the global bitmap for use as directory
+structures.  These structures are always 128k in size.  Space is
+allocated to the directory data file from the global bitmap in chunks, 
+then allocated by checking against the directory bitmap for free bits.
+
+The file extent data and file extent bitmap system files serve a similar
+purpose to the directory system files, except that they sub-allocate in
+512 byte segments.  These structures are used by ocfs for creating
+indirect extent trees for files which are fragmented beyond 3 extents.
+Space is directly allocated to these files from the global bitmap, and
+the file extent bitmap files keep track of free and used 512 byte
+chunks.
+
+The two logfiles together constitute a per-node journalling system. We
+journal filesystem metadata changes so that in the case of a
+catosrophic event (system crash, power outage, etc) we can recover the
+filesystem quickly and cleanly.
+Both logfiles consist of a stream of records. Each one has distinct
+record types, though some record types are shared.
+
+The recover log is filled with records which will be processed in the
+case that we have to abort an operation. In this case, the records in
+the cleanup log pertaining to that operation would be ignored.
+
+The cleanup log is filled with records which will be processed in the
+case that we want to commit an operation. In this case, the records in
+the recover log pertaining to that operation would be ignored.
+
+Each node has two log files, and in the case that a node crashes, one
+of the other live nodes in the cluster will process it's logs in order
+to complete or abort any operations it was doing.
+
+Finally, following the system files, the actual directory hierarchy
+begins:
+
++---+---+---+        +---+---+
+|   |   |   | ...... |   |   | 
++---+---+---+        +---+---+
+  ^   ^   ^            ^   ^
+  |   |   |            |   | 
+  |   |   |            |   +-- file entry #255
+  |   |   |            +-- file entry #254
+  |   |   +-- file entry #2
+  |   +-- file entry #1
+  +-- directory header
+
+The entire directory structure is 128k in size, made of 256 512-byte
+entries.  When a directory fills beyond 255 files, another 128k
+structure must be allocated somewhere on disk from the directory
+data/bitmap system files.  This pointer will be chained on to the first
+directory structure using a field in the directory header.  This header
+also contains information about the number of valid file entries, and
+also an alpha-sorted index of filenames within this 128k structure.
+
+Each file entry contains all the information needed to make up a valid
+inode: name, size, type, permissions, etc.  It also contains extent
+information which describes pointers to each of the extents which make 
+up the total allocation for the file.  Three of these extents can exist
+in the file entry itself, and will be migrated to an indirect tree
+structure if the file grows beyond the third extent.
+
+In addition to the fields described, all file entries (including those
+for each system file), each directory header, and some additional
+special sectors used for locking the global bitmap and other structures
+all contain a disk lock structure.  This is the persistent lock
+information used by any process requesting a lock on a filesystem
+structure.  This locking info includes the node number of the current
+lock owner, the lock level, and a bitmap of nodes which have an open
+file handle to a given file entry.
+  
+
+  * using debugocfs to inspect on-disk structures
+
+To debug any hangs or inconsistencies that you may find while using
+ocfs, the debugocfs tool can be used to inspect all of the filesystem
+structures above.  When using this tool, you need to have read access to
+the device on which the filesystem was created.  If you are debugging an
+issue in which you suspect that some degree of caching is preventing a
+node from seeing the most current data (ex. file size does not match
+on two separate nodes), then you should bind a raw device to the block
+device first and run debugocfs on this raw device instead.
+
+       -g: global bitmap
+       -l: full listing of all file entries
+       -v: vote sector
+       -p: publish sector
+       -d: ocfs_dir_node structure for a given path
+       -f: ocfs_file_entry structure for a given file
+       -s: suck file out to a given location
+       -a: file allocation system file
+       -A: dir allocation system file
+       -b: file allocation bitmap system file
+       -B: dir allocation bitmap system file
+       -r: recover log file system file
+       -c: cleanup log system file
+       -L: vol metadata log system file
+       -M: vol metadata system file
+       -n: perform action as node number given
+
+
+* explanation of features
+  * -h : volume header
+Displays the first 2 sectors on an ocfs volume: the vol disk header and
+volume label structures.  The pointers in the disk header (ex.  bitmap_off) 
+should not change after the first mount.
+  * -g : global bitmap
+Shows statistics about the global bitmap and the state of each bit
+within it.
+  * -v : vote sector
+Prints the last vote written out by the selected node.  This will show
+the disk offset (in bytes) to the resource upon which the lock was
+requested, the sequence number of the lock (used to ensure uniqueness),
+the vote cast and the node for which the vote was cast.
+  * -p : publish sector
+Shows any vote request for a particular node (the vote, vote_type, 
+vote_map, seq_num, and dir_ent fields will be set) as well as an updated 
+timestamp for this node.  This timestamp is not actually a date (and 
+debugocfs may erroneously show it as such) but merely a tick count which 
+must continually increment for other nodes to acknowledge that this node 
+is still alive.  When watching the publish and vote sectors for lock 
+requests, the dir_ent field will tell you which disk offset is being 
+requested.
+  * -f : ocfs_file_entry structure
+  * -F : ocfs_file_entry and ocfs_extent_group structures
+Prints several fields for a given inode within the filesystem.  The path
+used for this file should be relative to the mountpoint.  For example,
+if an ocfs filesystem is mounted at /ocfs, the file in question is
+/ocfs/a/b/c, and the filesystem is on device /dev/sda1, you should run 
+"debugocfs -f /a/b/c /dev/sda1".  This will display not only the lock
+state info for the file (curr_master, file_lock, oin_node_map, seq_num),
+but also the normal unix file information such as size, owner,
+permissions, filename, creation/modification date, and file type flags.
+In addition, this command will show information regarding the data
+extents used to piece the file data together (up to 3 extents with
+file_off, num_bytes and disk_off), the alloc_size (the maximum size to
+which the file can grow before more extents need to be added), and the
+local_ext and granularity flags.  If local_ext is true (and granularity
+is -1) then the 3 extents listed point directly to the data.  Using this
+information one could dump num_bytes of data, seeking disk_off bytes into
+the device for each of these extents in order to piece the file data
+together.  If local_ext is false, the granularity will represent the
+number of levels in an indirect tree above the actual pointers to extent
+data.  If the -F option is used (instead of -f), a printout of the
+entire extent tree will be given, which will include the file entry at
+the top of the tree, extent data (EXTDAT) structures at the bottom of
+the tree pointing directly to data, and if necessary some extent header
+(EXTHDR) structures in the middle of the tree pointing to either more
+EXTHDRs or EXTDATs, depending upon the level within the tree.  This
+command may be used on any type of file, including directories.  When
+specifying a directory make sure to use a trailing slash (/).
+Directories will only have one extent listed, and the disk_off for this
+extent will point to the beginning of the actual 128k directory block.
+  * -d : ocfs_dir_node structure
+Shows the header information for a directory (first 512 bytes).  This
+will show the number of valid entries in this 128k block (num_ent_used),
+the pointer to the next block in the directory chain (next_node_ptr, if
+more than 255 file entries), and several fields used for effecient
+deletion and renaming of files (first_del, num_del).  In addition, the
+alphasorted index of filenames will be shown as well as the index_dirty
+flag which shows whether the index needs to be recreated.  The
+alloc_file_off and alloc_node fields are used when a directory is
+deleted to determine to which dir alloc system file to release the
+space.  The node_disk_off field points back up to the file entry for
+this directory.  The syntax for this command is exactly like the -f/-F
+commands, and one should also ensure that the directory name uses a
+trailing slash (/).
+
+  * -a : file allocation system file
+  * -A : dir allocation system file
+  * -b : file allocation bitmap system file
+  * -B : dir allocation bitmap system file
+  * -r : recover log file system file
+  * -c : cleanup log system file
+  * -L : vol metadata log system file
+  * -M : vol metadata system file
+These options show the ocfs_file_entry structure for the requested
+system file for any number of nodes.  The fields shown are exactly the
+same as those in the -f/-F options.  For the bitmap types, special
+bitmap statistics and free/set bit information will also be shown.
+
+
+* usage scenarios
+
+  * Before you get started
+Before you encounter any problems with an ocfs filesystem, it would 
+be wise to inspect the disk header and familiarize yourself with the 
+values shown (or save the output to a file), since they will not 
+change after the first mount.  To print this sector, run:
+  debugocfs -h /dev/device
+For recovery purposes, you may even want to save off this critical
+sector in case it ever becomes corrupted using the following command:
+  dd if=/dev/device of=diskhdr.bak bs=512 count=1
+and if you need to restore this sector:
+  dd if=diskhdr.bak of=/dev/device bs=512 count=1
+
+  * Erratic behavior or unable to mount
+If you are unable to mount an ocfs partition or it seems that there is
+inconsistent behavior with the filesystem, the first thing to check is
+the volume header.  Check the header using this command:
+  debugocfs -h /dev/device
+All of the _off parameters are byte offsets on the device and should be
+within range for that device (should all be less than device_size).  The
+cluster_size, permissions, owner and mountpoint should match the values
+chosen at format time.  The following fields will always be zero:
+serial_num, start_off, root_bitmap_off, root_bitmap_size, root_size,
+dir_node_size, file_node_size.  If any of these fields looks as if it
+has been overwritten or zeroed, you should consider restoring at least
+the first block of the disk as soon as possible.  The output from this
+debugocfs command should be included in a bug report.
+If the header is intact, other structures to check include the cleanup
+and recover log files.  Before running debugocfs, first determine your
+node number from the output of:
+  cat /proc/ocfs/##/mountpoint  and
+  cat /proc/ocfs/##/nodenum
+matching up the mountpoint to determine the proper mount number.  Once
+you have determined your nodenum for this volume, you can run:
+  debugocfs -r nodenum -c nodenum /dev/device
+to inspect the recover and cleanup logs for this node.  Under normal
+circumstances, the file_size for each of these should be zero.  During
+an active transaction this size may increase to as much as about 1MB,
+but if it grows much beyond this the time to complete recovery may be
+very long and seem like a hang.  You can watch this file size over time
+to ensure that it is reducing using a command such as:
+  watch -d "debugocfs -r nodenum -c nodenum /dev/device | grep file_size" 
+You may also specify a list or range of node numbers (ex. 7,8-10).
+
+  * File size, last modified, etc. for a file is incorrect
+Due to the nature of a clustered filesystem it is sometimes a challenge
+to keep the caching that the linux VFS provides from interfering.  You
+may at some point encounter a file which has different inode properties
+on different nodes.  To determine what is actually committed to disk,
+versus what is currently visible in the filesystem, you should first run
+an 'ls -lai filename', and then run:
+  debugocfs -f /path/to/file /dev/device
+on each node.  If the debugocfs information is different between the two
+nodes also, you may need to first bind the device to a raw device first
+in order to see the actual data on disk (this will ensure that an io is
+actually completed, bypassing the linux pagecache).  Read the man(8)
+manpage for info on how to bind a raw device, and make sure to download
+the debugocfs fixed for raw device support (ARU #XXXXXXX).
+Once you have collected all of this information you should submit a bug
+with all of this data and information on what filesystem actions were
+done on this file and on which nodes.  (ex. datafile was created on node
+0, extended by node 1, then truncated by node 0)  The disk should always
+hold the "correct" information, so unmounting the filesystem and
+remounting it is likely to correct such a problem.
+
+  * Deleted file shows in a directory
+  * Non-deleted file does not show
+  * Single filename shows up more than once
+These types of issues suggest that there is a problem with either the
+flags on a file entry or the index of the parent directory.  You will
+have to inspect several different filesystem structures to get a
+complete picture.  First, run:
+  debugocfs -d /parent/directory/ /dev/device    and
+  debugocfs -f /parent/directory/filename /dev/device
+From the '-d' output, if next_node_ptr is INVALID_NODE_POINTER then the
+directory is allocated in only one block (<256 file entries).  Otherwise
+this field will point to the next directory block in the chain.  To dump
+each successive block you can execute:
+  debugocfs -X -h hi -l lo -t ocfs_dir_node /dev/device
+where hi and lo represent the high and low order 32-bit values which
+make up the 64-bit quantity in next_node_ptr (ex. 34629255680 is hi=8,
+lo=269517312).  This can be done for each block in the directory chain
+to find files deeper than the first block.  
+The '-f' output will either show you a normal file entry or it may not
+show any output at all.  If it does not print the file entry this means
+that the filename was not found in any of the indexes of the
+directories.  It may be that the name can still be found somewhere
+within one of the blocks, but the index has been updated to no longer
+include this entry when searching or listing.  If you need to look at
+the raw data in the directory, you can do:
+  dd if=/dev/device of=dirdump bs=512 count=256 skip=<dir offset/512>
+for any/all of the directory blocks.  Or another method that can be used
+is to use the
+  debugocfs -X -h hi -l lo -t ocfs_file_entry /dev/device
+command to "cast" a given disk block to the ocfs_file_entry type.  As an
+example, let's say that the directory block you are looking at is at
+offset 34629255680.  This means that there will be a 512-byte header at
+that offset, followed by 255 512-byte file entries.  Also assume that
+the num_ent_used in this case is 9, and the index looks like 
+"2   4   0   7   3   1   5   6   8".  To look at each file entry in
+order, begin with the dir offset (34629255680), then add 512 to skip
+over the header (34629256192).  This is the location of entry #0, and
+each subsequent entry will follow 512 bytes later.  To examine each of
+the 9 files in this directory you could run (in bash):
+  first=34629256192; hi=0; lo=0; off=0; fourgb=4294967296
+  for i in 2 4 0 7 3 1 5 6 8; do 
+    off=`echo "$first + ($i * 512)" | bc`
+    hi=`echo "$off / $fourgb" | bc`
+    lo=`echo "$off % $fourgb" | bc`
+    debugocfs -X -h $hi -l $lo -t ocfs_file_entry echo $off $hi $lo
+  done
+If you need to inspect file entries which seem to have been deleted (and
+thus do not show up in the index), you can change the for statement to:
+  for ((i=0; i<255; i++)); do ...
+This will allow you to look at every block within the directory
+regardless of whether it is currently valid.  Information to look out
+for include the sync_flags field (should be OCFS_SYNC_FLAG_VALID on a
+normal file entry, may be one of the following for a deleted file: 
+OCFS_SYNC_FLAG_DELETED, OCFS_SYNC_FLAG_MARK_FOR_DELETION, 
+OCFS_SYNC_FLAG_NAME_DELETED) and the modify_time.  This may give you
+some indication of what caused the problem and when it occurred.
+If you encounter a situation where a filename appears more than once
+when doing a readdir (ls) it is very likely that there is a repeated
+entry within the directory index (ex. 2 4 0 7 7 1 5 6 8, 7 repeats).
+This may also manifest itself as a spuriously deleted file since this
+type of corruption would likely wipe out one file entry in order to
+double up another.
+Finally, you may see a problem when doing an 'ls -l' where it seems that
+the readdir() command has correctly returned one or more filenames, but
+the subsequent stat() that ls does on each file will fail on at least
+one of these.  This will show up as stderr output at the top of the 'ls'
+listing similar to:
+  ls: filename: No such file or directory
+This error indicates that the index within a directory block is in need
+of reindexing, and while all the files within the directory are still ok
+and intact, the alphasorted index needs to be resorted.  During certain
+operations on the directory (create, delete, rename) the index_dirty
+flag will get set to indicate that this needs to be recreated, but in
+certain very rare crashes it has been found that this fails to happen.
+
+
+  * Hang occurs while extending/truncating/removing a datafile
+Another common case where database administrators have seen issues when
+running ocfs has been in deadlock conditions or runaway lock requests
+when trying to get an exclusive lock on a datafile.  In some cases this
+has been found to even lock out all future lock requests on that node,
+including such things as doing an 'ls' on a directory.
+To diagnose such an issue, you should first examine the file entry on
+which the hang is happening using the methods above:
+  debugocfs -f /path/to/file /dev/device
+Of particular interest here are the curr_master and file_lock fields.
+The curr_master may be any valid node in the system or may be -1 (or
+INVALID) meaning that noone has ownership of the lock.  The file_lock
+may be one of OCFS_DLM_ENABLE_CACHE_LOCK, OCFS_DLM_EXCLUSIVE_LOCK,
+OCFS_DLM_SHARED_LOCK, or OCFS_DLM_NO_LOCK.  For the current version of
+ocfs, the ENABLE_CACHE and EXCLUSIVE levels should be treated the same,
+meaning that a particular node has an exclusive lock on this resource
+and has full write access to the metadata.  The SHARED lock is only used
+for readdir() operations currently, and NO_LOCK means that there are no
+nodes currently with a lock on this entry.
+Additionally, you will want to look at the publish and vote sectors for
+all nodes that you suspect are involved in the hang.  For instance, if
+you believe that node numbers 0 and 3 are deadlocked on a resource, you
+should run:
+  debugocfs -v 0,3 -p 0,3 /dev/device
+to see which node is requesting votes (in their publish sector) and what
+the other node (the voting node) is responding with.  Unless a node is
+responding with FLAG_VOTE_NODE (in the vote slot for the requesting
+node) or FLAG_VOTE_OIN_UPDATED then the requesting node may be forced to
+continue retrying the lock until the conflict is resolved.  To watch
+these values change over time, try:
+  watch -d --interval=1 "debugocfs -v 0,3 -p 0,3 /dev/device"
+in order to see if the lock sequence number is changing, and whether
+only one node is requesting votes (and starving out others).
+
+
+* Disclaimer
+Note that while all of these techniques can be used to help Oracle
+Support or Engineering determine the root cause of a problem with ocfs,
+one should not attempt to modify an ocfs filesystem by hand, and could
+result in further corruption of the filesystem.  Only attempt such an
+action if specifically asked to by Support.  With that said, it is
+worthwhile to note that it is extremely rare that one will encounter any
+problems whereby an oracle datafile's *data* will actually be corrupted.
+Most hangs, file entry and directory entry corruptions can be repaired,
+if necessary, for the purposes of recovering file data.

Added: trunk/debugocfs/extfinder.c
===================================================================
--- trunk/debugocfs/extfinder.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/debugocfs/extfinder.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,240 @@
+/*
+ * extfinder.c
+ *
+ * Lists the free extent sizes of an ocfs volume
+ *
+ * Copyright (C) 2003, 2004 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Sunil Mushran
+ */
+
+#include "debugocfs.h"
+#include "glib.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+int bmrun_reversesort(const void *a, const void *b);
+void print_global_bitmap_runs(int fd, void *buf);
+int read_vol_disk_header(int fd, ocfs_vol_disk_hdr * v);
+
+int extents_to_print = 0;
+int verbose = 0;
+
+typedef struct _bitmap_run
+{
+	int start;
+	int size;
+} bitmap_run;
+
+
+#define MAX_BITMAP_RUNS 10
+
+
+int bmrun_reversesort(const void *a, const void *b)
+{
+	bitmap_run *one, *two;
+	one = (bitmap_run *)a;	
+	two = (bitmap_run *)b;
+	if (one->size < two->size)
+		return 1;
+	else if (one->size == two->size)
+		return 0;
+	else 
+		return -1;
+}
+
+
+void print_global_bitmap_runs(int fd, void *buf)
+{
+//	__u64 dso, cs, num;
+	char *bmbuf = NULL;
+	int bufsz;
+	ocfs_vol_disk_hdr * v = (ocfs_vol_disk_hdr *)buf;
+	int non_sysfile, sysfile;
+	int i;
+	bitmap_run run;
+	GArray *arr = NULL;
+	
+	arr = g_array_new(TRUE, TRUE, sizeof(bitmap_run));
+	if (!arr) {
+		LOG_ERROR("out of memory");
+		goto bail;
+	}
+
+//	dso = v->data_start_off;
+//	cs = v->cluster_size;
+//	num = v->num_clusters;
+//	bufsz = (num+7)/8;
+	bufsz = 1024 * 1024;
+	bmbuf = (char *)malloc_aligned(bufsz); 
+	if (!bmbuf) {
+		LOG_ERROR("out of memory");
+		goto bail;
+	}
+
+	if (lseek64(fd, v->bitmap_off, SEEK_SET) == -1) {
+		LOG_ERROR("%s", strerror(errno));
+		goto bail;
+	}
+		
+	if (read(fd, bmbuf, bufsz) == -1) {
+		LOG_ERROR("%s", strerror(errno));
+		goto bail;
+	}
+
+	if (verbose) {
+		printf("bitmap_off = %llu\n", v->bitmap_off);
+		printf("data_start_off = %llu\n", v->data_start_off);
+		printf("cluster_size = %llu\n", v->cluster_size);
+		printf("num_clusters = %llu\n", v->num_clusters);
+	}
+   
+	sysfile = ((8 * ONE_MEGA_BYTE) / v->cluster_size);
+	non_sysfile = v->num_clusters - sysfile;
+	if (non_sysfile < 0)
+			non_sysfile = 0;
+
+	run.start = -1;
+	run.size = 0;
+	for (i = 0; i < non_sysfile; i++) {
+		if (!test_bit(i, bmbuf)) {
+			run.size++;
+			if (run.start==-1)
+				run.start = i;
+		}
+		else {
+			if (run.start != -1 && run.size != 0) {
+				g_array_append_val(arr, run);
+				run.start = -1;
+				run.size = 0;
+			}
+		}
+	}
+
+	if (run.start != -1)
+		g_array_append_val(arr, run);
+
+	printf("Runs of contiguous free space available (decending order)\n");
+	printf("Run #\tLength (KB)\tStarting bit number\n");
+	printf("=====\t===========\t===================\n");
+	if (arr->len > 0) {
+		qsort(arr->data, arr->len, sizeof(bitmap_run), bmrun_reversesort);
+    		for (i = 0; i < (arr->len > extents_to_print ?
+				 extents_to_print : arr->len); i++) {
+			bitmap_run *run = &g_array_index(arr, bitmap_run, i);
+			__u64 kb = (((__u64)run->size) * v->cluster_size) / 1024ULL;
+			printf("%5d\t%11llu\t%-9d\n", i+1, kb, run->start);
+		}
+	}
+bail:
+	if (arr)
+		g_array_free(arr, FALSE);
+
+	if (bmbuf)
+		free_aligned(bmbuf);
+	return ;
+}
+
+int read_vol_disk_header(int fd, ocfs_vol_disk_hdr * v)
+{
+	int ret = -1;
+
+	if (lseek64(fd, 0, SEEK_SET) == -1) {
+		LOG_ERROR("%s", strerror(errno));
+		goto bail;
+	}
+
+	if (read(fd, v, 512) == -1) {
+		LOG_ERROR("%s", strerror(errno));
+		goto bail;
+	}
+
+	if (strncmp(v->signature, "OracleCFS", strlen("OracleCFS")) != 0) {
+		LOG_ERROR("not a valid ocfs partition");
+		goto bail;
+	}
+
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+void usage()
+{
+    printf("usage: extfinder /dev/device\n");
+}
+
+void version(char *prog)
+{
+    printf("%s %s %s (build %s)\n", prog,
+	   OCFS_BUILD_VERSION, OCFS_BUILD_DATE,
+	   OCFS_BUILD_MD5);
+}
+
+
+/* uh, main */
+int main(int argc, char **argv)
+{
+    ocfs_vol_disk_hdr *diskHeader = NULL;
+    int fd = 0;
+    char rawdev[255];
+    int rawminor = 0;
+
+    version(argv[0]);
+
+    if (argc < 2) {
+	usage();
+	goto bail;
+    }
+
+    if (argc==3)
+	extents_to_print = atoi(argv[2]);
+
+    if (extents_to_print <= 0)
+        extents_to_print = MAX_BITMAP_RUNS;
+
+    diskHeader = (ocfs_vol_disk_hdr *) malloc_aligned(512);
+    if (!diskHeader) {
+	    LOG_ERROR("out of memory");
+	    goto bail;
+    }
+
+    if (bind_raw(argv[1], &rawminor, rawdev, sizeof(rawdev)) == -1)
+	    goto bail;
+
+    fd = open(rawdev, O_RDONLY);
+    if (fd == -1) {
+	usage();
+	goto bail;
+    }
+
+    if (read_vol_disk_header(fd, diskHeader) == -1)
+	    goto bail;
+
+    print_global_bitmap_runs(fd, diskHeader);
+
+bail:
+    if (diskHeader)
+	    free_aligned(diskHeader);
+    if (fd)
+	    close(fd);
+    if (rawminor)
+	    unbind_raw(rawminor, rawdev);
+    exit(0);
+}

Added: trunk/debugocfs/io.c
===================================================================
--- trunk/debugocfs/io.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/debugocfs/io.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,212 @@
+/*
+ * io.c
+ *
+ * provides the actual file I/O support in debugocfs and
+ * libdebugocfs for specific filesystem structures
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Kurt Hackel
+ */
+
+#include "debugocfs.h"
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+extern int filenum;
+extern user_args args;
+extern __u32 OcfsDebugCtxt;
+extern __u32 OcfsDebugLevel;
+
+
+loff_t myseek64(int fd, loff_t off, int whence)
+{
+    loff_t res;
+
+    if ((res = lseek64(fd, off, whence) == -1))
+    {
+	printf("Failed to lseek to %lld!\n", off);
+    }
+    return res;
+}
+
+void read_publish_sector(int fd, ocfs_publish * ps, __u64 offset)
+{
+    myseek64(fd, offset, SEEK_SET);
+    read(fd, ps, 512);
+}
+
+int write_publish_sector(int fd, ocfs_publish * ps, __u64 offset)
+{
+    int ret;
+    void *sector;
+
+    sector = malloc_aligned(512);
+    memset(sector, 1, 512);
+    memcpy(sector, ps, sizeof(ocfs_publish));
+    myseek64(fd, offset, SEEK_SET);
+    ret = write(fd, sector, 512);
+    free_aligned(sector);
+    return ret;
+}
+
+
+void read_vote_sector(int fd, ocfs_vote * vs, __u64 offset)
+{
+    myseek64(fd, offset, SEEK_SET);
+    read(fd, vs, 512);
+}
+
+int write_vote_sector(int fd, ocfs_vote * vs, __u64 offset)
+{
+    int ret;
+    void *sector;
+
+    sector = malloc_aligned(512);
+    memset(sector, 1, 512);
+    memcpy(sector, vs, sizeof(ocfs_vote));
+    myseek64(fd, offset, SEEK_SET);
+    ret = write(fd, sector, 512);
+    free_aligned(sector);
+    return ret;
+}
+
+void read_system_file(int fd, ocfs_vol_disk_hdr * v, int fileid,
+		      ocfs_file_entry * fe)
+{
+    __u64 diskOffset = (fileid * 512) + v->internal_off;
+
+    myseek64(fd, diskOffset, SEEK_SET);
+    read(fd, fe, 512);
+}
+
+int write_system_file(int fd, ocfs_vol_disk_hdr * v, int fileid,
+		      ocfs_file_entry * fe)
+{
+    int ret;
+    void *sector;
+    __u64 diskOffset = (fileid * 512) + v->internal_off;
+
+    sector = malloc_aligned(512);
+    memset(sector, 1, 512);
+    memcpy(sector, fe, sizeof(ocfs_file_entry));
+    myseek64(fd, diskOffset, SEEK_SET);
+    ret = write(fd, sector, 512);
+    free_aligned(sector);
+    return ret;
+}
+
+void read_vol_disk_header(int fd, ocfs_vol_disk_hdr * v)
+{
+    myseek64(fd, 0, SEEK_SET);
+    //read(fd, v, sizeof(ocfs_vol_disk_hdr));
+    read(fd, v, 512);
+}
+
+int write_vol_disk_header(int fd, ocfs_vol_disk_hdr * v)
+{
+    int ret;
+    void *sector;
+
+    sector = malloc_aligned(512);
+    memset(sector, 1, 512);
+    memcpy(sector, v, sizeof(ocfs_vol_disk_hdr));
+    myseek64(fd, 0, SEEK_SET);
+    ret = write(fd, sector, 512);
+    free_aligned(sector);
+    return ret;
+}
+
+void read_vol_label(int fd, ocfs_vol_label * v)
+{
+    myseek64(fd, 512, SEEK_SET);
+    //read(fd, v, sizeof(ocfs_vol_label));
+    read(fd, v, 512);
+}
+
+int write_vol_label(int fd, ocfs_vol_label * v)
+{
+    int ret;
+    void *sector;
+
+    sector = malloc_aligned(512);
+    memset(sector, 1, 512);
+    memcpy(sector, v, sizeof(ocfs_vol_label));
+    myseek64(fd, 512, SEEK_SET);
+    ret = write(fd, sector, 512);
+    free_aligned(sector);
+    return ret;
+}
+
+void read_extent(int fd, ocfs_extent_group * e, __u64 offset)
+{
+    myseek64(fd, offset, SEEK_SET);
+    if (read(fd, e, 512) != 512)
+        printf("hmm... short read for extent\n");
+}
+
+
+void read_dir_node(int fd, ocfs_dir_node * d, __u64 offset)
+{
+    int err;
+
+    myseek64(fd, offset, SEEK_SET);
+    err = read(fd, d, DIR_NODE_SIZE);
+    if (err == -1)
+	    fprintf(stderr, "read_dir_node: %s\n", strerror(errno));
+    else if (err != DIR_NODE_SIZE)
+	    printf("hmm... short read for dir node\n");
+}
+
+int write_dir_node_header(int fd, ocfs_dir_node * d, __u64 offset)
+{
+    int ret;
+    void *sector;
+
+    sector = malloc_aligned(512);
+    memset(sector, 1, 512);
+    memcpy(sector, d, sizeof(ocfs_dir_node));
+    myseek64(fd, offset, SEEK_SET);
+    ret = write(fd, sector, 512);
+    free_aligned(sector);
+    return ret;
+}
+
+int write_file_entry(int fd, ocfs_file_entry * f, __u64 offset)
+{
+    int ret;
+    void *sector;
+
+    sector = malloc_aligned(512);
+    memset(sector, 1, 512);
+    memcpy(sector, f, sizeof(ocfs_file_entry));
+    myseek64(fd, offset, SEEK_SET);
+    ret = write(fd, sector, 512);
+    free_aligned(sector);
+    return ret;
+}
+
+
+void read_cdsl_data(int fd, void *data, __u64 offset)
+{
+    int len = sizeof(__u64) * MAX_NODES;
+
+    myseek64(fd, offset, SEEK_SET);
+    if (read(fd, data, len) != len)
+	printf("hmm... short read for cdsl data\n");
+}

Added: trunk/debugocfs/libdebugocfs.c
===================================================================
--- trunk/debugocfs/libdebugocfs.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/debugocfs/libdebugocfs.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,337 @@
+#include "debugocfs.h"
+#include <time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "glib.h"
+#include "libdebugocfs.h"
+
+static int libocfs_init(const char *dev, ocfs_vol_disk_hdr ** dh)
+{
+    int fd;
+
+    fd = open(dev, O_RDONLY);
+    if (fd == -1)
+    {
+	return fd;
+    }
+    *dh = (ocfs_vol_disk_hdr *) malloc(512);
+    read_vol_disk_header(fd, *dh);
+    return fd;
+}
+
+static int libocfs_init_write(const char *dev, ocfs_vol_disk_hdr ** dh)
+{
+    int fd;
+
+    fd = open(dev, O_RDWR);
+    if (fd == -1)
+    {
+	return fd;
+    }
+    *dh = (ocfs_vol_disk_hdr *) malloc(512);
+    read_vol_disk_header(fd, *dh);
+    return fd;
+}
+
+int libocfs_readdir(const char *dev, const char *dir, int recurse,
+		    GArray ** arr)
+{
+    int fd;
+    ocfs_vol_disk_hdr *diskHeader;
+    __u64 off;
+    ocfs_super *vcb;
+
+    if ((fd = libocfs_init(dev, &diskHeader)) == -1)
+	return 1;
+
+    if (!arr ||
+	(*arr = g_array_new(TRUE, TRUE, sizeof(libocfs_stat))) == NULL)
+    {
+	free(diskHeader);
+	close(fd);
+	return 2;
+    }
+
+    if (strcmp(dir, "/") == 0)
+	off = diskHeader->root_off;
+    else
+    {
+	vcb = get_fake_vcb(fd, diskHeader, DEFAULT_NODE_NUMBER);
+	find_file_entry(vcb, diskHeader->root_off, "/", dir, FIND_MODE_DIR,
+			(void *) (&off));
+	free(vcb);
+    }
+
+    if (off <= 0)
+    {
+	g_array_free(*arr, FALSE);
+	free(diskHeader);
+	close(fd);
+	return 3;
+    }
+
+    walk_dir_nodes(fd, off, dir, (void *) (*arr));
+
+    close(fd);
+    free(diskHeader);
+    return 0;
+}
+
+int libocfs_get_bitmap(const char *dev, char **bmap, int *numbits)
+{
+    int fd;
+    __u64 readlen;
+    ocfs_vol_disk_hdr *diskHeader;
+
+    if (!bmap || !numbits)
+	return 2;
+
+    if ((fd = libocfs_init(dev, &diskHeader)) == -1)
+	return 1;
+
+    readlen = 1 << 20;		// now fixed size of 1MB
+    *bmap = (void *) g_malloc(readlen);
+
+    myseek64(fd, diskHeader->bitmap_off, SEEK_SET);
+    read(fd, *bmap, readlen);
+
+    *numbits = diskHeader->num_clusters;
+
+    free(diskHeader);
+    close(fd);
+    return 0;
+}
+
+int libocfs_get_volume_info(const char *dev, libocfs_volinfo ** info)
+{
+    int fd;
+    ocfs_vol_disk_hdr *diskHeader;
+
+    if (!info)
+	return 2;
+
+    if ((fd = libocfs_init(dev, &diskHeader)) == -1)
+	return 1;
+
+    *info = (libocfs_volinfo *) malloc(sizeof(libocfs_volinfo));
+    (*info)->major_ver = diskHeader->major_version;
+    (*info)->minor_ver = diskHeader->minor_version;
+    memcpy((*info)->signature, diskHeader->signature, 128);
+    (*info)->signature[127] = '\0';
+    memcpy((*info)->mountpoint, diskHeader->mount_point, 128);
+    (*info)->mountpoint[127] = '\0';
+    (*info)->length = diskHeader->device_size;
+    (*info)->num_extents = diskHeader->num_clusters;
+    (*info)->extent_size = diskHeader->cluster_size;
+    memset((*info)->mounted_nodes, 0, 32);
+    (*info)->protection = diskHeader->prot_bits;
+    (*info)->protection |= S_IFDIR;
+    (*info)->uid = diskHeader->uid;
+    (*info)->gid = diskHeader->gid;
+
+    free(diskHeader);
+    close(fd);
+    return 0;
+}
+
+int libocfs_is_ocfs_partition(const char *dev)
+{
+    int fd, ret = 0;
+    ocfs_vol_disk_hdr *diskHeader;
+
+    if ((fd = libocfs_init(dev, &diskHeader)) == -1)
+	return 0;
+    if (memcmp(diskHeader->signature,
+	       OCFS_VOLUME_SIGNATURE,
+	       strlen(OCFS_VOLUME_SIGNATURE)) == 0)
+	ret = 1;
+    if (diskHeader->major_version >= 9)
+        ret = 0;
+
+    free(diskHeader);
+    close(fd);
+    return ret;
+}
+
+int libocfs_chown_volume(const char *dev, int protection, int uid, int gid)
+{
+    int fd, ret = 0;
+    ocfs_vol_disk_hdr *diskHeader;
+
+    if ((fd = libocfs_init_write(dev, &diskHeader)) == -1)
+    {
+	ret = 1;
+	goto bail;
+    }
+
+    diskHeader->prot_bits = (protection & 0007777);	// blank out non-permissions
+    diskHeader->uid = uid;
+    diskHeader->gid = gid;
+
+    /* XXX totally, completely, utterly UNSAFE!!!!!!!!!!!!!! XXX */
+    /* no locking at all, need to figure this out */
+    if (write_vol_disk_header(fd, diskHeader) != OCFS_SECTOR_SIZE)
+	ret = 2;
+
+    free(diskHeader);
+    close(fd);
+  bail:
+    return ret;
+}
+
+
+int get_node_config_data(ocfs_super * vcb, GArray * arr)
+{
+    ocfs_disk_node_config_info *Node;
+    void *buffer;
+    int i, j, ret = 0;
+    libocfs_node libnode;
+    int status;
+    __u32 tmp;
+
+    buffer = malloc(vcb->vol_layout.node_cfg_size);
+
+    tmp = LO(vcb->vol_layout.node_cfg_size);
+    status =
+	ocfs_read_disk(vcb, buffer, tmp, vcb->vol_layout.node_cfg_off);
+    if (status < 0)
+    {
+	ret = 1;
+	goto bail;
+    }
+
+    for (i = 0; i < OCFS_MAXIMUM_NODES; i++)
+    {
+	// starts at the 3rd sector
+	Node =
+	    (ocfs_disk_node_config_info *) ((char *) buffer +
+					    ((2 + i) * OCFS_SECTOR_SIZE));
+
+	if (!Node)
+	    continue;
+	if (Node->node_name[0] == '\0')
+	    continue;
+
+	memset(&libnode, 0, sizeof(libocfs_node));
+	strncpy(libnode.name, Node->node_name, OCFS_DBGLIB_MAX_NODE_NAME_LENGTH);
+	libnode.slot = i;
+	strncpy(libnode.addr, Node->ipc_config.ip_addr, OCFS_DBGLIB_IP_ADDR_LEN);
+        memcpy(libnode.guid, Node->guid.guid, OCFS_DBGLIB_GUID_LEN);
+	g_array_append_val(arr, libnode);
+    }
+  bail:
+    free(buffer);
+    return ret;
+}
+
+
+int libocfs_get_node_map(const char *dev, GArray ** arr)
+{
+    int fd, ret = 0;
+    ocfs_vol_disk_hdr *diskHeader;
+    ocfs_super *vcb;
+
+    if ((fd = libocfs_init(dev, &diskHeader)) == -1)
+    {
+	ret = 1;
+	goto bail;
+    }
+    vcb = get_fake_vcb(fd, diskHeader, DEFAULT_NODE_NUMBER);
+
+    if (!arr ||
+	(*arr = g_array_new(TRUE, TRUE, sizeof(libocfs_node))) == NULL)
+    {
+	ret = 2;
+	goto free;
+    }
+
+    ret = get_node_config_data(vcb, *arr);
+
+  free:
+    free(diskHeader);
+    free(vcb);
+    close(fd);
+  bail:
+    return ret;
+}
+
+int libocfs_dump_file(const char *dev, const char *path, const char *file)
+{
+    return libocfs_dump_file_as_node(dev, path, file, DEFAULT_NODE_NUMBER);
+}
+
+int libocfs_dump_file_as_node(const char *dev, const char *path,
+			      const char *file, int node)
+{
+    int fd, ret = 0;
+    ocfs_vol_disk_hdr *diskHeader;
+    ocfs_super *vcb;
+
+    if ((fd = libocfs_init(dev, &diskHeader)) == -1)
+    {
+	ret = 1;
+	goto bail;
+    }
+
+    vcb = get_fake_vcb(fd, diskHeader, node);
+    ret = suck_file(vcb, path, file);
+
+    free(diskHeader);
+    free(vcb);
+    close(fd);
+
+  bail:
+    return ret;
+}
+
+
+void handle_one_file_entry(int fd, ocfs_file_entry *fe, void *buf)
+{
+    libocfs_stat st;
+    int j;
+    void *cdslbuf;
+    GArray *arr = (GArray *)buf;
+        
+    memcpy(st.name, fe->filename, 255);
+    st.name[254] = '\0';
+    st.current_master = fe->disk_lock.curr_master;
+    st.size = fe->file_size;
+    st.alloc_size = fe->alloc_size;
+    st.open_map = (fe->disk_lock.oin_node_map & 0x00000000ffffffffULL);	// uh, this is really still just 32 bits
+    st.protection = fe->prot_bits;
+
+    if (fe->attribs & OCFS_ATTRIB_DIRECTORY)
+        st.protection |= S_IFDIR;
+    else if (fe->attribs & OCFS_ATTRIB_CHAR)
+        st.protection |= S_IFCHR;
+    else if (fe->attribs & OCFS_ATTRIB_BLOCK)
+        st.protection |= S_IFBLK;
+    else if (fe->attribs & OCFS_ATTRIB_REG)
+        st.protection |= S_IFREG;
+    else if (fe->attribs & OCFS_ATTRIB_FIFO)
+        st.protection |= S_IFIFO;
+    else if (fe->attribs & OCFS_ATTRIB_SYMLINK)
+        st.protection |= S_IFLNK;
+    else if (fe->attribs & OCFS_ATTRIB_SOCKET)
+        st.protection |= S_IFSOCK;
+        
+    st.uid = fe->uid;
+    st.gid = fe->gid;
+    st.dir_entries = -1;	// TODO: need to implement or throw it out
+        
+    st.attribs = 0;
+    st.cdsl_bitmap = 0;
+    if (fe->attribs & OCFS_ATTRIB_FILE_CDSL)
+    {
+        st.attribs |= OCFS_DBGLIB_ATTRIB_FILE_CDSL;
+        cdslbuf = malloc(sizeof(__u64) * MAX_NODES);
+        read_cdsl_data(fd, cdslbuf, fe->extents[0].disk_off);
+        for (j = 0; j < MAX_NODES; j++)
+            if (*(((__u64 *) cdslbuf) + j) != 0)
+                st.cdsl_bitmap |= (1 << j);
+        free(cdslbuf);
+    }
+
+    g_array_append_val(arr, st);
+}

Added: trunk/debugocfs/libdebugocfs.h
===================================================================
--- trunk/debugocfs/libdebugocfs.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/debugocfs/libdebugocfs.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,86 @@
+/*
+ * libdebugocfs.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Kurt Hackel
+ */
+
+#ifndef _LIBDEBUGOCFS_H_
+#define _LIBDEBUGOCFS_H_
+
+#define OCFS_DBGLIB_ATTRIB_FILE_CDSL (0x1)
+
+typedef struct _libocfs_stat
+{
+    char name[255];
+    int current_master;
+    unsigned long long size;
+    unsigned long long alloc_size;
+    unsigned int open_map;
+    int protection;
+    int uid;
+    int gid;
+    int dir_entries;		/* will be -1 if not a dir */
+    int attribs;
+    unsigned int cdsl_bitmap;
+}
+libocfs_stat;
+
+typedef struct _libocfs_volinfo
+{
+    int major_ver;
+    int minor_ver;
+    char signature[128];
+    char mountpoint[128];
+    unsigned long long length;
+    unsigned long long num_extents;
+    int extent_size;
+    char mounted_nodes[32];	/* hardcoded for now! */
+    int protection;
+    int uid;
+    int gid;
+}
+libocfs_volinfo;
+
+#define OCFS_DBGLIB_MAX_NODE_NAME_LENGTH 32
+#define OCFS_DBGLIB_GUID_LEN             32
+#define OCFS_DBGLIB_IP_ADDR_LEN          15
+typedef struct _libocfs_node
+{
+    char name[OCFS_DBGLIB_MAX_NODE_NAME_LENGTH + 1];
+    char addr[OCFS_DBGLIB_IP_ADDR_LEN + 1];
+    int slot;
+    char guid[OCFS_DBGLIB_GUID_LEN + 1];
+}
+libocfs_node;
+
+int libocfs_readdir(const char *dev, const char *dir, int recurse,
+		    GArray ** arr);
+int libocfs_get_bitmap(const char *dev, char **bmap, int *numbits);
+int libocfs_get_volume_info(const char *dev, libocfs_volinfo ** info);
+int libocfs_is_ocfs_partition(const char *dev);
+int libocfs_chown_volume(const char *dev, int protection, int uid, int gid);
+int libocfs_get_node_map(const char *dev, GArray ** arr);
+int libocfs_dump_file(const char *dev, const char *path, const char *file);
+int libocfs_dump_file_as_node(const char *dev, const char *path,
+			      const char *file, int node);
+
+#endif				/* _LIBDEBUGOCFS_H_ */

Added: trunk/debugocfs/main.c
===================================================================
--- trunk/debugocfs/main.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/debugocfs/main.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,551 @@
+/*
+ * main.c
+ *
+ * entry point for normal and -X mode debugocfs
+ *
+ * Copyright (C) 2002, 2004 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Author: Kurt Hackel, Sunil Mushran
+ */
+
+#include "debugocfs.h"
+
+/* getopt stuff */
+int getopt(int argc, char *const argv[], const char *optstring);
+extern char *optarg;
+extern int optind, opterr, optopt;
+
+extern __u32 OcfsDebugCtxt;
+extern __u32 OcfsDebugLevel;
+
+void translate_usage(void);
+void do_translate(int argc, char **argv);
+
+/* global stuff */
+int filenum;
+user_args args;
+
+void usage(void)
+{
+    printf("debugocfs: Usage: debugocfs [-?] [-h] [-g] [-l] [-v range] [-p range]\n");
+    printf("           [-d /dir/name] [-f /file/name [-s /path/to/file]] [-a range] [-A range]\n");
+    printf("           [-b range] [-B range] [-r range] [-c range] [-L range] [-M range]\n");
+    printf("           [-n nodenum] /dev/name\n");
+    printf("\n");
+    printf("       -h: volume header\n");
+    printf("       -g: global bitmap\n");
+    printf("       -l: full listing of all file entries\n");
+    printf("       -v: vote sector\n");
+    printf("       -2: print 8-byte number as 2 4-byte numbers\n");
+    printf("       -p: publish sector\n");
+    printf("       -d: first ocfs_dir_node structure for a given path\n");
+    printf("       -D: all ocfs_dir_node structures for a given path\n");
+    printf("       -f: ocfs_file_entry structure for a given file\n");
+    printf("       -F: ocfs_file_entry and ocfs_extent_group structures for a given file\n");
+    printf("       -s: suck file out to a given location\n");
+    printf("       -a: file allocation system file\n");
+    printf("       -A: dir allocation system file\n");
+    printf("       -b: file allocation bitmap system file\n");
+    printf("       -B: dir allocation bitmap system file\n");
+    printf("       -r: recover log file system file\n");
+    printf("       -c: cleanup log system file\n");
+    printf("       -L: vol metadata log system file\n");
+    printf("       -M: vol metadata system file\n");
+    printf("       -n: perform action as node number given\n");
+    printf("/dev/name: readable device\n");
+    printf("    range: node numbers to inspect (0-31), commas and dashes ok\n");
+    printf("            ex. 0-3,5,14-17\n");
+}
+
+void translate_usage(void)
+{
+    printf("Usage: debugocfs -X { -h highoff -l lowoff | -o off } -t type\n");
+    printf("\n");
+    printf("       highoff/lowoff: 32-bit high and low offsets to data\n");
+    printf("                  off: 64-bit offset to data\n");
+    printf("                 type: one of the following types to cast data to:\n");
+    printf("                         ocfs_vol_label\n");
+    printf("                         ocfs_vol_disk_hdr\n");
+    printf("                         ocfs_dir_node\n");
+    printf("                         ocfs_file_entry\n");
+    printf("                         ocfs_vote\n");
+    printf("                         ocfs_publish\n");
+    printf("                         cdsl_offsets\n");
+}
+
+
+/* special translate mode junk */
+typedef void (*debugocfs_print_func) (void *buf);
+
+void do_translate(int argc, char **argv)
+{
+    int c, ok = true;
+    __u64 off = 0;
+    int size = 0;
+    char *type = NULL;
+    char *dot;
+    int fd = 0;
+    debugocfs_print_func func;
+    int flags;
+    char rawdev[255];
+    int rawminor = 0;
+
+    while (1)
+    {
+	c = getopt(argc, argv, "2o:h:l:s:t:");
+	if (c == -1)
+	    break;
+	switch (c)
+	{
+	    case 'o':
+		if ((dot = strchr(optarg, '.')) != NULL)
+		{
+		    *dot = '\0';
+		    off = atoll(optarg);
+		    *dot = '.';
+		}
+		break;
+	    case 'h':
+		off |= ((__u64) strtoul(optarg, NULL, 0)) << 32;
+		ok = !ok;
+		break;
+	    case 'l':
+		off |= strtoul(optarg, NULL, 0);
+		ok = !ok;
+		break;
+	    case 't':
+		type = (char *) strdup(optarg);
+		break;
+	    case '2':		/* display 8-byte nums as 2 4-byte nums */
+		args.twoFourbyte = true;
+		break;
+            case '?':
+                translate_usage();
+                exit(1);
+                break;
+	    default:
+		break;
+	}
+    }
+    if (!ok)
+    {
+	printf("Oops. You must give both a high and low part.\n");
+	exit(1);
+    }
+
+    if (type == NULL)
+    {
+	printf ("Oops. You must give a valid type.\n");
+	exit(1);
+    }
+    if (strcasecmp(type, "ocfs_vol_label") == 0)
+    {
+	size = sizeof(ocfs_vol_label);
+	func = print_vol_label;
+    }
+    else if (strcasecmp(type, "ocfs_vol_disk_hdr") == 0)
+    {
+        size = sizeof(ocfs_vol_disk_hdr);
+	func = print_vol_disk_header;
+    }
+    else if (strcasecmp(type, "ocfs_dir_node") == 0)
+    {
+        size = sizeof(ocfs_dir_node);
+        func = print_dir_node;
+    }
+    else if (strcasecmp(type, "ocfs_file_entry") == 0)
+    {
+        size = sizeof(ocfs_file_entry);
+        func = print_file_entry;
+    }
+    else if (strcasecmp(type, "ocfs_vote") == 0)
+    {
+        size = sizeof(ocfs_vote);
+        func = print_vote_sector;
+    }
+    else if (strcasecmp(type, "ocfs_publish") == 0)
+    {
+        size = sizeof(ocfs_publish);
+        func = print_publish_sector;
+    }
+    else if (strcasecmp(type, "cdsl_offsets") == 0)
+    {
+        size = (sizeof(__u64) * MAX_NODES);
+        func = print_cdsl_offsets;
+    }
+    else if (strcasecmp(type, "ocfs_extent_group") == 0)
+    {
+	    size = sizeof(ocfs_extent_group);
+	    func = print_extent_ex;
+    }
+    else
+    {
+	printf ("Oops. You must give a valid type.\n");
+	exit(1);
+    }
+
+    if (bind_raw(argv[optind], &rawminor, rawdev, sizeof(rawdev)) == -1)
+	    goto bail;
+
+    flags = O_RDONLY | O_LARGEFILE;
+    fd = open(rawdev, flags);
+    if (fd == -1)
+	goto bail;
+
+    printf("offset: %lld, type: %s\n", off, type);
+
+    {
+	void *buf;
+
+        buf = malloc_aligned(size);
+	if (buf == NULL)
+	{
+	    printf("failed to alloc %d bytes\n", size);
+	    exit(1);
+	}
+	myseek64(fd, off, SEEK_SET);
+
+	printf("seeked ok\n");
+	if (read(fd, buf, size) != -1)
+	{
+	    printf("successful read\n");
+            func(buf);
+	}
+	free(buf);
+    }
+
+bail:
+    if (type)
+	free(type);
+    if (fd)
+	    close(fd);
+    if (rawminor)
+	    unbind_raw(rawminor, rawdev);
+}
+
+void version(char *prog)
+{
+	printf("%s %s %s (build %s)\n", prog, OCFS_BUILD_VERSION,
+	       OCFS_BUILD_DATE, OCFS_BUILD_MD5);
+}
+
+/* uh, main */
+int main(int argc, char **argv)
+{
+    ocfs_vol_label *volLabel = NULL;
+    ocfs_vote *vs = NULL;
+    ocfs_publish *ps = NULL;
+    ocfs_vol_disk_hdr *diskHeader = NULL;
+    int i, fd = 0;
+    ocfs_super *vcb = NULL;
+    char *env;
+    int flags;
+    char rawdev[255];
+    int rawminor = 0;
+
+    version(argv[0]);
+
+    if ((env = getenv("dbgctxt")) != NULL)
+        OcfsDebugCtxt = strtol(env, NULL, 16);
+    if ((env = getenv("dbglvl")) != NULL)
+        OcfsDebugLevel = strtol(env, NULL, 16);
+
+    memset(&args, 0, sizeof(user_args));
+    volLabel = (ocfs_vol_label *) malloc_aligned(512);
+    vs = (ocfs_vote *) malloc_aligned(512);
+    ps = (ocfs_publish *) malloc_aligned(512);
+    diskHeader = (ocfs_vol_disk_hdr *) malloc_aligned(512);
+    if (!volLabel || !vs || !ps || !diskHeader) {
+	    LOG_ERROR("out of memory");
+	    goto bail;
+    }
+
+    args.nodenum = -1;
+    while (1)
+    {
+	int off = 0;
+	int c = getopt(argc, argv, "hgl2v:p:d:D:f:F:a:A:b:B:b:r:c:L:M:s:n:X");
+
+	if (c == -1)
+	    break;
+	switch (c)
+	{
+	    case 'h':		/* header */
+		args.showHeader = true;
+		break;
+	    case 'g':		/* global bitmap */
+		args.showBitmap = true;
+		break;
+	    case 'p':		/* publish 0-31 */
+		args.showPublish = true;
+		if (!parse_numeric_range(optarg, &(args.publishNodes[0]),
+					 0, MAX_NODES, 0))
+		{
+		    usage();
+		    exit(1);
+		}
+		break;
+	    case 'v':		/* vote 0-31 */
+		args.showVote = true;
+		if (!parse_numeric_range(optarg, &(args.voteNodes[0]),
+					 0, MAX_NODES, 0))
+		{
+		    usage();
+		    exit(1);
+		}
+		break;
+	    case 'c':
+		if (!off)
+		    off = OCFS_SYSFILE_TYPE_TO_FILE_NUM(OCFS_CLEANUP_LOG_SYSFILE, 0);
+	    case 'r':
+		if (!off)
+                    off = OCFS_SYSFILE_TYPE_TO_FILE_NUM(OCFS_RECOVER_LOG_SYSFILE, 0);
+	    case 'b':
+		if (!off)
+		    off = OCFS_SYSFILE_TYPE_TO_FILE_NUM(OCFS_FILE_EXTENT_BM_SYSFILE, 0);
+	    case 'a':
+		if (!off)
+	   	    off = OCFS_SYSFILE_TYPE_TO_FILE_NUM(OCFS_FILE_EXTENT_SYSFILE, 0);
+	    case 'B':
+		if (!off)
+		    off = OCFS_SYSFILE_TYPE_TO_FILE_NUM(OCFS_DIR_BM_SYSFILE, 0);
+	    case 'A':
+		if (!off)
+		    off = OCFS_SYSFILE_TYPE_TO_FILE_NUM(OCFS_DIR_SYSFILE, 0);
+	    case 'L':
+		if (!off)
+		    off = OCFS_SYSFILE_TYPE_TO_FILE_NUM(OCFS_VOL_MD_LOG_SYSFILE, 0);
+	    case 'M':
+		if (!off)
+		    off = OCFS_SYSFILE_TYPE_TO_FILE_NUM(OCFS_VOL_MD_SYSFILE, 0);
+
+		if (off==OCFS_INVALID_SYSFILE ||
+                    !parse_numeric_range(optarg, &(args.systemFiles[0]), 0, MAX_NODES, off))
+		{
+		    usage();
+		    exit(1);
+		}
+		args.showSystemFiles = true;
+		break;
+	    case 'l':		/* listing */
+		args.showListing = true;
+		break;
+	    case 'd':		/* dirent */
+		args.showDirent = true;
+		args.dirent = (char *) strdup(optarg);
+		break;
+	    case 'D':		/* direntall */
+		args.showDirentAll = true;
+		args.dirent = (char *) strdup(optarg);
+		break;
+	    case 'f':		/* fileent */
+		args.showFileent = true;
+		args.fileent = (char *) strdup(optarg);
+		break;
+	    case 'F':		/* fileent + extents */
+		args.showFileext = true;
+		args.fileent = (char *) strdup(optarg);
+		break;
+	    case 's':		/* suck */
+		args.suckFile = true;
+		args.suckTo = (char *) strdup(optarg);
+		break;
+	    case 'n':		/* node number */
+		args.nodenum = atoi(optarg);
+		break;
+	    case 'X':		/* translate */
+		do_translate(argc, argv);
+		exit(0);
+		break;
+	    case '2':		/* display 8-byte nums as 2 4-byte nums */
+		args.twoFourbyte = true;
+		break;
+	    default:
+	    case '?':
+		usage();
+		exit(1);
+		break;
+	}
+    }
+
+    // what should be the default node number? 
+    if (args.nodenum < 0 || args.nodenum >= MAX_NODES)
+	args.nodenum = DEFAULT_NODE_NUMBER;
+
+    if (!(args.showHeader || args.showPublish || args.showVote ||
+	  args.showListing || args.showDirent || args.showFileent ||
+	  args.showFileext || args.showSystemFiles || args.showBitmap ||
+	  args.showDirentAll))
+    {
+	usage();
+	exit(1);
+    }
+
+    if (bind_raw(argv[optind], &rawminor, rawdev, sizeof(rawdev)) == -1)
+	    goto bail;
+
+    flags = O_RDONLY | O_LARGEFILE;
+    fd = open(rawdev, flags);
+    if (fd == -1)
+    {
+	usage();
+	goto bail;
+    }
+
+    read_vol_disk_header(fd, diskHeader);
+    read_vol_label(fd, volLabel);
+
+    vcb = get_fake_vcb(fd, diskHeader, args.nodenum);
+    if (!vcb) {
+	    LOG_ERROR("out of memory");
+	    goto bail;
+    }
+
+    if (args.showHeader)
+    {
+	printf("diskheader:\n");
+	print_vol_disk_header(diskHeader);
+	printf("\nvolumelabel:\n");
+	print_vol_label(volLabel);
+	printf("\n");
+    }
+
+    if (args.showBitmap)
+    {
+	printf("global_bitmap:\n");
+	print_global_bitmap(fd, diskHeader);
+	printf("\n");
+    }
+
+    if (args.showPublish)
+    {
+	for (i = 0; i < MAX_NODES; i++)
+	{
+	    if (args.publishNodes[i])
+	    {
+		printf("publish%d:\n", i);
+		read_publish_sector(fd, ps,
+				    diskHeader->publ_off + (__u64) (i * 512));
+		print_publish_sector(ps);
+	    }
+	}
+	printf("\n");
+    }
+    if (args.showVote)
+    {
+	for (i = 0; i < MAX_NODES; i++)
+	{
+	    if (args.voteNodes[i])
+	    {
+		printf("vote%d:\n", i);
+		read_vote_sector(fd, vs,
+				 diskHeader->vote_off + (__u64) (i * 512));
+		print_vote_sector(vs);
+	    }
+	}
+	printf("\n");
+    }
+
+    if (args.showListing)
+    {
+	filenum = 1;
+	printf("filelisting:\n");
+	walk_dir_nodes(fd, diskHeader->root_off, "/", NULL);
+    }
+
+    if (args.showDirent || args.showDirentAll)
+    {
+	printf("dirinfo:\n");
+	if (strcmp(args.dirent, "/") == 0)
+	{
+	    ocfs_dir_node *dir = (ocfs_dir_node *) malloc_aligned(DIR_NODE_SIZE);
+	    __u64 dir_off = diskHeader->root_off;
+
+	    printf("\tName = /\n");
+	    while (1) {
+		    read_dir_node(fd, dir, dir_off);
+		    print_dir_node(dir);
+		    if (!args.showDirentAll || dir->next_node_ptr == INVALID_NODE_POINTER)
+			    break;
+		    dir_off = dir->next_node_ptr;
+		    memset(dir, 0, DIR_NODE_SIZE);
+	    	    printf("dirinfo:\n");
+	    }
+	    free(dir);
+	}
+	else
+	{
+	    find_file_entry(vcb, diskHeader->root_off, "/", args.dirent,
+			    FIND_MODE_DIR, NULL);
+	}
+    }
+
+    if (args.showSystemFiles)
+    {
+	for (i = 0; i < MAX_SYSTEM_FILES; i++)
+	{
+	    if (args.systemFiles[i])
+	    {
+		print_system_file(fd, diskHeader, i);
+	    }
+	}
+    }
+
+    if (args.showFileent || args.showFileext)
+    {
+	if (args.suckFile)
+	{
+	    suck_file(vcb, args.fileent, args.suckTo);
+	    free(args.suckTo);
+	}
+	else
+	{
+	    printf("fileinfo:\n");
+	    if (strcmp(args.fileent, "/") == 0)
+	    {
+		printf("the root directory '/' has no file entry\n");
+		goto bail;
+	    }
+	    else
+	    {
+		find_file_entry(vcb, diskHeader->root_off, "/", args.fileent,
+				(args.showFileext ? FIND_MODE_FILE_EXTENT :
+				 FIND_MODE_FILE), NULL);
+	    }
+	}
+    }
+
+bail:
+    if (volLabel)
+	    free_aligned(volLabel);
+    if (vs)
+	    free_aligned(vs);
+    if (ps)
+	    free_aligned(ps);
+    if (diskHeader)
+	    free_aligned(diskHeader);
+    if (vcb && vcb->sb)
+	    free_aligned(vcb->sb);
+    if (vcb)
+	    free_aligned(vcb);
+    if (fd)
+	    close(fd);
+    if (rawminor)
+	    unbind_raw(rawminor, rawdev);
+    exit(0);
+}

Added: trunk/debugocfs/print.c
===================================================================
--- trunk/debugocfs/print.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/debugocfs/print.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,893 @@
+/*
+ * print.c
+ *
+ * stdout printing support for debugocfs
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Kurt Hackel
+ */
+
+#include "debugocfs.h"
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+
+extern int filenum;
+extern user_args args;
+extern __u32 OcfsDebugCtxt;
+extern __u32 OcfsDebugLevel;
+
+void print_time(__u64 * sec);
+void print_file_attributes(__u32 attribs);
+void print_protection_bits(__u32 prot);
+void print_global_bitmap(int fd, void *buf);
+void print_system_file(int fd, ocfs_vol_disk_hdr * v, int fileid);
+void print_file_data(int fd, ocfs_file_entry * fe);
+void print_alloc_log(ocfs_alloc_log * rec);
+void print_dir_log(ocfs_dir_log * rec);
+void print_recovery_log(ocfs_recovery_log * rec);
+void print_lock_log(ocfs_lock_log * rec);
+void print_bcast_rel_log(ocfs_bcast_rel_log * rec);
+void print_delete_log(ocfs_delete_log * rec);
+void print_free_log(ocfs_free_log * rec);
+void print_extent_rec(ocfs_free_extent_log * rec);
+
+
+typedef __u64 (*bit2off_func)(int bitnum, void *data);
+__u64 global_bm_bitnum_to_offset(int bitnum, void *data);
+void print_bitmap(char *bmbuf, int bmsize, bit2off_func func, void *data);
+
+void print_vol_label(void *buf)
+{
+    ocfs_vol_label *v = (ocfs_vol_label *)buf;
+    print_disk_lock(&v->disk_lock);
+    printf("\tlabel = %s\n", v->label);
+    printf("\tlabel_len = %u\n", v->label_len);
+}
+
+void print_vol_disk_header(void *buf)
+{
+    ocfs_vol_disk_hdr * v = (ocfs_vol_disk_hdr *)buf;
+    printf("\tversion = %u.%u\n", v->major_version, v->minor_version);
+    printf("\tsignature = %s\n", v->signature);
+    printf("\tmount_point = %s\n", v->mount_point);
+    printf("\tserial_num = %llu\n", v->serial_num);
+    printf("\tdevice_size = %llu\n", v->device_size);
+    printf("\tstart_off = %llu\n", v->start_off);
+    printf("\tbitmap_off = %llu\n", v->bitmap_off);
+    printf("\tpubl_off = %llu\n", v->publ_off);
+    printf("\tvote_off = %llu\n", v->vote_off);
+    printf("\troot_bitmap_off = %llu\n", v->root_bitmap_off);
+    printf("\tdata_start_off = %llu\n", v->data_start_off);
+    printf("\troot_bitmap_size = %llu\n", v->root_bitmap_size);
+    printf("\troot_off = %llu\n", v->root_off);
+    printf("\troot_size = %llu\n", v->root_size);
+    printf("\tcluster_size = %llu\n", v->cluster_size);
+    printf("\tnum_nodes = %llu\n", v->num_nodes);
+    printf("\tnum_clusters = %llu\n", v->num_clusters);
+    printf("\tdir_node_size = %llu\n", v->dir_node_size);
+    printf("\tfile_node_size = %llu\n", v->file_node_size);
+    printf("\tinternal_off = %llu\n", v->internal_off);
+    printf("\tnode_cfg_off = %llu\n", v->node_cfg_off);
+    printf("\tnode_cfg_size = %llu\n", v->node_cfg_size);
+    printf("\tnew_cfg_off = %llu\n", v->new_cfg_off);
+    printf("\tprot_bits = 0%o\n", v->prot_bits);
+    printf("\tuid = %u\n", v->uid);
+    printf("\tgid = %u\n", v->gid);
+    printf("\texcl_mount = %d\n", v->excl_mount);
+}
+
+__u64 global_bm_bitnum_to_offset(int bitnum, void *data)
+{
+    ocfs_vol_disk_hdr *v = (ocfs_vol_disk_hdr *)data;
+    return (((__u64)bitnum * v->cluster_size) + v->data_start_off);
+}
+
+void print_bitmap(char *bmbuf, int bmsize, bit2off_func func, void *data)
+{    
+    int i;
+    __u64 off;
+
+    printf("\tSET\n");
+    for (i=0; i<bmsize; i++)
+    {
+        off = func(i, data);
+        if (test_bit(i, bmbuf))
+        {
+            printf("\t\t%llu (%d)\n", off, i);
+        }
+    }
+    printf("\tUNSET\n");
+    for (i=0; i<bmsize; i++)
+    {
+        off = func(i, data);
+        if (!test_bit(i, bmbuf))
+        {
+            printf("\t\t%llu (%d)\n", off, i);
+        }
+    }
+}
+
+void print_global_bitmap(int fd, void *buf)
+{
+    __u64 dso, cs, num;
+    char *bmbuf;
+    int bufsz;
+    ocfs_vol_disk_hdr * v = (ocfs_vol_disk_hdr *)buf;
+
+    dso = v->data_start_off;
+    cs = v->cluster_size;
+    num = v->num_clusters;
+    bufsz = (num+7)/8;
+    bufsz = OCFS_ALIGN(bufsz, 512);
+    bmbuf = (char *)malloc_aligned(bufsz); 
+    myseek64(fd, v->bitmap_off, SEEK_SET);
+    read(fd, bmbuf, bufsz);
+
+    printf("\tbitmap_off = %llu\n", v->bitmap_off);
+    printf("\tdata_start_off = %llu\n", v->data_start_off);
+    printf("\tcluster_size = %llu\n", v->cluster_size);
+    printf("\tnum_clusters = %llu\n", v->num_clusters);
+    print_bitmap(bmbuf, num, global_bm_bitnum_to_offset, v);
+    free_aligned(bmbuf);
+}
+
+void print_dir_node(void *buf)
+{
+    int i;
+    ocfs_dir_node * d = (ocfs_dir_node *)buf;
+
+    print_disk_lock(&d->disk_lock);
+    printf("\talloc_file_off = %llu\n", d->alloc_file_off);
+    printf("\talloc_node = %u\n", d->alloc_node);
+    printf("\tfree_node_ptr = ");
+    print_node_pointer(d->free_node_ptr);
+    printf("\tnode_disk_off = ");
+    print_node_pointer(d->node_disk_off);
+    printf("\tnext_node_ptr = ");
+    print_node_pointer(d->next_node_ptr);
+    printf("\tindx_node_ptr = ");
+    print_node_pointer(d->indx_node_ptr);
+    printf("\tnext_del_ent_node = ");
+    print_node_pointer(d->next_del_ent_node);
+    printf("\thead_del_ent_node = ");
+    print_node_pointer(d->head_del_ent_node);
+    printf("\tfirst_del = %d\n", d->first_del);
+    printf("\tnum_del = %d\n", d->num_del);
+    printf("\tnum_ents = %d\n", d->num_ents);
+    printf("\tdepth = %d\n", d->depth);
+    printf("\tnum_ent_used = %d\n", d->num_ent_used);
+    printf("\tdir_node_flags = %s\n",
+	   d->
+	   dir_node_flags & DIR_NODE_FLAG_ROOT ? "DIR_NODE_FLAG_ROOT" : "");
+    printf("\tsync_flags = ");
+    print_synch_flags(d->sync_flags);
+    printf("\tindex_dirty = %s\n", d->index_dirty ? "true" : "false");
+    printf("\tbad_off = %d\n", d->bad_off);
+
+    printf("\tindex = ");
+    for (i = 0; i < 256; i++)
+    {
+	if (i % 16 == 0 && i != 0)
+	    printf("\n\t\t");
+	printf("%3u ", d->index[i]);
+    }
+    printf("\n");
+}
+
+void print_file_entry(void *buf)
+{
+    ocfs_file_entry * fe = (ocfs_file_entry *)buf;
+    char fname[OCFS_MAX_FILENAME_LENGTH + 1];
+    int i;
+    ocfs_alloc_ext *ext;
+
+    strncpy(fname, fe->filename, OCFS_MAX_FILENAME_LENGTH);
+    fname[OCFS_MAX_FILENAME_LENGTH] = '\0';
+    print_disk_lock(&fe->disk_lock);
+    printf("\tlocal_ext = %s\n", fe->local_ext ? "true" : "false");
+    printf("\tgranularity = %d\n", fe->granularity);
+    printf("\tfilename = %s\n", fname);
+    printf("\tfilename_len = %d\n", fe->filename_len);
+    if (args.twoFourbyte)
+    	printf("\tfile_size = %u.%u\n", HILO(fe->file_size));
+    else
+    	printf("\tfile_size = %llu\n", fe->file_size);
+    if (args.twoFourbyte)
+        printf("\talloc_size = %u.%u\n", HILO(fe->alloc_size));
+    else
+        printf("\talloc_size = %llu\n", fe->alloc_size);
+    printf("\tattribs = ");
+    print_file_attributes((__u32) fe->attribs);
+    printf("\tprot_bits = ");
+    print_protection_bits((__u32) fe->prot_bits);
+    printf("\tuid = %d\n", fe->uid);
+    printf("\tgid = %d\n", fe->gid);
+    printf("\tcreate_time = ");
+    print_time(&(fe->create_time));
+    printf("\tmodify_time = ");
+    print_time(&(fe->modify_time));
+    printf("\tdir_node_ptr = ");
+    print_node_pointer(fe->dir_node_ptr);
+    printf("\tthis_sector = ");
+    print_node_pointer(fe->this_sector);
+    printf("\tlast_ext_ptr = ");
+    print_node_pointer(fe->last_ext_ptr);
+    printf("\tsync_flags = ");
+    print_synch_flags(fe->sync_flags);
+    printf("\tlink_cnt = %u\n", fe->link_cnt);
+    printf("\tnext_del = %d\n", fe->next_del);
+    printf("\tnext_free_ext = %u\n", fe->next_free_ext);
+
+    for (i = 0; i < OCFS_MAX_FILE_ENTRY_EXTENTS; i++)
+    {
+	ext = &(fe->extents[i]);
+	if (args.twoFourbyte) {
+	    printf("\textent[%d].file_off = %u.%u\n", i, HILO(ext->file_off));
+	    printf("\textent[%d].num_bytes = %u.%u\n", i, HILO(ext->num_bytes));
+	    printf("\textent[%d].disk_off = %u.%u\n", i, HILO(ext->disk_off));
+	} else {
+	    printf("\textent[%d].file_off = %llu\n", i, ext->file_off);
+	    printf("\textent[%d].num_bytes = %llu\n", i, ext->num_bytes);
+	    printf("\textent[%d].disk_off = %llu\n", i, ext->disk_off);
+	}
+    }
+
+    printf("\n");
+}
+
+void print_extent_ex(void *buf)
+{
+	print_extent(buf, 1, args.twoFourbyte);
+}
+
+void print_extent(void *buf, int twolongs, bool prev_ptr_error)
+{
+    ocfs_extent_group * exthdr = (ocfs_extent_group *)buf;
+    char sig[10];
+    int i;
+    __u64 len;
+    char err[200];
+    ocfs_alloc_ext *ext;
+
+#define ERROR_STR	"<========== ERROR"
+
+    strncpy(sig, exthdr->signature, sizeof(sig));
+    printf("\tsignature = %s\n", sig);
+    printf("\tnext_free_ext = %d\n", exthdr->next_free_ext);
+    printf("\tcurr_sect = %u\n", exthdr->curr_sect);
+    printf("\tmax_sects = %u\n", exthdr->max_sects);
+    printf("\ttype = %u\n", exthdr->type);
+    printf("\tgranularity = %d\n", exthdr->granularity);
+    printf("\talloc_node = %u\n", exthdr->alloc_node);
+
+    *err = '\0';
+    if (prev_ptr_error)
+	strcpy(err, ERROR_STR);
+
+    if (twolongs) {
+	printf("\tthis_ext = %u.%u\n", HILO(exthdr->this_ext));
+	printf("\tnext_data_ext = %u.%u\n", HILO(exthdr->next_data_ext));
+	printf("\talloc_file_off = %u.%u\n", HILO(exthdr->alloc_file_off));
+	printf("\tlast_ext_ptr = %u.%u\n", HILO(exthdr->last_ext_ptr));
+	printf("\tup_hdr_node_ptr = %u.%u %s\n", HILO(exthdr->up_hdr_node_ptr), err);
+    } else {
+	printf("\tthis_ext = %llu\n", exthdr->this_ext);
+	printf("\tnext_data_ext = %llu\n", exthdr->next_data_ext);
+	printf("\talloc_file_off = %llu\n", exthdr->alloc_file_off);
+	printf("\tlast_ext_ptr = %llu\n", exthdr->last_ext_ptr);
+	printf("\tup_hdr_node_ptr = %llu %s\n", exthdr->up_hdr_node_ptr, err);
+    }
+
+    len = exthdr->extents[0].file_off;
+
+    for (i = 0; i < OCFS_MAX_DATA_EXTENTS; i++) {
+	ext = &(exthdr->extents[i]);
+	if (ext->file_off == 0)
+		len = 0;
+	*err = '\0';
+        if (len != ext->file_off)
+		sprintf(err, "%s(%llu, %llu)", ERROR_STR, len, len - ext->file_off);
+	if (twolongs) {
+		printf("\textent[%d].file_off = %u.%u %s\n", i, HILO(ext->file_off), err);
+		printf("\textent[%d].num_bytes = %u.%u\n", i, HILO(ext->num_bytes));
+		printf("\textent[%d].disk_off = %u.%u\n", i, HILO(ext->disk_off));
+	} else {
+		printf("\textent[%d].file_off = %llu %s\n", i, ext->file_off, err);
+		printf("\textent[%d].num_bytes = %llu\n", i, ext->num_bytes);
+		printf("\textent[%d].disk_off = %llu\n", i, ext->disk_off);
+	}
+	len += ext->num_bytes;
+    }
+
+    printf("\n");
+}
+
+void print_vote_sector(void *buf)
+{
+    ocfs_vote * vote = (ocfs_vote *)buf;
+    printf("\tseq_num = %llu\n", vote->vote_seq_num);
+    printf("\tdir_ent = %llu\n", vote->dir_ent);
+    printf("\topen_handle = %s\n", vote->open_handle ? "Yes" : "No");
+    {
+	int j;
+
+	for (j = 0; j < MAX_NODES; j++)
+	{
+	    if (args.voteNodes[j])
+	    {
+		printf("\tVote%d = ", j);
+		print_vote_type(vote->vote[j]);
+	    }
+	}
+    }
+    printf("\n");
+}
+
+void print_publish_sector(void *buf)
+{
+    ocfs_publish * pub = (ocfs_publish *)buf;
+    printf("\ttime = ");
+    printf("%u.%u\n", HI(pub->time), LO(pub->time));
+    printf("\tvote = %s\n", pub->vote ? "Yes" : "No");
+    printf("\tdirty = %s\n", pub->dirty ? "Yes" : "No");
+    printf("\tvote_type = ");
+    print_publish_flags(pub->vote_type);
+    printf("\tvote_map = ");
+    print___u64_as_bitmap(pub->vote_map);
+    printf("\tseq_num = %llu\n", pub->publ_seq_num);
+    printf("\tdir_ent = %llu\n", pub->dir_ent);
+    {
+	int j;
+
+	printf("\thbm = ");
+	for (j = 0; j < MAX_NODES; j++)
+	{
+	    if (args.publishNodes[j])
+		printf("%u ", pub->hbm[j]);
+	}
+	printf("\n");
+    }
+    printf("\n");
+}
+
+void print_cdsl_offsets(void *buf)
+{
+    __u64 * off = (__u64 *)buf;
+    int i;
+
+    for (i = 0; i < 32; i++)
+    {
+	printf("\tOffset[%d] = %llu\n", i, off[i]);
+    }
+}
+
+void print_disk_lock(void *buf)
+{
+    ocfs_disk_lock * l = (ocfs_disk_lock *)buf;
+
+    printf("\tcurr_master = ");
+    if (l->curr_master == -1)
+	printf("INVALID_MASTER\n");
+    else
+	printf("%d\n", l->curr_master);
+    printf("\tfile_lock = ");
+    print_lock_type(l->file_lock);
+    printf("\toin_node_map = ");
+    print___u64_as_bitmap(l->oin_node_map);
+    printf("\tseq_num = %llu\n", l->dlock_seq_num);
+}
+
+int ocfs_find_clear_bits (ocfs_alloc_bm * bitmap, __u32 numBits, __u32 offset, __u32 sysonly);
+
+void print_system_file(int fd, ocfs_vol_disk_hdr * v, int fileid)
+{
+    ocfs_super *vcb = NULL;
+    void *buf = NULL;
+    int nodenum, size;
+    __u64 diskoff; 
+    int type = OCFS_INVALID_SYSFILE;
+    ocfs_file_entry *fe = NULL;
+    char *desc;
+    __u64 fileSize, allocSize;
+    int status;
+
+    /* find the physical disk offset */
+    diskoff = (__u64) (fileid * 512) + v->internal_off;
+   
+    type = OCFS_FILE_NUM_TO_SYSFILE_TYPE(fileid);
+    switch (type)
+    {
+        case OCFS_VOL_MD_SYSFILE:
+            desc = "vol_metadata";
+            nodenum = fileid - OCFS_FILE_VOL_META_DATA;
+            break;
+        case OCFS_VOL_MD_LOG_SYSFILE:
+            desc = "vol_metadata_log";
+            nodenum = fileid - OCFS_FILE_VOL_LOG_FILE;
+            break;
+        case OCFS_DIR_SYSFILE:
+            desc = "dir_alloc";
+            nodenum = fileid - OCFS_FILE_DIR_ALLOC;
+            break;
+        case OCFS_DIR_BM_SYSFILE:
+            desc = "dir_alloc_bitmap";
+            nodenum = fileid - OCFS_FILE_DIR_ALLOC_BITMAP;
+            break;
+        case OCFS_FILE_EXTENT_SYSFILE:
+            desc = "file_extent";
+            nodenum = fileid - OCFS_FILE_FILE_ALLOC;
+            break;
+        case OCFS_FILE_EXTENT_BM_SYSFILE:
+            desc = "file_extent_bitmap";
+            nodenum = fileid - OCFS_FILE_FILE_ALLOC_BITMAP;
+            break;
+        case OCFS_RECOVER_LOG_SYSFILE:
+            desc = "recover_log";
+            nodenum = fileid - LOG_FILE_BASE_ID;
+            break;
+        case OCFS_CLEANUP_LOG_SYSFILE:
+            desc = "cleanup_log";
+            nodenum = fileid - CLEANUP_FILE_BASE_ID;
+            break;
+        default:
+	    printf("error!!!!!  bad system file number!\n");
+            return;
+    }
+
+    vcb = get_fake_vcb(fd, v, nodenum);
+    printf("%s_%d:\n", desc, nodenum);
+    printf("\tfile_number = %d\n", fileid);
+    printf("\tdisk_offset = %llu\n", diskoff);
+    if (!ocfs_force_get_file_entry(vcb, &fe, diskoff, true))
+    {   
+        print_file_entry(fe);
+        ocfs_release_file_entry(fe);
+    }
+
+    status = ocfs_get_system_file_size(vcb, fileid, &fileSize, &allocSize);
+    if (status >= 0)
+    {
+        printf("\tfile_size = %d\n", fileSize);
+        printf("\talloc_size = %d\n", allocSize);
+
+        if (type==OCFS_DIR_BM_SYSFILE || type==OCFS_FILE_EXTENT_BM_SYSFILE)
+        {
+	    size = OCFS_ALIGN(allocSize, 512);
+	    buf = (void *) malloc_aligned(size);
+            if (allocSize)
+            {
+	        status = ocfs_read_system_file(vcb, fileid, buf, allocSize, (__u64)0);
+	        if (status >= 0)
+	        {
+		    ocfs_alloc_bm bm;
+		    int freebits, firstclear;
+    
+		    ocfs_initialize_bitmap(&bm, (__u32 *) buf, (__u32) (fileSize * 8));
+		    freebits = ocfs_count_bits(&bm);
+		    firstclear = ocfs_find_clear_bits(&bm, 1, 0, 0);
+    
+		    printf("\tTotalBits = %u\n", ((__u32) fileSize * 8));
+		    printf("\tFreeBits = %u\n", freebits);
+		    printf("\tUsedBits = %u\n", ((__u32) fileSize * 8) - freebits);
+		    printf("\tFirstClearBit = %u\n", firstclear);
+	        }
+            }
+        }
+        /* two types of log files */
+        else if (type==OCFS_CLEANUP_LOG_SYSFILE || type==OCFS_RECOVER_LOG_SYSFILE)
+        {
+	    ocfs_log_record *lr;
+	    ocfs_cleanup_record *cr;
+	    int st;
+            __u64 logsize;
+    
+	    if (fileid < CLEANUP_FILE_BASE_ID)
+	    {
+	        /* LOG_FILE */
+	        nodenum = fileid - LOG_FILE_BASE_ID;
+	        logsize = 512;
+	    }
+	    else
+	    {
+	        /* CLEANUP_FILE */
+	        nodenum = fileid - CLEANUP_FILE_BASE_ID;
+	        logsize = sizeof(ocfs_cleanup_record);
+	        logsize = OCFS_ALIGN(logsize, 512);
+	    }
+    
+	    vcb = get_fake_vcb(fd, v, nodenum);
+	    buf = malloc_aligned(logsize);
+	    memset(buf, 0, logsize);
+            if (allocSize)
+            {
+	        st = ocfs_read_system_file(vcb, (__u32) fileid, buf, logsize, (__u64)0);
+    
+	        if (type == OCFS_RECOVER_LOG_SYSFILE)
+	        {
+	            lr = (ocfs_log_record *) buf;
+	            printf("\tlog_id = %llu\n", lr->log_id);
+	            printf("\tlog_type = ");
+	            print_log_type(lr->log_type);
+	            print_record((void *) &(lr->rec), lr->log_type);
+	        }
+	        else // if (type == OCFS_CLEANUP_LOG_SYSFILE)
+	        {
+	            cr = (ocfs_cleanup_record *) buf;
+	            printf("\tlog_id = %llu\n", cr->log_id);
+	            printf("\tlog_type = ");
+	            print_log_type(cr->log_type);
+	            print_record((void *) &(cr->rec), cr->log_type);
+	        }
+            }
+        }
+        else
+        {
+        }
+    }
+
+    if (buf != NULL)
+	free_aligned(buf);
+    if (vcb != NULL)
+	free(vcb);
+}
+
+
+void print_file_data(int fd, ocfs_file_entry * fe)
+{
+    char buf[101];
+
+    if (fe->local_ext && fe->extents[0].disk_off != 0)
+    {
+	myseek64(fd, fe->extents[0].disk_off, SEEK_SET);
+	read(fd, buf, 100);
+	buf[100] = '\0';
+	printf("\tFileData = %s\n", buf);
+    }
+}
+
+void handle_one_file_entry(int fd, ocfs_file_entry *fe, void *buf)
+{
+    const char *parent = (const char *)buf;
+
+    printf("\tFile%d = %s%s%s\n", filenum++, parent, fe->filename,
+        fe->attribs & OCFS_ATTRIB_DIRECTORY ? "/" : "");
+    if (fe->attribs & OCFS_ATTRIB_DIRECTORY)
+    {
+        if (fe->extents[0].disk_off)
+        {
+            char *newparent = (char *) malloc(strlen(parent) + strlen(fe->filename) + 2);
+            sprintf(newparent, "%s%s/", parent, fe->filename);
+            walk_dir_nodes(fd, fe->extents[0].disk_off, newparent, NULL);
+            free(newparent);
+        }
+    }
+}
+
+/* helper functions for pretty-printing various flags */
+
+void print_node_pointer(__u64 ptr)
+{
+    if (ptr == INVALID_NODE_POINTER)
+	printf("INVALID_NODE_POINTER\n");
+    else {
+        if (args.twoFourbyte)
+	    printf("%u.%u\n", HILO(ptr));
+	else
+	    printf("%llu\n", ptr);
+    }
+}
+
+void print___u64_as_bitmap(__u64 x)
+{
+    int pos = 0;
+
+    while (pos < 32)
+    {
+	printf("%d", (x & (1 << pos)) ? 1 : 0);
+	pos++;
+    }
+    printf("\n");
+}
+
+void print_time(__u64 * sec)
+{
+    printf("%s", ctime((const time_t *) sec));
+}
+
+
+void print_lock_type(__u8 lock)
+{
+    if (lock == OCFS_DLM_NO_LOCK)
+        printf("OCFS_DLM_NO_LOCK\n");
+    else if (lock == OCFS_DLM_EXCLUSIVE_LOCK)
+        printf("OCFS_DLM_EXCLUSIVE_LOCK\n");
+    else if (lock == OCFS_DLM_SHARED_LOCK)
+        printf("OCFS_DLM_SHARED_LOCK\n");
+    else if (lock == OCFS_DLM_ENABLE_CACHE_LOCK)
+        printf("OCFS_DLM_ENABLE_CACHE_LOCK\n");
+    else
+        printf("UNKNOWN LOCK TYPE\n");
+}
+
+void print_file_attributes(__u32 attribs)
+{
+    if (attribs & OCFS_ATTRIB_DIRECTORY)
+	printf("OCFS_ATTRIB_DIRECTORY ");
+    if (attribs & OCFS_ATTRIB_FILE_CDSL)
+	printf("OCFS_ATTRIB_FILE_CDSL ");
+    if (attribs & OCFS_ATTRIB_CHAR)
+	printf("OCFS_ATTRIB_CHAR ");
+    if (attribs & OCFS_ATTRIB_BLOCK)
+	printf("OCFS_ATTRIB_BLOCK ");
+    if (attribs & OCFS_ATTRIB_REG)
+	printf("OCFS_ATTRIB_REG ");
+    if (attribs & OCFS_ATTRIB_FIFO)
+	printf("OCFS_ATTRIB_FIFO ");
+    if (attribs & OCFS_ATTRIB_SYMLINK)
+	printf("OCFS_ATTRIB_SYMLINK ");
+    if (attribs & OCFS_ATTRIB_SOCKET)
+	printf("OCFS_ATTRIB_SOCKET ");
+
+    printf("\n");
+}
+
+void print_vote_type(int type)
+{
+    if (type & FLAG_VOTE_NODE)
+	printf("FLAG_VOTE_NODE ");
+    if (type & FLAG_VOTE_OIN_UPDATED)
+	printf("FLAG_VOTE_OIN_UPDATED ");
+    if (type & FLAG_VOTE_OIN_ALREADY_INUSE)
+	printf("FLAG_VOTE_OIN_ALREADY_INUSE ");
+    if (type & FLAG_VOTE_UPDATE_RETRY)
+	printf("FLAG_VOTE_UPDATE_RETRY ");
+    if (type & FLAG_VOTE_FILE_DEL)
+	printf("FLAG_VOTE_FILE_DEL ");
+
+    printf("(0x%08x)", type);
+
+    printf("\n");
+}
+
+void print_log_type(int type)
+{
+    if (type == LOG_TYPE_DISK_ALLOC)
+        printf("LOG_TYPE_DISK_ALLOC\n");
+    else if (type == LOG_TYPE_DIR_NODE)
+        printf("LOG_TYPE_DIR_NODE\n");
+    else if (type == LOG_TYPE_RECOVERY)
+        printf("LOG_TYPE_RECOVERY\n");
+    else if (type == LOG_CLEANUP_LOCK)
+        printf("LOG_CLEANUP_LOCK\n");
+    else if (type == LOG_TYPE_TRANS_START)
+        printf("LOG_TYPE_TRANS_START\n");
+    else if (type == LOG_TYPE_TRANS_END)
+        printf("LOG_TYPE_TRANS_END\n");
+    else if (type == LOG_RELEASE_BDCAST_LOCK)
+        printf("LOG_RELEASE_BDCAST_LOCK\n");
+    else if (type == LOG_DELETE_ENTRY)
+        printf("LOG_DELETE_ENTRY\n");
+    else if (type == LOG_MARK_DELETE_ENTRY)
+        printf("LOG_MARK_DELETE_ENTRY\n");
+    else if (type == LOG_FREE_BITMAP)
+        printf("LOG_FREE_BITMAP\n");
+    else if (type == LOG_UPDATE_EXTENT)
+        printf("LOG_UPDATE_EXTENT\n");
+    else if (type == LOG_DELETE_NEW_ENTRY)
+        printf("LOG_DELETE_NEW_ENTRY\n");
+    else
+        printf("unknown log type (%d)\n", type);
+}
+
+void print_alloc_log(ocfs_alloc_log * rec)
+{
+    printf("\tlength = %llu\n", rec->length);
+    printf("\tfile_off = %llu\n", rec->file_off);
+    printf("\ttype = %u\n", rec->type);
+    printf("\tnode_num = %u\n", rec->node_num);
+}
+
+void print_dir_log(ocfs_dir_log * rec)
+{
+    printf("\torig_off = %llu\n", rec->orig_off);
+    printf("\tsaved_off = %llu\n", rec->saved_off);
+    printf("\tlength = %llu\n", rec->length);
+}
+
+void print_recovery_log(ocfs_recovery_log * rec)
+{
+    printf("\tnode_num = %llu\n", rec->node_num);
+}
+
+void print_lock_log(ocfs_lock_log * rec)
+{
+    int i;
+
+    printf("\tnum_lock_upds = %u\n", rec->num_lock_upds);
+    for (i = 0; i < rec->num_lock_upds && i < LOCK_UPDATE_LOG_SIZE; i++)
+    {
+	printf("\torig_off[%d] = %llu\n", i, rec->lock_upd[i].orig_off);
+	printf("\tnew_off[%d] = %llu\n", i, rec->lock_upd[i].new_off);
+    }
+}
+void print_bcast_rel_log(ocfs_bcast_rel_log * rec)
+{
+    printf("\tlock_id = %llu\n", rec->lock_id);
+}
+
+void print_delete_log(ocfs_delete_log * rec)
+{
+    printf("\tnode_num = %llu\n", rec->node_num);
+    printf("\tent_del = %llu\n", rec->ent_del);
+    printf("\tparent_dirnode_off = %llu\n", rec->parent_dirnode_off);
+    printf("\tflags = %u\n", rec->flags);
+}
+
+void print_free_log(ocfs_free_log * rec)
+{
+    int i;
+
+    printf("\tnum_free_upds = %u\n", rec->num_free_upds);
+    for (i = 0; i < rec->num_free_upds && i < FREE_LOG_SIZE; i++)
+    {
+	printf("\tlength = %llu\n", rec->free_bitmap[i].length);
+	printf("\tfile_off = %llu\n", rec->free_bitmap[i].file_off);
+	printf("\ttype = %u\n", rec->free_bitmap[i].type);
+	printf("\tnode_num = %u\n", rec->free_bitmap[i].node_num);
+    }
+}
+void print_extent_rec(ocfs_free_extent_log * rec)
+{
+    printf("\tindex = %u\n", rec->index);
+    printf("\tdisk_off = %llu\n", rec->disk_off);
+}
+
+void print_record(void *rec, int type)
+{
+    switch (type)
+    {
+	case LOG_TYPE_DISK_ALLOC:
+	    print_alloc_log((ocfs_alloc_log *) rec);
+	    break;
+	case LOG_TYPE_DIR_NODE:
+	    print_dir_log((ocfs_dir_log *) rec);
+	    break;
+	case LOG_TYPE_RECOVERY:
+	    print_recovery_log((ocfs_recovery_log *) rec);
+	    break;
+	case LOG_CLEANUP_LOCK:
+	    print_lock_log((ocfs_lock_log *) rec);
+	    break;
+	case LOG_RELEASE_BDCAST_LOCK:
+	    print_bcast_rel_log((ocfs_bcast_rel_log *) rec);
+	    break;
+	case LOG_DELETE_ENTRY:
+	case LOG_MARK_DELETE_ENTRY:
+	    print_delete_log((ocfs_delete_log *) rec);
+	    break;
+	case LOG_FREE_BITMAP:
+	    print_free_log((ocfs_free_log *) rec);
+	    break;
+	case LOG_UPDATE_EXTENT:
+	    print_extent_rec((ocfs_free_extent_log *) rec);
+	    break;
+
+	case LOG_TYPE_TRANS_START:
+	case LOG_TYPE_TRANS_END:
+	default:
+	    /* print nothing */
+	    break;
+    }
+}
+
+void print_synch_flags(int flags)
+{
+    if (flags == 0)
+    {
+	printf("OCFS_SYNC_FLAG_DELETED\n");
+	return;
+    }
+    if (flags & OCFS_SYNC_FLAG_VALID)
+	printf("OCFS_SYNC_FLAG_VALID ");
+    if (flags & OCFS_SYNC_FLAG_CHANGE)
+	printf("OCFS_SYNC_FLAG_CHANGE ");
+    if (flags & OCFS_SYNC_FLAG_MARK_FOR_DELETION)
+	printf("OCFS_SYNC_FLAG_MARK_FOR_DELETION ");
+    if (flags & OCFS_SYNC_FLAG_NAME_DELETED)
+	printf("OCFS_SYNC_FLAG_NAME_DELETED ");
+
+    printf("\n");
+}
+
+void print_publish_flags(int type)
+{
+    if (type & FLAG_FILE_CREATE)
+	printf("FLAG_FILE_CREATE ");
+    if (type & FLAG_FILE_EXTEND)
+	printf("FLAG_FILE_EXTEND ");
+    if (type & FLAG_FILE_DELETE)
+	printf("FLAG_FILE_DELETE ");
+    if (type & FLAG_FILE_RENAME)
+	printf("FLAG_FILE_RENAME ");
+    if (type & FLAG_FILE_UPDATE)
+	printf("FLAG_FILE_UPDATE ");
+    if (type & FLAG_FILE_CREATE_DIR)
+	printf("FLAG_FILE_CREATE_DIR ");
+    if (type & FLAG_FILE_UPDATE_OIN)
+	printf("FLAG_FILE_UPDATE_OIN ");
+    if (type & FLAG_FILE_RELEASE_MASTER)
+	printf("FLAG_FILE_RELEASE_MASTER ");
+    if (type & FLAG_CHANGE_MASTER)
+	printf("FLAG_CHANGE_MASTER ");
+    if (type & FLAG_ADD_OIN_MAP)
+	printf("FLAG_ADD_OIN_MAP ");
+    if (type & FLAG_DIR)
+	printf("FLAG_DIR ");
+    if (type & FLAG_DEL_NAME)
+	printf("FLAG_DEL_NAME ");
+    if (type & FLAG_RESET_VALID)
+	printf("FLAG_RESET_VALID ");
+    if (type & FLAG_FILE_RELEASE_CACHE)
+	printf("FLAG_FILE_RELEASE_CACHE ");
+    if (type & FLAG_FILE_CREATE_CDSL)
+	printf("FLAG_FILE_CREATE_CDSL ");
+    if (type & FLAG_FILE_DELETE_CDSL)
+	printf("FLAG_FILE_DELETE_CDSL ");
+    if (type & FLAG_FILE_CHANGE_TO_CDSL)
+	printf("FLAG_FILE_CHANGE_TO_CDSL ");
+    if (type & FLAG_FILE_TRUNCATE)
+	printf("FLAG_FILE_TRUNCATE ");
+
+    printf("(0x%08x)", type);
+
+    printf("\n");
+}
+
+void print_protection_bits(__u32 prot)
+{
+    if (prot & S_ISUID)
+	printf("S_ISUID ");
+    if (prot & S_ISGID)
+	printf("S_ISGID ");
+    if (prot & S_ISVTX)
+	printf("S_ISVTX ");
+    if (prot & S_IRUSR)
+	printf("S_IRUSR ");
+    if (prot & S_IWUSR)
+	printf("S_IWUSR ");
+    if (prot & S_IXUSR)
+	printf("S_IXUSR ");
+    if (prot & S_IRGRP)
+	printf("S_IRGRP ");
+    if (prot & S_IWGRP)
+	printf("S_IWGRP ");
+    if (prot & S_IXGRP)
+	printf("S_IXGRP ");
+    if (prot & S_IROTH)
+	printf("S_IROTH ");
+    if (prot & S_IWOTH)
+	printf("S_IWOTH ");
+    if (prot & S_IXOTH)
+	printf("S_IXOTH ");
+
+    printf("\n");
+}
+
+

Added: trunk/debugocfs/test.c
===================================================================
--- trunk/debugocfs/test.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/debugocfs/test.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,87 @@
+/*
+ * test.c
+ *
+ * 
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Kurt Hackel
+ *
+ * gcc -o test test.c `pkg-config --cflags --libs glib` -ldebugocfs -locfsusr -L. -L../../ocfs2/ -g
+ */
+
+#include <glib.h>
+#include <stdio.h>
+#include "libdebugocfs.h"
+
+int main(int argc, char **argv)
+{
+    int ret, i;
+    GArray *arr;
+
+    if (argc < 3)
+    {
+	fprintf(stderr, "usage: test /dev/path /dir/to/read/\n");
+	exit(1);
+    }
+
+    ret = libocfs_readdir(argv[1], argv[2], TRUE, &arr);
+    printf("ret=%d arraysize=%d\n", ret, arr->len);
+    if (ret == 0)
+    {
+	for (i = 0; i < arr->len; i++)
+	{
+	    libocfs_stat *x;
+
+	    x = (libocfs_stat *) (arr->data + (sizeof(libocfs_stat) * i));
+	    printf("name=%s size=%llu\n", x->name, x->size);
+	}
+    }
+    g_array_free(arr, TRUE);
+
+    ret = libocfs_get_node_map(argv[1], &arr);
+    printf("ret=%d arraysize=%d\n", ret, arr->len);
+
+    if (ret == 0)
+    {
+	for (i = 0; i < arr->len; i++)
+	{
+	    libocfs_node *x;
+
+	    x = (libocfs_node *) (arr->data + (sizeof(libocfs_node) * i));
+	    printf("name='%s' ip=%s slot=%d guid='%s'\n", x->name,
+		   x->addr, x->slot, x->guid);
+	}
+    }
+    g_array_free(arr, TRUE);
+
+
+
+}
+
+#if 0
+33 typedef struct _libocfs_node 34
+{
+    35 char name[MAX_NODE_NAME_LENGTH + 1];
+    36 int num_addrs;
+    37 char **addrs;		// array of char[16]
+    38 int slot;
+  39}
+libocfs_node;
+
+#endif

Added: trunk/format/Cscope.make
===================================================================
--- trunk/format/Cscope.make	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/format/Cscope.make	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,14 @@
+.PHONY: cscope
+cscope:
+	rm -f cscope.*
+	echo "-k" >> cscope.files
+	echo "-I $(TOPDIR)/ocfs2/Common/inc" >> cscope.files
+	echo "-I inc" >> cscope.files
+	find . -maxdepth 2 -name '*.c' -print >>cscope.files
+	find . -maxdepth 2 -name '*.h' -print >>cscope.files
+	find ../libocfs -maxdepth 2 -name '*.h' -print >>cscope.files
+	find ../../ocfs2/Common -maxdepth 2 -name ocfsheartbeat\* -print >>cscope.files
+	find $(TOPDIR)/ocfs2/Common/inc -maxdepth 2 -name 'ocfscom.h' -print >>cscope.files
+	find $(TOPDIR)/ocfs2/Common/inc -maxdepth 2 -name 'ocfsvol.h' -print >>cscope.files
+	find $(TOPDIR)/ocfs2/Common/inc -maxdepth 2 -name 'ocfstrace.h' -print >>cscope.files
+	cscope -b

Added: trunk/format/Makefile
===================================================================
--- trunk/format/Makefile	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/format/Makefile	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,57 @@
+TOPDIR = ..
+
+include $(TOPDIR)/Preamble.make
+
+WARNINGS = -Wall -Wstrict-prototypes -Wno-format -Wmissing-prototypes \
+           -Wmissing-declarations
+
+ifdef OCFS_DEBUG
+OPTS = -g
+endif
+
+CFLAGS = $(OPTS) -fno-strict-aliasing $(WARNINGS) -pthread
+
+SBIN_PROGRAMS = mkfs.ocfs mounted.ocfs resizeocfs
+
+INCLUDES = -I$(TOPDIR)/libocfs/Common/inc -I$(TOPDIR)/libocfs/Linux/inc -Iinc -I$(TOPDIR)/libocfs
+DEFINES = -DLINUX -DUSERSPACE_TOOL -DFORMAT_OCFS
+
+OPTIMIZE = -O2
+
+ifeq ($(OCFS_PROCESSOR),x86_64)
+  CFLAGS += -m64
+endif
+ifeq ($(OCFS_PROCESSOR),ia64)
+endif
+ifeq ($(OCFS_PROCESSOR),i686)
+  DEFINES += -D__ILP32__
+endif
+
+CFLAGS += $(OPTIMIZE)
+
+VERSION_FILES = format.c frmtport.c inc/format.h inc/frmtport.h mounted.c resize.c inc/resize.h
+VERSION_SRC = frmtport.c
+VERSION_PREFIX = OCFS
+
+DIST_RULES = dist-incdir
+
+MANS = mkfs.ocfs.1 resizeocfs.1
+
+DIST_FILES = $(VERSION_FILES) $(VERSION_SRC) mkfs.ocfs.1.in resizeocfs.1.in
+
+vpath ocfsheartbeat.c $(TOPDIR)/libocfs/Common
+
+
+mkfs.ocfs: format.o frmtport.o
+	$(LINK) -L$(TOPDIR)/libocfs -locfs
+
+mounted.ocfs: mounted.o frmtport.o
+	$(LINK) -L$(TOPDIR)/libocfs -locfs
+
+resizeocfs: resize.o frmtport.o
+	$(LINK) -L$(TOPDIR)/libocfs -locfs
+
+dist-incdir:
+	$(TOPDIR)/mkinstalldirs $(DIST_DIR)/inc
+
+include $(TOPDIR)/Postamble.make

Added: trunk/format/format.c
===================================================================
--- trunk/format/format.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/format/format.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,980 @@
+/*
+ * format.c
+ *
+ * ocfs format utility
+ *
+ * Copyright (C) 2002, 2004 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#include <format.h>
+#include <signal.h>
+
+bool in_data_blocks = false;
+bool format_intr = false;
+
+ocfs_options opts = {
+	.device = "",
+	.block_size = 0,
+	.clear_data_blocks = false,
+	.force_op = false,
+	.gid = 0,
+	.volume_label = "",
+	.mount_point = "",
+	.query_only = false,
+	.perms = 0755,
+	.quiet = false,
+	.uid = 0,
+	.print_progress = false,
+	.slot_num = OCFS_INVALID_NODE_NUM,
+	.device_size = 0 
+};
+
+__u64 sect_count = 0;
+__u64 format_size = 0;
+int rawminor = 0;
+char rawdev[FILE_NAME_SIZE];
+int file = 0;
+
+char *usage_string =
+"usage: mkfs.ocfs -b block-size [-C] [-F] [-g gid] [-h] -L volume-label\n"
+"                 -m mount-path [-n] [-p permissions] [-q] [-u uid] [-V] device\n\n"
+"	-b Block size in kilo bytes\n"
+"	-C Clear all data blocks\n"
+"	-F Force format existing OCFS volume\n"
+"	-g GID for the root directory\n"
+"	-h Help\n"
+"	-L Volume label\n"
+"	-m Path where this device will be mounted\n"
+"	-n Query only\n"
+"	-p Permissions for the root directory\n"
+"	-q Quiet execution\n"
+"	-u UID for the root directory\n"
+"	-V Print version and exit\n";
+
+
+/*
+ * main()
+ *
+ */
+int main(int argc, char **argv)
+{
+    ocfs_vol_disk_hdr *volhdr = NULL;
+    __u32 sect_size = OCFS_SECTOR_SIZE;
+    __u64 vol_size = 0;
+    char vol_id[MAX_VOL_ID_LENGTH];
+    __u64 offset;
+    __u64 publ_off = 0;
+    __u64 data_start_off = 0;
+    bool ocfs_vol = false;
+    __u32 nodemap = 0;
+    char *node_names[OCFS_MAXIMUM_NODES];
+
+    /* Set ctrl-c handler */
+    if (signal(SIGINT, HandleSignal) == SIG_ERR) {
+	    fprintf(stderr, "Could not set SIGINT\n");
+	    goto bail;
+    }
+
+    if (!(volhdr = (ocfs_vol_disk_hdr *) MemAlloc(sect_size)))
+	    goto bail;
+    else
+	    memset(volhdr, 0, sect_size);
+
+    /* Read the options */
+    if (!ReadOptions(argc, argv))
+	goto bail;
+
+    /* Validate the options */
+    if (!ValidateOptions())
+	goto bail;
+
+    /* Generate Volume ID */
+    if (!GenerateVolumeID(vol_id, sizeof(vol_id)))
+	goto bail;
+
+    /* Open the supplied disk */
+    if (!(file = OpenDisk(opts.device)))
+	goto bail;
+
+    /* Get the partition Information */
+    if (!(GetDiskGeometry(file, &vol_size, &sect_size)))
+	goto bail;
+
+    if (vol_size < OCFS_MIN_VOL_SIZE) {
+	fprintf(stderr, "Error: %s at %lluMB is smaller than %uMB.\n"
+		"Aborting.\n", opts.device, (vol_size/(1024*1024)),
+	       	(OCFS_MIN_VOL_SIZE/(1024*1024)));
+	    goto bail;
+    }
+
+    /* close and reopen after binding to raw */
+    safeclose(file);
+
+    /* bind device to raw */
+    if (bind_raw(opts.device, &rawminor, rawdev, sizeof(rawdev)))
+	goto bail;
+
+    /* Open the supplied disk */
+    if (!(file = OpenDisk(rawdev)))
+	goto bail;
+
+    /* Initialize the DiskHeader structure */
+    if (!(InitVolumeDiskHeader(volhdr, sect_size, vol_size, &data_start_off)))
+	goto bail;
+
+#ifdef DEBUG
+	ShowDiskHdrVals(volhdr);
+#endif
+
+     /* query_only option bails you here */
+    if (opts.query_only)
+	goto bail;
+
+    /* OCFS formatted disks will not be overwritten without the -f option */
+    if (!CheckForceFormat(file, &publ_off, &ocfs_vol, sect_size))
+	goto bail;
+
+    /* If valid ocfs volume, check for any heart beating node(s) */
+    if (ocfs_vol) {
+	if (!check_heart_beat(&file, rawdev, volhdr, &nodemap, sect_size))
+		goto bail;
+	if (nodemap) {
+		/* Exit as device is mounted on some node */
+		get_node_names(file, volhdr, node_names, sect_size);
+		printf("%s mounted on nodes:", opts.device);
+		print_node_names(node_names, nodemap);
+		printf("Aborting.\n");
+		goto bail;
+	}
+    }
+
+    if (opts.clear_data_blocks)
+	    format_size = (volhdr->device_size / sect_size) -
+		    		OCFS_NUM_END_SECTORS;
+    else
+	    format_size = CLEAR_DATA_BLOCK_SIZE + (data_start_off / sect_size);
+
+    /* Clear the Volume header in the first sector of the volume */
+    PRINT_PROGRESS();
+    PRINT_VERBOSE("Clearing volume header sectors...");
+    fflush(stdout);
+    offset = volhdr->start_off;
+    if (!ClearSectors(file, offset, 1, sect_size))
+	goto bail;
+
+    /* Write the Volume Label in the 2nd and 3rd sectors */
+    offset = volhdr->start_off + sect_size;
+    if (!WriteVolumeLabel(file, vol_id, sizeof(vol_id), offset, sect_size))
+	goto bail;
+
+    /* Clear sectors 4 to 8 */
+    offset = volhdr->start_off + (3 * sect_size);
+    if (!ClearSectors(file, offset, 5, sect_size))
+	goto bail;
+
+    sect_count += 8;
+    PRINT_VERBOSE("\rCleared volume header sectors                 \n");
+
+    /* Initialize Node config header */
+    PRINT_PROGRESS();
+    PRINT_VERBOSE("Clearing node config sectors...");
+    fflush(stdout);
+    offset = volhdr->node_cfg_off;
+    if (!InitNodeConfHdr(file, offset, sect_size))
+	goto bail;
+
+    /* Clear Node config info */
+    offset = volhdr->node_cfg_off + (2 * sect_size);
+    if (!ClearSectors(file, offset, OCFS_MAXIMUM_NODES, sect_size))
+	goto bail;
+
+    /* Clear NewConf */
+    offset = volhdr->node_cfg_off + volhdr->node_cfg_size;
+    if (!ClearSectors(file, offset, 4, sect_size))
+	goto bail;
+    fsync(file);
+
+    sect_count += OCFS_MAXIMUM_NODES + 6;
+    PRINT_VERBOSE("\rCleared node config sectors                 \n");
+
+    /* Clear Publish Sectors */
+    PRINT_PROGRESS();
+    PRINT_VERBOSE("Clearing publish sectors...");
+    fflush(stdout);
+    if (!ClearSectors(file, volhdr->publ_off, OCFS_MAXIMUM_NODES, sect_size))
+	goto bail;
+    fsync(file);
+
+    sect_count += OCFS_MAXIMUM_NODES;
+    PRINT_VERBOSE("\rCleared publish sectors                     \n");
+
+    /* Clear Vote Sectors */
+    PRINT_PROGRESS();
+    PRINT_VERBOSE("Clearing vote sectors...");
+    fflush(stdout);
+    if (!ClearSectors(file, volhdr->vote_off, OCFS_MAXIMUM_NODES, sect_size))
+	goto bail;
+    fsync(file);
+
+    sect_count += OCFS_MAXIMUM_NODES;
+    PRINT_VERBOSE("\rCleared vote sectors                        \n");
+
+    /* Clear the Bitmap */
+    PRINT_PROGRESS();
+    PRINT_VERBOSE("Clearing bitmap sectors...");
+    fflush(stdout);
+    if (!ClearBitmap(file, volhdr))
+	goto bail;
+    fsync(file);
+
+    sect_count += (OCFS_MAX_BITMAP_SIZE / sect_size);
+    PRINT_VERBOSE("\rCleared bitmap sectors                      \n");
+
+    /* Clear OCFS_NUM_FREE_SECTORS */
+    PRINT_PROGRESS();
+    fflush(stdout);
+    offset = volhdr->bitmap_off + OCFS_MAX_BITMAP_SIZE;
+    if (!ClearSectors(file, offset, OCFS_NUM_FREE_SECTORS, sect_size))
+	goto bail;
+    fsync(file);
+
+    sect_count += OCFS_NUM_FREE_SECTORS;
+
+    /* Clear the data blocks */
+    if (!ClearDataBlocks(file, volhdr, sect_size))
+	goto bail;
+    fsync(file);
+
+    /* Write volume header */
+    PRINT_VERBOSE("Writing volume header...");
+    fflush(stdout);
+    sigblock(sigmask(SIGINT));   /* blocking ctrl-c */
+    offset = volhdr->start_off;
+    if (!WriteVolumeHdr(file, volhdr, offset, sect_size))
+	goto bail;
+
+    sect_count = format_size;
+    PRINT_PROGRESS();
+    PRINT_VERBOSE("\rWrote volume header                         \n");
+    fflush(stdout);
+
+  bail:
+    safefree(volhdr);
+    safeclose(file);
+    unbind_raw(rawminor, rawdev);
+    return 0;
+}				/* main */
+
+
+/*
+ * CheckForceFormat()
+ *
+ */
+int CheckForceFormat(int file, __u64 *publ_off, bool *ocfs_vol, __u32 sect_size)
+{
+	__u32 len;
+	char *buf;
+	int ret = 0;
+	ocfs_vol_disk_hdr *volhdr = NULL;
+	char format;
+
+	len = sect_size;
+	if (!(buf = (char *) MemAlloc(len)))
+		goto bail;
+	else
+		memset(buf, 0, len);
+
+	/* Seek to 1st sector */
+	if (!SetSeek(file, 0))
+		goto bail;
+
+	/* Read the Information of first sector on disk */
+	if (!(Read(file, len, buf)))
+		goto bail;
+
+	volhdr = (ocfs_vol_disk_hdr *) buf;
+
+	if ((!memcmp(volhdr->signature, OCFS_VOLUME_SIGNATURE,
+		     strlen(OCFS_VOLUME_SIGNATURE)))) {
+		*ocfs_vol = true;
+    		*publ_off = volhdr->publ_off;
+	} else {
+		*ocfs_vol = false;
+		*publ_off = (__u64) 0;
+	}
+
+	/* Ensure forceformat flag is set to prevent overwriting */
+	if (*ocfs_vol) {
+		if (opts.force_op)
+			ret = 1;
+		else {
+			if (opts.print_progress) {
+				fprintf(stderr, "Error: Use -F to format "
+					"existing OCFS volume.\n");
+				goto bail;
+			}
+			printf("Format existing OCFS volume (y/N): ");
+			format = getchar();
+			if (format == 'y' || format == 'Y')
+				ret = 1;
+			else
+				printf("Aborting.\n");
+		}
+	} else
+		ret = 1;
+
+      bail:
+	safefree(buf);
+	return ret;
+}				/* CheckForceFormat */
+
+
+/*
+ * WriteVolumeHdr()
+ *
+ */
+int WriteVolumeHdr(int file, ocfs_vol_disk_hdr * volhdr, __u64 offset,
+		   __u32 sect_size)
+{
+    int ret = 0;
+
+    if (!SetSeek(file, offset))
+	goto bail;
+
+    if (!Write(file, sect_size, (void *) volhdr))
+	goto bail;
+
+    ret = 1;
+  bail:
+    return ret;
+}				/* WriteVolumeHdr */
+
+
+/*
+ * WriteVolumeLabel()
+ *
+ */
+int WriteVolumeLabel(int file, char *volid, __u32 volidlen, __u64 offset,
+		     __u32 sect_size)
+{
+    ocfs_vol_label *pLabel;
+    __u32 len;
+    char *buf;
+    int ret = 0;
+
+    len = 2 * sect_size;
+    if (!(buf = (char *) MemAlloc(len)))
+	goto bail;
+    else
+	memset(buf, 0, len);
+
+    /* Populate volume label */
+    InitVolumeLabel((ocfs_vol_label *) buf, sect_size, volid, volidlen);
+
+    /* Set the bitmap lock to invalid_master */
+    pLabel = (ocfs_vol_label *) (buf + sect_size);
+    pLabel->disk_lock.curr_master = -1;
+
+    if (!SetSeek(file, offset))
+	goto bail;
+
+    if (!Write(file, len, buf))
+	goto bail;
+
+    ret = 1;
+  bail:
+    safefree(buf);
+    return ret;
+}				/* WriteVolumeLabel */
+
+
+/*
+ * InitNodeConfHdr()
+ *
+ */
+int InitNodeConfHdr(int file, __u64 offset, __u32 sect_size)
+{
+    __u32 len;
+    char *buf;
+    int ret = 0;
+
+    len = 2 * sect_size;
+    if (!(buf = (char *) MemAlloc(len)))
+	goto bail;
+    else
+	memset(buf, 0, len);
+
+    /* Set node config header */
+    SetNodeConfigHeader((ocfs_node_config_hdr *) buf);
+
+    /* Set the File pointer to node config sector */
+    if (!SetSeek(file, offset))
+	goto bail;
+
+    if (!(Write(file, len, buf)))
+	goto bail;
+
+    ret = 1;
+  bail:
+    safefree(buf);
+    return ret;
+}				/* InitNodeConfHdr */
+
+
+/*
+ * ClearSectors()
+ *
+ */
+int ClearSectors(int file, __u64 strtoffset, __u32 noofsects, __u32 sect_size)
+{
+    __u32 len;
+    char *buf = NULL;
+    __u32 i;
+    int ret = 0;
+
+    len = sect_size;
+    if (!(buf = (char *) MemAlloc(len)))
+	goto bail;
+    else
+	memset(buf, 0, len);
+
+    if (!SetSeek(file, strtoffset))
+	goto bail;
+
+    for (i = 0; i < noofsects; ++i)
+    {
+	if (!Write(file, len, buf))
+	    goto bail;
+    }
+
+    ret = 1;
+  bail:
+    safefree(buf);
+    return ret;
+}				/* ClearSectors */
+
+
+/*
+ * ClearBitmap()
+ *
+ */
+int ClearBitmap(int file, ocfs_vol_disk_hdr * volhdr)
+{
+    __u32 len;
+    char *buf = NULL;
+    int ret = 0;
+
+    len = OCFS_MAX_BITMAP_SIZE;
+    if (!(buf = (char *) MemAlloc(len)))
+	goto bail;
+    else
+	memset(buf, 0, len);
+
+    /* Initialize the bitmap on disk */
+    if (!SetSeek(file, volhdr->bitmap_off))
+	goto bail;
+
+    if (!(Write(file, len, buf)))
+	goto bail;
+
+    ret = 1;
+  bail:
+    safefree(buf);
+    return ret;
+}				/* ClearBitmap */
+
+
+/*
+ * ClearDataBlocks()
+ *
+ */
+int ClearDataBlocks(int file, ocfs_vol_disk_hdr * volhdr, __u32 sect_size)
+{
+	__u64 blocks = 0;
+	__u64 bytes = 0;
+	__u64 len;
+	__u64 offset;
+	__u64 i;
+	char *buf = NULL;
+	int ret = 0;
+
+	len = CLEAR_DATA_BLOCK_SIZE * sect_size;
+	if (!(buf = (char *) MemAlloc(len)))
+		goto bail;
+	else
+		memset(buf, 0, len);
+
+	offset = volhdr->device_size - volhdr->data_start_off;
+	blocks = offset / len;
+	bytes = offset % len;
+
+	offset = volhdr->data_start_off;
+	if (!SetSeek(file, offset))
+		goto bail;
+
+	if (!opts.clear_data_blocks) {
+		PRINT_PROGRESS();
+		PRINT_VERBOSE("Clearing data block...");
+		fflush (stdout);
+		/* clear first 1M of data blocks */
+		if (!(Write(file, len, buf)))
+			goto bail;
+		fsync(file);
+		PRINT_VERBOSE("\rCleared data block              \n");
+		fflush (stdout);
+		sect_count += CLEAR_DATA_BLOCK_SIZE;
+		ret = 1;
+		goto bail;
+	}
+
+	if (blocks) {
+		in_data_blocks = true;
+		for (i = 0; i < blocks; i++, offset += len) {
+			PRINT_PROGRESS();
+			PRINT_VERBOSE("\rClearing data block %llu of %llu",
+				      i, blocks);
+			fflush(stdout);
+			if (!(Write(file, len, buf)))
+				goto bail;
+			if (!(i % 20))
+				fsync(file);
+			sect_count += CLEAR_DATA_BLOCK_SIZE;
+			if (format_intr)
+				break;
+		}
+	}
+
+	if (!format_intr && bytes) {
+		if (!(Write(file, bytes, buf)))
+			goto bail;
+	}
+
+	PRINT_PROGRESS();
+
+	if (format_intr)
+		printf("\nFormatting interrupted..... volume may "
+		       "not be usable                    \n");
+	else
+		PRINT_VERBOSE("\rCleared data blocks                         "
+			      "                 \n");
+	fflush(stdout);
+
+	ret = 1;
+      bail:
+	safefree(buf);
+	return ret;
+}				/* ClearDataBlocks */
+
+
+/*
+ * ReadOptions()
+ *
+ */
+int ReadOptions(int argc, char **argv)
+{
+	int i;
+	int ret = 1;
+
+	if (argc < 2) {
+		version(argv[0]);
+		usage();
+		ret = 0;
+		goto bail;
+	}
+
+	for (i = 1; i < argc && ret; i++) {
+		switch(*argv[i]) {
+		case '-':
+			switch(*++argv[i]) {
+			case 'b':	/* block size */
+				++i;
+				if (i < argc && argv[i])
+					opts.block_size = atoi(argv[i]);
+				else {
+					fprintf(stderr, "Invalid block size.\n"
+						"Aborting.\n");
+					ret = 0;
+				}
+				break;
+
+			case 'C':	/* clear all data blocks */
+				opts.clear_data_blocks = true;
+				break;
+
+			case 'F':	/* force format */
+				opts.force_op = true;
+				break;
+
+			case 'g':	/* gid */
+				++i;
+				if (i < argc && argv[i])
+					opts.gid = get_gid(argv[i]);
+				else {
+					fprintf(stderr, "Invalid group id.\n"
+						"Aborting.\n");
+					ret = 0;
+				}
+				break;
+
+			case 'L':	/* volume label */
+				++i;
+				if (i < argc && argv[i])
+					strncpy(opts.volume_label, argv[i],
+						MAX_VOL_LABEL_LEN);
+				else {
+					fprintf(stderr,"Invalid volume label.\n"
+						"Aborting.\n");
+					ret = 0;
+				}
+				break;
+
+			case 'h':       /* help */
+				version(argv[0]);
+				usage();
+				ret = 0;
+				break;
+
+			case 'm':	/* mount point */
+				++i;
+				if (i < argc && argv[i])
+					strncpy(opts.mount_point, argv[i],
+						FILE_NAME_SIZE);
+				else {
+					fprintf(stderr,"Invalid mount point.\n"
+						"Aborting.\n");
+					ret = 0;
+				}
+				break;
+
+			case 'n':	/* query */
+				opts.query_only = true;
+				break;
+
+			case 'p':	/* permissions */
+				++i;
+				if (i < argc && argv[i]) {
+					opts.perms = strtoul(argv[i],
+								  NULL, 8);
+					opts.perms &= 0007777;
+				} else {
+					fprintf(stderr,"Invalid permissions.\n"
+						"Aborting.\n");
+					ret = 0;
+				}
+				break;
+
+			case 'q':	/* quiet */
+				opts.quiet = true;
+				break;
+
+			case 'u':	/* uid */
+				++i;
+				if (i < argc && argv[i])
+					opts.uid = get_uid(argv[i]);
+				else {
+					fprintf(stderr,"Invalid user id.\n"
+						"Aborting.\n");
+					ret = 0;
+				}
+				break;
+
+			case 'V':	/* print version */
+				version(argv[0]);
+				ret = 0;
+				break;
+
+			case 'x':	/* used for debugocfs */
+				opts.print_progress = true;
+				break;
+
+			default:
+				ret = 0;
+				break;
+			}
+			break;
+
+		default:
+			strncpy(opts.device, argv[i], FILE_NAME_SIZE);
+			break;
+		}
+	}
+
+      bail:
+	return ret;
+}				/* ReadOptions */
+
+
+/*
+ * InitVolumeDiskHeader()
+ *
+ */
+int InitVolumeDiskHeader(ocfs_vol_disk_hdr *volhdr, __u32 sect_size, __u64 vol_size,
+			 __u64 * data_start_off)
+{
+    __u64 DataSize = 0;
+    __u64 num_blocks = 0;
+    __u32 VolHdrSize = 0;
+    __u32 NodeConfSize = 0;
+    __u32 NewConfSize = 0;
+    __u32 PublishSize = 0;
+    __u32 VoteSize = 0;
+    __u32 BitmapSize = 0;
+    __u64 BegFreeSize = 0;
+    __u64 EndFreeSize = 0;
+    __u32 tmpbitmap;
+    __u32 block_size = opts.block_size;
+    char *MountPoint = opts.mount_point;
+
+/*
+**                 node_cfg_off                  publ_off
+** start_off            |                            |
+**  |                   |              new_cfg_off   |
+**  |Sector    Sector   |                      |     |
+**  V  0         1-7    V                      V     V
+**  ----------------------------------------------------------------------- ...
+**  |       |  |  |  |  |   |                  |     |                    |
+**  |Volume |  |  |  |  | 2 |OCFS_MAXIMUM_NODES|  4  | OCFS_MAXIMUM_NODES |
+**  |Header | 1| 2| 3|  |sct|sectors           | sct | sectors            |
+**  |       |  |  |  |  |   |                  |     |                    |
+**  ----------------------------------------------------------------------- ...
+**          |  |  |  |   <--- node_cfg_size -->
+**          |  |  |  V
+**          V  |  |  Not Used(4,5,6,7)
+**   VolLabel+ |  V
+**    VOL_LOCK | NMMAP+
+**             V   NMLOCK
+**    BitMap Lock
+**
+**                  
+**                    bitmap_off
+** vote_off               |                                     data_start_off 
+**   |                    |                                              |
+**   V                    V                                              V
+** ..--------------------------------------------------------------------- ...
+**   |                    |                      |                       |
+**   | OCFS_MAXIMUM_NODES | OCFS_MAX_BITMAP_SIZE | OCFS_NUM_FREE_SECTORS |
+**   | sectors            | sectors              | sectors               |
+**   |                    |                      |                       |
+** ..--------------------------------------------------------------------- ...
+**
+**
+** If we define OCFS_MAX_DIRECTORY_ENTRIES to be 5000 files and keep 1024
+** sectors free. The total disk space required by Ocfs is appx. 3MB.
+*/
+
+    memset(volhdr, 0, sizeof(ocfs_vol_disk_hdr));
+
+    volhdr->minor_version = OCFS_MINOR_VERSION;
+    volhdr->major_version = OCFS_MAJOR_VERSION;
+
+    memcpy(volhdr->signature, OCFS_VOLUME_SIGNATURE,
+	   strlen(OCFS_VOLUME_SIGNATURE));
+    strncpy(volhdr->mount_point, MountPoint, MAX_MOUNT_POINT_LEN - 1);
+
+    volhdr->device_size = vol_size;
+    volhdr->start_off = 0;
+    volhdr->num_nodes = OCFS_MAXIMUM_NODES;
+    volhdr->root_size = 0;
+    volhdr->cluster_size = (block_size * 1024);
+
+    /* uid/gid/perms */
+    volhdr->uid = opts.uid;
+    volhdr->gid = opts.gid;
+    volhdr->prot_bits = opts.perms;
+    volhdr->excl_mount = NOT_MOUNTED_EXCLUSIVE;
+
+    /* Calculate various sizes */
+    VolHdrSize = 8 * sect_size;
+    NodeConfSize = (2 + volhdr->num_nodes) * sect_size;
+    NewConfSize = 4 * sect_size;
+    PublishSize = volhdr->num_nodes * sect_size;
+    VoteSize = volhdr->num_nodes * sect_size;
+    BitmapSize = OCFS_MAX_BITMAP_SIZE;
+    BegFreeSize = OCFS_NUM_FREE_SECTORS * sect_size;
+    EndFreeSize = OCFS_NUM_END_SECTORS * sect_size;
+
+    /* Fill in volhdr */
+    volhdr->node_cfg_off = volhdr->start_off + VolHdrSize;
+    volhdr->node_cfg_size = NodeConfSize;
+    volhdr->new_cfg_off = volhdr->node_cfg_off + NodeConfSize;
+    volhdr->publ_off = volhdr->new_cfg_off + NewConfSize;
+    volhdr->vote_off = volhdr->publ_off + PublishSize;
+    volhdr->bitmap_off = volhdr->vote_off + VoteSize;
+    volhdr->root_off = 0;
+    volhdr->root_bitmap_off = 0;
+    volhdr->root_bitmap_size = 0;
+    volhdr->data_start_off = volhdr->bitmap_off + BitmapSize + BegFreeSize;
+#define OCFS_DATA_START_ALIGN		4096
+    volhdr->data_start_off = OCFS_ALIGN(volhdr->data_start_off,
+				       	OCFS_DATA_START_ALIGN);
+
+    /* calculate number of data blocks */
+    *data_start_off = volhdr->data_start_off;
+    DataSize = volhdr->device_size - volhdr->data_start_off - EndFreeSize;
+
+    num_blocks = DataSize / volhdr->cluster_size;
+    tmpbitmap = OCFS_BUFFER_ALIGN(((num_blocks + 7) / 8), sect_size);
+    if (tmpbitmap > BitmapSize)
+    {
+	fprintf(stderr, "%dKB block size is too small to format "
+		"the entire disk.\nPlease specify a larger value.\n",
+		block_size);
+	return 0;
+    }
+
+    volhdr->num_clusters = num_blocks;
+
+    return 1;
+}				/* InitVolumeDiskHeader */
+
+
+/*
+ * InitVolumeLabel()
+ *
+ * Populate ocfs_vol_label
+ */
+void InitVolumeLabel(ocfs_vol_label * vollbl, __u32 sect_size, char *id,
+		     __u32 id_len)
+{
+    /* Set the volume label */
+    strcpy(vollbl->label, opts.volume_label);
+    vollbl->label_len = strlen(opts.volume_label);
+
+    /* Set the volume id */
+    memcpy(vollbl->vol_id, id, id_len);
+    vollbl->vol_id_len = id_len;
+
+    /* Set the volume lock to invalid_master */
+    vollbl->disk_lock.curr_master = -1;
+
+    return;
+}				/* InitVolumeLabel */
+
+
+/*
+ * SetNodeConfigHeader()
+ *
+ */
+void SetNodeConfigHeader(ocfs_node_config_hdr * nodehdr)
+{
+    strcpy(nodehdr->signature, NODE_CONFIG_HDR_SIGN);
+
+    nodehdr->version = NODE_CONFIG_VER;
+    nodehdr->num_nodes = 0;
+    nodehdr->disk_lock.curr_master = -1;
+    nodehdr->last_node = 0;
+
+    return;
+}				/* SetNodeConfigHeader */
+
+
+/*
+ * ShowDiskHdrVals()
+ *
+ */
+void ShowDiskHdrVals(ocfs_vol_disk_hdr * voldiskhdr)
+{
+    printf("signature        = %s\n"
+	   "mount_point      = %s\n"
+	   "serial_num       = %llu\n"
+	   "device_size      = %llu\n"
+	   "num_nodes        = %llu\n"
+	   "cluster_size     = %llu\n"
+	   "num_clusters     = %llu\n"
+	   "start_off        = %llu\n"
+	   "node_cfg_off     = %llu\n"
+	   "node_cfg_size    = %llu\n"
+	   "new_cfg_off      = %llu\n"
+	   "publ_off         = %llu\n"
+	   "vote_off         = %llu\n"
+	   "bitmap_off       = %llu\n"
+	   "root_bitmap_off  = %llu\n"
+	   "root_bitmap_size = %llu\n"
+	   "data_start_off   = %llu\n"
+	   "root_off         = %llu\n"
+	   "root_size        = %llu\n"
+	   "dir_node_size    = %llu\n"
+	   "file_node_size   = %llu\n"
+	   "internal_off     = %llu\n"
+	   "uid              = %u\n"
+	   "gid              = %u\n"
+	   "prot_bits        = %u\n"
+	   "excl_mount       = %d\n",
+	   voldiskhdr->signature,
+	   voldiskhdr->mount_point,
+	   voldiskhdr->serial_num,
+	   voldiskhdr->device_size,
+	   voldiskhdr->num_nodes,
+	   voldiskhdr->cluster_size,
+	   voldiskhdr->num_clusters,
+	   voldiskhdr->start_off,
+	   voldiskhdr->node_cfg_off,
+	   voldiskhdr->node_cfg_size,
+	   voldiskhdr->new_cfg_off,
+	   voldiskhdr->publ_off,
+	   voldiskhdr->vote_off,
+	   voldiskhdr->bitmap_off,
+	   voldiskhdr->root_bitmap_off,
+	   voldiskhdr->root_bitmap_size,
+	   voldiskhdr->data_start_off,
+	   voldiskhdr->root_off,
+	   voldiskhdr->root_size,
+	   voldiskhdr->dir_node_size,
+	   voldiskhdr->file_node_size,
+	   voldiskhdr->internal_off,
+	   voldiskhdr->uid,
+	   voldiskhdr->gid,
+	   voldiskhdr->prot_bits,
+	   voldiskhdr->excl_mount);
+    fflush(stdout);
+
+    return;
+}				/* ShowDiskHdrVals */
+
+
+/*
+ * HandleSignal()
+ */
+void HandleSignal(int sig)
+{
+	switch (sig) {
+
+	case SIGINT:
+		if (in_data_blocks && opts.clear_data_blocks) {
+			sigblock(sigmask(SIGINT));
+			format_intr = true;
+		} else {
+			fprintf(stderr, "\nError: Volume not formatted due " \
+				"to interruption.\n");
+    			safeclose(file);
+    			unbind_raw(rawminor, rawdev);
+			exit(1);
+		}
+		break;
+	}
+
+	if (sig != SIGINT)
+		signal(sig, HandleSignal);
+
+	return ;
+
+} /* HandleSignal */
+

Added: trunk/format/frmtport.c
===================================================================
--- trunk/format/frmtport.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/format/frmtport.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,637 @@
+/*
+ * frmtport.c
+ *
+ * ocfs format utility functions
+ *
+ * Copyright (C) 2002, 2004 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#include <format.h>
+
+ocfs_global_ctxt OcfsGlobalCtxt;
+__u32 debug_context = 0;
+__u32 debug_level = 0;
+__u32 debug_exclude = 0;
+
+extern char *usage_string;
+extern ocfs_options opts;
+
+/*
+ * MemAlloc()
+ *
+ */
+void *MemAlloc(__u32 size)
+{
+    void *buf = NULL;
+
+    if (!(buf = malloc_aligned(size)))
+	fprintf(stderr, "Error allocating %u bytes of memory.\n", size);
+
+    return buf;
+}				/* MemAlloc */
+
+/*
+ * OpenDisk()
+ *
+ */
+int OpenDisk(char *device)
+{
+    int file;
+    mode_t oldmode;
+
+    oldmode = umask(0000);
+    file = open(device, O_RDWR | O_CREAT, 0777);
+    umask(oldmode);
+    if (file == -1)
+    {
+	fprintf(stderr, "Error opening device %s.\n%s\n", device,
+		strerror(errno));
+	file = 0;
+    }
+
+    return file;
+}				/* OpenDisk */
+
+
+/*
+ * GetDiskGeometry()
+ *
+ */
+int GetDiskGeometry(int file, __u64 * vollength, __u32 * sect_size)
+{
+    /* SM: should be signed... struct hd_struct.nr_sects */
+    /* MS: the above only applies to 2.4.9 */
+    unsigned long devicesize;
+    int ret = 0;
+
+    if (ioctl(file, BLKGETSIZE, &devicesize) == -1)
+    {
+	fprintf(stderr, "Error reading size of %s device.\n%s\n", opts.device,
+		strerror(errno));
+	goto bail;
+    }
+
+#if defined(USE_SECTOR_SIZE_IOCTL)
+    if (ioctl(file, BLKSSZGET, sect_size) == -1)
+    {
+	fprintf(stderr, "Error reading the sector size for %s device.\n%s\n",
+		opts.device, strerror(errno));
+	goto bail;
+    }
+#else
+    *sect_size = OCFS_SECTOR_SIZE;
+#endif
+
+    if (devicesize && *sect_size)
+    {
+	*vollength = devicesize;
+	*vollength *= *sect_size;
+	ret = 1;
+    }
+    else
+	fprintf(stderr, "Invalid device specified %s\n", opts.device);
+
+  bail:
+    return ret;
+}				/* GetDiskGeometry */
+
+
+/*
+ * SetSeek()
+ *
+ */
+int SetSeek(int file, __u64 offset)
+{
+    off_t ext_offset;
+    int ret = 0;
+
+    ext_offset = (off_t) offset;
+
+    if (lseek(file, ext_offset, SEEK_SET) == -1)
+	fprintf(stderr, "Error setting file pointer to (%u).\n%s\n",
+		ext_offset, strerror(errno));
+    else
+	ret = 1;
+
+    return ret;
+}				/* SetSeek */
+
+
+/*
+ * Read()
+ *
+ */
+int Read(int file, __u32 size, char *buf)
+{
+    int ret = 0;
+
+    if (read(file, buf, size) == -1)
+	fprintf(stderr, "Error reading device %s.\n%s\n",
+		opts.device, strerror(errno));
+    else
+	ret = 1;
+
+    return ret;
+}				/* Read */
+
+
+/*
+ * Write()
+ *
+ */
+int Write(int file, __u32 size, char *buf)
+{
+    int ret = 0;
+
+    if (write(file, buf, size) == -1)
+	fprintf(stderr, "Error writing to device %s.\n%s\n", opts.device,
+		strerror(errno));
+    else
+	ret = 1;
+
+    return ret;
+}				/* Write */
+
+
+/*
+ * GenerateVolumeID()
+ *
+ * Volume id is used by ocfs to identify the volume in ipc messages.
+ */
+int GenerateVolumeID(char *volid, int volidlen)
+{
+    int ret = 0;
+
+    if (volidlen < MAX_VOL_ID_LENGTH)
+    {
+	fprintf(stderr, "internal error [%s], [%d]\n", __FILE__, __LINE__);
+	goto bail;
+    }
+
+    /* Read random bytes */
+    if (!GetRandom(volid, volidlen))
+	goto bail;
+
+    ret = 1;
+
+  bail:
+    return ret;
+}				/* GenerateVolumeID */
+
+/*
+ * version()
+ *
+ */
+void version(char *progname)
+{
+	printf("%s %s %s (build %s)\n", progname,
+					OCFS_BUILD_VERSION,
+					OCFS_BUILD_DATE,
+					OCFS_BUILD_MD5);
+	return;
+}				/* version */
+
+/*
+ * usage()
+ *
+ */
+void usage(void)
+{
+	printf("%s\n", usage_string);
+	return ;
+}				/* usage */
+
+
+/*
+ * ValidateOptions()
+ *
+ */
+int ValidateOptions(void)
+{
+	int valid_vals[] = {4, 8, 16, 32, 64, 128, 256, 512, 1024, 0};
+	int i;
+
+	if (opts.device[0] == '\0') {
+		fprintf(stderr, "Error: Device not specified.\n");
+		return 0;
+	}
+
+	for (i = 0; valid_vals[i]; ++i) {
+		if (opts.block_size == valid_vals[i])
+			break;
+	}
+
+	if (!valid_vals[i]) {
+		fprintf(stderr, "Error: Invalid block size.\n");
+		return 0;
+	}
+
+	if (opts.query_only)
+		return 1;
+
+	if (opts.volume_label[0] == '\0') {
+		fprintf(stderr, "Error: Volume label not specified.\n");
+		return 0;
+	}
+
+	if (opts.mount_point[0] == '\0') {
+		fprintf(stderr, "Error: Mount point not specified.\n");
+		return 0;
+	}
+
+	return 1;
+}				/* ValidateOptions */
+
+
+/*
+ * GetRandom()
+ *
+ * Returns random bytes of length randlen in buffer randbuf.
+ */
+int GetRandom(char *randbuf, int randlen)
+{
+    int randfd = 0;
+    int ret = 0;
+    int readlen = 0;
+    int len = 0;
+
+    if ((randfd = open("/dev/urandom", O_RDONLY)) == -1)
+    {
+	fprintf(stderr, "Error opening /dev/urandom.\n%s\n", strerror(errno));
+	goto bail;
+    }
+
+    if (randlen > 0)
+    {
+	while (readlen < randlen)
+	{
+	    if ((len =
+		 read(randfd, randbuf + readlen, randlen - readlen)) == -1)
+	    {
+		fprintf(stderr, "Error reading /dev/urandom.\n%s\n",
+			strerror(errno));
+		goto bail;
+	    }
+	    readlen += len;
+	}
+    }
+
+    ret = 1;
+
+  bail:
+    if (randfd > 0)
+	close(randfd);
+
+    return ret;
+}				/* GetRandom */
+
+
+/*
+ * ReadPublish()
+ *
+ */
+int ReadPublish(int file, __u64 publ_off, __u32 sect_size, void **buf)
+{
+	int ret = 0;
+	__u32 pub_len;
+
+	pub_len = OCFS_MAXIMUM_NODES * sect_size;
+
+	/* Alloc memory to read publish sectors */
+	if (!*buf) {
+		if (!(*buf = MemAlloc(pub_len)))
+			goto bail;
+	}
+
+	if (!SetSeek(file, publ_off))
+		goto bail;
+
+	/* read OCFS_MAXIMUM_NODES sectors starting publ_off */
+	if (!(Read(file, pub_len, *buf)))
+		goto bail;
+
+	ret = 1;
+
+      bail:
+	return ret;
+}				/* ReadPubllish */
+
+
+/*
+ * get_uid()
+ *
+ */
+uid_t get_uid(char *id)
+{
+	struct passwd *pw = NULL;
+	uid_t uid = 0;
+
+	if (isdigit(*id))
+		uid = atoi(id);
+	else {
+		pw = getpwnam(id);
+		if (pw)
+			uid = pw->pw_uid;
+	}
+
+	return uid;
+}				/* get_uid */
+
+
+/*
+ * get_gid()
+ *
+ */
+uid_t get_gid(char *id)
+{
+	struct group *gr = NULL;
+	gid_t gid = 0;
+
+	if (isdigit(*id))
+		gid = atoi(id);
+	else {
+		gr = getgrnam(id);
+		if (gr)
+			gid = gr->gr_gid;
+	}
+
+	return gid;
+}				/* get_gid */
+
+
+/*
+ * read_sectors()
+ *
+ */
+int read_sectors(int file, __u64 strtoffset, __u32 noofsects, __u32 sect_size,
+		 void *buf)
+{
+	__u32 i;
+	char *p;
+	int ret = 0;
+
+	if (!SetSeek(file, strtoffset))
+		goto bail;
+
+	for (i = 0, p = buf; i < noofsects; ++i, p += sect_size) {
+		if (!Read(file, sect_size, p))
+			goto bail;
+	}
+
+	ret = 1;
+
+      bail:
+	return ret;
+}				/* read_sectors */
+
+
+/*
+ * write_sectors()
+ *
+ */
+int write_sectors(int file, __u64 strtoffset, __u32 noofsects, __u32 sect_size,
+		  void *buf)
+{
+	__u32 i;
+	char *p;
+	int ret = 0;
+
+	if (!SetSeek(file, strtoffset))
+		goto bail;
+
+	for (i = 0, p = buf; i < noofsects; ++i, p += sect_size) {
+		if (!Write(file, sect_size, (void *)p))
+			goto bail;
+	}
+
+	ret = 1;
+
+      bail:
+	return ret;
+}				/* write_sectors */
+
+
+/*
+ * validate_volume_size()
+ *
+ */
+int validate_volume_size(__u64 given_vol_size, __u64 actual_vol_size)
+{
+	int ret = 0;
+	char str1[100], str2[100];
+
+	if (given_vol_size < OCFS_MIN_VOL_SIZE) {
+		num_to_str(given_vol_size, str1);
+		num_to_str(OCFS_MIN_VOL_SIZE, str2);
+		fprintf(stderr, "The size specified, %s, is smaller than "
+			"the minimum size, %s.\nAborting.\n", str1, str2);
+		goto bail;
+	}
+
+	if (given_vol_size > actual_vol_size) {
+		num_to_str(given_vol_size, str1);
+		num_to_str(actual_vol_size, str2);
+		fprintf(stderr, "The size specified, %s, is larger than "
+			"the device size, %s.\nAborting.\n",
+			str1, str2);
+		goto bail;
+	}
+
+	ret = 1;
+
+      bail:
+	return ret;
+}				/* validate_volume_size */
+
+
+/*
+ * num_to_str()
+ *
+ */
+void num_to_str(__u64 num, char *numstr)
+{
+	__u64 newnum;
+	int i = 0;
+	char append[] = " KMGT";
+	int len;
+
+	len = strlen(append);
+
+	for (i = 0, newnum = num; i < len && newnum > 1023; ++i)
+		newnum /= (__u64)1024;
+
+	sprintf(numstr, "%llu%c", newnum, append[i]);
+
+	return ;
+}				/* num_to_str */
+
+
+/*
+ * is_ocfs_volume()
+ *
+ */
+int is_ocfs_volume(int file, ocfs_vol_disk_hdr *volhdr, bool *ocfs_vol,
+		   __u32 sect_size)
+{
+	char *buf;
+	int ret = 0;
+
+	buf = (char *)volhdr;
+	memset(buf, 0, sect_size);
+
+	if (!SetSeek(file, 0))
+		goto bail;
+
+	if (!(Read(file, sect_size, buf)))
+		goto bail;
+
+	volhdr = (ocfs_vol_disk_hdr *) buf;
+
+	if ((!memcmp(volhdr->signature, OCFS_VOLUME_SIGNATURE,
+		     strlen(OCFS_VOLUME_SIGNATURE))))
+		*ocfs_vol = true;
+	else
+		*ocfs_vol = false;
+
+	ret = 1;
+
+      bail:
+	return ret;
+}				/* is_ocfs_volume */
+
+/*
+ * check_heart_beat()
+ *
+ */
+int check_heart_beat(int *file, char *device, ocfs_vol_disk_hdr *volhdr,
+		     __u32 *nodemap, __u32 sect_size)
+{
+	char *publish = NULL;
+	ocfs_super osb;
+	int ret = 0;
+	int i;
+	int waittime;
+
+	memset (&osb, 0, sizeof(ocfs_super));
+
+	if (!ReadPublish(*file, volhdr->publ_off, sect_size, (void **)&publish))
+		goto bail;
+
+	/* alloc osb and pop sect_size */
+	osb.sect_size = sect_size;
+
+        /* call ocfs_update_publish_map(first_time = true) */
+	ocfs_update_publish_map (&osb, (void *)publish, true);
+
+	/* sleep(OCFS_NM_HEARTBEAT_TIME * 10) */
+	PRINT_VERBOSE("Checking heart beat on volume ");
+	waittime = (OCFS_NM_HEARTBEAT_TIME/1000);
+	waittime = (waittime ? waittime : 1);
+	for (i = 0; i < OCFS_HBT_WAIT; ++i) {
+		PRINT_VERBOSE(".");
+		fflush(stdout);
+		sleep(waittime);
+	}
+   
+	/* Close and re-open device to force disk read */
+	safeclose(*file);
+	if (!(*file = OpenDisk(device)))
+		goto bail;
+
+	memset (publish, 0, sect_size);
+	if (!ReadPublish(*file, volhdr->publ_off, sect_size, (void **)&publish))
+		goto bail;
+
+	/* call ocfs_update_publish_map(first_time = false) */
+	ocfs_update_publish_map (&osb, (void *)publish, false);
+
+	PRINT_VERBOSE("\r                                                \r");
+	fflush(stdout);
+
+	*nodemap = LO(osb.publ_map);
+
+	ret = 1;
+      bail:
+	safefree(publish);
+	return ret;
+}				/* check_heart_beat */
+
+/*
+ * get_node_names()
+ *
+ */
+int get_node_names(int file, ocfs_vol_disk_hdr *volhdr, char **node_names,
+		   __u32 sect_size)
+{
+	char *buf = NULL;
+	char *p;
+	int len;
+	int ret = 0;
+	int i;
+	ocfs_disk_node_config_info *conf;
+
+	len = volhdr->node_cfg_size;
+	if (!(buf = (char *) MemAlloc(len)))
+		goto bail;
+	else
+		memset(buf, 0, len);
+
+	if (!SetSeek(file, volhdr->node_cfg_off))
+		goto bail;
+
+	if (!(Read(file, len, buf)))
+		goto bail;
+
+	p = buf + (sect_size * 2);
+	for (i = 0; i < OCFS_MAXIMUM_NODES; ++i, p += sect_size) {
+		conf = (ocfs_disk_node_config_info *)p;
+		if (conf->node_name[0])
+			node_names[i] = strdup(conf->node_name);
+	}
+
+	ret = 1;
+      bail:
+	safefree(buf);
+	return ret;
+}				/* get_node_names */
+
+
+/*
+ * print_node_names()
+ *
+ */
+void print_node_names(char **node_names, __u32 nodemap)
+{
+	int i, j;
+	char comma = '\0';
+
+	for (j = 1, i = 0; i < OCFS_MAXIMUM_NODES; ++i, j <<= 1) {
+		if (nodemap & j) {
+			if (node_names[i])
+				printf("%c %s", comma, node_names[i]);
+			else
+				printf("%c %d", comma, i);
+			comma = ',';
+		}
+	}
+	printf("\n");
+}				/* print_node_names */
+

Added: trunk/format/inc/format.h
===================================================================
--- trunk/format/inc/format.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/format/inc/format.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,148 @@
+/*
+ * format.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002, 2004 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _FORMAT_H_
+#define _FORMAT_H_
+
+#include <libocfs.h>
+#include <sys/ioctl.h>
+#include <ctype.h>
+#include <pwd.h>
+#include <grp.h>
+
+#define  OCFS_MAXIMUM_NODES            32
+#define  FILE_NAME_SIZE                200
+#define  OCFS_MAX_DIRECTORY_ENTRIES    100
+#define  OCFS_NUM_FREE_SECTORS         512             /* in sectors */
+#define  OCFS_NUM_END_SECTORS          1024            /* in sectors */
+#define  OCFS_MAX_BITMAP_SIZE          1024 * 1024     /* in bytes */
+#define  CLEAR_DATA_BLOCK_SIZE         2048            /* in sectors */
+
+#define  OCFS_MIN_VOL_SIZE             (200 * 1024 * 1024)	/* in bytes */
+
+#define  OCFS_FORMAT_NAME             "mkfs.ocfs"
+#define  OCFS_RESIZE_NAME             "resizeocfs"
+
+#define  OCFS_HBT_WAIT			10
+
+#define  OCFS_BUFFER_ALIGN(buf, secsz)  ((__u64)buf +                 \
+                                         (((__u64)buf % secsz) ?      \
+                                          (secsz - ((__u64)buf % secsz)) : 0))
+
+#define PRINT_PROGRESS()					\
+	if (opts.print_progress) {				\
+		__u64	__p;					\
+		__p = (sect_count * 100) / format_size; 	\
+		if (sect_count != format_size)			\
+			printf("%llu\n", __p);			\
+		else						\
+			printf("COMPLETE\n");			\
+	}
+
+#define PRINT_VERBOSE(f, a...)	do { if (!opts.quiet) printf(f, ##a); \
+				} while (0)
+
+#define KILO_BYTE	(1024)
+#define MEGA_BYTE	(KILO_BYTE * 1024)
+#define GIGA_BYTE	(MEGA_BYTE * 1024)
+#define TERA_BYTE	((__u64)GIGA_BYTE * (__u64)1024)
+
+#define MULT_FACTOR(c, f)				\
+	do {						\
+		switch (c) {				\
+		case 'k':				\
+		case 'K': (f) = KILO_BYTE; break;	\
+		case 'm':				\
+		case 'M': (f) = MEGA_BYTE; break;	\
+		case 'g':				\
+		case 'G': (f) = GIGA_BYTE; break;	\
+		case 't':				\
+		case 'T': (f) = TERA_BYTE; break;	\
+		default : (f) = 1; break;		\
+		}					\
+	} while (0)
+
+#undef MIN
+#define MIN(a, b)  (((a) < (b)) ? (a) : (b))
+
+#define safefree(a)  do { if(a) { free_aligned(a); (a) = NULL; } }while(0)
+#define safeclose(a)  do { if(a) { close(a); (a) = 0; } }while(0)
+
+typedef struct _ocfs_options
+{
+	__u8 device[FILE_NAME_SIZE];
+	__u32 block_size;
+	bool clear_data_blocks;
+	bool force_op;
+	gid_t gid;
+	__u8 volume_label[MAX_VOL_LABEL_LEN];
+	__u8 mount_point[FILE_NAME_SIZE];
+	bool query_only;
+	mode_t perms;
+	bool quiet;
+	uid_t uid;
+	bool print_progress;
+	__u32 slot_num;
+	__u64 device_size;
+	bool list_nodes;
+}
+ocfs_options;
+
+#include <frmtport.h>
+
+/* function prototypes */
+int CheckForceFormat(int file, __u64 *publ_off, bool *ocfs_vol, __u32 sect_size);
+
+int CheckHeartBeat(int *file, __u64 publ_off, __u32 sect_size);
+
+int WriteVolumeHdr(int file, ocfs_vol_disk_hdr * volhdr, __u64 offset,
+		   __u32 sect_size);
+
+int WriteVolumeLabel(int file, char *volid, __u32 volidlen, __u64 offset,
+		     __u32 sect_size);
+
+int InitNodeConfHdr(int file, __u64 offset, __u32 sect_size);
+
+int ClearSectors(int file, __u64 strtoffset, __u32 noofsects, __u32 sect_size);
+
+int ClearBitmap(int file, ocfs_vol_disk_hdr * volhdr);
+
+int ClearDataBlocks(int file, ocfs_vol_disk_hdr * volhdr, __u32 sect_size);
+
+int ReadOptions(int argc, char **argv);
+
+int InitVolumeDiskHeader(ocfs_vol_disk_hdr *volhdr, __u32 sect_size,
+			 __u64 vol_size, __u64 * non_data_size);
+
+void InitVolumeLabel(ocfs_vol_label * vollbl, __u32 sect_size, char *id,
+		     __u32 id_len);
+
+void SetNodeConfigHeader(ocfs_node_config_hdr * nodehdr);
+
+void ShowDiskHdrVals(ocfs_vol_disk_hdr * voldiskhdr);
+
+void HandleSignal(int sig);
+#endif /* _FORMAT_H_ */

Added: trunk/format/inc/frmtport.h
===================================================================
--- trunk/format/inc/frmtport.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/format/inc/frmtport.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,80 @@
+/*
+ * frmtport.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002, 2004 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _FRMTPORT_H_
+#define _FRMTPORT_H_
+
+/* function prototypes */
+void *MemAlloc(__u32 size);
+
+int OpenDisk(char *device);
+
+int GetDiskGeometry(int file, __u64 * vollength, __u32 * sect_size);
+
+int SetSeek(int file, __u64 offset);
+
+int Read(int file, __u32 size, char *buf);
+
+int Write(int file, __u32 size, char *buf);
+
+int GenerateVolumeID(char *volid, int volidlen);
+
+void version(char *progname);
+
+void usage(void);
+
+int ValidateOptions(void);
+
+int GetRandom(char *randbuf, int randlen);
+
+int ReadPublish(int file, __u64 publ_off, __u32 sect_size, void **buf);
+
+uid_t get_uid(char *id);
+
+gid_t get_gid(char *id);
+
+int read_sectors(int file, __u64 strtoffset, __u32 noofsects, __u32 sect_size,
+		 void *buf);
+
+int write_sectors(int file, __u64 strtoffset, __u32 noofsects, __u32 sect_size,
+		  void *buf);
+
+int validate_volume_size(__u64 given_vol_size, __u64 actual_vol_size);
+
+void num_to_str(__u64 num, char *numstr);
+
+int is_ocfs_volume(int file, ocfs_vol_disk_hdr *volhdr, bool *ocfs_vol,
+		   __u32 sect_size);
+
+int check_heart_beat(int *file, char *device, ocfs_vol_disk_hdr *volhdr,
+		     __u32 *nodemap, __u32 sect_size);
+
+int get_node_names(int file, ocfs_vol_disk_hdr *volhdr, char **node_names,
+		   __u32 sect_size);
+
+void print_node_names(char **node_names, __u32 nodemap);
+
+#endif /* _FRMTPORT_H_ */

Added: trunk/format/inc/resize.h
===================================================================
--- trunk/format/inc/resize.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/format/inc/resize.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,55 @@
+/*
+ * resize.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002, 2004 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Sunil Mushran
+ */
+
+#ifndef _RESIZE_H_
+#define _RESIZE_H_
+
+#include <signal.h>
+#include <ctype.h>
+#include <limits.h>
+
+/* function prototypes */
+
+int read_options(int argc, char **argv);
+
+bool validate_options(void);
+
+int update_volume_header(int file, ocfs_vol_disk_hdr *volhdr,
+			 __u32 sect_size, __u64 vol_size, bool *update);
+
+int update_node_cfg(int file, ocfs_vol_disk_hdr *volhdr, __u64 cfg_hdr_off,
+		    __u64 cfg_node_off, __u64 new_cfg_off,
+		    ocfs_node_config_hdr *node_hdr,
+		    ocfs_disk_node_config_info *node_info, __u32 sect_size,
+		    bool *update);
+
+void handle_signal(int sig);
+
+int print_node_cfgs(int file, ocfs_vol_disk_hdr *volhdr, __u32 sect_size);
+
+int process_new_volsize(int file, ocfs_vol_disk_hdr *volhdr, __u32 sect_size,
+		       	__u64 vol_size, bool *update);
+
+#endif /* _RESIZE_H_ */

Added: trunk/format/mkfs.ocfs.1.in
===================================================================
--- trunk/format/mkfs.ocfs.1.in	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/format/mkfs.ocfs.1.in	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,72 @@
+.TH "mkfs.ocfs" "1" "November 2003" "Version @VERSION@" "OCFS Manual Pages"
+.SH "NAME"
+mkfs.ocfs \- Build an OCFS file system.
+.SH "SYNOPSIS"
+\fBmkfs.ocfs\fR \-b block\-size [\-C] [\-F] [\-g gid] [\-h] \-L volume\-label \-m mount\-path [\-n] [\-p permissions] [\-q] [\-u uid] [\-V] device
+.SH "DESCRIPTION"
+.PP 
+\fBmkfs.ocfs\fR is used to build an OCFS file system on a device, usually a partition in a shared disk. \fBmkfs.ocfs\fR will not format a partition if a node has it mounted to prevent data loss. After the filesystem is formatted, it needs to be exclusively mounted by one node, usually node 0, for the first time. After the first mount, all subsequent mounts can be performed in parallel.
+.SH "OPTIONS"
+.TP
+\fB\-b\fR \fIblocksize\fR
+Block size in kilo bytes. The size of the blocksize (4k\-1M) will determine the maximum filesystem size possible for the OCFS (32Gb\-8Tb).
+
+.TP
+\fB\-C\fR 
+Clear all data blocks. Use this option only if it is really necessary to clear all blocks. This will slow down the process.
+
+.TP
+\fB\-F\fR 
+Force format. Use this option only if formatting an existing OCFS partition.
+
+.TP
+\fB\-g\fR \fIgid\fR 
+Set the \fIgid\fR for the root directory. On mount time, it will automatcially
+assign the \fIgid\fR specified by this parameter to the mount point. One may
+use the \fIgid\fR or the group name (i.e.:1011 or \fIdba\fR).
+
+.TP
+\fB\-h\fR 
+Help. 
+
+.TP
+\fB\-L\fR \fIVolume label\fR
+Volume label. Allows mount of the file system using LABEL=<Volume Label> instead of device name.
+
+.TP
+\fB\-m\fR \fImount point\fR
+Mount point where the formatted device will be mounted.
+
+.TP
+\fB\-n\fR 
+Query only. Will not build the filesystem.
+
+.TP
+\fB\-p\fR \fINNNN\fR
+Permissions \fINNNN\fR for the root directory. On mount, it will automatcially assign the permission specified by this parameter to the mount point.
+
+.TP
+\fB\-q\fR 
+Quiet execution.
+
+.TP
+\fB\-u\fR \fIuid\fR
+Set the \fIuid\fR for the root directory. On mount time, it will automatcially
+assign \fIuid\fR specified by this parameter to the mount point. One can use
+the \fIuid\fR or the username (i.e.:1011 or \fIoracle\fR).
+
+.TP
+\fB\-V\fR 
+Print version and exit.
+
+.SH "BUGS"
+Stuff.
+
+.SH "SEE ALSO"
+.BR ocfs(5)
+
+.SH "AUTHORS"
+Oracle Corporation
+
+.SH "COPYRIGHT"
+Copyright \(co 2002 Oracle Corporation

Added: trunk/format/mounted.c
===================================================================
--- trunk/format/mounted.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/format/mounted.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,224 @@
+/*
+ * mounted.c
+ *
+ * ocfs mount detect utility
+ *
+ * Copyright (C) 2003, 2004 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Sunil Mushran
+ */
+
+#include <format.h>
+#include <signal.h>
+
+ocfs_options opts = {
+	.device = "",
+	.block_size = 0,
+	.clear_data_blocks = false,
+	.force_op = false,
+	.gid = 0,
+	.volume_label = "",
+	.mount_point = "",
+	.query_only = false,
+	.perms = 0755,
+	.quiet = false,
+	.uid = 0,
+	.print_progress = false,
+	.slot_num = OCFS_INVALID_NODE_NUM,
+	.device_size = 0
+};
+
+char *usage_string = "usage: mounted.ocfs <device>";
+int file = 0;
+int rawminor = 0;
+char rawdev[FILE_NAME_SIZE];
+
+#define PRINT_VERBOSE(f, a...)	do { if (true) printf(f, ##a); \
+				} while (0)
+
+int get_vol_label(int file, ocfs_vol_label *vollabel, __u32 sect_size);
+void handle_signal(int sig);
+int read_options(int argc, char **argv);
+
+/*
+ * main()
+ *
+ */
+int main(int argc, char **argv)
+{
+	ocfs_vol_disk_hdr *volhdr = NULL;
+	ocfs_vol_label *vollbl = NULL;
+	__u32 sect_size = OCFS_SECTOR_SIZE;
+	__u64 vol_size = 0;
+	__u32 i;
+	bool ocfs_vol = false;
+	char *node_names[OCFS_MAXIMUM_NODES];
+	__u32 nodemap = 0;
+
+	for (i = 0; i < OCFS_MAXIMUM_NODES; ++i)
+		node_names[i] = NULL;
+
+	if (signal(SIGINT, handle_signal) == SIG_ERR) {
+		fprintf(stderr, "Could not set SIGINT\n");
+		goto bail;
+	}
+
+	if (!read_options(argc, argv))
+		goto bail;
+
+	if (!(file = OpenDisk(opts.device)))
+		goto bail;
+
+	if (!(GetDiskGeometry(file, &vol_size, &sect_size)))
+		goto bail;
+
+	volhdr = MemAlloc(sect_size);
+	vollbl = MemAlloc(sect_size);
+	if (!volhdr || !vollbl)
+		goto bail;
+	else {
+		memset(volhdr, 0, sect_size);
+		memset(vollbl, 0, sect_size);
+	}
+
+	/* close and open after binding to raw */
+	safeclose(file);
+
+	if (bind_raw(opts.device, &rawminor, rawdev, sizeof(rawdev)))
+		goto bail;
+	
+	if (!(file = OpenDisk(rawdev)))
+		goto bail;
+
+	if (!is_ocfs_volume(file, volhdr, &ocfs_vol, sect_size))
+		goto bail;
+
+	if (!ocfs_vol) {
+		fprintf(stderr, "Error: %s is not an ocfs volume.\n", opts.device);
+		goto bail;
+	}
+
+	printf("Device: %s\n", opts.device);
+
+	if (get_vol_label(file, vollbl, sect_size)) {
+		printf("Label : %s\n", vollbl->label);
+		printf("Id    : ");
+		for (i = 0; i < vollbl->vol_id_len; ++i)
+			printf("%02X", vollbl->vol_id[i]);
+		printf("\n");
+	}
+
+	if (!check_heart_beat(&file, rawdev, volhdr, &nodemap, sect_size)) {
+		fprintf(stderr, "Error detecting heartbeat on volume.\n");
+		goto bail;
+	}
+
+	if (!nodemap) {
+		printf("Nodes : Not mounted\n");
+		goto bail;
+	}
+
+	get_node_names(file, volhdr, node_names, sect_size);
+
+	printf("Nodes :");
+	print_node_names(node_names, nodemap);
+
+bail:
+	for (i = 0; i < OCFS_MAXIMUM_NODES; ++i)
+		safefree(node_names[i]);
+
+	safefree(volhdr);
+	safefree(vollbl);
+	safeclose(file);
+	unbind_raw(rawminor, rawdev);
+	return 0;
+}				/* main */
+
+
+/*
+ * get_vol_label()
+ *
+ */
+int get_vol_label(int file, ocfs_vol_label *vollbl, __u32 sect_size)
+{
+	int ret = 0;
+
+	if (!SetSeek(file, sect_size))
+		goto bail;
+
+	if (!(Read(file, sect_size, (char *)vollbl)))
+		goto bail;
+
+	ret = 1;
+bail:
+	return ret;
+}				/* get_vol_label */
+
+
+/*
+ * handle_signal()
+ */
+void handle_signal(int sig)
+{
+	switch (sig) {
+	case SIGINT:
+		fprintf(stderr, "\nInterrupted.\n");
+		safeclose(file);
+		unbind_raw(rawminor, rawdev);
+		exit(1);
+		break;
+
+	default:
+		break;
+	}
+
+	if (sig != SIGINT)
+		signal(sig, handle_signal);
+
+	return ;
+}				/* handle_signal */
+
+
+/*
+ * read_options()
+ *
+ * mounted.ocfs <device>
+ *
+ */
+int read_options(int argc, char **argv)
+{
+	int ret = 0;
+
+	if (argc < 2) {
+		version(argv[0]);
+		usage();
+		goto bail;
+	}
+
+	strncpy(opts.device, argv[1], FILE_NAME_SIZE);
+	if (strlen(opts.device))
+		ret = 1;
+	else {
+		version(argv[0]);
+		usage();
+	}
+
+      bail:
+	return ret;
+}				/* read_options */
+

Added: trunk/format/resize.c
===================================================================
--- trunk/format/resize.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/format/resize.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,720 @@
+/*
+ * resize.c
+ *
+ * ocfs resize utility
+ *
+ * Copyright (C) 2002, 2004 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Sunil Mushran
+ */
+
+#include <format.h>
+#include <resize.h>
+
+ocfs_options opts = {
+	.device = "",
+	.block_size = 0,
+	.clear_data_blocks = false,
+	.force_op = false,
+	.gid = -1,
+	.volume_label = "",
+	.mount_point = "",
+	.query_only = false,
+	.perms = -1,
+	.quiet = false,
+	.uid = -1,
+	.print_progress = false,
+	.slot_num = OCFS_INVALID_NODE_NUM,
+	.device_size = 0,
+	.list_nodes = false
+};
+
+bool ignore_signal = false;
+int file = 0;
+int rawminor = 0;
+char rawdev[FILE_NAME_SIZE];
+
+char *usage_string =
+"usage: resizeocfs [-F] [-g gid] [-h] [-l] [-n] [-N nodenum] [-p permissions]\n"
+"                  [-q] [-S size] [-u uid] [-V] device\n\n"
+"	-F Force resize existing OCFS volume\n"
+"	-g Group ID for the root directory\n"
+"	-h Help\n"
+"	-l List all the node config slots\n"
+"	-n Query only\n"
+"	-N Node config slot be to be cleared\n"
+"	-p Permissions for the root directory\n"
+"	-q Quiet execution\n"
+"	-S Volume size, e.g., 50G (M for mega, G for giga, T for tera)\n"
+"	-u User ID for the root directory\n"
+"	-V Print version and exit\n";
+
+/*
+ * main()
+ *
+ */
+int main(int argc, char **argv)
+{
+	ocfs_vol_disk_hdr *volhdr = NULL;
+	ocfs_node_config_hdr *node_hdr = NULL;
+	ocfs_disk_node_config_info *node_info = NULL;
+	__u32 sect_size = OCFS_SECTOR_SIZE;
+	__u64 vol_size = 0;
+	__u64 offset;
+	bool ocfs_vol = false;
+	char proceed;
+	bool update = false;
+	char *node_names[OCFS_MAXIMUM_NODES];
+	__u32 nodemap = 0;
+	int i;
+	__u64 cfg_hdr_off = 0;
+	__u64 cfg_node_off = 0;
+	__u64 new_cfg_off = 0;
+
+	for (i = 0; i < OCFS_MAXIMUM_NODES; ++i)
+		node_names[i] = NULL;
+
+	/* Set ctrl-c handler */
+	if (signal(SIGINT, handle_signal) == SIG_ERR) {
+		fprintf(stderr, "Could not set SIGINT\n");
+		goto bail;
+	}
+
+	/* Read the options */
+	if (!read_options(argc, argv))
+		goto bail;
+
+	/* Validate the options */
+	if (!validate_options())
+		goto bail;
+
+	/* Open the disk */
+	if (!(file = OpenDisk(opts.device)))
+		goto bail;
+
+	/* Allocate mem */
+	volhdr = MemAlloc(OCFS_SECTOR_SIZE);
+	node_hdr = MemAlloc(OCFS_SECTOR_SIZE);
+	node_info = MemAlloc(OCFS_SECTOR_SIZE);
+	if (!volhdr || !node_hdr || !node_info)
+		goto bail;
+
+	/* Is this an existing ocfs volume */
+	if (!is_ocfs_volume(file, volhdr, &ocfs_vol, sect_size))
+		goto bail;
+
+
+	/* Abort if not an ocfs volume */
+	if (!ocfs_vol) {
+		fprintf(stderr, "%s is not an ocfs volume.\nAborting.\n",
+			opts.device);
+		goto bail;
+	}
+
+	if (opts.list_nodes) {
+		print_node_cfgs(file, volhdr, sect_size);
+		goto bail;
+	}
+
+	/* Get the partition Information */
+	if (!(GetDiskGeometry(file, &vol_size, &sect_size)))
+		goto bail;
+
+	if (opts.device_size) {
+		if (!(validate_volume_size(opts.device_size, vol_size)))
+			goto bail;
+		vol_size = opts.device_size;
+	}
+
+	/* close and open after binding to raw */
+	safeclose(file);
+
+	/* bind device to raw */
+	if (bind_raw(opts.device, &rawminor, rawdev, sizeof(rawdev)))
+		goto bail;
+
+	/* Open the disk */
+	if (!(file = OpenDisk(rawdev)))
+		goto bail;
+
+	/* read volume header */
+	if (!read_sectors(file, 0, 1, sect_size, (void *)volhdr))
+		goto bail;
+
+	/* Update node cfgs */
+	if (IS_VALID_NODE_NUM(opts.slot_num)) {
+		cfg_hdr_off = volhdr->node_cfg_off;
+		cfg_node_off = volhdr->node_cfg_off + (2 + opts.slot_num) * sect_size;
+		new_cfg_off = volhdr->new_cfg_off + sect_size;
+
+		if (!(update_node_cfg(file, volhdr, cfg_hdr_off, cfg_node_off,
+				      new_cfg_off, node_hdr, node_info,
+				      sect_size, &update)))
+			goto bail;
+	}
+
+	/* Update volume disk header */
+	if (opts.gid != -1 || opts.uid != -1 || opts.perms != -1 ||
+	    opts.device_size) {
+		if (!(update_volume_header(file, volhdr, sect_size, vol_size,
+					   &update)))
+			goto bail;
+	}
+
+	if (!update) {
+		printf("No changes made to the volume.\nAborting.\n");
+		goto bail;
+	}
+
+	/* query_only option bails you here */
+	if (opts.query_only) {
+		printf("Changes not written to disk.\n");
+		goto bail;
+	}
+
+	if (!opts.force_op) {
+		printf("Proceed (y/N): ");
+		proceed = getchar();
+		if (toupper(proceed) != 'Y') {
+			printf("Aborting operation.\n");
+			goto bail;
+		}
+	}
+
+	/* Check for heartbeat for any write operation */
+	if (!check_heart_beat(&file, rawdev, volhdr, &nodemap, sect_size))
+		goto bail;
+
+	if (nodemap) {
+		/* Exit as device is mounted on some node */
+		get_node_names(file, volhdr, node_names, sect_size);
+		printf("%s mounted on nodes:", opts.device);
+		print_node_names(node_names, nodemap);
+		printf("Aborting.\n");
+		goto bail;
+	}
+
+	/* do not allow interrupts */
+	ignore_signal = true;
+
+	/* Write node cfgs */
+	if (IS_VALID_NODE_NUM(opts.slot_num)) {
+		if (!write_sectors(file, cfg_hdr_off, 1, sect_size,
+				   (void *)node_hdr))
+			goto bail;
+		if (!write_sectors(file, cfg_node_off, 1, sect_size,
+				   (void *)node_info))
+			goto bail;
+		if (!write_sectors(file, new_cfg_off, 1, sect_size,
+				   (void *)node_hdr))
+			goto bail;
+	}
+
+	/* Write volume disk header */
+	if (opts.gid != -1 || opts.uid != -1 || opts.perms != -1 ||
+	    opts.device_size) {
+		offset = volhdr->start_off;
+		if (!write_sectors(file, offset, 1, sect_size, (void *)volhdr))
+			goto bail;
+	}
+
+	printf("Changes written to disk.\n");
+
+bail:
+	safefree(volhdr);
+	safefree(node_hdr);
+	safefree(node_info);
+
+	for (i = 0; i < OCFS_MAXIMUM_NODES; ++i)
+		safefree(node_names[i]);
+
+	safeclose(file);
+	unbind_raw(rawminor, rawdev);
+	return 0;
+}				/* main */
+
+
+/*
+ * read_options()
+ *
+ * resizeocfs [ -C ] [ -f ] [ -g gid] [ -L label] [ -m mount-point]
+ *            [ -p permissions] [ -q ] [ -S size] [ -u uid] [ -V ] device
+ *
+ */
+int read_options(int argc, char **argv)
+{
+	int i;
+	int ret = 1;
+	char tmp[128];
+	char *p;
+	__u64 fac = 1;
+	long double size;
+
+	if (argc < 2) {
+		version(argv[0]);
+		usage();
+		ret = 0;
+		goto bail;
+	}
+
+	for (i = 1; i < argc && ret; i++) {
+		switch(*argv[i]) {
+		case '-':
+			switch(*++argv[i]) {
+			case 'C':	/* clear all data blocks */
+				opts.clear_data_blocks = true;
+				break;
+
+			case 'F':	/* force resize */
+				opts.force_op = true;
+				break;
+
+			case 'g':	/* gid */
+				++i;
+				if (i < argc && argv[i])
+					opts.gid = get_gid(argv[i]);
+				else {
+					fprintf(stderr, "Invalid group id.\n"
+						"Aborting.\n");
+					ret = 0;
+				}
+				break;
+
+			case 'h':	/* help */
+				version(argv[0]);
+				usage();
+				ret = 0;
+				break;
+
+			case 'l':	/* list node configs */
+				opts.list_nodes = true;
+				break;
+
+			case 'n':	/* query */
+				opts.query_only = true;
+				break;
+
+			case 'N':	/* node cfg slot */
+				++i;
+				if (i < argc && argv[i])
+					opts.slot_num = atoi(argv[i]);
+				else {
+					fprintf(stderr,"Invalid node config slot.\n"
+						"Aborting.\n");
+					ret = 0;
+				}
+				break;
+
+			case 'p':	/* permissions */
+				++i;
+				if (i < argc && argv[i]) {
+					opts.perms = strtoul(argv[i], NULL, 8);
+					opts.perms &= 0007777;
+				} else {
+					fprintf(stderr,"Invalid permissions.\n"
+						"Aborting.\n");
+					ret = 0;
+				}
+				break;
+
+			case 'q':	/* quiet */
+				opts.quiet = true;
+				break;
+
+			case 'S':	/* device size */
+				++i;
+				if (i < argc && argv[i]) {
+					strcpy(tmp, argv[i]);
+					size = strtold(tmp, &p);
+					if (p)
+						MULT_FACTOR(*p, fac);
+					opts.device_size = (__u64)(size * fac);
+				} else {
+					fprintf(stderr,"Invalid device size.\n"
+						"Aborting.\n");
+					ret = 0;
+				}
+				break;
+
+			case 'u':	/* uid */
+				++i;
+				if (i < argc && argv[i])
+					opts.uid = get_uid(argv[i]);
+				else {
+					fprintf(stderr,"Invalid user id.\n"
+						"Aborting.\n");
+					ret = 0;
+				}
+				break;
+
+			case 'V':	/* print version */
+				version(argv[0]);
+				ret = 0;
+				break;
+
+			case 'x':	/* used for debugocfs */
+				opts.print_progress = true;
+				break;
+
+			default:
+				fprintf(stderr, "Invalid switch -%c.\n"
+					"Aborting.\n", *argv[i]);
+				ret = 0;
+				break;
+			}
+			break;
+
+		default:
+			strncpy(opts.device, argv[i], FILE_NAME_SIZE);
+			break;
+		}
+	}
+
+      bail:
+	return ret;
+}				/* read_options */
+
+
+/*
+ * validate_options()
+ *
+ */
+bool validate_options(void)
+{
+	if (opts.device[0] == '\0') {
+		fprintf(stderr, "Error: Device not specified.\n");
+		usage();
+		return 0;
+	}
+
+	if (opts.slot_num != OCFS_INVALID_NODE_NUM) {
+		if (opts.slot_num < 0 || opts.slot_num >= OCFS_MAXIMUM_NODES) {
+			fprintf(stderr, "Error: Invalid node config slot "
+			       	"specified.\n");
+			usage();
+			return 0;
+		}
+	}
+
+	return 1;
+}				/* validate_options */
+
+
+/*
+ * update_volume_header()
+ *
+ */
+int update_volume_header(int file, ocfs_vol_disk_hdr *volhdr, __u32 sect_size,
+			 __u64 vol_size, bool *update)
+{
+	int ret = 1;
+
+	if (opts.uid != -1) {
+		if (getpwuid(opts.uid)) {
+			printf("Changing uid from %d to %d\n", volhdr->uid,
+			       opts.uid);
+			volhdr->uid = opts.uid;
+			*update = true;
+		} else {
+			fprintf (stderr, "Error: Invalid uid %d\n", opts.uid); 
+			ret = 0;
+			goto bail;
+		}
+	}
+
+	if (opts.gid != -1) {
+		if (getgrgid(opts.gid)) {
+			printf("Changing gid from %d to %d\n", volhdr->gid,
+			       opts.gid);
+			volhdr->gid = opts.gid;
+			*update = true;
+		} else {
+			fprintf (stderr, "Error: Invalid gid %d\n", opts.gid); 
+			ret = 0;
+			goto bail;
+		}
+	}
+
+	if (opts.perms != -1) {
+		if (opts.perms >= 0000 && opts.perms <= 07777) {
+			printf("Changing permissions from 0%o to 0%o\n",
+			       volhdr->prot_bits, opts.perms);
+			volhdr->prot_bits = opts.perms;
+			*update = true;
+		} else {
+			fprintf (stderr, "Error permissions 0%o\n", opts.perms);
+			ret = 0;
+			goto bail;
+		}
+	}
+
+	if (opts.device_size) {
+		ret = process_new_volsize(file, volhdr, sect_size, vol_size,
+					  update);
+		if (ret)
+			*update = true;
+	}
+
+bail:
+	return ret;
+}				/* update_volume_header */
+
+/*
+ * update_node_cfg()
+ *
+ */
+int update_node_cfg(int file, ocfs_vol_disk_hdr *volhdr, __u64 cfg_hdr_off,
+		    __u64 cfg_node_off, __u64 new_cfg_off,
+		    ocfs_node_config_hdr *node_hdr,
+		    ocfs_disk_node_config_info *node_info, __u32 sect_size,
+		    bool *update)
+{
+	bool ret = 0;
+	ocfs_guid guid;
+
+	if (!read_sectors(file, cfg_hdr_off, 1, sect_size, (void *)node_hdr))
+		goto bail;
+
+	if (!read_sectors(file, cfg_node_off, 1, sect_size, (void *)node_info))
+		goto bail;
+
+	memset(&guid, 0, sizeof(ocfs_guid));
+
+	if (memcmp(&node_info->guid, &guid, sizeof(guid))) {
+		printf("Clearing node number %d used by node %s\n",
+		       opts.slot_num, node_info->node_name);
+		node_hdr->num_nodes--;
+		node_hdr->cfg_seq_num++;
+		memset(node_info, 0, sizeof(ocfs_disk_node_config_info));
+		*update = true;
+	} else {
+		fprintf(stderr, "Node number %d is not in use\n",
+		       	opts.slot_num);
+	}
+
+	ret = 1;
+bail:
+	return ret;
+}				/* update_node_cfg */
+
+/*
+ * handle_signal()
+ */
+void handle_signal(int sig)
+{
+	switch (sig) {
+	case SIGINT:
+		if (!ignore_signal) {
+			fprintf(stderr, "\nOperation interrupted.\nAborting.\n");
+			safeclose(file);
+			unbind_raw(rawminor, rawdev);
+			exit(1);
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	if (sig != SIGINT)
+		signal(sig, handle_signal);
+
+	return ;
+}				/* handle_signal */
+
+/*
+ * print_node_cfgs()
+ *
+ */
+int print_node_cfgs(int file, ocfs_vol_disk_hdr *volhdr, __u32 sect_size)
+{
+	char *buf = NULL;
+	char *p;
+	int len;
+	int ret = 0;
+	int i;
+	ocfs_disk_node_config_info *conf;
+
+	len = volhdr->node_cfg_size;
+	if (!(buf = (char *) MemAlloc(len)))
+		goto bail;
+	else
+		memset(buf, 0, len);
+
+	if (!SetSeek(file, volhdr->node_cfg_off))
+		goto bail;
+
+	if (!(Read(file, len, buf)))
+		goto bail;
+
+	p = buf + (sect_size * 2);
+
+	printf ("%2s %-32s %-15s %-7s %-s\n", "#", "Name", "IP Address", "IP Port", "Node GUID");
+	printf ("%2s %-32s %-15s %-7s %-s\n", "=", "================================",
+	       	"===============", "=======", "================================");
+	for (i = 0; i < OCFS_MAXIMUM_NODES; ++i, p += sect_size) {
+		conf = (ocfs_disk_node_config_info *)p;
+		if (!conf->node_name[0])
+			continue;
+		printf ("%2d %-32s %-15s %-7d %*s\n", i, conf->node_name,
+		       	conf->ipc_config.ip_addr, conf->ipc_config.ip_port,
+		       	GUID_LEN, conf->guid.guid);
+	}
+
+	ret = 1;
+      bail:
+	safefree(buf);
+	return ret;
+}				/* print_node_cfgs */
+
+
+/*
+ * process_new_volsize()
+ *
+ */
+int process_new_volsize(int file, ocfs_vol_disk_hdr *volhdr, __u32 sect_size,
+		       	__u64 vol_size, bool *update)
+{
+	__u64 end_free_sz;
+	__u64 new_data_sz;
+	__u64 old_num_blks, new_num_blks;
+	__u64 max_vol_sz, min_vol_sz;
+	__u8 *bitmap = NULL;
+	__u32 num_sectors;
+	__u32 new_bitmap_sz;
+	__u32 old_num_bytes, new_num_bytes;
+	__u32 i;
+	__u32 byte_ind, bit_ind;
+	__u8 *p;
+	int ret = 0;
+	char str1[100], str2[100];
+
+	if (vol_size > volhdr->device_size) {
+		end_free_sz = OCFS_NUM_END_SECTORS * sect_size;
+		new_data_sz = vol_size - volhdr->data_start_off - end_free_sz;
+
+		new_num_blks = (__u64)(new_data_sz / volhdr->cluster_size);
+		old_num_blks = volhdr->num_clusters;
+
+		if (new_num_blks == old_num_blks) {
+			fprintf(stderr, "No change in number of blocks (%llu)."
+				"\nAborting.\n", old_num_blks);
+			goto bail;
+		}
+
+		new_bitmap_sz = OCFS_BUFFER_ALIGN(((new_num_blks + 7) / 8),
+						  sect_size);
+		if (new_bitmap_sz > OCFS_MAX_BITMAP_SIZE) {
+			max_vol_sz = OCFS_MAX_BITMAP_SIZE * 8 *
+				     volhdr->cluster_size;
+			max_vol_sz += volhdr->data_start_off + end_free_sz;
+
+			num_to_str(volhdr->cluster_size, str1);
+			num_to_str(max_vol_sz, str2);
+			fprintf(stderr, "With a %s block size, the max "
+				"volume size can be %s.\nAborting.\n",
+				str1, str2);
+			goto bail;
+		}
+
+		if (!opts.quiet) {
+			printf("Increasing volume size from %llu bytes to %llu bytes.\n",
+			       volhdr->device_size, vol_size);
+			printf("Increasing number of blocks from %llu to %llu."
+			       "\n", volhdr->num_clusters, new_num_blks);
+		}
+
+		volhdr->device_size = vol_size;
+		volhdr->num_clusters = new_num_blks;
+		*update = true;
+
+	} else if (vol_size < volhdr->device_size) {
+		end_free_sz = OCFS_NUM_END_SECTORS * sect_size;
+		new_data_sz = vol_size - volhdr->data_start_off - end_free_sz;
+
+		new_num_blks = new_data_sz / volhdr->cluster_size;
+		old_num_blks = volhdr->num_clusters;
+
+		if (new_num_blks == old_num_blks) {
+			fprintf(stderr, "No change in number of blocks (%llu)."
+				"\nAborting.\n", old_num_blks);
+			goto bail;
+		}
+
+		if (!(bitmap = (char *) MemAlloc(OCFS_MAX_BITMAP_SIZE)))
+			goto bail;
+
+		/* read the bitmap */
+		num_sectors = OCFS_MAX_BITMAP_SIZE / sect_size;
+		if (!read_sectors(file, volhdr->bitmap_off, num_sectors,
+				  sect_size, (void *)bitmap))
+			goto bail;
+
+#define GET_LAST_BYTE(num_bytes, num_blocks)		\
+		do {					\
+			num_bytes = (num_blocks) / 8;	\
+			if ((num_blocks) % 8)		\
+				++(num_bytes);		\
+		} while (0)
+
+		GET_LAST_BYTE(new_num_bytes, new_num_blks);
+		GET_LAST_BYTE(old_num_bytes, old_num_blks);
+
+		for (i = old_num_bytes, p = bitmap + old_num_bytes;
+		     i > new_num_bytes - 1; --i, --p)
+			if (*p)
+				break;
+
+		byte_ind = i;
+		if (byte_ind > new_num_bytes - 1) {
+			char x = 0x80;
+			for (i = 8; i > 0; --i, x >>= 1) {
+				if (*p & x)
+					break;
+			}
+
+			bit_ind = i;
+
+			min_vol_sz = (byte_ind - 1) * 8 * volhdr->cluster_size;
+			min_vol_sz += bit_ind * volhdr->cluster_size;
+			min_vol_sz += volhdr->data_start_off + end_free_sz;
+
+			fprintf(stderr, "Due to disk usage, the volume size "
+				"cannot be smaller than %llu bytes.\nAborting.\n",
+				min_vol_sz);
+			goto bail;
+		}
+
+		if (!opts.quiet) {
+			printf("Decreasing volume size from %llu bytes to %llu bytes.\n",
+			       volhdr->device_size, vol_size);
+			printf("Decreasing number of blocks from %llu to %llu."
+			       "\n", volhdr->num_clusters, new_num_blks);
+		}
+
+		volhdr->device_size = vol_size;
+		volhdr->num_clusters = new_num_blks;
+		*update = true;
+	}
+
+	ret = 1;
+
+bail:
+	safefree(bitmap);
+	return ret;
+}				/* process_new_volsize */

Added: trunk/format/resizeocfs.1.in
===================================================================
--- trunk/format/resizeocfs.1.in	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/format/resizeocfs.1.in	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,72 @@
+.TH "resizeocfs" "19" "January 2004" "Version @VERSION@" "OCFS Manual Pages"
+.SH "NAME"
+resizeocfs \- Change Filesystem Metadata and resize existing OCFS volume.
+.SH "SYNOPSIS"
+\fBresizeocfs\fR [\-F] [\-g gid] [\-h] [\-l] [\-n] [\-N nodenum] [\-p permissions] [\-q] [\-S size] [\-u uid] [\-V] device
+.SH "DESCRIPTION"
+.PP 
+\fBresizeocfs\fR is used to maintain metadata information in an OCFS file system or to resize it. This command should be used carefully as it may affect applications that have access to the filesystem.
+.SH "OPTIONS"
+.TP
+\fB\-F\fR 
+Force resize existing OCFS volume.
+
+.TP
+\fB\-g\fR \fIgid\fR 
+Change the group ID for the root directory. On mount time, it will
+automatically assign the \fIgid\fR specified by this parameter to the mount
+point. One may use the \fIgid\fR or the group name(i.e:1011 or \fIdba\fR).
+
+.TP
+\fB\-h\fR 
+Help. 
+
+.TP
+\fB\-l\fR 
+List all the node config slots. With this command, one can list all nodes that once mounted the specified OCFS device.
+
+.TP
+\fB\-n\fR 
+Query only. Will not perform any change to the filesystem.
+
+.TP
+\fB\-N\fR \fInodenum\fR
+Node config slot be to be cleared. This is used to remove a specific node that
+used to be part of the cluster from the used slots list. Only one slot can be
+cleared at the time.
+
+.TP
+\fB\-p\fR \fINNNN\fR
+Permissions \fINNNN\fR for the root directory. On mount, it will automatcially
+assign the permission specified by this parameter to the mount point.
+
+.TP
+\fB\-q\fR 
+Quiet execution.
+
+.TP
+\fB\-S\fR \fIsize\fR
+Volume \fIsize\fR for the root directory, e.g., 50G (M for mega, G for giga, T
+for tera).
+
+.TP
+\fB\-u\fR \fIuid\fR
+Change the user ID owner of the root directory. On mount time, it will
+automatcially assign \fIuid\fR specified by this parameter to the mount
+point. One may use the \fIuid\fR or the username (i.e.:1011 or \fIoracle\fR).
+
+.TP
+\fB\-V\fR 
+Print version and exit.
+
+.SH "BUGS"
+Stuff.
+
+.SH "SEE ALSO"
+.BR ocfs(5)
+
+.SH "AUTHORS"
+Oracle Corporation
+
+.SH "COPYRIGHT"
+Copyright \(co 2002 Oracle Corporation

Added: trunk/fsck/Cscope.make
===================================================================
--- trunk/fsck/Cscope.make	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/fsck/Cscope.make	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,9 @@
+cscope:
+	rm -f cscope.*
+	echo "-k" >> cscope.files
+	echo "-I ../../ocfs2/Common/inc" >> cscope.files
+	echo "-I ../../ocfs2/Linux/inc" >> cscope.files
+	find . -name '*.c' -print >>cscope.files
+	find . -name '*.h' -print >>cscope.files
+	find ../libocfs -name '*.h' -print >>cscope.files
+	cscope -b

Added: trunk/fsck/Makefile
===================================================================
--- trunk/fsck/Makefile	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/fsck/Makefile	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,67 @@
+TOPDIR = ..
+
+include $(TOPDIR)/Preamble.make
+
+MANS = fsck.ocfs.1
+
+SBIN_PROGRAMS = fsck.ocfs
+DIST_FILES = mkgetconst fsck.h classes.h  defaults.h fsck_print.h layout.h sig.h verify.h mkgetconst classes.c parse fsck.ocfs.1.in
+
+ifdef OCFS_DEBUG
+  OPTS = -g
+endif
+
+WARNINGS = -Wall -Wstrict-prototypes -Wno-format -Wmissing-prototypes \
+           -Wmissing-declarations
+
+LIBOCFS_LIBS = -L$(TOPDIR)/libocfs -locfs
+LIBOCFS_CFLAGS = -pthread -I$(TOPDIR)/libocfs
+
+CFLAGS = $(OPTS) -fno-strict-aliasing $(WARNINGS) $(LIBOCFS_CFLAGS)
+INCLUDES = -I. -I$(TOPDIR)/libocfs/Common/inc -I$(TOPDIR)/libocfs/Linux/inc
+
+DEFINES = -DLINUX -DUSERSPACE_TOOL -DSHOW_INVALID_VALUES -DFSCK_OCFS
+
+OPTIMIZE = -O2
+
+ifeq ($(OCFS_PROCESSOR),x86_64)
+  CFLAGS += -m64
+endif
+ifeq ($(OCFS_PROCESSOR),ia64)
+endif
+ifeq ($(OCFS_PROCESSOR),i686)
+  DEFINES += -D__ILP32__
+endif
+
+CFLAGS += $(OPTIMIZE)
+
+ifdef OCFS_DEBUG
+  DEFINES += -DDEBUG
+endif
+
+GLIB_OBJS = verify.o fsck_io.o class_print.o class_rw.o fsck_print.o sig.o layout.o defaults.o
+
+## FIXME: make real later
+VERSION_FILES = fsck.c verify.c fsck_io.c class_print.c class_rw.c fsck_print.c sig.c layout.c defaults.c ver.c parse.c
+VERSION_SRC = ver.c
+VERSION_PREFIX = FSCK
+
+parse: parse.c
+	gcc $(INCLUDES) -D_GNU_SOURCE parse.c -o $@
+
+classes.c: parse
+	export COMMON_HEADERS=$(TOPDIR)/libocfs/Common/inc; cat $(TOPDIR)/libocfs/Common/inc/ocfsdisk.h $(TOPDIR)/libocfs/Common/inc/ocfsvol.h | ./parse > $@
+
+classes.o: classes.c
+	$(CC) $(CFLAGS) $(INCLUDES) $(DEFINES) $(GLIB_CFLAGS) -o $@ -c $<
+
+fsck.o: fsck.c
+	$(CC) $(CFLAGS) $(INCLUDES) $(GLIB_CFLAGS) $(DEFINES) -DUSE_MALLOC_ALIGNED $(VERMAGIC) -o $@ -c $<
+
+$(GLIB_OBJS): %.o: %.c
+	$(CC) $(CFLAGS) $(INCLUDES) $(GLIB_CFLAGS) $(DEFINES) -DUSE_MALLOC_ALIGNED $(VERMAGIC) -o $@ -c $<
+
+fsck.ocfs: classes.o fsck.o $(GLIB_OBJS) ver.o
+	$(LINK) -static $(GLIB_LIBS) $(LIBOCFS_LIBS)
+
+include $(TOPDIR)/Postamble.make

Added: trunk/fsck/class_print.c
===================================================================
--- trunk/fsck/class_print.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/fsck/class_print.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,96 @@
+/*
+ * class_print.c
+ *
+ * generic print for structures in ocfs file system check utility
+ *
+ * Copyright (C) 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Sunil Mushran
+ */
+
+#include "fsck.h"
+
+/*
+ * print_class_member()
+ *
+ */
+int print_class_member(char *buf, ocfs_class *cl, ocfs_class_member *mbr,
+		       FILE *out, bool bad)
+{
+	GString *gs = NULL;
+	int ret;
+	char *inval_str = "";
+
+	ret = mbr->to_string(&gs, buf, &mbr->type);
+
+	if (ret != 0 || bad)
+		inval_str = "<INVALID VALUE> ";
+	    
+	fprintf(out, "%s: %s%s", mbr->name, inval_str, gs==NULL ? "NULL" : gs->str);
+	if (gs)
+		g_string_free(gs, true);
+	
+	return ret;
+}				/* print_class_member */
+
+/*
+ * _print_class()
+ *
+ */
+int _print_class(char *buf, ocfs_class *cl, FILE *out, bool num, GHashTable *ht)
+{
+	int ret = 0, i, bad;
+
+	bad = 0;
+	fprintf(out, "\n%s\n=================================\n", cl->name);
+	for (i=0; i<cl->num_members; i++)
+	{
+		bool fail;
+		ocfs_class_member *mbr = &(cl->members[i]);
+
+		fail = (g_hash_table_lookup(ht, GINT_TO_POINTER(i)) != NULL);
+		if (num)
+			fprintf(out, "%3d. ", i+1);
+
+		if (print_class_member(buf, cl, mbr, out, fail) != 0)
+		{
+			bad++;
+			ret = -1;
+		}
+		fprintf(out, "\n");
+	}
+
+	if (ret == -1)
+		LOG_ERROR("%d bad fields total", bad);
+
+	return ret;
+}				/* _print_class */
+
+extern ocfsck_context ctxt;
+
+/*
+ * print_class()
+ *
+ */
+int print_class(char *buf, ocfs_class *cl, FILE *out, GHashTable *ht)
+{
+	if (ctxt.write_changes)
+		return _print_class(buf, cl, out, true, ht);
+	else
+		return _print_class(buf, cl, out, false, ht);
+}				/* print_class */

Added: trunk/fsck/class_rw.c
===================================================================
--- trunk/fsck/class_rw.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/fsck/class_rw.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,1890 @@
+/*
+ * class_rw.c
+ *
+ * reader-writer functions for each type
+ *
+ * Copyright (C) 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Sunil Mushran
+ */
+
+/*****************************************************
+   Implement a type reader-writer function for each type
+
+   Create some kind of type array[] for each class or
+   change the one i already have
+
+   Develop an opaque iterator object that deals with running
+   thru each thing in this type array for editing class
+
+   Process:
+
+   * Verify the whole structure at once: this should
+     probably return the number of bad fields, should
+     probably pass the opaque structure, maybe the
+     opaque can hold each of the suggested values for
+     each bad entry?
+
+   * Iterate w/the opaque thru the print() function,
+     showing something for each messed up field
+
+   * Should the edit() iterate thru all of them?, or
+     know to get at one by index# ??
+ 
+*****************************************************/
+
+#include "fsck.h"
+#include "classes.h"  
+
+// for now, ultraslow-nonhashed-stinkyperformance
+// eh, who cares
+ocfs_class_member * find_class_member(ocfs_class *cl, const char *name, int *idx)
+{
+	int i;
+	ocfs_class_member *ret;
+
+	*idx = -1;
+	for (i=0; i < cl->num_members; i++)
+	{
+		ret = &(cl->members[i]);
+		if (strcmp(ret->name, name)==0)
+		{
+			*idx = i;
+			return ret;
+		}
+	}
+	return NULL;
+}
+	
+	
+// ATTRIBS: __u32
+int _attribs_valid(void *top, typeinfo *info)
+{
+	__u32 attribs = G_STRUCT_MEMBER(__u32, top, info->off);
+	if (!(attribs & (OCFS_ATTRIB_DIRECTORY| OCFS_ATTRIB_FILE_CDSL| OCFS_ATTRIB_CHAR|
+			 OCFS_ATTRIB_BLOCK| OCFS_ATTRIB_REG| OCFS_ATTRIB_FIFO|
+			 OCFS_ATTRIB_SYMLINK| OCFS_ATTRIB_SOCKET)) &&
+	    attribs != 0)
+	{
+		return -1;
+	}
+	return 0;
+}
+
+int _attribs_to_string_u32(GString **retval, void *top, typeinfo *info)
+{
+	__u32 attribs;
+	
+	attribs = G_STRUCT_MEMBER(__u32, top, info->off);
+	if (_attribs_valid(top, info) == -1)
+	{
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "%u", attribs);
+#endif
+		return -1;
+	}
+
+	*retval = g_string_new("");
+	if (attribs & OCFS_ATTRIB_FILE_CDSL)
+		g_string_append(*retval, "cdsl ");
+
+	switch (attribs & ~OCFS_ATTRIB_FILE_CDSL)
+	{
+		case OCFS_ATTRIB_DIRECTORY:
+			g_string_append(*retval, "directory");
+			break;
+		case OCFS_ATTRIB_CHAR:
+			g_string_append(*retval, "character device");
+			break;
+		case OCFS_ATTRIB_BLOCK:
+			g_string_append(*retval, "block device");
+			break;
+		case OCFS_ATTRIB_FIFO:
+			g_string_append(*retval, "fifo");
+			break;
+		case OCFS_ATTRIB_SYMLINK:
+			g_string_append(*retval, "symlink");
+			break;
+		case OCFS_ATTRIB_SOCKET:
+			g_string_append(*retval, "socket");
+			break;
+		default:
+		case OCFS_ATTRIB_REG:
+			g_string_append(*retval, "regular file");
+			break;
+	}
+	
+	return 0;
+}
+
+int _string_to_attribs_u32(char *newval, void *top, typeinfo *info)
+{
+	__u32 attribs = 0;
+
+	if (strcasecmp(newval, "dir")==0)
+		attribs |= OCFS_ATTRIB_DIRECTORY;
+	else if (strcasecmp(newval, "char")==0)
+		attribs |= OCFS_ATTRIB_CHAR;
+	else if (strcasecmp(newval, "block")==0)
+		attribs |= OCFS_ATTRIB_BLOCK;
+	else if (strcasecmp(newval, "reg")==0)
+		attribs |= OCFS_ATTRIB_REG;
+	else if (strcasecmp(newval, "fifo")==0)
+		attribs |= OCFS_ATTRIB_FIFO;
+	else if (strcasecmp(newval, "symlink")==0)
+		attribs |= OCFS_ATTRIB_SYMLINK;
+	else if (strcasecmp(newval, "socket")==0)
+		attribs |= OCFS_ATTRIB_SOCKET;
+	else if (strcasecmp(newval, "cdsl-dir")==0)
+		attribs |= (OCFS_ATTRIB_DIRECTORY|OCFS_ATTRIB_FILE_CDSL);
+	else if (strcasecmp(newval, "cdsl-reg")==0)
+		attribs |= (OCFS_ATTRIB_REG|OCFS_ATTRIB_FILE_CDSL);
+	else
+		return -1;
+
+	G_STRUCT_MEMBER(__u32, top, info->off) = attribs;
+	return 0;
+}
+
+char * _get_attribs_helptext(typeinfo *info)
+{
+	return strdup("one of: dir char block reg fifo symlink socket cdsl-dir cdsl-reg");
+}
+
+
+// BOOL: __s32 __u8 bool
+int _bool_valid(void *top, typeinfo *info)
+{
+	__s32 b = G_STRUCT_MEMBER(__s32, top, info->off);
+	if (b != 0 && b != 1)
+		return -1;
+	return 0;
+}
+
+int _bool_to_string_s32(GString **retval, void *top, typeinfo *info)
+{
+	__s32 val = 0;
+
+	val = G_STRUCT_MEMBER(__s32, top, info->off);
+	if (_bool_valid(top, info) == -1)
+	{
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "%d", val);
+#endif
+		return -1;
+	}
+	*retval = g_string_new("");
+	g_string_append(*retval, val ? "TRUE" : "FALSE");
+
+	return 0;
+}
+
+int _string_to_bool_s32(char *newval, void *top, typeinfo *info)
+{
+	__s32 val;
+
+	if (strcasecmp(newval, "true")==0)
+		val = 1;
+	else if (strcasecmp(newval, "false")==0)
+		val = 0;
+	else
+		return -1;
+
+	G_STRUCT_MEMBER(__s32, top, info->off) = val;
+
+	return 0;
+}
+
+int _bool_to_string_u8(GString **retval, void *top, typeinfo *info)
+{
+	__u8 val = 0;
+
+	val = G_STRUCT_MEMBER(__u8, top, info->off);
+	if (_bool_valid(top, info) == -1)
+	{
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "%u", val);
+#endif
+		return -1;
+	}
+	*retval = g_string_new("");
+	g_string_append(*retval, val ? "TRUE" : "FALSE");
+
+	return 0;
+}
+
+int _string_to_bool_u8(char *newval, void *top, typeinfo *info)
+{
+	__u8 val;
+
+	if (strcasecmp(newval, "true")==0)
+		val = 1;
+	else if (strcasecmp(newval, "false")==0)
+		val = 0;
+	else
+		return -1;
+
+	G_STRUCT_MEMBER(__u8, top, info->off) = val;
+
+	return 0;
+}
+
+int _bool_to_string_bool(GString **retval, void *top, typeinfo *info)
+{
+	return _bool_to_string_s32(retval, top, info);
+}
+
+int _string_to_bool_bool(char *newval, void *top, typeinfo *info)
+{
+	return _string_to_bool_s32(newval, top, info);
+}
+
+char * _get_bool_helptext(typeinfo *info)
+{
+	return strdup("TRUE or FALSE");
+}
+
+
+// CLUSTERSIZE: __u64 
+int _clustersize_valid(void *top, typeinfo *info)
+{
+	__u64 cs = G_STRUCT_MEMBER(__u64, top, info->off);
+	if (cs==4096 || cs==8192 || cs==16384 || cs==32768 ||
+	    cs==65536 || cs==131072 || cs==262144 ||
+	    cs==524288 || cs==1048576)
+	{
+		return 0;
+	}
+	return -1;
+}
+
+int _clustersize_to_string_u64(GString **retval, void *top, typeinfo *info)
+{
+	__u64 csize;
+	
+	csize = G_STRUCT_MEMBER(__u64, top, info->off);
+
+	if (_clustersize_valid(top, info) != -1)
+	{
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "%llu", csize);
+		return 0;
+	}
+
+#ifdef SHOW_INVALID_VALUES
+	*retval = g_string_new("");
+	g_string_sprintf(*retval, "%llu", csize);
+#endif
+	return -1;
+}
+
+int _string_to_clustersize_u64(char *newval, void *top, typeinfo *info)
+{
+	__u64 csize;
+	
+	csize = strtoull (newval, NULL, 10);
+	if (csize==4096 || csize==8192 || csize==16384 || csize==32768 ||
+	    csize==65536 || csize==131072 || csize==262144 ||
+	    csize==524288 || csize==1048576)
+	{
+		G_STRUCT_MEMBER(__u64, top, info->off) = csize;
+		return 0;
+	}
+
+	return -1;
+}
+
+char * _get_clustersize_helptext(typeinfo *info)
+{
+	return strdup("one of 4096,8192,16384,32768,65536,131072,262144,524288,1048576");
+}
+
+
+
+// DATE: __u64
+int _date_valid(void *top, typeinfo *info)
+{
+	return 0;
+}
+
+int _date_to_string_u64(GString **retval, void *top, typeinfo *info)
+{
+	__u64 sec;
+	char *t, *t2;
+
+	sec = G_STRUCT_MEMBER(__u64, top, info->off);
+	if (_date_valid(top, info) == -1)
+	{
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "%llu", sec);
+#endif
+		return -1;
+	}
+	*retval = g_string_new("");
+	t = ctime((time_t *) &sec);
+	t2 = t;
+	while (*t2)
+	{
+       		if (*t2=='\n' || *t2=='\r')
+			*t2 = ' ';
+		t2++;
+	}
+	g_string_append(*retval, t);
+	return 0;
+}
+
+int _string_to_date_u64(char *newval, void *top, typeinfo *info)
+{
+	__u64 sec;
+	struct tm t;
+	int ret = -1;
+	char mo[4];
+	int d, y, h, mi, s, i;
+	char *months[] = { "JAN", "FEB", "MAR", "APR", "MAY", "JUN", 
+			   "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };
+
+	memset(&t, 0, sizeof(struct tm));
+
+	if (sscanf(newval, "%3s %d %d %d:%d:%d", mo, &d, &y, &h, &mi, &s) == 6)
+	{
+		g_strup(mo);
+		if (d<=31 && y>=1900 && h<=23 && mi<=59 && s<=59)
+		{
+			for (i=0; i<12; i++)
+			{
+				if (strcmp(mo, months[i])==0)
+				{
+					t.tm_mon = i+1;
+					t.tm_sec = s;
+					t.tm_min = mi;
+					t.tm_hour = h;
+					t.tm_year = y-1900;
+					sec = mktime(&t);
+					G_STRUCT_MEMBER(__u64, top, info->off) = sec;
+					ret = 0;
+				}
+			}
+		}
+	}
+
+	return ret;
+}
+
+char * _get_date_helptext(typeinfo *info)
+{
+	return strdup("Jan 28 2003 22:30:32");
+}
+
+
+// DIRFLAG: __u8
+int _dirflag_valid(void *top, typeinfo *info)
+{
+	__u8 flag = G_STRUCT_MEMBER(__u8, top, info->off);
+	if (flag != 0 && flag != DIR_NODE_FLAG_ROOT)
+		return -1;
+	return 0;			
+}
+
+int _dirflag_to_string_u8(GString **retval, void *top, typeinfo *info)
+{
+	__u8 flag;
+	flag = G_STRUCT_MEMBER(__u8, top, info->off);
+	if (_dirflag_valid(top, info) == -1)
+	{
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "%u", flag);
+#endif
+		return -1;
+	}
+	*retval = g_string_new("");
+	g_string_append(*retval, flag & DIR_NODE_FLAG_ROOT ? "DIR_NODE_FLAG_ROOT" : "");
+	return 0;
+}
+
+int _string_to_dirflag_u8(char *newval, void *top, typeinfo *info)
+{
+	__u8 flag=0;
+
+	if (strcasecmp(newval, "DIR_NODE_FLAG_ROOT")==0)
+		flag |= DIR_NODE_FLAG_ROOT;
+
+	G_STRUCT_MEMBER(__u8, top, info->off) = flag;
+	return 0;
+}
+
+char * _get_dirflag_helptext(typeinfo *info)
+{
+	return strdup("DIR_NODE_FLAG_ROOT or NONE");
+}
+
+
+// DIRINDEX: __u8[256]
+int _dirindex_valid(void *top, typeinfo *info)
+{
+	// this one is tough since we don't want duplicate
+	// values, but we don't know the upper bound here
+	// so we can't check
+	if (info->array_size != 256)
+		return -1;
+	
+	return 0;	
+}
+
+int _dirindex_to_string_u8(GString **retval, void *top, typeinfo *info)
+{
+	int i;
+	__u8 *buf = NULL;
+	__u8 *arr;
+
+	if (info->array_size <= 0)
+		return -1;
+
+	arr =  G_STRUCT_MEMBER_P(top, info->off);
+
+	if (_dirindex_valid(top, info) == -1) {
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "[%u, ...]", arr[0]);
+#endif
+		return -1;
+	}
+
+	if ((buf = malloc(info->array_size + 1)) == NULL) {
+		LOG_ERROR("unable to allocate %d bytes of memory",
+			  info->array_size + 1);
+		goto bail;
+	}
+
+	memcpy(buf, arr, info->array_size);
+
+	*retval = g_string_new("");
+	for (i=0; i<info->array_size; i++) {
+		g_string_sprintfa((*retval), "%d ", buf[i]);
+	}
+
+      bail:
+	free(buf);
+	return 0;
+}
+
+int _string_to_dirindex_u8(char *newval, void *top, typeinfo *info)
+{
+	int ret = -1;
+	char **arr;
+	__u8 index[256];
+	int i;
+
+	memset(&(index[0]), 0, 256);
+	arr = g_strsplit(newval, ":", 0);
+
+	for (i=0; i<256; i++)
+	{  
+		int tmp;
+		if (arr[i]==NULL)
+			break;
+	        tmp = atoi(arr[i]);
+		if (tmp<0 || tmp>255)
+			goto bail;
+		index[i] = (__u8)tmp;
+	}
+	memcpy(G_STRUCT_MEMBER(__u8 *, top, info->off), index, 256);
+	ret = 0;
+
+bail:
+	g_strfreev(arr);
+	return ret;
+}
+
+char * _get_dirindex_helptext(typeinfo *info)
+{
+	return strdup("a string like 5:7:1:2:4:255:... with each index between 0 and 255");
+}
+
+
+// DIRNODEINDEX: __s8 __u8
+int _dirnodeindex_valid(void *top, typeinfo *info)
+{
+	return 0;
+}
+
+int _dirnodeindex_to_string_s8(GString **retval, void *top, typeinfo *info)
+{
+	__s8 idx;
+	idx = G_STRUCT_MEMBER(__s8, top, info->off);
+	if (_dirnodeindex_valid(top, info) == -1)
+	{
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "%d", idx);
+#endif
+		return -1;
+	}
+	*retval = g_string_new("");
+	if (idx==INVALID_DIR_NODE_INDEX)
+		g_string_append(*retval, "INVALID_DIR_NODE_INDEX");
+	else
+		g_string_sprintf(*retval, "%d", idx);
+	return 0;
+}
+
+int _string_to_dirnodeindex_s8(char *newval, void *top, typeinfo *info)
+{
+	int tmp;
+	char *ptr;
+
+	if (strcasecmp(newval, "INVALID_DIR_NODE_INDEX")==0)
+		tmp = INVALID_DIR_NODE_INDEX;
+	else
+	{
+		tmp = strtol(newval, &ptr, 10);
+		if (ptr==newval || tmp<-1 || tmp>255)
+			return -1;
+	}
+
+	G_STRUCT_MEMBER(__s8, top, info->off) = (__s8)tmp;
+	return 0;
+}
+
+/* the signed and unsigned are the same?!  
+ * why yes!  because we like to put -1 into the unsigned one too!
+ * /me pokes eyes out
+ */
+int _dirnodeindex_to_string_u8(GString **retval, void *top, typeinfo *info)
+{
+	return _dirnodeindex_to_string_s8(retval, top, info);
+}
+
+int _string_to_dirnodeindex_u8(char *newval, void *top, typeinfo *info)
+{
+	return _string_to_dirnodeindex_s8(newval, top, info);
+}
+
+char * _get_dirnodeindex_helptext(typeinfo *info)
+{
+	if (info->is_signed)
+		return strdup("some number between -1 and 255, or INVALID_DIR_NODE_INDEX");
+	else
+		return strdup("some number between 0 and 255, or INVALID_DIR_NODE_INDEX");
+}
+
+
+
+// DISKPTR: __s64 __u64
+int _diskptr_valid(void *top, typeinfo *info)
+{
+	if (info->is_signed)
+	{
+		__s64 s = G_STRUCT_MEMBER(__s64, top, info->off);
+		if (s != INVALID_NODE_POINTER && (s % 512))
+			return -1;
+	}
+	else
+	{
+		__u64 u = G_STRUCT_MEMBER(__u64, top, info->off);
+		if (u != INVALID_NODE_POINTER && (u % 512))
+			return -1;
+	}
+	return 0;
+}
+
+// more junk here: (I think) it's really always a __u64 with -1 being a special case :(
+int _diskptr_to_string_s64(GString **retval, void *top, typeinfo *info)
+{
+	__s64 ptr;
+	ptr = G_STRUCT_MEMBER(__s64, top, info->off);
+	if (_diskptr_valid(top, info) == -1)
+	{
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "%u.%u", HILO(ptr));
+#endif
+		return -1;
+	}
+	*retval = g_string_new("");
+	if (ptr==INVALID_NODE_POINTER)
+		g_string_append(*retval, "INVALID_NODE_POINTER");
+	else
+		g_string_sprintf(*retval, "%u.%u", HILO(ptr));
+	return 0;
+}
+
+int _string_to_diskptr_s64(char *newval, void *top, typeinfo *info)
+{
+	__s64 ptr;
+	char *bad;
+
+	if (strcasecmp(newval, "INVALID_NODE_POINTER")==0)
+		ptr = INVALID_NODE_POINTER;
+	else
+	{
+		ptr = strtoll(newval, &bad, 10);
+		if (bad==newval || ptr<-1)
+			return -1;
+	}	
+	G_STRUCT_MEMBER(__s64, top, info->off) = ptr;
+	return 0;
+}
+
+int _diskptr_to_string_u64(GString **retval, void *top, typeinfo *info)
+{
+	return _diskptr_to_string_s64(retval, top, info);
+}
+
+int _string_to_diskptr_u64(char *newval, void *top, typeinfo *info)
+{
+	return _string_to_diskptr_s64(newval, top, info);
+}
+
+char * _get_diskptr_helptext(typeinfo *info)
+{
+	return strdup("a 64-bit offset, or INVALID_NODE_POINTER");
+}
+
+
+// EXTENTTYPE: __u32
+int _extenttype_valid(void *top, typeinfo *info)
+{
+	__u32 type = G_STRUCT_MEMBER(__u32, top, info->off);
+	if (type != OCFS_EXTENT_DATA && type != OCFS_EXTENT_HEADER)
+		return -1;
+	return 0;
+}
+
+int _extenttype_to_string_u32(GString **retval, void *top, typeinfo *info)
+{
+	__u32 type;
+	type = G_STRUCT_MEMBER(__u32, top, info->off);
+
+	if (_extenttype_valid(top, info) == -1)
+	{
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "%u", type);
+#endif
+		return -1;
+	}
+
+	if (type == OCFS_EXTENT_DATA)
+		*retval = g_string_new("OCFS_EXTENT_DATA");
+	else
+		*retval = g_string_new("OCFS_EXTENT_HEADER");
+
+	return 0;
+}
+
+int _string_to_extenttype_u32(char *newval, void *top, typeinfo *info)
+{
+	__u32 type;
+
+	if (strcasecmp(newval, "OCFS_EXTENT_HEADER")==0)
+		type = OCFS_EXTENT_HEADER;
+	else if (strcasecmp(newval, "OCFS_EXTENT_DATA")==0)
+		type = OCFS_EXTENT_DATA;
+	else 
+		return -1;
+
+	G_STRUCT_MEMBER(__u32, top, info->off) = type;
+
+	return 0;
+}
+
+char * _get_extenttype_helptext(typeinfo *info)
+{
+	return strdup("OCFS_EXTENT_HEADER or OCFS_EXTENT_DATA");
+}
+
+
+// FILEFLAG: __u32
+int _fileflag_valid(void *top, typeinfo *info)
+{
+	__u32 flag = G_STRUCT_MEMBER(__u32, top, info->off);
+	if (flag!=0 && ! (flag & (FLAG_FILE_CREATE|FLAG_FILE_EXTEND|
+				  FLAG_FILE_DELETE|FLAG_FILE_RENAME|
+				  FLAG_FILE_UPDATE|FLAG_FILE_CREATE_DIR|
+				  FLAG_FILE_UPDATE_OIN|FLAG_FILE_RELEASE_MASTER|
+				  FLAG_FILE_RELEASE_CACHE|FLAG_FILE_CREATE_CDSL|
+				  FLAG_FILE_DELETE_CDSL|FLAG_FILE_CHANGE_TO_CDSL|
+				  FLAG_FILE_TRUNCATE)))
+		return -1;
+	return 0;
+}
+
+int _fileflag_to_string_u32(GString **retval, void *top, typeinfo *info)
+{
+	__u32 flag;
+
+	flag = G_STRUCT_MEMBER(__u32, top, info->off);
+	if (_fileflag_valid(top, info) == -1)
+	{
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "%u", flag);
+#endif
+		return -1;
+	}
+	    
+	*retval = g_string_new("");
+	if (flag & FLAG_FILE_CREATE)
+		g_string_append(*retval, "FLAG_FILE_CREATE ");
+	if (flag & FLAG_FILE_EXTEND)
+		g_string_append(*retval, "FLAG_FILE_EXTEND ");
+	if (flag & FLAG_FILE_DELETE)
+		g_string_append(*retval, "FLAG_FILE_DELETE ");
+	if (flag & FLAG_FILE_RENAME)
+		g_string_append(*retval, "FLAG_FILE_RENAME ");
+	if (flag & FLAG_FILE_UPDATE)
+		g_string_append(*retval, "FLAG_FILE_UPDATE ");
+	if (flag & FLAG_FILE_CREATE_DIR)
+		g_string_append(*retval, "FLAG_FILE_CREATE_DIR ");
+	if (flag & FLAG_FILE_UPDATE_OIN)
+		g_string_append(*retval, "FLAG_FILE_UPDATE_OIN ");
+	if (flag & FLAG_FILE_RELEASE_MASTER)
+		g_string_append(*retval, "FLAG_FILE_RELEASE_MASTER ");
+	if (flag & FLAG_FILE_RELEASE_CACHE)
+		g_string_append(*retval, "FLAG_FILE_RELEASE_CACHE ");
+	if (flag & FLAG_FILE_CREATE_CDSL)
+		g_string_append(*retval, "FLAG_FILE_CREATE_CDSL ");
+	if (flag & FLAG_FILE_DELETE_CDSL)
+		g_string_append(*retval, "FLAG_FILE_DELETE_CDSL ");
+	if (flag & FLAG_FILE_CHANGE_TO_CDSL)
+		g_string_append(*retval, "FLAG_FILE_CHANGE_TO_CDSL ");
+	if (flag & FLAG_FILE_TRUNCATE)
+		g_string_append(*retval, "FLAG_FILE_TRUNCATE ");
+	if ((*retval)->len > 0)
+		g_string_truncate(*retval, (*retval)->len - 1);
+
+	return 0;
+}
+
+int _string_to_fileflag_u32(char *newval, void *top, typeinfo *info)
+{
+	int ret = -1;
+	char **arr;
+	__u32 flag;
+
+	flag = 0;
+	arr = g_strsplit(newval, " ", 0);
+
+	while (*arr!=NULL)
+	{  
+		if (strcasecmp(*arr, "FLAG_FILE_CREATE")==0)
+			flag |= FLAG_FILE_CREATE;
+		else if (strcasecmp(*arr, "FLAG_FILE_EXTEND")==0)
+			flag |= FLAG_FILE_EXTEND;
+		else if (strcasecmp(*arr, "FLAG_FILE_DELETE")==0)
+			flag |= FLAG_FILE_DELETE;
+		else if (strcasecmp(*arr, "FLAG_FILE_RENAME")==0)
+			flag |= FLAG_FILE_RENAME;
+		else if (strcasecmp(*arr, "FLAG_FILE_UPDATE")==0)
+			flag |= FLAG_FILE_UPDATE;
+		else if (strcasecmp(*arr, "FLAG_FILE_CREATE_DIR")==0)
+			flag |= FLAG_FILE_CREATE_DIR;
+		else if (strcasecmp(*arr, "FLAG_FILE_UPDATE_OIN")==0)
+			flag |= FLAG_FILE_UPDATE_OIN;
+		else if (strcasecmp(*arr, "FLAG_FILE_RELEASE_MASTER")==0)
+			flag |= FLAG_FILE_RELEASE_MASTER;
+		else if (strcasecmp(*arr, "FLAG_FILE_RELEASE_CACHE")==0)
+			flag |= FLAG_FILE_RELEASE_CACHE;
+		else if (strcasecmp(*arr, "FLAG_FILE_CREATE_CDSL")==0)
+			flag |= FLAG_FILE_CREATE_CDSL;
+		else if (strcasecmp(*arr, "FLAG_FILE_DELETE_CDSL")==0)
+			flag |= FLAG_FILE_DELETE_CDSL;
+		else if (strcasecmp(*arr, "FLAG_FILE_CHANGE_TO_CDSL")==0)
+			flag |= FLAG_FILE_CHANGE_TO_CDSL;
+		else if (strcasecmp(*arr, "FLAG_FILE_TRUNCATE")==0)
+			flag |= FLAG_FILE_TRUNCATE;
+		arr++;
+	}
+	G_STRUCT_MEMBER(__u32, top, info->off) = flag;
+	ret = 0;
+	g_strfreev(arr);
+	return ret;
+}
+
+char * _get_fileflag_helptext(typeinfo *info)
+{
+	return strdup("one or more of: FLAG_FILE_CREATE FLAG_FILE_EXTEND "
+		      "FLAG_FILE_DELETE FLAG_FILE_RENAME FLAG_FILE_UPDATE "
+		      "FLAG_FILE_CREATE_DIR FLAG_FILE_UPDATE_OIN "
+		      "FLAG_FILE_RELEASE_MASTER FLAG_FILE_RELEASE_CACHE "
+		      "FLAG_FILE_CREATE_CDSL FLAG_FILE_DELETE_CDSL "
+		      "FLAG_FILE_CHANGE_TO_CDSL FLAG_FILE_TRUNCATE");
+}
+
+// GID: __u32
+int _gid_valid(void *top, typeinfo *info)
+{
+#ifdef ARE_WE_SURE_WE_WANT_TO_DO_THIS
+	struct group *gr;
+	__u32 id = G_STRUCT_MEMBER(__u32, top, info->off);
+
+	gr = getgrgid(id);
+	if (gr == NULL)
+		return -1;
+#endif
+	return 0;
+}
+
+int _gid_to_string_u32(GString **retval, void *top, typeinfo *info)
+{
+	__u32 id;
+	struct group *gr;
+
+	*retval = g_string_new("");
+	id = G_STRUCT_MEMBER(__u32, top, info->off);
+	
+	if (_gid_valid(top, info) == -1)
+	{
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "%u", id);
+#endif
+		return -1;
+	}
+	gr = getgrgid(id);
+	g_string_sprintf(*retval, "%u (%s)", id,
+			 gr ? gr->gr_name : "unknown group id");
+	return 0;
+}
+
+int _string_to_gid_u32(char *newval, void *top, typeinfo *info)
+{
+	__u32 id;
+	char *bad = NULL;
+	struct group *gr;
+
+	gr = getgrnam(newval);
+	if (gr == NULL)
+	{
+		id = strtoul(newval, &bad, 10);
+		if (bad == newval)
+			return -1;
+	}
+	else
+		id = gr->gr_gid;
+
+	G_STRUCT_MEMBER(__u32, top, info->off) = id;
+	return 0;
+}
+
+char * _get_gid_helptext(typeinfo *info)
+{
+	return strdup("a numeric gid");
+}
+
+// UID: __u32
+int _uid_valid(void *top, typeinfo *info)
+{
+#ifdef ARE_WE_SURE_WE_WANT_TO_DO_THIS
+	struct passwd *pw;
+	__u32 id =  G_STRUCT_MEMBER(__u32, top, info->off);
+
+	pw = getpwuid(id);
+	if (pw == NULL)
+		return -1;
+#endif
+	return 0;
+}
+
+int _uid_to_string_u32(GString **retval, void *top, typeinfo *info)
+{
+	__u32 id;
+	struct passwd *pw;
+
+	*retval = g_string_new("");
+	id = G_STRUCT_MEMBER(__u32, top, info->off);
+	if (_uid_valid(top, info) == -1)
+	{
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "%u", id);
+#endif
+		return -1;
+	}
+	pw = getpwuid(id);
+	g_string_sprintf(*retval, "%u (%s)", id,
+			 pw ? pw->pw_name : "unknown user id");
+	return 0;
+}
+
+int _string_to_uid_u32(char *newval, void *top, typeinfo *info)
+{
+	__u32 id;
+	char *bad = NULL;
+	struct passwd *pw;
+
+	pw = getpwnam(newval);
+	if (pw == NULL)
+	{
+		id = strtoul(newval, &bad, 10);
+		if (bad == newval)
+			return -1;
+	}
+	else
+		id = pw->pw_uid;
+
+	G_STRUCT_MEMBER(__u32, top, info->off) = id;
+	return 0;
+}
+
+char * _get_uid_helptext(typeinfo *info)
+{
+	return strdup("a numeric uid");
+}
+
+// LOCKLEVEL: __u8
+int _locklevel_valid(void *top, typeinfo *info)
+{
+	__u8 lvl = G_STRUCT_MEMBER(__u8, top, info->off);
+	if (lvl != OCFS_DLM_SHARED_LOCK && lvl != OCFS_DLM_EXCLUSIVE_LOCK &&
+	    lvl != OCFS_DLM_ENABLE_CACHE_LOCK && lvl != OCFS_DLM_NO_LOCK)
+		return -1;
+	return 0;
+}
+
+int _locklevel_to_string_u8(GString **retval, void *top, typeinfo *info)
+{
+	__u8 lvl;
+
+	lvl = G_STRUCT_MEMBER(__u8, top, info->off);
+	if (_locklevel_valid(top, info) == -1)
+	{
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "%u", lvl);
+#endif
+		return -1;
+	}
+
+	*retval = g_string_new("");
+	switch (lvl)
+	{
+		case OCFS_DLM_ENABLE_CACHE_LOCK:
+			g_string_append(*retval, "OCFS_DLM_ENABLE_CACHE_LOCK");
+			break;
+		case OCFS_DLM_EXCLUSIVE_LOCK: 
+			g_string_append(*retval, "OCFS_DLM_EXCLUSIVE_LOCK");
+			break;
+		case OCFS_DLM_SHARED_LOCK:
+			g_string_append(*retval, "OCFS_DLM_SHARED_LOCK");
+			break;
+		case OCFS_DLM_NO_LOCK:
+			g_string_append(*retval, "OCFS_DLM_NO_LOCK");
+			break;
+	}
+	return 0;
+}
+
+int _string_to_locklevel_u8(char *newval, void *top, typeinfo *info)
+{
+	__u8 lvl; 
+
+	if (strcasecmp(newval, "OCFS_DLM_NO_LOCK")==0)
+		lvl = OCFS_DLM_NO_LOCK;
+	else if (strcasecmp(newval, "OCFS_DLM_SHARED_LOCK")==0)
+		lvl = OCFS_DLM_SHARED_LOCK;
+	else if (strcasecmp(newval, "OCFS_DLM_EXCLUSIVE_LOCK")==0)
+		lvl = OCFS_DLM_EXCLUSIVE_LOCK;
+	else if (strcasecmp(newval, "OCFS_DLM_ENABLE_CACHE_LOCK")==0)
+		lvl = OCFS_DLM_ENABLE_CACHE_LOCK;
+	else
+		return -1;
+	
+	G_STRUCT_MEMBER(__u8, top, info->off) = lvl;
+	return 0;
+
+}
+
+char * _get_locklevel_helptext(typeinfo *info)
+{
+	return strdup("one of OCFS_DLM_ENABLE_CACHE_LOCK OCFS_DLM_EXCLUSIVE_LOCK "
+		      "OCFS_DLM_SHARED_LOCK OCFS_DLM_NO_LOCK");
+}
+
+// NODEBITMAP: __u64
+int _nodebitmap_valid(void *top, typeinfo *info)
+{
+	__u64 bm = G_STRUCT_MEMBER(__u64, top, info->off);
+	// should have nothing in the upper 32 bits
+	if (bm & 0xffffffff00000000ULL)
+		return -1;
+	return 0;
+}
+
+int _nodebitmap_to_string_u64(GString **retval, void *top, typeinfo *info)
+{
+	__u64 bm;
+	int pos;
+
+	bm = G_STRUCT_MEMBER(__u64, top, info->off);
+
+	if (_nodebitmap_valid(top, info) == -1)
+	{
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "%llu", bm);
+#endif
+		return -1;
+	}
+
+	*retval = g_string_new("");	
+	for (pos=0; pos<32; pos++)
+		g_string_sprintfa(*retval, "%d", (bm & (1 << pos)) ? 1 : 0);
+
+	return 0;
+}
+
+int _string_to_nodebitmap_u64(char *newval, void *top, typeinfo *info)
+{
+	__u64 bm;
+	char *bad = NULL;
+
+	bm = strtol(newval, &bad, 2);
+	if (bad == newval)
+		return -1;
+	G_STRUCT_MEMBER(__u64, top, info->off) = bm;
+	return 0;
+}
+
+char * _get_nodebitmap_helptext(typeinfo *info)
+{
+	return strdup("a 32-node binary map like: "
+		      "01101010011101010101010100101100");
+}
+
+// NODENUM: __u32 __s32
+int _nodenum_valid(void *top, typeinfo *info)
+{
+	__s32 snum = G_STRUCT_MEMBER(__s32, top, info->off);
+	__u32 unum = G_STRUCT_MEMBER(__u32, top, info->off);
+
+	if (info->is_signed)
+	{
+		if (snum < OCFS_INVALID_NODE_NUM || snum > 31)
+			return -1;
+	}
+	else
+	{
+		if (unum > 31 && unum != OCFS_INVALID_NODE_NUM)
+			return -1;
+	}
+			
+	return 0;
+}
+
+int _nodenum_to_string_u32(GString **retval, void *top, typeinfo *info)
+{
+	__u32 num;
+
+	num = G_STRUCT_MEMBER(__u32, top, info->off);
+	if (_nodenum_valid(top, info) == -1)
+	{
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "%u", num);
+#endif
+		return -1;
+	}
+
+	*retval = g_string_new("");
+	if (num == OCFS_INVALID_NODE_NUM)
+		g_string_append(*retval, "OCFS_INVALID_NODE_NUM");
+	else
+		g_string_sprintf(*retval, "%u", num);
+
+	return 0;
+}
+
+int _string_to_nodenum_u32(char *newval, void *top, typeinfo *info)
+{
+	__u32 num;
+	char *bad = NULL;
+
+	if (strcasecmp(newval, "OCFS_INVALID_NODE_NUM")==0)
+		num = OCFS_INVALID_NODE_NUM;
+	else
+		num = strtoul(newval, &bad, 10);
+	if (bad == newval || num<0 || num>31)
+		return -1;
+	G_STRUCT_MEMBER(__u32, top, info->off) = num;
+	return 0;
+}
+
+int _nodenum_to_string_s32(GString **retval, void *top, typeinfo *info)
+{
+	__s32 num;
+
+	num = G_STRUCT_MEMBER(__s32, top, info->off);
+	if (_nodenum_valid(top, info) == -1)
+	{
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "%d", num);
+#endif
+		return -1;
+	}
+
+	*retval = g_string_new("");
+	if (num == OCFS_INVALID_NODE_NUM)
+		g_string_append(*retval, "OCFS_INVALID_NODE_NUM");
+	else
+		g_string_sprintf(*retval, "%d", num);
+
+	return 0;
+}
+
+int _string_to_nodenum_s32(char *newval, void *top, typeinfo *info)
+{
+	__s32 num;
+	char *bad = NULL;
+
+	if (strcasecmp(newval, "OCFS_INVALID_NODE_NUM")==0)
+		num = OCFS_INVALID_NODE_NUM;
+	else
+		num = strtol(newval, &bad, 10);
+	if (bad == newval || num<-1 || num>31)
+		return -1;
+	G_STRUCT_MEMBER(__s32, top, info->off) = num;
+	return 0;
+}
+
+char * _get_nodenum_helptext(typeinfo *info)
+{
+	return strdup("a node number between 0 and 31, or OCFS_INVALID_NODE_NUM");
+}
+
+// PERMS: __u32
+int _perms_valid(void *top, typeinfo *info)
+{
+	return 0;	
+}
+
+int _perms_to_string_u32(GString **retval, void *top, typeinfo *info)
+{
+	__u32 mode;
+
+	mode = G_STRUCT_MEMBER(__u32, top, info->off);
+	if (_perms_valid(top, info) == -1)
+	{
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "%u", mode);
+#endif
+		return -1;
+	}
+
+	*retval = g_string_sized_new(10);
+	g_string_append_c(*retval, '-');
+	g_string_append_c(*retval, mode & S_IRUSR ? 'r' : '-');
+	g_string_append_c(*retval, mode & S_IWUSR ? 'w' : '-');
+	if (mode & S_ISUID)
+		g_string_append_c(*retval, mode & S_IXUSR ? 's' : 'S');
+	else
+		g_string_append_c(*retval, mode & S_IXUSR ? 'x' : '-');
+	
+	g_string_append_c(*retval, mode & S_IRGRP ? 'r' : '-');
+	g_string_append_c(*retval, mode & S_IWGRP ? 'w' : '-');
+	if (mode & S_ISGID)
+		g_string_append_c(*retval, mode & S_IXGRP ? 's' : 'S');
+	else
+		g_string_append_c(*retval, mode & S_IXGRP ? 'x' : '-');
+	
+	g_string_append_c(*retval, mode & S_IROTH ? 'r' : '-');
+	g_string_append_c(*retval, mode & S_IWOTH ? 'w' : '-');
+	if (mode & S_ISVTX)
+		g_string_append_c(*retval, mode & S_IXOTH ? 't' : 'T');
+	else
+		g_string_append_c(*retval, mode & S_IXOTH ? 'x' : '-');
+	return 0;
+}
+
+int _string_to_perms_u32(char *newval, void *top, typeinfo *info)
+{
+	int mode = 0;
+
+	if (strlen(newval)!=10) 
+		return -1;
+
+	if (newval[1] == 'r')
+		mode |= S_IRUSR;
+	if (newval[2] == 'w')
+		mode |= S_IWUSR;
+	if (newval[3] == 'x' || newval[3] == 's')
+		mode |= S_IXUSR;
+	if (newval[3] == 's' || newval[3] == 'S')
+		mode |= S_ISUID;
+
+	if (newval[4] == 'r')
+		mode |= S_IRGRP;
+	if (newval[5] == 'w')
+		mode |= S_IWGRP;
+	if (newval[6] == 'x' || newval[6] == 's')
+		mode |= S_IXGRP;
+	if (newval[6] == 's' || newval[6] == 'S')
+		mode |= S_ISGID;
+
+	if (newval[7] == 'r')
+		mode |= S_IROTH;
+	if (newval[8] == 'w')
+		mode |= S_IWOTH;
+	if (newval[9] == 'x' || newval[9] == 't')
+		mode |= S_IXOTH;
+	if (newval[9] == 't' || newval[9] == 'T')
+		mode |= S_ISVTX;
+
+	G_STRUCT_MEMBER(__u32, top, info->off) = mode;
+
+	return 0;
+}
+
+char * _get_perms_helptext(typeinfo *info)
+{
+	return 	strdup("-rwxrwxrwx  (filetype ignored; x,s,S,t,T allowed)");
+}
+
+// SYNCFLAG: __u32 __u8
+int _syncflag_valid(void *top, typeinfo *info)
+{
+	__u32 sync = G_STRUCT_MEMBER(__u32, top, info->off);
+	if (sync !=0 && !(sync & (OCFS_SYNC_FLAG_VALID|
+				  OCFS_SYNC_FLAG_CHANGE|
+				  OCFS_SYNC_FLAG_MARK_FOR_DELETION|
+				  OCFS_SYNC_FLAG_NAME_DELETED)))
+		return -1;
+	return 0;
+}
+
+int _syncflag_to_string_u32(GString **retval, void *top, typeinfo *info)
+{
+	__u32 sync;
+	sync = G_STRUCT_MEMBER(__u32, top, info->off);
+	if (_syncflag_valid(top, info) == -1)
+	{
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "%u", sync);
+#endif
+		return -1;
+	}
+	
+	*retval = g_string_new("");
+	if (sync == OCFS_SYNC_FLAG_DELETED)
+		g_string_append(*retval, "deleted");
+	if (sync & OCFS_SYNC_FLAG_VALID)
+		g_string_append(*retval, "valid ");
+	if (sync & OCFS_SYNC_FLAG_CHANGE)
+		g_string_append(*retval, "change ");
+	if (sync & OCFS_SYNC_FLAG_MARK_FOR_DELETION)
+		g_string_append(*retval, "mark-del ");
+	if (sync & OCFS_SYNC_FLAG_NAME_DELETED)
+		g_string_append(*retval, "name-del ");
+	return 0;
+}
+
+int _string_to_syncflag_u32(char *newval, void *top, typeinfo *info)
+{
+	__u32 sync = 0;
+	int ret = -1;
+	char **arr;
+
+	arr = g_strsplit(newval, " ", 0);
+
+	while (*arr != NULL)
+	{
+		if (strcasecmp(*arr, "deleted")==0)
+			sync |= OCFS_SYNC_FLAG_DELETED;
+		else if (strcasecmp(*arr, "valid")==0)
+			sync |= OCFS_SYNC_FLAG_VALID;
+		else if (strcasecmp(*arr, "change")==0)
+			sync |= OCFS_SYNC_FLAG_CHANGE;
+		else if (strcasecmp(*arr, "mark-del")==0)
+			sync |= OCFS_SYNC_FLAG_MARK_FOR_DELETION;
+		else if (strcasecmp(*arr, "name-del")==0)
+			sync |= OCFS_SYNC_FLAG_NAME_DELETED;
+		else
+			goto bail;
+		arr++;
+	}
+	G_STRUCT_MEMBER(__u32, top, info->off) = sync;
+	ret = 0;
+bail:
+	g_strfreev(arr);
+	return ret;
+}
+
+int _syncflag_to_string_u8(GString **retval, void *top, typeinfo *info)
+{
+	__u8 sync;
+	sync = G_STRUCT_MEMBER(__u8, top, info->off);
+	if (_syncflag_valid(top, info) == -1)
+	{
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "%u", sync);
+#endif
+		return -1;
+	}
+
+	*retval = g_string_new("");
+	if (sync == OCFS_SYNC_FLAG_DELETED)
+		g_string_append(*retval, "deleted");
+	if (sync & OCFS_SYNC_FLAG_VALID)
+		g_string_append(*retval, "valid ");
+	if (sync & OCFS_SYNC_FLAG_CHANGE)
+		g_string_append(*retval, "change ");
+	if (sync & OCFS_SYNC_FLAG_MARK_FOR_DELETION)
+		g_string_append(*retval, "mark-del ");
+	if (sync & OCFS_SYNC_FLAG_NAME_DELETED)
+		g_string_append(*retval, "name-del ");
+	return 0;
+}
+
+int _string_to_syncflag_u8(char *newval, void *top, typeinfo *info)
+{
+	__u8 sync = 0;
+	int ret = -1;
+	char **arr;
+
+	sync = 0;
+	arr = g_strsplit(newval, " ", 0);
+
+	while (*arr != NULL)
+	{
+		if (strcasecmp(*arr, "deleted")==0)
+			sync |= OCFS_SYNC_FLAG_DELETED;
+		else if (strcasecmp(*arr, "valid")==0)
+			sync |= OCFS_SYNC_FLAG_VALID;
+		else if (strcasecmp(*arr, "change")==0)
+			sync |= OCFS_SYNC_FLAG_CHANGE;
+		else if (strcasecmp(*arr, "mark-del")==0)
+			sync |= OCFS_SYNC_FLAG_MARK_FOR_DELETION;
+		else if (strcasecmp(*arr, "name-del")==0)
+			sync |= OCFS_SYNC_FLAG_NAME_DELETED;
+		else
+			goto bail;
+		arr++;
+	}
+	G_STRUCT_MEMBER(__u8, top, info->off) = sync;
+	ret = 0;
+bail:
+	g_strfreev(arr);
+	return ret;
+
+}
+
+char * _get_syncflag_helptext(typeinfo *info)
+{
+	return strdup("one or more of: deleted valid change mark-del name-del");
+}
+
+// CHAR ARRAY: __u8[]
+int _char_array_valid(void *top, typeinfo *info)
+{
+	return 0;
+}
+
+int _char_array_to_string_u8(GString **retval, void *top, typeinfo *info)
+{
+	char *buf = NULL;
+	__u8 *arr;
+
+	if (info->array_size <= 0)
+		return -1;
+	arr =  G_STRUCT_MEMBER_P(top, info->off);
+	if (_char_array_valid(top, info) == -1)
+	{
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "[ %u, ... ]", arr[0]);
+#endif
+		return -1;
+	}
+	
+	if ((buf = malloc(info->array_size + 1)) == NULL) {
+		LOG_ERROR("unable to allocate %d bytes of memory",
+			  info->array_size + 1);
+		goto bail;
+	}
+
+	memcpy(buf, arr, info->array_size);
+	buf[ info->array_size ] = '\0';
+	*retval = g_string_new(buf);
+
+      bail:
+	free(buf);
+	return 0;
+}
+
+int _string_to_char_array_u8(char *newval, void *top, typeinfo *info)
+{
+	char *buf;
+	if (info->array_size <= 0)
+		return -1;
+
+	buf = G_STRUCT_MEMBER_P(top, info->off);
+	strncpy(buf, newval, info->array_size);
+	buf[info->array_size - 1] = '\0';
+	return 0;
+}
+
+char * _get_char_array_helptext(typeinfo *info)
+{
+	return g_strdup_printf("a string with maximum length %d",
+			       info->array_size - 1);
+}
+
+// HEX ARRAY: __u8[]
+int _hex_array_valid(void *top, typeinfo *info)
+{
+	return 0;
+}
+
+int _hex_array_to_string_u8(GString **retval, void *top, typeinfo *info)
+{
+	char *buf = NULL;
+	char *p;
+	int i;
+	__u8 *arr;
+
+	if (info->array_size <= 0)
+		return -1;
+	arr =  G_STRUCT_MEMBER_P(top, info->off);
+	if (_char_array_valid(top, info) == -1)
+	{
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "[ %X, ... ]", arr[0]);
+#endif
+		return -1;
+	}
+	
+	if ((buf = malloc(2 * info->array_size + 1)) == NULL) {
+		LOG_ERROR("unable to allocate %d bytes of memory",
+			  info->array_size + 1);
+		goto bail;
+	}
+
+	for (i = 0, p = buf; i < info->array_size; ++i, p += 2)
+		sprintf(p, "%2X", arr[i]);
+	buf[ 2 * info->array_size ] = '\0';
+	*retval = g_string_new(buf);
+
+      bail:
+	free(buf);
+	return 0;
+}
+
+int _string_to_hex_array_u8(char *newval, void *top, typeinfo *info)
+{
+	unsigned char *buf;
+	unsigned char tb[3];
+	int i;
+	unsigned char *p;
+
+	if (info->array_size <= 0)
+		return -1;
+
+	buf = G_STRUCT_MEMBER_P(top, info->off);
+
+	tb[2] = '\0';
+	for (i = 0, p = newval; i < info->array_size; ++i, ++p) {
+		tb[0] = *p;
+		tb[1] = *(++p);
+		buf[i] = strtoul(tb, NULL, 16);
+	}
+
+	return 0;
+}
+
+char * _get_hex_array_helptext(typeinfo *info)
+{
+	return g_strdup_printf("a hex string with maximum length %d",
+			       info->array_size);
+}
+
+// NUMBER RANGE: __s32 __u8 __u16 __u32 __u64
+int _number_range_valid(void *top, typeinfo *info) 
+{
+	if (info->is_signed)
+	{
+		__s64 num, hi, lo;
+		switch (info->type_size)
+		{
+		case 1:
+			num = G_STRUCT_MEMBER(__s8, top, info->off);
+			hi = (__s8)(info->hi & 0xffLL);
+			lo = (__s8)(info->lo & 0xffLL);
+			break;
+		case 2:
+			num = G_STRUCT_MEMBER(__s16, top, info->off);
+			hi = (__s16)(info->hi & 0xffffLL);
+			lo = (__s16)(info->lo & 0xffffLL);
+			break;
+		case 4:
+			num = G_STRUCT_MEMBER(__s32, top, info->off);
+			hi = (__s32)(info->hi & 0xffffffffLL);
+			lo = (__s32)(info->lo & 0xffffffffLL);
+			break;
+		case 8:
+			num = G_STRUCT_MEMBER(__s64, top, info->off);
+			hi = (__s64)info->hi;
+			lo = (__s64)info->lo;
+			break;
+		default:
+			return -1;
+			break;
+		}
+		if (num < lo || num > hi)
+			return -1;
+	}
+	else
+	{
+		__u64 num, hi, lo;
+		switch (info->type_size)
+		{
+		case 1:
+			num = G_STRUCT_MEMBER(__u8, top, info->off);
+			hi = (__u8)(info->hi & 0xffLL);
+			lo = (__u8)(info->lo & 0xffLL);
+			break;
+		case 2:
+			num = G_STRUCT_MEMBER(__u16, top, info->off);
+			hi = (__u16)(info->hi & 0xffffLL);
+			lo = (__u16)(info->lo & 0xffffLL);
+			break;
+		case 4:
+			num = G_STRUCT_MEMBER(__u32, top, info->off);
+			hi = (__u32)(info->hi & 0xffffffffLL);
+			lo = (__u32)(info->lo & 0xffffffffLL);
+			break;
+		case 8:
+			num = G_STRUCT_MEMBER(__u64, top, info->off);
+			hi = (__u64)info->hi;
+			lo = (__u64)info->lo;
+			break;
+		default:
+			return -1;
+			break;
+		}
+		if (num < lo || num > hi)
+			return -1;
+
+	}
+	return 0;
+}
+
+int _number_range_to_string_s32(GString **retval, void *top,
+				typeinfo *info)
+{
+	__s32 num;
+
+	num = G_STRUCT_MEMBER(__s32, top, info->off);
+	if (_number_range_valid(top, info) == -1)
+	{
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "%d", num);
+#endif
+		return -1;
+	}
+	*retval = g_string_new("");
+	g_string_sprintfa(*retval, "%d", num);
+	return 0;
+}
+
+int _string_to_number_range_s32(char *newval, void *top, typeinfo *info)
+{
+	__s32 num, hi, lo;
+	char *bad = NULL;
+
+	hi = (__s32)(info->hi & 0xffffffffULL);
+	lo = (__s32)(info->lo & 0xffffffffULL);
+	
+	num = strtol(newval, &bad, 10);
+	if (bad == newval || num < lo || num > hi)
+		return -1;
+	G_STRUCT_MEMBER(__s32, top, info->off) = num;
+	return 0;
+}
+
+int _number_range_to_string_u8(GString **retval, void *top, typeinfo *info)
+{
+	__u8 num;
+
+	num = G_STRUCT_MEMBER(__u8, top, info->off);
+	if (_number_range_valid(top, info) == -1)
+	{
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "%u", num);
+#endif
+		return -1;
+	}
+	
+	*retval = g_string_new("");
+	g_string_sprintfa(*retval, "%u", num);
+	return 0;
+}
+
+int _string_to_number_range_u8(char *newval, void *top, typeinfo *info)
+{
+	__u32 tmp;
+	__u8 hi, lo;
+	char *bad = NULL;
+
+	hi = (__u8)(info->hi & 0xffULL);
+	lo = (__u8)(info->lo & 0xffULL);
+	
+	tmp = strtoul(newval, &bad, 10);
+	if (bad == newval || tmp < lo || tmp > hi)
+		return -1;
+	G_STRUCT_MEMBER(__u8, top, info->off) = tmp;
+	return 0;
+}
+
+int _number_range_to_string_u16(GString **retval, void *top, typeinfo *info)
+{
+	__u16 num;
+
+	num = G_STRUCT_MEMBER(__u16, top, info->off);
+	if (_number_range_valid(top, info) == -1)
+	{
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "%u", num);
+#endif
+		return -1;
+	}
+	
+	*retval = g_string_new("");
+	g_string_sprintfa(*retval, "%u", num);
+	return 0;
+}
+
+int _string_to_number_range_u16(char *newval, void *top, typeinfo *info)
+{
+	__u32 tmp;
+	__u16 hi, lo;
+	char *bad = NULL;
+
+	hi = (__u16)(info->hi & 0xffffULL);
+	lo = (__u16)(info->lo & 0xffffULL);
+	
+	tmp = strtoul(newval, &bad, 10);
+	if (bad == newval || tmp < lo || tmp > hi)
+		return -1;
+	G_STRUCT_MEMBER(__u16, top, info->off) = tmp;
+	return 0;
+}
+
+int _number_range_to_string_u32(GString **retval, void *top, typeinfo *info)
+{
+	__u32 num;
+
+	num = G_STRUCT_MEMBER(__u32, top, info->off);
+	if (_number_range_valid(top, info) == -1)
+	{
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "%u", num);
+#endif
+		return -1;
+	}
+	
+	*retval = g_string_new("");
+	g_string_sprintfa(*retval, "%u", num);
+	return 0;
+}
+
+int _string_to_number_range_u32(char *newval, void *top, typeinfo *info)
+{
+	__u32 tmp, hi, lo;
+	char *bad = NULL;
+
+	hi = (__u32)(info->hi & 0xffffffffULL);
+	lo = (__u32)(info->lo & 0xffffffffULL);
+	
+	tmp = strtoul(newval, &bad, 10);
+	if (bad == newval || tmp < lo || tmp > hi)
+		return -1;
+	G_STRUCT_MEMBER(__u32, top, info->off) = tmp;
+	return 0;
+}
+
+int _number_range_to_string_u64(GString **retval, void *top, typeinfo *info)
+{
+	__u64 num;
+
+	num = G_STRUCT_MEMBER(__u64, top, info->off);
+	if (_number_range_valid(top, info) == -1)
+	{
+#ifdef SHOW_INVALID_VALUES
+		*retval = g_string_new("");
+		g_string_sprintf(*retval, "%llu", num);
+#endif
+		return -1;
+	}
+	*retval = g_string_new("");
+	g_string_sprintfa(*retval, "%llu", num);
+	return 0;
+}
+
+int _string_to_number_range_u64(char *newval, void *top, typeinfo *info)
+{
+	__u64 tmp;
+	char *bad = NULL;
+
+	tmp = strtoull(newval, &bad, 10);
+	if (bad == newval || tmp < info->lo || tmp > info->hi)
+		return -1;
+	G_STRUCT_MEMBER(__u64, top, info->off) = tmp;
+	return 0;
+}
+
+char * _get_number_range_helptext(typeinfo *info)
+{
+	if (info->is_signed)
+		return g_strdup_printf("a number between %d and %d (inclusive)", 
+				       (__s32)(info->lo & 0xffffffffULL), 
+				       (__s32)(info->hi & 0xffffffffULL));
+	else
+		return g_strdup_printf("a number between %llu and %llu (inclusive)",
+				       info->lo, info->hi);
+}
+
+// VOTEFLAG: __u8[32]
+int _voteflag_array_valid(void *top, typeinfo *info)
+{
+	int i;
+	__u8 *arr;
+	if (info->array_size != 32)
+		return -1;
+
+	arr = G_STRUCT_MEMBER_P(top, info->off);
+	for (i=0; i<info->array_size; i++)
+	{
+		if (arr[i] != 0 &&
+		    arr[i] != FLAG_VOTE_NODE &&
+		    arr[i] != FLAG_VOTE_OIN_UPDATED &&
+		    arr[i] != FLAG_VOTE_OIN_ALREADY_INUSE &&
+		    arr[i] != FLAG_VOTE_UPDATE_RETRY &&
+		    arr[i] != FLAG_VOTE_FILE_DEL)
+			return -1;
+	}
+	return 0;
+}
+
+int _voteflag_array_to_string_u8(GString **retval, void *top, typeinfo *info)
+{
+	__u8 *arr;
+	int i;
+
+	if (info->array_size <= 0)
+		return -1;
+
+        arr = G_STRUCT_MEMBER_P(top, info->off);
+	if (_voteflag_array_valid(top, info) == -1)
+		goto fail;
+
+	*retval = g_string_new("");
+	for (i=0; i<info->array_size; i++)
+	{
+		if (i!=0)
+			g_string_append(*retval, " ");
+		if (arr[i] & FLAG_VOTE_NODE)
+			g_string_append(*retval, "vote");
+		else if (arr[i] & FLAG_VOTE_OIN_UPDATED)
+			g_string_append(*retval, "updated");
+		else if (arr[i] & FLAG_VOTE_OIN_ALREADY_INUSE)
+			g_string_append(*retval, "inuse");
+		else if (arr[i] & FLAG_VOTE_UPDATE_RETRY)
+			g_string_append(*retval, "retry");
+		else if (arr[i] & FLAG_VOTE_FILE_DEL)
+			g_string_append(*retval, "delete");
+		else if (arr[i] == 0)
+			g_string_append(*retval, "none");
+	}
+
+	return 0;
+fail:
+#ifdef SHOW_INVALID_VALUES
+	{
+		int j;
+		for (j=0; j<info->array_size; j++)
+		{
+			if (j!=0)
+				g_string_append(*retval, ":");
+			g_string_sprintfa(*retval, "%u", arr[j]);
+		}
+	}
+#else
+	g_string_free(*retval, true);
+#endif
+	return -1;
+}
+
+int _string_to_voteflag_array_u8(char *newval, void *top, typeinfo *info)
+{
+	__u8 *flag;
+	int ret = -1, i;
+	char **arr;
+	
+	if (info->array_size <= 0)
+		return -1;
+
+	flag = G_STRUCT_MEMBER(__u8 *, top, info->off);
+	arr = g_strsplit(newval, " ", 0);
+	
+	for (i=0; i<info->array_size && arr[i]!=NULL; i++)
+	{
+		flag[i] = 0;
+		if (strcasecmp(arr[i], "vote")==0)
+			flag[i] |= FLAG_VOTE_NODE;
+		else if (strcasecmp(arr[i], "updated")==0)
+			flag[i] |= FLAG_VOTE_OIN_UPDATED;
+		else if (strcasecmp(arr[i], "inuse")==0)
+			flag[i] |= FLAG_VOTE_OIN_ALREADY_INUSE;
+		else if (strcasecmp(arr[i], "retry")==0)
+			flag[i] |= FLAG_VOTE_UPDATE_RETRY;
+		else if (strcasecmp(arr[i], "delete")==0)
+			flag[i] |= FLAG_VOTE_FILE_DEL;
+		else if (strcasecmp(arr[i], "none")==0 || atoi(arr[i])==0)
+			flag[i] = 0;
+		else
+			goto bail;
+
+	}
+	ret = 0;
+bail:
+	g_strfreev(arr);
+	return ret;
+}
+
+char * _get_voteflag_array_helptext(typeinfo *info)
+{
+	return g_strdup_printf("one flag for each node (up to %d): "
+			       "none vote updated inuse retry delete "
+			       "(space-delimited)",
+			       info->array_size);
+}
+

Added: trunk/fsck/classes.h
===================================================================
--- trunk/fsck/classes.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/fsck/classes.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,186 @@
+/*
+ * classes.h
+ *
+ * Function prototypes, macros, etc. for related 'C' files
+ *
+ * Copyright (C) 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Sunil Mushran
+ */
+
+#ifndef _CLASSES_H
+#define _CLASSES_H
+
+
+typedef struct _typeinfo
+{
+	int off;
+	int array_size;
+	int type_size;
+	bool is_signed;
+	__u64 lo;
+	__u64 hi;
+} typeinfo;
+
+typedef struct _ocfs_class_member
+{
+	char *name;
+	char *flavor;
+	typeinfo type;
+	int (*valid) (void *, typeinfo *);
+	int (*to_string) (GString **, void *, typeinfo *);
+	int (*from_string) (char *, void *, typeinfo *);
+	char * (*helptext) (typeinfo *);
+} ocfs_class_member;
+
+typedef struct _ocfs_class
+{
+	char *name;
+	int num_members;
+	ocfs_class_member *members;
+} ocfs_class;
+
+ocfs_class_member * find_class_member(ocfs_class *cl, const char *name, int *idx);
+
+extern ocfs_class ocfs_alloc_ext_class;
+extern ocfs_class ocfs_publish_class;
+extern ocfs_class ocfs_vote_class;
+extern ocfs_class ocfs_file_entry_class;
+extern ocfs_class ocfs_dir_node_class;
+extern ocfs_class ocfs_extent_group_class;
+extern ocfs_class ocfs_vol_disk_hdr_class;
+extern ocfs_class ocfs_disk_lock_class;
+extern ocfs_class ocfs_vol_label_class;
+extern ocfs_class ocfs_ipc_config_info_class;
+extern ocfs_class ocfs_guid_class;
+extern ocfs_class ocfs_disk_node_config_info_class;
+extern ocfs_class ocfs_node_config_hdr_class;
+
+int _attribs_valid(void *top, typeinfo *info);
+int _bool_valid(void *top, typeinfo *info);
+int _clustersize_valid(void *top, typeinfo *info);
+int _date_valid(void *top, typeinfo *info);
+int _dirflag_valid(void *top, typeinfo *info);
+int _dirindex_valid(void *top, typeinfo *info);
+int _dirnodeindex_valid(void *top, typeinfo *info);
+int _diskptr_valid(void *top, typeinfo *info);
+int _extenttype_valid(void *top, typeinfo *info);
+int _fileflag_valid(void *top, typeinfo *info);
+int _gid_valid(void *top, typeinfo *info);
+int _uid_valid(void *top, typeinfo *info);
+int _locklevel_valid(void *top, typeinfo *info);
+int _nodebitmap_valid(void *top, typeinfo *info);
+int _nodenum_valid(void *top, typeinfo *info);
+int _perms_valid(void *top, typeinfo *info);
+int _syncflag_valid(void *top, typeinfo *info);
+int _char_array_valid(void *top, typeinfo *info);
+int _hex_array_valid(void *top, typeinfo *info);
+int _number_range_valid(void *top, typeinfo *info) ;
+int _voteflag_array_valid(void *top, typeinfo *info);
+
+int _attribs_to_string_u32(GString **retval, void *top, typeinfo *info);
+int _string_to_attribs_u32(char *newval, void *top, typeinfo *info);
+char * _get_attribs_helptext(typeinfo *info);
+int _bool_to_string_s32(GString **retval, void *top, typeinfo *info);
+int _string_to_bool_s32(char *newval, void *top, typeinfo *info);
+int _bool_to_string_u8(GString **retval, void *top, typeinfo *info);
+int _string_to_bool_u8(char *newval, void *top, typeinfo *info);
+int _bool_to_string_bool(GString **retval, void *top, typeinfo *info);
+int _string_to_bool_bool(char *newval, void *top, typeinfo *info);
+char * _get_bool_helptext(typeinfo *info);
+int _clustersize_to_string_u64(GString **retval, void *top, typeinfo *info);
+int _string_to_clustersize_u64(char *newval, void *top, typeinfo *info);
+char * _get_clustersize_helptext(typeinfo *info);
+int _date_to_string_u64(GString **retval, void *top, typeinfo *info);
+int _string_to_date_u64(char *newval, void *top, typeinfo *info);
+char * _get_date_helptext(typeinfo *info);
+int _dirflag_to_string_u8(GString **retval, void *top, typeinfo *info);
+int _string_to_dirflag_u8(char *newval, void *top, typeinfo *info);
+char * _get_dirflag_helptext(typeinfo *info);
+int _dirindex_to_string_u8(GString **retval, void *top, typeinfo *info);
+int _string_to_dirindex_u8(char *newval, void *top, typeinfo *info);
+char * _get_dirindex_helptext(typeinfo *info);
+int _dirnodeindex_to_string_s8(GString **retval, void *top, typeinfo *info);
+int _string_to_dirnodeindex_s8(char *newval, void *top, typeinfo *info);
+int _dirnodeindex_to_string_u8(GString **retval, void *top, typeinfo *info);
+int _string_to_dirnodeindex_u8(char *newval, void *top, typeinfo *info);
+char * _get_dirnodeindex_helptext(typeinfo *info);
+int _diskptr_to_string_s64(GString **retval, void *top, typeinfo *info);
+int _string_to_diskptr_s64(char *newval, void *top, typeinfo *info);
+int _diskptr_to_string_u64(GString **retval, void *top, typeinfo *info);
+int _string_to_diskptr_u64(char *newval, void *top, typeinfo *info);
+char * _get_diskptr_helptext(typeinfo *info);
+int _extenttype_to_string_u32(GString **retval, void *top, typeinfo *info);
+int _string_to_extenttype_u32(char *newval, void *top, typeinfo *info);
+char * _get_extenttype_helptext(typeinfo *info);
+int _fileflag_to_string_u32(GString **retval, void *top, typeinfo *info);
+int _string_to_fileflag_u32(char *newval, void *top, typeinfo *info);
+char * _get_fileflag_helptext(typeinfo *info);
+int _gid_to_string_u32(GString **retval, void *top, typeinfo *info);
+int _string_to_gid_u32(char *newval, void *top, typeinfo *info);
+char * _get_gid_helptext(typeinfo *info);
+int _uid_to_string_u32(GString **retval, void *top, typeinfo *info);
+int _string_to_uid_u32(char *newval, void *top, typeinfo *info);
+char * _get_uid_helptext(typeinfo *info);
+int _locklevel_to_string_u8(GString **retval, void *top, typeinfo *info);
+int _string_to_locklevel_u8(char *newval, void *top, typeinfo *info);
+char * _get_locklevel_helptext(typeinfo *info);
+int _nodebitmap_to_string_u64(GString **retval, void *top, typeinfo *info);
+int _string_to_nodebitmap_u64(char *newval, void *top, typeinfo *info);
+char * _get_nodebitmap_helptext(typeinfo *info);
+int _nodenum_to_string_u32(GString **retval, void *top, typeinfo *info);
+int _string_to_nodenum_u32(char *newval, void *top, typeinfo *info);
+int _nodenum_to_string_s32(GString **retval, void *top, typeinfo *info);
+int _string_to_nodenum_s32(char *newval, void *top, typeinfo *info);
+char * _get_nodenum_helptext(typeinfo *info);
+int _perms_to_string_u32(GString **retval, void *top, typeinfo *info);
+int _string_to_perms_u32(char *newval, void *top, typeinfo *info);
+char * _get_perms_helptext(typeinfo *info);
+int _syncflag_to_string_u32(GString **retval, void *top, typeinfo *info);
+int _string_to_syncflag_u32(char *newval, void *top, typeinfo *info);
+int _syncflag_to_string_u8(GString **retval, void *top, typeinfo *info);
+int _string_to_syncflag_u8(char *newval, void *top, typeinfo *info);
+char * _get_syncflag_helptext(typeinfo *info);
+int _char_array_to_string_u8(GString **retval, void *top, typeinfo *info);
+int _string_to_char_array_u8(char *newval, void *top, typeinfo *info);
+char * _get_char_array_helptext(typeinfo *info);
+int _hex_array_to_string_u8(GString **retval, void *top, typeinfo *info);
+int _string_to_hex_array_u8(char *newval, void *top, typeinfo *info);
+char * _get_hex_array_helptext(typeinfo *info);
+int _number_range_to_string_s32(GString **retval, void *top, typeinfo *info);
+int _string_to_number_range_s32(char *newval, void *top, typeinfo *info);
+int _number_range_to_string_u8(GString **retval, void *top, typeinfo *info);
+int _string_to_number_range_u8(char *newval, void *top, typeinfo *info);
+int _number_range_to_string_u16(GString **retval, void *top, typeinfo *info);
+int _string_to_number_range_u16(char *newval, void *top, typeinfo *info);
+int _number_range_to_string_u32(GString **retval, void *top, typeinfo *info);
+int _string_to_number_range_u32(char *newval, void *top, typeinfo *info);
+int _number_range_to_string_u64(GString **retval, void *top, typeinfo *info);
+int _string_to_number_range_u64(char *newval, void *top, typeinfo *info);
+char * _get_number_range_helptext(typeinfo *info);
+int _voteflag_array_to_string_u8(GString **retval, void *top, typeinfo *info);
+int _string_to_voteflag_array_u8(char *newval, void *top, typeinfo *info);
+char * _get_voteflag_array_helptext(typeinfo *info);
+int _extent_array_to_string(GString **retval, void *top, typeinfo *info);
+int _string_to_extent_array(char *newval, void *top, typeinfo *info);
+char * _get_extent_array_helptext(typeinfo *info);
+int _disklock_to_string(GString **retval, void *top, typeinfo *info);
+int _string_to_disklock(char *newval, void *top, typeinfo *info);
+char * _get_disklock_helptext(typeinfo *info);
+
+#endif /* _CLASSES_H */

Added: trunk/fsck/defaults.c
===================================================================
--- trunk/fsck/defaults.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/fsck/defaults.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,107 @@
+/*
+ * defaults.c
+ *
+ * defaults for structures in ocfs file system check utility
+ *
+ * Copyright (C) 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Sunil Mushran
+ */
+
+#include "fsck.h"
+
+int get_nodecfghdr_defaults (char *buf, GString **out, int idx, int fld)
+{
+	return 0;
+}
+
+int get_nodecfginfo_defaults (char *buf, GString **out, int idx, int fld)
+{
+	return 0;
+}
+
+int get_cleanup_log_defaults (char *buf, GString **out, int idx, int fld)
+{
+	return 0;
+}
+int get_dir_alloc_bitmap_defaults (char *buf, GString **out, int idx, int fld)
+{
+	return 0;
+}
+int get_dir_alloc_defaults (char *buf, GString **out, int idx, int fld)
+{
+	return 0;
+}
+int get_vol_disk_header_defaults  (char *buf, GString **out, int idx, int fld)
+{
+	return 0;
+}
+int get_disk_lock_defaults (char *buf, GString **out, int idx, int fld)
+{
+	return 0;
+}
+int get_file_alloc_bitmap_defaults (char *buf, GString **out, int idx, int fld)
+{
+	return 0;
+}
+int get_file_alloc_defaults (char *buf, GString **out, int idx, int fld)
+{
+	return 0;
+}
+int get_publish_sector_defaults (char *buf, GString **out, int idx, int fld)
+{
+	return 0;
+}
+int get_recover_log_defaults (char *buf, GString **out, int idx, int fld)
+{
+	return 0;
+}
+int get_vol_metadata_defaults (char *buf, GString **out, int idx, int fld)
+{
+	return 0;
+}
+int get_vol_metadata_log_defaults (char *buf, GString **out, int idx, int fld)
+{
+	return 0;
+}
+int get_vol_label_defaults  (char *buf, GString **out, int idx, int fld)
+{
+	return 0;
+}
+int get_vote_sector_defaults (char *buf, GString **out, int idx, int fld)
+{
+	return 0;
+}
+int get_dir_node_defaults (char *buf, GString **out, int idx, int fld)
+{
+	return 0;
+}
+int get_file_entry_defaults (char *buf, GString **out, int idx, int fld)
+{
+	return 0;
+}
+int get_extent_header_defaults (char *buf, GString **out, int idx, int fld)
+{
+	return 0;
+}
+int get_extent_data_defaults (char *buf, GString **out, int idx, int fld)
+{
+	return 0;
+}
+
+

Added: trunk/fsck/defaults.h
===================================================================
--- trunk/fsck/defaults.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/fsck/defaults.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,49 @@
+/*
+ * defaults.h
+ *
+ * Function prototypes, macros, etc. for related 'C' files
+ *
+ * Copyright (C) 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Sunil Mushran
+ */
+
+#ifndef DEFAULTS_H
+#define DEFAULTS_H
+
+int get_nodecfghdr_defaults (char *buf, GString **out, int idx, int fld);
+int get_nodecfginfo_defaults (char *buf, GString **out, int idx, int fld);
+int get_cleanup_log_defaults (char *buf, GString **out, int idx, int fld);
+int get_dir_alloc_bitmap_defaults (char *buf, GString **out, int idx, int fld);
+int get_dir_alloc_defaults (char *buf, GString **out, int idx, int fld);
+int get_vol_disk_header_defaults  (char *buf, GString **out, int idx, int fld);
+int get_disk_lock_defaults (char *buf, GString **out, int idx, int fld);
+int get_file_alloc_bitmap_defaults (char *buf, GString **out, int idx, int fld);
+int get_file_alloc_defaults (char *buf, GString **out, int idx, int fld);
+int get_publish_sector_defaults (char *buf, GString **out, int idx, int fld);
+int get_recover_log_defaults (char *buf, GString **out, int idx, int fld);
+int get_vol_metadata_defaults (char *buf, GString **out, int idx, int fld);
+int get_vol_metadata_log_defaults (char *buf, GString **out, int idx, int fld);
+int get_vol_label_defaults  (char *buf, GString **out, int idx, int fld);
+int get_vote_sector_defaults (char *buf, GString **out, int idx, int fld);
+int get_dir_node_defaults (char *buf, GString **out, int idx, int fld);
+int get_file_entry_defaults (char *buf, GString **out, int idx, int fld);
+int get_extent_header_defaults (char *buf, GString **out, int idx, int fld);
+int get_extent_data_defaults (char *buf, GString **out, int idx, int fld);
+
+#endif /* DEFAULTS_H */

Added: trunk/fsck/fsck.c
===================================================================
--- trunk/fsck/fsck.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/fsck/fsck.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,1686 @@
+/*
+ * fsck.c
+ *
+ * ocfs file system check utility
+ *
+ * Copyright (C) 2003, 2004 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Sunil Mushran
+ */
+
+#include "fsck.h"
+
+#define MAX_EXTENTS	2048
+#define OCFS_HBT_WAIT	10
+
+int prn_len = 1;
+int cnt_err = 0;
+int cnt_wrn = 0;
+int cnt_obj = 0;
+bool int_err = false;
+bool prn_err = false;
+
+__u32 OcfsDebugCtxt = 0;
+__u32 OcfsDebugLevel = 0;
+__u32 debug_context = 0;
+__u32 debug_level = 0;
+__u32 debug_exclude = 0;
+
+ocfs_global_ctxt OcfsGlobalCtxt;
+ocfsck_context ctxt;
+extern void version(char *progname);
+void init_global_context(void);
+
+
+
+void init_global_context()
+{
+	char *tmp;
+
+	memset(&OcfsGlobalCtxt, 0, sizeof(ocfs_global_ctxt));
+	OcfsGlobalCtxt.obj_id.type = OCFS_TYPE_GLOBAL_DATA;
+	OcfsGlobalCtxt.obj_id.size = sizeof (ocfs_global_ctxt);
+	OcfsGlobalCtxt.pref_node_num = 31;
+	OcfsGlobalCtxt.node_name = "user-tool";
+	OcfsGlobalCtxt.comm_info.type = OCFS_UDP;
+	OcfsGlobalCtxt.comm_info.ip_addr = "0.0.0.0";
+	OcfsGlobalCtxt.comm_info.ip_port = OCFS_IPC_DEFAULT_PORT;
+	OcfsGlobalCtxt.comm_info.ip_mask = NULL;
+	OcfsGlobalCtxt.comm_info_read = true;
+	memset(&OcfsGlobalCtxt.guid.id.host_id, 'f', HOSTID_LEN);
+	memset(&OcfsGlobalCtxt.guid.id.mac_id,  '0', MACID_LEN);
+
+	tmp = getenv("debug_level");
+	if (tmp)
+		debug_level = atoi(tmp);
+	tmp = getenv("debug_context");
+	if (tmp)
+		debug_context = atoi(tmp);
+	tmp = getenv("debug_exclude");
+	if (tmp)
+		debug_exclude = atoi(tmp);
+}
+
+char *usage_str = 
+"usage: fsck.ocfs [OPTIONS] device\n"
+"	-n No hearbeat check\n"
+"	-w Writeable\n"
+"	-V Version\n"
+"	-v Verbose\n"
+"	-q Quiet";
+
+/*
+ * usage()
+ *
+ */
+void usage(void)
+{
+	printf("%s\n", usage_str);
+}				/* usage */
+
+/*
+ * parse_fsck_cmdline()
+ *
+ */
+int parse_fsck_cmdline(int argc, char **argv)
+{
+	int off;
+	int c;
+	int ret = -1;
+
+	ctxt.write_changes = false;
+	ctxt.no_hb_chk = false;
+	ctxt.verbose = false;
+	ctxt.modify_all = false;
+	ctxt.quiet = false;
+	ctxt.dev_is_file = false;
+
+	if (argc < 2) {
+		usage();
+		goto bail;
+	}
+
+	while (1) {
+		off = 0;
+		c = getopt(argc, argv, "wnVvmqf?");
+
+		if (c == -1)
+			break;
+
+		switch (c) {
+		case 'w':
+			ctxt.write_changes = true;
+			break;
+		case 'n':
+			ctxt.no_hb_chk = true;
+			break;
+		case 'm':
+			ctxt.modify_all = true;
+			break;
+		case 'v':
+			ctxt.verbose = true;
+			break;
+		case 'q':
+			ctxt.quiet = true;
+			break;
+		case 'f':
+			ctxt.dev_is_file = true;
+			break;
+		case 'V':
+			version(argv[0]);
+			goto bail;
+		default:
+		case '?':
+			usage();
+			goto bail;
+		}
+	}
+
+	if (ctxt.modify_all)
+		ctxt.verbose = true;
+
+	if (ctxt.write_changes)
+		ctxt.no_hb_chk = false;
+
+	if (ctxt.dev_is_file)
+		ctxt.no_hb_chk = false;
+
+	ret = 0;
+bail:
+	return ret;
+}				/* parse_fsck_cmdline */
+
+/*
+ * edit_structure()
+ *
+ */
+int edit_structure(ocfs_disk_structure *s, char *buf, int idx, int *changed, char *option)
+{
+	int ret = 0;
+	int fld;
+	ocfs_class *cls;
+	ocfs_class_member *m;
+	GString *cur;
+	GString *dflt;
+	char *newval = NULL;
+	char *bad;
+	char *loc;
+
+	if ((newval = malloc(USER_INPUT_MAX)) == NULL) {
+		LOG_INTERNAL();
+		goto bail;
+	}
+
+	*changed = 0;
+	cls = s->cls;
+	*option = '\0';
+
+	while (1) {
+		cur = dflt = NULL;
+		bad = NULL;
+	
+		printf("choose a field to edit (1-%d, 's' to step, "
+		       "'n' for next, 'd' for dirnode or 'q' to quit) : ", cls->num_members);
+		if (fgets(newval, USER_INPUT_MAX, stdin) == NULL) {
+			ret = -1;
+			break;
+		}
+
+		if ((loc = rindex(newval, '\n')) != NULL)
+			*loc = '\0';
+
+	       	if (strcasecmp(newval, "q") == 0 || strcasecmp(newval, "quit") == 0 ||
+		    strcasecmp(newval, "n") == 0 || strcasecmp(newval, "next") == 0 ||
+		    strcasecmp(newval, "s") == 0 || strcasecmp(newval, "step") == 0 ||
+		    strcasecmp(newval, "d") == 0 || strcasecmp(newval, "dirnode") == 0)  {
+			*option = tolower(*newval);
+			ret = -1;
+			break;
+		}
+
+		fld = strtol(newval, &bad, 10);
+		fld--;
+
+		if (bad == newval || IS_INVALID_FIELD_NUM(cls, fld)) {
+			ret = 0;
+			LOG_ERROR("bad field number");
+			break;
+		}
+	
+		// show current value and default value	
+		m = &(cls->members[fld]);
+		if (m->to_string(&cur, buf, &(m->type))==-1) {
+			ret = -1;
+			LOG_ERROR("to_string failed");
+			break;
+		}
+
+		if (s->defaults(buf, &dflt, idx, fld)==-1) {
+			ret = -1;
+			LOG_ERROR("defaults failed");
+			break;
+		}
+
+		printf("%s : %s (default=%s)\n", m->name, 
+		       cur ? cur->str : "", 
+		       dflt ? dflt->str : "");
+
+		// get new value and validate it
+		if (fgets(newval, USER_INPUT_MAX, stdin) == NULL) {
+			ret = -1;
+			break;
+		}
+
+		if ((loc = rindex(newval, '\n')) != NULL)
+			*loc = '\0';
+
+	       	if (strcasecmp(newval, "q")==0 || strcasecmp(newval, "quit")==0) {
+			ret = -1;
+			break;
+		}
+
+		if (strcmp(newval, "?")==0 || strcasecmp(newval, "help")==0) {
+			char *help = m->helptext(&(m->type));
+			printf("%s\n", help);
+			free(help);
+			ret = 0;
+			break;
+		}
+
+		if ((ret = m->from_string(newval, buf, &(m->type))) == -1) {
+			LOG_ERROR("bad entry");
+			ret = -1;
+			break;
+		}
+
+		(*changed)++;
+		
+		if (dflt) {
+			g_string_free(dflt, true);
+			dflt = NULL;
+		}
+
+		if (cur) {
+			g_string_free(cur, true);
+			cur = NULL;
+		}
+	}
+
+	if (dflt)
+		g_string_free(dflt, true);
+
+	if (cur)
+		g_string_free(cur, true);
+
+bail:
+	safefree(newval);
+
+	return ret;
+}				/* edit_structure */
+
+/*
+ * confirm_changes()
+ *
+ */
+int confirm_changes(__u64 off, ocfs_disk_structure *s, char *buf, int idx, GHashTable *bad)
+{
+	int ret = -1;
+	char *yesno, *loc;
+	int fd = ctxt.fd;
+
+	yesno = malloc(USER_INPUT_MAX);
+	if (!yesno) {
+		LOG_INTERNAL();
+		goto bail;
+	}
+
+	if (s->output(buf, idx, bad, stdout)==-1) {
+		//fprintf(stderr, "at least one bad field found\n");
+	}
+
+	printf("\n\nDo you really want to write your changes out? : ");
+
+	if (fgets(yesno, USER_INPUT_MAX, stdin) == NULL) {
+		ret = -1;
+		goto bail;
+	}
+
+	if ((loc = rindex(yesno, '\n')) != NULL)
+		*loc = '\0';
+
+       	if (strcasecmp(yesno, "yes")==0 || strcasecmp(yesno, "y")==0) {
+		if (s->write(fd, buf, off, idx)==-1)
+			LOG_ERROR("failed to write data to disk");
+		else {
+			GHashTable *tmp = NULL;
+			ret = s->verify(fd, buf, idx, &tmp);
+			if (tmp != NULL)
+				g_hash_table_destroy(tmp);
+		}
+	}
+
+bail:
+	safefree(yesno);
+	return ret;
+}				/* confirm_changes */
+
+static char *saved_block = NULL;
+/*
+ * read_print_struct()
+ *
+ */
+int read_print_struct(ocfs_disk_structure *s, char *buf, __u64 off, int idx, GHashTable **bad)
+{
+	int ret = 0;
+	int fd = ctxt.fd;
+	
+	if (saved_block == NULL)
+		saved_block = malloc(512);
+
+	if (saved_block == NULL)
+		return -1;
+
+	if (s->read(fd, buf, off, idx)==-1) {
+		LOG_ERROR("failed to read data");
+		return -2;
+	}
+
+	memcpy(saved_block, buf, 512);
+
+	if (s->sig_match) {
+		if (s->sig_match(buf, idx)==-EINVAL) {
+			LOG_ERROR("Bad signature found");
+			ret = -1;
+			if (ctxt.write_changes) {
+				if (!*bad)
+					*bad = g_hash_table_new(g_direct_hash, g_direct_equal);
+				ret = confirm_changes(off, s, buf, idx, *bad);
+				LOG_PRINT("Fixed");
+			} else
+				LOG_PRINT("To fix, rerun with -w");
+			/* restore the original if the new one was not written */
+			if (ret == -1)
+				memcpy(buf, saved_block, 512);
+		}
+	}
+
+	if (s->verify(fd, buf, idx, bad)==-1) {
+		LOG_ERROR("structure failed verification");
+		ret = -1;
+	}
+
+	if (ret == -1 || (ret == 0 && ctxt.verbose)) {
+		if (s->output(buf, idx, *bad, stdout)==-1) {
+			//fprintf(stderr, "at least one bad field found\n");
+			//ret = -1;
+		}
+	}
+
+	return ret;
+}				/* read_print_struct */
+
+
+/*
+ * get_device_size()
+ *
+ */
+int get_device_size(int fd)
+{
+	int ret = -1;
+	__u32 numblks;
+	struct stat buf;
+
+	if (fstat(fd, &buf) == -1) {
+		printf("%s: %s\n", ctxt.device, strerror(errno));
+		goto bail;
+	}
+
+	if (ctxt.dev_is_file) {		/* used during testing */
+		ctxt.device_size = buf.st_size;
+		goto finito;
+	} else if (S_ISCHR(buf.st_mode)) {
+		char *junk;
+		__u64 hi, lo, new, delta, last;
+		int ret;
+
+		junk = malloc_aligned(512);
+		hi = 0xfffffffffffffd00;
+		lo = 0ULL;
+		new = hi >> 1;
+
+		ctxt.device_size = 0;
+		do {
+			last = new;
+			myseek64(fd, new, SEEK_SET);
+			ret = read(fd, junk, 512);
+			if (ret == 512) {
+				// go higher
+				ctxt.device_size = (new + 512);
+				lo = new;
+				delta = (hi - lo) >> 1;
+				new = hi - delta;
+				new &= 0xfffffffffffffd00;
+			} else {
+				// go lower
+				hi = new;
+				delta = (hi - lo) >> 1;
+				new = lo + delta;
+				new &= 0xfffffffffffffd00;
+			}
+			
+			if (last == new || hi <= lo)
+				break;
+		} while (1);
+		while (ret == 512)
+		{
+			ctxt.device_size = (new + 512);
+			myseek64(fd, new, SEEK_SET);
+			ret = read(fd, junk, 512);
+			new += 512;
+		}
+		goto finito;
+	} else {
+		if (ioctl(fd, BLKGETSIZE, &numblks) == -1) {
+			printf("%s: %s\n", ctxt.device, strerror(errno));
+			goto bail;
+		} 
+		ctxt.device_size = numblks;
+		ctxt.device_size *= OCFS_SECTOR_SIZE;
+		goto finito;
+	}
+
+finito:
+	ret = 0;
+bail:
+	return ret;
+}				/* get_device_size */
+
+/*
+ * fsck_initialize()
+ *
+ */
+int fsck_initialize(char **buf)
+{
+	int ret = -1;
+	int fd;
+
+	if (ctxt.write_changes)
+		ctxt.flags = O_RDWR | O_LARGEFILE | O_SYNC;
+	else
+		ctxt.flags = O_RDONLY | O_LARGEFILE;
+
+	if (bind_raw(ctxt.device, &ctxt.raw_minor, ctxt.raw_device, sizeof(ctxt.raw_device)))
+		goto bail;
+
+	if (ctxt.verbose)
+		CLEAR_AND_PRINT("Bound %s to %s", ctxt.device, ctxt.raw_device);
+
+	if ((fd = myopen(ctxt.raw_device, ctxt.flags)) == -1) {
+		LOG_ERROR("Error opening %s.\n%s.", ctxt.raw_device,
+			  strerror(errno));
+		goto bail;
+	} else
+		ctxt.fd = fd;
+
+	if ((ctxt.hdr = malloc_aligned(OCFS_SECTOR_SIZE)) == NULL) {
+		LOG_INTERNAL();
+		goto bail;
+	}
+
+	if ((ctxt.vol_bm = malloc_aligned(VOL_BITMAP_BYTES)) == NULL) {
+		LOG_INTERNAL();
+		goto bail;
+	} else
+		memset(ctxt.vol_bm, 0, VOL_BITMAP_BYTES);
+
+	if ((*buf = malloc_aligned(OCFS_SECTOR_SIZE)) == NULL) {
+		LOG_INTERNAL();
+		goto bail;
+	}
+
+	/* Seek to the first block */
+	if (myseek64(fd, 0, SEEK_SET) == -1) {
+		LOG_INTERNAL();
+		goto bail;
+	}
+
+	/* Read the super block */
+	if (myread(fd, (char *)ctxt.hdr, OCFS_SECTOR_SIZE) == -1) {
+		LOG_INTERNAL();
+		goto bail;
+	}
+
+	/* Get the device size */
+	if (get_device_size(fd) == -1) {
+		LOG_ERROR("unable to get the device size. exiting");
+		goto bail;
+	}
+
+	ctxt.vol_bm_data = g_array_new(false, true, sizeof(bitmap_data));
+	ctxt.dir_bm_data = g_array_new(false, true, sizeof(bitmap_data));
+	ctxt.ext_bm_data = g_array_new(false, true, sizeof(bitmap_data));
+
+	ret = 0;
+
+bail:
+	return ret;
+}				/* fsck_initialize */
+
+/*
+ * main()
+ *
+ */
+int main(int argc, char **argv)
+{
+	int i;
+	int ret;
+	__u64 off;
+	char *buf = NULL;
+	char option = '\0';
+	ocfs_disk_structure *s;
+	ocfs_layout_t *l;
+	int j;
+	GHashTable *bad = NULL;
+	int changed = 0;
+
+	memset(&ctxt, 0, sizeof(ctxt));
+	init_global_context();
+
+	if (parse_fsck_cmdline(argc, argv) == -1)
+		goto quiet_bail;
+
+	if (optind >= argc) {
+		usage();
+		goto quiet_bail;
+	}
+
+	version(argv[0]);
+
+	strncpy(ctxt.device, argv[optind], OCFS_MAX_FILENAME_LENGTH);
+
+	if (fsck_initialize(&buf) == -1) {
+		goto quiet_bail;
+	}
+
+	/* Exit if not an OCFS volume */
+	if (memcmp(ctxt.hdr->signature, OCFS_VOLUME_SIGNATURE,
+		   strlen(OCFS_VOLUME_SIGNATURE))) {
+		printf("%s: bad signature in super block\n", ctxt.device);
+		goto quiet_bail;
+	}
+
+	/* Exit if heartbeat detected */
+	if (!ctxt.no_hb_chk) {
+		if (!check_heart_beat(&ctxt.fd, OCFSCK_PUBLISH_OFF,
+				      OCFS_SECTOR_SIZE))
+			goto quiet_bail;
+	}
+
+	/* Check ocfs volume header blocks */
+	for (i = 0; i < ocfs_header_layout_sz; i++) {
+		option = '\0';
+		l = &(ocfs_header_layout[i]);
+		if ((s = l->kind) == NULL || s->cls == NULL ||
+		    s->read == NULL || s->write == NULL) {
+			continue;
+		}
+
+		CLEAR_AND_PRINT("Checking %s...", l->name);
+
+		ret = 0;
+		for (j = 0; j < l->num_blocks; j++) {
+			bad = NULL;
+			off = BLOCKS2BYTES((l->block+j));
+
+			ret = read_print_struct(s, buf, off, j, &bad);
+			if (ret == -2)
+				break;
+			if (ret != -1 && !ctxt.modify_all)
+				continue;
+			while (ctxt.write_changes) {
+				changed = 0;
+				if (edit_structure(s, buf, j, &changed, &option) != -1)
+					continue;
+
+				if (!changed)
+					break;
+
+				if ((ret = confirm_changes(off, s, buf, j, bad)) == -1)
+					LOG_PRINT("Abort write");
+
+				break;
+			}
+
+			if (bad)
+				g_hash_table_destroy(bad);
+
+			if (option == 's')
+				continue;
+
+			else if (option == 'n' || option == 'd' || option == 'q')
+				break;
+		}
+
+		if (option == 'q' || option == 'd')
+			break;
+
+		if (ret < 0 && s == &diskhdr_t) {
+			LOG_ERROR("Volume header bad. Exiting");
+			goto bail;
+		}
+	}
+
+	if (option == 'q')
+		goto bail;
+
+	CLEAR_AND_PRINT("Checking Directories and Files...");
+	traverse_dir_nodes(ctxt.fd, ctxt.hdr->root_off, "/");
+
+	CLEAR_AND_PRINT("Checking Global Bitmap...");
+	if (check_global_bitmap(ctxt.fd) == -1)
+		LOG_ERROR("Global bitmap check failed");
+
+	CLEAR_AND_PRINT("Checking Extent Bitmap...");
+	if (check_node_bitmaps(ctxt.fd, ctxt.ext_bm_data, ctxt.ext_bm,
+			       ctxt.ext_bm_sz, "extent") == -1)
+		LOG_ERROR("Extent bitmap check failed");
+
+	CLEAR_AND_PRINT("Checking Directory Bitmap...");
+	if (check_node_bitmaps(ctxt.fd, ctxt.dir_bm_data, ctxt.dir_bm,
+			       ctxt.dir_bm_sz, "directory") == -1)
+		LOG_ERROR("Directory bitmap check failed");
+
+bail:
+	if (!int_err) {
+		if (cnt_err == 0)
+			CLEAR_AND_PRINT("%s: clean, %d objects, %u/%llu "
+					"blocks", ctxt.device, cnt_obj,
+				       	ctxt.vol_bm_data->len,
+				       	ctxt.hdr->num_clusters);
+		else
+			CLEAR_AND_PRINT("%s: %d errors, %d objects, %u/%llu "
+					"blocks", ctxt.device, cnt_err, cnt_obj,
+					ctxt.vol_bm_data->len,
+					ctxt.hdr->num_clusters);
+	}
+
+quiet_bail:
+	myclose(ctxt.fd);
+
+	unbind_raw(ctxt.raw_minor, ctxt.raw_device);
+
+	printf("\n");
+
+	if (ctxt.vol_bm_data)
+		g_array_free(ctxt.vol_bm_data, true);
+
+	if (ctxt.dir_bm_data)
+		g_array_free(ctxt.dir_bm_data, true);
+
+	if (ctxt.ext_bm_data)
+		g_array_free(ctxt.ext_bm_data, true);
+
+	for (i = 0; i < OCFS_MAXIMUM_NODES; ++i)
+		free_aligned(ctxt.dir_bm[i]);
+
+	for (i = 0; i < OCFS_MAXIMUM_NODES; ++i)
+		free_aligned(ctxt.ext_bm[i]);
+
+	free_aligned(buf);
+	free_aligned(ctxt.hdr);
+	free_aligned(ctxt.vol_bm);
+
+	exit(0);
+}				/* main */
+
+
+/*
+ * check_global_bitmap()
+ *
+ */
+int check_global_bitmap(int fd)
+{
+	int ret = -1;
+	bitmap_data *bm1;
+	bitmap_data *bm2;
+	__u8 *vol_bm = NULL;
+	__u32 i;
+	__u32 j;
+
+	/* sorting the global bitmap data on alloc_node and bit_num */
+	qsort(ctxt.vol_bm_data->data, ctxt.vol_bm_data->len,
+	      sizeof(bitmap_data), &qsort_compare);
+#if 0
+	for (i = 0; i < ctxt.vol_bm_data->len; ++i) {
+		bm1 = &(g_array_index(ctxt.vol_bm_data, bitmap_data, i));
+		printf("BOO: bit=%u, num=%u, blk=%u.%u, fe=%u.%u\n", bm1->bitnum,
+		       bm1->num, HILO(bm1->fss_off), HILO(bm1->parent_off));
+	}
+#endif
+
+	/* walk the list and check for any duplicates */
+	for (i = 0; i < ctxt.vol_bm_data->len; ++i) {
+		bm1 = &(g_array_index(ctxt.vol_bm_data, bitmap_data, i));
+		for (j = i + 1; j < ctxt.vol_bm_data->len; ++j) {
+			bm2 = &(g_array_index(ctxt.vol_bm_data, bitmap_data, j));
+			if (bm2->bitnum == bm1->bitnum) {
+				LOG_ERROR("Block %u.%u (bit# %u) allocated "
+					  "to File Entries %u.%u and %u.%u",
+					  HILO(bm1->fss_off), bm1->bitnum,
+					  HILO(bm1->parent_off),
+					  HILO(bm2->parent_off));
+				continue;
+			} else
+				break;
+		}
+	}
+
+	/* make a temp copy of the volume bitmap */
+	if ((vol_bm = malloc_aligned(VOL_BITMAP_BYTES)) == NULL) {
+		LOG_INTERNAL();
+		goto bail;
+	} else
+		memcpy(vol_bm, ctxt.vol_bm, VOL_BITMAP_BYTES);
+
+	/* clearing all the allocated bits in the global bitmap */
+	for (i = 0; i < ctxt.vol_bm_data->len; ++i) {
+		bm1 = &(g_array_index(ctxt.vol_bm_data, bitmap_data, i));
+		j = __test_and_clear_bit(bm1->bitnum, vol_bm);
+		if (!j) {
+			if (!test_bit(bm1->bitnum, ctxt.vol_bm))
+				LOG_ERROR("Bit %u is unset in the global bitmap",
+					  bm1->bitnum);
+		}
+	}
+
+#ifdef STILL_DEBUGGING
+	/* cross check... ensure no bit in the global bitmap is set */
+	/* The first 1MB in the bitmap is for the system fe's */
+	j = VOL_BITMAP_BYTES / ctxt.hdr->cluster_size;
+	for (i = j; i < ctxt.hdr->num_clusters; ++i) {
+		if (test_bit(i, vol_bm))
+			LOG_ERROR("Bit %u in the global bitmap is "
+				  "unaccounted", i);
+	}
+#endif
+
+	ret = 0;
+bail:
+	free_aligned(vol_bm);
+	return ret;
+}				/* check_global_bitmap */
+
+
+/*
+ * check_node_bitmaps()
+ *
+ * Checks extent and directory bitmaps for all nodes
+ *
+ */
+int check_node_bitmaps(int fd, GArray *bm_data, __u8 **node_bm,
+		       __u32 *node_bm_sz, char *str)
+{
+	int ret = -1;
+	bitmap_data *bm1;
+	bitmap_data *bm2;
+	__u8 *temp_bm[OCFS_MAXIMUM_NODES];
+	__u32 i;
+	__u32 j;
+
+	/* sorting the node bitmap data on alloc_node and bit_num */
+	qsort(bm_data->data, bm_data->len, sizeof(bitmap_data), &qsort_compare);
+#ifdef STILL_DEBUGGING
+	for (i = 0; i < bm_data->len; ++i) {
+		bm1 = &(g_array_index(bm_data, bitmap_data, i));
+	}
+#endif
+	for (i = 0; i < bm_data->len; ++i) {
+		bm1 = &(g_array_index(bm_data, bitmap_data, i));
+		for (j = i + 1; j < bm_data->len; ++j) {
+			bm2 = &(g_array_index(bm_data, bitmap_data, j));
+			if (bm2->alloc_node != bm1->alloc_node)
+				break;
+			if (bm2->bitnum == bm1->bitnum) {
+				LOG_ERROR("Block %u.%u (bit# %u) allocated "
+					  "to %s %u.%u and %u.%u on node %u",
+					  HILO(bm1->fss_off), bm1->bitnum,
+					  str, HILO(bm1->parent_off),
+					  HILO(bm2->parent_off), bm1->alloc_node);
+				continue;
+			} else
+				break;
+		}
+	}
+
+	/* make a temp copy of the node bitmaps */
+	for (i = 0; i < OCFS_MAXIMUM_NODES; ++i) {
+		if (!node_bm_sz[i]) {
+			temp_bm[i] = NULL;
+			continue;
+		}
+		if ((temp_bm[i] = malloc_aligned(node_bm_sz[i])) == NULL) {
+			LOG_INTERNAL();
+			goto bail;
+		} else
+			memcpy(temp_bm[i], node_bm[i], node_bm_sz[i]);
+	}
+
+	/* clearing all the allocated bits in the extent bitmap */
+	for (i = 0; i < bm_data->len; ++i) {
+		bm1 = &(g_array_index(bm_data, bitmap_data, i));
+		if (!temp_bm[bm1->alloc_node]) {
+			LOG_ERROR("%s bitmap for node %d not allocated but "
+				  "structure at offset %u.%u suggests otherwise",
+				  str, bm1->alloc_node, HILO(bm1->fss_off));
+			continue;
+		}
+		j = __test_and_clear_bit(bm1->bitnum, temp_bm[bm1->alloc_node]);
+		if (!j) {
+			if (!test_bit(bm1->bitnum, node_bm[bm1->alloc_node]))
+				LOG_ERROR("Bit %u is unset in the %s bitmap "
+					  "of node %d", bm1->bitnum, str,
+					  bm1->alloc_node);
+		}
+	}
+
+#ifdef STILL_DEBUGGING
+	/* cross check... ensure no bit in the extent/directory bitmap is set */
+	for (i = 0; i < OCFS_MAXIMUM_NODES; ++i) {
+		if (!temp_bm[i])
+			continue;
+		len = node_bm_sz[i] * 8;
+		for (j = 0; j < len; ++j) {
+			if (test_bit(j, temp_bm[i]))
+				LOG_ERROR("Bit %u in the %s bitmap of node "
+					  "%d is unaccounted", j, str, i);
+		}
+	}
+#endif
+
+	ret = 0;
+bail:
+	for (i = 0; i < OCFS_MAXIMUM_NODES; ++i)
+		free_aligned(temp_bm[i]);
+	return ret;
+}				/* check_node_bitmaps */
+
+
+/*
+ * qsort_compare()
+ *
+ */
+int qsort_compare(const void *q1, const void *q2)
+{
+	bitmap_data *bm1 = (bitmap_data *)q1;
+	bitmap_data *bm2 = (bitmap_data *)q2;
+	__s32 ret;
+
+	ret = bm1->alloc_node - bm2->alloc_node;
+	if (!ret)
+		ret = bm1->bitnum - bm2->bitnum;
+
+	return ret;
+}				/* qsort_compare */
+
+static int fe_compare_func(const void *m1, const void *m2);
+
+/* if we ever rewrite this as a shared library or 
+ * parallelized fsck we will have to change this */
+ocfs_dir_node *globaldir = NULL;
+
+static int fe_compare_func(const void *m1, const void *m2)
+{
+	ocfs_file_entry *fe1, *fe2;
+	__u8 idx1, idx2;
+	int ret;
+
+	if (globaldir == NULL) {
+		LOG_INTERNAL();
+		exit(0);
+	}
+
+	idx1 = *(__u8 *)m1;
+	idx2 = *(__u8 *)m2;
+
+	fe1 = (ocfs_file_entry *) ((char *)FIRST_FILE_ENTRY(globaldir) + (idx1 * OCFS_SECTOR_SIZE));
+	fe2 = (ocfs_file_entry *) ((char *)FIRST_FILE_ENTRY(globaldir) + (idx2 * OCFS_SECTOR_SIZE));
+
+	if (IS_FE_DELETED(fe1->sync_flags) ||
+	    (!(fe1->sync_flags & OCFS_SYNC_FLAG_VALID)) ||
+	    IS_FE_DELETED(fe2->sync_flags) ||
+	    (!(fe2->sync_flags & OCFS_SYNC_FLAG_VALID)))
+		return 0;
+
+	ret = strncmp(fe1->filename, fe2->filename, 255);
+	
+	return -ret;
+}
+
+
+/*
+ * traverse_dir_nodes()
+ *
+ */
+void traverse_dir_nodes(int fd, __u64 offset, char *dirpath)
+{
+	int i;
+	int ret;
+	char *dirbuf = NULL;
+	ocfs_file_entry *febuf = NULL;
+	__u64 dir_offset;
+	__u64 off;
+	ocfs_disk_structure *dirst;
+	ocfs_disk_structure *fest;
+	GHashTable *bad;
+	ocfs_dir_node *dir;
+	__u8 *index = NULL;
+	int deleted_files;
+   
+	dirst = &dirnode_t;
+	fest = &fileent_t;
+	bad = NULL;
+
+	if ((index = malloc(256)) == NULL) {
+		LOG_INTERNAL();
+		goto bail;
+	}
+
+	if ((dirbuf = malloc_aligned(DIR_NODE_SIZE)) == NULL) {
+		LOG_INTERNAL();
+		goto bail;
+	}
+
+	if ((febuf = (ocfs_file_entry *) malloc_aligned(OCFS_SECTOR_SIZE)) == NULL) {
+		LOG_INTERNAL();
+		goto bail;
+	}
+
+	dir_offset = offset;
+	dir = (ocfs_dir_node *)dirbuf;
+
+	CLEAR_AND_PRINT(dirpath);
+
+	while (1) {
+		ret = read_print_struct(dirst, dirbuf, dir_offset, 0, &bad);
+
+		if (bad)
+			g_hash_table_destroy(bad);
+
+		if (ret == -1) {
+			LOG_ERROR("failed to read directory at offset %u.%u",
+				  HILO(dir_offset));
+			goto bail;
+		}
+
+		/* check the dir->index integrity */
+		globaldir = dir;
+		memcpy(index, dir->index, dir->num_ent_used);
+		qsort(index, dir->num_ent_used, sizeof(__u8), fe_compare_func);
+
+		if (memcmp(index, dir->index, dir->num_ent_used) != 0) {
+			__u8 *idxtmp = NULL;
+
+			LOG_ERROR("Bad dir index found");
+			if (ctxt.write_changes) {
+				if ((idxtmp = malloc(256)) == NULL) {
+					LOG_INTERNAL();
+					goto bail;
+				}
+				memcpy(idxtmp, dir->index, 256);
+				memcpy(dir->index, index, dir->num_ent_used);
+				if (dirst->write(ctxt.fd, dirbuf, dir_offset, 0) == -1) {
+					LOG_ERROR("failed to write at offset %u.%u",
+						  HILO(dir_offset));
+					memcpy(dir->index, idxtmp, 256);
+				}
+				safefree(idxtmp);
+				LOG_PRINT("Fixed");
+			} else
+				LOG_PRINT("To fix, rerun with -w");
+		}
+
+		/* check the undeletable dir bug, BUG #3016598 */
+		for (i=0, deleted_files=0; i < dir->num_ent_used; i++) {
+			if (IS_FE_DELETED((FILEENT(dir, i))->sync_flags))
+				deleted_files++;
+		}
+		if (dir->num_ent_used && dir->num_ent_used == deleted_files) {
+			/* we hit the bug... fix by zeroing num_ent_used */
+			LOG_ERROR("Undeletable directory found");
+			if (ctxt.write_changes) {
+				dir->num_ent_used = 0;
+				if (dirst->write(ctxt.fd, dirbuf, dir_offset, 0)==-1) {
+					LOG_ERROR("failed to write at offset %u/%u", dir_offset);
+					dir->num_ent_used = 1;
+				}
+				LOG_PRINT("Fixed");
+			} else
+				LOG_PRINT("To fix, rerun with -w");
+		}
+
+		/* Add bitmap entry for the dirnode itself */
+		add_bm_data(dir->alloc_file_off, 1, dir->alloc_node, 
+			    dir_offset, bm_dir);
+
+		// TODO: add in directory editing here
+		for (i = 0; i < dir->num_ent_used; i++) {
+			off = dir_offset;
+			off += OCFS_SECTOR_SIZE;	/* move past the dirnode header */
+			off += (OCFS_SECTOR_SIZE * dir->index[i]);
+
+			ret = read_print_struct(fest, (char *)febuf, off, 0, &bad);
+			if (bad)
+				g_hash_table_destroy(bad);
+			if (ret == -1) {
+				LOG_ERROR("failed to read file entry at offset %u.%u",
+					  HILO(off));
+				continue;
+			}
+
+			// TODO: add in file entry editing here
+
+			if (!IS_FE_DELETED(febuf->sync_flags))
+				check_file_entry(fd, febuf, off, false, dirpath);
+		}
+
+		/* is there another directory chained off of this one? */
+		if (dir->next_node_ptr == -1)
+			break;		// nope, we're done
+		else
+			dir_offset = dir->next_node_ptr;	// keep going
+	}
+
+bail:
+	free_aligned(dirbuf);
+	free_aligned(febuf);
+	safefree(index);
+}				/* traverse_dir_nodes */
+
+/*
+ * handle_one_cdsl_entry()
+ *
+ */
+void handle_one_cdsl_entry(int fd, ocfs_file_entry *fe, __u64 offset)
+{
+}				/* handle_one_cdsl_entry */
+
+
+/*
+ * check_file_entry()
+ *
+ */
+void check_file_entry(int fd, ocfs_file_entry *fe, __u64 offset,
+		      bool systemfile, char *dirpath)
+{
+	void *buf = NULL;
+	int indx = 0;
+	int val = 0;
+	char *path = NULL;
+
+	if (systemfile)
+		val = 3;
+	else {
+		if (fe->attribs & OCFS_ATTRIB_FILE_CDSL)
+			val = 1;
+		else if (fe->attribs & OCFS_ATTRIB_DIRECTORY)
+			val = 2;
+		else if (fe->attribs & (OCFS_ATTRIB_REG | OCFS_ATTRIB_SYMLINK))
+			val = 3;
+		else {
+			LOG_ERROR ("unknown attribs %x at offset %u.%u",
+				   fe->attribs, HILO(offset));
+			goto bail;
+		}
+	}
+
+	++cnt_obj;
+	if (val == 2)
+		path = g_strdup_printf("%s%s/", dirpath, fe->filename);
+	else
+		path = g_strdup_printf("%s%s", dirpath, fe->filename);
+
+	switch (val) {
+	case 1:
+		CLEAR_AND_PRINT(path);
+		handle_one_cdsl_entry(fd, fe, offset);
+		break;
+
+	case 2:
+		if (fe->extents[0].disk_off) {
+			handle_leaf_extents(fd, fe->extents, 1,
+				 	OCFS_INVALID_NODE_NUM, fe->this_sector);
+			traverse_dir_nodes(fd, fe->extents[0].disk_off, path);
+		} else
+			LOG_ERROR("Invalid dir entry at %u.%u", HILO(offset));
+		break;
+
+	case 3:
+		CLEAR_AND_PRINT(path);
+		if (fe->local_ext)
+			handle_leaf_extents(fd, fe->extents,
+					    OCFS_MAX_FILE_ENTRY_EXTENTS,
+					    OCFS_INVALID_NODE_NUM, fe->this_sector);
+		else {
+			if ((buf = malloc_aligned(MAX_EXTENTS * OCFS_SECTOR_SIZE)) == NULL) {
+				LOG_INTERNAL();
+				goto bail;
+			}
+
+			traverse_fe_extents(fd, fe, buf, &indx);
+
+			/* check ext->next_data_ext */
+			check_next_data_ext(fe, buf, indx);
+
+			/* check fe->last_ext_ptr */
+			check_fe_last_data_ext(fe, buf, indx);
+		}
+		break;
+
+	default:
+		break;
+	}
+
+bail:
+	safefree(path);
+	free_aligned(buf);
+	return ;
+}				/* check_file_entry */
+
+/*
+ * add_bm_data()
+ *
+ */
+bitmap_data * add_bm_data(__u64 start, __u64 len, __s32 alloc_node,
+			  __u64 parent_offset, int type)
+{
+	bitmap_data *bm = NULL;
+	__u32 bitnum = 0;
+	__u32 num = 0;
+	void *buf = NULL;
+	void *p;
+	int i;
+
+	switch (type) {
+	case bm_extent:
+		bitnum = start >> OCFS_LOG_SECTOR_SIZE;
+		num = len;
+		break;
+
+	case bm_dir:
+		bitnum = start / OCFS_DEFAULT_DIR_NODE_SIZE;
+		num = len;
+		break;
+
+	case bm_symlink:
+		break;
+
+	case bm_filedata:
+		bitnum = (start - ctxt.hdr->data_start_off) >>
+				ctxt.cluster_size_bits;
+		num = len >> ctxt.cluster_size_bits;
+		break;
+
+	default:
+		break;
+	}
+
+	if (num == 0)
+		goto bail;
+
+	if ((buf = malloc(sizeof(bitmap_data) * num)) == NULL) {
+		LOG_INTERNAL();
+		goto bail;
+	}
+
+	for (i = 0, p = buf; i < num; ++i) {
+		bm = (bitmap_data *)p;
+		bm->bitnum = bitnum + i;
+		bm->fss_off = start;
+		bm->alloc_node = alloc_node;
+		bm->parent_off = parent_offset;
+		p += sizeof(bitmap_data);
+	}
+
+	bm = (bitmap_data *)buf;
+
+	switch (type) {
+	case bm_dir:
+		g_array_append_vals(ctxt.dir_bm_data, bm, num);
+		break;
+
+	case bm_extent:
+		g_array_append_vals(ctxt.ext_bm_data, bm, num);
+		break;
+
+	case bm_filedata:
+		g_array_append_vals(ctxt.vol_bm_data, bm, num);
+		break;
+
+	default:
+		break;
+	}
+
+bail:
+	return bm;
+}				/* add_bm_data */
+
+
+/*
+ * handle_leaf_extents()
+ *
+ */
+int handle_leaf_extents (int fd, ocfs_alloc_ext *arr, int num, __u32 node,
+			 __u64 parent_offset)
+{
+	int i;
+	int ret = 0;
+
+	for (i = 0; i < num; i++) {
+		if (arr[i].disk_off)
+			if (!add_bm_data(arr[i].disk_off, arr[i].num_bytes,
+					 node, parent_offset, bm_filedata))
+				ret = -1;
+	}
+
+	return ret;
+}				/* handle_leaf_extents */
+
+
+/*
+ * traverse_extent()
+ *
+ */
+void traverse_extent(int fd, ocfs_extent_group * exthdr, int flag, void *buf,
+		     int *indx)
+{
+	ocfs_extent_group *ext = NULL;
+	int i;
+	int j;
+	__u64 len;
+	int ret;
+	int type;
+	ocfs_disk_structure *disk_struct;
+	GHashTable *bad;
+
+	if (*indx >= MAX_EXTENTS) {
+		LOG_ERROR("Too many extents after ext=%u.%u",
+			  HILO(exthdr->this_ext));
+		goto bail;
+	}
+
+	for (i = 0; i < exthdr->next_free_ext; ++i) {
+		if (!exthdr->extents[i].disk_off)
+			continue;
+
+		ext = (ocfs_extent_group *) (buf + (*indx * OCFS_SECTOR_SIZE));
+		++*indx;
+
+		if (flag == OCFS_EXTENT_HEADER)
+			disk_struct = &exthdr_t;
+		else
+			disk_struct = &extdat_t;
+
+		ret = read_print_struct(disk_struct, (char *)ext,
+					exthdr->extents[i].disk_off, 0, &bad);
+
+		if (bad)
+			g_hash_table_destroy(bad);
+
+		if (ret == -1) {
+			LOG_ERROR("failed to read extent at offset %u.%u",
+				  HILO(exthdr->extents[i].disk_off));
+			goto bail;
+		}
+
+		// TODO: add in extent editing here
+
+		/* check up_hdr_node_ptr */
+		if (exthdr->this_ext != ext->up_hdr_node_ptr) {
+			LOG_ERROR("up_hdr_node_ptr %u.%u in extent %u.%u "
+				  "should be %u.%u", HILO(ext->up_hdr_node_ptr),
+				  HILO(ext->this_ext), HILO(exthdr->this_ext));
+		}
+
+		/* check first file offset */
+		if (exthdr->extents[i].file_off != ext->extents[0].file_off) {
+			LOG_ERROR("extents[0].file_off=%u.%u in extent %u.%u "
+				  "should be %u.%u", HILO(ext->extents[0].file_off),
+				  HILO(ext->this_ext), HILO(exthdr->extents[i].file_off));
+		}
+
+		/* check total bytes */
+		for (j = 0, len = 0; j < OCFS_MAX_DATA_EXTENTS; j++)
+			len += ext->extents[j].num_bytes;
+
+		if (exthdr->extents[i].num_bytes != len) {
+			LOG_ERROR("total num_bytes in extent %u.%u is %u.%u "
+				  "but should be %u.%u", HILO(ext->this_ext),
+				  HILO(len), HILO(exthdr->extents[i].num_bytes));
+		}
+
+		/* Add bitmap entry for the extent itself */
+		add_bm_data(ext->alloc_file_off, 1, ext->alloc_node, ext->this_ext,
+			    bm_extent);
+
+		if (flag == OCFS_EXTENT_HEADER) {
+			type = ext->granularity ? OCFS_EXTENT_HEADER : OCFS_EXTENT_DATA;
+			traverse_extent(fd, ext, type, buf, indx);
+		} else {
+			handle_leaf_extents(fd, ext->extents, ext->next_free_ext,
+					    OCFS_INVALID_NODE_NUM, ext->this_ext);
+		}
+	}
+
+bail:
+	return ;
+}				/* traverse_extent */
+
+
+/*
+ * traverse_fe_extents()
+ *
+ */
+void traverse_fe_extents(int fd, ocfs_file_entry *fe, void *buf, int *indx)
+{
+	int i;
+	int j;
+	int ret;
+	__u64 len;
+	ocfs_extent_group *ext = NULL;
+	int type;
+	ocfs_disk_structure *disk_struct;
+	GHashTable *bad;
+
+	if (*indx >= MAX_EXTENTS) {
+		LOG_ERROR("error too many extents in fe at offset %u.%u",
+			  HILO(fe->this_sector));
+		goto bail;
+	}
+
+	for (i = 0; i < fe->next_free_ext; i++) {
+		if (!fe->extents[i].disk_off)
+			continue;
+
+		ext = (ocfs_extent_group *) (buf + (*indx * OCFS_SECTOR_SIZE));
+		++*indx;
+
+		if (fe->granularity)
+			disk_struct = &exthdr_t;
+		else
+			disk_struct = &extdat_t;
+
+		ret = read_print_struct(disk_struct, (char *)ext, 
+					fe->extents[i].disk_off, 0, &bad);
+		if (bad)
+			g_hash_table_destroy(bad);
+
+		if (ret == -1) {
+			LOG_ERROR("failed to read extent at offset %u.%u",
+				  HILO(fe->extents[i].disk_off));
+			goto bail;
+		}
+
+		// TODO: add in extent editing here
+		if (fe->this_sector != ext->up_hdr_node_ptr) {
+			LOG_ERROR("up_hdr_node_ptr %u.%u in extent %u.%u "
+				  "should be %u.%u", HILO(ext->up_hdr_node_ptr),
+				  HILO(ext->this_ext), HILO(fe->this_sector));
+		}
+
+		/* check first file offset */
+		if (fe->extents[i].file_off != ext->extents[0].file_off) {
+			LOG_ERROR("extents[0].file_off=%u.%u in extent %u.%u "
+				  "should be %u.%u", HILO(ext->extents[0].file_off),
+				  HILO(ext->this_ext), HILO(fe->extents[i].file_off));
+		}
+
+		/* check total bytes */
+		for (j = 0, len = 0; j < OCFS_MAX_DATA_EXTENTS; j++)
+			len += ext->extents[j].num_bytes;
+
+		if (fe->extents[i].num_bytes != len) {
+			LOG_ERROR("total num_bytes in extent %u.%u is %u.%u "
+				  "but should be %u.%u", HILO(ext->this_ext),
+				  HILO(len), HILO(fe->extents[i].num_bytes));
+		}
+
+		/* Add bitmap entry for the extent itself */
+		add_bm_data(ext->alloc_file_off, 1, ext->alloc_node, ext->this_ext,
+			    bm_extent);
+
+		if (fe->granularity) {
+			type = ext->granularity ? OCFS_EXTENT_HEADER : OCFS_EXTENT_DATA;
+			traverse_extent(fd, ext, type, buf, indx);
+		} else {
+			handle_leaf_extents(fd, ext->extents, ext->next_free_ext,
+					    OCFS_INVALID_NODE_NUM, ext->this_ext);
+		}
+	}
+
+bail:
+	return ;
+}				/* traverse_fe_extents */
+
+
+/*
+ * check_next_data_ext()
+ *
+ */
+int check_next_data_ext(ocfs_file_entry *fe, void *buf, int indx)
+{
+	void *ptr;
+	int i;
+	__u64 next_data_ext;
+	ocfs_extent_group *ext;
+	int ret = 0;
+
+	ptr = buf + ((indx - 1) * OCFS_SECTOR_SIZE);
+
+	for (i = indx - 1, next_data_ext = 0; i >= 0; --i,
+	     ptr -= OCFS_SECTOR_SIZE) {
+		ext = (ocfs_extent_group *)ptr;
+
+		if (ext->type != OCFS_EXTENT_DATA)
+			continue;
+
+		if (ext->next_data_ext != next_data_ext) {
+			LOG_ERROR("ext->next_data_ext=%u.%u in extent "
+				  "%u.%u instead of %u.%u",
+				  HILO(ext->next_data_ext),
+				  HILO(ext->this_ext),
+				  HILO(next_data_ext));
+			ret = -1;
+		}
+		next_data_ext = ext->this_ext;
+	}
+
+	return ret;
+}				/* check_next_data_ext */
+
+/*
+ * check_fe_last_data_ext()
+ *
+ */
+int check_fe_last_data_ext(ocfs_file_entry *fe, void *buf, int indx)
+{
+	ocfs_extent_group *ext;
+	int ret = 0;
+
+	ext = (ocfs_extent_group *) (buf + ((indx - 1) * OCFS_SECTOR_SIZE));
+
+	if (fe->last_ext_ptr != ext->this_ext) {
+		LOG_ERROR("fe->last_ext_ptr=%u.%u in fe %u.%u "
+			  "instead of %u.%u", HILO(fe->last_ext_ptr),
+			  HILO(fe->this_sector), HILO(ext->this_ext));
+		ret = -1;
+	}
+
+	return ret;
+}				/* check_fe_last_data_ext */
+
+
+/*
+ * check_heart_beat()
+ *
+ */
+int check_heart_beat(int *file, __u64 publ_off, __u32 sect_size)
+{
+	char *publish = NULL;
+	ocfs_super osb;
+	int ret = 0;
+	int i;
+	int waittime;
+	char *node_names[OCFS_MAXIMUM_NODES];
+	__u32 nodemap;
+
+	for (i = 0; i < OCFS_MAXIMUM_NODES; ++i)
+		node_names[i] = NULL;
+
+	memset (&osb, 0, sizeof(ocfs_super));
+
+	if (!read_publish(*file, publ_off, sect_size, (void **)&publish)) {
+		LOG_INTERNAL();
+		goto bail;
+	}
+
+	/* alloc osb and pop sect_size */
+	osb.sect_size = sect_size;
+
+        /* call ocfs_update_publish_map(first_time = true) */
+	ocfs_update_publish_map (&osb, (void *)publish, true);
+
+	/* sleep(OCFS_NM_HEARTBEAT_TIME * 10) */
+	printf("Checking heart beat on volume ");
+	waittime = (OCFS_NM_HEARTBEAT_TIME/1000);
+	waittime = (waittime ? waittime : 1);
+	for (i = 0; i < OCFS_HBT_WAIT; ++i) {
+		printf(".");
+		fflush(stdout);
+		sleep(waittime);
+	}
+   
+	/* Close and re-open device to force disk read */
+	myclose(*file);
+
+	if ((*file = myopen(ctxt.raw_device, ctxt.flags)) == -1) {
+		LOG_INTERNAL();
+		goto bail;
+	}
+
+	memset (publish, 0, sect_size);
+	if (!read_publish(*file, publ_off, sect_size, (void **)&publish)) {
+		LOG_INTERNAL();
+		goto bail;
+	}
+
+	/* call ocfs_update_publish_map(first_time = false) */
+	ocfs_update_publish_map (&osb, (void *)publish, false);
+
+	printf("\r                                                \r");
+	fflush(stdout);
+
+	/* OCFS currently supports upto 32 nodes */
+	nodemap = LO(osb.publ_map);
+	if (!nodemap)
+		goto success;
+
+	/* Get names of all the nodes */
+	get_node_names(*file, ctxt.hdr, node_names, sect_size);
+
+	/* Prints the ones which are mounted */
+	printf("%s is mounted on nodes:", ctxt.device);
+	print_node_names(node_names, nodemap);
+
+	if (ctxt.write_changes) {
+		ctxt.write_changes = false;
+		printf("umount volume on node(s) before running fsck -w\n");
+		printf("Continuing in read-only mode\n");
+	}
+
+	printf("As %s is mounted on one or more nodes, fsck.ocfs may "
+	       "display false-positive errors\n", ctxt.device);
+
+success:
+	ret = 1;
+bail:
+	for (i = 0; i < OCFS_MAXIMUM_NODES; ++i)
+		free(node_names[i]);
+
+	free_aligned(publish);
+	return ret;
+}				/* check_heart_beat */
+
+/*
+ * read_publish()
+ *
+ */
+int read_publish(int file, __u64 publ_off, __u32 sect_size, void **buf)
+{
+	int ret = 0;
+	__u32 pub_len;
+
+	pub_len = OCFS_MAXIMUM_NODES * sect_size;
+
+	if (!*buf) {
+		if (!(*buf = malloc_aligned(pub_len))) {
+			LOG_INTERNAL();
+			goto bail;
+		}
+	}
+
+	if (myseek64(file, publ_off, SEEK_SET) == -1) {
+		LOG_INTERNAL();
+		goto bail;
+	}
+
+	if (myread(file, *buf, pub_len) == -1) {
+		LOG_INTERNAL();
+		goto bail;
+	}
+			
+	ret = 1;
+
+bail:
+	return ret;
+}				/* read_publish */
+
+/*
+ * get_node_names()
+ *
+ */
+int get_node_names(int file, ocfs_vol_disk_hdr *volhdr, char **node_names,
+		   __u32 sect_size)
+{
+	char *buf = NULL;
+	char *p;
+	int len;
+	int ret = 0;
+	int i;
+	ocfs_disk_node_config_info *conf;
+
+	len = volhdr->node_cfg_size;
+	if (!(buf = (char *) malloc_aligned(len))) {
+		LOG_INTERNAL();
+		goto bail;
+	} else
+		memset(buf, 0, len);
+
+	if (myseek64(file, volhdr->node_cfg_off, SEEK_SET) == -1) {
+		LOG_INTERNAL();
+		goto bail;
+	}
+
+	if (myread(file, buf, len) == -1) {
+		LOG_INTERNAL();
+		goto bail;
+	}
+
+	p = buf + (sect_size * 2);
+	for (i = 0; i < OCFS_MAXIMUM_NODES; ++i, p += sect_size) {
+		conf = (ocfs_disk_node_config_info *)p;
+		if (conf->node_name[0])
+			node_names[i] = strdup(conf->node_name);
+	}
+
+	ret = 1;
+bail:
+	free_aligned(buf);
+	return ret;
+}				/* get_node_names */
+
+
+/*
+ * print_node_names()
+ *
+ */
+void print_node_names(char **node_names, __u32 nodemap)
+{
+	int i, j;
+	char comma = '\0';
+
+	for (j = 1, i = 0; i < OCFS_MAXIMUM_NODES; ++i, j <<= 1) {
+		if (nodemap & j) {
+			if (node_names[i])
+				printf("%c %s", comma, node_names[i]);
+			else
+				printf("%c %d", comma, i);
+			comma = ',';
+		}
+	}
+	printf("\n");
+}				/* print_node_names */

Added: trunk/fsck/fsck.h
===================================================================
--- trunk/fsck/fsck.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/fsck/fsck.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,286 @@
+/*
+ * fsck.h
+ *
+ * Function prototypes, macros, etc. for related 'C' files
+ *
+ * Copyright (C) 2003, 2004 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Sunil Mushran
+ */
+
+#ifndef FSCK_H
+#define FSCK_H
+
+#define _GNU_SOURCE
+
+#define _LARGEFILE64_SOURCE
+
+#include <stdio.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <glib.h>
+#include <unistd.h>
+#include <string.h>
+#include <grp.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <asm/types.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+
+#include <libocfs.h>
+
+#include "classes.h"
+#include "sig.h"
+#include "fsck_print.h"
+#include "verify.h"
+#include "defaults.h"
+#include "layout.h"
+
+extern bool prn_err;
+extern bool int_err;
+extern int  cnt_err;
+extern int cnt_wrn;
+
+#define MAX_NODES			OCFS_MAXIMUM_NODES
+#define MAX_SYSTEM_FILES		(CLEANUP_FILE_BASE_ID + OCFS_MAXIMUM_NODES) /* 193? */
+#define DIR_NODE_SIZE			(1024 * 128)
+#define IS_INVALID_FIELD_NUM(c,n)	((n) >= (c)->num_members || (n) < 0)
+#define USER_INPUT_MAX			1024
+#define BITS_PER_BYTE			8
+#define VOL_BITMAP_BYTES		(1024 * 1024)
+
+#define DISK_OFF_TO_BIT_NUMBER(off)      \
+		((off - ctxt.hdr->data_start_off) >> ctxt.cluster_size_bits)
+#define BIT_NUMBER_TO_DISK_OFF(num)      \
+		((num << ctxt.cluster_size_bits) + ctxt.hdr->data_start_off)
+#define NUM_BYTES_TO_NUM_BITS(bytes)     \
+		(bytes >> ctxt.cluster_size_bits)
+#define MAX_BITS                         \
+		(ctxt.hdr->num_clusters * BITS_PER_BYTE)
+
+#define safefree(a)		\
+do {				\
+	if (a)			\
+		free(a);	\
+	(a) = NULL;		\
+} while (0)
+
+#define LOG_INTERNAL()						\
+	do {							\
+		prn_err = true; int_err = true;			\
+		fprintf(stdout, "\nINTERNAL ERROR: ");		\
+		fprintf(stdout, "%s, %d", __FILE__, __LINE__);	\
+		fflush(stdout);					\
+	} while (0)
+
+/* override libocfs definition */
+#undef LOG_ERROR
+#define LOG_ERROR(fmt, arg...)					\
+	do {							\
+		prn_err = true; cnt_err++;			\
+		fprintf(stdout, "\nERROR: ");			\
+		fprintf(stdout, fmt, ## arg);			\
+		fprintf(stdout, ", %s, %d", __FILE__, __LINE__);\
+		fflush(stdout);					\
+	} while (0)
+
+#define LOG_WARNING(fmt, arg...)				\
+	do {							\
+		prn_err = true; cnt_wrn++;			\
+		fprintf(stdout, "\nWARNING: ");			\
+		fprintf(stdout, fmt, ## arg);			\
+		fflush(stdout);					\
+	} while (0)
+
+#define LOG_PRINT(fmt, arg...)					\
+	do {							\
+		prn_err = true;					\
+		fprintf(stdout, "\n");				\
+		fprintf(stdout, fmt, ## arg);			\
+		fflush(stdout);					\
+	} while (0)
+
+#define CLEAR_AND_PRINT(fmt, arg...)					\
+do {									\
+	if (!ctxt.quiet) {						\
+		gchar *_a = g_strdup_printf(fmt, ## arg);		\
+		if (ctxt.verbose)					\
+			printf("\n%s\n", _a);				\
+		else {							\
+			int _j = strlen(_a);				\
+			int _l = prn_len - _j;				\
+			char _n = (prn_err ? '\n' : '\r');		\
+			if (_l > 0) {					\
+				gchar *_s = g_strnfill(_l, ' ');	\
+				printf("%c%s%s", _n, _a, _s);		\
+				prn_len = _j;				\
+				free(_s);				\
+			} else						\
+				prn_len = printf("%c%s", _n, _a);	\
+			prn_err = false;				\
+		}							\
+		free(_a);						\
+	}								\
+} while (0)
+
+typedef struct _filedata
+{
+    ocfs_io_runs *array;
+    __u32 num;
+    mode_t mode;
+    uid_t user;
+    gid_t group;
+    unsigned int major;
+    unsigned int minor;
+    char *linkname;
+} filedata;
+
+
+void usage(void);
+int parse_fsck_cmdline(int argc, char **argv);
+int edit_structure(ocfs_disk_structure *s, char *buf, int idx, int *changed,
+		   char *option);
+int confirm_changes(__u64 off, ocfs_disk_structure *s, char *buf, int idx,
+		    GHashTable *bad);
+int read_print_struct(ocfs_disk_structure *s, char *buf, __u64 off, int idx,
+		      GHashTable **bad);
+void *mem_alloc(int len);
+int fsck_initialize(char **buf);
+int qsort_compare(const void *q1, const void *q2);
+int check_global_bitmap(int fd);
+int check_node_bitmaps(int fd, GArray *bm_data, __u8 **node_bm,
+		       __u32 *node_bm_sz, char *str);
+void handle_one_cdsl_entry(int fd, ocfs_file_entry *fe, __u64 offset);
+int handle_leaf_extents (int fd, ocfs_alloc_ext *arr, int num, __u32 node,
+			 __u64 parent_offset);
+void traverse_dir_nodes(int fd, __u64 offset, char *path);
+void check_file_entry(int fd, ocfs_file_entry *fe, __u64 offset,
+		      bool systemfile, char *path);
+void traverse_extent(int fd, ocfs_extent_group * exthdr, int flag, void *buf,
+		     int *indx);
+void traverse_fe_extents(int fd, ocfs_file_entry *fe, void *buf, int *indx);
+int traverse_local_extents(int fd, ocfs_file_entry *fe);
+int check_next_data_ext(ocfs_file_entry *fe, void *buf, int indx);
+int check_fe_last_data_ext(ocfs_file_entry *fe, void *buf, int indx);
+int get_device_size(int fd);
+int check_heart_beat(int *file, __u64 publ_off, __u32 sect_size);
+int read_publish(int file, __u64 publ_off, __u32 sect_size, void **buf);
+int get_node_names(int file, ocfs_vol_disk_hdr *volhdr, char **node_names,
+		   __u32 sect_size);
+void print_node_names(char **node_names, __u32 nodemap);
+
+////////////////////////
+void ocfs_extent_map_init (ocfs_extent_map * map);
+
+void ocfs_extent_map_destroy (ocfs_extent_map * map);
+
+#define ocfs_extent_map_get_count(map)  ((map)->count)
+
+bool ocfs_extent_map_add (ocfs_extent_map * map, __s64 virtual,
+			  __s64 physical, __s64 sectors);
+
+void ocfs_extent_map_remove (ocfs_extent_map * map, __s64 virtual,
+			     __s64 sectors);
+
+bool ocfs_extent_map_lookup (ocfs_extent_map * map, __s64 virtual,
+			     __s64 * physical, __s64 * sectors, __u32 * index);
+
+bool ocfs_extent_map_next_entry (ocfs_extent_map * map, __u32 index,
+				 __s64 * virtual, __s64 * physical,
+				 __s64 * sectors);
+//////////////////////
+
+
+enum {
+	bm_extent,
+	bm_dir,
+	bm_symlink,
+	bm_filedata
+};
+
+typedef struct _bitmap_data
+{
+	__u32 bitnum;
+	__s32 alloc_node;
+	__u64 fss_off;		/* file system structure offset */
+	__u64 parent_off;	/* offset of the fs structure housing the extent */
+} bitmap_data;
+
+typedef struct _ocfsck_context
+{
+	char device[OCFS_MAX_FILENAME_LENGTH];
+	char raw_device[OCFS_MAX_FILENAME_LENGTH];
+	int raw_minor;
+	int flags;
+	int fd;
+	ocfs_super *vcb;
+	bool write_changes;
+	bool verbose;
+	bool modify_all;
+	bool quiet;
+	bool no_hb_chk;
+	bool dev_is_file;
+	ocfs_vol_disk_hdr *hdr;
+	__u8 *vol_bm;
+	__u8 *dir_bm[OCFS_MAXIMUM_NODES];
+	__u8 *ext_bm[OCFS_MAXIMUM_NODES];
+	__u32 dir_bm_sz[OCFS_MAXIMUM_NODES];
+	__u32 ext_bm_sz[OCFS_MAXIMUM_NODES];
+	__u64 device_size;
+	int cluster_size_bits;
+	GArray *vol_bm_data;
+	GArray *dir_bm_data;
+	GArray *ext_bm_data;
+} ocfsck_context;
+
+//int ocfs_lookup_file_allocation (ocfs_super * osb, ocfs_inode * oin,
+//				 __s64 Vbo, __s64 * Lbo, __u32 sectors);
+
+loff_t myseek64(int fd, loff_t off, int whence);
+int myread(int file, char *buf, __u32 len);
+int mywrite(int file, char *buf, __u32 len);
+int myopen(char *path, int flags);
+void myclose(int file);
+void read_system_file(int fd, ocfs_vol_disk_hdr * v, int fileid,
+		      ocfs_file_entry * fe);
+int write_system_file(int fd, ocfs_vol_disk_hdr * v, int fileid,
+		      ocfs_file_entry * fe);
+void read_cdsl_data(int fd, void *data, __u64 offset);
+
+int ocfs_find_clear_bits (ocfs_alloc_bm * bitmap, __u32 numBits,
+			  __u32 offset, __u32 sysonly);
+
+int print_class_member(char *buf, ocfs_class *cl, ocfs_class_member *mbr,
+		       FILE *out, bool bad);
+int _print_class(char *buf, ocfs_class *cl, FILE *out, bool num, GHashTable *ht);
+int print_class(char *buf, ocfs_class *cl, FILE *out, GHashTable *ht);
+bitmap_data * add_bm_data(__u64 start, __u64 len, __s32 alloc_node, 
+			  __u64 parent_offset, int type);
+
+int read_one_sector(int fd, char *buf, __u64 offset, int idx);
+int write_one_sector(int fd, char *buf, __u64 offset, int idx);
+int read_dir_node(int fd, char *buf, __u64 offset, int idx);
+int write_dir_node (int fd, char *buf, __u64 offset, int idx);
+int read_volume_bitmap (int fd, char *buf, __u64 offset, int idx);
+int write_volume_bitmap (int fd, char *buf, __u64 offset, int idx);
+
+
+#endif /* FSCK_H */

Added: trunk/fsck/fsck.ocfs.1.in
===================================================================
--- trunk/fsck/fsck.ocfs.1.in	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/fsck/fsck.ocfs.1.in	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,49 @@
+.TH "fsck.ocfs" "1" "November 2003" "Version @VERSION@" "OCFS Manual Pages"
+.SH "NAME"
+fsck.ocfs \- Build an OCFS file system.
+.SH "SYNOPSIS"
+\fBfsck.ocfs\fR \-w  [\-V] [\-v] [\-q] device 
+.SH "DESCRIPTION"
+.PP 
+\fBfsck.ocfs\fR is used to check an OCFS file system on a device, usually a
+partition in a shared disk. \fBfsck.ocfs\fR will work read-only if \-w is not
+specified in the command line. This was done to allow users to run fsck while
+the OCFS filesystem is actually mounted and active. The \fBfsck.ocfs\fR
+command will look for the first available raw device in the list that is
+available and automatically bind the device specified to it and unbind when it
+is done. The command will fail if there is no free raw device availabe for
+use, so it is suggested to the user to keep at least one raw device configured
+and free for \fBfsck.ocfs\fR to use. One can also bind the devices to a
+specific raw devices and use them instead of the block device. The \fBfsck.ocfs\fR
+uses a raw device to get o_direct behavior.
+
+.SH "OPTIONS"
+.TP
+\fB\-w\fR 
+This option tell \fBfsck.ocfs\fR that it is going to run in read/write
+mode. This option should only be specified with the device properly unmounted
+on all nodes.
+
+.TP
+\fB\-V\fR 
+Display \fBfsck.ocfs\fR version.
+
+.TP
+\fB\-v\fR 
+Run \fBfsck.ocfs\fR in verbose mode.
+
+.TP
+\fB\-q\fR 
+Run \fBfsck.ocfs\fR in quiet mode.
+   
+.SH "BUGS"
+Stuff.
+
+.SH "SEE ALSO"
+.BR ocfs(5)
+
+.SH "AUTHORS"
+Oracle Corporation
+
+.SH "COPYRIGHT"
+Copyright \(co 2002 Oracle Corporation

Added: trunk/fsck/fsck_io.c
===================================================================
--- trunk/fsck/fsck_io.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/fsck/fsck_io.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,214 @@
+/*
+ * fsck_io.c
+ *
+ * provides the actual file I/O support in ocfs file system
+ * check utility
+ *
+ * Copyright (C) 2003, 2004 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Author: Kurt Hackel, Sunil Mushran
+ */
+
+#include "fsck.h"
+
+void *mem_alloc(int len)
+{
+	void *buf;
+
+	if ((buf = malloc_aligned(len)) == NULL)
+		LOG_ERROR("unable to allocate %d bytes of memory", len);
+
+	return buf;
+}				/* mem_alloc */
+
+
+loff_t myseek64(int fd, loff_t off, int whence)
+{
+	loff_t ret;
+
+	if ((ret = lseek64(fd, off, whence) == -1))
+		LOG_ERROR("lseek() %s", strerror(errno));
+
+	return ret;
+}				/* myseek64 */
+
+/*
+ * myread()
+ *
+ */
+int myread(int file, char *buf, __u32 len)
+{
+	int ret;
+
+	if ((ret = read(file, buf, len)) == -1)
+		LOG_ERROR("read() %s", strerror(errno));
+
+	return ret;
+}				/* myread */
+
+
+/*
+ * mywrite()
+ *
+ */
+int mywrite(int file, char *buf, __u32 len)
+{
+	int ret;
+
+	if ((ret = write(file, buf, len)) == -1)
+		LOG_ERROR("write() %s", strerror(errno));
+
+	return ret;
+}				/* mywrite */
+
+/*
+ * myopen()
+ *
+ */
+int myopen(char *path, int flags)
+{
+    int file;
+    mode_t oldmode;
+
+    oldmode = umask(0000);
+    file = open(path, flags, 0777);
+    umask(oldmode);
+
+    return file;
+}				/* myopen */
+
+
+/*
+ * myclose()
+ *
+ */
+void myclose(int file)
+{
+    if (file)
+	close(file);
+}				/* myclose */
+
+
+void read_system_file(int fd, ocfs_vol_disk_hdr * v, int fileid,
+		      ocfs_file_entry * fe)
+{
+    __u64 diskOffset = (fileid * OCFS_SECTOR_SIZE) + v->internal_off;
+
+    myseek64(fd, diskOffset, SEEK_SET);
+    read(fd, fe, OCFS_SECTOR_SIZE);
+}				/* read_system_file */
+
+
+int write_system_file(int fd, ocfs_vol_disk_hdr * v, int fileid,
+		      ocfs_file_entry * fe)
+{
+    int ret;
+    void *sector;
+    __u64 diskOffset = (fileid * OCFS_SECTOR_SIZE) + v->internal_off;
+
+    sector = malloc_aligned(OCFS_SECTOR_SIZE);
+    memset(sector, 0, OCFS_SECTOR_SIZE);
+    memcpy(sector, fe, sizeof(ocfs_file_entry));
+    myseek64(fd, diskOffset, SEEK_SET);
+    ret = write(fd, sector, OCFS_SECTOR_SIZE);
+    free(sector);
+    return ret;
+}				/* write_system_file */
+
+
+void read_cdsl_data(int fd, void *data, __u64 offset)
+{
+	int len = sizeof(__u64) * MAX_NODES;
+	int rdlen;
+
+	myseek64(fd, offset, SEEK_SET);
+	if ((rdlen = read(fd, data, len)) != len)
+		LOG_ERROR("short read for cdsl data... %d instead of %d bytes",
+			  rdlen, len);
+}				/* read_cdsl_data */
+
+
+int read_one_sector(int fd, char *buf, __u64 offset, int idx)
+{
+	int ret;
+
+	myseek64(fd, offset, SEEK_SET);
+	if ((ret = read(fd, buf, OCFS_SECTOR_SIZE)) == -1)
+		LOG_ERROR("read() %s", strerror(errno));
+	return ret;
+}				/* read_one_sector */
+
+
+int write_one_sector(int fd, char *buf, __u64 offset, int idx)
+{
+	int ret;
+
+	myseek64(fd, offset, SEEK_SET);
+	if ((ret = write(fd, buf, OCFS_SECTOR_SIZE)) == -1)
+		LOG_ERROR("write() %s", strerror(errno));
+	return ret;
+}				/* write_one_sector */
+
+
+int read_dir_node(int fd, char *buf, __u64 offset, int idx)
+{
+	int rdlen;
+
+	myseek64(fd, offset, SEEK_SET);
+
+	if ((rdlen = read(fd, buf, DIR_NODE_SIZE)) != DIR_NODE_SIZE) {
+		if (rdlen == -1)
+			LOG_ERROR("read() %s\n", strerror(errno));
+		else
+			LOG_ERROR("short read for dirnode... %d instead "
+				  "of %d bytes", rdlen, DIR_NODE_SIZE);
+	}
+    	return 0;
+}				/* read_dir_node */
+
+
+int write_dir_node (int fd, char *buf, __u64 offset, int idx)
+{
+	int ret;
+	myseek64(fd, offset, SEEK_SET);
+	if ((ret = write(fd, buf, DIR_NODE_SIZE)) == -1)
+		LOG_ERROR("write() %s", strerror(errno));
+	return ret;
+}				/* write_dir_node */
+
+
+int read_volume_bitmap (int fd, char *buf, __u64 offset, int idx)
+{
+	int rdlen;
+	
+	myseek64(fd, offset, SEEK_SET);
+	if ((rdlen = read(fd, buf, VOL_BITMAP_BYTES)) != VOL_BITMAP_BYTES)
+		LOG_ERROR("short read for volume bitmap... %d instead of %d bytes",
+			  rdlen, VOL_BITMAP_BYTES);
+	return 0;
+}				/* read_volume_bitmap */
+
+
+int write_volume_bitmap (int fd, char *buf, __u64 offset, int idx)
+{
+	int ret;
+	myseek64(fd, offset, SEEK_SET);
+	if ((ret = write(fd, buf, VOL_BITMAP_BYTES)) == -1)
+		LOG_ERROR("write() %s", strerror(errno));
+	return ret;
+}				/* write_volume_bitmap */

Added: trunk/fsck/fsck_print.c
===================================================================
--- trunk/fsck/fsck_print.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/fsck/fsck_print.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,126 @@
+/*
+ * fsck_print.c
+ *
+ * print function for each structure type in ocfs
+ *
+ * Copyright (C) 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Sunil Mushran
+ */
+
+#include "fsck.h"
+
+
+int print_dir_node (char *buf, int idx, GHashTable *bad, FILE *f)
+{
+	return print_class(buf, &ocfs_dir_node_class, f, bad);
+}
+int print_file_entry(char *buf, int idx, GHashTable *bad, FILE *f) 
+{ 
+	return print_class(buf, &ocfs_file_entry_class, f, bad);
+}
+
+int print_extent_header(char *buf, int idx, GHashTable *bad, FILE *f) 
+{ 
+	return print_class(buf, &ocfs_extent_group_class, f, bad);
+}
+
+int print_extent_data(char *buf, int idx, GHashTable *bad, FILE *f) 
+{ 
+	return print_class(buf, &ocfs_extent_group_class, f, bad);
+}
+
+int print_vol_disk_header(char *buf, int idx, GHashTable *bad, FILE *f) 
+{ 
+	return print_class(buf, &ocfs_vol_disk_hdr_class, f, bad);
+}
+
+int print_vol_label(char *buf, int idx, GHashTable *bad, FILE *f) 
+{ 
+	return print_class(buf, &ocfs_vol_label_class, f, bad);
+}
+
+int print_disk_lock(char *buf, int idx, GHashTable *bad, FILE *f) 
+{ 
+	return print_class(buf, &ocfs_disk_lock_class, f, bad);
+}
+
+int print_nodecfghdr(char *buf, int idx, GHashTable *bad, FILE *f) 
+{
+	return print_class(buf, &ocfs_node_config_hdr_class, f, bad);
+}
+
+int print_nodecfginfo(char *buf, int idx, GHashTable *bad, FILE *f) 
+{
+	return print_class(buf, &ocfs_disk_node_config_info_class, f, bad);
+}
+
+int print_publish_sector(char *buf, int idx, GHashTable *bad, FILE *f) 
+{ 
+	return print_class(buf, &ocfs_publish_class, f, bad);
+}
+
+int print_vote_sector(char *buf, int idx, GHashTable *bad, FILE *f) 
+{ 
+	return print_class(buf, &ocfs_vote_class, f, bad);
+}
+
+int print_volume_bitmap(char *buf, int idx, GHashTable *bad, FILE *f) 
+{ 
+	return 0; //print_class(buf, &ocfs_volume_bitmap_class, f, bad);
+}
+
+int print_vol_metadata(char *buf, int idx, GHashTable *bad, FILE *f) 
+{ 
+	return print_class(buf, &ocfs_file_entry_class, f, bad);
+}
+
+int print_vol_metadata_log(char *buf, int idx, GHashTable *bad, FILE *f) 
+{ 
+	return print_class(buf, &ocfs_file_entry_class, f, bad);
+}
+
+int print_dir_alloc(char *buf, int idx, GHashTable *bad, FILE *f) 
+{ 
+	return print_class(buf, &ocfs_file_entry_class, f, bad);
+}
+
+int print_dir_alloc_bitmap(char *buf, int idx, GHashTable *bad, FILE *f) 
+{ 
+	return print_class(buf, &ocfs_file_entry_class, f, bad);
+}
+
+int print_file_alloc(char *buf, int idx, GHashTable *bad, FILE *f) 
+{ 
+	return print_class(buf, &ocfs_file_entry_class, f, bad);
+}
+
+int print_file_alloc_bitmap(char *buf, int idx, GHashTable *bad, FILE *f) 
+{ 
+	return print_class(buf, &ocfs_file_entry_class, f, bad);
+}
+
+int print_recover_log(char *buf, int idx, GHashTable *bad, FILE *f) 
+{ 
+	return print_class(buf, &ocfs_file_entry_class, f, bad);
+}
+
+int print_cleanup_log(char *buf, int idx, GHashTable *bad, FILE *f) 
+{ 
+	return print_class(buf, &ocfs_file_entry_class, f, bad);
+}

Added: trunk/fsck/fsck_print.h
===================================================================
--- trunk/fsck/fsck_print.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/fsck/fsck_print.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,54 @@
+/*
+ * fsck_print.h
+ *
+ * Function prototypes, macros, etc. for related 'C' files
+ *
+ * Copyright (C) 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Sunil Mushran
+ */
+
+#ifndef FSCK_PRINT_H
+#define FSCK_PRINT_H
+
+
+// for ALL print functions...
+// TODO: deal with bad array
+int print_dir_node (char *buf, int idx, GHashTable *bad, FILE *f);
+int print_file_entry(char *buf, int idx, GHashTable *bad, FILE *f);
+int print_extent_header(char *buf, int idx, GHashTable *bad, FILE *f);
+int print_extent_data(char *buf, int idx, GHashTable *bad, FILE *f);
+int print_vol_disk_header(char *buf, int idx, GHashTable *bad, FILE *f);
+int print_vol_label(char *buf, int idx, GHashTable *bad, FILE *f);
+int print_disk_lock(char *buf, int idx, GHashTable *bad, FILE *f);
+int print_disk_lock(char *buf, int idx, GHashTable *bad, FILE *f);
+int print_nodecfghdr(char *buf, int idx, GHashTable *bad, FILE *f);
+int print_nodecfginfo(char *buf, int idx, GHashTable *bad, FILE *f);
+int print_publish_sector(char *buf, int idx, GHashTable *bad, FILE *f);
+int print_vote_sector(char *buf, int idx, GHashTable *bad, FILE *f);
+int print_volume_bitmap(char *buf, int idx, GHashTable *bad, FILE *f);
+int print_vol_metadata(char *buf, int idx, GHashTable *bad, FILE *f);
+int print_vol_metadata_log(char *buf, int idx, GHashTable *bad, FILE *f);
+int print_dir_alloc(char *buf, int idx, GHashTable *bad, FILE *f);
+int print_dir_alloc_bitmap(char *buf, int idx, GHashTable *bad, FILE *f);
+int print_file_alloc(char *buf, int idx, GHashTable *bad, FILE *f);
+int print_file_alloc_bitmap(char *buf, int idx, GHashTable *bad, FILE *f);
+int print_recover_log(char *buf, int idx, GHashTable *bad, FILE *f);
+int print_cleanup_log(char *buf, int idx, GHashTable *bad, FILE *f);
+
+#endif /* FSCK_PRINT_H */

Added: trunk/fsck/layout.c
===================================================================
--- trunk/fsck/layout.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/fsck/layout.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,432 @@
+/*
+ * layout.c
+ *
+ * ocfs file system block structure layouts
+ *
+ * Copyright (C) 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Sunil Mushran
+ */
+
+#include "layout.h"
+
+#define LAYOUT_LOCAL_DEFS
+ocfs_disk_structure dirnode_t = {
+	dir_node,
+       	&ocfs_dir_node_class,
+       	dir_node_sig_match,
+       	read_dir_node,
+	write_dir_node,
+       	verify_dir_node,
+       	print_dir_node,
+       	get_dir_node_defaults
+};
+ocfs_disk_structure fileent_t = {
+	file_entry,
+       	&ocfs_file_entry_class,
+       	file_entry_sig_match,
+       	read_one_sector,
+	write_one_sector,
+       	verify_file_entry,
+       	print_file_entry,
+       	get_file_entry_defaults
+};
+ocfs_disk_structure exthdr_t = {
+	extent_header,
+       	&ocfs_extent_group_class,
+       	extent_header_sig_match,
+       	read_one_sector,
+	write_one_sector,
+       	verify_extent_header,
+       	print_extent_header,
+       	get_extent_header_defaults
+};
+ocfs_disk_structure extdat_t = {
+	extent_data,
+	&ocfs_extent_group_class,
+       	extent_data_sig_match,
+       	read_one_sector,
+	write_one_sector,
+       	verify_extent_data,
+       	print_extent_data,
+       	get_extent_data_defaults
+};
+ocfs_disk_structure diskhdr_t = { 
+	vol_disk_header,
+       	&ocfs_vol_disk_hdr_class,
+       	NULL,
+       	read_one_sector,
+	write_one_sector,
+       	verify_vol_disk_header,
+       	print_vol_disk_header,
+       	get_vol_disk_header_defaults 
+};
+ocfs_disk_structure vollabel_t = { 
+	vol_label_lock,
+       	&ocfs_vol_label_class,
+       	NULL,
+       	read_one_sector,
+	write_one_sector,
+       	verify_vol_label,
+       	print_vol_label,
+       	get_vol_label_defaults 
+};
+ocfs_disk_structure bmlock_t = {
+	bitmap_lock,
+       	&ocfs_disk_lock_class,
+       	NULL,
+       	read_one_sector,
+	write_one_sector,
+       	verify_disk_lock,
+       	print_disk_lock,
+       	get_disk_lock_defaults
+};
+ocfs_disk_structure nmlock_t = {
+	nm_lock,
+       	&ocfs_disk_lock_class,
+       	NULL,
+       	read_one_sector,
+	write_one_sector,
+       	verify_disk_lock,
+       	print_disk_lock,
+       	get_disk_lock_defaults
+};
+ocfs_disk_structure unused_t = {
+	unused,
+       	NULL,
+       	NULL,
+       	NULL,
+	NULL,
+       	NULL,
+       	NULL,
+       	NULL,
+};
+ocfs_disk_structure free_t = {
+	free_sector,
+       	NULL,
+       	NULL,
+       	NULL,
+	NULL,
+       	NULL,
+       	NULL,
+       	NULL,
+};
+ocfs_disk_structure nodecfghdr_t = {
+	node_cfg_hdr,
+       	&ocfs_node_config_hdr_class,
+       	nodecfghdr_sig_match,
+       	read_one_sector,
+	write_one_sector,
+       	verify_nodecfghdr,
+       	print_nodecfghdr,
+       	get_nodecfghdr_defaults
+};
+ocfs_disk_structure nodecfginfo_t = {
+	node_cfg_info,
+       	&ocfs_disk_node_config_info_class,
+       	NULL,
+       	read_one_sector,
+	write_one_sector,
+       	verify_nodecfginfo,
+       	print_nodecfginfo,
+       	get_nodecfginfo_defaults
+};
+ocfs_disk_structure publish_t = {
+	publish_sector,
+       	&ocfs_publish_class,
+       	NULL,
+       	read_one_sector,
+	write_one_sector,
+       	verify_publish_sector,
+       	print_publish_sector,
+       	get_publish_sector_defaults
+};
+ocfs_disk_structure vote_t = {
+	vote_sector,
+       	&ocfs_vote_class,
+       	vote_sector_sig_match,
+       	read_one_sector,
+	write_one_sector,
+       	verify_vote_sector,
+       	print_vote_sector,
+       	get_vote_sector_defaults
+};
+ocfs_disk_structure volbm_t = {
+	volume_bitmap,
+       	NULL,
+       	NULL,
+       	read_volume_bitmap,
+	write_volume_bitmap,
+       	verify_volume_bitmap,
+       	print_volume_bitmap,
+       	NULL
+};
+ocfs_disk_structure volmd_t = {
+	vol_metadata,
+       	&ocfs_file_entry_class,
+       	file_entry_sig_match,
+       	read_one_sector,
+	write_one_sector,
+       	verify_vol_metadata,
+       	print_vol_metadata,
+       	get_vol_metadata_defaults
+};
+ocfs_disk_structure volmdlog_t = {
+	vol_metadata_log,
+       	&ocfs_file_entry_class,
+       	file_entry_sig_match,
+       	read_one_sector,
+	write_one_sector,
+       	verify_vol_metadata_log,
+       	print_vol_metadata_log,
+       	get_vol_metadata_log_defaults
+};
+ocfs_disk_structure diralloc_t = {
+	dir_alloc,
+       	&ocfs_file_entry_class,
+       	file_entry_sig_match,
+       	read_one_sector,
+	write_one_sector,
+       	verify_dir_alloc,
+       	print_dir_alloc,
+       	get_dir_alloc_defaults
+};
+ocfs_disk_structure dirallocbm_t = {
+	dir_alloc_bitmap,
+       	&ocfs_file_entry_class,
+       	file_entry_sig_match,
+       	read_one_sector,
+	write_one_sector,
+       	verify_dir_alloc_bitmap,
+       	print_dir_alloc_bitmap,
+       	get_dir_alloc_bitmap_defaults
+};
+ocfs_disk_structure filealloc_t = {
+	file_alloc,
+       	&ocfs_file_entry_class,
+       	file_entry_sig_match,
+       	read_one_sector,
+	write_one_sector,
+       	verify_file_alloc,
+       	print_file_alloc,
+       	get_file_alloc_defaults
+};
+ocfs_disk_structure fileallocbm_t = {
+	file_alloc_bitmap,
+       	&ocfs_file_entry_class,
+       	file_entry_sig_match,
+       	read_one_sector,
+	write_one_sector,
+       	verify_file_alloc_bitmap,
+       	print_file_alloc_bitmap,
+       	get_file_alloc_bitmap_defaults
+};
+ocfs_disk_structure recover_t = {
+	recover_log,
+       	&ocfs_file_entry_class,
+       	file_entry_sig_match,
+       	read_one_sector,
+	write_one_sector,
+       	verify_recover_log,
+       	print_recover_log,
+       	get_recover_log_defaults
+};
+ocfs_disk_structure cleanup_t = {
+	cleanup_log,
+       	&ocfs_file_entry_class,
+       	file_entry_sig_match,
+       	read_one_sector,
+	write_one_sector,
+       	verify_cleanup_log,
+       	print_cleanup_log,
+       	get_cleanup_log_defaults
+};
+
+ocfs_layout_t ocfs_header_layout[] = 
+{
+	{ 0, 1, &diskhdr_t, "Volume Header" },
+	{ 1, 1, &vollabel_t, "Volume Label" },
+	{ 2, 1, &bmlock_t, "Bitmap Lock" },
+	{ 3, 1, &nmlock_t, "NM Lock" },
+	{ 4, 4, &unused_t, "" },
+	{ 8, 1, &nodecfghdr_t, "Node Config Header" },
+	{ 9, 1, &unused_t, "" },
+	{ 10, 32, &nodecfginfo_t, "Node Config Info" },
+	{ 42, 1, &unused_t, "" },
+	{ 43, 1, &nodecfghdr_t, "Node Config Trailer" },
+	{ 44, 2, &unused_t, "" },
+	{ 46, 32, &publish_t, "Publish" },
+	{ 78, 32, &vote_t, "Vote" },
+	{ 110, 2048, &volbm_t, "Volume Bitmap File" },
+	{ 2158, 514, &free_t, "Free Bitmap File" },
+	{ 2672, 32, &volmd_t, "Volume Metadata File" },
+	{ 2704, 32, &volmdlog_t, "Volume Metadata Logfile" },
+	{ 2736, 32, &diralloc_t, "Directory Alloc File" },
+	{ 2768, 32, &dirallocbm_t, "Directory Alloc Bitmap File" },
+	{ 2800, 32, &filealloc_t, "Extent Alloc File" },
+	{ 2832, 32, &fileallocbm_t, "Extent Alloc Bitmap File" },
+	{ 2864, 32, &recover_t, "Recover File" },
+	{ 2896, 32, &cleanup_t, "Cleanup File" }
+};
+int ocfs_header_layout_sz = sizeof(ocfs_header_layout)/sizeof(ocfs_layout_t);
+
+ocfs_layout_t ocfs_data_layout[] = 
+{
+	{ ANY_BLOCK, 256, &dirnode_t, "directory node" },
+	{ ANY_BLOCK, 1, &fileent_t, "file entry" },
+	{ ANY_BLOCK, 1, &exthdr_t, "extent header" },
+	{ ANY_BLOCK, 1, &extdat_t, "extent data" }
+};
+int ocfs_data_layout_sz = sizeof(ocfs_data_layout)/sizeof(ocfs_layout_t);
+
+ocfs_layout_t ocfs_dir_layout[] = 
+{
+	{ 0, 1, &dirnode_t },
+	{ 1, 255, &fileent_t }
+};
+int ocfs_dir_layout_sz = sizeof(ocfs_dir_layout)/sizeof(ocfs_layout_t);
+
+ocfs_disk_structure *ocfs_all_structures[] = 
+{
+	&dirnode_t,
+	&fileent_t,
+	&exthdr_t,
+	&extdat_t,
+	&diskhdr_t,
+	&publish_t,
+	&vote_t,
+	&volmd_t,
+	&volmdlog_t,
+	&diralloc_t,
+	&dirallocbm_t,
+	&filealloc_t,
+	&fileallocbm_t,
+	&recover_t,
+	&cleanup_t,
+	&vollabel_t,
+	&bmlock_t,
+	&nmlock_t,
+	&nodecfghdr_t,
+	&nodecfginfo_t,
+	&volbm_t,
+	&unused_t,
+	&free_t
+};
+int ocfs_all_structures_sz = sizeof(ocfs_all_structures)/sizeof(ocfs_disk_structure);
+
+/* 
+     autoconfig subtypes
+
+int get_autoconfig_header_copy_defaults (char *buf, char **out, int idx);
+int get_autoconfig_header_defaults (char *buf, char **out, int idx);
+int get_autoconfig_node_info_defaults (char *buf, char **out, int idx);
+int autoconfig_header_copy_sig_match (char *buf, int idx);
+int autoconfig_header_sig_match (char *buf, int idx);
+int autoconfig_node_info_sig_match (char *buf, int idx);
+int print_autoconfig_header (char *buf, int idx);
+int print_autoconfig_header_copy (char *buf, int idx);
+int print_autoconfig_node_info (char *buf, int idx);
+int verify_autoconfig_header (int fd, char *buf, int idx);
+int verify_autoconfig_header_copy (int fd, char *buf, int idx);
+int verify_autoconfig_node_info (int fd, char *buf, int idx);
+
+
+ocfs_disk_structure autoconfig_hdr_t = {
+	autoconfig_header,
+	autoconfig_header_sig_match,
+	read_one_sector,
+	write_one_sector,
+	verify_autoconfig_header,
+	print_autoconfig_header,
+	get_autoconfig_header_defaults
+};
+ocfs_disk_structure autoconfig_node_info_t = {
+	autoconfig_node_info,
+	autoconfig_node_info_sig_match,
+	read_one_sector,
+	write_one_sector,
+	verify_autoconfig_node_info,
+	print_autoconfig_node_info,
+	get_autoconfig_node_info_defaults
+};
+ocfs_disk_structure autoconfig_hdr_copy_t = {
+	autoconfig_header_copy,
+	autoconfig_header_copy_sig_match,
+	read_one_sector,
+	write_one_sector,
+	verify_autoconfig_header_copy,
+	print_autoconfig_header_copy,
+	get_autoconfig_header_copy_defaults
+};
+
+ocfs_layout_t ocfs_autoconfig_layout[] = 
+{
+	{ 0, 1, autoconfig_hdr_t },
+	{ 1, 1, unused_t },
+	{ 2, 32, autoconfig_node_info_t },
+	{ 34, 1, unused_t },
+	{ 35, 1, autoconfig_hdr_copy_t }
+};
+int ocfs_autoconfig_layout_sz = sizeof(ocfs_autoconfig_layout)/sizeof(ocfs_layout_t);
+
+*/       
+
+
+
+
+ocfs_layout_t * find_nxt_hdr_struct(int type, int start)
+{
+	int i;
+	ocfs_disk_structure *s;
+	ocfs_layout_t *ret = NULL;
+
+	for (i=start; i<ocfs_header_layout_sz; i++)
+	{
+		ret = &(ocfs_header_layout[i]);
+		s = ret->kind;
+		if (s->type != type)
+			ret = NULL;
+		else
+			break;
+	}
+	return ret;
+}
+								
+
+ocfs_disk_structure * find_matching_struct(char *buf, int idx)
+{
+	int i;
+	ocfs_disk_structure *s;
+
+	for (i=0; i<ocfs_all_structures_sz; i++)
+	{
+		s = ocfs_all_structures[i];
+		if (s->sig_match == NULL)
+			continue;
+		if (s->sig_match(buf, idx) == 0)
+		{
+			return s;
+		}
+	}
+	return NULL;
+}
+
+
+
+#undef LAYOUT_LOCAL_DEFS
+

Added: trunk/fsck/layout.h
===================================================================
--- trunk/fsck/layout.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/fsck/layout.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,224 @@
+/*
+ * layout.h
+ *
+ * Function prototypes, macros, etc. for related 'C' files
+ *
+ * Copyright (C) 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Sunil Mushran
+ */
+
+#ifndef LAYOUT_H
+#define LAYOUT_H
+
+#define BLOCKS2BYTES(x)   ((x) << 9)
+#define BYTES2BLOCKS(x)   ((x) >> 9)
+
+/* 100% totally hardcoded to the ocfs version!!! */
+/*
+
+  block#    datatype                       description
+  --------- ------------------------------ --------------------------------------------
+  0         ocfs_vol_disk_header           *the* header                     - disk header
+  1         ocfs_vol_label                 volume label, volume lock        - locks
+  2         ocfs_file_entry (lock only)    bitmap lock                      - locks
+  3         ocfs_file_entry (lock only)    nm lock????                      - locks
+  4-7       none                           unused                           - 
+  8         ocfs_node_config_hdr           autoconfig header                - autoconfig
+  9         none                           unused                           - autoconfig
+  10-41     ocfs_disk_node_config_info     autoconfig nodes            0-31 - autoconfig 
+  42        none                           autoconfig lock (zeroed)         - autoconfig
+  43        ocfs_node_config_hdr           exact copy of block#8            - autoconfig
+  44-45     none                           unused                           - autoconfig
+  46-77     ocfs_publish                   publish nodes               0-31 - publish
+  78-109    ocfs_vote                      vote nodes                  0-31 - vote
+  110-2157  bitmap                         1MB (8 million bits max)         - volume bitmap
+  2158-2671 none                           514 free sectors                 - free sectors
+  2672-2703 ocfs_file_entry                OCFS_VOL_MD_SYSFILE         0-31 - data_start_off
+  2704-2735 ocfs_file_entry                OCFS_VOL_MD_LOG_SYSFILE     0-31 - 
+  2736-2767 ocfs_file_entry                OCFS_DIR_SYSFILE            0-31 - 
+  2768-2799 ocfs_file_entry                OCFS_DIR_BM_SYSFILE         0-31 - 
+  2800-2831 ocfs_file_entry                OCFS_FILE_EXTENT_SYSFILE    0-31 - 
+  2832-2863 ocfs_file_entry                OCFS_FILE_EXTENT_BM_SYSFILE 0-31 -
+  2864-2895 ocfs_file_entry                OCFS_RECOVER_LOG_SYSFILE    0-31 - 
+  2896-2927 ocfs_file_entry                OCFS_CLEANUP_LOG_SYSFILE    0-31 - 
+  ####      ocfs_dir_node                  the root directory               - root_off (offset can vary)
+  ####      none                           1022 free sectors                - end sectors
+
+*/
+
+typedef struct _ocfs_disk_structure ocfs_disk_structure;
+
+#include "fsck.h"
+
+enum
+{
+	unused = 0,
+	vol_disk_header,
+	vol_label_lock,
+	bitmap_lock,
+	nm_lock,
+	node_cfg_hdr,
+	node_cfg_info,
+	publish_sector,
+	vote_sector,
+	volume_bitmap,
+	free_sector,
+	vol_metadata,
+	vol_metadata_log,
+	dir_alloc,
+	dir_alloc_bitmap,
+	file_alloc,
+	file_alloc_bitmap,
+	recover_log,
+	cleanup_log,
+	dir_node,
+	file_entry,
+	extent_header,
+	extent_data,
+};
+
+
+struct _ocfs_disk_structure
+{
+	int type;
+	ocfs_class *cls;
+	int (*sig_match) (char *buf, int idx);
+	int (*read) (int fd, char *buf, __u64 offset, int idx);
+	int (*write) (int fd, char *buf, __u64 offset, int idx);
+	int (*verify) (int fd, char *buf, int idx, GHashTable **bad);
+	int (*output) (char *buf, int idx, GHashTable *bad, FILE *f);
+	int (*defaults) (char *buf, GString **out, int idx, int fld);
+};
+
+#define ANY_BLOCK  (0xffffffffUL)
+typedef struct _ocfs_layout_t
+{
+	__u32    block;
+	__u32    num_blocks;
+	ocfs_disk_structure *kind; 
+	char     name[50];
+} ocfs_layout_t;
+	
+/* 
+ * these are all version 1.0.0 constants 
+ * I could have derived them, but what's the point?  
+ * they're konstant ;-)
+ * I may later include the headers for mkfs/module
+ * but I'm feeling lazy now...
+ */
+#define OCFSCK_BITMAP_OFF           56320LLU    /* block# 110 */
+#define OCFSCK_PUBLISH_OFF          23552LLU    /* block# 46  */
+#define OCFSCK_VOTE_OFF             39936LLU    /* block# 78  */
+#define OCFSCK_AUTOCONF_OFF         4096LLU     /* block# 8 */
+#define OCFSCK_AUTOCONF_SIZE        17408LLU    /* 34 blocks */
+#define OCFSCK_NEW_CFG_OFF          21504LLU    /* block# 42 */
+#define OCFSCK_DATA_START_OFF       1368064LLU  /* block# 2672 */
+#define OCFSCK_INTERNAL_OFF         OCFSCK_DATA_START_OFF
+#define OCFSCK_ROOT_OFF 	    2416640LLU  /* block# 4720 */
+#define OCFSCK_MIN_MOUNT_POINT_LEN  (strlen("/a"))
+#define OCFSCK_END_SECTOR_BYTES     (1022*512)
+#define OCFSCK_NON_DATA_AREA        (OCFSCK_DATA_START_OFF+OCFSCK_END_SECTOR_BYTES)
+#define OCFSCK_MAX_CLUSTERS         (1024*1024*8)  /* maximum 1mb (8megabits) */
+
+
+#define BM_DATA_BIT_SET         0x01	
+#define BM_ALLOCATED            0x02
+#define BM_SIG_BIT_1            0x04
+#define BM_SIG_BIT_2            0x08
+#define BM_SIG_BIT_3            0x10
+#define BM_MULTIPLY_ALLOCATED   0x20
+#define BM_RESERVED_1           0x40
+#define BM_RESERVED_2           0x80
+				
+#define BM_SIG_NONE             (0)
+#define BM_SIG_FILE             (BM_SIG_BIT_1)
+#define BM_SIG_DIR              (BM_SIG_BIT_2)
+#define BM_SIG_EXTHDR           (BM_SIG_BIT_3)
+#define BM_SIG_EXTDAT           (BM_SIG_BIT_1|BM_SIG_BIT_2)
+#define BM_SIG_VOL              (BM_SIG_BIT_1|BM_SIG_BIT_3)
+#define BM_SIG_NODECFG          (BM_SIG_BIT_2|BM_SIG_BIT_3)
+#define BM_SIG_OTHER            (BM_SIG_BIT_1|BM_SIG_BIT_2|BM_SIG_BIT_3)
+
+
+#define ONE_KB                     (1024)
+#define ONE_MB                     (ONE_KB*ONE_KB)
+
+#define OCFSCK_LO_CLUSTER_SIZE     (4 * ONE_KB)
+#define OCFSCK_HI_CLUSTER_SIZE     (ONE_MB)
+#define OCFSCK_DIR_NODE_SIZE       (128 * ONE_KB)
+#define OCFSCK_BITMAP_DATA_SIZE    (8 * ONE_MB)
+
+
+
+
+
+
+#if 0
+
+1. traverse each directory, checking each dir header and file entry signature
+2. check the allocation for each file and dir, matching it back to a bit in the global bitmap
+3. link any set bits with no matching file entry to lost+found data chunks
+4. do interactive repairs of the header block with appropriate defaults
+5. make a lock-state mode which can allow the user to change the lock state of any file entry
+7. mark non set bits as set in bitmap according to space usage
+8. verify if this is mounted filesystem or not
+
+** 6. allow some (as yet undefined) editing of autoconfig sectors
+** 9. clearing of bloated system files
+
+#endif
+
+ocfs_layout_t * find_nxt_hdr_struct(int type, int start);
+ocfs_disk_structure * find_matching_struct(char *buf, int idx);
+
+#ifndef LAYOUT_LOCAL_DEFS
+extern ocfs_disk_structure dirnode_t;
+extern ocfs_disk_structure fileent_t;
+extern ocfs_disk_structure exthdr_t;
+extern ocfs_disk_structure extdat_t;
+extern ocfs_disk_structure diskhdr_t;
+extern ocfs_disk_structure vollabel_t;
+extern ocfs_disk_structure bmlock_t;
+extern ocfs_disk_structure nmlock_t;
+extern ocfs_disk_structure unused_t;
+extern ocfs_disk_structure free_t;
+extern ocfs_disk_structure nodecfghdr_t;
+extern ocfs_disk_structure nodecfginfo_t;
+extern ocfs_disk_structure publish_t;
+extern ocfs_disk_structure vote_t;
+extern ocfs_disk_structure volbm_t;
+extern ocfs_disk_structure volmd_t;
+extern ocfs_disk_structure volmdlog_t;
+extern ocfs_disk_structure diralloc_t;
+extern ocfs_disk_structure dirallocbm_t;
+extern ocfs_disk_structure filealloc_t;
+extern ocfs_disk_structure fileallocbm_t;
+extern ocfs_disk_structure recover_t;
+extern ocfs_disk_structure cleanup_t;
+extern ocfs_layout_t ocfs_header_layout[];
+extern int ocfs_header_layout_sz;
+extern ocfs_layout_t ocfs_data_layout[];
+extern int ocfs_data_layout_sz;
+extern ocfs_layout_t ocfs_dir_layout[];
+extern int ocfs_dir_layout_sz;
+extern ocfs_disk_structure *ocfs_all_structures[];
+extern int ocfs_all_structures_sz;
+#endif /* LAYOUT_LOCAL_DEFS */
+
+#endif /* LAYOUT_H */

Added: trunk/fsck/mkgetconst
===================================================================
--- trunk/fsck/mkgetconst	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/fsck/mkgetconst	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,45 @@
+#!/bin/bash
+# this is used by parse.c to turn a #define'd
+# constant name into a usable array bound
+# eg.  ocfs_alloc_ext extents[OCFS_MAX_DATA_EXTENTS]
+# input:   OCFS_MAX_DATA_EXTENTS 
+# output:  18
+# don't know why i bothered with sign/size
+# arrays should be unsigned 32-bit int bounded here
+# and hell, if it's that big, we're screwed
+
+
+if [ "$bigint" = "" ]; then
+	typ="long";
+	fmt="l";
+else
+	typ="long long";
+	fmt="ll";
+fi
+
+if [ "$signed" = "" ]; then
+	sgn="unsigned";
+	fmt=$fmt"u";
+else
+	sgn="signed";
+	fmt=$fmt"d";
+fi
+
+cat > getconst.c << DONE
+/* just to make it shut up */
+#define O_DIRECT        040000
+
+#include <stdio.h>
+#include "ocfsconst.h"
+
+int main(int argc, char **argv)
+{
+	${sgn} ${typ} c = $1;
+	printf("%${fmt}\n", c);
+	exit(0);
+}
+DONE
+
+gcc -I. -I${COMMON_HEADERS} -o getconst getconst.c
+./getconst
+rm getconst.c getconst > /dev/null 2>&1


Property changes on: trunk/fsck/mkgetconst
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/fsck/parse.c
===================================================================
--- trunk/fsck/parse.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/fsck/parse.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,523 @@
+/*
+ * parse.c
+ *
+ * Utility to parse headers for ocfs file system check utility
+ *
+ * Copyright (C) 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Sunil Mushran
+ */
+
+/*  gcc -D_GNU_SOURCE parse.c -o parse . ./parseenv */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <ocfsbool.h>
+
+typedef struct _member
+{
+	char *name;
+	char *type;
+	char *flavor;
+	char *array_size;
+	char *hi;
+	char *lo;
+	int size;
+	bool is_signed;
+	int off;
+} member;
+
+typedef struct _oclass
+{
+	char *name;
+	int num_members;
+	int max_members;
+	member *members;
+} oclass;
+
+typedef struct _base_type
+{
+	char *name;
+	bool is_signed;
+	int size;
+} base_type;
+
+base_type known_types[] = 
+{ 
+	{"u64", false, 8}, 
+	{"u32", false, 4},
+	{"u16", false, 2},
+	{"u8",  false, 1},
+	{"s64", true,  8},
+	{"s32", true,  4},
+	{"s16", true,  2},
+	{"s8",  true,  1},
+	{"bool",false, 4}
+};
+int num_known = sizeof(known_types)/sizeof(base_type);
+
+void get_type_and_name(char *str, member *m);
+int print_one_member(oclass *cl, member *m, char *prefix);
+int print_one_class(oclass *cl);
+
+
+int num_classes = 0;
+int max_classes = 0;
+oclass *classes = NULL;
+
+oclass * add_class(oclass *cl)
+{
+	oclass *ret;
+
+	if (++num_classes > max_classes)
+	{
+		max_classes += 5;
+		classes = realloc(classes, max_classes*sizeof(oclass));
+	}
+	ret = (oclass *) (((char *)classes) + ((num_classes-1)*sizeof(oclass)));
+	memcpy(ret, cl, sizeof(oclass));
+	return ret;
+}
+
+member * add_member(oclass *cl, member *m)
+{
+	member *ret;
+	if (++(cl->num_members) > cl->max_members)
+	{
+		cl->max_members += 5;
+		cl->members = realloc(cl->members, cl->max_members*sizeof(member));
+	}
+	ret = (member *) (((char *)cl->members) + ((cl->num_members-1)*sizeof(member)));
+	memcpy(ret, m, sizeof(member));
+	return ret;
+}
+
+int main(int argc, char **argv)
+{
+	FILE *f;
+	char *buf;
+	bool in_class;
+	int i, j;
+	oclass curclass, *cc;
+
+	buf = malloc(4097);
+	if (buf==NULL)
+		exit(1);
+
+	if (argc < 2)
+	{
+		f = stdin;
+	}
+	else
+	{
+		f = fopen(argv[1], "r");
+		if (f == NULL)
+			exit(1);
+	}
+
+	printf("#include \"fsck.h\"\n\n");
+
+	in_class = false;
+	while (1)
+	{
+		member curmember, *cm = &curmember;
+		
+		memset(cm, 0, sizeof(member));
+		if (fgets(buf, 4097, f) == NULL)
+			break;
+		if (strstr(buf, "// CLASS"))
+		{
+			char *tmp, *tmp2, *tmp3;
+			in_class = true;
+			tmp = strstr(buf, "typedef");
+			if ((tmp3 = strstr(tmp, "struct")) == NULL)
+				tmp = strstr(tmp, "union");
+			else
+				tmp = tmp3;
+			tmp = strstr(tmp, "_");
+			tmp2 = ++tmp;
+			while (isalnum(*tmp2) || *tmp2=='_')
+				tmp2++;
+			*tmp2 = '\0';
+			curclass.name = strdup(tmp);
+			curclass.num_members = 0;
+			curclass.max_members = 0;
+			curclass.members = NULL;
+			cc = add_class(&curclass);
+		}
+		else if (strstr(buf, "// END CLASS"))
+		{
+			in_class = false;
+			cc = NULL;
+		}
+		else if (strstr(buf, "// DISKLOCK"))
+		{
+			get_type_and_name(buf, cm);
+			cm = add_member(cc, cm);
+			cm->flavor = strdup("disklock");
+		}
+		else if (strstr(buf, "// IPCONFIG"))
+		{
+			get_type_and_name(buf, cm);
+			cm = add_member(cc, cm);
+			cm->flavor = strdup("ipconfig");
+		}
+		else if (strstr(buf, "// GUID"))
+		{
+			get_type_and_name(buf, cm);
+			cm = add_member(cc, cm);
+			cm->flavor = strdup("guid");
+		}
+		else if (strstr(buf, "// ATTRIBS"))
+		{
+			get_type_and_name(buf, cm);
+			cm = add_member(cc, cm);
+			cm->flavor = strdup("attribs");
+		}
+		else if (strstr(buf, "// BOOL"))
+		{
+			get_type_and_name(buf, cm);
+			cm = add_member(cc, cm);
+			cm->flavor = strdup("bool");
+		}
+		else if (strstr(buf, "// CLUSTERSIZE"))
+		{
+			get_type_and_name(buf, cm);
+			cm = add_member(cc, cm);
+			cm->flavor = strdup("clustersize");
+		}
+		else if (strstr(buf, "// DATE"))
+		{
+			get_type_and_name(buf, cm);
+			cm = add_member(cc, cm);
+			cm->flavor = strdup("date");
+		}
+		else if (strstr(buf, "// DIRFLAG"))
+		{
+			get_type_and_name(buf, cm);
+			cm = add_member(cc, cm);
+			cm->flavor = strdup("dirflag");
+		}
+		else if (strstr(buf, "// DIRINDEX"))
+		{
+			get_type_and_name(buf, cm);
+			cm = add_member(cc, cm);
+			cm->flavor = strdup("dirindex");
+		}
+		else if (strstr(buf, "// DIRNODEINDEX"))
+		{
+			get_type_and_name(buf, cm);
+			cm = add_member(cc, cm);
+			cm->flavor = strdup("dirnodeindex");
+		}
+		else if (strstr(buf, "// DISKPTR"))
+		{
+			get_type_and_name(buf, cm);
+			cm = add_member(cc, cm);
+			cm->flavor = strdup("diskptr");
+		}
+		else if (strstr(buf, "// EXTENTTYPE"))
+		{
+			get_type_and_name(buf, cm);
+			cm = add_member(cc, cm);
+			cm->flavor = strdup("extenttype");
+		}
+		else if (strstr(buf, "// FILEFLAG"))
+		{
+			get_type_and_name(buf, cm);
+			cm = add_member(cc, cm);
+			cm->flavor = strdup("fileflag");
+		}
+		else if (strstr(buf, "// GID"))
+		{
+			get_type_and_name(buf, cm);
+			cm = add_member(cc, cm);
+			cm->flavor = strdup("gid");
+		}
+		else if (strstr(buf, "// LOCKLEVEL"))
+		{
+			get_type_and_name(buf, cm);
+			cm = add_member(cc, cm);
+			cm->flavor = strdup("locklevel");
+		}
+		else if (strstr(buf, "// NODEBITMAP"))
+		{
+			get_type_and_name(buf, cm);
+			cm = add_member(cc, cm);
+			cm->flavor = strdup("nodebitmap");
+		}
+		else if (strstr(buf, "// NODENUM"))
+		{
+			get_type_and_name(buf, cm);
+			cm = add_member(cc, cm);
+			cm->flavor = strdup("nodenum");
+		}
+		else if (strstr(buf, "// PERMS"))
+		{
+			get_type_and_name(buf, cm);
+			cm = add_member(cc, cm);
+			cm->flavor = strdup("perms");
+		}
+		else if (strstr(buf, "// SYNCFLAG"))
+		{
+			get_type_and_name(buf, cm);
+			cm = add_member(cc, cm);
+			cm->flavor = strdup("syncflag");
+		}
+		else if (strstr(buf, "// UID"))
+		{
+			get_type_and_name(buf, cm);
+			cm = add_member(cc, cm);
+			cm->flavor = strdup("uid");
+		}
+		else if (strstr(buf, "// UNUSED"))
+		{
+			// do nothing
+		}
+		else if (strstr(buf, "// EXTENT["))
+		{
+			get_type_and_name(buf, cm);
+			cm = add_member(cc, cm);
+			cm->flavor = strdup("extent_array");
+		}
+		else if (strstr(buf, "// CHAR"))
+		{
+			get_type_and_name(buf, cm);
+			cm = add_member(cc, cm);
+			cm->flavor = strdup("char_array");
+		}
+		else if (strstr(buf, "// HEX"))
+		{
+			get_type_and_name(buf, cm);
+			cm = add_member(cc, cm);
+			cm->flavor = strdup("hex_array");
+		}
+		else if (strstr(buf, "// VOTEFLAG"))
+		{
+			get_type_and_name(buf, cm);
+			cm = add_member(cc, cm);
+			cm->flavor = strdup("voteflag_array");
+		}
+		else if (strstr(buf, "// NUMBER RANGE"))
+		{
+			char *tmp1,*tmp2;
+			tmp1 = strstr(buf, "RANGE");
+			tmp1 = strstr(tmp1, "(");
+			tmp2 = ++tmp1;
+			while (*tmp2!=',')
+				tmp2++;
+			cm->lo = strndup(tmp1, tmp2-tmp1);
+			tmp1 = ++tmp2;
+			while (*tmp2!=')')
+				tmp2++;
+			cm->hi = strndup(tmp1, tmp2-tmp1);
+			get_type_and_name(buf, cm);
+			cm = add_member(cc, cm);
+			cm->flavor = strdup("number_range");
+		}
+	}
+
+	for (i=0; i<num_classes; i++)
+		print_one_class(&(classes[i]));
+	
+	printf("ocfs_class *ocfs_all_classes[] = {\n");
+	
+	for (i=0; i<num_classes; i++)
+		printf("\t&(%s_class),\n", classes[i].name);
+
+	printf("};\n");
+	printf("int ocfs_num_classes = %d;\n", num_classes);
+
+	exit(0);	
+}
+int print_one_class(oclass *cl)
+{
+	int i;
+
+	printf("static ocfs_class_member %s_members[] = {\n", cl->name);
+	for (i=0; i<cl->num_members; i++)
+	{
+		member *m = &(cl->members[i]);
+		print_one_member(cl, m, NULL);
+	}
+	printf("};\n");
+
+	printf("ocfs_class %s_class = {\n", cl->name);
+	printf("\t\"%s\", \n", cl->name);
+	printf("\tsizeof(%s_members) / sizeof(ocfs_class_member), \n", cl->name);
+	printf("\t%s_members\n", cl->name);
+	printf("};\n");
+}
+
+int get_const_array_size(char *name)
+{
+	int ret;
+	char buf[200];
+	FILE *pipe;
+	
+	memset(buf, 0, 200);
+	sprintf(buf, "./mkgetconst \"%s\"", name);
+
+	pipe = popen(buf, "r");
+	if (pipe==NULL)
+		return 0;
+	ret = fread(buf, 200, 1, pipe);
+	buf[199] = '\0';
+	pclose(pipe);
+	ret = atoi(buf);
+
+	return ret;
+}
+
+int print_one_member(oclass *cl, member *m, char *prefix)
+{
+	int l, k, j, i;
+	base_type *this_type = NULL;
+
+	for (k=0; k<num_known; k++)
+	{
+		if (strcmp(known_types[k].name, m->type)==0 || 
+		    (strlen(m->type)>2 && strcmp(known_types[k].name, &(m->type[2]))==0 &&
+			  m->type[0]=='_' && m->type[1]=='_' ))
+		{
+			this_type = &(known_types[k]);
+			break;
+		}
+	}
+	
+	if (this_type == NULL)
+	{
+		if (prefix == NULL)
+		{
+			// TODO: get each of the subtype fields and print them here	
+			for (i=0; i<num_classes; i++)
+			{
+				oclass *subcl;
+				subcl = &(classes[i]);
+				if (strcmp(subcl->name, m->type)==0)
+				{
+					if (m->array_size)
+					{
+						char arrname[50];
+						int asz;
+					        asz = atoi(m->array_size);
+						if (asz==0)
+						{
+							asz = get_const_array_size(m->array_size);
+							// char *env_sz = getenv(m->array_size);
+							if (asz == 0)
+								exit(1);
+						}
+
+						for (l=0; l<asz; l++)
+						{
+							sprintf(arrname, "%s[%d]", m->name, l);
+							for (j=0; j<subcl->num_members; j++)
+								print_one_member(cl, &(subcl->members[j]), arrname);
+						}
+					}
+					else
+					{
+						for (j=0; j<subcl->num_members; j++)
+							print_one_member(cl, &(subcl->members[j]), m->name);
+					}
+					return 0;
+				}
+			}
+		}
+		// either 2 levels deep or failed to find class
+		exit(1);
+	}
+	
+	// open member
+	printf("\t{\n");
+	
+	// name
+	if (prefix)
+		printf("\t\t\"%s.%s\", ", prefix, m->name);
+	else
+		printf("\t\t\"%s\", ", m->name);
+		
+	// flavor
+	printf("\"%s\",\n", m->flavor);
+	
+	// typeinfo: { off, array_size, type_size, is_signed, lo, hi }
+	if (prefix)
+		printf("\t\t{ G_STRUCT_OFFSET(%s, %s.%s), ", cl->name, prefix, m->name);
+	else
+		printf("\t\t{ G_STRUCT_OFFSET(%s, %s), ", cl->name, m->name);
+	printf("%s, ", m->array_size ? m->array_size : "0");
+	printf("%d, ", this_type->size);
+	printf("%s, ", this_type->is_signed ? "true" : "false");
+	if (m->lo && m->hi)
+		printf("%s, %s },\n", m->lo, m->hi);
+	else
+		printf("0, 0 },\n");
+
+	// valid
+	printf("\t\t_%s_valid, ", m->flavor);
+
+	// to_string
+	printf("_%s_to_string_%s, ",  m->flavor, this_type->name);
+
+	// from_string
+	printf("_string_to_%s_%s, ",  m->flavor, this_type->name);
+
+	// helptext
+	printf("_get_%s_helptext", m->flavor);
+
+	// close member	
+	printf("\n\t},\n");
+	return 0;
+}
+
+void get_type_and_name(char *str, member *m)
+{
+	char *tmp, *tmp2, *tmp3;
+
+	tmp = str;
+	while (*tmp != ';')
+		tmp++;
+	*tmp = '\0';
+	tmp--;
+	while (isalnum(*tmp) || *tmp=='[' || *tmp==']' || *tmp=='_' || *tmp=='+')
+		tmp--;
+	tmp++;
+	if ((tmp2=strchr(tmp, '[')) != NULL)
+	{
+		tmp3 = ++tmp2;
+		while (*tmp3 != ']')
+			tmp3++;
+		*tmp3 = '\0';
+		m->array_size = strdup(tmp2);
+		*(--tmp2) = '\0';
+	}
+	m->name = strdup(tmp);
+	tmp--;
+	tmp2 = str;
+	while (isspace(*tmp2))
+		tmp2++;
+	while (isspace(*tmp))
+		tmp--;
+	*(++tmp) = '\0';
+	m->type = strdup(tmp2);
+}

Added: trunk/fsck/sig.c
===================================================================
--- trunk/fsck/sig.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/fsck/sig.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,143 @@
+/*
+ * sig.c
+ *
+ * class signature checking for ocfs file system check utility
+ *
+ * Copyright (C) 2002, 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Author: Kurt Hackel, Sunil Mushran
+ */
+
+#include "fsck.h"
+
+
+int nodecfghdr_sig_match (char *buf, int idx)
+{
+	ocfs_node_config_hdr *hdr = (ocfs_node_config_hdr *)buf;
+	if (!strncmp (hdr->signature, NODE_CONFIG_HDR_SIGN, NODE_CONFIG_SIGN_LEN))
+		return 0;
+	fprintf(stderr, "\ninvalid signature found on autoconfig header.  found '%*s'\n",
+		NODE_CONFIG_SIGN_LEN, hdr->signature);
+	strcpy (hdr->signature, NODE_CONFIG_HDR_SIGN);
+	return -EINVAL;
+}
+
+int cleanup_log_sig_match (char *buf, int idx)
+{
+	return 0;
+}
+
+int dir_alloc_bitmap_sig_match (char *buf, int idx)
+{
+	return 0;
+}
+
+int dir_alloc_sig_match (char *buf, int idx)
+{
+	return 0;
+}
+
+int vol_disk_header_sig_match  (char *buf, int idx)
+{
+	return 0;
+}
+
+int disk_lock_sig_match (char *buf, int idx)
+{
+	return 0;
+}
+
+int file_alloc_bitmap_sig_match (char *buf, int idx)
+{
+	return 0;
+}
+
+int file_alloc_sig_match (char *buf, int idx)
+{
+	return 0;
+}
+
+int publish_sector_sig_match (char *buf, int idx)
+{
+	return 0;
+}
+
+int recover_log_sig_match (char *buf, int idx)
+{
+	return 0;
+}
+
+int vol_metadata_log_sig_match (char *buf, int idx)
+{
+	return 0;
+}
+
+int vol_metadata_sig_match (char *buf, int idx)
+{
+	return 0;
+}
+
+int vote_sector_sig_match (char *buf, int idx)
+{
+	return 0;
+}
+
+int dir_node_sig_match (char *buf, int idx)
+{
+	ocfs_dir_node *dir = (ocfs_dir_node *)buf;
+	if (IS_VALID_DIR_NODE(dir))
+		return 0;
+	fprintf(stderr, "\ninvalid signature found on directory.  found '%*s'\n",
+		strlen(OCFS_DIR_NODE_SIGNATURE), dir->signature);
+	strcpy (dir->signature, OCFS_DIR_NODE_SIGNATURE);
+	return -EINVAL;
+}
+
+int file_entry_sig_match (char *buf, int idx)
+{
+	ocfs_file_entry *fe = (ocfs_file_entry *)buf;
+	if (IS_VALID_FILE_ENTRY(fe))
+		return 0;
+	fprintf(stderr, "\ninvalid signature found on file entry.  found '%*s'\n",
+		strlen(OCFS_FILE_ENTRY_SIGNATURE), fe->signature);
+	strcpy (fe->signature, OCFS_FILE_ENTRY_SIGNATURE);
+	return -EINVAL;
+}
+
+int extent_header_sig_match (char *buf, int idx)
+{
+	ocfs_extent_group *ext = (ocfs_extent_group *)buf;
+	if (IS_VALID_EXTENT_HEADER(ext))
+		return 0;
+	fprintf(stderr, "\ninvalid signature found on extent header.  found '%*s'\n",
+		strlen(OCFS_EXTENT_HEADER_SIGNATURE), ext->signature);
+	strcpy (ext->signature, OCFS_EXTENT_HEADER_SIGNATURE);
+	return -EINVAL;
+}
+
+int extent_data_sig_match (char *buf, int idx)
+{
+	ocfs_extent_group *ext = (ocfs_extent_group *)buf;
+	if (IS_VALID_EXTENT_DATA(ext))
+		return 0;
+	fprintf(stderr, "\ninvalid signature found on extent data.  found '%*s'\n",
+		strlen(OCFS_EXTENT_DATA_SIGNATURE), ext->signature);
+	strcpy (ext->signature, OCFS_EXTENT_DATA_SIGNATURE);
+	return -EINVAL;
+}
+

Added: trunk/fsck/sig.h
===================================================================
--- trunk/fsck/sig.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/fsck/sig.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,47 @@
+/*
+ * sig.h
+ *
+ * Function prototypes, macros, etc. for related 'C' files
+ *
+ * Copyright (C) 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Sunil Mushran
+ */
+
+#ifndef SIG_H
+#define SIG_H
+
+int nodecfghdr_sig_match (char *buf, int idx);
+int cleanup_log_sig_match (char *buf, int idx);
+int dir_alloc_bitmap_sig_match (char *buf, int idx);
+int dir_alloc_sig_match (char *buf, int idx);
+int vol_disk_header_sig_match  (char *buf, int idx);
+int disk_lock_sig_match (char *buf, int idx);
+int file_alloc_bitmap_sig_match (char *buf, int idx);
+int file_alloc_sig_match (char *buf, int idx);
+int publish_sector_sig_match (char *buf, int idx);
+int recover_log_sig_match (char *buf, int idx);
+int vol_metadata_log_sig_match (char *buf, int idx);
+int vol_metadata_sig_match (char *buf, int idx);
+int vote_sector_sig_match (char *buf, int idx);
+int dir_node_sig_match (char *buf, int idx);
+int file_entry_sig_match (char *buf, int idx);
+int extent_header_sig_match (char *buf, int idx);
+int extent_data_sig_match (char *buf, int idx);
+
+#endif /* SIG_H */

Added: trunk/fsck/ver.c
===================================================================
--- trunk/fsck/ver.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/fsck/ver.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,41 @@
+/*
+ * ver.c
+ *
+ * prints version
+ *
+ * Copyright (C) 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Sunil Mushran
+ */
+
+#include <stdio.h>
+
+void version(char *progname);
+
+/*
+ * version()
+ *
+ */
+void version(char *progname)
+{
+	printf("%s %s %s (build %s)\n", progname,
+					FSCK_BUILD_VERSION,
+					FSCK_BUILD_DATE,
+					FSCK_BUILD_MD5);
+	return ;
+}				/* version */

Added: trunk/fsck/verify.c
===================================================================
--- trunk/fsck/verify.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/fsck/verify.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,951 @@
+/*
+ * verify.c
+ *
+ * verification checks for ocfs file system check utility
+ *
+ * Copyright (C) 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Sunil Mushran
+ */
+
+#include "fsck.h"
+
+
+extern ocfsck_context ctxt;
+
+/*
+ * test_member_range()
+ *
+ */
+int test_member_range(ocfs_class *cl, const char *name, char *buf)
+{
+	ocfs_class_member *mbr;
+	int i, ret = -1;
+
+	mbr = find_class_member(cl, name, &i);
+	if (mbr->valid(buf, &(mbr->type)) != 0)
+		ret = i;
+	return ret;
+}				/* test_member_range */
+
+/*
+ * check_outside_bounds()
+ *
+ */
+int check_outside_bounds(char *buf, int structsize)
+{
+	int i;
+	/* check for oddities */
+	for (i=structsize; i<512; i++)
+		if (buf[i] != 0)
+			return -1;
+	return 0;
+}				/* check_outside_bounds */
+
+/*
+ * verify_nodecfghdr()
+ *	 ocfs_disk_lock disk_lock;
+ *	 char signature[NODE_CONFIG_SIGN_LEN];
+ *	 __u32 version;
+ *	 __u32 num_nodes;
+ *	 __u32 last_node;
+ *	 __u64 cfg_seq_num;
+ */
+int verify_nodecfghdr (int fd, char *buf, int idx, GHashTable **bad)
+{
+	int ret = 0;
+	ocfs_node_config_hdr *hdr;
+	ocfs_layout_t *lay;
+	ocfs_class *cl;
+	ocfs_class_member *mbr;
+	int i;
+
+	hdr = (ocfs_node_config_hdr *)buf;
+	lay = find_nxt_hdr_struct(node_cfg_hdr, 0);
+	cl = lay->kind->cls;
+	*bad = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+	if (check_outside_bounds(buf, sizeof(ocfs_node_config_hdr)) == -1)
+		LOG_WARNING("nonzero bytes after the disk structure");
+
+	ret = verify_disk_lock (fd, buf, idx, bad);
+
+	if (hdr->version != NODE_CONFIG_VER) {
+		mbr = find_class_member(cl, "version", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+
+	if (hdr->num_nodes > OCFS_MAXIMUM_NODES) {
+		mbr = find_class_member(cl, "num_nodes", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+
+	if (g_hash_table_size(*bad) == 0)
+		ret = 0;
+
+	return ret;
+}				/* verify_nodecfghdr */
+
+/*
+ * verify_nodecfginfo()
+ *	ocfs_disk_lock disk_lock;
+ *	char node_name[MAX_NODE_NAME_LENGTH + 1];
+ *	ocfs_guid guid;
+ *	ocfs_ipc_config_info ipc_config;
+ */
+int verify_nodecfginfo (int fd, char *buf, int idx, GHashTable **bad)
+{
+	int ret = 0;
+	ocfs_disk_node_config_info *node;
+	ocfs_layout_t *lay;
+	ocfs_class *cl;
+
+	node = (ocfs_disk_node_config_info *)buf;
+	lay = find_nxt_hdr_struct(node_cfg_info, 0);
+	cl = lay->kind->cls;
+	*bad = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+	if (check_outside_bounds(buf, sizeof(ocfs_disk_node_config_info)) == -1)
+		LOG_WARNING("nonzero bytes after the disk structure");
+
+	ret = verify_disk_lock (fd, buf, idx, bad);
+
+	if (g_hash_table_size(*bad) == 0)
+		ret = 0;
+
+	return ret;
+}				/* verify_nodecfginfo */
+
+/*
+ * verify_system_file_entry()
+ *
+ */
+int verify_system_file_entry (int fd, char *buf, int idx, GHashTable **bad, char *fname, int type)
+{
+	int ret, i;
+	ocfs_file_entry *fe;
+	ocfs_class_member *mbr;
+	ocfs_class *cl;
+
+	cl = &ocfs_file_entry_class;
+	fe = (ocfs_file_entry *)buf;
+
+	ret = verify_file_entry (fd, buf, idx, bad);
+
+	if (strncmp(fe->filename, fname, strlen(fname)) != 0)
+	{
+		mbr = find_class_member(cl, "filename", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+		ret = -1;
+	}
+
+	check_file_entry(fd, fe, fe->this_sector, true, "$");
+
+	if (fe->disk_lock.curr_master != ((type+idx) % OCFS_MAXIMUM_NODES) &&
+	    fe->disk_lock.curr_master != OCFS_INVALID_NODE_NUM &&
+	    fe->disk_lock.file_lock != OCFS_DLM_NO_LOCK) {
+		fprintf(stderr, "bug 3038188 found!  system file locked "
+			"by another node: file=%s type=%d idx=%d node=%d.\n", 
+			fname, type, idx, fe->disk_lock.curr_master);
+		fprintf(stderr, "solution: unmount on all nodes except %d, then "
+			"touch a file in any directory on node %d.\n", 
+			((type+idx) % OCFS_MAXIMUM_NODES), ((type+idx) % OCFS_MAXIMUM_NODES));
+	}
+
+ 	return ret;
+}				/* verify_system_file_entry */
+
+#include <unistd.h>
+#include <linux/unistd.h>
+
+
+/*
+ * load_sysfile_bitmap()
+ *
+ */
+static int load_sysfile_bitmap (int fd, char *buf, int idx, bool dirbm)
+{
+	int ret = -1;
+	ocfs_file_entry *fe;
+	loff_t prev;
+	char *ptr;
+	int fileid;
+
+	fe = (ocfs_file_entry *)buf;
+
+	if (fe->file_size <= 0) {
+		ret = 0;
+		goto bail;
+	}
+	
+	if (dirbm) {
+		if ((ctxt.dir_bm[idx] = malloc_aligned(fe->alloc_size)) == NULL) {
+			LOG_INTERNAL();
+			goto bail;
+		}
+		memset(ctxt.dir_bm[idx], 0, fe->alloc_size);
+		ctxt.dir_bm_sz[idx] = fe->file_size;
+		ptr = ctxt.dir_bm[idx];
+		fileid = idx + OCFS_FILE_DIR_ALLOC_BITMAP;
+	} else {
+		if ((ctxt.ext_bm[idx] = malloc_aligned(fe->alloc_size)) == NULL) {
+			LOG_INTERNAL();
+			goto bail;
+		}
+		memset(ctxt.ext_bm[idx], 0, fe->alloc_size);
+		ctxt.ext_bm_sz[idx] = fe->file_size;
+		ptr = ctxt.ext_bm[idx];
+		fileid = idx + OCFS_FILE_FILE_ALLOC_BITMAP;
+	}
+
+	if ((prev=myseek64(fd, 0ULL, SEEK_CUR)) == -1) {
+		LOG_INTERNAL();
+		goto bail;
+	}
+
+	ret = ocfs_read_system_file(ctxt.vcb, fileid, ptr, fe->alloc_size,
+				    (__u64)0);
+#if 0
+	if (ret >= 0) {
+		ocfs_alloc_bm bm;
+		int freebits, firstclear;
+
+		LOG_VERBOSE("succeeded\n");
+		ocfs_initialize_bitmap(&bm, ptr, (__u32) (fe->file_size * 8));
+		freebits = ocfs_count_bits(&bm);
+		firstclear = ocfs_find_clear_bits(&bm, 1, 0, 0);
+		LOG_VERBOSE("freebits=%d firstclear=%d numbits=%llu\n",
+			    freebits, firstclear, fe->file_size * 8);
+	} else {
+		LOG_VERBOSE("failed\n");
+	}
+#endif
+
+	if ((prev=myseek64(fd, prev, SEEK_SET)) == -1) {
+		LOG_INTERNAL();
+		goto bail;
+	}
+
+      bail:
+	return ret;
+}				/* load_sysfile_bitmap */
+
+/*
+ * verify_dir_alloc_bitmap()
+ *
+ */
+int verify_dir_alloc_bitmap (int fd, char *buf, int idx, GHashTable **bad)
+{
+	char fname[30];
+	sprintf(fname, "%s%d", "DirBitMapFile", idx+OCFS_FILE_DIR_ALLOC_BITMAP);
+	load_sysfile_bitmap(fd, buf, idx, true);
+	return verify_system_file_entry (fd, buf, idx, bad, fname, OCFS_FILE_DIR_ALLOC_BITMAP);
+}				/* verify_dir_alloc_bitmap */
+
+/*
+ * verify_file_alloc_bitmap()
+ *
+ */
+int verify_file_alloc_bitmap (int fd, char *buf, int idx, GHashTable **bad)
+{
+	char fname[30];
+	sprintf(fname, "%s%d", "ExtentBitMapFile", idx+OCFS_FILE_FILE_ALLOC_BITMAP);
+	load_sysfile_bitmap(fd, buf, idx, false);
+	return verify_system_file_entry (fd, buf, idx, bad, fname, OCFS_FILE_FILE_ALLOC_BITMAP);
+}				/* verify_file_alloc_bitmap */
+
+/*
+ * verify_dir_alloc()
+ *
+ */
+int verify_dir_alloc (int fd, char *buf, int idx, GHashTable **bad)
+{
+	char fname[30];
+	sprintf(fname, "%s%d", "DirFile", idx+OCFS_FILE_DIR_ALLOC);
+	return verify_system_file_entry (fd, buf, idx, bad, fname, OCFS_FILE_DIR_ALLOC);
+}				/* verify_dir_alloc */
+
+/*
+ * verify_file_alloc()
+ *
+ */
+int verify_file_alloc (int fd, char *buf, int idx, GHashTable **bad)
+{
+	char fname[30];
+	sprintf(fname, "%s%d", "ExtentFile", idx+OCFS_FILE_FILE_ALLOC);
+	return verify_system_file_entry (fd, buf, idx, bad, fname, OCFS_FILE_FILE_ALLOC);
+}				/* verify_file_alloc */
+
+/*
+ * verify_vol_metadata()
+ *
+ */
+int verify_vol_metadata (int fd, char *buf, int idx, GHashTable **bad)
+{
+	char fname[30];
+	sprintf(fname, "%s", "VolMetaDataFile");  // no file #
+	return verify_system_file_entry (fd, buf, idx, bad, fname, OCFS_FILE_VOL_META_DATA);
+}				/* verify_vol_metadata */
+
+/*
+ * verify_vol_metadata_log()
+ *
+ */
+int verify_vol_metadata_log (int fd, char *buf, int idx, GHashTable **bad)
+{
+	char fname[30];
+	sprintf(fname, "%s", "VolMetaDataLogFile");  // no file #
+	return verify_system_file_entry (fd, buf, idx, bad, fname, OCFS_FILE_VOL_LOG_FILE);
+}				/* verify_vol_metadata_log */
+
+/*
+ * verify_cleanup_log()
+ *
+ */
+int verify_cleanup_log (int fd, char *buf, int idx, GHashTable **bad)
+{
+	char fname[30];
+	sprintf(fname, "%s%d", "CleanUpLogFile", idx+CLEANUP_FILE_BASE_ID);
+	return verify_system_file_entry (fd, buf, idx, bad, fname, CLEANUP_FILE_BASE_ID);
+}				/* verify_cleanup_log */
+
+/*
+ * verify_recover_log()
+ *
+ */
+int verify_recover_log (int fd, char *buf, int idx, GHashTable **bad)
+{
+	char fname[30];
+	sprintf(fname, "%s%d", "RecoverLogFile", idx+LOG_FILE_BASE_ID);
+	return verify_system_file_entry (fd, buf, idx, bad, fname, LOG_FILE_BASE_ID);
+}				/* verify_recover_log */
+
+/*
+ * verify_volume_bitmap()
+ *
+ */
+int verify_volume_bitmap (int fd, char *buf, int idx, GHashTable **bad)
+{
+	return 0;
+}				/* verify_volume_bitmap */
+
+/*
+ * verify_publish_sector()
+ *
+ */
+int verify_publish_sector (int fd, char *buf, int idx, GHashTable **bad)
+{
+	int i;
+	ocfs_publish *pub;
+	ocfs_class *cl;
+
+	pub = (ocfs_publish *)buf;
+	cl = &ocfs_publish_class;
+	*bad = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+	if ((i = test_member_range(cl, "time", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	if ((i = test_member_range(cl, "vote", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	if ((i = test_member_range(cl, "dirty", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	if ((i = test_member_range(cl, "vote_type", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	if ((i = test_member_range(cl, "vote_map", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	if ((i = test_member_range(cl, "publ_seq_num", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	if ((i = test_member_range(cl, "dir_ent", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	if ((i = test_member_range(cl, "comm_seq_num", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+
+	if (g_hash_table_size(*bad) == 0)
+		return 0;
+	return -1;
+}				/* verify_publish_sector */
+
+/*
+ * verify_vote_sector()
+ *
+ */
+int verify_vote_sector (int fd, char *buf, int idx, GHashTable **bad)
+{
+	int i;
+	ocfs_vote *vote;
+	ocfs_class *cl;
+
+	vote = (ocfs_vote *)buf;
+	cl = &ocfs_vote_class;
+	*bad = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+	if ((i = test_member_range(cl, "vote", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	if ((i = test_member_range(cl, "vote_seq_num", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	if ((i = test_member_range(cl, "dir_ent", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	if ((i = test_member_range(cl, "open_handle", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+
+	if (g_hash_table_size(*bad) == 0)
+		return 0;
+	return -1;
+}				/* verify_vote_sector */
+
+/*
+ * verify_dir_node()
+ *
+ */
+int verify_dir_node (int fd, char *buf, int idx, GHashTable **bad)
+{
+	int ret = 0;
+//	ocfs_dir_node *dir;
+	ocfs_class *cl;
+//	int i;
+//	ocfs_class_member *mbr;
+//	int j;
+//	__u64 size = 0;
+//	__u64 off = 0;
+//	char tmpstr[255];
+
+	cl = &ocfs_dir_node_class;
+	*bad = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+	if (check_outside_bounds(buf, sizeof(ocfs_dir_node)) == -1)
+		LOG_WARNING("nonzero bytes after the disk structure");
+
+	/* ocfs_disk_lock disk_lock; */ 
+	ret = verify_disk_lock (fd, buf, idx, bad);
+
+	/* __u64 alloc_file_off;     */ 
+	/* __u32 alloc_node;         */ 
+	/* __u64 free_node_ptr;      */ 
+	/* __u64 node_disk_off;      */ 
+	/* __s64 next_node_ptr;      */ 
+	/* __s64 indx_node_ptr;      */ 
+	/* __s64 next_del_ent_node;  */ 
+	/* __s64 head_del_ent_node;  */ 
+	/* __u8 first_del;           */
+	/* __u8 num_del;             */
+	/* __u8 num_ents;	     */
+	/* __u8 depth;		     */
+	/* __u8 num_ent_used;	     */
+	/* __u8 dir_node_flags;	     */
+	/* __u8 sync_flags;          */
+	/* __u8 index[256];          */
+	/* __u8 index_dirty;         */
+	/* __u8 bad_off;             */
+	/* __u64 num_tot_files;      */
+	/* __u8 reserved[119];       */
+	/* __u8 file_ent[1];         */
+
+	if (g_hash_table_size(*bad) == 0)
+		ret = 0;
+
+	return 0;
+}				/* verify_dir_node */
+
+/*
+ * verify_file_entry()
+ *
+ */
+int verify_file_entry (int fd, char *buf, int idx, GHashTable **bad)
+{
+	int ret = 0;
+	ocfs_file_entry *fe;
+	ocfs_class *cl;
+	ocfs_class_member *mbr;
+	int i;
+	int j;
+	__u64 size = 0;
+	__u64 off = 0;
+	char tmpstr[255];
+
+	fe = (ocfs_file_entry *)buf;
+	cl = &ocfs_file_entry_class;
+	*bad = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+	if (check_outside_bounds(buf, sizeof(ocfs_file_entry)) == -1)
+		LOG_WARNING("nonzero bytes after the disk structure");
+
+	/* ocfs_disk_lock disk_lock; */
+	ret = verify_disk_lock (fd, buf, idx, bad);
+
+	/* bool local_ext;     */
+	/* __s32 granularity;  */
+	if ((fe->local_ext && fe->granularity != -1) ||
+	    (!fe->local_ext && fe->granularity < 0)) {
+		mbr = find_class_member(cl, "local_ext", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+		mbr = find_class_member(cl, "granularity", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+
+	/* __u8 next_free_ext; */
+	if (fe->next_free_ext > OCFS_MAX_FILE_ENTRY_EXTENTS) {
+		mbr = find_class_member(cl, "next_free_ext", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+
+	/* __s8 next_del; */
+	/* __u8 filename[OCFS_MAX_FILENAME_LENGTH]; */
+	/* __u16 filename_len; */
+	
+	for (j = 0; j < OCFS_MAX_FILE_ENTRY_EXTENTS; j++)
+		size += fe->extents[j].num_bytes;
+
+	/* __u64 file_size;    */
+	if (!(fe->attribs & OCFS_ATTRIB_DIRECTORY) && fe->file_size > size) {
+		mbr = find_class_member(cl, "file_size", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+	
+	/* __u64 alloc_size;   */
+	if (!(fe->attribs & OCFS_ATTRIB_DIRECTORY) && fe->alloc_size != size) {
+		mbr = find_class_member(cl, "alloc_size", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+
+	/* __u64 create_time;  */
+	/* __u64 modify_time;  */
+
+	/* ocfs_alloc_ext extents[OCFS_MAX_FILE_ENTRY_EXTENTS]; */
+	for (j = 0, off = 0; j < OCFS_MAX_FILE_ENTRY_EXTENTS; ++j) {
+		if (!fe->extents[j].num_bytes)
+			continue;
+
+		if (fe->extents[j].file_off != off) {
+			sprintf(tmpstr, "extents[%d].file_off", j);
+			mbr = find_class_member(cl, tmpstr, &i);
+			g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+		}
+
+		off += fe->extents[j].num_bytes;
+
+		if (fe->extents[j].num_bytes && !fe->extents[j].disk_off) {
+			sprintf(tmpstr, "extents[%d].num_bytes", j);
+			mbr = find_class_member(cl, tmpstr, &i);
+			g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+		}
+	}
+
+	/* __u64 dir_node_ptr; */
+
+	/* __u64 this_sector;  */
+	if (!fe->this_sector) {
+		mbr = find_class_member(cl, "this_sector", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+
+	/* __u64 last_ext_ptr; */
+	if (!fe->local_ext && !fe->last_ext_ptr) {
+		mbr = find_class_member(cl, "last_ext_ptr", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+
+	/* __u32 sync_flags;  */
+	/* __u32 link_cnt;  */
+	/* __u32 attribs;   */
+	/* __u32 prot_bits; */
+	/* __u32 uid;       */
+	/* __u32 gid;       */
+	/* __u16 dev_major; */
+	/* __u16 dev_minor; */
+
+	if (g_hash_table_size(*bad) == 0)
+		ret = 0;
+
+	return 0;
+}				/* verify_file_entry */
+
+/*
+ * verify_extent_group()
+ *
+ */
+int verify_extent_group (int fd, char *buf, int idx, GHashTable **bad, int type, __u64 up_ptr)
+{
+	ocfs_extent_group *ext;
+	ocfs_class *cl;
+	ocfs_class_member *mbr;
+	int i, j;
+	char mname[255];
+	__u64 len;
+
+	ext = (ocfs_extent_group *)buf;
+	cl = &ocfs_extent_group_class;
+	*bad = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+	if (ext->type != type) {
+		mbr = find_class_member(cl, "type", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+
+	if ((i = test_member_range(cl, "next_free_ext", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+
+	if ((i = test_member_range(cl, "curr_sect", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+
+	if ((i = test_member_range(cl, "max_sects", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+
+	if ((i = test_member_range(cl, "alloc_node", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+
+	if ((i = test_member_range(cl, "this_ext", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+
+	if ((i = test_member_range(cl, "next_data_ext", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+
+	if ((i = test_member_range(cl, "alloc_file_off", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+
+	if ((i = test_member_range(cl, "last_ext_ptr", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+
+	if ((i = test_member_range(cl, "granularity", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+
+	// make sure the up_ptr isn't b0rk3n
+	if (up_ptr != 0ULL && ext->up_hdr_node_ptr != up_ptr) {
+		i = test_member_range(cl, "up_hdr_node_ptr", buf);
+		if (i != -1)
+			g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+
+	len = ext->extents[0].file_off;
+	for (j = 0; j < OCFS_MAX_DATA_EXTENTS; j++) {
+		if (!ext->extents[j].num_bytes)
+			continue;
+
+		if (ext->extents[j].file_off != len) {
+			sprintf(mname, "extents[%d].file_off", j);
+			mbr = find_class_member(cl, mname, &i);
+			g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+		}
+
+		len += ext->extents[j].num_bytes;
+
+		if (ext->extents[j].num_bytes && !ext->extents[j].disk_off) {
+			sprintf(mname, "extents[%d].num_bytes", i);
+			mbr = find_class_member(cl, mname, &i);
+			g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+		}
+	}
+
+	if (g_hash_table_size(*bad) == 0)
+		return 0;
+
+	return -1;
+}				/* verify_extent_group */
+
+/*
+ * verify_extent_header()
+ *
+ */
+int verify_extent_header (int fd, char *buf, int idx, GHashTable **bad)
+{
+	return verify_extent_group(fd, buf, idx, bad, OCFS_EXTENT_HEADER, 0ULL);
+}				/* verify_extent_header */
+
+/*
+ * verify_extent_data()
+ *
+ */
+int verify_extent_data (int fd, char *buf, int idx, GHashTable **bad)
+{
+	return verify_extent_group(fd, buf, idx, bad, OCFS_EXTENT_DATA, 0ULL);
+}				/* verify_extent_data */
+
+
+
+// TODO: FIXME error handling
+/*
+ * load_volume_bitmap()
+ *
+ */
+int load_volume_bitmap(void)
+{
+	loff_t old;
+	int ret = -1;
+
+	/* assumes the hdr has already been verified */
+	if (ctxt.hdr->bitmap_off == 0) {
+		LOG_INTERNAL();
+		goto bail;
+	}
+
+	if ((old = myseek64(ctxt.fd, 0, SEEK_CUR)) == -1) {
+		LOG_INTERNAL();
+		goto bail;
+	}
+
+	if (myseek64(ctxt.fd, ctxt.hdr->bitmap_off, SEEK_SET) == -1) {
+		LOG_INTERNAL();
+		goto bail;
+	}
+
+//	if (myread(ctxt.fd, ctxt.vol_bm, (ctxt.hdr->num_clusters + 7 / 8)) == -1) {
+	if (myread(ctxt.fd, ctxt.vol_bm, VOL_BITMAP_BYTES) == -1) {
+		LOG_INTERNAL();
+		goto bail;
+	}
+
+	if (myseek64(ctxt.fd, old, SEEK_SET) == -1) {
+		LOG_INTERNAL();
+		goto bail;
+	}
+
+	ret = 0;
+
+      bail:
+	return ret;
+}				/* load_volume_bitmap */
+
+/*
+ * verify_vol_disk_header()
+ *
+ */
+int verify_vol_disk_header(int fd, char *buf, int idx, GHashTable **bad)
+{
+	int len, ret = -1;
+	__u64 j;
+	ocfs_dir_node *dir = NULL;
+	ocfs_vol_disk_hdr *hdr;
+	ocfs_layout_t *lay;
+	ocfs_class *cl;
+	ocfs_class_member *mbr;
+	int i;
+
+	dir = (ocfs_dir_node *) malloc_aligned(512);
+	hdr = (ocfs_vol_disk_hdr *)buf;
+	lay = find_nxt_hdr_struct(vol_disk_header, 0);
+	cl = lay->kind->cls;
+	*bad = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+	if (check_outside_bounds(buf, sizeof(ocfs_vol_disk_hdr)) == -1) {
+		LOG_WARNING("nonzero bytes after the disk header structure");
+	}
+
+	if (hdr->minor_version != OCFS_MINOR_VERSION)
+	{
+		mbr = find_class_member(cl, "minor_version", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+	if (hdr->major_version != OCFS_MAJOR_VERSION)
+	{
+		mbr = find_class_member(cl, "major_version", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+	if (strncmp(hdr->signature, OCFS_VOLUME_SIGNATURE, MAX_VOL_SIGNATURE_LEN) != 0)
+	{
+		mbr = find_class_member(cl, "signature", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+	len = strnlen(hdr->mount_point, MAX_MOUNT_POINT_LEN);
+	if (len == MAX_MOUNT_POINT_LEN || len < OCFSCK_MIN_MOUNT_POINT_LEN)
+	{
+		mbr = find_class_member(cl, "mount_point", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+	if (hdr->bitmap_off != OCFSCK_BITMAP_OFF)
+	{
+		mbr = find_class_member(cl, "bitmap_off", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+	if (hdr->publ_off != OCFSCK_PUBLISH_OFF)
+	{
+		mbr = find_class_member(cl, "publ_off", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+	if (hdr->vote_off != OCFSCK_VOTE_OFF)
+	{
+		mbr = find_class_member(cl, "vote_off", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+	if (hdr->node_cfg_off != OCFSCK_AUTOCONF_OFF)
+	{
+		mbr = find_class_member(cl, "node_cfg_off", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+	if (hdr->node_cfg_size !=  OCFSCK_AUTOCONF_SIZE)
+	{
+		mbr = find_class_member(cl, "node_cfg_size", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+	if (hdr->new_cfg_off != OCFSCK_NEW_CFG_OFF)
+	{
+		mbr = find_class_member(cl, "new_cfg_off", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+	if (hdr->data_start_off != OCFSCK_DATA_START_OFF)
+	{
+		mbr = find_class_member(cl, "data_start_off", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+	if (hdr->internal_off != OCFSCK_INTERNAL_OFF)
+	{
+		mbr = find_class_member(cl, "internal_off", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+	if (hdr->num_nodes != (__u64)OCFS_MAXIMUM_NODES)
+	{
+		mbr = find_class_member(cl, "num_nodes", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+	if (hdr->serial_num != 0ULL)
+	{
+		mbr = find_class_member(cl, "serial_num", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+	if (hdr->start_off != 0ULL)
+	{
+		mbr = find_class_member(cl, "start_off", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+	if (hdr->root_bitmap_off != 0ULL)
+	{
+		mbr = find_class_member(cl, "root_bitmap_off", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+	if (hdr->root_bitmap_size != 0ULL)
+	{
+		mbr = find_class_member(cl, "root_bitmap_size", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+	if (hdr->root_size != 0ULL)
+	{
+		mbr = find_class_member(cl, "root_size", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+	if (hdr->dir_node_size != 0ULL)
+	{
+		mbr = find_class_member(cl, "dir_node_size", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+	if (hdr->file_node_size != 0ULL)
+	{
+		mbr = find_class_member(cl, "file_node_size", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+	if ((i = test_member_range(cl, "excl_mount", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	if ((i = test_member_range(cl, "uid", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	if ((i = test_member_range(cl, "gid", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	if ((i = test_member_range(cl, "prot_bits", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+
+	if (hdr->device_size > ctxt.device_size)
+	{
+		mbr = find_class_member(cl, "device_size", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+	
+	ctxt.cluster_size_bits = 11; // 2048
+	for (j = OCFSCK_LO_CLUSTER_SIZE; j <= OCFSCK_HI_CLUSTER_SIZE; j *= 2)
+	{
+		ctxt.cluster_size_bits++;
+		if (hdr->cluster_size == j)
+		{
+			if (j * hdr->num_clusters > ctxt.device_size - OCFSCK_NON_DATA_AREA ||
+			    hdr->num_clusters < 1 || hdr->num_clusters > OCFSCK_MAX_CLUSTERS)
+			{
+				mbr = find_class_member(cl, "num_clusters", &i);
+				g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+			}
+			break;
+		}
+	}
+	if (j > OCFSCK_HI_CLUSTER_SIZE)
+	{
+		mbr = find_class_member(cl, "cluster_size", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+
+	/* the root off is *always* at OCFSCK_ROOT_OFF */
+	/* and we can no longer do the signature check because */
+	/* it may be bad and we want to be able to change it later */
+	if (hdr->root_off != OCFSCK_ROOT_OFF)
+	{
+		mbr = find_class_member(cl, "root_off", &i);
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	}
+
+
+	if (g_hash_table_size(*bad) == 0)
+	{
+		memcpy(ctxt.hdr, buf, OCFS_SECTOR_SIZE);
+		ctxt.vcb = get_fake_vcb(ctxt.fd, ctxt.hdr, /* node# */ 0);
+		if ((ret = load_volume_bitmap()) != 0)
+			LOG_ERROR("failed to read volume bitmap");
+	}
+	if (dir)
+		free_aligned(dir);
+	return ret;
+}				/* verify_vol_disk_header */
+
+/*
+ * verify_vol_label()
+ *
+ */
+int verify_vol_label (int fd, char *buf, int idx, GHashTable **bad)
+{
+	ocfs_vol_label *lbl;
+
+	lbl = (ocfs_vol_label *)buf;
+
+	if (check_outside_bounds(buf, sizeof(ocfs_vol_label)) == -1) {
+		LOG_WARNING("nonzero bytes after the volume label structure");
+	}
+
+	return verify_disk_lock (fd, buf, idx, bad);
+}				/* verify_vol_label */
+
+/*
+ * verify_disk_lock()
+ *
+ */
+int verify_disk_lock (int fd, char *buf, int idx, GHashTable **bad)
+{
+	ocfs_disk_lock *lock;
+	ocfs_class *cl;
+	int i;
+
+	lock = (ocfs_disk_lock *)buf;
+	cl = &ocfs_disk_lock_class;
+	*bad = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+	if ((i = test_member_range(cl, "curr_master", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	if ((i = test_member_range(cl, "writer_node_num", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	if ((i = test_member_range(cl, "reader_node_num", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	if ((i = test_member_range(cl, "oin_node_map", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+	if ((i = test_member_range(cl, "file_lock", buf)) != -1)
+		g_hash_table_insert(*bad, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
+
+	if (g_hash_table_size(*bad) == 0)
+		return 0;
+	return -1;
+}				/* verify_disk_lock */

Added: trunk/fsck/verify.h
===================================================================
--- trunk/fsck/verify.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/fsck/verify.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,57 @@
+/*
+ * verify.h
+ *
+ * Function prototypes, macros, etc. for related 'C' files
+ *
+ * Copyright (C) 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Sunil Mushran
+ */
+
+#ifndef VERIFY_H
+#define VERIFY_H
+
+int test_member_range(ocfs_class *cl, const char *name, char *buf);
+int check_outside_bounds(char *buf, int structsize);
+int verify_vol_disk_header  (int fd, char *buf, int idx, GHashTable **bad);
+int verify_disk_lock (int fd, char *buf, int idx, GHashTable **bad);
+int verify_vol_label  (int fd, char *buf, int idx, GHashTable **bad);
+int verify_nodecfghdr (int fd, char *buf, int idx, GHashTable **bad);
+int verify_nodecfginfo (int fd, char *buf, int idx, GHashTable **bad);
+int verify_cleanup_log (int fd, char *buf, int idx, GHashTable **bad);
+int verify_dir_alloc (int fd, char *buf, int idx, GHashTable **bad);
+int verify_dir_alloc_bitmap (int fd, char *buf, int idx, GHashTable **bad);
+int verify_file_alloc (int fd, char *buf, int idx, GHashTable **bad);
+int verify_file_alloc_bitmap (int fd, char *buf, int idx, GHashTable **bad);
+int verify_publish_sector (int fd, char *buf, int idx, GHashTable **bad);
+int verify_recover_log (int fd, char *buf, int idx, GHashTable **bad);
+int verify_vol_metadata (int fd, char *buf, int idx, GHashTable **bad);
+int verify_vol_metadata_log (int fd, char *buf, int idx, GHashTable **bad);
+int verify_volume_bitmap (int fd, char *buf, int idx, GHashTable **bad);
+int verify_vote_sector (int fd, char *buf, int idx, GHashTable **bad);
+int verify_dir_node (int fd, char *buf, int idx, GHashTable **bad);
+int verify_file_entry (int fd, char *buf, int idx, GHashTable **bad);
+int verify_extent_group (int fd, char *buf, int idx, GHashTable **bad,
+			 int type, __u64 up_ptr);
+int verify_extent_header (int fd, char *buf, int idx, GHashTable **bad);
+int verify_extent_data (int fd, char *buf, int idx, GHashTable **bad);
+int verify_system_file_entry (int fd, char *buf, int idx, GHashTable **bad, 
+			      char *fname, int type);
+int load_volume_bitmap(void);
+
+#endif /* VERIFY_H */

Added: trunk/install-sh
===================================================================
--- trunk/install-sh	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/install-sh	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,310 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2004-01-12.10
+
+# 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.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+# put in absolute paths if you don't have them in your path; or use env. 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}"
+
+transformbasename=
+transform_arg=
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=
+chgrpcmd=
+stripcmd=
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=
+dst=
+dir_arg=
+
+usage="Usage: $0 [OPTION]... SRCFILE DSTFILE
+   or: $0 [OPTION]... SRCFILES... DIRECTORY
+   or: $0 -d DIRECTORIES...
+
+In the first form, install SRCFILE to DSTFILE, removing SRCFILE by default.
+In the second, create the directory path DIR.
+
+Options:
+-b=TRANSFORMBASENAME
+-c         copy source (using $cpprog) instead of moving (using $mvprog).
+-d         create directories instead of installing files.
+-g GROUP   $chgrp installed files to GROUP.
+-m MODE    $chmod installed files to MODE.
+-o USER    $chown installed files to USER.
+-s         strip installed files (using $stripprog).
+-t=TRANSFORM
+--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 -n "$1"; do
+  case $1 in
+    -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+        shift
+        continue;;
+
+    -c) instcmd=$cpprog
+        shift
+        continue;;
+
+    -d) dir_arg=true
+        shift
+        continue;;
+
+    -g) chgrpcmd="$chgrpprog $2"
+        shift
+        shift
+        continue;;
+
+    --help) echo "$usage"; exit 0;;
+
+    -m) chmodcmd="$chmodprog $2"
+        shift
+        shift
+        continue;;
+
+    -o) chowncmd="$chownprog $2"
+        shift
+        shift
+        continue;;
+
+    -s) stripcmd=$stripprog
+        shift
+        continue;;
+
+    -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+        shift
+        continue;;
+
+    --version) echo "$0 $scriptversion"; exit 0;;
+
+    *)  # When -d is used, all remaining arguments are directories to create.
+	test -n "$dir_arg" && break
+        # 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
+	break;;
+  esac
+done
+
+if test -z "$1"; 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
+
+for src
+do
+  # Protect names starting with `-'.
+  case $src in
+    -*) src=./$src ;;
+  esac
+
+  if test -n "$dir_arg"; then
+    dst=$src
+    src=
+
+    if test -d "$dst"; then
+      instcmd=:
+      chmodcmd=
+    else
+      instcmd=$mkdirprog
+    fi
+  else
+    # Waiting for this to be detected by the "$instcmd $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
+      dst=$dst/`basename "$src"`
+    fi
+  fi
+
+  # This sed command emulates the dirname command.
+  dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+  # Make sure that the destination directory exists.
+
+  # Skip lots of stat calls in the usual case.
+  if test ! -d "$dstdir"; then
+    defaultIFS='
+  	'
+    IFS="${IFS-$defaultIFS}"
+
+    oIFS=$IFS
+    # Some sh's can't handle IFS=/ for some reason.
+    IFS='%'
+    set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
+    IFS=$oIFS
+
+    pathcomp=
+
+    while test $# -ne 0 ; do
+      pathcomp=$pathcomp$1
+      shift
+      test -d "$pathcomp" || $mkdirprog "$pathcomp"
+      pathcomp=$pathcomp/
+    done
+  fi
+
+  if test -n "$dir_arg"; then
+    $doit $instcmd "$dst" \
+      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
+      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
+      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
+      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
+
+  else
+    # If we're going to rename the final executable, determine the name now.
+    if test -z "$transformarg"; then
+      dstfile=`basename "$dst"`
+    else
+      dstfile=`basename "$dst" $transformbasename \
+               | sed $transformarg`$transformbasename
+    fi
+
+    # don't allow the sed command to completely eliminate the filename.
+    test -z "$dstfile" && dstfile=`basename "$dst"`
+
+    # 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 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
+    trap '(exit $?); exit' 1 2 13 15
+
+    # Move or copy the file name to the temp name
+    $doit $instcmd "$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 $instcmd $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 "$dsttmp"; } &&
+
+    # 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 "$dstdir/$dstfile"; then
+        $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
+        || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
+        || {
+  	  echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
+  	  (exit 1); exit
+        }
+      else
+        :
+      fi
+    } &&
+
+    # Now rename the file to the real destination.
+    $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
+  fi || { (exit 1); exit; }
+done
+
+# The final little trick to "correctly" pass the exit status to the exit trap.
+{
+  (exit 0); exit
+}
+
+# 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:


Property changes on: trunk/install-sh
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/libocfs/Common/inc/ocfs.h
===================================================================
--- trunk/libocfs/Common/inc/ocfs.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/inc/ocfs.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,137 @@
+/*
+ * ocfs.h
+ *
+ * Main include file
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef  _OCFS_H_
+#define  _OCFS_H_
+
+/* XXX Hack to avoid warning */
+struct mem_dqinfo;
+extern inline void mark_info_dirty(struct mem_dqinfo *info);
+
+extern inline int generic_fls(int x);
+extern inline int get_bitmask_order(unsigned int count);
+
+#include <linux/version.h>
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,9)
+#ifdef __i386__
+extern inline void prefetch(const void *x);
+#endif
+#endif
+
+#ifndef SUSE
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,18)
+#ifdef __ia64__
+extern inline void prefetch(const void *x);
+extern inline void prefetchw(const void *x);
+#endif
+#endif
+#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,21)
+#ifdef __ia64__
+extern inline void prefetch(const void *x);
+extern inline void prefetchw(const void *x);
+#endif
+#endif
+#endif
+
+/*
+** System header files
+*/
+#define   __KERNEL_SYSCALLS__
+#include  <linux/types.h>
+#include  <linux/config.h>
+#include  <linux/module.h>
+#include  <linux/init.h>
+#include  <linux/kernel.h>
+#include  <asm/byteorder.h>
+#include  <linux/spinlock.h>
+#include  <linux/slab.h>
+#include  <linux/slab.h>
+#include  <linux/sched.h>
+#include  <linux/delay.h>
+#include  <linux/wait.h>
+#include  <linux/list.h>
+#include  <linux/fs.h>
+#include  <linux/pagemap.h>
+#include  <linux/random.h>
+#include  <linux/string.h>
+#include  <linux/locks.h>
+#include  <linux/hdreg.h>
+#include  <linux/file.h>
+#include  <linux/raw.h>
+#include  <linux/vmalloc.h>
+#include  <linux/proc_fs.h>
+#include  <linux/unistd.h>
+#include  <asm/uaccess.h>
+#include  <linux/net.h>
+#include  <net/sock.h>
+#include  <linux/ctype.h>
+#include  <linux/tqueue.h>
+#include  <linux/inet.h>
+
+/*
+** Private header files
+*/
+#include  <ocfsbool.h>
+#include  <ocfsconst.h>
+#include  <ocfscom.h>
+
+#include  <ocfshash.h>
+#include  <ocfstrace.h>
+#include  <ocfsvol.h>
+#include  <ocfsdisk.h>
+#include  <ocfsdef.h>
+#include  <ocfstrans.h>
+#include  <ocfsdlm.h>
+
+#include  <ocfsver.h>
+
+#include  <ocfsiosup.h>
+#include  <ocfsport.h>
+#include  <ocfsgenmisc.h>
+#include  <ocfsgenalloc.h>
+#include  <ocfsgencreate.h>
+#include  <ocfsgendirnode.h>
+#include  <ocfsgendlm.h>
+#include  <ocfsheartbeat.h>
+#include  <ocfsgennm.h>
+#include  <ocfsgensysfile.h>
+#include  <ocfsgentrans.h>
+#include  <ocfsgenutil.h>
+#include  <ocfsgenvolcfg.h>
+#include  <ocfsgenvote.h>
+
+#include  <ocfsbitmap.h>
+#include  <ocfsdlmp.h>
+#include  <ocfsfile.h>
+#include  <ocfsioctl.h>
+#include  <ocfsipc.h>
+#include  <ocfsmain.h>
+#include  <ocfsmount.h>
+#include  <ocfsproc.h>
+
+#endif				/* _OCFS_H_ */

Added: trunk/libocfs/Common/inc/ocfsbool.h
===================================================================
--- trunk/libocfs/Common/inc/ocfsbool.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/inc/ocfsbool.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,37 @@
+/*
+ * ocfsbool.h
+ *
+ * Defines a boolean type. Yes, we use our own boolean type. Eventually
+ * someone will have to do a global search and replace to just use __s32
+ *
+ * Copyright (C) 2003 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts, Mark Fasheh
+ */
+
+
+#ifndef  _OCFSBOOL_H_
+#define  _OCFSBOOL_H_
+
+typedef enum { false = 0, true = 1 } ocfs_bool;
+
+/* This should be removed and all old code fixed to just use ocfs_bool */
+typedef ocfs_bool bool;
+
+#endif	/* _OCFSBOOL_H_ */

Added: trunk/libocfs/Common/inc/ocfscom.h
===================================================================
--- trunk/libocfs/Common/inc/ocfscom.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/inc/ocfscom.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,161 @@
+/*
+ * ocfscom.h
+ *
+ * Includes datatype typedefs among other things
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSCOM_H_
+#define _OCFSCOM_H_
+
+#define OCFS_POINTER_SIZE   (sizeof(void *))
+
+#ifdef __LP64__
+#define OCFS_GCC_ATTR_PACKED	__attribute__ ((packed))
+#define OCFS_GCC_ATTR_ALIGNED	__attribute__ ((aligned(4)))
+#define OCFS_GCC_ATTR_PACKALGN	__attribute__ ((aligned(4), packed))
+#else
+#define OCFS_GCC_ATTR_PACKED
+#define OCFS_GCC_ATTR_ALIGNED
+#define OCFS_GCC_ATTR_PACKALGN
+#endif
+
+typedef struct _ocfs_alloc_bm
+{
+	void *buf;
+	__u32 size;
+	__u32 failed;
+	__u32 ok_retries;
+}
+ocfs_alloc_bm;
+
+typedef struct _ocfs_sem
+{
+	long magic;		/* OCFS_SEM_MAGIC */
+	pid_t pid;
+	long count;
+	struct semaphore sem;
+}
+ocfs_sem;
+
+/* convenience macro */
+#define ocfs_safefree(x)	\
+do {				\
+	if (x)			\
+		ocfs_free(x);	\
+	(x) = NULL;		\
+} while (0)
+
+#define ocfs_safevfree(x)	\
+do {				\
+	if (x)			\
+		vfree(x);	\
+	(x) = NULL;		\
+} while (0)
+
+#define OCFS_ASSERT(x)             do { if (!(x)) BUG(); } while (0)
+#define OCFS_BREAKPOINT()          printk("DEBUG BREAKPOINT! %s, %d\n", \
+                                          __FILE__, __LINE__)
+
+/* time is in 0.1 microsecs */
+#ifdef USERSPACE_TOOL
+
+#define OcfsQuerySystemTime(t)                                          \
+                          do {                                          \
+				  (*t) = (time(NULL)); 			\
+                          } while (0)
+#else
+#define OcfsQuerySystemTime(t)                                                \
+                          do {                                                \
+                            (*t)  = (__u64)((__u64)CURRENT_TIME * (__u64)10000000); \
+                            (*t) += (__u64)((__u64)xtime.tv_usec * (__u64)10);      \
+                          } while (0)
+#endif
+
+#ifdef __KERNEL__
+#define ocfs_getpid()               current->pid
+#endif
+#ifndef __KERNEL__
+#define ocfs_getpid()               getpid()
+#endif
+
+typedef struct _ocfs_extent
+{
+	__s64 virtual;
+	__s64 physical;
+	__s64 sectors;
+}
+ocfs_extent;
+
+typedef struct _ocfs_extent_map
+{
+	spinlock_t lock;
+	__u32 capacity;
+	__u32 count;
+	bool initialized;
+	void *buf;
+}
+ocfs_extent_map;
+
+typedef struct _alloc_item
+{
+        enum { SLAB_ITEM, KMALLOC_ITEM, VMALLOC_ITEM } type;
+	void *address;
+        union {
+        	int length;
+                void *slab;
+        } u;
+	struct list_head list;
+	char tag[30];
+}
+alloc_item;
+
+/* i_flags flag - heh yeah i know it's evil! */
+#define S_OCFS_OIN_VALID          256
+
+#define inode_data_is_oin(i)      (i->i_flags & S_OCFS_OIN_VALID)
+
+#define SET_INODE_OFFSET(i,o)     do { \
+                                      i->i_flags     &= ~S_OCFS_OIN_VALID; \
+                                      i->u.generic_ip = (void *)HI(o); \
+                                      i->i_ino        = LO(o); \
+                                  } while (0)
+
+#define GET_INODE_OFFSET(i)       (__u64)((((__u64)((unsigned long)i->u.generic_ip))<<32) + \
+                                        ((__u64)i->i_ino))
+
+#define SET_INODE_OIN(i,o)        do { \
+                                      i->i_flags     |= S_OCFS_OIN_VALID; \
+                                      i->u.generic_ip = (void *)o; \
+                                  } while (0)
+
+#define FIRST_FILE_ENTRY(dir)   ((char *) ((char *)dir)+OCFS_SECTOR_SIZE)
+#define FILEENT(dir,idx)        (ocfs_file_entry *) ( ((char *)dir) + \
+                                ((dir->index[idx]+1) * OCFS_SECTOR_SIZE))
+
+#define IS_FE_DELETED(_flg)				\
+	(!(_flg) ||					\
+	 ((_flg) & OCFS_SYNC_FLAG_MARK_FOR_DELETION) ||	\
+	 ((_flg) & OCFS_SYNC_FLAG_NAME_DELETED) ||	\
+	 ((_flg) & OCFS_SYNC_FLAG_DELETED))
+
+#endif				/*  _OCFSCOM_H_ */

Added: trunk/libocfs/Common/inc/ocfsconst.h
===================================================================
--- trunk/libocfs/Common/inc/ocfsconst.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/inc/ocfsconst.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,258 @@
+/*
+ * ocfsconst.h
+ *
+ * constants
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#define  OCFS_DIR_FILENAME                 "DirFile"
+#define  OCFS_DIR_BITMAP_FILENAME          "DirBitMapFile"
+#define  OCFS_FILE_EXTENT_FILENAME         "ExtentFile"
+#define  OCFS_FILE_EXTENT_BITMAP_FILENAME  "ExtentBitMapFile"
+#define  OCFS_RECOVER_LOG_FILENAME         "RecoverLogFile"
+#define  OCFS_CLEANUP_LOG_FILENAME         "CleanUpLogFile"
+
+#define  ONE_SECOND              (10 * 1000 * 1000)  /* 100 nanosec unit */
+#define  ONE_MILLI_SEC           (10 * 1000)         /* 100 nanosec unit */
+#define  ONE_MEGA_BYTE           (1 * 1024 * 1024)   /* in bytes */
+
+#define  MISS_COUNT_VALUE        20
+
+#define  OCFS_DEFAULT_DIR_NODE_SIZE  (1024 * 128)
+#define  OCFS_DEFAULT_FILE_NODE_SIZE (512)
+
+#define  OCFS_PAGE_SIZE		4096
+
+#define  ULONGLONG_MAX		(~0ULL)
+
+/*
+** The following flag values reflect the operation to be performed
+**   by ocfs_create_modify_file
+*/
+#define  FLAG_FILE_CREATE         0x1
+#define  FLAG_FILE_EXTEND         0x2
+#define  FLAG_FILE_DELETE         0x4
+#define  FLAG_FILE_RENAME         0x8
+#define  FLAG_FILE_UPDATE         0x10
+#define  FLAG_FILE_CREATE_DIR     0x40
+#define  FLAG_FILE_UPDATE_OIN     0x80
+#define  FLAG_FILE_RELEASE_MASTER 0x100
+#define  FLAG_CHANGE_MASTER       0x400
+#define  FLAG_ADD_OIN_MAP         0x800
+#define  FLAG_DIR                 0x1000
+#define  FLAG_DEL_NAME            0x20000
+#define  FLAG_RESET_VALID         0x40000
+#define  FLAG_FILE_RELEASE_CACHE  0x400000
+#define  FLAG_FILE_CREATE_CDSL    0x800000
+#define  FLAG_FILE_DELETE_CDSL    0x1000000
+#define  FLAG_FILE_CHANGE_TO_CDSL 0x4000000
+#define  FLAG_FILE_TRUNCATE       0x8000000   // kch- consider removing this and ocfs_truncate_file
+#define  FLAG_FILE_ACQUIRE_LOCK   0x10000000
+#define  FLAG_FILE_RELEASE_LOCK   0x20000000
+
+enum {
+    OCFS_INVALID_SYSFILE = -1,
+    OCFS_VOL_MD_SYSFILE = 0,
+    OCFS_VOL_MD_LOG_SYSFILE,
+    OCFS_DIR_SYSFILE,
+    OCFS_DIR_BM_SYSFILE,
+    OCFS_FILE_EXTENT_SYSFILE,
+    OCFS_FILE_EXTENT_BM_SYSFILE,
+    OCFS_RECOVER_LOG_SYSFILE,
+    OCFS_CLEANUP_LOG_SYSFILE,
+#ifdef LOCAL_ALLOC
+    OCFS_VOL_BM_SYSFILE
+#endif
+};
+#define OCFS_FILE_VOL_META_DATA      (OCFS_VOL_MD_SYSFILE         * OCFS_MAXIMUM_NODES)
+#define OCFS_FILE_VOL_LOG_FILE       (OCFS_VOL_MD_LOG_SYSFILE     * OCFS_MAXIMUM_NODES)
+#define OCFS_FILE_DIR_ALLOC          (OCFS_DIR_SYSFILE            * OCFS_MAXIMUM_NODES)
+#define OCFS_FILE_DIR_ALLOC_BITMAP   (OCFS_DIR_BM_SYSFILE         * OCFS_MAXIMUM_NODES)
+#define OCFS_FILE_FILE_ALLOC         (OCFS_FILE_EXTENT_SYSFILE    * OCFS_MAXIMUM_NODES)
+#define OCFS_FILE_FILE_ALLOC_BITMAP  (OCFS_FILE_EXTENT_BM_SYSFILE * OCFS_MAXIMUM_NODES)
+#define LOG_FILE_BASE_ID             (OCFS_RECOVER_LOG_SYSFILE    * OCFS_MAXIMUM_NODES)
+#define CLEANUP_FILE_BASE_ID         (OCFS_CLEANUP_LOG_SYSFILE    * OCFS_MAXIMUM_NODES)
+#ifdef LOCAL_ALLOC
+#define OCFS_VOL_BITMAP_FILE         (OCFS_VOL_BM_SYSFILE         * OCFS_MAXIMUM_NODES)
+#endif
+
+
+#define  OCFS_LOG_SECTOR_SIZE        9
+#define  OCFS_SECTOR_SIZE            (1<<OCFS_LOG_SECTOR_SIZE)
+#define  OCFS_MOD_SECTOR_SIZE        (OCFS_SECTOR_SIZE - 1)
+#define  OCFS_MAXIMUM_NODES          32
+#define  OCFS_MAX_FILENAME_LENGTH    255
+
+#define  OCFS_VOLUME_LOCK_OFFSET     (OCFS_SECTOR_SIZE)
+/* change this to some other sector, change format TODO */
+#define  OCFS_BITMAP_LOCK_OFFSET     (OCFS_SECTOR_SIZE * 2)
+
+#define  HEARTBEAT_METHOD_DISK       (1)
+#define  HEARTBEAT_METHOD_IPC        (2)
+
+/*
+** Extents Defines
+*/
+#define  OCFS_EXTENT_DATA             1
+#define  OCFS_EXTENT_HEADER           2
+
+#define  OCFS_MAX_FILE_ENTRY_EXTENTS  3
+#define  OCFS_MAX_DATA_EXTENTS        18
+#define  NUM_SECTORS_IN_LEAF_NODE     1
+
+/*
+** Structure signatures 
+*/
+#define  OCFS_TYPE_OFILE            (0x02534643)
+#define  OCFS_TYPE_OIN            (0x03534643)
+#define  OCFS_TYPE_OSB            (0x05534643)
+#define  OCFS_TYPE_GLOBAL_DATA    (0x07534643)
+
+#define  CACHE_LOCK_SLOT_TIME          (ONE_SECOND * 10)
+
+#define  OCFS_DLM_NO_LOCK              (0x0)
+#define  OCFS_DLM_SHARED_LOCK          (0x1)
+#define  OCFS_DLM_EXCLUSIVE_LOCK       (0x2)
+#define  OCFS_DLM_ENABLE_CACHE_LOCK    (0x8)
+
+#define  OCFS_INVALID_NODE_NUM         UINT_MAX
+
+typedef enum _ocfs_rw_mode
+{
+	OCFS_READ,
+	OCFS_WRITE
+}
+ocfs_rw_mode;
+
+#define  FLAG_ALWAYS_UPDATE_OPEN       0x1
+#define  LOCK_STATE_INIT               0x2
+#define  LOCK_STATE_IN_VOTING          0x4
+
+#define  OCFS_OIN_IN_TEARDOWN                    (0x00000002)
+#define  OCFS_OIN_DIRECTORY                      (0x00000008)
+#define  OCFS_OIN_ROOT_DIRECTORY                 (0x00000010)
+#define  OCFS_OIN_CACHE_UPDATE                   (0x00000100)
+#define  OCFS_OIN_DELETE_ON_CLOSE                (0x00000200)
+#define  OCFS_OIN_NEEDS_DELETION                 (0x00000400)
+#define  OCFS_INITIALIZED_MAIN_RESOURCE          (0x00002000)
+#define  OCFS_INITIALIZED_PAGING_IO_RESOURCE     (0x00004000)
+#define  OCFS_OIN_INVALID                        (0x00008000)
+#define  OCFS_OIN_IN_USE                         (0x00020000)
+#define  OCFS_OIN_OPEN_FOR_DIRECTIO              (0x00100000)
+#define  OCFS_OIN_OPEN_FOR_WRITE                 (0x00200000)
+
+
+#define  OCFS_OSB_FLAGS_BEING_DISMOUNTED  (0x00000004)
+#define  OCFS_OSB_FLAGS_SHUTDOWN          (0x00000008)
+#define  OCFS_OSB_FLAGS_OSB_INITIALIZED   (0x00000020)
+
+#define  OCFS_FLAG_GLBL_CTXT_RESOURCE_INITIALIZED (0x00000001)
+#define  OCFS_FLAG_MEM_LISTS_INITIALIZED          (0x00000002)
+#define  OCFS_FLAG_SHUTDOWN_VOL_THREAD            (0x00000004)
+
+#define  DIR_NODE_FLAG_ROOT           0x1
+
+/*
+** Information on Publish sector of each node
+*/
+#define  DISK_HBEAT_COMM_ON           20	/* in the order of 5 secs */
+#define  DISK_HBEAT_NO_COMM           4		/* in the order of 1 sec */
+#define  DISK_HBEAT_INVALID           0		/* in the order of 100ms */
+
+/*
+** Information on Vote sector of each node
+*/
+#define  FLAG_VOTE_NODE               0x1
+#define  FLAG_VOTE_OIN_UPDATED        0x2
+#define  FLAG_VOTE_OIN_ALREADY_INUSE  0x4
+#define  FLAG_VOTE_UPDATE_RETRY       0x8
+#define  FLAG_VOTE_FILE_DEL           0x10
+
+/*
+** File Entry contains this information
+*/
+#define  OCFS_SYNC_FLAG_DELETED            (0)
+#define  OCFS_SYNC_FLAG_VALID              (0x1)
+#define  OCFS_SYNC_FLAG_CHANGE             (0x2)
+#define  OCFS_SYNC_FLAG_MARK_FOR_DELETION  (0x4)
+#define  OCFS_SYNC_FLAG_NAME_DELETED       (0x8)
+
+#define  OCFS_ATTRIB_DIRECTORY             (0x1)
+#define  OCFS_ATTRIB_FILE_CDSL             (0x8)
+#define  OCFS_ATTRIB_CHAR                  (0x10)
+#define  OCFS_ATTRIB_BLOCK                 (0x20)
+#define  OCFS_ATTRIB_REG                   (0x40)
+#define  OCFS_ATTRIB_FIFO                  (0x80)
+#define  OCFS_ATTRIB_SYMLINK               (0x100)
+#define  OCFS_ATTRIB_SOCKET                (0x200)
+
+#define  INVALID_DIR_NODE_INDEX              -1
+#define  INVALID_NODE_POINTER                -1
+#define  OCFS_DIR_NODE_SIGNATURE             "DIRNV20"
+#define  OCFS_FILE_ENTRY_SIGNATURE           "FIL"
+#define  OCFS_EXTENT_HEADER_SIGNATURE        "EXTHDR2"
+#define  OCFS_EXTENT_DATA_SIGNATURE          "EXTDAT1"
+
+#define  MAX_IP_ADDR_LEN	32
+
+#define  OCFS_IP_ADDR           "ip_address"
+#define  OCFS_IP_PORT           "ip_port"
+#define  OCFS_IP_MASK           "subnet_mask"
+#define  OCFS_COMM_TYPE         "type"
+
+#define OCFS_SEM_MAGIC         0xAFABFACE
+#define OCFS_SEM_DELETED       0x0D0D0D0D
+
+#define SHUTDOWN_SIGS   (sigmask(SIGKILL) | sigmask(SIGHUP) | \
+                         sigmask(SIGINT) | sigmask(SIGQUIT))
+
+#define EFAIL                      999
+
+#define OCFS_MAGIC                 0xa156f7eb
+#define OCFS_ROOT_INODE_NUMBER     2
+#define OCFS_LINUX_MAX_FILE_SIZE   9223372036854775807LL
+#define INITIAL_EXTENT_MAP_SIZE    10
+
+#define OCFS_VOLCFG_LOCK_ITERATE	10	/* in jiffies */
+#define OCFS_VOLCFG_LOCK_TIME		1000    /* in ms */
+#define OCFS_VOLCFG_HDR_SECTORS		2	/* in sectors */
+#define OCFS_VOLCFG_NEWCFG_SECTORS	4	/* in sectors */
+
+#define OCFS_PUBLISH_CLEAR		0
+#define OCFS_PUBLISH_SET		1
+
+#define OCFS_NM_HEARTBEAT_TIME		500	/* in ms */
+#define OCFS_HEARTBEAT_INIT             10      /* number of NM iterations to stabilize the publish map */
+
+#ifndef O_DIRECT
+#define O_DIRECT        040000
+#endif
+
+#define NOT_MOUNTED_EXCLUSIVE   (-1)
+
+/* Four functions where dlm locks are taken */
+#define OCFS_UPDATE_LOCK_STATE		1
+#define OCFS_MAKE_LOCK_MASTER		2
+#define OCFS_DISK_RELEASE_LOCK		3
+#define OCFS_BREAK_CACHE_LOCK		4
+
+#define IORUN_ALLOC_SIZE    (OCFS_MAX_DATA_EXTENTS * sizeof (ocfs_io_runs))

Added: trunk/libocfs/Common/inc/ocfsdef.h
===================================================================
--- trunk/libocfs/Common/inc/ocfsdef.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/inc/ocfsdef.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,508 @@
+/*
+ * ocfsdef.h
+ *
+ * Defines in-memory structures
+ *
+ * Copyright (C) 2002, 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef  _OCFSDEF_H_
+#define  _OCFSDEF_H_
+
+#define  OIN_NEEDS_VERIFICATION(a)	((a)->needs_verification)
+#define  OIN_UPDATED(a)			((a)->needs_verification = false)
+
+#define  IS_VALID_DIR_NODE(ptr)                                       \
+                 (!strncmp((ptr)->signature, OCFS_DIR_NODE_SIGNATURE, \
+                           strlen(OCFS_DIR_NODE_SIGNATURE)))
+
+/* sm - ocfs 1.0 fails to set fe->sig for dirs */
+#define  IS_VALID_FILE_ENTRY(ptr)     \
+		(((ptr)->attribs & OCFS_ATTRIB_DIRECTORY) ||	\
+		 (!strcmp((ptr)->signature, OCFS_FILE_ENTRY_SIGNATURE)))
+
+#define  IS_VALID_EXTENT_HEADER(ptr)  \
+                (!strcmp((ptr)->signature, OCFS_EXTENT_HEADER_SIGNATURE))
+
+#define  IS_VALID_EXTENT_DATA(ptr)    \
+                (!strcmp((ptr)->signature, OCFS_EXTENT_DATA_SIGNATURE))
+
+#define  IS_VALID_NODE_NUM(node)      \
+                (((node) >= 0) && ((node) < OCFS_MAXIMUM_NODES))
+
+#define  IS_VALID_OIN(_oin)	((_oin)->obj_id.type == OCFS_TYPE_OIN)
+
+#define  IS_VALID_OSB(_osb)	((_osb)->obj_id.type == OCFS_TYPE_OSB)
+
+#define  OCFS_GET_EXTENT(vbo, extent, k)                            \
+              do {                                                  \
+                for ((k) = 0; (k) < OCFS_MAX_DATA_EXTENTS; (k)++) { \
+                  if((__s64)((extent)->extents[(k)].file_off +        \
+                     (extent)->extents[(k)].num_bytes) > (vbo))     \
+                    break;                                          \
+                }                                                   \
+              }  while(0)
+
+#define  OCFS_GET_FILE_ENTRY_EXTENT(vbo, fileentry, k)                    \
+              do {                                                        \
+                for ((k) = 0; (k) < OCFS_MAX_FILE_ENTRY_EXTENTS; (k)++) { \
+                  if((__s64)((fileentry)->extents[(k)].file_off +           \
+                     (fileentry)->extents[(k)].length) > (vbo))           \
+                    break;                                                \
+                }                                                         \
+              } while(0)
+
+#define  CHECK_FOR_LAST_EXTENT(fileentry, k)                              \
+              do {                                                        \
+                for((k) = 0; (k) < OCFS_MAX_FILE_ENTRY_EXTENTS; (k)++) {  \
+                  if((fileentry)->extents[(k)].disk_off == 0)             \
+                    break;                                                \
+                }                                                         \
+                (k) = ((k) >= 1) ? ((k) - 1) : (k);                       \
+              } while(0)
+
+#ifdef LOCAL_ALLOC
+#define OCFS_FILE_NUM_TO_SYSFILE_TYPE(num)   ( (num >= 0 && num < OCFS_VOL_BITMAP_FILE + OCFS_MAXIMUM_NODES) ? \
+                                               num/OCFS_MAXIMUM_NODES : OCFS_INVALID_SYSFILE )
+#define OCFS_SYSFILE_TYPE_TO_FILE_NUM(type,node)   ( (type > OCFS_INVALID_SYSFILE && type <= OCFS_VOL_BM_SYSFILE && \
+                                                      node >=0 && node < OCFS_MAXIMUM_NODES) ? \
+                                                     (type * OCFS_MAXIMUM_NODES) + node : -1 )
+#else
+#define OCFS_FILE_NUM_TO_SYSFILE_TYPE(num)   ( (num >= 0 && num < CLEANUP_FILE_BASE_ID + OCFS_MAXIMUM_NODES) ? \
+                                               num/OCFS_MAXIMUM_NODES : OCFS_INVALID_SYSFILE )
+#define OCFS_SYSFILE_TYPE_TO_FILE_NUM(type,node)   ( (type > OCFS_INVALID_SYSFILE && type <= CLEANUP_FILE_BASE_ID && \
+                                                      node >=0 && node < OCFS_MAXIMUM_NODES) ? \
+                                                     (type * OCFS_MAXIMUM_NODES) + node : -1 )
+#endif
+
+#define down_with_flag(_sem, _flg)	\
+	do {				\
+		if (!_flg) {		\
+			down (_sem);	\
+			_flg = true;	\
+		}			\
+	} while (0)
+
+#define up_with_flag(_sem, _flg)	\
+	do {				\
+		if (_flg) {		\
+			up (_sem);	\
+			_flg = false;	\
+		}			\
+	} while (0)
+
+#ifdef USERSPACE_TOOL
+#define ocfs_task_interruptible(_o)     (true)
+#else
+#define ocfs_task_interruptible(_o)	((_o)->dlm_task != current && signal_pending(current))
+#endif
+
+#define ocfs_trans_in_progress(_o)			\
+do {							\
+	int _i = 0;					\
+	while (((_o)->trans_in_progress) && (_i < 10)) {\
+		ocfs_sleep (100);			\
+		_i++;					\
+	}						\
+} while (0)
+
+struct _ocfs_file;
+struct _ocfs_inode;
+struct _ocfs_super;
+
+/*
+** Macros
+*/
+#define  OCFS_SET_FLAG(flag, value)    ((flag) |= (value))
+#define  OCFS_CLEAR_FLAG(flag, value)  ((flag) &= ~(value))
+
+#define  OCFS_SECTOR_ALIGN(buf)                     \
+               ((__u64)buf +                          \
+                (((__u64)buf % OCFS_SECTOR_SIZE) ?    \
+                 (OCFS_SECTOR_SIZE - ((__u64)buf % OCFS_SECTOR_SIZE)):0))
+
+#define  OCFS_ALIGN(val, align)        \
+               ((__u64)val  +            \
+                (((__u64)val % align) ? (align - ((__u64)val % align)): 0))
+
+/*
+** Structures...
+*/
+
+#define  IS_NODE_ALIVE(pubmap, i, numnodes)  \
+                                  (((pubmap) >> ((i) % (numnodes))) & 0x1)
+
+#define  IS_VALIDBIT_SET(flags)   ((flags) & 0x1)
+
+#define  SET_VALID_BIT(flags)     ((flags) |= 0x1)
+
+/*
+**  All structures have a type, and a size associated with it.
+**  The type serves to identify the structure. The size is used for
+**  consistency checking ...
+*/
+#define  UPDATE_PUBLISH_MAP(pubmap, num, flag, numnodes)          \
+                do {                                              \
+                  __u64 var = 0x1;                                  \
+                  if((flag) == OCFS_PUBLISH_CLEAR)                \
+                    (pubmap) &= (~(var << ((num) % (numnodes)))); \
+                  else                                            \
+                    (pubmap) |= (var << ((num) % (numnodes)));    \
+                } while(0)
+
+typedef struct _ocfs_obj_id
+{
+	__u32 type;		/* 4 byte signature to uniquely identify the struct */
+	__u32 size;		/* sizeof the struct */
+}
+ocfs_obj_id;
+
+typedef struct _ocfs_filldir
+{
+       __u8 fname[OCFS_MAX_FILENAME_LENGTH];
+       loff_t pos;
+       __u32 ino;
+} ocfs_filldir;
+
+
+/**************************************************************************
+**  Each file open instance is represented by a context control block.
+**  For each successful create/open request; a file object and a ocfs_file will
+**  be created.
+**  For open operations performed internally by the FSD, there may not
+**  exist file objects; but a ocfs_file will definitely be created.
+**  This structure must be quad-word aligned because it is zone allocated.
+**************************************************************************/
+typedef struct _ocfs_file
+{
+	ocfs_obj_id obj_id;
+	struct _ocfs_inode *oin;	/* ptr to the assoc. ocfs_inode */
+	struct list_head next_ofile;	/* all OFILEs for a ocfs_inode are linked */
+	struct file *k_file;
+	__u64 curr_byte_off;
+	__s64 curr_dir_off;
+	void *curr_dir_buf;
+	ocfs_filldir filldir;
+}
+ocfs_file;
+
+typedef struct _ocfs_inode ocfs_inode;
+typedef struct _ocfs_super ocfs_super;
+typedef struct _ocfs_superduper ocfs_superduper;
+typedef struct _ocfs_io_runs ocfs_io_runs;
+
+typedef struct _ocfs_lock_res
+{
+	__u32 signature;
+	__u8 lock_type;		/* Support only Exclusive & Shared */
+	atomic_t lr_share_cnt;	/* Used in case of Shared resources */
+	atomic_t lr_ref_cnt;	/* When 0, freed */
+	__u32 master_node_num;	/* Master Node */
+	__u64 last_upd_seq_num;
+	__u64 last_lock_upd;
+	__u64 sector_num;
+	__u64 oin_openmap;
+	__u64 tmp_openmap;	/* oin_openmap collected over the comm */
+	__u8 in_use;
+	int thread_id;
+	struct list_head cache_list;
+	bool in_cache_list;
+	__u32 lock_state;
+	__u32 vote_state;		/* Is the lockres being voted on over ipcdlm */
+	ocfs_inode *oin;
+	spinlock_t lock_mutex;
+	wait_queue_head_t voted_event;
+	atomic_t voted_event_woken;
+	__u64 req_vote_map;
+	__u64 got_vote_map;
+	__u32 vote_status;
+	__u64 last_write_time;
+	__u64 last_read_time;
+	__u32 writer_node_num;
+	__u32 reader_node_num;
+}
+ocfs_lock_res;
+
+struct _ocfs_inode
+{
+	ocfs_obj_id obj_id;
+	__s64 alloc_size;
+	struct inode *inode;
+	ocfs_sem main_res;
+	ocfs_sem paging_io_res;
+	ocfs_lock_res *lock_res;
+	__u64 file_disk_off;	/* file location on the volume */
+	__u64 dir_disk_off;	/* for dirs, offset to dirnode structure */
+	__u64 chng_seq_num;
+	__u64 parent_dirnode_off;	/* from the start of vol */
+	ocfs_extent_map map;
+	struct _ocfs_super *osb;	/* ocfs_inode belongs to this volume */
+	__u32 oin_flags;
+	struct list_head next_ofile;	/* list of all ofile(s) */
+	__u32 open_hndl_cnt;
+	bool needs_verification;
+	bool cache_enabled;
+};
+
+typedef enum _ocfs_vol_state
+{
+	VOLUME_DISABLED,
+	VOLUME_INIT,
+	VOLUME_ENABLED,
+	VOLUME_LOCKED,
+	VOLUME_IN_RECOVERY,
+	VOLUME_MOUNTED,
+	VOLUME_BEING_DISMOUNTED,
+	VOLUME_DISMOUNTED
+}
+ocfs_vol_state;
+
+typedef struct _ocfs_node_config_info
+{
+	char node_name[MAX_NODE_NAME_LENGTH];
+	ocfs_guid guid;
+	ocfs_ipc_config_info ipc_config;
+}
+ocfs_node_config_info;
+
+typedef struct _ocfs_dlm_stats
+{
+	atomic_t total;
+	atomic_t okay;
+	atomic_t etimedout;
+	atomic_t efail;
+	atomic_t eagain;
+	atomic_t enoent;
+	atomic_t def;
+}
+ocfs_dlm_stats;
+
+typedef struct _ocfs_lock_type_stats
+{
+	atomic_t update_lock_state;
+	atomic_t make_lock_master;
+	atomic_t disk_release_lock;
+	atomic_t break_cache_lock;
+	atomic_t others;
+}
+ocfs_lock_type_stats;
+
+/*
+ * ocfs_super
+ *
+ * A mounted volume is represented using the following structure.
+ */
+struct _ocfs_super
+{
+	ocfs_obj_id obj_id;
+	ocfs_sem osb_res;	/* resource to protect the ocfs_super */
+	struct list_head osb_next;	/* list of ocfs_super(s) */
+	__u32 osb_id;		/* id used by the proc interface */
+	struct completion complete;
+	struct task_struct *dlm_task;
+	__u32 osb_flags;
+	bool blk_zero_write;	/* true when blk 0 is written on first mount */
+	__s64 file_open_cnt;	/* num of open files/dirs. vol cannot be dismounted if > 0 */
+	__u64 publ_map;		/* each bit represents state of node */
+	HASHTABLE root_sect_node;	/* lockres->sector_num hash */
+	struct list_head cache_lock_list;
+	struct super_block *sb;
+	ocfs_inode *oin_root_dir;	/* ptr to the root dir ocfs_inode */
+	ocfs_vol_layout vol_layout;
+	ocfs_vol_node_map vol_node_map;
+	struct semaphore cfg_lock;
+	ocfs_node_config_info *node_cfg_info[OCFS_MAXIMUM_NODES];
+	__u64 cfg_seq_num;
+	bool cfg_initialized;
+	__u32 num_cfg_nodes;
+	__u32 node_num;
+	bool reclaim_id;                /* reclaim the original node number*/
+	__u8 hbm;
+	unsigned long hbt;
+	__u64 log_disk_off;
+	__u64 log_meta_disk_off;
+	__u64 log_file_size;
+	__u32 sect_size;
+	bool needs_flush;
+	bool commit_cache_exec;
+	ocfs_sem map_lock;
+	ocfs_extent_map metadata_map;
+	ocfs_extent_map trans_map;
+	ocfs_alloc_bm cluster_bitmap;
+	__u32 max_dir_node_ent;
+	ocfs_vol_state vol_state;
+	__s64 curr_trans_id;
+	bool trans_in_progress;
+	ocfs_sem log_lock;
+	ocfs_sem recovery_lock;
+	__u32 node_recovering;
+#ifdef PARANOID_LOCKS
+	ocfs_sem dir_alloc_lock;
+	ocfs_sem file_alloc_lock;
+#endif
+	ocfs_sem vol_alloc_lock;
+	struct timer_list lock_timer;
+	atomic_t lock_stop;
+	wait_queue_head_t lock_event;
+	atomic_t lock_event_woken;
+	struct semaphore comm_lock;	/* protects ocfs_comm_process_vote_reply */
+	atomic_t nm_init;
+	wait_queue_head_t nm_init_event;
+	bool cache_fs;
+	__u32 prealloc_lock;
+	ocfs_io_runs *data_prealloc;
+	ocfs_io_runs *md_prealloc;
+	__u8 *cfg_prealloc;
+	__u32 cfg_len;
+	__u8 *log_prealloc;
+	struct semaphore publish_lock;  /* protects r/w to publish sector */
+	atomic_t node_req_vote;		/* set when node's vote req pending */
+	struct semaphore trans_lock;	/* serializes transactions */
+	ocfs_dlm_stats net_reqst_stats;	/* stats of netdlm vote requests */
+	ocfs_dlm_stats net_reply_stats;	/* stats of netdlm vote reponses */
+	ocfs_dlm_stats dsk_reqst_stats;	/* stats of diskdlm vote requests */
+	ocfs_dlm_stats dsk_reply_stats;	/* stats of diskdlm vote reponses */
+	ocfs_lock_type_stats lock_type_stats;	/* stats of lock types taken */
+	__u64 last_disk_seq;		/* last vote seq voted on on disk */
+	char dev_str[20];		/* "major,minor" of the device */
+};
+
+enum {
+    OSB_DATA_LOCK,
+    OSB_MD_LOCK,
+    OSB_CFG_LOCK,
+    OSB_LOG_LOCK
+};
+
+#define OSB_PREALLOC_LOCK_TEST(osb, l)   (osb->prealloc_lock & (1<<l))
+#define OSB_PREALLOC_LOCK_SET(osb, l)    (osb->prealloc_lock |= (1<<l))
+#define OSB_PREALLOC_LOCK_CLEAR(osb, l)  (osb->prealloc_lock &= ~(1<<l))
+
+
+typedef struct _ocfs_comm_info
+{
+	__u32 type;
+	char *ip_addr;
+	__u32 ip_port;
+	char *ip_mask;
+}
+ocfs_comm_info;
+
+typedef struct _ocfs_global_ctxt
+{
+	ocfs_obj_id obj_id;
+	ocfs_sem res;
+	struct list_head osb_next;	/* List of all volumes */
+	kmem_cache_t *oin_cache;
+	kmem_cache_t *ofile_cache;
+	kmem_cache_t *fe_cache;
+	kmem_cache_t *lockres_cache;
+	kmem_cache_t *dirnode_cache;
+	__u32 flags;
+	__u32 pref_node_num;		/* preferred... osb has the real one */
+	ocfs_guid guid;			/* uniquely identifies a node */
+	char *node_name;		/* human readable node identification */
+	char *cluster_name;		/* unused */
+	ocfs_comm_info comm_info;	/* ip address, etc for listener */
+	bool comm_info_read;		/* ipc info loaded from config file */
+	wait_queue_head_t flush_event;	/* unused */
+	__u8 hbm;
+	spinlock_t comm_seq_lock;	/* protects comm_seq_num */
+	__u64 comm_seq_num;		/* local node seq num used in ipcdlm */
+#ifdef OCFS_LINUX_MEM_DEBUG
+        struct list_head item_list;
+#endif
+	atomic_t cnt_lockres;		/* count of allocated lockres */
+	ocfs_dlm_stats net_reqst_stats;	/* stats of netdlm vote requests */
+	ocfs_dlm_stats net_reply_stats;	/* stats of netdlm vote reponses */
+	ocfs_dlm_stats dsk_reqst_stats;	/* stats of diskdlm vote requests */
+	ocfs_dlm_stats dsk_reply_stats;	/* stats of diskdlm vote reponses */
+}
+ocfs_global_ctxt;
+
+struct _ocfs_io_runs
+{
+	__u64 disk_off;
+	__u32 offset;
+	__u32 byte_cnt;
+};
+
+#if defined(OCFS_LINUX_MEM_DEBUG)
+# define ocfs_malloc(_s)					\
+({								\
+	void *m = ocfs_linux_dbg_alloc(_s, __FILE__, __LINE__);	\
+	if (debug_level & OCFS_DEBUG_LEVEL_MALLOC)		\
+		printk("malloc(%s,%d) = %p\n", __FILE__,	\
+		       __LINE__, m);				\
+	m;							\
+})
+
+# define ocfs_free(x)\
+do {								\
+	if (debug_level & OCFS_DEBUG_LEVEL_MALLOC)		\
+		printk("free(%s,%d) = %p\n", __FILE__,	\
+		       __LINE__, x);				\
+	ocfs_linux_dbg_free(x);					\
+} while (0)
+
+#elif !defined(OCFS_LINUX_MEM_DEBUG)
+# define ocfs_malloc(Size)     kmalloc((size_t)(Size), GFP_KERNEL)
+# define ocfs_free             kfree
+#endif				/* ! defined(OCFS_MEM_DBG) */
+
+
+typedef struct _ocfs_ipc_ctxt
+{
+	ocfs_sem ipc_ctxt_res;
+	__u32 dlm_msg_size;
+	__u16 version;
+	bool init;
+	bool re_init;
+	struct socket *send_sock;
+	struct socket *recv_sock;
+	struct completion complete;
+	struct task_struct *task;
+}
+ocfs_ipc_ctxt;
+
+typedef enum _ocfs_protocol
+{
+	OCFS_TCP = 1,
+	OCFS_UDP
+}
+ocfs_protocol;
+
+extern ocfs_ipc_ctxt OcfsIpcCtxt;
+
+typedef struct _ocfs_ipc_dlm_config
+{
+	__u16 version;
+	__u32 msg_size;
+	__u32 num_recv_threads;
+}
+ocfs_ipc_dlm_config;
+
+/*
+** Globals ...
+*/
+extern ocfs_global_ctxt OcfsGlobalCtxt;
+
+#endif				/* _OCFSDEF_H_ */

Added: trunk/libocfs/Common/inc/ocfsdisk.h
===================================================================
--- trunk/libocfs/Common/inc/ocfsdisk.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/inc/ocfsdisk.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,237 @@
+/*
+ * ocfsdisk.h
+ *
+ * Defines disk-based structures
+ *
+ * Copyright (C) 2002, 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef  _OCFSDISK_H_
+#define  _OCFSDISK_H_
+
+typedef struct _ocfs_alloc_ext		// CLASS
+{
+	/* Starting offset within the file */
+	__u64 file_off;			// DISKPTR
+	/* Number of bytes used by this alloc */
+	__u64 num_bytes;		// NUMBER RANGE(0,ULONG_LONG_MAX)
+	/* Physical Disk Offset */
+	__u64 disk_off;			// DISKPTR
+}
+ocfs_alloc_ext;				// END CLASS
+
+typedef struct _ocfs_publish		// CLASS
+{
+	__u64 time;			// NUMBER RANGE(0,ULONG_LONG_MAX)
+	__s32 vote;			// BOOL
+	bool dirty;			// BOOL
+	__u32 vote_type;		// FILEFLAG
+	__u64 vote_map;			// NODEBITMAP
+	__u64 publ_seq_num;		// NUMBER RANGE(0,ULONG_LONG_MAX)
+	__u64 dir_ent;			// NUMBER RANGE(0,ULONG_LONG_MAX)
+	__u8 hbm[OCFS_MAXIMUM_NODES];	// UNUSED
+	/* last seq num used in comm voting */
+	__u64 comm_seq_num;		// NUMBER RANGE(0,ULONG_LONG_MAX)
+}
+OCFS_GCC_ATTR_PACKALGN
+ocfs_publish;				// END CLASS
+
+typedef struct _ocfs_vote		// CLASS
+{
+	__u8 vote[OCFS_MAXIMUM_NODES];	// VOTEFLAG[OCFS_MAXIMUM_NODES]
+	__u64 vote_seq_num;		// NUMBER RANGE(0,ULONG_LONG_MAX)
+	__u64 dir_ent;			// NUMBER RANGE(0,ULONG_LONG_MAX)
+	__u8 open_handle;		// BOOL
+}
+OCFS_GCC_ATTR_PACKALGN
+ocfs_vote;				// END CLASS
+
+typedef struct _ocfs_file_entry		// CLASS
+{
+	ocfs_disk_lock disk_lock;	// DISKLOCK
+	__u8 signature[8];		// CHAR[8]
+	bool local_ext;			// BOOL
+	__u8 next_free_ext;		// NUMBER RANGE(0,OCFS_MAX_FILE_ENTRY_EXTENTS)
+	__s8 next_del;			// DIRNODEINDEX
+	__s32 granularity;		// NUMBER RANGE(-1,3)
+	__u8 filename[OCFS_MAX_FILENAME_LENGTH];	// CHAR[OCFS_MAX_FILENAME_LENGTH]
+	__u16 filename_len;		// NUMBER RANGE(0,OCFS_MAX_FILENAME_LENGTH)
+	__u64 file_size;		// NUMBER RANGE(0,ULONG_LONG_MAX)
+	__u64 alloc_size;		// NUMBER RANGE(0,ULONG_LONG_MAX)
+	__u64 create_time;		// DATE
+	__u64 modify_time;		// DATE
+	ocfs_alloc_ext extents[OCFS_MAX_FILE_ENTRY_EXTENTS];	// EXTENT[OCFS_MAX_FILE_ENTRY_EXTENTS]
+	__u64 dir_node_ptr;		// NUMBER RANGE(0,ULONG_LONG_MAX)
+	__u64 this_sector;		// NUMBER RANGE(0,ULONG_LONG_MAX)
+	__u64 last_ext_ptr;		// NUMBER RANGE(0,ULONG_LONG_MAX)
+	__u32 sync_flags;		// SYNCFLAG
+	__u32 link_cnt;			// NUMBER RANGE(0,UINT_MAX)
+	__u32 attribs;			// ATTRIBS
+	__u32 prot_bits;		// PERMS
+	__u32 uid;			// UID
+	__u32 gid;			// GID
+	__u16 dev_major;		// NUMBER RANGE(0,65535)   
+	__u16 dev_minor;		// NUMBER RANGE(0,65535)
+	/* 32-bit: sizeof(fe) = 484 bytes */
+	/* 64-bit: sizeof(fe) = 488 bytes */
+	/* Need to account for that fact when the struct is extended. */
+}
+ocfs_file_entry;			// END CLASS
+
+/* not sizeof-safe across platforms */
+typedef struct _ocfs_index_node
+{
+	__u64 down_ptr;
+	__u64 file_ent_ptr;
+	__u8 name_len;
+	__u8 name[1];
+}
+OCFS_GCC_ATTR_PACKALGN
+ocfs_index_node;
+
+typedef struct _ocfs_index_hdr
+{
+	ocfs_disk_lock disk_lock;
+	__u64 signature;
+	__s64 up_tree_ptr;	/* Pointer to parent of this dnode */
+	__u64 node_disk_off;
+	__u8 state;		/* In recovery, needs recovery etc */
+	__u64 down_ptr	OCFS_GCC_ATTR_ALIGNED;
+	__u8 num_ents;;		/* Number of extents in this Node */
+	__u8 depth;		/* Depth of this Node from root of the btree */
+	__u8 num_ent_used;	/* Num of entries in the dir blk used up. */
+	__u8 dir_node_flags;	/* Flags */
+	__u8 sync_flags;		/* Flags */
+	__u8 index[256];
+	__u8 reserved[161];
+	__u8 file_ent[1];	/* 63 entries here with 32K DIR_NODE size */
+}
+OCFS_GCC_ATTR_PACKED
+ocfs_index_hdr;
+
+/* not sizeof-safe across platforms */
+typedef struct _ocfs_dir_node		// CLASS
+{
+	ocfs_disk_lock disk_lock;	// DISKLOCK
+	__u8 signature[8];		// CHAR[8]
+	__u64 alloc_file_off;		// NUMBER RANGE(0,ULONG_LONG_MAX) 
+	__u32 alloc_node;		// NUMBER RANGE(0,31)
+	__u64 free_node_ptr;		// DISKPTR
+	__u64 node_disk_off;		// DISKPTR
+	__s64 next_node_ptr;		// DISKPTR 
+	__s64 indx_node_ptr;		// DISKPTR
+	__s64 next_del_ent_node;	// DISKPTR
+	__s64 head_del_ent_node;	// DISKPTR
+	__u8 first_del;			// DIRNODEINDEX
+	__u8 num_del;			// NUMBER RANGE(0,254)
+	__u8 num_ents;			// NUMBER RANGE(0,254)
+	__u8 depth;			// UNUSED
+	__u8 num_ent_used;		// NUMBER RANGE(0,254)
+	__u8 dir_node_flags;		// DIRFLAG
+	__u8 sync_flags;		// NUMBER RANGE(0,0)
+	__u8 index[256];		// DIRINDEX
+	__u8 index_dirty;		// NUMBER RANGE(0,1)
+	__u8 bad_off;			// NUMBER RANGE(0,254)
+	__u8 reserved[127];		// UNUSED
+	__u8 file_ent[1];		// UNUSED
+}
+OCFS_GCC_ATTR_PACKALGN
+ocfs_dir_node;				// END CLASS
+
+typedef struct _ocfs_vol_node_map
+{
+	__u64 time[OCFS_MAXIMUM_NODES];
+	__u64 scan_time[OCFS_MAXIMUM_NODES];
+	__u8 scan_rate[OCFS_MAXIMUM_NODES];
+#ifdef UNUSED
+	__u8 exp_scan_rate[OCFS_MAXIMUM_NODES];
+	__u64 exp_rate_chng_time[OCFS_MAXIMUM_NODES];
+#endif
+	__u32 miss_cnt[OCFS_MAXIMUM_NODES];
+	atomic_t dismount[OCFS_MAXIMUM_NODES];
+	__u64 largest_seq_num;
+}
+ocfs_vol_node_map;
+
+typedef struct _ocfs_vol_layout
+{
+	__u64 start_off;
+	__u32 num_nodes;
+	__u32 cluster_size;
+	__u8 mount_point[MAX_MOUNT_POINT_LEN];
+	__u8 vol_id[MAX_VOL_ID_LENGTH];
+	__u8 label[MAX_VOL_LABEL_LEN];
+	__u32 label_len;
+	__u64 size;
+	__u64 root_start_off;
+	__u64 serial_num;
+	__u64 root_size;
+	__u64 publ_sect_off;
+	__u64 vote_sect_off;
+	__u64 root_bitmap_off;
+	__u64 root_bitmap_size;
+	__u64 data_start_off;
+	__u64 num_clusters;
+	__u64 root_int_off;
+	__u64 dir_node_size;
+	__u64 file_node_size;
+	__u64 bitmap_off;
+	__u64 node_cfg_off;
+	__u64 node_cfg_size;
+	__u64 new_cfg_off;
+	__u32 prot_bits;
+	__u32 uid;
+	__u32 gid;
+}
+ocfs_vol_layout;
+
+typedef struct _ocfs_extent_group	// CLASS
+{
+	__u8 signature[8];		// CHAR ARRAY[8]
+	/* 0 when init, -1 when full */
+	__s32 next_free_ext;		// NUMBER RANGE(-1,INT_MAX)
+	/* Currently available sector for use */
+	__u32 curr_sect;		// NUMBER RANGE(0,UINT_MAX)
+	/* Maximum Number of Sectors */
+	__u32 max_sects;		// NUMBER RANGE(0,UINT_MAX)
+	/* Type of this sector... either */
+	/*  Actual Data or a Ptr to another location */
+	__u32 type;			// EXTENTTYPE
+	/* Number of leaf levels */
+	__s32 granularity;		// NUMBER RANGE(-1,INT_MAX)
+	__u32 alloc_node;		// NODENUM
+	__u64 this_ext;			// DISKPTR
+	__u64 next_data_ext;		// DISKPTR
+	__u64 alloc_file_off;		// DISKPTR
+	__u64 last_ext_ptr;		// DISKPTR
+	__u64 up_hdr_node_ptr;		// DISKPTR
+	ocfs_alloc_ext extents[OCFS_MAX_DATA_EXTENTS];	// EXTENT[OCFS_MAX_DATA_EXTENTS]
+}
+ocfs_extent_group;			// END CLASS
+
+typedef struct _ocfs_bitmap_lock
+{
+    ocfs_disk_lock disk_lock;
+    __u32 used_bits;
+}
+OCFS_GCC_ATTR_PACKALGN
+ocfs_bitmap_lock;
+#endif /*_OCFSDISK_H_ */

Added: trunk/libocfs/Common/inc/ocfsdlm.h
===================================================================
--- trunk/libocfs/Common/inc/ocfsdlm.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/inc/ocfsdlm.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,144 @@
+/*
+ * ocfsdlm.h
+ *
+ * ipcdlm related structures
+ *
+ * Copyright (C) 2002, 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef  _OCFSDLM_H_
+#define  _OCFSDLM_H_
+
+#define  OCFS_MAX_DLM_PKT_SIZE			256
+#define  OCFS_DLM_MAX_MSG_SIZE			256
+
+#define  OCFS_DLM_MSG_MAGIC			0x79677083
+
+typedef struct _ocfs_dlm_msg_hdr
+{
+	__u64 lock_id;
+	__u32 flags;
+	__u64 lock_seq_num;
+	__u8 open_handle;
+}
+OCFS_GCC_ATTR_PACKALGN
+ocfs_dlm_msg_hdr;
+
+typedef ocfs_dlm_msg_hdr ocfs_dlm_req_master;
+typedef ocfs_dlm_msg_hdr ocfs_dlm_disk_vote_req;
+
+typedef struct _ocfs_dlm_reply_master
+{
+	ocfs_dlm_msg_hdr h;
+	__u32 status;
+}
+ocfs_dlm_reply_master;
+
+typedef struct _ocfs_dlm_disk_vote_reply
+{
+	ocfs_dlm_msg_hdr h;
+	__u32 status;
+}
+ocfs_dlm_disk_vote_reply;
+
+typedef struct _ocfs_dlm_msg
+{
+	__u32 magic;
+	__u32 msg_len;
+	__u8 vol_id[MAX_VOL_ID_LENGTH];
+	__u32 src_node;
+	__u32 dst_node;
+	__u32 msg_type;
+	__u32 check_sum;
+	__u8 msg_buf[1];
+}
+ocfs_dlm_msg;
+
+typedef struct _ocfs_recv_ctxt
+{
+	__s32 msg_len;
+	__u8 msg[OCFS_MAX_DLM_PKT_SIZE];
+	int status;
+	struct tq_struct ipc_tq;
+}
+ocfs_recv_ctxt;
+
+enum
+{
+	OCFS_VOTE_REQUEST = 1,
+	OCFS_VOTE_REPLY,
+	OCFS_INFO_DISMOUNT
+};
+
+#define ocfs_compute_dlm_stats(__status, __vote_status, __stats)	\
+do {									\
+	atomic_inc (&((__stats)->total));				\
+	if (__status == -ETIMEDOUT)					\
+		atomic_inc (&((__stats)->etimedout));			\
+	else {								\
+		switch (__vote_status) {				\
+		case -EAGAIN:						\
+		case FLAG_VOTE_UPDATE_RETRY:				\
+			atomic_inc (&((__stats)->eagain));		\
+			break;						\
+		case -ENOENT:						\
+		case FLAG_VOTE_FILE_DEL:				\
+			atomic_inc (&((__stats)->enoent));		\
+			break;						\
+		case -EBUSY:						\
+		case -EFAIL:						\
+		case FLAG_VOTE_OIN_ALREADY_INUSE:			\
+			atomic_inc (&((__stats)->efail));		\
+			break;						\
+		case 0:							\
+		case FLAG_VOTE_NODE:					\
+		case FLAG_VOTE_OIN_UPDATED:				\
+			atomic_inc (&((__stats)->okay));		\
+			break;						\
+		default:						\
+			atomic_inc (&((__stats)->def));			\
+			break;						\
+		}							\
+	}								\
+} while (0)
+
+#define ocfs_compute_lock_type_stats(__stats, __type)			\
+do {\
+	switch (__type) {\
+	case OCFS_UPDATE_LOCK_STATE:\
+		atomic_inc (&((__stats)->update_lock_state));\
+		break;\
+	case OCFS_MAKE_LOCK_MASTER:\
+		atomic_inc (&((__stats)->make_lock_master));\
+		break;\
+	case OCFS_DISK_RELEASE_LOCK:\
+		atomic_inc (&((__stats)->disk_release_lock));\
+		break;\
+	case OCFS_BREAK_CACHE_LOCK:\
+		atomic_inc (&((__stats)->break_cache_lock));\
+		break;\
+	default:\
+		atomic_inc (&((__stats)->others));\
+		break;\
+	}\
+} while (0)
+
+#endif				/* _OCFSDLM_H_ */

Added: trunk/libocfs/Common/inc/ocfserr.h
===================================================================
--- trunk/libocfs/Common/inc/ocfserr.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/inc/ocfserr.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,4 @@
+#ifndef _OCFSERR_H_
+#define _OCFSERR_H_
+
+#endif				/* _OCFSERR_H_ */

Added: trunk/libocfs/Common/inc/ocfsgenalloc.h
===================================================================
--- trunk/libocfs/Common/inc/ocfsgenalloc.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/inc/ocfsgenalloc.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,189 @@
+/*
+ * ocfsgenalloc.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSGENALLOC_H_
+#define _OCFSGENALLOC_H_
+
+enum {
+	EXTENT_HEADER,
+	EXTENT_DATA
+};
+
+#define OCFS_EXTENT_MERGEABLE(ext, off)	\
+			(((ext)->disk_off + (ext)->num_bytes) == (off))
+
+#define ocfs_read_extent(osb, ext, off, typ)				\
+({									\
+	int __status;							\
+	ocfs_extent_group *__ext;					\
+	__status = ocfs_read_disk(osb, (ext), (osb)->sect_size, off);	\
+	if (__status >= 0) {						\
+		__ext = (ocfs_extent_group *) (ext);			\
+		if ((typ) == EXTENT_HEADER) {				\
+			if (!IS_VALID_EXTENT_HEADER(__ext))		\
+				__status = -EFAIL;			\
+		}							\
+		if ((typ) == EXTENT_DATA) {				\
+			if (!IS_VALID_EXTENT_DATA(__ext))		\
+				__status = -EFAIL;			\
+		}							\
+	}								\
+	__status;							\
+})
+
+int _write_free_extent_log(ocfs_super *osb, ocfs_cleanup_record *CleanupLogRec,
+		   __u32 len, __u32 fileoff, __u32 nodenum, __u32 thistype);
+
+int ocfs_kill_this_tree(ocfs_super *osb, ocfs_extent_group *extent_grp,
+			ocfs_cleanup_record *CleanupLogRec);
+
+int ocfs_lookup_file_allocation (ocfs_super * osb,
+			  ocfs_inode * oin,
+			  __s64 Vbo,
+			  __s64 * Lbo,
+			  __u32 ByteCount, __u32 * NumIndex, void **Buffer);
+
+
+int ocfs_read_file_entry (ocfs_super * osb,
+		   ocfs_file_entry * FileEntry, __u64 DiskOffset);
+
+int ocfs_write_file_entry (ocfs_super * osb, ocfs_file_entry * FileEntry, __u64 Offset);
+
+void ocfs_remove_extent_map_entry (ocfs_super * osb,
+			  ocfs_extent_map * Map, __s64 Vbo, __u32 ByteCount);
+
+int ocfs_allocate_new_data_node (ocfs_super * osb,
+		     ocfs_file_entry * FileEntry,
+		     __u64 actualDiskOffset,
+		     __u64 actualLength,
+		     ocfs_extent_group * ExtentHeader, __u64 * NewExtentOffset);
+
+int ocfs_add_to_last_data_node (ocfs_super * osb,
+		   ocfs_inode * oin,
+		   ocfs_file_entry * FileEntry,
+		   __u64 actualDiskOffset,
+		   __u64 actualLength, __u32 * ExtentIndex, bool * IncreaseDepth);
+
+int ocfs_update_last_data_extent (ocfs_super * osb,
+		      ocfs_file_entry * FileEntry, __u64 NextDataOffset);
+
+int ocfs_update_uphdrptr(ocfs_super *osb, ocfs_file_entry *fe,
+			 __u64 new_up_hdr_ptr);
+
+int ocfs_grow_extent_tree (ocfs_super * osb,
+		ocfs_file_entry * FileEntry,
+		__u64 actualDiskOffset, __u64 actualLength);
+
+int ocfs_allocate_extent (ocfs_super * osb,
+		    ocfs_inode * oin,
+		    ocfs_file_entry * FileEntry,
+		    __u64 actualDiskOffset, __u64 actualLength);
+
+bool ocfs_get_next_extent_map_entry (ocfs_super * osb,
+			   ocfs_extent_map * Map,
+			   __u32 RunIndex,
+			   __s64 * Vbo, __s64 * Lbo, __u32 * SectorCount);
+
+int ocfs_update_all_headers (ocfs_super * osb,
+		  ocfs_extent_group * AllocExtent, __u64 FileSize, ocfs_file_entry *fe);
+
+int ocfs_free_extents_for_truncate (ocfs_super * osb, ocfs_file_entry * FileEntry);
+
+int ocfs_get_leaf_extent (ocfs_super * osb,
+	       ocfs_file_entry * FileEntry,
+	       __s64 Vbo, ocfs_extent_group * OcfsDataExtent);
+
+int ocfs_adjust_allocation (ocfs_io_runs ** IoRuns, __u32 * ioRunSize);
+
+bool ocfs_lookup_extent_map_entry (ocfs_super * osb,
+			  ocfs_extent_map * Map,
+			  __s64 Vbo, __s64 * Lbo, __u64 * SectorCount, __u32 * Index);
+
+bool ocfs_add_extent_map_entry (ocfs_super * osb,
+		       ocfs_extent_map * Map, __s64 Vbo, __s64 Lbo, __u64 ByteCount);
+
+int ocfs_update_extent_map (ocfs_super * osb,
+		     ocfs_extent_map * Map,
+		     void *Buffer,
+		     __s64 * localVbo, __u64 * remainingLength, __u32 Flag);
+
+int ocfs_extent_map_load (ocfs_super * osb,
+		     ocfs_extent_map * Map,
+		     void **Buffer, __s64 Vbo, __u64 ByteCount, __u32 * RetRuns);
+
+                                                                                
+int ocfs_fix_extent_group(ocfs_super *osb, ocfs_extent_group *group);
+
+int ocfs_update_last_ext_ptr(ocfs_super *osb, ocfs_file_entry *fe);
+
+int ocfs_split_this_tree(ocfs_super * osb, ocfs_extent_group *extent_grp,
+                        ocfs_cleanup_record *CleanupLogRec, ocfs_file_entry *fe);
+
+int _squish_extent_entries(ocfs_super *osb, ocfs_alloc_ext *extarr, __u8 *freeExtent, ocfs_cleanup_record *CleanupLogRec, __u64 FileSize, bool flag);
+
+/*
+ * ocfs_force_get_file_entry()
+ *
+ */
+static inline int ocfs_force_get_file_entry (ocfs_super * osb, ocfs_file_entry ** FileEntry,
+		       __u64 DiskOffset, bool force)
+{
+	if (!FileEntry)
+		return -EFAIL;
+	*FileEntry = ocfs_allocate_file_entry ();
+	if (!*FileEntry)
+		return -ENOMEM;
+	if (force)
+		return ocfs_read_force_disk (osb, *FileEntry, osb->sect_size,
+					  DiskOffset);
+	else
+		return ocfs_read_file_entry (osb, *FileEntry, DiskOffset);
+}  /* ocfs_force_get_file_entry */
+
+
+/*
+ * ocfs_force_put_file_entry()
+ *
+ */
+static inline int ocfs_force_put_file_entry (ocfs_super * osb, ocfs_file_entry * FileEntry,
+		       bool force)
+{
+	if (!FileEntry)
+		return -EFAIL;
+	if (force)
+		return ocfs_write_force_disk (osb, FileEntry, osb->sect_size,
+					   FileEntry->this_sector);
+	else
+		return ocfs_write_file_entry (osb, FileEntry,
+					   FileEntry->this_sector);
+}  /* ocfs_force_put_file_entry */
+
+
+#define ocfs_get_file_entry(x,y,z)  ocfs_force_get_file_entry(x,y,z,false)
+#define ocfs_put_file_entry(x,y)    ocfs_force_put_file_entry(x,y,false)
+
+
+#endif				/* _OCFSGENALLOC_H_ */

Added: trunk/libocfs/Common/inc/ocfsgencreate.h
===================================================================
--- trunk/libocfs/Common/inc/ocfsgencreate.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/inc/ocfsgencreate.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,103 @@
+/*
+ * ocfsgencreate.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSGENCREATE_H_
+#define _OCFSGENCREATE_H_
+
+int ocfs_verify_update_oin (ocfs_super * osb, ocfs_inode * oin);
+
+int ocfs_find_contiguous_space_from_bitmap (ocfs_super * osb,
+			       __u64 file_size,
+			       __u64 * cluster_off, __u64 * cluster_count, bool sysfile);
+
+int ocfs_create_oin_from_entry (ocfs_super * osb,
+		    ocfs_file_entry * fe,
+		    ocfs_inode ** new_oin,
+		    __u64 parent_dir_off, ocfs_inode * parent_oin);
+
+int ocfs_find_files_on_disk (ocfs_super * osb,
+		 __u64 parent_off,
+		 struct qstr * file_name,
+		 ocfs_file_entry * fe, ocfs_file * ofile);
+
+void ocfs_initialize_dir_node (ocfs_super * osb,
+		   ocfs_dir_node * dir_node,
+		   __u64 bitmap_off, __u64 file_off, __u32 node);
+
+int ocfs_delete_file_entry (ocfs_super * osb,
+		 ocfs_file_entry * fe, __u64 parent_off, __s32 log_node_num);
+
+int ocfs_rename_file (ocfs_super * osb,
+		__u64 parent_off, struct qstr * file_name, __u64 file_off);
+
+int ocfs_del_file (ocfs_super * osb, __u64 parent_off, __u32 flags, __u64 file_off);
+
+int ocfs_extend_file (ocfs_super * osb, __u64 parent_off,
+		ocfs_inode * oin, __u64 file_size, __u64 * file_off);
+
+int ocfs_change_file_size (ocfs_super * osb,
+		    __u64 parent_off,
+		    ocfs_inode * oin,
+		    __u64 file_size, __u64 * file_off, struct iattr *attr);
+
+int ocfs_get_dirnode(ocfs_super *osb, ocfs_dir_node *lockn, __u64 lockn_off,
+		     ocfs_dir_node *dirn);
+
+int ocfs_create_directory (ocfs_super * osb, __u64 parent_off, ocfs_file_entry * fe);
+
+int ocfs_create_file (ocfs_super * osb, __u64 parent_off, ocfs_file_entry * fe);
+
+int ocfs_create_modify_file (ocfs_super * osb,
+		  __u64 parent_off,
+		  ocfs_inode * oin,
+		  struct qstr * file_name,
+		  __u64 file_size,
+		  __u64 * file_off, __u32 flags, ocfs_file_entry * fe, struct iattr *attr);
+
+int ocfs_initialize_oin (ocfs_inode * oin,
+		   ocfs_super * osb,
+		   __u32 flags, struct file *file_obj, __u64 file_off, __u64 lock_id);
+
+int ocfs_create_delete_cdsl (struct inode *inode,
+		  struct file *filp, ocfs_super * osb, ocfs_cdsl * cdsl);
+
+int ocfs_find_create_cdsl (ocfs_super * osb, ocfs_file_entry * fe);
+
+#ifdef UNUSED_CODE
+int ocfs_update_file_entry_slot (ocfs_super * osb, ocfs_inode * oin, ocfs_rw_mode rw_mode);
+
+void ocfs_check_lock_state (ocfs_super * osb, ocfs_inode * oin);
+#endif
+
+int ocfs_delete_cdsl (ocfs_super * osb, __u64 parent_off, ocfs_file_entry * fe);
+
+int ocfs_create_cdsl (ocfs_super * osb, __u64 parent_off, ocfs_file_entry * fe);
+
+int ocfs_change_to_cdsl (ocfs_super * osb, __u64 parent_off, ocfs_file_entry * fe);
+
+int ocfs_truncate_file (ocfs_super * osb, __u64 file_off, __u64 file_size, ocfs_inode *oin);
+
+#endif				/* _OCFSGENCREATE_H_ */

Added: trunk/libocfs/Common/inc/ocfsgendirnode.h
===================================================================
--- trunk/libocfs/Common/inc/ocfsgendirnode.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/inc/ocfsgendirnode.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,85 @@
+/*
+ * ocfsgendirnode.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002, 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSGENDIRNODE_H_
+#define _OCFSGENDIRNODE_H_
+
+void ocfs_print_file_entry (ocfs_file_entry * fe);
+
+void ocfs_print_dir_node (ocfs_super * osb, ocfs_dir_node * DirNode);
+
+int ocfs_alloc_node_block (ocfs_super * osb,
+		__u64 FileSize,
+		__u64 * DiskOffset,
+		__u64 * file_off, __u64 * NumClusterAlloc, __u32 NodeNum, __u32 Type);
+
+int ocfs_free_vol_block (ocfs_super * osb, ocfs_free_log * FreeLog, __u32 NodeNum, __u32 Type);
+
+int ocfs_free_node_block (ocfs_super * osb,
+	       __u64 file_off, __u64 Length, __u32 NodeNum, __u32 Type);
+
+int ocfs_free_directory_block (ocfs_super * osb, ocfs_file_entry * fe, __s32 LogNodeNum);
+
+int ocfs_recover_dir_node (ocfs_super * osb,
+		__u64 OrigDirNodeOffset, __u64 SavedDirNodeOffset);
+
+#define ocfs_read_dir_node(__osb, __dirn, __off)	\
+	ocfs_read_disk(__osb, __dirn, (__osb)->vol_layout.dir_node_size, __off)
+
+int ocfs_write_force_dir_node (ocfs_super * osb,
+		       ocfs_dir_node * DirNode, __s32 IndexFileEntry);
+
+int ocfs_write_dir_node (ocfs_super * osb,
+		  ocfs_dir_node * DirNode, __s32 IndexFileEntry);
+
+bool ocfs_walk_dir_node (ocfs_super * osb,
+	       ocfs_dir_node * DirNode,
+	       ocfs_file_entry * found_fe, ocfs_file * OFile);
+
+bool ocfs_search_dir_node (ocfs_super * osb,
+		 ocfs_dir_node * DirNode,
+		 struct qstr * SearchName,
+		 ocfs_file_entry * found_fe, ocfs_file * OFile);
+
+bool ocfs_find_index (ocfs_super * osb,
+	   ocfs_dir_node * DirNode, struct qstr * FileName, int *Index);
+
+int ocfs_reindex_dir_node (ocfs_super * osb, __u64 DirNodeOffset, ocfs_dir_node * DirNode);
+
+int ocfs_insert_dir_node (ocfs_super * osb,
+	       ocfs_dir_node * DirNode,
+	       ocfs_file_entry * InsertEntry,
+	       ocfs_dir_node * LockNode, __s32 * IndexOffset);
+
+int ocfs_del_file_entry (ocfs_super * osb,
+	      ocfs_file_entry * EntryToDel, ocfs_dir_node * LockNode);
+
+int ocfs_insert_file (ocfs_super * osb,
+	    ocfs_dir_node * DirNode,
+	    ocfs_file_entry * InsertEntry,
+	    ocfs_dir_node * LockNode, ocfs_lock_res * LockResource);
+
+#endif				/* _OCFSGENDIRNODE_H_ */

Added: trunk/libocfs/Common/inc/ocfsgendlm.h
===================================================================
--- trunk/libocfs/Common/inc/ocfsgendlm.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/inc/ocfsgendlm.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,133 @@
+/*
+ * ocfsgendlm.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSGENDLM_H_
+#define _OCFSGENDLM_H_
+
+typedef struct _ocfs_offset_map
+{
+	__u32 length;
+	__u64 log_disk_off;
+	__u64 actual_disk_off;
+}
+OCFS_GCC_ATTR_PACKALGN
+ocfs_offset_map;
+
+int ocfs_insert_cache_link (ocfs_super * osb, ocfs_lock_res * lockres);
+
+int ocfs_update_lock_state (ocfs_super * osb, ocfs_lock_res * lockres,
+			    __u32 flags, bool *disk_vote);
+
+int ocfs_disk_request_vote (ocfs_super * osb, __u64 lock_id, __u32 lock_type,
+			    __u32 flags, __u64 vote_map, __u64 * lock_seq_num);
+
+int ocfs_wait_for_disk_lock_release (ocfs_super * osb, __u64 offset,
+				     __u32 time_to_wait, __u32 lock_type);
+
+int ocfs_wait_for_lock_release (ocfs_super * osb, __u64 offset, __u32 time_to_wait,
+				ocfs_lock_res * lockres, __u32 lock_type);
+
+int ocfs_get_vote_on_disk (ocfs_super * osb, __u64 lock_id, __u32 lock_type,
+			   __u32 flags, __u64 * got_vote_map, __u64 vote_map,
+			   __u64 lock_seq_num, __u64 * oin_open_map);
+
+int ocfs_disk_reset_voting (ocfs_super * osb, __u64 lock_id, __u32 lock_type);
+
+int ocfs_wait_for_vote (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags,
+			__u64 vote_map, __u32 time_to_wait, __u64 lock_seq_num,
+			ocfs_lock_res * lockres);
+
+int ocfs_reset_voting (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u64 vote_map);
+
+int ocfs_request_vote (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags,
+		       __u64 vote_map, __u64 * lock_seq_num);
+
+int ocfs_comm_request_vote (ocfs_super * osb, __u64 lock_id, __u32 lock_type,
+			    __u32 flags, ocfs_file_entry * fe, __u32 attempts);
+
+void ocfs_init_dlm_msg (ocfs_super * osb, ocfs_dlm_msg * dlm_msg, __u32 msg_len);
+
+int ocfs_send_dlm_request_msg (ocfs_super * osb, __u64 lock_id, __u32 lock_type,
+			       __u32 flags, ocfs_lock_res * lockres,
+			       __u64 vote_map);
+
+int ocfs_comm_make_lock_master (ocfs_super * osb, __u64 lock_id, __u32 lock_type,
+				__u32 flags, ocfs_lock_res * lockres,
+				ocfs_file_entry * fe, __u64 vote_map,
+				__u32 attempts);
+
+int ocfs_make_lock_master (ocfs_super * osb, __u64 lock_id, __u32 lock_type,
+			   __u32 flags, ocfs_lock_res * lockres,
+			   ocfs_file_entry * fe, bool *disk_vote);
+
+int ocfs_acquire_lockres_ex (ocfs_lock_res * lockres, __u32 timeout);
+#define ocfs_acquire_lockres(a)		ocfs_acquire_lockres_ex(a, 0)
+
+void ocfs_release_lockres (ocfs_lock_res * lockres);
+
+int ocfs_update_disk_lock (ocfs_super * osb, ocfs_lock_res * lockres,
+			   __u32 flags, ocfs_file_entry * fe);
+
+int ocfs_update_master_on_open (ocfs_super * osb, ocfs_lock_res * lockres);
+
+void ocfs_init_lockres (ocfs_super * osb, ocfs_lock_res * lockres,
+			__u64 lock_id);
+
+int ocfs_create_update_lock (ocfs_super * osb, ocfs_inode * oin, __u64 lock_id,
+			     __u32 flags);
+
+int ocfs_get_x_for_del (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags,
+			ocfs_lock_res * lockres, ocfs_file_entry * fe);
+
+int ocfs_try_exclusive_lock (ocfs_super *osb, ocfs_lock_res *lockres, __u32 flags,
+			     __u32 updated, ocfs_file_entry *fe, __u64 lock_id,
+			     __u32 lock_type);
+
+int ocfs_acquire_lock (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags,
+		       ocfs_lock_res ** lockres, ocfs_file_entry * lock_fe);
+
+int ocfs_disk_release_lock (ocfs_super * osb, __u64 lock_id, __u32 lock_type,
+			    __u32 flags, ocfs_lock_res * lockres, ocfs_file_entry *fe);
+
+int ocfs_release_lock (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags,
+		       ocfs_lock_res * lockres, ocfs_file_entry *fe);
+
+int ocfs_init_dlm (void);
+
+int ocfs_add_lock_to_recovery (void);
+
+int ocfs_create_log_extent_map (ocfs_super * osb, ocfs_io_runs ** PTransRuns,
+		__u32 * PNumTransRuns, __u64 diskOffset, __u64 ByteCount);
+
+int ocfs_lookup_cache_link (ocfs_super * osb, __u8 * buf, __u64 actual_disk_off,
+			    __u64 length);
+
+int ocfs_process_log_file (ocfs_super * osb, bool flag);
+
+int ocfs_break_cache_lock (ocfs_super * osb, ocfs_lock_res * lockres,
+			   ocfs_file_entry *fe);
+
+#endif				/* _OCFSGENDLM_H_ */

Added: trunk/libocfs/Common/inc/ocfsgenmisc.h
===================================================================
--- trunk/libocfs/Common/inc/ocfsgenmisc.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/inc/ocfsgenmisc.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,365 @@
+/*
+ * ocfsgenmisc.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSGENMISC_H_
+#define _OCFSGENMISC_H_
+
+int ocfs_create_meta_log_files (ocfs_super * osb);
+
+int ocfs_create_new_oin (ocfs_inode ** Returnedoin,
+		  __u64 * AllocationSize,
+		  __u64 * EndOfFile, struct file *FileObject, ocfs_super * osb);
+
+int ocfs_create_root_dir_node (ocfs_super * osb);
+
+int ocfs_create_root_oin (ocfs_super * osb);
+
+void ocfs_delete_all_extent_maps (ocfs_inode * oin);
+
+void ocfs_release_oin (ocfs_inode * oin, bool FreeMemory);
+
+int ocfs_initialize_osb (ocfs_super * osb,
+		   ocfs_vol_disk_hdr * VolDiskHdr,
+		   ocfs_vol_label * VolLabel, __u32 SectorSize);
+
+int ocfs_verify_volume (ocfs_vol_disk_hdr * VolDiskHdr);
+
+int ocfs_vol_member_reconfig (ocfs_super * osb);
+
+int ocfs_check_volume (ocfs_super * osb);
+
+void ocfs_delete_osb (ocfs_super * osb);
+
+int ocfs_commit_cache (ocfs_super * osb, bool Flag);
+
+
+/* sorry about all the macros, but file and line are important */
+
+#ifndef USERSPACE_TOOL
+/* lockres macros */
+#ifdef OCFS_MEM_DBG
+#define ocfs_allocate_lockres()						\
+({									\
+	ocfs_lock_res *_l = NULL;					\
+	 _l = (ocfs_lock_res *)ocfs_dbg_slab_alloc 			\
+	 	(OcfsGlobalCtxt.lockres_cache, __FILE__, __LINE__);	\
+	if (_l)	{							\
+       		memset (_l, 0, sizeof(ocfs_lock_res));			\
+		atomic_inc (&(OcfsGlobalCtxt.cnt_lockres));		\
+	}								\
+	_l;								\
+})
+
+#define ocfs_free_lockres(_r)						\
+do {									\
+	ocfs_dbg_slab_free (OcfsGlobalCtxt.lockres_cache, _r);		\
+	atomic_dec (&(OcfsGlobalCtxt.cnt_lockres));			\
+} while (0)
+
+#else  /* !OCFS_MEM_DBG */
+#define ocfs_allocate_lockres()						\
+({									\
+ 	ocfs_lock_res *_l = NULL;					\
+	_l = (ocfs_lock_res *)kmem_cache_alloc				\
+			(OcfsGlobalCtxt.lockres_cache, GFP_NOFS);	\
+	if (_l)	{							\
+       		memset (_l, 0, sizeof(ocfs_lock_res));			\
+		atomic_inc (&(OcfsGlobalCtxt.cnt_lockres));		\
+	}								\
+	_l;								\
+})
+
+#define ocfs_free_lockres(_r)						\
+do {									\
+	kmem_cache_free (OcfsGlobalCtxt.lockres_cache, _r);		\
+	atomic_dec (&(OcfsGlobalCtxt.cnt_lockres));			\
+} while (0)
+
+#endif
+
+#define _ocfs_get_lockres(_r)					\
+do {								\
+	if (_r) 						\
+		atomic_inc(&((_r)->lr_ref_cnt));		\
+} while (0)
+
+#define _ocfs_put_lockres(_r)					\
+do {								\
+	if (_r) {						\
+		if (atomic_dec_and_test(&((_r)->lr_ref_cnt))) 	\
+			ocfs_free_lockres(_r);			\
+	}							\
+} while (0)
+
+#ifdef OCFS_DBG_LOCKRES
+#define ocfs_get_lockres(_r)						\
+do {									\
+	if (_r) {							\
+		if (debug_level & OCFS_DEBUG_LEVEL_LOCKRES)		\
+			printk("(%d) get: 0x%08x, %d, %s, %d\n",	\
+			       ocfs_getpid(), (_r),			\
+			       atomic_read(&((_r)->lr_ref_cnt)) + 1,	\
+			       __FUNCTION__, __LINE__);			\
+		_ocfs_get_lockres(_r);					\
+	} else {							\
+		if (debug_level & OCFS_DEBUG_LEVEL_LOCKRES)		\
+			printk("(%d) get: null, -1, %s, %d\n",		\
+			       ocfs_getpid(), __FUNCTION__, __LINE__);	\
+	}								\
+} while (0)
+
+#define ocfs_put_lockres(_r)						\
+do {									\
+	if (_r) {							\
+		if (debug_level & OCFS_DEBUG_LEVEL_LOCKRES)		\
+			printk("(%d) put: 0x%08x, %d, %s, %d\n",	\
+			       ocfs_getpid(), (_r),			\
+			       atomic_read(&((_r)->lr_ref_cnt)) - 1,	\
+			       __FUNCTION__, __LINE__);			\
+		_ocfs_put_lockres(_r);					\
+	} else {							\
+		if (debug_level & OCFS_DEBUG_LEVEL_LOCKRES)		\
+			printk("(%d) put: null, -1, %s, %d\n",		\
+			       ocfs_getpid(), __FUNCTION__, __LINE__);	\
+	}								\
+} while (0)
+#else	/* !OCFS_DBG_LOCKRES */
+#define ocfs_get_lockres(_r)		_ocfs_get_lockres(_r)
+#define	ocfs_put_lockres(_r)		_ocfs_put_lockres(_r)
+#endif
+
+
+
+/* ofile macros */
+#ifdef OCFS_MEM_DBG
+#define ocfs_allocate_ofile()    ((ocfs_file *)({ \
+        ocfs_file *of = NULL; \
+        of = ocfs_dbg_slab_alloc(OcfsGlobalCtxt.ofile_cache, __FILE__, __LINE__); \
+	if (of != NULL) { \
+	  memset (of, 0, sizeof (ocfs_file)); \
+	  of->obj_id.type = OCFS_TYPE_OFILE; \
+          of->obj_id.size = sizeof (ocfs_file); \
+        } \
+	of; }))
+
+#define ocfs_release_ofile(of)						\
+do {									\
+	if (of) {							\
+        	ocfs_release_dirnode ((of)->curr_dir_buf);		\
+        	ocfs_dbg_slab_free (OcfsGlobalCtxt.ofile_cache, (of));	\
+	}								\
+} while (0)
+#else  /* !OCFS_MEM_DBG */
+#define ocfs_allocate_ofile()    ((ocfs_file *)({ \
+        ocfs_file *of = NULL; \
+	of = kmem_cache_alloc (OcfsGlobalCtxt.ofile_cache, GFP_NOFS); \
+	if (of != NULL) { \
+	  memset (of, 0, sizeof (ocfs_file)); \
+	  of->obj_id.type = OCFS_TYPE_OFILE; \
+          of->obj_id.size = sizeof (ocfs_file); \
+        } \
+	of; }))
+
+#define ocfs_release_ofile(of)						\
+do {									\
+	if (of) {							\
+        	ocfs_release_dirnode ((of)->curr_dir_buf);		\
+		kmem_cache_free (OcfsGlobalCtxt.ofile_cache, (of));	\
+	}								\
+} while (0)
+#endif
+
+
+/* file entry macros */
+#ifdef OCFS_MEM_DBG
+#define ocfs_allocate_file_entry()  ((ocfs_file_entry *)({ \
+	ocfs_file_entry *FileEntry = NULL; \
+	FileEntry = ocfs_dbg_slab_alloc (OcfsGlobalCtxt.fe_cache, __FILE__, __LINE__); \
+	if (FileEntry != NULL) \
+	  memset (FileEntry, 0, OCFS_SECTOR_SIZE); \
+	FileEntry; }))
+
+#define ocfs_release_file_entry(fe)					  \
+	do {								  \
+		if (fe) {						  \
+			ocfs_dbg_slab_free (OcfsGlobalCtxt.fe_cache, fe); \
+			fe = NULL;					  \
+		}							  \
+	} while (0)
+#else  /* !OCFS_MEM_DBG */
+#define ocfs_allocate_file_entry()  ((ocfs_file_entry *)({ \
+	ocfs_file_entry *FileEntry = NULL; \
+	FileEntry = kmem_cache_alloc (OcfsGlobalCtxt.fe_cache, GFP_NOFS); \
+	if (FileEntry != NULL) \
+ 	  memset (FileEntry, 0, OCFS_SECTOR_SIZE); \
+	FileEntry; }))
+
+#define ocfs_release_file_entry(fe)					\
+	do {								\
+		if (fe) {						\
+			kmem_cache_free (OcfsGlobalCtxt.fe_cache, fe);	\
+			fe = NULL;					\
+		}							\
+	} while (0)
+#endif
+
+/* oin macros - currently the release is handled separately */
+#ifdef OCFS_MEM_DBG
+#define ocfs_allocate_oin()  ((ocfs_inode *)({ \
+	ocfs_inode *oin = NULL; \
+	oin = ocfs_dbg_slab_alloc (OcfsGlobalCtxt.oin_cache, __FILE__, __LINE__); \
+	if (oin != NULL) { \
+ 	  memset (oin, 0, sizeof (ocfs_inode)); \
+	  oin->obj_id.type = OCFS_TYPE_OIN; \
+          oin->obj_id.size = sizeof (ocfs_inode); \
+        } \
+	oin; })) 
+#else  /* !OCFS_MEM_DBG */
+#define ocfs_allocate_oin()  ((ocfs_inode *)({ \
+	ocfs_inode *oin = NULL; \
+	oin = kmem_cache_alloc (OcfsGlobalCtxt.oin_cache, GFP_NOFS); \
+	if (oin != NULL) { \
+          memset (oin, 0, sizeof (ocfs_inode)); \
+          oin->obj_id.type = OCFS_TYPE_OIN; \
+          oin->obj_id.size = sizeof (ocfs_inode); \
+        } \
+	oin; })) 
+#endif
+
+/* dirnode macros */
+#ifdef OCFS_MEM_DBG
+#define ocfs_allocate_dirnode()					\
+((ocfs_dir_node *)({						\
+	ocfs_dir_node *_dn = NULL;				\
+	_dn = ocfs_dbg_slab_alloc (OcfsGlobalCtxt.dirnode_cache, __FILE__, __LINE__); \
+	if (_dn)						\
+		memset (_dn, 0, OCFS_DEFAULT_DIR_NODE_SIZE);	\
+	_dn; }))
+
+#define ocfs_release_dirnode(_dn)				\
+	do {							\
+		if (_dn) {					\
+			ocfs_dbg_slab_free (OcfsGlobalCtxt.dirnode_cache, (_dn));\
+			(_dn) = NULL;				\
+		}						\
+	} while (0)
+#else  /* !OCFS_MEM_DBG */
+#define ocfs_allocate_dirnode()					\
+((ocfs_dir_node *)({						\
+	ocfs_dir_node *_dn = NULL;				\
+	_dn = kmem_cache_alloc (OcfsGlobalCtxt.dirnode_cache, GFP_NOFS);\
+	if (_dn)						\
+		memset (_dn, 0, OCFS_DEFAULT_DIR_NODE_SIZE);	\
+	_dn; }))
+
+#define ocfs_release_dirnode(_dn)				\
+	do {							\
+		if (_dn) {					\
+			kmem_cache_free (OcfsGlobalCtxt.dirnode_cache, (_dn));\
+			(_dn) = NULL;				\
+		}						\
+	} while (0)
+#endif
+#endif  /* !USERSPACE_TOOL */
+
+
+
+
+/* userspace stuff */
+#ifdef USERSPACE_TOOL
+/* lockres macros */
+#define ocfs_allocate_lockres()	((ocfs_lock_res *)ocfs_malloc(sizeof(ocfs_lock_res)))
+#define ocfs_free_lockres(_r)	ocfs_safefree(_r)
+
+#define ocfs_get_lockres(_r)					\
+do {								\
+	if (_r) 						\
+		atomic_inc(&((_r)->lr_ref_cnt));		\
+} while (0)
+
+#define ocfs_put_lockres(_r)					\
+do {								\
+	if (_r) {						\
+		if (atomic_dec_and_test(&((_r)->lr_ref_cnt))) 	\
+			ocfs_free_lockres(_r);			\
+	}							\
+} while (0)
+
+/* ofile macros */
+#define ocfs_allocate_ofile()    ((ocfs_file *)({ \
+        ocfs_file *of = NULL; \
+	of = (ocfs_file *)ocfs_malloc(sizeof(ocfs_file)); \
+	if (of != NULL) { \
+	  memset (of, 0, sizeof (ocfs_file)); \
+	  of->obj_id.type = OCFS_TYPE_OFILE; \
+          of->obj_id.size = sizeof (ocfs_file); \
+        } \
+	of; }))
+
+#define ocfs_release_ofile(of) ({ \
+	ocfs_safefree (of->curr_dir_buf); \
+	ocfs_safefree (of);  })
+
+
+/* file entry macros */
+#define ocfs_allocate_file_entry()  ((ocfs_file_entry *)({ \
+	ocfs_file_entry *FileEntry = NULL; \
+	FileEntry = (ocfs_file_entry *)ocfs_malloc(OCFS_SECTOR_SIZE); \
+	if (FileEntry != NULL) \
+ 	  memset (FileEntry, 0, OCFS_SECTOR_SIZE); \
+	FileEntry; }))
+
+#define ocfs_release_file_entry(fe)		 ocfs_safefree(fe)
+
+/* oin macros */
+#define ocfs_allocate_oin()  ((ocfs_inode *)({ \
+	ocfs_inode *oin = NULL; \
+	oin = (ocfs_inode *)ocfs_malloc(sizeof(ocfs_inode)); \
+	if (oin != NULL) { \
+          memset (oin, 0, sizeof (ocfs_inode)); \
+          oin->obj_id.type = OCFS_TYPE_OIN; \
+          oin->obj_id.size = sizeof (ocfs_inode); \
+        } \
+	oin; })) 
+
+#define ocfs_release_oin(oin,x)	({ \
+	if (x) \
+		ocfs_safefree(oin);  })
+
+/* dirnode macros */
+#define ocfs_allocate_dirnode()					\
+((ocfs_dir_node *)({						\
+	ocfs_dir_node *_dn = NULL;				\
+	_dn = (ocfs_dir_node *)ocfs_malloc(OCFS_DEFAULT_DIR_NODE_SIZE);\
+	if (_dn)						\
+		memset (_dn, 0, OCFS_DEFAULT_DIR_NODE_SIZE);	\
+	_dn; }))
+
+#define ocfs_release_dirnode(_dn)		ocfs_safefree(_dn)
+
+#endif  /* USERSPACE_TOOL */
+
+#endif				/* _OCFSGENMISC_H_ */

Added: trunk/libocfs/Common/inc/ocfsgennm.h
===================================================================
--- trunk/libocfs/Common/inc/ocfsgennm.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/inc/ocfsgennm.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,57 @@
+/*
+ * ocfsgennm.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSGENNM_H_
+#define _OCFSGENNM_H_
+
+int ocfs_flush_data (ocfs_inode * oin);
+
+int ocfs_disk_update_resource (ocfs_super * osb, ocfs_lock_res * lockres,
+			       ocfs_file_entry * file_ent, __u32 timeout);
+
+int ocfs_check_for_stale_lock(ocfs_super *osb, ocfs_lock_res *lockres, 
+			      ocfs_file_entry *fe, __u64 lock_id);
+
+int ocfs_find_update_res (ocfs_super * osb, __u64 lock_id,
+			  ocfs_lock_res ** lockres, ocfs_file_entry * fe,
+			  __u32 * updated, __u32 timeout);
+
+int ocfs_vote_for_del_ren (ocfs_super * osb, ocfs_publish * publish,
+			   __u32 node_num, ocfs_vote * vote,
+			   ocfs_lock_res ** lockres);
+
+struct inode * ocfs_get_inode_from_offset(ocfs_super * osb, __u64 fileoff);
+
+int ocfs_process_update_inode_request (ocfs_super * osb, __u64 lock_id,
+				       ocfs_lock_res * lockres, __u32 node_num);
+
+int ocfs_process_vote (ocfs_super * osb, ocfs_publish * publish, __u32 node_num);
+
+int ocfs_common_del_ren (ocfs_super * osb, __u64 lock_id, __u32 flags,
+			 __u32 node_num, __u64 seq_num, __u8 * vote,
+			 ocfs_lock_res ** lockres);
+
+#endif				/* _OCFSGENNM_H_ */

Added: trunk/libocfs/Common/inc/ocfsgensysfile.h
===================================================================
--- trunk/libocfs/Common/inc/ocfsgensysfile.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/inc/ocfsgensysfile.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,54 @@
+/*
+ * ocfsgensysfile.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSGENSYSFILE_H_
+#define _OCFSGENSYSFILE_H_
+
+int ocfs_init_system_file (ocfs_super * osb, __u32 FileId, char *filename,
+			   ocfs_file_entry *fe);
+
+int ocfs_read_system_file (ocfs_super * osb,
+		__u32 FileId, void *Buffer, __u64 Length, __u64 Offset);
+
+int ocfs_write_system_file (ocfs_super * osb,
+		 __u32 FileId, void *Buffer, __u64 Length, __u64 Offset);
+
+__u64 ocfs_file_to_disk_off (ocfs_super * osb, __u32 FileId, __u64 Offset);
+
+int ocfs_get_system_file_size (ocfs_super * osb, __u32 FileId, __u64 * Length, __u64 * AllocSize);
+
+int ocfs_extend_system_file (ocfs_super * osb, __u32 FileId, __u64 FileSize, ocfs_file_entry *fe);
+
+int ocfs_find_extents_of_system_file (ocfs_super * osb,
+			 __u64 file_off,
+			 __u64 Length,
+			 ocfs_file_entry * fe, void **Buffer, __u32 * NumEntries);
+
+int ocfs_free_file_extents (ocfs_super * osb, ocfs_file_entry * fe, __s32 LogNodeNum);
+
+int ocfs_write_map_file (ocfs_super * osb);
+
+#endif				/* _OCFSGENSYSFILE_H_ */

Added: trunk/libocfs/Common/inc/ocfsgentrans.h
===================================================================
--- trunk/libocfs/Common/inc/ocfsgentrans.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/inc/ocfsgentrans.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,51 @@
+/*
+ * ocfsgentrans.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSGENTRANS_H_
+#define _OCFSGENTRANS_H_
+
+int ocfs_free_disk_bitmap (ocfs_super * osb, ocfs_cleanup_record * log_rec);
+
+int ocfs_process_record (ocfs_super * osb, void *buffer);
+
+int ocfs_process_log (ocfs_super * osb, __u64 trans_id, __u32 node_num, __u32 * type);
+
+int ocfs_start_trans (ocfs_super * osb);
+
+int ocfs_commit_trans (ocfs_super * osb, __u64 trans_id);
+
+int ocfs_abort_trans (ocfs_super * osb, __u64 trans_id);
+
+int ocfs_reset_publish (ocfs_super * osb, __u64 node_num);
+
+int ocfs_recover_vol (ocfs_super * osb, __u64 node_num);
+
+int ocfs_write_log (ocfs_super * osb, ocfs_log_record * log_rec, __u32 type);
+
+int ocfs_write_node_log (ocfs_super * osb,
+		  ocfs_log_record * log_rec, __u32 node_num, __u32 type);
+
+#endif				/* _OCFSGENTRANS_H_ */

Added: trunk/libocfs/Common/inc/ocfsgenutil.h
===================================================================
--- trunk/libocfs/Common/inc/ocfsgenutil.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/inc/ocfsgenutil.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,32 @@
+/*
+ * ocfsgenutil.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSGENUTIL_H_
+#define _OCFSGENUTIL_H_
+
+int ocfs_compare_qstr (struct qstr * s1, struct qstr * s2);
+
+#endif				/* _OCFSGENUTIL_H_ */

Added: trunk/libocfs/Common/inc/ocfsgenvolcfg.h
===================================================================
--- trunk/libocfs/Common/inc/ocfsgenvolcfg.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/inc/ocfsgenvolcfg.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,84 @@
+/*
+ * ocfsgenvolcfg.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSGENVOLCFG_H_
+#define _OCFSGENVOLCFG_H_
+
+typedef struct _ocfs_cfg_task
+{
+	struct tq_struct cfg_tq;
+	ocfs_super *osb;
+	__u64 lock_off;
+	__u8 *buffer;
+}
+ocfs_cfg_task;
+
+typedef enum _ocfs_volcfg_op
+{
+	OCFS_VOLCFG_ADD,
+	OCFS_VOLCFG_UPD
+}
+ocfs_volcfg_op;
+
+void ocfs_worker (void *Arg);
+
+void ocfs_assert_lock_owned (unsigned long Arg);
+
+int ocfs_add_to_disk_config (ocfs_super * osb, __u32 pref_node_num,
+			     ocfs_disk_node_config_info * NodeCfgInfo);
+
+int ocfs_write_volcfg_header (ocfs_super * osb, ocfs_volcfg_op op);
+
+void ocfs_volcfg_gblctxt_to_disknode(ocfs_disk_node_config_info *disk);
+
+void ocfs_volcfg_gblctxt_to_node(ocfs_node_config_info *node);
+
+int ocfs_config_with_disk_lock (ocfs_super * osb, __u64 LockOffset, __u8 * Buffer,
+				__u32 node_num, ocfs_volcfg_op op);
+
+int ocfs_release_disk_lock (ocfs_super * osb, __u64 LockOffset);
+
+void ocfs_cfg_worker (ocfs_super * osb);
+
+int ocfs_disknode_to_node (ocfs_node_config_info ** CfgInfo,
+		 ocfs_disk_node_config_info * NodeCfgInfo);
+
+int ocfs_update_disk_config (ocfs_super * osb, __u32 node_num,
+			     ocfs_disk_node_config_info * disk);
+
+int ocfs_chk_update_config (ocfs_super * osb);
+
+int ocfs_add_node_to_config (ocfs_super * osb);
+
+int ocfs_get_config (ocfs_super * osb);
+
+bool ocfs_has_node_config_changed (ocfs_super * osb);
+
+int ocfs_refresh_node_config (ocfs_super * osb);
+
+void ocfs_show_all_node_cfgs (ocfs_super * osb);
+
+#endif				/* _OCFSGENVOLCFG_H_ */

Added: trunk/libocfs/Common/inc/ocfsgenvote.h
===================================================================
--- trunk/libocfs/Common/inc/ocfsgenvote.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/inc/ocfsgenvote.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,55 @@
+/*
+ * ocfsgenvote.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSGENVOTE_H_
+#define _OCFSGENVOTE_H_
+
+int ocfs_send_vote_reply (ocfs_super * osb, ocfs_dlm_msg * dlm_msg,
+			  __u32 vote_status, bool inode_open);
+
+int ocfs_comm_vote_for_del_ren (ocfs_super * osb, ocfs_lock_res ** lockres,
+				ocfs_dlm_msg * dlm_msg);
+
+bool ocfs_check_ipc_msg (__u8 * msg, __u32 msg_len);
+
+void ocfs_find_osb (__s8 * volume_id, ocfs_super ** osb);
+
+int ocfs_find_create_lockres (ocfs_super * osb, __u64 lock_id,
+			      ocfs_lock_res ** lockres);
+
+int ocfs_comm_process_vote (ocfs_super * osb, ocfs_dlm_msg * dlm_msg);
+
+int ocfs_comm_process_vote_reply (ocfs_super * osb, ocfs_dlm_msg * dlm_msg);
+
+void ocfs_dlm_recv_msg (void *val);
+
+int ocfs_comm_process_msg (__u8 * msg);
+
+int ocfs_send_dismount_msg (ocfs_super * osb, __u64 vote_map);
+
+void ocfs_comm_process_dismount (ocfs_super * osb, ocfs_dlm_msg * dlm_msg);
+
+#endif				/* _OCFSGENVOTE_H_ */

Added: trunk/libocfs/Common/inc/ocfsheartbeat.h
===================================================================
--- trunk/libocfs/Common/inc/ocfsheartbeat.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/inc/ocfsheartbeat.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,36 @@
+/*
+ * ocfsheartbeat.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSHEARTBEAT_H_
+#define _OCFSHEARTBEAT_H_
+
+void ocfs_update_publish_map (ocfs_super * osb, void *buffer, bool first_time);
+
+int ocfs_nm_thread (ocfs_super * mount_osb);
+
+int ocfs_nm_heart_beat (ocfs_super * osb, __u32 flag, bool read_publish);
+
+#endif				/* _OCFSHEARTBEAT_H_ */

Added: trunk/libocfs/Common/inc/ocfstrace.h
===================================================================
--- trunk/libocfs/Common/inc/ocfstrace.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/inc/ocfstrace.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,276 @@
+/*
+ * ocfstrace.h
+ *
+ * Trace related macros
+ *
+ * Copyright (C) 2002, 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Sunil Mushran, Manish Singh, Wim Coekaerts
+ */
+
+#ifndef  _OCFSTRACE_H_
+#define  _OCFSTRACE_H_
+
+extern __u32 debug_context;
+extern __u32 debug_level;
+extern __u32 debug_exclude;
+
+#define HI(val)            ((unsigned long)(((val) >> 16) >> 16))
+#define LO(val)            ((unsigned long)((val) & 0x00000000FFFFFFFFUL))
+
+#define HILO(val)	   HI(val), LO(val)
+
+/* Tracing Levels */
+#define OCFS_DEBUG_LEVEL_ERROR         0x00000001
+#define OCFS_DEBUG_LEVEL_TRACE         0x00000002
+
+#define OCFS_DEBUG_LEVEL_ENTRY         0x00000010
+#define OCFS_DEBUG_LEVEL_EXIT          0x00000020
+
+#define OCFS_DEBUG_LEVEL_TIMING        0x00000100
+#define OCFS_DEBUG_LEVEL_STACK         0x00000200
+
+#define OCFS_DEBUG_LEVEL_LOCKRES       0x00001000	/* get/put lockres */
+#define OCFS_DEBUG_LEVEL_MALLOC        0x00002000	/* malloc/free lockres */
+
+/* Tracing Contexts */
+#define OCFS_DEBUG_CONTEXT_INIT        0x00000001	/* ocfsgeninit.c,ocfsmain.c */
+#define OCFS_DEBUG_CONTEXT_MEM         0x00000002	/* ocfs_memcheck() in ocfsmain.c */
+
+#define OCFS_DEBUG_CONTEXT_NM          0x00000010	/* ocfsgennm.c */
+#define OCFS_DEBUG_CONTEXT_DLM         0x00000020	/* ocfsgendlm.c */
+#define OCFS_DEBUG_CONTEXT_VOTE        0x00000040	/* ocfsgenvote.c */
+#define OCFS_DEBUG_CONTEXT_IPC         0x00000080	/* ocfsipc.c */
+
+#define OCFS_DEBUG_CONTEXT_VOLCFG      0x00000100	/* ocfsgenvolcfg.c */
+#define OCFS_DEBUG_CONTEXT_HEARTBEAT   0x00000200	/* ocfsgenheartbeat.c */
+
+#define OCFS_DEBUG_CONTEXT_MOUNT       0x00001000	/* ocfsmount.c */
+#define OCFS_DEBUG_CONTEXT_SHUTDOWN    0x00002000	/* ocfsgenshutdn.c */
+#define OCFS_DEBUG_CONTEXT_CREATE      0x00004000	/* gencreate.c, create.c ?? */
+#define OCFS_DEBUG_CONTEXT_CLOSE       0x00008000	/* genclose.c, ocfsclose.c */
+
+#define OCFS_DEBUG_CONTEXT_EXTENT      0x00010000	/* ocfsgenalloc.c */
+#define OCFS_DEBUG_CONTEXT_DIRINFO     0x00020000	/* ocfsgendirnode.c */
+#define OCFS_DEBUG_CONTEXT_FILEINFO    0x00040000	/* ocfsfile.c */
+#define OCFS_DEBUG_CONTEXT_TRANS       0x00080000	/* ocfsgentrans.c */
+
+#define OCFS_DEBUG_CONTEXT_DISKIO      0x00100000	/* ocfsgenio.c */
+#define OCFS_DEBUG_CONTEXT_MISC        0x00200000	/* ocfsgenmisc.c */
+
+#define OCFS_DEBUG_CONTEXT_UTIL        0x01000000	/* ocfsgenutil.c */
+#define OCFS_DEBUG_CONTEXT_HASH        0x02000000	/* ocfshash.h */
+#define OCFS_DEBUG_CONTEXT_PORT        0x08000000	/* ocfsport.c */
+
+#define OCFS_DEBUG_CONTEXT_IOCTL       0x10000000	/* ocfsioctl.c */
+#define OCFS_DEBUG_CONTEXT_PROC        0x20000000	/* ocfsproc.c */
+#define OCFS_DEBUG_CONTEXT_IOSUP       0x40000000	/* ocfsiosup.c */
+
+
+#ifndef OCFS_DBG_TIMING
+# define DECL_U8_ARRAY(__t, __s)
+# define INIT_U8_ARRAY(__s)
+# define PRINT_STRING(__t)		printk("\n");
+# define PRINT_ENTRY(__t)	\
+		printk("(%d) ENTRY: %s", ocfs_getpid (), __FUNCTION__)
+#else
+# define DECL_U8_ARRAY(__t, __s)		__u8 (__t)[(__s)]
+# define INIT_U8_ARRAY(__s)		*(__s) = '\0'
+# define PRINT_STRING(__t)		printk("%s\n", (__t))
+# define PRINT_ENTRY(__t)	\
+		printk("(%d) %sENTRY: %s", ocfs_getpid (), (__t), __FUNCTION__)
+#endif
+
+#ifndef OCFS_DBG_TIMING
+# define GET_STACK(s)
+#else
+# define GET_STACK(s)							\
+	IF_LEVEL(OCFS_DEBUG_LEVEL_STACK) {				\
+		__s32 esp;						\
+		__asm__ __volatile__("andl %%esp,%0" : "=r" (esp) : 	\
+				     "0" (8191));			\
+		esp -= sizeof(struct task_struct);			\
+		sprintf((s), "[%ld] ", esp);				\
+	}
+#endif
+
+/* privately used macros */
+#define IF_LEVEL(level)	\
+	if ((debug_context & OCFS_DEBUG_CONTEXT) && (debug_level & level) && \
+	    ocfs_getpid()!=debug_exclude)
+				
+
+#ifndef OCFS_DBG_TIMING
+# define ENTRY_TIMING_DECLS
+# define GET_TIMING(s, hi, lo)
+#else
+# define ENTRY_TIMING_DECLS	__u32 _HI = 0, _LO = 0
+# define GET_TIMING(s, hi, lo)					\
+	do {							\
+		IF_LEVEL(OCFS_DEBUG_LEVEL_TIMING) {		\
+			__u32 _lo, _hi;				\
+			rdtsc (_lo, _hi);			\
+			if ((s) == NULL) {			\
+				(hi) = _hi; (lo) = _lo;		\
+			} else {				\
+				__u64 _b, _e;			\
+				_b = hi; _b <<= 32; _b |= lo;	\
+				_e = _hi; _e <<= 32; _e |= _lo;	\
+				_e -= _b; 			\
+				sprintf((s), " => [%u.%u]",	\
+					HI(_e), LO(_e));	\
+			}					\
+		}						\
+	} while (0)
+#endif
+
+/* IF macro */
+#define IF_TRACE(func)						\
+	do {							\
+		if ((debug_context & OCFS_DEBUG_CONTEXT) &&	\
+		    (debug_level & OCFS_DEBUG_LEVEL_TRACE))	\
+			func;					\
+	} while (0)
+
+/* TRACE disabled. ERROR macros are never disabled. */
+
+static inline void eat_value_int(int val)
+{
+	return;
+}
+
+static inline void eat_value_long(long val)
+{
+	return;
+}
+
+static inline void eat_value_ulong(unsigned long val)
+{
+	return;
+}
+
+static inline void eat_value_ptr(void *val)
+{
+	return;
+}
+
+#if !defined(TRACE)
+# define  LOG_ENTRY()
+# define  LOG_EXIT()
+# define  LOG_EXIT_STATUS(val)			eat_value_int(val)
+# define  LOG_EXIT_LONG(val)			eat_value_long(val)
+# define  LOG_EXIT_ULONG(val)			eat_value_ulong(val)
+# define  LOG_EXIT_PTR(val)			eat_value_ptr(val)
+# define  LOG_TRACE_STR(str)
+# define  LOG_TRACE_STATUS(val)			eat_value_int(val)
+# define  LOG_ENTRY_ARGS(fmt, arg...)
+# define  LOG_EXIT_ARGS(fmt, arg...)
+# define  LOG_TRACE_ARGS(fmt, arg...)
+#endif				/* !defined(TRACE) */
+
+/* TRACE enabled */
+#if defined(TRACE)
+
+/* ENTRY macros */
+/* LOG_ENTRY_ARGS()
+ *
+ * Note: The macro expects the args to be terminated by a newline.
+ */
+#define LOG_ENTRY_ARGS(fmt, arg...)					\
+	ENTRY_TIMING_DECLS;						\
+	do {								\
+		DECL_U8_ARRAY(_t, 16);					\
+		INIT_U8_ARRAY(_t);					\
+		GET_STACK(_t);						\
+		GET_TIMING(NULL, _HI, _LO);				\
+		IF_LEVEL(OCFS_DEBUG_LEVEL_ENTRY) {			\
+			PRINT_ENTRY(_t);				\
+			if (fmt==NULL)					\
+				printk("() \n");			\
+			else						\
+				printk(fmt, ##arg);			\
+		}							\
+	} while (0)
+
+#define LOG_ENTRY()            LOG_ENTRY_ARGS(NULL)
+
+
+
+/* EXIT macros */
+/* LOG_EXIT_ARGS()
+ *
+ */
+#define LOG_EXIT_ARGS(fmt, arg...)					\
+	do {								\
+		IF_LEVEL(OCFS_DEBUG_LEVEL_EXIT) {			\
+			DECL_U8_ARRAY(_t, 50);				\
+			INIT_U8_ARRAY(_t);				\
+			GET_TIMING(_t, _HI, _LO);			\
+			printk("(%d) EXIT : %s() %s",			\
+			       ocfs_getpid (), __FUNCTION__, 		\
+			       (fmt==NULL ? "" : "= "));		\
+			if (fmt!=NULL)					\
+				printk(fmt, ## arg);			\
+			PRINT_STRING(_t);				\
+		}							\
+	}  while (0)
+
+#define LOG_EXIT()             LOG_EXIT_ARGS(NULL)
+#define LOG_EXIT_STATUS(val)   LOG_EXIT_ARGS("%d ", val)
+#define LOG_EXIT_LONG(val)     LOG_EXIT_ARGS("%d ", val)
+#define LOG_EXIT_ULONG(val)    LOG_EXIT_ARGS("%u ", val)
+#define LOG_EXIT_PTR(val)      LOG_EXIT_ARGS("0x%p ", val)
+
+
+/* TRACE macros */
+/* LOG_TRACE_ARGS()
+ *
+ * Note: The macro expects the args to be terminated by a newline.
+ */
+#define LOG_TRACE_ARGS(fmt, arg...)					\
+	do {								\
+		IF_LEVEL(OCFS_DEBUG_LEVEL_TRACE) {			\
+			printk("(%d) TRACE: %s(%d) ", ocfs_getpid (),	\
+			       __FUNCTION__, __LINE__);			\
+			printk(fmt, ## arg);				\
+		}							\
+	} while (0)
+
+#define LOG_TRACE_STR(str)     LOG_TRACE_ARGS("%s\n", str)
+#define LOG_TRACE_STATUS(val)  LOG_TRACE_ARGS("%d\n", val);
+
+#endif				/* TRACE */
+
+
+
+/* ERROR macros are not compiled out */
+/* LOG_ERROR_ARGS()
+ *
+ * Note: The macro expects the args to be terminated by a newline.
+ */
+#define LOG_ERROR_ARGS(fmt, arg...)					\
+	do {								\
+		printk(KERN_ERR "(%d) ERROR: ", ocfs_getpid ());        \
+		printk(fmt, ## arg);					\
+		printk(", %s, %d\n", __FILE__, __LINE__);		\
+	} while (0)
+
+#define LOG_ERROR_STR(str)     LOG_ERROR_ARGS("%s", str)
+#define LOG_ERROR_STATUS(st)   LOG_ERROR_ARGS("status = %d", st)
+
+#endif				/* _OCFSTRACE_H_ */

Added: trunk/libocfs/Common/inc/ocfstrans.h
===================================================================
--- trunk/libocfs/Common/inc/ocfstrans.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/inc/ocfstrans.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,168 @@
+/*
+ * ocfstrans.h
+ *
+ * Logging and recovery related structures
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSTRANS_H_
+#define _OCFSTRANS_H_
+
+#define  LOG_TYPE_DISK_ALLOC      1
+#define  LOG_TYPE_DIR_NODE        2
+#define  LOG_TYPE_RECOVERY        3
+#define  LOG_CLEANUP_LOCK         4
+#define  LOG_TYPE_TRANS_START     5
+#define  LOG_TYPE_TRANS_END       6
+#define  LOG_RELEASE_BDCAST_LOCK  7
+#define  LOG_DELETE_ENTRY         8
+#define  LOG_MARK_DELETE_ENTRY    9
+#define  LOG_FREE_BITMAP          10
+#define  LOG_UPDATE_EXTENT        11
+#define  LOG_DELETE_NEW_ENTRY     12
+
+typedef struct _ocfs_free_bitmap
+{
+	__u64 length;
+	__u64 file_off;
+	__u32 type;
+	__u32 node_num;
+}
+ocfs_free_bitmap;
+
+typedef struct _ocfs_free_extent_log
+{
+	__u32 index;
+	__u8 pad[4];
+	__u64 disk_off;
+}
+ocfs_free_extent_log;
+
+#define  FREE_LOG_SIZE            150
+
+typedef struct _ocfs_free_log
+{
+	__u32 num_free_upds;
+	__u8 pad[4];
+	ocfs_free_bitmap free_bitmap[FREE_LOG_SIZE];
+}
+ocfs_free_log;
+
+typedef struct _ocfs_delete_log
+{
+	__u64 node_num;
+	__u64 ent_del;
+	__u64 parent_dirnode_off;
+	__u32 flags;
+	__u8 pad[4];
+}
+ocfs_delete_log;
+
+typedef struct _ocfs_recovery_log
+{
+	__u64 node_num;
+}
+ocfs_recovery_log;
+
+#define  DISK_ALLOC_DIR_NODE      1
+#define  DISK_ALLOC_EXTENT_NODE   2
+#define  DISK_ALLOC_VOLUME        3
+
+typedef struct _ocfs_alloc_log
+{
+	__u64 length;
+	__u64 file_off;
+	__u32 type;
+	__u32 node_num;
+}
+ocfs_alloc_log;
+
+typedef struct _ocfs_dir_log
+{
+	__u64 orig_off;
+	__u64 saved_off;
+	__u64 length;
+}
+ocfs_dir_log;
+
+typedef struct _ocfs_lock_update
+{
+	__u64 orig_off;
+	__u64 new_off;
+}
+ocfs_lock_update;
+
+#define  LOCK_UPDATE_LOG_SIZE     450
+
+typedef struct _ocfs_lock_log
+{
+	__u32 num_lock_upds;
+	__u8 pad[4];
+	ocfs_lock_update lock_upd[LOCK_UPDATE_LOG_SIZE];
+}
+ocfs_lock_log;
+
+typedef struct _ocfs_bcast_rel_log
+{
+	__u64 lock_id;
+}
+ocfs_bcast_rel_log;
+
+typedef struct _ocfs_cleanup_record
+{
+	__u64 log_id;
+	__u32 log_type;
+	__u8 pad[4];
+	union
+	{
+		ocfs_lock_log lock;
+		ocfs_alloc_log alloc;
+		ocfs_bcast_rel_log bcast;
+		ocfs_delete_log del;
+		ocfs_free_log free;
+	}
+	rec;
+}
+ocfs_cleanup_record;
+
+typedef struct _ocfs_log_record
+{
+	__u64 log_id;
+	__u32 log_type;
+	__u8 pad[4];
+	union
+	{
+		ocfs_dir_log dir;
+		ocfs_alloc_log alloc;
+		ocfs_recovery_log recovery;
+		ocfs_bcast_rel_log bcast;
+		ocfs_delete_log del;
+		ocfs_free_extent_log extent;
+	}
+	rec;
+}
+ocfs_log_record;
+
+#define  LOG_RECOVER              1
+#define  LOG_CLEANUP              2
+
+#endif				/*  _OCFSTRANS_H_ */

Added: trunk/libocfs/Common/inc/ocfsver.h
===================================================================
--- trunk/libocfs/Common/inc/ocfsver.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/inc/ocfsver.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,32 @@
+/*
+ * ocfsver.h
+ *
+ * version printing function
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSVER_H_
+#define _OCFSVER_H_
+
+void ocfs_version_print (void);
+
+#endif				/* _OCFSVER_H_ */

Added: trunk/libocfs/Common/inc/ocfsvol.h
===================================================================
--- trunk/libocfs/Common/inc/ocfsvol.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/inc/ocfsvol.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,206 @@
+/*
+ * ocfsvol.h
+ *
+ * On-disk structures. See format.h for disk layout.
+ *
+ * Copyright (C) 2002, 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSVOL_H_
+#define _OCFSVOL_H_
+
+#define  OCFS_MINOR_VERSION              (2)
+#define  OCFS_MAJOR_VERSION              (1)
+#define  OCFS_MINOR_VER_STRING           "2"
+#define  OCFS_MAJOR_VER_STRING           "1"
+
+#define  OCFS_VOLUME_SIGNATURE           "OracleCFS"
+#define  MAX_VOL_SIGNATURE_LEN		128
+#define  MAX_MOUNT_POINT_LEN		128
+
+typedef struct _ocfs_vol_disk_hdr		// CLASS
+{
+	__u32 minor_version;			// NUMBER RANGE(0,UINT_MAX)
+	__u32 major_version;			// NUMBER RANGE(0,UINT_MAX)
+	__u8 signature[MAX_VOL_SIGNATURE_LEN];	// CHAR[MAX_VOL_SIGNATURE_LEN]
+	__u8 mount_point[MAX_MOUNT_POINT_LEN];	// CHAR[MAX_MOUNT_POINT_LEN]
+	__u64 serial_num;			// NUMBER RANGE(0,ULONG_LONG_MAX)
+	/* Size of the device in bytes */           
+	__u64 device_size;			// NUMBER RANGE(0,ULONG_LONG_MAX)
+	/* Start of the volume... typically 0 */    
+	__u64 start_off;			// NUMBER RANGE(0,ULONG_LONG_MAX)
+	/* Offset to Volume Bitmap... */            
+	__u64 bitmap_off;			// NUMBER RANGE(0,ULONG_LONG_MAX)
+	/* Offset to the Publish Sector */          
+	__u64 publ_off;				// NUMBER RANGE(0,ULONG_LONG_MAX)
+	/* Offset to the Vote Sector */             
+	__u64 vote_off;				// NUMBER RANGE(0,ULONG_LONG_MAX)
+	__u64 root_bitmap_off;			// NUMBER RANGE(0,ULONG_LONG_MAX)
+	__u64 data_start_off;			// NUMBER RANGE(0,ULONG_LONG_MAX)
+	__u64 root_bitmap_size;			// NUMBER RANGE(0,ULONG_LONG_MAX)
+	__u64 root_off;				// NUMBER RANGE(0,ULONG_LONG_MAX)
+	__u64 root_size;			// NUMBER RANGE(0,ULONG_LONG_MAX)
+	/* Cluster size as specified during format */        
+	__u64 cluster_size;			// CLUSTERSIZE
+	/* Max number of nodes.... OCFS_MAXIMUM_NODES */
+	__u64 num_nodes;			// NUMBER RANGE(0,32)
+	/* Number of free clusters at format */
+	__u64 num_clusters;			// NUMBER RANGE(0,ULONG_LONG_MAX)
+	/* OCFS_DEFAULT_DIR_NODE_SIZE */
+	__u64 dir_node_size;			// NUMBER RANGE(0,ULONG_LONG_MAX)
+	/* OCFS_DEFAULT_FILE_NODE_SIZE */
+	__u64 file_node_size;			// NUMBER RANGE(0,ULONG_LONG_MAX)
+	__u64 internal_off;			// NUMBER RANGE(0,ULONG_LONG_MAX)
+	/* Offset to Node Config */
+	__u64 node_cfg_off;			// NUMBER RANGE(0,ULONG_LONG_MAX)
+	/* Size of Node Config */
+	__u64 node_cfg_size;			// NUMBER RANGE(0,ULONG_LONG_MAX)
+	/* Offset to Node Config Lock */
+	__u64 new_cfg_off;			// NUMBER RANGE(0,ULONG_LONG_MAX)
+	__u32 prot_bits;			// PERMS
+	__u32 uid;				// UID
+	__u32 gid;				// GID
+	__s32 excl_mount;			// NODENUM
+}
+ocfs_vol_disk_hdr;				// END CLASS
+
+#define DLOCK_FLAG_OPEN_MAP    (0x1)
+#define DLOCK_FLAG_LOCK        (0x2)
+#define DLOCK_FLAG_SEQ_NUM     (0x4)
+#define DLOCK_FLAG_MASTER      (0x8)
+#define DLOCK_FLAG_LAST_UPDATE (0x10)
+#define DLOCK_FLAG_ALL         (DLOCK_FLAG_OPEN_MAP | DLOCK_FLAG_LOCK | \
+                                DLOCK_FLAG_SEQ_NUM | DLOCK_FLAG_MASTER | \
+                                DLOCK_FLAG_LAST_UPDATE)
+
+typedef struct _ocfs_disk_lock			// CLASS
+{
+	__u32 curr_master;			// NODENUM
+	__u8 file_lock;				// LOCKLEVEL
+	__u64 last_write_time;			// NUMBER RANGE(0,ULONG_LONG_MAX)
+	__u64 last_read_time;			// NUMBER RANGE(0,ULONG_LONG_MAX)
+	__u32 writer_node_num;			// NODENUM
+	__u32 reader_node_num;			// NODENUM
+	__u64 oin_node_map;			// NODEBITMAP
+	__u64 dlock_seq_num;			// NUMBER RANGE(0,ULONG_LONG_MAX)
+}
+ocfs_disk_lock;					// END CLASS
+
+#define DISK_LOCK_CURRENT_MASTER(x)   ( ((ocfs_disk_lock *)x)->curr_master )
+#define DISK_LOCK_OIN_MAP(x)          ( ((ocfs_disk_lock *)x)->oin_node_map )
+#define DISK_LOCK_FILE_LOCK(x)        ( ((ocfs_disk_lock *)x)->file_lock )
+#define DISK_LOCK_LAST_READ(x)        ( ((ocfs_disk_lock *)x)->last_read_time )
+#define DISK_LOCK_LAST_WRITE(x)       ( ((ocfs_disk_lock *)x)->last_write_time )
+#define DISK_LOCK_READER_NODE(x)      ( ((ocfs_disk_lock *)x)->reader_node_num )
+#define DISK_LOCK_SEQNUM(x)           ( ((ocfs_disk_lock *)x)->dlock_seq_num )
+#define DISK_LOCK_WRITER_NODE(x)      ( ((ocfs_disk_lock *)x)->writer_node_num )
+
+#define MAX_VOL_ID_LENGTH		16
+#define MAX_VOL_LABEL_LEN		64
+#define MAX_CLUSTER_NAME_LEN		64
+
+typedef struct _ocfs_vol_label			// CLASS
+{
+	ocfs_disk_lock disk_lock;		// DISKLOCK
+	__u8 label[MAX_VOL_LABEL_LEN];		// CHAR[MAX_VOL_LABEL_LEN]
+	__u16 label_len;			// NUMBER RANGE(0,MAX_VOL_LABEL_LEN)
+	__u8 vol_id[MAX_VOL_ID_LENGTH];		// HEX[MAX_VOL_ID_LENGTH]
+	__u16 vol_id_len;			// NUMBER RANGE(0,MAX_VOL_ID_LENGTH)
+	__u8 cluster_name[MAX_CLUSTER_NAME_LEN];// CHAR[MAX_CLUSTER_NAME_LEN]
+	__u16 cluster_name_len;			// NUMBER RANGE(0,MAX_CLUSTER_NAME_LEN)
+}
+ocfs_vol_label;					// END CLASS
+
+#define OCFS_IPC_DEFAULT_PORT   7000
+
+typedef struct _ocfs_ipc_config_info		// CLASS
+{
+	__u8 type;				// NUMBER RANGE(0, 255)
+	__u8 ip_addr[MAX_IP_ADDR_LEN+1];	// CHAR[MAX_IP_ADDR_LEN+1]
+	__u32 ip_port;				// NUMBER RANGE(0,ULONG_MAX)
+	__u8 ip_mask[MAX_IP_ADDR_LEN+1];	// CHAR[MAX_IP_ADDR_LEN+1]
+}
+ocfs_ipc_config_info;				// END CLASS
+
+#define OCFS_IPC_DLM_VERSION    0x0201
+
+#define GUID_LEN		32
+#define HOSTID_LEN		20
+#define MACID_LEN		12
+/* TODO this structure will break in 64-bit.... need to pack */
+typedef union _ocfs_guid			// CLASS
+{
+	struct
+	{
+		char host_id[HOSTID_LEN];
+		char mac_id[MACID_LEN];
+	} id;
+	__u8 guid[GUID_LEN];			// CHAR[GUID_LEN]
+}
+ocfs_guid;					// END CLASS
+
+#define MAX_NODE_NAME_LENGTH    32
+
+typedef struct _ocfs_disk_node_config_info	// CLASS
+{
+	ocfs_disk_lock disk_lock;		// DISKLOCK
+	__u8 node_name[MAX_NODE_NAME_LENGTH+1];	// CHAR[MAX_NODE_NAME_LENGTH+1]
+	ocfs_guid guid;				// GUID
+	ocfs_ipc_config_info ipc_config;	// IPCONFIG
+}
+ocfs_disk_node_config_info;			// END CLASS
+
+#define NODE_CONFIG_HDR_SIGN        "NODECFG"
+#define NODE_CONFIG_SIGN_LEN        8
+#define NODE_CONFIG_VER             2
+#define NODE_MIN_SUPPORTED_VER      2
+
+typedef struct _ocfs_node_config_hdr		// CLASS
+{
+	ocfs_disk_lock disk_lock;		// DISKLOCK
+	__u8 signature[NODE_CONFIG_SIGN_LEN];	// CHAR[NODE_CONFIG_SIGN_LEN]
+	__u32 version;				// NUMBER RANGE(0,ULONG_MAX)
+	__u32 num_nodes;			// NUMBER RANGE(0,32)
+	__u32 last_node;			// NUMBER RANGE(0,32)
+	__u64 cfg_seq_num;			// NUMBER RANGE(0,ULONG_LONG_MAX)
+}
+OCFS_GCC_ATTR_PACKALGN
+ocfs_node_config_hdr;				// END CLASS
+
+/*
+** CDSL
+*/
+#define OCFS_CDSL_CREATE        (0x1)
+#define OCFS_CDSL_DELETE        (0x2)
+#define OCFS_CDSL_REVERT        (0x3)
+
+#define OCFS_FLAG_CDSL_FILE     (0x1)
+#define OCFS_FLAG_CDSL_DIR      (0x2)
+
+typedef struct _ocfs_cdsl
+{
+	__u8 name[1024];
+	__u32 flags;
+	__u32 operation;
+}
+ocfs_cdsl;
+
+#endif				/*  _OCFSVOL_H_ */

Added: trunk/libocfs/Common/ocfsgenalloc.c
===================================================================
--- trunk/libocfs/Common/ocfsgenalloc.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/ocfsgenalloc.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,2555 @@
+/*
+ * ocfsgenalloc.c
+ *
+ * Allocate and free file system structures.
+ *
+ * Copyright (C) 2002, 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifdef __KERNEL__
+#include <ocfs.h>
+#else
+#include <libocfs.h>
+#endif
+
+
+
+/* Tracing */
+#define OCFS_DEBUG_CONTEXT    OCFS_DEBUG_CONTEXT_EXTENT
+
+
+
+/*
+ * ocfs_read_file_entry()
+ *
+ * This function reads the File Entry from the disk.
+ *
+ * Returns 0 on success, < 0 on error
+ */
+int ocfs_read_file_entry (ocfs_super * osb, ocfs_file_entry * FileEntry,
+		   __u64 DiskOffset)
+{
+	int status = 0;
+
+	LOG_ENTRY_ARGS ("(osb=%p, fileentry=%p, offset=%u.%u)\n", osb, FileEntry,
+			HI (DiskOffset), LO (DiskOffset));
+
+	OCFS_ASSERT (FileEntry);
+	OCFS_ASSERT (osb);
+
+	/* Size of File Entry is one sector */
+	status =
+	    ocfs_read_metadata (osb, FileEntry, (__u32) osb->sect_size, DiskOffset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+	}
+
+	LOG_EXIT_STATUS (status);
+	return (status);
+}				/* ocfs_read_file_entry */
+
+
+/*
+ * ocfs_write_file_entry()
+ *
+ * This function writes the File Entry to the disk.
+ *
+ * Returns 0 on success, < 0 on error
+ */
+int ocfs_write_file_entry (ocfs_super * osb, ocfs_file_entry * FileEntry, __u64 Offset)
+{
+	int status = 0;
+
+	LOG_ENTRY ();
+
+	OCFS_ASSERT (FileEntry);
+	OCFS_ASSERT (osb);
+
+	LOG_TRACE_ARGS ("File offset on the disk is %u.%u\n", HI (Offset),
+			LO (Offset));
+
+	/* size of File Entry is one sector */
+	if ((DISK_LOCK_FILE_LOCK (FileEntry) == OCFS_DLM_ENABLE_CACHE_LOCK) &&
+	    (DISK_LOCK_CURRENT_MASTER (FileEntry) == osb->node_num) &&
+	    (Offset >= osb->vol_layout.bitmap_off)) {
+		status =
+		    ocfs_write_metadata (osb, FileEntry, (__u32) osb->sect_size,
+				       Offset);
+	} else {
+		status =
+		    ocfs_write_disk (osb, FileEntry, (__u32) osb->sect_size,
+				   Offset);
+	}
+
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+	}
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_write_file_entry */
+
+/*
+ * ocfs_remove_extent_map_entry()
+ *
+ * Remove an entry from the extent map
+ */
+void ocfs_remove_extent_map_entry (ocfs_super * osb,
+			  ocfs_extent_map * Map, __s64 Vbo, __u32 ByteCount)
+{
+	LOG_ENTRY ();
+
+	if ((ByteCount) && (ByteCount != 0xFFFFFFFF)) {
+		ByteCount--;
+		ByteCount >>= OCFS_LOG_SECTOR_SIZE;
+		ByteCount++;
+	}
+
+	Vbo >>= OCFS_LOG_SECTOR_SIZE;
+
+	ocfs_extent_map_remove ((ocfs_extent_map *) Map, (__s64) Vbo,
+			     (__s64) ByteCount);
+
+	LOG_EXIT ();
+	return;
+}				/* ocfs_remove_extent_map_entry */
+
+/* ocfs_allocate_new_data_node()
+ *
+ */
+int ocfs_allocate_new_data_node (ocfs_super * osb,
+		     ocfs_file_entry * FileEntry,
+		     __u64 actualDiskOffset,
+		     __u64 actualLength,
+		     ocfs_extent_group * ExtentHeader, __u64 * NewExtentOffset)
+{
+	int status = 0;
+	__u8 *tempBuf = NULL;
+	__u32 length;
+	__u32 k, i;
+	__u32 depth;
+	ocfs_extent_group *IterExtentHeader = NULL, *IterExtent;
+
+	__u32 allocSize;
+	__u64 upHeaderPtr;
+	__u64 physicalOffset;
+	__u64 fileOffset = 0;
+	__u64 numSectorsAlloc = 0;
+	__u64 lastExtPointer;
+
+	LOG_ENTRY ();
+
+	if (ExtentHeader != NULL) {
+		allocSize = (__u32) ((NUM_SECTORS_IN_LEAF_NODE +
+				    ExtentHeader->granularity) *
+				   OCFS_SECTOR_SIZE);
+
+		/* allocate contiguous blocks on disk */
+		status = ocfs_alloc_node_block (osb, allocSize, &physicalOffset,
+					 &fileOffset, (__u64 *) & numSectorsAlloc,
+					 osb->node_num, DISK_ALLOC_EXTENT_NODE);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+
+		if (fileOffset == 0) {
+			LOG_ERROR_ARGS ("offset=0, file=%s", FileEntry->filename);
+		}
+
+		k = ExtentHeader->next_free_ext;
+		ExtentHeader->extents[k].file_off = FileEntry->alloc_size;
+		ExtentHeader->extents[k].num_bytes = actualLength;
+		ExtentHeader->extents[k].disk_off = physicalOffset;
+		ExtentHeader->next_free_ext++;
+		depth = ExtentHeader->granularity;
+		upHeaderPtr = ExtentHeader->this_ext;
+	} else {
+		allocSize =
+		    ((NUM_SECTORS_IN_LEAF_NODE +
+		      FileEntry->granularity) * OCFS_SECTOR_SIZE);
+
+		/* Allocate contiguous blocks on disk */
+		status = ocfs_alloc_node_block (osb, allocSize, &physicalOffset,
+					 &fileOffset, (__u64 *) & numSectorsAlloc,
+					 osb->node_num, DISK_ALLOC_EXTENT_NODE);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+
+		if (fileOffset == 0) {
+			LOG_ERROR_ARGS ("offset=0, file=%s", FileEntry->filename);
+		}
+
+		k = FileEntry->next_free_ext;
+		FileEntry->extents[k].file_off = FileEntry->alloc_size;
+		FileEntry->extents[k].num_bytes = actualLength;
+		FileEntry->extents[k].disk_off = physicalOffset;
+		FileEntry->next_free_ext++;
+		depth = FileEntry->granularity;
+		upHeaderPtr = FileEntry->this_sector;
+	}
+
+	/* Common code between grow and this func. */
+
+	length = (__u32) OCFS_ALIGN (allocSize, osb->sect_size);
+	tempBuf = ocfs_malloc (length);
+	if (tempBuf == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto finally;
+	}
+
+	memset (tempBuf, 0, length);
+
+	lastExtPointer = FileEntry->last_ext_ptr;
+
+	/* Fill in all the headers on the way to the leaf node */
+	for (i = 0; i < depth; i++) {
+		IterExtentHeader = (ocfs_extent_group *)
+			           (tempBuf + (OCFS_SECTOR_SIZE * i));
+
+		IterExtentHeader->last_ext_ptr = lastExtPointer;
+		IterExtentHeader->up_hdr_node_ptr = upHeaderPtr;
+
+		strcpy (IterExtentHeader->signature,
+			OCFS_EXTENT_HEADER_SIGNATURE);
+
+		IterExtentHeader->type = OCFS_EXTENT_HEADER;
+		IterExtentHeader->granularity = (depth - 1 - i);
+		IterExtentHeader->extents[0].disk_off =
+		    (__u64) (physicalOffset + (OCFS_SECTOR_SIZE * (i + 1)));
+		IterExtentHeader->extents[0].file_off = FileEntry->alloc_size;
+		IterExtentHeader->extents[0].num_bytes = actualLength;
+		IterExtentHeader->next_free_ext = 1;
+		IterExtentHeader->alloc_file_off =
+		    fileOffset + (OCFS_SECTOR_SIZE * i);
+		IterExtentHeader->alloc_node = osb->node_num;
+		IterExtentHeader->this_ext =
+		    (__u64) (physicalOffset + (OCFS_SECTOR_SIZE * i));
+
+		upHeaderPtr = IterExtentHeader->this_ext;
+		lastExtPointer = IterExtentHeader->this_ext;
+	}
+
+	/* Fill in the leaf branch of the extent tree */
+	IterExtent = (ocfs_extent_group *)
+		     (tempBuf + (OCFS_SECTOR_SIZE * depth));
+	IterExtent->this_ext = (__u64) (physicalOffset +
+				      (OCFS_SECTOR_SIZE * depth));
+	IterExtent->last_ext_ptr = lastExtPointer;
+	IterExtent->up_hdr_node_ptr = upHeaderPtr;
+	(*NewExtentOffset) = IterExtent->this_ext;
+
+	if ((depth) &&
+	    (IterExtent->this_ext != IterExtentHeader->extents[0].disk_off)) {
+		LOG_ERROR_ARGS ("depth=%d, this_ext=%u.%u, disk_off=%u.%u",
+				depth, HI(IterExtent->this_ext),
+				LO(IterExtent->this_ext),
+				HI(IterExtentHeader->extents[0].disk_off),
+				LO(IterExtentHeader->extents[0].disk_off));
+	}
+
+	strcpy (IterExtent->signature, OCFS_EXTENT_DATA_SIGNATURE);
+
+	IterExtent->extents[0].file_off = FileEntry->alloc_size;
+	IterExtent->extents[0].num_bytes = actualLength;
+	IterExtent->extents[0].disk_off = actualDiskOffset;
+	IterExtent->curr_sect = 1;
+	IterExtent->max_sects = NUM_SECTORS_IN_LEAF_NODE;
+	IterExtent->next_free_ext = 1;
+	IterExtent->type = OCFS_EXTENT_DATA;
+	IterExtent->alloc_file_off = fileOffset + (OCFS_SECTOR_SIZE * depth);
+	IterExtent->alloc_node = osb->node_num;
+
+	FileEntry->last_ext_ptr = IterExtent->this_ext;
+
+	/* Write the extents to disk */
+	status = ocfs_write_disk (osb, tempBuf, allocSize, physicalOffset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	if (ExtentHeader != NULL) {
+		/* This has to be in the end... */
+		status = ocfs_write_disk (osb, ExtentHeader, OCFS_SECTOR_SIZE,
+					ExtentHeader->this_ext);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+
+		for (i = ExtentHeader->granularity + 1;
+		     i < FileEntry->granularity; i++) {
+			status =
+			    ocfs_read_extent (osb, ExtentHeader,
+					    ExtentHeader->up_hdr_node_ptr,
+					    EXTENT_HEADER);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto finally;
+			}
+
+			if (ExtentHeader->next_free_ext == 0) {
+				LOG_ERROR_STATUS (status = -EFAIL);
+				goto finally;
+			}
+
+			k = ExtentHeader->next_free_ext - 1;
+
+			ExtentHeader->extents[k].num_bytes += actualLength;
+
+			status = ocfs_write_sector (osb, ExtentHeader,
+						  ExtentHeader->this_ext);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto finally;
+			}
+		}
+		k = FileEntry->next_free_ext - 1;
+		FileEntry->extents[k].num_bytes += actualLength;
+	}
+      finally:
+	ocfs_safefree (tempBuf);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_allocate_new_data_node */
+
+/* ocfs_add_to_last_data_node()
+ *
+ */
+int ocfs_add_to_last_data_node (ocfs_super * osb,
+		   ocfs_inode * oin,
+		   ocfs_file_entry * FileEntry,
+		   __u64 actualDiskOffset,
+		   __u64 actualLength, __u32 * ExtentIndex, bool * IncreaseDepth)
+{
+	int status = 0;
+	__u32 k = 0, i;
+	__u32 length;
+	__u8 *buffer = NULL;
+	ocfs_extent_group *OcfsExtent = NULL, *OcfsExtentHeader = NULL;
+	ocfs_extent_group *AllocExtentBuf = NULL;
+	bool UpdateParent = true;
+	__u64 newExtentOff;
+
+	LOG_ENTRY ();
+
+	*IncreaseDepth = false;
+	length = (__u32) OCFS_ALIGN (sizeof (ocfs_extent_group), osb->sect_size);
+	buffer = ocfs_malloc (length);
+	if (buffer == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto bail;
+	}
+
+	status = ocfs_read_extent (osb, buffer, FileEntry->last_ext_ptr,
+				   EXTENT_DATA);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status = -EINVAL);
+		goto bail;
+	}
+
+	OcfsExtent = (ocfs_extent_group *) buffer;
+
+	/* Read the last enxtent and keep traversing upward till we find a */
+	/* free extent or we are at the top and need to create another level. */
+	if (OcfsExtent->next_free_ext > OCFS_MAX_DATA_EXTENTS) {
+		LOG_ERROR_STATUS(status = -EINVAL);
+		goto bail;
+	}
+
+	k = OcfsExtent->next_free_ext - 1;
+
+	LOG_TRACE_ARGS ("Using local_ext for extent Entry = %u\n", k);
+
+	/* Check here a case where the new allocation can be joined with */
+	/* the last Extent */
+	if (OcfsExtent->next_free_ext >= 1) {
+		if (OCFS_EXTENT_MERGEABLE
+		    (&(OcfsExtent->extents[k]), actualDiskOffset)) {
+			/* We can join the extents, just increase the len of extent */
+			OcfsExtent->extents[k].num_bytes += actualLength;
+			status = 0;
+			goto bail;
+		}
+	} else {
+		LOG_ERROR_ARGS ("next_free_ext=%d", OcfsExtent->next_free_ext);
+	}
+
+	/* We cannot merge give him the next extent */
+	k = OcfsExtent->next_free_ext;
+
+	if (k == OCFS_MAX_DATA_EXTENTS) {
+		__u64 up_hdr_node_ptr = 0;
+
+		if (FileEntry->granularity == 0) {
+			if (FileEntry->next_free_ext ==
+			    OCFS_MAX_FILE_ENTRY_EXTENTS) {
+				(*IncreaseDepth) = true;
+				goto bail;
+			} else {
+				status = ocfs_allocate_new_data_node (osb, FileEntry,
+						     actualDiskOffset,
+						     actualLength, NULL,
+						     &newExtentOff);
+				if (status < 0) {
+					LOG_ERROR_STATUS (status);
+					goto bail;
+				}
+				OcfsExtent->next_data_ext = newExtentOff;
+				UpdateParent = false;
+				FileEntry->last_ext_ptr = newExtentOff;
+				status =
+				    ocfs_write_sector (osb, OcfsExtent,
+						     OcfsExtent->this_ext);
+				if (status < 0) {
+					LOG_ERROR_STATUS (status);
+					goto bail;
+				}
+			}
+		} else {
+			i = 0;
+
+			length =
+			    (__u32) OCFS_ALIGN (sizeof (ocfs_extent_group),
+						osb->sect_size);
+			AllocExtentBuf = OcfsExtentHeader =
+			    ocfs_malloc (length);
+			if (OcfsExtentHeader == NULL) {
+				LOG_ERROR_STATUS (status = -ENOMEM);
+				goto bail;
+			}
+
+			up_hdr_node_ptr = OcfsExtent->up_hdr_node_ptr;
+
+			for (i = 0; i < FileEntry->granularity; i++) {
+				memset (OcfsExtentHeader, 0,
+					sizeof (ocfs_extent_group));
+
+				status =
+				    ocfs_read_extent (osb, OcfsExtentHeader,
+						    up_hdr_node_ptr, EXTENT_HEADER);
+				if (status < 0) {
+					LOG_ERROR_STATUS (status);
+					goto bail;
+				}
+
+				if (OcfsExtentHeader->granularity != i) {
+					LOG_ERROR_STATUS(status = -EINVAL);
+					goto bail;
+				}
+
+				if (OcfsExtentHeader->next_free_ext >
+				    OCFS_MAX_DATA_EXTENTS) {
+					LOG_ERROR_STATUS(status = -EINVAL);
+					goto bail;
+				}
+
+				if (OcfsExtentHeader->next_free_ext ==
+				    OCFS_MAX_DATA_EXTENTS) {
+					up_hdr_node_ptr =
+					    OcfsExtentHeader->up_hdr_node_ptr;
+					continue;
+				} else {
+					break;
+				}
+			}
+
+			if (i == FileEntry->granularity) {
+				if (FileEntry->next_free_ext ==
+				    OCFS_MAX_FILE_ENTRY_EXTENTS) {
+					(*IncreaseDepth) = true;
+					goto bail;
+				} else {
+					status = ocfs_allocate_new_data_node (osb, FileEntry,
+							     actualDiskOffset,
+							     actualLength, NULL,
+							     &newExtentOff);
+					if (status < 0) {
+						LOG_ERROR_STATUS (status);
+						goto bail;
+					}
+					OcfsExtent->next_data_ext =
+					    newExtentOff;
+					UpdateParent = false;
+					FileEntry->last_ext_ptr = newExtentOff;
+					status =
+					    ocfs_write_sector (osb, OcfsExtent,
+							     OcfsExtent->
+							     this_ext);
+					if (status < 0) {
+						LOG_ERROR_STATUS (status);
+						goto bail;
+					}
+				}
+				goto bail;
+			} else {
+				status = ocfs_allocate_new_data_node (osb, FileEntry,
+						     actualDiskOffset,
+						     actualLength,
+						     OcfsExtentHeader,
+						     &newExtentOff);
+				if (status < 0) {
+					LOG_ERROR_STATUS (status);
+					goto bail;
+				}
+				OcfsExtent->next_data_ext = newExtentOff;
+				UpdateParent = false;
+				FileEntry->last_ext_ptr = newExtentOff;
+				status =
+				    ocfs_write_sector (osb, OcfsExtent,
+						     OcfsExtent->this_ext);
+				if(status < 0) {
+					LOG_ERROR_STATUS (status);
+					goto bail;
+				}
+			}
+		}
+	} else {
+		/* FileOffset for the new Extent will be equal to the previous */
+		/* allocation size of file */
+		OcfsExtent->extents[k].file_off = FileEntry->alloc_size;
+		OcfsExtent->extents[k].num_bytes = actualLength;
+		OcfsExtent->extents[k].disk_off = actualDiskOffset;
+		OcfsExtent->next_free_ext++;
+	}
+
+      bail:
+	if (status >= 0 && !(*IncreaseDepth) && UpdateParent) {
+		status =
+		    ocfs_write_sector (osb, OcfsExtent, OcfsExtent->this_ext);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+
+		for (i = 0; i < FileEntry->granularity; i++) {
+			OcfsExtentHeader = (ocfs_extent_group *) buffer;
+			status = ocfs_read_extent (osb, buffer,
+						 OcfsExtentHeader->up_hdr_node_ptr,
+						 EXTENT_HEADER);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto finally;
+			}
+
+			OcfsExtentHeader = (ocfs_extent_group *) buffer;
+
+			if (OcfsExtentHeader->next_free_ext == 0) {
+				LOG_ERROR_STATUS (status = -EFAIL);
+				goto finally;
+			}
+
+			k = OcfsExtentHeader->next_free_ext - 1;
+
+			OcfsExtentHeader->extents[k].num_bytes +=
+			    actualLength;
+
+			status = ocfs_write_sector (osb, OcfsExtentHeader,
+						  OcfsExtentHeader->this_ext);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto finally;
+			}
+		}
+
+		k = FileEntry->next_free_ext - 1;
+
+		FileEntry->extents[k].num_bytes += actualLength;
+	}
+
+      finally:
+	ocfs_safefree (buffer);
+	ocfs_safefree (AllocExtentBuf);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_add_to_last_data_node */
+
+/* ocfs_update_last_data_extent()
+ *
+ */
+int ocfs_update_last_data_extent (ocfs_super * osb,
+		      ocfs_file_entry * FileEntry, __u64 NextDataOffset)
+{
+	int status = 0;
+	__u32 length = 0;
+	__u8 *buffer = NULL;
+	ocfs_extent_group *OcfsExtent;
+
+	LOG_ENTRY ();
+
+	length = (__u32) OCFS_ALIGN (sizeof (ocfs_extent_group), osb->sect_size);
+	buffer = ocfs_malloc (length);
+	if (buffer == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto finally;
+	}
+
+	status = ocfs_read_extent (osb, buffer, FileEntry->last_ext_ptr,
+				   EXTENT_DATA);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	OcfsExtent = (ocfs_extent_group *) buffer;
+
+	if (OcfsExtent->next_data_ext != 0) {
+		LOG_ERROR_ARGS ("fe->last_ext_ptr=%u.%u, next_data_ext=%u.%u",
+				HI(FileEntry->last_ext_ptr),
+				LO(FileEntry->last_ext_ptr),
+				HI(OcfsExtent->next_data_ext),
+				LO(OcfsExtent->next_data_ext));
+	}
+
+	OcfsExtent->next_data_ext = NextDataOffset;
+
+	status = ocfs_write_sector (osb, buffer, FileEntry->last_ext_ptr);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+      finally:
+	ocfs_safefree (buffer);
+
+	LOG_EXIT_STATUS (status);
+	return (status);
+}				/* ocfs_update_last_data_extent */
+
+
+/*
+ * ocfs_update_uphdrptr()
+ *
+ */
+int ocfs_update_uphdrptr(ocfs_super *osb, ocfs_file_entry *fe,
+			 __u64 new_up_hdr_ptr)
+{
+	int status = 0;
+	int len;
+	int i;
+	__u8 *buffer = NULL;
+	ocfs_extent_group *extent;
+	__u64 offset;
+
+	LOG_ENTRY ();
+
+	len = OCFS_ALIGN (sizeof (ocfs_extent_group), osb->sect_size);
+	buffer = ocfs_malloc (len);
+	if (buffer == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto bail;
+	}
+
+	for (i = 0; i < OCFS_MAX_FILE_ENTRY_EXTENTS; ++i) {
+		offset = fe->extents[i].disk_off;
+
+		status = ocfs_read_sector (osb, buffer, offset);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto bail;
+		}
+
+		extent = (ocfs_extent_group *) buffer;
+
+		if (extent->up_hdr_node_ptr != fe->this_sector)
+			LOG_ERROR_ARGS ("fe->this_sector=%u.%u, uphdrptr=%u.%u",
+					HI(fe->this_sector),
+					LO(fe->this_sector),
+					HI(extent->up_hdr_node_ptr),
+					LO(extent->up_hdr_node_ptr));
+
+		extent->up_hdr_node_ptr = new_up_hdr_ptr;
+
+		status = ocfs_write_sector (osb, buffer, offset);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto bail;
+		}
+	}
+
+      bail:
+	ocfs_safefree (buffer);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_update_uphdrptr */
+
+
+/* ocfs_grow_extent_tree()
+ *
+ */
+int ocfs_grow_extent_tree (ocfs_super * osb,
+		ocfs_file_entry * FileEntry,
+		__u64 actualDiskOffset, __u64 actualLength)
+{
+	int status = 0;
+	__s32 k, i;
+	__u32 length = 0;
+	__u32 numSectorsAlloc = 0;
+	__u8 *buffer = NULL;
+	ocfs_extent_group *OcfsExtent = NULL;
+	ocfs_extent_group *ExtentHeader = NULL;
+	__u64 physicalOffset;
+	__u64 fileOffset = 0;
+	__u64 upHeaderPtr, lastExtentPtr;
+	__u32 AllocSize;
+	__u64 new_up_hdr_ptr = 0;
+
+	LOG_ENTRY ();
+
+	AllocSize = ((FileEntry->granularity + 2) * OCFS_SECTOR_SIZE);
+
+	/* Allocate the space from the Extent file. This function should */
+	/* return contigous disk blocks requested. */
+	status = ocfs_alloc_node_block (osb, AllocSize, &physicalOffset,
+				 &fileOffset, (__u64 *) & numSectorsAlloc,
+				 osb->node_num, DISK_ALLOC_EXTENT_NODE);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	if (fileOffset == 0) {
+		LOG_TRACE_ARGS ("offset=0, file=%s\n", FileEntry->filename);
+	}
+
+	if (physicalOffset == 0) {
+		LOG_ERROR_STATUS(status = -ENOMEM);
+		goto finally;
+	}
+
+	length = (__u32) OCFS_ALIGN (AllocSize, osb->sect_size);
+	buffer = ocfs_malloc (length);
+	if (buffer == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto finally;
+	}
+
+	memset (buffer, 0, length);
+
+	OcfsExtent = (ocfs_extent_group *) buffer;
+
+	/* Copy the File Entry information in to the newly allocated sector */
+	for (k = 0; k < OCFS_MAX_FILE_ENTRY_EXTENTS; k++) {
+		OcfsExtent->extents[k].file_off =
+		    FileEntry->extents[k].file_off;
+		OcfsExtent->extents[k].num_bytes =
+		    FileEntry->extents[k].num_bytes;
+		OcfsExtent->extents[k].disk_off =
+		    FileEntry->extents[k].disk_off;
+	}
+
+	OcfsExtent->last_ext_ptr = FileEntry->last_ext_ptr;
+
+	lastExtentPtr = FileEntry->last_ext_ptr;
+
+	OcfsExtent->this_ext = new_up_hdr_ptr = physicalOffset;
+	OcfsExtent->alloc_file_off = fileOffset;
+	OcfsExtent->alloc_node = osb->node_num;
+	OcfsExtent->next_data_ext = 0;
+
+	FileEntry->local_ext = false;
+	FileEntry->granularity++;
+
+	LOG_TRACE_ARGS ("Granularity is: %d\n", FileEntry->granularity);
+
+	/* If granularity is zero now, the for loop will not execute. */
+	/* First time a file is created ,granularity = -1 and local_ext flag */
+	/* is set to true */
+
+	upHeaderPtr = FileEntry->this_sector;
+
+	for (i = 0; i < FileEntry->granularity; i++) {
+		ExtentHeader =
+		    (ocfs_extent_group *) (buffer + (OCFS_SECTOR_SIZE * i));
+		ExtentHeader->type = OCFS_EXTENT_HEADER;
+		ExtentHeader->granularity = (FileEntry->granularity - 1) - i;
+
+		strcpy (ExtentHeader->signature, OCFS_EXTENT_HEADER_SIGNATURE);
+
+		if (i == 0) {
+			ExtentHeader->extents[OCFS_MAX_FILE_ENTRY_EXTENTS].
+			    disk_off = physicalOffset + OCFS_SECTOR_SIZE;
+			ExtentHeader->extents[OCFS_MAX_FILE_ENTRY_EXTENTS].
+			    file_off = FileEntry->alloc_size;
+			ExtentHeader->extents[OCFS_MAX_FILE_ENTRY_EXTENTS].
+			    num_bytes = actualLength;
+
+			ExtentHeader->next_free_ext =
+			    OCFS_MAX_FILE_ENTRY_EXTENTS + 1;
+			ExtentHeader->this_ext = physicalOffset;
+			ExtentHeader->last_ext_ptr = lastExtentPtr;
+			ExtentHeader->up_hdr_node_ptr = upHeaderPtr;
+
+			upHeaderPtr = ExtentHeader->this_ext;
+			lastExtentPtr = ExtentHeader->this_ext;
+		} else {
+			ExtentHeader->extents[0].disk_off =
+			    physicalOffset + (OCFS_SECTOR_SIZE * (i + 1));
+			ExtentHeader->extents[0].file_off =
+			    FileEntry->alloc_size;
+			ExtentHeader->extents[0].num_bytes = actualLength;
+			ExtentHeader->next_free_ext = 1;
+			ExtentHeader->alloc_file_off =
+			    fileOffset + (OCFS_SECTOR_SIZE * i);
+			ExtentHeader->alloc_node = osb->node_num;
+			ExtentHeader->this_ext =
+			    physicalOffset + (OCFS_SECTOR_SIZE * i);
+			ExtentHeader->up_hdr_node_ptr = upHeaderPtr;
+			ExtentHeader->last_ext_ptr = lastExtentPtr;
+
+			upHeaderPtr = ExtentHeader->this_ext;
+			lastExtentPtr = ExtentHeader->this_ext;
+		}
+	}
+
+	/* Update the Data Segment */
+	OcfsExtent = (ocfs_extent_group *) (buffer + (OCFS_SECTOR_SIZE *
+						      FileEntry->granularity));
+
+	i = (FileEntry->granularity) ? 0 : OCFS_MAX_FILE_ENTRY_EXTENTS;
+
+	LOG_TRACE_ARGS ("EntryAvailable is: %d\n", OcfsExtent->next_free_ext);
+
+	/* For the time being we are assuming that the newly allocated Extent */
+	/* will have one more entry to accomodate the latest allocation */
+
+	strcpy (OcfsExtent->signature, OCFS_EXTENT_DATA_SIGNATURE);
+
+	OcfsExtent->extents[i].file_off = FileEntry->alloc_size;
+	OcfsExtent->extents[i].num_bytes = actualLength;
+	OcfsExtent->extents[i].disk_off = actualDiskOffset;
+	OcfsExtent->curr_sect = 1;
+	OcfsExtent->max_sects = NUM_SECTORS_IN_LEAF_NODE;
+	OcfsExtent->type = OCFS_EXTENT_DATA;
+	OcfsExtent->next_free_ext = i + 1;
+	OcfsExtent->alloc_file_off =
+	    fileOffset + (FileEntry->granularity * OCFS_SECTOR_SIZE);
+	OcfsExtent->alloc_node = osb->node_num;
+	OcfsExtent->this_ext =
+	    physicalOffset + (FileEntry->granularity * OCFS_SECTOR_SIZE);
+	OcfsExtent->up_hdr_node_ptr = upHeaderPtr;
+	OcfsExtent->last_ext_ptr = lastExtentPtr;
+	OcfsExtent->next_data_ext = 0;
+
+	upHeaderPtr = OcfsExtent->this_ext;
+	lastExtentPtr = OcfsExtent->this_ext;
+
+	/* We assume that the AllocSize passed in is Sector aligned */
+
+	status = ocfs_write_disk (osb, buffer, AllocSize, physicalOffset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	/* Update the Previous Last Data Extent with this new Data Extent Pointer */
+	if (FileEntry->last_ext_ptr != 0) {
+		status =
+		    ocfs_update_last_data_extent (osb, FileEntry, OcfsExtent->this_ext);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+	}
+
+	/* Update the uphdrptr of the three extents pointed to by fe */
+	if (FileEntry->granularity > 0) {
+		status = ocfs_update_uphdrptr(osb, FileEntry, new_up_hdr_ptr);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+	}
+
+	/* Clear all the extent information from File Entry */
+	for (i = 0; i < OCFS_MAX_FILE_ENTRY_EXTENTS; i++) {
+		FileEntry->extents[i].file_off = 0;
+		FileEntry->extents[i].num_bytes = 0;
+		FileEntry->extents[i].disk_off = 0;
+	}
+
+	/* Update the File Entry Extent */
+	FileEntry->local_ext = false;
+
+	FileEntry->extents[0].file_off = 0;
+	FileEntry->extents[0].num_bytes = FileEntry->alloc_size +
+	    actualLength;
+	FileEntry->extents[0].disk_off = physicalOffset;
+	FileEntry->last_ext_ptr = lastExtentPtr;
+	FileEntry->next_free_ext = 1;
+
+      finally:
+	ocfs_safefree (buffer);
+
+	LOG_EXIT_STATUS (status);
+	return (status);
+}				/* ocfs_grow_extent_tree */
+
+/*
+ * ocfs_allocate_extent()
+ *
+ */
+int ocfs_allocate_extent (ocfs_super * osb,
+		    ocfs_inode * oin,
+		    ocfs_file_entry * FileEntry,
+		    __u64 actualDiskOffset, __u64 actualLength)
+{
+	int status = 0;
+	bool IncreaseTreeDepth = false;
+	__u32 k = 0;
+
+	LOG_ENTRY ();
+
+	/* Don't do an Assertion on oin as it can NULL also in some cases. */
+	OCFS_ASSERT (FileEntry);
+
+	if (!IS_VALID_FILE_ENTRY (FileEntry)) {
+		LOG_ERROR_STATUS(status = -EINVAL);
+		goto finally;
+	}
+
+	if (FileEntry->local_ext) {
+		/* We are still using the local extents of File Entry */
+		if (FileEntry->next_free_ext > OCFS_MAX_FILE_ENTRY_EXTENTS) {
+			LOG_ERROR_STATUS(status = -EINVAL);
+			goto finally;
+		}
+
+		if (FileEntry->next_free_ext >= 1) {
+			k = FileEntry->next_free_ext - 1;
+
+			LOG_TRACE_ARGS
+			    ("Using local_ext for extent Entry = %u\n", k);
+
+			/* Check here a case where the new allocation can be */
+			/* joined with the last extent. */
+			if (OCFS_EXTENT_MERGEABLE
+			    (&FileEntry->extents[k], actualDiskOffset)) {
+				/* We can join the extents, just increase the len of extent */
+				FileEntry->extents[k].num_bytes += actualLength;
+				status = 0;
+				goto finally;
+			}
+		}
+
+		/* We cannot merge give him the next extent */
+		k = FileEntry->next_free_ext;
+		if (k == OCFS_MAX_FILE_ENTRY_EXTENTS) {
+			IncreaseTreeDepth = true;
+		} else {
+			/* file_off for the new extent will be equal to the previous */
+			/* allocation size of file */
+			FileEntry->extents[k].file_off = FileEntry->alloc_size;
+			FileEntry->extents[k].num_bytes = actualLength;
+			FileEntry->extents[k].disk_off = actualDiskOffset;
+			FileEntry->next_free_ext++;
+
+			status = 0;
+			goto finally;
+		}
+	} else {
+		if (FileEntry->granularity > 3)
+			LOG_ERROR_ARGS ("granularity=%d", FileEntry->granularity);
+
+		/* This File is no longer using Local Extents */
+		status = ocfs_add_to_last_data_node (osb, oin, FileEntry,
+						     actualDiskOffset, actualLength,
+						     &k, &IncreaseTreeDepth);
+		if (status < 0) {
+			LOG_ERROR_STATUS(status);
+			goto finally;
+		}
+	}
+
+	if (IncreaseTreeDepth) {
+		status = ocfs_grow_extent_tree (osb, FileEntry,
+						actualDiskOffset, actualLength);
+		if (status < 0) {
+			LOG_ERROR_STATUS(status);
+			goto finally;
+		}
+	}
+
+      finally:
+	if ((status == 0) && (oin != NULL)) {
+		__s64 Vbo = 0;
+		__s64 Lbo = 0;
+
+		/* Add this Entry in to extent map. If a new mapping run to be added */
+		/* overlaps an existing mapping run, ocfs_add_extent_map_entry merges */
+		/* them into a single mapping run.So just adding this entry will be fine. */
+		Vbo = FileEntry->alloc_size;
+		Lbo = actualDiskOffset;
+
+		/* Add the Entry to the extent map list */
+		if (!ocfs_add_extent_map_entry (osb, &oin->map, Vbo, Lbo,
+						actualLength))
+			LOG_ERROR_STATUS (status = -EFAIL);
+	}
+
+	/* ?? We should update the Filesize and allocation size here */
+
+	LOG_EXIT_STATUS (status);
+	return (status);
+}				/* ocfs_allocate_extent */
+
+#if 0
+/*
+ * ocfs_check_for_extent_merge()
+ *
+ * In order to optimize the usage of Extents Per file, ocfs tries to merge
+ * contigous allocations of same file. This function is called whever a
+ * new allocation is added in order to check if it is possible to merge
+ * it with the previous allocation.
+ *
+ * Returns true if possible, false, if not.
+ */
+bool ocfs_check_for_extent_merge (ocfs_alloc_ext * LastExtent, __u64 ActualDiskOffset)
+{
+	bool ret = false;
+
+	LOG_ENTRY ();
+
+	/* Check here a case where the new allocation can be */
+	/* joined with the last extent. */
+
+	if ((LastExtent->disk_off +
+	     LastExtent->num_bytes) == ActualDiskOffset) {
+		ret = true;
+	}
+
+	LOG_EXIT_ULONG (ret);
+	return ret;
+}				/* ocfs_check_for_extent_merge */
+#endif
+
+/*
+ * ocfs_get_next_extent_map_entry()
+ *
+ * This routine looks up the existing mapping of VBO to LBO for a  file.
+ * The information it queries is either stored in the extent map field
+ * of the oin or is stored in the allocation file and needs to be
+ * retrieved, decoded and updated in the extent map.
+ *
+ */
+bool ocfs_get_next_extent_map_entry (ocfs_super * osb,
+			   ocfs_extent_map * Map,
+			   __u32 RunIndex, __s64 * Vbo, __s64 * Lbo,
+			   __u32 * SectorCount)
+{
+	bool Results;
+	__s64 LiVbo;
+	__s64 LiLbo;
+	__s64 LiSectorCount;
+
+	LOG_ENTRY ();
+
+	LiLbo = 0;
+
+	Results = ocfs_extent_map_next_entry (Map, RunIndex, &LiVbo, &LiLbo,
+					  &LiSectorCount);
+
+	*Vbo = ((__s64) LiVbo) << OCFS_LOG_SECTOR_SIZE;
+
+	if (((__u32) LiLbo) != -1) {
+		*Lbo = ((__s64) LiLbo) << OCFS_LOG_SECTOR_SIZE;
+	} else {
+		Results = false;
+		*Lbo = 0;
+	}
+
+	*SectorCount = ((__u32) LiSectorCount) << OCFS_LOG_SECTOR_SIZE;
+
+	if ((*SectorCount == 0) && (LiSectorCount != 0)) {
+		*SectorCount = (__u32) - 1;	/* it overflowed */
+		Results = false;
+	}
+
+	LOG_EXIT_ULONG (Results);
+	return Results;
+}				/* ocfs_get_next_extent_map_entry  */
+
+
+/*
+ * ocfs_update_all_headers()
+ *
+ */
+int ocfs_update_all_headers (ocfs_super * osb, ocfs_extent_group * AllocExtent,
+			     __u64 FileSize, ocfs_file_entry *fe)
+{
+	int status = 0;
+	__u64 upHeaderPtr;
+	__u32 i = 0;
+	ocfs_extent_group *ExtentHeader = NULL;
+	ocfs_file_entry *FileEntry = NULL;
+
+	LOG_ENTRY ();
+
+	status = ocfs_write_sector (osb, AllocExtent, AllocExtent->this_ext);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto finally;
+	}
+
+	ExtentHeader = AllocExtent;
+
+	while (1) {
+		upHeaderPtr = ExtentHeader->up_hdr_node_ptr;
+
+		memset (ExtentHeader, 0, OCFS_SECTOR_SIZE);
+
+		status = ocfs_read_sector (osb, ExtentHeader, upHeaderPtr);
+		if (status < 0) {
+			LOG_ERROR_STATUS(status = -EINVAL);
+			goto finally;
+		}
+
+		if (IS_VALID_EXTENT_HEADER (ExtentHeader)) {
+			for (i = 0; i < AllocExtent->next_free_ext; i++) {
+				if ((AllocExtent->extents[i].file_off +
+				     AllocExtent->extents[i].num_bytes) >
+				    FileSize) {
+					if (AllocExtent->extents[i].file_off >
+					    FileSize) {
+						AllocExtent->extents[i].
+						    file_off =
+						    AllocExtent->extents[i].
+						    num_bytes = 0;
+						AllocExtent->next_free_ext = i;
+						break;
+					} else {
+						AllocExtent->extents[i].
+						    num_bytes -=
+						    ((AllocExtent->extents[i].
+						      file_off +
+						      AllocExtent->extents[i].
+						      num_bytes) - FileSize);
+						AllocExtent->next_free_ext =
+						    i + 1;
+						break;
+					}
+				}
+			}
+			status = ocfs_write_sector (osb, AllocExtent, AllocExtent->this_ext);
+			continue;
+		} else {
+			FileEntry = fe;
+
+			if (!IS_VALID_FILE_ENTRY (FileEntry)) {
+				LOG_ERROR_STATUS(status = -EFAIL);
+				goto finally;
+			}
+
+			for (i = 0; i < FileEntry->next_free_ext; i++) {
+				if ((FileEntry->extents[i].file_off +
+				     FileEntry->extents[i].num_bytes) >
+				    FileSize) {
+					if (FileEntry->extents[i].file_off >
+					    FileSize) {
+						FileEntry->extents[i].file_off =
+						    FileEntry->extents[i].
+						    num_bytes = 0;
+						FileEntry->next_free_ext = i;
+						break;
+					} else {
+						FileEntry->extents[i].
+						    num_bytes -=
+						    ((FileEntry->extents[i].
+						      file_off +
+						      FileEntry->extents[i].
+						      num_bytes) - FileSize);
+						FileEntry->next_free_ext =
+						    i + 1;
+						break;
+					}
+				}
+			}
+			break;
+		}
+	}
+
+finally:
+	LOG_EXIT_STATUS (status);
+	return status;
+}  /* ocfs_update_all_headers */
+
+
+/*
+ * _write_free_extent_log()
+ *  removed most logging from this function as it overwhelms printk on redhat.
+ */
+
+int _write_free_extent_log(ocfs_super *osb, ocfs_cleanup_record *CleanupLogRec, 
+                                  __u32 len, __u32 fileoff, __u32 nodenum, __u32 thistype)
+{
+        __u32 numUpdt;
+        int status=0;
+        ocfs_free_bitmap *fb;
+
+//	LOG_ENTRY ();
+//	LOG_TRACE_ARGS("len = %u, fileoff = %u, nodenum = %u\n", len, fileoff, nodenum);
+
+	if (thistype == DISK_ALLOC_EXTENT_NODE)
+	        LOG_TRACE_ARGS("Removing metadata at alloc_fileoff=%u, nodenum=%u\n", fileoff, nodenum);
+        numUpdt = CleanupLogRec->rec.free.num_free_upds; 
+        if (numUpdt >= FREE_LOG_SIZE) { 
+                status = ocfs_write_node_log (osb, (ocfs_log_record *) CleanupLogRec, 
+                                              osb->node_num, LOG_CLEANUP); 
+                if (status < 0) { 
+                        LOG_ERROR_STATUS (status);
+                        return status;
+                } 
+                numUpdt = CleanupLogRec->rec.free.num_free_upds = 0; 
+        }
+        fb = &(CleanupLogRec->rec.free.free_bitmap[numUpdt]); 
+        fb->length = len; 
+        fb->file_off = fileoff; 
+	//fb->type = DISK_ALLOC_VOLUME;
+        fb->type = thistype; 
+        fb->node_num = nodenum; 
+        (CleanupLogRec->rec.free.num_free_upds)++; 
+
+	// LOG_EXIT_STATUS (status);
+        return status;
+} 			/* _write_free_extent_log */
+
+ 
+int _squish_extent_entries(ocfs_super *osb, ocfs_alloc_ext *extarr, __u8 *freeExtent, 
+                                  ocfs_cleanup_record *CleanupLogRec, __u64 FileSize, bool flag) 
+{
+        int status = 0;
+	bool FirstTime = true;
+        ocfs_alloc_ext *ext; 
+        __u32 i, csize = osb->vol_layout.cluster_size, 
+            numBitsAllocated = 0, bitmapOffset = 0, 
+            firstfree = *freeExtent;
+        __u64 bytes, foff, doff, 
+            dstart = osb->vol_layout.data_start_off, 
+            diskOffsetTobeFreed, lengthTobeFreed = 0, 
+            actualSize = 0, origLength = 0;
+
+	LOG_ENTRY ();
+
+        firstfree = *freeExtent;
+        for (i = 0; i < firstfree; i++) { 
+                ext = &(extarr[i]); 
+                bytes = ext->num_bytes; 
+                foff = ext->file_off; 
+                doff = ext->disk_off; 
+                actualSize = (bytes + foff);
+                if (flag || actualSize > FileSize) { 
+                        if (flag || foff >= FileSize) { 
+                                if (!flag && FirstTime) { 
+                                        *freeExtent = i; 
+                                        FirstTime = false; 
+                                } 
+                                numBitsAllocated = (__u32) (bytes/csize); 
+                                bitmapOffset = (__u32) ((doff - dstart) / csize); 
+                                ext->num_bytes = ext->disk_off = ext->file_off = 0; 
+                        } else { 
+                                if (FirstTime) { 
+                                        *freeExtent = i + 1; 
+                                        FirstTime = false; 
+                                } 
+                                origLength = bytes; 
+                                ext->num_bytes = bytes = FileSize - foff; 
+                                lengthTobeFreed = origLength - bytes; 
+                                if (lengthTobeFreed == 0) { 
+                                        continue; 
+                                } 
+                                numBitsAllocated = (__u32) (lengthTobeFreed / csize); 
+                                diskOffsetTobeFreed = doff + bytes; 
+                                bitmapOffset = (__u32) ((diskOffsetTobeFreed - dstart) / csize); 
+                        } 
+                        status = _write_free_extent_log(osb, CleanupLogRec, numBitsAllocated, 
+                                                        bitmapOffset, -1, DISK_ALLOC_VOLUME); 
+                        if (status < 0) {
+				LOG_ERROR_STATUS (status);
+                                break;
+			}
+                }
+        } 
+
+	LOG_EXIT_STATUS (status);
+        return status; 
+}
+
+/* used by ocfs_kill_this_tree and ocfs_split_this_tree */
+/* This value needs to be removed in a future version and set to
+ * granularity + 1, dynamically */
+#define OCFS_TREE_STACK_SIZE 8
+
+/*
+ * ocfs_kill_this_tree
+ *
+ * Given an extent_group (can be a DAT or header), delete everything,
+ * including itself, it's children, and any data blocks they point to.
+ * Works fine with any granularity (up to 4, in which case we'd need
+ * more stack space)
+ */
+
+/* We can't recurse, so we keep a simple stack of ocfs_extent_groups. */
+int ocfs_kill_this_tree(ocfs_super *osb, ocfs_extent_group *extent_grp, ocfs_cleanup_record *CleanupLogRec) {
+       int status = -EFAIL;
+       int i;
+       __u32 victim;
+       __u32 size = OCFS_ALIGN (sizeof (ocfs_extent_group), osb->sect_size);
+       __u32 csize = osb->vol_layout.cluster_size;
+       __u64 dstart = osb->vol_layout.data_start_off;
+       __u32 num_sectors = 0, bitmap_offset = 0;
+       ocfs_alloc_ext *ext;
+       ocfs_extent_group * grp_stack[OCFS_TREE_STACK_SIZE];
+       ocfs_extent_group * AllocExtent; /* convenience, points to TOS */
+       int tos = 0;
+
+       LOG_ENTRY();
+
+       for (i =0; i < OCFS_TREE_STACK_SIZE; i++)
+               grp_stack[i] = NULL;
+
+       grp_stack[tos] = extent_grp;
+
+       do {
+               AllocExtent = grp_stack[tos];
+
+               if (!IS_VALID_EXTENT_DATA(AllocExtent) &&
+                   !IS_VALID_EXTENT_HEADER(AllocExtent)) {
+                       LOG_ERROR_STR("Invalid extent group!");
+                       goto bail;
+               }
+
+               if (IS_VALID_EXTENT_DATA(AllocExtent)) {
+                       LOG_TRACE_ARGS("found some data to free (%u.%u)\n", HI(AllocExtent->this_ext), LO(AllocExtent->this_ext));
+                       for(i = 0; i < AllocExtent->next_free_ext; i++) {
+                               /* Free the data associated with each header */
+                               ext = &AllocExtent->extents[i];
+                               num_sectors = (__u32) (ext->num_bytes / csize);
+                               bitmap_offset = (__u32) ((ext->disk_off - dstart) / csize);
+                               status = _write_free_extent_log(osb, CleanupLogRec, num_sectors, bitmap_offset, -1, DISK_ALLOC_VOLUME);
+                               if (status < 0) {
+                                       LOG_ERROR_STATUS (status);
+                                       goto bail;
+                               }
+                       }
+                       /* Pop one off the stack */
+                       tos--;
+               } else {
+                       /* Ok, we're a header. */
+
+                       /* Did we already kill all his children, or
+                        * are they already dead? */
+                       if (AllocExtent->next_free_ext == 0) {
+                               tos--;
+                               LOG_TRACE_ARGS("Popping this header (%u.%u)\n",
+HI(AllocExtent->this_ext), LO(AllocExtent->this_ext), AllocExtent->next_free_ext);
+                               goto free_meta;
+                       }
+
+                       /* We're gonna read in our last used extent
+                        * and put him at the top of the stack. We
+                        * also update our next_free_ext so that next
+                        * time we read in the next to last one and so
+                        * on until we've finished all of them
+                        */
+
+                       /* grow the stack, only allocating mem if we
+                        * haven't already */
+                       tos++;
+                       if (grp_stack[tos] == NULL)
+                               grp_stack[tos] = ocfs_malloc(size);
+                       else
+                               memset(grp_stack[tos], 0, size);
+                       victim = AllocExtent->next_free_ext - 1;
+                       ext = &AllocExtent->extents[victim];
+
+                       status = ocfs_read_sector(osb, grp_stack[tos], ext->disk_off);
+                       if (status < 0) {
+                               LOG_ERROR_STATUS (status);
+                               goto bail;
+                       }
+                       AllocExtent->next_free_ext--;
+                       LOG_TRACE_ARGS("Pushing this header (%u.%u)\n", HI(grp_stack[tos]->this_ext), LO(grp_stack[tos]->this_ext));
+
+                       /* We only want to free on our way up the tree */
+                       continue;
+               }
+
+       free_meta:
+               /* Free the metadata associated with this extent group */
+               status = _write_free_extent_log(osb, CleanupLogRec, 1, AllocExtent->alloc_file_off, AllocExtent->alloc_node, DISK_ALLOC_EXTENT_NODE);
+               if (status < 0) {
+                       LOG_ERROR_STATUS (status);
+                       goto bail;
+               }
+       } while (tos >= 0);
+
+       status = 0;
+bail:
+       /* Free the stack. We never free the bottom of the stack
+        * because we were passed that guy from the caller */
+       for(i = 1; i < OCFS_TREE_STACK_SIZE; i++)
+               ocfs_safefree(grp_stack[i]);
+
+       LOG_EXIT_STATUS (status);
+       return(status);
+}
+
+
+int ocfs_fix_extent_group(ocfs_super *osb, ocfs_extent_group *group) {
+       ocfs_alloc_ext *ext;
+       int status=-EFAIL;
+       int i;
+
+       LOG_ENTRY ();
+
+       if (!group) {
+               LOG_ERROR_STR("Invalid extent group (NULL)!");
+               goto bail;
+       }
+
+       if (!IS_VALID_EXTENT_DATA(group) &&
+           !IS_VALID_EXTENT_HEADER(group)) {
+               LOG_ERROR_STR("Invalid extent group!");
+               goto bail;
+       }
+
+       ext = group->extents;
+
+       for(i=group->next_free_ext; i < OCFS_MAX_DATA_EXTENTS; i++) {
+               ext[i].num_bytes = 0;
+               ext[i].disk_off = 0;
+               ext[i].file_off = 0;
+       }
+
+       /* Alright, write this guy back out now */
+       if (osb != NULL) {
+               status = ocfs_write_sector (osb, group, group->this_ext);
+
+               if (status < 0) {
+                       LOG_ERROR_STATUS (status);
+                       goto bail;
+               }
+       }
+       status=0;
+bail:
+       LOG_EXIT_STATUS (status);
+
+       return(status);
+}
+
+/*
+ * ocfs_split_this_tree
+ *
+ * Given an extent_group (DAT or HDR) takes the new alloc_size from fe
+ * and splits this tree into two parts, one of which is deleted.
+ *
+ */
+int ocfs_split_this_tree(ocfs_super * osb, ocfs_extent_group *extent_grp,
+                   ocfs_cleanup_record *CleanupLogRec, ocfs_file_entry *fe) {
+       int status = -EFAIL;
+       __u64 newsize = fe->alloc_size;
+       ocfs_alloc_ext *ext;
+       ocfs_extent_group * grp_stack[OCFS_TREE_STACK_SIZE];
+       ocfs_extent_group * AllocExtent; /* convenience, points to TOS */
+       ocfs_extent_group *tmp = NULL, *tmp2 = NULL;
+       int tos = 0;
+       int i, victim;
+       __u64 bytes, foff, doff, orig_bytes, dstart = osb->vol_layout.data_start_off, total_bytes, csize = osb->vol_layout.cluster_size;
+       __u32 num_sectors, bitmap_offset, size;
+       bool done = false;
+       int gran = fe->granularity;
+
+       LOG_ENTRY();
+
+       size = sizeof (ocfs_cleanup_record);
+       size = (__u32) OCFS_ALIGN (size, OCFS_PAGE_SIZE);
+
+       /* This is a similar hack to the one below, untested for gran = 3 files
+          because I can't recreate one. */
+       if (gran == 3) {
+               LOG_ERROR_STR("Truncating file with granularity 3, this is not tested and may be unsafe!");
+               LOG_TRACE_STR("Found a granularity 3 tree, trimming it.\n");
+               tmp2 = ocfs_malloc(size);
+
+               if (tmp2 == NULL) {
+                       LOG_ERROR_STATUS(status);
+                       goto bail;
+               }
+
+               for(i = (extent_grp->next_free_ext - 1); i>=0; i--) {
+                       ext = &extent_grp->extents[i];
+
+                       status = ocfs_read_sector(osb, tmp2, ext->disk_off);
+                       if (status < 0) {
+                               LOG_ERROR_STATUS (status);
+                               goto bail;
+                       }
+
+                       if (ext->file_off >= newsize) {
+                               /* Trim this whole subtree */
+                               status = ocfs_kill_this_tree(osb, tmp2, CleanupLogRec);
+                               if (status < 0) {
+                                       LOG_ERROR_STATUS (status);
+                                       goto bail;
+                               }
+                               ext->file_off = 0;
+                               ext->disk_off = 0;
+                               ext->num_bytes = 0;
+                               extent_grp->next_free_ext = i;
+                       } else  { /* This is the one we want to split. */
+                               ext->num_bytes = newsize - ext->file_off;
+                               break;
+                       }
+               }
+               /* Write out our new top of the tree duder */
+               status = ocfs_write_sector(osb, extent_grp, extent_grp->this_ext);
+
+               /* Make our new TOS the header we want to split. */
+               extent_grp = tmp2;
+               LOG_TRACE_STR("Ok, continuing as if granularity = 2");
+
+               /* We want to do the next bit of stuff too */
+               gran = 2;
+       }
+
+       /* get rid of everything from the top level HDR that we can, then
+          proceeed as if we're granularity 1 (which we know works) */
+       if (gran == 2) {
+               LOG_TRACE_STR("Found a granularity 2 tree, trimming it.\n");
+               tmp = ocfs_malloc(size);
+
+               if (tmp == NULL) {
+                       LOG_ERROR_STATUS(status);
+                       goto bail;
+               }
+
+               for(i = (extent_grp->next_free_ext - 1); i>=0; i--) {
+                       ext = &extent_grp->extents[i];
+
+                       status = ocfs_read_sector(osb, tmp, ext->disk_off);
+                       if (status < 0) {
+                               LOG_ERROR_STATUS (status);
+                               goto bail;
+                       }
+
+                       if (ext->file_off >= newsize) {
+                               /* Trim this whole subtree */
+                               status = ocfs_kill_this_tree(osb, tmp, CleanupLogRec);
+                               if (status < 0) {
+                                       LOG_ERROR_STATUS (status);
+                                       goto bail;
+                               }
+                               ext->file_off = 0;
+                               ext->disk_off = 0;
+                               ext->num_bytes = 0;
+                               extent_grp->next_free_ext = i;
+                       } else  { /* This is the one we want to split. */
+                               ext->num_bytes = newsize - ext->file_off;
+                               break;
+                       }
+               }
+               /* Write out our new top of the tree duder */
+               status = ocfs_write_sector(osb, extent_grp, extent_grp->this_ext);
+
+               /* Make our new TOS the header we want to split. */
+               extent_grp = tmp;
+               LOG_TRACE_STR("Ok, continuing as if granularity = 1");
+
+               /* Right now, we don't use 'gran' below here, but just
+                * in case */
+               gran = 1;
+       }
+
+       for (i =0; i < OCFS_TREE_STACK_SIZE; i++)
+               grp_stack[i] = NULL;
+
+       grp_stack[tos] = extent_grp;
+
+       /* Ok, find the splitting point (can be a DAT or HDR) */
+       do {
+               AllocExtent = grp_stack[tos];
+
+               if (!IS_VALID_EXTENT_DATA(AllocExtent) &&
+                   !IS_VALID_EXTENT_HEADER(AllocExtent)) {
+                       LOG_ERROR_STR("Invalid extent group!");
+                       goto bail;
+               }
+
+               if (IS_VALID_EXTENT_DATA(AllocExtent)) {
+                       /* shall we just do away with him? */
+                       LOG_TRACE_STR("Found a whole data extent!");
+                       /* changed this from > to >= */
+                       if (AllocExtent->extents[0].file_off >= newsize) {
+                               LOG_TRACE_ARGS("Killing this data extent (%u, %u)\n", HI(AllocExtent->this_ext), LO(AllocExtent->this_ext));
+                               /* Boundary case - what if this guy is
+                                * the last DAT we should delete
+                                * (i.e., split no more ;) */
+                               status = ocfs_kill_this_tree(osb, AllocExtent, CleanupLogRec);
+                               if (status < 0) {
+                                       LOG_ERROR_STATUS (status);
+                                       goto bail;
+                               }
+
+                       } else {
+                               /* Alright, we know for sure that
+                                * we're splitting in this guy. */
+                               LOG_TRACE_ARGS("Splitting this data extent (%u, %u)\n", HI(AllocExtent->this_ext), LO(AllocExtent->this_ext));
+                               fe->last_ext_ptr= AllocExtent->this_ext;
+                               AllocExtent->next_data_ext = 0;
+                               /* total_bytes is used below to know
+                                * how much total we've whacked off
+                                * this extent*/
+                               total_bytes = 0;
+
+                               /* there is a chance the split is at a
+                                * header boundary. this will catch
+                                * it: */
+                               ext = &AllocExtent->extents[AllocExtent->next_free_ext - 1];
+                               if ((ext->file_off + ext->num_bytes)==newsize){
+                                       LOG_TRACE_STR("Ok, hit that boundary in the DAT");
+                                       goto fix_headers;
+                               }
+                               /* Either kill the data or resize it */
+                               for(i = (AllocExtent->next_free_ext - 1); i>=0;
+i--) {
+                                       ext = &AllocExtent->extents[i];
+
+                                       /* changed this from > to >= */
+                                       /* Do we delete it completely? */
+                                       if (ext->file_off >= newsize) {
+                                               total_bytes+=ext->num_bytes;
+
+                                               num_sectors = (__u32) (ext->num_bytes / csize);
+                                               bitmap_offset = (__u32) ((ext->disk_off - dstart) / csize);
+                                               ext->file_off = 0;
+                                               ext->num_bytes = 0;
+                                               ext->disk_off = 0;
+                                       } else {
+                                               /* Do we shrink it? */
+                                               orig_bytes = ext->num_bytes;
+                                               doff = ext->disk_off;
+                                               foff = ext->file_off;
+                                               bytes = ext->num_bytes = newsize - foff;
+                                               num_sectors = (__u32) ((orig_bytes - bytes) / csize);
+                                               bitmap_offset = (__u32) (((doff
++ bytes) - dstart) / csize);
+                                               //we want to exit the for loop now
+                                               total_bytes+= (orig_bytes - bytes);
+                                               done = true;
+                                       }
+                                       status = _write_free_extent_log(osb, CleanupLogRec, num_sectors, bitmap_offset, -1, DISK_ALLOC_VOLUME);
+                                       if (status < 0) {
+                                               LOG_ERROR_STATUS (status);
+                                               goto bail;
+                                       }
+
+                                       if (done) {
+                                               AllocExtent->next_free_ext=i+1;
+                                               break;
+                                       }
+                               } /* For loop */
+
+                               LOG_TRACE_ARGS("Writing that data extent back out to disk now (%u,%u)\n", HI(AllocExtent->this_ext), LO(AllocExtent->this_ext));
+			       /* Either way, we need to write this back out*/
+                               status = ocfs_write_sector (osb, AllocExtent, AllocExtent->this_ext);
+                               if (status < 0) {
+                                       LOG_ERROR_STATUS(status);
+                                       goto bail;
+                               }
+
+                               LOG_TRACE_ARGS("Fixing the headers above us! (tos=%d)\n", tos);
+                       fix_headers:
+                               /*And here we should fix the headers above us*/
+                               tos--;
+                               while (tos >= 0) {
+                                       LOG_TRACE_ARGS("at top of loop, tos=%d\n", tos);
+                                       AllocExtent = grp_stack[tos];
+                                       victim = AllocExtent->next_free_ext;
+                                       AllocExtent->next_free_ext++;
+                                       /* need to also update
+                                        * numbytes on these guys */
+                                       ext = &AllocExtent->extents[victim];
+                                       ext->num_bytes-= total_bytes;
+                                       status = ocfs_fix_extent_group(osb, AllocExtent);
+                                       if (status < 0) {
+                                               LOG_ERROR_STATUS(status);
+                                               goto bail;
+                                       }
+                                       tos--;
+                               }
+                               LOG_TRACE_STR("breaking to end the function now!");
+                               break;
+                       }
+               } else {
+                       /* It's a header extent */
+
+                       /* Did we already kill all his children, or
+                         * are they already dead? */
+                        if (AllocExtent->next_free_ext == 0) {
+                               /*Ok, we're done with this guy, pop the stack*/
+                               tos--;
+                                LOG_TRACE_ARGS("Popping this header (%u.%u)\n", HI(AllocExtent->this_ext), LO(AllocExtent->this_ext), AllocExtent->next_free_ext);
+
+                               status = _write_free_extent_log(osb, CleanupLogRec, 1, AllocExtent->alloc_file_off, AllocExtent->alloc_node, DISK_ALLOC_EXTENT_NODE);
+                               if (status < 0) {
+                                       LOG_ERROR_STATUS (status);
+                                       goto bail;
+                               }
+                               continue;
+                       }
+                       /* changed this from > to >= */
+                       /* Do we just delete this whole part of the tree? */
+                       if (AllocExtent->extents[0].file_off >= newsize) {
+                               LOG_TRACE_ARGS("whacking this tree: (%u.%u)\n",
+HI(AllocExtent->this_ext), LO(AllocExtent->this_ext));
+
+                               if (AllocExtent->extents[0].file_off ==newsize)
+                                       done = true;
+
+                               ocfs_kill_this_tree(osb, AllocExtent,CleanupLogRec);
+                               tos--;
+                               if (tos < 0) {
+                                       LOG_ERROR_STR("End of stack reached.");
+                                       goto bail;
+                               }
+                               /* I just have to fix my parent,
+                                * right? Yes, but only because our
+                                * max granularity is 2. if it were
+                                * more, we'd have to fix his
+                                * parents parent. */
+
+                               victim = grp_stack[tos]->next_free_ext;
+                               grp_stack[tos]->extents[victim].file_off = 0;
+                               grp_stack[tos]->extents[victim].num_bytes = 0;
+                               grp_stack[tos]->extents[victim].disk_off = 0;
+                               grp_stack[tos]->next_free_ext--;
+
+                               /* Here's an interesting boundary
+                                * case. What if we're truncating on a
+                                * boundary between two headers and
+                                * this is the one we just deleted. In
+                                * that case we're done, but need to
+                                * write the parent out before we leave
+                                * again, this bit of code depends on
+                                * granularity of 2. */
+                               if (done) {
+                                       LOG_TRACE_STR("Found a boundary header, almost done (gonna quit)");
+                                       status = ocfs_fix_extent_group(osb, grp_stack[tos]);
+                                       if (status < 0) {
+                                               LOG_ERROR_STATUS(status);
+                                               goto bail;
+                                       }
+                                       /* decrement tos so we dont
+                                        * trigger an error
+                                        * condition */
+                                       tos--;
+                                       break;
+                               }
+                               /* Ok, we're not a boundary case, continue */
+                               continue;
+                       }
+
+                        /* grow the stack, only allocating mem if we
+                         * haven't already */
+                       tos++;
+                       if (grp_stack[tos] == NULL)
+                               grp_stack[tos] = ocfs_malloc(size);
+                       else
+                               memset(grp_stack[tos], 0, size);
+
+                       /* Go one extent to the left */
+                       AllocExtent->next_free_ext--;
+                       victim = AllocExtent->next_free_ext;
+                       ext = &AllocExtent->extents[victim];
+
+                       status = ocfs_read_sector(osb, grp_stack[tos], ext->disk_off);
+                       if (status < 0) {
+                               LOG_ERROR_STATUS (status);
+                               goto bail;
+                       }
+
+                       LOG_TRACE_ARGS("Pushing this group (%u.%u)\n", HI(grp_stack[tos]->this_ext), LO(grp_stack[tos]->this_ext));
+
+                       /* We only want to free on our way up the tree */
+                       continue;
+               }
+
+               tos--;
+       } while (tos >= 0);
+
+       if (tos >= 0)
+               LOG_ERROR_ARGS("Quitting main loop while top of stack >= 0 (tos=%d)\n", tos);
+
+       status=0;
+bail:
+       ocfs_safefree(tmp);
+       ocfs_safefree(tmp2);
+        /* Free the stack. We never free the bottom of the stack
+         * because we were passed that guy from the caller */
+        for(i = 1; i < OCFS_TREE_STACK_SIZE; i++)
+                ocfs_safefree(grp_stack[i]);
+
+       LOG_EXIT_STATUS (status);
+       return(status);
+}
+
+/*
+ * ocfs_update_last_ext_ptr
+ *
+ *  Travel all the way to the rightmost DAT and set fe->last_ext_ptr to it.
+ */
+int ocfs_update_last_ext_ptr(ocfs_super *osb, ocfs_file_entry *fe) {
+       int status = -EFAIL;
+       ocfs_extent_group *AllocExtent = NULL;
+       __u32 size;
+       __u64 next_ext;
+       int victim;
+
+       LOG_ENTRY ();
+
+       if (fe->next_free_ext == 0) {
+               LOG_TRACE_STR("setting to zero as there isn't any used extents");
+               fe->last_ext_ptr = 0;
+       }
+
+       size = OCFS_ALIGN (sizeof (ocfs_extent_group), osb->sect_size);
+       AllocExtent = ocfs_malloc (size);
+
+       victim = fe->next_free_ext - 1;
+       status = ocfs_read_sector(osb, AllocExtent, fe->extents[victim].disk_off);
+       if (status < 0) {
+               LOG_ERROR_STATUS(status);
+               goto bail;
+       }
+
+       if (!IS_VALID_EXTENT_DATA(AllocExtent) &&
+           !IS_VALID_EXTENT_HEADER(AllocExtent)) {
+               LOG_ERROR_STR("Invalid extent group!");
+               goto bail;
+       }
+
+       while (!IS_VALID_EXTENT_DATA(AllocExtent)) {
+               if (!IS_VALID_EXTENT_HEADER(AllocExtent)) {
+                       LOG_ERROR_STR("Invalid extent group!");
+                       goto bail;
+               }
+
+               next_ext = AllocExtent->extents[AllocExtent->next_free_ext - 1].disk_off;
+               status = ocfs_read_sector(osb, AllocExtent, next_ext);
+               if (status < 0) {
+                       LOG_ERROR_STATUS(status);
+                       goto bail;
+               }
+       }
+
+       fe->last_ext_ptr = AllocExtent->this_ext;
+       status = 0;
+bail:
+       ocfs_safefree(AllocExtent);
+
+       LOG_EXIT_STATUS(status);
+       return(status);
+}
+ 
+/*
+ * ocfs_free_extents_for_truncate()
+ *
+ */
+int ocfs_free_extents_for_truncate (ocfs_super * osb, ocfs_file_entry * FileEntry)
+{
+	int status = 0;
+	__u32 size;
+	ocfs_cleanup_record *CleanupLogRec = NULL;
+	ocfs_extent_group *AllocExtent = NULL;
+        __u64 alloc_size;
+        int i, j;
+        bool updated_lep; /* used to mark whether fe->last_ext_ptr has
+                           * been updated */
+
+	LOG_ENTRY ();
+
+        alloc_size = FileEntry->alloc_size;
+	size = sizeof (ocfs_cleanup_record);
+	size = (__u32) OCFS_ALIGN (size, OCFS_PAGE_SIZE);
+
+	CleanupLogRec = ocfs_malloc (size);
+	if (CleanupLogRec == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto finally;
+	}
+
+	CleanupLogRec->rec.free.num_free_upds = 0;
+	CleanupLogRec->log_id = osb->curr_trans_id;
+	CleanupLogRec->log_type = LOG_FREE_BITMAP;
+
+        /* local extents */
+	if (FileEntry->local_ext) {
+               LOG_TRACE_STR("local extents, calling _squish_extent_entries");
+                status = _squish_extent_entries(osb, FileEntry->extents, &FileEntry->next_free_ext, CleanupLogRec, alloc_size, false);
+               LOG_TRACE_ARGS("return from _squish_extent_entries, status=%d",
+status);
+
+                if (status < 0) {
+                        LOG_ERROR_STATUS (status);
+                        goto finally;
+                }
+                goto write_log;
+        }
+
+        LOG_TRACE_ARGS("non-local extents. taking that code path, truncating to alloc_size of (%u.%u)\n", HI(alloc_size), LO(alloc_size));
+        /* non-local extents */
+        updated_lep = false;
+	size = OCFS_ALIGN (sizeof (ocfs_extent_group), osb->sect_size);
+	AllocExtent = ocfs_malloc (size);
+	if (AllocExtent == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto finally;
+	}
+
+	memset (AllocExtent, 0, size);
+
+        /* Loop backwards through only the used free extent headers here */
+        for (i = (FileEntry->next_free_ext - 1); i >= 0; i--) {
+                LOG_TRACE_ARGS("at top of loop, i = %d\n", i);
+                /* Go ahead and read that bit of the tree - we'll need it. */
+                status = ocfs_read_metadata (osb, AllocExtent, osb->sect_size,
+                                             FileEntry->extents[i].disk_off);
+		if (status < 0) {
+			LOG_ERROR_STATUS(status);
+			goto finally;
+		}
+
+               /* Figure out, do we want to kill this whole tree? */
+               if (FileEntry->extents[i].file_off >= alloc_size) {
+                       LOG_TRACE_ARGS("Found an entire tree to delete!\n");
+
+                       status = ocfs_kill_this_tree(osb, AllocExtent, CleanupLogRec);
+                       if (status < 0) {
+                               LOG_ERROR_STATUS(status);
+				goto finally;
+			}
+                        /* Ok, update the FileEntry */
+                        FileEntry->extents[i].file_off = 0;
+                        FileEntry->extents[i].disk_off = 0;
+                        FileEntry->extents[i].num_bytes = 0;
+                        FileEntry->next_free_ext = i;
+                } else { /* Ok, we only want part of it. */
+                        /* Actually, the truth is we might NOT want to
+                         * split this tree, but we call this function
+                         * anyways in order to update last_ext_ptr. */
+
+                       LOG_TRACE_ARGS("Splitting this tree!\n");
+                       status = ocfs_split_this_tree(osb, AllocExtent, CleanupLogRec, FileEntry);
+                       if (status < 0) {
+                               LOG_ERROR_STATUS(status);
+				goto finally;
+			}
+                       /* Ok, update the FileEntry */
+                       LOG_TRACE_ARGS("Alright. num_bytes = (%u,%u), alloc_size = (%u,%u) file_off = (%u,%u)\n", HI(FileEntry->extents[i].num_bytes), LO(FileEntry->extents[i].num_bytes), HI(alloc_size), LO(alloc_size), HI(FileEntry->extents[i].file_off), LO(FileEntry->extents[i].file_off));
+                       FileEntry->extents[i].num_bytes = alloc_size;
+                       for (j=0; j < i; j++)
+                               FileEntry->extents[i].num_bytes += FileEntry->extents[j].num_bytes;
+
+                       FileEntry->next_free_ext = i + 1;
+                       /* We're done - we can't split more than one
+                        * parts of the tree. */
+                       updated_lep = true;
+                       break;
+               }
+       }
+
+       /* Ok, trunc to zero is a special case */
+       if (alloc_size == 0) {
+               FileEntry->last_ext_ptr = 0;
+               FileEntry->granularity = -1;
+               FileEntry->local_ext = true;
+               updated_lep = true;
+       }
+
+       if (!updated_lep) {
+               LOG_TRACE_STR("Updating FileEntry->last_ext_ptr");
+               status = ocfs_update_last_ext_ptr(osb, FileEntry);
+               if (status < 0) {
+                       LOG_ERROR_STATUS(status);
+			goto finally;
+		}
+	}
+	LOG_TRACE_ARGS("non-local extents, out of loop now, i = %d\n", i);
+
+write_log:
+       /* There may be some log records that haven't been written out
+        * by _write_free_extent_log() yet, so finish up here.*/
+
+	if (CleanupLogRec->rec.free.num_free_upds > 0) {
+		status = ocfs_write_node_log (osb, (ocfs_log_record *) CleanupLogRec,
+					      osb->node_num, LOG_CLEANUP);
+		if (status < 0) {
+			LOG_ERROR_STATUS(status);
+			goto finally;
+		}
+	}
+
+      finally:
+	ocfs_safefree (AllocExtent);
+	ocfs_safefree (CleanupLogRec);
+
+	LOG_EXIT_ULONG (status);
+	return status;
+}  /* ocfs_free_extents_for_truncate */
+
+/*
+ * ocfs_lookup_file_allocation()
+ *
+ * This routine looks up the existing mapping of VBO to LBO for a  file.
+ * The information it queries is either stored in the extent map field
+ * of the oin or is stored in the allocation file and needs to be retrieved,
+ * decoded and updated in the extent map.
+ *
+ */
+int ocfs_lookup_file_allocation (ocfs_super * osb, ocfs_inode * oin, __s64 Vbo,
+				 __s64 * Lbo, __u32 ByteCount, __u32 * NumIndex,
+				 void **Buffer)
+{
+	int status = 0;
+	ocfs_file_entry *FileEntry = NULL;
+	__u32 allocSize = 0;
+	__u64 length = 0, remainingLength = 0;
+	__u8 *buffer = NULL;
+	__u32 Runs;
+	__s64 localVbo;
+	ocfs_extent_group *OcfsExtent = NULL;
+	ocfs_io_runs *IoRuns = NULL;
+
+	LOG_ENTRY ();
+
+	OCFS_ASSERT (osb);
+	OCFS_ASSERT (oin);
+	*Buffer = NULL;
+
+	if (Vbo >= oin->alloc_size) {
+		goto READ_ENTRY;
+	}
+
+	/* special case: just one byte - also happens to be the *only* 
+	 * way in which this func is currently called */
+	if (ByteCount == 1) {
+		status = -EFAIL;
+		/* return the blocknum directly, no need to alloc ioruns */
+		if (ocfs_lookup_extent_map_entry (osb, &oin->map, Vbo, Lbo, 
+						  &length, &Runs)) {
+			status = 0;
+			goto no_iorun_exit;
+		}
+	} else {
+		status = ocfs_extent_map_load (osb, &(oin->map), Buffer, Vbo, 
+					       ByteCount, &Runs);
+	}
+	if (status >= 0) {
+		/* If status is success, we found the needed extent map */
+		goto finally;
+	}
+
+      READ_ENTRY:
+	if (*Buffer) {
+		ocfs_free (*Buffer);
+		*Buffer = NULL;
+	}
+
+	remainingLength = ByteCount;
+	length = 0;
+	localVbo = Vbo;
+
+	/*  We are looking for a Vbo, but it is not in the Map or not Valid. */
+	/*  Thus we have to go to the disk, and update the Map */
+
+	/* Read the file Entry corresponding to this */
+	status = ocfs_get_file_entry (osb, &FileEntry, oin->file_disk_off);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	if (!IS_VALID_FILE_ENTRY (FileEntry)) {
+		LOG_ERROR_STATUS (status = -EINVAL);
+		goto finally;
+	}
+
+	if (Vbo >= (__s64) FileEntry->alloc_size) {
+		LOG_ERROR_ARGS ("fe=%u.%u, vbo=%u.%u, fe->alloc_sz=%u.%u, oin->alloc_size=%u.%u",
+			       	HILO (FileEntry->this_sector), HILO (Vbo),
+			       	HILO (FileEntry->alloc_size), HILO (oin->alloc_size));
+		status = -EFAIL;
+		goto finally;
+	}
+
+	if (FileEntry->local_ext) {
+		status = ocfs_update_extent_map (osb, &oin->map, FileEntry,
+						 NULL, NULL, 1);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+	} else {
+		/* Extents are branched and we are no longer using Local Extents */
+		/* for this File Entry. */
+		allocSize = (NUM_SECTORS_IN_LEAF_NODE +
+			     FileEntry->granularity) * OCFS_SECTOR_SIZE;
+		length = OCFS_ALIGN (allocSize, osb->sect_size);
+		buffer = ocfs_malloc ((__u32) length);
+		if (buffer == NULL) {
+			LOG_ERROR_STATUS (status = -ENOMEM);
+			goto finally;
+		}
+
+		OcfsExtent = (ocfs_extent_group *) buffer;
+
+		status = ocfs_get_leaf_extent (osb, FileEntry, localVbo, OcfsExtent);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+
+		while (1) {
+			status =
+			    ocfs_update_extent_map (osb, &oin->map, OcfsExtent,
+						 &localVbo, &remainingLength,
+						 2);
+			if (status < 0) {
+				LOG_ERROR_STATUS(status);
+				goto finally;
+			}
+
+			if (remainingLength > 0) {
+				if (!OcfsExtent->next_data_ext) {
+					LOG_ERROR_ARGS ("vbo=%u.%u, "
+						"oin->alloc_size=%u.%u, thisext=%u.%u",
+						HILO(localVbo), HILO(oin->alloc_size),
+						HILO(OcfsExtent->this_ext));
+					status = -EFAIL;
+					goto finally;
+				}
+
+				status = ocfs_read_extent (osb, OcfsExtent,
+							 OcfsExtent->next_data_ext,
+							 EXTENT_DATA);
+				if (status < 0) {
+					LOG_ERROR_STATUS(status);
+					goto finally;
+				}
+			} else {
+				break;
+			}
+		}
+	}
+
+	if (ByteCount == 1) {
+		status = -EFAIL;
+		if (ocfs_lookup_extent_map_entry (osb, &oin->map, Vbo, Lbo, 
+						  &length, &Runs)) {
+			status = 0;
+		}
+		goto no_iorun_exit;
+	} else {
+		status = ocfs_extent_map_load (osb, &(oin->map), Buffer, Vbo, 
+					       ByteCount, &Runs);
+	}
+
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+	}
+
+finally:
+	if (status >= 0) {
+		IoRuns = (ocfs_io_runs *) (*Buffer);
+		*(NumIndex) = Runs;
+		*(Lbo) = IoRuns[0].disk_off;
+	}
+
+no_iorun_exit:	
+	/* Should send a null for IoRuns in case of onl 1 extent */
+	LOG_TRACE_ARGS ("Num of Runs is: %d\n", Runs);
+
+	ocfs_safefree (buffer);
+
+	ocfs_release_file_entry (FileEntry);
+
+	LOG_EXIT_STATUS (status);
+	return (status);
+}				/* ocfs_lookup_file_allocation */
+
+/* ocfs_extent_map_load()
+ *
+ */
+int ocfs_extent_map_load (ocfs_super * osb,
+		     ocfs_extent_map * Map,
+		     void **Buffer, __s64 Vbo, __u64 ByteCount, __u32 * RetRuns)
+{
+	int status = -EFAIL;
+	ocfs_io_runs *IoRuns = NULL;
+	__u32 BufferOffset;
+	__u32 ioExtents = OCFS_MAX_DATA_EXTENTS;
+	__u64 length = 0, remainingLength = 0;
+	__u32 Runs, Index, ioRunSize;
+	__s64 localLbo;
+	__s64 localVbo;
+
+	LOG_ENTRY ();
+
+	ioRunSize = OCFS_MAX_DATA_EXTENTS * sizeof (ocfs_io_runs);
+	IoRuns = ocfs_malloc (ioRunSize);
+	if (IoRuns == NULL) {
+		LOG_ERROR_STATUS(status = -ENOMEM);
+		goto bail;
+	}
+
+	remainingLength = ByteCount;
+	Runs = 0;
+	length = 0;
+	localVbo = Vbo;
+	BufferOffset = 0;
+
+	while (ocfs_lookup_extent_map_entry
+	       (osb, Map, localVbo, &localLbo, &length, &Index)) {
+		IoRuns[Runs].disk_off = localLbo;
+		IoRuns[Runs].byte_cnt = length;
+		IoRuns[Runs].offset = BufferOffset;
+
+		if (length >= remainingLength) {
+			IoRuns[Runs].byte_cnt = remainingLength;
+			status = 0;
+			Runs++;
+			break;
+		} else {
+			Runs++;
+			if (Runs >= ioExtents) {
+				status = ocfs_adjust_allocation (&IoRuns, &ioRunSize);
+				if (status < 0) {
+					LOG_ERROR_STATUS(status);
+					goto bail;
+				}
+
+				ioExtents *= 2;
+			}
+			localVbo += length;
+			BufferOffset += length;
+			remainingLength -= length;
+			continue;
+		}
+	}
+
+	(*RetRuns) = Runs;
+	(*Buffer) = IoRuns;
+
+      bail:
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_extent_map_load */
+
+
+/*
+ * ocfs_lookup_extent_map_entry()
+ *
+ * search for an VBO in the extent map passed on.
+ *
+ * Returns true if entry available in the extent map, false otherwise.
+ */
+bool ocfs_lookup_extent_map_entry (ocfs_super * osb,
+			  ocfs_extent_map * Map,
+			  __s64 Vbo, __s64 * Lbo, __u64 * SectorCount, __u32 * Index)
+{
+	bool ret;
+	__s64 LiLbo = 0;
+	__s64 LiSectorCount = 0;
+	__u64 remainder = 0;
+
+	LOG_ENTRY ();
+
+	/* Sector Align the vbo */
+	remainder = Vbo & OCFS_MOD_SECTOR_SIZE;
+
+	ret = ocfs_extent_map_lookup (Map, (Vbo >> OCFS_LOG_SECTOR_SIZE), &LiLbo,
+				   &LiSectorCount, Index);
+	if ((__u32) LiLbo != -1) {
+		*Lbo = (((__s64) LiLbo) << (__s64) OCFS_LOG_SECTOR_SIZE);
+		if (ret) {
+			*Lbo += remainder;
+		}
+	} else {
+		ret = false;
+		*Lbo = 0;
+	}
+
+	*SectorCount = LiSectorCount;
+	if (*SectorCount) {
+		*SectorCount <<= (__s64) OCFS_LOG_SECTOR_SIZE;
+		if (*SectorCount == 0) {
+			*SectorCount = (__u32) - 1;
+		}
+
+		if (ret) {
+			*SectorCount -= remainder;
+		}
+	}
+
+	LOG_EXIT_ULONG (ret);
+	return ret;
+}				/* ocfs_lookup_extent_map_entry */
+
+
+/*
+ * ocfs_adjust_allocation()
+ *
+ * It gets called if the number of runs is more than a default number and
+ * so will free up the previously allocated memory and allocated twice the
+ * prevously allocated memory.
+ *
+ */
+int ocfs_adjust_allocation (ocfs_io_runs ** IoRuns, __u32 * ioRunSize)
+{
+	int status = 0;
+	__u32 runSize = 0;
+	ocfs_io_runs *localIoRuns = NULL;
+
+	LOG_ENTRY ();
+
+	OCFS_ASSERT (IoRuns);
+
+	runSize = (*ioRunSize) * 2;
+	localIoRuns = ocfs_malloc (runSize);
+	if (localIoRuns == NULL) {
+		LOG_ERROR_STATUS(status = -ENOMEM);
+		goto bail;
+	}
+
+	memcpy (localIoRuns, *IoRuns, *ioRunSize);
+	ocfs_free (*IoRuns);
+	*IoRuns = localIoRuns;
+	*ioRunSize = runSize;
+
+	/* Don't free localIoRuns here */
+bail:
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_adjust_allocation */
+
+/* ocfs_update_extent_map()
+ *
+ */
+int ocfs_update_extent_map (ocfs_super * osb, ocfs_extent_map * Map,
+			    void *Buffer, __s64 * localVbo,
+			    __u64 * remainingLength, __u32 Flag)
+{
+	int status = -EFAIL;
+	ocfs_file_entry *FileEntry;
+	ocfs_extent_group *OcfsExtent;
+	__s64 tempVbo;
+	__s64 tempLbo;
+	__u64 tempSize;
+	bool Ret;
+	int j;
+
+	LOG_ENTRY ();
+
+	if (Flag == 1) {
+		FileEntry = (ocfs_file_entry *) Buffer;
+
+		OCFS_ASSERT (FileEntry->local_ext);
+
+		for (j = 0; j < FileEntry->next_free_ext; j++) {
+			tempVbo = FileEntry->extents[j].file_off;
+			tempLbo = FileEntry->extents[j].disk_off;
+			tempSize = FileEntry->extents[j].num_bytes;
+
+			/* Add the Extent to extent map list */
+			Ret =
+			    ocfs_add_extent_map_entry (osb, Map, tempVbo, tempLbo,
+						   tempSize);
+			if (!Ret) {
+				LOG_ERROR_STATUS (status = -ENOMEM);
+				goto bail;
+			}
+		}
+		status = 0;
+	} else {
+		__u64 localLength = 0;
+
+		OcfsExtent = (ocfs_extent_group *) Buffer;
+
+		for (j = 0; j < OcfsExtent->next_free_ext; j++) {
+			if ((__s64) (OcfsExtent->extents[j].file_off +
+				   OcfsExtent->extents[j].num_bytes) >
+			    (*localVbo)) {
+				tempVbo = OcfsExtent->extents[j].file_off;
+				tempLbo = OcfsExtent->extents[j].disk_off;
+				tempSize = OcfsExtent->extents[j].num_bytes;
+
+				/* Add the Extent to extent map list */
+				Ret =
+				    ocfs_add_extent_map_entry (osb, Map, tempVbo,
+							   tempLbo, tempSize);
+				if (!Ret) {
+					LOG_ERROR_STATUS (status = -ENOMEM);
+					goto bail;
+				}
+
+				localLength =
+				    (tempSize - ((*localVbo) - tempVbo));
+
+				/* Since we have read the disk we should add some */
+				/* more Entries to the extent map list */
+				if (localLength >= (*remainingLength)) {
+					(*remainingLength) = 0;
+					status = 0;
+					goto bail;
+				} else {
+					(*remainingLength) -= localLength;
+					(*localVbo) += localLength;
+				}
+			}
+		}
+
+		if ((OcfsExtent->next_free_ext != OCFS_MAX_DATA_EXTENTS) &&
+		    (*remainingLength)) {
+			LOG_ERROR_ARGS ("next_free_extent=%d, rem_len=%u.%u",
+				OcfsExtent->next_free_ext, HI(*remainingLength),
+				LO(*remainingLength));
+		} else
+			status = 0;
+	}
+
+      bail:
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_update_extent_map */
+
+/*
+ * ocfs_add_extent_map_entry()
+ *
+ * adds an entry to an extent map
+ *
+ * Returns true on success, false otherwise.
+ */
+bool ocfs_add_extent_map_entry (ocfs_super * osb,
+		       ocfs_extent_map * Map, __s64 Vbo, __s64 Lbo, __u64 ByteCount)
+{
+	bool ret;
+
+	LOG_ENTRY ();
+
+	/* Convert the Bytes in to number of Sectors */
+	if (ByteCount) {
+		/* Round up sectors */
+		ByteCount--;
+		ByteCount >>= OCFS_LOG_SECTOR_SIZE;
+		ByteCount++;
+	}
+
+	/* Make the ByteOffsets in to Sector numbers. */
+	/* In case of 512 byte sectors the OcfsLogOf gives back a value of 9. */
+	/* And by doing a right shift of 9 bits we are actually dividing */
+	/* the value by 512. */
+	Vbo >>= OCFS_LOG_SECTOR_SIZE;
+	Lbo >>= OCFS_LOG_SECTOR_SIZE;
+
+	ret = ocfs_extent_map_add (Map, ((__s64) Vbo), ((__s64) Lbo), ((__s64) ByteCount));
+	if (!ret)
+		LOG_ERROR_ARGS ("fileoff=%u.%u, diskoff=%u.%u, len=%u.%u",
+				HI(Vbo), LO(Vbo), HI(Lbo), LO(Lbo),
+				HI(ByteCount), LO(ByteCount));
+
+	LOG_EXIT_ULONG (ret);
+	return ret;
+}				/* ocfs_add_extent_map_entry */
+
+/* ocfs_get_leaf_extent()
+ *
+ */
+int ocfs_get_leaf_extent (ocfs_super * osb,
+	       ocfs_file_entry * FileEntry,
+	       __s64 Vbo, ocfs_extent_group * OcfsDataExtent)
+{
+	int status = 0, tempstat;
+	__u32 i, j, length;
+	ocfs_extent_group *ExtentHeader = NULL;
+	__u64 childDiskOffset = 0;
+
+	LOG_ENTRY ();
+
+	for (i = 0; i < FileEntry->next_free_ext; i++) {
+		if ((__s64) (FileEntry->extents[i].file_off +
+			   FileEntry->extents[i].num_bytes) > Vbo) {
+			childDiskOffset = FileEntry->extents[i].disk_off;
+			break;
+		}
+	}
+
+	if (childDiskOffset == 0) {
+		LOG_ERROR_STATUS (status = -EINVAL);
+		goto finally;
+	}
+
+	if (FileEntry->granularity >= 1) {
+		length = osb->sect_size;
+		ExtentHeader = ocfs_malloc ((__u32) length);
+		if (ExtentHeader == NULL) {
+			LOG_ERROR_STATUS (status = -ENOMEM);
+			goto finally;
+		}
+	}
+
+	for (i = 0; i < FileEntry->granularity; i++) {
+		tempstat = ocfs_read_extent (osb, ExtentHeader, childDiskOffset,
+					     EXTENT_HEADER);
+		if (tempstat < 0) {
+			LOG_ERROR_STATUS (status = tempstat);
+			goto finally;
+		}
+
+		for (j = 0; j < ExtentHeader->next_free_ext; j++) {
+			if ((__s64) (ExtentHeader->extents[j].file_off +
+				   ExtentHeader->extents[j].num_bytes) > Vbo)
+			{
+				childDiskOffset =
+			 	    ExtentHeader->extents[j].disk_off;
+				break;
+			}
+		}
+	}
+
+	tempstat = ocfs_read_extent (osb, OcfsDataExtent, childDiskOffset,
+				     EXTENT_DATA);
+	if (tempstat < 0) {
+		LOG_ERROR_STATUS (status = tempstat);
+		goto finally;
+	}
+
+      finally:
+	ocfs_safefree (ExtentHeader);
+
+	LOG_EXIT_STATUS (status);
+	return (status);
+}				/* ocfs_get_leaf_extent */

Added: trunk/libocfs/Common/ocfsgencreate.c
===================================================================
--- trunk/libocfs/Common/ocfsgencreate.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/ocfsgencreate.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,2893 @@
+/*
+ * ocfsgencreate.c
+ *
+ * Does lots of things sort-of associated with creating a file.
+ *
+ * Copyright (C) 2002, 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifdef __KERNEL__
+#include <ocfs.h>
+#else
+#include <libocfs.h>
+#endif
+
+
+/* Tracing */
+#define OCFS_DEBUG_CONTEXT  OCFS_DEBUG_CONTEXT_CREATE
+
+/*
+ * ocfs_verify_update_oin()
+ *
+ * This function searches the cached oin list for a volume for a given
+ * filename. We currently cache all the oin's. We should hash this list.
+ *
+ */ 
+int ocfs_verify_update_oin (ocfs_super * osb, ocfs_inode * oin)
+{
+	int status = 0;
+	ocfs_file_entry *fe = NULL;
+	ocfs_lock_res *pLockRes;
+	struct inode *inode = NULL;
+#ifndef USERSPACE_TOOL
+        struct list_head *iter;
+        struct list_head *temp_iter;
+	struct dentry *dentry;
+#endif
+        int disk_len;
+
+	/* We are setting the oin Updated flag in the end. */
+	LOG_ENTRY ();
+
+	OCFS_ASSERT (oin);
+
+	status = ocfs_get_file_entry (osb, &fe, oin->file_disk_off);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	/* Make sure that what we found is not a directory. */
+	if (!(oin->oin_flags & OCFS_OIN_DIRECTORY)) {
+		/* Add checks as needed */
+		if (IS_FE_DELETED(fe->sync_flags) ||
+		    (!(fe->sync_flags & OCFS_SYNC_FLAG_VALID))) {
+			LOG_TRACE_ARGS ("Invalid file: %*s, syncflg=0x%X",
+				       	fe->filename_len, fe->filename,
+				       	fe->sync_flags);
+			OCFS_SET_FLAG (oin->oin_flags, OCFS_OIN_INVALID);
+			/* ?? I think we should remove the oin here from the oin list */
+			status = -ENOENT;
+			goto leave;
+		}
+
+                disk_len = strlen(fe->filename);
+		inode = oin->inode;
+		if (inode == NULL) {
+			LOG_TRACE_ARGS ("oin has no matching inode: %*s",
+				       	fe->filename_len, fe->filename);
+			OCFS_SET_FLAG (oin->oin_flags, OCFS_OIN_INVALID);
+			status = -ENOENT;
+			goto leave;
+		}
+		
+#ifndef USERSPACE_TOOL
+                status = -ENOENT;
+		dentry = NULL;
+                list_for_each_safe (iter, temp_iter, &(inode->i_dentry)) {
+                        dentry = list_entry (iter, struct dentry, d_alias);
+                        if (dentry->d_name.len == disk_len &&
+                            strncmp(dentry->d_name.name, fe->filename, disk_len)==0)
+                        {
+                                status = 0;
+                        }
+                }
+		if (status < 0) {
+			LOG_TRACE_ARGS ("name did not match inode: %*s, %d",
+				       	fe->filename_len, fe->filename);
+			OCFS_SET_FLAG (oin->oin_flags, OCFS_OIN_INVALID);
+			goto leave;
+		}
+#endif
+
+		if ((oin->alloc_size != (__s64) fe->alloc_size) ||
+		    (inode->i_size != (__s64) fe->file_size) ||
+		    (oin->chng_seq_num != DISK_LOCK_SEQNUM (fe)) ||
+		    inode->i_uid != fe->uid ||
+		    inode->i_gid != fe->gid || inode->i_mode != fe->prot_bits) {
+
+			if (oin->alloc_size > (__s64)fe->alloc_size) {
+				ocfs_extent_map_destroy (&oin->map);
+				ocfs_extent_map_init (&oin->map);
+			}
+
+			LOG_TRACE_STR
+			    ("Allocsize, filesize or seq no did not match");
+			oin->alloc_size = fe->alloc_size;
+			inode->i_size = fe->file_size;
+			oin->chng_seq_num = DISK_LOCK_SEQNUM (fe);
+
+			inode->i_blocks = (inode->i_size + 512) >> 9;
+			inode->i_uid = fe->uid;
+			inode->i_gid = fe->gid;
+			inode->i_mode = fe->prot_bits;
+			inode->i_blksize = (__u32) osb->vol_layout.cluster_size;
+		        inode->i_ctime = fe->create_time;
+        		inode->i_atime = fe->modify_time;
+        		inode->i_mtime = fe->modify_time;
+
+			if (!S_ISDIR (inode->i_mode)) {
+				truncate_inode_pages (inode->i_mapping, 0);
+			}
+
+			switch (fe->attribs & (~OCFS_ATTRIB_FILE_CDSL)) {
+			    case OCFS_ATTRIB_DIRECTORY:
+				    inode->i_size = OCFS_DEFAULT_DIR_NODE_SIZE;
+				    inode->i_blocks = (inode->i_size + 512) >> 9;
+				    inode->i_mode |= S_IFDIR;
+				    break;
+			    case OCFS_ATTRIB_SYMLINK:
+				    inode->i_mode |= S_IFLNK;
+				    break;
+			    case OCFS_ATTRIB_REG:
+				    inode->i_mode |= S_IFREG;
+				    break;
+			    case OCFS_ATTRIB_CHAR:
+			    case OCFS_ATTRIB_BLOCK:
+			    case OCFS_ATTRIB_FIFO:
+			    case OCFS_ATTRIB_SOCKET:
+			    {
+				    kdev_t kdev;
+
+				    if (fe->attribs == OCFS_ATTRIB_CHAR)
+					    inode->i_mode |= S_IFCHR;
+				    else if (fe->attribs == OCFS_ATTRIB_BLOCK)
+					    inode->i_mode |= S_IFBLK;
+				    else if (fe->attribs == OCFS_ATTRIB_FIFO)
+					    inode->i_mode |= S_IFIFO;
+				    else if (fe->attribs == OCFS_ATTRIB_SOCKET)
+					    inode->i_mode |= S_IFSOCK;
+
+				    inode->i_rdev = NODEV;
+				    kdev = MKDEV (fe->dev_major, fe->dev_minor);
+				    init_special_inode (inode, inode->i_mode,
+							kdev_t_to_nr (kdev));
+				    break;
+			    }
+			    default:
+			    	    LOG_ERROR_ARGS ("attribs=%d", fe->attribs);
+				    inode->i_mode |= S_IFREG;
+				    break;
+			}
+
+			if (fe->local_ext) {
+				__s64 tempVbo;
+				__s64 tempLbo;
+				__u64 tempSize;
+				__u32 j;
+
+				/* Add the Extents to extent map */
+				for (j = 0; j < fe->next_free_ext; j++) {
+					tempVbo = fe->extents[j].file_off;
+					tempLbo = fe->extents[j].disk_off;
+					tempSize = fe->extents[j].num_bytes;
+
+					if (!ocfs_add_extent_map_entry (osb,
+							&oin->map, tempVbo, tempLbo,
+							tempSize))
+						goto leave;
+				}
+			}
+		}
+
+		pLockRes = oin->lock_res;
+		ocfs_get_lockres (pLockRes);
+
+		/* ??? we need to the lock resource before updating it */
+		if (pLockRes) {
+			pLockRes->lock_type = DISK_LOCK_FILE_LOCK (fe);
+			pLockRes->master_node_num = DISK_LOCK_CURRENT_MASTER (fe);
+			pLockRes->oin_openmap = DISK_LOCK_OIN_MAP (fe);
+			pLockRes->last_write_time = DISK_LOCK_LAST_WRITE (fe);
+			pLockRes->last_read_time = DISK_LOCK_LAST_READ (fe);
+			pLockRes->reader_node_num = DISK_LOCK_READER_NODE (fe);
+			pLockRes->writer_node_num = DISK_LOCK_WRITER_NODE (fe);
+		}
+
+		ocfs_put_lockres (pLockRes);
+
+		status = 0;
+	} else {
+		/* Update for the DIRECTORY */
+	}
+
+      leave:
+	if (status == 0)
+		OIN_UPDATED (oin);
+
+	ocfs_release_file_entry (fe);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_verify_update_oin */
+
+/*
+ * ocfs_find_contiguous_space_from_bitmap()
+ *
+ * This function looks for free space in the volume based on the bitmap.
+ * It looks for contiguous space only and if it founds the space available
+ * it returns cluster bitmap offset. Each bit in Cluster bitmap represents
+ * memory equal to cluster size (specified during format).
+ *
+ * TODO: The Bitmap stuff needs to be changed for handling more than 32 bits...
+ * Although we can go upto 4k(clustersize) * 8 * 4M(max 32 bits for now...)
+ *
+ * Returns 0 on success, < 0 on error.
+ */
+int ocfs_find_contiguous_space_from_bitmap (ocfs_super * osb,
+			       __u64 file_size,
+			       __u64 * cluster_off, __u64 * cluster_count, bool sysfile)
+{
+	int status = 0, tmpstat;
+	__u32 size = 0, ByteOffset = 0, ClusterCount = 0;
+	__u64 ByteCount = 0;
+	__u32 LargeAlloc = 0;
+	static __u32 LargeAllocOffset = 0;
+	static __u32 SmallAllocOffset = 0;
+	__u64 startOffset = 0;
+	bool bLockAcquired = false;
+	ocfs_lock_res *pLockResource = NULL;
+        ocfs_file_entry *fe = NULL;
+        ocfs_bitmap_lock *bm_lock = NULL;
+
+	LOG_ENTRY ();
+
+	OCFS_ASSERT (osb);
+
+	ocfs_down_sem (&(osb->vol_alloc_lock), true);
+
+	/* Get the allocation lock here */
+        fe = ocfs_allocate_file_entry();
+        if (!fe) {
+                LOG_ERROR_STATUS (status = -ENOMEM);
+                goto leave;
+        }
+        bm_lock = (ocfs_bitmap_lock *)fe;
+
+	status = ocfs_acquire_lock (osb, OCFS_BITMAP_LOCK_OFFSET,
+			     OCFS_DLM_EXCLUSIVE_LOCK, 0, &pLockResource,
+			     fe);
+	if (status < 0) {
+		if (status != -EINTR)
+			LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	bLockAcquired = true;
+
+ 	LOG_TRACE_STR ("LOCK");
+ 
+	ByteCount = file_size;
+
+	/* Calculate the size in Bytes */
+	size = (__u32) OCFS_SECTOR_ALIGN ((osb->cluster_bitmap.size) / 8);
+
+	startOffset = osb->vol_layout.bitmap_off;
+	status = ocfs_read_metadata (osb, osb->cluster_bitmap.buf, size,
+				     startOffset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	/* Round off the byte count to next clustersize (bytes per cluster) */
+	ByteCount += (ByteCount % (osb->vol_layout.cluster_size)) ?
+	    (osb->vol_layout.cluster_size -
+	     (ByteCount % (osb->vol_layout.cluster_size))) : 0;
+
+	if (ByteCount == 0) {
+		LOG_ERROR_STR ("DISK_FULL?: Bytecount==0");
+		status = 0;
+		goto leave;
+	}
+
+	ClusterCount =
+	    (__u32) ((__u64) ByteCount / (__u64) osb->vol_layout.cluster_size);
+
+	if (sysfile ? (ClusterCount > osb->vol_layout.num_clusters) :
+			(ClusterCount > (osb->vol_layout.num_clusters - 
+		        ((8 * ONE_MEGA_BYTE) / osb->vol_layout.cluster_size)))){
+		LOG_ERROR_STR ("Disk Full");
+		status = -ENOSPC;
+		goto leave;
+	}
+
+	/* This function will check for clear bits in the Bitmap for consecutive */
+	/* clear bits equal to ClusterCount */
+
+	/* If we create a chunk that is larger than 5% of the disksize, then start */
+	/* allocation at 5%, so that small files stay in the beginning as much as possible */
+	
+	if (ClusterCount > (osb->vol_layout.num_clusters / 20)) {
+		LargeAlloc = 1;
+		LargeAllocOffset = (osb->vol_layout.num_clusters / 20);
+	}
+	
+
+	ByteOffset = ocfs_find_clear_bits (&osb->cluster_bitmap, ClusterCount,
+					LargeAlloc ? LargeAllocOffset :
+					SmallAllocOffset, sysfile ? 0 :
+					((8 * ONE_MEGA_BYTE) / osb->vol_layout.cluster_size));
+
+	/* if fails we should try again from the beginning of the disk. */
+	/* in the end we pass # of bits we want to keep for system file extention only */
+	/* right now if we run out of diskspace, we still have 8mb free for a systemfile */
+
+	if (ByteOffset == -1 && LargeAlloc) {
+		osb->cluster_bitmap.failed++;
+		ByteOffset = ocfs_find_clear_bits (&osb->cluster_bitmap,
+					ClusterCount, 0,
+					sysfile ? 0 :
+						((8 * ONE_MEGA_BYTE) /
+						 osb->vol_layout.cluster_size));
+	}
+
+	/* It returns -1 on failure, otherwise ByteOffset points at the */
+	/* location inb bitmap from where there are ClusterCount no of bits */
+	/* are free.  */
+
+	if (ByteOffset == -1) {
+		if (sysfile)
+			LOG_ERROR_ARGS (
+				"Systemfile cannot allocate contiguously %u blocks",
+				ClusterCount);
+		status = -ENOSPC;
+		goto leave;
+	}
+
+#ifdef SMART_ALLOC
+	/* FIXME : we try to be smart and keep track of the last offset we were at
+	 * need to add the same in delfile so that we put it lower again
+	 */
+	if (LargeAlloc) {
+		osb->cluster_bitmap.ok_retries++;
+		LargeAllocOffset = ByteOffset + ClusterCount;
+	} else {
+		SmallAllocOffset = ByteOffset + ClusterCount;
+	}
+#endif
+
+	ocfs_set_bits (&osb->cluster_bitmap, ByteOffset, ClusterCount);
+
+	LOG_TRACE_ARGS("gb_s: bit=%d, len=%d\n", ByteOffset, ClusterCount);
+
+	startOffset = osb->vol_layout.bitmap_off;
+
+	status =
+	    ocfs_write_metadata (osb, osb->cluster_bitmap.buf, size, startOffset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+        
+        /* write the bitmap size info to the lock sector */
+        /* TODO: optimize by making this part of ocfs_release_lock 
+         * for now, it will be back-to-back writes to same sector */
+        bm_lock->used_bits = ocfs_count_bits(&osb->cluster_bitmap);
+        status = ocfs_write_force_disk(osb, bm_lock, OCFS_SECTOR_SIZE,
+				       OCFS_BITMAP_LOCK_OFFSET);
+        if (status < 0) {
+                LOG_ERROR_STATUS (status);
+                goto leave;
+        }
+
+	*cluster_off = ByteOffset;
+	*cluster_count = ClusterCount;
+	status = 0;
+
+      leave:
+	ocfs_up_sem (&(osb->vol_alloc_lock));
+	if (bLockAcquired) {
+		tmpstat = ocfs_release_lock (osb, OCFS_BITMAP_LOCK_OFFSET,
+				OCFS_DLM_EXCLUSIVE_LOCK, 0, pLockResource, fe);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+		LOG_TRACE_STR ("UNLOCK");
+	}
+	ocfs_put_lockres (pLockResource);
+	ocfs_release_file_entry(fe);
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_find_contiguous_space_from_bitmap */
+
+/* ocfs_create_oin_from_entry()
+ *
+ */
+int
+ocfs_create_oin_from_entry (ocfs_super * osb,
+		    ocfs_file_entry * fe,
+		    ocfs_inode ** new_oin,
+		    __u64 parent_dir_off, ocfs_inode * parent_oin)
+{
+	int status = 0;
+	__u64 allocSize = 0;
+	__u64 endofFile = 0;
+	ocfs_inode *oin;
+	__u64 lockId;
+	int j;
+	__s64 tempVbo;
+	__s64 tempLbo;
+	__u64 tempSize;
+	ocfs_extent_group *buffer = NULL;
+	ocfs_extent_group *pOcfsExtent;
+	bool bRet;
+
+	LOG_ENTRY ();
+
+	/* First insert on the sector node tree... */
+
+	/* Check for state on the disk and notify master */
+	*new_oin = NULL;
+
+	/* We have a new file on disk , so create an oin for the file */
+	status = ocfs_create_new_oin (&oin, &allocSize, &endofFile, NULL, osb);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	oin->parent_dirnode_off = parent_dir_off;
+	oin->chng_seq_num = DISK_LOCK_SEQNUM (fe);
+	oin->alloc_size = fe->alloc_size;
+
+	if (fe->this_sector == 0)
+		LOG_ERROR_STR ("this_sector=0");
+
+	/* The oins gets Linked into the osb in this function */
+
+	if (fe->attribs & OCFS_ATTRIB_DIRECTORY) {
+		lockId = fe->extents[0].disk_off;
+		status = ocfs_initialize_oin (oin, osb,
+				OCFS_OIN_DIRECTORY | OCFS_OIN_IN_USE, NULL,
+				fe->this_sector, lockId);
+		if (status < 0) {
+			if (status != -EINTR)
+				LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+		oin->dir_disk_off = fe->extents[0].disk_off;
+	} else {
+		status = ocfs_initialize_oin (oin, osb, OCFS_OIN_IN_USE, NULL,
+					    fe->this_sector, fe->this_sector);
+		if (status < 0) {
+			if (status != -EINTR)
+				LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+
+		if (fe->local_ext) {
+			for (j = 0; j < fe->next_free_ext; j++) {
+				tempVbo = fe->extents[j].file_off;
+				tempLbo = fe->extents[j].disk_off;
+				tempSize = fe->extents[j].num_bytes;
+
+				/* Add the Extent to extent map */
+				bRet = ocfs_add_extent_map_entry (osb, &oin->map,
+						tempVbo, tempLbo, tempSize);
+				if (!bRet) {
+					LOG_ERROR_STATUS (status = -ENOMEM);
+					goto leave;
+				}
+			}
+		} else {
+			__u32 alloSize;
+			__u32 length;
+
+			/* Extents are branched and we are no longer using */
+			/* Local Extents for this File Entry. */
+			alloSize =
+			    (NUM_SECTORS_IN_LEAF_NODE +
+			     fe->granularity) * OCFS_SECTOR_SIZE;
+
+			length = (__u32) OCFS_ALIGN (alloSize, osb->sect_size);
+			buffer = ocfs_malloc (length);
+			if (buffer == NULL) {
+				LOG_ERROR_STATUS (status = -ENOMEM);
+				goto leave;
+			}
+
+			pOcfsExtent = (ocfs_extent_group *) buffer;
+
+			status = ocfs_get_leaf_extent (osb, fe, 0, pOcfsExtent);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto leave;
+			}
+
+			while (1) {
+				if (!IS_VALID_EXTENT_DATA (pOcfsExtent)) {
+					LOG_ERROR_STATUS(status = -EFAIL);
+					goto leave;
+				}
+
+				for (j = 0; j < pOcfsExtent->next_free_ext; j++) {
+					tempVbo = pOcfsExtent->extents[j].file_off;
+					tempLbo = pOcfsExtent->extents[j].disk_off;
+					tempSize = pOcfsExtent->extents[j].num_bytes;
+
+					/* Add the Extent to extent map */
+					bRet =
+					    ocfs_add_extent_map_entry (osb,
+								   &oin->map,
+								   tempVbo,
+								   tempLbo,
+								   tempSize);
+					if (!bRet) {
+						LOG_ERROR_STATUS (status =
+								  -ENOMEM);
+						goto leave;
+					}
+				}
+
+				if (pOcfsExtent->next_data_ext > 0) {
+					if (!pOcfsExtent->next_data_ext) {
+						LOG_ERROR_STATUS (status = -EFAIL);
+						goto leave;
+					}
+
+					status =
+					    ocfs_read_sector (osb, pOcfsExtent,
+							    pOcfsExtent->
+							    next_data_ext);
+					if (status < 0) {
+						LOG_ERROR_STATUS (status);
+						goto leave;
+					}
+				} else
+					break;
+			}
+		}
+	}
+
+	*new_oin = oin;
+      leave:
+	if (!*new_oin)
+		ocfs_release_oin (oin, true);
+
+	ocfs_safefree (buffer);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_create_oin_from_entry */
+
+/* ocfs_find_files_on_disk()
+ *
+ */
+int
+ocfs_find_files_on_disk (ocfs_super * osb,
+		 __u64 parent_off,
+		 struct qstr * file_name,
+		 ocfs_file_entry * fe, ocfs_file * ofile)
+{
+	int status = -ENOENT;
+	ocfs_dir_node *pDirNode = NULL;
+	__u64 thisDirNode, lockId;
+	int tmpstat;
+	bool bRet;
+	ocfs_lock_res *lockres = NULL;
+	bool bReadDirNode = true;
+	ocfs_file_entry *dirfe = NULL;
+	bool lock_acq = false;
+
+	LOG_ENTRY_ARGS ("(osb=0x%p, poff=%u.%u, fe=0x%p)\n",
+			osb, parent_off, fe);
+
+	lockId = parent_off;
+
+	dirfe = ocfs_allocate_file_entry();
+	if (dirfe == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	/* Get a shared lock on the directory... */
+	status = ocfs_acquire_lock (osb, lockId, OCFS_DLM_SHARED_LOCK, FLAG_DIR,
+				    &lockres, dirfe);
+	if (status < 0) {
+		if (status != -EINTR)
+			LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	lock_acq = true;
+
+	if ((ofile == NULL)
+	    || ((ofile != NULL) && (ofile->curr_dir_buf == NULL))) {
+		pDirNode = ocfs_allocate_dirnode();	
+		if (pDirNode == NULL) {
+			LOG_ERROR_STATUS (status = -ENOMEM);
+			goto leave;
+		}
+
+		if (ofile != NULL) {
+			ofile->curr_dir_buf = pDirNode;
+		}
+	} else {
+		pDirNode = ofile->curr_dir_buf;
+	}
+
+	if ((ofile != NULL) && (ofile->curr_dir_off > 0)) {
+		thisDirNode = ofile->curr_dir_off;
+		if (pDirNode->node_disk_off == thisDirNode) {
+			bReadDirNode = false;
+		}
+	} else {
+		thisDirNode = parent_off;
+	}
+
+	if (bReadDirNode) {
+		status = ocfs_read_dir_node (osb, pDirNode, thisDirNode);
+		if (status < 0) {
+			/* Volume should be disabled in this case */
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+	}
+
+	status = -ENOENT;
+
+	/* if file_name is null here, it means that we want to walk the */
+	/* directory for all files if it is not null, it means we want */
+	/* a particular file */
+	if (file_name == NULL) {
+		bRet = ocfs_walk_dir_node (osb, pDirNode, fe, ofile);
+		if (bRet)
+			status = 0;
+	} else {
+		bRet = ocfs_search_dir_node (osb, pDirNode, file_name, fe, ofile);
+		if (bRet)
+			status = 0;
+	}
+
+	if (status >= 0 && (fe->attribs & OCFS_ATTRIB_FILE_CDSL)) {
+		/* Return the relevant CDSL for this node */
+		ocfs_find_create_cdsl (osb, fe);
+	}
+
+      leave:
+	if (lock_acq) {
+		tmpstat = ocfs_release_lock (osb, lockId, OCFS_DLM_SHARED_LOCK,
+					     FLAG_DIR, lockres, dirfe);
+		if (tmpstat < 0) {
+			LOG_ERROR_STATUS (tmpstat);
+			/* Volume should be disabled in this case */
+		}
+	}
+
+	ocfs_release_file_entry(dirfe);
+	ocfs_put_lockres (lockres);
+
+	if (ofile == NULL && pDirNode) {
+		ocfs_release_dirnode (pDirNode);
+	}
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_find_files_on_disk */
+
+/* ocfs_initialize_dir_node()
+ *
+ */
+void ocfs_initialize_dir_node (ocfs_super * osb, ocfs_dir_node * dir_node,
+			       __u64 bitmap_off, __u64 file_off, __u32 node)
+{
+	LOG_ENTRY ();
+
+	memset (dir_node, 0, sizeof (ocfs_dir_node));
+	strcpy (dir_node->signature, OCFS_DIR_NODE_SIGNATURE);
+
+	dir_node->num_ents = (__u8) osb->max_dir_node_ent;
+	dir_node->node_disk_off = bitmap_off;
+	dir_node->alloc_file_off = file_off;
+	dir_node->alloc_node = node;
+
+	DISK_LOCK_CURRENT_MASTER (dir_node) = OCFS_INVALID_NODE_NUM;
+
+	dir_node->free_node_ptr = INVALID_NODE_POINTER;
+	dir_node->next_node_ptr = INVALID_NODE_POINTER;
+	dir_node->indx_node_ptr = INVALID_NODE_POINTER;
+	dir_node->next_del_ent_node = INVALID_NODE_POINTER;
+	dir_node->head_del_ent_node = INVALID_NODE_POINTER;
+
+	dir_node->first_del = INVALID_DIR_NODE_INDEX;
+	dir_node->index_dirty = 0;
+
+	LOG_EXIT ();
+	return;
+}				/* ocfs_initialize_dir_node */
+
+/* ocfs_delete_file_entry()
+ *
+ */
+int
+ocfs_delete_file_entry (ocfs_super * osb,
+		 ocfs_file_entry * fe, __u64 parent_off, __s32 log_node_num)
+{
+	int status = 0;
+	__u32 size;
+	ocfs_cleanup_record *pCleanupLogRec = NULL;
+
+	LOG_ENTRY ();
+
+	size = sizeof (ocfs_cleanup_record);
+	size = (__u32) OCFS_ALIGN (size, OCFS_PAGE_SIZE);
+
+	pCleanupLogRec = ocfs_malloc (size);
+	if (pCleanupLogRec == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	/* Now start writing the cleanup log of the filentry master. */
+	/* It is this node for normal cases and or the node we are doing */
+	/* recovery for. */
+
+	pCleanupLogRec->log_id = osb->curr_trans_id;
+	pCleanupLogRec->log_type = LOG_DELETE_ENTRY;
+
+	pCleanupLogRec->rec.del.node_num = log_node_num;
+	pCleanupLogRec->rec.del.ent_del = fe->this_sector;
+	pCleanupLogRec->rec.del.parent_dirnode_off = parent_off;
+	pCleanupLogRec->rec.del.flags = 0;
+
+	status = ocfs_write_node_log (osb, (ocfs_log_record *) pCleanupLogRec,
+				   log_node_num, LOG_CLEANUP);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	if (fe->link_cnt) {
+		/* Decrement Link count when implementing links... TODO*/
+		OCFS_SET_FLAG (fe->sync_flags, OCFS_SYNC_FLAG_NAME_DELETED);
+		fe->sync_flags &= (~OCFS_SYNC_FLAG_VALID);
+	} else {
+		OCFS_SET_FLAG (fe->sync_flags, OCFS_SYNC_FLAG_MARK_FOR_DELETION);
+		fe->sync_flags &= (~OCFS_SYNC_FLAG_VALID);
+	}
+
+	status = ocfs_write_file_entry (osb, fe, fe->this_sector);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	/* Free up all the bits in the bitmap. */
+	if (fe->attribs & OCFS_ATTRIB_DIRECTORY) {
+		/* Write to the cleanup record which bits need to be freed for */
+		/* the ocfs_dir_node */
+
+		/* Iterate through all the dir nodes for this directory and free them */
+
+		/* TODO Free the index nodes too. */
+
+		status = ocfs_free_directory_block (osb, fe, log_node_num);
+		if (status < 0)
+			LOG_ERROR_STATUS (status);
+		goto leave;
+	} else {
+		/* Write to the cleanup record which bits need to be freed for */
+		/* the cluster bitmap */
+		status = ocfs_free_file_extents (osb, fe, log_node_num);
+		if (status < 0)
+			LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+      leave:
+	ocfs_safefree (pCleanupLogRec);
+
+	LOG_EXIT_STATUS (status);
+	return (status);
+}				/* ocfs_delete_file_entry */
+
+/* ocfs_rename_file()
+ *
+ */
+int
+ocfs_rename_file (ocfs_super * osb,
+		__u64 parent_off, struct qstr * file_name, __u64 file_off)
+{
+	int status = 0;
+	int tmpstat;
+	ocfs_dir_node *pLockNode = NULL;
+	ocfs_file_entry *fe = NULL;
+	ocfs_file_entry *lockfe = NULL;
+	__u64 changeSeqNum = 0;
+	bool bAcquiredLock = false;
+	__u32 lockFlags = 0;
+	ocfs_lock_res *pLockResource = NULL;
+	__u64 lockId = 0;
+	bool bParentLockAcquired = false;
+	__u32 parentLockFlags;
+	ocfs_lock_res *pParentLockResource = NULL;
+	__u64 parentLockId;
+	__u32 index;
+
+	LOG_ENTRY ();
+
+	parentLockId = parent_off;
+	parentLockFlags = (FLAG_FILE_CREATE | FLAG_DIR);
+	status = ocfs_acquire_lock (osb, parentLockId, OCFS_DLM_EXCLUSIVE_LOCK,
+				    (__u32) parentLockFlags, &pParentLockResource,
+				    NULL);
+	if (status < 0) {
+		if (status != -EINTR)
+			LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	bParentLockAcquired = true;
+
+	status = ocfs_get_file_entry (osb, &fe, file_off);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	/* lock file ent for a dir is out in the 1st extent, this_sector for file */
+	if (fe->attribs & OCFS_ATTRIB_DIRECTORY) {
+		lockId = fe->extents[0].disk_off;
+		lockFlags = (FLAG_DIR | FLAG_FILE_RENAME);
+		lockfe = ocfs_allocate_file_entry(); 
+		if (lockfe == NULL) {
+			LOG_ERROR_STATUS (status = -ENOMEM);
+			goto leave;
+		}
+	} else {
+		lockId = fe->this_sector;
+		lockFlags = FLAG_FILE_RENAME;
+		lockfe = fe;
+	}
+
+	status = ocfs_acquire_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
+				    lockFlags, &pLockResource, lockfe);
+	if (status < 0) {
+		if (status != -EINTR)
+			LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	bAcquiredLock = true;
+
+	/* Change the name and write it back.... */
+        fe->filename[0] = '\0';
+	strncpy (fe->filename, file_name->name, file_name->len);
+	fe->filename[file_name->len] = '\0';
+
+	DISK_LOCK_SEQNUM (fe) = changeSeqNum;
+
+	/* Set the Valid bit here */
+	SET_VALID_BIT (fe->sync_flags);
+	fe->sync_flags &= ~(OCFS_SYNC_FLAG_CHANGE);
+
+	status = ocfs_get_file_entry (osb, (ocfs_file_entry **) & pLockNode,
+				      fe->dir_node_ptr);
+	pLockNode->index_dirty = 1;
+	pLockNode->bad_off = (fe->this_sector - fe->dir_node_ptr) / osb->sect_size;
+	pLockNode->bad_off -= 1;
+
+	for (index = 0; index < pLockNode->num_ent_used; index++) {
+		if (pLockNode->index[index] == pLockNode->bad_off)
+			break;
+	}
+
+	if (index < pLockNode->num_ent_used) {
+		memmove (&pLockNode->index[index], &pLockNode->index[index + 1],
+			 pLockNode->num_ent_used - (index + 1));
+		pLockNode->index[pLockNode->num_ent_used - 1] = pLockNode->bad_off;
+
+		status = ocfs_write_file_entry (osb, (ocfs_file_entry *) pLockNode,
+						fe->dir_node_ptr);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+	}
+
+	status = ocfs_write_file_entry (osb, fe, fe->this_sector);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	LOG_TRACE_ARGS ("sector=%u.%u, name=%s\n", HI (fe->this_sector),
+			LO (fe->this_sector), fe->filename);
+
+	/* Update the disk as the other node will not see this file directory */
+	if (DISK_LOCK_FILE_LOCK (pLockNode) < OCFS_DLM_ENABLE_CACHE_LOCK) {
+		status = ocfs_force_put_file_entry (osb, fe, true);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+	}
+
+	if (index < pLockNode->num_ent_used) {
+		status = ocfs_reindex_dir_node (osb, fe->dir_node_ptr, NULL);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+	}
+
+      leave:
+
+	if (bAcquiredLock) {
+		tmpstat = ocfs_release_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
+					    lockFlags, pLockResource, lockfe);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+	}
+
+	if (bParentLockAcquired) {
+		tmpstat = ocfs_release_lock (osb, parentLockId,
+				OCFS_DLM_EXCLUSIVE_LOCK, parentLockFlags,
+				pParentLockResource, NULL);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+	}
+
+	if (lockfe != fe)
+		ocfs_release_file_entry (lockfe);
+	ocfs_release_file_entry (fe);
+	ocfs_release_file_entry ((ocfs_file_entry *) pLockNode);
+	ocfs_put_lockres (pLockResource);
+	ocfs_put_lockres (pParentLockResource);
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_rename_file */
+
+/* ocfs_del_file()
+ *
+ */
+int
+ocfs_del_file (ocfs_super * osb, __u64 parent_off, __u32 flags, __u64 file_off)
+{
+	int status = 0;
+	int tmpstat;
+	ocfs_file_entry *fe = NULL;
+	__u32 size = 0;
+	ocfs_dir_node *pLockNode = NULL;
+	__u32 lockFlags = 0;
+	bool bAcquiredLock = false;
+	ocfs_lock_res *pLockResource = NULL;
+	ocfs_cleanup_record *pCleanupLogRec = NULL;
+	ocfs_log_record *pOcfsLogRec;
+	__u64 lockId = 0;
+	__u32 log_node_num = OCFS_INVALID_NODE_NUM;
+
+	LOG_ENTRY_ARGS ("(osb=0x%p, poff=%u.%u, fl=%u, foff=%u.%u)\n",
+			osb, HILO(parent_off), flags, HILO(file_off));
+
+	status = ocfs_get_file_entry (osb, &fe, file_off);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	if (fe->attribs & OCFS_ATTRIB_DIRECTORY) {
+		lockId = fe->extents[0].disk_off;
+		lockFlags = (FLAG_FILE_DELETE | FLAG_DIR);
+		pLockNode = (ocfs_dir_node *) ocfs_allocate_file_entry ();
+		if (pLockNode == NULL) {
+			LOG_ERROR_STATUS (status = -ENOMEM);
+			goto leave;
+		}
+	} else {
+		lockId = fe->this_sector;
+		lockFlags = (FLAG_FILE_DELETE);
+		pLockNode = (ocfs_dir_node *)fe;
+	}
+	status = ocfs_acquire_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
+			lockFlags, &pLockResource, (ocfs_file_entry *) pLockNode);
+	if (status < 0) {
+		if (status != -EINTR)
+			LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	bAcquiredLock = true;
+
+	size = sizeof (ocfs_cleanup_record);
+	size = (__u32) OCFS_ALIGN (size, OCFS_PAGE_SIZE);
+
+	pCleanupLogRec = ocfs_malloc (size);
+	if (pCleanupLogRec == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	log_node_num = osb->node_num;
+
+	if (flags & FLAG_DEL_NAME) {
+		/* Now start writing the cleanup log of the filentry master. */
+		/* It is this node for normal cases and or the node we are doing */
+		/* recovery for. */
+		pCleanupLogRec->log_id = osb->curr_trans_id;
+		pCleanupLogRec->log_type = LOG_DELETE_ENTRY;
+
+		pCleanupLogRec->rec.del.node_num = log_node_num;
+		pCleanupLogRec->rec.del.ent_del = fe->this_sector;
+		pCleanupLogRec->rec.del.parent_dirnode_off = parent_off;
+		pCleanupLogRec->rec.del.flags = 0;
+
+		status = ocfs_write_node_log (osb,
+				(ocfs_log_record *) pCleanupLogRec,
+				log_node_num, LOG_CLEANUP);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+		status = 0;
+		goto leave;
+	}
+
+	/* Ask for a lock on the file to ensure there are no open oin's */
+	/* on the file on any node */
+	if (fe->attribs & OCFS_ATTRIB_DIRECTORY) {
+		if ((pLockNode->num_ent_used > 0) && !(flags & FLAG_DEL_NAME)) {
+			status = -ENOTEMPTY;
+			goto leave;
+		}
+	}
+
+	pOcfsLogRec = (ocfs_log_record *) pCleanupLogRec;
+
+	pOcfsLogRec->log_id = osb->curr_trans_id;
+	pOcfsLogRec->log_type = LOG_MARK_DELETE_ENTRY;
+
+	pOcfsLogRec->rec.del.node_num = log_node_num;
+	pOcfsLogRec->rec.del.ent_del = fe->this_sector;
+	pOcfsLogRec->rec.del.parent_dirnode_off = parent_off;
+
+	if (flags & FLAG_RESET_VALID) {
+		pOcfsLogRec->rec.del.flags = FLAG_RESET_VALID;
+	} else {
+		pOcfsLogRec->rec.del.flags = 0;
+	}
+
+	status = ocfs_write_log (osb, pOcfsLogRec, LOG_RECOVER);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	status = ocfs_delete_file_entry (osb, fe, parent_off, log_node_num);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	/* free up fileentry */
+
+      leave:
+
+        /* NEW: adding a fake release lock for the dead file entry here */
+        /* need this to alert dentry-owners on other nodes */
+        /* Release the file lock if we acquired it */
+	if (bAcquiredLock && lockFlags != 0 && lockId != 0) {
+		tmpstat = ocfs_release_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
+					    lockFlags, pLockResource,
+					    (ocfs_file_entry *)pLockNode);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+	}
+
+	if ((fe != (ocfs_file_entry *) pLockNode))
+		ocfs_release_file_entry ((ocfs_file_entry *) pLockNode);
+
+	ocfs_release_file_entry (fe);
+	ocfs_safefree (pCleanupLogRec);
+	ocfs_put_lockres (pLockResource);
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_del_file */
+
+/* ocfs_extend_file()
+ *
+ */
+int ocfs_extend_file (ocfs_super * osb, __u64 parent_off,
+		ocfs_inode * oin, __u64 file_size, __u64 * file_off)
+{
+	int status = 0;
+	int tmpstat;
+	ocfs_dir_node *pLockNode = NULL;
+	ocfs_file_entry *fileEntry = NULL;
+	__u64 tempOffset = 0;
+	__u64 allocSize = 0;
+	__u32 size;
+	__u64 bitmapOffset = 0;
+	__u64 numClustersAlloc = 0;
+	__u64 lockId = 0;
+	__u32 lockFlags = 0;
+	bool bFileLockAcquired = false;
+	bool bAcquiredLock = false;
+	ocfs_lock_res *pLockResource = NULL;
+	__u64 changeSeqNum = 0;
+	__u64 actualDiskOffset = 0;
+	__u64 actualLength = 0;
+	bool bCacheLock = false;
+
+	LOG_ENTRY ();
+
+	if (file_size == 0)
+		goto leave;
+
+	fileEntry = ocfs_allocate_file_entry ();
+	if (fileEntry == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	status = ocfs_read_file_entry (osb, fileEntry, *file_off);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	if (!IS_VALID_FILE_ENTRY(fileEntry)) {
+		LOG_ERROR_ARGS ("Invalid fe at offset %u.%u", HI(*file_off),
+				LO(*file_off));
+		status = -EFAIL;
+		goto leave;
+	}
+
+	/* Grab a lock on the entry found if we have more than 1 extents and */
+	/* also make this node the master*/
+
+	/* now we always take an EXTEND lock */
+	lockId = fileEntry->this_sector;
+	lockFlags = FLAG_FILE_EXTEND;
+	bFileLockAcquired = true;
+	pLockNode = (ocfs_dir_node *)fileEntry;
+
+	if ((DISK_LOCK_FILE_LOCK (fileEntry) == OCFS_DLM_ENABLE_CACHE_LOCK) &&
+	    (DISK_LOCK_CURRENT_MASTER (fileEntry) == osb->node_num)) {
+		bCacheLock = true;
+	}
+
+	status = ocfs_acquire_lock (osb, lockId,
+				    (bCacheLock ? OCFS_DLM_ENABLE_CACHE_LOCK :
+				                  OCFS_DLM_EXCLUSIVE_LOCK),
+				    lockFlags, &pLockResource,
+				    (ocfs_file_entry *) pLockNode);
+	if (status < 0) {
+		if (status != -EINTR)
+			LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	bAcquiredLock = true;
+
+	if (bCacheLock) {
+		DISK_LOCK_FILE_LOCK (fileEntry) = OCFS_DLM_ENABLE_CACHE_LOCK;
+		DISK_LOCK_CURRENT_MASTER (fileEntry) = osb->node_num;
+	}
+
+	if (file_size > (__s64) fileEntry->alloc_size) {
+		allocSize = file_size - fileEntry->alloc_size;
+
+		/* TODO: We can add something here so that after 2-3 allocations, */
+		/* we give a lot more disk space to the file than the allocSize so */
+		/* in order to try to use the Extents of File Entry only and ofcourse */
+		/* the file will have more contigous disk space. */
+		{
+			__u64 tempSize = fileEntry->alloc_size;
+
+			if (tempSize > ONE_MEGA_BYTE)
+				tempSize = ONE_MEGA_BYTE;
+			allocSize += (tempSize * 2);
+			if (allocSize < fileEntry->alloc_size / 100) {
+				allocSize = fileEntry->alloc_size / 100;
+				allocSize = OCFS_ALIGN(allocSize, (10*ONE_MEGA_BYTE));
+			}
+		}
+
+		status = ocfs_find_contiguous_space_from_bitmap (osb, allocSize,
+					&bitmapOffset, &numClustersAlloc, false);
+		if (status < 0) {
+			if (status != -ENOSPC)
+				LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+
+		actualDiskOffset =
+		    (bitmapOffset * osb->vol_layout.cluster_size) +
+		    osb->vol_layout.data_start_off;
+		actualLength =
+		    (__u64) (numClustersAlloc * osb->vol_layout.cluster_size);
+
+		LOG_TRACE_ARGS ("ocfs: extend %s fe=%u.%u (%u.%u + %u.%u = %u.%u)\n",
+		       fileEntry->filename, HILO(fileEntry->this_sector),
+		       HILO(fileEntry->alloc_size), HILO(actualLength),
+		       HILO(fileEntry->alloc_size + actualLength));
+
+		/* note: ok if oin is null here, not used in ocfs_allocate_extent */
+		status = ocfs_allocate_extent (osb, oin, fileEntry,
+					actualDiskOffset, actualLength);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+
+		/* update the total allocation size here */
+		fileEntry->alloc_size += actualLength;
+
+		if (oin) {
+			ocfs_down_sem (&(oin->main_res), true);
+			oin->alloc_size = fileEntry->alloc_size;
+			ocfs_up_sem (&(oin->main_res));
+		}
+
+		/* no need to do OCFS_SECTOR_ALIGN once the allocation size is correct. */
+		DISK_LOCK_SEQNUM (fileEntry) = changeSeqNum;
+	}
+
+	/* Update tha file size and add the new one to old one. */
+	fileEntry->file_size = file_size;
+
+	/* Set the Valid bit and reset the change bit here... TODO */
+	SET_VALID_BIT (fileEntry->sync_flags);
+	fileEntry->sync_flags &= ~(OCFS_SYNC_FLAG_CHANGE);
+
+	fileEntry->modify_time = CURRENT_TIME;
+
+	tempOffset = fileEntry->this_sector;
+	size = (__u32) OCFS_ALIGN (sizeof (ocfs_file_entry), osb->sect_size);
+
+	status = ocfs_write_file_entry (osb, (ocfs_file_entry *) fileEntry,
+					tempOffset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	/* Update all open oins */
+
+	/* Our local update is done, if somebody had asked for a bdcast lock  */
+	/* He shd set the state */
+
+      leave:
+	if (bAcquiredLock) {
+		if (bFileLockAcquired)
+			lockFlags |= FLAG_FILE_UPDATE_OIN;
+
+		tmpstat = ocfs_release_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
+					     lockFlags, pLockResource, fileEntry);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+	}
+
+	ocfs_release_file_entry (fileEntry);
+	ocfs_put_lockres (pLockResource);
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_extend_file */
+
+/* ocfs_change_file_size()
+ *
+ */
+int ocfs_change_file_size (ocfs_super * osb,
+		    __u64 parent_off,
+		    ocfs_inode * oin,
+		    __u64 file_size, __u64 * file_off, struct iattr *attr)
+{
+	int status = 0;
+	int tmpstat;
+	ocfs_dir_node *pLockNode = NULL;
+	ocfs_file_entry *fileEntry = NULL;
+	__u64 dirOffset = 0;
+	__u32 size;
+	bool bFileLockAcquired = false;
+	bool bAcquiredLock = false;
+	ocfs_lock_res *pLockResource = NULL;
+	__u64 changeSeqNum = 0;
+	__u64 lockId = 0;
+	__u32 lockFlags = 0;
+	bool bCacheLock = false;
+
+	LOG_ENTRY ();
+
+	fileEntry = ocfs_allocate_file_entry ();
+	if (fileEntry == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	status = ocfs_read_file_entry (osb, fileEntry, *file_off);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	if (!IS_VALID_FILE_ENTRY(fileEntry)) {
+		LOG_ERROR_ARGS ("Invalid fe at offset %u.%u", HI(*file_off),
+				LO(*file_off));
+		status = -EFAIL;
+		goto leave;
+	}
+
+	/* Acquire the Lock using TCP/IP and disk based locking */
+	if ((DISK_LOCK_FILE_LOCK (fileEntry) == OCFS_DLM_ENABLE_CACHE_LOCK) &&
+	    (DISK_LOCK_CURRENT_MASTER (fileEntry) == osb->node_num)) {
+		bCacheLock = true;
+	}
+
+	/* now we always take an UPDATE lock */
+	lockId = fileEntry->this_sector;
+	lockFlags = FLAG_FILE_UPDATE;
+	bFileLockAcquired = true;
+	pLockNode = (ocfs_dir_node *)fileEntry;
+
+	status = ocfs_acquire_lock (osb, lockId,
+				    (bCacheLock ? OCFS_DLM_ENABLE_CACHE_LOCK :
+				    		  OCFS_DLM_EXCLUSIVE_LOCK),
+				    lockFlags, &pLockResource,
+				    (ocfs_file_entry *) pLockNode);
+	if (status < 0) {
+		if (status != -EINTR)
+			LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	bAcquiredLock = true;
+
+	if (bCacheLock) {
+		DISK_LOCK_FILE_LOCK (fileEntry) = OCFS_DLM_ENABLE_CACHE_LOCK;
+		DISK_LOCK_CURRENT_MASTER (fileEntry) = osb->node_num;
+	}
+
+	fileEntry->modify_time = CURRENT_TIME;
+
+	DISK_LOCK_SEQNUM (fileEntry) = changeSeqNum;
+	if (attr->ia_valid & ATTR_SIZE)
+		fileEntry->file_size = attr->ia_size;
+	if (attr->ia_valid & ATTR_UID)
+		fileEntry->uid = attr->ia_uid;
+	if (attr->ia_valid & ATTR_GID)
+		fileEntry->gid = attr->ia_gid;
+	if (attr->ia_valid & ATTR_MODE)
+		fileEntry->prot_bits = attr->ia_mode & 0007777;
+	if (attr->ia_valid & ATTR_CTIME)
+		fileEntry->create_time = attr->ia_ctime;
+	if (attr->ia_valid & ATTR_MTIME)
+		fileEntry->modify_time = attr->ia_mtime;
+
+	/* Set the valid bit here */
+	SET_VALID_BIT (fileEntry->sync_flags);
+	fileEntry->sync_flags &= ~(OCFS_SYNC_FLAG_CHANGE);
+
+	dirOffset = fileEntry->this_sector;
+
+	size = (__u32) OCFS_SECTOR_ALIGN (sizeof (ocfs_file_entry));
+	status =
+	    ocfs_write_file_entry (osb, (ocfs_file_entry *) fileEntry, dirOffset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+      leave:
+	if (bAcquiredLock) {
+		if (bFileLockAcquired)
+			lockFlags |= FLAG_FILE_UPDATE_OIN;
+
+		tmpstat = ocfs_release_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
+					     lockFlags, pLockResource, fileEntry);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+	}
+
+	ocfs_release_file_entry (fileEntry);
+	ocfs_put_lockres (pLockResource);
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_change_file_size */
+
+/* ocfs_get_dirnode()
+ *
+ */
+int ocfs_get_dirnode(ocfs_super *osb, ocfs_dir_node *lockn, __u64 lockn_off,
+		     ocfs_dir_node *dirn)
+{
+	int status = 0;
+	__u64 node_off;
+
+	LOG_ENTRY_ARGS ("(lockn_off=%u.%u)\n", HILO (lockn_off));
+
+	if (lockn->head_del_ent_node != INVALID_NODE_POINTER)
+		node_off = lockn->head_del_ent_node;
+	else {
+    		if (lockn->free_node_ptr == INVALID_NODE_POINTER)
+			node_off = lockn_off;
+		else
+			node_off = lockn->free_node_ptr;
+	}
+
+	status = ocfs_read_dir_node (osb, dirn, node_off);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	if (dirn->node_disk_off != lockn->head_del_ent_node)
+		goto leave;
+
+	if (dirn->num_ent_used < osb->max_dir_node_ent)
+		goto leave;
+
+	/* dirn with no free slots and pointed to by head_del_ent_node */
+	node_off = lockn_off;
+	while (1) {
+		status = ocfs_read_dir_node (osb, dirn, node_off);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+
+		if (dirn->num_ent_used < osb->max_dir_node_ent) {
+			if (lockn->node_disk_off != dirn->node_disk_off)
+				lockn->head_del_ent_node = dirn->node_disk_off;
+			else
+				dirn->head_del_ent_node = dirn->node_disk_off;
+			goto leave;
+		}
+
+		node_off = dirn->next_node_ptr;
+
+		if (node_off == INVALID_NODE_POINTER) {
+			if (lockn->node_disk_off != dirn->node_disk_off)
+				lockn->head_del_ent_node = INVALID_NODE_POINTER;
+			else
+				dirn->head_del_ent_node = INVALID_NODE_POINTER;
+			goto leave;
+		}
+	}
+
+leave:
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_get_dirnode */
+
+/* ocfs_create_directory()
+ *
+ */
+int ocfs_create_directory (ocfs_super * osb, __u64 parent_off, ocfs_file_entry * fe)
+{
+	int status = 0;
+	int tmpstat;
+	ocfs_file_entry *fileEntry = NULL;
+	ocfs_dir_node *PDirNode = NULL;
+	ocfs_dir_node *PNewDirNode = NULL;
+	ocfs_dir_node *pLockNode = NULL;
+	__u64 allocSize = 0;
+	__u64 bitmapOffset;
+	__u64 numClustersAlloc = 0;
+	__u64 fileOffset = 0;
+	__u64 lockId = 0;
+	ocfs_lock_res *pLockResource = NULL;
+	__u32 lockFlags = 0;
+	bool bAcquiredLock = false;
+
+	LOG_ENTRY ();
+
+	fileEntry = fe;
+
+	pLockNode = (ocfs_dir_node *) ocfs_allocate_file_entry ();
+	if (pLockNode == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	lockId = parent_off;
+	lockFlags = FLAG_FILE_CREATE | FLAG_DIR;
+
+	status = ocfs_acquire_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
+				    lockFlags, &pLockResource,
+				    (ocfs_file_entry *) pLockNode);
+	if (status < 0) {
+		if (status != -EINTR)
+			LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	bAcquiredLock = true;
+
+	/* Zero out the entry for the file and rewrite it back to the disk */
+	/* Also, the other nodes should update their cache bitmap for file */
+	/* ent to mark this one as free now. */
+
+	allocSize = osb->vol_layout.dir_node_size;
+
+	status = ocfs_alloc_node_block (osb, allocSize, &bitmapOffset,
+				&fileOffset, &numClustersAlloc, osb->node_num,
+				DISK_ALLOC_DIR_NODE);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	/* update the total allocation size here */
+	fileEntry->alloc_size = osb->vol_layout.dir_node_size;
+	fileEntry->extents[0].disk_off = bitmapOffset;
+	fileEntry->file_size = osb->vol_layout.dir_node_size;
+	fileEntry->next_del = INVALID_DIR_NODE_INDEX;
+
+	if (DISK_LOCK_FILE_LOCK (pLockNode) != OCFS_DLM_ENABLE_CACHE_LOCK)
+		DISK_LOCK_FILE_LOCK (fileEntry) = OCFS_DLM_NO_LOCK;
+
+	PDirNode = ocfs_allocate_dirnode();
+	if (PDirNode == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	PNewDirNode = PDirNode;
+
+	ocfs_initialize_dir_node (osb, PNewDirNode, bitmapOffset, fileOffset,
+				  osb->node_num);
+
+	DISK_LOCK_CURRENT_MASTER (PNewDirNode) = osb->node_num;
+	DISK_LOCK_FILE_LOCK (PNewDirNode) = OCFS_DLM_ENABLE_CACHE_LOCK;
+	PNewDirNode->dir_node_flags |= DIR_NODE_FLAG_ROOT;
+
+	status = ocfs_write_metadata (osb, PNewDirNode,
+				      osb->vol_layout.dir_node_size,
+				      PNewDirNode->node_disk_off);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	// do we need to keep this???
+	status = ocfs_write_dir_node (osb, PNewDirNode, -1);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	if (pLockResource->lock_type != OCFS_DLM_ENABLE_CACHE_LOCK) {
+		status = ocfs_write_force_dir_node (osb, PNewDirNode, -1);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+	}
+
+	status = ocfs_get_dirnode(osb, pLockNode, parent_off, PDirNode);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	if (DISK_LOCK_FILE_LOCK (pLockNode) != OCFS_DLM_ENABLE_CACHE_LOCK)
+		DISK_LOCK_FILE_LOCK (fileEntry) = OCFS_DLM_NO_LOCK;
+
+	OcfsQuerySystemTime (&DISK_LOCK_LAST_WRITE (fileEntry));
+	OcfsQuerySystemTime (&DISK_LOCK_LAST_READ (fileEntry));
+
+	DISK_LOCK_WRITER_NODE (fileEntry) = osb->node_num;
+	DISK_LOCK_READER_NODE (fileEntry) = osb->node_num;
+
+	status = ocfs_insert_file (osb, PDirNode, fileEntry, pLockNode,
+				   pLockResource);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	bAcquiredLock = false;
+
+      leave:
+	if (bAcquiredLock) {
+		tmpstat = ocfs_release_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
+					     lockFlags, pLockResource,
+					     (ocfs_file_entry *) pLockNode);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+	}
+	ocfs_release_dirnode (PDirNode);
+	ocfs_release_file_entry ((ocfs_file_entry *) pLockNode);
+	ocfs_put_lockres (pLockResource);
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_create_directory */
+
+/* ocfs_create_file()
+ *
+ */
+int ocfs_create_file (ocfs_super * osb, __u64 parent_off, ocfs_file_entry * fe)
+{
+	int status = 0;
+	int tmpstat;
+	ocfs_file_entry *fileEntry = NULL;
+	ocfs_dir_node *PDirNode = NULL;
+	ocfs_dir_node *pLockNode = NULL;
+	__u64 lockId = 0;
+	ocfs_lock_res *pLockResource = NULL;
+	__u32 lockFlags = 0;
+	bool bAcquiredLock = false;
+
+	LOG_ENTRY_ARGS ("(osb=0x%p, poff=%u.%u, fe=0x%p)\n", osb,
+		       	HILO(parent_off), fe);
+
+	/* Zero out the entry for the file and rewrite it back to the disk */
+	/* Also, the other nodes should update their cache bitmap for file */
+	/* ent to mark this one as free now. */
+	pLockNode = (ocfs_dir_node *) ocfs_allocate_file_entry ();
+	if (pLockNode == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	lockId = parent_off;
+	lockFlags = FLAG_FILE_CREATE | FLAG_DIR;
+
+	status = ocfs_acquire_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
+				    lockFlags, &pLockResource,
+				    (ocfs_file_entry *) pLockNode);
+	if (status < 0) {
+		if (status != -EINTR)
+			LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	bAcquiredLock = true;
+
+	/* Change the name and write it back... */
+	fileEntry = fe;
+
+	PDirNode = ocfs_allocate_dirnode();
+	if (PDirNode == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	status = ocfs_get_dirnode(osb, pLockNode, parent_off, PDirNode);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	OcfsQuerySystemTime (&DISK_LOCK_LAST_WRITE (fileEntry));
+	OcfsQuerySystemTime (&DISK_LOCK_LAST_READ (fileEntry));
+
+	DISK_LOCK_WRITER_NODE (fileEntry) = osb->node_num;
+	DISK_LOCK_READER_NODE (fileEntry) = osb->node_num;
+
+	status = ocfs_insert_file (osb, PDirNode, fileEntry, pLockNode,
+				   pLockResource);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	bAcquiredLock = false;
+
+      leave:
+	if (bAcquiredLock) {
+		tmpstat = ocfs_release_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
+					     lockFlags, pLockResource,
+					     (ocfs_file_entry *) pLockNode);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+	}
+	ocfs_release_dirnode (PDirNode);
+	ocfs_release_file_entry ((ocfs_file_entry *) pLockNode);
+	ocfs_put_lockres (pLockResource);
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_create_file */
+
+/*
+ * ocfs_create_modify_file()
+ *
+ * Looks up for the existence of the filename in the oins in memory
+ * and the entries on the disk.
+ */
+int
+ocfs_create_modify_file (ocfs_super * osb,
+		  __u64 parent_off,
+		  ocfs_inode * oin,
+		  struct qstr * file_name,
+		  __u64 file_size,
+		  __u64 * file_off, __u32 flags, ocfs_file_entry * fe, struct iattr *attr)
+{
+	int status = 0;
+	int tmpstat = 0;
+	ocfs_file_entry *newfe = NULL;
+	__u64 changeSeqNum = 0;
+        __u64 t;
+
+	LOG_ENTRY_ARGS ("(osb=0x%p, poff=%u.%u, fe=0x%p)\n",
+			osb, HILO(parent_off), fe);
+
+	ocfs_start_trans (osb);
+
+	changeSeqNum = osb->curr_trans_id;
+	switch (flags) {
+	    case FLAG_FILE_EXTEND:
+		    status = ocfs_extend_file (osb, parent_off, oin, file_size,
+					       file_off);
+		    if (status < 0) {
+			    if (status != -ENOSPC && status != -EINTR)
+			    	LOG_ERROR_STATUS (status);
+			    goto leave;
+		    }
+		    break;
+
+	    case FLAG_FILE_DELETE:
+		    status = ocfs_del_file (osb, parent_off, 0, *file_off);
+		    if (status < 0) {
+			    if (status != -EINTR && status != -ENOTEMPTY)
+				    LOG_ERROR_STATUS (status);
+			    goto leave;
+		    }
+		    break;
+
+	    case FLAG_FILE_CREATE_DIR:
+		    if (fe == NULL) {
+			    newfe = ocfs_allocate_file_entry ();
+			    if (newfe == NULL) {
+				    LOG_ERROR_STATUS (status = -ENOMEM);
+				    goto leave;
+			    }
+		    } else {
+			    newfe = fe;
+		    }
+
+		    /* Change the name and write it back... */
+		    strncpy (newfe->filename, file_name->name, file_name->len);
+                    newfe->filename[file_name->len]='\0';
+		    newfe->filename_len = file_name->len;
+
+		    /* Set the valid bit here */
+		    SET_VALID_BIT (newfe->sync_flags);
+		    newfe->sync_flags &= ~(OCFS_SYNC_FLAG_CHANGE);
+		    newfe->attribs |= (OCFS_ATTRIB_DIRECTORY);
+
+		    DISK_LOCK_SEQNUM (newfe) = changeSeqNum;
+
+		    /* Initialize the lock state */
+		    DISK_LOCK_CURRENT_MASTER (newfe) = osb->node_num;
+		    DISK_LOCK_FILE_LOCK (newfe) = OCFS_DLM_ENABLE_CACHE_LOCK;
+		    DISK_LOCK_READER_NODE (newfe) = osb->node_num;
+		    DISK_LOCK_WRITER_NODE (newfe) = osb->node_num;
+                    OcfsQuerySystemTime(&t);
+                    DISK_LOCK_LAST_WRITE(newfe) = t;
+                    DISK_LOCK_LAST_READ(newfe) = t;
+
+		    newfe->create_time = newfe->modify_time = CURRENT_TIME;
+
+		    status = ocfs_create_directory (osb, parent_off, newfe);
+		    if (status >= 0) 
+			    *file_off = newfe->this_sector;
+		    else {
+			    if (status != -EINTR)
+			    	LOG_ERROR_STATUS (status);
+			    goto leave;
+		    }
+		    break;
+
+	    case FLAG_FILE_CREATE:
+		    if (fe == NULL) {
+			    newfe = ocfs_allocate_file_entry ();
+			    if (newfe == NULL) {
+				    LOG_ERROR_STATUS (status = -ENOMEM);
+				    goto leave;
+			    }
+		    } else {
+			    newfe = fe;
+		    }
+
+		    strncpy (newfe->filename, file_name->name, file_name->len);
+                    newfe->filename[file_name->len]='\0';
+		    newfe->filename_len = file_name->len;
+
+		    /* Set the flag to use the local extents */
+		    newfe->local_ext = true;
+		    newfe->granularity = -1;
+		    newfe->next_free_ext = 0;
+		    newfe->last_ext_ptr = 0;
+
+		    strcpy (newfe->signature, OCFS_FILE_ENTRY_SIGNATURE);
+
+		    /* Set the valid bit here */
+		    SET_VALID_BIT (newfe->sync_flags);
+		    newfe->sync_flags &= ~(OCFS_SYNC_FLAG_CHANGE);
+
+		    /* Initialize the lock state */
+		    DISK_LOCK_SEQNUM (newfe) = changeSeqNum;
+
+		    DISK_LOCK_CURRENT_MASTER (newfe) = osb->node_num;
+		    DISK_LOCK_FILE_LOCK (newfe) = OCFS_DLM_ENABLE_CACHE_LOCK;
+		    DISK_LOCK_READER_NODE (newfe) = osb->node_num;
+		    DISK_LOCK_WRITER_NODE (newfe) = osb->node_num;
+                    OcfsQuerySystemTime(&t);
+                    DISK_LOCK_LAST_WRITE(newfe) = t;
+                    DISK_LOCK_LAST_READ(newfe) = t;
+
+		    newfe->create_time = newfe->modify_time = CURRENT_TIME;
+
+		    status = ocfs_create_file (osb, parent_off, newfe);
+		    if (status >= 0) 
+			    *file_off = newfe->this_sector;
+		    else {
+			    if (status != -EINTR)
+			    	LOG_ERROR_STATUS (status);
+			    goto leave;
+		    }
+		    break;
+
+	    case FLAG_FILE_DELETE_CDSL:
+		    status = ocfs_delete_cdsl (osb, parent_off, fe);
+		    if (status < 0) {
+			    if (status != -EINTR)
+			    	LOG_ERROR_STATUS (status);
+			    goto leave;
+		    }
+		    break;
+
+	    case FLAG_FILE_CREATE_CDSL:
+		    status = ocfs_create_cdsl (osb, parent_off, fe);
+		    if (status < 0) {
+			    if (status != -EINTR)
+			    	LOG_ERROR_STATUS (status);
+			    goto leave;
+		    }
+		    break;
+
+	    case FLAG_FILE_CHANGE_TO_CDSL:
+		    status = ocfs_change_to_cdsl (osb, parent_off, fe);
+		    if (status < 0) {
+			    if (status != -EINTR)
+			    	LOG_ERROR_STATUS (status);
+			    goto leave;
+		    }
+		    break;
+
+	    case FLAG_FILE_TRUNCATE:
+		    status = ocfs_truncate_file (osb, *file_off, file_size, oin);
+		    if (status < 0) {
+			    if (status != -EINTR)
+			    	LOG_ERROR_STATUS (status);
+			    goto leave;
+		    }
+		    break;
+
+	    case FLAG_FILE_UPDATE:
+		    status = ocfs_change_file_size (osb, parent_off, oin, 
+					    file_size, file_off, attr);
+		    if (status < 0) {
+			    if (status != -EINTR)
+			    	LOG_ERROR_STATUS (status);
+			    goto leave;
+		    }
+		    break;
+
+	    default:
+		    break;
+	}
+
+	status = ocfs_commit_trans (osb, osb->curr_trans_id);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+      leave:
+	if (status < 0) {
+		tmpstat = ocfs_abort_trans (osb, osb->curr_trans_id);
+		if (tmpstat < 0) {
+			LOG_ERROR_STATUS (tmpstat);
+			/* VOL DISABLE TODO */
+			status = tmpstat;
+		}
+	}
+
+	osb->trans_in_progress = false;
+
+	if ((newfe != fe))
+		ocfs_release_file_entry (newfe);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_create_modify_file */
+
+
+/*
+ * ocfs_initialize_oin()
+ *
+ * Initialize a oin structure and file object. This function is called
+ * whenever a file is recognized for the first time.
+ */
+int
+ocfs_initialize_oin (ocfs_inode * oin,
+		   ocfs_super * osb,
+		   __u32 flags, struct file *file_obj, __u64 file_off, __u64 lock_id)
+{
+	int status = 0;
+
+	LOG_ENTRY ();
+
+	if (!(flags & OCFS_OIN_ROOT_DIRECTORY)) {
+		status = ocfs_create_update_lock (osb, oin, lock_id, flags);
+		if (status < 0) {
+			/* This can be okay as the other node can tell us the */
+			/* file was deleted. */
+			goto leave;
+		}
+	}
+
+        oin->dir_disk_off = 0;
+	oin->osb = osb;
+	INIT_LIST_HEAD (&(oin->next_ofile));
+	oin->oin_flags |= flags;
+	oin->open_hndl_cnt = 0;
+	oin->file_disk_off = file_off;
+	ocfs_extent_map_init (&oin->map);
+
+      leave:
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_initialize_oin */
+
+
+/*
+ * ocfs_create_delete_cdsl()
+ *
+ */
+int ocfs_create_delete_cdsl (struct inode *inode, struct file *filp,
+			     ocfs_super * osb, ocfs_cdsl * cdsl)
+{
+	int status = 0;
+	struct qstr fileName;
+	bool bAcquiredOSB = false;
+	ocfs_file_entry *fe = NULL;
+	__u64 tempSize = 0;
+	__u64 fileEntry = 0;
+	__u64 parent_off;
+
+	LOG_ENTRY ();
+
+	if (cdsl->name[0] == '\0') {
+		LOG_ERROR_STATUS (status = -EINVAL);
+		goto leave;
+	}
+
+	ocfs_down_sem (&(osb->osb_res), true);
+	bAcquiredOSB = true;
+
+	fileName.name = cdsl->name;
+        fileName.len = strlen(cdsl->name);
+
+	fe = ocfs_allocate_file_entry ();
+	if (fe == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	memset (fe, 0, sizeof (ocfs_file_entry));
+	if (!ocfs_linux_get_inode_offset (inode, &parent_off, NULL)) {
+		LOG_ERROR_STATUS (status = -EFAIL);
+		goto leave;
+	}
+
+	status = ocfs_find_files_on_disk (osb, parent_off, &fileName, fe, NULL);
+
+	if (status >= 0) {
+		if (cdsl->operation & OCFS_CDSL_CREATE) {
+			/* Create a cdsl with a file/directory already present. */
+			if ((cdsl->flags & OCFS_FLAG_CDSL_DIR) &&
+			    (!(fe->attribs & OCFS_ATTRIB_DIRECTORY))) {
+				status = -EEXIST;
+				goto leave;
+			}
+
+			fe->attribs |= OCFS_ATTRIB_FILE_CDSL;
+
+			/* Initialize the lock state */
+			DISK_LOCK_SEQNUM (fe) = 0;
+			DISK_LOCK_CURRENT_MASTER (fe) = OCFS_INVALID_NODE_NUM;
+			DISK_LOCK_FILE_LOCK (fe) = OCFS_DLM_NO_LOCK;
+			DISK_LOCK_READER_NODE (fe) = OCFS_INVALID_NODE_NUM;
+			DISK_LOCK_WRITER_NODE (fe) = OCFS_INVALID_NODE_NUM;
+
+			OcfsQuerySystemTime (&fe->modify_time);
+
+			fe->create_time = fe->modify_time;
+
+			status = ocfs_create_modify_file (osb, parent_off, NULL,
+					NULL, tempSize, &fileEntry,
+					FLAG_FILE_CHANGE_TO_CDSL, fe, NULL);
+			if (status != -EINTR)
+				LOG_ERROR_STATUS (status);
+			goto leave;
+		} else if ((cdsl->operation & OCFS_CDSL_DELETE)) {
+			status = ocfs_create_modify_file (osb, parent_off, NULL,
+					NULL, tempSize, &fileEntry,
+					FLAG_FILE_DELETE_CDSL, fe, NULL);
+			if (status == -EINTR)
+				LOG_ERROR_STATUS (status);
+			goto leave;
+		} else {
+			status = -EINVAL;
+			goto leave;
+		}
+	}
+
+	if ((status == -ENOENT) && (cdsl->operation & OCFS_CDSL_CREATE)) {
+		memset (fe, 0, sizeof (ocfs_file_entry));
+		memcpy (fe->filename, cdsl->name, strlen (cdsl->name));
+		fe->filename_len = strlen (fe->filename);
+
+		/* Set the flag to use the local extents */
+		fe->local_ext = true;
+		fe->granularity = -1;
+		fe->next_free_ext = 0;
+		fe->last_ext_ptr = 0;
+		fe->attribs |= OCFS_ATTRIB_FILE_CDSL;
+#ifdef USERSPACE_TOOL
+		fe->uid = getuid();
+		fe->gid = getgid();
+#else
+                fe->uid = current->fsuid;
+                fe->gid = current->fsgid;
+#endif
+                fe->prot_bits = 0755; //mode & 0007777;
+	
+
+		if (cdsl->flags & OCFS_FLAG_CDSL_DIR) {
+			fe->attribs |= OCFS_ATTRIB_DIRECTORY;
+                }
+
+		strcpy (fe->signature, OCFS_FILE_ENTRY_SIGNATURE);
+
+		/* Set the valid bit here */
+
+		SET_VALID_BIT (fe->sync_flags);
+		fe->sync_flags &= ~(OCFS_SYNC_FLAG_CHANGE);
+
+		/* Initialize the lock state */
+		DISK_LOCK_SEQNUM (fe) = 0;
+		DISK_LOCK_CURRENT_MASTER (fe) = OCFS_INVALID_NODE_NUM;
+		DISK_LOCK_FILE_LOCK (fe) = OCFS_DLM_NO_LOCK;
+		DISK_LOCK_READER_NODE (fe) = OCFS_INVALID_NODE_NUM;
+		DISK_LOCK_WRITER_NODE (fe) = OCFS_INVALID_NODE_NUM;
+
+		OcfsQuerySystemTime (&fe->modify_time);
+
+		fe->create_time = fe->modify_time;
+
+		status = ocfs_create_modify_file (osb, parent_off, NULL, NULL,
+				tempSize, &fileEntry, FLAG_FILE_CREATE_CDSL,
+				fe, NULL);
+
+		if (status != -EINTR)
+			LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+      leave:
+	if (bAcquiredOSB) {
+		ocfs_up_sem (&(osb->osb_res));
+		bAcquiredOSB = false;
+	}
+
+	ocfs_release_file_entry (fe);
+
+	LOG_EXIT_STATUS (status);
+	return (status);
+}  /* ocfs_create_delete_cdsl */
+
+
+/*
+ * ocfs_find_create_cdsl()
+ *
+ */
+int ocfs_find_create_cdsl (ocfs_super * osb, ocfs_file_entry * fe)
+{
+	int status = 0;
+	__u8 *buffer = NULL;
+	__u64 cdslOffset;
+	__u64 *cdslInfo;
+	ocfs_file_entry *new_fe = NULL;
+	__u32 length;
+	ocfs_dir_node *dnode;
+	ocfs_dir_node *new_dnode;
+
+	LOG_ENTRY ();
+
+	/* Read and see if we have a relevant entry for this node */
+
+	new_fe = ocfs_allocate_file_entry ();
+	if (new_fe == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	memcpy (new_fe, fe, sizeof (ocfs_file_entry));
+
+	length = (8 * OCFS_MAXIMUM_NODES);
+        length = OCFS_ALIGN (length, OCFS_SECTOR_SIZE);
+	status = ocfs_read_disk_ex (osb, (void **) &buffer, length, length,
+				    fe->extents[0].disk_off);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	cdslInfo = (__u64 *) buffer;
+	cdslOffset = cdslInfo[osb->node_num];
+	if (cdslOffset == 0) {
+		__u64 physicalOffset, fileOffset, numSectorsAlloc, bitmapOffset,
+		    numClustersAlloc;
+
+		/* create the entry if one doesn't exist and modify the cdsl data */
+
+		/* Allocate contiguous blocks on disk */
+		status = ocfs_alloc_node_block (osb, OCFS_SECTOR_SIZE,
+			&physicalOffset, &fileOffset, (__u64 *) & numSectorsAlloc,
+			osb->node_num, DISK_ALLOC_EXTENT_NODE);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+
+		if (fileOffset == 0) {
+			LOG_TRACE_ARGS ("offset=0, file=%s\n", fe->filename);
+		}
+
+		new_fe->this_sector = physicalOffset;
+
+		cdslInfo[osb->node_num] = cdslOffset = physicalOffset;
+
+		if (new_fe->attribs & OCFS_ATTRIB_DIRECTORY) {
+			status = ocfs_alloc_node_block (osb,
+				osb->vol_layout.dir_node_size, &bitmapOffset,
+				&fileOffset, &numClustersAlloc, osb->node_num,
+				DISK_ALLOC_DIR_NODE);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto leave;
+			}
+
+			/* update the total allocation size here */
+			new_fe->alloc_size = osb->vol_layout.dir_node_size;
+			new_fe->extents[0].disk_off = bitmapOffset;
+			new_fe->file_size = osb->vol_layout.dir_node_size;
+			new_fe->next_del = INVALID_DIR_NODE_INDEX;
+
+			dnode = ocfs_malloc (osb->vol_layout.dir_node_size);
+			if (dnode == NULL) {
+				LOG_ERROR_STATUS (status = -ENOMEM);
+				goto leave;
+			}
+
+			new_dnode = dnode;
+			memset (new_dnode, 0, osb->vol_layout.dir_node_size);
+
+			ocfs_initialize_dir_node (osb, new_dnode,
+				  bitmapOffset, fileOffset, osb->node_num);
+
+			DISK_LOCK_CURRENT_MASTER (new_dnode) = osb->node_num;
+			DISK_LOCK_FILE_LOCK (new_dnode) =
+						OCFS_DLM_ENABLE_CACHE_LOCK;
+			new_dnode->dir_node_flags |= DIR_NODE_FLAG_ROOT;
+
+			status = ocfs_write_dir_node (osb, new_dnode, -1);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto leave;
+			}
+		} else {
+			/* This is a file */
+			new_fe->extents[0].disk_off = 0;
+			new_fe->alloc_size = 0;
+			new_fe->file_size = 0;
+		}
+
+		status = ocfs_write_file_entry (osb, new_fe,
+						new_fe->this_sector);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+
+		status = ocfs_write_disk (osb, (__s8 *) buffer, length,
+					  fe->extents[0].disk_off);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+		memcpy (fe, new_fe, OCFS_SECTOR_SIZE);
+
+	} else {
+		status = ocfs_read_disk (osb, (__s8 *) fe, OCFS_SECTOR_SIZE,
+					 cdslOffset);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+	}
+
+      leave:
+	ocfs_safefree (buffer);
+	ocfs_release_file_entry (new_fe);
+	LOG_EXIT_STATUS (status);
+	return (status);
+}  /* ocfs_find_create_cdsl */
+
+
+#ifdef UNUSED_CODE
+/*
+ * ocfs_update_file_entry_slot()
+ *
+ */
+int ocfs_update_file_entry_slot (ocfs_super * osb, ocfs_inode * oin,
+				 ocfs_rw_mode rw_mode)
+{
+	int status = 0;
+	ocfs_file_entry *fe = NULL;
+
+	LOG_ENTRY ();
+
+	fe = ocfs_allocate_file_entry ();
+	if (fe == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	status = ocfs_read_file_entry (osb, (void *) fe, oin->file_disk_off);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	/* Update tick count if needed i.e., our slot time has expired */
+
+	if (rw_mode == OCFS_WRITE) {
+		OcfsQuerySystemTime (&DISK_LOCK_LAST_WRITE (fe));
+		DISK_LOCK_WRITER_NODE (fe) = osb->node_num;
+	} else {
+		OcfsQuerySystemTime (&DISK_LOCK_LAST_READ (fe));
+		DISK_LOCK_READER_NODE (fe) = osb->node_num;
+	}
+
+	status = ocfs_write_force_disk (osb, (void *) fe, osb->sect_size,
+					oin->file_disk_off);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+      leave:
+	ocfs_release_file_entry (fe);
+
+	LOG_EXIT_STATUS (status);
+	return (status);
+}  /* ocfs_update_file_entry_slot */
+
+/*
+ * ocfs_check_lock_state()
+ *
+ */
+void ocfs_check_lock_state (ocfs_super * osb, ocfs_inode * oin)
+{
+	int status = 0;
+	ocfs_lock_res *pLockRes = NULL;
+	__u64 readTimediff = 0;
+	__u64 writeTimediff = 0;
+	__u64 newTime = 0;
+
+	LOG_ENTRY ();
+
+	pLockRes = oin->lock_res;
+	OCFS_ASSERT (pLockRes);
+	ocfs_get_lockres (pLockRes);
+
+	OcfsQuerySystemTime (&newTime);
+
+	readTimediff = (__u64) (newTime - pLockRes->last_read_time);
+	writeTimediff = (__u64) (newTime - pLockRes->last_write_time);
+
+	/* Check the lock Id for which we are doing a open if somebody owns */
+	/* a cache on it ask for a flush. If there is no cache but a master */
+	/* which has a timestamp which is still in the slot */
+	/* ??? Do we want to do Update master on open in this case or just */
+	/* revert to Write Thru. Read caching can be enabled if we have a */
+	/* lot of readers but no writers. In this case when a writer comes */
+	/* it will need to update all readers so that they update their cache. */
+	/* Slot for reader, slot for writers can solve the issue. */
+
+	if (pLockRes->lock_type == OCFS_DLM_ENABLE_CACHE_LOCK) {
+		if ((pLockRes->master_node_num == osb->node_num) &&
+		    (writeTimediff > CACHE_LOCK_SLOT_TIME)) {
+			oin->cache_enabled = true;
+			ocfs_update_file_entry_slot (osb, oin, OCFS_WRITE);
+			goto leave;
+		} else {
+			status = ocfs_break_cache_lock (osb, pLockRes);
+			if (status < 0) {
+				if (status != -EINTR)
+					LOG_ERROR_STATUS (status);
+				goto leave;
+			}
+
+			oin->cache_enabled = false;
+			pLockRes->lock_type = OCFS_DLM_NO_LOCK;
+			status = 0;
+			goto leave;
+		}
+	}
+
+	if ((pLockRes->lock_type <= OCFS_DLM_SHARED_LOCK) &&
+	    (readTimediff > CACHE_LOCK_SLOT_TIME)) {
+		if (writeTimediff > CACHE_LOCK_SLOT_TIME)
+			oin->cache_enabled = true;
+
+		ocfs_update_file_entry_slot (osb, oin, OCFS_READ);
+		status = 0;
+		goto leave;
+	}
+
+      leave:
+	ocfs_put_lockres (pLockRes, osb);
+	LOG_EXIT ();
+	return;
+}				/* ocfs_check_lock_state */
+#endif /* UNUSED_CODE */
+
+
+
+/*
+ * ocfs_delete_cdsl()
+ *
+ */
+int ocfs_delete_cdsl (ocfs_super * osb, __u64 parent_off, ocfs_file_entry * fe)
+{
+	int status = 0;
+	int tmpstat;
+	ocfs_file_entry *newfe = NULL;
+	ocfs_dir_node *pLockNode = NULL;
+	__u32 lockFlags = 0;
+	bool bAcquiredLock = false;
+	ocfs_lock_res *pLockResource = NULL;
+	__u64 lockId = 0;
+	bool bParentLockAcquired = false;
+	__u32 parentLockFlags = 0;
+	ocfs_lock_res *pParentLockResource = NULL;
+	__u64 parentLockId = 0;
+
+	LOG_ENTRY ();
+
+	newfe = fe;
+	if (newfe == NULL) {
+		LOG_ERROR_STATUS (status = -EINVAL);
+		goto leave;
+	}
+
+	if (newfe->link_cnt != 0) {
+		LOG_ERROR_STATUS (status = -ENOTEMPTY);
+		goto leave;
+	}
+
+	pLockNode = (ocfs_dir_node *) ocfs_allocate_file_entry ();
+	if (pLockNode == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	parentLockId = parent_off;
+	parentLockFlags = (FLAG_FILE_CREATE | FLAG_DIR);
+	status = ocfs_acquire_lock (osb, parentLockId, OCFS_DLM_EXCLUSIVE_LOCK,
+				    parentLockFlags, &pParentLockResource,
+				    (ocfs_file_entry *) pLockNode);
+	if (status < 0) {
+		if (status != -EINTR)
+			LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	bParentLockAcquired = true;
+
+	lockId = newfe->this_sector;
+	lockFlags = (FLAG_FILE_DELETE);
+
+	status = ocfs_acquire_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
+				    lockFlags, &pLockResource, newfe);
+	if (status < 0) {
+		if (status != -EINTR)
+			LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	bAcquiredLock = true;
+
+	/* Check the file Entry and call delete if link count == 0 */
+	if (newfe->link_cnt == 0) {
+		/* Mark the file as being deleted */
+		OCFS_SET_FLAG (fe->sync_flags, OCFS_SYNC_FLAG_MARK_FOR_DELETION);
+		fe->sync_flags &= (~OCFS_SYNC_FLAG_VALID);
+
+		status = ocfs_write_file_entry (osb, fe, fe->this_sector);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+
+		/* Lock on directory shd be held by the node which either */
+		/* died or this node... */
+
+		status = ocfs_del_file_entry (osb, newfe, pLockNode);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+	} else {
+		status = -ENOTEMPTY;
+		goto leave;
+	}
+
+      leave:
+	/* Release the file lock if we acquired it */
+	if (bAcquiredLock) {
+		tmpstat = ocfs_release_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
+					    lockFlags, pLockResource, newfe);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+	}
+
+	/* Release the file lock if we acquired it */
+	if (bParentLockAcquired) {
+		tmpstat = ocfs_release_lock (osb, parentLockId,
+				OCFS_DLM_EXCLUSIVE_LOCK, parentLockFlags,
+				pParentLockResource,
+				(ocfs_file_entry *)pLockNode);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+	}
+
+	ocfs_release_file_entry ((ocfs_file_entry *) pLockNode);
+	ocfs_put_lockres (pLockResource);
+	ocfs_put_lockres (pParentLockResource);
+	LOG_EXIT_STATUS (status);
+	return status;
+}
+
+
+/*
+ * ocfs_change_to_cdsl()
+ *
+ */
+int ocfs_change_to_cdsl (ocfs_super * osb, __u64 parent_off, ocfs_file_entry * fe)
+{
+	int status = 0, tmpstat = 0;
+	ocfs_file_entry *new_fe = NULL;
+	ocfs_dir_node *pLockNode = NULL;
+	__u32 length;
+	__u64 lockId = 0;
+	__u64 offset;
+	__u64 numClustersAlloc;
+	ocfs_lock_res *lockres = NULL;
+	__u32 lockFlags = 0;
+	bool bAcquiredLock = false;
+	__u8 *buffer = NULL;
+	__u64 *cdslInfo;
+	bool bCacheLock = false;
+
+	/* Zero out the entry for the file and rewrite it back to the disk */
+	/* Also, the other nodes should update their cache bitmap for file */
+	/* ent to mark this one as free now. */
+
+	LOG_ENTRY();
+
+	if (fe == NULL) {
+		LOG_ERROR_STATUS (status = -EINVAL);
+		goto leave;
+	}
+
+	new_fe = ocfs_allocate_file_entry ();
+	if (new_fe == NULL) {
+		LOG_ERROR_STATUS(status = -ENOMEM);
+		goto leave;
+	}
+
+	memcpy (new_fe, fe, sizeof (ocfs_file_entry));
+
+	if ((DISK_LOCK_FILE_LOCK (new_fe) == OCFS_DLM_ENABLE_CACHE_LOCK)
+	    && (DISK_LOCK_CURRENT_MASTER (new_fe) == osb->node_num)) {
+		bCacheLock = true;
+	}
+
+	lockId = new_fe->this_sector;
+	lockFlags = FLAG_FILE_CHANGE_TO_CDSL;
+	pLockNode = (ocfs_dir_node *) new_fe;
+
+	status = ocfs_acquire_lock (osb, lockId,
+				    (bCacheLock ? OCFS_DLM_ENABLE_CACHE_LOCK :
+				    		  OCFS_DLM_EXCLUSIVE_LOCK),
+				    lockFlags, &lockres,
+				    (ocfs_file_entry *) pLockNode);
+	if (status < 0) {
+		if (status != -EINTR)
+			LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	bAcquiredLock = true;
+
+	if (bCacheLock) {
+		DISK_LOCK_FILE_LOCK (new_fe) = OCFS_DLM_ENABLE_CACHE_LOCK;
+		DISK_LOCK_CURRENT_MASTER (new_fe) = osb->node_num;
+	}
+
+	length = (8 * OCFS_MAXIMUM_NODES);
+	length = OCFS_ALIGN (length, OCFS_PAGE_SIZE);
+
+	status = ocfs_find_contiguous_space_from_bitmap (osb, length,
+				&offset, &numClustersAlloc, false);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+
+	new_fe->extents[0].disk_off = (offset * osb->vol_layout.cluster_size) +
+					osb->vol_layout.data_start_off;
+	new_fe->extents[0].num_bytes = numClustersAlloc *
+					osb->vol_layout.cluster_size;
+	new_fe->extents[0].file_off = 0;
+
+	new_fe->alloc_size = new_fe->file_size = new_fe->extents[0].num_bytes;
+
+	new_fe->attribs |= OCFS_ATTRIB_FILE_CDSL;
+
+	/* Initialize the table with 0 */
+	buffer = ocfs_malloc (length);
+	if (buffer == NULL) {
+		LOG_ERROR_STATUS(status = -ENOMEM);
+		goto leave;
+	}
+
+	memset (buffer, 0, length);
+	cdslInfo = (__u64 *) buffer;
+
+	/* Point entry for this node to the file entry we have */
+
+	{
+		__u64 physicalOffset, fileOffset, numSectorsAlloc;
+
+		/* create the entry if one doesn't exist and modify the cdsl data */
+
+		/* Allocate contiguous blocks on disk */
+		status =
+		    ocfs_alloc_node_block (osb, OCFS_SECTOR_SIZE, &physicalOffset,
+				    &fileOffset, (__u64 *) & numSectorsAlloc,
+				    osb->node_num, DISK_ALLOC_EXTENT_NODE);
+		if (status < 0) {
+			LOG_ERROR_STATUS(status);
+			goto leave;
+		}
+
+		fe->this_sector = physicalOffset;
+
+		*(cdslInfo + osb->node_num) = physicalOffset;
+
+		/* Write the new file entry to the disk */
+		status = ocfs_write_file_entry (osb, fe, physicalOffset);
+		if (status < 0) {
+			LOG_ERROR_STATUS(status);
+			goto leave;
+		}
+	}
+
+	status =
+	    ocfs_write_disk (osb, (__s8 *) buffer, length,
+			   new_fe->extents[0].disk_off);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+
+	OcfsQuerySystemTime (&DISK_LOCK_LAST_WRITE (new_fe));
+	OcfsQuerySystemTime (&DISK_LOCK_LAST_READ (new_fe));
+	DISK_LOCK_WRITER_NODE (new_fe) = osb->node_num;
+	DISK_LOCK_READER_NODE (new_fe) = osb->node_num;
+
+	/* Write the file entry with the cdsl back */
+	status = ocfs_write_file_entry (osb, new_fe, new_fe->this_sector);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+
+      leave:
+	if (bAcquiredLock) {
+		tmpstat = ocfs_release_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
+					     lockFlags, lockres, new_fe);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+	}
+
+	ocfs_release_file_entry (new_fe);
+	ocfs_safefree (buffer);
+	ocfs_put_lockres (lockres);
+	LOG_EXIT_STATUS(status);
+	return status;
+}  /* ocfs_change_to_cdsl */
+
+
+/*
+ * ocfs_create_cdsl()
+ *
+ */
+int ocfs_create_cdsl (ocfs_super * osb, __u64 parent_off, ocfs_file_entry * fe)
+{
+	int status = 0, tmpstat = 0;
+	ocfs_file_entry *fileEntry = NULL;
+	ocfs_dir_node *PDirNode = NULL, *pLockNode = NULL;
+	__u32 length;
+	__u64 lockId = 0, bitmapOffset, numClustersAlloc;
+	ocfs_lock_res *pLockResource = NULL;
+	__u32 lockFlags = 0;
+	bool bAcquiredLock = false;
+	__u8 *buffer = NULL;
+
+	LOG_ENTRY ();
+
+	/* Zero out the entry for the file and rewrite it back to the disk */ 
+	/* Also, the other nodes should update their cache bitmap for file */
+	/* ent to mark this one as free now. */
+
+	pLockNode = (ocfs_dir_node *) ocfs_allocate_file_entry ();
+	if (pLockNode == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	lockId = parent_off;
+	lockFlags = FLAG_FILE_CREATE | FLAG_DIR;
+
+	status = ocfs_acquire_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
+			lockFlags, &pLockResource, (ocfs_file_entry *) pLockNode);
+	if (status < 0) {
+		if (status != -EINTR)
+			LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+	bAcquiredLock = true;
+
+	/* Change the name and write it back... */
+	if (fe == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	fileEntry = fe;
+	length = (8 * OCFS_MAXIMUM_NODES);
+	length = OCFS_ALIGN (length, OCFS_PAGE_SIZE);
+
+	status = ocfs_find_contiguous_space_from_bitmap (osb, length,
+				&bitmapOffset, &numClustersAlloc, false);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	fileEntry->extents[0].disk_off =
+	    (bitmapOffset * osb->vol_layout.cluster_size)
+	    + osb->vol_layout.data_start_off;
+	fileEntry->extents[0].num_bytes =
+	    numClustersAlloc * osb->vol_layout.cluster_size;
+	fileEntry->extents[0].file_off = 0;
+
+	fileEntry->alloc_size = fileEntry->file_size =
+	    fileEntry->extents[0].num_bytes;
+
+	/* Initialize the table with 0 */
+	buffer = ocfs_malloc (length);
+	if (buffer == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	memset (buffer, 0, length);
+
+	status =
+	    ocfs_write_disk (osb, (__s8 *) buffer, length,
+			   fileEntry->extents[0].disk_off);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	PDirNode = ocfs_allocate_dirnode();
+	if (PDirNode == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	status = ocfs_get_dirnode(osb, pLockNode, parent_off, PDirNode);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	OcfsQuerySystemTime (&DISK_LOCK_LAST_WRITE (fileEntry));
+	OcfsQuerySystemTime (&DISK_LOCK_LAST_READ (fileEntry));
+	DISK_LOCK_WRITER_NODE (fileEntry) = osb->node_num;
+	DISK_LOCK_READER_NODE (fileEntry) = osb->node_num;
+
+	status = ocfs_insert_file (osb, PDirNode, fileEntry, pLockNode,
+				   pLockResource);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+
+	bAcquiredLock = false;
+
+      leave:
+	if (bAcquiredLock) {
+		tmpstat = ocfs_release_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
+					     lockFlags, pLockResource,
+					     (ocfs_file_entry *) pLockNode);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+	}
+
+	ocfs_release_dirnode (PDirNode);
+	ocfs_release_file_entry ((ocfs_file_entry *) pLockNode);
+	ocfs_safefree (buffer);
+	ocfs_put_lockres (pLockResource);
+	LOG_EXIT_STATUS (status);
+	return status;
+}  /* ocfs_create_cdsl */
+
+
+/*
+ * ocfs_truncate_file()
+ *
+ */
+int ocfs_truncate_file (ocfs_super * osb, __u64 file_off, __u64 file_size, ocfs_inode * oin)
+{
+	int status = 0, tmpstat;
+	ocfs_file_entry *fe = NULL;
+	__u64 lockId = 0;
+	__u32 lockFlags = 0;
+	bool bFileLockAcquired = false;
+	bool bAcquiredLock = false;
+	ocfs_lock_res *pLockResource = NULL;
+	__u64 changeSeqNum = 0;
+	bool bCacheLock = false;
+	ocfs_dir_node *pLockNode = NULL;
+        __u64 new_alloc_size;
+        __u32 csize = osb->vol_layout.cluster_size;
+
+	LOG_ENTRY ();
+
+        new_alloc_size = OCFS_ALIGN(file_size, csize);
+
+	fe = ocfs_allocate_file_entry ();
+	if (fe == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	status = ocfs_read_file_entry (osb, fe, file_off);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	if (!IS_VALID_FILE_ENTRY(fe)) {
+		LOG_ERROR_ARGS ("Invalid fe at offset %u.%u", HI(file_off),
+				LO(file_off));
+		status = -EFAIL;
+		goto leave;
+	}
+
+	lockId = fe->this_sector;
+	lockFlags = FLAG_FILE_TRUNCATE;
+	bFileLockAcquired = true;
+	pLockNode = (ocfs_dir_node *) fe;
+
+	if ((DISK_LOCK_FILE_LOCK (fe) == OCFS_DLM_ENABLE_CACHE_LOCK)
+	    && (DISK_LOCK_CURRENT_MASTER (fe) == osb->node_num)) {
+		bCacheLock = true;
+	}
+
+	status = ocfs_acquire_lock (osb, lockId,
+				    (bCacheLock ? OCFS_DLM_ENABLE_CACHE_LOCK :
+				    		  OCFS_DLM_EXCLUSIVE_LOCK),
+				    lockFlags, &pLockResource,
+				    (ocfs_file_entry *) pLockNode);
+	if (status < 0) {
+		if (status != -EINTR)
+			LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	bAcquiredLock = true;
+
+        LOG_TRACE_ARGS ("ocfs: truncate %s fe=%u.%u (%u.%u - %u.%u = %u.%u)\n",
+	       fe->filename, HILO(fe->this_sector), HILO(fe->alloc_size),
+	       HILO(fe->alloc_size - new_alloc_size), HILO(new_alloc_size));
+
+	fe->file_size = file_size;
+	fe->alloc_size = new_alloc_size;
+
+	status = ocfs_free_extents_for_truncate (osb, fe);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	if (bCacheLock) {
+		DISK_LOCK_FILE_LOCK (fe) = OCFS_DLM_ENABLE_CACHE_LOCK;
+		DISK_LOCK_CURRENT_MASTER (fe) = osb->node_num;
+	}
+
+	DISK_LOCK_SEQNUM (fe) = changeSeqNum;
+	SET_VALID_BIT (fe->sync_flags);
+	fe->sync_flags &= ~(OCFS_SYNC_FLAG_CHANGE);
+	OcfsQuerySystemTime (&fe->modify_time);
+
+	status = ocfs_write_file_entry (osb, fe, fe->this_sector);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	if (oin) {
+	/* if we updated correctly then we can update the OIN */
+		ocfs_down_sem (&(oin->main_res), true);
+		oin->alloc_size = new_alloc_size;
+		ocfs_up_sem (&(oin->main_res));
+	}
+
+      leave:
+	if (bAcquiredLock) {
+		if (bFileLockAcquired)
+			lockFlags |= FLAG_FILE_UPDATE_OIN;
+
+		tmpstat = ocfs_release_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
+					     lockFlags, pLockResource, fe);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+	}
+
+	ocfs_release_file_entry (fe);
+	ocfs_put_lockres (pLockResource);
+	LOG_EXIT_STATUS(status);
+	return status;
+}  /* ocfs_truncate_file */

Added: trunk/libocfs/Common/ocfsgendirnode.c
===================================================================
--- trunk/libocfs/Common/ocfsgendirnode.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/ocfsgendirnode.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,1635 @@
+/*
+ * ocfsgendirnode.c
+ *
+ * Allocate, free, read, write, find, etc. dirnodes.
+ *
+ * Copyright (C) 2002, 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifdef __KERNEL__
+#include <ocfs.h>
+#else
+#include <libocfs.h>
+#endif
+
+
+/* Tracing */
+#define OCFS_DEBUG_CONTEXT   OCFS_DEBUG_CONTEXT_DIRINFO
+
+/*
+ * ocfs_print_file_entry()
+ *
+ */
+void ocfs_print_file_entry (ocfs_file_entry * fe)
+{
+	LOG_TRACE_ARGS ("This fe has name %s\n", fe->filename);
+}				/* ocfs_print_file_entry */
+
+/*
+ * ocfs_print_dir_node()
+ *
+ */
+void ocfs_print_dir_node (ocfs_super * osb, ocfs_dir_node * DirNode)
+{
+	int i;
+	ocfs_file_entry *pOrigFileEntry;
+
+	if (DirNode->dir_node_flags & DIR_NODE_FLAG_ROOT)
+		LOG_TRACE_STR ("First dirnode of the dir");
+
+	LOG_TRACE_ARGS ("signature: %s\n", DirNode->signature);
+
+	LOG_TRACE_ARGS ("node_disk_off: %u.%u\n", HILO (DirNode->node_disk_off));
+
+	LOG_TRACE_ARGS ("num_ents: %u, num_ent_used: %u\n", DirNode->num_ents,
+		DirNode->num_ent_used);
+
+	for (i = 0; i < DirNode->num_ent_used; i++) {
+		pOrigFileEntry = FILEENT (DirNode, i);
+		LOG_TRACE_ARGS ("filename: %s\n", pOrigFileEntry->filename);
+	}
+}				/* ocfs_print_dir_node */
+
+/*
+ * ocfs_alloc_node_block()
+ *
+ */
+int ocfs_alloc_node_block (ocfs_super * osb,
+		__u64 FileSize,
+		__u64 * DiskOffset,
+		__u64 * file_off, __u64 * NumClusterAlloc, __u32 NodeNum, __u32 Type)
+{
+	int status = 0;
+	int tmpstat;
+	__u64 fileSize = 0;
+	__u64 offset = 0;
+	__u64 length = 0;
+	__u64 lockId = 0;
+	__u64 numBytes = 0;
+	__u64 allocSize = 0;
+	__u64 prevFileSize = 0;
+	__u64 extent;
+	__u64 newFileSize;
+	__u64 bitMapSize;
+	__u8 *buffer = NULL;
+	ocfs_alloc_bm DirAllocBitMap;
+	__u32 numBits = 0;
+	__u32 foundBit = -1;
+	__u32 blockSize = 0;
+	bool bLockAcquired = false;
+	ocfs_lock_res *pLockResource = NULL;
+	__u32 fileId = 0;
+	__u32 extendFileId = 0;
+	ocfs_log_record *pOcfsLogRec = NULL;
+	ocfs_file_entry *fe = NULL;
+
+	LOG_ENTRY ();
+
+	fe = ocfs_allocate_file_entry();
+	if (fe == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+#ifdef PARANOID_LOCKS
+	ocfs_down_sem (&(osb->dir_alloc_lock), true);
+	ocfs_down_sem (&(osb->file_alloc_lock), true);
+#endif
+	ocfs_down_sem (&(osb->vol_alloc_lock), true);
+
+	if (Type == DISK_ALLOC_DIR_NODE) {
+		fileId = OCFS_FILE_DIR_ALLOC_BITMAP + NodeNum;
+		blockSize = (__u32) osb->vol_layout.dir_node_size;
+		extendFileId = OCFS_FILE_DIR_ALLOC + NodeNum;
+	} else if (Type == DISK_ALLOC_EXTENT_NODE) {
+		fileId = OCFS_FILE_FILE_ALLOC_BITMAP + NodeNum;
+		extendFileId = OCFS_FILE_FILE_ALLOC + NodeNum;
+		blockSize = (__u32) osb->vol_layout.file_node_size;
+	}
+
+	/* Allocate a block of size blocksize from the relevant file/bitmap */
+
+	OCFS_ASSERT (blockSize);
+
+	lockId = (fileId * OCFS_SECTOR_SIZE) + osb->vol_layout.root_int_off;
+
+	/* Get a lock on the file */
+	status =
+	    ocfs_acquire_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
+			     FLAG_FILE_CREATE, &pLockResource, fe);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	bLockAcquired = true;
+
+	numBytes = OCFS_ALIGN ((FileSize), blockSize);
+	numBits = (__u32) (numBytes / blockSize);
+
+//    while(1)
+	{
+		/* Read in the bitmap file for the dir alloc and look for the required */
+		/* space, if found */
+		fileSize = fe->file_size;
+		allocSize = fe->alloc_size;
+
+		prevFileSize = fileSize;
+
+		if ((fileSize != 0) && (allocSize != 0)) {
+			/* Round this off to dirnodesize */
+			length = OCFS_ALIGN (allocSize, OCFS_PAGE_SIZE);
+
+			buffer = vmalloc (length);
+			if (buffer == NULL) {
+				LOG_ERROR_STATUS (status = -ENOMEM);
+				goto leave;
+			}
+
+			status =
+			    ocfs_read_system_file (osb, fileId, buffer, allocSize,
+					    offset);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto leave;
+			}
+
+			ocfs_initialize_bitmap (&DirAllocBitMap, (__u32 *) buffer,
+					      (__u32) (fileSize * 8));
+
+			/* Find the requisite number of bits... */
+
+			/* This function will check for clear bits in the Bitmap for */
+			/* consective clear bits equal to ClusterCount */
+			foundBit =
+			    ocfs_find_clear_bits (&DirAllocBitMap, (__u32) numBits,
+					       0, 0);
+		}
+
+		/* It returns -1 on failure , otherwise ByteOffset points at the */
+		/* location in bitmap from where there are ClusterCount no of bits */
+		/* are free. */
+
+		if (foundBit == -1) {
+			/* if not found add more allocation to the file and try again. */
+
+			/* Lets get a 1MB chunks every time or clustersize which ever */
+			/* is greater or the number of bit asked */
+			extent =
+			    ((ONE_MEGA_BYTE) >
+			     osb->vol_layout.
+			     cluster_size) ? (ONE_MEGA_BYTE) : osb->vol_layout.
+			    cluster_size;
+
+			extent = (extent > (numBits * blockSize)) ? extent :
+			    (numBits * blockSize);
+
+			extent = OCFS_ALIGN (extent, ONE_MEGA_BYTE);
+
+			status = ocfs_get_system_file_size (osb, (extendFileId),
+						&newFileSize, &allocSize);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto leave;
+			}
+
+			/* This is for OUI optimzation to allocate more disk space for */
+			/* directory allocations */
+
+			if (allocSize > 0)
+				extent *= 2;
+
+			status =
+			    ocfs_extend_system_file (osb, (extendFileId),
+					      newFileSize + extent, NULL);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto leave;
+			}
+
+			newFileSize += extent;
+			bitMapSize = newFileSize / (blockSize * 8);
+
+			/* Calculate the new bitmap size */
+			status = ocfs_extend_system_file (osb, fileId, bitMapSize, fe);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto leave;
+			}
+
+			/* ?? Free the buffer here */
+			vfree (buffer);
+			buffer = NULL;
+
+			fileSize = fe->file_size;
+			allocSize = fe->alloc_size;
+
+			length = OCFS_ALIGN (allocSize, OCFS_PAGE_SIZE);
+
+			buffer = vmalloc (length);
+			if (buffer == NULL) {
+				LOG_ERROR_STATUS (status = -ENOMEM);
+				goto leave;
+			}
+
+			status =
+			    ocfs_read_system_file (osb, fileId, buffer, allocSize,
+					    offset);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto leave;
+			}
+
+			ocfs_initialize_bitmap (&DirAllocBitMap, (__u32 *) buffer,
+					      (__u32) (fileSize * 8));
+
+			foundBit = prevFileSize * 8;
+//        continue;
+
+		}
+/*      else
+      {
+        break;
+      }
+*/
+	}
+
+	LOG_TRACE_ARGS ("byte offset=%d\n", foundBit);
+
+	ocfs_set_bits (&DirAllocBitMap, (__u32) foundBit, (__u32) numBits);
+
+	/* Log the change under current transid, */
+	{
+		__u32 size;
+
+		size = sizeof (ocfs_log_record);
+		size = (__u32) OCFS_ALIGN (size, osb->sect_size);
+
+		if ((pOcfsLogRec = ocfs_malloc (size)) == NULL) {
+			LOG_ERROR_STATUS (status = -ENOMEM);
+			goto leave;
+		}
+
+		pOcfsLogRec->log_id = osb->curr_trans_id;
+		pOcfsLogRec->log_type = LOG_TYPE_DISK_ALLOC;
+
+		pOcfsLogRec->rec.alloc.length = numBits;
+		pOcfsLogRec->rec.alloc.file_off = (foundBit * blockSize);
+		pOcfsLogRec->rec.alloc.type = Type;
+		pOcfsLogRec->rec.alloc.node_num = NodeNum;
+
+		/* Log the original dirnode sector and the new cluster where the */
+		/* info is stored */
+		status = ocfs_write_log (osb, pOcfsLogRec, LOG_RECOVER);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+	}
+
+	/* Write the bitmap file back */
+	status = ocfs_write_system_file (osb, fileId, buffer, allocSize, offset);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+
+	*DiskOffset = ocfs_file_to_disk_off (osb, (extendFileId),
+					(foundBit * blockSize));
+	if (*DiskOffset == 0) {
+		LOG_ERROR_STATUS(status = -EFAIL);
+		goto leave;
+	}
+
+	*file_off = (__u64) ((__u64) foundBit * (__u64) blockSize);
+	/* this can just fall through */
+	if (*file_off == 0) {
+		LOG_TRACE_ARGS ("offset=%u.%u, type=%x, blksz=%u, foundbit=%u\n",
+			HI(*file_off), LO(*file_off), Type, blockSize, foundBit);
+	}
+
+      leave:
+	
+        ocfs_up_sem (&(osb->vol_alloc_lock));
+#ifdef PARANOID_LOCKS
+	ocfs_up_sem (&(osb->file_alloc_lock));
+	ocfs_up_sem (&(osb->dir_alloc_lock));
+#endif
+	if (bLockAcquired) {
+		tmpstat =
+		    ocfs_release_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
+				     FLAG_FILE_CREATE, pLockResource, fe);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+	}
+
+	ocfs_safevfree (buffer);
+	ocfs_release_file_entry (fe);
+	ocfs_safefree (pOcfsLogRec);
+	ocfs_put_lockres (pLockResource);
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_alloc_node_block */
+
+/*
+ * ocfs_free_vol_block()
+ *
+ */
+int ocfs_free_vol_block (ocfs_super * osb, ocfs_free_log * FreeLog, __u32 NodeNum, __u32 Type)
+{
+	int status = 0;
+	__u64 fileSize = 0;
+	__u64 offset = 0;
+	__u64 length = 0;
+	__u64 allocSize = 0;
+	__u32 foundBit = -1;
+	__u32 blockSize = 0;
+	__u32 fileId = 0;
+	__u32 extendFileId = 0;
+	__u8 *buffer = NULL;
+	ocfs_alloc_bm AllocBitMap;
+	ocfs_alloc_bm *pTempBitMap;
+	__u32 i;
+	__u32 size;
+
+	LOG_ENTRY ();
+
+#ifdef PARANOID_LOCKS
+	ocfs_down_sem (&(osb->dir_alloc_lock), true);
+	ocfs_down_sem (&(osb->file_alloc_lock), true);
+#endif
+	ocfs_down_sem (&(osb->vol_alloc_lock), true);
+
+	switch (Type) {
+	    case DISK_ALLOC_DIR_NODE:
+		    fileId = OCFS_FILE_DIR_ALLOC_BITMAP + NodeNum;
+		    blockSize = (__u32) osb->vol_layout.dir_node_size;
+		    extendFileId = OCFS_FILE_DIR_ALLOC + NodeNum;
+
+		    if (!IS_VALID_NODE_NUM (NodeNum)) {
+			    LOG_ERROR_STATUS(status = -EINVAL);
+			    goto leave;
+		    }
+		    break;
+
+	    case DISK_ALLOC_EXTENT_NODE:
+		    fileId = OCFS_FILE_FILE_ALLOC_BITMAP + NodeNum;
+		    extendFileId = OCFS_FILE_FILE_ALLOC + NodeNum;
+		    blockSize = (__u32) osb->vol_layout.file_node_size;
+
+		    if (!IS_VALID_NODE_NUM (NodeNum)) {
+			    LOG_ERROR_STATUS(status = -EINVAL);
+			    goto leave;
+		    }
+		    break;
+
+	    case DISK_ALLOC_VOLUME:
+		    break;
+
+	    default:
+		    goto leave;
+	}
+
+	if (Type == DISK_ALLOC_VOLUME) {
+		size = (__u32) OCFS_SECTOR_ALIGN ((osb->cluster_bitmap.size) / 8);
+		status = ocfs_read_metadata (osb, osb->cluster_bitmap.buf, size,
+					   osb->vol_layout.bitmap_off);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+		pTempBitMap = &osb->cluster_bitmap;
+	} else {
+		/* Read in the bitmap file for the dir alloc and look for the */
+		/* required space, if found */
+
+		status = ocfs_get_system_file_size (osb, fileId, &fileSize, &allocSize);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+
+		/* Round this off to dirnodesize */
+		length = OCFS_ALIGN (allocSize, OCFS_PAGE_SIZE);
+
+                /* !!! vmalloc !!! */
+		if ((buffer = vmalloc (length)) == NULL) {
+			LOG_ERROR_STATUS (status = -ENOMEM);
+			goto leave;
+		}
+
+		status =
+		    ocfs_read_system_file (osb, fileId, buffer, allocSize, offset);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+
+		ocfs_initialize_bitmap (&AllocBitMap, (__u32 *) buffer,
+				      (__u32) (fileSize * 8));
+		pTempBitMap = &AllocBitMap;
+	}
+
+	for (i = 0; i < FreeLog->num_free_upds; i++) {
+		if (FreeLog->free_bitmap[i].file_off == 0 && Type == 0) {
+			LOG_ERROR_ARGS ("offset=0, type=%x, blksz=%d", Type,
+					blockSize);
+		}
+
+		if (Type == DISK_ALLOC_VOLUME)
+			foundBit = (__u32) FreeLog->free_bitmap[i].file_off;
+		else
+			foundBit =
+			    (__u32) (FreeLog->free_bitmap[i].file_off /
+				   blockSize);
+
+		ocfs_clear_bits (pTempBitMap, (__u32) foundBit,
+			       (__u32) FreeLog->free_bitmap[i].length);
+
+		LOG_TRACE_ARGS("gb_c: bit=%d, len=%u, i=%d\n", foundBit,
+			       (__u32)FreeLog->free_bitmap[i].length, i);
+	}
+
+	/* Write a cleanup log here */
+
+	if (Type == DISK_ALLOC_VOLUME) {
+		size = (__u32) OCFS_SECTOR_ALIGN ((osb->cluster_bitmap.size) / 8);
+
+#if 0
+		/* I have absolutely no idea why this is done twice! */
+		status = ocfs_write_disk (osb, osb->cluster_bitmap.buf,
+					size, osb->vol_layout.bitmap_off);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+#endif
+		status = ocfs_write_metadata (osb, osb->cluster_bitmap.buf,
+					    size, osb->vol_layout.bitmap_off);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+	} else {
+		status =
+		    ocfs_write_system_file (osb, fileId, buffer, allocSize, offset);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+	}
+      leave:
+	ocfs_up_sem (&(osb->vol_alloc_lock));
+#ifdef PARANOID_LOCKS
+	ocfs_up_sem (&(osb->file_alloc_lock));
+	ocfs_up_sem (&(osb->dir_alloc_lock));
+#endif
+	ocfs_safevfree (buffer);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_free_vol_block */
+
+/*
+ * ocfs_free_node_block()
+ *
+ */
+int ocfs_free_node_block (ocfs_super * osb, __u64 file_off, __u64 Length, __u32 NodeNum,
+	       __u32 Type)
+{
+	int status = 0;
+	int tmpstat;
+	__u64 fileSize = 0;
+	__u64 offset = 0;
+	__u64 length = 0;
+	__u64 lockId = 0;
+	__u64 allocSize = 0;
+	__u8 *buffer = NULL;
+	ocfs_alloc_bm DirAllocBitMap;
+	__u32 foundBit = -1;
+	__u32 blockSize = 0;
+	bool bLockAcquired = false;
+	ocfs_lock_res *pLockResource = NULL;
+	__u32 fileId = 0;
+	__u32 extendFileId = 0;
+	ocfs_file_entry *fe = NULL;
+
+	LOG_ENTRY ();
+
+	fe = ocfs_allocate_file_entry();
+	if (fe == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	if (Type == DISK_ALLOC_DIR_NODE) {
+		fileId = OCFS_FILE_DIR_ALLOC_BITMAP + NodeNum;
+		blockSize = (__u32) osb->vol_layout.dir_node_size;
+		extendFileId = OCFS_FILE_DIR_ALLOC + NodeNum;
+	} else if (Type == DISK_ALLOC_EXTENT_NODE) {
+		fileId = OCFS_FILE_FILE_ALLOC_BITMAP + NodeNum;
+		extendFileId = OCFS_FILE_FILE_ALLOC + NodeNum;
+		blockSize = (__u32) osb->vol_layout.file_node_size;
+	}
+
+	/* Allocate a block of size blocksize from the relevant file/bitmap */
+
+	lockId = (fileId * OCFS_SECTOR_SIZE) + osb->vol_layout.root_int_off;
+
+	/* Get a lock on the file */
+	status = ocfs_acquire_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
+				    FLAG_FILE_CREATE, &pLockResource, fe);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	bLockAcquired = true;
+
+	/* Read in the bitmap file for the dir alloc and look for the required */
+	/* space, if found */
+	status = ocfs_get_system_file_size (osb, fileId, &fileSize, &allocSize);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	/* Round this off to dirnodesize */
+	length = OCFS_ALIGN (allocSize, OCFS_PAGE_SIZE);
+
+	if ((buffer = ocfs_malloc (length)) == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	status = ocfs_read_system_file (osb, fileId, buffer, allocSize, offset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	ocfs_initialize_bitmap (&DirAllocBitMap, (__u32 *) buffer,
+			      (__u32) (fileSize * 8));
+
+	foundBit = (__u32) (file_off / blockSize);
+	ocfs_clear_bits (&DirAllocBitMap, (__u32) foundBit, (__u32) Length);
+
+	status = ocfs_write_system_file (osb, fileId, buffer, allocSize, offset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+      leave:
+	if (bLockAcquired) {
+		tmpstat = ocfs_release_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
+					     FLAG_FILE_CREATE, pLockResource, fe);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+	}
+
+	ocfs_safefree (buffer);
+	ocfs_release_file_entry (fe);
+	ocfs_put_lockres (pLockResource);
+	LOG_EXIT_STATUS (0);
+	return 0;
+}				/* ocfs_free_node_block */
+
+/*
+ * ocfs_free_directory_block()
+ *
+ */
+int ocfs_free_directory_block (ocfs_super * osb, ocfs_file_entry * fe, __s32 LogNodeNum)
+{
+	int status = 0;
+        ocfs_file_entry *dir_hdr_fe = NULL;
+	ocfs_dir_node *PDirNode;
+	__u32 size;
+	__u32 numUpdt;
+	__u64 currentDirNode;
+	ocfs_cleanup_record *pCleanupLogRec = NULL;
+
+	LOG_ENTRY ();
+
+	size = sizeof (ocfs_cleanup_record);
+	size = (__u32) OCFS_ALIGN (size, OCFS_PAGE_SIZE);
+
+	if ((pCleanupLogRec = ocfs_malloc (size)) == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	pCleanupLogRec->rec.free.num_free_upds = 0;
+
+	currentDirNode = fe->extents[0].disk_off;
+
+	size = OCFS_SECTOR_SIZE;
+
+	status = ocfs_get_file_entry (osb, &dir_hdr_fe, currentDirNode);
+	if (status < 0 || dir_hdr_fe==NULL) {
+                if (status >= 0)
+                        status = -EFAIL;
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+        /* alloc a file entry, but use it as a dir node header. yeah. ok. */
+        PDirNode = (ocfs_dir_node *)dir_hdr_fe;
+
+	pCleanupLogRec->log_id = osb->curr_trans_id;
+	pCleanupLogRec->log_type = LOG_FREE_BITMAP;
+
+	while ((PDirNode->node_disk_off != INVALID_NODE_POINTER) &&
+	       (IS_VALID_DIR_NODE (PDirNode))) {
+		/* Add to the cleanup log */
+		numUpdt = pCleanupLogRec->rec.free.num_free_upds;
+		if (numUpdt >= FREE_LOG_SIZE) {
+			status =
+			    ocfs_write_node_log (osb,
+					      (ocfs_log_record *)
+					      pCleanupLogRec, LogNodeNum,
+					      LOG_CLEANUP);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto leave;
+			}
+			numUpdt = pCleanupLogRec->rec.free.num_free_upds = 0;
+		}
+
+		pCleanupLogRec->rec.free.free_bitmap[numUpdt].length = 1;
+		pCleanupLogRec->rec.free.free_bitmap[numUpdt].file_off =
+		    PDirNode->alloc_file_off;
+		pCleanupLogRec->rec.free.free_bitmap[numUpdt].type =
+		    DISK_ALLOC_DIR_NODE;
+		pCleanupLogRec->rec.free.free_bitmap[numUpdt].node_num =
+		    PDirNode->alloc_node;
+		(pCleanupLogRec->rec.free.num_free_upds)++;
+
+		/* LOG_FREE_BITMAP */
+
+		if (PDirNode->next_node_ptr != INVALID_NODE_POINTER) {
+			status = ocfs_read_disk (osb, PDirNode,
+						 OCFS_SECTOR_SIZE,
+						 PDirNode->next_node_ptr);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto leave;
+			}
+			continue;
+		} else {
+			break;
+		}
+	}
+
+	/* Write the log and break */
+	if (pCleanupLogRec->rec.free.num_free_upds > 0) {
+		status =
+		    ocfs_write_node_log (osb, (ocfs_log_record *) pCleanupLogRec,
+				      LogNodeNum, LOG_CLEANUP);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+	}
+      leave:
+       	ocfs_release_file_entry(dir_hdr_fe);
+	ocfs_safefree (pCleanupLogRec);
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_free_directory_block */
+
+/*
+ * ocfs_recover_dir_node()
+ *
+ */
+int ocfs_recover_dir_node (ocfs_super * osb, __u64 OrigDirNodeOffset,
+			   __u64 SavedDirNodeOffset)
+{
+	LOG_ENTRY ();
+
+	LOG_EXIT_STATUS (0);
+	return 0;
+}				/* ocfs_recover_dir_node */
+
+#if 0
+/*
+ * ocfs_read_dir_node()
+ *
+ */
+int ocfs_read_dir_node (ocfs_super * osb, ocfs_dir_node * DirNode,
+			__u64 NodeDiskOffset)
+{
+	int status = 0;
+
+	LOG_ENTRY ();
+
+	/* Read in the Dir Node from the disk into the buffer supplied */
+	status = ocfs_read_disk (osb, DirNode, osb->vol_layout.dir_node_size,
+				 NodeDiskOffset);
+	if (status < 0) {
+ 		LOG_ERROR_ARGS ("status=%d, dirnodesz=%u.%u, off=%u.%u",
+ 				status, HILO(osb->vol_layout.dir_node_size),
+ 				HILO(NodeDiskOffset));
+	}
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_read_dir_node */
+#endif
+
+/*
+ * ocfs_write_force_dir_node()
+ *
+ */
+int ocfs_write_force_dir_node (ocfs_super * osb,
+		       ocfs_dir_node * DirNode, __s32 IndexFileEntry)
+{
+	int status = 0;
+
+	LOG_ENTRY ();
+
+	if (IndexFileEntry != -1) {
+		/* Read in the Dir Node from the disk into the buffer supplied */
+		status = ocfs_write_disk (osb,
+					(__u8 *) (((__u8 *) DirNode) +
+						 ((IndexFileEntry +
+						   1) * osb->sect_size)),
+					osb->sect_size,
+					DirNode->node_disk_off +
+					((IndexFileEntry +
+					  1) * osb->sect_size));
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+		}
+	}
+
+	/* Write the first sector last */
+	status = ocfs_write_disk (osb, DirNode, osb->sect_size,
+				  DirNode->node_disk_off);
+	if (status < 0)
+		LOG_ERROR_STATUS (status);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_write_force_dir_node */
+
+/*
+ * ocfs_write_dir_node()
+ *
+ */
+int ocfs_write_dir_node (ocfs_super * osb, ocfs_dir_node * DirNode, __s32 IndexFileEntry)
+{
+	int status = 0;
+	__u64 offset;
+	__u32 size;
+	__u8 *buffer;
+	bool bCacheWrite = false;
+	bool bFileCacheWrite = false;
+
+	LOG_ENTRY ();
+
+	if ((DISK_LOCK_CURRENT_MASTER (DirNode) == osb->node_num) &&
+	    (DISK_LOCK_FILE_LOCK (DirNode) == OCFS_DLM_ENABLE_CACHE_LOCK)) {
+		bCacheWrite = true;
+	}
+
+	if (IndexFileEntry != -1) {
+		ocfs_file_entry *fe = NULL;
+
+		/* Read in the Dir Node from the disk into the buffer supplied */
+
+		offset = DirNode->node_disk_off +
+		    ((IndexFileEntry + 1) * osb->sect_size);
+		size = (__u32) osb->sect_size;
+		buffer = (__u8 *) (((__u8 *) DirNode) +
+				  ((IndexFileEntry + 1) * osb->sect_size));
+		fe = (ocfs_file_entry *) buffer;
+
+		if ((DISK_LOCK_CURRENT_MASTER (fe) == osb->node_num) &&
+		    (DISK_LOCK_FILE_LOCK (fe) == OCFS_DLM_ENABLE_CACHE_LOCK)) {
+			bFileCacheWrite = true;
+		}
+
+		/* Write in the dir node */
+		if (bFileCacheWrite) {
+			status = ocfs_write_metadata (osb, buffer, size, offset);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+			}
+			if (!bCacheWrite) {
+				status =
+				    ocfs_write_disk (osb, buffer, size, offset);
+				if (status < 0) {
+					LOG_ERROR_STATUS (status);
+				}
+			}
+		} else {
+			status = ocfs_write_disk (osb, buffer, size, offset);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+			}
+		}
+	}
+
+	/* Write the first sector last */
+	offset = DirNode->node_disk_off;
+	size = (__u32) OCFS_SECTOR_SIZE;
+
+	/* Write the dir node */
+	if (bCacheWrite) {
+		status = ocfs_write_metadata (osb, DirNode, size, offset);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+		}
+	} else {
+		status = ocfs_write_disk (osb, DirNode, size, offset);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+		}
+	}
+
+	IF_TRACE (ocfs_print_dir_node (osb, DirNode));
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_write_dir_node */
+
+
+/*
+ * ocfs_walk_dir_node()
+ *
+ */
+bool ocfs_walk_dir_node (ocfs_super * osb, ocfs_dir_node * DirNode,
+			 ocfs_file_entry * found_fe, ocfs_file * OFile)
+{
+	__u32 start;
+	__u32 i;
+	ocfs_file_entry *fe;
+	int status;
+	bool bRet = false;
+
+	LOG_ENTRY ();
+
+	if (OFile != NULL)
+		start = OFile->curr_byte_off;
+	else
+		start = 0;
+
+	if (!IS_VALID_DIR_NODE (DirNode)) {
+		bRet = false;
+		goto bail;
+	}
+
+	while (1) {
+		/* Iterate thru this dirnode and find a matching entry */
+		for (i = start; i < DirNode->num_ent_used; i++) {
+			fe = FILEENT (DirNode, i);
+
+			if (IS_FE_DELETED(fe->sync_flags) ||
+			    (!(fe->sync_flags & OCFS_SYNC_FLAG_VALID))) {
+				continue;
+			}
+
+			/* Check to see if the name satisfies pattern */
+			{
+				if ((OFile == NULL)
+				    && (fe->attribs & OCFS_ATTRIB_DIRECTORY)) {
+					continue;
+				}
+
+				status = 0;
+				memcpy ((void *) found_fe, (void *) fe,
+					OCFS_SECTOR_SIZE);
+
+				LOG_TRACE_ARGS
+				    ("Returning entry: %u, name: %s\n", i,
+				     fe->filename);
+
+				if (OFile != NULL) {
+					OFile->curr_dir_off =
+					    DirNode->node_disk_off;
+					OFile->curr_byte_off = i + 1;
+				}
+
+				bRet = true;
+				goto bail;
+			}
+		}
+
+		if (DirNode->next_node_ptr != -1) {
+			status =
+			    ocfs_read_dir_node (osb, DirNode,
+					     DirNode->next_node_ptr);
+
+			if (!IS_VALID_DIR_NODE (DirNode)) {
+				bRet = false;
+				goto bail;
+			}
+			start = 0;
+			continue;
+		} else {
+			/* We are done... */
+			break;
+		}
+	}
+
+	if (OFile != NULL) {
+		OFile->curr_dir_off = DirNode->node_disk_off;
+		OFile->curr_byte_off = i + 1;
+	}
+
+      bail:
+	LOG_EXIT_ULONG (bRet);
+	return bRet;
+}				/* ocfs_walk_dir_node */
+
+/*
+ * ocfs_search_dir_node()
+ *
+ */
+bool ocfs_search_dir_node (ocfs_super * osb, ocfs_dir_node * DirNode,
+			   struct qstr * SearchName, ocfs_file_entry * found_fe,
+			   ocfs_file * OFile)
+{
+	__u32 start;
+	__u32 index;
+	ocfs_file_entry *fe;
+	int status;
+	bool bRet = false;
+
+	LOG_ENTRY ();
+
+	if (OFile != NULL)
+		start = OFile->curr_byte_off;
+	else
+		start = 0;
+
+	index = start;
+
+	while (1) {
+		/* Iterate thru this dirnode and find a matching entry */
+		if (index < DirNode->num_ent_used) {
+			if (ocfs_find_index (osb, DirNode, SearchName, (int *) &index)) {
+				fe = FILEENT (DirNode, index);
+
+				memcpy ((void *) found_fe, (void *) fe,
+					OCFS_SECTOR_SIZE);
+				if (OFile != NULL) {
+					OFile->curr_dir_off =
+					    DirNode->node_disk_off;
+					OFile->curr_byte_off = index + 1;
+				}
+				bRet = true;
+				goto bail;
+			}
+		}
+
+		if (DirNode->next_node_ptr != -1) {
+			status =
+			    ocfs_read_dir_node (osb, DirNode,
+					     DirNode->next_node_ptr);
+
+			if (!IS_VALID_DIR_NODE (DirNode)) {
+				bRet = false;
+				goto bail;
+			}
+
+			index = 0;
+			continue;
+		} else {
+			/* We are done... */
+			break;
+		}
+	}
+
+	if (OFile != NULL) {
+		OFile->curr_dir_off = DirNode->node_disk_off;
+		OFile->curr_byte_off = index + 1;
+	}
+
+      bail:
+	LOG_EXIT_ULONG (bRet);
+	return bRet;
+}				/* ocfs_search_dir_node */
+
+
+/*
+ * ocfs_find_index()
+ *
+ */
+bool ocfs_find_index (ocfs_super * osb, ocfs_dir_node * DirNode,
+		      struct qstr * FileName, int *Index)
+{
+	int lowBnd, upBnd;
+	ocfs_file_entry *fe;
+	int res = -1, index = 0, start = 0;
+	int ret = false;
+        struct qstr q;
+
+	LOG_ENTRY ();
+	if (!IS_VALID_DIR_NODE (DirNode) || FileName==NULL) {
+		ret = false;
+		goto bail;
+	}
+
+	if (*Index > 0)
+		start = *Index;
+
+	if (DirNode->index_dirty) {
+		for (index = start; index < DirNode->num_ent_used; index++) {
+			fe = FILEENT (DirNode, index);
+			if (IS_FE_DELETED(fe->sync_flags) ||
+			    (!(fe->sync_flags & OCFS_SYNC_FLAG_VALID))) {
+				continue;
+			}
+                        q.name = fe->filename;
+                        q.len = strlen(fe->filename);
+                        res = ocfs_compare_qstr(&q, FileName);
+			if (!res) {
+				*Index = index;
+				ret = true;
+				goto bail;
+			}
+		}
+		*Index = index;
+		ret = false;
+		goto bail;
+	}
+
+	for (lowBnd = start, upBnd = (DirNode->num_ent_used - start); upBnd;
+	     upBnd >>= 1) {
+		index = lowBnd + (upBnd >> 1);
+
+		fe = FILEENT (DirNode, index);
+
+		if (IS_FE_DELETED(fe->sync_flags) ||
+		    (!(fe->sync_flags & OCFS_SYNC_FLAG_VALID))) {
+			for (index = lowBnd; index < (lowBnd + upBnd); index++) {
+				fe = FILEENT (DirNode, index);
+				if (IS_FE_DELETED(fe->sync_flags) ||
+				    (!(fe->sync_flags & OCFS_SYNC_FLAG_VALID))) {
+					continue;
+				}
+                               
+                                q.name = fe->filename;
+                                q.len = strlen(fe->filename);
+                                res = ocfs_compare_qstr(&q, FileName);
+				if (!res) {
+					*Index = index;
+					ret = true;
+					goto bail;
+				}
+				if (res < 0) {
+					*Index = index;
+					ret = false;
+					goto bail;
+				}
+			}
+			*Index = lowBnd + upBnd - 1;
+			ret = false;
+			goto bail;
+		}
+
+                q.name = fe->filename;
+                q.len = strlen(fe->filename);
+                res = ocfs_compare_qstr(&q, FileName);
+		if (!res) {
+			*Index = index;
+			ret = true;
+			goto bail;
+		}
+
+		if (res > 0) {
+			lowBnd = index + 1;
+			--upBnd;
+		}
+	}
+
+	*Index = index;
+
+      bail:
+	LOG_EXIT_ULONG (ret);
+	return ret;
+}				/* ocfs_find_index */
+
+/*
+ * ocfs_reindex_dir_node()
+ *
+ */
+int ocfs_reindex_dir_node (ocfs_super * osb, __u64 DirNodeOffset, ocfs_dir_node * DirNode)
+{
+	int status = 0;
+	ocfs_dir_node *pDirNode = NULL;
+	ocfs_file_entry *pInsertEntry;
+	ocfs_file_entry *fe;
+	__u32 index;
+	__u8 offset = 0;
+	int res;
+
+	LOG_ENTRY ();
+
+	if (DirNode == NULL) {
+		pDirNode = ocfs_allocate_dirnode();
+		if (pDirNode == NULL) {
+			LOG_ERROR_STATUS (status = -ENOMEM);
+			goto leave;
+		}
+
+		status = ocfs_read_dir_node (osb, pDirNode, DirNodeOffset);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+	} else {
+		pDirNode = DirNode;
+	}
+
+	if (pDirNode->index_dirty) {
+		offset = pDirNode->bad_off;
+		pInsertEntry =
+		    (ocfs_file_entry *) (FIRST_FILE_ENTRY (pDirNode) +
+					 (offset * OCFS_SECTOR_SIZE));
+
+		for (index = 0; index < pDirNode->num_ent_used; index++) {
+			fe = FILEENT (pDirNode, index);
+
+			if (IS_FE_DELETED(fe->sync_flags) ||
+			    (!(fe->sync_flags & OCFS_SYNC_FLAG_VALID))) {
+				continue;
+			}
+
+			res = strcmp (fe->filename, pInsertEntry->filename);
+			if (res < 0) {
+				break;
+			}
+		}
+
+		if (index < (pDirNode->num_ent_used - 1)) {
+			memmove (&pDirNode->index[index + 1],
+				 &pDirNode->index[index],
+				 pDirNode->num_ent_used - index);
+			pDirNode->index[index] = offset;
+		}
+
+		pDirNode->index_dirty = 0;
+
+		status = ocfs_write_dir_node (osb, pDirNode, -1);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+
+	}
+      leave:
+	if (DirNode == NULL)
+		ocfs_release_dirnode (pDirNode);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_reindex_dir_node */
+
+/*
+ * ocfs_insert_dir_node()
+ *
+ */
+int ocfs_insert_dir_node (ocfs_super * osb,
+	       ocfs_dir_node * DirNode,
+	       ocfs_file_entry * InsertEntry,
+	       ocfs_dir_node * LockNode, __s32 * IndexOffset)
+{
+	int status = 0;
+	ocfs_file_entry *fe;
+	int res = 0;
+	int index = -1;
+	ocfs_file_entry *lastEntry;
+	ocfs_log_record *pLogRec = NULL;
+	__u32 size;
+	__u8 freeOffset;
+        struct qstr q;
+
+	LOG_ENTRY ();
+
+	if (!IS_VALID_DIR_NODE (DirNode)) {
+		LOG_ERROR_STATUS(status = -EINVAL);
+		goto bail;
+	}
+
+	if (DirNode->index_dirty) {
+		status = ocfs_reindex_dir_node (osb, DirNode->node_disk_off, DirNode);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto bail;
+		}
+	}
+
+	if (DirNode->num_ent_used < osb->max_dir_node_ent) {
+		if (DirNode->num_ent_used) {
+                        q.name = InsertEntry->filename;
+                        q.len = strlen(InsertEntry->filename);                    
+			if (ocfs_find_index (osb, DirNode, &q, &index)) {
+				/* Already inserted... */
+				status = -EEXIST;
+				goto bail;
+			}
+
+			if (index < DirNode->num_ent_used) {
+				fe = FILEENT (DirNode, index);
+
+				res = strcmp (fe->filename, InsertEntry->filename);
+				if (res > 0) {
+					/* We are greater than the entry in question we */
+					/* shd be less than the one next to it */
+					index++;
+				}
+			}
+		} else {
+			index = 0;
+		}
+
+		if (index < DirNode->num_ent_used)
+			memmove (&DirNode->index[index + 1],
+				 &DirNode->index[index],
+				 DirNode->num_ent_used - index);
+
+		if (DirNode->num_ent_used) {
+			if (DirNode->num_del) {
+				/* Insert at first deleted & change first deleted */
+				freeOffset = DirNode->first_del;
+				DirNode->num_del--;
+				if (DirNode->num_del) {
+					lastEntry =
+					    (ocfs_file_entry
+					     *) (FIRST_FILE_ENTRY (DirNode) +
+						 (freeOffset *
+						  OCFS_SECTOR_SIZE));
+					DirNode->first_del =
+					    lastEntry->next_del;
+				}
+			} else {
+				/* Insert at end and change the index */
+				freeOffset = DirNode->num_ent_used;
+			}
+		} else {
+			freeOffset = 0;
+		}
+
+		lastEntry = (ocfs_file_entry *) (FIRST_FILE_ENTRY (DirNode) +
+						 (freeOffset *
+						  OCFS_SECTOR_SIZE));
+
+		*IndexOffset = freeOffset;
+
+		/* Put the entry at the end */
+		InsertEntry->dir_node_ptr = DirNode->node_disk_off;
+
+		memcpy (lastEntry, InsertEntry, osb->sect_size);
+
+		OCFS_SET_FLAG (lastEntry->sync_flags, OCFS_SYNC_FLAG_VALID);
+
+		lastEntry->this_sector = DirNode->node_disk_off +
+		    ((freeOffset + 1) * OCFS_SECTOR_SIZE);
+		InsertEntry->this_sector = lastEntry->this_sector;
+
+		if (!(InsertEntry->sync_flags & OCFS_SYNC_FLAG_VALID)) {
+			/* This is special for rename... */
+
+			/* Log into recovery that this name only needs to be deleted if we fail */
+			size = sizeof (ocfs_log_record);
+			size = (__u32) OCFS_ALIGN (size, osb->sect_size);
+
+			if ((pLogRec = ocfs_malloc (size)) == NULL) {
+				LOG_ERROR_STATUS (status = -ENOMEM);
+				goto bail;
+			}
+
+			/* Now start writing the cleanup log of the filentry master. */
+			/* It is this node for normal cases and or the node we are doing */
+			/* recovery for. */
+			pLogRec->log_id = osb->curr_trans_id;
+			pLogRec->log_type = LOG_DELETE_NEW_ENTRY;
+
+			pLogRec->rec.del.node_num = osb->node_num;
+			pLogRec->rec.del.ent_del = InsertEntry->this_sector;
+			pLogRec->rec.del.parent_dirnode_off =
+			    LockNode->node_disk_off;
+			pLogRec->rec.del.flags = 0;
+
+			status =
+			    ocfs_write_node_log (osb, pLogRec, osb->node_num,
+					      LOG_RECOVER);
+			ocfs_safefree (pLogRec);
+			if (status < 0)
+				goto bail;
+		}
+
+		if (DISK_LOCK_FILE_LOCK (InsertEntry) ==
+		    OCFS_DLM_ENABLE_CACHE_LOCK) {
+			status = ocfs_write_metadata (osb, InsertEntry,
+					OCFS_SECTOR_SIZE, InsertEntry->this_sector);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto bail;
+			}
+		}
+
+		DirNode->index[index] = freeOffset;
+		DirNode->num_ent_used++;
+	} else {
+		LOG_ERROR_STATUS (status = -ENOSPC);
+		goto bail;
+	}
+
+      bail:
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_insert_dir_node */
+
+/*
+ * ocfs_del_file_entry()
+ *
+ */
+int ocfs_del_file_entry (ocfs_super * osb, ocfs_file_entry * EntryToDel,
+			 ocfs_dir_node * LockNode)
+{
+	int status = 0;
+	int tmpstat = 0;
+	__u32 offset;
+	ocfs_dir_node *PDirNode = NULL;
+	ocfs_file_entry *fe;
+	ocfs_lock_res *dir_lres = NULL;
+	__u64 dir_off;
+	bool lock_acq = false;
+	int index = 0;
+	int length = 0;
+
+	LOG_ENTRY ();
+
+	dir_off = LockNode->node_disk_off;
+
+	/* lock the dirnode */
+	status = ocfs_acquire_lock (osb, dir_off, OCFS_DLM_EXCLUSIVE_LOCK,
+			(FLAG_DIR | FLAG_FILE_CREATE), &dir_lres, (ocfs_file_entry *)LockNode);
+	if (status < 0) {
+		if (status != -EINTR)
+			LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+	lock_acq = true;
+
+	PDirNode = ocfs_allocate_dirnode();
+	if (PDirNode == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	status = ocfs_read_dir_node (osb, PDirNode, EntryToDel->dir_node_ptr);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	offset = (EntryToDel->this_sector - PDirNode->node_disk_off) /
+				OCFS_SECTOR_SIZE;
+
+	offset -= 1;
+	for (index = 0; index < PDirNode->num_ent_used; index++) {
+		if (PDirNode->index[index] != offset)
+			continue;
+
+		fe = FILEENT (PDirNode, index);
+
+		length = OCFS_SECTOR_SIZE;
+		if (memcmp (fe, EntryToDel, length) == 0) {
+			memmove (&PDirNode->index[index],
+				 &PDirNode->index[index + 1],
+				 PDirNode->num_ent_used - (index + 1));
+
+			PDirNode->num_ent_used--;
+			if (PDirNode->num_ent_used == 0) {
+				PDirNode->num_del = 0;
+			} else {
+				/* Insert this dir node as one containing a deleted entry if the */
+				/* count on the root dir node for deleted entries is 0 */
+				if (PDirNode->num_del != 0) {
+					PDirNode->num_del++;
+					fe->sync_flags = OCFS_SYNC_FLAG_DELETED;
+					fe->next_del = PDirNode->first_del;
+					PDirNode->first_del = offset;
+				} else {
+					PDirNode->num_del++;
+					fe->sync_flags = OCFS_SYNC_FLAG_DELETED;
+					fe->next_del = INVALID_DIR_NODE_INDEX;
+					PDirNode->first_del = offset;
+				}
+			}
+
+			if (LockNode->head_del_ent_node == INVALID_NODE_POINTER) {
+				if (LockNode->node_disk_off != PDirNode->node_disk_off)
+					LockNode->head_del_ent_node = PDirNode->node_disk_off;
+				else
+					PDirNode->head_del_ent_node = PDirNode->node_disk_off;
+			}
+
+			status = ocfs_write_dir_node (osb, PDirNode, offset);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto leave;
+			}
+
+			if (LockNode->node_disk_off != PDirNode->node_disk_off) {
+				if ((DISK_LOCK_CURRENT_MASTER (LockNode) ==
+				     osb->node_num)
+				    && (DISK_LOCK_FILE_LOCK (LockNode) ==
+					OCFS_DLM_ENABLE_CACHE_LOCK))
+					status =
+					    ocfs_write_metadata (osb, LockNode,
+							       osb->sect_size,
+							       LockNode->
+							       node_disk_off);
+				else
+					status =
+					    ocfs_write_disk (osb, LockNode,
+							   osb->sect_size,
+							   LockNode->
+							   node_disk_off);
+
+				if (status < 0) {
+					LOG_ERROR_STATUS (status);
+					goto leave;
+				}
+			}
+			goto leave;
+		}
+	}
+      leave:
+	if (lock_acq) {
+		tmpstat = ocfs_release_lock (osb, dir_off, OCFS_DLM_EXCLUSIVE_LOCK,
+					     (FLAG_DIR | FLAG_FILE_CREATE),
+					     dir_lres, (ocfs_file_entry *)LockNode);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+	}
+
+	ocfs_release_dirnode (PDirNode);
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_del_file_entry */
+
+/*
+ * ocfs_insert_file()
+ *
+ */
+int ocfs_insert_file (ocfs_super * osb, ocfs_dir_node * DirNode,
+		      ocfs_file_entry * InsertEntry, ocfs_dir_node * LockNode,
+		      ocfs_lock_res * LockResource)
+{
+	int status = 0;
+	__u64 bitmapOffset = 0;
+	__u64 numClustersAlloc = 0;
+	ocfs_dir_node *pNewDirNode = NULL;
+	__s32 indexOffset = -1;
+
+	LOG_ENTRY ();
+
+	IF_TRACE (ocfs_print_dir_node (osb, DirNode));
+
+	if (!IS_VALID_DIR_NODE (DirNode)) {
+		LOG_ERROR_STATUS (status = -EFAIL);
+		goto leave;
+	}
+
+	/* If we have a list of dir nodes go to the last dirnode */
+	/* and insert in that. */
+
+	/* We should not find this entry already inserted */
+	if (DirNode->num_ent_used < osb->max_dir_node_ent) {
+		status = ocfs_insert_dir_node (osb, DirNode, InsertEntry, LockNode,
+					&indexOffset);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+	} else {
+		pNewDirNode = ocfs_allocate_dirnode();
+		if (pNewDirNode == NULL) {
+			LOG_ERROR_STATUS (status = -ENOMEM);
+			goto leave;
+		}
+
+		if (DirNode->next_node_ptr != INVALID_NODE_POINTER) {
+			status = ocfs_read_dir_node (osb, pNewDirNode,
+					 DirNode->next_node_ptr);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto leave;
+			}
+		} else {
+			__u64 fileOffset = 0;
+
+			/* Allocate a new dir node */
+			status =
+			    ocfs_alloc_node_block (osb, osb->vol_layout.dir_node_size,
+					    &bitmapOffset, &fileOffset,
+					    &numClustersAlloc, osb->node_num,
+					    DISK_ALLOC_DIR_NODE);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto leave;
+			}
+			memset (pNewDirNode, 0, osb->vol_layout.dir_node_size);
+			ocfs_initialize_dir_node (osb, pNewDirNode, bitmapOffset,
+					   fileOffset, osb->node_num);
+		}
+
+		if ((DISK_LOCK_CURRENT_MASTER (DirNode) == osb->node_num) &&
+		    (DISK_LOCK_FILE_LOCK (DirNode) ==
+		     OCFS_DLM_ENABLE_CACHE_LOCK)) {
+			DISK_LOCK_CURRENT_MASTER (pNewDirNode) = osb->node_num;
+			DISK_LOCK_FILE_LOCK (pNewDirNode) =
+			    OCFS_DLM_ENABLE_CACHE_LOCK;
+		}
+
+		status = ocfs_insert_dir_node (osb, pNewDirNode, InsertEntry, LockNode,
+					&indexOffset);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+
+		if (LockNode->node_disk_off == DirNode->node_disk_off) {
+			DirNode->free_node_ptr = pNewDirNode->node_disk_off;
+		} else {
+			LockNode->free_node_ptr = pNewDirNode->node_disk_off;
+		}
+
+		/* Insert in this dirnode and setup the pointers */
+		DirNode->next_node_ptr = pNewDirNode->node_disk_off;
+
+		/* Create the btree now... */
+		status = ocfs_write_dir_node (osb, pNewDirNode, indexOffset);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+		indexOffset = -1;
+	}
+
+	if (DISK_LOCK_FILE_LOCK (DirNode) != OCFS_DLM_ENABLE_CACHE_LOCK) {
+		/* This is an optimization... */
+		ocfs_acquire_lockres (LockResource);
+		LockResource->lock_type = OCFS_DLM_NO_LOCK;
+		ocfs_release_lockres (LockResource);
+
+		if (LockNode->node_disk_off == DirNode->node_disk_off)
+			/* Reset the lock on the disk */
+			DISK_LOCK_FILE_LOCK (DirNode) = OCFS_DLM_NO_LOCK;
+		else
+			DISK_LOCK_FILE_LOCK (LockNode) = OCFS_DLM_NO_LOCK;
+	}
+
+	status = ocfs_write_dir_node (osb, DirNode, indexOffset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	if (LockNode->node_disk_off != DirNode->node_disk_off) {
+		if ((DISK_LOCK_CURRENT_MASTER (LockNode) == osb->node_num) &&
+		    (DISK_LOCK_FILE_LOCK (LockNode) ==
+		     OCFS_DLM_ENABLE_CACHE_LOCK))
+			status =
+			    ocfs_write_metadata (osb, LockNode, osb->sect_size,
+					       LockNode->node_disk_off);
+		else
+			status =
+			    ocfs_write_disk (osb, LockNode, osb->sect_size,
+					   LockNode->node_disk_off);
+
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+	}
+      leave:
+	ocfs_release_dirnode (pNewDirNode);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_insert_file */

Added: trunk/libocfs/Common/ocfsgendlm.c
===================================================================
--- trunk/libocfs/Common/ocfsgendlm.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/ocfsgendlm.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,2490 @@
+/*
+ * ocfsgendlm.c
+ *
+ * Distributed lock manager. Requests and processes lock votes.
+ *
+ * Copyright (C) 2002, 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifdef __KERNEL__
+#include <ocfs.h>
+extern __u32 comm_voting;
+#else
+#include <libocfs.h>
+#endif
+
+
+#define WAIT_FOR_VOTE_INCREMENT  200
+
+/* Tracing */
+#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_DLM
+
+/*
+ * ocfs_insert_cache_link()
+ *
+ */
+int ocfs_insert_cache_link (ocfs_super * osb, ocfs_lock_res * lockres)
+{
+	int status = 0;
+
+	LOG_ENTRY ();
+
+	lockres->in_cache_list = true;
+
+	list_add_tail (&(lockres->cache_list), &(osb->cache_lock_list));
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_insert_cache_link */
+
+/*
+ * ocfs_update_lock_state()
+ *
+ */
+int ocfs_update_lock_state (ocfs_super * osb, ocfs_lock_res * lockres,
+			    __u32 flags, bool *disk_vote)
+{
+	__u32 votemap;
+	int status = 0;
+	int tmpstat;
+	__u64 lockseqno = 0;
+	unsigned long jif;
+
+	LOG_ENTRY_ARGS ("(0x%p, 0x%p, %u)\n", osb, lockres, flags);
+
+	ocfs_acquire_lockres (lockres);
+	votemap = (1 << lockres->master_node_num);
+	flags |= FLAG_FILE_ACQUIRE_LOCK;
+
+	ocfs_compute_lock_type_stats (&(osb->lock_type_stats),
+				      OCFS_UPDATE_LOCK_STATE);
+
+#ifndef USERSPACE_TOOL
+	if (comm_voting && !*disk_vote) {
+		LOG_TRACE_STR ("Network vote");
+		jif = jiffies;
+		status = ocfs_send_dlm_request_msg (osb, lockres->sector_num,
+				lockres->lock_type, flags, lockres, votemap);
+		if (status >= 0) {
+			status = lockres->vote_status;
+			if (status >= 0)
+				goto vote_success;
+			else
+				goto finito;
+		} else if (status == -ETIMEDOUT) {
+			LOG_TRACE_STR ("Network voting timed out");
+		}
+		lockres->vote_state = 0;
+	}
+#endif
+
+	LOG_TRACE_STR ("Disk vote");
+	*disk_vote = true;
+	jif = jiffies;
+	status = ocfs_request_vote (osb, lockres->sector_num,
+			lockres->lock_type, flags, votemap, &lockseqno);
+	if (status < 0) {
+		if (status != -EAGAIN)
+			LOG_ERROR_STATUS (status);
+		goto finito;
+	}
+
+	status = ocfs_wait_for_vote (osb, lockres->sector_num,
+				     lockres->lock_type, flags, votemap, 5000,
+				     lockseqno, lockres);
+	if (status < 0) {
+		if (status != -EAGAIN)
+			LOG_ERROR_STATUS (status);
+		goto finito;
+	}
+
+#ifndef USERSPACE_TOOL
+      vote_success:
+#endif
+	jif = jiffies - jif;
+	LOG_TRACE_ARGS ("Lock time: %u\n", jif);
+
+	if (flags & FLAG_CHANGE_MASTER)
+		lockres->master_node_num = osb->node_num;
+
+      finito:
+	if (*disk_vote) {
+		tmpstat = ocfs_reset_voting (osb, lockres->sector_num,
+					     lockres->lock_type, votemap);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+	}
+	ocfs_release_lockres (lockres);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_update_lock_state */
+
+/*
+ * ocfs_disk_request_vote()
+ *
+ */
+int ocfs_disk_request_vote (ocfs_super * osb, __u64 lock_id, __u32 lock_type,
+			    __u32 flags, __u64 vote_map, __u64 * lock_seq_num)
+{
+	int status = 0;
+	__u64 offset = 0;
+	__u64 pub_off;
+	__u32 size = 0;
+	__u32 numnodes = 0;
+	__u32 i;
+	__u8 *buffer = NULL;
+	ocfs_publish *pubsect = NULL;
+	__u64 largestseqno = 0;
+	__u64 pubmap = 0;
+	__u8 *p;
+	__u32 wait;
+	bool publish_flag = false;
+
+	LOG_ENTRY_ARGS ("(osb=0x%p, id=%u.%u, ty=%u, fl=%u, vm=0x%08x)\n", osb,
+		 HI(lock_id), LO(lock_id), lock_type, flags, LO(vote_map));
+
+	LOG_TRACE_ARGS ("osb=0x%p, id=%u.%u, ty=%u, fl=%u, vm=0x%08x\n",
+		osb, HI(lock_id), LO(lock_id), lock_type, flags, LO(vote_map));
+
+	pubmap = osb->publ_map;
+	offset = osb->vol_layout.publ_sect_off;
+	numnodes = OCFS_MAXIMUM_NODES;
+	size = (numnodes * osb->sect_size);
+
+	/* take lock to prevent overwrites by vote_reset and nm thread */
+	down_with_flag (&(osb->publish_lock), publish_flag);
+
+	/* Read the Publish Sector of all nodes */
+	status = ocfs_read_disk_ex (osb, (void **)&buffer, size, size, offset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	for (i = 0, p = buffer; i < numnodes; i++, p += osb->sect_size) {
+		pubsect = (ocfs_publish *) p;
+		if (pubsect->time == (__u64) 0)
+			continue;
+		if (pubsect->publ_seq_num <= largestseqno)
+			continue;
+		largestseqno = pubsect->publ_seq_num;
+		if (pubsect->dirty) {
+			up_with_flag (&(osb->publish_lock), publish_flag);
+			if (!IS_NODE_ALIVE (pubmap, i, numnodes)) {
+				LOG_TRACE_ARGS ("ocfs_recover_vol(%u)\n", i);
+				ocfs_recover_vol (osb, i);
+			} else {
+				get_random_bytes(&wait, sizeof(wait));
+				wait %= 200;
+				wait += OCFS_NM_HEARTBEAT_TIME;
+				LOG_TRACE_ARGS ("wait: %d\n", wait);
+				ocfs_sleep (wait);
+			}
+			status = -EAGAIN;
+			goto finally;
+		}
+	}
+
+	/* Increment the largest sequence number by one & */
+	/* write it in its own Publish Sector and set the Dirty Bit */
+	pubsect = (ocfs_publish *) (buffer + (osb->node_num * osb->sect_size));
+	largestseqno++;
+	LOG_TRACE_ARGS ("largestseqno : %u.%u\n", HI(largestseqno), LO(largestseqno));
+	pubsect->publ_seq_num = largestseqno;
+	pubsect->dirty = true;
+	pubsect->vote = FLAG_VOTE_NODE;
+	pubsect->vote_map = vote_map;
+	pubsect->vote_type = flags;
+	pubsect->dir_ent = lock_id;
+
+	pub_off = osb->vol_layout.publ_sect_off +
+			(osb->node_num * osb->sect_size);
+
+	status = ocfs_write_disk (osb, pubsect, osb->sect_size, pub_off);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	atomic_set (&osb->node_req_vote, 1);
+
+	*lock_seq_num = largestseqno;
+
+      finally:
+	up_with_flag (&(osb->publish_lock), publish_flag);
+	ocfs_safefree (buffer);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_disk_request_vote */
+
+/*
+ * ocfs_wait_for_disk_lock_release()
+ *
+ * @osb: ocfs super block for the volume
+ * @offset:
+ * @time_to_wait:
+ * @lock_type: lowest level to which a lock must deprecate for us to break out.
+ *
+ * Returns 0 of success, < 0 if error.
+ */
+int ocfs_wait_for_disk_lock_release (ocfs_super * osb, __u64 offset,
+				     __u32 time_to_wait, __u32 lock_type)
+{
+	int status = -ETIMEDOUT;
+	int tmpstat = -ETIMEDOUT;
+	__u32 timewaited = 0;
+	ocfs_file_entry *fe = NULL;
+
+	LOG_ENTRY ();
+
+	/* Create a sepearate thread which should  set the event of the */
+	/* resource after N retries. */
+
+	fe = ocfs_allocate_file_entry ();
+	if (fe == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto finally;
+	}
+
+	while (time_to_wait > timewaited) {
+		memset (fe, 0, sizeof (ocfs_file_entry));
+		tmpstat = ocfs_read_force_disk (osb, fe, osb->sect_size, offset);
+		if (tmpstat < 0) {
+			LOG_ERROR_STATUS (status = tmpstat);
+			goto finally;
+		}
+
+		/* This will always be zero when the first Node comes up after reboot */
+		/* (for volume lock) */
+		if ((DISK_LOCK_CURRENT_MASTER (fe) == OCFS_INVALID_NODE_NUM) ||
+		    (DISK_LOCK_CURRENT_MASTER (fe) == osb->node_num)) {
+			status = 0;
+			goto finally;
+		}
+
+		if (!IS_NODE_ALIVE (osb->publ_map,
+				    DISK_LOCK_CURRENT_MASTER (fe),
+				    OCFS_MAXIMUM_NODES)) {
+//			LOG_TRACE_ARGS ("ocfs_recover_vol(%u)\n",
+//					DISK_LOCK_CURRENT_MASTER (fe));
+//			ocfs_recover_vol(osb, DISK_LOCK_CURRENT_MASTER(fe));
+
+			/* Reset the lock as not owned and return success?? */
+			/* This needs to be under some sort of cluster wide lock */
+			DISK_LOCK_CURRENT_MASTER (fe) = OCFS_INVALID_NODE_NUM;
+			DISK_LOCK_FILE_LOCK (fe) = OCFS_DLM_NO_LOCK;
+			status = 0;
+			goto finally;
+		}
+
+		/* If we are here in the code it means the local node is not the master */
+		if (DISK_LOCK_FILE_LOCK (fe) <= lock_type) {
+			status = 0;
+			goto finally;
+		} else
+			ocfs_sleep (WAIT_FOR_VOTE_INCREMENT);
+		timewaited += WAIT_FOR_VOTE_INCREMENT;
+	}
+
+      finally:
+	ocfs_release_file_entry (fe);
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_wait_for_disk_lock_release */
+
+/*
+ * ocfs_wait_for_lock_release()
+ *
+ */
+int ocfs_wait_for_lock_release (ocfs_super * osb, __u64 offset, __u32 time_to_wait,
+				ocfs_lock_res * lockres, __u32 lock_type)
+{
+	int status = -ETIMEDOUT;
+	int tmpstat = -ETIMEDOUT;
+	__u32 timewaited = 0;
+	ocfs_file_entry *fe = NULL;
+	__u32 length = 0;
+
+	LOG_ENTRY_ARGS ("(0x%p, %u.%u, %u, 0x%p, %u)\n", osb,
+			HI (offset), LO (offset), time_to_wait,
+			lockres, lock_type);
+
+	fe = ocfs_allocate_file_entry ();
+	if (fe == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto finally;
+	}
+
+	while (time_to_wait > timewaited) {
+		memset (fe, 0, sizeof (ocfs_file_entry));
+		length = osb->sect_size;
+		tmpstat = ocfs_read_disk (osb, fe, length, offset);
+		if (tmpstat < 0) {
+			LOG_ERROR_STATUS (status = tmpstat);
+			goto finally;
+		}
+
+		if ((DISK_LOCK_CURRENT_MASTER (fe) == OCFS_INVALID_NODE_NUM) ||
+		    (DISK_LOCK_CURRENT_MASTER (fe) == osb->node_num)) {
+			status = 0;
+			goto finally;
+		}
+
+		if (!IS_NODE_ALIVE (osb->publ_map, DISK_LOCK_CURRENT_MASTER(fe),
+				    OCFS_MAXIMUM_NODES)) {
+//			LOG_ERROR_ARGS ("ocfs_recover_vol(%u)",
+//					DISK_LOCK_CURRENT_MASTER (fe));
+//			ocfs_recover_vol(osb, DISK_LOCK_CURRENT_MASTER(fe));
+
+			/* Reset the lock as not owned and return success?? */
+			/* This needs to be under some sort of cluster wide lock, */
+			DISK_LOCK_CURRENT_MASTER (fe) = OCFS_INVALID_NODE_NUM;
+			DISK_LOCK_FILE_LOCK (fe) = OCFS_DLM_NO_LOCK;
+			status = 0;
+			goto finally;
+		}
+
+		/* The local node is not the master */
+		if (DISK_LOCK_FILE_LOCK (fe) >= OCFS_DLM_ENABLE_CACHE_LOCK) {
+			lockres->lock_type = DISK_LOCK_FILE_LOCK (fe);
+			lockres->master_node_num = DISK_LOCK_CURRENT_MASTER (fe);
+			status = ocfs_break_cache_lock (osb, lockres, fe);
+			if (status < 0) {
+				if (status != -EINTR)
+					LOG_ERROR_STATUS (status);
+				goto finally;
+			}
+			DISK_LOCK_FILE_LOCK (fe) = lockres->lock_type;
+			DISK_LOCK_CURRENT_MASTER (fe) = lockres->master_node_num;
+		}
+
+		if (DISK_LOCK_FILE_LOCK (fe) <= lock_type) {
+			status = 0;
+			goto finally;
+		} else
+			ocfs_sleep (WAIT_FOR_VOTE_INCREMENT);
+		timewaited += WAIT_FOR_VOTE_INCREMENT;
+	}
+
+	LOG_TRACE_ARGS("probing the node %d for possible stale lock, lockid=%u.%u\n",
+		       lockres->master_node_num, HILO (lockres->sector_num));
+
+	status = ocfs_update_master_on_open (osb, lockres);
+	if (status >= 0) {
+		tmpstat = ocfs_read_disk (osb, fe, osb->sect_size, offset);
+		if (tmpstat < 0) {
+			LOG_ERROR_STATUS(tmpstat);
+			status = tmpstat;
+		}
+		if (DISK_LOCK_FILE_LOCK(fe) < lockres->lock_type) {
+			LOG_TRACE_STR("stale lock was found and corrected!");
+		}
+	}
+
+      finally:
+	if (status == -ETIMEDOUT) {
+		LOG_ERROR_ARGS ("WARNING: timeout lockid=%u.%u, master=%u, "
+				"type=%u\n", HILO (lockres->sector_num),
+			       	lockres->master_node_num, lockres->lock_type);
+	}
+
+	if (lockres && status >= 0) {
+		ocfs_acquire_lockres (lockres);
+		lockres->lock_type = DISK_LOCK_FILE_LOCK (fe);
+		lockres->master_node_num = DISK_LOCK_CURRENT_MASTER (fe);
+		lockres->oin_openmap = DISK_LOCK_OIN_MAP (fe);
+		lockres->last_lock_upd = DISK_LOCK_LAST_WRITE (fe);
+		lockres->lock_type = DISK_LOCK_FILE_LOCK(fe);
+		ocfs_release_lockres (lockres);
+	}
+
+	ocfs_release_file_entry (fe);
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_wait_for_lock_release */
+
+/*
+ * ocfs_get_vote_on_disk()
+ *
+ */
+int ocfs_get_vote_on_disk (ocfs_super * osb, __u64 lock_id, __u32 lock_type,
+			   __u32 flags, __u64 * got_vote_map, __u64 vote_map,
+			   __u64 lock_seq_num, __u64 * oin_open_map)
+{
+	int status = 0;
+	__u32 length = 0;
+	__u32 i;
+	__u32 numnodes;
+	__u8 *buffer = NULL;
+	ocfs_vote *vote;
+	__u8 *p;
+
+	LOG_ENTRY_ARGS ("(lockid=%u.%u, locktype=%u, votemap=0x%08x)\n",
+			HI (lock_id), LO (lock_id), lock_type, LO (vote_map));
+
+	numnodes = OCFS_MAXIMUM_NODES;
+
+	/* Read the vote sectors of all the nodes */
+	length = numnodes * osb->sect_size;
+	status = ocfs_read_disk_ex (osb, (void **)&buffer, length, length,
+				    osb->vol_layout.vote_sect_off);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	for (i = 0, p = buffer; i < numnodes; i++, p += osb->sect_size) {
+		vote = (ocfs_vote *) p;
+
+		/* A node we were asking to vote is dead */
+		if ((IS_NODE_ALIVE (vote_map, i, numnodes)) &&
+		    !(IS_NODE_ALIVE (osb->publ_map, i, numnodes))) {
+			if (flags & FLAG_FILE_UPDATE_OIN) {
+				(*got_vote_map) |= 1 << i;
+			} else {
+				status = -EAGAIN;
+				goto finally;
+			}
+		}
+
+		if (!IS_NODE_ALIVE (vote_map, i, numnodes) ||
+		    !IS_NODE_ALIVE (osb->publ_map, i, numnodes) ||
+		    vote->vote_seq_num != lock_seq_num ||
+		    vote->dir_ent != lock_id)
+			continue;
+
+		/* A node we were asking to vote is alive */
+		if (vote->vote[osb->node_num] == FLAG_VOTE_NODE) {
+			(*got_vote_map) |= 1 << i;
+			if (flags & FLAG_FILE_EXTEND || flags & FLAG_FILE_UPDATE) {
+				(*oin_open_map) |= (vote->open_handle << i);
+			}
+		} else if (vote->vote[osb->node_num] == FLAG_VOTE_OIN_ALREADY_INUSE) {
+			(*got_vote_map) |= 1 << i;
+			status = -EFAIL;
+			if (flags & FLAG_FILE_DELETE) {
+				status = -EBUSY;
+			}
+			goto finally;
+		} else if (vote->vote[osb->node_num] == FLAG_VOTE_OIN_UPDATED) {
+			(*got_vote_map) |= 1 << i;
+		} else if (vote->vote[osb->node_num] == FLAG_VOTE_UPDATE_RETRY) {
+			status = -EAGAIN;
+			goto finally;
+		} else if (vote->vote[osb->node_num] == FLAG_VOTE_FILE_DEL) {
+			status = -ENOENT;
+			goto finally;
+		}
+	}
+
+      finally:
+	ocfs_safefree (buffer);
+	LOG_EXIT_STATUS (status);
+	return (status);
+}				/* ocfs_get_vote_on_disk */
+
+/*
+ * ocfs_disk_reset_voting()
+ *
+ */
+int ocfs_disk_reset_voting (ocfs_super * osb, __u64 lock_id, __u32 lock_type)
+{
+	int status = 0;
+	ocfs_publish *pubsect = NULL;
+	__u64 offset = 0;
+
+	LOG_ENTRY_ARGS ("(0x%p, %u.%u, %u)\n", osb, HI (lock_id),
+			LO (lock_id), lock_type);
+
+	/* take lock to prevent publish overwrites by vote_req and nm thread */
+	down (&(osb->publish_lock));
+
+	/* Read node's publish sector */
+	offset = osb->vol_layout.publ_sect_off +
+		 (osb->node_num * osb->sect_size);
+	status = ocfs_read_disk_ex (osb, (void *)&pubsect, osb->sect_size,
+				    osb->sect_size, offset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	pubsect->dirty = false;
+	pubsect->vote = 0;
+	pubsect->vote_type = 0;
+	pubsect->vote_map = 0;
+	pubsect->dir_ent = 0;
+
+	/* Write it back */
+	status = ocfs_write_disk (osb, pubsect, osb->sect_size, offset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	atomic_set (&osb->node_req_vote, 0);
+
+      finally:
+	up (&(osb->publish_lock));
+	ocfs_safefree (pubsect);
+	LOG_EXIT_STATUS (status);
+	return (status);
+}				/* ocfs_disk_reset_voting */
+
+/*
+ * ocfs_wait_for_vote()
+ *
+ */
+int ocfs_wait_for_vote (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags,
+			__u64 vote_map, __u32 time_to_wait, __u64 lock_seq_num,
+			ocfs_lock_res * lockres)
+{
+	int status = -EAGAIN;
+	__u32 timewaited = 0;
+	__u64 gotvotemap = 0;
+	__u64 fileopenmap = 0;
+
+	LOG_ENTRY_ARGS ("(osb=0x%p, id=%u.%u, ty=%u, fl=%u, vm=0x%08x, "
+		"sq:%u.%u)\n", osb, HI (lock_id), LO (lock_id), lock_type,
+		flags, LO (vote_map), HI(lock_seq_num), LO(lock_seq_num));
+
+	while (time_to_wait > timewaited) {
+		ocfs_sleep (WAIT_FOR_VOTE_INCREMENT);
+
+		if (!atomic_read (&osb->node_req_vote)) {
+			LOG_TRACE_ARGS ("wait EAGAIN\n");
+			status = -EAGAIN;
+			goto bail;
+		}
+
+		gotvotemap |= (1 << osb->node_num);
+
+		status = ocfs_get_vote_on_disk (osb, lock_id, lock_type, flags,
+				&gotvotemap, vote_map, lock_seq_num, &fileopenmap);
+		if (status < 0) {
+			if (status != -EAGAIN)
+				LOG_ERROR_STATUS (status);
+			goto bail;
+		}
+
+		if (!(gotvotemap & (1 << osb->node_num))) {
+			status = -EAGAIN;
+			goto bail;
+		}
+
+		vote_map |= (1 << osb->node_num);
+		if (vote_map == gotvotemap) {
+			if ((flags & FLAG_FILE_EXTEND) || (flags & FLAG_FILE_UPDATE))
+				lockres->oin_openmap = fileopenmap;
+			status = 0;
+			goto bail;
+		}
+		timewaited += WAIT_FOR_VOTE_INCREMENT;
+	}
+
+      bail:
+	ocfs_compute_dlm_stats ((timewaited >= time_to_wait ? -ETIMEDOUT : 0),
+			       	status, &(OcfsGlobalCtxt.dsk_reqst_stats));
+	ocfs_compute_dlm_stats ((timewaited >= time_to_wait ? -ETIMEDOUT : 0),
+			       	status, &(osb->dsk_reqst_stats));
+
+	LOG_TRACE_ARGS ("disk vote id=%u.%u, seq=%u.%u, map=0x%08x, "
+		       	"flags=0x%08x, type=0x%08x, status=%d\n",
+		       	HILO(lock_id), HILO(lock_seq_num), LO(vote_map),
+		       	flags, lock_type, status);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_wait_for_vote */
+
+/*
+ * ocfs_reset_voting()
+ *
+ */
+int ocfs_reset_voting (ocfs_super * osb, __u64 lock_id, __u32 lock_type,
+		       __u64 vote_map)
+{
+	int status;
+
+	LOG_ENTRY ();
+
+	status = ocfs_disk_reset_voting (osb, lock_id, lock_type);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_reset_voting */
+
+/*
+ * ocfs_request_vote()
+ *
+ */
+int ocfs_request_vote (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags,
+		       __u64 vote_map, __u64 * lock_seq_num)
+{
+	int status;
+
+	LOG_ENTRY ();
+
+	status = ocfs_disk_request_vote (osb, lock_id, lock_type, flags,
+					 vote_map, lock_seq_num);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_request_vote */
+
+#ifndef USERSPACE_TOOL
+/*
+ * ocfs_init_dlm_msg()
+ *
+ */
+void ocfs_init_dlm_msg (ocfs_super * osb, ocfs_dlm_msg * dlm_msg, __u32 msg_len)
+{
+	LOG_ENTRY ();
+
+	dlm_msg->magic = OCFS_DLM_MSG_MAGIC;
+	dlm_msg->msg_len = msg_len;
+
+	memcpy (dlm_msg->vol_id, osb->vol_layout.vol_id, MAX_VOL_ID_LENGTH);
+
+	dlm_msg->src_node = osb->node_num;
+
+	LOG_EXIT ();
+	return;
+}				/* ocfs_init_dlm_msg */
+
+/*
+ * ocfs_send_dlm_request_msg()
+ *
+ */
+int ocfs_send_dlm_request_msg (ocfs_super * osb, __u64 lock_id, __u32 lock_type,
+			       __u32 flags, ocfs_lock_res * lockres,
+			       __u64 vote_map)
+{
+	int status = 0;
+	ocfs_dlm_msg *dlm_msg = NULL;
+	__u32 msg_len;
+	ocfs_dlm_msg_hdr *req;
+
+	LOG_ENTRY_ARGS ("(osb=0x%p, id:%u.%u, ty=%u, fl=%u, vm=0x%08x)\n", osb,
+			HI(lock_id), LO(lock_id), lock_type, flags, LO(vote_map));
+
+	msg_len = sizeof (ocfs_dlm_msg) - 1 + sizeof (ocfs_dlm_req_master);
+
+	dlm_msg = ocfs_malloc (msg_len);
+	if (dlm_msg == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto finally;
+	}
+
+	ocfs_acquire_lockres (lockres);
+	lockres->vote_state = LOCK_STATE_IN_VOTING;
+	lockres->req_vote_map = vote_map;
+	lockres->got_vote_map = 0;
+	lockres->tmp_openmap = 0;
+	spin_lock (&OcfsGlobalCtxt.comm_seq_lock);
+	OcfsGlobalCtxt.comm_seq_num++;
+	lockres->last_upd_seq_num = OcfsGlobalCtxt.comm_seq_num;
+	spin_unlock (&OcfsGlobalCtxt.comm_seq_lock);
+	ocfs_release_lockres (lockres);
+
+	ocfs_init_dlm_msg (osb, dlm_msg, msg_len);
+
+	dlm_msg->msg_type = OCFS_VOTE_REQUEST;
+
+	req = (ocfs_dlm_msg_hdr *) dlm_msg->msg_buf;
+	req->lock_id = lock_id;
+	req->flags = flags;
+	req->lock_seq_num = lockres->last_upd_seq_num;
+
+	LOG_TRACE_ARGS ("ocfs: vote request lockid=%u.%u, seq=%u.%u, map=0x%08x\n",
+	       HILO(req->lock_id), HILO(req->lock_seq_num), LO(vote_map));
+
+	ocfs_send_bcast (osb, vote_map, dlm_msg);
+	status = ocfs_wait (lockres->voted_event,
+			    atomic_read (&lockres->voted_event_woken), 1000);
+	atomic_set (&lockres->voted_event_woken, 0);
+ 
+	if (status == -ETIMEDOUT) {
+		LOG_TRACE_ARGS ("timedout seq=%u.%u\n", HILO(req->lock_seq_num));
+	}
+
+	ocfs_compute_dlm_stats (status, lockres->vote_status,
+			       	&(OcfsGlobalCtxt.net_reqst_stats));
+
+	ocfs_compute_dlm_stats (status, lockres->vote_status,
+			       	&(osb->net_reqst_stats));
+
+      finally:
+	ocfs_safefree (dlm_msg);
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_send_dlm_request_msg */
+#endif /* USERSPACE_TOOL */
+
+/*
+ * ocfs_make_lock_master()
+ *
+ */
+int ocfs_make_lock_master (ocfs_super * osb, __u64 lock_id, __u32 lock_type,
+			   __u32 flags, ocfs_lock_res * lockres,
+			   ocfs_file_entry * fe, bool *disk_vote)
+{
+	__u64 vote_map = 0;
+	__u64 lockseqnum = 0;
+	int status = 0;
+	int tmpstat;
+	unsigned long jif;
+
+	LOG_ENTRY ();
+
+	ocfs_acquire_lockres (lockres);
+	vote_map = osb->publ_map;
+
+	if (((flags & FLAG_FILE_DELETE) || (flags & FLAG_FILE_RENAME)) &&
+	    (!(flags & FLAG_DIR)) &&
+	    (DISK_LOCK_CURRENT_MASTER (fe) == osb->node_num)) {
+		vote_map = DISK_LOCK_OIN_MAP (fe);
+		vote_map &= osb->publ_map;	/* remove all dead nodes */
+	}
+
+	vote_map &= ~(1 << osb->node_num);
+
+	if (vote_map == 0) {
+		/* As this is the only node alive, make it master of the lock */
+		if (lockres->lock_type <= lock_type)
+			lockres->lock_type = (__u8) lock_type;
+		lockres->master_node_num = osb->node_num;
+
+		status = ocfs_update_disk_lock (osb, lockres,
+				DLOCK_FLAG_MASTER | DLOCK_FLAG_LOCK, fe);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto bail;
+		}
+		goto bail;
+	}
+
+	ocfs_compute_lock_type_stats (&(osb->lock_type_stats),
+				      OCFS_MAKE_LOCK_MASTER);
+
+	flags |= FLAG_FILE_ACQUIRE_LOCK;
+
+#ifndef USERSPACE_TOOL
+	if (comm_voting && !*disk_vote) {
+		LOG_TRACE_STR ("Network vote");
+		jif = jiffies;
+		status = ocfs_send_dlm_request_msg (osb, lock_id, lock_type,
+						    flags, lockres, vote_map);
+		if (status >= 0) {
+			status = lockres->vote_status;
+			if (status >= 0)
+				goto vote_success;
+			else
+				goto bail;
+		} else if (status == -ETIMEDOUT) {
+			LOG_TRACE_STR ("Network voting timed out");
+		}
+		lockres->vote_state = 0;
+	}
+#endif
+
+	LOG_TRACE_STR ("Disk vote");
+	*disk_vote = true;
+	jif = jiffies;
+	status = ocfs_request_vote (osb, lock_id, lock_type, flags, vote_map,
+				    &lockseqnum);
+	if (status < 0) {
+		if (status != -EAGAIN)
+			LOG_ERROR_STATUS (status);
+		goto bail;
+	}
+
+	status = ocfs_wait_for_vote (osb, lock_id, lock_type, flags, vote_map,
+				     5000, lockseqnum, lockres);
+	if (status < 0) {
+		if (status != -EAGAIN)
+			LOG_ERROR_STATUS (status);
+		goto bail;
+	}
+
+#ifndef USERSPACE_TOOL
+      vote_success:
+#endif
+	jif = jiffies - jif;
+	LOG_TRACE_ARGS ("Lock time: %u\n", jif);
+
+	/* Make this node the master of this lock */
+	if (lockres->lock_type <= lock_type)
+		lockres->lock_type = (__u8) lock_type;
+
+	lockres->master_node_num = osb->node_num;
+
+	/* Write that we now are the master to the disk */
+	status = ocfs_update_disk_lock (osb, lockres,
+		 DLOCK_FLAG_MASTER | DLOCK_FLAG_LOCK | DLOCK_FLAG_OPEN_MAP, fe);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto bail;
+	}
+
+      bail:
+	if (*disk_vote) {
+		tmpstat = ocfs_reset_voting (osb, lock_id, lock_type, vote_map);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+	}
+	ocfs_release_lockres (lockres);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_make_lock_master */
+
+/*
+ * ocfs_acquire_lockres_ex()
+ *
+ * @lockres: lockres to acquire
+ * @timeout: timeout in ms, 0 == no timeout
+ */
+int ocfs_acquire_lockres_ex (ocfs_lock_res * lockres, __u32 timeout)
+{
+	int mypid;
+	unsigned long jif = 0;
+	int status = 0;
+	int cnt = 0;
+
+	LOG_ENTRY_ARGS ("(0x%p, %d)\n", lockres, timeout);
+
+	mypid = ocfs_getpid ();
+
+	if (timeout)
+		jif = jiffies + (timeout * HZ / 1000);
+
+	while (1) {
+		spin_lock (&lockres->lock_mutex);
+
+		if (lockres->in_use) {
+			if (lockres->thread_id != mypid) {
+				spin_unlock (&lockres->lock_mutex);
+				if (jif && jif < jiffies) {
+					LOG_TRACE_ARGS ("lockpid=%d, newpid=%d,"
+						" timedout\n",
+						lockres->thread_id, mypid);
+					status = -ETIMEDOUT;
+					goto bail;
+				}
+
+				if (++cnt == 10) {
+					LOG_TRACE_ARGS ("lockpid=%d, newpid=%d\n",
+						lockres->thread_id, mypid);
+					cnt = 0;
+				}
+				ocfs_sleep (OCFS_NM_HEARTBEAT_TIME / 10);
+			}
+			else {
+				lockres->in_use++;
+				spin_unlock (&lockres->lock_mutex);
+				break;
+			}
+		} else {
+			lockres->in_use = 1;
+			lockres->thread_id = mypid;
+			spin_unlock (&lockres->lock_mutex);
+			break;
+		}
+	}
+
+      bail:
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_acquire_lockres_ex */
+
+/*
+ * ocfs_release_lockres()
+ *
+ */
+void ocfs_release_lockres (ocfs_lock_res * lockres)
+{
+	LOG_ENTRY_ARGS ("(0x%p)\n", lockres);
+
+	spin_lock (&lockres->lock_mutex);
+	if (lockres->in_use == 0) {
+		LOG_TRACE_ARGS("Releasing lockres with inuse 0: 0x%p\n",
+			       lockres);
+		lockres->thread_id = 0;
+		lockres->in_use = 0;
+	} else {
+		lockres->in_use--;
+		if (lockres->in_use == 0) {
+			lockres->thread_id = 0;
+		}
+	}
+	spin_unlock (&lockres->lock_mutex);
+
+	LOG_EXIT ();
+	return;
+}				/* ocfs_release_lockres */
+
+
+/*
+ * ocfs_update_disk_lock()
+ *
+ */
+int ocfs_update_disk_lock (ocfs_super * osb, ocfs_lock_res * lockres,
+			   __u32 flags, ocfs_file_entry * fe)
+{
+	int status = 0;
+	__u64 offset = 0;
+	ocfs_file_entry *tmp_fe = NULL;
+
+	LOG_ENTRY ();
+
+	offset = lockres->sector_num;
+	if (fe == NULL)
+		status = ocfs_get_file_entry (osb, &tmp_fe, lockres->sector_num);
+	else {
+		tmp_fe = fe;
+		status = ocfs_read_disk (osb, (void *) tmp_fe,
+					 (__u32) osb->sect_size, offset);
+	}
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	if (flags & DLOCK_FLAG_MASTER)
+		DISK_LOCK_CURRENT_MASTER (tmp_fe) = lockres->master_node_num;
+
+	if (flags & DLOCK_FLAG_LOCK)
+		DISK_LOCK_FILE_LOCK (tmp_fe) = lockres->lock_type;
+
+	if (flags & DLOCK_FLAG_OPEN_MAP)
+		DISK_LOCK_OIN_MAP (tmp_fe) = lockres->oin_openmap;
+
+	if (flags & DLOCK_FLAG_SEQ_NUM)
+		DISK_LOCK_SEQNUM (tmp_fe) = lockres->last_upd_seq_num;
+
+	status = ocfs_write_disk (osb, tmp_fe, osb->sect_size, offset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+      finally:
+	if ((tmp_fe != fe))
+		ocfs_release_file_entry (tmp_fe);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_update_disk_lock */
+
+/*
+ * ocfs_update_master_on_open()
+ *
+ */
+int ocfs_update_master_on_open (ocfs_super * osb, ocfs_lock_res * lockres)
+{
+	int status = -EAGAIN;
+	bool disk_vote = false;
+
+	LOG_ENTRY ();
+
+	while (status == -EAGAIN) {
+		if (!IS_NODE_ALIVE (osb->publ_map, lockres->master_node_num,
+				    OCFS_MAXIMUM_NODES)) {
+			LOG_TRACE_ARGS ("Master (%u) dead, lockid %u.%u\n",
+				lockres->master_node_num,
+				HI (lockres->sector_num), LO (lockres->sector_num));
+			status = 0;
+			goto bail;
+		}
+
+		ocfs_acquire_lockres (lockres);
+
+		if (lockres->master_node_num == osb->node_num) {
+			LOG_TRACE_ARGS ("Added node to map 0x%08x, lockid %u.%u\n",
+			     LO (lockres->oin_openmap), HI (lockres->sector_num),
+			     LO (lockres->sector_num));
+
+			lockres->oin_openmap |= (1 << osb->node_num);
+			status = ocfs_update_disk_lock (osb, lockres,
+						DLOCK_FLAG_OPEN_MAP, NULL);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto bail;
+			}
+			ocfs_release_lockres (lockres);
+		} else {
+			status = ocfs_update_lock_state (osb, lockres,
+						 FLAG_ADD_OIN_MAP, &disk_vote);
+			if (status < 0) {
+				if (status != -EAGAIN)
+					LOG_ERROR_STATUS (status);
+				ocfs_release_lockres (lockres);
+				if (status == -EAGAIN) {
+					ocfs_sleep (500);
+					if (ocfs_task_interruptible (osb)) {
+						LOG_TRACE_ARGS("interrupted... "
+							"lockid=%u.%u\n",
+							HILO(lockres->sector_num));
+						status = -EINTR;
+						goto bail;
+					}
+					continue;
+				}
+				goto bail;
+			}
+			ocfs_release_lockres (lockres);
+		}
+	}
+
+      bail:
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_update_master_on_open */
+
+/*
+ * ocfs_init_lockres()
+ *
+ */
+void ocfs_init_lockres (ocfs_super * osb, ocfs_lock_res * lockres, __u64 lock_id)
+{
+	LOG_ENTRY_ARGS ("(0x%p, 0x%p, %u.%u)\n", osb, lockres,
+			HI (lock_id), LO (lock_id));
+
+	lockres->signature = 0x55AA;
+	lockres->lock_type = OCFS_DLM_NO_LOCK;
+	lockres->master_node_num = OCFS_INVALID_NODE_NUM;
+	lockres->last_upd_seq_num = 0;
+	lockres->oin_openmap = 0;
+	lockres->sector_num = lock_id;
+	lockres->in_use = 0;
+	lockres->oin = NULL;
+	lockres->lock_state = 0;
+	lockres->vote_state = 0;
+	lockres->in_cache_list = false;
+
+#ifndef USERSPACE_TOOL
+	spin_lock_init (&lockres->lock_mutex);
+	init_waitqueue_head (&lockres->voted_event);
+#endif
+	atomic_set (&lockres->voted_event_woken, 0);
+	atomic_set (&lockres->lr_ref_cnt, 0);
+	atomic_set (&lockres->lr_share_cnt, 0);
+
+	/* For read/write caching */
+	lockres->last_read_time = 0;
+	lockres->last_write_time = 0;
+	lockres->writer_node_num = OCFS_INVALID_NODE_NUM;
+	lockres->reader_node_num = OCFS_INVALID_NODE_NUM;
+
+	LOG_EXIT ();
+	return;
+}				/* ocfs_init_lockres */
+
+/*
+ * ocfs_create_update_lock()
+ *
+ */
+int ocfs_create_update_lock (ocfs_super * osb, ocfs_inode * oin, __u64 lock_id,
+			     __u32 flags)
+{
+	int status = 0;
+	ocfs_lock_res *lockres = NULL;
+	ocfs_lock_res *tmp_lockres = NULL;
+	bool is_dir = false;
+
+	LOG_ENTRY_ARGS ("(0x%p, 0x%p, %u.%u, %u)\n", osb, oin,
+			HI (lock_id), LO (lock_id), flags);
+
+	is_dir = (flags & OCFS_OIN_DIRECTORY) ? true : false;
+
+	/* Check the lock state on the disk / in our resource map */
+	status = ocfs_lookup_sector_node (osb, lock_id, &lockres);
+	if (status >= 0) {
+		ocfs_acquire_lockres (lockres);
+		if (lockres->oin) {
+			if (lockres->oin->obj_id.type != OCFS_TYPE_OIN) {
+				ocfs_release_lockres (lockres);
+				LOG_ERROR_STATUS (status = -EFAIL);
+				goto bail;
+			} else {
+				ocfs_put_lockres (lockres->oin->lock_res);
+				lockres->oin->lock_res = NULL;
+			}
+		}
+		lockres->oin = oin;
+		oin->oin_flags |= flags;
+		oin->lock_res = lockres;
+		ocfs_get_lockres (lockres);
+		ocfs_release_lockres (lockres);
+
+		status = ocfs_wait_for_lock_release (osb, lock_id, 30000, lockres,
+				(is_dir ? OCFS_DLM_EXCLUSIVE_LOCK : OCFS_DLM_NO_LOCK));
+		if (status < 0) {
+			if (status != -EINTR)
+				LOG_ERROR_STATUS (status);
+			goto bail;
+		}
+	} else {
+		/* Create a resource and insert in the hash */
+		lockres = ocfs_allocate_lockres();
+		if (lockres == NULL) {
+			LOG_ERROR_STATUS (status = -ENOMEM);
+			goto bail;
+		}
+
+		ocfs_init_lockres (osb, lockres, lock_id);
+
+		ocfs_get_lockres (lockres);
+
+		status = ocfs_wait_for_lock_release (osb, lock_id, 30000, lockres,
+				(is_dir ? OCFS_DLM_EXCLUSIVE_LOCK : OCFS_DLM_NO_LOCK));
+		if (status < 0) {
+			if (status != -EINTR)
+				LOG_ERROR_STATUS (status);
+			goto bail;
+		}
+		
+		status = ocfs_check_for_stale_lock(osb, lockres, NULL, lock_id);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto bail;
+		}
+
+		status = ocfs_insert_sector_node (osb, lockres, &tmp_lockres);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto bail;
+		}
+
+		/* Check if another process added a lockres after our lookup */
+		if (tmp_lockres) {
+			/* If so, put the recently allocated lockres */
+			ocfs_put_lockres (lockres);
+			lockres = tmp_lockres;
+			status = ocfs_wait_for_lock_release (osb, lock_id, 30000, lockres,
+					(is_dir ? OCFS_DLM_EXCLUSIVE_LOCK : OCFS_DLM_NO_LOCK));
+			if (status < 0) {
+				if (status != -EINTR)
+					LOG_ERROR_STATUS (status);
+				goto bail;
+			}
+		} else {
+			if (flags & OCFS_OIN_CACHE_UPDATE) {
+				status = ocfs_insert_cache_link (osb, lockres);
+				if (status < 0) {
+					LOG_ERROR_STR ("Lock up volume");
+					goto bail;
+				}
+			}
+		}
+	}
+
+	ocfs_acquire_lockres (lockres);
+
+	lockres->oin = oin;
+	oin->oin_flags |= flags;
+	if (oin->lock_res != lockres) {
+		ocfs_put_lockres (oin->lock_res);
+		oin->lock_res = lockres;
+		ocfs_get_lockres (lockres);
+	}
+
+	LOG_TRACE_ARGS ("MasterNode=%d, ThisNode=%d\n",
+			lockres->master_node_num, osb->node_num);
+
+	if ((!is_dir) && (lockres->master_node_num != OCFS_INVALID_NODE_NUM) &&
+	    ((!IS_NODE_ALIVE (lockres->oin_openmap, osb->node_num, OCFS_MAXIMUM_NODES)) ||
+	     (lockres->lock_state & FLAG_ALWAYS_UPDATE_OPEN))) {
+		/* Send a message to master so that he can send the oin update to */
+		/* this node also. If u are the master then update File_entry */
+		/* and set the bit that this node has a open */
+		status = ocfs_update_master_on_open (osb, lockres);
+		if (status < 0 && status != -EINTR)
+			LOG_ERROR_STATUS (status);
+	}
+
+	ocfs_release_lockres (lockres);
+
+      bail:
+	ocfs_put_lockres(lockres);
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_create_update_lock */
+
+
+/*
+ * ocfs_get_x_for_del()
+ *
+ */
+int ocfs_get_x_for_del (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags,
+			ocfs_lock_res * lockres, ocfs_file_entry * fe)
+{
+	int status = -EFAIL;
+	bool disk_vote = false;
+
+	LOG_ENTRY_ARGS ("(lockid=%u.%u, locktype=%u)\n", HI (lock_id),
+			LO (lock_id), lock_type);
+
+	while (1) {
+		ocfs_acquire_lockres (lockres);
+		/* If I am master and I am the only one in the oin node map */
+		/* update the disk */
+		status = ocfs_make_lock_master (osb, lock_id, lock_type, flags,
+						lockres, fe, &disk_vote);
+		if (status >= 0) {
+			ocfs_release_lockres (lockres);
+			status = 0;
+			goto finally;
+		} else if (status == -EAGAIN) {
+			ocfs_release_lockres (lockres);
+			ocfs_sleep (500);
+			if (ocfs_task_interruptible (osb)) {
+				LOG_TRACE_ARGS("interrupted... lockid=%u.%u\n",
+					       HILO(lock_id));
+				status = -EINTR;
+				goto finally;
+			}
+			status = ocfs_disk_update_resource (osb, lockres, fe, 0);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				osb->vol_state = VOLUME_DISABLED;
+				goto finally;
+			}
+			continue;
+		} else {
+			ocfs_release_lockres (lockres);
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+	}
+
+      finally:
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_get_x_for_del */
+
+#define ACQUIRE_WITH_FLAG(lock, flag)			\
+	do {						\
+		if (!(flag)) {				\
+			ocfs_acquire_lockres(lock);	\
+			(flag) = true;			\
+		}					\
+	} while (0)
+
+#define RELEASE_WITH_FLAG(lock, flag)			\
+	do {						\
+		if (flag) {				\
+			ocfs_release_lockres(lock);	\
+			(flag) = false;			\
+		}					\
+	} while (0)
+
+/*
+ * ocfs_try_exclusive_lock()
+ *
+ */
+int ocfs_try_exclusive_lock(ocfs_super *osb, ocfs_lock_res *lockres, __u32 flags,
+			    __u32 updated, ocfs_file_entry *fe, __u64 lock_id,
+			    __u32 lock_type)
+{
+    int status = 0;
+    bool lockres_acq = false;
+    bool make_lock_master;
+    bool disk_vote = false;
+
+    LOG_ENTRY_ARGS ("(osb=0x%p, lres=0x%p, fl=%u, up=%u, fe=0x%p, "
+		    "id=%u.%u ty=%u)\n", osb, lockres, flags, updated, fe,
+		    HILO(lock_id), lock_type);
+
+    ocfs_get_lockres(lockres);
+    while (1) {
+	ACQUIRE_WITH_FLAG(lockres, lockres_acq);
+   
+	if (lockres->master_node_num != osb->node_num || !updated) {
+		status = ocfs_read_file_entry (osb, fe, lock_id);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+		lockres->master_node_num = DISK_LOCK_CURRENT_MASTER (fe);
+		lockres->lock_type = DISK_LOCK_FILE_LOCK (fe);
+		lockres->oin_openmap = DISK_LOCK_OIN_MAP (fe);
+		updated = true;
+	}
+            
+        if (lockres->master_node_num == osb->node_num) {
+            if ((flags & FLAG_FILE_DELETE) || (flags & FLAG_FILE_RENAME)) {
+                status = ocfs_get_x_for_del (osb, lock_id, lock_type, flags,
+					     lockres, fe);
+		if (status < 0) {
+			if (status != -EINTR)
+				LOG_ERROR_STATUS (status);
+		}
+                goto finally;
+            }
+#if 0
+            if (!updated) {
+                if (lockres->master_node_num != DISK_LOCK_CURRENT_MASTER (fe)) {
+                    lockres->master_node_num = DISK_LOCK_CURRENT_MASTER (fe);
+                    lockres->lock_type = DISK_LOCK_FILE_LOCK (fe);
+                    lockres->oin_openmap = DISK_LOCK_OIN_MAP (fe);
+                    RELEASE_WITH_FLAG(lockres, lockres_acq);
+                    continue;
+                }
+            }
+#endif
+            DISK_LOCK_CURRENT_MASTER (fe) = osb->node_num;
+                
+            if (DISK_LOCK_FILE_LOCK (fe) < OCFS_DLM_EXCLUSIVE_LOCK) {
+                DISK_LOCK_FILE_LOCK (fe) = lock_type;
+                    
+                if (lock_type == OCFS_DLM_ENABLE_CACHE_LOCK) {
+                    status = ocfs_write_force_disk (osb, fe, osb->sect_size, lock_id);
+                    if (status < 0) {
+                        LOG_ERROR_STATUS (status);
+                        goto finally;
+                    }
+                }
+            }
+                                            
+            status = ocfs_write_file_entry (osb, fe, lock_id);
+            if (status < 0) {
+                LOG_ERROR_STATUS (status);
+                goto finally;
+            }
+
+            /* We got the lock */
+            lockres->lock_type = lock_type;
+            status = 0;
+            goto finally;
+        } else {
+            make_lock_master = false;
+#if 0
+            lockres->master_node_num = DISK_LOCK_CURRENT_MASTER (fe);
+            lockres->lock_type = DISK_LOCK_FILE_LOCK (fe);
+            lockres->oin_openmap = DISK_LOCK_OIN_MAP (fe);
+#endif
+            if (lockres->master_node_num != OCFS_INVALID_NODE_NUM) {
+                if (!IS_VALID_NODE_NUM (lockres->master_node_num)) {
+		    status = -EINVAL;
+		    LOG_ERROR_ARGS ("node=%d, status = %d", lockres->master_node_num, status);
+                    goto finally;
+                }
+            }
+    
+            if (lockres->master_node_num == OCFS_INVALID_NODE_NUM) {
+                make_lock_master = true;
+            } else if (!IS_NODE_ALIVE (osb->publ_map, lockres->master_node_num,
+				       OCFS_MAXIMUM_NODES)) {
+                make_lock_master = true;
+                RELEASE_WITH_FLAG(lockres, lockres_acq); 
+                        
+                LOG_TRACE_ARGS ("ocfs_recover_vol(%d)\n",
+				lockres->master_node_num);
+                status = ocfs_recover_vol (osb, lockres->master_node_num);
+                if (status < 0) {
+                    LOG_ERROR_STATUS (status);
+                    goto finally;
+                }
+                ACQUIRE_WITH_FLAG(lockres, lockres_acq); 
+            }
+
+            if (make_lock_master) {
+                /*
+		 * I am not master, master is dead or not there.
+                 * If lock was owned we need to do recovery
+                 * otherwise we need to arbitrate for the lock
+		 */
+
+//                RELEASE_WITH_FLAG(lockres, lockres_acq); 
+
+                status = ocfs_make_lock_master (osb, lock_id, lock_type, flags,
+						lockres, fe, &disk_vote);
+                if (status >= 0) {
+//                    RELEASE_WITH_FLAG(lockres, lockres_acq); 
+                            
+                    if (lock_type == OCFS_DLM_ENABLE_CACHE_LOCK) {
+                        DISK_LOCK_FILE_LOCK (fe) = lock_type;
+                        status = ocfs_write_force_disk (osb, fe, osb->sect_size,
+							lock_id);
+                        if (status < 0) {
+                            LOG_ERROR_STATUS (status);
+                            goto finally;
+                        }
+                    }
+        
+                    DISK_LOCK_CURRENT_MASTER (fe) = osb->node_num;
+                    DISK_LOCK_FILE_LOCK (fe) = lock_type;
+                      
+                    status = ocfs_write_file_entry (osb, fe, lock_id);
+                    if (status < 0) {
+                        LOG_ERROR_STATUS (status);
+                        goto finally;
+                    }
+                                
+                    /* We got the lock */
+                    status = 0;
+                    goto finally;
+                } else if (status == -EAGAIN) {
+                    RELEASE_WITH_FLAG(lockres, lockres_acq); 
+		    ocfs_sleep (500);
+		    if (ocfs_task_interruptible (osb)) {
+			LOG_TRACE_ARGS("interrupted... lockid=%u.%u\n",
+				       HILO(lock_id));
+			status = -EINTR;
+			goto finally;
+		    }
+#if 0
+                    status = ocfs_disk_update_resource (osb, lockres, fe, 0);
+                    if (status < 0) {
+                        LOG_ERROR_STATUS (status);
+                        osb->vol_state = VOLUME_DISABLED;
+                        goto finally;
+                    }
+#endif
+		    updated = false;
+                    continue;
+                } else {
+                    RELEASE_WITH_FLAG(lockres, lockres_acq); 
+                    goto finally;
+                }
+            } else /* !make_lock_master */ {
+                /*
+		 * MasterNode is alive and it is not this node
+                 * If the lock is acquired already by the master
+                 * wait for release else change master.
+		 */
+   
+		if (lockres->lock_type <= OCFS_DLM_SHARED_LOCK) {
+                    if ((flags & FLAG_FILE_DELETE) ||
+			(flags & FLAG_FILE_RENAME)) {
+                        status = ocfs_get_x_for_del (osb, lock_id, lock_type,
+						     flags, lockres, fe);
+                        RELEASE_WITH_FLAG(lockres, lockres_acq); 
+			if (status < 0) {
+				if (status != -EINTR)
+					LOG_ERROR_STATUS (status);
+			}
+                        goto finally;
+                    }
+
+                    /* Change Lock Master */
+                    status = ocfs_update_lock_state (osb, lockres,
+						FLAG_CHANGE_MASTER, &disk_vote);
+//                    RELEASE_WITH_FLAG(lockres, lockres_acq); 
+
+                    if (status < 0) {
+			RELEASE_WITH_FLAG(lockres, lockres_acq); 
+			if (status == -EAGAIN) {
+				ocfs_sleep (500);
+				if (ocfs_task_interruptible (osb)) {
+					LOG_TRACE_ARGS("interrupted... "
+						"lockid=%u.%u\n", HILO(lock_id));
+					status = -EINTR;
+					goto finally;
+				}
+				continue;
+			}
+                        goto finally;
+                    }
+                                
+		    status = ocfs_read_file_entry (osb, fe, lock_id);
+                    if (status < 0) {
+                        LOG_ERROR_STATUS (status);
+                        goto finally;
+                    }
+        
+                    DISK_LOCK_CURRENT_MASTER (fe) = osb->node_num;
+                    DISK_LOCK_FILE_LOCK (fe) = lock_type;
+                    status = ocfs_write_file_entry (osb, fe, lock_id);
+                    if (status < 0) {
+                        LOG_ERROR_STATUS (status);
+                        goto finally;
+                    }
+       
+                    /* Update our state... */
+                    lockres-> master_node_num = DISK_LOCK_CURRENT_MASTER (fe);
+                    lockres->lock_type = DISK_LOCK_FILE_LOCK (fe);
+                    lockres-> oin_openmap = DISK_LOCK_OIN_MAP (fe);
+		    RELEASE_WITH_FLAG(lockres, lockres_acq);
+                    goto finally;
+                } else {
+                    /* Wait for lock release */
+                    RELEASE_WITH_FLAG(lockres, lockres_acq); 
+
+                    status = ocfs_wait_for_lock_release (osb, lock_id, 30000, lockres,
+			((flags & FLAG_DIR) ? OCFS_DLM_SHARED_LOCK : OCFS_DLM_NO_LOCK));
+                    if (status < 0) {
+			if (status == -ETIMEDOUT) {
+				LOG_TRACE_ARGS("lock %u.%u, level %d, not being "
+					"freed by node %u\n", HILO(lock_id),
+				       	lockres->lock_type, lockres->master_node_num);
+				continue;
+			} else if (status == -EINTR)
+				goto finally;
+                        else
+                            goto finally;
+                    }
+                    /* Try and acquire the lock again */
+                    continue;
+                }
+            } /* make_lock_master */
+        } /* master_node_num */
+    } /* while */
+    
+finally: 
+    RELEASE_WITH_FLAG(lockres, lockres_acq); 
+    ocfs_put_lockres(lockres);
+    LOG_EXIT_STATUS (status);
+    return status;
+}				/* ocfs_try_exclusive_lock */
+
+/*
+ * ocfs_acquire_lock()
+ *
+ */
+int ocfs_acquire_lock (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags,
+		       ocfs_lock_res ** lockres, ocfs_file_entry * lock_fe)
+{
+	int status = -EFAIL;
+	bool lockres_acq = false;
+	ocfs_file_entry *disklock = NULL;
+	__u32 updated = 0;
+
+	LOG_ENTRY_ARGS ("(0x%p, %u.%u, %u, %u, 0x%p, 0x%p)\n", osb,
+			HI (lock_id), LO (lock_id), lock_type, flags, lockres,
+			lock_fe);
+
+	if (lock_fe)
+		disklock = lock_fe;
+	else {
+		disklock = ocfs_allocate_file_entry ();
+		if (disklock == NULL) {
+			LOG_ERROR_STATUS (status = -ENOMEM);
+			goto finally;
+		}
+	}
+
+	status = ocfs_find_update_res (osb, lock_id, lockres, disklock,
+				       &updated, 0);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	switch (lock_type) {
+	    case OCFS_DLM_SHARED_LOCK:
+		    if (!(flags & FLAG_DIR)) {
+			    status = 0;
+			    goto finally;
+		    }
+
+		    ocfs_acquire_lockres (*lockres);
+		    lockres_acq = true;
+
+		    if ((*lockres)->lock_type == OCFS_DLM_NO_LOCK) {
+			    (*lockres)->lock_type = OCFS_DLM_SHARED_LOCK;
+		    }
+		    if (((*lockres)->lock_type == OCFS_DLM_ENABLE_CACHE_LOCK) &&
+			((*lockres)->master_node_num != osb->node_num)) {
+			    status = ocfs_break_cache_lock (osb, *lockres, disklock);
+			    if (status < 0) {
+				    if (status != -EINTR)
+					LOG_ERROR_STATUS (status);
+				    goto finally;
+			    }
+		    }
+
+		    atomic_inc (&((*lockres)->lr_share_cnt));
+
+		    if (lockres_acq) {
+			    ocfs_release_lockres (*lockres);
+			    lockres_acq = false;
+		    }
+
+		    status = 0;
+		    goto finally;
+		    break;
+
+	    case OCFS_DLM_EXCLUSIVE_LOCK:
+	    case OCFS_DLM_ENABLE_CACHE_LOCK:
+		    /* This will be called for vol, allocation, file and */
+		    /* directory from create modify */
+		    status = ocfs_try_exclusive_lock(osb, *lockres, flags,
+						     updated, disklock, lock_id,
+						     lock_type);
+		    if (status < 0) {
+			if (status != -EINTR)
+				LOG_ERROR_STATUS (status);
+			goto finally;
+		    }
+		    break;
+
+	    default:
+		    break;
+	}
+
+      finally:
+	if ((lock_fe == NULL))
+		ocfs_release_file_entry (disklock);
+	if (lockres_acq)
+		ocfs_release_lockres (*lockres);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_acquire_lock */
+
+/*
+ * ocfs_disk_release_lock()
+ *
+ */
+int ocfs_disk_release_lock (ocfs_super * osb, __u64 lock_id, __u32 lock_type,
+			    __u32 flags, ocfs_lock_res * lockres, ocfs_file_entry *fe)
+{
+	__u32 votemap = 0;
+	__u32 tempmap = 0;
+	__u32 i;
+	int status = 0;
+	int tmpstat;
+	__u64 lockseqno;
+	bool cachelock = false;
+	bool disk_vote = false;
+	bool fe_alloc = false;
+	unsigned long jif;
+	bool disk_reset = true;
+
+	LOG_ENTRY_ARGS ("(0x%p, %u.%u, %u, %u, 0x%p)\n", osb, HI (lock_id),
+			LO (lock_id), lock_type, flags, lockres);
+
+//	ocfs_acquire_lockres (lockres);
+
+	if (fe == NULL) {
+		status = ocfs_get_file_entry (osb, &fe, lock_id);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finito;
+		}
+		fe_alloc = true;
+	}
+
+	if (!IS_VALID_NODE_NUM (DISK_LOCK_CURRENT_MASTER (fe))) {
+		LOG_ERROR_STATUS(status = -EINVAL);
+		goto finito;
+	}
+
+	if (DISK_LOCK_CURRENT_MASTER (fe) != osb->node_num) {
+		LOG_ERROR_ARGS ("Current master is NOT this NODE (%d)",
+				DISK_LOCK_CURRENT_MASTER (fe));
+		status = 0;
+		goto finito;
+	}
+
+	for (i = 0; i < OCFS_MAXIMUM_NODES; i++) {
+		if (((1 << i) & DISK_LOCK_OIN_MAP (fe)) &&
+		    IS_NODE_ALIVE (osb->publ_map, i, OCFS_MAXIMUM_NODES)) {
+			votemap |= (1 << i);
+		}
+	}
+
+	/* Send an update to all nodes alive, can be optimized later TODO */
+	if ((flags & FLAG_FILE_RENAME) || (flags & FLAG_FILE_DELETE))
+		votemap = (__u32) (osb->publ_map);
+
+	/* TODO: figure out how to properly handle inode updates w/no oin */
+	votemap = (__u32) (osb->publ_map);	// temporary hack, forces broadcast
+
+	/* remove current node from the votemap */
+	tempmap = (1 << osb->node_num);
+	votemap &= (~tempmap);
+	jif = jiffies;
+
+	if (votemap == 0)
+		goto finally;
+
+	if (!(flags & FLAG_FILE_UPDATE_OIN) && !(flags & FLAG_FILE_DELETE))
+		goto finally;
+
+	ocfs_compute_lock_type_stats (&(osb->lock_type_stats),
+				      OCFS_DISK_RELEASE_LOCK);
+
+	flags |= FLAG_FILE_RELEASE_LOCK;
+	status = -EAGAIN;
+	while (status == -EAGAIN) {
+#ifndef USERSPACE_TOOL
+		if (comm_voting && !disk_vote) {
+			LOG_TRACE_STR ("Network vote");
+			status = ocfs_send_dlm_request_msg (osb, lock_id, lock_type,
+						    	flags, lockres, votemap);
+			if (status >= 0) {
+				status = lockres->vote_status;
+				if (status >= 0) {
+					goto finally;
+				} else if (status == -EAGAIN) {
+					goto loop;
+				} else {
+					LOG_ERROR_STATUS (status);
+					goto finito;
+				}
+			} else if (status == -ETIMEDOUT) {
+				LOG_TRACE_STR ("Network voting timed out");
+			}
+			lockres->vote_state = 0;
+		}
+#endif
+	
+		LOG_TRACE_STR ("Disk vote");
+		disk_vote = true;
+		jif = jiffies;
+
+		disk_reset = false;
+		status = ocfs_request_vote (osb, lock_id, lock_type, flags,
+					    votemap, &lockseqno);
+		if (status < 0) {
+			if (status == -EAGAIN) {
+				if ((flags & FLAG_FILE_UPDATE_OIN)) {
+					// ?????
+				}
+				goto reset;
+			}
+			LOG_ERROR_STATUS (status);
+			goto finito;
+		}
+
+		status = ocfs_wait_for_vote (osb, lock_id, lock_type,
+					     FLAG_FILE_UPDATE_OIN, votemap,
+					     5000, lockseqno, lockres);
+		if (status < 0) {
+			if (status == -EAGAIN)
+				goto reset;
+			LOG_ERROR_STATUS (status);
+			goto finito;
+		}
+
+              reset:
+		tmpstat = ocfs_reset_voting (osb, lock_id, lock_type,
+					     DISK_LOCK_OIN_MAP (fe));
+		if (tmpstat < 0) {
+			LOG_ERROR_STATUS (status = tmpstat);
+			goto finito;
+		}
+
+		disk_reset = true;
+
+		if (status != -EAGAIN)
+			break;
+
+#ifndef USERSPACE_TOOL
+	      loop:
+#endif
+		LOG_TRACE_ARGS ("id=%u.%u\n", HILO(lock_id));
+		ocfs_sleep (500);
+	}
+
+      finally:
+	jif = jiffies - jif;
+	LOG_TRACE_ARGS ("Lock time: %u\n", jif);
+
+	if (disk_vote && !disk_reset) {
+		tmpstat = ocfs_reset_voting (osb, lock_id, lock_type,
+					    DISK_LOCK_OIN_MAP (fe));
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+	}
+
+	if (flags & FLAG_FILE_RELEASE_MASTER)
+		DISK_LOCK_CURRENT_MASTER (fe) = OCFS_INVALID_NODE_NUM;
+
+	if ((DISK_LOCK_FILE_LOCK (fe) == OCFS_DLM_ENABLE_CACHE_LOCK) &&
+	    (DISK_LOCK_CURRENT_MASTER (fe) == osb->node_num))
+		cachelock = true;
+	else
+		DISK_LOCK_FILE_LOCK (fe) = OCFS_DLM_NO_LOCK;
+
+	/* Reset the lock on the disk */
+	if (!cachelock) {
+		tmpstat = ocfs_write_file_entry (osb, fe, lock_id);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+	}
+
+      finito:
+	if (fe_alloc)
+		ocfs_release_file_entry (fe);
+//	ocfs_release_lockres (lockres);
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_disk_release_lock */
+
+/*
+ * ocfs_release_lock()
+ *
+ */
+int ocfs_release_lock (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags,
+		       ocfs_lock_res * lockres, ocfs_file_entry *fe)
+{
+	int status = 0;
+	bool lock_acq = false;
+
+	LOG_ENTRY_ARGS ("(0x%p, %u.%u, %u, %u, 0x%p)\n", osb, HI (lock_id),
+			LO (lock_id), lock_type, flags, lockres);
+
+	ocfs_acquire_lockres (lockres);
+	lock_acq = true;
+
+	switch (lock_type) {
+	    case OCFS_DLM_SHARED_LOCK:
+		    if (atomic_dec_and_test (&lockres->lr_share_cnt)) {
+			    if (lockres->lock_type == OCFS_DLM_SHARED_LOCK)
+				    lockres->lock_type = OCFS_DLM_NO_LOCK;
+		    }
+		    status = 0;
+		    goto finally;
+
+	    case OCFS_DLM_EXCLUSIVE_LOCK:
+		    break;
+	}
+	/*
+	 * Change flags based on which kind of lock we are releasing
+	 * For directory we need special handling of oin updates when the release
+	 * is for XBcast
+	 * For file we need to update oin's
+	 * For Shared we need to update the lock state locally only
+	 */
+
+	/* OcfsRelease */
+
+	/* CommReleaseLock */
+	if (flags & FLAG_FILE_DELETE) {
+		lockres->lock_type = OCFS_DLM_NO_LOCK;
+		lockres->master_node_num = OCFS_INVALID_NODE_NUM;
+		status = 0;
+		goto do_release_lock;
+	}
+//    if(lock_id != OCFS_BITMAP_LOCK_OFFSET)
+	{
+		if ((lockres->lock_type == OCFS_DLM_ENABLE_CACHE_LOCK) &&
+		    (lockres->master_node_num == osb->node_num)) {
+			status = 0;
+			goto finally;
+		}
+	}
+
+	if (lock_id == OCFS_BITMAP_LOCK_OFFSET) {
+		LOG_TRACE_ARGS ("Bitmap lock state is (%d)\n",
+				lockres->lock_type);
+	}
+
+	lockres->lock_type = OCFS_DLM_NO_LOCK;
+	if (flags & FLAG_FILE_RELEASE_MASTER)
+		lockres->master_node_num = OCFS_INVALID_NODE_NUM;
+
+do_release_lock:
+//	if (lock_acq) {
+//		ocfs_release_lockres (lockres);
+//		lock_acq = false;
+//	}
+
+	status = ocfs_disk_release_lock (osb, lock_id, lock_type, flags,
+					 lockres, fe);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+finally:
+	if (lock_acq)
+		ocfs_release_lockres (lockres);
+
+	LOG_EXIT_STATUS (status);
+	return (status);
+}				/* ocfs_release_lock */
+
+/*
+ * ocfs_init_dlm()
+ *
+ */
+int ocfs_init_dlm (void)
+{
+	LOG_ENTRY ();
+
+	OcfsIpcCtxt.init = false;
+	OcfsIpcCtxt.re_init = false;
+
+	LOG_EXIT_STATUS (0);
+	return 0;
+}				/* ocfs_init_dlm */
+
+
+/*
+ * ocfs_add_lock_to_recovery()
+ *
+ */
+int ocfs_add_lock_to_recovery (void)
+{
+	return 0;
+}				/* ocfs_add_lock_to_recovery */
+
+/*
+ * ocfs_create_log_extent_map()
+ *
+ */
+int ocfs_create_log_extent_map (ocfs_super * osb,
+		    ocfs_io_runs ** PTransRuns,
+		    __u32 * PNumTransRuns, __u64 diskOffset, __u64 ByteCount)
+{
+	int status = 0;
+	__s64 tempVbo = 0;
+	__s64 tempLbo = 0;
+	__u32 tempSize = 0;
+	__u32 numDataRuns = 0;
+	__u32 numTransRuns;
+	__u32 i;
+	__u32 numMetaDataRuns = 0;
+	__u32 ioRunSize;
+	ocfs_io_runs *IoDataRuns = NULL;
+	ocfs_io_runs *IoMetaDataRuns = NULL;
+	ocfs_io_runs *IoTransRuns = NULL;
+	ocfs_io_runs *TransRuns = NULL;
+	__u64 file_size;
+	__u64 remainingLength;
+	bool bRet;
+	__u32 RunsInExtentMap = 0;
+	__u32 ExtentMapIndex;
+	__u32 length;
+	__s64 diskOffsetToFind = 0;
+	__s64 foundFileOffset = 0;
+	__s64 foundDiskOffset = 0;
+
+	LOG_ENTRY ();
+
+	ioRunSize = (OCFS_MAX_DATA_EXTENTS * sizeof (ocfs_io_runs));
+
+	IoTransRuns = ocfs_malloc (ioRunSize);
+	if (IoTransRuns == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto bail;
+	}
+
+	IoMetaDataRuns = ocfs_malloc (ioRunSize);
+	if (IoMetaDataRuns == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto bail;
+	}
+
+	IoDataRuns = ocfs_malloc (ioRunSize);
+	if (IoDataRuns == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto bail;
+	}
+
+	TransRuns = ocfs_malloc (ioRunSize);
+	if (TransRuns == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto bail;
+	}
+
+	diskOffsetToFind = diskOffset;
+	remainingLength = ByteCount;
+
+	ocfs_down_sem (&(osb->map_lock), true);
+
+	RunsInExtentMap = ocfs_extent_map_get_count (&osb->metadata_map);
+
+	for (ExtentMapIndex = 0; ExtentMapIndex < RunsInExtentMap;
+	     ExtentMapIndex++) {
+		__u32 tempLen;
+
+		if (!ocfs_get_next_extent_map_entry
+		    (osb, &osb->metadata_map, ExtentMapIndex, &foundFileOffset,
+		     &foundDiskOffset, &tempLen))
+			continue;
+
+		length = tempLen;
+
+		if (foundDiskOffset >= (diskOffsetToFind + remainingLength))
+			break;
+
+		if (diskOffsetToFind >= (foundDiskOffset + length)) {
+			/* This meta data run is before the relevant stf */
+			continue;
+		} else {
+			if ((diskOffsetToFind >= foundDiskOffset) &&
+			    ((diskOffsetToFind + remainingLength) <=
+			     (foundDiskOffset + length))) {
+				/* It is only metadata */
+				IoMetaDataRuns[numMetaDataRuns].offset =
+				    diskOffsetToFind;
+				IoMetaDataRuns[numMetaDataRuns].disk_off =
+				    diskOffsetToFind;
+				IoMetaDataRuns[numMetaDataRuns].byte_cnt =
+				    remainingLength;
+				remainingLength -=
+				    IoMetaDataRuns[numMetaDataRuns].byte_cnt;
+				diskOffsetToFind +=
+				    IoMetaDataRuns[numMetaDataRuns].byte_cnt;
+				numMetaDataRuns++;
+				break;
+			} else if ((diskOffsetToFind < foundDiskOffset) &&
+				   ((diskOffsetToFind + remainingLength) >
+				    foundDiskOffset)) {
+				/* We have a data run and a metadata run */
+				IoDataRuns[numDataRuns].offset =
+				    diskOffsetToFind;
+				IoDataRuns[numDataRuns].disk_off =
+				    diskOffsetToFind;
+				IoDataRuns[numDataRuns].byte_cnt =
+				    foundDiskOffset - diskOffsetToFind;
+				remainingLength -=
+				    IoDataRuns[numDataRuns].byte_cnt;
+				diskOffsetToFind +=
+				    IoDataRuns[numDataRuns].byte_cnt;
+				numDataRuns++;
+
+				IoMetaDataRuns[numMetaDataRuns].offset =
+				    foundDiskOffset;
+				IoMetaDataRuns[numMetaDataRuns].disk_off =
+				    foundDiskOffset;
+				IoMetaDataRuns[numMetaDataRuns].byte_cnt =
+				    (remainingLength >
+				     length) ? length : remainingLength;
+
+				remainingLength -=
+				    IoMetaDataRuns[numMetaDataRuns].byte_cnt;
+				diskOffsetToFind +=
+				    IoMetaDataRuns[numMetaDataRuns].byte_cnt;
+				numMetaDataRuns++;
+				if (remainingLength > 0)
+					continue;
+				else
+					break;
+			} else if ((diskOffsetToFind >= foundDiskOffset) &&
+				   ((diskOffsetToFind + remainingLength) >
+				    (foundDiskOffset + length))) {
+				/* Meta data and as yet unknown data */
+				IoMetaDataRuns[numMetaDataRuns].offset =
+				    diskOffsetToFind;
+				IoMetaDataRuns[numMetaDataRuns].disk_off =
+				    diskOffsetToFind;
+				IoMetaDataRuns[numMetaDataRuns].byte_cnt =
+				    length - (diskOffsetToFind -
+					      foundDiskOffset);
+				remainingLength -=
+				    IoMetaDataRuns[numMetaDataRuns].byte_cnt;
+				diskOffsetToFind +=
+				    IoMetaDataRuns[numMetaDataRuns].byte_cnt;
+				numMetaDataRuns++;
+				continue;
+			}
+		}
+	}
+
+	ocfs_up_sem (&(osb->map_lock));
+
+	numTransRuns = *PNumTransRuns = 0;
+
+	/* Create new extent map from real runs */
+
+	for (i = 0; i < numMetaDataRuns; i++) {
+		if (osb->log_disk_off == 0)
+			ocfs_create_meta_log_files (osb);
+
+		file_size = osb->log_file_size;
+
+		if (file_size > (10 * ONE_MEGA_BYTE))
+			LOG_ERROR_ARGS ("file_size=%d.%d", HI(file_size),
+					LO(file_size));
+
+		tempVbo = IoMetaDataRuns[i].disk_off;	/* Actual Disk Offset */
+		tempLbo = file_size + osb->log_disk_off;	/* Log file disk Offset */
+		tempSize = IoMetaDataRuns[i].byte_cnt;	/* Lenght of run */
+
+		osb->log_file_size = (file_size + tempSize);
+
+		/* Add the Extent to extent map list */
+		ocfs_down_sem (&(osb->map_lock), true);
+		LOG_TRACE_STR ("Acquired map_lock");
+
+		bRet =
+		    ocfs_add_extent_map_entry (osb, &osb->trans_map, tempVbo,
+					   tempLbo, tempSize);
+		if (!bRet) {
+			ocfs_remove_extent_map_entry (osb, &osb->trans_map, tempVbo,
+						  tempSize);
+			bRet =
+			    ocfs_add_extent_map_entry (osb, &osb->trans_map,
+						   tempVbo, tempLbo, tempSize);
+		}
+
+		ocfs_up_sem (&(osb->map_lock));
+		LOG_TRACE_STR ("Released map_lock");
+
+		if (!bRet) {
+			LOG_ERROR_STATUS(status = -EFAIL);
+			goto bail;
+		}
+
+		TransRuns[numTransRuns].offset = tempVbo;
+		TransRuns[numTransRuns].disk_off = tempLbo;
+		TransRuns[numTransRuns].byte_cnt = tempSize;
+		numTransRuns++;
+	}
+
+	file_size = osb->log_file_size;
+
+	if (file_size > (10 * ONE_MEGA_BYTE))
+		LOG_ERROR_ARGS ("file_size=%d.%d", HI(file_size), LO(file_size));
+
+	if (file_size >= (2 * ONE_MEGA_BYTE))
+		osb->needs_flush = true;
+
+	*PNumTransRuns = numTransRuns;
+	*PTransRuns = TransRuns;
+
+	ocfs_safefree (IoTransRuns);
+	ocfs_safefree (IoMetaDataRuns);
+	ocfs_safefree (IoDataRuns);
+
+      bail:
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_create_log_extent_map */
+
+/*
+ * ocfs_lookup_cache_link()
+ *
+ */
+int ocfs_lookup_cache_link (ocfs_super * osb, __u8 * buf, __u64 actual_disk_off,
+			    __u64 length)
+{
+	int status = 0;
+#ifndef USERSPACE_TOOL
+	ocfs_file_entry *fe = NULL;
+	ocfs_lock_res *lockres = NULL;
+	__u64 offset = 0;
+	struct list_head *entry;
+	struct list_head *tmp_entry;
+	ocfs_inode *oin;
+#endif
+
+	LOG_ENTRY ();
+
+#ifndef USERSPACE_TOOL
+	offset = actual_disk_off;
+
+	list_for_each_safe (entry, tmp_entry, &(osb->cache_lock_list)) {
+		lockres = list_entry (entry, ocfs_lock_res, cache_list);
+		if (lockres == NULL) {
+			LOG_ERROR_STATUS(status = -EFAIL);
+			goto bail;
+		}
+
+		ocfs_acquire_lockres (lockres);
+
+		if ((lockres->sector_num >= actual_disk_off) &&
+		    (lockres->sector_num < (actual_disk_off + length))) {
+			LOG_TRACE_ARGS ("ocfs_lookup_cache_link has a valid "
+				"entry in cache link for disk offset %u.%u\n",
+				HI (lockres->sector_num), LO (lockres->sector_num));
+
+			/* Change Lock type */
+			fe = (ocfs_file_entry *)
+				((__u8 *) buf + (lockres->sector_num - actual_disk_off));
+
+			/* Flush */
+			if (lockres->oin != NULL) {
+				oin = lockres->oin;
+				oin->cache_enabled = false;
+
+				/* If the Open Handle Count is zero , then release the */
+				/* lock and no need to flush as the data must already */
+				/* be flushed */
+
+				if (!(oin->oin_flags & OCFS_OIN_DIRECTORY)) {
+					if (oin->open_hndl_cnt == 0)
+						lockres->lock_type =
+						    DISK_LOCK_FILE_LOCK (fe) =
+						    OCFS_DLM_NO_LOCK;
+					else
+						ocfs_flush_cache (osb);
+				}
+			} else {
+				/* Release the lock, as there will be no open */
+				/* handle if there is no oin, and so we don't */
+				/* need to keep the lock state to caching */
+				lockres->lock_type = DISK_LOCK_FILE_LOCK (fe) =
+								OCFS_DLM_NO_LOCK;
+			}
+			lockres->in_cache_list = false;
+			list_del (entry);
+		}
+		ocfs_release_lockres (lockres);
+	}
+      bail:
+#endif /* USERSPACE_TOOL */
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_lookup_cache_link */
+
+/*
+ * ocfs_process_log_file()
+ * 
+ * This is recovery. It will read the log file based on trans extent map and
+ * do the actual disk writes of meta data at right disk offset.
+ */
+int ocfs_process_log_file (ocfs_super * osb, bool flag)
+{
+	int status = 0;
+	__u8 *meta_data_buf = NULL;
+	__u8 *tmp_buf = NULL;
+	__u32 size;
+	__u32 i = 0;
+	ocfs_offset_map *map_buf;
+	__u64 file_size;
+	__u64 meta_file_size;
+	__u64 meta_alloc_size;
+	__u64 offset;
+
+	LOG_ENTRY ();
+
+	meta_alloc_size = 0;
+	status = ocfs_get_system_file_size (osb,
+					    (OCFS_FILE_VOL_META_DATA + osb->node_num),
+					    &meta_file_size, &meta_alloc_size);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	size = OCFS_ALIGN (meta_file_size, osb->vol_layout.cluster_size);
+	meta_data_buf = ocfs_malloc (size);
+	if (meta_data_buf == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto finally;
+	}
+
+	status = ocfs_read_system_file (osb,
+					(OCFS_FILE_VOL_META_DATA + osb->node_num),
+					meta_data_buf, size, 0);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto finally;
+	}
+
+	file_size = osb->log_file_size;
+
+	size = 0;
+	i = 0;
+
+	while (meta_file_size != 0) {
+		map_buf = (ocfs_offset_map *)
+				(meta_data_buf + (i * sizeof (ocfs_offset_map)));
+
+		if ((map_buf->length % OCFS_SECTOR_SIZE) ||
+		    (map_buf->actual_disk_off % OCFS_SECTOR_SIZE)) {
+			LOG_ERROR_STR ("length or actual_disk_off is not aligned");
+		}
+
+		if (size < map_buf->length) {
+			ocfs_safefree (tmp_buf);
+			size = OCFS_ALIGN (map_buf->length, osb->sect_size);
+			tmp_buf = ocfs_malloc (size);
+			if (tmp_buf == NULL) {
+				LOG_ERROR_STATUS (status = -ENOMEM);
+				goto finally;
+			}
+		}
+
+		offset = map_buf->log_disk_off;
+
+		status = ocfs_read_force_disk (osb, tmp_buf, map_buf->length,
+					       offset);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+
+		offset = map_buf->actual_disk_off;
+
+		if (flag) {
+			status = ocfs_lookup_cache_link (osb, tmp_buf,
+					map_buf->actual_disk_off, map_buf->length);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto finally;
+			}
+		}
+
+		status = ocfs_write_force_disk (osb, tmp_buf, map_buf->length,
+						offset);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+
+		meta_file_size -= sizeof (ocfs_offset_map);
+		i++;
+	}
+
+      finally:
+	ocfs_safefree (meta_data_buf);
+	ocfs_safefree (tmp_buf);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_process_log_file */
+
+
+/*
+ * ocfs_break_cache_lock()
+ *
+ */
+int ocfs_break_cache_lock (ocfs_super * osb, ocfs_lock_res * lockres,
+			   ocfs_file_entry *fe)
+{
+	int status;
+	int tmpstat;
+	__u32 votemap;
+	__u64 lockseqno = 0;
+	bool disk_vote = false;
+	unsigned long jif;
+	bool disk_reset = true;
+	__u32 flags = FLAG_FILE_RELEASE_CACHE | FLAG_FILE_ACQUIRE_LOCK;
+
+	LOG_ENTRY_ARGS ("(osb=0x%p, lres=0x%p, fe=0x%p)\n", osb, lockres, fe);
+
+	ocfs_acquire_lockres (lockres);
+
+	/* Ask the node with cache to flush and revert to write thru on this file */
+	votemap = (1 << lockres->master_node_num);
+
+	ocfs_compute_lock_type_stats (&(osb->lock_type_stats),
+				      OCFS_BREAK_CACHE_LOCK);
+
+	jif = jiffies;
+	status = -EAGAIN;
+	while (status == -EAGAIN) {
+		if (!IS_NODE_ALIVE (osb->publ_map, lockres->master_node_num,
+				    OCFS_MAXIMUM_NODES)) {
+			LOG_TRACE_ARGS ("Master (%u) is dead, lockid %u.%u\n",
+				lockres->master_node_num, lockres->sector_num);
+			/* TODO recovery needs to be done here .....and then become master */
+			status = 0;
+			goto finally;
+		}
+
+#ifndef USERSPACE_TOOL  
+		if (comm_voting && !disk_vote) {
+			LOG_TRACE_STR ("Network vote");
+			jif = jiffies;
+			status = ocfs_send_dlm_request_msg (osb, lockres->sector_num,
+						    	lockres->lock_type, flags,
+						    	lockres, votemap);
+			if (status >= 0) {
+				status = lockres->vote_status;
+				if (status >= 0) {
+					lockres->lock_type = OCFS_DLM_NO_LOCK;
+					goto finally;
+				} else if (status == -EAGAIN) {
+					goto loop;
+				} else {
+					LOG_ERROR_STATUS (status);
+					goto finito;
+				}
+			} else if (status == -ETIMEDOUT) {
+				LOG_TRACE_STR ("Network voting timed out");
+			}
+			lockres->vote_state = 0;
+		}
+#endif
+
+		LOG_TRACE_STR ("Disk vote");
+		disk_vote = true;
+		jif = jiffies;
+		disk_reset = false;
+		status = ocfs_request_vote (osb, lockres->sector_num,
+					    lockres->lock_type, flags,
+					    votemap, &lockseqno);
+		if (status < 0) {
+			if (status == -EAGAIN)
+				goto reset;
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+
+		status = ocfs_wait_for_vote (osb, lockres->sector_num,
+					     lockres->lock_type, flags,
+					     votemap, 15000, lockseqno, lockres);
+		if (status < 0) {
+			if (status == -EAGAIN)
+				goto reset;
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+
+              reset:
+		tmpstat = ocfs_reset_voting (osb, lockres->sector_num,
+					    lockres->lock_type, votemap);
+		if (tmpstat < 0) {
+			LOG_ERROR_STATUS (status = tmpstat);
+			goto finito;
+		}
+
+		disk_reset = true;
+
+		if (status != -EAGAIN)
+			break;
+
+#ifndef USERSPACE_TOOL
+	      loop:
+#endif
+		LOG_TRACE_ARGS ("id=%u.%u\n", HILO(lockres->sector_num));
+		ocfs_sleep (500);
+
+		if (ocfs_task_interruptible (osb)) {
+			LOG_TRACE_ARGS("interrupted.... lockid=%u.%u\n",
+				       HILO(lockres->sector_num));
+			status = -EINTR;
+			goto finito;
+		}
+	}
+
+	lockres->lock_type = (__u8) OCFS_DLM_NO_LOCK;
+
+      finally:
+	jif = jiffies - jif;
+	LOG_TRACE_ARGS ("Lock time: %u\n", jif);
+
+	if (disk_vote && !disk_reset) {
+		tmpstat = ocfs_reset_voting (osb, lockres->sector_num,
+					    lockres->lock_type, votemap);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+	}
+
+      finito:
+	ocfs_release_lockres (lockres);
+	LOG_EXIT_STATUS (status);
+	return (status);
+}				/* ocfs_break_cache_lock */

Added: trunk/libocfs/Common/ocfsgenmisc.c
===================================================================
--- trunk/libocfs/Common/ocfsgenmisc.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/ocfsgenmisc.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,992 @@
+/*
+ * ocfsgenmisc.c
+ *
+ * Miscellaneous.
+ *
+ * Copyright (C) 2002, 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifdef __KERNEL__
+#include <ocfs.h>
+#else
+#include <libocfs.h>
+#endif
+
+
+/* Tracing */
+#define OCFS_DEBUG_CONTEXT    OCFS_DEBUG_CONTEXT_MISC
+
+/*  Global Sequence number for error log. */
+
+__u32 OcfsErrorLogSequence = 0;
+
+/*
+ * ocfs_create_meta_log_files()
+ *
+ */
+int ocfs_create_meta_log_files (ocfs_super * osb)
+{
+	int status = 0;
+	__u64 fileSize = 0;
+	__u64 allocSize = 0;
+	__u64 log_disk_off = 0;
+	__u32 logFileId;
+
+	LOG_ENTRY ();
+
+	logFileId = (OCFS_FILE_VOL_LOG_FILE + osb->node_num);
+
+	status = ocfs_get_system_file_size (osb, logFileId, &fileSize, &allocSize);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto bail;
+	}
+
+	if (allocSize != 0) {
+		log_disk_off = ocfs_file_to_disk_off (osb, (OCFS_FILE_VOL_LOG_FILE +
+						       osb->node_num), 0);
+		if (log_disk_off == 0) {
+			LOG_ERROR_STATUS(status = -EFAIL);
+			goto bail;
+		}
+
+		osb->log_disk_off = log_disk_off;
+
+		log_disk_off = ocfs_file_to_disk_off (osb, (OCFS_FILE_VOL_META_DATA +
+						       osb->node_num), 0);
+		if (log_disk_off == 0) {
+			LOG_ERROR_STATUS(status = -EFAIL);
+			goto bail;
+		}
+		osb->log_meta_disk_off = log_disk_off;
+		goto bail;
+	}
+
+	status = ocfs_extend_system_file (osb, (OCFS_FILE_VOL_LOG_FILE +
+					 osb->node_num), (ONE_MEGA_BYTE * 10), NULL);
+	if (status < 0) {
+		/* if that fails, fall back to smaller, for fragmented fs */
+		status = ocfs_extend_system_file (osb, (OCFS_FILE_VOL_LOG_FILE +
+					osb->node_num), 128 * 1024, NULL);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto bail;
+		}
+	}
+
+	ocfs_extend_system_file (osb, (OCFS_FILE_VOL_LOG_FILE + osb->node_num), 0, NULL);
+
+	log_disk_off = ocfs_file_to_disk_off (osb, (OCFS_FILE_VOL_LOG_FILE +
+					       osb->node_num), 0);
+	if (log_disk_off == 0) {
+		LOG_ERROR_STATUS(status = -EFAIL);
+		goto bail;
+	}
+
+	osb->log_disk_off = log_disk_off;
+
+	status = ocfs_extend_system_file (osb, (OCFS_FILE_VOL_META_DATA +
+					 osb->node_num), ONE_MEGA_BYTE, NULL);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto bail;
+	}
+
+	ocfs_extend_system_file (osb, (OCFS_FILE_VOL_META_DATA + osb->node_num), 0, NULL);
+
+	log_disk_off = ocfs_file_to_disk_off (osb, (OCFS_FILE_VOL_META_DATA +
+					       osb->node_num), 0);
+	if (log_disk_off == 0) {
+		LOG_ERROR_STATUS(status = -EFAIL);
+		goto bail;
+	}
+
+	osb->log_meta_disk_off = log_disk_off;
+
+      bail:
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_create_meta_log_files */
+
+/*
+ * ocfs_create_new_oin()
+ *
+ * Create a new oin.
+ */
+int ocfs_create_new_oin (ocfs_inode ** Returnedoin,
+		  __u64 * alloc_size,
+		  __u64 * EndOfFile, struct file *FileObject, ocfs_super * osb)
+{
+	int status = 0;
+	ocfs_inode *oin = NULL;
+
+	LOG_ENTRY ();
+
+	/* Don't do OCFS_ASSERT for FileObject, as it is OK if FileObject is NULL */
+
+	OCFS_ASSERT (osb);
+
+	oin = ocfs_allocate_oin ();
+	*Returnedoin = oin;
+
+	if (oin == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto finally;
+	}
+
+	ocfs_init_sem (&(oin->main_res));
+	ocfs_init_sem (&(oin->paging_io_res));
+	OCFS_SET_FLAG (oin->oin_flags, OCFS_INITIALIZED_MAIN_RESOURCE);
+
+	/*  Initialize the alloc size value here, file size will come later in i_size */
+	oin->alloc_size = *(alloc_size);
+
+	/* Insert the pointer to osb in the oin and also Initialize the OFile list  */
+	oin->osb = osb;
+	INIT_LIST_HEAD (&(oin->next_ofile));
+
+      finally:
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_create_new_oin */
+
+/* ocfs_create_root_dir_node()
+ *
+ */
+int ocfs_create_root_dir_node (ocfs_super * osb)
+{
+	int status = 0, tempstat;
+	ocfs_dir_node *NewDirNode = NULL;
+	__u64 bitmapOffset, numClustersAlloc, fileOffset = 0;
+	__u32 size, i;
+	ocfs_vol_disk_hdr *volDiskHdr = NULL;
+	ocfs_lock_res *LockResource = NULL;
+	bool lock_acq = false;
+	char *buf = NULL;
+	ocfs_file_entry *fe = NULL;
+	ocfs_file_entry *sys_fe = NULL;
+
+	LOG_ENTRY ();
+
+	fe = ocfs_allocate_file_entry ();
+	if (fe == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto bail;
+	}
+
+	/* Acquire volume Lock ...  */
+	status = ocfs_acquire_lock (osb, OCFS_VOLUME_LOCK_OFFSET,
+				    OCFS_DLM_EXCLUSIVE_LOCK, FLAG_FILE_CREATE,
+				    &LockResource, fe);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto bail;
+	} else
+		lock_acq = true;
+
+	NewDirNode = ocfs_allocate_dirnode();
+	if (NewDirNode == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto bail;
+	}
+
+	size = (ONE_MEGA_BYTE > osb->vol_layout.cluster_size) ?
+	    ONE_MEGA_BYTE : osb->vol_layout.cluster_size;
+
+	status = ocfs_find_contiguous_space_from_bitmap (osb, size,
+					&bitmapOffset, &numClustersAlloc, false);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto bail;
+	}
+
+	osb->vol_layout.root_int_off = (bitmapOffset *
+					osb->vol_layout.cluster_size) +
+					osb->vol_layout.data_start_off;
+
+	sys_fe = ocfs_allocate_file_entry ();
+	if (sys_fe == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto bail;
+	}
+
+	if ((buf = ocfs_malloc (OCFS_MAX_FILENAME_LENGTH)) == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto bail;
+	}
+
+	/*  Create Files in root for directory, file node allocations */
+	/*  Create the dir alloc file now that we have a internal */
+	for (i = 0; i < OCFS_MAXIMUM_NODES; i++) {
+		ocfs_init_system_file (osb, OCFS_FILE_VOL_META_DATA + i, buf, sys_fe);
+		ocfs_init_system_file (osb, OCFS_FILE_VOL_LOG_FILE + i, buf, sys_fe);
+		ocfs_init_system_file (osb, OCFS_FILE_DIR_ALLOC + i, buf, sys_fe);
+		ocfs_init_system_file (osb, OCFS_FILE_DIR_ALLOC_BITMAP + i, buf, sys_fe);
+		ocfs_init_system_file (osb, OCFS_FILE_FILE_ALLOC + i, buf, sys_fe);
+		ocfs_init_system_file (osb, OCFS_FILE_FILE_ALLOC_BITMAP + i, buf, sys_fe);
+		ocfs_init_system_file (osb, LOG_FILE_BASE_ID + i, buf, sys_fe);
+		ocfs_init_system_file (osb, CLEANUP_FILE_BASE_ID + i, buf, sys_fe);
+#ifdef LOCAL_ALLOC
+		ocfs_init_system_file (osb, OCFS_VOL_BITMAP_FILE + (2*i), buf, sys_fe);
+#endif 
+	}
+
+	status = ocfs_alloc_node_block (osb, osb->vol_layout.dir_node_size,
+				 &bitmapOffset, &fileOffset,
+				 &numClustersAlloc, osb->node_num,
+				 DISK_ALLOC_DIR_NODE);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status = -EFAIL);
+		goto bail;
+	}
+
+	osb->vol_layout.root_start_off = bitmapOffset;
+
+	ocfs_initialize_dir_node (osb, NewDirNode, bitmapOffset, fileOffset,
+				  osb->node_num);
+	NewDirNode->dir_node_flags |= DIR_NODE_FLAG_ROOT;
+
+	status = ocfs_write_dir_node (osb, NewDirNode, -1);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto bail;
+	}
+
+	/*  Read the first sector bytes from the target device */
+	size = osb->sect_size;
+	status = ocfs_read_disk_ex (osb, (void **) &volDiskHdr, size, size, 0);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto bail;
+	}
+
+	volDiskHdr->root_off = osb->vol_layout.root_start_off;
+	volDiskHdr->internal_off = osb->vol_layout.root_int_off;
+
+	osb->blk_zero_write = true;
+	status = ocfs_write_disk (osb, (__s8 *) volDiskHdr, size, 0);
+	osb->blk_zero_write = false;
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto bail;
+	}
+
+      bail:
+	if (status < 0) {
+		LOG_ERROR_STR ("Disabling Volume");
+		osb->vol_state = VOLUME_DISABLED;
+	}
+
+	/*  Release Volume Lock */
+	if (lock_acq) {
+		tempstat = ocfs_release_lock (osb, OCFS_VOLUME_LOCK_OFFSET,
+				OCFS_DLM_EXCLUSIVE_LOCK, 0, LockResource, fe);
+		if (tempstat < 0) {
+			LOG_ERROR_STATUS (tempstat);
+			osb->vol_state = VOLUME_DISABLED;
+		}
+	}
+	ocfs_release_dirnode (NewDirNode);
+	ocfs_safefree (volDiskHdr);
+	ocfs_safefree (buf);
+	ocfs_release_file_entry (sys_fe);
+	ocfs_release_file_entry (fe);
+	ocfs_put_lockres (LockResource);
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_create_root_dir_node */
+
+/* ocfs_create_root_oin()
+ *
+ */
+int ocfs_create_root_oin (ocfs_super * osb)
+{
+	int status = 0;
+	int tmpstat;
+	__u64 allocSize = 0;
+	__u64 endofFile = 0;
+	ocfs_inode *oin = NULL;
+	ocfs_vol_disk_hdr *volDiskHdr = NULL;
+	ocfs_lock_res *LockResource = NULL;
+	bool vol_locked = false;
+	ocfs_file_entry *fe = NULL;
+
+	LOG_ENTRY ();
+
+	fe = ocfs_allocate_file_entry ();
+	if (fe == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto finally;
+	}
+
+	if (osb->vol_layout.root_start_off == 0) {
+		status = ocfs_wait_for_disk_lock_release (osb, OCFS_VOLUME_LOCK_OFFSET,
+						 10000, OCFS_DLM_NO_LOCK);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+
+		status = ocfs_acquire_lock (osb, OCFS_VOLUME_LOCK_OFFSET,
+				     OCFS_DLM_EXCLUSIVE_LOCK, FLAG_FILE_CREATE,
+				     &LockResource, fe);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		} else
+			vol_locked = true;
+
+		status = ocfs_read_disk_ex (osb, (void **) &volDiskHdr,
+					OCFS_SECTOR_SIZE, OCFS_SECTOR_SIZE, 0);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+
+		if (vol_locked) {
+			status = ocfs_release_lock (osb, OCFS_VOLUME_LOCK_OFFSET,
+						    OCFS_DLM_EXCLUSIVE_LOCK, 0,
+						    LockResource, fe);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				osb->vol_state = VOLUME_DISABLED;
+			}
+			vol_locked = false;
+		}
+
+		if (volDiskHdr->root_off != 0) {
+//			ocfs_sleep (3000);
+			ocfs_wait_for_disk_lock_release (osb,
+							OCFS_VOLUME_LOCK_OFFSET,
+							30000, OCFS_DLM_NO_LOCK);
+			osb->vol_layout.root_start_off = volDiskHdr->root_off;
+			osb->vol_layout.root_int_off = volDiskHdr->internal_off;
+		}
+
+		status = ocfs_create_root_dir_node (osb);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+		/*  if it fails, Release the memory for the OFile we allocated above */
+	} else {
+		status = ocfs_create_meta_log_files (osb);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+	}
+
+	/* Create the root directory oin. This is done either here or in */
+	/* FindNewoin's if it fails, Release the memory for the OFile we */
+	/* allocated above */
+	status = ocfs_create_new_oin (&oin, &allocSize, &endofFile, NULL, osb);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	/*  This is for root . */
+	status = ocfs_initialize_oin (oin, osb,
+			   OCFS_OIN_DIRECTORY | OCFS_OIN_ROOT_DIRECTORY, NULL,
+			   0, osb->vol_layout.root_start_off);
+	if (status < 0) {
+		if (status != -EINTR)
+			LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	// oin->Parentoin = NULL; /*  Root has no parent */
+
+	/*  Set the Rootdirectories root Dir Node */
+
+	osb->oin_root_dir = oin;
+
+	oin->dir_disk_off = osb->vol_layout.root_start_off;
+
+      finally:
+	if (status < 0 && oin)
+		ocfs_release_oin (oin, true);
+
+	if (vol_locked) {
+		tmpstat = ocfs_release_lock (osb, OCFS_VOLUME_LOCK_OFFSET,
+					     OCFS_DLM_EXCLUSIVE_LOCK, 0,
+					     LockResource, fe);
+		if (tmpstat < 0) {
+			LOG_ERROR_STATUS (tmpstat);
+			osb->vol_state = VOLUME_DISABLED;
+		}
+	}
+
+	ocfs_safefree (volDiskHdr);
+	ocfs_release_file_entry (fe);
+	ocfs_put_lockres (LockResource);
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_create_root_oin */
+
+
+
+/*
+ * ocfs_delete_all_extent_maps()
+ *
+ */
+void ocfs_delete_all_extent_maps (ocfs_inode * oin)
+{
+	__u32 RunsInExtentMap = 0, ExtentMapIndex, ByteCount = 0;
+	__s64 Vbo;
+	__s64 Lbo;
+
+	LOG_ENTRY ();
+
+	RunsInExtentMap = ocfs_extent_map_get_count (&oin->map);
+
+	for (ExtentMapIndex = 0; ExtentMapIndex < RunsInExtentMap;
+	     ExtentMapIndex++) {
+		if (ocfs_get_next_extent_map_entry
+		    (oin->osb, &oin->map, ExtentMapIndex, &Vbo, &Lbo,
+		     &ByteCount)) {
+			ocfs_remove_extent_map_entry (oin->osb, &oin->map, Vbo,
+						  ByteCount);
+		}
+	}
+
+	LOG_EXIT ();
+	return;
+}				/* ocfs_delete_all_extent_maps */
+
+
+#ifndef USERSPACE_TOOL
+/*
+ * ocfs_release_oin()
+ *
+ */
+void ocfs_release_oin (ocfs_inode * oin, bool FreeMemory)
+{
+	ocfs_lock_res *lockres = NULL;
+	ocfs_super *osb = NULL;
+	struct inode *inode;
+
+	LOG_ENTRY_ARGS ("oin = %p, free = %s\n", oin, FreeMemory? "yes" : "no");
+
+	if (!oin || !oin->osb)
+		goto bail;
+
+	osb = oin->osb;
+
+	lockres = oin->lock_res;
+
+	if (lockres != NULL) {
+		ocfs_get_lockres (lockres);
+		ocfs_acquire_lockres (lockres);
+		if (lockres->oin == oin)
+			lockres->oin = NULL;
+		ocfs_release_lockres (lockres);
+	}
+
+	inode = (struct inode *) oin->inode;
+
+	if (inode) {
+		__u64 savedOffset = oin->file_disk_off;
+
+		SET_INODE_OIN (inode, NULL);
+		SET_INODE_OFFSET (inode, savedOffset);
+		LOG_TRACE_ARGS ("inode oin cleared / flags: %d / offset: %u.%u\n",
+			inode->i_flags, savedOffset);
+	}
+
+	ocfs_extent_map_destroy (&oin->map);
+
+	/*  Delete the ocfs_sem objects */
+	if (oin->oin_flags & OCFS_INITIALIZED_MAIN_RESOURCE) {
+		ocfs_del_sem (&(oin->main_res));
+		OCFS_CLEAR_FLAG (oin->oin_flags, OCFS_INITIALIZED_MAIN_RESOURCE);
+	}
+	if (oin->oin_flags & OCFS_INITIALIZED_PAGING_IO_RESOURCE) {
+		ocfs_del_sem (&(oin->paging_io_res));
+		OCFS_CLEAR_FLAG (oin->oin_flags,
+			       OCFS_INITIALIZED_PAGING_IO_RESOURCE);
+	}
+
+	if (FreeMemory) {
+#ifdef OCFS_MEM_DBG
+		ocfs_dbg_slab_free (OcfsGlobalCtxt.oin_cache, oin);
+#else
+		kmem_cache_free (OcfsGlobalCtxt.oin_cache, oin);
+#endif
+		oin = NULL;
+		ocfs_put_lockres (lockres);
+	}
+
+	ocfs_put_lockres (lockres);
+bail:
+	LOG_EXIT ();
+	return;
+}				/* ocfs_release_oin */
+#endif /* !USERSPACE_TOOL */
+
+/*
+ * ocfs_initialize_osb()
+ *
+ */
+int ocfs_initialize_osb (ocfs_super * osb, ocfs_vol_disk_hdr * vdh,
+			 ocfs_vol_label * vol_label, __u32 sect_size)
+{
+	int status = 0;
+	ocfs_publish *publish = NULL;
+	__u32 bitmap_len, length;
+	void *bitmap_buf, *buffer = NULL;
+	__u64 offset;
+	ocfs_vol_layout *vol_layout;
+
+	LOG_ENTRY ();
+
+	if (osb == NULL) {
+		LOG_ERROR_STATUS(status = -EFAIL);
+		goto finally;
+	}
+
+	OCFS_CLEAR_FLAG (osb->osb_flags, OCFS_OSB_FLAGS_SHUTDOWN);
+
+	vol_layout = &(osb->vol_layout);
+
+	vol_layout->cluster_size = (__u32) (vdh->cluster_size);
+	osb->obj_id.type = OCFS_TYPE_OSB;
+	osb->obj_id.size = sizeof (ocfs_super);
+
+	snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u",
+		 MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev));
+
+#ifdef __LP64__
+#define HASHBITS	11
+#else
+#define HASHBITS	12
+#endif
+	if (!ocfs_hash_create (&(osb->root_sect_node), HASHBITS)) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto bail;
+	}
+
+	ocfs_init_sem (&(osb->osb_res));
+	ocfs_init_sem (&(osb->map_lock));
+	ocfs_init_sem (&(osb->log_lock));
+	ocfs_init_sem (&(osb->recovery_lock));
+#ifdef PARANOID_LOCKS
+	ocfs_init_sem (&(osb->dir_alloc_lock));
+	ocfs_init_sem (&(osb->file_alloc_lock));
+#endif
+	ocfs_init_sem (&(osb->vol_alloc_lock));
+
+	init_MUTEX (&(osb->cfg_lock));
+	init_MUTEX (&(osb->comm_lock));
+	init_MUTEX (&(osb->trans_lock));
+
+	osb->node_recovering = OCFS_INVALID_NODE_NUM;
+
+	osb->needs_flush = false;
+	osb->commit_cache_exec = false;
+	osb->log_disk_off = 0;
+	osb->log_meta_disk_off = 0;
+	osb->trans_in_progress = false;
+
+	osb->last_disk_seq = ULONGLONG_MAX;
+
+	init_MUTEX (&(osb->publish_lock));
+	atomic_set (&osb->node_req_vote, 0);
+
+	init_waitqueue_head (&osb->nm_init_event);
+	atomic_set (&osb->nm_init, 0);
+
+	ocfs_extent_map_init (&osb->metadata_map);
+	ocfs_extent_map_init (&osb->trans_map);
+
+	INIT_LIST_HEAD (&(osb->cache_lock_list));
+	osb->sect_size = sect_size;
+	osb->oin_root_dir = NULL;
+	osb->node_num = OCFS_INVALID_NODE_NUM;
+
+	memcpy (vol_layout->mount_point, vdh->mount_point, strlen (vdh->mount_point));
+	vol_layout->serial_num = vdh->serial_num;
+	vol_layout->size = (__u64) (vdh->device_size);
+	vol_layout->start_off = vdh->start_off;
+	vol_layout->bitmap_off = (__u64) vdh->bitmap_off;
+	vol_layout->publ_sect_off = vdh->publ_off;
+	vol_layout->vote_sect_off = vdh->vote_off;
+	vol_layout->root_bitmap_off = vdh->root_bitmap_off;
+	vol_layout->root_start_off = vdh->root_off;
+	vol_layout->root_int_off = vdh->internal_off;
+	vol_layout->root_size = vdh->root_size;
+	vol_layout->cluster_size = (__u32) vdh->cluster_size;
+	vol_layout->num_nodes = (__u32) vdh->num_nodes;
+	vol_layout->data_start_off = vdh->data_start_off;
+	vol_layout->root_bitmap_size = vdh->root_bitmap_size;
+	vol_layout->num_clusters = vdh->num_clusters;
+	vol_layout->dir_node_size = vdh->dir_node_size;
+	vol_layout->file_node_size = vdh->file_node_size;
+	vol_layout->node_cfg_off = vdh->node_cfg_off;
+	vol_layout->node_cfg_size = vdh->node_cfg_size;
+	vol_layout->new_cfg_off = vdh->new_cfg_off;
+	vol_layout->prot_bits = vdh->prot_bits;
+	vol_layout->uid = vdh->uid;
+	vol_layout->gid = vdh->gid;
+
+	memcpy (vol_layout->vol_id, vol_label->vol_id, MAX_VOL_ID_LENGTH);
+
+	if (vol_layout->dir_node_size == 0) 
+		vol_layout->dir_node_size = OCFS_DEFAULT_DIR_NODE_SIZE;
+
+	if (vol_layout->file_node_size == 0) 
+		vol_layout->file_node_size = OCFS_DEFAULT_FILE_NODE_SIZE;
+
+	osb->max_dir_node_ent =
+		    (__u32) (vol_layout->dir_node_size / sect_size) - 2;
+	bitmap_len = (__u32) vol_layout->num_clusters;
+
+	/* In the start one sector is for Volume header and second sector */
+	/* is for Global sequence Number and Directoy Entry. */
+	{
+		__u32 sz = OCFS_ALIGN ((bitmap_len + 7) / 8, OCFS_PAGE_SIZE);
+
+		if ((bitmap_buf = vmalloc (sz)) == NULL) {
+			LOG_ERROR_STR ("vmalloc failed");
+			status = -ENOMEM;
+			goto finally;
+		}
+	}
+
+	ocfs_initialize_bitmap (&osb->cluster_bitmap, (__u32 *) bitmap_buf,
+				bitmap_len);
+
+	osb->prealloc_lock = 0;
+	osb->data_prealloc = ocfs_malloc (IORUN_ALLOC_SIZE);
+	if (!osb->data_prealloc) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto bail;
+	}
+
+	osb->md_prealloc = ocfs_malloc (IORUN_ALLOC_SIZE);
+	if (!osb->md_prealloc) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto bail;
+	}
+
+	osb->cfg_len = (OCFS_MAXIMUM_NODES +
+			OCFS_VOLCFG_NEWCFG_SECTORS) * sect_size;
+	osb->cfg_prealloc = ocfs_malloc (osb->cfg_len);
+	if (!osb->cfg_prealloc) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto bail;
+	}
+
+	osb->log_prealloc = ocfs_malloc (OCFS_ALIGN(sizeof(ocfs_cleanup_record),
+						    OCFS_PAGE_SIZE));
+	if (!osb->log_prealloc) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto bail;
+	}
+
+	status = ocfs_get_config (osb);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	/* Read the Publish Sector of local Node */
+	offset = vol_layout->publ_sect_off + (osb->node_num * osb->sect_size);
+	status = ocfs_read_force_disk_ex (osb, (void **)&publish, osb->sect_size,
+					  osb->sect_size, offset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	/*  Zero out the time stamp to write a new value */
+	publish->time = 0;
+	OcfsQuerySystemTime (&publish->time);
+
+	status = ocfs_write_disk (osb, publish, osb->sect_size, offset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	/*  Read disk for all Publish Sectors  */
+	length = OCFS_MAXIMUM_NODES * osb->sect_size;
+	status = ocfs_read_force_disk_ex (osb, (void **)&buffer, length, length,
+					  vol_layout->publ_sect_off);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	ocfs_update_publish_map (osb, (__u8 *) buffer, true);
+
+	/* We might need to add a variable in Global List of osb to */
+	/* delay any creation, if any other node is already creating a file */
+
+	/*  Link this osb onto the global linked list of all osb structures. */
+	/*  The Global Link List is mainted for the whole driver . */
+	ocfs_down_sem (&(OcfsGlobalCtxt.res), true);
+	list_add_tail (&(osb->osb_next), &(OcfsGlobalCtxt.osb_next));
+	ocfs_up_sem (&(OcfsGlobalCtxt.res));
+
+	/*  Mark the fact that this osb structure is initialized. */
+	OCFS_SET_FLAG (osb->osb_flags, OCFS_OSB_FLAGS_OSB_INITIALIZED);
+
+	/* skip the frees which happen on error only */
+	goto finally;
+
+      bail:
+	if (osb->root_sect_node.buckets)
+		ocfs_hash_destroy (&(osb->root_sect_node), NULL);
+	ocfs_safefree (osb->data_prealloc);
+	ocfs_safefree (osb->md_prealloc);
+	ocfs_safefree (osb->log_prealloc);
+	ocfs_safefree (osb->cfg_prealloc);
+
+      finally:
+	ocfs_safefree (publish);
+	ocfs_safefree (buffer);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_initialize_osb */
+
+/*
+ * ocfs_verify_volume()
+ *
+ */
+int ocfs_verify_volume (ocfs_vol_disk_hdr * vdh)
+{
+	int status = 0;
+
+	LOG_ENTRY ();
+
+	if (vdh == NULL) {
+		LOG_ERROR_STATUS (status = -EFAIL);
+		goto bail;
+	}
+
+	/*  Compare the Signature with the one we read from disk  */
+	if (memcmp (vdh->signature, OCFS_VOLUME_SIGNATURE,
+		    strlen (OCFS_VOLUME_SIGNATURE)) != 0) {
+		LOG_ERROR_STR ("Invalid volume signature");
+		status = -EINVAL;
+		goto bail;
+	}
+
+	/*  Check the Volume Length and the ClusterSize.  */
+	if (vdh->device_size == 0) {
+		LOG_ERROR_STR ("Device size cannot be zero");
+		status = -EINVAL;
+		goto bail;
+	}
+
+	if (vdh->cluster_size == 0) {
+		LOG_ERROR_STR ("Cluster size cannot be zero");
+		status = -EINVAL;
+		goto bail;
+	}
+
+	if (vdh->major_version != OCFS_MAJOR_VERSION) {
+		LOG_ERROR_ARGS ("Version number not compatible: %u.%u",
+				vdh->major_version, vdh->minor_version);
+		status = -EINVAL;
+		goto bail;
+	}
+
+	/*  Verify if mount point and volume size are valid */
+	/*  Read the root directory and make sure it is valid */
+	/*  Check to see who else is alive. */
+	/*  Kick in the NM i/f to start writing time stamps to the disk */
+
+      bail:
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_verify_volume */
+
+/*
+ * ocfs_vol_member_reconfig()
+ *
+ */
+int ocfs_vol_member_reconfig (ocfs_super * osb)
+{
+	int status = 0;
+
+	LOG_ENTRY ();
+
+	/* Start out with the highest multiple.... */
+	osb->hbm = DISK_HBEAT_COMM_ON;
+
+	/* Trigger the NM on this node to init the VolMap based on the info */
+	/* on the disk currently and advertise to other nodes our existance. */
+	ocfs_nm_heart_beat (osb, HEARTBEAT_METHOD_DISK, true);
+
+	/* Send a mesg to force the nm on all other nodes to process this */
+	/* volume, this should allow for them to detect our existance. */
+//    ocfs_nm_heart_beat(osb, HEARTBEAT_METHOD_IPC, 0);
+
+	osb->publ_map |= (1 << osb->node_num);
+
+	/* Create the Rootdirectory oin. */
+	osb->vol_state = VOLUME_INIT;
+
+	status = ocfs_create_root_oin (osb);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+	osb->vol_state = VOLUME_ENABLED;
+
+      finally:
+
+	LOG_EXIT_STATUS (status);
+	return (status);
+}				/* ocfs_vol_member_reconfig */
+
+/*
+ * ocfs_check_volume()
+ *
+ */
+int ocfs_check_volume (ocfs_super * osb)
+{
+	int status = 0;
+	__u64 offset = 0;
+	__u8 *buffer = NULL;
+	ocfs_publish *publish;
+
+	LOG_ENTRY ();
+
+	/* Read the node's publish sector */
+	offset = osb->vol_layout.publ_sect_off +
+		      (osb->node_num * osb->sect_size);
+	status = ocfs_read_force_disk_ex (osb, (void **)&buffer, osb->sect_size,
+					  osb->sect_size, offset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	publish = (ocfs_publish *) buffer;
+
+	if (publish->dirty) {
+		ocfs_down_sem (&(osb->osb_res), true);
+		status = ocfs_recover_vol (osb, osb->node_num);
+		ocfs_up_sem (&(osb->osb_res));
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+	}
+
+      finally:
+	ocfs_safefree (buffer);
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_check_volume */
+
+
+/*
+ * ocfs_delete_osb()
+ *
+ * The routine gets called from dismount or close whenever a dismount on 
+ * volume is requested and the osb open count becomes 1.
+ * It will remove the osb from the global list and also free up all the
+ * initialized resources and fileobject.
+ */
+void ocfs_delete_osb (ocfs_super * osb)
+{
+	struct list_head null_list;
+
+	LOG_ENTRY ();
+
+	if (!osb)
+		goto finito;
+
+	memset (&null_list, 0, sizeof(struct list_head));
+	ocfs_down_sem (&(OcfsGlobalCtxt.res), true);
+	if (memcmp (&osb->osb_next, &null_list, sizeof(struct list_head)))
+		list_del (&(osb->osb_next));
+	ocfs_up_sem (&(OcfsGlobalCtxt.res));
+
+	ocfs_del_sem (&(osb->osb_res));
+	ocfs_del_sem (&(osb->log_lock));
+	ocfs_del_sem (&(osb->recovery_lock));
+	ocfs_del_sem (&(osb->map_lock));
+	ocfs_extent_map_destroy (&osb->metadata_map);
+	ocfs_extent_map_destroy (&osb->trans_map);
+	ocfs_safefree(osb->data_prealloc);
+	ocfs_safefree(osb->md_prealloc);
+	ocfs_safefree(osb->cfg_prealloc);
+	ocfs_safefree(osb->log_prealloc);
+	memset (osb, 0, sizeof (ocfs_super));
+
+finito:
+	LOG_EXIT ();
+	return;
+}				/* ocfs_delete_osb */
+
+/*
+ * ocfs_commit_cache()
+ *
+ */
+int ocfs_commit_cache (ocfs_super * osb, bool Flag)
+{
+	int status = 0;
+
+	LOG_ENTRY ();
+
+	ocfs_flush_cache (osb);
+
+	ocfs_down_sem (&(osb->map_lock), true);
+
+	status = ocfs_write_map_file (osb);
+	if (status >= 0) {
+		status = ocfs_process_log_file (osb, Flag);
+		if (status < 0)
+			LOG_ERROR_STATUS (status);
+
+		status = ocfs_extend_system_file (osb,
+				(OCFS_FILE_VOL_LOG_FILE + osb->node_num),
+				0, NULL);
+		if (status < 0)
+			LOG_ERROR_STATUS (status);
+
+		osb->log_file_size = 0;
+
+		status = ocfs_extend_system_file (osb,
+				(OCFS_FILE_VOL_META_DATA + osb->node_num),
+				0, NULL);
+		if (status < 0)
+			LOG_ERROR_STATUS (status);
+
+		ocfs_extent_map_destroy (&osb->metadata_map);
+		ocfs_extent_map_destroy (&osb->trans_map);
+		ocfs_extent_map_init (&osb->metadata_map);
+		ocfs_extent_map_init (&osb->trans_map);
+	}
+
+	ocfs_up_sem (&(osb->map_lock));
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_commit_cache */

Added: trunk/libocfs/Common/ocfsgennm.c
===================================================================
--- trunk/libocfs/Common/ocfsgennm.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/ocfsgennm.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,876 @@
+/*
+ * ocfsgennm.c
+ *
+ * process vote, nm thread, etc.
+ *
+ * Copyright (C) 2002, 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifdef __KERNEL__
+#include <ocfs.h>
+struct inode * ocfs_get_inode_from_offset(ocfs_super * osb, __u64 fileoff);
+#else
+#include <libocfs.h>
+#endif
+
+
+/* Tracing */
+#define OCFS_DEBUG_CONTEXT      OCFS_DEBUG_CONTEXT_NM
+
+
+/*
+ * ocfs_flush_data()
+ * 
+ */
+int ocfs_flush_data (ocfs_inode * oin)
+{
+	int status = 0;
+
+	LOG_ENTRY ();
+
+	OCFS_ASSERT(IS_VALID_OIN(oin));
+
+	if (oin->oin_flags & OCFS_OIN_DIRECTORY)
+		goto bail;
+
+	ocfs_down_sem (&(oin->main_res), true);
+
+	oin->cache_enabled = false;
+	ocfs_flush_cache (oin->osb);
+
+	/* Grab and release PagingIo to serialize ourselves with the lazy writer. */
+	/* This will work to ensure that all IO has completed on the cached */
+	/* data and we will succesfully tear away the cache section. */
+	ocfs_down_sem (&(oin->paging_io_res), true);
+	ocfs_up_sem (&(oin->paging_io_res));
+
+	ocfs_purge_cache_section (oin, NULL, 0);
+
+	ocfs_up_sem (&(oin->main_res));
+
+      bail:
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_flush_data */
+
+/*
+ * ocfs_disk_update_resource()
+ *
+ * @osb: ocfs super block for the volume
+ * @lock_res: lockres to be updated
+ * @file_ent: corresponding file entry
+ *
+ * Updates the in memory lock resource from the disklock info
+ * stored in the file entry on disk.
+ *
+ * Returns 0 if success, < 0 if error.
+ */
+int ocfs_disk_update_resource (ocfs_super * osb, ocfs_lock_res * lock_res,
+			       ocfs_file_entry * file_ent, __u32 timeout)
+{
+	int status = 0;
+	ocfs_file_entry *fe = NULL;
+
+	LOG_ENTRY_ARGS ("(0x%p, 0x%p, 0x%p)\n", osb, lock_res,
+			file_ent);
+
+	if (file_ent) {
+		fe = file_ent;
+		status = ocfs_read_file_entry (osb, fe, lock_res->sector_num);
+	} else
+		status = ocfs_get_file_entry (osb, &fe, lock_res->sector_num);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	status = ocfs_acquire_lockres_ex (lock_res, timeout);
+	if (status < 0) {
+		LOG_TRACE_ARGS ("Timedout locking lockres for id: %u.%u\n",
+			HI(lock_res->sector_num), LO(lock_res->sector_num));
+		goto finally;
+	}
+
+	lock_res->lock_type = DISK_LOCK_FILE_LOCK (fe);
+	lock_res->master_node_num = DISK_LOCK_CURRENT_MASTER (fe);
+	lock_res->oin_openmap = DISK_LOCK_OIN_MAP (fe);
+
+	ocfs_release_lockres (lock_res);
+
+      finally:
+	if (file_ent == NULL)
+		ocfs_release_file_entry (fe);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_disk_update_resource */
+
+
+int ocfs_check_for_stale_lock(ocfs_super *osb, ocfs_lock_res *lockres, ocfs_file_entry *fe, __u64 lock_id)
+{
+	int status = 0;
+	ocfs_file_entry *tmpfe = NULL;
+
+	LOG_ENTRY_ARGS ("(0x%p, 0x%p, 0x%p, %u.%u)\n", osb, lockres, fe,
+		       	HILO(lock_id));
+
+	if (fe == NULL) {
+		tmpfe = ocfs_allocate_file_entry ();
+		if (tmpfe == NULL) {
+			LOG_ERROR_STATUS (status == -ENOMEM);
+			goto bail;
+		}
+		status = ocfs_read_force_disk (osb, tmpfe, osb->sect_size, lock_id);
+		if (status < 0) {
+			LOG_ERROR_STATUS(status);
+			goto bail;
+		}
+		fe = tmpfe;
+	}
+
+	/* should NEVER see am EXCLUSIVE on disk when creating lockres */
+	/* indicates that a lock was held when the node died */
+	if (lockres->lock_type == OCFS_DLM_EXCLUSIVE_LOCK &&
+	    lockres->master_node_num == osb->node_num) {
+		LOG_TRACE_ARGS("stale lock found! lockid=%u.%u\n", HILO(lock_id));
+		lockres->lock_type = OCFS_DLM_NO_LOCK;
+		DISK_LOCK_FILE_LOCK (fe) = OCFS_DLM_NO_LOCK;
+		status = ocfs_write_force_disk (osb, fe, osb->sect_size, lock_id);
+		if (status < 0) {
+			LOG_ERROR_ARGS("error updating stale lockid=%u.%u\n",
+				       HILO(lock_id));
+		}
+	}
+
+bail:
+	if (tmpfe)
+		ocfs_release_file_entry(tmpfe);
+
+	LOG_EXIT_STATUS(status);
+	return status;
+}
+
+/*
+ * ocfs_find_update_res()
+ *
+ * @osb: ocfs super block for the volume
+ * @lock_id: sector number of the resource to be locked
+ * @lockres: lockres of the resource
+ * @fe: corresponding file entry
+ * @updated: set to 1 if lockres is refreshed from disk
+ *
+ * Searches for the lockres for the given lockid in the hashtable.
+ * If not found, it allocates a lockres for the lockid, and adds
+ * it to the hashtable. If found and it's master node is not the
+ * same as the current node, the lockres is refreshed from the disk.
+ *
+ * Returns 0 if success, < 0 if error.
+ */
+int ocfs_find_update_res (ocfs_super * osb, __u64 lock_id,
+			  ocfs_lock_res ** lockres, ocfs_file_entry * fe,
+			  __u32 * updated, __u32 timeout)
+{
+	int status = 0;
+	ocfs_lock_res *tmp_lockres = NULL;
+
+	LOG_ENTRY_ARGS ("(0x%p, %u.%u, 0x%p, 0x%p, 0x%p)\n", osb,
+			HI (lock_id), LO (lock_id), lockres, fe,
+			updated);
+
+	status = ocfs_lookup_sector_node (osb, lock_id, lockres);
+	if (status < 0) {
+		*lockres = ocfs_allocate_lockres();
+		if (*lockres == NULL) {
+			LOG_ERROR_STATUS (status = -ENOMEM);
+			goto finally;
+		}
+
+		ocfs_init_lockres (osb, *lockres, lock_id);
+
+		ocfs_get_lockres (*lockres);
+
+		status = ocfs_disk_update_resource (osb, *lockres, fe,
+						    timeout);
+		if (status < 0) {
+			if (status != -ETIMEDOUT) {
+				LOG_ERROR_STR ("Disabling Volume");
+				osb->vol_state = VOLUME_DISABLED;
+			}
+			goto finally;
+		}
+
+		if (lock_id != (*lockres)->sector_num) {
+			LOG_ERROR_ARGS ("lockid=%u.%u != secnum=%u.%u\n",
+					HILO(lock_id),
+					HILO((*lockres)->sector_num));
+			status = -EFAIL;
+			goto finally;
+		}
+
+		status = ocfs_check_for_stale_lock(osb, *lockres, fe, lock_id);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+		
+		if (updated)
+			*updated = 1;
+
+		status = ocfs_insert_sector_node (osb, *lockres, &tmp_lockres);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+
+		if (!tmp_lockres)
+			goto finally;
+		else {
+			ocfs_put_lockres (*lockres);
+			*lockres = tmp_lockres;
+		}
+	}
+
+	if (lock_id != (*lockres)->sector_num) {
+		LOG_ERROR_ARGS ("lockid=%u.%u != secnum=%u.%u",
+				HILO(lock_id),
+				HILO((*lockres)->sector_num));
+		status = -EFAIL;
+		goto finally;
+	}
+
+	if ((*lockres)->master_node_num != osb->node_num) {
+		status = ocfs_disk_update_resource (osb, *lockres, fe, timeout);
+		if (status < 0) {
+			if (status != -ETIMEDOUT) {
+				LOG_ERROR_STR ("Disabling Volume");
+				osb->vol_state = VOLUME_DISABLED;
+			}
+			goto finally;
+		}
+		if (updated)
+			*updated = 1;
+	}
+
+      finally:
+	if (status < 0)
+		*lockres = NULL;
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_find_update_res */
+
+#undef OCFS_DEBUG_CONTEXT
+#define OCFS_DEBUG_CONTEXT      OCFS_DEBUG_CONTEXT_DLM
+/*
+ * ocfs_vote_for_del_ren()
+ *
+ * @osb:
+ * @publish:
+ * @node_num: node asking for the vote
+ * @vote:
+ * @lockres:
+ *
+ */
+int ocfs_vote_for_del_ren (ocfs_super * osb, ocfs_publish * publish,
+			   __u32 node_num, ocfs_vote * vote,
+			   ocfs_lock_res ** lockres)
+{
+	int status = 0;
+	__u8 voted;
+
+	LOG_ENTRY ();
+
+	voted = vote->vote[node_num];
+
+	status = ocfs_common_del_ren (osb, publish->dir_ent, publish->vote_type,
+				node_num, publish->publ_seq_num, &voted, lockres);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto bail;
+	}
+
+	vote->vote[node_num] = voted;
+
+bail:
+	LOG_EXIT_STATUS (status);
+	return (status);
+}				/* ocfs_vote_for_del_ren */
+
+#ifndef USERSPACE_TOOL
+/*
+ * ocfs_get_inode_from_offset()
+ *
+ */
+struct inode * ocfs_get_inode_from_offset(ocfs_super * osb, __u64 fileoff)
+{
+        int status;
+        struct inode *inode = NULL;
+        ocfs_file_entry *fe;
+	ocfs_find_inode_args args;
+
+	LOG_ENTRY ();
+        
+	status = ocfs_get_file_entry (osb, &fe, fileoff);
+	if (status >= 0) {
+		args.offset = fe->this_sector;
+		args.entry = fe;
+		inode = iget4 (osb->sb, (__u32) LO (fileoff),
+			       (find_inode_t) ocfs_find_inode,
+			       (void *) (&args));
+                if (inode != NULL && is_bad_inode (inode)) {
+		        iput (inode);
+		        inode = NULL;
+                }
+		ocfs_release_file_entry (fe);
+		fe = NULL;
+	}
+
+	LOG_EXIT_PTR (inode);
+        return inode;
+}				/* ocfs_get_inode_from_offset */
+#endif
+
+/*
+ * ocfs_process_update_inode_request()
+ *
+ * @osb:
+ * @lock_id:
+ * @lockres:
+ * @node_num: node asking for the vote
+ *
+ * get an inode just long enough to dump its pages
+ */
+int ocfs_process_update_inode_request (ocfs_super * osb, __u64 lock_id,
+				       ocfs_lock_res * lockres, __u32 node_num)
+{
+	int status = 0;
+#ifndef USERSPACE_TOOL
+	struct inode *inode = NULL;
+#endif
+
+	LOG_ENTRY ();
+
+	if (lockres && lockres->oin) {
+		LOG_ERROR_STR ("should not be called if there exists an " \
+			       "oin for this inode!\n");
+		status = -EFAIL;
+		goto bail;
+	}
+
+#ifndef USERSPACE_TOOL
+	inode = ocfs_get_inode_from_offset(osb, lock_id);
+	if (inode) {
+		truncate_inode_pages (inode->i_mapping, 0);
+		iput (inode);
+		inode = NULL;
+	}
+#endif
+
+	if (lockres)
+		ocfs_remove_sector_node (osb, lockres);
+
+      bail:
+	LOG_EXIT ();
+	return status;
+}				/* ocfs_process_update_inode_request */
+
+
+/*
+ * ocfs_process_vote()
+ *
+ * @osb:
+ * @publish:
+ * @node_num: node asking for the vote
+ *
+ */
+int ocfs_process_vote (ocfs_super * osb, ocfs_publish * publish, __u32 node_num)
+{
+	int status = 0;
+	int tmpstat = 0;
+	ocfs_lock_res *lockres = NULL;
+	bool lockres_acq = false;
+	__u32 flags;
+	__u32 num_nodes;
+	__u32 i;
+	__u64 offset;
+	ocfs_file_entry *fe = NULL;
+	ocfs_vote *vote = NULL;
+	ocfs_inode *oin = NULL;
+
+	LOG_ENTRY_ARGS ("(0x%p, 0x%p, %u)\n", osb, publish, node_num);
+
+	LOG_TRACE_ARGS ("node=%u, id=%u.%u, seq=%u.%u\n", node_num,
+		HI(publish->dir_ent), LO(publish->dir_ent),
+		HI(publish->publ_seq_num), LO(publish->publ_seq_num));
+
+	num_nodes = OCFS_MAXIMUM_NODES;
+	flags = publish->vote_type;
+
+	offset = osb->vol_layout.vote_sect_off + (osb->node_num * osb->sect_size);
+	status = ocfs_read_force_disk_ex (osb, (void **)&vote, osb->sect_size,
+					  osb->sect_size, offset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finito;
+	}
+
+	/* Exclusive vote for */
+	status = ocfs_find_update_res (osb, publish->dir_ent, &lockres, NULL,
+				       NULL, (OCFS_NM_HEARTBEAT_TIME/2));
+	if (status < 0) {
+		if (status == -ETIMEDOUT)
+			goto finito;
+		if (flags & FLAG_FILE_UPDATE_OIN) {
+			status = ocfs_process_update_inode_request (osb,
+					publish->dir_ent, lockres, node_num);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto finito;
+			}
+			vote->dir_ent = publish->dir_ent;
+			vote->vote_seq_num = publish->publ_seq_num;
+			vote->vote[node_num] = FLAG_VOTE_OIN_UPDATED;
+		} else
+			LOG_ERROR_STATUS (status);
+		goto finito;
+	}
+
+	status = ocfs_acquire_lockres_ex (lockres, (OCFS_NM_HEARTBEAT_TIME/2));
+	if (status < 0) {
+		LOG_TRACE_ARGS ("Timedout locking lockres for id: %u.%u\n",
+			       	HILO (lockres->sector_num));
+		goto finally;
+	} else
+		lockres_acq = true;
+
+	/* Zero out the vote for everybody, if any already set and hung */
+	for (i = 0; i < num_nodes; i++)
+		vote->vote[i] = 0;
+
+	if ((flags & FLAG_FILE_DELETE) || (flags & FLAG_FILE_RENAME)) {
+		status = ocfs_vote_for_del_ren (osb, publish, node_num, vote,
+						&lockres);
+		if (status < 0)
+			LOG_ERROR_STATUS (status);
+		goto finito;
+	}
+
+	if (flags & FLAG_FILE_RELEASE_CACHE) {
+		ocfs_file_entry *tmp_fe = NULL;
+
+		if (!osb->commit_cache_exec) {
+			osb->needs_flush = true;
+			ocfs_trans_in_progress(osb);
+			if (osb->trans_in_progress == false) {
+				osb->commit_cache_exec = true;
+				ocfs_commit_cache (osb, true);
+				osb->needs_flush = false;
+				osb->commit_cache_exec = false;
+
+				if (lockres->oin != NULL) {
+					ocfs_flush_data (lockres->oin);
+					lockres->lock_type = OCFS_DLM_NO_LOCK;
+				}
+
+				status = ocfs_get_file_entry (osb, &tmp_fe,
+							      publish->dir_ent);
+				if (status < 0) {
+					LOG_ERROR_STATUS (status);
+					goto finito;
+				}
+
+				/* At this stage there is nothing in disk, so */
+				/* no need to update cache, as there is */
+				/* nothing there */
+				if (DISK_LOCK_FILE_LOCK (tmp_fe) > OCFS_DLM_NO_LOCK) {
+					__u64 tmp = publish->dir_ent;
+
+					DISK_LOCK_FILE_LOCK (tmp_fe) = OCFS_DLM_NO_LOCK;
+
+					status = ocfs_write_force_disk (osb, tmp_fe,
+									osb->sect_size, tmp);
+					if (status < 0) {
+						LOG_ERROR_STATUS (status);
+						goto finito;
+					}
+					lockres->lock_type = OCFS_DLM_NO_LOCK;
+				}
+				ocfs_release_file_entry (tmp_fe);
+				vote->vote[node_num] = FLAG_VOTE_NODE;
+			} else {
+				/* Ask for a retry as txn is in progress */
+				vote->vote[node_num] = FLAG_VOTE_UPDATE_RETRY;
+				vote->open_handle = false;
+			}
+			goto finito;
+		}
+	}
+
+	if (publish->vote_type & FLAG_FILE_UPDATE_OIN) {
+		oin = lockres->oin;
+		if (oin) {
+			OCFS_ASSERT(IS_VALID_OIN(oin));
+			ocfs_down_sem (&(oin->main_res), true);
+			oin->needs_verification = true;
+			tmpstat = ocfs_verify_update_oin(osb, oin);
+			if (tmpstat < 0)
+				LOG_ERROR_STATUS (tmpstat);
+			ocfs_up_sem (&(oin->main_res));
+
+			vote->dir_ent = publish->dir_ent;
+			vote->vote_seq_num = publish->publ_seq_num;
+			vote->vote[node_num] = FLAG_VOTE_OIN_UPDATED;
+		} else {
+			status = ocfs_process_update_inode_request (osb,
+					publish->dir_ent, lockres, node_num);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto finito;
+			}
+			vote->dir_ent = publish->dir_ent;
+			vote->vote_seq_num = publish->publ_seq_num;
+			vote->vote[node_num] = FLAG_VOTE_OIN_UPDATED;
+		}
+		goto finito;
+	}
+
+	if (lockres->master_node_num != OCFS_INVALID_NODE_NUM) {
+		if (lockres->master_node_num == osb->node_num) {
+			/* I am currently the master of the lock */
+			if (flags & FLAG_CHANGE_MASTER) {
+				osb->needs_flush = true;
+				ocfs_trans_in_progress(osb);
+				if (lockres->lock_type == OCFS_DLM_NO_LOCK) {
+					__u64 tmp = publish->dir_ent;
+
+					ocfs_commit_cache (osb, true);
+					lockres->master_node_num = node_num;
+					osb->needs_flush = false;
+
+					if (lockres->oin != NULL) {
+						ocfs_flush_data (lockres->oin);
+						lockres->lock_type = OCFS_DLM_NO_LOCK;
+					}
+
+					status = ocfs_get_file_entry (osb, &fe,
+								      publish->dir_ent);
+					if (status < 0) {
+						LOG_ERROR_STATUS (status);
+						goto finito;
+					}
+
+					if (lockres->oin)
+						DISK_LOCK_OIN_MAP (fe) |= (1 << osb->node_num);
+
+					DISK_LOCK_CURRENT_MASTER (fe) = node_num;
+
+					/* Write new master on the disk */
+					status = ocfs_write_disk (osb, fe, osb->sect_size, tmp);
+					if (status < 0) {
+						LOG_ERROR_STATUS (status);
+						goto finito;
+					}
+					lockres->master_node_num = node_num;
+					vote->vote[node_num] = FLAG_VOTE_NODE;
+				} else {
+					/* Ask for a retry as txn is in progress */
+					vote->vote[node_num] = FLAG_VOTE_UPDATE_RETRY;
+					vote->open_handle = false;
+				}
+			} else if (flags & FLAG_ADD_OIN_MAP) {
+				status = ocfs_get_file_entry (osb, &fe, publish->dir_ent);
+				if (status < 0) {
+					LOG_ERROR_STATUS (status);
+					goto finito;
+				}
+
+				if (fe->attribs & OCFS_ATTRIB_DIRECTORY) {
+					LOG_TRACE_STR("stale lock probe on directory!, respond but do nothing");
+					vote->vote[node_num] = FLAG_VOTE_NODE;	
+				} else if (IS_FE_DELETED(fe->sync_flags) ||
+					   (!(fe->sync_flags & OCFS_SYNC_FLAG_VALID))) {
+					vote->vote[node_num] = FLAG_VOTE_FILE_DEL;
+					vote->open_handle = false;
+				} else {
+					__u64 tmp = publish->dir_ent;
+
+					DISK_LOCK_OIN_MAP (fe) |= (1 << node_num);
+
+					/* Write new map on the disk */
+					status = ocfs_write_disk (osb, fe,
+							osb->sect_size, tmp);
+					if (status < 0) {
+						LOG_ERROR_STATUS (status);
+						goto finito;
+					}
+
+					/* Add this node to the oin map on the file entry */
+					lockres->oin_openmap = DISK_LOCK_OIN_MAP (fe);
+					vote->vote[node_num] = FLAG_VOTE_NODE;
+				}
+			}
+		} else {
+			/* I am not currently the master of the lock */
+			if (IS_NODE_ALIVE (osb->publ_map, lockres->master_node_num,
+					   OCFS_MAXIMUM_NODES)) {
+				 /* We have no business voting on this lock */
+				vote->vote[node_num] = FLAG_VOTE_UPDATE_RETRY;
+				vote->open_handle = false;
+			} else {
+				/* Master Node is dead and a vote is needed */
+				/* to create a new master */
+				vote->open_handle = false;
+				vote->vote[node_num] = FLAG_VOTE_NODE;
+
+				if ((!(flags & FLAG_DIR)) &&
+				    ((flags & FLAG_FILE_EXTEND) || (flags & FLAG_FILE_UPDATE))) {
+					if (lockres->oin)
+						vote->open_handle = true;
+				}
+			}
+		}
+	} else {
+		/* Vote for the node */
+		vote->vote[node_num] = FLAG_VOTE_NODE;
+		vote->open_handle = false;
+
+		if ((!(flags & FLAG_DIR)) &&
+		    ((flags & FLAG_FILE_EXTEND) || (flags & FLAG_FILE_UPDATE))) {
+			if (lockres->oin)
+				vote->open_handle = true;
+		}
+	}
+
+      finito:
+	vote->dir_ent = publish->dir_ent;
+	vote->vote_seq_num = publish->publ_seq_num;
+
+	if (status >= 0) {
+		offset = osb->vol_layout.vote_sect_off +
+			 (osb->node_num * osb->sect_size);
+		status = ocfs_write_disk (osb, vote, osb->sect_size, offset);
+		if (status < 0)
+			LOG_ERROR_STATUS (status);
+		else {
+			ocfs_compute_dlm_stats (0, vote->vote[node_num],
+					       	&(OcfsGlobalCtxt.dsk_reply_stats));
+			ocfs_compute_dlm_stats (0, vote->vote[node_num],
+					       	&(osb->dsk_reply_stats));
+			LOG_TRACE_ARGS ("disk reply id=%u.%u, seq=%u.%u, "
+				"node=%u, vote=0x%x, status=%d\n",
+				HILO(publish->dir_ent), HILO(publish->publ_seq_num),
+			       	node_num, vote->vote[node_num], status);
+		}
+	}
+
+finally:
+	ocfs_release_file_entry (fe);
+
+	ocfs_safefree (vote);
+
+	if (lockres && lockres_acq)
+		ocfs_release_lockres (lockres);
+
+	ocfs_put_lockres(lockres);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_process_vote */
+
+
+/*
+ * ocfs_common_del_ren()
+ *
+ */
+int ocfs_common_del_ren (ocfs_super * osb, __u64 lock_id, __u32 flags,
+			 __u32 node_num, __u64 seq_num, __u8 * vote,
+			 ocfs_lock_res ** lockres)
+{
+	int status = 0;
+	__u32 retry_cnt = 0;
+	bool acq_oin = false;
+	ocfs_file_entry *fe = NULL;
+	bool rls_oin = true;
+	ocfs_inode *oin = NULL;
+	ocfs_sem *oin_sem = NULL;
+
+	LOG_ENTRY ();
+
+	oin = (*lockres)->oin;
+	if (oin) {
+		ocfs_down_sem (&oin->main_res, true);
+		oin->needs_verification = true;
+		status = ocfs_verify_update_oin(osb, oin);
+		if (status < 0) {
+			if (status == -ENOENT) {
+				*vote = FLAG_VOTE_NODE;
+				status = 0;
+			} else
+				LOG_ERROR_STATUS (status);
+			ocfs_up_sem (&oin->main_res);
+			goto finally;
+		}
+		ocfs_up_sem (&oin->main_res);
+	}
+
+	/* Check for oin */
+	if (oin) {
+		oin_sem = &(oin->main_res);
+		ocfs_down_sem (oin_sem, true);
+		acq_oin = true;
+
+		/* If OIN_IN_USE is set we should go back and retry */
+		while ((oin->oin_flags & OCFS_OIN_IN_USE) && (retry_cnt < 5)) {
+			if (acq_oin) {
+				ocfs_up_sem (oin_sem);
+				acq_oin = false;
+			}
+
+			ocfs_sleep (20);
+			retry_cnt++;
+
+			if (!acq_oin) {
+				ocfs_down_sem (oin_sem, true);
+				acq_oin = true;
+			}
+		}
+
+/* The macro below takes into account the pre RELEASE/ACQUIRE_LOCK flag days */
+/* Allows for rolling upgrade */
+#define IS_RELEASE_LOCK(_f)	(((_f) & FLAG_FILE_RELEASE_LOCK) ||	\
+				 !((_f) & (FLAG_FILE_ACQUIRE_LOCK | FLAG_FILE_RELEASE_LOCK)))
+
+		if (((*lockres)->oin->open_hndl_cnt == 0) &&
+		    (!(oin->oin_flags & OCFS_OIN_IN_USE))) {
+			if (!(oin->oin_flags & OCFS_OIN_IN_TEARDOWN) &&
+			    IS_RELEASE_LOCK(flags)) {
+				if (acq_oin) {
+					ocfs_up_sem (oin_sem);
+					acq_oin = false;
+				}
+
+				rls_oin = false;
+
+				if (!acq_oin) {
+					ocfs_down_sem (oin_sem, true);
+					acq_oin = true;
+				}
+
+				OCFS_SET_FLAG (oin->oin_flags,
+					       OCFS_OIN_NEEDS_DELETION);
+
+				if (acq_oin) {
+					ocfs_up_sem (oin_sem);
+					acq_oin = false;
+				}
+
+				ocfs_release_lockres (*lockres);
+
+				if (oin && oin->inode) {
+					struct inode *inode = oin->inode;
+					inode->i_nlink = 0;
+					d_prune_aliases (inode);
+				}
+
+				if (rls_oin) {
+					ocfs_release_cached_oin (osb, oin);
+					ocfs_release_oin (oin, true);
+				} else {
+					ocfs_down_sem (&(oin->paging_io_res),
+						       true);
+					ocfs_purge_cache_section (oin, NULL, 0);
+					ocfs_up_sem (&(oin->paging_io_res));
+				}
+
+				if (oin && oin->inode) {
+#ifndef USERSPACE_TOOL
+					iput (oin->inode);
+#endif
+					oin->inode = NULL;
+				}
+				*lockres = NULL;
+			}
+			*vote = FLAG_VOTE_NODE;
+			goto finito;
+		} else {
+			*vote = FLAG_VOTE_OIN_ALREADY_INUSE;
+			goto finito;
+		}
+	} else {
+#ifndef USERSPACE_TOOL
+                struct inode *inode = NULL;
+                if (flags & FLAG_FILE_DELETE && IS_RELEASE_LOCK(flags)) {
+                        inode = ocfs_get_inode_from_offset(osb, lock_id);
+                        if (inode) {
+				inode->i_nlink = 0;
+				d_prune_aliases (inode);
+	                        iput (inode);
+	                        inode = NULL;
+                        }
+                }
+#endif
+		*vote = FLAG_VOTE_NODE;
+		goto finito;
+	}
+
+finito:
+	if (*lockres) {
+		(*lockres)->lock_state |= FLAG_ALWAYS_UPDATE_OPEN;
+		(*lockres)->last_upd_seq_num = seq_num;
+
+		if ((*lockres)->master_node_num != OCFS_INVALID_NODE_NUM) {
+			if (!IS_NODE_ALIVE (osb->publ_map, (*lockres)->master_node_num,
+					    OCFS_MAXIMUM_NODES)) {
+				(*lockres)->master_node_num = node_num;
+			}
+		} else {
+			(*lockres)->master_node_num = node_num;
+		}
+
+		/* Change the master if there is no lock */
+		if (((*lockres)->master_node_num == osb->node_num) &&
+		    ((*lockres)->lock_state <= OCFS_DLM_SHARED_LOCK)) {
+
+			status = ocfs_get_file_entry (osb, &fe, lock_id);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto finally;
+			}
+
+			DISK_LOCK_CURRENT_MASTER (fe) = node_num;
+
+			status = ocfs_write_disk (osb, fe, osb->sect_size, lock_id);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto finally;
+			}
+			(*lockres)->master_node_num = node_num;
+		}
+	}
+
+finally:
+	ocfs_release_file_entry (fe);
+
+	if (acq_oin && oin_sem)
+		ocfs_up_sem (oin_sem);
+
+	LOG_EXIT_STATUS (status);
+	return (status);
+}				/* ocfs_common_del_ren */

Added: trunk/libocfs/Common/ocfsgensysfile.c
===================================================================
--- trunk/libocfs/Common/ocfsgensysfile.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/ocfsgensysfile.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,971 @@
+/*
+ * ocfsgensysfile.c
+ *
+ * Initialize, read, write, etc. system files.
+ *
+ * Copyright (C) 2002, 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifdef __KERNEL__
+#include <ocfs.h>
+#else
+#include <libocfs.h>
+#endif
+
+/* Tracing */
+#define OCFS_DEBUG_CONTEXT    OCFS_DEBUG_CONTEXT_MISC
+
+/*
+ * ocfs_init_system_file()
+ *
+ */
+int ocfs_init_system_file (ocfs_super * osb, __u32 file_id, char *filename,
+			   ocfs_file_entry *fe)
+{
+	int status = 0;
+	__u64 offset = 0;
+	__u32 length = 0;
+
+	LOG_ENTRY_ARGS ("(file_id = %u)\n", file_id);
+
+	memset (filename, 0, sizeof (OCFS_MAX_FILENAME_LENGTH));
+
+	if ((file_id >= OCFS_FILE_DIR_ALLOC) &&
+	    (file_id < (OCFS_FILE_DIR_ALLOC + 32))) {
+		sprintf (filename, "%s%d", OCFS_DIR_FILENAME, file_id);
+	} else if ((file_id >= OCFS_FILE_DIR_ALLOC_BITMAP) &&
+		   (file_id < (OCFS_FILE_DIR_ALLOC_BITMAP + 32))) {
+		sprintf (filename, "%s%d", OCFS_DIR_BITMAP_FILENAME, file_id);
+	} else if ((file_id >= OCFS_FILE_FILE_ALLOC) &&
+		   (file_id < (OCFS_FILE_FILE_ALLOC + 32))) {
+		sprintf (filename, "%s%d", OCFS_FILE_EXTENT_FILENAME, file_id);
+	} else if ((file_id >= OCFS_FILE_FILE_ALLOC_BITMAP) &&
+		   (file_id < (OCFS_FILE_FILE_ALLOC_BITMAP + 32))) {
+		sprintf (filename, "%s%d", OCFS_FILE_EXTENT_BITMAP_FILENAME,
+			 file_id);
+	} else if ((file_id >= LOG_FILE_BASE_ID)
+		   && (file_id < (LOG_FILE_BASE_ID + 32))) {
+		sprintf (filename, "%s%d", OCFS_RECOVER_LOG_FILENAME, file_id);
+	} else if ((file_id >= CLEANUP_FILE_BASE_ID) &&
+		   (file_id < (CLEANUP_FILE_BASE_ID + 32))) {
+		sprintf (filename, "%s%d", OCFS_CLEANUP_LOG_FILENAME, file_id);
+	} else if ((file_id >= OCFS_FILE_VOL_META_DATA) &&
+		   (file_id < (OCFS_FILE_VOL_META_DATA + 32))) {
+		sprintf (filename, "%s", "VolMetaDataFile");
+	} else if ((file_id >= OCFS_FILE_VOL_LOG_FILE) &&
+		   (file_id < (OCFS_FILE_VOL_LOG_FILE + 32))) {
+		sprintf (filename, "%s", "VolMetaDataLogFile");
+#ifdef LOCAL_ALLOC
+	} else if ((file_id >= OCFS_VOL_BITMAP_FILE) && 
+	      	   (file_id < (OCFS_FILE_VOL_LOG_FILE + 64))) {
+		sprintf (filename, "%s", "VolBitMapFile");
+#endif
+	} else {
+		sprintf (filename, "%s", "UKNOWNSysFile");
+	}
+
+	offset = (file_id * osb->sect_size) + osb->vol_layout.root_int_off;
+
+	length = osb->sect_size;
+
+	memset (fe, 0, sizeof (ocfs_file_entry));
+	/*  Set the Flag to use the Local Extents */
+	fe->local_ext = true;
+	fe->granularity = -1;
+
+	strcpy (fe->signature, OCFS_FILE_ENTRY_SIGNATURE);
+	fe->next_free_ext = 0;
+
+	/*  Add a file Name  */
+	memcpy (fe->filename, filename, strlen (filename));
+	(fe->filename)[strlen (filename)] = '\0';
+
+	/*  Set the Valid bit here  */
+	SET_VALID_BIT (fe->sync_flags);
+	fe->sync_flags &= ~(OCFS_SYNC_FLAG_CHANGE);
+	fe->this_sector = offset;
+	fe->last_ext_ptr = 0;
+
+	status = ocfs_write_disk (osb, (void *) fe, osb->sect_size, offset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+      leave:
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_init_system_file */
+
+/*
+ * ocfs_read_system_file()
+ *
+ */
+int ocfs_read_system_file (ocfs_super * osb,
+		__u32 FileId, void *Buffer, __u64 Length, __u64 Offset)
+{
+	int status = 0;
+	ocfs_file_entry *fe = NULL;
+	void *extentBuffer = NULL;
+	__u32 numExts = 0, i;
+	ocfs_io_runs *IoRuns = NULL;
+	__u64 templength;
+	__u32 *tempBuffer;
+	__u64 tempOffset = 0;
+	bool bWriteThru = false;
+
+	LOG_ENTRY_ARGS ("(FileId = %u)\n", FileId);
+
+	if ((FileId == (__u32) (OCFS_FILE_VOL_LOG_FILE + osb->node_num)) ||
+	    (FileId == (__u32) (OCFS_FILE_VOL_META_DATA + osb->node_num))) {
+		bWriteThru = true;
+	}
+
+	/*  Read the File Entry corresponding to File Id */
+	status = ocfs_force_get_file_entry (osb, &fe,
+					(FileId * osb->sect_size) +
+					osb->vol_layout.root_int_off,
+					bWriteThru);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	if (!IS_VALID_FILE_ENTRY (fe)) {
+		LOG_ERROR_STATUS(status = -EINVAL);
+		goto leave;
+	}
+
+	status = ocfs_find_extents_of_system_file (osb, Offset, Length,
+					  fe, &extentBuffer, &numExts);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	OCFS_ASSERT (extentBuffer);
+
+	IoRuns = (ocfs_io_runs *) extentBuffer;
+	tempOffset = 0;
+	templength = 0;
+	tempBuffer = Buffer;
+
+	for (i = 0; i < numExts; i++) {
+		tempBuffer += templength;
+		/*  ?? need to align both the length and buffer and also */
+		/* offset ( atleast the starting one) */
+		tempOffset = IoRuns[i].disk_off;
+		templength = IoRuns[i].byte_cnt;
+
+		if (bWriteThru) {
+			status = ocfs_read_disk (osb, (void *) tempBuffer,
+						 (__u32) templength, tempOffset);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto leave;
+			}
+		} else {
+			status = ocfs_read_metadata (osb, (void *) tempBuffer,
+						(__u32) templength, tempOffset);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto leave;
+			}
+		}
+	}
+
+      leave:
+	ocfs_release_file_entry (fe);
+#ifdef SYSFILE_EXTMAP_FIX
+	if (extentBuffer)
+		vfree(extentBuffer);
+#else
+	ocfs_safefree (extentBuffer);
+#endif
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_read_system_file */
+
+
+/*
+ * ocfs_write_system_file()
+ *
+ */
+int ocfs_write_system_file (ocfs_super * osb,
+		 __u32 FileId, void *Buffer, __u64 Length, __u64 Offset)
+{
+	int status = 0;
+	ocfs_file_entry *fe = NULL;
+	void *extentBuffer = NULL;
+	__u32 numExts = 0, i;
+	ocfs_io_runs *IoRuns = NULL;
+	__u64 templength;
+	__u32 *tempBuffer;
+	__u64 tempOffset = 0;
+	bool bWriteThru = false;
+
+	LOG_ENTRY_ARGS ("(FileId = %u)\n", FileId);
+
+	if ((FileId == (OCFS_FILE_VOL_LOG_FILE + osb->node_num)) ||
+	    (FileId == (OCFS_FILE_VOL_META_DATA + osb->node_num))) {
+		bWriteThru = true;
+	}
+
+	/*  Read the File Entry corresponding to File Id */
+	status = ocfs_force_get_file_entry (osb, &fe,
+					(FileId * osb->sect_size) +
+					osb->vol_layout.root_int_off,
+					bWriteThru);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+	if (!IS_VALID_FILE_ENTRY (fe)) {
+		LOG_ERROR_STATUS(status = -EINVAL);
+		goto leave;
+	}
+
+	status = ocfs_find_extents_of_system_file (osb, Offset, Length,
+					  fe, &extentBuffer, &numExts);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	OCFS_ASSERT (extentBuffer);
+
+	IoRuns = (ocfs_io_runs *) extentBuffer;
+	tempOffset = 0;
+	templength = 0;
+	tempBuffer = Buffer;
+
+	for (i = 0; i < numExts; i++) {
+		tempBuffer += templength;
+		/*  ?? need to align both the length and buffer and also */
+		/* offset ( atleast the starting one) */
+		tempOffset = IoRuns[i].disk_off;
+		templength = IoRuns[i].byte_cnt;
+		/*  ?? Also need to read the data from the start of sector */
+		/* and then munge it . */
+		if (bWriteThru) {
+			status =
+			    ocfs_write_force_disk (osb, (void *) tempBuffer,
+						(__u32) templength, tempOffset);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto leave;
+			}
+		} else {
+			status =
+			    ocfs_write_metadata (osb, (void *) tempBuffer,
+					       (__u32) templength, tempOffset);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto leave;
+			}
+		}
+	}
+
+      leave:
+	ocfs_release_file_entry (fe);
+#ifdef SYSFILE_EXTMAP_FIX
+       if (extentBuffer)
+              vfree(extentBuffer);
+#else
+	ocfs_safefree (extentBuffer);
+#endif
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_write_system_file */
+
+/*
+ * ocfs_file_to_disk_off()
+ *
+ */
+__u64 ocfs_file_to_disk_off (ocfs_super * osb, __u32 FileId, __u64 Offset)
+{
+	int status = 0;
+	__u64 StartOffset = 0;
+	void *Buffer = NULL;
+	ocfs_file_entry *fe = NULL;
+	ocfs_io_runs *IoRuns;
+	__u32 NumExts = 0;
+	bool bWriteThru = false;
+
+	LOG_ENTRY_ARGS ("(FileId = %u)\n", FileId);
+
+	if ((FileId == (OCFS_FILE_VOL_LOG_FILE + osb->node_num)) ||
+	    (FileId == (OCFS_FILE_VOL_META_DATA + osb->node_num))) {
+		bWriteThru = true;
+	}
+
+	/*  Read the File Entry corresponding to File Id */
+	status = ocfs_force_get_file_entry (osb, &fe,
+					(FileId * osb->sect_size) +
+					osb->vol_layout.root_int_off,
+					bWriteThru);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+	if (!IS_VALID_FILE_ENTRY (fe)) {
+		LOG_ERROR_STATUS(status = -EINVAL);
+		goto leave;
+	}
+
+	status = ocfs_find_extents_of_system_file (osb, Offset, osb->sect_size,
+					  fe, &Buffer, &NumExts);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	OCFS_ASSERT (Buffer);
+
+	IoRuns = (ocfs_io_runs *) Buffer;
+	/*  Return the disk offset of first run . */
+	StartOffset = (IoRuns[0].disk_off);
+
+      leave:
+	ocfs_release_file_entry (fe);
+#ifdef SYSFILE_EXTMAP_FIX
+	if (Buffer)
+		vfree(Buffer);
+#else
+	ocfs_safefree (Buffer);
+#endif
+
+	LOG_EXIT_ARGS ("%u.%u", HI (StartOffset), LO (StartOffset));
+	return StartOffset;
+}				/* ocfs_file_to_disk_off */
+
+
+/*
+ * ocfs_get_system_file_size()
+ *
+ */
+int ocfs_get_system_file_size (ocfs_super * osb, __u32 FileId, __u64 * Length, __u64 * AllocSize)
+{
+	int status = 0;
+	ocfs_file_entry *fe = NULL;
+	bool bWriteThru = false;
+	__u64 offset;
+
+	LOG_ENTRY_ARGS ("(FileId = %u)\n", FileId);
+
+	if ((FileId == (OCFS_FILE_VOL_LOG_FILE + osb->node_num)) ||
+	    (FileId == (OCFS_FILE_VOL_META_DATA + osb->node_num))) {
+		bWriteThru = true;
+	}
+	*AllocSize = *Length = 0;
+
+	offset = (FileId * osb->sect_size) + osb->vol_layout.root_int_off;
+
+	status = ocfs_force_get_file_entry (osb, &fe, offset, bWriteThru);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	if (!IS_VALID_FILE_ENTRY (fe)) {
+		LOG_ERROR_ARGS("offset=%u.%u", HI(offset), LO(offset));
+		status = -EINVAL;
+		goto leave;
+	}
+
+	*Length = (__u64) (fe->file_size);
+	*AllocSize = (__u64) (fe->alloc_size);
+
+      leave:
+	ocfs_release_file_entry (fe);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_get_system_file_size */
+
+/*
+ * ocfs_extend_system_file()
+ *
+ */
+int ocfs_extend_system_file (ocfs_super * osb, __u32 FileId, __u64 FileSize, ocfs_file_entry *fe)
+{
+	int status = 0;
+	__u64 actualDiskOffset = 0, actualLength = 0;
+	bool bWriteThru = false;
+	bool local_fe = false;
+
+	LOG_ENTRY_ARGS ("(FileId = %u, Size = %u.%u)\n", FileId, HI (FileSize),
+			LO (FileSize));
+
+	if ((FileId == (OCFS_FILE_VOL_LOG_FILE + osb->node_num)) ||
+	    (FileId == (OCFS_FILE_VOL_META_DATA + osb->node_num))) {
+		bWriteThru = true;
+	}
+	OCFS_ASSERT (osb);
+
+	if (!fe) {
+		local_fe = true;
+		status = ocfs_force_get_file_entry (osb, &fe,
+						(FileId * osb->sect_size) +
+						osb->vol_layout.root_int_off,
+						bWriteThru);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+	}
+
+	if (!IS_VALID_FILE_ENTRY (fe)) {
+		LOG_ERROR_STATUS (status = -EINVAL);
+		goto leave;
+	}
+
+	if (FileSize <= fe->alloc_size) {
+		fe->file_size = FileSize;
+	} else {
+		/*  We need to allocate from bitmap */
+		__u64 numClusterAlloc = 0, BitmapOffset = 0;
+
+		status =
+		    ocfs_find_contiguous_space_from_bitmap (osb,
+						   FileSize - fe->alloc_size,
+						   &BitmapOffset,
+						   &numClusterAlloc, true);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+
+		actualDiskOffset =
+		    (BitmapOffset * osb->vol_layout.cluster_size) +
+		    osb->vol_layout.data_start_off;
+		actualLength =
+		    (__u64) (numClusterAlloc * osb->vol_layout.cluster_size);
+
+		status = ocfs_allocate_extent (osb, NULL, fe, actualDiskOffset,
+					     actualLength);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+
+		fe->alloc_size += actualLength;
+		fe->file_size = FileSize;
+	}
+
+	if (!bWriteThru) {
+		DISK_LOCK_CURRENT_MASTER (fe) = osb->node_num;
+		DISK_LOCK_FILE_LOCK (fe) = OCFS_DLM_ENABLE_CACHE_LOCK;
+	}
+
+	status = ocfs_force_put_file_entry (osb, fe, bWriteThru);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+      leave:
+	if (local_fe)
+		ocfs_release_file_entry (fe);
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_extend_system_file */
+
+
+/*
+ * ocfs_find_extents_of_system_file()
+ *
+ * Searches for the extents in the file entry passed starting from
+ * file offset up to the length specified.
+ */
+int ocfs_find_extents_of_system_file (ocfs_super * osb,
+			 __u64 file_off,
+			 __u64 Length,
+			 ocfs_file_entry * fe, void **Buffer, __u32 * NumEntries)
+{
+	int status = -EFAIL;
+	__u32 allocSize = 0, size;
+	__u8 *buffer = NULL;
+	__u32 k = 0, j;
+	__u32 Runs, Runoffset;
+	__u32 length;
+	ocfs_extent_group *pOcfsExtent = NULL, *pOcfsExtentHeader = NULL;
+	ocfs_io_runs *IoRuns;
+	__u64 newOffset = 0, searchVbo, remainingLength = 0;
+
+	LOG_ENTRY ();
+
+	OCFS_ASSERT (osb);
+
+	if (!IS_VALID_FILE_ENTRY (fe)) {
+		LOG_ERROR_STATUS(status = -EFAIL);
+		goto leave;
+	}
+#ifdef SYSFILE_EXTMAP_FIX
+      if (fe->local_ext)
+      {
+              size = OCFS_MAX_FILE_ENTRY_EXTENTS * sizeof (ocfs_io_runs);
+      }
+      else
+      {
+              int pow = fe->granularity + 1;
+              /* extent tree looks like
+               *             fe[0]        fe[1]    fe[2]
+               *        hdr[0]...hdr[17]  .....
+               * dat[0]..dat[17]
+               *
+               * granularity of fe is tree height
+               * so max runs (total of all leaves) is
+               * 3 x 18 ^ (granularity+1)
+               * (OCFS_MAX_DATA_EXTENTS = 18)
+               *
+               * g=0: 1296 bytes
+               * g=1: 23328 bytes
+               * g=2: 419904 bytes!
+               */
+              size = 3;
+              while (pow)
+              {
+                      size *= OCFS_MAX_DATA_EXTENTS;
+                      pow--;
+              }
+              size *= sizeof (ocfs_io_runs);
+      }
+      size = OCFS_ALIGN (size, osb->sect_size);
+      IoRuns = vmalloc(size);
+#else
+	/* ??? need to allocate accoordingly ...as number of runs can be more */
+	size = (OCFS_MAX_DATA_EXTENTS * sizeof (ocfs_io_runs));
+	size = OCFS_ALIGN (size, osb->sect_size);
+
+	IoRuns = ocfs_malloc (size);
+#endif
+	if (IoRuns == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	memset (IoRuns, 0, size);
+
+	remainingLength = Length;
+	Runs = 1;
+	Runoffset = 0;
+	newOffset = file_off;
+
+	if (fe->local_ext) {
+		for (j = 0; j < OCFS_MAX_FILE_ENTRY_EXTENTS; j++) {
+			if ((fe->extents[j].file_off +
+			     fe->extents[j].num_bytes) > newOffset) {
+				IoRuns[Runoffset].disk_off =
+				    fe->extents[j].disk_off +
+				    (newOffset - fe->extents[j].file_off);
+				IoRuns[Runoffset].byte_cnt =
+				    (__u32) ((fe->extents[j].file_off +
+					    fe->extents[j].num_bytes) -
+					   newOffset);
+				if (IoRuns[Runoffset].byte_cnt >=
+				    remainingLength) {
+					IoRuns[Runoffset].byte_cnt =
+					    (__u32) remainingLength;
+					status = 0;
+					break;
+				} else {
+					newOffset += IoRuns[Runoffset].byte_cnt;
+					remainingLength -=
+					    IoRuns[Runoffset].byte_cnt;
+					Runs++;
+					Runoffset++;
+				}
+			}
+		}
+
+		*NumEntries = Runs;
+		*Buffer = IoRuns;
+		goto leave;
+	} else {
+		/* Extents are branched and we are no longer using Local Extents */
+		/* for this File Entry. */
+
+		allocSize = (NUM_SECTORS_IN_LEAF_NODE + fe->granularity) *
+		    OCFS_SECTOR_SIZE;
+
+		length = (__u32) OCFS_ALIGN (allocSize, osb->sect_size);
+
+		buffer = ocfs_malloc (length);
+		if (buffer == NULL) {
+			LOG_ERROR_STATUS (status = -ENOMEM);
+			goto leave;
+		}
+
+		while (1) {
+			/* Keep going downwards looking for the Entry, till we hit */
+			/* the last Data entry */
+			for (k = 0; k < OCFS_MAX_FILE_ENTRY_EXTENTS; k++) {
+				if ((__s64) (fe->extents[k].file_off +
+					   fe->extents[k].num_bytes) >
+				    newOffset) {
+					break;
+				}
+			}
+
+			if (k == OCFS_MAX_FILE_ENTRY_EXTENTS) {
+				LOG_ERROR_STR ("data extents maxed");
+			}
+
+			memset (buffer, 0, length);
+
+			if (fe->extents[k].disk_off == 0) {
+				LOG_ERROR_STR ("disk_off=0");
+			}
+
+			status =
+			    ocfs_read_metadata (osb, (void *) buffer, allocSize,
+					      fe->extents[k].disk_off);
+
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto leave;
+			}
+
+			pOcfsExtent = (ocfs_extent_group *) buffer;
+			while (pOcfsExtent->type != OCFS_EXTENT_DATA) {
+				__u64 diskoffset;
+
+				if (!IS_VALID_EXTENT_HEADER (pOcfsExtent)) {
+					LOG_ERROR_STATUS(status = -EFAIL);
+					goto leave;
+				}
+
+				OCFS_GET_EXTENT ((__s64) newOffset, pOcfsExtent,
+						 k);
+				if (k == OCFS_MAX_DATA_EXTENTS) {
+					LOG_ERROR_STR ("data extents maxed");
+				}
+
+				if (pOcfsExtent->extents[k].disk_off == 0) {
+					LOG_ERROR_STR ("disk_off=0");
+				}
+
+				diskoffset = pOcfsExtent->extents[k].disk_off;
+
+				memset (buffer, 0, length);
+
+				status =
+				    ocfs_read_metadata (osb, (void *) buffer,
+						      allocSize,
+						      diskoffset); 
+				if (status < 0) {
+					LOG_ERROR_STATUS (status);
+					goto leave;
+				}
+				pOcfsExtent = (ocfs_extent_group *) buffer;
+			}
+			pOcfsExtentHeader = (ocfs_extent_group *) buffer;
+
+			searchVbo = newOffset;
+
+			OCFS_ASSERT (pOcfsExtentHeader->type ==
+				     OCFS_EXTENT_DATA);
+
+			if (!IS_VALID_EXTENT_DATA (pOcfsExtentHeader)) {
+				LOG_ERROR_STATUS(status = -EFAIL);
+				goto leave;
+			}
+
+			{
+				for (j = 0; j < OCFS_MAX_DATA_EXTENTS; j++) {
+					if ((pOcfsExtent->extents[j].file_off +
+					     pOcfsExtent->extents[j].
+					     num_bytes) > newOffset) {
+						IoRuns[Runoffset].disk_off =
+						    pOcfsExtent->extents[j].
+						    disk_off + (newOffset -
+								pOcfsExtent->
+								extents[j].
+								file_off);
+						IoRuns[Runoffset].byte_cnt =
+						    (__u32) ((pOcfsExtent->
+							    extents[j].
+							    file_off +
+							    pOcfsExtent->
+							    extents[j].
+							    num_bytes) -
+							   newOffset);
+
+						if (IoRuns[Runoffset].
+						    byte_cnt >=
+						    remainingLength) {
+							IoRuns[Runoffset].
+							    byte_cnt = (__u32)
+							    remainingLength;
+							status = 0;
+							break;
+						} else {
+							newOffset +=
+							    IoRuns[Runoffset].
+							    byte_cnt;
+							remainingLength -=
+							    IoRuns[Runoffset].
+							    byte_cnt;
+							Runs++;
+							Runoffset++;
+							if (Runs >=
+							    OCFS_MAX_DATA_EXTENTS)
+							{
+								LOG_ERROR_ARGS ("Runs=%d", Runs);
+							}
+						}
+					}
+				}
+
+				if (j == OCFS_MAX_DATA_EXTENTS) {
+					continue;
+				} else {
+					*NumEntries = Runs;
+					*Buffer = IoRuns;
+					goto leave;
+				}
+			}
+		}
+	}
+
+      leave:
+	/* Don't free the IoRuns Memory here */
+	ocfs_safefree (buffer);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_find_extents_of_system_file */
+
+/*
+ * ocfs_free_file_extents()
+ *
+ */
+int ocfs_free_file_extents (ocfs_super * osb, ocfs_file_entry * fe, __s32 LogNodeNum)
+{
+	int status = 0;
+	__u32 i, size, numUpdt = 0;
+	__u32 numBitsAllocated = 0, bitmapOffset = 0;
+	ocfs_cleanup_record *pCleanupLogRec = NULL;
+	ocfs_extent_group *PAllocExtent = NULL;
+
+	LOG_ENTRY ();
+
+	size = sizeof (ocfs_cleanup_record);
+	size = (__u32) OCFS_ALIGN (size, OCFS_PAGE_SIZE);
+
+	pCleanupLogRec = ocfs_malloc (size);
+	if (pCleanupLogRec == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	pCleanupLogRec->rec.free.num_free_upds = 0;
+	pCleanupLogRec->log_id = osb->curr_trans_id;
+	pCleanupLogRec->log_type = LOG_FREE_BITMAP;
+
+	if (fe->local_ext) {
+		for (i = 0; i < fe->next_free_ext; i++) {
+			numBitsAllocated = (__u32) (fe->extents[i].num_bytes /
+						  (osb->vol_layout.
+						   cluster_size));
+
+			bitmapOffset =
+			    (__u32) ((fe->extents[i].disk_off -
+				    osb->vol_layout.data_start_off) /
+				   (osb->vol_layout.cluster_size));
+
+			numUpdt = pCleanupLogRec->rec.free.num_free_upds;
+
+			pCleanupLogRec->rec.free.free_bitmap[numUpdt].length =
+			    numBitsAllocated;
+			pCleanupLogRec->rec.free.free_bitmap[numUpdt].file_off =
+			    bitmapOffset;
+			pCleanupLogRec->rec.free.free_bitmap[numUpdt].type =
+			    DISK_ALLOC_VOLUME;
+			pCleanupLogRec->rec.free.free_bitmap[numUpdt].node_num =
+			    -1;
+
+			(pCleanupLogRec->rec.free.num_free_upds)++;
+		}
+	} else {
+		size = OCFS_ALIGN (sizeof (ocfs_extent_group), osb->sect_size);
+
+		PAllocExtent = ocfs_malloc (size);
+		if (PAllocExtent == NULL) {
+			LOG_ERROR_STATUS (status = -ENOMEM);
+			goto leave;
+		}
+
+		memset (PAllocExtent, 0, size);
+
+		for (i = 0; i < fe->next_free_ext; i++) {
+			status = ocfs_read_extent (osb, PAllocExtent,
+						   fe->extents[i].disk_off,
+						   (fe->granularity ?
+						    EXTENT_HEADER : EXTENT_DATA));
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto leave;
+			}
+
+			status = ocfs_kill_this_tree(osb, PAllocExtent, pCleanupLogRec);
+			if (status < 0) {
+				LOG_ERROR_STATUS(status);
+				goto leave;
+			}
+		}
+	}
+
+	/* Write the log */
+	if (pCleanupLogRec->rec.free.num_free_upds > 0) {
+		status =
+		    ocfs_write_node_log (osb, (ocfs_log_record *) pCleanupLogRec,
+				      LogNodeNum, LOG_CLEANUP);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+	}
+
+      leave:
+	ocfs_safefree (PAllocExtent);
+	ocfs_safefree (pCleanupLogRec);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_free_file_extents */
+
+/*
+ * ocfs_write_map_file()
+ *
+ */
+int ocfs_write_map_file (ocfs_super * osb)
+{
+	int status;
+	__u32 RunsInMap;
+	__u32 MapIndex;
+	__u32 length;
+	ocfs_offset_map *pMapBuffer = NULL;
+	__u64 fileSize;
+	__u64 allocSize;
+	__u64 neededSize;
+	__s64 foundVolOffset;
+	__s64 foundlogOffset;
+	__u32 numRec;
+	ocfs_file_entry *fe = NULL;
+
+	LOG_ENTRY ();
+
+	RunsInMap = ocfs_extent_map_get_count (&osb->trans_map);
+
+	LOG_TRACE_ARGS ("NumRuns in trans_map=%u\n", RunsInMap);
+
+	if (RunsInMap == 0) {
+		status = -EFAIL; /* valid error */
+		goto leave;
+	}
+
+	neededSize =
+	    OCFS_ALIGN ((RunsInMap * sizeof (ocfs_offset_map)), osb->sect_size);
+
+	status = ocfs_get_system_file_size (osb,
+				    (OCFS_FILE_VOL_META_DATA + osb->node_num),
+				    &fileSize, &allocSize);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	if (allocSize < neededSize) {
+		LOG_TRACE_ARGS ("allocSize(%u.%u) < neededSize(%u.%u)",
+				HI(allocSize), LO(allocSize), HI(neededSize),
+				LO(neededSize));
+		status = ocfs_extend_system_file (osb,
+				  (OCFS_FILE_VOL_META_DATA + osb->node_num),
+				  neededSize, NULL);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+	}
+
+	pMapBuffer = ocfs_malloc (neededSize);
+	if (pMapBuffer == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	numRec = 0;
+	for (MapIndex = 0; MapIndex < RunsInMap; MapIndex++) {
+		if (!ocfs_get_next_extent_map_entry (osb, &osb->trans_map, MapIndex,
+						&foundVolOffset,
+						&foundlogOffset, &length)) {
+			/* It means this is a hole */
+			continue;
+		}
+
+		pMapBuffer[numRec].length = length;
+		pMapBuffer[numRec].actual_disk_off = foundVolOffset;
+		pMapBuffer[numRec].log_disk_off = foundlogOffset;
+		numRec++;
+	}
+
+	status = ocfs_force_get_file_entry (osb, &fe,
+					((OCFS_FILE_VOL_META_DATA +
+					  osb->node_num) * osb->sect_size) +
+					osb->vol_layout.root_int_off, true);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	if (!IS_VALID_FILE_ENTRY (fe)) {
+		LOG_ERROR_STATUS (status = -EINVAL);
+		goto leave;
+	}
+
+	status = ocfs_write_force_disk (osb, (void *) pMapBuffer, neededSize,
+					osb->log_meta_disk_off);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	fe->file_size = (numRec * sizeof (ocfs_offset_map));
+
+	status = ocfs_force_put_file_entry (osb, fe, true);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+      leave:
+	ocfs_release_file_entry (fe);
+
+	ocfs_safefree (pMapBuffer);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_write_map_file */
+

Added: trunk/libocfs/Common/ocfsgentrans.c
===================================================================
--- trunk/libocfs/Common/ocfsgentrans.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/ocfsgentrans.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,1269 @@
+/*
+ * ocfsgentrans.c
+ *
+ * Logging and recovery for file system structures.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifdef __KERNEL__
+#include <ocfs.h>
+#else
+#include <libocfs.h>
+#endif
+
+
+/* Tracing */
+#define OCFS_DEBUG_CONTEXT      OCFS_DEBUG_CONTEXT_TRANS
+
+/*
+ * ocfs_free_disk_bitmap()
+ *
+ * 
+ *
+ * called by: ocfs_process_record()
+ */
+int ocfs_free_disk_bitmap (ocfs_super * osb, ocfs_cleanup_record * log_rec)
+{
+	int status = 0;
+	__u32 num_upd;
+	__u32 i;
+	__u32 node_num;
+	ocfs_free_log **free_dir_node = NULL;
+	ocfs_free_log **free_ext_node = NULL;
+	ocfs_free_log *free_vol_bits = NULL;
+	ocfs_lock_res **dirnode_lockres = NULL;
+	ocfs_lock_res **extnode_lockres = NULL;
+	ocfs_lock_res *vol_lockres = NULL;
+	ocfs_free_log *tmp_log;
+	ocfs_free_log *free_log;
+	__u32 tmp_indx;
+	__u64 lock_id;
+        ocfs_file_entry *fe = NULL;
+        ocfs_bitmap_lock *bm_lock = NULL;
+
+	LOG_ENTRY_ARGS ("(0x%p, 0x%p)\n", osb, log_rec);
+
+#define ALLOC_BLOCK(ptr, len, err)				\
+	do {							\
+		(ptr) = ocfs_malloc (len);			\
+		if (!(ptr)) {					\
+			LOG_ERROR_STATUS ((err) = -ENOMEM);	\
+			goto finally;				\
+		}						\
+	} while (0)
+
+	ALLOC_BLOCK(free_dir_node,
+		    OCFS_MAXIMUM_NODES * sizeof (ocfs_free_log *), status);
+	ALLOC_BLOCK(free_ext_node,
+		    OCFS_MAXIMUM_NODES * sizeof (ocfs_free_log *), status);
+	ALLOC_BLOCK(dirnode_lockres,
+		    OCFS_MAXIMUM_NODES * sizeof (ocfs_lock_res *), status);
+	ALLOC_BLOCK(extnode_lockres,
+		    OCFS_MAXIMUM_NODES * sizeof (ocfs_lock_res *), status);
+
+	/* init */
+	for (i = 0; i < OCFS_MAXIMUM_NODES; i++) {
+		free_dir_node[i] = NULL;
+		free_ext_node[i] = NULL;
+	}
+
+	free_log = &(log_rec->rec.free);
+
+	/* alloc memory */
+	num_upd = free_log->num_free_upds;
+	for (i = 0; i < num_upd; i++) {
+		switch (free_log->free_bitmap[i].type) {
+		    case DISK_ALLOC_DIR_NODE:
+			    node_num = free_log->free_bitmap[i].node_num;
+			    if (free_dir_node[node_num] == NULL) {
+				    free_dir_node[node_num] =
+					ocfs_malloc (sizeof (ocfs_free_log));
+				    if (free_dir_node[node_num] == NULL) {
+					    LOG_ERROR_STATUS (status = -ENOMEM);
+					    goto finally;
+				    }
+				    free_dir_node[node_num]->num_free_upds = 0;
+			    }
+			    tmp_log = free_dir_node[node_num];
+			    break;
+
+		    case DISK_ALLOC_EXTENT_NODE:
+			    node_num = free_log->free_bitmap[i].node_num;
+			    if (free_ext_node[node_num] == NULL) {
+				    free_ext_node[node_num] =
+					ocfs_malloc (sizeof (ocfs_free_log));
+				    if (free_ext_node[node_num] == NULL) {
+					    LOG_ERROR_STATUS (status = -ENOMEM);
+					    goto finally;
+				    }
+				    free_ext_node[node_num]->num_free_upds = 0;
+			    }
+			    tmp_log = free_ext_node[node_num];
+			    break;
+
+		    case DISK_ALLOC_VOLUME:
+			    if (free_vol_bits == NULL) {
+				    free_vol_bits =
+					ocfs_malloc (sizeof (ocfs_free_log));
+				    if (free_vol_bits == NULL) {
+					    LOG_ERROR_STATUS (status = -ENOMEM);
+					    goto finally;
+				    }
+				    free_vol_bits->num_free_upds = 0;
+			    }
+			    tmp_log = free_vol_bits;
+			    break;
+
+		    default:
+			    tmp_log = NULL;
+			    break;
+		}
+
+		if (tmp_log) {
+			ocfs_free_bitmap *fb1, *fb2;
+
+			tmp_indx = tmp_log->num_free_upds;
+
+			fb1 = &(tmp_log->free_bitmap[tmp_indx]);
+			fb2 = &(free_log->free_bitmap[i]);
+
+			fb1->length = fb2->length;
+			fb1->file_off = fb2->file_off;
+			fb1->type = fb2->type;
+			fb1->node_num = fb2->node_num;
+
+			tmp_log->num_free_upds++;
+		}
+	}
+
+	/* Get all locks */
+	if (free_vol_bits != NULL) {
+		fe = ocfs_allocate_file_entry();
+		if (!fe) {
+			LOG_ERROR_STATUS (status = -ENOMEM);
+			goto finally;
+		}
+		bm_lock = (ocfs_bitmap_lock *)fe;
+		status = ocfs_acquire_lock (osb, OCFS_BITMAP_LOCK_OFFSET,
+					    OCFS_DLM_EXCLUSIVE_LOCK,
+					    FLAG_FILE_CREATE, &vol_lockres, fe);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+	}
+
+	lock_id = (OCFS_FILE_DIR_ALLOC_BITMAP * osb->sect_size) +
+		  osb->vol_layout.root_int_off;
+	for (i = 0; i < OCFS_MAXIMUM_NODES; i++, lock_id += osb->sect_size) {
+		if (free_dir_node[i] != NULL) {
+			status = ocfs_acquire_lock (osb, lock_id,
+						    OCFS_DLM_EXCLUSIVE_LOCK,
+						    FLAG_FILE_CREATE,
+						    &(dirnode_lockres[i]), NULL);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto finally;
+			}
+		}
+	}
+
+	lock_id = (OCFS_FILE_FILE_ALLOC_BITMAP * osb->sect_size) +
+		  osb->vol_layout.root_int_off;
+	for (i = 0; i < OCFS_MAXIMUM_NODES; i++, lock_id += osb->sect_size) {
+		if (free_ext_node[i] != NULL) {
+			status = ocfs_acquire_lock (osb, lock_id,
+				 		    OCFS_DLM_EXCLUSIVE_LOCK,
+						    FLAG_FILE_CREATE,
+						    &(extnode_lockres[i]), NULL);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto finally;
+			}
+		}
+	}
+
+	/* free vol block */
+	if (free_vol_bits != NULL)
+		ocfs_free_vol_block (osb, free_vol_bits, -1, DISK_ALLOC_VOLUME);
+
+	/* We can potentiallly loose some allocation for dirNodes or extent */
+	/* nodes but they should not be much...  */
+	for (i = 0; i < OCFS_MAXIMUM_NODES; i++) {
+		if (free_dir_node[i] != NULL)
+			ocfs_free_vol_block (osb, free_dir_node[i], i,
+					     DISK_ALLOC_DIR_NODE);
+
+		if (free_ext_node[i] != NULL)
+			ocfs_free_vol_block (osb, free_ext_node[i], i,
+					     DISK_ALLOC_EXTENT_NODE);
+	}
+
+	/* release all locks */
+	if (free_vol_bits != NULL) {
+                bm_lock->used_bits = ocfs_count_bits(&osb->cluster_bitmap);
+                status = ocfs_write_force_disk(osb, bm_lock, OCFS_SECTOR_SIZE, 
+                                               OCFS_BITMAP_LOCK_OFFSET);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+		status = ocfs_release_lock (osb, OCFS_BITMAP_LOCK_OFFSET,
+					    OCFS_DLM_EXCLUSIVE_LOCK,
+					    FLAG_FILE_CREATE, vol_lockres, fe);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+	}
+
+	lock_id = (OCFS_FILE_DIR_ALLOC_BITMAP * osb->sect_size) +
+		  osb->vol_layout.root_int_off;
+	for (i = 0; i < OCFS_MAXIMUM_NODES; i++, lock_id += osb->sect_size) {
+		if (free_dir_node[i] != NULL) {
+			status = ocfs_release_lock (osb, lock_id,
+						    OCFS_DLM_EXCLUSIVE_LOCK,
+						    FLAG_FILE_CREATE,
+						    dirnode_lockres[i], NULL);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto finally;
+			}
+		}
+	}
+
+	lock_id = (OCFS_FILE_FILE_ALLOC_BITMAP * osb->sect_size) +
+		  osb->vol_layout.root_int_off;
+	for (i = 0; i < OCFS_MAXIMUM_NODES; i++, lock_id += osb->sect_size) {
+		if (free_ext_node[i] != NULL) {
+			status = ocfs_release_lock (osb, lock_id,
+						    OCFS_DLM_EXCLUSIVE_LOCK,
+						    FLAG_FILE_CREATE,
+						    extnode_lockres[i], NULL);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto finally;
+			}
+		}
+
+	}
+
+      finally:
+	for (i = 0; i < OCFS_MAXIMUM_NODES; i++) {
+		if (free_dir_node[i])
+			ocfs_put_lockres (dirnode_lockres[i]);
+		if (free_ext_node[i])
+			ocfs_put_lockres (extnode_lockres[i]);
+	}
+	ocfs_put_lockres (vol_lockres);
+
+	for (i = 0; i < OCFS_MAXIMUM_NODES; i++) {
+		ocfs_safefree (free_dir_node[i]);
+		ocfs_safefree (free_ext_node[i]);
+	}
+
+	ocfs_safefree (free_dir_node);
+	ocfs_safefree (free_ext_node);
+	ocfs_safefree (dirnode_lockres);
+	ocfs_safefree (extnode_lockres);
+
+	ocfs_safefree (free_vol_bits);
+	ocfs_release_file_entry(fe);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_free_disk_bitmap */
+
+/*
+ * ocfs_process_record()
+ *
+ *
+ * called by: ocfs_process_log()
+ */
+int ocfs_process_record (ocfs_super * osb, void *buffer)
+{
+	int status = 0;
+	ocfs_log_record *log_rec;
+	ocfs_cleanup_record *clean_rec;
+	ocfs_file_entry *fe = NULL;
+	ocfs_dir_node *lock_node = NULL;
+	__u8 *read_buf = NULL;
+	__u32 node_num;
+	__u32 index;
+	ocfs_extent_group *alloc_ext;
+	__u64 disk_off = 0;
+	__u32 num_upd;
+	__u32 i;
+	__u64 lock_id;
+	ocfs_lock_res *lock_res;
+	ocfs_lock_res **lock_res_array = NULL;
+	ocfs_lock_res *tmp_lockres;
+
+	LOG_ENTRY_ARGS ("(0x%p, 0x%p)\n", osb, buffer);
+
+	log_rec = (ocfs_log_record *) buffer;
+	clean_rec = (ocfs_cleanup_record *) buffer;
+
+	switch (log_rec->log_type) {
+	    case LOG_TYPE_DISK_ALLOC:
+	    {
+		    switch (log_rec->rec.alloc.type) {
+			case DISK_ALLOC_DIR_NODE:
+			case DISK_ALLOC_EXTENT_NODE:
+				status = ocfs_free_node_block (osb,
+						   log_rec->rec.alloc.file_off,
+						   log_rec->rec.alloc.length,
+						   log_rec->rec.alloc.node_num,
+						   log_rec->rec.alloc.type);
+				break;
+			default:
+				break;
+		    }
+	    }
+		    break;
+
+	    case LOG_DELETE_NEW_ENTRY:
+		    status = ocfs_get_file_entry (osb, &fe,
+						  log_rec->rec.del.ent_del);
+		    if (status < 0) {
+			    LOG_ERROR_STATUS (status);
+			    goto finally;
+		    }
+
+		    status = ocfs_get_file_entry (osb,
+					  (ocfs_file_entry **) (&lock_node),
+					  log_rec->rec.del.parent_dirnode_off);
+		    if (status < 0) {
+			    LOG_ERROR_STATUS (status);
+			    goto finally;
+		    }
+
+		    node_num = log_rec->rec.del.node_num;
+
+		    /*
+		       ** Lock on directory shd be held by the node which either
+		       ** died or this node...
+		     */
+		    status = ocfs_del_file_entry (osb, fe, lock_node);
+		    if (status < 0) {
+			    LOG_ERROR_STATUS (status);
+			    goto finally;
+		    }
+		    break;
+
+	    case LOG_DELETE_ENTRY:
+		    /*
+		       ** Delete the entry from the dir node it was associated
+		       ** with. Now it can be reused.
+		     */
+		    status = ocfs_get_file_entry (osb, &fe,
+						  clean_rec->rec.del.ent_del);
+		    if (status < 0) {
+			    LOG_ERROR_STATUS (status);
+			    goto finally;
+		    }
+
+		    status = ocfs_get_file_entry (osb,
+					 (ocfs_file_entry **) (&lock_node),
+					 clean_rec->rec.del.parent_dirnode_off);
+		    if (status < 0) {
+			    LOG_ERROR_STATUS (status);
+			    goto finally;
+		    }
+
+		    node_num = clean_rec->rec.del.node_num;
+
+		    /*
+		       ** Lock on directory shd be held by the node which
+		       ** either died or this node...
+		     */
+		    status = ocfs_del_file_entry (osb, fe, lock_node);
+		    if (status < 0) {
+			    LOG_ERROR_STATUS (status);
+			    goto finally;
+		    }
+		    break;
+
+	    case LOG_MARK_DELETE_ENTRY:
+		    status = ocfs_get_file_entry (osb, &fe,
+						  log_rec->rec.del.ent_del);
+		    if (status < 0) {
+			    LOG_ERROR_STATUS (status);
+			    goto finally;
+		    }
+
+		    if (log_rec->rec.del.flags & FLAG_RESET_VALID) {
+			    OCFS_SET_FLAG (fe->sync_flags, OCFS_SYNC_FLAG_VALID);
+			    status = ocfs_write_file_entry (osb, fe,
+						      log_rec->rec.del.ent_del);
+			    if (status < 0) {
+				    LOG_ERROR_STATUS (status);
+				    goto finally;
+			    }
+
+			    /* We are done... */
+			    status = 0;
+			    goto finally;
+		    }
+
+		    /*
+		       ** Read in the entry to be deleted. We are doing
+		       ** recovery on another node?
+		       ** What if we were in abort trans for this node???
+		     */
+		    node_num = log_rec->rec.del.node_num;
+
+		    /* This is recovery for a dead node */
+		    if (fe->sync_flags & OCFS_SYNC_FLAG_VALID) {
+			    /* No recovery needed for the entry, let it stay */
+			    status = 0;
+			    goto finally;
+		    } else {
+			    status = ocfs_delete_file_entry (osb, fe,
+						log_rec->rec.del.parent_dirnode_off,
+						node_num);
+			    goto finally;
+		    }
+		    break;
+
+	    case LOG_FREE_BITMAP:
+		    status = ocfs_free_disk_bitmap (osb, buffer);
+		    if (status < 0) {
+			    LOG_ERROR_STATUS (status);
+			    goto finally;
+		    }
+		    break;
+
+	    case LOG_UPDATE_EXTENT:
+		     /* Make sure we have the file lock here */
+		    disk_off = log_rec->rec.extent.disk_off;
+		    status = ocfs_read_disk_ex (osb, (void **)&read_buf,
+				osb->sect_size, osb->sect_size, disk_off);
+		    if (status < 0) {
+			    LOG_ERROR_STATUS (status);
+			    goto finally;
+		    }
+
+		    alloc_ext = (ocfs_extent_group *) read_buf;
+
+		    index = log_rec->rec.extent.index;
+
+		    alloc_ext->extents[index].file_off = 0;
+		    alloc_ext->extents[index].num_bytes = 0;
+		    alloc_ext->extents[index].disk_off = 0;
+
+		    disk_off = log_rec->rec.extent.disk_off;
+
+		    status = ocfs_write_disk (osb, read_buf,
+					      (__u32) osb->sect_size, disk_off);
+		    if (status < 0) {
+			    LOG_ERROR_STATUS (status);
+			    goto finally;
+		    }
+		    break;
+
+	    case LOG_TYPE_DIR_NODE:
+		    status = ocfs_recover_dir_node (osb,
+						    log_rec->rec.dir.orig_off,
+						    log_rec->rec.dir.saved_off);
+		    if (status < 0) {
+			    LOG_ERROR_STATUS (status);
+			    /*
+			       ** Bad one. We should disable this volume and try
+			       ** and let somebody else do the recovery...
+			     */
+		    }
+		    break;
+
+	    case LOG_TYPE_RECOVERY:
+		    /*
+		       ** This node was recovering another node and died.
+		       ** All locks in the function need to be recursive...
+		     */
+		    node_num = osb->node_recovering;
+
+		    status = ocfs_recover_vol (osb,
+					       log_rec->rec.recovery.node_num);
+		    if (status < 0) {
+			    LOG_ERROR_STATUS (status);
+			    /*
+			       ** Bad one. We should disable this volume and try
+			       ** and let somebody else do the recovery...
+			     */
+		    }
+		    osb->node_recovering = node_num;
+		    break;
+
+	    case LOG_TYPE_TRANS_START:
+		    /* We are back to the record till which we needed to */
+		    /* roll back. Check to ensure the file size for recovery */
+		    /* log is 1 rec long */
+		    status = 0;
+		    break;
+
+	    case LOG_CLEANUP_LOCK:
+		    lock_res_array = ocfs_malloc (LOCK_UPDATE_LOG_SIZE *
+						  sizeof (ocfs_lock_res *));
+		    if (!lock_res_array) {
+			    LOG_ERROR_STATUS (status = -ENOMEM);
+			    goto finally;
+		    }
+
+		    num_upd = clean_rec->rec.lock.num_lock_upds;
+
+		    for (i = 0; i < num_upd; i++) {
+			    lock_id = clean_rec->rec.lock.lock_upd[i].orig_off;
+			    lock_res_array[i] = NULL;
+
+			    status = ocfs_lookup_sector_node (osb, lock_id,
+							      &lock_res);
+			    if (status >= 0) {
+				    ocfs_remove_sector_node (osb, lock_res);
+				    lock_res->sector_num =
+					clean_rec->rec.lock.lock_upd[i].new_off;
+				    lock_res_array[i] = lock_res;
+			    } else {
+				    /* We don't have the resource so don't */
+				    /* bother with it */
+			    }
+		    }
+
+		    for (i = 0; i < num_upd; i++) {
+			    tmp_lockres = NULL;
+			    lock_res = lock_res_array[i];
+			    if (lock_res) {
+				    /* Reinsert with new ID */
+				    status = ocfs_insert_sector_node (osb, lock_res,
+								      &tmp_lockres);
+				    if (status < 0) {
+					    LOG_ERROR_STATUS (status);
+					    goto finally;
+				    }
+				    if (tmp_lockres)
+					    LOG_ERROR_STR ("This too can happen");
+				    else
+					    ocfs_put_lockres (lock_res);
+			    }
+		    }
+		    break;
+
+	    default:
+		    break;
+	}
+
+      finally:
+	if (fe)
+		ocfs_release_file_entry (fe);
+	if (lock_node)
+		ocfs_release_file_entry ((ocfs_file_entry *) lock_node);
+	ocfs_safefree (read_buf);
+	ocfs_safefree (lock_res_array);
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_process_record */
+
+/*
+ * ocfs_process_log()
+ *
+ *
+ * called by: ocfs_commit_trans(), ocfs_abort_trans(), ocfs_recover_vol()
+ */
+int ocfs_process_log (ocfs_super * osb, __u64 trans_id, __u32 node_num, __u32 * type)
+{
+	int status = 0;
+	__u64 file_size;
+	__u64 offset;
+	__u64 alloc_size;
+	__u32 log_type;
+	__u32 log_rec_size;
+	__u32 size;
+	__u32 log_file_id;
+	ocfs_log_record *log_rec = NULL;
+        bool use_prealloc = false;
+
+	LOG_ENTRY_ARGS ("(0x%p, %u.%u, %u, 0x%p)\n", osb, HI (trans_id),
+			LO (trans_id), node_num, type);
+
+	log_type = *type;
+
+	if (log_type == LOG_RECOVER) {
+		log_file_id = (LOG_FILE_BASE_ID + node_num);
+		log_rec_size = osb->sect_size;
+	} else if (log_type == LOG_CLEANUP) {
+		log_file_id = (CLEANUP_FILE_BASE_ID + node_num);
+		log_rec_size = sizeof (ocfs_cleanup_record);
+		log_rec_size = (__u32) OCFS_ALIGN (log_rec_size, osb->sect_size);
+	} else {
+		LOG_ERROR_ARGS ("logtype=%u is invalid", log_type);
+		goto finally;
+	}
+
+	size = log_rec_size;
+	size = (__u32) OCFS_ALIGN (size, OCFS_PAGE_SIZE);
+
+        /* try to use prealloc log record if available */
+        ocfs_down_sem (&osb->osb_res, true);
+        if (! OSB_PREALLOC_LOCK_TEST(osb, OSB_LOG_LOCK))
+        {
+                OSB_PREALLOC_LOCK_SET(osb, OSB_LOG_LOCK);
+                log_rec = (ocfs_log_record *)osb->log_prealloc;
+                use_prealloc = true;
+        }
+        ocfs_up_sem(&osb->osb_res);
+
+        if (log_rec == NULL)
+        {
+	        if ((log_rec = ocfs_malloc (size)) == NULL) {
+		        LOG_ERROR_STATUS (status = -ENOMEM);
+		        goto finally;
+	        }
+        }
+
+	status = ocfs_get_system_file_size (osb, log_file_id, &file_size, &alloc_size);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	if (file_size <= 0) {
+		if (log_type == LOG_RECOVER)
+			*type = LOG_CLEANUP;
+		goto finally;
+	} else {
+		if (log_type == LOG_RECOVER) {
+			/*
+			   **  This helps in bdcast recovery by having other nodes just set
+			   **  the event and not process cleanup log
+			 */
+			status = ocfs_extend_system_file (osb,
+					  (CLEANUP_FILE_BASE_ID + node_num), 0, NULL);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto finally;
+			}
+		}
+	}
+
+	while (file_size != 0) {
+		/* Recover from the log file */
+		/* Read in the last record */
+		offset = file_size - log_rec_size;
+		status = ocfs_read_system_file (osb, log_file_id, log_rec,
+						log_rec_size, offset);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+
+		status = ocfs_process_record (osb, log_rec);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+
+		status = ocfs_extend_system_file (osb, log_file_id, offset, NULL);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+
+		status = ocfs_get_system_file_size (osb, log_file_id,
+						    &file_size, &alloc_size);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+	}
+
+      finally:
+        ocfs_down_sem (&osb->osb_res, true);
+        if (use_prealloc && OSB_PREALLOC_LOCK_TEST(osb, OSB_LOG_LOCK))
+                OSB_PREALLOC_LOCK_CLEAR(osb, OSB_LOG_LOCK);
+        else
+                ocfs_safefree (log_rec);
+        ocfs_up_sem(&osb->osb_res);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_process_log() */
+
+/*
+ * ocfs_start_trans()
+ *
+ *
+ * called by: ocfs_create_modify_file(), ocfs_set_rename_information()
+ */
+int ocfs_start_trans (ocfs_super * osb)
+{
+	LOG_ENTRY_ARGS ("(0x%p)\n", osb);
+
+	down (&osb->trans_lock);
+
+	osb->curr_trans_id = osb->vol_node_map.largest_seq_num;
+
+	if (osb->needs_flush) {
+		while (osb->needs_flush)
+			ocfs_sleep (100);	/* in ms */
+	}
+
+	osb->trans_in_progress = true;
+
+	LOG_EXIT_STATUS (0);
+	return 0;
+}				/* ocfs_start_trans */
+
+/*
+ * ocfs_commit_trans()
+ *
+ *
+ * called by: ocfs_create_modify_file(), ocfs_set_rename_information()
+ */
+int ocfs_commit_trans (ocfs_super * osb, __u64 trans_id)
+{
+	int status = 0;
+	__u64 offset = 0;
+	__u32 log_type;
+
+	LOG_ENTRY_ARGS ("(0x%p, %u.%u)\n", osb, HI (trans_id), LO (trans_id));
+
+	/* Log to the file for multiple transactions... */
+	status = ocfs_extend_system_file (osb,
+				(LOG_FILE_BASE_ID + osb->node_num), offset, NULL);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	log_type = LOG_CLEANUP;
+
+	status = ocfs_process_log (osb, trans_id, osb->node_num, &log_type);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	status = ocfs_extend_system_file (osb,
+				(CLEANUP_FILE_BASE_ID + osb->node_num), offset, NULL);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	osb->curr_trans_id = -1;
+
+      finally:
+	osb->trans_in_progress = false;
+	up (&osb->trans_lock);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_commit_trans */
+
+/*
+ * ocfs_abort_trans()
+ *
+ *
+ * called by: ocfs_create_modify_file(), ocfs_set_rename_information()
+ */
+int ocfs_abort_trans (ocfs_super * osb, __u64 trans_id)
+{
+	int status = 0;
+	__u64 offset = 0;
+	__u32 log_type;
+
+	LOG_ENTRY_ARGS ("(0x%p, %u.%u)\n", osb, HI (trans_id), LO (trans_id));
+
+	/* Read the log file and free up stf... */
+	log_type = LOG_RECOVER;
+
+	status = ocfs_process_log (osb, trans_id, osb->node_num, &log_type);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	status = ocfs_extend_system_file (osb,
+				(LOG_FILE_BASE_ID + osb->node_num), offset, NULL);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	status = ocfs_extend_system_file (osb,
+				(CLEANUP_FILE_BASE_ID + osb->node_num), offset, NULL);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	osb->curr_trans_id = -1;
+
+      finally:
+	osb->trans_in_progress = false;
+	up (&osb->trans_lock);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_abort_trans */
+
+/*
+ * ocfs_reset_publish()
+ *
+ *
+ * called by: ocfs_recover_vol()
+ *
+ * NOTE: This function is very similar to ocfs_disk_reset_voting().
+ * This function should replace the other one.
+ */
+int ocfs_reset_publish (ocfs_super * osb, __u64 node_num)
+{
+	int status = 0;
+	ocfs_publish *publish = NULL;
+	__u64 node_publ_off;
+
+	LOG_ENTRY_ARGS ("(0x%p, %u.%u)\n", osb, HI (node_num), LO (node_num));
+
+	/* Read the publish sector */
+	node_publ_off = osb->vol_layout.publ_sect_off +
+		        (node_num * osb->sect_size);
+	status = ocfs_read_disk_ex (osb, (void **)&publish, osb->sect_size,
+				    osb->sect_size, node_publ_off);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	publish->dirty = false;
+	publish->vote = 0;
+	publish->vote_type = 0;
+
+	/* Write the publish sector */
+	status = ocfs_write_disk (osb, publish, osb->sect_size, node_publ_off);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+      finally:
+	ocfs_safefree (publish);
+
+	LOG_EXIT_STATUS (status);
+	return (status);
+}				/* ocfs_reset_publish */
+
+
+/*
+ * ocfs_recover_vol()
+ *
+ * called by: ocfs_process_record(), ocfs_disk_request_vote(),
+ *            ocfs_acquire_lock(), ocfs_check_volume(), ocfs_nm_thread()
+ */
+int ocfs_recover_vol (ocfs_super * osb, __u64 node_num)
+{
+	int status = 0;
+	int tmpstat;
+	bool recovery_lock = false;
+	bool lock_acq = false;
+	__u64 lock_id = 0;
+	__u64 file_size = 0;
+	__u64 alloc_size = 0;
+	ocfs_lock_res *lock_res = NULL;
+	ocfs_log_record *log_rec = NULL;
+	__u32 size;
+	__u32 log_type;
+	__u64 trans_id = 0;
+	__u64 cleanup_file_size = 0;
+	__u32 file_id;
+	ocfs_file_entry *fe = NULL;
+
+	LOG_ENTRY_ARGS ("(0x%p, %u.%u)\n", osb, HI (node_num), LO (node_num));
+
+	fe = ocfs_allocate_file_entry ();
+	if (fe == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto finally;
+	}
+
+	if (!IS_VALID_NODE_NUM(node_num)) {
+		LOG_ERROR_STATUS (status = -EINVAL);
+		goto finally;
+	}
+
+	/* Grab the local recovery resource to ensure no other thread comes */
+	/* in from this node for recovery */
+	ocfs_down_sem (&(osb->recovery_lock), true);
+	recovery_lock = true;
+
+	if (osb->node_recovering == node_num) {
+		goto finally;
+	}
+
+	/* Now reset the publish sector to have the dirty bit not set...  */
+	status = ocfs_reset_publish (osb, node_num);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	file_id = (__u32) (LOG_FILE_BASE_ID + node_num);
+
+	/* Read in the the recovery log */
+	status = ocfs_get_system_file_size (osb, file_id, &file_size,
+					    &alloc_size);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	file_id = (__u32) (CLEANUP_FILE_BASE_ID + node_num);
+	status = ocfs_get_system_file_size (osb, file_id, &cleanup_file_size,
+					    &alloc_size);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	if ((file_size == 0) && (cleanup_file_size == 0)) {
+		/* Nothing to do so ...  */
+		/*
+		   ** Read the log file and go back to the last checkpoint,
+		   ** start of file for us. Read the logs for the transaction
+		   ** being recovered and un
+		 */
+
+		osb->node_recovering = OCFS_INVALID_NODE_NUM;
+		status = 0;
+		goto finally;
+	}
+
+	osb->node_recovering = node_num;
+	osb->vol_state = VOLUME_IN_RECOVERY;
+
+	/*
+	   ** Grab the lock on the log file for the node which needs recovery,
+	   ** this ensures nobody else in the cluster process the recovery
+	 */
+	lock_id = ((LOG_FILE_BASE_ID + node_num) * osb->sect_size) +
+		  osb->vol_layout.root_int_off;
+
+	status = ocfs_acquire_lock (osb, lock_id, OCFS_DLM_EXCLUSIVE_LOCK,
+				    FLAG_FILE_CREATE, &lock_res, fe);
+	if (status < 0) {
+		goto finally;
+	}
+
+	lock_acq = true;
+
+	if (node_num != osb->node_num) {
+		/*
+		   ** Write a log entry indicating this node is doing recovery
+		   ** for nodenum, if this node now dies during recovery.
+		   ** The node doing recovery for this node will know it needs
+		   ** to recover the vol for node node num too...
+		 */
+		size = max(sizeof (ocfs_log_record),
+			   sizeof (ocfs_cleanup_record));
+		size = (__u32) OCFS_ALIGN (size, OCFS_PAGE_SIZE);
+
+		if ((log_rec = ocfs_malloc (size)) == NULL) {
+			LOG_ERROR_STATUS (status = -ENOMEM);
+			goto finally;
+		}
+
+		log_rec->log_id = osb->curr_trans_id;
+		log_rec->log_type = LOG_TYPE_RECOVERY;
+		log_rec->rec.recovery.node_num = node_num;
+
+		/*
+		   ** Log the original dirnode sector and the new cluster
+		   ** where the info is stored
+		 */
+		status = ocfs_write_log (osb, log_rec, LOG_RECOVER);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+	}
+
+	log_type = LOG_RECOVER;
+
+	status = ocfs_process_log (osb, trans_id, osb->node_num, &log_type);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	/*
+	   ** If a cleanup file exists we should just reset the file size
+	   ** if we aborted the transaction otherwise process the cleanup file....
+	 */
+	if (log_type == LOG_CLEANUP) {
+		status = ocfs_process_log (osb, trans_id, osb->node_num,
+					   &log_type);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+	}
+
+	/* Read the log file and go back to the last checkpoint, */
+	/* start of file for us. Read the logs for the transaction  */
+	/* being recovered and un */
+	osb->node_recovering = OCFS_INVALID_NODE_NUM;
+
+	/* The vol state migh thave to turn inti flags...  */
+	osb->vol_state = VOLUME_ENABLED;
+
+	if (recovery_lock) {
+		ocfs_up_sem (&(osb->recovery_lock));
+		recovery_lock = false;
+	}
+
+      finally:
+	if (recovery_lock) {
+		ocfs_up_sem (&(osb->recovery_lock));
+		recovery_lock = false;
+	}
+
+	if (lock_acq) {
+		tmpstat = ocfs_release_lock (osb, lock_id,
+					     OCFS_DLM_EXCLUSIVE_LOCK,
+					     FLAG_FILE_CREATE, lock_res, fe);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+	}
+	ocfs_release_file_entry (fe);
+	ocfs_put_lockres (lock_res);
+	LOG_EXIT_STATUS (status);
+	return (status);
+}				/* ocfs_recover_vol */
+
+/*
+ * ocfs_write_log()
+ *
+ * called by: ocfs_recover_vol(), ocfs_del_file(), ocfs_alloc_node_block()
+ */
+int ocfs_write_log (ocfs_super * osb, ocfs_log_record * log_rec, __u32 type)
+{
+	int status = 0;
+	int tmpstat;
+	__s32 log_file_id = -1;
+	__u64 lock_id = 0;
+	__u64 file_size = 0;
+	__u64 offset = 0;
+	__u64 log_rec_size = 0;
+	__u64 alloc_size = 0;
+	ocfs_lock_res *lock_res = NULL;
+	bool log_lock = false;
+	bool lock_acq = false;
+	ocfs_file_entry *fe = NULL;
+
+	LOG_ENTRY_ARGS ("(0x%p, 0x%p, %u)\n", osb, log_rec, type);
+
+	fe = ocfs_allocate_file_entry ();
+	if (!fe) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto finally;
+	}
+
+	/* Get the log lock */
+	ocfs_down_sem (&(osb->log_lock), true);
+	log_lock = true;
+
+	if (type == LOG_RECOVER) {
+		log_file_id = (LOG_FILE_BASE_ID + osb->node_num);
+		log_rec_size = osb->sect_size;
+	} else if (type == LOG_CLEANUP) {
+		log_file_id = (CLEANUP_FILE_BASE_ID + osb->node_num);
+		log_rec_size = sizeof (ocfs_cleanup_record);
+		log_rec_size = OCFS_ALIGN (log_rec_size, osb->sect_size);
+	} else {
+		LOG_ERROR_ARGS ("logtype=%u is invalid", type);
+		goto finally;
+	}
+
+	/*
+	   ** Always log to the end of the file after taking a file lock
+	   ** and a log lock
+	 */
+	lock_id = (log_file_id * osb->sect_size) + osb->vol_layout.root_int_off;
+
+	status = ocfs_acquire_lock (osb, lock_id, OCFS_DLM_EXCLUSIVE_LOCK,
+				    FLAG_FILE_CREATE, &lock_res, fe);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	lock_acq = true;
+
+	file_size = fe->file_size;
+	alloc_size = fe->alloc_size;
+	offset = file_size;
+
+	if (alloc_size < (file_size + log_rec_size)) {
+		file_size += ONE_MEGA_BYTE;
+		status = ocfs_extend_system_file (osb, log_file_id, file_size, fe);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+	}
+
+	status = ocfs_write_system_file (osb, log_file_id, log_rec,
+					 log_rec_size, offset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	status = ocfs_extend_system_file (osb, log_file_id,
+					  (offset + log_rec_size), fe);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+      finally:
+	if (log_lock) {
+		ocfs_up_sem (&(osb->log_lock));
+		log_lock = false;
+	}
+
+	if (lock_acq) {
+		tmpstat = ocfs_release_lock (osb, lock_id,
+					     OCFS_DLM_EXCLUSIVE_LOCK,
+					     FLAG_FILE_CREATE, lock_res, fe);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+	}
+	ocfs_release_file_entry (fe);
+	ocfs_put_lockres (lock_res);
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_write_log */
+
+/*
+ * ocfs_write_node_log()
+ *
+ * called by: ocfs_free_extents_for_truncate(), <ocfs_delete_file_entry(),
+ *            ocfs_del_file(), ocfs_free_directory_block(),
+ *            ocfs_insert_dir_node(), ocfs_free_file_extents()
+ */
+int ocfs_write_node_log (ocfs_super * osb, ocfs_log_record * log_rec,
+			 __u32 node_num, __u32 type)
+{
+	int status = 0;
+	int tmpstat;
+	__s32 log_file_id = -1;
+	__u64 lock_id = 0;
+	__u64 file_size = 0;
+	__u64 offset = 0;
+	__u64 log_rec_size = 0;
+	__u64 alloc_size = 0;
+	ocfs_lock_res *lock_res = NULL;
+	bool log_lock = false;
+	bool lock_acq = false;
+	ocfs_file_entry *fe = NULL;
+
+	LOG_ENTRY_ARGS ("(0x%p, 0x%p, %u, %u)\n", osb, log_rec, node_num,
+			type);
+
+	fe = ocfs_allocate_file_entry ();
+	if (!fe) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto finally;
+	}
+
+	/* Get the log lock */
+	ocfs_down_sem (&(osb->log_lock), true);
+	log_lock = true;
+
+	if (type == LOG_RECOVER) {
+		log_file_id = (LOG_FILE_BASE_ID + node_num);
+		log_rec_size = osb->sect_size;
+	} else if (type == LOG_CLEANUP) {
+		log_file_id = (CLEANUP_FILE_BASE_ID + node_num);
+		log_rec_size = sizeof (ocfs_cleanup_record);
+		log_rec_size = OCFS_ALIGN (log_rec_size, osb->sect_size);
+	} else {
+		LOG_ERROR_ARGS ("logtype=%u is invalid", type);
+		goto finally;
+	}
+
+	/* Always log to the eof after taking a file lock and a log lock */
+	lock_id = (log_file_id * osb->sect_size) + osb->vol_layout.root_int_off;
+
+	status = ocfs_acquire_lock (osb, lock_id, OCFS_DLM_EXCLUSIVE_LOCK,
+				    FLAG_FILE_CREATE, &lock_res, fe);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	lock_acq = true;
+
+	file_size = fe->file_size;
+	alloc_size = fe->alloc_size;
+	offset = file_size;
+
+	if (alloc_size < (file_size + log_rec_size)) {
+		file_size += ONE_MEGA_BYTE;
+		status = ocfs_extend_system_file (osb, log_file_id, file_size, fe);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+	}
+
+	status = ocfs_write_system_file (osb, log_file_id, log_rec,
+					 log_rec_size, offset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	status = ocfs_extend_system_file (osb, log_file_id,
+					  (offset + log_rec_size), fe);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+      finally:
+	if (log_lock) {
+		ocfs_up_sem (&(osb->log_lock));
+		log_lock = false;
+	}
+
+	if (lock_acq) {
+		tmpstat =
+		    ocfs_release_lock (osb, lock_id, OCFS_DLM_EXCLUSIVE_LOCK,
+				       FLAG_FILE_CREATE, lock_res, fe);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+	}
+	ocfs_release_file_entry (fe);
+	ocfs_put_lockres (lock_res);
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_write_node_log */

Added: trunk/libocfs/Common/ocfsgenutil.c
===================================================================
--- trunk/libocfs/Common/ocfsgenutil.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/ocfsgenutil.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,54 @@
+/*
+ * ocfsgenutil.c
+ *
+ * Generic utilities
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifdef __KERNEL__
+#include <ocfs.h>
+#else
+#include <libocfs.h>
+#endif
+
+
+/* Tracing */
+#define OCFS_DEBUG_CONTEXT     OCFS_DEBUG_CONTEXT_UTIL
+
+/*
+ * ocfs_compare_qstr()
+ *
+ */
+int ocfs_compare_qstr (struct qstr * s1, struct qstr * s2)
+{
+        int s = strncmp ((const char *) s1->name, (const char *) s2->name,
+                        s1->len < s2->len ? s1->len : s2->len);
+
+        if (s != 0)
+                return s;
+        if (s1->len > s2->len)
+                return 1;
+        else if (s1->len < s2->len)
+                return -1;
+        else
+                return s;
+}				/* ocfs_compare_qstr */

Added: trunk/libocfs/Common/ocfsgenvolcfg.c
===================================================================
--- trunk/libocfs/Common/ocfsgenvolcfg.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/ocfsgenvolcfg.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,955 @@
+/* 
+ * ocfsgenvolcfg.c
+ *
+ * Auto configuration, namely, node number.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifdef __KERNEL__
+#include <ocfs.h>
+#else
+#include <libocfs.h>
+void *assert_lock (void *arg);
+#endif
+
+/* Tracing */
+#define  OCFS_DEBUG_CONTEXT  OCFS_DEBUG_CONTEXT_VOLCFG
+
+/*
+ * ocfs_worker()
+ *
+ * This function reiterates the lock on the disk from this node once
+ * it has obtained it.
+ */
+void ocfs_worker (void *Arg)
+{
+	__u32 length;
+	char *buffer;
+	int status;
+	ocfs_super *osb;
+	__u64 offset;
+	ocfs_cfg_task *cfg_task;
+
+	LOG_ENTRY ();
+
+	cfg_task = (ocfs_cfg_task *) Arg;
+
+	/* Obtain the volume for which we need to reiterate the lock */
+	osb = cfg_task->osb;
+	buffer = cfg_task->buffer;
+	length = osb->sect_size;
+	offset = cfg_task->lock_off;
+
+	/* Write the sector back */
+	status = ocfs_write_disk (osb, buffer, length, offset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		/* deliberate no exit jump here */
+	}
+
+	if (atomic_read (&osb->lock_stop)) {
+		LOG_TRACE_ARGS ("Last Lock written : %d\n", jiffies);
+		atomic_set (&osb->lock_event_woken, 1);
+		wake_up (&osb->lock_event);
+	} else {
+#ifdef USERSPACE_TOOL
+		{
+			long j = jiffies + OCFS_VOLCFG_LOCK_ITERATE;
+			while (j > jiffies) {
+				sched_yield();
+			}
+		}
+#else
+		mod_timer (&osb->lock_timer, jiffies + OCFS_VOLCFG_LOCK_ITERATE);
+#endif
+	}
+
+	LOG_EXIT ();
+	return;
+}				/* ocfs_worker */
+
+
+#ifdef USERSPACE_TOOL
+void *assert_lock (void *arg)
+{
+	ocfs_cfg_task *cfg_task = (ocfs_cfg_task *) arg;
+	ocfs_super *osb = cfg_task->osb;
+
+	while (1)
+	{
+		ocfs_worker(arg);
+		if (atomic_read (&osb->lock_event_woken))
+			return NULL;
+	}
+}
+#else
+/*
+ * ocfs_assert_lock_owned()
+ *
+ * Routine called by a timer to reiterate the disk lock.
+ */
+void ocfs_assert_lock_owned (unsigned long Arg)
+{
+	ocfs_cfg_task *cfg_task;
+
+	LOG_ENTRY ();
+
+	cfg_task = (ocfs_cfg_task *) Arg;
+
+	/* initialize the task */
+	INIT_TQUEUE (&(cfg_task->cfg_tq), ocfs_worker, cfg_task);
+
+	/* submit it */
+	schedule_task (&cfg_task->cfg_tq);
+
+	LOG_EXIT ();
+	return ;
+}				/* ocfs_assert_lock_owned */
+#endif /* USERSPACE_TOOL */
+
+
+/*
+ * ocfs_add_to_disk_config()
+ *
+ */
+int ocfs_add_to_disk_config (ocfs_super * osb, __u32 pref_node_num,
+			     ocfs_disk_node_config_info * new_disk_node)
+{
+	int status = 0;
+	__u64 offset;
+	ocfs_disk_node_config_info *disk_node = NULL;
+	__u8 *buffer = NULL;
+	__u8 *p;
+	__u32 node_num;
+	__u32 sect_size;
+	__u32 size;
+
+	LOG_ENTRY ();
+
+	sect_size = osb->sect_size;
+
+	/* Read the nodecfg info for all nodes from disk */
+	size = OCFS_VOLCFG_HDR_SECTORS * sect_size;
+	offset = osb->vol_layout.node_cfg_off + size;
+	size = osb->vol_layout.node_cfg_size - size;
+	status = ocfs_read_disk_ex (osb, (void **) &buffer, size, size, offset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	/* Check if preferred node num is available */
+	node_num = OCFS_INVALID_NODE_NUM;
+	if (pref_node_num >= 0 && pref_node_num < OCFS_MAXIMUM_NODES) {
+		p = buffer + (pref_node_num * sect_size);
+		disk_node = (ocfs_disk_node_config_info *)p;
+		if (disk_node->node_name[0] == '\0')
+			node_num = pref_node_num;
+	}
+
+	/* if not, find the first available empty slot */
+	if (node_num == OCFS_INVALID_NODE_NUM) {
+		p = buffer;
+		for (node_num = 0; node_num < OCFS_MAXIMUM_NODES; ++node_num,
+		     p += sect_size) {
+			disk_node = (ocfs_disk_node_config_info *) p;
+			if (disk_node->node_name[0] == '\0')
+				break;
+		}
+	}
+
+	/* If no free slots, error out */
+	if (node_num >= OCFS_MAXIMUM_NODES) {
+		LOG_ERROR_STR ("Unable to allocate node number as no slots " \
+			       "are available");
+		status = -ENOSPC;
+		goto finally;
+	}
+
+	/* Copy the new nodecfg into the memory buffer */
+	p = buffer + (node_num * sect_size);
+	memcpy (p, new_disk_node, sect_size);
+
+	/* Write the new node details on disk */
+	size = (node_num + OCFS_VOLCFG_HDR_SECTORS) * sect_size;
+	offset = osb->vol_layout.node_cfg_off + size;
+	disk_node = (ocfs_disk_node_config_info *) p;
+	status = ocfs_write_disk (osb, (void *) disk_node, sect_size, offset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	/* Update the nodecfg hdr on disk */
+	status = ocfs_write_volcfg_header (osb, OCFS_VOLCFG_ADD);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+      finally:
+	ocfs_safefree (buffer);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_add_to_disk_config */
+
+/*
+ * ocfs_write_volcfg_header()
+ *
+ */
+int ocfs_write_volcfg_header (ocfs_super * osb, ocfs_volcfg_op op)
+{
+	int status = 0;
+	ocfs_node_config_hdr *hdr;
+	__u8 *buffer = NULL;
+	__u64 offset;
+
+	LOG_ENTRY ();
+
+	/* Read the nodecfg header */
+	offset = osb->vol_layout.node_cfg_off;
+	status = ocfs_read_disk_ex (osb, (void **) &buffer, osb->sect_size,
+				    osb->sect_size, offset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto bail;
+	}
+
+	hdr = (ocfs_node_config_hdr *) buffer;
+
+	if (op == OCFS_VOLCFG_ADD)
+		hdr->num_nodes++;
+
+	/* Increment the seq# to trigger other nodes to re-read node cfg */
+	hdr->cfg_seq_num++;
+
+	/* Write the nodecfg header */
+	status = ocfs_write_disk (osb, (void *) hdr, osb->sect_size, offset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto bail;
+	}
+
+	/* Write the nodecfg hdr into the second sector of newcfg. */
+	/* We do so so that we can read the nodecfg hdr easily when we */
+	/* read the publish sector, for e.g. in ocfs_nm_thread() */
+	offset = osb->vol_layout.new_cfg_off + osb->sect_size;
+	status = ocfs_write_disk (osb, (void *) hdr, osb->sect_size, offset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto bail;
+	}
+
+      bail:
+	ocfs_safefree (buffer);
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_write_volcfg_header */
+
+/*
+ * ocfs_config_with_disk_lock()
+ *
+ * This function tries to obtain the lock on the disk for the volume
+ * specified. The logic for obtaining a disk lock is as follows :
+ *
+ * Read the volcfg lock sector. If it is not locked, lock it by stamping
+ * ones node number. Read the same sector after OCFS_VOLCFG_LOCK_TIME.
+ * If the contents have not been modified, the lock is ours. Retain the
+ * lock by reiterating the lock write operation every OCFS_VOLCFG_ITERATE_TIME.
+ *
+ * If the volcfg lock sector is owned by someone else, wait for
+ * OCFS_VOLCFG_LOCK_TIME and read the lock sector again. If the lock sector
+ * is owned by the same node as before attempt to break the lock as the
+ * node may have died. If however, the lock sector is now owned by someone
+ * else, wait for OCFS_VOLCFG_LOCK_TIME before repeating the entire exercise
+ * again.
+ *
+ * Returns 0 if success, < 0 if error.
+ */
+int ocfs_config_with_disk_lock (ocfs_super * osb, __u64 LockOffset, __u8 * Buffer,
+				__u32 node_num, ocfs_volcfg_op op)
+{
+	int status = 0;
+	char *rd_buf = NULL;
+	char *lock_buf = NULL;
+	bool TriedAcquire = false;
+	bool BreakLock = false;
+	ocfs_disk_lock *DiskLock;
+	ocfs_cfg_task *cfg_task = NULL;
+	__u32 sect_size;
+	__u64 lock_node_num = OCFS_INVALID_NODE_NUM;
+#ifdef USERSPACE_TOOL
+	bool thread_started = false;
+	pthread_t thread;
+#endif
+
+	LOG_ENTRY ();
+
+	sect_size = osb->sect_size;
+
+	/* Allocate buffer for reading the disk */
+	rd_buf = ocfs_malloc (osb->sect_size);
+	if (rd_buf == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto finito;
+	}
+
+	cfg_task = ocfs_malloc (sizeof (ocfs_cfg_task));
+	if (cfg_task == NULL)
+	{
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto finito;
+	}
+
+	lock_buf = ocfs_malloc (sect_size);
+	if (lock_buf == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto finito;
+	}
+
+	/* initialize cfg_task with info reqd to reiterate the volcfg lock */
+	cfg_task->osb = osb;
+	cfg_task->buffer = lock_buf;
+	cfg_task->lock_off = LockOffset;
+
+#ifndef USERSPACE_TOOL
+	/* Initialize the kernel timer */
+	init_timer(&osb->lock_timer);
+	osb->lock_timer.function = ocfs_assert_lock_owned;
+	osb->lock_timer.expires = 0;
+	osb->lock_timer.data = (unsigned long) cfg_task;
+#endif
+
+	init_waitqueue_head (&osb->lock_event);
+	atomic_set (&osb->lock_event_woken, 0);
+	atomic_set (&osb->lock_stop, 0);
+
+	while (1) {
+		/* Read the volcfg lock sector */
+		status = ocfs_read_disk (osb, rd_buf, sect_size, LockOffset);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finito;
+		}
+
+		DiskLock = (ocfs_disk_lock *) rd_buf;
+		lock_node_num = DISK_LOCK_CURRENT_MASTER(DiskLock);
+
+		if (DISK_LOCK_FILE_LOCK (DiskLock) == 0 || BreakLock) {
+			if (DISK_LOCK_FILE_LOCK (DiskLock) != 0)
+				LOG_TRACE_STR ("Try to break node config lock");
+			else
+				LOG_TRACE_STR ("Lock node config");
+
+			/* Attempt to lock volcfg */
+			DiskLock = (ocfs_disk_lock *) Buffer;
+			DISK_LOCK_CURRENT_MASTER (DiskLock) = osb->node_num;
+			DISK_LOCK_FILE_LOCK (DiskLock) = 1;
+
+			/* Write into volcfg lock sector... */
+			status = ocfs_write_disk (osb, Buffer, sect_size,
+						  LockOffset);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto finito;
+			}
+			TriedAcquire = true;
+		}
+
+		ocfs_sleep (OCFS_VOLCFG_LOCK_TIME);
+
+		/* Read the volcfg lock sector again... */
+		status = ocfs_read_disk (osb, rd_buf, sect_size, LockOffset);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finito;
+		}
+
+		/* If we tried to acquire and we still own it we take it... */
+		if ((TriedAcquire) && (memcmp (rd_buf, Buffer, sect_size) == 0)) {
+			memcpy (lock_buf, Buffer, sect_size);
+
+#ifdef USERSPACE_TOOL
+			if (!thread_started) {
+     				pthread_create(&thread, NULL, assert_lock, cfg_task);
+				thread_started=true;
+			}
+#else
+			/* Set timer to reiterate lock every few jiffies */
+			LOG_TRACE_ARGS ("Start Timer: %d\n", jiffies);
+			osb->lock_timer.expires = jiffies +
+						  OCFS_VOLCFG_LOCK_ITERATE;
+			add_timer(&osb->lock_timer);
+#endif
+
+			/* Write the config info into the disk */
+			DiskLock = (ocfs_disk_lock *) Buffer;
+			DISK_LOCK_CURRENT_MASTER (DiskLock) =
+							OCFS_INVALID_NODE_NUM;
+			DISK_LOCK_FILE_LOCK (DiskLock) = 0;
+
+			if (op == OCFS_VOLCFG_ADD)
+				status = ocfs_add_to_disk_config (osb, node_num,
+					(ocfs_disk_node_config_info *) Buffer);
+			else if (op == OCFS_VOLCFG_UPD)
+				status = ocfs_update_disk_config (osb, node_num,
+					 (ocfs_disk_node_config_info *) Buffer);
+			else
+				status = -EFAIL;
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto finito;
+			}
+			break;
+		} else {
+			DiskLock = (ocfs_disk_lock *) rd_buf;
+			if (DISK_LOCK_CURRENT_MASTER (DiskLock) == lock_node_num)
+				BreakLock = true;
+			else {
+				LOG_TRACE_ARGS ("Node config locked by node: %d\n",
+					DISK_LOCK_CURRENT_MASTER (DiskLock));
+				ocfs_sleep (OCFS_VOLCFG_LOCK_TIME);
+			}
+		}
+	}
+
+      finito:
+	ocfs_release_disk_lock (osb, LockOffset);
+#ifdef USERSPACE_TOOL
+	if (thread_started) {
+		void *ret=NULL;
+		pthread_join(thread, &ret);
+	}
+#endif
+
+	ocfs_safefree (rd_buf);
+	ocfs_safefree (lock_buf);
+	ocfs_safefree (cfg_task);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_config_with_disk_lock */
+
+/*
+ * ocfs_release_disk_lock()
+ *
+ * This function Cancels the timer to reiterate we own the disk lock and
+ * then frees it by writing the sector for the disk lock.
+ *
+ * Returns 0 if success, < 0 if error.
+ */
+int ocfs_release_disk_lock (ocfs_super * osb, __u64 LockOffset)
+{
+	int status = 0;
+	__s8 *buffer = NULL;
+	__u32 sect_size = osb->sect_size;
+
+	LOG_ENTRY ();
+
+	buffer = ocfs_malloc (sect_size);
+	if (buffer == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto finally;
+	}
+
+	/* reset lock... */
+	memset (buffer, 0, sect_size);
+
+	/* Cancel the timer so that we don't reiterate the lock anymore */
+	LOG_TRACE_STR ("Waiting for osb->lock_event");
+	atomic_set (&osb->lock_stop, 1);
+	ocfs_wait (osb->lock_event, atomic_read (&osb->lock_event_woken), 0);
+	atomic_set (&osb->lock_event_woken, 0);
+#ifndef USERSPACE_TOOL
+	del_timer_sync(&osb->lock_timer);
+#endif
+
+	/* Release the lock */
+	status = ocfs_write_disk (osb, buffer, sect_size, LockOffset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+      finally:
+	ocfs_safefree (buffer);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_release_disk_lock */
+
+/*
+ * ocfs_add_node_to_config()
+ *
+ */
+int ocfs_add_node_to_config (ocfs_super * osb)
+{
+	int status = 0;
+	ocfs_disk_node_config_info *disk;
+	void *buffer = NULL;
+	__u64 offset;
+	__u32 sect_size = osb->sect_size;
+
+	LOG_ENTRY ();
+
+	buffer = ocfs_malloc (sect_size);
+	if (buffer == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto bail;
+	} else
+		memset (buffer, 0, sect_size);
+
+	disk = (ocfs_disk_node_config_info *) buffer;
+
+	/* populate the disknodecfg info from global context */
+	ocfs_volcfg_gblctxt_to_disknode (disk);
+
+	/* Write this nodes config onto disk */
+	offset = osb->vol_layout.new_cfg_off;
+	status = ocfs_config_with_disk_lock (osb, offset, (__u8 *) disk,
+					     OcfsGlobalCtxt.pref_node_num,
+					     OCFS_VOLCFG_ADD);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto bail;
+	}
+
+	status = ocfs_chk_update_config (osb);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto bail;
+	}
+
+      bail:
+	ocfs_safefree (buffer);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_add_node_to_config */
+
+/*
+ * ocfs_disknode_to_node()
+ *
+ */
+int ocfs_disknode_to_node (ocfs_node_config_info ** node,
+			  ocfs_disk_node_config_info * disk)
+{
+	int status = 0;
+
+	LOG_ENTRY ();
+
+	if (*node == NULL) {
+		if ((*node = (ocfs_node_config_info *)
+		     ocfs_malloc (sizeof (ocfs_node_config_info))) == NULL) {
+			LOG_ERROR_STATUS (status = -ENOMEM);
+			goto bail;
+		}
+		memset (*node, 0, sizeof (ocfs_node_config_info));
+	}
+
+	strncpy ((*node)->node_name, disk->node_name, MAX_NODE_NAME_LENGTH);
+
+	memcpy((*node)->guid.guid, disk->guid.guid, GUID_LEN);
+
+	(*node)->ipc_config.type = disk->ipc_config.type;
+	(*node)->ipc_config.ip_port = disk->ipc_config.ip_port;
+	strncpy((*node)->ipc_config.ip_addr, disk->ipc_config.ip_addr,
+		MAX_IP_ADDR_LEN);
+	strncpy((*node)->ipc_config.ip_mask, disk->ipc_config.ip_mask,
+		MAX_IP_ADDR_LEN);
+
+      bail:
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_disknode_to_node */
+
+/*
+ * ocfs_update_disk_config()
+ *
+ */
+int ocfs_update_disk_config (ocfs_super * osb, __u32 node_num,
+			     ocfs_disk_node_config_info * disk)
+{
+	int status = 0;
+	__u64 offset;
+
+	LOG_ENTRY ();
+
+	/* Write the node details */
+	offset = osb->vol_layout.node_cfg_off +
+		 ((node_num + OCFS_VOLCFG_HDR_SECTORS) * osb->sect_size);
+	status = ocfs_write_disk (osb, (void *) disk, osb->sect_size, offset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	status = ocfs_write_volcfg_header (osb, OCFS_VOLCFG_UPD);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+      finally:
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_update_disk_config */
+
+/*
+ * ocfs_volcfg_gblctxt_to_disknode()
+ *
+ */
+void ocfs_volcfg_gblctxt_to_disknode(ocfs_disk_node_config_info *disk)
+{
+	ocfs_ipc_config_info *ipc;
+	ocfs_comm_info *g_ipc;
+
+	LOG_ENTRY ();
+
+	ipc = &(disk->ipc_config);
+	g_ipc = &(OcfsGlobalCtxt.comm_info);
+
+	if (OcfsGlobalCtxt.node_name)
+		strncpy (disk->node_name, OcfsGlobalCtxt.node_name,
+			 MAX_NODE_NAME_LENGTH);
+
+	memcpy(disk->guid.guid, OcfsGlobalCtxt.guid.guid, GUID_LEN);
+
+	ipc->type = g_ipc->type;
+	ipc->ip_port = g_ipc->ip_port;
+	if (g_ipc->ip_addr)
+		strncpy (ipc->ip_addr, g_ipc->ip_addr, MAX_IP_ADDR_LEN);
+	if (g_ipc->ip_mask)
+		strncpy (ipc->ip_mask, g_ipc->ip_mask, MAX_IP_ADDR_LEN);
+
+	LOG_EXIT ();
+	return ;
+}				/* ocfs_volcfg_gblctxt_to_disknode */
+
+/*
+ * ocfs_volcfg_gblctxt_to_node()
+ *
+ */
+void ocfs_volcfg_gblctxt_to_node(ocfs_node_config_info *node)
+{
+	ocfs_ipc_config_info *ipc;
+	ocfs_comm_info *g_ipc;
+
+	LOG_ENTRY ();
+
+	ipc = &(node->ipc_config);
+	g_ipc = &(OcfsGlobalCtxt.comm_info);
+
+	if (OcfsGlobalCtxt.node_name)
+		strncpy (node->node_name, OcfsGlobalCtxt.node_name,
+			 MAX_NODE_NAME_LENGTH);
+
+	memcpy(node->guid.guid, OcfsGlobalCtxt.guid.guid, GUID_LEN);
+
+	ipc->type = g_ipc->type;
+	ipc->ip_port = g_ipc->ip_port;
+	if (g_ipc->ip_addr)
+		strncpy (ipc->ip_addr, g_ipc->ip_addr, MAX_IP_ADDR_LEN);
+	if (g_ipc->ip_mask)
+		strncpy (ipc->ip_mask, g_ipc->ip_mask, MAX_IP_ADDR_LEN);
+
+	LOG_EXIT ();
+	return ;
+}				/* ocfs_volcfg_gblctxt_to_node */
+
+/*
+ * ocfs_chk_update_config()
+ *
+ */
+int ocfs_chk_update_config (ocfs_super * osb)
+{
+	int status = 0;
+	ocfs_node_config_hdr *hdr = NULL;
+	ocfs_disk_node_config_info *disk = NULL;
+	__u8 *buffer = NULL;
+	__u64 offset;
+	__s32 i;
+	__u32 sect_size = osb->sect_size;
+	__u8 *p;
+
+	LOG_ENTRY ();
+
+	/* Read in the config on the disk */
+	offset = osb->vol_layout.node_cfg_off;
+	status = ocfs_read_disk_ex (osb, (void **) &buffer,
+				    (__u32)osb->vol_layout.node_cfg_size,
+				    (__u32)osb->vol_layout.node_cfg_size, offset);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	/* 1st block in buffer is the NodeCfgHdr */
+	hdr = (ocfs_node_config_hdr *) buffer;
+
+	if (strncmp (hdr->signature, NODE_CONFIG_HDR_SIGN,
+		     NODE_CONFIG_SIGN_LEN)) {
+		LOG_ERROR_STR ("Invalid node config signature");
+		status = -EINVAL;
+		goto finally;
+	}
+
+	if  (hdr->version < NODE_MIN_SUPPORTED_VER ||
+	     hdr->version > NODE_CONFIG_VER) {
+		LOG_ERROR_ARGS ("Node config version mismatch, (%d) < minimum" \
+			        " (%d) or > current (%d)", hdr->version,
+			        NODE_MIN_SUPPORTED_VER, NODE_CONFIG_VER);
+		status = -EINVAL;
+		goto finally;
+	}
+
+	/* Exit if nodecfg on disk has remained unchanged... */
+	if ((osb->cfg_initialized) && (osb->cfg_seq_num == hdr->cfg_seq_num) &&
+	    (osb->num_cfg_nodes == hdr->num_nodes))
+		goto finally;
+
+	/* ... else refresh nodecfg in memory */
+	p = buffer + (OCFS_VOLCFG_HDR_SECTORS * sect_size);
+
+	/* Read the nodecfg for all possible nodes as there may be holes */
+	/* i.e., node numbers need not be dolled out in sequence */
+	for (i = 0; i < OCFS_MAXIMUM_NODES; i++, p += sect_size) {
+		disk = (ocfs_disk_node_config_info *) p;
+
+		if (disk->node_name[0] == '\0')
+			continue;
+
+		status = ocfs_disknode_to_node (&osb->node_cfg_info[i], disk);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+
+		/* If nodenum is set, goto next node */
+		if (osb->node_num != OCFS_INVALID_NODE_NUM)
+			continue;
+
+		/*
+		 * If node num is not set, set it if guid matches.
+		 * If guid does not match and the hostid also does not
+		 * match, goto next slot.
+		 * However if the guid does not natch but the hostid
+		 * matches, it means that the user re-ran ocfs_uid_gen
+		 * with the -r option to reclaim its node number. In
+		 * this case, allow the reclaim only if the user mounts
+		 * the volume with the reclaimid option. Else, error.
+		 */
+		if (!memcmp(&OcfsGlobalCtxt.guid.guid, disk->guid.guid,
+			    GUID_LEN)) {
+			osb->node_num = i;
+			continue;
+		}
+
+		/* If the hostid does not match, goto next... */
+		if (memcmp(&OcfsGlobalCtxt.guid.id.host_id,
+			   disk->guid.id.host_id, HOSTID_LEN))
+			continue;
+
+		/* ...else allow node to reclaim the number if reclaimid set */
+		if (osb->reclaim_id) {
+			osb->node_num = i;
+			/* Write this node's cfg with the new guid on disk */
+			status = ocfs_refresh_node_config (osb);
+			if (status < 0) {
+				LOG_ERROR_STATUS(status);
+				goto finally;
+			}
+		}
+		else {
+			LOG_ERROR_STR("Re-mount volume with the reclaimid " \
+				      "option to reclaim the node number");
+			status = -EFAIL;
+			goto finally;
+		}
+	}
+
+	osb->cfg_initialized = true;
+	osb->cfg_seq_num = hdr->cfg_seq_num;
+	osb->num_cfg_nodes = hdr->num_nodes;
+	LOG_TRACE_ARGS ("Num of configured nodes (%u)\n", osb->num_cfg_nodes);
+	IF_TRACE(ocfs_show_all_node_cfgs (osb));
+
+      finally:
+	ocfs_safefree (buffer);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_chk_update_config */
+
+/*
+ * ocfs_get_config()
+ *
+ */
+int ocfs_get_config (ocfs_super * osb)
+{
+	int status = 0;
+
+	LOG_ENTRY ();
+
+	/* Update our config info for this volume from the disk */
+	status = ocfs_chk_update_config (osb);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto bail;
+	}
+
+	if (osb->node_num == OCFS_INVALID_NODE_NUM) {
+		if (osb->reclaim_id) {
+			LOG_ERROR_STR ("unable to reclaim id");
+			status = -EINVAL;
+			goto bail;
+		}
+		status = ocfs_add_node_to_config (osb);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto bail;
+		}
+	} else {
+		if (ocfs_has_node_config_changed (osb)) {
+			status = ocfs_refresh_node_config (osb);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto bail;
+			}
+		}
+	}
+
+	LOG_TRACE_ARGS ("Node Num: %d\n", osb->node_num);
+
+      bail:
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_get_config */
+
+/*
+ * ocfs_has_node_config_changed()
+ *
+ */
+bool ocfs_has_node_config_changed (ocfs_super * osb)
+{
+	ocfs_node_config_info *node;
+	ocfs_ipc_config_info *ipc;
+	ocfs_comm_info *g_ipc;
+	bool chg = false;
+
+	LOG_ENTRY ();
+
+	node = osb->node_cfg_info[osb->node_num];
+	ipc = &(node->ipc_config);
+	g_ipc = &(OcfsGlobalCtxt.comm_info);
+
+	if (OcfsGlobalCtxt.node_name &&
+	    strncmp (node->node_name, OcfsGlobalCtxt.node_name,
+		     MAX_NODE_NAME_LENGTH))
+		chg = true;
+
+	if (!chg && ipc->type != g_ipc->type)
+		chg = true;
+
+	if (!chg && ipc->ip_port != g_ipc->ip_port)
+		chg = true;
+
+	if (!chg && g_ipc->ip_addr &&
+	    strncmp (ipc->ip_addr, g_ipc->ip_addr, MAX_IP_ADDR_LEN))
+		chg = true;
+
+	if (!chg && g_ipc->ip_mask &&
+	    strncmp (ipc->ip_mask, g_ipc->ip_mask, MAX_IP_ADDR_LEN))
+		chg = true;
+
+	LOG_EXIT_LONG (chg);
+	return chg;
+}				/* ocfs_has_node_config_changed */
+
+/*
+ * ocfs_refresh_node_config()
+ *
+ */
+int ocfs_refresh_node_config (ocfs_super * osb)
+{
+	ocfs_node_config_info *node;
+	ocfs_disk_node_config_info *disk;
+	__u64 offset;
+	__u8 *buffer = NULL;
+	int status = 0;
+
+	LOG_ENTRY ();
+
+	buffer = ocfs_malloc (osb->sect_size);
+	if (buffer == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto bail;
+	}
+
+	memset ((void *) buffer, 0, osb->sect_size);
+	disk = (ocfs_disk_node_config_info *) buffer;
+
+	/* populate the nodecfg info in disk from global context */
+	ocfs_volcfg_gblctxt_to_disknode (disk);
+
+	/* populate the nodecfg info in mem from global context */
+	node = osb->node_cfg_info[osb->node_num];
+	ocfs_volcfg_gblctxt_to_node (node);
+
+	/* Update the nodecfg on disk with the new info */
+	offset = osb->vol_layout.new_cfg_off;
+	status = ocfs_config_with_disk_lock (osb, offset, (__u8 *) disk,
+					     osb->node_num, OCFS_VOLCFG_UPD);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto bail;
+	}
+
+      bail:
+	ocfs_safefree(buffer);
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_refresh_node_config */
+
+/*
+ * ocfs_show_all_node_cfgs()
+ *
+ */
+void ocfs_show_all_node_cfgs (ocfs_super * osb)
+{
+	ocfs_node_config_info *node;
+	__u32 i;
+
+	for (i = 0; i < OCFS_MAXIMUM_NODES; i++) {
+		node = osb->node_cfg_info[i];
+
+		if (!node || node->node_name[0] == '\0')
+			continue;
+
+		LOG_TRACE_ARGS ("Node (%u) is (%s)\n", i, node->node_name);
+		LOG_TRACE_ARGS ("ip=%s, port=%d\n", node->ipc_config.ip_addr,
+				node->ipc_config.ip_port);
+	}
+
+	return;
+}				/* ocfs_show_all_node_cfgs */

Added: trunk/libocfs/Common/ocfsheartbeat.c
===================================================================
--- trunk/libocfs/Common/ocfsheartbeat.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Common/ocfsheartbeat.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,372 @@
+/*
+ * ocfsheartbeat.c
+ *
+ * Keeps track of alive nodes in the cluster.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#if !defined(USERSPACE_TOOL)
+#include <ocfs.h>
+#else
+#include <libocfs.h>
+#endif
+
+/* Tracing */
+#define OCFS_DEBUG_CONTEXT      OCFS_DEBUG_CONTEXT_HEARTBEAT
+
+/*
+ * ocfs_nm_heart_beat()
+ *
+ * @osb: ocfs super block for the volume
+ * @flag: type of heart beat
+ * @read_publish: if the publish sector needs to be re-read
+ *
+ * Updates the timestamp in the nodes publish sector.
+ *
+ * Returns 0 if success, < 0 if error.
+ */
+int ocfs_nm_heart_beat (ocfs_super * osb, __u32 flag, bool read_publish)
+{
+	ocfs_publish *publish = NULL;
+	int status = 0;
+	__u64 node_publ_off = 0;
+
+	LOG_ENTRY_ARGS ("(0x%p, %u, %s)\n", osb, flag,
+			read_publish ? "true" : "false");
+
+	if (flag & HEARTBEAT_METHOD_DISK) {
+		node_publ_off = osb->vol_layout.publ_sect_off +
+			        (osb->node_num * osb->sect_size);
+
+		if (read_publish) {
+			status = ocfs_read_force_disk_ex (osb, (void **)&publish,
+				  osb->sect_size, osb->sect_size, node_publ_off);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto finally;
+			}
+		} else {
+			publish = (ocfs_publish *)
+				(osb->cfg_prealloc +
+				 ((OCFS_VOLCFG_NEWCFG_SECTORS + osb->node_num) *
+				  osb->sect_size));
+		}
+
+		OcfsQuerySystemTime (&publish->time);
+
+		publish->hbm[osb->node_num] = osb->hbm;
+
+		spin_lock (&OcfsGlobalCtxt.comm_seq_lock);
+		publish->comm_seq_num = OcfsGlobalCtxt.comm_seq_num;
+		spin_unlock (&OcfsGlobalCtxt.comm_seq_lock);
+
+		/* Write the current time in local node's publish sector */
+		status = ocfs_write_force_disk (osb, publish, osb->sect_size,
+						node_publ_off);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+	}
+
+	if (flag & HEARTBEAT_METHOD_IPC) {
+		/* Plug this in later... */
+	}
+
+      finally:
+	if (read_publish)
+		ocfs_safefree (publish);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_nm_heart_beat */
+
+/*
+ * ocfs_nm_thread()
+ *
+ */
+int ocfs_nm_thread (ocfs_super * mount_osb)
+{
+	int status = 0;
+	__u8 *buffer = NULL;
+	ocfs_super *osb = NULL;
+	ocfs_publish *publish;
+	ocfs_publish *publish_to_vote = NULL;
+	__u32 i;
+	__u32 highest_vote_node = 0;
+	__u64 offset = 0;
+	__u32 num_nodes = 0;
+	__u32 vote_node = OCFS_INVALID_NODE_NUM;
+	int ret = 0;
+	ocfs_node_config_hdr *node_cfg_hdr = NULL;
+	__u8 *p;
+	__u64 curr_node_map;
+	__u64 curr_publ_seq;
+
+	LOG_ENTRY ();
+
+	/* For each mounted volume reiterate the time stamp on the publish sector */
+	if (!mount_osb) {
+		LOG_ERROR_STATUS (status = -EFAIL);
+		goto finally;
+	} else
+		osb = mount_osb;
+
+	/* Ensure that the volume is valid ... */
+	if (osb->obj_id.type != OCFS_TYPE_OSB)
+		goto finally;
+
+	/* ... and that it is mounted */
+	if (osb->osb_flags & OCFS_OSB_FLAGS_BEING_DISMOUNTED)
+		goto finally;
+	if (!time_after (jiffies, osb->hbt))
+		goto finally;
+
+	if (osb->vol_state == VOLUME_MOUNTED) {
+		if (osb->needs_flush) {
+			ocfs_trans_in_progress(osb);
+			if (osb->trans_in_progress == false) {
+				ocfs_commit_cache (osb, false);
+				osb->needs_flush = false;
+			}
+		}
+	}
+
+	/* lock publish to prevent overwrites from vote_req and vote_reset */
+	down (&(osb->publish_lock));
+
+	/* Get the Publish Sector start Offset */
+	offset = osb->vol_layout.new_cfg_off;
+
+	/* Read disk for Publish Sectors of all nodes */
+	status = ocfs_read_force_disk (osb, osb->cfg_prealloc, osb->cfg_len,
+				       offset);
+	if (status < 0) {
+		up (&(osb->publish_lock));
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	/* Update the timestamp on disk to indicate that it is alive */
+	ocfs_nm_heart_beat (osb, HEARTBEAT_METHOD_DISK, false);
+
+	/* release publish lock */
+	up (&(osb->publish_lock));
+
+	/* If another node was added to the config read and update the cfg */
+	node_cfg_hdr = (ocfs_node_config_hdr *) (osb->cfg_prealloc + osb->sect_size);
+
+	if ((osb->cfg_seq_num != node_cfg_hdr->cfg_seq_num) ||
+	    (osb->num_cfg_nodes != node_cfg_hdr->num_nodes)) {
+		down (&(osb->cfg_lock));
+		status = ocfs_chk_update_config (osb);
+		up (&(osb->cfg_lock));
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+	}
+
+	buffer = osb->cfg_prealloc +
+			(OCFS_VOLCFG_NEWCFG_SECTORS * osb->sect_size);
+
+	num_nodes = OCFS_MAXIMUM_NODES;
+
+	/* Refresh the publish map */
+	ocfs_update_publish_map (osb, buffer, false);
+
+	/* send signal to mount thread to continue */
+	if (atomic_read (&osb->nm_init) < OCFS_HEARTBEAT_INIT) {
+		atomic_inc (&osb->nm_init);
+	} else if (atomic_read (&osb->nm_init) == OCFS_HEARTBEAT_INIT) {
+		wake_up (&osb->nm_init_event);
+		atomic_inc (&osb->nm_init);
+	}
+
+	LOG_TRACE_ARGS ("Publish map: 0x%08x\n", LO (osb->publ_map));
+
+	/* map of local node */
+	curr_node_map = (__u64) ((__u64)1 << osb->node_num);
+	curr_publ_seq = 0;
+
+	/* Check for the highest node looking for a vote, if anybody is looking */
+	for (i = 0, p = buffer; i < num_nodes; i++, p += osb->sect_size) {
+		publish = (ocfs_publish *) p;
+
+		if (publish->time == (__u64) 0)
+			continue;
+
+		if (publish->vote != FLAG_VOTE_NODE ||
+		    !(publish->vote_map & curr_node_map))
+			continue;
+
+		LOG_TRACE_ARGS ("node(%u): vote=%d dirty=%d type=%u\n", i,
+				publish->vote, publish->dirty, publish->vote_type);
+
+		highest_vote_node = i;
+
+		/* Check if the node is alive or not */
+		if (IS_NODE_ALIVE (osb->publ_map, highest_vote_node, num_nodes)) {
+			vote_node = highest_vote_node;
+			publish_to_vote = publish;
+			curr_publ_seq = publish->publ_seq_num;
+		} else {
+			status = ocfs_recover_vol (osb, highest_vote_node);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto finally;
+			}
+		}
+	}
+
+	if ((vote_node != OCFS_INVALID_NODE_NUM) &&
+	    (vote_node != osb->node_num) &&
+	    (curr_publ_seq != osb->last_disk_seq)) {
+		publish = (ocfs_publish *)
+				(buffer + (osb->node_num * osb->sect_size));
+		if (publish->vote)
+			publish->vote = 0;
+
+		ocfs_process_vote (osb, publish_to_vote, vote_node);
+		osb->last_disk_seq = curr_publ_seq;
+	}
+	osb->hbt = 50 + jiffies;
+
+      finally:
+	LOG_EXIT_STATUS (ret);
+	return ret;
+}				/* ocfs_nm_thread() */
+
+
+/*
+ * ocfs_update_publish_map()
+ *
+ * @osb: ocfs super block for the volume
+ * @buffer: publish sectors read in the last round
+ * @first_time: if true, the buffer needs to be initialized
+ *
+ * Reads the publish sectors and compares the timestamp of each node
+ * to the one it read in the last round. As long as the timestamp keeps
+ * changing, the node is marked alive. Conversely, if the timestamp does
+ * not change over time, the node is marked dead. The function marks all
+ * the live nodes in the publishmap.
+ *
+ */
+void ocfs_update_publish_map (ocfs_super * osb, void *buffer, bool first_time)
+{
+	ocfs_publish *publish;
+	ocfs_vol_node_map *node_map;
+	__u64 curr_time = 0;
+	__u32 i;
+	__u32 num_nodes;
+	__u8 *p;
+
+	LOG_ENTRY_ARGS ("(0x%p, 0x%p, %u)\n", osb, buffer, first_time);
+
+	num_nodes = OCFS_MAXIMUM_NODES;
+	node_map = &(osb->vol_node_map);
+	OcfsQuerySystemTime (&curr_time);
+
+	/* First time thru, update buffer with timestamps for all nodes */
+	if (first_time) {
+		/* Read the last comm_seq_num */
+		p = buffer + (osb->node_num * osb->sect_size);
+		publish = (ocfs_publish *) p;
+		spin_lock (&OcfsGlobalCtxt.comm_seq_lock);
+		OcfsGlobalCtxt.comm_seq_num = publish->comm_seq_num + 10;
+		spin_unlock (&OcfsGlobalCtxt.comm_seq_lock);
+		/* Refresh local buffers */
+		for (i = 0, p = (__u8 *) buffer; i < num_nodes;
+		     i++, p += osb->sect_size) {
+			publish = (ocfs_publish *) p;
+			node_map->time[i] = publish->time;
+			node_map->scan_rate[i] = publish->hbm[i];
+			node_map->scan_time[i] = curr_time;
+		}
+		goto bail;	/* exit */
+	}
+
+	for (i = 0, p = (__u8 *) buffer; i < num_nodes;
+	    				 i++, p += osb->sect_size) {
+		publish = (ocfs_publish *) p;
+
+		/* Loop if slot is unused */
+		if (publish->time == (__u64) 0)
+			continue;
+
+		/* Check if the node is hung or not by comparing the disk */
+		/* and memory timestamp values */
+		if (node_map->time[i] == publish->time) {
+			if (IS_NODE_ALIVE(osb->publ_map, i, num_nodes)) {
+				if (atomic_read (&(node_map->dismount[i]))) {
+					node_map->miss_cnt[i] = MISS_COUNT_VALUE;
+					atomic_set (&(node_map->dismount[i]), 0);
+				} else
+					(node_map->miss_cnt[i])++;
+				if (node_map->miss_cnt[i] > MISS_COUNT_VALUE) {
+#if !defined(USERSPACE_TOOL)
+					printk ("ocfs: Removing %s (node %d) "
+						"from clustered device (%s)\n",
+						osb->node_cfg_info[i]->node_name, i,
+						osb->dev_str);
+#endif
+					UPDATE_PUBLISH_MAP (osb->publ_map, i,
+					    OCFS_PUBLISH_CLEAR, num_nodes);
+				}
+			}
+		} else {
+#if !defined(USERSPACE_TOOL)
+			if (!IS_NODE_ALIVE(osb->publ_map, i, num_nodes) &&
+			    osb->node_num != i)
+				printk ("ocfs: Adding %s (node %d) to "
+					"clustered device (%s)\n",
+				       	osb->node_cfg_info[i]->node_name, i,
+					osb->dev_str);
+#endif
+			node_map->miss_cnt[i] = 0;
+			node_map->time[i] = publish->time;
+			UPDATE_PUBLISH_MAP (osb->publ_map, i, OCFS_PUBLISH_SET,
+					    num_nodes);
+			/* Update the multiple the other node wants us to beat */
+			if ((publish->hbm[osb->node_num] != DISK_HBEAT_INVALID)
+			    && (osb->hbm > publish->hbm[osb->node_num])) {
+				/* Go to the lowest multiplier any of the nodes */
+				/* alive want us to heartbeat with. */
+				osb->hbm = publish->hbm[osb->node_num];
+
+				if (osb->hbm == 0)
+					osb->hbm = DISK_HBEAT_NO_COMM;
+
+				if (OcfsGlobalCtxt.hbm > osb->hbm)
+						OcfsGlobalCtxt.hbm = osb->hbm;
+
+				if (OcfsGlobalCtxt.hbm == 0)
+					OcfsGlobalCtxt.hbm = DISK_HBEAT_NO_COMM;
+			}
+		}
+		node_map->scan_time[i] = curr_time;
+	}
+
+      bail:
+	LOG_EXIT ();
+	return;
+}				/* ocfs_update_publish_map */

Added: trunk/libocfs/Linux/inc/ocfsbitmap.h
===================================================================
--- trunk/libocfs/Linux/inc/ocfsbitmap.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Linux/inc/ocfsbitmap.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,36 @@
+/*
+ * ocfsbitmap.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSBITMAP_H_
+#define _OCFSBITMAP_H_
+
+void ocfs_initialize_bitmap (ocfs_alloc_bm * bitmap, void *buf, __u32 sz);
+int ocfs_find_clear_bits (ocfs_alloc_bm * bitmap, __u32 numBits, __u32 offset, __u32 sysonly);
+int ocfs_count_bits (ocfs_alloc_bm * bitmap);
+void ocfs_set_bits (ocfs_alloc_bm * bitmap, __u32 start, __u32 num);
+void ocfs_clear_bits (ocfs_alloc_bm * bitmap, __u32 start, __u32 num);
+
+#endif				/* _OCFSBITMAP_H_ */

Added: trunk/libocfs/Linux/inc/ocfsdlmp.h
===================================================================
--- trunk/libocfs/Linux/inc/ocfsdlmp.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Linux/inc/ocfsdlmp.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,43 @@
+/*
+ * ocfsdlmp.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSDLMP_H_
+#define _OCFSDLMP_H_
+
+int ocfs_insert_sector_node (ocfs_super * osb, ocfs_lock_res * lock_res,
+			     ocfs_lock_res ** found_lockres);
+
+int ocfs_lookup_sector_node (ocfs_super * osb, __u64 lock_id, ocfs_lock_res ** lock_res);
+
+void ocfs_remove_sector_node (ocfs_super * osb, ocfs_lock_res * lock_res);
+
+#ifdef USERSPACE_TOOL
+void *ocfs_volume_thread (void *arg);
+#else
+int ocfs_volume_thread (void *arg);
+#endif
+
+#endif				/* _OCFSDLMP_H_ */

Added: trunk/libocfs/Linux/inc/ocfsfile.h
===================================================================
--- trunk/libocfs/Linux/inc/ocfsfile.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Linux/inc/ocfsfile.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,36 @@
+/*
+ * ocfsfile.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSFILE_H_
+#define _OCFSFILE_H_
+
+int ocfs_set_disposition_information (struct inode *dir, struct dentry *dentry);
+
+int ocfs_set_rename_information (struct inode *old_dir,
+			  struct dentry *old_dentry,
+			  struct inode *new_dir, struct dentry *new_dentry);
+
+#endif				/* _OCFSFILE_H_ */

Added: trunk/libocfs/Linux/inc/ocfshash.h
===================================================================
--- trunk/libocfs/Linux/inc/ocfshash.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Linux/inc/ocfshash.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,134 @@
+/*
+ * ocfshash.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef  _OCFSHASH_H_
+#define  _OCFSHASH_H_
+
+/* Data structures */
+typedef struct _HASHBUCKET
+{
+	void *key;
+	__u32 keylen;
+	void *val;
+	__u32 vallen;
+	struct _HASHBUCKET *next;
+}
+HASHBUCKET;
+
+typedef struct
+{
+	__u32 size;
+	__u32 mask;
+	__u32 entries;
+	__u32 inithash;
+	__u32 newbuckets;		/* Used for statistics */
+	__u32 reusedbuckets;	/* Used for statistics */
+	ocfs_sem hashlock;
+	HASHBUCKET *lastfree;
+	HASHBUCKET *freelist;
+	HASHBUCKET *buckets;
+}
+HASHTABLE;
+
+/* Function prototypes */
+int ocfs_hash_create (HASHTABLE * ht, __u32 noofbits);
+
+void ocfs_hash_destroy (HASHTABLE * ht, void (*freefn) (const void *p));
+
+int ocfs_hash_add (HASHTABLE * ht, void *key, __u32 keylen, void *val, __u32 vallen,
+		   void **found, __u32 *foundlen);
+
+int ocfs_hash_del (HASHTABLE * ht, void *key, __u32 keylen);
+
+int ocfs_hash_get (HASHTABLE * ht, void *key, __u32 keylen, void **val, __u32 * vallen);
+
+void ocfs_hash_stat (HASHTABLE * ht, char *data, __u32 datalen);
+
+#define hashsize(n)             ((__u32)1<<(n))
+#define hashmask(n)             (hashsize(n)-1)
+
+#define HASHTABLE_DESTROYED(h)  (((HASHTABLE *)h)->buckets==NULL)
+
+/*
+ * --------------------------------------------------------------------
+ * mix -- mix 3 32-bit values reversibly.
+ * For every delta with one or two bits set, and the deltas of all three
+ * high bits or all three low bits, whether the original value of a,b,c
+ * is almost all zero or is uniformly distributed.
+ * If mix() is run forward or backward, at least 32 bits in a,b,c
+ * have at least 1/4 probability of changing.
+ * If mix() is run forward, every bit of c will change between 1/3 and
+ * 2/3 of the time.  (Well, 22/100 and 78/100 for some 2-bit deltas.)
+ * mix() takes 36 machine instructions, but only 18 cycles on a superscalar
+ * machine (like a Pentium or a Sparc).  No faster mixer seems to work,
+ * that's the result of my brute-force search.  There were about 2^^68
+ * hashes to choose from.  I only tested about a billion of those.
+ * --------------------------------------------------------------------
+ * */
+#define mix(a,b,c)              \
+{                               \
+  a -= b; a -= c; a ^= (c>>13); \
+  b -= c; b -= a; b ^= (a<<8);  \
+  c -= a; c -= b; c ^= (b>>13); \
+  a -= b; a -= c; a ^= (c>>12); \
+  b -= c; b -= a; b ^= (a<<16); \
+  c -= a; c -= b; c ^= (b>>5);  \
+  a -= b; a -= c; a ^= (c>>3);  \
+  b -= c; b -= a; b ^= (a<<10); \
+  c -= a; c -= b; c ^= (b>>15); \
+}
+
+/*
+ * --------------------------------------------------------------------
+ * hash() -- hash a variable-length key into a 32-bit value
+ *   k       : the key (the unaligned variable-length array of bytes)
+ *   len     : the length of the key, counting by bytes
+ *   initval : can be any 4-byte value
+ *
+ * Returns a 32-bit value.  Every bit of the key affects every bit of
+ * the return value.  Every 1-bit and 2-bit delta achieves avalanche.
+ * About 6*len+35 instructions.
+ *
+ * The best hash table sizes are powers of 2.  There is no need to do
+ * mod a prime (mod is sooo slow!).  If you need less than 32 bits,
+ * use a bitmask.  For example, if you need only 10 bits, do
+ * h = (h & hashmask(10));
+ * In which case, the hash table should have hashsize(10) elements.
+ *
+ * If you are hashing n strings (__u8 **)k, do it like this:
+ * for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
+ *
+ * By Bob Jenkins, 1996.  bob_jenkins at burtleburtle.net.  You may use this
+ * code any way you wish, private, educational, or commercial.  It's free.
+ *
+ * See http://burtleburtle.net/bob/hash/evahash.html
+ * Use for hash table lookup, or anything where one collision in 2^^32 is
+ * acceptable.  Do NOT use for cryptographic purposes.
+ * --------------------------------------------------------------------
+ * */
+__u32 hash (__u8 * k, __u32 length, __u32 initval);
+
+#endif				/* _OCFSHASH_H_ */

Added: trunk/libocfs/Linux/inc/ocfsioctl.h
===================================================================
--- trunk/libocfs/Linux/inc/ocfsioctl.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Linux/inc/ocfsioctl.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,52 @@
+/*
+ * ocfsioctl.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSIOCTL_H_
+#define _OCFSIOCTL_H_
+
+#define  OCFS_NAME              "OCFS"
+
+int ocfs_ioctl (struct inode *inode,
+	    struct file *filp, unsigned int cmd, unsigned long arg);
+
+/* structure read by ioctl cmd */
+typedef struct _ocfs_ioc
+{
+	char name[255];		/* "OCFS" */
+	char version[255];	/* version */
+	__u16 nodenum;		/* node number */
+	char nodename[255];	/* node name */
+} ocfs_ioc;
+
+/* ioctl commands */
+#define  OCFS_IOC_MAGIC          'O'
+#define  OCFS_IOC_GETTYPE        _IOR(OCFS_IOC_MAGIC, 1, ocfs_ioc)
+
+/* OCFS_CDSL defined in ocfsvol.h */
+#define  OCFS_IOC_CDSL_MODIFY    _IOR(OCFS_IOC_MAGIC, 2, ocfs_cdsl)
+#define  OCFS_IOC_CDSL_GETINFO   _IOR(OCFS_IOC_MAGIC, 3, ocfs_cdsl)
+
+#endif				/* _OCFSIOCTL_H_ */

Added: trunk/libocfs/Linux/inc/ocfsiosup.h
===================================================================
--- trunk/libocfs/Linux/inc/ocfsiosup.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Linux/inc/ocfsiosup.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,72 @@
+/*
+ * ocfsiosup.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002, 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSIOSUP_H_
+#define _OCFSIOSUP_H_
+
+#define ocfs_write_sector(osb, buf, off)	\
+			ocfs_write_disk(osb, buf, OCFS_SECTOR_SIZE, off)
+
+#define ocfs_read_sector(osb, buf, off)		\
+			ocfs_read_disk(osb, buf, OCFS_SECTOR_SIZE, off)
+
+int LinuxWriteForceDisk (ocfs_super * osb, void *Buffer, __u32 Length,
+			 __u64 Offset, bool Cached);
+
+int LinuxReadForceDisk (ocfs_super * osb, void *Buffer, __u32 Length,
+			__u64 Offset, bool Cached);
+
+#define ocfs_write_metadata(osb, buf, len, off)		\
+ 		LinuxWriteForceDisk(osb, buf, len, off, false)
+ 
+#define ocfs_read_metadata(osb, buf, len, off)		\
+ 		LinuxReadForceDisk(osb, buf, len, off, false)
+
+#if 0	
+int ocfs_write_metadata (ocfs_super * osb, void *Buffer, __u32 Length,
+			 __u64 Offset);
+
+int ocfs_read_metadata (ocfs_super * osb, void *Buffer, __u32 Length,
+			__u64 Offset);
+#endif
+
+int ocfs_write_force_disk (ocfs_super * osb, void *Buffer, __u32 Length,
+			   __u64 Offset);
+
+int ocfs_write_disk (ocfs_super * osb, void *Buffer, __u32 Length, __u64 Offset);
+
+int ocfs_read_force_disk (ocfs_super * osb, void *Buffer, __u32 Length,
+			  __u64 Offset);
+
+int ocfs_read_force_disk_ex (ocfs_super * osb, void **Buffer, __u32 AllocLen,
+			     __u32 ReadLen, __u64 Offset);
+
+int ocfs_read_disk (ocfs_super * osb, void *Buffer, __u32 Length, __u64 Offset);
+
+int ocfs_read_disk_ex (ocfs_super * osb, void **Buffer, __u32 AllocLen,
+		       __u32 ReadLen, __u64 Offset);
+
+#endif				/* _OCFSIOSUP_H_ */

Added: trunk/libocfs/Linux/inc/ocfsipc.h
===================================================================
--- trunk/libocfs/Linux/inc/ocfsipc.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Linux/inc/ocfsipc.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,58 @@
+/*
+ * ocfsipc.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002, 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSIPC_H_
+#define _OCFSIPC_H_
+
+int ocfs_cleanup_ipc (void);    /* unused and empty */
+
+int ocfs_init_ipc (void);       /* empty */
+
+int ocfs_recv_thread (void *unused);
+
+int ocfs_init_udp (void);
+
+int ocfs_init_ipc_dlm (ocfs_protocol protocol);
+
+int ocfs_send_udp_msg (ocfs_ipc_config_info * send, void *msg, __u32 msglen,
+		       wait_queue_head_t * event);
+
+int ocfs_recv_udp_msg (ocfs_recv_ctxt * recv_ctxt);
+
+int ocfs_send_bcast (ocfs_super * osb, __u64 votemap, ocfs_dlm_msg * dlm_msg);
+
+//void ocfs_dlm_send_msg (ocfs_super * osb, ocfs_ipc_config_info * send,
+//			ocfs_dlm_msg * dlm_msg);
+
+int ocfs_init_udp_sock (struct socket **send_sock, struct socket **recv_sock);
+
+int ocfs_send_to (struct socket *sock, struct sockaddr *addr,
+		  int addrlen, char *buf, int buflen);
+
+int ocfs_recv_from (struct socket *sock, struct sockaddr *addr,
+		    int *addrlen, char *buf, int *buflen);
+
+#endif				/* _OCFSIPC_H_ */

Added: trunk/libocfs/Linux/inc/ocfsmain.h
===================================================================
--- trunk/libocfs/Linux/inc/ocfsmain.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Linux/inc/ocfsmain.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,158 @@
+/*
+ * ocfsmain.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSMAIN_H_
+#define _OCFSMAIN_H_
+
+/* Module versioning */
+#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
+
+int ocfs_find_inode (struct inode *inode, unsigned long ino, void *opaque);
+
+int ocfs_symlink_get_block (struct inode *inode,
+			long iblock, struct buffer_head *bh_result, int create);
+
+int ocfs_get_block (struct inode *inode,
+		long iblock, struct buffer_head *bh_result, int create);
+
+void ocfs_release_cached_oin (ocfs_super * osb, ocfs_inode * oin);
+
+int ocfs_initialize_mem_lists (void);
+void ocfs_free_mem_lists (void);
+int ocfs_remount (struct super_block *sb, int *flags, char *data);
+
+typedef struct _ocfs_find_inode_args
+{
+	__u64 offset;
+	ocfs_file_entry *entry;
+}
+ocfs_find_inode_args;
+
+#ifdef OCFSMAIN_PRIVATE_DECLS
+static int ocfs_parse_options (char *options, __u32 * uid, __u32 * gid,
+			       bool * cache, bool * reclaim_id);
+static struct super_block *ocfs_read_super (struct super_block *sb, void *data,
+					    int silent);
+static int __init ocfs_driver_entry (void);
+static void __exit ocfs_driver_exit (void);
+
+int ocfs_read_params(void);
+
+#ifdef OCFS_LINUX_MEM_DEBUG
+static void ocfs_memcheck (void);
+#endif
+
+static void ocfs_populate_inode (struct inode *inode, ocfs_file_entry *fe,
+				 umode_t mode, void *genptr);
+
+static void ocfs_read_inode2 (struct inode *inode, void *opaque);
+
+static void ocfs_read_inode (struct inode *inode);
+
+static struct dentry *ocfs_lookup (struct inode *dir, struct dentry *dentry);
+
+static int ocfs_statfs (struct super_block *sb, struct statfs *buf);
+
+static ssize_t ocfs_file_write (struct file *filp,
+		 const char *buf, size_t count, loff_t * ppos);
+
+static ssize_t ocfs_file_read (struct file *filp, char *buf, size_t count, loff_t * ppos);
+
+static int ocfs_readpage (struct file *file, struct page *page);
+
+static int ocfs_writepage (struct page *page);
+
+static int ocfs_prepare_write (struct file *file,
+		    struct page *page, unsigned from, unsigned to);
+
+static int ocfs_commit_write (struct file *file,
+		   struct page *page, unsigned from, unsigned to);
+
+static int ocfs_create_or_open_file (struct inode *inode,
+			  struct inode *dir,
+			  struct dentry *dentry,
+			  int mode, ocfs_file ** newofile, int dev);
+
+static int ocfs_file_open (struct inode *inode, struct file *file);
+
+static int ocfs_mknod (struct inode *dir, struct dentry *dentry, int mode, int dev);
+
+static int ocfs_mkdir (struct inode *dir, struct dentry *dentry, int mode);
+
+static int ocfs_create (struct inode *dir, struct dentry *dentry, int mode);
+
+static int ocfs_link (struct dentry *old_dentry, struct inode *dir, struct dentry *dentry);
+
+static inline int ocfs_positive (struct dentry *dentry);
+
+static int ocfs_empty (struct dentry *dentry);
+
+static int ocfs_unlink (struct inode *dir, struct dentry *dentry);
+
+static int ocfs_rename (struct inode *old_dir,
+	     struct dentry *old_dentry,
+	     struct inode *new_dir, struct dentry *new_dentry);
+
+static int ocfs_symlink (struct inode *dir, struct dentry *dentry, const char *symname);
+
+static int ocfs_file_release (struct inode *inode, struct file *file);
+
+static int ocfs_flush (struct file *file);
+
+static int ocfs_sync_file (struct file *file, struct dentry *dentry, int datasync);
+
+static void ocfs_put_super (struct super_block *sb);
+
+static int ocfs_readdir (struct file *filp, void *dirent, filldir_t filldir);
+
+static void ocfs_put_inode (struct inode *inode);
+
+static void ocfs_clear_inode (struct inode *inode);
+
+static int ocfs_setattr (struct dentry *dentry, struct iattr *attr);
+
+static int ocfs_getattr (struct dentry *dentry, struct iattr *attr);
+
+static int ocfs_dentry_revalidate (struct dentry *dentry, int flags);
+
+static void ocfs_set_exclusive_mount_flag (struct super_block *sb, int val);
+
+static ssize_t ocfs_rw_direct (int rw, struct file *filp, char *buf,
+			       size_t size, loff_t * offp);
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,10)
+static int ocfs_direct_IO (int rw,
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,20) || defined(SUSE)
+		struct file *filp,
+#else
+		struct inode *inode,
+#endif
+		struct kiobuf *iobuf, unsigned long blocknr, int blocksize);
+#endif
+
+#endif				/* OCFSMAIN_PRIVATE_DECLS */
+
+#endif				/* _OCFSMAIN_H_ */

Added: trunk/libocfs/Linux/inc/ocfsmount.h
===================================================================
--- trunk/libocfs/Linux/inc/ocfsmount.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Linux/inc/ocfsmount.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,36 @@
+/*
+ * ocfsmount.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSMOUNT_H_
+#define _OCFSMOUNT_H_
+
+int ocfs_read_disk_header (__u8 ** buffer, struct super_block *sb);
+
+int ocfs_mount_volume (struct super_block *sb, bool reclaim_id);
+
+int ocfs_dismount_volume (struct super_block *sb);
+
+#endif				/* _OCFSMOUNT_H_ */

Added: trunk/libocfs/Linux/inc/ocfsport.h
===================================================================
--- trunk/libocfs/Linux/inc/ocfsport.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Linux/inc/ocfsport.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,197 @@
+/*
+ * ocfsport.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSPORT_H_
+#define _OCFSPORT_H_
+
+
+/* timeout structure taken from Ben's aio.c */
+#ifndef USERSPACE_TOOL
+typedef struct _ocfs_timeout {
+	struct timer_list	timer;
+	int			timed_out;
+	wait_queue_head_t	wait;
+}
+ocfs_timeout;
+
+static void ocfs_timeout_func(unsigned long data)
+{
+	ocfs_timeout *to = (ocfs_timeout *)data; 
+
+	to->timed_out = 1;
+	wake_up(&to->wait);
+}
+
+static inline void ocfs_init_timeout(ocfs_timeout *to)
+{
+	init_timer(&to->timer);
+	to->timer.data = (unsigned long)to;
+	to->timer.function = ocfs_timeout_func;
+	to->timed_out = 0;
+	init_waitqueue_head(&to->wait);
+}
+
+static inline void ocfs_set_timeout(ocfs_timeout *to, __u32 timeout)
+{
+	__u32 how_long;
+
+	if (!timeout) {
+		to->timed_out = 1;
+		return ;
+	}
+
+	how_long = (timeout * HZ / 1000);
+	if (how_long < 1)
+		how_long = 1;
+
+	to->timer.expires = jiffies + how_long;
+	add_timer(&to->timer);
+}
+
+static inline void ocfs_clear_timeout(ocfs_timeout *to)
+{
+	del_timer_sync(&to->timer);
+}
+
+#define __ocfs_wait(wq, condition, timeo, ret)			\
+do {								\
+	ocfs_timeout __to;					\
+								\
+	DECLARE_WAITQUEUE(__wait, current);			\
+	DECLARE_WAITQUEUE(__to_wait, current);			\
+								\
+	ocfs_init_timeout(&__to);				\
+								\
+	if (timeo) {						\
+		ocfs_set_timeout(&__to, timeo);			\
+		if (__to.timed_out) {				\
+			ocfs_clear_timeout(&__to);		\
+		}						\
+	}							\
+								\
+	add_wait_queue(&wq, &__wait);				\
+	add_wait_queue(&__to.wait, &__to_wait);			\
+	do {							\
+		ret = 0;					\
+		set_task_state(current, TASK_INTERRUPTIBLE);	\
+		if (condition)					\
+			break;					\
+		ret = -ETIMEDOUT;				\
+		if (__to.timed_out)				\
+			break;					\
+		schedule();					\
+		if (signal_pending(current)) {			\
+			ret = -EINTR;				\
+			break;					\
+		}						\
+	} while (1);						\
+								\
+	set_task_state(current, TASK_RUNNING);			\
+	remove_wait_queue(&wq, &__wait);			\
+	remove_wait_queue(&__to.wait, &__to_wait);		\
+								\
+	if (timeo)						\
+		ocfs_clear_timeout(&__to);			\
+								\
+} while(0)
+
+#else /* USERSPACE_TOOL */
+
+/* userspace version not intended to be the same as above */
+/* timeout is ignored, waits forever until condition */
+#define __ocfs_wait(wq, condition, timeo, ret) 			\
+do {								\
+	struct timespec req, rem;				\
+	ret = 0;						\
+	memset(&rem, 0, sizeof(struct timespec));		\
+	req.tv_sec = 0;						\
+	req.tv_nsec = 10000000;	/* 10ms */			\
+	while (!(condition) && nanosleep(&req, &rem)==-1) {	\
+		req.tv_nsec=rem.tv_nsec;			\
+		rem.tv_nsec = 0;				\
+	}							\
+	if (condition)						\
+		break;						\
+} while (1)
+
+#endif  /* USERSPACE_TOOL */
+
+#define ocfs_wait(wq, condition, timeout)			\
+({								\
+        int __ret = 0;						\
+        if (!(condition))					\
+                __ocfs_wait(wq, condition, timeout, __ret);	\
+        __ret;							\
+})
+
+void ocfs_init_sem (ocfs_sem * res);
+
+bool ocfs_down_sem (ocfs_sem * res, bool wait);
+
+void ocfs_up_sem (ocfs_sem * res);
+
+int ocfs_del_sem (ocfs_sem * res);
+
+void ocfs_daemonize (char *name, int len);
+
+int ocfs_sleep (__u32 ms);
+
+void ocfs_extent_map_init (ocfs_extent_map * map);
+
+void ocfs_extent_map_destroy (ocfs_extent_map * map);
+
+__u32 ocfs_extent_map_get_count (ocfs_extent_map * map);
+
+bool ocfs_extent_map_add (ocfs_extent_map * map, __s64 virtual,
+			  __s64 physical, __s64 sectorcount);
+
+void ocfs_extent_map_remove (ocfs_extent_map * map, __s64 virtual,
+			     __s64 sectorcount);
+
+bool ocfs_extent_map_lookup (ocfs_extent_map * map, __s64 virtual,
+			     __s64 * physical, __s64 * sectorcount, __u32 * index);
+
+bool ocfs_extent_map_next_entry (ocfs_extent_map * map, __u32 runindex,
+				 __s64 * virtual, __s64 * physical,
+				 __s64 * sectorcount);
+
+void *ocfs_dbg_slab_alloc (kmem_cache_t *slab, char *file, int line);
+void ocfs_dbg_slab_free (kmem_cache_t *slab, void *m);
+
+void *ocfs_linux_dbg_alloc (int Size, char *file, int line);
+void ocfs_linux_dbg_free (const void *Buffer);
+
+bool ocfs_linux_get_inode_offset (struct inode *inode, __u64 * off,
+				  ocfs_inode ** oin);
+bool ocfs_linux_get_dir_entry_offset (ocfs_super * osb, __u64 * off,
+				      __u64 parentOff, struct qstr * fileName,
+				      ocfs_file_entry ** fileEntry);
+
+void ocfs_flush_cache (ocfs_super * osb);
+
+bool ocfs_purge_cache_section (ocfs_inode * oin, __u64 * file_off, __u32 Length);
+
+#endif				/* _OCFSPORT_H_ */

Added: trunk/libocfs/Linux/inc/ocfsproc.h
===================================================================
--- trunk/libocfs/Linux/inc/ocfsproc.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Linux/inc/ocfsproc.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,81 @@
+/*
+ * ocfsproc.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002, 2003 Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Sunil Mushran, Manish Singh, Wim Coekaerts
+ */
+
+#ifndef _OCFSPROC_H_
+#define _OCFSPROC_H_
+
+int ocfs_proc_init (void);
+
+void ocfs_proc_deinit (void);
+
+void ocfs_proc_add_volume (ocfs_super * osb);
+
+void ocfs_proc_remove_volume (ocfs_super * osb);
+
+#ifdef OCFSPROC_PRIVATE_DECLS
+static int ocfs_proc_calc_metrics (char *page,
+		     char **start, off_t off, int count, int *eof, int len);
+
+#ifdef OCFS_LINUX_MEM_DEBUG
+static int ocfs_proc_memallocs (char *page,
+		   char **start, off_t off, int count, int *eof, void *data);
+#endif
+
+static int ocfs_proc_globalctxt(char *page, 
+		char **start, off_t off, int count, int *eof, void *data);
+
+static int ocfs_proc_dlm_stats(char *page, char **start, off_t off,
+			       int count, int *eof, void *data);
+
+static int ocfs_proc_version (char *page,
+		 char **start, off_t off, int count, int *eof, void *data);
+
+static int ocfs_proc_nodenum (char *page,
+		 char **start, off_t off, int count, int *eof, void *data);
+
+static int ocfs_proc_nodename (char *page,
+		  char **start, off_t off, int count, int *eof, void *data);
+
+static int ocfs_proc_mountpoint (char *page,
+		    char **start, off_t off, int count, int *eof, void *data);
+
+static int ocfs_proc_statistics (char *page,
+		    char **start, off_t off, int count, int *eof, void *data);
+
+static int ocfs_proc_hash_stats (char *page,
+		  char **start, off_t off, int count, int *eof, void *data);
+
+static int ocfs_proc_device (char *page, char **start, off_t off,
+			     int count, int *eof, void *data);
+
+static int ocfs_proc_lock_type_stats (char *page, char **start, off_t off,
+				      int count, int *eof, void *data);
+
+static int ocfs_proc_nodes (char *page, char **start, off_t off,
+			    int count, int *eof, void *data);
+
+#endif				/* OCFSPROC_PRIVATE_DECLS */
+
+#endif				/* _OCFSPROC_H_ */

Added: trunk/libocfs/Linux/ocfsbitmap.c
===================================================================
--- trunk/libocfs/Linux/ocfsbitmap.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Linux/ocfsbitmap.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,163 @@
+/*
+ * ocfsbitmap.c
+ *
+ * Bitmap infrastructure code
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#if defined(__KERNEL__)
+#include  <ocfs.h>
+#else
+#include  <libocfs.h>
+#endif
+
+/* Tracing */
+#define OCFS_DEBUG_CONTEXT  OCFS_DEBUG_CONTEXT_PORT
+
+#define BITCOUNT(x)     (((BX_(x)+(BX_(x)>>4)) & 0x0F0F0F0F) % 255)
+#define BX_(x)          ((x) - (((x)>>1)&0x77777777) \
+		             - (((x)>>2)&0x33333333) \
+			     - (((x)>>3)&0x11111111))
+
+/*
+ * ocfs_initialize_bitmap()
+ *
+ */
+void ocfs_initialize_bitmap (ocfs_alloc_bm * bitmap, void *buf, __u32 sz)
+{
+	LOG_ENTRY ();
+
+	bitmap->buf = buf;
+	bitmap->size = sz;
+	bitmap->failed = 0;
+	bitmap->ok_retries = 0;
+
+	LOG_EXIT ();
+	return;
+}				/* ocfs_initialize_bitmap */
+
+/*
+ * ocfs_find_clear_bits()
+ *
+ * sysonly is passed # bits in bitmap that are rserved for system file space
+ * in case we have a disk full.
+ */
+int ocfs_find_clear_bits (ocfs_alloc_bm * bitmap, __u32 numBits, __u32 offset, __u32 sysonly)
+{
+	__u32 next_zero, off, count, size, first_zero = -1; 
+	void *buffer;
+
+	LOG_ENTRY ();
+
+	buffer = bitmap->buf;
+	size = bitmap->size - sysonly;
+	count = 0;
+	off = offset;
+
+	while ((size - off + count >= numBits) &&
+	       (next_zero = find_next_zero_bit (buffer, size, off)) != size) {
+                if (next_zero >= bitmap->size - sysonly)
+                    break;
+
+		if (next_zero != off) {
+			first_zero = next_zero;
+			off = next_zero + 1;
+			count = 0;
+		} else {
+			off++;
+			if (count == 0)
+				first_zero = next_zero;
+		}
+
+		count++;
+
+		if (count == numBits)
+			goto bail;
+	}
+	first_zero = -1;
+
+      bail:
+	if (first_zero != -1 && first_zero > bitmap->size) {
+		LOG_ERROR_ARGS("um... first_zero>bitmap->size (%d > %d)",
+			       first_zero, bitmap->size);
+		first_zero = -1;
+	}
+	LOG_EXIT_LONG (first_zero);
+	return first_zero;
+}				/* ocfs_find_clear_bits */
+
+/*
+ * ocfs_count_bits()
+ *
+ */
+int ocfs_count_bits (ocfs_alloc_bm * bitmap)
+{
+	__u32 size, count = 0, off = 0;
+	unsigned char tmp;
+	__u8 *buffer;
+
+	LOG_ENTRY ();
+
+	buffer = bitmap->buf;
+
+	size = (bitmap->size >> 3);
+
+	while (off < size) {
+		memcpy (&tmp, buffer, 1);
+		count += BITCOUNT (tmp);
+		off++;
+		buffer++;
+	}
+
+	LOG_EXIT_ULONG (count);
+	return count;
+}				/* ocfs_count_bits */
+
+/*
+ * ocfs_set_bits()
+ *
+ */
+void ocfs_set_bits (ocfs_alloc_bm * bitmap, __u32 start, __u32 num)
+{
+	LOG_ENTRY ();
+
+	while (num--)
+		set_bit (start++, bitmap->buf);
+
+	LOG_EXIT ();
+	return;
+}				/* ocfs_set_bits */
+
+/*
+ * ocfs_clear_bits()
+ *
+ */
+void ocfs_clear_bits (ocfs_alloc_bm * bitmap, __u32 start, __u32 num)
+{
+	LOG_ENTRY ();
+
+	while (num--)
+		clear_bit (start++, bitmap->buf);
+
+	LOG_EXIT ();
+	return;
+}				/* ocfs_clear_bits */

Added: trunk/libocfs/Linux/ocfsdlm.c
===================================================================
--- trunk/libocfs/Linux/ocfsdlm.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Linux/ocfsdlm.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,225 @@
+/*
+ * ocfsdlm.c
+ *
+ * Allows one dlm thread per mounted volume instead of one
+ * for all volumes.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifdef __KERNEL__
+#include <ocfs.h>
+#else
+#include <libocfs.h>
+#endif
+
+
+/* Tracing */
+#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_NM
+
+/*
+ * ocfs_insert_sector_node()
+ *
+ */
+int ocfs_insert_sector_node (ocfs_super * osb, ocfs_lock_res * lock_res,
+			     ocfs_lock_res ** found_lock_res)
+{
+	int status = 0;
+	__u32 tmp;
+
+	LOG_ENTRY_ARGS ("(0x%p, 0x%p)\n", osb, lock_res);
+
+	if (HASHTABLE_DESTROYED (&(osb->root_sect_node))) {
+		LOG_TRACE_STATUS (status = -EFAIL);
+		goto bail;
+	}
+
+	if (lock_res->signature != 0x55AA) {
+		LOG_ERROR_STATUS (status = -EFAIL);
+		goto bail;
+	}
+
+	if (!ocfs_hash_add (&(osb->root_sect_node), &(lock_res->sector_num),
+			    sizeof (__u64), lock_res, sizeof (ocfs_lock_res *),
+			    (void **)found_lock_res, &tmp)) {
+		LOG_ERROR_STATUS(status = -EFAIL);
+		goto bail;
+	}
+
+	if (*found_lock_res) {
+		ocfs_get_lockres (*found_lock_res);
+		LOG_TRACE_ARGS ("isn: fres=0x%p, ref=%d, lid=%u.%u\n",
+				*found_lock_res,
+				atomic_read (&((*found_lock_res)->lr_ref_cnt)),
+				HILO((*found_lock_res)->sector_num));
+	}
+	else {
+		ocfs_get_lockres (lock_res);
+		LOG_TRACE_ARGS ("isn: lres=0x%p, ref=%d, lid=%u.%u\n", lock_res,
+				atomic_read (&lock_res->lr_ref_cnt),
+				HILO(lock_res->sector_num));
+	}
+
+      bail:
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_insert_sector_node */
+
+/*
+ * ocfs_lookup_sector_node()
+ *
+ */
+int ocfs_lookup_sector_node (ocfs_super * osb, __u64 lock_id, ocfs_lock_res ** lock_res)
+{
+	int status = 0;
+	__u32 len = 0;
+
+	LOG_ENTRY_ARGS ("(0x%p, %u.%u, 0x%p)\n", osb, HI (lock_id),
+			LO (lock_id), lock_res);
+
+	if (HASHTABLE_DESTROYED (&(osb->root_sect_node))) {
+		status = -EFAIL;
+		LOG_TRACE_STATUS (status);
+		goto bail;
+	}
+
+	if (ocfs_hash_get (&(osb->root_sect_node), &(lock_id), sizeof (__u64),
+			 (void **) lock_res, &len)) {
+		if (len != sizeof (ocfs_lock_res *)) {
+			LOG_ERROR_STATUS (status = -EFAIL);
+			goto bail;
+		}
+
+		if ((*lock_res)->signature != 0x55AA) {
+			LOG_ERROR_STATUS (status = -EFAIL);
+			goto bail;
+		}
+
+		ocfs_get_lockres (*lock_res);
+		LOG_TRACE_ARGS ("lsn: lid=%u.%u, lres=0x%p, ref=%d\n",
+				HILO(lock_id), *lock_res,
+				atomic_read (&((*lock_res)->lr_ref_cnt)));
+	} else
+		status = -ENOENT;
+
+
+      bail:
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_lookup_sector_node */
+
+/*
+ * ocfs_remove_sector_node()
+ *
+ */
+void ocfs_remove_sector_node (ocfs_super * osb, ocfs_lock_res * lock_res)
+{
+	LOG_ENTRY_ARGS ("(0x%p, 0x%p)\n", osb, lock_res);
+
+	if (HASHTABLE_DESTROYED (&(osb->root_sect_node))) {
+		LOG_TRACE_STATUS (-EFAIL);
+		goto bail;
+	}
+
+	if (lock_res->signature != 0x55AA) {
+		LOG_ERROR_STATUS (-EFAIL);
+		goto bail;
+	}
+
+	LOG_TRACE_ARGS ("rsn: lres=0x%p, ref=%d, lid=%u.%u\n", lock_res,
+			atomic_read (&lock_res->lr_ref_cnt),
+			HILO(lock_res->sector_num));
+
+	ocfs_hash_del (&(osb->root_sect_node), &(lock_res->sector_num),
+		       sizeof (__u64));
+
+	ocfs_put_lockres (lock_res);
+
+      bail:
+	LOG_EXIT ();
+	return ;
+}				/* ocfs_remove_sector_node */
+
+/*
+ * ocfs_volume_thread()
+ * 
+ * Called by OcfsMountVolume(). This function is executed as a kernel thread
+ * for each mounted ocfs volume.
+ */
+#ifdef USERSPACE_TOOL
+void *ocfs_volume_thread (void *arg)
+#else
+int  ocfs_volume_thread (void *arg)
+#endif
+
+{
+	ocfs_super *osb;
+	char proc[16];
+	int status = 0;
+	int flush_counter = 0;
+
+	LOG_ENTRY ();
+
+	osb = (ocfs_super *) arg;
+
+	sprintf (proc, "ocfsnm-%d", osb->osb_id);
+	ocfs_daemonize (proc, strlen(proc));
+
+#ifdef USERSPACE_TOOL
+	osb->dlm_task->thread = pthread_self();
+#else
+	osb->dlm_task = current;
+#endif
+
+	/* The delay changes based on multiplier */
+	while (!(OcfsGlobalCtxt.flags & OCFS_FLAG_SHUTDOWN_VOL_THREAD) &&
+	       !(osb->osb_flags & OCFS_OSB_FLAGS_BEING_DISMOUNTED)) {
+
+		if (OcfsGlobalCtxt.hbm == 0)
+			OcfsGlobalCtxt.hbm = DISK_HBEAT_NO_COMM;
+
+		ocfs_sleep (OCFS_NM_HEARTBEAT_TIME);
+
+		if ((OcfsGlobalCtxt.flags & OCFS_FLAG_SHUTDOWN_VOL_THREAD) ||
+		    (osb->osb_flags & OCFS_OSB_FLAGS_BEING_DISMOUNTED))
+			break;
+
+		status = ocfs_nm_thread (osb);
+		if (status < 0) {
+			if (osb->osb_flags & OCFS_OSB_FLAGS_BEING_DISMOUNTED)
+				break;
+		}
+
+		/* do a syncdev every 2 mins currently that is 500ms per cycle */
+		if (flush_counter++ == 240) {
+			fsync_no_super (osb->sb->s_dev);
+			flush_counter = 0;
+		}
+	}
+	
+	complete (&(osb->complete));
+	LOG_EXIT_LONG (0);
+#ifdef USERSPACE_TOOL
+	return NULL;
+#else
+	return 0;
+#endif
+}				/* ocfs_volume_thread */

Added: trunk/libocfs/Linux/ocfsfile.c
===================================================================
--- trunk/libocfs/Linux/ocfsfile.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Linux/ocfsfile.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,369 @@
+/*
+ * ocfsfile.c
+ *
+ * 
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifdef __KERNEL__
+#include <ocfs.h>
+#else
+#include <libocfs.h>
+#endif
+
+/* Tracing */
+#define OCFS_DEBUG_CONTEXT      OCFS_DEBUG_CONTEXT_FILEINFO
+
+/*
+ * ocfs_set_disposition_information()
+ *
+ * Called during file deletion. It checks for the attributes and looks up
+ * in the OIN list if the file is present. If it finds the file, it deletes
+ * the partition on ths disk and also removes the OIN from the list.
+ */
+int ocfs_set_disposition_information (struct inode *dir, struct dentry *dentry)
+{
+	int status = 0;
+	bool main_resAcquired = false;
+	ocfs_inode *OIN = NULL;
+	ocfs_super *osb = NULL;
+	struct inode *inode;
+	__u64 parentOff, fileOff;
+
+	LOG_ENTRY ();
+
+	if (!dentry->d_inode) {
+		LOG_ERROR_STATUS (status = -EFAIL);
+		goto finally;
+	}
+	inode = dentry->d_inode;
+	osb = ((ocfs_super *)(dir->i_sb->u.generic_sbp));
+	OCFS_ASSERT(IS_VALID_OSB(osb));
+
+	if (inode_data_is_oin (inode)) {
+		OIN = ((ocfs_inode *)inode->u.generic_ip);
+		if (OIN == NULL) {
+			LOG_ERROR_STATUS (status = -EFAIL);
+			goto finally;
+		}
+		OCFS_ASSERT(IS_VALID_OIN(OIN));
+
+		if (OIN->open_hndl_cnt > 0) {
+			LOG_TRACE_STR ("Cannot remove an open file");
+			status = -EBUSY;
+			goto finally;
+		}
+
+		ocfs_down_sem (&(OIN->main_res), true);
+		main_resAcquired = true;
+
+		/*
+		   ** Check if the user wants to delete the file or not delete the file.
+		   ** Do some checking to see if the file can even be deleted.
+		 */
+		if (OIN->oin_flags & OCFS_OIN_DELETE_ON_CLOSE) {
+			LOG_TRACE_STR ("OCFS_OIN_DELETE_ON_CLOSE set");
+			goto finally;
+		}
+
+		if (OIN->oin_flags & OCFS_OIN_ROOT_DIRECTORY) {
+			LOG_TRACE_STR ("Cannot delete the root directory");
+			status = -EPERM;
+			goto finally;
+		}
+
+		OCFS_SET_FLAG (OIN->oin_flags, OCFS_OIN_DELETE_ON_CLOSE);
+
+		if (main_resAcquired) {
+			ocfs_up_sem (&(OIN->main_res));
+			main_resAcquired = false;
+		}
+
+	}
+
+	/* Call CreateModify with delete flag to free up the bitmap etc. */
+	if (!ocfs_linux_get_inode_offset (dir, &parentOff, NULL)) {
+		LOG_ERROR_STATUS (status = -ENOENT);
+		goto finally;
+	}
+
+	if (S_ISDIR (inode->i_mode)) {
+		if (!ocfs_linux_get_dir_entry_offset (osb, &fileOff, parentOff,
+						      &(dentry->d_name), NULL)) {
+			LOG_ERROR_STATUS (status = -ENOENT);
+		}
+	} else {
+		if (!ocfs_linux_get_inode_offset (inode, &fileOff, NULL)) {
+			LOG_ERROR_STATUS (status = -ENOENT);
+		}
+	}
+
+	if (fileOff != -1)
+		status = ocfs_create_modify_file (osb, parentOff, NULL, NULL, 0,
+				  &fileOff, FLAG_FILE_DELETE, NULL, NULL);
+	if (status < 0) {
+		if (status != -ENOTEMPTY && status != -EPERM &&
+		    status != -EBUSY && status != -EINTR)
+			LOG_ERROR_STATUS(status);
+		if (OIN) {
+			ocfs_down_sem (&(OIN->main_res), true);
+			OCFS_CLEAR_FLAG (OIN->oin_flags,
+				       OCFS_OIN_DELETE_ON_CLOSE);
+			OCFS_CLEAR_FLAG (OIN->oin_flags, OCFS_OIN_IN_USE);
+			ocfs_up_sem (&(OIN->main_res));
+		}
+		goto finally;
+	}
+
+	if (OIN)
+		ocfs_release_cached_oin (osb, OIN);
+
+      finally:
+	if (main_resAcquired) {
+		ocfs_up_sem (&(OIN->main_res));
+		main_resAcquired = false;
+	}
+
+	LOG_EXIT_STATUS (status);
+	return (status);
+}				/* ocfs_set_disposition_information */
+
+/*
+ * ocfs_set_rename_information()
+ *
+ */
+int ocfs_set_rename_information (struct inode *old_dir,
+			  struct dentry *old_dentry,
+			  struct inode *new_dir, struct dentry *new_dentry)
+{
+	int status = 0;
+	ocfs_inode *oldOIN = NULL;
+	ocfs_file_entry *newfe = NULL;
+	ocfs_file_entry *oldfe = NULL;
+	__u64 oldOffset;
+	__u64 newDirOff;
+	__u64 oldDirOff;
+	ocfs_super *osb = NULL;
+	bool DeleteTargetOin = false;
+        __u64 t;
+	ocfs_inode *newOIN = NULL;
+
+	LOG_ENTRY ();
+
+	newfe = ocfs_allocate_file_entry ();
+	if (newfe == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto finally;
+	}
+
+	oldfe = ocfs_allocate_file_entry ();
+	if (oldfe == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto finally;
+	}
+
+	osb = ((ocfs_super *)(old_dir->i_sb->u.generic_sbp));
+	OCFS_ASSERT(IS_VALID_OSB(osb));
+
+	/* old parent dir offset */
+	if (!ocfs_linux_get_inode_offset (old_dir, &oldDirOff, NULL)) {
+		LOG_ERROR_STATUS (status = -ENOENT);
+		goto finally;
+	}
+
+	/* old file offset */
+	if (!ocfs_linux_get_inode_offset (old_dentry->d_inode, &oldOffset,
+					  &oldOIN)) {
+		LOG_ERROR_STATUS (status = -ENOENT);
+		goto finally;
+	}
+
+	if (S_ISDIR (old_dentry->d_inode->i_mode)) {
+		/* overwrite oldOffset to get ptr to OCFS_FILE_ENTRY not DIR_NODE */
+		if (!ocfs_linux_get_dir_entry_offset (osb, &oldOffset,
+				      oldDirOff, &(old_dentry->d_name), NULL)) {
+			LOG_ERROR_STATUS (status = -ENOENT);
+			goto finally;
+		}
+	}
+
+	if (oldOIN) {
+		if (oldOIN->open_hndl_cnt != 0) {
+			status = -EBUSY;
+			goto finally;
+		}
+	}
+
+	/* new parent dir offset */
+	if (inode_data_is_oin (new_dir))
+		newDirOff = ((ocfs_inode *)new_dir->u.generic_ip)->dir_disk_off;
+	else
+		newDirOff = GET_INODE_OFFSET (new_dir);
+
+	/* Don't ever take the main resource for the OIN before this as */
+	/* Locking hierarchy will be broken */
+	if (new_dentry->d_inode != NULL &&
+	    inode_data_is_oin (new_dentry->d_inode)) {
+		/* overwriting an existing inode */
+		newOIN = ((ocfs_inode *)new_dentry->d_inode->u.generic_ip);
+		OCFS_ASSERT(IS_VALID_OIN(newOIN));
+
+		if (!(newOIN->oin_flags & OCFS_OIN_IN_TEARDOWN) &&
+		    !(newOIN->oin_flags & OCFS_OIN_DELETE_ON_CLOSE)) {
+			/* OIN exists and it's not marked for deletion! */
+			ocfs_down_sem (&(newOIN->main_res), true);
+			OCFS_SET_FLAG (newOIN->oin_flags, OCFS_OIN_IN_USE);
+			status = ocfs_verify_update_oin (osb, newOIN);
+			if (status < 0)
+				LOG_ERROR_STATUS (status);
+			ocfs_up_sem (&(newOIN->main_res));
+			DeleteTargetOin = true;
+		}
+	}
+
+	status = ocfs_find_files_on_disk (osb, newDirOff,
+				  &(new_dentry->d_name), newfe, NULL);
+
+	if ((status < 0) && (status != -ENOENT)) {
+		/* If we cannot find the file specified we should just */
+		/* return the error... */
+		LOG_ERROR_STATUS (status);
+		goto finally;
+	}
+
+	ocfs_start_trans (osb);
+
+	if (status >= 0) {
+		/* Try and delete the file we found. */
+		/* Call CreateModify with delete flag as we need to free up */
+		/* the bitmap etc. */
+		status = ocfs_del_file (osb, newDirOff, FLAG_RESET_VALID, newfe->this_sector);
+
+		if (status < 0) {
+			/* Delete this file entry, createmodify will create a new */
+			/* one with the changed attributes. */
+			/* This is dangerous as we can potentially fail in */
+			/* CreateModify and we have no file left?? */
+			/* TODO we should make this transactional such that */
+			/* either we get the new file or the old file stays. */
+			/* Also, we need to ensure nobdy has the file open currently. */
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+		// Delete the Oin if one exists
+		if (DeleteTargetOin) {
+			ocfs_release_cached_oin (osb, newOIN);
+			ocfs_release_oin (newOIN, true);
+		}
+	}
+
+	if (old_dir != new_dir) {
+		/* Delete the file Entry only on the source directory */
+
+		LOG_TRACE_STR ("Source & Target Directories are different");
+
+		status = ocfs_read_file_entry (osb, oldfe, oldOffset);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+
+		status = ocfs_del_file (osb, oldDirOff, FLAG_DEL_NAME, oldOffset);
+		if (status < 0) {
+			if (status != -ENOTEMPTY && status != -EINTR)
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+
+		oldfe->sync_flags &= ~OCFS_SYNC_FLAG_VALID;
+                strncpy(oldfe->filename, new_dentry->d_name.name, new_dentry->d_name.len);
+                oldfe->filename[new_dentry->d_name.len] = '\0';
+		oldfe->filename_len = new_dentry->d_name.len;
+
+		OcfsQuerySystemTime (&t);
+
+		/* Initialize the lock state */
+
+		// DISK_LOCK_SEQNUM(oldfe) = changeSeqNum;
+		DISK_LOCK_CURRENT_MASTER (oldfe) = osb->node_num;
+		DISK_LOCK_FILE_LOCK (oldfe) = OCFS_DLM_ENABLE_CACHE_LOCK;
+		DISK_LOCK_LAST_WRITE (oldfe) = t;
+		DISK_LOCK_LAST_READ (oldfe) = t;
+		DISK_LOCK_READER_NODE (oldfe) = osb->node_num;
+		DISK_LOCK_WRITER_NODE (oldfe) = osb->node_num;
+		oldfe->modify_time = CURRENT_TIME;
+		// oldfe->create_time = t;
+
+		status = ocfs_create_file (osb, newDirOff, oldfe);
+		if (status < 0) {
+			if (status != -EINTR)
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+
+		status = ocfs_commit_trans (osb, osb->curr_trans_id);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+
+		if (oldOIN) {
+			// OCFS_SET_FLAG (oldOIN->oin_flags, OCFS_OIN_DELETE_ON_CLOSE);
+			ocfs_release_cached_oin (osb, oldOIN);
+			ocfs_release_oin (oldOIN, true);
+			if (new_dentry->d_inode)
+				fsync_inode_buffers(old_dentry->d_inode);
+		}
+		/* move the inode offset over to the new entry */
+		if (S_ISDIR (old_dentry->d_inode->i_mode)) {
+		SET_INODE_OFFSET (old_dentry->d_inode, oldfe->extents[0].disk_off);
+		} else {
+		SET_INODE_OFFSET (old_dentry->d_inode, oldfe->this_sector);
+		}
+
+	} else {
+		/* Write the new file name to disk */
+		LOG_TRACE_STR ("Source & Target Directories are same");
+		status = ocfs_rename_file (osb, oldDirOff, &(new_dentry->d_name), oldOffset);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+
+		status = ocfs_commit_trans (osb, osb->curr_trans_id);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
+	}
+
+      finally:
+	if (status < 0 && osb->trans_in_progress)
+		ocfs_abort_trans (osb, osb->curr_trans_id);
+	if (newfe)
+		ocfs_release_file_entry (newfe);
+	if (oldfe)
+		ocfs_release_file_entry (oldfe);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_set_rename_information */

Added: trunk/libocfs/Linux/ocfshash.c
===================================================================
--- trunk/libocfs/Linux/ocfshash.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Linux/ocfshash.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,512 @@
+/*
+ * ocfshash.c
+ *
+ * Allows for creation and destruction of a hash table which one
+ * can use to read, write and delete data.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifdef __KERNEL__
+#include <ocfs.h>
+#else
+#include <libocfs.h>
+#endif
+
+
+/* Tracing */
+#define OCFS_DEBUG_CONTEXT      OCFS_DEBUG_CONTEXT_HASH
+
+/*
+ * ocfs_hash_create()
+ *
+ */
+int ocfs_hash_create (HASHTABLE *ht, __u32 noofbits)
+{
+	int ret = 0;
+	__u32 size = 0;
+
+	LOG_ENTRY ();
+
+	if (noofbits > 32 || noofbits < 1) {
+		LOG_ERROR_STR ("Error in noofbits");
+		goto bail;
+	}
+
+	ht->size = hashsize (noofbits);
+	ht->mask = hashmask (noofbits);
+	ht->inithash = 0x10325476;
+	ht->entries = 0;
+	ht->newbuckets = 0;
+	ht->reusedbuckets = 0;
+	ht->freelist = NULL;
+	ht->lastfree = NULL;
+
+	ocfs_init_sem (&(ht->hashlock));
+
+	size = ht->size * sizeof (HASHBUCKET);
+	ht->buckets = (HASHBUCKET *) ocfs_malloc (size);
+	if (!ht->buckets) {
+		LOG_ERROR_ARGS ("unable to allocate %u bytes of memory", size);
+		goto bail;
+	}
+
+	memset (ht->buckets, 0, (ht->size * sizeof (HASHBUCKET)));
+	ret = 1;
+
+      bail:
+	LOG_EXIT_LONG (ret);
+	return ret;
+}				/* ocfs_hash_create */
+
+/*
+ * ocfs_hash_destroy()
+ *
+ * @ht: ptr to the hash table
+ * @freefn: if not null, uses function to free bucket->val
+ *
+ */
+void ocfs_hash_destroy (HASHTABLE *ht, void (*freefn) (const void *p))
+{
+	HASHBUCKET *bucket;
+	HASHBUCKET *nxtbucket;
+	__u32 slot;
+
+	LOG_ENTRY ();
+
+	if (!ht || !ht->buckets)
+		goto bail;
+
+	if (ht->buckets) {
+		for (slot = 0; slot < ht->size; slot++) {
+			if (freefn) {
+				bucket = &(ht->buckets[slot]);
+				if (bucket->key && bucket->val)
+					freefn (bucket->val);
+			}
+
+			bucket = ht->buckets[slot].next;
+			while (bucket) {
+				if (freefn && bucket->key && bucket->val)
+					freefn (bucket->val);
+				nxtbucket = bucket->next;
+				ocfs_safefree (bucket);
+				bucket = nxtbucket;
+			}
+		}
+	}
+
+	bucket = ht->freelist;
+	while (bucket) {
+		nxtbucket = bucket->next;
+		ocfs_safefree (bucket);
+		bucket = nxtbucket;
+	}
+
+	ocfs_safefree (ht->buckets);
+	ht->buckets = NULL;
+
+      bail:
+	LOG_EXIT ();
+	return;
+}				/* ocfs_hash_destroy */
+
+/*
+ * ocfs_hash_add()
+ *
+ * @ht: ptr to the hash table
+ * @key: key
+ * @keylen: length of key
+ * @val: value
+ * @vallen: length of value
+ *
+ */
+int ocfs_hash_add (HASHTABLE * ht, void *key, __u32 keylen, void *val, __u32 vallen,
+		   void **found, __u32 *foundlen)
+{
+	HASHBUCKET *bucket;
+	HASHBUCKET *prvbucket = NULL;
+	HASHBUCKET *lastbucket;
+	__u32 slot;
+	int ret = 1;
+	int lockacqrd = false;
+
+	LOG_ENTRY ();
+
+	if (!ht || !ht->buckets) {
+		ret = 0;
+		goto bail;
+	}
+
+	*found = NULL;
+	*foundlen = 0;
+
+	slot = hash (key, keylen, ht->inithash) & ht->mask;
+	bucket = &(ht->buckets[slot]);
+
+	/* Acquire Lock */
+	ocfs_down_sem (&(ht->hashlock), true);
+	lockacqrd = true;
+
+	while (bucket) {
+		if (bucket->key) {
+			if (!memcmp (bucket->key, key, keylen)) {
+				/* return warning & val if key already exists */
+				LOG_TRACE_STR ("Duplicate key");
+				*found = bucket->val;
+				*foundlen = bucket->vallen;
+				ret = 2;
+				goto bail;
+			}
+		} else {
+			/* Fill the empty bucket */
+			bucket->key = key;
+			bucket->keylen = keylen;
+			bucket->val = val;
+			bucket->vallen = vallen;
+
+			/* Increment the number of entries */
+			ht->entries++;
+			ret = 1;
+			goto bail;
+		}
+		prvbucket = bucket;
+		bucket = bucket->next;
+	}
+
+	/* Save the last bucket for this slot */
+	lastbucket = prvbucket;
+
+	/* Check if any bucket in freelist ... */
+	if (ht->freelist) {
+		/* ... if so, attach it to the end of the slot list ... */
+		lastbucket->next = bucket = ht->freelist;
+
+		/* ... and detach it from the freelist */
+		if (ht->lastfree == ht->freelist)
+			ht->freelist = ht->lastfree = NULL;
+		else
+			ht->freelist = ht->freelist->next;
+
+		/* Fill the empty bucket */
+		bucket->key = key;
+		bucket->keylen = keylen;
+		bucket->val = val;
+		bucket->vallen = vallen;
+		bucket->next = NULL;
+		ht->reusedbuckets++;
+
+		/* Increment the number of entries */
+		ht->entries++;
+		ret = 1;
+		goto bail;
+	}
+
+	/* Create a new bucket and add to the end of list */
+	if ((bucket = (HASHBUCKET *) ocfs_malloc (sizeof (HASHBUCKET))) == NULL) {
+		LOG_ERROR_ARGS ("unable to allocate %u bytes of memory",
+				sizeof (HASHBUCKET));
+		ret = 0;
+		goto bail;
+	}
+
+	bucket->key = key;
+	bucket->keylen = keylen;
+	bucket->val = val;
+	bucket->vallen = vallen;
+	bucket->next = NULL;
+	lastbucket->next = bucket;
+	ht->newbuckets++;
+
+	/* Increment the number of entries */
+	ht->entries++;
+
+      bail:
+	/* Release Lock */
+	if (lockacqrd)
+		ocfs_up_sem (&(ht->hashlock));
+
+	LOG_EXIT_LONG (ret);
+	return ret;
+}				/* ocfs_hash_add */
+
+/*
+ * ocfs_hash_del()
+ *
+ * @ht: ptr to hash table
+ * @key: key to be deleted
+ * @keylen: length of key
+ *
+ */
+int ocfs_hash_del (HASHTABLE * ht, void *key, __u32 keylen)
+{
+	HASHBUCKET *bucket;
+	HASHBUCKET *prvbucket = NULL;
+	__u32 slot;
+	int ret = 0;
+	int lockacqrd = false;
+
+	LOG_ENTRY ();
+
+	if (!ht || !ht->buckets)
+		goto bail;
+
+	slot = hash (key, keylen, ht->inithash) & ht->mask;
+	bucket = &(ht->buckets[slot]);
+
+	/* Acquire Lock */
+	ocfs_down_sem (&(ht->hashlock), true);
+	lockacqrd = true;
+
+	while (bucket) {
+		if (bucket->key) {
+			if (!memcmp (bucket->key, key, keylen)) {
+				/* Found it */
+				if (!prvbucket) {
+					/* If first bucket, clear it */
+					bucket->key = NULL;
+				} else {
+					/* If not first bucket, detach the bucket from list ... */
+					prvbucket->next = bucket->next;
+
+					/* ... clear it ... */
+					bucket->key = NULL;
+					bucket->next = NULL;
+
+					/* ... and attach to the end of the free list */
+					if (ht->lastfree) {
+						ht->lastfree->next = bucket;
+						ht->lastfree = bucket;
+					} else {
+						ht->lastfree = ht->freelist =
+						    bucket;
+					}
+				}
+				/* Decrement the number of entries and exit */
+				ht->entries--;
+				ret = 1;
+				goto bail;
+			}
+		}
+		prvbucket = bucket;
+		bucket = bucket->next;
+	}
+
+      bail:
+	/* Release Lock */
+	if (lockacqrd)
+		ocfs_up_sem (&(ht->hashlock));
+
+	LOG_EXIT_LONG (ret);
+	return ret;
+}				/* ocfs_hash_del */
+
+/*
+ * ocfs_hash_get()
+ *
+ */
+int ocfs_hash_get (HASHTABLE * ht, void *key, __u32 keylen, void **val, __u32 * vallen)
+{
+	HASHBUCKET *bucket;
+	__u32 slot;
+	int ret = 0;
+	int lockacqrd = false;
+
+	LOG_ENTRY ();
+
+	if (!ht || !ht->buckets)
+		goto bail;
+
+	slot = hash (key, keylen, ht->inithash) & ht->mask;
+	bucket = &(ht->buckets[slot]);
+
+	/* Acquire Lock */
+	ocfs_down_sem (&(ht->hashlock), true);
+	lockacqrd = true;
+
+	while (bucket) {
+		if (bucket->key) {
+			if (!memcmp (bucket->key, key, keylen)) {
+				/* found it */
+				*val = bucket->val;
+				*vallen = bucket->vallen;
+				ret = 1;
+				goto bail;
+			}
+		}
+		bucket = bucket->next;
+	}
+
+      bail:
+	/* Release Lock */
+	if (lockacqrd)
+		ocfs_up_sem (&(ht->hashlock));
+
+	LOG_EXIT_LONG (ret);
+	return ret;
+}				/* ocfs_hash_get */
+
+/*
+ * ocfs_hash_stat()
+ *
+ */
+void ocfs_hash_stat (HASHTABLE * ht, char *data, __u32 datalen)
+{
+	HASHBUCKET *bucket;
+	__u32 slot;
+	__u32 i;
+	char *p;
+	__u32 len = 0;
+	__u32 rlen;
+	__u32 stats[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+	int lockacqrd = false;
+
+	LOG_ENTRY ();
+
+	if (!ht || !ht->buckets)
+		goto bail;
+
+	if (!data || !datalen)
+		goto bail;
+
+	/* Acquire Lock */
+	ocfs_down_sem (&(ht->hashlock), true);
+	lockacqrd = true;
+
+	for (slot = 0; slot < ht->size; ++slot) {
+		bucket = &(ht->buckets[slot]);
+		i = 0;
+
+		while (bucket) {
+			if (bucket->key)
+				++i;
+			bucket = bucket->next;
+		}
+
+		if (i < 9)
+			stats[i]++;
+		else
+			stats[9]++;
+	}
+
+	for (i = 0, p = data, rlen = datalen; i < 10; ++i, p += len, rlen -= len)
+		len = snprintf (p, rlen, "%2u: %u\n", i, stats[i]);
+
+	len = rlen;
+	len += snprintf (p, rlen, "New: %u, Reused: %u\n", ht->newbuckets,
+			 ht->reusedbuckets);
+
+	data[len + 1] = '\0';
+
+      bail:
+	/* Release Lock */
+	if (lockacqrd)
+		ocfs_up_sem (&(ht->hashlock));
+
+	LOG_EXIT ();
+	return;
+}				/* ocfs_hash_stat */
+
+/*
+ * --------------------------------------------------------------------
+ * hash() -- hash a variable-length key into a 32-bit value
+ *   k       : the key (the unaligned variable-length array of bytes)
+ *   len     : the length of the key, counting by bytes
+ *   initval : can be any 4-byte value
+ *
+ * Returns a 32-bit value.  Every bit of the key affects every bit of
+ * the return value.  Every 1-bit and 2-bit delta achieves avalanche.
+ * About 6*len+35 instructions.
+ *
+ * The best hash table sizes are powers of 2.  There is no need to do
+ * mod a prime (mod is sooo slow!).  If you need less than 32 bits,
+ * use a bitmask.  For example, if you need only 10 bits, do
+ * h = (h & hashmask(10));
+ * In which case, the hash table should have hashsize(10) elements.
+ *
+ * If you are hashing n strings (__u8 **)k, do it like this:
+ * for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
+ *
+ * By Bob Jenkins, 1996.  bob_jenkins at burtleburtle.net.  You may use this
+ * code any way you wish, private, educational, or commercial.  It's free.
+ *
+ * See http://burtleburtle.net/bob/hash/evahash.html
+ * Use for hash table lookup, or anything where one collision in 2^^32 is
+ * acceptable.  Do NOT use for cryptographic purposes.
+ * --------------------------------------------------------------------
+ */
+__u32 hash (k, length, initval)
+register __u8 *k;		/* the key */
+register __u32 length;		/* the length of the key */
+register __u32 initval;		/* the previous hash, or an arbitrary value */
+{
+	register __u32 a, b, c, len;
+
+	/* Set up the internal state */
+	len = length;
+	a = b = 0x9e3779b9;	/* the golden ratio; an arbitrary value */
+	c = initval;		/* the previous hash value */
+
+   /*---------------------------------------- handle most of the key */
+	while (len >= 12) {
+		a += (k[0] + ((__u32) k[1] << 8) + ((__u32) k[2] << 16) +
+		      ((__u32) k[3] << 24));
+		b += (k[4] + ((__u32) k[5] << 8) + ((__u32) k[6] << 16) +
+		      ((__u32) k[7] << 24));
+		c += (k[8] + ((__u32) k[9] << 8) + ((__u32) k[10] << 16) +
+		      ((__u32) k[11] << 24));
+		mix (a, b, c);
+		k += 12;
+		len -= 12;
+	}
+
+   /*------------------------------------- handle the last 11 bytes */
+	c += length;
+	switch (len) {		/* all the case statements fall through */
+	    case 11:
+		    c += ((__u32) k[10] << 24);
+	    case 10:
+		    c += ((__u32) k[9] << 16);
+	    case 9:
+		    c += ((__u32) k[8] << 8);
+		    /* the first byte of c is reserved for the length */
+	    case 8:
+		    b += ((__u32) k[7] << 24);
+	    case 7:
+		    b += ((__u32) k[6] << 16);
+	    case 6:
+		    b += ((__u32) k[5] << 8);
+	    case 5:
+		    b += k[4];
+	    case 4:
+		    a += ((__u32) k[3] << 24);
+	    case 3:
+		    a += ((__u32) k[2] << 16);
+	    case 2:
+		    a += ((__u32) k[1] << 8);
+	    case 1:
+		    a += k[0];
+		    /* case 0: nothing left to add */
+	}
+	mix (a, b, c);
+   /*-------------------------------------------- report the result */
+	return c;
+}				/* hash */

Added: trunk/libocfs/Linux/ocfsmount.c
===================================================================
--- trunk/libocfs/Linux/ocfsmount.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Linux/ocfsmount.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,540 @@
+/*
+ * ocfsmount.c
+ *
+ * Mount and dismount volume
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifdef __KERNEL__
+#include <ocfs.h>
+#else  /* ! KERNEL */
+#include <libocfs.h>
+#endif
+
+/* Tracing */
+#define OCFS_DEBUG_CONTEXT      OCFS_DEBUG_CONTEXT_MOUNT
+
+static bool is_exclusive_node_alive (struct super_block *sb,
+				     ocfs_vol_disk_hdr * hdr);
+
+extern spinlock_t osb_id_lock;
+extern __u32 osb_id;		/* Keeps track of next available OSB Id */
+extern spinlock_t mount_cnt_lock;
+extern __u32 mount_cnt;		/* Count of mounted volumes */
+extern bool mount_cnt_inc;	/* true when mount_cnt is inc by 1 during first mount */
+
+/*
+ * ocfs_read_disk_header()
+ *
+ */
+int ocfs_read_disk_header (__u8 ** buffer, struct super_block *sb)
+{
+	int status = 0;
+#ifndef USERSPACE_TOOL
+	struct buffer_head *bh = NULL;
+#endif
+
+	LOG_ENTRY ();
+
+	if (buffer == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	/*  Read the first sector bytes from the target device */
+	if ((*buffer = ocfs_malloc (1024)) == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+#ifdef USERSPACE_TOOL
+	lseek64(sb->s_dev, 0ULL, SEEK_SET);
+	status = read(sb->s_dev, *buffer, 512);
+	if (status < 512) {
+		status = -EIO;
+		goto leave;
+	}
+#else
+	bh = bread (sb->s_dev, 0, 512);
+	if (!bh) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+	memcpy (*buffer, bh->b_data, 512);
+	bforget (bh);
+#endif
+
+#ifdef USERSPACE_TOOL
+	lseek64(sb->s_dev, 512ULL, SEEK_SET);
+	status = read(sb->s_dev, (*buffer+512), 512);
+	if (status < 512) {
+		status = -EIO;
+		goto leave;
+	}
+#else
+	bh = bread (sb->s_dev, 1, 512);
+	if (!bh) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+	memcpy ((void *) (*buffer + 512), bh->b_data, 512);
+	bforget (bh);
+#endif
+
+      leave:
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_read_disk_header */
+
+
+/*
+ * is_exclusive_node_alive()
+ *
+ */
+static bool is_exclusive_node_alive (struct super_block *sb,
+				     ocfs_vol_disk_hdr * hdr)
+{
+	bool ret = false;
+	__u64 off;
+	__u64 ts;
+	ocfs_publish *pub;
+#ifndef USERSPACE_TOOL
+	struct buffer_head *bh = NULL;
+#endif
+
+	/* get the blocknum of the publish sector in question */
+	off = (hdr->publ_off >> (__u64) 9);
+	off += (__u64) hdr->excl_mount;
+
+	/* get the timestamp from the publish sector */
+#ifdef USERSPACE_TOOL
+	pub = (ocfs_publish *)ocfs_malloc(512);
+	if (pub == NULL) {
+		LOG_ERROR_STR("out of memory");
+		return true;
+	}
+	lseek64(sb->s_dev, off, SEEK_SET);
+	if (read(sb->s_dev, pub, 512) != 512) {
+		LOG_ERROR_STR("failed to read publish sector");
+		free(pub);
+		return true;
+	}
+	ts = pub->time;
+#else
+	bh = bread (sb->s_dev, (__u32) off, 512);
+	if (!bh) {
+		LOG_ERROR_ARGS ("failed to read block: %u\n", (__u32) off);
+		return true;
+	}
+	pub = (ocfs_publish *) bh->b_data;
+	ts = pub->time;
+	bforget (bh);
+#endif
+
+	/* wait... */
+	LOG_ERROR_STR ("sorry to have to do this, but you'll have to "
+		"wait a bit while I check the other node...\n");
+	ocfs_sleep (5000);	/* 5 seconds */
+
+	/* get the timestamp from the publish sector */
+#ifdef USERSPACE_TOOL
+	lseek64(sb->s_dev, off, SEEK_SET);
+	if (read(sb->s_dev, pub, 512) != 512) {
+		LOG_ERROR_STR("failed to read publish sector");
+		free(pub);
+		return true;
+	}
+#else
+
+	bh = bread (sb->s_dev, (__u32) off, 512);
+	if (!bh) {
+		LOG_ERROR_ARGS ("failed to read block: %u\n", (__u32) off);
+		return true;
+	}
+	pub = (ocfs_publish *) bh->b_data;
+#endif
+
+	if (ts != pub->time) {
+		/* aha! she's still there! */
+		LOG_ERROR_ARGS
+		    ("timestamp still changing, the node is alive!: %u.%u -> %u.%u\n",
+		     HI (ts), LO (ts), HI (pub->time), LO (pub->time));
+		ret = true;
+	} else {
+		LOG_ERROR_ARGS
+		    ("timestamp NOT changing, the node is DEAD!: %u.%u -> %u.%u\n",
+		     HI (ts), LO (ts), HI (pub->time), LO (pub->time));
+		ret = false;
+	}
+
+#ifdef USERSPACE_TOOL
+	free(pub);
+#else
+	bforget (bh);
+#endif
+
+	return ret;
+}				/* is_exclusive_node_alive */
+
+
+/*
+ * ocfs_mount_volume()
+ *
+ */
+int ocfs_mount_volume (struct super_block *sb, bool reclaim_id)
+{
+	int status = 0;
+	ocfs_super *osb;
+	__u8 *buffer = NULL;
+	ocfs_vol_disk_hdr *volDiskHdr;
+	ocfs_vol_label *volLabel;
+	int sectsize;
+#ifndef USERSPACE_TOOL
+	int child_pid;
+#endif
+
+	LOG_ENTRY ();
+
+	/* TODO: not using this yet, EVERYTHING assumes 512! */
+	sectsize = OCFS_SECTOR_SIZE;
+
+	status = ocfs_read_disk_header (&buffer, sb);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	volDiskHdr = (ocfs_vol_disk_hdr *) buffer;
+
+	LOG_TRACE_STR ("ocfs_verify_volume...");
+	status = ocfs_verify_volume (volDiskHdr);
+	if (status < 0) {
+		LOG_ERROR_ARGS ("Device (%u,%u) failed verification",
+			       	MAJOR(sb->s_dev), MINOR(sb->s_dev));
+		goto leave;
+	}
+
+	if (volDiskHdr->excl_mount != NOT_MOUNTED_EXCLUSIVE) {
+		if (is_exclusive_node_alive (sb, volDiskHdr)) {
+			LOG_ERROR_ARGS ("Cannot mount. Node %d has this "
+					"volume mounted exclusive.\n",
+					volDiskHdr->excl_mount);
+			status = -EACCES;
+			goto leave;
+		} else {
+			LOG_ERROR_ARGS ("Cannot mount. Node %d mounted this "
+					"volume exclusive, but has DIED! "
+					"Please recover.\n",
+					volDiskHdr->excl_mount);
+			status = -EACCES;
+			goto leave;
+		}
+	}
+
+	/* 2nd sector */
+	volLabel = (ocfs_vol_label *) (buffer + sectsize);
+
+	/* Check if the cluster name on the disk matches the one in the registry */
+#ifdef ENABLE_CLUSTER_NAME_CHECK	/* TODO */
+	if (OcfsGlobalCtxt.ClusterName == NULL ||
+	    volLabel->ClusterNameLength < 1 ||
+	    volLabel->ClusterName[0] == '\0' ||
+	    memcmp (OcfsGlobalCtxt.ClusterName, volLabel->ClusterName,
+		    volLabel->ClusterNameLength) != 0) {
+		LOG_ERROR_ARGS
+		    ("expected cluster name: '%s'  volume cluster name: '%s'\n",
+		     OcfsGlobalCtxt.ClusterName, volLabel->ClusterName);
+		status = -EINVAL;
+		goto leave;
+	}
+#endif
+
+	if ((osb = ocfs_malloc (sizeof (ocfs_super))) == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+        memset(osb, 0, sizeof(ocfs_super));
+        sb->u.generic_sbp = (void *)osb;
+        osb->sb = sb;
+
+	osb->reclaim_id = reclaim_id;
+
+	status = ocfs_initialize_osb (osb, volDiskHdr, volLabel, sectsize);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+        
+	if (osb->vol_layout.root_start_off == 0 && osb->node_num != 0) {
+		LOG_ERROR_ARGS("The volume must be mounted by node 0 before it can "
+			       "be used and you are node %u", osb->node_num);
+		status = -EINVAL;
+		goto leave;
+	}
+
+	osb->sect_size = sectsize;
+
+	spin_lock (&osb_id_lock);
+	osb->osb_id = osb_id;
+	if (osb_id < ULONG_MAX)
+		osb_id++;
+	else {
+		spin_unlock (&osb_id_lock);
+		LOG_ERROR_STR ("Too many volumes mounted");
+		status = -ENOMEM;
+		goto leave;
+	}
+	spin_unlock (&osb_id_lock);
+
+	/* Launch the NM thread for the mounted volume */
+	ocfs_down_sem (&(osb->osb_res), true);
+#ifdef USERSPACE_TOOL
+	osb->dlm_task = (struct task_struct *)ocfs_malloc(sizeof(struct task_struct));
+	if (osb->dlm_task == NULL) {
+		LOG_ERROR_STATUS(status = -ENOMEM); 
+		goto leave;
+	}
+	if (pthread_create(&osb->dlm_task->thread, NULL,
+       			   ocfs_volume_thread, osb) != 0) {
+		LOG_ERROR_STATUS(status = -errno);
+		goto leave;
+	}
+#else
+	child_pid = kernel_thread (ocfs_volume_thread, osb,
+				   CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+	if (child_pid < 0) {
+		LOG_ERROR_ARGS ("unable to launch ocfsnm thread (error=%d)\n",
+				child_pid);
+		ocfs_up_sem (&(osb->osb_res));
+		status = -EFAIL;
+		goto leave;
+	}
+#endif
+	init_completion (&osb->complete);
+	ocfs_up_sem (&(osb->osb_res));
+
+#ifndef USERSPACE_TOOL
+	/* Add proc entry for this volume */
+	ocfs_proc_add_volume (osb);
+
+	/* GlobalMountCount */
+	spin_lock (&mount_cnt_lock);
+	mount_cnt++;
+	if (mount_cnt == 1) {
+		/* Start the ipcdlm */
+		ocfs_init_ipc_dlm (OCFS_UDP);
+		OcfsIpcCtxt.init = true;
+		if (mount_cnt_inc == false) {
+			MOD_INC_USE_COUNT;
+			mount_cnt_inc = true;
+		}
+	}
+	spin_unlock (&mount_cnt_lock);
+#endif
+
+	/* wait for nm thread to be init */
+	ocfs_wait (osb->nm_init_event,
+		   (atomic_read (&osb->nm_init) >= OCFS_HEARTBEAT_INIT ), 0);
+
+	/*  Join or Form the cluster... */
+	LOG_TRACE_STR ("ocfs_vol_member_reconfig...");
+	ocfs_down_sem (&(osb->osb_res), true);
+	status = ocfs_vol_member_reconfig (osb);
+	ocfs_up_sem (&(osb->osb_res));
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	/* Read the publish sector for this node and cleanup dirent being */
+	/* modified when we crashed. */
+	LOG_TRACE_STR ("ocfs_check_volume...");
+	ocfs_down_sem (&(osb->osb_res), true);
+	status = ocfs_check_volume (osb);
+	ocfs_up_sem (&(osb->osb_res));
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	osb->vol_state = VOLUME_MOUNTED;
+
+      leave:
+	ocfs_safefree (buffer);
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_mount_volume */
+
+
+/*
+ * lockres_hash_free_func()
+ *
+ */
+static void lockres_hash_free_func (const void *p)
+{
+	/* Force remove the lockres */
+	ocfs_free_lockres((ocfs_lock_res *)p);
+}
+
+
+/*
+ * ocfs_dismount_volume()
+ *
+ */
+int ocfs_dismount_volume (struct super_block *sb)
+{
+	int status = 0;
+	bool AcquiredOSB = false;
+	ocfs_super *osb = NULL;
+	ocfs_inode *rootoin;
+	__u32 nodemap;
+	__u32 tempmap;
+	int i;
+
+	LOG_ENTRY_ARGS ("(0x%p)\n", sb);
+
+	if (sb == NULL || sb->u.generic_sbp == NULL) {
+		LOG_ERROR_STATUS (status = -EFAIL);
+		goto leave;
+	}
+
+	osb = (ocfs_super *)(sb->u.generic_sbp);
+	OCFS_ASSERT(IS_VALID_OSB(osb));
+	rootoin = osb->oin_root_dir;
+
+	ocfs_down_sem (&(osb->osb_res), true);
+	AcquiredOSB = true;
+	/* we shouldn't have to do the stuff below, vfs takes care of it */
+#ifdef UMOUNT_CHECK 
+	if (osb->file_open_cnt > 0) {
+		LOG_ERROR_ARGS ("Dismount failed... file_open_cnt(%d) > 0\n",
+				osb->file_open_cnt);
+		LOG_ERROR_STR
+		    ("WARNING!!! Need to uncomment this when file opens are correct!\n");
+/*      commenting this out for now until we deal with open files properly */
+		status = -EBUSY;
+		goto leave;
+	}
+#endif
+	LOG_TRACE_ARGS ("osb=0x%p rootoin=0x%p offset=%u.%u\n", osb,
+			rootoin, rootoin->file_disk_off);
+
+	fsync_no_super (sb->s_dev);
+
+	ocfs_release_oin (rootoin, true);
+
+	/* Destroy the Hash table */
+	ocfs_hash_destroy (&(osb->root_sect_node), lockres_hash_free_func);
+
+	/* Remove the proc element for this volume */
+#ifndef USERSPACE_TOOL
+	ocfs_proc_remove_volume (osb);
+#endif
+
+	/* Dismount */
+	OCFS_SET_FLAG (osb->osb_flags, OCFS_OSB_FLAGS_BEING_DISMOUNTED);
+	osb->vol_state = VOLUME_BEING_DISMOUNTED;
+
+	/* Wait for this volume's NM thread to exit */
+	if (osb->dlm_task) {
+		LOG_TRACE_STR ("Waiting for ocfsnm to exit....");
+#ifdef USERSPACE_TOOL
+		pthread_join(osb->dlm_task->thread, NULL);
+		ocfs_safefree(osb->dlm_task);
+#else
+		send_sig (SIGINT, osb->dlm_task, 0);
+		wait_for_completion (&(osb->complete));
+#endif
+		osb->dlm_task = NULL;
+	}
+
+	/* create map of all active nodes except self */
+	nodemap = (__u32)osb->publ_map;
+	tempmap = (1 << osb->node_num);
+	nodemap &= (~tempmap);
+
+#ifndef USERSPACE_TOOL
+	/* send dismount msg to all */
+	status = ocfs_send_dismount_msg (osb, (__u64)nodemap);
+	if (status < 0)
+		LOG_ERROR_STATUS (status);
+
+	/* decrement mount count */
+	spin_lock (&mount_cnt_lock);
+	mount_cnt--;
+	if (mount_cnt == 0) {
+		/* Shutdown ocfslsnr */
+		if (OcfsIpcCtxt.task) {
+			LOG_TRACE_STR ("Waiting for ocfslsnr to exit....");
+			send_sig (SIGINT, OcfsIpcCtxt.task, 0);
+			wait_for_completion (&(OcfsIpcCtxt.complete));
+			OcfsIpcCtxt.task = NULL;
+		}
+	}
+	spin_unlock (&mount_cnt_lock);
+#endif
+
+	ocfs_down_sem (&(OcfsGlobalCtxt.res), true);
+	vfree (osb->cluster_bitmap.buf);
+	ocfs_up_sem (&(OcfsGlobalCtxt.res));
+
+	osb->vol_state = VOLUME_DISMOUNTED;
+	if (AcquiredOSB) {
+		ocfs_up_sem (&(osb->osb_res));
+		AcquiredOSB = false;
+	}
+
+	printk ("ocfs: Unmounting device (%s) on %s (node %d)\n", osb->dev_str,
+		osb->node_cfg_info[osb->node_num]->node_name, osb->node_num);
+
+	/* Free all nodecfgs */
+	for (i = 0; i < OCFS_MAXIMUM_NODES; ++i) {
+		ocfs_node_config_info *p;
+		p = osb->node_cfg_info[i];
+		ocfs_safefree (p);
+	}
+
+	ocfs_delete_osb (osb);
+	ocfs_safefree (osb);
+	sb->s_dev = 0;
+
+#ifndef USERSPACE_TOOL
+	spin_lock (&mount_cnt_lock);
+	if (mount_cnt == 0 && atomic_read (&OcfsGlobalCtxt.cnt_lockres) == 0 &&
+	    mount_cnt_inc == true) {
+		MOD_DEC_USE_COUNT;
+		mount_cnt_inc = false;
+	}
+	spin_unlock (&mount_cnt_lock);
+#endif
+
+      leave:
+	if (AcquiredOSB) {
+		ocfs_up_sem (&(osb->osb_res));
+		AcquiredOSB = false;
+	}
+
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_dismount_volume */

Added: trunk/libocfs/Linux/ocfsport.c
===================================================================
--- trunk/libocfs/Linux/ocfsport.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Linux/ocfsport.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,966 @@
+/*
+ * ocfsport.c
+ *
+ * Linux specific utilities
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
+ *          Manish Singh, Wim Coekaerts
+ */
+
+#ifdef __KERNEL__
+#include <ocfs.h>
+#else  /* ! KERNEL */
+#include <libocfs.h>
+#endif
+
+
+static int get_overlap_type (__u64 new, __u64 newend, __u64 exist, __u64 existend);
+static bool OcfsCoalesceExtentMapEntry (ocfs_extent_map * map,
+			    __s64 virtual, __s64 physical, __s64 sectorcount);
+
+
+/* Tracing */
+#define OCFS_DEBUG_CONTEXT  OCFS_DEBUG_CONTEXT_PORT
+
+/*
+ * ocfs_init_sem()
+ *
+ */
+void ocfs_init_sem (ocfs_sem * res)
+{
+#ifdef USERSPACE_TOOL
+#if 0
+	if ((res->sem.semid = semget(IPC_PRIVATE, 1, IPC_CREAT | S_IRWXU)) == -1) {
+		fprintf(stderr, "ocfs_init_sem failed, %s\n", strerror(errno));
+		exit(1);	
+	}
+	ocfs_up_sem(res);
+#endif
+#else
+	LOG_ENTRY_ARGS ("(0x%p)\n", res);
+
+	memset (res, 0, sizeof (ocfs_sem));
+	init_MUTEX (&(res->sem));
+	res->magic = OCFS_SEM_MAGIC;
+	
+	LOG_EXIT ();
+#endif
+}				/* ocfs_init_sem */
+
+/*
+ * ocfs_down_sem()
+ *
+ * Counter layer atop the sem. If a process which already owns the sem,
+ * attempts to re-acquire it, ocfs_down_sem() increments the
+ * count by 1. If however, a different process attempts to acquire that
+ * sem, it blocks waiting for the sem to be released.
+ * ocfs_up_sem() decrements the count by 1, if the owning
+ * process releases the sem. The sem is released when the counter hits 0.
+ * NT Port leftover, we want to get rid of this as soon as possible
+ */
+bool ocfs_down_sem (ocfs_sem * res, bool wait)
+{
+	bool ret = true;
+#ifdef USERSPACE_TOOL
+#if 0
+	struct sembuf sops;
+
+	/* NOT implementing the recursive sem in user */
+	sops.sem_num = 0;
+	sops.sem_op = -1;
+	sops.sem_flg = SEM_UNDO | (wait ? 0 : IPC_NOWAIT);
+	if (semop(res->sem.semid, &sops, 1) == -1) {
+		ret = false;
+		if (errno == EAGAIN && !wait)
+			ret = true;
+	}
+	if (ret == false)
+		fprintf(stderr, "ocfs_down_sem failed, %s\n", strerror(errno));
+#endif
+#else
+	LOG_ENTRY_ARGS ("(0x%p, %u)\n", res, wait);
+
+	if (!res || res->magic != OCFS_SEM_MAGIC)
+		BUG();
+
+#define WAIT_TILL_ACQUIRE(a)			\
+	do {					\
+		down(&((a)->sem));		\
+		(a)->pid = current->pid;	\
+		(a)->count = 1;			\
+	} while(0)
+
+	if (res->pid == 0) {
+		if (wait)
+			WAIT_TILL_ACQUIRE(res);
+		else {
+			if (!down_trylock(&(res->sem))) {
+				res->pid = current->pid;
+				res->count = 1;
+			}
+			else
+				ret = false;
+		}
+	} else {
+		if (res->pid == current->pid) {
+			res->count++;
+		} else {
+			if (wait)
+				WAIT_TILL_ACQUIRE(res);
+			else
+				ret = false;
+		}
+	}
+
+	LOG_EXIT_ULONG (ret);
+#endif /* !USERSPACE_TOOL */
+
+	return ret;
+}				/* ocfs_down_sem */
+
+/*
+ * ocfs_up_sem()
+ *
+ * ocfs_up_sem() decrements the count by 1, if the owning
+ * process releases the sem. The sem is released when the counter hits 0.
+ * Remained of NT port, we really really do not want this nesting
+ * but for now it's there, we'll clean it up
+ */
+void ocfs_up_sem (ocfs_sem * res)
+{
+#ifdef USERSPACE_TOOL
+#if 0
+	struct sembuf sops;
+	
+	/* NOT implementing the recursive sem in user */
+	sops.sem_num = 0;
+	sops.sem_op = 1;
+	sops.sem_flg = SEM_UNDO;
+	if (semop(res->sem.semid, &sops, 1) == -1) {
+		fprintf(stderr, "ocfs_up_sem failed, %s\n", strerror(errno));
+	}
+#endif
+#else
+	LOG_ENTRY_ARGS ("(0x%p)\n", res);
+
+	if (!res || res->magic != OCFS_SEM_MAGIC)
+		BUG();
+
+	if (res->count && current->pid == res->pid) {
+		res->count--;
+		if (!res->count) {
+			res->pid = 0;
+			up (&(res->sem));
+		}
+	}
+
+	LOG_EXIT ();
+#endif
+
+	return;
+}				/* ocfs_up_sem */
+
+/*
+ * ocfs_del_sem()
+ *
+ */
+int ocfs_del_sem (ocfs_sem * res)
+{
+#ifdef USERSPACE_TOOL
+#if 0
+	union semun junk;
+	if (semctl(res->sem.semid, 0, IPC_RMID, junk) == -1) {
+		LOG_EXIT ();
+		return -errno;
+	}
+#endif
+#else
+	if (res)
+		res->magic = OCFS_SEM_DELETED;
+#endif
+
+	return 0;
+}				/* ocfs_del_sem */
+
+
+/*
+ * ocfs_daemonize() 
+ *
+ */
+void ocfs_daemonize (char *name, int len)
+{
+#ifndef USERSPACE_TOOL
+	sigset_t tmpsig;
+
+	daemonize ();
+	reparent_to_init ();
+
+	if (len > 0) {
+		if (len > 15)
+			BUG();
+		strncpy (current->comm, name, len);
+		current->comm[len] = '\0';
+	}
+
+	/* Block all signals except SIGKILL, SIGSTOP, SIGHUP and SIGINT */
+#ifdef HAVE_NPTL
+        spin_lock_irq (&current->sighand->siglock);
+        tmpsig = current->blocked;
+        siginitsetinv (&current->blocked, SHUTDOWN_SIGS);
+        recalc_sigpending ();
+        spin_unlock_irq (&current->sighand->siglock);
+#else
+	spin_lock_irq (&current->sigmask_lock);
+	tmpsig = current->blocked;
+	siginitsetinv (&current->blocked, SHUTDOWN_SIGS);
+	recalc_sigpending (current);
+	spin_unlock_irq (&current->sigmask_lock);
+#endif
+#endif	/* !USERSPACE_TOOL */
+
+	return;
+}				/* ocfs_daemonize */
+
+
+/*
+ * ocfs_sleep()
+ *
+ * The interval time is in milliseconds
+ *
+ * This function needs to be removed.
+ * Instead call schedule_timeout() directly and handle signals.
+ */
+int ocfs_sleep (__u32 ms)
+{
+#ifdef USERSPACE_TOOL
+	struct timespec req, rem;
+
+	memset(&rem, 0, sizeof(struct timespec));
+	req.tv_sec = ms / 1000;
+	req.tv_nsec = (ms % 1000) * 1000000;
+	while (nanosleep(&req, &rem) == -1 && errno == EINTR) {
+		req.tv_sec = rem.tv_sec;
+		req.tv_nsec = rem.tv_nsec;
+		memset(&rem, 0, sizeof(struct timespec));
+	}
+#else
+	__u32 numJiffies;
+
+	LOG_ENTRY ();
+
+	/* 10ms = 1 jiffy, minimum resolution is one jiffy */
+	numJiffies = ms * HZ / 1000;
+	numJiffies = (numJiffies < 1) ? 1 : numJiffies;
+	set_current_state (TASK_INTERRUPTIBLE);
+	numJiffies = schedule_timeout (numJiffies);
+	
+	LOG_EXIT ();
+#endif
+
+	return 0;
+}				/* ocfs_sleep */
+
+#ifndef USERSPACE_TOOL
+
+#ifdef OCFS_LINUX_MEM_DEBUG
+#define SUPER_VERBOSE_MEM_DEBUG  1
+#endif
+
+/*
+ * ocfs_dbg_slab_alloc()
+ *
+ */
+void *ocfs_dbg_slab_alloc (kmem_cache_t *slab, char *file, int line)
+{
+    void *m;
+    m = kmem_cache_alloc(slab, GFP_NOFS);
+#ifdef OCFS_LINUX_MEM_DEBUG
+    if (m == NULL) {
+        LOG_ERROR_ARGS("failed to alloc from slab = %p", slab);
+    } else {
+		alloc_item *new;
+		new = kmalloc (sizeof (alloc_item), GFP_NOFS);
+                new->type = SLAB_ITEM;
+		new->address = m;
+		new->u.slab = slab;
+		snprintf (new->tag, 30, "%d:%s", line, file);
+		new->tag[29] = '\0';
+		list_add (&new->list, &OcfsGlobalCtxt.item_list);
+#ifdef SUPER_VERBOSE_MEM_DEBUG
+		LOG_TRACE_ARGS (" + %x (%p, '%s')\n", m, slab, new->tag);
+#endif
+    }
+#endif
+    return m;
+}                               /* ocfs_dbg_slab_alloc */
+
+/*
+ * ocfs_dbg_slab_free()
+ *
+ */
+void ocfs_dbg_slab_free (kmem_cache_t *slab, void *m)
+{
+
+#ifdef OCFS_LINUX_MEM_DEBUG
+	struct list_head *iter;
+	struct list_head *temp_iter;
+        alloc_item *item = NULL;
+        bool do_free = false;
+
+	list_for_each_safe (iter, temp_iter, &OcfsGlobalCtxt.item_list) {
+		item = list_entry (iter, alloc_item, list);
+
+		if (item->address == m && item->type == SLAB_ITEM) {
+#ifdef SUPER_VERBOSE_MEM_DEBUG
+			LOG_TRACE_ARGS (" - %x (%p, '%s')\n", m, item->u.slab, item->tag);
+#endif
+                        list_del (&item->list);
+                        do_free = true;
+			break;
+		}
+	}
+
+        if (do_free) {
+                kmem_cache_free(slab, m);
+                kfree (item);
+                return;
+        }
+	LOG_ERROR_ARGS ("tried to free mem never allocated: %x", m);
+#endif
+#ifndef OCFS_LINUX_MEM_DEBUG
+	kmem_cache_free(slab, m);
+#endif
+}				/* ocfs_dbg_slab_free */
+
+
+
+/*
+ * ocfs_linux_dbg_alloc()
+ *
+ */
+void *ocfs_linux_dbg_alloc (int Size, char *file, int line)
+{
+	void *m;
+
+	m = kmalloc (Size, GFP_NOFS);
+#ifdef OCFS_LINUX_MEM_DEBUG
+	if (m == NULL) {
+		LOG_ERROR_ARGS ("failed! (size=%d)", Size);
+	} else {
+		alloc_item *new;
+		new = kmalloc (sizeof (alloc_item), GFP_NOFS);
+                new->type = KMALLOC_ITEM;
+		new->address = m;
+		new->u.length = Size;
+		snprintf (new->tag, 30, "%d:%s", line, file);
+		new->tag[29] = '\0';
+		list_add (&new->list, &OcfsGlobalCtxt.item_list);
+#ifdef SUPER_VERBOSE_MEM_DEBUG
+		LOG_TRACE_ARGS (" + %x (%d, '%s')\n", m, Size, new->tag);
+#endif
+	}
+#endif
+	return m;
+}				/* ocfs_linux_dbg_alloc */
+
+/*
+ * ocfs_linux_dbg_free()
+ *
+ */
+void ocfs_linux_dbg_free (const void *Buffer)
+{
+
+#ifdef OCFS_LINUX_MEM_DEBUG
+	struct list_head *iter;
+	struct list_head *temp_iter;
+        alloc_item *item = NULL;
+        bool do_free = false;
+
+	list_for_each_safe (iter, temp_iter, &OcfsGlobalCtxt.item_list) {
+		item = list_entry (iter, alloc_item, list);
+
+		if (item->address == Buffer && item->type == KMALLOC_ITEM) {
+#ifdef SUPER_VERBOSE_MEM_DEBUG
+			LOG_TRACE_ARGS (" - %x (%d, '%s')\n", Buffer,
+					item->u.length, item->tag);
+#endif
+			list_del (&item->list);
+                        do_free = true;
+			break;
+		}
+	}
+        if (do_free) {
+                kfree (Buffer);
+                kfree (item);
+                return;
+        }
+	LOG_ERROR_ARGS ("tried to free mem never allocated: %x", Buffer);
+#endif
+#ifndef OCFS_LINUX_MEM_DEBUG
+	kfree (Buffer);
+#endif
+}				/* ocfs_linux_dbg_free */
+
+
+/*
+ * ocfs_linux_get_inode_offset()
+ *
+ */
+bool ocfs_linux_get_inode_offset (struct inode * inode, __u64 * off, ocfs_inode ** oin)
+{
+	if (off == NULL)
+		return false;
+
+	if (oin != NULL)
+		*oin = NULL;
+
+	if (inode_data_is_oin (inode)) {
+		ocfs_inode *f = ((ocfs_inode *)inode->u.generic_ip);
+
+		if (f == NULL) {
+			LOG_ERROR_STR ("bad inode oin");
+			*off = -1;
+			return false;
+		} else {
+			OCFS_ASSERT(IS_VALID_OIN(f));
+			if (oin != NULL)
+				*oin = f;
+			if (S_ISDIR (inode->i_mode))
+				*off = f->dir_disk_off;
+			else
+				*off = f->file_disk_off;
+		}
+	} else {
+		*off = GET_INODE_OFFSET (inode);
+	}
+	return (*off != -1);
+}				/* ocfs_linux_get_inode_offset */
+
+
+/*
+ * ocfs_linux_get_dir_entry_offset()
+ *
+ */
+bool ocfs_linux_get_dir_entry_offset (ocfs_super * osb, __u64 * off, __u64 parentOff,
+			    struct qstr * fileName, ocfs_file_entry ** fileEntry)
+{
+	int status;
+	ocfs_file_entry *ent;
+
+	if (off == NULL)
+		return false;
+
+	*off = -1;
+	ent = ocfs_allocate_file_entry ();
+	if (ent != NULL) {
+		status = ocfs_find_files_on_disk (osb, parentOff, fileName, ent, NULL);
+		if (status >= 0)
+			*off = ent->this_sector;
+
+		/* if the caller wants the file entry let him free it */
+		if (fileEntry)
+			*fileEntry = ent;
+		else
+			ocfs_release_file_entry (ent);
+	}
+	return (*off != -1);
+}				/* ocfs_linux_get_dir_entry_offset */
+
+#endif /* !USERSPACE_TOOL */
+
+/*
+ * ocfs_flush_cache()
+ *
+ */
+void ocfs_flush_cache (ocfs_super * osb)
+{
+	fsync_no_super (osb->sb->s_dev);
+}				/* ocfs_flush_cache */
+
+
+/*
+ * ocfs_purge_cache_section()
+ *
+ */
+bool ocfs_purge_cache_section (ocfs_inode * oin, __u64 * file_off, __u32 Length)
+{
+	if (oin != NULL && oin->inode != NULL) {
+		fsync_inode_buffers (oin->inode);
+	}
+	return true;
+}				/* ocfs_purge_cache_section */
+
+#ifndef USERSPACE_TOOL
+/* prefetch has been declared to allow to build in debug mode */
+#ifdef DEBUG
+#ifndef ARCH_HAS_PREFETCH
+inline void prefetch (const void *x) {;}
+#endif
+#ifndef ARCH_HAS_PREFETCHW
+inline void prefetchw(const void *x) {;}
+#endif
+#endif /* !DEBUG */
+#endif /* !USERSPACE_TOOL */
+
+
+/* Crazy wacky extent map stuff */
+/* works ok in userland stuff too */
+
+#define GET_EXTENT_MAP_ENTRY(map, i)    ((ocfs_extent *) ((__u8 *)map->buf + \
+							  ((i) * sizeof(ocfs_extent))))
+
+/*
+ * ocfs_extent_map_init()
+ *
+ */
+void ocfs_extent_map_init (ocfs_extent_map * map)
+{
+	LOG_ENTRY ();
+
+	OCFS_ASSERT (map != NULL);
+	spin_lock_init(&(map->lock));
+	map->capacity = 0;
+	map->count = 0;
+	map->initialized = true;
+	map->buf = NULL;
+
+	LOG_EXIT ();
+	return;
+}				/* ocfs_extent_map_init */
+
+/*
+ * ocfs_extent_map_destroy()
+ *
+ */
+void ocfs_extent_map_destroy (ocfs_extent_map * map)
+{
+	LOG_ENTRY ();
+
+	if (!map)
+		goto leave;
+	
+	if (map->initialized) {
+                spin_lock(&(map->lock));
+		#warning RACE! need to retest map->initialized here!
+		map->capacity = 0;
+		map->count = 0;
+		ocfs_safefree (map->buf);
+		map->initialized = false;
+                spin_unlock(&(map->lock));
+	}
+
+leave:
+	LOG_EXIT ();
+	return;
+}				/* ocfs_extent_map_destroy */
+
+/*
+ * ocfs_extent_map_get_count()
+ *
+ */
+__u32 ocfs_extent_map_get_count (ocfs_extent_map * map)
+{
+	__u32 ret;
+
+	LOG_ENTRY ();
+
+	OCFS_ASSERT (map != NULL);
+	#warning this locking almost has to be a bug
+	spin_lock(&(map->lock));
+	ret = map->count;
+	spin_unlock(&(map->lock));
+
+	LOG_EXIT_ULONG (ret);
+	return ret;
+}				/* ocfs_extent_map_get_count */
+
+enum
+{
+	LEFT_NO_OVERLAP,
+	LEFT_ADJACENT,
+	LEFT_OVERLAP,
+	FULLY_CONTAINED,
+	FULLY_CONTAINING,
+	RIGHT_OVERLAP,
+	RIGHT_ADJACENT,
+	RIGHT_NO_OVERLAP
+};
+
+/*
+ * get_overlap_type()
+ *
+ */
+static int get_overlap_type (__u64 new, __u64 newend, __u64 exist, __u64 existend)
+{
+	OCFS_ASSERT (newend > new);
+	OCFS_ASSERT (existend > exist);
+
+	if (new < exist) {
+		if (newend < exist)
+			return LEFT_NO_OVERLAP;
+		else if (newend == exist)
+			return LEFT_ADJACENT;
+		else if (newend >= existend)	/* && newend > exist */
+			return FULLY_CONTAINING;
+		else		/* newend < existend && newend > exist */
+			return LEFT_OVERLAP;
+	} else if (new > exist) {
+		if (new > existend)
+			return RIGHT_NO_OVERLAP;
+		else if (new == existend)
+			return RIGHT_ADJACENT;
+		else if (newend > existend)	/* && new < existend */
+			return RIGHT_OVERLAP;
+		else		/* newend <= existend && new < existend */
+			return FULLY_CONTAINED;
+	} else if (newend > existend)	/* && new == exist */
+		return FULLY_CONTAINING;
+	else			/* newend <= existend && new == exist */
+		return FULLY_CONTAINED;
+}				/* get_overlap_type */
+
+/*
+ * OcfsCoalesceExtentMapEntry()
+ *
+ * Must call this with spinlock already held!
+ */
+static bool OcfsCoalesceExtentMapEntry (ocfs_extent_map * map,
+			    __s64 virtual, __s64 physical, __s64 sectorcount)
+{
+	ocfs_extent *tmp, *tmp2;
+	int i, voverlap, loverlap, newIdx;
+	bool ret = false;
+
+	LOG_ENTRY ();
+
+	if (!map->initialized) {
+		LOG_ERROR_STR ("ExtentMap is not initialized");
+		goto bail;
+	}
+
+	/* attempt to coalesce this into an existing entry */
+
+	/* 
+	 * NOTE: if we are successful in coalescing this entry with an entry from somewhere
+	 *       in the list, we still need to check the rest of the list in case this entry
+	 *       ends up filling one or more holes
+	 *                 |---- this ----|
+	 *       |-- found --|          |-- another entry --|
+	 *                     |---| <--- yet another entry
+	 */
+
+	newIdx = -1;
+	for (i = 0; i < map->count; i++) {
+		tmp = GET_EXTENT_MAP_ENTRY (map, i);
+		voverlap =
+		    get_overlap_type (virtual, virtual + sectorcount,
+				      tmp->virtual,
+				      tmp->virtual + tmp->sectors);
+		loverlap =
+		    get_overlap_type (physical, physical + sectorcount,
+				      tmp->physical,
+				      tmp->physical + tmp->sectors);
+
+		/* first off, if the virtual range and real range don't */
+		/* overlap in the same way it definitely can't be coalesced */
+		if (voverlap != loverlap)
+			continue;
+
+		switch (voverlap) {
+		    case FULLY_CONTAINED:	/* already fully accounted for, done */
+			    ret = true;
+			    goto bail;
+			    break;
+
+		    case LEFT_ADJACENT:	/* add new left part to found entry */
+			    sectorcount += tmp->sectors;
+			    tmp->sectors = 0;	/* mark for deletion */
+			    ret = true;
+			    break;
+
+		    case RIGHT_ADJACENT:	/* add new right part to found entry */
+			    virtual = tmp->virtual;
+			    physical = tmp->physical;
+			    sectorcount += tmp->sectors;
+			    tmp->sectors = 0;	/* mark for deletion */
+			    ret = true;
+			    break;
+
+		    case FULLY_CONTAINING:	/* completely take over this entry */
+			    tmp->sectors = 0;	/* mark for deletion */
+			    ret = true;
+			    break;
+
+		    case LEFT_OVERLAP:	/* should begin at new physical/virtual, end at old end */
+			    if ((tmp->virtual - virtual) == (tmp->physical - physical))
+			    {
+				    /* must be same distance from edge */
+				    sectorcount =
+					tmp->sectors + (tmp->virtual - virtual);
+				    tmp->sectors = 0;	/* mark for deletion */
+				    ret = true;
+			    }
+			    break;
+
+		    case RIGHT_OVERLAP:	/* should begin at old physical/virtual, end at new end */
+			    if ((virtual - tmp->virtual) ==
+				(physical - tmp->physical)) {
+				    sectorcount =
+					virtual + sectorcount - tmp->virtual;
+				    virtual = tmp->virtual;
+				    physical = tmp->physical;
+				    tmp->sectors = 0;	/* mark for deletion */
+				    ret = true;
+			    }
+			    break;
+
+		    case LEFT_NO_OVERLAP:	/* keep looking */
+		    case RIGHT_NO_OVERLAP:
+			    break;
+		}
+
+		if (tmp->sectors == 0) {
+			if (newIdx == -1)	/* first time thru, this is where we */
+						/* will put the coalesced entry */
+				newIdx = i;
+			else {
+				/* otherwise swap the tail with the current... */
+				tmp2 = GET_EXTENT_MAP_ENTRY (map, map->count - 1);
+				tmp->virtual = tmp2->virtual;
+				tmp->physical = tmp2->physical;
+				tmp->sectors = tmp2->sectors;
+				tmp2->sectors = 0;
+				map->count--;	/* ...and dump the tail */
+			}
+		}
+	}
+
+	if (newIdx != -1) {	/* finally, stick the coalesced thing into newIdx */
+		tmp = GET_EXTENT_MAP_ENTRY (map, newIdx);
+		tmp->virtual = virtual;
+		tmp->physical = physical;
+		tmp->sectors = sectorcount;
+	}
+
+      bail:
+
+	LOG_EXIT_ULONG (ret);
+	return ret;
+}				/* OcfsCoalesceExtentMapEntry */
+
+/*
+ * ocfs_extent_map_add()
+ *
+ */
+bool ocfs_extent_map_add (ocfs_extent_map * map, __s64 virtual, __s64 physical,
+			  __s64 sectorcount)
+{
+	ocfs_extent *tmp;
+	void *newpool;
+	__u32 newmax;
+	bool ret = false;
+
+	LOG_ENTRY ();
+
+	OCFS_ASSERT (map != NULL);
+
+	if (!map->initialized) {
+		LOG_ERROR_STATUS (-EFAIL);
+		goto bail;
+	}
+	spin_lock(&(map->lock));
+
+	if ((ret =
+	     OcfsCoalesceExtentMapEntry (map, virtual, physical,
+					 sectorcount))) {
+		LOG_TRACE_STR ("Successfully coalesced map entry");
+		goto release_spinlock;
+	}
+
+	/* if extra allocation needed, do it now */
+	if (map->count >= map->capacity) {
+		/* TODO: come up with some better algorithm, */
+		/* for now: first-double size, second-just one more */
+		newmax =
+		    (map->capacity >
+		     0) ? map->capacity * 2 : INITIAL_EXTENT_MAP_SIZE;
+		newpool = ocfs_malloc (newmax * sizeof (ocfs_extent));
+		if (newpool == NULL && newmax != INITIAL_EXTENT_MAP_SIZE) {
+			newmax = map->capacity + 1;
+			newpool = ocfs_malloc (newmax * sizeof (ocfs_extent));
+		}
+		if (newpool == NULL) {
+			LOG_ERROR_STATUS (-ENOMEM);
+			goto release_spinlock;
+		}
+		if (map->buf && map->capacity)
+			memcpy (newpool, map->buf,
+				map->capacity * sizeof (ocfs_extent));
+		ocfs_safefree (map->buf);
+		map->buf = newpool;
+		map->capacity = newmax;
+	}
+
+	tmp = GET_EXTENT_MAP_ENTRY (map, map->count);
+	tmp->virtual = virtual;
+	tmp->physical = physical;
+	tmp->sectors = sectorcount;
+	map->count++;
+	ret = true;
+
+release_spinlock:
+	spin_unlock(&(map->lock));
+
+bail:
+	LOG_EXIT_ULONG (ret);
+	return ret;
+}				/* ocfs_extent_map_add */
+
+/* ocfs_extent_map_remove()
+ *
+ */
+void ocfs_extent_map_remove (ocfs_extent_map * map, __s64 virtual, __s64 sectorcount)
+{
+	ocfs_extent *tmp;
+	__u32 i;
+	int voverlap;
+
+	LOG_ENTRY ();
+
+	OCFS_ASSERT (map != NULL);
+
+	if (!map->initialized)
+		goto bail;
+	spin_lock(&(map->lock));
+	for (i = 0; i < map->count; i++) {
+		tmp = GET_EXTENT_MAP_ENTRY (map, i);
+		voverlap =
+		    get_overlap_type (virtual, virtual + sectorcount,
+				      tmp->virtual,
+				      tmp->virtual + tmp->sectors);
+		switch (voverlap) {
+		    case FULLY_CONTAINED:
+			    /* for now, don't allow splitting of entries */
+			    if (virtual == tmp->virtual
+				&& sectorcount == tmp->sectors) {
+				    if (i != map->count - 1)
+					    memcpy ((void *) tmp, (void *)
+						    GET_EXTENT_MAP_ENTRY (map,
+									  (map->
+									   count
+									   -
+									   1)),
+						    sizeof (ocfs_extent));
+				    map->count--;
+				    goto release_spinlock;
+			    }
+			    break;
+		    default:	/* all others would be an error */
+			    break;
+		}
+	}
+
+release_spinlock:
+	spin_unlock(&(map->lock));
+bail:
+
+	LOG_EXIT ();
+	return;
+}				/* ocfs_extent_map_remove */
+
+/*
+ * ocfs_extent_map_lookup()
+ *
+ */
+bool ocfs_extent_map_lookup (ocfs_extent_map *map, __s64 virtual, __s64 *physical,
+			     __s64 *sectorcount, __u32 *index)
+{
+	ocfs_extent *tmp;
+	bool ret = false;
+	__u32 idx = 0;
+
+	LOG_ENTRY ();
+
+	OCFS_ASSERT (map != NULL);
+
+	if (!map->initialized) {
+		LOG_ERROR_STR ("BUG! Uninitialized ExtentMap!");
+		goto bail;
+	}
+	spin_lock(&(map->lock));
+
+	for (idx = 0; idx < map->count; idx++) {
+		__s64 hi, lo, delta;
+
+		tmp = GET_EXTENT_MAP_ENTRY (map, idx);
+
+		lo = tmp->virtual;
+		hi = lo + tmp->sectors;
+		delta = virtual - lo;
+
+		if (virtual >= lo && virtual < hi) {
+			*physical = tmp->physical + delta;
+			*sectorcount = tmp->sectors - delta;
+			idx++;
+			ret = true;
+			break;
+		}
+	}
+	spin_unlock(&(map->lock));
+
+bail:
+	*index = idx;
+
+	LOG_EXIT_ULONG (ret);
+	return ret;
+}				/* ocfs_extent_map_lookup */
+
+/*
+ * ocfs_extent_map_next_entry()
+ *
+ */
+bool ocfs_extent_map_next_entry (ocfs_extent_map *map, __u32 runindex,
+				 __s64 *virtual, __s64 *physical, __s64 *sectorcount)
+{
+	ocfs_extent *tmp;
+	bool ret = false;
+
+	LOG_ENTRY ();
+
+	OCFS_ASSERT (map != NULL);
+
+	if (!map->initialized)
+		goto bail;
+	spin_lock(&(map->lock));
+	if (runindex >= map->count)
+		goto release_spinlock;
+	tmp = GET_EXTENT_MAP_ENTRY (map, runindex);
+	*virtual = tmp->virtual;
+	*physical = tmp->physical;
+	*sectorcount = tmp->sectors;
+	ret = true;
+
+release_spinlock:
+	spin_unlock(&(map->lock));
+bail:
+
+	LOG_EXIT_ULONG (ret);
+	return ret;
+}				/* ocfs_extent_map_next_entry */

Added: trunk/libocfs/Makefile
===================================================================
--- trunk/libocfs/Makefile	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/Makefile	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,119 @@
+TOPDIR = ..
+
+include $(TOPDIR)/Preamble.make
+
+WARNINGS = -Wall -Wstrict-prototypes -Wno-format
+
+ifneq ($(OCFS_PROCESSOR),x86_64)
+WARNINGS += -Wmissing-prototypes -Wmissing-declarations
+endif
+
+ifdef OCFS_DEBUG
+OPTS += -g
+endif
+
+DEFINES = -DLINUX -DUSERSPACE_TOOL
+
+INCLUDES = -I. -ICommon/inc -ILinux/inc
+
+LIBRARIES = libocfs.a
+
+CFLAGS = $(OPTS) -fno-strict-aliasing -pthread $(WARNINGS)
+
+OPTIMIZE = -O2
+
+ifeq ($(OCFS_PROCESSOR),ppc64)
+endif
+ifeq ($(OCFS_PROCESSOR),x86_64)
+  CFLAGS += -m64
+endif
+ifeq ($(OCFS_PROCESSOR),ia64)
+endif
+ifeq ($(OCFS_PROCESSOR),i686)
+  DEFINES += -D__ILP32__
+endif
+
+CFLAGS += $(OPTIMIZE)
+
+ifdef OCFS_DEBUG
+DEFINES += -DDEBUG
+endif
+
+ifdef OCFS_TRACE
+DEFINES += -DTRACE
+endif
+
+CPARTNER = \
+	Common/ocfsgenalloc.c	\
+	Common/ocfsgensysfile.c	\
+	Common/ocfsgencreate.c	\
+	Common/ocfsgenutil.c	\
+	Common/ocfsgenmisc.c	\
+	Common/ocfsgentrans.c	\
+	Common/ocfsgendirnode.c	\
+	Common/ocfsgenvolcfg.c	\
+	Linux/ocfsmount.c	\
+	Linux/ocfsfile.c	\
+	Linux/ocfsport.c	\
+	Linux/ocfsbitmap.c	\
+	Linux/ocfshash.c	\
+	Common/ocfsgennm.c	\
+	Common/ocfsheartbeat.c	\
+	Common/ocfsgendlm.c 	\
+	libocfs.c
+
+CALONE = \
+	Linux/ocfsdlm.c	\
+	bindraw.c
+
+CFILES = $(CPARTNER) $(CALONE)
+
+HTEMP1 = $(subst .c,.h,$(CPARTNER))
+HTEMP2 = $(subst Common,Common/inc,$(HTEMP1))
+HPARTNER = $(subst Linux,Linux/inc,$(HTEMP2))
+
+HALONE = \
+	Common/inc/ocfs.h		\
+	Common/inc/ocfsbool.h		\
+	Common/inc/ocfsdef.h		\
+	Common/inc/ocfserr.h		\
+	Common/inc/ocfstrace.h		\
+	Common/inc/ocfsvol.h		\
+	Common/inc/ocfscom.h		\
+	Common/inc/ocfsdisk.h		\
+	Common/inc/ocfstrans.h		\
+	Common/inc/ocfsconst.h		\
+	Common/inc/ocfsdlm.h		\
+	Common/inc/ocfsver.h		\
+	Common/inc/ocfsgenvote.h	\
+	Linux/inc/ocfsdlmp.h		\
+	Linux/inc/ocfsioctl.h		\
+	Linux/inc/ocfsiosup.h		\
+	Linux/inc/ocfsmain.h		\
+	Linux/inc/ocfsproc.h
+
+HFILES = $(HPARTNER) $(HALONE)
+
+$(CFILES): $(HFILES)
+
+OBJS = $(subst .c,.o,$(CFILES))
+
+libocfs.a: $(OBJS)
+	rm -f $@
+	$(AR) r $@ $^
+	$(RANLIB) $@
+
+CLEAN_RULES = clean-libocfs
+
+clean-libocfs:
+	rm -f Common/*.o Linux/*.o Common/*.p Linux/*.p Common/*.s Linux/*.s *.o *.p *.s
+
+DIST_FILES = $(CFILES) $(HFILES)
+
+DIST_RULES = dist-subdircreate
+
+dist-subdircreate:
+	$(TOPDIR)/mkinstalldirs $(DIST_DIR)/Common/inc
+	$(TOPDIR)/mkinstalldirs $(DIST_DIR)/Linux/inc
+
+include $(TOPDIR)/Postamble.make

Added: trunk/libocfs/bindraw.c
===================================================================
--- trunk/libocfs/bindraw.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/bindraw.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,130 @@
+
+/*
+ * bindraw.c
+ *
+ * Binds device to first available raw device
+ *
+ * Copyright (C) 2004, Oracle.  All rights reserved.
+ *
+ * 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 021110-1307, USA.
+ *
+ * Authors: Sunil Mushran
+ */
+
+#include <sys/raw.h>
+
+#include "libocfs.h"
+
+/*
+ * bind_raw()
+ *
+ */
+int bind_raw(char *blk_dev, int *raw_minor, char *raw_dev, int rdlen)
+{
+	int fd = 0;
+	int i;
+	struct raw_config_request rcs;
+	struct stat statbuf;
+	int ret = -1;
+
+	memset(&statbuf, 0, sizeof(struct stat));
+	if (stat(blk_dev, &statbuf) == -1) {
+		LOG_ERROR("%s", strerror(errno));
+		goto bail;
+	}
+
+	if (MAJOR(statbuf.st_rdev) == 0) {
+		LOG_ERROR("Invalid device %s", blk_dev);
+		goto bail;
+	}
+
+	if (strstr(blk_dev, "/dev/raw")) {
+		strncpy(raw_dev, blk_dev, rdlen-1);
+		raw_dev[rdlen-1] = '\0';
+	}
+	else {
+		fd = open("/dev/rawctl", O_RDWR);
+		if (fd == -1) {
+			LOG_ERROR("Error opening /dev/rawctl.\n%s",
+				  strerror(errno));
+			goto bail;
+		}
+
+		for (i = 1; i < 255; ++i) {
+			memset(&rcs, 0, sizeof(struct raw_config_request));
+			rcs.raw_minor = i;
+			if (ioctl(fd, RAW_GETBIND, &rcs) == -1)
+				continue;
+			if (rcs.block_major == 0)
+				break;
+		}
+
+		if (i >= 255) {
+			LOG_ERROR("unable to find a free raw device /dev/raw/rawXX");
+			goto bail;
+		}
+
+		*raw_minor = i;
+		snprintf(raw_dev, rdlen, "/dev/raw/raw%d", i);
+
+		rcs.raw_minor = i;
+		rcs.block_major = (__u64)MAJOR(statbuf.st_rdev);
+		rcs.block_minor = (__u64)MINOR(statbuf.st_rdev);
+		if (ioctl(fd, RAW_SETBIND, &rcs) == -1) {
+			LOG_ERROR("%s", strerror(errno));
+			goto bail;
+		}
+	}
+
+	ret = 0;
+bail:
+	if (fd)
+		close(fd);
+	return ret;
+}				/* bind_raw */
+
+/*
+ * unbind_raw()
+ *
+ */
+void unbind_raw(int raw_minor, char *raw_dev)
+{
+	int fd = 0;
+	struct raw_config_request rcs;
+	
+	if (raw_minor == 0)
+		goto bail;
+
+	fd = open("/dev/rawctl", O_RDWR);
+	if (fd == -1) {
+		LOG_ERROR("Error opening /dev/rawctl.\n%s",
+			  strerror(errno));
+		goto bail;
+	}
+
+	rcs.raw_minor = raw_minor;
+	rcs.block_major = 0;
+	rcs.block_minor = 0;
+	if (ioctl(fd, RAW_SETBIND, &rcs) == -1) {
+		LOG_ERROR("%s", strerror(errno));
+		goto bail;
+	}
+
+bail:
+	if (fd)
+		close(fd);
+	return ;
+}				/* unbind_raw */

Added: trunk/libocfs/libocfs.c
===================================================================
--- trunk/libocfs/libocfs.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/libocfs.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,256 @@
+/*
+ * libocfs.c
+ *
+ * provides dummy functions for userspace tools
+ * to allow ocfs kernel module source to work in userspace
+ *
+ * Copyright (C) 2002, 2003 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Kurt Hackel
+ */
+
+#define DUMMY_C_LOCAL_DECLS
+#include <libocfs.h>
+#undef DUMMY_C_LOCAL_DECLS
+#include <string.h>
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+
+long TIME_ZERO = 0;
+__u32 osb_id;
+__u32 mount_cnt;
+ocfs_ipc_ctxt OcfsIpcCtxt;
+
+#if 0
+ocfs_global_ctxt OcfsGlobalCtxt = {
+	.pref_node_num = -1,
+	.node_name = "userspacetool",
+	.comm_info = {OCFS_UDP, "0.0.0.0", OCFS_IPC_DEFAULT_PORT, NULL}
+};
+#endif
+extern ocfs_global_ctxt OcfsGlobalCtxt;
+
+bool ocfs_linux_get_inode_offset (struct inode * inode, __u64 * off, ocfs_inode ** oin)
+{
+    return false;
+}
+
+bool ocfs_linux_get_dir_entry_offset (ocfs_super * osb, __u64 * off, __u64 parentOff,
+				struct qstr * fileName, ocfs_file_entry ** fileEntry)
+{
+    return false;
+}
+
+void complete(struct completion *c)
+{
+}
+
+void ocfs_release_cached_oin (ocfs_super * osb, ocfs_inode * oin)
+{
+}
+
+void init_waitqueue_head(wait_queue_head_t *q)
+{
+}
+
+void init_MUTEX (struct semaphore *sem)
+{
+}
+
+
+void truncate_inode_pages(struct address_space *as, loff_t off)
+{
+}
+
+unsigned int kdev_t_to_nr(kdev_t dev)
+{
+	return 0;
+}
+
+void init_special_inode(struct inode *inode, umode_t mode, int x)
+{
+}
+
+int fsync_inode_buffers(struct inode *inode)
+{
+	return 0;
+}
+
+void d_prune_aliases(struct inode *inode)
+{
+
+}
+
+void get_random_bytes(void *buf, int nbytes)
+{
+	FILE *f;
+
+	f = fopen("/dev/random", "r");
+	if (!f) {
+		fprintf(stderr, "get_random_bytes: cannot open /dev/random\n");
+		exit(1);
+	}
+	if (fread(buf, 1, nbytes, f) != nbytes) {
+		fprintf(stderr, "get_random_bytes: cannot read /dev/random\n");
+		fclose(f);
+		exit(1);
+	}
+	fclose(f);
+}
+
+char *ocfs_strerror(int errnum) 
+{
+	return strerror(errnum);
+}
+
+void *ocfs_linux_dbg_alloc(int Size, char *file, int line)
+{
+    return malloc_aligned(Size);
+}
+void ocfs_linux_dbg_free (const void *Buffer)
+{
+    free_aligned((void *)Buffer);
+}
+
+int ocfs_write_disk(ocfs_super * vcb, void *buf, __u32 len, __u64 off)
+{
+    return ocfs_write_force_disk(vcb, buf, len, off);
+}
+
+int LinuxWriteForceDisk(ocfs_super * vcb, void *buf, __u32 len, __u64 off,
+			bool cached)
+{
+    int fd;
+    
+    fd = (int) vcb->sb->s_dev;
+
+    lseek64(fd, off, SEEK_SET);
+
+    if (write(fd, buf, len) == -1) {
+	    fprintf(stderr, "fd is %d\n", fd);
+	    fprintf(stderr, "LinuxWriteForceDisk: Could not write: %s\n", strerror(errno));
+	    return(-EFAIL);
+    }
+    
+    return 0;
+}
+
+int ocfs_write_force_disk(ocfs_super * vcb, void *buf, __u32 len, __u64 off)
+{
+    return LinuxWriteForceDisk(vcb, buf, len, off, false);
+}
+#if 0
+int ocfs_write_metadata(ocfs_super * vcb, void *buf, __u32 len, __u64 off)
+{
+    return ocfs_write_force_disk(vcb, buf, len, off);
+}
+#endif
+
+int ocfs_read_force_disk_ex (ocfs_super * osb, void **Buffer, __u32 AllocLen,
+			     __u32 ReadLen, __u64 Offset)
+{
+	return ocfs_read_disk_ex(osb, Buffer, AllocLen, ReadLen, Offset);
+}
+int ocfs_read_disk_ex (ocfs_super * osb, void **Buffer, __u32 AllocLen,
+		       __u32 ReadLen, __u64 Offset) 
+{
+	if (!Buffer)
+		return -EINVAL;
+	if (!*Buffer) {
+		*Buffer = malloc_aligned(AllocLen);
+		if (!*Buffer)
+			return -ENOMEM;
+	}
+	return ocfs_read_disk(osb, *Buffer, ReadLen, Offset);
+}
+
+
+int ocfs_read_disk(ocfs_super * vcb, void *buf, __u32 len, __u64 off)
+{
+    int fd;
+
+    fd = (int) vcb->sb->s_dev;
+
+    lseek64(fd, off, SEEK_SET);
+
+    if (read(fd, buf, len) == -1) {
+	    fprintf(stderr, "ocfs_read_disk: Could not read: %s\n", strerror(errno));
+	    return(-EFAIL);
+    }
+
+    return (0);
+}
+
+int LinuxReadForceDisk(ocfs_super * VCB, void *Buffer, __u32 Length,
+		       __u64 Offset, bool Cached)
+{
+    return ocfs_read_disk(VCB, Buffer, Length, Offset);
+}
+int ocfs_read_force_disk(ocfs_super * VCB, void *Buffer, __u32 Length, __u64 Offset)
+{
+    return ocfs_read_disk(VCB, Buffer, Length, Offset);
+}
+#if 0
+int ocfs_read_metadata(ocfs_super * VCB, void *Buffer, __u32 Length, __u64 Offset)
+{
+    return ocfs_read_disk(VCB, Buffer, Length, Offset);
+}
+#endif
+
+
+ocfs_super *get_fake_vcb(int fd, ocfs_vol_disk_hdr * hdr, int nodenum)
+{
+    ocfs_super *vcb;
+
+    /* fake a few VCB values */
+    vcb = (ocfs_super *) malloc_aligned(sizeof(ocfs_super));
+    if (!vcb)
+	    return NULL;
+    vcb->sb = malloc_aligned(sizeof(struct super_block));
+    if (!vcb->sb) {
+	    free_aligned(vcb);
+	    return NULL;
+    }
+
+    vcb->vol_layout.root_start_off = hdr->root_off;
+    vcb->vol_layout.root_int_off = hdr->internal_off;
+    vcb->vol_layout.cluster_size = hdr->cluster_size;
+    vcb->vol_layout.data_start_off = hdr->data_start_off;
+    vcb->vol_layout.node_cfg_off = hdr->node_cfg_off;
+    vcb->vol_layout.node_cfg_size = hdr->node_cfg_size;
+
+    vcb->sect_size = 512;
+    vcb->curr_trans_id = 0;
+    vcb->sb->s_dev = fd;
+    vcb->node_num = nodenum;
+
+    return vcb;
+}
+
+
+void * malloc_aligned(int size)
+{
+	return memalign(512, size);
+}
+
+void free_aligned(void *ptr)
+{
+	if (ptr)
+		free(ptr);
+}

Added: trunk/libocfs/libocfs.h
===================================================================
--- trunk/libocfs/libocfs.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/libocfs/libocfs.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,464 @@
+/*
+ * libocfs.h
+ *
+ * kernel dummy types, macros, etc. used by userspace tools
+ *
+ * Copyright (C) 2002, 2003 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Kurt Hackel, Sunil Mushran
+ */
+
+#ifndef _LIBOCFS_H_
+#define _LIBOCFS_H_
+
+#ifndef DUMMY_C_LOCAL_DECLS
+extern long TIME_ZERO;
+#endif
+
+/* Horrific, for SuSE */
+#ifdef __ia64__
+#define ia64_cmpxchg(sem,ptr,old,new,size)						\
+({											\
+	__typeof__(ptr) _p_ = (ptr);							\
+	__typeof__(new) _n_ = (new);							\
+	__u64 _o_, _r_;									\
+											\
+	switch (size) {									\
+	      case 1: _o_ = (__u8 ) (long) (old); break;				\
+	      case 2: _o_ = (__u16) (long) (old); break;				\
+	      case 4: _o_ = (__u32) (long) (old); break;				\
+	      case 8: _o_ = (__u64) (long) (old); break;				\
+	      default: break;								\
+	}										\
+	 __asm__ __volatile__ ("mov ar.ccv=%0;;" :: "rO"(_o_));				\
+	switch (size) {									\
+	      case 1:									\
+		__asm__ __volatile__ ("cmpxchg1."sem" %0=[%1],%2,ar.ccv"		\
+				      : "=r"(_r_) : "r"(_p_), "r"(_n_) : "memory");	\
+		break;									\
+											\
+	      case 2:									\
+		__asm__ __volatile__ ("cmpxchg2."sem" %0=[%1],%2,ar.ccv"		\
+				      : "=r"(_r_) : "r"(_p_), "r"(_n_) : "memory");	\
+		break;									\
+											\
+	      case 4:									\
+		__asm__ __volatile__ ("cmpxchg4."sem" %0=[%1],%2,ar.ccv"		\
+				      : "=r"(_r_) : "r"(_p_), "r"(_n_) : "memory");	\
+		break;									\
+											\
+	      case 8:									\
+		__asm__ __volatile__ ("cmpxchg8."sem" %0=[%1],%2,ar.ccv"		\
+				      : "=r"(_r_) : "r"(_p_), "r"(_n_) : "memory");	\
+		break;									\
+											\
+	      default:									\
+		_r_ = 0;								\
+		break;									\
+	}										\
+	(__typeof__(old)) _r_;								\
+})
+
+#define cmpxchg_acq(ptr,o,n)	ia64_cmpxchg("acq", (ptr), (o), (n), sizeof(*(ptr)))
+#endif
+
+/* Get large file support */
+#define _GNU_SOURCE
+
+/* plain old user stuff */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+
+/* reqd by ocfsformat */
+#undef WNOHANG
+#undef WUNTRACED
+#include <linux/fs.h>
+
+#include <pthread.h>
+#include <sched.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+
+
+/* it sucks, but i have to fake a few types to get by */
+#define INIT_LIST_HEAD(a)	do { } while(0)
+#define list_add_tail(a,b)	do { } while(0)
+#define list_del(a)		do { } while(0)
+#define spin_lock_init(lock)    do { } while(0)
+#define spin_lock(lock)         (void)(lock) /* Not "unused variable". */
+#define spin_is_locked(lock)    (0)
+#define spin_trylock(lock)      ({1; })
+#define spin_unlock_wait(lock)  do { } while(0)
+#define spin_unlock(lock)       do { } while(0)
+#define down(x)			do { } while(0)
+#define up(x)			do { } while(0)
+#define init_timer(x)		do { } while(0)
+#define wake_up(x)		do { } while(0)
+#define max(a,b)		((a) < (b) ? (b) : (a))
+#define min(a,b)		((a) < (b) ? (a) : (b))
+#define CURRENT_TIME		(time(NULL))
+#define init_completion(x)	do { } while(0)
+#define HZ			(100)
+#define jiffies                 ({ struct timeval tv; \
+				   long j; \
+				   gettimeofday(&tv, NULL); \
+				   if (TIME_ZERO==0) \
+				     TIME_ZERO = tv.tv_sec; \
+				   j = (tv.tv_sec - TIME_ZERO) * HZ; \
+				   if (j < 0) \
+				     j = 0; \
+				   j += ((tv.tv_usec) / (1000000 / HZ)); \
+				   (j); })
+#define time_after(a,b)		((long)(b) - (long)(a) < 0)
+#define kmalloc(a, b) malloc_aligned(a)
+#define vmalloc(a)    malloc_aligned(a)
+#define kfree(a)      free_aligned(a)
+#define vfree(a)      free_aligned(a)
+#define fsync_no_super(fd)     fsync(fd)
+#define printk(a, x...)    fprintf(stderr, a, ##x)
+#define BUG()              fprintf(stderr, "BUG!\n")
+
+#define OCFS_PAGE_SIZE  4096
+#define IN
+#define OUT
+#define KERN_ERR   
+#define FILE_BUFFER_SIZE  (1048576 * 2)
+#define ATTR_MODE       1
+#define ATTR_UID        2
+#define ATTR_GID        4
+#define ATTR_SIZE       8
+#define ATTR_ATIME      16
+#define ATTR_MTIME      32
+#define ATTR_CTIME      64
+#define ATTR_ATIME_SET  128
+#define ATTR_MTIME_SET  256
+#define ATTR_FORCE      512     /* Not a change, but a change it */
+#define ATTR_ATTR_FLAG  1024
+#define NODEV 0
+
+#ifndef UINT_MAX
+#define UINT_MAX	(~0U)
+#endif
+#ifndef ULONG_MAX
+#define ULONG_MAX	(~0U)
+#endif
+
+
+
+#define DELETED_FLAGS  (OCFS_SYNC_FLAG_DELETED | \
+			OCFS_SYNC_FLAG_MARK_FOR_DELETION | \
+			OCFS_SYNC_FLAG_NAME_DELETED)
+
+
+
+typedef unsigned short kdev_t;
+
+struct buffer_head {
+	int a;
+};
+
+struct address_space {
+	int a;
+};
+
+struct iattr { 
+    unsigned long long ia_size;
+    int ia_uid;
+    int ia_gid;
+    int ia_mode;
+    int ia_ctime;
+    int ia_mtime;
+    int ia_valid;
+};
+
+typedef int spinlock_t;
+typedef int wait_queue_head_t;
+
+struct completion {
+	unsigned int done;
+	wait_queue_head_t wait;
+};
+
+struct timer_list {
+	unsigned long expires;
+	unsigned long data;
+	void (*function)(unsigned long);
+};
+
+struct super_block
+{
+    int s_dev;
+    union {
+	    void *generic_sbp;
+    } u;
+};
+
+struct semaphore
+{
+    int semid;
+};
+struct list_head
+{
+    int a;
+};
+struct inode
+{
+    void * i_mapping;
+    struct list_head i_dentry;
+    int i_nlink;
+    struct super_block *i_sb;
+    unsigned int i_flags;
+    unsigned long i_ino;
+    int i_mode;
+    unsigned long long i_size;
+    int i_uid;
+    int i_gid;
+    unsigned long i_blocks;
+    unsigned long i_blksize;
+    int i_ctime;
+    int i_atime;
+    int i_mtime;
+    kdev_t i_rdev;
+    union {
+        void *generic_ip;
+    } u;
+};
+struct qstr {
+	const unsigned char * name; 
+	unsigned int len;
+	unsigned int hash;
+};
+struct dentry 
+{
+	struct qstr d_name;
+	struct inode *d_inode;
+};
+typedef int kmem_cache_t;
+struct tq_struct
+{
+    int a;
+};
+
+
+struct task_struct
+{
+    pthread_t thread;
+};
+
+union semun {
+	int val;                    /* value for SETVAL */
+	struct semid_ds *buf;       /* buffer for IPC_STAT, IPC_SET */
+	unsigned short int *array;  /* array for GETALL, SETALL */
+	struct seminfo *__buf;      /* buffer for IPC_INFO */
+};
+
+/* aligned alloc prototypes */
+void *memalign(size_t boundary, size_t size);
+void * malloc_aligned(int size);
+void free_aligned(void *ptr);
+
+#ifndef ATOMIC_INIT
+
+/* atomic_t stuff */
+
+#if !defined(_ASM_IA64_ATOMIC_H) && !defined(__ARCH_X86_64_ATOMIC__) && !defined(__ARCH_I386_ATOMIC__)
+typedef struct { volatile int counter; } atomic_t;
+#endif
+
+#define ATOMIC_INIT(i)  { (i) }
+
+#define atomic_read(v)          ((v)->counter)
+#define atomic_set(v,i)         (((v)->counter) = (i))
+
+static inline void atomic_inc(atomic_t *v)
+{
+    v->counter++;
+}
+
+static inline int atomic_dec_and_test(atomic_t *v)
+{
+    v->counter--;
+    return v->counter != 0;
+}
+#endif
+
+#ifndef smp_mb__before_clear_bit
+/* bitops (taken from asm-generic) */
+
+static inline void set_bit(int nr, void *addr)
+{
+    unsigned long mask = 1UL << (nr & 0x1f);
+    unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
+
+    *p |= mask;
+}
+
+static inline void clear_bit(int nr, void *addr)
+{
+    unsigned long mask = 1UL << (nr & 0x1f);
+    unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
+
+    *p &= ~mask;
+}
+
+static inline int test_bit(int nr, const void *addr)
+{
+    return (1 & (((const unsigned int *) addr)[nr >> 5] >> (nr & 31))) != 0;
+}
+
+static inline int __test_and_clear_bit(int nr, volatile void *addr)
+{
+    unsigned long mask = 1UL << (nr & 0x1f);
+    unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
+    unsigned long old = *p;
+
+    *p = old & ~mask;
+    return (old & mask) != 0;
+}
+
+static inline unsigned long ffz(unsigned long word)
+{
+    unsigned long result = 0;
+                                                                                
+    while(word & 1) {
+            result++;
+            word >>= 1;
+    }
+    return result;
+}
+
+/* FIXME: This is a really really crappy quick and dirty thing */
+static inline unsigned long find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
+{
+    unsigned long bits = sizeof(unsigned long) * 8;
+    unsigned long bits1 =  bits - 1;
+    unsigned long * p = ((unsigned long *) addr) + (offset >> 6);
+    unsigned long result = offset & ~bits1;
+    unsigned long tmp;
+
+    if (offset >= size)
+        return size;
+    size -= result;
+    offset &= bits1;
+    if (offset) {
+        tmp = *(p++);
+        tmp |= ~0UL >> (bits-offset);
+        if (size < bits)
+            goto found_first;
+        if (~tmp)
+            goto found_middle;
+        size -= bits;
+        result += bits;
+    }
+    while (size & ~bits1) {
+        if (~(tmp = *(p++)))
+            goto found_middle;
+        result += bits;
+        size -= bits;
+    }
+    if (!size)
+        return result;
+    tmp = *p;
+found_first:
+    tmp |= ~0UL << size;
+    if (tmp == ~0UL)        /* Are any bits zero? */
+        return result + size; /* Nope. */
+found_middle:
+    return result + ffz(tmp);
+}
+#endif
+
+
+/* include all the rest from ocfs.h */
+#include <ocfsbool.h>
+#include <ocfscom.h>
+#include <ocfsconst.h>
+#include <ocfshash.h>
+#include <ocfstrace.h>
+#include <ocfsvol.h>
+#include <ocfsdisk.h>
+#include <ocfsdef.h>
+#include <ocfstrans.h>
+#include <ocfsdlm.h>
+#include <ocfsver.h>
+#include <ocfsiosup.h>
+#include <ocfsport.h>
+#include <ocfsgenmisc.h>
+#include <ocfsgenalloc.h>
+#include <ocfsgencreate.h>
+#include <ocfsgendirnode.h>
+#include <ocfsgendlm.h>
+#include <ocfsheartbeat.h>
+#include <ocfsgennm.h>
+#include <ocfsgensysfile.h>
+#include <ocfsgentrans.h>
+#include <ocfsgenutil.h>
+#include <ocfsgenvolcfg.h>
+#include <ocfsgenvote.h>
+#include <ocfsbitmap.h>
+#include <ocfsdlmp.h>
+#include <ocfsfile.h>
+#include <ocfsioctl.h>
+//#include <ocfsipc.h>
+#include <ocfsmain.h>
+#include <ocfsmount.h>
+#include <ocfsproc.h>
+
+
+/* Error reporting convenience function */
+#define LOG_ERROR(fmt, arg...)						\
+	do {								\
+		fprintf(stderr, "ERROR: ");				\
+		fprintf(stderr, fmt, ## arg);				\
+		fprintf(stderr, ", %s, %d\n", __FILE__, __LINE__);	\
+		fflush(stderr);						\
+	} while (0)
+
+
+/* prototypes for fake functions in libocfs.c */
+void complete(struct completion *c);
+void init_waitqueue_head(wait_queue_head_t *q);
+void init_MUTEX (struct semaphore *sem);
+void truncate_inode_pages(struct address_space *as, loff_t off);
+unsigned int kdev_t_to_nr(kdev_t dev);
+void init_special_inode(struct inode *inode, umode_t mode, int x);
+int fsync_inode_buffers(struct inode *inode);
+void d_prune_aliases(struct inode *inode);
+void get_random_bytes(void *buf, int nbytes);
+char *ocfs_strerror(int errnum) ;
+ocfs_super *get_fake_vcb(int fd, ocfs_vol_disk_hdr * hdr, int nodenum);
+
+/* raw device binding functions */
+
+int bind_raw(char *blk_dev, int *raw_minor, char *raw_dev, int rdlen);
+void unbind_raw(int raw_minor, char *raw_dev);
+
+
+#endif

Added: trunk/load_ocfs/Makefile
===================================================================
--- trunk/load_ocfs/Makefile	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/load_ocfs/Makefile	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,18 @@
+TOPDIR = ..
+
+include $(TOPDIR)/Preamble.make
+
+SBIN_EXTRA = load_ocfs
+
+MANS = load_ocfs.1
+
+INSTALL_RULES = install-ocfs2
+
+install-ocfs2: install-sbin-extra
+	cd $(DESTDIR)$(sbindir) \
+	&& rm -f load_ocfs2 \
+	&& $(LN_S) load_ocfs load_ocfs2
+
+DIST_FILES = load_ocfs.1.in
+
+include $(TOPDIR)/Postamble.make

Added: trunk/load_ocfs/load_ocfs
===================================================================
--- trunk/load_ocfs/load_ocfs	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/load_ocfs/load_ocfs	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,572 @@
+#!/bin/sh
+
+#
+# This is a smart module loader.  The main loading engine should work
+# untouched.
+#
+# A parameter for the module must be listed in the
+# VALID_PARMS shell variable.  This variable is a colon-separated list
+# of the valid module parameters.  Parameters that are required
+# must also be listed in the REQUIRED_PARMS shell variable.  This is
+# also a colon-separated list.
+#
+# This script now supports multiple versions of a module.  Often, one
+# version of the module will support a parameter that another version
+# does not.  The union of all possible parameters should be in the
+# VALID_PARMS list.  Each module version should specify the appropriate
+# subset in the USED_PARMS list.  The USED_PARMS list should contain
+# at least the REQUIRED_PARMS list.  It then adds any parameters shared
+# between modules and any parameters unique to this version of the
+# module.  This allows the configuration file to support multiple
+# module versions, ignoring the parameters for a version of the module
+# not in this use.
+#
+# Validation of parameter values can also be done.  If a shell function
+# of the name validate_<variable_name> exists, it will be run with the
+# parameter value as its only argument.  If it fails, module loading
+# will fail.
+#
+# Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+#
+# 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 recieved 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 021110-1307, USA.
+#
+# Author: Joel Becker <joel.becker at oracle.com>
+#
+
+#
+##################################################################
+#
+# Edit MODULE and CONFIG to specify the module name and the
+# configuration file location.
+#
+# Edit VALID_PARMS and REQUIRED_PARMS to specify the parameters
+# allowed and required.  Also, add any validation functions needed.
+#
+# If there are multiple versions of the module, set the USED_PARMS list
+# for each version.  Also, use the load_* switch to choose the module
+# name and which USED_PARMS list to use.
+#
+
+# Force LC_ALL=C for proper ifconfig(8) parsing
+export LC_ALL=C
+
+# Path to configuration file
+CONFIG=/etc/ocfs.conf
+
+# Set VALID_PARMS to the untion of all parameters valid for the modules
+# this script suppports.  Set REQUIRED_PARMS to the parameters requred
+# by all the modules this script supports.
+COMMON_PARMS="node_name:node_number:debug_context:debug_level:ip_address:guid:comm_voting"
+VALID_PARMS="$COMMON_PARMS:ip_port:ip_port_v2"
+REQUIRED_PARMS="node_name:ip_address:guid"
+
+# Multi-module switch.  The script's argv0 is used to determine the
+# module name.
+MODULE_SCRIPT="`basename $0`"
+MODULE="${MODULE_SCRIPT#load_}"
+case "$MODULE" in
+ocfs2)
+    REQUIRED_PARMS="$REQUIRED_PARMS:ip_port_v2"
+    USED_PARMS="$COMMON_PARMS:ip_port_v2"
+    ;;
+ocfs)
+    REQUIRED_PARMS="$REQUIRED_PARMS:ip_port"
+    USED_PARMS="$COMMON_PARMS:ip_port"
+    ;;
+esac
+
+# If you must hardcode an absolute module path for testing, do it HERE.
+# MODULE=/path/to/test/module/ocfsX.o
+
+# Helper function for IP addresses
+check_ip()
+{
+    ADDR="$1"
+    case "$ADDR" in
+    *[^0-9.]*)
+        ;;
+    *)
+        R=${ADDR}
+        IP0=${R%%.*}
+        R=${R#*.}
+        IP1=${R%%.*}
+        R=${R#*.}
+        IP2=${R%%.*}
+        R=${R#*.}
+        IP3=$R
+        if [ -n "$IP0" -a -n "$IP1" -a -n "$IP2" -a -n "$IP3" ]
+        then
+            if [ "$IP0" -gt -1 -a "$IP0" -lt 256 -a \
+                 "$IP1" -gt -1 -a "$IP1" -lt 256 -a \
+                 "$IP2" -gt -1 -a "$IP2" -lt 256 -a \
+                 "$IP3" -gt -1 -a "$IP3" -lt 256 ]
+            then
+                return 0
+            fi
+        fi
+        ;;
+    esac
+    
+    log "IP address \"$ADDR\" is invalid"
+    return 1
+}
+
+# Helper function to verify an address is associated with an interface
+check_ifconfig()
+{
+    ADDR="$1"
+    IFCONFIG="`ifconfig 2>/dev/null`"
+    if [ "$?" != 0 ]
+    then
+        log "Unable to run ifconfig"
+        return 1
+    fi
+
+    case "$IFCONFIG" in
+    *addr:"$ADDR"[\ \	]*)
+        return 0
+        ;;
+    *)
+        ;;
+    esac
+
+    log "IP address \"$ADDR\" is not associated with an interface"
+    return 1
+}
+
+# Validate the ip_address module parameter
+validate_ip_address()
+{
+    ADDR="$1"
+
+    if ! check_ip "$ADDR"
+    then
+        return 1
+    fi
+    if ! check_ifconfig "$ADDR"
+    then
+        return 1
+    fi
+
+    return 0
+}
+
+# Validate the ip_port module parameter
+validate_ip_port()
+{
+    PORT="$1"
+
+    case "$PORT" in
+    *[^0-9]*)
+        return 1
+        ;;
+    *)
+        ;;
+    esac
+
+    return 0
+}
+
+# Validate the node_number module parameter
+validate_node_number()
+{
+    NUM="$1"
+
+    case "$NUM" in
+    *[^0-9]*)
+        ;;
+    *)
+        if [ "$NUM" -gt -1 -o "$NUM" -lt 32 ]
+        then
+            return 0
+        fi
+        ;;
+    esac
+
+    log "Invalid node number: \"$NUM\""
+    return 1
+}
+
+# Validate the guid against the MAC address.  This depends on the IP
+validate_guid()
+{
+    GUID="`echo \"$1\" | tr \"a-z\" \"A-Z\"`"
+
+    if [ "`expr length "$GUID"`" != "32" ]
+    then
+        log "The GUID is not 32 characters"
+        return 1
+    fi
+
+    if [ -z "$ip_address" ]
+    then
+        log "No IP address is in the ocfs.conf file.  Please create
+	a correct configuration file."
+        return 1
+    fi
+
+    if ! check_ip "$ADDR"
+    then
+        log "The IP address is invalid."
+        return 1
+    fi
+
+    CUR_MAC=""
+    RES_MAC=`ifconfig 2>/dev/null | while read -r LINE
+    do
+        case "$LINE" in
+        *HWaddr\ *)
+            CUR_MAC="${LINE##*HWaddr }"
+            ;;
+        *\ addr:"$ip_address"\ *)
+            if [ -n "$CUR_MAC" ]
+            then
+                echo "$CUR_MAC" | sed -e 's/://g' | tr "a-z" "A-Z"
+                return 0
+            fi
+            ;;
+        "")
+            CUR_MAC=""
+            ;;
+        *)
+            ;;
+        esac
+    done`
+
+    if [ -z "$RES_MAC" ]
+    then
+        log "There is no active interface for the IP address $ip_address"
+        return 1
+    fi
+
+    if [ "${GUID%$RES_MAC}" = "$GUID" ]
+    then
+        log "The GUID does not match the current MAC address for $ip_address.
+	If this is a new node, please run 'ocfs_uid_gen -c' to create
+	a new GUID for this node.  If this node already belongs to a
+	filesystem and the MAC address of the machine has changed,
+	please run 'ocfs_uid_gen -r'."
+        return 1
+    fi
+
+    # Here we hack in the cs value for the OCFS module.  Note
+    # That this is in module-specific validate_* code, not the
+    # generic engine
+
+    GC="${GUID}"
+
+    CS=0
+    while expr length "$GC" >/dev/null 2>&1
+    do
+        LETTER="`expr substr "$GC" 1 1 2>/dev/null`" 
+        GC="${GC#$LETTER}"
+        case "$LETTER" in
+        [0-9])
+            CS="`expr "$CS" + "$LETTER" + 48`"
+            ;;
+        A)
+            CS="`expr "$CS" + 65`"
+            ;;
+        B)
+            CS="`expr "$CS" + 66`"
+            ;;
+        C)
+            CS="`expr "$CS" + 67`"
+            ;;
+        D)
+            CS="`expr "$CS" + 68`"
+            ;;
+        E)
+            CS="`expr "$CS" + 69`"
+            ;;
+        F)
+            CS="`expr "$CS" + 70`"
+            ;;
+        *)
+            log "Invalid character in GUID: \"$LETTER\""
+            return 1
+            ;;
+        esac
+    done
+
+    # This is the real hack, modifying INSMOD
+    INSMOD="$INSMOD cs=\"$CS\""
+
+    # Hack #2, modifying $guid for uppercase
+    guid="$GUID"
+
+    return 0
+}
+
+
+#
+##################################################################
+#
+# Below here is the generic engine.  This code should not change.
+#
+
+# Check on insmod
+INSMOD="/sbin/insmod"
+if [ ! -x $INSMOD ]
+then
+	die "/sbin/insmod does not exist"
+fi
+INSMOD="$INSMOD $MODULE"
+
+log()
+{
+    echo "load_ocfs: $@" >&2
+}
+
+die()
+{
+    log "$@"
+    exit 1
+}
+
+lead_strip()
+{
+    LINE="$@"
+    NEWLINE="${LINE# }"
+    while [ "$LINE" != "$NEWLINE" ]
+    do
+        LINE="$NEWLINE"
+        NEWLINE="${LINE# }"
+    done
+
+    echo "$LINE"
+}
+
+tail_strip()
+{
+    LINE="$@"
+    NEWLINE="${LINE% }"
+    while [ "$LINE" != "$NEWLINE" ]
+    do
+        LINE="$NEWLINE"
+        NEWLINE="${LINE% }"
+    done
+
+    echo "$LINE"
+}
+
+
+# Validate the valid parameter list
+case "$VALID_PARMS" in
+*[\ /-]*)
+    die "Module parameter list is invalid: \"$VALID_PARMS\""
+    ;;
+*)
+    ;;
+esac
+
+# Validate the required parameter list
+TREQ="$REQUIRED_PARMS"
+while [ -n "$TREQ" ]
+do
+    TPARM="${TREQ%%:*}"
+    TREQ="${TREQ#*:}"
+    if [ "$TREQ" = "$TPARM" ]
+    then
+        TREQ=""
+    fi
+
+    case "$VALID_PARMS" in
+    *:"$TPARM":*|*:"$TPARM"|"$TPARM":*|"$TPARM")
+        ;;
+    *)
+        die "Required parameter \"$TPARM\" is not in VALID_PARMS"
+        ;;
+    esac
+done
+
+# Validate the used parameter list.  Yes, this repeats required ones.
+TUSE="$USED_PARMS"
+while [ -n "$TUSE" ]
+do
+    TPARM="${TUSE%%:*}"
+    TUSE="${TUSE#*:}"
+    if [ "$TUSE" = "$TPARM" ]
+    then
+        TUSE=""
+    fi
+
+    case "$VALID_PARMS" in
+    *:"$TPARM":*|*:"$TPARM"|"$TPARM":*|"$TPARM")
+        ;;
+    *)
+        die "Used parameter \"$TPARM\" is not in VALID_PARMS"
+        ;;
+    esac
+done
+
+# Do a quick validation of the command line arguments
+# Actually using the values comes later.
+for ORIGARG in "$@"
+do
+    ARG="`lead_strip "$ORIGARG"`"
+    case "$ARG" in
+    *=*)
+        PARM="`tail_strip "${ARG%%=*}"`"
+        case "$VALID_PARMS" in
+        *:"$PARM":*|*:"$PARM"|"$PARM":*|"$PARM")
+            ;;
+        *)
+            die "Unknown module parameter in argument: \"$ORIGARG\""
+            ;;
+        esac
+        ;;
+    *)
+        die "Invalid argument: \"$ORIGARG\""
+        ;;
+    esac
+done
+
+# Read config file
+while read -r RAWLINE
+do
+    LINE="`lead_strip "$RAWLINE"`"
+    LINE="`tail_strip "$LINE"`"
+    case "$LINE" in
+    \#*)
+        ;;
+    "")
+        ;;
+    *=*)
+        PARM="`tail_strip "${LINE%%=*}"`"
+        VALUE="`lead_strip "${LINE#*=}"`"
+        if [ -z "$PARM" ]
+        then
+            die "Invalid config line: \"$RAWLINE\""
+        fi
+        if [ -z "$VALUE" ]
+        then
+            continue
+        fi
+        case "$PARM" in
+        *[\ :/-]*)
+            die "Invalid module parameter name: \"$PARM\""
+            ;;
+        *)
+            ;;
+        esac
+        case "$VALID_PARMS" in
+        *:"$PARM":*|*:"$PARM"|"$PARM":*|"$PARM")
+            eval EARVAL=\""\$$PARM"\"
+            if [ -n "$EARVAL" ]
+            then
+                die "Module parameter \"$PARM\" is in the configuration file twice"
+            fi
+            eval $PARM=\""$VALUE"\"
+            ;;
+        *)
+            die "Unknown module parameter: \"$PARM\""
+            ;;
+        esac
+        ;;
+    *)
+        die "Invalid config line: \"$RAWLINE\""
+        ;;
+    esac
+done < "$CONFIG"
+
+# Now we actually use the arguments
+# It's after the config read to override configuration bits
+for ORIGARG in "$@"
+do
+    ARG="`lead_strip "$ORIGARG"`"
+    ARG="`tail_strip "$ARG"`"
+    case "$ARG" in
+    *=*)
+        PARM="`tail_strip "${ARG%%=*}"`"
+        VALUE="`lead_strip "${ARG#*=}"`"
+        # We checked the parameter's validity above
+        eval $PARM=\""$VALUE"\"
+        ;;
+    *)
+        die "Broken script: Invalid argument: \"$ORIGARG\""
+        ;;
+    esac
+done
+
+# Run the validate functions on the parameters.  This must happen
+# after all values have been loaded.
+TVALID="$VALID_PARMS"
+while [ -n "$TVALID" ]
+do
+    TPARM="${TVALID%%:*}"
+    TVALID="${TVALID#*:}"
+    if [ "$TVALID" = "$TPARM" ]
+    then
+        TVALID=""
+    fi
+    if [ -n "$TPARM" ]
+    then
+        eval VALUE=\""\$$TPARM"\"
+        if [ -n "$VALUE" ]
+        then
+            TYPE="`type "validate_$TPARM" 2>/dev/null | head -1`"
+            case "$TYPE" in
+            *\ function)
+                eval "validate_$TPARM" \""$VALUE"\"
+                if [ "$?" != 0 ]
+                then
+                    die "Parameter \"$TPARM\" is invalid"
+                fi
+                ;;
+            *)
+                ;;
+            esac
+            # Ignore parameters not in the USED list
+            case "$USED_PARMS" in
+            *:"$TPARM":*|*:"$TPARM"|"$TPARM":*|"$TPARM")
+                INSMOD="$INSMOD $TPARM=\"$VALUE\""
+                ;;
+            *)
+                ;;
+            esac
+        fi
+    fi
+done
+
+# Check for all required parameters
+TREQ="$REQUIRED_PARMS"
+while [ -n "$TREQ" ]
+do
+    TPARM="${TREQ%%:*}"
+    TREQ="${TREQ#*:}"
+    if [ "$TREQ" = "$TPARM" ]
+    then
+        TREQ=""
+    fi
+
+    case "$INSMOD" in
+    *" $TPARM="*)
+        ;;
+    *)
+        die "Required parameter \"$TPARM\" was not specified"
+        ;;
+    esac
+done
+
+sh -c "echo $INSMOD"
+sh -c "$INSMOD"
+if [ "$?" != 0 ]
+then
+    die "insmod failed"
+fi
+
+


Property changes on: trunk/load_ocfs/load_ocfs
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/load_ocfs/load_ocfs.1.in
===================================================================
--- trunk/load_ocfs/load_ocfs.1.in	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/load_ocfs/load_ocfs.1.in	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,22 @@
+.TH "load_ocfs" "1" "November 2003" "Version @VERSION@" "OCFS Manual Pages"
+.SH "NAME"
+load_ocfs \- Load the ocfs.o module according to the setup file /etc/ocfs.conf.
+.SH "SYNOPSIS"
+\fBload_ocfs\fR 
+.SH "DESCRIPTION"
+.PP 
+\fBload_ocfs\fR is used to load the \fIocfs.o\fR module into the kernel area. During the load process, it will validate all the parameters set in the file \fI/etc/ocfs.conf\fR. If the \fI/etc/ocfs.o\fR file is missing, then the module will not be loaded. Use the \fIocfstool\fR utility to generate the proper \fI/etc/ocfs.conf\fR file before using \fIload_ocfs\fR.
+.SH "OPTIONS"
+.TP
+
+.SH "BUGS"
+Stuff.
+
+.SH "SEE ALSO"
+.BR ocfs(5) ocfstool(1)
+
+.SH "AUTHORS"
+Oracle Corporation
+
+.SH "COPYRIGHT"
+Copyright \(co 2002 Oracle Corporation

Added: trunk/mkinstalldirs
===================================================================
--- trunk/mkinstalldirs	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/mkinstalldirs	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,143 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+
+scriptversion=2003-11-08.23
+
+# Original author: Noah Friedman <friedman at prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain.
+#
+# This file is maintained in Automake, please report
+# bugs to <bug-automake at gnu.org> or send patches to
+# <automake-patches at gnu.org>.
+
+errstatus=0
+dirmode=""
+
+usage="\
+Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ...
+
+Create each directory DIR (with mode MODE, if specified), including all
+leading file name components.
+
+Report bugs to <bug-automake at gnu.org>."
+
+# process command line arguments
+while test $# -gt 0 ; do
+  case $1 in
+    -h | --help | --h*)         # -h for help
+      echo "$usage"
+      exit 0
+      ;;
+    -m)                         # -m PERM arg
+      shift
+      test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
+      dirmode=$1
+      shift
+      ;;
+    --version)
+      echo "$0 $scriptversion"
+      exit 0
+      ;;
+    --)                         # stop option processing
+      shift
+      break
+      ;;
+    -*)                         # unknown option
+      echo "$usage" 1>&2
+      exit 1
+      ;;
+    *)                          # first non-opt arg
+      break
+      ;;
+  esac
+done
+
+for file
+do
+  if test -d "$file"; then
+    shift
+  else
+    break
+  fi
+done
+
+case $# in
+  0) exit 0 ;;
+esac
+
+case $dirmode in
+  '')
+    if mkdir -p -- . 2>/dev/null; then
+      echo "mkdir -p -- $*"
+      exec mkdir -p -- "$@"
+    else
+      # On NextStep and OpenStep, the `mkdir' command does not
+      # recognize any option.  It will interpret all options as
+      # directories to create, and then abort because `.' already
+      # exists.
+      test -d ./-p && rmdir ./-p
+      test -d ./-- && rmdir ./--
+    fi
+    ;;
+  *)
+    if mkdir -m "$dirmode" -p -- . 2>/dev/null; then
+      echo "mkdir -m $dirmode -p -- $*"
+      exec mkdir -m "$dirmode" -p -- "$@"
+    else
+      # Clean up after NextStep and OpenStep mkdir.
+      for d in ./-m ./-p ./-- "./$dirmode";
+      do
+        test -d $d && rmdir $d
+      done
+    fi
+    ;;
+esac
+
+for file
+do
+  set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+  shift
+
+  pathcomp=
+  for d
+  do
+    pathcomp="$pathcomp$d"
+    case $pathcomp in
+      -*) pathcomp=./$pathcomp ;;
+    esac
+
+    if test ! -d "$pathcomp"; then
+      echo "mkdir $pathcomp"
+
+      mkdir "$pathcomp" || lasterr=$?
+
+      if test ! -d "$pathcomp"; then
+	errstatus=$lasterr
+      else
+	if test ! -z "$dirmode"; then
+	  echo "chmod $dirmode $pathcomp"
+	  lasterr=""
+	  chmod "$dirmode" "$pathcomp" || lasterr=$?
+
+	  if test ! -z "$lasterr"; then
+	    errstatus=$lasterr
+	  fi
+	fi
+      fi
+    fi
+
+    pathcomp="$pathcomp/"
+  done
+done
+
+exit $errstatus
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:


Property changes on: trunk/mkinstalldirs
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/ocfs_uid_gen/Makefile
===================================================================
--- trunk/ocfs_uid_gen/Makefile	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfs_uid_gen/Makefile	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,11 @@
+TOPDIR = ..
+
+include $(TOPDIR)/Preamble.make
+
+SBIN_EXTRA = ocfs_uid_gen
+
+MANS = ocfs_uid_gen.1
+
+DIST_FILES = ocfs_uid_gen ocfs_uid_gen.1.in
+
+include $(TOPDIR)/Postamble.make

Added: trunk/ocfs_uid_gen/ocfs_uid_gen
===================================================================
--- trunk/ocfs_uid_gen/ocfs_uid_gen	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfs_uid_gen/ocfs_uid_gen	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,394 @@
+#!/bin/sh
+
+#
+# ocfs_uid_gen - Generate a GUID for an OCFS node.
+# 
+# The GUID for an OCFS node is a 128 bit quantity.  The first 80 bits
+# are called the "host portion"  This portion is unique per node, and
+# remains with a node for its lifetime in the cluster.  The remaining
+# 48 bits are the MAC address of the interface used for cluster IPC.
+# If a node's MAC address changes due to a change of interface or the
+# replacement of a NIC, the host portion of the GUID remains the same,
+# but the MAC portion of the GUID is updated to reflect the new
+# hardware.
+#
+# Usage: ocfs_uid_gen -c [-f]
+#        ocfs_uid_gen -r
+#        ocfs_uid_gen -h
+#
+#        The '-c' option specifies creation of a new GUID.  The new
+#        GUID will contain a new host portion and the MAC address
+#        for the IP address contained in the ocfs.conf file.  If a
+#        GUID already exists in the ocfs.conf file, the '-f' option is
+#        required to overwrite it.
+#
+#        The '-r' option specifies recovery of the GUID.  The existing
+#        GUID in ocfs.conf will be updated, retaining the host portion
+#        and changing the MAC address to the MAC for the IP address
+#        contained in the ocfs.conf file.
+#
+# Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+#
+# 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 recieved 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 021110-1307, USA.
+#
+# Author: Joel Becker
+#
+
+
+# Force LC_ALL=C for proper ifconfig(8) parsing
+export LC_ALL=C
+
+#
+###################################################################
+# Variables
+#
+CONFIG="/etc/ocfs.conf"
+
+
+
+#
+###################################################################
+# Functions
+#
+
+# Print usage and exit
+print_usage()
+{
+    RC="$1"
+
+    if [ "$RC" != "0" ]
+    then
+        exec 1>&2
+    fi
+
+cat <<EOCAT
+Usage: ocfs_uid_gen -c
+       ocfs_uid_gen -r
+
+       -c    Create a new GUID for a new node before it enters the
+             cluster.
+       -r    Recover the GUID, inserting the new MAC address.  This
+             operation is only for existing nodes whose MAC address
+             has changed.
+EOCAT
+
+    exit $RC
+}
+
+# Output
+msg()
+{
+    echo "ocfs_uid_gen: $@"
+}
+
+log()
+{
+    echo "ocfs_uid_gen: $@" >&2
+}
+
+# Output and exit
+die()
+{
+    log "$@"
+    exit 1
+}
+
+# Strip leading spaces
+lead_strip()
+{
+    LINE="$@"
+    NEWLINE="${LINE# }"
+    while [ "$LINE" != "$NEWLINE" ]
+    do
+        LINE="$NEWLINE"
+        NEWLINE="${LINE# }"
+    done
+
+    echo "$LINE"
+}
+
+# Strip trailing spaces
+tail_strip()
+{
+    LINE="$@"
+    NEWLINE="${LINE% }"
+    while [ "$LINE" != "$NEWLINE" ]
+    do
+        LINE="$NEWLINE"
+        NEWLINE="${LINE% }"
+    done
+
+    echo "$LINE"
+}
+
+# Generate the 80 bits of host portion
+generate_bits()
+{
+    dd if=/dev/urandom bs=1 count=20 2>/dev/null | tr '\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377' '0000000000000000111111111111111122222222222222223333333333333333444444444444444455555555555555556666666666666666777777777777777788888888888888889999999999999999AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDDEEEEEEEEEEEEEEEEFFFFFFFFFFFFFFFF' 2>/dev/null
+}
+
+# Find the MAC address of a given IP
+grab_mac()
+{
+    IP="$1"
+    if [ -z "$IP" ]
+    then
+        return 1
+    fi
+
+    CUR_MAC=""
+    ifconfig 2>/dev/null | while read -r LINE
+    do
+        case "$LINE" in
+        *HWaddr\ *)
+            CUR_MAC="${LINE##*HWaddr }"
+            ;;
+        *\ addr:"$IP"\ *)
+            if [ -n "$CUR_MAC" ]
+            then
+                echo "$CUR_MAC" | sed -e 's/://g'
+		return
+            fi
+            ;;
+        "")
+            CUR_MAC=""
+            ;;
+        *)
+            ;;
+        esac
+    done
+}
+
+# Load the relevant bits of the configuration
+load_config()
+{
+    if [ ! -f "$CONFIG" -o ! -r "$CONFIG" ]
+    then
+        log "Unable to read configuration file \"$CONFIG\""
+        return 1
+    fi
+
+    while read -r RAWLINE
+    do
+        LINE="`lead_strip "$RAWLINE"`"
+        LINE="`tail_strip "$LINE"`"
+        case "$LINE" in
+        \#*)
+            ;;
+        "")
+            ;;
+        *=*)
+            PARM="`tail_strip "${LINE%%=*}"`"
+            VALUE="`lead_strip "${LINE#*=}"`"
+            if [ -z "$PARM" ]
+            then
+                log "Invalid config line: \"$RAWLINE\""
+                return 1
+            fi
+            case "$PARM" in
+            *[\ :/-]*)
+                log "Invalid module parameter name: \"$PARM\""
+                return 1
+                ;;
+            guid)
+                echo "ORIGGUID=$VALUE"
+                ;;
+            ip_address)
+                echo "IP=$VALUE"
+                ;;
+            *)
+                ;;
+            esac
+            ;;
+        *)
+            log "Invalid config line: \"$RAWLINE\""
+            return 1
+            ;;
+        esac
+    done < "$CONFIG"
+
+    return 0
+}
+
+
+#
+##################################################################
+# Main program
+#
+
+if [ "$#" -lt 1 -o -z "$1" ]
+then
+    print_usage 0
+fi
+
+OPER=""
+FORCE=""
+case "$1" in
+-c)
+    OPER=create
+    if [ "$#" -gt 1 ]
+    then
+        if [ "$2" = "-f" ]
+        then
+            FORCE="true"
+        else
+            print_usage 1
+        fi
+    fi
+    ;;
+-r)
+    OPER=recover
+    ;;
+*)
+    print_usage 1
+    ;;
+esac
+
+CONFIG_STR="`load_config`"
+if [ -z "$CONFIG_STR" -o "$?" != 0 ]
+then
+    die "Unable to load configuration"
+fi
+eval "$CONFIG_STR"
+
+if [ -z "$IP" ]
+then
+    die "IP address not in the confiugration file"
+fi
+
+MAC="`grab_mac "$IP"`"
+if [ -z "$MAC" -o "$?" != 0 ]
+then
+    die "Unable to find MAC address for the IP $IP"
+fi
+
+if [ "$OPER" = "create" ]
+then
+    if [ -n "$ORIGGUID" -a "$FORCE" != "true" ]
+    then
+        die "There is already a GUID in the configuration file $CONFIG.
+	Specify the '-f' option to overwrite the existing GUID."
+    fi
+
+    GUID="`generate_bits`"
+    if [ -z "$GUID" -o "`expr length "$GUID"`" != "20" ]
+    then
+        die "Unable to generate a valid host portion of the GUID"
+    fi
+
+    GUID="${GUID}${MAC}"
+elif [ "$OPER" = "recover" ]
+then
+    if [ -z "$ORIGGUID" -o "`expr length "$ORIGGUID"`" != "32" ]
+    then
+        die "The original GUID is missing or corrupt.  Recovery cannot
+	take place."
+    fi
+
+    if [ "${ORIGGUID%$MAC}" != "$ORIGGUID" ]
+    then
+        msg "The GUID is already correct.  No action taken."
+        exit 0
+    fi
+
+    GUID="`expr substr "$ORIGGUID" 1 20`"
+    GUID="${GUID}${MAC}"
+else
+    die "BUG!  Invalid operation: \"$OPER\""
+fi
+
+msg "The new GUID is $GUID"
+TMPNAM="/etc/ocfs_uid_gen$$`date +%Y%m%d%H%M%S`"
+mkdir -m 0700 "$TMPNAM" 2>/dev/null
+if [ "$?" != 0 ]
+then
+    die "Unable to create temporary files"
+fi
+
+OUTNAM="${CONFIG##*/}"
+OUTNAM="${TMPNAM}/${OUTNAM}"
+
+sed -e 's/^[ 	]*guid[ 	]*=.*$/	guid = '"$GUID"'/' < "$CONFIG" > "${OUTNAM}"
+ERROR=$?
+
+if [ ! -f "$OUTNAM" -o ! -r "$OUTNAM" -o ! -s "$OUTNAM" ]
+then
+    ERROR=1
+fi
+if ! grep "^	guid = $GUID" "$OUTNAM" 1>/dev/null 2>&1
+then
+    if ! grep "^[ 	]*guid[ 	]*=" "$CONFIG" 1>/dev/null 2>&1
+    then
+        echo "	guid = $GUID" >> "$OUTNAM"
+        if ! grep "^	guid = $GUID" "$OUTNAM" 1>/dev/null 2>&1
+        then
+            ERROR=1
+        fi
+    else
+        ERROR=1
+    fi
+fi
+if [ "$ERROR" != 0 ]
+then
+    rm -rf "$TMPNAM" 2>/dev/null
+    die "Unable to create temporary files"
+fi
+
+BAKNAM="${CONFIG}.bak""`date +%Y%m%d%H%M%S`"
+if [ -L "$BAKNAM" ]
+then
+    rm -rf "$TMPNAM" 2>/dev/null
+    die "Backup name \"$BAKNAM\" is a link.  Is this an attack?"
+fi
+
+\cp -ip "$CONFIG" "$BAKNAM" 2>/dev/null
+if [ "$?" != 0 ]
+then
+    rm -rf "$TMPNAM" 2>/dev/null
+    die "Unable to backup $CONFIG"
+fi
+if ! diff -q "$CONFIG" "$BAKNAM" >/dev/null 2>&1
+then
+    rm -rf "$BAKNAM" "$TMPNAM" 2>/dev/null
+    die "Unable to backup $CONFIG"
+fi
+
+\mv -f "$OUTNAM" "$CONFIG" 2>/dev/null
+ERROR=$?
+
+rm -rf "$TMPNAM"
+if [ "$ERROR" = 0 ]
+then
+    exit 0
+fi
+
+# From here on, it's error recovery
+
+log "Unable to install new configuration"
+\cp -fp "$BAKNAM" "$CONFIG" 2>/dev/null
+ERROR="$?"
+if [ "$ERROR" = 0 ]
+then
+    diff -q "$BAKNAM" "$CONFIG" >/dev/null 2>&1
+    ERROR=$?
+fi
+
+if [ "$ERROR" = 0 ]
+then
+    die "Original configuration file restored"
+else
+    die "Unable to restore original configuration file.  Backup is $BAKNAM"
+fi


Property changes on: trunk/ocfs_uid_gen/ocfs_uid_gen
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/ocfs_uid_gen/ocfs_uid_gen.1.in
===================================================================
--- trunk/ocfs_uid_gen/ocfs_uid_gen.1.in	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfs_uid_gen/ocfs_uid_gen.1.in	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,29 @@
+.TH "ocfs_uid_gen" "1" "November 2003" "Version @VERSION@" "OCFS Manual Pages"
+.SH "NAME"
+ocfs_uid_gen \- Create or Recover the GUID for a node.
+.SH "SYNOPSIS"
+\fBocfs_uid_gen\fR [-c|-r]
+.SH "DESCRIPTION"
+.PP 
+\fBocfs_uid_gen\fR is used to create a GUID or recover a lost GUID. It uses the NIC MAC address to generate the GUID and needs to be executed only once in most of the situations. The first time it is executed, it has to be invoked with the \-c option. The only exception is when the NIC that is used by ocfs is replaced, in this case, the \-r option should be used. When the \-r option is invoked to recover a GUID, the first mount needs to be invoked using the arguments "\-o reclaimid" or the mount will fail.
+
+.SH "OPTIONS"
+.TP
+\fB\-c\fR 
+Create a new GUID for a new node before it enters the cluster.
+.TP
+\fB\-r\fR 
+Recover the GUID, inserting the new MAC address.  This operation is only for existing nodes whose MAC address has changed.
+.TP
+
+.SH "BUGS"
+Stuff.
+
+.SH "SEE ALSO"
+.BR ocfs(5)  ocfstool(1)
+
+.SH "AUTHORS"
+Oracle Corporation
+
+.SH "COPYRIGHT"
+Copyright \(co 2002 Oracle Corporation

Added: trunk/ocfstool/Makefile
===================================================================
--- trunk/ocfstool/Makefile	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/Makefile	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,61 @@
+TOPDIR = ..
+
+include $(TOPDIR)/Preamble.make
+
+WARNINGS = -Wall
+
+ifdef OCFS_DEBUG
+OPTS = -g
+endif
+
+CFLAGS = $(OPTS) $(WARNINGS) -pthread
+
+
+BIN_PROGRAMS = ocfstool
+
+MANS = ocfstool.1
+
+DEFINES = -DOCFSTOOL_VERSION=\"0.0.5\"
+INCLUDES = $(GTK_CFLAGS) -I$(TOPDIR)/libocfs -I$(TOPDIR)/debugocfs
+
+OPTIMIZE = -O2
+
+ifeq ($(OCFS_PROCESSOR),ppc64)
+endif
+ifeq ($(OCFS_PROCESSOR),x86_64)
+  CFLAGS += -m64
+endif
+ifeq ($(OCFS_PROCESSOR),ia64)
+endif
+ifeq ($(OCFS_PROCESSOR),i686)
+endif
+
+CFLAGS += $(OPTIMIZE)
+
+CBITS = \
+	ocfsbitmap.c	\
+	ocfsbrowser.c	\
+	ocfscellmap.c	\
+	ocfsformat.c	\
+	ocfsfreespace.c	\
+	ocfsgenconfig.c	\
+	ocfsgeneral.c	\
+	ocfsguiutil.c	\
+	ocfsmount.c	\
+	ocfsnodemap.c	\
+	ocfsplist.c	\
+	ocfsprocess.c
+
+HBITS = $(subst .c,.h,$(CBITS))
+
+CFILES = $(CBITS) ocfstool.c
+HFILES = $(HBITS)
+
+OBJS = $(subst .c,.o,$(CFILES))
+
+DIST_FILES = $(CFILES) $(HFILES) ocfstool.1.in
+
+ocfstool: $(OBJS)
+	$(LINK) $(GTK_LIBS) -L$(TOPDIR)/debugocfs -ldebugocfs -L$(TOPDIR)/libocfs -locfs
+
+include $(TOPDIR)/Postamble.make

Added: trunk/ocfstool/ocfsbitmap.c
===================================================================
--- trunk/ocfstool/ocfsbitmap.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfsbitmap.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,70 @@
+/*
+ * ocfsbitmap.c
+ *
+ * The bitmap display tab
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Manish Singh
+ */
+
+#include <stdlib.h>
+
+#include <gtk/gtk.h>
+
+#include "libdebugocfs.h"
+
+#include "ocfscellmap.h"
+#include "ocfsbitmap.h"
+
+
+GtkWidget *
+ocfs_bitmap (const gchar *device,
+	     gboolean     advanced)
+{
+  GtkWidget  *scrl_win;
+  guint8     *bits;
+  gint        length, i;
+  GByteArray *map;
+
+  if (device && libocfs_get_bitmap (device, (gchar **) &bits, &length) == 0)
+    {
+      scrl_win = gtk_widget_new (GTK_TYPE_SCROLLED_WINDOW,
+				 "hscrollbar_policy", GTK_POLICY_NEVER,
+				 "vscrollbar_policy", GTK_POLICY_ALWAYS,
+				 "border_width", 4,
+				 NULL);
+
+      map = g_byte_array_new ();
+      g_byte_array_set_size (map, length);
+
+      for (i = 0; i < length; i++)
+	map->data[i] = (bits[i / 8] & (1 << (i % 8))) ? 0xff : 0x00;
+
+      g_free (bits);
+      
+      gtk_widget_new (OCFS_TYPE_CELL_MAP,
+		      "map", map,
+		      "parent", scrl_win,
+		      NULL);
+
+      return scrl_win;
+    }
+  else
+    return gtk_label_new ("Invalid device");
+}

Added: trunk/ocfstool/ocfsbitmap.h
===================================================================
--- trunk/ocfstool/ocfsbitmap.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfsbitmap.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,37 @@
+/*
+ * ocfsbitmap.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Manish Singh
+ */
+
+#ifndef __OCFS_BITMAP_H__
+#define __OCFS_BITMAP_H__
+
+
+#include <gtk/gtk.h>
+
+
+GtkWidget *ocfs_bitmap (const gchar *device,
+			gboolean     advanced);
+
+
+#endif /* __OCFS_BITMAP_H__ */

Added: trunk/ocfstool/ocfsbrowser.c
===================================================================
--- trunk/ocfstool/ocfsbrowser.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfsbrowser.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,717 @@
+/*
+ * ocfsbrowser.c
+ *
+ * The file browser tab
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Manish Singh
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#include <grp.h>
+#include <unistd.h>
+
+#include <gtk/gtk.h>
+
+#include "libdebugocfs.h"
+
+#include "ocfsplist.h"
+#include "ocfsprocess.h"
+#include "ocfsguiutil.h"
+#include "ocfsnodemap.h"
+#include "ocfsbrowser.h"
+
+
+typedef struct _FileInfo FileInfo;
+
+struct _FileInfo
+{
+  libocfs_stat  stat;
+  gchar        *fullpath;
+  gboolean      filled;
+};
+
+
+static void       info_field          (GtkTable       *table,
+				       gint           *pos,
+				       gboolean        list,
+				       const gchar    *tag,
+				       const gchar    *desc);
+static void       free_file_info      (gpointer        info);
+static gboolean   dir_populate        (GtkCTree       *ctree,
+				       GtkCTreeNode   *parent,
+				       const gchar    *device);
+static void       load_node_map       (GtkObject      *table,
+				       gboolean        is_cdsl,
+				       guint           bitmap,
+				       gboolean        valid);
+static void       tree_select         (GtkCTree       *ctree,
+				       GtkCTreeNode   *row,
+				       gint            column,
+				       GtkObject      *table);
+static void       set_label_size      (GtkWidget      *label,
+				       GtkStyle       *style);
+static GtkWidget *create_context_menu (GtkObject      *ctree,
+				       const gchar    *device,
+				       GtkWindow      *parent);
+static gboolean   tree_button_press   (GtkCTree       *ctree,
+				       GdkEventButton *event,
+				       const gchar    *device);
+static void       dump_file           (GtkObject      *item,
+				       FileInfo       *info);
+static void       dump_cdsl           (GtkObject      *item,
+				       FileInfo       *info);
+static void       run_cdslctl         (GtkObject      *item,
+				       FileInfo       *info);
+
+
+static void
+info_field (GtkTable    *table,
+	    gint        *pos,
+	    gboolean     list,
+	    const gchar *tag,
+	    const gchar *desc)
+{
+  gchar        *str;
+  GtkWidget    *label;
+  GtkWidget    *field;
+  GtkWidget    *attach;
+  static gchar *titles[2] = { "Slot #", "Node Name" };
+
+  str = g_strconcat (desc, ":", NULL);
+  label = gtk_widget_new (GTK_TYPE_LABEL,
+			  "label", str,
+			  "xalign", 1.0,
+			  "yalign", 0.0,
+			  "justify", GTK_JUSTIFY_RIGHT,
+			  NULL);
+  g_free (str);
+
+  gtk_table_attach (table, label, 0, 1, *pos, *pos + 1,
+		    GTK_FILL, GTK_FILL, 0, 0);
+
+  str = g_strconcat (tag, "-desc", NULL);
+  gtk_object_set_data (GTK_OBJECT (table), str, label);
+  g_free (str);
+
+  if (list)
+    {
+      field = GTK_WIDGET (ocfs_build_clist (2, titles, &attach));
+      gtk_widget_set_usize (field, -1, 100);
+    }
+  else
+    attach = field = gtk_widget_new (GTK_TYPE_LABEL,
+				     "label", "N/A",
+				     "xalign", 0.0,
+				     "yalign", 0.0,
+				     "justify", GTK_JUSTIFY_LEFT,
+				     NULL);
+
+  gtk_table_attach (table, attach, 1, 2, *pos, *pos + 1,
+		    GTK_FILL, GTK_FILL, 0, 0);
+
+  str = g_strconcat (tag, list ? "-list" : "-label", NULL);
+  gtk_object_set_data (GTK_OBJECT (table), str, field);
+  g_free (str);
+
+  (*pos)++;
+}
+
+static void
+free_file_info (gpointer info)
+{
+  g_free (((FileInfo *) info)->fullpath);
+  g_free (info);
+}
+
+static gboolean
+dir_populate (GtkCTree     *ctree,
+	      GtkCTreeNode *parent,
+	      const gchar  *device)
+{
+  GtkCTreeNode *node;
+  GArray       *files;
+  gchar        *dir, *text;
+  gint          ret, i;
+  gboolean      is_dir;
+  FileInfo     *info;
+
+  if (parent)
+    {
+      info = gtk_ctree_node_get_row_data (ctree, parent);
+
+      if (!info->filled)
+	{
+	  info->filled = TRUE;
+
+	  dir = g_strconcat (info->fullpath, "/", NULL);
+
+	  node = GTK_CTREE_ROW (parent)->children;
+	  gtk_ctree_remove_node (ctree, node);
+	}
+      else
+	return TRUE;
+    }
+  else
+    dir = g_strdup ("/");
+
+  if (device)
+    ret = libocfs_readdir (device, dir, FALSE, &files);
+  else
+    ret = -1;
+
+  if (ret == 0 && files->len == 0)
+    {
+      g_array_free (files, TRUE);
+      ret = -2;
+    }
+
+  if (ret != 0)
+    {
+      if (ret == -1)
+	text = "No device selected";
+      else if (ret == -2)
+	text = "Empty directory";
+      else
+	text = "Error reading device";
+
+      gtk_ctree_insert_node (ctree, parent, NULL, &text, 4,
+			     NULL, NULL, NULL, NULL,
+			     FALSE, FALSE);
+
+      g_free (dir);
+
+      return FALSE;
+    }
+
+  gtk_clist_freeze (GTK_CLIST (ctree));
+
+  for (i = 0; i < files->len; i++)
+    {
+      info = g_new0 (FileInfo, 1);
+      memcpy (info, &(g_array_index (files, libocfs_stat, (i))),
+		    sizeof (libocfs_stat));
+
+      if (info->stat.attribs & OCFS_DBGLIB_ATTRIB_FILE_CDSL)
+	text = g_strconcat (info->stat.name, "@", NULL);
+      else
+	text = g_strdup (info->stat.name);
+
+      is_dir = S_ISDIR (info->stat.protection);
+
+      info->fullpath = g_strconcat (dir, info->stat.name, NULL);
+
+      node = gtk_ctree_insert_node (ctree, parent, NULL, &text, 4,
+				    NULL, NULL, NULL, NULL,
+				    !is_dir, FALSE);
+
+      g_free (text);
+
+      if (is_dir)
+	{
+	  info->filled = FALSE;
+
+	  text = "Dummy";
+	  gtk_ctree_insert_node (ctree, node, NULL, &text, 4,
+				 NULL, NULL, NULL, NULL,
+				 FALSE, FALSE);
+	}
+
+      gtk_ctree_node_set_row_data_full (ctree, node, info, free_file_info);
+    }
+
+  g_array_free (files, TRUE);
+  g_free (dir);
+
+  gtk_clist_thaw (GTK_CLIST (ctree));
+
+  return TRUE;
+}
+
+static void
+load_node_map (GtkObject   *table,
+	       gboolean     is_cdsl,
+	       guint        bitmap,
+	       gboolean     valid)
+{
+  GtkCList  *clist;
+  GtkLabel  *label;
+  gchar     *device;
+  gchar     *texts[2];
+
+  clist = gtk_object_get_data (table, "nodemap-list");
+  label = gtk_object_get_data (table, "nodemap-desc");
+
+  gtk_label_set_text (label, is_cdsl ? "Nodes With Data:" : "Opened By:");
+
+#define INVALID_LIST()				G_STMT_START {	\
+  gtk_clist_clear (clist);					\
+  gtk_widget_set_sensitive (GTK_WIDGET (clist)->parent, FALSE);	\
+  gtk_widget_set_sensitive (GTK_WIDGET (label), FALSE);		\
+  texts[0] = "N/A"; texts[1] = "";				\
+  gtk_clist_append (clist, texts);				\
+  return;					} G_STMT_END
+
+  if (valid)
+    {
+      gtk_widget_set_sensitive (GTK_WIDGET (clist)->parent, TRUE);
+      gtk_widget_set_sensitive (GTK_WIDGET (label), TRUE);
+    }
+  else
+    INVALID_LIST ();
+
+  device = gtk_object_get_data (table, "device");
+
+  if (!ocfs_nodemap_list (clist, device, bitmap))
+    INVALID_LIST ();
+}
+
+static void
+tree_select (GtkCTree     *ctree,
+	     GtkCTreeNode *row,
+	     gint          column,
+	     GtkObject    *table)
+{
+  FileInfo *info;
+  GtkLabel *label;
+  gchar    *str;
+  gboolean  valid = TRUE;
+  gboolean  is_cdsl = FALSE;
+
+  if (table == NULL)
+    table = gtk_object_get_data (GTK_OBJECT (ctree), "table");
+
+  info = gtk_ctree_node_get_row_data (ctree, row);
+
+  if (info == NULL)
+    {
+      valid = FALSE;
+      info = g_new0 (FileInfo, 1);
+    }
+  else
+    is_cdsl = info->stat.attribs & OCFS_DBGLIB_ATTRIB_FILE_CDSL;
+
+#define SET_LABEL(tag)			G_STMT_START {	\
+  label = gtk_object_get_data (table, tag "-label");	\
+  gtk_label_set_text (label, valid ? str : "N/A");	\
+  g_free (str);				} G_STMT_END
+
+  if (info->stat.current_master != -1)
+    str = g_strdup_printf ("%d", info->stat.current_master);
+  else
+    str = g_strdup ("None");
+
+  SET_LABEL ("current_master");
+
+#define SET_LABEL_BYTES(field, show)	G_STMT_START {	\
+  str = ocfs_format_bytes (info->stat.field, (show));	\
+  SET_LABEL (#field);			} G_STMT_END
+
+  SET_LABEL_BYTES (size, TRUE);
+  SET_LABEL_BYTES (alloc_size, TRUE);
+
+#undef SET_LABEL_BYTES
+
+#define SET_LABEL_NAME(func, field)	G_STMT_START {	\
+  str = func (info->stat.field);			\
+  SET_LABEL (#field);			} G_STMT_END
+
+  SET_LABEL_NAME (ocfs_get_user_name,  uid);
+  SET_LABEL_NAME (ocfs_get_group_name, gid);
+
+#undef SET_LABEL_NAME
+
+  str = g_strdup_printf ("0%o", info->stat.protection & 0777);
+  SET_LABEL ("protection");
+
+#undef SET_LABEL
+
+  if (is_cdsl)
+    load_node_map (table, TRUE, info->stat.cdsl_bitmap, TRUE);
+  else
+    load_node_map (table, FALSE, info->stat.open_map,
+		   valid && S_ISREG (info->stat.protection));
+
+  if (!valid)
+    {
+      g_free (info);
+      info = NULL;
+    }
+
+  gtk_object_set_data (GTK_OBJECT (ctree), "selected-info", info);
+}
+
+static void
+set_label_size (GtkWidget *label,
+		GtkStyle  *style)
+{
+  gint width;
+
+  width = gdk_string_width (label->style->font, "1.0 TB (1000000000000b)");
+  gtk_widget_set_usize (label, width, -1);
+}
+
+static GtkWidget *
+create_context_menu (GtkObject   *ctree,
+		     const gchar *device,
+		     GtkWindow   *parent)
+{
+  GtkWidget *menu;
+  GtkWidget *item;
+  FileInfo  *info;
+  gchar     *mountpoint;
+  gboolean   is_cdsl;
+
+  menu = gtk_menu_new ();
+
+  info = gtk_object_get_data (ctree, "selected-info");
+  if (info == NULL || S_ISDIR (info->stat.protection))
+    return NULL;
+
+  is_cdsl = info->stat.attribs & OCFS_DBGLIB_ATTRIB_FILE_CDSL;
+
+  item = gtk_menu_item_new_with_label (is_cdsl ? "Dump CDSL..."
+					       : "Dump File...");
+  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+  gtk_widget_show (item);
+
+  gtk_object_set_data (GTK_OBJECT (item), "parent", parent);
+  gtk_object_set_data (GTK_OBJECT (item), "device", (gpointer) device);
+
+  gtk_signal_connect (GTK_OBJECT (item), "activate",
+		      GTK_SIGNAL_FUNC ((is_cdsl ? dump_cdsl : dump_file)),
+		      info);
+
+  mountpoint = ocfs_get_mountpoint (device);
+
+  if (mountpoint)
+    {
+      item = gtk_menu_item_new_with_label (is_cdsl ? "Undo CDSL" : "Make CDSL");
+      gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+      gtk_widget_show (item);
+
+      gtk_object_set_data (GTK_OBJECT (item), "parent", parent);
+      gtk_object_set_data (GTK_OBJECT (item), "ctree", ctree);
+
+      gtk_object_set_data (GTK_OBJECT (item), "action", is_cdsl ? "-d" : "-c");
+      gtk_object_set_data_full (GTK_OBJECT (item), "mountpoint",
+				mountpoint, g_free);
+
+      gtk_signal_connect (GTK_OBJECT (item), "activate",
+			  GTK_SIGNAL_FUNC (run_cdslctl), info);
+    }
+
+  return menu;
+}
+
+static void
+ungrab_tree (GtkWidget *ctree)
+{
+  if (GTK_WIDGET_HAS_GRAB (ctree))
+    {
+      gtk_grab_remove (ctree);
+      if (gdk_pointer_is_grabbed ())
+	gdk_pointer_ungrab (GDK_CURRENT_TIME);
+    }
+}
+
+static gboolean
+tree_button_press (GtkCTree       *ctree,
+		   GdkEventButton *event,
+		   const gchar    *device)
+{
+  GtkWindow *parent;
+  GtkWidget *menu;
+
+  if (event->button == 3)
+    {
+      parent = ocfs_widget_get_toplevel (GTK_WIDGET (ctree));
+
+      menu = create_context_menu (GTK_OBJECT (ctree), device, parent);
+
+      if (menu)
+	{
+	  gtk_signal_connect_object (GTK_OBJECT (menu), "hide",
+				     GTK_SIGNAL_FUNC (ungrab_tree),
+				     GTK_OBJECT (ctree));
+
+	  gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
+			  3, event->time);
+
+	  gtk_main ();
+
+	  gtk_widget_destroy (menu);
+	}
+    }
+
+  return FALSE;
+}
+
+static void
+dump_file (GtkObject *item,
+	   FileInfo  *info)
+{
+  GtkWindow *parent;
+  gchar     *device, *dump;
+
+  parent = gtk_object_get_data (item, "parent");
+  device = gtk_object_get_data (item, "device");
+
+  dump = ocfs_get_filename (parent, "Dump File");
+
+  if (dump == NULL)
+    return;
+
+  if (libocfs_dump_file (device, info->fullpath, dump))
+    ocfs_error_box (parent, NULL, "Couldn't dump %s on device %s to %s",
+		    info->fullpath, device, dump);
+
+  g_free (dump);
+}
+
+static void
+do_dump_cdsl (GtkWidget *button,
+	      GtkCList  *node_list)
+{
+  GtkWindow *parent;
+  gchar     *device, *path, *dump, *node;
+  gint       row, node_num;
+
+  parent = ocfs_widget_get_toplevel (button);
+
+  device = gtk_object_get_data (GTK_OBJECT (node_list), "device");
+  path   = gtk_object_get_data (GTK_OBJECT (node_list), "path");
+  dump   = gtk_object_get_data (GTK_OBJECT (node_list), "dump");
+
+  if (node_list->selection == NULL)
+    {
+      ocfs_error_box (parent, NULL, "No device selected");
+      return;
+    }
+
+  row = GPOINTER_TO_INT (node_list->selection->data);
+
+  gtk_clist_get_text (node_list, row, 0, &node);
+
+  node_num = (gint) strtol (node, NULL, 10);
+
+  if (libocfs_dump_file_as_node (device, path, dump, node_num))
+    ocfs_error_box (parent, NULL, "Couldn't dump %s (node %d) on device "
+				  "%s to %s", path, node_num, device, dump);
+
+  gtk_main_quit ();
+}
+
+static void
+dump_cdsl (GtkObject *item,
+	   FileInfo  *info)
+{
+  GtkWindow    *parent;
+  GtkWidget    *dialog;
+  GtkWidget    *scrl_win;
+  GtkCList     *list;
+  gchar        *device, *dump;
+  static gchar *titles[2] = { "Slot #", "Node Name" };
+
+  parent = gtk_object_get_data (item, "parent");
+  device = gtk_object_get_data (item, "device");
+
+  dump = ocfs_get_filename (parent, "Dump CDSL");
+
+  if (dump == NULL)
+    return;
+
+  list = ocfs_build_clist (2, titles, &scrl_win);
+
+  if (!ocfs_nodemap_list (list, device, info->stat.cdsl_bitmap))
+    {
+      ocfs_error_box (parent, NULL, "Couldn't get node map of device %s",
+		      device);
+
+      g_free (dump);
+      return;
+    }
+
+  dialog = ocfs_dialog_new (parent, "Select Node", do_dump_cdsl, list);
+
+  gtk_widget_set_usize (scrl_win, 300, 200);
+  gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), scrl_win);
+
+  gtk_object_set_data (GTK_OBJECT (list), "device", device);
+  gtk_object_set_data (GTK_OBJECT (list), "path",   info->fullpath);
+  gtk_object_set_data (GTK_OBJECT (list), "dump",   dump);
+
+  ocfs_dialog_run (dialog);
+
+  g_free (dump);
+}
+
+static void
+run_cdslctl (GtkObject *item,
+	     FileInfo  *info)
+{
+  GtkWindow    *parent;
+  GtkCTree     *ctree;
+  GtkCTreeNode *node;
+  pid_t         pid;
+  gint          outfd, errfd;
+  gboolean      is_cdsl, success;
+  gchar        *mountpoint, *fname, *newname;
+  guint8        spacing;
+  gchar        *argv[] = {
+    "cdslctl", 
+    NULL, NULL,
+    NULL
+  };
+
+  parent     = gtk_object_get_data (item, "parent");
+  mountpoint = gtk_object_get_data (item, "mountpoint");
+ 
+  fname = g_strconcat (mountpoint, info->fullpath, NULL);
+
+  is_cdsl = info->stat.attribs & OCFS_DBGLIB_ATTRIB_FILE_CDSL;
+
+  argv[1] = is_cdsl ? "-d" : "-c";
+  argv[2] = fname;
+
+  pid = ocfs_process_run (argv[0], argv, &outfd, &errfd);
+
+  success = ocfs_process_reap (parent, pid, TRUE, FALSE, "cdslctl", "cdslctl",
+			       -1, NULL, -1, NULL, NULL);
+
+  close (outfd);
+  close (errfd);
+
+  g_free (fname);
+
+  if (success)
+    {
+      ctree = GTK_CTREE (gtk_object_get_data (item, "ctree"));
+      node = GTK_CLIST (ctree)->selection->data;
+
+      gtk_ctree_node_get_pixtext (ctree, node, 0, &fname, &spacing, NULL, NULL);
+
+      if (is_cdsl)
+	{
+	  info->stat.attribs &= !OCFS_DBGLIB_ATTRIB_FILE_CDSL;
+	  
+	  newname = g_strdup (fname);
+	  newname[strlen (newname) - 1] = '\0';
+	}
+      else
+	{
+	  info->stat.attribs |= OCFS_DBGLIB_ATTRIB_FILE_CDSL;
+
+	  newname = g_strconcat (fname, "@", NULL);
+	}
+
+      gtk_ctree_node_set_pixtext (ctree, node, 0, newname, spacing, NULL, NULL);
+      g_free (newname);
+
+      tree_select (ctree, node, 0, NULL);
+    }
+  else
+    ocfs_error_box (parent, NULL, "cdslctl command failed!");
+}
+
+GtkWidget *
+ocfs_browser (const gchar *device,
+	      gboolean     advanced)
+{
+  GtkWidget *hbox;
+  GtkWidget *scrl_win;
+  GtkWidget *ctree;
+  GtkWidget *label;
+  GtkTable  *table;
+  gchar     *dev;
+  gint       pos = 0;
+
+  hbox = gtk_hbox_new (FALSE, 4);
+
+  scrl_win = gtk_widget_new (GTK_TYPE_SCROLLED_WINDOW,
+			     "hscrollbar_policy", GTK_POLICY_AUTOMATIC,
+			     "vscrollbar_policy", GTK_POLICY_AUTOMATIC,
+			     "parent", hbox,
+			     NULL);
+
+  ctree = gtk_ctree_new (1, 0);
+
+  gtk_widget_set (ctree,
+		  "selection_mode", GTK_SELECTION_BROWSE,
+		  "parent", scrl_win,
+		  NULL);
+
+  gtk_clist_set_button_actions (GTK_CLIST (ctree), 2, GTK_BUTTON_SELECTS);
+
+  gtk_clist_set_column_auto_resize (GTK_CLIST (ctree), 0, TRUE);
+  gtk_clist_column_titles_hide (GTK_CLIST (ctree));
+  gtk_clist_set_auto_sort (GTK_CLIST (ctree), TRUE);
+
+  table = GTK_TABLE (gtk_widget_new (GTK_TYPE_TABLE,
+				     "n_rows", 7,
+				     "n_columns", 2,
+				     "homogeneous", FALSE,
+				     "row_spacing", 4,
+				     "column_spacing", 4,
+				     "border_width", 4,
+				     NULL));
+  gtk_box_pack_end (GTK_BOX (hbox), GTK_WIDGET (table), FALSE, FALSE, 0);
+
+  info_field (table, &pos, FALSE, "current_master", "Current Master");
+  info_field (table, &pos, FALSE, "size",           "Size");
+  info_field (table, &pos, FALSE, "alloc_size",     "Allocation Size");
+  info_field (table, &pos, FALSE, "uid",            "User");
+  info_field (table, &pos, FALSE, "gid",            "Group");
+  info_field (table, &pos, FALSE, "protection",     "Protection");
+  info_field (table, &pos, TRUE,  "nodemap",        "Opened By");
+
+  label = gtk_object_get_data (GTK_OBJECT (table), "size-label");
+  gtk_signal_connect (GTK_OBJECT (label), "style_set",
+		      GTK_SIGNAL_FUNC (set_label_size), NULL);
+
+  gtk_signal_connect (GTK_OBJECT (ctree), "tree_select_row",
+		      GTK_SIGNAL_FUNC (tree_select), table);
+
+  if (dir_populate (GTK_CTREE (ctree), NULL, device))
+    {
+      dev = g_strdup (device);
+      gtk_object_weakref (GTK_OBJECT (ctree), g_free, dev);
+
+      gtk_object_set_data (GTK_OBJECT (table), "device", dev);
+
+      gtk_signal_connect (GTK_OBJECT (ctree), "tree_expand",
+			  GTK_SIGNAL_FUNC (dir_populate), dev);
+
+      if (advanced)
+	{
+	  gtk_signal_connect_after (GTK_OBJECT (ctree), "button_press_event",
+				    GTK_SIGNAL_FUNC (tree_button_press), dev);
+
+	  gtk_object_set_data (GTK_OBJECT (ctree), "table", table);
+	}
+
+      gtk_clist_select_row (GTK_CLIST (ctree), 0, 0);
+    }
+
+  return hbox;
+}

Added: trunk/ocfstool/ocfsbrowser.h
===================================================================
--- trunk/ocfstool/ocfsbrowser.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfsbrowser.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,34 @@
+/*
+ * ocfsbrowser.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Manish Singh
+ */
+
+#ifndef __OCFS_BROWSER_H__
+#define __OCFS_BROWSER_H__
+
+
+GtkWidget *ocfs_browser (const gchar *device,
+			 gboolean     advanced);
+
+
+#endif /* __OCFS_BROWSER_H__ */

Added: trunk/ocfstool/ocfscellmap.c
===================================================================
--- trunk/ocfstool/ocfscellmap.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfscellmap.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,665 @@
+/*
+ * ocfscellmap.c
+ *
+ * A scrollable bitmap display widget
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Manish Singh
+ */
+
+#include <gtk/gtk.h>
+
+#include "ocfscellmap.h"
+
+
+#define DEFAULT_CELL_WIDTH  10
+#define DEFAULT_CELL_HEIGHT 10
+
+#define CELL_MAP_MASK       (GDK_EXPOSURE_MASK |            \
+			     GDK_POINTER_MOTION_MASK |      \
+			     GDK_POINTER_MOTION_HINT_MASK | \
+			     GDK_ENTER_NOTIFY_MASK |        \
+			     GDK_BUTTON_PRESS_MASK |        \
+			     GDK_BUTTON_RELEASE_MASK |      \
+			     GDK_BUTTON1_MOTION_MASK)
+
+
+enum {
+  ARG_0,
+  ARG_MAP,
+  ARG_CELL_WIDTH,
+  ARG_CELL_HEIGHT,
+  ARG_HADJUSTMENT,
+  ARG_VADJUSTMENT
+};
+
+
+static void     ocfs_cell_map_class_init      (OcfsCellMapClass  *class);
+static void     ocfs_cell_map_init            (OcfsCellMap       *cell_map);
+static void     ocfs_cell_map_set_arg         (GtkObject         *object,
+					       GtkArg            *arg,
+					       guint              arg_id);
+static void     ocfs_cell_map_get_arg         (GtkObject         *object,
+					       GtkArg            *arg,
+					       guint              arg_id);
+static void     ocfs_cell_map_destroy         (GtkObject         *object);
+static void     ocfs_cell_map_finalize        (GtkObject         *object);
+static void     ocfs_cell_map_size_request    (GtkWidget         *widget,
+					       GtkRequisition    *requisition);
+static void     create_offscreen_pixmap       (OcfsCellMap       *cell_map);
+static void     paint_cell_map                (OcfsCellMap       *cell_map);
+static void     ocfs_cell_map_state_changed   (GtkWidget         *widget,
+					       GtkStateType       old_state);
+static gboolean ocfs_cell_map_configure       (GtkWidget         *widget,
+					       GdkEventConfigure *event);
+static gboolean ocfs_cell_map_expose          (GtkWidget         *widget,
+					       GdkEventExpose    *event);
+static gboolean ocfs_cell_map_button_press    (GtkWidget         *widget,
+					       GdkEventButton    *event);
+static gboolean ocfs_cell_map_button_release  (GtkWidget         *widget,
+					       GdkEventButton    *event);
+static gboolean ocfs_cell_map_motion_notify   (GtkWidget         *widget,
+					       GdkEventMotion    *event);
+static void     ocfs_cell_map_set_adjustments (OcfsCellMap       *cell_map,
+					       GtkAdjustment     *hadj,
+					       GtkAdjustment     *vadj);
+static void     update_adjustment             (GtkAdjustment     *adj,
+					       OcfsCellMap       *cell_map);
+static void     compute_vertical_scroll       (OcfsCellMap       *cell_map);
+
+
+static GtkDrawingAreaClass *parent_class = NULL;
+
+
+GtkType
+ocfs_cell_map_get_type (void)
+{
+  static GtkType cell_map_type = 0;
+
+  if (! cell_map_type)
+    {
+      static const GtkTypeInfo cell_map_info =
+      {
+        "OcfsCellMap",
+	sizeof (OcfsCellMap),
+	sizeof (OcfsCellMapClass),
+	(GtkClassInitFunc) ocfs_cell_map_class_init,
+	(GtkObjectInitFunc) ocfs_cell_map_init,
+	/* reserved_1 */ NULL,
+	/* reserved_2 */ NULL,
+	(GtkClassInitFunc) NULL,
+      };
+
+      cell_map_type = gtk_type_unique (GTK_TYPE_DRAWING_AREA, &cell_map_info);
+    }
+  
+  return cell_map_type;
+}
+
+static void
+ocfs_cell_map_class_init (OcfsCellMapClass *class)
+{
+  GtkObjectClass *object_class;
+  GtkWidgetClass *widget_class;
+
+  object_class = (GtkObjectClass *) class;
+  widget_class = (GtkWidgetClass *) class;
+
+  parent_class = gtk_type_class (GTK_TYPE_WIDGET);
+
+  gtk_object_add_arg_type ("OcfsCellMap::map",
+			   GTK_TYPE_POINTER,
+			   GTK_ARG_READWRITE,
+			   ARG_MAP);
+  gtk_object_add_arg_type ("OcfsCellMap::cell_width",
+			   GTK_TYPE_INT,
+			   GTK_ARG_READWRITE,
+			   ARG_CELL_WIDTH);
+  gtk_object_add_arg_type ("OcfsCellMap::cell_height",
+			   GTK_TYPE_INT,
+			   GTK_ARG_READWRITE,
+			   ARG_CELL_HEIGHT);
+  gtk_object_add_arg_type ("OcfsCellMap::hadjustment",
+			   GTK_TYPE_ADJUSTMENT,
+			   GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT,
+			   ARG_HADJUSTMENT);
+  gtk_object_add_arg_type ("OcfsCellMap::vadjustment",
+			   GTK_TYPE_ADJUSTMENT,
+			   GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT,
+			   ARG_VADJUSTMENT);
+
+  object_class->set_arg = ocfs_cell_map_set_arg;
+  object_class->get_arg = ocfs_cell_map_get_arg;
+  object_class->destroy = ocfs_cell_map_destroy;
+  object_class->finalize = ocfs_cell_map_finalize;
+
+  widget_class->state_changed = ocfs_cell_map_state_changed;
+  widget_class->size_request = ocfs_cell_map_size_request;
+  widget_class->configure_event = ocfs_cell_map_configure;
+  widget_class->expose_event = ocfs_cell_map_expose;
+
+  widget_class->button_press_event = ocfs_cell_map_button_press;
+  widget_class->button_release_event = ocfs_cell_map_button_release;
+  widget_class->motion_notify_event = ocfs_cell_map_motion_notify;
+
+  widget_class->set_scroll_adjustments_signal =
+    gtk_signal_new ("set_scroll_adjustments",
+		    GTK_RUN_LAST,
+		    object_class->type,
+		    GTK_SIGNAL_OFFSET (OcfsCellMapClass, set_scroll_adjustments),
+		    gtk_marshal_NONE__POINTER_POINTER,
+		    GTK_TYPE_NONE, 2,
+		    GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
+
+  class->set_scroll_adjustments = ocfs_cell_map_set_adjustments;
+}
+
+static void
+ocfs_cell_map_init (OcfsCellMap *cell_map)
+{
+  gint old_mask;
+
+  cell_map->map = NULL;
+
+  cell_map->cell_width = DEFAULT_CELL_WIDTH;
+  cell_map->cell_height = DEFAULT_CELL_HEIGHT;
+
+  cell_map->offscreen_pixmap = NULL;
+
+  cell_map->hadj = NULL;
+  cell_map->vadj = NULL;
+
+  old_mask = gtk_widget_get_events (GTK_WIDGET (cell_map));
+  gtk_widget_set_events (GTK_WIDGET (cell_map), old_mask | CELL_MAP_MASK);
+}
+
+static void
+ocfs_cell_map_set_arg (GtkObject *object,
+		       GtkArg    *arg,
+		       guint      arg_id)
+{
+  OcfsCellMap *cell_map;
+
+  cell_map = OCFS_CELL_MAP (object);
+
+  switch (arg_id)
+    {
+    case ARG_MAP:
+      ocfs_cell_map_set_map (cell_map, GTK_VALUE_POINTER (*arg));
+      break;
+    case ARG_CELL_WIDTH:
+      cell_map->cell_width = GTK_VALUE_INT (*arg);
+      break;
+    case ARG_CELL_HEIGHT:
+      cell_map->cell_height = GTK_VALUE_INT (*arg);
+      break;
+    case ARG_HADJUSTMENT:
+      ocfs_cell_map_set_adjustments (cell_map, GTK_VALUE_POINTER (*arg), cell_map->vadj);
+      break;
+    case ARG_VADJUSTMENT:
+      ocfs_cell_map_set_adjustments (cell_map, cell_map->hadj, GTK_VALUE_POINTER (*arg));
+      break;
+    default:
+      break;
+    }
+}
+
+static void
+ocfs_cell_map_get_arg (GtkObject *object,
+		       GtkArg    *arg,
+		       guint      arg_id)
+{
+  OcfsCellMap *cell_map;
+
+  cell_map = OCFS_CELL_MAP (object);
+
+  switch (arg_id)
+    {
+    case ARG_MAP:
+      GTK_VALUE_POINTER (*arg) = cell_map->map;
+      break;
+    case ARG_CELL_WIDTH:
+      GTK_VALUE_INT (*arg) = cell_map->cell_width;
+      break;
+    case ARG_CELL_HEIGHT:
+      GTK_VALUE_INT (*arg) = cell_map->cell_height;
+      break;
+    case ARG_HADJUSTMENT:
+      GTK_VALUE_POINTER (*arg) = cell_map->hadj;
+      break;
+    case ARG_VADJUSTMENT:
+      GTK_VALUE_POINTER (*arg) = cell_map->vadj;
+      break;
+    default:
+      arg->type = GTK_TYPE_INVALID;
+      break;
+    }
+}
+
+static void
+ocfs_cell_map_destroy (GtkObject *object)
+{
+  OcfsCellMap *cell_map = OCFS_CELL_MAP (object);
+
+  gtk_signal_disconnect_by_data (GTK_OBJECT (cell_map->hadj), cell_map);
+  gtk_signal_disconnect_by_data (GTK_OBJECT (cell_map->vadj), cell_map);
+
+  GTK_OBJECT_CLASS (parent_class)->destroy (object);
+}
+
+static void
+ocfs_cell_map_finalize (GtkObject *object)
+{
+  OcfsCellMap *cell_map = OCFS_CELL_MAP (object);
+
+  gtk_object_unref (GTK_OBJECT (cell_map->hadj));
+  gtk_object_unref (GTK_OBJECT (cell_map->vadj));
+ 
+  if (cell_map->offscreen_pixmap)
+    gdk_pixmap_unref (cell_map->offscreen_pixmap);
+
+  if (cell_map->map)
+    g_byte_array_free (cell_map->map, TRUE);
+
+  GTK_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+GtkWidget *
+ocfs_cell_map_new (GByteArray *map)
+{
+  return gtk_widget_new (OCFS_TYPE_CELL_MAP,
+			 "map", map,
+			 NULL);
+}
+
+void
+ocfs_cell_map_set_map (OcfsCellMap *cell_map,
+		       GByteArray  *map)
+{
+  g_return_if_fail (OCFS_IS_CELL_MAP (cell_map));
+
+  if (cell_map->map)
+    g_byte_array_free (cell_map->map, TRUE);
+
+  cell_map->map = map;
+
+  paint_cell_map (cell_map);
+  gtk_widget_queue_draw (GTK_WIDGET (cell_map));
+}
+
+void
+ocfs_cell_map_set_cell_props (OcfsCellMap *cell_map,
+			      gint         cell_width,
+			      gint         cell_height)
+{
+  g_return_if_fail (OCFS_IS_CELL_MAP (cell_map));
+  
+#define SET_PROP(prop, def)	G_STMT_START {	\
+  if (prop > -1)				\
+    cell_map->prop = prop;			\
+  else if (prop == -1)				\
+    cell_map->prop = def;	} G_STMT_END
+
+  SET_PROP (cell_width, DEFAULT_CELL_WIDTH);
+  SET_PROP (cell_height, DEFAULT_CELL_HEIGHT);
+
+#undef SET_PROP
+
+  compute_vertical_scroll (cell_map);
+}
+
+static void
+ocfs_cell_map_state_changed (GtkWidget    *widget,
+			     GtkStateType  old_state)
+{
+  OcfsCellMap *cell_map = OCFS_CELL_MAP (widget);
+
+  paint_cell_map (cell_map);
+  gtk_widget_queue_draw (widget);
+}
+
+static void
+ocfs_cell_map_size_request (GtkWidget      *widget,
+			    GtkRequisition *requisition)
+{
+  OcfsCellMap *cell_map = OCFS_CELL_MAP (widget);
+
+  requisition->width  = cell_map->cell_width;
+  requisition->height = cell_map->cell_height;
+}
+
+static void
+create_offscreen_pixmap (OcfsCellMap *cell_map)
+{
+  GtkWidget    *widget;
+
+  if (GTK_WIDGET_REALIZED (cell_map))
+    {
+      widget = GTK_WIDGET (cell_map);
+
+      if (cell_map->offscreen_pixmap)
+	gdk_pixmap_unref (cell_map->offscreen_pixmap);
+
+      cell_map->offscreen_pixmap = gdk_pixmap_new (widget->window,
+						   widget->allocation.width,
+						   widget->allocation.height,
+						   -1);
+      paint_cell_map (cell_map);
+    }
+}
+
+static void
+paint_cell_map (OcfsCellMap *cell_map)
+{
+  GtkWidget    *widget = GTK_WIDGET (cell_map);
+  GtkStateType  state, type;
+  gint          i;
+  gint          width, height;
+  gint          dx, dy;
+  gint          per_row;
+  gint          start, end;
+  gint          val;
+
+  if (!cell_map->offscreen_pixmap)
+    return;
+
+  gtk_paint_flat_box (widget->style,
+		      cell_map->offscreen_pixmap,
+		      GTK_STATE_NORMAL, GTK_SHADOW_NONE,
+		      NULL, widget, "cell_map_bg",
+		      0, 0,
+		      widget->allocation.width,
+		      widget->allocation.height);
+
+  if (cell_map && cell_map->map->len)
+    {
+      width  = widget->allocation.width  - 1;
+      height = widget->allocation.height - 1;
+
+      per_row = width / cell_map->cell_width;
+      per_row = MAX (1, per_row);
+      
+      val = cell_map->vadj->value;
+
+      start = val / cell_map->cell_height * per_row;
+      end = height / cell_map->cell_height * per_row + start;
+      end = MIN (end, cell_map->map->len);
+
+      if (end != cell_map->map->len && end + per_row > cell_map->map->len)
+	{
+	  if (val % cell_map->cell_height)
+	    {
+	      start += per_row;
+	      end = cell_map->map->len;
+	    }
+	}
+
+      state = GTK_STATE_NORMAL;
+      if (!GTK_WIDGET_IS_SENSITIVE (widget))
+	state = GTK_STATE_INSENSITIVE;
+
+      for (i = start; i < end; i++)
+	{
+	  dx = (i % per_row) * cell_map->cell_width;
+	  dy = ((i - start) / per_row) * cell_map->cell_height;
+
+	  type = cell_map->map->data[i] ? GTK_STATE_SELECTED
+					: state;
+
+	  gdk_draw_rectangle (cell_map->offscreen_pixmap,
+			      widget->style->fg_gc[state],
+			      FALSE,
+			      dx, dy,
+			      cell_map->cell_width,
+			      cell_map->cell_height);
+
+	  gdk_draw_rectangle (cell_map->offscreen_pixmap,
+			      widget->style->bg_gc[type],
+			      TRUE,
+			      dx + 1, dy + 1,
+			      cell_map->cell_width - 1,
+			      cell_map->cell_height - 1);
+	}
+    }
+}
+
+static gboolean
+ocfs_cell_map_configure (GtkWidget         *widget,
+			 GdkEventConfigure *event)
+{
+  OcfsCellMap *cell_map = OCFS_CELL_MAP (widget);
+
+  create_offscreen_pixmap (cell_map);
+  compute_vertical_scroll (cell_map);
+
+  return FALSE;
+}
+
+static gboolean
+ocfs_cell_map_expose (GtkWidget      *widget,
+		      GdkEventExpose *event)
+{
+  if (GTK_WIDGET_DRAWABLE (widget))
+    gdk_draw_pixmap (widget->window,
+		     widget->style->black_gc,
+		     OCFS_CELL_MAP (widget)->offscreen_pixmap,
+		     event->area.x, event->area.y,
+		     event->area.x, event->area.y,
+		     event->area.width,
+		     event->area.height);
+
+  return FALSE;
+}
+
+static gboolean
+ocfs_cell_map_button_press (GtkWidget      *widget,
+			    GdkEventButton *event)
+{
+  return FALSE;
+}
+
+static gboolean
+ocfs_cell_map_button_release (GtkWidget      *widget,
+			      GdkEventButton *event)
+{
+  return FALSE;
+}
+
+static gboolean
+ocfs_cell_map_motion_notify (GtkWidget      *widget,
+			     GdkEventMotion *event)
+{
+  return FALSE;
+}
+
+static void
+ocfs_cell_map_set_adjustments (OcfsCellMap   *cell_map,
+			       GtkAdjustment *hadj,
+			       GtkAdjustment *vadj)
+{
+  if (hadj)
+    g_return_if_fail (GTK_IS_ADJUSTMENT (hadj));
+  else
+    hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
+
+  if (vadj)
+    g_return_if_fail (GTK_IS_ADJUSTMENT (vadj));
+  else
+    vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
+
+  if (cell_map->hadj && (cell_map->hadj != hadj))
+    {
+      gtk_signal_disconnect_by_data (GTK_OBJECT (cell_map->hadj), cell_map);
+      gtk_object_unref (GTK_OBJECT (cell_map->hadj));
+    }
+
+  if (cell_map->vadj && (cell_map->vadj != vadj))
+    {
+      gtk_signal_disconnect_by_data (GTK_OBJECT (cell_map->vadj), cell_map);
+      gtk_object_unref (GTK_OBJECT (cell_map->vadj));
+    }
+
+  if (cell_map->hadj != hadj)
+    {
+      cell_map->hadj = hadj;
+      gtk_object_ref (GTK_OBJECT (cell_map->hadj));
+      gtk_object_sink (GTK_OBJECT (cell_map->hadj));
+
+      gtk_signal_connect (GTK_OBJECT (cell_map->hadj), "changed",
+			  GTK_SIGNAL_FUNC (update_adjustment), cell_map);
+      gtk_signal_connect (GTK_OBJECT (cell_map->hadj), "value_changed",
+			  GTK_SIGNAL_FUNC (update_adjustment), cell_map);
+
+      update_adjustment (hadj, cell_map);
+    }
+
+  if (cell_map->vadj != vadj)
+    {
+      cell_map->vadj = vadj;
+      gtk_object_ref (GTK_OBJECT (cell_map->vadj));
+      gtk_object_sink (GTK_OBJECT (cell_map->vadj));
+
+      gtk_signal_connect (GTK_OBJECT (cell_map->vadj), "changed",
+			  GTK_SIGNAL_FUNC (update_adjustment), cell_map);
+      gtk_signal_connect (GTK_OBJECT (cell_map->vadj), "value_changed",
+			  GTK_SIGNAL_FUNC (update_adjustment), cell_map);
+
+      update_adjustment (vadj, cell_map);
+    }
+}
+
+static void
+update_adjustment (GtkAdjustment *adj,
+		   OcfsCellMap   *cell_map)
+{
+  gfloat prev_val;
+
+  prev_val = adj->value;
+
+  adj->value = MIN (adj->value, adj->upper - adj->page_size);
+  adj->value = MAX (adj->value, 0.0);
+
+  if (adj->value != prev_val)
+    {
+      gtk_signal_handler_block_by_func (GTK_OBJECT (adj),
+					GTK_SIGNAL_FUNC (update_adjustment),
+					cell_map);
+      gtk_adjustment_changed (adj);
+      gtk_signal_handler_unblock_by_func (GTK_OBJECT (adj),
+					  GTK_SIGNAL_FUNC (update_adjustment),
+					  cell_map);
+    }
+
+  if (GTK_WIDGET_REALIZED (cell_map))
+    {
+      if (adj == cell_map->vadj)
+	{
+	  paint_cell_map (cell_map);
+	  gtk_widget_queue_draw (GTK_WIDGET (cell_map));
+	}
+      else
+	g_warning ("Horizontal scrolling not supported");
+    }
+}
+
+static void
+compute_vertical_scroll (OcfsCellMap *cell_map)
+{
+  gint width, height;
+  gint per_row, real_height;
+  gint old_value;
+
+  old_value = (gint) cell_map->vadj->value;
+
+  width  = GTK_WIDGET (cell_map)->allocation.width - 1;
+  height = GTK_WIDGET (cell_map)->allocation.height - 1;
+
+  per_row = width / cell_map->cell_width;
+  per_row = MAX (1, per_row);
+
+  real_height = (cell_map->map->len / per_row + 1) * cell_map->cell_height;
+
+  cell_map->vadj->upper = real_height;
+
+  cell_map->vadj->step_increment = MIN (cell_map->vadj->upper, cell_map->cell_height);
+  cell_map->vadj->page_increment = MIN (cell_map->vadj->upper, height - cell_map->cell_height * 2);
+  cell_map->vadj->page_size      = MIN (cell_map->vadj->upper, height);
+  cell_map->vadj->value          = MIN (cell_map->vadj->value, cell_map->vadj->upper - cell_map->vadj->page_size);
+  cell_map->vadj->value          = MAX (cell_map->vadj->value, 0.0);
+
+  gtk_signal_emit_by_name (GTK_OBJECT (cell_map->vadj), "changed");
+}
+
+#ifdef CELLMAP_TEST
+
+#define LENGTH 160
+
+int
+main (int    argc,
+      char **argv)
+{
+  GtkWidget  *window;
+  GtkWidget  *vbox;
+  GtkWidget  *scrl_win;
+  GtkWidget  *cell_map;
+  GtkWidget  *button;
+  GByteArray *map;
+  gint        i;
+
+  gtk_init (&argc, &argv);
+
+  map = g_byte_array_new ();
+  g_byte_array_set_size (map, LENGTH);
+
+  for (i = 0; i < LENGTH; i++)
+    map->data[i] = i % 2 ? 0xff : 0x00;
+
+  window = gtk_widget_new (GTK_TYPE_WINDOW,
+			   "type", GTK_WINDOW_TOPLEVEL,
+			   "border_width", 5,
+			   "signal::delete-event", gtk_main_quit, NULL,
+			   NULL);
+
+  vbox = gtk_vbox_new (FALSE, 5);
+  gtk_container_add (GTK_CONTAINER (window), vbox);
+
+  scrl_win = gtk_widget_new (GTK_TYPE_SCROLLED_WINDOW,
+			     "hscrollbar_policy", GTK_POLICY_NEVER,
+			     "vscrollbar_policy", GTK_POLICY_ALWAYS,
+			     "parent", vbox,
+			     NULL);
+
+  cell_map = gtk_widget_new (OCFS_TYPE_CELL_MAP,
+			     "map", map,
+			     "parent", scrl_win,
+			     NULL);
+
+  button = gtk_widget_new (GTK_TYPE_BUTTON,
+			   "label", "Whee!",
+			   "signal::clicked", gtk_main_quit, NULL,
+			   NULL);
+  gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+
+  gtk_widget_show_all (window);
+
+  gtk_main ();
+
+  return 0;
+}
+#endif

Added: trunk/ocfstool/ocfscellmap.h
===================================================================
--- trunk/ocfstool/ocfscellmap.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfscellmap.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,77 @@
+/*
+ * ocfscellmap.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Manish Singh
+ */
+
+#ifndef __OCFS_CELL_MAP_H__
+#define __OCFS_CELL_MAP_H__
+
+
+#include <gtk/gtk.h>
+
+
+#define OCFS_TYPE_CELL_MAP            (ocfs_cell_map_get_type ())
+#define OCFS_CELL_MAP(obj)            (GTK_CHECK_CAST ((obj), OCFS_TYPE_CELL_MAP, OcfsCellMap))
+#define OCFS_CELL_MAP_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), OCFS_TYPE_CELL_MAP, OcfsCellMapClass))
+#define OCFS_IS_CELL_MAP(obj)         (GTK_CHECK_TYPE ((obj), OCFS_TYPE_CELL_MAP))
+#define OCFS_IS_CELL_MAP_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), OCFS_TYPE_CELL_MAP))
+
+
+typedef struct _OcfsCellMap      OcfsCellMap;
+typedef struct _OcfsCellMapClass OcfsCellMapClass;
+
+struct _OcfsCellMap
+{
+  GtkWidget      parent_instance;
+
+  GByteArray    *map;
+
+  gint           cell_width;
+  gint           cell_height;
+
+  GdkPixmap     *offscreen_pixmap;
+
+  GtkAdjustment *hadj;
+  GtkAdjustment *vadj;
+};
+
+struct _OcfsCellMapClass
+{
+  GtkWidgetClass parent_class;
+
+  void  (*set_scroll_adjustments) (OcfsCellMap   *bd,
+				   GtkAdjustment *hadjustment,
+				   GtkAdjustment *vadjustment);
+};
+
+
+GtkType     ocfs_cell_map_get_type       (void);
+GtkWidget  *ocfs_cell_map_new            (GByteArray  *map);
+void        ocfs_cell_map_set_map        (OcfsCellMap *cell_map,
+					  GByteArray  *map);
+void        ocfs_cell_map_set_cell_props (OcfsCellMap *cell_map,
+					  gint         cell_width,
+					  gint         cell_height);
+
+
+#endif /* __OCFS_CELL_MAP_H__ */

Added: trunk/ocfstool/ocfsformat.c
===================================================================
--- trunk/ocfstool/ocfsformat.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfsformat.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,517 @@
+/*
+ * ocfsformat.c
+ *
+ * The format dialog box
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Manish Singh
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <grp.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <gtk/gtk.h>
+
+#include "libdebugocfs.h"
+
+#include "ocfsprocess.h"
+#include "ocfsguiutil.h"
+#include "ocfsplist.h"
+#include "ocfsformat.h"
+
+enum {
+  DEVICE,
+  SIZE,
+  LABEL,
+  MOUNT,
+  UID,
+  GID,
+  PERMS,
+  CLEAR,
+  FORCE,
+  NUM_ENTRIES
+};
+
+/* FIXME: shouldn't really hardcode these */
+#define SIZE_LABEL 64
+#define SIZE_MOUNT (sizeof (((libocfs_volinfo *) 0)->mountpoint) / \
+		    sizeof (((libocfs_volinfo *) 0)->mountpoint[0]) - 1)
+
+typedef enum {
+  ENTRY_COMBO,
+  ENTRY_TEXT,
+  ENTRY_HOSTNAME,
+  ENTRY_OCTAL,
+  ENTRY_SIZE,
+  ENTRY_UID,
+  ENTRY_GID,
+  ENTRY_CHECK
+} EntryType;
+
+typedef struct _FormatEntry FormatEntry;
+
+struct _FormatEntry
+{
+  const gchar *desc;
+  const gchar *def;
+
+  guint16      max;
+
+  EntryType    type;
+
+  gboolean     format_only;
+  gboolean     advanced;
+
+  GtkWidget   *entry;
+};
+
+
+static void      do_format     (GtkWidget   *button,
+			        FormatEntry *entries);
+static gchar    *size_iterator (gpointer     data);
+static void      build_entries (GtkTable    *table,
+				gboolean     advanced,
+				gboolean     resize,
+				FormatEntry *entries);
+static gboolean  disk_op       (GtkWindow   *parent,
+				gchar       *device,
+				gboolean     advanced,
+				gboolean     resize);
+
+
+static void
+do_format (GtkWidget   *button,
+	   FormatEntry *entries)
+{
+  GtkWindow     *parent;
+  gboolean       resize;
+  struct passwd *pwd;
+  struct group  *grp;
+  pid_t          pid;
+  gint           outfd, errfd;
+  gboolean       success;
+  gint           pos;
+  gchar         *errmsg;
+  gchar         *device;
+  gchar         *size = NULL, *label = NULL, *mount = NULL;
+  gchar         *uid, *gid, *perms;
+  gchar         *query, *action, *actioning;
+  gint           max_arg;
+  gchar         *argv[] = {
+    NULL,
+    "-x", "-q",
+    "-u", NULL,
+    "-g", NULL,
+    "-p", NULL,
+    "-b", NULL,
+    "-L", NULL,
+    "-m", NULL,
+    NULL, NULL, NULL,
+    NULL
+  };
+
+  parent = ocfs_widget_get_toplevel (button);
+
+  resize = GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (parent),
+						 "resize_action"));
+
+  if (resize)
+    { 
+      argv[0] = "resizeocfs";
+      max_arg = 9;
+
+      query = "resize";
+      action = "Resize";
+      actioning = "Resizing";
+    }
+  else
+    {
+      argv[0] = "mkfs.ocfs";
+      max_arg = 15;
+
+      query = "format";
+      action = "Format";
+      actioning = "Formatting";
+    }
+
+#define CHECK_TEXT(type, value, error)			G_STMT_START {	\
+  gint len;								\
+									\
+  (value) = gtk_entry_get_text (GTK_ENTRY (entries[(type)].entry));	\
+									\
+  len = strlen ((value));						\
+									\
+  if (len == 0)								\
+    {									\
+      ocfs_error_box (parent, NULL, "Invalid %s", (error));		\
+      return;								\
+    }							} G_STMT_END
+
+  if (!resize)
+    CHECK_TEXT (LABEL, label, "volume label");
+
+#undef CHECK_TEXT
+
+#define CHECK_ENTRY(type, value, check, min, error)	G_STMT_START {	\
+  gint len;								\
+									\
+  (value) = gtk_entry_get_text (GTK_ENTRY (entries[(type)].entry));	\
+									\
+  len = strlen ((value));						\
+									\
+  if (len < (min) || (value)[0] != (check))				\
+    {									\
+      ocfs_error_box (parent, NULL, "Invalid %s", (error));		\
+      return;								\
+    }							} G_STMT_END
+
+  if (!resize)
+    CHECK_ENTRY (MOUNT, mount, '/', 2, "mountpoint");
+
+  CHECK_ENTRY (PERMS, perms, '0', 4, "protection");
+
+#undef CHECK_ENTRY
+
+#define COMBO_ENTRY(type, value) \
+  (value) = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (entries[(type)].entry)->entry))
+    
+  COMBO_ENTRY (DEVICE, device);
+
+  if (!resize)
+    {
+      COMBO_ENTRY (SIZE, size);
+      pos = strspn (size, "0123456789");
+      size = g_strndup (size, pos);
+    }
+
+  COMBO_ENTRY (UID, uid);
+  pwd = getpwnam (uid);
+  uid = g_strdup_printf ("%d", pwd->pw_uid);
+
+  COMBO_ENTRY (GID, gid);
+  grp = getgrnam (gid);
+  gid = g_strdup_printf ("%d", grp->gr_gid);
+
+#undef COMBO_ENTRY
+
+#define OPT_CHECK(type, option)				G_STMT_START {	\
+  GtkWidget *button;							\
+									\
+  button = entries[type].entry;						\
+									\
+  if (button)								\
+    {									\
+      if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))	\
+	argv[max_arg++] = option;					\
+    }							} G_STMT_END
+
+  OPT_CHECK (CLEAR, "-C");
+  OPT_CHECK (FORCE, "-F");
+
+#undef OPT_CHECK
+
+  if (!ocfs_query_box (parent, "Are you sure you want to %s %s?", query, device))
+    return;
+
+  argv[4] = uid;
+  argv[6] = gid;
+  argv[8] = perms;
+
+  if (!resize)
+    {
+      argv[10] = size;
+      argv[12] = label;
+      argv[14] = mount;
+    }
+
+  argv[max_arg++] = device;
+  argv[max_arg] = NULL;
+
+  pid = ocfs_process_run (argv[0], argv, &outfd, &errfd);
+
+  g_free (uid);
+  g_free (gid);
+
+  success = ocfs_process_reap (parent, pid, FALSE, FALSE,
+			       action, actioning,
+			       outfd, NULL, errfd, &errmsg, NULL);
+  if (!success)
+    {
+      ocfs_error_box (parent, errmsg, "%s error", action);
+      g_free (errmsg);
+    }
+  else
+    gtk_object_set_data (GTK_OBJECT (button), "success", GINT_TO_POINTER (1));
+
+  gtk_main_quit ();
+}
+
+static gchar *
+size_iterator (gpointer data)
+{
+  gint *i = data;
+
+  *i += 1;
+
+  return *i < 10 ? g_strdup_printf ("%d K", 2 << *i) : NULL;
+}
+
+static void
+build_entries (GtkTable    *table,
+	       gboolean     advanced,
+	       gboolean     resize,
+	       FormatEntry *entries)
+{
+  GtkWidget *label;
+  GtkWidget *entry;
+  gchar     *desc, *def;
+  gint       i, j, row;
+  gboolean   do_label;
+
+  for (i = 0, row = 0; i < NUM_ENTRIES; i++)
+    {
+      if (resize && entries[i].format_only)
+	{
+	  entries[i].entry = NULL;
+	  continue;
+	}
+
+      if (!advanced && entries[i].advanced)
+	{
+	  entries[i].entry = NULL;
+	  continue;
+	}
+
+      do_label = TRUE;
+
+      switch (entries[i].type)
+	{
+	case ENTRY_CHECK:
+	  entry = gtk_check_button_new_with_label (entries[i].desc);
+
+	  if (strcmp (entries[i].def, "1") == 0)
+	    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (entry), TRUE);
+
+	  do_label = FALSE;
+	  break;
+
+	case ENTRY_TEXT:
+	case ENTRY_HOSTNAME:
+	  entry = gtk_entry_new ();
+
+	  if (entries[i].type == ENTRY_HOSTNAME)
+	    {
+	      def = g_new0 (char, entries[i].max + 1);
+	      gethostname (def, entries[i].max + 1);
+	      def[entries[i].max] = '\0';
+
+	      gtk_entry_set_text (GTK_ENTRY (entry), def);
+
+	      g_free (def);
+	    }
+	  else
+	    gtk_entry_set_text (GTK_ENTRY (entry), entries[i].def);
+
+	  gtk_entry_set_max_length (GTK_ENTRY (entry), entries[i].max);
+	  break;
+
+	case ENTRY_OCTAL:
+	  entry = ocfs_build_octal_entry (entries[i].def);
+	  break;
+
+	case ENTRY_COMBO:
+	case ENTRY_SIZE:
+          entry = ocfs_build_combo ();
+
+	  if (entries[i].type == ENTRY_SIZE)
+	    {
+	      j = 0;
+	      def = g_strconcat (entries[i].def, " K", NULL);
+	      ocfs_build_list (GTK_COMBO (entry)->list, def, size_iterator, &j);
+	      g_free (def);
+	    }
+
+	  break;
+
+	case ENTRY_UID:
+	  entry = ocfs_build_combo_user (entries[i].def);
+	  break;
+
+	case ENTRY_GID:
+	  entry = ocfs_build_combo_group (entries[i].def);
+	  break;
+
+	default:
+	  entry = NULL;
+	  break;
+	}
+
+      gtk_table_attach_defaults (table, entry, 1, 2, row, row + 1);
+      entries[i].entry = entry;
+
+      if (do_label)
+	{
+	  desc = g_strconcat (entries[i].desc, ":", NULL);
+	  label = gtk_widget_new (GTK_TYPE_LABEL,
+				  "label", desc,
+				  "xalign", 1.0,
+				  NULL);
+	  g_free (desc);
+
+	  gtk_table_attach_defaults (table, label, 0, 1, row, row + 1);
+	}
+
+      row++;
+    }
+}
+
+static FormatEntry entries[] = {
+  { "Device",                "",        0,          ENTRY_COMBO,    FALSE, FALSE, NULL },
+  { "Block Size",            "128",     0,          ENTRY_SIZE,     TRUE,  FALSE, NULL },
+  { "Volume Label",          "oracle",  SIZE_LABEL, ENTRY_TEXT,     TRUE,  FALSE, NULL },
+  { "Mountpoint",            "/oracle", SIZE_MOUNT, ENTRY_TEXT,     TRUE,  FALSE, NULL },
+  { "User",                  "root",    0,          ENTRY_UID,      FALSE, FALSE, NULL },
+  { "Group",                 "root",    0,          ENTRY_GID,      FALSE, FALSE, NULL },
+  { "Protection",            "0755",    0,          ENTRY_OCTAL,    FALSE, FALSE, NULL },
+  { "Clear All Data Blocks", "",        0,          ENTRY_CHECK,    FALSE, TRUE,  NULL },
+  { "Force",                 "",        0,          ENTRY_CHECK,    FALSE, TRUE,  NULL },
+};
+
+gboolean
+disk_op (GtkWindow *parent,
+	 gchar     *device,
+	 gboolean   advanced,
+	 gboolean   resize)
+{
+  GtkWidget    *dialog;
+  GtkWidget    *table;
+  GtkWidget    *item;
+  GtkContainer *container;
+  GList        *list, *last;
+  gchar        *str, *title;
+  gint          rows;
+
+  list = ocfs_partition_list (TRUE);
+  if (list == NULL)
+    {
+      ocfs_error_box (parent, NULL, "No unmounted partitions");
+      return FALSE;
+    }
+
+  if (resize)
+    {
+      title = "OCFS Resize";
+
+      if (advanced)
+	rows = 9;
+      else
+	rows = 7;
+    }
+  else
+    {
+      title = "OCFS format";
+
+      if (advanced)
+	rows = 6;
+      else
+	rows = 4;
+    }
+
+  dialog = ocfs_dialog_new (parent, title, do_format, entries);
+  gtk_object_set_data (GTK_OBJECT (dialog), "resize_action",
+		       GINT_TO_POINTER (resize));
+
+  table = gtk_widget_new (GTK_TYPE_TABLE,
+			  "n_rows", rows,
+			  "n_columns", 2,
+			  "homogeneous", FALSE,
+			  "row_spacing", 4,
+			  "column_spacing", 4,
+			  "border_width", 4,
+			  "parent", GTK_DIALOG (dialog)->vbox,
+			  NULL);
+
+  build_entries (GTK_TABLE (table), advanced, resize, entries);
+
+  list = g_list_sort (list, (GCompareFunc) strcmp);
+
+  container = GTK_CONTAINER (GTK_COMBO (entries[DEVICE].entry)->list);
+
+  while (list)
+    {
+      str = list->data;
+
+      item = gtk_list_item_new_with_label (str);
+      gtk_widget_show (item);
+      gtk_container_add (container, item);
+
+      if (device && strcmp (device, str) == 0)
+	gtk_list_item_select (GTK_LIST_ITEM (item));
+
+      g_free (str);
+
+      last = list;
+      list = list->next;
+
+      g_list_free_1 (last);
+    }
+
+#ifdef FORMAT_TEST
+  gtk_window_set_modal (GTK_WINDOW (dialog), FALSE);
+#endif
+
+  gtk_widget_grab_focus (entries[DEVICE].entry);
+
+  return ocfs_dialog_run (dialog);
+}
+
+gboolean
+ocfs_format (GtkWindow *parent,
+	     gchar     *device,
+	     gboolean   advanced)
+{
+  return disk_op (parent, device, advanced, FALSE);
+}
+
+gboolean
+ocfs_resize (GtkWindow *parent,
+	     gchar     *device,
+	     gboolean   advanced)
+{
+  return disk_op (parent, device, advanced, TRUE);
+}
+
+#ifdef FORMAT_TEST
+int
+main (int    argc,
+      char **argv)
+{
+  gtk_init (&argc, &argv);
+
+  ocfs_format (NULL, NULL, FALSE);
+  ocfs_resize (NULL, NULL, FALSE);
+
+  return 0;
+}
+#endif

Added: trunk/ocfstool/ocfsformat.h
===================================================================
--- trunk/ocfstool/ocfsformat.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfsformat.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,38 @@
+/*
+ * ocfsformat.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Manish Singh
+ */
+
+#ifndef __OCFS_FORMAT_H__
+#define __OCFS_FORMAT_H__
+
+
+gboolean ocfs_format (GtkWindow *parent,
+		      gchar     *device,
+		      gboolean   advanced);
+gboolean ocfs_resize (GtkWindow *parent,
+		      gchar     *device,
+		      gboolean   advanced);
+
+
+#endif /* __OCFS_FORMAT_H__ */

Added: trunk/ocfstool/ocfsfreespace.c
===================================================================
--- trunk/ocfstool/ocfsfreespace.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfsfreespace.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,174 @@
+/*
+ * ocfsfreespace.c
+ *
+ * The free space display tab
+ *
+ * Copyright (C) 2003 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Manish Singh
+ */
+
+#include <stdlib.h>
+
+#include <gtk/gtk.h>
+
+#include "libdebugocfs.h"
+
+#include "ocfsguiutil.h"
+#include "ocfsfreespace.h"
+
+
+typedef struct _FreeNode FreeNode;
+                                                                                
+struct _FreeNode
+{
+    guint64 size;
+    gint    offset;
+};
+
+
+static gint      size_compare   (gconstpointer  da,
+				 gconstpointer  db);
+static GSList   *get_free_areas (guint8        *bits,
+                                 gint           length,
+				 gint           extent_size);
+static gboolean  list_populate  (GtkCList      *clist,
+				 const gchar   *device);
+
+
+static gint
+size_compare (gconstpointer da,
+              gconstpointer db)
+{
+  const FreeNode *a, *b;
+
+  a = da;
+  b = db;
+
+  if (a->size < b->size)
+    return 1;
+  else if (a->size > b->size)
+    return -1;
+  else if (a->offset < b->offset)
+    return -1;
+  else if (a->offset > b->offset)
+    return 1;
+  else
+    return 0;
+}
+
+static GSList *
+get_free_areas (guint8 *bits,
+		gint    length,
+		gint    extent_size) 
+{
+  FreeNode *node = NULL;
+  GSList   *node_list = NULL;
+  gint      i;
+
+  for (i = 0; i < length; i++)
+    {
+      if (!(bits[i / 8] & (1 << (i % 8))))
+	{
+	  if (!node)
+	    {
+	      node = g_new (FreeNode, 1);
+
+	      node->size = extent_size;
+	      node->offset = i;
+
+	      node_list = g_slist_append (node_list, node);
+	    }
+	  else
+	    node->size += extent_size;
+	}
+      else
+	node = NULL;
+    }
+
+  node_list = g_slist_sort (node_list, size_compare);
+
+  return node_list;
+}
+
+static gboolean
+list_populate (GtkCList    *clist,
+	       const gchar *device)
+{
+  guint8          *bits;
+  gint             length;
+  libocfs_volinfo *info;
+  GSList          *node_list, *last;
+  FreeNode        *node;
+  gchar           *texts[2], buf[10];
+
+  if (!device ||
+      libocfs_get_bitmap (device, (gchar **) &bits, &length) ||
+      libocfs_get_volume_info (device, &info))
+    return FALSE;
+
+  node_list = get_free_areas (bits, length, info->extent_size);
+
+  free (info);
+  g_free (bits);
+
+  gtk_clist_freeze (clist);
+  gtk_clist_clear (clist);
+
+  texts[1] = buf;
+
+  while (node_list)
+    {
+      node = node_list->data;
+
+      texts[0] = ocfs_format_bytes (node->size, FALSE);
+
+      g_snprintf (buf, sizeof (buf), "%d", node->offset);
+
+      gtk_clist_append (clist, texts);
+      
+      g_free (texts[0]);
+
+      last = node_list;
+      node_list = node_list->next;
+      
+      g_free (node);
+      g_slist_free_1 (last);
+    }
+
+  gtk_clist_thaw (clist);
+
+  return TRUE;
+}
+
+GtkWidget *
+ocfs_freespace (const gchar *device,
+		gboolean     advanced)
+{
+  GtkCList     *clist;
+  GtkWidget    *scrl_win;
+  static gchar *titles[2] = { "Size", "Bit #" };
+
+  clist = ocfs_build_clist (2, titles, &scrl_win);
+  gtk_clist_set_auto_sort (clist, FALSE);
+
+  if (list_populate (clist, device))
+    return scrl_win;
+  else
+    return gtk_label_new ("Invalid device");
+}

Added: trunk/ocfstool/ocfsfreespace.h
===================================================================
--- trunk/ocfstool/ocfsfreespace.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfsfreespace.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,34 @@
+/*
+ * ocfsfreespace.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2003 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Manish Singh
+ */
+
+#ifndef __OCFS_FREESPACE_H__
+#define __OCFS_FREESPACE_H__
+
+
+GtkWidget *ocfs_freespace (const gchar *device,
+			   gboolean     advanced);
+
+
+#endif /* __OCFS_FREESPACE_H__ */

Added: trunk/ocfstool/ocfsgenconfig.c
===================================================================
--- trunk/ocfstool/ocfsgenconfig.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfsgenconfig.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,320 @@
+/*
+ * ocfsgenconfig.c
+ *
+ * The /etc/ocfs.conf generator
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Manish Singh
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <gtk/gtk.h>
+
+#include "ocfsprocess.h"
+#include "ocfsguiutil.h"
+#include "ocfsgenconfig.h"
+
+
+enum {
+  NODENAME,
+  DEVICE,
+  PORT
+};
+
+/* FIXME: shouldn't really hardcode this */
+#define SIZE_HOSTNAME 255 
+
+#define INTERFACE_LIST_CMD "/sbin/ifconfig | grep '^[a-z]' | cut -c 1-8"
+
+#define INTERFACE_INFO_CMD "/sbin/ifconfig %s | grep 'inet addr:' | " \
+			   "sed 's/.*inet addr:\\([0-9.]*\\).*/\\1/'"
+
+
+static void     uid_gen               (GtkWindow    *parent);
+static void     do_config             (GtkWidget    *button,
+				       GtkWidget   **entries);
+static void     numeric_insert_filter (GtkEditable  *editable,
+				       const gchar  *text,
+				       gint          length,
+				       gint         *position);
+static gboolean build_entries         (GtkWindow    *parent,
+				       GtkTable     *table,
+				       gboolean      advanced,
+				       GtkWidget   **entries);
+
+
+static void
+uid_gen (GtkWindow *parent)
+{
+  gchar    *argv[] = { "ocfs_uid_gen", "-c", NULL };
+  pid_t     pid;
+  gint      outfd, errfd;
+  gchar    *outmsg, *errmsg;
+  gboolean  success;
+
+  pid = ocfs_process_run (argv[0], argv, &outfd, &errfd);
+
+  success = ocfs_process_reap (parent, pid, TRUE, TRUE,
+			       "UID Generator", "UID Generator",
+			       outfd, &outmsg, errfd, &errmsg,
+			       NULL);
+  if (!success)
+    {
+      unlink (CONFFILE);
+
+      ocfs_error_box (parent, errmsg, "ocfs_uid_gen failed");
+      g_free (errmsg);
+    }
+
+  g_free (outmsg);
+}
+
+static void
+do_config (GtkWidget  *button,
+	   GtkWidget **entries)
+{
+  GtkWindow  *parent;
+  gchar      *interface, *address, *nodename;
+  gint        port;
+  gchar      *cmd;
+  gchar     **info;
+  FILE       *config;
+
+  parent = ocfs_widget_get_toplevel (button);
+
+  nodename = gtk_entry_get_text (GTK_ENTRY (entries[NODENAME]));
+  if (strlen (nodename) == 0)
+    {
+      ocfs_error_box (parent, NULL, "Invalid node name");
+      return;
+    }
+
+  port = strtol (gtk_entry_get_text (GTK_ENTRY (entries[PORT])), NULL, 10);
+  if (port == 0 || port > 65535)
+    {
+      ocfs_error_box (parent, NULL, "Invalid port");
+      return;
+    }
+
+  interface = gtk_entry_get_text (GTK_ENTRY (entries[DEVICE]));
+  
+  cmd = g_strdup_printf (INTERFACE_INFO_CMD, interface);
+
+  info = ocfs_shell_output (parent, cmd); 
+
+  if (info && info[0] && info[0][0])
+    {
+      address = g_strdup (info[0]);
+    }
+  else
+    {
+      ocfs_error_box (parent, NULL, "Invalid interface");
+      return;
+    }
+
+  g_strfreev (info);
+
+  config = fopen (CONFFILE, "w");
+
+  if (config == NULL)
+    {
+      ocfs_error_box (parent, NULL, "Could not open %s", CONFFILE);
+      return;
+    }
+
+  fprintf (config, "#\n");
+  fprintf (config, "# ocfs config\n");
+  fprintf (config, "# Ensure this file exists in /etc\n");
+  fprintf (config, "#\n\n");
+  fprintf (config, "\tnode_name = %s\n", nodename);
+  fprintf (config, "\tip_address = %s\n", address);
+  fprintf (config, "\tip_port = %d\n", port);
+  fprintf (config, "\tcomm_voting = 1\n");
+
+  fclose (config);
+
+  g_free (address);
+
+  gtk_main_quit ();
+
+  uid_gen (parent);
+}
+
+static void
+numeric_insert_filter (GtkEditable  *editable,
+		       const gchar  *text,
+		       gint          length,
+		       gint         *position)
+{
+  gint i;
+
+  for (i = 0; i < length; i++)
+    if (text[i] < 0x30 || text[i] > 0x39)
+      gtk_signal_emit_stop_by_name (GTK_OBJECT (editable), "insert_text");
+}
+
+static gboolean
+build_entries (GtkWindow  *parent,
+	       GtkTable   *table,
+	       gboolean    advanced,
+	       GtkWidget **entries)
+{
+  GtkWidget     *label; 
+  GtkCombo      *combo; 
+  GtkWidget     *entry;
+  GtkContainer  *list;
+  GtkWidget     *item;
+  gchar         *def;
+  gchar        **interfaces;
+  int            i;
+  
+  combo = GTK_COMBO (ocfs_build_combo ());
+
+  entries[DEVICE] = entry = combo->entry;
+  list = GTK_CONTAINER (combo->list);
+
+  interfaces = ocfs_shell_output (parent, INTERFACE_LIST_CMD);
+
+  if (interfaces && interfaces[0] && interfaces[0][0])
+    {
+      for (i = 0; interfaces[i] != NULL; i++)
+	{
+	  item = gtk_list_item_new_with_label (interfaces[i]);
+	  gtk_widget_show (item);
+	  gtk_container_add (list, item);
+
+	  if (i == 0)
+	    gtk_list_item_select (GTK_LIST_ITEM (item));
+	}
+    }
+  else
+    {
+      ocfs_error_box (parent, NULL, "Unable to query network interfaces");
+      return FALSE;
+    }
+
+  g_strfreev (interfaces);
+
+  gtk_table_attach_defaults (table, GTK_WIDGET (combo), 1, 2, 0, 1);
+
+  label = gtk_widget_new (GTK_TYPE_LABEL,
+			  "label", "Interface:",
+			  "xalign", 1.0,
+			  NULL);
+  gtk_table_attach_defaults (table, label, 0, 1, 0, 1);
+
+  entry = gtk_widget_new (GTK_TYPE_ENTRY,
+			  "max_length", SIZE_HOSTNAME,
+			  NULL);
+
+  def = g_new0 (char, SIZE_HOSTNAME + 1);
+  gethostname (def, SIZE_HOSTNAME + 1);
+  def[SIZE_HOSTNAME] = '\0';
+
+  gtk_entry_set_text (GTK_ENTRY (entry), def);
+
+  g_free (def);
+
+  gtk_table_attach_defaults (table, entry, 1, 2, 2, 3);
+  entries[NODENAME] = entry;
+
+  label = gtk_widget_new (GTK_TYPE_LABEL,
+			  "label", "Node Name:",
+			  "xalign", 1.0,
+			  NULL);
+  gtk_table_attach_defaults (table, label, 0, 1, 2, 3);
+
+  entry = gtk_widget_new (GTK_TYPE_ENTRY,
+			  "max_length", 5,
+			  "signal::insert_text", numeric_insert_filter, NULL,
+			  NULL);
+  gtk_entry_set_text (GTK_ENTRY (entry), "7000");
+
+  gtk_table_attach_defaults (table, entry, 1, 2, 1, 2);
+  entries[PORT] = entry;
+
+  label = gtk_widget_new (GTK_TYPE_LABEL,
+			  "label", "Port:",
+			  "xalign", 1.0,
+			  NULL);
+  gtk_table_attach_defaults (table, label, 0, 1, 1, 2);
+
+  return TRUE;
+}
+
+void
+ocfs_generate_config (GtkWindow *parent,
+		      gboolean   advanced)
+{
+  struct stat  sbuf;
+  GtkWidget   *dialog;
+  GtkWidget   *table;
+  GtkWidget   *entries[3];
+
+  if (stat (CONFFILE, &sbuf) == 0)
+    {
+      ocfs_error_box (parent, NULL, "WARNING: %s exists\nIf you need to "
+				    "change settings or do recovery, please "
+				    "do so using command line tools",
+				    CONFFILE);
+      return;
+    }
+
+  dialog = ocfs_dialog_new (parent, "OCFS Generate Config", do_config, entries);
+
+  table = gtk_widget_new (GTK_TYPE_TABLE,
+			  "n_rows", 3,
+			  "n_columns", 2,
+			  "homogeneous", FALSE,
+			  "row_spacing", 4,
+			  "column_spacing", 4,
+			  "border_width", 4,
+			  "parent", GTK_DIALOG (dialog)->vbox,
+			  NULL);
+
+  if (!build_entries (parent, GTK_TABLE (table), advanced, entries))
+    return;
+
+#ifdef GENCONFIG_TEST
+  gtk_window_set_modal (GTK_WINDOW (dialog), FALSE);
+#endif
+
+  gtk_widget_grab_focus (entries[DEVICE]);
+
+  ocfs_dialog_run (dialog);
+}
+
+#ifdef GENCONFIG_TEST
+int
+main (int    argc,
+      char **argv)
+{
+  gtk_init (&argc, &argv);
+
+  ocfs_generate_config (NULL, TRUE);
+
+  return 0;
+}
+#endif

Added: trunk/ocfstool/ocfsgenconfig.h
===================================================================
--- trunk/ocfstool/ocfsgenconfig.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfsgenconfig.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,41 @@
+/*
+ * ocfsgenconfig.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Manish Singh
+ */
+
+#ifndef __OCFS_GENCONFIG_H__
+#define __OCFS_GENCONFIG_H__
+
+
+#ifdef DEVEL_MACHINE
+#define CONFFILE "ocfs.conf"
+#else
+#define CONFFILE "/etc/ocfs.conf"
+#endif
+
+
+void ocfs_generate_config (GtkWindow *parent,
+			   gboolean   advanced);
+
+
+#endif /* __OCFS_GENCONFIG_H__ */

Added: trunk/ocfstool/ocfsgeneral.c
===================================================================
--- trunk/ocfstool/ocfsgeneral.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfsgeneral.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,362 @@
+/*
+ * ocfsgeneral.c
+ *
+ * The general overview tab
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Manish Singh
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <gtk/gtk.h>
+
+#include "libdebugocfs.h"
+
+#include "ocfsguiutil.h"
+#include "ocfsgeneral.h"
+
+
+enum {
+  EDIT_UID,
+  EDIT_GID,
+  EDIT_PERMS,
+  NUM_EDITS
+};
+
+typedef enum
+{
+  NONE,
+  BYTES,
+  SIZE,
+  UID,
+  GID
+} FormatType;
+
+typedef struct _InfoEntry InfoEntry;
+typedef struct _InfoState InfoState;
+
+struct _InfoEntry
+{
+  const gchar *key;
+
+  GtkWidget *(* build_func) (const gchar *def);
+};
+
+struct _InfoState
+{
+  gchar     *device;
+
+  GtkLabel  *labels[NUM_EDITS];
+  GtkWidget *entries[NUM_EDITS];
+};
+
+
+static void info_label      (GtkTable    *table,
+			     gint        *pos,
+			     gboolean     valid,
+			     FormatType   type,
+			     const gchar *desc,
+			     const gchar *format,
+			     ...) G_GNUC_PRINTF (6, 7);
+static void build_edit_info (GtkTable    *table,
+			     GtkObject   *labels,
+			     InfoEntry   *entries,
+			     InfoState   *state);
+static void edit_info       (GtkWidget   *button,
+			     GtkObject   *labels);
+static void info_change     (GtkWidget   *button,
+			     InfoState   *state);
+
+
+static void
+info_label (GtkTable    *table,
+	    gint        *pos,
+	    gboolean     valid,
+	    FormatType   type,
+	    const gchar *desc,
+	    const gchar *format,
+	    ...)
+{
+  va_list    args;
+  gchar     *str;
+  gint       id, size;
+  guint64    bytes;
+  GtkWidget *label;
+
+  str = g_strconcat (desc, ":", NULL);
+  label = gtk_widget_new (GTK_TYPE_LABEL,
+			  "label", str,
+			  "xalign", 1.0,
+			  "yalign", 0.0,
+			  "justify", GTK_JUSTIFY_RIGHT,
+			  NULL);
+  g_free (str);
+
+  gtk_table_attach (table, label, 0, 1, *pos, *pos + 1,
+		    GTK_FILL, GTK_FILL, 0, 0);
+
+  if (valid)
+    {
+      va_start (args, format);
+
+      switch (type)
+	{
+	case UID:
+	  id = va_arg (args, gint);
+	  str = ocfs_get_user_name (id);
+	  break;
+
+	case GID:
+	  id = va_arg (args, gint);
+	  str = ocfs_get_group_name (id);
+	  break;
+
+	case BYTES:
+	  bytes = va_arg (args, guint64);
+	  str = ocfs_format_bytes (bytes, TRUE);
+	  break;
+
+	case SIZE:
+	  size = va_arg (args, gint);
+	  str = ocfs_format_bytes (size, FALSE);
+	  break;
+
+	case NONE:
+	default:
+	  str = g_strdup_vprintf (format, args);
+	  break;
+	}
+
+      va_end (args);
+    }
+
+  label = gtk_widget_new (GTK_TYPE_LABEL,
+			  "label", valid ? str : "N/A",
+			  "xalign", 0.0,
+			  "yalign", 0.0,
+			  "justify", GTK_JUSTIFY_LEFT,
+			  NULL);
+  if (valid)
+    g_free (str);
+
+  gtk_table_attach (table, label, 1, 2, *pos, *pos + 1,
+		    GTK_FILL, GTK_FILL, 0, 0);
+
+  gtk_object_set_data (GTK_OBJECT (table), desc, label);
+
+  *pos += 1;
+}
+
+static void
+build_edit_info (GtkTable  *table,
+		 GtkObject *labels,
+		 InfoEntry *entries,
+		 InfoState *state)
+{
+  GtkWidget *label;
+  gchar     *desc, *def;
+  gint       i;
+
+  for (i = 0; i < NUM_EDITS; i++)
+    {
+      state->labels[i] = GTK_LABEL (gtk_object_get_data (labels,
+				    entries[i].key));
+
+      gtk_label_get (state->labels[i], &def);
+      state->entries[i] = entries[i].build_func (def);
+
+      gtk_table_attach_defaults (table, state->entries[i], 1, 2, i, i + 1);
+
+      desc = g_strconcat (entries[i].key, ":", NULL);
+      label = gtk_widget_new (GTK_TYPE_LABEL,
+			      "label", desc,
+			      "xalign", 1.0,
+			      NULL);
+      g_free (desc);
+
+      gtk_table_attach_defaults (table, label, 0, 1, i, i + 1);
+    }
+}
+
+static InfoEntry entries[] = {
+  { "UID",        ocfs_build_combo_user  },
+  { "GID",        ocfs_build_combo_group },
+  { "Protection", ocfs_build_octal_entry },
+};
+
+static void
+edit_info (GtkWidget *button,
+	   GtkObject *labels)
+{
+  GtkWidget *dialog;
+  GtkWidget *table;
+  InfoState  state;
+
+  state.device = gtk_object_get_data (labels, "device");
+
+  dialog = ocfs_dialog_new (ocfs_widget_get_toplevel (button),
+			    "Edit Device Info", info_change, &state);
+
+  table = gtk_widget_new (GTK_TYPE_TABLE,
+			  "n_rows", 3,
+			  "n_columns", 2,
+			  "homogeneous", FALSE,
+			  "row_spacing", 4,
+			  "column_spacing", 4,
+			  "border_width", 4,
+			  "parent", GTK_DIALOG (dialog)->vbox,
+			  NULL);
+
+  build_edit_info (GTK_TABLE (table), labels, entries, &state);
+
+  ocfs_dialog_run (dialog);
+}
+
+static void
+info_change (GtkWidget *button,
+	     InfoState *state)
+{
+  GtkWindow     *parent;
+  const gchar   *buf;
+  struct passwd *pwd;
+  struct group  *grp;
+  gint           len;
+  gint           perms, uid, gid;
+
+  parent = ocfs_widget_get_toplevel (button);
+
+  buf = gtk_entry_get_text (GTK_ENTRY (state->entries[EDIT_PERMS]));
+
+  len = strlen (buf);
+
+  if (len == 0 || len < 4 || buf[0] != '0')
+    {
+      ocfs_error_box (parent, NULL, "Invalid protection");
+      return;
+    }
+
+  perms = strtol (buf, NULL, 8);
+
+#define COMBO_ENTRY(type) \
+  buf = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (state->entries[(type)])->entry))
+
+  COMBO_ENTRY (EDIT_UID);
+  pwd = getpwnam (buf);
+  uid = pwd->pw_uid;
+
+  COMBO_ENTRY (EDIT_GID);
+  grp = getgrnam (buf);
+  gid = grp->gr_gid;
+
+
+  if (libocfs_chown_volume (state->device, perms, uid, gid) != 0)
+    {
+      ocfs_error_box (parent, NULL, "Unable to chown volume %s", state->device);
+      return;
+    }
+
+  buf = gtk_entry_get_text (GTK_ENTRY (state->entries[EDIT_PERMS]));
+  gtk_label_set_text (state->labels[EDIT_PERMS], buf);
+
+  COMBO_ENTRY (EDIT_UID);
+  gtk_label_set_text (state->labels[EDIT_UID], buf);
+
+  COMBO_ENTRY (EDIT_GID);
+  gtk_label_set_text (state->labels[EDIT_GID], buf);
+
+#undef COMBO_ENTRY
+
+  gtk_main_quit (); 
+}
+    	
+GtkWidget *
+ocfs_general (const gchar *device,
+	      gboolean     advanced)
+{
+  gboolean         valid = TRUE;
+  libocfs_volinfo *info = NULL;
+  GtkTable        *table;
+  GtkWidget       *hbox;
+  GtkWidget       *button;
+  gint             pos = 0;
+
+  if (device)
+    libocfs_get_volume_info (device, &info);
+
+  if (!info)
+    {
+      valid = FALSE;
+      info = malloc (sizeof (libocfs_volinfo));
+    }
+
+  table = GTK_TABLE (gtk_widget_new (GTK_TYPE_TABLE,
+				     "n_rows", advanced ? 10 : 9,
+				     "n_columns", 2,
+				     "homogeneous", FALSE,
+				     "row_spacing", 4,
+				     "column_spacing", 4,
+				     "border_width", 4,
+				     NULL));
+
+  info_label (table, &pos, valid, NONE, "Version", "%d.%d",
+	      info->major_ver, info->minor_ver);
+
+  info_label (table, &pos, valid, NONE, "Mountpoint", info->mountpoint);
+
+  info_label (table, &pos, valid, BYTES, "Volume Length", "%llu",
+	      info->length);
+  info_label (table, &pos, valid, NONE, "Number of Extents", "%llu",
+	      info->num_extents);
+  info_label (table, &pos, valid, SIZE, "Extent Size", "%d",
+	      info->extent_size);
+
+  info_label (table, &pos, valid, UID, "UID", "%d",  info->uid);
+  info_label (table, &pos, valid, GID, "GID", "%d", info->gid);
+
+  info_label (table, &pos, valid, NONE, "Protection", "0%o",
+	      info->protection & 0777);
+
+  free (info);
+
+  if (advanced)
+    {
+      hbox = gtk_hbox_new (FALSE, 0);
+      gtk_table_attach (table, hbox, 1, 2, pos, pos + 1,
+	  		GTK_FILL, GTK_FILL, 0, 0);
+
+      button = gtk_widget_new (GTK_TYPE_BUTTON,
+			       "label", "Edit...",
+			       "sensitive", valid,
+			       "signal::clicked", edit_info, table,
+			       NULL);
+
+      gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+
+      if (valid)
+	gtk_object_set_data_full (GTK_OBJECT (table), "device",
+				  g_strdup (device), g_free);
+    }
+
+  return GTK_WIDGET (table);
+}

Added: trunk/ocfstool/ocfsgeneral.h
===================================================================
--- trunk/ocfstool/ocfsgeneral.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfsgeneral.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,37 @@
+/*
+ * ocfsgeneral.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Manish Singh
+ */
+
+#ifndef __OCFS_GENERAL_H__
+#define __OCFS_GENERAL_H__
+
+
+#include <gtk/gtk.h>
+
+
+GtkWidget *ocfs_general (const gchar *device,
+			 gboolean     advanced);
+
+
+#endif /* __OCFS_GENERAL_H__ */

Added: trunk/ocfstool/ocfsguiutil.c
===================================================================
--- trunk/ocfstool/ocfsguiutil.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfsguiutil.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,575 @@
+/*
+ * ocfsguiutil.c
+ *
+ * Misc gui helper functions
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Manish Singh
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "ocfsprocess.h"
+#include "ocfsguiutil.h"
+
+
+static GtkWidget *make_dialog         (GtkWindow      *parent,
+				       const gchar    *title,
+				       gboolean        yes_no,
+				       gchar          *label,
+				       GtkSignalFunc   cb,
+				       gpointer        cb_data,
+				       GtkWidget     **ok);
+static gboolean   dialog_key_pressed  (GtkWidget      *dialog,
+				       GdkEventKey    *event);
+static void       do_yes              (GtkObject      *dialog);
+static void       get_text            (GtkObject      *button,
+				       gchar         **text);
+static gboolean   quit_on_delete      (void);
+static void       get_filename        (GtkWidget      *button,
+				       gchar         **fname);
+static void       octal_insert_filter (GtkEditable    *editable,
+				       const gchar    *text,
+				       gint            length,
+				       gint           *position);
+static gchar     *uid_iterator        (gpointer        data);
+static gchar     *gid_iterator        (gpointer        data);
+
+
+GtkWindow *
+ocfs_widget_get_toplevel (GtkWidget *widget)
+{
+  GtkWidget *toplevel;
+
+  toplevel = gtk_widget_get_toplevel (widget);
+
+  if (GTK_WIDGET_TOPLEVEL (toplevel))
+    return GTK_WINDOW (toplevel);
+
+  return NULL;
+}
+
+static gboolean
+dialog_key_pressed (GtkWidget   *dialog,
+		    GdkEventKey *event)
+{
+  if (event->keyval == GDK_Escape)
+    {
+      gtk_main_quit ();
+      return TRUE;
+    }
+
+  return FALSE;
+} 
+
+static GtkWidget *
+make_dialog (GtkWindow      *parent,
+	     const gchar    *title,
+	     gboolean        yes_no,
+	     gchar          *label,
+	     GtkSignalFunc   cb,
+	     gpointer        cb_data,
+	     GtkWidget     **ok)
+{
+  GtkWidget *dialog;
+  GtkWidget *action_area;
+  GtkWidget *hbbox;
+  GtkWidget *button;
+
+  dialog = gtk_widget_new (GTK_TYPE_DIALOG,
+			   "title", title,
+			   "allow_grow", FALSE,
+			   "modal", TRUE,
+			   "signal::delete-event", gtk_main_quit, NULL,
+			   "signal::key_press_event", dialog_key_pressed, NULL,
+			   NULL);
+  gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
+
+  gtk_widget_set (GTK_DIALOG (dialog)->vbox,
+		  "border_width", 4,
+		  NULL);
+
+  action_area = GTK_DIALOG (dialog)->action_area;
+  gtk_widget_set (action_area,
+		  "border_width", 2,
+		  "homogeneous", FALSE,
+		  NULL);
+
+  hbbox = gtk_hbutton_box_new ();
+  gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbbox), 4);
+  gtk_box_pack_end (GTK_BOX (action_area), hbbox, FALSE, FALSE, 0);
+
+  button = gtk_widget_new (GTK_TYPE_BUTTON,
+			   "label", yes_no ? "Yes" : "OK",
+			   "parent", hbbox,
+			   "can_default", TRUE,
+			   "has_default", TRUE,
+			   "signal::clicked", cb ? cb : gtk_main_quit, cb_data,
+			   NULL);
+
+  gtk_object_set_data (GTK_OBJECT (dialog), "button", button);
+
+  if (cb)
+    gtk_widget_new (GTK_TYPE_BUTTON,
+		    "label", yes_no ? "No" : "Cancel",
+		    "parent", hbbox,
+		    "can_default", TRUE,
+		    "signal::clicked", gtk_main_quit, NULL,
+		    NULL);
+
+  if (label)
+    {
+      gtk_widget_new (GTK_TYPE_LABEL,
+		      "label", label,
+		      "parent", GTK_DIALOG (dialog)->vbox,
+		      "wrap", TRUE,
+		      "yalign", 0.0,
+		      NULL);
+      g_free (label);
+    }
+
+  if (ok)
+    *ok = button;
+
+  return dialog;
+}
+
+GtkWidget *
+ocfs_dialog_new (GtkWindow     *parent,
+		 const gchar   *title,
+		 GtkSignalFunc  cb,
+		 gpointer       cb_data)
+{
+  return make_dialog (parent, title, FALSE, NULL, cb, cb_data, NULL);
+}
+
+gboolean
+ocfs_dialog_run (GtkWidget *dialog)
+{
+  GtkWidget *button;
+  gboolean   ret = FALSE;
+
+  gtk_widget_show_all (dialog);
+
+  gtk_main ();
+
+  button = gtk_object_get_data (GTK_OBJECT (dialog), "button");
+
+  if (gtk_object_get_data (GTK_OBJECT (button), "success"))
+    ret = TRUE;
+
+  gtk_widget_destroy (dialog);
+
+  return ret;
+}
+
+void
+ocfs_error_box (GtkWindow   *parent,
+		const gchar *errmsg, 
+    		const gchar *format,
+		...)
+{
+  GtkWidget *dialog;
+  gchar     *msg, *str;
+  va_list    args;
+
+  va_start (args, format);
+  msg = g_strdup_vprintf (format, args);
+  va_end (args);
+
+  if (errmsg && errmsg[0])
+    {
+      str = g_strconcat (msg, ":\n", errmsg, NULL);
+      g_free (msg);
+    }
+  else
+    str = msg;
+
+  dialog = make_dialog (parent, "Error", FALSE, str, NULL, NULL, NULL);
+
+  ocfs_dialog_run (dialog);
+}
+
+static void
+do_yes (GtkObject *button)
+{
+  gtk_object_set_data (button, "success", GINT_TO_POINTER (1));
+  gtk_main_quit ();
+}
+
+gboolean
+ocfs_query_box (GtkWindow   *parent,
+    		const gchar *format,
+		...)
+{
+  GtkWidget *dialog;
+  gchar     *msg;
+  va_list    args;
+
+  va_start (args, format);
+  msg = g_strdup_vprintf (format, args);
+  va_end (args);
+
+  dialog = make_dialog (parent, "Query", TRUE, msg, do_yes, NULL, NULL);
+
+  return ocfs_dialog_run (dialog);
+}
+
+static void
+get_text (GtkObject  *button,
+	  gchar     **text)
+{
+  GtkEntry *entry;
+  gchar    *str;
+
+  entry = gtk_object_get_data (button, "entry");
+
+  str = gtk_entry_get_text (entry);
+
+  if (strlen (str) == 0)
+    return;
+
+  *text = g_strdup (str);
+
+  gtk_object_set_data (button, "success", GINT_TO_POINTER (1));
+
+  gtk_main_quit ();
+}
+
+gchar *
+ocfs_query_text (GtkWindow   *parent,
+		 const gchar *prompt,
+		 const gchar *def)
+{
+  GtkWidget *dialog;
+  GtkWidget *table;
+  GtkWidget *entry;
+  GtkWidget *label;
+  GtkWidget *button;
+  gboolean   success;
+  gchar     *str, *text;
+
+  dialog = make_dialog (parent, prompt, FALSE, NULL, get_text, &text, &button);
+
+  table = gtk_widget_new (GTK_TYPE_TABLE,
+			  "n_rows", 1,
+			  "n_columns", 2,
+			  "homogeneous", FALSE,
+			  "row_spacing", 4,
+			  "column_spacing", 4,
+			  "border_width", 4,
+			  "parent", GTK_DIALOG (dialog)->vbox,
+			  NULL);
+
+  entry = gtk_entry_new ();
+  gtk_entry_set_text (GTK_ENTRY (entry), def);
+  gtk_table_attach_defaults (GTK_TABLE (table), entry, 1, 2, 0, 1);
+
+  gtk_object_set_data (GTK_OBJECT (button), "entry",  entry);
+
+  str = g_strconcat (prompt, ":", NULL);
+  label = gtk_widget_new (GTK_TYPE_LABEL,
+			  "label", str,
+			  "xalign", 1.0,
+			  NULL);
+  gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 0, 1);
+
+  success = ocfs_dialog_run (dialog);
+
+  return success ? text : NULL;
+}
+
+static gboolean
+quit_on_delete (void)
+{
+  gtk_main_quit ();
+  return TRUE;
+}
+
+static void
+get_filename (GtkWidget  *button,
+	      gchar     **fname)
+{
+  GtkWidget *fs;
+
+  fs = gtk_widget_get_toplevel (button);
+
+  *fname = g_strdup (gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
+
+  gtk_main_quit ();
+}
+
+gchar *
+ocfs_get_filename (GtkWindow   *parent,
+		   const gchar *title)
+{
+  /* NOTE: not threadsafe */
+  static GtkWidget *fs = NULL;
+  static gchar     *fname = NULL;
+  struct stat       sbuf;
+
+  if (fs == NULL)
+    {
+      fs = gtk_widget_new (GTK_TYPE_FILE_SELECTION,
+			   "modal", TRUE,
+			   "signal::delete-event", quit_on_delete, NULL,
+			   NULL);
+
+      gtk_signal_connect (GTK_OBJECT (fs), "destroy",
+			  GTK_SIGNAL_FUNC (gtk_widget_destroyed), &fs);
+
+      gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (fs)->ok_button),
+			  "clicked", GTK_SIGNAL_FUNC (get_filename), &fname);
+      gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (fs)->cancel_button),
+			  "clicked", GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
+    }
+
+  gtk_window_set_title (GTK_WINDOW (fs), title);
+  gtk_window_set_transient_for (GTK_WINDOW (fs), parent);
+
+  gtk_widget_show (fs);
+
+  gtk_main ();
+
+  gtk_widget_hide (fs);
+
+  if (stat (fname, &sbuf) == 0 &&
+      !ocfs_query_box (parent, "%s exists. Overwrite?", fname))
+    {
+      g_free (fname);
+      return NULL;
+    }
+
+  return fname;
+}
+
+gchar *
+ocfs_get_user_name (uid_t uid)
+{
+  struct passwd *pwd;
+  gchar         *str;
+
+  pwd = getpwuid (uid);
+
+  if (pwd)
+    str = g_strdup (pwd->pw_name);
+  else
+    str = g_strdup_printf ("%d", uid);
+
+  return str;
+}
+
+gchar *
+ocfs_get_group_name (gid_t gid)
+{
+  struct group *grp;
+  gchar        *str;
+
+  grp = getgrgid (gid);
+
+  if (grp)
+    str = g_strdup (grp->gr_name);
+  else
+    str = g_strdup_printf ("%d", gid);
+
+  return str;
+}
+
+/* Replace with G_GUINT64_FORMAT when we can */
+#ifdef __LP64__
+#define FORMAT64 "%lu"
+#else
+#define FORMAT64 "%llu"
+#endif
+
+gchar *
+ocfs_format_bytes (guint64  bytes,
+		   gboolean show_bytes)
+{
+  gfloat  fbytes = bytes;
+  gchar  *suffixes[] = { "K", "MB", "GB", "TB" };
+  gint    i;
+
+  if (bytes == 1)
+    return g_strdup ("1 byte");
+  else if (bytes < 1024)
+    return g_strdup_printf (FORMAT64 " bytes", bytes);
+
+  for (i = -1; i < 3 && fbytes >= 1024; i++)
+    fbytes /= 1024;
+
+  if (show_bytes)
+    return g_strdup_printf ("%.1f %s (" FORMAT64 "b)", fbytes, suffixes[i],
+			    bytes);
+  else
+    return g_strdup_printf ("%.0f %s", fbytes, suffixes[i]);
+}
+
+void
+ocfs_build_list (GtkWidget        *list,
+		 const gchar      *def,
+		 OcfsListIterator  iterator,
+		 gpointer          data)
+{
+  GtkContainer *container = GTK_CONTAINER (list);
+  GtkWidget    *item;
+  gchar        *buf;
+
+  while ((buf = iterator (data)) != NULL)
+    {
+      item = gtk_list_item_new_with_label (buf);
+      gtk_widget_show (item);
+      gtk_container_add (container, item);
+
+      if (strcmp (def, buf) == 0)
+        gtk_list_item_select (GTK_LIST_ITEM (item));
+
+      g_free (buf);
+    }
+}
+
+static void
+octal_insert_filter (GtkEditable *editable,
+		     const gchar *text,
+		     gint         length,
+		     gint        *position)
+{
+  gint i;
+
+  for (i = 0; i < length; i++)
+    if (text[i] < 0x30 || text[i] > 0x37)
+      gtk_signal_emit_stop_by_name (GTK_OBJECT (editable), "insert_text");
+}
+
+GtkWidget *
+ocfs_build_octal_entry (const gchar *def)
+{
+  GtkWidget *entry;
+
+  entry = gtk_widget_new (GTK_TYPE_ENTRY,
+			  "max_length", 4,
+			  "signal::insert_text", octal_insert_filter, NULL,
+			  NULL);
+
+  gtk_entry_set_text (GTK_ENTRY (entry), def);
+
+  return entry;
+}
+
+GtkWidget *
+ocfs_build_combo (void)
+{
+  GtkWidget *combo;
+
+  combo = gtk_combo_new ();
+
+  gtk_editable_set_editable (GTK_EDITABLE (GTK_COMBO (combo)->entry), FALSE);
+
+  return combo;
+}
+
+static gchar *
+uid_iterator (gpointer data)
+{
+  struct passwd *pwd;
+
+  pwd = getpwent ();
+
+  return pwd ? g_strdup (pwd->pw_name) : NULL;
+}
+
+GtkWidget *
+ocfs_build_combo_user (const gchar *def)
+{
+  GtkWidget *combo;
+
+  combo = ocfs_build_combo ();
+
+  setpwent ();
+  ocfs_build_list (GTK_COMBO (combo)->list, def, uid_iterator, NULL);
+  endpwent ();
+
+  return combo;
+}
+
+static gchar *
+gid_iterator (gpointer data)
+{
+  struct group *grp;
+
+  grp = getgrent ();
+
+  return grp ? g_strdup (grp->gr_name) : NULL;
+}   
+
+GtkWidget *
+ocfs_build_combo_group (const gchar *def)
+{
+  GtkWidget *combo;
+
+  combo = ocfs_build_combo ();
+
+  setgrent ();
+  ocfs_build_list (GTK_COMBO (combo)->list, def, gid_iterator, NULL);
+  endgrent ();
+
+  return combo;
+}
+
+GtkCList *
+ocfs_build_clist (gint        columns,
+                  gchar      *titles[],
+		  GtkWidget **scrl_win)
+{
+  GtkCList *clist;
+  gint      i;
+
+  clist = GTK_CLIST (gtk_clist_new_with_titles (columns, titles));
+
+  gtk_clist_set_selection_mode (clist, GTK_SELECTION_BROWSE);
+
+  gtk_clist_column_titles_passive (clist);
+
+  for (i = 0; i < columns; i++)
+    gtk_clist_set_column_auto_resize (clist, i, TRUE);
+
+  gtk_clist_set_auto_sort (clist, TRUE);
+
+  if (scrl_win)
+    {
+      *scrl_win = gtk_widget_new (GTK_TYPE_SCROLLED_WINDOW,
+				  "hscrollbar_policy", GTK_POLICY_AUTOMATIC,
+				  "vscrollbar_policy", GTK_POLICY_AUTOMATIC,
+				  NULL);
+
+      gtk_container_add (GTK_CONTAINER (*scrl_win), GTK_WIDGET (clist));
+    }
+
+  return clist;
+}

Added: trunk/ocfstool/ocfsguiutil.h
===================================================================
--- trunk/ocfstool/ocfsguiutil.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfsguiutil.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,83 @@
+/*
+ * ocfsguiutil.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Manish Singh
+ */
+
+#ifndef __OCFS_GUI_UTIL_H__
+#define __OCFS_GUI_UTIL_H__
+
+
+#include <sys/types.h>
+
+#include <gtk/gtk.h>
+
+
+typedef gchar *(*OcfsListIterator) (gpointer data);
+
+
+GtkWindow *ocfs_widget_get_toplevel (GtkWidget         *widget);
+
+GtkWidget *ocfs_dialog_new          (GtkWindow         *parent,
+				     const gchar       *title,
+				     GtkSignalFunc      callback,
+				     gpointer           callback_data);
+gboolean   ocfs_dialog_run          (GtkWidget         *dialog);
+
+void       ocfs_error_box           (GtkWindow         *parent,
+				     const gchar       *errmsg,
+				     const gchar       *format,
+				     ...) G_GNUC_PRINTF (3, 4);
+gboolean   ocfs_query_box           (GtkWindow         *parent,
+				     const gchar       *format,
+				     ...) G_GNUC_PRINTF (2, 3);
+gchar     *ocfs_query_text          (GtkWindow         *parent,
+				     const gchar       *prompt,
+				     const gchar       *def);
+
+gchar     *ocfs_get_filename        (GtkWindow         *parent,
+				     const gchar       *title);
+
+gchar     *ocfs_get_user_name       (uid_t              uid);
+gchar     *ocfs_get_group_name      (gid_t              gid);
+
+gchar     *ocfs_format_bytes        (guint64            bytes,
+				     gboolean           show_bytes);
+
+void       ocfs_build_list          (GtkWidget         *list,
+				     const gchar       *def,
+				     OcfsListIterator   iterator,
+				     gpointer           data);
+
+GtkWidget *ocfs_build_octal_entry   (const gchar       *def);
+
+GtkWidget *ocfs_build_combo         (void);
+
+GtkWidget *ocfs_build_combo_user    (const gchar       *def);
+GtkWidget *ocfs_build_combo_group   (const gchar       *def);
+
+GtkCList  *ocfs_build_clist         (gint               columns,
+				     gchar             *titles[],
+				     GtkWidget        **scrl_win);
+
+
+#endif /* __OCFS_GUI_UTIL_H__ */

Added: trunk/ocfstool/ocfsmount.c
===================================================================
--- trunk/ocfstool/ocfsmount.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfsmount.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,106 @@
+/*
+ * ocfsmount.c
+ *
+ * The mount and unmount actions
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Manish Singh
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <glib.h>
+
+#include "libdebugocfs.h"
+
+#include "ocfsprocess.h"
+#include "ocfsguiutil.h"
+#include "ocfsmount.h"
+
+
+#ifdef DEVEL_MACHINE
+#define MOUNT_CMD   "ocfsmount"
+#define UNMOUNT_CMD "ocfsumount"
+#else
+#define MOUNT_CMD   "mount"
+#define UNMOUNT_CMD "umount"
+#endif
+
+
+pid_t
+ocfs_mount (GtkWindow *parent,
+	    gchar     *device,
+	    gboolean   query,
+	    gchar     *mountpoint,
+	    gint      *errfd)
+{
+  libocfs_volinfo *info;
+  gchar           *argv[] = { MOUNT_CMD, "-t", "ocfs", device, NULL, NULL };
+  pid_t            pid;
+  gchar           *def = "";
+
+#ifndef DEVEL_MACHINE
+  if (query)
+    {
+      if (libocfs_get_volume_info ((gchar *) device, &info) == 0)
+	def = info->mountpoint;
+      else
+	info = malloc (4);
+
+      mountpoint = ocfs_query_text (parent, "Mountpoint", def);
+
+      if (!mountpoint || mountpoint[0] != '/')
+	{
+	  free (info);
+	  return -ENOTDIR;
+	}
+
+      argv[4] = mountpoint;
+    }
+  else
+    {
+      if (libocfs_get_volume_info ((gchar *) device, &info) != 0)
+	return -EIO;
+
+      argv[4] = info->mountpoint;
+    }
+#else
+  info = malloc (4);
+  argv[4] = "/poop";
+  def = "";
+#endif
+
+  pid = ocfs_process_run (argv[0], argv, NULL, errfd);
+
+  free (info);
+
+  return pid;
+}
+
+pid_t
+ocfs_unmount (gchar *mountpoint,
+	      gint  *errfd)
+{
+  gchar *argv[] = { UNMOUNT_CMD, mountpoint, NULL };
+
+  return ocfs_process_run (argv[0], argv, NULL, errfd);
+}

Added: trunk/ocfstool/ocfsmount.h
===================================================================
--- trunk/ocfstool/ocfsmount.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfsmount.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,42 @@
+/*
+ * ocfsmount.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Manish Singh
+ */
+
+#ifndef __OCFS_MOUNT_H__
+#define __OCFS_MOUNT_H__
+
+
+#include <sys/types.h>
+
+
+pid_t ocfs_mount   (GtkWindow *parent,
+		    gchar     *device,
+		    gboolean   query, 
+		    gchar     *mountpoint,
+		    gint      *errfd);
+pid_t ocfs_unmount (gchar     *mountpoint,
+		    gint      *errfd);
+
+
+#endif /* __OCFS_MOUNT_H__ */

Added: trunk/ocfstool/ocfsnodemap.c
===================================================================
--- trunk/ocfstool/ocfsnodemap.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfsnodemap.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,89 @@
+/*
+ * ocfsnodemap.c
+ *
+ * The node map display tab
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Manish Singh
+ */
+
+#include <string.h>
+
+#include <gtk/gtk.h>
+
+#include "libdebugocfs.h"
+
+#include "ocfsguiutil.h"
+#include "ocfsnodemap.h"
+
+
+gboolean
+ocfs_nodemap_list (GtkCList    *clist,
+		   const gchar *device,
+		   guint        bitmap)
+{
+  GArray *nodes;
+  gchar  *texts[4], buf[6];
+  gint    i;
+
+  gtk_clist_freeze (clist);
+  gtk_clist_clear (clist);
+
+  if (!device || libocfs_get_node_map (device, &nodes))
+    return FALSE;
+
+#define INODE(i) (g_array_index (nodes, libocfs_node, (i)))
+
+  for (i = 0; i < nodes->len; i++)
+    {
+      if (bitmap & (1 << i))
+	{
+	  g_snprintf (buf, sizeof (buf), "%d", INODE(i).slot);
+	  texts[0] = buf;
+
+	  texts[1] = INODE(i).name;
+	  texts[2] = INODE(i).addr;
+	  texts[3] = INODE(i).guid;
+
+	  gtk_clist_append (clist, texts);
+	}
+    }
+
+  gtk_clist_thaw (clist);
+
+  g_array_free (nodes, TRUE);
+
+  return TRUE;
+}
+
+GtkWidget *
+ocfs_nodemap (const gchar *device,
+	      gboolean     advanced)
+{
+  GtkCList     *clist;
+  GtkWidget    *scrl_win;
+  static gchar *titles[4] = { "Slot #", "Node Name", "IP Address", "GUID" };
+
+  clist = ocfs_build_clist (advanced ? 4 : 3, titles, &scrl_win);
+
+  if (ocfs_nodemap_list (clist, device, 0xffffffff))
+    return scrl_win;
+  else
+    return gtk_label_new ("Invalid device");
+}

Added: trunk/ocfstool/ocfsnodemap.h
===================================================================
--- trunk/ocfstool/ocfsnodemap.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfsnodemap.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,38 @@
+/*
+ * ocfsnodemap.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Manish Singh
+ */
+
+#ifndef __OCFS_NODEMAP_H__
+#define __OCFS_NODEMAP_H__
+
+
+gboolean   ocfs_nodemap_list (GtkCList    *clist,
+			      const gchar *device,
+			      guint        bitmap);
+
+GtkWidget *ocfs_nodemap      (const gchar *device,
+			      gboolean     advanced);
+
+
+#endif /* __OCFS_NODEMAP_H__ */

Added: trunk/ocfstool/ocfsplist.c
===================================================================
--- trunk/ocfstool/ocfsplist.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfsplist.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,327 @@
+/*
+ * ocfsplist.c
+ *
+ * Create a list of valid partitions
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Manish Singh
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <glib.h>
+
+#include "libdebugocfs.h"
+
+#include "ocfsplist.h"
+
+
+typedef struct _BuildData BuildData;
+
+struct _BuildData
+{
+  gboolean  unmounted;
+  GList    *list;
+};
+
+
+static gboolean valid_device        (const gchar *device,
+				     gboolean     no_ocfs_check);
+static void     partition_info_fill (GHashTable  *info);
+static gboolean list_builder        (gpointer     key,
+				     gpointer     value,
+				     gpointer     user_data);
+
+
+gboolean
+valid_device (const gchar *device,
+	      gboolean     no_ocfs_check)
+{
+  gboolean     is_bad = FALSE;
+  struct stat  sbuf;
+  FILE        *f;
+  gchar        buf[100], *proc, *d;
+  gint         i, fd;
+
+  if ((stat (device, &sbuf) != 0) ||
+      (!S_ISBLK (sbuf.st_mode)) ||
+      ((sbuf.st_mode & 0222) == 0))
+    return FALSE;
+
+  if (strncmp ("/dev/hd", device, 7) == 0)
+    {
+      i = strlen (device) - 1;
+      while (i > 5 && isdigit (device[i]))
+	i--;
+
+      d =  g_strndup (device + 5, i + 1);
+      proc = g_strconcat ("/proc/ide/", d, "/media", NULL);
+      g_free (d);
+
+      f = fopen (proc, "r");
+      g_free (proc);
+
+      if (f != NULL && fgets (buf, sizeof (buf), f))
+	is_bad = ((strncmp (buf, "cdrom", 5) == 0) ||
+		  (strncmp (buf, "tape",  4) == 0));
+
+      if (f)
+	fclose (f);
+     
+      if (is_bad)
+	return FALSE; 
+    }
+
+#ifndef DEVEL_MACHINE
+  fd = open (device, O_RDWR);
+  if (fd == -1)
+    return FALSE;
+  close (fd);
+
+  return no_ocfs_check ? TRUE : libocfs_is_ocfs_partition ((gchar *) device);
+#else
+  fd = 0;
+  return TRUE;
+#endif
+}
+
+static void
+partition_info_fill (GHashTable *info)
+{
+  FILE   *proc;
+  gchar   line[100], name[100], *device;
+  GSList *list;
+  gint    i;
+  gchar  *p;
+
+  proc = fopen ("/proc/partitions", "r");
+  if (proc == NULL)
+    return;
+
+  while (fgets (line, sizeof(line), proc) != NULL)
+    {
+      if (sscanf(line, "%*d %*d %*d %99[^ \t\n]", name) != 1)
+	continue;
+
+      device = g_strconcat ("/dev/", name, NULL);
+
+      i = strlen (device) - 1;
+      if (isdigit (device[i]))
+	{
+	  while (i > 0 && isdigit (device[i]))
+	    i--;
+
+	  p = g_strndup (device, i + 1);
+	  list = g_hash_table_lookup (info, p);
+
+	  if (list == NULL)
+	    {
+	      list = g_slist_prepend (NULL, device);
+	      g_hash_table_insert (info, p, list);
+	    }
+	  else
+	    {
+	      if (strcmp (p, list->data) == 0)
+		{
+		  g_free (list->data);
+		  list->data = device;
+		}
+	      else
+		g_slist_append (list, device);
+
+	      g_free (p);
+	    }
+	}
+      else if (!g_hash_table_lookup (info, device))
+	{
+	  list = g_slist_prepend (NULL, g_strdup (device));
+	  g_hash_table_insert (info, device, list);
+	}
+      else
+	g_free (device);
+    }
+
+  fclose (proc);
+}
+
+gchar *
+ocfs_get_mountpoint (const gchar *device)
+{
+  FILE  *proc;
+  gint   len;
+  gchar  buf[4096], *str, *p, *q;
+  gchar *mountpoint = NULL;
+
+  proc = fopen ("/proc/mounts", "r");
+  if (proc == NULL)
+    return NULL;
+
+  len = strlen (device);
+
+  while (fgets (buf, 4096, proc) != NULL)
+    {
+      str = g_new (gchar, len + 2);
+      strcpy (str, device);
+      str[len] = ' ';
+      str[len + 1] = '\0';
+
+      if (strncmp (buf, str, len + 1) == 0)
+	{
+	  p = buf + len + 1;
+	  while (*p == ' ' || *p == '\t')
+	    p++;
+
+	  q = p;
+
+	  while (*q != '\0' && *q != '\n' && *q != '\r' &&
+		 *q != ' '  && *q != '\t')
+	    q++;
+
+	  *q = '\0';
+
+	  mountpoint = g_strdup (p);
+	  break;
+	}
+
+      g_free (str);
+    }
+
+  fclose (proc);
+
+  return mountpoint;
+}
+
+static gboolean
+list_builder (gpointer key,
+	      gpointer value,
+	      gpointer user_data)
+{
+  BuildData         *bdata;
+  GSList            *list, *last;
+  gchar             *device;
+  OcfsPartitionInfo *info;
+
+  bdata = user_data;
+  list = value;
+
+  while (list)
+    {
+      device = list->data;
+
+      if (valid_device (device, bdata->unmounted))
+	{
+	  info = g_new (OcfsPartitionInfo, 1);
+
+	  info->device = g_strdup (device);
+	  info->mountpoint = ocfs_get_mountpoint (device);
+
+	  if (bdata->unmounted)
+	    {
+	      if (info->mountpoint == NULL)
+		bdata->list = g_list_prepend (bdata->list, info->device);
+
+	      g_free (info);
+	    }
+	  else
+	    bdata->list = g_list_prepend (bdata->list, info);
+	}
+
+      last = list;
+      list = list->next;
+
+      g_free (device);
+      g_slist_free_1 (last);
+    }
+
+  g_free (key);
+
+  return TRUE;
+}
+
+#ifdef LIST_TEST
+static void
+print_hash (gpointer key,
+	    gpointer value,
+	    gpointer user_data)
+{
+  GSList *list;
+
+  g_print ("Key: %s; Values:", (gchar *) key);
+  for (list = value; list != NULL; list = list->next)
+    g_print (" %s", (gchar *) list->data);
+  g_print ("\n");
+}
+#endif
+
+GList *
+ocfs_partition_list (gboolean unmounted)
+{
+  GHashTable *info;
+  BuildData   bdata = { unmounted, NULL };
+
+  info = g_hash_table_new (g_str_hash, g_str_equal);
+
+  partition_info_fill (info);
+
+#ifdef LIST_TEST
+  g_hash_table_foreach (info, print_hash, NULL);
+#endif
+
+  g_hash_table_foreach_remove (info, list_builder, &bdata);
+  
+  g_hash_table_destroy (info);
+
+  return bdata.list;
+}
+
+#ifdef LIST_TEST
+int
+main (int    argc,
+      char **argv)
+{
+  GList             *plist, *list;
+  OcfsPartitionInfo *info;
+
+  g_print ("All:\n");
+
+  plist = ocfs_partition_list (FALSE);
+  
+  for (list = plist; list; list = list->next)
+    {
+      info = list->data;
+      g_print ("Device: %s; Mountpoint %s\n", info->device, info->mountpoint);
+    }
+
+  g_print ("Unmounted:\n");
+
+  plist = ocfs_partition_list (TRUE);
+  
+  for (list = plist; list; list = list->next)
+    g_print ("Device: %s\n", (gchar *) list->data);
+
+  return 0;
+}
+#endif

Added: trunk/ocfstool/ocfsplist.h
===================================================================
--- trunk/ocfstool/ocfsplist.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfsplist.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,46 @@
+/*
+ * ocfsplist.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Manish Singh
+ */
+
+#ifndef __OCFS_PARTITION_LIST_H__
+#define __OCFS_PARTITION_LIST_H__
+
+#include <glib.h>
+
+
+typedef struct _OcfsPartitionInfo OcfsPartitionInfo;
+
+struct _OcfsPartitionInfo
+{
+  gchar *device;
+  gchar *mountpoint;
+};
+
+
+GList *ocfs_partition_list (gboolean     unmounted);
+
+gchar *ocfs_get_mountpoint (const gchar *device);
+
+
+#endif /* __OCFS_PARTITION_LIST_H__ */

Added: trunk/ocfstool/ocfsprocess.c
===================================================================
--- trunk/ocfstool/ocfsprocess.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfsprocess.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,590 @@
+/*
+ * ocfsprocess.c
+ *
+ * Misc process control helpers
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Manish Singh
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include <gtk/gtk.h>
+
+#include "ocfsguiutil.h"
+#include "ocfsprocess.h"
+
+
+#define INTERVAL 100
+#define TIMEOUT  10000
+
+typedef void (*OutputFunc) (const gchar *buf,
+			    gpointer     data);
+
+typedef struct _ProcInfo      ProcInfo;
+typedef struct _KillInfo      KillInfo;
+typedef struct _OutputClosure OutputClosure;
+
+struct _ProcInfo
+{
+  gboolean     success;
+
+  gboolean     killed;
+  gboolean     cancel;
+
+  pid_t        pid;
+
+  gboolean     spin;
+
+  gint         count;
+  guint        threshold;
+
+  const gchar *title;
+  const gchar *desc;
+
+  GtkWidget   *dialog;
+  GtkWidget   *pbar;
+
+  GtkWindow   *parent;
+};
+
+struct _KillInfo
+{
+  pid_t    pid;
+  gboolean sent_kill;
+};
+
+struct _OutputClosure
+{
+  OutputFunc func;
+  gpointer   data;
+};
+
+
+static gboolean  proc_timeout        (ProcInfo       *pinfo);
+static void      proc_kill           (ProcInfo       *pinfo);
+static gboolean  kill_timeout        (KillInfo       *kinfo);
+static void      make_progress_box   (ProcInfo       *pinfo);
+static gboolean  out_read            (GIOChannel     *channel,
+				      GIOCondition    cond,
+				      OutputClosure  *output);
+static void      build_msg           (const gchar    *buf,
+				      GString        *str);
+static void      update_pbar         (const gchar    *buf,
+				      GtkWidget      *pbar);
+
+
+pid_t
+ocfs_process_run (gchar  *progname,
+		  gchar **argv,
+		  gint   *outfd,
+		  gint   *errfd)
+{
+  gint  rc, sleep_count = 0;
+  pid_t pid;
+  gint  out_pipe[2], err_pipe[2];
+
+#ifdef DEBUG_PROCESS
+  {
+    gchar **arg = argv;
+
+    while (*arg)
+      {
+        g_print ("%s ", *arg);
+        arg++;
+      }
+
+    g_print ("\n");
+  }
+#endif
+
+  rc = pipe (out_pipe);
+  if (rc == -1)
+    return -errno;
+
+  rc = pipe (err_pipe);
+  if (rc == -1)
+    {
+      rc = -errno;
+      close (out_pipe[0]);
+      close (out_pipe[1]);
+      return rc;
+    }
+
+  while ((pid = fork ()) == -1)
+    {
+      sleep_count++;
+
+      if (sleep_count > 4)
+	{
+	  rc = -errno;
+	  close (out_pipe[0]);
+	  close (out_pipe[1]);
+	  return rc;
+	}
+
+      sleep (2);
+    }
+
+  if (pid == 0)
+    {
+      close (out_pipe[0]);
+      close (err_pipe[0]);
+
+      if (outfd)
+	{
+	  if (out_pipe[1] != STDOUT_FILENO)
+	    {
+	      rc = dup2 (out_pipe[1], STDOUT_FILENO);
+
+	      if (rc == -1)
+		_exit (-errno);
+
+	      close (out_pipe[1]);
+	    }
+	}
+      else
+	close (out_pipe[1]);
+
+      if (errfd)
+	{
+	  if (err_pipe[1] != STDERR_FILENO)
+	    {
+	      rc = dup2 (err_pipe[1], STDERR_FILENO);
+
+	      if (rc == -1)
+		_exit (-errno);
+
+	      close (err_pipe[1]);
+	    }
+	}
+      else
+	close (err_pipe[1]);
+
+#ifdef DEVEL_MACHINE
+      putenv ("PATH=/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games:.");
+#endif
+
+      execvp (progname, argv);
+      rc = -errno;
+      fprintf (stderr, "Could not run \"%s\", %s\n", progname,
+	       g_strerror (errno));
+      _exit (rc);
+    }
+
+  close (out_pipe[1]);
+  close (err_pipe[1]);
+
+  if (outfd)
+    *outfd = out_pipe[0];
+  else
+    close (out_pipe[0]);
+
+  if (errfd)
+    *errfd = err_pipe[0];
+  else
+    close (err_pipe[0]);
+  
+  return pid;
+}
+
+gboolean
+ocfs_process_reap (GtkWindow    *parent,
+		   pid_t         pid,
+		   gboolean      spin,
+		   gboolean      spin_wait,
+		   const gchar  *title,
+		   const gchar  *desc,
+		   gint          outfd,
+		   gchar       **outmsg,
+		   gint          errfd,
+		   gchar       **errmsg,
+		   gboolean     *killed)
+{
+  ProcInfo       pinfo;
+  OutputClosure  err_closure, out_closure;
+  GIOChannel    *err = NULL, *out = NULL;
+  gint           timeout_id, err_id = 0, out_id = 0;
+  gboolean       do_out = FALSE;
+
+  if (pid < 0)
+    {
+      *errmsg = g_strdup (g_strerror (-pid));
+      return FALSE;
+    }
+
+  pinfo.pid = pid;
+
+  pinfo.killed = FALSE;
+
+  pinfo.spin = spin;
+
+  pinfo.count = TIMEOUT / INTERVAL;
+  pinfo.threshold = pinfo.count - INTERVAL * 10;
+
+  pinfo.title = title;
+  pinfo.desc = desc;
+
+  pinfo.parent = parent;
+
+  if (spin)
+    {
+      pinfo.cancel = FALSE;
+
+      if (!spin_wait)
+	{
+	  pinfo.count = TIMEOUT * 60;
+	  make_progress_box (&pinfo);
+	}
+      else
+	pinfo.dialog = NULL;
+    }
+  else
+    {
+      pinfo.cancel = TRUE;
+      make_progress_box (&pinfo);
+    }
+
+  timeout_id = g_timeout_add (INTERVAL, (GSourceFunc) proc_timeout, &pinfo);
+
+  if (errmsg)
+    {
+      err_closure.func = (OutputFunc) build_msg;
+      err_closure.data = g_string_new ("");
+
+      err = g_io_channel_unix_new (errfd);
+      err_id = g_io_add_watch (err, G_IO_IN, (GIOFunc) out_read, &err_closure);
+    }
+
+  if (outmsg)
+    {
+      out_closure.func = (OutputFunc) build_msg;
+      out_closure.data = g_string_new ("");
+
+      do_out = TRUE;
+    }
+  else if (!spin)
+    {
+      out_closure.func = (OutputFunc) update_pbar;
+      out_closure.data = pinfo.pbar;
+
+      do_out = TRUE;
+    }
+
+  if (do_out)
+    {
+      out = g_io_channel_unix_new (outfd);
+      out_id = g_io_add_watch (out, G_IO_IN, (GIOFunc) out_read, &out_closure);
+    }
+
+  gtk_main ();
+
+  if (pinfo.dialog)
+    gtk_widget_destroy (pinfo.dialog);
+
+  g_source_remove (timeout_id);
+
+  if (errmsg)
+    {
+      GString *errstr = err_closure.data;
+
+      g_source_remove (err_id);
+
+      g_io_channel_close (err);
+      g_io_channel_unref (err);
+
+      if (!pinfo.success)
+	{
+	  if (pinfo.killed)
+	    {
+	      if (errstr->len)
+		g_string_append (errstr, "\n");
+
+	      g_string_append (errstr, "Killed prematurely.");
+	    }
+
+	  *errmsg = errstr->str;
+	}
+
+      g_string_free (errstr, pinfo.success);
+    }
+
+  if (do_out)
+    {
+      g_source_remove (out_id);
+
+      g_io_channel_close (out);
+      g_io_channel_unref (out);
+
+      if (outmsg)
+	{
+	  GString *outstr = out_closure.data;
+
+	  *outmsg = outstr->str;
+
+	  g_string_free (outstr, FALSE);
+	}
+    }
+
+  if (killed)
+    *killed = pinfo.killed;
+
+  return pinfo.success;
+}
+
+gchar **
+ocfs_shell_output (GtkWindow *parent,
+		   gchar     *command)
+{
+  gchar    **ret;
+  pid_t      pid;
+  gint       outfd, errfd;
+  gboolean   success;
+  gchar     *outmsg, *errmsg;
+  gchar     *argv[] = {
+    "/bin/sh", "-c",
+    NULL,
+    NULL
+  };
+
+  argv[2] = command; 
+
+  pid = ocfs_process_run (argv[0], argv, &outfd, &errfd);
+
+  success = ocfs_process_reap (parent, pid, TRUE, TRUE,
+			       "Shell Comand", "Shell Command",
+			       outfd, &outmsg, errfd, &errmsg,
+			       NULL);
+
+  ret = success ? g_strsplit (outmsg, "\n", 0) : NULL;
+
+  g_free (outmsg);
+
+  if (!success)
+    g_free (errmsg);
+
+  return ret;
+}
+
+static gboolean
+proc_timeout (ProcInfo *pinfo)
+{
+  pid_t  pid;
+  gint   status;
+
+  if (pinfo->spin)
+    pinfo->count--;
+
+  pid = waitpid (pinfo->pid, &status, WNOHANG);
+
+  if (pid == -1)
+    {
+      pinfo->success = FALSE;
+      gtk_main_quit ();
+      return FALSE;
+    }
+  else if (pid == pinfo->pid)
+    {
+      pinfo->success = (WIFEXITED (status) && WEXITSTATUS (status) == 0);
+      gtk_main_quit ();
+      return FALSE;
+    }
+
+  if (!pinfo->spin)
+    return TRUE;
+
+  if (pinfo->count < 1)
+    {
+      proc_kill (pinfo);
+      return FALSE;
+    }
+
+  if (pinfo->count < pinfo->threshold && pinfo->dialog == NULL)
+    make_progress_box (pinfo);
+
+  if (pinfo->dialog)
+    {
+      GtkAdjustment *adj;
+      gfloat         value;
+
+      adj = GTK_PROGRESS (pinfo->pbar)->adjustment;
+
+      value = adj->value + 1;
+      if (value > adj->upper)
+	value = adj->lower;
+
+      gtk_progress_set_value (GTK_PROGRESS (pinfo->pbar), value);
+    }
+
+  return TRUE;
+}
+
+static void
+proc_kill (ProcInfo *pinfo)
+{
+  KillInfo *kinfo;
+
+  pinfo->success = FALSE;
+  pinfo->killed = TRUE;
+
+  kinfo = g_new0 (KillInfo, 1);
+  kinfo->pid = pinfo->pid;
+
+  kill (kinfo->pid, 15);
+  g_timeout_add (INTERVAL * 5, (GSourceFunc) kill_timeout, kinfo);
+
+  gtk_main_quit ();
+}
+
+static gboolean
+kill_timeout (KillInfo *kinfo)
+{
+  if (!kinfo->sent_kill && waitpid (kinfo->pid, NULL, WNOHANG) == 0)
+    {
+      kill (kinfo->pid, 9);
+      kinfo->sent_kill = TRUE;
+
+      return TRUE;
+    }
+
+  g_free (kinfo);
+
+  return FALSE;
+}
+
+static void
+make_progress_box (ProcInfo *pinfo)
+{
+  GtkWidget *dialog;
+  GtkWidget *action_area;
+  GtkWidget *hbbox;
+  GtkWidget *vbox;
+  GtkWidget *label;
+  gchar     *str;
+
+  dialog = gtk_widget_new (pinfo->cancel ? GTK_TYPE_DIALOG : GTK_TYPE_WINDOW,
+			   "title", pinfo->title,
+			   "allow_grow", FALSE,
+			   "modal", TRUE,
+			   "signal::delete-event", gtk_true, NULL,
+			   NULL);
+  gtk_window_set_transient_for (GTK_WINDOW (dialog), pinfo->parent);
+
+  if (pinfo->cancel)
+    {
+      vbox = GTK_DIALOG (dialog)->vbox;
+
+      action_area = GTK_DIALOG (dialog)->action_area;
+      gtk_widget_set (action_area,
+		      "border_width", 2,
+		      "homogeneous", FALSE,
+		      NULL);
+
+      hbbox = gtk_hbutton_box_new ();
+      gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbbox), 4);
+      gtk_box_pack_end (GTK_BOX (action_area), hbbox, FALSE, FALSE, 0);
+
+      gtk_widget_new (GTK_TYPE_BUTTON,
+		      "label", "Cancel",
+		      "parent", hbbox,
+		      "can_default", TRUE,
+		      "has_default", TRUE,
+		      "signal::clicked", proc_kill, pinfo,
+		      NULL);
+    }
+  else
+    vbox = gtk_widget_new (GTK_TYPE_VBOX,
+			   "spacing", 0,
+			   "homogeneous", FALSE,
+			   "border_width", 4,
+			   "parent", dialog,
+			   NULL);
+
+  pinfo->dialog = dialog;
+
+  str = g_strconcat (pinfo->desc, "...", NULL);
+  label = gtk_label_new (str);
+  g_free (str);
+
+  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+
+  pinfo->pbar = gtk_progress_bar_new ();
+  gtk_box_pack_start (GTK_BOX (vbox), pinfo->pbar, FALSE, FALSE, 0);
+
+  if (pinfo->spin)
+    gtk_progress_set_activity_mode (GTK_PROGRESS (pinfo->pbar), TRUE);
+  else
+    gtk_progress_set_show_text (GTK_PROGRESS (pinfo->pbar), TRUE);
+
+  gtk_widget_realize (dialog);
+  gdk_window_set_decorations (dialog->window, GDK_DECOR_BORDER);
+
+  gtk_widget_show_all (dialog);
+}
+
+gboolean
+out_read (GIOChannel    *channel,
+	  GIOCondition   cond,
+	  OutputClosure *output)
+{
+  gint     count = 0;
+  GIOError error;
+  gchar    buf[256];
+
+  error = g_io_channel_read (channel, buf, sizeof (buf) - 1, &count);
+
+  if (error == G_IO_ERROR_NONE)
+    {
+      buf[count] = '\0';
+      output->func (buf, output->data);
+      return TRUE;
+    }
+  else if (error == G_IO_ERROR_AGAIN)
+    return TRUE;
+
+  return FALSE;
+}
+
+static void
+build_msg (const gchar *buf,
+	   GString     *str)
+{
+  g_string_append (str, buf);
+}
+
+static void
+update_pbar (const gchar *buf,
+	     GtkWidget   *pbar)
+{
+  gfloat value;
+
+  if (strncmp (buf, "COMPLETE", 8) == 0)
+    value = 100.0;
+  else
+    value = (gfloat) atoi (buf);
+
+  gtk_progress_set_value (GTK_PROGRESS (pbar), value);
+}

Added: trunk/ocfstool/ocfsprocess.h
===================================================================
--- trunk/ocfstool/ocfsprocess.h	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfsprocess.h	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,54 @@
+/*
+ * ocfsprocess.h
+ *
+ * Function prototypes for related 'C' file.
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Manish Singh
+ */
+
+#ifndef __OCFS_PROCESS_H__
+#define __OCFS_PROCESS_H__
+
+
+#include <sys/types.h>
+
+#include <gtk/gtk.h>
+
+
+pid_t      ocfs_process_run  (gchar        *progname,
+			      gchar       **argv,
+			      gint         *outfd,
+			      gint         *errfd);
+gboolean   ocfs_process_reap (GtkWindow    *parent,
+			      pid_t         pid,
+			      gboolean      spin,
+			      gboolean      spin_wait,
+			      const gchar  *title,
+			      const gchar  *desc,
+			      gint          outfd,
+			      gchar       **outmsg,
+			      gint          errfd,
+			      gchar       **errmsg,
+			      gboolean     *killed);
+gchar    **ocfs_shell_output (GtkWindow    *parent,
+			      gchar        *command);
+
+
+#endif /* __OCFS_PROCESS_H__ */

Added: trunk/ocfstool/ocfstool.1.in
===================================================================
--- trunk/ocfstool/ocfstool.1.in	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfstool.1.in	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,24 @@
+.TH OCFSTOOL 1 "August 2002" "Version @VERSION@" "OCFS Manual Pages"
+.SH NAME
+ocfstool - GUI frontend for OCFS management and debugging
+.SH SYNOPSIS
+.B ocfstool
+
+.SH DESCRIPTION
+.PP
+\fBocfstool\fP is a GUI frontend for managing and debugging OCFS volumes on
+the system. One can mount and unmount volumes, format, view overview
+information and individual files, see the current node map, and block
+bitmap.
+
+.SH BUGS
+Stuff.
+
+.SH SEE ALSO
+.BR ocfs(5)
+
+.SH AUTHORS
+Oracle Corporation
+
+.SH COPYRIGHT
+Copyright \(co 2002 Oracle Corporation

Added: trunk/ocfstool/ocfstool.c
===================================================================
--- trunk/ocfstool/ocfstool.c	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/ocfstool/ocfstool.c	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,717 @@
+/*
+ * ocfstool.c
+ *
+ * The main gui
+ *
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * 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 recieved 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 021110-1307, USA.
+ *
+ * Author: Manish Singh
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <gtk/gtk.h>
+
+#include "ocfsprocess.h"
+#include "ocfsguiutil.h"
+#include "ocfsplist.h"
+#include "ocfsmount.h"
+#include "ocfsformat.h"
+#include "ocfsgenconfig.h"
+#include "ocfsgeneral.h"
+#include "ocfsbrowser.h"
+#include "ocfsnodemap.h"
+#include "ocfsbitmap.h"
+#include "ocfsfreespace.h"
+
+
+typedef GtkWidget *(*TabFunc) (const gchar *device,
+			       gboolean     advanced);
+
+
+static void       cleanup                (void);
+static void       usage                  (char          *prgname);
+static void       about                  (GtkCList      *clist);
+static void       level                  (GtkCList      *clist,
+					  guint          advanced);
+static void       select_device          (GtkCList      *clist,
+					  const gchar   *device);
+static void       refresh_partition_list (GtkCList      *clist);
+static gint       list_compare           (GtkCList      *clist,
+					  gconstpointer  p1,
+					  gconstpointer  p2);
+static void       update_tab             (GtkObject     *clist,
+					  const gchar   *tag,
+					  TabFunc        func,
+					  const gchar   *device);
+static void       update_notebook        (GtkObject     *clist,
+					  const gchar   *device);
+static void       list_select            (GtkCList      *clist,
+					  gint           row,
+					  gint           column,
+					  GdkEvent      *event);
+static GtkWidget *create_partition_list  (void);
+static void       mount                  (GtkWidget     *button,
+					  GtkCList      *clist);
+static void       unmount                (GtkWidget     *button,
+					  GtkCList      *clist);
+static void       disk_op                (GtkCList      *clist,
+					  guint          action);
+static void       genconfig              (GtkCList      *clist);
+static void       refresh                (GtkCList      *clist);
+static GtkWidget *create_action_area     (GtkCList      *clist);
+static void       tab_frame              (const gchar   *tag,
+					  const gchar   *desc,
+					  GtkWidget     *notebook, 
+					  GtkWidget     *clist,
+					  TabFunc        func);
+static void       create_window          (void);
+
+
+static void
+cleanup (void)
+{
+  exit (0);
+}
+
+static void
+usage (char *prgname)
+{
+  g_print ("Usage: %s [OPTION]...\n\n", prgname);
+  g_print ("Options:\n");
+  g_print ("  -V, --version  print version information and exit\n");
+  g_print ("      --help     display this help and exit\n");
+}
+
+static void
+about (GtkCList *clist)
+{
+  GtkWidget *dialog;
+
+  dialog = ocfs_dialog_new (ocfs_widget_get_toplevel (GTK_WIDGET (clist)),
+			    "About", NULL, NULL);
+
+
+  gtk_widget_new (GTK_TYPE_LABEL,
+		  "label", "Oracle Cluster Filesytem Tool\n"
+			   "Version " OCFSTOOL_VERSION "\n\n"
+			   "Copyright (C) Oracle Corporation 2002\n"
+			   "All Rights Reserved",
+		  "parent", GTK_DIALOG (dialog)->vbox,
+		  NULL);
+
+  ocfs_dialog_run (dialog);
+}
+
+static void
+level (GtkCList *clist,
+       guint     advanced)
+{
+  guint      old;
+  gint       row;
+  gchar     *device;
+  GtkWidget *item;
+
+  old = GPOINTER_TO_UINT (gtk_object_get_data (GTK_OBJECT (clist), "advanced"));
+
+  if (old == advanced)
+    return;
+
+  gtk_object_set_data (GTK_OBJECT (clist), "advanced",
+		       GUINT_TO_POINTER (advanced));
+
+  if (clist->selection)
+    {
+      row = GPOINTER_TO_INT (clist->selection->data);
+
+#ifdef DEVEL_MACHINE
+      device = "test.dump";
+#else
+      gtk_clist_get_text (clist, row, 0, &device);
+#endif  
+    }
+  else
+    device = NULL;
+
+  item = gtk_object_get_data (GTK_OBJECT (clist), "resize_item");
+
+  if (advanced)
+    gtk_widget_show (item);
+  else
+    gtk_widget_hide (item);
+    
+  update_notebook (GTK_OBJECT (clist), device);
+}
+
+static void
+select_device (GtkCList    *clist,
+	       const gchar *device)
+{
+  GList       *list;
+  GtkCListRow *row;
+  gint         i;
+
+  for (list = clist->row_list, i = 0; list; list = list->next, i++)
+    {
+      row = list->data;
+
+      if (strcmp (device, GTK_CELL_TEXT (row->cell[0])->text) == 0)
+	{
+	  gtk_clist_select_row (clist, i, 0);
+
+	  if (!gtk_clist_row_is_visible (clist, i))
+	    gtk_clist_moveto (clist, i, -1, 0.5, 0.0);
+	}
+    }
+}
+
+static void
+refresh_partition_list (GtkCList *clist)
+{
+  GList             *list, *last;
+  OcfsPartitionInfo *info;
+  gchar             *texts[2], *device = NULL;
+  gint               row;
+
+  if (clist->selection)
+    {
+      row = GPOINTER_TO_INT (clist->selection->data);
+
+      gtk_clist_get_text (clist, row, 0, &device);
+      device = g_strdup (device);
+    }
+
+  gtk_clist_freeze (clist);
+
+  gtk_clist_clear (clist);
+
+  list = ocfs_partition_list (FALSE);
+
+#ifndef DEVEL_MACHINE
+  while (list)
+    {
+      last = list;
+      list = list->next;
+
+      info = last->data;
+
+      texts[0] = info->device;
+      texts[1] = info->mountpoint ? info->mountpoint : "";
+
+      gtk_clist_append (clist, texts);
+
+      g_free (info->device);
+      g_free (info->mountpoint);
+
+      g_list_free_1 (last);
+    }
+#else
+  last = list;
+  info = NULL;
+
+  texts[0] = "/dev/hda1"; 
+  texts[1] = "/"; 
+  gtk_clist_append (clist, texts);
+
+  texts[0] = "/dev/hda2"; 
+  texts[1] = ""; 
+  gtk_clist_append (clist, texts);
+#endif
+
+  if (device)
+    select_device (clist, device);
+
+  gtk_clist_thaw (clist);
+}
+
+static gint
+list_compare (GtkCList      *clist,
+	      gconstpointer  p1,
+	      gconstpointer  p2)
+{
+  gchar       *d1, *d2;
+  gchar       *m1, *m2;
+
+  GtkCListRow *row1 = (GtkCListRow *) p1;
+  GtkCListRow *row2 = (GtkCListRow *) p2;
+
+  d1 = GTK_CELL_TEXT (row1->cell[0])->text;
+  d2 = GTK_CELL_TEXT (row2->cell[0])->text;
+
+  m1 = GTK_CELL_TEXT (row1->cell[1])->text;
+  m2 = GTK_CELL_TEXT (row2->cell[1])->text;
+
+  if (m1 && !m2)
+    return -1;
+  else if (!m1 && m2)
+    return 1;
+  else
+    return strcmp (d1, d2);
+}
+
+static void
+update_tab (GtkObject   *clist,
+	    const gchar *tag,
+	    TabFunc      func,
+	    const gchar *device)
+{
+  gboolean   advanced;
+  gchar     *str;
+  GtkWidget *container;
+  GtkWidget *info;
+
+  advanced = gtk_object_get_data (clist, "advanced") != NULL;
+
+  str = g_strconcat (tag, "-frame", NULL);
+  container = gtk_object_get_data (clist, str);
+  g_free (str);
+
+  gtk_widget_destroy (GTK_BIN (container)->child);
+
+  info = func (device, advanced);
+  gtk_container_add (GTK_CONTAINER (container), info);
+  gtk_widget_show_all (info);
+}
+
+static void
+update_notebook (GtkObject   *clist,
+		 const gchar *device)
+{
+  update_tab (clist, "general",   ocfs_general,   device);
+  update_tab (clist, "browser",   ocfs_browser,   device);
+  update_tab (clist, "nodemap",   ocfs_nodemap,   device);
+  update_tab (clist, "bitmap",    ocfs_bitmap,    device);
+  update_tab (clist, "freespace", ocfs_freespace, device);
+}
+
+static void
+list_select (GtkCList *clist,
+	     gint      row,
+	     gint      column,
+	     GdkEvent *event)
+{
+  gchar     *device, *mountpoint;
+  GtkWidget *button;
+
+  gtk_clist_get_text (clist, row, 0, &device);
+  gtk_clist_get_text (clist, row, 1, &mountpoint);
+
+  if (mountpoint && mountpoint[0] != '\0')
+    {
+      button = gtk_object_get_data (GTK_OBJECT (clist), "mount-button");
+      gtk_widget_set_sensitive (button, FALSE);
+
+      button = gtk_object_get_data (GTK_OBJECT (clist), "unmount-button");
+      gtk_widget_set_sensitive (button, TRUE);
+    }
+  else
+    {
+      button = gtk_object_get_data (GTK_OBJECT (clist), "mount-button");
+      gtk_widget_set_sensitive (button, TRUE);
+
+      button = gtk_object_get_data (GTK_OBJECT (clist), "unmount-button");
+      gtk_widget_set_sensitive (button, FALSE);
+    }
+
+#ifdef DEVEL_MACHINE
+  device = "test.dump";
+#endif  
+
+  update_notebook (GTK_OBJECT (clist), device);
+}
+
+static GtkWidget *
+create_partition_list (void)
+{
+  GtkCList     *clist;
+  static gchar *titles[2] = { "Device", "Mountpoint" };
+
+  clist = ocfs_build_clist (2, titles, NULL);
+
+  gtk_clist_set_compare_func (clist, list_compare);
+
+  gtk_signal_connect (GTK_OBJECT (clist), "select_row",
+		      GTK_SIGNAL_FUNC (list_select), NULL);
+
+  return GTK_WIDGET (clist);
+}
+
+static void
+mount (GtkWidget *button,
+       GtkCList  *clist)
+{
+  GtkWindow *parent;
+  pid_t      pid;
+  gint       errfd;
+  gboolean   success, killed;
+  gchar     *device, *mountpoint = NULL;
+  gchar     *errmsg;
+  gint       row;
+  gboolean   advanced;
+
+  if (clist->selection == NULL)
+    return;
+
+  parent = ocfs_widget_get_toplevel (button);
+
+  advanced = gtk_object_get_data (GTK_OBJECT (clist), "advanced") != NULL;
+
+  row = GPOINTER_TO_INT (clist->selection->data);
+
+  gtk_clist_get_text (clist, row, 0, &device);
+
+  pid = ocfs_mount (parent, device, advanced, mountpoint, &errfd);
+
+  success = ocfs_process_reap (parent, pid, TRUE, FALSE,
+			       "Mount", "Mounting",
+			       -1, NULL, errfd, &errmsg, &killed);
+
+  if (!success)
+    {
+      if (killed)
+	ocfs_error_box (parent, NULL, "mount died unexpectedly! Your system "
+				      "is probably in an inconsistent state. "
+				      "You should reboot at the earliest "
+				      "oppurtunity");
+      else
+	ocfs_error_box (parent, errmsg, "Could not mount %s", device);
+
+      g_free (errmsg);
+    }
+
+  refresh_partition_list (clist);
+}
+
+static void
+unmount (GtkWidget *button,
+	 GtkCList  *clist)
+{
+  GtkWindow *parent;
+  pid_t      pid;
+  gint       errfd;
+  gboolean   success, killed;
+  gchar     *device, *mountpoint;
+  gchar     *errmsg;
+  gint       row;
+
+  if (clist->selection == NULL)
+    return;
+
+  parent = ocfs_widget_get_toplevel (button);
+
+  row = GPOINTER_TO_INT (clist->selection->data);
+
+  gtk_clist_get_text (clist, row, 0, &device);
+  device = g_strdup (device);
+
+  gtk_clist_get_text (clist, row, 1, &mountpoint);
+
+  pid = ocfs_unmount (mountpoint, &errfd);
+  success = ocfs_process_reap (parent, pid, TRUE, FALSE,
+			       "Unmount", "Unmounting",
+			       -1, NULL, errfd, &errmsg, &killed);
+
+  if (success)
+    {
+      refresh_partition_list (clist);
+      select_device (clist, device);
+    }
+  else
+    {
+      if (killed)
+	ocfs_error_box (parent, NULL, "umount died unexpectedly! Your system "
+				      "is probably in an inconsistent state. "
+				      "You should reboot at the earliest "
+				      "oppurtunity");
+      else
+	ocfs_error_box (parent, errmsg, "Could not unmount %s mounted on %s",
+			device, mountpoint);
+
+      g_free (errmsg);
+
+      refresh_partition_list (clist);
+    }
+
+  g_free (device);
+}
+
+static void
+disk_op (GtkCList *clist,
+         guint     action)
+{
+  GtkWindow   *parent;
+  gboolean     advanced, success;
+  gint         row;
+  gchar       *device;
+  struct stat  sbuf;
+
+  advanced = gtk_object_get_data (GTK_OBJECT (clist), "advanced") != NULL;
+
+  parent = ocfs_widget_get_toplevel (GTK_WIDGET (clist));
+
+  if (clist->selection != NULL)
+    {
+      row = GPOINTER_TO_INT (clist->selection->data);
+
+      gtk_clist_get_text (clist, row, 0, &device);
+      device = g_strdup (device);
+    }
+  else
+    device = NULL;
+
+  if (action == 0)
+    success = ocfs_format (parent, device, advanced);
+  else
+    success = ocfs_resize (parent, device, advanced);
+
+  g_free (device);
+
+  refresh_partition_list (clist);
+
+  if (success && stat (CONFFILE, &sbuf) != 0)
+    if (ocfs_query_box (parent, "Do you want to generate the config file?"))
+      genconfig (clist);
+}
+
+static void
+genconfig (GtkCList *clist)
+{
+  GtkWindow *parent;
+  gboolean   advanced;
+
+  advanced = gtk_object_get_data (GTK_OBJECT (clist), "advanced") != NULL;
+
+  parent = ocfs_widget_get_toplevel (GTK_WIDGET (clist));
+
+  ocfs_generate_config (parent, advanced);
+}
+
+static void
+refresh (GtkCList *clist)
+{
+  refresh_partition_list (clist);
+
+  if (clist->rows == 0)
+    update_notebook (GTK_OBJECT (clist), NULL);
+}
+
+static GtkWidget *
+create_action_area (GtkCList *clist)
+{
+  GtkWidget *vbbox;
+  GtkWidget *button;
+
+  vbbox = gtk_vbutton_box_new ();
+  gtk_button_box_set_layout (GTK_BUTTON_BOX (vbbox), GTK_BUTTONBOX_START);
+  gtk_box_set_spacing (GTK_BOX (vbbox), 5);
+  gtk_container_set_border_width (GTK_CONTAINER (vbbox), 5);
+
+  button = gtk_widget_new (GTK_TYPE_BUTTON,
+			   "label", "Mount",
+			   "parent", vbbox,
+			   "signal::clicked", mount, clist,
+			   NULL);
+  gtk_object_set_data (GTK_OBJECT (clist), "mount-button", button);
+
+  button = gtk_widget_new (GTK_TYPE_BUTTON,
+			   "label", "Unmount",
+			   "parent", vbbox,
+			   "signal::clicked", unmount, clist,
+			   NULL);
+  gtk_object_set_data (GTK_OBJECT (clist), "unmount-button", button);
+
+  button = gtk_widget_new (GTK_TYPE_BUTTON,
+			   "label", "Refresh",
+			   "parent", vbbox,
+			   "object_signal::clicked", refresh, clist,
+			   NULL);
+
+  return vbbox;
+}
+
+static void
+tab_frame (const gchar *tag,
+	   const gchar *desc,
+	   GtkWidget   *notebook,
+	   GtkWidget   *clist,
+	   TabFunc      func)
+{
+  gchar     *str;
+  GtkWidget *frame;
+  GtkWidget *info;
+
+  frame = gtk_widget_new (GTK_TYPE_FRAME,
+			  "shadow", GTK_SHADOW_NONE,
+			  "border_width", 0,
+			  NULL);
+
+  str = g_strconcat (tag, "-frame", NULL);
+  gtk_object_set_data (GTK_OBJECT (clist), str, frame);
+  g_free (str);
+
+  info = func (NULL, FALSE);
+  gtk_container_add (GTK_CONTAINER (frame), info);
+
+  gtk_container_add_with_args (GTK_CONTAINER (notebook), frame,
+			       "tab_label", desc,
+			       NULL);
+}
+
+static GtkItemFactoryEntry menu_items[] =
+{
+  { "/_File",                     NULL,         NULL,      0, "<Branch>" },
+  { "/File/E_xit",                "<control>Q", cleanup,   0 },
+  { "/_Tasks",                    NULL,         NULL,      0, "<Branch>" },
+  { "/Tasks/_Format...",          "<control>F", disk_op,   0 },
+  { "/Tasks/_Resize...",          "<control>R", disk_op,   1 },
+  { "/Tasks/---",                 NULL,         NULL,      0, "<Separator>" },
+  { "/Tasks/_Generate Config...", "<control>G", genconfig, 0 },
+  { "/_Preferences",              NULL,         NULL,      0, "<Branch>" },
+  { "/Preferences/_Basic",        "<control>B", level,     0, "<RadioItem>" },
+  { "/Preferences/_Advanced",     "<control>A", level,     1, "/Preferences/Basic" },
+  { "/_Help",                     NULL,         NULL,      0, "<Branch>" },
+  { "/Help/_About...",            NULL,         about,     0 },
+};
+
+static int nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
+
+
+static void
+create_window (void)
+{
+  GtkWidget      *window;
+  GtkWidget      *hbox;
+  GtkWidget      *vbox;
+  GtkWidget      *vpaned;
+  GtkWidget      *clist;
+  GtkWidget      *scrl_win;
+  GtkWidget      *frame;
+  GtkWidget      *vbbox;
+  GtkWidget      *notebook;
+  GtkWidget      *item;
+  GtkAccelGroup  *accel_group;
+  GtkItemFactory *item_factory;
+
+  window = gtk_widget_new (GTK_TYPE_WINDOW,
+			   "type", GTK_WINDOW_TOPLEVEL,
+			   "title", "OCFS Tool",
+			   "default_width", 520,
+			   "default_height", 420,
+			   "border_width", 0,
+			   "signal::delete_event", cleanup, NULL,
+			   NULL);
+
+  clist = create_partition_list ();
+
+  accel_group = gtk_accel_group_new ();
+  item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>",
+				       accel_group);
+  gtk_object_set_data_full (GTK_OBJECT (window), "<main>",
+			    item_factory, (GtkDestroyNotify) gtk_object_unref);
+  gtk_accel_group_attach (accel_group, GTK_OBJECT (window));
+
+  gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, clist);
+
+  vbox = gtk_vbox_new (FALSE, 0);
+  gtk_container_add (GTK_CONTAINER (window), vbox);
+
+  gtk_box_pack_start (GTK_BOX (vbox),
+		      gtk_item_factory_get_widget (item_factory, "<main>"),
+      		      FALSE, FALSE, 0);
+
+  vpaned = gtk_vpaned_new ();
+  gtk_container_set_border_width (GTK_CONTAINER (vpaned), 4);
+  gtk_box_pack_start (GTK_BOX (vbox), vpaned, TRUE, TRUE, 0);
+
+  hbox = gtk_hbox_new (FALSE, 0);
+  gtk_paned_pack1 (GTK_PANED (vpaned), hbox, FALSE, FALSE);
+
+  scrl_win = gtk_widget_new (GTK_TYPE_SCROLLED_WINDOW,
+			     "hscrollbar_policy", GTK_POLICY_AUTOMATIC,
+			     "vscrollbar_policy", GTK_POLICY_AUTOMATIC,
+			     "parent", hbox,
+			     NULL);
+  gtk_container_add (GTK_CONTAINER (scrl_win), clist);
+
+  frame = gtk_widget_new (GTK_TYPE_FRAME,
+      			  "shadow", GTK_SHADOW_IN,
+			  NULL);
+  gtk_box_pack_end (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
+  
+  vbbox = create_action_area (GTK_CLIST (clist));
+  gtk_container_add (GTK_CONTAINER (frame), vbbox);
+
+  notebook = gtk_widget_new (GTK_TYPE_NOTEBOOK,
+			     "tab_pos", GTK_POS_TOP,
+			     NULL);
+  gtk_paned_pack2 (GTK_PANED (vpaned), notebook, FALSE, FALSE);
+
+  tab_frame ("general",   "General",          notebook, clist, ocfs_general);
+  tab_frame ("browser",   "File Listing",     notebook, clist, ocfs_browser);
+  tab_frame ("nodemap",   "Configured Nodes", notebook, clist, ocfs_nodemap);
+  tab_frame ("bitmap",    "Bitmap View",      notebook, clist, ocfs_bitmap);
+  tab_frame ("freespace", "Free Space",       notebook, clist, ocfs_freespace);
+
+  refresh_partition_list (GTK_CLIST (clist));
+
+  gtk_widget_show_all (window);
+
+  item = gtk_item_factory_get_item (item_factory, "/Tasks/Resize...");
+  gtk_object_set_data (GTK_OBJECT (clist), "resize_item", item);
+  gtk_widget_hide (item);
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+  int i;
+
+  gtk_init (&argc, &argv);
+
+  for (i = 1; i < argc; i++)
+    {
+      if ((strcmp (argv[i], "--version") == 0) ||
+	  (strcmp (argv[i], "-V") == 0))
+	{
+	  g_print ("OCFSTool version " OCFSTOOL_VERSION "\n");
+	  exit (0);
+	}
+      else if (strcmp (argv[i], "--help") == 0)
+	{
+	  usage (argv[0]);
+	  exit (0);
+	}
+      else
+	{
+	  usage (argv[0]);
+	  exit (1);
+	}
+    }
+
+  create_window ();
+
+  gtk_main ();
+
+  return 0;
+}

Added: trunk/vendor/Makefile
===================================================================
--- trunk/vendor/Makefile	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/vendor/Makefile	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,7 @@
+TOPDIR = ..
+
+include $(TOPDIR)/Preamble.make
+
+SUBDIRS = common redhat unitedlinux
+
+include $(TOPDIR)/Postamble.make

Added: trunk/vendor/common/Makefile
===================================================================
--- trunk/vendor/common/Makefile	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/vendor/common/Makefile	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,7 @@
+TOPDIR = ../..
+
+include $(TOPDIR)/Preamble.make
+
+DIST_FILES = ocfs-tools.spec.in
+
+include $(TOPDIR)/Postamble.make

Added: trunk/vendor/common/ocfs-tools.spec.in
===================================================================
--- trunk/vendor/common/ocfs-tools.spec.in	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/vendor/common/ocfs-tools.spec.in	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,116 @@
+#
+# Spec file for ocfs-tools
+#
+
+# Macros
+# This one is hardcoded because, well, it belongs there
+%define _prefix /usr
+# Because RPM is dumb
+%define _unpackaged_files_terminate_build 0
+
+Summary: Tools for managing the Oracle Cluster Filesystem
+Name: ocfs-tools
+Version: @DIST_VERSION@
+Release: @RPM_VERSION@
+Copyright: GPL
+Group: System Environment/Kernel
+Source: ocfs-tools- at DIST_VERSION@.tar.gz
+URL: http://oss.oracle.com/projects/ocfs-tools/
+Distribution: Oracle
+Vendor: Oracle Corporation
+Packager: nobody <nobody at oracle.com>
+Exclusiveos: Linux
+Requires: ocfs-support >= @DIST_VERSION@, gtk+ >= 1.2.8
+BuildRequires: gtk+-devel >= 1.2.8
+
+BuildRoot: %{_tmppath}/ocfs-tools-%{PACKAGE_VERSION}-%{PACKAGE_RELEASE}-root
+
+%description
+Tools to manage the Oracle Cluster Filesystem
+
+
+%package -n ocfs-support
+Summary: Support programs for the Oracle Cluster Filesystem
+Group: System Environment/Kernel
+Requires: fileutils, sh-utils, net-tools, chkconfig, modutils
+AutoReqProv: No
+
+
+%description -n ocfs-support
+Support programs for using the Oracle Cluster Filesystem.
+
+
+%prep
+%setup -n ocfs-tools-%{version}
+
+
+%build
+%configure --sbindir=/sbin
+make
+
+
+%install
+
+mkdir -p $RPM_BUILD_ROOT/etc/init.d
+IVENDOR=redhat
+if [ -r /etc/UnitedLinux-release -o -r /etc/SuSE-release ]
+then
+    IVENDOR=unitedlinux
+fi
+cp -f vendor/$IVENDOR/ocfs.init $RPM_BUILD_ROOT/etc/init.d/ocfs
+ln -s ocfs $RPM_BUILD_ROOT/etc/init.d/ocfs2
+
+make DESTDIR="$RPM_BUILD_ROOT" install
+
+
+%clean
+rm -rf "$RPM_BUILD_ROOT"
+
+
+%pre -n ocfs-support
+# Cleanup for bad RPMs
+if [ -e /usr/sbin/load_ocfs ] ; then
+	rm -f /usr/sbin/load_ocfs
+fi
+
+if [ -e /usr/sbin/ocfs_uid_gen ] ; then
+	rm -f /usr/sbin/ocfs_uid_gen
+fi
+
+%post -n ocfs-support
+chkconfig ocfs on
+chkconfig ocfs2 on
+/etc/init.d/ocfs link
+/etc/init.d/ocfs2 link
+
+
+%files
+%defattr(-,root,root)
+/usr/bin
+/usr/share
+
+
+%files -n ocfs-support
+%defattr(-,root,root)
+/sbin/load_ocfs
+/sbin/load_ocfs2
+/sbin/mkfs.ocfs
+/sbin/resizeocfs
+/sbin/mounted.ocfs
+/sbin/fsck.ocfs
+/sbin/ocfs_uid_gen
+/etc/init.d/ocfs
+/etc/init.d/ocfs2
+/sbin/bug3016598
+/sbin/bug3123542
+
+
+%changelog
+* Wed Jan 28 2004 Manish Singh <manish.singh at oracle.com>
+- Split out tools
+
+* Thu Mar 27 2003 Joel Becker <joel.becker at oracle.com>
+- Added %if %{up} and ocfs-support Requires
+
+* Thu Mar 27 2003 Bryce	<philip.copeland at oracle.com>
+- Initial swipe at rpm spec file cleanup

Added: trunk/vendor/redhat/Makefile
===================================================================
--- trunk/vendor/redhat/Makefile	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/vendor/redhat/Makefile	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,7 @@
+TOPDIR = ../..
+
+include $(TOPDIR)/Preamble.make
+
+DIST_FILES = ocfs.init
+
+include $(TOPDIR)/Postamble.make

Added: trunk/vendor/redhat/ocfs.init
===================================================================
--- trunk/vendor/redhat/ocfs.init	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/vendor/redhat/ocfs.init	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,364 @@
+#! /bin/sh
+# init fragment for ocfs
+#
+# chkconfig: 2345 24 20
+# description: Setup OCFS environment
+
+#
+# Note that the start priority is 24.  This is precisely one less than
+# the start priority for netfs (25).  This is because we expect OCFS
+# volumes to be mounted in the netfs start.
+#
+# All OCFS volumes that are to be mounted at boot need to have the
+# '_netdev' option added to their fstab entry.  This prevents them
+# from trying to mount before this script has run.
+#
+
+
+# Force LC_ALL=C for proper ifconfig(8) parsing
+export LC_ALL=C
+
+
+# Source init.d functions
+. /etc/init.d/functions
+
+# Source networking configuration
+. /etc/sysconfig/network
+
+case "`basename $0`" in
+*ocfs)
+    MODNAME=ocfs
+    FSNAME=OCFS
+    LOAD_OCFS=/sbin/load_ocfs
+    ;;
+*ocfs2)
+    MODNAME=ocfs2
+    FSNAME=OCFS2
+    LOAD_OCFS=/sbin/load_ocfs2
+    ;;
+*)
+    echo -n "Checking for OCFS version: "
+    failure $"OCFS version is bad;"
+    echo
+    exit 1
+esac
+
+if ! test -x "$LOAD_OCFS"; then
+    echo -n "Checking for $LOAD_OCFS: "
+    failure $"$LOAD_OCFS does not exist;"
+    echo
+    exit 1
+fi
+
+KVER="`uname -r`"
+case "$KVER" in
+2.4.9-e.*)
+    BASE_VER=2.4.9-e
+    BASE_STR=2.4.9-e
+    ;;
+2.4.18-e.*)
+    BASE_VER=2.4.18-e
+    BASE_STR=2.4.18-e
+    ;;
+2.4.21-*.EL*)
+    BASE_VER=2.4.21-
+    BASE_STR=2.4.21-EL
+    ;;
+2.4.20-18.10.*)
+    # Oracle's shared-ieee1394 demo kernels
+    BASE_VER=2.4.20-18.10
+    BASE_STR=2.4.20-18.10
+    ;;
+*)
+    echo -n "Checking for Red Hat enterprise kernel: "
+    failure $"Kernel ${KVER} is not a Red Hat enterprise release;"
+    echo
+    exit 1
+    ;;
+esac
+
+EVER="${KVER#${BASE_VER}}"
+ETYPE=""
+case "$EVER" in
+*hugemem)
+    ETYPE=hugemem
+    ;;
+*smp)
+    ETYPE=smp
+    ;;
+*enterprise)
+    if test "$BASE_VER" = "2.4.9-e"
+    then
+        ETYPE=enterprise
+    fi
+    ;;
+*summit)
+    if test "$BASE_VER" = "2.4.9-e"
+    then
+        ETYPE=summit
+    fi
+    ;;
+*[0-9])
+    ETYPE=up
+    ;;
+*[0-9].EL)
+    # UP on RHEL 3
+    ETYPE=up
+    ;;
+esac
+
+if test -z "$ETYPE"
+then
+    echo -n "Checking for Red Hat enterprise kernel: "
+    failure $"Kernel ${KVER} is not a Red Hat enterprise release;"
+    echo 
+    exit 1
+fi
+
+case "$EVER" in
+*.EL)
+    EVER="${EVER%.EL}"
+    ;;
+*)
+    ;;
+esac
+
+if test "$ETYPE" = "up"
+then
+    ETYPE=""
+fi
+case "$BASE_STR" in
+2.4.21-EL)
+    EVER="${EVER%.EL${ETYPE}}"
+    ;;
+*)
+    EVER="${EVER%${ETYPE}}"
+    ;;
+esac
+
+check_ver()
+{
+    VERNUM="$1"
+    case "$VERNUM" in
+    [0-9])
+        ;;
+    [1-9][0-9])
+        ;;
+    [1-9][0-9][0-9])
+        ;;
+    *)
+        echo -n "Checking for Red Hat enterprise kernel: "
+        failure $"Kernel ${KVER} is not a Red Hat enterprise release;"
+        echo
+        exit 1
+        ;;
+    esac
+}
+
+EMAJOR=0
+EMINOR=0
+EMICRO=0
+EVER="${EVER#.}"
+EMAJOR="${EVER%%.*}"
+check_ver $EMAJOR
+ETMP="${EVER#${EMAJOR}}"
+ETMP="${ETMP#.}"
+if test -n "$ETMP"
+then
+    EMINOR="${ETMP%%.*}"
+    check_ver $EMINOR
+    ETMP="${ETMP#${EMINOR}}"
+    ETMP="${ETMP#.}"
+fi
+if test -n "$ETMP"
+then
+    EMICRO="${ETMP%%.*}"
+    check_ver $EMICRO
+    ETMP="${ETMP#${EMICRO}}"
+    ETMP="${ETMP#.}"
+fi
+if test -n "$ETMP"
+then
+    echo -n "Checking for Red Hat enterprise kernel: "
+    failure $"Kernel ${KVER} is not a Red Hat enterprise release;"
+    echo
+    exit 1
+fi
+
+# This is for path happiness...
+if test "$ETYPE" != ""
+then
+    ETYPE="${ETYPE}-"
+fi
+MODPATH="/lib/modules/${KVER}/kernel/drivers/addon/${MODNAME}"
+case "$BASE_STR" in
+2.4.9-e)
+    if test "${EMAJOR}" -gt 23
+    then
+        OBJPATH="/lib/modules/${BASE_STR}-${ETYPE}ABI/${MODNAME}"
+    else
+        OBJPATH="/lib/modules/${BASE_STR}-${ETYPE}ABI/${MODNAME}-noaio"
+    fi
+    ;;
+2.4.18-e)
+    OBJPATH="/lib/modules/${BASE_STR}-${ETYPE}ABI/${MODNAME}"
+    ;;
+2.4.21-EL)
+    OBJPATH="/lib/modules/${BASE_STR}-${ETYPE}ABI/${MODNAME}"
+    ;;
+2.4.20-18.10)
+    OBJPATH="/lib/modules/${BASE_STR}-${ETYPE}ABI/${MODNAME}"
+    ;;
+*)
+    echo -n "Checking for Red Hat enterprise kernel: "
+    failure $"Can't get here! (Kernel ${KVER});"
+    echo
+    exit 1
+esac
+
+test -r "${OBJPATH}/${MODNAME}.o" || exit 0
+
+
+fstab_check()
+{
+    # Are there any volumes to mount?
+    ANY="`awk '/^[  ]*#/{next}$4 ~ /^noauto$|^noauto,|,noauto$/{next}$3 == "ocfs"{print $2}' /etc/fstab 2>/dev/null`"
+    test -z "$ANY" && return
+      
+    # Check if anything is missing netdev
+    ANY="`awk '/^[  ]*#/{next}$4 ~ /^noauto$|^noauto,|,noauto$/{next}$4 ~ /^_netdev$|^_netdev,|,_netdev$/{next}$3 == "ocfs"{print $2}' /etc/fstab 2>/dev/null`"
+    test -n "$ANY" && echo "Warning: ${FSNAME} filesystems missing \"_netdev\" option: $ANY"
+}
+
+module_link()
+{
+    if test -L "${MODPATH}/${MODNAME}.o"
+    then
+        LINKTARGET="`ls -l "${MODPATH}/${MODNAME}.o" 2>/dev/null | sed -e 's/^.* -> //'`"
+        case "${LINKTARGET}" in
+        ${OBJPATH}/${MODNAME}.o)
+            return
+            ;;
+        ${OBJPATH%-noaio}/${MODNAME}.o)
+            ;;
+        ${OBJPATH}-noaio/${MODNAME}.o)
+            ;;
+        *)
+            return
+            ;;
+        esac
+        rm -f "${MODPATH}/${MODNAME}.o"
+    fi
+
+    echo -n "Linking ${FSNAME} module into the module path "
+
+    # Same deal for modules that are physically there
+    if test -f "${MODPATH}/${MODNAME}.o" ; then
+        EXISTVER="`modinfo "${MODPATH}/${MODNAME}.o" | awk '/description.*version/{sub(/^.*\(version /, ""); sub(/\)"$/, ""); print;}'`"
+        if test -n "${EXISTVER}" ; then
+            ABIVER="`modinfo "${OBJPATH}/${MODNAME}.o" | awk '/description.*version/{sub(/^.*\(version /, ""); sub(/\)"$/, ""); print;}'`"
+
+            echo
+            echo "Leaving existing ${MODNAME} module in place (ABI module version $ABIVER, existing module version $EXISTVER)"
+            success
+            echo
+            return
+        else
+            # The existing module is too old - pre-ABI packaging
+            echo
+            echo "Warning: Moving ancient ${MODNAME}.o out of the way"
+            mv -f "${MODPATH}/${MODNAME}.o" "${MODPATH}/${MODNAME}.o.preABI" >/dev/null 2>&1
+            if test "$?" != 0 ; then
+                failure $"Unable to move ancient ${MODNAME} module out of the way;"
+                echo
+                exit 1
+            fi
+        fi
+    fi
+
+    if test ! -d "$MODPATH" ; then
+        if test -e "${MODPATH}"; then
+            failure $"Path \"${MODPATH}\" already exists, but is not a directory;"
+            echo
+            exit 1
+        else
+            mkdir -p "$MODPATH" >/dev/null 2>&1
+            if test $? != 0; then
+                failure $"Unable to create directory \"${MODPATH}\";"
+                echo
+                exit 1
+            fi
+        fi
+    fi
+
+    ln -s "${OBJPATH}/${MODNAME}.o" "${MODPATH}/${MODNAME}.o" >/dev/null 2>&1
+    if test $? != 0; then
+        failure $"Unable to create symbolic link \"${MODPATH}/${MODNAME}.o\";"
+        echo
+        exit 1
+    fi
+
+    success
+    echo
+}
+
+case "$1" in
+    start)
+        module_link
+
+        fstab_check
+
+        echo -n $"Loading ${FSNAME}: "
+
+        if ! test -r /etc/ocfs.conf; then
+            failure $"No configuration file /etc/ocfs.conf; loading ${FSNAME};"
+            echo
+            exit 1
+        fi
+
+        if test "$NETWORKING" = "no"; then
+            failure $"Network is unavailable; loading ${FSNAME};"
+            echo
+            exit 1
+        fi
+
+        if grep "^${MODNAME} " /proc/modules >/dev/null 2>&1; then
+            success $"${FSNAME} is already loaded;"
+            echo
+            exit 0
+        fi
+
+        # action - DO NOT REMOVE, this is to trick RH /etc/rc
+        initlog -q -c "$LOAD_OCFS" && success || failure
+        RETVAL=$?
+        echo
+        
+	;;
+	
+    link)
+	module_link
+        ;;
+
+    status)
+        echo -n $"Checking if ${FSNAME} is loaded: "
+        if grep "^${MODNAME} " /proc/modules >/dev/null 2>&1; then
+            success $"${FSNAME} is already loaded; status"
+            echo
+            exit 0
+        else
+            failure $"${FSNAME} is not loaded; status"
+            echo
+            exit 1
+        fi
+        ;;
+
+    stop|force-reload|restart)
+        RETVAL=0
+	;;
+
+    *)
+	echo "Usage: $0 {start|stop|restart|force-reload}"
+        RETVAL=1
+esac
+
+exit $RETVAL


Property changes on: trunk/vendor/redhat/ocfs.init
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/vendor/unitedlinux/Makefile
===================================================================
--- trunk/vendor/unitedlinux/Makefile	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/vendor/unitedlinux/Makefile	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,7 @@
+TOPDIR = ../..
+
+include $(TOPDIR)/Preamble.make
+
+DIST_FILES = ocfs.init
+
+include $(TOPDIR)/Postamble.make

Added: trunk/vendor/unitedlinux/ocfs.init
===================================================================
--- trunk/vendor/unitedlinux/ocfs.init	2004-01-29 07:42:46 UTC (rev 1)
+++ trunk/vendor/unitedlinux/ocfs.init	2004-01-29 08:00:03 UTC (rev 2)
@@ -0,0 +1,106 @@
+#! /bin/sh
+# init fragment for ocfs
+#
+### BEGIN INIT INFO
+# Provides: ocfs
+# Required-Start: $network
+# Required-Stop:
+# Default-Start: 2 3 5
+# Default-Stop:
+# Description: Load OCFS driver at system boot
+### END INIT INFO
+
+#
+# Note that the start priority is after the network comes up.
+# There is no real automatic mounting yet.
+#
+# All OCFS volumes that are to be mounted at boot need to have the
+# '_netdev' option added to their fstab entry.  This prevents them
+# from trying to mount before this script has run.
+#
+
+case "`basename $0`" in
+*ocfs)
+    MODNAME=ocfs
+    FSNAME=OCFS
+    LOAD_OCFS=/sbin/load_ocfs
+    ;;
+*ocfs2)
+    MODNAME=ocfs2
+    FSNAME=OCFS2
+    LOAD_OCFS=/sbin/load_ocfs2
+    ;;
+*)
+    exit 1
+esac
+
+test -x "$LOAD_OCFS" || exit 5
+
+test -r /etc/ocfs.conf || exit 6
+
+KVER="`uname -r`"
+case "$KVER" in
+2.4.19-64GB-SMP|2.4.19-4GB-SMP|2.4.19-4GB)
+    MODPATH="/lib/modules/${KVER}/kernel/drivers/addon/${MODNAME}"
+    ;;
+*)
+    # Not a supported kernel
+    exit 0
+    ;;
+esac
+
+test -r "${MODPATH}/${MODNAME}.o" || exit 5
+
+# Source init.d functions
+. /etc/rc.status
+
+# Source networking configuration
+#. /etc/sysconfig/network
+
+
+fstab_check()
+{
+    # Are there any volumes to mount?
+    ANY="`awk '/^[  ]*#/{next}$4 ~ /^noauto$|^noauto,|,noauto$/{next}$3 == "ocfs"{print $2}' /etc/fstab 2>/dev/null`"
+    test -z "$ANY" && return
+      
+    # Check if anything is missing netdev
+    ANY="`awk '/^[  ]*#/{next}$4 ~ /^noauto$|^noauto,|,noauto$/{next}$4 ~ /^_netdev$|^_netdev,|,_netdev$/{next}$3 == "ocfs"{print $2}' /etc/fstab 2>/dev/null`"
+    test -n "$ANY" && echo "Warning: ${FSNAME} filesystems missing \"_netdev\" option: $ANY"
+}
+
+
+rc_reset
+
+case "$1" in
+    start)
+        fstab_check
+
+        echo -n $"Loading ${FSNAME}:"
+
+        # Note that UnitedLinux doesn't have NETWORKING=no
+
+        if grep '^${MODNAME} ' /proc/modules >/dev/null 2>&1; then
+            rc_status -v
+            rc_exit
+        fi
+
+        "$LOAD_OCFS"
+        rc_status -v
+        ;;
+        
+    status)
+        echo -n $"Checking if ${FSNAME} is loaded: "
+        grep '^${MODNAME} ' /proc/modules >/dev/null 2>&1
+        rc_status -v
+        ;;
+
+    stop|force-reload|restart)
+	;;
+
+    *)
+	echo "Usage: $0 {start|stop|status|restart|force-reload}"
+        exit 1
+esac
+
+rc_exit


Property changes on: trunk/vendor/unitedlinux/ocfs.init
___________________________________________________________________
Name: svn:executable
   + *



More information about the Ocfs-tools-commits mailing list